Saturday, July 30, 2022

1136. Parallel Courses

 一刷 07/2022

Version #1 Topological Sort

Time O(N + E)

Space O(N + E)

Runtime: 6 ms, faster than 97.21% of Java online submissions for Parallel Courses.
Memory Usage: 43.1 MB, less than 97.94% of Java online submissions for Parallel Courses.

class Solution {

    public int minimumSemesters(int n, int[][] relations) {

        int[] prevCount = new int[n];

        List<Integer>[] nextCourses = new ArrayList[n];

        for (int i = 0; i < n; i++) {

            nextCourses[i] = new ArrayList<>();

        }

        for (int[] relation : relations) {

            int prev = relation[0] - 1;

            int next = relation[1] - 1;

            nextCourses[prev].add(next);

            prevCount[next]++;

        }

        int taken = 0;

        int semester = 0;

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

        for (int i = 0; i < n; i++) {

            if (prevCount[i] == 0) {

                que.offer(i);

            }

        }

        while (!que.isEmpty()) {

            int size = que.size();

            semester++;

            // 1 - 3 - 2

            while (size-- > 0) {

                int curr = que.poll();

                taken++;

                for (int next : nextCourses[curr]) {

                    prevCount[next]--;

                    if (prevCount[next] == 0) {

                        que.offer(next);

                    }

                }

            }

        }

        return taken == n ? semester : -1;

    }

}

Friday, July 29, 2022

486. Predict the Winner

 一刷 07/2022

Version #1 DP game theory

Time O(N^2)

Space O(N^2) - space can be optimized to O(N)

Runtime: 0 ms, faster than 100.00% of Java online submissions for Predict the Winner.
Memory Usage: 39.9 MB, less than 87.08% of Java online submissions for Predict the Winner.

class Solution {

    public boolean PredictTheWinner(int[] nums) {

        int len = nums.length;

        int[][] dp = new int[len][len];

        // dp[i][j] - max score diff that we can get between nums [j, i]

        for (int i = 0; i < nums.length; i++) {

            for (int j = i; j >= 0; j--) {

                if (i == j) {

                    dp[i][j] = nums[i];

                } else {

                    // [j, i]

                    dp[i][j] = Math.max(nums[i] - dp[i - 1][j], nums[j] - dp[i][j + 1]);

                }

            }

        }

        return dp[len - 1][0] >= 0;

    }

}

85. Maximal Rectangle

 一刷 07/2022

Version #1 Stack

关键是求maximum rectangle in histogram

Time O(MN)

Space O(N)

Runtime: 34 ms, faster than 67.15% of Java online submissions for Maximal Rectangle.
Memory Usage: 54.6 MB, less than 54.71% of Java online submissions for Maximal Rectangle.

class Solution {

    public int maximalRectangle(char[][] matrix) {

        int[] row = new int[matrix[0].length];

        int max = 0;

        for (int y = 0; y < matrix.length; y++) {

            for (int x = 0; x < matrix[0].length; x++) {

                if (matrix[y][x] == '0') {

                    row[x] = 0;

                } else {

                    row[x]++;

                }

            }

            max = Math.max(max, maxRecInHisto(row));

        }

        return max;

    }

    

    private int maxRecInHisto(int[] row) {

        int max = 0;

        Stack<Integer> stack = new Stack<>();

        for (int i = 0; i < row.length; i++) {

            while (!stack.isEmpty() && row[stack.peek()] >= row[i]) {

                int h = row[stack.pop()];

                int w = i - (stack.isEmpty() ? -1 : stack.peek()) - 1;

                max = Math.max(max, h * w);

            }

            stack.push(i);

        }

        int i = row.length;

        while (!stack.isEmpty()) {

            int h = row[stack.pop()];

            int w = i - (stack.isEmpty() ? -1 : stack.peek()) - 1;

            max = Math.max(max, h * w);

        }

        return max;

    }

}

916. Word Subsets

 一刷 07/2022

Version #1 Array as HashMap

Time O(M + N)

Space O(1)

Runtime: 26 ms, faster than 86.18% of Java online submissions for Word Subsets.
Memory Usage: 89.1 MB, less than 52.85% of Java online submissions for Word Subsets.

