前言
第五天:双指针
双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务。若两个指针指向同一数组,遍历方向相同且不会相交,则也称为滑动窗口(两个指针包围的区域即为当前的窗口),经常用于区间搜索。若两个指针指向同一数组,但是遍历方向相反,则可以用来进行搜索,待搜索的数组往往是排好序的。
一、练习题目
题目链接 | 难度 |
---|---|
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.压缩字符串
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