leetcode 50-100题-java版(按顺序,不分专题)

(53)最大子序和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1]
输出:1
思路:一般情况下,两个数组或两个字符串,都需要双指针,二维dp;但是一维数组和一个字符串情况下,要先考虑一维dp函数可行否。本题:dp[i] 表示以下标i结尾的子数组的最大和。i为状态,就是下标的一次遍历;dp[i]就是想要的结果;选择就是 nums[i] 和 nums[i] + dp[i-1]谁更大;basecase也简单。

class Solution {
   
    public int maxSubArray(int[] nums) {
   
        // 可以用一维dp,也可以用二维dp和双指针;但能一维就不二维
        // 以后遇到题先考虑一维行不行,再考虑二维

        // dp[i] 表示以下标i结尾的子数组的最大和。i为状态,就是下标的一次遍历;dp[i]就是想要的结果;
        // 选择就是 nums[i] 和 nums[i] + dp[i-1]谁更大;basecase也简单

        // int n = nums.length;
        // if(n==1)
        //     return nums[0];
        // int [] dp = new int[n];
        // dp[0] = nums[0];
        // int ans=dp[0];
        // for(int i=1; i<n; i++){
   
        //     dp[i] = Math.max(nums[i], nums[i]+dp[i-1]);
        //     ans = ans>dp[i]?ans:dp[i];
        // }
        // return ans;
        
        // 因为dp[i]只和上一个状态dp[i-1]有关,所以可以不用dp数组,只用一个变量

        int n = nums.length;
        if(n==1)
            return nums[0];
        int ans = nums[0];
        int dp_i = nums[0];
        for(int i=1; i<n; i++){
   
            dp_i = Math.max(nums[i], nums[i]+dp_i);
            ans = ans>dp_i?ans:dp_i;
        }
        return ans;
    }
}

(58)最后一个单词的长度

给你一个字符串 s,由若干单词组成,单词之间用空格隔开。返回字符串中最后一个单词的长度。如果不存在最后一个单词,请返回 0 。单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。
示例 1:
输入:s = “Hello World”
输出:5
示例 2:
输入:s = " "
输出:0

提示:
1 <= s.length <= 104
s 仅有英文字母和空格 ’ ’ 组成

思路:从后向前遍历就可

class Solution {
   
    public int lengthOfLastWord(String s) {
   

        if(s.length()==1 && " ".equals(s))
            return 0;
        int n = s.length();
        int cnt=0;
        for(int i=n-1; i>=0; i--){
   
            // s.charAt(i)如果是空格,有可能是最后一个单词后边的,也可能前边的空格
            if(s.charAt(i)==' '){
   
                if(cnt>0){
    // cnt>0说明是最后一个单词左边的空格,此时cnt的值就是最后一个单词的长度
                    return cnt;
                } else {
    // cnt=0说明还没遍历到最后一个单词,继续遍历
                    continue;
                }
            } else {
   
                cnt++; // 不是空格,说明正在遍历最后一个单词,长度加1
            }
        }
        return cnt;
    }
}

(62)不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。问总共有多少条不同的路径?
示例:
输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。

  1. 向右 -> 向下 -> 向下
  2. 向下 -> 向下 -> 向右
  3. 向下 -> 向右 -> 向下

提示:
1 <= m, n <= 100
题目数据保证答案小于等于 2 * 10^9,小于20亿,也就是说int类型数据就可以

思路:最简单的状态转移,因为是二维地图,所以得用二维dp。因为这个dp的base case都是1,并且每个位置的数据只和自己左边和上边有关系,所以完全可以把dp[m[[n] 改成dp[2][n] 稍微减少点空间消耗。

class Solution {
   
    public int uniquePaths(int m, int n) {
   

        int [][] dp = new int[m][n];
        dp[0][0] = 1; //m=n=1时,代表什么都不做就到达终点,只有一种情况
        for(int i=1; i<n; i++){
   
            dp[0][i] = 1;
        }
        for(int i=1; i<m; i++){
   
            dp[i][0] = 1;
        }
        for(int i=1; i<m; i++){
   
            for(int j=1; j<n; j++){
   
                dp[i][j] = dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[m-1][n-1];
    }
}

(63)不同路径2

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?网格中的障碍物和空位置分别用 1 和 0 来表示。

提示:
m == obstacleGrid.length
n == obstacleGrid[i].length
1 <= m, n <= 100
obstacleGrid[i][j] 为 0 或 1

思路:和上题一样

class Solution {
   
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
   

        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        int [][] dp = new int[m][n];

        for(int i=0; i<n; i++){
   
            if(obstacleGrid[0][i]==0)
                dp[0][i] = 1;
            else
                break;
        }
        for(int i=0; i<m; i++){
   
            if(obstacleGrid[i][0]==0)
                dp[i][0] = 1;
            else
                break;
        }
        for(int i=1; i<m; i++){
   
            for(int j=1; j<n; j++){
   
                if(obstacleGrid[i][j]==1){
   
                    dp[i][j] = 0;
                } else{
   
                    dp[i][j] = dp[i-1][j]+dp[i][j-1];
                }
            }
        }
        return dp[m-1][n-1];
    }
}

(64)最小路径和

给定一个包含非负整数的 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

提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 200
0 <= grid[i][j] <= 100

思路:和前两题一样。Math.min(), Math.max(), Math.abs(), Math.pow(a,b)是java.lang包下的,不用自己导包

class Solution {
   
    public int minPathSum(int[][] grid) {
   
        int m = grid.length;
        int n = grid[0].length;

        int [][] dp = new int[m][n];
        dp[0][0] = grid[0][0];
        for(int i=1; i<n; i++){
   
            dp[0][i] = grid[0][i]+dp[0][i-1];
        }
        for(int i=1; i<m; i++){
   
            dp[i][0] = grid[i][0]+dp[i-1][0]<
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值