C++ 双指针算法(超通俗讲解 + 实战代码)
1. 移动零
283. 移动零
https://leetcode.cn/problems/move-zeroes/
给定一个数组
nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。
cppclass Solution { public: void moveZeroes(vector<int>& nums) { int cur=0,curf=0; while(cur!=nums.size()) { if(nums[cur]==0) { cur++; } else { swap(nums[curf],nums[cur]); curf++; cur++; } } } };
2. 复写零
1089. 复写零
https://leetcode.cn/problems/duplicate-zeros/
给你一个长度固定的整数数组
arr,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。注意:请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。
cppclass Solution { public: void duplicateZeros(vector<int>& arr) { int dest=-1,cur=0,sz=arr.size(); while(cur<sz) { if(arr[cur]!=0) dest++; else dest+=2; if(dest>=sz-1) break; cur++; } if(dest==sz) { dest-=2; arr[sz-1]=0; cur--; } while(cur>=0) { if(arr[cur]!=0) { arr[dest]=arr[cur]; dest--; cur--; } else { arr[dest--]=0; arr[dest--]=0; cur--; } } } };
3. 快乐树
202. 快乐数
https://leetcode.cn/problems/happy-number/
编写一个算法来判断一个数
n是不是快乐数。「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
如果
n是 快乐数 就返回true;不是,则返回false
cppclass Solution { public: int bitsum(int n) { int add=0,sum; while(n!=0) { sum=n%10; sum*=sum; n=n/10; add+=sum; } return add; } bool isHappy(int n) { int slow=n; int fast=bitsum(n); while(slow!=fast) { slow=bitsum(slow); fast=bitsum(bitsum(fast)); } return slow==1; } };
4. 盛水最多的容器
11. 盛最多水的容器
https://leetcode.cn/problems/container-with-most-water/
给定一个长度为
n的整数数组height。有n条垂线,第i条线的两个端点是(i, 0)和(i, height[i])。找出其中的两条线,使得它们与
x轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。
说明:你不能倾斜容器。
5. 有效三角形个数
611. 有效三角形的个数
https://leetcode.cn/problems/valid-triangle-number/
给定一个包含非负整数的数组
nums,返回其中可以组成三角形三条边的三元组个数。
cppclass Solution { public: int triangleNumber(vector<int>& nums) { int i=0,count=0,left,right; sort(nums.begin(),nums.end()); if(nums.size()<3) return 0; while(i<nums.size()-2) { left=i+1; while(left!=nums.size()-1) { right=nums.size()-1; while(right!=left) { if (nums[left]+nums[right]>nums[i]&& nums[left]+nums[i]>nums[right]) { count=count+(right-left); break; } else right--; } left++; } i++; } return count; } };
6. 三数之和
15. 三数之和
https://leetcode.cn/problems/3sum/
给你一个整数数组
nums,判断是否存在三元组[nums[i], nums[j], nums[k]]满足i != j、i != k且j != k,同时还满足nums[i] + nums[j] + nums[k] == 0。请你返回所有和为0且不重复的三元组。注意:答案中不可以包含重复的三元组。
cppclass Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { sort(nums.begin(),nums.end()); vector<vector<int>> sv; int k=0,left,right,add; while(k<nums.size()-2) { left=k+1; right=nums.size()-1; while(left<right) { add=nums[k]+nums[left]+nums[right]; //判断情况,区分进行 if(add>0) right--; else if(add<0) left++; else if(add==0) { sv.push_back({nums[k],nums[left],nums[right]}); //跳过重复数 while(nums[left]==nums[left+1] && left+1<right) left++; while(nums[right]==nums[right-1] && right-1>left) right--; left++;right--; } } k++; //跳过重复数 while(nums[k]==nums[k-1] && k!=nums.size()-1) k++; } return sv; } };
7. 四数之和
18. 四数之和
https://leetcode.cn/problems/4sum/
给你一个由
n个整数组成的数组nums,和一个目标值target。请你找出并返回满足下述全部条件且不重复的四元组[nums[a], nums[b], nums[c], nums[d]](若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < na、b、c和d互不相同nums[a] + nums[b] + nums[c] + nums[d] == target你可以按 任意顺序 返回答案 。
cppclass Solution { public: vector<vector<int>> fourSum(vector<int>& nums, int target) { sort(nums.begin(),nums.end()); vector<vector<int>> sv; int x=0,a; int k,left,right; long long add; if(nums.size()<4) return sv; while(x<nums.size()-3) { k=x+1; a=nums[x]; while(k<nums.size()-2) { left=k+1; right=nums.size()-1; while(left<right) { add=(long long)nums[k]+nums[left]+nums[right]; if(add>target-a) right--; else if(add<target-a) left++; else if(add==target-a) { sv.push_back({nums[x],nums[k],nums[left],nums[right]}); while(nums[left]==nums[left+1] && left+1<right) left++; while(nums[right]==nums[right-1] && right-1>left) right--; left++;right--; } } k++; while(nums[k]==nums[k-1]&&k!=nums.size()-1) k++; } x++; while(nums[x]==nums[x-1]&&x!=nums.size()-1) x++; } return sv; } };


