Thursday, June 30, 2022

1710. Maximum Units on a Truck

 一刷 06/2022

Version #1 Sort the array

Time O(NlogN)

Space O(N) ~ O(logN) depending on the sorting algorithm

Runtime: 13 ms, faster than 50.13% of Java online submissions for Maximum Units on a Truck.
Memory Usage: 51.2 MB, less than 33.19% of Java online submissions for Maximum Units on a Truck.

class Solution {

    public int maximumUnits(int[][] boxTypes, int truckSize) {

        Arrays.sort(boxTypes, (a, b) -> Integer.compare(b[1], a[1]));

        int total = 0;

        int i = 0;

        while (truckSize > 0 && i < boxTypes.length) {

            int box = boxTypes[i][0] <= truckSize ? boxTypes[i][0] : truckSize;

            total += box * boxTypes[i][1];

            truckSize -= box;

            i++;

        }

        return total;

    }

}

Tuesday, June 28, 2022

343. Integer Break

 一刷 06/2022

Version #1 DP

Time O(N^2)

Space O(N)

Runtime: 2 ms, faster than 25.67% of Java online submissions for Integer Break.
Memory Usage: 40.9 MB, less than 43.50% of Java online submissions for Integer Break.

class Solution {

    public int integerBreak(int n) {

        long[] dp = new long[n + 1];

        dp[1] = 1;

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

            dp[i] = i - 1; // split i into 1 and i - 1

            for (int diff = i - 1; diff >= i / 2; diff--) {

                dp[i] = Math.max(dp[i], Math.max(dp[i - diff], i - diff) * Math.max(dp[diff], diff));

            }

        }

        return (int)dp[n];

    }

}

406. Queue Reconstruction by Height

 一刷 06/2022

Version #2 Sorting

看了答案发现max heap完全没有必要

可以直接sort

Time O(N^2)

Space O(1)

Runtime: 10 ms, faster than 66.77% of Java online submissions for Queue Reconstruction by Height.
Memory Usage: 54.5 MB, less than 60.13% of Java online submissions for Queue Reconstruction by Height.

class Solution {

    public int[][] reconstructQueue(int[][] people) {

        Arrays.sort(people, (a, b) -> a[0] == b[0] ? Integer.compare(a[1], b[1]) : Integer.compare(b[0], a[0]));

        List<int[]> que = new ArrayList<>();

        for (int[] person : people) {

            que.add(person[1], person);

        }

        return que.toArray(new int[0][]);

    }

}


Version #1 Max Heap

Reconstruct from highest height to lowest

Time O(N^2logN)

Space O(N)

Runtime: 9 ms, faster than 77.17% of Java online submissions for Queue Reconstruction by Height.
Memory Usage: 55.3 MB, less than 6.65% of Java online submissions for Queue Reconstruction by Height.

class Solution {

    public int[][] reconstructQueue(int[][] people) {

        // insert shorter people in front of taller people will not influence the taller people's k value

        // So we should have a max heap that pops out tallest people to shortest people

        // If two people have the same height, the one with smaller k value should be polled out first

        Queue<int[]> maxHeap = new PriorityQueue<>((a, b) -> {

            if (a[0] != b[0]) {

                return Integer.compare(b[0], a[0]); // larger number has higher priority

            }

            return Integer.compare(a[1], b[1]);

        });

        for (int[] person : people) {

            maxHeap.offer(person);

        }

        List<int[]> que = new ArrayList<>();

        while (!maxHeap.isEmpty()) {

            int[] curr = maxHeap.poll();

            que.add(curr[1], curr);

        }

        return que.toArray(new int[0][]);

    }

}

583. Delete Operation for Two Strings

 一刷 06/2022

Version #1 DP with 2D array

一个写错的地方就是当i == 0 || j == 0的时候,dp[i][j]等于不为0的那个substring的长度,因为需要全部删掉才能匹配

Time O(MN)

Space O(MN)

Runtime: 17 ms, faster than 43.26% of Java online submissions for Delete Operation for Two Strings.
Memory Usage: 47.2 MB, less than 34.52% of Java online submissions for Delete Operation for Two Strings.

class Solution {

