leetcode题解-Dynamic Programming简单类别题目汇总

本文通过五个经典DP问题,包括爬楼梯、最小花费爬楼梯、最大子数组和、打家劫舍等,介绍了动态规划的基本思想及实现技巧。文章不仅提供了详细的解题思路,还附带了清晰易懂的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天刷了DP类别的5个简单级别的题目,这里简单总结一下,关于DP的定义以及一些常用的思路大家可以去看算法导论或者一些博客进行学习,这里就只关注这几个题目,不对DP进行很多介绍。

70, Climbing Stairs && 746,Min Cost Climbing Stairs && 53. Maximum Subarray && 198. House Robber

题目:

 70. Climbing Stairs

 You are climbing a stair case. It takes n steps to reach to the top.

 Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

 Note: Given n will be a positive integer.


 Example 1:

 Input: 2
 Output:  2
 Explanation:  There are two ways to climb to the top.

 1. 1 step + 1 step
 2. 2 steps
 Example 2:

 Input: 3
 Output:  3
 Explanation:  There are three ways to climb to the top.

 1. 1 step + 1 step + 1 step
 2. 1 step + 2 steps
 3. 2 steps + 1 step


 746. Min Cost Climbing Stairs

 On a staircase, the i-th step has some non-negative cost cost[i] assigned (0 indexed).

 Once you pay the cost, you can either climb one or two steps. You need to find minimum cost to reach the top of the

 floor, and you can either start from the step with index 0, or the step with index 1.

 Example 1:
 Input: cost = [10, 15, 20]
 Output: 15
 Explanation: Cheapest is start on cost[1], pay that cost and go to the top.
 Example 2:
 Input: cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
 Output: 6
 Explanation: Cheapest is start on cost[0], and only step on 1s, skipping cost[3].
 Note:
 cost will have a length in the range [2, 1000].

 53. Maximum Subarray

 Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

 For example, given the array [-2,1,-3,4,-1,2,1,-5,4],
 the contiguous subarray [4,-1,2,1] has the largest sum = 6.

 click to show more practice.

 More practice:
 If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.


 198. House Robber

 You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

 Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

之所以把这三道题目放在一起进行介绍是因为他们都属于找到一种递推关系然后用一个数组来保存简单情况下的结果,并使用简单情况的结果去求解复杂情况的问题。首先来看第一道题目,爬楼梯:从只有一个台阶开始,只有一种方案;接下来有两个台阶,可以有两种方案;三个台阶三种方案;四个台阶就应该有:从第三个台阶走一步+从第二个台阶走两步=5种方案。。。。所以递推公式就是An=A(n-1)+A(n-2)。代码也很简单,如下所示:

    //bottom-top
    public int climbStairs(int n) {
        int [] res = new int[n];
        for(int i=0; i<n; i++){
            if(i<3) res[i] = i+1;
            else
                res[i] = res[i-1] + res[i-2];
        }
        return res[n-1];
    }

    //top-bottom memory the intermediate
    public int climbStairs1(int n) {
        int[] N = new int[n];
        for (int i = 0; i < n; i++){
            N[i] = -1;
        }

        return topdownclimbStairs(n, N);
    }

接下来看第二道题目,也很简单,最小费用问题,很明显是最优化解适合用DP算法来求解,因为每次可以选择走一个或者两个台阶,所以思路跟上面一道题目相似,找到递归解就有下面的代码:

    public int minCostClimbingStairs(int[] cost) {
        int [] minCost = new int[cost.length];
        for(int i=0; i<cost.length; i++){
            if(i<2) minCost[i] = cost[i];
            else
                minCost[i] = cost[i] + Math.min(minCost[i-1], minCost[i-2]);
        }
        return Math.min(minCost[cost.length-1], minCost[cost.length-2]);
    }

第三道题目也是一样,不同的是递归里面不再是简单的n-1加上n-2,而是跟第二题一样,会涉及一些最大最小值判断或者大于零小于零的判断,找到这个点,题目就很容易求解了:

    /**
     Base case: 1 element, return nums[0]

     Other cases:

     If dp[i-1] < 0, dp[i] = nums[i]

     if dp[i-1] >0, dp[i] = nums[i] + dp[i-1]

     then pick the max sum.

     We only need dp[i-1], so i use prev to record it, the space complexity is reduced to O(1).
     */
    public int maxSubArray(int[] A) {
        int dp[] = new int[A.length]; int max = A[0]; dp[0] = A[0];
        for (int i = 1; i < A.length; i++) {
            dp[i] = Math.max(dp[i-1] + A[i] ,A[i]);
            max = Math.max(max, dp[i]);
        }
        return max;
    }

    public int maxSubArray1(int[] A) {
        int res = Integer.MIN_VALUE, sum = 0;
        for (int i = 0; i < A.length; i++) {
            sum = Math.max(sum, 0) + A[i];
            res = Math.max(res, sum);
        }
        return res;
    }

接下来是第四道题目,不再赘述直接看解法:

    public int rob(int[] nums) {
        if(nums.length==0) return 0;
        if(nums.length==1) return nums[0];
        int [] res = new int[nums.length];
        res[0] = nums[0];
        res[1] = Math.max(nums[0], nums[1]);
        for(int i=2; i<nums.length; i++){
            res[i] = Math.max(res[i-2] + nums[i], res[i-1]);
        }
        return res[nums.length-1];
    }

    public int rob1(int[] num) {
        int prevNo = 0;
        int prevYes = 0;
        for (int n : num) {
            int temp = prevNo;
            prevNo = Math.max(prevNo, prevYes);
            prevYes = n + temp;
        }
        return Math.max(prevNo, prevYes);
    }

303. Range Sum Query - Immutable

然后我们再来看最后一个题目:

 303. Range Sum Query - Immutable

 Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.

 Example:
 Given nums = [-2, 0, 3, -5, 2, -1]

 sumRange(0, 2) -> 1
 sumRange(2, 5) -> -1
 sumRange(0, 5) -> -3
 Note:
 You may assume that the array does not change.
 There are many calls to sumRange function.

这个题目跟上面的有一点不一样就是,使用一个数组来保存之前元素的求和,然后在求解两个元素之间的喝的时候直接相减即可==代码如下所示:

public class NumArray {
    //95%
    int[] nums;
    public NumArray(int[] nums) {
        for(int i = 1; i < nums.length; i++)
            nums[i] += nums[i - 1];

        this.nums = nums;
    }

    public int sumRange(int i, int j) {
        if(i == 0)
            return nums[j];

        return nums[j] - nums[i - 1];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值