## Zeros And Ones

### October 17, 2017

Our windowing algorithm scans the array from left to right. Indices lo and hi point to the beginning and end of a subsequence of an array that contains a single zero. As we scan, if the new array element causes us to have two zeros in the subsequence (count = 2) we reset the window. prev2 and prev1 are the indices of the two most recent zeros. The maximum is reset whenever the window becomes larger than the current maximum. Here’s the code:

```(define (zero xs)
(let ((max-count 0) (max-index -1) (prev2 -1) (prev1 -1) (count 0) (lo 0))
(do ((hi 0 (+ hi 1)) (xs xs (cdr xs))) ((null? xs) max-index)
(when (zero? (car xs)) (set! prev2 prev1) (set! prev1 hi) (set! count (+ count 1)))
(when (= count 2) (set! lo (+ prev2 1)) (set! count 1))
(when (< max-count (- hi lo -1)) (set! max-count (- hi lo -1)) (set! max-index prev1)))))```

And here are two examples:

```> (zero '(1 0 1 1 1 0 1 1 1 1 0 1 1 1 1 0 0 1 1))
10
> (zero '(0 0 1 0 1 1 1 0 1 1))
7```

Our algorithm takes O(n) time and O(1) space. You can run the program at https://ideone.com/PaCY31.

Pages: 1 2

### 10 Responses to “Zeros And Ones”

1. Daniel said

Here’s a solution in C99. The algorithm is O(n) time, O(1) space. It considers sub arrays have three zeros, one on each end. It returns the second zero of the longest such sub array. For the algorithm to work properly, indices -1 and n are treated as if there were zeros there.

```/* zeros_and_ones.c */

#include <stdio.h>

int replace_idx(int* array, int n) {
int idx0 = -1;
int idx1 = -1;
int idx2 = -1;
int max_length = 0;
int max_idx = -1;
for (int i = 0; i <= n; ++i) {
int val = 0;
if (i != n) val = array[i];
if (val == 0) {
idx0 = idx1;
idx1 = idx2;
idx2 = i;
int length = idx2 - idx0 - 1;
if (length > max_length) {
max_length = length;
max_idx = idx1;
}
}
}
return max_idx;
}

int main(int argc, char* argv[]) {
int array[] = {1,0,1,1,1,0,1,1,1,1,0,1,1,1,1,0,0,1,1};
int n = sizeof(array) / sizeof(int);
printf("%d\n", replace_idx(array, n));
}
```

Output:

```\$ c99 -g -Wall -o zeros_and_ones zeros_and_ones.c
\$ ./zeros_and_ones
```
```10
```
2. Daniel said

Clarification: It considers sub arrays that have three zeros, with one of the zeros at the beginning and one of the zeros at the end.

3. Daniel said

Clarification: It returns the index of the second zero of the longest such sub array (index with respect to the entire input array).

4. Himanshu said

How do we know the number of total characters that is 1 and 0 the array contains?

5. isaac said

here is another solution in c

```#include <stdio.h>

int main() {

int d[] = {1,0,1,1,1,0,1,1,1,1,0,1,1,1,1,0,0,1,1};
int d_size = sizeof(d)/sizeof(int);
int i = 0;
int best_zero_index = -1;   //holds the answer
int prev_zero_index = -1;   //holds previous zero index
int post_zero_streak = 0;   //number of ones after a zero
int pre_zero_streak = 0;    //number of ones before a zero
int max_ones_streak = 0;    //holds maximum ones streak length

for(i = 0; i <= d_size; i++) {  //from 0 to sizeof(d) + 1, last enumartion supposes the array ends with zero

if(i == d_size || d[i] == 0) {
if((pre_zero_streak + post_zero_streak + 1) >= max_ones_streak) {   //checks for a better answer
best_zero_index = prev_zero_index;
max_ones_streak = pre_zero_streak + post_zero_streak + 1;
}

pre_zero_streak = post_zero_streak;
post_zero_streak = 0;
prev_zero_index = i;
}

else {
post_zero_streak += 1;
}

}

printf("best zero index:%d\n", best_zero_index);
return 0;
}
```
6. isaac said

having had a look at Daniel’s code, realized they are quite the same.
sorry for posting repetitive solution.

7. Globules said

