having-fun-tickling-algorithms

112. Path Sum

sum: represents the remaining path sum from current node to leaf node before the current node is taken into consideration. That’s why for the leaf node, we need to do sum - root.val == 0

If there are n nodes in binary tree, maximum height of the binary tree is n-1 and minimum height is floor(log_2(n)).

For example, left skewed binary tree shown in Figure 1(a) with 5 nodes has height 5-1 = 4 and binary tree shown in Figure 1(b) with 5 nodes has height floor(log(25)) = 2.

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) return false;
        if (root.left == null && root.right == null && root.val == targetSum) return true;
        return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
    }
}

234. Palindrome Linked List

Approach 1: reverse the second half of the list, then compare with the first half

class Solution {
    public boolean isPalindrome(ListNode head) {
        if (head == null || head.next == null) return true;
        //fast and slow pointers:
        ListNode fast = head, slow = head;
        while (fast.next != null && fast.next.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        ListNode secondHalf = reverse(slow.next);
        ListNode firstHalf = head;
        //check if fast and "slow -> fast" parts are the same
        while(firstHalf != null && secondHalf != null){
            if(firstHalf.val != secondHalf.val) return false;
            secondHalf = secondHalf.next;
            firstHalf = firstHalf.next;
        }
        return true;
    }

    public ListNode reverse(ListNode head){
        ListNode newHead = null;
        while (head != null){
            ListNode next = head.next;
            head.next = newHead;
            newHead = head;
            head = next;
        }
        return newHead;
    }
}

Approach 2: Recursive

Example :
1-> 2-> 3-> 4-> 2-> 1

ref points 1 initially.
Make recursive calls until you reach the last element - 1.
On returning from each recurssion, check if it is equal to ref values.
ref values are updated to on each recurssion.
So first check is ref 1 -  end 1
Second ref 2 - second last 2 ...and so on.

class Solution {
    ListNode ref;
    public boolean isPalindrome(ListNode head) {
        ref = head;
        return check(head);
    }

    public boolean check(ListNode node){
        if(node == null) return true;
        boolean ans = check(node.next);
        boolean isEqual = (ref.val == node.val)? true : false;
        ref = ref.next;
        return ans && isEqual;
    }
}

1413. Minimum Value to Get Positive Step by Step Sum

class Solution {
    public int minStartValue(int[] nums) {
        //Return the minimum positive value of startValue such that the step by step sum is never less than 1.
        /*
        prefix sum
         Get the smallest value of all the sums starting from index 0 to nums.length - 1
         if it's negative, we get its absolute value, then plus 1
         if it's positive, we plus 1
        */
        if (nums == null) {
            throw new IllegalArgumentException("Input array is null");
        }
        int min = 0;
        int prefixSum = 0;
        for(int i = 0; i < nums.length; i ++){
            prefixSum += nums[i];
            // Find the minimum prefix sum which is <= zero, as it will help us to find the lowest negative value.
            min = Math.min(min, prefixSum);
        }
        return 1 - min;
    }
}

2068. Check Whether Two Strings are Almost Equivalent

Approach 1: using 2 arrays of 26 size

class Solution {
    public boolean checkAlmostEquivalent(String word1, String word2) {
        int[] one = new int[26];
        int[] two = new int[26];
        for(int i = 0; i < word1.length(); i ++){
            one[word1.charAt(i) - 'a'] ++;
            two[word2.charAt(i) - 'a'] ++;
        }
        for(int j = 0; j < 26; j ++){
            if (Math.abs(one[j] - two[j]) > 3){
                return false;
            }
        }
        return true;
    }
}

Approach 2: HashMap

 public boolean checkAlmostEquivalent(String word1, String word2) {
        Map<Character, Integer> map = new HashMap<>();
        for(int i = 0; i < word1.length(); i ++){
            map.put(word1.charAt(i), map.getOrDefault(word1.charAt(i), 0) + 1);
            map.put(word2.charAt(i), map.getOrDefault(word2.charAt(i), 0) - 1);
        }
        for(int v: map.values()){
            if (Math.abs(v) > 3){
                return false;
            }
        }
        return true;
}

70. Climbing Stairs

Approach 1: Dynamic Programming

Base cases:

