Open In App

Print all subsequences in first decreasing then increasing by selecting N/2 elements from [1, N]

Last Updated : 03 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a positive integer N, the task is to print all the subsequences of the array in such a way that the subsequence is first decreasing then increasing by selecting ceil(N/2) elements from 1 to N.

Examples:

Input: N = 5
Output :
(2, 1, 3), (2, 1, 4), (2, 1, 5), (3, 1, 2), (3, 1, 4), (3, 1, 5), (3, 2, 4), (3, 2, 5), (4, 1, 2), 
(4, 1, 3), (4, 1, 5), (4, 2, 3), (4, 2, 5), (4, 3, 5), (5, 1, 2), (5, 1, 3), (5, 1, 4), (5, 2, 3), 
(5, 2, 4), (5, 3, 4).
These are the valid sequences of size 3 which first decreases and then increases. 

Approach: The approach is based on using the inbuilt function of python itertools.permutation to generate all the subsequences of size ceil(N/2). Follow the steps below to solve the problem:

  • Initialize an array arr[] and insert all the elements from 1 to N.
  • Initialize a variable K as ceil(N/2).
  • Insert all the subsequences in the array “sequences” using the built-in function called itertools.permutations(arr, k).
  • Iterate through the array sequences using the variable seq and perform the following steps:
    • Check if seq[1]>seq[0] or seq[-1]< seq[-2] or if the seq is increasing or descending then continue else this sequence is not satisfying the condition mentioned above.
    • If there is more than 1 element than seq[i]<seq[i-1] and seq[i] <seq[i+1] then also continue and do not print the array.
    • If the seq does not follow any of the points above, then print the seq.

Below is the implementation of the above approach:

C++




// cpp program for the above approach
#include<bits/stdc++.h>
using namespace std;
 
// Function to check if the sequence is valid
// or not
bool  ValidSubsequence(vector<int>seq)
{
 
  // If first element is greater or last second
  // element is greater than last element
  int n = seq.size();
  if ((seq[0] < seq[1]) || (seq[n - 1] < seq[n - 2]))
    return false;
  int i = 0;
 
  // If the sequence is decreasing or increasing
  // or sequence is increasing return false
  // return 0;
  while (i<(seq.size() - 1))
  {
    if (seq[i] > seq[i + 1])
    {
      i++;
      continue;
    }
    else if (seq[i] < seq[i + 1]){
 
      int j = i + 1;
      if ((j != (seq.size())-1) && (seq[j]>seq[j + 1]))
        return false;
    }
    i+= 1;
 
  }
  // If the sequence do not follow above condition
  // Return True
  return true;
 
}
 
 
int main(){
  int N = 5;
  int K = (N+1)/2;
  vector<int>arr,arr0;
  for(int i = 0; i < N; i++)
  {
    arr.push_back(i+1);
  }
 
  // Generate all permutation of size N / 2 using
  // default function
  vector<vector<int>>sequences;
  do{
    vector<int>temp;
    for(int i = 0; i < K; i++)
    {
      temp.push_back(arr[i]);
    }
    sequences.push_back(temp);
  }while(next_permutation(arr.begin(),arr.end()));
 
  // Print the sequence which is valid valley subsequence
  map<vector<int>,int>vis;
  for (auto seq :sequences)
  {
 
    // Check whether the seq is valid or not
    // Function Call
    if (ValidSubsequence(seq) && !vis[seq])
    {
      vis[seq] = 1;
      for(auto j:seq){
        cout<<j<<" ";
      }
      cout<<endl;
    }
  }
}
 
// This code is contributed by Stream_Cipher


Python3




# Python3 program for the above approach
 
# import the ceil permutations in function
from math import ceil
 
# Function to generate all the permutations
from itertools import permutations
 
# Function to check if the sequence is valid
# or not
def ValidSubsequence(seq):
   
  # If first element is greater or last second
  # element is greater than last element
  if (seq[0]<seq[1]) or (seq[-1]<seq[-2]): return False
   
  i = 0
   
  # If the sequence is decreasing or increasing
  # or sequence is increasing return false
  while i<len(seq)-1:
    if seq[i]>seq[i + 1]:
      pass
    elif seq[i]<seq[i + 1]:
      j = i + 1
      if (j != len(seq)-1) and (seq[j]>seq[j + 1]):
        return False
    i+= 1
     
   # If the sequence do not follow above condition
   # Return True
  return True
 
         
# Driver code
N = 5
K = ceil(N / 2)
arr = list(range(1, N + 1))
 
# Generate all permutation of size N / 2 using
# default function
sequences = list(permutations(arr, K))
 
# Print the sequence which is valid valley subsequence
for seq in sequences:
  # Check whether the seq is valid or not
  # Function Call
  if ValidSubsequence(seq):
    print(seq, end =" ")


