leetcode-day7

78.给你一个整数数组 nums ,数组中的元素互不相同。返回该数组所有可能的子集(幂集)。
解集不能包含重复的子集。你可以按任意顺序返回解集。
迭代法实现子集枚举:

class Solution {
    //我们用 1 表示「在子集中」,0 表示不在子集中,那么每一个子集可以对应一个长度为 n 的 0/1序列,第 i 位表示 ai 是否在子集中。
    List<Integer> t = new ArrayList<Integer>();
    List<List<Integer>> ans = new ArrayList<List<Integer>>();
    public List<List<Integer>> subsets(int[] nums) {
        int n = nums.length;
        for (int mask = 0; mask < (1 << n); mask++) {//1 << n:1的二进制左移n位再转成10进制
            t.clear();
            for (int i = 0; i < n; i++) {
                //https://blog.csdn.net/feiyu_diary/article/details/78802996
                //用于判断mask的第i位是否为0
                if ((mask & (1 << i)) != 0) {
                    t.add(nums[i]);
                }
            }
            ans.add(new ArrayList<Integer>(t));
        }
        return ans;
    }
}

递归法实现子集枚举:

class Solution {
    List<Integer> t = new ArrayList<Integer>();
    List<List<Integer>> ans = new ArrayList<List<Integer>>();
    public List<List<Integer>> subsets(int[] nums) {
        dfs(0, nums);
        return ans;
    }
    public void dfs(int cur, int[] nums) {
        if (cur == nums.length) {
            //记录答案
            ans.add(new ArrayList<Integer>(t));
            return;
        }
        //考虑选择当前位置(二进制当前位置为1)
        t.add(nums[cur]);
        dfs(cur + 1, nums);
        t.remove(t.size() - 1);//再移出t中最后一个元素
        //考虑不选择当前位置(二进制当前位置为0)
        dfs(cur + 1, nums);
    }
}

79.给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
dfs+回溯:

class Solution {
    public boolean exist(char[][] board, String word) {
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                if (board[i][j] == word.charAt(0) && dfs(board, word, i, j, 0)) {
                    return true;
                }
            }
        }
        return false;
    }
    public boolean dfs(char[][] board, String word, int i, int j, int k) {
        if (k == word.length()) {
            return true;
        }
        if (i < 0 || j < 0 || i >= board.length || j >= board[i].length) {
            return false;
        }
        if (word.charAt(k) != board[i][j]) {
            return false;
        }
        char t = board[i][j];
        board[i][j] = '0';//表示访问过了
        //下一个位置所以k+1,然后ij的变化分别为一个点的四个方位
        boolean res = dfs(board, word, i + 1, j, k + 1) ||dfs(board, word, i - 1, j, k + 1) || 
        dfs(board, word, i, j + 1, k + 1) || dfs(board, word, i, j - 1, k + 1);
        board[i][j] = t;//还原
        return res;
    }
}

84.给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为1。求在该柱状图中,能够勾勒出来的矩形的最大面积。
单调栈:

class Solution {
    public int largestRectangleArea(int[] heights) {
        int n = heights.length;
        int[] left = new int[n];
        int[] right = new int[n];
        Deque<Integer> stack = new ArrayDeque<Integer>();
        //单调递减栈
        for (int i = 0; i < n; i++) {
            while (!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
                stack.pop();
            }
            left[i] = (stack.isEmpty() ? -1 : stack.peek());
            stack.push(i);
        }
        stack.clear();
        for (int i = n - 1; i >= 0; i--) {
            while (!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
                stack.pop();
            }
            right[i] = (stack.isEmpty() ? n : stack.peek());
            stack.push(i);
        }
        int ans = 0;
        for (int i = 0; i < n; i++) {
            ans = Math.max(ans, (right[i] - left[i] - 1) * heights[i]);
        }
        return ans;
    }
}

单调栈 + 常数优化:

class Solution {
    public int largestRectangleArea(int[] heights) {
        int n = heights.length;
        int[] left = new int[n];
        int[] right = new int[n];
        Arrays.fill(right, n);
        Deque<Integer> stack = new ArrayDeque<Integer>();
        for (int i = 0; i < n; ++i) {
            while (!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
                right[stack.peek()] = i;
                stack.pop();
            }
            left[i] = (stack.isEmpty() ? -1 : stack.peek());
            stack.push(i);
        }
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            ans = Math.max(ans, (right[i] - left[i] - 1) * heights[i]);
        }
        return ans;
    }
}

85.给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。(结合第84题)
暴力解法优化:

