Showing posts with label Recursion. Show all posts
Showing posts with label Recursion. Show all posts

Thursday, September 1, 2022

interviewBit Medium: Palindrome Partitioning II

Problem Name: Palindrome Partitioning II

Problem Description: https://www.interviewbit.com/problems/palindrome-partitioning-ii/

Problem Approach used: This problem can be solved with MCM approach. You can note this when you feel the urge to partition the input String into parts (which are palindromes themselves in this case). 

Time Complexity:  O(n^2) worst-case time complexity and O(n^2) auxiliary space for memoisation.

Solution:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public class Solution {
    public int minCut(String A) {
        
        int memo[][] = new int[502][502];
        for (int i=0; i<502; i++) {
            Arrays.fill (memo[i], -1);
        }
        // i=0, j=n-1 // to ensure 2 partitions
        return palinPartition(A, 0, A.length()-1, memo);
    }
    
    int palinPartition(String A, int i, int j, int [][] memo) {
        if (i >= j) {
            return 0;
        }
        
        if (isPalindrome(A, i, j)) {
            return 0;
        }
        
        if (memo[i][j] != -1) {
            return memo[i][j];
        }
        
        int mn = Integer.MAX_VALUE;
        // k= i -> j-1
        for (int k=i; k<j; k++) {
            
            int c1 = palinPartition(A, i, k, memo);
            int c2 = palinPartition(A, k+1, j, memo);
            int temp = c1+c2+1;
            
            mn = Math.min (mn, temp);
        }
        
        return memo[i][j] = mn;
        
    }
    
    boolean isPalindrome(String s, int i, int j) {
        
        if (i >= j)
            return true;
            
        while (i<j) {
            if (s.charAt(i) != s.charAt(j)) {
                return false;
            } else {
                i++;
                j--;
            }
        }
        
        return true;
    }
}


Until Next time, Keep coding and have fun!


Love! ❤️ 
#Lets #Code

Follow us on :

https://twitter.com/ThinkAlgorithms





Tuesday, April 5, 2022

Leetcode Medium: Set Matrix Zeroes

 Problem Name: Set Matrix Zeroes

Problem Descriptionhttps://leetcode.com/problems/set-matrix-zeroes/

Problem Approach used: Its a trick problem to solve it in constant space. We've used the same, using HashSets in the below solution.

Time Complexity:  O(m*n) worst-case time complexity and O(1) auxiliary space complexity.

Solution:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// In 1 line of thought, constant space solution is ideally not possible as all possible int values can be part of the matrix, but if we can assume some sentinel value out of these (like Integer.MIN_VALUE in our case) for marking original zeroes, a solution follows.

// * Also we can use a trick to solve ths problem: marking 1st(top and left) elements of the row and column respetively, to 0.

class Solution {
    Set<Integer> toZeroRows = new HashSet<>(), toZeroColumns = new HashSet<>();
    
    public void setZeroes(int[][] matrix) {
        for (int row=0; row<matrix.length; row++) {
            for (int column=0; column<matrix[0].length; column++) {
                if (matrix[row][column] == 0) {
                    toZeroRows.add(row);
                    toZeroColumns.add(column);
                }
            }
        }
        // Print initial matrix
        printMatrix(matrix);
        
        for (int row=0; row<matrix.length; row++) {
            if (toZeroRows.contains(row)) {
                for(int columnIndex=0; columnIndex<matrix[0].length; columnIndex++) {
                    matrix[row][columnIndex] = 0;
                }
            }
        }
        
        printMatrix(matrix);
        
        for (int column=0; column<matrix[0].length; column++) {
            if (toZeroColumns.contains(column))
                for(int rowIndex=0; rowIndex<matrix.length; rowIndex++) {
                    matrix[rowIndex][column] = 0;
                }
        }
        printMatrix(matrix);
        
    }
    
    public void printMatrix(int [][] matrix) {
        for (int row = 0; row<matrix.length; row++) {
            for (int column = 0; column<matrix[0].length; column++) {
                System.out.print(" " + matrix[row][column]);
            }
            System.out.println();
        }
    }
}


Happy Coding!


Love! ❤️ 
#Lets #Code

Follow us on :

https://twitter.com/ThinkAlgorithms

Leetcode Problem: Climbing Stairs

 Problem of Today: Climbing Stairs

