新坑 Leet Code DP(動態規劃)題解總和

     畢業老,挖新坑,同學推薦了一個Leet Code OJ給我,之前搞ACM我最喜歡做DP題,所以對於新OJ,我想說的是,DP題就交給我吧。題目題解沒有順序,要查某題可以自行搜索,我還未解決的可以留言提醒我去搞定。順帶一提我這次做題準備全用JAVA來做。


P303. Range Sum Query - Immutable

題解:題目大一爲給定一個數組,給出一些問題,讓我們求出區間和,如果用O(n^2)的方法會非常直觀,但是效率不高,其實我們只要做一個預處理,每個問題就能夠在O(1)的時間內解出。因爲Range(i,j)=Sum[j]-Sum[i-1]{sum[i]爲數組前幾個數字的和}。所以預處理就是做數組前幾數和的過程。總體來說是一道簡單題。

參考代碼:

public class NumArray {
    private int[] sum;
    public NumArray(int[] nums) {
      int l=nums.length;
      if(l!=0){
      sum=new int[l];
      sum[0]=nums[0];
      for(int i=1;i<l;i++)
        sum[i]=sum[i-1]+nums[i];
      }
    }

    public int sumRange(int i, int j) {
      if(i==0) return sum[j];
      return sum[j]-sum[i-1];
    }
}


P368. Largest Divisible Subset

題解:題目大意爲一個非負數字集合,沒有重複的數字。求一個最長的子集,子集中任意兩數要滿足大的數要整除小的數。基本的DP題型,這道題時間複雜度要求不高,用n(O^2)的方法即可AC,首先先將數組排序,dp[i][1]代表數組中前i個數中最長的子集。由於當a整除b時,一定能保證整除b所有可以整除的其他數。所以轉移方程就是

dp[i][1]=max(dp[i][1],dp[j][1]+1){i%j==0};然後dp[i][0]則用來記錄它是由哪個j轉移過來的,方便輸出答案集合。具體詳情請看參考代碼。

參考代碼:

public class Solution {
    public static List<Integer> largestDivisibleSubset(int[] nums) {
      List<Integer> re=new ArrayList<Integer>();
      if(nums.length==0) return re;
      if(nums.length==1){
        re.add(nums[0]);
        return re;
      }
      Arrays.sort(nums);
      int l=nums.length;
      int[][] dp=new int[l+1][2];
      dp[0][1]=1; dp[0][0]=-1;
      for(int i=1;i<l;i++){
        dp[i][1]=1; dp[i][0]=-1;
        for(int j=0;j<i;j++)
        if(nums[i]%nums[j]==0 && dp[j][1]+1>dp[i][1]){
          dp[i][1]=dp[j][1]+1;
          dp[i][0]=j;
        }
      } 
      int maxv=0,maxi=0;
      for(int i=0;i<l;i++)
      if(dp[i][1]>maxv){
        maxv=dp[i][1];
        maxi=i;
      }
      while(maxi!=-1){
        re.add(nums[maxi]);
        maxi=dp[maxi][0];
      }
      return re;
    }
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章