在上一篇文章中我們已經對雙指針有了一定了解,接下來我們通過題目來對雙指針進行更好的理解。
1.?leetcode?202. 快樂數
這道題使用的方法是快慢指針, 比如說一個數X,那么創建兩個變量X1和X2,然后X1每次變化兩次,X2變化一次,那么X1和X2肯定會相遇(假如說X不是快樂數,那么X1和X2會在一個變化范圍內相遇,反之就是在1的位置相遇)。
PS:這道題在我看來不是傳統意義上的快慢指針,在我看來跟多的是使用了其思想。
我們在代碼里面使用了slow和fast兩個指針來模擬相遇。
class Solution {
public:int happysum(int a){int count=0;while(a){int b=a%10;count+=b*b;a/=10;}return count;}bool isHappy(int n) {int slow=n;int fast=n;fast=happysum(fast);while(slow!=fast){slow=happysum(slow);fast=happysum(fast);fast=happysum(fast);}return fast==1;}
};
2. leetcode?11. 盛最多水的容器
這道題的話暴力是肯定不行的,那么我們可以通過左右指針的方式?。簡單來說就是最左和最右兩邊先進行一次計算,然后哪邊短哪邊移動,然后比較這幾個值的大小就可以得到結果。
PS:我們也可以理解為計算橫坐標在某個值時的最大值。
class Solution {
public:int maxArea(vector<int>& h) {int left=0;int n=h.size()-1;int right=n;int mymax=0;while(left<right){int count=min(h[left],h[right])*n;n--;if(h[left]>=h[right])right--;elseleft++;mymax=max(mymax,count);}return mymax;}
};
3. leetcode?611. 有效三角形的個數
?三角形三邊需滿足?“任意兩邊之和大于第三邊”,但直接枚舉所有三元組驗證效率低(時間復雜度高)。所以需要利用排序 + 雙指針優化。
簡單來說,就是先拿一個最大的,然后在剩下的里面通過left++和right--來直接找到符合的區間,因為實現排好序了所以一旦找到直接right-left就可以了。
class Solution {
public:int triangleNumber(vector<int>& nums) {int count=0;sort(nums.begin(),nums.end());int n=nums.size()-1;for(int i=n;i>=2;--i){int left=0;int right=i-1;while(left!=right){if(nums[left]+nums[right]>nums[i]){count+=right-left;right--;}else{left++;}}}return count;}
};
?4. leetcode?LCR 179. 查找總價格為目標值的兩個商品
?這道題也可以通過二分的方式來進行解決,在這里我們通過雙指針的方式來進行解決。
簡單來說就是先設一個left和一個right,然后通過t-p[left]的方式來得到一個值(即以p[left]為確定值的前提來查找有沒有另一個值)。因為這個數組是升序的,所以說如果找不到就說明是p[left]太小了,所以left++即可。
class Solution {
public:vector<int> twoSum(vector<int>& p, int t) {int n=p.size();int left=0;vector<int> v;for(left=0;;++left){int right=n-1;while(left<right){if(t-p[left]>p[right])break;else if(t-p[left]<p[right]){right--;}else{v.push_back(p[left]);v.push_back(p[right]);return v;}}}}
};
5. leetcode?15. 三數之和
這道題的話就和上面那到類似,唯一要注意的就是題目要求中說答案中不可以包含重復的三元組。
所以我們要先對其進行去重。三個數都有可能重復,所以三個數都要檢查一下。
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {sort(nums.begin(),nums.end());vector<vector<int>> v;int n=nums.size();for(int i=0;i<=n-3;++i){if(i>0&&nums[i]==nums[i-1])continue;int left=i+1;int right=n-1;int t=nums[i];while(left<right){if(t+nums[left]+nums[right]>0){right--;}else if(t+nums[left]+nums[right]<0){left++;}else{v.push_back({nums[i],nums[left],nums[right]});while(left<right&&nums[left]==nums[left+1])left++;while(left<right&&nums[right]==nums[right-1])right--;right--;left++;}}}return v;}
};