Leetcode動態規劃【簡單題】

Leetcode動態規劃【簡單題】

動態規劃(Dynamic programming,簡稱DP),是一種把原問題分解爲相對簡單的子問題的方式求解複雜問題的方法。動態規劃相較於遞歸,擁有更少的計算量。算法

53. 最大子序和

題目描述

給定一個整數數組 nums ,找到一個具備最大和的連續子數組(子數組最少包含一個元素),返回其最大和。數組

思路分析

  • 遍歷數組,定義當前最大連續子序列的和爲sum,返回的結果爲target。
  • 若是sum>0,表示sum對結果有增益效果,則保留sum並加上當前遍歷數字。
  • 反之,若是sum<=0,表示無增益,那麼直接捨棄,讓sum更新爲當前遍歷數字。
  • 比較sum和target的大小,將最大值置爲target,結束遍歷。
public static int maxSubArray(int[] nums){
        int sum = 0;
        int target = nums[0];
        for(int num:nums){
            //sum>0 增益效果,保留sum並加上當前遍歷數字
            if(sum>0){
                sum+=num;
            //sum<=0 無增益效果,直接捨棄,並將sum更新爲當前遍歷數字
            }else{
                sum = num;
            }
            //比較sum和target的大小,將最大值設爲target
            target = Math.max(target, sum);
        }

        return target;
    }

複雜度分析

  • 時間複雜度:O(n) :只遍歷了一次數組。
  • 空間複雜度:O(1):只用了常熟的空間。

70.爬樓梯

題目描述

假設你正在爬樓梯。須要 n 階你才能到達樓頂。優化

每次你能夠爬 1 或 2 個臺階。你有多少種不一樣的方法能夠爬到樓頂呢?ui

注意:給定 n 是一個正整數。設計

思路分析

  • 咱們能夠想,每次只能爬一個或者兩個臺階意味着,假設如今有i階樓梯,想要達到有兩種狀況:
  • 在第(i-1)階後再爬1階,或者在第(i-2)階後再爬2階。
  • 那麼到達第i階的方法總數就是到第(i-1)階和第(i-2)階方法數的和。
public static int climbStairs(int n) {
        if (n == 1) return 1;
        int[] dp = new int[n + 1];
        dp[1] = 1;
        dp[2] = 2;
        for (int i = 3; i < n + 1; i++) {
            //
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }

複雜度分析

  • 時間複雜度:O(n) ,for循環到達n。
  • 空間複雜度:O(n),建立的dp數組用了n的空間。

121.買賣股票的最佳時機

題目描述

給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。code

若是你最多隻容許完成一筆交易(即買入和賣出一支股票),設計一個算法來計算你所能獲取的最大利潤。遞歸

注意你不能在買入股票前賣出股票。索引

思路分析

假設當前在第i天,令minPrice存儲前i-1天的最低價格,令maxProfit存儲前i-1天的最大收益,那麼在第i天的狀況:leetcode

  • 在第i天賣出,說明若是想要得到最大收益,必定要在前i-1天的最低價格時買入,此時最大收益爲prices[i]-minPrice
  • 不在第i天賣出,說明第i天的最大收益就是前i-1天的最大收益。
  • 可得狀態轉移方程:第i天的最大收益=max(在第i天賣出所得的收益,前i-1天的最大收益)。
public static int maxProfit(int[] prices){
        int minPrice = Integer.MAX_VALUE;
        int maxProfit = 0;
        for(int i = 0;i<prices.length;i++){
            minPrice = Math.min(minPrice,prices[i]);
            maxProfit = Math.max(prices[i]-minPrice,maxProfit);
        }
        return maxProfit;

    }

複雜度分析

  • 時間複雜度:O(n),只需遍歷一次
  • 空間複雜度:O(1),只使用了兩個變量

303.區域和檢索-數組不可變

題目描述

給定一個整數數組 nums,求出數組從索引 ij (ij) 範圍內元素的總和,包含 i, j 兩點。

說明:

  1. 你能夠假設數組不可變。
  2. 會屢次調用 sumRange 方法。

思路分析

  • 若是使用暴力求解,確定會超時,由於題目說明:會調用屢次sumRange方法,每次都會消耗O(n)的時間。
  • 那麼,如何優化呢?能夠預先計算從0到k的累計和,存入一個新的數組。這種記憶化存儲的方式,以便於在查詢時直接查表。
  • 爲了不額外的條件檢查,可讓新數組的第一個元素爲0,存放的和能夠從索引1開始。
  • 舉個例子:原數組nums:[1,3,5,7,9] --> 新數組sums:[0,1,4,9,16,25]
public class NumArray {
    private int[] sums;
    public NumArray(int[] nums){
        sums = new int[nums.length+1];
        for(int i = 0;i<nums.length;i++){
            //建立從索引爲1開始的數組,數組中存儲的是原數組第一位到索引前一位的總和            
            sums[i+1] = sums[i]+nums[i];
        }
    }
    public int sumRange(int i,int j){
        return sums[j+1]-sums[i];
    }
    /**
     * Your NumArray object will be instantiated and called as such:
     * NumArray obj = new NumArray(nums);
     * int param_1 = obj.sumRange(i,j);
     */
}

複雜度分析

  • 時間複雜度:預計算時間爲O(n),可是實際查詢只要O(1)。

  • 空間複雜度:建立了新數組的空間,O(n)。

參考連接:

畫解算法

動態規劃套路詳解

官方題解爬樓梯

相關文章
相關標籤/搜索