# week1
day1
#1 两数之和
method1——暴力,两个for循环走天下( method2——hash表:unordered_map。first是key,second是value,这里用nums的值做key来查找,下标存起来。
unordered_map<int, int> seen ;
for(int i=0; i<nums.size(); i++) {
auto it = seen.find(target - nums[i]) ;
if(it != seen.end()) {
return {i, it->second} ;
}
seen[nums[i]] = i ;
}
return {} ;
#53 最大子数组合
经典dp,思想就是看之前的状态,对自己状态是【加成】就一起走,否则就干脆只要自己。这题的分治法也可以了解一下,涉及到线段树。
maxSum[i] = max(maxSum[i-1] + nums[i], nums[i]) ;
#121 买卖股票的最佳时机
内心os:要是我的基金也这么懂事就好了……( 思想就是在每一天,我都幻想自己是在最低点买进的,那么就可以得到在当天卖出一个理想的最大收益。
int profit = 0, minPrice = 10e6 ;
for(int i = 0; i<prices.size(); i++) {
minPrice = min(minPrice, prices[i]) ;
profit = max(prices[i] - minPrice, profit) ;
}
return profit ;
day2
#21 合并两个有序链表
不用多说,递归or迭代,设置一个哑节点会比较方便想清楚,要注意判空。经常就是new一个老大指针用作返回最后答案,再new一个指针用来移动模拟过程。递归感觉就是单纯在赋值。
#141 环形链表
找有没有环,快慢指针来咯!看看会不会相遇(同时出发或者一前一后出发都行,进循环条件不一样罢了)不过为啥一定会相遇呢?可以理解成在环里面每次快指针都更【近】慢指针【一】小步?如果步数变了真的可能永远遇不上?。或者hash表也很简单粗暴,第二次访问到这个节点就表明有环(.count(), .find())
#160 相交链表
走完我的走你的,如果相交就遇在交叉点 a+c+b = b+c+a 如果c=0不相交那就一起走到nullptr。或者hash表先记录list1所有节点,再访问list2,有过记录就是有交集。
#206 反转链表
梦开始的地方(不是
迭代:先让当前指针的next指向前一个节点,然后当前节点也变成了pre,需要原先节点的next所以要记录一下。最后pre就变成了【新的头节点】,它在的位置是原先的尾巴。
递归:
head->next->next = head ;
head->next = nullptr ;
day3
#103 二叉树的锯齿形层序遍历
层序遍历变种,晓得了deque,双端队列针对这题的操作就比较方便
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>> ans ;
if(!root) return ans ;
queue<TreeNode*> treeQueue ;
treeQueue.push(root) ;
bool isLeft = true ;
while(!treeQueue.empty()) {
int size = treeQueue.size() ;
deque<int> levelList ;
for(int i=0; i<size; i++) {
auto node = treeQueue.front() ;
treeQueue.pop() ;
if(isLeft) {
levelList.push_back(node->val) ;
} else {
levelList.push_front(node->val) ;
}
if(node->left) treeQueue.push(node->left) ;
if(node->right) treeQueue.push(node->right) ;
}
ans.emplace_back(levelList.begin(), levelList.end()) ;
isLeft = !isLeft ;
}
return ans ;
}
#199 二叉树的右视图
这题没怎么看题解,觉得不就是上一题一样层序变种,取每一层最后一个元素不就好了。当时图方便还是用的dequeue,push_front,取levelList[0]
ans.emplace_back(levelList[0]) ;
#104 二叉树的最大深度
method1——DFS
if(!root) return 0 ;
return max(maxDepth(root->left), maxDepth(root->right)) + 1 ;
method2——BFS 为什么直接写 i < treeQueue.size() 会解答不通过???非得先int size = treeQueue.size() ? why 好像知道了,每经过一次for循环 队列大小都在变…………得先取到这一层的长度
int maxDepth(TreeNode* root) {
if(!root) return 0 ;
queue<TreeNode*> treeQueue ;
treeQueue.push(root) ;
int depth = 0 ;
while(!treeQueue.empty()) {
int size = treeQueue.size() ;
for(int i=0; i<size; i++) {
auto node = treeQueue.front() ;
treeQueue.pop() ;
if(node->left) treeQueue.push(node->left) ;
if(node->right) treeQueue.push(node->right) ;
}
depth += 1 ;
}
return depth ;
}
#110 平衡二叉树
method1——自顶向下(会重复调用节点
bool isBalanced(TreeNode* root) {
if(!root) return true ;
int left = maxDepth(root->left) ;
int right = maxDepth(root->right) ;
return (abs(right - left) <= 1 && isBalanced(root->left) && isBalanced(root->right));
}
int maxDepth(TreeNode* root) {
if(!root) return 0 ;
return max(maxDepth(root->left), maxDepth(root->right)) + 1 ;
}
method2——自底向上,叶子状态传递给根,每个节点只调用一次
bool isBalanced(TreeNode* root) {
if(!root) return true ;
return maxDepth(root) > 0 ;
}
int maxDepth(TreeNode* root) {
if(!root) return 0 ;
int left = maxDepth(root->left) ;
int right = maxDepth(root->right) ;
if(abs(right-left) > 1 || left == -1 || right == -1) return -1 ;
return max(maxDepth(root->left), maxDepth(root->right)) + 1 ;
}
#543 二叉树的直径
对于当前节点,经过它的最长路径不就是max左深+max右深
int ans = 0 ;
int depth(TreeNode* root) {
if(!root) return 0 ;
int left = depth(root->left) ;
int right = depth(root->right) ;
ans = max(ans, left+right) ;
return max(left, right) + 1 ;
}
int diameterOfBinaryTree(TreeNode* root) {
depth(root) ;
return ans ;
}
day4
#704 二分查找
easy
int search(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1 ;
while(l<=r) {
int mid = (l + r) >> 1 ;
if(nums[mid] == target) return mid ;
else if(nums[mid] < target) l = mid + 1 ;
else r = mid - 1 ;
}
return -1 ;
}
#34 在排序数组中查找元素的第一个和最后一个位置
找 第一个大于等于的 和 第一个大于的下标 - 1
返回left或者right+1,因为最终right会在左边 left会在右边
#76 最小覆盖子串
- 好家伙 还没写过
#26 删除有序数组中的重复项
双指针,一个指着需要的位置,一个用来遍历
#80 删除有序数组中的重复项 II
数组本身有序 只要 和前面的前面的保持不一致就能满足题意。初始位置一样也可以,一前一后也可以,知道最后返回啥就行。
day5
#153 寻找旋转排序数组中的最小值
条件为 l < r, 返回nums[l] nums[r]都行最后指着一个位置;如果条件是 l <= r,那就返回nums[r]
#154 寻找旋转排序数组中的最小值 II
在上题基础上考虑一个相等的情况
#33 搜索旋转排序数组
#80 搜索旋转排序数组 II
这题于33相当于154之于153,考虑一个相等的情况,有相等的就可以忽略当前左右边界了,属于是工具人只需要一个(