面試題——尋找矩陣中的極小值

AcWing 1452 尋找矩陣的極小值

題目

給定一個n×n的矩陣,矩陣中包含n×n個_互不相同_的整數。

定義極小值:如果一個數的值比與它相鄰的所有數字的值都小,則這個數值就被稱爲極小值。

一個數的相鄰數字是指其上下左右四個方向相鄰的四個數字,另外注意,處於邊界或角落的數的相鄰數字可能少於四個。

要求在O(nlogn)的時間複雜度之內找出任意一個極小值的位置,並輸出它在第幾行第幾列。

本題中矩陣是隱藏的,你可以通過我們預設的int函數query來獲得矩陣中某個位置的數值是多少。

例如,query(a,b)即可獲得矩陣中第a行第b列的位置的數值。

注意:

  1. 矩陣的行和列均從0開始編號。
  2. query()函數的調用次數不能超過(n+2)×⌈log2n⌉+n
  3. 答案不唯一,輸出任意一個極小值的位置即可。

數據範圍

1 ≤ n ≤ 300,矩陣中的整數在int範圍內。

輸入樣例:

[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

輸出樣例:

[0, 0]

思路

​ 這道題我們通過二分的思想解決,我們假設一個如下5 * 5的矩陣

1  2  3  4  5
6  7  8  9  10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

​ 肉眼可見,我們直接就可以看出本矩陣的極小值是1,但是我們怎麼實現合格問題呢?

​ 我們先從中間列也就是第2列將矩陣分爲兩部分,左和右,之後我們從中間列從上到下第一個元素開始遍歷中間列,找到中間列的最小值,可以看到,最小值是3,隨後我們對比3的左右元素,如果這時3的左右元素都> 3,那很幸運,3就是矩陣的極小值,如果3的左右元素有< 3的,那麼我們只需要再次二分這半部分矩陣即可,因爲這半部分矩陣中,一定存在極小值

​ 系統給我們提供了query(x, y)函數來獲取矩陣中(x, y)位置的元素,但是有使用次數限制,這裏的限制證明過程過於繁瑣,我們只需要儘量降低query(x, y)函數的使用次數即可

​ 最後經過不斷二分操作,矩陣一定只剩下一列,這時我們只需要取這一列的最小值即可,這個值便是整個矩陣的極小值!代碼如下:

代碼

class Solution {
public:
	vector<int> getMinimumValue(int n) {
		long INF = 1e15;
		int l = 0, r = n - 1;
		int k;
		while (l < r) {
			int mid = (l + r) / 2;
			long min = INF;
			for (int i = 0; i < n; ++i) {
			    int val = query(i, mid);
				if (min >= val) {
					min = val;
					k = i;
				}
			}
			long left = mid ? query(k, mid - 1) : INF;
			long right = (mid + 1) < n ? query(k, mid + 1) : INF;
			if (left > min && right > min)
				return{ k, mid };
			if (left < min)
				r = mid - 1;
			else
				l = mid + 1;
		}
		long min = INF;
		for (int i = 0; i < n; i++) {
		    int val = query(i, r);
			if (min > val) {
				min = val;
				k = i;
			}
		}
		return { k, r };
	}
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章