DP选编(3) 265. Paint House II 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public int minCostII (int [][] costs) { int k=costs[0 ].length; int n=costs.length; int [][] dp=new int [n][k]; for (int i = 0 ; i < k; i++) { dp[0 ][i]=costs[0 ][i]; } for (int i = 1 ; i < n; i++) { for (int j = 0 ; j < k; j++) { int min=Integer.MAX_VALUE; for (int p = 0 ; p < k; p++) { if (p==j){ continue ; } min=Math.min(min,dp[i-1 ][p]); } dp[i][j]=costs[i][j]+min; } } int res=Integer.MAX_VALUE; for (int i = 0 ; i < k; i++) { res=Math.min(res,dp[n-1 ][i]); } return res; }
Follow up: Could you solve it in O(nk)
runtime?
276. Paint Fence 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public int numWays (int n, int k) { if (n==1 ){ return k; } if (n==2 ){ return k*k; } int [] dp=new int [n+1 ]; dp[1 ]=k; dp[2 ]=k*k; for (int i = 3 ; i < n; i++) { dp[i]=(dp[i-1 ]+dp[i-2 ])*(k-1 ); } return dp[n]; }
651. 4 Keys Keyboard 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public int maxA (int n) { if (n<=3 ){ return n; } int [] dp=new int [n+1 ]; dp[1 ]=1 ; dp[2 ]=2 ; dp[3 ]=3 ; for (int i = 4 ; i <= n; i++) { dp[i]=i; int p=2 ; for (int j = i-3 ; j>=1 ; j--) { dp[i]=Math.max(dp[i],dp[j]*p); p++; if (p>=6 ){ break ; } } } return dp[n]; }
1259. Handshakes That Don’t Cross 1 2 3 4 5 6 7 8 9 10 11 12 13 public int numberOfWays (int numPeople) { int [] dp=new int [numPeople+1 ]; dp[0 ]=1 ; int m=(int )1e9 +7 ; for (int i = 2 ; i <= numPeople; i+=2 ) { for (int j = 0 ; j <= i-2 ; j+=2 ) { dp[i]+=(long )dp[j]*dp[i-2 -j]%m; dp[i]%=m; } } return dp[numPeople]; }
1444. Number of Ways of Cutting a Pizza 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 public class LeetCode1444 { int mod=(int )1e9 +7 ; int row; int col; int [][][] dp; int [][] sum; public int ways (String[] pizza, int k) { row=pizza.length; col=pizza[0 ].length(); sum=new int [row+1 ][col+1 ]; for (int i = row-1 ; i >= 0 ; i--) { for (int j = col-1 ; j >= 0 ; j--) { sum[i][j]=sum[i+1 ][j]+sum[i][j+1 ]-sum[i+1 ][j+1 ]+ (pizza[i].charAt(j)=='A' ? 1 : 0 ); } } dp=new int [row][col][k+1 ]; return dfs(0 ,0 ,k); } int dfs (int i, int j, int k) { if (sum[i][j]==0 ){ return 0 ; } if (k==1 ){ return 1 ; } if (dp[i][j][k]!=0 ){ return dp[i][j][k]; } int res=0 ; for (int x = i+1 ; x < row; x++) { if (sum[i][j]-sum[x][j]>0 ){ res=(res+dfs(x,j,k-1 ))%mod; } } for (int y = j+1 ; y < col; y++) { if (sum[i][j]-sum[i][y]>0 ){ res=(res+dfs(i,y,k-1 ))%mod; } } dp[i][j][k]=res; return res; } }
983. Minimum Cost For Tickets 法一:dfs with memo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 int [] days;int [] costs;Map<Integer,Integer> memo=new HashMap <>(); public int mincostTickets (int [] days, int [] costs) { this .days=days; this .costs=costs; return backtracking(0 ,0 ); } int backtracking (int i, int nextStart) { if (i>=days.length || nextStart>days[days.length-1 ]){ return 0 ; } if (memo.containsKey(i*365 +nextStart)){ return memo.get(i*365 +nextStart); } int choose1=costs[0 ]; for (int j = i; j < days.length; j++) { if (days[j]<nextStart){ continue ; } choose1+=backtracking(j+1 ,days[j]+1 ); break ; } int choose7=costs[1 ]; for (int j = i; j < days.length; j++) { if (days[j]<nextStart){ continue ; } choose7+=backtracking(j+1 ,days[j]+7 ); break ; } int choose30=costs[2 ]; for (int j = i; j < days.length; j++) { if (days[j]<nextStart){ continue ; } choose30+=backtracking(j+1 ,days[j]+30 ); break ; } int res=Math.min(Math.min(choose1,choose7),choose30); memo.put(i*365 +nextStart,res) return res; }
法二:dp with queue https://leetcode.com/problems/minimum-cost-for-tickets/discuss/226659/Two-DP-solutions-with-pictures
同法一表现无异
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public int mincostTickets (int [] days, int [] costs) { int n=days.length; int total=0 ; Deque<int []> last7=new LinkedList <>(); Deque<int []> last30=new LinkedList <>(); for (int i = 0 ; i < n; i++) { while (!last7.isEmpty() && last7.peek()[0 ]+7 <=days[i]){ last7.poll(); } last7.offer(new int []{days[i],total+costs[1 ]}); while (!last30.isEmpty() && last30.peek()[0 ]+30 <=days[i]){ last30.poll(); } last30.offer(new int []{days[i],total+costs[2 ]}); total=Math.min(total+costs[0 ],Math.min(last7.peek()[1 ],last30.peek()[1 ])); } return total; }
法三:dp 注意:
dp数组长度并不由days数组长度决定,而是由lastday决定
由于只需考虑前30天,可以进一步通过 mod30 来优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public int mincostTickets (int [] days, int [] costs) { int [] dp = new int [30 ]; int d = 0 ; int lastday = days[days.length - 1 ]; for (int i = days[0 ]; i <= lastday; i++) { if (i != days[d]) dp[i % 30 ] = dp[(i - 1 ) % 30 ]; else { dp[i % 30 ] = Math.min(dp[(i - 1 ) % 30 ] + costs[0 ], Math.min(dp[Math.max(i - 7 , 0 ) % 30 ] + costs[1 ], dp[Math.max(i - 30 , 0 ) % 30 ] + costs[2 ])); d++; } } return dp[lastday % 30 ]; }
790. Domino and Tromino Tiling 难以理解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public int numTilings (int n) { if (n==1 ) return 1 ; else if (n==2 ) return 2 ; int mod = 1000000007 ; int [] dp=new int [n+1 ];dp[1 ]=1 ; dp[2 ]=2 ; dp[3 ]=5 ; for (int i = 4 ;i<=n;i++){ dp[i]=(2 *dp[i-1 ]%mod+dp[i-3 ]%mod)%mod; } return dp[n];}
勉强可以理解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public int numTilings (int n) { if (n==1 ){ return 1 ; } if (n==2 ){ return 2 ; } int mod=(int )1e9 +7 ; long [] f=new long [n+1 ]; long [] p=new long [n+1 ]; f[1 ]=1 ; f[2 ]=2 ; p[2 ]=1 ; for (int i = 3 ; i <= n; i++) { p[i]=(p[i-1 ]%mod+f[i-2 ]%mod)%mod; f[i]=(f[i-1 ]%mod+f[i-2 ]%mod+2 *p[i-1 ]%mod)%mod; } return (int )f[n]; }
2218. Maximum Value of K Coins From Piles 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 int n;int [][] dp;List<List<Integer>> piles; public int maxValueOfCoins (List<List<Integer>> piles, int k) { n=piles.size(); this .piles=piles; dp=new int [n][k+1 ]; return dp(0 ,k); } int dp (int i, int k) { if (i>=n || k==0 ){ return 0 ; } if (dp[i][k]!=0 ){ return dp[i][k]; } int max=dp(i+1 ,k); int cur=0 ; for (int j=0 ; j<Math.min(k,piles.get(i).size()); j++){ cur+=piles.get(i).get(j); max=Math.max(max,cur+dp(i+1 ,k-j-1 )); } return dp[i][k]=max; }
2140. Solving Questions With Brainpower 1 2 3 4 5 6 7 8 9 10 11 12 public long mostPoints (int [][] questions) { int n=questions.length; long [] dp=new long [n]; dp[n-1 ]=questions[n-1 ][0 ]; for (int i = n-2 ; i >= 0 ; i--) { int next=i+questions[i][1 ]+1 ; dp[i]=Math.max(dp[i+1 ], questions[i][0 ]+(next<n? dp[next] : 0 )); } return dp[0 ]; }
1547. Minimum Cost to Cut a Stick https://leetcode.com/problems/minimum-cost-to-cut-a-stick/discuss/781074/JavaC%2B%2BPython-Merge-Stones
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public int minCost (int n, int [] cuts) { List<Integer> list=new ArrayList <>(); list.add(0 ); list.add(n); for (int cut : cuts) { list.add(cut); } Collections.sort(list); int k=list.size(); int [][] dp=new int [k][k]; for (int d=2 ; d<k; d++){ for (int i=0 ; i+d<k; i++){ dp[i][i+d]=Integer.MAX_VALUE; for (int m=i+1 ; m<i+d; m++){ dp[i][i+d]=Math.min(dp[i][i+d], dp[i][m]+dp[m][i+d]+list.get(i+d)-list.get(i)); } } } return dp[0 ][k-1 ]; }
2328. Number of Increasing Paths in a Grid 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 public int countPaths (int [][] grid) { int row=grid.length; int col=grid[0 ].length; int mod=(int )1e9 +7 ; int [] dx=new int []{0 ,0 ,1 ,-1 }; int [] dy=new int []{1 ,-1 ,0 ,0 }; long [][] dp=new long [row][col]; TreeMap<Integer, List<int []>> map=new TreeMap <>(); for (int i = 0 ; i < row; i++) { for (int j = 0 ; j < col; j++) { map.putIfAbsent(grid[i][j],new ArrayList <>()); map.get(grid[i][j]).add(new int []{i,j}); } } long res=0 ; for (Integer val : map.keySet()) { for (int [] arr : map.get(val)) { int i=arr[0 ]; int j=arr[1 ]; dp[i][j]=1 ; for (int k = 0 ; k < 4 ; k++) { int x=i+dx[k]; int y=j+dy[k]; if (x>=0 && x<row && y>=0 && y<col && grid[x][y]<val){ dp[i][j]+=dp[x][y]; dp[i][j]%=mod; } } res+=dp[i][j]; res%=mod; } } return (int )res; }
2742. Painting the Walls 0/1 knapsack
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public int paintWalls (int [] cost, int [] time) { int n=cost.length; int [] dp=new int [n+1 ]; Arrays.fill(dp,(int )1e9 ); for (int i = 0 ; i < n; i++) { for (int j = n; j > 0 ; j--) { dp[j]=Math.min(dp[j], cost[i] + (j-time[i]-1 >0 ? dp[j-time[i]-1 ] :0 )); } } return dp[n]; }
1575. Count All Possible Routes What’s the state of each sub problem?
What’s the base case?
What’s the state transfer equation?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 int mod=(int )1e9 +7 ;int [][] dp;int finish;int [] locations;public int countRoutes (int [] locations, int start, int finish, int fuel) { int n=locations.length; dp=new int [n][fuel+1 ]; for (int i = 0 ; i < n; i++) { Arrays.fill(dp[i],-1 ); } dp[finish][0 ]=1 ; this .locations=locations; this .finish=finish; return dfs(start,fuel); } private int dfs (int start, int fuel) { if (fuel<0 ){ return 0 ; } if (dp[start][fuel]!=-1 ){ return dp[start][fuel]; } if (fuel==0 ){ return 0 ; } int res= start==finish ? 1 : 0 ; for (int i = 0 ; i < locations.length; i++) { if (i==start){ continue ; } res=(res+dfs(i,fuel-Math.abs(locations[start]-locations[i])))%mod; } return dp[start][fuel]=res; }
1723. Find Minimum Time to Finish All Jobs https://leetcode.com/problems/find-minimum-time-to-finish-all-jobs/discuss/1009817/One-branch-cutting-trick-to-solve-three-LeetCode-questions
思路:
similar to 698. Partition to K Equal Sum Subsets
DFS + optimization(branch cutting)
assign the most time consuming job first
avoid duplicated search (same scenario)
avoid meaningless search (>=res)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 int res=Integer.MAX_VALUE;int [] workers;int n;int k;public int minimumTimeRequired (int [] jobs, int k) { Arrays.sort(jobs); workers=new int [k]; n=jobs.length; this .k=k; dfs(jobs,n-1 ,0 ); return res; } private void dfs (int [] jobs, int cur, int preMax) { if (cur==-1 ){ res=Math.min(res,preMax); return ; } for (int i = 0 ; i < k; i++) { boolean skip=false ; for (int j = 0 ; j < i; j++) { if (workers[i]==workers[j]){ skip=true ; break ; } } if (!skip && workers[i]+jobs[cur]<res){ workers[i]+=jobs[cur]; dfs(jobs,cur-1 ,Math.max(preMax,workers[i])); workers[i]-=jobs[cur]; } } }
1751. Maximum Number of Events That Can Be Attended II 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 int n;int [][] dp;int [][] events;public int maxValue (int [][] events, int k) { this .events=events; n=events.length; dp=new int [n][k+1 ]; for (int [] arr : dp) { Arrays.fill(arr,-1 ); } Arrays.sort(events,(a,b)->(a[0 ]!=b[0 ] ? a[0 ]-b[0 ] : a[1 ]-b[1 ])); return dfs(0 ,k); } private int dfs (int i, int k) { if (i==-1 || i==n || k==0 ){ return 0 ; } if (dp[i][k]!=-1 ){ return dp[i][k]; } int c1=dfs(i+1 ,k); int next=binarySearch(i); int c2=events[i][2 ]+dfs(next,k-1 ); return dp[i][k]=Math.max(c1,c2); } private int binarySearch (int cur) { int left=cur+1 ; int right=n; int mid=0 ; int curEnd=events[cur][1 ]; while (left<right){ mid=(left+right)/2 ; if (events[mid][0 ]<=curEnd){ left=mid+1 ; }else { right=mid; } } return left; }
2361. Minimum Costs Using the Train Line 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public long [] minimumCosts(int [] regular, int [] express, int expressCost) { int n=regular.length; long [] res=new long [n]; long [][] dp=new long [n][2 ]; dp[0 ][0 ]=regular[0 ]; dp[0 ][1 ]=expressCost+express[0 ]; res[0 ]=Math.min(dp[0 ][0 ],dp[0 ][1 ]); for (int i = 1 ; i < n; i++) { dp[i][0 ]=Math.min(dp[i-1 ][0 ]+regular[i],dp[i-1 ][1 ]+regular[i]); dp[i][1 ]=Math.min(dp[i-1 ][0 ]+expressCost+express[i],dp[i-1 ][1 ]+express[i]); res[i]=Math.min(dp[i][0 ],dp[i][1 ]); } return res; }
664. Strange Printer 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 int n;int [][] dp;public int strangePrinter (String s) { n=s.length(); dp=new int [n][n]; for (int i = 0 ; i < n; i++) { Arrays.fill(dp[i],-1 ); } return dfs(s,0 ,n-1 )+1 ; } private int dfs (String s, int l, int r) { if (dp[l][r]!=-1 ){ return dp[l][r]; } int res=n; int j=-1 ; for (int i=l;i<r; i++){ if (s.charAt(i)!=s.charAt(r) && j==-1 ){ j=i; } if (j!=-1 ){ res=Math.min(res,dfs(s,j,i)+dfs(s,i+1 ,r)+1 ); } } if (j==-1 ){ res=0 ; } return dp[l][r]=res; }
808. Soup Servings 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 Map<Integer, Map<Integer,Double>> map; public double soupServings (int n) { if (n>=5000 ){ return 1.0 ; } map=new HashMap <>(); return dfs(n,n); } private double dfs (int a, int b) { if (a<=0 && b<=0 ){ return 0.5 ; } if (a<=0 ){ return 1 ; } if (b<=0 ){ return 0 ; } if (map.containsKey(a) && map.get(a).containsKey(b)){ return map.get(a).get(b); } double res=0 ; res+=0.25 *dfs(a-100 ,b); res+=0.25 *dfs(a-75 ,b-25 ); res+=0.25 *dfs(a-50 ,b-50 ); res+=0.25 *dfs(a-25 ,b-75 ); map.putIfAbsent(a,new HashMap <>()); map.get(a).put(b,res); return res; }
920. Number of Music Playlists 思路:
fill i spots with j unique songs
option 1: already know i-1, j-1, can simply choose another song from other n-j+1 songs, and append it
option 2: try to append an old song, and this song cannot appear in interval [i-k,i-1] => k old songs in this interval should not be considered
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 int n;int k;int [][] dp;int mod=(int )1e9 +7 ;public int numMusicPlaylists (int n, int goal, int k) { this .n=n; this .k=k; dp=new int [goal+1 ][n+1 ]; for (int i = 0 ; i <= goal; i++) { Arrays.fill(dp[i],-1 ); } return (int )dfs(goal,n); } private long dfs (int spots, int songs) { if (spots==0 && songs==0 ){ return 1 ; } if (spots==0 || songs==0 ){ return 0 ; } if (dp[spots][songs]!=-1 ){ return dp[spots][songs]; } long res=dfs(spots-1 ,songs-1 )*(n-songs+1 )%mod; if (songs-k>0 ){ res+=dfs(spots-1 ,songs)*(songs-k)%mod; res%=mod; } return dp[spots][songs]=(int )res; }
2369. Check if There is a Valid Partition For The Array 每个子问题只考察开头即可,开头不符合直接剪枝
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 int n;int [] dp; public boolean validPartition (int [] nums) { n=nums.length; dp=new int [n]; return dfs(nums,0 ); } private boolean dfs (int [] nums, int start) { if (start==n){ return true ; } if (dp[start]!=0 ){ return start==1 ; } boolean res=false ; if (start+2 <n && nums[start]==nums[start+1 ] && nums[start]==nums[start+2 ]){ res|=dfs(nums,start+3 ); } if (start+1 <n && nums[start]==nums[start+1 ]){ res|=dfs(nums,start+2 ); } if (start+2 <n && nums[start]+1 ==nums[start+1 ] && nums[start]+2 ==nums[start+2 ]){ res|=dfs(nums,start+3 ); } dp[start]=res ? 1 : -1 ; return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 int n;int [] dp; public int minExtraChar (String s, String[] dictionary) { Set<String> set=new HashSet <>(); for (String s1 : dictionary) { set.add(s1); } n=s.length(); dp=new int [n]; Arrays.fill(dp,-1 ); return dfs(s,set,0 ); } private int dfs (String s, Set<String> set, int start) { if (start==n){ return 0 ; } if (dp[start]!=-1 ){ return dp[start]; } int res=Integer.MAX_VALUE; for (int i = start; i < n; i++) { int sub=dfs(s,set,i+1 ); if (set.contains(s.substring(start,i+1 ))){ res=Math.min(res,sub); }else { res=Math.min(res,sub+i-start+1 ); } } return dp[start]=res; }
403. Frog Jump 法一: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 int [] stones;int [][] dp=new int [2000 ][2000 ];Map<Integer,Integer> map=new HashMap <>(); int n;public boolean canCross (int [] stones) { this .stones=stones; n=stones.length; for (int i = 0 ; i < n; i++) { map.put(stones[i],i); } for (int [] arr : dp) { Arrays.fill(arr,-1 ); } return dfs(0 ,1 ); } private boolean dfs (int curIdx, int preStep) { if (curIdx==n-1 ){ return true ; } if (dp[curIdx][preStep]!=-1 ){ return dp[curIdx][preStep]==1 ; } int curPos=stones[curIdx]; boolean res=false ; for (int i=preStep-1 ; i<=preStep+1 ; i++){ if (i>0 && map.containsKey(curPos+i)){ res|=dfs(map.get(curPos+i),i); } } dp[curIdx][preStep]=(res?1 :0 ); return res; }
法二: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public boolean canCross (int [] stones) { int n=stones.length; if (stones[1 ]!=1 ){ return false ; } Map<Integer,Set<Integer>> map=new HashMap <>(); for (int stone : stones) { map.put(stone,new HashSet <>()); } Deque<int []> q=new LinkedList <>(); map.remove(0 ); map.remove(1 ); q.offer(new int []{1 ,1 }); while (!q.isEmpty()){ int [] cur=q.poll(); int idx=cur[0 ]; int k=cur[1 ]; if (idx==stones[n-1 ]){ return true ; } for (int p=-1 ; p<=1 ; p++){ if (k+p>0 ){ if (map.containsKey(idx+k+p) && !map.get(idx+k+p).contains(k+p)){ q.offer(new int []{idx+k+p,k+p}); map.get(idx+k+p).add(k+p); } } } } return false ; }
377. Combination Sum IV 法一:top-down 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 int n;Map<Integer,Integer> map=new HashMap <>(); public int combinationSum4 (int [] nums, int target) { Arrays.sort(nums); n=nums.length; return dfs(nums,target); } int dfs (int [] nums, int target) { if (target<=0 ){ if (target==0 ){ return 1 ; } return 0 ; } if (map.containsKey(target)){ return map.get(target); } int res=0 ; for (int i = 0 ; i < n; i++) { if (target-nums[i]<0 ){ break ; } res+=dfs(nums,target-nums[i]); } map.put(target,res); return res; }
法二:bottom-up 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public int combinationSum4 (int [] nums, int target) { int n=nums.length; int [] dp=new int [target+1 ]; Arrays.sort(nums); dp[0 ]=1 ; for (int i=1 ; i<=target; i++){ for (int num: nums){ if (i-num<0 ){ break ; } dp[i]+=dp[i-num]; } } return dp[target]; }