双指针算法

核心思想: 将需要O(n²)的双重循环优化到O(n)

模板:

for(int i = 0, j = 0; i <= n; i++){
	while(j < i && check(i, j))j++;
}

双指针例题

leecode 3. 无重复字符的最长子串

主要的思路是用两个指针做头尾,并向后移动。当子串重复出现时,一定是与头指针的元素重复(因为子串是连续的),因此尾指针向后移动,头指针向后移动(删除头指针元素)

int lengthOfLongestSubstring(string s) {
	int res = 0;
	vector<int>temp(105, 0);
	for(int i = 0, j = 0; i < s.size(); i++){
		temp[(s[i] - '0' + 103) % 103]++;
		while(temp[(s[i] - '0' + 103) % 103] > 1){//判断是否出现了重复元素
			temp[(s[j] - '0' + 103) % 103]--;
			j++;
		}
		res = max(res, i - j + 1);
	}
	return res;
}

这里注意,因为s中含有字符和空格,转换为int后会出现复数,需要取模。

leecode 283.移动零(首刷)

空间占用的有点多

void moveZeroes(vector<int>& nums) {
        int start = 1e4 + 10;
        for(int i = 0; i < nums.size(); i++){
            if(!nums[i]){
                start = i;
                break;
            }
        }
        for(int i = start + 1, j = start; i < nums.size(); i++){
            if(nums[i]){
                nums[j++] ^= nums[i];
                nums[i] = 0;
                while(nums[j] && j < i)j++;//j一直找到下一个为0的点
            }
        }
    }
leecode 42. 接雨水

思路很牛逼,基本就是通过头尾双指针和短板效应约束水位最高边界,详解参考:经典面试题:接雨水问题详解 很清晰。

int trap(vector<int>& height) {
        int n = height.size();
        if(!n)return 0;
        int left = 0, right = n - 1;//双指针
        int l_max = height[0], r_max = height[n - 1];
        int ans = 0;
        while(left <= right){
            l_max = max(l_max, height[left]);
            r_max = max(r_max, height[right]);

            if(l_max < r_max){
                ans += l_max - height[left];
                left ++;
            }else{
                ans += r_max - height[right];
                right --;
            }
        }
        return ans;
    }
相交链表

原理:假设headA链表的单独部分和重合部分为a + c, headB链表的单独部分和重合部分为b + c,每个指针每次均向后移位,分别将两个链表遍历一遍:

  1. 若每个指针将两个链表遍历结束之后还是没有相交,则两个链表无相交的地方。
  2. 若某个指针将其中一个链表遍历结束后,指向另一个链表的头部紧接着遍历。
  3. 这样能找到遍历的节点,因为ptr1停下时走过了 a + c + b, ptr2停下时走过了 b + c + a
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(!headA || !headB)return nullptr;
        ListNode* ptr1 = headA,*ptr2 = headB;
        while(ptr1 != ptr2){
            ptr1 = (ptr1 ? ptr1->next : headB);
            ptr2 = (ptr2 ? ptr2->next : headA);
        }
        return ptr1;
    }

leecode 11.盛水最多的容器
跟接雨水的题目很像,但是简单很多很多,不过接雨水是要考虑左右边界的高度和内部水柱的距离,而这道题简单很多,只需找到需要作为边界的左右两个柱子就行。

class Solution {
public:
    int maxArea(vector<int>& height) {
        int n = height.size();
        if(!n)return 0;
        int left = 0, right = n - 1;
        int res = 0;
        while(left <= right){
            res = max(res, min( height[left],height[right]) * (right - left));
            if(height[left] < height[right])left ++;
            else right--;
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值