常用算法及题解
背包问题
https://zhuanlan.zhihu.com/p/93857890?utm_source=wechat_session
数字找规律——分治
https://blog.nowcoder.net/n/f5703527172e480fa830275e521e356f
排序算法动图
http://tools.jb51.net/aideddesign/paixu_ys
快速排序
可以用递归实现。
在上图的一次递归中,取右侧第一个数字a为标准,从左到右遍历,设当前被遍历数为x。
- 若x大于a,则从右侧端点开始寻找第一个小于a的数字b,将其于x进行位置交换。
- 若x小于a,则位置不变。
- 重复以上操作,直到左右两个遍历指针相交。
- 此时再分别将已经分好的两块数据进行递归操作即可。
堆排序
这是一个二叉树,存储在一个一维数组上。
二叉树的根为该数组中最大的值,root->left、root->right都比root小。
直接上代码吧,下面的代码实现了一个最大堆,和最大堆排序:
#include <vector> #include <iostream> #include <string> #include <algorithm> using namespace std; template<typename _T> class BigHeapTree : public vector<_T> { public: class TreeNode { public: TreeNode(BigHeapTree& tree, int idx):tree(tree), idx(idx) {} TreeNode parent() { return TreeNode(tree, (idx-1)/2); } TreeNode sibling() { return TreeNode(tree, idx % 2 ? idx+1 : idx-1); } TreeNode child_left(){ return TreeNode(tree, idx*2+1); } TreeNode child_right(){ return TreeNode(tree, idx*2+2); } inline void swap(TreeNode& node) { _T tmp = node.value(); node.value() = this->value(); this->value() = tmp; } inline bool is_root()const { return !idx; } inline bool is_right()const { return !is_left(); } inline bool is_left()const { return idx % 2; } inline bool has_sibling()const { return tree.size()-1 != idx; } inline bool is_valid()const { return idx < tree.size(); } inline const _T& value()const { return tree[idx]; } inline _T& value() { return tree[idx]; } inline bool operator<(const TreeNode& node)const { return value() < node.value(); } BigHeapTree& tree; int idx; }; BigHeapTree(const vector<_T>& vec) { this->reserve(vec.size()); for(auto& val : vec) this->insert(val); } inline void insert(const _T& val) { this->push_back(val); this->come_up(this->last()); } inline void insert(_T&& val) { this->push_back(val); this->come_up(this->last()); } inline TreeNode root(){ return TreeNode(*this, 0); } inline TreeNode last(){ return TreeNode(*this, this->size()-1); } static void sort(vector<_T>& vec) { BigHeapTree tree(vec); for(auto& val : vec) { TreeNode root = tree.root(), last = tree.last(); val = root.value(); root.swap(last); tree.resize(tree.size()-1); tree.come_down(root); } } protected: void come_up(TreeNode node) { // 将元素进行上浮操作 auto parent = node.parent(); if(parent < node) { parent.swap(node); return come_up(parent); } } void come_down(TreeNode node) { // 将node进行下沉操作 TreeNode big = node.child_left(); if(big.is_valid()) { // 找到俩子元素中最大的big TreeNode right = node.child_right(); if(right.is_valid() && big < right) big.swap(right); // 将big与当前node比较,并排序 if(node < big) { node.swap(big); this->come_down(big); } } } }; int main() { vector<int> vec = {435,436,5545,4785,576,54,67,8987565,46,7897654,467,876,54,67898,57654,86,67687977,654354,4458}; cout << "unsort array:\t"; for(auto val : vec) cout << val << " "; cout << endl; BigHeapTree<int>::sort(vec); cout << "sorted array:\t"; for(auto val : vec) cout << val << " "; cout << endl; }
上面我继承了vector类,但该算法依然有可以优化的地方:
- 在构造函数中可以用从下而上的迭代方法inplace构造一个最大堆
- 在排序函数中可以通过将“删除”的元素放到末尾,来inpalce排序数组
- 结合以上两种方式,可以构造出一个inpalce排序,且复杂度仅为N*log(N)的排序算法
春招时间不够,以上代码将不再优化,直接开搞下一个!
归并排序
常用数据结构分析
二叉树
- 图左为完全二叉树,其节点顺序排列;图右为满二叉树,其深为k,有
个节点
动态规划
求最长升序序列
#include <vector> #include <iostream> #include <string> #include <algorithm> using namespace std; class LevelArray : public vector<int> { public: void append(int val) { this->push_back(val); this->max_val = max(val, this->max_val); } int max_val = INT32_MIN; }; int main() { vector<int> nums = {1,3,6,7,9,4,10,5,6}; vector<int> dp(nums.size()); vector<LevelArray> ar; // LevelArray tmp; tmp.append(nums[nums.size()-1]); ar.push_back(tmp); for(int i=nums.size()-2; i>=0; --i) { int cur_val = nums[i]; for(int j=0; j < ar.size(); ++j) { if(cur_val >= ar[j].max_val) { // 当>=时结果不含鞍点,否则含鞍点 ar[j].append(cur_val); break; }else if(j+1==ar.size()) { LevelArray x; x.append(cur_val); ar.push_back(x); break; } } } for(auto& a : ar){ for(auto& val : a) cout << val << " "; cout << endl; } }