美文网首页
Leetcode数组II

Leetcode数组II

作者: 1nvad3r | 来源:发表于2020-10-22 20:01 被阅读0次

55. 跳跃游戏

动态规划:

class Solution {
    public boolean canJump(int[] nums) {
        int len = nums.length;
        if (len == 0) {
            return false;
        }
        boolean[] dp = new boolean[len];
        dp[len - 1] = true;
        for (int i = len - 2; i >= 0; i--) {
            if (nums[i] == 0) {
                dp[i] = false;
            } else if (nums[i] + i >= len - 1) {
                dp[i] = true;
            } else {
                for (int j = i + 1; j <= i + nums[i]; j++) {
                    if (dp[j] == true) {
                        dp[i] = true;
                        break;
                    }
                }
            }
        }
        return dp[0];
    }
}

一次遍历:
不断记录最远可到达距离,只要当前位置大于最远可到达距离,就返回false。

class Solution {
    public boolean canJump(int[] nums) {
        int maxPosition = 0;
        for (int i = 0; i < nums.length; i++) {
            if (i > maxPosition) {
                return false;
            }
            maxPosition = Math.max(i + nums[i], maxPosition);
        }
        return true;
    }
}

56. 合并区间

给出一个区间的集合,请合并所有重叠的区间。
先把二维数组按照左区间从小到大的顺序排序,初始左区间为第一个区间的左区间,右区间为第一个区间的右区间。然后按顺序遍历剩余的所有数组,当某个区间的左区间比之前最大的右区间还大时,肯定合并不了了,把之前确定好的左右区间加入到list中,然后左右区间设定为当前区间,继续遍历。
否则更新右区间的大小,取当前右区间与之前最大右区间的较大值。
最后将list<int[]>转换为二维数组即可。

class Solution {
    public int[][] merge(int[][] intervals) {
        if (intervals.length == 0) {
            return new int[0][2];
        }
        List<int[]> res = new ArrayList<>();
        Arrays.sort(intervals, Comparator.comparingInt(a -> a[0]));
        int left = intervals[0][0], right = intervals[0][1];
        for (int i = 1; i < intervals.length; i++) {
            if (intervals[i][0] > right) {
                res.add(new int[]{left, right});
                left = intervals[i][0];
                right = intervals[i][1];
            } else {
                right = Math.max(right, intervals[i][1]);
            }
        }
        res.add(new int[]{left, right});
        return res.toArray(new int[res.size()][]);
    }
}

57. 插入区间

遍历原有的区间,判断与待插入的区间是否有交集。
如果两个区间,左区间的较大值小于等于右区间的较小值,那么有交集。
如果和新区间没有交集,那么直接加到结果集中,如果有交集,新区间更新为并集的左端点和右端点。然后再将后面的区间与更新之后的新区间进行比较。
最后使用 Collections.sort解决区间仍然有序的问题。

class Solution {
    public boolean isIntersection(int[] interval, int[] newInterval) {
        int L1 = interval[0], R1 = interval[1], L2 = newInterval[0], R2 = newInterval[1];
        if (Math.max(L1, L2) <= Math.min(R1, R2)) {
            return true;
        } else {
            return false;
        }
    }


    public int[][] insert(int[][] intervals, int[] newInterval) {
        if (intervals.length == 0) {
            return new int[][]{newInterval};
        }
        List<int[]> res = new ArrayList<>();
        for (int[] interval : intervals) {
            if (isIntersection(interval, newInterval) == true) {
                newInterval[0] = Math.min(interval[0], newInterval[0]);
                newInterval[1] = Math.max(interval[1], newInterval[1]);
            } else {
                res.add(interval);
            }
        }
        res.add(newInterval);
        Collections.sort(res, Comparator.comparingInt(a -> a[0]));
        return res.toArray(new int[res.size()][]);
    }
}

59. 螺旋矩阵 II

54.螺旋矩阵思路一模一样。

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] res = new int[n][n];
        int L = 0, R = n - 1, U = 0, D = n - 1;
        int num = 1;
        while (true) {
            for (int i = L; i <= R; i++) {
                res[U][i] = num++;
            }
            if (++U > D) {
                break;
            }
            for (int i = U; i <= D; i++) {
                res[i][R] = num++;
            }
            if (L > --R) {
                break;
            }
            for (int i = R; i >= L; i--) {
                res[D][i] = num++;
            }
            if (U > --D) {
                break;
            }
            for (int i = D; i >= U; i--) {
                res[i][L] = num++;
            }
            if (++L > R) {
                break;
            }
        }
        return res;
    }
}

