Jump Game全家福 1340. Jump Game V dfs + 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 int [] dp;public int maxJumps (int [] arr, int d) { int n=arr.length; dp=new int [n]; int max=0 ; for (int i = 0 ; i < n; i++) { max=Math.max(max,dfs(arr,i,d)); } return max; } int dfs (int [] arr, int cur, int d) { if (dp[cur]!=0 ){ return dp[cur]; } int res=1 ; for (int j=cur+1 ; j<=Math.min(cur+d,arr.length-1 ) && arr[j]<arr[cur]; j++){ res=Math.max(res,1 +dfs(arr,j,d)); } for (int j=cur-1 ; j>=Math.max(cur-d,0 ) && arr[j]<arr[cur]; j--){ res=Math.max(res,1 +dfs(arr,j,d)); } return dp[cur]=res; }
55. Jump Game 思路:
1 2 3 4 5 6 7 8 9 public boolean canJump (int [] nums) { int lastGood=nums.length-1 ; for (int i = nums.length - 1 ; i >= 0 ; i--) { if (i+nums[i]>=lastGood){ lastGood=i; } } return lastGood==0 ; }
45. Jump Game II 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public int jump (int [] nums) { int answer = 0 , n = nums.length; int curEnd = 0 , curFar = 0 ; for (int i = 0 ; i < n - 1 ; ++i) { curFar = Math.max(curFar, i + nums[i]); if (i == curEnd) { answer++; curEnd = curFar; } } return answer; }
1306. Jump Game III dfs也可以用visited[]去重
1 2 3 4 5 6 7 8 9 10 11 12 13 14 boolean [] visited;public boolean canReach (int [] arr, int start) { visited=new boolean [arr.length]; return dfs(arr,start); } boolean dfs (int [] arr, int cur) { if (cur<0 || cur>=arr.length || visited[cur]){ return false ; } visited[cur]=true ; boolean res=arr[cur]==0 || dfs(arr,cur+arr[cur]) || dfs(arr,cur-arr[cur]); return res; }
1345. Jump Game IV TLE: 26 / 33 test cases passed.
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 public int minJumps (int [] arr) { int n=arr.length; Map<Integer, List<Integer>> map=new HashMap <>(); for (int i = 0 ; i < n; i++) { map.putIfAbsent(arr[i],new ArrayList <>()); map.get(arr[i]).add(i); } int d=0 ; boolean [] visited=new boolean [n]; Deque<Integer> q=new LinkedList <>(); q.offer(0 ); visited[0 ]=true ; while (!q.isEmpty()){ int size=q.size(); while (size-->0 ){ int cur=q.poll(); if (cur==n-1 ){ return d; } if (cur-1 >=0 && !visited[cur-1 ]){ q.offer(cur-1 ); visited[cur-1 ]=true ; } if (cur+1 <n && !visited[cur+1 ]){ q.offer(cur+1 ); visited[cur+1 ]=true ; } for (Integer next : map.get(arr[cur])) { if (!visited[next]){ q.offer(next); visited[next]=true ; } } } d++; } return -1 ; }
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 public int minJumps (int [] arr) { int n=arr.length; Map<Integer, List<Integer>> map=new HashMap <>(); for (int i = 0 ; i < n; i++) { map.putIfAbsent(arr[i],new ArrayList <>()); map.get(arr[i]).add(i); } int d=0 ; boolean [] visited=new boolean [n]; Deque<Integer> q=new LinkedList <>(); q.offer(0 ); visited[0 ]=true ; while (!q.isEmpty()){ int size=q.size(); while (size-->0 ){ int cur=q.poll(); if (cur==n-1 ){ return d; } if (cur-1 >=0 && !visited[cur-1 ]){ q.offer(cur-1 ); visited[cur-1 ]=true ; } if (cur+1 <n && !visited[cur+1 ]){ q.offer(cur+1 ); visited[cur+1 ]=true ; } for (Integer next : map.get(arr[cur])) { if (!visited[next]){ q.offer(next); visited[next]=true ; } } map.get(arr[cur]).clear(); } d++; } return -1 ; }
1696. Jump Game VI TLE: 60 / 72 test cases passed.
1 2 3 4 5 6 7 8 9 10 11 12 public int maxResult (int [] nums, int k) { int n=nums.length; int [] dp=new int [n]; Arrays.fill(dp,Integer.MIN_VALUE); dp[0 ]=nums[0 ]; for (int i = 0 ; i < n; i++) { for (int j=i+1 ; j<n && j<=i+k; j++){ dp[j]=Math.max(dp[j],dp[i]+nums[j]); } } return dp[n-1 ]; }
Priority Queue Approcah:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public int maxResult (int [] nums, int k) { int n=nums.length; int [] dp=new int [n]; Arrays.fill(dp,Integer.MIN_VALUE); dp[0 ]=nums[0 ]; PriorityQueue<Integer> pq=new PriorityQueue <>((a,b)->(dp[b]-dp[a])); pq.offer(0 ); for (int i = 1 ; i < n; i++) { while (pq.peek()+k<i){ pq.poll(); } dp[i]=nums[i]+dp[pq.peek()]; pq.offer(i); } return dp[n-1 ]; }
https://leetcode.com/problems/jump-game-vi/discuss/1260843/C%2B%2BJavaPython-DP-and-Decreasing-Deque-Clean-and-Concise-Time-O(N)-Space-O(K)
In Decreasing Deque approach:
We used a deque to store indices of nums elements, elements is in decreasing order, the front is the maximum element.
When adding a new number nums[i], we eliminate elements which is less or equal to nums[i] in deque, which will never be chosen in the future.
Push index of current nums[i] to back of the deque.
If the last element in deque is out of range K then remove it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public int maxResult (int [] nums, int k) { int n=nums.length; int [] dp=new int [n]; Deque<Integer> q=new LinkedList <>(); q.offerLast(0 ); dp[0 ]=nums[0 ]; for (int i = 1 ; i < n; i++) { while (q.peekFirst()+k<i){ q.pollFirst(); } dp[i]=nums[i]+dp[q.peekFirst()]; while (!q.isEmpty() && dp[q.peekLast()]<=dp[i]){ q.pollLast(); } q.offerLast(i); } return dp[n-1 ]; }
1871. Jump Game VII 经典O(n^2)超时的”10^5”
107 / 142 test cases passed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public boolean canReach (String s, int minJump, int maxJump) { char [] chars=s.toCharArray(); int n=s.length(); if (chars[n-1 ]=='1' ){ return false ; } Deque<Integer> q=new LinkedList <>(); q.offer(0 ); boolean [] visited=new boolean [n]; visited[0 ]=true ; while (!q.isEmpty()){ int cur=q.poll(); if (cur==n-1 ){ return true ; } for (int i=cur+minJump; i<=cur+maxJump && i<n; i++){ if (!visited[i] && chars[i]=='0' ){ visited[i]=true ; q.offer(i); } } } return false ; }
(hint: Use partial sums to mark the intervals as reachable.)
https://leetcode.com/problems/jump-game-vii/discuss/1224804/JavaC%2B%2BPython-One-Pass-DP
dp + sliding window 太妙了!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public boolean canReach (String s, int minJump, int maxJump) { int n=s.length(); char [] chars=s.toCharArray(); boolean [] dp=new boolean [n]; int pre=0 ; dp[0 ]=true ; for (int i = 1 ; i < n; i++) { if (i-minJump>=0 && dp[i-minJump]){ pre++; } if (i-maxJump-1 >=0 && dp[i-maxJump-1 ]){ pre--; } dp[i]= pre>0 && chars[i]=='0' ; } return dp[n-1 ]; }
2297. Jump Game VIII 反思:
当给定条件看似杂乱时,尝试通过反证法等数学推理转化条件为基本模板
https://leetcode.com/problems/jump-game-viii/discuss/2140361/Java-or-Monostack-%2B-DP-or-Concise-and-Short-or-Explained
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public long minCost (int [] nums, int [] costs) { int n= nums.length; long [] dp=new long [n]; Arrays.fill(dp,Long.MAX_VALUE); dp[0 ]=0 ; Deque<Integer> stack1=new LinkedList <>(); Deque<Integer> stack2=new LinkedList <>(); for (int i = 0 ; i < n; i++) { while (!stack1.isEmpty() && nums[stack1.peek()]<=nums[i]){ dp[i]=Math.min(dp[i],dp[stack1.pop()]+costs[i]); } while (!stack2.isEmpty() && nums[stack2.peek()]>nums[i]){ dp[i]=Math.min(dp[i],dp[stack2.pop()]+costs[i]); } stack1.push(i); stack2.push(i); } return dp[n-1 ]; }