Java




import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
public class ValleySubSequence {
     
    // Function to check if the sequence is valid
    // or not
    public static boolean ValidSubsequence(List<Integer> seq) {
 
        // If first element is greater or last second
        // element is greater than last element
        int n = seq.size();
        if ((seq.get(0) < seq.get(1)) || (seq.get(n - 1) < seq.get(n - 2)))
            return false;
        int i = 0;
 
        // If the sequence is decreasing or increasing
        // or sequence is increasing return false
        // return 0;
        while (i < (seq.size() - 1)) {
            if (seq.get(i) > seq.get(i + 1)) {
                i++;
                continue;
            } else if (seq.get(i) < seq.get(i + 1)) {
 
                int j = i + 1;
                if ((j != (seq.size() - 1)) && (seq.get(j) > seq.get(j + 1)))
                    return false;
            }
            i += 1;
 
        }
        // If the sequence do not follow above condition
        // Return True
        return true;
 
    }
 
    public static void main(String[] args) {
        int N = 5;
        int K = (N + 1) / 2;
        List<Integer> arr = new ArrayList<Integer>();
        for (int i = 0; i < N; i++) {
            arr.add(i + 1);
        }
 
        // Generate all permutation of size N / 2 using
        // default function
        List<List<Integer>> sequences = new ArrayList<List<Integer>>();
        do {
            List<Integer> temp = new ArrayList<Integer>();
            for (int i = 0; i < K; i++) {
                temp.add(arr.get(i));
            }
            sequences.add(temp);
        } while (nextPermutation(arr));
 
        // Print the sequence which is valid valley subsequence
        Map<List<Integer>, Integer> vis = new HashMap<List<Integer>, Integer>();
        for (List<Integer> seq : sequences) {
 
            // Check whether the seq is valid or not
            // Function Call
            if (ValidSubsequence(seq) && !vis.containsKey(seq)) {
                vis.put(seq, 1);
                for (int j : seq) {
                    System.out.print(j + " ");
                }
                System.out.println();
            }
        }
    }
     
    public static boolean nextPermutation(List<Integer> arr) {
        int n = arr.size();
        int i = n - 2;
        while (i >= 0 && arr.get(i) >= arr.get(i + 1)) {
            i--;
        }
        if (i < 0) {
            return false;
        }
        int j = n - 1;
        while (arr.get(j) <= arr.get(i)) {
            j--;
        }
        int temp = arr.get(i);
        arr.set(i, arr.get(j));
        arr.set(j, temp);
        int l = i + 1;
        int r = n - 1;
        while (l < r) {
            int m = arr.get(l);
            arr.set(l, arr.get(r));
            arr.set(r, m);
            l++;
            r--;
        }
        return true;
    }
 
}


C#




using System;
using System.Collections.Generic;
 
class GFG {
    // Function to check if the sequence is valid
    // or not
    public static bool ValidSubsequence(List<int> seq)
    {
 
        // If first element is greater or last second
        // element is greater than last element
        int n = seq.Count;
        if ((seq[0] < seq[1]) || (seq[n - 1] < seq[n - 2]))
            return false;
        int i = 0;
 
        // If the sequence is decreasing or increasing
        // or sequence is increasing return false
        while (i < (seq.Count - 1)) {
            if (seq[i] > seq[i + 1]) {
                i++;
                continue;
            }
            else if (seq[i] < seq[i + 1]) {
 
                int j = i + 1;
                if ((j != (seq.Count - 1))
                    && (seq[j] > seq[j + 1]))
                    return false;
            }
            i += 1;
        }
        // If the sequence do not follow above condition
        // Return True
        return true;
    }
 
    public static void Main(string[] args)
    {
        int N = 5;
        int K = (N + 1) / 2;
        List<int> arr = new List<int>();
        for (int i = 0; i < N; i++) {
            arr.Add(i + 1);
        }
 
        // Generate all permutation of size N / 2 using
        // default function
        List<List<int> > sequences = new List<List<int> >();
        do {
            List<int> temp = new List<int>();
            for (int i = 0; i < K; i++) {
                temp.Add(arr[i]);
            }
            sequences.Add(temp);
        } while (nextPermutation(arr));
 
        // Print the sequence which is valid valley
        // subsequence
        Dictionary<Tuple<int, int, int>, int> vis
            = new Dictionary<Tuple<int, int, int>, int>();
        foreach(List<int> seq1 in sequences)
        {
 
            // Check whether the seq is valid or not
            // Function Call
            var seq2
                = Tuple.Create(seq1[0], seq1[1], seq1[2]);
            if (ValidSubsequence(seq1)
                && !vis.ContainsKey(seq2)) {
                vis.Add(seq2, 1);
                Console.Write("(");
                foreach(int j in seq1)
                {
                    Console.Write(" " + j);
                }
                Console.Write(" ) ");
            }
        }
    }
     