class Solution {

    public List<String> wordSubsets(String[] words1, String[] words2) {

        // calculate the maximum counter of each character in words2

        // the counter of characters in words1 need to be at least larger than or equals to the maximum counter of words2

        int[] maxCount = new int[26];

        for (String word : words2) {

            int[] count = new int[26];

            for (int i = 0; i < word.length(); i++) {

                int index = word.charAt(i) - 'a';

                count[index]++;

                maxCount[index] = Math.max(maxCount[index], count[index]);

            }

        }

        List<String> result = new ArrayList<>();

        for (String word : words1) {

            int[] count = new int[26];

            for (int i = 0; i < word.length(); i++) {

                count[word.charAt(i) - 'a']++;

            }

            int i = 0;

            for (i = 0; i < 26; i++) {

                if (count[i] < maxCount[i]) {

                    break;

                }

            }

            if (i == 26) {

                result.add(word);

            }

        }

        return result;

    }

}

Thursday, July 28, 2022

714. Best Time to Buy and Sell Stock with Transaction Fee

 一刷 07/2022

Version #2 Better DP with two states

不是特别理解

Time O(N)

Space O(1)

Runtime: 4 ms, faster than 90.39% of Java online submissions for Best Time to Buy and Sell Stock with Transaction Fee.
Memory Usage: 76.1 MB, less than 31.51% of Java online submissions for Best Time to Buy and Sell Stock with Transaction Fee.

class Solution {

    public int maxProfit(int[] prices, int fee) {

        int cash = 0;

        int hold = -prices[0];

        for (int i = 1; i < prices.length; i++) {

            cash = Math.max(cash, hold + prices[i] - fee);

            hold = Math.max(hold, cash - prices[i]);

        }

        return cash;

    }

}


Version #1 DP with max previous profit

Time O(N)

Space O(N)

Runtime: 9 ms, faster than 46.70% of Java online submissions for Best Time to Buy and Sell Stock with Transaction Fee.
Memory Usage: 70.1 MB, less than 68.66% of Java online submissions for Best Time to Buy and Sell Stock with Transaction Fee.

class Solution {

    public int maxProfit(int[] prices, int fee) {

        int[] dp = new int[prices.length];

        int prevMax = -prices[0] - fee;

        // dp[i] - max profix that can achieve on day i

        for (int i = 1; i < prices.length; i++) {

            prevMax = Math.max(prevMax, (i >= 2 ? dp[i - 2] : 0) - prices[i - 1] - fee);

            dp[i] = Math.max(dp[i - 1], prices[i] + prevMax);

        }

        return dp[prices.length - 1];

    }

}

489. Robot Room Cleaner

 一刷 07/2022

Version #1 Backtracking

重点是每次要回到原位原方向

而且每次当前方向要传到下一层,因为需要知道进入当前层的时候robot的方向

同时如果不能move的时候也要记得转

Time O(MN)

Space O(MN)

Runtime: 8 ms, faster than 69.21% of Java online submissions for Robot Room Cleaner.
Memory Usage: 44.9 MB, less than 75.18% of Java online submissions for Robot Room Cleaner.

class Solution {

    public void cleanRoom(Robot robot) {

        // try to turn 4 directions and move

        Set<Pair<Integer, Integer>> visited = new HashSet<>();

        clean(robot, 0, 0, visited, 0);

    }

    

    private int[] dx = new int[]{0, 1, 0, -1};

    private int[] dy = new int[]{1, 0, -1, 0};

    

    private void clean(Robot robot, int y, int x, Set<Pair<Integer, Integer>> visited, int dir) {

        if (!visited.add(new Pair(y, x))) {

            return;

        }

        robot.clean();

        // 

        for (int i = 0; i < 4; i++) {

            int nd = (dir + i) % 4;

            if (robot.move()) {

                clean(robot, y + dy[nd], x + dx[nd], visited, nd);

                robot.turnLeft();

                robot.turnLeft();

                robot.move();

                robot.turnLeft();

            } else {

                robot.turnRight();

            }

        }

    }

}

