1. 題目來源
2. 題目說明
3. 題目解析
方法一:暴力+巧妙解法
有一說一,題是好理解,但是真難做…最後 1 個多小時都在幹這個題目,還是沒能幹出來…結果暴力就能過…真的…暴力出奇跡。
這個暴力不知道穩定不,在比賽時 cpp
貌似沒過,java
可以,也都是聽大佬講的,自己想了一堆奇妙的方法,磕磕絆絆把自己繞進去了。
見題解大佬 Ikaruga【有序矩陣中的第 k 個最小數組和】抄作業。看了大佬的代碼總是能學習幾個新函數 😃。
二分 + dfs
應該是這道題很棒的解法了。
參見代碼如下:
// 執行用時 :1376 ms, 在所有 C++ 提交中擊敗了100.00%的用戶
// 內存消耗 :156.1 MB, 在所有 C++ 提交中擊敗了100.00%的用戶
class Solution {
public:
int kthSmallest(vector<vector<int>>& mat, int k) {
vector<int> ans(mat[0]);
for (int i = 1; i < mat.size(); ++i) {
multiset<int> st;
for (int x : ans) {
for (int y : mat[i]) {
st.insert(x + y);
}
}
ans.assign(st.begin(), st.end());
ans.resize(min(k, (int)ans.size()));
}
return ans.back();
}
};
作者:newbie-19
鏈接:https://leetcode-cn.com/problems/find-the-kth-smallest-sum-of-a-matrix-with-sorted-rows/solution/er-fen-by-newbie-19-3/
來源:力扣(LeetCode)
class Solution {
public:
int kthSmallest(vector<vector<int>>& mat, int k) {
int m=mat.size(),n=mat[0].size();
multiset<int>s(mat[0].begin(),mat[0].end());
for(int i=1;i<m;i++){
multiset<int>temp;
for(int x : s){
for(int y : mat[i]){
temp.insert(x+y);
}
}
s.clear();
auto it=temp.begin();
for(int j=0;j<min(k,(int)temp.size());j++,it++){
s.insert(*it);
}
}
return *s.rbegin();
}
};
方法二:優先隊列+bfs+巧妙解法
來自坑神的代碼+思路…由於數據最大爲 40 * 200 = 8000
故可選擇暴力去做。坑神一開始想精細化的去 bfs
即在優先隊列中僅保留 200 個理想狀態即可,但是確實很麻煩就改道暴力了。
有一說一,代碼沒看太懂,bfs
學的菜…人被這個題整蒙了…
參考代碼如下:
// 執行用時 :284 ms, 在所有 C++ 提交中擊敗了100.00%的用戶
// 內存消耗 :13 MB, 在所有 C++ 提交中擊敗了100.00%的用戶
const int INF = 1e9;
int n, m;
vector<vector<int>> mat;
struct Node {
int cur[41], sum = 0;
Node(){
sum = 0;
for (int i = 0; i < n; i++)
sum = sum + mat[i][cur[i] = 0];
}
Node getNext(int k){
Node ret;
for (int i = 0; i < n; i++) ret.cur[i] = cur[i];
ret.cur[k]++; ret.sum = 0;
for (int i = 0; i < n; i++) ret.sum += mat[i][ret.cur[i]];
return ret;
}
string i2s(int x){
string ret = "";
while(x){
ret += (char)(x % 10 + '0');
x /= 10;
}
return ret;
}
string getString(){
string ret = "";
for (int i = 0; i < n; i++)
ret += "#" + i2s(cur[i]);
return ret;
}
friend bool operator < (const Node &a, const Node &b){
return a.sum > b.sum;
}
};
set<string> hash_que;
priority_queue<Node> que;
class Solution {
public:
int kthSmallest(vector<vector<int>>& v, int k) {
mat = v; n = mat.size(); m = mat[0].size();
while(!que.empty()) que.pop();
que.push(Node()); hash_que.clear();
int cnt = 0;
while(!que.empty()){
Node x = que.top(); que.pop();
if (hash_que.insert(x.getString()).second){
++cnt;
if (cnt == k) return x.sum;
for (int i = 0; i < n; i++)
if (x.cur[i] + 1 < m) que.push(x.getNext(i));
}
}
return 0;
}
};
方法三:二分+dfs+巧妙解
依舊見題解大佬 Ikaruga【有序矩陣中的第 k 個最小數組和】抄作業。
大佬解釋原圖:
class Solution {
public:
int kthSmallest(vector<vector<int>>& mat, int k) {
int l = 0;
int r = 0;
for (int i = 0; i < mat.size(); i++) {
l += mat[i].front();
r += mat[i].back();
}
int base = l;
while (l < r) {
int mid = l + (r - l) / 2;
int cnt = 1;
dfs(mat, k, mid, 0, base, cnt);
if (cnt < k) {
l = mid + 1;
}
else {
r = mid;
}
}
return r;
}
void dfs(vector<vector<int>>& mat, int k, int maxSum, int idx, int sum, int& cnt) {
if (idx == mat.size()) return;
if (sum > maxSum || cnt > k) return;
dfs(mat, k, maxSum, idx + 1, sum, cnt);
for (int j = 1; j < mat[idx].size(); j++) {
int temp = sum + mat[idx][j] - mat[idx][0];
if (temp > maxSum) break;
cnt++;
dfs(mat, k, maxSum, idx + 1, temp, cnt);
}
}
};
作者:newbie-19
鏈接:https://leetcode-cn.com/problems/find-the-kth-smallest-sum-of-a-matrix-with-sorted-rows/solution/er-fen-by-newbie-19-3/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
class Solution {
public:
vector<vector<int>>temp;
int m,n;
int kthSmallest(vector<vector<int>>& mat, int k) {
temp=mat;
m=mat.size(),n=mat[0].size();
int left=0,right=0;
for(int i=0;i<m;i++) left+=mat[i][0],right+=mat[i].back();
int init=left;
while(left<right){
int mid=(left+right)>>1;
int num=1;
dfs(mid,0,init,num,k);
if(num>=k) right=mid;
else left=mid+1;
}
return left;
}
void dfs(int mid,int index,int sum,int& num,int k){
if(sum>mid||index==m||num>k) return;
dfs(mid,index+1,sum,num,k);
for(int i=1;i<n;i++){
if(sum+temp[index][i]-temp[index][0]<=mid){
num++;
dfs(mid,index+1,sum+temp[index][i]-temp[index][0],num,k);
}else{
break;
}
}
}
};