Problem description: https://leetcode.com/problems/climbing-stairs/

Solution Approach: Memoization

Solution: 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Solution {
    private int memo[];
    
    // Bottom-up
    public int climbStairs(int n) {
        memo = new int[n+1];
        for (int i=0; i<=n; i++) {
            memo[n] = -1;
        }
        memo[0] = 1;
        memo[1] = 1;
        for (int i=2; i<=n; i++) {
            memo[i] = memo[i-1] + memo[i-2];
        }
        
        return memo[n];
    }
}


Happy Coding!


Love! ❤️ 
#Lets #Code

Follow us on :

https://twitter.com/ThinkAlgorithms


Monday, December 6, 2021

LeetCode Medium: Generate Parentheses

Dear followers,


Tonight, I came across a nice problem for post-dinner exercise, about generating all possible valid parentheses sequences given the number of brackets to use in total.

PROBLEM LINK: https://leetcode.com/problems/generate-parentheses/

PROBLEM SOLVING APPROACH: Recursion (using Choice Diagram and Decision tree)

TIME-COMPLEXITY: O(2^n) in the worst case but the input n is given to be max 8, so very much doable :)


Here's a sample Java solution for your reference:


class Solution {
    public List<String> generateParenthesis(int n) {
        ArrayList<String> generatedParentheses = new ArrayList<>();
        genParenthesesRecur(n, n, "", generatedParentheses);
        return generatedParentheses;
    }
    
    private void genParenthesesRecur (int remOpenBrackets, int remClosingBrackets, String outputFromCaller, List<String> generatedParentheses) {
        // Base Cases
        if (remOpenBrackets < 0 || remClosingBrackets < 0)
            return;
        
        if (remClosingBrackets < remOpenBrackets) {
            return;
        }
        
        if (remOpenBrackets == 0 && remClosingBrackets == 0) {
           generatedParentheses.add(outputFromCaller);
        }
        
        // Recursive Case
        String opUsingAnOpeningBracket = outputFromCaller + "(";
        genParenthesesRecur(remOpenBrackets-1, remClosingBrackets, opUsingAnOpeningBracket, generatedParentheses);
        if (remClosingBrackets > remOpenBrackets) {
            String opUsingAClosingBracket = outputFromCaller + ")";
            genParenthesesRecur(remOpenBrackets, remClosingBrackets-1, opUsingAClosingBracket, generatedParentheses);
        }
    }
}

Thanks for Reading!

Happy Programming!!


Love! ❤️ 
#Lets #Code

Follow us on :

https://twitter.com/ThinkAlgorithms


Friday, December 3, 2021

Recursion Series: Deleting the middle element from a stack

This post marks the start point of the much awaited recursion series on Let'sCode_ =) 

We start it with a GeeksForGeeks problem : https://www.geeksforgeeks.org/delete-middle-element-stack/


Position of Middle element of all elements from top of stack (1 based):

stack.size()/2 + 1


Now, to build an effective solution we can use:

Methodology: Recursion

Time Complexity: O(n) where n is the number of elements in the stack

Space Complexity: O(n) considering the accumulation of constant space in each level of the recursive stack. O(1) if we dis-consider the stack space accumulation.


Here is one such solution:

<-- --todeletepos="" base="" case="" deletemidrecur="" int="" nteger="" printstack="" private="" return="" stack.pop="" stack.push="" stack="" static="" tack="" top="" void="">/*package whatever //do not write package name here */

import java.io.*;
import java.util.*;

class GFG {
	public static void main (String[] args) {
		System.out.println("GfG!");
		Stack<Integer> stack = new Stack<>();
		
		stack.push(6);
		stack.push(5);
		stack.push(4);
		stack.push(3);
		stack.push(2);
		stack.push(1);
		deleteMid(stack);
		
	}
	
	private static void deleteMid(Stack<Integer> stack) {
	    if (stack == null)
	        return;
	    if (stack.isEmpty())
	        return;
	        
	    int mid = stack.size()/2+1;
	    deleteMidRecur(stack, mid);
	    printStack(stack);
	}
	
	private static void deleteMidRecur (Stack<Integer> stack, int toDeletePos) {
	    if (toDeletePos == 1) {
	        // delete this element <-- base case
	        stack.pop();
	        return;
	    }
	    
	    int top = stack.pop();
	    deleteMidRecur(stack, --toDeletePos);
	    stack.push(top);
	}
	
