WEEK1 ?follow /

128 阅读3分钟

# 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

截屏2022-03-14 下午3.20.33.png 返回left或者right+1,因为最终right会在左边 left会在右边

#76 最小覆盖子串

  • 好家伙 还没写过

#26 删除有序数组中的重复项

双指针,一个指着需要的位置,一个用来遍历

image.png

#80 删除有序数组中的重复项 II

数组本身有序 只要 和前面的前面的保持不一致就能满足题意。初始位置一样也可以,一前一后也可以,知道最后返回啥就行。

image.png

image.png

day5

#153 寻找旋转排序数组中的最小值

条件为 l < r, 返回nums[l] nums[r]都行最后指着一个位置;如果条件是 l <= r,那就返回nums[r] image.png

#154 寻找旋转排序数组中的最小值 II

在上题基础上考虑一个相等的情况

image.png

#33 搜索旋转排序数组

image.png

#80 搜索旋转排序数组 II

这题于33相当于154之于153,考虑一个相等的情况,有相等的就可以忽略当前左右边界了,属于是工具人只需要一个(

image.png