Skip to content

aa25g15/DSA-Java-Medium

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 

Repository files navigation

Leetcode DSA in Java

https://neetcode.io/practice

MEDIUM

You got to remember this only since this has a simple concept but confusing implementation with difficult to handle edge cases.

public ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode start = new ListNode(0);
    ListNode slow = start;
    ListNode fast = start;
    start.next = head;

    for(int i = 0; i <= n; i++ ) {
        fast = fast.next;
    }

    while(fast != null) {
        fast = fast.next;
        slow = slow.next;
    }

    // Delete the node
    slow.next = slow.next.next;

    return start.next;
}

Implementation using stack:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        Stack<ListNode> stack = new Stack<>();

        ListNode currentNode = head;
        while(currentNode != null){
            stack.push(currentNode);
            currentNode = currentNode.next;
        }

        // Boundary cases
        if(n == stack.size()){
            return head.next;
        }

        if(n == 1){
            stack.pop();
            ListNode beforeNthNode = stack.peek();
            beforeNthNode.next = null;
            return head;
        }

        for(int i = 0; i < n - 2; i++){
            stack.pop();
        }
        
        ListNode afterNthNode = stack.pop();
        ListNode nthNode = stack.pop();
        ListNode beforeNthNode = stack.pop();

        beforeNthNode.next = afterNthNode;

        return head;
    }
}

My own solution:

class Solution {
    public int totalFruit(int[] fruits) {
        return collectFruitsAroundATree(0, fruits, 0);
    }

    private int collectFruitsAroundATree(int index, int[] fruits, int maxCollected) {
        if(index > fruits.length - 1) return maxCollected;

        int fruitBasket1Type = -1;
        int fruitBasket2Type = -1;
        int currentCollected = 0;

        int i = index;

        // look back first
        while(i >= 0){
            if(fruitBasket1Type == -1 || fruitBasket1Type == fruits[i]){
                fruitBasket1Type = fruits[i--];
                currentCollected++;
            } else if(fruitBasket2Type == -1 || fruitBasket2Type == fruits[i]) {
                fruitBasket2Type = fruits[i--];
                currentCollected++;
            } else {
                // fruit cannot go in any basket!
                break;
            }
        }

        int j = index + 1;

        // look ahead later
        while(j < fruits.length){
            if(fruitBasket1Type == -1 || fruitBasket1Type == fruits[j]){
                fruitBasket1Type = fruits[j++];
                currentCollected++;
            } else if(fruitBasket2Type == -1 || fruitBasket2Type == fruits[j]) {
                fruitBasket2Type = fruits[j++];
                currentCollected++;
            } else {
                // fruit cannot go in any basket!
                break;
            }
        }

        return collectFruitsAroundATree(j, fruits, Math.max(maxCollected, currentCollected));
    }
}

2 pointers:

class Solution {
    public int maxArea(int[] height) {
        int leftPointer = 0;
        int rightPointer = height.length - 1;
        int maxVolume = 0;

        while(leftPointer < rightPointer) {
            int currentVolume = Math.min(height[leftPointer], height[rightPointer]) * 
            (rightPointer - leftPointer);
            maxVolume = Math.max(maxVolume, currentVolume);
            
            if(height[leftPointer] < height[rightPointer]){
                leftPointer++;
            } else {
                rightPointer--;
            }
        }

        return maxVolume;
    }
}

Stack:

class MinStack {
    LinkedList<Integer> list = new LinkedList<Integer>();
    LinkedList<Integer> minList = new LinkedList<Integer>();
    int size = 0;
    
    public void push(int val) {
        list.push(val);
        size++;
        // we will track the minimum value for each push operation
        minList.push(Math.min(minList.size() == 0 ? Integer.MAX_VALUE : minList.peek(), val));
    }
    
    public void pop() {
        if(size == 0) return;

        list.pop();
        size--;

        minList.pop();
    }
    
    public int top() {
        return list.peek();
    }
    
