【五月集训】Day05——双指针


前言

        第五天:双指针
        双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务。若两个指针指向同一数组,遍历方向相同且不会相交,则也称为滑动窗口(两个指针包围的区域即为当前的窗口),经常用于区间搜索。若两个指针指向同一数组,但是遍历方向相反,则可以用来进行搜索,待搜索的数组往往是排好序的。


一、练习题目

题目链接难度
917. 仅仅反转字母★☆☆☆☆
167. 两数之和 II - 输入有序数组★★☆☆☆
165. 比较版本号★★☆☆☆
443. 压缩字符串★★★☆☆

二、思路与代码

1. 仅仅反转字母

        给你一个字符串 s ,根据下述规则反转字符串:1)所有非英文字母保留在原有位置。2)所有英文字母(小写或大写)位置反转。返回反转后的 s 。

首尾分别创建一个指针,若两处所指均为字母,交换其位置即可。

class Solution(object):
    def reverseOnlyLetters(self, s):
        """
        :type s: str
        :rtype: str
        """
        l, r = 0, len(s) - 1 #首尾分别创建一个指针
        ans = list(s) #由于python中字符串不可变,先将字符串s转换为列表并赋值给ans
        while l < r:
            while l < r and not ans[l].isalpha(): #如果左指针小于右指针,并且当前值不是字母,则继续遍历
                l += 1
            while l < r and not ans[r].isalpha(): #同上一个注释
                r -= 1
            if l < r:  #依据题意,交换两边的值
                tmp = ans[r]
                ans[r] = ans[l]
                ans[l] = tmp
                l += 1
                r -= 1
        return ''.join(ans) #将列表合并成字符串

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

        题目描述

同样,左右双指针,若两指针所指数字和大于target,说明右指针所指数字偏大,指针左移;若和小于target,说明左指针所指数字偏小,左指针右移。

class Solution(object):
    def twoSum(self, numbers, target):
        """
        :type numbers: List[int]
        :type target: int
        :rtype: List[int]
        """
        l, r = 0, len(numbers) - 1
        while l < r:
            if numbers[l] + numbers[r] > target: #数组按非递减顺序排列,如果和大于target则移动右指针,反之左指针
                r -= 1
            elif numbers[l] + numbers[r] < target:
                l += 1
            elif numbers[l] + numbers[r] == target:
                ans = [l+1, r+1] 
                return ans

3.比较版本号

        题目描述

这一题有点偏字符串,思路看注释应该就可以了。

class Solution(object):
    def compareVersion(self, version1, version2):
        """
        :type version1: str
        :type version2: str
        :rtype: int
        """
        v1s = version1.split('.') #以'.'为分隔符,拆开给定字符串
        v2s = version2.split('.')
        while len(v1s) < len(v2s): #当得到的两个列表长度不同时,在长度小的列表后补零,使两者长度相同
            v1s.append('0')
        while len(v2s) < len(v1s):
            v2s.append('0') 
        
        for i in range(len(v1s)): #按顺序比较两个列表中数字的大小
            if (int(v1s[i]) > int(v2s[i])): #将字符强制转换为int整型
                return 1
            elif (int(v1s[i]) < int(v2s[i])):
                return -1
            else:
                continue
        return 0

4.压缩字符串

        题目描述比较tricky的情况

1)为了压缩相同字符,并返回题目要求的结果,需定义三个指针,分别为left,right,point三个指针;
2)left,right指针用来搜索相同字符串区间长度,point指针用来定位压缩后的字符串的位置;
3)一个细节,在开始遍历前,在原字符串末尾加上空字符" ",防止遗漏字符串的最后一个字符。

class Solution(object):
    def compress(self, chars):
        """
        :type chars: List[str]
        :rtype: int
        """
        point = left = 0 # 定义两个指针
        chars.append(' ') # 在字符串末尾加上空字符,防止遍历不到最后一个字符
        for right, char in enumerate(chars): 
            if char != chars[left]:  # 如果遍历中的字符与左指针所指字符不同
                chars[point] = chars[left]  # 将原字符串里,point指针所指位置赋值为left指针的大小
                point += 1 # point指针右移一位
                distance = right - left #左右指针的距离大小
                if distance > 1: 
                    for i in str(distance): #将int整型距离变为str型
                        chars[point] = i
                        point += 1
                left = right #将右指针大小赋值给左指针
        return point

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值