66. 加一

class Solution {
    public int[] plusOne(int[] digits) {
        for (int i = digits.length - 1; i >= 0; i--) {
            digits[i]++;
            digits[i] %= 10;
            if (digits[i] != 0) {
                return digits;
            }
        }
        digits = new int[digits.length + 1];
        digits[0] = 1;
        return digits;
    }
}

73. 矩阵置零

比较容易想到的方法是先遍历一次,记录所有0对应的行和列。
然后再把这些行和列都置0。
时间复杂度O(mn),空间复杂度O(m+n)。

class Solution {
    public void setZeroes(int[][] matrix) {
        Set<Integer> row = new HashSet<>(), col = new HashSet<>();
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                if (matrix[i][j] == 0) {
                    row.add(i);
                    col.add(j);
                }
            }
        }
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                if (row.contains(i) || col.contains(j)) {
                    matrix[i][j] = 0;
                }
            }
        }
    }
}

优化:
用每一行的第一个数记录该行是否有0,如果有则该行第一个数记为0。
用每一列的第一个数记录该列是否有0,如果有则该列第一个数记为0。
额外用两个变量记录第一行和第一列是否有0。
空间复杂度O(1)

class Solution {
    public void setZeroes(int[][] matrix) {
        boolean rowFlag = false, colFlag = false;//第一行第一列是否有0
        for (int j = 0; j < matrix[0].length; j++) {
            if (matrix[0][j] == 0) {
                rowFlag = true;
                break;
            }
        }
        for (int i = 0; i < matrix.length; i++) {
            if (matrix[i][0] == 0) {
                colFlag = true;
                break;
            }
        }
        for (int i = 1; i < matrix.length; i++) {
            for (int j = 1; j < matrix[0].length; j++) {
                if (matrix[i][j] == 0) {
                    matrix[0][j] = matrix[i][0] = 0;
                }
            }
        }
        for (int i = 1; i < matrix.length; i++) {
            for (int j = 1; j < matrix[0].length; j++) {
                if (matrix[i][0] == 0 || matrix[0][j] == 0) {
                    matrix[i][j] = 0;
                }
            }
        }
        if (rowFlag == true) {
            for (int j = 0; j < matrix[0].length; j++) {
                matrix[0][j] = 0;
            }
        }
        if (colFlag == true) {
            for (int i = 0; i < matrix.length; i++) {
                matrix[i][0] = 0;
            }
        }
    }
}

74. 搜索二维矩阵

将二维数组想象成一维的,然后使用二分查找。
mid在二维数组中的位置是 [mid / col][mid % col]。

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        if (matrix.length == 0) {
            return false;
        }
        int row = matrix.length, col = matrix[0].length;
        int lo = 0, hi = row * col - 1;
        int mid;
        while (lo <= hi) {
            mid = lo + (hi - lo) / 2;
            if (matrix[mid / col][mid % col] == target) {
                return true;
            } else if (matrix[mid / col][mid % col] > target) {
                hi--;
            } else {
                lo++;
            }
        }
        return false;
    }
}

75. 颜色分类

一次遍历,用p0,p2,cur来分别追踪0的最右边界,2的最左边界,当前考虑的元素。
初始p0 = 0,p2 = nums.length-1,cur = 0
cur从左往右扫描,当nums[cur]等于0时,与p0位置的元素交换位置,并p0加1,cur加1。
当nums[cur]等于1时,继续往右扫描,cur加1。当nums[cur]等于2时,与p2位置的元素交换位置,并p2减1,注意此时cur不加。 直到cur大于p2时就可以停止了。

class Solution {
    public void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }

    public void sortColors(int[] nums) {
        int p0 = 0, p2 = nums.length - 1, cur = 0;
        while (cur <= p2) {
            if (nums[cur] == 0) {
                swap(nums, cur++, p0++);
            } else if (nums[cur] == 1) {
                cur++;
            } else if (nums[cur] == 2) {
                swap(nums, cur, p2--);
            }
        }
    }
}