    public int minDistance(String word1, String word2) {

        // dp[i][j] - number of operations to make word1[0, i) and word2[0, j) the same

        int[][] dp = new int[word1.length() + 1][word2.length() + 1];

        // if (word1.charAt(i - 1) == word2.charAt(j - 1)) dp[i][j] = dp[i - 1][j - 1]

        // otherwise dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + 1

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

            for (int j = 0; j <= word2.length(); j++) {

                if (i == 0) {

                    dp[i][j] = j;

                    continue;

                }

                if (j == 0) {

                    dp[i][j] = i;

                    continue;

                }

                if (word1.charAt(i - 1) == word2.charAt(j - 1)) {

                    dp[i][j] = dp[i - 1][j - 1];

                } else {

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

                }

            }

        }

        return dp[word1.length()][word2.length()];

    }

}


Version #2 DP with optimized memory usage

Time O(MN)

Space O(M) - M is the length of word2

If we want to make space O(min{M, N}) we could switch word1 and word2 and always use the shorter length

Runtime: 13 ms, faster than 73.06% of Java online submissions for Delete Operation for Two Strings.
Memory Usage: 42.1 MB, less than 99.71% of Java online submissions for Delete Operation for Two Strings.

class Solution {

    public int minDistance(String word1, String word2) {

        // dp[i][j] - number of operations to make word1[0, i) and word2[0, j) the same

        int[][] dp = new int[2][word2.length() + 1];

        // if (word1.charAt(i - 1) == word2.charAt(j - 1)) dp[i][j] = dp[i - 1][j - 1]

        // otherwise dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + 1

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

            for (int j = 0; j <= word2.length(); j++) {

                if (i == 0 || j == 0) {

                    dp[i % 2][j] = i + j;

                    continue;

                }

                if (word1.charAt(i - 1) == word2.charAt(j - 1)) {

                    dp[i % 2][j] = dp[(i - 1) % 2][j - 1];

                } else {

                    dp[i % 2][j] = 1 + Math.min(dp[(i - 1) % 2][j], dp[i % 2][j - 1]);

                }

            }

        }

        return dp[word1.length() % 2][word2.length()];

    }

}

1143. Longest Common Subsequence

 一刷 06/2022

Version #1 DP - 2D array

This can be optimized to 1D array

Time O(MN)

Space O(MN)

Runtime: 19 ms, faster than 59.45% of Java online submissions for Longest Common Subsequence.
Memory Usage: 46.8 MB, less than 17.45% of Java online submissions for Longest Common Subsequence.

class Solution {

    public int longestCommonSubsequence(String text1, String text2) {

        // dp[i][j] the longest common subsequence with text1 [0, i) and text2 [0, j)

        // dp[i][j] = dp[i - 1][j], dp[i][j - 1] -> we don't match

        //          (text1.charAt(i - 1) == text2.charAt(j - 1)) + dp[i - 1][j - 1]

        int[][] dp = new int[text1.length() + 1][text2.length() + 1];

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

            for (int j = 1; j <= text2.length(); j++) {

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

                dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 1] + (text1.charAt(i - 1) == text2.charAt(j - 1) ? 1 : 0));

                // System.out.printf("dp[%d][%d]=%d\n", i, j, dp[i][j]);

            }

        }

        return dp[text1.length()][text2.length()];

    }

}

673. Number of Longest Increasing Subsequence

二刷 07/2022

Version #2 DP + binary search + prefix sum

比想象中的好写一点,关键点是binary search到start == end的时候,start点不一定是符合条件的,需要特殊讨论

另一个很大的bug是Arrays.fill(endings, new ArrayList<>())会造成所有的index都是同一个list,不能这么写

Time O(NlogN)

Space O(N)

Runtime: 10 ms, faster than 99.39% of Java online submissions for Number of Longest Increasing Subsequence.
Memory Usage: 47.1 MB, less than 5.28% of Java online submissions for Number of Longest Increasing Subsequence.
class Solution {
    public int findNumberOfLIS(int[] nums) {
        List<Pair<Integer, Integer>>[] endings = new ArrayList[nums.length];
        for (int i = 0; i < endings.length; i++) {
            endings[i] = new ArrayList<>();
        }
        // find the first index of the list whose last element is larger than or equals to nums[i]
        for (int num : nums) {
            int listIndex = findListIndex(endings, num);
            List<Pair<Integer, Integer>> list = endings[listIndex];
            int prevCount = 1;
            if (listIndex > 0) {
                List<Pair<Integer, Integer>> prevList = endings[listIndex - 1];
                prevCount = findPrevCount(prevList, num);
            }
            int prefixSum = 0;
            if (list.size() > 0) {
                prefixSum = list.get(list.size() - 1).getValue();
            }
            list.add(new Pair<>(num, prefixSum + prevCount));
        }
        for (int i = endings.length - 1; i >= 0; i--) {
            if (endings[i].size() > 0) {
                return endings[i].get(endings[i].size() - 1).getValue();
            }
        }
        return 0;
    }
    
