Find all possible combinations of K numbers from 1 to n

coding interview problem

Shubham Kumar Gupta
EnjoyAlgorithms

--

Difficulty Level

Medium

Asked In

Amazon, Adobe

Three Solutions Discussed

  1. Inclusion and Exclusion of every element
  2. Fix elements and recur for creating a combination of K numbers
  3. Recursive Backtracking — DFS Approach

Key Takeaway after reading this blog

  • This is a good interview problem to understand the concept of problem-solving using backtracking and combinatorics.
  • We can use similar ideas to solve other interview problems.

Let’s understand the problem

Given two numbers n and K and you have to find all possible combinations of K numbers from 1 to n.

Example

Solution 1 — Inclusion and Exclusion of every element

Algorithm Idea

We use the idea similar to the subset sum problem for creating possible combinations of K numbers from n numbers— We select each number from 1 to n and recur for two possible cases:

(i) The selected number is the part of the solution or included in the set

(ii) The selected number is not part of the solution or not included in the set

Suppose we have n = 4 and K=2 i.e: Given Range : [1,2,3,4]. The following tree diagram explains the generation of all combinations of size 2.

  • We are going left if we are including the number and going right if we are not including the number.
  • At each level, we are including or excluding one number at a time.
  • We have a combination of size 2 at each leaf node.

To implement this, we use a temporary array temp[] to stores all outputs one by one. When the number of elements in temp[] becomes equal to K (size of a combination), we print it. All we need to do is to consider both cases and recursively creates all possible combinations. The main idea of this approach comes from the pascal’s Identity i.e: C(n, K) = C( n-1, K)+C (n-1, K-1) (Think!)

Algorithm Code C++

Algorithm Analysis

Here for each element, there are two possibilities i.e; whether the element will be selected or not. This creates two cases for each element and we are going to iterate for all n elements. So, the overall time complexity will be O(2^n). (Think!)

Space Complexity = O(K* C(n, K))

Possible questions by the interviewer

  • Why space complexity is O(K* C(n, K))?
  • How to handle duplicates in the above solution?
  • How can we improve the time complexity?

Solution 2 — Fix elements and recur for creating a combination of K numbers

Algorithm Idea

The idea is to generate a combination tree where we fix each number from 1 to n and recursively build the combination of K numbers. Suppose we have n = 5 and K=3 i.e: Given Range : [1,2,3,4, 5].

  • We first fix number 1 and recursively generate the all unique combination of size 3 starting with number 1 i.e. {1,2,3}, {1,2,4}, {1,2,5}, {1,3,4}, {1,4,5}.
  • Then we first fix number 2 and recursively generate the all unique combination of size 3 starting with number 2 i.e. {2,3,4}, {2,3,5} and {2,4,5}.
  • Then we first fix number 3 and recursively generate the all unique combination of size 3 starting with number 3 i.e. {3,4, 5}.
  • There would be no unique combination of size 3 starting from 4 and 5. (Think!)

To implement this

  • We use a temporary array temp[] to stores all outputs one by one.
  • We start from the first index in temp[] and one by one fix elements at this index and recur for the remaining indexes.
  • When the number of elements in temp[] becomes equal to K (size of a combination), recursion stop and we print temp[].

Algorithm Code C++

Algorithm Analysis

The loop in the algorithm will run C(n, K) times as this is the possible number of combinations and in each iteration, Elements can get selected in the range of (n-K) as K elements are already selected and we just replacing elements which are already occupied. So, the overall time complexity will be O(C(n, K) * (n-K)).

Space Complexity = O(K* C(n, K)) (as we have total C(n, K) possible answer each having a size of K)

Possible questions by the interviewer

  • Explain the derivation of space and time complexity?
  • Why are we checking the condition end-i+1 ≥ k - ind inside the loop?
  • Draw the recursion tree for the above code.
  • Can we use this idea to solve other similar problems?
  • is there a different way to implement the above solution?
  • What are the modifications in the algorithm in case of duplicate numbers?
  • can we improve the time complexity further?

3. Recursive Backtracking — DFS Approach

Algorithm Idea

In this approach, we are using the power of DFS to recursively iterate through the range to generate all possible combinations. The iteration steps of the DFS approach is similar to the second approach we discussed above.

Here we iterate until we get a set consisting of K elements and store that subset in our resultant vector and then we backtrack and remove the previous element inserted in our temporary vector and consider further elements from the range which are not considered. This way all combinations are generated.

Algorithm Code C++

Algorithm Analysis

for loop can run for a maximum of n times with each backtrack with the maximum iteration of NcK times. i.e: overall time complexity will be O(N* C(n, K)).

Space Complexity = O(k* C(n, K))(as we have total C(n, K) possible answer each having a size of k )

Possible questions by the interviewer

  • Explain the space and time complexity?
  • Explore the best, average, and worst-case scenario?
  • The number of edge cases needs to be handled?
  • what are the modifications in the algorithm in case of duplicate numbers?

Problems for practice — Backtracking/DFS Approach

Enjoy learning, Enjoy Algorithms!

--

--