leetcode解题思路分析(九)57-63题

末蓝、 2023-07-02 03:24 109阅读 0赞
  1. 插入区间
    给出一个无重叠的 ,按照区间起始端点排序的区间列表。
    在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。

本质上和上一题是一个东西,但是因为给出的已经是无重叠并且排好序的,所以最简单的是一次遍历然后按情况插入新区间

  1. class Solution {
  2. public:
  3. vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
  4. intervals.push_back(newInterval);
  5. sort(intervals.begin(), intervals.end());
  6. vector<vector<int>> ans{ intervals[0]};
  7. int n = intervals.size();
  8. for(int i = 0; i < n; i ++){
  9. if(ans.back()[1] >= intervals[i][0]){
  10. ans.back()[1] = max(intervals[i][1], ans.back()[1]);
  11. continue;
  12. }
  13. else{
  14. ans.push_back(intervals[i]);
  15. continue;
  16. }
  17. }
  18. return ans;
  19. }
  20. };
  1. 最后一个单次长度
    给定一个仅包含大小写字母和空格 ’ ’ 的字符串 s,返回其最后一个单词的长度。
    如果字符串从左向右滚动显示,那么最后一个单词就是最后出现的单词。
    如果不存在最后一个单词,请返回 0 。

本题思路很简单,从后往前遍历寻找第一个词即可。注意可能一开始就是空格,所以需要判断

  1. class Solution {
  2. public:
  3. int lengthOfLastWord(string s) {
  4. int i = s.size();
  5. int cnt = 0;
  6. bool lastWord = false;
  7. if (i == 0)
  8. return 0;
  9. i--;
  10. while (i >= 0)
  11. {
  12. if (s[i] == ' ')
  13. {
  14. if (lastWord)
  15. break;
  16. else
  17. i--;
  18. }
  19. else
  20. {
  21. lastWord = true;
  22. cnt++;
  23. i--;
  24. }
  25. }
  26. return cnt;
  27. }
  28. };
  1. 螺旋矩阵2
    给定一个正整数 n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。

本题比之前54题螺旋矩阵要相对简单,可以参考54题得解

  1. class Solution {
  2. public:
  3. vector<vector<int>> generateMatrix(int n) {
  4. vector<vector<int>> res(n, vector<int>(n));
  5. for(int s = 0, e = n - 1, m = 1; s<=e ; s++,e--){
  6. if(s==e) res[s][e] = m++;
  7. for (int j = s; j <= e-1; j++) res[s][j] = m++;
  8. for (int i = s; i <= e-1; i++) res[i][e] = m++;
  9. for (int j = e; j >= s+1; j--) res[e][j] = m++;
  10. for (int i = e; i >= s+1; i--) res[i][s] = m++;
  11. }
  12. return res;
  13. }
  14. };
  1. 第K个排列
    给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。给定 n 和 k,返回第 k 个排列。

本题和前面的全排列其实是一个东西,所以可以用回溯剪枝的方式做,返回第k个。但是这样很浪费,因为没必要实现全排列。还有一种做法是根据n!个特点针对性求第k个。简单的说,对于特定的n位,只有(n - 1)!种解。这对每一位均适用。由此我们可以推出第k个排列每一位是多少

  1. class Solution {
  2. public:
  3. string getPermutation(int n, int k) {
  4. if (n==1) return "1";
  5. int m = 1;
  6. vector<char> num;
  7. for (int i = 1; i < n; i++) {
  8. m *= i;
  9. num.push_back('0' + i);
  10. }
  11. num.push_back('0' + n);
  12. string s = "";
  13. while (true) {
  14. if (k%m==0){
  15. s += num[k/m-1];
  16. num.erase(num.begin() + k / m - 1);
  17. reverse(num.begin(), num.end());
  18. s.insert(s.end(), num.begin(), num.end());
  19. return s;
  20. }
  21. else{
  22. s += num[k/m];
  23. num.erase(num.begin() + k / m);
  24. if (n==2) {
  25. s += num.back();
  26. return s;
  27. }
  28. k %= m;
  29. n--;
  30. m /= n;
  31. }
  32. }
  33. return s;
  34. }
  35. };
  1. 旋转链表
    给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。

本题的做法是首先迭代找到尾部,然后首尾相连成环,之后K–找到新的尾部断开即可

  1. /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */
  2. class Solution {
  3. public:
  4. ListNode* rotateRight(ListNode* head, int k) {
  5. if(!head||k==0)return head;
  6. ListNode *tail=head;
  7. int size=1;
  8. while(tail->next){
  9. size++;
  10. tail=tail->next;
  11. }
  12. if(k%size==0)return head;
  13. //首尾相连,形成环形链表
  14. tail->next=head;
  15. int m=size-k%size;
  16. //tail移动m步,到达新头节点的前驱节点
  17. while(m--)tail=tail->next;
  18. //tail的next节点为新的头节点,顺便断开环形链表
  19. ListNode *res=tail->next;
  20. tail->next=nullptr;
  21. return res;
  22. }
  23. };
  1. 不同路径
    一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
    机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
    问总共有多少条不同的路径?

看到求所有解,无非是回溯剪枝或者动态规划求解

  1. class Solution {
  2. public:
  3. int uniquePaths(int m, int n) {
  4. int x, y;
  5. int dp[m][n] = { 0};
  6. for (x = m - 1; x >= 0; x--)
  7. {
  8. for (y = n - 1; y >= 0; y--)
  9. {
  10. if ((x == m - 1 && n - y == 2) || (y == n - 1 && m - x == 2))
  11. dp[x][y] = 1;
  12. else if (x == m - 1 && n - y > 2)
  13. dp[x][y] = dp[x][y + 1];
  14. else if (y == n - 1 && m - x > 2)
  15. dp[x][y] = dp[x + 1][y];
  16. else if (n - y >= 2 && m - x >= 2)
  17. dp[x][y] = dp[x + 1][y] + dp[x][y + 1];
  18. else dp[x][y] = 1;
  19. }
  20. }
  21. return dp[0][0];
  22. }
  23. };
  1. 不同路径 II
    一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
    机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
    现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

此题和上题并无太大区别,只需要在判断中加一个障碍物判断即可

  1. class Solution {
  2. public:
  3. int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
  4. int x, y;
  5. int m = obstacleGrid.size();
  6. int n = obstacleGrid[0].size();
  7. if (m == 1 && n == 1)
  8. {
  9. if (obstacleGrid[0][0])
  10. return 0;
  11. else return 1;
  12. }
  13. long dp[100][100] = { 0};
  14. for (x = m - 1; x >= 0; x--)
  15. {
  16. for (y = n - 1; y >= 0; y--)
  17. {
  18. if (obstacleGrid[x][y] == 1)
  19. dp[x][y] = 0;
  20. else if ((x == m - 1 && n - y == 2) || (y == n - 1 && m - x == 2))
  21. dp[x][y] = dp[m - 1][n - 1];
  22. else if (x == m - 1 && n - y > 2)
  23. dp[x][y] = dp[x][y + 1];
  24. else if (y == n - 1 && m - x > 2)
  25. dp[x][y] = dp[x + 1][y];
  26. else if (n - y >= 2 && m - x >= 2)
  27. dp[x][y] = dp[x + 1][y] + dp[x][y + 1];
  28. else dp[x][y] = 1;
  29. }
  30. }
  31. return dp[0][0];
  32. }
  33. };

发表评论

表情:
评论列表 (有 0 条评论,109人围观)

还没有评论,来说两句吧...

相关阅读