LeetCode双指针
Two Sum
- 先排序
- 排序完,用两个指针分别指向第一个和最后一个
- 根据和,分别移动前后指针
上述方法需要额外保存排序前的位置,所以可解,但不推荐,现给出排序好的解法(不是当前题目解法)
vector<int> twoSum(vector<int>& nums, int target) {
int n = nums.size();
vectort<int> res;
for(int i = 0, j = n - 1; i < j;) {
int t = nums[i] + nums[j];
if(t > target) {
j--;
} else if(t < target) {
i++;
} else {
res.push_back(i);
res.push_back(j);
break;
}
}
return res;
}
- 用map保存已经计算过数值位置
- 如果找到target - 当前数在map中,直接输出结果
- 如果不存在,则把结果放入map中
vector<int> twoSum(vector<int>& nums, int target) {
int n = nums.size();
vector<int> res;
map<int, int> nmap;
for(int i = 0; i < n; i++) {
int t = target - nums[i];
if(nmap.find(t) != nmap.end()) {
res.push_back(nmap[t]);
res.push_back(i);
break;
}
nmap[nums[i]] = i;
}
return res;
}
Container With Most Water
- 前后指针遍历
- 哪边数字小,移动哪边
int maxArea(vector<int>& height) {
int res = -1, i = 0, j = height.size() - 1;
while(i <= j) {
int area = (j - i) * min(height[i], height[j]);
res = max(res, area);
if(height[i] < height[j]) {
i++;
} else {
j--;
}
}
return res;
}
3Sum
- 分别用两个数组保存出现的次数和去重后排序的数组
- 然后计算最终是否满足条件
- 也可以用map来保存上述两个值,过程是一样的
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
if(nums.size()==0) return res;
int max=0, min=0;
// 这里是计算数组的最大值和最小值
for(int d:nums){
max=max<d?d:max;
min=min>d?d:min;
}
// 下面这些是计算最大最小值里面的这个数字出现了多少次,比如
// nums = [-1,0,1,2,-1,-4], tb=[1,0,0,2,1,1,1]
int tb_size=max-min+1, m=-min;
vector<char> tb(tb_size, 0);
for(int d:nums){
if(++tb[d+m]>3)tb[d+m]=3;
}
if(tb[m]==2) tb[m]=1;
// 下面这些是计算不重复的数组并排序过的,比如
// nums = [-1,0,1,2,-1,-4], v= [-4,-1,0,1,2]
vector<int> v;
for(int i=0;i<tb_size;++i)
if(tb[i]>0) v.push_back(i-m);
int vsz=size(v);
// 下面这些我没看懂
for(int i=0;i<vsz;++i){
int vi=v[i];
if(vi>0) break;
for(int j=i;j<vsz;++j){
int vj=v[j];
int vk=-vi-vj; // 求相反数
if(vk<vj) break; //说明第三个数已经到第二个数后面去了,所以直接break
if(vk>max||tb[vk+m]==0) continue; //说明相反数在里面并不存在,直接进行下一次循环
if(tb[vj+m]>1||vi<vj && vj<vk) res.push_back({vi,vj,vk}); // 求出的结果是否合法
}
}
return res;
}
3Sum Closest
- 第一个从
0~n
遍历,第二个从i~n
遍历 - 如果sum大于target, 则右指针移动
- 如果sum小于target,则左指针移动
int threeSumClosest(vector<int>& nums, int target) {
std::sort(nums.begin(), nums.end());
int n = nums.size();
if(n < 3) return 0;
int res = nums[0] + nums[1] + nums[2];
for(int i = 0; i < n; i++) {
int j = i + 1, k = n - 1;
while(j < k) {
int sum = nums[i] + nums[j] + nums[k];
res = abs(target - sum) < abs(res - target) ? sum : res;
if(sum < target) {
j++;
} else if(sum > target) {
k--;
} else {
res = target;
return res;
}
}
}
return res;
}
Trapping Rain Water
- 只要左右都有黑色方块,那么积水一直会增加
- 所以可以用双向指针解决问题
int trap(vector<int>& height) {
int res = 0, i = 0, j = height.size() - 1;
int lmax = 0, rmax = 0;
while(i < j) {
if(height[i] < height[j]) {
height[i] >= lmax ? (lmax = height[i]) : res += (lmax - height[i]);
i++;
} else {
height[j] >= rmax ? (rmax = height[j]) : res += (rmax - height[j]);
j--;
}
}
return res;
}
- 动态规划
- 从左到右,找到当前最大值
left_max
- 从右到左,找到当前最大值
right_max
- 遍历,找到
left_max
和right_max
最小值,减去height
就是积水
int trap(vector<int>& height) {
if(height.size() == 0) return 0;
int res = 0, n = height.size();
vector<int> left_max(n, 0), right_max(n, 0);
left_max[0] = height[0];
for(int i = 1; i < n; i++) {
left_max[i] = max(height[i], left_max[i - 1]);
}
right_max[n - 1] = height[n - 1];
for(int i = n - 2; i >= 0; i++) {
right_max[i] = max(right_max[i + 1], height[i]);
}
for(int i = 1; i < n - 1; i++) {
res += min(left_max[i], right[i]) - height[i];
}
return res;
}
Sort Colors
- 分别用前后指针代表0和2所在的位置,然后遍历中间的
- 如果是0, 跟左指针换
- 如果是2, 跟右指针换
void sortColors(vector<int>& nums) {
int n = nums.size(), n0 = 0, n2 = n - 1;
int i = 0;
while( i <= n2) {
if(nums[i] == 0 && i != 0) {
swap(nums[i], nums[n0++]);
} else if(nums[i] == 2 && i != n2) {
swap(nums[i], nums[n2--]);
} else {
i++;
}
}
}
Minimum Window Substring
- 双指针,先后两个指针
- 先移动右指针,用一个vector或map保存字符的个数
- 当所有字符全部存在时,移动左指针
- 直到不满足条件时,跳出循环
string minWindow(string s, string t) {
vector<int> count(128, 0);
for(char c : t) count[c]++;
int remain = t.size(), left = 0, right = 0, minStart = 0, minLen = INT_MAX;
while(right < s.size()) {
count[s[right]]--;
if(count[s[right]] >= 0)remain--;
right++;
while(remain == 0) {
if(right - left < minLen) {
minStart = left;
minLen = right - left;
}
count[s[left]]++;
if(count[s[left]] > 0) remain++;
left++;
}
}
return minLen < INT_MAX ? s.substr(minStart, minLen) : "";
}
Remove Duplicates from Sorted List
- 一个指向当前的不重复尾部
- 一个指向下一个遍历
- 如果相等, 则
left -> next = right -> next
- 否则
left = right
ListNode* deleteDuplicates(ListNode* head) {
if(head == nullptr) return head;
ListNode* left = head;
ListNode* right = head->next;
while(right != nullptr) {
if(left -> val == right -> val) {
left->next = right->next;
} else {
left = right;
}
right = right->next;
}
return head;
}
Subarray Product Less Than K
- 用一个数字保存乘积,先移动右指针
- 当乘积大于K时,一直除左边的
- 直到程序小于K或
left = right
时 - 每次结果是
left - right + 1
int numSubarrayProductLessThanK(vector<int>& nums, int k) {
if(k == 0) return 0;
int size = nums.size(), mul = 0, left = 0, right = 0, res = 0;
while(right < size) {
mul *= nums[right];
while(mul >= k && left <= right) {
mul / = nums[left++];
}
res += right - left + 1;
++right;
}
return res;
}
Backspace String Compare
- 从后面开始遍历,用一个数字记录当前space的个数
- 然后保存新的字符串即可
string backspace(string str) {
string res = "";
int count = 0;
for(int i = str.size() - 1; i >= 0; i--) {
if(str[i] == '#') {
count++;
continue;
}
if(count > 0 ) {
count--;
} else {
res = str[i] + res;
}
}
return res;
}
bool backspaceCompare(string S, string T) {
return backspace(S) == backspace(T);
}
Squares of a Sorted Array
- 先找到大于等于0的分界点,然后计算平方值
- 如果左边大,则压入右边,右边++
- 如果右边大,则压入左边,左边--
- 最后把剩下的全都计算平方加进去
vector<int> sortedSquares(vector<int>& A) {
vector<int> res;
int more = 0, less = 0;
for(int i = 0; i < A.size(); i++) {
if(A[i] >= 0 ) {
more = i;
less = i - 1;
break;
}
}
while(less >= 0 && more < A.size()) {
int m = A[less] * A[less];
int n = A[more] * A[more];
if(m > n) {
res.push_back(n);
more++;
}
if(m < n) {
res.push_back(m);
less--;
}
if(m == n) {
res.push_back(m);
if(more != less) res.push_back(n);
more++;
less--;
}
}
while(less >= 0) {
res.push_back(A[less] * A[less]);
less--;
}
while(more < A.size()) {
res.push_back(A[more] * A[more]);
more++;
}
return res;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了