算法与数据结构基础 - 双指针(Two Pointers)

作者: 博客园-SharePoint团队  更新时间:2019-08-15 15:02:00  原文链接


双指针基础

双指针(Two Pointers)是面对数组、链表结构的一种处理技巧。这里“指针”是泛指,不但包括通常意义上的指针,还包括索引、迭代器等可用于遍历的游标。

同方向指针

设定两个指针、从头往尾(或从尾到头)遍历,我称之为同方向指针,第一个指针用于遍历,第二个指针满足一定条件下移动。例如 LeetCode题目 283. Move Zeroes:

    // 283. Move Zeroes
    void moveZeroes(vector<int>& nums) {
        int i=0;
        for(int j=0;j<nums.size();j++){
            if(nums[j]!=0) nums[i++]=nums[j];
        }
        while(i<nums.size()) nums[i++]=0;
    }

相关LeetCode题:

283. Move Zeroes 题解

26. Remove Duplicates from Sorted Array 题解

80. Remove Duplicates from Sorted Array II 题解

349. Intersection of Two Arrays 题解

350. Intersection of Two Arrays II 题解

925. Long Pressed Name 题解

88. Merge Sorted Array 题解

844. Backspace String Compare 题解

86. Partition List 题解

986. Interval List Intersections 题解

209. Minimum Size Subarray Sum 题解

713. Subarray Product Less Than K 题解

826. Most Profit Assigning Work 题解

930. Binary Subarrays With Sum 题解

838. Push Dominoes 题解

滑动窗口(Sliding Windows)也属于同方向指针,关于滑动窗口详见:

算法与数据结构基础 - 滑动窗口(Sliding Window)

快慢指针

若双指针以固定步长移动,如第一个指针移动两步、第二个指针移动一步,这种我们称之为快慢指针。快慢指针常用于单向链表环(Cycle)判断、Loop判断等问题。

相关LeetCode题:

19. Remove Nth Node From End of List 题解

141. Linked List Cycle 题解

142. Linked List Cycle II 题解

234. Palindrome Linked List 题解

457. Circular Array Loop 题解

287. Find the Duplicate Number 题解

反方向指针

若双指针其中一个从头开始、另一个从尾开始,两者往中间遍历,这种使用方法我称之为反方向指针。例如常见的反转字符串问题 LeetCode 344. Reverse String:

    // 344. Reverse String 
    void reverseString(vector<char>& s) {
        int i=0,j=s.size()-1;
        while(i<j) swap(s[i++],s[j--]);
    }

相关LeetCode题:

344. Reverse String 题解

125. Valid Palindrome 题解

345. Reverse Vowels of a String 题解

61. Rotate List 题解

75. Sort Colors 题解

1093. Statistics from a Large Sample 题解

11. Container With Most Water 题解

42. Trapping Rain Water 题解

应用于有序数列

一些情况下先对数组排序,利用有序这个性质来判别双指针怎么移动,例如 LeetCode题目 15. 3Sum:

            // 15. 3Sum
            int l=i+1, r=nums.size()-1;
            while(l<r){
                int tmp=nums[i]+nums[l]+nums[r];
                if(tmp>0) r--;
                else if(tmp<0) l++;
                ……
            }