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

96 阅读1分钟

图片.png

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

11. 盛最多水的容器

思路

(双指针扫描) O(n)

过程如下:

1、定义两个指针ij,分别表示容器的左右边界,初始化i = 0j = h.size() - 1,容器大小为min(h[i], h[j])*(j - i)

2、若h[i] < h[j],则i++,否则j--,每次迭代更新最大值。

证明:

容器大小由短板决定, 移动长板的话, 水面高度不可能再上升, 而宽度变小了, 所以只有通过移动短板, 才有可能使水位上升。

时间复杂度分析: 两个指针总共扫描 n 次,因此总时间复杂度是 O(n)。

c++代码

 class Solution {
 public:
     int maxArea(vector<int>& h) {
         int res = 0;
         for(int i = 0, j = h.size() - 1; i < j;){
             res = max(res, min(h[i], h[j])*(j - i));
             if(h[i] < h[j]) i++;
             else j--;
         }
         return res;
     }
 };

15. 三数之和

思路

(排序 + 双指针) O(n^2)

  • 1、将整个nums数组按从小到大排好序
  • 2、枚举每个数,表示该数nums[i]已被确定,在排序后的情况下,通过双指针lr分别从左边l = i + 1和右边r = n - 1往中间靠拢,找到nums[i] + nums[l] + nums[r] == 0的所有符合条件的搭配
  • 3、在找符合条件搭配的过程中,假设sum = nums[i] + nums[l] + nums[r]sum > 0,则r往左走,使sum变小 若sum < 0,则l往右走,使sum变大 若sum == 0,则表示找到了与nums[i]搭配的组合nums[l]nums[r],存到ans
  • 4、判重处理 确定好nums[i]时,l需要从i + 1开始 当nums[i] == nums[i - 1],表示当前确定好的数与上一个一样,需要直接跳过 当找符合条件搭配时,即sum == 0,需要对相同的nums[l]nums[r]进行判重处理

时间复杂度分析: O(n^2)。

c++代码

 class Solution {
 public:
     vector<vector<int>> threeSum(vector<int>& nums) {
         int n = nums.size();
         vector<vector<int>> res;
         sort(nums.begin(), nums.end());
         for(int i = 0; i < n; i++){
             if(i && nums[i] == nums[i - 1]) continue;  //跳过相同的i,保证每次都是新开始
             int l = i + 1, r = n - 1;
             while(l < r){
                 int sum = nums[i] + nums[l] + nums[r];
                 if(sum > 0) r--;
                 else if(sum < 0) l++;
                 else if(sum == 0){
                     res.push_back({nums[i], nums[l], nums[r]});
                     do l++; while(l < r && nums[l] == nums[l - 1]);  //跳过相同的l
                     do r--; while(l < r && nums[r] == nums[r + 1]);  //跳过相同的r
                 }
             }
         }
         return res;
     }
 };

17. 电话号码的字母组合

思路

(回溯,哈希,组合排列) O(4^n)

对于字符串23来说,递归搜索树如下图所示:

图片.png

递归函数设计:

 void dfs(string& digits, int u, string path) {

digits字符串数组,u表示枚举到digitis的第u个位置,path用来记录路径。

解题过程如下:

1、将数字到字母的映射到哈希表中。

2、递归搜索每个数字对应位置可以填哪些字符,这里我们从哈希表中查找,并将其拼接到path后。

3、当u == digits.size()时,表示搜索完一条路径,将其加入答案数组中。

时间复杂度分析: 一个数字最多有4种情况,假设有n个数字,因此4^n种情况是一个上限,因此时间复杂度是O(4^n)。

c++代码

 class Solution {
 public:
     vector<string> res;
     string strs[10] = {
         "", "", "abc", "def",
         "ghi", "jkl", "mno",
         "pqrs", "tuv", "wxyz"
     };
     vector<string> letterCombinations(string digits) {
         if(digits.empty()) return res;
         dfs(digits, 0, "");
         return res;
     }
 ​
     void dfs(string digits, int u, string path){
         if(u == digits.size()){
             res.push_back(path);
             return ;
         }
         for(char c : strs[digits[u] - '0']){
             dfs(digits, u + 1, path + c);
         }
     }
 };