leetcode題解-Dynamic Programming簡單類別題目彙總

今天刷了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];
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章