78. 子集

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> temp = new ArrayList<>();

    public void dfs(int begin, int[] nums) {
        if (begin == nums.length) {
            return;
        }
        for (int i = begin; i < nums.length; i++) {
            temp.add(nums[i]);
            res.add(new ArrayList<>(temp));
            dfs(i + 1, nums);
            temp.remove(temp.size() - 1);
        }
    }

    public List<List<Integer>> subsets(int[] nums) {
        res.add(new ArrayList<>());
        dfs(0, nums);
        return res;
    }
}

79. 单词搜索

class Solution {
    int[] X = {-1, 0, 1, 0};//左上右下
    int[] Y = {0, -1, 0, 1};
    boolean[][] isVisit;

    public boolean check(int i, int j, int index, char[][] board, String word) {
        if (i < 0 || i >= board.length || j < 0 || j >= board[0].length) {
            return false;
        }
        if (isVisit[i][j] == true) {
            return false;
        }
        if (word.charAt(index) == board[i][j]) {
            return true;
        } else {
            return false;
        }
    }

    public boolean dfs(int i, int j, int index, char[][] board, String word) {
        if (index == word.length()) {
            return true;
        }
        if (check(i, j, index, board, word) == true) {
            isVisit[i][j] = true;
            for (int flag = 0; flag < 4; flag++) {
                int newI = i + X[flag], newJ = j + Y[flag];
                if (dfs(newI, newJ, index + 1, board, word) == true) {
                    return true;
                }
            }
            isVisit[i][j] = false;
        } else {
            return false;
        }
        return false;
    }

    public boolean exist(char[][] board, String word) {
        isVisit = new boolean[board.length][board[0].length];
        if (board.length == 0) {
            return false;
        }
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if (dfs(i, j, 0, board, word) == true) {
                    return true;
                }
            }
        }
        return false;
    }
}

80. 删除排序数组中的重复项 II

class Solution {
    public int removeDuplicates(int[] nums) {
        if (nums.length == 0) {
            return 0;
        }
        int count = 0, pos = 0;
        for (int i = 0; i < nums.length; i++) {
            if (i == 0) {
                count = 1;
            } else {
                if (nums[i] == nums[i - 1]) {
                    count++;
                } else {
                    count = 1;
                }
            }
            if (count <= 2) {
                nums[pos++] = nums[i];
            }
        }
        return pos;
    }
}

81. 搜索旋转排序数组 II

class Solution {
    public boolean search(int[] nums, int target) {
        int lo = 0, hi = nums.length - 1;
        while (lo <= hi) {
            int mid = lo + (hi - lo) / 2;
            if (nums[mid] == target) {
                return true;
            }
            if (nums[lo] == nums[mid]) {
                lo++;
                continue;
            }
            if (nums[lo] < nums[mid]) {
                if (nums[mid] > target && nums[lo] <= target) {
                    hi = mid - 1;
                } else {
                    lo = mid + 1;
                }
            } else { //此时mid右侧都是递增的
                if (nums[mid] < target && nums[hi] >= target) {
                    lo = mid + 1;
                } else {
                    hi = mid - 1;
                }
            }
        }
        return false;
    }
}

84. 柱状图中最大的矩形

暴力法:

class Solution {
    public int largestRectangleArea(int[] heights) {
        int res = 0;
        for (int i = 0; i < heights.length; i++) {
            int height = heights[i];
            int lo = i - 1, hi = i + 1;
            while (lo >= 0 && heights[lo] >= height) {
                lo--;
            }
            while (hi <= heights.length - 1 && heights[hi] >= height) {
                hi++;
            }
            res = Math.max(res, (hi - lo - 1) * height);
        }
        return res;
    }
}

优化:单调栈

class Solution {
    public int largestRectangleArea(int[] heights) {
        if (heights.length == 0) {
            return 0;
        }
        Deque<Integer> stack = new ArrayDeque<>();
        int res = heights[0];
        stack.push(0);
        for (int i = 1; i < heights.length; i++) {
            while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) {
                int height = heights[stack.pop()];
                res = stack.isEmpty() ? Math.max(res, height * (i)) : Math.max(res, height * (i - stack.peek() - 1));
            }
            stack.push(i);
        }
        while (!stack.isEmpty()) {
            int height = heights[stack.pop()];
            int lo = stack.isEmpty() ? -1 : stack.peek(), hi = heights.length;
            res = Math.max(res, (hi - lo - 1) * height);
        }
        return res;
    }
}

