Open In App

Number of ways to form an array with distinct adjacent elements

Given three integers N, M and X, the task is to find the number of ways to form an array, such that all consecutive numbers of the array are distinct, and the value at any index of the array from 2 to N – 1(Considering 1 based indexing) lies between 1 and M, while the value at index 1 is X and the value at index N is 1. 
Note: Value of X lies between 1 and M.
Examples: 
 

Input: N = 4, M = 3, X = 2 
Output:
The following arrays are possible: 
1) 2, 1, 2, 1 
2) 2, 1, 3, 1 
3) 2, 3, 2, 1
Input: N = 2, M = 3, X = 2 
Output:
The only possible array is: 2, 1

 

Approach: The problem can be solved using Dynamic Programming. Let, f(i) represent the number of ways to form the array till the ith index, such that every consecutive element of the array is distinct. Let f(i, One) represent the number of ways to form the array till the i-th index such that every consecutive element of the array is distinct and arri = 1. 
Similarly, let f(i, Non-One) represent the number of ways to form the array till the ith index, such that every consecutive element of the array is distinct and arri is not equal to 1.
The following recurrence is formed: 
 

f(i, Non-One) = f(i - 1, One) * (M - 1) + f(i - 1, Non-One) * (M - 2)

which means that the number of ways to form the array till the ith index with arrayi not equal to 1 is formed using two cases: 
 

  1. If the number at arrayi – 1 is 1, then opt one number out of (M – 1) options to place at the ith index, since arrayi is not equal to 1.
  2. If the number at arrayi – 1 is not 1, then we need to opt one number out of (M – 2) options, since arrayi is not equal to 1 and arrayi ≠ arrayi – 1.

Similarly, f(i, One) = f(i – 1, Non-One), since the number of ways to form the array till the ith index with arrayi = 1, is same as number of ways to form the array till the (i – 1)th index with arrayi – 1 ≠ 1, thus at the ith index there is only one option. At the end the required answer if f(N, One) since arrayN needs to be equal to 1.
Below is the implementation of the above approach: 
 




// C++ program to count the number of ways
// to form arrays of N numbers such that the
// first and last numbers are fixed
// and all consecutive numbers are distinct
#include <bits/stdc++.h>
using namespace std;
 
// Returns the total ways to form arrays such that
// every consecutive element is different and each
// element except the first and last can take values
// from 1 to M
int totalWays(int N, int M, int X)
{
 
    // define the dp[][] array
    int dp[N + 1][2];
 
    // if the first element is 1
    if (X == 1) {
 
        // there is only one way to place
        // a 1 at the first index
        dp[0][0] = 1;
    }
    else {
 
        // the value at first index needs to be 1,
        // thus there is no way to place a non-one integer
        dp[0][1] = 0;
    }
 
    // if the first element was 1 then at index 1,
    // only non one integer can be placed thus
    // there are M - 1 ways to place a non one integer
    // at index 2 and 0 ways to place a 1 at the 2nd index
    if (X == 1) {
        dp[1][0] = 0;
        dp[1][1] = M - 1;
    }
 
    // Else there is one way to place a one at
    // index 2 and if a non one needs to be placed here,
    // there are (M - 2) options, i.e
    // neither the element at this index
    // should be 1, neither should it be
    // equal to the previous element
    else {
        dp[1][0] = 1;
        dp[1][1] = (M - 2);
    }
 
    // Build the dp array in bottom up manner
    for (int i = 2; i < N; i++) {
 
        // f(i, one) = f(i - 1, non-one)
        dp[i][0] = dp[i - 1][1];
 
        // f(i, non-one) = f(i - 1, one) * (M - 1) +
        // f(i - 1, non-one) * (M - 2)
        dp[i][1] = dp[i - 1][0] * (M - 1) + dp[i - 1][1] * (M - 2);
    }
 
    // last element needs to be one, so return dp[n - 1][0]
    return dp[N - 1][0];
}
 
// Driver Code
int main()
{
 
    int N = 4, M = 3, X = 2;
    cout << totalWays(N, M, X) << endl;
 
    return 0;
}




