给定数组中不同的交替三元组索引的计数
给定一个大小为N的二进制数组arr[] ,任务是找出不同交替三元组的计数。
注意:如果这些索引的值是 {0, 1, 0} 或 {1, 0, 1} 形式,则三元组是交替的。
例子:
Input: arr[] = {0, 0, 1, 1, 0, 1}
Output: 6
Explanation: Here four sequence of “010” and two sequence of “101” exist.
So, the total number of ways of alternating sequence of size 3 is 6.
Input: arr[] = {0, 0, 0, 0, 0}
Output: 0
Explanation: As there are no 1s in the array so we cannot find any 3 size alternating sequence.
朴素的做法:解决这个问题的基本思路如下:
Find all the triplets and check which among those follow the alternating property.
按照下面提到的步骤来实现这个想法:
- 使用三个嵌套循环指向i、j、k使得 ( i < j < k )。
- 检查arr[i] < arr[j] > arr[k]或arr[i] > arr[j] < arr[k] 。
- 如果是这样,那么增加答案。
- 否则,继续迭代。
- 返回三元组的最终计数。
时间复杂度: O(N 3 )
辅助空间: O(1)
高效的方法:这个问题可以使用基于以下思想的动态规划有效地解决:
The count of alternating subsequences ending at jth index having size i is the same as the sum of values of all the subsequences having size i-1 and having value different from arr[j].
So dynamic programming concept can be utilised here.
要利用动态规划概念,请形成一个 dp[][] 数组,其中 dp[i][j] 存储大小为i并在第 j 个索引处结束的交替子序列的计数。这里i不能超过 3,因为我们需要找到三胞胎。
按照下面提到的步骤来实现这个想法:
- 声明一个二维数组 (比如dp[][] )具有(4 行)和(N + 1 列)并用值0对其进行初始化。
- 从i = 1 到 3迭代可能的子序列长度:
- 现在从j = 0 迭代到 N-1 (考虑到j是这样一个子序列的最后一个索引):
- 如果序列的大小是1或者说(i == 1) ,那么dp[i][j] = 1因为只有一种方法可以创建一个包含一个元素的 1 大小的序列。
- 否则,从k = 0 迭代直到 j以找到与arr[j]不同的任何先前元素。
- 如果存在,则将dp[i][k]添加到dp[i][j]。
- 现在从j = 0 迭代到 N-1 (考虑到j是这样一个子序列的最后一个索引):
- 返回与dp[3][j]行中存储的值的总和相同的可能三元组数。
下面是上述方法的实现:
C++
// C++ code to implement the approach
#include
using namespace std;
// Function to find the distinct ways to
// find alternate sequence of size 3.
long long numberOfWays(vector& s,
int n)
{
int size = 3;
long long ans = 0;
// Declaring a 2d dp
vector > dp(size + 1,
vector(
n + 1, 0));
for (int i = 1; i <= size; i++) {
for (int j = 0; j < n; j++) {
// Filling the first row with 1.
if (i == 1) {
dp[i][j] = 1;
}
else {
// Finding the sum of
// all sequences
// which are ending with
// alternate number
for (int k = 0; k < j; k++) {
if (s[k] != s[j]) {
dp[i][j] += dp[i - 1][k];
}
}
}
}
}
// Answer is the sum of last row of dp
for (int i = 0; i < n; i++) {
ans += dp[size][i];
}
return ans;
}
// Driver code
int main()
{
vector arr = { 0, 0, 1, 1, 0, 1 };
int N = arr.size();
cout << numberOfWays(arr, N);
return 0;
}
Java
// Java code to implement the approach
import java.io.*;
class GFG
{
// Function to find the distinct ways to
// find alternate sequence of size 3.
public static long numberOfWays(int s[], int n)
{
int size = 3;
long ans = 0;
// Declaring a 2d dp
long dp[][] = new long[size + 1][n + 1];
for (int i = 1; i <= size; i++) {
for (int j = 0; j < n; j++) {
// Filling the first row with 1.
if (i == 1) {
dp[i][j] = 1;
}
else {
// Finding the sum of
// all sequences
// which are ending with
// alternate number
for (int k = 0; k < j; k++) {
if (s[k] != s[j]) {
dp[i][j] += dp[i - 1][k];
}
}
}
}
}
// Answer is the sum of last row of dp
for (int i = 0; i < n; i++) {
ans += dp[size][i];
}
return ans;
}
public static void main(String[] args)
{
int arr[] = { 0, 0, 1, 1, 0, 1 };
int N = arr.length;
System.out.print(numberOfWays(arr, N));
}
}
// This code is contributed by Rohit Pradhan
C#
// C# code to implement the approach
using System;
public class GFG{
// Function to find the distinct ways to
// find alternate sequence of size 3.
public static long numberOfWays(int[] s, int n)
{
int size = 3;
long ans = 0;
// Declaring a 2d dp
long[,] dp = new long[size + 1,n + 1];
for (int i = 1; i <= size; i++) {
for (int j = 0; j < n; j++) {
// Filling the first row with 1.
if (i == 1) {
dp[i, j] = 1;
}
else {
// Finding the sum of
// all sequences
// which are ending with
// alternate number
for (int k = 0; k < j; k++) {
if (s[k] != s[j]) {
dp[i, j] += dp[i - 1, k];
}
}
}
}
}
// Answer is the sum of last row of dp
for (int i = 0; i < n; i++) {
ans += dp[size, i];
}
return ans;
}
static public void Main (){
int[] arr = { 0, 0, 1, 1, 0, 1 };
int N = arr.Length;
Console.Write(numberOfWays(arr, N));
}
}
// This code is contributed by hrithikgarg03188.
Javascript
6
时间复杂度: O(N 2 )
辅助空间: 在)