class Solution {
    public int maximalRectangle(char[][] matrix) {
        int n = matrix.length;
        if(n == 0) return 0; //若n=0,不存在矩阵
        int m = matrix[0].length;
        int[][] matrix1 = new int[n][m];
        for(int i = 0;i < m;i++){
            if(matrix[0][i] == '1') matrix1[0][i] = 1;
        }
        for(int i = 1;i < n;i++){
            for(int j = 0;j < m;j++){
                if(matrix[i][j] == '1') 
                matrix1[i][j] = matrix1[i - 1][j] + 1;
                else
                matrix1[i][j] = 0;
            }
        }
        int ans = 0;
        for(int i = 0;i < n;i++){
            for(int j = 0;j < m;j++){
                //这一行计算的面积根本不会超过ans则进入下一行
                if(matrix1[i][j] * m <= ans) continue;
                int cnt = 1; //现在只有它自己
                for(int k = j + 1;k < m;k++){
                    if(matrix1[i][k] < matrix1[i][j]) break;
                    cnt++;
                }
                for(int k = j - 1;k >= 0;k--){
                    if(matrix1[i][k] < matrix1[i][j]) break;
                    cnt++;
                }
                ans = Math.max(ans, cnt * matrix1[i][j]);
            }
        }
        return ans;
    }
}

类似于单调栈的方法:

class Solution {
    public int maximalRectangle(char[][] matrix) {
        if (matrix.length == 0 || matrix[0].length == 0) { //行数或列数为0,不存在矩阵
            return 0;
        }
        int[] heights = new int[matrix[0].length];
        int maxArea = 0; //初始化为0
        for (int row = 0; row < matrix.length; row++) {
            //遍历每一列,更新高度
            for (int col = 0; col < matrix[0].length; col++) {
                if (matrix[row][col] == '1') {
                    heights[col] += 1;
                } else {
                    heights[col] = 0;
                }
            }
            //调用函数更新面积
            maxArea = Math.max(maxArea, largestRectangleArea(heights));
        }
        return maxArea;
    }
    public int largestRectangleArea(int[] heights) {
        //求每个柱子的左边第一个小的柱子的下标
        int[] leftLessMin = new int[heights.length];
        leftLessMin[0] = -1; //第一个柱子前边没有柱子,所以赋值为 -1,便于计算面积  
        for (int i = 1; i < heights.length; i++) {
            int l = i - 1; //当前柱子更小一些,进行左移
            while (l >= 0 && heights[l] >= heights[i]) {
                l = leftLessMin[l];
            }
            leftLessMin[i] = l;
        }
        //求每个柱子的右边第一个小的柱子的下标
        int[] rightLessMin = new int[heights.length];
        rightLessMin[heights.length - 1] = heights.length;
        for (int i = heights.length - 2; i >= 0; i--) {
            int r = i + 1;
            while (r <= heights.length - 1 && heights[r] >= heights[i]) {
                r = rightLessMin[r];
            }
            rightLessMin[i] = r;
        }
        //求包含每个柱子的矩形区域的最大面积,选出最大的
        int maxArea = 0;
        for (int i = 0; i < heights.length; i++) {
            int area = (rightLessMin[i] - leftLessMin[i] - 1) * heights[i];
            maxArea = Math.max(area, maxArea);
        }
        return maxArea;
    }
}

单调栈+常数优化:

class Solution {
    public int maximalRectangle(char[][] matrix) {
        if (matrix.length == 0 || matrix[0].length == 0) { //行数或列数为0,不存在矩阵
            return 0;
        }
        int[] heights = new int[matrix[0].length];
        int maxArea = 0; //初始化为0
        for (int row = 0; row < matrix.length; row++) {
            //遍历每一列,更新高度
            for (int col = 0; col < matrix[0].length; col++) {
                if (matrix[row][col] == '1') {
                    heights[col] += 1;
                } else {
                    heights[col] = 0;
                }
            }
            //调用函数更新面积
            maxArea = Math.max(maxArea, largestRectangleArea(heights));
        }
        return maxArea;
    }
    public int largestRectangleArea(int[] heights) {
        int n = heights.length;
        int[] left = new int[n];
        int[] right = new int[n];
        Arrays.fill(right, n);
        Deque<Integer> stack = new ArrayDeque<Integer>();
        for (int i = 0; i < n; ++i) {
            while (!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
                right[stack.peek()] = i;
                stack.pop();
            }
            left[i] = (stack.isEmpty() ? -1 : stack.peek());
            stack.push(i);
        }
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            ans = Math.max(ans, (right[i] - left[i] - 1) * heights[i]);
        }
        return ans;
    }
}

你可能感兴趣的:(leetcode,深度优先,算法)