// Java program to count the
// number of ways to form
// arrays of N numbers such
// that the first and last
// numbers are fixed and all
// consecutive numbers are
// distinct
import java.io.*;
 
class GFG
{
 
// Returns the total ways to
// form arrays such that every
// consecutive element is
// different and each element
// except the first and last
// can take values from 1 to M
static int totalWays(int N,
                     int M, int X)
{
 
    // define the dp[][] array
    int dp[][] = new int[N + 1][2];
 
    // if the first element is 1
    if (X == 1)
    {
 
        // there is only one
        // way to place a 1
        // at the first index
        dp[0][0] = 1;
    }
    else
    {
 
        // the value at first index
        // needs to be 1, thus there
        // is no way to place a
        // non-one integer
        dp[0][1] = 0;
    }
 
    // if the first element was 1
    // then at index 1, only non
    // one integer can be placed
    // thus there are M - 1 ways
    // to place a non one integer
    // at index 2 and 0 ways to
    // place a 1 at the 2nd index
    if (X == 1)
    {
        dp[1][0] = 0;
        dp[1][1] = M - 1;
    }
 
    // Else there is one way to
    // place a one at index 2
    // and if a non one needs to
    // be placed here, there are
    // (M - 2) options, i.e neither
    // the element at this index
    // should be 1, neither should
    // it be equal to the previous
    // element
    else
    {
        dp[1][0] = 1;
        dp[1][1] = (M - 2);
    }
 
    // Build the dp array
    // in bottom up manner
    for (int i = 2; i < N; i++)
    {
 
        // f(i, one) = f(i - 1,
        // non-one)
        dp[i][0] = dp[i - 1][1];
 
        // f(i, non-one) =
        // f(i - 1, one) * (M - 1) +
        // f(i - 1, non-one) * (M - 2)
        dp[i][1] = dp[i - 1][0] * (M - 1) +
                   dp[i - 1][1] * (M - 2);
    }
 
    // last element needs to be
    // one, so return dp[n - 1][0]
    return dp[N - 1][0];
}
 
// Driver Code
public static void main (String[] args)
{
    int N = 4, M = 3, X = 2;
    System.out.println(totalWays(N, M, X));
}
}
 
// This code is contributed by anuj_67.




# Python 3 program to count the number of ways
# to form arrays of N numbers such that the
# first and last numbers are fixed
# and all consecutive numbers are distinct
 
# Returns the total ways to form arrays such that
# every consecutive element is different and each
# element except the first and last can take values
# from 1 to M
def totalWays(N,M,X):
     
    # define the dp[][] array
    dp = [[0 for i in range(2)] for j in range(N+1)]
 
    # if the first element is 1
    if (X == 1):
         
        # there is only one way to place
        # a 1 at the first index
        dp[0][0] = 1
 
    else:
        # the value at first index needs to be 1,
        # thus there is no way to place a non-one integer
        dp[0][1] = 0
 
    # if the first element was 1 then at index 1,
    # only non one integer can be placed thus
    # there are M - 1 ways to place a non one integer
    # at index 2 and 0 ways to place a 1 at the 2nd index
    if (X == 1):
        dp[1][0] = 0
        dp[1][1] = M - 1
 
    # Else there is one way to place a one at
    # index 2 and if a non one needs to be placed here,
    # there are (M - 2) options, i.e
    # neither the element at this index
    # should be 1, neither should it be
    # equal to the previous element
    else:
        dp[1][0] = 1
        dp[1][1] = (M - 2)
 
    # Build the dp array in bottom up manner
    for i in range(2,N):
        # f(i, one) = f(i - 1, non-one)
        dp[i][0] = dp[i - 1][1]
 
        # f(i, non-one) = f(i - 1, one) * (M - 1) +
        # f(i - 1, non-one) * (M - 2)
        dp[i][1] = dp[i - 1][0] * (M - 1) + dp[i - 1][1] * (M - 2)
 
    # last element needs to be one, so return dp[n - 1][0]
    return dp[N - 1][0]
 
# Driver Code
if __name__ == '__main__':
    N = 4
    M = 3
    X = 2
    print(totalWays(N, M, X))
     