Tuesday, July 26, 2022

51. N-Queens

 一刷 07/2022

Version #1 Backtracking

Time O(N!)

Space O(N)

Runtime: 8 ms, faster than 46.32% of Java online submissions for N-Queens.
Memory Usage: 47 MB, less than 14.31% of Java online submissions for N-Queens.

class Solution {

    public List<List<String>> solveNQueens(int n) {

        List<List<String>> result = new ArrayList<>();

        char[] array = new char[n];

        Arrays.fill(array, '.');

        helper(n, 0, new HashSet<>(), new HashSet<>(), new HashSet<>(), new ArrayList<>(), result, array);

        return result;

    }

    

    private void helper(int n, int y, Set<Integer> cols, Set<Integer> diff, Set<Integer> sum, List<String> path, List<List<String>> result, char[] array) {

        if (y == n) {

            result.add(new ArrayList<>(path));

            return;

        }

        for (int x = 0; x < n; x++) {

            if (cols.contains(x) || diff.contains(y - x) || sum.contains(y + x)) {

                continue;

            }

            array[x] = 'Q';

            cols.add(x);

            diff.add(y - x);

            sum.add(y + x);

            path.add(new String(array));

            array[x] = '.';

            helper(n, y + 1, cols, diff, sum, path, result, array);

            cols.remove(x);

            diff.remove(y - x);

            sum.remove(y + x);

            path.remove(path.size() - 1);

        }

    }

}

Friday, July 22, 2022

254. Factor Combinations

 一刷 07/2022

Version #1 Backtracking

自己想的时候先计算了一下小于等于sqrt(n)的所有factor

然后每次取一些factor和它们的remainder组成一组答案,要求remaider必须大于等于factor来保证没有重复答案

看了其他人的做法不需要提前算出factor,只要在i和n之间iterate找到能整除的数 感觉这个做法比较慢

Time O(logN^logN) given that we have logN number of factors and we called the recursive function time complexity of a recursive function = number of choices ^ number of steps

Space O(logN)

Runtime: 5 ms, faster than 90.58% of Java online submissions for Factor Combinations.
Memory Usage: 54.2 MB, less than 22.28% of Java online submissions for Factor Combinations.

class Solution {

    public List<List<Integer>> getFactors(int n) {

        List<Integer> factors = new ArrayList<>();

        for (int i = 2; i <= Math.sqrt(n); i++) {

            if (n % i == 0) {

                factors.add(i);

            }

        }

        List<List<Integer>> result = new ArrayList<>();

        select(factors, 0, new ArrayList<>(), n, result);

        return result;

    }

    

    private void select(List<Integer> factors, int index, List<Integer> path, int target, List<List<Integer>> result) {

        if (path.size() > 0) {

            path.add(target);

            result.add(new ArrayList<>(path));

            path.remove(path.size() - 1);

        }

        for (int i = index; i < factors.size(); i++) {

            int f = factors.get(i);

            if (target % f != 0) {

                continue;

            }

            if (target / f < f) {

                break;

            }

            path.add(f);

            select(factors, i, path, target / f, result);

            path.remove(path.size() - 1);

        }

    }

}

1192. Critical Connections in a Network

 一刷 07/2022

Version #1 DFS with node rank

一开始想到了是要求cycle,但是没有想到怎么把cycle里面的edge记录下来

看答案学习了这个rank的方法,是以前从来没有遇到过的,狠狠记住

Time O(E + V)

Space O(E + V)

Runtime: 311 ms, faster than 25.27% of Java online submissions for Critical Connections in a Network.
Memory Usage: 372.1 MB, less than 8.95% of Java online submissions for Critical Connections in a Network.

class Solution {

    public List<List<Integer>> criticalConnections(int n, List<List<Integer>> connections) {

        // If an edge is part of a cycle, then it is not a critical connection

        List<List<Integer>> graph = new ArrayList<>();

        for (int i = 0; i < n; i++) {

            graph.add(new ArrayList<>());

        }

        for (List<Integer> conn : connections) {

            int node1 = conn.get(0);

            int node2 = conn.get(1);

            graph.get(node1).add(node2);

            graph.get(node2).add(node1);

        }

        Set<List<Integer>> nonCriticalConn = new HashSet<>();

        dfs(graph, 0, nonCriticalConn, 0, new HashMap<>());

        List<List<Integer>> result = new ArrayList<>();

        for (List<Integer> conn : connections) {

            Collections.sort(conn);

            if (nonCriticalConn.contains(conn)) {

                continue;

            }

            result.add(conn);

        }

        return result;

    }

    