	private static void printStack (Stack<Integer> stack) {
	    while (!stack.isEmpty()) {
	        System.out.println(stack.pop());
	    }
	}
}

IMO, such are the most efficient solutions to this problem. So share your thoughts and let me know your point of views.


Happy Coding!


Love! ❤️ 
#Lets #Code

Follow us on :

https://twitter.com/ThinkAlgorithms

 https://www.facebook.com/theAlgorithmicCoder

Sunday, August 29, 2021

LeetCode Medium: Course Schedule

 The next problem in the current coding spree was:

Problem Name: Course Schedule

Problem Descriptionhttps://leetcode.com/problems/course-schedule/

Problem Approach used: Detecting cycles on the directed graph pf dependencies using DFS to solve in O(V+E) where V is the number of courses in the input and E is the number of edges between them.

Time ComplexityO(lg n) worst-case time and O(1) auxiliary space complexity


Java Solution:


//Cycle detection

// package com.projects.cv.course_schedule;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Solution {

    // private static Logger logger = Logger.getLogger("MyLogger");
    int nodes;


    public boolean canFinish(int numCourses, int[][] prerequisites) {

        if (prerequisites == null)
            return false;
        int pL = prerequisites.length;
        nodes = numCourses;

        // Build directed graph
        Map<Integer, List<Integer>> g = new HashMap<>();
        for (int i=0; i<pL; i++) {
            if (!g.containsKey(prerequisites[i][0]))
                g.put(prerequisites[i][0], new ArrayList<>());
            g.get(prerequisites[i][0]).add(prerequisites[i][1]);
        }

        System.out.println(g);

        //Create visited to prevent re-visiting
        int visited[] = new int[numCourses];

        for (int i=0; i<numCourses; i++) {
            if (visited[i] == 0) {
                if (hasCycleDfs(g, visited, i, -1))
                    return false;
            }
        }

        return true;

    }

    private boolean hasCycleDfs( Map<Integer, List<Integer>> g, int[] visited, int n, int parent) {
        if (visited[n] == -1) {
            //current exploration path
            System.out.println("cycle found at u(" + parent + ")->v(" + n + ")");
            return true;
        }
        if (visited[n] == 1) {
            return false;
        }

        visited[n] = -1;

        if (g.get(n) == null) { // tackle bad callers
            visited[n] = 1;
            return false;
        }

        for (int neighBr : g.get(n)) {
            if (hasCycleDfs(g, visited, neighBr, n))
                return true;
        }

        visited[n] = 1;

        return false;
    }

    // public static void main(String[] args) {
    //     Solution s = new Solution();
    //     int[][] deps = {{1, 0}};
    //     s.canFinish(2, deps);
    // }

}



Love! ❤️ 
#Lets #Code

Follow us on :



https://twitter.com/ThinkAlgorithms

https://www.facebook.com/theAlgorithmicCoder

 




GeeksforGeeks Medium: Find the Number of Islands

Yesterday I solved a few hands-on coding problems using Java programming language.


I came across this easy problem(called Medium there) over GfG, to turn on the inertia:


Problem: Find the Number of Islands

Problem Descriptionhttps://practice.geeksforgeeks.org/problems/find-the-number-of-islands 

Problem Approach: DFS

Time Complexity: O(V) where v = number of cells in the input grid

One Java Solution:


// { Driver Code Starts
import java.util.*;
import java.lang.*;
import java.io.*;
class GFG
{
    public static void main(String[] args) throws IOException
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int T = Integer.parseInt(br.readLine().trim());
        while(T-->0)
        {
            String[] s = br.readLine().trim().split(" ");
            int n = Integer.parseInt(s[0]);
            int m = Integer.parseInt(s[1]);
            char[][] grid = new char[n][m];
            for(int i = 0; i < n; i++){
                String[] S = br.readLine().trim().split(" ");
                for(int j = 0; j < m; j++){
                    grid[i][j] = S[j].charAt(0);
                }
            }
            Solution obj = new Solution();
            int ans = obj.numIslands(grid);
            System.out.println(ans);
        }
    }
}// } Driver Code Ends