    private int findPrevCount(List<Pair<Integer, Integer>> prevList, int num) {
        // prev list is a decreasing list
        // we need to find out the first index smaller than num
        int start = 0, end = prevList.size() - 1;
        while (start < end) {
            int mid = start + (end - start) / 2;
            if (prevList.get(mid).getKey() >= num) {
                start = mid + 1;
            } else {
                end = mid;
            }
        }
        int total = prevList.get(prevList.size() - 1).getValue();
        if (start == 0 && prevList.get(start).getKey() < num) {
            return total;
        }
        return total - prevList.get(start - 1).getValue();
    }
    
    private int findListIndex(List<Pair<Integer, Integer>>[] endings, int num) {
        int start = 0, end = endings.length - 1;
        while (start < end) {
            int mid = start + (end - start) / 2;
            List<Pair<Integer, Integer>> midList = endings[mid];
            if (midList.size() == 0) {
                end = mid;
                continue;
            }
            int lastElement = midList.get(midList.size() - 1).getKey();
            if (lastElement < num) {
                start = mid + 1;
            } else {
                end = mid;
            }
        }
        if (endings[start].size() == 0 || endings[start].get(endings[start].size() - 1).getKey() >= num) {
            return start;
        }
        return start + 1;
    } 

} 


一刷 06/2022

Version #1 Naiive DP with two arrays

for each element in the array or on in the tree, they all carry three fields :

1) the maximum increasing / decreasing length ends at the current element,

2) its own value ,

3) the total number of maximum length,

Time O(N^2)

Space O(N)

Runtime: 33 ms, faster than 43.44% of Java online submissions for Number of Longest Increasing Subsequence.
Memory Usage: 44.3 MB, less than 53.55% of Java online submissions for Number of Longest Increasing Subsequence.

class Solution {

    public int findNumberOfLIS(int[] nums) {

        int[] len = new int[nums.length];

        int[] count = new int[nums.length];

        int maxLen = 0;

        int maxCount = 0;

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

            len[end] = 1;

            count[end] = 1;

            for (int prev = end - 1; prev >= 0; prev--) {

                if (nums[prev] >= nums[end]) {

                    continue;

                }

                // nums[prev] < nums[end] - can concatenate

                if (len[prev] + 1 > len[end]) {

                    len[end] = len[prev] + 1;

                    count[end] = count[prev];

                } else if (len[prev] + 1 == len[end]) {

                    count[end] += count[prev];

                }

            }

            if (len[end] == maxLen) {

                maxCount += count[end];

            } else if (len[end] > maxLen) {

                maxLen = len[end];

                maxCount = count[end];

            }

        }

        return maxCount;

    }

}

Monday, June 27, 2022

1647. Minimum Deletions to Make Character Frequencies Unique

 一刷 06/2022

Version #2 Sorting - better

Time O(N)

Space O(1)

Runtime: 12 ms, faster than 84.44% of Java online submissions for Minimum Deletions to Make Character Frequencies Unique.
Memory Usage: 53.8 MB, less than 78.50% of Java online submissions for Minimum Deletions to Make Character Frequencies Unique.

class Solution {

    public int minDeletions(String s) {

        int[] freq = new int[26];

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

            freq[s.charAt(i) - 'a']++;

        }

        Arrays.sort(freq);

        int maxAllowed = s.length(); // Assuming this is the max freq that's not used

        int result = 0;

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

            if (freq[i] > maxAllowed) {

                result += freq[i] - maxAllowed; // current freq become the max allowed

            } else {

                // freq[i] <= maxAllowed

                maxAllowed = freq[i];

            }

            maxAllowed = maxAllowed == 0 ? 0 : maxAllowed - 1;

        }

        return result;

    }

}



Version #1 Intuitive Solution

Time O(N)

Space O(N)

Runtime: 24 ms, faster than 36.15% of Java online submissions for Minimum Deletions to Make Character Frequencies Unique.
Memory Usage: 54.5 MB, less than 46.42% of Java online submissions for Minimum Deletions to Make Character Frequencies Unique.

class Solution {

    public int minDeletions(String s) {

        int[] count = new int[26];

        int max = 0;

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

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

        }

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

