LeetCode 376, 329, 301

163 阅读2分钟

LeetCode 376 Wiggle Subsequence

链接:leetcode.com/problems/wi…

方法:DP

时间复杂度:O(n) 空间复杂度:O(n),滚动数组优化为O(1) 想法:用DP。参考了www.acwing.com/solution/co… up[i]代表以nums[i]为结尾的,最后一个状态是上升的最长wiggle subsequence长度,down[i]代表以nums[i]为结尾的,最后一个状态是下降的最长wiggle subsequence长度。当往后遍历的时候,如果这个值大于之前那个值,说明往上拐了一下,up[i] = down[i - 1] + 1。如果这个值小于之前那个值,说明往下拐了一下,down[i] = up[i - 1] + 1。写完会发现i处的状态只与i-1的状态有关,因此很容易用两个变量up和down代替数组。 代码:

class Solution {
    public int wiggleMaxLength(int[] nums) {
        int n = nums.length;
        int[] up = new int[n];
        int[] down = new int[n];
        up[0] = 1;
        down[0] = 1;
        
        for (int i = 1; i < n; i++) {
            if (nums[i] > nums[i - 1]) {
                up[i] = down[i - 1] + 1;
                down[i] = down[i - 1];
            }
            else if (nums[i] < nums[i - 1]) {
                down[i] = up[i - 1] + 1;
                up[i] = up[i - 1];
            }
            else {
                up[i] = up[i - 1];
                down[i] = down[i - 1];
            }
        }
        
        return Math.max(up[n - 1], down[n - 1]);
    }
}

LeetCode 329 Longest Increasing Path in a Matrix

链接:leetcode.com/problems/lo…

方法:DFS+memo

时间复杂度:O(mn) 空间复杂度:O(mn) 想法:比较好想的DFS,然后仔细再想想就会发现有重复调用,因此是DFS+memo。不是很清楚为什么标的hard。dfs为int型,返回的就是在matrix的[x,y]这个坐标,最长的increasing path的长度。因为假设说我要求从[x,y]这个地方开始,它有一些increasing path,这些path的第二个节点一定是围着[x,y]的那一圈、并且值比matrix[x][y]大的元素,并且length(x,y) = length(newX, newY + 1)。最后求的最长的长度就是里面的最大值。 代码:

class Solution {
    private int[][] memo;
    private int m, n;
    private int[] dx = new int[] {0, -1, 0, 1};
    private int[] dy = new int[] {-1, 0, 1, 0};
    
    public int longestIncreasingPath(int[][] matrix) {
        m = matrix.length;
        n = matrix[0].length;
        memo = new int[m][n];
        
        int res = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                res = Math.max(res, dfs(matrix, i, j));
            }
        }
        return res;
    }
    
    private int dfs(int[][] matrix, int x, int y) {
        if (memo[x][y] != 0) {
            return memo[x][y];
        }
        
        int ans = 1;
        for (int i = 0; i < 4; i++) {
            int newX = x + dx[i];
            int newY = y + dy[i];
            if (!isValid(newX, newY) || matrix[newX][newY] <= matrix[x][y]) {
                continue;
            }
            ans = Math.max(ans, dfs(matrix, newX, newY) + 1);
        }
        
        memo[x][y] = ans;
        return ans;
    }
    
    private boolean isValid(int x, int y) {
        return x >= 0 && x < m && y >= 0 && y < n;
    }
}

LeetCode 301 Remove Invalid Parentheses

链接:leetcode.com/problems/re…

方法:DFS

时间复杂度:O(2l+r),其中l和r分别为字符串中多余的左、右括号 空间复杂度:O(n2) 想法:数据规模比较小,可以用DFS做。解法是看的zxi.mytechroad.com/blog/search… 。我一开始做这道题的时候觉得应该会有更好的做法,但确实也没想到。那这种做法就比较直接,就是先统计多余的左括号有多少个,多余的右括号有多少个,然后以这两个数,和遍历到字符串的index来做dfs,每次如果还有多余的左括号,并且目前搜到的这个地方对应的是左括号,就试图删它。有右括号同理。删完括号判定是不是valid就可以了。 代码:

class Pair {
    public int left, right;
    
    public Pair(int left, int right) {
        this.left = left;
        this.right = right;
    }
}

class Solution {
    public List<String> removeInvalidParentheses(String s) {
        Pair p = getLeftRight(s);
        int l = p.left, r = p.right;
        
        List<String> res = new ArrayList<>();
        dfs(s, l, r, 0, res);
        
        return res;
    }
    
    private void dfs(String s, int left, int right, int index, List<String> res) {
        if (left == 0 && right == 0) {
            if (isValid(s)) {
                res.add(s);
            }
            return;
        }
        
        for (int i = index; i < s.length(); i++) {
            if (i != index && s.charAt(i) == s.charAt(i - 1)) {
                continue;
            }
            char c = s.charAt(i);
            String tmp = s.substring(0, i) + s.substring(i + 1, s.length());
            if (c == '(' && left > 0) {
                dfs(tmp, left - 1, right, i, res);
            }
            else if (c == ')' && right > 0) {
                dfs(tmp, left, right - 1, i, res);
            }
        }
    }
    
    private boolean isValid(String s) {
        Pair p = getLeftRight(s);
        return p.left == 0 && p.right == 0;
    }
    
    private Pair getLeftRight(String s) {
        int left = 0, right = 0;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == '(') {
                left++;
            }
            else if (c == ')') {
                if (left > 0) {
                    left--;
                }
                else {
                    right++;
                }
            }
        }
        return new Pair(left, right);
    }
}