LeetCode-【差分解决区间问题】解题技巧

1094. 拼车

此题关键在于:上车下车先后是固定的, 那么可以用差分法,在特定车站上车就+人数, 下车就-人数,那么计算, 如果出现 > capacity 就是false;

1.所有车站人数初始化为0;

2.遍历trips,依次维护上下车各车站人数变化;

3.遍历所有车站,累加各个车站人数,出现> > capacity 就是false,否则返回true;

class Solution(object):
    def carPooling(self, trips, capacity):
        """
        :type trips: List[List[int]]
        :type capacity: int
        :rtype: bool
        """
        diff = [0]*1002
        for n,i,j in trips:
            diff[i]+=n
            diff[j]-=n
        curr = 0
        for i in range(1001):
            curr+=diff[i]
            if capacity < curr:
                return False
        return True

1109. 航班预订统计

此题关键在于:此题与上体类似,航班只上座,变化点在于起始航班上座数,所以只需要依次累加就行,所求即为各个航班总上座数。

备注:注意边界条件;

class Solution(object):
    def corpFlightBookings(self, bookings, n):
        """
        :type bookings: List[List[int]]
        :type n: int
        :rtype: List[int]
        """
        diff = [0]*(n+2)
        for f,l,s in bookings:
            diff[f] += s
            diff[l+1] -= s
        ret = []
        curr = 0
        for i in diff[1:-1]:
            curr+=i
            ret.append(curr)
        return ret

5767. 检查是否区域内所有整数都被覆盖

此题关键在于:先对各个区间进行预处理,区间开始时+1,区间结束时-1,然后遍历所有区间,在区间内且累加和小于等于0,则表明没有覆盖到。

备注:注意边界条件。

class Solution(object):
    def isCovered(self, ranges, left, right):
        """
        :type ranges: List[List[int]]
        :type left: int
        :type right: int
        :rtype: bool
        """
        diff = [0]*52
        for i,j in ranges:
            diff[i]+=1
            diff[j+1]-=1
        curr = 0
        for i in range(1,51):
            curr+=diff[i]
            if i>=left and i<=right and curr<=0:
                return False
        return True

370. 区间加法

class Solution(object):
    def getModifiedArray(self, length, updates):
        """
        :type length: int
        :type updates: List[List[int]]
        :rtype: List[int]
        """
        diff = [0]*(length+1)
        for i,j,v in updates:
            diff[i]+=v
            diff[j+1]-=v
        ret = []
        curr = 0
        for i in range(length):
            curr+=diff[i]
            ret.append(curr)
        return ret

1854. 人口最多的年份

class Solution(object):
    def maximumPopulation(self, logs):
        """
        :type logs: List[List[int]]
        :rtype: int
        """
        diff = [0]*2051
        for begin,end in logs:
            diff[begin]+=1
            diff[end]-=1
        max_ = 0
        curr = 0
        ret = 0
        for i in range(1950,2051):
            curr+=diff[i]
            if curr>max_:
                max_=curr
                ret = i
        return ret

732. 我的日程安排表 III

class MyCalendarThree:

    def __init__(self):
        self.dict_ = {}


    def book(self, start: int, end: int) -> int:
        self.dict_[start] = self.dict_.get(start,0)+1
        self.dict_[end] = self.dict_.get(end,0)-1

        ret = 0
        curr = 0
        for i in sorted(self.dict_):
            curr += self.dict_[i]
            ret = max(ret,curr)
        return ret


# Your MyCalendarThree object will be instantiated and called as such:
# obj = MyCalendarThree()
# param_1 = obj.book(start,end)

2145. 统计隐藏数组数目

class Solution:
    def numberOfArrays(self, differences: List[int], lower: int, upper: int) -> int:
        L = len(differences)
        prenum = [0]
        min_ = 0
        max_ = 0
        for i in range(L):
            prenum.append(prenum[-1]+differences[i])
            min_ = min(min_,prenum[-1])
            max_ = max(max_,prenum[-1])
        # 先得到min_提高到lower所需的差值,将差值加到max_,然后计算max_到upper的差值
        # 如果max_差值大于upper,说明溢出区间了;否则不然计算出来的就是实际数量
        ret = upper-(lower-min_+max_)+1
        if ret<0:
            return 0
        return ret

6158. 字母移位 II

超时版本,未使用差分:

class Solution:
    def shiftingLetters(self, s: str, shifts: List[List[int]]) -> str:
        L = len(s)
        arr = [0]*L
        for b,e,d in shifts:
            t = 1
            if d == 0:
                t=-1
            for i in range(b,e+1):
                arr[i]+=t
        ret = ""
        for i,v in enumerate(arr):
            v%=26
            if (v >= 0 and ord(s[i]) + v <= ord('z')) or (v<0 and ord(s[i])-ord('a')+v>=0):
                ret+=chr(ord(s[i])+v)
            elif (v<0 and ord(s[i])-ord('a')+v<0):
                ret+=chr(ord(s[i])+26+v)
            elif (v >= 0 and ord(s[i]) + v > ord('z')):
                ret+=chr(ord(s[i])-26+v)
        return ret

差分版本,可以对比理解下差分的巧妙之处:

class Solution:
    def shiftingLetters(self, s: str, shifts: List[List[int]]) -> str:
        L = len(s)
        arr = [0]*(L+1)
        for b,e,d in shifts:
            t = 1
            if d == 0:
                t=-1
            arr[b] += t
            arr[e+1] -= t
        ret = ""
        v = 0
        for i in range(L):
            v+=arr[i]
            v%=26
            if (v >= 0 and ord(s[i]) + v <= ord('z')) or (v<0 and ord(s[i])-ord('a')+v>=0):
                ret+=chr(ord(s[i])+v)
            elif (v<0 and ord(s[i])-ord('a')+v<0):
                ret+=chr(ord(s[i])+26+v)
            elif (v >= 0 and ord(s[i]) + v > ord('z')):
                ret+=chr(ord(s[i])-26+v)
        return ret

2406. 将区间分为最少组数

class Solution:
    def minGroups(self, intervals: List[List[int]]) -> int:
        ret = 0
        N = 10**6+2
        arr = [0]*N
        for i in intervals:
            arr[i[0]]+=1
            arr[i[1]+1]-=1
        for i in range(1,N):
            arr[i]+=arr[i-1]
            ret=max(ret,arr[i])
        return ret

2536. 子矩阵元素加 1

class Solution:
    def rangeAddQueries(self, n: int, queries: List[List[int]]) -> List[List[int]]:
        grid = []
        pre = []
        for i in range(n):
            grid.append([0]*n)
        for i in range(n+1):
            pre.append([0]*(n+1))
        for q in queries:
            pre[q[0]][q[1]]+=1
            pre[q[0]][q[3]+1]-=1
            pre[q[2]+1][q[1]]-=1
            pre[q[2]+1][q[3]+1]+=1
        for r in range(n):
            for c in range(1,n):
                pre[r][c]+=pre[r][c-1]
        for r in range(1,n):
            for c in range(n):
                pre[r][c]+=pre[r-1][c]
        for r in range(n):
            for c in range(n):
                grid[r][c] = pre[r][c]
        return grid

你可能感兴趣的:(LeetCode,差分法,leetcode,算法)