            max = Math.max(max, count[i]);

        }

        int[] freq = new int[max + 1];

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

            freq[count[i]]++;

        }

        int change = 0;

        for (int i = freq.length - 1; i > 0; i--) {

            if (freq[i] > 1) {

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

                change += freq[i] - 1;

            }

        }

        return change;

    }

413. Arithmetic Slices

 一刷 06/2022

Version #1 DP with 1D array

Time O(N)

Space O(N)

Runtime: 0 ms, faster than 100.00% of Java online submissions for Arithmetic Slices.
Memory Usage: 42.6 MB, less than 11.92% of Java online submissions for Arithmetic Slices.

class Solution {

    public int numberOfArithmeticSlices(int[] nums) {

        // number of arithmetic slice ending with nums[i]

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

        int sum = 0;

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

            if (i < 2 || nums[i] - nums[i - 1] != nums[i - 1] - nums[i - 2]) {

                // dp[i] = 0; // can be ignore, since default is 0 already

                continue;

            }

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

            sum += dp[i];

        }

        return sum;

    }

}

518. Coin Change 2

 一刷 06/2022

Version #1 DP

自己没做出来

这道题和combination sum 4 的区别是,不同的顺序会当成同一个答案

在combination sum的时候,(1,1,2)和(2,1,1)是不一样的,所以outer loop iterate over sum,inner loop iterate over number

这道题(1,1,2)和(2,1,1)是同一个答案,所以要保证一个顺序,比如前面的数先选,所以outer loop iterate over numbers, inner loop iterate over sum

Time O(N*amount)

Space O(amount)

Runtime: 7 ms, faster than 57.10% of Java online submissions for Coin Change 2.
Memory Usage: 42.2 MB, less than 58.74% of Java online submissions for Coin Change 2.

class Solution {

    public int change(int amount, int[] coins) {

        int[] dp = new int[amount + 1];

        dp[0] = 1;

        for (int coin : coins) {

            for (int i = 1; i <= amount; i++) {

                if (i - coin >= 0) {

                    dp[i] += dp[i - coin];

                }

            }

        }

        return dp[amount];

    }

}


Sunday, June 26, 2022

1689. Partitioning Into Minimum Number Of Deci-Binary Numbers

 一刷 06/2022

Time O(Len)

Space O(1)

Runtime: 9 ms, faster than 63.10% of Java online submissions for Partitioning Into Minimum Number Of Deci-Binary Numbers.
Memory Usage: 54.4 MB, less than 31.55% of Java online submissions for Partitioning Into Minimum Number Of Deci-Binary Numbers.

class Solution {

    public int minPartitions(String n) {

        int max = 0;

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

            max = Math.max(max, n.charAt(i) - '0');

        }

        return max;

    }

}

Friday, June 24, 2022

665. Non-decreasing Array

 一刷 06/2022

Version #1 Greedy

反正我是想不出来

Time O(N)

Space O(1)

Runtime: 1 ms, faster than 97.53% of Java online submissions for Non-decreasing Array.
Memory Usage: 43.6 MB, less than 83.86% of Java online submissions for Non-decreasing Array.

class Solution {

    public boolean checkPossibility(int[] nums) {

        //     i i+1 

        // 2 3 4 2 6 

        // 2 2 4 3 6

        boolean violated = false; 

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

            if (nums[i + 1] >= nums[i]) {

                continue;

            }

            if (violated) {

                return false;

            }

            violated = true;

            if (i == 0 || nums[i + 1] >= nums[i - 1]) {

                nums[i] = nums[i + 1];

            } else {

                nums[i + 1] = nums[i]; 

            }

        }

        return true;

    }

}

797. All Paths From Source to Target

 一刷 06/2022

Version #1 DFS

Time - given that there are N nodes, there could be at most have 2^N - 1 paths from start to end, and for the path there could be N - 2 nodes

O(2NN)

Space 

O(2NN)

Runtime: 1 ms, faster than 99.86% of Java online submissions for All Paths From Source to Target.
Memory Usage: 44.1 MB, less than 90.00% of Java online submissions for All Paths From Source to Target.

class Solution {

    public List<List<Integer>> allPathsSourceTarget(int[][] graph) {

        if (graph == null || graph.length == 0) {

            return new ArrayList<>();

        }

        boolean[] visited = new boolean[graph.length];

        visited[0] = true;

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

        dfs(graph, visited, 0, new ArrayList<>(), result);

        return result;

    }

    

