算法刷题打卡(一)

最小路径和: 64

64. 最小路径和 - 力扣(LeetCode) (leetcode-cn.com)

给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。

示例 1:

输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
输出:7
解释:因为路径 1→3→1→1→1 的总和最小。
示例 2:

输入:grid = [[1,2,3],[4,5,6]]
输出:12

题解:

dp[ i ] [ j ] 当前位置 向下或者向右 走 也就是说 从它的左边或者上边过来的。要最优解 也就是左边或者上边的最小值 + 上自己当前的。

数组第一行 只能依赖左边的数据 因为它没有上一行

数组第一列 只能依赖上边的数据 因为它没有左一列

   public int minPathSum(int[][] grid) {
	if (grid == null || grid.length == 0 || grid[0] == null || grid[0].length == 0) {
			return 0;
		}
		int row = grid.length;
		int col = grid[0].length;
		int[][] dp = new int[row][col];
		dp[0][0] = grid[0][0];
		for (int i = 1; i < row; i++) {
			dp[i][0] = dp[i - 1][0] + grid[i][0];
		}
		for (int j = 1; j < col; j++) {
			dp[0][j] = dp[0][j - 1] + grid[0][j];
		}
		for (int i = 1; i < row; i++) {
			for (int j = 1; j < col; j++) {
				dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
			}
		}
		return dp[row - 1][col - 1];
    }

此方法 需要 创建 grid的小的 一个 dp表

dp[ i ] [ j ] 只依赖它的 左 和它的上 省空间

准备 一个数组 直接在这个数组上 进行 自我更新!(按照数组 说的行 个)

第0 行 只依赖左 可以直接完成第一行, 第1行的 第一个数据 是依赖0行的 第一个 无左 下一个数据 需要的是左和上的数据 因为 1行第0个可以直接根据 0行0个 来进行更新, 所以 1 1的值 的左侧上边,选出小的就可以 自我更新。

    public int minPathSum(int[][] grid) {
        if (grid == null || grid.length == 0 || grid[0] == null || grid[0].length == 0){
            return 0;
        }
        int row = grid.length;
        int col = grid[0].length;
        int[] dp = new int[col];
        dp[0] = grid[0][0];
        for (int j = 1; j < col; j++) {
            dp[j] = dp[j - 1] + grid[0][j];
        }
        for (int i = 1; i < row; i++) {
            dp[0] += grid[i][0];
            for (int j = 1; j < col; j++) {
                dp[j] = Math.min(dp[j], dp[j - 1]) + grid[i][j];
            }
        }
        return dp[col - 1];
    }

只出现一次的数字Ⅲ 260

260. 只出现一次的数字 III - 力扣(LeetCode) (leetcode-cn.com)

给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。

进阶:你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?

示例 1:

输入:nums = [1,2,1,3,2,5]
输出:[3,5]
解释:[5, 3] 也是有效的答案。
示例 2:

输入:nums = [-1,0]
输出:[-1,0]
示例 3:

输入:nums = [0,1]
输出:[1,0]
提示:

2 <= nums.length <= 3 * 104
-231 <= nums[i] <= 231 - 1
除两个只出现一次的整数外,nums 中的其他数字都出现两次

题解:异或运算,只有两个元素出现一次。

在异或中 a^a =0, 所有 整个数组 异或最后的结果就是 只出现一次的两个元素的异或结果。

取出最右侧的1 因为两个数异或

​ 1001100

^ 0101010

​ 1100110 取出最右侧的1 之后 就肯定会得到其中的一个 , 在与整个数组异或的结果异或 就能得到另一个。

   public int[] singleNumber(int[] nums) {
        int eor=0;
        for(int i =0; i < nums.length; i++){
           eor^=nums[i];
        }
        int right = eor & (-eor);
        int other = 0;
        for(int i = 0; i< nums.length; i++){
            if((nums[i] & right) != 0 ){ 
                other^=nums[i];
            }
        }
       return new int[]{other,other^eor};
    }

滑动窗口最大值 239

239. 滑动窗口最大值 - 力扣(LeetCode) (leetcode-cn.com)

暴力解…就每个新的拿出最大值。好像是超出时间限制

public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums == null || k < 1 || nums.length < k) {
            return null;
        }
        int N = nums.length;
        int[] res = new int[N - k + 1];
        int index = 0;
        int L = 0;
        int R = k - 1;
        while (R < N) {
            int max = nums[L];
            for (int i = L + 1; i <= R; i++) {
                max = Math.max(max, nums[i]);

            }
            res[index++] = max;
            L++;
            R++;
        }
        return res;
    }
  1. 准备队列 按照大到小存放数据。 队列存 的是下标。在来到新的值的时候 需要与队列的进行判断 如果新到来的小直接放在尾部

