[Leetcode Weekly Contest]176

链接:LeetCode

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

给一个\(m * n\)的矩阵 grid,矩阵中的元素无论是按行还是按列,都以非递增顺序排列。 
请你统计并返回 grid 中 负数 的数目。
示例 1:

输入:grid = \([[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]]\)
输出:8
解释:矩阵中共有 8 个负数。

因为是非递增顺序排列,所以最小的数在矩阵左下角,每次跟矩阵左下角进行比较即可,时间复杂度\(O(m+n)\)

class Solution:
    def countNegatives(self, grid: List[List[int]]) -> int:
        m, n = len(grid), len(grid[0])
        r, c, cnt = m - 1, 0, 0
        while r >= 0 and c < n:
            if grid[r][c] < 0:
                cnt += n - c
                r -= 1
            else:
                c += 1
        return cnt

[Leetcode]5341. 最后 K 个数的乘积

实现一个「数字乘积类」ProductOfNumbers,要求支持下述两种方法:
1. add(int num)

将数字 num 添加到当前数字列表的最后面。
2. getProduct(int k)

返回当前数字列表中,最后\(k\)个数字的乘积。
你可以假设当前列表中始终 至少 包含\(k\)个数字。
题目数据保证:任何时候,任一连续数字序列的乘积都在 32-bit 整数范围内,不会溢出。

类似于在数组中寻找K个数的和,我们可以先求出从开始位到每一位的总积,然后用总积除以从开始位到最后k-1位的总积,即可。但有一种特殊情况就是出现了0,当出现0的时候,后面每一个位置的总积都是0,无法用这种方法,这个时候我们将数组清零即可,当判断最后\(k\)个数字的乘积,如果数组个数小于K个,则说明之前是出现了0。这也是最简单的一种判别方法了。

class ProductOfNumbers:

    def __init__(self):
        self.products = []

    def add(self, num: int) -> None:
        if not num:
            self.products = []
        else:
            if not self.products:
                self.products.append(num)
            else:
                self.products.append(self.products[-1]*num)
        
    def getProduct(self, k: int) -> int:
        if k>len(self.products):
            return 0
        if k == len(self.products):
            return self.products[-1]
        n = len(self.products)
        return self.products[-1]//self.products[n-k-1]

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

给你一个数组 events,其中\(events[i] = [startDayi, endDayi]\),表示会议\(i\)开始于 \(startDay_i\),结束于\(endDay_i\)
你可以在满足\(startDay_i <= d <= endDay_i\)中的任意一天\(d\)参加会议\(i\)。注意,一天只能参加一个会议。
请你返回你可以参加的最大会议数目。

输入:events = \([[1,2],[2,3],[3,4]]\)
输出:3
解释:你可以参加所有的三个会议。
安排会议的一种方案如上图。
第 1 天参加第一个会议。
第 2 天参加第二个会议。
第 3 天参加第三个会议。

这实际是一道考验贪婪法求解的题目。首先,我们很明确一个事情,就是给定一个event,如果我要参加其会议,当然是越早越好,这可以给后面的会议让出时间,所以选择不是问题,而问题在于排序。怎么明确,先参加哪个会议呢?
答案是\(endDay_i\)最小的那个。假设我们先将\(endDay_i\)排序,那么对于\(endDay_i\)最小的那个会议,我选择其\(startDay_i\)一天参加会议不会影响后面的会议的选择。想想反证法:假设我们占用了任何一个其他会议\(event_j\)的时间,最佳的选择应该是会议\(event_j\)\(startDay_i\),而会议\(event_i\)在其他时间,那么这种情况对于\(event_i\)\(endDay_i<=endDay_j\),所以无论会议
\(event_i\)选在哪个时间,\(event_j\)也可以选择那个时间。这说明,我们选任何一个其他会议\(event_j\)的情况,都能在先选\(event_i\)的策略中找到一样的,即选择\(endDay_i\)最小的那个会议先参加,其最大会议数目大于等于先参加其他任何会议。
接下来,我们用一个集合set来存储我们参加会议的时间即可。

class Solution:
    def maxEvents(self, events: List[List[int]]) -> int:
        if not events or not events[0]:
            return 0
        events = sorted(events, key=lambda x: x[1])
        visited = set()
        for s, e in events:
            for t in range(s, e+1):
                if t not in visited:
                    visited.add(t)
                    break
        return len(visited)

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

给你一个整数数组 target 。一开始,你有一个数组 A ,它的所有元素均为 1 ,你可以执行以下操作:

令 x 为你数组里所有元素的和
选择满足 0 <= i < target.size 的任意下标 i ,并让 A 数组里下标为 i 处的值为 x 。
你可以重复该过程任意次
如果能从 A 开始构造出目标数组 target ,请你返回 True ,否则返回 False 。

示例 1:
输入:\(target = [9,3,5]\)
输出:true
解释:从 \([1, 1, 1]\) 开始
\([1, 1, 1]\), 和为 3 ,选择下标 1
\([1, 3, 1]\), 和为 5, 选择下标 2
\([1, 3, 5]\), 和为 9, 选择下标 0
\([9, 3, 5]\) 完成

这是一道贪婪+堆的题目。
首先,我们先看看例子,对于\(target = [9,3,5]\),虽然我们不知道\([1, 1, 1]\)怎么开始求和构成成如此数组,但显然最后一层构造所替换掉的元素,必然是数组中的最大值,也就是9。接下来,我们要逆向思考,9之前替换的数字是什么呢?根据规则,我们知道,9,即x等于3加5加本来的元素,所以本来的元素是\(1\),那么此时,\(target = [1,3,5]\),接下来,我们再按照这种方式求最大值原来的值是多少,并进行替换即可。
这里比较高效的方法是大顶堆,在每次进行\(pop\)的时候,提取出数组最大值,然后把替换前的数\(push\)进去,这里有两个技巧:
1.因为是大顶堆,python默认的 heapq是小顶堆,所以我们放入的时候取负数即可。
2.如果我们计算出的替换出的数<1,那么说明这是无法从\([1, 1, 1]\) 开始构造而成的,返回False即可。

class Solution:
    def isPossible(self, target: List[int]) -> bool:
        total=sum(target)
        target=[-x for x in target]
        heapq.heapify(target)
        while target:
            curMax=-heapq.heappop(target)
            if curMax==1:
                return len(target)==0 or max(target)==-1
            total-=curMax
            next_sum=curMax-total
            total+=next_sum
            if next_sum < 1:
                return False
            heapq.heappush(target,-next_sum)
posted @ 2020-02-16 20:21  Jamest  阅读(212)  评论(0编辑  收藏  举报