每日背诵,
- 中序遍历非递归
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> sta;
vector<int> res;
if(root) sta.push(root);
while(!sta.empty()) {
TreeNode* node = sta.top();
if(node == NULL) {
sta.pop();//吐出标志位
node = sta.top();
sta.pop();
res.emplace_back(node->val);//吐出标志位后的node
}
else {
sta.pop();//先吐出,稍后再放入
if(node->right) sta.push(node->right);//右孩子先入栈
sta.push(node);//前序遍历移动这个的位置
sta.push(NULL);
if(node->left) sta.push(node->left);
}
}
return res;
}
};
- 快排
class Solution {
public:
vector<int> sortArray(vector<int>& nums) {
srand(time(0));
quickSort(nums, 0, nums.size()-1);
return nums;
}
void quickSort(vector<int>& nums, int left, int right) {
if(left >= right) return;//***
int mid = partition(nums, left, right);
quickSort(nums, left, mid-1);
quickSort(nums, mid+1, right);
}
int partition(vector<int>& nums, int left, int right) {
int point = rand()%(right-left+1) +left;
swap(nums[left],nums[point]);
int local = left;
while(left < right) {
while(left < right && nums[right] >= nums[local]) right--; //向左移动到第一个比基准值小的点
while(left < right && nums[left] <= nums[local]) left++;
if(left < right) swap(nums[left],nums[right]);
}
swap(nums[local],nums[left]);//将基准值放到中间
return left;
}
};
- KMP
class Solution {
public:
int strStr(string haystack, string needle) {
int m = haystack.size();
int n = needle.size();
if(n == 0) return 0;
if(m == 0) return -1;
vector<int> next(n,0);
getNext(next,needle);
for(int i = 0,j = 0;i < m;i++) {
while(j > 0 && needle[j] != haystack[i]) {
j = next[j-1];
}
if(needle[j] == haystack[i]) j++;
if(j == n) return i-n+1;
}
return -1;
}
void getNext(vector<int>& next,string s) {
for(int i = 1,j = 0;i<s.size();i++) {
while(j > 0 && s[j] != s[i]) {
j = next[j-1];//因为当next[j] != 0时,当前j前面几个字符和前缀字符相同,可以直接从前缀的下一位比较
//直到j = 0或者s[j] == s[i]
}
if(s[j] == s[i]) j++;
next[i] = j;
}
}
};
- 背包问题
01背包:416. 分割等和子集 474. 一和零 494. 目标和 879. 盈利计划 1049. 最后一块石头的重量 II 1230. 抛掷硬币
先遍历物品,再遍历背包,二维数组
//求最大能装多少价值
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
//求有多少种组合/排列
dp[i][j] = dp[i-1][j];//首先等于前i-1种物品能凑成j的方式
if(j >= nums[i-1]) //一维数组的话,直接从weight开始
dp[i][j] += dp[i-1][j-nums[i-1]];//再加上前i-1种物品能凑出j-nums[i]的方式
完全背包:1449. 数位成本和为目标值的最大数字 322. 零钱兑换 518. 零钱兑换 II 279. 完全平方数
377. 组合总和 Ⅳ
一维数组,从前到后遍历
若先遍历物品,虽然每个物品有无限个,但是物品之间有先后顺序,是计算组合
若先遍历背包容量,物品之间无序(在下一次大循环中前面的物品重新放入),是计算排列
两种背包code的区别:
0-1背包:二维数组,第一行和第一列都需要初始化,需要nums+1行和bagSize+1列
若使用一维数组,后遍历的需要从后向前
遍历中需要判断当前的bagSize是否比当前物品的weight重
完全背包:使用一维数组,第一个元素初始化,需要bagSize+1列 ,从前往后。
- 前缀和
常见于求连续子数组,后边的前缀和减前边的前缀和就是中间数组的和,若求长度,需要用map存前面的下标
例:二维子矩阵的和,0 和 1 个数相同的子数组,和为 k 的子数组