class Solution
{
    int r, c;
    byte[] xOffset = {1, 1, 1, 0, -1, -1, -1, 0};
    byte[] yOffset = {1, 0, -1, -1, -1, 0, 1, 1};
    
    //Function to find the number of islands.
    public int numIslands(char[][] grid)
    {
        // Code here
        r = grid.length;
        c = grid[0].length;
        
        boolean[][] visited = new boolean[r][c];
        int cnt = 0;
        for (int i=0; i<r; i++) {
            for(int j=0; j<c; j++) {
                if (grid[i][j]=='1' && !visited[i][j]) {
                    dfs(grid, visited, i, j);
                    cnt++;
                }
            }
        }
        
        return cnt;
    }
    
    private void dfs (char[][] grid, boolean[][] visited, int x, int y) {
        //input validation
        if (!valid (grid, x, y) || visited[x][y]==true) {
            return;
        }
        
        visited[x][y] = true;
        
        for (int i=0; i<8; i++) {
            int newX = x + xOffset[i];
            int newY = y + yOffset[i];
            
            if(valid(grid, newX, newY) && !visited[newX][newY]) {
                dfs(grid, visited, newX, newY);
            }
        }
    }
    
    boolean valid (char[][]grid, int x, int y) {
        if (x<0 || x>=r || y<0 || y>=c || grid[x][y] == '0'){
            return false;
        }
        return true;
    }
}



Do share your thoughts and feel free to talk about the alternatives/optimisations you feel can be done in the comment section!


Love! ❤️ 
#Lets #Code

Follow us on :

https://twitter.com/ThinkAlgorithms
 https://www.facebook.com/theAlgorithmicCoder

 

 



Sunday, February 14, 2021

HackerRank: Reverse a doubly linked list

Problem Description: https://www.hackerrank.com/challenges/reverse-a-doubly-linked-list/problem

Runtime complexity of my below code: O(n) where n is the size of the linked list.

Solution approach: Recursive

My Java Solution:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import java.io.*;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.regex.*;

public class Solution {

    static class DoublyLinkedListNode {
        public int data;
        public DoublyLinkedListNode next;
        public DoublyLinkedListNode prev;

        public DoublyLinkedListNode(int nodeData) {
            this.data = nodeData;
            this.next = null;
            this.prev = null;
        }
    }

    static class DoublyLinkedList {
        public DoublyLinkedListNode head;
        public DoublyLinkedListNode tail;

        public DoublyLinkedList() {
            this.head = null;
            this.tail = null;
        }

        public void insertNode(int nodeData) {
            DoublyLinkedListNode node = new DoublyLinkedListNode(nodeData);

            if (this.head == null) {
                this.head = node;
            } else {
                this.tail.next = node;
                node.prev = this.tail;
            }

            this.tail = node;
        }
    }

    public static void printDoublyLinkedList(DoublyLinkedListNode node, String sep, BufferedWriter bufferedWriter) throws IOException {
        while (node != null) {
            bufferedWriter.write(String.valueOf(node.data));

            node = node.next;

            if (node != null) {
                bufferedWriter.write(sep);
            }
        }
    }

    // Complete the reverse function below.

    /*
     * For your reference:
     *
     * DoublyLinkedListNode {
     *     int data;
     *     DoublyLinkedListNode next;
     *     DoublyLinkedListNode prev;
     * }
     *
     */
    static DoublyLinkedListNode reverse(DoublyLinkedListNode head) {
        return reverseRecur(head, head.next);
    }
    
    
    private static DoublyLinkedListNode reverseRecur(DoublyLinkedListNode current, DoublyLinkedListNode nextNode) { // 2, 3    3, 4   4, \0
        if (current == null)
            return current;

        if (nextNode == null && current.prev == null) {
            return current;
        }

        //Node nextNode = current.next; 2
        DoublyLinkedListNode prevNode = current.prev; // \0  1 2 3

        if (nextNode == null) {
            current.prev = null;
            return current;  // 4
        }

        //Assume reversed till current.
        DoublyLinkedListNode nextToNext = nextNode.next; // 4  \0

        // 1 <-> 2 <-> 3 <-> 4  ->   4<->3<->2<->1
        nextNode.next = current;  //4 <-> 3 <-> 2 <-> 1 -> \0
        current.prev = nextNode;
        current.next = prevNode;

        return reverseRecur(nextNode, nextToNext); // 3, 4    4, \0

    }