    public int getMin() {
        return minList.peek();
    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(val);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */

Backtracking:

class Solution {
    public boolean exist(char[][] board, String word) {
        for(int i = 0; i < board.length; i++){
            for(int j = 0; j < board[0].length; j++){
                if(explore(board, word, i, j, 0)){
                    return true;   
                }
            }
        }
        
        return false;
    }
    
    private boolean explore(char[][] board, String word, int row, int col, int index){
        if(
            row < 0 ||
            row > board.length - 1 ||
            col < 0 ||
            col > board[0].length - 1 ||
            index > word.length() - 1
        ) {
            // out of bounds
            return false;
        }
        
        if(board[row][col] == word.charAt(index)) {
            // check if this is the last index
            if(index == word.length() - 1){
                return true;
            }
            
            char val = board[row][col];
            board[row][col] = '-';
            
            // Explore all directions since we have a match on this node and
            // return true if any direction matches
            if(
                explore(board, word, row - 1, col, index + 1) || // up
                explore(board, word, row + 1, col, index + 1) || // down
                explore(board, word, row, col - 1, index + 1) || // left
                explore(board, word, row, col + 1, index + 1) // right
            ) {
                return true;
            } else {
                board[row][col] = val;
            }
        }
        
        return false;
    }
}
class Solution {
    public int orangesRotting(int[][] grid) {
        int timePassed = -1;
        int freshOranges = 0;
        Queue<int[]> rottenOranges = new LinkedList<int[]>();

        for(int row = 0; row < grid.length; row++){
            for(int col = 0; col < grid[0].length; col++){
                if(grid[row][col] == 2){
                    rottenOranges.add(new int[]{row, col});
                } else if (grid[row][col] == 1) {
                    freshOranges++;
                }
            }
        }

        if(freshOranges == 0) return 0; // All rotten
        if(rottenOranges.size() == 0) return -1; // All fresh

        while(rottenOranges.size() != 0) {
            timePassed++;
            int size = rottenOranges.size();

            for(int i = 0; i < size; i++){
                int[] currentOrange = rottenOranges.remove();
                int row = currentOrange[0];
                int col = currentOrange[1];

                // All surrounding will rot, add to queue
                if(row - 1 >= 0 && grid[row - 1][col] == 1){
                    rottenOranges.add(new int[]{row - 1, col});
                    grid[row - 1][col] = 2; // rotten
                    freshOranges--;
                }
                if(row + 1 < grid.length && grid[row + 1][col] == 1){
                    rottenOranges.add(new int[]{row + 1, col});
                    grid[row + 1][col] = 2; // rotten
                    freshOranges--;
                }
                if(col - 1 >= 0 && grid[row][col - 1] == 1){
                    rottenOranges.add(new int[]{row, col - 1});
                    grid[row][col - 1] = 2; // rotten
                    freshOranges--;
                }
                if(col + 1 < grid[0].length && grid[row][col + 1] == 1){
                    rottenOranges.add(new int[]{row, col + 1});
                    grid[row][col + 1] = 2; // rotten
                    freshOranges--;
                }
            }
        }

        return freshOranges > 0 ? -1 : timePassed;
    }
}

7. Combination Sum (Can Reuse Element) - https://leetcode.com/problems/combination-sum/description/

class Solution {
    List<List<Integer>> solList = new LinkedList<>();

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        // Arrays.sort(candidates);
        generateCombs(candidates, target, 0, new LinkedList<Integer>(), 0, 0);
        return this.solList;
    }

    private void generateCombs(
        int[] candidates, 
        int target, 
        int sum, 
        LinkedList<Integer> sol, 
        int index,
        int numCombs
    ){
        if(numCombs >= 150 || sum > target){
            return;
        }
        
        if(sum == target){
            this.solList.add(new LinkedList<>(sol));
        }

        for(int i = index; i < candidates.length; i++){
            sol.push(candidates[i]);
            generateCombs(candidates, target, sum + candidates[i], sol, i, numCombs + 1);
            sol.pop();
        }
    }
}

8. Combination Sum (Can’t Reuse Element) - https://leetcode.com/problems/combination-sum-ii/description/

class Solution {
    private List<List<Integer>> resultList = new LinkedList<List<Integer>>();

    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        generateCombs(
            candidates,
            target,
            0,
            0,
            new LinkedList<Integer>()
        );
        return this.resultList;
    }