    private int dfs(List<List<Integer>> graph, int node, Set<List<Integer>> nonCriticalConn, int rank, Map<Integer, Integer> ranks) {

        // assign rank + 1 to all the neighbors

        // if a neighbor already has a rank smaller than current rank, it means the neighbor has been visited

        // return the min rank of all neighbors recursively

        if (ranks.containsKey(node)) {

            return ranks.get(node);

        }

        ranks.put(node, rank);

        int minRank = rank;

        for (int next : graph.get(node)) {

            Integer nextRank = ranks.get(next);

            // skip the parent

            if (nextRank != null && nextRank == rank - 1) {

                continue;

            }

            nextRank = dfs(graph, next, nonCriticalConn, rank + 1, ranks);

            if (nextRank <= rank) {

                nonCriticalConn.add(new ArrayList<>(Arrays.asList(new Integer[]{Math.min(node, next), Math.max(node, next)})));

                minRank = Math.min(minRank, nextRank);

            }

        }

        return minRank;

    }

}

1059. All Paths from Source Lead to Destination

 一刷 07/2022

Version #1 DFS

If we want to detect cycle in a graph, we need to keep track of each path with backtracking instead of keep track of the globally visited nodes

Time O(V + E) - for full graph dfs

Space O(V + E) - E is occupied by the adjacency list and V is used by the system stack

Runtime: 6 ms, faster than 94.73% of Java online submissions for All Paths from Source Lead to Destination.
Memory Usage: 45.3 MB, less than 93.00% of Java online submissions for All Paths from Source Lead to Destination.

class Solution {

    public boolean leadsToDestination(int n, int[][] edges, int source, int destination) {

        // If there's any cycles, then return false

        List<List<Integer>> graph = new ArrayList<>();

        for (int i = 0; i < n; i++) {

            graph.add(new ArrayList<>());

        }

        for (int[] edge : edges) {

            // edge[0] -> edge[1]

            graph.get(edge[0]).add(edge[1]);

        }

        Set<Integer> path = new HashSet<>();

        path.add(source);

        return dfs(graph, source, destination, path);

    }

    

    private boolean dfs(List<List<Integer>> graph, int node, int destination, Set<Integer> path) {

        if (graph.get(node).size() == 0) {

            return node == destination;

        }

        for (Integer next : graph.get(node)) {

            if (!path.add(next)) {

                return false;

            }

            path.add(next);

            if (!dfs(graph, next, destination, path)) {

                return false;

            }

            path.remove(next);

        }

        return true;

    }

}

Thursday, July 21, 2022

1319. Number of Operations to Make Network Connected

 一刷 07/2022

Version #1 DFS

We just need to count the number of connected components

Time O(N) - N is number of nodes

Space O(E) - number of edges

Runtime: 45 ms, faster than 19.38% of Java online submissions for Number of Operations to Make Network Connected.
Memory Usage: 74.6 MB, less than 31.76% of Java online submissions for Number of Operations to Make Network Connected.

class Solution {

    public int makeConnected(int n, int[][] connections) {

        // If we have more than n - 1 cables then we are able to connect all the computers

        if (connections.length < n - 1) {

            return -1;

        }

        List<List<Integer>> graph = new ArrayList<>();

        for (int i = 0; i < n; i++) {

            graph.add(new ArrayList<>());

        }

        for (int[] conn : connections) {

            graph.get(conn[0]).add(conn[1]);

            graph.get(conn[1]).add(conn[0]);

        }

        int componentCnt = 0;

        Set<Integer> visited = new HashSet<>();

        for (int i = 0; i < n; i++) {

            if (visited.add(i)) {

                dfs(i, graph, visited);

                componentCnt++;

            }

        }

        return componentCnt - 1;

    }

    

