2023秋招leetcode笔记

目录

topcode顺序刷题

215. 数组中的第K个最大元素

25. K 个一组翻转链表

15. 三数之和

53. 最大子数组和

1. 两数之和

回溯算法专题:

​​​​​​​77. 组合

40. 组合总和 II

216. 组合总和 III

17. 电话号码的字母组合

贪心算法:

455. 分发饼干

376. 摆动序列

53. 最大子数组和

122. 买卖股票的最佳时机 II

动态规划专题:

53. 最大子数组和


topcode顺序刷题

215. 数组中的第K个最大元素
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int> pg;
        for(int i = 0; i < nums.size(); i++)
        {
            pg.push(-nums[i]);
            if(pg.size() > k)
            {
                pg.pop();
            }
        }
        int result = -pg.top();
        return result;
    }
};

笔记:

优先队列默认是一个最大堆,每次输出的堆顶元素是此时堆中的最大元素

详解:c++优先队列(priority_queue)用法详解_c++优先级队列_吕白_的博客-CSDN博客

25. K 个一组翻转链表
class Solution {
public:
    void reverse(ListNode* head, ListNode* last) {
        ListNode* cur = head;
        ListNode* pre = nullptr;
        ListNode* tmp;
        while(pre != last)
        {
            tmp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = tmp;
        }
    }

    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode* result = new ListNode(0);
        ListNode* pre = result;
        ListNode* tail = head;
        while(head)
        {
            tail = head;
            for(int i = 1; i < k; i++)
            {
                tail = tail->next;
                if(tail == nullptr)
                {
                    pre->next = head;
                    return result->next;
                }
            }
            ListNode* curtail = tail->next;
            reverse(head,tail);
            pre->next = tail;
            pre = head;
            head = curtail;
        }
        return result->next;
    }
};

就是分步,每k个进行一个旋转,主要问题是在旋转的时候设置变量的时候要注意,指针别指错了。

15. 三数之和
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        vector<vector<int>> result;
        vector<int> cur;
        for(int i = 0; i < nums.size(); i++)
        {
            if(nums[i] > 0)
                break;
            if(i > 0 && nums[i] == nums[i-1])
                continue;
            int j = i+1;
            int k = nums.size()-1;
            while(j < k)
            {
                if(nums[i] + nums[j] + nums[k] == 0)
                {
                    cur.clear();
                    cur.push_back(nums[i]);
                    cur.push_back(nums[j]);
                    cur.push_back(nums[k]);
                    result.push_back(cur);
                    while(j < k && nums[j+1] == nums[j])
                    {
                        j++;
                    }
                    while(j < k && nums[k-1] == nums[k])
                    {
                        k--;
                    }
                    j++;
                    k--;
                }else if(nums[i] + nums[j] + nums[k] > 0)
                {
                    k--;
                }else if(nums[i] + nums[j] +nums[k] < 0)
                {
                    j++;
                }
            }
        }
        return result;
    }
};

搞一个滑动窗口就行

53. 最大子数组和
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        vector<int> dp(nums.size(),0);
        dp[0] = nums[0];
        int result = nums[0];
        if(nums.size() == 1)
            return nums[0];
        for(int i = 1; i < nums.size(); i++)
        {
            dp[i] = max(dp[i-1]+nums[i],nums[i]);
            if(dp[i] > result)
                result = dp[i];
        }
        return result;
    }
};

21. 合并两个有序链表

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        ListNode* head = new ListNode(0);
        head->next = nullptr;
        ListNode* result = head;
        while(list1&&list2)
        {
            if(list1->val > list2->val)
            {
                head->next = list2;
                list2 = list2->next;
                head = head->next;
            }else if(list1 ->val <= list2->val)
            {
                head->next = list1;
                list1 = list1->next;
                head = head->next;
            }
        }
        if(list1)
            head->next = list1;
        if(list2)
            head->next = list2;
        return result->next;
    }
};

1. 两数之和
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> result;
        for(int i = 0 ; i < nums.size(); i ++)
        {
            int curr = target - nums[i];
            for(int j = i+1; j < nums.size(); j++)
            {
                if(nums[j] == curr)
                {
                    result.push_back(i);
                    result.push_back(j);
                }
            }
        }
        return result;
    }
};

