通过将任何一个“ 0”替换为“ 1”来查找二进制数组中最长的“ 1”序列

时间:2018-10-01 10:08:52

标签: algorithm data-structures

我有一个仅由0和1组成的数组。任务是找到0的索引,将其替换为1会导致给定数组的最长序列。 解决方案必须在 O(n)时间和 O(1)空间内工作。

例如:

阵列-011101101001    
答案-4(产生0111 1 1101001)

“我的方法”给我的结果优于O(n2),但在长字符串输入上超时。

int findIndex(int[] a){

    int maxlength = 0; int maxIndex= -1;
    int n=a.length;
    int i=0; 
    while(true){

        if( a[i] == 0 ){
            int leftLenght=0;
            int j=i-1;
            //finding count of 1s to left of this zero
            while(j>=0){
                if(a[j]!=1){
                    break;
                }
                leftLenght++;
                j--;
            }

            int rightLenght=0;
            j=i+1;
            // finding count of 1s to right of this zero
            while(j<n){
                if(a[j]!=1){
                    break;
                }
                rightLenght++;
                j++;
            }

            if(maxlength < leftLenght+rightLenght + 1){
                maxlength = leftLenght+rightLenght + 1;
                maxIndex = i;
            }
        }
        if(i == n-1){
            break;
        }
        i++;
    }
    return maxIndex;
}

3 个答案:

答案 0 :(得分:2)

这种方法很简单,您只需要在遍历数组时维护两个数字,一个连续块的当前计数和一个连续的块(由零分隔)的当前计数即可。

注意:此解决方案假定数组中至少有一个零,否则将返回-1

int cal(int[]data){
    int last = 0;
    int cur = 0;
    int max = 0; 
    int start = -1; 
    int index = -1;
    for(int i = 0; i < data.length; i++){
        if(data[i] == 0){
           if(max < 1 + last + cur){
              max = 1 + last + cur;
              if(start != -1){
                index = start;
              }else{
                index = i;
              }
           }
           last = cur;
           start = i;
           cur = 0;  
        }else{
            cur++;
        }
    }
    if(cur != 0 && start != -1){
       if(max < 1 + last + cur){
          return start;
       }
    }     
    return index;
}

O(n)时间,O(1)空间

实时演示:https://ideone.com/1hjS25

答案 1 :(得分:1)

我相信可以通过仅维护一个变量来解决该问题,该变量存储到达0之前看到的1的最后一个轨迹。

int last_trail = 0;
int cur_trail = 0;
int last_seen = -1;
int ans = 0, maxVal = 0;
for(int i = 0; i < a.size(); i++) {
    if(a[i] == '0') {
        if(cur_trail + last_trail + 1 >  maxVal) {
            maxVal = cur_trail + last_trail + 1;
            ans = last_seen;
        }
        last_trail = cur_trail;
        cur_trail = 0;
        last_seen = i; 
    } else {
        cur_trail++;
    }
}
if(cur_trail + last_trail + 1 >  maxVal && last_seen > -1) {
    maxVal = cur_trail + last_trail + 1;
    ans = last_seen;
}

答案 2 :(得分:0)

这可以通过一种称为two pointers的技术来解决。大多数两指针使用O(1)空间和O(n)时间。

代码:https://www.ideone.com/N8bznU

#include <iostream>
#include <string>
using namespace std;


int findOptimal(string &s) {
    s += '0'; // add a sentinel 0
    int best_zero = -1;
    int prev_zero = -1;
    int zeros_in_interval = 0;
    int start = 0;
    int best_answer = -1;
    for(int i = 0; i < (int)s.length(); ++i) {
        if(s[i] == '1') continue;
        else if(s[i] == '0' and  zeros_in_interval == 0) {
            zeros_in_interval++;
            prev_zero = i;
        }
        else if(s[i] == '0' and zeros_in_interval == 1) {
            int curr_answer =  i - start; // [start, i) only contains one 0
            cout << "tried this : [" << s.substr(start, i - start) << "]\n";
            if(curr_answer > best_answer) {
                best_answer = curr_answer;
                best_zero = prev_zero;
            }
            start = prev_zero + 1;
            prev_zero = i;
        }
    }
    cout << "Answer = " << best_zero << endl;
    return best_zero;
}
int main() {
    string input = "011101101001";
    findOptimal(input);
    return 0;
}

这是C ++中的实现。输出看起来像这样:

tried this : [0111]
tried this : [111011]
tried this : [1101]
tried this : [10]
tried this : [01]
Answer = 4