    private void dfs(int i, List<List<Integer>> graph, Set<Integer> visited) {

        for (int next : graph.get(i)) {

            if (visited.add(next)) {

                dfs(next, graph, visited);

            }

        }

    }

}

92. Reverse Linked List II

 一刷 07/2022

Version #1 Iteration

Time O(N)

Space O(1)

Runtime: 0 ms, faster than 100.00% of Java online submissions for Reverse Linked List II.
Memory Usage: 42.2 MB, less than 24.21% of Java online submissions for Reverse Linked List II.

class Solution {

    public ListNode reverseBetween(ListNode head, int left, int right) {

        if (left >= right) {

            return head;

        }

        ListNode dummy = new ListNode(0);

        dummy.next = head;

        ListNode prev = dummy;

        ListNode curr = head;

        while (curr != null && left > 1) {

            prev = curr;

            curr = curr.next;

            left--;

            right--;

        }

        prev.next = reverseUntil(curr, right);

        return dummy.next;

    }

    

    private ListNode reverseUntil(ListNode head, int right) {

        ListNode prev = null;

        ListNode curr = head;

        ListNode next = null;

        // prev -> curr -> next

        while (curr != null && right > 0) {

            next = curr.next;

            curr.next = prev;

            prev = curr;

            curr = next;

            right--;

        }

        head.next = curr;

        return prev;

    }

}

Monday, July 18, 2022

408. Valid Word Abbreviation

 一刷 07/2022

Version #1 Iteration

Time O(N)

Space O(1)

Runtime: 1 ms, faster than 99.55% of Java online submissions for Valid Word Abbreviation.
Memory Usage: 42.5 MB, less than 35.98% of Java online submissions for Valid Word Abbreviation.

class Solution {

    public boolean validWordAbbreviation(String word, String abbr) {

        int pw = 0, pa = 0;

        int num = 0;

        while (pw < word.length() && pa < abbr.length()) {

            while (pa < abbr.length() && Character.isDigit(abbr.charAt(pa))) {

                char c = abbr.charAt(pa);

                if (c == '0' && num == 0) {

                    return false;

                }

                num = num * 10 + (c - '0');

                pa++;

            }

            pw += num;

            num = 0;

            if (pw >= word.length() || pa >= abbr.length()) {

                break;

            }

            if (word.charAt(pw) != abbr.charAt(pa)) {

                return false;

            }

            pw++;

            pa++;

        }

        return pw == word.length() && pa == abbr.length();

    }

}

Sunday, July 17, 2022

1074. Number of Submatrices That Sum to Target

二刷 07/2022

Version #2 Prefix Sum by Row

比之前的方法少了一个dimension,因为用到了hashmap记录了之前prefixsum的值

Time O(M^2N)

Space O(MN)

Runtime: 276 ms, faster than 45.16% of Java online submissions for Number of Submatrices That Sum to Target.
Memory Usage: 117.6 MB, less than 37.22% of Java online submissions for Number of Submatrices That Sum to Target.

class Solution {

    public int numSubmatrixSumTarget(int[][] matrix, int target) {

        int rows = matrix.length;

        int cols = matrix[0].length;

        int[][] prefixSums = new int[rows][cols + 1];

        for (int y = 0; y < rows; y++) {

            for (int x = 1; x <= cols; x++) {

                prefixSums[y][x] = prefixSums[y][x - 1] + matrix[y][x - 1];

            }

        }

        int result = 0;

        // prefixSum[i] - sum from element [0, i - 1]

        // prefixSum[end] - prefixSum[start] - sum [start, end)

        for (int start = 0; start < cols; start++) {

            for (int end = start + 1; end <= cols; end++) {

                Map<Integer, Integer> map = new HashMap<>();

                int sum = 0;

                map.put(0, 1);

                for (int y = 0; y < rows; y++) {

                    sum += prefixSums[y][end] - prefixSums[y][start];

                    // sum - prevSum = target

                    result += map.getOrDefault(sum - target, 0);

                    map.put(sum, map.getOrDefault(sum, 0) + 1);

                }

            }

        }

        return result;

    }

}


 一刷 07/2022