如果大,队列尾部扔掉不要,在比较大接着扔掉不要 直到新来的数找到位置。加入到队列的尾部。

此题窗口为3, 在窗口移动时,需要去判断 队列中的数 还可不可以用(是不是在窗口范围内) ,如果不在 扔掉它。R-K是不在窗口内的下标。

当R >= k-1 形成窗口 的时候拿出当前的最大值就是队列的first

 public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums == null || k < 1 || nums.length < k) {
            return null;
        }
        LinkedList<Integer> lMax = new LinkedList<>();
        int[] res = new int[nums.length - k + 1];
        int index = 0;
        for(int R =0; R < nums.length; R++){
            while(!lMax.isEmpty() && nums[lMax.peekLast()] <= nums[R]){
                lMax.pollLast();
            }
            lMax.addLast(R);
            if(lMax.peekFirst() == R-k){
                lMax.pollFirst();
            }
            if(R >= k-1){
                res[index++] = nums[lMax.peekFirst()];
            }
        }
        return res;
    }

柱状图中最大矩形 84

84. 柱状图中最大的矩形 - 力扣(LeetCode) (leetcode-cn.com)

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10

输入: heights = [2,4]
输出: 4

解题:以index 的值 为高 能扩多远 扩出来的个数*自己 枚举每一个高求出最好的答案

    public int largestRectangleArea(int[] heights) {
         if (heights == null || heights.length == 0) {
            return 0;
        }
        int maxArea = 0;
        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < heights.length; i++) {
            while (!stack.isEmpty() && heights[i] <= heights[stack.peek()]) {
                int j = stack.pop();
                int k = stack.isEmpty() ? -1 : stack.peek();
                int curArea = heights[j] * (i - k - 1);
                maxArea = Math.max(curArea, maxArea);
            }
            stack.push(i);
        }
        while (!stack.isEmpty()) {
            int j = stack.pop();
            int k = stack.isEmpty() ? -1 : stack.peek();
            int curArea = heights[j] * (heights.length - k - 1);
            maxArea = Math.max(curArea, maxArea);
        }
        return maxArea;
    }

最大矩形85

85. 最大矩形 - 力扣(LeetCode) (leetcode-cn.com)

给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

示例 1:

输入:matrix = [[“1”,“0”,“1”,“0”,“0”],[“1”,“0”,“1”,“1”,“1”],[“1”,“1”,“1”,“1”,“1”],[“1”,“0”,“0”,“1”,“0”]]
输出:6
解释:最大矩形如上图所示。
示例 2:

输入:matrix = []
输出:0
示例 3:

输入:matrix = [[“0”]]
输出:0
示例 4:

输入:matrix = [[“1”]]
输出:1
示例 5:

输入:matrix = [[“0”,“0”]]
输出:0

解题:压缩数组 + 单调栈

以 第0行作底 1行做底… 有0高度归0 n 行 每一行按照高度扩 求出最大值

[1,1,1,0,1,1] [1,1,1,0,1,1]

[0,1,0,1,0,0] [0,2,0,1,0,0]

[1,1,1,1,0,1] -> [1,3,1,2,0,1]

[1,1,1,1,0,0] [2,4,2,3,0,0]

  public int maximalRectangle(char[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return 0;
        }
        int maxArea = 0;
        int[] height = new int[matrix[0].length];
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                height[j] = matrix[i][j] == '0' ? 0 : height[j] + 1;
            }
            maxArea = Math.max(MaximumValuePerLine(height), maxArea);
        }
        return maxArea;
    }
    public static int MaximumValuePerLine(int[] height) {
        if (height == null || height.length == 0) {
            return 0;
        }
        int maxArea = 0;
        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < height.length; i++) {
            while (!stack.isEmpty() && height[i] <= height[stack.peek()]) {
                int j = stack.pop();
                int k = stack.isEmpty() ? -1 : stack.peek();
                int curArea = height[j] * (i - k - 1);
                maxArea = Math.max(curArea, maxArea);
            }
            stack.push(i);
        }
        while (!stack.isEmpty()) {
            int j = stack.pop();
            int k = stack.isEmpty() ? -1 : stack.peek();
            int curArea = height[j] * (height.length - k - 1);
            maxArea = Math.max(curArea, maxArea);
        }
        return maxArea;
    }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值