2022年10月20日 14点18分
只要数组有序,就应该想到双指针技巧。
快慢指针
# 26. 删除有序数组中的重复项
# 83. 删除排序链表中的重复元素
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head:return head
slow = head
fast = head
while fast:
if fast.val!=slow.val:
slow.next = fast
slow = slow.next
fast = fast.next
slow.next = None
return head
# 27. 移除元素
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
i,j,n = 0,0,len(nums)
while j < n:
if nums[j] != val:
nums[i] = nums[j]
i = i + 1
j = j + 1
return n - j + i
左右指针
二分查找
# 167. 两数之和 II - 输入有序数组
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
left,right = 0,len(numbers)-1
while left<right:
sum = numbers[left] + numbers[right]
if sum==target:
return [left+1,right+1]
elif sum<target:
left += 1
else:
right -= 1
return [-1,-1]
# 5. 最长回文子串
class Solution:
def longestPalindrome(self, s: str) -> str:
r = ''
n = len(s)
for i in range(n):
s1 = self.getPalindrome(s,i,i)
s2 = self.getPalindrome(s,i,i+1)
if len(s1) > len(r):
r = s1
if len(s2) > len(r):
r = s2
return r
def getPalindrome(self,s,i,j):
while i>=0 and j<len(s) and s[i]==s[j]:
i-=1
j+=1
return s[i+1:j]
前缀和
前缀和主要适用的场景是原始数组不会被修改的情况下,频繁查询某个区间的累加和
一维数组中的前缀和
# 303. 区域和检索 - 数组不可变
class NumArray:
def __init__(self, nums: List[int]):
n = len(nums)
self.s = [0]
x = 0
for i in range(n):
x += nums[i]
self.s.append(x)
def sumRange(self, left: int, right: int) -> int:
return self.s[right+1] - self.s[left]
二维矩阵中的前缀和
304. 二维区域和检索 - 矩阵不可变
class NumMatrix:
def __init__(self, matrix: List[List[int]]):
m, n = len(matrix), (len(matrix[0]) if matrix else 0)
self.sums = [[0] * (n + 1) for _ in range(m + 1)]
_sums = self.sums
for i in range(m):
for j in range(n):
_sums[i + 1][j + 1] = _sums[i][j + 1] + _sums[i + 1][j] - _sums[i][j] + matrix[i][j]
def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
_sums = self.sums
return _sums[row2 + 1][col2 + 1] - _sums[row1][col2 + 1] - _sums[row2 + 1][col1] + _sums[row1][col1]
差分数组
差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减
对 nums 数组构造一个 diff 差分数组,diff[i] 就是 nums[i] 和 nums[i-1] 之差
int[] diff = new int[nums.length];
// 构造差分数组
diff[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
diff[i] = nums[i] - nums[i - 1];
}
这样构造差分数组 diff,就可以快速进行区间增减的操作,如果你想对区间 nums[i…j] 的元素全部加 3,那么只需要让 diff[i] += 3,然后再让 diff[j+1] -= 3(这一步是为了让后序元素不受影响)
# 差分数组构造类
class Difference:
def __init__(self,nums):
self.diff = [0]*len(nums)
_diff = self.diff
_diff[0] = nums[0]
for i in range(1,len(nums)):
_diff[i] = nums[i] - nums[i-1]
def increment(self,i,j,val):
_diff = self.diff
_diff[i] += val
if j+1 <len(_diff):
_diff[j+1] -= val
def result(self):
_diff = self.diff
res = [0]*len(_diff)
res[0] = _diff[0]
for i in range(1,len(_diff)):
res[i] = res[i-1] + _diff[i]
return res
# 1109. 航班预订统计
class Solution:
def corpFlightBookings(self, bookings: List[List[int]], n: int) -> List[int]:
nums = [0]*n
df = Difference(nums)
for booking in bookings:
i = booking[0] - 1
j = booking[1] - 1
val = booking[2]
df.increment(i,j,val)
return df.result()
# 官方题解,简化版本
class Solution:
def corpFlightBookings(self, bookings: List[List[int]], n: int) -> List[int]:
nums = [0] * n
for left, right, inc in bookings:
nums[left - 1] += inc
if right < n:
nums[right] -= inc
for i in range(1, n):
nums[i] += nums[i - 1]
return nums
- 拼车
class Solution:
def carPooling(self, trips: List[List[int]], capacity: int) -> bool:
nums = [0]*1001
df = Difference(nums)
for trip in trips:
val = trip[0]
i = trip[1]
j = trip[2] - 1
df.increment(i,j,val)
res = df.result()
for r in res:
if r > capacity:
return False
return True
二维数组[矩阵]花式遍历
- 对角翻转
- 镜像翻转
- 顺时针90°
- 逆时针90°
- 螺旋遍历