zoukankan      html  css  js  c++  java
  • 【LeetCode】Array

    [11] Container With Most Water [Medium]

    O(n^2)的暴力解法直接TLE。

    正确的解法是Two Pointers。 O(n)的复杂度。保持两个指针i,j;分别指向长度数组的首尾。如果ai 小于aj,则移动i向后(i++)。反之,移动j向前(j--)。如果当前的area大于了所记录的area,替换之。这个想法的基础是,如果i的长度小于j,无论如何移动j,短板在i,不可能找到比当前记录的area更大的值了,只能通过移动i来找到新的可能的更大面积。

     1 class Solution {
     2 public:
     3     int maxArea(vector<int>& height) {
     4         int i = 0;
     5         int j = height.size() - 1;
     6         int ans = 0;
     7         while(i < j) {
     8             int area = (j - i) * min(height[i], height[j]);
     9             ans = max(ans, area);
    10             if (height[i] <= height[j]) {
    11                 ++i;
    12             }
    13             else {
    14                 --j;
    15             }
    16         }
    17         return ans;
    18     }
    19 };
    View Code

    [15] 3Sum [Medium]

    它要求返回结果不重复,所以去重。不能用unique,会TLE,直接在循环里面跳过。

    先排序,两根指针,夹逼定理

     1 class Solution {
     2 public:
     3     vector<vector<int>> threeSum(vector<int>& nums) {
     4         vector<vector<int>> result;
     5         if (nums.size() < 3) {
     6             return result;
     7         }
     8         sort(nums.begin(), nums.end());
     9         for (int i = 0; i < nums.size(); ) {
    10             int j = i + 1;
    11             int k = nums.size() - 1;
    12             while (j < k) {
    13                 if (nums[i] + nums[j] + nums[k] == 0) {
    14                     result.push_back(vector<int>{nums[i], nums[j], nums[k]});
    15                     ++j, --k;
    16                     while (j < k && nums[j-1] == nums[j]) { ++j; }
    17                     while (j < k && nums[k+1] == nums[k]) { --k; }
    18                 }
    19                 else if (nums[i] + nums[j] + nums[k] < 0) {
    20                     ++j;
    21                     while (j < k && nums[j-1] == nums[j]) { ++j; }
    22                 }
    23                 else {
    24                     --k;
    25                     while (j < k && nums[k+1] == nums[k]) { --k; }
    26                 }
    27             }
    28             ++i;
    29             while (nums[i-1] == nums[i]) { ++i; }
    30         }
    31         return result;
    32     }
    33 };
    View Code

    [16] 3Sum Closest [Medium]

    三个数求和,返回离target最近的和。

    Two Pointers, 跟15题一样, 先排序,两根指针左右夹逼。

     1 class Solution {
     2 public:
     3     int threeSumClosest(vector<int>& nums, int target) {
     4         int result = 0;
     5         int min_gap = INT_MAX;
     6         sort(nums.begin(), nums.end());
     7         for (int i = 0; i < nums.size() - 2; ++i) {
     8             int start = i + 1, end = nums.size() - 1;
     9             while (start < end) {
    10                 int temp = nums[i] + nums[start] + nums[end];
    11                 int gap = abs(temp - target);
    12                 if (gap < min_gap) {
    13                     min_gap = gap;
    14                     result = temp;
    15                 }
    16                 if (temp == target) break;
    17                 if (temp > target) {
    18                     --end;
    19                 }
    20                 else if (temp < target) {
    21                     ++start;
    22                 }
    23             }
    24         }
    25         return result;
    26     }
    27 };
    View Code

    [17] 4Sum [Medium]

    四个数求和,求出和target相等的元组, 思路和3sum一个样,包括和去重的方式都一样。

    还是先排序,然后两根指针。

     1 class Solution {
     2 public:
     3     vector<vector<int>> fourSum(vector<int>& nums, int target) {
     4         vector<vector<int>> result;
     5         if (nums.size() < 4) {
     6             return result;
     7         }
     8         sort(nums.begin(), nums.end());
     9         for (int i = 0; i < nums.size()-3; ) {
    10             for(int j = i+1; j < nums.size()-2; ) {
    11                 int start = j + 1, end = nums.size() - 1;
    12                 while (start < end) {
    13                     int sum = nums[i] + nums[j] + nums[start] + nums[end];
    14                     if (sum == target) {
    15                         result.push_back(vector<int>{nums[i], nums[j], nums[start], nums[end]});
    16                         ++start, --end;
    17                         while (start < end && nums[start-1] == nums[start]) {
    18                             ++start;
    19                         }
    20                         while (start < end && nums[end+1] == nums[end]) {
    21                             --end;
    22                         }
    23                     }
    24                     else if (sum < target) {
    25                         ++start;
    26                         while (start < end && nums[start-1] == nums[start]) {
    27                             ++start;
    28                         }
    29                     }
    30                     else {
    31                         --end;
    32                         while (start < end && nums[end+1] == nums[end]) {
    33                             --end;
    34                         }
    35                     }
    36                 }
    37                 ++j;
    38                 while (nums[j-1] == nums[j]) { ++j; }
    39             }
    40             ++i;
    41             while(nums[i-1] == nums[i]) { ++i; }
    42         }
    43         return result;
    44     }
    45 };
    View Code

    [45] Jump Game II [Hard]

    这个题需要记忆。再考肯定不会。。。要记忆。。。

    给你一个数组,数组元素的值是从当前index最多能往前面移动的步数,求到数组末尾最少移动的步数。

    我是参考了这个:https://www.tianmaying.com/tutorial/LC45

     1 /*
     2 将每个位置都看作一个点,并从第i个点向它之后的nums[i]个点都连一条长度为1的有向边,而现在的问题就是从0号点到达size-1号点需要的最短距离,这就是一个很简单的最短路问题,实际上由于边的长度均为1,而且不存在环,我们可以用宽度优先搜索(时间复杂度为O(n^2),即边数)来进行相关的计算。
     3 
     4 不难发现,这道题目转换出的最短路问题存在三个条件:
     5 
     6 边的长度均为1
     7 不存在环
     8 连出的边是连续的
     9 我们是不是可以用这三个“很强”的条件来做一些优化呢,答案自然是肯定的!
    10 
    11 ——如果令f[i]表示从0号点到达i号点的最短路径,那么对于任意i<j,有f[i]<=f[j],即f是非递减的,这个结论的证明是显然的,在此不作过多赘述。
    12 
    13 在有了这样的结论之后,我们就会发现,其实对于f数组来说,它会是一段段的存在,先是一个0,然后是一段1,然后是一段2,依此类推,那么现在问题来了,每一段的长度是多少呢?
    14 
    15 这个问题很好回答,如果我们令l[k]表示f数组中值为k的一段的左边界,r[k]表示f数组中值为k的一段的有边界,那么有
    16 
    17 l[k] = r[k - 1] + 1,这是显然的
    18 r[k] = max{i + nums[i] | l[k - 1] <= i <= r[k - 1]},由于f值为k的位置一定是从f值为k-1的位置走来的,所以只需要看从所有f值为k-1的位置里最远可以到达的地方即可。
    19 也就是说,我们可以在对nums的一遍扫描中,依次求出所有的l[k]和r[k],而f数组也就自然求解出来了——答案也就得到了。
    20 */
    View Code
     1 class Solution {
     2 public:
     3     int jump(vector<int>& nums) {
     4         int k = 0, l = 0, r = 0;
     5         while (r < nums.size()-1) {
     6             int next_r = r;
     7             for (int i = l; i <= r; ++i) next_r = max(next_r, nums[i]+i);
     8             ++k; l = r + 1; r = next_r; 
     9         }
    10         return k;
    11     }
    12 };
    View Code

    [48] Rotate Image [Medium]

    题目要求一个方阵顺时针旋转90°。

    经过研究发现顺时针旋转90°,相当于先转置,再每行逆序。要学会矩阵转置的写法

     1 class Solution {
     2 public:
     3     void rotate(vector<vector<int>>& matrix) {
     4         const int N = matrix.size();
     5         //trans
     6         for (int i = 0; i < N; ++i) {
     7             for (int j = i+1; j < N; ++j) {
     8                 swap(matrix[i][j], matrix[j][i]);
     9             }
    10         }
    11         
    12         //reverse
    13         for (int i = 0; i < N; ++i) {
    14             int start = 0, end = N - 1;
    15             while (start < end) {
    16                 swap(matrix[i][start++], matrix[i][end--]);
    17             }
    18         }
    19     }
    20 };
    View Code

    [54] Spiral Matrix [Medium]

    打印旋转矩阵。 设置有用的四个变量 beginx, beginy, endx, endy。然后用一个i去遍历。

     1 class Solution {
     2 public:
     3     vector<int> spiralOrder(vector<vector<int>>& matrix) {
     4         vector<int> ans;
     5         if (matrix.size() == 0) {
     6             return ans;
     7         }
     8         const int m = matrix.size();
     9         const int n = matrix[0].size();
    10         int beginx = 0, beginy = 0;
    11         int endx = n-1, endy = m - 1;
    12         while (true) {
    13             for (int i = beginx; i <= endx; ++i) {
    14                 ans.push_back(matrix[beginy][i]);
    15             }
    16             ++beginy;
    17             if (beginy > endy) break;
    18             
    19             for (int i = beginy; i <= endy; ++i) {
    20                 ans.push_back(matrix[i][endx]);
    21             }
    22             --endx;
    23             if (beginx > endx) break;
    24             
    25             for (int i = endx; i >= beginx; --i) {
    26                 ans.push_back(matrix[endy][i]);
    27             }
    28             --endy;
    29             if (beginy > endy) break;
    30             
    31             for (int i = endy; i >= beginy; --i) {
    32                 ans.push_back(matrix[i][beginx]);
    33             }
    34             ++beginx;
    35             if (beginx > endx) break;
    36         }        
    37         return ans;
    38     }
    39 };
    View Code

    [56] Merge Intervals [Hard]

    合并线段(数轴) 参考57题。 在 Insert Interval的基础上,一个新的interval集合,然后每次从旧的里面取一个interval出来,然后插入到新的集合中。

     1 /**
     2  * Definition for an interval.
     3  * struct Interval {
     4  *     int start;
     5  *     int end;
     6  *     Interval() : start(0), end(0) {}
     7  *     Interval(int s, int e) : start(s), end(e) {}
     8  * };
     9  */
    10 class Solution {
    11 public:
    12     vector<Interval> merge(vector<Interval>& intervals) {
    13         vector<Interval> ans;
    14         if (intervals.size() == 0) {
    15             return ans;
    16         }
    17         ans.push_back(intervals[0]);
    18         for (int i = 1; i < intervals.size(); ++i) {
    19             insert_interval(ans, intervals[i]);
    20         }
    21         return ans;
    22     }
    23     vector<Interval> insert_interval(vector<Interval>& intervals, Interval newInterval) {
    24         vector<Interval>::iterator it = intervals.begin();
    25         while (it != intervals.end()) {
    26             if (it->start > newInterval.end) {
    27                 break;    
    28             }
    29             else if (it->end < newInterval.start) {
    30                 it++;
    31                 continue;
    32             }
    33             else {
    34                 newInterval.start = min(newInterval.start, it->start);
    35                 newInterval.end = max(newInterval.end, it->end);
    36                 intervals.erase(it);
    37             }
    38         }
    39         intervals.insert(it, newInterval);
    40         return intervals;
    41     }
    42 };
    View Code

    [57] Insert Interval [Hard]

    先判断是否能放在最前面,然后在现有的intervals中一个一个遍历。有覆盖就更新newInterval,然后把原本的那段删除。

     1 /**
     2  * Definition for an interval.
     3  * struct Interval {
     4  *     int start;
     5  *     int end;
     6  *     Interval() : start(0), end(0) {}
     7  *     Interval(int s, int e) : start(s), end(e) {}
     8  * };
     9  */
    10 class Solution {
    11 public:
    12     vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
    13         vector<Interval>::iterator it = intervals.begin();
    14         while (it != intervals.end()) {
    15             if (it->start > newInterval.end) {
    16                 break;
    17             }
    18             else if (it->end < newInterval.start) {
    19                 ++it;
    20                 continue;
    21             }
    22             else {
    23                 newInterval.start = min(it->start, newInterval.start);
    24                 newInterval.end = max(it->end, newInterval.end);
    25                 intervals.erase(it);
    26             }
    27         }
    28         intervals.insert(it, newInterval);
    29         return intervals;
    30     }
    31 };
    View Code

    [59] Spiral Matrix II [Medium]

    跟前一题Spiral Matrix的区别是前一题是遍历, 这个题是造一个矩阵出来。 思路写法都一样。

     1 class Solution {
     2 public:
     3     vector<vector<int>> generateMatrix(int n) {
     4         vector<vector<int>> matrix(n, vector<int>(n, 0));
     5         if (n == 0) {
     6             return matrix;
     7         }
     8         int number = 1;
     9         int beginx = 0, beginy = 0, endx = n - 1, endy = n - 1;
    10         while (true) {
    11             for (int i = beginx; i <= endx; ++i) {
    12                 matrix[beginy][i] = number++;
    13             }
    14             ++beginy;
    15             if (beginy > endy) { break; }
    16             
    17             for (int i = beginy; i <= endy; ++i) {
    18                 matrix[i][endx] = number++;
    19             }
    20             --endx;
    21             if (beginx > endx) { break; }
    22 
    23             for (int i = endx; i >= beginx; --i) {
    24                 matrix[endy][i] = number++;
    25             }            
    26             --endy;
    27             if (beginy > endy) { break; }
    28             
    29             for (int i = endy; i >= beginy; --i) {
    30                 matrix[i][beginx] = number++;
    31             }
    32             ++beginx;
    33             if (beginx > endx) { break; }
    34         }
    35         return matrix;
    36     }
    37 };
    View Code

    [73] Set Matrix Zeroes [Medium]

    如果矩阵中一个元素为0, 那么把该元素所在的行和列都置零。O(1)的空间复杂度

    思路:有个简单的O(m+n)的空间复杂度的,就是设两个布尔数组,来控制行和列是否为0.

    但是如果要降低到O(1)的话,就可以牺牲第0行和第0列来存这两个数组。提前用两个变量保存好第0行,第0列是否置0.

     1 class Solution {
     2 public:
     3     void setZeroes(vector<vector<int>>& matrix) {
     4         const int m = matrix.size();
     5         if (m == 0) return;
     6         const int n = matrix[0].size();
     7         bool row_has_zero = false;
     8         bool col_has_zero = false;
     9         for (size_t i = 0; i < m; ++i) {
    10             if (matrix[i][0] == 0) {
    11                 col_has_zero = true;
    12                 break;
    13             }
    14         }
    15         for (size_t j = 0; j < n; ++j) {
    16             if (matrix[0][j] == 0) {
    17                 row_has_zero = true;
    18                 break;
    19             }
    20         }
    21         
    22         for (size_t i = 1; i < m; ++i) {
    23             for (size_t j = 1; j < n; ++j) {
    24                 if (matrix[i][j] == 0) {
    25                     matrix[i][0] = 0;
    26                     matrix[0][j] = 0;
    27                 }
    28             }
    29         }
    30         
    31         for (size_t i = 1; i < m; ++i) {
    32             for (size_t j = 1; j < n; ++j) {
    33                 if (matrix[i][0] == 0 || matrix[0][j] == 0) {
    34                     matrix[i][j] = 0;
    35                 }
    36             }
    37         }
    38         
    39         if (col_has_zero == true) {
    40             for (size_t i = 0; i < m; ++i) {
    41                 matrix[i][0] = 0;
    42             }
    43         }
    44         
    45         if (row_has_zero == true) {
    46             for (size_t j = 0; j < n; ++j) {
    47                 matrix[0][j] = 0;
    48             }
    49         }
    50         return;
    51     }
    52 };
    View Code

    [118] Pascal's Triangle [Easy]

     1 class Solution {
     2 public:
     3     vector<vector<int>> generate(int numRows) {
     4         vector<vector<int>> ans;
     5         if (numRows == 0) return ans;
     6         for (size_t i = 0; i < numRows; ++i) {
     7             vector<int> ans_row(i+1, 1);
     8             if (i == 0 || i == 1) {
     9                 ans.push_back(ans_row);
    10                 continue;
    11             }
    12             for (size_t j = 1; j < i ; ++j) {
    13                 ans_row[j] = ans[i-1][j-1] + ans[i-1][j];
    14             }
    15             ans.push_back(ans_row);
    16         }
    17         return ans;
    18     }
    19 };
    View Code

    [119] Pascal's Triangle II [Easy]

    只要求O(k)的额外空间。我自己写的解法用了两个数组,其实一个就够了。

     1 class Solution {
     2 public:
     3     vector<int> getRow(int rowIndex) {
     4        vector<int> ans(rowIndex+1, 1);
     5        vector<int> help(rowIndex+1, 0);
     6        if (rowIndex == 0 || rowIndex == 1) {
     7            return ans;
     8        }
     9        for (size_t i = 2; i < rowIndex+1; ++i) {
    10            help = ans;
    11            for (size_t j = 1; j < i; ++j) {
    12                 ans[j] = help[j-1] + help[j];       
    13            }
    14            ans[i] = 1;
    15        }
    16        return ans;
    17     }
    18 };
    View Code

    一个数组的还没看懂(好困,睡了==)

     1 class Solution {
     2 public:
     3     vector<int> getRow(int rowIndex) {
     4         vector<int> A(rowIndex+1, 0);
     5         A[0] = 1;
     6         for(int i=1; i<rowIndex+1; i++)
     7             for(int j=i; j>=1; j--)
     8                 A[j] += A[j-1];
     9         return A;
    10     }
    11 };
    View Code
  • 相关阅读:
    nginx article
    学习历程
    GRPC
    学习记录
    JAVA知识点记录
    flag
    读的文章
    This usually happens because your environment has changed since running `npm install`.
    expandedRowKeys、expandedRowsChange、expand
    服务端高并发分布式架构演进之路
  • 原文地址:https://www.cnblogs.com/zhangwanying/p/6136030.html
Copyright © 2011-2022 走看看