赞
踩
双指针从广义上来说,是指用两个变量在线性结构上遍历而解决的问题。狭义上说,
对于数组,指两个变量在数组上相向移动解决的问题;
对于链表,指两个变量在链表上同向移动解决的问题,也称为「快慢指针」问题。
//左闭右开[left,right) int left = 0, right = nums.size(), middle = left + (right-left)/2; while(left < right){ if(nums[middle]>target) right = middle; else if(nums[middle]<target) left = middle + 1; else return middle; } //左闭右闭[left,right] int left = 0, right = nums.size()-1, middle = left + (right-left)/2; while(left <= right){ if(nums[middle]>target) right = middle-1; else if(nums[middle]<target) left = middle + 1; else return middle; }
/* 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 输入:height = [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 */ class Solution { public: int trap(vector<int>& height) { int n = height.size(); int left = 1, right = n-2; int lmax = height[0], rmax = height[n-1]; int ans = 0; while(left <= right){ if(lmax <= rmax){ ans += max(lmax-height[left],0); lmax = max(lmax,height[left]); left++; } else{ ans += max(rmax-height[right],0); rmax = max(rmax,height[right]); right--; } } return ans; } };
/* 给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 输入:nums = [3,4,-1,1] 输出:2 */ class Solution { public: int firstMissingPositive(vector<int>& nums) { int left=0, right = nums.size(); while(left < right){ if(nums[left] == left+1) left++; else if(nums[left]<=left||nums[left]>right||nums[nums[left]-1]==nums[left]){ right--; swap(nums[left],nums[right]); } else swap(nums[left],nums[nums[left]-1]); } return left + 1; } };
/* 给你一个数组nums和一个值val,你需要原地移除所有数值等于val的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。 输入:nums = [3,2,2,3], val = 3 输出:2, nums = [2,2] 解释:函数应该返回新的长度 2, 并且nums中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案 */ class Solution { public: int removeElement(vector<int>& nums, int val) { int n = nums.size(); int fast=0, slow=0; while(fast<n){ if(nums[fast] == val) fast++; else{ nums[slow]=nums[fast]; fast++; slow++; } } return slow; } };
/* 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 输入: nums = [0,1,0,3,12] 输出: [1,3,12,0,0] */ class Solution { public: void moveZeroes(vector<int>& nums) { int n = nums.size(); int fast=0, slow=0; while(fast<n){ if(nums[fast]==0) fast++; else{ nums[slow]=nums[fast]; fast++; slow++; } } for(int i = slow; i < n; i++) nums[i] = 0; } };
/* 给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。 你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。 输入:nums = [1,3,4,2,2] 输出:2 */ class Solution { public: int findDuplicate(vector<int>& nums) { int n = nums.size(); if(n<2) return -1; int fast = nums[nums[0]]; int slow = nums[0]; while(fast != slow){ fast = nums[nums[fast]]; slow = nums[slow]; } fast = 0;//第一次相遇了,fast回到开头 while(fast != slow){ fast = nums[fast]; slow = nums[slow]; } return fast; } };
/* 给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。 输入:nums = [4,1,2,1,2] 输出:4 */ class Solution { public: int singleNumber(vector<int>& nums) { int n = nums.size(); if(n<2) return nums[0]; sort(nums.begin(),nums.end()); int fast = 1, slow = 0; while(fast < n-1){ if(nums[fast] == nums[slow]){ fast += 2; slow += 2; } else{ return nums[slow]; } } return nums[n-1]; } };
/* 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。 如果链表中存在环 ,则返回 true 。 否则,返回 false 。 输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点。 */ /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: bool hasCycle(ListNode *head) { if(head == NULL || head->next == NULL || head->next->next == NULL) return false; ListNode* fast = head->next->next; ListNode* slow = head->next; while(fast != slow){ if(fast->next == NULL || fast->next->next == NULL) return false; fast = fast->next->next; slow = slow->next; } return true; } };
/* 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。 不允许修改 链表。 输入:head = [3,2,0,-4], pos = 1 输出:返回索引为 1 的链表节点 解释:链表中有一个环,其尾部连接到第二个节点。 */ /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *detectCycle(ListNode *head) { if (head == NULL || head->next == NULL || head->next->next == NULL) { return NULL; } ListNode* slow = head->next; ListNode* fast = head->next->next; while(fast != slow){ if(fast->next == NULL || fast->next->next == NULL) return NULL; fast = fast->next->next; slow = slow->next; } fast = head; while(fast != slow){ fast = fast->next; slow = slow->next; } return fast; } };
参考:
https://leetcode.cn/tag/two-pointers/problemset/
https://www.bilibili.com/video/BV1V841167Rg/?spm_id_from=333.337.search-card.all.click&vd_source=f1c65f89fc3b6299ff0fcd42c1a8d57b
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。