Version #1 Square Prefix Sum Brute Force

Time O(M^2N^2)

Space O(MN)

Runtime: 351 ms, faster than 18.36% of Java online submissions for Number of Submatrices That Sum to Target.
Memory Usage: 45.8 MB, less than 76.92% of Java online submissions for Number of Submatrices That Sum to Target.

class Solution {

    public int numSubmatrixSumTarget(int[][] matrix, int target) {

        int rows = matrix.length;

        int cols = matrix[0].length;

        long[][] sums = new long[rows + 1][cols + 1];

        for (int y = 0; y <= rows; y++) {

            for (int x = 0; x <= cols; x++) {

                if (y == 0 || x == 0) {

                    sums[y][x] = 0;

                    continue;

                }

                sums[y][x] = matrix[y - 1][x - 1] + sums[y - 1][x] + sums[y][x - 1] - sums[y - 1][x - 1];

            }

        }

        int result = 0;

        //  (top,left)  (top,right)

        //  (down,left) (down,right)

        for (int top = 0; top < rows; top++) {

            for (int down = top + 1; down <= rows; down++) {

                for (int left = 0; left < cols; left++) {

                    for (int right = left + 1; right <= cols; right++) {

                        if (sums[down][right] - sums[top][right] - sums[down][left] + sums[top][left] == target) {

                            result++;

                        }

                    }

                }

            }

        }

        return result;

     }

}

Saturday, July 16, 2022

14. Longest Common Prefix

[TODO] Version #2 Binary Search


一刷 07/2022

Version #1 Iteration

用了一个while true取代了先把所有str iteration一遍然后去min的过程

Time O(MN)

Space O(1)

Runtime: 1 ms, faster than 88.54% of Java online submissions for Longest Common Prefix.
Memory Usage: 40.1 MB, less than 96.22% of Java online submissions for Longest Common Prefix.

class Solution {

    public String longestCommonPrefix(String[] strs) {

        StringBuilder sb = new StringBuilder();

        int i = 0;

        while (true) {

            Character c = null;

            for (String str : strs) {

                if (i >= str.length()) {

                   return sb.toString();

                }

                if (c != null && str.charAt(i) != c) {

                    return sb.toString();

                }

                if (c == null) {

                    c = str.charAt(i);

                }

            }

            sb.append(c);

            i++;

        }

    }

}

576. Out of Boundary Paths

 一刷 07/2022

Version #1 DP

写了一个bug就是MOD应该是(int)(1e9+7)而不是(int)(10e9 + 7)

其他的没有什么特别的

跟以前做的一个计算落在board里面的概率的题几乎一模一样

Time O(KMN) - K max steps, MN area of the board

Space O(MN)

Runtime: 12 ms, faster than 43.75% of Java online submissions for Out of Boundary Paths.
Memory Usage: 41.4 MB, less than 92.29% of Java online submissions for Out of Boundary Paths.

class Solution {

    private int[] dx = new int[]{1, 0, -1, 0};

    private int[] dy = new int[]{0, -1, 0, 1};

    private int MOD = (int)(1e9 + 7);

    public int findPaths(int m, int n, int maxMove, int startRow, int startColumn) {

        int result = 0;

        int[][] prevCount = new int[m][n];

        prevCount[startRow][startColumn] = 1;

        while (maxMove-- > 0) {

            int[][] currCount = new int[m][n];

            for (int y = 0; y < m; y++) {

                for (int x = 0; x < n; x++) {

                    for (int i = 0; i < 4; i++) {

                        int ny = y + dy[i];

                        int nx = x + dx[i];

                        if (ny < 0 || nx < 0 || ny >= m || nx >= n) {

                            result = (result + prevCount[y][x]) % MOD;

                        } else {

                            currCount[ny][nx] = (currCount[ny][nx] + prevCount[y][x]) % MOD;

                        }

                    }

                }

            }

            prevCount = currCount;

        }

        return result;

    }

}

Friday, July 15, 2022

628. Maximum Product of Three Numbers

 一刷 07/2022

Version #1 Sorting

Time O(NlogN)