# This code is contributed by
# Surendra_Gangwar




// C# program to count the
// number of ways to form
// arrays of N numbers such
// that the first and last
// numbers are fixed and all
// consecutive numbers are
// distinct
using System;
 
class GFG
{
 
// Returns the total ways to
// form arrays such that every
// consecutive element is
// different and each element
// except the first and last
// can take values from 1 to M
static int totalWays(int N,
                     int M, int X)
{
 
    // define the dp[][] array
    int [,]dp = new int[N + 1, 2];
 
    // if the first element is 1
    if (X == 1)
    {
 
        // there is only one
        // way to place a 1
        // at the first index
        dp[0, 0] = 1;
    }
    else
    {
 
        // the value at first index
        // needs to be 1, thus there
        // is no way to place a
        // non-one integer
        dp[0, 1] = 0;
    }
 
    // if the first element was 1
    // then at index 1, only non
    // one integer can be placed
    // thus there are M - 1 ways
    // to place a non one integer
    // at index 2 and 0 ways to
    // place a 1 at the 2nd index
    if (X == 1)
    {
        dp[1, 0] = 0;
        dp[1, 1] = M - 1;
    }
 
    // Else there is one way to
    // place a one at index 2
    // and if a non one needs to
    // be placed here, there are
    // (M - 2) options, i.e neither
    // the element at this index
    // should be 1, neither should
    // it be equal to the previous
    // element
    else
    {
        dp[1, 0] = 1;
        dp[1, 1] = (M - 2);
    }
 
    // Build the dp array
    // in bottom up manner
    for (int i = 2; i < N; i++)
    {
 
        // f(i, one) = f(i - 1,
        // non-one)
        dp[i, 0] = dp[i - 1, 1];
 
        // f(i, non-one) =
        // f(i - 1, one) * (M - 1) +
        // f(i - 1, non-one) * (M - 2)
        dp[i, 1] = dp[i - 1, 0] * (M - 1) +
                   dp[i - 1, 1] * (M - 2);
    }
 
    // last element needs to be
    // one, so return dp[n - 1][0]
    return dp[N - 1, 0];
}
 
// Driver Code
public static void Main ()
{
    int N = 4, M = 3, X = 2;
    Console.WriteLine(totalWays(N, M, X));
}
}
 
// This code is contributed
// by anuj_67.




<script>
    // Javascript program to count the
    // number of ways to form
    // arrays of N numbers such
    // that the first and last
    // numbers are fixed and all
    // consecutive numbers are
    // distinct
     
    // Returns the total ways to
    // form arrays such that every
    // consecutive element is
    // different and each element
    // except the first and last
    // can take values from 1 to M
    function totalWays(N, M, X)
    {
 
        // define the dp[][] array
        let dp = new Array(N + 1);
        for(let i = 0; i < N + 1; i++)
        {
            dp[i] = new Array(2);
            for(let j = 0; j < 2; j++)
            {
                dp[i][j] = 0;
            }
        }
 
        // if the first element is 1
        if (X == 1)
        {
 
            // there is only one
            // way to place a 1
            // at the first index
            dp[0][0] = 1;
        }
        else
        {
 
            // the value at first index
            // needs to be 1, thus there
            // is no way to place a
            // non-one integer
            dp[0][1] = 0;
        }
 
        // if the first element was 1
        // then at index 1, only non
        // one integer can be placed
        // thus there are M - 1 ways
        // to place a non one integer
        // at index 2 and 0 ways to
        // place a 1 at the 2nd index
        if (X == 1)
        {
            dp[1][0] = 0;
            dp[1][1] = M - 1;
        }
 
        // Else there is one way to
        // place a one at index 2
        // and if a non one needs to
        // be placed here, there are
        // (M - 2) options, i.e neither
        // the element at this index
        // should be 1, neither should
        // it be equal to the previous
        // element
        else
        {
            dp[1][0] = 1;
            dp[1][1] = (M - 2);
        }
 
        // Build the dp array
        // in bottom up manner
        for (let i = 2; i < N; i++)
        {
 
            // f(i, one) = f(i - 1,
            // non-one)
            dp[i][0] = dp[i - 1][1];
 
            // f(i, non-one) =
            // f(i - 1, one) * (M - 1) +
            // f(i - 1, non-one) * (M - 2)
            dp[i][1] = dp[i - 1][0] * (M - 1) +
                       dp[i - 1][1] * (M - 2);
        }
 
        // last element needs to be
        // one, so return dp[n - 1][0]
        return dp[N - 1][0];
    }
     
    let N = 4, M = 3, X = 2;
    document.write(totalWays(N, M, X));
 
