白银挑战——双指针思想以及应用
1.双指针思想
所谓双指针其实是两个变量,不一定是真正的指针
2.删除元素专题
2.1原地移除所有数值等于val的元素
leetcode27.给你一个数组Nums和一个值val,你需要原地移除所有数值等于val的元素,并返回移除后数组的新长度。要求:不要使用额外的数组空间,你必须仅使用O(1)额外空间并原地修改输入数组。元素的舒徐可以改变。你不需要考虑数组中超出新长度后面的元素。
第一种:快慢双指针
第二种:对撞型双指针
拓展:对撞双指针+覆盖
class RemoveElement:
# 第一种:快慢双指针
def removeElement(self, nums, val):
fast = 0
slow = 0
while fast < len(nums):
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
fast += 1
return slow
# 第二种:对撞型双指针
def removeElement2(self, nums, val):
left = 0
right = len(nums) - 1
while left <= right:
if nums[left] == val and nums[right] != val:
tmp = nums[right]
nums[right] = nums[left]
nums[left] = tmp
if nums[left] != val:
left += 1
if nums[right] == val:
right -= 1
return left
# 对撞双指针+覆盖
def removeElement3(self, nums, val):
left = 0
right = len(nums) - 1
while left <= right:
if nums[left] == val: # 注意这里没有nums[right] != val,为什么?
nums[left] = nums[right]
right -= 1
else:
left += 1
return left
if __name__ == '__main__':
nums = [0, 1, 2, 2, 3, 0, 4, 2]
nums2 = [3,2,2,3]
val = 2
val2 = 3
removeElement = RemoveElement()
print(removeElement.removeElement3(nums, val))
print(nums)
2.2删除有序数组中的重复项
LeetCode26:给你一个有序数组nums,请你原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。不要额外的数组空间,你必须在原地修改输入数组,并在使用O(1)额外空间的条件下完成。
class RemoveDuplicates:
def remove_duplicates(self, nums):
slow = 1
for i in range(1, len(nums)):
if nums[i] != nums[slow - 1]:
nums[slow] = nums[i]
slow += 1
return slow
if __name__ == '__main__':
nums = [0, 0, 1, 1, 1, 2, 2, 3, 3, 4]
removeDuplicates = RemoveDuplicates()
print(removeDuplicates.remove_duplicates(nums))
print(nums)
3.元素奇偶移动专题
LeetCode905:按奇偶排序数组。给定一个非负整数数组A,返回一个数组,在该数组中,A的所有偶数元素之后跟着所有奇数元素。你可以返回满足此条件的任何数组作为答案。
采用对撞型指针。
class SortArrayByParity:
def sortArrayByParity(self, nums):
n = len(nums)
res = [0] * n
left = 0
right = n - 1
for num in nums:
if num % 2 == 0:
res[left] = num
left += 1
else:
res[right] = num
right -= 1
return res
if __name__ == '__main__':
nums = [3, 1, 2, 4]
sort_array = SortArrayByParity()
print(sort_array.sortArrayByParity(nums))
4.数组轮转问题
LeetCode189:给你一个数组,将数组中的元素向右轮转K个位置,其中K是非负数。
方法:两轮翻转
class Rotate:
def rotate(self, nums, k):
length = len(nums)
k %= length
nums[:] = nums[::-1]
nums[:k] = nums[:k][::-1]
nums[k:] = nums[k:][::-1]
if __name__ == '__main__':
nums = [1, 2, 3, 4, 5, 6, 7]
rotater = Rotate()
rotater.rotate(nums, 3)
print(nums)
[m : ] 代表列表中的第m+1项到最后一项
[ : n] 代表列表中的第一项到第n项
a=[1,2,3.4,5]
print(a)
[ 1 2 3 4 5 ]
print(a[-1]) 取最后一个元素
结果:[5]
print(a[:-1]) 除了最后一个取全部
结果:[ 1 2 3 4 ]
print(a[::-1]) 取从后向前(相反)的元素
结果:[ 5 4 3 2 1 ]
print(a[2::-1]) 取从下标为2的元素翻转读取
结果:[ 3 2 1 ]
print(a[1:]) 取第二个到最后一个元素
结果:[2 3 4 5]
5.数组的区间专题
LeetCode228:给定一个无重复元素的有序整数数组nums。返回恰好覆盖数组中所有数字的最小有序区间范围列表。也就是说,nums的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于nums的数组x。列表中的每个区间范围[a,b]应该按如下格式输出:"a->b"
方法:快慢指针:慢指针指向每个区间的起始位置,快指针从慢指针位置快事向后遍历直到不满足连续递增(或快指针达到数组边界),则当前区间结束
实现的精华是:fast+1 == nums.length || nums[fast] + 1 != nums[fast+1]
class SummaryRanges:
def summaryRanges(self, nums):
n = len(nums)
slow,fast = 0, 0
res = []
while fast < n:
if fast < n - 1 and nums[fast] + 1 == nums[fast + 1]:
fast = fast + 1
else:
res.append((nums[slow], nums[fast]))
slow = fast + 1
fast = fast + 1
print(res)
# 转换成需要的字符串样式
def p(x):
slow, fast = x
if slow == fast:
return str(slow)
else:
return str(slow) + "->" + str(fast)
return list(map(p, res))
if __name__ == '__main__':
nums = [0, 2, 3, 4, 6, 8, 9]
summaryRanges = SummaryRanges()
print(summaryRanges.summaryRanges(nums))
map() 会根据提供的函数对指定序列做映射。
第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表.
6.字符串替换空格问题
请实现一个函数,将一个字符串中的每个空格替换成"%20"
class ReplaceSpace:
# 如果长度不可变,我们需要申请一个更大的空间
def replaceSpace(self, s):
res = []
for c in s:
if c == ' ':
res.append("%20")
else:
res.append(c)
return "".join(res)
# 如果使用长度可变的空间来管理原始数组,或者原始数组申请的足够大,
# 这时候就可能要求你不能申请O(n)大小的空间
# 方法:先遍历一遍字符串,可以统计出字符串中的空格个数
# 接下来从字符串的尾部开始替换和复制
def replaceSpace2(self, s):
counter = s.count(' ')
res = list(s)
res.extend([' '] * counter * 2)
left, right = len(s) - 1, len(res) - 1
while left >= 0:
if res[left] != ' ':
res[right] = res[left]
right -= 1
else:
res[right - 2: right + 1] = "%20"
right -= 3
left -= 1
return ''.join(res)
if __name__ == '__main__':
replaceSpace = ReplaceSpace()
s = "hello python!"
print(replaceSpace.replaceSpace2(s))
Python中的 .join() 函数
这个函数展开来写应该是str.join(item),join函数是一个字符串操作函数
str表示字符串(字符),item表示一个成员,注意括号里必须只能有一个成员,比如','.join('a','b')这种写法是行不通的
','.join('abc') 代码的含义是“将字符串abc中的每个成员以字符''分隔开再拼接成一个字符串”,输出结果为:'a,b,c'