Space O(N) or O(NlogN) depending on the sorting algorithm

Runtime: 18 ms, faster than 23.65% of Java online submissions for Maximum Product of Three Numbers.
Memory Usage: 54.1 MB, less than 62.91% of Java online submissions for Maximum Product of Three Numbers.

class Solution {

    public int maximumProduct(int[] nums) {

        // if all negative / all positive / only 1 negative -> 3 largest

        Arrays.sort(nums);

        int lastIndex = nums.length - 1;

        if (nums[lastIndex] <= 0 || nums[1] >= 0) {

            return nums[lastIndex] * nums[lastIndex - 1] * nums[lastIndex - 2];

        }

        // - - - + + +

        return nums[lastIndex] * Math.max(nums[0] * nums[1], nums[lastIndex - 1] * nums[lastIndex - 2]);

    }

}

67. Add Binary

 一刷 07/2022

Version #1 Iteration

Time O(N)

Space O(1)

Runtime: 2 ms, faster than 90.84% of Java online submissions for Add Binary.
Memory Usage: 43 MB, less than 45.39% of Java online submissions for Add Binary.

class Solution {

    public String addBinary(String a, String b) {

        StringBuilder sb = new StringBuilder();

        int carry = 0;

        int i = a.length() - 1;

        int j = b.length() - 1;

        while (i >= 0 || j >= 0 || carry > 0) {

            int bitA = i >= 0 ? a.charAt(i) - '0' : 0;

            int bitB = j >= 0 ? b.charAt(j) - '0' : 0;

            int sum = bitA + bitB + carry;

            // 3 - 1 1

            //

            carry = sum / 2;

            sb.append((char)(sum % 2 + '0'));

            i--;

            j--;

        }

        return sb.reverse().toString();

    }

}

Thursday, July 14, 2022

232. Implement Queue using Stacks

 一刷 07/2022

Version #2 Two Stack - time optimized

We don't transfer until the output is empty

Time - amortized O(1)

Space O(N)

Runtime: 1 ms, faster than 69.17% of Java online submissions for Implement Queue using Stacks.
Memory Usage: 42 MB, less than 40.33% of Java online submissions for Implement Queue using Stacks.

class MyQueue {

    Stack<Integer> input;

    Stack<Integer> output;

    public MyQueue() {

        input = new Stack<>();

        output = new Stack<>();

    }

    

    public void push(int x) {

        input.push(x);

    }

    

    private void transfer() {

        while (!input.isEmpty()) {

            output.push(input.pop());

        }

    }

    

    public int pop() {

        if (output.isEmpty()) {

            transfer();

        }

        return output.pop();

    }

    

    public int peek() {

        if (output.isEmpty()) {

            transfer();

        }

        return output.peek();

    }

    

    public boolean empty() {

        return input.isEmpty() && output.isEmpty();

    }

}


Version #1 Two Stacks 

Time - worst case O(N) time

Space O(N)

Runtime: 0 ms, faster than 100.00% of Java online submissions for Implement Queue using Stacks.
Memory Usage: 41.9 MB, less than 49.96% of Java online submissions for Implement Queue using Stacks.

class MyQueue {

    Stack<Integer> firstStack;

    Stack<Integer> secondStack;


    public MyQueue() {

        firstStack = new Stack<>();

        secondStack = new Stack<>();

    }

    

    public void push(int x) {

        while (!secondStack.isEmpty()) {

            firstStack.push(secondStack.pop());

        }

        firstStack.push(x);

    }

    

    public int pop() {

        while (!firstStack.isEmpty()) {

            secondStack.push(firstStack.pop());

        }

        return secondStack.pop();

    }

    

    public int peek() {

        while (!firstStack.isEmpty()) {

            secondStack.push(firstStack.pop());

        }

        return secondStack.peek();

    }

    

    public boolean empty() {

        return firstStack.isEmpty() && secondStack.isEmpty();

    }

}


1352. Product of the Last K Numbers

 一刷 07/2022

Version #1 Prefix Product

一个需要学的的地方就是对0的处理

当一段subarray elements包含0的时候这一段的product也是0

所以我们只需要记录0之后的prefix product