    private void generateCombs(
        int[] candidates,
        int target,
        int currentSum,
        int start,
        LinkedList<Integer> tempList
    ){
        if(currentSum > target) return; // invalid situation
        if(currentSum == target) this.resultList.add(new LinkedList<Integer>(tempList));

        for(int i = start; i < candidates.length; i++) {
            if(i > start && candidates[i] == candidates[i - 1]) continue; // No duplicates

            tempList.add(candidates[i]);

            generateCombs(
                candidates,
                target,
                currentSum + candidates[i],
                i + 1,
                tempList
            );

            tempList.removeLast();
        }
    }
}

9. Permutations of Number Array (Without Duplicates) - https://leetcode.com/problems/permutations/description/

class Solution {
    List<List<Integer>> solList = new LinkedList<>();

    public List<List<Integer>> permute(int[] nums) {
        generatePerms(nums, new HashSet<Integer>(), new LinkedList<>());
        return this.solList;
    }

    private void generatePerms(int[] nums, HashSet<Integer> set, LinkedList<Integer> sol){
        if(set.size() == nums.length){
            this.solList.add(new LinkedList<Integer>(sol));
            return;
        }
        for(int i = 0; i < nums.length; i++){
            if(set.contains(nums[i])) continue; // Candidate considered
            set.add(nums[i]);
            sol.push(nums[i]);
            generatePerms(nums, set, sol);
            set.remove(nums[i]);
            sol.pop();
        }
    }
}

10. Permutations of Number Array (With Duplicates) - https://leetcode.com/problems/permutations-ii/description/

class Solution {
    List<List<Integer>> resultList = new LinkedList<List<Integer>>();

    public List<List<Integer>> permuteUnique(int[] nums) {
        Arrays.sort(nums);
        generatePerms(nums, new LinkedList<Integer>(), new boolean[nums.length]);
        return resultList;
    }

    private void generatePerms(
        int[] nums,
        LinkedList<Integer> result,
        boolean[] used
        ) {
        if(result.size() == nums.length){
            this.resultList.add(new LinkedList(result));
            return; // we are done now, backtrack
        }

        for(int i = 0; i < nums.length; i++){
            if(used[i] || (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])) continue;

            result.add(nums[i]);
            used[i] = true;
            generatePerms(nums, result, used);

            // backtrack cleanup step
            result.removeLast();
            used[i] = false;
        }
    }
}

11. Subsets of Number Array (Without Duplicates) - https://leetcode.com/problems/subsets/description/

class Solution {
    List<List<Integer>> solList = new LinkedList<>();

    public List<List<Integer>> subsets(int[] nums) {
        generateSubsets(nums, 0, new LinkedList<Integer>());
        return this.solList;
    }

    private void generateSubsets(int[] nums, int start, LinkedList<Integer> sol) {
        this.solList.add(new LinkedList<>(sol));

        for(int i = start; i < nums.length; i++){
            sol.push(nums[i]);
            generateSubsets(nums, i + 1, sol);
            sol.pop();
        }
    }
}

12. Subsets of Number Array (With Duplicates) - https://leetcode.com/problems/subsets-ii/description/

class Solution {
    List<List<Integer>> solList = new LinkedList<>();

    public List<List<Integer>> subsetsWithDup(int[] nums) {
        Arrays.sort(nums);
        generateSubsets(nums, 0, new LinkedList<Integer>());
        return this.solList;
    }

    private void generateSubsets(int[] nums, int start, LinkedList<Integer> sol){
        this.solList.add(new LinkedList<>(sol));

        for(int i = start; i < nums.length; i++){
            if(i > start && nums[i - 1] == nums[i]) continue;
            sol.push(nums[i]);
            generateSubsets(nums, i + 1, sol);
            sol.pop();
        }
    }
}
class Solution {
    List<List<String>> resultList = new LinkedList<List<String>>();

    public List<List<String>> partition(String s) {
        generatePartitions(s, new LinkedList<String>(), 0);

        return this.resultList;
    }

    private void generatePartitions(
        String s,
        LinkedList<String> result,
        int start
    ) {
        if(start == s.length()){
            this.resultList.add(new LinkedList<String>(result));
        } else {
            for(int i = start; i < s.length(); i++) {
                if(this.checkPalindrome(s, start, i)) {
                    result.add(s.substring(start, i + 1));
                    generatePartitions(s, result, i + 1);

                    // backtrack cleanup
                    result.removeLast();
                }
            }
        }
    }

