双指针问题

快慢指针

26. 删除排序数组中的重复项

给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

示例 1:

给定数组 nums = [1,1,2],

函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。

你不需要考虑数组中超出新长度后面的元素。

思路

当快指针和慢指针相同时 快指针前进一步 不同时慢指针向前一步赋值快指针 快指针前进一步

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        slow=0
        fast=1
        while fast<len(nums):
            if nums[slow]==nums[fast]:
                fast+=1
            else:
                slow+=1
                nums[slow]=nums[fast]
                fast+=1
        return slow+1

27. 移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:

给定 nums = [3,2,2,3], val = 3,

函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。

你不需要考虑数组中超出新长度后面的元素。

思路

一个快指针一个慢指针 当快指针为目标值时跳过 否则将快指针的值赋值给慢指针 返回慢指针位置

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        fast=0
        slow=-1
        while fast<len(nums):
            if nums[fast]==val:
                fast+=1
            else:
                slow+=1
                nums[slow]=nums[fast]
                fast+=1           
        return slow+1

283. 移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:

必须在原数组上操作,不能拷贝额外的数组。
尽量减少操作次数。

思路

定义两个指针 快指针搜索 慢指针记录不是0的数当快指针到最后 以后慢指针后的全部赋值0

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        fast=0
        slow=-1  
        while fast<len(nums):
            if nums[fast]==0:
                fast+=1
            else:
                slow+=1
                nums[slow]=nums[fast]
                fast+=1
        slow+=1
        while slow < len(nums):       
            nums[slow]=0
            slow+=1

141. 环形链表

给定一个链表,判断链表中是否有环。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
在这里插入图片描述

示例 2:

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
在这里插入图片描述

示例 3:

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
在这里插入图片描述

思路

快指针慢指针从头同时出发慢指针走一个,快指针走两个如果能碰到就说明有环,否则没环,.

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        fast=head
        slow=head
        while  fast and fast.next is not None:
            fast=fast.next.next
            slow=slow.next
            if  fast==slow:
                return True
        return False

80.删除排序数组中重复项

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例 1:

给定 nums = [1,1,1,2,2,3],

函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。

你不需要考虑数组中超出新长度后面的元素。
示例 2:

给定 nums = [0,0,1,1,1,1,2,3,3],

函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。

你不需要考虑数组中超出新长度后面的元素。

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        slow=1 #慢指针
        fast=2 #快指针
        while fast <len(nums):#循环条件快指针指向列表内元素
            if nums[fast]==nums[slow-1]:
                fast+=1 #快指针与慢指针前一个元素以及慢指针所指元素相同快指针向前走一步(有序数列首尾相同中间元素必相同)
            else:
                nums[slow+1]=nums[fast] #找到不同元素慢指针记录
                slow+=1
                fast+=1
        return slow+1 #返回慢指针对应第几个元素

349. 两个数组的交集

给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]

说明:

输出结果中的每个元素一定是唯一的。
我们可以不考虑输出结果的顺序。

思路

以一个列表为主找另外一个列表中找是否有元素与之相同 如果相同则存入新列表中返回新建列表

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        nums1.sort()
        nums2.sort()
        i=0
        j=0
        list1=[]#创建空列表
        while i<len(nums1) and j<len(nums2):
            if i>0 and nums1[i]==nums1[i-1]:
                i+=1
            else:            
                if nums1[i]<nums2[j]:
                    i+=1
                elif nums1[i]>nums2[j]:
                    j+=1
                else:
                    list1.append(nums1[i])
                    i+=1
                    j+=1            
        return list1

碰撞指针

704. 二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

思路

取中

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left=-1
        right=len(nums)
        while left <=right:
            if target not in nums:
                return -1
            mid=(left + right)//2
            if target< nums[mid]:
                right =mid 
            elif target>nums[mid]:
                left =mid
            else :
                return mid

15. 三数之和

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

思路

三指针一中心两个碰撞指针 没便利一个中心指针其右侧两指针碰撞一次,当三指针之和等于目标时
记录一次继续运行/

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        res=[]
        for i in range(len(nums)-2):
            if i>0 and nums[i-1]==nums[i]:
                continue

            left=i+1
            right=len(nums)-1
            while left<right:
                threeSums=nums[i]+nums[left]+nums[right]
                if threeSums<0:
                    left+=1
                elif threeSums>0:
                    right-=1
                else:
                    res.append([nums[i],nums[left],nums[right]])
                    while left <right and nums[left]==nums[left+1]:
                        left+=1 
                    while left<right and nums[right]==nums[right-1]:
                        right-=1
                    left+=1
                    right-=1
                    
        return res

16. 最接近的三数之和

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

示例:

输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。

思路

定义三个指针 一个中心指针 两个指针中心指针从最左遍历 每个数都进行一次指针碰撞 利用三数比较大小的思想 .

class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        nums.sort()#先进行排序
        min=abs(nums[0]+nums[1]+nums[2]-target) #假设前三个最接近target
        res=nums[0]+nums[1]+nums[2]
        for i in range(len(nums)-2):#i为中心指针
            left=i+1 #定制左指针
            right=len(nums)-1 #定义右指针
            while left<right:
                sum1=nums[i]+nums[left]+nums[right]
                if abs(target-sum1) < min :
                    min=abs(target-sum1)
                    res=sum1
                if sum1 >target:
                    right-=1
                elif sum1 <target:
                    left+=1
                else:
                    return sum1
        return res

167. 两数之和 II - 输入有序数组

给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。

函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。

说明:

返回的下标值(index1 和 index2)不是从零开始的。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
示例:

输入: numbers = [2, 7, 11, 15], target = 9
输出: [1,2]
解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

思路

定义两指针一个指向最大值,一个指向最小值 如果大 指向大的左移.如果和小,指向小的右移 相等则记录下来

class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        left=0
        right=len(numbers)-1
        while left<right:
            cur=numbers[left]+numbers[right]
            if cur==target:
                left+=1
                right+=1
                return [left,right]
                
            else:
                if cur<target:
                    left+=1
                else:
                    right-=1

分离指针

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值