如果last k element 超出了有记录的长度,就证明是0

Time O(1) to add, O(1) to get product

Space O(N)

Runtime: 21 ms, faster than 72.32% of Java online submissions for Product of the Last K Numbers.
Memory Usage: 75.8 MB, less than 64.79% of Java online submissions for Product of the Last K Numbers.

class ProductOfNumbers {

    private List<Integer> prefixProduct;

    public ProductOfNumbers() {

        prefixProduct = new ArrayList<>();

        prefixProduct.add(1);

    }

    

    public void add(int num) {

        if (num == 0) {

            prefixProduct = new ArrayList<>();

            prefixProduct.add(1);

        } else {

            int prev = prefixProduct.get(prefixProduct.size() - 1);

            prefixProduct.add(prev * num);

        }

    }

    

    public int getProduct(int k) {

        // last index is prefixProduct.size() - 1

        // first index is prefixProduct.size() - 1 - k

        int lastIndex = prefixProduct.size() - 1;

        return lastIndex - k >= 0 ? prefixProduct.get(lastIndex) / prefixProduct.get(lastIndex - k) : 0;

    }

}

697. Degree of an Array

 一刷 07/2022

Version #1 3 HashMaps

Time O(N)

Space O(N)

Runtime: 26 ms, faster than 66.81% of Java online submissions for Degree of an Array.
Memory Usage: 54.6 MB, less than 38.79% of Java online submissions for Degree of an Array.

class Solution {

    public int findShortestSubArray(int[] nums) {

        // key-number, value-frequency

        Map<Integer, Integer> freq = new HashMap<>();

        // key-number, value-first,last index of this number

        Map<Integer, Integer> leftIndex = new HashMap<>();

        Map<Integer, Integer> rightIndex = new HashMap<>();

        int maxFreq = 0;

        for (int i = 0; i < nums.length; i++) {

            int currFreq = freq.getOrDefault(nums[i], 0) + 1;

            maxFreq = Math.max(maxFreq, currFreq);

            freq.put(nums[i], currFreq);

            if (!leftIndex.containsKey(nums[i])) {

                leftIndex.put(nums[i], i);

            }

            rightIndex.put(nums[i], i);

        }

        int len = nums.length;

        for (Map.Entry<Integer, Integer> entry : freq.entrySet()) {

            int num = entry.getKey();

            if (entry.getValue() == maxFreq) {

                len = Math.min(len, rightIndex.get(num) - leftIndex.get(num) + 1);

            }

        }

        return len;

    }

}

Wednesday, July 13, 2022

696. Count Binary Substrings

 一刷 07/2022

Version #2 Iteration with optimized space

Time O(N)

Space O(1)

Runtime: 14 ms, faster than 61.35% of Java online submissions for Count Binary Substrings.
Memory Usage: 49.2 MB, less than 52.26% of Java online submissions for Count Binary Substrings.

class Solution {

    public int countBinarySubstrings(String s) {

        int result = 0;

        int prevCount = 0;

        int currCount = 0;

        for (int i = 0; i < s.length(); i++) {

            if (i == 0 || s.charAt(i) == s.charAt(i - 1)) {

                currCount++;

            } else {

                prevCount = currCount;

                currCount = 1;

            }

            // prev count

            if (prevCount >= currCount) {

                result++;

            }

        }

        return result;

    }

}



Version #1 Iteration with O(N) space

Time O(N)

Space O(N)

Runtime: 22 ms, faster than 14.97% of Java online submissions for Count Binary Substrings.
Memory Usage: 52.4 MB, less than 16.55% of Java online submissions for Count Binary Substrings.

class Solution {

    public int countBinarySubstrings(String s) {

        int result = 0;

        int[] count = new int[s.length()];

        count[0] = 1;

        for (int i = 1; i < s.length(); i++) {

            if (s.charAt(i) == s.charAt(i - 1)) {

                count[i] = count[i - 1] + 1;

            } else {

                count[i] = 1;

            }

            // prev count

            if (i - count[i] >= 0 && count[i - count[i]] >= count[i]) {

                result++;

            }

        }

        return result;

    }

}