1. 题目描述
Given a matrix with only 0 and 1, and every row sorted, e.g.
M and N rows
0 0 0 0 1 1 1
0 0 0 1 1 1 1
0 0 0 0 0 1 1
0 0 0 0 0 0 1
Print which rows have most 1s
2. 题目分析
审题时注意三个要点:
- 矩阵中仅包含0和1
- 每一行都是排序过的
- 打印其中有最多的1,可能有多行
3. 思路
1)找到行中的第一个1,那么行中的1的个数就确定了;
2)因为题目是找最多的1的行号,先前行的1的个数可作为一个界,避免每次都要遍历所有内容
给定一行的数据, 每次索引到的第一个1的idx, 会作为下次搜索的下届, 即每次做行搜索时都有一个累积的效果。
这种积累效应使遍历所有行的实质上就是等同于遍历一个行。
迭代一行内容的复杂度是O(M). 有人可能会问:如果采用二分搜索,它的复杂度难道不是O(log(M))?但它的内容是跨行的,所以不能是O(log(M))
所以它的最优算法的时间复杂度为O(N + M).
最好情况的复杂度是: O(N), 当矩阵arr[0][0]=1 或矩阵全为0时, 因为每次做行搜索只有一次check
最差情况的复杂度是?: O(M+N), 当矩阵为右下斜三角
4. 算法
#include<stdio.h>
#include<vector>
#define ROW 4
#define COLUMN 4
using namespace std;
// if move a step in row from the border(end), then we need to update the "max_1" row
// return value is an index. if index >=0, it means we need to update the result
int findMaxInRow(int arr[], int end) {
int i=end;
if (arr[i] == 0) return -1;
for (i=end-1; i >=0; i--) {
if (arr[i] == 0) return i+1;
}
// no 0 in the row, so the index is start point
return 0;
}
// function for finding row with maximum 1
void findMax(int arr[][COLUMN])
{
vector<int> results;
int end = COLUMN-1, idx = 0;
for (int i=0; i<ROW; i++) {
int *rowArr = arr[i];
idx = findMaxInRow(rowArr, end);
if (idx == -1) continue;
if (idx == end) {
results.push_back(i);
continue;
}
// move a step in a row, so we need to update
results.clear(); // previous results is unusable
results.push_back(i);
end = idx;
}
if (results.size() != 0) {
for (auto item : results) printf("%d ", item);
printf("\n");
}else {
printf("No 1 in these rows\n");
}
}
int main()
{
int arr[4][4] = {0, 0, 0, 1,
0, 0, 0, 1,
0, 1, 1, 1,
0, 1, 1, 1};
findMax(arr);
return 0;
}