    private boolean checkPalindrome(String s, int low, int high) {
        while(low < high){
            if(s.charAt(low++) != s.charAt(high--)) return false;
        }
        return true;
    }
}
/**
 * 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 {
    List<List<Integer>> solList = new ArrayList<List<Integer>>();

    public List<List<Integer>> levelOrder(TreeNode root) {
        if(root == null) return this.solList;

        traverse(root, 1);
        return this.solList;
    }

    public void traverse(TreeNode node, int level){
        if(this.solList.size() < level){
            // this level has not been reached yet
            this.solList.add(new LinkedList<Integer>());
        }
        this.solList.get(level - 1).add(node.val);

        if(node.left != null) traverse(node.left, level + 1);
        if(node.right != null) traverse(node.right, level + 1);
    }
}
/**
 * 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 isValidBST(TreeNode root) {
        return validateAtNode(root);
    }

    private boolean validateAtNode(TreeNode node){
        if(node != null){
            if(
                checkLeftNodes(node.left, node.val) &&
                checkRightNodes(node.right, node.val)
            ){
                // Tree is valid till now, go deeper
                return validateAtNode(node.left) && validateAtNode(node.right);
            } else {
                return false;
            }
        }
        return true;
    }

    private boolean checkLeftNodes(TreeNode node, int val){
        if(node != null){
            return node.val < val && 
            checkLeftNodes(node.left, val) && 
            checkLeftNodes(node.right, val);
        }
        return true;
    }

    private boolean checkRightNodes(TreeNode node, int val){
        if(node != null){
            return node.val > val && 
            checkRightNodes(node.left, val) && 
            checkRightNodes(node.right, val);
        }
        return true;
    }
}

Couldn't Solve!

Couldn't Solve!

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public void reorderList(ListNode head) {
        ArrayList<ListNode> list = new ArrayList<ListNode>();

        ListNode currentNode = head;
        while(currentNode.next != null){
            list.add(currentNode);
            currentNode = currentNode.next;
        }
        list.add(currentNode);

        int startIndex = 0;
        int endIndex = list.size() - 1;
        while(startIndex < endIndex){
            ListNode startNode = list.get(startIndex);
            ListNode endNode = list.get(endIndex);
            startNode.next = endNode;
            startIndex++;
            endIndex--;
            if(startIndex < endIndex){
                endNode.next = list.get(startIndex);
            } else if(startIndex == endIndex) {
                endNode.next = list.get(startIndex);
                endNode.next.next = null;
            } else {
                endNode.next = null;
            }
        }
    }
}
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        HashMap<Integer, Integer> frequencyMap = new HashMap<>();
        int maxFrequency = 0;

        for(int i = 0; i < nums.length; i++){
            if(frequencyMap.containsKey(nums[i])){
                int frequency = frequencyMap.get(nums[i]);
                frequencyMap.put(nums[i], frequency + 1);
                maxFrequency = Math.max(frequency + 1, maxFrequency);
            } else {
                frequencyMap.put(nums[i], 1);
                maxFrequency = Math.max(1, maxFrequency);
            }
        }

        List<LinkedList<Integer>> frequencyBuckets = 
        new ArrayList<LinkedList<Integer>>(maxFrequency);

       for(int i = 0; i < maxFrequency; i++){
           frequencyBuckets.add(new LinkedList<Integer>());
       }

        frequencyMap.forEach((num, frequency) -> {
            frequencyBuckets.get(frequency - 1).add(num);
        });

        // return top k
        int[] sol = new int[k];
        int added = 0;
        int bucketIndex = frequencyBuckets.size() - 1;

        while(added < k && bucketIndex >= 0){
            ListIterator<Integer> iterator = frequencyBuckets.get(bucketIndex).listIterator();

            while(iterator.hasNext() && added < k){
                sol[added] = iterator.next();
                added++;
            }
            bucketIndex--;
        }

        return sol;
    }
}
class Solution {
    public int lengthOfLongestSubstring(String s) {
        // Sliding window approach
        int start = 0;
        int end = 0;
        HashSet<Character> window = new HashSet<>();
        int maxLength = 0;
        
        while(end < s.length()){
            if(window.contains(s.charAt(end))){
                // window shrinking
                window.remove(s.charAt(start++));
            } else {
                // window growing
                window.add(s.charAt(end++));
                maxLength = Math.max(window.size(), maxLength);
                System.out.println(maxLength);
            }
        }

        return maxLength;
    }
}

Using Arrays.sort():

import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.Arrays;

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {      
        Map<String, List<String>> solMap = new HashMap<>(strs.length);
        
        for(int i = 0; i < strs.length; i++){            
            String key = generateKey(strs[i]);
            if(solMap.containsKey(key)){
                solMap.get(key).add(strs[i]);
            } else {
                List<String> groupedList = new ArrayList<>();
                groupedList.add(strs[i]);
                solMap.put(key, groupedList);
            }
        }
        return new ArrayList<>(solMap.values());
    }
    
    public String generateKey(String string){
        if(string.length() == 0){ return string; }
        
        char[] charArray = string.toCharArray();
        Arrays.sort(charArray);
        return String.valueOf(charArray);
    }
}

Without using Arrays.sort():

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        HashMap<String, LinkedList<String>> map = new HashMap<>();

        for(int i = 0; i < strs.length; i++){
            int[] chars = new int[26];
            for(int j = 0; j < strs[i].length(); j++){
                chars[(int)(strs[i].charAt(j) - 'a')]++;
            }
            StringBuilder sb = new StringBuilder();
            for(int k = 0; k < chars.length; k++){
                sb.append(String.valueOf(chars[k]));
                sb.append(",");
            }
            String key = sb.toString();

            if(map.containsKey(key)){
                map.get(key).add(strs[i]);
            } else {
                LinkedList<String> newList = new LinkedList<>();
                newList.add(strs[i]);
                map.put(key, newList);
            }
        }

        List<List<String>> solList = new LinkedList<>();
        map.forEach((key, value) -> {
            solList.add(value);
        });

        return solList;
    }
}

Could'nt Solve!

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        return solve(nums, 0);
    }

    private List<List<Integer>> solve(int[] nums, int target){
        HashSet<List<Integer>> set = new HashSet<>();
        Arrays.sort(nums);

        for(int i = 0; i < nums.length - 2; i++){
            int j = i + 1;
            int k = nums.length - 1;

            while(j < k){
                int sum = nums[i] + nums[j] + nums[k];

                if(sum == target){
                    List<Integer> sol = new LinkedList<>();
                    sol.add(nums[i]);
                    sol.add(nums[j++]);
                    sol.add(nums[k--]);
                    set.add(sol);
                    continue;
                }

                if(sum < target){
                    // We are less than target, array is sorted, we need to increase sum
                    j++;
                    continue;
                }

                if(sum > target){
                    // We are more than target, array is sorted, we need to reduce sum
                    k--;
                }
            }
        }

        return new ArrayList<>(set);
    }
}
  • Find land starting location
  • Increment numIslands
  • Then, recursively mark all the touching land locations by assigning '-'
  • Continue traversing the grid
class Solution {
    int solution = 0;

    public int numIslands(char[][] grid) {
        for(int row = 0; row < grid.length; row++){
            for(int col = 0; col < grid[0].length; col++){
                if(grid[row][col] == '1'){
                    // Found the starting of an island
                    this.solution++;
                    // Mark the territory as explored
                    this.exploreIsland(grid, row, col);
                }
            }
        }
        return this.solution;
    }

    private void exploreIsland(char[][] grid, int row, int col){
        if(
            row < 0 ||
            col < 0 ||
            row > grid.length - 1 ||
            col > grid[0].length - 1
        ){
            // Out of bounds
            return;
        }
        if(grid[row][col] != '1'){
            // This is not a land, return
            return;
        }
        grid[row][col] = '-'; // Visited
        
        exploreIsland(grid, row - 1, col); // top
        exploreIsland(grid, row + 1, col); // bottom
        exploreIsland(grid, row, col - 1); // left
        exploreIsland(grid, row, col + 1); // top
    }
}
  • Concept - Remember inorder traversal of a BST is always sorted!
/**
 * 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 {
    List<Integer> traversalList = new LinkedList<>();

    public int kthSmallest(TreeNode root, int k) {
        this.inorderTraversal(root);
        
        int counter = 0;
        ListIterator<Integer> iterator = this.traversalList.listIterator();
        while (iterator.hasNext()){
            if(counter == k - 1){
                break;
            }
            counter++;
            iterator.next();
        }
        return iterator.next();
    }

    private void inorderTraversal(TreeNode node){
        if(node == null){
            return;
        }

        // Left, Node, Right
        inorderTraversal(node.left);
        this.traversalList.add(node.val);
        inorderTraversal(node.right);
    }
}

You need to remember this question. I am unable to understand it.

/**
 * 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 {
    int iterations = 0;

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < inorder.length; i++){
            map.put(inorder[i], i);
        }
        return createNodes(0, preorder.length - 1, preorder, inorder, map);
    }

    private TreeNode createNodes(int preStart, int preEnd, int[] preorder, int[] inorder, HashMap<Integer, Integer> map){
        if(preStart > preEnd || this.iterations > preorder.length - 1){
            return null;
        }

        int indexInorder = map.get(preorder[this.iterations]);
        TreeNode node = new TreeNode(preorder[this.iterations]);

        this.iterations++;

        node.left = createNodes(preStart, indexInorder - 1, preorder, inorder, map);
        node.right = createNodes(indexInorder + 1, preEnd, preorder, inorder, map);

        return node;
    }
}
  • Simply use a heap and poll elements
class Solution {
    public int findKthLargest(int[] nums, int k) {
        PriorityQueue<Integer> maxHeap = new PriorityQueue<>(nums.length, Comparator.reverseOrder());

        for(int i = 0; i < nums.length; i++){
            maxHeap.add(nums[i]);
        }

        for(int j = 0; j < k - 1; j++){
            maxHeap.poll(); // Remember poll is faster than remove if you want to remove the root element everytime
        }

        return maxHeap.peek();
    }
}
  • Check row uniqueness with a set
  • Check col uniqueness with a set
  • Check region uniqueness with a set
class Solution {
    public boolean isValidSudoku(char[][] board) {
        for(int row = 0; row < board.length; row++){
            if(!this.checkRow(board, row)) return false;
        }

        for(int col = 0; col < board[0].length; col++){
            if(!this.checkCol(board, col)) return false;
        }

        return (
            this.checkSection(board, 0, 2, 0, 2) &&
            this.checkSection(board, 3, 5, 0, 2) &&
            this.checkSection(board, 6, 8, 0, 2) &&
            this.checkSection(board, 0, 2, 3, 5) &&
            this.checkSection(board, 3, 5, 3, 5) &&
            this.checkSection(board, 6, 8, 3, 5) &&
            this.checkSection(board, 0, 2, 6, 8) &&
            this.checkSection(board, 3, 5, 6, 8) &&
            this.checkSection(board, 6, 8, 6, 8)
        );
    }

    private boolean checkRow(char[][] board, int row){
        HashSet<Character> set = new HashSet<>();
        for(int i = 0; i < board[row].length; i++){
            if(!checkChar(board[row][i])){
                continue;
            }
            if(set.contains(board[row][i])){
                // Repeated
                return false;
            }
            set.add(board[row][i]);
        }
        return true;
    }

    private boolean checkCol(char[][] board, int col){
        HashSet<Character> set = new HashSet<>();
        for(int i = 0; i < board.length; i++){
            if(!checkChar(board[i][col])){
                continue;
            }
            if(set.contains(board[i][col])){
                // Repeated
                return false;
            }
            set.add(board[i][col]);
        }
        return true;
    }

    private boolean checkSection(char[][] board, int rowStart, int rowEnd, int colStart, int colEnd){
        HashSet<Character> set = new HashSet<>();
        for(int i = rowStart; i <= rowEnd; i++){
            for(int j = colStart; j <= colEnd; j++){
                if(!checkChar(board[i][j])){
                    continue;
                }
                if(set.contains(board[i][j])){
                    // Repeated
                    return false;
                }
                set.add(board[i][j]);
                }
        }
        return true;
    }

    private boolean checkChar(char c){
        if(c >= '1' && c <= '9'){
            return true;
        }
        return false;
    }
}

One of those questions which you have to remember.

  • Populate res array with product of all elements before position i during pass from left to right
  • On another pass from right to left, multiply the value in res at position i with product of all elements after i
class Solution {
    public int[] productExceptSelf(int[] nums) {
        int[] res = new int[nums.length];

        // Pre-Product
        int preProduct = 1;
        for(int i = 0; i < nums.length; i++){
            res[i] = preProduct;
            preProduct *= nums[i];
        }

        // Post-Product
        int postProduct = 1;
        for(int j = nums.length - 1; j >= 0; j--){
            res[j] *= postProduct;
            postProduct *= nums[j];
        }

        return res;
    }
}
class Solution {
    public int longestConsecutive(int[] nums) {
        if(nums.length == 0) return 0;

        HashMap<Integer, Integer> map = new HashMap<>();
        int max = 1;

        for(int i = 0; i < nums.length; i++){
            map.put(nums[i], i);
        }

        for(int i = 0; i < nums.length; i++){
            max = Math.max(findLongest(nums[i], map, nums), max);
        }

        return max;
    }

    private int findLongest(int num, HashMap<Integer, Integer> map, int[] nums){
        int current = num;
        int sol = 0;
        // Search forward
        while(map.containsKey(current)){
            nums[map.get(current)] = Integer.MIN_VALUE;
            sol++;
            current++;
            if(sol == map.size()) return sol;
        }
        // Search backward
        current = num - 1;
        while(map.containsKey(current)){
            nums[map.get(current)] = Integer.MIN_VALUE;
            sol++;
            current--;
            if(sol == map.size()) return sol;
        }
        return sol;
    }
}
class Solution {
    public int[][] merge(int[][] intervals) {
        ArrayList<int[]> solList = new ArrayList<>();
        Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
        
        int i = 0;
        int j = 0;
        int[] sol = new int[2];
        while(j < intervals.length){
            sol[0] = intervals[i][0];
            sol[1] = Math.max(intervals[j][1], sol[1]);
            if(j < intervals.length - 1 && sol[1] >= intervals[j + 1][0]){
                // Merging intervals
                j++;
            } else {
                // Mutually exclusive intervals
                solList.add(sol);
                sol = new int[2];
                j++;
                i = j;
            }
        }
        return solList.toArray(new int[solList.size()][]);
    }
}
class Solution {
    public int[][] insert(int[][] intervals, int[] newInterval) {
        int[][] intervals2 = new int[intervals.length + 1][];
        ArrayList<int[]> solList = new ArrayList<>();

        // Insert new interval in the right starting place
        int i = 0;
        int j = 0;
        boolean inserted = false;
        while(i < intervals.length){
            if(!inserted && newInterval[0] < intervals[i][0]){
                intervals2[j++] = newInterval;
                inserted = true;
            } else {
                intervals2[j++] = intervals[i++];
            }
        }
        if(!inserted){
            // Will be inserted in the end
            intervals2[intervals2.length - 1] = newInterval;
        }

        merge(solList, intervals2);
        return solList.toArray(new int[solList.size()][]);
    }

    private void merge(ArrayList<int[]> solList, int[][] intervals2){
        int i = 0;
        int j = 0;
        int[] sol = new int[2];
        
        while(j < intervals2.length){
            sol[0] = intervals2[i][0];
            sol[1] = Math.max(intervals2[j][1], sol[1]);
            
            if(j < intervals2.length - 1 && sol[1] >= intervals2[j + 1][0]){
                // merge
                j++;
            } else {
                // mutually independent
                solList.add(sol);
                sol = new int[2];
                j++;
                i = j;
            }
        }
    }
}
class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
        return calculateIntervals(intervals);
    }

    private int calculateIntervals(int[][] intervals){
        int i = 0;
        int j = 0;
        int[] tempInterval = new int[2];
        int sol = 0;
        tempInterval[0] = intervals[i][0];
        tempInterval[1] = intervals[j][1];
        while(j < intervals.length){
            tempInterval[0] = intervals[i][0];
            tempInterval[1] = Math.min(intervals[j][1], tempInterval[1]);
            if(j < intervals.length - 1 && tempInterval[1] > intervals[j + 1][0]){
                // merge
                j++;
                sol++;
            } else {
                j++;
                i = j;
                tempInterval = new int[2];
                if(j < intervals.length){
                    tempInterval[0] = intervals[i][0];
                    tempInterval[1] = intervals[j][1];
                }
            }
        }
        return sol;
    }
}
class Solution {
    public int maxSubArray(int[] nums) {
        int sum = 0;
        int max = Integer.MIN_VALUE;
        
        for(int i = 0; i < nums.length; i++){
            sum += nums[i];
            max = Math.max(sum, max);
            if(sum < 0){
                sum = 0;
            }
        }

        return max;
    }
}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published