Leetcode Templates

 
    public int search(int[] nums, int target) {
        if(nums == null || nums.length == 0){
            return -1;
        }
        int left =0, right = nums.length;
        while(left < right){
            int middle = left + (right - left)/2;
            if(nums[middle] == target) return middle; //f(x)
            if(nums[middle] > target){ // g(x)
                right = middle;
            } else{
                left = middle + 1;
            }
        }
        // left is the smallest index which satisfice g(x)
        // in this case, left is upper bond
        return -1;
    }

Sliding Window (Two pointers)

public int lengthOfLongestSubstringKDistinct(String s, int k) {
        if(s == null || s.length() == 0){
            return 0;
        }
        int start = 0, end = 0;
        int count = 0, max = 0;
        int[] charMap = new int[128];
        while(end < s.length()){
            // increase end pointer and count for char at end
            if(charMap[s.charAt(end++)]++ == 0){
                count++;
            }
            // while conditions not met, move start pointer
            while(count > k){
                if(charMap[s.charAt(start++)]-- == 1){
                    count--;
                }
            }
            // calculate max for all valid conditions
            max = Math.max(max, end - start);
        }

        return max;
}

Tree

BST

Inorder traversal a Binary Serch Tree with iteration which will get a sorted array.

public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> list = new ArrayList<>();
    if(root == null) return list;
    Stack<TreeNode> stack = new Stack<>();
    while(root != null || !stack.empty()){
        while(root != null){
            stack.push(root);
            root = root.left;
        }
        root = stack.pop();
        list.add(root.val);
        root = root.right;

    }
    return list;
}

Back Tracking

Combination

    public static List<List<Integer>> allCombine(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        backtrack(result, new ArrayList<>(), nums, 0);
        return result;
    }

    public static void backtrack(List<List<Integer>> result, List<Integer> tmpList, int[] nums, int index) {
        // Make a copy of tmpList
        result.add(new ArrayList<>(tmpList));
        // Loop through all possibilities for next position (Purning)
        for (int i = index; i < nums.length; i++) {
            tmpList.add(nums[i]);
            backtrack(result, tmpList, nums, i + 1);
            tmpList.remove(tmpList.size() - 1);
        }
    }

Permutation

    public List<List<Integer>> permuteUnique(int[] nums) {
        // Need to srot the array first if it contains the same numbers
        Arrays.sort(nums);
        List<List<Integer>> result = new ArrayList<>();
        backtrack(result, new ArrayList<>(), nums, new boolean[nums.length]);
        return result;
    }

    private void backtrack(List<List<Integer>> result, List<Integer> tmp, int[] nums, boolean[] visited){
        // Only add valid list to result
        if(tmp.size() == nums.length){
            result.add(new ArrayList(tmp));
            return;
        }

        for(int i=0; i < nums.length; i++){
            // Do not put the same # at the same position twice
            if(visited[i] || i > 0 && nums[i] == nums[i-1] && !visited[i-1]){
                continue;
            }
            tmp.add(nums[i]);
            visited[i] = true;
            backtrack(result, tmp, nums, visited);
            visited[i] = false;
            tmp.remove(tmp.size() -1);
        }
    }

Graph

BFS

Leetcode 286


    public void wallsAndGates(int[][] rooms) {
        if(rooms == null || rooms.length == 0){
            return;
        }
        int m = rooms.length, n = rooms[0].length;
        Queue<int[]> queue = new ArrayDeque<>();
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                if(rooms[i][j] == 0){
                    queue.offer(new int[]{i, j, 0});
                }
            }
        }
        int[][] directions = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
        while(!queue.isEmpty()){
            int[] cur = queue.poll();
            for(int[] dir : directions){
                int r = cur[0] + dir[0];
                int c = cur[1] + dir[1];
                // out of boundaries
                if(r < 0 || r >= m || c < 0 || c >= n){
                    continue;
                }
                // condition check/check visited or not
                if(rooms[r][c] != Integer.MAX_VALUE){
                    continue;
                }
                // set visted and update node
                rooms[r][c] = cur[2] + 1;
                // add neighbour into queue
                queue.offer(new int[]{r, c, rooms[r][c]});
            }
        }
    }

DFS

Leetcode 733

   public int[][] floodFill(int[][] image, int sr, int sc, int newColor) {
        int color = image[sr][sc];
        // do dfs for each source point
        if(color != newColor)
            dfs(image, sr, sc, color, newColor);
        return image;
    }

    private void dfs(int[][] image, int row, int col,int color, int newColor){
        // if condition do not meet, return
        if(row < 0 || row >= image.length || col < 0 || col >= image[0].length
           || image[row][col] != color){
            return;
        }
        // set visted and operate current point
        image[row][col] = newColor;
        dfs(image, row, col - 1, color, newColor);
        dfs(image, row, col + 1, color, newColor);
        dfs(image, row - 1, col, color, newColor);
        dfs(image, row + 1, col, color, newColor);
    }

Dijkstra

