面試演算法題 尋找矩陣的極小值
阿新 • • 發佈:2022-02-11
AcWing 1452. 尋找矩陣的極小值
給定一個 n×n 的矩陣,矩陣中包含 n×n 個 互不相同 的整數。
定義極小值:如果一個數的值比與它相鄰的所有數字的值都小,則這個數值就被稱為極小值。
一個數的相鄰數字是指其上下左右四個方向相鄰的四個數字,另外注意,處於邊界或角落的數的相鄰數字可能少於四個。
要求在 O(nlogn) 的時間複雜度之內找出任意一個極小值的位置,並輸出它在第幾行第幾列。
本題中矩陣是隱藏的,你可以通過我們預設的 int 函式 query 來獲得矩陣中某個位置的數值是多少。
例如,query(a,b) 即可獲得矩陣中第 a 行第 b 列的位置的數值。
注意:
矩陣的行和列均從 0 開始編號。
query()函式的呼叫次數不能超過 (n+2)×⌈log2n⌉+n。
答案不唯一,輸出任意一個極小值的位置即可。
資料範圍
1≤n≤300,矩陣中的整數在int範圍內。
輸入樣例:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
輸出樣例:
[0, 0]
程式碼
// Forward declaration of queryAPI. // int query(int x, int y); // return int means matrix[x][y]. //不能行列二分,行列二分的答案不一定正確 // 主要思想是用二分的方法進行列查詢,對每列找到最小值,判單這個最小值左右兩個數是否能讓該數滿足矩陣極小值,如果不能排除掉一半的列 class Solution { public: vector<int> getMinimumValue(int n) { typedef long long LL; const LL INF = 1e15; int l = 0, r = n -1; while (l < r){ int mid = l + r >> 1;//去mid列 int k;//記錄列裡面最小值的位置 LL val = INF;//取最小值過程中可能會爆int, 取LL //查詢列裡面最小值 for (int i = 0; i < n; i ++){ int t = query(i,mid); if(t < val){ val = t; k = i; } } LL left = mid ? query(k, mid -1) :INF;// 特判下mid是不是邊界 LL right = mid + 1 < n ? query(k, mid + 1):INF; // 進行mid判斷,可以篩掉一半的列 if(val < left && val < right) return {k,mid}; if(left < val) r = mid - 1; else l = mid + 1; } //得到最後r==l ,找該列中最小值即符合條件 int k; LL val = INF; for (int i = 0; i < n; i ++){ int t = query(i, r); if(t < val){ val = t; k = i; } } return {k,r}; } };