```-- Find the index of an element, whose value is 0, which if set to 1 would
-- maximize the length of a run of 1s.
--
-- Let ns = [n(0), n(1), ..., n(N-1)] be a list of 0s and 1s of length N, and
-- let is = [i(0) = 0, i(1), i(2), ..., i(m), i(m+1) = N], be the indices of all
-- the 0 elements of ns.  (Only i(j), for 1 ≤ j ≤ m, refer to actual elements of
-- ns.)  We have:
--
--   - the length of the run of 1s preceding i(j) is i(j)-i(j-1)-1
--   - the length of the run of 1s following i(j) is i(j+1)-i(j)-1
--
-- The length of the run of 1s created by setting i(j) to 1 would be:
--
--   i(j)-i(j-1)-1 + 1 + i(j+1)-i(j)-1
--
-- Therefore, we want to find the i(j), 1 ≤ j ≤ m, that maximizes:
--
--   i(j)-i(j-1)-1+1+i(j+1)-i(j)-1, or
--   -i(j-1)+i(j+1)-1, or
--   i(j+1)-i(j-1)-1, or
--   i(j+1)-i(j-1)

import Data.List (elemIndices)

-- The value of `replaceIdx ns' is the zero-based index of ns where setting a 0
-- to 1 would result in the longest run of 1s in ns.  If ns contains no 0s then
-- return nothing.  If there is more than one index that would result in runs of
-- the same length, then return the greatest.
longestRunIdx :: [Int] -> Maybe Int
longestRunIdx ns = go \$ 0 : elemIndices 0 ns ++ [length ns]
where go [_,_] = Nothing
go is    = Just . snd . maximum \$ lenIdxs is
lenIdxs is = zipWith3 (\x j y -> (y-x, j)) is (drop 1 is) (drop 2 is)

main :: IO ()
main = do
print \$ longestRunIdx []
print \$ longestRunIdx 
print \$ longestRunIdx [1,1]
print \$ longestRunIdx [0,1,1]
print \$ longestRunIdx [1,0,1]
print \$ longestRunIdx [1,1,0]
print \$ longestRunIdx [1,0,1,1,1,0,1,1,1,1,0,1,1,1,1,0,0,1,1]
```
```\$ ./longrun
Nothing
Nothing
Nothing
Just 0
Just 1
Just 2
Just 10
```
8. Globules said

@Himanshu I don’t think we should need to know any of those things. The array could be empty (i.e. have 0 length), it could be all 0s, all 1s, or any combination of 0s and 1s.

9. David Liu said

Here’s a python solution:

Zeros and Ones

Given an array containing only zeros and ones, find the index of the zero that, if converted to one, will make the longest sequence of ones. For instance, given the array [1,0,1,1,1,0,1,1,1,1,0,1,1,1,1,0,0,1,1], replacing the zero at index 10 (counting from 0) forms a sequence of 9 ones.

Array1 = [1,0,1,1,1,0,1,1,1,1,0,1,1,1,1,0,0,1,1]

print(“Initial array:”, Array1)

Step 1: Find indicies of all Zeros in Array1

L = len(Array1)
zeros = []

for i in range(L):
if Array1[i] == 0:
zeros.append(i)

print(“Indicies of all zeros:”, zeros)

Step 2: Number of Ones before and after each zero is equal to differences in index values to the next and previous zero minus one.

L_z = len(zeros)

before = []
after = []
total = []

for i in range(L_z):
if i == 0: # The number of ones before the first zero is equal to its index
valb = zeros[i]
vala = zeros[i+1]-zeros[i]-1
elif i == (L_z-1): # The number of ones after the last zero is equal to its index minus array length minus one.
vala = L-zeros[i]-1
valb = zeros[i]-zeros[i-1]-1
else:
valb = zeros[i]-zeros[i-1]-1
vala = zeros[i+1]-zeros[i]-1

``````before.append(valb)
after.append(vala)
total.append(vala+valb)
``````

print(“Number of Ones before each Zero:”, before)
print(“Number of Ones after each Zero:”, after)
print(“Number of Ones before AND after each Zero:”, total)

Step 3: Find index of maximum value

index_max = total.index(max(total))

print(“\nThe zero to replace is in index number”,zeros[index_max])

10. David Liu said

Trying to figure out the proper way to format this…

```# Zeros and Ones
# Given an array containing only zeros and ones, find the index of the zero that, if converted to one, will make the longest sequence of ones. For instance, given the array [1,0,1,1,1,0,1,1,1,1,0,1,1,1,1,0,0,1,1], replacing the zero at index 10 (counting from 0) forms a sequence of 9 ones.

Array1 = [1,0,1,1,1,0,1,1,1,1,0,1,1,1,1,0,0,1,1]

print("Initial array:", Array1)

# Step 1: Find indicies of all Zeros in Array1

L = len(Array1)
zeros = []

for i in range(L):
if Array1[i] == 0:
zeros.append(i)

print("Indicies of all zeros:", zeros)

# Step 2: Number of Ones before and after each zero is equal to differences in index values to the next and previous zero minus one.

L_z = len(zeros)

before = []
after = []
total = []

for i in range(L_z):
if i == 0:  # The number of ones before the first zero is equal to its index
valb = zeros[i]
vala = zeros[i+1]-zeros[i]-1
elif i == (L_z-1): # The number of ones after the last zero is equal to its index minus array length minus one.
vala = L-zeros[i]-1
valb = zeros[i]-zeros[i-1]-1
else:
valb = zeros[i]-zeros[i-1]-1
vala = zeros[i+1]-zeros[i]-1

before.append(valb)
after.append(vala)
total.append(vala+valb)

print("Number of Ones before each Zero:", before)
print("Number of Ones after each Zero:", after)
print("Number of Ones before AND after each Zero:", total)

# Step 3: Find index of maximum value

index_max = total.index(max(total))

print("\nThe zero to replace is in index number",zeros[index_max])
```