Count ways to select three indices from Binary String with different adjacent digits


In this problem, we will find the number of pairs of 3 indices so that any adjacent indices don’t have the same value in the pair.

We can get the output by checking each pair of 3 indexes, but it can be more time-consuming. Another approach to solving the problem is to take the current index and also take the index from left and right, which doesn’t contain a similar value to the current index's value. This way, we can count the total number of pairs each index can form and sum them to get the output.

Problem statement − We have given a bin_str binary string and need to find the number of pairs of 3 indexes in increasing order, such that adjacent indices don’t contain the same value.

Sample Examples

Input

bin_str = "0101";

Output

2

Explanation

We can take the {0, 1, 2} and {1, 2, 3} index pairs. So, in the 010 and 101 strings, any two adjacent characters are not the same.

Input

bin_str = "110001";

Output

6

Explanation

We can take {0, 2, 5}, {0, 3, 5}, {0, 4, 5}, {1, 2, 5}, {1, 3, 5}, and {1, 4, 5}.

Input

bin_str = “11111”

Output

0

Explanation

As all characters of the string are same, it doesn’t contain any required pairs of indices.

Approach 1

In this approach, we will use three nested loops to find the pair of 3 indices so that the adjacent index doesn’t contain the same value. We will check for each pair whether it follows the conditions given in the problem statement.

Algorithm

  • Step 1 − Initialize the ‘ans’ with 0 to store the number of required pairs.

  • Step 2 − Use the first loop to traverse the string from the 0th index to the binary string’s length – 3 index.

  • Step 3 − Use a nested loop to traverse from the (p + 1) index to the binary string’s length – 2 index.

  • Step 4 − Use another nested loop to traverse the string from the (q + 1) index to the binary string’s length – 1.

  • Step 5 − In the nested loop, if the character at the p and q index are not same, and the character at the q and r index is not same, increment the ‘ans’ value by 1.

  • Step 6 − Return the value of ‘ans’.

Example

Following are the examples to the above algorithm −

#include <stdio.h>
#include <string.h>

long long findIndexSelection(char* bin_str) {
   int bin_len = strlen(bin_str);
   long long ans = 0;
    
   // Creating the pair of 3 indexes
   for (int p = 0; p < bin_len - 2; p++) {
      for (int q = p + 1; q < bin_len - 1; q++) {
         for (int r = q + 1; r < bin_len; r++) {
            
            // Check whether adjacent characters are not the same
            if (bin_str[p] != bin_str[q] && bin_str[q] != bin_str[r]) {
               ans++;
            }
         }
      }
   }
    
   // Final output
   return ans;
}

int main() {
   char bin_str[] = "0101";
   printf("The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is %lld\n", findIndexSelection(bin_str));
   return 0;
}

Output

The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is 2
#include <bits/stdc++.h>
using namespace std;

long long findIndexSelection(string bin_str) {
   int bin_len = bin_str.size();
   int ans = 0;
   
   // Creating the pair of 3 indexes
   for (int p = 0; p < bin_len - 2; p++) { 
      for (int q = p + 1; q < bin_len - 1; q++) {
         for (int r = q + 1; r < bin_len; r++) {
      
            // Check whether adjacent characters are the same or not
            if (bin_str[p] != bin_str[q] && bin_str[q] != bin_str[r]) {
               ans++;
            }
         }
      }
   }
   
   // Final output
   return ans;
}
int main() {
   string bin_str = "0101";
   cout << "The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is " << findIndexSelection(bin_str) << endl;
   return 0;
}

Output

The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is 2
public class Main {
   public static long findIndexSelection(String binStr) {
      int binLen = binStr.length();
      long ans = 0;
        
      // Creating the pair of 3 indexes
      for (int p = 0; p < binLen - 2; p++) {
         for (int q = p + 1; q < binLen - 1; q++) {
            for (int r = q + 1; r < binLen; r++) {
                
               // Check whether adjacent characters are not the same
               if (binStr.charAt(p) != binStr.charAt(q) && binStr.charAt(q) != binStr.charAt(r)) {
                  ans++;
               }
            }
         }
      }
        
      // Final output
      return ans;
   }

   public static void main(String[] args) {
      String binStr = "0101";
      System.out.println("The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is " + findIndexSelection(binStr));
   }
}

Output

The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is 2
def find_index_selection(bin_str):
   bin_len = len(bin_str)
   ans = 0
    
   # Creating the pair of 3 indexes
   for p in range(bin_len - 2):
      for q in range(p + 1, bin_len - 1):
         for r in range(q + 1, bin_len):
            
            # Check whether adjacent characters are not the same
            if bin_str[p] != bin_str[q] and bin_str[q] != bin_str[r]:
               ans += 1
    
   return ans

if __name__ == "__main__":
   bin_str = "0101"
   print("The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is", find_index_selection(bin_str))

Output

The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is 2

Time complexity − O(N*N*N), as we use three nested loops.

Space complexity − O(1) as we don’t use any dynamic space.

Approach 2

If we want to make a pair using the current index, we need to take one left index and one right index, as we need to choose indexes in increasing order. So, we can take all indexes from the left and right that don’t contain the same character as the current index.

The number of pairs we can construct using the current index is given below.

Pairs = (number of left indexes have dissimilar value) * (number of right indexes have dissimilar value)

After that, we can sum the pairs we can construct using each index.

Algorithm

  • Step 1 − Initialize the ‘cnt1’ and ‘cnt0’ variables to store the count of zeros and ones in the given binary string.

  • Step 2 − Traverse the string and update the count of zeros and ones.

  • Step 3 − Initialize the ‘ans’ with 0 to store total pairs.

  • Step 4 − Traverse the string to find total valid pairs.

  • Step 5 − If the current character is ‘0’, add (ones* (cnt1 - ones)) to the ‘ans’. We take multiplication left and right 1’s, which forms the pair like 101. Also, increment ‘zeros’ by 1.

  • Step 6 − If the current character is ‘1’, add (zeros * (cnt0 – zeros)) to the ‘ans’. It forms a string like 010. Next, increment ‘ones’ by 1.

  • Step 7 − Return the ‘ans’ value.

Example

Following are the examples to the above algorithm −

#include <stdio.h>
#include <string.h>

long long findIndexSelection(char* bin_str) {
   int bin_len = strlen(bin_str);
   // Counting the number of zeros and ones
   int cnt0 = 0, cnt1 = 0;
    
   // To store zeros and ones till ith index
   int zeros = 0, ones = 0;
    
   // Traverse the string to count 0's and 1's
   for (int p = 0; p < bin_len; p++) {
      if (bin_str[p] == '0') {
         cnt0++;
      } else {
         cnt1++;
      }
   }
    
   // To store the maximum number of pairs
   long long ans = 0;
    
   // Finding pairs
   for (int p = 0; p < bin_len; p++) {
      if (bin_str[p] == '0') {
        
         // Getting the number of pairs that can be formed with the current index
         ans += (ones * (cnt1 - ones));
            
         // Increase zeros
         zeros++;
      } else {
        
         // Getting the number of pairs that can be formed with the current index
         ans += (zeros * (cnt0 - zeros));
         ones++;
      }
   }
   return ans;
}

int main() {
   char bin_str[] = "1010";
   printf("The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is %lld\n", findIndexSelection(bin_str));
   return 0;
}

Output

The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is 2
#include <bits/stdc++.h>
using namespace std;

long long findIndexSelection(string bin_str) {
   int bin_len = bin_str.size();
   // Counting the number of zeros and ones
   int cnt0 = 0, cnt1 = 0;
   
   // To store zeros and ones till ith index
   int zeros = 0, ones = 0;
   
   // Traverse the string to count 0's and 1's
   for (int p = 0; p < bin_len; p++) {
      if (bin_str[p] == '0') {
         cnt0++;
      } else {
         cnt1++;
      }
   }
   
   // To store the maximum number of pairs
   long long ans = 0;
   
   // Finding pairs
   for (int p = 0; p < bin_len; p++) {
      if (bin_str[p] == '0') {
      
         // Getting the number of pairs can be formed with a current index
         ans += (ones * (cnt1 - ones));
         
         // Increase zeros
         zeros++;
      } else {
      
         // Getting the number of pairs can be formed with a current index
         ans += (zeros * (cnt0 - zeros));
         ones++;
      }
   }
   return ans;
}
int main() {
   string bin_str = "1010";
   cout << "The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is " << findIndexSelection(bin_str) << endl;
   return 0;
}

Output

The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is 2
public class Main {
   public static long findIndexSelection(String binStr) {
      int binLen = binStr.length();
      // Counting the number of zeros and ones
      int cnt0 = 0, cnt1 = 0;
        
      // To store zeros and ones till ith index
      int zeros = 0, ones = 0;
        
      // Traverse the string to count 0's and 1's
      for (int p = 0; p < binLen; p++) {
         if (binStr.charAt(p) == '0') {
            cnt0++;
         } else {
            cnt1++;
         }
      }
        
      // To store the maximum number of pairs
      long ans = 0;
        
      // Finding pairs
      for (int p = 0; p < binLen; p++) {
         if (binStr.charAt(p) == '0') {
            
            // Getting the number of pairs that can be formed with the current index
            ans += (ones * (cnt1 - ones));
                
            // Increase zeros
            zeros++;
         } else {
            
            // Getting the number of pairs that can be formed with the current index
            ans += (zeros * (cnt0 - zeros));
            ones++;
         }
      }
      return ans;
   }

   public static void main(String[] args) {
      String binStr = "1010";
      System.out.println("The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is " + findIndexSelection(binStr));
   }
}

Output

The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is 2
def find_index_selection(bin_str):
   bin_len = len(bin_str)
   # Counting the number of zeros and ones
   cnt0 = 0
   cnt1 = 0
   
   # To store zeros and ones till ith index
   zeros = 0
   ones = 0
   
   # Traverse the string to count 0's and 1's
   for p in range(bin_len):
      if bin_str[p] == '0':
         cnt0 += 1
      else:
         cnt1 += 1
    
   # To store the maximum number of pairs
   ans = 0
    
   # Finding pairs
   for p in range(bin_len):
      if bin_str[p] == '0':
        
         # Getting the number of pairs that can be formed with the current index
         ans += (ones * (cnt1 - ones))
            
         # Increase zeros
         zeros += 1
      else:
        
         # Getting the number of pairs that can be formed with the current index
         ans += (zeros * (cnt0 - zeros))
         ones += 1
    
   return ans

if __name__ == "__main__":
   bin_str = "1010"
   print("The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is", find_index_selection(bin_str))

Output

The maximum number of ways to select indexes such that two adjacent indexes don't have the same character is 2

Time complexity – O(N) to traverse the string.

Space complexity – O(1), as we don’t use any dynamic space.

We learned the naïve approach and optimized approach to solve the problem. The first approach has high time complexity and can’t be used for large inputs. The second approach uses the concept of prefixes 1s and 0s to solve the problem.

Updated on: 16-Oct-2023

59 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements