Wednesday, April 26, 2017

76. Minimum Window Substring

五刷 07/2022
Version #1 Array as counter map + Sliding window
写了一个bug就是没有在while count== 0 的时候update答案,而是在出了while loop的时候才update,这在这道题里是不对的
求max的时候是跳过所有不符合的然后走到符合的
这道题是求min所以是跳过所有符合的until不符合的,所以要在while loop里面update
Time O(N)
Space O(256)~O(1)

Runtime: 4 ms, faster than 95.18% of Java online submissions for Minimum Window Substring.
Memory Usage: 44.1 MB, less than 65.84% of Java online submissions for Minimum Window Substring.
class Solution {
    public String minWindow(String s, String t) {
        // A satisfied window must could possible containing more characters than the character count in t
        int[] map = new int[128];
        int count = t.length(); // we need to map count number of characters
        for (int i = 0; i < t.length(); i++) {
            // if the count is zero, a new character is encountered
            map[t.charAt(i)]++;
        }
        Integer resStart = null, resEnd = null;
        int start = 0;
        // if the number of character is decreased to less than zero, means we have matched more tha needed characters
        for (int end = 0; end < s.length(); end++) {
            char c = s.charAt(end);
            if (map[c] > 0) {
                count--;
            }
            map[c]--;
            while (count == 0) {
                if (resStart == null || end - start < resEnd - resStart) {
                    resStart = start;
                    resEnd = end;
                }
                c = s.charAt(start);
                map[c]++;
                if (map[c] > 0) {
                    count++;
                }
                start++;
            }
        }
        return resStart == null ? "" : s.substring(resStart, resEnd + 1);
    }
}


四刷 int[256]

73.14 %
class Solution {
    public String minWindow(String s, String t) {
        int[] map = new int[256];
        String result = null;
        int count = t.length();
        int left = -1;
        for (int i = 0; i < t.length(); i++) {
            map[t.charAt(i)]++;
        }
        // T = "ABC"
        // S = "ADOBECODEBANC"
        for (int right = 0; right < s.length(); right++) {
            char curr = s.charAt(right);
            if (map[curr] > 0) count--;
            map[curr]--;
            while (count == 0) {
                if (result == null || right - left < result.length()) {
                    result = s.substring(left + 1, right + 1);
                }
                left++;
                curr = s.charAt(left);
                map[curr]++;
                if (map[curr] > 0) count++;
            }
        }
        return result == null ? "" : result;
    }
}


三刷 HashMap

48.12 % 
class Solution {
    public String minWindow(String s, String t) {
        Map<Character, Integer> map = new HashMap<>();
        int total = t.length();
        String result = null;
        for (int i = 0; i < t.length(); i++) {
            map.put(t.charAt(i), map.getOrDefault(t.charAt(i), 0) + 1);
        }
        int left = -1;
        int right = 0;
        // (left, right]
        while (right < s.length()) {
            char c = s.charAt(right);
            int count;
            if (map.containsKey(c)) {
                count = map.get(c);
                if (count > 0) {
                    total--;
                }
                map.put(c, count - 1);
            }
            while (total == 0 && left < right) {
                if (result == null || right - left < result.length()) {
                    result = s.substring(left + 1, right + 1);
                }
                left++;
                c = s.charAt(left);
                if (map.containsKey(c)) {
                    count = map.get(c);
                    if (count >= 0) {
                        total++;
                    }
                    map.put(c, count + 1);
                }
             
            }
            right++;
        }
        return result == null ? "" : result;
    }
}


二刷
96.35 % 
class Solution {
    public String minWindow(String s, String t) {
        int[] counter = new int[256];
        int match = 0;
        for (int i = 0; i < t.length(); i++) {
            counter[t.charAt(i)]++;
            match++;
        }
        int fast = 0;
        int slow = 0;
        int min = s.length() + 1;
        int start = 0;
        int end = 0;
        // [slow, fast]
        for (fast = 0; fast < s.length(); fast++) {
            if (--counter[s.charAt(fast)] >= 0) {
                match--;
            }
     
            while (match == 0) {
                if (fast - slow + 1 < min) {
                    min = fast - slow + 1;
                    start = slow;
                    end = fast;
                }
                if (++counter[s.charAt(slow++)] > 0) {
                    match++;
                }
            }
        }
        if (min == s.length() + 1) return "";
        return s.substring(start, end + 1);
    }
}

一刷

Time O(length of string)
Space O(1)
2 bugs
1st I forgot to update the value of minLength by the value of currLength
2st Didn't take care of the situation that the string is not found.

public class Solution {
    /**
     * @param source: A string
     * @param target: A string
     * @return: A string denote the minimum window
     *          Return "" if there is no such a string
     */
    public String minWindow(String source, String target) {
        // write your code
        if (source == null || source.length() == 0 || target == null || target.length() == 0) return "";
        int[] sourceHash = new int[256];
        int[] targetHash = new int[256];
        //total number of target chars
        int count = 0;
        //Index is the ASCII number of each character
        for (int i = 0; i < target.length(); i++) {
            targetHash[target.charAt(i)]++;
            count++;
        }
        int left = 0, right = 0;
        //result String [start, end]
        int start = 0, end = 0, minLength = Integer.MAX_VALUE;
        int index;
        for (right = 0; right < source.length(); right++) {
            index = source.charAt(right);
            if (targetHash[index] > 0) {
                sourceHash[index]++;
                if (targetHash[index] >= sourceHash[index]) count--;
            }
            while (count == 0) {
                index = source.charAt(left);
                int currLength = right - left + 1;
                if (currLength < minLength) {
             
                    minLength = currLength;
                    start = left;
                    end = right;
                }
                if (targetHash[index] > 0) {
                    sourceHash[index]--;
                    if (targetHash[index] > sourceHash[index]) count++;
                }
                left++;
            }
        }
        if (minLength == Integer.MAX_VALUE) return "";
        return source.substring(start, end + 1);
    }
}

Tuesday, April 25, 2017

Coins in a Line





public class Solution {
    /**
     * @param n: an integer
     * @return: a boolean which equals to true if the first player will win
     */
    public boolean firstWillWin(int n) {
        // write your code here
        if (n <= 0) return false;
        boolean[] dp = new boolean[2];
        dp[0] = false;
        dp[1] = true;
        for (int i = 2; i <= n; i++) {
            dp[i % 2] = !(dp[(i - 1) % 2] && dp[(i - 2) % 2]);
         
        }
        return dp[n % 2];
    }
}

Longest Increasing Continuous subsequence II

public class Solution {
    /**
     * @param A an integer matrix
     * @return  an integer
     */
    public int longestIncreasingContinuousSubsequenceII(int[][] A) {
        // Write your code here
        if (A == null || A.length == 0 || A[0] == null || A[0].length == 0) return 0;
        int rows = A.length, cols = A[0].length;
        int maxLength = 0;
        dp = new int[rows][cols];
        visited = new boolean[rows][cols];
        for (int x = 0; x < rows; x++) {
            for (int y = 0; y < cols; y++) {
                maxLength = Math.max(maxLength, search(A, x, y));
            }
        }
        return maxLength;
    }
    private int[][] dp;
    private boolean[][] visited;
    private int[] dx = {1, 0, -1, 0};
    private int[] dy = {0, 1, 0, -1};
    //The max length of path starting from current point (x,y)
    private int search(int[][] A, int x, int y) {
        if (visited[x][y]) return dp[x][y];
        int currMax = 0;
        //Traverse its neighbors
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if (nx < 0 || nx >= A.length || ny < 0 || ny >= A[0].length) continue;
            if (A[nx][ny] > A[x][y]) {
                currMax = Math.max(currMax, search(A, nx, ny));
            }
        }
        dp[x][y] = currMax + 1;
        visited[x][y] = true;
        return dp[x][y];
    }
}

Longest Increasing Continuous Subsequence

public class Solution {
    /**
     * @param A an array of Integer
     * @return  an integer
     */
    public int longestIncreasingContinuousSubsequence(int[] A) {
        // Write your code here
        if (A == null || A.length == 0) return 0;
        int increase = 1, decrease = 1;
        int max = 1;
        for (int i = 1; i < A.length; i++) {
            if (A[i] > A[i - 1]) {
                increase++;
                decrease = 1;
            } else if (A[i] < A[i - 1]) {
                decrease++;
                increase = 1;
            } else {
                decrease = 1;
                increase = 1;
            }
            max = Math.max(max, Math.max(increase, decrease));
        }
        return max;
    }
}

221. Maximal Square

























三刷 07/2022
Version #1 1D DP

Time O(MN)
Space O(N)
Runtime: 12 ms, faster than 26.14% of Java online submissions for Maximal Square.
Memory Usage: 57.4 MB, less than 73.58% of Java online submissions for Maximal Square.