    private static final Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) throws IOException {
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));

        int t = scanner.nextInt();
        scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");

        for (int tItr = 0; tItr < t; tItr++) {
            DoublyLinkedList llist = new DoublyLinkedList();

            int llistCount = scanner.nextInt();
            scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");

            for (int i = 0; i < llistCount; i++) {
                int llistItem = scanner.nextInt();
                scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");

                llist.insertNode(llistItem);
            }

            DoublyLinkedListNode llist1 = reverse(llist.head);

            printDoublyLinkedList(llist1, " ", bufferedWriter);
            bufferedWriter.newLine();
        }

        bufferedWriter.close();

        scanner.close();
    }
}



Do share your thoughts below!

Until next time, Happy Coding!


Wednesday, December 30, 2020

LeetCode Easy(medium-ish): Subtree of Another Tree

Hello Peeps,

We're getting back in touch with problem solving after a long-long time. I was _really really_ busy with family functions in this break.

Yesterday, I solved this LeetCode problem Subtree of Another Tree categorised as easy on LeetCode. I would say medium would have been a more appropriate categorisation of this recursively solvable problem.


Problem link: https://leetcode.com/problems/subtree-of-another-tree/
Solution Approach: Recursion
Time Complexity: O(n) where n is the number of nodes in the tree s.
Space Complexity: O(h) where h is the height of the tree s.


Solution:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSubtree(TreeNode s, TreeNode t) {
        
        //Main logic
        boolean matchFound = false;
        
        //Base condition
        if (s == null && t == null)
            return true;

        if ((s!=null && t==null) || (s==null && t!=null))
            return false;

        if (s.val == t.val)
            matchFound = matches (s, t);

        if (!matchFound) {
            matchFound = isSubtree(s.left, t);
        }
        if (!matchFound) {
            matchFound = isSubtree(s.right, t);
        }

        return matchFound;
    }
    
    private boolean matches (TreeNode s, TreeNode t) {
        if (s==null && t==null)
            return true;
        if ((s!=null && t==null) || (s==null && t!=null))
            return false;
        if (s.val != t.val)
            return false;
        return matches(s.left, t.left) && matches(s.right, t.right);
    }
}

That's all for now!

Happy Coding!!

Tuesday, August 18, 2020

LeetCode Hard: Special Binary String

This is one Hard category problem on LeetCode.

A few things to observe in this problem are :

  1. Treating a special binary string as a string with 1 corresponding to char ‘(‘ and 0 to character ‘)’ reduces it to a valid string of properly closed parentheses.
  2. The first character of special binary strings (like the input string) has to be a 1, and the last character, a 0.
  3. The special binary string can be a concatenation of only special binary strings.
Keeping these factsin mind, here is my recursive solution to the same:
 
class Solution {
    public String makeLargestSpecial(String S) {
        
        ArrayList res = new ArrayList<>();
        
        int count = 0, st = 0;
        for (int i=0; i<S.length(); i++) {
            if (S.charAt(i) == '1')
                count++;
            else
                count--;
            if (count == 0) {
                res.add('1' + makeLargestSpecial(S.substring(st+1, i)) + '0');
                st = i+1;
            }
        }
        
        Collections.sort(res, Collections.reverseOrder());
        return String.join("", res);
        
    }
}

Let me know your thouhts in the comments below.
 
Happy Coding!

Monday, July 13, 2020

SPOJ Dynamic Programming: KNAPSACK

Today I started with solving Dynamic Programming problems and the first one on the refresher list was the classical 0/1-Knapsack.

I found an online judge, SPOJ, testing solutions to this problem here: https://www.spoj.com/problems/KNAPSACK/