 public int climbStairs(int n) {
        int[] dp = new int[n+1];
        if (n == 0) return 0;
        if (n == 1) return 1;
        if (n == 2) return 2;

        dp[1] = 1;
        dp[2] = 2;
        for(int i = 3; i <= n; i ++){
            dp[i] = dp[i-1] + dp[i-2];
        }
        return dp[n];
    }

509. Fibonacci Number

Approach 1: DP

base case: F(0) = 0, F(1) = 1

dp[i] = dp[i-1] + dp[i-2];

 public int fib(int n) {
        if (n == 0) return 0;
        if (n == 1) return 1;
        if (n == 2) return 1;
        int[] dp = new int[n+1];
        dp[0] = 0;
        dp[1] = 1;
        for(int i = 2; i <= n; i ++){
            dp[i] = dp[i-1] + dp[i-2];
        }
        return dp[n];
    }

Approach 2: Iterative

        if(N <= 1) return N;
		int a = 0, b = 1;
		while(N-- > 1){
			int sum = a + b;
			a = b;
			b = sum;
		}
        return b;

Approach 3: Recursive

else, return fib(N - 1) + fib(N - 2)

public int fib(int N){
        if(N <= 1) return N;
        else
            return fib(N - 1) + fib(N - 2);
}

58. Length of Last Word

Approach 1: Stack

class Solution {
    public int lengthOfLastWord(String s) {
       Stack<String> stack = new Stack<>();

        for(String word:s.split(" ")){
            stack.push(word);
        }
        return stack.pop().length();
    }
}

Approach 2: loop from the back

class Solution {
    public int lengthOfLastWord(String s) {
        int length = 0;
        for (int i = s.length() - 1; i >= 0; i --){
            if (s.charAt(i) != ' '){
                length ++;
            }else{
                if (length > 0){
                    return length;
                }
            }
        }

        return length;
    }
}

2273. Find Resultant Array After Removing Anagrams

Approach 1: sorting

class Solution {
    public List<String> removeAnagrams(String[] words) {
       List<String> list = new ArrayList<>();
       String prev = "";
       for(int i = 0; i < words.length; i++){
           char[] ch = words[i].toCharArray();
           Arrays.sort(ch);
           String curr = new String(ch);
           if (!curr.equals(prev)){
               list.add(words[i]);
               prev = curr;
           }
       }
       return list;
    }
}

Array of Array Products

Given an array of integers arr, you’re asked to calculate for each index i the product of all integers except the integer at that index (i.e. except arr[i]). Implement a function arrayOfArrayProducts that takes an array of integers and returns an array of the products.

Solve without using division and analyze your solution’s time and space complexities.

Examples:

input:  arr = [8, 10, 2]
output: [20, 16, 80] # by calculating: [10*2, 8*2, 8*10]

input:  arr = [2, 7, 3, 4]
output: [84, 24, 56, 42] # by calculating: [7*3*4, 2*3*4, 2*7*4, 2*7*3]
 static int[] arrayOfArrayProducts(int[] arr) {
    // your code goes here
    /*
    0---> i - 1 product

    i + 1 --> arr.length - 1

    */
    if (arr.length == 0){
      return arr;
    }
    if (arr.length == 1) {
      return new int[0];
    }
    int[] result = new int[arr.length];
    int product1 = 1;
    result[0] = 1;
    for(int i = 1; i < arr.length; i ++){
       product1 *= arr[i-1];
       result[i] = product1;
    }
    int product2 = 1;
    for(int i = arr.length - 2; i >= 0; i--){
       product2 *= arr[i + 1];
       result[i]*=product2;
    }
    return result;
  }

Approach 1:


##

Approach 1:


##

Approach 1:


##

Approach 1:


##

Approach 1:


##

Approach 1:


Approach 1:


##

Approach 1:


##

Approach 1:


##

Approach 1:


##

Approach 1:


##

Approach 1:


##

Approach 1:


##

Approach 1:


##

Approach 1:


##

Approach 1:


##

Approach 1: