-
Notifications
You must be signed in to change notification settings - Fork 1
/
Extra Questions.txt
3012 lines (2444 loc) · 108 KB
/
Extra Questions.txt
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Some Extra Questions
------------------------------------------------------------------------------------
1. Tower of Hanoi ->https://www.youtube.com/watch?v=QDBrZFROuA0
-> Make the recursion Tree and do the dry run , and do inorder traversal
public static void toh(int n, int t1id, int t2id, int t3id){
if(n==0){
return;
}
//(*) ->Means following all instructions of tower of hanoi
toh(n-1,t1id,t3id,t2id); //will print the instructions to move n-1 disks from t1 to t3 using t2(*)
System.out.println(n+"["+t1id+" -> "+t2id+"]");
toh(n-1,t3id,t2id,t1id);
}
-------------------------------------------------------------------------------------
2. Do All variations of buy and sell stock
-> https://www.youtube.com/watch?v=MyqDgMy-Kew
a) Buy & Sell Stock -> part 1 and 2 in dp and arrays
b) Buy and sell stock with transaction fee (LeetCode 714)
-> public int maxProfit(int[] prices, int fee) {
if(prices.length==0){
return 0;
}
// at any ith day we have 2 options
// if you don't own a stock-> 2 options either buy or not
// if you own a stock -> 2 options either sell or not
// as soon as i buy -> - (prices[i]+fee);
// as soon as i sell -> + prices[i]
int[][]dp=new int[prices.length][2];
for(int[]dpp:dp){
Arrays.fill(dpp,-1);
}
//since initally i don't own a stock so passing 0 for owning means not owning
return BuyNSellStockWithFee(0,prices,fee,0,dp);
}
public int BuyNSellStockWithFee(int idx, int[]prices,int fee,int own,int[][]dp){
if(idx==prices.length)return 0;
if(dp[idx][own]!=-1){
return dp[idx][own];
}
if(own==1){
int op1 = prices[idx]+BuyNSellStockWithFee(idx+1,prices,fee,0,dp); //sell
int op2 = BuyNSellStockWithFee(idx+1,prices,fee,1,dp); //not sell
return dp[idx][own]=Math.max(op1,op2);
}else{
int op1 = -(prices[idx]+fee)+BuyNSellStockWithFee(idx+1,prices,fee,1,dp); //buy
int op2 = BuyNSellStockWithFee(idx+1,prices,fee,0,dp); //not buy
return dp[idx][own]=Math.max(op1,op2);
}
}
c) Buy and Sell Stock with Cooldown ( LeetCode 309)
(for Buy and sell stock 3 & 4 you can refer kartik arora solution which is very intuitive as well)
d) Buy and Sell Stock III (in dp section)
e) Buy and Sell Stock IV (k transactions allowed) (in dp section)
->
class Solution {
public int maxProfit(int[] prices) {
//intuition :
// we will have 3 states i) index ii) own or now own iii) cooldown or not cooldown
// cooldown only give problem while buying not with selling.
// else the explaination remains same as buy and sell stock with transaction fee.
int[][][]dp=new int[prices.length][2][2];
for(int [][]dpp:dp){
for(int[]dppp:dpp){
Arrays.fill(dppp,-1);
}
}
//since intially we don't have the cooldown
return BuyNSellStockCooldown(0,0,0,prices,dp);
}
public int BuyNSellStockCooldown(int idx, int own ,int cooldown,int[]prices,int[][][]dp){
if(idx==prices.length)return 0;
if(dp[idx][own][cooldown]!=-1){
return dp[idx][own][cooldown];
}
if(own==0){
int op1 = (cooldown==1)?0: -(prices[idx]) + BuyNSellStockCooldown(idx+1,1,0,prices,dp);
int op2 = BuyNSellStockCooldown(idx+1,0,0,prices,dp);
return dp[idx][own][cooldown]=Math.max(op1,op2);
}else{
int op1 = prices[idx] + BuyNSellStockCooldown(idx+1,0,1,prices,dp); //as soon as i sell there will be cooldown.
int op2= BuyNSellStockCooldown(idx+1,1,0,prices,dp);
return dp[idx][own][cooldown]=Math.max(op1,op2);
}
}
}
-------------------------------------------------------------------------------------
3. Permutations (leetcode 46)
->Time complexity->(n!*n)
->Space complexity->(2n)
Using extra space->
public void solve( List<List<Integer>>ans,List<Integer>ds,boolean[]freq,int[]nums){
if(ds.size()==nums.length)
{
ans.add(new ArrayList<>(ds));
return;
}
for(int i=0;i<nums.length;i++){
if(!freq[i]){
freq[i]=true;
ds.add(nums[i]);
solve(ans,ds,freq,nums);
ds.remove(ds.size()-1);
freq[i]=false;
}
}
}
Space optimised->
public void solve(List<List<Integer>>ans,int idx,int[]nums){
if(idx==nums.length){
//copy the altered array.
List<Integer>ds=new ArrayList<>();
for(int i=0;i<nums.length;i++){
ds.add(nums[i]);
}
ans.add(new ArrayList<>(ds));
return;
}
//swap every index with every other ahead index
for(int i=idx;i<nums.length;i++){
swap(i,idx,nums);
solve(ans,idx+1,nums);
swap(i,idx,nums);
}
}
-------------------------------------------------------------------------------------
4. Subarray Product less than K (leetcode 713)
-> //for every iteration,we try to get the longest subarray with product < k ending with nums[j];
public int numSubarrayProductLessThanK(int[] nums, int k) {
long pro=1l;
int ans=0;
int i=0,j=0;
while(j<nums.length ){
pro = pro * nums[j];
while(i<=j && pro>=k){
pro/=nums[i];
i++;
}
ans+=(j-i+1); // dry run you will get the flow that how it is calculating
j++;
}
return ans;
}
-> Similar approach problem -> Number of Smooth Descent Periods of a Stock (Leetcode 2110)
-------------------------------------------------------------------------------------
5. Contiguous Array ( Leetcode 525 )
M1)
public int findMaxLength(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
int max = 0;
int zero = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 0) zero++;
else zero--;
if (zero == 0) max = i + 1;
if (!map.containsKey(zero)) map.put(zero, i);
else max = Math.max(max, i - map.get(zero));
}
return max;
}
M2)
-> Just add 1 in case of 0 and -1 in case of 1 and find the largest subarray with sum 0
-> i mean the below solution.
-------------------------------------------------------------------------------------
6. Largest Subarray with sum 0
public static int LargestSubarrayWithSum0(int[]arr,int n){
HashMap<Integer,Integer>map=new HashMap<>();
int max=0;
int sum=0;
for(int i=0;i<arr.length;i++){
sum+=arr[i];
if(sum==0){
max=i+1;
}else{
if(map.get(sum)!=null){
max=Math.max(max,i-map.get(sum));
}else{
map.put(sum,i);
}
}
}
return max;
}
-------------------------------------------------------------------------------------
7. largest Subarray with sum no larger than k
private int maxSumSubArray(int[] a , int k){
int max = Integer.MIN_VALUE;
int preSum = 0;
TreeSet<Integer> ts = new TreeSet();
ts.add(0);
for(int i=0;i<a.length;i++){
preSum += a[i];
Integer gap = ts.ceiling(preSum - k);
if(gap != null) max = Math.max(max, preSum - gap);
ts.add(preSum);
}
return max;
}
# Longest subarray with sum k
->
static int lenOfLongSubarr(int[] arr, int n, int k)
{
// HashMap to store (sum, index) tuples
HashMap<Integer, Integer> map = new HashMap<>();
int sum = 0, maxLen = 0;
// traverse the given array
for (int i = 0; i < n; i++) {
// accumulate sum
sum += arr[i];
// when subarray starts from index '0'
if (sum == k)
maxLen = i + 1;
// make an entry for 'sum' if it is
// not present in 'map'
if (!map.containsKey(sum)) {
map.put(sum, i);
}
// check if 'sum-k' is present in 'map'
// or not
if (map.containsKey(sum - k)) {
// update maxLength
if (maxLen < (i - map.get(sum - k)))
maxLen = i - map.get(sum - k);
}
}
return maxLen;
}
-------------------------------------------------------------------------------------
8. Subarray Sum Equals K (pepcoding)
public int subarraySum(int[] nums, int k) {
int sum = 0, result = 0;
Map<Integer, Integer> preSum = new HashMap<>();
preSum.put(0, 1);
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
if (preSum.containsKey(sum - k)) {
result += preSum.get(sum - k);
}
preSum.put(sum, preSum.getOrDefault(sum, 0) + 1);
}
return result;
}
Binary Subarrays with Sum (Leetcode 930)
-> public int numSubarraysWithSum(int[] nums, int k) {
// atMostK(nums,k)<- this will give subarray sum <=k | atMostK(nums,k-1) <= this will give subarray sum <=k-1 // the diff atMostK(nums,k) - atmostK(nums,k-1) <- this will give subarray sum exactly == k.
return SubarraySumAtMostK(nums,k) - SubarraySumAtMostK(nums,k-1);
}
public int SubarraySumAtMostK(int[]nums,int k){
int sum=0;
int i=0;
int j=0;
int ans=0;
while(j<nums.length){
sum+=nums[j];
while(i<=j && sum>k){
sum-=nums[i++];
}
ans+=(j-i+1);
j++;
}
return ans;
}
-------------------------------------------------------------------------------------
9. Word Break (pepcoding)->https://www.youtube.com/watch?v=2NaaM_z_Jig
-------------------------------------------------------------------------------------
10. Minimum Size Subarray Sum (Leetcode 209)
public int minSubArrayLen(int x, int[] arr) {
// Initialize current sum and minimum length
int curr_sum = 0;
int n = arr.length;
int ans = n + 1;
// Initialize starting and ending indexes
int start = 0, end = 0;
boolean fl = false;
while (end < n) {
// Keep adding array elements while current sum
// is smaller than or equal to x
while (curr_sum < x && end < n)
curr_sum += arr[end++];
// If current sum becomes greater than x.
while (curr_sum >= x && start < n) {
fl=true;
// Update minimum length if needed
ans=Math.min(ans,end-start);
// remove starting elements
curr_sum -= arr[start++];
}
}
if(!fl)return 0;
return ans;
}
-------------------------------------------------------------------------------------
11. Predict the winner (LeetCode 486)
-> Just like optimal Strategy game in Dp notes.
int p1Score = predictWinner(nums,0,n-1,dp);
return (p1Score>=total-p1Score);
public int predictWinner(int[]nums,int i,int j, int[][]dp){
if(i>j){
return 0;
}
if(i==j)return nums[i];
if(dp[i][j]!=-1)return dp[i][j];
int case1 = nums[i] + Math.min(predictWinner(nums,i+1,j-1,dp),predictWinner(nums,i+2,j,dp));
int case2 = nums[j] + Math.min(predictWinner(nums,i+1,j-1,dp),predictWinner(nums,i,j-2,dp));
return dp[i][j] = Math.max(case1,case2);
}
-------------------------------------------------------------------------------------
12. Frog Jump (LeetCode 403)
-> Array is sorted here in stricly increasing order
public boolean canCross(int[] stones) {
int n = stones.length;
HashMap<Integer,HashSet<Integer>>map = new HashMap<>();
for(int i=0;i<n;i++){
map.put(stones[i],new HashSet<>());
}
//since from 0 we can take 1 jump only
map.get(stones[0]).add(1);
for(int i=0;i<n;i++){
int currStone = stones[i];
HashSet<Integer> jumps = map.get(currStone);
for(int jump: jumps){
int pos = currStone + jump;
if(pos == stones[n-1])return true;
if(map.containsKey(pos)){
if(jump-1>0)map.get(pos).add(jump-1);
map.get(pos).add(jump);
map.get(pos).add(jump+1);
}
}
}
return false;
}
-------------------------------------------------------------------------------------
13. Longest Arithmetic Subsequence of Given Difference (Leetcode 1218)
->
public int longestSubsequence(int[] arr, int diff) {
int[]dp = new int[arr.length];
HashMap<Integer,Integer>map = new HashMap<>();
int max=0;
for(int i=0;i<arr.length;i++){
if(map.containsKey(arr[i]-diff)){
int k = map.get(arr[i]-diff);
dp[i]=1+dp[k];
}else{
dp[i]=1;
}
max = Math.max(max,dp[i]);
map.put(arr[i],i);
}
return max;
}
->
public int longestSubsequence(int[] arr, int difference) {
HashMap<Integer, Integer> dp = new HashMap<>();
int longest = 0;
for(int i=0; i<arr.length; i++) {
dp.put(arr[i], dp.getOrDefault(arr[i] - difference, 0) + 1);
longest = Math.max(longest, dp.get(arr[i]));
}
return longest;
}
-------------------------------------------------------------------------------------
14. All Paths From Source to Target (Leetcode 797)
-> list.add(0); then call below function
public void dfs(List<List<Integer>>adj,int node,int n,boolean[]vis,List<Integer>list,List<List<Integer>>ans){
if(node==n-1){
ans.add(new ArrayList<>(list));
return;
}
for(int an:adj.get(node)){
if(!vis[an]){
list.add(an);
vis[an]=true;
dfs(adj,an,n,vis,list,ans);
vis[an]=false;
list.remove(list.size()-1);
}
}
}
-------------------------------------------------------------------------------------
15. Maximum Binary Tree (Leetcode-654)
M1) Recursion
M2) Using stack
-> O(N)
-> for eg: 3,2,1,6,0,5
i) 3 in the stack
ii) 3,2 in the stack (3.right = 2)
iii) 3,2,1 in the stack (2.right = 1)
iv) 6 pop out all the make (6.left = 3), 6 in the stack
v) 6,0 in the stack (6.right = 0)
vi) 5 pop out 0 and make (5.left = 0), 6,5 in the stack
vii) stack no empty hence (6.right = 5)
viii) stack first element is the root.
public TreeNode constructMaximumBinaryTree(int[] nums) {
Deque<TreeNode>st = new LinkedList<>();
for(int i=0;i<nums.length;i++){
TreeNode curr = new TreeNode(nums[i]);
while(!st.isEmpty() && st.peek().val<nums[i]){
curr.left = st.pop(); // here the curr big node will have its left as second big node in left.
}
if(!st.isEmpty()){
// through this any node which is smaller then peek and in right will be attached to right of peek
// for eg: 3.right = 2, 2.right = 1.
st.peek().right = curr;
}
st.push(curr);
}
return (st.isEmpty())?null:st.removeLast();
}
-------------------------------------------------------------------------------------
16. Path In Zigzag Labelled Binary Tree (Leetcode 1104.)
-------------------------------------------------------------------------------------
17. Validate Binary Tree Nodes (Leetcode 1361)
->
M1) O(N) S(N)
-> Firstly check root of the binary tree using both left and right arrays.
-> Now apply bfs using root, if node.left exists and its already visited then return false, same goes with right.
-> Only take a count variable and increase it, at last if count == n, then return true else false.
public boolean validateBinaryTreeNodes(int n, int[] leftChild, int[] rightChild) {
boolean[] isNotRoot = new boolean[n];
for(int i: leftChild){
if(i != -1){isNotRoot[i] = true;}
}
for(int i :rightChild){
if(i != -1){isNotRoot[i] = true;}
}
int root = -1;
for(int i = 0; i < n; i++){
if(!isNotRoot[i]){
if(root != -1){ return false; } //since root can't be more than 1.
root = i;
}
}
if(root == -1){ return false; }
Queue<Integer> queue = new LinkedList();
queue.add(root);
boolean[] seen = new boolean[n];
seen[root] = true;
int count = 0;
while(!queue.isEmpty()){
int size = queue.size();
for(int i = 0; i < size; i++){
int curr = queue.remove();
count++;
if(leftChild[curr] != -1){
if(seen[leftChild[curr]]){ return false; }
seen[leftChild[curr]] = true;
queue.add(leftChild[curr]);
}
if(rightChild[curr] != -1){
if(seen[rightChild[curr]]){ return false; }
seen[rightChild[curr]] = true;
queue.add(rightChild[curr]);
}
}
}
return count == n;
}
M2) It uses union and find (refer to discuss section for this approach)
-------------------------------------------------------------------------------------
18. Biggest cycle in Directed Graph.
-------------------------------------------------------------------------------------
19. Ford-Fulkerson Algorithm for Maximum Flow Problem
-------------------------------------------------------------------------------------
20. Longest path in an undirected tree.
-> Apply 2 DFS/BFS two times
1. choose any node apply dfs/bfs to find the longest distance let this node be y, but return it with pair (node,distance)
-> you will do this by putting pair(node,dis) in queue, take distance array and find distance of all. return the longest distance with node.
2. Now from y apply dfs/bfs to find the longest path. which is the diamter of the tree.
-> Send src node as the result of first dfs/bfs and apply same just like the first one.
-> this returned node is the farthest and its distance is the longest.(basically diameter)
-------------------------------------------------------------------------------------
21. Number of Ways to arrive at destination ()
-> Dijkstra + Dp
public int countPaths(int n, int[][] roads) {
List<List<City>>adj = new ArrayList<>();
for(int i=0;i<n;i++){
adj.add(new ArrayList<>());
}
for(int i=0;i<roads.length;i++){
int u = roads[i][0];
int v = roads[i][1];
int t = roads[i][2];
adj.get(u).add(new City(v,t));
adj.get(v).add(new City(u,t));
}
int[]ways = new int[n];
int[]dis = new int[n];
Arrays.fill(dis,Integer.MAX_VALUE);
ways[0]= 1;
dis[0] = 0;
PriorityQueue<City>pq = new PriorityQueue<>((a,b)->(a.time-b.time));
pq.add(new City(0,0));//src, dis
while(!pq.isEmpty()){
City rc = pq.poll();
if(rc.time>dis[rc.city])continue; // skip because we already got our low distance in prev iteration
for(City ac:adj.get(rc.city)){
if(dis[rc.city]+ac.time<dis[ac.city]){
dis[ac.city] = dis[rc.city]+ac.time;
ways[ac.city] = ways[rc.city];
pq.add(new City(ac.city,dis[ac.city]));
}else if(dis[rc.city]+ac.time==dis[ac.city]){ // if distance remains same means, we got another path hence adding.
ways[ac.city] = (ways[ac.city]+ways[rc.city])%m;
}
}
}
return ways[n-1];
}
-------------------------------------------------------------------------------------
22. Cycle sort
-------------------------------------------------------------------------------------
23. Cherry Pickup (Leetcode 741)
// we are starting both journies form (0,0) itself and not like one from 0,0 and than return journey from (n-1,n-1)
// and this is because the possible path combination from (0,0) to (n-1,n-1) is same as (n-1,n-1) to (0,0) even if there
// are thorns (hurdles)
public int cherryPickup(int[][] grid) {
int[][][] dp = new int[grid.length][grid.length][grid.length];
return Math.max(0, helper(grid, dp, 0, 0, 0)); // return 0 if there is no path from 0,0 to n-1,n-1
}
// Instead of going once from 0,0 to n-1,n-1 and then back, we simply go twice from 0,0 to n-1,n-1 because every path from n-1,n-1 to 0,0 can be interpreted as a path from 0,0 to n-1,n-1
// Note that the one person can never cross the past path of the other person (they can only meet at the same position) so we don't need to worry about one person picking up an already picked up cherry from the past
// What does a state represent? dp[r1][c1][c2] represents the max number of cherries that can be collected by 2 people going from r1,c1 and r2,c2 to n-1,n-1
// Transitions between states? we collect cherries on current positions of the two people (r1,c1 and r2,c2), then we go through all possible next states and choose the best one (max number of cherries) as the next state (we do this by adding the number of cherries of the best next state to the number of cherries we picked up on the current two positions of the people). In the end, the state dp[0][0][0] will contain the max number of cherries that can be picked up by going from 0,0 to n-1,n-1 and back.
private int helper(int[][] grid, int[][][] dp, int r1, int c1, int c2) {
// we can deduce r2 because r1 + c1 == r2 + c2, since with each move either r or c of a person gets incremented by exactly one (Manhattan distance to origin stays equal)
// this way we reduce the 4D dp problem to a 3D one (we save space by reducing the number of things we store in a state)
int r2 = r1 + c1 - c2;
// check if current state is out of bounds or on thorns
if (r1 >= grid.length || c1 >= grid.length || r2 >= grid.length || c2 >= grid.length || grid[r1][c1] == -1 || grid[r2][c2] == -1) {
return Integer.MIN_VALUE; // current state should not be included in the solution
}
// check if we have already computed a solution for this state
if (dp[r1][c1][c2] != 0) return dp[r1][c1][c2];
// check if we reached the end state (note that if r1,c1 reached the end, this implies that r2,c2 also reached the end)
if (r1 == grid.length - 1 && c1 == grid.length - 1) {
return grid[r1][c1];
}
// compute and return answer for current state
int result = grid[r1][c1];
// in case the second person is on the same position, don't pick up the same cherry twice. Note that r1 == r2 <--> c1 == c2 (eg. they can't be on the same row without also being on the same column)
if (r1 != r2) {
result += grid[r2][c2];
}
// pick best possible next state
int bestNextState = Math.max(helper(grid, dp, r1 + 1, c1, c2), // down, down
helper(grid, dp, r1, c1 + 1, c2 + 1)); // right, right
bestNextState = Math.max(bestNextState, helper(grid, dp, r1 + 1, c1, c2 + 1)); // down, right
bestNextState = Math.max(bestNextState, helper(grid, dp, r1, c1 + 1, c2)); // right, down
result += bestNextState;
dp[r1][c1][c2] = result; // store current state such that it can be re-used
return result;
}
-------------------------------------------------------------------------------------
24. Split Array Largest Sum (Leetcode 410) Premium**
-------------------------------------------------------------------------------------
25. Divide Chocolate (Leetcode 1231) Premium**
-------------------------------------------------------------------------------------
26. Combinations (LeetCode 77)
-> public static List<List<Integer>> combine(int n, int k) {
List<List<Integer>> combs = new ArrayList<List<Integer>>();
combine(combs, new ArrayList<Integer>(), 1, n, k);
return combs;
}
public static void combine(List<List<Integer>> combs, List<Integer> comb, int start, int n, int k) {
if(k==0) {
combs.add(new ArrayList<Integer>(comb));
return;
}
for(int i=start;i<=n;i++) {
comb.add(i);
combine(combs, comb, i+1, n, k-1);
comb.remove(comb.size()-1);
}
}
-> Or can use pick/notPick strategy.
-------------------------------------------------------------------------------------
27. House Robber 3 -> https://leetcode.com/problems/house-robber-iii/discuss/79330/Step-by-step-tackling-of-the-problem
-> we are just checking whether we would rob root or not.
public int rob(TreeNode root) {
return robSub(root, new HashMap<>());
}
private int robSub(TreeNode root, Map<TreeNode, Integer> map) {
if (root == null) return 0;
if (map.containsKey(root)) return map.get(root);
int val = 0;
if (root.left != null) {
val += robSub(root.left.left, map) + robSub(root.left.right, map);
}
if (root.right != null) {
val += robSub(root.right.left, map) + robSub(root.right.right, map);
}
val = Math.max(val + root.val, robSub(root.left, map) + robSub(root.right, map));
map.put(root, val);
return val;
}
-> More optimised
O(n)
public int rob(TreeNode root) {
int[] res = robSub(root);
return Math.max(res[0], res[1]);
}
private int[] robSub(TreeNode root) {
if (root == null) return new int[2];
int[] left = robSub(root.left);
int[] right = robSub(root.right);
int[] res = new int[2];
res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
res[1] = root.val + left[0] + right[0];
return res;
}
-------------------------------------------------------------------------------------
28. Permutation in String (Leetcode : 567)
-> Sliding window approach that can be used in various other questions also.
public boolean checkInclusion(String s1, String s2) {
if(s1.length()>s2.length()) return false;
HashMap<Character,Integer>map = new HashMap<>();
int psize = s1.length();
int size = s2.length();
for(int i=0;i<psize;i++){
char ch = s1.charAt(i);
map.put(ch,map.getOrDefault(ch,0)+1);
}
int begin = 0, end = 0;
int counter = map.size(); //taking map size because string can also have duplicates.
while(end<size){
char c = s2.charAt(end);
if(map.containsKey(c)){
map.put(c,map.get(c)-1);
if(map.get(c)==0)counter--;
}
end++;
while(counter==0){
char temp = s2.charAt(begin);
if(map.containsKey(temp)){
map.put(temp,map.get(temp)+1);
if(map.get(temp)>0)counter++;
}
if(end-begin == psize){
return true;
}
begin++;
}
}
return false;
}
-------------------------------------------------------------------------------------
29. Subset II (Leetcode 90)
->
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>>ans=new ArrayList<>();
Arrays.sort(nums);
powerSet(nums,0,new ArrayList<>(),ans);
return ans;
}
public void powerSet(int[]nums,int idx,List<Integer>list,List<List<Integer>>ans){
ans.add(new ArrayList<>(list));
for(int i=idx;i<nums.length;i++){
if(i!=idx && nums[i]==nums[i-1]) // for i = idx (first item of that subset)
continue;
list.add(nums[i]);
powerSet(nums,i+1,list,ans);
list.remove(list.size()-1);
}
return;
}
-------------------------------------------------------------------------------------
30. Burst Ballons
// we have n! ways to burst the ballons
// for eg) {2 3 5} -> a) 2 3 5 , b) 2 5 3 , c) 3 5 2 , d) 3 2 5 , e) 5 2 3 , f) 5 3 2 => 3! = 6 ways
/*
Intuition -> https://www.youtube.com/watch?v=YzvF8CqPafI
1. We know that if only one ballon remains then the coins which we will get is 1*nums[i]*1;
2. So we can say that we already know the ans for last ballon which get bursted.
3. Hence we say that for each i we are considering that all the ballons in its left and right already get bursted means
it is the last ballon to get burst then what will be the max coins which we can collect.
4. We are saying this because we know that there is no relation with the already bursted ballons.
dp[i][j] stores that we you burst a range (i,j){ in a definite order } out of the whole array leaving
other left and right elements as it is then what is the max coins you can collect.
[a1,a2,a3,a4,(ai,ai1,ai2,ai3,....aj),an-2,an-1,an] <- so here suppose you have ai->aj range.
Now for this we say that we are bursting 'ai' and (ai1->aj) is already bursted so coins we will get is (a4*ai*an-2);
when we burst 'ai3', we consider that it is the last ballon to be bursted in the range (ai->aj)<- already bursted.
so in this case we get coins =>(a4*ai3*an-2);
*/
public int maxCoins(int[] nums) {
return BurstBallons(nums,0,nums.length-1,new int[nums.length][nums.length]);
}
public int BurstBallons(int[]nums,int start,int end,int[][]dp){
if(start>end) return 0;
if(dp[start][end]>0) return dp[start][end];
int ans = 0;
for(int i=start;i<=end;i++){
int left=(start>0)?nums[start-1]:1;
int right=(end<nums.length-1)?nums[end+1]:1;
int sum=left*nums[i]*right + BurstBallons(nums,start,i-1,dp) + BurstBallons(nums,i+1,end,dp);
ans=Math.max(sum,ans);
}
return dp[start][end] = ans;
}
-------------------------------------------------------------------------------------
31. Rotate Array (in place)
-> Complexity should be O(N).
The basic idea is that, for example, nums = [1,2,3,4,5,6,7] and k = 3, first we reverse [1,2,3,4], it becomes[4,3,2,1]; then we reverse[5,6,7], it becomes[7,6,5], finally we reverse the array as a whole, it becomes[4,3,2,1,7,6,5] ---> [5,6,7,1,2,3,4].
Reverse is done by using two pointers, one point at the head and the other point at the tail, after switch these two, these two pointers move one position towards the middle.
public void rotate(int[] nums, int k) {
int n = nums.length;
k = k % n;
reverse(nums,0,n-k-1);
reverse(nums,n-k,n-1);
reverse(nums,0,n-1);
}
public void reverse(int[]nums,int l,int h){
while(l<h){
int temp = nums[l];
nums[l]=nums[h];
nums[h]=temp;
l++;
h--;
}
}
-------------------------------------------------------------------------------------
32. Closest Leaf to a given node in a binary tree
O(N)-S(H)
public static int INF = 1000000;
// Function that returns the distance of the closest leaf in the sub tree.
public static int closestLeafNodeInSubtree(BinaryTreeNode<Integer> root) {
if (root == null) {
return INF;
}
if (root.left == null && root.right == null){
// Node is a leaf node.
return 0;
}
int distLeft = closestLeafNodeInSubtree(root.left);
int distRight = closestLeafNodeInSubtree(root.right);
return (1 + Math.min(distLeft, distRight));
}
private static int ans;
// Helper function to calculate the closest leaf distance of the node.
public static int findClosestLeafNodeDistanceHelper(BinaryTreeNode<Integer> root, int x){
if (root == null){
return INF;
}
// If the required node is found, calculate the distance of the closest leaf node.
if (root.data == x){
ans = closestLeafNodeInSubtree(root);
return 0;
}
int distLeft = findClosestLeafNodeDistanceHelper(root.left, x);
if (distLeft != INF) {
// Node X is present in left subtree.
int dist = (distLeft + 2) + closestLeafNodeInSubtree(root.right);
ans = Math.min(ans, dist);
return (1 + distLeft);
}
int distRight = findClosestLeafNodeDistanceHelper(root.right, x);
if (distRight != INF) {
// Node X is present in right subtree.
int dist = (distRight + 2) + closestLeafNodeInSubtree(root.left);
ans = Math.min(ans, dist);
return (1 + distRight);
}
// Node X not found in the subtree.
return INF;
}
-------------------------------------------------------------------------------------
33. Split BST
public TreeNode[] splitBST(TreeNode root, int V) {
if (root == null)
return new TreeNode[]{null, null};
if (root.val == V) {
TreeNode right = root.right;
root.right = null;
return new TreeNode[]{root, right};
}
else if (root.val > V) {
TreeNode[] nodes = splitBST(root.left, V);
TreeNode left = nodes[0];
TreeNode right = nodes[1];
root.left = right;
return new TreeNode[]{left,root};
} else {
TreeNode[] nodes = splitBST(root.right, V);
TreeNode left = nodes[0];
TreeNode right = nodes[1];
root.right=left; //since we have gone to root right having values more than root.val either we get left array having values smaller than equal to v or right having greater than V but overall all nodes have values greater than curr node that's why we did this.
return new TreeNode[]{root, right};
}
}
-------------------------------------------------------------------------------------
34. Given a binary search tree and a range [L, R], delete all elements which are not in the range.
(Trim a Binary Search Tree- (LC-669))
O(N)
private static Node removeOutsideRange(Node root,
int min, int max)
{
// BASE CASE
if(root == null)
{
return null;
}
// FIRST FIX THE LEFT AND
// RIGHT SUBTREE OF ROOT
root.left = removeOutsideRange(root.left,
min, max);
root.right = removeOutsideRange(root.right,
min, max);
// NOW FIX THE ROOT. THERE ARE
// TWO POSSIBLE CASES FOR THE ROOT
// 1. a) Root's key is smaller than
// min value(root is not in range)
if(root.key < min)
{
Node rchild = root.right;
root = null;
return rchild;
}
// 1. b) Root's key is greater than
// max value (Root is not in range)
if(root.key > max)
{
Node lchild = root.left;