持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
11. 盛最多水的容器
思路
(双指针扫描) O(n)
过程如下:
1、定义两个指针i和j,分别表示容器的左右边界,初始化i = 0, j = 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]已被确定,在排序后的情况下,通过双指针l,r分别从左边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来说,递归搜索树如下图所示:
递归函数设计:
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);
}
}
};