      // This function converts a given list to its next permutation
    public static bool nextPermutation(List<int> arr)
    {
        int n = arr.Count;
        int i = n - 2;
        while (i >= 0 && arr[i] >= arr[i + 1]) {
            i--;
        }
        if (i < 0) {
            return false;
        }
        int j = n - 1;
        while (arr[j] <= arr[i]) {
            j--;
        }
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
        int l = i + 1;
        int r = n - 1;
        while (l < r) {
            int m = arr[l];
            arr[l] = arr[r];
            arr[r] = m;
            l++;
            r--;
        }
        return true;
    }
}
// This code is contributed by phasing17


Javascript




// This function generates all valley subsequences of length n
function generateValleySubsequences(n) {
// Calculate the number of elements in the first half of the valley subsequence
let k = Math.floor((n + 1) / 2);
// Create an array with elements from 1 to n
let arr = [];
for (let i = 0; i < n; i++) {
arr.push(i + 1);
}
// Generate all permutations of the array
let sequences = [];
do {
let temp = [];
// Take the first k elements of the permutation as the first half of the valley subsequence
for (let i = 0; i < k; i++) {
temp.push(arr[i]);
}
sequences.push(temp);
} while (nextPermutation(arr)); // Continue generating permutations until all have been generated
let output = "";
let vis = new Map();
// Iterate over all generated sequences and check if they are valid valley subsequences
for (let seq of sequences) {
if (ValidSubsequence(seq) && !vis.has(seq)) {
vis.set(seq, 1);
// Add the sequence to the output string
output += "(" + seq.join(", ") + ") ";
}
}
console.log(output.trim()); // Print the output string with leading and trailing whitespace removed
}
 
// This function checks if a sequence is a valid valley subsequence
function ValidSubsequence(seq) {
let n = seq.length;
// Check if the first and last elements of the sequence are in decreasing order
if (seq[0] < seq[1] || seq[n - 1] < seq[n - 2]) {
return false;
}
let i = 0;
// Iterate over the sequence and check if it is a valley subsequence
while (i < n - 1) {
if (seq[i] > seq[i + 1]) {
i++;
continue;
} else if (seq[i] < seq[i + 1]) {
let j = i + 1;
// Check if the remaining elements of the sequence are in decreasing order
if (j !== n - 1 && seq[j] > seq[j + 1]) {
return false;
}
}
i++;
}
return true;
}
 
// This function generates the next lexicographically larger permutation of an array
function nextPermutation(arr) {
let n = arr.length;
let i = n - 2;
// Find the rightmost element that is smaller than the element to its right
while (i >= 0 && arr[i] >= arr[i + 1]) {
i--;
}
// If no such element exists, the array is already the largest permutation
if (i < 0) {
return false;
}
let j = n - 1;
// Find the smallest element to the right of the element at index i that is greater than the element at index i
while (arr[j] <= arr[i]) {
j--;
}
// Swap the elements at indices i and j
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
// Reverse the elements from index i + 1 to the end of the array
let l = i + 1;
let r = n - 1;
while (l < r) {
let m = arr[l];
arr[l] = arr[r];
arr[r] = m;
l++;
r--;
    }
    return true;
}
 
function generateValleySubsequences(n) {
    let k = Math.floor((n + 1) / 2);
    let arr = [];
    for (let i = 0; i < n; i++) {
        arr.push(i + 1);
    }
    let sequences = [];
    do {
        let temp = [];
        for (let i = 0; i < k; i++) {
            temp.push(arr[i]);
        }
        sequences.push(temp);
    } while (nextPermutation(arr));
    let output = "";
    let vis = new Map();
    for (let seq of sequences) {
        if (ValidSubsequence(seq) && !vis.has(seq)) {
            vis.set(seq, 1);
            output += "(" + seq.join(", ") + ") ";
        }
    }
    console.log(output.trim());
}
 
generateValleySubsequences(5);


Output: 

(2, 1, 3) (2, 1, 4) (2, 1, 5) (3, 1, 2) (3, 1, 4) (3, 1, 5) (3, 2, 4) (3, 2, 5) (4, 1, 2) (4, 1, 3) (4, 1, 5) (4, 2, 3) (4, 2, 5) (4, 3, 5) (5, 1, 2) (5, 1, 3) (5, 1, 4) (5, 2, 3) (5, 2, 4) (5, 3, 4)

 

Time Complexity: O(CNN/2  * ceil(N/2)! *N)
Auxiliary Space: O(CNN/2  * ceil(N/2)!)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads