一 題目描述
在一個排序矩陣中找從小到大的第 k 個整數。
排序矩陣的定義為:每一行遞增,每一列也遞增。
二 題解
由於排序矩陣中的每一行都是遞增的,並且每一列都是遞增的。從小到大第k個數,實際上就是第k小的數。思路如下:
假設排序矩陣共有row行和col列,由於每行是遞增的,我們只要選擇出每行的最小數(一共row個)並從這row個數中選出最小的數來,重復這個過程k次,第k次選擇出的最小值就是整個矩陣中第k小的數。
代碼如下:
class Solution
{
public:
/**
* @param matrix: a matrix of integers
* @param k: An integer
* @return: the kth smallest number in the matrix
*/
int kthSmallest(vector<vector<int>> &matrix, int k)
{
size_t row = matrix.size();
size_t col = matrix[0].size();
if(row == 0 || col == 0)
return -1;
int minRows[row];//用於存儲每行的最小值對應的列數
memset(minRows,0,sizeof(minRows));//對minRows初始化,且初始值都為0
if(k > row * col)//錯誤處理
return -1;
int rs;
int tmp;
for(int cnt = 1; cnt <= k; cnt++)
{
int min_val = INT_MAX;//每次比較都需要初始化,注意該變量定義的位置
for(int row_index = 0; row_index < row; row_index++)
{
if(minRows[row_index] < col)//注意這個判斷條件一定要加上,防止越界
{
if(matrix[row_index][minRows[row_index]] < min_val)
{
min_val = matrix[row_index][minRows[row_index]];
tmp = row_index;
}
}
}
minRows[tmp]++;//更新相應行中最小值的位置,要注意此處的位置,是在row輪循環之后才能找出最小值
if(cnt == k)
rs = min_val;
}
return rs;
}
};
該算法思路表簡單,算法的時間復雜度為O(k*row),此外,有幾個需要注意的地方:
1.我們每次選擇出的最小值指的是這row個數中的最小值,所以mi_val這個變量需要在每次循環開始的時候才定義,這里我定義的是INT_MAX,所以所有的行需要遍歷一一遍。
2.在每次進行row輪循環的時候,一定不要忘記判斷,相應的值的列數的索引是否已經達到最大值。
3.注意minRows數組更新的時候是在row輪循環結束的后才進行更新。
============================================================================================================
此外,本題是從列的角度來考慮的,即每次找出一列數中的最小值來;,當然也可從行的角度來考慮,每次找出一行數中的最小值來,重復k次,第k次的最小值就是最終結果。兩種方法思想類似,利用第二種方法的話時間復雜度就變成了O(k*col)。
當列數大於行數的時候,用第一種方法比較好;而當行數大於列數的時候用第二種方法比較好,當然前提是行數和列數的差值比較大,否則兩種方法性能差不多;當然,也可以結合這兩種情況,對於行列數不同的情況時,采用不同方法。