    private void dfs(int[][] graph, boolean[] visited, int node, List<Integer> path, List<List<Integer>> result) {

        path.add(node);

        if (node == graph.length - 1) {

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

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

            return;

        }

        for (int next : graph[node]) {

            if (visited[next]) {

                continue;

            }

            visited[next] = true;

            dfs(graph, visited, next, path, result);

            visited[next] = false;

        }

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

    }

}

1091. Shortest Path in Binary Matrix

 一刷 06/2022

Version #2 A* Algorithm[TODO]

Version #1 BFS

写了两个bug

一个是起点和终点不一定是0,需要特殊check

另一个是如果只有一个点,因为我是塞进que之前检查是不是终点,就会把(0,0)给忽略,也要做特殊检查 像答案是poll之后再检查就没有这个问题

Time O(MN)

Space O(MN)

Runtime: 16 ms, faster than 92.75% of Java online submissions for Shortest Path in Binary Matrix.
Memory Usage: 43.5 MB, less than 95.08% of Java online submissions for Shortest Path in Binary Matrix.

class Solution {

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

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

    public int shortestPathBinaryMatrix(int[][] grid) {

        if (grid == null || grid.length == 0 || grid[0] == null || grid[0].length == 0) {

            return 0;

        }

        if (grid[0][0] != 0 || grid[rows - 1][cols - 1] != 0) {

            return -1;

        }

        

        int rows = grid.length;

        int cols = grid[0].length;

        if (rows == 1 && cols == 1) {

            return 1;

        }

        Queue<int[]> que = new ArrayDeque<>();

        boolean[][] visited = new boolean[rows][cols];

        visited[0][0] = true;

        que.offer(new int[]{0, 0});

        int distances = 1;

        while (!que.isEmpty()) {

            int size = que.size();

            distances++;

            while (size-- > 0) {

                int[] curr = que.poll();

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

                    int x = curr[1] + dx[i];

                    int y = curr[0] + dy[i];

                    if (x < 0 || x >= cols || y < 0 || y >= rows) {

                        continue;

                    }

                    

                    if (grid[y][x] != 0 || visited[y][x]) {

                        continue;

                    }

                    if (y == rows - 1 && x == cols - 1) {

                        return distances;

                    }

                    visited[y][x] = true;

                    que.offer(new int[]{y, x});

                }

            }

        }

        return -1;

    }

}

572. Subtree of Another Tree

 一刷 06/2022

Version #1 Recursion

Time O(N^2)

Space O(N)

Runtime: 3 ms, faster than 96.91% of Java online submissions for Subtree of Another Tree.
Memory Usage: 47.4 MB, less than 7.96% of Java online submissions for Subtree of Another Tree.

class Solution {

    public boolean isSubtree(TreeNode root, TreeNode subRoot) {

        if (root == null) {

            return subRoot == null;

        }

        return isSubtreeFromRoot(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);

    }

    

    private boolean isSubtreeFromRoot(TreeNode node, TreeNode subNode) {

        if (subNode == null && node == null) {

            return true;

        }

        if (subNode == null || node == null) {

            return false;

        }

        return node.val == subNode.val && isSubtreeFromRoot(node.left, subNode.left) && isSubtreeFromRoot(node.right, subNode.right);

    }

}

547. Number of Provinces

 一刷 06/2022

Version #1 DFS

Time - O(N^2) since the graph is traversed once

Space O(N) for the visited array

Runtime: 1 ms, faster than 99.93% of Java online submissions for Number of Provinces.
Memory Usage: 53.4 MB, less than 76.07% of Java online submissions for Number of Provinces.

class Solution {

    public int findCircleNum(int[][] isConnected) {

        if (isConnected == null || isConnected.length == 0 || isConnected[0] == null || isConnected[0].length == 0) {

            return 0;

        }

        int N = isConnected.length;

        boolean[] visited = new boolean[N];

        int count = 0;

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

            if (visited[i]) {

                continue;

            }

            count++;

            visited[i] = true;

            // DFS

            dfs(isConnected, i, visited);

        }

        return count;

    }

    

    private void dfs(int[][] isConnected, int i, boolean[] visited) {

        for (int j = 0; j < isConnected.length; j++) {

            if (visited[j] || isConnected[i][j] == 0) {

                continue;

            }

            visited[j] = true;

            dfs(isConnected, j, visited);

        }

    }

}

Thursday, June 23, 2022

986. Interval List Intersections

 一刷 06/2022

Version #1 Two Pointers - Not optimal