简单粗暴

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> result;
        unordered_map<int,int> unmap;
        for(int i = 0 ; i < nums.size(); i++)
        {
            unmap.insert(pair<int,int>(nums[i],i));
        }
        for(int i = 0; i < nums.size(); i++)
        {
            int cur = target - nums[i];
            if(unmap.find(cur) != unmap.end())
            {
                auto index = unmap.find(cur);
                if(index->second == i)
                    continue;
                else
                {
                    result.push_back(i);
                    result.push_back(index->second);
                    break;
                }
            }
        }
        return result;
    }
};

这种方法更简单!运用unordered_map的性质,用时更短

5. 最长回文子串

class Solution {
public:
    string longestPalindrome(string s) {
        vector<vector<bool>> dp(s.size(),vector<bool>(s.size(),false));
        int length = 0;
        int maxlenth = 0;
        int left = 0;
        int right = 0;
        for(int i = s.size()-1; i >= 0; i-- )
        {
            for(int j = i; j < s.size(); j++)
            {
                if(s[i] == s[j])
                {
                    if(j - i <= 1)
                        dp[i][j] = true;
                    else if(dp[i+1][j-1])
                        dp[i][j] = true;
                }
                if(dp[i][j] && j-i+1 > maxlenth)
                {
                    maxlenth = j - i + 1;
                    left = i;
                    right = j;   
                }
            }
        }
        return s.substr(left,maxlenth);
    }
};

回溯算法专题:

​​​​​​​77. 组合
class Solution {
public:
    vector<vector<int>> result;
    void combineselect(vector<int>path , int n , int k, int index)
    {
        if(path.size() == k)
        {
            result.push_back(path);
            return;
        }
        for(int i = index+1; i <= n; i++)
        {
            path.push_back(i);
            combineselect(path, n, k, i);
            path.pop_back();
        }
    }
    vector<vector<int>> combine(int n, int k) {
        vector<int> path;
        result.clear();
        path.clear();
        combineselect(path,n,k,0);
        return result;
    }
};

 ​​​​​​​39. 组合总和

class Solution {
public:
    vector<vector<int>> result;
    void backtrack(vector<int> path, vector<int>&candidates, int sum ,int target,int index)
    {
        if(sum == target)
        {
            result.push_back(path);
            return;
        }
        if(sum > target)
            return;
        for(int i = index; i < candidates.size(); i++)
        {
            path.push_back(candidates[i]);
            sum += candidates[i];
            backtrack(path,candidates,sum,target,i);
            sum -= candidates[i];
            path.pop_back();
        }
    }

    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<int> path;
        sort(candidates.begin(),candidates.end());
        backtrack(path,candidates,0,target,0);
        return result;
    }
};
40. 组合总和 II
class Solution {
public:
    vector<vector<int>> result;
    void trackback(vector<int> path, vector<int>& candidates, int target, int sum , int index)
    {
        if(sum == target)
        {
            result.push_back(path);
            return;
        }
        if(sum > target)
            return;
        for(int i = index; i < candidates.size(); i++)
        {
            if(i > index && candidates[i] == candidates[i-1])
                continue;
            sum += candidates[i];
            path.push_back(candidates[i]);
            trackback(path,candidates,target,sum,i+1);
            path.pop_back();
            sum -= candidates[i];
        }
    }
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<int> path;
        sort(candidates.begin(),candidates.end());
        trackback(path,candidates,target,0,0);
        return result;
    }
};

代码:if(i > index && candidates[i] == candidates[i-1])
                continue;

每一层的时候,都不要拿和前面一样的

216. 组合总和 III
class Solution {
public:
    vector<vector<int>> result;
    void backtrack(vector<int> path,int k, int n,int index,int sum)
    {
        if(sum == n && path.size() == k)
        {
            result.push_back(path);
            return;
        }
        if(sum > n)
            return;
        for(int i = index ; i < 10; i++)
        {
            sum += i;
            path.push_back(i);
            backtrack(path,k,n,i+1,sum);
            sum -= i;
            path.pop_back();
        }
    }
    vector<vector<int>> combinationSum3(int k, int n) {
        vector<int> path;
        backtrack(path,k,n,1,0);
        return result;
    }
};
17. 电话号码的字母组合
class Solution {
public:
    vector<string> result;
    string letter(int cur)
    {
        if(cur == 2)
            return "abc";
        if(cur == 3)
            return "def";
        if(cur == 4)
            return "ghi";
        if(cur == 5)
            return "jkl";
        if(cur == 6)
            return "mno";
        if(cur == 7)
            return "pqrs";
        if(cur == 8)
            return "tuv";
        if(cur == 9)
            return "wxyz";
        return "";
    }
    void backtrack(string digits,string path,int index)
    {
        if(path.size() == digits.size())
        {
            result.push_back(path);
            return;
        }
        int cur = digits[index] - '0';
        string letter1 = letter(cur);
        for(int i = 0 ; i < letter1.size(); i++)
        {
            path.push_back(letter1[i]);
            backtrack(digits,path,index+1);
            path.pop_back();
        }
    }

    vector<string> letterCombinations(string digits) {
        if(digits.size() == 0)
            return result;
        string path = "";
        backtrack(digits,path,0);
        return result;
    }
};

贪心算法:

455. 分发饼干
class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        int result = 0;
        int i = 0;
        int j = 0;
        sort(g.begin(),g.end());
        sort(s.begin(),s.end());
        while(i < g.size() && j < s.size())
        {
            if(g[i] > s[j])
            {
                j++;
            }else
            {
                result++;
                i++;
                j++;
            }
        }
        return result;
    }
};

376. 摆动序列
class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        bool pre_smaller = false;
        bool pre_bigger = false;
        int result = nums.size();
        for(int i = 1; i < nums.size(); i++)
        {
            if(nums[i] > nums[i-1])
            {
                if(pre_bigger)
                {
                    result--;
                }else
                {
                    pre_bigger = true;
                    pre_smaller = false;
                }
            }else if(nums[i] < nums[i-1])
            {
                if(pre_smaller)
                {
                    result--;
                }else{
                    pre_smaller = true;
                    pre_bigger = false;
                }
            }else{
                result--;
            }
        }
        return result;
    }
};

这道题其实要透过现象看本质,就是找峰值啊!遇到这种题不要慌,慢慢分析

解析:​​​​​​​代码随想录

53. 最大子数组和

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int sum = 0;
        sum = nums[0];
        int result = sum;
        for(int i = 1; i < nums.size(); i++)
        {
            if(sum < 0)
                sum = nums[i];
            else
                sum += nums[i];
            if(result < sum)
                result = sum;
        }
        return result;
    }
};

只要sum<0,就不加了,停止,从后面开始

局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。

122. 买卖股票的最佳时机 II
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int sum = 0;
        for(int i = 1 ; i < prices.size(); i++)
        {
            if(prices[i] - prices[i-1] > 0)
            {
                sum += prices[i] - prices[i-1];
            }
        }
        return sum;
    }
};

如果想到其实最终利润是可以分解的,那么本题就很容易了!

局部最优:收集每天的正利润,全局最优:求得最大利润



55. 跳跃游戏
class Solution {
public:
    bool canJump(vector<int>& nums) {
        int cur_range = 0;
        if(nums.size()== 1)
            return true;
        int cover =0;
        for(int i =0 ; i <= cover ; i++)
        {
            cover = max(nums[i] + i,cover);
            if(cover >= nums.size()-1)
            {
                return true;
            }
        }
        return false;
    }
};

局部最优解:每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后得到整体最大覆盖范围,看是否能到终点

45. 跳跃游戏 II
class Solution {
public:
    int jump(vector<int>& nums) {
        if(nums.size() == 1)
        {
            return 0;
        }
        int curDistance = 0;
        int nextDistance = 0;
        int time = 0;
        for(int i = 0; i <= curDistance; i++)
        {
            nextDistance = max(nextDistance,i+nums[i]);
            if(i == curDistance)
            {
                time++;
                curDistance = nextDistance;
                if(nextDistance>= nums.size()-1)
                {
                    break;
                }
            }
        }
        return time;
    }
};

以最小的步数增加最大的覆盖范围,直到覆盖范围覆盖了终点

1005. K 次取反后最大化的数组和

class Solution {
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        sort(nums.begin(),nums.end());
        int sum = 0;
        for(int i = 0; i < nums.size(); i++)
        {
            if(nums[i] < 0 && k > 0)
            {
                nums[i] = -nums[i];
                k--;
            }
            sum += nums[i];
        }
        if(k > 0)
        {
            sort(nums.begin(),nums.end());
            sum -= nums[0];
            sum += nums[0] * pow(-1,k);
        }
        return sum;
    }
};

