Analysis of classic examples of double pointer algorithm

Table of contents

Question 1, moving zero

Question 2, copy zero

Question 3: Happy Number

Question 4: How much water can be held in the largest container?

Question 5. Number of valid triangles

Question 6 The sum of two numbers


Question 1, moving zero

Given an array  nums, write a function that  0 moves all to the end of the array while maintaining the relative order of non-zero elements.

Note  that arrays must be operated on in-place without copying the array.

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int dest=-1;
        for(int cur=0;cur<nums.size();cur++)
        {
            if(nums[cur]!=0){
                swap(nums[++dest],nums[cur]);
            }
        }
    }
};

Question 2, copy zero

Given a fixed-length integer array arr, copy every zero that appears in the array and shift the remaining elements to the right.

Note: Please do not write elements beyond the length of the array. Please make the above modifications to the input array in-place and do not return anything from the function.

Analysis:

Copying from front to back will cause the original data to be overwritten, so we consider finding the last copied data first and starting to copy from the back to the front.

But when looking for the last copied data, if the last copied data is 0, then the dest pointer may go out of bounds.

        while(dest<arr.size()){//这样写找的cur是超出的那个数据,需要额外判断情况太麻烦
            if(arr[cur]=0){
                cur++;
                dest+=2;//步长为2就可能越界      
            }
            else{
                ++cur;
                ++dest
            }
        }
public:
    void duplicateZeros(vector<int>& arr) {
        int cur=0,dest=-1,n=arr.size();//我不知道dest的最后位置是什么,需要进行模拟所以初始化为-1
        while(cur<n){
            if(arr[cur]==0){
                dest+=2;
            }
            else{
                dest++;
            }

            if(dest>=n-1) break;//先判断写入的是否越界,若不越界才继续向下找
            cur++;
        }

        if(dest==n){
            arr[n-1]=0;
            dest-=2;
            cur--;
        }

        while(cur>=0){
            if(arr[cur]==0){
                arr[dest--]=0;
                arr[dest--]=0;
                cur--;
            }
            else{
                arr[dest--]=arr[cur--];
            }
        }

    }
};

Question 3: Happy Number

Write an algorithm to determine whether a number n is a happy number.

"Happy Number" is defined as:

For a positive integer, each time the number is replaced by the sum of the squares of its digits at each position.
Then repeat this process until the number reaches 1, or it may loop infinitely but never reaches 1.
If this process results in 1, then this number is the happy number.

After a number undergoes this operation, the value range will definitely be narrowed. According to the pigeonhole principle, it can always be trapped in a loop.

class Solution {
public:
    bool isHappy(int n) {
        int slow=n,fast=n;
        fast=0;
        while(n!=0){   
                fast+=(n%10)*(n%10);
                n/=10;
            }
        while(slow!=fast){
            int tmp1=slow;
            int tmp2=fast;
            slow=fast=0;
            while(tmp1!=0){
                slow+=(tmp1%10)*(tmp1%10);
                tmp1/=10;
            }
            while(tmp2!=0){
                fast+=(tmp2%10)*(tmp2%10);
                tmp2/=10;
            }
            tmp2=fast;
            fast=0;
            while(tmp2!=0){
                fast+=(tmp2%10)*(tmp2%10);
                tmp2/=10;
            }
        }

        if(slow==1){
            return true;
        }
        return false;
    }
};

Of course we can observe that taking the sum of the squares of each digit is used multiple times, so we can encapsulate a function

class Solution {
public:

int all_sum(int n){
    int sum=0;
    while(n!=0){
        sum+=(n%10)*(n%10);
        n/=10;
    }
    return sum;
}
    bool isHappy(int n) {
        int slow=n,fast=all_sum(n);
        while(slow!=fast){
            slow=all_sum(slow);
            fast=all_sum(all_sum(fast));
        }
        if(slow==1) 
        return true;

        return false;
    }
};

Question 4: How much water can be held in the largest container?

Given an integer array height of length n. There are n vertical lines, and the two endpoints of the i-th line are (i, 0) and (i, height[i]).

Find the two lines such that together with the x-axis they form a container that can hold the most water.

Returns the maximum amount of water the container can store.

Source: LeetCode
link: https://leetcode.cn/problems/container-with-most-water

We can know that choosing the smaller cup wall to enumerate inward will only make our volume smaller anyway.

class Solution {
public:
    int maxArea(vector<int>& height) {
        int ret=0;
        int left=0,right=height.size()-1;
        while(left<right){
            int min_high=height[left];
            if(height[left]>height[right]){
                min_high=height[right];
            }
            int tmp=min_high*(right-left);
            if(tmp>ret){
                ret=tmp;
            }
            if(height[left]>height[right]){
                right--;
            }
            else{
                left++;
            }
        }
        return ret;

    }
};

More concise way of writing

        int ret=0;
        int left=0,right=height.size()-1;
        while(left<right){
            int tmp=min(height[left],height[right])*(right-left);
            ret=max(tmp,ret);
            if(height[left]<height[right]) left++;
            else right--;
        }
        return ret;

Question 5. Number of valid triangles

Given an array containing non-negative integers  nums , return the number of triples that can form three sides of a triangle.

class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        sort(nums.begin(),nums.end());

        int ret=0,left=0,right=0;

        for(int i=nums.size()-1;i>=2;i--){
            left=0,right=i-1;

            while(left<right){
                if(nums[right]+nums[left]>nums[i]){
                    ret=ret+right-left;
                    right--;
                }
                else{
                    left++;
                }

            }
        }
        
    return ret;
    }

};

Question 6 The sum of two numbers

Wrong interpretation of the question

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> ret;
        ret.resize(2);

        sort(nums.begin(),nums.end());//排序以后你就不知道他原来的下标是多少了

        int left=0,right=nums.size()-1;

        while(left<right){
            if(nums[left]+nums[right]>target){
                right--;
            }
            else if(nums[left]+nums[right]<target){
                ++left;
            }
            else if(nums[left]+nums[right]==target){
                ret[0]=left;
                ret[1]=right;
                break;
            }

        }

        return ret;
    }
};

 Using a hash table is a good way to quickly search


class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> hashtable;
        for (int i = 0; i < nums.size(); ++i) {
            auto it = hashtable.find(target - nums[i]);
            if (it != hashtable.end()) {
                return {it->second, i};
            }
            hashtable[nums[i]] = i;
        }
        return {};
    }
};

Guess you like

Origin blog.csdn.net/m0_74234485/article/details/131507226