题目描述:
给定一个矩阵,包含 N * M 个整数和一个包含 K 个整数的数组。现在要求在这个矩阵中找一个宽度最小的子矩阵,要求子矩阵包含数组中所有的整数。
输入描述:
第一行输入两个正整数 N,M,表示矩阵大小;
接下来 N 行 M 列表示矩阵内容;
下一行包含一个正整数 K;
下一行包含 K 个整数,表示所需包含的数组,K 个整数可能存在重复数字;
特别注意事项:
所有输入数据小于1000。
输出描述:
输出包含一个整数,表示满足要求子矩阵的最小宽度,若找不到,输出-1。
示例1:
输入
2 5
1 2 2 3 1
2 3 2 3 2
3
1 2 3
输出
2
说明:矩阵第0列和第3列包含了1,2,3,居住第3行和第4行包含了1,2,3,所以输出是2
示例2:
输入
2 5
1 2 2 3 1
2 3 2 3 4
3
1 1 4
输出
5
说明:矩阵第1,2,3,4,5列包含了1,1,4,说以输出是5
C++源码:
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
int minSubMatrixWidth(const vector<vector<int>>& matrix, const unordered_map<int, int>& nums) {
int N = matrix.size();
int M = matrix[0].size();
int result = -1;
for (int left = 0; left < M; ++left) {
unordered_map<int, int> window;
for (int right = left; right < M; ++right) {
for (int i = 0; i < N; ++i) {
if (matrix[i][right] != 0) { // Only consider non-zero elements to match with nums
++window[matrix[i][right]];
}
}
bool allFound = true;
for (const auto& num : nums) {
if (window[num.first] < num.second) {
allFound = false;
break;
}
}
if (allFound) {
if (result == -1 || right - left + 1 < result) {
result = right - left + 1;
}
// Correct logic to shrink the window from the left
for (const auto& num : nums) {
--window[num.first]; // Decrease count of the leaving element
if (window[num.first] < num.second) {
// Restore the count since we've found the point where the condition breaks
++window[num.first];
break; // Stop shrinking as soon as any count falls below requirement
}
}
// Actual shrink after checking all required numbers
++left;
}
}
}
return result;
}
int main() {
int N, M;
cin >> N >> M;
vector<vector<int>> matrix(N, vector<int>(M));
for (int i = 0; i < N; ++i) {
for (int j = 0; j < M; ++j) {
cin >> matrix[i][j];
}
}
int K;
cin >> K;
unordered_map<int, int> nums;
for (int i = 0; i < K; ++i) {
int num;
cin >> num;
++nums[num];
}
cout << minSubMatrixWidth(matrix, nums) << endl;
system("pause");
return 0;
}