继续优化,左右各加一个高度为0的柱子,可以不用判断栈空情况,使代码更简单。

class Solution {
    public int largestRectangleArea(int[] heights) {
        if (heights.length == 0) {
            return 0;
        }
        Deque<Integer> stack = new ArrayDeque<>();
        int[] newHeights = new int[heights.length + 2];
        System.arraycopy(heights, 0, newHeights, 1, heights.length);
        int res = 0;
        stack.push(0);
        for (int i = 1; i < newHeights.length; i++) {
            while (newHeights[i] < newHeights[stack.peek()]) {
                int height = newHeights[stack.pop()];
                res = Math.max(res, height * (i - stack.peek() - 1));
            }
            stack.push(i);
        }
        return res;
    }
}

85. 最大矩形

class Solution {
    public int largestRectangleArea(int[] heights) {
        if (heights.length == 0) {
            return 0;
        }
        Deque<Integer> stack = new ArrayDeque<>();
        int[] newHeights = new int[heights.length + 2];
        System.arraycopy(heights, 0, newHeights, 1, heights.length);
        int res = 0;
        stack.push(0);
        for (int i = 1; i < newHeights.length; i++) {
            while (newHeights[i] < newHeights[stack.peek()]) {
                int height = newHeights[stack.pop()];
                res = Math.max(res, height * (i - stack.peek() - 1));
            }
            stack.push(i);
        }
        return res;
    }

    public int maximalRectangle(char[][] matrix) {
        if (matrix.length == 0) {
            return 0;
        }
        int res = 0;
        int[] heights = new int[matrix[0].length];
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                if (matrix[i][j] == '1') {
                    heights[j] += 1;
                } else {
                    heights[j] = 0;
                }
            }
            res = Math.max(res, largestRectangleArea(heights));
        }
        return res;
    }
}

88. 合并两个有序数组

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int pos = m + n - 1, pos1 = m - 1, pos2 = n - 1;
        while (pos >= 0) {
            if (pos1 < 0) {
                while (pos2 >= 0) {
                    nums1[pos--] = nums2[pos2--];
                }
                break;
            }
            if (pos2 < 0) {
                while (pos1 >= 0) {
                    nums1[pos--] = nums1[pos1--];
                }
                break;
            }
            if (nums1[pos1] > nums2[pos2]) {
                nums1[pos--] = nums1[pos1--];
            } else {
                nums1[pos--] = nums2[pos2--];
            }
        }
    }
}

90. 子集 II

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> temp = new ArrayList<>();

    public void dfs(int begin, int[] nums) {
        if (begin == nums.length) {
            return;
        }
        for (int i = begin; i < nums.length; i++) {
            if (i - 1 >= begin && nums[i] == nums[i - 1]) {
                continue;
            }
            temp.add(nums[i]);
            res.add(new ArrayList<>(temp));
            dfs(i + 1, nums);
            temp.remove(temp.size() - 1);
        }
    }

    public List<List<Integer>> subsetsWithDup(int[] nums) {
        res.add(new ArrayList<>());
        Arrays.sort(nums);
        dfs(0, nums);
        return res;
    }
}

105. 从前序与中序遍历序列构造二叉树

class Solution {
    public TreeNode build(int preL, int preR, int inL, int inR, int[] preOrder, int[] inOrder) {
        if (preL > preR) {
            return null;
        }
        int rootVal = preOrder[preL];
        TreeNode root = new TreeNode(rootVal);
        int index;
        for (index = inL; index <= inR; index++) {
            if (inOrder[index] == rootVal) {
                break;
            }
        }
        int leftNum = index - inL;
        root.left = build(preL + 1, preL + leftNum, inL, inL + leftNum, preOrder, inOrder);
        root.right = build(preL + leftNum + 1, preR, index + 1, inR, preOrder, inOrder);
        return root;

    }


    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return build(0, preorder.length - 1, 0, inorder.length - 1, preorder, inorder);
    }
}

106. 从中序与后序遍历序列构造二叉树

