1. 程式人生 > 其它 >第93期-基礎結構:矩陣 統計有序矩陣中的負數

第93期-基礎結構:矩陣 統計有序矩陣中的負數

1 問題描述

統計有序矩陣中的負數 給你一個 m * n 的矩陣 grid,矩陣中的元素無論是按行還是按列,都以非遞增順序排列。
請你統計並返回 grid 中 負數 的數目。

示例 1:

輸入:grid = [[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]]
輸出:8
解釋:矩陣中共有 8 個負數。

示例 2:

輸入:grid = [[3,2],[1,0]]
輸出:0

示例 3:

輸入:grid = [[1,-1],[-1,-1]]
輸出:3

示例 4:

輸入:grid = [[-1]]
輸出:1

初始程式碼

from typing import
List class Solution: def countNegatives(self, grid: List[List[int]]) -> int: #在此之間填寫程式碼 print(Solution().countNegatives([[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]])) print(Solution().countNegatives([[3,2],[1,0]])) print(Solution().countNegatives([[1,-1],[-1,-1]])) print(Solution().countNegatives([[-1]]))
View Code

2 解題思路

  • 標籤:矩陣
  • 思路:二分查詢
  • 注意到題目中給了一個性質,即矩陣中的元素無論是按行還是按列,都以非遞增順序排列,可以考慮把這個性質利用起來
  • 遍歷矩陣的每一行
  • 二分查詢到該行從前往後的第一個負數
  • 最後的答案就是每一行負數數量之和

#3 解題方法

from typing import List
class Solution:
    def countNegatives(self, grid: List[List[int]]) -> int:
        def a(x):
            m,n=0,len(x)-1
            while
m<=n: t=(m+n)//2 if x[t]>=0:m=t+1 else:n=t-1 return len(x)-m b=0 for i in grid: b+=a(i) return b print(Solution().countNegatives([[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]])) print(Solution().countNegatives([[3,2],[1,0]])) print(Solution().countNegatives([[1,-1],[-1,-1]])) print(Solution().countNegatives([[-1]]))
View Code

第1-3,17-20行:題目中已經給出的資訊,執行程式碼時要根據這些程式碼進行編輯
第4行:建立函式a,其中變數x為列表
第5行:定義變數m,n分別為列表x兩端索引
第6行:當m<n的時候,執行迴圈
第7行:定義變數t等於m和n的中間值
第8行:若索引t對應的元素大於或等於0,則將m移向t+1的位置
第9行:若索引t對應的元素小於0,則將n移向t-1的位置
第10行:返回函式a的值為列表x的長度減去第一個負數的索引,即返回函式a負數的個數
第11-14行:定義變數b並遍歷矩陣中的所有列表,使用a函式將所有列表中負數的個數加在一起並複製給b,返回b的值

程式碼執行結果為:

#演算法講解

這裡用到了基礎演算法:二分查詢,簡單講解下這個演算法:
二分查詢法
如果要查詢的資料已經事先排好序了,就可以使用二分查詢法來進行查詢
以升序數列為例,比較一個元素與數列中的中間位置的元素的大小,如果比中間位置的元素大,則繼續在後半部分的數列中進行二分查詢;如果比中間位置的元素小,則在數列的前半部分進行比較;如果相等,則找到了元素的位置。每次比較的數列長度都會是之前數列的一半,直到找到相等元素的位置或者最終沒有找到要找的元素。
演算法複雜度
二分查詢的基本思想是將n個元素分成大致相等的兩部分,取a[n/2]與x做比較,如果x=a[n/2],則找到x,演算法中止;如果x<a[n/2],則只要在陣列a的左半部分繼續搜尋x,如果x>a[n/2],則只要在陣列a的右半部搜尋x.
時間複雜度:因為每次查詢都會比上一次少一半的範圍,最多隻需要比較log2(n)次,所以時間複雜度為O(logn)。
分析
二分查詢法必須事先進過排序,切要求所有被查資料都必須載入到記憶體中方能進行。
此法適用於不需增刪的靜態資料
發散
常見的查詢方法還有:順序查詢法、插值查詢法、斐波拉契查詢法、雜湊查詢法等,有興趣的同學可以去研究一下。