算法题目1

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. 题目分析

审题时注意三个要点:

  1. 矩阵中仅包含0和1
  2. 每一行都是排序过的
  3. 打印其中有最多的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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值