📌  相关文章
📜  二进制字符串中三元组的计数,使得 S[i]、S[j] 和 S[j]、S[k] 的按位与相同

📅  最后修改于: 2022-05-13 01:56:08.237000             🧑  作者: Mango

二进制字符串中三元组的计数,使得 S[i]、S[j] 和 S[j]、S[k] 的按位与相同

给定一个长度为N的二进制字符串S ,由 0 和 1 组成。任务是计算三元组(i, j, k)的数量,使得S[i] & S[j] = S[j] & S[k] ,其中0 ≤ i < j < k < N&表示按位与运算符。

例子:

天真的方法:解决问题的最简单方法是:

请按照以下步骤解决此问题:

  • 声明一个变量ans并将其初始化为0以存储总计数。
  • 现在,需要三个嵌套循环来遍历所有三元组。
    • 第一个循环遍历索引i ,第二个遍历索引ji+1开始,第三个遍历索引kj+1开始。
    • 现在,检查条件S[i] & S[j] = S[j] & S[k]是否为真。如果为真,则将ans增加1
  • 返回三元组的总数。

以下是上述方法的实现:

C++
// C++ program for above approach
 
#include 
using namespace std;
 
// Function to count total number of triplets
int countTriplets(int n, string& s)
{
    // Stores the count of triplets.
    int ans = 0;
 
    // Iterate over all the triplets.
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            for (int k = j + 1; k < n; ++k) {
 
                // Extract integer from 'S[i]',
                // 'S[j]', 'S[k]'.
                int x = s[i] - '0';
                int y = s[j] - '0',
                    z = s[k] - '0';
 
                // If condition 'S[i]' & 'S[j]'
                // == 'S[j]' &'S[k]' is true,
                // increment 'ans'.
                if ((x & y) == (y & z)) {
                    ans++;
                }
            }
        }
    }
 
    // Return the answer
    return ans;
}
 
// Driver code
int main()
{
    int N = 4;
    string S = "0010";
 
    // Function call
    cout << countTriplets(N, S);
    return 0;
}


Java
// JAVA program for above approach
import java.util.*;
class GFG {
 
  // Function to count total number of triplets
  public static int countTriplets(int n, String s)
  {
 
    // Stores the count of triplets.
    int ans = 0;
 
    // Iterate over all the triplets.
    for (int i = 0; i < n; ++i) {
      for (int j = i + 1; j < n; ++j) {
        for (int k = j + 1; k < n; ++k) {
 
          // Extract integer from 'S[i]',
          // 'S[j]', 'S[k]'.
          int x = s.charAt(i);
          int y = s.charAt(j), z = s.charAt(k);
 
          // If condition 'S[i]' & 'S[j]'
          // == 'S[j]' &'S[k]' is true,
          // increment 'ans'.
          if ((x & y) == (y & z)) {
            ans++;
          }
        }
      }
    }
 
    // Return the answer
    return ans;
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int N = 4;
    String S = "0010";
 
    // Function call
    System.out.print(countTriplets(N, S));
  }
}
 
// This code is contributed by Taranpreet


Python3
# Python3 program for above approach
 
# Function to count total number of triplets
def countTriplets(n, s):
   
    # Stores the count of triplets.
    ans = 0
     
    # Iterate over all the triplets.
    for i in range(n):
        for j in range(i + 1, n):
            for k in range(j + 1, n):
               
                # Extract integer from 'S[i]', S[j], S[k]
                x = ord(S[i]) - ord("0")
                y = ord(S[j]) - ord("0")
                z = ord(S[k]) - ord("0")
 
                # If condition 'S[i]' & 'S[j]'
                # == S[j]' & 'S[k]'
                # is true, increment ans
                if (x & y) == (y & z):
                    ans += 1
    # return the answer
    return ans
 
# Driver code
N = 4
S = "0010"
 
# function call
print(countTriplets(N, S))
 
# This code is contributed by hrithikgarg03188.


C#
// C# program for above approach
using System;
public class GFG{
 
  // Function to count total number of triplets
  static int countTriplets(int n, string s)
  {
 
    // Stores the count of triplets.
    int ans = 0;
 
    // Iterate over all the triplets.
    for (int i = 0; i < n; ++i) {
      for (int j = i + 1; j < n; ++j) {
        for (int k = j + 1; k < n; ++k) {
 
          // Extract integer from 'S[i]',
          // 'S[j]', 'S[k]'.
          int x = s[i];
          int y = s[j], z = s[k];
 
          // If condition 'S[i]' & 'S[j]'
          // == 'S[j]' &'S[k]' is true,
          // increment 'ans'.
          if ((x & y) == (y & z)) {
            ans++;
          }
        }
      }
    }
 
    // Return the answer
    return ans;
  }
 