class Solution {
    public TreeNode helper(int[] inorder, int[] postorder, int inL, int inR, int postL, int postR) {
        if (inL > inR) {
            return null;
        }
        int rootVal = postorder[postR];
        TreeNode root = new TreeNode(rootVal);
        int index;//根结点在中序遍历中的位置
        for (index = inL; index <= inR; index++) {
            if (inorder[index] == rootVal) {
                break;
            }
        }
        int numLeft = index - inL;//左子树个数
        root.left = helper(inorder, postorder, inL, inL + numLeft - 1, postL, postL + numLeft - 1);
        root.right = helper(inorder, postorder, index + 1, inR, postL + numLeft, postR - 1);
        return root;
    }

    public TreeNode buildTree(int[] inorder, int[] postorder) {
        return helper(inorder, postorder, 0, inorder.length - 1, 0, postorder.length - 1);
    }
}

118. 杨辉三角

class Solution {
    List<List<Integer>> res = new ArrayList<>();

    public List<Integer> getNline(int n) {
        List<Integer> list = new ArrayList<>();
        for (int i = 1; i <= n; i++) {
            if (i == 1 || i == n) {
                list.add(1);
                continue;
            }
            list.add(res.get(n - 2).get(i - 2) + res.get(n - 2).get(i - 1));
        }
        return list;
    }

    public List<List<Integer>> generate(int numRows) {
        for (int i = 1; i <= numRows; i++) {
            res.add(getNline(i));
        }
        return res;
    }
}

119. 杨辉三角 II

class Solution {
    public List<Integer> getRow(int rowIndex) {
        List<Integer> pre = new ArrayList<>(), cur = new ArrayList<>();
        pre.add(1);
        for (int i = 1; i <= rowIndex; i++) {
            for (int j = 1; j <= i + 1; j++) {
                if (j == 1 || j == i + 1) {
                    cur.add(1);
                    continue;
                }
                cur.add(pre.get(j - 2) + pre.get(j - 1));
            }
            pre = new ArrayList<>(cur);
            cur.clear();
        }
        return pre;
    }
}

120. 三角形最小路径和

class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        int len = triangle.size();
        int[] pre = new int[len];
        for (int i = 0; i < triangle.get(len - 1).size(); i++) {
            pre[i] = triangle.get(len - 1).get(i);
        }
        for (int i = len - 2; i >= 0; i--) {
            for (int j = 0; j <= i; j++) {
                pre[j] = Math.min(pre[j], pre[j + 1]) + triangle.get(i).get(j);
            }
        }
        return pre[0];
    }
}

121. 买卖股票的最佳时机

class Solution {
    public int maxProfit(int[] prices) {
        int res = 0, minPrice = Integer.MAX_VALUE;
        for (int i = 0; i < prices.length; i++) {
            minPrice = Math.min(minPrice, prices[i]);
            res = Math.max(res, prices[i] - minPrice);
        }
        return res;
    }
}
class Solution {
    public int maxProfit(int[] prices) {
        if (prices.length == 0) {
            return 0;
        }
        int[][] dp = new int[prices.length][2];
        dp[0][0] = 0;
        dp[0][1] = -prices[0];
        for (int i = 1; i < prices.length; i++) {
            dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            dp[i][1] = Math.max(dp[i - 1][1], 0 - prices[i]);
        }
        return dp[prices.length - 1][0];
    }
}

122. 买卖股票的最佳时机 II

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        if (len == 0) {
            return 0;
        }
        int[][] dp = new int[len][2];
        dp[0][0] = 0;
        dp[0][1] = -prices[0];
        for (int i = 1; i < len; i++) {
            dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
        }
        return dp[len - 1][0];
    }
}

123. 买卖股票的最佳时机 III

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        if (len == 0) {
            return 0;
        }
        int[][][] dp = new int[len][3][2];
        for (int i = 1; i <= 2; i++) {
            dp[0][i][0] = 0;
            dp[0][i][1] = -prices[0];
        }
        for (int i = 1; i < len; i++) {
            for (int j = 1; j <= 2; j++) {
                dp[i][j][0] = Math.max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i]);
                dp[i][j][1] = Math.max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i]);
            }
        }
        return dp[len - 1][2][0];
    }
}

相关文章

网友评论

      本文标题:Leetcode数组II

      本文链接:https://www.haomeiwen.com/subject/nciemktx.html