Here is my accepted(https://www.spoj.com/status/KNAPSACK,chandniverma/) solution to the same:

import java.util.*;
import java.lang.*;

class Main
{
 public static void main (String[] args) throws java.lang.Exception
 {
  Scanner sc = new Scanner (System.in);
  int s = sc.nextInt();
  int n = sc.nextInt();
  
  int[] size = new int[n+1];
  long[] val = new long[n+1];
  for (int i=1; i<=n; i++) {
   size[i] = sc.nextInt();
   val[i] = sc.nextInt();
  }
  sc.close();
  
  long[][] memo = new long[n+1][s+1];
  for (int i=0; i<=n; i++) {
   for (int j=0; j<=s; j++) {
    memo[i][j] = -1;
   }
  }
  System.out.println(getMaxVal(size, val, s, n, memo));
 }

 private static long getMaxVal(int[] size, long[] val, int s, int n, long[][] memo) {
  if (n<=0 || s<=0)
   return 0;

  if (memo[n][s] != -1)
   return memo[n][s];

  if ((s-size[n]) >= 0) {
   return memo[n][s] = Math.max (
    val[n] + getMaxVal(size, val, s-size[n], n-1, memo),
    getMaxVal(size, val, s, n-1, memo)
    );
  } else {
   return memo[n][s] = getMaxVal(size, val, s, n-1, memo);
  }
 }
}
This solution works with a complexity of O(n*s) where n is the number of items under consideration and s is the size or capacity of the bag.

You can always find my SPOJ profile with solved problem list at https://www.spoj.com/users/chandniverma/.

You can also checkout my recent-most submissions at SPOJ on https://www.spoj.com/status/chandniverma/.

Feel free to share optimisations and improvisations in comments below!

See ya next time!

<3✌

Sunday, July 12, 2020

LeetCode Medium: Count Complete Tree Nodes

Here is one LeetCode Medium level problem (Problem # 222: Count Complete Tree Nodes) which is an actual 2 liner to solve when solved recursively:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int countNodes(TreeNode root) {
        if (root == null)
            return 0;
        
        return countNodes(root.left) + countNodes(root.right) + 1;
    }
}


This solution is O(n) in number of nodes in the binary tree and is a generic solution that can be used to solve any binary tree for that matter.

The fact that this is a complete binary tree, brings to my mind another solution approach with O((lg n)^2) solution which I'll share here very soon!

Until next time,

Stay Tuned and Happy Coding!
See ya later!!


LeetCode Medium: Lowest Common Ancestor of a Binary Tree

My Solution for LeetCode medium problem #236: Lowest Common Ancestor of a Binary Tree, based on tree-recursion:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null)
            return null;
        boolean leftHasP = hasDescendant(root.left, p.val);
        boolean leftHasQ = hasDescendant(root.left, q.val);
        boolean rightHasP = hasDescendant(root.right, p.val);
        boolean rightHasQ = hasDescendant(root.right, q.val);
        
        if (root.val == p.val || root.val == q.val)
            return root;
        if ((leftHasP && rightHasQ) || (leftHasQ && rightHasP))
            return root;
        if (!leftHasP && !leftHasQ)
            return lowestCommonAncestor(root.right, p, q);
        else
            return lowestCommonAncestor(root.left, p, q);
        
    }
    
    private boolean hasDescendant(TreeNode root, int val) {
        if (root == null)
            return false;
        
        if (root.val == val) {
            return true;
        }
        if (hasDescendant(root.left, val) || hasDescendant(root.right, val)) {
            return true;
        }
        
        return false;
    }
}


Feel free to share your thoughts in comments, below!

LeetCode Medium: Construct Binary Tree from Inorder and Postorder Traversal

When we are given Inorder traversal of nodes in a tree, along with 1 other traversal, either preorder or postorder,  we can derive the original tree structure from the provided information.

I have solved the following LeetCode problem with the same idea in mind. Grab a look:


Problem #106: Construct Binary Tree from Inorder and Postorder Traversal 
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        if (inorder.length == 0 || postorder.length==0)
            return null;
        TreeNode root = treeFromInorderPostorder(inorder, 0, inorder.length-1, postorder, 0, postorder.length-1);
        return root;
    }
    
    private TreeNode treeFromInorderPostorder(int[] inorder, int inStart, int inEnd, int[] postorder, int postStart, int postEnd) {
        
        int rootVal = postorder[postEnd];
        TreeNode root = new TreeNode(rootVal);
        
        int inRootIdx = inStart;
        for (int i=inStart; i<=inEnd; i++) {
            if (inorder[i]==rootVal) {
                inRootIdx = i;
                break;
            }
        }
        // assert(inRootIdx != -1);
        int nodesInLeftSubtree = inRootIdx - inStart;
        if (nodesInLeftSubtree == 0) {
            root.left = null;
        } else {
        root.left = treeFromInorderPostorder(inorder, inStart, inRootIdx-1, postorder, postStart, postStart+nodesInLeftSubtree-1);
        }
        
        int nodesInRightSubtree = inEnd - inRootIdx;
        if (nodesInRightSubtree == 0) {
            root.right = null;
        } else {
        root.right = treeFromInorderPostorder(inorder, inRootIdx+1, inEnd, postorder, postStart+nodesInLeftSubtree, postEnd-1);
        }
        
        return root;
    }
}

