力扣刷题之双指针(python3)

本文主要是记录一下自己写过的双指针题目,基本是力扣hot100题里的,持续更新

1.什么是双指针(对撞指针、快慢指针)

双指针,指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的。换言之,双指针法充分使用了数组有序这一特征,从而在某些情况下能够简化一些运算。

2.对撞指针的用法

对撞指针是指在有序数组中,将指向最左侧的索引定义为左指针(left),最右侧的定义为右指针(right),然后从两头向中间进行数组遍历。

对撞数组适用于有序数组,也就是说当你遇到题目给定有序数组时,应该第一时间想到用对撞指针解题。

力扣题目344.反转字符串

反转字符串icon-default.png?t=M3K6https://leetcode-cn.com/problems/reverse-string/

 此题的要求为,原地修改数组,第一反应就是利用双指针求解

左指针为第一个字符,右指针为最后一个字符,交换左右指针后左指针向右走一步,右指针向左走一步,如此反复直到左右指针相撞为止。

 python代码如下:

class Solution:
    def reverseString(self, s: List[str]) -> None:
        left = 0
        right = len(s) - 1
        while left <= right:
            s[left],s[right] = s[right],s[left]
            left += 1
            right -= 1
        return s

力扣题目977.有序数组的平方

有序数组的平方icon-default.png?t=M3K6https://leetcode-cn.com/problems/squares-of-a-sorted-array/

 

由于是要生成这个数组的平方数组,而且数组是从小到大排序,有三种可能情况(举例子说明),第一种:全负数,比如[-5,-4,-3,-2,-1]

第二种:全正数,比如[1,2,3,4,5]

第三种:有正有负,比如[-4,-3,0,1,2],[-2,-1,0,1,99]

不管是哪种情况,我们可以确定最大值要么在最左侧,要么在最右侧。

直接分配两个指针,left = 0,right = len(nums)- 1,再安排一个list用于存储生成的平方数,site则为list的位置,从右到左安排。如果nums[right]的平方要大于nums[left]的平方,那么把这一数值存入list的site位中,如果nums[right]的平方要小于等于nums[left]的平方,那么存的就是nums[left]的平方了。当左右指针相撞时(也就是循环条件为while left <= right),平方数也存完了。

python代码如下: 

class Solution(object):
    def sortedSquares(self, nums):
        left = 0
        right = len(nums) - 1
        pf_nums = [0] * len(nums) #建立一个数组存储平方数
        pf_site = len(nums) - 1 #记录存储平方数的位置,从右向左移动
        while right >= left:
            if nums[right] * nums[right] > nums[left] * nums[left]: #哪个大存哪个
                pf_nums[pf_site] = nums[right] * nums[right] #将较大值存入相应的平方数组位置
                right -= 1 #右指针向左移动
            elif nums[right] * nums[right] <= nums[left] * nums[left]:
                pf_nums[pf_site] = nums[left] * nums[left]
                left += 1 #左指针向右移动
            pf_site -= 1 #每存一个数字,存储的位置就向左移动一次
        return pf_nums

力扣题目167.两数之和Ⅱ-输入有序数组

 两数之和 II - 输入有序数组icon-default.png?t=M3K6https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/

 

根据题目可知,此序列为递增序列,那么左边的肯定最小,右边的肯定最大,左指针为0 右指针为len-1,如果两个之和比目标值要小,那么就要增大最小值,也就是左指针右移,如果两个之和比目标值要大,那么减小最大值,也就是右指针左移。

python代码如下:

class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        left = 0
        right = len(numbers) - 1
        while left < right:#不能返回两个相同数字因此是left小于right
            if numbers[left] + numbers[right] == target:
                return left+1 ,right+1
            elif numbers[left] + numbers[right] < target:
                left += 1
            elif numbers[left] + numbers[right] > target:
                right -= 1

力扣577.反转字符串中的单词Ⅲ

反转字符串中的单词 IIIicon-default.png?t=M3K6https://leetcode-cn.com/problems/reverse-words-in-a-string-iii/ 

首先对句子进行切片处理,分解为一个个单词,对每个单词进行处理,每个单词的第一个字母为左指针,最后一个字母为右指针,左右指针交换位置即可,再通过join函数组合起来即可

class Solution:
    def reverseWords(self, s: str) -> str:
        words = s.split() #首先分解句子变为一个个单词
        s_r = []
        for str in words:
            str = list(str)
            left = 0
            right = len(str) - 1
            while left < right:
                str[left],str[right] = str[right],str[left]
                left += 1
                right -= 1
            s_r.append(''.join(str))
        return ' '.join(s_r)

 

3.快慢指针的用法

快慢指针就是定义两根指针,一般为slow和fast,移动的速度一快一慢,以此来制造出自己想要的差值。

力扣283.移动零

移动零icon-default.png?t=M3K6https://leetcode-cn.com/problems/move-zeroes/

此题不是经典的快慢指针,经典的快慢指针是快指针走两步慢指针走一步

此题让快指针为遍历指针,慢指针在原地待命,快指针遍历nums里的所有元素,遇到不为0的则让慢指针位置的值变为快指针位置的值,同时慢指针向右移动一步,快指针遍历完之后,再将后面的元素(慢指针所在位置开始)全部变为0

python代码如下:

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        fast = 0 #遍历指针
        slow = 0 #为非0了再进1
        while fast <= len(nums) - 1:
            if nums[fast] != 0:
                nums[slow] = nums[fast]
                slow += 1
            fast += 1
        nums[slow:] = list(0 for i in range(len(nums)-slow))
        return nums

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值