-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdata.json
More file actions
1227 lines (1227 loc) · 144 KB
/
data.json
File metadata and controls
1227 lines (1227 loc) · 144 KB
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
[
{
"id": 1,
"question": "Given an integer array nums, rotate the array to the right by k steps, where k is non-negative.\n\nExample 1:\nInput: nums = [1,2,3,4,5,6,7], k = 3\nOutput: [5,6,7,1,2,3,4]\nExplanation:\nrotate 1 steps to the right: [7,1,2,3,4,5,6]\nrotate 2 steps to the right: [6,7,1,2,3,4,5]\nrotate 3 steps to the right: [5,6,7,1,2,3,4]\n\nExample 2:\nInput: nums = [-1,-100,3,99], k = 2\nOutput: [3,99,-1,-100]\nExplanation:\nrotate 1 steps to the right: [99,-1,-100,3]\nrotate 2 steps to the right: [3,99,-1,-100]\n\n\nConstraints:\n1 <= nums.length <= 10^5\n-2^31 <= nums[i] <= 2^31 - 1\n0 <= k <= 10^5\n\n\nFollow up:\nTry to come up with as many solutions as you can. There are at least three different ways to solve this problem.\nCould you do it in-place with O(1) extra space?",
"topic": "Array",
"pattern": "Reverse / Cyclic Shift",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Rotate Array",
"problem_link": "https://leetcode.com/problems/rotate-array",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/1_Array/1_Rotate_Array.py",
"approaches": [
{
"tc": "T.C. - O(n*k)",
"sc": "S.C - O(1)",
"intuition": "Right rotate the array k times",
"code": "from typing import List\n\n\nclass Solution:\n def rotate(self, nums: List[int], k: int) -> None:\n \"\"\"\n Do not return anything, modify nums in-place instead.\n \"\"\"\n for _ in range(k):\n for j in range(len(nums) - 1, 0, -1):\n nums[j], nums[j - 1] = nums[j - 1], nums[j]",
"type": "Brute"
},
{
"tc": "T.C. - O(n)+O(n)+O(n) ~ O(n)",
"sc": "S.C - O(1)",
"intuition": "Reverse the entire array\nReverse the array from 0 to k-1\nReverse the array from k to n-1",
"code": "from typing import List\n\n\nclass Solution:\n def rev_array(self, i: int, j: int, ls: list[int]):\n while i < j:\n ls[i], ls[j] = ls[j], ls[i]\n i += 1\n j -= 1\n\n def rotate(self, nums: List[int], k: int) -> None:\n \"\"\"\n Do not return anything, modify nums in-place instead.\n \"\"\"\n n = len(nums)\n k = k % n\n\n self.rev_array(0, n - 1, nums)\n self.rev_array(0, k - 1, nums)\n self.rev_array(k, n - 1, nums)",
"type": "Optimal"
}
]
},
{
"id": 2,
"question": "Given an array nums of size n, return the majority element.\nThe majority element is the element that appears more than \u230an / 2\u230b times. You may assume that the majority element always exists in the array.\n\n\nExample 1:\nInput: nums = [3,2,3]\nOutput: 3\n\nExample 2:\nInput: nums = [2,2,1,1,1,2,2]\nOutput: 2\n\n\nConstraints:\nn == nums.length\n1 <= n <= 5 * 10^4\n-10^9 <= nums[i] <= 10^9\n\nFollow-up: Could you solve the problem in linear time and in O(1) space?",
"topic": "Array",
"pattern": "Boyer\u2013Moore Majority Vote Algorithm",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Majority Element",
"problem_link": "https://leetcode.com/problems/majority-element",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/1_Array/2_Majority_Element.py",
"approaches": [
{
"tc": "T.C. - O(n^2)",
"sc": "S.C - O(1)",
"intuition": "For each element try to find out the number of times it occur If its count is greater than n/2 , then its the majority element",
"code": "from typing import List\n\n\nclass Solution:\n def majorityElement(self, nums: List[int]) -> int:\n major_element = -1\n n = len(nums)\n\n for i in range(len(nums)):\n c = 1\n for j in range(len(nums)):\n if i == j:\n continue\n\n if nums[i] == nums[j]:\n c += 1\n\n if c > n // 2:\n major_element = nums[i]\n\n return major_element",
"type": "Brute"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(n)",
"intuition": "Store the frequency of each number in a hashmap Identify the number with frequency more than n//2 Number with frequency n//2 is the majority element",
"code": "from typing import List\nfrom collections import defaultdict\n\n\nclass Solution:\n def majorityElement(self, nums: List[int]) -> int:\n freq_map = defaultdict(int)\n\n for num in nums:\n freq_map[num] += 1\n\n major_element = -1\n n = len(nums)\n for num, val in freq_map.items():\n if val > n // 2:\n return num\n\n return major_element",
"type": "Better"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(1)",
"intuition": "We can observe something suppose we have an array of size n=6.\nFor being majority element an element must occure atleast more\nthan floor(n/2) i.e. say atleast 4 times.\nExample array: [1,1,1,1,2,2] . Here 4 is the majority element.\nSimilary if we are supposed to fina an element occuring more\nthan floor(n/3) then it must appear atleast 3 times.\nExample array: [1,1,1,2,2,2] . Here 1,2 are the majority element.\nSo it is clear the max majority element we can have for n is k-1:\nn/2 -> 1\nn/3 -> 2\nn/4 -> 3\nThe intuition to solve this problem is to think of a cancelling\nmechanism,if we take the array [1,1,1,1,2,2] and suppose we were\naksed to find element occuring more than floor(n/2), what we can\ndo is that think like this if \"1\" gets 4 votes and \"2\" gets 2 votes\nthen 2 votes of \"1\" gets cancelled by 2 votes of \"2\".So \"1\" is in\nmajority by 2.\nWe start by assuming the first element is the major element\nwe maintain the count of current majority element\nif we encounter a different element we reduce the count\nif the count becomes zero then the current element becomes majority with count reset\nto 1",
"code": "from typing import List\n\n\nclass Solution:\n def majorityElement(self, nums: List[int]) -> int:\n c = 0\n major_element = None\n\n for i in range(len(nums)):\n if c == 0:\n c = 1\n major_element = nums[i]\n elif nums[i] == major_element:\n c += 1\n elif nums[i] != major_element:\n c -= 1\n\n return major_element",
"type": "Optimal"
}
]
},
{
"id": 3,
"question": "Given an integer array of size n, find all elements that appear more than \u230a n/3 \u230b times.\n\nExample 1:\nInput: nums = [3,2,3]\nOutput: [3]\n\nExample 2:\nInput: nums = [1]\nOutput: [1]\n\nExample 3:\nInput: nums = [1,2]\nOutput: [1,2]\n\n\nConstraints:\n1 <= nums.length <= 5 * 10^4\n-10^9 <= nums[i] <= 10^9",
"topic": "Array",
"pattern": "Boyer\u2013Moore Majority Vote Algorithm",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Majority Element II",
"problem_link": "https://leetcode.com/problems/majority-element-ii",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/1_Array/3_Majority_Element_II.py",
"approaches": [
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(n)",
"intuition": "Store the frequency of each number in a hashmap Identify the number with frequency more than n//3 Numbers with frequency n//3 is the majority element",
"code": "from typing import List\nfrom collections import defaultdict\n\n\nclass Solution:\n def majorityElement(self, nums: List[int]) -> List[int]:\n freq_map = defaultdict(int)\n\n for num in nums:\n freq_map[num] += 1\n\n ans = []\n\n for num, freq in freq_map.items():\n if freq > len(nums) // 3:\n ans.append(num)\n\n return ans",
"type": "Better"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(1)",
"intuition": "We can observe something suppose we have an array of size n=6.\nFor being majority element an element must occure atleast more\nthan floor(n/2) i.e. say atleast 4 times.\nExample array: [1,1,1,1,2,2] . Here 4 is the majority element.\nSimilary if we are supposed to fina an element occuring more\nthan floor(n/3) then it must appear atleast 3 times.\nExample array: [1,1,1,2,2,2] . Here 1,2 are the majority element.\nSo it is clear the max majority element we can have for n is k-1:\nn/2 -> 1\nn/3 -> 2\nn/4 -> 3\nThe intuition to solve this problem is to think of a cancelling\nmechanism,if we take the array [1,1,1,1,2,2] and suppose we were\naksed to find element occuring more than floor(n/3), what we can\ndo is that think like this if \"1\" gets 4 votes and \"2\" gets 2 votes\nthen 2 votes of \"1\" gets cancelled by 2 votes of \"2\".So \"1\" is in\nmajority by 2.\nSince there can be atmose 0,1 or 2 elements\nTake this example:\nn=10\n------- -------\n[_ _ _ _ _ _ _ _ _ _ ]\n<n/3> <n/3> <n/3>\nNo space to accomodate another array elements.\nWe start by assuming there are 2 majority elements.\nwe maintain the count of current majority elements\nif we encounter a different element we reduce the count\nif the count becomes zero then the current element becomes majority with count reset\nto 1\nAfter all this we do verify if it appears more than floor(n/3) times",
"code": "from typing import List\n\n\nclass Solution:\n def majorityElement(self, nums: List[int]) -> List[int]:\n c1 = 0\n major_element1 = None\n\n c2 = 0\n major_element2 = None\n\n for i in range(len(nums)):\n if nums[i] == major_element1:\n c1 += 1\n elif nums[i] == major_element2:\n c2 += 1\n elif c1 == 0: # this must be done after\n major_element1 = nums[i]\n c1 = 1\n elif c2 == 0: # this must be done after\n major_element2 = nums[i]\n c2 = 1\n else:\n c1 -= 1\n c2 -= 1\n\n # Verification\n ans = []\n c1, c2 = 0, 0\n n = len(nums)\n for i in range(len(nums)):\n if nums[i] == major_element1:\n c1 += 1\n if nums[i] == major_element2:\n c2 += 1\n\n if c1 > n // 3:\n ans.append(major_element1)\n if c2 > n // 3:\n ans.append(major_element2)\n\n return ans",
"type": "Optimal"
}
]
},
{
"id": 4,
"question": "Given an integer array nums and an integer k, return the kth largest element in the array.\nNote that it is the kth largest element in the sorted order, not the kth distinct element.\nCan you solve it without sorting?\n\nExample 1:\nInput: nums = [3,2,1,5,6,4], k = 2\nOutput: 5\n\nExample 2:\nInput: nums = [3,2,3,1,2,4,5,5,6], k = 4\nOutput: 4\n\n\nConstraints:\n1 <= k <= nums.length <= 10^5\n-10^4 <= nums[i] <= 10^4",
"topic": "Array",
"pattern": "Heap / QuickSelect",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Kth Largest Element in an Array",
"problem_link": "https://leetcode.com/problems/kth-largest-element-in-an-array",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/1_Array/4_Kth_Largest_Element_in_an_Array.py",
"approaches": [
{
"tc": "T.C. - O(nlog(n))",
"sc": "S.C - O(n)",
"intuition": "Sort the array in descending and return the kth element from first",
"code": "from typing import List\n\n\nclass Solution:\n def findKthLargest(self, nums: List[int], k: int) -> int:\n return sorted(nums, reverse=True)[k - 1]",
"type": "Brute"
},
{
"tc": "T.C. - O(nlog(k))",
"sc": "S.C - O(k)",
"intuition": "Use a Min heap and keep maintaining a min heap of size k atlast at top will be your kth largest element",
"code": "from typing import List\nimport heapq\n\n\nclass Solution:\n def findKthLargest(self, nums: List[int], k: int) -> int:\n min_heap: list[int] = []\n\n for i in range(len(nums)):\n elem = nums[i]\n heapq.heappush(min_heap, elem)\n if len(min_heap) > k:\n heapq.heappop(min_heap)\n\n return min_heap[0]",
"type": "Better"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(1)",
"intuition": "We are going to use the quick select algo\nIn this algo we choose a pivot as first number\nThen we try to place all the numbers greater than\npivot at left and all smaller at right.We try to\nmimic a descending order sort.\nThe get pivot algo work as below:\n+ place two pointers at given l and r range\n+ only swap numbers at index l and r if they are not in correct place\n+ move i, j if nums[i]>=pivot or nums[j]<=pivot\natlast we just need to swap the jth and lth index\nYou will see by swapping the jth and lth index\nautmatically all the elements greater than pivot\ngets placed to left and smaller to left\nas the jth index will become pivot now",
"code": "from typing import List\n\n\nclass Solution:\n def get_pivot(self, l, r, nums: List[int]) -> int:\n i, j = l + 1, r\n p = nums[l]\n\n while i <= j:\n if nums[i] < p and nums[j] > p:\n nums[i], nums[j] = nums[j], nums[i]\n i += 1\n j -= 1\n\n if nums[i] >= p:\n i += 1\n\n if nums[j] <= p:\n j -= 1\n\n nums[l], nums[j] = nums[j], nums[l]\n return j\n\n def findKthLargest(self, nums: List[int], k: int) -> int:\n l = 0\n r = len(nums) - 1\n pivot_index = -1\n\n while True:\n pivot_index = self.get_pivot(l, r, nums)\n if pivot_index == k - 1:\n break\n elif pivot_index > k - 1:\n r = pivot_index - 1\n else:\n l = pivot_index + 1\n\n return nums[pivot_index]",
"type": "Optimal"
}
]
},
{
"id": 5,
"question": "Given an array of integers citations where citations[i] is the number of citations a researcher received for their ith paper, return the researcher's h-index.\nAccording to the definition of h-index on Wikipedia: The h-index is defined as the maximum value of h such that the given researcher has published at least h papers that have each been cited at least h times.\n\nExample 1:\nInput: citations = [3,0,6,1,5]\nOutput: 3\nExplanation: [3,0,6,1,5] means the researcher has 5 papers in total and each of them had received 3, 0, 6, 1, 5 citations respectively.\nSince the researcher has 3 papers with at least 3 citations each and the remaining two with no more than 3 citations each, their h-index is 3.\n\nExample 2:\nInput: citations = [1,3,1]\nOutput: 1",
"topic": "Array",
"pattern": "Counting Sort",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "H Index",
"problem_link": "https://leetcode.com/problems/h-index",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/1_Array/5_H_Index.py",
"approaches": [
{
"tc": "T.C. - O(max(citations)*n)+O(nlog(n))",
"sc": "S.C - O(1)",
"intuition": "For all possible values of citations check whether we can find alteast x papers with x no of citations",
"code": "from typing import List\n\n\nclass Solution:\n def hasAtleast_H_Paper_With_H_Citation(self, h: int, citations: List[int]):\n paper_with_h_citations = 0\n for citation_val in citations:\n if citation_val >= h:\n paper_with_h_citations += 1\n\n return True if paper_with_h_citations >= h else False\n\n def hIndex(self, citations: List[int]) -> int:\n h_idx = 0\n citations.sort()\n\n for h_index in range(max(citations) + 1):\n if self.hasAtleast_H_Paper_With_H_Citation(h_index, citations):\n h_idx = h_index\n\n return h_idx",
"type": "Brute"
},
{
"tc": "T.C. - O(nlog(n))",
"sc": "S.C - O(1)",
"intuition": "We are going to do a binary search in the range of 1 and max value of citaion if for current value of h_index we are able to find h paper with h citations we are going to go towards right otherwise to the left",
"code": "from typing import List\n\n\nclass Solution:\n def hasAtleast_H_Paper_With_H_Citation(self, h: int, citations: List[int]):\n paper_with_h_citations = 0\n for citation_val in citations:\n if citation_val >= h:\n paper_with_h_citations += 1\n\n return True if paper_with_h_citations >= h else False\n\n def hIndex(self, citations: List[int]) -> int:\n h_idx = 0\n citations.sort()\n st, en = 0, max(citations) + 1\n\n while st <= en:\n mid = (st + en) // 2\n\n if self.hasAtleast_H_Paper_With_H_Citation(mid, citations):\n h_idx = mid\n st = mid + 1\n else:\n en = mid - 1\n\n return h_idx",
"type": "Better"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(n)",
"intuition": "We are going to follow a counting sort appraoch\nWe are going to initialize a count array of size n+1\nIn that count array we are going to store how many\ntimes ith citations value has occured\nRememeber the count array stores the paper count with\nexactly i as the h-index not how many papers with atlest h-index\nThen we are going to traverse back from the array and maintain\npaper count we have seen so far. For every index we are going to\nask one question does we have atleast h paper with h citation\nif yes we return the first value we get",
"code": "from typing import List\n\n\nclass Solution:\n def hIndex(self, citations: List[int]) -> int:\n n = len(citations)\n # count[i] = how many papers have exactly i citations (i from 0..n)\n count = [0] * (n + 1)\n\n for c in citations:\n # citations larger than n are capped at n\n count[min(c, n)] += 1\n\n paper = 0 # number of papers with citations >= current i\n for i in range(n, -1, -1):\n paper += count[i] # add papers that have i citations\n if paper >= i: # H\u2011index condition satisfied\n return i\n return 0",
"type": "Optimal"
}
]
},
{
"id": 1,
"question": "Given an m x n matrix, return all elements of the matrix in spiral order.\n\nExample 1:\nInput: matrix = [[1,2,3],[4,5,6],[7,8,9]]\nOutput: [1,2,3,6,9,8,7,4,5]\n\nExample 2:\nInput: matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]\nOutput: [1,2,3,4,8,12,11,10,9,5,6,7]\n\nConstraints:\nm == matrix.length\nn == matrix[i].length\n1 <= m, n <= 10\n-100 <= matrix[i][j] <= 100",
"topic": "Matrix",
"pattern": "Simulation / Direction Vectors",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Spiral Matrix",
"problem_link": "https://leetcode.com/problems/spiral-matrix",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/2_Matrix/1_Spiral_Matrix.py",
"approaches": [
{
"tc": "T.C. - O(m*n)",
"sc": "S.C - O(m*n)",
"intuition": "As you travel in a spiral fashion mark the cells in a visited set only go ahead if its not in visited or else change direction",
"code": "from typing import List\n\n\nclass Solution:\n def spiralOrder(self, matrix: List[List[int]]) -> List[int]:\n res: list[int] = []\n m, n = len(matrix), len(matrix[0])\n visited = set()\n total_steps = m * n\n\n row, col = 0, 0\n\n while total_steps > 0:\n # Left to Right\n while col < n and (row, col) not in visited:\n visited.add((row, col))\n res.append(matrix[row][col])\n col += 1\n total_steps -= 1\n row += 1\n col -= 1\n\n # Top to Bottom\n while row < m and (row, col) not in visited:\n visited.add((row, col))\n res.append(matrix[row][col])\n row += 1\n total_steps -= 1\n row -= 1\n col -= 1\n\n # Bottom Right to Bottom Left\n while col >= 0 and (row, col) not in visited:\n visited.add((row, col))\n res.append(matrix[row][col])\n col -= 1\n total_steps -= 1\n row -= 1\n col += 1\n\n # Bottom to Top\n while row >= 0 and (row, col) not in visited:\n visited.add((row, col))\n res.append(matrix[row][col])\n row -= 1\n total_steps -= 1\n row += 1\n col += 1\n\n return res",
"type": "Brute"
},
{
"tc": "T.C. - O(m*n)",
"sc": "S.C - O(1)",
"intuition": "Take 4 pointers left,right,top,bottom\nleft,right will help us travel horizontally\ntop,bottom will help us travel vertically\nAlso suppose we have a matrix with one\nrow only, we only require to print the\nleft to right elements only",
"code": "from typing import List\n\n\nclass Solution:\n def spiralOrder(self, matrix: List[List[int]]) -> List[int]:\n m, n = len(matrix), len(matrix[0])\n left, right = 0, n - 1\n top, bottom = 0, m - 1\n res: list[int] = []\n\n while top <= bottom and left <= right:\n # Left to Right\n for i in range(left, right + 1):\n res.append(matrix[top][i])\n top += 1\n\n # Top to Bottom\n for j in range(top, bottom + 1):\n res.append(matrix[j][right])\n right -= 1\n\n # Right to Left\n if top <= bottom:\n for k in range(right, left - 1, -1):\n res.append(matrix[bottom][k])\n bottom -= 1\n\n # Bottom to Top\n if left <= right:\n for l in range(bottom, top - 1, -1):\n res.append(matrix[l][left])\n left += 1\n\n return res",
"type": "Optimal"
}
]
},
{
"id": 2,
"question": "You are given an n x n 2D matrix representing an image, rotate the image by 90 degrees (clockwise).\n\nYou have to rotate the image in-place, which means you have to modify the input 2D matrix directly.\nDO NOT allocate another 2D matrix and do the rotation.\n\nExample 1:\nInput: matrix = [[1,2,3],[4,5,6],[7,8,9]]\nOutput: [[7,4,1],[8,5,2],[9,6,3]]\n\nExample 2:\nInput: matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]\nOutput: [[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]\n\nConstraints:\nn == matrix.length == matrix[i].length\n1 <= n <= 20\n-1000 <= matrix[i][j] <= 1000",
"topic": "Matrix",
"pattern": "Transpose + Reverse / Layer Rotation",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Rotate Image",
"problem_link": "https://leetcode.com/problems/rotate-image",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/2_Matrix/2_Rotate_Image.py",
"approaches": [
{
"tc": "T.C. - O(n^2)+O(n^2)",
"sc": "S.C - O(1)",
"intuition": "Do Transpose of a matrix\nReverse every row in matrix",
"code": "from typing import List\n\n\nclass Solution:\n def rotate(self, matrix: List[List[int]]) -> None:\n \"\"\"\n Do not return anything, modify matrix in-place instead.\n \"\"\"\n n = len(matrix)\n for i in range(n):\n for j in range(i + 1, n):\n matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]\n\n for i in range(n):\n l, r = 0, n - 1\n while l < r:\n matrix[i][l], matrix[i][r] = matrix[i][r], matrix[i][l]\n l += 1\n r -= 1",
"type": "Optimal"
}
]
},
{
"id": 3,
"question": "According to Wikipedia's article: \"The Game of Life, also known simply as Life,\nis a cellular automaton devised by the British mathematician John Horton Conway in 1970.\"\nThe board is made up of an m x n grid of cells, where each cell has an initial state:\nlive (represented by a 1) or dead (represented by a 0).\nEach cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):\n\nAny live cell with fewer than two live neighbors dies as if caused by under-population.\nAny live cell with two or three live neighbors lives on to the next generation.\nAny live cell with more than three live neighbors dies, as if by over-population.\nAny dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.\nThe next state of the board is determined by applying the above rules simultaneously to every cell\nin the current state of the m x n grid board. In this process, births and deaths occur simultaneously.\n\nGiven the current state of the board, update the board to reflect its next state.\nNote that you do not need to return anything.\n\nExample 1:\nInput: board = [[0,1,0],[0,0,1],[1,1,1],[0,0,0]]\nOutput: [[0,0,0],[1,0,1],[0,1,1],[0,1,0]]\n\nExample 2:\nInput: board = [[1,1],[1,0]]\nOutput: [[1,1],[1,1]]",
"topic": "Matrix",
"pattern": "Simulation / In-place State Encoding",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Game of Life",
"problem_link": "https://leetcode.com/problems/game-of-life",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/2_Matrix/3_Game_of_Life.py",
"approaches": [
{
"tc": "T.C. - O(m*n*8)",
"sc": "S.C - O(m*n)",
"intuition": "For each cell determine neighbour count and make it live or die based on the the conditions given",
"code": "from typing import List\n\n\nclass Solution:\n def neightbourCount(self, board: List[List[int]], curr_pos: tuple[int, int]) -> int:\n m, n = len(board), len(board[0])\n dirs = [(0, 1), (1, 0), (-1, -1), (1, 1), (0, -1), (-1, 0), (1, -1), (-1, 1)]\n x, y = curr_pos\n c = 0\n\n for dx, dy in dirs:\n pos_x = x + dx\n pos_y = y + dy\n\n if pos_x < 0 or pos_x >= m:\n continue\n\n if pos_y < 0 or pos_y >= n:\n continue\n\n if board[pos_x][pos_y] == 1:\n c += 1\n\n return c\n\n def gameOfLife(self, board: List[List[int]]) -> None:\n \"\"\"\n Do not return anything, modify board in-place instead.\n \"\"\"\n m, n = len(board), len(board[0])\n res = [[0 for _ in range(n)] for _ in range(m)]\n\n for i in range(m):\n for j in range(n):\n neightbourCount = self.neightbourCount(\n board,\n (\n i,\n j,\n ),\n )\n if board[i][j] == 1:\n if neightbourCount == 2 or neightbourCount == 3:\n res[i][j] = 1\n elif neightbourCount < 2:\n res[i][j] = 0\n elif neightbourCount > 3:\n res[i][j] = 0\n else:\n if neightbourCount == 3:\n res[i][j] = 1\n\n board[:] = res",
"type": "Brute"
},
{
"tc": "T.C. - O(m*n)+O(m*n)",
"sc": "S.C - O(1)",
"intuition": "We need to somehow store the previous state of our matrix\nFor each cell ge the neightbour count\nWhat we can do is mark the cell that will become living state to dead state with -2\nand cell that will become dead state to living with 2.\nAt last conver thr -2 to 0 and 2 to 1",
"code": "from typing import List\n\n\nclass Solution:\n def neightbourCount(self, board: List[List[int]], curr_pos: tuple[int, int]) -> int:\n m, n = len(board), len(board[0])\n dirs = [(0, 1), (1, 0), (-1, -1), (1, 1), (0, -1), (-1, 0), (1, -1), (-1, 1)]\n x, y = curr_pos\n c = 0\n\n for dx, dy in dirs:\n pos_x = x + dx\n pos_y = y + dy\n\n if pos_x < 0 or pos_x >= m:\n continue\n\n if pos_y < 0 or pos_y >= n:\n continue\n\n if board[pos_x][pos_y] in [1, -2]:\n c += 1\n\n return c\n\n def gameOfLife(self, board: List[List[int]]) -> None:\n \"\"\"\n Do not return anything, modify board in-place instead.\n \"\"\"\n m, n = len(board), len(board[0])\n\n for i in range(m):\n for j in range(n):\n neightbourCount = self.neightbourCount(\n board,\n (\n i,\n j,\n ),\n )\n if board[i][j] == 1:\n if neightbourCount < 2:\n board[i][j] = -2\n elif neightbourCount > 3:\n board[i][j] = -2\n else:\n if neightbourCount == 3:\n board[i][j] = 2\n\n for i in range(m):\n for j in range(n):\n if board[i][j] == -2:\n board[i][j] = 0\n elif board[i][j] == 2:\n board[i][j] = 1",
"type": "Optimal"
}
]
},
{
"id": 4,
"question": "Determine if a 9 x 9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:\n\nEach row must contain the digits 1-9 without repetition.\nEach column must contain the digits 1-9 without repetition.\nEach of the nine 3 x 3 sub-boxes of the grid must contain the digits 1-9 without repetition.\nNote:\n\nA Sudoku board (partially filled) could be valid but is not necessarily solvable.\nOnly the filled cells need to be validated according to the mentioned rules.\n\n\nExample 1:\nInput: board =\n[[\"5\",\"3\",\".\",\".\",\"7\",\".\",\".\",\".\",\".\"]\n,[\"6\",\".\",\".\",\"1\",\"9\",\"5\",\".\",\".\",\".\"]\n,[\".\",\"9\",\"8\",\".\",\".\",\".\",\".\",\"6\",\".\"]\n,[\"8\",\".\",\".\",\".\",\"6\",\".\",\".\",\".\",\"3\"]\n,[\"4\",\".\",\".\",\"8\",\".\",\"3\",\".\",\".\",\"1\"]\n,[\"7\",\".\",\".\",\".\",\"2\",\".\",\".\",\".\",\"6\"]\n,[\".\",\"6\",\".\",\".\",\".\",\".\",\"2\",\"8\",\".\"]\n,[\".\",\".\",\".\",\"4\",\"1\",\"9\",\".\",\".\",\"5\"]\n,[\".\",\".\",\".\",\".\",\"8\",\".\",\".\",\"7\",\"9\"]]\nOutput: true\n\nExample 2:\nInput: board =\n[[\"8\",\"3\",\".\",\".\",\"7\",\".\",\".\",\".\",\".\"]\n,[\"6\",\".\",\".\",\"1\",\"9\",\"5\",\".\",\".\",\".\"]\n,[\".\",\"9\",\"8\",\".\",\".\",\".\",\".\",\"6\",\".\"]\n,[\"8\",\".\",\".\",\".\",\"6\",\".\",\".\",\".\",\"3\"]\n,[\"4\",\".\",\".\",\"8\",\".\",\"3\",\".\",\".\",\"1\"]\n,[\"7\",\".\",\".\",\".\",\"2\",\".\",\".\",\".\",\"6\"]\n,[\".\",\"6\",\".\",\".\",\".\",\".\",\"2\",\"8\",\".\"]\n,[\".\",\".\",\".\",\"4\",\"1\",\"9\",\".\",\".\",\"5\"]\n,[\".\",\".\",\".\",\".\",\"8\",\".\",\".\",\"7\",\"9\"]]\nOutput: false\nExplanation: Same as Example 1, except with the\n5 in the top left corner being modified to 8. Since there are two 8's in the top left 3x3 sub-box, it is invalid.\n\nConstraints:\nboard.length == 9\nboard[i].length == 9\nboard[i][j] is a digit 1-9 or '.'.",
"topic": "Matrix",
"pattern": "HashMap / Set / Row-Col-Box Tracking",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Valid Sudoku",
"problem_link": "https://leetcode.com/problems/valid-sudoku",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/2_Matrix/4_Valid_Sudoku.py",
"approaches": [
{
"tc": "T.C. - O(m*n)+O(m*n)+O(m*n)",
"sc": "S.C - O(m*n)+O(m*n)+O(m*n)",
"intuition": "Validate all rows,cols and 3x3 grid based on the given condition",
"code": "from typing import List\n\n\nclass Solution:\n def isValidSudoku(self, board: List[List[str]]) -> bool:\n m, n = len(board), len(board[0])\n\n # Validate all rows\n for i in range(m):\n visited = set()\n for j in range(n):\n if board[i][j] == \".\":\n continue\n curr_num = int(board[i][j])\n if curr_num < 1 or curr_num > 9:\n return False\n if curr_num in visited:\n return False\n visited.add(curr_num)\n\n # Validate all cols\n for j in range(n):\n visited = set()\n for i in range(m):\n if board[i][j] == \".\":\n continue\n curr_num = int(board[i][j])\n if curr_num < 1 or curr_num > 9:\n return False\n if curr_num in visited:\n return False\n visited.add(curr_num)\n\n # Validate all 9 3x3 matrix\n for br in range(0, 9, 3):\n for bc in range(0, 9, 3):\n visited = set()\n for i in range(br, br + 3):\n for j in range(bc, bc + 3):\n if board[i][j] == \".\":\n continue\n curr_num = int(board[i][j])\n if curr_num < 1 or curr_num > 9:\n return False\n if curr_num in visited:\n return False\n visited.add(curr_num)\n\n return True",
"type": "Brute"
},
{
"tc": "T.C. -",
"sc": "S.C -",
"intuition": "",
"code": "from typing import List\n\n\nclass Solution:\n def isValidSudoku(self, board: List[List[str]]) -> bool:\n pass",
"type": "Optimal"
}
]
},
{
"id": 5,
"question": "Given an m x n integer matrix matrix, if an element is 0, set its entire row and column to 0's.\nYou must do it in place.\n\nExample 1:\nInput: matrix = [[1,1,1],[1,0,1],[1,1,1]]\nOutput: [[1,0,1],[0,0,0],[1,0,1]]\n\nExample 2:\nInput: matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]\nOutput: [[0,0,0,0],[0,4,5,0],[0,3,1,0]]\n\nConstraints:\nm == matrix.length\nn == matrix[0].length\n1 <= m, n <= 200\n-2^31 <= matrix[i][j] <= 2^31 - 1\n\nFollow up:\nA straightforward solution using O(mn) space is probably a bad idea.\nA simple improvement uses O(m + n) space, but still not the best solution.\nCould you devise a constant space solution?",
"topic": "Matrix",
"pattern": "Marking Rows & Columns / In-place",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Set Matrix Zeroes",
"problem_link": "https://leetcode.com/problems/set-matrix-zeroes",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/2_Matrix/5_Set_Matrix_Zeroes.py",
"approaches": [
{
"tc": "T.C. -",
"sc": "S.C -",
"intuition": "",
"code": "",
"type": "Brute"
},
{
"tc": "T.C. -",
"sc": "S.C -",
"intuition": "",
"code": "",
"type": "Better"
},
{
"tc": "T.C. -",
"sc": "S.C -",
"intuition": "",
"code": "",
"type": "Optimal"
}
]
},
{
"id": 1,
"question": "Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.\n\nYou may assume that each input would have exactly one solution, and you may not use the same element twice.\n\nYou can return the answer in any order.\n\nExample 1:\nInput: nums = [2,7,11,15], target = 9\nOutput: [0,1]\nExplanation: Because nums[0] + nums[1] == 9, we return [0, 1].\n\nExample 2:\nInput: nums = [3,2,4], target = 6\nOutput: [1,2]\n\nExample 3:\nInput: nums = [3,3], target = 6\nOutput: [0,1]\n\n\nConstraints:\n\n2 <= nums.length <= 10^4\n-10^9 <= nums[i] <= 10^9\n-10^9 <= target <= 10^9\nOnly one valid answer exists.\n\n\nFollow-up: Can you come up with an algorithm that is less than O(n2) time complexity?",
"topic": "Hashing",
"pattern": "HashMap / Complement Lookup",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Two Sum",
"problem_link": "https://leetcode.com/problems/two-sum",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/3_Hashing/1_Two_Sum.py",
"approaches": [
{
"tc": "T.C. - O(n^2)",
"sc": "S.C - O(1)",
"intuition": "Check all possible pairs and find out the pair that gives us the given target",
"code": "from typing import List\n\n\nclass Solution:\n def twoSum(self, nums: List[int], target: int) -> List[int]:\n for i in range(len(nums)):\n for j in range(i + 1, len(nums)):\n if nums[i] + nums[j] == target:\n return [i, j]",
"type": "Brute"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(1)",
"intuition": "We know that if x+y = target\nif are going to do a complement look up\nwe are going to mark all the visited elements using a map\nand Check if we have encounter target-y earlier or not",
"code": "from typing import List\n\n\nclass Solution:\n def twoSum(self, nums: List[int], target: int) -> List[int]:\n visited = {}\n\n for i in range(len(nums)):\n diff = target - nums[i]\n if diff in visited:\n return [i, visited[diff]]\n\n visited[nums[i]] = i",
"type": "Optimal"
}
]
},
{
"id": 2,
"question": "Given two strings s and t, return true if t is an anagram of s, and false otherwise.\n\nExample 1:\nInput: s = \"anagram\", t = \"nagaram\"\nOutput: true\n\nExample 2:\nInput: s = \"rat\", t = \"car\"\nOutput: false\n\n\nConstraints:\n1 <= s.length, t.length <= 5 * 10^4\ns and t consist of lowercase English letters.\n\nFollow up: What if the inputs contain Unicode characters? How would you adapt your solution to such a case?",
"topic": "Hashing",
"pattern": "HashMap / Frequency Count",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Valid Anagram",
"problem_link": "https://leetcode.com/problems/valid-anagram",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/3_Hashing/2_Valid_Anagram.py",
"approaches": [
{
"tc": "T.C. - O(s+t)",
"sc": "S.C - O(s+t)",
"intuition": "Maintain a counter map\nstore the frequency of each character for string s\ndecrement the coresspoding character for string t in counter map\nvalidate couter map has all value as zero",
"code": "class Solution:\n def isAnagram(self, s: str, t: str) -> bool:\n if len(s) != len(t):\n return False\n\n counter_map = {}\n\n for i in range(len(s)):\n counter_map[s[i]] = 1 + counter_map.get(s[i], 0)\n\n for j in range(len(t)):\n ch = t[j]\n\n if ch not in counter_map:\n return False\n\n counter_map[ch] -= 1\n\n for _, val in counter_map.items():\n if val != 0:\n return False\n\n return True",
"type": "Optimal"
}
]
},
{
"id": 3,
"question": "Given an array of strings strs, group the anagrams together. You can return the answer in any order.\n\nExample 1:\nInput: strs = [\"eat\",\"tea\",\"tan\",\"ate\",\"nat\",\"bat\"]\nOutput: [[\"bat\"],[\"nat\",\"tan\"],[\"ate\",\"eat\",\"tea\"]]\n\nExplanation:\nThere is no string in strs that can be rearranged to form \"bat\".\nThe strings \"nat\" and \"tan\" are anagrams as they can be rearranged to form each other.\nThe strings \"ate\", \"eat\", and \"tea\" are anagrams as they can be rearranged to form each other.\n\nExample 2:\nInput: strs = [\"\"]\nOutput: [[\"\"]]\n\nExample 3:\nInput: strs = [\"a\"]\nOutput: [[\"a\"]]\n\n\nConstraints:\n\n1 <= strs.length <= 10^4\n0 <= strs[i].length <= 100\nstrs[i] consists of lowercase English letters.",
"topic": "Hashing",
"pattern": "HashMap / Sorting Key",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Group Anagrams",
"problem_link": "https://leetcode.com/problems/group-anagrams",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/3_Hashing/3_Group_Anagrams.py",
"approaches": [
{
"tc": "T.C. - O(n*k)",
"sc": "S.C - O(n*k+m)",
"intuition": "Group all the words by their frequency count array",
"code": "from collections import defaultdict\nfrom typing import List\n\n\nclass Solution:\n def get_freq_string(self, s: str) -> str:\n counter_map = [0] * 26\n for ch in s:\n counter_map[ord(ch) - 97] += 1\n\n res = \"\"\n for i in range(len(counter_map)):\n if counter_map[i] > 0:\n res += f\"{chr(i+97)}{counter_map[i]}\"\n\n return res\n\n def groupAnagrams(self, strs: List[str]) -> List[List[str]]:\n groups = defaultdict(list)\n\n for s in strs:\n count = [0] * 26\n for c in s:\n count[ord(c) - 97] += 1\n groups[tuple(count)].append(s)\n\n return list(groups.values())",
"type": "Optimal"
}
]
},
{
"id": 4,
"question": "Given an integer array nums, return an array answer such that answer[i] is equal to the product of all the elements of nums except nums[i].\nThe product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.\nYou must write an algorithm that runs in O(n) time and without using the division operation.\n\nExample 1:\nInput: nums = [1,2,3,4]\nOutput: [24,12,8,6]\n\nExample 2:\nInput: nums = [-1,1,0,-3,3]\nOutput: [0,0,9,0,0]\n\nConstraints:\n2 <= nums.length <= 10^5\n-30 <= nums[i] <= 30\nThe input is generated such that answer[i] is guaranteed to fit in a 32-bit integer.\n\nFollow up: Can you solve the problem in O(1) extra space complexity? (The output array does not count as extra space for space complexity analysis.)",
"topic": "Hashing",
"pattern": "Prefix & Suffix Product / HashMap",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Product of Array Except Self",
"problem_link": "https://leetcode.com/problems/product-of-array-except-self",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/3_Hashing/4_Product_of_Array_Except_Self.py",
"approaches": [
{
"tc": "T.C. - O(n^2)",
"sc": "S.C - O(1)",
"intuition": "Use two loop Outer loop fixes one element Inner loop traverse the entire array and skips the current fixed element Also we maintain the product",
"code": "from typing import List\n\n\nclass Solution:\n def productExceptSelf(self, nums: List[int]) -> List[int]:\n res = [0] * len(nums)\n\n for i in range(len(nums)):\n p = 1\n for j in range(len(nums)):\n if i == j:\n continue\n p *= nums[j]\n res[i] = p\n\n return res",
"type": "Brute"
},
{
"tc": "T.C. - O(n)+O(n)+O(n) ~ O(n)",
"sc": "S.C - O(n)+O(n) ~ O(n)",
"intuition": "Build a prefix product array Build a suffix product array for an elemen at pos i its product is nothing but multiplication og prefix[i]*suffix[i]",
"code": "from typing import List\n\n\nclass Solution:\n def productExceptSelf(self, nums: List[int]) -> List[int]:\n n = len(nums)\n\n pref = [1] * n\n for i in range(1, n):\n pref[i] = pref[i - 1] * nums[i - 1]\n\n suff = [1] * n\n for i in range(n - 2, -1, -1):\n suff[i] = suff[i + 1] * nums[i + 1]\n\n ans = [1] * n\n for i in range(n):\n ans[i] = pref[i] * suff[i]\n\n return ans",
"type": "Better"
},
{
"tc": "T.C. - O(n)+O(n)",
"sc": "S.C - O(1)",
"intuition": "Maintain a prefix and suffix pointers\nKeep updating the prefix in result array from front\nKeep updating the suffix in result array from back",
"code": "from typing import List\n\n\nclass Solution:\n def productExceptSelf(self, nums: List[int]) -> List[int]:\n n = len(nums)\n res = [0] * n\n\n pref = 1\n for i in range(len(nums)):\n res[i] = pref\n pref *= nums[i]\n\n suff = 1\n for j in range(len(nums) - 1, -1, -1):\n res[j] *= suff\n suff *= nums[j]\n\n return res",
"type": "Optimal"
}
]
},
{
"id": 5,
"question": "Given two strings ransomNote and magazine, return true if ransomNote can be constructed by using the letters from magazine and false otherwise.\nEach letter in magazine can only be used once in ransomNote.\n\n\nExample 1:\nInput: ransomNote = \"a\", magazine = \"b\"\nOutput: false\n\nExample 2:\nInput: ransomNote = \"aa\", magazine = \"ab\"\nOutput: false\n\nExample 3:\nInput: ransomNote = \"aa\", magazine = \"aab\"\nOutput: true\n\nConstraints:\n1 <= ransomNote.length, magazine.length <= 10^5\nransomNote and magazine consist of lowercase English letters.",
"topic": "Hashing",
"pattern": "HashMap / Frequency Count",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Ransom note",
"problem_link": "https://leetcode.com/problems/ransom-note",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/3_Hashing/5_Ransom_note.py",
"approaches": [
{
"tc": "T.C. - O(n)+O(n) ~ O(n)",
"sc": "S.C - O(n)",
"intuition": "First store the frequency map of each character for magazine\nNow iterate over the ransomNote string and decrement the coresponding\ncharacter by 1 and if at any point we say the current char is not present\nor no characters left we can return False",
"code": "class Solution:\n def canConstruct(self, ransomNote: str, magazine: str) -> bool:\n mp = {}\n for i in range(len(magazine)):\n mp[magazine[i]] = 1 + mp.get(magazine[i], 0)\n\n for j in range(len(ransomNote)):\n if ransomNote[j] not in mp:\n return False\n\n if mp[ransomNote[j]] == 0:\n return False\n\n mp[ransomNote[j]] -= 1\n\n return True",
"type": "Optimal"
}
]
},
{
"id": 6,
"question": "Given a pattern and a string s, find if s follows the same pattern.\nHere follow means a full match, such that there is a bijection between a letter in pattern and a non-empty word in s. Specifically:\nEach letter in pattern maps to exactly one unique word in s.\nEach unique word in s maps to exactly one letter in pattern.\nNo two letters map to the same word, and no two words map to the same letter.\n\nExample 1:\nInput: pattern = \"abba\", s = \"dog cat cat dog\"\nOutput: true\n\nExplanation:\nThe bijection can be established as:\n'a' maps to \"dog\".\n'b' maps to \"cat\".\n\nExample 2:\nInput: pattern = \"abba\", s = \"dog cat cat fish\"\nOutput: false\n\nExample 3:\nInput: pattern = \"aaaa\", s = \"dog cat cat dog\"\nOutput: false\n\n\nConstraints:\n1 <= pattern.length <= 300\npattern contains only lower-case English letters.\n1 <= s.length <= 3000\ns contains only lowercase English letters and spaces ' '.\ns does not contain any leading or trailing spaces.\nAll the words in s are separated by a single space.",
"topic": "Hashing",
"pattern": "HashMap / Bijective Mapping",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Word Pattern",
"problem_link": "https://leetcode.com/problems/word-pattern",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/3_Hashing/6_Word_Pattern.py",
"approaches": [
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(pattern)+O(words)",
"intuition": "all the characters mapped shoudl be consitent\nif a character say a was mapped to cat\nthen in the future it should stay as cat only",
"code": "class Solution:\n def wordPattern(self, pattern: str, s: str) -> bool:\n words = s.split()\n if len(pattern) != len(words):\n return False\n\n char_to_word = {}\n word_to_char = {}\n\n for i in range(len(pattern)):\n c = pattern[i]\n w = words[i]\n\n if c in char_to_word and w != char_to_word[c]:\n return False\n\n if w in word_to_char and c != word_to_char[w]:\n return False\n\n char_to_word[c] = w\n word_to_char[w] = c\n\n return True",
"type": "Optimal"
}
]
},
{
"id": 7,
"question": "Given an integer array nums and an integer k, return true if there are two distinct indices i and j in the array such that nums[i] == nums[j] and abs(i - j) <= k.\n\nExample 1:\nInput: nums = [1,2,3,1], k = 3\nOutput: true\n\nExample 2:\nInput: nums = [1,0,1,1], k = 1\nOutput: true\n\nExample 3:\nInput: nums = [1,2,3,1,2,3], k = 2\nOutput: false\n\nConstraints:\n1 <= nums.length <= 10^5\n-10^9 <= nums[i] <= 10^9\n0 <= k <= 10^5",
"topic": "Hashing",
"pattern": "HashMap / Sliding Window",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Contains Duplicate II",
"problem_link": "https://leetcode.com/problems/contains-duplicate-ii",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/3_Hashing/7_Contains_Duplicate_II.py",
"approaches": [
{
"tc": "T.C. - O(n^2)",
"sc": "S.C - O(1)",
"intuition": "Try finding all the possible pairs which satisfies the condition if pair found return true return false",
"code": "from typing import List\n\n\nclass Solution:\n def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:\n for i in range(len(nums)):\n for j in range(i + 1, len(nums)):\n if nums[i] == nums[j] and abs(i - j) <= k:\n return True\n\n return False",
"type": "Brute"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(n)",
"intuition": "Store all the numbers as you visit them\nif we have already encountered current number before\nwe check whether its satisfies the given condition",
"code": "from typing import List\n\n\nclass Solution:\n def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:\n visited = {}\n\n for idx, num in enumerate(nums):\n if num in visited and abs(idx - visited[num]) <= k:\n return True\n visited[num] = idx\n\n return False",
"type": "Optimal"
}
]
},
{
"id": 8,
"question": "Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.\n\nA subarray is a contiguous non-empty sequence of elements within an array.\n\n\nExample 1:\nInput: nums = [1,1,1], k = 2\nOutput: 2\n\nExample 2:\nInput: nums = [1,2,3], k = 3\nOutput: 2\n\nConstraints:\n1 <= nums.length <= 2 * 10^4\n-1000 <= nums[i] <= 1000\n-10^7 <= k <= 10^7",
"topic": "Hashing",
"pattern": "Prefix Sum + HashMap",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Subarray Sum Equals K",
"problem_link": "https://leetcode.com/problems/subarray-sum-equals-k",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/3_Hashing/8_Subarray_Sum_Equals_K.py",
"approaches": [
{
"tc": "T.C. - O(n^2)",
"sc": "S.C - O(1)",
"intuition": "Generate all possible subarrays and check which subarrays gives us sum k",
"code": "from typing import List\n\n\nclass Solution:\n def subarraySum(self, nums: List[int], k: int) -> int:\n c = 0\n\n for i in range(len(nums)):\n sm = 0\n for j in range(i, len(nums)):\n sm += nums[j]\n\n if sm == k:\n c += 1\n\n return c",
"type": "Brute"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(n)",
"intuition": "We are going to use the concept of prefix sum.\nwe need to observe that if there exists another\nsubarray ending at index i with sum k,\nthen the prefix sum of the rest of the subarray will be x-k.\nfor a subarray ending at index i with the prefix sum x,\nif we remove the part with the prefix sum x-k, we will\nbe left with the part whose sum is equal to k.\nNow, there may exist multiple subarrays with the prefix sum x-k.\nSo, the number of subarrays with sum k that we can generate\nfrom the entire subarray ending at index i, is exactly equal\nto the number of subarrays with the prefix sum x-k,\nthat we can remove from the entire subarray.\nWe carry the cumultaive sum(x) till now and at\nevery index i we are going to check if there\nexists a sum (x-k) we have encounterd before.\nif we have encounterd (x-k) then we can say\nthere exists a subarray of size k.",
"code": "from typing import List\n\n\nclass Solution:\n def subarraySum(self, nums: List[int], k: int) -> int:\n curr_pref_sum = 0\n freq_mp = {0: 1}\n c = 0\n\n for num in nums:\n curr_pref_sum += num\n complement = curr_pref_sum - k\n\n if complement in freq_mp:\n c += freq_mp[complement]\n\n freq_mp[curr_pref_sum] = freq_mp.get(curr_pref_sum, 0) + 1\n\n return c",
"type": "Optimal"
}
]
},
{
"id": 9,
"question": "Given an array of integers arr[] and a number k, count the number of subarrays having XOR of their elements as k.\n\nExamples:\n\nInput: arr[] = [4, 2, 2, 6, 4], k = 6\nOutput: 4\nExplanation: The subarrays having XOR of their elements as 6 are [4, 2], [4, 2, 2, 6, 4], [2, 2, 6], and [6]. Hence, the answer is 4.\n\nInput: arr[] = [5, 6, 7, 8, 9], k = 5\nOutput: 2\nExplanation: The subarrays having XOR of their elements as 5 are [5] and [5, 6, 7, 8, 9]. Hence, the answer is 2.\n\nInput: arr[] = [1, 1, 1, 1], k = 0\nOutput: 4\nExplanation: The subarrays are [1, 1], [1, 1], [1, 1] and [1, 1, 1, 1].\n\nConstraints:\n1 \u2264 arr.size() \u2264 10^5\n0 \u2264 arr[i] \u226410^5\n0 \u2264 k \u2264 10^5",
"topic": "Hashing",
"pattern": "Prefix XOR + HashMap",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Count Subarrays with given XOR",
"problem_link": "https://www.geeksforgeeks.org/problems/count-subarray-with-given-xor/1",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/3_Hashing/9_Count_Subarrays_with_given_XOR.py",
"approaches": [
{
"tc": "T.C. - O(n^2)",
"sc": "S.C - O(1)",
"intuition": "Generate all possible subarrays and check which subarrays gives us xor k",
"code": "from typing import List\n\n\ndef countSubarraysXor_bruteforce(arr: List[int], k: int):\n cnt = 0\n n = len(arr)\n for i in range(n):\n cur_xor = 0\n for j in range(i, n):\n cur_xor ^= arr[j]\n if cur_xor == k:\n cnt += 1\n return cnt",
"type": "Brute"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(n)",
"intuition": "We are going to use the concept of prefix XOR.\nObserve that if a subarray ending at index\u202fi has XOR equal to k,\nthen the XOR of the part of the array before that subarray must be x\u202f\u2295\u202fk, where x is the current prefix XOR up to i.\nFor a subarray that ends at i with prefix XOR x, removing\nthe earlier segment whose prefix XOR is x\u202f\u2295\u202fk leaves exactly the segment whose XOR is k.\nThere can be many earlier positions whose prefix XOR equals x\u202f\u2295\u202fk.\nThe number of subarrays with XOR k that end at i is therefore exactly the number of times the value x\u202f\u2295\u202fk has already been seen.\nWe keep a running prefix XOR x while scanning the array, and at each index i\nwe check whether the value x\u202f\u2295\u202fk has been encountered before. Every\nprior occurrence of x\u202f\u2295\u202fk indicates a distinct subarray ending at i whose XOR is k.",
"code": "from typing import List\n\n\nclass Solution:\n def subarrayXor(self, arr: List[int], k: int):\n curr_pref_xor = 0\n freq_mp = {0: 1}\n c = 0\n\n for _, num in enumerate(arr):\n curr_pref_xor ^= num\n complement = curr_pref_xor ^ k\n\n if complement in freq_mp:\n c += freq_mp[complement]\n\n freq_mp[curr_pref_xor] = 1 + freq_mp.get(curr_pref_xor, 0)\n\n return c",
"type": "Optimal"
}
]
},
{
"id": 10,
"question": "Given an array arr[] containing integers and an integer k, your task is to find the length of the longest subarray where the sum of its elements is equal to the given value k. If there is no subarray with sum equal to k, return 0.\n\nExamples:\n\nInput: arr[] = [10, 5, 2, 7, 1, -10], k = 15\nOutput: 6\nExplanation: Subarrays with sum = 15 are [5, 2, 7, 1], [10, 5] and [10, 5, 2, 7, 1, -10]. The length of the longest subarray with a sum of 15 is 6.\n\nInput: arr[] = [-5, 8, -14, 2, 4, 12], k = -5\nOutput: 5\nExplanation: Only subarray with sum = -5 is [-5, 8, -14, 2, 4] of length 5.\n\nInput: arr[] = [10, -10, 20, 30], k = 5\nOutput: 0\nExplanation: No subarray with sum = 5 is present in arr[].\n\nConstraints:\n1 \u2264 arr.size() \u2264 10^5\n-10^4 \u2264 arr[i] \u2264 10^4\n-10^9 \u2264 k \u2264 10^9",
"topic": "Hashing",
"pattern": "Prefix Sum + HashMap",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Longest Subarray with Sum K",
"problem_link": "https://www.geeksforgeeks.org/problems/longest-sub-array-with-sum-k0809/1",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/3_Hashing/10_Longest_Subarray_with_Sum_K.py",
"approaches": [
{
"tc": "T.C. - O(n^2)",
"sc": "S.C - O(1)",
"intuition": "Generate all pssible subarrays Find the longeest subarray with sum k",
"code": "from typing import List\n\n\nclass Solution:\n def longestSubarray(self, arr: List[int], k: int):\n longest = 0\n\n for i in range(len(arr)):\n sm = 0\n for j in range(i, len(arr)):\n sm += arr[j]\n if sm == k:\n longest = max(longest, j - i + 1)\n\n return longest",
"type": "Brute"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(n)",
"intuition": "We use the concept of prefix sum but\nnow we store the index as close to left\nas possible to increase the subarray size",
"code": "from typing import List\n\n\nclass Solution:\n def longestSubarray(self, arr: List[int], k: int):\n curr_pref_sum = 0\n idx_mp = {0: -1}\n longest = 0\n\n for idx, num in enumerate(arr):\n curr_pref_sum += num\n complement = curr_pref_sum - k\n\n if complement in idx_mp:\n longest = max(longest, idx - idx_mp[complement])\n\n # store the index as left as possible as newer index will decrease our size\n if curr_pref_sum not in idx_mp:\n idx_mp[curr_pref_sum] = idx\n\n return longest",
"type": "Optimal"
}
]
},
{
"id": 11,
"question": "Given an unsorted array of integers nums, return the length of the longest consecutive elements sequence.\nYou must write an algorithm that runs in O(n) time.\n\nExample 1:\nInput: nums = [100,4,200,1,3,2]\nOutput: 4\nExplanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4.\n\nExample 2:\nInput: nums = [0,3,7,2,5,8,4,6,0,1]\nOutput: 9\n\nExample 3:\nInput: nums = [1,0,1,2]\nOutput: 3\n\nConstraints:\n0 <= nums.length <= 10^5\n-10^9 <= nums[i] <= 10^9",
"topic": "Hashing",
"pattern": "HashSet / Union-Find",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Longest Consecutive Sequence",
"problem_link": "https://leetcode.com/problems/longest-consecutive-sequence",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/3_Hashing/11_Longest_Consecutive_Sequence.py",
"approaches": [
{
"tc": "T.C. - O(n^2)",
"sc": "S.C - O(1)",
"intuition": "For every value in array check whether its consecutive elements are present or not",
"code": "from typing import List\n\n\nclass Solution:\n def linearSearch(self, arr: List[int], targetVal: int):\n for i in range(len(arr)):\n if arr[i] == targetVal:\n return i\n return -1\n\n def longestConsecutive(self, nums: List[int]) -> int:\n longest = 0\n\n for i in range(len(nums)):\n curr = nums[i]\n length = 1\n while self.linearSearch(nums, curr + length) != -1:\n length += 1\n longest = max(longest, length)\n\n return longest",
"type": "Brute"
},
{
"tc": "T.C. - O(nlog(n))",
"sc": "S.C - O(1)",
"intuition": "Sort the array Check whether the array follow the consecutive sequence pattern",
"code": "from typing import List\n\n\nclass Solution:\n def longestConsecutive(self, nums: List[int]) -> int:\n if len(nums) == 0:\n return 0\n\n longest = 1\n curr_length = 1\n nums.sort()\n\n for i in range(1, len(nums)):\n if nums[i - 1] == nums[i]:\n continue\n\n if nums[i - 1] == nums[i] - 1:\n curr_length += 1\n else:\n curr_length = 1\n\n longest = max(longest, curr_length)\n\n return longest",
"type": "Better"
},
{
"tc": "T.C. - O(n)+O(2n)",
"sc": "S.C - O(n)",
"intuition": "The answer lies in visualization\nconsider the below array\n100 4 200 1 3 2\n\n1 2 3 4 100 200\n---------------------------\n\nconvert the given array to set\nstarting values of the sequence does not have left neightbour\nso whenever we find an element which does not have left neightbour\nwe will start a while loop incrementing it by 1 and check if that\nnumber exists and keep on building the sequence and atlast we can\ncheck if its the max length till now or not",
"code": "from typing import List\n\n\nclass Solution:\n def longestConsecutive(self, nums: List[int]) -> int:\n numSet = set(nums)\n longest = 0\n\n for num in numSet:\n if (num - 1) not in numSet:\n length = 1\n while (num + length) in numSet:\n length += 1\n longest = max(length, longest)\n return longest",
"type": "Optimal"
}
]
},
{
"id": 12,
"question": "Implement the RandomizedSet class:\n\nRandomizedSet() Initializes the RandomizedSet object.\nbool insert(int val) Inserts an item val into the set if not present. Returns true if the item was not present, false otherwise.\nbool remove(int val) Removes an item val from the set if present. Returns true if the item was present, false otherwise.\nint getRandom() Returns a random element from the current set of elements (it's guaranteed that at least one\nelement exists when this method is called). Each element must have the same probability of being returned.\nYou must implement the functions of the class such that each function works in average O(1) time complexity.\n\nExample 1:\nInput\n[\"RandomizedSet\", \"insert\", \"remove\", \"insert\", \"getRandom\", \"remove\", \"insert\", \"getRandom\"]\n[[], [1], [2], [2], [], [1], [2], []]\nOutput\n[null, true, false, true, 2, true, false, 2]\n\nExplanation\nRandomizedSet randomizedSet = new RandomizedSet();\nrandomizedSet.insert(1); // Inserts 1 to the set. Returns true as 1 was inserted successfully.\nrandomizedSet.remove(2); // Returns false as 2 does not exist in the set.\nrandomizedSet.insert(2); // Inserts 2 to the set, returns true. Set now contains [1,2].\nrandomizedSet.getRandom(); // getRandom() should return either 1 or 2 randomly.\nrandomizedSet.remove(1); // Removes 1 from the set, returns true. Set now contains [2].\nrandomizedSet.insert(2); // 2 was already in the set, so return false.\nrandomizedSet.getRandom(); // Since 2 is the only number in the set, getRandom() will always return 2.\n\n\nConstraints:\n\n-2^31 <= val <= 2^31 - 1\nAt most 2 * 105 calls will be made to insert, remove, and getRandom.\nThere will be at least one element in the data structure when getRandom is called.",
"topic": "Hashing",
"pattern": "HashMap / Set",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Insert Delete GetRandom O(1)",
"problem_link": "https://leetcode.com/problems/insert-delete-getrandom-o1",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/3_Hashing/12_Insert_Delete_GetRandom_O(1).py",
"approaches": [
{
"tc": "T.C. - O(1)",
"sc": "S.C - O(n)+O(n) ~ O(n)",
"intuition": "Use a map and store the val,index pair in it\nUse an array to store elements\nUse an index to track last inserted element index\n+ Every time a get request come return true if not found otherwise false by doing a lookup in map\n+ Every time a remove request come return false if\nfound and find the index of element to be deleted from the map\nand swap it with element at last index\nAlso update the index of the last element\nAlso remove the entry from map and list\nnot found otherwise true\n+ Every time getRandom request comes use random.choice library over the stored array",
"code": "import random\nfrom typing import Dict, List\n\n\nclass RandomizedSet:\n def __init__(self) -> None:\n self.mp: Dict[int, int] = {}\n self.arr: List[int] = []\n\n def insert(self, val: int) -> bool:\n if val in self.mp:\n return False\n self.mp[val] = len(self.arr)\n self.arr.append(val)\n return True\n\n def remove(self, val: int) -> bool:\n if val not in self.mp:\n return False\n\n # Index of element to delete and index of last element\n idx_to_delete = self.mp[val]\n last_idx = len(self.arr) - 1\n last_val = self.arr[last_idx]\n\n # Move last element into the spot of the element to delete\n self.arr[idx_to_delete], self.arr[last_idx] = (\n self.arr[last_idx],\n self.arr[idx_to_delete],\n )\n self.mp[last_val] = idx_to_delete\n\n # Remove the last element from the list and delete the map entry\n self.arr.pop(-1)\n del self.mp[val]\n\n return True\n\n def getRandom(self) -> int:\n return random.choice(self.arr)",
"type": "Optimal"
}
]
},
{
"id": 1,
"question": "You are given two integer arrays nums1 and nums2, sorted in non-decreasing order, and two integers m and n,\nrepresenting the number of elements in nums1 and nums2 respectively.\nMerge nums1 and nums2 into a single array sorted in non-decreasing order.\nThe final sorted array should not be returned by the function, but instead be stored inside the array nums1.\nTo accommodate this, nums1 has a length of m + n, where the first m elements denote the elements that\nshould be merged, and the last n elements are set to 0 and should be ignored. nums2 has a length of n.\n\n\nExample 1:\nInput: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3\nOutput: [1,2,2,3,5,6]\nExplanation: The arrays we are merging are [1,2,3] and [2,5,6].\nThe result of the merge is [1,2,2,3,5,6] with the underlined elements coming from nums1.\n\nExample 2:\nInput: nums1 = [1], m = 1, nums2 = [], n = 0\nOutput: [1]\nExplanation: The arrays we are merging are [1] and [].\nThe result of the merge is [1].\n\nExample 3:\nInput: nums1 = [0], m = 0, nums2 = [1], n = 1\nOutput: [1]\nExplanation: The arrays we are merging are [] and [1].\nThe result of the merge is [1].\nNote that because m = 0, there are no elements in nums1. The 0 is only there to ensure the merge result can fit in nums1.\n\nConstraints:\nnums1.length == m + n\nnums2.length == n\n0 <= m, n <= 200\n1 <= m + n <= 200\n-10^9 <= nums1[i], nums2[j] <= 10^9\n\nFollow up: Can you come up with an algorithm that runs in O(m + n) time?",
"topic": "TwoPointers",
"pattern": "Two Pointers",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Merge Sorted Array",
"problem_link": "https://leetcode.com/problems/merge-sorted-array",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/4_Two_Pointers/1_Merge_Sorted_Array.py",
"approaches": [
{
"tc": "T.C. - O(m+n)+O(m+n)",
"sc": "S.C - O(m+n)",
"intuition": "We apply the classic merge 2 sorted algorithm We store the data in a temporary array Then we copy the data from temporary array to nums1",
"code": "from typing import List\n\n\nclass Solution:\n def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:\n \"\"\"\n Do not return anything, modify nums1 in-place instead.\n \"\"\"\n\n tmp = [0] * (m + n)\n p1, p2 = 0, 0\n k = 0\n\n while p1 < m and p2 < n:\n if nums1[p1] < nums2[p2]:\n tmp[k] = nums1[p1]\n p1 += 1\n else:\n tmp[k] = nums2[p2]\n p2 += 1\n k += 1\n\n while p1 < m:\n tmp[k] = nums1[p1]\n p1 += 1\n k += 1\n\n while p2 < n:\n tmp[k] = nums2[p2]\n p2 += 1\n k += 1\n\n for i in range(len(tmp)):\n nums1[i] = tmp[i]",
"type": "Brute"
},
{
"tc": "T.C. - O(m+n)",
"sc": "S.C - O(1)",
"intuition": "When merging nums2 into nums1 in-place, starting from the front can destroy data you still need.\n\nExample:\nnums1 = [2, 7, 0, 0], m = 2\nnums2 = [1, 3], n = 2\n\nIf you start filling from index 0 with the smallest element, you might put 1 at nums1[0] and\nthen 2 at nums1[1], but in the process you can overwrite 7 before you\u2019ve compared it with 3.\nThis makes it hard to correctly merge while preserving all elements.\n\nTo avoid overwriting useful values, we go from right to left. nums1 has enough space at\nthe end (the zeros) to hold all elements, so we fill from the last index:\n\nCompare the largest elements: 7 (from nums1) and 3 (from nums2); place 7 at the end.\nThen compare 2 and 3; place 3.\nThen compare 2 and 1; place 2.\nFinally place 1.\nThis gives: [1, 2, 3, 7], and we never overwrite a needed element.\n\nIf nums1\u2019s initial part is exhausted before nums2 (for example, nums1 = [0,0,0], m = 0,\nnums2 = [2,5,6], n = 3), we simply copy all remaining elements from nums2 into\nnums1 from the back, which still results in a sorted array.",
"code": "from typing import List\n\n\nclass Solution:\n def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:\n \"\"\"\n Do not return anything, modify nums1 in-place instead.\n \"\"\"\n\n p1, p2 = m - 1, n - 1\n k = m + n - 1\n\n while p1 >= 0 and p2 >= 0:\n if nums2[p2] > nums1[p1]:\n nums1[k] = nums2[p2]\n p2 -= 1\n else:\n nums1[k] = nums1[p1]\n p1 -= 1\n k -= 1\n\n while p2 >= 0 and p1 < 0:\n nums1[k] = nums2[p2]\n p2 -= 1\n k -= 1",
"type": "Optimal"
}
]
},
{
"id": 2,
"question": "Given an integer array nums, move all 0's to the end of it while maintaining the relative order of the non-zero elements.\n\nNote that you must do this in-place without making a copy of the array.\n\n\nExample 1:\nInput: nums = [0,1,0,3,12]\nOutput: [1,3,12,0,0]\n\nExample 2:\nInput: nums = [0]\nOutput: [0]\n\nConstraints:\n1 <= nums.length <= 10^4\n-23^1 <= nums[i] <= 2^31 - 1\n\nFollow up: Could you minimize the total number of operations done?",
"topic": "TwoPointers",
"pattern": "Two Pointers",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Move Zeroes",
"problem_link": "https://leetcode.com/problems/move-zeroes",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/4_Two_Pointers/2_Move_Zeroes.py",
"approaches": [
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(n)",
"intuition": "Store the non zero elements in an temporary array then assign nums to temporary array",
"code": "from typing import List\n\n\nclass Solution:\n def moveZeroes(self, nums: List[int]) -> None:\n \"\"\"\n Do not return anything, modify nums in-place instead.\n \"\"\"\n tmp = [0] * len(nums)\n\n k = 0\n for i in range(len(nums)):\n if nums[i] != 0:\n tmp[k] = nums[i]\n k += 1\n\n nums[:] = tmp",
"type": "Brute"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(1)",
"intuition": "All non-zero elements should end up on the left side of the array, and all zeros on the right,\nwhile keeping the relative order of non-zero elements the same.\n\nTo do this, think of one pointer as a \u201cwrite\u201d pointer that marks the position where\nthe next non-zero element should go, and another pointer as a \u201cscan\u201d pointer that\nmoves through the array. As we scan, whenever we see a non-zero value, we swap it into\nthe position of the write pointer and move the write pointer forward. Zeros are simply skipped.\n\nFor example, in [0, 1, 0, 3, 12]:\n\nScan hits 1: swap with first position \u2192 [1, 0, 0, 3, 12]\nScan hits 3: put it next \u2192 [1, 3, 0, 0, 12]\nScan hits 12: put it next \u2192 [1, 3, 12, 0, 0]\nBy the end, all non-zeros are compacted at the front in their original order, and zeros naturally move to the back.",
"code": "from typing import List\n\n\nclass Solution:\n def moveZeroes(self, nums: List[int]) -> None:\n \"\"\"\n Do not return anything, modify nums in-place instead.\n \"\"\"\n\n p1, p2 = 0, 0\n while p2 < len(nums):\n if nums[p2] != 0:\n nums[p1], nums[p2] = nums[p2], nums[p1]\n p1 += 1\n p2 += 1",
"type": "Optimal"
}
]
},
{
"id": 3,
"question": "Given an integer array nums and an integer val, remove all occurrences of val in nums in-place. The order of the elements may be changed.\nThen return the number of elements in nums which are not equal to val.\n\nConsider the number of elements in nums which are not equal to val be k, to get accepted, you need to do the following things:\n\nChange the array nums such that the first k elements of nums contain the elements which are not equal to val. The\nremaining elements of nums are not important as well as the size of nums.\nReturn k.\nCustom Judge:\n\nThe judge will test your solution with the following code:\n\nint[] nums = [...]; // Input array\nint val = ...; // Value to remove\nint[] expectedNums = [...]; // The expected answer with correct length.\n// It is sorted with no values equaling val.\n\nint k = removeElement(nums, val); // Calls your implementation\n\nassert k == expectedNums.length;\nsort(nums, 0, k); // Sort the first k elements of nums\nfor (int i = 0; i < actualLength; i++) {\nassert nums[i] == expectedNums[i];\n}\nIf all assertions pass, then your solution will be accepted.\n\nExample 1:\nInput: nums = [3,2,2,3], val = 3\nOutput: 2, nums = [2,2,_,_]\nExplanation: Your function should return k = 2, with the first two elements of nums being 2.\nIt does not matter what you leave beyond the returned k (hence they are underscores).\n\nExample 2:\nInput: nums = [0,1,2,2,3,0,4,2], val = 2\nOutput: 5, nums = [0,1,4,0,3,_,_,_]\nExplanation: Your function should return k = 5, with the first five elements of nums containing 0, 0, 1, 3, and 4.\nNote that the five elements can be returned in any order.\nIt does not matter what you leave beyond the returned k (hence they are underscores).\n\nConstraints:\n0 <= nums.length <= 100\n0 <= nums[i] <= 50\n0 <= val <= 100",
"topic": "TwoPointers",
"pattern": "Two Pointers",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Remove Element",
"problem_link": "https://leetcode.com/problems/remove-element",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/4_Two_Pointers/3_Remove_Element.py",
"approaches": [
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(n)",
"intuition": "store all the non zero values in a temporary array assign nums to temporary array return the length of nums array",
"code": "from typing import List\n\n\nclass Solution:\n def removeElement(self, nums: List[int], val: int) -> int:\n ls = []\n\n for i in nums:\n if i != val:\n ls.append(i)\n nums[:] = ls[:]\n\n return len(ls)",
"type": "Brute"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(1)",
"intuition": "All elements that are not equal to val should end up on the left side of the array,\nand all occurrences of val can be pushed to the right (their positions don\u2019t matter after removal).\nWe only care about how many non-val elements remain and that they occupy the first k positions.\nTo do this, think of one pointer k as the position where the next \u201ckept\u201d element (not equal to val) should go,\nand another pointer idx that scans through the array. As we scan:\nIf nums[idx] is not val, we swap it into position k and move k forward.\nIf nums[idx] is val, we just skip it.",
"code": "from typing import List\n\n\nclass Solution:\n def removeElement(self, nums: List[int], val: int) -> int:\n k = 0\n idx = 0\n\n while idx < len(nums):\n if nums[idx] != val:\n nums[idx], nums[k] = nums[k], nums[idx]\n k += 1\n idx += 1\n\n return k",
"type": "Optimal"
}
]
},
{
"id": 4,
"question": "Given an integer array nums sorted in non-decreasing order, remove the duplicates in-place such that each unique element appears only once.\nThe relative order of the elements should be kept the same.\nConsider the number of unique elements in nums to be k. After removing duplicates, return the number of unique elements k.\n\nThe first k elements of nums should contain the unique numbers in sorted order. The remaining elements beyond index k - 1 can be ignored.\n\nCustom Judge:\nThe judge will test your solution with the following code:\nint[] nums = [...]; // Input array\nint[] expectedNums = [...]; // The expected answer with correct length\nint k = removeDuplicates(nums); // Calls your implementation\nassert k == expectedNums.length;\nfor (int i = 0; i < k; i++) {\nassert nums[i] == expectedNums[i];\n}\nIf all assertions pass, then your solution will be accepted.\n\n\nExample 1:\nInput: nums = [1,1,2]\nOutput: 2, nums = [1,2,_]\nExplanation: Your function should return k = 2, with the first two elements of nums being 1 and 2 respectively.\nIt does not matter what you leave beyond the returned k (hence they are underscores).\n\nExample 2:\nInput: nums = [0,0,1,1,1,2,2,3,3,4]\nOutput: 5, nums = [0,1,2,3,4,_,_,_,_,_]\nExplanation: Your function should return k = 5, with the first five elements of nums being 0, 1, 2, 3, and 4 respectively.\nIt does not matter what you leave beyond the returned k (hence they are underscores).\n\nConstraints:\n1 <= nums.length <= 3 * 10^4\n-100 <= nums[i] <= 100\nnums is sorted in non-decreasing order.",
"topic": "TwoPointers",
"pattern": "Two Pointers",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Remove Duplicates from Sorted Array",
"problem_link": "https://leetcode.com/problems/remove-duplicates-from-sorted-array",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/4_Two_Pointers/4_Remove_Duplicates_from_Sorted_Array.py",
"approaches": [
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(n)",
"intuition": "We use two pointers , k to keep track of the position to insert unique element and i to traverse the whole array, if we see an element that we have not seen before, we add it to the kth index and mark it as visited",
"code": "from typing import List\n\n\nclass Solution:\n def removeDuplicates(self, nums: List[int]) -> int:\n visited = {}\n k = 0\n\n for i in range(len(nums)):\n if nums[i] not in visited:\n nums[k] = nums[i]\n k += 1\n visited[nums[i]] = 1\n\n return k",
"type": "Brute"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(1)",
"intuition": "The array is sorted, so any duplicates appear next to each other.\nWe scan the array with an index i and keep another index k that tracks\nthe position where the next unique element should be written.\n\nWhenever nums[i] is different from the previous element, it means we are\nseeing this value for the first time in sequence, so it is unique at this point.\n\nWe then place nums[i] at index k and move k forward.\nBy the end, the first k positions of the array contain all unique elements\nin sorted order, and k is the count of unique elements.",
"code": "from typing import List\n\n\nclass Solution:\n def removeDuplicates(self, nums: List[int]) -> int:\n k = 1\n for i in range(1, len(nums)):\n if nums[i] != nums[i - 1]:\n nums[k] = nums[i]\n k += 1\n\n return k",
"type": "Optimal"
}
]
},
{
"id": 5,
"question": "Given an integer array nums sorted in non-decreasing order, remove some duplicates in-place\nsuch that each unique element appears at most twice. The relative order of the elements should be kept the same.\nSince it is impossible to change the length of the array in some languages, you must instead\nhave the result be placed in the first part of the array nums. More formally, if there are k\nelements after removing the duplicates, then the first k elements of nums should hold the final result.\nIt does not matter what you leave beyond the first k elements.\nReturn k after placing the final result in the first k slots of nums.\n\nDo not allocate extra space for another array. You must do this by modifying the input array in-place with O(1) extra memory.\n\nCustom Judge:\nThe judge will test your solution with the following code:\n\nint[] nums = [...]; // Input array\nint[] expectedNums = [...]; // The expected answer with correct length\n\nint k = removeDuplicates(nums); // Calls your implementation\n\nassert k == expectedNums.length;\nfor (int i = 0; i < k; i++) {\nassert nums[i] == expectedNums[i];\n}\nIf all assertions pass, then your solution will be accepted.\n\n\nExample 1:\nInput: nums = [1,1,1,2,2,3]\nOutput: 5, nums = [1,1,2,2,3,_]\nExplanation: Your function should return k = 5, with the first five elements of nums being 1, 1, 2, 2 and 3 respectively.\nIt does not matter what you leave beyond the returned k (hence they are underscores).\n\nExample 2:\nInput: nums = [0,0,1,1,1,1,2,3,3]\nOutput: 7, nums = [0,0,1,1,2,3,3,_,_]\nExplanation: Your function should return k = 7, with the first seven elements of nums being 0, 0, 1, 1, 2, 3 and 3 respectively.\nIt does not matter what you leave beyond the returned k (hence they are underscores).\n\n\nConstraints:\n1 <= nums.length <= 3 * 10^4\n-10^4 <= nums[i] <= 10^4\nnums is sorted in non-decreasing order.",
"topic": "TwoPointers",
"pattern": "Two Pointers",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Remove Duplicates from Sorted Array II",
"problem_link": "https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/4_Two_Pointers/5_Remove_Duplicates_from_Sorted_Array_II.py",
"approaches": [
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(n)",
"intuition": "We use two pointers , k to keep track of the position to insert unique element and i to traverse the whole array, if we see an element that we have not seen before or if the element is visited but its visted count is less than 2, we add it to the kth index and mark it as visited",
"code": "from typing import List\n\n\nclass Solution:\n def removeDuplicates(self, nums: List[int]) -> int:\n visited = {}\n k = 0\n\n for i in range(len(nums)):\n if nums[i] not in visited or (visited.get(nums[i], 0)) < 2:\n nums[k] = nums[i]\n k += 1\n\n visited[nums[i]] = 1 + visited.get(nums[i], 0)\n\n return k",
"type": "Brute"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(1)",
"intuition": "The array is sorted, so equal elements are grouped together. We want each\nelement to appear at most twice in the final array.\n\nWe use:\n- i : to traverse the array from left to right (starting at index 1)\n- k : to mark the position where the next allowed element should be placed\n- count : to track how many times the current value has appeared consecutively\n\nThe logic follows two simple rules:\n1) If we see the *same* element as the previous one:\n- If count < 2, we are allowed to keep it, so we write it at index k\nand increase both k and count.\n- If count == 2, we skip it (do nothing), because we already kept two.\n\n2) If we see a *new* element (different from the previous one):\n- We reset count to 1 (first occurrence of this new value),\nwrite it at index k, and move k forward.",
"code": "from typing import List\n\n\nclass Solution:\n def removeDuplicates(self, nums: List[int]) -> int:\n k = 1\n count = 1\n\n for i in range(1, len(nums)):\n if count < 2 and nums[i] == nums[i - 1]:\n nums[k] = nums[i]\n k += 1\n count += 1\n\n elif nums[i] != nums[i - 1]:\n nums[k] = nums[i]\n count = 1\n k += 1\n\n return k",
"type": "Optimal"
}
]
},
{
"id": 6,
"question": "Given an integer array nums sorted in non-decreasing order, return an array of the squares of each number sorted in non-decreasing order.\n\nExample 1:\nInput: nums = [-4,-1,0,3,10]\nOutput: [0,1,9,16,100]\nExplanation: After squaring, the array becomes [16,1,0,9,100].\nAfter sorting, it becomes [0,1,9,16,100].\n\nExample 2:\nInput: nums = [-7,-3,2,3,11]\nOutput: [4,9,9,49,121]\n\nConstraints:\n1 <= nums.length <= 10^4\n-10^4 <= nums[i] <= 10^4\nnums is sorted in non-decreasing order.\n\nFollow up: Squaring each element and sorting the new array is very trivial, could you find an O(n) solution using a different approach?",
"topic": "TwoPointers",
"pattern": "Two Pointers",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Squares of a Sorted Array",
"problem_link": "https://leetcode.com/problems/squares-of-a-sorted-array",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/4_Two_Pointers/6_Squares_of_a_Sorted_Array.py",
"approaches": [
{
"tc": "T.C. - O(n)+O(nlog(n))",
"sc": "S.C - O(n)",
"intuition": "Square each number in the array sort the array",
"code": "from typing import List\n\n\nclass Solution:\n def sortedSquares(self, nums: List[int]) -> List[int]:\n return sorted([i * i for i in nums])",
"type": "Brute"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(1)",
"intuition": "The array is sorted in non-decreasing order, so negative numbers (if any)\nare on the left and positive numbers are on the right. When we square them,\nboth sides become non-negative, and the largest squares will come from the\nvalues with the largest absolute magnitude, which are at the two ends.\n\nThis means the biggest square is always at either the leftmost or rightmost\nposition of the current range. So we use two pointers:\n- p1 at the start (left side, large negative numbers)\n- p2 at the end (right side, large positive numbers)\nand a pointer k at the end of the result array.\n\nAt each step, we compare nums[p1]^2 and nums[p2]^2:\n- Place the larger square at res[k].\n- Move the corresponding pointer (p1 or p2) inward.\n- Move k one step left to fill the next largest square.",
"code": "from typing import List\n\n\nclass Solution:\n def sortedSquares(self, nums: List[int]) -> List[int]:\n k = len(nums) - 1\n p1, p2 = 0, len(nums) - 1\n res = [0] * len(nums)\n\n while p1 <= p2:\n n1, n2 = nums[p1] ** 2, nums[p2] ** 2\n\n if n1 > n2:\n res[k] = n1\n p1 += 1\n else:\n res[k] = n2\n p2 -= 1\n\n k -= 1\n\n return res",
"type": "Optimal"
}
]
},
{
"id": 7,
"question": "Given two integer arrays nums1 and nums2, return an array of their intersection.\nEach element in the result must be unique and you may return the result in any order.\n\nExample 1:\nInput: nums1 = [1,2,2,1], nums2 = [2,2]\nOutput: [2]\n\nExample 2:\nInput: nums1 = [4,9,5], nums2 = [9,4,9,8,4]\nOutput: [9,4]\nExplanation: [4,9] is also accepted.\n\nConstraints:\n1 <= nums1.length, nums2.length <= 1000\n0 <= nums1[i], nums2[i] <= 1000",
"topic": "TwoPointers",
"pattern": "Two Pointers",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Intersection of Two Arrays",
"problem_link": "https://leetcode.com/problems/intersection-of-two-arrays",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/4_Two_Pointers/7_Intersection_of_Two_Arrays.py",
"approaches": [
{
"tc": "T.C. - O(mlog(m))+O(nlog(n))+O(m+n)",
"sc": "S.C - O(m+n)+O(m+n)",
"intuition": "Sort the array Take 2 pointers p1 and p2 pointing to start indexes of 2 arrays If elements at p1 and p2 are equal add it to resultant set otherwise increment the pointer that points to the smaller integer value",
"code": "from typing import List\n\n\nclass Solution:\n def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:\n nums1.sort()\n nums2.sort()\n\n res = set()\n p1, p2 = 0, 0\n\n while p1 < len(nums1) and p2 < len(nums2):\n if nums1[p1] == nums2[p2]:\n res.add(nums1[p1])\n p1 += 1\n p2 += 1\n else:\n if nums1[p1] < nums2[p2]:\n p1 += 1\n else:\n p2 += 1\n\n return list(res)",
"type": "Brute"
},
{
"tc": "T.C. - O(m+n)",
"sc": "S.C - O(m)+O(m+n)",
"intuition": "Take 2 visited maps for nums1 and nums2 Put all the elements of nums1 in a visited map 1 Traverse the second array nums2 only if it is present in first visted map and not in visited map 2 put it in the result array",
"code": "from typing import List\n\n\nclass Solution:\n def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:\n visited1 = {}\n res = []\n\n for num in nums1:\n visited1[num] = 1\n\n visited2 = {}\n for num in nums2:\n if num in visited1 and num not in visited2:\n res.append(num)\n visited2[num] = 1\n\n return res",
"type": "Better"
},
{
"tc": "T.C. - O(m+n)",
"sc": "S.C - O(m+n)",
"intuition": "We want the set of distinct numbers that appear in both arrays.\nA simple way is to remember which numbers appear in nums1, then\ncheck nums2 against that memory.\n\nWe first record all elements of nums1 in a map (or set-like structure),\nmeaning \u201cthese values exist in nums1\u201d. Then we scan nums2 and, for each\nnumber, check if it was present in nums1.\n\nTo avoid duplicates in the result, once we add a number from nums2 to\nthe result, we mark it as already used (or conceptually \"remove\" it\nfrom availability), so if it appears again in nums2 we do not add it twice.",
"code": "from typing import List\n\n\nclass Solution:\n def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:\n visited = {}\n res = []\n\n for num in nums1:\n visited[num] = False\n\n for num in nums2:\n if num in visited and not visited[num]:\n visited[num] = True\n res.append(num)\n\n return res",
"type": "Optimal"
}
]
},
{
"id": 8,
"question": "A phrase is a palindrome if, after converting all uppercase letters into lowercase letters and\nremoving all non-alphanumeric characters, it reads the same forward and backward. Alphanumeric characters include letters and numbers.\nGiven a string s, return true if it is a palindrome, or false otherwise.\n\n\nExample 1:\nInput: s = \"A man, a plan, a canal: Panama\"\nOutput: true\nExplanation: \"amanaplanacanalpanama\" is a palindrome.\n\nExample 2:\nInput: s = \"race a car\"\nOutput: false\nExplanation: \"raceacar\" is not a palindrome.\n\nExample 3:\nInput: s = \" \"\nOutput: true\nExplanation: s is an empty string \"\" after removing non-alphanumeric characters.\nSince an empty string reads the same forward and backward, it is a palindrome.",
"topic": "TwoPointers",
"pattern": "Two Pointers",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Valid Palindrome",
"problem_link": "https://leetcode.com/problems/valid-palindrome",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/4_Two_Pointers/8_Valid_Palindrome.py",
"approaches": [
{
"tc": "T.C. - O(n)+O(n)",
"sc": "S.C - O(n)",
"intuition": "Create a new string considering only alpha numeric characters then reverse the new string and check whether it becomes the new string or not",
"code": "class Solution:\n def isPalindrome(self, s: str) -> bool:\n new_st = \"\"\n\n for i in range(len(s)):\n if s[i].isalnum():\n new_st += s[i].lower()\n\n return new_st[::-1] == new_st",
"type": "Brute"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(1)",
"intuition": "We want to check if the string reads the same forward and backward,\nignoring non-alphanumeric characters and case.\n\nUse two pointers: one starting from the left, one from the right.\nMove both pointers inward:\n- Skip any character that is not a letter or digit on either side.\n- When both pointers point to valid characters, compare them in\nlowercase form.\nIf at any point the characters differ, it's not a palindrome.\nIf the pointers cross without a mismatch, the string is a valid palindrome.",
"code": "class Solution:\n def isPalindrome(self, s: str) -> bool:\n p1, p2 = 0, len(s) - 1\n\n while p1 < p2:\n if not s[p1].isalnum():\n p1 += 1\n continue\n\n if not s[p2].isalnum():\n p2 -= 1\n continue\n\n if s[p1].lower() != s[p2].lower():\n return False\n\n p1 += 1\n p2 -= 1\n\n return True",
"type": "Optimal"
}
]
},
{
"id": 9,
"question": "Given two strings s and t, return true if s is a subsequence of t, or false otherwise.\nA subsequence of a string is a new string that is formed from the original string by deleting\nsome (can be none) of the characters without disturbing the relative positions of the\nremaining characters. (i.e., \"ace\" is a subsequence of \"abcde\" while \"aec\" is not).\n\nExample 1:\nInput: s = \"abc\", t = \"ahbgdc\"\nOutput: true\n\nExample 2:\nInput: s = \"axc\", t = \"ahbgdc\"\nOutput: false\n\nConstraints:\n0 <= s.length <= 100\n0 <= t.length <= 10^4\ns and t consist only of lowercase English letters.\n\nFollow up: Suppose there are lots of incoming s, say s1, s2, ..., sk where k >= 109,\nand you want to check one by one to see if t has its subsequence. In this scenario, how would you change your code?",
"topic": "TwoPointers",
"pattern": "Two Pointers",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Is Subsequence",
"problem_link": "https://leetcode.com/problems/is-subsequence",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/4_Two_Pointers/9_Is_Subsequence.py",
"approaches": [
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(1)",
"intuition": "We want to check if string s appears inside string t in the same order, but not necessarily contiguously. This is the definition of a subsequence. Use two pointers: - p1 for s - p2 for t Move p2 through t. Whenever s[p1] == t[p2], we advance p1 to look for the next character of s. p2 always moves forward. If by the end p1 has reached len(s), it means we successfully matched every character of s in order within t, so s is a subsequence of t. Otherwise, some character of s could not be matched and the answer is False.",
"code": "class Solution:\n def isSubsequence(self, s: str, t: str) -> bool:\n p1, p2 = 0, 0\n\n while p1 < len(s) and p2 < len(t):\n if t[p2] == s[p1]:\n p1 += 1\n p2 += 1\n\n return p1 == len(s)",
"type": "Optimal"
},
{
"tc": "T.C. - O(t)+ O(|s| \u00d7 log(|t|))*k",
"sc": "S.C - O(t)",
"intuition": "Since t is fixed we can do some pre-computation,\nwe are going to build a hashmap table where key\nis the character in string t and value is the list\nof indices of that character.\nWe are going to keep track of index mapped from\nstring t as we proceed\nFor each character of s we are going to check if it\nis present in the table or not,if present we are\ngoing to check if we are able to find an index\ngreater than last index.",
"code": "import bisect\nfrom collections import defaultdict\n\n\nclass SubsequenceCheckerBinarySearch:\n def __init__(self, t: str):\n self.char_indices = defaultdict(list)\n\n for i, char in enumerate(t):\n self.char_indices[char].append(i)\n\n def isSubsequence(self, s: str) -> bool:\n last_index = -1\n\n for i in range(len(s)):\n chr = s[i]\n if chr not in self.char_indices:\n return False\n\n next_index = bisect.bisect_right(self.char_indices[chr], last_index)\n if next_index == len(self.char_indices[chr]):\n return False\n\n last_index = self.char_indices[chr][next_index]\n\n return True\n\n\nt = \"ahbgdc\"\nchecker = SubsequenceCheckerBinarySearch(t)\n\nprint(checker.isSubsequence(\"abc\")) # True\nprint(checker.isSubsequence(\"axc\")) # False\nprint(checker.isSubsequence(\"\")) # True\nprint(checker.isSubsequence(\"ahbgdc\")) # True",
"type": "Optimal"
}
]
},
{
"id": 10,
"question": "Given a 1-indexed array of integers numbers that is already sorted in non-decreasing order, find two numbers such that they add up to a specific target number. Let these two numbers be numbers[index1] and numbers[index2] where 1 <= index1 < index2 <= numbers.length.\n\nReturn the indices of the two numbers, index1 and index2, added by one as an integer array [index1, index2] of length 2.\n\nThe tests are generated such that there is exactly one solution. You may not use the same element twice.\n\nYour solution must use only constant extra space.\n\nExample 1:\nInput: numbers = [2,7,11,15], target = 9\nOutput: [1,2]\nExplanation: The sum of 2 and 7 is 9. Therefore, index1 = 1, index2 = 2. We return [1, 2].\n\nExample 2:\nInput: numbers = [2,3,4], target = 6\nOutput: [1,3]\nExplanation: The sum of 2 and 4 is 6. Therefore index1 = 1, index2 = 3. We return [1, 3].\n\nExample 3:\nInput: numbers = [-1,0], target = -1\nOutput: [1,2]\nExplanation: The sum of -1 and 0 is -1. Therefore index1 = 1, index2 = 2. We return [1, 2].\n\nConstraints:\n2 <= numbers.length <= 3 * 10^4\n-1000 <= numbers[i] <= 1000\nnumbers is sorted in non-decreasing order.\n-1000 <= target <= 1000\nThe tests are generated such that there is exactly one solution.",
"topic": "TwoPointers",
"pattern": "Two Pointers",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Two Sum II Input Array Is Sorted",
"problem_link": "https://leetcode.com/problems/two-sum-ii-input-array-is-sorted",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/4_Two_Pointers/10_Two_Sum_II_Input_Array_Is_Sorted.py",
"approaches": [
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(1)",
"intuition": "The array is sorted in non-decreasing order, so we can use two pointers\nto efficiently find a pair that sums to the target.\n\nPlace one pointer p1 at the start and another p2 at the end:\n- If numbers[p1] + numbers[p2] is exactly target, we are done.\n- If the sum is greater than target, we need a smaller sum, so we move p2 left\nto reduce the value.\n- If the sum is less than target, we need a larger sum, so we move p1 right\nto increase the value.\n\nBecause the array is sorted, moving pointers this way systematically explores\nall viable pairs without needing extra space or nested loops.",
"code": "from typing import List\n\n\nclass Solution:\n def twoSum(self, numbers: List[int], target: int) -> List[int]:\n p1, p2 = 0, len(numbers) - 1\n\n while p1 < p2:\n if numbers[p1] + numbers[p2] == target:\n return [p1 + 1, p2 + 1]\n if numbers[p1] + numbers[p2] > target:\n p2 -= 1\n if numbers[p1] + numbers[p2] < target:\n p1 += 1",
"type": "Optimal"
}
]
},
{
"id": 11,
"question": "Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such\nthat i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.\nNotice that the solution set must not contain duplicate triplets.\n\n\nExample 1:\nInput: nums = [-1,0,1,2,-1,-4]\nOutput: [[-1,-1,2],[-1,0,1]]\nExplanation:\nnums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0.\nnums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0.\nnums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0.\nThe distinct triplets are [-1,0,1] and [-1,-1,2].\nNotice that the order of the output and the order of the triplets does not matter.\n\nExample 2:\nInput: nums = [0,1,1]\nOutput: []\nExplanation: The only possible triplet does not sum up to 0.\n\nExample 3:\nInput: nums = [0,0,0]\nOutput: [[0,0,0]]\nExplanation: The only possible triplet sums up to 0.\n\nConstraints:\n3 <= nums.length <= 3000\n-10^5 <= nums[i] <= 10^5",
"topic": "TwoPointers",
"pattern": "TwoPointers after Sorting",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "3 Sum",
"problem_link": "https://leetcode.com/problems/3sum",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/4_Two_Pointers/11_3_Sum.py",
"approaches": [
{
"tc": "T.C. - O(n^3)",
"sc": "S.C - O(t)",
"intuition": "We first sort the array. Sorting helps in two ways: it makes the numbers easier to work with, and it ensures that any triplet we pick will be in a fixed, sorted order, which is useful for removing duplicates. After sorting, we use three nested loops to try every possible combination of three different indices i, j, and k (with i < j < k). For each combination, we check whether nums[i] + nums[j] + nums[k] equals zero. If it does, then we have found a valid triplet.",
"code": "from typing import List\n\n\nclass Solution:\n def threeSum(self, nums: List[int]) -> List[List[int]]:\n nums.sort()\n res = set()\n\n for i in range(len(nums)):\n for j in range(i + 1, len(nums)):\n for k in range(j + 1, len(nums)):\n if nums[i] + nums[j] + nums[k] == 0:\n res.add(\n (\n nums[i],\n nums[j],\n nums[k],\n )\n )\n\n return list(res)",
"type": "Brute"
},
{
"tc": "T.C. - O(n^2)",
"sc": "S.C - O(n)",
"intuition": "The key idea is to fix one number and then reduce the problem to a \u201ctwo-sum\u201d style search for the other two numbers. After sorting, pick one number as the first element of the triplet. Now the problem becomes: can we find two other numbers in the remaining part of the array whose sum is equal to the value that balances this first number to reach zero? To do that efficiently, we use a hash-based check: as we scan through the remaining numbers, we keep track of which values we\u2019ve already seen, and for each new value we ask, \u201cIs there another value we saw earlier that would complete the triplet to sum to zero?\u201d Whenever that condition is met, we\u2019ve found a valid triplet. Sorting ensures that each triplet has a consistent order, which makes it easy to avoid counting the same combination more than once.",
"code": "from typing import List\n\n\nclass Solution:\n def threeSum(self, nums: List[int]) -> List[List[int]]:\n nums.sort()\n res = set()\n\n for i in range(len(nums)):\n mp = {}\n for j in range(i + 1, len(nums)):\n complement = 0 - nums[i] - nums[j]\n if complement in mp:\n res.add(\n (\n nums[i],\n nums[j],\n complement,\n )\n )\n mp[nums[j]] = j\n\n return list(res)",
"type": "Better"
},
{
"tc": "T.C. - O(n^2)",
"sc": "S.C - O(1)",
"intuition": "This is a modified version of the Two Sum II pattern extended to three numbers.\n\n1) Sort the array.\nOnce sorted, we can fix one number nums[i] and then search for two numbers\nnums[j] and nums[k] such that nums[i] + nums[j] + nums[k] == 0 using\na standard two-pointer approach on the subarray to the right of i.\n\n2) Two-pointer search for each fixed i.\nFor each index i:\n- Set j = i + 1 (start of the remaining subarray)\n- Set k = len(nums) - 1 (end of the array)\nThen:\n- If the sum is too small, move j right to increase the sum.\n- If the sum is too large, move k left to decrease the sum.\n- If the sum is exactly zero, we record this triplet.\n\n3) Avoiding duplicates for i, j, and k.\nBecause the array can contain duplicates, we must be careful not to produce\nthe same triplet multiple times.",
"code": "from typing import List\n\n\nclass Solution:\n def threeSum(self, nums: List[int]) -> List[List[int]]:\n nums.sort()\n ans = []\n\n for i in range(len(nums)):\n # skip duplicate\n if i > 0 and nums[i] == nums[i - 1]:\n continue\n\n j, k = i + 1, len(nums) - 1\n\n while j < k:\n sm = nums[i] + nums[j] + nums[k]\n\n if sm == 0:\n ans.append([nums[i], nums[j], nums[k]])\n j += 1\n k -= 1\n\n # skip duplicates from left\n while j < k and nums[j] == nums[j - 1]:\n j += 1\n\n # skip duplicates from right\n while j < k and nums[k] == nums[k + 1]:\n k -= 1\n\n elif sm > 0:\n k -= 1\n\n else:\n j += 1\n\n return ans",
"type": "Optimal"
}
]
},
{
"id": 12,
"question": "You are given an integer array height of length n. There are n vertical lines drawn such that the\ntwo endpoints of the ith line are (i, 0) and (i, height[i]).\nFind two lines that together with the x-axis form a container, such that the container contains the most water.\nReturn the maximum amount of water a container can store.\nNotice that you may not slant the container.\n\n\nExample 1:\nInput: height = [1,8,6,2,5,4,8,3,7]\nOutput: 49\nExplanation: The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7].\nIn this case, the max area of water (blue section) the container can contain is 49.\n\nExample 2:\nInput: height = [1,1]\nOutput: 1\n\n\nConstraints:\nn == height.length\n2 <= n <= 10^5\n0 <= height[i] <= 10^4",
"topic": "TwoPointers",
"pattern": "TwoPointers / Greedy",
"language": "python",
"difficulty": "Medium",
"difficulty_num": 2,
"problem_name": "Container With Most Water",
"problem_link": "https://leetcode.com/problems/container-with-most-water",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/4_Two_Pointers/12_Container_With_Most_Water.py",
"approaches": [
{
"tc": "T.C. - O(n^2)",
"sc": "S.C - O(1)",
"intuition": "Find all the possble container's water storing capacity and take the max among them",
"code": "from typing import List\n\n\nclass Solution:\n def maxArea(self, height: List[int]) -> int:\n mx_area = float(\"-inf\")\n for i in range(len(height)):\n for j in range(i + 1, len(height)):\n w = (j - i) + 1\n h = min(height[i], height[j])\n area = w * h\n mx_area = max(mx_area, area)\n\n return mx_area",
"type": "Brute"
},
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(1)",
"intuition": "Our goal is to maximize the area but maximizing width and height\nWe want two lines that form the container with the maximum area.\nThe area is determined by:\narea = (right_index - left_index) * min(height[left], height[right])\n\nWe place two pointers at the extremes: left (l) at 0 and right (r) at n-1,\nto maximize width\nAt each step, we compute the current area and update the maximum.\n\nThe key decision is: which pointer to move?\n- The height of the container is limited by the shorter line.\n- If we move the taller line inward, the width shrinks, but the height\ncannot increase beyond the shorter line we kept, so area cannot improve\nbecause height is still bounded by the same or a smaller value.\n- If instead we move the shorter line inward, there is a chance of\nfinding a taller line that can compensate for the reduced width and\ngive a larger area.",
"code": "from typing import List\n\n\nclass Solution:\n def maxArea(self, height: List[int]) -> int:\n l, r = 0, len(height) - 1\n mx_area = float(\"-inf\")\n\n while l < r:\n w = r - l\n h = min(height[l], height[r])\n mx_area = max(mx_area, w * h)\n\n if height[l] < height[r]:\n l += 1\n else:\n r -= 1\n\n return mx_area",
"type": "Optimal"
}
]
},
{
"id": 1,
"question": "You are given an integer n. You have to print all numbers from 1 to n.\nNote: You must use recursion only, and print all numbers from 1 to n in a single line, separated by spaces.\n\nExamples:\n\nInput: n = 10\nOutput: 1 2 3 4 5 6 7 8 9 10\n\nInput: n = 5\nOutput: 1 2 3 4 5\n\nInput: n = 1\nOutput: 1\n\nConstraints:\n1 \u2264 n \u2264 10^3",
"topic": "Recursion",
"pattern": "IBH",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Print 1 to N",
"problem_link": "https://www.geeksforgeeks.org/problems/print-1-to-n-without-using-loops-1587115620/1",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/6_Recursion/1_Print_1_to_N.py",
"approaches": [
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(n)",
"intuition": "Use the IBH method for recursion\nH -> define printNos will 1 to n for the given n\nB -> if n is less than 1 just return\nI -> make the function print 1 to n-1, we just print n",
"code": "class Solution:\n def printNos(self, n):\n # Base\n if n < 1:\n return\n\n # Hypothesis\n self.printNos(n - 1)\n\n # Induction\n print(n, end=\" \")",
"type": "Optimal"
}
]
},
{
"id": 2,
"question": "Print numbers from N to 1 (space separated) without the help of loops.\n\nExample 1:\n\nInput:\nN = 10\nOutput: 10 9 8 7 6 5 4 3 2 1\nYour Task:\nThis is a function problem. You only need to complete the function printNos() that\ntakes N as parameter and prints number from N to 1 recursively. Don't print newline, it will be added by the driver code.\n\nExpected Time Complexity: O(N).\nExpected Auxiliary Space: O(N) (Recursive).\n\nConstraint\n1<=n<=1000",
"topic": "Recursion",
"pattern": "IBH",
"language": "python",
"difficulty": "Easy",
"difficulty_num": 1,
"problem_name": "Print N to 1",
"problem_link": "https://www.geeksforgeeks.org/problems/print-n-to-1-without-loop/0",
"solution_link": "https://raw.githubusercontent.com/glowfi/DS/main/Programs/python/6_Recursion/2_Print_N_to_1.py",
"approaches": [
{
"tc": "T.C. - O(n)",
"sc": "S.C - O(n)",
"intuition": "Use the IBH method for recursion\nH -> define printNos will n to 1 for the given n\nB -> if n is less than 1 just return\nI -> make the function print n-1 to n, we just print n",
"code": "class Solution:\n def printNos(self, n):\n # Base\n if n < 1:\n return\n\n # Induction\n print(n, end=\" \")\n\n # Hypothesis\n self.printNos(n - 1)",
"type": "Optimal"
}