11. Two Pointers(with example problems)

本文深入探讨双指针算法的两大类型:同向指针与面对面指针,涵盖滑动窗口、元素截断、回文验证、字符串旋转等经典问题,并解析2Sum、3Sum等常见求和问题及三角形计数等高级应用,附带详细代码实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0. Basic Concepts

0.1 Two Pointers Type?

  1. Same direction pointers
  2. Face-to-face directions pointers

1. Problem Type:

1.1 Same direction pointers

When it comes to same direction pointers, two types of problems jump into my minds.

One the the sliding window problem: two pointers move right forward simultaneously, which usually go with the sum sub-array.

The other the truncation problem: this type of problem want you to remove the duplicate the elements etc, then the left pointer will record the current index, while the right pointer will iterate the array. When there is proper element, put it to the left pointer position. In this type of problem, left pointer index is usually the size of the new array.

1.1.1 Examples:

604. Window Sum

    vector<int> winSum(vector<int> &nums, int k) {
        // write your code here
        vector<int> result;
        // Inquery base case: what if the size of nums is less than k
        if(nums.size() < k)
        {
            return result;
        }
        
        int l = 0, r = k-1;
        int sum = 0;
        for(int i = l; i <= r; i++)
        {
            sum += nums[i];
        }
        
        while(r < nums.size())
        {
            result.push_back(sum);
            sum -= nums[l++];
            sum += nums[++r];
        }
        return result;
    }

539. Move Zeroes

    void moveZeroes(vector<int> &nums) {
        // write your code here
        if(nums.empty() )
            return;
            
        int left = 0, right = 0;
        int n = nums.size();
        
        while(right < n) {
            if(nums[right] == 0) {
                right ++;
            } else {
                nums[left++] = nums[right++];
            }
        }
        
        while(left < n ) {
            nums[left++] = 0;
        }
    }

521. Remove Duplicate Numbers in Array

    int deduplication(vector<int> &nums) {
        // write your code here
        if(nums.empty())
            return 0;
        sort(nums.begin(), nums.end() );
        
        int left = 1, right = 1;
        int n = nums.size();
        while(right < n) {
            if(nums[right] != nums[left -1]) {
                nums[left++] = nums[right++];
            } else {
                right ++;
            }
        }
        return left;
    }

1.2 Face-to-face direction pointers

1.2.1 Examples:

415. Valid Palindrome

    bool isPalindrome(string &s) {
        // write your code here
        if(s.length() == 0)
            return true;
            
        int l = 0, r = s.length() -1;
        
        while(l < r)
        {
            while(l < r && !isdigit(s[l]) && !isalpha(s[l]))
                l++;
            
            while(l < r && !isdigit(s[r]) && !isalpha(s[r]))
                r--;   
            
            if(l < r && tolower(s[l++]) != tolower(s[r--])){
                return false;
            }
            
        }
        return true;
    }

8. Rotate String