Leetcode 743

    public int networkDelayTime(int[][] times, int N, int K) {
        Map<Integer, List<int[]>> graph = new HashMap<>();
        for(int[] time : times){
            List<int[]> edges = graph.getOrDefault(time[0], new ArrayList<>());
            edges.add(new int[]{time[1], time[2]});
            graph.put(time[0], edges);
        }
        // target, weight -- use heap to reduce time complexity
        PriorityQueue<int[]> pq = new PriorityQueue<>((n1, n2) -> n1[1] -n2[1]);
        pq.offer(new int[]{K, 0});
        // Init distance map
        int[] dist = new int[N+1];
        Arrays.fill(dist, Integer.MAX_VALUE);
        dist[K] = 0;
        int count = 0;
        while(!pq.isEmpty()){
            int[] cur = pq.poll();
            if(dist[cur[0]] < cur[1]) continue;
            count++;
            if(graph.get(cur[0]) != null){
                for(int[] edge : graph.get(cur[0])){
                    int d = cur[1] + edge[1];
                    if(d < dist[edge[0]]){
                        dist[edge[0]] = d;
                        pq.offer(new int[]{edge[0], d});
                    }
                }
            }
        }
        if(count != N) return -1;
        int max = 0;
        for(int i = 1; i <= N; i++){
            max = Math.max(max, dist[i]);
        }

        return max;
    }

Toplogical Sort

    public boolean canFinish(int numCourses, int[][] prerequisites) {
        if(prerequisites == null || prerequisites.length == 0) return true;

        Map<Integer, Integer> inDegMap = new HashMap<>();
        Map<Integer, List<Integer>> graph = new HashMap<>();

        for(int[] pre: prerequisites){
            inDegMap.put(pre[1], inDegMap.getOrDefault(pre[1], 0) + 1);
            List<Integer> list = graph.getOrDefault(pre[0], new ArrayList<>());
            list.add(pre[1]);
            graph.put(pre[0], list);
        }

        Queue<Integer> queue = new ArrayDeque<>();

        for(int i = 0; i < numCourses; i++){
            if(!inDegMap.containsKey(i)){
                queue.offer(i);
            }
        }
        while(!queue.isEmpty()){
            int cur = queue.poll();
            List<Integer> list = graph.get(cur);
            if(list == null) continue;
            for(int n : list){
                int count = inDegMap.get(n);
                if(count == 1){
                    inDegMap.remove(n);
                    queue.offer(n);
                }else{
                    inDegMap.put(n, count -1);
                }
            }
        }

        return inDegMap.size() == 0;
    }

Union Find

class UnionFind{
    int[] parents;
    int[] ranks;

    public UnionFind(int n){
        parents = new int[n];
        ranks = new int[n];
        for(int i = 0; i < n; i++){
            parents[i] = i;
        }
    }

    public int find(int i){
        int p = parents[i];
        if(i == p){
            return p;
        }
        return parents[p] = find(p);
    }

    public void union(int a, int b){
        int root1 = find(a);
        int root2 = find(b);
        if(root1 == root2){
            return;
        }
        if(ranks[root1] < ranks[root2]){
            parents[root1] = root2;
        }else if(ranks[root2] < ranks[root1]){
            parents[root2] = root1;
        }else{
            parents[root2] = root1;
            ranks[root1]++;
        }
    }

}

Trie

class TrieNode{
    Map<Character, TrieNode> children;
    boolean isWord;

    public TrieNode(){
        children = new HashMap<>();
    }
}

class Trie{
    TrieNode root;

    public Tire(){
        root = new TrieNode();
    }

    public void insert(String word){
        TrieNode p = root;
        for(char c : word.toCharArray){
            p.children.computeIfAbsent(c, k -> new TrieNode());
            p = p.children.get(c);
        }
        p.isWord = true;
    }

    public TrieNode find(String prefix){
        TrieNode p = root;
        for(char c : prefix.toCharArray()){
            if(p.children.get(c) == null){
                return null;
            }
            p = p.children.get(c);
        }

        return p;
    }
}

Segment Tree

class SegmentTreeNode{
    int start;
    int end;
    int sum;
    SegmentTreeNode left;
    SegmentTreeNode right;

	public SegmentTreeNode(int start, int end){
        this.start = start;
        this.end = end;
    }

    private SegmentTreeNode buildTree(int start, int end, int[] nums){
	    if(start > end) return null;
        SegmentTreeNode node = new SegmentTreeNode(start, end);
 	    if(start == end){
	        node.sum = nums[start];
	        return node;
        } else {
            int mid = start + (end - start)/2;
            node.left = buildTree(start, mid, nums);
            node.right = buildTree(mid + 1, end, nums);
	        node.sum = node.left.sum + node.right.sum;
        }

        return node;
    }

    private void updateNode(SegmentTreeNode node, int index, int val){
	    if(node.start == node.end){
	        node.sum = val;
	        return;
        }
        int mid = node.start + (node.end - node.start)/2;
        if(mid >= index){
            updateNode(node.left, index, val);
        }else{
            updateNode(node.right, index, val);
        }
        node.sum = node.left.sum + node.right.sum;
    }

    private int sumRange(SegmentTreeNode node, int start, int end){
	    if(node.start == start && node.end == end){
	        return node.sum;
        }
        int mid = node.start + (node.end - node.start)/2;
        if(start > mid){
	        return sumRange(node.right, start, end);
        }else if(end <= mid){
	        return sumRange(node.left, start, end);
        }else{
            return sumRange(node.left, start, mid) + sumRange(node.right, mid + 1, end);
        }
    }
}