1. 程式人生 > 其它 >力扣1337(java&python)-矩陣中戰鬥力最弱的 K 行(簡單)

力扣1337(java&python)-矩陣中戰鬥力最弱的 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]
 

提示:

  • m == mat.length
  • n == mat[i].length
  • 2 <= n, m <= 100
  • 1 <= k <= m
  • matrix[i][j] 不是 0 就是 1

來源:力扣(LeetCode)
連結:https://leetcode.cn/problems/the-k-weakest-rows-in-a-matrix
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

解題思路:

根據題目中的意思:軍人總是排在一行中的靠前位置,1 總是出現在 0 之前,且二維矩陣中不是0就是1。就可以用二分查詢,找出一行中最後一個1 的位置,設定位置的初始值pos為-1,則得知最後一個1的位置後,這一行1的個數就為pos+1。

二分查詢的細節:

  • 設定left = 0, right = col - 1, pos = -1, mid = left + (right - left + 1) / 2;
  • 迴圈的條件是:left < right;
  • 如果 mat[i][mid] == 0,則說明mid右邊的數都為0,需要移動right到mid-1,搜尋範圍為[left, mid -1];
  • 如果 mat[i][mid] == 1,則說明mid左邊的數都為1,但是mid也有可能是最後一個1的位置,故將 left 移動到 mid,搜尋範圍為[mid, right](所以mid需要向上取整);
  • 迴圈結束後:left == right,需要判斷left處的值是否為1,為1則pos = left,否則pos還是迴圈中的pos。

得到每一行的戰鬥力後,可以將每一行的戰鬥力和其索引放入到一個小跟堆裡面,但是當戰鬥力相同時,索引較小的更弱,故需要在小根堆中存放戰鬥力和索引的二元組。

java程式碼(left < right):

 1 class Solution {
 2     public int[] kWeakestRows(int[][] mat, int k) {
 3         int row = mat.length, col = mat[0].length;
 4         //建立一個小跟堆
 5         PriorityQueue<int[]> queue = new PriorityQueue<>((x1, x2) -> {
 6             //如果兩行個數不相同,就按照個數升序
 7             if (x1[0] != x2[0]){
 8                return x1[0] - x2[0];
 9             } else {
10                 //如果兩行個數相同,就按照行索引升序
11                return x1[1] - x2[1];
12             }
13         });
14         //二分查詢,找到每行1的個數
15         for (int i = 0; i < row; i++){
16             int pos = -1;
17             int left = 0, right = col - 1;
18             while (left < right){
19                 int mid = left + (right - left + 1) / 2;
20                 if (mat[i][mid] == 0){
21                     right = mid - 1;
22                 }else {
23                     left = mid;
24                     //更新pos的位置
25                     pos = mid;
26                 }
27             }
28             pos = mat[i][left] == 1 ? left : pos;
29             //pos+1:pos為位置,pos+1就為長度
30             queue.offer(new int[]{pos+1, i});
31         }
32         int[] res = new int[k];
33         for (int l = 0; l < k; l++){
34             res[l] = queue.poll()[1];
35         }
36         return res;
37     }
38 }

 python3程式碼(left <= right):

 1 class Solution:
 2     def kWeakestRows(self, mat: List[List[int]], k: int) -> List[int]:
 3         row, col = len(mat), len(mat[0])
 4         power = list()
 5         for i in range(row):
 6             left, right, pos = 0, col-1, -1
 7             while left <= right:
 8                 mid = left + (right - left) // 2
 9                 if mat[i][mid] == 0:
10                     right = mid - 1
11                 else:
12                     left = mid + 1
13                     pos = mid
14             power.append((pos+1, i))
15         # 將列表轉換為堆
16         heapq.heapify(power)
17         res = list()
18         for i in range(k):
19             res.append(heapq.heappop(power)[1])
20         return res

 小知識:

1.java使用優先佇列實現大頂堆和小頂堆,預設是小根堆,當然記不住預設也沒有關係

小根堆建立:

 PriorityQueue<Integer> minHeap = new PriorityQueue<>(k,(a,b) -> a-b);

大跟堆建立:

PriorityQueue<Integer> maxHeap = new PriorityQueue<>(k,(a,b) -> b-a);

其中構造器中的k表示建立堆的大小,之後用Lambda表示式快速實現自定義排序。

2.heapq堆的常用方法:

  • heapq.heapify(list): 將列表轉換為堆
  • heapq.heappush(heap, itme):heap為定義堆,item增加的元素
  • heapq.heappop(heap):刪除並返回最小值,因為堆的特徵是heap[0]永遠是最小的元素,所以一般都是刪除第一個元素
  • heapq.heapreplace(heap.item) :刪除並返回最小元素值,新增新的元素值
  • heap.heappushpop(list, itme):判斷新增元素值與堆的第一個元素值對比;如果大,則刪除並返回第一個元素,然後新增新元素值item;如果小,則返回item,原堆不變
  • heap.nlargest(n, heap):查詢堆中的最大n個元素
  • heap.nsmallest(n, heap):查詢堆中的最小n個元素