leetcode 176 周赛

5340. 统计有序矩阵中的负数

题意:

统计二维矩阵中非负个数。

代码:

class Solution:
    def countNegatives(self, grid: List[List[int]]) -> int:
        ans =0
        for row in grid:
            for num in row:
                if num < 0: ans+=1
        return ans

5341. 最后 K 个数的乘积

题意:

实现一个类两个函数,对一个数组具有两个操作:

  • 在一个数组末尾添加元素
  • 求数组末尾k个元素的乘积

思路:

明显第一个操作已经是O(1)没办法优化,第二个操作如果是求前k个乘积就很明显预处理出前缀和,然后O(1),同时有了前缀和pre(i)也可以O(1)求得任意区间的和 sum(i,j)

sum(i,j)= pre(j) - pre(i-1)

那么借用前缀和思想,我们在第一个操作里随便得到前缀积,那后k个乘积很容易想到乘法逆运算除法O(1)可以求得区间的积,自然后k个乘积也很容易。
mutil(i,j) = pre(j) / pre(i-1)

但要注意一个细节,插入元素为0的时候,需要特殊处理,如果问的后k个元素里面有0,直接返回0即可。

这样两个操作都是O(1)

代码:

class ProductOfNumbers:

    def __init__(self):
        self.data = [1]

    def add(self, num: int) -> None:
        if num == 0:
             self.data = [1]
        else :
            self.data.append(self.data[-1] * num)

    def getProduct(self, k: int) -> int:
        if k>= len(self.data) :
             return 0
        else : 
            return int(self.data[-1] / self.data[-1-k])

5342. 最多可以参加的会议数目

题意:

题面很清晰,就是尽量选择满足条件的区间。

思路:

明显的贪心,分析一下原则:即在当前满足条件的所有任务里,为了后面尽量选择更多一点,就是选择结束日期最早的那个任务。

具体怎么实现这个原则: 先对所有任务的起始时间排序,然后用一个最小堆的数据结构维护当前满足条件(任务起始天数小于等于当前日期)的所有任务的结束日期。

然后以日期为轴枚举每天选择满足条件里结束日期最小的任务,顺带更新一下这个最小堆

代码:

class Solution:
    def maxEvents(self, events) -> int:
        events = sorted(events, key =lambda x : x[0])
        ans = 0
        small_headp = []
        import heapq
        i ,day , n = 0 ,events[0][0], len(events)
        while True :
            while i<n and events[i][0] <= day :
                heapq.heappush(small_headp , events[i][1])
                i +=1
            while len(small_headp) >0 and small_headp[0] < day:
                heapq.heappop(small_headp)
            if len(small_headp) >0:
                ans += 1
                heapq.heappop(small_headp)
            day +=1
            if i ==n and len(small_headp) == 0: break
        return ans

5343. 多次求和构造目标数组

题意

给一个target数组,问能不能从全是[1,1,1,…,1]的数组通过重复替换某个位置的值为当前数组之和逐步变换而来。

解题思路

开始先尝试暴力广搜,TLE,然后尝试正向找一下的规律进行剪枝,正向并不能判断出每一次正确位置的规律…

但反过来:每一次选择改变的那个位置会变成当前的最大值, 也就是我们从target每次都是从最大值推过来的…于是反向递推一下就好。

然后这里找当前数组里最大值,可以用最大堆,或者bisect.insort()进行log级别优化。

leetcode 176 周赛_第1张图片

代码

heapq最小堆取相反数变成最大堆。

class Solution:
    def isPossible(self, target: List[int]) -> bool:
        import heapq
        que = []
        total = 0
        for num in target:
            heapq.heappush(que,(-num))
            total +=num
        while True:
            max_value = heapq.heappop(que)
            max_value *= -1
            if max_value == 1: return True
            total -= max_value
            max_value -= total
            total += max_value
            if max_value <=0:  return False
            heapq.heappush(que, (-max_value)) 

利用bisect.insort也可以实现了找最大值时Log的优化!

class Solution:
    def isPossible(self, target) -> bool:
        total = sum(target)
        if total == len(target) : return True
        target = sorted(target)
        while True:
            num = target.pop()
            if num == 1: return True
            total -= num
            num -= total
            if num <0 :return False
            total += num
            import bisect
            bisect.insort(target, num)

你可能感兴趣的:(每周一题(,hihocode,leetcode))