class Solution {
    public int maximalSquare(char[][] matrix) {
        // max side length with (y, x) as the bottom right cornor of the square
        int[] dp = new int[matrix[0].length];
        int max = 0;
        for (int y = 0; y < matrix.length; y++) {
            int[] ndp = new int[matrix[0].length];
            for (int x = 0; x < matrix[0].length; x++) {
                if (matrix[y][x] == '0') {
                    continue;
                }
                if (y == 0 || x == 0) {
                    ndp[x] = 1;
                } else {
                    ndp[x] = 1 + Math.min(ndp[x - 1], Math.min(dp[x], dp[x - 1]));
                }
                max = Math.max(max, ndp[x]);
            }
            dp = ndp;
        }
        return max * max;
    }
}



一刷
side length边长
public class Solution {
    /**
     * @param matrix: a matrix of 0 and 1
     * @return: an integer
     */
    public int maxSquare(int[][] matrix) {
        // write your code here
        if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) return 0;
        int rows = matrix.length;
        int cols = matrix[0].length;
        int maxLength = 0;
        //dp[x][y] is the maximum side length of the square whose left down corner is matrix[x][y]
        int[][] dp = new int[2][cols];
        for (int x = 0; x < rows; x++) {
            for (int y = 0; y < cols; y++) {
                //System.out.println(x + " " + y);
                if (x == 0 || y == 0) {
                    dp[x % 2][y] = matrix[x][y];
                } else if (matrix[x][y] == 1){
                    dp[x % 2][y] = 1 + Math.min(dp[(x - 1) % 2][y - 1], Math.min(dp[(x - 1) % 2][y], dp[x % 2][y - 1]));
                } else {
                    dp[x % 2][y] = 0;
                }
                maxLength = Math.max(dp[x % 2][y], maxLength);
            }
        }
        return maxLength * maxLength;
    }
}

二刷
空间未优化版
Space O(n^2)
 53.84 %
public class Solution {
    public int maximalSquare(char[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) return 0;
        int max = 0;
        int rows = matrix.length, cols = matrix[0].length;
        int[][] dp = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            if (matrix[i][0] == '1') {
                dp[i][0] = 1;
                max = 1;
            }
        }
        for (int j = 1; j < cols; j++) {
            if (matrix[0][j] == '1') {
                dp[0][j] = 1;
                max = 1;
            }
        }
        for (int i = 1; i < rows; i++) {
            for (int j = 1; j < cols; j++) {
                if (matrix[i][j] == '1') {
                    dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
                    max = Math.max(max, dp[i][j]);
                }
            }
        }
        return max * max;
    }
}

Rolling Array
15.08 %
Space O(n)
写了一个bug
当matrix[i][j] == '0' 的时候,因为原来是二维默认初始值为0,所以不用处理
但是这里的array要reuse所以必须要置零

public class Solution {
    public int maximalSquare(char[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) return 0;
        int max = 0;
        int rows = matrix.length, cols = matrix[0].length;
        int[][] dp = new int[2][cols];
        for (int i = 0; i < cols; i++) {
            if (matrix[0][i] == '1') {
                dp[0][i] = 1;
                max = 1;
            }
        }
     
        for (int i = 1; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (matrix[i][j] == '1') {
                    if (j == 0) {
                        dp[i % 2][j] = 1;
                    } else {
                        dp[i % 2][j] = Math.min(Math.min(dp[(i - 1) % 2][j], dp[i % 2][j - 1]), dp[(i - 1) % 2][j - 1]) + 1;
                    }
                    max = Math.max(max, dp[i % 2][j]);
                } else {
                    dp[i % 2][j] = 0;
                }
            }
        }
        return max * max;
    }
}

House Robber

dp with rolling array
The index of dp array is calculated by the original index mod 2.

public class Solution {
    /**
     * @param A: An array of non-negative integers.
     * return: The maximum amount of money you can rob tonight
     */
    public long houseRobber(int[] A) {
        // write your code here
        if (A == null || A.length == 0) return 0;
        long[] dp = new long[2];
        dp[0] = 0;
        dp[1] = A[0];
        for (int i = 2; i <= A.length; i++) {
            dp[i % 2] = Math.max(dp[(i - 1) % 2], dp[i % 2] + A[i - 1]);
        }
        return dp[A.length % 2];
    }
}