leetcode-数组-【双指针(快慢指针、左右指针)、前缀和、差分数组】

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°
  • 螺旋遍历
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值