In the similar vein, consider a previously solved problem:

The bounds for parameters with which to make recursive calls in these problems can be slightly tricky to understand so one needs to be careful with those.
Besides that, as always, let me know in comments if you find these solutions helpful or have ideas for improvement.

Toodles!

LeetCode medium: Construct Binary Tree from Preorder and Inorder Traversal

When we are given Inorder traversal of nodes in a tree, along with 1 other traversal, either preorder or postorder,  we can derive the original tree structure from the provided information.

I have solved the following LeetCode problem with the same idea in mind:


Problem #105: LeetCode medium: Construct Binary Tree from Preorder and Inorder Traversal
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if (inorder.length == 0 || preorder.length==0)
            return null;
        TreeNode root = treeFromInorderPreorder(inorder, 0, inorder.length-1, preorder, 0, preorder.length-1);
        return root;
    }
    
    private TreeNode treeFromInorderPreorder(int[] inorder, int inStart, int inEnd, int[] preorder, int preStart, int preEnd) {
        
        int rootVal = preorder[preStart];
        TreeNode root = new TreeNode(rootVal);
        
        int inRootIdx = inStart;
        for (int i=inStart; i<=inEnd; i++) {
            if (inorder[i]==rootVal) {
                inRootIdx = i;
                break;
            }
        }
        // assert(inRootIdx != -1);
        int nodesInLeftSubtree = inRootIdx - inStart;
        if (nodesInLeftSubtree == 0) {
            root.left = null;
        } else {
        root.left = treeFromInorderPreorder(inorder, inStart, inRootIdx-1, preorder, preStart+1, preStart+1+nodesInLeftSubtree);
        }
        
        int nodesInRightSubtree = inEnd - inRootIdx;
        if (nodesInRightSubtree == 0) {
            root.right = null;
        } else {
        root.right = treeFromInorderPreorder(inorder, inRootIdx+1, inEnd, preorder, preStart+nodesInLeftSubtree+1, preEnd);
        }
        
        return root;
    }
}


In the similar vein, consider:

The bounds for parameters with which to make recursive calls can be slightly tricky to understand so one needs to be careful with those.
Besides that, as always, let me know in comments if you find these solutions helpful or have ideas for improvement.

Toodles!...

Tuesday, July 7, 2020

LeetCode: More problems on Trees

Here are my Java solutions to more problems on trees. Following are 2 related ones:


Problem #104: Maximum Depth of Binary Tree

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null)
            return 0;
        
        int lDepth = maxDepth(root.left);
        int rDepth = maxDepth(root.right);
        
        return Math.max(lDepth, rDepth)+1;
    }
}



Problem #543: Diameter of a Binary Tree

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    
    private int height(TreeNode root) {
        if (root == null)
            return -1;
        
        return Math.max(height(root.left), height(root.right)) + 1;
    }
    
    public int diameterOfBinaryTree(TreeNode root) {
        if (root == null)
            return 0;
        
        int lHeight = height(root.left);
        int rHeight = height(root.right);
        int lDiameter = diameterOfBinaryTree(root.left);
        int rDiameter = diameterOfBinaryTree(root.right);
        
        return Math.max(lHeight+rHeight+2 , Math.max(lDiameter, rDiameter));
    }
}


~~~

I plan to extend this category of posts with more related ones to come soon!

Until then,

Happy Problem Solving!!

Sunday, June 28, 2020

LeetCode Trees and Graphs: Problem #101: Symmetric Tree

The next problem on hit list is Problem #101: Symmetric Tree

Again, this can be solved using many approaches both recursively or iteratively.


Approach 1: My recursive solution with complexity O(n) where n is the total number of TreeNodes in the tree is as follows:


