LeetCodeDiary

A Diary for solving LeetCode problems

View on GitHub

1337. 矩阵中战斗力最弱的 K 行

给你一个大小为 m * n 的矩阵 mat,矩阵由若干军人和平民组成,分别用 1 和 0 表示。

请你返回矩阵中战斗力最弱的 k 行的索引,按从最弱到最强排序。

如果第 i 行的军人数量少于第 j 行,或者两行军人数量相同但 i 小于 j,那么我们认为第 i 行的战斗力比第 j 行弱。

军人 总是 排在一行中的靠前位置,也就是说 1 总是出现在 0 之前。

示例 1:

输入:mat = 
[[1,1,0,0,0],
 [1,1,1,1,0],
 [1,0,0,0,0],
 [1,1,0,0,0],
 [1,1,1,1,1]], 
k = 3
输出:[2,0,3]
解释:
每行中的军人数目:
行 0 -> 2 
行 1 -> 4 
行 2 -> 1 
行 3 -> 2 
行 4 -> 5 
从最弱到最强对这些行排序后得到 [2,0,3,1,4]

示例 2:

输入:mat = 
[[1,0,0,0],
 [1,1,1,1],
 [1,0,0,0],
 [1,0,0,0]], 
k = 2
输出:[0,2]
解释: 
每行中的军人数目:
行 0 -> 1 
行 1 -> 4 
行 2 -> 1 
行 3 -> 1 
从最弱到最强对这些行排序后得到 [0,2,3,1]

提示:

数组 二分 堆 简单

代码

1. 求和排序

class Solution:
    def kWeakestRows(self, mat: List[List[int]], k: int) -> List[int]:
        rows = [ (sum(r), i) for i, r in enumerate(mat)]
        rows.sort(key=lambda k:(k[0],k[1]))
        return [r[1] for r in rows[:k]]

2. 二分查找+堆

class Solution:
    def kWeakestRows(self, mat: List[List[int]], k: int) -> List[int]:
        m, n = len(mat), len(mat[0])
        q = []
        for i in range(m):
            l, r = 0, n - 1
            while l < r:
                mid = l + r + 1 >> 1
                if mat[i][mid]:
                    l = mid
                else:
                    r = mid - 1
            cur = r + 1 if mat[i][r] else r
            if len(q) == k and -q[0][0] > cur:
                heapq.heappop(q)
            if len(q) < k:
                heapq.heappush(q, (-cur, -i))
        ans = [0] * k
        idx = k - 1
        while q:
            ans[idx] = -heapq.heappop(q)[1]
            idx -= 1
        return ans