// This code is contributed by divyeshrabadiya07.
</script>




<?php
// PHP program to count the
// number of ways to form
// arrays of N numbers such
// that the first and last
// numbers are fixed and all
// consecutive numbers are distinct
 
// Returns the total ways to
// form arrays such that every
// consecutive element is
// different and each element
// except the first and last
// can take values from 1 to M
function totalWays($N, $M, $X)
{
 
    // define the dp[][] array
    $dp = array(array());
 
    // if the first element is 1
    if ($X == 1)
    {
 
        // there is only one
        // way to place a 1
        // at the first index
        $dp[0][0] = 1;
    }
    else
    {
 
        // the value at first
        // index needs to be 1,
        // thus there is no way
        // to place a non-one integer
        $dp[0][1] = 0;
    }
 
    // if the first element was
    // 1 then at index 1, only
    // non one integer can be
    // placed thus there are M - 1
    // ways to place a non one
    // integer at index 2 and 0 ways
    // to place a 1 at the 2nd index
    if ($X == 1)
    {
        $dp[1][0] = 0;
        $dp[1][1] = $M - 1;
    }
 
    // Else there is one way
    // to place a one at index
    // 2 and if a non one needs
    // to be placed here, there
    // are (M - 2) options, i.e
    // neither the element at
    // this index should be 1,
    // neither should it be equal
    // to the previous element
    else
    {
        $dp[1][0] = 1;
        $dp[1][1] = ($M - 2);
    }
 
    // Build the dp array
    // in bottom up manner
    for ($i = 2; $i <$N; $i++)
    {
 
        // f(i, one) =
        // f(i - 1, non-one)
        $dp[$i][0] = $dp[$i - 1][1];
 
        // f(i, non-one) =
        // f(i - 1, one) * (M - 1) +
        // f(i - 1, non-one) * (M - 2)
        $dp[$i][1] = $dp[$i - 1][0] *
                           ($M - 1) +
                     $dp[$i - 1][1] *
                           ($M - 2);
    }
 
    // last element needs to
    // be one, so return dp[n - 1][0]
    return $dp[$N - 1][0];
}
 
// Driver Code
$N = 4; $M = 3; $X = 2;
echo totalWays($N, $M, $X);
 
// This code is contributed
// by anuj_67.
?>

Output
3







Time Complexity: O(N), where N is the size of the array
Auxiliary Space: O(N), for dp array

Efficient approach : Space optimization O(1)

In previous approach we the current value dp[i] is only depend upon the previous value i.e. dp[i-1]. So to optimize the space we can keep track of previous and current values by the help of three variables prev and curr which will reduce the space complexity from O(N) to O(1).  

Implementation Steps:

Implementation:




// C++ program to count the number of ways
// to form arrays of N numbers such that the
// first and last numbers are fixed
// and all consecutive numbers are distinct
#include <bits/stdc++.h>
using namespace std;
 
 
// Returns the total ways to form arrays such that
// every consecutive element is different and each
// element except the first and last can take values
// from 1 to M
int totalWays(int N, int M, int X)
{
    // initialize variable to keep track
    // of previous and current value
    int prev, curr;
 
     
    // Base case
    if (X == 1) {
        prev = 1;
    } else {
        curr = 0;
    }
 
    if (X == 1) {
        curr = M - 1;
    } else {
        prev = 1;
        curr = M - 2;
    }
     
    // iterating over subproblems to get the computation of
    // current value from previous computation
    for (int i = 2; i < N; i++) {
        int temp = prev;
        prev = curr;
        curr = temp * (M - 1) + curr * (M - 2);
    }
 
    // return answer
    return prev;
}
 