/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if (root == null)
            return true;
        
        if (root.left == null && root.right == null)
            return true;
        
        return isMirror (root.left, root.right);
    }
    
    private boolean isMirror(TreeNode r1, TreeNode r2) {
        if (r1 == null && r2 == null)
            return true;
        if ((r1 == null && r2 != null) || (r1 != null && r2 == null))
            return false;
        if (r1.val != r2.val)
            return false;
        
        boolean mirror = isMirror(r1.left, r2.right);
        if (mirror)
            mirror = isMirror(r1.right, r2.left);
        
        return mirror;
    }
}


Approach 2: An iterative solution approach making use of a BFS like queue insertion of node-pairs to check for equality when popped (again O(n)):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if (root == null)
            return true;
        
        if (root.left == null && root.right == null)
            return true;
        
        //iterative solution
        
        Queue<TreeNode> q = new LinkedList<>();
        q.add(root.left);
        q.add(root.right);
        while(!q.isEmpty()) {
            TreeNode n1 = q.remove();
            TreeNode n2 = q.remove();
            
            if (n1 == null && n2 == null)
                continue;
            if ((n1 == null && n2 != null) || (n1 != null && n2 == null))
                return false;
            if (n1.val != n2.val)
                return false;
            
            q.add(n1.left);
            q.add(n2.right);
            q.add(n1.right);
            q.add(n2.left);
        }
        
        return true;
    }
}

That's not all! There are definitely more approaches to it. One which I can think of is using stacks. Feel free to share your solutions for the same.

As always, you can checkout my latest accepted solutions on leetcode at https://leetcode.com/chandniverma/ . All the best!


LeetCode Trees and Graphs: Problem #100: Same Tree

Today I plan to do some problems on trees. With that, I started with Same Tree.

Here's my recursive solution of the same:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if (p == null) {
            if (q == null)
                return true;
            return false;
        } else {
            if (q == null)
                return false;
        }
        
        if (p.val != q.val)
            return false;
        
        boolean sameTree = true;
        sameTree = isSameTree(p.left, q.left);
        
        if (sameTree)
            sameTree = isSameTree(p.right, q.right);
        
        return sameTree;
    }
}

Sweet and Simple!
Happy Coding!!

Wednesday, June 24, 2020

LeetCode Medium: Binary Tree Postorder Traversal | T-Contest: Minimal Source Call for Submissions

My recursive solution for Problem #145: Binary Tree Postorder Traversal:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> values = new ArrayList<>();
        postorderTraversalRecur(root, values);
        return values;
    }
    
    void postorderTraversalRecur(TreeNode root, List<Integer> values) {
        if (root == null)
            return;
        
        postorderTraversalRecur(root.left, values);
        postorderTraversalRecur(root.right, values);
        values.add(root.val);
    }
}

I leave the iterative one for you to do as an exercise!
Let's see some solutions coming up through the remainder of June and July 2020, and the Java solution with least program-size(size of source code) will win a free t-shirt from Let's Code_ merchandise!!!

Let's Code_!!!

Saturday, June 13, 2020

LeetCode Medium: Binary Tree Inorder Traversal

Here are 2 of my accepted solution approaches (both O(n) where n is the number of nodes in the input tree) for solving the Problem #94 Binary Tree Inorder Traversal on Leetcode:

Approach 1: Simple Recursive
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> values = new ArrayList<>();
        preorderTraversalRecur(root, values);
        return values;
    }
    
    void preorderTraversalRecur(TreeNode root, List<Integer> values) {
        if (root == null)
            return;
        
        values.add(root.val);
        preorderTraversalRecur(root.left, values);
        preorderTraversalRecur(root.right, values);
    }
}

Approach 2: Iterative Stack based
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> values = new ArrayList<>();
        inorderTraversal(root, values);
        return values;
    }
    
    void inorderTraversal(TreeNode root, List<Integer> values) {
        if (root == null)
            return;
        
        inorderTraversal(root.left, values);
        values.add(root.val);
        inorderTraversal(root.right, values);
    }
}

Know of any more alternative? ..Feel free to share your code or suggestions in comments below!

Featured Post

interviewBit Medium: Palindrome Partitioning II

Problem Name:  Palindrome Partitioning II Problem Description : https://www.interviewbit.com/problems/palindrome-partitioning-ii/ Problem Ap...