Skip to main content

Command Palette

Search for a command to run...

More problems on Recursion

Updated
3 min read

In this article we will be solving few more problems on recursion.

1) Combination sum I

class Solution {
public:

void combo(vector<vector<int>>&result, vector<int>a, vector<int>&v,int i, int n, int tot, int sum){
    if(i==n){
        if(tot==0) result.push_back(a); 
        return;
    }

if(v[i]<=tot){
a.push_back(v[i]);
combo(result,a,v,i,n,tot-v[i],sum);
a.pop_back();
}

combo(result,a,v,i+1,n,tot,sum);
}

vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<vector<int>> result;
        combo(result, {}, candidates, 0, candidates.size(), target, target);
        return result;
    }
};

2) Combination sum II

class Solution {
public:

void combo(vector<vector<int>>&result, vector<int>a, vector<int>&v,int i, int tot){

if(tot==0){ result.push_back(a); return; }

for(int j=i; j<v.size(); j++){
    if(j>i && v[j]==v[j-1]) continue;
    if(v[j]>tot) break;
    a.push_back(v[j]);
    combo(result,a,v,j+1,tot-v[j]);
    a.pop_back();
}
}

vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<vector<int>> result;
        sort(candidates.begin(),candidates.end());
        combo(result, {}, candidates, 0, target);
        return result;
    }
};

Note:

Even though we are using a function call in a for loop instead of 2 function calls, we are still following the take / not take approach.

Bcoz, in 2 calls, we take a element and call once, then remove element and call to next position.

In for loop + function call, we take a element and call once, and then remove element but for loop calls to next position.

3) Permutations of an array

[ Approach 1 ]

class Solution {
public:

    void func(vector<int>& v, vector<int> a, vector<bool> b, vector<vector<int>>& result){

        if(a.size()==v.size()){ result.push_back(a); return; }

        for(int i=0; i<v.size(); i++){
            if(! b[i]){ 
                a.push_back(v[i]); b[i]=true; 
                func(v,a,b,result); 
                a.pop_back(); b[i]=false;
            }
        }

    }

    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> result;
        func(nums, {}, vector<bool>(nums.size(), false), result);
        return result;
    }
};

[ Approach 2 ]

class Solution {
public:

    void swap(vector<int>&v, int x, int y){
        int temp=v[x];
        v[x]=v[y];
        v[y]=temp;
}


    void func(vector<int>& v, int start, vector<vector<int>>& result){
        if(start==v.size()-1){ result.push_back(v); return;}
        for(int i=start; i<v.size(); i++){
            swap(v,start,i);
            func(v,start+1,result);
            swap(v,start,i);
        }
    }

    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> result;
        func(nums, 0, result);
        return result;
    }
};

4) Combination Sum III

class Solution {
public:
  void f(vector<vector<int>>& result, vector<int> a, int i, int k, int n){
    if(k==0 || n<=0){
        if(k==0 && n==0) result.push_back(a);
        return;
    }

    for(int j=i; j<10; j++){
        a.push_back(j);
        f(result, a, j+1, k-1, n-j);
        a.pop_back();
    }
  }


    vector<vector<int>> combinationSum3(int k, int n) {
        vector<vector<int>> result; 
        f(result,{},1,k,n);
        return result;
    }
};

5) Generate Parantheses

class Solution {
public:

    void f(vector<string>& result, string a, int n, int left){
        if(n==0){result.push_back(a); return;}
        string l="(", r=")";
        if(left<n) f(result, a+l, n, left+1);
        if(left>0) f(result, a+r, n-1, left-1);
    }


    vector<string> generateParenthesis(int n) {
        vector<string> result;
        f(result,"", n, 0);
        return result;
    }
};

6) Generate Binary Strings Without Consecutive 1s

class Solution {
public:

    void f(vector<string>& result, string a, int n){
        if(n==0){result.push_back(a); return;}
        f(result, a+"0", n-1);
        if(a.back()!='1') f(result, a+"1", n-1);
    }

    vector<string> generateBinaryStrings(int n) {
        vector<string> result;
        f(result, "", n);
        return result;
    }
};

7) Sudoku Solver

class Solution {
public:

    bool isValid(vector<vector<char>>& board, int x, int y){
        for(int i=0; i<9; i++) if(board[x][i]==board[x][y] && i!=y) return false;
        for(int i=0; i<9; i++) if(board[i][y]==board[x][y] && i!=x) return false;

        int rol=(x/3)*3, col=(y/3)*3;
        for(int i=rol; i<rol+3; i++){
            for(int j=col; j<col+3; j++){
                if(board[i][j]==board[x][y] && (i!=x || j!=y)) return false;
            }
        }

        return true;
    }

    bool tryEveryBoard(vector<vector<char>>& board){
        for(int i=0; i<9; i++){
            for(int j=0; j<9; j++){
                if(board[i][j]=='.'){
                    for(char k='1'; k<='9'; k++){
                        board[i][j]=k;
                        if(isValid(board, i, j) && tryEveryBoard(board)) return true;
                        board[i][j]='.';
                    }
                    return false;
                }
            }
        }
        return true; 
    }

    void solveSudoku(vector<vector<char>>& board) {
        tryEveryBoard(board);
    }
};

Note:

1) With tryEveryBoard, we are trying all possibilities in place.

2) In tryEveryBoard, if k is valid at board[i][j], then we go further and if tryEveryBoard also returns true, which means already a solution found, we stop there and return true.

3) We return false at tryEveryBoard after every possibility, coz if there’s further chance tryEveryBoard() will be called else we stop there ( early pruning ).

4) We finally return true as we found a solution.