  // Driver code
  static public void Main ()
  {
 
    int N = 4;
    string S = "0010";
 
    // Function call
    Console.Write(countTriplets(N, S));
  }
}
 
// This code is contributed by hrithikgarg03188.


Javascript


C++
// C++ program for above approach
 
#include 
using namespace std;
 
// Function to count number of triplets
int countTriplets(int n, string& s)
{
    // Stores the count of triplets.
    int ans = 0;
 
    // 'pre[i]', 'suf[i]', stores the
    // number of zeroes in
    // the prefix and suffix
    vector pre(n), suf(n);
 
    // Build the prefix array
    for (int i = 0; i < n; ++i) {
        pre[i] = (i == 0 ? 0 : pre[i - 1])
                 + (s[i] == '0');
    }
 
    // Build the suffix array.
    for (int i = n - 1; i >= 0; --i) {
        suf[i]
            = (i == n - 1 ? 0 : suf[i + 1])
              + (s[i] == '0');
    }
 
    // Iterate over the middle index
    // of the triplet.
    for (int j = 1; j < n - 1; ++j) {
 
        // If 'S[j]' == '0'
        if (s[j] == '0') {
            ans += j * (n - j - 1);
        }
        else {
 
            // If 'S[j]' == '1'
            ans += pre[j - 1] * suf[j + 1]
                   + (j - pre[j - 1])
                         * (n - j - 1 - suf[j + 1]);
        }
    }
 
    // Return the answer.
    return ans;
}
 
// Driver code
int main()
{
    int N = 4;
    string S = "0010";
 
    // Function call
    cout << countTriplets(N, S);
    return 0;
}


输出
4

时间复杂度: O(N 3 )
辅助空间: O(1)

有效方法:有效解决问题的想法基于以下观察:

观察:

请按照以下步骤解决此问题:

  • 声明一个变量(比如ans 存储三元组的计数并将其初始化为 0。
  • 创建一个前缀数组pre和一个后缀数组suf 。这两个数组在数组的前缀和后缀中存储了零的数量。
  • 对于构建前缀数组,从0 迭代到 N – 1
    • 如果 S[i] == '0',则 pre[i] = pre[i – 1] + 1。
    • 如果 S[i]== '1',则 pre[i] = pre[i – 1]。
  • 对于构建后缀数组,从N – 1 迭代到 0
    • 如果 S[i] == '0',则 suf[i] = suf[i + 1] + 1。
    • 如果 S[i] == '1',则 suf[i] = suf[i + 1]。
  • 现在再次迭代,从1 到 N – 2 (我们正在迭代 S[j]):
    • 如果 S[j] == '0',则根据观察将 j * (N – j – 1)添加到ans变量中。
    • 如果 S[j] == '1',则添加 'pre[j - 1]' * 'suf[j + 1]' + (j - 'pre[j - 1]') * (N - j - 1 – 'suf[j + 1]')到 ans 根据上述观察。
  • 现在返回ans变量,因为它包含三元组的最终计数。

以下是上述方法的实现:

C++

// C++ program for above approach
 
#include 
using namespace std;
 
// Function to count number of triplets
int countTriplets(int n, string& s)
{
    // Stores the count of triplets.
    int ans = 0;
 
    // 'pre[i]', 'suf[i]', stores the
    // number of zeroes in
    // the prefix and suffix
    vector pre(n), suf(n);
 
    // Build the prefix array
    for (int i = 0; i < n; ++i) {
        pre[i] = (i == 0 ? 0 : pre[i - 1])
                 + (s[i] == '0');
    }
 
    // Build the suffix array.
    for (int i = n - 1; i >= 0; --i) {
        suf[i]
            = (i == n - 1 ? 0 : suf[i + 1])
              + (s[i] == '0');
    }
 
    // Iterate over the middle index
    // of the triplet.
    for (int j = 1; j < n - 1; ++j) {
 
        // If 'S[j]' == '0'
        if (s[j] == '0') {
            ans += j * (n - j - 1);
        }
        else {
 
            // If 'S[j]' == '1'
            ans += pre[j - 1] * suf[j + 1]
                   + (j - pre[j - 1])
                         * (n - j - 1 - suf[j + 1]);
        }
    }
 
    // Return the answer.
    return ans;
}
 
// Driver code
int main()
{
    int N = 4;
    string S = "0010";
 
    // Function call
    cout << countTriplets(N, S);
    return 0;
}
输出
4

时间复杂度: O(N)
辅助空间: O(N)