局部最优:让绝对值大的负数变为正数,当前数值达到最大,整体最优:整个数组和达到最大。

动态规划专题:

动规五部曲如下:

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组​​​​​​​

​​​​​​​

53. 最大子数组和
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        vector<int> dp(nums.size(),0);
        dp[0] = nums[0];
        int result = nums[0];
        for(int i = 1; i < nums.size(); i++)
        {
            dp[i] = max(dp[i-1]+nums[i],nums[i]);
            if(dp[i] > result)
                result = dp[i];
        }
        return result;
    }
};

dp[i]:包括下标i(以nums[i]为结尾)的最大连续子序列和为dp[i]

dp[i]只有两个方向可以推出来:

  • dp[i - 1] + nums[i],即:nums[i]加入当前连续子序列和
  • nums[i],即:从头开始计算当前连续子序列和

详细思路:代码随想录 

509. 斐波那契数

class Solution {
public:
    int fib(int n) {
        if(n == 0)
            return 0;
        if(n == 1)
            return 1;
        return fib(n-1)+fib(n-2);
    }
};

70. 爬楼梯

class Solution {
public:
    int climbStairs(int n) {
        if(n == 1)
            return 1;
        vector<int> dp(n+1,0);
        dp[1] = 1;
        dp[2] = 2;
        for(int i = 3; i <= n ; i++)
        {
            dp[i] = dp[i-2] + dp[i-1];
        }
        return dp[n];
    }
};



746. 使用最小花费爬楼梯

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        vector<int> dp(cost.size()+1, 0);
        if(cost.size() == 1)
            return cost[0];
        dp[0] = 0;
        dp[1] = 0;
        int n = cost.size();
        for(int i = 2; i <= n ; i++)
        {
            dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
        }
        return dp[n];
    }
};

62. 不同路径

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m+1,vector<int>(n+1,0));
        dp[0][0] = 1;
        for(int i = 1; i < m; i++)
        {
            dp[i][0] = 1;
        }
        for(int j = 1; j < n; j++)
        {
            dp[0][j] = 1;
        }
        for(int i = 1; i <m; i++)
        {
            for(int j = 1; j < n; j++)
            {
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
        int result = dp[m-1][n-1];
        return result;
    }
};

63. 不同路径 II

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        vector<vector<int>> dp(m,vector<int>(n,0));
        for(int i = 0; i < m; i++)
        {
            if(obstacleGrid[i][0] == 0)
            {
                dp[i][0] = 1;
            }else
            {
                break;
            }   
        }
        for(int j = 0; j < n; j++)
        {
            if(obstacleGrid[0][j] == 0)
            {
                dp[0][j] = 1;
            }else
            {
                break;
            }
        }
        for(int i = 1; i <m; i++)
        {
            for(int j = 1; j < n; j++)
            {
                if(obstacleGrid[i][j] == 0)
                {
                    dp[i][j] = dp[i-1][j] + dp[i][j-1];
                }else
                {
                    dp[i][j] = 0;
                }
            }
        }
        return dp[m-1][n-1];

    }
};

单调栈

739. 每日温度

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        stack<int> st;
        vector<int> result(temperatures.size(),0);
        st.push(0);
        for(int i = 1; i < temperatures.size(); i++)
        {
            while(!st.empty() && temperatures[i] > temperatures[st.top()])
            {
                result[st.top()] = i - st.top();
                st.pop();
            }
            st.push(i);
        }
        return result;
    }
};

42. 接雨水

class Solution {
public:
    int trap(vector<int>& height) {
        stack<int> st;
        int result = 0;
        st.push(0);
        for(int i = 1; i < height.size() ; i++)
        {
            if(height[i] < height[st.top()])
            {
                st.push(i);
            }else if(height[i] == height[st.top()])
            {
                st.pop();
                st.push(i);
            }else
            {
                while(!st.empty() && height[i] > height[st.top()])
                {
                    int mid = st.top();
                    st.pop();
                    if(!st.empty())
                    {
                        int h = min(height[i],height[st.top()]) - height[mid];
                        int w = i - st.top()-1;
                        result += h*w;
                    }
                }
                st.push(i);
            }
        }
        return result;
    }
};

讲解:代码随想录

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值