看了答案的解法写的更加简洁

先po一下自己独立写的解法

Time O(M + N)

Space O(1)

Runtime: 5 ms, faster than 53.62% of Java online submissions for Interval List Intersections.
Memory Usage: 54.9 MB, less than 27.57% of Java online submissions for Interval List Intersections.

class Solution {

    public int[][] intervalIntersection(int[][] firstList, int[][] secondList) {

        int firstPointer = 0, secondPointer = 0;

        List<int[]> overlaps = new ArrayList<>();

        while (firstPointer < firstList.length && secondPointer < secondList.length) {

            int[] first = firstList[firstPointer];

            int[] second = secondList[secondPointer];

            // [f]           [f]

            //     [s]    [s]

            if (first[1] < second[0]) {

                firstPointer++;

                continue;

            } 

            if (first[0] > second[1]) {

                secondPointer++;

                continue;

            }

            int[] overlap = new int[]{Math.max(first[0], second[0]), Math.min(first[1], second[1])};

            overlaps.add(overlap);

            if (overlap[1] == second[1]) {

                secondPointer++;

            } else {

                firstPointer++;

            }

            // [f        ]           [f]

            //   [s]    [s]

        }

        return overlaps.toArray(new int[0][]);

    }

}


Version #2 Simplified Two Pointers

Time O(M + N)

Space O(1)


Runtime: 4 ms, faster than 74.00% of Java online submissions for Interval List Intersections.
Memory Usage: 54.7 MB, less than 53.37% of Java online submissions for Interval List Intersections.

class Solution {

    public int[][] intervalIntersection(int[][] firstList, int[][] secondList) {

        int firstPointer = 0, secondPointer = 0;

        List<int[]> overlaps = new ArrayList<>();

        while (firstPointer < firstList.length && secondPointer < secondList.length) {

            int[] first = firstList[firstPointer];

            int[] second = secondList[secondPointer];

            // [f]

            //        [s]

            int lo = Math.max(first[0], second[0]);

            int hi = Math.min(first[1], second[1]);

            if (lo <= hi) {

                overlaps.add(new int[]{lo, hi});

            }

            if (first[1] < second[1]) {

                firstPointer++;

            } else {

                secondPointer++;

            }

        }

        return overlaps.toArray(new int[0][]);

    }

}

1099. Two Sum Less Than K

 一刷 06/2022

Version #1 Two Pointers

As a quick refresher, the pointers are initially set to the first and the last element respectively. We compare the sum of these two elements with the target. If it is smaller than the target, we increment the lower pointer left. Otherwise, we decrement the higher pointer right. Thus, the sum always moves toward the target, and we "prune" pairs that would move it further away. Again, this works only if the array is sorted.

Time O(NlogN)

Space O(logN) to O(N) depends on the sorting algorithm


Runtime: 3 ms, faster than 65.67% of Java online submissions for Two Sum Less Than K.
Memory Usage: 42.5 MB, less than 45.06% of Java online submissions for Two Sum Less Than K.

class Solution {

    public int twoSumLessThanK(int[] nums, int k) {

        int max = -1;

        Arrays.sort(nums);

        int start = 0, end = nums.length - 1;

        while (start < end) {

            if (nums[start] + nums[end] < k) {

                max = Math.max(max, nums[start] + nums[end]);

                start++;

            } else {

                end--;

            }

        }

        return max;

    }

}


Version #2 Counting Sort + Two Pointers

有一个很容易错的点就是当start==end的时候也是有可能的,要求count[start] > 1这样就可以同样的数加在一起

Time O(M + N) - M is the range of values in the input array, N is the length of the input array

Space O(M)

Runtime: 3 ms, faster than 65.67% of Java online submissions for Two Sum Less Than K.
Memory Usage: 41.8 MB, less than 77.93% of Java online submissions for Two Sum Less Than K.

class Solution {

    public int twoSumLessThanK(int[] nums, int k) {

        int[] count = new int[1001];

        for (int num : nums) {

            count[num]++;

        }

        int max = -1;

        int start = 0, end = count.length - 1;

        while (start <= end) {

            if (count[start] == 0) {

                start++;

                continue;

            } 

            if (count[end] == 0) {

                end--;

                continue;

            }

            if (start + end >= k) {

                end--;

                continue;

            }

            // start + end < k

            if (start < end || count[start] > 1) {

                max = Math.max(max, start + end);

            }

            start++;

        }

        return max;

    }

}