Check if given Array can be made a permutation of 1 to N by reducing elements by half


Our purpose is to determine whether performing multiple divisions on each item contained within an array creates a list of integers from one through N devoid of any duplicates. Success in this endeavor would denote the accomplishment of our investigative objectives satisfactorily. In essence, ascertaining whether cutting all elements provided within the given array by two produces permutations comprised entirely of non-repeating values ranging between one and N constitutes the main focus of our work. When confirmed, evaluating our thesis follows as the next logical step.

Syntax

Before delving into our proposed solution it is important for us to have a cursory understanding of the methods' syntax which would be implemented shortly.

bool canBePermutation(vector& arr)
{
   // Implementation goes here
}

Algorithm

To address this matter let us proceed by utilizing the algorithm outlined below presented in a step by step manner −

  • To keep tabs on the components observed in the array, commence by initiating a set or hash set. Then, iterate through each and every element present within said array.

  • In order to obtain integers between 1 and N it is necessary to divide each element by two multiple times.

  • Check if the resulting value is already present in the set. If it is, return false as we cannot have duplicates in a permutation.

  • In order for an array to qualify as a valid permutation each and every element must meet the aforementioned conditions. Assuming this criterion is fulfilled in totality confirming its eligibility by providing a return value of true can be deemed an appropriate course of action.

Approaches

In order to effectively address this issue. It may be beneficial to explore different strategies. I will present two possible approaches −

Approach 1: Set-based Approach

Creating a highly effective method requires using meticulous techniques such as implementing a tracking system with created sets to keep account of components encountered throughout the process. It involves evaluating each component iteratively via division processes making sure its resulting value falls between one and N range values only then verifying with checks onto our tracking sets before appending newly observed items only then returning false if there are any exceptions else returning true once all values pass constellations demanding evaluation checks.

Example

#include <iostream>
#include <vector>
#include <unordered_set>

bool canBePermutation(std::vector<int>& arr) {
   std::unordered_set<int> seen;
   
   for (int num : arr) {
      while (num > 0 && num != 1) {
         if (seen.find(num) != seen.end())
            return false;
         
         seen.insert(num);
         num /= 2;
      }
      
      if (num == 0)
         return false;
   }
   
   return true;
}

int main() {
   std::vector<int> arr = {4, 2, 1, 3};
   
   if (canBePermutation(arr)) {
      std::cout << "The given array can be transformed into a permutation.";
   } else {
      std::cout << "The given array cannot be transformed into a permutation.";
   }
   
   return 0;
}

Output

The given array cannot be transformed into a permutation.

Explanation

The initial step in Approach 1 involves setting up an unordered set that tracks elements present within an array. This coded approach then proceeds with iterating throughout every element within that same array repeatedly reducing them into integers between one and N by dividing them with two each time. Throughout these iterations, checks are made on whether or not there have already been items seemingly created within that same collection; thereby attempting to avoid repeating permutations due simply to duplication. Upon detecting duplicates resulting from these repetitions-permutations, false will be returned instead like it would when everything checks out without repeating finishes - passing for true instead - effective in both indicating if a given collection can be moved into its respective permutation whilst minimising its components through halving.

Approach 2: Sorting Approach

Ascending order sorting facilitates detecting whether each array item may render itself to its matching value within a sorted list. Our output would yield false if none of these items satisfy this criteria; however it would return true should all items pass this test.

Example

#include <iostream>
#include <vector>
#include <algorithm>

bool canBePermutation(std::vector<int>& arr) {
   std::sort(arr.begin(), arr.end());

   for (int i = 0; i < arr.size(); i++) {
      int expected = i + 1;
      while (arr[i] > 0 && arr[i] != expected)
         arr[i] /= 2;

      if (arr[i] != expected)
         return false;
   }
   
   return true;
}

int main() {
   std::vector<int> arr = {4, 2, 1, 3};
   
   if (canBePermutation(arr)) {
      std::cout << "The given array can be transformed into a permutation.";
   } else {
      std::cout << "The given array cannot be transformed into a permutation.";
   }
   
   return 0;
}

Output

The given array can be transformed into a permutation.

Explanation

As per Approach 2 (sorting approach), we take up with arranging our original input Array in an ascending order first before proceeding down further with our code routine check. The code subsequently runs various iterations through each individual element of this aforementioned Array while checking whether they are divisible by two or not until they reach their designated and supposed values established upon their position within their newly ordered location range of index values. If during one such iteration rounds there exists any noncompliance towards meeting these predefined critical conditions then our code delineates an outcome as "false", which denotes unachievability regarding a sought transformation of this Array into a corresponding sequential permutation. On the inverse, meanwhile, every compliant element yields an outcome of "true" leading to a viable positive direction for our array reshuffling ambitions.

Conclusion

In this piece, we delved into the challenge of verifying whether a given array can undergo transformation into a permutation comprising numbers ranging from 1 to N by reducing its elements in half. We provided readers with an outline, syntax, and algorithmic procedure for tackling this problem effectively. Additionally, we included two viable approaches along with complete executable code samples in C++. By applying either the set-based technique or sorting strategy highlighted in this piece, readers can satisfactorily establish if any given array matches all necessary criteria for a legitimate permutation.

Updated on: 25-Jul-2023

124 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements