算法学习笔记
线性枚举
一种暴力算法,对元素进行依次处理
求最大值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int findMax (vector<int > v) { int max = v[0 ]; for (int i = 1 ; i < v.size (); i++) { if (v[i] > max) { max = v[i]; } } return max; } int main () {vector<int > v = {23 ,12 ,55 ,34 ,87 ,13 ,76 }; cout <<"Max:" << findMax (v) << endl; return 0 ; }
真题
1 2 3 4 5 6 7 8 9 10 11 class Solution {public : bool threeConsecutiveOdds (vector<int >& arr) { for (int i=1 ;i<arr.size ()-1 ;i++){ if (arr[i-1 ]%2 ==1 &&arr[i]%2 ==1 &&arr[i+1 ]%2 ==1 ) return true ; } return false ; } };
1 2 3 4 5 6 7 8 9 10 11 12 class Solution {public : int findMaxConsecutiveOnes (vector<int >& nums) { int sum=0 ,max=-100 ; for (int i=0 ;i<nums.size ();){ while (i<nums.size ()&&nums[i++]==1 ) sum++; if (max<sum) max=sum; sum=0 ; } return max; } };
1 2 3 4 5 6 7 8 9 10 11 12 class Solution {public : int singleNonDuplicate (vector<int >& nums) { int i=0 ; for (i=0 ;i<nums.size ()-1 ;i+=2 ){ if (nums[i]!=nums[i+1 ]){ return nums[i]; } } return nums[i--]; } };
模拟
没有特定的算法,按照题目要求一步一步做 废话-_-(
真题
1 2 3 4 5 6 7 8 9 class Solution {public : vector<int > swapNumbers (vector<int >& numbers) { numbers[0 ] = numbers[0 ] ^ numbers[1 ]; numbers[1 ] = numbers[0 ] ^ numbers[1 ]; numbers[0 ] = numbers[0 ] ^ numbers[1 ]; return numbers; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution { public: int hammingWeight(uint32_t n) { int count = 0; while (n > 0) { if (n & 1) { count++; } n >>= 1; } return count; } };
递推
递推是一个循环或者迭代的过程
斐波那契数列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void fbV () { vector<int > v ({0 ,1 }) ; for (int i=1 ;i<=30 ;i++) { v.push_back (v[i]+v[i-1 ]); } for (int i=0 ;i<v.size ();i++) { cout<<v[i]<<" " ; } } int main () {fbV (); return 0 ; }
1 2 输出: 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269
真题
1 2 3 4 5 6 7 8 9 10 class Solution {public : int climbStairs (int n) { vector<int > v ({1 ,1 }) ; for (int i = 1 ;i < n;i++){ v.push_back (v[i-1 ]+v[i]); } return v[n]; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution {public : vector<int > getRow (int rowIndex) { int v[35 ][35 ]; for (int i = 0 ;i<=rowIndex;i++){ for (int j = 0 ;j <= i;j++){ if (j == 0 || j == i) v[i][j] = 1 ; else { v[i][j] = v[i-1 ][j] + v[i-1 ][j-1 ]; } } } vector<int > n; for (int i = 0 ;i <= rowIndex;i++){ n.push_back (v[rowIndex][i]); } return n; } };
排序
选择排序
最暴力的一集,时间复杂度o(n^2)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <iostream> using namespace std;void select_sort (int * a,int n) { for (int i = 0 ; i < n; i++) { int index = i; for (int j = i + 1 ; j < n; j++) { if (a[index] > a[j])index = j; } swap (a[i], a[index]); } } void main () { int a[10 ]{ 5 ,7 ,9 ,6 ,3 ,1 ,4 ,8 }; select_sort (a, 8 ); for (int i = 0 ; i < 8 ; i++) { cout << a[i]<<" " ; } }
冒泡排序
最暴力的二集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 void MP (vector<int >& v) { for (int i = 0 ; i < v.size ()-1 ; i++) { for (int j = 0 ; j < v.size ()-i-1 ; j++) { if (v[j] > v[j+1 ]) { swap (v[j], v[j+1 ]); } } } } void print_vector (vector<int >& v) { for (int i = 0 ; i < v.size (); i++) { cout << v[i] << " " ; } cout << endl; } int main () { vector<int > v ({93 ,21 ,43 ,6 ,1 ,3 ,5 ,3 ,23 ,32 }) ; MP (v); print_vector (v); return 0 ; }
插入排序
最暴力的三集
1 2 3 4 5 6 7 8 9 10 11 12 13 void InsertSort (vector<int >& v) { for (int i = 1 ; i < v.size (); i++) { int temp = v[i]; int j = i - 1 ; while (j >= 0 && v[j] > temp) { v[j + 1 ] = v[j]; j--; } v[j + 1 ] = temp; } }
计数排序
用好了效率爆炸,用不好程序爆炸,最局限的一集
1 2 3 4 5 6 7 8 9 10 11 12 13 void countingSort (vector<int >& v) { vector<int > temp (10000 ) ; for (int i = 0 ; i < v.size (); i++) { temp[v[i]] += 1 ; } v.clear (); for (int i = 0 ; i < temp.size (); i++) { while (temp[i] > 0 ) { v.push_back (i); temp[i] -= 1 ; } } }
归并排序
回归到了人类可以使用的排序,归并思想拆开来说就是递归和合并,先通过递归逻辑拆到最简处理,然后再合并
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 vector <int > tem; void merge_sort (vector<int >& v, int l, int r) { if (l >= r) return ; int mid = (l+r)/ 2 ; merge_sort (v, l, mid); merge_sort (v, mid + 1 , r); int i = l ,j = mid + 1 ; while (i <= mid && j <= r) { if (v[i] <= v[j]) { tem.push_back (v[i++]); } else { tem.push_back (v[j++]); } } while (i <= mid) tem.push_back (v[i++]); while (j <= r) tem.push_back (v[j++]); for (int k = l,p = 0 ; k <= r; k++,p++) v[k] = tem[p]; tem.clear (); }
快速排序
桶排序
基数排序
堆排序
哈希
贪心
前缀和
双指针
滑动窗口
二分查找
最短路Dijkstra
最小生成树Prim
深度&&广度优先搜索
深度优先搜索
广度优先搜索
数据结构
树
二叉树
二叉搜索树
图
邻接矩阵
邻接表
哈希表
数论
质数
约数
费马定理
欧拉函数
快速幂
扩展欧几里得算法
中国剩余定理
高斯消元
组合计数
容斥原理
简单博弈论
最短路
最短路Bellman-Ford
最短路Floyd
最短路Dijkstra+Heap
最短路SPFA
DP
线性DP
拓扑排序
记忆化搜索
0/1背包
0/1背包空间优化
完全背包
完全背包时间优化
区间DP
计数类DP
数位统计DP
状态压缩DP
树形DP