// Driver Code
int main()
{
    int N = 4, M = 3, X = 2;
    cout << totalWays(N, M, X) << endl;
 
    return 0;
}




import java.util.*;
 
public class GFG {
    // Returns the total ways to form arrays such that
    // every consecutive element is different and each
    // element except the first and last can take values
    // from 1 to M
        static int totalWays(int N, int M, int X) {
        // Initialize variables to keep track of previous and
       // current value
        int prev = 0, curr = 0;
 
        // Base case
        if (X == 1) {
            prev = 1;
        } else {
            curr = M - 1;
        }
 
        if (X == 1) {
            curr = M - 1;
        } else {
            prev = 1;
            curr = M - 2;
        }
 
        // Iterate over subproblems to compute the current
       // value from previous computation
        for (int i = 2; i < N; i++) {
            int temp = prev;
            prev = curr;
            curr = temp * (M - 1) + curr * (M - 2);
        }
 
        // Return the answer
        return prev;
    }
 
    // Driver Code
    public static void main(String[] args) {
        int N = 4, M = 3, X = 2;
        System.out.println(totalWays(N, M, X));
    }
}




#Returns the total ways to form arrays such that
#every consecutive element is different and each
#element except the first and last can take values
#from 1 to M
def totalWays(N, M, X):
    # Base case
    if X == 1:
        prev = 1
    else:
        curr = 0
 
    if X == 1:
        curr = M - 1
    else:
        prev = 1
        curr = M - 2
 
    # iterating over subproblems to get the computation of
    # current value from previous computation
    for i in range(2, N):
        temp = prev
        prev = curr
        curr = temp * (M - 1) + curr * (M - 2)
 
    # return answer
    return prev
 
 
# Driver Code
if __name__ == "__main__":
    N = 4
    M = 3
    X = 2
    print(totalWays(N, M, X))




// C# program to count the number of ways
// to form arrays of N numbers such that the
// first and last numbers are fixed
// and all consecutive numbers are distinct
using System;
 
namespace ArrayWays
{
    class GFG
    {
        // Returns the total ways to form arrays such that
        // every consecutive element is different and each
        // element except the first and last can take values
        // from 1 to M
        static int TotalWays(int N, int M, int X)
        {
            // Initialize variables to keep track
            // of previous and current value
            int prev = 0, curr = 0;
            // Base case
            if (X == 1)
            {
                prev = 1;
            }
            else
            {
                curr = 0;
            }
            if (X == 1)
            {
                curr = M - 1;
            }
            else
            {
                prev = 1;
                curr = M - 2;
            }
            // Iterating over subproblems to get the computation of
            // current value from previous computation
            for (int i = 2; i < N; i++)
            {
                int temp = prev;
                prev = curr;
                curr = temp * (M - 1) + curr * (M - 2);
            }
            // Return answer
            return prev;
        }
        // Driver Code
        static void Main(string[] args)
        {
            int N = 4, M = 3, X = 2;
            Console.WriteLine(TotalWays(N, M, X));
        }
    }
}




// Returns the total ways to form arrays such that
// every consecutive element is different and each
// element except the first and last can take values
// from 1 to M
function totalWays(N, M, X) {
    let prev, curr;
     
    // Base case
    if (X === 1) {
        prev = 1;
    } else {
        curr = 0;
    }
 
    if (X === 1) {
        curr = M - 1;
    } else {
        prev = 1;
        curr = M - 2;
    }
     
    // iterating over subproblems to get the computation of
    // current value from previous computation
    for (let i = 2; i < N; i++) {
        let temp = prev;
        prev = curr;
        curr = temp * (M - 1) + curr * (M - 2);
    }
 
    return prev;
}
 
// Driver Code
const N = 4, M = 3, X = 2;
console.log(totalWays(N, M, X));

Output: 

3

 

Time Complexity: O(N), where N is the size of the array
Auxiliary Space: O(1), only use variables  


Article Tags :