LeetCode 热题 HOT 100 打卡计划 | 第九天 | 每日进步一点点

201 阅读2分钟

图片.png

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情

55. 跳跃游戏

思路

(贪心) O(n)

从前往后遍历nums数组,记录我们能跳到的最远位置j,如果存在我们不能跳到的下标i,返回false即可,否则返回true

具体过程如下:

  • 1、定义一个j变量用来记录我们可以跳到的最远位置,初始化j = 0

  • 2、遍历整个nums[]数组,i表示当前需要跳到的下标位置。

    • j < i,说明下标i不可达,则返回false
    • 否则,说明i可达,则我们以i为起点更新可以跳到的最远位置j,即j = max(j, i + nums[i])
  • 3、如果可以遍历完整个数组,说明可以到达最后一个下标i,我们返回true

时间复杂度分析: 只遍历一次数组,因此时间复杂度为O(n)。

c++代码

 class Solution {
 public:
     bool canJump(vector<int>& nums) {
         for(int i = 0, j = 0; i < nums.size(); i++){
             if(j < i) return false;
             j = max(j, i + nums[i]);
         }
         return true;
     }
 };

56. 合并区间

思路

(数组,排序) O(nlogn)

1、将所有的区间按照左端点从小到大排序

图片.png 2、定义区间左端点l = a[0][0],右端点r = a[0][1](等价于两个左右指针),我们从前往后遍历每个区间:

  • 如果当前区间和上一个区间没有交集,也就是说当前区间的左端点>上一个区间的右端点,即a[i][0] > r,说明上一个区间独立,我们将上一个区间的左右端点[l,r]加入答案数组中,并更新左端点l,右端点r为当前区间的左右端点,即l = a[i][0], r = a[i][1]

    始终维持lr为最新独立区间的左右端点。

图片.png

  • 如果当前区间和上一个区间有交集,即当前区间的左端点<=上一个区间的右端点,我们让左端点l保持不变,右端点r更新为max(r,a[i][1]) ,进行区间的合并 。

3、最后再将最后一个合并或者未合并的独立区间[l,r]加入答案数组中。

时间复杂度分析: 遍历区间数组的时间为O(n),对区间数组进行排序的时间复杂度为O(nlogn) ,因此总的时间复杂度为O(nlogn)

c++代码

 class Solution {
 public:
     vector<vector<int>> merge(vector<vector<int>>& a) {
         vector<vector<int>> res;
         sort(a.begin(), a.end());  //按照左端点排序
         int l = a[0][0], r = a[0][1];
         for(int i = 1; i < a.size(); i++){
             if(a[i][0] > r){
                 res.push_back({l, r});
                 l = a[i][0], r = a[i][1];
             }else{
                 r = max(r, a[i][1]);
             }
         }    
         res.push_back({l, r});
         return res;
     }
 };

62. 不同路径

思路

(动态规划) O(m*n)

状态表示: f[i,j]表示从(0,0)走到(i,j)的所有不同路径的方案数。那么,f[m-1][n-1]就表示从网格左上角到网格右下角的所有不同路径的方案数,即为答案。

状态转移:

图片.png

由于限制了只能向下走或者向右走,因此到达(i,j)有两条路径

  • 从上方转移过来,f[i][j] = f[i-1][j]
  • 从左方转移过来,f[i][j] = f[i][j-1] ;

因此,状态计算方程为: f[i][j] = f[i-1][j] + f[i][j-1] , 将向右和向下两条路径的方案数相加起来。

初始化条件: f[0][0] = 1,从(0,0)到达(0,0)只有一条路径。

分析图示:

图片.png

时间复杂度分析: O(m*n),其中 m和 n分别是网格的行数和列数 。

c++代码

 class Solution {
 public:
     int uniquePaths(int m, int n) {
         if(!n || !m) return 0;
         vector<vector<int>>f(m + 1, vector<int>(n + 1));
         f[0][0] = 1;
         for(int i = 0; i < m; i++)
             for(int j = 0; j < n; j++){
                 if(!i && !j) continue;
                 if(i) f[i][j] += f[i - 1][j];
                 if(j) f[i][j] += f[i][j - 1];
             }
         return f[m - 1][n - 1];    
     }
 };