void rotateString(string &str,int offset){
        //wirte your code here
    	int len = str.length();
        if(len == 0 )
            return;
        offset = offset % len;
        
        str = str.substr(len - offset) + str.substr(0, len - offset);

39. Recover Rotated Sorted Array

vector<int> tmp;
        while(true)
        {
            tmp.push_back(nums[0]);
            nums.erase(nums.begin());
            if(nums.empty() || tmp.back() > nums[0] )
                break;
        }
        
        for(auto now : tmp){
            nums.push_back(now);
        }
        return;

1.3 2 Sum, 3 Sum

For 2 sum problem, which can also be two elements problem, it usually solved by hash table or two pointers. If the array is sorted, two pointers may have a better performance; If the array is not sorted, hash table/ hash set may be a better solution.

For 3 sum problem, which can also be three elements problem, it usually iterate one elements, and then perform two pointers methods.

1.3.1 Examples:

56. Two Sum

This version uses hash table.

    vector<int> twoSum(vector<int> &numbers, int target) {
        // write your code here
        vector<int> result;
        unordered_map<int, int> hash;
        int n = numbers.size();
        if(n == 0)
            return result;
            
        for(int i = 0; i < n; i++ ) {
            int tmp = target - numbers[i];
            if(hash.find(tmp)  != hash.end() ) {
                result.push_back(hash[tmp]);
                result.push_back(i);
                return result;
            } else {
                hash[numbers[i]] = i;
            }
        }
        return result;
    }

607. Two Sum III - Data structure design

Using hash set could have better performance

// using vector and hash table
class TwoSum {
private:
    vector<int> nums;
public:
    /**
     * @param number: An integer
     * @return: nothing
     */
    void add(int number) {
        // write your code here
        nums.push_back(number);
    }

    /**
     * @param value: An integer
     * @return: Find if there exists any pair of numbers which sum is equal to the value.
     */
    bool find(int value) {
        // write your code here
        unordered_map<int, int> hash;
        for(int i = 0; i < nums.size(); i++) {
            if(hash.count(nums[i])) {
                return true;
            } else {
                hash[value - nums[i] ] = i;
            }
        }
        return false;
    }
};


// using hash set
class TwoSum {
public:
    unordered_multiset<int> nums;
    // Add the number to an internal data structure.
    void add(int number) {
        // Write your code here
        nums.insert(number);
    }

    // Find if there exists any pair of numbers which sum is equal to the value.
    bool find(int value) {
        // Write your code here
        for (int i : nums) {
            int count = i == value - i ? 2 : 1;
            if (nums.count(value - i) >= count) {
                return true;
            }
        }
        return false;
    }
};

608. Two Sum II - Input array is sorted

class Solution {
public:
    /**
     * @param nums: an array of Integer
     * @param target: target = nums[index1] + nums[index2]
     * @return: [index1 + 1, index2 + 1] (index1 < index2)
     */
    vector<int> twoSum(vector<int> &nums, int target) {
        // write your code here
        int left = 0, right = nums.size() -1;
        vector<int> result {-1, -1};
        if(right <= 0)
            return result;
            
        while(left < right && right < nums.size()) {
            int sum = nums[left] + nums[right];
            if(sum == target) {
                result[0] = left +1;
                result[1] = right +1;
                return result;
            } 
            if(sum < target) {
                left++;
            }
            if(sum > target) {
                right --;
            }
        } 
        return result;
    }
};

587. Two Sum - Unique pairs
Sort the array first.

    int twoSum6(vector<int> &nums, int target) {
        // write your code here
        int n = nums.size();
        if(nums.empty() )
            return 0;
        sort(nums.begin(), nums.end() );
        int cnt = 0;
        int left = 0, right = n -1;
        while(left < right) {
            int sum = nums[left] + nums[right];
            if(sum == target) {
                cnt++;
                // move on to next number
                left ++;
                // if there is duplicate, move forward
                while(nums[left] == nums[left -1])
                    left ++;
            }
            
            if(sum < target) {
                left ++;
                while(nums[left] == nums[left -1])
                    left ++;
            }
            
            if(sum > target) {
                right --;
                while(nums[right] == nums[right +1])
                    right --;
            }
        }
        
        return cnt;
    }

57. 3Sum

    vector<vector<int>> threeSum(vector<int> &nums) {
        // write your code here
        vector<vector<int>> result;
        if(nums.empty() ) 
            return result;
            
        sort(nums.begin(), nums.end() );
            
        for(int i = 0; i < nums.size() -2;) {
            int left = i + 1, right = nums.size() -1; 
            while(left < right ) {
                int sum = nums[left] + nums[right] + nums[i];
                if(sum == 0) {
                    result.push_back(vector<int> {nums[i], nums[left], nums[right]});
                    left++;
                    while(nums[left] == nums[left -1]) 
                        left++;
                }
                
                if(sum > 0) {
                    right --;
                    while(nums[right] == nums[right +1])
                        right--;
                }
                
                if(sum < 0) {
                    left++;
                    while(nums[left] == nums[left -1]) 
                        left++;
                }
            }
             i++;
             while(nums[i] == nums[i -1])
                i++;
        }
        return result;
    }

382. Triangle Count

Let the a, b, c be the edges of a triangle, and c is the longest edges.

In this 3 elements problem, we iterate the edge c, and perform two pointers method on a and b.

int triangleCount(vector<int> &nums) {
        // write your code here
        
        sort(nums.begin(), nums.end());
        int result = 0;
        int begin, end;
        for(int i = nums.size() -1; i > 0; i--)
        {
            begin = 0, end = i-1;
            while(begin < end)
            {
                if(nums[begin] + nums[end] > nums[i])
                {
                    result += (end - begin);
                    end--;
                }
                else {
                    begin++;
                }
                
            }
        }
        
        return result;
    }

443. Two Sum - Greater than target

    int twoSum2(vector<int> &nums, int target) {
        // write your code here
        int n = nums.size();
        if(nums.empty() ) 
            return 0;
        int cnt = 0;
        
        sort(nums.begin(), nums.end() );
        
        int left = 0, right = n -1;
        while(left < right ) {
            if(nums[left] + nums[right] > target) {
                cnt += (right - left);
                right --;
            } else {
                left ++;
            }
        }
        return cnt;
    }

609. Two Sum - Less than or equal to target

    int twoSum5(vector<int> &nums, int target) {
        // write your code here
        int n = nums.size();
        if(nums.empty() ) 
            return 0;
        int cnt = 0;
        
        sort(nums.begin(), nums.end() );
        
        int left = 0, right = n -1;
        while(left < right ) {
            if(nums[left] + nums[right] <= target) {
                cnt += (right - left);
                left ++;
            } else {
                right --;
            }
        }
        return cnt;
    }

533. Two Sum - Closest to target

 int twoSumClosest(vector<int> &nums, int target) {
        // write your code here
        int result = INT_MAX;
        if(nums.empty() || nums.size() == 1)
        {
            return result;
        }
        
        sort(nums.begin(), nums.end());
        
        int begin = 0, end = nums.size() -1;
        while(begin < end)
        {  
            int sum = nums[begin] + nums[end];
            if(sum < target)
            {
                result = abs(sum - target) < result? abs(sum - target) : result;
                begin++;
                
            }
            else{
                result = abs(sum - target) < result? abs(sum - target) : result;
                end--;
            }
        }
        return result;
    }

59. 3Sum Closest

    int threeSumClosest(vector<int> &nums, int target) {
        // write your code here
        if(nums.empty() )
            return target;
            
        int diff = INT_MAX, result;
        sort(nums.begin(), nums.end() );
        for(int i = 0; i < nums.size(); i++ ) {
            int left = i +1, right = nums.size() -1;
            while(left < right) {
                int sum = nums[i] + nums[left] + nums[right];
                if(sum > target) {
                    if(abs(sum - target) < diff) {
                        diff = abs(sum - target);
                        result = sum;
                    }
                    right --;
                } else {
                    if(abs(sum - target) < diff) {
                        diff = abs(sum - target);
                        result = sum;
                    }
                    left ++;
                }
            }
        }
        return result;
    }

58. 4Sum

    vector<vector<int>> fourSum(vector<int> &nums, int target) {
        // write your code here
        vector<vector<int>> result;
        if(nums.empty() || nums.size() < 4 )
            return result;
            
        sort(nums.begin(), nums.end()) ;
        int left, right;
        for(int i = 0; i < nums.size() -3; ) {
            for(int j = i +1; j < nums.size() -2;) {
                left = j +1, right = nums.size() -1;
                while(left < right) {
                    int sum = nums[i] + nums[j] + nums[left] + nums[right];
                    if(sum == target) {
                        result.push_back(vector<int> {nums[i], nums[j], nums[left], nums[right]} );
                        left++;
                        while(nums[left] == nums[left -1])
                            left++;
                    }
                    if(sum < target ) {
                        left++;
                        while(nums[left] == nums[left -1])
                            left++;
                    }
                        
                    if(sum > target) {
                        right --;
                        while(nums[right] == nums[right +1])
                            right--;
                    }
                }
                j++;
                while(nums[j] == nums[j -1])
                    j++;
            }
            i++;
            while(nums[i] == nums[i -1])
                i++;
        }
        return result;
    }

610. Two Sum - Difference equals to target

    vector<int> twoSum7(vector<int> &nums, int target) {
        // write your code here
        vector<int> result;
        unordered_map<int, int> hashMap;
        int n = nums.size();
        for (int i = 0; i < n; i++) {
            int tmp = nums[i] - target;
            if (hashMap.find(tmp) != hashMap.end()) {
                result.push_back(hashMap[tmp] + 1);
                result.push_back(i + 1);
                return result;
            }

            tmp = nums[i] + target;
            if (hashMap.find(tmp) != hashMap.end()) {
                result.push_back(hashMap[tmp] + 1);
                result.push_back(i + 1);
                return result;
            }

            hashMap[nums[i]] = i;
        }
     }

1.4 Partition Array

1.4.1 Examples:

31. Partition Array

    int partitionArray(vector<int> &nums, int k) {
        // write your code here
        int left = 0, right = nums.size() -1;
        while(left <= right) {
            while(nums[left] < k) 
                left ++;
                
            while(nums[right] >= k) 
                right --;
                
            if(left <= right) {
                int tmp = nums[left];
                nums[left] = nums[right];
                nums[right] = tmp;
                left ++;
                right --;
            }
        }
        return left;
    }

461. Kth Smallest Numbers in Unsorted Array

class Solution {
public:
    /*
     * @param k an integer
     * @param nums an integer array
     * @return kth smallest element
     */
    int kthSmallest(int k, vector<int> nums) {
        return quickSelect(nums, 0, nums.size() - 1, k - 1);
    }

    int quickSelect(vector<int>& A, int start, int end , int k) {
        if (start == end)
            return A[start];
        
        int left = start, right = end;
        int pivot = A[(start + end) / 2];

        while (left <= right) {
            while (left <= right && A[left] < pivot) {
                left++;
            }
            while (left <= right && A[right] > pivot) {
                right--;
            }
            if (left <= right) {
                swap(A[left++], A[right--]);
            }
        }
        if (right >= k && start <= right)
            return quickSelect(A, start, right, k);
        else if (left <= k && left <= end)
            return quickSelect(A, left, end, k);
        else
            return A[k];
    }
};

49. Sort Letters by Case

class Solution {
public:
    /*
     * @param chars: The letter array you should sort by Case
     * @return: nothing
     */
    bool isLower(char c)
    {
        return c >= 'a' && c <= 'z';
    }
    
    void sortLetters(string &str) {
        // write your code here
        int start = 0, end = str.length() -1;
        
        while(start <= end)
        {
            while(start <= end && isLower(str[start]))
                start++;
                
            while(start <= end && !isLower(str[end]))
                end--;
                
            if(start <= end)
            {
                char tmp = str[start];
                str[start] = str[end];
                str[end] = tmp;
            }
        }        
    }
};

373. Partition Array by Odd and Even

    void partitionArray(vector<int> &nums) {
        // write your code here
        
        int start = 0, end = nums.size() -1;
        
        while(start <= end)
        {
            while(nums[start] % 2 == 1)
            	start++;           
            
            while(nums[end] %2 == 0)
            	end --;
            
            if(start <= end) {
                int tmp = nums[start];
                nums[start] = nums[end];
                nums[end] = tmp;
            }
        }
    }

144. Interleaving Positive and Negative Numbers

class Solution {
public:
    /**
     * @param A: An integer array.
     * @return: void
     */
    vector<int> subfun(vector<int> &A, vector<int> &B) {
        vector<int> ans;
        for(int i = 0; i < B.size(); i++) {
            ans.push_back(A[i]);
            ans.push_back(B[i]);
            }
        if(A.size() > B.size())
            ans.push_back(A[B.size()]);
        return ans;
    }
    void rerange(vector<int> &A) {
        // write your code here
        vector<int> Am, Ap, tmp;
        for(int i = 0; i < A.size(); i++)
            if(A[i] > 0)
                Ap.push_back(A[i]);
            else
                Am.push_back(A[i]);
        if(Ap.size() > Am.size())
            tmp = subfun(Ap, Am);
        else
            tmp = subfun(Am, Ap);

        for (int i = 0; i < tmp.size(); ++i)
            A[i] = tmp[i];
    }
};

148. Sort Colors
Three pointers problem.

    void sortColors(vector<int> &nums) {
        int left = 0, right = nums.size() - 1;
        int middle = 0;
        
        // should be <= not <
        while (middle <= right) {
            if (nums[middle] == 0) {
                swap(nums[middle], nums[left]);
                left++;
                middle++;
            } else if (nums[middle] == 1) {
                middle++;
            } else {
                swap(nums[middle], nums[right]);
                right--;
            }
        }
    }

143. Sort Colors II

One solution: Bucket Sorting

    void sortColors2(vector<int> &colors, int k) {
        // write your code here
        
        vector<int> count(k +1);
        for(auto num : colors) 
            count[num] ++;
        
        int index = 1;
        for(int i = 0; i < colors.size(); i++) {
            while(count[index] == 0) {
                index ++;
            }
            
            colors[i] = index ; 
            count[index] --;
        }
    }

Another Solution: divide and conquer

class Solution {
public:
    /**
     * @param colors: A list of integer
     * @param k: An integer
     * @return: nothing
     */
    void sortColors2(vector<int> &colors, int k) {
        // write your code here
        partition(colors, 0, colors.size()-1, 1, k);
    }
    
    void partition(vector<int>& colors, int start, int end, int startk, int endk) {
        if (start >= end || startk >= endk) {
            return;
        }
        
        int midk = (startk+endk)/2;
        int i = start, j = end;
        while (i <= j) {
            while (i <= j && colors[i] <= midk) {
                i++;
            }
            while (i <= j && colors[j] > midk) {
                j--;
            }
            if (i <= j) {
                int temp = colors[j];
                colors[j] = colors[i];
                colors[i] = temp;
                i++;
                j--;
            }
        }

        partition(colors, start, j, startk, midk);
        partition(colors, i, end, midk+1, endk);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值