【双指针-01】
目录
- 剑指 Offer 57 - II. 和为s的连续正数序列
- 剑指 Offer 57. 和为s的两个数字
- 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
- 剑指 Offer 53 - II. 0~n-1中缺失的数字
-
剑指 Offer 48. 最长不含重复字符的子字符串/3. 无重复字符的最长子串(滑动窗口)
一、剑指 Offer 57 - II. 和为s的连续正数序列
1.1 问题
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
示例 1:
输入:target = 9
输出:[[2,3,4],[4,5]]
示例 2:
输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
1.2 思路
双指针,左侧从1开始,且限定在target/2+1,找到一个后,左侧加1滑动。
1.3 代码
class Solution:
def findContinuousSequence(self, target: int) -> List[List[int]]:
i,j,sum,res= 1,1,0,[]
while i <= target//2 +1 :
if sum < target: #小了,加上右侧的数字
sum += j
j += 1
elif sum > target: #大了,减去左侧的数字
sum -= i
i += 1
else: #符合条件,滚动左侧指针
res.append(list(range(i,j)))
sum -= i
i +=1 #这个不能忘记
return res
二、剑指 Offer 57. 和为s的两个数字
2.1 问题
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[2,7] 或者 [7,2]
示例 2:
输入:nums = [10,26,30,31,47,60], target = 40
输出:[10,30] 或者 [30,10]
2.2 代码
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
i,j = 0,len(nums)-1
while i < j :
s = nums[i] + nums[j]
if s > target:
j -= 1
elif s < target:
i +=1
else:
return nums[i],nums[j]
return []
三、剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
3.1 问题
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
示例:
输入:nums = [1,2,3,4]
输出:[1,3,2,4]
注:[3,1,2,4] 也是正确的答案之一。
3.2 解释
双指针,分四种情况讨论,写的过程中,注意elif的使用。
3.3 代码
class Solution:
def exchange(self, nums: List[int]) -> List[int]:
if len(nums)==0 or len(nums) == 1:
return nums
i,j = 0 ,len(nums)-1
while (i<j): #注意分四中情况讨论
if nums[i] % 2 == 1 and nums[i] % 2 ==1:
i +=1
elif nums[j] %2 == 0 and nums[i] %2 ==0:
j -= 1
elif nums[i] % 2 ==0 and nums[j] %2 ==1:
nums[i],nums[j] = nums[j],nums[i]
i += 1
j -= 1
elif nums[i]%2==1 and nums[i]%2==0:
i += 1
j -=1
return nums
四、剑指 Offer 53 - II. 0~n-1中缺失的数字
4.1 问题
一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。
示例 1:
输入: [0,1,3]
输出: 2
4.2 代码(二分查找)
class Solution:
def missingNumber(self, nums: List[int]) -> int:
i , j = 0,len(nums)-1
while i <= j: #注意等号
mid = (i+j)//2 #整除
if nums[mid] == mid:
i = mid +1
else:j = mid -1
return i #返回i
五、剑指 Offer 48. 最长不含重复字符的子字符串/3. 无重复字符的最长子串(滑动窗口)
5.1 问题
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
5.2 代码
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s :return 0
max_len = 0
cur_len =0
lookup = []
for right in range(len(s)):
cur_len += 1
while s[right] in lookup:
lookup.pop(0)
cur_len -=1
if cur_len > max_len:max_len = cur_len
lookup.append(s[right])
return max_len