You are on page 1of 1364

Table of Contents

Table of Contents 2
1. Median of Two Sorted Arrays 17
1. Median of Two Sorted Arrays(C++) 18
1. Median of Two Sorted Arrays(Python) 20
2. Regular Expression Matching 22
2. Regular Expression Matching(Python) 23
3. Merge k Sorted Lists 25
3. Merge k Sorted Lists(C++) 26
3. Merge k Sorted Lists(Python) 28
4. Reverse Nodes in k-Group 30
4. Reverse Nodes in k-Group(C++) 32
4. Reverse Nodes in k-Group(Python) 33
5. Substring with Concatenation of All Words 34
5. Substring with Concatenation of All Words(C++) 35
5. Substring with Concatenation of All Words(Python) 37
6. Longest Valid Parentheses 39
6. Longest Valid Parentheses(C++) 40
6. Longest Valid Parentheses(Python) 41
7. Sudoku Solver 42
7. Sudoku Solver(Python) 43
8. First Missing Positive 44
8. First Missing Positive(C++) 45
8. First Missing Positive(Python) 46
9. Trapping Rain Water 47
9. Trapping Rain Water(C++) 48
9. Trapping Rain Water(Python) 49
10. Wildcard Matching 52
10. Wildcard Matching(Python) 53
11. Jump Game II 55
11. Jump Game II(Python) 56
12. N-Queens 57
12. N-Queens(Python) 58
13. N-Queens-II 59
13. N-Queens-II(Python) 60
14. Merge Intervals 61
14. Merge Intervals(C++) 62
14. Merge Intervals(Python) 63
15. Insert Interval 64
15. Insert Interval(C++) 65
15. Insert Interval(Python) 66
16. Valid Number 67
16. Valid Number(C++) 68
16. Valid Number(Python) 70
17. Text Justification 72
17. Text Justification(C++) 74
17. Text Justification(Python) 75
18. Edit Distance 76
18. Edit Distance(Python) 77
19. Minimum Window Substring 78
19. Minimum Window Substring(C++) 79
19. Minimum Window Substring(Python) 81
20. Largest Rectangle in Histogram 83
20. Largest Rectangle in Histogram(C++) 85
20. Largest Rectangle in Histogram(Python) 86
21. Maximal Rectangle 87
21. Maximal Rectangle(C++) 89
21. Maximal Rectangle(Python) 91
22. Scramble String 93
22. Scramble String(Python) 94
23. Interleaving String 95
23. Interleaving String(Python) 96
24. Recover Binary Search Tree 98
24. Recover Binary Search Tree(C++) 100
24. Recover Binary Search Tree(Python) 101
25. Distinct Subsequences 103
25. Distinct Subsequences(Python) 104
26. Populating Next Right Pointers in Each Node II 105
26. Populating Next Right Pointers in Each Node II(Python) 106
27. Best Time to Buy and Sell Stock III 107
27. Best Time to Buy and Sell Stock III(Python) 108
28. Binary Tree Maximum Path Sum 110
28. Binary Tree Maximum Path Sum(C++) 111
28. Binary Tree Maximum Path Sum(Python) 113
29. Word Ladder II 114
29. Word Ladder II(C++) 115
29. Word Ladder II(Python) 117
30. Longest Consecutive Sequence 119
30. Longest Consecutive Sequence(C++) 120
30. Longest Consecutive Sequence(Python) 121
31. Palindrome Partitioning II 122
31. Palindrome Partitioning II(Python) 123
32. Candy 124
32. Candy(C++) 125
32. Candy(Python) 126
33. Word Break II 127
33. Word Break II(C++) 128
33. Word Break II(Python) 129
34. Binary Tree Postorder Traversal 130
34. Binary Tree Postorder Traversal(C++) 132
34. Binary Tree Postorder Traversal(Python) 134
35. LRU Cache 136
35. LRU Cache(C++) 137
35. LRU Cache(Python) 139
36. Max Points on a Line 141
36. Max Points on a Line(C++) 142
36. Max Points on a Line(Python) 143
37. Find Minimum in Rotated Sorted Array II 144
37. Find Minimum in Rotated Sorted Array II(C++) 145
37. Find Minimum in Rotated Sorted Array II(Python) 146
38. Read N Characters Given Read4 II - Call multiple times 147
38. Read N Characters Given Read4 II - Call multiple times(C++) 149
38. Read N Characters Given Read4 II - Call multiple times(Python) 150
39. Longest Substring with At Most Two Distinct Characters 151
39. Longest Substring with At Most Two Distinct Characters(C++) 152
39. Longest Substring with At Most Two Distinct Characters(Python) 153
40. Maximum Gap 154
40. Maximum Gap(C++) 155
40. Maximum Gap(Python) 157
41. Dungeon Game 159
41. Dungeon Game(Python) 160
42. Department Top Three Salaries 162
42. Department Top Three Salaries(Shell) 164
43. Best Time to Buy and Sell Stock IV 165
43. Best Time to Buy and Sell Stock IV(C++) 166
43. Best Time to Buy and Sell Stock IV(Python) 167
44. Word Search II 169
44. Word Search II(C++) 171
44. Word Search II(Python) 173
45. Shortest Palindrome 174
45. Shortest Palindrome(C++) 175
45. Shortest Palindrome(Python) 178
46. The Skyline Problem 180
46. The Skyline Problem(C++) 182
46. The Skyline Problem(Python) 185
47. Basic Calculator 187
47. Basic Calculator(C++) 188
47. Basic Calculator(Python) 191
48. Number of Digit One 193
48. Number of Digit One(C++) 194
48. Number of Digit One(Python) 195
49. Sliding Window Maximum 196
49. Sliding Window Maximum(C++) 197
49. Sliding Window Maximum(Python) 198
50. Strobogrammatic Number III 199
50. Strobogrammatic Number III(C++) 200
50. Strobogrammatic Number III(Python) 202
51. Trips and Users 204
51. Trips and Users(Shell) 206
52. Paint House II 207
52. Paint House II(C++) 208
52. Paint House II(Python) 209
53. Alien Dictionary 210
53. Alien Dictionary(C++) 211
53. Alien Dictionary(Python) 215
54. Closest Binary Search Tree Value II 217
54. Closest Binary Search Tree Value II(C++) 218
54. Closest Binary Search Tree Value II(Python) 220
55. Integer to English Words 222
55. Integer to English Words(C++) 223
55. Integer to English Words(Python) 225
56. Expression Add Operators 226
56. Expression Add Operators(C++) 227
56. Expression Add Operators(Python) 229
57. Find the Duplicate Number 230
57. Find the Duplicate Number(C++) 231
57. Find the Duplicate Number(Python) 233
58. Word Pattern II 235
58. Word Pattern II(C++) 236
58. Word Pattern II(Python) 237
59. Find Median from Data Stream 238
59. Find Median from Data Stream(C++) 239
59. Find Median from Data Stream(Python) 241
60. Best Meeting Point 242
60. Best Meeting Point(C++) 243
60. Best Meeting Point(Python) 244
61. Serialize and Deserialize Binary Tree 245
61. Serialize and Deserialize Binary Tree(C++) 247
61. Serialize and Deserialize Binary Tree(Python) 249
62. Remove Invalid Parentheses 251
62. Remove Invalid Parentheses(C++) 252
62. Remove Invalid Parentheses(Python) 256
63. Smallest Rectangle Enclosing Black Pixels 258
63. Smallest Rectangle Enclosing Black Pixels(C++) 259
63. Smallest Rectangle Enclosing Black Pixels(Python) 261
64. Number of Islands II 262
64. Number of Islands II(C++) 264
64. Number of Islands II(Python) 266
65. Range Sum Query 2D - Mutable 267
65. Range Sum Query 2D - Mutable(C++) 268
65. Range Sum Query 2D - Mutable(Python) 271
66. Burst Balloons 273
66. Burst Balloons(C++) 274
66. Burst Balloons(Python) 275
67. Count of Smaller Numbers After Self 276
67. Count of Smaller Numbers After Self(C++) 277
67. Count of Smaller Numbers After Self(Python) 280
68. Remove Duplicate Letters 283
68. Remove Duplicate Letters(C++) 284
68. Remove Duplicate Letters(Python) 285
69. Shortest Distance from All Buildings 286
69. Shortest Distance from All Buildings(C++) 288
69. Shortest Distance from All Buildings(Python) 289
70. Create Maximum Number 290
70. Create Maximum Number(C++) 291
70. Create Maximum Number(Python) 293
71. Count of Range Sum 294
71. Count of Range Sum(C++) 295
71. Count of Range Sum(Python) 297
72. Longest Increasing Path in a Matrix 299
72. Longest Increasing Path in a Matrix(C++) 301
72. Longest Increasing Path in a Matrix(Python) 303
73. Patching Array 305
73. Patching Array(C++) 306
73. Patching Array(Python) 307
74. Self Crossing 308
74. Self Crossing(C++) 310
74. Self Crossing(Python) 311
75. Palindrome Pairs 312
75. Palindrome Pairs(C++) 313
75. Palindrome Pairs(Python) 316
76. Longest Substring with At Most K Distinct Characters 318
76. Longest Substring with At Most K Distinct Characters(C++) 319
76. Longest Substring with At Most K Distinct Characters(Python) 320
77. Data Stream as Disjoint Intervals 321
77. Data Stream as Disjoint Intervals(C++) 322
77. Data Stream as Disjoint Intervals(Python) 325
78. Russian Doll Envelopes 326
78. Russian Doll Envelopes(C++) 327
78. Russian Doll Envelopes(Python) 328
79. Rearrange String k Distance Apart 329
79. Rearrange String k Distance Apart(C++) 330
79. Rearrange String k Distance Apart(Python) 332
80. Max Sum of Rectangle No Larger Than K 334
80. Max Sum of Rectangle No Larger Than K(C++) 335
80. Max Sum of Rectangle No Larger Than K(Python) 336
81. Insert Delete GetRandom O(1) 338
81. Insert Delete GetRandom O(1)(C++) 339
81. Insert Delete GetRandom O(1)(Python) 340
82. Insert Delete GetRandom O(1) - Duplicates allowed 341
82. Insert Delete GetRandom O(1) - Duplicates allowed(C++) 342
82. Insert Delete GetRandom O(1) - Duplicates allowed(Python) 343
83. Perfect Rectangle 344
83. Perfect Rectangle(C++) 346
83. Perfect Rectangle(Python) 347
84. Frog Jump 348
84. Frog Jump(C++) 349
84. Frog Jump(Python) 350
85. Trapping Rain Water II 351
85. Trapping Rain Water II(C++) 353
85. Trapping Rain Water II(Python) 355
86. Split Array Largest Sum 356
86. Split Array Largest Sum(C++) 357
86. Split Array Largest Sum(Python) 358
87. Minimum Unique Word Abbreviation 359
87. Minimum Unique Word Abbreviation(C++) 360
87. Minimum Unique Word Abbreviation(Python) 362
88. Strong Password Checker 364
88. Strong Password Checker(C++) 365
88. Strong Password Checker(Python) 366
89. Word Squares 367
89. Word Squares(C++) 368
89. Word Squares(Python) 370
90. All O`one Data Structure 371
90. All O`one Data Structure(C++) 372
90. All O`one Data Structure(Python) 374
91. K-th Smallest in Lexicographical Order 376
91. K-th Smallest in Lexicographical Order(C++) 377
91. K-th Smallest in Lexicographical Order(Python) 379
92. Arithmetic Slices II - Subsequence 381
92. Arithmetic Slices II - Subsequence(C++) 382
92. Arithmetic Slices II - Subsequence(Python) 383
93. LFU Cache 384
93. LFU Cache(C++) 386
93. LFU Cache(Python) 388
94. Optimal Account Balancing 391
94. Optimal Account Balancing(C++) 392
94. Optimal Account Balancing(Python) 393
95. Count The Repetitions 394
95. Count The Repetitions(C++) 395
95. Count The Repetitions(Python) 396
96. Robot Room Cleaner 397
96. Robot Room Cleaner(C++) 399
96. Robot Room Cleaner(Python) 401
97. The Maze III 402
97. The Maze III(C++) 404
97. The Maze III(Python) 406
98. Freedom Trail 407
98. Freedom Trail(C++) 409
98. Freedom Trail(Python) 410
99. Super Washing Machines 411
99. Super Washing Machines(C++) 412
99. Super Washing Machines(Python) 413
100. Word Abbreviation 414
100. Word Abbreviation(C++) 415
100. Word Abbreviation(Python) 416
101. Remove Boxes 417
101. Remove Boxes(C++) 418
101. Remove Boxes(Python) 419
102. Student Attendance Record II 420
102. Student Attendance Record II(C++) 421
102. Student Attendance Record II(Python) 422
103. Find the Closest Palindrome 423
103. Find the Closest Palindrome(C++) 424
103. Find the Closest Palindrome(Python) 425
104. Maximum Vacation Days 426
104. Maximum Vacation Days(C++) 428
104. Maximum Vacation Days(Python) 429
105. Erect the Fence 430
105. Erect the Fence(C++) 432
105. Erect the Fence(Python) 433
106. Design In-Memory File System 434
106. Design In-Memory File System(C++) 436
106. Design In-Memory File System(Python) 438
107. Tag Validator 440
107. Tag Validator(C++) 442
107. Tag Validator(Python) 444
108. Non-negative Integers without Consecutive Ones 445
108. Non-negative Integers without Consecutive Ones(C++) 446
108. Non-negative Integers without Consecutive Ones(Python) 447
109. K Inverse Pairs Array 448
109. K Inverse Pairs Array(C++) 449
109. K Inverse Pairs Array(Python) 450
110. Course Schedule III 451
110. Course Schedule III(C++) 452
110. Course Schedule III(Python) 453
111. Design Excel Sum Formula 454
111. Design Excel Sum Formula(C++) 456
111. Design Excel Sum Formula(Python) 458
112. Smallest Range 460
112. Smallest Range(C++) 461
112. Smallest Range(Python) 462
113. Decode Ways II 463
113. Decode Ways II(C++) 465
113. Decode Ways II(Python) 466
114. Design Search Autocomplete System 467
114. Design Search Autocomplete System(C++) 468
114. Design Search Autocomplete System(Python) 470
115. Maximum Average Subarray II 472
115. Maximum Average Subarray II(C++) 473
115. Maximum Average Subarray II(Python) 475
116. Coin Path 476
116. Coin Path(C++) 477
116. Coin Path(Python) 478
117. Remove 9 479
117. Remove 9(C++) 480
117. Remove 9(Python) 481
118. Strange Printer 482
118. Strange Printer(C++) 483
118. Strange Printer(Python) 484
119. Kth Smallest Number in Multiplication Table 485
119. Kth Smallest Number in Multiplication Table(C++) 486
119. Kth Smallest Number in Multiplication Table(Python) 487
120. Cut Off Trees for Golf Event 488
120. Cut Off Trees for Golf Event(C++) 490
120. Cut Off Trees for Golf Event(Python) 493
121. 24 Game 495
121. 24 Game(C++) 496
121. 24 Game(Python) 499
122. K Empty Slots 501
122. K Empty Slots(C++) 502
122. K Empty Slots(Python) 503
123. Redundant Connection II 504
123. Redundant Connection II(C++) 506
123. Redundant Connection II(Python) 507
124. Maximum Sum of 3 Non-Overlapping Subarrays 508
124. Maximum Sum of 3 Non-Overlapping Subarrays(C++) 509
124. Maximum Sum of 3 Non-Overlapping Subarrays(Python) 510
125. Stickers to Spell Word 511
125. Stickers to Spell Word(C++) 512
125. Stickers to Spell Word(Python) 513
126. Falling Squares 514
126. Falling Squares(C++) 516
126. Falling Squares(Python) 520
127. Number of Distinct Islands II 524
127. Number of Distinct Islands II(C++) 526
127. Number of Distinct Islands II(Python) 528
128. Range Module 529
128. Range Module(C++) 530
128. Range Module(Python) 532
129. Find K-th Smallest Pair Distance 534
129. Find K-th Smallest Pair Distance(C++) 535
129. Find K-th Smallest Pair Distance(Python) 536
130. Number of Atoms 537
130. Number of Atoms(C++) 539
130. Number of Atoms(Python) 540
131. Minimum Window Subsequence 541
131. Minimum Window Subsequence(C++) 542
131. Minimum Window Subsequence(Python) 545
132. Count Different Palindromic Subsequences 546
132. Count Different Palindromic Subsequences(C++) 547
132. Count Different Palindromic Subsequences(Python) 549
133. My Calendar III 550
133. My Calendar III(C++) 551
133. My Calendar III(Python) 552
134. Parse Lisp Expression 554
134. Parse Lisp Expression(C++) 556
134. Parse Lisp Expression(Python) 557
135. Cherry Pickup 558
135. Cherry Pickup(C++) 559
135. Cherry Pickup(Python) 560
136. Prefix and Suffix Search 561
136. Prefix and Suffix Search(C++) 562
136. Prefix and Suffix Search(Python) 565
137. Contain Virus 567
137. Contain Virus(C++) 569
137. Contain Virus(Python) 571
138. Cracking the Safe 572
138. Cracking the Safe(C++) 573
138. Cracking the Safe(Python) 575
139. Set Intersection Size At Least Two 577
139. Set Intersection Size At Least Two(C++) 578
139. Set Intersection Size At Least Two(Python) 579
140. Employee Free Time 580
140. Employee Free Time(C++) 581
140. Employee Free Time(Python) 582
141. Special Binary String 583
141. Special Binary String(C++) 584
141. Special Binary String(Python) 585
142. Couples Holding Hands 586
142. Couples Holding Hands(C++) 587
142. Couples Holding Hands(Python) 588
143. Max Chunks To Make Sorted II 589
143. Max Chunks To Make Sorted II(C++) 590
143. Max Chunks To Make Sorted II(Python) 591
144. Basic Calculator IV 592
144. Basic Calculator IV(C++) 594
144. Basic Calculator IV(Python) 598
145. Basic Calculator III 601
145. Basic Calculator III(C++) 602
145. Basic Calculator III(Python) 604
146. Sliding Puzzle 606
146. Sliding Puzzle(C++) 608
146. Sliding Puzzle(Python) 611
147. Minimize Max Distance to Gas Station 613
147. Minimize Max Distance to Gas Station(C++) 614
147. Minimize Max Distance to Gas Station(Python) 615
148. Swim in Rising Water 616
148. Swim in Rising Water(C++) 618
148. Swim in Rising Water(Python) 619
149. Reaching Points 620
149. Reaching Points(C++) 621
149. Reaching Points(Python) 622
150. Transform to Chessboard 623
150. Transform to Chessboard(C++) 625
150. Transform to Chessboard(Python) 627
151. K-th Smallest Prime Fraction 628
151. K-th Smallest Prime Fraction(C++) 629
151. K-th Smallest Prime Fraction(Python) 630
152. Preimage Size of Factorial Zeroes Function 631
152. Preimage Size of Factorial Zeroes Function(C++) 632
152. Preimage Size of Factorial Zeroes Function(Python) 633
153. Smallest Rotation with Highest Score 634
153. Smallest Rotation with Highest Score(C++) 635
153. Smallest Rotation with Highest Score(Python) 636
154. Bricks Falling When Hit 637
154. Bricks Falling When Hit(C++) 639
154. Bricks Falling When Hit(Python) 641
155. Split Array With Same Average 644
155. Split Array With Same Average(C++) 645
155. Split Array With Same Average(Python) 646
156. Chalkboard XOR Game 647
156. Chalkboard XOR Game(Python) 648
157. Bus Routes 649
157. Bus Routes(C++) 650
157. Bus Routes(Python) 651
158. Race Car 652
158. Race Car(C++) 653
158. Race Car(Python) 654
159. Making A Large Island 655
159. Making A Large Island(C++) 656
159. Making A Large Island(Python) 657
160. Count Unique Characters of All Substrings of a Given String 658
160. Count Unique Characters of All Substrings of a Given String(C++) 659
160. Count Unique Characters of All Substrings of a Given String(Python) 660
161. Sum of Distances in Tree 661
161. Sum of Distances in Tree(C++) 663
161. Sum of Distances in Tree(Python) 664
162. Similar String Groups 665
162. Similar String Groups(C++) 666
162. Similar String Groups(Python) 669
163. Guess the Word 671
163. Guess the Word(C++) 672
163. Guess the Word(Python) 675
164. Shortest Path Visiting All Nodes 677
164. Shortest Path Visiting All Nodes(C++) 678
164. Shortest Path Visiting All Nodes(Python) 679
165. Rectangle Area II 680
165. Rectangle Area II(C++) 681
165. Rectangle Area II(Python) 683
166. K-Similar Strings 685
166. K-Similar Strings(C++) 686
166. K-Similar Strings(Python) 687
167. Minimum Cost to Hire K Workers 688
167. Minimum Cost to Hire K Workers(C++) 689
167. Minimum Cost to Hire K Workers(Python) 690
168. Shortest Subarray with Sum at Least K 691
168. Shortest Subarray with Sum at Least K(C++) 692
168. Shortest Subarray with Sum at Least K(Python) 693
169. Random Pick with Blacklist 694
169. Random Pick with Blacklist(C++) 696
169. Random Pick with Blacklist(Python) 698
170. Shortest Path to Get All Keys 700
170. Shortest Path to Get All Keys(C++) 702
170. Shortest Path to Get All Keys(Python) 704
171. Minimum Number of Refueling Stops 706
171. Minimum Number of Refueling Stops(C++) 707
171. Minimum Number of Refueling Stops(Python) 708
172. Nth Magical Number 709
172. Nth Magical Number(C++) 710
172. Nth Magical Number(Python) 711
173. Profitable Schemes 712
173. Profitable Schemes(C++) 713
173. Profitable Schemes(Python) 714
174. Reachable Nodes In Subdivided Graph 715
174. Reachable Nodes In Subdivided Graph(C++) 717
174. Reachable Nodes In Subdivided Graph(Python) 718
175. Super Egg Drop 719
175. Super Egg Drop(C++) 720
175. Super Egg Drop(Python) 721
176. Sum of Subsequence Widths 722
176. Sum of Subsequence Widths(C++) 723
176. Sum of Subsequence Widths(Python) 724
177. Maximum Frequency Stack 725
177. Maximum Frequency Stack(C++) 726
177. Maximum Frequency Stack(Python) 727
178. Orderly Queue 728
178. Orderly Queue(C++) 729
178. Orderly Queue(Python) 730
179. Numbers At Most N Given Digit Set 731
179. Numbers At Most N Given Digit Set(C++) 732
179. Numbers At Most N Given Digit Set(Python) 733
180. Valid Permutations for DI Sequence 734
180. Valid Permutations for DI Sequence(C++) 735
180. Valid Permutations for DI Sequence(Python) 736
181. Super Palindromes 737
181. Super Palindromes(C++) 738
181. Super Palindromes(Python) 739
182. Cat and Mouse 740
182. Cat and Mouse(C++) 742
182. Cat and Mouse(Python) 745
183. Number of Music Playlists 747
183. Number of Music Playlists(C++) 748
183. Number of Music Playlists(Python) 749
184. Minimize Malware Spread 750
184. Minimize Malware Spread(C++) 751
184. Minimize Malware Spread(Python) 752
185. Three Equal Parts 753
185. Three Equal Parts(C++) 754
185. Three Equal Parts(Python) 755
186. Minimize Malware Spread II 756
186. Minimize Malware Spread II(C++) 757
186. Minimize Malware Spread II(Python) 759
187. Stamping The Sequence 761
187. Stamping The Sequence(C++) 762
187. Stamping The Sequence(Python) 764
188. Distinct Subsequences II 765
188. Distinct Subsequences II(C++) 766
188. Distinct Subsequences II(Python) 767
189. Find the Shortest Superstring 768
189. Find the Shortest Superstring(C++) 769
189. Find the Shortest Superstring(Python) 771
190. Largest Component Size by Common Factor 772
190. Largest Component Size by Common Factor(C++) 774
190. Largest Component Size by Common Factor(Python) 776
191. Tallest Billboard 777
191. Tallest Billboard(C++) 778
191. Tallest Billboard(Python) 779
192. Delete Columns to Make Sorted III 780
192. Delete Columns to Make Sorted III(C++) 781
192. Delete Columns to Make Sorted III(Python) 782
193. Least Operators to Express Number 783
193. Least Operators to Express Number(C++) 784
193. Least Operators to Express Number(Python) 785
194. Binary Tree Cameras 786
194. Binary Tree Cameras(C++) 787
194. Binary Tree Cameras(Python) 788
195. Equal Rational Numbers 789
195. Equal Rational Numbers(C++) 790
195. Equal Rational Numbers(Python) 792
196. Odd Even Jump 793
196. Odd Even Jump(C++) 795
196. Odd Even Jump(Python) 797
197. Unique Paths III 798
197. Unique Paths III(C++) 800
197. Unique Paths III(Python) 802
198. Triples with Bitwise AND Equal To Zero 803
198. Triples with Bitwise AND Equal To Zero(C++) 804
198. Triples with Bitwise AND Equal To Zero(Python) 805
199. Subarrays with K Different Integers 806
199. Subarrays with K Different Integers(C++) 807
199. Subarrays with K Different Integers(Python) 809
200. Minimum Number of K Consecutive Bit Flips 811
200. Minimum Number of K Consecutive Bit Flips(C++) 812
200. Minimum Number of K Consecutive Bit Flips(Python) 813
201. Number of Squareful Arrays 814
201. Number of Squareful Arrays(C++) 815
201. Number of Squareful Arrays(Python) 816
202. Minimum Cost to Merge Stones 817
202. Minimum Cost to Merge Stones(C++) 818
202. Minimum Cost to Merge Stones(Python) 819
203. Grid Illumination 820
203. Grid Illumination(C++) 822
203. Grid Illumination(Python) 824
204. Numbers With Repeated Digits 825
204. Numbers With Repeated Digits(C++) 826
204. Numbers With Repeated Digits(Python) 827
205. Recover a Tree From Preorder Traversal 828
205. Recover a Tree From Preorder Traversal(C++) 830
205. Recover a Tree From Preorder Traversal(Python) 832
206. Stream of Characters 834
206. Stream of Characters(C++) 835
206. Stream of Characters(Python) 837
207. Escape a Large Maze 839
207. Escape a Large Maze(C++) 840
207. Escape a Large Maze(Python) 842
208. Longest Duplicate Substring 843
208. Longest Duplicate Substring(C++) 844
208. Longest Duplicate Substring(Python) 845
209. Number of Valid Subarrays 846
209. Number of Valid Subarrays(C++) 847
209. Number of Valid Subarrays(Python) 848
210. Digit Count in Range 849
210. Digit Count in Range(C++) 850
210. Digit Count in Range(Python) 851
211. Number of Submatrices That Sum to Target 852
211. Number of Submatrices That Sum to Target(C++) 853
211. Number of Submatrices That Sum to Target(Python) 854
212. Confusing Number II 855
212. Confusing Number II(C++) 856
212. Confusing Number II(Python) 859
213. Shortest Common Supersequence 861
213. Shortest Common Supersequence(C++) 862
213. Shortest Common Supersequence(Python) 863
214. Find in Mountain Array 864
214. Find in Mountain Array(C++) 865
214. Find in Mountain Array(Python) 866
215. Brace Expansion II 867
215. Brace Expansion II(C++) 868
215. Brace Expansion II(Python) 869
216. Game Play Analysis V 871
216. Game Play Analysis V(Shell) 872
217. Parsing A Boolean Expression 873
217. Parsing A Boolean Expression(C++) 874
217. Parsing A Boolean Expression(Python) 875
218. Building H2O 876
218. Building H2O(C++) 877
218. Building H2O(Python) 879
219. Divide Array Into Increasing Sequences 881
219. Divide Array Into Increasing Sequences(C++) 882
219. Divide Array Into Increasing Sequences(Python) 883
220. Smallest Sufficient Team 884
220. Smallest Sufficient Team(C++) 885
220. Smallest Sufficient Team(Python) 886
221. User Purchase Platform 887
221. User Purchase Platform(Shell) 888
222. Parallel Courses 889
222. Parallel Courses(C++) 891
222. Parallel Courses(Python) 892
223. Longest Chunked Palindrome Decomposition 893
223. Longest Chunked Palindrome Decomposition(C++) 894
223. Longest Chunked Palindrome Decomposition(Python) 895
224. String Transforms Into Another String 896
224. String Transforms Into Another String(C++) 897
224. String Transforms Into Another String(Python) 898
225. Online Majority Element In Subarray 899
225. Online Majority Element In Subarray(C++) 900
225. Online Majority Element In Subarray(Python) 905
226. Market Analysis II 909
226. Market Analysis II(Shell) 911
227. Last Substring in Lexicographical Order 912
227. Last Substring in Lexicographical Order(C++) 913
227. Last Substring in Lexicographical Order(Python) 915
228. Optimize Water Distribution in a Village 916
228. Optimize Water Distribution in a Village(C++) 917
228. Optimize Water Distribution in a Village(Python) 919
229. Dinner Plate Stacks 920
229. Dinner Plate Stacks(C++) 922
229. Dinner Plate Stacks(Python) 923
230. Number of Valid Words for Each Puzzle 924
230. Number of Valid Words for Each Puzzle(C++) 925
230. Number of Valid Words for Each Puzzle(Python) 927
231. Maximum Number of Ones 929
231. Maximum Number of Ones(C++) 930
231. Maximum Number of Ones(Python) 931
232. Make Array Strictly Increasing 932
232. Make Array Strictly Increasing(C++) 933
232. Make Array Strictly Increasing(Python) 934
233. Critical Connections in a Network 935
233. Critical Connections in a Network(C++) 936
233. Critical Connections in a Network(Python) 937
234. Tournament Winners 938
234. Tournament Winners(Shell) 940
235. Minimum Time to Build Blocks 941
235. Minimum Time to Build Blocks(C++) 942
235. Minimum Time to Build Blocks(Python) 943
236. Sort Items by Groups Respecting Dependencies 944
236. Sort Items by Groups Respecting Dependencies(C++) 945
236. Sort Items by Groups Respecting Dependencies(Python) 947
237. Design Skiplist 949
237. Design Skiplist(C++) 951
237. Design Skiplist(Python) 955
238. Minimum Moves to Reach Target with Rotations 957
238. Minimum Moves to Reach Target with Rotations(C++) 959
238. Minimum Moves to Reach Target with Rotations(Python) 961
239. Valid Palindrome III 962
239. Valid Palindrome III(C++) 963
239. Valid Palindrome III(Python) 964
240. Count Vowels Permutation 965
240. Count Vowels Permutation(C++) 966
240. Count Vowels Permutation(Python) 968
241. Maximum Equal Frequency 969
241. Maximum Equal Frequency(C++) 970
241. Maximum Equal Frequency(Python) 971
242. Report Contiguous Dates 972
242. Report Contiguous Dates(Shell) 974
243. Divide Chocolate 975
243. Divide Chocolate(C++) 976
243. Divide Chocolate(Python) 977
244. Maximum Profit in Job Scheduling 978
244. Maximum Profit in Job Scheduling(C++) 980
244. Maximum Profit in Job Scheduling(Python) 981
245. Tiling a Rectangle with the Fewest Squares 982
245. Tiling a Rectangle with the Fewest Squares(C++) 983
245. Tiling a Rectangle with the Fewest Squares(Python) 985
246. Palindrome Removal 986
246. Palindrome Removal(C++) 987
246. Palindrome Removal(Python) 988
247. Check If It Is a Good Array 989
247. Check If It Is a Good Array(C++) 990
247. Check If It Is a Good Array(Python) 991
248. Maximum Score Words Formed by Letters 992
248. Maximum Score Words Formed by Letters(C++) 993
248. Maximum Score Words Formed by Letters(Python) 994
249. Handshakes That Don't Cross 995
249. Handshakes That Don't Cross(C++) 998
249. Handshakes That Don't Cross(Python) 999
250. Minimum Moves to Move a Box to Their Target Location 1000
250. Minimum Moves to Move a Box to Their Target Location(C++) 1002
250. Minimum Moves to Move a Box to Their Target Location(Python) 1004
251. Number of Ways to Stay in the Same Place After Some Steps 1007
251. Number of Ways to Stay in the Same Place After Some Steps(C++) 1008
251. Number of Ways to Stay in the Same Place After Some Steps(Python) 1009
252. Number of Ships in a Rectangle 1010
252. Number of Ships in a Rectangle(C++) 1011
252. Number of Ships in a Rectangle(Python) 1012
253. Palindrome Partitioning III 1013
253. Palindrome Partitioning III(C++) 1014
253. Palindrome Partitioning III(Python) 1015
254. Minimum Number of Flips to Convert Binary Matrix to Zero Matrix 1016
254. Minimum Number of Flips to Convert Binary Matrix to Zero Matrix(C++) 1017
254. Minimum Number of Flips to Convert Binary Matrix to Zero Matrix(Python) 1018
255. Minimum Falling Path Sum II 1019
255. Minimum Falling Path Sum II(C++) 1020
255. Minimum Falling Path Sum II(Python) 1021
256. Shortest Path in a Grid with Obstacles Elimination 1022
256. Shortest Path in a Grid with Obstacles Elimination(C++) 1023
256. Shortest Path in a Grid with Obstacles Elimination(Python) 1025
257. Maximum Candies You Can Get from Boxes 1026
257. Maximum Candies You Can Get from Boxes(C++) 1028
257. Maximum Candies You Can Get from Boxes(Python) 1029
258. Number of Paths with Max Score 1030
258. Number of Paths with Max Score(C++) 1031
258. Number of Paths with Max Score(Python) 1032
259. Verbal Arithmetic Puzzle 1033
259. Verbal Arithmetic Puzzle(C++) 1034
259. Verbal Arithmetic Puzzle(Python) 1036
260. Minimum Insertion Steps to Make a String Palindrome 1037
260. Minimum Insertion Steps to Make a String Palindrome(C++) 1038
260. Minimum Insertion Steps to Make a String Palindrome(Python) 1039
261. Distinct Echo Substrings 1040
261. Distinct Echo Substrings(C++) 1041
261. Distinct Echo Substrings(Python) 1043
262. Minimum Distance to Type a Word Using Two Fingers 1045
262. Minimum Distance to Type a Word Using Two Fingers(C++) 1047
262. Minimum Distance to Type a Word Using Two Fingers(Python) 1049
263. Minimum Number of Taps to Open to Water a Garden 1050
263. Minimum Number of Taps to Open to Water a Garden(C++) 1052
263. Minimum Number of Taps to Open to Water a Garden(Python) 1053
264. Reverse Subarray To Maximize Array Value 1054
264. Reverse Subarray To Maximize Array Value(C++) 1055
264. Reverse Subarray To Maximize Array Value(Python) 1056
265. Minimum Difficulty of a Job Schedule 1057
265. Minimum Difficulty of a Job Schedule(C++) 1059
265. Minimum Difficulty of a Job Schedule(Python) 1060
266. Jump Game V 1061
266. Jump Game V(C++) 1063
266. Jump Game V(Python) 1067
267. Jump Game IV 1070
267. Jump Game IV(C++) 1071
267. Jump Game IV(Python) 1072
268. Maximum Students Taking Exam 1073
268. Maximum Students Taking Exam(C++) 1075
268. Maximum Students Taking Exam(Python) 1080
269. Construct Target Array With Multiple Sums 1084
269. Construct Target Array With Multiple Sums(C++) 1085
269. Construct Target Array With Multiple Sums(Python) 1086
270. Count All Valid Pickup and Delivery Options 1087
270. Count All Valid Pickup and Delivery Options(C++) 1088
270. Count All Valid Pickup and Delivery Options(Python) 1089
271. Largest Multiple of Three 1090
271. Largest Multiple of Three(C++) 1091
271. Largest Multiple of Three(Python) 1093
272. Minimum Cost to Make at Least One Valid Path in a Grid 1094
272. Minimum Cost to Make at Least One Valid Path in a Grid(C++) 1097
272. Minimum Cost to Make at Least One Valid Path in a Grid(Python) 1099
273. Get the Second Most Recent Activity 1102
273. Get the Second Most Recent Activity(Shell) 1103
274. Maximum Sum BST in Binary Tree 1104
274. Maximum Sum BST in Binary Tree(C++) 1106
274. Maximum Sum BST in Binary Tree(Python) 1108
275. Frog Position After T Seconds 1110
275. Frog Position After T Seconds(C++) 1112
275. Frog Position After T Seconds(Python) 1115
276. Maximum Performance of a Team 1117
276. Maximum Performance of a Team(C++) 1118
276. Maximum Performance of a Team(Python) 1119
277. Total Sales Amount by Year 1120
277. Total Sales Amount by Year(Shell) 1122
278. Pizza With 3n Slices 1124
278. Pizza With 3n Slices(C++) 1126
278. Pizza With 3n Slices(Python) 1128
279. Longest Happy Prefix 1129
279. Longest Happy Prefix(C++) 1130
279. Longest Happy Prefix(Python) 1132
280. Find All Good Strings 1133
280. Find All Good Strings(C++) 1134
280. Find All Good Strings(Python) 1136
281. Reducing Dishes 1137
281. Reducing Dishes(C++) 1138
281. Reducing Dishes(Python) 1139
282. Stone Game III 1140
282. Stone Game III(C++) 1142
282. Stone Game III(Python) 1143
283. Number of Ways to Paint N × 3 Grid 1144
283. Number of Ways to Paint N × 3 Grid(C++) 1146
283. Number of Ways to Paint N × 3 Grid(Python) 1147
284. Find the Quiet Students in All Exams 1148
284. Find the Quiet Students in All Exams(Shell) 1150
285. Restore The Array 1151
285. Restore The Array(C++) 1152
285. Restore The Array(Python) 1153
286. Build Array Where You Can Find The Maximum Exactly K Comparisons 1154
286. Build Array Where You Can Find The Maximum Exactly K Comparisons(C++) 1156
286. Build Array Where You Can Find The Maximum Exactly K Comparisons(Python) 1157
287. Constrained Subset Sum 1158
287. Constrained Subset Sum(C++) 1159
287. Constrained Subset Sum(Python) 1160
288. Number of Ways to Wear Different Hats to Each Other 1161
288. Number of Ways to Wear Different Hats to Each Other(C++) 1162
288. Number of Ways to Wear Different Hats to Each Other(Python) 1163
289. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit 1164
289. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit(C++) 1165
289. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit(Python) 1167
290. Find the Kth Smallest Sum of a Matrix With Sorted Rows 1169
290. Find the Kth Smallest Sum of a Matrix With Sorted Rows(C++) 1170
290. Find the Kth Smallest Sum of a Matrix With Sorted Rows(Python) 1172
291. Number of Ways of Cutting a Pizza 1174
291. Number of Ways of Cutting a Pizza(C++) 1176
291. Number of Ways of Cutting a Pizza(Python) 1177
292. Form Largest Integer With Digits That Add up to Target 1178
292. Form Largest Integer With Digits That Add up to Target(C++) 1180
292. Form Largest Integer With Digits That Add up to Target(Python) 1182
293. Maximum Number of Darts Inside of a Circular Dartboard 1185
293. Maximum Number of Darts Inside of a Circular Dartboard(C++) 1187
293. Maximum Number of Darts Inside of a Circular Dartboard(Python) 1188
294. Max Dot Product of Two Subsequences 1189
294. Max Dot Product of Two Subsequences(C++) 1190
294. Max Dot Product of Two Subsequences(Python) 1191
295. Cherry Pickup II 1192
295. Cherry Pickup II(C++) 1194
295. Cherry Pickup II(Python) 1196
296. Probability of a Two Boxes Having The Same Number of Distinct Balls 1197
296. Probability of a Two Boxes Having The Same Number of Distinct Balls(C++) 1199
296. Probability of a Two Boxes Having The Same Number of Distinct Balls(Python) 1200
297. Paint House III 1201
297. Paint House III(C++) 1203
297. Paint House III(Python) 1205
298. Allocate Mailboxes 1206
298. Allocate Mailboxes(C++) 1208
298. Allocate Mailboxes(Python) 1209
299. Sales by Day of the Week 1210
299. Sales by Day of the Week(Shell) 1212
300. Kth Ancestor of a Tree Node 1213
300. Kth Ancestor of a Tree Node(C++) 1214
300. Kth Ancestor of a Tree Node(Python) 1215
301. Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree 1216
301. Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree(C++) 1218
301. Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree(Python) 1220
302. Parallel Courses II 1221
302. Parallel Courses II(C++) 1223
302. Parallel Courses II(Python) 1226
303. Max Value of Equation 1227
303. Max Value of Equation(C++) 1228
303. Max Value of Equation(Python) 1229
304. Minimum Possible Integer After at Most K Adjacent Swaps On Digits 1230
304. Minimum Possible Integer After at Most K Adjacent Swaps On Digits(C++) 1231
304. Minimum Possible Integer After at Most K Adjacent Swaps On Digits(Python) 1232
305. Stone Game IV 1233
305. Stone Game IV(C++) 1234
305. Stone Game IV(Python) 1235
306. Best Position for a Service Centre 1236
306. Best Position for a Service Centre(C++) 1238
306. Best Position for a Service Centre(Python) 1240
307. Move Sub-Tree of N-Ary Tree 1242
307. Move Sub-Tree of N-Ary Tree(C++) 1245
307. Move Sub-Tree of N-Ary Tree(Python) 1249
308. Find a Value of a Mysterious Function Closest to Target 1252
308. Find a Value of a Mysterious Function Closest to Target(C++) 1254
308. Find a Value of a Mysterious Function Closest to Target(Python) 1256
309. Minimum Number of Increments on Subarrays to Form a Target Array 1258
309. Minimum Number of Increments on Subarrays to Form a Target Array(C++) 1259
309. Minimum Number of Increments on Subarrays to Form a Target Array(Python) 1260
310. String Compression II 1261
310. String Compression II(C++) 1262
310. String Compression II(Python) 1263
311. Get the Maximum Score 1264
311. Get the Maximum Score(C++) 1266
311. Get the Maximum Score(Python) 1267
312. Find Longest Awesome Substring 1268
312. Find Longest Awesome Substring(C++) 1269
312. Find Longest Awesome Substring(Python) 1270
313. Minimum Cost to Cut a Stick 1271
313. Minimum Cost to Cut a Stick(C++) 1273
313. Minimum Cost to Cut a Stick(Python) 1274
314. The Most Similar Path in a Graph 1275
314. The Most Similar Path in a Graph(C++) 1278
314. The Most Similar Path in a Graph(Python) 1279
315. Minimum Number of Days to Eat N Oranges 1280
315. Minimum Number of Days to Eat N Oranges(C++) 1281
315. Minimum Number of Days to Eat N Oranges(Python) 1282
316. Detect Cycles in 2D Grid 1283
316. Detect Cycles in 2D Grid(C++) 1285
316. Detect Cycles in 2D Grid(Python) 1287
317. Stone Game V 1289
317. Stone Game V(C++) 1290
317. Stone Game V(Python) 1292
318. Number of Ways to Reorder Array to Get Same BST 1294
318. Number of Ways to Reorder Array to Get Same BST(C++) 1296
318. Number of Ways to Reorder Array to Get Same BST(Python) 1297
319. Count All Possible Routes 1298
319. Count All Possible Routes(C++) 1300
319. Count All Possible Routes(Python) 1302
320. Remove Max Number of Edges to Keep Graph Fully Traversable 1304
320. Remove Max Number of Edges to Keep Graph Fully Traversable(C++) 1306
320. Remove Max Number of Edges to Keep Graph Fully Traversable(Python) 1308
321. Check If String Is Transformable With Substring Sort Operations 1309
321. Check If String Is Transformable With Substring Sort Operations(C++) 1310
321. Check If String Is Transformable With Substring Sort Operations(Python) 1311
322. Strange Printer II 1312
322. Strange Printer II(C++) 1314
322. Strange Printer II(Python) 1317
323. Minimum Cost to Connect Two Groups of Points 1319
323. Minimum Cost to Connect Two Groups of Points(C++) 1321
323. Minimum Cost to Connect Two Groups of Points(Python) 1322
324. Maximum Number of Achievable Transfer Requests 1323
324. Maximum Number of Achievable Transfer Requests(C++) 1325
324. Maximum Number of Achievable Transfer Requests(Python) 1327
325. Find Servers That Handled Most Number of Requests 1328
325. Find Servers That Handled Most Number of Requests(C++) 1330
325. Find Servers That Handled Most Number of Requests(Python) 1332
326. Maximum Number of Visible Points 1334
326. Maximum Number of Visible Points(C++) 1336
326. Maximum Number of Visible Points(Python) 1337
327. Minimum One Bit Operations to Make Integers Zero 1338
327. Minimum One Bit Operations to Make Integers Zero(C++) 1339
327. Minimum One Bit Operations to Make Integers Zero(Python) 1341
328. Count Subtrees With Max Distance Between Cities 1343
328. Count Subtrees With Max Distance Between Cities(C++) 1345
328. Count Subtrees With Max Distance Between Cities(Python) 1347
329. Fancy Sequence 1349
329. Fancy Sequence(C++) 1350
329. Fancy Sequence(Python) 1353
330. Graph Connectivity With Threshold 1355
330. Graph Connectivity With Threshold(C++) 1357
330. Graph Connectivity With Threshold(Python) 1359
331. Rank Transform of a Matrix 1360
331. Rank Transform of a Matrix(C++) 1362
331. Rank Transform of a Matrix(Python) 1364
***************************

1. Median of Two Sorted Arrays


***************************

Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.

The overall run time complexity should be O(log (m+n)) .

Example 1:

Input: nums1 = [1,3], nums2 = [2]


Output: 2.00000
Explanation: merged array = [1,2,3] and median is 2.

Example 2:

Input: nums1 = [1,2], nums2 = [3,4]


Output: 2.50000
Explanation: merged array = [1,2,3,4] and median is (2 + 3) / 2 = 2.5.

Example 3:

Input: nums1 = [0,0], nums2 = [0,0]


Output: 0.00000

Example 4:

Input: nums1 = [], nums2 = [1]


Output: 1.00000

Example 5:

Input: nums1 = [2], nums2 = []


Output: 2.00000

Constraints:

nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-106 <= nums1[i], nums2[i] <= 10 6
***************************

1. Median of Two Sorted Arrays(C++)


***************************

1 // Time: O(log(min(m, n)))


2 // Space: O(1)
3
4 class Solution {
5 public:
6 double findMedianSortedArrays(vector& nums1, vector& nums2) {
7 if ((nums1.size() + nums2.size()) % 2 == 1) {
8 return findKthInTwoSortedArrays(nums1, nums2, (nums1.size() + nums2.size()) / 2 + 1);
9 } else {
10 return (findKthInTwoSortedArrays(nums1, nums2, (nums1.size() + nums2.size()) / 2) +
11 findKthInTwoSortedArrays(nums1, nums2, (nums1.size() + nums2.size()) / 2 + 1)) / 2.0;
12 }
13 }
14
15 int findKthInTwoSortedArrays(const vector& A, const vector& B,
16 int k) {
17 const int m = A.size();
18 const int n = B.size();
19
20 // Make sure m is the smaller one.
21 if (m > n) {
22 return findKthInTwoSortedArrays(B, A, k);
23 }
24
25 int left = 0;
26 int right = m;
27 // Find a partition of A and B
28 // where min left s.t. A[left] >= B[k - 1 - left]. Thus A[left] is the (k+1)-th or above element.
29 while (left < right) {
30 int mid = left + (right - left) / 2;
31 if (0 <= k - 1 - mid && k - 1 - mid < n && A[mid] >= B[k - 1 - mid]) {
32 right = mid;
33 } else {
34 left = mid + 1;
35 }
36 }
37
38 int Ai_minus_1 = left - 1 >= 0 ? A[left - 1] : numeric_limits::min();
39 int Bj = k - 1 - left >= 0 ? B[k - 1 - left] : numeric_limits::min();
40
41 // kth element would be A[left - 1] or B[k - 1 - left].
42 return max(Ai_minus_1, Bj);
43 }
44 };
45
46 // Time: O(log(max(m, n)) * log(max_val - min_val))
47 // Space: O(1)
48 // Generic solution.
49 class Solution_Generic {
50 public:
51 double findMedianSortedArrays(vector& nums1, vector& nums2) {
52 vector *> arrays{&nums1, &nums2};
53 int total = accumulate(cbegin(arrays), cend(arrays), 0,
54 [](const auto& x, const auto& y) {
55 return x + size(*y);
56 });
57 if (total % 2 == 1) {
58 return findKthInSortedArrays(arrays, total / 2 + 1);
59 } else {
60 return (findKthInSortedArrays(arrays, total / 2) +
61 findKthInSortedArrays(arrays, total / 2 + 1)) / 2.0;
62 }
63 }
64
65 private:
66 int findKthInSortedArrays(const vector *>& arrays, int k) {
67 int left = numeric_limits::max();
68 int right = numeric_limits::min();
69 for (const auto array : arrays) {
70 if (!empty(*array)) {
71 left = min(left, array->front());
72 right = max(right, array->back());
73 }
74 }
75 // left xxxxxxxooooooo right, find first xo or oo
76 while (left <= right) {
77 const auto mid = left + (right - left) / 2;
78 if (check(arrays, mid, k)) {
79 right = mid - 1;
80 } else {
81 left = mid + 1;
82 }
83 }
84 return left;
85 }
86
87 bool check(const vector *>& arrays, int num, int target) {
88 int res = 0;
89 for (const auto array : arrays) {
90 if (!array->empty()) { // count the number of values which are less or equal to num
91 res += distance(array->cbegin(),
92 upper_bound(array->cbegin(), array->cend(), num));
93 }
94 }
95 return res >= target;
96 }
97 };
***************************

1. Median of Two Sorted Arrays(Python)


***************************

1 # Time: O(log(min(m, n)))


2 # Space: O(1)
3
4 class Solution(object):
5 def findMedianSortedArrays(self, nums1, nums2):
6 """
7 :type nums1: List[int]
8 :type nums2: List[int]
9 :rtype: float
10 """
11 len1, len2 = len(nums1), len(nums2)
12 if (len1 + len2) % 2 == 1:
13 return self.getKth(nums1, nums2, (len1 + len2)/2 + 1)
14 else:
15 return (self.getKth(nums1, nums2, (len1 + len2)/2) +
16 self.getKth(nums1, nums2, (len1 + len2)/2 + 1)) * 0.5
17
18 def getKth(self, A, B, k):
19 m, n = len(A), len(B)
20 if m > n:
21 return self.getKth(B, A, k)
22
23 left, right = 0, m
24 while left < right:
25 mid = left + (right - left) / 2
26 if 0 <= k - 1 - mid < n and A[mid] >= B[k - 1 - mid]:
27 right = mid
28 else:
29 left = mid + 1
30
31 Ai_minus_1 = A[left - 1] if left - 1 >= 0 else float("-inf")
32 Bj = B[k - 1 - left] if k - 1 - left >= 0 else float("-inf")
33
34 return max(Ai_minus_1, Bj)
35
36
37 # Time: O(log(max(m, n)) * log(max_val - min_val))
38 # Space: O(1)
39 # Generic solution.
40 class Solution_Generic(object):
41 def findMedianSortedArrays(self, nums1, nums2):
42 """
43 :type nums1: List[int]
44 :type nums2: List[int]
45 :rtype: float
46 """
47 array = [nums1, nums2]
48 total = sum(len(nums) for nums in array)
49 if total % 2 == 1:
50 return self.getKth(array, total//2 + 1)
51 else:
52 return (self.getKth(array, total//2) +
53 self.getKth(array, total//2 + 1)) * 0.5
54
55 def getKth(self, arrays, k):
56 def binary_search(array, left, right, target, check):
57 while left <= right:
58 mid = left + (right-left)//2
59 if check(array, mid, target):
60 right = mid-1
61 else:
62 left = mid+1
63 return left
64
65 def check(arrays, num, target):
66 res = 0
67 for array in arrays:
68 if array: # count the number of values which are less or equal to num
69 res += binary_search(array, 0, len(array) - 1, num,
70 lambda array, x, y: array[x] > y)
71 return res >= target
72
73 left, right = float("inf"), float("-inf")
74 for array in arrays:
75 if array:
76 left = min(left, array[0])
77 right = max(right, array[-1])
78 return binary_search(arrays, left, right, k, check)
79
80 class Solution_3(object):
81 def findMedianSortedArrays(self, A, B):
82
83 if A is None and B is None:
84 return -1.0
85 lenA = len(A)
86 lenB = len(B)
87 lenn = lenA + lenB
88
89 indexA,indexB,indexC = 0,0,0
90 C = [False for i in xrange(lenn)]
91 while indexA < lenA and indexB < lenB:
92 if A[indexA] < B[indexB]:
93 C[indexC] = A[indexA]
94 indexC += 1
95 indexA += 1
96 else:
97 C[indexC] = B[indexB]
98 indexC += 1
99 indexB += 1
100
101 while indexA < lenA:
102 C[indexC] = A[indexA]
103 indexC += 1
104 indexA += 1
105
106 while indexB < lenB:
107 C[indexC] = B[indexB]
108 indexC += 1
109 indexB += 1
110
111 indexM1 = (lenn - 1) / 2
112 indexM2 = lenn / 2
113
114 if (lenn % 2 == 0):
115 return (C[indexM1] + C[indexM2]) / 2.0
116 else:
117 return C[indexM2] / 1.0
118
***************************

2. Regular Expression Matching


***************************

Given an input string s and a pattern p, implement regular expression matching with support for '.' and '*' where:

'.' Matches any single character.​​​​


'*' Matches zero or more of the preceding element.

The matching should cover the entire input string (not partial).

Example 1:

Input: s = "aa", p = "a"


Output: false
Explanation: "a" does not match the entire string "aa".

Example 2:

Input: s = "aa", p = "a*"


Output: true
Explanation: '*' means zero or more of the preceding element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".

Example 3:

Input: s = "ab", p = ".*"


Output: true
Explanation: ".*" means "zero or more (*) of any character (.)".

Example 4:

Input: s = "aab", p = "c*a*b"


Output: true
Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore, it matches "aab".

Example 5:

Input: s = "mississippi", p = "mis*is*p*."


Output: false

Constraints:

1 <= s.length <= 20


1 <= p.length <= 30
s contains only lowercase English letters.
p contains only lowercase English letters, '.', and '*'.
It is guaranteed for each appearance of the character '*', there will be a previous valid character to match.
***************************

2. Regular Expression Matching(Python)


***************************

1 # Time: O(m * n)
2 # Space: O(n)
3
4 class Solution(object):
5 # @return a boolean
6 def isMatch(self, s, p):
7 k = 3
8 result = [[False for j in xrange(len(p) + 1)] for i in xrange(k)]
9
10 result[0][0] = True
11 for i in xrange(2, len(p) + 1):
12 if p[i-1] == '*':
13 result[0][i] = result[0][i-2]
14
15 for i in xrange(1,len(s) + 1):
16 if i > 1:
17 result[0][0] = False
18 for j in xrange(1, len(p) + 1):
19 if p[j-1] != '*':
20 result[i % k][j] = result[(i-1) % k][j-1] and (s[i-1] == p[j-1] or p[j-1] == '.')
21 else:
22 result[i % k][j] = result[i % k][j-2] or (result[(i-1) % k][j] and (s[i-1] == p[j-2] or p[j-2] == '.'))
23
24 return result[len(s) % k][len(p)]
25
26 # dp
27 # Time: O(m * n)
28 # Space: O(m * n)
29 class Solution2(object):
30 # @return a boolean
31 def isMatch(self, s, p):
32 result = [[False for j in xrange(len(p) + 1)] for i in xrange(len(s) + 1)]
33
34 result[0][0] = True
35 for i in xrange(2, len(p) + 1):
36 if p[i-1] == '*':
37 result[0][i] = result[0][i-2]
38
39 for i in xrange(1,len(s) + 1):
40 for j in xrange(1, len(p) + 1):
41 if p[j-1] != '*':
42 result[i][j] = result[i-1][j-1] and (s[i-1] == p[j-1] or p[j-1] == '.')
43 else:
44 result[i][j] = result[i][j-2] or (result[i-1][j] and (s[i-1] == p[j-2] or p[j-2] == '.'))
45
46 return result[len(s)][len(p)]
47
48 # iteration
49 class Solution3(object):
50 # @return a boolean
51 def isMatch(self, s, p):
52 p_ptr, s_ptr, last_s_ptr, last_p_ptr = 0, 0, -1, -1
53 last_ptr = []
54 while s_ptr < len(s):
55 if p_ptr < len(p) and (p_ptr == len(p) - 1 or p[p_ptr + 1] != '*') and \
56 (s_ptr < len(s) and (p[p_ptr] == s[s_ptr] or p[p_ptr] == '.')):
57 s_ptr += 1
58 p_ptr += 1
59 elif p_ptr < len(p) - 1 and (p_ptr != len(p) - 1 and p[p_ptr + 1] == '*'):
60 p_ptr += 2
61 last_ptr.append([s_ptr, p_ptr])
62 elif last_ptr:
63 [last_s_ptr, last_p_ptr] = last_ptr.pop()
64 while last_ptr and p[last_p_ptr - 2] != s[last_s_ptr] and p[last_p_ptr - 2] != '.':
65 [last_s_ptr, last_p_ptr] = last_ptr.pop()
66
67 if p[last_p_ptr - 2] == s[last_s_ptr] or p[last_p_ptr - 2] == '.':
68 last_s_ptr += 1
69 s_ptr = last_s_ptr
70 p_ptr = last_p_ptr
71 last_ptr.append([s_ptr, p_ptr])
72 else:
73 return False
74 else:
75 return False
76
77 while p_ptr < len(p) - 1 and p[p_ptr] == '.' and p[p_ptr + 1] == '*':
78 p_ptr += 2
79
80 return p_ptr == len(p)
81
82 # recursive
83 class Solution4(object):
84 # @return a boolean
85 def isMatch(self, s, p):
86 if not p:
87 return not s
88
89 if len(p) == 1 or p[1] != '*':
90 if len(s) > 0 and (p[0] == s[0] or p[0] == '.'):
91 return self.isMatch(s[1:], p[1:])
92 else:
93 return False
94 else:
95 while len(s) > 0 and (p[0] == s[0] or p[0] == '.'):
96 if self.isMatch(s, p[2:]):
97 return True
98 s = s[1:]
99 return self.isMatch(s, p[2:])
100
********************

3. Merge k Sorted Lists


********************

You are given an array of k linked-lists lists, each linked-list is sorted in ascending order.

Merge all the linked-lists into one sorted linked-list and return it.

Example 1:

Input: lists = [[1,4,5],[1,3,4],[2,6]]


Output: [1,1,2,3,4,4,5,6]
Explanation: The linked-lists are:
[
1->4->5,
1->3->4,
2->6
]
merging them into one sorted list:
1->1->2->3->4->4->5->6

Example 2:

Input: lists = []
Output: []

Example 3:

Input: lists = [[]]


Output: []

Constraints:

k == lists.length
0 <= k <= 10^4
0 <= lists[i].length <= 500
-10^4 <= lists[i][j] <= 10^4
lists[i] is sorted in ascending order.
The sum of lists[i].length won't exceed 10^4.
********************

3. Merge k Sorted Lists(C++)


********************

1 // Time: O(n * logk), n is the length of the result list.


2 // Space: O(1)
3
4 /**
5 * Definition for singly-linked list.
6 * struct ListNode {
7 * int val;
8 * ListNode *next;
9 * ListNode(int x) : val(x), next(NULL) {}
10 * };
11 */
12
13 // Merge two by two solution.
14 class Solution {
15 public:
16 ListNode *mergeKLists(vector &lists) {
17 if (lists.empty()) {
18 return nullptr;
19 }
20
21 int left = 0, right = lists.size() - 1;
22 while (right > 0) {
23 lists[left] = mergeTwoLists(lists[left], lists[right]);
24 ++left;
25 --right;
26 if (left >= right) {
27 left = 0;
28 }
29 }
30 return lists[0];
31 }
32
33 private:
34 ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
35 ListNode dummy{0};
36 auto curr = &dummy;
37
38 while (l1 && l2) {
39 if (l1->val <= l2->val) {
40 curr->next = l1;
41 l1 = l1->next;
42 } else {
43 curr->next = l2;
44 l2 = l2->next;
45 }
46 curr = curr->next;
47 }
48 curr->next = l1 ? l1 : l2;
49
50 return dummy.next;
51 }
52 };
53
54
55 // Time: O(n * logk)
56 // Space: O(logk)
57 // Divide and Conquer solution.
58 class Solution2 {
59 public:
60 ListNode *mergeKLists(vector &lists) {
61 return mergeKListsHelper(lists, 0, lists.size() - 1);
62 }
63
64 private:
65 ListNode *mergeKListsHelper(const vector &lists, int begin, int end) {
66 if (begin > end) {
67 return nullptr;
68 }
69 if (begin == end) {
70 return lists[begin];
71 }
72 return mergeTwoLists(mergeKListsHelper(lists, begin, (begin + end) / 2),
73 mergeKListsHelper(lists, (begin + end) / 2 + 1, end));
74 }
75
76 ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
77 ListNode dummy{0};
78 auto curr = &dummy;
79
80 while (l1 && l2) {
81 if (l1->val <= l2->val) {
82 curr->next = l1;
83 l1 = l1->next;
84 } else {
85 curr->next = l2;
86 l2 = l2->next;
87 }
88 curr = curr->next;
89 }
90 curr->next = l1 ? l1 : l2;
91
92 return dummy.next;
93 }
94 };
95
96
97 // Time: O(n * logk)
98 // Space: O(k)
99 // Heap solution.
100 class Solution3 {
101 public:
102 ListNode* mergeKLists(vector& lists) {
103 ListNode dummy(0);
104 auto *cur = &dummy;
105
106 struct Compare {
107 bool operator() (const ListNode *a, const ListNode *b) {
108 return a->val > b->val;
109 }
110 };
111
112 // Use min heap to keep the smallest node of each list
113 priority_queue, Compare> min_heap;
114 for (const auto& n : lists) {
115 if (n) {
116 min_heap.emplace(n);
117 }
118 }
119
120 while (!min_heap.empty()) {
121 // Get min of k lists.
122 auto *node = min_heap.top();
123 min_heap.pop();
124 cur->next = node;
125 cur = cur->next;
126 if (node->next) {
127 min_heap.emplace(node->next);
128 }
129 }
130
131 return dummy.next;
132 }
133 };
********************

3. Merge k Sorted Lists(Python)


********************

1 # Time: O(nlogk)
2 # Space: O(1)
3
4 class ListNode(object):
5 def __init__(self, x):
6 self.val = x
7 self.next = None
8
9 def __repr__(self):
10 if self:
11 return "{} -> {}".format(self.val, self.next)
12
13
14 # Merge two by two solution.
15 class Solution(object):
16 def mergeKLists(self, lists):
17 """
18 :type lists: List[ListNode]
19 :rtype: ListNode
20 """
21 def mergeTwoLists(l1, l2):
22 curr = dummy = ListNode(0)
23 while l1 and l2:
24 if l1.val < l2.val:
25 curr.next = l1
26 l1 = l1.next
27 else:
28 curr.next = l2
29 l2 = l2.next
30 curr = curr.next
31 curr.next = l1 or l2
32 return dummy.next
33
34 if not lists:
35 return None
36 left, right = 0, len(lists) - 1
37 while right > 0:
38 lists[left] = mergeTwoLists(lists[left], lists[right])
39 left += 1
40 right -= 1
41 if left >= right:
42 left = 0
43 return lists[0]
44
45
46 # Time: O(nlogk)
47 # Space: O(logk)
48 # Divide and Conquer solution.
49 class Solution2(object):
50 # @param a list of ListNode
51 # @return a ListNode
52 def mergeKLists(self, lists):
53 def mergeTwoLists(l1, l2):
54 curr = dummy = ListNode(0)
55 while l1 and l2:
56 if l1.val < l2.val:
57 curr.next = l1
58 l1 = l1.next
59 else:
60 curr.next = l2
61 l2 = l2.next
62 curr = curr.next
63 curr.next = l1 or l2
64 return dummy.next
65
66 def mergeKListsHelper(lists, begin, end):
67 if begin > end:
68 return None
69 if begin == end:
70 return lists[begin]
71 return mergeTwoLists(mergeKListsHelper(lists, begin, (begin + end) / 2), \
72 mergeKListsHelper(lists, (begin + end) / 2 + 1, end))
73
74 return mergeKListsHelper(lists, 0, len(lists) - 1)
75
76
77 # Time: O(nlogk)
78 # Space: O(k)
79 # Heap solution.
80 import heapq
81 class Solution3(object):
82 # @param a list of ListNode
83 # @return a ListNode
84 def mergeKLists(self, lists):
85 dummy = ListNode(0)
86 current = dummy
87
88 heap = []
89 for sorted_list in lists:
90 if sorted_list:
91 heapq.heappush(heap, (sorted_list.val, sorted_list))
92
93 while heap:
94 smallest = heapq.heappop(heap)[1]
95 current.next = smallest
96 current = current.next
97 if smallest.next:
98 heapq.heappush(heap, (smallest.next.val, smallest.next))
99
100 return dummy.next
101
102
************************

4. Reverse Nodes in k-Group


************************

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple ofk
then left-out nodes, in the end, should remain as it is.

You may not alter the values in the list's nodes, only nodes themselves may be changed.

Example 1:

Input: head = [1,2,3,4,5], k = 2


Output: [2,1,4,3,5]

Example 2:

Input: head = [1,2,3,4,5], k = 3


Output: [3,2,1,4,5]

Example 3:

Input: head = [1,2,3,4,5], k = 1


Output: [1,2,3,4,5]

Example 4:
Input: head = [1], k = 1
Output: [1]

Constraints:

The number of nodes in the list is in the rangesz.


1 <= sz <= 5000
0 <= Node.val <= 1000
1 <= k <= sz

Follow-up: Can you solve the problem in O(1) extra memory space?
************************

4. Reverse Nodes in k-Group(C++)


************************

1 // Time: O(n)
2 // Space: O(1)
3
4 /**
5 * Definition for singly-linked list.
6 * struct ListNode {
7 * int val;
8 * ListNode *next;
9 * ListNode(int x) : val(x), next(NULL) {}
10 * };
11 */
12 class Solution {
13 public:
14 ListNode* reverseKGroup(ListNode* head, int k) {
15 ListNode dummy{0};
16 dummy.next = head;
17 auto curr = head, curr_dummy = &dummy;
18 int len = 0;
19
20 while (curr) {
21 auto next_curr = curr->next;
22 len = (len + 1) % k;
23
24 if (len == 0) {
25 auto next_dummy = curr_dummy->next;
26 reverse(&curr_dummy, curr->next);
27 curr_dummy = next_dummy;
28 }
29 curr = next_curr;
30 }
31 return dummy.next;
32 }
33
34 void reverse(ListNode **begin, const ListNode *end) {
35 ListNode *first = (*begin)->next;
36 ListNode *curr = first->next;
37
38 while (curr != end) {
39 first->next = curr->next;
40 curr->next = (*begin)->next;
41 (*begin)->next = curr;
42 curr = first->next;
43 }
44 }
45 };
************************

4. Reverse Nodes in k-Group(Python)


************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class ListNode(object):
5 def __init__(self, x):
6 self.val = x
7 self.next = None
8
9 def __repr__(self):
10 if self:
11 return "{} -> {}".format(self.val, repr(self.next))
12
13 class Solution(object):
14 # @param head, a ListNode
15 # @param k, an integer
16 # @return a ListNode
17 def reverseKGroup(self, head, k):
18 dummy = ListNode(-1)
19 dummy.next = head
20
21 cur, cur_dummy = head, dummy
22 length = 0
23
24 while cur:
25 next_cur = cur.next
26 length = (length + 1) % k
27
28 if length == 0:
29 next_dummy = cur_dummy.next
30 self.reverse(cur_dummy, cur.next)
31 cur_dummy = next_dummy
32
33 cur = next_cur
34
35 return dummy.next
36
37 def reverse(self, begin, end):
38 first = begin.next
39 cur = first.next
40
41 while cur != end:
42 first.next = cur.next
43 cur.next = begin.next
44 begin.next = cur
45 cur = first.next
46
*****************************************

5. Substring with Concatenation of All Words


*****************************************

You are given a string s and an array of strings words of the same length. Return all starting indices of substring(s) ins that
is a concatenation of each word in words exactly once, in any order, and without any intervening characters.

You can return the answer in any order.

Example 1:

Input: s = "barfoothefoobarman", words = ["foo","bar"]


Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are "barfoo" and "foobar" respectively.
The output order does not matter, returning [9,0] is fine too.

Example 2:

Input: s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]


Output: []

Example 3:

Input: s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]


Output: [6,9,12]

Constraints:

1 <= s.length <= 104


s consists of lower-case English letters.
1 <= words.length <= 5000
1 <= words[i].length <= 30
words[i] consists of lower-case English letters.
*****************************************

5. Substring with Concatenation of All Words(C++)


*****************************************

1 // Time: O((m + n) * k), m is the length of the string,


2 // n is the size of the dictionary,
3 // k is the length of each word
4 // Space: O(n * k)
5
6 // Sliding window solution.
7 class Solution {
8 public:
9 vector findSubstring(string s, vector& words) {
10 if (words.empty()) {
11 return {};
12 }
13
14 vector result;
15 const int m = s.length(), n = words.size(), k = words.front().length();
16 if (m < n * k) {
17 return result;
18 }
19
20 unordered_map lookup;
21 for (const auto& word : words) {
22 ++lookup[word]; // Space: O(n * k)
23 }
24 for (int i = 0; i < k; ++i) { // Time: O(k)
25 unordered_map tmp;
26 for (int j = i, left = i, count = 0; j <= m - k; j += k) { // Time: O(m / k)
27 const auto& str = s.substr(j, k); // Time: O(k)
28 if (lookup.count(str)) {
29 ++tmp[str];
30 ++count;
31 while (tmp[str] > lookup[str]) {
32 --tmp[s.substr(left, k)];
33 --count;
34 left += k;
35 }
36 if (count == n) {
37 result.emplace_back(left);
38 }
39 } else {
40 tmp.clear();
41 count = 0;
42 left = j + k;
43 }
44 }
45 }
46 return result;
47 }
48 };
49
50
51 // Time: O((m - n * k) * n * k) ~ O(m * n * k), m is the length of the string,
52 // n is the size of the dictionary,
53 // k is the length of each word
54 // Space: O(n * k)
55 class Solution2 {
56 public:
57 vector findSubstring(string s, vector& words) {
58 const auto word_length = words.front().length();
59 const auto cat_length = word_length * words.size();
60 vector result;
61
62 if (s.length() < cat_length) {
63 return result;
64 }
65
66 unordered_map wordCount;
67 for (const auto & word : words) {
68 ++wordCount[word];
69 }
70
71 for (auto it = s.begin(); it != prev(s.end(), cat_length - 1); ++it) {
72 unordered_map unused(wordCount);
73 for (auto jt = it; jt != next(it, cat_length); jt += word_length) {
74 auto pos = unused.find(string(jt, next(jt, word_length)));
75 if (pos == unused.end()) {
76 break;
77 }
78 if (--pos->second == 0) {
79 unused.erase(pos);
80 }
81 }
82 if (unused.empty()) {
83 result.emplace_back(distance(s.begin(), it));
84 }
85 }
86 return result;
87 }
88 };
*****************************************

5. Substring with Concatenation of All Words(Python)


*****************************************

1 # Time: O((m + n) * k), where m is string length, n is dictionary size, k is word length
2 # Space: O(n * k)
3
4 import collections
5
6
7 class Solution(object):
8 def findSubstring(self, s, words):
9 """
10 :type s: str
11 :type words: List[str]
12 :rtype: List[int]
13 """
14 if not words:
15 return []
16
17 result, m, n, k = [], len(s), len(words), len(words[0])
18 if m < n*k:
19 return result
20
21 lookup = collections.defaultdict(int)
22 for i in words:
23 lookup[i] += 1 # Space: O(n * k)
24
25 for i in xrange(k): # Time: O(k)
26 left, count = i, 0
27 tmp = collections.defaultdict(int)
28 for j in xrange(i, m-k+1, k): # Time: O(m / k)
29 s1 = s[j:j+k] # Time: O(k)
30 if s1 in lookup:
31 tmp[s1] += 1
32 count += 1
33 while tmp[s1] > lookup[s1]:
34 tmp[s[left:left+k]] -= 1
35 count -= 1
36 left += k
37 if count == n:
38 result.append(left)
39 else:
40 tmp = collections.defaultdict(int)
41 count = 0
42 left = j+k
43 return result
44
45
46 # Time: O(m * n * k), where m is string length, n is dictionary size, k is word length
47 # Space: O(n * k)
48 class Solution2(object):
49 def findSubstring(self, s, words):
50 """
51 :type s: str
52 :type words: List[str]
53 :rtype: List[int]
54 """
55 result, m, n, k = [], len(s), len(words), len(words[0])
56 if m < n*k:
57 return result
58
59 lookup = collections.defaultdict(int)
60 for i in words:
61 lookup[i] += 1 # Space: O(n * k)
62
63 for i in xrange(m+1-k*n): # Time: O(m)
64 cur, j = collections.defaultdict(int), 0
65 while j < n: # Time: O(n)
66 word = s[i+j*k:i+j*k+k] # Time: O(k)
67 if word not in lookup:
68 break
69 cur[word] += 1
70 if cur[word] > lookup[word]:
71 break
72 j += 1
73 if j == n:
74 result.append(i)
75
76 return result
77
78
*************************

6. Longest Valid Parentheses


*************************

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.

Example 1:

Input: s = "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()".

Example 2:

Input: s = ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()".

Example 3:

Input: s = ""
Output: 0

Constraints:

0 <= s.length <= 3 * 10 4


s[i] is '(', or ')'.
*************************

6. Longest Valid Parentheses(C++)


*************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int longestValidParentheses(string s) {
7 return max(length(s.begin(), s.end(), '('), length(s.rbegin(), s.rend(), ')'));
8 }
9
10 private:
11 template
12 int length(T begin, T end, char c) {
13 int len = 0, depth = 0;
14 T start = begin;
15 for (T it = begin; it != end; ++it) {
16 if (*it == c) {
17 ++depth;
18 } else {
19 --depth;
20 if (depth < 0) {
21 start = next(it);
22 depth = 0;
23 } else {
24 if (depth == 0) {
25 len = max(len, static_cast(distance(start, it)) + 1);
26 }
27 }
28 }
29 }
30 return len;
31 }
32 };
*************************

6. Longest Valid Parentheses(Python)


*************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def longestValidParentheses(self, s):
6 """
7 :type s: str
8 :rtype: int
9 """
10 def length(it, start, c):
11 depth, longest = 0, 0
12 for i in it:
13 if s[i] == c:
14 depth += 1
15 else:
16 depth -= 1
17 if depth < 0:
18 start, depth = i, 0
19 elif depth == 0:
20 longest = max(longest, abs(i - start))
21 return longest
22
23 return max(length(xrange(len(s)), -1, '('), \
24 length(reversed(xrange(len(s))), len(s), ')'))
25
26
27 # Time: O(n)
28 # Space: O(n)
29 class Solution2(object):
30 # @param s, a string
31 # @return an integer
32 def longestValidParentheses(self, s):
33 longest, last, indices = 0, -1, []
34 for i in xrange(len(s)):
35 if s[i] == '(':
36 indices.append(i)
37 elif not indices:
38 last = i
39 else:
40 indices.pop()
41 if not indices:
42 longest = max(longest, i - last)
43 else:
44 longest = max(longest, i - indices[-1])
45 return longest
46
*************

7. Sudoku Solver
*************

Write a program to solve a Sudoku puzzle by filling the empty cells.

A sudoku solution must satisfy all of the following rules:

1. Each of the digits 1-9 must occur exactly once in each row.
2. Each of the digits 1-9 must occur exactly once in each column.
3. Each of the digits 1-9 must occur exactly once in each of the 93x3 sub-boxes of the grid.

The '.' character indicates empty cells.

Example 1:

Input: board = [["5","3",".",".","7",".",".",".","."],["6",".",".","1","9","5",".",".","."],[".","9","8",".",".",".",".","6","."],["8",".",".


Output: [["5","3","4","6","7","8","9","1","2"],["6","7","2","1","9","5","3","4","8"],["1","9","8","3","4","2","5","6","7"],["8","5","9","7","
Explanation: The input board is shown above and the only valid solution is shown below:

Constraints:

board.length == 9
board[i].length == 9
board[i][j] is a digit
or '.'.
It is guaranteed that the input board has only one solution.
*************

7. Sudoku Solver(Python)
*************

1 # Time: ((9!)^9)
2 # Space: (1)
3
4 class Solution(object):
5 # @param board, a 9x9 2D array
6 # Solve the Sudoku by modifying the input board in-place.
7 # Do not return any value.
8 def solveSudoku(self, board):
9 def isValid(board, x, y):
10 for i in xrange(9):
11 if i != x and board[i][y] == board[x][y]:
12 return False
13 for j in xrange(9):
14 if j != y and board[x][j] == board[x][y]:
15 return False
16 i = 3 * (x / 3)
17 while i < 3 * (x / 3 + 1):
18 j = 3 * (y / 3)
19 while j < 3 * (y / 3 + 1):
20 if (i != x or j != y) and board[i][j] == board[x][y]:
21 return False
22 j += 1
23 i += 1
24 return True
25
26 def solver(board):
27 for i in xrange(len(board)):
28 for j in xrange(len(board[0])):
29 if(board[i][j] == '.'):
30 for k in xrange(9):
31 board[i][j] = chr(ord('1') + k)
32 if isValid(board, i, j) and solver(board):
33 return True
34 board[i][j] = '.'
35 return False
36 return True
37
38 solver(board)
39
**********************

8. First Missing Positive


**********************

Given an unsorted integer array nums, return the smallest missing positive integer.

You must implement an algorithm that runs in O(n) time and uses constant extra space.

Example 1:

Input: nums = [1,2,0]


Output: 3

Example 2:

Input: nums = [3,4,-1,1]


Output: 2

Example 3:

Input: nums = [7,8,9,11,12]


Output: 1

Constraints:

1 <= nums.length <= 5 * 10 5


-231 <= nums[i] <= 2 31 - 1
**********************

8. First Missing Positive(C++)


**********************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int firstMissingPositive(vector& nums) {
7 int i = 0;
8 bucketSort(&nums);
9 for (; i < nums.size() && nums[i] == i + 1; ++i);
10 return i + 1;
11 }
12
13 private:
14 void bucketSort(vector *nums) {
15 int i = 0;
16 while (i < nums->size()) {
17 if ((*nums)[i] > 0 && (*nums)[i] <= nums->size() &&
18 (*nums)[i] != (*nums)[(*nums)[i] - 1]) {
19 swap((*nums)[i], (*nums)[(*nums)[i] - 1]);
20 } else {
21 ++i;
22 }
23 }
24 }
25 };
**********************

8. First Missing Positive(Python)


**********************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 # @param A, a list of integers
6 # @return an integer
7 def firstMissingPositive(self, A):
8 i = 0
9 while i < len(A):
10 if A[i] > 0 and A[i] - 1 < len(A) and A[i] != A[A[i]-1]:
11 A[A[i]-1], A[i] = A[i], A[A[i]-1]
12 else:
13 i += 1
14
15 for i, integer in enumerate(A):
16 if integer != i + 1:
17 return i + 1
18 return len(A) + 1
19
*******************

9. Trapping Rain Water


*******************

Given n non-negative integers representing an elevation map where the width of each bar is1, compute how much water it
can trap after raining.

Example 1:

Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]


Output: 6
Explanation: The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (

Example 2:

Input: height = [4,2,0,3,2,5]


Output: 9

Constraints:

n == height.length
1 <= n <= 2 * 10 4
0 <= height[i] <= 105
*******************

9. Trapping Rain Water(C++)


*******************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int trap(vector& height) {
7 int result = 0, left = 0, right = height.size() - 1, level = 0;
8 while (left < right) {
9 int lower = height[height[left] < height[right] ? left++ : right--];
10 level = max(level, lower);
11 result += level - lower;
12 }
13 return result;
14 }
15 };
16
17 // Time: O(n)
18 // Space: O(1)
19 class Solution2 {
20 public:
21 int trap(vector& height) {
22 if (height.empty()) {
23 return 0;
24 }
25
26 int i = 0, j = height.size() - 1;
27 int left_height = height[0];
28 int right_height = height[height.size() - 1];
29 int trap = 0;
30
31 while (i < j) {
32 if (left_height < right_height) {
33 ++i;
34 // Fill in the gap.
35 trap += max(0, left_height - height[i]);
36 // Update current max height from left.
37 left_height = max(left_height, height[i]);
38 }
39 else {
40 --j;
41 // Fill in the gap.
42 trap += max(0, right_height - height[j]);
43 // Update current max height from right.
44 right_height = max(right_height, height[j]);
45 }
46 }
47
48 return trap;
49 }
50 };
*******************

9. Trapping Rain Water(Python)


*******************
1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def trap(self, height):
6 """
7 :type height: List[int]
8 :rtype: int
9 """
10 result, left, right, level = 0, 0, len(height)-1, 0
11 while left < right:
12 if height[left] < height[right]:
13 lower = height[left]
14 left += 1
15 else:
16 lower = height[right]
17 right -= 1
18 level = max(level, lower)
19 result += level-lower
20 return result
21
22
23 # Time: O(n)
24 # Space: O(1)
25 class Solution2(object):
26 # @param A, a list of integers
27 # @return an integer
28 def trap(self, A):
29 result = 0
30 top = 0
31 for i in xrange(len(A)):
32 if A[top] < A[i]:
33 top = i
34
35 second_top = 0
36 for i in xrange(top):
37 if A[second_top] < A[i]:
38 second_top = i
39 result += A[second_top] - A[i]
40
41 second_top = len(A) - 1
42 for i in reversed(xrange(top, len(A))):
43 if A[second_top] < A[i]:
44 second_top = i
45 result += A[second_top] - A[i]
46
47 return result
48
49 # Time: O(n)
50 # Space: O(n)
51 class Solution3(object):
52 # @param A, a list of integers
53 # @return an integer
54 def trap(self, A):
55 result = 0
56 stack = []
57
58 for i in xrange(len(A)):
59 mid_height = 0
60 while stack:
61 [pos, height] = stack.pop()
62 result += (min(height, A[i]) - mid_height) * (i - pos - 1)
63 mid_height = height
64
65 if A[i] < height:
66 stack.append([pos, height])
67 break
68 stack.append([i, A[i]])
69
70 return result
71
*****************

10. Wildcard Matching


*****************

Given an input string (s ) and a pattern (p), implement wildcard pattern matching with support for '?' and '*' where:

'?' Matches any single character.


'*' Matches any sequence of characters (including the empty sequence).

The matching should cover the entire input string (not partial).

Example 1:

Input: s = "aa", p = "a"


Output: false
Explanation: "a" does not match the entire string "aa".

Example 2:

Input: s = "aa", p = "*"


Output: true
Explanation: '*' matches any sequence.

Example 3:

Input: s = "cb", p = "?a"


Output: false
Explanation: '?' matches 'c', but the second letter is 'a', which does not match 'b'.

Example 4:

Input: s = "adceb", p = "*a*b"


Output: true
Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".

Example 5:

Input: s = "acdcb", p = "a*c?b"


Output: false

Constraints:

0 <= s.length, p.length <= 2000


s contains only lowercase English letters.
p contains only lowercase English letters, '?' or '*'.
*****************

10. Wildcard Matching(Python)


*****************

1 # Time: O(m + n) ~ O(m * n)


2 # Space: O(1)
3
4 # iterative solution with greedy
5 class Solution(object):
6 def isMatch(self, s, p):
7 """
8 :type s: str
9 :type p: str
10 :rtype: bool
11 """
12 count = 0 # used for complexity check
13 p_ptr, s_ptr, last_s_ptr, last_p_ptr = 0, 0, -1, -1
14 while s_ptr < len(s):
15 if p_ptr < len(p) and (s[s_ptr] == p[p_ptr] or p[p_ptr] == '?'):
16 s_ptr += 1
17 p_ptr += 1
18 elif p_ptr < len(p) and p[p_ptr] == '*':
19 p_ptr += 1
20 last_s_ptr = s_ptr
21 last_p_ptr = p_ptr
22 elif last_p_ptr != -1:
23 last_s_ptr += 1
24 s_ptr = last_s_ptr
25 p_ptr = last_p_ptr
26 else:
27 assert(count <= (len(p)+1) * (len(s)+1))
28 return False
29 count += 1 # used for complexity check
30
31 while p_ptr < len(p) and p[p_ptr] == '*':
32 p_ptr += 1
33 count += 1 # used for complexity check
34
35 assert(count <= (len(p)+1) * (len(s)+1))
36 return p_ptr == len(p)
37
38
39 # dp with rolling window
40 # Time: O(m * n)
41 # Space: O(n)
42 class Solution2(object):
43 # @return a boolean
44 def isMatch(self, s, p):
45 k = 2
46 result = [[False for j in xrange(len(p) + 1)] for i in xrange(k)]
47
48 result[0][0] = True
49 for i in xrange(1, len(p) + 1):
50 if p[i-1] == '*':
51 result[0][i] = result[0][i-1]
52 for i in xrange(1,len(s) + 1):
53 result[i % k][0] = False
54 for j in xrange(1, len(p) + 1):
55 if p[j-1] != '*':
56 result[i % k][j] = result[(i-1) % k][j-1] and (s[i-1] == p[j-1] or p[j-1] == '?')
57 else:
58 result[i % k][j] = result[i % k][j-1] or result[(i-1) % k][j]
59
60 return result[len(s) % k][len(p)]
61
62
63 # dp
64 # Time: O(m * n)
65 # Space: O(m * n)
66 class Solution3(object):
67 # @return a boolean
68 def isMatch(self, s, p):
69 result = [[False for j in xrange(len(p) + 1)] for i in xrange(len(s) + 1)]
70
71 result[0][0] = True
72 for i in xrange(1, len(p) + 1):
73 if p[i-1] == '*':
74 result[0][i] = result[0][i-1]
75 for i in xrange(1,len(s) + 1):
76 result[i][0] = False
77 for j in xrange(1, len(p) + 1):
78 if p[j-1] != '*':
79 result[i][j] = result[i-1][j-1] and (s[i-1] == p[j-1] or p[j-1] == '?')
80 else:
81 result[i][j] = result[i][j-1] or result[i-1][j]
82
83 return result[len(s)][len(p)]
84
85
86 # recursive, slowest, TLE
87 class Solution4(object):
88 # @return a boolean
89 def isMatch(self, s, p):
90 if not p or not s:
91 return not s and not p
92
93 if p[0] != '*':
94 if p[0] == s[0] or p[0] == '?':
95 return self.isMatch(s[1:], p[1:])
96 else:
97 return False
98 else:
99 while len(s) > 0:
100 if self.isMatch(s, p[1:]):
101 return True
102 s = s[1:]
103 return self.isMatch(s, p[1:])
104
************

11. Jump Game II


************

Given an array of non-negative integers nums, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Your goal is to reach the last index in the minimum number of jumps.

You can assume that you can always reach the last index.

Example 1:

Input: nums = [2,3,1,1,4]


Output: 2
Explanation: The minimum number of jumps to reach the last index is 2. Jump 1 step from index 0 to 1, then 3 steps to the last index.

Example 2:

Input: nums = [2,3,0,1,4]


Output: 2

Constraints:

1 <= nums.length <= 10 4


0 <= nums[i] <= 1000
************

11. Jump Game II(Python)


************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 # @param A, a list of integers
6 # @return an integer
7 def jump(self, A):
8 jump_count = 0
9 reachable = 0
10 curr_reachable = 0
11 for i, length in enumerate(A):
12 if i > reachable:
13 return -1
14 if i > curr_reachable:
15 curr_reachable = reachable
16 jump_count += 1
17 reachable = max(reachable, i + length)
18 return jump_count
19
20
********

12. N-Queens
********

The n-queens puzzle is the problem of placing n queens on an n x n chessboard such that no two queens attack each other.

Given an integer n, return all distinct solutions to the n-queens puzzle. You may return the answer inany order.

Each solution contains a distinct board configuration of the n-queens' placement, where'Q' and '.' both indicate a queen and
an empty space, respectively.

Example 1:

Input: n = 4
Output: [[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above

Example 2:

Input: n = 1
Output: [["Q"]]

Constraints:

1 <= n <= 9
********

12. N-Queens(Python)
********

1 # Time: O(n!)
2 # Space: O(n)
3
4 class Solution(object):
5 def solveNQueens(self, n):
6 """
7 :type n: int
8 :rtype: List[List[str]]
9 """
10 def dfs(curr, cols, main_diag, anti_diag, result):
11 row, n = len(curr), len(cols)
12 if row == n:
13 result.append(map(lambda x: '.'*x + "Q" + '.'*(n-x-1), curr))
14 return
15 for i in xrange(n):
16 if cols[i] or main_diag[row+i] or anti_diag[row-i+n]:
17 continue
18 cols[i] = main_diag[row+i] = anti_diag[row-i+n] = True
19 curr.append(i)
20 dfs(curr, cols, main_diag, anti_diag, result)
21 curr.pop()
22 cols[i] = main_diag[row+i] = anti_diag[row-i+n] = False
23
24 result = []
25 cols, main_diag, anti_diag = [False]*n, [False]*(2*n), [False]*(2*n)
26 dfs([], cols, main_diag, anti_diag, result)
27 return result
28
29
30 # For any point (x,y), if we want the new point (p,q) don't share the same row, column, or diagonal.
31 # then there must have ```p+q != x+y``` and ```p-q!= x-y```
32 # the former focus on eliminate 'left bottom right top' diagonal
33 # the latter focus on eliminate 'left top right bottom' diagonal
34
35 # - col_per_row: the list of column index per row
36 # - cur_row:current row we are seraching for valid column
37 # - xy_diff:the list of x-y
38 # - xy_sum:the list of x+y
39 class Solution2(object):
40 def solveNQueens(self, n):
41 """
42 :type n: int
43 :rtype: List[List[str]]
44 """
45 def dfs(col_per_row, xy_diff, xy_sum):
46 cur_row = len(col_per_row)
47 if cur_row == n:
48 ress.append(col_per_row)
49 for col in range(n):
50 if col not in col_per_row and cur_row-col not in xy_diff and cur_row+col not in xy_sum:
51 dfs(col_per_row+[col], xy_diff+[cur_row-col], xy_sum+[cur_row+col])
52 ress = []
53 dfs([], [], [])
54 return [['.'*i + 'Q' + '.'*(n-i-1) for i in res] for res in ress]
55
56
***********

13. N-Queens-II
***********

The n-queens puzzle is the problem of placing n queens on an n x n chessboard such that no two queens attack each other.

Given an integer n, return the number of distinct solutions to the n-queens puzzle.

Example 1:

Input: n = 4
Output: 2
Explanation: There are two distinct solutions to the 4-queens puzzle as shown.

Example 2:

Input: n = 1
Output: 1

Constraints:

1 <= n <= 9
***********

13. N-Queens-II(Python)
***********

1 from functools import reduce


2 # Time: O(n!)
3 # Space: O(n)
4
5 class Solution(object):
6 # @return an integer
7 def totalNQueens(self, n):
8 self.cols = [False] * n
9 self.main_diag = [False] * (2 * n)
10 self.anti_diag = [False] * (2 * n)
11 return self.totalNQueensRecu([], 0, n)
12
13 def totalNQueensRecu(self, solution, row, n):
14 if row == n:
15 return 1
16 result = 0
17 for i in xrange(n):
18 if not self.cols[i] and not self.main_diag[row + i] and not self.anti_diag[row - i + n]:
19 self.cols[i] = self.main_diag[row + i] = self.anti_diag[row - i + n] = True
20 result += self.totalNQueensRecu(solution + [i], row + 1, n)
21 self.cols[i] = self.main_diag[row + i] = self.anti_diag[row - i + n] = False
22 return result
23
24 # slower solution
25 class Solution2(object):
26 # @return an integer
27 def totalNQueens(self, n):
28 return self.totalNQueensRecu([], 0, n)
29
30 def totalNQueensRecu(self, solution, row, n):
31 if row == n:
32 return 1
33 result = 0
34 for i in xrange(n):
35 if i not in solution and reduce(lambda acc, j: abs(row - j) != abs(i - solution[j]) and acc, xrange(len(solution))
36 result += self.totalNQueensRecu(solution + [i], row + 1, n)
37 return result
38
***************

14. Merge Intervals


***************

Given an array of intervals where intervals[i] = [start i, end i], merge all overlapping intervals, and return an array of the non-
overlapping intervals that cover all the intervals in the input.

Example 1:

Input: intervals = [[1,3],[2,6],[8,10],[15,18]]


Output: [[1,6],[8,10],[15,18]]
Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].

Example 2:

Input: intervals = [[1,4],[4,5]]


Output: [[1,5]]
Explanation: Intervals [1,4] and [4,5] are considered overlapping.

Constraints:

1 <= intervals.length <= 104


intervals[i].length == 2
0 <= starti <= end i <= 104
***************

14. Merge Intervals(C++)


***************

1 // Time: O(nlogn)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 vector> merge(vector>& intervals) {
7 sort(begin(intervals), end(intervals));
8 vector> result;
9 for (const auto& interval : intervals) {
10 if (empty(result) || interval[0] > result.back()[1]) {
11 result.emplace_back(interval);
12 } else {
13 result.back()[1] = max(result.back()[1], interval[1]);
14 }
15 }
16 return result;
17 }
18 };
***************

14. Merge Intervals(Python)


***************

1 # Time: O(nlogn)
2 # Space: O(1)
3
4 class Solution(object):
5 def merge(self, intervals):
6 """
7 :type intervals: List[List[int]]
8 :rtype: List[List[int]]
9 """
10 intervals.sort()
11 result = []
12 for interval in intervals:
13 if not result or interval[0] > result[-1][1]:
14 result.append(interval)
15 else:
16 result[-1][1] = max(result[-1][1], interval[1])
17 return result
***************

15. Insert Interval


***************

Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).

You may assume that the intervals were initially sorted according to their start times.

Example 1:

Input: intervals = [[1,3],[6,9]], newInterval = [2,5]


Output: [[1,5],[6,9]]

Example 2:

Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]


Output: [[1,2],[3,10],[12,16]]
Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10].

Example 3:

Input: intervals = [], newInterval = [5,7]


Output: [[5,7]]

Example 4:

Input: intervals = [[1,5]], newInterval = [2,3]


Output: [[1,5]]

Example 5:

Input: intervals = [[1,5]], newInterval = [2,7]


Output: [[1,7]]

Constraints:

0 <= intervals.length <= 104


intervals[i].length == 2
0 <= intervals[i][0] <= intervals[i][1] <= 105
intervals is sorted by intervals[i][0] in ascending order.
newInterval.length == 2
0 <= newInterval[0] <= newInterval[1] <= 10 5
***************

15. Insert Interval(C++)


***************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 vector> insert(vector>& intervals, vector& newInterval) {
7 size_t i = 0;
8 vector> result;
9 // Insert intervals appeared before newInterval.
10 while (i < size(intervals) && newInterval[0] > intervals[i][1]) {
11 result.emplace_back(intervals[i++]);
12 }
13
14 // Merge intervals that overlap with newInterval.
15 while (i < size(intervals) && newInterval[1] >= intervals[i][0]) {
16 newInterval = {min(newInterval[0], intervals[i][0]),
17 max(newInterval[1], intervals[i][1])};
18 ++i;
19 }
20 result.emplace_back(newInterval);
21
22 // Insert intervals appearing after newInterval.
23 copy(cbegin(intervals) + i, cend(intervals), back_inserter(result));
24 return result;
25 }
26 };
***************

15. Insert Interval(Python)


***************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def insert(self, intervals, newInterval):
6 """
7 :type intervals: List[List[int]]
8 :type newInterval: List[int]
9 :rtype: List[List[int]]
10 """
11 result = []
12 i = 0
13 while i < len(intervals) and newInterval[0] > intervals[i][1]:
14 result += intervals[i],
15 i += 1
16 while i < len(intervals) and newInterval[1] >= intervals[i][0]:
17 newInterval = [min(newInterval[0], intervals[i][0]),
18 max(newInterval[1], intervals[i][1])]
19 i += 1
20 result.append(newInterval)
21 result.extend(intervals[i:])
22 return result
************

16. Valid Number


************

A valid number can be split up into these components (in order):

1. A decimal number or an integer.


2. (Optional) An 'e' or 'E', followed by an integer.

A decimal number can be split up into these components (in order):

1. (Optional) A sign character (either '+' or '-').


2. One of the following formats:
1. One or more digits, followed by a dot '.'.
2. One or more digits, followed by a dot '.', followed by one or more digits.
3. A dot '.', followed by one or more digits.

An integer can be split up into these components (in order):

1. (Optional) A sign character (either '+' or '-').


2. One or more digits.

For example, all the following are valid numbers: ["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-
123.456e789"], while the following are not valid numbers:["abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53"] .

Given a string s , return true if s is a valid number.

Example 1:

Input: s = "0"
Output: true

Example 2:

Input: s = "e"
Output: false

Example 3:

Input: s = "."
Output: false

Example 4:

Input: s = ".1"
Output: true

Constraints:

1 <= s.length <= 20


s consists of only English letters (both uppercase and lowercase), digits (0-9), plus '+' , minus '-', or dot '.'.
************

16. Valid Number(C++)


************
1 // Time: O(n)
2 // Space: O(1)
3
4 // automata: http://images.cnitblog.com/i/627993/201405/012016243309923.png
5 class Solution {
6 public:
7 bool isNumber(string s) {
8 enum InputType {
9 INVALID, // 0
10 SPACE, // 1
11 SIGN, // 2
12 DIGIT, // 3
13 DOT, // 4
14 EXPONENT, // 5
15 NUM_INPUTS // 6
16 };
17 int transitionTable[][NUM_INPUTS] = {
18 -1, 0, 3, 1, 2, -1, // next states for state 0
19 -1, 8, -1, 1, 4, 5, // next states for state 1
20 -1, -1, -1, 4, -1, -1, // next states for state 2
21 -1, -1, -1, 1, 2, -1, // next states for state 3
22 -1, 8, -1, 4, -1, 5, // next states for state 4
23 -1, -1, 6, 7, -1, -1, // next states for state 5
24 -1, -1, -1, 7, -1, -1, // next states for state 6
25 -1, 8, -1, 7, -1, -1, // next states for state 7
26 -1, 8, -1, -1, -1, -1, // next states for state 8
27 };
28
29 int state = 0;
30 for (const auto& c: s) {
31 InputType inputType = INVALID;
32 if (isspace(c)) {
33 inputType = SPACE;
34 } else if (c == '+' || c == '-') {
35 inputType = SIGN;
36 } else if (isdigit(c)) {
37 inputType = DIGIT;
38 } else if (c == '.') {
39 inputType = DOT;
40 } else if (c == 'e' || c == 'E') {
41 inputType = EXPONENT;
42 }
43 // Get next state from current state and input symbol
44 state = transitionTable[state][inputType];
45
46 // Invalid input
47 if (state == -1) {
48 return false;
49 }
50 }
51 // If the current state belongs to one of the accepting (final) states,
52 // then the number is valid
53 return state == 1 || state == 4 || state == 7 || state == 8;
54 }
55 };
56
57 #include
58 class Solution_TLE {
59 public:
60 bool isNumber(string s) {
61 regex e("^\\s*[\\+-]?((\\d+(\\.\\d*)?)|\\.\\d+)([eE][\\+-]?\\d+)?\\s*$");
62 return regex_match(s, e);
63 }
64 };
************

16. Valid Number(Python)


************
1 # Time: O(n)
2 # Space: O(1)
3
4 class InputType(object):
5 INVALID = 0
6 SPACE = 1
7 SIGN = 2
8 DIGIT = 3
9 DOT = 4
10 EXPONENT = 5
11
12
13 # regular expression: "^\s*[\+-]?((\d+(\.\d*)?)|\.\d+)([eE][\+-]?\d+)?\s*$"
14 # automata: http://images.cnitblog.com/i/627993/201405/012016243309923.png
15 class Solution(object):
16 def isNumber(self, s):
17 """
18 :type s: str
19 :rtype: bool
20 """
21 transition_table = [[-1, 0, 3, 1, 2, -1], # next states for state 0
22 [-1, 8, -1, 1, 4, 5], # next states for state 1
23 [-1, -1, -1, 4, -1, -1], # next states for state 2
24 [-1, -1, -1, 1, 2, -1], # next states for state 3
25 [-1, 8, -1, 4, -1, 5], # next states for state 4
26 [-1, -1, 6, 7, -1, -1], # next states for state 5
27 [-1, -1, -1, 7, -1, -1], # next states for state 6
28 [-1, 8, -1, 7, -1, -1], # next states for state 7
29 [-1, 8, -1, -1, -1, -1]] # next states for state 8
30
31 state = 0
32 for char in s:
33 inputType = InputType.INVALID
34 if char.isspace():
35 inputType = InputType.SPACE
36 elif char == '+' or char == '-':
37 inputType = InputType.SIGN
38 elif char.isdigit():
39 inputType = InputType.DIGIT
40 elif char == '.':
41 inputType = InputType.DOT
42 elif char == 'e' or char == 'E':
43 inputType = InputType.EXPONENT
44
45 state = transition_table[state][inputType]
46
47 if state == -1:
48 return False
49
50 return state == 1 or state == 4 or state == 7 or state == 8
51
52
53 class Solution2(object):
54 def isNumber(self, s):
55 """
56 :type s: str
57 :rtype: bool
58 """
59 import re
60 return bool(re.match("^\s*[\+-]?((\d+(\.\d*)?)|\.\d+)([eE][\+-]?\d+)?\s*$", s))
61
62
******************

17. Text Justification


******************

Given an array of strings words and a width maxWidth, format the text such that each line has exactly maxWidth characters and
is fully (left and right) justified.

You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pad extra spaces' '
when necessary so that each line has exactly maxWidth characters.

Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line does not divide
evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right.

For the last line of text, it should be left-justified and no extra space is inserted between words.

Note:

A word is defined as a character sequence consisting of non-space characters only.


Each word's length is guaranteed to be greater than 0 and not exceed maxWidth.
The input array words contains at least one word.

Example 1:

Input: words = ["This", "is", "an", "example", "of", "text", "justification."], maxWidth = 16
Output:
[
"This is an",
"example of text",
"justification. "
]

Example 2:

Input: words = ["What","must","be","acknowledgment","shall","be"], maxWidth = 16


Output:
[
"What must be",
"acknowledgment ",
"shall be "
]
Explanation: Note that the last line is "shall be " instead of "shall be", because the last line must be left-justified instead of ful
Note that the second line is also left-justified becase it contains only one word.

Example 3:

Input: words = ["Science","is","what","we","understand","well","enough","to","explain","to","a","computer.","Art","is","everything","else","w


Output:
[
"Science is what we",
"understand well",
"enough to explain to",
"a computer. Art is",
"everything else we",
"do "
]
Constraints:

1 <= words.length <= 300


1 <= words[i].length <= 20
words[i] consists of only English letters and symbols.
1 <= maxWidth <= 100
words[i].length <= maxWidth
******************

17. Text Justification(C++)


******************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 vector fullJustify(vector& words, int maxWidth) {
7 vector res;
8 const int n = words.size();
9 int begin = 0, len = 0;
10 for (int i = 0; i < n; ++i) {
11 if (len + words[i].size() + (i - begin) > maxWidth) {
12 res.emplace_back(connect(words, maxWidth, begin, i, len, false));
13 begin = i;
14 len = 0;
15 }
16 len += words[i].size();
17 }
18 // Last line.
19 res.emplace_back(connect(words, maxWidth, begin, n, len, true));
20 return res;
21 }
22
23 private:
24 string connect(const vector& words, int maxWidth,
25 int begin, int end, int len,
26 bool is_last) {
27 string s;
28 int n = end - begin;
29 for (int i = 0; i < n; ++i) {
30 s += words[begin + i];
31 addSpaces(i, n - 1, maxWidth - len, is_last, &s);
32 }
33 // For only one word in a line.
34 if (s.size() < maxWidth) {
35 s.append(maxWidth - s.size(), ' ');
36 }
37 return s;
38 }
39
40 void addSpaces(int i, int spaceCnt, int maxWidth, bool is_last, string *s) {
41 if (i < spaceCnt) {
42 // For the last line of text, it should be left justified,
43 // and no extra space is inserted between words.
44 int spaces = is_last ? 1 : maxWidth / spaceCnt + (i < maxWidth % spaceCnt);
45 s->append(spaces, ' ');
46 }
47 }
48 };
******************

17. Text Justification(Python)


******************

1 # Time: O(n)
2 # Space: O(k), k is maxWidth.
3
4 class Solution(object):
5 def fullJustify(self, words, maxWidth):
6 """
7 :type words: List[str]
8 :type maxWidth: int
9 :rtype: List[str]
10 """
11 def addSpaces(i, spaceCnt, maxWidth, is_last):
12 if i < spaceCnt:
13 # For the last line of text, it should be left justified,
14 # and no extra space is inserted between words.
15 return 1 if is_last else (maxWidth // spaceCnt) + int(i < maxWidth % spaceCnt)
16 return 0
17
18 def connect(words, maxWidth, begin, end, length, is_last):
19 s = [] # The extra space O(k) is spent here.
20 n = end - begin
21 for i in xrange(n):
22 s += words[begin + i],
23 s += ' ' * addSpaces(i, n - 1, maxWidth - length, is_last),
24 # For only one word in a line.
25 line = "".join(s)
26 if len(line) < maxWidth:
27 line += ' ' * (maxWidth - len(line))
28 return line
29
30 res = []
31 begin, length = 0, 0
32 for i in xrange(len(words)):
33 if length + len(words[i]) + (i - begin) > maxWidth:
34 res += connect(words, maxWidth, begin, i, length, False),
35 begin, length = i, 0
36 length += len(words[i])
37
38 # Last line.
39 res += connect(words, maxWidth, begin, len(words), length, True),
40 return res
41
42
*************

18. Edit Distance


*************

Given two strings word1 and word2, return the minimum number of operations required to convertword1 to word2.

You have the following three operations permitted on a word:

Insert a character
Delete a character
Replace a character

Example 1:

Input: word1 = "horse", word2 = "ros"


Output: 3
Explanation:
horse -> rorse (replace 'h' with 'r')
rorse -> rose (remove 'r')
rose -> ros (remove 'e')

Example 2:

Input: word1 = "intention", word2 = "execution"


Output: 5
Explanation:
intention -> inention (remove 't')
inention -> enention (replace 'i' with 'e')
enention -> exention (replace 'n' with 'x')
exention -> exection (replace 'n' with 'c')
exection -> execution (insert 'u')

Constraints:

0 <= word1.length, word2.length <= 500


word1 and word2 consist of lowercase English letters.
*************

18. Edit Distance(Python)


*************

1 # Time: O(n * m)
2 # Space: O(n + m)
3
4 class Solution(object):
5 # @return an integer
6 def minDistance(self, word1, word2):
7 if len(word1) < len(word2):
8 return self.minDistance(word2, word1)
9
10 distance = [i for i in xrange(len(word2) + 1)]
11
12 for i in xrange(1, len(word1) + 1):
13 pre_distance_i_j = distance[0]
14 distance[0] = i
15 for j in xrange(1, len(word2) + 1):
16 insert = distance[j - 1] + 1
17 delete = distance[j] + 1
18 replace = pre_distance_i_j
19 if word1[i - 1] != word2[j - 1]:
20 replace += 1
21 pre_distance_i_j = distance[j]
22 distance[j] = min(insert, delete, replace)
23
24 return distance[-1]
25
26 # Time: O(n * m)
27 # Space: O(n * m)
28 class Solution2(object):
29 # @return an integer
30 def minDistance(self, word1, word2):
31 distance = [[i] for i in xrange(len(word1) + 1)]
32 distance[0] = [j for j in xrange(len(word2) + 1)]
33
34 for i in xrange(1, len(word1) + 1):
35 for j in xrange(1, len(word2) + 1):
36 insert = distance[i][j - 1] + 1
37 delete = distance[i - 1][j] + 1
38 replace = distance[i - 1][j - 1]
39 if word1[i - 1] != word2[j - 1]:
40 replace += 1
41 distance[i].append(min(insert, delete, replace))
42
43 return distance[-1][-1]
44
************************

19. Minimum Window Substring


************************

Given two strings s and t of lengths m and n respectively, return the minimum window substring of s such that every
character in t (including duplicates) is included in the window. If there is no such substring, return the empty string "".

The testcases will be generated such that the answer is unique.

A substring is a contiguous sequence of characters within the string.

Example 1:

Input: s = "ADOBECODEBANC", t = "ABC"


Output: "BANC"
Explanation: The minimum window substring "BANC" includes 'A', 'B', and 'C' from string t.

Example 2:

Input: s = "a", t = "a"


Output: "a"
Explanation: The entire string s is the minimum window.

Example 3:

Input: s = "a", t = "aa"


Output: ""
Explanation: Both 'a's from t must be included in the window.
Since the largest window of s only has one 'a', return empty string.

Constraints:

m == s.length
n == t.length
1 <= m, n <= 105
s and t consist of uppercase and lowercase English letters.

Follow up: Could you find an algorithm that runs in O(m + n) time?
************************

19. Minimum Window Substring(C++)


************************

1 // Time: O(n)
2 // Space: O(k)
3
4 class Solution {
5 public:
6 string minWindow(string s, string t) {
7 unordered_map count;
8 for (const auto& c : t) {
9 ++count[c];
10 }
11 int remain = t.length();
12 int left = -1, right = -1;
13 for (int i = 0, j = 0; j < s.length(); ++j) {
14 remain -= count[s[j]]-- > 0;
15 if (remain) {
16 continue;
17 }
18 while (count[s[i]] < 0) {
19 ++count[s[i++]];
20 }
21 if (right == -1 || j - i + 1 < right - left + 1) {
22 left = i;
23 right = j;
24 }
25 }
26 return left >= 0 ? s.substr(left, right - left + 1) : "";
27 }
28 };
29
30 // Time: O(n)
31 // Space: O(k)
32 class Solution2 {
33 public:
34 string minWindow(string s, string t) {
35 if (s.empty() || s.length() < t.length()) {
36 return "";
37 }
38
39 const int ASCII_MAX = 256;
40 vector exp_cnt(ASCII_MAX, 0);
41 vector cur_cnt(ASCII_MAX, 0);
42
43 int cnt = 0;
44 int start = 0;
45 int min_start = 0;
46 int min_width = numeric_limits::max();
47
48 for (const auto& c : t) {
49 ++exp_cnt[c];
50 }
51
52 for (int i = 0; i < s.length(); ++i) {
53 if (exp_cnt[s[i]] > 0) {
54 ++cur_cnt[s[i]];
55 if (cur_cnt[s[i]] <= exp_cnt[s[i]]) { // Counting expected elements.
56 ++cnt;
57 }
58 }
59 if (cnt == t.size()) { // If window meets the requirement.
60 while (exp_cnt[s[start]] == 0 || // Adjust left bound of window.
61 cur_cnt[s[start]] > exp_cnt[s[start]]) {
62 --cur_cnt[s[start]];
63 ++start;
64 }
65
66 if (min_width > i - start + 1) { // Update minimum window.
67 min_width = i - start + 1;
68 min_start = start;
69 }
70 }
71 }
72
73 if (min_width == numeric_limits::max()) {
74 return "";
75 }
76
77 return s.substr(min_start, min_width);
78 }
79 };
************************

19. Minimum Window Substring(Python)


************************
1 # Time: O(n)
2 # Space: O(k), k is the number of different characters
3
4 import collections
5
6
7 class Solution(object):
8 def minWindow(self, s, t):
9 """
10 :type s: str
11 :type t: str
12 :rtype: str
13 """
14 count, remain = collections.Counter(t), len(t)
15 i, left, right = 0, -1, -1
16 for j, c in enumerate(s):
17 remain -= count[c] > 0
18 count[c] -= 1
19 if remain:
20 continue
21 while count[s[i]] < 0: # greedily discard uneeds
22 count[s[i]] += 1
23 i += 1
24 if right == -1 or j-i+1 < right-left+1:
25 left, right = i, j
26 return s[left:right+1]
27
28
29 # Time: O(n)
30 # Space: O(k), k is the number of different characters
31 class Solution2(object):
32 def minWindow(self, s, t):
33 """
34 :type s: str
35 :type t: str
36 :rtype: str
37 """
38 current_count = [0 for i in xrange(52)]
39 expected_count = [0 for i in xrange(52)]
40
41 for char in t:
42 expected_count[ord(char) - ord('a')] += 1
43
44 i, count, start, min_width, min_start = 0, 0, 0, float("inf"), 0
45 while i < len(s):
46 current_count[ord(s[i]) - ord('a')] += 1
47 if current_count[ord(s[i]) - ord('a')] <= expected_count[ord(s[i]) - ord('a')]:
48 count += 1
49
50 if count == len(t):
51 while expected_count[ord(s[start]) - ord('a')] == 0 or \
52 current_count[ord(s[start]) - ord('a')] > expected_count[ord(s[start]) - ord('a')]:
53 current_count[ord(s[start]) - ord('a')] -= 1
54 start += 1
55
56 if min_width > i - start + 1:
57 min_width = i - start + 1
58 min_start = start
59 i += 1
60
61 if min_width == float("inf"):
62 return ""
63
64 return s[min_start:min_start + min_width]
65
66
******************************

20. Largest Rectangle in Histogram


******************************

Given an array of integers heights representing the histogram's bar height where the width of each bar is1, return the area of
the largest rectangle in the histogram.

Example 1:

Input: heights = [2,1,5,6,2,3]


Output: 10
Explanation: The above is a histogram where width of each bar is 1.
The largest rectangle is shown in the red area, which has an area = 10 units.

Example 2:

Input: heights = [2,4]


Output: 4

Constraints:

1 <= heights.length <= 10 5


0 <= heights[i] <= 10 4
******************************

20. Largest Rectangle in Histogram(C++)


******************************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int largestRectangleArea(vector& heights) {
7 vector stk = {-1};
8 int result = 0;
9 for (int i = 0; i <= size(heights); ++i) {
10 while (stk.back() != -1 && (i == size(heights) || heights[stk.back()] >= heights[i])) {
11 int last = stk.back(); stk.pop_back();
12 result = max(result, heights[last] * ((i - 1) - stk.back()));
13 }
14 stk.emplace_back(i);
15 }
16 return result;
17 }
18 };
******************************

20. Largest Rectangle in Histogram(Python)


******************************

1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 def largestRectangleArea(self, heights):
6 """
7 :type heights: List[int]
8 :rtype: int
9 """
10 stk, result = [-1], 0
11 for i in xrange(len(heights)+1):
12 while stk[-1] != -1 and (i == len(heights) or heights[stk[-1]] >= heights[i]):
13 result = max(result, heights[stk.pop()]*((i-1)-stk[-1]))
14 stk.append(i)
15 return result
*****************

21. Maximal Rectangle


*****************

Given a rows x cols binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area.

Example 1:

Input: matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]


Output: 6
Explanation: The maximal rectangle is shown in the above picture.

Example 2:

Input: matrix = []
Output: 0

Example 3:

Input: matrix = [["0"]]


Output: 0

Example 4:

Input: matrix = [["1"]]


Output: 1

Example 5:

Input: matrix = [["0","0"]]


Output: 0

Constraints:
rows == matrix.length
cols == matrix[i].length
0 <= row, cols <= 200
matrix[i][j] is '0' or '1'.
*****************

21. Maximal Rectangle(C++)


*****************

1 // Time: O(m * n)
2 // Space: O(n)
3
4 // Ascending stack solution.
5 class Solution {
6 public:
7 int maximalRectangle(vector > &matrix) {
8 if (matrix.empty() || matrix[0].empty()) {
9 return 0;
10 }
11
12 int result = 0;
13 vector heights(matrix[0].size(), 0);
14 for (int i = 0; i < matrix.size(); ++i) {
15 for (int j = 0; j < matrix[0].size(); ++j) {
16 heights[j] = matrix[i][j] == '1' ? heights[j] + 1 : 0;
17 }
18 result = max(result, largestRectangleArea(heights));
19 }
20 return result;
21 }
22
23 private:
24 int largestRectangleArea(const vector& heights) {
25 vector stk = {-1};
26 int res = 0;
27 for (int i = 0; i <= size(heights); ++i) {
28 while (stk.back() != -1 && (i == size(heights) || heights[stk.back()] >= heights[i])) {
29 int last = stk.back(); stk.pop_back();
30 res = max(res, heights[last] * ((i - 1) - stk.back()));
31 }
32 stk.emplace_back(i);
33 }
34 return res;
35 }
36 };
37
38 // Time: O(m * n)
39 // Space: O(n)
40 // DP solution.
41 class Solution2 {
42 public:
43 int maximalRectangle(vector > &matrix) {
44 if (matrix.empty()) {
45 return 0;
46 }
47
48 const int m = matrix.size();
49 const int n = matrix.front().size();
50 int res = 0;
51 vector H(n, 0); // Height of all ones rectangle include matrix[i][j].
52 vector L(n, 0); // Left closed bound of all ones rectangle include matrix[i][j].
53 vector R(n, n); // Right open bound of all ones rectangle include matrix[i][j].
54
55 for (int i = 0; i < m; ++i) {
56 int left = 0, right = n;
57 for (int j = 0; j < n; ++j) {
58 if (matrix[i][j] == '1') {
59 ++H[j]; // Update height.
60 L[j] = max(L[j], left); // Update left bound.
61 } else {
62 left = j + 1;
63 H[j] = L[j] = 0;
64 R[j] = n;
65 }
66 }
67
68 for (int j = n - 1; j >= 0; --j) {
69 if (matrix[i][j] == '1') {
70 R[j] = min(R[j], right); // Update right bound.
71 res = max(res, H[j] * (R[j] - L[j]));
72 } else {
73 right = j;
74 }
75 }
76 }
77
78 return res;
79 }
80 };
*****************

21. Maximal Rectangle(Python)


*****************
1 # Time: O(n^2)
2 # Space: O(n)
3
4 class Solution(object):
5 def maximalRectangle(self, matrix):
6 """
7 :type matrix: List[List[str]]
8 :rtype: int
9 """
10 def largestRectangleArea(heights):
11 stk, result, i = [-1], 0, 0
12 for i in xrange(len(heights)+1):
13 while stk[-1] != -1 and (i == len(heights) or heights[stk[-1]] >= heights[i]):
14 result = max(result, heights[stk.pop()]*((i-1)-stk[-1]))
15 stk.append(i)
16 return result
17
18 if not matrix:
19 return 0
20 result = 0
21 heights = [0]*len(matrix[0])
22 for i in xrange(len(matrix)):
23 for j in xrange(len(matrix[0])):
24 heights[j] = heights[j] + 1 if matrix[i][j] == '1' else 0
25 result = max(result, largestRectangleArea(heights))
26 return result
27
28
29 # Time: O(n^2)
30 # Space: O(n)
31 # DP solution.
32 class Solution2(object):
33 def maximalRectangle(self, matrix):
34 """
35 :type matrix: List[List[str]]
36 :rtype: int
37 """
38 if not matrix:
39 return 0
40
41 result = 0
42 m = len(matrix)
43 n = len(matrix[0])
44 L = [0 for _ in xrange(n)]
45 H = [0 for _ in xrange(n)]
46 R = [n for _ in xrange(n)]
47
48 for i in xrange(m):
49 left = 0
50 for j in xrange(n):
51 if matrix[i][j] == '1':
52 L[j] = max(L[j], left)
53 H[j] += 1
54 else:
55 L[j] = 0
56 H[j] = 0
57 R[j] = n
58 left = j + 1
59
60 right = n
61 for j in reversed(xrange(n)):
62 if matrix[i][j] == '1':
63 R[j] = min(R[j], right)
64 result = max(result, H[j] * (R[j] - L[j]))
65 else:
66 right = j
67
68 return result
69
***************

22. Scramble String


***************

We can scramble a string s to get a string t using the following algorithm:

1. If the length of the string is 1, stop.


2. If the length of the string is > 1, do the following:
Split the string into two non-empty substrings at a random index, i.e., if the string iss , divide it to x and y where s =
x + y.
Randomly decide to swap the two substrings or to keep them in the same order. i.e., after this step,s may
become s = x + y or s = y + x .
Apply step 1 recursively on each of the two substringsx and y .

Given two strings s1 and s2 of the same length, return true if s2 is a scrambled string of s1, otherwise, return false.

Example 1:

Input: s1 = "great", s2 = "rgeat"


Output: true
Explanation: One possible scenario applied on s1 is:
"great" --> "gr/eat" // divide at random index.
"gr/eat" --> "gr/eat" // random decision is not to swap the two substrings and keep them in order.
"gr/eat" --> "g/r / e/at" // apply the same algorithm recursively on both substrings. divide at ranom index each of them.
"g/r / e/at" --> "r/g / e/at" // random decision was to swap the first substring and to keep the second substring in the same order.
"r/g / e/at" --> "r/g / e/ a/t" // again apply the algorithm recursively, divide "at" to "a/t".
"r/g / e/ a/t" --> "r/g / e/ a/t" // random decision is to keep both substrings in the same order.
The algorithm stops now and the result string is "rgeat" which is s2.
As there is one possible scenario that led s1 to be scrambled to s2, we return true.

Example 2:

Input: s1 = "abcde", s2 = "caebd"


Output: false

Example 3:

Input: s1 = "a", s2 = "a"


Output: true

Constraints:

s1.length == s2.length
1 <= s1.length <= 30
s1 and s2 consist of lower-case English letters.
***************

22. Scramble String(Python)


***************

1 # Time: O(n^4)
2 # Space: O(n^3)
3
4 class Solution(object):
5 # @return a boolean
6 def isScramble(self, s1, s2):
7 if not s1 or not s2 or len(s1) != len(s2):
8 return False
9 if s1 == s2:
10 return True
11 result = [[[False for j in xrange(len(s2))] for i in xrange(len(s1))] for n in xrange(len(s1) + 1)]
12 for i in xrange(len(s1)):
13 for j in xrange(len(s2)):
14 if s1[i] == s2[j]:
15 result[1][i][j] = True
16
17 for n in xrange(2, len(s1) + 1):
18 for i in xrange(len(s1) - n + 1):
19 for j in xrange(len(s2) - n + 1):
20 for k in xrange(1, n):
21 if result[k][i][j] and result[n - k][i + k][j + k] or\
22 result[k][i][j + n - k] and result[n - k][i + k][j]:
23 result[n][i][j] = True
24 break
25
26 return result[n][0][0]
27
*******************

23. Interleaving String


*******************

Given strings s1, s2, and s3, find whether s3 is formed by an interleaving of s1 and s2.

An interleaving of two strings s and t is a configuration where they are divided into non-empty substrings such that:

s = s 1 + s 2 + ... + s n
t = t 1 + t 2 + ... + t m
|n - m| <= 1
The interleaving is s 1 + t 1 + s 2 + t 2 + s 3 + t 3 + ... or t1 + s 1 + t 2 + s 2 + t 3 + s 3 + ...

Note: a + b is the concatenation of strings a and b.

Example 1:

Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"


Output: true

Example 2:

Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"


Output: false

Example 3:

Input: s1 = "", s2 = "", s3 = ""


Output: true

Constraints:

0 <= s1.length, s2.length <= 100


0 <= s3.length <= 200
s1, s2, and s3 consist of lowercase English letters.

Follow up: Could you solve it using only O(s2.length) additional memory space?
*******************

23. Interleaving String(Python)


*******************
1 # Time: O(m * n)
2 # Space: O(m + n)
3
4 class Solution(object):
5 # @return a boolean
6 def isInterleave(self, s1, s2, s3):
7 if len(s1) + len(s2) != len(s3):
8 return False
9 if len(s1) > len(s2):
10 return self.isInterleave(s2, s1, s3)
11 match = [False for i in xrange(len(s1) + 1)]
12 match[0] = True
13 for i in xrange(1, len(s1) + 1):
14 match[i] = match[i -1] and s1[i - 1] == s3[i - 1]
15 for j in xrange(1, len(s2) + 1):
16 match[0] = match[0] and s2[j - 1] == s3[j - 1]
17 for i in xrange(1, len(s1) + 1):
18 match[i] = (match[i - 1] and s1[i - 1] == s3[i + j - 1]) \
19 or (match[i] and s2[j - 1] == s3[i + j - 1])
20 return match[-1]
21
22 # Time: O(m * n)
23 # Space: O(m * n)
24 # Dynamic Programming
25 class Solution2(object):
26 # @return a boolean
27 def isInterleave(self, s1, s2, s3):
28 if len(s1) + len(s2) != len(s3):
29 return False
30 match = [[False for i in xrange(len(s2) + 1)] for j in xrange(len(s1) + 1)]
31 match[0][0] = True
32 for i in xrange(1, len(s1) + 1):
33 match[i][0] = match[i - 1][0] and s1[i - 1] == s3[i - 1]
34 for j in xrange(1, len(s2) + 1):
35 match[0][j] = match[0][j - 1] and s2[j - 1] == s3[j - 1]
36 for i in xrange(1, len(s1) + 1):
37 for j in xrange(1, len(s2) + 1):
38 match[i][j] = (match[i - 1][j] and s1[i - 1] == s3[i + j - 1]) \
39 or (match[i][j - 1] and s2[j - 1] == s3[i + j - 1])
40 return match[-1][-1]
41
42 # Time: O(m * n)
43 # Space: O(m * n)
44 # Recursive + Hash
45 class Solution3(object):
46 # @return a boolean
47 def isInterleave(self, s1, s2, s3):
48 self.match = {}
49 if len(s1) + len(s2) != len(s3):
50 return False
51 return self.isInterleaveRecu(s1, s2, s3, 0, 0, 0)
52
53 def isInterleaveRecu(self, s1, s2, s3, a, b, c):
54 if repr([a, b]) in self.match.keys():
55 return self.match[repr([a, b])]
56
57 if c == len(s3):
58 return True
59
60 result = False
61 if a < len(s1) and s1[a] == s3[c]:
62 result = result or self.isInterleaveRecu(s1, s2, s3, a + 1, b, c + 1)
63 if b < len(s2) and s2[b] == s3[c]:
64 result = result or self.isInterleaveRecu(s1, s2, s3, a, b + 1, c + 1)
65
66 self.match[repr([a, b])] = result
67
68 return result
69
**************************

24. Recover Binary Search Tree


**************************

You are given the root of a binary search tree (BST), where exactly two nodes of the tree were swapped by mistake.Recover
the tree without changing its structure.

Follow up: A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?

Example 1:

Input: root = [1,3,null,null,2]


Output: [3,1,null,null,2]
Explanation: 3 cannot be a left child of 1 because 3 > 1. Swapping 1 and 3 makes the BST valid.

Example 2:

Input: root = [3,1,4,null,null,2]


Output: [2,1,4,null,null,3]
Explanation: 2 cannot be in the right subtree of 3 because 2 < 3. Swapping 2 and 3 makes the BST valid.

Constraints:
The number of nodes in the tree is in the range[2, 1000].
-231 <= Node.val <= 2 31 - 1
**************************

24. Recover Binary Search Tree(C++)


**************************

1 // Time: O(n)
2 // Space: O(1)
3
4 /**
5 * Definition for binary tree
6 * struct TreeNode {
7 * int val;
8 * TreeNode *left;
9 * TreeNode *right;
10 * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
11 * };
12 */
13 class Solution {
14 public:
15 void recoverTree(TreeNode *root) {
16 MorrisTraversal(root);
17 }
18
19 private:
20 void MorrisTraversal(TreeNode *root) {
21 if (!root) {
22 return;
23 }
24 pair broken;
25 TreeNode *prev = nullptr;
26 TreeNode *cur = root;
27 while (cur) {
28 if (!cur->left) {
29 detect(prev, cur, &broken);
30 prev = cur;
31 cur = cur->right;
32 } else {
33 TreeNode *node = cur->left;
34 while (node->right && node->right != cur) {
35 node = node->right;
36 }
37 if (!node->right) {
38 node->right = cur;
39 cur = cur->left;
40 } else {
41 detect(prev, cur, &broken);
42 prev = cur;
43 node->right = nullptr;
44 cur = cur->right;
45 }
46 }
47 }
48 swap(broken.first->val, broken.second->val);
49 }
50
51 void detect(TreeNode *prev, TreeNode *cur, pair *broken) {
52 if (prev && prev->val > cur->val) {
53 if (!broken->first) { // Find the first broken node.
54 broken->first = prev;
55 }
56 broken->second = cur; // Find the last broken node.
57 }
58 }
59 };
**************************

24. Recover Binary Search Tree(Python)


**************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class TreeNode(object):
5 def __init__(self, x):
6 self.val = x
7 self.left = None
8 self.right = None
9
10 def __repr__(self):
11 if self:
12 serial = []
13 queue = [self]
14
15 while queue:
16 cur = queue[0]
17
18 if cur:
19 serial.append(cur.val)
20 queue.append(cur.left)
21 queue.append(cur.right)
22 else:
23 serial.append("#")
24
25 queue = queue[1:]
26
27 while serial[-1] == "#":
28 serial.pop()
29
30 return repr(serial)
31
32 else:
33 return None
34
35 class Solution(object):
36 # @param root, a tree node
37 # @return a tree node
38 def recoverTree(self, root):
39 return self.MorrisTraversal(root)
40
41 def MorrisTraversal(self, root):
42 if root is None:
43 return
44 broken = [None, None]
45 pre, cur = None, root
46
47 while cur:
48 if cur.left is None:
49 self.detectBroken(broken, pre, cur)
50 pre = cur
51 cur = cur.right
52 else:
53 node = cur.left
54 while node.right and node.right != cur:
55 node = node.right
56
57 if node.right is None:
58 node.right =cur
59 cur = cur.left
60 else:
61 self.detectBroken(broken, pre, cur)
62 node.right = None
63 pre = cur
64 cur = cur.right
65
66 broken[0].val, broken[1].val = broken[1].val, broken[0].val
67
68 return root
69
70 def detectBroken(self, broken, pre, cur):
71 if pre and pre.val > cur.val:
72 if broken[0] is None:
73 broken[0] = pre
74 broken[1] = cur
75
*********************

25. Distinct Subsequences


*********************

Given two strings s and t, return the number of distinct subsequences of s which equals t.

A string's subsequence is a new string formed from the original string by deleting some (can be none) of the characters
without disturbing the remaining characters' relative positions. (i.e., "ACE" is a subsequence of "ABCDE" while "AEC" is not).

It is guaranteed the answer fits on a 32-bit signed integer.

Example 1:

Input: s = "rabbbit", t = "rabbit"


Output: 3
Explanation:
As shown below, there are 3 ways you can generate "rabbit" from S.
rabbbit
rabbbit
rabbbit

Example 2:

Input: s = "babgbag", t = "bag"


Output: 5
Explanation:
As shown below, there are 5 ways you can generate "bag" from S.
babgbag
babgbag
babgbag
babgbag
babgbag

Constraints:

1 <= s.length, t.length <= 1000


s and t consist of English letters.
*********************

25. Distinct Subsequences(Python)


*********************

1 # Time: O(n^2)
2 # Space: O(n)
3
4 class Solution(object):
5 # @return an integer
6 def numDistinct(self, S, T):
7 ways = [0 for _ in xrange(len(T) + 1)]
8 ways[0] = 1
9 for S_char in S:
10 for j, T_char in reversed(list(enumerate(T))):
11 if S_char == T_char:
12 ways[j + 1] += ways[j]
13 return ways[len(T)]
14
**********************************************

26. Populating Next Right Pointers in Each Node II


**********************************************

Given a binary tree

struct Node {
int val;
Node *left;
Node *right;
Node *next;
}

Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to
NULL.

Initially, all next pointers are set toNULL.

Follow up:

You may only use constant extra space.


Recursive approach is fine, you may assume implicit stack space does not count as extra space for this problem.

Example 1:

Input: root = [1,2,3,4,5,null,7]


Output: [1,#,2,3,#,4,5,7,#]
Explanation: Given the above binary tree (Figure A), your function should populate each next pointer to point to its next right node, just li

Constraints:

The number of nodes in the given tree is less than6000.


-100 <= node.val <= 100
**********************************************

26. Populating Next Right Pointers in Each Node


II(Python)
**********************************************

1 # Time: O(n)
2 # Space: O(1)
3
4 # Definition for a Node.
5 class Node(object):
6 def __init__(self, val=0, left=None, right=None, next=None):
7 self.val = val
8 self.left = left
9 self.right = right
10 self.next = next
11
12
13 class Solution(object):
14 # @param root, a tree node
15 # @return nothing
16 def connect(self, root):
17 head = root
18 pre = Node(0)
19 cur = pre
20 while root:
21 while root:
22 if root.left:
23 cur.next = root.left
24 cur = cur.next
25 if root.right:
26 cur.next = root.right
27 cur = cur.next
28 root = root.next
29 root, cur = pre.next, pre
30 cur.next = None
31 return head
***********************************

27. Best Time to Buy and Sell Stock III


***********************************

You are given an array prices where prices[i] is the price of a given stock on theith day.

Find the maximum profit you can achieve. You may completeat most two transactions.

Note: You may not engage in multiple transactions simultaneously (i.e., you must sell the stock before you buy again).

Example 1:

Input: prices = [3,3,5,0,0,3,1,4]


Output: 6
Explanation: Buy on day 4 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
Then buy on day 7 (price = 1) and sell on day 8 (price = 4), profit = 4-1 = 3.

Example 2:

Input: prices = [1,2,3,4,5]


Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are engaging multiple transactions at the same time. You must sel

Example 3:

Input: prices = [7,6,4,3,1]


Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

Example 4:

Input: prices = [1]


Output: 0

Constraints:

1 <= prices.length <= 10 5


0 <= prices[i] <= 10 5
***********************************

27. Best Time to Buy and Sell Stock III(Python)


***********************************
1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def maxProfit(self, prices):
6 """
7 :type prices: List[int]
8 :rtype: int
9 """
10 hold1, hold2 = float("-inf"), float("-inf")
11 release1, release2 = 0, 0
12 for i in prices:
13 release1 = max(release1, hold1 + i)
14 hold1 = max(hold1, -i)
15 release2 = max(release2, hold2 + i)
16 hold2 = max(hold2, release1 - i)
17 return release2
18
19
20 # Time: O(k * n)
21 # Space: O(k)
22 class Solution2(object):
23 def maxProfit(self, prices):
24 """
25 :type prices: List[int]
26 :rtype: int
27 """
28 def maxAtMostKPairsProfit(prices, k):
29 max_buy = [float("-inf") for _ in xrange(k + 1)]
30 max_sell = [0 for _ in xrange(k + 1)]
31 for i in xrange(len(prices)):
32 for j in xrange(1, k + 1):
33 max_buy[j] = max(max_buy[j], max_sell[j-1] - prices[i])
34 max_sell[j] = max(max_sell[j], max_buy[j] + prices[i])
35 return max_sell[k]
36
37 return maxAtMostKPairsProfit(prices, 2)
38
39
40 # Time: O(n)
41 # Space: O(n)
42 class Solution3(object):
43 # @param prices, a list of integer
44 # @return an integer
45 def maxProfit(self, prices):
46 min_price, max_profit_from_left, max_profits_from_left = \
47 float("inf"), 0, []
48 for price in prices:
49 min_price = min(min_price, price)
50 max_profit_from_left = max(max_profit_from_left, price - min_price)
51 max_profits_from_left.append(max_profit_from_left)
52
53 max_price, max_profit_from_right, max_profits_from_right = 0, 0, []
54 for i in reversed(range(len(prices))):
55 max_price = max(max_price, prices[i])
56 max_profit_from_right = max(max_profit_from_right,
57 max_price - prices[i])
58 max_profits_from_right.insert(0, max_profit_from_right)
59
60 max_profit = 0
61 for i in range(len(prices)):
62 max_profit = max(max_profit,
63 max_profits_from_left[i] +
64 max_profits_from_right[i])
65
66 return max_profit
67
****************************

28. Binary Tree Maximum Path Sum


****************************

A path in a binary tree is a sequence of nodes where each pair of adjacent nodes in the sequence has an edge connecting
them. A node can only appear in the sequence at most once. Note that the path does not need to pass through the root.

The path sum of a path is the sum of the node's values in the path.

Given the root of a binary tree, return the maximum path sum of any path.

Example 1:

Input: root = [1,2,3]


Output: 6
Explanation: The optimal path is 2 -> 1 -> 3 with a path sum of 2 + 1 + 3 = 6.

Example 2:

Input: root = [-10,9,20,null,null,15,7]


Output: 42
Explanation: The optimal path is 15 -> 20 -> 7 with a path sum of 15 + 20 + 7 = 42.

Constraints:

The number of nodes in the tree is in the range[1, 3 * 104].


-1000 <= Node.val <= 1000
****************************

28. Binary Tree Maximum Path Sum(C++)


****************************

1 // Time: O(n)
2 // Space: O(h)
3
4 /**
5 * Definition for a binary tree node.
6 * struct TreeNode {
7 * int val;
8 * TreeNode *left;
9 * TreeNode *right;
10 * TreeNode() : val(0), left(nullptr), right(nullptr) {}
11 * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
12 * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
13 * };
14 */
15 class Solution {
16 public:
17 int maxPathSum(TreeNode* root) {
18 return iter_dfs(root);
19 }
20
21 private:
22 int iter_dfs(TreeNode *node) {
23 int result = numeric_limits::min();
24
25 vector> stk;
26 function divide;
27 function, shared_ptr, int *)> conquer;
28 divide = [&](TreeNode *node, int *ret) {
29 if (!node) {
30 return;
31 }
32 auto ret1 = make_shared(), ret2 = make_shared();
33 stk.emplace_back(bind(conquer, node, ret1, ret2, ret));
34 stk.emplace_back(bind(divide, node->right, ret2.get()));
35 stk.emplace_back(bind(divide, node->left, ret1.get()));
36 };
37 conquer = [&](TreeNode *node, shared_ptr ret1, shared_ptr ret2, int *ret) {
38 result = max({result, node->val + max(*ret1, 0) + max(*ret2, 0)});
39 *ret = node->val + max({*ret1, *ret2, 0});
40 };
41
42 int max_sum = 0;
43 stk.emplace_back(bind(divide, node, &max_sum));
44 while (!stk.empty()) {
45 auto cb = move(stk.back()); stk.pop_back();
46 cb();
47 }
48 return result;
49 }
50 };
51
52 // Time: O(n)
53 // Space: O(h)
54 class Solution2 {
55 public:
56 int maxPathSum(TreeNode* root) {
57 return iter_dfs(root);
58 }
59
60 private:
61 int iter_dfs(TreeNode *node) {
62 int result = numeric_limits::min(), max_sum = 0;
63 vector, unique_ptr, int*>> stk;
64 stk.emplace_back(1, node, nullptr, nullptr, &max_sum);
65 while (!stk.empty()) {
66 const auto [step, node, ret1, ret2, ret] = move(stk.back()); stk.pop_back();
67 if (step == 1) {
68 if (!node) {
69 continue;
70 }
71 auto ret1 = make_unique(), ret2 = make_unique();
72 auto p1 = ret1.get(), p2 = ret2.get();
73 stk.emplace_back(2, node, move(ret1), move(ret2), ret);
74 stk.emplace_back(1, node->right, nullptr, nullptr, p2);
75 stk.emplace_back(1, node->left, nullptr, nullptr, p1);
76 } else if (step == 2) {
77 result = max({result, node->val + max(*ret1, 0) + max(*ret2, 0)});
78 *ret = node->val + max({*ret1, *ret2, 0});
79 }
80 }
81 return result;
82 }
83 };
84
85 // Time: O(n)
86 // Space: O(h)
87 class Solution3 {
88 public:
89 int maxPathSum(TreeNode* root) {
90 return dfs(root).first;
91 }
92
93 private:
94 pair dfs(TreeNode *node) {
95 if (!node) {
96 return {numeric_limits::min(), 0};
97 }
98 const auto& [max_left, curr_left] = dfs(node->left);
99 const auto& [max_right, curr_right] = dfs(node->right);
100 return {max({max_left, max_right, node->val + max(curr_left, 0) + max(curr_right, 0)}),
101 node->val + max({curr_left, curr_right, 0})};
102 }
103 };
****************************

28. Binary Tree Maximum Path Sum(Python)


****************************

1 # Time: O(n)
2 # Space: O(h), h is height of binary tree
3
4 class TreeNode(object):
5 def __init__(self, x):
6 self.val = x
7 self.left = None
8 self.right = None
9
10
11 class Solution(object):
12 # @param root, a tree node
13 # @return an integer
14 def maxPathSum(self, root):
15 def iter_dfs(node):
16 result = float("-inf")
17 max_sum = [0]
18 stk = [(1, [node, max_sum])]
19 while stk:
20 step, params = stk.pop()
21 if step == 1:
22 node, ret = params
23 if not node:
24 continue
25 ret1, ret2 = [0], [0]
26 stk.append((2, [node, ret1, ret2, ret]))
27 stk.append((1, [node.right, ret2]))
28 stk.append((1, [node.left, ret1]))
29 elif step == 2:
30 node, ret1, ret2, ret = params
31 result = max(result, node.val+max(ret1[0], 0)+max(ret2[0], 0))
32 ret[0] = node.val+max(ret1[0], ret2[0], 0)
33 return result
34
35 return iter_dfs(root)
36
37
38 # Time: O(n)
39 # Space: O(h), h is height of binary tree
40 class Solution2(object):
41 # @param root, a tree node
42 # @return an integer
43 def maxPathSum(self, root):
44 def dfs(node):
45 if not node:
46 return (float("-inf"), 0)
47 max_left, curr_left = dfs(node.left)
48 max_right, curr_right = dfs(node.right)
49 return (max(max_left, max_right, node.val+max(curr_left, 0)+max(curr_right,0)),
50 node.val+max(curr_left, curr_right, 0))
51
52 return dfs(root)[0]
**************

29. Word Ladder II


**************

A transformation sequence from word beginWord to word endWord using a dictionary wordList is a sequence of words beginWord
-> s1 -> s 2 -> ... -> s k such that:

Every adjacent pair of words differs by a single letter.


Every s i for 1 <= i <= k is in wordList. Note that beginWord does not need to be in wordList.
s k == endWord

Given two words, beginWord and endWord, and a dictionary wordList, return all the shortest transformation sequences from
beginWord to endWord, or an empty list if no such sequence exists. Each sequence should be returned as a list of the words
[beginWord, s 1, s 2, ..., s k] .

Example 1:

Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]


Output: [["hit","hot","dot","dog","cog"],["hit","hot","lot","log","cog"]]
Explanation: There are 2 shortest transformation sequences:
"hit" -> "hot" -> "dot" -> "dog" -> "cog"
"hit" -> "hot" -> "lot" -> "log" -> "cog"

Example 2:

Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]


Output: []
Explanation: The endWord "cog" is not in wordList, therefore there is no valid transformation sequence.

Constraints:

1 <= beginWord.length <= 5


endWord.length == beginWord.length
1 <= wordList.length <= 1000
wordList[i].length == beginWord.length
beginWord, endWord, and wordList[i] consist of lowercase English letters.
beginWord != endWord
All the words in wordList are unique.
**************

29. Word Ladder II(C++)


**************

1 // Time: O(b^(d/2)), b is the branch factor of bfs, d is the result depth


2 // Space: O(w * l), w is the number of words, l is the max length of words
3
4 class Solution {
5 public:
6 vector> findLadders(string beginWord, string endWord, vector& wordList) {
7 unordered_set words(cbegin(wordList), cend(wordList));
8 if (!words.count(endWord)) {
9 return {};
10 }
11 unordered_map> tree;
12 unordered_set left = {beginWord}, right = {endWord};
13 bool is_found = false, is_reversed = false;
14 while (!empty(left)) {
15 for (const auto& word : left) {
16 words.erase(word);
17 }
18 unordered_set new_left;
19 for (const auto& word : left) {
20 auto new_word = word;
21 for (int i = 0; i < size(new_word); ++i) {
22 char prev = new_word[i];
23 for (int j = 0; j < 26; ++j) {
24 new_word[i] = 'a' + j;
25 if (!words.count(new_word)) {
26 continue;
27 }
28 if (right.count(new_word)) {
29 is_found = true;
30 } else {
31 new_left.emplace(new_word);
32 }
33 if (!is_reversed) {
34 tree[new_word].emplace(word);
35 } else {
36 tree[word].emplace(new_word);
37 }
38 }
39 new_word[i] = prev;
40 }
41 }
42 if (is_found) {
43 break;
44 }
45 left = move(new_left);
46 if (size(left) > size(right)) {
47 swap(left, right);
48 is_reversed = !is_reversed;
49 }
50 }
51 return backtracking(tree, beginWord, endWord);
52 }
53
54 private:
55 vector> backtracking(
56 const unordered_map>& tree,
57 const string& beginWord,
58 const string& word) {
59
60 vector> result;
61 if (word == beginWord) {
62 result.emplace_back(vector({beginWord}));
63 } else {
64 if (tree.count(word)) {
65 for (const auto& new_word : tree.at(word)) {
66 if (word == new_word) {
67 continue;
68 }
69 auto paths = backtracking(tree, beginWord, new_word);
70 for (auto& path : paths) {
71 path.emplace_back(word);
72 result.emplace_back(move(path));
73 }
74 }
75 }
76 }
77 return result;
78 }
79 };
**************

29. Word Ladder II(Python)


**************

1 # Time: O(b^(d/2)), b is the branch factor of bfs, d is the result depth


2 # Space: O(w * l), w is the number of words, l is the max length of words
3
4 from collections import defaultdict
5 from string import ascii_lowercase
6
7
8 class Solution(object):
9 def findLadders(self, beginWord, endWord, wordList):
10 """
11 :type beginWord: str
12 :type endWord: str
13 :type wordList: List[str]
14 :rtype: List[List[str]]
15 """
16 def backtracking(tree, beginWord, word):
17 return [[beginWord]] if word == beginWord else [path + [word] for new_word in tree[word] for path in backtracking(
18
19 words = set(wordList)
20 if endWord not in words:
21 return []
22 tree = defaultdict(set)
23 is_found, left, right, is_reversed = False, {beginWord}, {endWord}, False
24 while left:
25 words -= left
26 new_left = set()
27 for word in left:
28 for new_word in (word[:i]+c+word[i+1:] for i in xrange(len(beginWord)) for c in ascii_lowercase):
29 if new_word not in words:
30 continue
31 if new_word in right:
32 is_found = True
33 else:
34 new_left.add(new_word)
35 tree[new_word].add(word) if not is_reversed else tree[word].add(new_word)
36 if is_found:
37 break
38 left = new_left
39 if len(left) > len(right):
40 left, right, is_reversed = right, left, not is_reversed
41 return backtracking(tree, beginWord, endWord)
42
43
44 # Time: O(b^d), b is the branch factor of bfs, d is the result depth
45 # Space: O(w * l), w is the number of words, l is the max length of words
46 class Solution2(object):
47 def findLadders(self, beginWord, endWord, wordList):
48 """
49 :type beginWord: str
50 :type endWord: str
51 :type wordList: List[str]
52 :rtype: List[List[str]]
53 """
54 dictionary = set(wordList)
55 result, cur, visited, found, trace = [], [beginWord], set([beginWord]), False, defaultdict(list)
56
57 while cur and not found:
58 for word in cur:
59 visited.add(word)
60
61 next = set()
62 for word in cur:
63 for i in xrange(len(word)):
64 for c in ascii_lowercase:
65 candidate = word[:i] + c + word[i + 1:]
66 if candidate not in visited and candidate in dictionary:
67 if candidate == endWord:
68 found = True
69 next.add(candidate)
70 trace[candidate].append(word)
71 cur = next
72
73 if found:
74 self.backtrack(result, trace, [], endWord)
75
76 return result
77
78 def backtrack(self, result, trace, path, word):
79 if not trace[word]:
80 path.append(word)
81 result.append(path[::-1])
82 path.pop()
83 else:
84 for prev in trace[word]:
85 path.append(word)
86 self.backtrack(result, trace, path, prev)
87 path.pop()
****************************

30. Longest Consecutive Sequence


****************************

Given an unsorted array of integers nums, return the length of the longest consecutive elements sequence.

You must write an algorithm that runs in O(n) time.

Example 1:

Input: nums = [100,4,200,1,3,2]


Output: 4
Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4.

Example 2:

Input: nums = [0,3,7,2,5,8,4,6,0,1]


Output: 9

Constraints:

0 <= nums.length <= 10 5


-109 <= nums[i] <= 10 9
****************************

30. Longest Consecutive Sequence(C++)


****************************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int longestConsecutive(vector& nums) {
7 // unprocessed_entries records the existence of each entry in num.
8 unordered_set unprocessed_entries;
9 for (const auto& num : nums) {
10 unprocessed_entries.emplace(num);
11 }
12
13 int max_interval_size = 0;
14 while (!unprocessed_entries.empty()) {
15 int num = *unprocessed_entries.begin();
16 unprocessed_entries.erase(num);
17
18 // Finds the lower bound of the largest range containing a.
19 int lower_bound = num - 1;
20 while (unprocessed_entries.count(lower_bound)) {
21 unprocessed_entries.erase(lower_bound);
22 --lower_bound;
23 }
24
25 // Finds the upper bound of the largest range containing a.
26 int upper_bound = num + 1;
27 while (unprocessed_entries.count(upper_bound)) {
28 unprocessed_entries.erase(upper_bound);
29 ++upper_bound;
30 }
31 max_interval_size =
32 max(max_interval_size, upper_bound - lower_bound - 1);
33 }
34 return max_interval_size;
35 }
36 };
37
38 // Time: O(n)
39 // Space: O(n)
40 class Solution2 {
41 public:
42 int longestConsecutive(vector &nums) {
43 if (nums.empty()) {
44 return 0;
45 }
46 unordered_map hash;
47 int ans{1};
48 for (const auto& i : nums) {
49 if (!hash[i]) {
50 hash[i] = 1;
51 int leftbound{hash[i - 1]}, rightbound{hash[i + 1]}; // Get neighbor info.
52 hash[i - leftbound] = hash[i + rightbound] = 1 + leftbound + rightbound; // Update left and right bound info.
53 ans = max(ans, 1 + leftbound + rightbound);
54 }
55 }
56 return ans;
57 }
58 };
****************************

30. Longest Consecutive Sequence(Python)


****************************

1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 # @param num, a list of integer
6 # @return an integer
7 def longestConsecutive(self, num):
8 result, lengths = 1, {key: 0 for key in num}
9 for i in num:
10 if lengths[i] == 0:
11 lengths[i] = 1
12 left, right = lengths.get(i - 1, 0), lengths.get(i + 1, 0)
13 length = 1 + left + right
14 result, lengths[i - left], lengths[i + right] = max(result, length), length, length
15 return result
16
**************************

31. Palindrome Partitioning II


**************************

Given a string s , partition s such that every substring of the partition is a palindrome.

Return the minimum cuts needed for a palindrome partitioning of s .

Example 1:

Input: s = "aab"
Output: 1
Explanation: The palindrome partitioning ["aa","b"] could be produced using 1 cut.

Example 2:

Input: s = "a"
Output: 0

Example 3:

Input: s = "ab"
Output: 1

Constraints:

1 <= s.length <= 2000


s consists of lower-case English letters only.
**************************

31. Palindrome Partitioning II(Python)


**************************

1 # Time: O(n^2)
2 # Space: O(n^2)
3
4 class Solution(object):
5 # @param s, a string
6 # @return an integer
7 def minCut(self, s):
8 lookup = [[False for j in xrange(len(s))] for i in xrange(len(s))]
9 mincut = [len(s) - 1 - i for i in xrange(len(s) + 1)]
10
11 for i in reversed(xrange(len(s))):
12 for j in xrange(i, len(s)):
13 if s[i] == s[j] and (j - i < 2 or lookup[i + 1][j - 1]):
14 lookup[i][j] = True
15 mincut[i] = min(mincut[i], mincut[j + 1] + 1)
16
17 return mincut[0]
18
*****

32. Candy
*****

There are n children standing in a line. Each child is assigned a rating value given in the integer arrayratings.

You are giving candies to these children subjected to the following requirements:

Each child must have at least one candy.


Children with a higher rating get more candies than their neighbors.

Return the minimum number of candies you need to have to distribute the candies to the children.

Example 1:

Input: ratings = [1,0,2]


Output: 5
Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.

Example 2:

Input: ratings = [1,2,2]


Output: 4
Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively.
The third child gets 1 candy because it satisfies the above two conditions.

Constraints:

n == ratings.length
1 <= n <= 2 * 10 4
0 <= ratings[i] <= 2 * 10 4
*****

32. Candy(C++)
*****

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int candy(vector& ratings) {
7 vector candies(ratings.size(), 1);
8 for (int i = 1; i < ratings.size(); ++i) {
9 if (ratings[i] > ratings[i - 1]) {
10 candies[i] = candies[i - 1] + 1;
11 }
12 }
13 for (int i = ratings.size() - 2; i >= 0; --i) {
14 if (ratings[i] > ratings[i + 1] && candies[i] <= candies[i + 1]) {
15 candies[i] = candies[i + 1] + 1;
16 }
17 }
18 return accumulate(candies.cbegin(), candies.cend(), 0);
19 }
20 };
*****

32. Candy(Python)
*****

1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 # @param ratings, a list of integer
6 # @return an integer
7 def candy(self, ratings):
8 candies = [1 for _ in xrange(len(ratings))]
9 for i in xrange(1, len(ratings)):
10 if ratings[i] > ratings[i - 1]:
11 candies[i] = candies[i - 1] + 1
12
13 for i in reversed(xrange(1, len(ratings))):
14 if ratings[i - 1] > ratings[i] and candies[i - 1] <= candies[i]:
15 candies[i - 1] = candies[i] + 1
16
17 return sum(candies)
*************

33. Word Break II


*************

Given a string s and a dictionary of strings wordDict , add spaces in s to construct a sentence where each word is a valid
dictionary word. Return all such possible sentences in any order.

Note that the same word in the dictionary may be reused multiple times in the segmentation.

Example 1:

Input: s = "catsanddog", wordDict = ["cat","cats","and","sand","dog"]


Output: ["cats and dog","cat sand dog"]

Example 2:

Input: s = "pineapplepenapple", wordDict = ["apple","pen","applepen","pine","pineapple"]


Output: ["pine apple pen apple","pineapple pen apple","pine applepen apple"]
Explanation: Note that you are allowed to reuse a dictionary word.

Example 3:

Input: s = "catsandog", wordDict = ["cats","dog","sand","and","cat"]


Output: []

Constraints:

1 <= s.length <= 20


1 <= wordDict.length <= 1000
1 <= wordDict[i].length <= 10
s and wordDict[i] consist of only lowercase English letters.
All the strings of wordDict are unique.
*************

33. Word Break II(C++)


*************

1 // Time: O(n * l^2 + n * r), l is the max length of the words,


2 // r is the number of the results.
3 // Space: O(n^2)
4
5 class Solution {
6 public:
7 vector wordBreak(string s, unordered_set& wordDict) {
8 const int n = s.length();
9
10 size_t max_len = 0;
11 for (const auto& str: wordDict) {
12 max_len = max(max_len, str.length());
13 }
14
15 vector canBreak(n + 1, false);
16 vector> valid(n, vector(n, false));
17 canBreak[0] = true;
18 for (int i = 1; i <= n; ++i) {
19 for (int l = 1; l <= max_len && i - l >= 0; ++l) {
20 if (canBreak[i - l] && wordDict.count(s.substr(i - l, l))) {
21 valid[i - l][i - 1] = true;
22 canBreak[i] = true;
23 }
24 }
25 }
26
27 vector result, path;
28 if (canBreak[n]) {
29 wordBreakHelper(s, valid, 0, &path, &result);
30 }
31 return result;
32 }
33
34
35 void wordBreakHelper(const string& s, const vector>& valid,
36 int start, vector *path, vector *result) {
37 if (start == s.length()) {
38 string tmp;
39 for (const auto& str : *path) {
40 tmp += str;
41 tmp += " ";
42 }
43 tmp.pop_back();
44 result->emplace_back(move(tmp));
45 return;
46 }
47 for (int i = start; i < s.length(); ++i) {
48 if (valid[start][i]) {
49 path->emplace_back(s.substr(start, i + 1 - start));
50 wordBreakHelper(s, valid, i + 1, path, result);
51 path->pop_back();
52 }
53 }
54 }
55 };
*************

33. Word Break II(Python)


*************

1 # Time: O(n * l^2 + n * r), l is the max length of the words,


2 # r is the number of the results.
3 # Space: O(n^2)
4
5 class Solution(object):
6 def wordBreak(self, s, wordDict):
7 """
8 :type s: str
9 :type wordDict: Set[str]
10 :rtype: List[str]
11 """
12 n = len(s)
13
14 max_len = 0
15 for string in wordDict:
16 max_len = max(max_len, len(string))
17
18 can_break = [False for _ in xrange(n + 1)]
19 valid = [[False] * n for _ in xrange(n)]
20 can_break[0] = True
21 for i in xrange(1, n + 1):
22 for l in xrange(1, min(i, max_len) + 1):
23 if can_break[i-l] and s[i-l:i] in wordDict:
24 valid[i-l][i-1] = True
25 can_break[i] = True
26
27 result = []
28 if can_break[-1]:
29 self.wordBreakHelper(s, valid, 0, [], result)
30 return result
31
32 def wordBreakHelper(self, s, valid, start, path, result):
33 if start == len(s):
34 result.append(" ".join(path))
35 return
36 for i in xrange(start, len(s)):
37 if valid[start][i]:
38 path += [s[start:i+1]]
39 self.wordBreakHelper(s, valid, i + 1, path, result)
40 path.pop()
41
42
*******************************

34. Binary Tree Postorder Traversal


*******************************

Given the root of a binary tree, return the postorder traversal of its nodes' values.

Example 1:

Input: root = [1,null,2,3]


Output: [3,2,1]

Example 2:

Input: root = []
Output: []

Example 3:

Input: root = [1]


Output: [1]

Example 4:

Input: root = [1,2]


Output: [2,1]
Example 5:

Input: root = [1,null,2]


Output: [2,1]

Constraints:

The number of the nodes in the tree is in the range[0, 100].


-100 <= Node.val <= 100

Follow up: Recursive solution is trivial, could you do it iteratively?


*******************************

34. Binary Tree Postorder Traversal(C++)


*******************************

1 // Time: O(n)
2 // Space: O(1)
3
4 /**
5 * Definition for a binary tree node.
6 * struct TreeNode {
7 * int val;
8 * TreeNode *left;
9 * TreeNode *right;
10 * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
11 * };
12 */
13 class Solution {
14 public:
15 vector postorderTraversal(TreeNode* root) {
16 vector res;
17 TreeNode dummy(INT_MIN);
18 dummy.left = root;
19 auto *cur = &dummy;
20 while (cur) {
21 if (!cur->left) {
22 cur = cur->right;
23 } else {
24 auto *node = cur->left;
25 while (node->right && node->right != cur) {
26 node = node->right;
27 }
28 if (!node->right) {
29 node->right = cur;
30 cur = cur->left;
31 } else {
32 const auto& v = trace_back(cur->left, node);
33 res.insert(res.end(), v.cbegin(), v.cend());
34 node->right = nullptr;
35 cur = cur->right;
36 }
37 }
38 }
39 return res;
40 }
41
42 private:
43 vector trace_back(const TreeNode *from, const TreeNode *to) {
44 vector res;
45 auto *cur = from;
46 while (cur != to) {
47 res.emplace_back(cur->val);
48 cur = cur->right;
49 }
50 res.emplace_back(to->val);
51 reverse(res.begin(), res.end());
52 return res;
53 }
54 };
55
56 // Time: O(n)
57 // Space: O(h)
58 class Solution2 {
59 public:
60 vector postorderTraversal(TreeNode* root) {
61 vector res;
62 stack> s;
63 s.emplace(root, false);
64 while (!s.empty()) {
65 bool visited;
66 tie(root, visited) = s.top();
67 s.pop();
68 if (root == nullptr) {
69 continue;
70 }
71 if (visited) {
72 res.emplace_back(root->val);
73 } else {
74 s.emplace(root, true);
75 s.emplace(root->right, false);
76 s.emplace(root->left, false);
77 }
78 }
79 return res;
80 }
81 };
*******************************

34. Binary Tree Postorder Traversal(Python)


*******************************
1 # Time: O(n)
2 # Space: O(1)
3
4 class TreeNode(object):
5 def __init__(self, x):
6 self.val = x
7 self.left = None
8 self.right = None
9
10
11 # Morris Traversal Solution
12 class Solution(object):
13 def postorderTraversal(self, root):
14 """
15 :type root: TreeNode
16 :rtype: List[int]
17 """
18 dummy = TreeNode(0)
19 dummy.left = root
20 result, cur = [], dummy
21 while cur:
22 if cur.left is None:
23 cur = cur.right
24 else:
25 node = cur.left
26 while node.right and node.right != cur:
27 node = node.right
28
29 if node.right is None:
30 node.right = cur
31 cur = cur.left
32 else:
33 result += self.traceBack(cur.left, node)
34 node.right = None
35 cur = cur.right
36
37 return result
38
39 def traceBack(self, frm, to):
40 result, cur = [], frm
41 while cur is not to:
42 result.append(cur.val)
43 cur = cur.right
44 result.append(to.val)
45 result.reverse()
46 return result
47
48
49 # Time: O(n)
50 # Space: O(h)
51 # Stack Solution
52 class Solution2(object):
53 def postorderTraversal(self, root):
54 """
55 :type root: TreeNode
56 :rtype: List[int]
57 """
58 result, stack = [], [(root, False)]
59 while stack:
60 root, is_visited = stack.pop()
61 if root is None:
62 continue
63 if is_visited:
64 result.append(root.val)
65 else:
66 stack.append((root, True))
67 stack.append((root.right, False))
68 stack.append((root.left, False))
69 return result
70
*********

35. LRU Cache


*********

Design a data structure that follows the constraints of aLeast Recently Used (LRU) cache.

Implement the LRUCache class:

LRUCache(int capacity) Initialize the LRU cache with positive size capacity .
int get(int key) Return the value of the key if the key exists, otherwise return -1.
void put(int key, int value) Update the value of the key if the key exists. Otherwise, add the key-value pair to the cache. If the
number of keys exceeds the capacity from this operation, evict the least recently used key.

The functions get and put must each run in O(1) average time complexity.

Example 1:

Input
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
Output
[null, null, null, 1, null, -1, null, -1, 3, 4]

Explanation
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // cache is {1=1}
lRUCache.put(2, 2); // cache is {1=1, 2=2}
lRUCache.get(1); // return 1
lRUCache.put(3, 3); // LRU key was 2, evicts key 2, cache is {1=1, 3=3}
lRUCache.get(2); // returns -1 (not found)
lRUCache.put(4, 4); // LRU key was 1, evicts key 1, cache is {4=4, 3=3}
lRUCache.get(1); // return -1 (not found)
lRUCache.get(3); // return 3
lRUCache.get(4); // return 4

Constraints:

1 <= capacity <= 3000


0 <= key <= 10 4
0 <= value <= 10 5
At most 2 * 105 calls will be made to get and put.
*********

35. LRU Cache(C++)


*********

1 // Time: O(1), per operation.


2 // Space: O(k), k is the capacity of cache.
3
4 #include
5
6 class LRUCache {
7 public:
8 LRUCache(int capacity) : capa_(capacity) {
9 }
10
11 int get(int key) {
12 if (!map_.count(key)) {
13 return -1;
14 }
15 // It key exists, update it.
16 const auto value = map_[key]->second;
17 update(key, value);
18 return value;
19 }
20
21 void put(int key, int value) {
22 if (capa_ <= 0) {
23 return;
24 }
25
26 // If cache is full while inserting, remove the last one.
27 if (!map_.count(key) && list_.size() == capa_) {
28 auto del = list_.front(); list_.pop_front();
29 map_.erase(del.first);
30 }
31 update(key, value);
32 }
33
34 private:
35 list> list_; // key, value
36 unordered_map>::iterator> map_; // key, list iterator
37 int capa_;
38
39 // Update (key, iterator of (key, value)) pair
40 void update(int key, int value) {
41 auto it = map_.find(key);
42 if (it != map_.end()) {
43 list_.erase(it->second);
44 }
45 list_.emplace_back(key, value);
46 map_[key] = prev(end(list_));
47 }
48 };
49
50 // Time: O(1), per operation.
51 // Space: O(k), k is the capacity of cache.
52 class LRUCache2 {
53 public:
54 LRUCache2(int capacity) : capa_(capacity) {
55 }
56
57 int get(int key) {
58 if (!map_.count(key)) {
59 return -1;
60 }
61 // It key exists, update it.
62 const auto value = map_[key]->second;
63 update(key, value);
64 return value;
65 }
66
67 void put(int key, int value) {
68 if (capa_ <= 0) {
69 return;
70 }
71
72 // If cache is full while inserting, remove the last one.
73 if (!map_.count(key) && list_.size() == capa_) {
74 auto del = list_.back(); list_.pop_back();
75 map_.erase(del.first);
76 }
77 update(key, value);
78 }
79
80 private:
81 list> list_; // key, value
82 unordered_map>::iterator> map_; // key, list iterator
83 int capa_;
84
85 // Update (key, iterator of (key, value)) pair
86 void update(int key, int value) {
87 auto it = map_.find(key);
88 if (it != map_.end()) {
89 list_.erase(it->second);
90 }
91 list_.emplace_front(key, value);
92 map_[key] = list_.begin();
93 }
94 };
*********

35. LRU Cache(Python)


*********

1 # Time: O(1), per operation.


2 # Space: O(k), k is the capacity of cache.
3
4 import collections
5
6
7 # using OrderedDict
8 class LRUCache(object):
9 def __init__(self, capacity):
10 self.cache = collections.OrderedDict()
11 self.capacity = capacity
12
13 def get(self, key):
14 if key not in self.cache:
15 return -1
16 val = self.cache[key]
17 self.__update(key, val)
18 return val
19
20 def put(self, key, val):
21 if key not in self.cache and len(self.cache) == self.capacity:
22 self.cache.popitem(last=False)
23 self.__update(key, val)
24
25 def __update(self, key, val):
26 if key in self.cache:
27 del self.cache[key]
28 self.cache[key] = val
29
30
31 # Time: O(1), per operation.
32 # Space: O(k), k is the capacity of cache.
33
34
35 class ListNode(object):
36 def __init__(self, key, val):
37 self.val = val
38 self.key = key
39 self.next = None
40 self.prev = None
41
42 class LinkedList(object):
43 def __init__(self):
44 self.head = None
45 self.tail = None
46
47 def insert(self, node):
48 node.next, node.prev = None, None # avoid dirty node
49 if self.head is None:
50 self.head = node
51 else:
52 self.tail.next = node
53 node.prev = self.tail
54 self.tail = node
55
56 def delete(self, node):
57 if node.prev:
58 node.prev.next = node.next
59 else:
60 self.head = node.next
61 if node.next:
62 node.next.prev = node.prev
63 else:
64 self.tail = node.prev
65 node.next, node.prev = None, None # make node clean
66
67 class LRUCache2(object):
68
69 def __init__(self, capacity):
70 self.list = LinkedList()
71 self.dict = {}
72 self.capacity = capacity
73
74 def get(self, key):
75 if key not in self.dict:
76 return -1
77 val = self.dict[key].val
78 self.__update(key, val)
79 return val
80
81 def put(self, key, val):
82 if key not in self.dict and len(self.dict) == self.capacity:
83 del self.dict[self.list.head.key]
84 self.list.delete(self.list.head)
85 self.__update(key, val)
86
87 def __update(self, key, val):
88 if key in self.dict:
89 self.list.delete(self.dict[key])
90 node = ListNode(key, val)
91 self.list.insert(node)
92 self.dict[key] = node
********************

36. Max Points on a Line


********************

Given an array of points where points[i] = [x i, y i] represents a point on the X-Y plane, return the maximum number of points that
lie on the same straight line.

Example 1:

Input: points = [[1,1],[2,2],[3,3]]


Output: 3

Example 2:

Input: points = [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]


Output: 4

Constraints:

1 <= points.length <= 300


points[i].length == 2
-104 <= x i, y i <= 104
All the points are unique.
********************

36. Max Points on a Line(C++)


********************

1 // Time: O(n^2)
2 // Space: O(n)
3
4 /**
5 * Definition for a point.
6 * struct Point {
7 * int x;
8 * int y;
9 * Point() : x(0), y(0) {}
10 * Point(int a, int b) : x(a), y(b) {}
11 * };
12 */
13 class Solution {
14 public:
15 int maxPoints(vector& points) {
16 int max_points = 0;
17 for (int i = 0; i < points.size(); ++i) {
18 unordered_map slope_count;
19 const auto& start = points[i];
20 int same = 1;
21
22 for (int j = i + 1; j < points.size(); ++j) {
23 const auto& end = points[j];
24 if (start.x == end.x && start.y == end.y) {
25 ++same;
26 } else {
27 auto slope = numeric_limits::max();
28 if (start.x - end.x != 0) {
29 slope = (start.y - end.y) * 1.0 / (start.x - end.x);
30 }
31 ++slope_count[slope];
32 }
33 }
34
35 int current_max = same;
36 for (const auto& kvp : slope_count) {
37 current_max = max(current_max, kvp.second + same);
38 }
39 max_points = max(max_points, current_max);
40 }
41
42 return max_points;
43 }
44 };
********************

36. Max Points on a Line(Python)


********************

1 # Time: O(n^2)
2 # Space: O(n)
3
4 import collections
5
6
7 # Definition for a point
8 class Point(object):
9 def __init__(self, a=0, b=0):
10 self.x = a
11 self.y = b
12
13 class Solution(object):
14 def maxPoints(self, points):
15 """
16 :type points: List[Point]
17 :rtype: int
18 """
19 max_points = 0
20 for i, start in enumerate(points):
21 slope_count, same = collections.defaultdict(int), 1
22 for j in xrange(i + 1, len(points)):
23 end = points[j]
24 if start.x == end.x and start.y == end.y:
25 same += 1
26 else:
27 slope = float("inf")
28 if start.x - end.x != 0:
29 slope = (start.y - end.y) * 1.0 / (start.x - end.x)
30 slope_count[slope] += 1
31
32 current_max = same
33 for slope in slope_count:
34 current_max = max(current_max, slope_count[slope] + same)
35
36 max_points = max(max_points, current_max)
37
38 return max_points
39
***************************************

37. Find Minimum in Rotated Sorted Array II


***************************************

Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums =
[0,1,4,4,5,6,7] might become:

[4,5,6,7,0,1,4] if it was rotated 4 times.


[0,1,4,4,5,6,7] if it was rotated 7 times.

Notice that rotating an array [a[0], a[1], a[2], ..., a[n-1]] 1 time results in the array[a[n-1], a[0], a[1], a[2], ..., a[n-2]].

Given the sorted rotated array nums that may contain duplicates, return the minimum element of this array.

You must decrease the overall operation steps as much as possible.

Example 1:

Input: nums = [1,3,5]


Output: 1

Example 2:

Input: nums = [2,2,2,0,1]


Output: 0

Constraints:

n == nums.length
1 <= n <= 5000
-5000 <= nums[i] <= 5000
nums is sorted and rotated between 1 and n times.

Follow up: This problem is similar to Find Minimum in Rotated Sorted Array, but nums may contain duplicates. Would this
affect the runtime complexity? How and why?
***************************************

37. Find Minimum in Rotated Sorted Array II(C++)


***************************************

1 // Time: O(logn)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int findMin(vector& nums) {
7 int left = 0, right = nums.size() - 1;
8
9 // Find min left s.t. nums[left] < nums[left'].
10 while (left < right && nums[left] >= nums[right]) {
11 int mid = left + (right - left) / 2;
12 if (nums[mid] == nums[left]) {
13 ++left;
14 } else if (nums[mid] < nums[left]) {
15 right = mid;
16 } else {
17 left = mid + 1;
18 }
19 }
20
21 return nums[left];
22 }
23 };
***************************************

37. Find Minimum in Rotated Sorted Array II(Python)


***************************************

1 # Time: O(logn) ~ O(n)


2 # Space: O(1)
3
4 class Solution(object):
5 def findMin(self, nums):
6 """
7 :type nums: List[int]
8 :rtype: int
9 """
10 left, right = 0, len(nums) - 1
11 while left < right:
12 mid = left + (right - left) / 2
13
14 if nums[mid] == nums[right]:
15 right -= 1
16 elif nums[mid] < nums[right]:
17 right = mid
18 else:
19 left = mid + 1
20
21 return nums[left]
22
23
24 class Solution2(object):
25 def findMin(self, nums):
26 """
27 :type nums: List[int]
28 :rtype: int
29 """
30 left, right = 0, len(nums) - 1
31 while left < right and nums[left] >= nums[right]:
32 mid = left + (right - left) / 2
33
34 if nums[mid] == nums[left]:
35 left += 1
36 elif nums[mid] < nums[left]:
37 right = mid
38 else:
39 left = mid + 1
40
41 return nums[left]
42
43
******************************************************

38. Read N Characters Given Read4 II - Call multiple


times
******************************************************

Given a file and assume that you can only read the file using a given methodread4, implement a method read to read n
characters. Your method read may be called multiple times.

Method read4:

The API read4 reads four consecutive characters from file, then writes those characters into the buffer arraybuf4.

The return value is the number of actual characters read.

Note that read4() has its own file pointer, much likeFILE *fp in C.

Definition of read4:

Parameter: char[] buf4


Returns: int

buf4[] is a destination, not a source. The results from read4 will be copied to buf4[].

Below is a high-level example of how read4 works:

File file("abcde"); // File is "abcde", initially file pointer (fp) points to 'a'
char[] buf4 = new char[4]; // Create buffer with enough space to store characters
read4(buf4); // read4 returns 4. Now buf4 = "abcd", fp points to 'e'
read4(buf4); // read4 returns 1. Now buf4 = "e", fp points to end of file
read4(buf4); // read4 returns 0. Now buf4 = "", fp points to end of file

Method read:

By using the read4 method, implement the method read that reads n characters from file and store it in the buffer array buf.
Consider that you cannot manipulate file directly.
The return value is the number of actual characters read.

Definition of read:

Parameters: char[] buf, int n


Returns: int

buf[] is a destination, not a source. You will need to write the results to buf[].

Note:

Consider that you cannot manipulate the file directly. The file is only accessible forread4 but not for read.
The read function may be called multiple times.
Please remember to RESET your class variables declared in Solution, as static/class variables are persisted across
multiple test cases. Please see here for more details.
You may assume the destination buffer array, buf, is guaranteed to have enough space for storing n characters.
It is guaranteed that in a given test case the same bufferbuf is called by read.

Example 1:

Input: file = "abc", queries = [1,2,1]


Output: [1,2,0]
Explanation: The test case represents the following scenario:
File file("abc");
Solution sol;
sol.read(buf, 1); // After calling your read method, buf should contain "a". We read a total of 1 character from the file, so return 1.
sol.read(buf, 2); // Now buf should contain "bc". We read a total of 2 characters from the file, so return 2.
sol.read(buf, 1); // We have reached the end of file, no more characters can be read. So return 0.
Assume buf is allocated and guaranteed to have enough space for storing all characters from the file.

Example 2:

Input: file = "abc", queries = [4,1]


Output: [3,0]
Explanation: The test case represents the following scenario:
File file("abc");
Solution sol;
sol.read(buf, 4); // After calling your read method, buf should contain "abc". We read a total of 3 characters from the file, so return 3.
sol.read(buf, 1); // We have reached the end of file, no more characters can be read. So return 0.

Constraints:

1 <= file.length <= 500


file consist of English letters and digits.
1 <= queries.length <= 10
1 <= queries[i] <= 500
******************************************************

38. Read N Characters Given Read4 II - Call multiple


times(C++)
******************************************************

1 // Time: O(n)
2 // Space: O(1)
3
4 // Forward declaration of the read4 API.
5 int read4(char *buf);
6
7 // shorter version of Solution2
8 class Solution {
9 public:
10 /**
11 * @param buf Destination buffer
12 * @param n Maximum number of characters to read
13 * @return The number of characters read
14 */
15 int read(char *buf, int n) {
16 int i = 0;
17 while (i < n && (i4_ < n4_ || (i4_ = 0) < (n4_ = read4(buf4_)))) {
18 buf[i++] = buf4_[i4_++];
19 }
20 return i;
21 }
22
23 private:
24 char buf4_[4];
25 int i4_ = 0, n4_ = 0;
26 };
27
28 // Time: O(n)
29 // Space: O(1)
30 class Solution2 {
31 public:
32 /**
33 * @param buf Destination buffer
34 * @param n Maximum number of characters to read
35 * @return The number of characters read
36 */
37 int read(char *buf, int n) {
38 int i = 0;
39 while (i < n) {
40 if (i4_ < n4_) { // Any characters in buf4.
41 buf[i++] = buf4_[i4_++];
42 } else if (n4_ = read4(buf4_)) { // Read more characters.
43 i4_ = 0;
44 } else { // Buffer has been empty.
45 break;
46 }
47 }
48 return i;
49 }
50
51 private:
52 char buf4_[4];
53 int i4_ = 0, n4_ = 0;
54 };
******************************************************

38. Read N Characters Given Read4 II - Call multiple


times(Python)
******************************************************

1 # Time: O(n)
2 # Space: O(1)
3
4 def read4(buf):
5 global file_content
6 i = 0
7 while i < len(file_content) and i < 4:
8 buf[i] = file_content[i]
9 i += 1
10
11 if len(file_content) > 4:
12 file_content = file_content[4:]
13 else:
14 file_content = ""
15 return i
16
17 # The read4 API is already defined for you.
18 # @param buf, a list of characters
19 # @return an integer
20 # def read4(buf):
21
22 class Solution(object):
23 def __init__(self):
24 self.__buf4 = [''] * 4
25 self.__i4 = 0
26 self.__n4 = 0
27
28 def read(self, buf, n):
29 """
30 :type buf: Destination buffer (List[str])
31 :type n: Maximum number of characters to read (int)
32 :rtype: The number of characters read (int)
33 """
34 i = 0
35 while i < n:
36 if self.__i4 < self.__n4: # Any characters in buf4.
37 buf[i] = self.__buf4[self.__i4]
38 i += 1
39 self.__i4 += 1
40 else:
41 self.__n4 = read4(self.__buf4) # Read more characters.
42 if self.__n4:
43 self.__i4 = 0
44 else: # Buffer has been empty.
45 break
46
47 return i
48
******************************************************

39. Longest Substring with At Most Two Distinct


Characters
******************************************************

Given a string s , return the length of the longest substring that contains at most two distinct characters.

Example 1:

Input: s = "eceba"
Output: 3
Explanation: The substring is "ece" which its length is 3.

Example 2:

Input: s = "ccaabbb"
Output: 5
Explanation: The substring is "aabbb" which its length is 5.

Constraints:

1 <= s.length <= 104


s consists of English letters.
******************************************************

39. Longest Substring with At Most Two Distinct


Characters(C++)
******************************************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int lengthOfLongestSubstringTwoDistinct(string s) {
7 const int k = 2;
8 int longest = 0, start = 0, distinct_count = 0;
9 array visited = {0};
10 for (int i = 0; i < s.length(); ++i) {
11 if (visited[s[i]] == 0) {
12 ++distinct_count;
13 }
14 ++visited[s[i]];
15 while (distinct_count > k) {
16 --visited[s[start]];
17 if (visited[s[start]] == 0) {
18 --distinct_count;
19 }
20 ++start;
21 }
22 longest = max(longest, i - start + 1);
23 }
24 return longest;
25 }
26 };
******************************************************

39. Longest Substring with At Most Two Distinct


Characters(Python)
******************************************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 # @param s, a string
6 # @return an integer
7 def lengthOfLongestSubstringTwoDistinct(self, s):
8 longest, start, distinct_count, visited = 0, 0, 0, [0 for _ in xrange(256)]
9 for i, char in enumerate(s):
10 if visited[ord(char)] == 0:
11 distinct_count += 1
12 visited[ord(char)] += 1
13 while distinct_count > 2:
14 visited[ord(s[start])] -= 1
15 if visited[ord(s[start])] == 0:
16 distinct_count -= 1
17 start += 1
18 longest = max(longest, i - start + 1)
19 return longest
20
21
22 # Time: O(n)
23 # Space: O(1)
24 from collections import Counter
25
26
27 class Solution2(object):
28 def lengthOfLongestSubstringTwoDistinct(self, s):
29 """
30 :type s: str
31 :rtype: int
32 """
33 counter = Counter()
34 left, max_length = 0, 0
35 for right, char in enumerate(s):
36 counter[char] += 1
37 while len(counter) > 2:
38 counter[s[left]] -= 1
39 if counter[s[left]] == 0:
40 del counter[s[left]]
41 left += 1
42 max_length = max(max_length, right-left+1)
43 return max_length
***********

40. Maximum Gap


***********

Given an integer array nums, return the maximum difference between two successive elements in its sorted form. If the array
contains less than two elements, return 0.

You must write an algorithm that runs in linear time and uses linear extra space.

Example 1:

Input: nums = [3,6,9,1]


Output: 3
Explanation: The sorted form of the array is [1,3,6,9], either (3,6) or (6,9) has the maximum difference 3.

Example 2:

Input: nums = [10]


Output: 0
Explanation: The array contains less than 2 elements, therefore return 0.

Constraints:

1 <= nums.length <= 10 5


0 <= nums[i] <= 10 9
***********

40. Maximum Gap(C++)


***********

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 struct Bucket {
7 int max = numeric_limits::min();
8 int min = numeric_limits::max();
9 };
10
11 int maximumGap(vector& nums) {
12 if (nums.size() < 2) {
13 return 0;
14 }
15
16 // Init bucket.
17 int max_val = *max_element(nums.cbegin(), nums.cend());
18 int min_val = *min_element(nums.cbegin(), nums.cend());
19 int gap = max(1, static_cast((max_val - min_val) /
20 (nums.size() - 1)));
21 vector buckets((max_val - min_val) / gap + 1);
22
23 // Find the bucket where the n should be put.
24 for (const auto& n : nums) {
25 // min_val / max_val is in the first / last bucket.
26 if (n == max_val || n == min_val) {
27 continue;
28 }
29 int i = (n - min_val) / gap;
30 buckets[i].min = min(buckets[i].min, n);
31 buckets[i].max = max(buckets[i].max, n);
32 }
33
34 // Maximum gap should not be smaller than any gap inside the bucket.
35 // i.e. max_gap >= (max_val - min_val) / (count - 1)
36 // Thus, only count each bucket gap between the first and the last bucket.
37 int max_gap = 0, pre_bucket_max = min_val;
38 for (const auto& bucket : buckets) {
39 if (bucket.min != numeric_limits::max()) {
40 max_gap = max(max_gap, bucket.min - pre_bucket_max);
41 pre_bucket_max = bucket.max;
42 }
43 }
44 // Count the last bucket.
45 max_gap = max(max_gap, max_val - pre_bucket_max);
46
47 return max_gap;
48 }
49 };
50
51 // Time: O(nlogn)
52 // Space: O(n)
53 class Solution2 {
54 public:
55 int maximumGap(vector& nums) {
56 if (nums.size() < 2) {
57 return 0;
58 }
59
60 // Init bucket.
61 int max_val = *max_element(nums.cbegin(), nums.cend());
62 int min_val = *min_element(nums.cbegin(), nums.cend());
63 int gap = max(1, static_cast((max_val - min_val) /
64 (nums.size() - 1)));
65 map> bucket;
66 using ValueType = enum {MIN, MAX};
67
68 // Find the bucket where the n should be put.
69 for (const auto& n : nums) {
70 // min_val / max_val is in the first / last bucket.
71 if (n == max_val || n == min_val) {
72 continue ;
73 }
74 int i = (n - min_val) / gap;
75 bucket[i][MIN] = min(!bucket[i][MIN] ? numeric_limits::max() :
76 bucket[i][MIN], n);
77 bucket[i][MAX] = max(!bucket[i][MAX] ? numeric_limits::min() :
78 bucket[i][MAX], n);
79 }
80
81 // Count each bucket gap between the first and the last bucket.
82 int max_gap = 0, pre_bucket_max = min_val;
83 for (auto& kvp : bucket) {
84 max_gap = max(max_gap, kvp.second[MIN] - pre_bucket_max);
85 pre_bucket_max = (kvp.second)[MAX];
86 }
87 // Count the last bucket.
88 max_gap = max(max_gap, max_val - pre_bucket_max);
89
90 return max_gap;
91 }
92 };
***********

40. Maximum Gap(Python)


***********
1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 def maximumGap(self, nums):
6 """
7 :type nums: List[int]
8 :rtype: int
9 """
10 if len(nums) < 2:
11 return 0
12
13 # Init bucket.
14 max_val, min_val = max(nums), min(nums)
15 gap = max(1, (max_val - min_val) / (len(nums) - 1))
16 bucket_size = (max_val - min_val) / gap + 1
17 bucket = [{'min':float("inf"), 'max':float("-inf")} \
18 for _ in xrange(bucket_size)]
19
20 # Find the bucket where the n should be put.
21 for n in nums:
22 # min_val / max_val is in the first / last bucket.
23 if n in (max_val, min_val):
24 continue
25 i = (n - min_val) / gap
26 bucket[i]['min'] = min(bucket[i]['min'], n)
27 bucket[i]['max'] = max(bucket[i]['max'], n)
28
29 # Count each bucket gap between the first and the last bucket.
30 max_gap, pre_bucket_max = 0, min_val
31 for i in xrange(bucket_size):
32 # Skip the bucket it empty.
33 if bucket[i]['min'] == float("inf") and \
34 bucket[i]['max'] == float("-inf"):
35 continue
36 max_gap = max(max_gap, bucket[i]['min'] - pre_bucket_max)
37 pre_bucket_max = bucket[i]['max']
38 # Count the last bucket.
39 max_gap = max(max_gap, max_val - pre_bucket_max)
40
41 return max_gap
42
43
44 # Time: O(nlogn)
45 # Space: O(n)
46 class Solution2(object):
47 def maximumGap(self, nums):
48 """
49 :type nums: List[int]
50 :rtype: int
51 """
52
53 if len(nums) < 2:
54 return 0
55
56 nums.sort()
57 pre = nums[0]
58 max_gap = float("-inf")
59
60 for i in nums:
61 max_gap = max(max_gap, i - pre)
62 pre = i
63 return max_gap
64
65
************

41. Dungeon Game


************

The demons had captured the princess and imprisoned her in the bottom-right corner of a dungeon . The dungeon consists of
m x n rooms laid out in a 2D grid. Our valiant knight was initially positioned inthe top-left room and must fight his way
through dungeon to rescue the princess.

The knight has an initial health point represented by a positive integer. If at any point his health point drops to0 or below, he
dies immediately.

Some of the rooms are guarded by demons (represented by negative integers), so the knight loses health upon entering
these rooms; other rooms are either empty (represented as 0) or contain magic orbs that increase the knight's health
(represented by positive integers).

To reach the princess as quickly as possible, the knight decides to move onlyrightward or downward in each step.

Return the knight's minimum initial health so that he can rescue the princess.

Note that any room can contain threats or power-ups, even the first room the knight enters and the bottom-right room where
the princess is imprisoned.

Example 1:

Input: dungeon = [[-2,-3,3],[-5,-10,1],[10,30,-5]]


Output: 7
Explanation: The initial health of the knight must be at least 7 if he follows the optimal path: RIGHT-> RIGHT -> DOWN -> DOWN.

Example 2:

Input: dungeon = [[0]]


Output: 1

Constraints:

m == dungeon.length
n == dungeon[i].length
1 <= m, n <= 200
-1000 <= dungeon[i][j] <= 1000
************

41. Dungeon Game(Python)


************
1 # Time: O(m * n)
2 # Space: O(m + n)
3
4 class Solution(object):
5 # @param dungeon, a list of lists of integers
6 # @return a integer
7 def calculateMinimumHP(self, dungeon):
8 DP = [float("inf") for _ in dungeon[0]]
9 DP[-1] = 1
10
11 for i in reversed(xrange(len(dungeon))):
12 DP[-1] = max(DP[-1] - dungeon[i][-1], 1)
13 for j in reversed(xrange(len(dungeon[i]) - 1)):
14 min_HP_on_exit = min(DP[j], DP[j + 1])
15 DP[j] = max(min_HP_on_exit - dungeon[i][j], 1)
16
17 return DP[0]
18
19 # Time: O(m * n logk), where k is the possible maximum sum of loses
20 # Space: O(m + n)
21 class Solution2(object):
22 # @param dungeon, a list of lists of integers
23 # @return a integer
24 def calculateMinimumHP(self, dungeon):
25 maximum_loses = 0
26 for rooms in dungeon:
27 for room in rooms:
28 if room < 0:
29 maximum_loses += abs(room)
30
31 return self.binarySearch(dungeon, maximum_loses)
32
33 def binarySearch(self, dungeon, maximum_loses):
34 start, end = 1, maximum_loses + 1
35 result = 0
36 while start < end:
37 mid = start + (end - start) / 2
38 if self.DP(dungeon, mid):
39 end = mid
40 else:
41 start = mid + 1
42 return start
43
44 def DP(self, dungeon, HP):
45 remain_HP = [0 for _ in dungeon[0]]
46 remain_HP[0] = HP + dungeon[0][0]
47 for j in xrange(1, len(remain_HP)):
48 if remain_HP[j - 1] > 0:
49 remain_HP[j] = max(remain_HP[j - 1] + dungeon[0][j], 0)
50
51 for i in xrange(1, len(dungeon)):
52 if remain_HP[0] > 0:
53 remain_HP[0] = max(remain_HP[0] + dungeon[i][0], 0)
54 else:
55 remain_HP[0] = 0
56
57 for j in xrange(1, len(remain_HP)):
58 remain = 0
59 if remain_HP[j - 1] > 0:
60 remain = max(remain_HP[j - 1] + dungeon[i][j], remain)
61 if remain_HP[j] > 0:
62 remain = max(remain_HP[j] + dungeon[i][j], remain)
63 remain_HP[j] = remain
64
65 return remain_HP[-1] > 0
66
*****************************

42. Department Top Three Salaries


*****************************

Table: Employee

+--------------+---------+
| Column Name | Type |
+--------------+---------+
| Id | int |
| Name | varchar |
| Salary | int |
| DepartmentId | int |
+--------------+---------+
Id is the primary key for this table.
Each row contains the ID, name, salary, and department of one employee.

Table: Department

+-------------+---------+
| Column Name | Type |
+-------------+---------+
| Id | int |
| Name | varchar |
+-------------+---------+
Id is the primary key for this table.
Each row contains the ID and the name of one department.

A company's executives are interested in seeing who earns the most money in each of the company's departments. Ahigh
earner in a department is an employee who has a salary in thetop three unique salaries for that department.

Write an SQL query to find the employees who arehigh earners in each of the departments.

Return the result table in any order.

The query result format is in the following example:


Employee table:
+----+-------+--------+--------------+
| Id | Name | Salary | DepartmentId |
+----+-------+--------+--------------+
| 1 | Joe | 85000 | 1 |
| 2 | Henry | 80000 | 2 |
| 3 | Sam | 60000 | 2 |
| 4 | Max | 90000 | 1 |
| 5 | Janet | 69000 | 1 |
| 6 | Randy | 85000 | 1 |
| 7 | Will | 70000 | 1 |
+----+-------+--------+--------------+

Department table:
+----+-------+
| Id | Name |
+----+-------+
| 1 | IT |
| 2 | Sales |
+----+-------+

Result table:
+------------+----------+--------+
| Department | Employee | Salary |
+------------+----------+--------+
| IT | Max | 90000 |
| IT | Joe | 85000 |
| IT | Randy | 85000 |
| IT | Will | 70000 |
| Sales | Henry | 80000 |
| Sales | Sam | 60000 |
+------------+----------+--------+

In the IT department:
- Max earns the highest unique salary
- Both Randy and Joe earn the second-highest unique salary
- Will earns the third-highest unique salary

In the Sales department:


- Henry earns the highest salary
- Sam earns the second-highest salary
- There is no third-highest salary as there are only two employees
*****************************

42. Department Top Three Salaries(Shell)


*****************************

1 # Time: O(n^2)
2 # Space: O(n)
3
4 SELECT D.Name AS Department, E.Name AS Employee, E.Salary AS Salary
5 FROM Employee E INNER JOIN Department D ON E.DepartmentId = D.Id
6 WHERE (SELECT COUNT(DISTINCT(Salary)) FROM Employee
7 WHERE DepartmentId = E.DepartmentId AND Salary > E.Salary) < 3
8 ORDER by E.DepartmentId, E.Salary DESC;
9
**********************************

43. Best Time to Buy and Sell Stock IV


**********************************

You are given an integer array prices where prices[i] is the price of a given stock on theith day, and an integer k .

Find the maximum profit you can achieve. You may complete at mostk transactions.

Note: You may not engage in multiple transactions simultaneously (i.e., you must sell the stock before you buy again).

Example 1:

Input: k = 2, prices = [2,4,1]


Output: 2
Explanation: Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2.

Example 2:

Input: k = 2, prices = [3,2,6,5,0,3]


Output: 7
Explanation: Buy on day 2 (price = 2) and sell on day 3 (price = 6), profit = 6-2 = 4. Then buy on day 5 (price = 0) and sell on day 6 (price

Constraints:

0 <= k <= 100


0 <= prices.length <= 1000
0 <= prices[i] <= 1000
**********************************

43. Best Time to Buy and Sell Stock IV(C++)


**********************************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int maxProfit(int k, vector &prices) {
7 vector profits;
8 vector> v_p_stk; // mono stack, where v is increasing and p is strictly decreasing
9 for (int v = -1, p = -1; p + 1 < size(prices);) { // at most O(n) peaks, so v_p_stk and profits are both at most O(n) space
10 for (v = p + 1; v + 1 < size(prices); ++v) {
11 if (prices[v] < prices[v + 1]) {
12 break;
13 }
14 }
15 for (p = v; p + 1 < size(prices); ++p) {
16 if (prices[p] > prices[p + 1]) {
17 break;
18 }
19 }
20 while (!empty(v_p_stk) && (prices[v_p_stk.back().first] > prices[v])) { // not overlapped
21 const auto [last_v, last_p] = move(v_p_stk.back()); v_p_stk.pop_back();
22 profits.emplace_back(prices[last_p] - prices[last_v]); // count [prices[last_v], prices[last_p]] interval
23 }
24 while (!empty(v_p_stk) && (prices[v_p_stk.back().second] <= prices[p])) { // overlapped
25 // prices[last_v] <= prices[v] <= prices[last_p] <= prices[p],
26 // treat overlapped as [prices[v], prices[last_p]], [prices[last_v], prices[p]] intervals due to invariant max profit
27 const auto [last_v, last_p] = move(v_p_stk.back()); v_p_stk.pop_back();
28 profits.emplace_back(prices[last_p] - prices[v]); // count [prices[v], prices[last_p]] interval
29 v = last_v;
30 }
31 v_p_stk.emplace_back(v, p); // keep [prices[last_v], prices[p]] interval to check overlapped
32 }
33 while (!empty(v_p_stk)) {
34 const auto [last_v, last_p] = move(v_p_stk.back()); v_p_stk.pop_back();
35 profits.emplace_back(prices[last_p] - prices[last_v]); // count [prices[last_v], prices[last_p]] interval
36 }
37 if (k > size(profits)) {
38 k = size(profits);
39 } else {
40 nth_element(begin(profits), begin(profits) + k - 1, end(profits), greater());
41 }
42 return accumulate(cbegin(profits), cbegin(profits) + k, 0); // top k profits of nonoverlapped intervals
43 }
44 };
**********************************

43. Best Time to Buy and Sell Stock IV(Python)


**********************************

1 # Time: O(n) on average, using Median of Medians could achieve O(n) (Intro Select)
2 # Space: O(n)
3
4 import random
5
6
7 class Solution(object):
8 def maxProfit(self, k, prices):
9 """
10 :type k: int
11 :type prices: List[int]
12 :rtype: int
13 """
14 def nth_element(nums, n, compare=lambda a, b: a < b):
15 def tri_partition(nums, left, right, target, compare):
16 mid = left
17 while mid <= right:
18 if nums[mid] == target:
19 mid += 1
20 elif compare(nums[mid], target):
21 nums[left], nums[mid] = nums[mid], nums[left]
22 left += 1
23 mid += 1
24 else:
25 nums[mid], nums[right] = nums[right], nums[mid]
26 right -= 1
27 return left, right
28
29 left, right = 0, len(nums)-1
30 while left <= right:
31 pivot_idx = random.randint(left, right)
32 pivot_left, pivot_right = tri_partition(nums, left, right, nums[pivot_idx], compare)
33 if pivot_left <= n <= pivot_right:
34 return
35 elif pivot_left > n:
36 right = pivot_left-1
37 else: # pivot_right < n.
38 left = pivot_right+1
39
40 profits = []
41 v_p_stk = [] # mono stack, where v is increasing and p is strictly decreasing
42 v, p = -1, -1
43 while p+1 < len(prices): # at most O(n) peaks, so v_p_stk and profits are both at most O(n) space
44 for v in xrange(p+1, len(prices)-1):
45 if prices[v] < prices[v+1]:
46 break
47 else:
48 v = len(prices)-1
49 for p in xrange(v, len(prices)-1):
50 if prices[p] > prices[p+1]:
51 break
52 else:
53 p = len(prices)-1
54 while v_p_stk and prices[v_p_stk[-1][0]] > prices[v]: # not overlapped
55 last_v, last_p = v_p_stk.pop()
56 profits.append(prices[last_p]-prices[last_v]) # count [prices[last_v], prices[last_p]] interval
57 while v_p_stk and prices[v_p_stk[-1][1]] <= prices[p]: # overlapped
58 # prices[last_v] <= prices[v] <= prices[last_p] <= prices[p],
59 # treat overlapped as [prices[v], prices[last_p]], [prices[last_v], prices[p]] intervals due to invariant max profit
60 last_v, last_p = v_p_stk.pop()
61 profits.append(prices[last_p]-prices[v]) # count [prices[v], prices[last_p]] interval
62 v = last_v
63 v_p_stk.append((v, p)) # keep [prices[last_v], prices[p]] interval to check overlapped
64 while v_p_stk:
65 last_v, last_p = v_p_stk.pop()
66 profits.append(prices[last_p]-prices[last_v]) # count [prices[last_v], prices[last_p]] interval
67 if k > len(profits):
68 k = len(profits)
69 else:
70 nth_element(profits, k-1, compare=lambda a, b: a > b)
71 return sum(profits[i] for i in xrange(k)) # top k profits of nonoverlapped intervals
72
73
74 # Time: O(k * n)
75 # Space: O(k)
76 class Solution2(object):
77 def maxProfit(self, k, prices):
78 """
79 :type k: int
80 :type prices: List[int]
81 :rtype: int
82 """
83 def maxAtMostNPairsProfit(sprices):
84 profit = 0
85 for i in xrange(len(prices) - 1):
86 profit += max(0, prices[i + 1] - prices[i])
87 return profit
88
89 def maxAtMostKPairsProfit(prices, k):
90 max_buy = [float("-inf") for _ in xrange(k + 1)]
91 max_sell = [0 for _ in xrange(k + 1)]
92 for i in xrange(len(prices)):
93 for j in xrange(1, k + 1):
94 max_buy[j] = max(max_buy[j], max_sell[j-1] - prices[i])
95 max_sell[j] = max(max_sell[j], max_buy[j] + prices[i])
96 return max_sell[k]
97
98 if k >= len(prices) // 2:
99 return maxAtMostNPairsProfit(prices)
100
101 return maxAtMostKPairsProfit(prices, k)
**************

44. Word Search II


**************

Given an m x n board of characters and a list of strings words, return all words on the board.

Each word must be constructed from letters of sequentially adjacent cells, whereadjacent cells are horizontally or vertically
neighboring. The same letter cell may not be used more than once in a word.

Example 1:

Input: board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]


Output: ["eat","oath"]

Example 2:

Input: board = [["a","b"],["c","d"]], words = ["abcb"]


Output: []

Constraints:

m == board.length
n == board[i].length
1 <= m, n <= 12
board[i][j] is a lowercase English letter.
1 <= words.length <= 3 * 10 4
1 <= words[i].length <= 10
words[i] consists of lowercase English letters.
All the strings of words are unique.
**************

44. Word Search II(C++)


**************

1 // Time: O(m * n * 4 * 3^(h - 1)) ~= O(m * n * 3^h), h is the height of trie


2 // Space: O(t), t is the number of nodes in trie
3
4 class Solution {
5 private:
6 struct TrieNode {
7 bool isString = false;
8 unordered_map leaves;
9
10 bool Insert(const string& s) {
11 auto* p = this;
12 for (const auto& c : s) {
13 if (p->leaves.find(c) == p->leaves.cend()) {
14 p->leaves[c] = new TrieNode;
15 }
16 p = p->leaves[c];
17 }
18
19 // s already existed in this trie.
20 if (p->isString) {
21 return false;
22 } else {
23 p->isString = true;
24 return true;
25 }
26 }
27
28 ~TrieNode() {
29 for (auto& kv : leaves) {
30 if (kv.second) {
31 delete kv.second;
32 }
33 }
34 }
35 };
36
37 public:
38 /**
39 * @param board: A list of lists of character
40 * @param words: A list of string
41 * @return: A list of string
42 */
43 vector findWords(vector>& board, vector& words) {
44 unordered_set ret;
45 vector> visited(board.size(), vector(board[0].size(), false));
46 string cur;
47 TrieNode trie;
48 for (const auto& word : words) {
49 trie.Insert(word);
50 }
51
52 for (int i = 0; i < board.size(); ++i) {
53 for (int j = 0; j < board[0].size(); ++j) {
54 findWordsDFS(board, visited, &trie, i, j, cur, ret);
55 }
56 }
57
58 return vector(ret.begin(), ret.end());
59 }
60
61 void findWordsDFS(vector> &grid,
62 vector> &visited,
63 TrieNode *trie,
64 int i,
65 int j,
66 string cur,
67 unordered_set &ret) {
68 // Invalid state.
69 if (!trie || i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size()) {
70 return;
71 }
72
73 // Not in trie or visited.
74 if (!trie->leaves[grid[i][j] ] || visited[i][j]) {
75 return;
76 }
77
78 // Get next trie nodes.
79 TrieNode *nextNode = trie->leaves[grid[i][j]];
80
81 // Update current string.
82 cur.push_back(grid[i][j]);
83
84 // Find the string, add to the answers.
85 if (nextNode->isString) {
86 ret.insert(cur);
87 }
88
89 // Marked as visited.
90 visited[i][j] = true;
91
92 // Try each direction.
93 const vector> directions{{0, -1}, {0, 1},
94 {-1, 0}, {1, 0}};
95 for (const auto& d : directions) {
96 findWordsDFS(grid, visited, nextNode,
97 i + d.first, j + d.second, cur, ret);
98 }
99
100 visited[i][j] = false;
101 }
102 };
**************

44. Word Search II(Python)


**************

1 # Time: O(m * n * 4 * 3^(h - 1)) ~= O(m * n * 3^h), h is the height of trie


2 # Space: O(t), t is the number of nodes in trie
3
4 class TrieNode(object):
5 # Initialize your data structure here.
6 def __init__(self):
7 self.is_string = False
8 self.leaves = {}
9
10 # Inserts a word into the trie.
11 def insert(self, word):
12 cur = self
13 for c in word:
14 if not c in cur.leaves:
15 cur.leaves[c] = TrieNode()
16 cur = cur.leaves[c]
17 cur.is_string = True
18
19
20 class Solution(object):
21 def findWords(self, board, words):
22 """
23 :type board: List[List[str]]
24 :type words: List[str]
25 :rtype: List[str]
26 """
27 visited = [[False for j in xrange(len(board[0]))] for i in xrange(len(board))]
28 result = {}
29 trie = TrieNode()
30 for word in words:
31 trie.insert(word)
32
33 for i in xrange(len(board)):
34 for j in xrange(len(board[0])):
35 self.findWordsRecu(board, trie, 0, i, j, visited, [], result)
36
37 return result.keys()
38
39 def findWordsRecu(self, board, trie, cur, i, j, visited, cur_word, result):
40 if not trie or i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or visited[i][j]:
41 return
42
43 if board[i][j] not in trie.leaves:
44 return
45
46 cur_word.append(board[i][j])
47 next_node = trie.leaves[board[i][j]]
48 if next_node.is_string:
49 result["".join(cur_word)] = True
50
51 visited[i][j] = True
52 self.findWordsRecu(board, next_node, cur + 1, i + 1, j, visited, cur_word, result)
53 self.findWordsRecu(board, next_node, cur + 1, i - 1, j, visited, cur_word, result)
54 self.findWordsRecu(board, next_node, cur + 1, i, j + 1, visited, cur_word, result)
55 self.findWordsRecu(board, next_node, cur + 1, i, j - 1, visited, cur_word, result)
56 visited[i][j] = False
57 cur_word.pop()
*******************

45. Shortest Palindrome


*******************

You are given a string s . You can convert s to a palindrome by adding characters in front of it.

Return the shortest palindrome you can find by performing this transformation.

Example 1:

Input: s = "aacecaaa"
Output: "aaacecaaa"

Example 2:

Input: s = "abcd"
Output: "dcbabcd"

Constraints:

0 <= s.length <= 5 * 10 4


s consists of lowercase English letters only.
*******************

45. Shortest Palindrome(C++)


*******************

1 // Time: O(n)
2 // Space: O(n)
3
4 // KMP Algorithm optimized from Solution2
5 class Solution {
6 public:
7 string shortestPalindrome(string s) {
8 if (s.empty()) {
9 return s;
10 }
11 string rev_s(s.crbegin(), s.crend());
12 // Assume s is (Palindrome)abc,
13 // A would be (Palindrome)abc#cba(Palindrome).
14 string A = s + '#' + rev_s;
15 auto prefix = getPrefix(A);
16 // The index prefix.back() of A would be:
17 // (Palindrome)abc#cba(Palindrome)
18 // ^
19 // The index prefix.back() + 1 of s would be:
20 // (Palindrome)abc
21 // ^
22 // Get non palindrome part of s.
23 string non_palindrome = s.substr(prefix.back() + 1);
24 reverse(non_palindrome.begin(), non_palindrome.end());
25 return non_palindrome + s; // cba(Palindrome)abc.
26 }
27
28 private:
29 vector getPrefix(const string& pattern) {
30 vector prefix(pattern.length(), -1);
31 int j = -1;
32 for (int i = 1; i < pattern.length(); ++i) {
33 while (j > -1 && pattern[j + 1] != pattern[i]) {
34 j = prefix[j];
35 }
36 if (pattern[j + 1] == pattern[i]) {
37 ++j;
38 }
39 prefix[i] = j;
40 }
41 return prefix;
42 }
43 };
44
45 // Time: O(n)
46 // Space: O(n)
47 // KMP Algorithm
48 class Solution2 {
49 public:
50 string shortestPalindrome(string s) {
51 if (s.empty()) {
52 return s;
53 }
54 string rev_s(s.crbegin(), s.crend());
55 // Assume s is (Palindrome)abc,
56 // A would be (Palindrome)abccba(Palindrome).
57 string A = s + rev_s;
58 auto prefix = getPrefix(A);
59 // The index prefix.back() of A would be:
60 // (Palindrome)abccba(Palindrome)
61 // ^
62 // The index prefix.back() + 1 of s would be:
63 // (Palindrome)abc
64 // ^
65 // Get non palindrome part of s.
66 int i = prefix.back();
67 while (i >= s.length()) {
68 i = prefix[i];
69 }
70 string non_palindrome = s.substr(i + 1);
71 reverse(non_palindrome.begin(), non_palindrome.end());
72 return non_palindrome + s; // cba(Palindrome)abc.
73 }
74
75 private:
76 vector getPrefix(const string& pattern) {
77 vector prefix(pattern.length(), -1);
78 int j = -1;
79 for (int i = 1; i < pattern.length(); ++i) {
80 while (j > -1 && pattern[j + 1] != pattern[i]) {
81 j = prefix[j];
82 }
83 if (pattern[j + 1] == pattern[i]) {
84 ++j;
85 }
86 prefix[i] = j;
87 }
88 return prefix;
89 }
90 };
91
92 // Time: O(n)
93 // Space: O(n)
94 // Manacher's Algorithm
95 class Solution3 {
96 public:
97 string shortestPalindrome(string s) {
98 string T = preProcess(s);
99 int n = T.length();
100 vector P(n);
101 int C = 0, R = 0;
102 for (int i = 1; i < n - 1; ++i) {
103 int i_mirror = 2 * C - i; // equals to i' = C - (i-C)
104
105 P[i] = (R > i) ? min(R - i, P[i_mirror]) : 0;
106
107 // Attempt to expand palindrome centered at i
108 while (T[i + 1 + P[i]] == T[i - 1 - P[i]]) {
109 ++P[i];
110 }
111
112 // If palindrome centered at i expand past R,
113 // adjust center based on expanded palindrome.
114 if (i + P[i] > R) {
115 C = i;
116 R = i + P[i];
117 }
118 }
119
120 // Find the max len of palindrome which starts with the first char of s.
121 int max_len = 0;
122 for (int i = 1; i < n - 1; ++i) {
123 if (i - P[i] == 1) {
124 max_len = P[i];
125 }
126 }
127
128 // Assume s is (Palindrome)abc.
129 string ans = s.substr(max_len); // abc.
130 reverse(ans.begin(), ans.end()); // cba.
131 ans.append(s); // cba(Palindrome)abc.
132 return ans;
133 }
134 private:
135 string preProcess(string s) {
135 string preProcess(string s) {
136 int n = s.length();
137 if (n == 0) {
138 return "^$";
139 }
140 string ret = "^";
141 for (int i = 0; i < n; ++i) {
142 ret += "#" + s.substr(i, 1);
143 }
144 ret += "#$";
145 return ret;
146 }
147 };
*******************

45. Shortest Palindrome(Python)


*******************

1 # Time: O(n)
2 # Space: O(n)
3
4 # optimized from Solution2
5 class Solution(object):
6 def shortestPalindrome(self, s):
7 """
8 :type s: str
9 :rtype: str
10 """
11 def getPrefix(pattern):
12 prefix = [-1] * len(pattern)
13 j = -1
14 for i in xrange(1, len(pattern)):
15 while j > -1 and pattern[j+1] != pattern[i]:
16 j = prefix[j]
17 if pattern[j+1] == pattern[i]:
18 j += 1
19 prefix[i] = j
20 return prefix
21
22 if not s:
23 return s
24
25 A = s + '#' + s[::-1]
26 return s[getPrefix(A)[-1]+1:][::-1] + s
27
28
29 # Time: O(n)
30 # Space: O(n)
31 class Solution2(object):
32 def shortestPalindrome(self, s):
33 """
34 :type s: str
35 :rtype: str
36 """
37 def getPrefix(pattern):
38 prefix = [-1] * len(pattern)
39 j = -1
40 for i in xrange(1, len(pattern)):
41 while j > -1 and pattern[j+1] != pattern[i]:
42 j = prefix[j]
43 if pattern[j+1] == pattern[i]:
44 j += 1
45 prefix[i] = j
46 return prefix
47
48 if not s:
49 return s
50
51 A = s + s[::-1]
52 prefix = getPrefix(A)
53 i = prefix[-1]
54 while i >= len(s):
55 i = prefix[i]
56 return s[i+1:][::-1] + s
57
58
59 # Time: O(n)
60 # Space: O(n)
61 # Manacher's Algorithm
62 class Solution3(object):
63 def shortestPalindrome(self, s):
64 """
65 :type s: str
66 :rtype: str
67 """
68 def preProcess(s):
69 if not s:
70 return ['^', '$']
71 string = ['^']
72 for c in s:
73 string += ['#', c]
74 string += ['#', '$']
75 return string
76
77 string = preProcess(s)
78 palindrome = [0] * len(string)
79 center, right = 0, 0
80 for i in xrange(1, len(string) - 1):
81 i_mirror = 2 * center - i
82 if right > i:
83 palindrome[i] = min(right - i, palindrome[i_mirror])
84 else:
85 palindrome[i] = 0
86
87 while string[i + 1 + palindrome[i]] == string[i - 1 - palindrome[i]]:
88 palindrome[i] += 1
89
90 if i + palindrome[i] > right:
91 center, right = i, i + palindrome[i]
92
93 max_len = 0
94 for i in xrange(1, len(string) - 1):
95 if i - palindrome[i] == 1:
96 max_len = palindrome[i]
97 return s[len(s)-1:max_len-1:-1] + s
98
*******************

46. The Skyline Problem


*******************

A city's skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance.
Given the locations and heights of all the buildings, return the skyline formed by these buildings collectively.

The geometric information of each building is given in the arraybuildings where buildings[i] = [left i, right i, heighti]:

leftiis the x coordinate of the left edge of theith building.


righti is the x coordinate of the right edge of theith building.
heighti is the height of the ith building.

You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height0.

The skyline should be represented as a list of "key points"sorted by their x-coordinate in the form [[x1,y1],[x2,y2],...]. Each
key point is the left endpoint of some horizontal segment in the skyline except the last point in the list, which always has a y-
coordinate 0 and is used to mark the skyline's termination where the rightmost building ends. Any ground between the
leftmost and rightmost buildings should be part of the skyline's contour.

Note: There must be no consecutive horizontal lines of equal height in the output skyline. For instance,[...,[2 3],[4 5],[7 5],[11 5],
[12 7],...] is not acceptable; the three lines of height 5 should be merged into one in the final output as such:[...,[2 3],[4 5],[12 7],...]

Example 1:

Input: buildings = [[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]


Output: [[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]]
Explanation:
Figure A shows the buildings of the input.
Figure B shows the skyline formed by those buildings. The red points in figure B represent the key points in the output list.

Example 2:

Input: buildings = [[0,2,3],[2,5,3]]


Output: [[0,3],[5,0]]

Constraints:
1 <= buildings.length <= 10 4
0 <= lefti < right i <= 2 31 - 1
1 <= heighti <= 2 31 - 1
buildings is sorted by lefti in non-decreasing order.
*******************

46. The Skyline Problem(C++)


*******************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 // BST solution.
5 class Solution {
6 public:
7 enum {start, end, height};
8
9 struct Endpoint {
10 int height;
11 bool isStart;
12 };
13
14 vector > getSkyline(vector >& buildings) {
15 map> point_to_height; // Ordered, no duplicates.
16 for (const auto& building : buildings) {
17 point_to_height[building[start]].emplace_back(Endpoint{building[height], true});
18 point_to_height[building[end]].emplace_back(Endpoint{building[height], false});
19 }
20
21 vector> res;
22 map height_to_count; // BST.
23 int curr_max = 0;
24 // Enumerate each point in increasing order.
25 for (const auto& kvp : point_to_height) {
26 const auto& point = kvp.first;
27 const auto& heights = kvp.second;
28
29 for (const auto& h : heights) {
30 if (h.isStart) {
31 ++height_to_count[h.height];
32 } else {
33 --height_to_count[h.height];
34 if (height_to_count[h.height] == 0) {
35 height_to_count.erase(h.height);
36 }
37 }
38 }
39
40 if (height_to_count.empty() ||
41 curr_max != height_to_count.crbegin()->first) {
42 curr_max = height_to_count.empty() ?
43 0 : height_to_count.crbegin()->first;
44 res.emplace_back(point, curr_max);
45 }
46 }
47 return res;
48 }
49 };
50
51 // Time: O(nlogn)
52 // Space: O(n)
53 // Divide and conquer solution.
54 class Solution2 {
55 public:
56 enum {start, end, height};
57
58 vector> getSkyline(vector>& buildings) {
59 const auto intervals = ComputeSkylineInInterval(buildings, 0, buildings.size());
60
61 vector> res;
62 int last_end = -1;
63 for (const auto& interval : intervals) {
64 if (last_end != -1 && last_end < interval[start]) {
65 res.emplace_back(last_end, 0);
66 }
67 res.emplace_back(interval[start], interval[height]);
68 last_end = interval[end];
69 }
70 if (last_end != -1) {
71 res.emplace_back(last_end, 0);
72 }
73 return res;
74 }
75
76 // Divide and Conquer.
77 vector> ComputeSkylineInInterval(const vector>& buildings,
78 int left_endpoint, int right_endpoint) {
79 if (right_endpoint - left_endpoint <= 1) { // 0 or 1 skyline, just copy it.
80 return {buildings.cbegin() + left_endpoint,
81 buildings.cbegin() + right_endpoint};
82 }
83 int mid = left_endpoint + ((right_endpoint - left_endpoint) / 2);
84 auto left_skyline = ComputeSkylineInInterval(buildings, left_endpoint, mid);
85 auto right_skyline = ComputeSkylineInInterval(buildings, mid, right_endpoint);
86 return MergeSkylines(left_skyline, right_skyline);
87 }
88
89 // Merge Sort
90 vector> MergeSkylines(vector>& left_skyline, vector>& right_skyline) {
91 int i = 0, j = 0;
92 vector> merged;
93
94 while (i < left_skyline.size() && j < right_skyline.size()) {
95 if (left_skyline[i][end] < right_skyline[j][start]) {
96 merged.emplace_back(move(left_skyline[i++]));
97 } else if (right_skyline[j][end] < left_skyline[i][start]) {
98 merged.emplace_back(move(right_skyline[j++]));
99 } else if (left_skyline[i][start] <= right_skyline[j][start]) {
100 MergeIntersectSkylines(merged, left_skyline[i], i,
101 right_skyline[j], j);
102 } else { // left_skyline[i][start] > right_skyline[j][start].
103 MergeIntersectSkylines(merged, right_skyline[j], j,
104 left_skyline[i], i);
105 }
106 }
107
108 // Insert the remaining skylines.
109 merged.insert(merged.end(), left_skyline.begin() + i, left_skyline.end());
110 merged.insert(merged.end(), right_skyline.begin() + j, right_skyline.end());
111 return merged;
112 }
113
114 // a[start] <= b[start]
115 void MergeIntersectSkylines(vector>& merged, vector& a, int& a_idx,
116 vector& b, int& b_idx) {
117 if (a[end] <= b[end]) {
118 if (a[height] > b[height]) { // |aaa|
119 if (b[end] != a[end]) { // |abb|b
120 b[start] = a[end];
121 merged.emplace_back(move(a)), ++a_idx;
122 } else { // aaa
123 ++b_idx; // abb
124 }
125 } else if (a[height] == b[height]) { // abb
126 b[start] = a[start], ++a_idx; // abb
127 } else { // a[height] < b[height].
128 if (a[start] != b[start]) { // bb
129 merged.emplace_back(move(vector{a[start], b[start], a[height]})); // |a|bb
130 }
131 ++a_idx;
132 }
133 } else { // a[end] > b[end].
134 if (a[height] >= b[height]) { // aaaa
135 ++b_idx; // abba
135 ++b_idx; // abba
136 } else {
137 // |bb|
138 // |a||bb|a
139 if (a[start] != b[start]) {
140 merged.emplace_back(move(vector{a[start], b[start], a[height]}));
141 }
142 a[start] = b[end];
143 merged.emplace_back(move(b)), ++b_idx;
144 }
145 }
146 }
147 };
*******************

46. The Skyline Problem(Python)


*******************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 start, end, height = 0, 1, 2
5 class Solution(object):
6 # @param {integer[][]} buildings
7 # @return {integer[][]}
8 def getSkyline(self, buildings):
9 intervals = self.ComputeSkylineInInterval(buildings, 0, len(buildings))
10
11 res = []
12 last_end = -1
13 for interval in intervals:
14 if last_end != -1 and last_end < interval[start]:
15 res.append([last_end, 0])
16 res.append([interval[start], interval[height]])
17 last_end = interval[end]
18 if last_end != -1:
19 res.append([last_end, 0])
20
21 return res
22
23 # Divide and Conquer.
24 def ComputeSkylineInInterval(self, buildings, left_endpoint, right_endpoint):
25 if right_endpoint - left_endpoint <= 1:
26 return buildings[left_endpoint:right_endpoint]
27 mid = left_endpoint + ((right_endpoint - left_endpoint) / 2)
28 left_skyline = self.ComputeSkylineInInterval(buildings, left_endpoint, mid)
29 right_skyline = self.ComputeSkylineInInterval(buildings, mid, right_endpoint)
30 return self.MergeSkylines(left_skyline, right_skyline)
31
32 # Merge Sort.
33 def MergeSkylines(self, left_skyline, right_skyline):
34 i, j = 0, 0
35 merged = []
36
37 while i < len(left_skyline) and j < len(right_skyline):
38 if left_skyline[i][end] < right_skyline[j][start]:
39 merged.append(left_skyline[i])
40 i += 1
41 elif right_skyline[j][end] < left_skyline[i][start]:
42 merged.append(right_skyline[j])
43 j += 1
44 elif left_skyline[i][start] <= right_skyline[j][start]:
45 i, j = self.MergeIntersectSkylines(merged, left_skyline[i], i,\
46 right_skyline[j], j)
47 else: # left_skyline[i][start] > right_skyline[j][start].
48 j, i = self.MergeIntersectSkylines(merged, right_skyline[j], j, \
49 left_skyline[i], i)
50
51 # Insert the remaining skylines.
52 merged += left_skyline[i:]
53 merged += right_skyline[j:]
54 return merged
55
56 # a[start] <= b[start]
57 def MergeIntersectSkylines(self, merged, a, a_idx, b, b_idx):
58 if a[end] <= b[end]:
59 if a[height] > b[height]: # |aaa|
60 if b[end] != a[end]: # |abb|b
61 b[start] = a[end]
62 merged.append(a)
63 a_idx += 1
64 else: # aaa
65 b_idx += 1 # abb
66 elif a[height] == b[height]: # abb
67 b[start] = a[start] # abb
68 a_idx += 1
69 else: # a[height] < b[height].
70 if a[start] != b[start]: # bb
71 merged.append([a[start], b[start], a[height]]) # |a|bb
72 a_idx += 1
73 else: # a[end] > b[end].
74 if a[height] >= b[height]: # aaaa
75 b_idx += 1 # abba
76 else:
77 # |bb|
78 # |a||bb|a
79 if a[start] != b[start]:
80 merged.append([a[start], b[start], a[height]])
81 a[start] = b[end]
82 merged.append(b)
83 b_idx += 1
84 return a_idx, b_idx
85
****************

47. Basic Calculator


****************

Given a string s representing a valid expression, implement a basic calculator to evaluate it, and returnthe result of the
evaluation.

Note: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such aseval().

Example 1:

Input: s = "1 + 1"


Output: 2

Example 2:

Input: s = " 2-1 + 2 "


Output: 3

Example 3:

Input: s = "(1+(4+5+2)-3)+(6+8)"
Output: 23

Constraints:

1 <= s.length <= 3 * 10 5


s consists of digits, '+' , '-', '(', ')', and ' '.
s represents a valid expression.
'+' is not used as a unary operation.
'-' could be used as a unary operation
but it has to be followed by parentheses.
Every number and running calculation will fit in a signed 32-bit integer.
****************

47. Basic Calculator(C++)


****************

1 // Time: O(n)
2 // Space: O(n)
3
4 // Support +, -, *, /.
5 class Solution {
6 public:
7 int calculate(string s) {
8 static const unordered_map precedence = {{'+', 0}, {'-', 0}, {'*', 1}, {'/', 1}};
9
10 stack operands;
11 stack operators;
12 int64_t operand = 0;
13 for (int i = 0; i < size(s); ++i) {
14 if (isdigit(s[i])) {
15 operand = operand * 10 + s[i] - '0';
16 if (i + 1 == size(s) || !isdigit(s[i + 1])) {
17 operands.emplace(operand);
18 operand = 0;
19 }
20 } else if (s[i] == '(') {
21 operators.emplace(s[i]);
22 } else if (s[i] == ')') {
23 while (operators.top() != '(') {
24 compute(&operands, &operators);
25 }
26 operators.pop();
27 } else if (precedence.count(s[i])) {
28 while (!empty(operators) && precedence.count(operators.top()) &&
29 precedence.at(operators.top()) >= precedence.at(s[i])) {
30 compute(&operands, &operators);
31 }
32 operators.emplace(s[i]);
33 }
34 }
35 while (!empty(operators)) {
36 compute(&operands, &operators);
37 }
38 return operands.top();
39 }
40
41 private:
42 template
43 void compute(stack *operands, stack *operators) {
44 const auto right = operands->top(); operands->pop();
45 const auto left = operands->top(); operands->pop();
46 const char op = operators->top(); operators->pop();
47 if (op == '+') {
48 operands->emplace(left + right);
49 } else if (op == '-') {
50 operands->emplace(left - right);
51 } else if (op == '*') {
52 operands->emplace(left * right);
53 } else if (op == '/') {
54 operands->emplace(left / right);
55 }
56 }
57 };
58
59 // Time: O(n)
60 // Space: O(n)
61 // Support +, -, *, /.
62 class Solution2 {
63 public:
64 int calculate(string s) {
65 stack operands;
66 stack operators;
67 string operand;
68 for (int i = s.length() - 1; i >= 0; --i) {
69 if (isdigit(s[i])) {
70 operand.push_back(s[i]);
71 if (i == 0 || !isdigit(s[i - 1])) {
72 reverse(operand.begin(), operand.end());
73 operands.emplace(stol(operand));
74 operand.clear();
75 }
76 } else if (s[i] == ')' || s[i] == '*' ||
77 s[i] == '/') {
78 operators.emplace(s[i]);
79 } else if (s[i] == '+' || s[i] == '-') {
80 while (!operators.empty() && (operators.top() == '*' ||
81 operators.top() == '/')) {
82 compute(operands, operators);
83 }
84 operators.emplace(s[i]);
85 } else if (s[i] == '(') {
86 // operators at least one element, i.e. ')'.
87 while (operators.top() != ')') {
88 compute(operands, operators);
89 }
90 operators.pop();
91 }
92 }
93 while (!operators.empty()) {
94 compute(operands, operators);
95 }
96 return operands.top();
97 }
98
99 void compute(stack& operands, stack& operators) {
100 const int64_t left = operands.top();
101 operands.pop();
102 const int64_t right = operands.top();
103 operands.pop();
104 const char op = operators.top();
105 operators.pop();
106 if (op == '+') {
107 operands.emplace(left + right);
108 } else if (op == '-') {
109 operands.emplace(left - right);
110 } else if (op == '*') {
111 operands.emplace(left * right);
112 } else if (op == '/') {
113 operands.emplace(left / right);
114 }
115 }
116 };
117
118 // Time: O(n)
119 // Space: O(n)
120 // Only support +, -.
121 class Solution3 {
122 public:
123 int calculate(string s) {
124 stack operands;
125 stack operators;
126 string operand;
127 for (int i = s.length() - 1; i >= 0; --i) {
128 if (isdigit(s[i])) {
129 operand.push_back(s[i]);
130 if (i == 0 || !isdigit(s[i - 1])) {
131 reverse(operand.begin(), operand.end());
132 operands.emplace(stoi(operand));
133 operand.clear();
134 }
135 } else if (s[i] == ')' || s[i] == '+' || s[i] == '-') {
135 } else if (s[i] == ')' || s[i] == '+' || s[i] == '-') {
136 operators.emplace(s[i]);
137 } else if (s[i] == '(') {
138 while (operators.top() != ')') {
139 compute(operands, operators);
140 }
141 operators.pop();
142 }
143 }
144 while (!operators.empty()) {
145 compute(operands, operators);
146 }
147 return operands.top();
148 }
149
150 void compute(stack& operands, stack& operators) {
151 const int left = operands.top();
152 operands.pop();
153 const int right = operands.top();
154 operands.pop();
155 const char op = operators.top();
156 operators.pop();
157 if (op == '+') {
158 operands.emplace(left + right);
159 } else if (op == '-') {
160 operands.emplace(left - right);
161 }
162 }
163 };
****************

47. Basic Calculator(Python)


****************

1 # Time: O(n)
2 # Space: O(n)
3
4 import operator
5
6
7 class Solution(object):
8 def calculate(self, s):
9 """
10 :type s: str
11 :rtype: int
12 """
13 def compute(operands, operators):
14 right, left = operands.pop(), operands.pop()
15 operands.append(ops[operators.pop()](left, right))
16
17 ops = {'+':operator.add, '-':operator.sub, '*':operator.mul, '/':operator.div}
18 precedence = {'+':0, '-':0, '*':1, '/':1}
19 operands, operators, operand = [], [], 0
20 for i in xrange(len(s)):
21 if s[i].isdigit():
22 operand = operand*10 + int(s[i])
23 if i == len(s)-1 or not s[i+1].isdigit():
24 operands.append(operand)
25 operand = 0
26 elif s[i] == '(':
27 operators.append(s[i])
28 elif s[i] == ')':
29 while operators[-1] != '(':
30 compute(operands, operators)
31 operators.pop()
32 elif s[i] in precedence:
33 while operators and operators[-1] in precedence and \
34 precedence[operators[-1]] >= precedence[s[i]]:
35 compute(operands, operators)
36 operators.append(s[i])
37 while operators:
38 compute(operands, operators)
39 return operands[-1]
40
41
42 # Time: O(n)
43 # Space: O(n)
44 class Solution2(object):
45 # @param {string} s
46 # @return {integer}
47 def calculate(self, s):
48 operands, operators = [], []
49 operand = ""
50 for i in reversed(xrange(len(s))):
51 if s[i].isdigit():
52 operand += s[i]
53 if i == 0 or not s[i-1].isdigit():
54 operands.append(int(operand[::-1]))
55 operand = ""
56 elif s[i] == ')' or s[i] == '+' or s[i] == '-':
57 operators.append(s[i])
58 elif s[i] == '(':
59 while operators[-1] != ')':
60 self.compute(operands, operators)
61 operators.pop()
62
63 while operators:
64 self.compute(operands, operators)
65
66 return operands[-1]
67
68 def compute(self, operands, operators):
69 left, right = operands.pop(), operands.pop()
70 op = operators.pop()
71 if op == '+':
72 operands.append(left + right)
73 elif op == '-':
74 operands.append(left - right)
75
*******************

48. Number of Digit One


*******************

Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal ton.

Example 1:

Input: n = 13
Output: 6

Example 2:

Input: n = 0
Output: 0

Constraints:

0 <= n <= 10 9
*******************

48. Number of Digit One(C++)


*******************

1 // Time: O(logn) = O(1)


2 // Space: O(1)
3
4 class Solution {
5 public:
6 int countDigitOne(int n) {
7 static const int DIGIT = 1;
8
9 int is_zero = (DIGIT == 0) ? 1 : 0;
10 int result = is_zero;
11 for (int64_t base = 1; n >= base; base *= 10) {
12 result += (n / (10 * base) - is_zero) * base +
13 min(base, max(n % (10 * base) - DIGIT * base + 1, 0l));
14 }
15 return result;
16 }
17 };
*******************

48. Number of Digit One(Python)


*******************

1 # Time: O(logn)
2 # Space: O(1)
3
4 class Solution(object):
5 def countDigitOne(self, n):
6 """
7 :type n: int
8 :rtype: int
9 """
10 DIGIT = 1
11 is_zero = int(DIGIT == 0)
12 result = is_zero
13 base = 1
14 while n >= base:
15 result += (n//(10*base)-is_zero)*base + \
16 min(base, max(n%(10*base) - DIGIT*base + 1, 0))
17 base *= 10
18 return result
19
**********************

49. Sliding Window Maximum


**********************

You are given an array of integersnums, there is a sliding window of sizek which is moving from the very left of the array to
the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.

Return the max sliding window.

Example 1:

Input: nums = [1,3,-1,-3,5,3,6,7], k = 3


Output: [3,3,5,5,6,7]
Explanation:
Window position Max
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7

Example 2:

Input: nums = [1], k = 1


Output: [1]

Example 3:

Input: nums = [1,-1], k = 1


Output: [1,-1]

Example 4:

Input: nums = [9,11], k = 2


Output: [11]

Example 5:

Input: nums = [4,-2], k = 2


Output: [4]

Constraints:

1 <= nums.length <= 10 5


-104 <= nums[i] <= 10 4
1 <= k <= nums.length
**********************

49. Sliding Window Maximum(C++)


**********************

1 // Time: O(n)
2 // Space: O(k)
3
4 class Solution {
5 public:
6 vector maxSlidingWindow(vector& nums, int k) {
7 vector result;
8 deque dq;
9 for (int i = 0; i < nums.size(); ++i) {
10 if (!dq.empty() && i - dq.front() == k) {
11 dq.pop_front();
12 }
13 while (!dq.empty() && nums[dq.back()] <= nums[i]) {
14 dq.pop_back();
15 }
16 dq.emplace_back(i);
17 if (i >= k - 1) {
18 result.emplace_back(nums[dq.front()]);
19 }
20 }
21 return result;
22 }
23 };
**********************

49. Sliding Window Maximum(Python)


**********************

1 # Time: O(n)
2 # Space: O(k)
3
4 from collections import deque
5
6
7 class Solution(object):
8 def maxSlidingWindow(self, nums, k):
9 """
10 :type nums: List[int]
11 :type k: int
12 :rtype: List[int]
13 """
14 result, dq = [], deque()
15 for i in xrange(len(nums)):
16 if dq and i-dq[0] == k:
17 dq.popleft()
18 while dq and nums[dq[-1]] <= nums[i]:
19 dq.pop()
20 dq.append(i)
21 if i >= k-1:
22 result.append(nums[dq[0]])
23 return result
**************************

50. Strobogrammatic Number III


**************************

Given two strings low and high that represent two integers low and high where low <= high , return the number of
strobogrammatic numbers in the range [low, high] .

A strobogrammatic number is a number that looks the same when rotated180 degrees (looked at upside down).

Example 1:

Input: low = "50", high = "100"


Output: 3

Example 2:

Input: low = "0", high = "0"


Output: 1

Constraints:

1 <= low.length, high.length <= 15


low and high consist of only digits.
low <= high
low and high do not contain any leading zeros except for zero itself.
**************************

50. Strobogrammatic Number III(C++)


**************************

1 // Time: O(5^(n/2))
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int strobogrammaticInRange(string low, string high) {
7 int count = countStrobogrammaticUntil(high, false) -
8 countStrobogrammaticUntil(low, false) +
9 isStrobogrammatic(low);
10 return count >= 0 ? count : 0;
11 }
12
13 int countStrobogrammaticUntil(string num, bool can_start_with_0) {
14 if (can_start_with_0 && cache.find(num) != cache.end()) {
15 return cache[num];
16 }
17
18 int count = 0;
19 if (num.length() == 1) {
20 for (const auto& c : {'0', '1', '8'}) {
21 if (num.front() >= c) {
22 ++count;
23 }
24 }
25 cache[num] = count;
26 return count;
27 }
28
29 for (const auto& kvp : lookup) {
30 if (can_start_with_0 || kvp.first != '0') {
31 if (num.front() > kvp.first) {
32 if (num.length() == 2) { // num is like "21"
33 ++count;
34 } else { // num is like "201"
35 count += countStrobogrammaticUntil(string(num.length() - 2, '9'), true);
36 }
37 } else if (num.front() == kvp.first) {
38 if (num.length() == 2) { // num is like 12".
39 count += num.back() >= kvp.second;
40 } else {
41 if (num.back() >= kvp.second) { // num is like "102".
42 count += countStrobogrammaticUntil(getMid(num), true);
43 } else if (getMid(num) != string(num.length() - 2, '0')) { // num is like "110".
44 count += countStrobogrammaticUntil(getMid(num), true) -
45 isStrobogrammatic(getMid(num));
46 }
47 }
48 }
49 }
50 }
51
52 if (!can_start_with_0) { // Sum up each length.
53 for (int i = num.length() - 1; i > 0; --i) {
54 count += countStrobogrammaticByLength(i);
55 }
56 } else {
57 cache[num] = count;
58 }
59
60 return count;
61 }
62
63 string getMid(const string& num) {
64 return num.substr(1, num.length() - 2);
65 }
66
67 int countStrobogrammaticByLength(int n) {
68 switch (n) {
69 case 1:
70 return 3; // "0", "1", "8"
71 case 2:
72 return 4; // "11", "69", "88", "96"
73 case 3:
74 return 4 * 3; // "101", "111", "181", ...
75 default:
76 return 5 * countStrobogrammaticByLength(n - 2);
77 }
78 }
79
80 bool isStrobogrammatic(const string& num) {
81 const int n = num.size();
82 for (int i = 0; i <= n - 1 - i; ++i) {
83 const auto it = lookup.find(num[n - 1 - i]);
84 if (it == lookup.end() || num[i] != it->second) {
85 return false;
86 }
87 }
88 return true;
89 }
90
91 private:
92 const unordered_map lookup{{'0', '0'}, {'1', '1'},
93 {'6', '9'}, {'8', '8'},
94 {'9', '6'}};
95 unordered_map cache;
96 };
**************************

50. Strobogrammatic Number III(Python)


**************************

1 # Time: O(5^(n/2))
2 # Space: O(n)
3
4 class Solution(object):
5 lookup = {'0':'0', '1':'1', '6':'9', '8':'8', '9':'6'}
6 cache = {}
7
8 # @param {string} low
9 # @param {string} high
10 # @return {integer}
11 def strobogrammaticInRange(self, low, high):
12 count = self.countStrobogrammaticUntil(high, False) - \
13 self.countStrobogrammaticUntil(low, False) + \
14 self.isStrobogrammatic(low)
15 return count if count >= 0 else 0
16
17 def countStrobogrammaticUntil(self, num, can_start_with_0):
18 if can_start_with_0 and num in self.cache:
19 return self.cache[num]
20
21 count = 0
22 if len(num) == 1:
23 for c in ['0', '1', '8']:
24 if num[0] >= c:
25 count += 1
26 self.cache[num] = count
27 return count
28
29 for key, val in self.lookup.iteritems():
30 if can_start_with_0 or key != '0':
31 if num[0] > key:
32 if len(num) == 2: # num is like "21"
33 count += 1
34 else: # num is like "201"
35 count += self.countStrobogrammaticUntil('9' * (len(num) - 2), True)
36 elif num[0] == key:
37 if len(num) == 2: # num is like 12".
38 if num[-1] >= val:
39 count += 1
40 else:
41 if num[-1] >= val: # num is like "102".
42 count += self.countStrobogrammaticUntil(self.getMid(num), True)
43 elif (self.getMid(num) != '0' * (len(num) - 2)): # num is like "110".
44 count += self.countStrobogrammaticUntil(self.getMid(num), True) - \
45 self.isStrobogrammatic(self.getMid(num))
46
47 if not can_start_with_0: # Sum up each length.
48 for i in xrange(len(num) - 1, 0, -1):
49 count += self.countStrobogrammaticByLength(i)
50 else:
51 self.cache[num] = count
52
53 return count
54
55 def getMid(self, num):
56 return num[1:len(num) - 1]
57
58 def countStrobogrammaticByLength(self, n):
59 if n == 1:
60 return 3
61 elif n == 2:
62 return 4
63 elif n == 3:
64 return 4 * 3
65 else:
66 return 5 * self.countStrobogrammaticByLength(n - 2)
67
68 def isStrobogrammatic(self, num):
69 n = len(num)
70 for i in xrange((n+1) / 2):
71 if num[n-1-i] not in self.lookup or \
72 num[i] != self.lookup[num[n-1-i]]:
73 return False
74 return True
75
***************

51. Trips and Users


***************

Table: Trips

+-------------+----------+
| Column Name | Type |
+-------------+----------+
| Id | int |
| Client_Id | int |
| Driver_Id | int |
| City_Id | int |
| Status | enum |
| Request_at | date |
+-------------+----------+
Id is the primary key for this table.
The table holds all taxi trips. Each trip has a unique Id, while Client_Id and Driver_Id are foreign keys to the Users_Id at the Users table.
Status is an ENUM type of (‘completed’, ‘cancelled_by_driver’, ‘cancelled_by_client’).

Table: Users

+-------------+----------+
| Column Name | Type |
+-------------+----------+
| Users_Id | int |
| Banned | enum |
| Role | enum |
+-------------+----------+
Users_Id is the primary key for this table.
The table holds all users. Each user has a unique Users_Id, and Role is an ENUM type of (‘client’, ‘driver’, ‘partner’).
Status is an ENUM type of (‘Yes’, ‘No’).

Write a SQL query to find the cancellation rate of requests with unbanned users (both client and driver must not be
banned) each day between "2013-10-01" and "2013-10-03".

The cancellation rate is computed by dividing the number of canceled (by client or driver) requests with unbanned users by
the total number of requests with unbanned users on that day.

Return the result table in any order. Round Cancellation Rate to two decimal points.

The query result format is in the following example:


Trips table:
+----+-----------+-----------+---------+---------------------+------------+
| Id | Client_Id | Driver_Id | City_Id | Status | Request_at |
+----+-----------+-----------+---------+---------------------+------------+
| 1 | 1 | 10 | 1 | completed | 2013-10-01 |
| 2 | 2 | 11 | 1 | cancelled_by_driver | 2013-10-01 |
| 3 | 3 | 12 | 6 | completed | 2013-10-01 |
| 4 | 4 | 13 | 6 | cancelled_by_client | 2013-10-01 |
| 5 | 1 | 10 | 1 | completed | 2013-10-02 |
| 6 | 2 | 11 | 6 | completed | 2013-10-02 |
| 7 | 3 | 12 | 6 | completed | 2013-10-02 |
| 8 | 2 | 12 | 12 | completed | 2013-10-03 |
| 9 | 3 | 10 | 12 | completed | 2013-10-03 |
| 10 | 4 | 13 | 12 | cancelled_by_driver | 2013-10-03 |
+----+-----------+-----------+---------+---------------------+------------+

Users table:
+----------+--------+--------+
| Users_Id | Banned | Role |
+----------+--------+--------+
| 1 | No | client |
| 2 | Yes | client |
| 3 | No | client |
| 4 | No | client |
| 10 | No | driver |
| 11 | No | driver |
| 12 | No | driver |
| 13 | No | driver |
+----------+--------+--------+

Result table:
+------------+-------------------+
| Day | Cancellation Rate |
+------------+-------------------+
| 2013-10-01 | 0.33 |
| 2013-10-02 | 0.00 |
| 2013-10-03 | 0.50 |
+------------+-------------------+

On 2013-10-01:
- There were 4 requests in total, 2 of which were canceled.
- However, the request with Id=2 was made by a banned client (User_Id=2), so it is ignored in the calculation.
- Hence there are 3 unbanned requests in total, 1 of which was canceled.
- The Cancellation Rate is (1 / 3) = 0.33
On 2013-10-02:
- There were 3 requests in total, 0 of which were canceled.
- The request with Id=6 was made by a banned client, so it is ignored.
- Hence there are 2 unbanned requests in total, 0 of which were canceled.
- The Cancellation Rate is (0 / 2) = 0.00
On 2013-10-03:
- There were 3 requests in total, 1 of which was canceled.
- The request with Id=8 was made by a banned client, so it is ignored.
- Hence there are 2 unbanned request in total, 1 of which were canceled.
- The Cancellation Rate is (1 / 2) = 0.50
***************

51. Trips and Users(Shell)


***************

1 # Time: O((t * u) + tlogt)


2 # Space: O(t)
3
4 select
5 t.Request_at Day,
6 round(sum(case when t.Status = 'completed' then 0 else 1 end) / count(*), 2) Rate
7 from Trips t
8 inner join Users u
9 on t.Client_Id = u.Users_Id and u.Banned = 'No'
10 where t.Request_at between '2013-10-01' and '2013-10-03'
11 group by t.Request_at
12
**************

52. Paint House II


**************

There are a row of n houses, each house can be painted with one of thek colors. The cost of painting each house with a
certain color is different. You have to paint all the houses such that no two adjacent houses have the same color.

The cost of painting each house with a certain color is represented by ann x k cost matrix costs.

For example, costs[0][0] is the cost of painting house 0 with color 0; costs[1][2] is the cost of painting house 1 with color 2,
and so on...

Return the minimum cost to paint all houses.

Example 1:

Input: costs = [[1,5,3],[2,9,4]]


Output: 5
Explanation:
Paint house 0 into color 0, paint house 1 into color 2. Minimum cost: 1 + 4 = 5;
Or paint house 0 into color 2, paint house 1 into color 0. Minimum cost: 3 + 2 = 5.

Example 2:

Input: costs = [[1,3],[2,4]]


Output: 5

Constraints:

costs.length == n
costs[i].length == k
1 <= n <= 100
1 <= k <= 20
1 <= costs[i][j] <= 20

Follow up: Could you solve it in O(nk) runtime?


**************

52. Paint House II(C++)


**************

1 // Time: O(n * k)
2 // Space: O(k)
3
4 class Solution {
5 public:
6 int minCostII(vector>& costs) {
7 if (costs.empty()) {
8 return 0;
9 }
10
11 vector> min_cost(2, costs[0]);
12
13 const int n = costs.size();
14 const int k = costs[0].size();
15 for (int i = 1; i < n; ++i) {
16 int smallest = numeric_limits::max(), second_smallest = numeric_limits::max();
17 for (int j = 0; j < k; ++j) {
18 if (min_cost[(i - 1) % 2][j] < smallest) {
19 second_smallest = smallest;
20 smallest = min_cost[(i - 1) % 2][j];
21 } else if (min_cost[(i - 1) % 2][j] < second_smallest) {
22 second_smallest = min_cost[(i - 1) % 2][j];
23 }
24 }
25 for (int j = 0; j < k; ++j) {
26 const int min_j = (min_cost[(i - 1) % 2][j] != smallest) ? smallest : second_smallest;
27 min_cost[i % 2][j] = costs[i][j] + min_j;
28 }
29 }
30
31 return *min_element(min_cost[(n - 1) % 2].cbegin(), min_cost[(n - 1) % 2].cend());
32 }
33 };
34
35 // Time: O(n * k)
36 // Space: O(k)
37 class Solution2{
38 public:
39 int minCostII(vector>& costs) {
40 if (costs.empty()) {
41 return 0;
42 }
43 auto combine = [](const vector& tmp, const vector& house) {
44 const int smallest = *min_element(tmp.cbegin(), tmp.cend());
45 const int i = distance(tmp.begin(), find(tmp.cbegin(), tmp.cend(), smallest));
46 vector tmp2(tmp);
47 tmp2.erase(tmp2.begin() + i);
48 const int second_smallest = *min_element(tmp2.cbegin(), tmp2.cend());
49 vector min_cost(tmp.size(), smallest);
50 min_cost[i] = second_smallest;
51 transform(min_cost.cbegin(), min_cost.cend(), house.cbegin(),
52 min_cost.begin(), std::plus());
53 return min_cost;
54 };
55 vector min_cost = accumulate(costs.cbegin(), costs.cend(), vector(costs[0].size(), 0), combine);
56 return *min_element(min_cost.cbegin(), min_cost.cend());
57 }
58 };
**************

52. Paint House II(Python)


**************

1 # Time: O(n * k)
2 # Space: O(k)
3
4 class Solution2(object):
5 def minCostII(self, costs):
6 """
7 :type costs: List[List[int]]
8 :rtype: int
9 """
10 return min(reduce(self.combine, costs)) if costs else 0
11
12 def combine(self, tmp, house):
13 smallest, k, i = min(tmp), len(tmp), tmp.index(min(tmp))
14 tmp, tmp[i] = [smallest] * k, min(tmp[:i] + tmp[i+1:])
15 return map(sum, zip(tmp, house))
16
17
18 class Solution2(object):
19 def minCostII(self, costs):
20 """
21 :type costs: List[List[int]]
22 :rtype: int
23 """
24 if not costs:
25 return 0
26
27 n = len(costs)
28 k = len(costs[0])
29 min_cost = [costs[0], [0] * k]
30 for i in xrange(1, n):
31 smallest, second_smallest = float("inf"), float("inf")
32 for j in xrange(k):
33 if min_cost[(i - 1) % 2][j] < smallest:
34 smallest, second_smallest = min_cost[(i - 1) % 2][j], smallest
35 elif min_cost[(i - 1) % 2][j] < second_smallest:
36 second_smallest = min_cost[(i - 1) % 2][j]
37 for j in xrange(k):
38 min_j = smallest if min_cost[(i - 1) % 2][j] != smallest else second_smallest
39 min_cost[i % 2][j] = costs[i][j] + min_j
40
41 return min(min_cost[(n - 1) % 2])
42
****************

53. Alien Dictionary


****************

There is a new alien language that uses the English alphabet. However, the order among the letters is unknown to you.

You are given a list of strings words from the alien language's dictionary, where the strings inwords are sorted
lexicographically by the rules of this new language.

Return a string of the unique letters in the new alien language sorted inlexicographically increasing order by the new
language's rules. If there is no solution, return "". If there are multiple solutions, return any of them.

A string s is lexicographically smaller than a string t if at the first letter where they differ, the letter ins comes before the
letter in t in the alien language. If the first min(s.length, t.length) letters are the same, then s is smaller if and only if s.length <
t.length .

Example 1:

Input: words = ["wrt","wrf","er","ett","rftt"]


Output: "wertf"

Example 2:

Input: words = ["z","x"]


Output: "zx"

Example 3:

Input: words = ["z","x","z"]


Output: ""
Explanation: The order is invalid, so return "".

Constraints:

1 <= words.length <= 100


1 <= words[i].length <= 100
words[i] consists of only lowercase English letters.
****************

53. Alien Dictionary(C++)


****************

1 // Time: O(n)
2 // Space: O(|V|+|E|) = O(26 + 26^2) = O(1)
3
4 // BFS solution.
5 class Solution {
6 public:
7 string alienOrder(vector& words) {
8 unordered_set nodes;
9 unordered_map> in_degree, out_degree;
10 queue zero_in_degree_queue;
11 for (const auto& word : words) {
12 for (const auto& c : word) {
13 nodes.emplace(c);
14 }
15 }
16 for (int i = 1; i < words.size(); ++i) {
17 if (words[i - 1].length() > words[i].length() &&
18 words[i - 1].substr(0, words[i].length()) == words[i]) {
19 return "";
20 }
21 findEdges(words[i - 1], words[i], &in_degree, &out_degree);
22 }
23 for (const auto& node : nodes) {
24 if (in_degree.find(node) == in_degree.end()) {
25 zero_in_degree_queue.emplace(node);
26 }
27 }
28
29 // BFS
30 string result;
31 while (!zero_in_degree_queue.empty()) {
32 const auto& precedence = zero_in_degree_queue.front();
33 zero_in_degree_queue.pop();
34 result.push_back(precedence);
35
36 if (out_degree.find(precedence) != out_degree.end()) {
37 for (const auto& c : out_degree[precedence]) {
38 in_degree[c].erase(precedence);
39 if (in_degree[c].empty()) {
40 zero_in_degree_queue.emplace(c);
41 }
42 }
43 out_degree.erase(precedence);
44 }
45 }
46
47 if (!out_degree.empty()) {
48 return "";
49 }
50
51 return result;
52 }
53
54 private:
55 // Construct the graph.
56 void findEdges(const string &word1, const string &word2,
57 unordered_map> *in_degree,
58 unordered_map> *out_degree) {
59 const int len = min(word1.length(), word2.length());
60 for (int i = 0; i < len; ++i) {
61 if (word1[i] != word2[i]) {
62 (*in_degree)[word2[i]].emplace(word1[i]);
63 (*out_degree)[word1[i]].emplace(word2[i]);
64 break;
65 }
66 }
67 }
68 };
69
70 // DFS solution.
71 class Solution2 {
72 public:
73 string alienOrder(vector& words) {
74 // Find ancestors of each node by DFS.
75 unordered_set nodes;
76 unordered_map> ancestors;
77 for (int i = 0; i < words.size(); ++i) {
78 for (const auto& c : words[i]) {
79 nodes.emplace(c);
80 }
81 if (i > 0) {
82 findEdges(words[i - 1], words[i], &ancestors);
83 }
84 }
85
86 // Output topological order by DFS.
87 string result;
88 unordered_map visited;
89 for (const auto& node : nodes) {
90 if (topSortDFS(node, node, &ancestors, &visited, &result)) {
91 return "";
92 }
93 }
94
95 return result;
96 }
97
98 private:
99 // Construct the graph.
100 void findEdges(const string &word1, const string &word2,
101 unordered_map> *ancestors) {
102 const int len = min(word1.length(), word2.length());
103 for (int i = 0; i < len; ++i) {
104 if (word1[i] != word2[i]) {
105 (*ancestors)[word2[i]].emplace_back(word1[i]);
106 break;
107 }
108 }
109 }
110
111 // Topological sort, return whether there is a cycle.
112 bool topSortDFS(const char& root,
113 const char& node,
114 unordered_map> *ancestors,
115 unordered_map *visited,
116 string *result) {
117 if (visited->emplace(make_pair(node, root)).second) {
118 for (auto& ancestor: (*ancestors)[node]) {
119 if (topSortDFS(root, ancestor, ancestors, visited, result)) {
120 return true;
121 }
122 }
123 result->push_back(node);
124 } else if ((*visited)[node] == root) {
125 // Visited from the same root in the DFS path.
126 // So it is cyclic.
127 return true;
128 }
129 return false;
130 }
131 };
132
133 // DFS with adjacency matrix solution.
134 class Solution3 {
135 public:
135 public:
136 string alienOrder(vector& words) {
137 string result;
138 vector> graph(26, vector(26));
139 findDependency(words, &graph);
140 findOrder(&graph, &result);
141 return result;
142 }
143
144 private:
145 void findEdges(const string &word1, const string &word2, vector> *graph) {
146 const int len = min(word1.length(), word2.length());
147 for (int i = 0; i < len; ++i) {
148 if (word1[i] != word2[i]) {
149 (*graph)[word1[i] - 'a'][word2[i] - 'a'] = true;
150 break;
151 }
152 }
153 }
154
155 // Construct the graph.
156 void findDependency(const vector& words, vector> *graph) {
157 for (const auto& c : words[0]) {
158 (*graph)[c - 'a'][c - 'a'] = true;
159 }
160 for (int i = 1; i < words.size(); ++i) {
161 for (const auto& c : words[i]) {
162 (*graph)[c - 'a'] [c - 'a'] = true;
163 }
164 findEdges(words[i - 1], words[i], graph);
165 }
166 }
167
168 // Topological sort, return whether there is a cycle.
169 bool topSortDFS(string *result, vector *visited,
170 vector> *graph, const int root) {
171 if ((*visited)[root]) {
172 result->clear();
173 return true;
174 }
175 (*visited)[root] = true;
176 for (int i = 0; i < 26; ++i) {
177 if (i != root && (*graph)[root][i]) {
178 if (topSortDFS(result, visited, graph, i)) {
179 return true;
180 }
181 }
182 }
183 (*graph)[root][root] = false;
184 result->push_back(root + 'a');
185 return false;
186 }
187
188 void findOrder(vector> *graph, string *result) {
189 for (int i = 0; i < 26; ++i) {
190 // Find a root node.
191 bool root_node = (*graph)[i][i];
192 if ((*graph)[i][i]) {
193 for (int j = 0; j < 26; ++j) {
194 if (j != i && (*graph)[j][i]) {
195 root_node = false;
196 break;
197 }
198 }
199 }
200 if (root_node) {
201 string reversed_order = "";
202 vector visited(26, false);
203 if (topSortDFS(&reversed_order, &visited, graph, i)) {
204 result->clear();
205 return;
206 } else {
207 result->append(reversed_order);
208 }
208 }
209 }
210 }
211
212 // If there is any unvisited node, return "".
213 for (int i = 0; i < 26; ++i) {
214 if ((*graph)[i][i]) {
215 result->clear();
216 return;
217 }
218 }
219 // The order should be reversed.
220 reverse(result->begin(), result->end());
221 }
222 };
****************

53. Alien Dictionary(Python)


****************

1 # Time: O(n)
2 # Space: O(|V|+|E|) = O(26 + 26^2) = O(1)
3
4 import collections
5
6
7 # BFS solution.
8 class Solution(object):
9 def alienOrder(self, words):
10 """
11 :type words: List[str]
12 :rtype: str
13 """
14 result, in_degree, out_degree = [], {}, {}
15 zero_in_degree_queue = collections.deque()
16 nodes = set()
17 for word in words:
18 for c in word:
19 nodes.add(c)
20
21 for i in xrange(1, len(words)):
22 if (len(words[i-1]) > len(words[i]) and
23 words[i-1][:len(words[i])] == words[i]):
24 return ""
25 self.findEdges(words[i - 1], words[i], in_degree, out_degree)
26
27 for node in nodes:
28 if node not in in_degree:
29 zero_in_degree_queue.append(node)
30
31 while zero_in_degree_queue:
32 precedence = zero_in_degree_queue.popleft()
33 result.append(precedence)
34
35 if precedence in out_degree:
36 for c in out_degree[precedence]:
37 in_degree[c].discard(precedence)
38 if not in_degree[c]:
39 zero_in_degree_queue.append(c)
40
41 del out_degree[precedence]
42
43 if out_degree:
44 return ""
45
46 return "".join(result)
47
48 # Construct the graph.
49 def findEdges(self, word1, word2, in_degree, out_degree):
50 str_len = min(len(word1), len(word2))
51 for i in xrange(str_len):
52 if word1[i] != word2[i]:
53 if word2[i] not in in_degree:
54 in_degree[word2[i]] = set()
55 if word1[i] not in out_degree:
56 out_degree[word1[i]] = set()
57 in_degree[word2[i]].add(word1[i])
58 out_degree[word1[i]].add(word2[i])
59 break
60
61
62 # DFS solution.
63 class Solution2(object):
64 def alienOrder(self, words):
65 """
66 :type words: List[str]
67 :rtype: str
68 """
69 # Find ancestors of each node by DFS.
70 nodes, ancestors = set(), {}
71 for i in xrange(len(words)):
72 for c in words[i]:
73 nodes.add(c)
74 for node in nodes:
75 ancestors[node] = []
76 for i in xrange(1, len(words)):
77 if (len(words[i-1]) > len(words[i]) and
78 words[i-1][:len(words[i])] == words[i]):
79 return ""
80 self.findEdges(words[i - 1], words[i], ancestors)
81
82 # Output topological order by DFS.
83 result = []
84 visited = {}
85 for node in nodes:
86 if self.topSortDFS(node, node, ancestors, visited, result):
87 return ""
88
89 return "".join(result)
90
91 # Construct the graph.
92 def findEdges(self, word1, word2, ancestors):
93 min_len = min(len(word1), len(word2))
94 for i in xrange(min_len):
95 if word1[i] != word2[i]:
96 ancestors[word2[i]].append(word1[i])
97 break
98
99 # Topological sort, return whether there is a cycle.
100 def topSortDFS(self, root, node, ancestors, visited, result):
101 if node not in visited:
102 visited[node] = root
103 for ancestor in ancestors[node]:
104 if self.topSortDFS(root, ancestor, ancestors, visited, result):
105 return True
106 result.append(node)
107 elif visited[node] == root:
108 # Visited from the same root in the DFS path.
109 # So it is cyclic.
110 return True
111 return False
112
***********************************

54. Closest Binary Search Tree Value II


***********************************

Given the root of a binary search tree, a target value, and an integer k , return the k values in the BST that are closest to the
target. You may return the answer in any order.

You are guaranteed to have only one unique set ofk values in the BST that are closest to thetarget.

Example 1:

Input: root = [4,2,5,1,3], target = 3.714286, k = 2


Output: [4,3]

Example 2:

Input: root = [1], target = 0.000000, k = 1


Output: [1]

Constraints:

The number of nodes in the tree is n.


1 <= k <= n <= 10 4.
0 <= Node.val <= 10 9
-109 <= target <= 10 9

Follow up: Assume that the BST is balanced. Could you solve it in less thanO(n) runtime (where n = total nodes )?
***********************************

54. Closest Binary Search Tree Value II(C++)


***********************************
1 // Time: O(h + k)
2 // Space: O(h)
3
4 /**
5 * Definition for a binary tree node.
6 * struct TreeNode {
7 * int val;
8 * TreeNode *left;
9 * TreeNode *right;
10 * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
11 * };
12 */
13 class Solution {
14 public:
15 vector closestKValues(TreeNode* root, double target, int k) {
16 // The forward or backward iterator.
17 const auto backward = [](const vector& s) { return s.back()->left; };
18 const auto forward = [](const vector& s) { return s.back()->right; };
19 const auto closest = [&target](const TreeNode* a, const TreeNode* b) {
20 return abs(a->val - target) < abs(b->val - target);
21 };
22
23 // Build the stack to the closest node.
24 vector s;
25 while (root) {
26 s.emplace_back(root);
27 root = target < root->val ? root->left : root->right;
28 }
29
30 // Get the stack to the next smaller node.
31 vector forward_stack(s.cbegin(), next(min_element(s.cbegin(), s.cend(), closest)));
32 vector backward_stack(forward_stack);
33 nextNode(backward_stack, backward, forward);
34
35 // Get the closest k values by advancing the iterators of the stacks.
36 vector result;
37 for (int i = 0; i < k; ++i) {
38 if (!forward_stack.empty() &&
39 (backward_stack.empty() || closest(forward_stack.back(), backward_stack.back()))) {
40 result.emplace_back(forward_stack.back()->val);
41 nextNode(forward_stack, forward, backward);
42 } else if (!backward_stack.empty() &&
43 (forward_stack.empty() || !closest(forward_stack.back(), backward_stack.back()))) {
44 result.emplace_back(backward_stack.back()->val);
45 nextNode(backward_stack, backward, forward);
46 }
47 }
48 return result;
49 }
50
51 // Helper to make a stack to the next node.
52 template
53 void nextNode(vector& s, const T& child1, const U& child2) {
54 if (!s.empty()) {
55 if (child2(s)) {
56 s.emplace_back(child2(s));
57 while (child1(s)) {
58 s.emplace_back(child1(s));
59 }
60 } else {
61 auto child = s.back();
62 s.pop_back();
63 while (!s.empty() && child == child2(s)) {
64 child = s.back();
65 s.pop_back();
66 }
67 }
68 }
69 }
70 };
***********************************

54. Closest Binary Search Tree Value II(Python)


***********************************

1 # Time: O(h + k)
2 # Space: O(h)
3
4 class Solution(object):
5 def closestKValues(self, root, target, k):
6 """
7 :type root: TreeNode
8 :type target: float
9 :type k: int
10 :rtype: List[int]
11 """
12 # Helper to make a stack to the next node.
13 def nextNode(stack, child1, child2):
14 if stack:
15 if child2(stack):
16 stack.append(child2(stack))
17 while child1(stack):
18 stack.append(child1(stack))
19 else:
20 child = stack.pop()
21 while stack and child is child2(stack):
22 child = stack.pop()
23
24 # The forward or backward iterator.
25 backward = lambda stack: stack[-1].left
26 forward = lambda stack: stack[-1].right
27
28 # Build the stack to the closest node.
29 stack = []
30 while root:
31 stack.append(root)
32 root = root.left if target < root.val else root.right
33 dist = lambda node: abs(node.val - target)
34 forward_stack = stack[:stack.index(min(stack, key=dist))+1]
35
36 # Get the stack to the next smaller node.
37 backward_stack = list(forward_stack)
38 nextNode(backward_stack, backward, forward)
39
40 # Get the closest k values by advancing the iterators of the stacks.
41 result = []
42 for _ in xrange(k):
43 if forward_stack and \
44 (not backward_stack or dist(forward_stack[-1]) < dist(backward_stack[-1])):
45 result.append(forward_stack[-1].val)
46 nextNode(forward_stack, forward, backward)
47 elif backward_stack and \
48 (not forward_stack or dist(backward_stack[-1]) <= dist(forward_stack[-1])):
49 result.append(backward_stack[-1].val)
50 nextNode(backward_stack, backward, forward)
51 return result
52
53
54 class Solution2(object):
55 def closestKValues(self, root, target, k):
56 """
57 :type root: TreeNode
58 :type target: float
59 :type k: int
60 :rtype: List[int]
61 """
62 # Helper class to make a stack to the next node.
63 class BSTIterator:
64 # @param root, a binary search tree's root node
65 def __init__(self, stack, child1, child2):
66 self.stack = list(stack)
67 self.cur = self.stack.pop()
68 self.child1 = child1
69 self.child2 = child2
70
71 # @return an integer, the next node
72 def next(self):
73 node = None
74 if self.cur and self.child1(self.cur):
75 self.stack.append(self.cur)
76 node = self.child1(self.cur)
77 while self.child2(node):
78 self.stack.append(node)
79 node = self.child2(node)
80 elif self.stack:
81 prev = self.cur
82 node = self.stack.pop()
83 while node:
84 if self.child2(node) is prev:
85 break
86 else:
87 prev = node
88 node = self.stack.pop() if self.stack else None
89 self.cur = node
90 return node
91
92 # Build the stack to the closet node.
93 stack = []
94 while root:
95 stack.append(root)
96 root = root.left if target < root.val else root.right
97 dist = lambda node: abs(node.val - target) if node else float("inf")
98 stack = stack[:stack.index(min(stack, key=dist))+1]
99
100 # The forward or backward iterator.
101 backward = lambda node: node.left
102 forward = lambda node: node.right
103 smaller_it, larger_it = BSTIterator(stack, backward, forward), BSTIterator(stack, forward, backward)
104 smaller_node, larger_node = smaller_it.next(), larger_it.next()
105
106 # Get the closest k values by advancing the iterators of the stacks.
107 result = [stack[-1].val]
108 for _ in xrange(k - 1):
109 if dist(smaller_node) < dist(larger_node):
110 result.append(smaller_node.val)
111 smaller_node = smaller_it.next()
112 else:
113 result.append(larger_node.val)
114 larger_node = larger_it.next()
115 return result
116
117
118
************************

55. Integer to English Words


************************

Convert a non-negative integer num to its English words representation.

Example 1:

Input: num = 123


Output: "One Hundred Twenty Three"

Example 2:

Input: num = 12345


Output: "Twelve Thousand Three Hundred Forty Five"

Example 3:

Input: num = 1234567


Output: "One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven"

Example 4:

Input: num = 1234567891


Output: "One Billion Two Hundred Thirty Four Million Five Hundred Sixty Seven Thousand Eight Hundred Ninety One"

Constraints:

0 <= num <= 2 31 - 1


************************

55. Integer to English Words(C++)


************************
1 // Time: O(logn) = O(1), n is the value of the integer, which is less than 2^31 - 1
2 // Space: O(1)
3
4 class Solution {
5 public:
6 string numberToWords(int num) {
7 if (num == 0) {
8 return "Zero";
9 }
10 const unordered_map lookup = {{0, "Zero"}, {1, "One"}, {2, "Two"},
11 {3, "Three"}, {4, "Four"}, {5, "Five"},
12 {6, "Six"}, {7, "Seven"}, {8, "Eight"},
13 {9, "Nine"}, {10, "Ten"}, {11, "Eleven"},
14 {12, "Twelve"}, {13, "Thirteen"}, {14, "Fourteen"},
15 {15, "Fifteen"}, {16, "Sixteen"}, {17, "Seventeen"},
16 {18, "Eighteen"}, {19, "Nineteen"}, {20, "Twenty"},
17 {30, "Thirty"}, {40, "Forty"}, {50, "Fifty"},
18 {60, "Sixty"}, {70, "Seventy"}, {80, "Eighty"},
19 {90, "Ninety"}};
20 const vector unit{"", "Thousand", "Million", "Billion"};
21
22 vector res;
23 int i = 0;
24 while (num) {
25 const int cur = num % 1000;
26 if (num % 1000) {
27 res.emplace_back(threeDigits(cur, lookup, unit[i]));
28 }
29 num /= 1000;
30 ++i;
31 }
32 reverse(res.begin(), res.end());
33 return join(res, " ");
34 }
35
36 string join(const vector& strings, const string& delim) {
37 if (strings.empty()) {
38 return "";
39 }
40 ostringstream imploded;
41 copy(strings.begin(), prev(strings.end()), ostream_iterator(imploded, delim.c_str()));
42 return imploded.str() + *prev(strings.end());
43 }
44
45 string threeDigits(const int& num, const unordered_map& lookup, const string& unit) {
46 vector res;
47 if (num / 100) {
48 res.emplace_back(lookup.find(num / 100)->second + " " + "Hundred");
49 }
50 if (num % 100) {
51 res.emplace_back(twoDigits(num % 100, lookup));
52 }
53 if (!unit.empty()) {
54 res.emplace_back(unit);
55 }
56 return join(res, " ");
57 }
58
59 string twoDigits(const int& num, const unordered_map& lookup) {
60 if (lookup.find(num) != lookup.end()) {
61 return lookup.find(num)->second;
62 }
63 return lookup.find((num / 10) * 10)->second + " " + lookup.find(num % 10)->second;
64 }
65 };
************************

55. Integer to English Words(Python)


************************

1 # Time: O(logn) = O(1), n is the value of the integer, which is less than 2^31 - 1
2 # Space: O(1)
3
4 class Solution(object):
5 def numberToWords(self, num):
6 """
7 :type num: int
8 :rtype: str
9 """
10 if num == 0:
11 return "Zero"
12
13 lookup = {0: "Zero", 1:"One", 2: "Two", 3: "Three", 4: "Four", \
14 5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine", \
15 10: "Ten", 11: "Eleven", 12: "Twelve", 13: "Thirteen", 14: "Fourteen", \
16 15: "Fifteen", 16: "Sixteen", 17: "Seventeen", 18: "Eighteen", 19: "Nineteen", \
17 20: "Twenty", 30: "Thirty", 40: "Forty", 50: "Fifty", 60: "Sixty", \
18 70: "Seventy", 80: "Eighty", 90: "Ninety"}
19 unit = ["", "Thousand", "Million", "Billion"]
20
21 res, i = [], 0
22 while num:
23 cur = num % 1000
24 if num % 1000:
25 res.append(self.threeDigits(cur, lookup, unit[i]))
26 num //= 1000
27 i += 1
28 return " ".join(res[::-1])
29
30 def threeDigits(self, num, lookup, unit):
31 res = []
32 if num / 100:
33 res = [lookup[num / 100] + " " + "Hundred"]
34 if num % 100:
35 res.append(self.twoDigits(num % 100, lookup))
36 if unit != "":
37 res.append(unit)
38 return " ".join(res)
39
40 def twoDigits(self, num, lookup):
41 if num in lookup:
42 return lookup[num]
43 return lookup[(num / 10) * 10] + " " + lookup[num % 10]
44
************************

56. Expression Add Operators


************************

Given a string num that contains only digits and an integer target, return all possibilities to add the binary operators '+' , '-', or '*'
between the digits of num so that the resultant expression evaluates to thetarget value.

Example 1:

Input: num = "123", target = 6


Output: ["1*2*3","1+2+3"]

Example 2:

Input: num = "232", target = 8


Output: ["2*3+2","2+3*2"]

Example 3:

Input: num = "105", target = 5


Output: ["1*0+5","10-5"]

Example 4:

Input: num = "00", target = 0


Output: ["0*0","0+0","0-0"]

Example 5:

Input: num = "3456237490", target = 9191


Output: []

Constraints:

1 <= num.length <= 10


num consists of only digits.
-231 <= target <= 2 31 - 1
************************

56. Expression Add Operators(C++)


************************
1 // Time: O(4^n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 vector addOperators(string num, int target) {
7 vector result;
8 vector expr;
9 int val = 0;
10 string val_str;
11 for (int i = 0; i < num.length(); ++i) {
12 val = val * 10 + num[i] - '0';
13 val_str.push_back(num[i]);
14 // Avoid overflow and "00...".
15 if (to_string(val) != val_str) {
16 break;
17 }
18 expr.emplace_back(val_str);
19 addOperatorsDFS(num, target, i + 1, 0, val, &expr, &result);
20 expr.pop_back();
21 }
22 return result;
23 }
24
25 void addOperatorsDFS(const string& num, const int& target, const int& pos,
26 const int& operand1, const int& operand2,
27 vector *expr, vector *result) {
28 if (pos == num.length() && operand1 + operand2 == target) {
29 result->emplace_back(join(*expr));
30 } else {
31 int val = 0;
32 string val_str;
33 for (int i = pos; i < num.length(); ++i) {
34 val = val * 10 + num[i] - '0';
35 val_str.push_back(num[i]);
36 // Avoid overflow and "00...".
37 if (to_string(val) != val_str) {
38 break;
39 }
40
41 // Case '+':
42 expr->emplace_back("+" + val_str);
43 addOperatorsDFS(num, target, i + 1, operand1 + operand2, val, expr, result);
44 expr->pop_back();
45
46 // Case '-':
47 expr->emplace_back("-" + val_str);
48 addOperatorsDFS(num, target, i + 1, operand1 + operand2, -val, expr, result);
49 expr->pop_back();
50
51 // Case '*':
52 expr->emplace_back("*" + val_str);
53 addOperatorsDFS(num, target, i + 1, operand1, operand2 * val, expr, result);
54 expr->pop_back();
55 }
56 }
57 }
58
59 string join(const vector& expr) {
60 ostringstream stream;
61 copy(expr.cbegin(), expr.cend(), ostream_iterator(stream));
62 return stream.str();
63 }
64 };
************************

56. Expression Add Operators(Python)


************************

1 # Time: O(4^n)
2 # Space: O(n)
3
4 class Solution(object):
5 def addOperators(self, num, target):
6 """
7 :type num: str
8 :type target: int
9 :rtype: List[str]
10 """
11 result, expr = [], []
12 val, i = 0, 0
13 val_str = ""
14 while i < len(num):
15 val = val * 10 + ord(num[i]) - ord('0')
16 val_str += num[i]
17 # Avoid "00...".
18 if str(val) != val_str:
19 break
20 expr.append(val_str)
21 self.addOperatorsDFS(num, target, i + 1, 0, val, expr, result)
22 expr.pop()
23 i += 1
24 return result
25
26 def addOperatorsDFS(self, num, target, pos, operand1, operand2, expr, result):
27 if pos == len(num) and operand1 + operand2 == target:
28 result.append("".join(expr))
29 else:
30 val, i = 0, pos
31 val_str = ""
32 while i < len(num):
33 val = val * 10 + ord(num[i]) - ord('0')
34 val_str += num[i]
35 # Avoid "00...".
36 if str(val) != val_str:
37 break
38
39 # Case '+':
40 expr.append("+" + val_str)
41 self.addOperatorsDFS(num, target, i + 1, operand1 + operand2, val, expr, result)
42 expr.pop()
43
44 # Case '-':
45 expr.append("-" + val_str)
46 self.addOperatorsDFS(num, target, i + 1, operand1 + operand2, -val, expr, result)
47 expr.pop()
48
49 # Case '*':
50 expr.append("*" + val_str)
51 self.addOperatorsDFS(num, target, i + 1, operand1, operand2 * val, expr, result)
52 expr.pop()
53
54 i += 1
55
56
*************************

57. Find the Duplicate Number


*************************

Given an array of integers nums containing n + 1 integers where each integer is in the range [1, n] inclusive.

There is only one repeated number in nums, return this repeated number.

You must solve the problem without modifying the array nums and uses only constant extra space.

Example 1:

Input: nums = [1,3,4,2,2]


Output: 2

Example 2:

Input: nums = [3,1,3,4,2]


Output: 3

Example 3:

Input: nums = [1,1]


Output: 1

Example 4:

Input: nums = [1,1,2]


Output: 1

Constraints:

1 <= n <= 10 5
nums.length == n + 1
1 <= nums[i] <= n
All the integers in nums appear only once except for precisely one integer which appears two or more times.

Follow up:

How can we prove that at least one duplicate number must exist innums?
Can you solve the problem in linear runtime complexity?
*************************

57. Find the Duplicate Number(C++)


*************************

1 // Time: O(n)
2 // Space: O(1)
3
4 // Two pointers method, same as Linked List Cycle II.
5 class Solution {
6 public:
7 int findDuplicate(vector& nums) {
8 int slow = nums[0];
9 int fast = nums[nums[0]];
10 while (slow != fast) {
11 slow = nums[slow];
12 fast = nums[nums[fast]];
13 }
14
15 fast = 0;
16 while (slow != fast) {
17 slow = nums[slow];
18 fast = nums[fast];
19 }
20 return slow;
21 }
22 };
23
24 // Time: O(nlogn)
25 // Space: O(1)
26 // Binary search method.
27 class Solution2 {
28 public:
29 int findDuplicate(vector& nums) {
30 int left = 1, right = nums.size();
31
32 while (left <= right) {
33 const int mid = left + (right - left) / 2;
34 // Get count of num <= mid.
35 int count = 0;
36 for (const auto& num : nums) {
37 if (num <= mid) {
38 ++count;
39 }
40 }
41 if (count > mid) {
42 right = mid - 1;
43 } else {
44 left = mid + 1;
45 }
46 }
47 return left;
48 }
49 };
50
51 // Time: O(n)
52 // Space: O(n)
53 class Solution3 {
54 public:
55 int findDuplicate(vector& nums) {
56 int duplicate = 0;
57 // Mark the value as visited by negative.
58 for (auto& num : nums) {
59 if (nums[abs(num) - 1] > 0) {
60 nums[abs(num) - 1] *= -1;
61 } else {
62 duplicate = abs(num);
63 break;
64 }
65 }
66 // Rollback the value.
67 for (auto& num : nums) {
68 if (nums[abs(num) - 1] < 0) {
69 nums[abs(num) - 1] *= -1;
70 } else {
71 break;
72 }
73 }
74 return duplicate;
75 }
76 };
*************************

57. Find the Duplicate Number(Python)


*************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def findDuplicate(self, nums):
6 """
7 :type nums: List[int]
8 :rtype: int
9 """
10 # Treat each (key, value) pair of the array as the (pointer, next) node of the linked list,
11 # thus the duplicated number will be the begin of the cycle in the linked list.
12 # Besides, there is always a cycle in the linked list which
13 # starts from the first element of the array.
14 slow = nums[0]
15 fast = nums[nums[0]]
16 while slow != fast:
17 slow = nums[slow]
18 fast = nums[nums[fast]]
19
20 fast = 0
21 while slow != fast:
22 slow = nums[slow]
23 fast = nums[fast]
24 return slow
25
26
27 # Time: O(nlogn)
28 # Space: O(1)
29 # Binary search method.
30 class Solution2(object):
31 def findDuplicate(self, nums):
32 """
33 :type nums: List[int]
34 :rtype: int
35 """
36 left, right = 1, len(nums) - 1
37
38 while left <= right:
39 mid = left + (right - left) / 2
40 # Get count of num <= mid.
41 count = 0
42 for num in nums:
43 if num <= mid:
44 count += 1
45 if count > mid:
46 right = mid - 1
47 else:
48 left = mid + 1
49 return left
50
51 # Time: O(n)
52 # Space: O(n)
53 class Solution3(object):
54 def findDuplicate(self, nums):
55 """
56 :type nums: List[int]
57 :rtype: int
58 """
59 duplicate = 0
60 # Mark the value as visited by negative.
61 for num in nums:
62 if nums[abs(num) - 1] > 0:
63 nums[abs(num) - 1] *= -1
64 else:
65 duplicate = abs(num)
66 break
67 # Rollback the value.
68 for num in nums:
69 if nums[abs(num) - 1] < 0:
70 nums[abs(num) - 1] *= -1
71 else:
72 break
73 return duplicate
74
***************

58. Word Pattern II


***************

Given a pattern and a string s , return true if s matches the pattern.

A string s matches a pattern if there is some bijective mapping of single characters to strings such that if each character in
pattern is replaced by the string it maps to, then the resulting string iss . A bijective mapping means that no two characters
map to the same string, and no character maps to two different strings.

Example 1:

Input: pattern = "abab", s = "redblueredblue"


Output: true
Explanation: One possible mapping is as follows:
'a' -> "red"
'b' -> "blue"

Example 2:

Input: pattern = "aaaa", s = "asdasdasdasd"


Output: true
Explanation: One possible mapping is as follows:
'a' -> "asd"

Example 3:

Input: pattern = "abab", s = "asdasdasdasd"


Output: true
Explanation: One possible mapping is as follows:
'a' -> "a"
'b' -> "sdasd"
Note that 'a' and 'b' cannot both map to "asd" since the mapping is a bijection.

Example 4:

Input: pattern = "aabb", s = "xyzabcxzyabc"


Output: false

Constraints:

1 <= pattern.length, s.length <= 20


pattern and s consist of only lower-case English letters.
***************

58. Word Pattern II(C++)


***************

1 // Time: O(n * C(n - 1, c - 1)), n is length of str, c is unique count of pattern,


2 // there are H(n - c, c - 1) = C(n - 1, c - 1) possible splits of string,
3 // and each one costs O(n) to check if it matches the word pattern.
4 // Space: O(n + c)
5
6 class Solution {
7 public:
8 bool wordPatternMatch(string pattern, string str) {
9 unordered_map w2p;
10 unordered_map p2w;
11 return match(pattern, str, 0, 0, &w2p, &p2w);
12 }
13
14 bool match(const string &pattern, const string &str,
15 const int i, const int j,
16 unordered_map* w2p,
17 unordered_map* p2w) {
18
19 bool is_match = false;
20 if (i == pattern.length() && j == str.length()) {
21 is_match = true;
22 } else if (i < pattern.length() && j < str.length()) {
23 const char p = pattern[i];
24 if (p2w->count(p)) {
25 const auto& w = (*p2w)[p];
26 if (w == str.substr(j, w.length())) { // Match pattern.
27 is_match = match(pattern, str, i + 1, j + w.length(), w2p, p2w);
28 } // Else return false.
29 } else {
30 for (int k = j; k < str.length() && !is_match; ++k) {
31 const string w = str.substr(j, k - j + 1);
32 if (!w2p->count(w)) {
33 // Build mapping. Space: O(n + c)
34 (*w2p)[w] = p, (*p2w)[p] = w;
35 is_match = match(pattern, str, i + 1, k + 1, w2p, p2w);
36 w2p->erase(w), p2w->erase(p);
37 } // Else try longer word.
38 }
39 }
40 }
41 return is_match;
42 }
43 };
***************

58. Word Pattern II(Python)


***************

1 # Time: O(n * C(n - 1, c - 1)), n is length of str, c is unique count of pattern,


2 # there are H(n - c, c - 1) = C(n - 1, c - 1) possible splits of string,
3 # and each one costs O(n) to check if it matches the word pattern.
4 # Space: O(n + c)
5
6 class Solution(object):
7 def wordPatternMatch(self, pattern, str):
8 """
9 :type pattern: str
10 :type str: str
11 :rtype: bool
12 """
13 w2p, p2w = {}, {}
14 return self.match(pattern, str, 0, 0, w2p, p2w)
15
16
17 def match(self, pattern, str, i, j, w2p, p2w):
18 is_match = False
19 if i == len(pattern) and j == len(str):
20 is_match = True
21 elif i < len(pattern) and j < len(str):
22 p = pattern[i]
23 if p in p2w:
24 w = p2w[p]
25 if w == str[j:j+len(w)]: # Match pattern.
26 is_match = self.match(pattern, str, i + 1, j + len(w), w2p, p2w)
27 # Else return false.
28 else:
29 for k in xrange(j, len(str)): # Try any possible word
30 w = str[j:k+1]
31 if w not in w2p:
32 # Build mapping. Space: O(n + c)
33 w2p[w], p2w[p] = p, w
34 is_match = self.match(pattern, str, i + 1, k + 1, w2p, p2w)
35 w2p.pop(w), p2w.pop(p)
36 if is_match:
37 break
38 return is_match
39
40
****************************

59. Find Median from Data Stream


****************************

The median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value and the
median is the mean of the two middle values.

For example, for arr = [2,3,4] , the median is 3.


For example, for arr = [2,3] , the median is (2 + 3) / 2 = 2.5 .

Implement the MedianFinder class:

MedianFinder() initializes the MedianFinder object.


void addNum(int num) adds the integer num from the data stream to the data structure.
double findMedian() returns the median of all elements so far. Answers within10-5 of the actual answer will be accepted.

Example 1:

Input
["MedianFinder", "addNum", "addNum", "findMedian", "addNum", "findMedian"]
[[], [1], [2], [], [3], []]
Output
[null, null, null, 1.5, null, 2.0]

Explanation
MedianFinder medianFinder = new MedianFinder();
medianFinder.addNum(1); // arr = [1]
medianFinder.addNum(2); // arr = [1, 2]
medianFinder.findMedian(); // return 1.5 (i.e., (1 + 2) / 2)
medianFinder.addNum(3); // arr[1, 2, 3]
medianFinder.findMedian(); // return 2.0

Constraints:

-105 <= num <= 10 5


There will be at least one element in the data structure before callingfindMedian .
At most 5 * 104 calls will be made to addNum and findMedian .

Follow up:

If all integer numbers from the stream are in the range[0, 100], how would you optimize your solution?
If 99% of all integer numbers from the stream are in the range[0, 100], how would you optimize your solution?
****************************

59. Find Median from Data Stream(C++)


****************************

1 // Time: O(nlogn) for total n addNums, O(logn) per addNum, O(1) per findMedian.
2 // Space: O(n), total space
3
4 // Heap solution.
5 class MedianFinder {
6 public:
7
8 // Adds a number into the data structure.
9 void addNum(int num) {
10 // Balance smaller half and larger half.
11 if (max_heap_.empty() || num > max_heap_.top()) {
12 min_heap_.emplace(num);
13 if (min_heap_.size() > max_heap_.size() + 1) {
14 max_heap_.emplace(min_heap_.top());
15 min_heap_.pop();
16 }
17 } else {
18 max_heap_.emplace(num);
19 if (max_heap_.size() > min_heap_.size()) {
20 min_heap_.emplace(max_heap_.top());
21 max_heap_.pop();
22 }
23 }
24 }
25
26 // Returns the median of current data stream
27 double findMedian() {
28 return min_heap_.size() == max_heap_.size() ?
29 (max_heap_.top() + min_heap_.top()) / 2.0 :
30 min_heap_.top();
31
32 }
33
34 private:
35 // min_heap_ stores the larger half seen so far.
36 priority_queue, greater> min_heap_;
37 // max_heap_ stores the smaller half seen so far.
38 priority_queue, less> max_heap_;
39 };
40
41 // BST solution.
42 class MedianFinder2 {
43 public:
44
45 // Adds a number into the data structure.
46 void addNum(int num) {
47 // Balance smaller half and larger half.
48 if (max_bst_.empty() || num > *max_bst_.cbegin()) {
49 min_bst_.emplace(num);
50 if (min_bst_.size() > max_bst_.size() + 1) {
51 max_bst_.emplace(*min_bst_.cbegin());
52 min_bst_.erase(min_bst_.cbegin());
53 }
54 } else {
55 max_bst_.emplace(num);
56 if (max_bst_.size() > min_bst_.size()) {
57 min_bst_.emplace(*max_bst_.cbegin());
58 max_bst_.erase(max_bst_.cbegin());
59 }
60 }
61 }
62
63 // Returns the median of current data stream
64 double findMedian() {
65 return min_bst_.size() == max_bst_.size() ?
66 (*max_bst_.cbegin() + *min_bst_.cbegin()) / 2.0 :
67 *min_bst_.cbegin();
68
69 }
70
71 private:
72 // min_bst_ stores the larger half seen so far.
73 multiset> min_bst_;
74 // max_bst_ stores the smaller half seen so far.
75 multiset> max_bst_;
76 };
77
78 // Your MedianFinder object will be instantiated and called as such:
79 // MedianFinder mf;
80 // mf.addNum(1);
81 // mf.findMedian();
****************************

59. Find Median from Data Stream(Python)


****************************

1 # Time: O(nlogn) for total n addNums, O(logn) per addNum, O(1) per findMedian.
2 # Space: O(n), total space
3
4 from heapq import heappush, heappop
5
6 class MedianFinder(object):
7 def __init__(self):
8 """
9 Initialize your data structure here.
10 """
11 self.__max_heap = []
12 self.__min_heap = []
13
14 def addNum(self, num):
15 """
16 Adds a num into the data structure.
17 :type num: int
18 :rtype: void
19 """
20 # Balance smaller half and larger half.
21 if not self.__max_heap or num > -self.__max_heap[0]:
22 heappush(self.__min_heap, num)
23 if len(self.__min_heap) > len(self.__max_heap) + 1:
24 heappush(self.__max_heap, -heappop(self.__min_heap))
25 else:
26 heappush(self.__max_heap, -num)
27 if len(self.__max_heap) > len(self.__min_heap):
28 heappush(self.__min_heap, -heappop(self.__max_heap))
29
30 def findMedian(self):
31 """
32 Returns the median of current data stream
33 :rtype: float
34 """
35 return (-self.__max_heap[0] + self.__min_heap[0]) / 2.0 \
36 if len(self.__min_heap) == len(self.__max_heap) \
37 else self.__min_heap[0]
38
39
******************

60. Best Meeting Point


******************

Given an m x n binary grid grid where each 1 marks the home of one friend, return the minimal total travel distance.

The total travel distance is the sum of the distances between the houses of the friends and the meeting point.

The distance is calculated using Manhattan Distance, where distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y| .

Example 1:

Input: grid = [[1,0,0,0,1],[0,0,0,0,0],[0,0,1,0,0]]


Output: 6
Explanation: Given three friends living at (0,0), (0,4), and (2,2).
The point (0,2) is an ideal meeting point, as the total travel distance of 2 + 2 + 2 = 6 is minimal.
So return 6.

Example 2:

Input: grid = [[1,1]]


Output: 1

Constraints:

m == grid.length
n == grid[i].length
1 <= m, n <= 200
grid[i][j] is either 0
or 1.
There will be at least two friends in the grid.
******************

60. Best Meeting Point(C++)


******************

1 // Time: O(m * n)
2 // Space: O(m + n)
3
4 class Solution {
5 public:
6 int minTotalDistance(vector>& grid) {
7 vector x, y;
8 for (int i = 0; i < grid.size(); ++i) {
9 for (int j = 0; j < grid[0].size(); ++j) {
10 if (grid[i][j]) {
11 x.emplace_back(i);
12 y.emplace_back(j);
13 }
14 }
15 }
16 nth_element(x.begin(), x.begin() + x.size() / 2, x.end());
17 nth_element(y.begin(), y.begin() + y.size() / 2, y.end());
18 const int mid_x = x[x.size() / 2];
19 const int mid_y = y[y.size() / 2];
20 int sum = 0;
21 for (int i = 0; i < grid.size(); ++i) {
22 for (int j = 0; j < grid[0].size(); ++j) {
23 if (grid[i][j]) {
24 sum += abs(mid_x - i) + abs(mid_y - j);
25 }
26 }
27 }
28 return sum;
29 }
30 };
******************

60. Best Meeting Point(Python)


******************

1 # Time: O(m * n)
2 # Space: O(m + n)
3
4 from random import randint
5
6
7 class Solution(object):
8 def minTotalDistance(self, grid):
9 """
10 :type grid: List[List[int]]
11 :rtype: int
12 """
13 x = [i for i, row in enumerate(grid) for v in row if v == 1]
14 y = [j for row in grid for j, v in enumerate(row) if v == 1]
15 mid_x = self.findKthLargest(x, len(x) / 2 + 1)
16 mid_y = self.findKthLargest(y, len(y) / 2 + 1)
17
18 return sum([abs(mid_x-i) + abs(mid_y-j)
19 for i, row in enumerate(grid)
20 for j, v in enumerate(row) if v == 1])
21
22 def findKthLargest(self, nums, k):
23 left, right = 0, len(nums) - 1
24 while left <= right:
25 pivot_idx = randint(left, right)
26 new_pivot_idx = self.PartitionAroundPivot(left, right,
27 pivot_idx, nums)
28 if new_pivot_idx == k - 1:
29 return nums[new_pivot_idx]
30 elif new_pivot_idx > k - 1:
31 right = new_pivot_idx - 1
32 else: # new_pivot_idx < k - 1.
33 left = new_pivot_idx + 1
34
35 def PartitionAroundPivot(self, left, right, pivot_idx, nums):
36 pivot_value = nums[pivot_idx]
37 new_pivot_idx = left
38 nums[pivot_idx], nums[right] = nums[right], nums[pivot_idx]
39 for i in xrange(left, right):
40 if nums[i] > pivot_value:
41 nums[i], nums[new_pivot_idx] = nums[new_pivot_idx], nums[i]
42 new_pivot_idx += 1
43
44 nums[right], nums[new_pivot_idx] = nums[new_pivot_idx], nums[right]
45 return new_pivot_idx
46
*************************************

61. Serialize and Deserialize Binary Tree


*************************************

Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or
memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer
environment.

Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization
algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be
deserialized to the original tree structure.

Clarification: The input/output format is the same as how LeetCode serializes a binary tree. You do not necessarily need to
follow this format, so please be creative and come up with different approaches yourself.

Example 1:

Input: root = [1,2,3,null,null,4,5]


Output: [1,2,3,null,null,4,5]

Example 2:

Input: root = []
Output: []

Example 3:

Input: root = [1]


Output: [1]

Example 4:

Input: root = [1,2]


Output: [1,2]
Constraints:

The number of nodes in the tree is in the range[0, 104].


-1000 <= Node.val <= 1000
*************************************

61. Serialize and Deserialize Binary Tree(C++)


*************************************

1 // Time: O(n)
2 // Space: O(h)
3
4 /**
5 * Definition for a binary tree node.
6 * struct TreeNode {
7 * int val;
8 * TreeNode *left;
9 * TreeNode *right;
10 * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
11 * };
12 */
13 class Codec {
14 public:
15
16 // Encodes a tree to a single string.
17 string serialize(TreeNode* root) {
18 string output;
19 serializeHelper(root, &output);
20 return output;
21 }
22
23 // Decodes your encoded data to tree.
24 TreeNode* deserialize(string data) {
25 TreeNode *root = nullptr;
26 int start = 0;
27 return deserializeHelper(data, &start);
28 }
29
30 private:
31 bool getNumber(const string &data, int *start, int *num) {
32 int sign = 1;
33 if (data[*start] == '#') {
34 *start += 2; // Skip "# ".
35 return false;
36 } else if (data[*start] == '-') {
37 sign = -1;
38 ++(*start);
39 }
40
41 for (*num = 0; isdigit(data[*start]); ++(*start)) {
42 *num = *num * 10 + data[*start] - '0';
43 }
44 *num *= sign;
45 ++(*start); // Skip " ".
46
47 return true;
48 }
49
50 void serializeHelper(const TreeNode *root, string *prev) {
51 if (!root) {
52 prev->append("# ");
53 } else {
54 prev->append(to_string(root->val).append(" "));
55 serializeHelper(root->left, prev);
56 serializeHelper(root->right, prev);
57 }
58 }
59
60 TreeNode *deserializeHelper(const string& data, int *start) {
61 int num;
62 if (!getNumber(data, start, &num)) {
63 return nullptr;
64 } else {
65 TreeNode *root = new TreeNode(num);
66 root->left = deserializeHelper(data, start);
67 root->right = deserializeHelper(data, start);
68 return root;
69 }
70 }
71 };
72
73
74 // Time: O(n)
75 // Space: O(n)
76 class Codec2 {
77 public:
78
79 // Encodes a tree to a single string.
80 string serialize(TreeNode* root) {
81 ostringstream out;
82 serializeHelper(root, out);
83 return out.str();
84 }
85
86 // Decodes your encoded data to tree.
87 TreeNode* deserialize(string data) {
88 istringstream in(data); // Space: O(n)
89 return deserializeHelper(in);
90 }
91
92 private:
93 void serializeHelper(const TreeNode *root, ostringstream& out) {
94 if (!root) {
95 out << "# ";
96 } else {
97 out << root->val << " ";
98 serializeHelper(root->left, out);
99 serializeHelper(root->right, out);
100 }
101 }
102
103 TreeNode *deserializeHelper(istringstream& in) {
104 string val;
105 in >> val;
106 if (val == "#") {
107 return nullptr;
108 } else {
109 TreeNode* root = new TreeNode(stoi(val));
110 root->left = deserializeHelper(in);
111 root->right = deserializeHelper(in);
112 return root;
113 }
114 }
115 };
116
117 // Your Codec object will be instantiated and called as such:
118 // Codec codec;
119 // codec.deserialize(codec.serialize(root));
*************************************

61. Serialize and Deserialize Binary Tree(Python)


*************************************

1 # Time: O(n)
2 # Space: O(h)
3
4 class TreeNode(object):
5 def __init__(self, x):
6 self.val = x
7 self.left = None
8 self.right = None
9
10
11 class Codec(object):
12
13 def serialize(self, root):
14 """Encodes a tree to a single string.
15
16 :type root: TreeNode
17 :rtype: str
18 """
19 def serializeHelper(node):
20 if not node:
21 vals.append('#')
22 return
23 vals.append(str(node.val))
24 serializeHelper(node.left)
25 serializeHelper(node.right)
26 vals = []
27 serializeHelper(root)
28 return ' '.join(vals)
29
30
31 def deserialize(self, data):
32 """Decodes your encoded data to tree.
33
34 :type data: str
35 :rtype: TreeNode
36 """
37 def deserializeHelper():
38 val = next(vals)
39 if val == '#':
40 return None
41 node = TreeNode(int(val))
42 node.left = deserializeHelper()
43 node.right = deserializeHelper()
44 return node
45 def isplit(source, sep):
46 sepsize = len(sep)
47 start = 0
48 while True:
49 idx = source.find(sep, start)
50 if idx == -1:
51 yield source[start:]
52 return
53 yield source[start:idx]
54 start = idx + sepsize
55 vals = iter(isplit(data, ' '))
56 return deserializeHelper()
57
58
59 # time: O(n)
60 # space: O(n)
61
62 class Codec2(object):
63
64 def serialize(self, root):
65 """Encodes a tree to a single string.
66
67 :type root: TreeNode
68 :rtype: str
69 """
70 def gen_preorder(node):
71 if not node:
72 yield '#'
73 else:
74 yield str(node.val)
75 for n in gen_preorder(node.left):
76 yield n
77 for n in gen_preorder(node.right):
78 yield n
79
80 return ' '.join(gen_preorder(root))
81
82 def deserialize(self, data):
83 """Decodes your encoded data to tree.
84
85 :type data: str
86 :rtype: TreeNode
87 """
88 def builder(chunk_iter):
89 val = next(chunk_iter)
90 if val == '#':
91 return None
92 node = TreeNode(int(val))
93 node.left = builder(chunk_iter)
94 node.right = builder(chunk_iter)
95 return node
96
97 # https://stackoverflow.com/a/42373311/568901
98 chunk_iter = iter(data.split())
99 return builder(chunk_iter)
**************************

62. Remove Invalid Parentheses


**************************

Given a string s that contains parentheses and letters, remove the minimum number of invalid parentheses to make the
input string valid.

Return all the possible results. You may return the answer inany order.

Example 1:

Input: s = "()())()"
Output: ["(())()","()()()"]

Example 2:

Input: s = "(a)())()"
Output: ["(a())()","(a)()()"]

Example 3:

Input: s = ")("
Output: [""]

Constraints:

1 <= s.length <= 25


s consists of lowercase English letters and parentheses '(' and ')'.
There will be at most 20 parentheses in s .
**************************

62. Remove Invalid Parentheses(C++)


**************************

1 // Time: O(C(n, c)), try out all possible substrings with the minimum c deletion.
2 // Space: O(c), the depth is at most c, and it costs n at each depth
3
4 // DFS solution with removed array. (4ms)
5 class Solution {
6 public:
7 vector removeInvalidParentheses(string s) {
8 int left_removed = 0, right_removed = 0;
9 findMinRemove(s, &left_removed, &right_removed);
10
11 vector res;
12 vector removed;
13 removeInvalidParenthesesHelper(s, 0, left_removed, right_removed, &removed, &res);
14 return res;
15 }
16
17 private:
18 void findMinRemove(const string& s, int *left_removed, int *right_removed) {
19 // Calculate the minimum left and right parantheses to remove.
20 for (const auto& c : s) {
21 if (c == '(') {
22 ++(*left_removed);
23 } else if (c == ')') {
24 if (!(*left_removed)) {
25 ++(*right_removed);
26 } else {
27 --(*left_removed);
28 }
29 }
30 }
31 }
32
33 void removeInvalidParenthesesHelper(const string& s, int start,
34 int left_removed, int right_removed,
35 vector *removed, vector *res) {
36
37 if (left_removed == 0 && right_removed == 0) {
38 string tmp;
39 for (int i = 0, j = 0; i < s.length(); ++i) {
40 if (j < removed->size() && i == (*removed)[j]) {
41 ++j;
42 } else {
43 tmp.push_back(s[i]);
44 }
45 }
46 if (isValid(tmp)) {
47 res->emplace_back(tmp);
48 }
49 return;
50 }
51
52 for (int i = start; i < s.length(); ++i) {
53 if (right_removed == 0 && left_removed > 0 && s[i] == '(') {
54 if (i == start || s[i] != s[i - 1]) { // Skip duplicated.
55 removed->emplace_back(i);
56 removeInvalidParenthesesHelper(s, i + 1, left_removed - 1, right_removed,
57 removed, res);
58 removed->pop_back();
59 }
60 } else if (right_removed > 0 && s[i] == ')') {
61 if (i == start || s[i] != s[i - 1]) { // Skip duplicated.
62 removed->emplace_back(i);
63 removeInvalidParenthesesHelper(s, i + 1, left_removed, right_removed - 1,
64 removed, res);
65 removed->pop_back();
66 }
67 }
68
69 }
70 }
71
72 // Check whether s is valid or not.
73 bool isValid(string s) {
74 int sum = 0;
75 for (const auto &c : s) {
76 if (c == '(') {
77 ++sum;
78 } else if (c == ')') {
79 --sum;
80 }
81 if (sum < 0) {
82 return false;
83 }
84 }
85 return sum == 0;
86 }
87 };
88
89 // Time: O(C(n, c)), try out all possible substrings with the minimum c deletion.
90 // Space: O(c), the depth is at most c, and it costs n at each depth
91 // DFS solution with removed hash. (8ms)
92 class Solution2 {
93 public:
94 vector removeInvalidParentheses(string s) {
95 int left_removed = 0, right_removed = 0;
96 findMinRemove(s, &left_removed, &right_removed);
97
98 vector res;
99 unordered_set removed;
100 removeInvalidParenthesesHelper(s, 0, left_removed, right_removed, &removed, &res);
101 return res;
102 }
103
104 private:
105 void findMinRemove(const string& s, int *left_removed, int *right_removed) {
106 // Calculate the minimum left and right parantheses to remove.
107 for (const auto& c : s) {
108 if (c == '(') {
109 ++(*left_removed);
110 } else if (c == ')') {
111 if (!(*left_removed)) {
112 ++(*right_removed);
113 } else {
114 --(*left_removed);
115 }
116 }
117 }
118 }
119
120 void removeInvalidParenthesesHelper(const string& s, int start,
121 int left_removed, int right_removed,
122 unordered_set *removed, vector *res) {
123
124 if (left_removed == 0 && right_removed == 0) {
125 string tmp;
126 for (int i = 0; i < s.length(); ++i) {
127 if (!removed->count(i)) {
128 tmp.push_back(s[i]);
129 }
130 }
131 if (isValid(tmp)) {
132 res->emplace_back(tmp);
133 }
134 return;
135 }
135 }
136
137 for (int i = start; i < s.length(); ++i) {
138 if (right_removed == 0 && left_removed > 0 && s[i] == '(') {
139 if (i == start || s[i] != s[i - 1]) { // Skip duplicated.
140 removed->emplace(i);
141 removeInvalidParenthesesHelper(s, i + 1, left_removed - 1, right_removed,
142 removed, res);
143 removed->erase(i);
144 }
145 } else if (right_removed > 0 && s[i] == ')') {
146 if (i == start || s[i] != s[i - 1]) { // Skip duplicated.
147 removed->emplace(i);
148 removeInvalidParenthesesHelper(s, i + 1, left_removed, right_removed - 1,
149 removed, res);
150 removed->erase(i);
151 }
152 }
153
154 }
155 }
156
157 // Check whether s is valid or not.
158 bool isValid(string s) {
159 int sum = 0;
160 for (const auto &c : s) {
161 if (c == '(') {
162 ++sum;
163 } else if (c == ')') {
164 --sum;
165 }
166 if (sum < 0) {
167 return false;
168 }
169 }
170 return sum == 0;
171 }
172 };
173
174
175 // Time: O(n * C(n, c)), try out all possible substrings with the minimum c deletion.
176 // Space: O(n * c), the depth is at most c, and it costs n at each depth
177 // DFS solution. (4ms)
178 class Solution3 {
179 public:
180 vector removeInvalidParentheses(string s) {
181 int left_removed = 0, right_removed = 0;
182 findMinRemove(s, &left_removed, &right_removed);
183
184 vector res;
185 removeInvalidParenthesesHelper(s, 0, left_removed, right_removed, &res);
186 return res;
187 }
188
189 void findMinRemove(const string& s, int *left_removed, int *right_removed) {
190 // Calculate the minimum left and right parantheses to remove.
191 for (const auto& c : s) {
192 if (c == '(') {
193 ++(*left_removed);
194 } else if (c == ')') {
195 if (!(*left_removed)) {
196 ++(*right_removed);
197 } else {
198 --(*left_removed);
199 }
200 }
201 }
202 }
203
204 private:
205 void removeInvalidParenthesesHelper(const string& s, int start,
206 int left_removed, int right_removed, vector *res) {
207
208 if (left_removed == 0 && right_removed == 0) {
208 if (left_removed == 0 && right_removed == 0) {
209 if (isValid(s)) {
210 res->emplace_back(s);
211 }
212 return;
213 }
214
215 for (int i = start; i < s.length(); ++i) {
216 if (right_removed == 0 && left_removed > 0 && s[i] == '(') {
217 if (i == start || s[i] != s[i - 1]) { // Skip duplicated.
218 string tmp = s;
219 tmp.erase(i, 1);
220 removeInvalidParenthesesHelper(tmp, i, left_removed - 1, right_removed, res);
221 }
222 } else if (right_removed > 0 && s[i] == ')') {
223 if (i == start || s[i] != s[i - 1]) { // Skip duplicated.
224 string tmp = s;
225 tmp.erase(i, 1);
226 removeInvalidParenthesesHelper(tmp, i, left_removed, right_removed - 1, res);
227 }
228 }
229
230 }
231 }
232
233 // Check whether s is valid or not.
234 bool isValid(string s) {
235 int sum = 0;
236 for (const auto &c : s) {
237 if (c == '(') {
238 ++sum;
239 } else if (c == ')') {
240 --sum;
241 }
242 if (sum < 0) {
243 return false;
244 }
245 }
246 return sum == 0;
247 }
248 };
**************************

62. Remove Invalid Parentheses(Python)


**************************

1 # Time: O(C(n, c)), try out all possible substrings with the minimum c deletion.
2 # Space: O(c), the depth is at most c, and it costs n at each depth
3
4 class Solution(object):
5 def removeInvalidParentheses(self, s):
6 """
7 :type s: str
8 :rtype: List[str]
9 """
10 # Calculate the minimum left and right parantheses to remove
11 def findMinRemove(s):
12 left_removed, right_removed = 0, 0
13 for c in s:
14 if c == '(':
15 left_removed += 1
16 elif c == ')':
17 if not left_removed:
18 right_removed += 1
19 else:
20 left_removed -= 1
21 return (left_removed, right_removed)
22
23 # Check whether s is valid or not.
24 def isValid(s):
25 sum = 0
26 for c in s:
27 if c == '(':
28 sum += 1
29 elif c == ')':
30 sum -= 1
31 if sum < 0:
32 return False
33 return sum == 0
34
35 def removeInvalidParenthesesHelper(start, left_removed, right_removed):
36 if left_removed == 0 and right_removed == 0:
37 tmp = ""
38 for i, c in enumerate(s):
39 if i not in removed:
40 tmp += c
41 if isValid(tmp):
42 res.append(tmp)
43 return
44
45 for i in xrange(start, len(s)):
46 if right_removed == 0 and left_removed > 0 and s[i] == '(':
47 if i == start or s[i] != s[i - 1]: # Skip duplicated.
48 removed[i] = True
49 removeInvalidParenthesesHelper(i + 1, left_removed - 1, right_removed)
50 del removed[i]
51 elif right_removed > 0 and s[i] == ')':
52 if i == start or s[i] != s[i - 1]: # Skip duplicated.
53 removed[i] = True
54 removeInvalidParenthesesHelper(i + 1, left_removed, right_removed - 1)
55 del removed[i]
56
57 res, removed = [], {}
58 (left_removed, right_removed) = findMinRemove(s)
59 removeInvalidParenthesesHelper(0, left_removed, right_removed)
60 return res
61
*****************************************

63. Smallest Rectangle Enclosing Black Pixels


*****************************************

You are given an image that is represented by a binary matrix with 0 as a white pixel and 1 as a black pixel.

The black pixels are connected (i.e., there is only one black region). Pixels are connected horizontally and vertically.

Given two integers x and y that represent the location of one of the black pixels, returnthe area of the smallest (axis-aligned)
rectangle that encloses all black pixels.

Example 1:

Input: image = [["0","0","1","0"],["0","1","1","0"],["0","1","0","0"]], x = 0, y = 2


Output: 6

Example 2:

Input: image = [["1"]], x = 0, y = 0


Output: 1

Constraints:

m == image.length
n == image[i].length
1 <= m, n <= 100
image[i][j] is either '0' or '1'.
1 <= x < m
1 <= y < n
image[x][y] == '1'.
The black pixels in the image only form one component.
*****************************************

63. Smallest Rectangle Enclosing Black Pixels(C++)


*****************************************

1 // Time: O(nlogn)
2 // Space: O(1)
3
4 // Using template.
5 class Solution {
6 public:
7 int minArea(vector>& image, int x, int y) {
8 using namespace std::placeholders; // for _1, _2, _3...
9
10 const auto searchColumns =
11 [](const vector>& image, bool has_one, const int mid) {
12 return has_one == any_of(image.cbegin(), image.cend(),
13 [=](const vector& row) { return row[mid] == '1'; });
14 };
15 const auto searchRows =
16 [](const vector>& image, bool has_one, const int mid) {
17 return has_one == any_of(image[mid].cbegin(), image[mid].cend(),
18 [](const char& col) { return col == '1'; });
19 };
20
21 const int left = binarySearch(0, y - 1, bind(searchColumns, image, true, _1));
22 const int right = binarySearch(y + 1, image[0].size() - 1, bind(searchColumns, image, false, _1));
23 const int top = binarySearch(0, x - 1, bind(searchRows, image, true, _1));
24 const int bottom = binarySearch(x + 1, image.size() - 1, bind(searchRows, image, false, _1));
25
26 return (right - left) * (bottom - top);
27 }
28
29 private:
30 template
31 int binarySearch(int left, int right, const T& find) {
32 while (left <= right) {
33 const int mid = left + (right - left) / 2;
34 if (find(mid)) {
35 right = mid - 1;
36 } else {
37 left = mid + 1;
38 }
39 }
40 return left;
41 }
42 };
43
44 // Using std::bind().
45 class Solution2 {
46 public:
47 int minArea(vector>& image, int x, int y) {
48 using namespace std::placeholders; // for _1, _2, _3...
49
50 const auto searchColumns =
51 [](const vector>& image, bool has_one, const int mid) {
52 return has_one == any_of(image.cbegin(), image.cend(),
53 [=](const vector& row) { return row[mid] == '1'; });
54 };
55 const auto searchRows =
56 [](const vector>& image, bool has_one, const int mid) {
57 return has_one == any_of(image[mid].cbegin(), image[mid].cend(),
58 [](const char& col) { return col == '1'; });
59 };
60
61 function findLeft = bind(searchColumns, image, true, _1);
62 const int left = binarySearch(0, y - 1, findLeft);
63
64 function findRight = bind(searchColumns, image, false, _1);
65 const int right = binarySearch(y + 1, image[0].size() - 1, findRight);
66
67 function findTop = bind(searchRows, image, true, _1);
68 const int top = binarySearch(0, x - 1, findTop);
69
70 function findBottom = bind(searchRows, image, false, _1);
71 const int bottom = binarySearch(x + 1, image.size() - 1, findBottom);
72
73 return (right - left) * (bottom - top);
74 }
75
76 private:
77 int binarySearch(int left, int right, function& find) {
78 while (left <= right) {
79 const int mid = left + (right - left) / 2;
80 if (find(mid)) {
81 right = mid - 1;
82 } else {
83 left = mid + 1;
84 }
85 }
86 return left;
87 }
88 };
89
90 // Using lambda.
91 class Solution3 {
92 public:
93 int minArea(vector>& image, int x, int y) {
94 const auto searchColumns =
95 [](const vector>& image, bool has_one, const int mid) {
96 return has_one == any_of(image.cbegin(), image.cend(),
97 [=](const vector& row) { return row[mid] == '1'; });
98 };
99 const auto searchRows =
100 [](const vector>& image, bool has_one, const int mid) {
101 return has_one == any_of(image[mid].cbegin(), image[mid].cend(),
102 [](const char& col) { return col == '1'; });
103 };
104
105 const int left = binarySearch(0, y - 1, searchColumns, image, true);
106 const int right = binarySearch(y + 1, image[0].size() - 1, searchColumns, image, false);
107 const int top = binarySearch(0, x - 1, searchRows, image, true);
108 const int bottom = binarySearch(x + 1, image.size() - 1, searchRows, image, false);
109
110 return (right - left) * (bottom - top);
111 }
112
113 private:
114 int binarySearch(int left, int right,
115 const function>&, bool, const int)>& find,
116 const vector>& image,
117 bool has_one) {
118 while (left <= right) {
119 const int mid = left + (right - left) / 2;
120 if (find(image, has_one, mid)) {
121 right = mid - 1;
122 } else {
123 left = mid + 1;
124 }
125 }
126 return left;
127 }
128 };
*****************************************

63. Smallest Rectangle Enclosing Black Pixels(Python)


*****************************************

1 # Time: O(nlogn)
2 # Space: O(1)
3
4 import bisect
5 import itertools
6
7
8 class Solution(object):
9 def minArea(self, image, x, y):
10 """
11 :type image: List[List[str]]
12 :type x: int
13 :type y: int
14 :rtype: int
15 """
16 def binarySearch(left, right, find, image, has_one):
17 while left <= right: # O(logn) times
18 mid = left + (right - left) / 2
19 if find(image, has_one, mid): # Time: O(n)
20 right = mid - 1
21 else:
22 left = mid + 1
23 return left
24
25
26 searchColumns = lambda image, has_one, mid: any([int(row[mid]) for row in image]) == has_one
27 left = binarySearch(0, y - 1, searchColumns, image, True)
28 right = binarySearch(y + 1, len(image[0]) - 1, searchColumns, image, False)
29
30 searchRows = lambda image, has_one, mid: any(itertools.imap(int, image[mid])) == has_one
31 top = binarySearch(0, x - 1, searchRows, image, True)
32 bottom = binarySearch(x + 1, len(image) - 1, searchRows, image, False)
33
34 return (right - left) * (bottom - top)
35
********************

64. Number of Islands II


********************

You are given an empty 2D binary grid grid of size m x n . The grid represents a map where 0's represent water and 1's
represent land. Initially, all the cells of grid are water cells (i.e., all the cells are0's).

We may perform an add land operation which turns the water at position into a land. You are given an arraypositions where
positions[i] = [r i, c i] is the position (ri, c i) at which we should operate theith operation.

Return an array of integers answer where answer[i] is the number of islands after turning the cell(ri, c i) into a land.

An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all
four edges of the grid are all surrounded by water.

Example 1:

Input: m = 3, n = 3, positions = [[0,0],[0,1],[1,2],[2,1]]


Output: [1,1,2,3]
Explanation:
Initially, the 2d grid is filled with water.
- Operation #1: addLand(0, 0) turns the water at grid[0][0] into a land. We have 1 island.
- Operation #2: addLand(0, 1) turns the water at grid[0][1] into a land. We still have 1 island.
- Operation #3: addLand(1, 2) turns the water at grid[1][2] into a land. We have 2 islands.
- Operation #4: addLand(2, 1) turns the water at grid[2][1] into a land. We have 3 islands.

Example 2:

Input: m = 1, n = 1, positions = [[0,0]]


Output: [1]

Constraints:

1 <= m, n, positions.length <= 10 4


1 <= m * n <= 10 4
positions[i].length == 2
0 <= ri < m
0 <= c i < n
Follow up: Could you solve it in time complexity O(k log(mn)), where k == positions.length ?
********************

64. Number of Islands II(C++)


********************

1 // Time: O(klog*k) ~= O(k), k is the length of the positions


2 // Space: O(k)
3
4 // Using unordered_map.
5 class Solution {
6 public:
7 vector numIslands2(int m, int n, vector>& positions) {
8 vector numbers;
9 int number = 0;
10 const vector> directions{{0, -1}, {0, 1},
11 {-1, 0}, {1, 0}};
12 unordered_map set;
13 for (const auto& position : positions) {
14 const auto& node = make_pair(position.first, position.second);
15 set[node_id(node, n)] = node_id(node, n);
16 ++number;
17
18 for (const auto& d : directions) {
19 const auto& neighbor = make_pair(position.first + d.first,
20 position.second + d.second);
21 if (neighbor.first >= 0 && neighbor.first < m &&
22 neighbor.second >= 0 && neighbor.second < n &&
23 set.find(node_id(neighbor, n)) != set.end()) {
24 if (find_set(node_id(node, n), &set) !=
25 find_set(node_id(neighbor, n), &set)) {
26 // Merge different islands, amortised time: O(log*k) ~= O(1)
27 union_set(&set, node_id(node, n), node_id(neighbor, n));
28 --number;
29 }
30 }
31 }
32 numbers.emplace_back(number);
33 }
34
35 return numbers;
36 }
37
38 int node_id(const pair& node, const int n) {
39 return node.first * n + node.second;
40 }
41
42 int find_set(int x, unordered_map *set) {
43 if ((*set)[x] != x) {
44 (*set)[x] = find_set((*set)[x], set); // path compression.
45 }
46 return (*set)[x];
47 }
48
49 void union_set(unordered_map *set, const int x, const int y) {
50 int x_root = find_set(x, set), y_root = find_set(y, set);
51 (*set)[min(x_root, y_root)] = max(x_root, y_root);
52 }
53 };
54
55
56 // Time: O(klog*k) ~= O(k), k is the length of the positions
57 // Space: O(m * n)
58 // Using vector.
59 class Solution2 {
60 public:
61 /**
62 * @param n an integer
63 * @param m an integer
64 * @param operators an array of point
65 * @return an integer array
66 */
67 vector numIslands2(int m, int n, vector>& positions) {
68 vector numbers;
69 int number = 0;
70 const vector> directions{{0, -1}, {0, 1},
71 {-1, 0}, {1, 0}};
72 vector set(m * n, -1);
73 for (const auto& position : positions) {
74 const auto& node = make_pair(position.first, position.second);
75 set[node_id(node, n)] = node_id(node, n);
76 ++number;
77
78 for (const auto& d : directions) {
79 const auto& neighbor = make_pair(position.first + d.first,
80 position.second + d.second);
81 if (neighbor.first >= 0 && neighbor.first < m &&
82 neighbor.second >= 0 && neighbor.second < n &&
83 set[node_id(neighbor, n)] != -1) {
84 if (find_set(node_id(node, n), &set) !=
85 find_set(node_id(neighbor, n), &set)) {
86 // Merge different islands, amortised time: O(log*k) ~= O(1)
87 union_set(&set, node_id(node, n), node_id(neighbor, n));
88 --number;
89 }
90 }
91 }
92 numbers.emplace_back(number);
93 }
94
95 return numbers;
96 }
97
98 int node_id(const pair& node, const int m) {
99 return node.first * m + node.second;
100 }
101
102 int find_set(int x, vector *set) {
103 int parent = x;
104 while ((*set)[parent] != parent) {
105 parent = (*set)[parent];
106 }
107 while ((*set)[x] != x) {
108 int tmp = (*set)[x];
109 (*set)[x] = parent;
110 x = tmp;
111 }
112 return parent;
113 }
114
115 void union_set(vector *set, const int x, const int y) {
116 int x_root = find_set(x, set), y_root = find_set(y, set);
117 (*set)[min(x_root, y_root)] = max(x_root, y_root);
118 }
119 };
********************

64. Number of Islands II(Python)


********************

1 # Time: O(klog*k) ~= O(k), k is the length of the positions


2 # Space: O(k)
3
4 class Solution(object):
5 def numIslands2(self, m, n, positions):
6 """
7 :type m: int
8 :type n: int
9 :type positions: List[List[int]]
10 :rtype: List[int]
11 """
12 def node_id(node, n):
13 return node[0] * n + node[1]
14
15 def find_set(x):
16 if set[x] != x:
17 set[x] = find_set(set[x]) # path compression.
18 return set[x]
19
20 def union_set(x, y):
21 x_root, y_root = find_set(x), find_set(y)
22 set[min(x_root, y_root)] = max(x_root, y_root)
23
24 numbers = []
25 number = 0
26 directions = [(0, -1), (0, 1), (-1, 0), (1, 0)]
27 set = {}
28 for position in positions:
29 node = (position[0], position[1])
30 set[node_id(node, n)] = node_id(node, n)
31 number += 1
32
33 for d in directions:
34 neighbor = (position[0] + d[0], position[1] + d[1])
35 if 0 <= neighbor[0] < m and 0 <= neighbor[1] < n and \
36 node_id(neighbor, n) in set:
37 if find_set(node_id(node, n)) != find_set(node_id(neighbor, n)):
38 # Merge different islands, amortised time: O(log*k) ~= O(1)
39 union_set(node_id(node, n), node_id(neighbor, n))
40 number -= 1
41 numbers.append(number)
42
43 return numbers
44
****************************

65. Range Sum Query 2D - Mutable


****************************

Given a 2D matrix matrix, handle multiple queries of the following types:

1. Update the value of a cell inmatrix.


2. Calculate the sum of the elements of matrix inside the rectangle defined by its upper left corner (row1, col1) and lower
right corner (row2, col2).

Implement the NumMatrix class:

NumMatrix(int[][] matrix) Initializes the object with the integer matrix matrix.
void update(int row, int col, int val) Updates the value of matrix[row][col] to be val .
int sumRegion(int row1, int col1, int row2, int col2) Returns the sum of the elements of matrix inside the rectangle defined by its
upper left corner (row1, col1) and lower right corner (row2, col2).

Example 1:

Input
["NumMatrix", "sumRegion", "update", "sumRegion"]
[[[[3, 0, 1, 4, 2], [5, 6, 3, 2, 1], [1, 2, 0, 1, 5], [4, 1, 0, 1, 7], [1, 0, 3, 0, 5]]], [2, 1, 4, 3], [3, 2, 2], [2, 1, 4, 3]]
Output
[null, 8, null, 10]

Explanation
NumMatrix numMatrix = new NumMatrix([[3, 0, 1, 4, 2], [5, 6, 3, 2, 1], [1, 2, 0, 1, 5], [4, 1, 0, 1, 7], [1, 0, 3, 0, 5]]);
numMatrix.sumRegion(2, 1, 4, 3); // return 8 (i.e. sum of the left red rectangle)
numMatrix.update(3, 2, 2); // matrix changes from left image to right image
numMatrix.sumRegion(2, 1, 4, 3); // return 10 (i.e. sum of the right red rectangle)

Constraints:

m == matrix.length
n == matrix[i].length
1 <= m, n <= 200
-105 <= matrix[i][j] <= 105
0 <= row < m
0 <= col < n
-105 <= val <= 10 5
0 <= row1 <= row2 < m
0 <= col1 <= col2 < n
At most 104 calls will be made to sumRegion and update.
****************************

65. Range Sum Query 2D - Mutable(C++)


****************************

1 // Time: ctor: O(m * n)


2 // update: O(logm * logn)
3 // query: O(logm * logn)
4 // Space: O(m * n)
5
6 // 2d - Binary Indexed Tree (BIT) solution.
7 class NumMatrix {
8 public:
9 NumMatrix(vector> &matrix) : matrix_(matrix) {
10 if (matrix_.empty()) {
11 return;
12 }
13 bit_ = vector>(matrix_.size() + 1,
14 vector(matrix_[0].size() + 1));
15 for (int i = 1; i < bit_.size(); ++i) {
16 for (int j = 1; j < bit_[0].size(); ++j) {
17 bit_[i][j] = matrix[i - 1][j - 1] + bit_[i - 1][j] +
18 bit_[i][j - 1] - bit_[i - 1][j - 1];
19 }
20 }
21 for (int i = bit_.size() - 1; i >= 1; --i) {
22 for (int j = bit_[0].size() - 1; j >= 1; --j) {
23 int last_i = i - lower_bit(i), last_j = j - lower_bit(j);
24 bit_[i][j] = bit_[i][j] - bit_[i][last_j] -
25 bit_[last_i][j] + bit_[last_i][last_j];
26 }
27 }
28 }
29
30 void update(int row, int col, int val) {
31 if (val - matrix_[row][col]) {
32 add(row, col, val - matrix_[row][col]);
33 matrix_[row][col] = val;
34 }
35 }
36
37 int sumRegion(int row1, int col1, int row2, int col2) {
38 return sum(row2, col2) - sum(row2, col1 - 1) -
39 sum(row1 - 1, col2) + sum(row1 - 1, col1 - 1);
40 }
41
42 private:
43 vector> &matrix_;
44 vector> bit_;
45
46 int sum(int row, int col) {
47 ++row, ++col;
48 int sum = 0;
49 for (int i = row; i > 0; i -= lower_bit(i)) {
50 for (int j = col; j > 0; j -= lower_bit(j)) {
51 sum += bit_[i][j];
52 }
53 }
54 return sum;
55 }
56
57 void add(int row, int col, int val) {
58 ++row, ++col;
59 for (int i = row; i <= matrix_.size(); i += lower_bit(i)) {
60 for (int j = col; j <= matrix_[0].size(); j += lower_bit(j)) {
61 bit_[i][j] += val;
62 }
63 }
64 }
65
66 inline int lower_bit(int i) {
67 return i & -i;
68 }
69 };
70
71 // Time: ctor: O(m * n),
72 // update: O(max(m, n)),
73 // query: O(max(m, n))
74 // Space: O(m * n)
75 // Quad Tree solution.
76 // see complexity analysis of quad tree: https://apps.topcoder.com/forums/?module=Thread&threadID=633075
77 class NumMatrix2 {
78 public:
79 NumMatrix2(vector> &matrix) : matrix_(matrix) {
80 if (!matrix.empty() && !matrix[0].empty()) {
81 const int m = matrix.size();
82 const int n = matrix[0].size();
83 root_ = buildHelper(matrix,
84 make_pair(0, 0),
85 make_pair(m - 1, n - 1));
86 }
87 }
88
89 void update(int row, int col, int val) {
90 if (matrix_[row][col] != val) {
91 matrix_[row][col] = val;
92 updateHelper(root_, make_pair(row, col), val);
93 }
94 }
95
96 int sumRegion(int row1, int col1, int row2, int col2) {
97 return sumRangeHelper(root_, make_pair(row1, col1), make_pair(row2, col2));
98 }
99
100 private:
101 vector>& matrix_;
102
103 class SegmentTreeNode {
104 public:
105 pair start, end;
106 int sum;
107 vector neighbor;
108 SegmentTreeNode(const pair& i, const pair& j, int s) :
109 start(i), end(j), sum(s) {
110 }
111 };
112
113 SegmentTreeNode *root_;
114
115 // Build segment tree.
116 SegmentTreeNode *buildHelper(const vector>& matrix,
117 const pair& start,
118 const pair& end) {
119 if (start.first > end.first || start.second > end.second) {
120 return nullptr;
121 }
122
123 // The root's start and end is given by build method.
124 SegmentTreeNode *root = new SegmentTreeNode(start, end, 0);
125
126 // If start equals to end, there will be no children for this node.
127 if (start == end) {
128 root->sum = matrix[start.first][start.second];
129 return root;
130 }
131
132 int mid_x = (start.first + end.first) / 2;
133 int mid_y = (start.second + end.second) / 2;
134 root->neighbor.emplace_back(buildHelper(matrix, start, make_pair(mid_x, mid_y)));
135 root->neighbor.emplace_back(buildHelper(matrix, make_pair(start.first, mid_y + 1), make_pair(mid_x, end.second)));
135 root->neighbor.emplace_back(buildHelper(matrix, make_pair(start.first, mid_y + 1), make_pair(mid_x, end.second)));
136 root->neighbor.emplace_back(buildHelper(matrix, make_pair(mid_x + 1, start.second), make_pair(end.first, mid_y)));
137 root->neighbor.emplace_back(buildHelper(matrix, make_pair(mid_x + 1, mid_y + 1), end));
138 for (auto& node : root->neighbor) {
139 if (node) {
140 root->sum += node->sum;
141 }
142 }
143 return root;
144 }
145
146 void updateHelper(SegmentTreeNode *root, const pair& i, int val) {
147 // Out of range.
148 if (root == nullptr ||
149 (root->start.first > i.first || root->start.second > i.second) ||
150 (root->end.first < i.first || root->end.second < i.second)) {
151 return;
152 }
153
154 // Change the node's value with [i] to the new given value.
155 if ((root->start.first == i.first && root->start.second == i.second) &&
156 (root->end.first == i.first && root->end.second == i.second)) {
157 root->sum = val;
158 return;
159 }
160 for (auto& node : root->neighbor) {
161 updateHelper(node, i, val);
162 }
163
164 root->sum = 0;
165 for (auto& node : root->neighbor) {
166 if (node) {
167 root->sum += node->sum;
168 }
169 }
170 }
171
172 int sumRangeHelper(SegmentTreeNode *root, const pair& start, const pair& end) {
173 // Out of range.
174 if (root == nullptr ||
175 (root->start.first > end.first || root->start.second > end.second) ||
176 (root->end.first < start.first || root->end.second < start.second)) {
177 return 0;
178 }
179
180 // Current segment is totally within range [start, end]
181 if ((root->start.first >= start.first && root->start.second >= start.second) &&
182 (root->end.first <= end.first && root->end.second <= end.second)) {
183 return root->sum;
184 }
185 int sum = 0;
186 for (auto& node : root->neighbor) {
187 if (node) {
188 sum += sumRangeHelper(node, start, end);
189 }
190 }
191 return sum;
192 }
193 };
194
195 // Your NumMatrix object will be instantiated and called as such:
196 // NumMatrix numMatrix(matrix);
197 // numMatrix.sumRegion(0, 1, 2, 3);
198 // numMatrix.update(1, 1, 10);
199 // numMatrix.sumRegion(1, 2, 3, 4);
****************************

65. Range Sum Query 2D - Mutable(Python)


****************************

1 # Time: ctor: O(m * n)


2 # update: O(logm * logn)
3 # query: O(logm * logn)
4 # Space: O(m * n)
5
6 class NumMatrix(object):
7 def __init__(self, matrix):
8 """
9 initialize your data structure here.
10 :type matrix: List[List[int]]
11 """
12 if not matrix:
13 return
14 self.__matrix = matrix
15 self.__bit = [[0] * (len(self.__matrix[0]) + 1) \
16 for _ in xrange(len(self.__matrix) + 1)]
17 for i in xrange(1, len(self.__bit)):
18 for j in xrange(1, len(self.__bit[0])):
19 self.__bit[i][j] = matrix[i-1][j-1] + self.__bit[i-1][j] + \
20 self.__bit[i][j-1] - self.__bit[i-1][j-1]
21 for i in reversed(xrange(1, len(self.__bit))):
22 for j in reversed(xrange(1, len(self.__bit[0]))):
23 last_i, last_j = i - (i & -i), j - (j & -j)
24 self.__bit[i][j] = self.__bit[i][j] - self.__bit[i][last_j] - \
25 self.__bit[last_i][j] + self.__bit[last_i][last_j]
26
27 def update(self, row, col, val):
28 """
29 update the element at matrix[row,col] to val.
30 :type row: int
31 :type col: int
32 :type val: int
33 :rtype: void
34 """
35 if val - self.__matrix[row][col]:
36 self.__add(row, col, val - self.__matrix[row][col])
37 self.__matrix[row][col] = val
38
39 def sumRegion(self, row1, col1, row2, col2):
40 """
41 sum of elements matrix[(row1,col1)..(row2,col2)], inclusive.
42 :type row1: int
43 :type col1: int
44 :type row2: int
45 :type col2: int
46 :rtype: int
47 """
48 return self.__sum(row2, col2) - self.__sum(row2, col1 - 1) - \
49 self.__sum(row1 - 1, col2) + self.__sum(row1 - 1, col1 - 1)
50
51 def __sum(self, row, col):
52 row += 1
53 col += 1
54 ret = 0
55 i = row
56 while i > 0:
57 j = col
58 while j > 0:
59 ret += self.__bit[i][j]
60 j -= (j & -j)
61 i -= (i & -i)
62 return ret
63
64 def __add(self, row, col, val):
65 row += 1
66 col += 1
67 i = row
68 while i <= len(self.__matrix):
69 j = col
70 while j <= len(self.__matrix[0]):
71 self.__bit[i][j] += val
72 j += (j & -j)
73 i += (i & -i)
74
75
76
**************

66. Burst Balloons


**************

You are given n balloons, indexed from 0 to n - 1. Each balloon is painted with a number on it represented by an arraynums.
You are asked to burst all the balloons.

If you burst the ith balloon, you will get nums[i - 1] * nums[i] * nums[i + 1] coins. If i - 1 or i + 1 goes out of bounds of the array, then
treat it as if there is a balloon with a 1 painted on it.

Return the maximum coins you can collect by bursting the balloons wisely.

Example 1:

Input: nums = [3,1,5,8]


Output: 167
Explanation:
nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> []
coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167

Example 2:

Input: nums = [1,5]


Output: 10

Constraints:

n == nums.length
1 <= n <= 500
0 <= nums[i] <= 100
**************

66. Burst Balloons(C++)


**************

1 // Time: O(n^3)
2 // Space: O(n^2)
3
4 class Solution {
5 public:
6 int maxCoins(vector& nums) {
7 vector coins;
8 coins.emplace_back(1);
9 for (const auto& n : nums) {
10 if (n > 0) {
11 coins.emplace_back(n);
12 }
13 }
14 coins.emplace_back(1);
15
16 vector> max_coins(coins.size(), vector(coins.size()));
17 for (int k = 2; k < coins.size(); ++k) {
18 for (int left = 0; left < coins.size() - k; ++left) {
19 for (int i = left + 1, right = left + k; i < right; ++i) {
20 max_coins[left][right] = max(max_coins[left][right],
21 coins[left] * coins[i] * coins[right] +
22 max_coins[left][i] + max_coins[i][right]);
23 }
24 }
25 }
26
27 return max_coins[0][coins.size() - 1];
28 }
29 };
**************

66. Burst Balloons(Python)


**************

1 # Time: O(n^3)
2 # Space: O(n^2)
3
4
5 class Solution(object):
6 def maxCoins(self, nums):
7 """
8 :type nums: List[int]
9 :rtype: int
10 """
11 coins = [1] + [i for i in nums if i > 0] + [1]
12 n = len(coins)
13 max_coins = [[0 for _ in xrange(n)] for _ in xrange(n)]
14
15 for k in xrange(2, n):
16 for left in xrange(n - k):
17 right = left + k
18 for i in xrange(left + 1, right):
19 max_coins[left][right] = \
20 max(max_coins[left][right],
21 coins[left] * coins[i] * coins[right] +
22 max_coins[left][i] +
23 max_coins[i][right])
24
25 return max_coins[0][-1]
26
***********************************

67. Count of Smaller Numbers After Self


***********************************

You are given an integer array nums and you have to return a new counts array. The counts array has the property where
counts[i] is the number of smaller elements to the right ofnums[i].

Example 1:

Input: nums = [5,2,6,1]


Output: [2,1,1,0]
Explanation:
To the right of 5 there are 2 smaller elements (2 and 1).
To the right of 2 there is only 1 smaller element (1).
To the right of 6 there is 1 smaller element (1).
To the right of 1 there is 0 smaller element.

Example 2:

Input: nums = [-1]


Output: [0]

Example 3:

Input: nums = [-1,-1]


Output: [0,0]

Constraints:

1 <= nums.length <= 10 5


-104 <= nums[i] <= 10 4
***********************************

67. Count of Smaller Numbers After Self(C++)


***********************************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 // BIT solution. (24ms)
5 class Solution {
6 public:
7 vector countSmaller(vector& nums) {
8 // Get the place (position in the ascending order) of each number.
9 vector idx(size(nums));
10 iota(begin(idx), end(idx), 0);
11 vector lookup(size(nums));
12 sort(begin(idx), end(idx),
13 [&nums](const auto& a, const auto& b) {
14 return nums[a] == nums[b] ? a < b : nums[a] < nums[b];
15 });
16 for (int i = 0; i < size(idx); ++i) {
17 lookup[idx[i]] = i;
18 }
19 // Count the smaller elements after the number.
20 BIT bit(size(nums));
21 vector result(size(nums));
22 for (int i = size(nums) - 1; i >= 0; --i) {
23 result[i] = bit.query(lookup[i] - 1);
24 bit.add(lookup[i], 1);
25 }
26 return result;
27 }
28
29 private:
30 class BIT {
31 public:
32 BIT(int n) : bit_(n + 1) { // 0-indexed
33 }
34
35 void add(int i, int val) {
36 ++i;
37 for (; i < size(bit_); i += lower_bit(i)) {
38 bit_[i] += val;
39 }
40 }
41
42 int query(int i) const {
43 ++i;
44 int total = 0;
45 for (; i > 0; i -= lower_bit(i)) {
46 total += bit_[i];
47 }
48 return total;
49 }
50
51 private:
52 int lower_bit(int i) const {
53 return i & -i;
54 }
55
56 vector bit_;
57 };
58 };
59
60 // Time: O(nlogn)
61 // Space: O(n)
62 // Divide and Conquer solution. (80ms)
63 class Solution2 {
64 public:
65 vector countSmaller(vector& nums) {
66 vector counts(nums.size());
67 vector> num_idxs;
68 for (int i = 0; i < nums.size(); ++i) {
69 num_idxs.emplace_back(nums[i], i);
70 }
71 countAndMergeSort(&num_idxs, 0, num_idxs.size() - 1, &counts);
72 return counts;
73 }
74
75 void countAndMergeSort(vector> *num_idxs, int start, int end, vector *counts) {
76 if (end - start <= 0) { // The number of range [start, end] of which size is less than 2 doesn't need sort.
77 return;
78 }
79 int mid = start + (end - start) / 2;
80 countAndMergeSort(num_idxs, start, mid, counts);
81 countAndMergeSort(num_idxs, mid + 1, end, counts);
82
83 int r = mid + 1;
84 vector> tmp;
85 for (int i = start; i <= mid; ++i) {
86 // Merge the two sorted arrays into tmp.
87 while (r <= end && (*num_idxs)[r].first < (*num_idxs)[i].first) {
88 tmp.emplace_back((*num_idxs)[r++]);
89 }
90 tmp.emplace_back((*num_idxs)[i]);
91 (*counts)[(*num_idxs)[i].second] += r - (mid + 1);
92 }
93 // Copy tmp back to num_idxs.
94 copy(tmp.begin(), tmp.end(), num_idxs->begin() + start);
95 }
96 };
97
98 // Time: O(nlogn) ~ O(n^2)
99 // Space: O(n)
100 // BST solution. (40ms)
101 class Solution3 {
102 public:
103 class BSTreeNode {
104 public:
105 int val, count;
106 BSTreeNode *left, *right;
107 BSTreeNode(int val, int count) {
108 this->val = val;
109 this->count = count;
110 this->left = this->right = nullptr;
111 }
112 };
113
114 vector countSmaller(vector& nums) {
115 vector res(nums.size());
116
117 BSTreeNode *root = nullptr;
118
119 // Insert into BST and get left count.
120 for (int i = nums.size() - 1; i >= 0; --i) {
121 BSTreeNode *node = new BSTreeNode(nums[i], 0);
122 root = insertNode(root, node);
123 res[i] = query(root, nums[i]);
124 }
125
126 return res;
127 }
128
129 // Insert node into BST.
130 BSTreeNode* insertNode(BSTreeNode* root, BSTreeNode* node) {
131 if (root == nullptr) {
132 return node;
133 }
134 BSTreeNode* curr = root;
135 while (curr) {
135 while (curr) {
136 // Insert left if smaller.
137 if (node->val < curr->val) {
138 ++curr->count; // Increase the number of left children.
139 if (curr->left != nullptr) {
140 curr = curr->left;
141 } else {
142 curr->left = node;
143 break;
144 }
145 } else { // Insert right if larger or equal.
146 if (curr->right != nullptr) {
147 curr = curr->right;
148 } else {
149 curr->right = node;
150 break;
151 }
152 }
153 }
154 return root;
155 }
156
157 // Query the smaller count of the value.
158 int query(BSTreeNode* root, int val) {
159 if (root == nullptr) {
160 return 0;
161 }
162 int count = 0;
163 BSTreeNode* curr = root;
164 while (curr) {
165 // Insert left.
166 if (val < curr->val) {
167 curr = curr->left;
168 } else if (val > curr->val) {
169 count += 1 + curr->count; // Count the number of the smaller nodes.
170 curr = curr->right;
171 } else { // Equal.
172 return count + curr->count;
173 }
174 }
175 return 0;
176 }
177 };
***********************************

67. Count of Smaller Numbers After Self(Python)


***********************************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 class Solution(object):
5 def countSmaller(self, nums):
6 """
7 :type nums: List[int]
8 :rtype: List[int]
9 """
10 def countAndMergeSort(num_idxs, start, end, counts):
11 if end - start <= 0: # The size of range [start, end] less than 2 is always with count 0.
12 return 0
13
14 mid = start + (end - start) / 2
15 countAndMergeSort(num_idxs, start, mid, counts)
16 countAndMergeSort(num_idxs, mid + 1, end, counts)
17 r = mid + 1
18 tmp = []
19 for i in xrange(start, mid + 1):
20 # Merge the two sorted arrays into tmp.
21 while r <= end and num_idxs[r][0] < num_idxs[i][0]:
22 tmp.append(num_idxs[r])
23 r += 1
24 tmp.append(num_idxs[i])
25 counts[num_idxs[i][1]] += r - (mid + 1)
26
27 # Copy tmp back to num_idxs
28 num_idxs[start:start+len(tmp)] = tmp
29
30 num_idxs = []
31 counts = [0] * len(nums)
32 for i, num in enumerate(nums):
33 num_idxs.append((num, i))
34 countAndMergeSort(num_idxs, 0, len(num_idxs) - 1, counts)
35 return counts
36
37
38 # Time: O(nlogn)
39 # Space: O(n)
40 # BIT solution.
41 class Solution2(object):
42 def countSmaller(self, nums):
43 """
44 :type nums: List[int]
45 :rtype: List[int]
46 """
47 class BIT(object): # 0-indexed.
48 def __init__(self, n):
49 self.__bit = [0]*(n+1) # Extra one for dummy node.
50
51 def add(self, i, val):
52 i += 1 # Extra one for dummy node.
53 while i < len(self.__bit):
54 self.__bit[i] += val
55 i += (i & -i)
56
57 def query(self, i):
58 i += 1 # Extra one for dummy node.
59 ret = 0
60 while i > 0:
61 ret += self.__bit[i]
62 i -= (i & -i)
63 return ret
64
65 # Get the place (position in the ascending order) of each number.
66 sorted_nums = sorted(zip(nums, range(len(nums))))
67 lookup = {i:new_i for new_i, (_, i) in enumerate(sorted_nums)}
68
69 # Count the smaller elements after the number.
70 result, bit = [0]*len(nums), BIT(len(nums))
71 for i in reversed(xrange(len(nums))):
72 result[i] = bit.query(lookup[i]-1)
73 bit.add(lookup[i], 1)
74 return result
75
76
77 # Time: O(nlogn) ~ O(n^2)
78 # Space: O(n)
79 # BST solution.
80 class Solution3(object):
81 def countSmaller(self, nums):
82 """
83 :type nums: List[int]
84 :rtype: List[int]
85 """
86 res = [0] * len(nums)
87 bst = self.BST()
88 # Insert into BST and get left count.
89 for i in reversed(xrange(len(nums))):
90 bst.insertNode(nums[i])
91 res[i] = bst.query(nums[i])
92
93 return res
94
95 class BST(object):
96 class BSTreeNode(object):
97 def __init__(self, val):
98 self.val = val
99 self.count = 0
100 self.left = self.right = None
101
102 def __init__(self):
103 self.root = None
104
105 # Insert node into BST.
106 def insertNode(self, val):
107 node = self.BSTreeNode(val)
108 if not self.root:
109 self.root = node
110 return
111 curr = self.root
112 while curr:
113 # Insert left if smaller.
114 if node.val < curr.val:
115 curr.count += 1 # Increase the number of left children.
116 if curr.left:
117 curr = curr.left
118 else:
119 curr.left = node
120 break
121 else: # Insert right if larger or equal.
122 if curr.right:
123 curr = curr.right
124 else:
125 curr.right = node
126 break
127
128 # Query the smaller count of the value.
129 def query(self, val):
130 count = 0
131 curr = self.root
132 while curr:
133 # Insert left.
134 if val < curr.val:
135 curr = curr.left
135 curr = curr.left
136 elif val > curr.val:
137 count += 1 + curr.count # Count the number of the smaller nodes.
138 curr = curr.right
139 else: # Equal.
140 return count + curr.count
141 return 0
142
************************

68. Remove Duplicate Letters


************************

Given a string s , remove duplicate letters so that every letter appears once and only once. You must make sure your result
is the smallest in lexicographical order among all possible results.

Example 1:

Input: s = "bcabc"
Output: "abc"

Example 2:

Input: s = "cbacdcbc"
Output: "acdb"

Constraints:

1 <= s.length <= 104


s consists of lowercase English letters.

Note: This question is the same as 1081: https://leetcode.com/problems/smallest-subsequence-of-distinct-characters/


************************

68. Remove Duplicate Letters(C++)


************************

1 // Time: O(n)
2 // Space: O(k), k is size of the alphabet
3
4 // vector solution, need to know size of the alphabet in advance (4ms)
5 class Solution {
6 public:
7 string removeDuplicateLetters(string s) {
8 const int k = 26;
9 vector remaining(k);
10 for (const auto& c : s) {
11 ++remaining[c - 'a'];
12 }
13
14 vector in_stack(k);
15 string stk;
16 for (const auto& c : s) {
17 if (!in_stack[c - 'a']) {
18 while (!stk.empty() && stk.back() > c && remaining[stk.back() - 'a']) {
19 in_stack[stk.back() - 'a'] = false;
20 stk.pop_back();
21 }
22 stk.push_back(c);
23 in_stack[c - 'a'] = true;
24 }
25 --remaining[c - 'a'];
26 }
27 return stk;
28 }
29 };
30
31 // Time: O(n)
32 // Space: O(k), k is size of the alphabet
33 // hash solution, no need to know size of the alphabet in advance (16ms)
34 class Solution2 {
35 public:
36 string removeDuplicateLetters(string s) {
37 unordered_map remaining;
38 for (const auto& c : s) {
39 ++remaining[c];
40 }
41
42 unordered_set in_stack;
43 string stk;
44 for (const auto& c : s) {
45 if (!in_stack.count(c)) {
46 while (!stk.empty() && stk.back() > c && remaining[stk.back()]) {
47 in_stack.erase(stk.back());
48 stk.pop_back();
49 }
50 stk.push_back(c);
51 in_stack.emplace(c);
52 }
53 --remaining[c];
54 }
55 return stk;
56 }
57 };
************************

68. Remove Duplicate Letters(Python)


************************

1 # Time: O(n)
2 # Space: O(k), k is size of the alphabet
3
4 from collections import Counter
5
6
7 class Solution(object):
8 def removeDuplicateLetters(self, s):
9 """
10 :type s: str
11 :rtype: str
12 """
13 remaining = Counter(s)
14
15 in_stack, stk = set(), []
16 for c in s:
17 if c not in in_stack:
18 while stk and stk[-1] > c and remaining[stk[-1]]:
19 in_stack.remove(stk.pop())
20 stk += c
21 in_stack.add(c)
22 remaining[c] -= 1
23 return "".join(stk)
************************************

69. Shortest Distance from All Buildings


************************************

You are given an m x n grid grid of values 0, 1, or 2, where:

each 0 marks an empty land that you can pass by freely,


each 1 marks a building that you cannot pass through, and
each 2 marks an obstacle that you cannot pass through.

You want to build a house on an empty land that reaches all buildings in theshortest total travel distance. You can only
move up, down, left, and right.

Return the shortest travel distance for such a house. If it is not possible to build such a house according to the above rules,
return -1.

The total travel distance is the sum of the distances between the houses of the friends and the meeting point.

The distance is calculated using Manhattan Distance, where distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y| .

Example 1:

Input: grid = [[1,0,2,0,1],[0,0,0,0,0],[0,0,1,0,0]]


Output: 7
Explanation: Given three buildings at (0,0), (0,4), (2,2), and an obstacle at (0,2).
The point (1,2) is an ideal empty land to build a house, as the total travel distance of 3+3+1=7 is minimal.
So return 7.

Example 2:

Input: grid = [[1,0]]


Output: 1

Example 3:

Input: grid = [[1]]


Output: -1

Constraints:

m == grid.length
n == grid[i].length
1 <= m, n <= 100
grid[i][j] is either 0, 1,
or 2.
There will be at least one building in the grid.
************************************

69. Shortest Distance from All Buildings(C++)


************************************

1 // Time: O(k * m * n), k is the number of the buildings


2 // Space: O(m * n)
3
4 class Solution {
5 public:
6 int shortestDistance(vector>& grid) {
7 int m = grid.size(), n = grid[0].size(), cnt = 0;
8 vector> dists(m, vector(n)), cnts(m, vector(n));
9 for (int i = 0; i < m; ++i) {
10 for (int j = 0; j < n; ++j) {
11 if (grid[i][j] == 1) {
12 ++cnt;
13 BFS(grid, i, j, &dists, &cnts);
14 }
15 }
16 }
17
18 int shortest = numeric_limits::max();
19 for (int i = 0; i < m; ++i) {
20 for (int j = 0; j < n; ++j) {
21 if (dists[i][j] < shortest && cnts[i][j] == cnt) {
22 shortest = dists[i][j];
23 }
24 }
25 }
26
27 return shortest != numeric_limits::max() ? shortest : -1;
28 }
29
30 void BFS(const vector>& grid, int x, int y,
31 vector> *dists, vector> *cnts) {
32 int dist = 0, m = grid.size(), n = grid[0].size();
33 vector> visited(m, vector(n));
34
35 vector> pre_level{{x, y}}, cur_level;
36 visited[x][y] = true;
37 while (!pre_level.empty()) {
38 ++dist;
39 cur_level.clear();
40 for (const auto& p : pre_level) {
41 int i, j;
42 tie(i, j) = p;
43 const vector> directions{{0, -1}, {0, 1},
44 {-1, 0}, {1, 0}};
45 for (const auto& d : directions) {
46 const int I = i + d.first, J = j + d.second;
47 if (0 <= I && I < m && 0 <= J && J < n &&
48 grid[I][J] == 0 && !visited[I][J]) {
49 (*dists)[I][J] += dist;
50 ++(*cnts)[I][J];
51 cur_level.push_back({I, J});
52 visited[I][J] = true;
53 }
54 }
55 }
56 swap(pre_level, cur_level);
57 }
58 }
59 };
************************************

69. Shortest Distance from All Buildings(Python)


************************************

1 # Time: O(k * m * n), k is the number of the buildings


2 # Space: O(m * n)
3
4 class Solution(object):
5 def shortestDistance(self, grid):
6 """
7 :type grid: List[List[int]]
8 :rtype: int
9 """
10 def bfs(grid, dists, cnts, x, y):
11 dist, m, n = 0, len(grid), len(grid[0])
12 visited = [[False for _ in xrange(n)] for _ in xrange(m)]
13
14 pre_level = [(x, y)]
15 visited[x][y] = True
16 while pre_level:
17 dist += 1
18 cur_level = []
19 for i, j in pre_level:
20 for dir in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
21 I, J = i+dir[0], j+dir[1]
22 if 0 <= I < m and 0 <= J < n and grid[I][J] == 0 and not visited[I][J]:
23 cnts[I][J] += 1
24 dists[I][J] += dist
25 cur_level.append((I, J))
26 visited[I][J] = True
27
28 pre_level = cur_level
29
30
31 m, n, cnt = len(grid), len(grid[0]), 0
32 dists = [[0 for _ in xrange(n)] for _ in xrange(m)]
33 cnts = [[0 for _ in xrange(n)] for _ in xrange(m)]
34 for i in xrange(m):
35 for j in xrange(n):
36 if grid[i][j] == 1:
37 cnt += 1
38 bfs(grid, dists, cnts, i, j)
39
40 shortest = float("inf")
41 for i in xrange(m):
42 for j in xrange(n):
43 if dists[i][j] < shortest and cnts[i][j] == cnt:
44 shortest = dists[i][j]
45
46 return shortest if shortest != float("inf") else -1
47
*********************

70. Create Maximum Number


*********************

You are given two integer arrays nums1 and nums2 of lengths m and n respectively. nums1 and nums2 represent the digits of two
numbers. You are also given an integer k .

Create the maximum number of length k <= m + n from digits of the two numbers. The relative order of the digits from the
same array must be preserved.

Return an array of the k digits representing the answer.

Example 1:

Input: nums1 = [3,4,6,5], nums2 = [9,1,2,5,8,3], k = 5


Output: [9,8,6,5,3]

Example 2:

Input: nums1 = [6,7], nums2 = [6,0,4], k = 5


Output: [6,7,6,0,4]

Example 3:

Input: nums1 = [3,9], nums2 = [8,9], k = 3


Output: [9,8,9]

Constraints:

m == nums1.length
n == nums2.length
1 <= m, n <= 500
0 <= nums1[i], nums2[i] <= 9
1 <= k <= m + n
*********************

70. Create Maximum Number(C++)


*********************

1 // Time: O(k * (m + n + k)) ~ O(k * (m + n + k^2))


2 // Space: O(m + n + k^2)
3
4 // DP + Greedy solution.
5 class Solution {
6 public:
7 vector maxNumber(vector& nums1, vector& nums2, int k) {
8 const int m = nums1.size(), n = nums2.size();
9 vector> max_numbers1(k + 1), max_numbers2(k + 1);
10 maxNumberDP(nums1, max(0, k - n), min(k, m), &max_numbers1); // O(k * m) time, O(m + k^2) space.
11 maxNumberDP(nums2, max(0, k - m), min(k, n), &max_numbers2); // O(k * n) time, O(n + k^2) space.
12
13 vector res(k);
14 for (int i = max(0, k - n); i <= min(k, m); ++i) { // k * O(k) ~ k * O(k^2) time
15 vector tmp(k);
16 merge(max_numbers1[i], max_numbers2[k - i], &tmp);
17 if (tmp > res) {
18 res = move(tmp);
19 }
20 }
21 return res;
22 }
23
24 private:
25 void maxNumberDP(vector nums, int start, int end, vector> *max_numbers) {
26 (*max_numbers)[end] = maxNumber(nums, end);
27 for (int i = end - 1; i >= start; --i) {
28 (*max_numbers)[i] = deleteNumber((*max_numbers)[i + 1]);
29 }
30 }
31
32 // Time: O(n)
33 // Space: O(n)
34 vector maxNumber(const vector& nums, int k) {
35 vector res;
36 int drop = nums.size() - k;
37 for (const auto& num : nums) {
38 while (drop > 0 && !res.empty() && res.back() < num) {
39 res.pop_back();
40 --drop;
41 }
42 res.emplace_back(num);
43 }
44 res.resize(k);
45 return res;
46 }
47
48 // Time: O(n)
49 // Space: O(n)
50 vector deleteNumber(const vector& nums) {
51 vector res(nums);
52 for (int i = 0; i < res.size(); ++i) {
53 if (i == res.size() - 1 || res[i] < res[i + 1]) {
54 res.erase(res.begin() + i);
55 break;
56 }
57 }
58 return res;
59 }
60
61 // Time: O(k) ~ O(k^2)
62 // Space: O(1)
63 void merge(const vector& vec1, const vector& vec2, vector *res) {
64 auto first1 = vec1.begin(), last1 = vec1.end(),
65 first2 = vec2.begin(), last2 = vec2.end();
66 auto result = res->begin();
67 while (first1 != last1 || first2 != last2) {
68 if (greater(first1, last1, first2, last2)) {
69 *result++ = *first1++;
70 } else {
71 *result++ = *first2++;
72 }
73 }
74 }
75
76 template
77 bool greater(IT first1, IT last1, IT first2, IT last2) {
78 while (first1 != last1 && first2 != last2 && *first1 == *first2) {
79 ++first1;
80 ++first2;
81 }
82 return (first2 == last2) || (first1 != last1 && *first1 > *first2);
83 }
84 };
*********************

70. Create Maximum Number(Python)


*********************

1 # Time: O(k * (m + n + k)) ~ O(k * (m + n + k^2))


2 # Space: O(m + n + k^2)
3
4 class Solution(object):
5 def maxNumber(self, nums1, nums2, k):
6 """
7 :type nums1: List[int]
8 :type nums2: List[int]
9 :type k: int
10 :rtype: List[int]
11 """
12 def get_max_digits(nums, start, end, max_digits):
13 max_digits[end] = max_digit(nums, end)
14 for i in reversed(xrange(start, end)):
15 max_digits[i] = delete_digit(max_digits[i + 1])
16
17 def max_digit(nums, k):
18 drop = len(nums) - k
19 res = []
20 for num in nums:
21 while drop and res and res[-1] < num:
22 res.pop()
23 drop -= 1
24 res.append(num)
25 return res[:k]
26
27 def delete_digit(nums):
28 res = list(nums)
29 for i in xrange(len(res)):
30 if i == len(res) - 1 or res[i] < res[i + 1]:
31 res = res[:i] + res[i+1:]
32 break
33 return res
34
35 def merge(a, b):
36 return [max(a, b).pop(0) for _ in xrange(len(a)+len(b))]
37
38 m, n = len(nums1), len(nums2)
39
40 max_digits1, max_digits2 = [[] for _ in xrange(k + 1)], [[] for _ in xrange(k + 1)]
41 get_max_digits(nums1, max(0, k - n), min(k, m), max_digits1)
42 get_max_digits(nums2, max(0, k - m), min(k, n), max_digits2)
43
44 return max(merge(max_digits1[i], max_digits2[k-i]) \
45 for i in xrange(max(0, k - n), min(k, m) + 1))
46
******************

71. Count of Range Sum


******************

Given an integer array nums and two integers lower and upper, return the number of range sums that lie in[lower, upper] inclusive.

Range sum S(i, j) is defined as the sum of the elements innums between indices i and j inclusive, where i <= j .

Example 1:

Input: nums = [-2,5,-1], lower = -2, upper = 2


Output: 3
Explanation: The three ranges are: [0,0], [2,2], and [0,2] and their respective sums are: -2, -1, 2.

Example 2:

Input: nums = [0], lower = 0, upper = 0


Output: 1

Constraints:

1 <= nums.length <= 10 5


-231 <= nums[i] <= 2 31 - 1
-105 <= lower <= upper <= 10 5
The answer is guaranteed to fit in a 32-bit integer.
******************

71. Count of Range Sum(C++)


******************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 // Divide and Conquer solution.
5 class Solution {
6 public:
7 int countRangeSum(vector& nums, int lower, int upper) {
8 vector sums(nums.size() + 1);
9 for (int i = 0; i < nums.size(); ++i) {
10 sums[i + 1] = sums[i] + nums[i];
11 }
12 return countAndMergeSort(&sums, 0, sums.size(), lower, upper);
13 }
14
15 int countAndMergeSort(vector *sums, int start, int end, int lower, int upper) {
16 if (end - start <= 1) { // The number of range [start, end) of which size is less than 2 is always 0.
17 return 0;
18 }
19 int mid = start + (end - start) / 2;
20 int count = countAndMergeSort(sums, start, mid, lower, upper) +
21 countAndMergeSort(sums, mid, end, lower, upper);
22 int j = mid, k = mid, r = mid;
23 vector tmp;
24 for (int i = start; i < mid; ++i) {
25 // Count the number of range sums that lie in [lower, upper].
26 while (k < end && (*sums)[k] - (*sums)[i] < lower) {
27 ++k;
28 }
29 while (j < end && (*sums)[j] - (*sums)[i] <= upper) {
30 ++j;
31 }
32 count += j - k;
33
34 // Merge the two sorted arrays into tmp.
35 while (r < end && (*sums)[r] < (*sums)[i]) {
36 tmp.emplace_back((*sums)[r++]);
37 }
38 tmp.emplace_back((*sums)[i]);
39 }
40 // Copy tmp back to sums.
41 copy(tmp.begin(), tmp.end(), sums->begin() + start);
42 return count;
43 }
44 };
45
46 // Divide and Conquer solution.
47 class Solution2 {
48 public:
49 int countRangeSum(vector& nums, int lower, int upper) {
50 vector sums(nums.size() + 1);
51 for (int i = 0; i < nums.size(); ++i) {
52 sums[i + 1] = sums[i] + nums[i];
53 }
54 return countAndMergeSort(&sums, 0, sums.size() - 1, lower, upper);
55 }
56
57 int countAndMergeSort(vector *sums, int start, int end, int lower, int upper) {
58 if (end - start <= 0) { // The number of range [start, end] of which size is less than 2 is always 0.
59 return 0;
60 }
61 int mid = start + (end - start) / 2;
62 int count = countAndMergeSort(sums, start, mid, lower, upper) +
63 countAndMergeSort(sums, mid + 1, end, lower, upper);
64 int j = mid + 1, k = mid + 1, r = mid + 1;
65 vector tmp;
66 for (int i = start; i <= mid; ++i) {
67 // Count the number of range sums that lie in [lower, upper].
68 while (k <= end && (*sums)[k] - (*sums)[i] < lower) {
69 ++k;
70 }
71 while (j <= end && (*sums)[j] - (*sums)[i] <= upper) {
72 ++j;
73 }
74 count += j - k;
75
76 // Merge the two sorted arrays into tmp.
77 while (r <= end && (*sums)[r] < (*sums)[i]) {
78 tmp.emplace_back((*sums)[r++]);
79 }
80 tmp.emplace_back((*sums)[i]);
81 }
82 // Copy tmp back to sums.
83 copy(tmp.begin(), tmp.end(), sums->begin() + start);
84 return count;
85 }
86 };
******************

71. Count of Range Sum(Python)


******************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 class Solution(object):
5 def countRangeSum(self, nums, lower, upper):
6 """
7 :type nums: List[int]
8 :type lower: int
9 :type upper: int
10 :rtype: int
11 """
12 def countAndMergeSort(sums, start, end, lower, upper):
13 if end - start <= 1: # The size of range [start, end) less than 2 is always with count 0.
14 return 0
15 mid = start + (end - start) / 2
16 count = countAndMergeSort(sums, start, mid, lower, upper) + \
17 countAndMergeSort(sums, mid, end, lower, upper)
18 j, k, r = mid, mid, mid
19 tmp = []
20 for i in xrange(start, mid):
21 # Count the number of range sums that lie in [lower, upper].
22 while k < end and sums[k] - sums[i] < lower:
23 k += 1
24 while j < end and sums[j] - sums[i] <= upper:
25 j += 1
26 count += j - k
27
28 # Merge the two sorted arrays into tmp.
29 while r < end and sums[r] < sums[i]:
30 tmp.append(sums[r])
31 r += 1
32 tmp.append(sums[i])
33 # Copy tmp back to sums.
34 sums[start:start+len(tmp)] = tmp
35 return count
36
37 sums = [0] * (len(nums) + 1)
38 for i in xrange(len(nums)):
39 sums[i + 1] = sums[i] + nums[i]
40 return countAndMergeSort(sums, 0, len(sums), lower, upper)
41
42
43 # Divide and Conquer solution.
44 class Solution2(object):
45 def countRangeSum(self, nums, lower, upper):
46 """
47 :type nums: List[int]
48 :type lower: int
49 :type upper: int
50 :rtype: int
51 """
52 def countAndMergeSort(sums, start, end, lower, upper):
53 if end - start <= 0: # The size of range [start, end] less than 2 is always with count 0.
54 return 0
55
56 mid = start + (end - start) / 2
57 count = countAndMergeSort(sums, start, mid, lower, upper) + \
58 countAndMergeSort(sums, mid + 1, end, lower, upper)
59 j, k, r = mid + 1, mid + 1, mid + 1
60 tmp = []
61 for i in xrange(start, mid + 1):
62 # Count the number of range sums that lie in [lower, upper].
63 while k <= end and sums[k] - sums[i] < lower:
64 k += 1
65 while j <= end and sums[j] - sums[i] <= upper:
66 j += 1
67 count += j - k
68
69 # Merge the two sorted arrays into tmp.
70 while r <= end and sums[r] < sums[i]:
71 tmp.append(sums[r])
72 r += 1
73 tmp.append(sums[i])
74
75 # Copy tmp back to sums
76 sums[start:start+len(tmp)] = tmp
77 return count
78
79 sums = [0] * (len(nums) + 1)
80 for i in xrange(len(nums)):
81 sums[i + 1] = sums[i] + nums[i]
82 return countAndMergeSort(sums, 0, len(sums) - 1, lower, upper)
83
***********************************

72. Longest Increasing Path in a Matrix


***********************************

Given an m x n integers matrix, return the length of the longest increasing path in matrix.

From each cell, you can either move in four directions: left, right, up, or down. Youmay not move diagonally or move
outside the boundary (i.e., wrap-around is not allowed).

Example 1:

Input: matrix = [[9,9,4],[6,6,8],[2,1,1]]


Output: 4
Explanation: The longest increasing path is [1, 2, 6, 9].

Example 2:

Input: matrix = [[3,4,5],[3,2,6],[2,2,1]]


Output: 4
Explanation: The longest increasing path is [3, 4, 5, 6]. Moving diagonally is not allowed.

Example 3:

Input: matrix = [[1]]


Output: 1

Constraints:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 200
0 <= matrix[i][j] <= 231 - 1
***********************************

72. Longest Increasing Path in a Matrix(C++)


***********************************

1 // Time: O(m * n)
2 // Space: O(m * n)
3
4 // topological sort solution
5 class Solution {
6 public:
7 int longestIncreasingPath(vector>& matrix) {
8 static const vector> directions{{0, -1}, {0, 1},
9 {-1, 0}, {1, 0}};
10
11 if (matrix.empty()) {
12 return 0;
13 }
14
15 vector> in_degree(matrix.size(), vector(matrix[0].size()));
16 for (int i = 0; i < matrix.size(); ++i) {
17 for (int j = 0; j < matrix[0].size(); ++j) {
18 for (const auto& [di, dj] : directions) {
19 int ni = i + di, nj = j + dj;
20 if (!(0 <= ni && ni < matrix.size() &&
21 0 <= nj && nj < matrix[0].size() &&
22 matrix[ni][nj] > matrix[i][j])) {
23 continue;
24 }
25 ++in_degree[i][j];
26 }
27 }
28 }
29 vector> q;
30 for (int i = 0; i < matrix.size(); ++i) {
31 for (int j = 0; j < matrix[0].size(); ++j) {
32 if (!in_degree[i][j]) {
33 q.emplace_back(i, j);
34 }
35 }
36 }
37 int result = 0;
38 while (!q.empty()) {
39 vector> new_q;
40 for (const auto& [i, j] : q) {
41 for (const auto& [di, dj] : directions) {
42 int ni = i + di, nj = j + dj;
43 if (!(0 <= ni && ni < matrix.size() &&
44 0 <= nj && nj < matrix[0].size() &&
45 matrix[i][j] > matrix[ni][nj])) {
46 continue;
47 }
48 if (--in_degree[ni][nj] == 0) {
49 new_q.emplace_back(ni, nj);
50 }
51 }
52 }
53 q = move(new_q);
54 ++result;
55 }
56 return result;
57 }
58 };
59
60 // Time: O(m * n)
61 // Space: O(m * n)
62 // dfs + memorization solution
63 class Solution2 {
64 public:
65 int longestIncreasingPath(vector>& matrix) {
66 if (matrix.empty()) {
67 return 0;
68 }
69
70 int result = 0;
71 vector> max_lengths(matrix.size(), vector(matrix[0].size()));
72 for (int i = 0; i < matrix.size(); ++i) {
73 for (int j = 0; j < matrix[0].size(); ++j) {
74 result = max(result, longestpath(matrix, i, j, &max_lengths));
75 }
76 }
77 return result;
78 }
79
80 private:
81 int longestpath(const vector>& matrix, const int i, const int j,
82 vector> *max_lengths) {
83 if ((*max_lengths)[i][j] > 0) {
84 return (*max_lengths)[i][j];
85 }
86
87 int max_depth = 0;
88 const vector> directions{{0, -1}, {0, 1},
89 {-1, 0}, {1, 0}};
90 for (const auto& d : directions) {
91 const int x = i + d.first, y = j + d.second;
92 if (x >= 0 && x < matrix.size() &&
93 y >= 0 && y < matrix[0].size() &&
94 matrix[x][y] < matrix[i][j]) {
95 max_depth = max(max_depth,
96 longestpath(matrix, x, y, max_lengths));
97 }
98 }
99
100 (*max_lengths)[i][j] = max_depth + 1;
101 return (*max_lengths)[i][j];
102 }
103 };
***********************************

72. Longest Increasing Path in a Matrix(Python)


***********************************

1 # Time: O(m * n)
2 # Space: O(m * n)
3
4 # topological sort solution
5 class Solution(object):
6 def longestIncreasingPath(self, matrix):
7 """
8 :type matrix: List[List[int]]
9 :rtype: int
10 """
11 directions = [(0, -1), (0, 1), (-1, 0), (1, 0)]
12
13 if not matrix:
14 return 0
15
16 in_degree = [[0]*len(matrix[0]) for _ in xrange(len(matrix))]
17 for i in xrange(len(matrix)):
18 for j in xrange(len(matrix[0])):
19 for di, dj in directions:
20 ni, nj = i+di, j+dj
21 if not (0 <= ni < len(matrix) and
22 0 <= nj < len(matrix[0]) and
23 matrix[ni][nj] > matrix[i][j]):
24 continue
25 in_degree[i][j] += 1
26 q = []
27 for i in xrange(len(matrix)):
28 for j in xrange(len(matrix[0])):
29 if not in_degree[i][j]:
30 q.append((i, j))
31 result = 0
32 while q:
33 new_q = []
34 for i, j in q:
35 for di, dj in directions:
36 ni, nj = i+di, j+dj
37 if not (0 <= ni < len(matrix) and
38 0 <= nj < len(matrix[0]) and
39 matrix[i][j] > matrix[ni][nj]):
40 continue
41 in_degree[ni][nj] -= 1
42 if not in_degree[ni][nj]:
43 new_q.append((ni, nj))
44 q = new_q
45 result += 1
46 return result
47
48
49 # Time: O(m * n)
50 # Space: O(m * n)
51 # dfs + memoization solution
52 class Solution2(object):
53 def longestIncreasingPath(self, matrix):
54 """
55 :type matrix: List[List[int]]
56 :rtype: int
57 """
58 directions = [(0, -1), (0, 1), (-1, 0), (1, 0)]
59
60 def longestpath(matrix, i, j, max_lengths):
61 if max_lengths[i][j]:
62 return max_lengths[i][j]
63 max_depth = 0
64 for di, dj in directions:
65 x, y = i+di, j+dj
66 if 0 <= x < len(matrix) and 0 <= y < len(matrix[0]) and \
67 matrix[x][y] < matrix[i][j]:
68 max_depth = max(max_depth, longestpath(matrix, x, y, max_lengths))
69 max_lengths[i][j] = max_depth + 1
70 return max_lengths[i][j]
71
72 if not matrix:
73 return 0
74 result = 0
75 max_lengths = [[0 for _ in xrange(len(matrix[0]))] for _ in xrange(len(matrix))]
76 for i in xrange(len(matrix)):
77 for j in xrange(len(matrix[0])):
78 result = max(result, longestpath(matrix, i, j, max_lengths))
79 return result
**************

73. Patching Array


**************

Given a sorted integer array nums and an integer n, add/patch elements to the array such that any number in the range[1, n]
inclusive can be formed by the sum of some elements in the array.

Return the minimum number of patches required.

Example 1:

Input: nums = [1,3], n = 6


Output: 1
Explanation:
Combinations of nums are [1], [3], [1,3], which form possible sums of: 1, 3, 4.
Now if we add/patch 2 to nums, the combinations are: [1], [2], [3], [1,3], [2,3], [1,2,3].
Possible sums are 1, 2, 3, 4, 5, 6, which now covers the range [1, 6].
So we only need 1 patch.

Example 2:

Input: nums = [1,5,10], n = 20


Output: 2
Explanation: The two patches can be [2, 4].

Example 3:

Input: nums = [1,2,2], n = 5


Output: 0

Constraints:

1 <= nums.length <= 1000


1 <= nums[i] <= 10 4
nums is sorted in ascending order.
1 <= n <= 2 31 - 1
**************

73. Patching Array(C++)


**************

1 // Time: O(s + logn), s is the number of elements in the array


2 // Space: O(1)
3
4 class Solution {
5 public:
6 int minPatches(vector& nums, int n) {
7 int patch = 0;
8 for (uint64_t miss = 1, i = 0; miss <= n;) {
9 if (i < nums.size() && nums[i] <= miss) {
10 miss += nums[i++];
11 } else {
12 miss += miss; // miss may overflow, thus prefer to use uint64_t.
13 ++patch;
14 }
15 }
16 return patch;
17 }
18 };
**************

73. Patching Array(Python)


**************

1 # Time: O(s + logn), s is the number of elements in the array


2 # Space: O(1)
3
4 class Solution(object):
5 def minPatches(self, nums, n):
6 """
7 :type nums: List[int]
8 :type n: int
9 :rtype: int
10 """
11 patch, miss, i = 0, 1, 0
12 while miss <= n:
13 if i < len(nums) and nums[i] <= miss:
14 miss += nums[i]
15 i += 1
16 else:
17 miss += miss
18 patch += 1
19
20 return patch
21
*************

74. Self Crossing


*************

You are given an array of integersdistance.

You start at point (0,0) on an X-Y plane and you move distance[0] meters to the north, then distance[1] meters to the west,
distance[2] meters to the south, distance[3] meters to the east, and so on. In other words, after each move, your direction
changes counter-clockwise.

Return true if your path crosses itself, and false if it does not.

Example 1:

Input: distance = [2,1,1,2]


Output: true

Example 2:
Input: distance = [1,2,3,4]
Output: false

Example 3:

Input: distance = [1,1,1,1]


Output: true

Constraints:

1 <= distance.length <= 105


1 <= distance[i] <= 105
*************

74. Self Crossing(C++)


*************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 bool isSelfCrossing(vector& x) {
7 if (x.size() >= 5 && x[3] == x[1] && x[4] + x[0] >= x[2]) {
8 // Crossing in a loop:
9 // 2
10 // 3 ┌────â”​
11 // └─â•​â•​>┘1
12 // 4 0 (overlapped)
13 return true;
14 }
15
16 for (int i = 3; i < x.size(); ++i) {
17 if (x[i] >= x[i - 2] && x[i - 3] >= x[i - 1]) {
18 // Case 1:
19 // i-2
20 // i-1┌─â”​
21 // └─┼─>i
22 // i-3
23 return true;
24 } else if (i >= 5 && x[i - 4] <= x[i - 2] && x[i] + x[i - 4] >= x[i - 2] &&
25 x[i - 1] <= x[i - 3] && x[i - 1] + x[i - 5] >= x[i - 3]) {
26 // Case 2:
27 // i-4
28 // ┌──â”​
29 // │i<┼─â”​
30 // i-3│ i-5│i-1
31 // └────┘
32 // i-2
33 return true;
34 }
35 }
36 return false;
37 }
38 };
*************

74. Self Crossing(Python)


*************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def isSelfCrossing(self, x):
6 """
7 :type x: List[int]
8 :rtype: bool
9 """
10 if len(x) >= 5 and x[3] == x[1] and x[4] + x[0] >= x[2]:
11 # Crossing in a loop:
12 # 2
13 # 3 ┌────â”​
14 # └─â•​â•​>┘1
15 # 4 0 (overlapped)
16 return True
17
18 for i in xrange(3, len(x)):
19 if x[i] >= x[i - 2] and x[i - 3] >= x[i - 1]:
20 # Case 1:
21 # i-2
22 # i-1┌─â”​
23 # └─┼─>i
24 # i-3
25 return True
26 elif i >= 5 and x[i - 4] <= x[i - 2] and x[i] + x[i - 4] >= x[i - 2] and \
27 x[i - 1] <= x[i - 3] and x[i - 5] + x[i - 1] >= x[i - 3]:
28 # Case 2:
29 # i-4
30 # ┌──â”​
31 # │i<┼─â”​
32 # i-3│ i-5│i-1
33 # └────┘
34 # i-2
35 return True
36 return False
37
****************

75. Palindrome Pairs


****************

Given a list of unique words, return all the pairs of the distinct indices (i, j) in the given list, so that the concatenation of the
two words words[i] + words[j] is a palindrome.

Example 1:

Input: words = ["abcd","dcba","lls","s","sssll"]


Output: [[0,1],[1,0],[3,2],[2,4]]
Explanation: The palindromes are ["dcbaabcd","abcddcba","slls","llssssll"]

Example 2:

Input: words = ["bat","tab","cat"]


Output: [[0,1],[1,0]]
Explanation: The palindromes are ["battab","tabbat"]

Example 3:

Input: words = ["a",""]


Output: [[0,1],[1,0]]

Constraints:

1 <= words.length <= 5000


0 <= words[i].length <= 300
words[i] consists of lower-case English letters.
****************

75. Palindrome Pairs(C++)


****************

1 // Time: O(n * k^2), n is the number of the words, k is the max length of the words.
2 // Space: O(n * k)
3
4 class Solution {
5 public:
6 vector> palindromePairs(vector& words) {
7 vector> res;
8 unordered_map lookup;
9 for (int i = 0; i < words.size(); ++i) {
10 lookup[words[i]] = i;
11 }
12
13 for (int i = 0; i < words.size(); ++i) {
14 for (int j = 0; j <= words[i].length(); ++j) {
15 if (is_palindrome(words[i], j, words[i].length() - 1)) {
16 string suffix = words[i].substr(0, j);
17 reverse(suffix.begin(), suffix.end());
18 if (lookup.find(suffix) != lookup.end() && i != lookup[suffix]) {
19 res.push_back({i, lookup[suffix]});
20 }
21 }
22 if (j > 0 && is_palindrome(words[i], 0, j - 1)) {
23 string prefix = words[i].substr(j);
24 reverse(prefix.begin(), prefix.end());
25 if (lookup.find(prefix) != lookup.end() && lookup[prefix] != i) {
26 res.push_back({lookup[prefix], i});
27 }
28 }
29 }
30 }
31 return res;
32 }
33
34 private:
35 bool is_palindrome(string& s, int start, int end) {
36 while (start < end) {
37 if (s[start++] != s[end--]) {
38 return false;
39 }
40 }
41 return true;
42 }
43 };
44
45 // Time: O(n * k^2), n is the number of the words, k is the max length of the words.
46 // Space: O(n * k^2)
47 // Manacher solution.
48 class Solution2 {
49 public:
50 vector> palindromePairs(vector& words) {
51 unordered_multimap prefix, suffix;
52 for (int i = 0; i < words.size(); ++i) { // O(n)
53 vector P;
54 manacher(words[i], &P);
55 for (int j = 0; j < P.size(); ++j) { // O(k)
56 if (j - P[j] == 1) {
57 prefix.emplace(words[i].substr((j + P[j]) / 2), i); // O(k)
58 }
59 if (j + P[j] == P.size() - 2) {
60 suffix.emplace(words[i].substr(0, (j - P[j]) / 2), i);
61 }
62 }
63 }
64
65 vector> res;
66 for (int i = 0; i < words.size(); ++i) { // O(n)
67 string reversed_word(words[i].rbegin(), words[i].rend()); // O(k)
68 auto its = prefix.equal_range(reversed_word);
69 for (auto it = its.first; it != its.second; ++it) {
70 if (it->second != i) {
71 res.push_back({i, it->second});
72 }
73 }
74 its = suffix.equal_range(reversed_word);
75 for (auto it = its.first; it != its.second; ++it) {
76 if (words[i].size() != words[it->second].size()) {
77 res.push_back({it->second, i});
78 }
79 }
80 }
81 return res;
82 }
83
84 void manacher(const string& s, vector *P) {
85 string T = preProcess(s);
86 const int n = T.length();
87 P->resize(n);
88 int C = 0, R = 0;
89 for (int i = 1; i < n - 1; ++i) {
90 int i_mirror = 2 * C - i;
91 (*P)[i] = (R > i) ? min(R - i, (*P)[i_mirror]) : 0;
92 while (T[i + 1 + (*P)[i]] == T[i - 1 - (*P)[i]]) {
93 ++(*P)[i];
94 }
95 if (i + (*P)[i] > R) {
96 C = i;
97 R = i + (*P)[i];
98 }
99 }
100 }
101
102 string preProcess(const string& s) {
103 if (s.empty()) {
104 return "^$";
105 }
106 string ret = "^";
107 for (int i = 0; i < s.length(); ++i) {
108 ret += "#" + s.substr(i, 1);
109 }
110 ret += "#$";
111 return ret;
112 }
113 };
114
115 // Time: O(n * k^2), n is the number of the words, k is the max length of the words.
116 // Space: O(n * k)
117 // Trie solution.
118 class Solution_MLE {
119 public:
120 vector> palindromePairs(vector& words) {
121 vector> res;
122 TrieNode trie;
123 for (int i = 0; i < words.size(); ++i) {
124 trie.insert(words[i], i);
125 }
126 for (int i = 0; i < words.size(); ++i) {
127 trie.find(words[i], i, &res);
128 }
129 return res;
130 }
131
132 private:
133 struct TrieNode {
134 int word_idx = -1;
135 unordered_map leaves;
135 unordered_map leaves;
136
137 void insert(const string& s, int i) {
138 auto* p = this;
139 for (const auto& c : s) {
140 if (p->leaves.find(c) == p->leaves.cend()) {
141 p->leaves[c] = new TrieNode;
142 }
143 p = p->leaves[c];
144 }
145 p->word_idx = i;
146 }
147
148 void find(const string& s, int idx, vector> *res) {
149 auto* p = this;
150 for (int i = s.length() - 1; i >= 0; --i) { // O(k)
151 if (p->leaves.find(s[i]) != p->leaves.cend()) {
152 p = p->leaves[s[i]];
153 if (p->word_idx != -1 && p->word_idx != idx &&
154 is_palindrome(s, i - 1)) { // O(k)
155 res->push_back({p->word_idx, idx});
156 }
157 } else {
158 break;
159 }
160 }
161 }
162
163 bool is_palindrome(const string& s, int j) {
164 int i = 0;
165 while (i <= j) {
166 if (s[i++] != s[j--]) {
167 return false;
168 }
169 }
170 return true;
171 }
172
173 ~TrieNode() {
174 for (auto& kv : leaves) {
175 if (kv.second) {
176 delete kv.second;
177 }
178 }
179 }
180 };
181 };
****************

75. Palindrome Pairs(Python)


****************

1 # Time: O(n * k^2), n is the number of the words, k is the max length of the words.
2 # Space: O(n * k)
3
4 import collections
5
6
7 class Solution(object):
8 def palindromePairs(self, words):
9 """
10 :type words: List[str]
11 :rtype: List[List[int]]
12 """
13 res = []
14 lookup = {}
15 for i, word in enumerate(words):
16 lookup[word] = i
17
18 for i in xrange(len(words)):
19 for j in xrange(len(words[i]) + 1):
20 prefix = words[i][j:]
21 suffix = words[i][:j]
22 if prefix == prefix[::-1] and \
23 suffix[::-1] in lookup and lookup[suffix[::-1]] != i:
24 res.append([i, lookup[suffix[::-1]]])
25 if j > 0 and suffix == suffix[::-1] and \
26 prefix[::-1] in lookup and lookup[prefix[::-1]] != i:
27 res.append([lookup[prefix[::-1]], i])
28 return res
29
30 # Time: O(n * k^2), n is the number of the words, k is the max length of the words.
31 # Space: O(n * k^2)
32 # Manacher solution.
33 class Solution_TLE(object):
34 def palindromePairs(self, words):
35 """
36 :type words: List[str]
37 :rtype: List[List[int]]
38 """
39 def manacher(s, P):
40 def preProcess(s):
41 if not s:
42 return ['^', '$']
43 T = ['^']
44 for c in s:
45 T += ["#", c]
46 T += ['#', '$']
47 return T
48
49 T = preProcess(s)
50 center, right = 0, 0
51 for i in xrange(1, len(T) - 1):
52 i_mirror = 2 * center - i
53 if right > i:
54 P[i] = min(right - i, P[i_mirror])
55 else:
56 P[i] = 0
57 while T[i + 1 + P[i]] == T[i - 1 - P[i]]:
58 P[i] += 1
59 if i + P[i] > right:
60 center, right = i, i + P[i]
61
62 prefix, suffix = collections.defaultdict(list), collections.defaultdict(list)
63 for i, word in enumerate(words):
64 P = [0] * (2 * len(word) + 3)
65 manacher(word, P)
66 for j in xrange(len(P)):
67 if j - P[j] == 1:
68 prefix[word[(j + P[j]) / 2:]].append(i)
69 if j + P[j] == len(P) - 2:
70 suffix[word[:(j - P[j]) / 2]].append(i)
71 res = []
72 for i, word in enumerate(words):
73 for j in prefix[word[::-1]]:
74 if j != i:
75 res.append([i, j])
76 for j in suffix[word[::-1]]:
77 if len(word) != len(words[j]):
78 res.append([j, i])
79 return res
80
81
82 # Time: O(n * k^2), n is the number of the words, k is the max length of the words.
83 # Space: O(n * k)
84 # Trie solution.
85 class TrieNode(object):
86 def __init__(self):
87 self.word_idx = -1
88 self.leaves = {}
89
90 def insert(self, word, i):
91 cur = self
92 for c in word:
93 if not c in cur.leaves:
94 cur.leaves[c] = TrieNode()
95 cur = cur.leaves[c]
96 cur.word_idx = i
97
98 def find(self, s, idx, res):
99 cur = self
100 for i in reversed(xrange(len(s))):
101 if s[i] in cur.leaves:
102 cur = cur.leaves[s[i]]
103 if cur.word_idx not in (-1, idx) and \
104 self.is_palindrome(s, i - 1):
105 res.append([cur.word_idx, idx])
106 else:
107 break
108
109 def is_palindrome(self, s, j):
110 i = 0
111 while i <= j:
112 if s[i] != s[j]:
113 return False
114 i += 1
115 j -= 1
116 return True
117
118 class Solution_MLE(object):
119 def palindromePairs(self, words):
120 """
121 :type words: List[str]
122 :rtype: List[List[int]]
123 """
124 res = []
125 trie = TrieNode()
126 for i in xrange(len(words)):
127 trie.insert(words[i], i)
128
129 for i in xrange(len(words)):
130 trie.find(words[i], i, res)
131
132 return res
133
****************************************************

76. Longest Substring with At Most K Distinct Characters


****************************************************

Given a string s and an integer k , return the length of the longest substring of s that contains at most k distinct characters.

Example 1:

Input: s = "eceba", k = 2
Output: 3
Explanation: The substring is "ece" with length 3.

Example 2:

Input: s = "aa", k = 1
Output: 2
Explanation: The substring is "aa" with length 2.

Constraints:

1 <= s.length <= 5 * 10 4


0 <= k <= 50
****************************************************

76. Longest Substring with At Most K Distinct


Characters(C++)
****************************************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int lengthOfLongestSubstringKDistinct(string s, int k) {
7 int longest = 0, start = 0, distinct_count = 0;
8 array visited = {0};
9 for (int i = 0; i < s.length(); ++i) {
10 if (visited[s[i]] == 0) {
11 ++distinct_count;
12 }
13 ++visited[s[i]];
14 while (distinct_count > k) {
15 --visited[s[start]];
16 if (visited[s[start]] == 0) {
17 --distinct_count;
18 }
19 ++start;
20 }
21 longest = max(longest, i - start + 1);
22 }
23 return longest;
24 }
25 };
****************************************************

76. Longest Substring with At Most K Distinct


Characters(Python)
****************************************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def lengthOfLongestSubstringKDistinct(self, s, k):
6 """
7 :type s: str
8 :type k: int
9 :rtype: int
10 """
11 longest, start, distinct_count, visited = 0, 0, 0, [0 for _ in xrange(256)]
12 for i, char in enumerate(s):
13 if visited[ord(char)] == 0:
14 distinct_count += 1
15 visited[ord(char)] += 1
16 while distinct_count > k:
17 visited[ord(s[start])] -= 1
18 if visited[ord(s[start])] == 0:
19 distinct_count -= 1
20 start += 1
21 longest = max(longest, i - start + 1)
22 return longest
23
24
25 # Time: O(n)
26 # Space: O(1)
27 from collections import Counter
28
29
30 class Solution2(object):
31 def lengthOfLongestSubstringKDistinct(self, s, k):
32 """
33 :type s: str
34 :type k: int
35 :rtype: int
36 """
37 counter = Counter()
38 left, max_length = 0, 0
39 for right, char in enumerate(s):
40 counter[char] += 1
41 while len(counter) > k:
42 counter[s[left]] -= 1
43 if counter[s[left]] == 0:
44 del counter[s[left]]
45 left += 1
46 max_length = max(max_length, right-left+1)
47 return max_length
*********************************

77. Data Stream as Disjoint Intervals


*********************************

Given a data stream input of non-negative integers a1, a 2, ..., a n, summarize the numbers seen so far as a list of disjoint
intervals.

Implement the SummaryRanges class:

SummaryRanges() Initializes the object with an empty stream.


void addNum(int val) Adds the integer val to the stream.
int[][] getIntervals() Returns a summary of the integers in the stream currently as a list of disjoint intervals[starti, end i].

Example 1:

Input
["SummaryRanges", "addNum", "getIntervals", "addNum", "getIntervals", "addNum", "getIntervals", "addNum", "getIntervals", "addNum", "getInter
[[], [1], [], [3], [], [7], [], [2], [], [6], []]
Output
[null, null, [[1, 1]], null, [[1, 1], [3, 3]], null, [[1, 1], [3, 3], [7, 7]], null, [[1, 3], [7, 7]], null, [[1, 3], [6, 7]]]

Explanation
SummaryRanges summaryRanges = new SummaryRanges();
summaryRanges.addNum(1); // arr = [1]
summaryRanges.getIntervals(); // return [[1, 1]]
summaryRanges.addNum(3); // arr = [1, 3]
summaryRanges.getIntervals(); // return [[1, 1], [3, 3]]
summaryRanges.addNum(7); // arr = [1, 3, 7]
summaryRanges.getIntervals(); // return [[1, 1], [3, 3], [7, 7]]
summaryRanges.addNum(2); // arr = [1, 2, 3, 7]
summaryRanges.getIntervals(); // return [[1, 3], [7, 7]]
summaryRanges.addNum(6); // arr = [1, 2, 3, 6, 7]
summaryRanges.getIntervals(); // return [[1, 3], [6, 7]]

Constraints:

0 <= val <= 10 4


At most 3 * 104 calls will be made to addNum and getIntervals.

Follow up: What if there are lots of merges and the number of disjoint intervals is small compared to the size of the data
stream?
*********************************

77. Data Stream as Disjoint Intervals(C++)


*********************************

1 // Time: addNum: O(logn), getIntervals: O(n), n is the number of disjoint intervals.


2 // Space: O(n)
3
4 /**
5 * Definition for an interval.
6 * struct Interval {
7 * int start;
8 * int end;
9 * Interval() : start(0), end(0) {}
10 * Interval(int s, int e) : start(s), end(e) {}
11 * };
12 */
13 // Using set.
14 class SummaryRanges {
15 public:
16 /** Initialize your data structure here. */
17 SummaryRanges() {
18
19 }
20
21 void addNum(int val) {
22 auto it = intervals_.upper_bound(Interval(val, val));
23 int start = val, end = val;
24 if (it != intervals_.begin() && prev(it)->end + 1 >= val) {
25 --it;
26 }
27 while (it != intervals_.end() && end + 1 >= it->start) {
28 start = min(start, it->start);
29 end = max(end, it->end);
30 it = intervals_.erase(it);
31 }
32 intervals_.insert(it, Interval(start, end));
33 }
34
35 vector getIntervals() {
36 return {intervals_.cbegin(), intervals_.cend()};
37 }
38
39 private:
40 struct Compare {
41 bool operator() (const Interval& a, const Interval& b) {
42 return a.start < b.start;
43 }
44 };
45 set intervals_;
46 };
47
48
49 // Using map.
50 class SummaryRanges {
51 public:
52 /** Initialize your data structure here. */
53 SummaryRanges() {
54
55 }
56
57 void addNum(int val) {
58 auto it = intervals_.upper_bound(val);
59 int start = val, end = val;
60 if (it != intervals_.begin() && prev(it)->second + 1 >= val) {
61 --it;
62 }
63 while (it != intervals_.end() && end + 1 >= it->first) {
64 start = min(start, it->first);
65 end = max(end, it->second);
66 it = intervals_.erase(it);
67 }
68 intervals_[start] = end;
69 }
70
71 vector getIntervals() {
72 vector result;
73 for (const auto& kvp : intervals_) {
74 result.emplace_back(kvp.first, kvp.second);
75 }
76 return result;
77 }
78
79 private:
80 map intervals_;
81 };
82
83
84 // Time: addNum: O(n), getIntervals: O(n), n is the number of disjoint intervals.
85 // Space: O(n)
86 class SummaryRanges2 {
87 public:
88 public:
89 /** Initialize your data structure here. */
90 SummaryRanges2() {
91
92 }
93
94 void addNum(int val) {
95 auto it = upper_bound(intervals_.begin(), intervals_.end(), Interval(val, val), Compare());
96 int start = val, end = val;
97 if (it != intervals_.begin() && prev(it)->end + 1 >= val) {
98 --it;
99 }
100 while (it != intervals_.end() && end + 1 >= it->start) {
101 start = min(start, it->start);
102 end = max(end, it->end);
103 it = intervals_.erase(it);
104 }
105 intervals_.insert(it, Interval(start, end));
106 }
107
108 vector getIntervals() {
109 return intervals_;
110 }
111
112 private:
113 struct Compare {
114 bool operator() (const Interval& a, const Interval& b) {
115 return a.start < b.start;
116 }
117 };
118 vector intervals_;
119 };
120
121
122 // Time: addNum: O(logs), getIntervals: O(s), s is the data stream's size.
123 // Space: O(s)
124 class SummaryRanges3 {
125 public:
126 /** Initialize your data structure here. */
127 SummaryRanges3() {
128
129 }
130
131 void addNum(int val) {
132 nums_.emplace(val);
133 }
134
135 vector getIntervals() {
135 vector getIntervals() {
136 vector result;
137 if (nums_.empty()) {
138 return result;
139 }
140 auto start = *nums_.begin(), end = *nums_.begin();
141 for (auto it = next(nums_.begin()); it != nums_.end(); ++it) {
142 if (it != nums_.end() && *it == end + 1) {
143 end = *it;
144 } else {
145 result.emplace_back(start, end);
146 if (it != nums_.end()) {
147 start = end = *it;
148 }
149 }
150 }
151 result.emplace_back(start, end);
152 return result;
153 }
154
155 private:
156 set nums_;
157 };
158
159 /**
160 * Your SummaryRanges object will be instantiated and called as such:
161 * SummaryRanges obj = new SummaryRanges();
162 * obj.addNum(val);
163 * vector param_2 = obj.getIntervals();
164 */
165
*********************************

77. Data Stream as Disjoint Intervals(Python)


*********************************

1 # Time: addNum: O(n), getIntervals: O(n), n is the number of disjoint intervals.


2 # Space: O(n)
3
4 class Interval(object):
5 def __init__(self, s=0, e=0):
6 self.start = s
7 self.end = e
8
9
10 class SummaryRanges(object):
11
12 def __init__(self):
13 """
14 Initialize your data structure here.
15 """
16 self.__intervals = []
17
18 def addNum(self, val):
19 """
20 :type val: int
21 :rtype: void
22 """
23 def upper_bound(nums, target):
24 left, right = 0, len(nums) - 1
25 while left <= right:
26 mid = left + (right - left) / 2
27 if nums[mid].start > target:
28 right = mid - 1
29 else:
30 left = mid + 1
31 return left
32
33 i = upper_bound(self.__intervals, val)
34 start, end = val, val
35 if i != 0 and self.__intervals[i-1].end + 1 >= val:
36 i -= 1
37 while i != len(self.__intervals) and \
38 end + 1 >= self.__intervals[i].start:
39 start = min(start, self.__intervals[i].start)
40 end = max(end, self.__intervals[i].end)
41 del self.__intervals[i]
42 self.__intervals.insert(i, Interval(start, end))
43
44 def getIntervals(self):
45 """
46 :rtype: List[Interval]
47 """
48 return self.__intervals
49
50
51
**********************

78. Russian Doll Envelopes


**********************

You are given a 2D array of integersenvelopes where envelopes[i] = [w i, h i] represents the width and the height of an envelope.

One envelope can fit into another if and only if both the width and height of one envelope are greater than the other
envelope's width and height.

Return the maximum number of envelopes you can Russian doll (i.e., put one inside the other).

Note: You cannot rotate an envelope.

Example 1:

Input: envelopes = [[5,4],[6,4],[6,7],[2,3]]


Output: 3
Explanation: The maximum number of envelopes you can Russian doll is 3 ([2,3] => [5,4] => [6,7]).

Example 2:

Input: envelopes = [[1,1],[1,1],[1,1]]


Output: 1

Constraints:

1 <= envelopes.length <= 5000


envelopes[i].length == 2
1 <= wi, h i <= 104
**********************

78. Russian Doll Envelopes(C++)


**********************

1 // Time: O(nlogn + nlogk) = O(nlogn), k is the length of the result.


2 // Space: O(1)
3
4 class Solution {
5 public:
6 int maxEnvelopes(vector>& envelopes) {
7 vector result;
8
9 sort(envelopes.begin(), envelopes.end(), // O(nlogn)
10 [](const pair& a, const pair& b) {
11 if (a.first == b.first) {
12 return a.second > b.second;
13 }
14 return a.first < b.first;
15 });
16 for (const auto& envelope : envelopes) {
17 const auto target = envelope.second;
18 auto it = lower_bound(result.begin(), result.end(), target); // O(logk)
19 if (it == result.end()) {
20 result.emplace_back(target);
21 } else {
22 *it = target;
23 }
24 }
25
26 return result.size();
27 }
28 };
**********************

78. Russian Doll Envelopes(Python)


**********************

1 # Time: O(nlogn + nlogk) = O(nlogn), k is the length of the result.


2 # Space: O(1)
3
4 class Solution(object):
5 def maxEnvelopes(self, envelopes):
6 """
7 :type envelopes: List[List[int]]
8 :rtype: int
9 """
10 def insert(target):
11 left, right = 0, len(result) - 1
12 while left <= right:
13 mid = left + (right - left) / 2
14 if result[mid] >= target:
15 right = mid - 1
16 else:
17 left = mid + 1
18 if left == len(result):
19 result.append(target)
20 else:
21 result[left] = target
22
23 result = []
24
25 envelopes.sort(lambda x, y: y[1] - x[1] if x[0] == y[0] else \
26 x[0] - y[0])
27 for envelope in envelopes:
28 insert(envelope[1])
29
30 return len(result)
31
*********************************

79. Rearrange String k Distance Apart


*********************************

Given a string s and an integer k , rearrange s such that the same characters are at least distance k from each other. If it is
not possible to rearrange the string, return an empty string "".

Example 1:

Input: s = "aabbcc", k = 3
Output: "abcabc"
Explanation: The same letters are at least a distance of 3 from each other.

Example 2:

Input: s = "aaabc", k = 3
Output: ""
Explanation: It is not possible to rearrange the string.

Example 3:

Input: s = "aaadbbcc", k = 2
Output: "abacabcd"
Explanation: The same letters are at least a distance of 2 from each other.

Constraints:

1 <= s.length <= 3 * 10 5


s consists of only lowercase English letters.
0 <= k <= s.length
*********************************

79. Rearrange String k Distance Apart(C++)


*********************************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 string rearrangeString(string str, int k) {
7 int cnts [26] = {0};
8 for (int i = 0; i < str.length(); ++i) {
9 ++cnts[str[i] - 'a'];
10 }
11
12 vector> sorted_cnts;
13 for (int i = 0; i < 26; ++i) {
14 sorted_cnts.emplace_back(cnts[i], i + 'a');
15 }
16 sort(sorted_cnts.begin(), sorted_cnts.end(), greater>());
17
18 const auto max_cnt = sorted_cnts[0].first;
19 string blocks[max_cnt];
20 int i = 0;
21 for (const auto& cnt : sorted_cnts) {
22 for (int j = 0; j < cnt.first; ++j) {
23 blocks[i].push_back(cnt.second);
24 i = (i + 1) % max(cnt.first, max_cnt - 1);
25 }
26 }
27
28 string result;
29 for (int i = 0; i < max_cnt - 1; ++i) {
30 if (blocks[i].length() < k) {
31 return "";
32 } else {
33 result += blocks[i];
34 }
35 }
36 result += blocks[max_cnt - 1];
37 return result;
38 }
39 };
40
41 // Time: O(nlogc), c is the count of unique characters.
42 // Space: O(c)
43 class Solution2 {
44 public:
45 string rearrangeString(string str, int k) {
46 if (k == 0) {
47 return str;
48 }
49
50 unordered_map cnts;
51 for (const auto& c : str) {
52 ++cnts[c];
53 }
54
55 priority_queue> heap;
56 for (const auto& kvp : cnts) {
57 heap.emplace(kvp.second, kvp.first);
58 }
59
60 string result;
61 while (!heap.empty()) {
62 vector> used_cnt_chars;
63 int cnt = min(k, static_cast(str.length() - result.length()));
64 for (int i = 0; i < cnt; ++i) {
65 if (heap.empty()) {
66 return "";
67 }
68 auto cnt_char = heap.top();
69 heap.pop();
70 result.push_back(cnt_char.second);
71 if (--cnt_char.first > 0) {
72 used_cnt_chars.emplace_back(move(cnt_char));
73 }
74 }
75 for (auto& cnt_char: used_cnt_chars) {
76 heap.emplace(move(cnt_char));
77 }
78 }
79 return result;
80 }
81 };
*********************************

79. Rearrange String k Distance Apart(Python)


*********************************
1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 def rearrangeString(self, str, k):
6 """
7 :type str: str
8 :type k: int
9 :rtype: str
10 """
11 cnts = [0] * 26
12 for c in str:
13 cnts[ord(c) - ord('a')] += 1
14
15 sorted_cnts = []
16 for i in xrange(26):
17 sorted_cnts.append((cnts[i], chr(i + ord('a'))))
18 sorted_cnts.sort(reverse=True)
19
20 max_cnt = sorted_cnts[0][0]
21 blocks = [[] for _ in xrange(max_cnt)]
22 i = 0
23 for cnt in sorted_cnts:
24 for _ in xrange(cnt[0]):
25 blocks[i].append(cnt[1])
26 i = (i + 1) % max(cnt[0], max_cnt - 1)
27
28 for i in xrange(max_cnt-1):
29 if len(blocks[i]) < k:
30 return ""
31
32 return "".join(map(lambda x : "".join(x), blocks))
33
34
35 # Time: O(nlogc), c is the count of unique characters.
36 # Space: O(c)
37 from collections import Counter
38 from heapq import heappush, heappop
39 class Solution2(object):
40 def rearrangeString(self, s, k):
41 """
42 :type str: str
43 :type k: int
44 :rtype: str
45 """
46 if k <= 1:
47 return s
48
49 cnts = Counter(s)
50 heap = []
51 for c, cnt in cnts.iteritems():
52 heappush(heap, [-cnt, c])
53
54 result = []
55 while heap:
56 used_cnt_chars = []
57 for _ in xrange(min(k, len(s) - len(result))):
58 if not heap:
59 return ""
60 cnt_char = heappop(heap)
61 result.append(cnt_char[1])
62 cnt_char[0] += 1
63 if cnt_char[0] < 0:
64 used_cnt_chars.append(cnt_char)
65 for cnt_char in used_cnt_chars:
66 heappush(heap, cnt_char)
67
68 return "".join(result)
69
*************************************

80. Max Sum of Rectangle No Larger Than K


*************************************

Given an m x n matrix matrix and an integer k , return the max sum of a rectangle in the matrix such that its sum is no larger
than k .

It is guaranteed that there will be a rectangle with a sum no larger thank .

Example 1:

Input: matrix = [[1,0,1],[0,-2,3]], k = 2


Output: 2
Explanation: Because the sum of the blue rectangle [[0, 1], [-2, 3]] is 2, and 2 is the max number no larger than k (k = 2).

Example 2:

Input: matrix = [[2,2,-1]], k = 3


Output: 3

Constraints:

m == matrix.length
n == matrix[i].length
1 <= m, n <= 100
-100 <= matrix[i][j] <= 100
-105 <= k <= 10 5

Follow up: What if the number of rows is much larger than the number of columns?
*************************************

80. Max Sum of Rectangle No Larger Than K(C++)


*************************************

1 // Time: O(min(m, n)^2 * max(m, n) * log(max(m, n)))


2 // Space: O(max(m, n))
3
4 class Solution {
5 public:
6 int maxSumSubmatrix(vector>& matrix, int k) {
7 if (matrix.empty()) {
8 return 0;
9 }
10
11 const int m = min(matrix.size(), matrix[0].size());
12 const int n = max(matrix.size(), matrix[0].size());
13 int result = numeric_limits::min();
14
15 for (int i = 0; i < m; ++i) {
16 vector sums(n, 0);
17 for (int j = i; j < m; ++j) {
18 for (int l = 0; l < n; ++l) {
19 sums[l] += (m == matrix.size()) ? matrix[j][l] : matrix[l][j];
20 }
21
22 // Find the max subarray no more than K.
23 set accu_sum_set;
24 accu_sum_set.emplace(0);
25 int accu_sum = 0;
26 for (int sum : sums) {
27 accu_sum += sum;
28 auto it = accu_sum_set.lower_bound(accu_sum - k);
29 if (it != accu_sum_set.end()) {
30 result = max(result, accu_sum - *it);
31 }
32 accu_sum_set.emplace(accu_sum);
33 }
34 }
35 }
36
37 return result;
38 }
39 };
*************************************

80. Max Sum of Rectangle No Larger Than K(Python)


*************************************

1 # Time: O(min(m, n)^2 * max(m, n) * log(max(m, n)))


2 # Space: O(max(m, n))
3
4 from bisect import bisect_left, insort
5
6 class Solution(object):
7 def maxSumSubmatrix(self, matrix, k):
8 """
9 :type matrix: List[List[int]]
10 :type k: int
11 :rtype: int
12 """
13 if not matrix:
14 return 0
15
16 m = min(len(matrix), len(matrix[0]))
17 n = max(len(matrix), len(matrix[0]))
18 result = float("-inf")
19
20 for i in xrange(m):
21 sums = [0] * n
22 for j in xrange(i, m):
23 for l in xrange(n):
24 sums[l] += matrix[j][l] if m == len(matrix) else matrix[l][j]
25
26 # Find the max subarray no more than K.
27 accu_sum_set, accu_sum = [0], 0
28 for sum in sums:
29 accu_sum += sum
30 it = bisect_left(accu_sum_set, accu_sum - k) # Time: O(logn)
31 if it != len(accu_sum_set):
32 result = max(result, accu_sum - accu_sum_set[it])
33 insort(accu_sum_set, accu_sum) # Time: O(n)
34
35 return result
36
37
38 # Time: O(min(m, n)^2 * max(m, n) * log(max(m, n))) ~ O(min(m, n)^2 * max(m, n)^2)
39 # Space: O(max(m, n))
40 class Solution_TLE(object):
41 def maxSumSubmatrix(self, matrix, k):
42 """
43 :type matrix: List[List[int]]
44 :type k: int
45 :rtype: int
46 """
47 class BST(object): # not avl, rbtree
48 def __init__(self, val):
49 self.val = val
50 self.left = None
51 self.right = None
52
53 def insert(self, val): # Time: O(h) = O(logn) ~ O(n)
54 curr = self
55 while curr:
56 if curr.val >= val:
57 if curr.left:
58 curr = curr.left
59 else:
60 curr.left = BST(val)
61 return
62 else:
63 if curr.right:
64 curr = curr.right
65 else:
66 curr.right = BST(val)
67 return
68
69 def lower_bound(self, val): # Time: O(h) = O(logn) ~ O(n)
70 result, curr = None, self
71 while curr:
72 if curr.val >= val:
73 result, curr = curr, curr.left
74 else:
75 curr = curr.right
76 return result
77
78
79 if not matrix:
80 return 0
81
82 m = min(len(matrix), len(matrix[0]))
83 n = max(len(matrix), len(matrix[0]))
84 result = float("-inf")
85
86 for i in xrange(m):
87 sums = [0] * n
88 for j in xrange(i, m):
89 for l in xrange(n):
90 sums[l] += matrix[j][l] if m == len(matrix) else matrix[l][j]
91
92 # Find the max subarray no more than K.
93 accu_sum_set = BST(0)
94 accu_sum = 0
95 for sum in sums:
96 accu_sum += sum
97 node = accu_sum_set.lower_bound(accu_sum - k)
98 if node:
99 result = max(result, accu_sum - node.val)
100 accu_sum_set.insert(accu_sum)
101
102 return result
103
****************************

81. Insert Delete GetRandom O(1)


****************************

Implement the RandomizedSet class:

RandomizedSet() Initializes the RandomizedSet object.


bool insert(int val) Inserts an item val into the set if not present. Returns true if the item was not present, false otherwise.
bool remove(int val) Removes an item val from the set if present. Returns true if the item was present, false otherwise.
int getRandom() Returns a random element from the current set of elements (it's guaranteed that at least one element
exists when this method is called). Each element must have the same probability of being returned.

You must implement the functions of the class such that each function works inaverage O(1) time complexity.

Example 1:

Input
["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"]
[[], [1], [2], [2], [], [1], [2], []]
Output
[null, true, false, true, 2, true, false, 2]

Explanation
RandomizedSet randomizedSet = new RandomizedSet();
randomizedSet.insert(1); // Inserts 1 to the set. Returns true as 1 was inserted successfully.
randomizedSet.remove(2); // Returns false as 2 does not exist in the set.
randomizedSet.insert(2); // Inserts 2 to the set, returns true. Set now contains [1,2].
randomizedSet.getRandom(); // getRandom() should return either 1 or 2 randomly.
randomizedSet.remove(1); // Removes 1 from the set, returns true. Set now contains [2].
randomizedSet.insert(2); // 2 was already in the set, so return false.
randomizedSet.getRandom(); // Since 2 is the only number in the set, getRandom() will always return 2.

Constraints:

-231 <= val <= 2 31 - 1


At most 2 * 105 calls will be made to insert, remove, and getRandom.
There will be at least one element in the data structure whengetRandom is called.
****************************

81. Insert Delete GetRandom O(1)(C++)


****************************

1 // Time: O(1)
2 // Space: O(n)
3
4 class RandomizedSet {
5 public:
6 /** Initialize your data structure here. */
7 RandomizedSet() : gen_(random_device()()) {
8
9 }
10
11 /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
12 bool insert(int val) {
13 if (used_.count(val)) {
14 return false;
15 }
16
17 set_.emplace_back(val);
18 used_[val] = set_.size() - 1;
19
20 return true;
21 }
22
23 /** Removes a value from the set. Returns true if the set contained the specified element. */
24 bool remove(int val) {
25 if (!used_.count(val)) {
26 return false;
27 }
28
29 used_[set_.back()] = used_[val];
30 swap(set_[used_[val]], set_.back());
31
32 used_.erase(val);
33 set_.pop_back();
34
35 return true;
36 }
37
38 /** Get a random element from the set. */
39 int getRandom() {
40 uniform_int_distribution dist(0, set_.size() - 1);
41 return set_[dist(gen_)];
42 }
43
44 private:
45 vector set_;
46 unordered_map used_;
47 default_random_engine gen_;
48 };
49
50 /**
51 * Your RandomizedSet object will be instantiated and called as such:
52 * RandomizedSet obj = new RandomizedSet();
53 * bool param_1 = obj.insert(val);
54 * bool param_2 = obj.remove(val);
55 * int param_3 = obj.getRandom();
56 */
57
****************************

81. Insert Delete GetRandom O(1)(Python)


****************************

1 # Time: O(1)
2 # Space: O(n)
3
4 from random import randint
5
6 class RandomizedSet(object):
7
8 def __init__(self):
9 """
10 Initialize your data structure here.
11 """
12 self.__set = []
13 self.__used = {}
14
15
16 def insert(self, val):
17 """
18 Inserts a value to the set. Returns true if the set did not already contain the specified element.
19 :type val: int
20 :rtype: bool
21 """
22 if val in self.__used:
23 return False
24
25 self.__set += val,
26 self.__used[val] = len(self.__set)-1
27
28 return True
29
30
31 def remove(self, val):
32 """
33 Removes a value from the set. Returns true if the set contained the specified element.
34 :type val: int
35 :rtype: bool
36 """
37 if val not in self.__used:
38 return False
39
40 self.__used[self.__set[-1]] = self.__used[val]
41 self.__set[self.__used[val]], self.__set[-1] = self.__set[-1], self.__set[self.__used[val]]
42
43 self.__used.pop(val)
44 self.__set.pop()
45
46 return True
47
48 def getRandom(self):
49 """
50 Get a random element from the set.
51 :rtype: int
52 """
53 return self.__set[randint(0, len(self.__set)-1)]
54
55
56
*************************************************

82. Insert Delete GetRandom O(1) - Duplicates allowed


*************************************************

Implement the RandomizedCollection class:

RandomizedCollection() Initializes the RandomizedCollection object.


bool insert(int val) Inserts an item val into the multiset if not present. Returns true if the item was not present, false
otherwise.
bool remove(int val) Removes an item val from the multiset if present. Returns true if the item was present, false otherwise.
Note that if val has multiple occurrences in the multiset, we only remove one of them.
int getRandom() Returns a random element from the current multiset of elements (it's guaranteed that at least one
element exists when this method is called). The probability of each element being returned is linearly related to the
number of same values the multiset contains.

You must implement the functions of the class such that each function works inaverage O(1) time complexity.

Example 1:

Input
["RandomizedCollection", "insert", "insert", "insert", "getRandom", "remove", "getRandom"]
[[], [1], [1], [2], [], [1], []]
Output
[null, true, false, true, 2, true, 1]

Explanation
RandomizedCollection randomizedCollection = new RandomizedCollection();
randomizedCollection.insert(1); // return True. Inserts 1 to the collection. Returns true as the collection did not contain 1.
randomizedCollection.insert(1); // return False. Inserts another 1 to the collection. Returns false as the collection contained 1. Collecti
randomizedCollection.insert(2); // return True. Inserts 2 to the collection, returns true. Collection now contains [1,1,2].
randomizedCollection.getRandom(); // getRandom should return 1 with the probability 2/3, and returns 2 with the probability 1/3.
randomizedCollection.remove(1); // return True. Removes 1 from the collection, returns true. Collection now contains [1,2].
randomizedCollection.getRandom(); // getRandom should return 1 and 2 both equally likely.

Constraints:

-231 <= val <= 2 31 - 1


At most 2 * 105 calls will be made to insert, remove, and getRandom.
There will be at least one element in the data structure whengetRandom is called.
*************************************************

82. Insert Delete GetRandom O(1) - Duplicates


allowed(C++)
*************************************************

1 // Time: O(1)
2 // Space: O(n)
3
4 class RandomizedCollection {
5 public:
6 /** Initialize your data structure here. */
7 RandomizedCollection() : gen_(random_device()()) {
8
9 }
10
11 /** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
12 bool insert(int val) {
13 bool has = used_.count(val);
14
15 list_.emplace_back(val, used_[val].size());
16 used_[val].emplace_back(list_.size() - 1);
17
18 return !has;
19 }
20
21 /** Removes a value from the collection. Returns true if the collection contained the specified element. */
22 bool remove(int val) {
23 if (!used_.count(val)) {
24 return false;
25 }
26
27 used_[list_.back().first][list_.back().second] = used_[val].back();
28 swap(list_[used_[val].back()], list_.back());
29
30 used_[val].pop_back();
31 if (used_[val].empty()) {
32 used_.erase(val);
33 }
34 list_.pop_back();
35
36 return true;
37 }
38
39 /** Get a random element from the collection. */
40 int getRandom() {
41 uniform_int_distribution dist(0, list_.size() - 1);
42 return list_[dist(gen_)].first;
43 }
44
45 private:
46 vector> list_;
47 unordered_map> used_;
48 default_random_engine gen_;
49 };
50
51 /**
52 * Your RandomizedCollection object will be instantiated and called as such:
53 * RandomizedCollection obj = new RandomizedCollection();
54 * bool param_1 = obj.insert(val);
55 * bool param_2 = obj.remove(val);
56 * int param_3 = obj.getRandom();
57 */
58
*************************************************

82. Insert Delete GetRandom O(1) - Duplicates


allowed(Python)
*************************************************

1 # Time: O(1)
2 # Space: O(n)
3
4 from random import randint
5 from collections import defaultdict
6
7 class RandomizedCollection(object):
8
9 def __init__(self):
10 """
11 Initialize your data structure here.
12 """
13 self.__list = []
14 self.__used = defaultdict(list)
15
16
17 def insert(self, val):
18 """
19 Inserts a value to the collection. Returns true if the collection did not already contain the specified element.
20 :type val: int
21 :rtype: bool
22 """
23 has = val in self.__used
24
25 self.__list += (val, len(self.__used[val])),
26 self.__used[val] += len(self.__list)-1,
27
28 return not has
29
30
31 def remove(self, val):
32 """
33 Removes a value from the collection. Returns true if the collection contained the specified element.
34 :type val: int
35 :rtype: bool
36 """
37 if val not in self.__used:
38 return False
39
40 self.__used[self.__list[-1][0]][self.__list[-1][1]] = self.__used[val][-1]
41 self.__list[self.__used[val][-1]], self.__list[-1] = self.__list[-1], self.__list[self.__used[val][-1]]
42
43 self.__used[val].pop()
44 if not self.__used[val]:
45 self.__used.pop(val)
46 self.__list.pop()
47
48 return True
49
50 def getRandom(self):
51 """
52 Get a random element from the collection.
53 :rtype: int
54 """
55 return self.__list[randint(0, len(self.__list)-1)][0]
*****************

83. Perfect Rectangle


*****************

Given an array rectangles where rectangles[i] = [x i, y i, a i, b i] represents an axis-aligned rectangle. The bottom-left point of the
rectangle is (xi, y i) and the top-right point of it is (a i, b i).

Return true if all the rectangles together form an exact cover of a rectangular region.

Example 1:

Input: rectangles = [[1,1,3,3],[3,1,4,2],[3,2,4,4],[1,3,2,4],[2,3,3,4]]


Output: true
Explanation: All 5 rectangles together form an exact cover of a rectangular region.

Example 2:

Input: rectangles = [[1,1,2,3],[1,3,2,4],[3,1,4,2],[3,2,4,4]]


Output: false
Explanation: Because there is a gap between the two rectangular regions.

Example 3:
Input: rectangles = [[1,1,3,3],[3,1,4,2],[1,3,2,4],[3,2,4,4]]
Output: false
Explanation: Because there is a gap in the top center.

Example 4:

Input: rectangles = [[1,1,3,3],[3,1,4,2],[1,3,2,4],[2,2,4,4]]


Output: false
Explanation: Because two of the rectangles overlap with each other.

Constraints:

1 <= rectangles.length <= 2 * 10 4


rectangles[i].length == 4
-105 <= x i, y i, a i, b i <= 105
*****************

83. Perfect Rectangle(C++)


*****************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 bool isRectangleCover(vector>& rectangles) {
7 enum Location {L = 0, B = 1, R = 2, T = 3};
8 int left = numeric_limits::max(), bottom = numeric_limits::max(),
9 right = numeric_limits::min(), top = numeric_limits::min();
10 for (const auto& rect : rectangles) {
11 left = min(left, rect[L]);
12 bottom = min(bottom, rect[B]);
13 right = max(right, rect[R]);
14 top = max(top, rect[T]);
15 }
16
17 using P = pair, int>;
18 enum Corner {LB = 1, RB = 2, LT = 4, RT = 8};
19 unordered_map> corner_count;
20 vector

corners{{{L, B}, LB}, {{R, B}, RB}, {{L, T}, LT}, {{R, T}, RT}}; for (const auto& rect : rectangles) { for (const auto&
corner : corners) { const auto x = rect[corner.first.first]; const auto y = rect[corner.first.second]; if
(corner_count[x][y] & corner.second) { return false; } corner_count[x][y] |= corner.second; } } bitset<16> is_valid;
is_valid[LB | RB] = is_valid[LB | LT] = is_valid[RB | RT] = is_valid[LT | RT] = is_valid[LB | RB | LT | RT] = true; for
(auto itx = corner_count.cbegin(); itx != corner_count.cend(); ++itx) { const auto x = itx->first; for (auto ity = itx-
>second.cbegin(); ity != itx->second.cend(); ++ity) { const auto y = ity->first; const auto mask = ity->second; if ((left
< x && x < right) || (bottom < y && y < top)) { if (!is_valid[mask]) { return false; } } } } return true; } };
*****************

83. Perfect Rectangle(Python)


*****************

1 # Time: O(n)
2 # Space: O(n)
3
4 from collections import defaultdict
5
6 class Solution(object):
7 def isRectangleCover(self, rectangles):
8 """
9 :type rectangles: List[List[int]]
10 :rtype: bool
11 """
12 left = min(rec[0] for rec in rectangles)
13 bottom = min(rec[1] for rec in rectangles)
14 right = max(rec[2] for rec in rectangles)
15 top = max(rec[3] for rec in rectangles)
16
17 points = defaultdict(int)
18 for l, b, r, t in rectangles:
19 for p, q in zip(((l, b), (r, b), (l, t), (r, t)), (1, 2, 4, 8)):
20 if points[p] & q:
21 return False
22 points[p] |= q
23
24 for px, py in points:
25 if left < px < right or bottom < py < top:
26 if points[(px, py)] not in (3, 5, 10, 12, 15):
27 return False
28
29 return True
30
*********

84. Frog Jump


*********

A frog is crossing a river. The river is divided into some number of units, and at each unit, there may or may not exist a
stone. The frog can jump on a stone, but it must not jump into the water.

Given a list of stones' positions (in units) in sorted ascending order, determine if the frog can cross the river by landing on
the last stone. Initially, the frog is on the first stone and assumes the first jump must be 1 unit.

If the frog's last jump was k units, its next jump must be either k - 1 , k , or k + 1 units. The frog can only jump in the forward
direction.

Example 1:

Input: stones = [0,1,3,5,6,8,12,17]


Output: true
Explanation: The frog can jump to the last stone by jumping 1 unit to the 2nd stone, then 2 units to the 3rd stone, then 2 units to the 4th s

Example 2:

Input: stones = [0,1,2,3,4,8,9,11]


Output: false
Explanation: There is no way to jump to the last stone as the gap between the 5th and 6th stone is too large.

Constraints:

2 <= stones.length <= 2000


0 <= stones[i] <= 2 31 - 1
stones[0] == 0
stones is sorted in a strictly increasing order.
*********

84. Frog Jump(C++)


*********

1 // Time: O(n^2)
2 // Space: O(n^2)
3
4 class Solution {
5 public:
6 bool canCross(vector& stones) {
7 if (stones[1] != 1) {
8 return false;
9 }
10
11 unordered_map> last_jump_units;
12 for (const auto& s: stones) {
13 last_jump_units.emplace(s, {unordered_set()});
14 }
15 last_jump_units[1].emplace(1);
16
17 for (int i = 0; i + 1 < stones.size(); ++i) {
18 for (const auto& j : last_jump_units[stones[i]]) {
19 for (const auto& k : {j - 1, j, j + 1}) {
20 if (k > 0 && last_jump_units.count(stones[i] + k)) {
21 last_jump_units[stones[i] + k].emplace(k);
22 }
23 }
24 }
25 }
26
27 return !last_jump_units[stones.back()].empty();
28 }
29 };
*********

84. Frog Jump(Python)


*********

1 # Time: O(n^2)
2 # Space: O(n^2)
3
4 class Solution(object):
5 def canCross(self, stones):
6 """
7 :type stones: List[int]
8 :rtype: bool
9 """
10 if stones[1] != 1:
11 return False
12
13 last_jump_units = {s: set() for s in stones}
14 last_jump_units[1].add(1)
15 for s in stones[:-1]:
16 for j in last_jump_units[s]:
17 for k in (j-1, j, j+1):
18 if k > 0 and s+k in last_jump_units:
19 last_jump_units[s+k].add(k)
20 return bool(last_jump_units[stones[-1]])
21
**********************

85. Trapping Rain Water II


**********************

Given an m x n integer matrix heightMap representing the height of each unit cell in a 2D elevation map, returnthe volume of
water it can trap after raining.

Example 1:

Input: heightMap = [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]]


Output: 4
Explanation: After the rain, water is trapped between the blocks.
We have two small pounds 1 and 3 units trapped.
The total volume of water trapped is 4.

Example 2:

Input: heightMap = [[3,3,3,3,3],[3,2,2,2,3],[3,2,1,2,3],[3,2,2,2,3],[3,3,3,3,3]]


Output: 10

Constraints:
m == heightMap.length
n == heightMap[i].length
1 <= m, n <= 200
0 <= heightMap[i][j] <= 2 * 10 4
**********************

85. Trapping Rain Water II(C++)


**********************

1 // Time: O(m * n * log(m + n)) ~ O(m * n * log(m * n))


2 // Space: O(m * n)
3
4 class Solution {
5 public:
6 int trapRainWater(vector>& heightMap) {
7 // Init m_, n_, is_visited_.
8 m_ = heightMap.size();
9 if (!m_) {
10 return 0;
11 }
12 n_ = heightMap[0].size();
13 if (!n_) {
14 return 0;
15 }
16
17 is_visited_ = vector>(m_, vector(n_, false));
18
19 int trap = 0;
20
21 // Put the cells on the border into min heap.
22 for (int i = 0; i < m_; ++i) {
23 heap_.emplace(Cell{i, 0, heightMap[i][0]});
24 is_visited_[i][0] = true;
25 heap_.emplace(Cell{i, n_ - 1, heightMap[i][n_ - 1]});
26 is_visited_[i][n_ - 1] = true;
27 }
28 for (int j = 1; j < n_ - 1; ++j) {
29 heap_.emplace(Cell{0, j, heightMap[0][j]});
30 is_visited_[0][j] = true;
31 heap_.emplace(Cell{m_ - 1, j, heightMap[m_ - 1][j]});
32 is_visited_[m_ - 1][j] = true;
33 }
34 const vector> directions{{0, -1}, {0, 1},
35 {-1, 0}, {1, 0}};
36 // BFS with priority queue (min heap)
37 while (!heap_.empty()) {
38 Cell c = heap_.top();
39 heap_.pop();
40 for (const auto& d : directions) {
41 trap += fill(heightMap, c.i + d.first, c.j + d.second, c.height);
42 }
43 }
44
45 return trap;
46 }
47
48 private:
49 int fill(const vector>& heightMap, int i, int j, int height) {
50 // Out of border.
51 if ( i < 0 || i >= m_ || j < 0 || j >= n_) {
52 return 0;
53 }
54
55 // Fill unvisited cell.
56 if (!is_visited_[i][j]) {
57 heap_.emplace(Cell{i, j, max(height, heightMap[i][j])});
58 is_visited_[i][j] = true; // Marked as visited.
59 return max(0, height - heightMap[i][j]); // Fill in the gap.
60 }
61
62 return 0;
63 }
64
65 struct Cell {
66 int i;
67 int j;
68 int height;
69 };
70
71 struct Compare {
72 bool operator()(const Cell& a, const Cell& b) {
73 return a.height > b.height;
74 }
75 };
76
77 int m_;
78 int n_;
79 vector> is_visited_;
80 priority_queue, Compare> heap_; // Use min heap to get the lowerest cell.
81 };
**********************

85. Trapping Rain Water II(Python)


**********************

1 # Time: O(m * n * log(m + n)) ~ O(m * n * log(m * n))


2 # Space: O(m * n)
3
4 from heapq import heappush, heappop
5
6 class Solution(object):
7 def trapRainWater(self, heightMap):
8 """
9 :type heightMap: List[List[int]]
10 :rtype: int
11 """
12 m = len(heightMap)
13 if not m:
14 return 0
15 n = len(heightMap[0])
16 if not n:
17 return 0
18
19 is_visited = [[False for i in xrange(n)] for j in xrange(m)]
20
21 heap = []
22 for i in xrange(m):
23 heappush(heap, [heightMap[i][0], i, 0])
24 is_visited[i][0] = True
25 heappush(heap, [heightMap[i][n-1], i, n-1])
26 is_visited[i][n-1] = True
27 for j in xrange(1, n-1):
28 heappush(heap, [heightMap[0][j], 0, j])
29 is_visited[0][j] = True
30 heappush(heap, [heightMap[m-1][j], m-1, j])
31 is_visited[m-1][j] = True
32
33 trap = 0
34 while heap:
35 height, i, j = heappop(heap)
36 for (dx, dy) in [(1,0), (-1,0), (0,1), (0,-1)]:
37 x, y = i+dx, j+dy
38 if 0 <= x < m and 0 <= y < n and not is_visited[x][y]:
39 trap += max(0, height - heightMap[x][y])
40 heappush(heap, [max(height, heightMap[x][y]), x, y])
41 is_visited[x][y] = True
42
43 return trap
44
***********************

86. Split Array Largest Sum


***********************

Given an array nums which consists of non-negative integers and an integer m, you can split the array into m non-empty
continuous subarrays.

Write an algorithm to minimize the largest sum among thesem subarrays.

Example 1:

Input: nums = [7,2,5,10,8], m = 2


Output: 18
Explanation:
There are four ways to split nums into two subarrays.
The best way is to split it into [7,2,5] and [10,8],
where the largest sum among the two subarrays is only 18.

Example 2:

Input: nums = [1,2,3,4,5], m = 2


Output: 9

Example 3:

Input: nums = [1,4,4], m = 3


Output: 4

Constraints:

1 <= nums.length <= 1000


0 <= nums[i] <= 10 6
1 <= m <= min(50, nums.length)
***********************

86. Split Array Largest Sum(C++)


***********************

1 // Time: O(nlogs), s is the sum of nums


2 // Space: O(1)
3
4 class Solution {
5 public:
6 int splitArray(vector& nums, int m) {
7 int64_t left = *max_element(cbegin(nums), cend(nums));
8 int64_t right = accumulate(cbegin(nums), cend(nums), 0LL);
9 while (left <= right) {
10 const auto mid = left + (right - left) / 2;
11 if (check(nums, m, mid)) {
12 right = mid - 1;
13 } else {
14 left = mid + 1;
15 }
16 }
17 return left;
18 }
19
20 private:
21 bool check(vector& nums, int m, int64_t total) {
22 int cnt = 1;
23 int64_t curr_sum = 0;
24 for (const auto& num : nums) {
25 curr_sum += num;
26 if (curr_sum > total) {
27 curr_sum = num;
28 ++cnt;
29 }
30 }
31 return cnt <= m;
32 }
33 };
***********************

86. Split Array Largest Sum(Python)


***********************

1 # Time: O(nlogs), s is the sum of nums


2 # Space: O(1)
3
4 class Solution(object):
5 def splitArray(self, nums, m):
6 """
7 :type nums: List[int]
8 :type m: int
9 :rtype: int
10 """
11 def check(nums, m, s):
12 cnt, curr_sum = 1, 0
13 for num in nums:
14 curr_sum += num
15 if curr_sum > s:
16 curr_sum = num
17 cnt += 1
18 return cnt <= m
19
20 left, right = max(nums), sum(nums)
21 while left <= right:
22 mid = left + (right - left) // 2
23 if check(nums, m, mid):
24 right = mid - 1
25 else:
26 left = mid + 1
27 return left
********************************

87. Minimum Unique Word Abbreviation


********************************

A string can be abbreviated by replacing any number of non-adjacent substrings with their lengths. For example, a string
such as "substitution" could be abbreviated as (but not limited to):

"s10n" ("s ubstitutio n" )


"sub4u4" ("sub stit u tion" )
"12" ("substitution" )
"su3i1u2on" ("su bst i t u ti on")
"substitution" (no substrings replaced)

Note that "s55n" ("s ubsti tutio n" ) is not a valid abbreviation of "substitution" because the replaced substrings are adjacent.

The length of an abbreviation is the number of letters that were not replaced plus the number of substrings that were
replaced. For example, the abbreviation "s10n" has a length of 3 (2 letters + 1 substring) and "su3i1u2on" has a length of 9 (6
letters + 3 substrings).

Given a target string target and an array of strings dictionary , return an abbreviation of target with the shortest possible length
such that it is not an abbreviation of any string in dictionary . If there are multiple shortest abbreviations, return any of them.

Example 1:

Input: target = "apple", dictionary = ["blade"]


Output: "a4"
Explanation: The shortest abbreviation of "apple" is "5", but this is also an abbreviation of "blade".
The next shortest abbreviations are "a4" and "4e". "4e" is an abbreviation of blade while "a4" is not.
Hence, return "a4".

Example 2:

Input: target = "apple", dictionary = ["blade","plain","amber"]


Output: "1p3"
Explanation: "5" is an abbreviation of both "apple" but also every word in the dictionary.
"a4" is an abbreviation of "apple" but also "amber".
"4e" is an abbreviation of "apple" but also "blade".
"1p3", "2p2", and "3l1" are the next shortest abbreviations of "apple".
Since none of them are abbreviations of words in the dictionary, returning any of them is correct.

Constraints:

target.length == m
dictionary.length == n
1 <= m <= 21
0 <= n <= 1000
1 <= dictionary[i] <= 100
log2(n) + m <= 21 if n > 0
********************************

87. Minimum Unique Word Abbreviation(C++)


********************************

1 // Time: O((d + n) * 2^n)


2 // Space: O(d)
3
4 // optimized from Solution2
5 class Solution {
6 public:
7 string minAbbreviation(string target, vector& dictionary) {
8 vector diffs;
9 dictionary_to_diffs(target, dictionary, &diffs);
10 if (empty(diffs)) {
11 return to_string(size(target));
12 }
13 int total = 1 << size(target);
14 int result = total - 1;
15 for (int mask = 0; mask < total; ++mask) {
16 if (all_of(cbegin(diffs), cend(diffs), [&mask](int d) { return d & mask; })) {
17 if (bits_to_abbr_len(target, mask) < bits_to_abbr_len(target, result)) {
18 result = mask;
19 }
20 }
21 }
22 return bits_to_abbr(target, result);
23 }
24
25 private:
26 void dictionary_to_diffs(const string& target, const vector& dictionary,
27 vector *diffs) {
28
29 for (const auto& word : dictionary) {
30 if (size(word) != size(target)) {
31 continue;
32 }
33 int bits = 0;
34 for (int i = 0; i < size(word); ++i) {
35 if (target[i] != word[i]) {
36 bits |= 1 << i;
37 }
38 }
39 diffs->emplace_back(bits);
40 }
41 }
42
43 int bits_to_abbr_len(const string& target, int bits) {
44 int total = 0;
45 for (int i = 0, pre = 0; i < size(target); ++i, bits >>= 1) {
46 if (bits & 1) {
47 if (i - pre > 0) {
48 total += size(to_string(i - pre));
49 }
50 pre = i + 1;
51 ++total;
52 } else if (i == size(target) - 1) {
53 total += size(to_string(i - pre + 1));
54 }
55 }
56 return total;
57 }
58
59 string bits_to_abbr(const string& target, int bits) {
60 string abbr;
61 for (int i = 0, pre = 0; i < size(target); ++i, bits >>= 1) {
62 if (bits & 1) {
63 if (i - pre > 0) {
64 abbr += to_string(i - pre);
65 }
66 pre = i + 1;
67 abbr.push_back(target[i]);
68 } else if (i == size(target) - 1) {
69 abbr += to_string(i - pre + 1);
70 }
71 }
72 return abbr;
73 }
74 };
75
76 // Time: O((d + n) * 2^n)
77 // Space: O(d + n)
78 class Solution2 {
79 public:
80 string minAbbreviation(string target, vector& dictionary) {
81 vector diffs;
82 dictionary_to_diffs(target, dictionary, &diffs);
83 if (empty(diffs)) {
84 return to_string(size(target));
85 }
86 int total = 1 << size(target);
87 string result = target;
88 for (int mask = 0; mask < total; ++mask) {
89 if (all_of(cbegin(diffs), cend(diffs), [&mask](int d) { return d & mask; })) {
90 auto abbr = bits_to_abbr(target, mask);
91 if (size(abbr) < size(result)) {
92 result = move(abbr);
93 }
94 }
95 }
96 return result;
97 }
98
99 private:
100 void dictionary_to_diffs(const string& target, const vector& dictionary,
101 vector *diffs) {
102
103 for (const auto& word : dictionary) {
104 if (size(word) != size(target)) {
105 continue;
106 }
107 int bits = 0;
108 for (int i = 0; i < size(word); ++i) {
109 if (target[i] != word[i]) {
110 bits |= 1 << i;
111 }
112 }
113 diffs->emplace_back(bits);
114 }
115 }
116
117 string bits_to_abbr(const string& target, int bits) {
118 string abbr;
119 for (int i = 0, pre = 0; i < size(target); ++i, bits >>= 1) {
120 if (bits & 1) {
121 if (i - pre > 0) {
122 abbr += to_string(i - pre);
123 }
124 pre = i + 1;
125 abbr.push_back(target[i]);
126 } else if (i == size(target) - 1) {
127 abbr += to_string(i - pre + 1);
128 }
129 }
130 return abbr;
131 }
132 };
********************************

87. Minimum Unique Word Abbreviation(Python)


********************************

1 # Time: O((d + n) * 2^n)


2 # Space: O(d)
3
4 # optimized from Solution2
5 class Solution(object):
6 def minAbbreviation(self, target, dictionary):
7 """
8 :type target: str
9 :type dictionary: List[str]
10 :rtype: str
11 """
12 def bits_to_abbr_len(targets, bits):
13 total = 0
14 pre = 0
15 for i in xrange(len(target)):
16 if bits & 1:
17 if i - pre > 0:
18 total += len(str(i - pre))
19 pre = i + 1
20 total += 1
21 elif i == len(target) - 1:
22 total += len(str(i - pre + 1))
23 bits >>= 1
24 return total
25
26 def bits_to_abbr(targets, bits):
27 abbr = []
28 pre = 0
29 for i in xrange(len(target)):
30 if bits & 1:
31 if i - pre > 0:
32 abbr.append(str(i - pre))
33 pre = i + 1
34 abbr.append(target[i])
35 elif i == len(target) - 1:
36 abbr.append(str(i - pre + 1))
37 bits >>= 1
38 return "".join(abbr)
39
40 diffs = []
41 for word in dictionary:
42 if len(word) != len(target):
43 continue
44 diffs.append(sum(2**i for i, c in enumerate(word) if target[i] != c))
45
46 if not diffs:
47 return str(len(target))
48
49 result = 2**len(target)-1
50 for mask in xrange(2**len(target)):
51 if all(d & mask for d in diffs) and bits_to_abbr_len(target, mask) < bits_to_abbr_len(target, result):
52 result = mask
53 return bits_to_abbr(target, result)
54
55
56 # Time: O((d + n) * 2^n)
57 # Space: O(d + n)
58 class Solution2(object):
59 def minAbbreviation(self, target, dictionary):
60 """
61 :type target: str
62 :type dictionary: List[str]
63 :rtype: str
64 """
65 def bits_to_abbr(targets, bits):
66 abbr = []
67 pre = 0
68 for i in xrange(len(target)):
69 if bits & 1:
70 if i - pre > 0:
71 abbr.append(str(i - pre))
72 pre = i + 1
73 abbr.append(target[i])
74 elif i == len(target) - 1:
75 abbr.append(str(i - pre + 1))
76 bits >>= 1
77 return "".join(abbr)
78
79 diffs = []
80 for word in dictionary:
81 if len(word) != len(target):
82 continue
83 diffs.append(sum(2**i for i, c in enumerate(word) if target[i] != c))
84
85 if not diffs:
86 return str(len(target))
87
88 result = target
89 for mask in xrange(2**len(target)):
90 abbr = bits_to_abbr(target, mask)
91 if all(d & mask for d in diffs) and len(abbr) < len(result):
92 result = abbr
93 return result
94
***********************

88. Strong Password Checker


***********************

A password is considered strong if the below conditions are all met:

It has at least 6 characters and at most 20 characters.


It contains at least one lowercase letter, at least one uppercase letter, and at least one digit.
It does not contain three repeating characters in a row (i.e., "...aaa..." is weak, but "...aa...a..." is strong, assuming other
conditions are met).

Given a string password, return the minimum number of steps required to makepassword strong. if password is already strong,
return 0.

In one step, you can:

Insert one character to password,


Delete one character from password, or
Replace one character of password with another character.

Example 1:

Input: password = "a"


Output: 5

Example 2:

Input: password = "aA1"


Output: 3

Example 3:

Input: password = "1337C0d3"


Output: 0

Constraints:

1 <= password.length <= 50


password consists of letters, digits, dot '.' or exclamation mark '!'.
***********************

88. Strong Password Checker(C++)


***********************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int strongPasswordChecker(string s) {
7 int missing_type_cnt = 3;
8 missing_type_cnt -= static_cast(any_of(s.begin(), s.end(), [](char c){ return isdigit(c); }));
9 missing_type_cnt -= static_cast(any_of(s.begin(), s.end(), [](char c){ return isupper(c); }));
10 missing_type_cnt -= static_cast(any_of(s.begin(), s.end(), [](char c){ return islower(c); }));
11
12 int total_change_cnt = 0;
13 int one_change_cnt = 0, two_change_cnt = 0, three_change_cnt = 0;
14 for (int i = 2; i < s.length();) {
15 if (s[i] == s[i - 1] && s[i - 1] == s[i - 2]) {
16 int length = 2;
17 while (i < s.length() && s[i] == s[i - 1]) {
18 ++length;
19 ++i;
20 }
21 total_change_cnt += length / 3;
22 if (length % 3 == 0) {
23 ++one_change_cnt;
24 } else if (length % 3 == 1) {
25 ++two_change_cnt;
26 } else {
27 ++three_change_cnt;
28 }
29 } else {
30 ++i;
31 }
32 }
33
34 if (s.length() < 6) {
35 return max(missing_type_cnt, 6 - static_cast(s.length()));
36 } else if (s.length() <= 20) {
37 return max(missing_type_cnt, total_change_cnt);
38 }
39
40 int delete_cnt = s.length() - 20;
41
42 total_change_cnt -= min(delete_cnt, one_change_cnt) / 1;
43 total_change_cnt -= min(max(delete_cnt - one_change_cnt, 0), two_change_cnt * 2) / 2;
44 total_change_cnt -= min(max(delete_cnt - one_change_cnt - 2 * two_change_cnt, 0), three_change_cnt * 3) / 3;
45
46 return delete_cnt + max(missing_type_cnt, total_change_cnt);
47 }
48 };
***********************

88. Strong Password Checker(Python)


***********************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def strongPasswordChecker(self, s):
6 """
7 :type s: str
8 :rtype: int
9 """
10 missing_type_cnt = 3
11 if any('a' <= c <= 'z' for c in s):
12 missing_type_cnt -= 1
13 if any('A' <= c <= 'Z' for c in s):
14 missing_type_cnt -= 1
15 if any(c.isdigit() for c in s):
16 missing_type_cnt -= 1
17
18 total_change_cnt = 0
19 one_change_cnt, two_change_cnt, three_change_cnt = 0, 0, 0
20 i = 2
21 while i < len(s):
22 if s[i] == s[i-1] == s[i-2]:
23 length = 2
24 while i < len(s) and s[i] == s[i-1]:
25 length += 1
26 i += 1
27
28 total_change_cnt += length / 3
29 if length % 3 == 0:
30 one_change_cnt += 1
31 elif length % 3 == 1:
32 two_change_cnt += 1
33 else:
34 three_change_cnt += 1
35 else:
36 i += 1
37
38 if len(s) < 6:
39 return max(missing_type_cnt, 6 - len(s))
40 elif len(s) <= 20:
41 return max(missing_type_cnt, total_change_cnt)
42 else:
43 delete_cnt = len(s) - 20
44
45 total_change_cnt -= min(delete_cnt, one_change_cnt * 1) / 1
46 total_change_cnt -= min(max(delete_cnt - one_change_cnt, 0), two_change_cnt * 2) / 2
47 total_change_cnt -= min(max(delete_cnt - one_change_cnt - 2 * two_change_cnt, 0), three_change_cnt * 3) / 3
48
49 return delete_cnt + max(missing_type_cnt, total_change_cnt)
50
************

89. Word Squares


************

Given an array of unique strings words, return all the word squares you can build from words. The same word from words can
be used multiple times. You can return the answer in any order.

A sequence of strings forms a valid word square if the k th row and column read the same string, where 0 <= k < max(numRows,
numColumns).

For example, the word sequence ["ball","area","lead","lady"] forms a word square because each word reads the same both
horizontally and vertically.

Example 1:

Input: words = ["area","lead","wall","lady","ball"]


Output: [["ball","area","lead","lady"],["wall","area","lead","lady"]]
Explanation:
The output consists of two word squares. The order of output does not matter (just the order of words in each word square matters).

Example 2:

Input: words = ["abat","baba","atan","atal"]


Output: [["baba","abat","baba","atal"],["baba","abat","baba","atan"]]
Explanation:
The output consists of two word squares. The order of output does not matter (just the order of words in each word square matters).

Constraints:

1 <= words.length <= 1000


1 <= words[i].length <= 5
All words[i] have the same length.
words[i] consists of only lowercase English letters.
All words[i] are unique.
************

89. Word Squares(C++)


************
1 // Time: O(n^2 * n!)
2 // Space: O(n^2)
3
4 class Solution {
5 private:
6 struct TrieNode {
7 vector indices;
8 vector children;
9 TrieNode() : children(26, nullptr) {}
10 };
11
12 TrieNode *buildTrie(const vector& words) {
13 TrieNode *root = new TrieNode();
14 for (int i = 0; i < size(words); ++i) {
15 TrieNode* t = root;
16 for (int j = 0; j < size(words[i]); ++j) {
17 if (!t->children[words[i][j] - 'a']) {
18 t->children[words[i][j] - 'a'] = new TrieNode();
19 }
20 t = t->children[words[i][j] - 'a'];
21 t->indices.emplace_back(i);
22 }
23 }
24 return root;
25 }
26
27 public:
28 vector> wordSquares(vector& words) {
29 vector> result;
30
31 TrieNode *trie = buildTrie(words);
32 vector curr;
33 for (const auto& s : words) {
34 curr.emplace_back(s);
35 wordSquaresHelper(words, trie, &curr, &result);
36 curr.pop_back();
37 }
38
39 return result;
40 }
41
42 private:
43 void wordSquaresHelper(const vector& words, TrieNode *trie, vector *curr,
44 vector> *result) {
45 if (size(*curr) == size(words[0])) {
46 result->emplace_back(*curr);
47 return;
48 }
49
50 TrieNode *node = trie;
51 for (int i = 0; i < size(*curr); ++i) {
52 if (!(node = node->children[(*curr)[i][curr->size()] - 'a'])) {
53 return;
54 }
55 }
56
57 for (const auto& i : node->indices) {
58 curr->emplace_back(words[i]);
59 wordSquaresHelper(words, trie, curr, result);
60 curr->pop_back();
61 }
62 }
63 };
************

89. Word Squares(Python)


************

1 # Time: O(n^2 * n!)


2 # Space: O(n^2)
3
4 class TrieNode(object):
5 def __init__(self):
6 self.indices = []
7 self.children = [None] * 26
8
9 def insert(self, words, i):
10 cur = self
11 for c in words[i]:
12 if not cur.children[ord(c)-ord('a')]:
13 cur.children[ord(c)-ord('a')] = TrieNode()
14 cur = cur.children[ord(c)-ord('a')]
15 cur.indices.append(i)
16
17
18 class Solution(object):
19 def wordSquares(self, words):
20 """
21 :type words: List[str]
22 :rtype: List[List[str]]
23 """
24 result = []
25
26 trie = TrieNode()
27 for i in xrange(len(words)):
28 trie.insert(words, i)
29
30 curr = []
31 for s in words:
32 curr.append(s)
33 self.wordSquaresHelper(words, trie, curr, result)
34 curr.pop()
35
36 return result
37
38 def wordSquaresHelper(self, words, trie, curr, result):
39 if len(curr) >= len(words[0]):
40 return result.append(list(curr))
41
42 node = trie
43 for s in curr:
44 node = node.children[ord(s[len(curr)]) - ord('a')]
45 if not node:
46 return
47
48 for i in node.indices:
49 curr.append(words[i])
50 self.wordSquaresHelper(words, trie, curr, result)
51 curr.pop()
52
************************

90. All O`one Data Structure


************************

Design a data structure to store the strings' count with the ability to return the strings with minimum and maximum counts.

Implement the AllOne class:

AllOne() Initializes the object of the data structure.


inc(String key) Increments the count of the string key by 1. If key does not exist in the data structure, insert it with count1.
dec(String key) Decrements the count of the stringkey by 1. If the count of key is 0 after the decrement, remove it from the
data structure. It is guaranteed that key exists in the data structure before the decrement.
getMaxKey() Returns one of the keys with the maximal count. If no element exists, return an empty string"".
getMinKey() Returns one of the keys with the minimum count. If no element exists, return an empty string"".

Example 1:

Input
["AllOne", "inc", "inc", "getMaxKey", "getMinKey", "inc", "getMaxKey", "getMinKey"]
[[], ["hello"], ["hello"], [], [], ["leet"], [], []]
Output
[null, null, null, "hello", "hello", null, "hello", "leet"]

Explanation
AllOne allOne = new AllOne();
allOne.inc("hello");
allOne.inc("hello");
allOne.getMaxKey(); // return "hello"
allOne.getMinKey(); // return "hello"
allOne.inc("leet");
allOne.getMaxKey(); // return "hello"
allOne.getMinKey(); // return "leet"

Constraints:

1 <= key.length <= 10


key consists of lowercase English letters.
It is guaranteed that for each call to dec, key is existing in the data structure.
At most 5 * 104 calls will be made to inc, dec, getMaxKey, and getMinKey.
************************

90. All O`one Data Structure(C++)


************************

1 // Time: O(1), per operation


2 // Space: O(k)
3
4 class AllOne {
5 public:
6 /** Initialize your data structure here. */
7 AllOne() {
8
9 }
10
11 /** Inserts a new key with value 1. Or increments an existing key by 1. */
12 void inc(string key) {
13 if (!bucketOfKey_.count(key)) {
14 bucketOfKey_[key] = buckets_.insert(buckets_.begin(), {0, {key}});
15 }
16
17 auto next = bucketOfKey_[key], bucket = next++;
18 if (next == buckets_.end() || next->value > bucket->value + 1) {
19 next = buckets_.insert(next, {bucket->value + 1, {}});
20 }
21 next->keys.insert(key);
22 bucketOfKey_[key] = next;
23
24 bucket->keys.erase(key);
25 if (bucket->keys.empty()) {
26 buckets_.erase(bucket);
27 }
28 }
29
30 /** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
31 void dec(string key) {
32 if (!bucketOfKey_.count(key)) {
33 return;
34 }
35
36 auto prev = bucketOfKey_[key], bucket = prev--;
37 bucketOfKey_.erase(key);
38 if (bucket->value > 1) {
39 if (bucket == buckets_.begin() || prev->value < bucket->value - 1) {
40 prev = buckets_.insert(bucket, {bucket->value - 1, {}});
41 }
42 prev->keys.insert(key);
43 bucketOfKey_[key] = prev;
44 }
45
46 bucket->keys.erase(key);
47 if (bucket->keys.empty()) {
48 buckets_.erase(bucket);
49 }
50 }
51
52 /** Returns one of the keys with maximal value. */
53 string getMaxKey() {
54 return buckets_.empty() ? "" : *(buckets_.rbegin()->keys.begin());
55 }
56
57 /** Returns one of the keys with Minimal value. */
58 string getMinKey() {
59 return buckets_.empty() ? "" : *(buckets_.begin()->keys.begin());
60 }
61
62 private:
63 struct Bucket {
64 int value;
65 unordered_set keys;
66 };
67 list buckets_;
68 unordered_map::iterator> bucketOfKey_;
69 };
70
71 /**
72 * Your AllOne object will be instantiated and called as such:
73 * AllOne obj = new AllOne();
74 * obj.inc(key);
75 * obj.dec(key);
76 * string param_3 = obj.getMaxKey();
77 * string param_4 = obj.getMinKey();
78 */
79
************************

90. All O`one Data Structure(Python)


************************

1 # Time: O(1), per operation


2 # Space: O(k)
3
4 class Node(object):
5 """
6 double linked list node
7 """
8 def __init__(self, value, keys):
9 self.value = value
10 self.keys = keys
11 self.prev = None
12 self.next = None
13
14
15 class LinkedList(object):
16 def __init__(self):
17 self.head, self.tail = Node(0, set()), Node(0, set())
18 self.head.next, self.tail.prev = self.tail, self.head
19
20 def insert(self, pos, node):
21 node.prev, node.next = pos.prev, pos
22 pos.prev.next, pos.prev = node, node
23 return node
24
25 def erase(self, node):
26 node.prev.next, node.next.prev = node.next, node.prev
27 del node
28
29 def empty(self):
30 return self.head.next is self.tail
31
32 def begin(self):
33 return self.head.next
34
35 def end(self):
36 return self.tail
37
38 def front(self):
39 return self.head.next
40
41 def back(self):
42 return self.tail.prev
43
44
45 class AllOne(object):
46
47 def __init__(self):
48 """
49 Initialize your data structure here.
50 """
51 self.bucket_of_key = {}
52 self.buckets = LinkedList()
53
54 def inc(self, key):
55 """
56 Inserts a new key with value 1. Or increments an existing key by 1.
57 :type key: str
58 :rtype: void
59 """
60 if key not in self.bucket_of_key:
61 self.bucket_of_key[key] = self.buckets.insert(self.buckets.begin(), Node(0, set([key])))
62
63 bucket, next_bucket = self.bucket_of_key[key], self.bucket_of_key[key].next
64 if next_bucket is self.buckets.end() or next_bucket.value > bucket.value+1:
65 next_bucket = self.buckets.insert(next_bucket, Node(bucket.value+1, set()))
66 next_bucket.keys.add(key)
67 self.bucket_of_key[key] = next_bucket
68
69 bucket.keys.remove(key)
70 if not bucket.keys:
71 self.buckets.erase(bucket)
72
73 def dec(self, key):
74 """
75 Decrements an existing key by 1. If Key's value is 1, remove it from the data structure.
76 :type key: str
77 :rtype: void
78 """
79 if key not in self.bucket_of_key:
80 return
81
82 bucket, prev_bucket = self.bucket_of_key[key], self.bucket_of_key[key].prev
83 self.bucket_of_key.pop(key, None)
84 if bucket.value > 1:
85 if bucket is self.buckets.begin() or prev_bucket.value < bucket.value-1:
86 prev_bucket = self.buckets.insert(bucket, Node(bucket.value-1, set()))
87 prev_bucket.keys.add(key)
88 self.bucket_of_key[key] = prev_bucket
89
90 bucket.keys.remove(key)
91 if not bucket.keys:
92 self.buckets.erase(bucket)
93
94 def getMaxKey(self):
95 """
96 Returns one of the keys with maximal value.
97 :rtype: str
98 """
99 if self.buckets.empty():
100 return ""
101 return iter(self.buckets.back().keys).next()
102
103 def getMinKey(self):
104 """
105 Returns one of the keys with Minimal value.
106 :rtype: str
107 """
108 if self.buckets.empty():
109 return ""
110 return iter(self.buckets.front().keys).next()
111
**************************************

91. K-th Smallest in Lexicographical Order


**************************************

Given two integers n and k , return the k th lexicographically smallest integer in the range [1, n].

Example 1:

Input: n = 13, k = 2
Output: 10
Explanation: The lexicographical order is [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9], so the second smallest number is 10.

Example 2:

Input: n = 1, k = 1
Output: 1

Constraints:

1 <= k <= n <= 10 9


**************************************

91. K-th Smallest in Lexicographical Order(C++)


**************************************

1 // Time: O(logn)
2 // Space: O(logn)
3
4 class Solution {
5 public:
6 int findKthNumber(int n, int k) {
7 int result = 0;
8
9 vector cnts(10);
10 for (int i = 1; i <= 9; ++i) {
11 cnts[i] = cnts[i - 1] * 10 + 1;
12 }
13
14 vector nums;
15 for (int i = n; i > 0; i /= 10) {
16 nums.emplace_back(i % 10);
17 }
18 int total = n;
19 int target = 0;
20 for (int i = nums.size() - 1; i >= 0 && k; --i) {
21 target = target * 10 + nums[i];
22 const auto start = i == nums.size() - 1 ? 1 : 0;
23 for (int j = start; j <= 9; ++j) {
24 const auto candidate = result * 10 + j;
25 int num;
26 if (candidate < target) {
27 num = cnts[i + 1];
28 } else if (candidate > target) {
29 num = cnts[i];
30 } else {
31 num = total - cnts[i + 1] * (j - start) - cnts[i] * (9 - j);
32 }
33 if (k > num) {
34 k -= num;
35 } else {
36 result = candidate;
37 --k;
38 total = num - 1;
39 break;
40 }
41 }
42 }
43 return result;
44 }
45 };
46
47 // Time: O(logn * logn)
48 // Space: O(logn)
49 class Solution2 {
50 public:
51 int findKthNumber(int n, int k) {
52 int result = 0;
53 int index = 0;
54 findKthNumberHelper(n, k, 0, &index, &result);
55 return result;
56 }
57
58 private:
59 bool findKthNumberHelper(int n, int k, int cur, int *index, int *result) {
60 if (cur) {
61 ++(*index);
62 if (*index == k) {
63 *result = cur;
64 return true;
65 }
66 }
67 for (int i = (cur == 0 ? 1 : 0); i <= 9; ++i, cur /= 10) {
68 cur = cur * 10 + i;
69 int cnt = count(n, cur);
70 if (k > cnt + *index) {
71 *index += cnt;
72 continue;
73 }
74 if (cur <= n && findKthNumberHelper(n, k, cur, index, result)) {
75 return true;
76 }
77 }
78 return false;
79 }
80
81 int count(int n, long long prefix) { // Time: O(logn)
82 int result = 0;
83 int number = 1;
84 while (prefix <= n) {
85 result += number;
86 prefix *= 10;
87 number *= 10;
88 }
89 result -= max(number / 10 - (n - prefix / 10 + 1), static_cast(0));
90 return result;
91 }
92 };
**************************************

91. K-th Smallest in Lexicographical Order(Python)


**************************************

1 # Time: O(logn)
2 # Space: O(logn)
3
4 class Solution(object):
5 def findKthNumber(self, n, k):
6 """
7 :type n: int
8 :type k: int
9 :rtype: int
10 """
11 result = 0
12
13 cnts = [0] * 10
14 for i in xrange(1, 10):
15 cnts[i] = cnts[i - 1] * 10 + 1
16
17 nums = []
18 i = n
19 while i:
20 nums.append(i % 10)
21 i /= 10
22
23 total, target = n, 0
24 i = len(nums) - 1
25 while i >= 0 and k > 0:
26 target = target*10 + nums[i]
27 start = int(i == len(nums)-1)
28 for j in xrange(start, 10):
29 candidate = result*10 + j
30 if candidate < target:
31 num = cnts[i+1]
32 elif candidate > target:
33 num = cnts[i]
34 else:
35 num = total - cnts[i + 1]*(j-start) - cnts[i]*(9-j)
36 if k > num:
37 k -= num
38 else:
39 result = candidate
40 k -= 1
41 total = num-1
42 break
43 i -= 1
44
45 return result
46
47
48 # Time: O(logn * logn)
49 # Space: O(logn)
50 class Solution2(object):
51 def findKthNumber(self, n, k):
52 """
53 :type n: int
54 :type k: int
55 :rtype: int
56 """
57 def count(n, prefix):
58 result, number = 0, 1
59 while prefix <= n:
60 result += number
61 prefix *= 10
62 number *= 10
63 result -= max(number/10 - (n - prefix/10 + 1), 0)
64 return result
65
66 def findKthNumberHelper(n, k, cur, index):
67 if cur:
68 index += 1
69 if index == k:
70 return (cur, index)
71
72 i = int(cur == 0)
73 while i <= 9:
74 cur = cur * 10 + i
75 cnt = count(n, cur)
76 if k > cnt + index:
77 index += cnt
78 elif cur <= n:
79 result = findKthNumberHelper(n, k, cur, index)
80 if result[0]:
81 return result
82 i += 1
83 cur /= 10
84 return (0, index)
85
86 return findKthNumberHelper(n, k, 0, 0)[0]
87
**********************************

92. Arithmetic Slices II - Subsequence


**********************************

Given an integer array nums, return the number of all the arithmetic subsequences of nums.

A sequence of numbers is called arithmetic if it consists ofat least three elements and if the difference between any two
consecutive elements is the same.

For example, [1, 3, 5, 7, 9] , [7, 7, 7, 7] , and [3, -1, -5, -9] are arithmetic sequences.
For example, [1, 1, 2, 5, 7] is not an arithmetic sequence.

A subsequence of an array is a sequence that can be formed by removing some elements (possibly none) of the array.

For example, [2,5,10] is a subsequence of [1,2,1,2,4,1,5,10].

The answer is guaranteed to fit in 32-bit integer.

Example 1:

Input: nums = [2,4,6,8,10]


Output: 7
Explanation: All arithmetic subsequence slices are:
[2,4,6]
[4,6,8]
[6,8,10]
[2,4,6,8]
[4,6,8,10]
[2,4,6,8,10]
[2,6,10]

Example 2:

Input: nums = [7,7,7,7,7]


Output: 16
Explanation: Any subsequence of this array is arithmetic.

Constraints:

1 <= nums.length <= 1000


-231 <= nums[i] <= 2 31 - 1
**********************************

92. Arithmetic Slices II - Subsequence(C++)


**********************************

1 // Time: O(n^2)
2 // Space: O(n * d)
3
4 class Solution {
5 public:
6 int numberOfArithmeticSlices(vector& A) {
7 int result = 0;
8 vector> dp(A.size());
9 for (int i = 1; i < A.size(); ++i) {
10 for (int j = 0; j < i; ++j) {
11 const auto diff = static_cast(A[i]) - A[j];
12 ++dp[i][diff];
13 if (dp[j].count(diff)) {
14 dp[i][diff] += dp[j][diff];
15 result += dp[j][diff];
16 }
17 }
18 }
19 return result;
20 }
21 };
**********************************

92. Arithmetic Slices II - Subsequence(Python)


**********************************

1 # Time: O(n^2)
2 # Space: O(n * d)
3
4 import collections
5
6
7 class Solution(object):
8 def numberOfArithmeticSlices(self, A):
9 """
10 :type A: List[int]
11 :rtype: int
12 """
13 result = 0
14 dp = [collections.defaultdict(int) for i in xrange(len(A))]
15 for i in xrange(1, len(A)):
16 for j in xrange(i):
17 diff = A[i]-A[j]
18 dp[i][diff] += 1
19 if diff in dp[j]:
20 dp[i][diff] += dp[j][diff]
21 result += dp[j][diff]
22 return result
23
*********

93. LFU Cache


*********

Design and implement a data structure for a Least Frequently Used (LFU) cache.

Implement the LFUCache class:

LFUCache(int capacity) Initializes the object with the capacity of the data structure.
int get(int key) Gets the value of the key if the key exists in the cache. Otherwise, returns -1.
void put(int key, int value) Update the value of the key if present, or inserts the key if not already present. When the cache
reaches its capacity, it should invalidate and remove the least frequently used key before inserting a new item. For this
problem, when there is a tie (i.e., two or more keys with the same frequency), theleast recently used key would be
invalidated.

To determine the least frequently used key, a use counter is maintained for each key in the cache. The key with the
smallest use counter is the least frequently used key.

When a key is first inserted into the cache, its use counter is set to 1 (due to the put operation). The use counter for a key in
the cache is incremented either a get or put operation is called on it.

The functions get and put must each run in O(1) average time complexity.

Example 1:

Input
["LFUCache", "put", "put", "get", "put", "get", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [3], [4, 4], [1], [3], [4]]
Output
[null, null, null, 1, null, -1, 3, null, -1, 3, 4]

Explanation
// cnt(x) = the use counter for key x
// cache=[] will show the last used order for tiebreakers (leftmost element is most recent)
LFUCache lfu = new LFUCache(2);
lfu.put(1, 1); // cache=[1,_], cnt(1)=1
lfu.put(2, 2); // cache=[2,1], cnt(2)=1, cnt(1)=1
lfu.get(1); // return 1
// cache=[1,2], cnt(2)=1, cnt(1)=2
lfu.put(3, 3); // 2 is the LFU key because cnt(2)=1 is the smallest, invalidate 2.
// cache=[3,1], cnt(3)=1, cnt(1)=2
lfu.get(2); // return -1 (not found)
lfu.get(3); // return 3
// cache=[3,1], cnt(3)=2, cnt(1)=2
lfu.put(4, 4); // Both 1 and 3 have the same cnt, but 1 is LRU, invalidate 1.
// cache=[4,3], cnt(4)=1, cnt(3)=2
lfu.get(1); // return -1 (not found)
lfu.get(3); // return 3
// cache=[3,4], cnt(4)=1, cnt(3)=3
lfu.get(4); // return 4
// cache=[3,4], cnt(4)=2, cnt(3)=3

Constraints:

0 <= capacity <= 104


0 <= key <= 10 5
0 <= value <= 10 9
At most 2 * 105 calls will be made to get and put.
*********

93. LFU Cache(C++)


*********
1 // Time: O(1), per operation
2 // Space: O(k), k is the capacity of cache
3
4 class LFUCache {
5 public:
6 LFUCache(int capacity) : capa_(capacity), size_(0), min_freq_(numeric_limits::max()) {
7 }
8
9 int get(int key) {
10 if (!key_to_nodeit_.count(key)) {
11 return -1;
12 }
13 const auto value = std::get(*key_to_nodeit_[key]);
14 update(key, value);
15 return value;
16 }
17
18 void put(int key, int value) {
19 if (capa_ <= 0) {
20 return;
21 }
22
23 if (!key_to_nodeit_.count(key) && size_ == capa_) {
24 key_to_nodeit_.erase(std::get(freq_to_nodes_[min_freq_].front()));
25 freq_to_nodes_[min_freq_].pop_front();
26 if (freq_to_nodes_[min_freq_].empty()) {
27 freq_to_nodes_.erase(min_freq_);
28 }
29 --size_;
30 }
31 update(key, value);
32 }
33
34 private:
35 enum Data {KEY, VAL, FREQ};
36 int capa_;
37 int size_;
38 int min_freq_;
39 unordered_map>> freq_to_nodes_; // freq to list of {key, val, freq}
40 unordered_map>::iterator> key_to_nodeit_; // key to list iterator
41
42 void update(int key, int value) {
43 int freq = 0;
44 if (key_to_nodeit_.count(key)) {
45 auto old_node = *key_to_nodeit_[key];
46 freq = std::get(old_node);
47 freq_to_nodes_[freq].erase(key_to_nodeit_[key]);
48 if (freq_to_nodes_[freq].empty()) {
49 freq_to_nodes_.erase(freq);
50 if (min_freq_ == freq) {
51 ++min_freq_;
52 }
53 }
54 --size_;
55 }
56 min_freq_ = min(min_freq_, ++freq);
57 freq_to_nodes_[freq].emplace_back(key, value, freq);
58 key_to_nodeit_[key] = prev(freq_to_nodes_[freq].end());
59 ++size_;
60 }
61 };
62
63 /**
64 * Your LFUCache object will be instantiated and called as such:
65 * LFUCache obj = new LFUCache(capacity);
66 * int param_1 = obj.get(key);
67 * obj.put(key,value);
68 */
*********

93. LFU Cache(Python)


*********

1 # Time: O(1), per operation


2 # Space: O(k), k is the capacity of cache
3
4 import collections
5
6
7 # using OrderedDict
8 class LFUCache(object):
9
10 def __init__(self, capacity):
11 """
12 :type capacity: int
13 """
14 self.__capa = capacity
15 self.__size = 0
16 self.__min_freq = float("inf")
17 self.__freq_to_nodes = collections.defaultdict(collections.OrderedDict)
18 self.__key_to_freq = {}
19
20 def get(self, key):
21 """
22 :type key: int
23 :rtype: int
24 """
25 if key not in self.__key_to_freq:
26 return -1
27 value = self.__freq_to_nodes[self.__key_to_freq[key]][key]
28 self.__update(key, value)
29 return value
30
31 def put(self, key, value):
32 """
33 :type key: int
34 :type value: int
35 :rtype: void
36 """
37 if self.__capa <= 0:
38 return
39
40 if key not in self.__key_to_freq and self.__size == self.__capa:
41 del self.__key_to_freq[self.__freq_to_nodes[self.__min_freq].popitem(last=False)[0]]
42 if not self.__freq_to_nodes[self.__min_freq]:
43 del self.__freq_to_nodes[self.__min_freq]
44 self.__size -= 1
45 self.__update(key, value)
46
47 def __update(self, key, value):
48 freq = 0
49 if key in self.__key_to_freq:
50 freq = self.__key_to_freq[key]
51 del self.__freq_to_nodes[freq][key]
52 if not self.__freq_to_nodes[freq]:
53 del self.__freq_to_nodes[freq]
54 if self.__min_freq == freq:
55 self.__min_freq += 1
56 self.__size -= 1
57
58 freq += 1
59 self.__min_freq = min(self.__min_freq, freq)
60 self.__key_to_freq[key] = freq
61 self.__freq_to_nodes[freq][key] = value
62 self.__size += 1
63
64
65 # Time: O(1), per operation
66 # Space: O(k), k is the capacity of cache
67 import collections
68
69
70 class ListNode(object):
71 def __init__(self, key, value, freq):
72 self.key = key
73 self.val = value
74 self.freq = freq
75 self.next = None
76 self.prev = None
77
78
79 class LinkedList(object):
80 def __init__(self):
81 self.head = None
82 self.tail = None
83
84 def append(self, node):
85 node.next, node.prev = None, None # avoid dirty node
86 if self.head is None:
87 self.head = node
88 else:
89 self.tail.next = node
90 node.prev = self.tail
91 self.tail = node
92
93 def delete(self, node):
94 if node.prev:
95 node.prev.next = node.next
96 else:
97 self.head = node.next
98 if node.next:
99 node.next.prev = node.prev
100 else:
101 self.tail = node.prev
102 node.next, node.prev = None, None # make node clean
103
104
105 class LFUCache2(object):
106
107 def __init__(self, capacity):
108 """
109 :type capacity: int
110 """
111 self.__capa = capacity
112 self.__size = 0
113 self.__min_freq = float("inf")
114 self.__freq_to_nodes = collections.defaultdict(LinkedList)
115 self.__key_to_node = {}
116
117 def get(self, key):
118 """
119 :type key: int
120 :rtype: int
121 """
122 if key not in self.__key_to_node:
123 return -1
124 value = self.__key_to_node[key].val
125 self.__update(key, value)
126 return value
127
128 def put(self, key, value):
129 """
130 :type key: int
131 :type value: int
132 :rtype: void
133 """
134 if self.__capa <= 0:
135 return
135 return
136
137 if key not in self.__key_to_node and self.__size == self.__capa:
138 del self.__key_to_node[self.__freq_to_nodes[self.__min_freq].head.key]
139 self.__freq_to_nodes[self.__min_freq].delete(self.__freq_to_nodes[self.__min_freq].head)
140 if not self.__freq_to_nodes[self.__min_freq].head:
141 del self.__freq_to_nodes[self.__min_freq]
142 self.__size -= 1
143 self.__update(key, value)
144
145 def __update(self, key, value):
146 freq = 0
147 if key in self.__key_to_node:
148 old_node = self.__key_to_node[key]
149 freq = old_node.freq
150 self.__freq_to_nodes[freq].delete(old_node)
151 if not self.__freq_to_nodes[freq].head:
152 del self.__freq_to_nodes[freq]
153 if self.__min_freq == freq:
154 self.__min_freq += 1
155 self.__size -= 1
156
157 freq += 1
158 self.__min_freq = min(self.__min_freq, freq)
159 self.__key_to_node[key] = ListNode(key, value, freq)
160 self.__freq_to_nodes[freq].append(self.__key_to_node[key])
161 self.__size += 1
*************************

94. Optimal Account Balancing


*************************

You are given an array of transactionstransactions where transactions[i] = [from i, to i, amount i] indicates that the person with ID = from i
gave amounti $ to the person with ID = to i.

Return the minimum number of transactions required to settle the debt.

Example 1:

Input: transactions = [[0,1,10],[2,0,5]]


Output: 2
Explanation:
Person #0 gave person #1 $10.
Person #2 gave person #0 $5.
Two transactions are needed. One way to settle the debt is person #1 pays person #0 and #2 $5 each.

Example 2:

Input: transactions = [[0,1,10],[1,0,1],[1,2,5],[2,0,5]]


Output: 1
Explanation:
Person #0 gave person #1 $10.
Person #1 gave person #0 $1.
Person #1 gave person #2 $5.
Person #2 gave person #0 $5.
Therefore, person #1 only need to give person #0 $4, and all debt is settled.

Constraints:

1 <= transactions.length <= 8


transactions[i].length == 3
0 <= from i, to i <= 20
fromi != to i
1 <= amounti <= 100
*************************

94. Optimal Account Balancing(C++)


*************************

1 // Time: O(n * 2^n), n is the size of debts.


2 // Space: O(2^n)
3
4 class Solution {
5 public:
6 int minTransfers(vector>& transactions) {
7 unordered_map account;
8 for (const auto& transaction
9 : transactions) {
10 account[transaction[0]] += transaction[2];
11 account[transaction[1]] -= transaction[2];
12 }
13 vector debts;
14 for (const auto& kvp: account) {
15 if (kvp.second) {
16 debts.emplace_back(kvp.second);
17 }
18 }
19
20 vector dp(1 << debts.size());
21 vector sums(1 << debts.size());
22 for (int i = 0; i < dp.size(); ++i) {
23 for (int j = 0; j < debts.size(); ++j) {
24 if ((i & (1 << j)) == 0) {
25 auto nxt = i | (1 << j);
26 sums[nxt] = sums[i] + debts[j];
27 if (sums[nxt] == 0) {
28 dp[nxt] = max(dp[nxt], dp[i] + 1);
29 } else {
30 dp[nxt] = max(dp[nxt], dp[i]);
31 }
32 }
33 }
34 }
35 return debts.size() - dp.back();
36 }
37 };
*************************

94. Optimal Account Balancing(Python)


*************************

1 # Time: O(n * 2^n), n is the size of the debt.


2 # Space: O(2^n)
3
4 import collections
5
6
7 class Solution(object):
8 def minTransfers(self, transactions):
9 """
10 :type transactions: List[List[int]]
11 :rtype: int
12 """
13 accounts = collections.defaultdict(int)
14 for transaction in transactions:
15 accounts[transaction[0]] += transaction[2]
16 accounts[transaction[1]] -= transaction[2]
17
18 debts = [account for account in accounts.values() if account]
19
20 dp = [0]*(2**len(debts))
21 sums = [0]*(2**len(debts))
22 for i in xrange(len(dp)):
23 for j in xrange(len(debts)):
24 if (i & (1<
*********************

95. Count The Repetitions


*********************

We define str = [s, n] as the string str which consists of the string s concatenated n times.

For example, str == ["abc", 3] =="abcabcabc" .

We define that string s1 can be obtained from string s2 if we can remove some characters from s2 such that it becomes s1.

For example, s1 = "abc" can be obtained from s2 = "ab dbec" based on our definition by removing the bolded underlined
characters.

You are given two strings s1 and s2 and two integers n1 and n2. You have the two strings str1 = [s1, n1] and str2 = [s2, n2] .

Return the maximum integer m such that str = [str2, m] can be obtained from str1.

Example 1:

Input: s1 = "acb", n1 = 4, s2 = "ab", n2 = 2


Output: 2

Example 2:

Input: s1 = "acb", n1 = 1, s2 = "acb", n2 = 1


Output: 1

Constraints:

1 <= s1.length, s2.length <= 100


s1 and s2 consist of lowercase English letters.
1 <= n1, n2 <= 10 6
*********************

95. Count The Repetitions(C++)


*********************

1 // Time: O(s1 * min(s2, n1))


2 // Space: O(s2)
3
4 class Solution {
5 public:
6 int getMaxRepetitions(string s1, int n1, string s2, int n2) {
7 vector repeatCount(s2.size() + 1, 0);
8 unordered_map lookup;
9 int j = 0, count = 0;
10 for (int k = 1; k <= n1; ++k) {
11 for (int i = 0; i < s1.size(); ++i) {
12 if (s1[i] == s2[j]) {
13 j = (j + 1) % s2.size();
14 count += (j == 0);
15 }
16 }
17
18 if (lookup.find(j) != lookup.end()) { // cyclic
19 int i = lookup[j];
20 int prefixCount = repeatCount[i];
21 int patternCount = (count - repeatCount[i]) * ((n1 - i) / (k - i));
22 int suffixCount = repeatCount[i + (n1 - i) % (k - i)] - repeatCount[i];
23 return (prefixCount + patternCount + suffixCount) / n2;
24 }
25 lookup[j] = k;
26 repeatCount[k] = count;
27 }
28 return repeatCount[n1] / n2; // not cyclic iff n1 <= s2
29 }
30 };
*********************

95. Count The Repetitions(Python)


*********************

1 # Time: O(s1 * min(s2, n1))


2 # Space: O(s2)
3
4 class Solution(object):
5 def getMaxRepetitions(self, s1, n1, s2, n2):
6 """
7 :type s1: str
8 :type n1: int
9 :type s2: str
10 :type n2: int
11 :rtype: int
12 """
13 repeat_count = [0] * (len(s2)+1)
14 lookup = {}
15 j, count = 0, 0
16 for k in xrange(1, n1+1):
17 for i in xrange(len(s1)):
18 if s1[i] == s2[j]:
19 j = (j + 1) % len(s2)
20 count += (j == 0)
21
22 if j in lookup: # cyclic
23 i = lookup[j]
24 prefix_count = repeat_count[i]
25 pattern_count = (count - repeat_count[i]) * ((n1 - i) // (k - i))
26 suffix_count = repeat_count[i + (n1 - i) % (k - i)] - repeat_count[i]
27 return (prefix_count + pattern_count + suffix_count) / n2
28 lookup[j] = k
29 repeat_count[k] = count
30
31 return repeat_count[n1] / n2 # not cyclic iff n1 <= s2
32
******************

96. Robot Room Cleaner


******************

You are controlling a robot that is located somewhere in a room. The room is modeled as anm x n binary grid where 0
represents a wall and 1 represents an empty slot.

The robot starts at an unknown location in the root that is guaranteed to be empty, and you do not have access to the grid,
but you can move the robot using the given API Robot.

You are tasked to use the robot to clean the entire room (i.e., clean every empty cell in the room). The robot with the four
given APIs can move forward, turn left, or turn right. Each turn is 90 degrees.

When the robot tries to move into a wall cell, its bumper sensor detects the obstacle, and it stays on the current cell.

Design an algorithm to clean the entire room using the following APIs:

interface Robot {
// returns true if next cell is open and robot moves into the cell.
// returns false if next cell is obstacle and robot stays on the current cell.
boolean move();

// Robot will stay on the same cell after calling turnLeft/turnRight.


// Each turn will be 90 degrees.
void turnLeft();
void turnRight();

// Clean the current cell.


void clean();
}

Note that the initial direction of the robot will be facing up. You can assume all four edges of the grid are all surrounded by a
wall.

Custom testing:

The input is only given to initialize the room and the robot's position internally. You must solve this problem "blindfolded". In
other words, you must control the robot using only the four mentioned APIs without knowing the room layout and the initial
robot's position.

Example 1:
Input: room = [[1,1,1,1,1,0,1,1],[1,1,1,1,1,0,1,1],[1,0,1,1,1,1,1,1],[0,0,0,1,0,0,0,0],[1,1,1,1,1,1,1,1]], row = 1, col = 3
Output: Robot cleaned all rooms.
Explanation: All grids in the room are marked by either 0 or 1.
0 means the cell is blocked, while 1 means the cell is accessible.
The robot initially starts at the position of row=1, col=3.
From the top left corner, its position is one row below and three columns right.

Example 2:

Input: room = [[1]], row = 0, col = 0


Output: Robot cleaned all rooms.

Constraints:

m == room.length
n == room[i].length
1 <= m <= 100
1 <= n <= 200
room[i][j] is either 0 or 1.
0 <= row < m
0 <= col < n
room[row][col] == 1
All the empty cells can be visited from the starting position.
******************

96. Robot Room Cleaner(C++)


******************
1 // Time: O(n), n is the number of cells
2 // Space: O(n)
3
4 /**
5 * // This is the robot's control interface.
6 * // You should not implement it, or speculate about its implementation
7 * class Robot {
8 * public:
9 * // Returns true if the cell in front is open and robot moves into the cell.
10 * // Returns false if the cell in front is blocked and robot stays in the current cell.
11 * bool move();
12 *
13 * // Robot will stay in the same cell after calling turnLeft/turnRight.
14 * // Each turn will be 90 degrees.
15 * void turnLeft();
16 * void turnRight();
17 *
18 * // Clean the current cell.
19 * void clean();
20 * };
21 */
22 class Solution {
23 public:
24 template
25 struct PairHash {
26 size_t operator()(const pair& p) const {
27 size_t seed = 0;
28 seed ^= std::hash{}(p.first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
29 seed ^= std::hash{}(p.second) + 0x9e3779b9 + (seed<<6) + (seed>>2);
30 return seed;
31 }
32 };
33
34 void cleanRoom(Robot& robot) {
35 unordered_set, PairHash> lookup;
36 dfs({0, 0}, robot, 0, &lookup);
37 }
38
39 private:
40 void dfs(const pair& pos, Robot& robot, int dir,
41 unordered_set, PairHash> *lookup) {
42 static const vector> directions{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
43
44 robot.clean();
45 for (int i = 0; i < directions.size(); ++i, dir = (dir + 1) % directions.size(), robot.turnRight()) {
46 const auto& new_pos = pair(pos.first + directions[dir].first,
47 pos.second + directions[dir].second);
48 if (lookup->count(new_pos)) {
49 continue;
50 }
51 lookup->emplace(new_pos);
52 if (!robot.move()) {
53 continue;
54 }
55 dfs(new_pos, robot, dir, lookup);
56 goBack(robot);
57 }
58 }
59
60 void goBack(Robot& robot) {
61 robot.turnLeft();
62 robot.turnLeft();
63 robot.move();
64 robot.turnRight();
65 robot.turnRight();
66 }
67 };
******************

96. Robot Room Cleaner(Python)


******************

1 # Time: O(n), n is the number of cells


2 # Space: O(n)
3
4 class Solution(object):
5 def cleanRoom(self, robot):
6 """
7 :type robot: Robot
8 :rtype: None
9 """
10 directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
11
12 def goBack(robot):
13 robot.turnLeft()
14 robot.turnLeft()
15 robot.move()
16 robot.turnRight()
17 robot.turnRight()
18
19 def dfs(pos, robot, d, lookup):
20 robot.clean()
21 for _ in directions:
22 new_pos = (pos[0]+directions[d][0],
23 pos[1]+directions[d][1])
24 if new_pos not in lookup:
25 lookup.add(new_pos)
26 if robot.move():
27 dfs(new_pos, robot, d, lookup)
28 goBack(robot)
29 robot.turnRight()
30 d = (d+1) % len(directions)
31
32 dfs((0, 0), robot, 0, set())
************

97. The Maze III


************

There is a ball in a maze with empty spaces (represented as 0) and walls (represented as 1). The ball can go through the
empty spaces by rolling up, down, left or right, but it won't stop rolling until hitting a wall. When the ball stops, it could
choose the next direction. There is also a hole in this maze. The ball will drop into the hole if it rolls onto the hole.

Given the m x n maze, the ball's position ball and the hole's position hole , where ball = [ball row, ball col] and hole = [hole row, hole col],
return a string instructions of all the instructions that the ball should follow to drop in the hole with theshortest distance
possible. If there are multiple valid instructions, return thelexicographically minimum one. If the ball can't drop in the hole,
return "impossible" .

If there is a way for the ball to drop in the hole, the answerinstructions should contain the characters 'u' (i.e., up), 'd' (i.e.,
down), 'l' (i.e., left), and 'r' (i.e., right).

The distance is the number of empty spaces traveled by the ball from the start position (excluded) to the destination
(included).

You may assume that the borders of the maze are all walls (see examples).

Example 1:

Input: maze = [[0,0,0,0,0],[1,1,0,0,1],[0,0,0,0,0],[0,1,0,0,1],[0,1,0,0,0]], ball = [4,3], hole = [0,1]


Output: "lul"
Explanation: There are two shortest ways for the ball to drop into the hole.
The first way is left -> up -> left, represented by "lul".
The second way is up -> left, represented by 'ul'.
Both ways have shortest distance 6, but the first way is lexicographically smaller because 'l' < 'u'. So the output is "lul".
Example 2:

Input: maze = [[0,0,0,0,0],[1,1,0,0,1],[0,0,0,0,0],[0,1,0,0,1],[0,1,0,0,0]], ball = [4,3], hole = [3,0]


Output: "impossible"
Explanation: The ball cannot reach the hole.

Example 3:

Input: maze = [[0,0,0,0,0,0,0],[0,0,1,0,0,1,0],[0,0,0,0,1,0,0],[0,0,0,0,0,0,1]], ball = [0,4], hole = [3,5]


Output: "dldr"

Constraints:

m == maze.length
n == maze[i].length
1 <= m, n <= 100
maze[i][j] is 0 or 1.
ball.length == 2
hole.length == 2
0 <= ballrow, hole row <= m
0 <= ballcol, hole col <= n
Both the ball and the hole exist in an empty space, and they will not be in the same position initially.
The maze contains at least 2 empty spaces.
************

97. The Maze III(C++)


************

1 // Time: O(max(r, c) * wlogw)


2 // Space: O(w^2)
3
4 class Solution {
5 public:
6 string findShortestWay(vector>& maze, vector& ball, vector& hole) {
7 static const unordered_map> dirs = {{"u", {-1, 0}}, {"r", {0, 1}},
8 {"l", {0, -1}}, {"d", {1, 0}}};
9 priority_queue, greater> heap;
10 unordered_set visited;
11 heap.emplace(0, make_pair("", ball));
12
13 while (!heap.empty()) {
14 int dist = 0;
15 string path;
16 vector node;
17 tie(dist, lvalue(tie(path, node))) = heap.top();
18 heap.pop();
19 if (visited.count(hash(maze, node))) {
20 continue;
21 }
22
23 if (node[0] == hole[0] &&
24 node[1] == hole[1]) {
25 return path;
26 }
27
28 visited.emplace(hash(maze, node));
29 for (const auto& kvp : dirs) {
30 int neighbor_dist = 0;
31 string dir;
32 vector neighbor;
33 tie(neighbor_dist, lvalue(tie(dir, neighbor))) = findNeighbor(maze, hole, node, kvp);
34 heap.emplace(dist + neighbor_dist, make_pair(path + dir, neighbor));
35 }
36 }
37
38 return "impossible";
39 }
40
41 private:
42 using node = pair>>;
43
44 node findNeighbor(const vector>& maze, const vector& hole,
45 const vector& node, const pair>& kvp) {
46 string dir;
47 vector vec;
48 tie(dir, vec) = kvp;
49 vector cur_node = node;
50 int dist = 0;
51
52 while (0 <= cur_node[0] + vec[0] && cur_node[0] + vec[0] < maze.size() &&
53 0 <= cur_node[1] + vec[1] && cur_node[1] + vec[1] < maze[0].size() &&
54 !maze[cur_node[0] + vec[0]][cur_node[1] + vec[1]]) {
55
56 cur_node[0] += vec[0];
57 cur_node[1] += vec[1];
58 ++dist;
59 if (cur_node[0] == hole[0] &&
60 cur_node[1] == hole[1]) {
61 break;
62 }
63 }
64 return {dist, {dir, cur_node}};
65 }
66
67 int hash(const vector>& maze, const vector& node) {
68 return node[0] * maze[0].size() + node[1];
69 }
70
71 template
72 constexpr T &lvalue(T &&v) {
73 return v;
74 }
75 };
************

97. The Maze III(Python)


************

1 # Time: O(max(r, c) * wlogw)


2 # Space: O(w^2)
3
4 import heapq
5
6
7 class Solution(object):
8 def findShortestWay(self, maze, ball, hole):
9 """
10 :type maze: List[List[int]]
11 :type ball: List[int]
12 :type hole: List[int]
13 :rtype: str
14 """
15 ball, hole = tuple(ball), tuple(hole)
16 dirs = {'u' : (-1, 0), 'r' : (0, 1), 'l' : (0, -1), 'd': (1, 0)}
17
18 def neighbors(maze, node):
19 for dir, vec in dirs.iteritems():
20 cur_node, dist = list(node), 0
21 while 0 <= cur_node[0]+vec[0] < len(maze) and \
22 0 <= cur_node[1]+vec[1] < len(maze[0]) and \
23 not maze[cur_node[0]+vec[0]][cur_node[1]+vec[1]]:
24 cur_node[0] += vec[0]
25 cur_node[1] += vec[1]
26 dist += 1
27 if tuple(cur_node) == hole:
28 break
29 yield tuple(cur_node), dir, dist
30
31 heap = [(0, '', ball)]
32 visited = set()
33 while heap:
34 dist, path, node = heapq.heappop(heap)
35 if node in visited: continue
36 if node == hole: return path
37 visited.add(node)
38 for neighbor, dir, neighbor_dist in neighbors(maze, node):
39 heapq.heappush(heap, (dist+neighbor_dist, path+dir, neighbor))
40
41 return "impossible"
42
*************

98. Freedom Trail


*************

In the video game Fallout 4, the quest"Road to Freedom" requires players to reach a metal dial called the "Freedom Trail
Ring" and use the dial to spell a specific keyword to open the door.

Given a string ring that represents the code engraved on the outer ring and another stringkey that represents the keyword
that needs to be spelled, return the minimum number of steps to spell all the characters in the keyword.

Initially, the first character of the ring is aligned at the"12:00" direction. You should spell all the characters inkey one by one
by rotating ring clockwise or anticlockwise to make each character of the string key aligned at the"12:00" direction and then
by pressing the center button.

At the stage of rotating the ring to spell the key characterkey[i]:

1. You can rotate the ring clockwise or anticlockwise by one place, which counts asone step. The final purpose of the
rotation is to align one of ring's characters at the "12:00" direction, where this character must equal key[i].
2. If the character key[i] has been aligned at the "12:00" direction, press the center button to spell, which also counts asone
step. After the pressing, you could begin to spell the next character in the key (next stage). Otherwise, you have
finished all the spelling.

Example 1:

Input: ring = "godding", key = "gd"


Output: 4
Explanation:
For the first key character 'g', since it is already in place, we just need 1 step to spell this character.
For the second key character 'd', we need to rotate the ring "godding" anticlockwise by two steps to make it become "ddinggo".
Also, we need 1 more step for spelling.
So the final output is 4.

Example 2:
Input: ring = "godding", key = "godding"
Output: 13

Constraints:

1 <= ring.length, key.length <= 100


ring and key consist of only lower case English letters.
It is guaranteed that key could always be spelled by rotating ring.
*************

98. Freedom Trail(C++)


*************

1 // Time: O(k) ~ O(k * r^2)


2 // Space: O(r)
3
4 class Solution {
5 public:
6 int findRotateSteps(string ring, string key) {
7 unordered_map> lookup;
8 for (int i = 0; i < ring.size(); ++i) {
9 lookup[ring[i]].emplace_back(i);
10 }
11
12 vector> dp(2, vector (ring.size()));
13 for (int i = 1; i <= key.size(); ++i) {
14 fill(dp[i % 2].begin(), dp[i % 2].end(), numeric_limits::max());
15 for (const auto& j : lookup[key[i - 1]]) {
16 for (const auto& k : (i > 1 ? lookup[key[i - 2]] : vector(1))) {
17 int min_dist = min((k + ring.size() - j) % ring.size(),
18 (j + ring.size() - k) % ring.size()) +
19 dp[(i - 1) % 2][k];
20 dp[i % 2][j] = min(dp[i % 2][j], min_dist);
21 }
22 }
23 }
24 return *min_element(dp[key.size() % 2].begin(), dp[key.size() % 2].end()) + key.size();
25 }
26 };
*************

98. Freedom Trail(Python)


*************

1 # Time: O(k) ~ O(k * r^2)


2 # Space: O(r)
3
4 import collections
5
6
7 class Solution(object):
8 def findRotateSteps(self, ring, key):
9 """
10 :type ring: str
11 :type key: str
12 :rtype: int
13 """
14 lookup = collections.defaultdict(list)
15 for i in xrange(len(ring)):
16 lookup[ring[i]].append(i)
17
18 dp = [[0] * len(ring) for _ in xrange(2)]
19 prev = [0]
20 for i in xrange(1, len(key)+1):
21 dp[i%2] = [float("inf")] * len(ring)
22 for j in lookup[key[i-1]]:
23 for k in prev:
24 dp[i%2][j] = min(dp[i%2][j],
25 min((k+len(ring)-j) % len(ring), \
26 (j+len(ring)-k) % len(ring)) + \
27 dp[(i-1) % 2][k])
28 prev = lookup[key[i-1]]
29 return min(dp[len(key)%2]) + len(key)
30
**********************

99. Super Washing Machines


**********************

You have n super washing machines on a line. Initially, each washing machine has some dresses or is empty.

For each move, you could choose any m (1 <= m <= n ) washing machines, and pass one dress of each washing machine to
one of its adjacent washing machines at the same time.

Given an integer array machines representing the number of dresses in each washing machine from left to right on the line,
return the minimum number of moves to make all the washing machines have the same number of dresses . If it is not
possible to do it, return -1.

Example 1:

Input: machines = [1,0,5]


Output: 3
Explanation:
1st move: 1 0 <-- 5 => 1 1 4
2nd move: 1 <-- 1 <-- 4 => 2 1 3
3rd move: 2 1 <-- 3 => 2 2 2

Example 2:

Input: machines = [0,3,0]


Output: 2
Explanation:
1st move: 0 <-- 3 0 => 1 2 0
2nd move: 1 2 --> 0 => 1 1 1

Example 3:

Input: machines = [0,2,0]


Output: -1
Explanation:
It's impossible to make all three washing machines have the same number of dresses.

Constraints:

n == machines.length
1 <= n <= 10 4
0 <= machines[i] <= 10 5
**********************

99. Super Washing Machines(C++)


**********************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int findMinMoves(vector& machines) {
7 int sum = accumulate(machines.begin(), machines.end(), 0);
8 if (sum % machines.size() != 0) {
9 return -1;
10 }
11
12 int result = 0, target = sum / machines.size(), curr = 0;
13 for (const auto& n : machines) {
14 curr += n - target;
15 result = max(result, max(n - target, abs(curr)));
16 }
17 return result;
18 }
19 };
**********************

99. Super Washing Machines(Python)


**********************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def findMinMoves(self, machines):
6 """
7 :type machines: List[int]
8 :rtype: int
9 """
10 total = sum(machines)
11 if total % len(machines): return -1
12
13 result, target, curr = 0, total / len(machines), 0
14 for n in machines:
15 curr += n - target
16 result = max(result, max(n - target, abs(curr)))
17 return result
18
*****************

100. Word Abbreviation


*****************

Given an array of distinct strings words, return the minimal possible abbreviations for every word.

The following are the rules for a string abbreviation:

1. Begin with the first character, and then the number of characters abbreviated, followed by the last character.
2. If there is any conflict and more than one word shares the same abbreviation, a longer prefix is used instead of only
the first character until making the map from word to abbreviation become unique. In other words, a final abbreviation
cannot map to more than one original word.
3. If the abbreviation does not make the word shorter, then keep it as the original.

Example 1:

Input: words = ["like","god","internal","me","internet","interval","intension","face","intrusion"]


Output: ["l2e","god","internal","me","i6t","interval","inte4n","f2e","intr4n"]

Example 2:

Input: words = ["aa","aaa"]


Output: ["aa","aaa"]

Constraints:

1 <= words.length <= 400


2 <= words[i].length <= 400
words[i] consists of lowercase English letters.
All the strings of words are unique.
*****************

100. Word Abbreviation(C++)


*****************

1 // Time: O(n * l) ~ O(n^2 * l^2)


2 // Space: O(n * l)
3
4 class Solution {
5 public:
6 vector wordsAbbreviation(vector& dict) {
7 unordered_map> abbr_to_word;
8 unordered_map word_to_abbr;
9
10 for (const auto& word : dict) {
11 const auto prefix = word.substr(0, 1);
12 abbr_to_word[toAbbr(prefix, word)].emplace(word);
13 }
14
15 for (const auto& kvp : abbr_to_word) {
16 if (kvp.second.size() > 1) {
17 for (const auto& word : kvp.second) {
18 for (int i = 2; i < word.length(); ++i) {
19 const auto prefix = word.substr(0, i);
20 if (isUnique(prefix, kvp.second)) {
21 word_to_abbr[word] = toAbbr(prefix, word);
22 break;
23 }
24 }
25 }
26 } else {
27 word_to_abbr[*kvp.second.begin()] = kvp.first;
28 }
29 }
30
31 vector result;
32 for (const auto& word : dict) {
33 result.emplace_back(word_to_abbr[word]);
34 }
35 return result;
36 }
37
38 private:
39 bool isUnique(const string& prefix, const unordered_set& words) {
40 return 1 == count_if(words.begin(), words.end(),
41 [&prefix](const string& word) {
42 return !word.compare(0, prefix.length(), prefix);
43 });
44 }
45
46 string toAbbr(const string& prefix, const string& word) {
47 string abbr = prefix;
48 abbr += to_string(word.length() - 1 - prefix.length());
49 abbr += word.back();
50 return abbr.length() < word.length() ? abbr : word;
51 }
52 };
*****************

100. Word Abbreviation(Python)


*****************

1 # Time: O(n * l) ~ O(n^2 * l^2)


2 # Space: O(n * l)
3
4 import collections
5
6
7 class Solution(object):
8 def wordsAbbreviation(self, dict):
9 """
10 :type dict: List[str]
11 :rtype: List[str]
12 """
13 def isUnique(prefix, words):
14 return sum(word.startswith(prefix) for word in words) == 1
15
16 def toAbbr(prefix, word):
17 abbr = prefix + str(len(word) - 1 - len(prefix)) + word[-1]
18 return abbr if len(abbr) < len(word) else word
19
20 abbr_to_word = collections.defaultdict(set)
21 word_to_abbr = {}
22
23 for word in dict:
24 prefix = word[:1]
25 abbr_to_word[toAbbr(prefix, word)].add(word)
26
27 for abbr, conflicts in abbr_to_word.iteritems():
28 if len(conflicts) > 1:
29 for word in conflicts:
30 for i in xrange(2, len(word)):
31 prefix = word[:i]
32 if isUnique(prefix, conflicts):
33 word_to_abbr[word] = toAbbr(prefix, word)
34 break
35 else:
36 word_to_abbr[conflicts.pop()] = abbr
37
38 return [word_to_abbr[word] for word in dict]
39
************

101. Remove Boxes


************

You are given several boxes with different colors represented by different positive numbers.

You may experience several rounds to remove boxes until there is no box left. Each time you can choose some continuous
boxes with the same color (i.e., composed of k boxes, k >= 1 ), remove them and get k * k points.

Return the maximum points you can get.

Example 1:

Input: boxes = [1,3,2,2,2,3,4,3,1]


Output: 23
Explanation:
[1, 3, 2, 2, 2, 3, 4, 3, 1]
----> [1, 3, 3, 4, 3, 1] (3*3=9 points)
----> [1, 3, 3, 3, 1] (1*1=1 points)
----> [1, 1] (3*3=9 points)
----> [] (2*2=4 points)

Example 2:

Input: boxes = [1,1,1]


Output: 9

Example 3:

Input: boxes = [1]


Output: 1

Constraints:

1 <= boxes.length <= 100


1 <= boxes[i] <= 100
************

101. Remove Boxes(C++)


************

1 // Time: O(n^3) ~ O(n^4)


2 // Space: O(n^3)
3
4 class Solution {
5 public:
6 int removeBoxes(vector& boxes) {
7 int lookup[100][100][100] = {0};
8 return removeBoxesHelper(boxes, 0, boxes.size() - 1, 0, lookup);
9 }
10
11 private:
12 int removeBoxesHelper(const vector& boxes, int l, int r, int k, int lookup[100][100][100]) {
13 if (l > r) {
14 return 0;
15 }
16 if (lookup[l][r][k]) {
17 return lookup[l][r][k];
18 }
19
20 auto& result = lookup[l][r][k];
21 while (l < r && boxes[l + 1] == boxes[l]) {
22 ++l, ++k;
23 }
24 result = removeBoxesHelper(boxes, l + 1, r, 0, lookup) + (k + 1) * (k + 1);
25 for (int i = l + 1; i <= r; ++i) {
26 if (boxes[i] == boxes[l]) {
27 result = max(result,
28 removeBoxesHelper(boxes, l + 1, i - 1, 0, lookup) +
29 removeBoxesHelper(boxes, i, r, k + 1, lookup));
30 }
31 }
32 return result;
33 }
34 };
************

101. Remove Boxes(Python)


************

1 # Time: O(n^3) ~ O(n^4)


2 # Space: O(n^3)
3
4 class Solution(object):
5 def removeBoxes(self, boxes):
6 """
7 :type boxes: List[int]
8 :rtype: int
9 """
10 def dfs(boxes, l, r, k, lookup):
11 if l > r: return 0
12 if lookup[l][r][k]: return lookup[l][r][k]
13
14 ll, kk = l, k
15 while l < r and boxes[l+1] == boxes[l]:
16 l += 1
17 k += 1
18 result = dfs(boxes, l+1, r, 0, lookup) + (k+1) ** 2
19 for i in xrange(l+1, r+1):
20 if boxes[i] == boxes[l]:
21 result = max(result, dfs(boxes, l+1, i-1, 0, lookup) + dfs(boxes, i, r, k+1, lookup))
22 lookup[ll][r][kk] = result
23 return result
24
25 lookup = [[[0]*len(boxes) for _ in xrange(len(boxes)) ] for _ in xrange(len(boxes)) ]
26 return dfs(boxes, 0, len(boxes)-1, 0, lookup)
27
****************************

102. Student Attendance Record II


****************************

An attendance record for a student can be represented as a string where each character signifies whether the student was
absent, late, or present on that day. The record only contains the following three characters:

'A' : Absent.
'L': Late.
'P' : Present.

Any student is eligible for an attendance award if they meet both of the following criteria:

The student was absent ('A') for strictly fewer than 2 days total.
The student was never late ('L') for 3 or more consecutive days.

Given an integer n, return the number of possible attendance records of length n that make a student eligible for an
attendance award. The answer may be very large, so return it modulo 109 + 7 .

Example 1:

Input: n = 2
Output: 8
Explanation: There are 8 records with length 2 that are eligible for an award:
"PP", "AP", "PA", "LP", "PL", "AL", "LA", "LL"
Only "AA" is not eligible because there are 2 absences (there need to be fewer than 2).

Example 2:

Input: n = 1
Output: 3

Example 3:

Input: n = 10101
Output: 183236316

Constraints:

1 <= n <= 10 5
****************************

102. Student Attendance Record II(C++)


****************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int checkRecord(int n) {
7 static const long long M = 1000000007;
8 long long a0l0 = 1, a0l1 = 0, a0l2 = 0, a1l0 = 0, a1l1 = 0, a1l2 = 0;
9 for (int i = 0; i <= n; ++i) {
10 auto new_a0l0 = (a0l0 + a0l1 + a0l2) % M;
11 a0l2 = a0l1;
12 a0l1 = a0l0;
13 a0l0 = new_a0l0;
14 auto new_a1l0 = (a0l0 + a1l0 + a1l1 + a1l2) % M;
15 a1l2 = a1l1;
16 a1l1 = a1l0;
17 a1l0 = new_a1l0;
18 }
19 return static_cast(a1l0);
20 }
21 };
****************************

102. Student Attendance Record II(Python)


****************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def checkRecord(self, n):
6 """
7 :type n: int
8 :rtype: int
9 """
10 M = 1000000007
11 a0l0, a0l1, a0l2, a1l0, a1l1, a1l2 = 1, 0, 0, 0, 0, 0
12 for i in xrange(n+1):
13 a0l2, a0l1, a0l0 = a0l1, a0l0, (a0l0 + a0l1 + a0l2) % M
14 a1l2, a1l1, a1l0 = a1l1, a1l0, (a0l0 + a1l0 + a1l1 + a1l2) % M
15 return a1l0
16
***************************

103. Find the Closest Palindrome


***************************

Given a string n representing an integer, return the closest integer (not including itself), which is a palindrome. If there is a tie,
return the smaller one.

The closest is defined as the absolute difference minimized between two integers.

Example 1:

Input: n = "123"
Output: "121"

Example 2:

Input: n = "1"
Output: "0"
Explanation: 0 and 2 are the closest palindromes but we return the smallest which is 0.

Constraints:

1 <= n.length <= 18


n consists of only digits.
n does not have leading zeros.
n is representing an integer in the range [1, 1018 - 1] .
***************************

103. Find the Closest Palindrome(C++)


***************************

1 // Time: O(l)
2 // Space: O(l)
3
4 class Solution {
5 public:
6 string nearestPalindromic(string n) {
7 const auto l = n.size();
8 unordered_set candidates;
9 candidates.emplace(static_cast(pow(10, l)) + 1);
10 candidates.emplace(static_cast(pow(10, l - 1)) - 1);
11 auto prefix = stol(n.substr(0, (l + 1) / 2));
12 for (long long i = -1; i <= 1; ++i) {
13 auto p = to_string(prefix + i);
14 auto pp = p + string(p.rbegin() + (l % 2), p.rend());
15 candidates.emplace(stol(pp));
16 }
17 long long num = stol(n), closest_val = numeric_limits::max();
18 candidates.erase(num);
19 for (const auto& val : candidates) {
20 if (abs(val - num) < abs(closest_val - num)) {
21 closest_val = val;
22 } else if (abs(val - num) == abs(closest_val - num)) {
23 closest_val = min(closest_val, val);
24 }
25 }
26 return to_string(closest_val);
27 }
28 };
***************************

103. Find the Closest Palindrome(Python)


***************************

1 # Time: O(l)
2 # Space: O(l)
3
4 class Solution(object):
5 def nearestPalindromic(self, n):
6 """
7 :type n: str
8 :rtype: str
9 """
10 l = len(n)
11 candidates = set((str(10**l + 1), str(10**(l - 1) - 1)))
12 prefix = int(n[:(l + 1)/2])
13 for i in map(str, (prefix-1, prefix, prefix+1)):
14 candidates.add(i + [i, i[:-1]][l%2][::-1])
15 candidates.discard(n)
16 return min(candidates, key=lambda x: (abs(int(x) - int(n)), int(x)))
17
*********************

104. Maximum Vacation Days


*********************

LeetCode wants to give one of its best employees the option to travel amongn cities to collect algorithm problems. But all
work and no play makes Jack a dull boy, you could take vacations in some particular cities and weeks. Your job is to
schedule the traveling to maximize the number of vacation days you could take, but there are certain rules and restrictions
you need to follow.

Rules and restrictions:

1. You can only travel among n cities, represented by indexes from 0 to n - 1. Initially, you are in the city indexed0 on
Monday.
2. The cities are connected by flights. The flights are represented as ann x n matrix (not necessarily symmetrical), called
flights representing the airline status from the city i to the city j. If there is no flight from the city i to the city j, flights[i][j] == 0;
Otherwise, flights[i][j] == 1. Also, flights[i][i] == 0 for all i.
3. You totally have k weeks (each week has seven days) to travel. You can only take flights at most once per day and
can only take flights on each week's Monday morning. Since flight time is so short, we do not consider the impact of
flight time.
4. For each city, you can only have restricted vacation days in different weeks, given ann x k matrix called days
representing this relationship. For the value of days[i][j], it represents the maximum days you could take a vacation in
the city i in the week j.
5. You could stay in a city beyond the number of vacation days, but you should work on the extra days, which will not be
counted as vacation days.
6. If you fly from city A to city B and take the vacation on that day, the deduction towards vacation days will count towards
the vacation days of city B in that week.
7. We do not consider the impact of flight hours on the calculation of vacation days.

Given the two matrices flights and days, return the maximum vacation days you could take during k weeks.

Example 1:

Input: flights = [[0,1,1],[1,0,1],[1,1,0]], days = [[1,3,1],[6,0,3],[3,3,3]]


Output: 12
Explanation:
One of the best strategies is:
1st week : fly from city 0 to city 1 on Monday, and play 6 days and work 1 day.
(Although you start at city 0, we could also fly to and start at other cities since it is Monday.)
2nd week : fly from city 1 to city 2 on Monday, and play 3 days and work 4 days.
3rd week : stay at city 2, and play 3 days and work 4 days.
Ans = 6 + 3 + 3 = 12.

Example 2:

Input: flights = [[0,0,0],[0,0,0],[0,0,0]], days = [[1,1,1],[7,7,7],[7,7,7]]


Output: 3
Explanation:
Since there are no flights that enable you to move to another city, you have to stay at city 0 for the whole 3 weeks.
For each week, you only have one day to play and six days to work.
So the maximum number of vacation days is 3.
Ans = 1 + 1 + 1 = 3.

Example 3:
Input: flights = [[0,1,1],[1,0,1],[1,1,0]], days = [[7,0,0],[0,7,0],[0,0,7]]
Output: 21
Explanation:
One of the best strategies is:
1st week : stay at city 0, and play 7 days.
2nd week : fly from city 0 to city 1 on Monday, and play 7 days.
3rd week : fly from city 1 to city 2 on Monday, and play 7 days.
Ans = 7 + 7 + 7 = 21

Constraints:

n == flights.length
n == flights[i].length
n == days.length
k == days[i].length
1 <= n, k <= 100
flights[i][j] is either 0 or 1.
0 <= days[i] <= 7
*********************

104. Maximum Vacation Days(C++)


*********************

1 // Time: O(n^2 * k)
2 // Space: O(k)
3
4 class Solution {
5 public:
6 int maxVacationDays(vector>& flights, vector>& days) {
7 if (days.empty() || flights.empty()) {
8 return 0;
9 }
10 vector> dp(2, vector(days.size()));
11 for (int week = days[0].size() - 1; week >= 0; --week) {
12 for (int cur_city = 0; cur_city < days.size(); ++cur_city) {
13 dp[week % 2][cur_city] = days[cur_city][week] + dp[(week + 1) % 2][cur_city];
14 for (int dest_city = 0; dest_city < days.size(); ++dest_city) {
15 if (flights[cur_city][dest_city] == 1) {
16 dp[week % 2][cur_city] = max(dp[week % 2][cur_city],
17 days[dest_city][week] + dp[(week + 1) % 2][dest_city]);
18 }
19 }
20 }
21 }
22 return dp[0][0];
23 }
24 };
*********************

104. Maximum Vacation Days(Python)


*********************

1 # Time: O(n^2 * k)
2 # Space: O(k)
3
4 class Solution(object):
5 def maxVacationDays(self, flights, days):
6 """
7 :type flights: List[List[int]]
8 :type days: List[List[int]]
9 :rtype: int
10 """
11 if not days or not flights:
12 return 0
13 dp = [[0] * len(days) for _ in xrange(2)]
14 for week in reversed(xrange(len(days[0]))):
15 for cur_city in xrange(len(days)):
16 dp[week % 2][cur_city] = days[cur_city][week] + dp[(week+1) % 2][cur_city]
17 for dest_city in xrange(len(days)):
18 if flights[cur_city][dest_city] == 1:
19 dp[week % 2][cur_city] = max(dp[week % 2][cur_city], \
20 days[dest_city][week] + dp[(week+1) % 2][dest_city])
21 return dp[0][0]
22
***************

105. Erect the Fence


***************

You are given an array trees where trees[i] = [x i, y i] represents the location of a tree in the garden.

You are asked to fence the entire garden using the minimum length of rope as it is expensive. The garden is well fenced
only if all the trees are enclosed.

Return the coordinates of trees that are exactly located on the fence perimeter.

Example 1:

Input: points = [[1,1],[2,2],[2,0],[2,4],[3,3],[4,2]]


Output: [[1,1],[2,0],[3,3],[2,4],[4,2]]

Example 2:
Input: points = [[1,2],[2,2],[4,2]]
Output: [[4,2],[2,2],[1,2]]

Constraints:

1 <= points.length <= 3000


points[i].length == 2
0 <= x i, y i <= 100
All the given points are unique.
***************

105. Erect the Fence(C++)


***************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 vector> outerTrees(vector>& points) {
7 const auto& orientation = [](const vector& p,
8 const vector& q,
9 const vector& r) {
10 return (q[0] - p[0]) * (r[1] - p[1]) -
11 (q[1] - p[1]) * (r[0] - p[0]);
12 };
13 if (points.size() <= 1) {
14 return points;
15 }
16
17 vector> hull;
18 sort(points.begin(), points.end());
19 for (int i = 0; i < points.size(); ++i) {
20 while (hull.size() >= 2 &&
21 orientation(hull[hull.size() - 2],
22 hull[hull.size() - 1],
23 points[i]) < 0) {
24 hull.pop_back();
25 }
26 hull.emplace_back(points[i]);
27 }
28 for (int i = points.size() - 2; i >= 0; --i) {
29 while (hull.size() >= 2 &&
30 orientation(hull[hull.size() - 2],
31 hull[hull.size() - 1],
32 points[i]) < 0) {
33 hull.pop_back();
34 }
35 hull.emplace_back(points[i]);
36 }
37 const int cnt = hull.size() / 2;
38 for (int i = 0; i < cnt; ++i) {
39 if (hull[i] != hull.back()) {
40 break;
41 }
42 hull.pop_back();
43 }
44 return hull;
45 }
46 };
***************

105. Erect the Fence(Python)


***************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 import itertools
5
6
7 # Monotone Chain Algorithm
8 class Solution(object):
9 def outerTrees(self, points):
10 """
11 :type points: List[List[int]]
12 :rtype: List[List[int]]
13 """
14 def ccw(A, B, C):
15 return (B[0]-A[0])*(C[1]-A[1]) - (B[1]-A[1])*(C[0]-A[0])
16
17 if len(points) <= 1:
18 return points
19
20 hull = []
21 points.sort()
22 for i in itertools.chain(xrange(len(points)), reversed(xrange(len(points)-1))):
23 while len(hull) >= 2 and ccw(hull[-2], hull[-1], points[i]) < 0:
24 hull.pop()
25 hull.append(points[i])
26 for i in xrange(len(hull)//2):
27 if hull[i] != hull[-1]:
28 break
29 hull.pop()
30 return hull
****************************

106. Design In-Memory File System


****************************

Design a data structure that simulates an in-memory file system.

Implement the FileSystem class:

FileSystem() Initializes the object of the system.


List<String> ls(String path)
If path is a file path, returns a list that only contains this file's name.
If path is a directory path, returns the list of file and directory namesin this directory.
The answer should in lexicographic order.
void mkdir(String path) Makes a new directory according to the givenpath. The given directory path does not exist. If the
middle directories in the path do not exist, you should create them as well.
void addContentToFile(String filePath, String content)
If filePath does not exist, creates that file containing givencontent.
If filePath already exists, appends the givencontent to original content.
String readContentFromFile(String filePath) Returns the content in the file atfilePath.

Example 1:

Input
["FileSystem", "ls", "mkdir", "addContentToFile", "ls", "readContentFromFile"]
[[], ["/"], ["/a/b/c"], ["/a/b/c/d", "hello"], ["/"], ["/a/b/c/d"]]
Output
[null, [], null, null, ["a"], "hello"]

Explanation
FileSystem fileSystem = new FileSystem();
fileSystem.ls("/"); // return []
fileSystem.mkdir("/a/b/c");
fileSystem.addContentToFile("/a/b/c/d", "hello");
fileSystem.ls("/"); // return ["a"]
fileSystem.readContentFromFile("/a/b/c/d"); // return "hello"

Constraints:

1 <= path.length, filePath.length <= 100


path and filePath are absolute paths
which begin with '/' and do not end with '/' except that the path is just "/".
You can assume that all directory names and file names only contain lowercase letters, and the same names will not
exist in the same directory.
You can assume that all operations will be passed valid parameters, and users will not attempt to retrieve file content
or list a directory or file that does not exist.
1 <= content.length <= 50
At most 300 calls will be made to ls, mkdir, addContentToFile, and readContentFromFile.
****************************

106. Design In-Memory File System(C++)


****************************

1 // Time: ls: O(l + klogk), l is the path length, k is the number of entries in the last level directory
2 // mkdir: O(l)
3 // addContentToFile: O(l + c), c is the content size
4 // readContentFromFile: O(l + c)
5 // Space: O(n + s), n is the number of dir/file nodes, s is the total content size.
6
7 class FileSystem {
8 public:
9 FileSystem() : root_(new TrieNode()) {
10
11 }
12
13 vector ls(string path) {
14 auto curr = getNode(path);
15
16 if (curr->isFile) {
17 return {split(path, '/').back()};
18 }
19
20 vector result;
21 for (const auto& child : curr->children) {
22 result.emplace_back(child.first);
23 }
24 sort(result.begin(), result.end());
25 return result;
26 }
27
28 void mkdir(string path) {
29 auto curr = putNode(path);
30 curr->isFile = false;
31 }
32
33 void addContentToFile(string filePath, string content) {
34 auto curr = putNode(filePath);
35 curr->isFile = true;
36 curr->content += content;
37 }
38
39 string readContentFromFile(string filePath) {
40 return getNode(filePath)->content;
41 }
42
43 private:
44 struct TrieNode {
45 bool isFile;
46 unordered_map children;
47 string content;
48 };
49
50 TrieNode *root_;
51
52 TrieNode *getNode(const string& path) {
53 vector strs = split(path, '/');
54 auto curr = root_;
55 for (const auto& str : strs) {
56 curr = curr->children[str];
57 }
58 return curr;
59 }
60
61 TrieNode *putNode(const string& path) {
62 vector strs = split(path, '/');
63 auto curr = root_;
64 for (const auto& str : strs) {
65 if (!curr->children.count(str)) {
66 curr->children[str] = new TrieNode();
67 }
68 curr = curr->children[str];
69 }
70 return curr;
71 }
72
73 vector split(const string& s, const char delim) {
74 vector tokens;
75 stringstream ss(s);
76 string token;
77 while (getline(ss, token, delim)) {
78 if (!token.empty()) {
79 tokens.emplace_back(token);
80 }
81 }
82 return tokens;
83 }
84 };
85
86 /**
87 * Your FileSystem object will be instantiated and called as such:
88 * FileSystem obj = new FileSystem();
89 * vector param_1 = obj.ls(path);
90 * obj.mkdir(path);
91 * obj.addContentToFile(filePath,content);
92 * string param_4 = obj.readContentFromFile(filePath);
93 */
****************************

106. Design In-Memory File System(Python)


****************************

1 # Time: ls: O(l + klogk), l is the path length, k is the number of entries in the last level directory
2 # mkdir: O(l)
3 # addContentToFile: O(l + c), c is the content size
4 # readContentFromFile: O(l + c)
5 # Space: O(n + s), n is the number of dir/file nodes, s is the total content size.
6
7 class TrieNode(object):
8
9 def __init__(self):
10 self.is_file = False
11 self.children = {}
12 self.content = ""
13
14 class FileSystem(object):
15
16 def __init__(self):
17 self.__root = TrieNode()
18
19
20 def ls(self, path):
21 """
22 :type path: str
23 :rtype: List[str]
24 """
25 curr = self.__getNode(path)
26
27 if curr.is_file:
28 return [self.__split(path, '/')[-1]]
29
30 return sorted(curr.children.keys())
31
32
33 def mkdir(self, path):
34 """
35 :type path: str
36 :rtype: void
37 """
38 curr = self.__putNode(path)
39 curr.is_file = False
40
41
42 def addContentToFile(self, filePath, content):
43 """
44 :type filePath: str
45 :type content: str
46 :rtype: void
47 """
48 curr = self.__putNode(filePath)
49 curr.is_file = True
50 curr.content += content
51
52
53 def readContentFromFile(self, filePath):
54 """
55 :type filePath: str
56 :rtype: str
57 """
58 return self.__getNode(filePath).content
59
60
61 def __getNode(self, path):
62 curr = self.__root
63 for s in self.__split(path, '/'):
64 curr = curr.children[s]
65 return curr
66
67
68 def __putNode(self, path):
69 curr = self.__root
70 for s in self.__split(path, '/'):
71 if s not in curr.children:
72 curr.children[s] = TrieNode()
73 curr = curr.children[s]
74 return curr
75
76
77 def __split(self, path, delim):
78 if path == '/':
79 return []
80 return path.split('/')[1:]
81
82
*************

107. Tag Validator


*************

Given a string representing a code snippet, implement a tag validator to parse the code and return whether it is valid.

A code snippet is valid if all the following rules hold:

1. The code must be wrapped in a valid closed tag. Otherwise, the code is invalid.
2. A closed tag (not necessarily valid) has exactly the following format :<TAG_NAME>TAG_CONTENT</TAG_NAME>. Among
them, <TAG_NAME> is the start tag, and </TAG_NAME> is the end tag. The TAG_NAME in start and end tags should be
the same. A closed tag is valid if and only if the TAG_NAME and TAG_CONTENT are valid.
3. A valid TAG_NAME only contain upper-case letters, and has length in range [1,9]. Otherwise, the TAG_NAME is invalid.
4. A valid TAG_CONTENT may contain other valid closed tags, cdata and any characters (see note1) EXCEPT
unmatched <, unmatched start and end tag, and unmatched or closed tags with invalid TAG_NAME. Otherwise, the
TAG_CONTENT is invalid.
5. A start tag is unmatched if no end tag exists with the same TAG_NAME, and vice versa. However, you also need to
consider the issue of unbalanced when tags are nested.
6. A < is unmatched if you cannot find a subsequent >. And when you find a < or </, all the subsequent characters until the
next > should be parsed as TAG_NAME (not necessarily valid).
7. The cdata has the following format : <![CDATA[CDATA_CONTENT]]>. The range of CDATA_CONTENT is defined as the
characters between <![CDATA[ and the first subsequent ]]>.
8. CDATA_CONTENT may contain any characters. The function of cdata is to forbid the validator to parseCDATA_CONTENT,
so even it has some characters that can be parsed as tag (no matter valid or invalid), you should treat it as regular
characters.

Example 1:

Input: code = "<DIV>This is the first line <![CDATA[<div>]]></DIV>"


Output: true
Explanation:
The code is wrapped in a closed tag : <DIV> and </DIV>.
The TAG_NAME is valid, the TAG_CONTENT consists of some characters and cdata.
Although CDATA_CONTENT has an unmatched start tag with invalid TAG_NAME, it should be considered as plain text, not parsed as a tag.
So TAG_CONTENT is valid, and then the code is valid. Thus return true.

Example 2:

Input: code = "<DIV>>> ![cdata[]] <![CDATA[<div>]>]]>]]>>]</DIV>"


Output: true
Explanation:
We first separate the code into : start_tag|tag_content|end_tag.
start_tag -> "<DIV>"
end_tag -> "</DIV>"
tag_content could also be separated into : text1|cdata|text2.
text1 -> ">> ![cdata[]] "
cdata -> "<![CDATA[<div>]>]]>", where the CDATA_CONTENT is "<div>]>"
text2 -> "]]>>]"
The reason why start_tag is NOT "<DIV>>>" is because of the rule 6.
The reason why cdata is NOT "<![CDATA[<div>]>]]>]]>" is because of the rule 7.

Example 3:
Input: code = "<A> <B> </A> </B>"
Output: false
Explanation: Unbalanced. If "<A>" is closed, then "<B>" must be unmatched, and vice versa.

Example 4:

Input: code = "<DIV> div tag is not closed <DIV>"


Output: false

Constraints:

1 <= code.length <= 500


code consists of English letters, digits, '<' , '>' , '/', '!', '[', ']', '.', and ' '.
*************

107. Tag Validator(C++)


*************
1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 bool isValid(string code) {
7 auto i = 0;
8 return validTag(code, &i) && i == code.length();
9 }
10
11 private:
12 bool validTag(const string& s, int *i) {
13 auto j = *i;
14 auto tag = parseTagName(s, &j);
15 if (tag.empty()) {
16 return false;
17 }
18 parseContent(s, &j);
19 auto k = j + tag.size() + 2;
20 if (k >= s.size() || s.substr(j, k + 1 - j) != "") {
21 return false;
22 }
23 *i = k + 1;
24 return true;
25 }
26
27 string parseTagName(const string& s, int *i) {
28 if (s[*i] != '<') {
29 return "";
30 }
31 auto j = s.find('>', *i);
32 if (j == string::npos || j - 1 - *i < 1 || 9 < j - 1 - *i) {
33 return "";
34 }
35 auto tag = s.substr(*i + 1, j - 1 - *i);
36 for (const auto& c : tag) {
37 if (c < 'A' || 'Z' < c) {
38 return "";
39 }
40 }
41 *i = j + 1;
42 return tag;
43 }
44
45 void parseContent(const string& s, int *i) {
46 while (*i < s.size()) {
47 if (!validText(s, i) && !validCData(s, i) && !validTag(s, i)) {
48 break;
49 }
50 }
51 }
52
53 bool validText(const string& s, int *i) {
54 auto j = *i;
55 *i = s.find("<", *i);
56 return *i != j;
57 }
58
59 bool validCData(const string& s, int *i) {
60 if (s.find("", *i);
61 if (j == string::npos) {
62 return false;
63 }
64 *i = j + 3;
65 return true;
66 }
67 };
*************

107. Tag Validator(Python)


*************

1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 def isValid(self, code):
6 """
7 :type code: str
8 :rtype: bool
9 """
10 def validText(s, i):
11 j = i
12 i = s.find("<", i)
13 return i != j, i
14
15 def validCData(s, i):
16 if s.find("", i)
17 if j == -1:
18 return False, i
19 return True, j+3
20
21 def parseTagName(s, i):
22 if s[i] != '<':
23 return "", i
24 j = s.find('>', i)
25 if j == -1 or not (1 <= (j-1-i) <= 9):
26 return "", i
27 tag = s[i+1:j]
28 for c in tag:
29 if not (ord('A') <= ord(c) <= ord('Z')):
30 return "", i
31 return tag, j+1
32
33 def parseContent(s, i):
34 while i < len(s):
35 result, i = validText(s, i)
36 if result:
37 continue
38 result, i = validCData(s, i)
39 if result:
40 continue
41 result, i = validTag(s, i)
42 if result:
43 continue
44 break
45 return i
46
47 def validTag(s, i):
48 tag, j = parseTagName(s, i)
49 if not tag:
50 return False, i
51 j = parseContent(s, j)
52 k = j + len(tag) + 2
53 if k >= len(s) or s[j:k+1] != "":
54 return False, i
55 return True, k+1
56
57 result, i = validTag(code, 0)
58 return result and i == len(code)
59
**********************************************

108. Non-negative Integers without Consecutive Ones


**********************************************

Given a positive integer n, return the number of the integers in the range[0, n] whose binary representations do not contain
consecutive ones.

Example 1:

Input: n = 5
Output: 5
Explanation:
Here are the non-negative integers <= 5 with their corresponding binary representations:
0 : 0
1 : 1
2 : 10
3 : 11
4 : 100
5 : 101
Among them, only integer 3 disobeys the rule (two consecutive ones) and the other 5 satisfy the rule.

Example 2:

Input: n = 1
Output: 2

Example 3:

Input: n = 2
Output: 3

Constraints:

1 <= n <= 10 9
**********************************************

108. Non-negative Integers without Consecutive


Ones(C++)
**********************************************

1 // Time: O(1)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int findIntegers(int num) {
7 vector dp(32);
8 dp[0] = 1;
9 dp[1] = 2;
10 for (int i = 2; i < dp.size(); ++i) {
11 dp[i] = dp[i - 1] + dp[i - 2];
12 }
13 int result = 0, prev_bit = 0;
14 for (int i = 30; i >= 0; --i) {
15 if ((num & (1 << i)) != 0) {
16 result += dp[i];
17 if (prev_bit == 1) {
18 --result;
19 break;
20 }
21 prev_bit = 1;
22 } else {
23 prev_bit = 0;
24 }
25 }
26 return result + 1;
27 }
28 };
**********************************************

108. Non-negative Integers without Consecutive


Ones(Python)
**********************************************

1 # Time: O(1)
2 # Space: O(1)
3
4 class Solution(object):
5 def findIntegers(self, num):
6 """
7 :type num: int
8 :rtype: int
9 """
10 dp = [0] * 32
11 dp[0], dp[1] = 1, 2
12 for i in xrange(2, len(dp)):
13 dp[i] = dp[i-1] + dp[i-2]
14 result, prev_bit = 0, 0
15 for i in reversed(xrange(31)):
16 if (num & (1 << i)) != 0:
17 result += dp[i]
18 if prev_bit == 1:
19 result -= 1
20 break
21 prev_bit = 1
22 else:
23 prev_bit = 0
24 return result + 1
25
*********************

109. K Inverse Pairs Array


*********************

For an integer array nums, an inverse pair is a pair of integers [i, j] where 0 <= i < j < nums.length and nums[i] > nums[j] .

Given two integers n and k, return the number of different arrays consist of numbers from1 to n such that there are exactly k
inverse pairs. Since the answer can be huge, return it modulo 109 + 7 .

Example 1:

Input: n = 3, k = 0
Output: 1
Explanation: Only the array [1,2,3] which consists of numbers from 1 to 3 has exactly 0 inverse pairs.

Example 2:

Input: n = 3, k = 1
Output: 2
Explanation: The array [1,3,2] and [2,1,3] have exactly 1 inverse pair.

Constraints:

1 <= n <= 1000


0 <= k <= 1000
*********************

109. K Inverse Pairs Array(C++)


*********************

1 // Time: O(n * k)
2 // Space: O(k)
3
4 class Solution {
5 public:
6 int kInversePairs(int n, int k) {
7 static const int M = 1000000007;
8 vector> dp(2, vector(k + 1));
9 dp[0][0] = 1;
10 for (int i = 1; i <= n; ++i) {
11 dp[i % 2] = vector(k + 1);
12 dp[i % 2][0] = 1;
13 for (int j = 1; j <= k; ++j) {
14 dp[i % 2][j] = (dp[i % 2][j - 1] + dp[(i - 1) % 2][j]) % M;
15 if (j - i >= 0) {
16 dp[i % 2][j] = (dp[i % 2][j] - dp[(i - 1) % 2][j - i] + M) % M;
17 }
18 }
19 }
20 return dp[n % 2][k];
21 }
22 };
23
*********************

109. K Inverse Pairs Array(Python)


*********************

1 # Time: O(n * k)
2 # Space: O(k)
3
4 class Solution(object):
5 def kInversePairs(self, n, k):
6 """
7 :type n: int
8 :type k: int
9 :rtype: int
10 """
11 M = 1000000007
12 dp = [[0]*(k+1) for _ in xrange(2)]
13 dp[0][0] = 1
14 for i in xrange(1, n+1):
15 dp[i%2] = [0]*(k+1)
16 dp[i%2][0] = 1
17 for j in xrange(1, k+1):
18 dp[i%2][j] = (dp[i%2][j-1] + dp[(i-1)%2][j]) % M
19 if j-i >= 0:
20 dp[i%2][j] = (dp[i%2][j] - dp[(i-1)%2][j-i]) % M
21 return dp[n%2][k]
22
*******************

110. Course Schedule III


*******************

There are n different online courses numbered from 1 to n. You are given an array courses where courses[i] = [duration i, lastDay i]
indicate that the ith course should be taken continuously for durationi days and must be finished before or on lastDayi.

You will start on the 1st day and you cannot take two or more courses simultaneously.

Return the maximum number of courses that you can take.

Example 1:

Input: courses = [[100,200],[200,1300],[1000,1250],[2000,3200]]


Output: 3
Explanation:
There are totally 4 courses, but you can take 3 courses at most:
First, take the 1st course, it costs 100 days so you will finish it on the 100th day, and ready to take the next course on the 101st day.
Second, take the 3rd course, it costs 1000 days so you will finish it on the 1100th day, and ready to take the next course on the 1101st day.
Third, take the 2nd course, it costs 200 days so you will finish it on the 1300th day.
The 4th course cannot be taken now, since you will finish it on the 3300th day, which exceeds the closed date.

Example 2:

Input: courses = [[1,2]]


Output: 1

Example 3:

Input: courses = [[3,2],[4,3]]


Output: 0

Constraints:

1 <= courses.length <= 104


1 <= duration i, lastDay i <= 104
*******************

110. Course Schedule III(C++)


*******************

1 // Time: O(nlogn)
2 // Space: O(k), k is the number of courses you can take
3
4 class Solution {
5 public:
6 int scheduleCourse(vector>& courses) {
7 sort(courses.begin(), courses.end(),
8 [](const vector& a, const vector& b) {
9 return a[1] < b[1];
10 });
11 priority_queue max_heap;
12 int now = 0;
13 for (const auto& course : courses) {
14 max_heap.emplace(course[0]);
15 now += course[0];
16 if (now > course[1]) {
17 now -= max_heap.top(), max_heap.pop();
18 }
19 }
20 return heap.size();
21 }
22 };
23
*******************

110. Course Schedule III(Python)


*******************

1 # Time: O(nlogn)
2 # Space: O(k), k is the number of courses you can take
3
4 import collections
5 import heapq
6
7
8 class Solution(object):
9 def scheduleCourse(self, courses):
10 """
11 :type courses: List[List[int]]
12 :rtype: int
13 """
14 courses.sort(key=lambda t_end: t_end[1])
15 max_heap = []
16 now = 0
17 for t, end in courses:
18 now += t
19 heapq.heappush(max_heap, -t)
20 if now > end:
21 now += heapq.heappop(max_heap)
22 return len(max_heap)
23
************************

111. Design Excel Sum Formula


************************

Design the basic function of Excel and implement the function of the sum formula.

Implement the Excel class:

Excel(int height, char width) Initializes the object with the height and the width of the sheet. The sheet is an integer matrix mat
of size height x width with the row index in the range[1, height] and the column index in the range ['A', width] . All the values
should be zero initially.
void set(int row, char column, int val) Changes the value at mat[row][column] to be val .
int get(int row, char column) Returns the value at mat[row][column].
int sum(int row, char column, List<String> numbers) Sets the value at mat[row][column] to be the sum of cells represented by
numbers and returns the value at mat[row][column]. This sum formula should exist until this cell is overlapped by another
value or another sum formula. numbers[i] could be on the format:
"ColRow" that represents a single cell.
For example, "F7" represents the cell mat[7]['F'].
"ColRow1:ColRow2" that represents a range of cells. The range will always be a rectangle where"ColRow1" represent
the position of the top-left cell, and "ColRow2" represents the position of the bottom-right cell.
For example, "B3:F7" represents the cells mat[i][j] for 3 <= i <= 7 and 'B' <= j <= 'F' .

Note: You could assume that there will not be any circular sum reference.

For example, mat[1]['A'] == sum(1, "B") and mat[1]['B'] == sum(1, "A") .

Example 1:

Input
["Excel", "set", "sum", "set", "get"]
[[3, "C"], [1, "A", 2], [3, "C", ["A1", "A1:B2"]], [2, "B", 2], [3, "C"]]
Output
[null, null, 4, null, 6]

Explanation
Excel excel = new Excel(3, "C");
// construct a 3*3 2D array with all zero.
// A B C
// 1 0 0 0
// 2 0 0 0
// 3 0 0 0
excel.set(1, "A", 2);
// set mat[1]["A"] to be 2.
// A B C
// 1 2 0 0
// 2 0 0 0
// 3 0 0 0
excel.sum(3, "C", ["A1", "A1:B2"]); // return 4
// set mat[3]["C"] to be the sum of value at mat[1]["A"] and the values sum of the rectangle range whose top-left cell is mat[1]["A"] and bo
// A B C
// 1 2 0 0
// 2 0 0 0
// 3 0 0 4
excel.set(2, "B", 2);
// set mat[2]["B"] to be 2. Note mat[3]["C"] should also be changed.
// A B C
// 1 2 0 0
// 2 0 2 0
// 3 0 0 6
excel.get(3, "C"); // return 6
Constraints:

1 <= height <= 26


'A' <= width <= 'Z'
1 <= row <= height
'A' <= column <= width
-100 <= val <= 100
1 <= numbers.length <= 5
numbers[i] has the format "ColRow" or "ColRow1:ColRow2".
At most 100 calls will be made to set, get, and sum .
************************

111. Design Excel Sum Formula(C++)


************************

1 // Time: set: O((r * c)^2)


2 // get: O(1)
3 // sum: O((r * c)^2)
4 // Space: O(r * c)
5
6 class Excel {
7 public:
8 Excel(int H, char W) : Exl_(H + 1, vector(W - 'A' + 1)) {
9 }
10
11 // Time: O((r * c)^2)
12 void set(int r, char c, int v) {
13 auto col = c - 'A';
14 reset_dependency(r, col);
15 update_others(r, col, v);
16 }
17
18 // Time: O(1)
19 int get(int r, char c) {
20 return Exl_[r][c - 'A'];
21 }
22
23 // Time: O((r * c)^2)
24 int sum(int r, char c, vector strs) {
25 auto col = c - 'A';
26 reset_dependency(r, col);
27 auto result = calc_and_update_dependency(r, col, strs);
28 update_others(r, col, result);
29 return result;
30 }
31
32 private:
33 // Time: O(r * c)
34 void reset_dependency(int r, int col) {
35 auto key = r * 26 + col;
36 if (bward_.count(key)) {
37 for (const auto& k : bward_[key]) {
38 fward_[k].erase(key);
39 }
40 bward_.erase(key);
41 }
42 }
43
44 // Time: O(r * c * l), l is the length of strs
45 int calc_and_update_dependency(int r, int col, const vector& strs) {
46 auto result = 0;
47 for (const auto& s : strs) {
48 int p = s.find(':'), left, right, top, bottom;
49 left = s[0] - 'A';
50 right = s[p + 1] - 'A';
51 top = (p == string::npos) ? stoi(s.substr(1)) : stoi(s.substr(1, p - 1));
52 bottom = stoi(s.substr(p + 2));
53 for (int i = top; i <= bottom; ++i) {
54 for (int j = left; j <= right; ++j) {
55 result += Exl_[i][j];
56 ++fward_[i * 26 + j][r * 26 + col];
57 bward_[r * 26 + col].emplace(i * 26 + j);
58 }
59 }
60 }
61 return result;
62 }
63
64 // Time: O((r * c)^2)
65 void update_others(int r, int col, int v) {
66 auto prev = Exl_[r][col];
67 Exl_[r][col] = v;
68 queue> q;
69 q.emplace(make_pair(r * 26 + col, v - prev));
70 while (!q.empty()) {
71 int key, diff;
72 tie(key, diff) = q.front(), q.pop();
73 if (fward_.count(key)) {
74 for (auto it = fward_[key].begin(); it != fward_[key].end(); ++it) {
75 int k, count;
76 tie(k, count) = *it;
77 q.emplace(make_pair(k, diff * count));
78 Exl_[k / 26][k % 26] += diff * count;
79 }
80 }
81 }
82 }
83
84 unordered_map> fward_;
85 unordered_map> bward_;
86 vector> Exl_;
87 };
88
89 /**
90 * Your Excel object will be instantiated and called as such:
91 * Excel obj = new Excel(H, W);
92 * obj.set(r,c,v);
93 * int param_2 = obj.get(r,c);
94 * int param_3 = obj.sum(r,c,strs);
95 */
************************

111. Design Excel Sum Formula(Python)


************************

1 # Time: set: O((r * c)^2)


2 # get: O(1)
3 # sum: O((r * c)^2)
4 # Space: O(r * c)
5
6 import collections
7
8
9 class Excel(object):
10
11 def __init__(self, H, W):
12 """
13 :type H: int
14 :type W: str
15 """
16 self.__exl = [[0 for _ in xrange(ord(W)-ord('A')+1)] \
17 for _ in xrange(H+1)]
18 self.__fward = collections.defaultdict(lambda : collections.defaultdict(int))
19 self.__bward = collections.defaultdict(set)
20
21
22 def set(self, r, c, v):
23 """
24 :type r: int
25 :type c: str
26 :type v: int
27 :rtype: void
28 """
29 self.__reset_dependency(r, c)
30 self.__update_others(r, c, v)
31
32
33 def get(self, r, c):
34 """
35 :type r: int
36 :type c: str
37 :rtype: int
38 """
39 return self.__exl[r][ord(c) - ord('A')]
40
41
42 def sum(self, r, c, strs):
43 """
44 :type r: int
45 :type c: str
46 :type strs: List[str]
47 :rtype: int
48 """
49 self.__reset_dependency(r, c)
50 result = self.__calc_and_update_dependency(r, c, strs)
51 self.__update_others(r, c, result)
52 return result
53
54
55 def __reset_dependency(self, r, c):
56 key = (r, c)
57 if key in self.__bward.keys():
58 for k in self.__bward[key]:
59 self.__fward[k].pop(key, None)
60 self.__bward[key] = set()
61
62
63 def __calc_and_update_dependency(self, r, c, strs):
64 result = 0
65 for s in strs:
66 s, e = s.split(':')[0], s.split(':')[1] if ':' in s else s
67 left, right, top, bottom = ord(s[0])-ord('A'), ord(e[0])-ord('A'), int(s[1:]), int(e[1:])
68 for i in xrange(top, bottom+1):
69 for j in xrange(left, right+1):
70 result += self.__exl[i][j]
71 self.__fward[(i, chr(ord('A')+j))][(r, c)] += 1
72 self.__bward[(r, c)].add((i, chr(ord('A')+j)))
73 return result
74
75
76 def __update_others(self, r, c, v):
77 prev = self.__exl[r][ord(c)-ord('A')]
78 self.__exl[r][ord(c)-ord('A')] = v
79 q = collections.deque()
80 q.append(((r, c), v-prev))
81 while q:
82 key, diff = q.popleft()
83 if key in self.__fward:
84 for k, count in self.__fward[key].iteritems():
85 q.append((k, diff*count))
86 self.__exl[k[0]][ord(k[1])-ord('A')] += diff*count
87
88
89
**************

112. Smallest Range


**************

You have k lists of sorted integers in non-decreasing order. Find the smallest range that includes at least one number from
each of the k lists.

We define the range [a, b] is smaller than range [c, d] if b - a < d - c or a < c if b - a == d - c .

Example 1:

Input: nums = [[4,10,15,24,26],[0,9,12,20],[5,18,22,30]]


Output: [20,24]
Explanation:
List 1: [4, 10, 15, 24,26], 24 is in range [20,24].
List 2: [0, 9, 12, 20], 20 is in range [20,24].
List 3: [5, 18, 22, 30], 22 is in range [20,24].

Example 2:

Input: nums = [[1,2,3],[1,2,3],[1,2,3]]


Output: [1,1]

Example 3:

Input: nums = [[10,10],[11,11]]


Output: [10,11]

Example 4:

Input: nums = [[10],[11]]


Output: [10,11]

Example 5:

Input: nums = [[1],[2],[3],[4],[5],[6],[7]]


Output: [1,7]

Constraints:

nums.length == k
1 <= k <= 3500
1 <= nums[i].length <= 50
-105 <= nums[i][j] <= 10 5
nums[i] is sorted in non-decreasing order.
**************

112. Smallest Range(C++)


**************

1 // Time: O(nlogk)
2 // Space: O(k)
3
4 class Solution {
5 public:
6 vector smallestRange(vector>& nums) {
7 using VIT = vector::iterator;
8
9 const auto comp = [](const pair& p1, const pair& p2) {
10 return *p1.first > *p2.first;
11 };
12
13 int left = numeric_limits::max(), right = numeric_limits::min();
14 priority_queue, vector>, decltype(comp)> min_heap(comp);
15 for (auto &row : nums) {
16 left = min(left, row[0]);
17 right = max(right, row[0]);
18 min_heap.emplace(row.begin(), row.end());
19 }
20
21 vector result = {left, right};
22 while (!min_heap.empty()) {
23 auto p = min_heap.top();
24 min_heap.pop();
25 ++p.first;
26 if (p.first == p.second) {
27 break;
28 }
29 min_heap.emplace(p);
30
31 left = *min_heap.top().first;
32 right = max(right, *p.first);
33 if (right - left < result[1] - result[0]) {
34 result = {left, right};
35 }
36 }
37 return result;
38 }
39 };
40
**************

112. Smallest Range(Python)


**************

1 # Time: O(nlogk)
2 # Space: O(k)
3
4 import heapq
5
6
7 class Solution(object):
8 def smallestRange(self, nums):
9 """
10 :type nums: List[List[int]]
11 :rtype: List[int]
12 """
13 left, right = float("inf"), float("-inf")
14 min_heap = []
15 for row in nums:
16 left = min(left, row[0])
17 right = max(right, row[0])
18 it = iter(row)
19 heapq.heappush(min_heap, (next(it, None), it))
20
21 result = (left, right)
22 while min_heap:
23 (val, it) = heapq.heappop(min_heap)
24 val = next(it, None)
25 if val is None:
26 break
27 heapq.heappush(min_heap, (val, it))
28 left, right = min_heap[0][0], max(right, val)
29 if right - left < result[1] - result[0]:
30 result = (left, right)
31 return result
32
**************

113. Decode Ways II


**************

A message containing letters from A-Z can be encoded into numbers using the following mapping:

'A' -> "1"


'B' -> "2"
...
'Z' -> "26"

To decode an encoded message, all the digits must be grouped then mapped back into letters using the reverse of the
mapping above (there may be multiple ways). For example, "11106" can be mapped into:

"AAJF" with the grouping (1 1 10 6)


"KJF" with the grouping (11 10 6)

Note that the grouping (1 11 06) is invalid because "06" cannot be mapped into 'F' since "6" is different from "06".

In addition to the mapping above, an encoded message may contain the'*' character, which can represent any digit from '1'
to '9' ('0' is excluded). For example, the encoded message "1*" may represent any of the encoded messages "11", "12", "13",
"14", "15", "16", "17", "18", or "19". Decoding "1*" is equivalent to decoding any of the encoded messages it can represent.

Given a string s consisting of digits and '*' characters, return the number of ways to decode it.

Since the answer may be very large, return it modulo 109 + 7 .

Example 1:

Input: s = "*"
Output: 9
Explanation: The encoded message can represent any of the encoded messages "1", "2", "3", "4", "5", "6", "7", "8", or "9".
Each of these can be decoded to the strings "A", "B", "C", "D", "E", "F", "G", "H", and "I" respectively.
Hence, there are a total of 9 ways to decode "*".

Example 2:

Input: s = "1*"
Output: 18
Explanation: The encoded message can represent any of the encoded messages "11", "12", "13", "14", "15", "16", "17", "18", or "19".
Each of these encoded messages have 2 ways to be decoded (e.g. "11" can be decoded to "AA" or "K").
Hence, there are a total of 9 * 2 = 18 ways to decode "1*".

Example 3:

Input: s = "2*"
Output: 15
Explanation: The encoded message can represent any of the encoded messages "21", "22", "23", "24", "25", "26", "27", "28", or "29".
"21", "22", "23", "24", "25", and "26" have 2 ways of being decoded, but "27", "28", and "29" only have 1 way.
Hence, there are a total of (6 * 2) + (3 * 1) = 12 + 3 = 15 ways to decode "2*".
Constraints:

1 <= s.length <= 105


s[i] is a digit or '*'.
**************

113. Decode Ways II(C++)


**************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int numDecodings(string s) {
7 static const int M = 1000000007;
8 static const int W = 3;
9 vector dp(W);
10 dp[0] = 1;
11 dp[1] = s[0] == '*' ? 9 : (s[0] != '0' ? dp[0] : 0);
12 for (int i = 1; i < s.length(); ++i) {
13 if (s[i] == '*') {
14 dp[(i + 1) % W] = 9 * dp[i % W];
15 if (s[i - 1] == '1') {
16 dp[(i + 1) % W] = (dp[(i + 1) % W] + 9 * dp[(i - 1) % W]) % M;
17 } else if (s[i - 1] == '2') {
18 dp[(i + 1) % W] = (dp[(i + 1) % W] + 6 * dp[(i - 1) % W]) % M;
19 } else if (s[i - 1] == '*') {
20 dp[(i + 1) % W] = (dp[(i + 1) % W] + 15 * dp[(i - 1) % W]) % M;
21 }
22 } else {
23 dp[(i + 1) % W] = s[i] != '0' ? dp[i % W] : 0;
24 if (s[i - 1] == '1') {
25 dp[(i + 1) % W] = (dp[(i + 1) % W] + dp[(i - 1) % W]) % M;
26 } else if (s[i - 1] == '2' && s[i] <= '6') {
27 dp[(i + 1) % W] = (dp[(i + 1) % W] + dp[(i - 1) % W]) % M;
28 } else if (s[i - 1] == '*') {
29 dp[(i + 1) % W] = (dp[(i + 1) % W] + (s[i] <= '6' ? 2 : 1) * dp[(i - 1) % W]) % M;
30 }
31 }
32 }
33 return static_cast(dp[s.length() % W]);
34 }
35 };
**************

113. Decode Ways II(Python)


**************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def numDecodings(self, s):
6 """
7 :type s: str
8 :rtype: int
9 """
10 M, W = 1000000007, 3
11 dp = [0] * W
12 dp[0] = 1
13 dp[1] = 9 if s[0] == '*' else dp[0] if s[0] != '0' else 0
14 for i in xrange(1, len(s)):
15 if s[i] == '*':
16 dp[(i + 1) % W] = 9 * dp[i % W]
17 if s[i - 1] == '1':
18 dp[(i + 1) % W] = (dp[(i + 1) % W] + 9 * dp[(i - 1) % W]) % M
19 elif s[i - 1] == '2':
20 dp[(i + 1) % W] = (dp[(i + 1) % W] + 6 * dp[(i - 1) % W]) % M
21 elif s[i - 1] == '*':
22 dp[(i + 1) % W] = (dp[(i + 1) % W] + 15 * dp[(i - 1) % W]) % M
23 else:
24 dp[(i + 1) % W] = dp[i % W] if s[i] != '0' else 0
25 if s[i - 1] == '1':
26 dp[(i + 1) % W] = (dp[(i + 1) % W] + dp[(i - 1) % W]) % M
27 elif s[i - 1] == '2' and s[i] <= '6':
28 dp[(i + 1) % W] = (dp[(i + 1) % W] + dp[(i - 1) % W]) % M
29 elif s[i - 1] == '*':
30 dp[(i + 1) % W] = (dp[(i + 1) % W] + (2 if s[i] <= '6' else 1) * dp[(i - 1) % W]) % M
31 return dp[len(s) % W]
32
*********************************

114. Design Search Autocomplete System


*********************************

Design a search autocomplete system for a search engine. Users may input a sentence (at least one word and end with a
special character '#').

You are given a string array sentences and an integer array times both of length n where sentences[i] is a previously typed
sentence and times[i] is the corresponding number of times the sentence was typed. For each input character except'#',
return the top 3 historical hot sentences that have the same prefix as the part of the sentence already typed.

Here are the specific rules:

The hot degree for a sentence is defined as the number of times a user typed the exactly same sentence before.
The returned top 3 hot sentences should be sorted by hot degree (The first is the hottest one). If several sentences
have the same hot degree, use ASCII-code order (smaller one appears first).
If less than 3 hot sentences exist, return as many as you can.
When the input is a special character, it means the sentence ends, and in this case, you need to return an empty list.

Implement the AutocompleteSystem class:

AutocompleteSystem(String[] sentences, int[] times) Initializes the object with the sentences and times arrays.
List<String> input(char c) This indicates that the user typed the characterc .
Returns an empty array [] if c == '#' and stores the inputted sentence in the system.
Returns the top 3 historical hot sentences that have the same prefix as the part of the sentence already typed. If
there are fewer than 3 matches, return them all.

Example 1:

Input
["AutocompleteSystem", "input", "input", "input", "input"]
[[["i love you", "island", "iroman", "i love leetcode"], [5, 3, 2, 2]], ["i"], [" "], ["a"], ["#"]]
Output
[null, ["i love you", "island", "i love leetcode"], ["i love you", "i love leetcode"], [], []]

Explanation
AutocompleteSystem obj = new AutocompleteSystem(["i love you", "island", "iroman", "i love leetcode"], [5, 3, 2, 2]);
obj.input("i"); // return ["i love you", "island", "i love leetcode"]. There are four sentences that have prefix "i". Among them, "ironman" a
obj.input(" "); // return ["i love you", "i love leetcode"]. There are only two sentences that have prefix "i ".
obj.input("a"); // return []. There are no sentences that have prefix "i a".
obj.input("#"); // return []. The user finished the input, the sentence "i a" should be saved as a historical sentence in system. And the fol

Constraints:

n == sentences.length
n == times.length
1 <= n <= 100
1 <= sentences[i].length <= 100
1 <= times[i] <= 50
c is a lowercase English letter,
a hash '#', or space ' '.
Each tested sentence will be a sequence of characters c that end with the character '#'.
Each tested sentence will have a length in the range[1, 200].
The words in each input sentence are separated by single spaces.
At most 5000 calls will be made to input.
*********************************

114. Design Search Autocomplete System(C++)


*********************************

1 // Time: O(p^2), p is the length of the prefix


2 // Space: O(p * t + s), t is the number of nodes of trie
3 // , s is the size of the sentences
4
5 class AutocompleteSystem {
6 public:
7 AutocompleteSystem(vector sentences, vector times) : cur_node_(&trie_) {
8 for (int i = 0; i < size(sentences); ++i) {
9 sentence_to_count_[sentences[i]] = times[i];
10 trie_.insert(sentences[i], sentence_to_count_[sentences[i]]);
11 }
12 }
13
14 vector input(char c) {
15 vector result;
16 if (c == '#') {
17 ++sentence_to_count_[search_];
18 trie_.insert(search_, sentence_to_count_[search_]);
19 cur_node_ = &trie_;
20 search_.clear();
21 } else {
22 search_.push_back(c);
23 if (cur_node_) {
24 if (!cur_node_->leaves_.count(c)) {
25 cur_node_ = nullptr;
26 return {};
27 }
28 cur_node_ = cur_node_->leaves_[c];
29 for (const auto& p : cur_node_->infos_) {
30 result.emplace_back(p.second);
31 }
32 }
33 }
34 return result;
35 }
36
37 private:
38 class TrieNode {
39 public:
40 static const int TOP_COUNT = 3;
41
42 ~TrieNode() {
43 for (auto& kv : leaves_) {
44 if (kv.second) {
45 delete kv.second;
46 }
47 }
48 }
49
50 // Time: O(s)
51 void insert(const string& s, int times) {
52 auto* cur = this;
53 cur->add_info(s, times);
54 for (const auto& c : s) {
55 if (!cur->leaves_.count(c)) {
56 cur->leaves_[c] = new TrieNode;
57 }
58 cur = cur->leaves_[c];
59 cur->add_info(s, times);
60 }
61 }
62
63 // Time: O(1)
64 void add_info(const string& s, int times) {
65 auto it = find_if(begin(infos_), end(infos_),
66 [&s, ×](const pair& p) {
67 return p.second == s;
68 } );
69 if (it != end(infos_)) {
70 it->first = -times;
71 } else {
72 infos_.emplace_back(-times, s);
73 }
74 sort(begin(infos_), end(infos_));
75 if (size(infos_) > TOP_COUNT) {
76 infos_.pop_back();
77 }
78 }
79
80 vector> infos_;
81 unordered_map leaves_;
82 };
83
84 TrieNode trie_;
85 TrieNode *cur_node_;
86 string search_;
87 unordered_map sentence_to_count_;
88 };
89
90 /**
91 * Your AutocompleteSystem object will be instantiated and called as such:
92 * AutocompleteSystem obj = new AutocompleteSystem(sentences, times);
93 * vector param_1 = obj.input(c);
94 */
*********************************

114. Design Search Autocomplete System(Python)


*********************************

1 # Time: O(p^2), p is the length of the prefix


2 # Space: O(p * t + s), t is the number of nodes of trie
3 # , s is the size of the sentences
4
5 import collections
6
7
8 class TrieNode(object):
9
10 def __init__(self):
11 self.__TOP_COUNT = 3
12 self.infos = []
13 self.leaves = {}
14
15
16 def insert(self, s, times):
17 cur = self
18 cur.add_info(s, times)
19 for c in s:
20 if c not in cur.leaves:
21 cur.leaves[c] = TrieNode()
22 cur = cur.leaves[c]
23 cur.add_info(s, times)
24
25
26 def add_info(self, s, times):
27 for p in self.infos:
28 if p[1] == s:
29 p[0] = -times
30 break
31 else:
32 self.infos.append([-times, s])
33 self.infos.sort()
34 if len(self.infos) > self.__TOP_COUNT:
35 self.infos.pop()
36
37
38 class AutocompleteSystem(object):
39
40 def __init__(self, sentences, times):
41 """
42 :type sentences: List[str]
43 :type times: List[int]
44 """
45 self.__trie = TrieNode()
46 self.__cur_node = self.__trie
47 self.__search = []
48 self.__sentence_to_count = collections.defaultdict(int)
49 for sentence, count in zip(sentences, times):
50 self.__sentence_to_count[sentence] = count
51 self.__trie.insert(sentence, count)
52
53
54 def input(self, c):
55 """
56 :type c: str
57 :rtype: List[str]
58 """
59 result = []
60 if c == '#':
61 self.__sentence_to_count["".join(self.__search)] += 1
62 self.__trie.insert("".join(self.__search), self.__sentence_to_count["".join(self.__search)])
63 self.__cur_node = self.__trie
64 self.__search = []
65 else:
66 self.__search.append(c)
67 if self.__cur_node:
68 if c not in self.__cur_node.leaves:
69 self.__cur_node = None
70 return []
71 self.__cur_node = self.__cur_node.leaves[c]
72 result = [p[1] for p in self.__cur_node.infos]
73 return result
74
75
76
***************************

115. Maximum Average Subarray II


***************************

You are given an integer array nums consisting of n elements, and an integer k .

Find a contiguous subarray whose length is greater than or equal to k that has the maximum average value and return
this value. Any answer with a calculation error less than 10-5 will be accepted.

Example 1:

Input: nums = [1,12,-5,-6,50,3], k = 4


Output: 12.75000
Explanation:
- When the length is 4, averages are [0.5, 12.75, 10.5] and the maximum average is 12.75
- When the length is 5, averages are [10.4, 10.8] and the maximum average is 10.8
- When the length is 6, averages are [9.16667] and the maximum average is 9.16667
The maximum average is when we choose a subarray of length 4 (i.e., the sub array [12, -5, -6, 50]) which has the max average 12.75, so we re
Note that we do not consider the subarrays of length < 4.

Example 2:

Input: nums = [5], k = 1


Output: 5.00000

Constraints:

n == nums.length
1 <= k <= n <= 10 4
-104 <= nums[i] <= 10 4
***************************

115. Maximum Average Subarray II(C++)


***************************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 double findMaxAverage(vector& nums, int k) {
7 double left = *min_element(nums.begin(), nums.end());
8 double delta = numeric_limits::max();
9 while (delta > 1e-5) {
10 delta = getDelta(left, nums, k);
11 left += delta;
12 }
13 return left;
14 }
15
16 private:
17 double getDelta(double avg, const vector& nums, int k) {
18 vector accu(nums.size() + 1);
19 int minval_pos = -1;
20 double delta = 0.0;
21 for (int i = 0; i < nums.size(); ++i) {
22 accu[i + 1] = nums[i] + accu[i] - avg;
23 if (i >= k - 1) {
24 if (minval_pos == -1 || accu[i - k + 1] < accu[minval_pos]) {
25 minval_pos = i - k + 1;
26 }
27 if (accu[i+1] - accu[minval_pos] >= 0) {
28 delta = max(delta, (accu[i + 1] - accu[minval_pos]) / (i + 1 - minval_pos));
29 }
30 }
31 }
32 return delta;
33 }
34 };
35
36
37 // Time: O(nlogm), m is (max_val - min_val)
38 // Space: O(1)
39 class Solution2 {
40 public:
41 double findMaxAverage(vector& nums, int k) {
42 double left = *min_element(nums.begin(), nums.end());
43 double right = *max_element(nums.begin(), nums.end());
44 while (right - left > 1e-5) {
45 double mid = left + (right - left) / 2;
46 if (isMidLargerOrEqualToTarget(mid, nums, k)) {
47 right = mid;
48 } else {
49 left = mid;
50 }
51 }
52 return left;
53 }
54
55 private:
56 bool isMidLargerOrEqualToTarget(double mid, const vector& nums, int k) {
57 double sum = 0, prev = 0, min_sum = 0;
58 for (int i = 0; i < k; ++i) {
59 sum += nums[i] - mid;
60 }
61 if (sum > 0) {
62 return false;
63 }
64 for (int i = k; i < nums.size(); ++i) {
65 sum += nums[i] - mid;
66 prev += nums[i - k] - mid;
67 min_sum = min(prev, min_sum);
68 if (sum > min_sum) {
69 return false;
70 }
71 }
72 return true;
73 }
74 };
***************************

115. Maximum Average Subarray II(Python)


***************************

1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 def findMaxAverage(self, nums, k):
6 """
7 :type nums: List[int]
8 :type k: int
9 :rtype: float
10 """
11 def getDelta(avg, nums, k):
12 accu = [0.0] * (len(nums) + 1)
13 minval_pos = None
14 delta = 0.0
15 for i in xrange(len(nums)):
16 accu[i+1] = nums[i] + accu[i] - avg
17 if i >= (k-1):
18 if minval_pos == None or accu[i-k+1] < accu[minval_pos]:
19 minval_pos = i-k+1
20 if accu[i+1] - accu[minval_pos] >= 0:
21 delta = max(delta, (accu[i+1] - accu[minval_pos]) / (i+1 - minval_pos))
22 return delta
23
24 left, delta = min(nums), float("inf")
25 while delta > 1e-5:
26 delta = getDelta(left, nums, k)
27 left += delta
28 return left
29
*********

116. Coin Path


*********

You are given an integer array coins (1-indexed) of length n and an integer maxJump. You can jump to any index i of the array
coins if coins[i] != -1 and you have to pay coins[i] when you visit index i. In addition to that, if you are currently at indexi, you can
only jump to any index i + k where i + k <= n and k is a value in the range [1, maxJump].

You are initially positioned at index 1 (coins[1] is not -1). You want to find the path that reaches index n with the minimum cost.

Return an integer array of the indices that you will visit in order so that you can reach index n with the minimum cost. If there
are multiple paths with the same cost, return the lexicographically smallest such path. If it is not possible to reach index n,
return an empty array.

A path p1 = [Pa1, Pa 2, ..., Pa x] of length x is lexicographically smaller than p2 = [Pb1, Pb 2, ..., Pb x] of length y , if and only if at the
first j where Paj and Pbj differ, Paj < Pb j; when no such j exists, then x < y .

Example 1:

Input: coins = [1,2,4,-1,2], maxJump = 2


Output: [1,3,5]

Example 2:

Input: coins = [1,2,4,-1,2], maxJump = 1


Output: []

Constraints:

1 <= coins.length <= 1000


-1 <= coins[i] <= 100
coins[1] != -1
1 <= maxJump <= 100
*********

116. Coin Path(C++)


*********

1 // Time: O(n * B)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 vector cheapestJump(vector& A, int B) {
7 vector result;
8 if (A.empty() || A.back() == -1) {
9 return result;
10 }
11 const int n = A.size();
12 vector dp(n, numeric_limits::max()), next(n, -1);
13 dp[n - 1] = A[n - 1];
14 for (int i = n - 2; i >= 0; --i) {
15 if (A[i] == -1) {
16 continue;
17 }
18 for (int j = i + 1; j <= min(i + B, n - 1); ++j) {
19 if (dp[j] == numeric_limits::max()) {
20 continue;
21 }
22 if (A[i] + dp[j] < dp[i]) {
23 dp[i] = A[i] + dp[j];
24 next[i] = j;
25 }
26 }
27 }
28 if (dp[0] == numeric_limits::max()) {
29 return result;
30 }
31 int k = 0;
32 while (k != -1) {
33 result.emplace_back(k + 1);
34 k = next[k];
35 }
36 return result;
37 }
38 };
*********

116. Coin Path(Python)


*********

1 # Time: O(n * B)
2 # Space: O(n)
3
4 class Solution(object):
5 def cheapestJump(self, A, B):
6 """
7 :type A: List[int]
8 :type B: int
9 :rtype: List[int]
10 """
11 result = []
12 if not A or A[-1] == -1:
13 return result
14 n = len(A)
15 dp, next_pos = [float("inf")] * n, [-1] * n
16 dp[n-1] = A[n-1]
17 for i in reversed(xrange(n-1)):
18 if A[i] == -1:
19 continue
20 for j in xrange(i+1, min(i+B+1,n)):
21 if A[i] + dp[j] < dp[i]:
22 dp[i] = A[i] + dp[j]
23 next_pos[i] = j
24 if dp[0] == float("inf"):
25 return result
26 k = 0
27 while k != -1:
28 result.append(k+1)
29 k = next_pos[k]
30 return result
31
********

117. Remove 9
********

Start from integer 1, remove any integer that contains 9 such as 9, 19, 29...

So now, you will have a new integer sequence: 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, ...

Given a positive integer n, you need to return the n-th integer after removing. Note that 1 will be the first integer.

Example 1:

Input: n = 9
Output: 10

Constraints:

1 <= n <= 8 x 10^8


********

117. Remove 9(C++)


********

1 // Time: O(logn)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int newInteger(int n) {
7 int result = 0, base = 1;
8 while (n > 0) {
9 result += (n % 9) * base;
10 n /= 9;
11 base *= 10;
12 }
13 return result;
14 }
15 };
********

117. Remove 9(Python)


********

1 # Time: O(logn)
2 # Space: O(1)
3
4 class Solution(object):
5 def newInteger(self, n):
6 """
7 :type n: int
8 :rtype: int
9 """
10 result, base = 0, 1
11 while n > 0:
12 result += (n%9) * base
13 n /= 9
14 base *= 10
15 return result
16
***************

118. Strange Printer


***************

There is a strange printer with the following two special properties:

The printer can only print a sequence ofthe same character each time.
At each turn, the printer can print new characters starting from and ending at any place and will cover the original
existing characters.

Given a string s , return the minimum number of turns the printer needed to print it.

Example 1:

Input: s = "aaabbb"
Output: 2
Explanation: Print "aaa" first and then print "bbb".

Example 2:

Input: s = "aba"
Output: 2
Explanation: Print "aaa" first and then print "b" from the second place of the string, which will cover the existing character 'a'.

Constraints:

1 <= s.length <= 100


s consists of lowercase English letters.
***************

118. Strange Printer(C++)


***************

1 // Time: O(n^3)
2 // Space: O(n^2)
3
4 class Solution {
5 public:
6 int strangePrinter(string s) {
7 vector> lookup(s.length(), vector(s.length()));
8 return dp(s, 0, s.length() - 1, &lookup);
9 }
10
11 private:
12 int dp(const string& s, int i, int j, vector> *lookup) {
13 if (i > j) {
14 return 0;
15 }
16 if (!(*lookup)[i][j]) {
17 (*lookup)[i][j] = dp(s, i, j - 1, lookup) + 1;
18 for (int k = i; k < j; ++k) {
19 if (s[k] == s[j]) {
20 (*lookup)[i][j] = min((*lookup)[i][j],
21 dp(s, i, k, lookup) + dp(s, k + 1, j - 1, lookup));
22 }
23 }
24 }
25 return (*lookup)[i][j];
26 }
27 };
***************

118. Strange Printer(Python)


***************

1 # Time: O(n^3)
2 # Space: O(n^2)
3
4 class Solution(object):
5 def strangePrinter(self, s):
6 """
7 :type s: str
8 :rtype: int
9 """
10 def dp(s, i, j, lookup):
11 if i > j:
12 return 0
13 if (i, j) not in lookup:
14 lookup[(i, j)] = dp(s, i, j-1, lookup) + 1
15 for k in xrange(i, j):
16 if s[k] == s[j]:
17 lookup[(i, j)] = min(lookup[(i, j)], \
18 dp(s, i, k, lookup) + dp(s, k+1, j-1, lookup))
19 return lookup[(i, j)]
20
21 lookup = {}
22 return dp(s, 0, len(s)-1, lookup)
23
*******************************************

119. Kth Smallest Number in Multiplication Table


*******************************************

Nearly everyone has used the Multiplication Table. The multiplication table of size m x n is an integer matrix mat where mat[i][j]
== i * j (1-indexed).

Given three integers m, n, and k , return the k th smallest element in the m x n multiplication table.

Example 1:

Input: m = 3, n = 3, k = 5
Output: 3
Explanation: The 5th smallest number is 3.

Example 2:

Input: m = 2, n = 3, k = 6
Output: 6
Explanation: The 6th smallest number is 6.

Constraints:

1 <= m, n <= 3 * 10 4
1 <= k <= m * n
*******************************************

119. Kth Smallest Number in Multiplication Table(C++)


*******************************************

1 // Time: O(m * log(m * n))


2 // Space: O(1)
3
4 class Solution {
5 public:
6 int findKthNumber(int m, int n, int k) {
7 int left = 1, right = m * n;
8 while (left <= right) {
9 const auto mid = left + (right - left) / 2;
10 if (count(mid, m, n) >= k) {
11 right = mid - 1;
12 } else {
13 left = mid + 1;
14 }
15 }
16 return left;
17 }
18
19 private:
20 int count(int target, int m, int n) {
21 auto count = 0;
22 for (int i = 1; i <= m; ++i) {
23 count += min(target / i , n);
24 }
25 return count;
26 }
27 };
*******************************************

119. Kth Smallest Number in Multiplication Table(Python)


*******************************************

1 # Time: O(m * log(m * n))


2 # Space: O(1)
3
4 class Solution(object):
5 def findKthNumber(self, m, n, k):
6 """
7 :type m: int
8 :type n: int
9 :type k: int
10 :rtype: int
11 """
12 def count(target, m, n):
13 return sum(min(target//i, n) for i in xrange(1, m+1))
14
15 left, right = 1, m*n
16 while left <= right:
17 mid = left + (right-left)/2
18 if count(mid, m, n) >= k:
19 right = mid-1
20 else:
21 left = mid+1
22 return left
23
****************************

120. Cut Off Trees for Golf Event


****************************

You are asked to cut off all the trees in a forest for a golf event. The forest is represented as anm x n matrix. In this matrix:

0means the cell cannot be walked through.


1represents an empty cell that can be walked through.
A number greater than 1 represents a tree in a cell that can be walked through, and this number is the tree's height.

In one step, you can walk in any of the four directions: north, east, south, and west. If you are standing in a cell with a tree,
you can choose whether to cut it off.

You must cut off the trees in order from shortest to tallest. When you cut off a tree, the value at its cell becomes1 (an empty
cell).

Starting from the point (0, 0) , return the minimum steps you need to walk to cut off all the trees. If you cannot cut off all the
trees, return -1.

You are guaranteed that no two trees have the same height, and there is at least one tree needs to be cut off.

Example 1:

Input: forest = [[1,2,3],[0,0,4],[7,6,5]]


Output: 6
Explanation: Following the path above allows you to cut off the trees from shortest to tallest in 6 steps.

Example 2:

Input: forest = [[1,2,3],[0,0,0],[7,6,5]]


Output: -1
Explanation: The trees in the bottom row cannot be accessed as the middle row is blocked.
Example 3:

Input: forest = [[2,3,4],[0,0,5],[8,7,6]]


Output: 6
Explanation: You can follow the same path as Example 1 to cut off all the trees.
Note that you can cut off the first tree at (0, 0) before making any steps.

Constraints:

m == forest.length
n == forest[i].length
1 <= m, n <= 50
0 <= forest[i][j] <= 10 9
****************************

120. Cut Off Trees for Golf Event(C++)


****************************

1 // Time: O(t * (logt + m * n)), t is the number of trees


2 // Space: O(t + m * n)
3
4 // Solution Reference:
5 // 1. https://discuss.leetcode.com/topic/103532/my-python-solution-inspired-by-a-algorithm/2
6 // 2. https://discuss.leetcode.com/topic/103562/python-solution-based-on-wufangjie-s-hadlock-s-algorithm
7 // 3. https://en.wikipedia.org/wiki/A*_search_algorithm
8 // 4. https://cg2010studio.files.wordpress.com/2011/12/dijkstra-vs-a-star.png
9 class Solution {
10 public:
11 int cutOffTree(vector>& forest) {
12 const auto m = forest.size(), n = forest[0].size();
13 priority_queue>,
14 vector>>,
15 greater>> > min_heap;
16
17 for (int i = 0; i < m; ++i) {
18 for (int j = 0; j < n; ++j) {
19 if (forest[i][j] > 1) {
20 min_heap.emplace(forest[i][j], make_pair(i, j));
21 }
22 }
23 }
24
25 pair start;
26 int result = 0;
27 while (!min_heap.empty()) {
28 auto tree = min_heap.top(); min_heap.pop();
29 int step = minStep(forest, start, tree.second, m, n);
30 if (step < 0) {
31 return -1;
32 }
33 result += step;
34 start = tree.second;
35 }
36 return result;
37 }
38
39 private:
40 int minStep(const vector>& forest,
41 const pair& start,
42 const pair& end,
43 const int m, const int n) {
44
45 int min_steps = abs(start.first - end.first) + abs(start.second - end.second);
46 unordered_set lookup;
47 vector> closer{start}, detour;
48 while (true) {
49 if (closer.empty()) { // cannot find a path in the closer expansions
50 if (detour.empty()) { // no other possible path
51 return -1;
52 }
53 // try other possible paths in detour expansions with extra 2-step cost
54 min_steps += 2;
55 swap(closer, detour);
56 }
57 int i, j;
58 tie(i, j) = closer.back(); closer.pop_back();
59 if (make_pair(i, j) == end) {
60 return min_steps;
61 }
62 if (!lookup.count(i * n + j)) {
63 lookup.emplace(i * n + j);
64 vector> expansions = {{i + 1, j}, {i - 1, j}, {i, j + 1}, {i, j - 1}};
65 for (const auto& expansion : expansions) {
66 int I, J;
67 tie(I, J) = expansion;
68 if (0 <= I && I < m && 0 <= J && J < n &&
69 forest[I][J] && !lookup.count(I * n + J)) {
70 bool is_closer = dot({I - i, J - j}, {end.first - i, end.second - j}) > 0;
71 is_closer ? closer.emplace_back(I, J) : detour.emplace_back(I, J);
72 }
73 }
74 }
75 }
76
77 return min_steps;
78 }
79
80 inline int dot(const pair& a, const pair& b) {
81 return a.first * b.first + a.second * b.second;
82 }
83 };
84
85
86 // Time: O(t * (logt + m * n)), t is the number of trees
87 // Space: O(t + m * n)
88 class Solution2 {
89 public:
90 int cutOffTree(vector>& forest) {
91 const auto m = forest.size(), n = forest[0].size();
92 priority_queue>,
93 vector>>,
94 greater>> > min_heap;
95
96 for (int i = 0; i < m; ++i) {
97 for (int j = 0; j < n; ++j) {
98 if (forest[i][j] > 1) {
99 min_heap.emplace(forest[i][j], make_pair(i, j));
100 }
101 }
102 }
103
104 pair start;
105 int result = 0;
106 while (!min_heap.empty()) {
107 auto tree = min_heap.top(); min_heap.pop();
108 int step = minStep(forest, start, tree.second, m, n);
109 if (step < 0) {
110 return -1;
111 }
112 result += step;
113 start = tree.second;
114 }
115 return result;
116 }
117
118 private:
119 int minStep(const vector>& forest,
120 const pair& start,
121 const pair& end,
122 const int m, const int n) {
123
124 int min_steps = 0;
125 unordered_set lookup;
126 queue> q;
127 q.emplace(start);
128 lookup.emplace(start.first * n + start.second);
129 while (!q.empty()) {
130 int size = q.size();
131 for (int i = 0; i < size; ++i) {
132 auto curr = q.front(); q.pop();
133 if (curr == end) {
134 return min_steps;
135 }
135 }
136 static const vector> directions{{0, -1}, {0, 1},
137 {-1, 0}, {1, 0}};
138 for (const auto& direction : directions) {
139 int i = curr.first + direction.first;
140 int j = curr.second + direction.second;
141 if (i < 0 || i >= m || j < 0 || j >= n ||
142 !forest[i][j] || lookup.count(i * n + j)) {
143 continue;
144 }
145 q.emplace(i, j);
146 lookup.emplace(i * n + j);
147 }
148 }
149 ++min_steps;
150 }
151 return -1;
152 }
153 };
****************************

120. Cut Off Trees for Golf Event(Python)


****************************

1 # Time: O(t * (logt + m * n)), t is the number of trees


2 # Space: O(t + m * n)
3
4 import collections
5 import heapq
6
7
8 class Solution(object):
9 def cutOffTree(self, forest):
10 """
11 :type forest: List[List[int]]
12 :rtype: int
13 """
14 def dot(p1, p2):
15 return p1[0]*p2[0]+p1[1]*p2[1]
16
17 def minStep(p1, p2):
18 min_steps = abs(p1[0]-p2[0])+abs(p1[1]-p2[1])
19 closer, detour = [p1], []
20 lookup = set()
21 while True:
22 if not closer: # cannot find a path in the closer expansions
23 if not detour: # no other possible path
24 return -1
25 # try other possible paths in detour expansions with extra 2-step cost
26 min_steps += 2
27 closer, detour = detour, closer
28 i, j = closer.pop()
29 if (i, j) == p2:
30 return min_steps
31 if (i, j) not in lookup:
32 lookup.add((i, j))
33 for I, J in (i+1, j), (i-1, j), (i, j+1), (i, j-1):
34 if 0 <= I < m and 0 <= J < n and forest[I][J] and (I, J) not in lookup:
35 is_closer = dot((I-i, J-j), (p2[0]-i, p2[1]-j)) > 0
36 (closer if is_closer else detour).append((I, J))
37 return min_steps
38
39 m, n = len(forest), len(forest[0])
40 min_heap = []
41 for i in xrange(m):
42 for j in xrange(n):
43 if forest[i][j] > 1:
44 heapq.heappush(min_heap, (forest[i][j], (i, j)))
45
46 start = (0, 0)
47 result = 0
48 while min_heap:
49 tree = heapq.heappop(min_heap)
50 step = minStep(start, tree[1])
51 if step < 0:
52 return -1
53 result += step
54 start = tree[1]
55 return result
56
57
58 # Time: O(t * (logt + m * n)), t is the number of trees
59 # Space: O(t + m * n)
60 class Solution_TLE(object):
61 def cutOffTree(self, forest):
62 """
63 :type forest: List[List[int]]
64 :rtype: int
65 """
66 def minStep(p1, p2):
67 min_steps = 0
68 lookup = {p1}
69 q = collections.deque([p1])
70 while q:
71 size = len(q)
72 for _ in xrange(size):
73 (i, j) = q.popleft()
74 if (i, j) == p2:
75 return min_steps
76 for i, j in (i+1, j), (i-1, j), (i, j+1), (i, j-1):
77 if not (0 <= i < m and 0 <= j < n and forest[i][j] and (i, j) not in lookup):
78 continue
79 q.append((i, j))
80 lookup.add((i, j))
81 min_steps += 1
82 return -1
83
84 m, n = len(forest), len(forest[0])
85 min_heap = []
86 for i in xrange(m):
87 for j in xrange(n):
88 if forest[i][j] > 1:
89 heapq.heappush(min_heap, (forest[i][j], (i, j)))
90
91 start = (0, 0)
92 result = 0
93 while min_heap:
94 tree = heapq.heappop(min_heap)
95 step = minStep(start, tree[1])
96 if step < 0:
97 return -1
98 result += step
99 start = tree[1]
100 return result
101
*******

121. 24 Game
*******

You are given an integer array cards of length 4. You have four cards, each containing a number in the range[1, 9]. You
should arrange the numbers on these cards in a mathematical expression using the operators ['+', '-', '*', '/'] and the
parentheses '(' and ')' to get the value 24.

You are restricted with the following rules:

The division operator '/' represents real division, not integer division.
For example, 4 / (1 - 2 / 3) = 4 / (1 / 3) = 12 .
Every operation done is between two numbers. In particular, we cannot use'-' as a unary operator.
For example, if cards = [1, 1, 1, 1] , the expression "-1 - 1 - 1 - 1" is not allowed.
You cannot concatenate numbers together
For example, if cards = [1, 2, 1, 2] , the expression "12 + 12" is not valid.

Return true if you can get such expression that evaluates to24, and false otherwise.

Example 1:

Input: cards = [4,1,8,7]


Output: true
Explanation: (8-4) * (7-1) = 24

Example 2:

Input: cards = [1,2,1,2]


Output: false

Constraints:

cards.length == 4
1 <= cards[i] <= 9
*******

121. 24 Game(C++)
*******

1 // Time: O(n^3 * 4^n) = O(1), n = 4


2 // Space: O(n^2) = O(1)
3
4 class Solution {
5 public:
6 bool judgePoint24(vector& nums) {
7 vector doubles;
8 std::transform(nums.begin(), nums.end(), std::back_inserter(doubles),
9 [](const int num) { return double(num); });
10 return dfs(doubles);
11 }
12
13 private:
14 bool dfs(const vector& nums) {
15 if (nums.size() == 1) {
16 return fabs(nums[0] - 24) < 1e-6;
17 }
18 static unordered_map> ops =
19 {
20 {'+', std::plus()},
21 {'-', std::minus()},
22 {'*', std::multiplies()},
23 {'/', std::divides()},
24 };
25 for (int i = 0; i < nums.size(); ++i) {
26 for (int j = 0; j < nums.size(); ++j) {
27 if (i == j) {
28 continue;
29 }
30 vector next_nums;
31 for (int k = 0; k < nums.size(); ++k) {
32 if (k == i || k == j) {
33 continue;
34 }
35 next_nums.emplace_back(nums[k]);
36 }
37 for (const auto& op : ops) {
38 if (((op.first == '+' || op.first == '*') && i > j) ||
39 (op.first == '/' && nums[j] == 0)) {
40 continue;
41 }
42 next_nums.emplace_back(op.second(nums[i], nums[j]));
43 if (dfs(next_nums)) {
44 return true;
45 }
46 next_nums.pop_back();
47 }
48 }
49 }
50 return false;
51 }
52 };
53
54
55 class Fraction {
56 public:
57 Fraction() = default;
58 Fraction(int n)
59 : Fraction(n, 1)
60 {
61 }
62 Fraction(int n, int d)
63 : numerator_(n)
64 , denominator_(d)
65 {
66 }
67 ~Fraction() = default;
68
69 void set_num(int value) { numerator_ = value; }
70 void set_den(int value) { denominator_ = value; }
71 int get_num() const { return numerator_; }
72 int get_den() const { return denominator_; }
73 void reduce();
74 int calculate_gcd(int, int) const;
75 private:
76 int numerator_, denominator_;
77 };
78
79 void Fraction::reduce()
80 {
81 const auto gcd = calculate_gcd(numerator_, denominator_);
82 numerator_ = numerator_ / gcd;
83 denominator_ = denominator_ / gcd;
84 }
85
86 int Fraction::calculate_gcd(int a, int b) const
87 {
88 a = std::abs(a);
89 b = std::abs(b);
90 while (b != 0) {
91 int tmp = b;
92 b = a % b;
93 a = tmp;
94 }
95 return a;
96 }
97
98 Fraction operator+(const Fraction& lhs, const Fraction& rhs)
99 {
100 Fraction result{};
101
102 result.set_num((lhs.get_num() * rhs.get_den()) + (lhs.get_den() * rhs.get_num()));
103 result.set_den(lhs.get_den() * rhs.get_den());
104
105 result.reduce();
106
107 return result;
108 }
109
110 Fraction operator-(const Fraction& lhs, const Fraction& rhs)
111 {
112 Fraction result{};
113
114 result.set_num((lhs.get_num() * rhs.get_den()) - (lhs.get_den() * rhs.get_num()));
115 result.set_den(lhs.get_den() * rhs.get_den());
116
117 result.reduce();
118
119 return result;
120 }
121
122 Fraction operator*(const Fraction& lhs, const Fraction& rhs)
123 {
124 Fraction result{};
125
126 result.set_num(lhs.get_num() * rhs.get_num());
127 result.set_den(lhs.get_den() * rhs.get_den());
128
129 result.reduce();
130
131 return result;
132 }
133
134 Fraction operator/(const Fraction& lhs, const Fraction& rhs)
135 {
135 {
136 Fraction result{};
137
138 result.set_num(lhs.get_num() * rhs.get_den());
139 result.set_den(lhs.get_den() * rhs.get_num());
140
141 result.reduce();
142
143 return result;
144 }
145
146 bool operator==(const Fraction &lhs, const Fraction &rhs) {
147 return (((lhs.get_num() * rhs.get_den()) - (rhs.get_num() * lhs.get_den())) == 0);
148 }
149
150 std::ostream &operator<<(std::ostream &os, const Fraction &value) {
151 os << value.get_num() << "/" << value.get_den();
152 return os;
153 }
154
155 // Time: O(n^3 * 4^n) = O(1), n = 4
156 // Space: O(n^2) = O(1)
157 class Solution2 {
158 public:
159 bool judgePoint24(vector& nums) {
160 vector fraction_nums;
161 std::transform(nums.begin(), nums.end(), std::back_inserter(fraction_nums),
162 [](const int num) { return Fraction(num); });
163 return dfs(fraction_nums);
164 }
165
166 private:
167 bool dfs(const vector& nums) {
168 if (nums.size() == 1) {
169 return nums[0] == 24;
170 }
171 static unordered_map> ops =
172 {
173 {'+', std::plus()},
174 {'-', std::minus()},
175 {'*', std::multiplies()},
176 {'/', std::divides()},
177 };
178 for (int i = 0; i < nums.size(); ++i) {
179 for (int j = 0; j < nums.size(); ++j) {
180 if (i == j) {
181 continue;
182 }
183 vector next_nums;
184 for (int k = 0; k < nums.size(); ++k) {
185 if (k == i || k == j) {
186 continue;
187 }
188 next_nums.emplace_back(nums[k]);
189 }
190 for (const auto& op : ops) {
191 if (((op.first == '+' || op.first == '*') && i > j) ||
192 (op.first == '/' && nums[j] == 0)) {
193 continue;
194 }
195 next_nums.emplace_back(op.second(nums[i], nums[j]));
196 if (dfs(next_nums)) {
197 return true;
198 }
199 next_nums.pop_back();
200 }
201 }
202 }
203 return false;
204 }
205 };
*******

121. 24 Game(Python)
*******
1 # Time: O(n^3 * 4^n) = O(1), n = 4
2 # Space: O(n^2) = O(1)
3
4 from operator import add, sub, mul, truediv
5 from fractions import Fraction
6
7
8 class Solution(object):
9 def judgePoint24(self, nums):
10 """
11 :type nums: List[int]
12 :rtype: bool
13 """
14 if len(nums) == 1:
15 return abs(nums[0]-24) < 1e-6
16 ops = [add, sub, mul, truediv]
17 for i in xrange(len(nums)):
18 for j in xrange(len(nums)):
19 if i == j:
20 continue
21 next_nums = [nums[k] for k in xrange(len(nums)) if i != k != j]
22 for op in ops:
23 if ((op is add or op is mul) and j > i) or \
24 (op == truediv and nums[j] == 0):
25 continue
26 next_nums.append(op(nums[i], nums[j]))
27 if self.judgePoint24(next_nums):
28 return True
29 next_nums.pop()
30 return False
31
32
33 # Time: O(n^3 * 4^n) = O(1), n = 4
34 # Space: O(n^2) = O(1)
35 class Solution2(object):
36 def judgePoint24(self, nums):
37 """
38 :type nums: List[int]
39 :rtype: bool
40 """
41 def dfs(nums):
42 if len(nums) == 1:
43 return nums[0] == 24
44 ops = [add, sub, mul, truediv]
45 for i in xrange(len(nums)):
46 for j in xrange(len(nums)):
47 if i == j:
48 continue
49 next_nums = [nums[k] for k in xrange(len(nums))
50 if i != k != j]
51 for op in ops:
52 if ((op is add or op is mul) and j > i) or \
53 (op == truediv and nums[j] == 0):
54 continue
55 next_nums.append(op(nums[i], nums[j]))
56 if dfs(next_nums):
57 return True
58 next_nums.pop()
59 return False
60
61 return dfs(map(Fraction, nums))
62
*************

122. K Empty Slots


*************

You have n bulbs in a row numbered from 1 to n. Initially, all the bulbs are turned off. We turn onexactly one bulb every day
until all bulbs are on after n days.

You are given an array bulbs of length n where bulbs[i] = x means that on the (i+1)th day, we will turn on the bulb at position
x where i is 0-indexed and x is 1-indexed.

Given an integer k , return the minimum day number such that there exists two turned on bulbs that have exactly k bulbs
between them that are all turned off. If there isn't such day, return -1.

Example 1:

Input: bulbs = [1,3,2], k = 1


Output: 2
Explanation:
On the first day: bulbs[0] = 1, first bulb is turned on: [1,0,0]
On the second day: bulbs[1] = 3, third bulb is turned on: [1,0,1]
On the third day: bulbs[2] = 2, second bulb is turned on: [1,1,1]
We return 2 because on the second day, there were two on bulbs with one off bulb between them.

Example 2:

Input: bulbs = [1,2,3], k = 1


Output: -1

Constraints:

n == bulbs.length
1 <= n <= 2 * 10 4
1 <= bulbs[i] <= n
bulbs is a permutation of numbers from 1 to n.
0 <= k <= 2 * 10 4
*************

122. K Empty Slots(C++)


*************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int kEmptySlots(vector& flowers, int k) {
7 vector days(flowers.size());
8 for (int i = 0; i < flowers.size(); ++i) {
9 days[flowers[i] - 1] = i;
10 }
11 auto result = numeric_limits::max();
12 for (int i = 0, left = 0, right = k + 1; right < days.size(); ++i) {
13 if (days[i] < days[left] || days[i] <= days[right]) {
14 if (i == right) {
15 result = min(result, max(days[left], days[right]));
16 }
17 left = i, right = k + 1 + i;
18 }
19 }
20 return (result == numeric_limits::max()) ? -1 : result + 1;
21 }
22 };
*************

122. K Empty Slots(Python)


*************

1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 def kEmptySlots(self, flowers, k):
6 """
7 :type flowers: List[int]
8 :type k: int
9 :rtype: int
10 """
11 days = [0] * len(flowers)
12 for i in xrange(len(flowers)):
13 days[flowers[i]-1] = i
14 result = float("inf")
15 i, left, right = 0, 0, k+1
16 while right < len(days):
17 if days[i] < days[left] or days[i] <= days[right]:
18 if i == right:
19 result = min(result, max(days[left], days[right]))
20 left, right = i, k+1+i
21 i += 1
22 return -1 if result == float("inf") else result+1
23
24
***********************

123. Redundant Connection II


***********************

In this problem, a rooted tree is a directed graph such that, there is exactly one node (the root) for which all other nodes are
descendants of this node, plus every node has exactly one parent, except for the root node which has no parents.

The given input is a directed graph that started as a rooted tree withn nodes (with distinct values from 1 to n), with one
additional directed edge added. The added edge has two different vertices chosen from 1 to n, and was not an edge that
already existed.

The resulting graph is given as a 2D-array of edges. Each element of edges is a pair [ui, v i] that represents a directed edge
connecting nodes ui and v i, where ui is a parent of child v i.

Return an edge that can be removed so that the resulting graph is a rooted tree ofn nodes. If there are multiple answers,
return the answer that occurs last in the given 2D-array.

Example 1:

Input: edges = [[1,2],[1,3],[2,3]]


Output: [2,3]

Example 2:
Input: edges = [[1,2],[2,3],[3,4],[4,1],[1,5]]
Output: [4,1]

Constraints:

n == edges.length
3 <= n <= 1000
edges[i].length == 2
1 <= ui, v i <= n
ui != v i
***********************

123. Redundant Connection II(C++)


***********************

1 // Time: O(nlog*n) ~= O(n), n is the length of the positions


2 // Space: O(n)
3
4 class Solution {
5 public:
6 vector findRedundantDirectedConnection(vector>& edges) {
7 vector cand1, cand2;
8 unordered_map parent;
9 for (const auto& edge : edges) {
10 if (!parent.count(edge[1])) {
11 parent[edge[1]] = edge[0];
12 } else {
13 cand1 = {parent[edge[1]], edge[1]};
14 cand2 = edge;
15 }
16 }
17
18 UnionFind union_find(edges.size() + 1);
19 for (const auto& edge : edges) {
20 if (edge == cand2) {
21 continue;
22 }
23 if (!union_find.union_set(edge[0], edge[1])) {
24 return cand2.empty() ? edge : cand1;
25 }
26 }
27 return cand2;
28 }
29
30 private:
31 class UnionFind {
32 public:
33 UnionFind(const int n) : set_(n) {
34 iota(set_.begin(), set_.end(), 0);
35 }
36
37 int find_set(const int x) {
38 if (set_[x] != x) {
39 set_[x] = find_set(set_[x]); // Path compression.
40 }
41 return set_[x];
42 }
43
44 bool union_set(const int x, const int y) {
45 int x_root = find_set(x), y_root = find_set(y);
46 if (x_root == y_root) {
47 return false;
48 }
49 set_[min(x_root, y_root)] = max(x_root, y_root);
50 return true;
51 }
52
53 private:
54 vector set_;
55 };
56 };
***********************

123. Redundant Connection II(Python)


***********************

1 # Time: O(nlog*n) ~= O(n), n is the length of the positions


2 # Space: O(n)
3
4 class UnionFind(object):
5 def __init__(self, n):
6 self.set = range(n)
7
8 def find_set(self, x):
9 if self.set[x] != x:
10 self.set[x] = self.find_set(self.set[x]) # path compression.
11 return self.set[x]
12
13 def union_set(self, x, y):
14 x_root, y_root = map(self.find_set, (x, y))
15 if x_root == y_root:
16 return False
17 self.set[min(x_root, y_root)] = max(x_root, y_root)
18 return True
19
20
21 class Solution(object):
22 def findRedundantDirectedConnection(self, edges):
23 """
24 :type edges: List[List[int]]
25 :rtype: List[int]
26 """
27 cand1, cand2 = [], []
28 parent = {}
29 for edge in edges:
30 if edge[1] not in parent:
31 parent[edge[1]] = edge[0]
32 else:
33 cand1 = [parent[edge[1]], edge[1]]
34 cand2 = edge
35
36 union_find = UnionFind(len(edges)+1)
37 for edge in edges:
38 if edge == cand2:
39 continue
40 if not union_find.union_set(*edge):
41 return cand1 if cand2 else edge
42 return cand2
43
******************************************

124. Maximum Sum of 3 Non-Overlapping Subarrays


******************************************

Given an integer array nums and an integer k , find three non-overlapping subarrays of length k with maximum sum and return
them.

Return the result as a list of indices representing the starting position of each interval 0( -indexed). If there are multiple
answers, return the lexicographically smallest one.

Example 1:

Input: nums = [1,2,1,2,6,7,5,1], k = 2


Output: [0,3,5]
Explanation: Subarrays [1, 2], [2, 6], [7, 5] correspond to the starting indices [0, 3, 5].
We could have also taken [2, 1], but an answer of [1, 3, 5] would be lexicographically larger.

Example 2:

Input: nums = [1,2,1,2,1,2,1,2,1], k = 2


Output: [0,2,4]

Constraints:

1 <= nums.length <= 2 * 10 4


1 <= nums[i] < 2 16
1 <= k <= floor(nums.length / 3)
******************************************

124. Maximum Sum of 3 Non-Overlapping Subarrays(C++)


******************************************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 vector maxSumOfThreeSubarrays(vector& nums, int k) {
7 const auto n = nums.size();
8 vector accu = {0};
9 for (const auto& num : nums) {
10 accu.emplace_back(accu.back() + num);
11 }
12
13 vector left_pos(n);
14 for (int i = k, total = accu[k] - accu[0]; i < n; ++i) {
15 if (accu[i + 1] - accu[i + 1 - k] > total) {
16 left_pos[i] = i + 1 - k;
17 total = accu[i + 1] - accu[i + 1 - k];
18 } else {
19 left_pos[i] = left_pos[i - 1];
20 }
21 }
22
23 vector right_pos(n, n - k);
24 for (int i = n - k - 1, total = accu[n] - accu[n - k]; i >= 0; --i) {
25 if (accu[i + k] - accu[i] > total) {
26 right_pos[i] = i;
27 total = accu[i + k] - accu[i];
28 } else {
29 right_pos[i] = right_pos[i + 1];
30 }
31 }
32
33 vector result(3);
34 for (int i = k, max_sum = 0; i <= n - 2 * k; ++i) {
35 auto left = left_pos[i - 1], right = right_pos[i + k];
36 auto total = (accu[i + k] - accu[i]) +
37 (accu[left + k] - accu[left]) +
38 (accu[right + k] - accu[right]);
39 if (total > max_sum) {
40 max_sum = total;
41 result = {left, i, right};
42 }
43 }
44 return result;
45 }
46 };
******************************************

124. Maximum Sum of 3 Non-Overlapping


Subarrays(Python)
******************************************

1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 def maxSumOfThreeSubarrays(self, nums, k):
6 """
7 :type nums: List[int]
8 :type k: int
9 :rtype: List[int]
10 """
11 n = len(nums)
12 accu = [0]
13 for num in nums:
14 accu.append(accu[-1]+num)
15
16 left_pos = [0] * n
17 total = accu[k]-accu[0]
18 for i in xrange(k, n):
19 if accu[i+1]-accu[i+1-k] > total:
20 left_pos[i] = i+1-k
21 total = accu[i+1]-accu[i+1-k]
22 else:
23 left_pos[i] = left_pos[i-1]
24
25 right_pos = [n-k] * n
26 total = accu[n]-accu[n-k]
27 for i in reversed(xrange(n-k)):
28 if accu[i+k]-accu[i] > total:
29 right_pos[i] = i
30 total = accu[i+k]-accu[i]
31 else:
32 right_pos[i] = right_pos[i+1]
33
34 result, max_sum = [], 0
35 for i in xrange(k, n-2*k+1):
36 left, right = left_pos[i-1], right_pos[i+k]
37 total = (accu[i+k]-accu[i]) + \
38 (accu[left+k]-accu[left]) + \
39 (accu[right+k]-accu[right])
40 if total > max_sum:
41 max_sum = total
42 result = [left, i, right]
43 return result
44
**********************

125. Stickers to Spell Word


**********************

We are given n different types of stickers. Each sticker has a lowercase English word on it.

You would like to spell out the given stringtarget by cutting individual letters from your collection of stickers and rearranging
them. You can use each sticker more than once if you want, and you have infinite quantities of each sticker.

Return the minimum number of stickers that you need to spell outtarget. If the task is impossible, return -1.

Note: In all test cases, all words were chosen randomly from the1000 most common US English words, and target was
chosen as a concatenation of two random words.

Example 1:

Input: stickers = ["with","example","science"], target = "thehat"


Output: 3
Explanation:
We can use 2 "with" stickers, and 1 "example" sticker.
After cutting and rearrange the letters of those stickers, we can form the target "thehat".
Also, this is the minimum number of stickers necessary to form the target string.

Example 2:

Input: stickers = ["notice","possible"], target = "basicbasic"


Output: -1
Explanation:
We cannot form the target "basicbasic" from cutting letters from the given stickers.

Constraints:

n == stickers.length
1 <= n <= 50
1 <= stickers[i].length <= 10
1 <= target <= 15
stickers[i] and target consist of lowercase English letters.
**********************

125. Stickers to Spell Word(C++)


**********************

1 // Time: O(T * S^T)


2 // Space: O(T * S^T)
3
4 class Solution {
5 public:
6 int minStickers(vector& stickers, string target) {
7 vector> sticker_counts(stickers.size(), vector(26));
8 unordered_map dp;
9 for (int i = 0; i < stickers.size(); ++i) {
10 for (const auto& c : stickers[i]) {
11 ++sticker_counts[i][c - 'a'];
12 }
13 }
14 dp[""] = 0;
15 return minStickersHelper(sticker_counts, target, &dp);
16 }
17
18 private:
19 int minStickersHelper(const vector>& sticker_counts, const string& target,
20 unordered_map *dp) {
21 if (dp->count(target)) {
22 return (*dp)[target];
23 }
24 int result = numeric_limits::max();
25 vector target_count(26);
26 for (const auto& c : target) {
27 ++target_count[c - 'a'];
28 }
29 for (const auto& sticker_count : sticker_counts) {
30 if (sticker_count[target[0] - 'a'] == 0) {
31 continue;
32 }
33 string new_target;
34 for (int i = 0; i < target_count.size(); ++i) {
35 if (target_count[i] - sticker_count[i] > 0) {
36 new_target += string(target_count[i] - sticker_count[i], 'a' + i);
37 }
38 }
39 if (new_target.length() != target.length()) {
40 int num = minStickersHelper(sticker_counts, new_target, dp);
41 if (num != -1) {
42 result = min(result, 1 + num);
43 }
44 }
45 }
46 (*dp)[target] = (result == numeric_limits::max()) ? -1 : result;
47 return (*dp)[target];
48 }
49 };
**********************

125. Stickers to Spell Word(Python)


**********************

1 # Time: O(T * S^T)


2 # Space: O(T * S^T)
3
4 import collections
5
6
7 class Solution(object):
8 def minStickers(self, stickers, target):
9 """
10 :type stickers: List[str]
11 :type target: str
12 :rtype: int
13 """
14 def minStickersHelper(sticker_counts, target, dp):
15 if "".join(target) in dp:
16 return dp["".join(target)]
17 target_count = collections.Counter(target)
18 result = float("inf")
19 for sticker_count in sticker_counts:
20 if sticker_count[target[0]] == 0:
21 continue
22 new_target = []
23 for k in target_count.keys():
24 if target_count[k] > sticker_count[k]:
25 new_target += [k]*(target_count[k] - sticker_count[k])
26 if len(new_target) != len(target):
27 num = minStickersHelper(sticker_counts, new_target, dp)
28 if num != -1:
29 result = min(result, 1+num)
30 dp["".join(target)] = -1 if result == float("inf") else result
31 return dp["".join(target)]
32
33 sticker_counts = map(collections.Counter, stickers)
34 dp = { "":0 }
35 return minStickersHelper(sticker_counts, target, dp)
36
***************

126. Falling Squares


***************

There are several squares being dropped onto the X-axis of a 2D plane.

You are given a 2D integer arraypositions where positions[i] = [left i, sideLength i] represents the ith square with a side length of
sideLength i that is dropped with its left edge aligned with X-coordinate lefti.

Each square is dropped one at a time from a height above any landed squares. It then falls downward (negative Y direction)
until it either lands on the top side of another square or on the X-axis. A square brushing the left/right side of another
square does not count as landing on it. Once it lands, it freezes in place and cannot be moved.

After each square is dropped, you must record the height of the current tallest stack of squares.

Return an integer array ans where ans[i] represents the height described above after dropping the ith square.

Example 1:

Input: positions = [[1,2],[2,3],[6,1]]


Output: [2,5,5]
Explanation:
After the first drop, the tallest stack is square 1 with a height of 2.
After the second drop, the tallest stack is squares 1 and 2 with a height of 5.
After the third drop, the tallest stack is still squares 1 and 2 with a height of 5.
Thus, we return an answer of [2, 5, 5].

Example 2:
Input: positions = [[100,100],[200,100]]
Output: [100,100]
Explanation:
After the first drop, the tallest stack is square 1 with a height of 100.
After the second drop, the tallest stack is either square 1 or square 2, both with heights of 100.
Thus, we return an answer of [100, 100].
Note that square 2 only brushes the right side of square 1, which does not count as landing on it.

Constraints:

1 <= positions.length <= 1000


1 <= lefti <= 108
1 <= sideLength i <= 106
***************

126. Falling Squares(C++)


***************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 vector fallingSquares(vector>& positions) {
7 vector result;
8 map heights;
9 int maxH = heights[-1] = 0;
10 for (const auto& p : positions) {
11 auto it0 = heights.upper_bound(p[0]);
12 auto it1 = heights.lower_bound(p[0] + p[1]);
13 int h0 = prev(it0)->second;
14 int h1 = prev(it1)->second;
15 for (auto it = it0; it != it1; ++it) {
16 h0 = max(h0, it->second);
17 }
18 heights.erase(it0, it1);
19 heights[p[0]] = h0 + p[1];
20 heights[p[0] + p[1]] = h1;
21 maxH = max(maxH, h0 + p[1]);
22 result.emplace_back(maxH);
23 }
24 return result;
25 }
26 };
27
28 // Time: O(nlogn)
29 // Space: O(n)
30 // Segment Tree solution.
31 class Solution2 {
32 public:
33 vector fallingSquares(vector>& positions) {
34 set index;
35 for (const auto& position : positions) {
36 index.emplace(position[0]);
37 index.emplace(position[0] + position[1] - 1);
38 }
39 SegmentTree tree(index.size());
40 auto max_height = 0;
41 vector result;
42 for (const auto& position : positions) {
43 const auto L = distance(index.begin(), index.find(position[0]));
44 const auto R = distance(index.begin(), index.find(position[0] + position[1] - 1));
45 const auto h = tree.query(L, R) + position[1];
46 tree.update(L, R, h);
47 max_height = max(max_height, h);
48 result.emplace_back(max_height);
49 }
50 return result;
51 }
52
53 private:
54 class SegmentTree {
55 public:
56 SegmentTree(int N)
57 : N_(N),
58 tree_(2 * N),
59 lazy_(N)
60 {
61 H_ = 1;
62 while ((1 << H_) < N) {
63 ++H_;
64 }
65 }
66
67 void update(int L, int R, int h) {
68 L += N_; R += N_;
69 int L0 = L, R0 = R;
70 while (L <= R) {
71 if ((L & 1) == 1) {
72 apply(L++, h);
73 }
74 if ((R & 1) == 0) {
75 apply(R--, h);
76 }
77 L >>= 1; R >>= 1;
78 }
79 pull(L0); pull(R0);
80 }
81
82 int query(int L, int R) {
83 L += N_; R += N_;
84 auto result = 0;
85 push(L); push(R);
86 while (L <= R) {
87 if ((L & 1) == 1) {
88 result = max(result, tree_[L++]);
89 }
90 if ((R & 1) == 0) {
91 result = max(result, tree_[R--]);
92 }
93 L >>= 1; R >>= 1;
94 }
95 return result;
96 }
97
98 private:
99 int N_, H_;
100 vector tree_, lazy_;
101
102 void apply(int x, int val) {
103 tree_[x] = max(tree_[x], val);
104 if (x < N_) {
105 lazy_[x] = max(lazy_[x], val);
106 }
107 }
108
109 void pull(int x) {
110 while (x > 1) {
111 x >>= 1;
112 tree_[x] = max(tree_[x * 2], tree_[x * 2 + 1]);
113 tree_[x] = max(tree_[x], lazy_[x]);
114 }
115 }
116
117 void push(int x) {
118 for (int h = H_; h > 0; --h) {
119 int y = x >> h;
120 if (lazy_[y] > 0) {
121 apply(y * 2, lazy_[y]);
122 apply(y * 2 + 1, lazy_[y]);
123 lazy_[y] = 0;
124 }
125 }
126 }
127 };
128 };
129
130
131 // Time: O(n * sqrt(n))
132 // Space: O(n)
133 class Solution3 {
134 public:
135 vector fallingSquares(vector>& positions) {
135 vector fallingSquares(vector>& positions) {
136 set index;
137 for (const auto& position : positions) {
138 index.emplace(position[0]);
139 index.emplace(position[0] + position[1] - 1);
140 }
141 const auto W = index.size();
142 const auto B = static_cast(sqrt(W));
143 vector heights(W);
144 vector blocks(B + 2), blocks_read(B + 2);
145
146 auto max_height = 0;
147 vector result;
148 for (const auto& position : positions) {
149 const auto L = distance(index.begin(), index.find(position[0]));
150 const auto R = distance(index.begin(), index.find(position[0] + position[1] - 1));
151 const auto h = query(B, L, R, heights, blocks, blocks_read) + position[1];
152 update(B, h, L, R, &heights, &blocks, &blocks_read);
153 max_height = max(max_height, h);
154 result.emplace_back(max_height);
155 }
156 return result;
157 }
158
159 private:
160 int query(const int B,
161 int left, int right,
162 const vector& heights,
163 const vector& blocks, const vector& blocks_read) {
164 int result = 0;
165 while (left % B > 0 && left <= right) {
166 result = max(result, max(heights[left], blocks[left / B]));
167 result = max(result, blocks[left / B]);
168 ++left;
169 }
170 while (right % B != B - 1 && left <= right) {
171 result = max(result, max(heights[right], blocks[right / B]));
172 --right;
173 }
174 while (left <= right) {
175 result = max(result, max(blocks[left / B], blocks_read[left / B]));
176 left += B;
177 }
178 return result;
179 }
180
181 void update(const int B, const int h,
182 int left, int right,
183 vector *heights,
184 vector *blocks, vector *blocks_read) {
185 while (left % B > 0 && left <= right) {
186 (*heights)[left] = max((*heights)[left], h);
187 (*blocks_read)[left / B] = max((*blocks_read)[left / B], h);
188 ++left;
189 }
190 while (right % B != B - 1 && left <= right) {
191 (*heights)[right] = max((*heights)[right], h);
192 (*blocks_read)[right / B] = max((*blocks_read)[right / B], h);
193 --right;
194 }
195 while (left <= right) {
196 (*blocks)[left / B] = max((*blocks)[left / B], h);
197 left += B;
198 }
199 }
200 };
201
202
203 // Time: O(n^2)
204 // Space: O(n)
205 class Solution4 {
206 public:
207 vector fallingSquares(vector>& positions) {
208 vector heights(positions.size());
208 vector heights(positions.size());
209 for (int i = 0; i < positions.size(); ++i) {
210 int left_i = positions[i][0], size_i = positions[i][1];
211 int right_i = left_i + size_i;
212 heights[i] += size_i;
213 for (int j = i + 1; j < positions.size(); ++j) {
214 int left_j = positions[j][0], size_j = positions[j][1];
215 int right_j = left_j + size_j;
216 if (left_j < right_i and left_i < right_j) { // intersect
217 heights[j] = max(heights[j], heights[i]);
218 }
219 }
220 }
221
222 vector result;
223 for (const auto& height : heights) {
224 result.emplace_back(result.empty() ? height : max(result.back(), height));
225 }
226 return result;
227 }
228 };
***************

126. Falling Squares(Python)


***************

1 # Time: O(n^2), could be improved to O(nlogn) in cpp by ordered map (bst)


2 # Space: O(n)
3
4 import bisect
5
6
7 class Solution(object):
8 def fallingSquares(self, positions):
9 result = []
10 pos = [-1]
11 heights = [0]
12 maxH = 0
13 for left, side in positions:
14 l = bisect.bisect_right(pos, left)
15 r = bisect.bisect_left(pos, left+side)
16 high = max(heights[l-1:r] or [0]) + side
17 pos[l:r] = [left, left+side] # Time: O(n)
18 heights[l:r] = [high, heights[r-1]] # Time: O(n)
19 maxH = max(maxH, high)
20 result.append(maxH)
21 return result
22
23
24 class SegmentTree(object):
25 def __init__(self, N,
26 query_fn=min,
27 update_fn=lambda x, y: y,
28 default_val=float("inf")):
29 self.N = N
30 self.H = (N-1).bit_length()
31 self.query_fn = query_fn
32 self.update_fn = update_fn
33 self.default_val = default_val
34 self.tree = [default_val] * (2 * N)
35 self.lazy = [None] * N
36
37 def __apply(self, x, val):
38 self.tree[x] = self.update_fn(self.tree[x], val)
39 if x < self.N:
40 self.lazy[x] = self.update_fn(self.lazy[x], val)
41
42 def update(self, L, R, h):
43 def pull(x):
44 while x > 1:
45 x //= 2
46 self.tree[x] = self.query_fn(self.tree[x*2], self.tree[x*2 + 1])
47 if self.lazy[x] is not None:
48 self.tree[x] = self.update_fn(self.tree[x], self.lazy[x])
49
50 L += self.N
51 R += self.N
52 L0, R0 = L, R
53 while L <= R:
54 if L & 1:
55 self.__apply(L, h)
56 L += 1
57 if R & 1 == 0:
58 self.__apply(R, h)
59 R -= 1
60 L //= 2
61 R //= 2
62 pull(L0)
63 pull(R0)
64
65 def query(self, L, R):
66 def push(x):
67 n = 2**self.H
68 while n != 1:
69 y = x // n
70 if self.lazy[y] is not None:
71 self.__apply(y*2, self.lazy[y])
72 self.__apply(y*2 + 1, self.lazy[y])
73 self.lazy[y] = None
74 n //= 2
75
76 result = self.default_val
77 if L > R:
78 return result
79
80 L += self.N
81 R += self.N
82 push(L)
83 push(R)
84 while L <= R:
85 if L & 1:
86 result = self.query_fn(result, self.tree[L])
87 L += 1
88 if R & 1 == 0:
89 result = self.query_fn(result, self.tree[R])
90 R -= 1
91 L //= 2
92 R //= 2
93 return result
94
95 def data(self):
96 showList = []
97 for i in xrange(self.N):
98 showList.append(self.query(i, i))
99 return showList
100
101
102 class SegmentTree2(object):
103 def __init__(self, nums,
104 query_fn=min,
105 update_fn=lambda x, y: y,
106 default_val=float("inf")):
107 """
108 initialize your data structure here.
109 :type nums: List[int]
110 """
111 N = len(nums)
112 self.__original_length = N
113 self.__tree_length = 2**(N.bit_length() + (N&(N-1) != 0))-1
114 self.__query_fn = query_fn
115 self.__update_fn = update_fn
116 self.__default_val = default_val
117 self.__tree = [default_val for _ in range(self.__tree_length)]
118 self.__lazy = [None for _ in range(self.__tree_length)]
119 self.__constructTree(nums, 0, self.__original_length-1, 0)
120
121 def update(self, i, j, val):
122 self.__updateTree(val, i, j, 0, self.__original_length-1, 0)
123
124 def query(self, i, j):
125 return self.__queryRange(i, j, 0, self.__original_length-1, 0)
126
127 def __constructTree(self, nums, left, right, idx):
128 if left > right:
129 return
130 if left == right:
131 self.__tree[idx] = self.__update_fn(self.__tree[idx], nums[left])
132 return
133 mid = left + (right-left)//2
134 self.__constructTree(nums, left, mid, idx*2 + 1)
135 self.__constructTree(nums, mid+1, right, idx*2 + 2)
135 self.__constructTree(nums, mid+1, right, idx*2 + 2)
136 self.__tree[idx] = self.__query_fn(self.__tree[idx*2 + 1], self.__tree[idx*2 + 2])
137
138 def __apply(self, left, right, idx, val):
139 self.__tree[idx] = self.__update_fn(self.__tree[idx], val)
140 if left != right:
141 self.__lazy[idx*2 + 1] = self.__update_fn(self.__lazy[idx*2 + 1], val)
142 self.__lazy[idx*2 + 2] = self.__update_fn(self.__lazy[idx*2 + 2], val)
143
144 def __updateTree(self, val, range_left, range_right, left, right, idx):
145 if left > right:
146 return
147 if self.__lazy[idx] is not None:
148 self.__apply(left, right, idx, self.__lazy[idx])
149 self.__lazy[idx] = None
150 if range_left > right or range_right < left:
151 return
152 if range_left <= left and right <= range_right:
153 self.__apply(left, right, idx, val)
154 return
155 mid = left + (right-left)//2
156 self.__updateTree(val, range_left, range_right, left, mid, idx*2 + 1)
157 self.__updateTree(val, range_left, range_right, mid+1, right, idx*2 + 2)
158 self.__tree[idx] = self.__query_fn(self.__tree[idx*2 + 1],
159 self.__tree[idx*2 + 2])
160
161 def __queryRange(self, range_left, range_right, left, right, idx):
162 if left > right:
163 return self.__default_val
164 if self.__lazy[idx] is not None:
165 self.__apply(left, right, idx, self.__lazy[idx])
166 self.__lazy[idx] = None
167 if right < range_left or left > range_right:
168 return self.__default_val
169 if range_left <= left and right <= range_right:
170 return self.__tree[idx]
171 mid = left + (right-left)//2
172 return self.__query_fn(self.__queryRange(range_left, range_right, left, mid, idx*2 + 1),
173 self.__queryRange(range_left, range_right, mid + 1, right, idx*2 + 2))
174
175
176 # Time: O(nlogn)
177 # Space: O(n)
178 # Segment Tree solution.
179 class Solution2(object):
180 def fallingSquares(self, positions):
181 index = set()
182 for left, size in positions:
183 index.add(left)
184 index.add(left+size-1)
185 index = sorted(list(index))
186 tree = SegmentTree(len(index), max, max, 0)
187 # tree = SegmentTree2([0]*len(index), max, max, 0)
188 max_height = 0
189 result = []
190 for left, size in positions:
191 L, R = bisect.bisect_left(index, left), bisect.bisect_left(index, left+size-1)
192 h = tree.query(L, R) + size
193 tree.update(L, R, h)
194 max_height = max(max_height, h)
195 result.append(max_height)
196 return result
197
198
199 # Time: O(n * sqrt(n))
200 # Space: O(n)
201 class Solution3(object):
202 def fallingSquares(self, positions):
203 def query(heights, left, right, B, blocks, blocks_read):
204 result = 0
205 while left % B and left <= right:
206 result = max(result, heights[left], blocks[left//B])
207 left += 1
208 while right % B != B-1 and left <= right:
208 while right % B != B-1 and left <= right:
209 result = max(result, heights[right], blocks[right//B])
210 right -= 1
211 while left <= right:
212 result = max(result, blocks[left//B], blocks_read[left//B])
213 left += B
214 return result
215
216 def update(heights, left, right, B, blocks, blocks_read, h):
217 while left % B and left <= right:
218 heights[left] = max(heights[left], h)
219 blocks_read[left//B] = max(blocks_read[left//B], h)
220 left += 1
221 while right % B != B-1 and left <= right:
222 heights[right] = max(heights[right], h)
223 blocks_read[right//B] = max(blocks_read[right//B], h)
224 right -= 1
225 while left <= right:
226 blocks[left//B] = max(blocks[left//B], h)
227 left += B
228
229 index = set()
230 for left, size in positions:
231 index.add(left)
232 index.add(left+size-1)
233 index = sorted(list(index))
234 W = len(index)
235 B = int(W**.5)
236 heights = [0] * W
237 blocks = [0] * (B+2)
238 blocks_read = [0] * (B+2)
239
240 max_height = 0
241 result = []
242 for left, size in positions:
243 L, R = bisect.bisect_left(index, left), bisect.bisect_left(index, left+size-1)
244 h = query(heights, L, R, B, blocks, blocks_read) + size
245 update(heights, L, R, B, blocks, blocks_read, h)
246 max_height = max(max_height, h)
247 result.append(max_height)
248 return result
249
250
251 # Time: O(n^2)
252 # Space: O(n)
253 class Solution4(object):
254 def fallingSquares(self, positions):
255 """
256 :type positions: List[List[int]]
257 :rtype: List[int]
258 """
259 heights = [0] * len(positions)
260 for i in xrange(len(positions)):
261 left_i, size_i = positions[i]
262 right_i = left_i + size_i
263 heights[i] += size_i
264 for j in xrange(i+1, len(positions)):
265 left_j, size_j = positions[j]
266 right_j = left_j + size_j
267 if left_j < right_i and left_i < right_j: # intersect
268 heights[j] = max(heights[j], heights[i])
269
270 result = []
271 for height in heights:
272 result.append(max(result[-1], height) if result else height)
273 return result
274
*****************************

127. Number of Distinct Islands II


*****************************

You are given an m x n binary matrix grid. An island is a group of 1's (representing land) connected 4-directionally (horizontal
or vertical.) You may assume all four edges of the grid are surrounded by water.

An island is considered to be the same as another if they have the same shape, or have the same shape afterrotation (90,
180, or 270 degrees only) or reflection (left/right direction or up/down direction).

Return the number of distinct islands.

Example 1:

Input: grid = [[1,1,0,0,0],[1,0,0,0,0],[0,0,0,0,1],[0,0,0,1,1]]


Output: 1
Explanation: The two islands are considered the same because if we make a 180 degrees clockwise rotation on the first island, then two island

Example 2:
Input: grid = [[1,1,0,0,0],[1,1,0,0,0],[0,0,0,1,1],[0,0,0,1,1]]
Output: 1

Constraints:

m == grid.length
n == grid[i].length
1 <= m, n <= 50
grid[i][j] is either 0 or 1.
*****************************

127. Number of Distinct Islands II(C++)


*****************************

1 // Time: O((m * n) * log(m * n))


2 // Space: O(m * n)
3
4 class Solution {
5 public:
6 int numDistinctIslands2(vector>& grid) {
7 unordered_set>, VectorHash> islands;
8 for (int i = 0; i < grid.size(); ++i) {
9 for (int j = 0; j < grid[i].size(); ++j) {
10 if (grid[i][j] == 1) {
11 vector> island;
12 if (dfs(i, j, &grid, &island)) {
13 islands.emplace(normalize(island));
14 }
15 }
16 }
17 }
18 return islands.size();
19 }
20
21 private:
22 struct VectorHash {
23 size_t operator()(const std::vector>& v) const {
24 size_t seed = 0;
25 for (const auto& i : v) {
26 seed ^= std::hash{}(i.first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
27 seed ^= std::hash{}(i.second) + 0x9e3779b9 + (seed<<6) + (seed>>2);
28 }
29 return seed;
30 }
31 };
32
33 bool dfs(const int i, const int j,
34 vector> *grid, vector> *island) {
35
36 static const vector> directions{{1, 0}, {-1, 0},
37 {0, 1}, {0, -1}};
38
39 if (i < 0 || i >= grid->size() ||
40 j < 0 || j >= (*grid)[0].size() ||
41 (*grid)[i][j] <= 0) {
42 return false;
43 }
44 (*grid)[i][j] *= -1;
45 island->emplace_back(i, j);
46 for (const auto& direction : directions) {
47 dfs(i + direction.first, j + direction.second, grid, island);
48 }
49 return true;
50 }
51
52 vector> normalize(const vector>& island) {
53 vector>> shapes(8);
54 for (const auto& p : island) {
55 int x, y;
56 tie(x, y) = p;
57 vector> rotations_and_reflections{{ x, y}, { x, -y}, {-x, y}, {-x, -y},
58 { y, x}, { y, -x}, {-y, x}, {-y, -x}};
59 for (int i = 0; i < rotations_and_reflections.size(); ++i) {
60 shapes[i].emplace_back(rotations_and_reflections[i]);
61 }
62 }
63 for (auto& shape : shapes) {
64 sort(shape.begin(), shape.end()); // Time: O(ilogi), i is the size of the island, the max would be (m * n)
65 const auto origin = shape.front();
66 for (auto& p : shape) {
67 p = {p.first - origin.first,
68 p.second - origin.second};
69 }
70 }
71 return *min_element(shapes.begin(), shapes.end());
72 }
73 };
*****************************

127. Number of Distinct Islands II(Python)


*****************************

1 # Time: O((m * n) * log(m * n))


2 # Space: O(m * n)
3
4 class Solution(object):
5 def numDistinctIslands2(self, grid):
6 """
7 :type grid: List[List[int]]
8 :rtype: int
9 """
10 directions = [(0, -1), (0, 1), (-1, 0), (1, 0)]
11
12 def dfs(i, j, grid, island):
13 if not (0 <= i < len(grid) and \
14 0 <= j < len(grid[0]) and \
15 grid[i][j] > 0):
16 return False
17 grid[i][j] *= -1
18 island.append((i, j))
19 for d in directions:
20 dfs(i+d[0], j+d[1], grid, island)
21 return True
22
23 def normalize(island):
24 shapes = [[] for _ in xrange(8)]
25 for x, y in island:
26 rotations_and_reflections = [[ x, y], [ x, -y], [-x, y], [-x, -y],
27 [ y, x], [ y, -x], [-y, x], [-y, -x]]
28 for i in xrange(len(rotations_and_reflections)):
29 shapes[i].append(rotations_and_reflections[i])
30 for shape in shapes:
31 shape.sort() # Time: O(ilogi), i is the size of the island, the max would be (m * n)
32 origin = list(shape[0])
33 for p in shape:
34 p[0] -= origin[0]
35 p[1] -= origin[1]
36 return min(shapes)
37
38 islands = set()
39 for i in xrange(len(grid)):
40 for j in xrange(len(grid[0])):
41 island = []
42 if dfs(i, j, grid, island):
43 islands.add(str(normalize(island)))
44 return len(islands)
45
************

128. Range Module


************

A Range Module is a module that tracks ranges of numbers. Design a data structure to track the ranges represented as
half-open intervals and query about them.

A half-open interval [left, right) denotes all the real numbers x where left <= x < right .

Implement the RangeModule class:

RangeModule() Initializes the object of the data structure.


void addRange(int left, int right) Adds the half-open interval [left, right) ,
tracking every real number in that interval. Adding an
interval that partially overlaps with currently tracked numbers should add any numbers in the interval [left, right) that are
not already tracked.

boolean queryRange(int left, int right) Returns true if every real number in the interval [left, right) is currently being tracked, and
false otherwise.

void removeRange(int left, int right) Stops tracking every real number currently being tracked in thehalf-open interval [left,
right) .

Example 1:

Input
["RangeModule", "addRange", "removeRange", "queryRange", "queryRange", "queryRange"]
[[], [10, 20], [14, 16], [10, 14], [13, 15], [16, 17]]
Output
[null, null, null, true, false, true]

Explanation
RangeModule rangeModule = new RangeModule();
rangeModule.addRange(10, 20);
rangeModule.removeRange(14, 16);
rangeModule.queryRange(10, 14); // return True,(Every number in [10, 14) is being tracked)
rangeModule.queryRange(13, 15); // return False,(Numbers like 14, 14.03, 14.17 in [13, 15) are not being tracked)
rangeModule.queryRange(16, 17); // return True, (The number 16 in [16, 17) is still being tracked, despite the remove operation)

Constraints:

1 <= left < right <= 10 9


At most 104 calls will be made to addRange, queryRange, and removeRange .
************

128. Range Module(C++)


************

1 // Time: addRange: O(n)


2 // removeRange: O(n)
3 // queryRange: O(logn)
4 // Space: O(n)
5
6 class RangeModule {
7 public:
8 RangeModule() {
9
10 }
11
12 // Time: O(n)
13 void addRange(int left, int right) {
14 vector> tmp;
15 int i = 0;
16 for (const auto& interval: intervals_) {
17 if (right < interval.first ) {
18 tmp.emplace_back(left, right);
19 break;
20 } else if (interval.second < left) {
21 tmp.emplace_back(interval);
22 } else {
23 left = min(left, interval.first);
24 right = max(right, interval.second);
25 }
26 ++i;
27 }
28 if (i == intervals_.size()) {
29 tmp.emplace_back(left, right);
30 }
31 while (i < intervals_.size()) {
32 tmp.emplace_back(intervals_[i++]);
33 }
34 swap(intervals_, tmp);
35 }
36
37 // Time: O(logn)
38 bool queryRange(int left, int right) {
39 const auto it = lower_bound(intervals_.begin(), intervals_.end(), make_pair(left, right),
40 [](const pair& lhs,
41 const pair& rhs) {
42 return less{}(lhs.second, rhs.first);
43 });
44 return it != intervals_.end() && it->first <= left && it->second >= right;
45 }
46
47 // Time: O(logn)
48 bool queryRange2(int left, int right) {
49 auto it = lower_bound(intervals_.begin(), intervals_.end(), make_pair(left, numeric_limits::max()));
50 if (it != intervals_.begin()) {
51 it = prev(it);
52 }
53 return it != intervals_.end() && it->first <= left && it->second >= right;
54 }
55
56 // Time: O(n)
57 void removeRange(int left, int right) {
58 vector> tmp;
59 for (const auto& interval : intervals_) {
60 if (interval.second <= left || interval.first >= right) {
61 tmp.emplace_back(interval);
62 } else {
63 if (interval.first < left) {
64 tmp.emplace_back(interval.first, left);
65 }
66 if (right < interval.second) {
67 tmp.emplace_back(right, interval.second);
68 }
69 }
70 }
71 swap(intervals_, tmp);
72 }
73
74 private:
75 vector> intervals_;
76 };
77
78 /**
79 * Your RangeModule object will be instantiated and called as such:
80 * RangeModule obj = new RangeModule();
81 * obj.addRange(left,right);
82 * bool param_2 = obj.queryRange(left,right);
83 * obj.removeRange(left,right);
84 */
************

128. Range Module(Python)


************
1 # Time: addRange: O(n)
2 # removeRange: O(n)
3 # queryRange: O(logn)
4 # Space: O(n)
5
6 import bisect
7
8
9 class RangeModule(object):
10
11 def __init__(self):
12 self.__intervals = []
13
14 def addRange(self, left, right):
15 """
16 :type left: int
17 :type right: int
18 :rtype: void
19 """
20 tmp = []
21 i = 0
22 for interval in self.__intervals:
23 if right < interval[0]:
24 tmp.append((left, right))
25 break
26 elif interval[1] < left:
27 tmp.append(interval)
28 else:
29 left = min(left, interval[0])
30 right = max(right, interval[1])
31 i += 1
32 if i == len(self.__intervals):
33 tmp.append((left, right))
34 while i < len(self.__intervals):
35 tmp.append(self.__intervals[i])
36 i += 1
37 self.__intervals = tmp
38
39 def queryRange(self, left, right):
40 """
41 :type left: int
42 :type right: int
43 :rtype: bool
44 """
45 i = bisect.bisect_left(self.__intervals, (left, float("inf")))
46 if i: i -= 1
47 return bool(self.__intervals) and \
48 self.__intervals[i][0] <= left and \
49 right <= self.__intervals[i][1]
50
51 def removeRange(self, left, right):
52 """
53 :type left: int
54 :type right: int
55 :rtype: void
56 """
57 tmp = []
58 for interval in self.__intervals:
59 if interval[1] <= left or interval[0] >= right:
60 tmp.append(interval)
61 else:
62 if interval[0] < left:
63 tmp.append((interval[0], left))
64 if right < interval[1]:
65 tmp.append((right, interval[1]))
66 self.__intervals = tmp
67
68
69
********************************

129. Find K-th Smallest Pair Distance


********************************

The distance of a pair of integers a and b is defined as the absolute difference betweena and b.

Given an integer array nums and an integer k , return the k th smallest distance among all the pairs nums[i] and nums[j] where 0
<= i < j < nums.length.

Example 1:

Input: nums = [1,3,1], k = 1


Output: 0
Explanation: Here are all the pairs:
(1,3) -> 2
(1,1) -> 0
(3,1) -> 2
Then the 1st smallest distance pair is (1,1), and its distance is 0.

Example 2:

Input: nums = [1,1,1], k = 2


Output: 0

Example 3:

Input: nums = [1,6,1], k = 3


Output: 5

Constraints:

n == nums.length
2 <= n <= 10 4
0 <= nums[i] <= 10 6
1 <= k <= n * (n - 1) / 2
********************************

129. Find K-th Smallest Pair Distance(C++)


********************************

1 // Time: O(nlogn + nlogw), n = len(nums), w = max(nums) - min(nums)


2 // Space: O(1)
3
4 // Binary search with sliding window solution
5 class Solution {
6 public:
7 int smallestDistancePair(vector& nums, int k) {
8 sort(nums.begin(), nums.end());
9 int left = 0, right = nums.back() - nums.front() + 1;
10 while (left < right) {
11 const auto mid = left + (right - left) / 2;
12 if (possible(mid, nums, k)) {
13 right = mid;
14 } else {
15 left = mid + 1;
16 }
17 }
18 return left;
19 }
20
21 private:
22 bool possible(const int guess, const vector& nums, const int k) {
23 int count = 0, left = 0;
24 for (int right = 0; right < nums.size(); ++right) {
25 while ((nums[right] - nums[left]) > guess) {
26 ++left;
27 }
28 count += right - left;
29 }
30 return count >= k;
31 }
32 };
********************************

129. Find K-th Smallest Pair Distance(Python)


********************************

1 # Time: O(nlogn + nlogw), n = len(nums), w = max(nums)-min(nums)


2 # Space: O(1)
3
4 class Solution(object):
5 def smallestDistancePair(self, nums, k):
6 """
7 :type nums: List[int]
8 :type k: int
9 :rtype: int
10 """
11 # Sliding window solution
12 def possible(guess, nums, k):
13 count, left = 0, 0
14 for right, num in enumerate(nums):
15 while num-nums[left] > guess:
16 left += 1
17 count += right-left
18 return count >= k
19
20 nums.sort()
21 left, right = 0, nums[-1]-nums[0]+1
22 while left < right:
23 mid = left + (right-left)/2
24 if possible(mid, nums, k):
25 right = mid
26 else:
27 left = mid+1
28 return left
29
***************

130. Number of Atoms


***************

Given a string formula representing a chemical formula, return the count of each atom.

The atomic element always starts with an uppercase character, then zero or more lowercase letters, representing the name.

One or more digits representing that element's count may follow if the count is greater than1. If the count is 1, no digits will
follow.

For example, "H2O" and "H2O2" are possible, but "H1O2" is impossible.

Two formulas are concatenated together to produce another formula.

For example, "H2O2He3Mg4" is also a formula.

A formula placed in parentheses, and a count (optionally added) is also a formula.

For example, "(H2O2)" and "(H2O2)3" are formulas.

Return the count of all elements as a string in the following form: the first name (in sorted order), followed by its count (if that
count is more than 1), followed by the second name (in sorted order), followed by its count (if that count is more than1), and
so on.

Example 1:

Input: formula = "H2O"


Output: "H2O"
Explanation: The count of elements are {'H': 2, 'O': 1}.

Example 2:

Input: formula = "Mg(OH)2"


Output: "H2MgO2"
Explanation: The count of elements are {'H': 2, 'Mg': 1, 'O': 2}.

Example 3:

Input: formula = "K4(ON(SO3)2)2"


Output: "K4N2O14S4"
Explanation: The count of elements are {'K': 4, 'N': 2, 'O': 14, 'S': 4}.

Example 4:

Input: formula = "Be32"


Output: "Be32"

Constraints:

1 <= formula.length <= 1000


formula consists of English letters, digits, '(', and ')'.
formula is always valid.
All the values in the output will fit in a 32-bit integer.
***************

130. Number of Atoms(C++)


***************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 string countOfAtoms(string formula) {
7 stack> stk;
8 stk.emplace();
9 int submatches[] = { 1, 2, 3, 4, 5 };
10 const auto e = regex("([A-Z][a-z]*)(\\d*)|(\\()|(\\))(\\d*)");
11 for (regex_token_iterator it(formula.begin(), formula.end(), e, submatches), end;
12 it != end;) {
13 const auto& name = (it++)->str();
14 const auto& m1 = (it++)->str();
15 const auto& left_open = (it++)->str();
16 const auto& right_open = (it++)->str();
17 const auto& m2 = (it++)->str();
18 if (!name.empty()) {
19 stk.top()[name] += stoi(!m1.empty() ? m1 : "1");
20 }
21 if (!left_open.empty()) {
22 stk.emplace();
23 }
24 if (!right_open.empty()) {
25 const auto top = move(stk.top()); stk.pop();
26 for (const auto& kvp: top) {
27 stk.top()[kvp.first] += kvp.second * stoi(!m2.empty() ? m2 : "1");
28 }
29 }
30 }
31 string result;
32 for (const auto& kvp : stk.top()) {
33 result += kvp.first;
34 if (kvp.second > 1) {
35 result += to_string(kvp.second);
36 }
37 }
38 return result;
39 }
40 };
***************

130. Number of Atoms(Python)


***************

1 # Time: O(n)
2 # Space: O(n)
3
4 import collections
5 import re
6
7
8 class Solution(object):
9 def countOfAtoms(self, formula):
10 """
11 :type formula: str
12 :rtype: str
13 """
14 parse = re.findall(r"([A-Z][a-z]*)(\d*)|(\()|(\))(\d*)", formula)
15 stk = [collections.Counter()]
16 for name, m1, left_open, right_open, m2 in parse:
17 if name:
18 stk[-1][name] += int(m1 or 1)
19 if left_open:
20 stk.append(collections.Counter())
21 if right_open:
22 top = stk.pop()
23 for k, v in top.iteritems():
24 stk[-1][k] += v * int(m2 or 1)
25
26 return "".join(name + (str(stk[-1][name]) if stk[-1][name] > 1 else '') \
27 for name in sorted(stk[-1]))
28
**************************

131. Minimum Window Subsequence


**************************

Given strings s1 and s2, return the minimum contiguous substring part of s1, so that s2 is a subsequence of the part.

If there is no such window in s1 that covers all characters in s2, return the empty string "". If there are multiple such minimum-
length windows, return the one with the left-most starting index.

Example 1:

Input: s1 = "abcdebdde", s2 = "bde"


Output: "bcde"
Explanation:
"bcde" is the answer because it occurs before "bdde" which has the same length.
"deb" is not a smaller window because the elements of s2 in the window must occur in order.

Example 2:

Input: s1 = "jmeqksfrsdcmsiwvaovztaqenprpvnbstl", s2 = "u"


Output: ""

Constraints:

1 <= s1.length <= 2 * 10 4


1 <= s2.length <= 100
s1 and s2 consist of lowercase English letters.
**************************

131. Minimum Window Subsequence(C++)


**************************
1 // Time: O(s * t)
2 // Space: O(s)
3
4 class Solution {
5 public:
6 string minWindow(string S, string T) {
7 vector> lookup(S.size() + 1, vector(26, -1));
8 vector find_char_next_pos(26, -1);
9 for (int i = S.length() - 1; i >= 0; --i) {
10 find_char_next_pos[S[i] - 'a'] = i + 1;
11 lookup[i] = find_char_next_pos;
12 }
13
14 int min_i = -1, min_len = numeric_limits::max();
15 for (int i = 0; i < S.length(); ++i) {
16 if (S[i] != T[0]) {
17 continue;
18 }
19 int start = i;
20 for (const auto& c : T) {
21 start = lookup[start][c - 'a'];
22 if (start == -1) {
23 break;
24 }
25 }
26 if (start != -1) {
27 if (start - i < min_len) {
28 min_i = i;
29 min_len = start - i;
30 }
31 }
32 }
33 return min_i != -1 ? S.substr(min_i, min_len) : "";
34 }
35 };
36
37 // Time: O(s * t)
38 // Space: O(s)
39 class Solution2 {
40 public:
41 string minWindow(string S, string T) {
42 vector> dp(2, vector(S.length(), -1));
43 for (int j = 0; j < S.length(); ++j) {
44 if (S[j] == T[0]) {
45 dp[0][j] = j;
46 }
47 }
48
49 for (int i = 1; i < T.length(); ++i) {
50 int prev = -1;
51 dp[i % 2] = vector(S.length(), -1);
52 for (int j = 0; j < S.length(); ++j) {
53 if (prev != -1 && S[j] == T[i]) {
54 dp[i % 2][j] = prev;
55 }
56 if (dp[(i - 1) % 2][j] != -1) {
57 prev = dp[(i - 1) % 2][j];
58 }
59 }
60 }
61
62 int start = 0, end = S.length();
63 for (int j = 0; j < S.length(); ++j) {
64 int i = dp[(T.length() - 1) % 2][j];
65 if (i >= 0 && j - i < end - start) {
66 tie(start, end) = make_pair(i, j);
67 }
68 }
69 return end < S.length() ? S.substr(start, end - start + 1) : "";
70 }
71 };
**************************

131. Minimum Window Subsequence(Python)


**************************

1 # Time: O(s * t)
2 # Space: O(s)
3
4 class Solution(object):
5 def minWindow(self, S, T):
6 """
7 :type S: str
8 :type T: str
9 :rtype: str
10 """
11 lookup = [[None for _ in xrange(26)] for _ in xrange(len(S)+1)]
12 find_char_next_pos = [None]*26
13 for i in reversed(xrange(len(S))):
14 find_char_next_pos[ord(S[i])-ord('a')] = i+1
15 lookup[i] = list(find_char_next_pos)
16
17 min_i, min_len = None, float("inf")
18 for i in xrange(len(S)):
19 if S[i] != T[0]:
20 continue
21 start = i
22 for c in T:
23 start = lookup[start][ord(c)-ord('a')]
24 if start == None:
25 break
26 else:
27 if start-i < min_len:
28 min_i, min_len = i, start-i
29 return S[min_i:min_i+min_len] if min_i is not None else ""
30
31
32 # Time: O(s * t)
33 # Space: O(s)
34 class Solution2(object):
35 def minWindow(self, S, T):
36 """
37 :type S: str
38 :type T: str
39 :rtype: str
40 """
41 dp = [[None for _ in xrange(len(S))] for _ in xrange(2)]
42 for j, c in enumerate(S):
43 if c == T[0]:
44 dp[0][j] = j
45
46 for i in xrange(1, len(T)):
47 prev = None
48 dp[i%2] = [None] * len(S)
49 for j, c in enumerate(S):
50 if prev is not None and c == T[i]:
51 dp[i%2][j] = prev
52 if dp[(i-1)%2][j] is not None:
53 prev = dp[(i-1)%2][j]
54
55 start, end = 0, len(S)
56 for j, i in enumerate(dp[(len(T)-1)%2]):
57 if i >= 0 and j-i < end-start:
58 start, end = i, j
59 return S[start:end+1] if end < len(S) else ""
60
****************************************

132. Count Different Palindromic Subsequences


****************************************

Given a string s, return the number of different non-empty palindromic subsequences in s . Since the answer may be very
large, return it modulo 109 + 7 .

A subsequence of a string is obtained by deleting zero or more characters from the string.

A sequence is palindromic if it is equal to the sequence reversed.

Two sequences a1, a 2, ... and b1, b 2, ... are different if there is some i for which ai != bi.

Example 1:

Input: s = "bccb"
Output: 6
Explanation: The 6 different non-empty palindromic subsequences are 'b', 'c', 'bb', 'cc', 'bcb', 'bccb'.
Note that 'bcb' is counted only once, even though it occurs twice.

Example 2:

Input: s = "abcdabcdabcdabcdabcdabcdabcdabcddcbadcbadcbadcbadcbadcbadcbadcba"
Output: 104860361
Explanation: There are 3104860382 different non-empty palindromic subsequences, which is 104860361 modulo 109 + 7.

Constraints:

1 <= s.length <= 1000


s[i] is either 'a', 'b', 'c', or 'd'.
****************************************

132. Count Different Palindromic Subsequences(C++)


****************************************

1 // Time: O(n^2)
2 // Space: O(n)
3 class Solution {
4 public:
5 int countPalindromicSubsequences(string S) {
6 static const int P = 1e9 + 7;
7 static const string chars = "abcd";
8 vector>> dp(3, vector>(S.size(), vector(4)));
9 for (int len = 1; len <= S.size(); ++len) {
10 for (int i = 0; i + len <= S.size(); ++i) {
11 for (const auto& c : chars) {
12 dp[len % 3][i][c - 'a'] = 0;
13 if (len == 1) {
14 dp[len % 3][i][c - 'a'] = S[i] == c;
15 } else {
16 if (S[i] != c) {
17 dp[len % 3][i][c - 'a'] = dp[(len - 1) % 3][i + 1][c - 'a'];
18 } else if (S[i + len - 1] != c) {
19 dp[len % 3][i][c - 'a'] = dp[(len - 1) % 3][i][c - 'a'];
20 } else {
21 dp[len % 3][i][c - 'a'] = 2;
22 if (len > 2) {
23 for (const auto& cc : chars) {
24 dp[len % 3][i][c - 'a'] += dp[(len - 2) % 3][i + 1][cc - 'a'];
25 dp[len % 3][i][c - 'a'] %= P;
26 }
27 }
28 }
29 }
30 }
31 }
32 }
33 int result = 0;
34 for (const auto& c : chars) {
35 result = (result + dp[S.size() % 3][0][c - 'a']) % P;
36 }
37 return result;
38 }
39 };
40
41 // Time: O(n^2)
42 // Space: O(n^2)
43 class Solution2 {
44 public:
45 int countPalindromicSubsequences(string S) {
46 vector> prv(S.length(), vector(4, -1));
47 vector> nxt(S.length(), vector(4, -1));
48 vector last(4, -1);
49 for (int i = 0; i < S.length(); ++i) {
50 last[S[i] - 'a'] = i;
51 prv[i] = last;
52 }
53 last = vector(4, -1);
54 for (int i = S.length() - 1; i >= 0; --i) {
55 last[S[i] - 'a'] = i;
56 nxt[i] = last;
57 }
58 vector> lookup(S.length(), vector(S.length(), -1));
59 return dp(0, S.length() - 1, prv, nxt, &lookup) - 1;
60 }
61
62 private:
63 int dp(const int i, const int j,
64 const vector>& prv,
65 const vector>& nxt,
66 vector> *lookup) {
67
68 if ((*lookup)[i][j] != -1) {
69 return (*lookup)[i][j];
70 }
71 auto result = 1;
72 if (i <= j) {
73 for (int x = 0; x < 4; ++x) {
74 auto i0 = nxt[i][x];
75 auto j0 = prv[j][x];
76 if (i <= i0 && i0 <= j) {
77 result = (result + 1) % P;
78 }
79 if (i0 != -1 && j0 != -1 && i0 < j0) {
80 result = (result + dp(i0 + 1, j0 - 1, prv, nxt, lookup)) % P;
81 }
82 }
83 }
84 result %= P;
85 (*lookup)[i][j] = result;
86 return result;
87 }
88 static const int P = 1e9 + 7;
89 };
****************************************

132. Count Different Palindromic Subsequences(Python)


****************************************

1 # Time: O(n^2)
2 # Space: O(n^2)
3
4 class Solution(object):
5 def countPalindromicSubsequences(self, S):
6 """
7 :type S: str
8 :rtype: int
9 """
10 def dp(i, j, prv, nxt, lookup):
11 if lookup[i][j] is not None:
12 return lookup[i][j]
13 result = 1
14 if i <= j:
15 for x in xrange(4):
16 i0 = nxt[i][x]
17 j0 = prv[j][x]
18 if i <= i0 <= j:
19 result = (result + 1) % P
20 if None < i0 < j0:
21 result = (result + dp(i0+1, j0-1, prv, nxt, lookup)) % P
22 result %= P
23 lookup[i][j] = result
24 return result
25
26 prv = [None] * len(S)
27 nxt = [None] * len(S)
28
29 last = [None] * 4
30 for i in xrange(len(S)):
31 last[ord(S[i])-ord('a')] = i
32 prv[i] = tuple(last)
33
34 last = [None] * 4
35 for i in reversed(xrange(len(S))):
36 last[ord(S[i])-ord('a')] = i
37 nxt[i] = tuple(last)
38
39 P = 10**9 + 7
40 lookup = [[None] * len(S) for _ in xrange(len(S))]
41 return dp(0, len(S)-1, prv, nxt, lookup) - 1
42
***************

133. My Calendar III


***************

A k -booking happens when k events have some non-empty intersection (i.e., there is some time that is common to allk
events.)

You are given some events [start, end), after each given event, return an integer k representing the maximum k -booking
between all the previous events.

Implement the MyCalendarThree class:

MyCalendarThree() Initializes the object.


int book(int start, int end) Returns an integer k representing the largest integer such that there exists a k -booking in the
calendar.

Example 1:

Input
["MyCalendarThree", "book", "book", "book", "book", "book", "book"]
[[], [10, 20], [50, 60], [10, 40], [5, 15], [5, 10], [25, 55]]
Output
[null, 1, 1, 2, 3, 3, 3]

Explanation
MyCalendarThree myCalendarThree = new MyCalendarThree();
myCalendarThree.book(10, 20); // return 1, The first event can be booked and is disjoint, so the maximum k-booking is a 1-booking.
myCalendarThree.book(50, 60); // return 1, The second event can be booked and is disjoint, so the maximum k-booking is a 1-booking.
myCalendarThree.book(10, 40); // return 2, The third event [10, 40) intersects the first event, and the maximum k-booking is a 2-booking.
myCalendarThree.book(5, 15); // return 3, The remaining events cause the maximum K-booking to be only a 3-booking.
myCalendarThree.book(5, 10); // return 3
myCalendarThree.book(25, 55); // return 3

Constraints:

0 <= start < end <= 10 9


At most 400 calls will be made to book.
***************

133. My Calendar III(C++)


***************

1 // Time: O(nlogn) ~ O(n^2)


2 // Space: O(n)
3
4 class MyCalendarThree {
5 public:
6 MyCalendarThree() {
7 events_.emplace(-1, 0);
8 }
9
10 int book(int start, int end) {
11 auto sit = events_.emplace(start, prev(events_.upper_bound(start))->second).first;
12 auto eit = events_.emplace(end, prev(events_.upper_bound(end))->second).first;
13 for (; sit != eit; ++sit) {
14 count_ = max(count_, ++(sit->second));
15 }
16 return count_;
17 }
18
19 private:
20 map events_;
21 int count_ = 0;
22 };
23
24 // Time: O(n^2)
25 // Space: O(n)
26 class MyCalendarThree2 {
27 public:
28 MyCalendarThree2() {
29
30 }
31
32 int book(int start, int end) {
33 ++books_[start];
34 --books_[end];
35 int result = 0;
36 int cnt = 0;
37 for (const auto &book : books_) {
38 cnt += book.second;
39 result = max(result, cnt);
40 }
41 return result;
42 }
43
44 private:
45 map books_;
46 };
47
48 /**
49 * Your MyCalendarThree object will be instantiated and called as such:
50 * MyCalendarThree obj = new MyCalendarThree();
51 * int param_1 = obj.book(start,end);
52 */
***************

133. My Calendar III(Python)


***************
1 # Time: O(nlogn) ~ O(n^2)
2 # Space: O(n)
3
4 import bisect
5
6
7 class MyCalendarThree(object):
8
9 def __init__(self):
10 self.__books = [[-1, 0]]
11 self.__count = 0
12
13 def book(self, start, end):
14 """
15 :type start: int
16 :type end: int
17 :rtype: int
18 """
19 i = bisect.bisect_right(self.__books, [start, float("inf")])
20 if self.__books[i-1][0] == start:
21 i -= 1
22 else:
23 self.__books.insert(i, [start, self.__books[i-1][1]])
24 j = bisect.bisect_right(self.__books, [end, float("inf")])
25 if self.__books[j-1][0] == end:
26 j -= 1
27 else:
28 self.__books.insert(j, [end, self.__books[j-1][1]])
29 for k in xrange(i, j):
30 self.__books[k][1] += 1
31 self.__count = max(self.__count, self.__books[k][1])
32 return self.__count
33
34
35 # Time: O(n^2)
36 # Space: O(n)
37 class MyCalendarThree2(object):
38
39 def __init__(self):
40 self.__books = []
41
42
43 def book(self, start, end):
44 """
45 :type start: int
46 :type end: int
47 :rtype: int
48 """
49 i = bisect.bisect_left(self.__books, (start, 1))
50 if i < len(self.__books) and self.__books[i][0] == start:
51 self.__books[i] = (self.__books[i][0], self.__books[i][1]+1)
52 else:
53 self.__books.insert(i, (start, 1))
54
55 j = bisect.bisect_left(self.__books, (end, 1))
56 if j < len(self.__books) and self.__books[j][0] == end:
57 self.__books[j] = (self.__books[j][0], self.__books[j][1]-1)
58 else:
59 self.__books.insert(j, (end, -1))
60
61 result, cnt = 0, 0
62 for book in self.__books:
63 cnt += book[1]
64 result = max(result, cnt)
65 return result
66
*********************

134. Parse Lisp Expression


*********************

You are given a string expression representing a Lisp-like expression to return the integer value of.

The syntax for these expressions is given as follows.

An expression is either an integer, let expression, add expression, mult expression, or an assigned variable.
Expressions always evaluate to a single integer.
(An integer could be positive or negative.)
A let expression takes the form "(let v 1 e1 v 2 e2 ... v n en expr)", where let is always the string "let", then there are one or more
pairs of alternating variables and expressions, meaning that the first variable v 1 is assigned the value of the expression
e1, the second variable v 2 is assigned the value of the expressione2, and so on sequentially; and then the value of this
let expression is the value of the expression expr.
An add expression takes the form "(add e 1 e2)" where add is always the string "add", there are always two expressions e1,
e2 and the result is the addition of the evaluation ofe1 and the evaluation of e2.
A mult expression takes the form "(mult e 1 e2)" where mult is always the string "mult", there are always two expressions
e1, e2 and the result is the multiplication of the evaluation of e1 and the evaluation of e2.
For this question, we will use a smaller subset of variable names. A variable starts with a lowercase letter, then zero or
more lowercase letters or digits. Additionally, for your convenience, the names "add", "let", and "mult" are protected and
will never be used as variable names.
Finally, there is the concept of scope. When an expression of a variable name is evaluated, within the context of that
evaluation, the innermost scope (in terms of parentheses) is checked first for the value of that variable, and then outer
scopes are checked sequentially. It is guaranteed that every expression is legal. Please see the examples for more
details on the scope.

Example 1:

Input: expression = "(let x 2 (mult x (let x 3 y 4 (add x y))))"


Output: 14
Explanation: In the expression (add x y), when checking for the value of the variable x,
we check from the innermost scope to the outermost in the context of the variable we are trying to evaluate.
Since x = 3 is found first, the value of x is 3.

Example 2:

Input: expression = "(let x 3 x 2 x)"


Output: 2
Explanation: Assignment in let statements is processed sequentially.

Example 3:

Input: expression = "(let x 1 y 2 x (add x y) (add x y))"


Output: 5
Explanation: The first (add x y) evaluates as 3, and is assigned to x.
The second (add x y) evaluates as 3+2 = 5.

Example 4:

Input: expression = "(let x 2 (add (let x 3 (let x 4 x)) x))"


Output: 6
Explanation: Even though (let x 4 x) has a deeper scope, it is outside the context
of the final x in the add-expression. That final x will equal 2.
Example 5:

Input: expression = "(let a1 3 b2 (add a1 1) b2)"


Output: 4
Explanation: Variable names can contain digits after the first character.

Constraints:

1 <= expression.length <= 2000


There are no leading or trailing spaces in exprssion.
All tokens are separated by a single space in expressoin.
The answer and all intermediate calculations of that answer are guaranteed to fit in a32-bit integer.
The expression is guaranteed to be legal and evaluate to an integer.
*********************

134. Parse Lisp Expression(C++)


*********************

1 // Time: O(n^2)
2 // Space: O(n^2)
3
4 class Solution {
5 public:
6 int evaluate(string expression) {
7 vector tokens{""};
8 unordered_map lookup;
9 vector, unordered_map>> stk;
10 for (const auto& c : expression) {
11 if (c == '(') {
12 if (tokens[0] == "let") {
13 evaluate(tokens, &lookup);
14 }
15 stk.emplace_back(move(tokens), lookup);
16 tokens = {""};
17 } else if (c == ' ') {
18 tokens.emplace_back();
19 } else if (c == ')') {
20 const auto& val = evaluate(tokens, &lookup);
21 tie(tokens, lookup) = move(stk.back());
22 stk.pop_back();
23 tokens.back() += val;
24 } else {
25 tokens.back().push_back(c);
26 }
27 }
28 return stoi(tokens[0]);
29 }
30
31 private:
32 string evaluate(const vector& tokens, unordered_map* lookup) {
33 static const unordered_set operators{"add", "mult"};
34 if (operators.count(tokens[0])) {
35 const auto& a = stoi(getval(*lookup, tokens[1]));
36 const auto& b = stoi(getval(*lookup, tokens[2]));
37 return to_string(tokens[0] == "add" ? a + b : a * b);
38 }
39 for (int i = 1; i < tokens.size() - 1; i += 2) {
40 if (!tokens[i + 1].empty()) {
41 (*lookup)[tokens[i]] = getval(*lookup, tokens[i + 1]);
42 }
43 }
44 return getval(*lookup, tokens.back());
45 }
46
47 string getval(const unordered_map& lookup, const string& x) {
48 return lookup.count(x) ? lookup.at(x) : x;
49 }
50 };
*********************

134. Parse Lisp Expression(Python)


*********************

1 # Time: O(n^2)
2 # Space: O(n^2)
3
4 class Solution(object):
5 def evaluate(self, expression):
6 """
7 :type expression: str
8 :rtype: int
9 """
10 def getval(lookup, x):
11 return lookup.get(x, x)
12
13 def evaluate(tokens, lookup):
14 if tokens[0] in ('add', 'mult'):
15 a, b = map(int, map(lambda x: getval(lookup, x), tokens[1:]))
16 return str(a+b if tokens[0] == 'add' else a*b)
17 for i in xrange(1, len(tokens)-1, 2):
18 if tokens[i+1]:
19 lookup[tokens[i]] = getval(lookup, tokens[i+1])
20 return getval(lookup, tokens[-1])
21
22 tokens, lookup, stk = [''], {}, []
23 for c in expression:
24 if c == '(':
25 if tokens[0] == 'let':
26 evaluate(tokens, lookup)
27 stk.append((tokens, dict(lookup)))
28 tokens = ['']
29 elif c == ' ':
30 tokens.append('')
31 elif c == ')':
32 val = evaluate(tokens, lookup)
33 tokens, lookup = stk.pop()
34 tokens[-1] += val
35 else:
36 tokens[-1] += c
37 return int(tokens[0])
38
*************

135. Cherry Pickup


*************

You are given an n x n grid representing a field of cherries, each cell is one of three possible integers.

0 means the cell is empty, so you can pass through,


1 means the cell contains a cherry that you can pick up and pass through, or
-1 means the cell contains a thorn that blocks your way.

Return the maximum number of cherries you can collect by following the rules below:

Starting at the position (0, 0) and reaching (n - 1, n - 1) by moving right or down through valid path cells (cells with value0
or 1).
After reaching (n - 1, n - 1) , returning to (0, 0) by moving left or up through valid path cells.
When passing through a path cell containing a cherry, you pick it up, and the cell becomes an empty cell0.
If there is no valid path between (0, 0) and (n - 1, n - 1) , then no cherries can be collected.

Example 1:

Input: grid = [[0,1,-1],[1,0,-1],[1,1,1]]


Output: 5
Explanation: The player started at (0, 0) and went down, down, right right to reach (2, 2).
4 cherries were picked up during this single trip, and the matrix becomes [[0,1,-1],[0,0,-1],[0,0,0]].
Then, the player went left, up, up, left to return home, picking up one more cherry.
The total number of cherries picked up is 5, and this is the maximum possible.

Example 2:

Input: grid = [[1,1,-1],[1,-1,1],[-1,1,1]]


Output: 0

Constraints:

n == grid.length
n == grid[i].length
1 <= n <= 50
grid[i][j] is -1, 0, or 1.
grid[0][0] != -1
grid[n - 1][n - 1] != -1
*************

135. Cherry Pickup(C++)


*************

1 // Time: O(n^3)
2 // Space: O(n^2)
3
4 class Solution {
5 public:
6 int cherryPickup(vector>& grid) {
7 // dp holds the max # of cherries two k-length paths can pickup.
8 // The two k-length paths arrive at (i, k - i) and (j, k - j),
9 // respectively.
10 const int n = grid.size();
11 vector> dp(n, vector(n, -1));
12 dp[0][0] = grid[0][0];
13
14 const int max_len = 2 * (n - 1);
15 for (int k = 1; k <= max_len; ++k) {
16 for (int i = min(k, n - 1); i >= max(0, k - n + 1); --i) { // 0 <= i < n, 0 <= k-i < n
17 for (int j = min(k , n - 1); j >= i; --j) { // i <= j < n, 0 <= k-j < n
18 if (grid[i][k - i] == -1 ||
19 grid[j][k - j] == -1) {
20 dp[i][j] = -1;
21 continue;
22 }
23 int cnt = grid[i][k - i] + ((i == j) ? 0 : grid[j][k - j]);
24 int max_cnt = -1;
25 static const vector> directions{{0, 0}, {-1, 0}, {0, -1}, {-1, -1}};
26 for (const auto& direction : directions) {
27 const auto ii = i + direction.first;
28 const auto jj = j + direction.second;
29 if (ii >= 0 && jj >= 0 && dp[ii][jj] >= 0) {
30 max_cnt = max(max_cnt, dp[ii][jj] + cnt);
31 }
32 }
33 dp[i][j] = max_cnt;
34 }
35 }
36 }
37 return max(dp[n - 1][n - 1], 0);
38 }
39 };
*************

135. Cherry Pickup(Python)


*************

1 # Time: O(n^3)
2 # Space: O(n^2)
3
4 class Solution(object):
5 def cherryPickup(self, grid):
6 """
7 :type grid: List[List[int]]
8 :rtype: int
9 """
10 # dp holds the max # of cherries two k-length paths can pickup.
11 # The two k-length paths arrive at (i, k - i) and (j, k - j),
12 # respectively.
13 n = len(grid)
14 dp = [[-1 for _ in xrange(n)] for _ in xrange(n)]
15 dp[0][0] = grid[0][0]
16 max_len = 2 * (n-1)
17 directions = [(0, 0), (-1, 0), (0, -1), (-1, -1)]
18 for k in xrange(1, max_len+1):
19 for i in reversed(xrange(max(0, k-n+1), min(k+1, n))): # 0 <= i < n, 0 <= k-i < n
20 for j in reversed(xrange(i, min(k+1, n))): # i <= j < n, 0 <= k-j < n
21 if grid[i][k-i] == -1 or grid[j][k-j] == -1:
22 dp[i][j] = -1
23 continue
24 cnt = grid[i][k-i]
25 if i != j:
26 cnt += grid[j][k-j]
27 max_cnt = -1
28 for direction in directions:
29 ii, jj = i+direction[0], j+direction[1]
30 if ii >= 0 and jj >= 0 and dp[ii][jj] >= 0:
31 max_cnt = max(max_cnt, dp[ii][jj]+cnt)
32 dp[i][j] = max_cnt
33 return max(dp[n-1][n-1], 0)
34
************************

136. Prefix and Suffix Search


************************

Design a special dictionary with some words that searchs the words in it by a prefix and a suffix.

Implement the WordFilter class:

Initializes the object with the words in the dictionary.


WordFilter(string[] words)
Returns the index of the word in the dictionary,which has the prefix prefix and the suffix suffix. If
f(string prefix, string suffix)
there is more than one valid index, return the largest of them. If there is no such word in the dictionary, return-1.

Example 1:

Input
["WordFilter", "f"]
[[["apple"]], ["a", "e"]]
Output
[null, 0]

Explanation
WordFilter wordFilter = new WordFilter(["apple"]);
wordFilter.f("a", "e"); // return 0, because the word at index 0 has prefix = "a" and suffix = 'e".

Constraints:

1 <= words.length <= 15000


1 <= words[i].length <= 10
1 <= prefix.length, suffix.length <= 10
words[i], prefix and suffix consist of lower-case English letters only.
At most 15000 calls will be made to the function f.
************************

136. Prefix and Suffix Search(C++)


************************

1 // Time: ctor: O(w * l^2), w is the number of words, l is the word length on average
2 // search: O(p + s) , p is the length of the prefix, s is the length of the suffix,
3 // Space: O(t), t is the number of trie nodes
4
5 class WordFilter {
6 public:
7 WordFilter(vector words) {
8 for (int i = 0; i < words.size(); ++i) {
9 for (int j = 0; j <= words[i].length(); ++j) {
10 trie_.insert(words[i].substr(j) + SEPARATOR + words[i], i);
11 }
12 }
13 }
14
15 int f(string prefix, string suffix) {
16 return trie_.find(suffix + SEPARATOR + prefix);
17 }
18
19 private:
20 struct TrieNode {
21 int weight;
22 vector leaves;
23
24 TrieNode() : weight(0), leaves(27) {}
25
26 void insert(const string& s, const int weight) {
27 auto* p = this;
28 p->weight = weight;
29 for (const auto& c : s) {
30 if (!p->leaves[c - 'a']) {
31 p->leaves[c - 'a'] = new TrieNode;
32 }
33 p = p->leaves[c - 'a'];
34 p->weight = weight;
35 }
36 }
37
38 int find(const string& s) const {
39 auto* p = this;
40 for (const auto& c : s) {
41 if (!p->leaves[c - 'a']) {
42 return -1;
43 }
44 p = p->leaves[c - 'a'];
45 }
46 return p->weight;
47 }
48
49 ~TrieNode() {
50 for (auto& node : leaves) {
51 if (node) {
52 delete node;
53 }
54 }
55 }
56 };
57 const string SEPARATOR = "{"; // ascii code of 'z' + 1
58 TrieNode trie_;
59 };
60
61 // Time: ctor: O(w * l), w is the number of words, l is the word length on average
62 // search: O(p + s + max(m, n)), p is the length of the prefix, s is the length of the suffix,
63 // m is the number of the prefix match, n is the number of the suffix match
64 // Space: O(w * l)
65 class WordFilter2 {
66 public:
67 WordFilter(vector words) {
68 for (int i = words.size() - 1; i >= 0; --i) {
69 auto word = words[i];
70 prefix_trie_.insert(word, i);
71 reverse(word.begin(), word.end());
72 suffix_trie_.insert(word, i);
73 }
74 }
75
76 int f(string prefix, string suffix) {
77 const auto& prefix_match = prefix_trie_.find(prefix);
78 reverse(suffix.begin(), suffix.end());
79 const auto& suffix_match = suffix_trie_.find(suffix);
80 int i = 0, j = 0;
81 while (i != prefix_match.size() && j != suffix_match.size()) {
82 if (prefix_match[i] == suffix_match[j]) {
83 return prefix_match[i];
84 } else if (prefix_match[i] > suffix_match[j]) {
85 ++i;
86 } else {
87 ++j;
88 }
89 }
90 return -1;
91 }
92
93 private:
94 struct TrieNode {
95 vector words; // index of words
96 vector leaves;
97
98 TrieNode() : leaves(26) {}
99
100 void insert(const string& s, const int i) {
101 auto* p = this;
102 p->words.emplace_back(i);
103 for (const auto& c : s) {
104 if (!p->leaves[c - 'a']) {
105 p->leaves[c - 'a'] = new TrieNode;
106 }
107 p = p->leaves[c - 'a'];
108 p->words.emplace_back(i);
109 }
110 }
111
112 const vector& find(const string& s) const {
113 auto* p = this;
114 for (const auto& c : s) {
115 if (!p->leaves[c - 'a']) {
116 static const vector empty;
117 return empty;
118 }
119 p = p->leaves[c - 'a'];
120 }
121 return p->words;
122 }
123
124 ~TrieNode() {
125 for (auto& node : leaves) {
126 if (node) {
127 delete node;
128 }
129 }
130 }
131 };
132 TrieNode prefix_trie_, suffix_trie_;
133 };
134
135 /**
135 /**
136 * Your WordFilter object will be instantiated and called as such:
137 * WordFilter obj = new WordFilter(words);
138 * int param_1 = obj.f(prefix,suffix);
139 */
************************

136. Prefix and Suffix Search(Python)


************************

1 # Time: ctor: O(w * l^2), w is the number of words, l is the word length on average
2 # search: O(p + s) , p is the length of the prefix, s is the length of the suffix,
3 # Space: O(t), t is the number of trie nodes
4
5 import collections
6
7
8 class WordFilter(object):
9
10 def __init__(self, words):
11 """
12 :type words: List[str]
13 """
14 _trie = lambda: collections.defaultdict(_trie)
15 self.__trie = _trie()
16
17 for weight, word in enumerate(words):
18 word += '#'
19 for i in xrange(len(word)):
20 cur = self.__trie
21 cur["_weight"] = weight
22 for j in xrange(i, 2*len(word)-1):
23 cur = cur[word[j%len(word)]]
24 cur["_weight"] = weight
25
26 def f(self, prefix, suffix):
27 """
28 :type prefix: str
29 :type suffix: str
30 :rtype: int
31 """
32 cur = self.__trie
33 for letter in suffix + '#' + prefix:
34 if letter not in cur:
35 return -1
36 cur = cur[letter]
37 return cur["_weight"]
38
39
40 # Time: ctor: O(w * l), w is the number of words, l is the word length on average
41 # search: O(p + s + max(m, n)), p is the length of the prefix, s is the length of the suffix,
42 # m is the number of the prefix match, n is the number of the suffix match
43 # Space: O(w * l)
44 class Trie(object):
45
46 def __init__(self):
47 _trie = lambda: collections.defaultdict(_trie)
48 self.__trie = _trie()
49
50 def insert(self, word, i):
51 def add_word(cur, i):
52 if "_words" not in cur:
53 cur["_words"] = []
54 cur["_words"].append(i)
55
56 cur = self.__trie
57 add_word(cur, i)
58 for c in word:
59 cur = cur[c]
60 add_word(cur, i)
61
62 def find(self, word):
63 cur = self.__trie
64 for c in word:
65 if c not in cur:
66 return []
67 cur = cur[c]
68 return cur["_words"]
69
70
71 class WordFilter2(object):
72
73 def __init__(self, words):
74 """
75 :type words: List[str]
76 """
77 self.__prefix_trie = Trie()
78 self.__suffix_trie = Trie()
79 for i in reversed(xrange(len(words))):
80 self.__prefix_trie.insert(words[i], i)
81 self.__suffix_trie.insert(words[i][::-1], i)
82
83 def f(self, prefix, suffix):
84 """
85 :type prefix: str
86 :type suffix: str
87 :rtype: int
88 """
89 prefix_match = self.__prefix_trie.find(prefix)
90 suffix_match = self.__suffix_trie.find(suffix[::-1])
91 i, j = 0, 0
92 while i != len(prefix_match) and j != len(suffix_match):
93 if prefix_match[i] == suffix_match[j]:
94 return prefix_match[i]
95 elif prefix_match[i] > suffix_match[j]:
96 i += 1
97 else:
98 j += 1
99 return -1
100
101
102
*************

137. Contain Virus


*************

A virus is spreading rapidly, and your task is to quarantine the infected area by installing walls.

The world is modeled as an m x n binary grid isInfected, where isInfected[i][j] == 0 represents uninfected cells, and isInfected[i][j] == 1
represents cells contaminated with the virus. A wall (and only one wall) can be installed between any two 4-directionally
adjacent cells, on the shared boundary.

Every night, the virus spreads to all neighboring cells in all four directions unless blocked by a wall. Resources are limited.
Each day, you can install walls around only one region (i.e., the affected area (continuous block of infected cells) that
threatens the most uninfected cells the following night). There will never be a tie.

Return the number of walls used to quarantine all the infected regions. If the world will become fully infected, return the
number of walls used.

Example 1:

Input: isInfected = [[0,1,0,0,0,0,0,1],[0,1,0,0,0,0,0,1],[0,0,0,0,0,0,0,1],[0,0,0,0,0,0,0,0]]


Output: 10
Explanation: There are 2 contaminated regions.
On the first day, add 5 walls to quarantine the viral region on the left. The board after the virus spreads is:

On the second day, add 5 walls to quarantine the viral region on the right. The virus is fully contained.

Example 2:
Input: isInfected = [[1,1,1],[1,0,1],[1,1,1]]
Output: 4
Explanation: Even though there is only one cell saved, there are 4 walls built.
Notice that walls are only built on the shared boundary of two different cells.

Example 3:

Input: isInfected = [[1,1,1,0,0,0,0,0,0],[1,0,1,0,1,1,1,1,1],[1,1,1,0,0,0,0,0,0]]


Output: 13
Explanation: The region on the left only builds two new walls.

Constraints:

m == isInfected.length
n == isInfected[i].length
1 <= m, n <= 50
isInfected[i][j] is either 0
or 1.
There is always a contiguous viral region throughout the described process that willinfect strictly more
uncontaminated squares in the next round.
*************

137. Contain Virus(C++)


*************

1 // Time: O((m * n)^(4/3)), days = O((m * n)^(1/3))


2 // Space: O(m * n)
3
4 class Solution {
5 public:
6 int containVirus(vector>& grid) {
7 int result = 0;
8 while (true) {
9 P_SET lookup;
10 vector regions, frontiers;
11 vector perimeters;
12 for (int r = 0; r < grid.size(); ++r) {
13 for (int c = 0; c < grid[r].size(); ++c) {
14 const auto& p = make_pair(r, c);
15 if (grid[r][c] == 1 && lookup.count(p) == 0) {
16 regions.emplace_back();
17 frontiers.emplace_back();
18 perimeters.emplace_back();
19 dfs(grid, p, &lookup, ®ions, &frontiers, &perimeters);
20 }
21 }
22 }
23 if (regions.empty()) {
24 break;
25 }
26
27 int triage_idx = 0;
28 for (int i = 0; i < frontiers.size(); ++i) {
29 if (frontiers[i].size() > frontiers[triage_idx].size()) {
30 triage_idx = i;
31 }
32 }
33 for (int i = 0; i < regions.size(); ++i) {
34 if (i == triage_idx) {
35 result += perimeters[i];
36 for (const auto& p : regions[i]) {
37 grid[p.first][p.second] = -1;
38 }
39 continue;
40 }
41 for (const auto& p : regions[i]) {
42 for (const auto& d : directions) {
43 int nr = p.first + d.first;
44 int nc = p.second + d.second;
45 if (nr < 0 || nr >= grid.size() ||
46 nc < 0 || nc >= grid[nr].size()) {
47 continue;
48 }
49 if (grid[nr][nc] == 0) {
50 grid[nr][nc] = 1;
51 }
52 }
53 }
54 }
55 }
56
57 return result;
58 }
59
60 private:
61 template
62 struct PairHash {
63 size_t operator()(const pair& p) const {
64 size_t seed = 0;
65 seed ^= std::hash{}(p.first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
66 seed ^= std::hash{}(p.second) + 0x9e3779b9 + (seed<<6) + (seed>>2);
67 return seed;
68 }
69 };
70 using P = pair;
71 using P_SET = unordered_set>;
72
73 void dfs(const vector>& grid,
74 const P& p,
75 P_SET *lookup,
76 vector *regions,
77 vector *frontiers,
78 vector *perimeters) {
79
80 if (lookup->count(p)) {
81 return;
82 }
83 lookup->emplace(p);
84 regions->back().emplace(p);
85 for (const auto& d : directions) {
86 int nr = p.first + d.first;
87 int nc = p.second + d.second;
88 if (nr < 0 || nr >= grid.size() ||
89 nc < 0 || nc >= grid[nr].size()) {
90 continue;
91 }
92 if (grid[nr][nc] == 1) {
93 dfs(grid, make_pair(nr, nc), lookup, regions, frontiers, perimeters);
94 } else if (grid[nr][nc] == 0) {
95 frontiers->back().emplace(nr, nc);
96 ++perimeters->back();
97 }
98 }
99 }
100 const vector

directions = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}}; };


*************

137. Contain Virus(Python)


*************

1 # Time: O((m * n)^(4/3)), days = O((m * n)^(1/3))


2 # Space: O(m * n)
3
4 class Solution(object):
5 def containVirus(self, grid):
6 """
7 :type grid: List[List[int]]
8 :rtype: int
9 """
10 directions = [(0, 1), (0, -1), (-1, 0), (1, 0)]
11
12 def dfs(grid, r, c, lookup, regions, frontiers, perimeters):
13 if (r, c) in lookup:
14 return
15 lookup.add((r, c))
16 regions[-1].add((r, c))
17 for d in directions:
18 nr, nc = r+d[0], c+d[1]
19 if not (0 <= nr < len(grid) and \
20 0 <= nc < len(grid[r])):
21 continue
22 if grid[nr][nc] == 1:
23 dfs(grid, nr, nc, lookup, regions, frontiers, perimeters)
24 elif grid[nr][nc] == 0:
25 frontiers[-1].add((nr, nc))
26 perimeters[-1] += 1
27
28 result = 0
29 while True:
30 lookup, regions, frontiers, perimeters = set(), [], [], []
31 for r, row in enumerate(grid):
32 for c, val in enumerate(row):
33 if val == 1 and (r, c) not in lookup:
34 regions.append(set())
35 frontiers.append(set())
36 perimeters.append(0)
37 dfs(grid, r, c, lookup, regions, frontiers, perimeters)
38
39 if not regions: break
40
41 triage_idx = frontiers.index(max(frontiers, key = len))
42 for i, region in enumerate(regions):
43 if i == triage_idx:
44 result += perimeters[i]
45 for r, c in region:
46 grid[r][c] = -1
47 continue
48 for r, c in region:
49 for d in directions:
50 nr, nc = r+d[0], c+d[1]
51 if not (0 <= nr < len(grid) and \
52 0 <= nc < len(grid[r])):
53 continue
54 if grid[nr][nc] == 0:
55 grid[nr][nc] = 1
56
57 return result
58
*****************

138. Cracking the Safe


*****************

There is a safe protected by a password. The password is a sequence ofn digits where each digit can be in the range[0, k -
1].

The safe has a peculiar way of checking the password. When you enter in a sequence, it checks themost recent n digits
that were entered each time you type a digit.

For example, the correct password is "345" and you enter in "012345" :
After typing 0, the most recent 3 digits is "0", which is incorrect.
After typing 1, the most recent 3 digits is "01", which is incorrect.
After typing 2, the most recent 3 digits is "012", which is incorrect.
After typing 3, the most recent 3 digits is "123", which is incorrect.
After typing 4, the most recent 3 digits is "234", which is incorrect.
After typing 5, the most recent 3 digits is "345", which is correct and the safe unlocks.

Return any string of minimum length that will unlock the safe at some point of entering it.

Example 1:

Input: n = 1, k = 2
Output: "10"
Explanation: The password is a single digit, so enter each digit. "01" would also unlock the safe.

Example 2:

Input: n = 2, k = 2
Output: "01100"
Explanation: For each possible password:
- "00" is typed in starting from the 4th digit.
- "01" is typed in starting from the 1st digit.
- "10" is typed in starting from the 3rd digit.
- "11" is typed in starting from the 2nd digit.
Thus "01100" will unlock the safe. "01100", "10011", and "11001" would also unlock the safe.

Constraints:

1 <= n <= 4
1 <= k <= 10
1 <= k n <= 4096
*****************

138. Cracking the Safe(C++)


*****************

1 // Time: O(k^n)
2 // Space: O(k^n)
3
4 // https://en.wikipedia.org/wiki/De_Bruijn_sequence
5 // https://en.wikipedia.org/wiki/Lyndon_word
6 class Solution {
7 public:
8 string crackSafe(int n, int k) {
9 const int M = pow(k, n - 1);
10 vector P;
11 for (int i = 0; i < k; ++i) {
12 for (int q = 0; q < M; ++q) {
13 P.emplace_back(q * k + i); // rotate: i*k^(n-1) + q => q*k + i
14 }
15 }
16 const int total = pow(k, n);
17 string result(n - 1, '0' + k - 1);
18 for (int i = 0; i < total; ++i) {
19 int j = i;
20 // concatenation in lexicographic order of Lyndon words
21 while (P[j] >= 0) {
22 result.push_back('0' + j / M);
23 auto Pj = P[j];
24 P[j] = -1;
25 j = Pj;
26 }
27 }
28 return result;
29 }
30 };
31
32 // Time: O(k^n)
33 // Space: O(k^n)
34 class Solution2 {
35 public:
36 string crackSafe(int n, int k) {
37 const int M = pow(k, n - 1);
38 int unique_rolling_hash = 0;
39 string result(n - 1, '0');
40 unordered_set lookup;
41 const int total = pow(k, n);
42 while (lookup.size() < total) {
43 for (int i = k - 1; i >= 0; --i) { // preorder like traversal relative to initial result to avoid getting stuck, i.e. don'
44 const auto& new_unique_rolling_hash = unique_rolling_hash * k + i;
45 if (!lookup.count(new_unique_rolling_hash)) {
46 lookup.emplace(new_unique_rolling_hash);
47 result.push_back('0' + i);
48 unique_rolling_hash = new_unique_rolling_hash % M;
49 break;
50 }
51 }
52 }
53 return result;
54 }
55 };
56
57 // Time: O(k^n)
58 // Space: O(k^n)
59 class Solution3 {
60 public:
61 string crackSafe(int n, int k) {
62 const int M = pow(k, n - 1);
63 int unique_rolling_hash = 0;
64 unordered_set lookup;
65 string result(n - 1, '0');
66 dfs(k, M, unique_rolling_hash, &lookup, &result);
67 return result;
68 }
69
70 private:
71 void dfs(int k, int M, int unique_rolling_hash, unordered_set *lookup, string *result) {
72 for (int i = k - 1; i >= 0; --i) { // preorder like traversal relative to initial result to avoid getting stuck, i.e. don't us
73 const auto& new_unique_rolling_hash = unique_rolling_hash * k + i;
74 if (!lookup->count(new_unique_rolling_hash)) {
75 lookup->emplace(new_unique_rolling_hash);
76 result->push_back('0' + i);
77 dfs(k, M, new_unique_rolling_hash % M, lookup, result);
78 break;
79 }
80 }
81 }
82 };
83
84 // Time: O(n * k^n)
85 // Space: O(n * k^n)
86 class Solution4 {
87 public:
88 string crackSafe(int n, int k) {
89 string result(n - 1, '0' + k - 1);
90 unordered_set lookup;
91 const int total = pow(k, n);
92 while (lookup.size() < total) {
93 const auto& node = result.substr(result.length() - n + 1);
94 for (int i = 0; i < k; ++i) { // preorder like traversal relative to initial result to avoid getting stuck, i.e. don't use
95 const auto& neighbor = node + to_string(i);
96 if (!lookup.count(neighbor)) {
97 lookup.emplace(neighbor);
98 result.push_back('0' + i);
99 break;
100 }
101 }
102 }
103 return result;
104 }
105 };
106
107 // Time: O(n * k^n)
108 // Space: O(n * k^n)
109 class Solution5 {
110 public:
111 string crackSafe(int n, int k) {
112 unordered_set lookup;
113 string result(n - 1, '0' + k - 1);
114 auto node = result;
115 dfs(k, node, &lookup, &result);
116 return result;
117 }
118
119 private:
120 void dfs(int k, const string& node, unordered_set *lookup, string *result) {
121 for (int i = 0; i < k; ++i) { // preorder like traversal relative to initial result to avoid getting stuck, i.e. don't use k-1
122 const auto& neighbor = node + to_string(i);
123 if (!lookup->count(neighbor)) {
124 lookup->emplace(neighbor);
125 result->push_back('0' + i);
126 dfs(k, neighbor.substr(1), lookup, result);
127 break;
128 }
129 }
130 }
131 };
*****************

138. Cracking the Safe(Python)


*****************

1 # Time: O(k^n)
2 # Space: O(k^n)
3
4 class Solution(object):
5 def crackSafe(self, n, k):
6 """
7 :type n: int
8 :type k: int
9 :rtype: str
10 """
11 M = k**(n-1)
12 P = [q*k+i for i in xrange(k) for q in xrange(M)] # rotate: i*k^(n-1) + q => q*k + i
13 result = [str(k-1)]*(n-1)
14 for i in xrange(k**n):
15 j = i
16 # concatenation in lexicographic order of Lyndon words
17 while P[j] >= 0:
18 result.append(str(j//M))
19 P[j], j = -1, P[j]
20 return "".join(result)
21
22
23 # Time: O(k^n)
24 # Space: O(k^n)
25 class Solution2(object):
26 def crackSafe(self, n, k):
27 """
28 :type n: int
29 :type k: int
30 :rtype: str
31 """
32 total = k**n
33 M = total//k
34 unique_rolling_hash = 0
35 result = [str(0)]*(n-1)
36 lookup = set()
37 while len(lookup) < total:
38 for i in reversed(xrange(k)): # preorder like traversal relative to initial result to avoid getting stuck, i.e. don't use
39 new_unique_rolling_hash = unique_rolling_hash*k + i
40 if new_unique_rolling_hash not in lookup:
41 lookup.add(new_unique_rolling_hash)
42 result.append(str(i))
43 unique_rolling_hash = new_unique_rolling_hash%M
44 break
45 return "".join(result)
46
47
48 # Time: O(k^n)
49 # Space: O(k^n)
50 class Solution3(object):
51 def crackSafe(self, n, k):
52 """
53 :type n: int
54 :type k: int
55 :rtype: str
56 """
57 M = k**(n-1)
58 def dfs(k, unique_rolling_hash, lookup, result):
59 for i in reversed(xrange(k)): # preorder like traversal relative to initial result to avoid getting stuck, i.e. don't use
60 new_unique_rolling_hash = unique_rolling_hash*k + i
61 if new_unique_rolling_hash not in lookup:
62 lookup.add(new_unique_rolling_hash)
63 result.append(str(i))
64 dfs(k, new_unique_rolling_hash%M, lookup, result)
65 break
66
67 unique_rolling_hash = 0
68 result = [str(0)]*(n-1)
69 lookup = set()
70 dfs(k, unique_rolling_hash, lookup, result)
71 return "".join(result)
72
73
74 # Time: O(n * k^n)
75 # Space: O(n * k^n)
76 class Solution4(object):
77 def crackSafe(self, n, k):
78 """
79 :type n: int
80 :type k: int
81 :rtype: str
82 """
83 result = [str(k-1)]*(n-1)
84 lookup = set()
85 total = k**n
86 while len(lookup) < total:
87 node = result[len(result)-n+1:]
88 for i in xrange(k): # preorder like traversal relative to initial result to avoid getting stuck, i.e. don't use k-1 until
89 neighbor = "".join(node) + str(i)
90 if neighbor not in lookup:
91 lookup.add(neighbor)
92 result.append(str(i))
93 break
94 return "".join(result)
95
96
97 # Time: O(n * k^n)
98 # Space: O(n * k^n)
99 class Solution5(object):
100 def crackSafe(self, n, k):
101 """
102 :type n: int
103 :type k: int
104 :rtype: str
105 """
106 def dfs(k, node, lookup, result):
107 for i in xrange(k): # preorder like traversal relative to initial result to avoid getting stuck, i.e. don't use k-1 until
108 neighbor = node + str(i)
109 if neighbor not in lookup:
110 lookup.add(neighbor)
111 result.append(str(i))
112 dfs(k, neighbor[1:], lookup, result)
113 break
114
115 result = [str(k-1)]*(n-1)
116 lookup = set()
117 dfs(k, "".join(result), lookup, result)
118 return "".join(result)
119
**********************************

139. Set Intersection Size At Least Two


**********************************

An integer interval [a, b] (for integers a < b ) is a set of all consecutive integers froma to b, including a and b.

Find the minimum size of a set S such that for every integer interval A inintervals, the intersection of S with A has a size of at
least two.

Example 1:

Input: intervals = [[1,3],[1,4],[2,5],[3,5]]


Output: 3
Explanation: Consider the set S = {2, 3, 4}. For each interval, there are at least 2 elements from S in the interval.
Also, there isn't a smaller size set that fulfills the above condition.
Thus, we output the size of this set, which is 3.

Example 2:

Input: intervals = [[1,2],[2,3],[2,4],[4,5]]


Output: 5
Explanation: An example of a minimum sized set is {1, 2, 3, 4, 5}.

Constraints:

1 <= intervals.length <= 3000


intervals[i].length == 2
0 <= ai < bi <= 108
**********************************

139. Set Intersection Size At Least Two(C++)


**********************************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 // greedy solution
5 class Solution {
6 public:
7 int intersectionSizeTwo(vector>& intervals) {
8 sort(intervals.begin(), intervals.end(),
9 [](const vector& a, const vector& b) {
10 return (a[0] != b[0]) ? (a[0] < b[0]) : (b[1] < a[1]);
11 });
12 vector cnts(intervals.size(), 2);
13 int result = 0;
14 while (!intervals.empty()) {
15 auto start = intervals.back()[0]; intervals.pop_back();
16 auto cnt = cnts.back(); cnts.pop_back();
17 for (int s = start; s < start + cnt; ++s) {
18 for (int i = 0; i < intervals.size(); ++i) {
19 if (cnts[i] && s <= intervals[i][1]) {
20 --cnts[i];
21 }
22 }
23 }
24 result += cnt;
25 }
26 return result;
27 }
28 };
**********************************

139. Set Intersection Size At Least Two(Python)


**********************************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 class Solution(object):
5 def intersectionSizeTwo(self, intervals):
6 """
7 :type intervals: List[List[int]]
8 :rtype: int
9 """
10 intervals.sort(key = lambda s_e: (s_e[0], -s_e[1]))
11 cnts = [2] * len(intervals)
12 result = 0
13 while intervals:
14 (start, _), cnt = intervals.pop(), cnts.pop()
15 for s in xrange(start, start+cnt):
16 for i in xrange(len(intervals)):
17 if cnts[i] and s <= intervals[i][1]:
18 cnts[i] -= 1
19 result += cnt
20 return result
21
******************

140. Employee Free Time


******************

We are given a list schedule of employees, which represents the working time for each employee.

Each employee has a list of non-overlapping Intervals, and these intervals are in sorted order.

Return the list of finite intervals representing common, positive-length free time for all employees, also in sorted order.

(Even though we are representing Intervals in the form [x, y] , the objects inside are Intervals, not lists or arrays. For example,
schedule[0][0].start = 1, schedule[0][0].end = 2 , and schedule[0][0][0] is not defined). Also, we wouldn't include intervals like [5, 5] in our
answer, as they have zero length.

Example 1:

Input: schedule = [[[1,2],[5,6]],[[1,3]],[[4,10]]]


Output: [[3,4]]
Explanation: There are a total of three employees, and all common
free time intervals would be [-inf, 1], [3, 4], [10, inf].
We discard any intervals that contain inf as they aren't finite.

Example 2:

Input: schedule = [[[1,3],[6,7]],[[2,4]],[[2,5],[9,12]]]


Output: [[5,6],[7,9]]

Constraints:

1 <= schedule.length , schedule[i].length <= 50


0 <= schedule[i].start < schedule[i].end <= 10^8
******************

140. Employee Free Time(C++)


******************

1 // Time: O(m * logn), m is the number of schedule, n is the number of employees, m >= n
2 // Space: O(n)
3
4 /**
5 * Definition for an interval.
6 * struct Interval {
7 * int start;
8 * int end;
9 * Interval() : start(0), end(0) {}
10 * Interval(int s, int e) : start(s), end(e) {}
11 * };
12 */
13 class Solution {
14 public:
15 vector employeeFreeTime(vector>& schedule) {
16 vector result;
17 using P = pair>;
18 priority_queue, greater

> min_heap; for (int i = 0; i < schedule.size(); ++i) { min_heap.emplace(schedule[i][0].start, make_pair(i, 0)); } int
last_end = -1; while (!min_heap.empty()) { int t; pair p; tie(t, p) = min_heap.top(); min_heap.pop(); if (0 <= last_end
&& last_end < t) { result.emplace_back(last_end, t); } last_end = max(last_end, schedule[p.first][p.second].end); if
(p.second + 1 < schedule[p.first].size()) { min_heap.emplace(schedule[p.first][p.second + 1].start, make_pair(p.first,
p.second + 1)); } } return result; } };
******************

140. Employee Free Time(Python)


******************

1 # Time: O(m * logn), m is the number of schedule, n is the number of employees, m >= n
2 # Space: O(n)
3
4 import heapq
5
6
7 class Interval(object):
8 def __init__(self, s=0, e=0):
9 self.start = s
10 self.end = e
11
12
13 class Solution(object):
14 def employeeFreeTime(self, schedule):
15 """
16 :type schedule: List[List[Interval]]
17 :rtype: List[Interval]
18 """
19 result = []
20 min_heap = [(emp[0].start, eid, 0) for eid, emp in enumerate(schedule)]
21 heapq.heapify(min_heap)
22 last_end = -1
23 while min_heap:
24 t, eid, i = heapq.heappop(min_heap)
25 if 0 <= last_end < t:
26 result.append(Interval(last_end, t))
27 last_end = max(last_end, schedule[eid][i].end)
28 if i+1 < len(schedule[eid]):
29 heapq.heappush(min_heap, (schedule[eid][i+1].start, eid, i+1))
30 return result
31
*********************

141. Special Binary String


*********************

Special binary strings are binary strings with the following two properties:

The number of 0's is equal to the number of 1's.


Every prefix of the binary string has at least as many1's as 0's.

You are given a special binary string s .

A move consists of choosing two consecutive, non-empty, special substrings ofs , and swapping them. Two strings are
consecutive if the last character of the first string is exactly one index before the first character of the second string.

Return the lexicographically largest resulting string possible after applying the mentioned operations on the string.

Example 1:

Input: s = "11011000"
Output: "11100100"
Explanation: The strings "10" [occuring at s[1]] and "1100" [at s[3]] are swapped.
This is the lexicographically largest string possible after some number of swaps.

Example 2:

Input: s = "10"
Output: "10"

Constraints:

1 <= s.length <= 50


s[i] is either '0' or '1'.
s is a special binary string.
*********************

141. Special Binary String(C++)


*********************

1 // Time: f(n) = k * f(n/k) + n/k * klogk <= O(logn * nlogk) <= O(n^2)
2 // n is the length of S, k is the max number of special strings in each depth
3 // Space: O(n)
4
5 class Solution {
6 public:
7 string makeLargestSpecial(string S) {
8 vector result;
9 int anchor = 0, count = 0;
10 for (int i = 0; i < S.length(); ++i) {
11 (S[i] == '1') ? ++count : --count;
12 if (count == 0) {
13 result.emplace_back("1");
14 result.back() += makeLargestSpecial(S.substr(anchor + 1, i - anchor - 1));
15 result.back() += "0";
16 anchor = i + 1;
17 }
18 }
19 sort(result.begin(), result.end(), greater());
20 return accumulate(result.begin(), result.end(), string());
21 }
22 };
*********************

141. Special Binary String(Python)


*********************

1 # Time: f(n) = k * f(n/k) + n/k * klogk <= O(logn * nlogk) <= O(n^2)
2 # n is the length of S, k is the max number of special strings in each depth
3 # Space: O(n)
4
5 class Solution(object):
6 def makeLargestSpecial(self, S):
7 """
8 :type S: str
9 :rtype: str
10 """
11 result = []
12 anchor = count = 0
13 for i, v in enumerate(S):
14 count += 1 if v == '1' else -1
15 if count == 0:
16 result.append("1{}0".format(self.makeLargestSpecial(S[anchor+1:i])))
17 anchor = i+1
18 result.sort(reverse = True)
19 return "".join(result)
20
*********************

142. Couples Holding Hands


*********************

There are n couples sitting in 2n seats arranged in a row and want to hold hands.

The people and seats are represented by an integer arrayrow where row[i] is the ID of the person sitting in theith seat. The
couples are numbered in order, the first couple being (0, 1) , the second couple being (2, 3) , and so on with the last couple
being (2n - 2, 2n - 1) .

Return the minimum number of swaps so that every couple is sitting side by side. A swap consists of choosing any two
people, then they stand up and switch seats.

Example 1:

Input: row = [0,2,1,3]


Output: 1
Explanation: We only need to swap the second (row[1]) and third (row[2]) person.

Example 2:

Input: row = [3,2,0,1]


Output: 0
Explanation: All couples are already seated side by side.

Constraints:

2n == row.length
2 <= n <= 30
n is even.
0 <= row[i] < 2n
All the elements of row are unique.
*********************

142. Couples Holding Hands(C++)


*********************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int minSwapsCouples(vector& row) {
7 int N = row.size() / 2;
8 vector> couples(N);
9 for (int seat = 0; seat < row.size(); ++seat) {
10 couples[row[seat] / 2].emplace_back(seat / 2);
11 }
12 vector> adj(N);
13 for (const auto& couple : couples) {
14 adj[couple[0]].emplace_back(couple[1]);
15 adj[couple[1]].emplace_back(couple[0]);
16 }
17
18 int result = 0;
19 for (int couch = 0; couch < N; ++couch) {
20 if (adj[couch].empty()) {
21 continue;
22 }
23 int couch1 = couch;
24 int couch2 = adj[couch1].back(); adj[couch1].pop_back();
25 while (couch2 != couch) {
26 ++result;
27 adj[couch2].erase(find(adj[couch2].begin(), adj[couch2].end(), couch1));
28 couch1 = couch2;
29 couch2 = adj[couch1].back(); adj[couch1].pop_back();
30 }
31 }
32 return result; // also equals to N - (# of cycles)
33 }
34 };
*********************

142. Couples Holding Hands(Python)


*********************

1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 def minSwapsCouples(self, row):
6 """
7 :type row: List[int]
8 :rtype: int
9 """
10 N = len(row)//2
11 couples = [[] for _ in xrange(N)]
12 for seat, num in enumerate(row):
13 couples[num//2].append(seat//2)
14 adj = [[] for _ in xrange(N)]
15 for couch1, couch2 in couples:
16 adj[couch1].append(couch2)
17 adj[couch2].append(couch1)
18
19 result = 0
20 for couch in xrange(N):
21 if not adj[couch]: continue
22 couch1, couch2 = couch, adj[couch].pop()
23 while couch2 != couch:
24 result += 1
25 adj[couch2].remove(couch1)
26 couch1, couch2 = couch2, adj[couch2].pop()
27 return result # also equals to N - (# of cycles)
28
****************************

143. Max Chunks To Make Sorted II


****************************

You are given an integer array arr.

We split arr into some number of chunks (i.e., partitions), and individually sort each chunk. After concatenating them, the
result should equal the sorted array.

Return the largest number of chunks we can make to sort the array.

Example 1:

Input: arr = [5,4,3,2,1]


Output: 1
Explanation:
Splitting into two or more chunks will not return the required result.
For example, splitting into [5, 4], [3, 2, 1] will result in [4, 5, 1, 2, 3], which isn't sorted.

Example 2:

Input: arr = [2,1,3,4,4]


Output: 4
Explanation:
We can split into two chunks, such as [2, 1], [3, 4, 4].
However, splitting into [2, 1], [3], [4], [4] is the highest number of chunks possible.

Constraints:

1 <= arr.length <= 2000


0 <= arr[i] <= 10 8
****************************

143. Max Chunks To Make Sorted II(C++)


****************************

1 // Time: O(n)
2 // Space: O(n)
3
4 // mono stack solution
5 class Solution {
6 public:
7 int maxChunksToSorted(vector& arr) {
8 vector increasing_stk;
9 for (const auto& num : arr) {
10 int max_num = empty(increasing_stk) ? num : max(increasing_stk.back(), num);
11 while (!empty(increasing_stk) && increasing_stk.back() > num) {
12 increasing_stk.pop_back();
13 }
14 increasing_stk.emplace_back(max_num);
15 }
16 return size(increasing_stk);
17 }
18 };
19
20 // Time: O(nlogn)
21 // Space: O(n)
22 class Solution2 {
23 public:
24 int maxChunksToSorted(vector& arr) {
25 vector idxs(arr.size());
26 iota(idxs.begin(), idxs.end(), 0);
27 sort(idxs.begin(), idxs.end(),
28 [&](int i1, int i2) {
29 return arr[i1] != arr[i2] ? arr[i1] < arr[i2] : i1 < i2;
30 });
31
32 int result = 0;
33 for (auto i = 0, max_i = 0; i < idxs.size(); ++i) {
34 max_i = max(max_i, idxs[i]);
35 if (max_i == i) ++result;
36 }
37 return result;
38 }
39 };
****************************

143. Max Chunks To Make Sorted II(Python)


****************************

1 # Time: O(n)
2 # Space: O(n)
3
4 # mono stack solution
5 class Solution(object):
6 def maxChunksToSorted(self, arr):
7 """
8 :type arr: List[int]
9 :rtype: int
10 """
11 result, increasing_stk = 0, []
12 for num in arr:
13 max_num = num if not increasing_stk else max(increasing_stk[-1], num)
14 while increasing_stk and increasing_stk[-1] > num:
15 increasing_stk.pop()
16 increasing_stk.append(max_num)
17 return len(increasing_stk)
18
19
20 # Time: O(nlogn)
21 # Space: O(n)
22 class Solution2(object):
23 def maxChunksToSorted(self, arr):
24 """
25 :type arr: List[int]
26 :rtype: int
27 """
28 def compare(i1, i2):
29 return arr[i1]-arr[i2] if arr[i1] != arr[i2] else i1-i2
30
31 idxs = [i for i in xrange(len(arr))]
32 result, max_i = 0, 0
33 for i, v in enumerate(sorted(idxs, cmp=compare)):
34 max_i = max(max_i, v)
35 if max_i == i:
36 result += 1
37 return result
38
*******************

144. Basic Calculator IV


*******************

Given an expression such as expression = "e + 8 - a + 5" and an evaluation map such as {"e": 1} (given in terms of evalvars = ["e"]
and evalints = [1] ), return a list of tokens representing the simplified expression, such as ["-1*a","14"]

An expression alternates chunks and symbols, with a space separating each chunk and symbol.
A chunk is either an expression in parentheses, a variable, or a non-negative integer.
A variable is a string of lowercase letters (not including digits.) Note that variables can be multiple letters, and note that
variables never have a leading coefficient or unary operator like "2x" or "-x".

Expressions are evaluated in the usual order: brackets first, then multiplication, then addition and subtraction.

For example, expression = "1 + 2 * 3" has an answer of ["7"].

The format of the output is as follows:

For each term of free variables with a non-zero coefficient, we write the free variables within a term in sorted order
lexicographically.
For example, we would never write a term like "b*a*c", only "a*b*c".
Terms have degrees equal to the number of free variables being multiplied, counting multiplicity. We write the largest
degree terms of our answer first, breaking ties by lexicographic order ignoring the leading coefficient of the term.
For example, "a*a*b*c" has degree 4.
The leading coefficient of the term is placed directly to the left with an asterisk separating it from the variables (if they
exist.) A leading coefficient of 1 is still printed.
An example of a well-formatted answer is ["-2*a*a*a", "3*a*a*b", "3*b*b", "4*a", "5*c", "-6"] .
Terms (including constant terms) with coefficient0 are not included.
For example, an expression of "0" has an output of [].

Example 1:

Input: expression = "e + 8 - a + 5", evalvars = ["e"], evalints = [1]


Output: ["-1*a","14"]

Example 2:

Input: expression = "e - 8 + temperature - pressure", evalvars = ["e", "temperature"], evalints = [1, 12]
Output: ["-1*pressure","5"]

Example 3:

Input: expression = "(e + 8) * (e - 8)", evalvars = [], evalints = []


Output: ["1*e*e","-64"]

Example 4:

Input: expression = "a * b * c + b * a * c * 4", evalvars = [], evalints = []


Output: ["5*a*b*c"]

Example 5:
Input: expression = "((a - b) * (b - c) + (c - a)) * ((a - b) + (b - c) * (c - a))", evalvars = [], evalints = []
Output: ["-1*a*a*b*b","2*a*a*b*c","-1*a*a*c*c","1*a*b*b*b","-1*a*b*b*c","-1*a*b*c*c","1*a*c*c*c","-1*b*b*b*c","2*b*b*c*c","-1*b*c*c*c","2*a*a

Constraints:

1 <= expression.length <= 250


expression consists of lowercase English letters, digits, '+' , '-', '*', '(', ')', ' '.
expression does not contain any leading or trailing spaces.
All the tokens in expression are separated by a single space.
0 <= evalvars.length <= 100
1 <= evalvars[i].length <= 20
evalvars[i] consists of lowercase English letters.
evalints.length == evalvars.length
-100 <= evalints[i] <= 100
*******************

144. Basic Calculator IV(C++)


*******************

1 // Time: +: O(d * t), t is the number of terms, d is the average degree of terms
2 // -: O(d * t)
3 // *: O(d * t^2)
4 // eval: O(d * t)
5 // to_list: O(d * tlogt)
6 // Space: O(e + d * t), e is the number of evalvars
7
8 class Poly {
9 public:
10 Poly() {}
11
12 Poly(const string& expr) {
13 vector key;
14 if (is_number(expr)) {
15 if (stoi(expr)) {
16 polies_[key] = stoi(expr);
17 }
18 } else {
19 key.emplace_back(expr);
20 ++polies_[key];
21 }
22 }
23
24 Poly operator+(const Poly &rhs) const { // Time: O(d * t)
25 Poly result;
26 for (const auto& kvp : polies_) {
27 result.update(kvp.first, kvp.second);
28 }
29 for (const auto& kvp : rhs.polies_) {
30 result.update(kvp.first, kvp.second);
31 }
32 return result;
33 }
34
35 Poly operator-(const Poly &rhs) const { // Time: O(d * t)
36 Poly result;
37 for (const auto& kvp : polies_) {
38 result.update(kvp.first, kvp.second);
39 }
40 for (const auto& kvp : rhs.polies_) {
41 result.update(kvp.first, -kvp.second);
42 }
43 return result;
44 }
45
46 Poly operator*(const Poly &rhs) const { // Time: O(d * t^2)
47 Poly result;
48 for (const auto& kvp1 : polies_) {
49 for (const auto& kvp2 : rhs.polies_) {
50 result.update(merge(kvp1.first, kvp2.first),
51 kvp1.second * kvp2.second);
52 }
53 }
54 return result;
55 }
56
57 Poly eval(const unordered_map& lookup) const { // Time: O(d * t)
58 Poly result;
59 for (const auto& kvp : polies_) {
60 vector key;
61 int c = kvp.second;
62 for (const auto& token : kvp.first) {
63 if (lookup.count(token)) {
64 c *= lookup.at(token);
65 } else {
66 key.emplace_back(token);
67 }
68 }
69 result.update(key, c);
70 }
71 return result;
72 }
73
74 operator vector() const { // Time: O(d * tlogt)
75 map, int, Compare>> sorted(polies_.begin(), polies_.end());
76 vector result;
77 for (const auto& kvp : sorted) {
78 vector tmp(kvp.first);
79 tmp.emplace(tmp.begin(), to_string(kvp.second));
80 result.emplace_back(join(tmp, "*"));
81 }
82 return result;
83 }
84
85 private:
86 bool is_number(const std::string &s) const {
87 return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit);
88 }
89
90 void update(const vector& key, int val) {
91 polies_[key] += val;
92 if (polies_[key] == 0) {
93 polies_.erase(key);
94 }
95 }
96
97 vector merge(const vector& arr1, const vector& arr2) const { // Time: O(d)
98 vector result;
99 int i = 0, j = 0;
100 while (i < arr1.size() || j < arr2.size()) {
101 if (j == arr2.size() || (i != arr1.size() && arr1[i] < arr2[j])) {
102 result.emplace_back(arr1[i++]);
103 } else {
104 result.emplace_back(arr2[j++]);
105 }
106 }
107 return result;
108 }
109
110 string join(const vector& strings, const string& delim) const {
111 if (strings.empty()) {
112 return "";
113 }
114 ostringstream imploded;
115 copy(strings.begin(), prev(strings.end()), ostream_iterator(imploded, delim.c_str()));
116 return imploded.str() + *prev(strings.end());
117 }
118
119 template
120 class Compare {
121 public:
122 bool operator()
123 (const ContType& x,const ContType& y) const {
124 return x.size() != y.size() ? x.size() > y.size() : x < y;
125 }
126 };
127
128 template
129 struct Hash {
130 size_t operator()(const ContType& v) const {
131 size_t seed = 0;
132 for (const auto& i : v) {
133 seed ^= std::hash{}(i) + 0x9e3779b9 + (seed<<6) + (seed>>2);
134 }
135 return seed;
135 return seed;
136 }
137 };
138
139 unordered_map, int, Hash>> polies_;
140 };
141
142 class Solution {
143 public:
144 vector basicCalculatorIV(string expression, vector& evalvars, vector& evalints) {
145 unordered_map lookup;
146 for (int i = 0; i < evalvars.size(); ++i) {
147 lookup[evalvars[i]] = evalints[i];
148 }
149 return parse(expression).eval(lookup);
150 }
151
152 private:
153 Poly parse(const string& s) {
154 static const unordered_map precedence = {{'+', 0}, {'-', 0}, {'*', 1}};
155
156 stack operands;
157 stack operators;
158 string operand;
159 for (int i = 0; i < size(s); ++i) {
160 if (isalnum(s[i])) {
161 operand.push_back(s[i]);
162 if (i + 1 == size(s) || !isalnum(s[i + 1])) {
163 operands.emplace(Poly(operand));
164 operand = "";
165 }
166 } else if (s[i] == '(') {
167 operators.emplace(s[i]);
168 } else if (s[i] == ')') {
169 while (operators.top() != '(') {
170 compute(&operands, &operators);
171 }
172 operators.pop();
173 } else if (precedence.count(s[i])) {
174 while (!empty(operators) && precedence.count(operators.top()) &&
175 precedence.at(operators.top()) >= precedence.at(s[i])) {
176 compute(&operands, &operators);
177 }
178 operators.emplace(s[i]);
179 }
180 }
181 while (!empty(operators)) {
182 compute(&operands, &operators);
183 }
184 return operands.top();
185 }
186
187 template
188 void compute(stack *operands, stack *operators) {
189 const auto right = move(operands->top()); operands->pop();
190 const auto left = move(operands->top()); operands->pop();
191 const char op = operators->top(); operators->pop();
192 if (op == '+') {
193 operands->emplace(left + right);
194 } else if (op == '-') {
195 operands->emplace(left - right);
196 } else if (op == '*') {
197 operands->emplace(left * right);
198 }
199 }
200 };
201
202 class Solution2 {
203 public:
204 vector basicCalculatorIV(string expression, vector& evalvars, vector& evalints) {
205 unordered_map lookup;
206 for (int i = 0; i < evalvars.size(); ++i) {
207 lookup[evalvars[i]] = evalints[i];
208 }
208 }
209 return parse(expression).eval(lookup);
210 }
211
212 private:
213 Poly parse(const string& s) {
214 if (s.empty()) {
215 return Poly();
216 }
217 stack operands;
218 stack operators;
219 string operand;
220 for (int i = s.length() - 1; i >= 0; --i) {
221 if (isalnum(s[i])) {
222 operand.push_back(s[i]);
223 if (i == 0 || !isalnum(s[i - 1])) {
224 reverse(operand.begin(), operand.end());
225 operands.emplace(Poly(operand));
226 operand.clear();
227 }
228 } else if (s[i] == ')' || s[i] == '*') {
229 operators.emplace(s[i]);
230 } else if (s[i] == '+' || s[i] == '-') {
231 while (!operators.empty() && operators.top() == '*') {
232 compute(operands, operators);
233 }
234 operators.emplace(s[i]);
235 } else if (s[i] == '(') {
236 while (operators.top() != ')') {
237 compute(operands, operators);
238 }
239 operators.pop();
240 }
241 }
242 while (!operators.empty()) {
243 compute(operands, operators);
244 }
245 return operands.top();
246 }
247
248 template
249 void compute(stack& operands, stack& operators) {
250 const auto left = operands.top();
251 operands.pop();
252 const auto right = operands.top();
253 operands.pop();
254 const char op = operators.top();
255 operators.pop();
256 if (op == '+') {
257 operands.emplace(left + right);
258 } else if (op == '-') {
259 operands.emplace(left - right);
260 } else if (op == '*') {
261 operands.emplace(left * right);
262 }
263 }
264 };
*******************

144. Basic Calculator IV(Python)


*******************

1 # Time: +: O(d * t), t is the number of terms,


2 # d is the average degree of terms
3 # -: O(d * t)
4 # *: O(d * t^2)
5 # eval: O(d * t)
6 # to_list: O(d * tlogt)
7 # Space: O(e + d * t), e is the number of evalvars
8
9 import collections
10 import itertools
11 import operator
12
13
14 def clear(result):
15 to_remove = [k for k, v in result.iteritems() if v == 0]
16 for k in to_remove:
17 result.pop(k)
18
19
20 class Poly(collections.Counter):
21 def __init__(self, expr=None):
22 if expr is None:
23 return
24 if expr.isdigit():
25 if int(expr):
26 self.update({(): int(expr)})
27 else:
28 self[(expr,)] += 1
29
30 def __add__(self, other):
31 result = Poly()
32 result.update(self)
33 result.update(other)
34 clear(result)
35 return result
36
37 def __sub__(self, other):
38 result = Poly()
39 result.update(self)
40 result.update({k: -v for k, v in other.iteritems()})
41 clear(result)
42 return result
43
44 def __mul__(self, other):
45 def merge(k1, k2):
46 result = []
47 i, j = 0, 0
48 while i != len(k1) or j != len(k2):
49 if j == len(k2) or (i != len(k1) and k1[i] < k2[j]):
50 result.append(k1[i])
51 i += 1
52 else:
53 result.append(k2[j])
54 j += 1
55 return result
56
57 result = Poly()
58 for k1, v1 in self.iteritems():
59 for k2, v2 in other.iteritems():
60 result.update({tuple(merge(k1, k2)): v1*v2})
61 clear(result)
62 return result
63
64 def eval(self, lookup):
65 result = Poly()
66 for polies, c in self.iteritems():
67 key = []
68 for var in polies:
69 if var in lookup:
70 c *= lookup[var]
71 else:
72 key.append(var)
73 result[tuple(key)] += c
74 clear(result)
75 return result
76
77 def to_list(self):
78 return ["*".join((str(v),) + k)
79 for k, v in sorted(self.iteritems(),
80 key=lambda x: (-len(x[0]), x[0]))]
81
82
83 class Solution(object):
84 def basicCalculatorIV(self, expression, evalvars, evalints):
85 """
86 :type expression: str
87 :type evalvars: List[str]
88 :type evalints: List[int]
89 :rtype: List[str]
90 """
91 ops = {'+':operator.add, '-':operator.sub, '*':operator.mul}
92 def compute(operands, operators):
93 right, left = operands.pop(), operands.pop()
94 operands.append(ops[operators.pop()](left, right))
95
96 def parse(s):
97 precedence = {'+':0, '-':0, '*':1}
98 operands, operators, operand = [], [], []
99 for i in xrange(len(s)):
100 if s[i].isalnum():
101 operand.append(s[i])
102 if i == len(s)-1 or not s[i+1].isalnum():
103 operands.append(Poly("".join(operand)))
104 operand = []
105 elif s[i] == '(':
106 operators.append(s[i])
107 elif s[i] == ')':
108 while operators[-1] != '(':
109 compute(operands, operators)
110 operators.pop()
111 elif s[i] in precedence:
112 while operators and operators[-1] in precedence and \
113 precedence[operators[-1]] >= precedence[s[i]]:
114 compute(operands, operators)
115 operators.append(s[i])
116 while operators:
117 compute(operands, operators)
118 return operands[-1]
119
120 lookup = dict(itertools.izip(evalvars, evalints))
121 return parse(expression).eval(lookup).to_list()
122
123
124 class Solution2(object):
125 def basicCalculatorIV(self, expression, evalvars, evalints):
126 """
127 :type expression: str
128 :type evalvars: List[str]
129 :type evalints: List[int]
130 :rtype: List[str]
131 """
132 def compute(operands, operators):
133 left, right = operands.pop(), operands.pop()
134 op = operators.pop()
135 if op == '+':
135 if op == '+':
136 operands.append(left + right)
137 elif op == '-':
138 operands.append(left - right)
139 elif op == '*':
140 operands.append(left * right)
141
142 def parse(s):
143 if not s:
144 return Poly()
145 operands, operators = [], []
146 operand = ""
147 for i in reversed(xrange(len(s))):
148 if s[i].isalnum():
149 operand += s[i]
150 if i == 0 or not s[i-1].isalnum():
151 operands.append(Poly(operand[::-1]))
152 operand = ""
153 elif s[i] == ')' or s[i] == '*':
154 operators.append(s[i])
155 elif s[i] == '+' or s[i] == '-':
156 while operators and operators[-1] == '*':
157 compute(operands, operators)
158 operators.append(s[i])
159 elif s[i] == '(':
160 while operators[-1] != ')':
161 compute(operands, operators)
162 operators.pop()
163 while operators:
164 compute(operands, operators)
165 return operands[-1]
166
167 lookup = dict(itertools.izip(evalvars, evalints))
168 return parse(expression).eval(lookup).to_list()
169
********************

145. Basic Calculator III


********************

Implement a basic calculator to evaluate a simple expression string.

The expression string contains only non-negative integers, '+' , '-', '*', '/' operators, and open '(' and closing parentheses ')'. The
integer division should truncate toward zero.

You may assume that the given expression is always valid. All intermediate results will be in the range of[-231, 2 31 - 1] .

Note: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such aseval().

Example 1:

Input: s = "1+1"
Output: 2

Example 2:

Input: s = "6-4/2"
Output: 4

Example 3:

Input: s = "2*(5+5*2)/3+(6/2+8)"
Output: 21

Example 4:

Input: s = "(2+6*3+5-(3*14/7+2)*5)+3"
Output: -12

Example 5:

Input: s = "0"
Output: 0

Constraints:

1 <= s <= 10 4
s consists of digits, '+' , '-', '*', '/' , '(', and ')'.
s is a valid expression.
********************

145. Basic Calculator III(C++)


********************

1 // Time: O(n)
2 // Space: O(n)
3
4 // Support +, -, *, /.
5 class Solution {
6 public:
7 int calculate(string s) {
8 static const unordered_map precedence = {{'+', 0}, {'-', 0}, {'*', 1}, {'/', 1}};
9
10 stack operands;
11 stack operators;
12 int64_t operand = 0;
13 for (int i = 0; i < size(s); ++i) {
14 if (isdigit(s[i])) {
15 operand = operand * 10 + s[i] - '0';
16 if (i + 1 == size(s) || !isdigit(s[i + 1])) {
17 operands.emplace(operand);
18 operand = 0;
19 }
20 } else if (s[i] == '(') {
21 operators.emplace(s[i]);
22 } else if (s[i] == ')') {
23 while (operators.top() != '(') {
24 compute(&operands, &operators);
25 }
26 operators.pop();
27 } else if (precedence.count(s[i])) {
28 while (!empty(operators) && precedence.count(operators.top()) &&
29 precedence.at(operators.top()) >= precedence.at(s[i])) {
30 compute(&operands, &operators);
31 }
32 operators.emplace(s[i]);
33 }
34 }
35 while (!empty(operators)) {
36 compute(&operands, &operators);
37 }
38 return operands.top();
39 }
40
41 private:
42 template
43 void compute(stack *operands, stack *operators) {
44 const auto right = operands->top(); operands->pop();
45 const auto left = operands->top(); operands->pop();
46 const char op = operators->top(); operators->pop();
47 if (op == '+') {
48 operands->emplace(left + right);
49 } else if (op == '-') {
50 operands->emplace(left - right);
51 } else if (op == '*') {
52 operands->emplace(left * right);
53 } else if (op == '/') {
54 operands->emplace(left / right);
55 }
56 }
57 };
58
59 // Time: O(n)
60 // Space: O(n)
61 // Support +, -, *, /.
62 class Solution2 {
63 public:
64 int calculate(string s) {
65 stack operands;
66 stack operators;
67 string operand;
68 for (int i = s.length() - 1; i >= 0; --i) {
69 if (isdigit(s[i])) {
70 operand.push_back(s[i]);
71 if (i == 0 || !isdigit(s[i - 1])) {
72 reverse(operand.begin(), operand.end());
73 operands.emplace(stol(operand));
74 operand.clear();
75 }
76 } else if (s[i] == ')' || s[i] == '*' ||
77 s[i] == '/') {
78 operators.emplace(s[i]);
79 } else if (s[i] == '+' || s[i] == '-') {
80 while (!operators.empty() && (operators.top() == '*' ||
81 operators.top() == '/')) {
82 compute(operands, operators);
83 }
84 operators.emplace(s[i]);
85 } else if (s[i] == '(') {
86 // operators at least one element, i.e. ')'.
87 while (operators.top() != ')') {
88 compute(operands, operators);
89 }
90 operators.pop();
91 }
92 }
93 while (!operators.empty()) {
94 compute(operands, operators);
95 }
96 return operands.top();
97 }
98
99 template
100 void compute(stack& operands, stack& operators) {
101 const auto left = operands.top();
102 operands.pop();
103 const auto right = operands.top();
104 operands.pop();
105 const char op = operators.top();
106 operators.pop();
107 if (op == '+') {
108 operands.emplace(left + right);
109 } else if (op == '-') {
110 operands.emplace(left - right);
111 } else if (op == '*') {
112 operands.emplace(left * right);
113 } else if (op == '/') {
114 operands.emplace(left / right);
115 }
116 }
117 };
********************

145. Basic Calculator III(Python)


********************

1 # Time: O(n)
2 # Space: O(n)
3
4 import operator
5
6
7 class Solution(object):
8 def calculate(self, s):
9 """
10 :type s: str
11 :rtype: int
12 """
13 def compute(operands, operators):
14 right, left = operands.pop(), operands.pop()
15 operands.append(ops[operators.pop()](left, right))
16
17 ops = {'+':operator.add, '-':operator.sub, '*':operator.mul, '/':operator.div}
18 precedence = {'+':0, '-':0, '*':1, '/':1}
19 operands, operators, operand = [], [], 0
20 for i in xrange(len(s)):
21 if s[i].isdigit():
22 operand = operand*10 + int(s[i])
23 if i == len(s)-1 or not s[i+1].isdigit():
24 operands.append(operand)
25 operand = 0
26 elif s[i] == '(':
27 operators.append(s[i])
28 elif s[i] == ')':
29 while operators[-1] != '(':
30 compute(operands, operators)
31 operators.pop()
32 elif s[i] in precedence:
33 while operators and operators[-1] in precedence and \
34 precedence[operators[-1]] >= precedence[s[i]]:
35 compute(operands, operators)
36 operators.append(s[i])
37 while operators:
38 compute(operands, operators)
39 return operands[-1]
40
41
42 # Time: O(n)
43 # Space: O(n)
44 class Solution2(object):
45 def calculate(self, s):
46 """
47 :type s: str
48 :rtype: int
49 """
50 operands, operators = [], []
51 operand = ""
52 for i in reversed(xrange(len(s))):
53 if s[i].isdigit():
54 operand += s[i]
55 if i == 0 or not s[i-1].isdigit():
56 operands.append(int(operand[::-1]))
57 operand = ""
58 elif s[i] == ')' or s[i] == '*' or s[i] == '/':
59 operators.append(s[i])
60 elif s[i] == '+' or s[i] == '-':
61 while operators and \
62 (operators[-1] == '*' or operators[-1] == '/'):
63 self.compute(operands, operators)
64 operators.append(s[i])
65 elif s[i] == '(':
66 while operators[-1] != ')':
67 self.compute(operands, operators)
68 operators.pop()
69
70 while operators:
71 self.compute(operands, operators)
72
73 return operands[-1]
74
75 def compute(self, operands, operators):
76 left, right = operands.pop(), operands.pop()
77 op = operators.pop()
78 if op == '+':
79 operands.append(left + right)
80 elif op == '-':
81 operands.append(left - right)
82 elif op == '*':
83 operands.append(left * right)
84 elif op == '/':
85 operands.append(left / right)
86
**************

146. Sliding Puzzle


**************

On an 2 x 3 board, there are five tiles labeled from1 to 5, and an empty square represented by 0. A move consists of
choosing 0 and a 4-directionally adjacent number and swapping it.

The state of the board is solved if and only if the board is[[1,2,3],[4,5,0]].

Given the puzzle board board, return the least number of moves required so that the state of the board is solved. If it is
impossible for the state of the board to be solved, return -1.

Example 1:

Input: board = [[1,2,3],[4,0,5]]


Output: 1
Explanation: Swap the 0 and the 5 in one move.

Example 2:

Input: board = [[1,2,3],[5,4,0]]


Output: -1
Explanation: No number of moves will make the board solved.

Example 3:
Input: board = [[4,1,2],[5,0,3]]
Output: 5
Explanation: 5 is the smallest number of moves that solves the board.
An example path:
After move 0: [[4,1,2],[5,0,3]]
After move 1: [[4,1,2],[0,5,3]]
After move 2: [[0,1,2],[4,5,3]]
After move 3: [[1,0,2],[4,5,3]]
After move 4: [[1,2,0],[4,5,3]]
After move 5: [[1,2,3],[4,5,0]]

Example 4:

Input: board = [[3,2,4],[1,5,0]]


Output: 14

Constraints:

board.length == 2
board[i].length == 3
0 <= board[i][j] <= 5
Each value board[i][j] is unique.
**************

146. Sliding Puzzle(C++)


**************

1 // Time: O((m * n) * (m * n)!)


2 // Space: O((m * n) * (m * n)!)
3
4 // A* Search Algorithm
5 class Solution {
6 public:
7 int slidingPuzzle(vector>& board) {
8 const auto& R = board.size(), &C = board[0].size();
9 vector begin, end;
10 unordered_map> expected;
11 int zero_idx = 0;
12 for (int i = 0; i < R; ++i) {
13 for (int j = 0; j < C; ++j) {
14 auto val = (C * i + j + 1) % (R * C);
15 expected[val] = {i, j};
16 if (board[i][j] == 0) {
17 zero_idx = begin.size();
18 }
19 begin.emplace_back(board[i][j]);
20 end.emplace_back(val);
21 }
22 }
23
24 int min_steps = heuristic_estimate(begin, R, C, expected);
25 unordered_set, Hash>> lookup;
26 vector>> closer{make_pair(zero_idx, begin)}, detour;
27 while (true) {
28 if (closer.empty()) {
29 if (detour.empty()) {
30 return -1;
31 }
32 min_steps += 2;
33 swap(closer, detour);
34 }
35 int zero;
36 vector board;
37 tie(zero, board) = closer.back(); closer.pop_back();
38 if (board == end) {
39 return min_steps;
40 }
41 if (!lookup.count(board)) {
42 lookup.emplace(board);
43 int r = zero / C;
44 int c = zero % C;
45 static const vector> directions{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
46 for (const auto& direction : directions) {
47 int i = r + direction.first;
48 int j = c + direction.second;
49 if (0 <= i && i < R && 0 <= j && j < C) {
50 auto new_zero = C * i + j;
51 auto new_board = board;
52 swap(new_board[zero], new_board[new_zero]);
53 int r2, c2;
54 tie(r2, c2) = expected[board[new_zero]];
55 int r1 = zero / C;
56 int c1 = zero % C;
57 int r0 = new_zero / C;
58 int c0 = new_zero % C;
59 bool is_closer = dot({r1 - r0, c1 - c0}, {r2 - r0, c2 - c0}) > 0;
60 is_closer ? closer.emplace_back(new_zero, new_board) : detour.emplace_back(new_zero, new_board);
61 }
62 }
63 }
64 }
65
66 return min_steps;
67 }
68
69 private:
70 int heuristic_estimate(const vector& board, int R, int C, const unordered_map>& expected) {
71 int result = 0;
72 for (int i = 0; i < R; ++i) {
73 for (int j = 0; j < C; ++j) {
74 const auto& val = board[C * i + j];
75 if (val == 0) {
76 continue;
77 }
78 int r, c;
79 tie(r, c) = expected.at(val);
80 result += abs(r - i) + abs(c - j);
81 }
82 }
83 return result;
84 }
85
86 inline int dot(const pair& a, const pair& b) {
87 return a.first * b.first + a.second * b.second;
88 }
89
90 template
91 struct Hash {
92 size_t operator()(const ContType& v) const {
93 size_t seed = 0;
94 for (const auto& i : v) {
95 seed ^= std::hash{}(i) + 0x9e3779b9 + (seed<<6) + (seed>>2);
96 }
97 return seed;
98 }
99 };
100 };
101
102 // Time: O((m * n) * (m * n)! * log((m * n)!))
103 // Space: O((m * n) * (m * n)!)
104 // A* Search Algorithm
105 class Solution2 {
106 public:
107 int slidingPuzzle(vector>& board) {
108 const auto& R = board.size(), &C = board[0].size();
109 vector begin, end;
110 unordered_map> expected;
111 int zero_idx = 0;
112 for (int i = 0; i < R; ++i) {
113 for (int j = 0; j < C; ++j) {
114 auto val = (C * i + j + 1) % (R * C);
115 expected[val] = {i, j};
116 if (board[i][j] == 0) {
117 zero_idx = begin.size();
118 }
119 begin.emplace_back(board[i][j]);
120 end.emplace_back(val);
121 }
122 }
123 vector end_wrong(end);
124 swap(end_wrong[end_wrong.size() - 2], end_wrong[end_wrong.size() - 3]);
125
126 using P = tuple>;
127 priority_queue, greater

> min_heap; min_heap.emplace(make_tuple(0, 0, zero_idx, begin)); unordered_map, int, Hash>> lookup; lookup[begin] = 0;
while (!min_heap.empty()) { int f, g, zero; vector board; tie(f, g, zero, board) = min_heap.top(); min_heap.pop(); if
(board == end) { return g; } if (board == end_wrong) { return -1; } if (f > lookup[board]) { continue; } int r = zero /
C; int c = zero % C; static const vector> directions{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; for (const auto& direction :
directions) { int i = r + direction.first; int j = c + direction.second; if (0 <= i && i < R && 0 <= j && j < C) { auto
new_zero = C * i + j; auto new_board = board; swap(new_board[zero], new_board[new_zero]); f = g + 1 +
heuristic_estimate(new_board, R, C, expected); if (!lookup.count(new_board) || f < lookup[new_board]) lookup[new_board] =
f; min_heap.emplace(make_tuple(f, g + 1, new_zero, new_board)); } } } } return -1; } private: int heuristic_estimate(const
vector& board, int R, int C, const unordered_map>& expected) { int result = 0; for (int i = 0; i < R; ++i) { for (int j =
0; j < C; ++j) { const auto& val = board[C * i + j]; if (val == 0) { continue; } int r, c; tie(r, c) = expected.at(val);
result += abs(r - i) + abs(c - j); } } return result; } template struct Hash { size_t operator()(const ContType& v) const
{ size_t seed = 0; for (const auto& i : v) { seed ^= std::hash{}(i) + 0x9e3779b9 + (seed<<6) + (seed>>2); } return seed; }
}; };
**************

146. Sliding Puzzle(Python)


**************

1 # Time: O((m * n) * (m * n)!)


2 # Space: O((m * n) * (m * n)!)
3
4 import heapq
5 import itertools
6
7
8 # A* Search Algorithm
9 class Solution(object):
10 def slidingPuzzle(self, board):
11 """
12 :type board: List[List[int]]
13 :rtype: int
14 """
15 def dot(p1, p2):
16 return p1[0]*p2[0]+p1[1]*p2[1]
17
18 def heuristic_estimate(board, R, C, expected):
19 result = 0
20 for i in xrange(R):
21 for j in xrange(C):
22 val = board[C*i + j]
23 if val == 0: continue
24 r, c = expected[val]
25 result += abs(r-i) + abs(c-j)
26 return result
27
28 R, C = len(board), len(board[0])
29 begin = tuple(itertools.chain(*board))
30 end = tuple(range(1, R*C) + [0])
31 expected = {(C*i+j+1) % (R*C) : (i, j)
32 for i in xrange(R) for j in xrange(C)}
33
34 min_steps = heuristic_estimate(begin, R, C, expected)
35 closer, detour = [(begin.index(0), begin)], []
36 lookup = set()
37 while True:
38 if not closer:
39 if not detour:
40 return -1
41 min_steps += 2
42 closer, detour = detour, closer
43 zero, board = closer.pop()
44 if board == end:
45 return min_steps
46 if board not in lookup:
47 lookup.add(board)
48 r, c = divmod(zero, C)
49 for direction in ((-1, 0), (1, 0), (0, -1), (0, 1)):
50 i, j = r+direction[0], c+direction[1]
51 if 0 <= i < R and 0 <= j < C:
52 new_zero = i*C+j
53 tmp = list(board)
54 tmp[zero], tmp[new_zero] = tmp[new_zero], tmp[zero]
55 new_board = tuple(tmp)
56 r2, c2 = expected[board[new_zero]]
57 r1, c1 = divmod(zero, C)
58 r0, c0 = divmod(new_zero, C)
59 is_closer = dot((r1-r0, c1-c0), (r2-r0, c2-c0)) > 0
60 (closer if is_closer else detour).append((new_zero, new_board))
61 return min_steps
62
63
64 # Time: O((m * n) * (m * n)! * log((m * n)!))
65 # Space: O((m * n) * (m * n)!)
66 # A* Search Algorithm
67 class Solution2(object):
68 def slidingPuzzle(self, board):
69 """
70 :type board: List[List[int]]
71 :rtype: int
72 """
73 def heuristic_estimate(board, R, C, expected):
74 result = 0
75 for i in xrange(R):
76 for j in xrange(C):
77 val = board[C*i + j]
78 if val == 0: continue
79 r, c = expected[val]
80 result += abs(r-i) + abs(c-j)
81 return result
82
83 R, C = len(board), len(board[0])
84 begin = tuple(itertools.chain(*board))
85 end = tuple(range(1, R*C) + [0])
86 end_wrong = tuple(range(1, R*C-2) + [R*C-1, R*C-2, 0])
87 expected = {(C*i+j+1) % (R*C) : (i, j)
88 for i in xrange(R) for j in xrange(C)}
89
90 min_heap = [(0, 0, begin.index(0), begin)]
91 lookup = {begin: 0}
92 while min_heap:
93 f, g, zero, board = heapq.heappop(min_heap)
94 if board == end: return g
95 if board == end_wrong: return -1
96 if f > lookup[board]: continue
97
98 r, c = divmod(zero, C)
99 for direction in ((-1, 0), (1, 0), (0, -1), (0, 1)):
100 i, j = r+direction[0], c+direction[1]
101 if 0 <= i < R and 0 <= j < C:
102 new_zero = C*i+j
103 tmp = list(board)
104 tmp[zero], tmp[new_zero] = tmp[new_zero], tmp[zero]
105 new_board = tuple(tmp)
106 f = g+1+heuristic_estimate(new_board, R, C, expected)
107 if f < lookup.get(new_board, float("inf")):
108 lookup[new_board] = f
109 heapq.heappush(min_heap, (f, g+1, new_zero, new_board))
110 return -1
111
************************************

147. Minimize Max Distance to Gas Station


************************************

You are given an integer array stations that represents the positions of the gas stations on thex-axis. You are also given an
integer k .

You should add k new gas stations. You can add the stations anywhere on thex-axis, and not necessarily on an integer
position.

Let penalty() be the maximum distance between adjacent gas stations after adding the k new stations.

Return the smallest possible value of penalty() . Answers within 10-6 of the actual answer will be accepted.

Example 1:

Input: stations = [1,2,3,4,5,6,7,8,9,10], k = 9


Output: 0.50000

Example 2:

Input: stations = [23,24,36,39,46,56,57,65,84,98], k = 1


Output: 14.00000

Constraints:

10 <= stations.length <= 2000


0 <= stations[i] <= 10 8
stations is sorted in a strictly increasing order.
1 <= k <= 10 6
************************************

147. Minimize Max Distance to Gas Station(C++)


************************************

1 // Time: O(nlogr)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 double minmaxGasDist(vector& stations, int K) {
7 double left = 0.0;
8 double right = 1e8;
9 while (right - left > 1e-6) {
10 const auto mid = left + (right - left) / 2.0;
11 if (possible(stations, K, mid)) {
12 right = mid;
13 } else {
14 left = mid;
15 }
16 }
17 return left;
18 }
19
20 private:
21 bool possible(const vector& stations, int K, double guess) {
22 int sum = 0;
23 for (int i = 0; i + 1 < stations.size(); ++i) {
24 sum += int((stations[i + 1] - stations[i]) / guess);
25 }
26 return sum <= K;
27 }
28 };
************************************

147. Minimize Max Distance to Gas Station(Python)


************************************

1 # Time: O(nlogr)
2 # Space: O(1)
3
4 class Solution(object):
5 def minmaxGasDist(self, stations, K):
6 """
7 :type stations: List[int]
8 :type K: int
9 :rtype: float
10 """
11 def possible(stations, K, guess):
12 return sum(int((stations[i+1]-stations[i]) / guess)
13 for i in xrange(len(stations)-1)) <= K
14
15 left, right = 0, 10**8
16 while right-left > 1e-6:
17 mid = left + (right-left)/2.0
18 if possible(mid):
19 right = mid
20 else:
21 left = mid
22 return left
23
********************

148. Swim in Rising Water


********************

You are given an n x n integer matrix grid where each value grid[i][j] represents the elevation at that point (i, j).

The rain starts to fall. At time t, the depth of the water everywhere is t. You can swim from a square to another 4-directionally
adjacent square if and only if the elevation of both squares individually are at most t. You can swim infinite distances in zero
time. Of course, you must stay within the boundaries of the grid during your swim.

Return the least time until you can reach the bottom right square(n - 1, n - 1) if you start at the top left square(0, 0) .

Example 1:

Input: grid = [[0,2],[1,3]]


Output: 3
Explanation:
At time 0, you are in grid location (0, 0).
You cannot go anywhere else because 4-directionally adjacent neighbors have a higher elevation than t = 0.
You cannot reach point (1, 1) until time 3.
When the depth of water is 3, we can swim anywhere inside the grid.

Example 2:
Input: grid = [[0,1,2,3,4],[24,23,22,21,5],[12,13,14,15,16],[11,17,18,19,20],[10,9,8,7,6]]
Output: 16
Explanation: The final route is shown.
We need to wait until time 16 so that (0, 0) and (4, 4) are connected.

Constraints:

n == grid.length
n == grid[i].length
1 <= n <= 50
0 <= grid[i][j] < n 2
Each value grid[i][j] is unique.
********************

148. Swim in Rising Water(C++)


********************

1 // Time: O(n^2)
2 // Space: O(n^2)
3
4 class Solution {
5 public:
6 int swimInWater(vector>& grid) {
7 const int n = grid.size();
8 vector> positions(n * n);
9 for (int i = 0; i < n; ++i) {
10 for (int j = 0; j < n; ++j) {
11 positions[grid[i][j]] = {i, j};
12 }
13 }
14 static const vector> directions{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
15 UnionFind union_find(n * n);
16 for (int elevation = 0; elevation < positions.size(); ++elevation) {
17 int i, j;
18 tie(i, j) = positions[elevation];
19 for (const auto& dir : directions) {
20 int x = i + dir.first;
21 int y = j + dir.second;
22 if (0 <= x && x < n &&
23 0 <= y && y < n &&
24 grid[x][y] <= elevation) {
25 union_find.union_set(i * n + j, x * n + y);
26 if (union_find.find_set(0) == union_find.find_set(n * n - 1)) {
27 return elevation;
28 }
29 }
30 }
31 }
32 return n * n - 1;
33 }
34
35 private:
36 class UnionFind {
37 public:
38 UnionFind(const int n) : set_(n) {
39 iota(set_.begin(), set_.end(), 0);
40 }
41
42 int find_set(const int x) {
43 if (set_[x] != x) {
44 set_[x] = find_set(set_[x]); // Path compression.
45 }
46 return set_[x];
47 }
48
49 void union_set(const int x, const int y) {
50 int x_root = find_set(x), y_root = find_set(y);
51 if (x_root != y_root) {
52 set_[min(x_root, y_root)] = max(x_root, y_root);
53 }
54 }
55
56 private:
57 vector set_;
58 };
59 };
********************

148. Swim in Rising Water(Python)


********************

1 # Time: O(n^2)
2 # Space: O(n^2)
3
4 class UnionFind(object):
5 def __init__(self, n):
6 self.set = range(n)
7
8 def find_set(self, x):
9 if self.set[x] != x:
10 self.set[x] = self.find_set(self.set[x]) # path compression.
11 return self.set[x]
12
13 def union_set(self, x, y):
14 x_root, y_root = map(self.find_set, (x, y))
15 if x_root == y_root:
16 return False
17 self.set[min(x_root, y_root)] = max(x_root, y_root)
18 return True
19
20
21 class Solution(object):
22 def swimInWater(self, grid):
23 """
24 :type grid: List[List[int]]
25 :rtype: int
26 """
27 n = len(grid)
28 positions = [None] * (n**2)
29 for i in xrange(n):
30 for j in xrange(n):
31 positions[grid[i][j]] = (i, j)
32 directions = ((-1, 0), (1, 0), (0, -1), (0, 1))
33
34 union_find = UnionFind(n**2)
35 for elevation in xrange(n**2):
36 i, j = positions[elevation]
37 for direction in directions:
38 x, y = i+direction[0], j+direction[1]
39 if 0 <= x < n and 0 <= y < n and grid[x][y] <= elevation:
40 union_find.union_set(i*n+j, x*n+y)
41 if union_find.find_set(0) == union_find.find_set(n**2-1):
42 return elevation
43 return n**2-1
44
45
***************

149. Reaching Points


***************

Given four integers sx, sy, tx, and ty, return true if it is possible to convert the point (sx, sy) to the point (tx, ty) through some
operations, or false otherwise.

The allowed operation on some point (x, y) is to convert it to either (x, x + y) or (x + y, y) .

Example 1:

Input: sx = 1, sy = 1, tx = 3, ty = 5
Output: true
Explanation:
One series of moves that transforms the starting point to the target is:
(1, 1) -> (1, 2)
(1, 2) -> (3, 2)
(3, 2) -> (3, 5)

Example 2:

Input: sx = 1, sy = 1, tx = 2, ty = 2
Output: false

Example 3:

Input: sx = 1, sy = 1, tx = 1, ty = 1
Output: true

Constraints:

1 <= sx, sy, tx, ty <= 10 9


***************

149. Reaching Points(C++)


***************

1 // Time: O(log(max(m, n)))


2 // Space: O(1)
3
4 class Solution {
5 public:
6 bool reachingPoints(int sx, int sy, int tx, int ty) {
7 while (tx >= sx && ty >= sy) {
8 if (tx < ty) {
9 swap(sx, sy);
10 swap(tx, ty);
11 }
12 if (ty > sy) {
13 tx %= ty;
14 } else {
15 return (tx - sx) % ty == 0;
16 }
17 }
18 return false;
19 }
20 };
***************

149. Reaching Points(Python)


***************

1 # Time: O(log(max(m, n)))


2 # Space: O(1)
3
4 class Solution(object):
5 def reachingPoints(self, sx, sy, tx, ty):
6 """
7 :type sx: int
8 :type sy: int
9 :type tx: int
10 :type ty: int
11 :rtype: bool
12 """
13 while tx >= sx and ty >= sy:
14 if tx < ty:
15 sx, sy = sy, sx
16 tx, ty = ty, tx
17 if ty > sy:
18 tx %= ty
19 else:
20 return (tx - sx) % ty == 0
21
22 return False
23
***********************

150. Transform to Chessboard


***********************

You are given an n x n binary grid board. In each move, you can swap any two rows with each other, or any two columns with
each other.

Return the minimum number of moves to transform the board into achessboard board. If the task is impossible, return -1.

A chessboard board is a board where no 0's and no 1's are 4-directionally adjacent.

Example 1:

Input: board = [[0,1,1,0],[0,1,1,0],[1,0,0,1],[1,0,0,1]]


Output: 2
Explanation: One potential sequence of moves is shown.
The first move swaps the first and second column.
The second move swaps the second and third row.

Example 2:

Input: board = [[0,1],[1,0]]


Output: 0
Explanation: Also note that the board with 0 in the top left corner, is also a valid chessboard.

Example 3:

Input: board = [[1,0],[1,0]]


Output: -1
Explanation: No matter what sequence of moves you make, you cannot end with a valid chessboard.
Constraints:

n == board.length
n == board[i].length
2 <= n <= 30
board[i][j] is either 0 or 1.
***********************

150. Transform to Chessboard(C++)


***********************

1 // Time: O(n^2)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int movesToChessboard(vector>& board) {
7 const int N = board.size();
8 unordered_map, int, Hash>> row_lookup, col_lookup;
9 for (int i = 0; i < N; ++i) {
10 const auto& row = board[i];
11 ++row_lookup[row];
12 if (row_lookup.size() > 2) {
13 return -1;
14 }
15 }
16 for (int j = 0; j < N; ++j) {
17 vector col;
18 for (int i = 0; i < N; ++i) {
19 col.emplace_back(board[i][j]);
20 }
21 ++col_lookup[col];
22 if (col_lookup.size() > 2) {
23 return -1;
24 }
25 }
26
27 int row_count = move(N, row_lookup);
28 if (row_count < 0) {
29 return -1;
30 }
31 int col_count = move(N, col_lookup);
32 if (col_count < 0) {
33 return -1;
34 }
35 return row_count + col_count;
36 }
37
38 private:
39 template
40 struct Hash {
41 size_t operator()(const ContType& v) const {
42 size_t seed = 0;
43 for (const auto& i : v) {
44 seed ^= std::hash{}(i) + 0x9e3779b9 + (seed<<6) + (seed>>2);
45 }
46 return seed;
47 }
48 };
49
50 int move(int N, const unordered_map, int, Hash>>& lookup) {
51 if (lookup.size() != 2 ||
52 min(lookup.begin()->second, next(lookup.begin())->second) != N / 2 ||
53 max(lookup.begin()->second, next(lookup.begin())->second) != (N + 1) / 2) {
54 return -1;
55 }
56 const auto& seq1 = lookup.begin()->first;
57 const auto& seq2 = next(lookup.begin())->first;
58 for (int i = 0; i < N; ++i) {
59 if (seq1[i] == seq2[i]) {
60 return -1;
61 }
62 }
63
64 vector begins = (N % 2) ? vector{static_cast(std::count(seq1.begin(), seq1.end(), 1) * 2 > N)} :
65 vector{0, 1};
66 int result = numeric_limits::max();
67 for (const auto& begin : begins) {
68 int i = begin;
69 int sum = 0;
70 for (const auto& v : seq1) {
71 sum += static_cast((i % 2) != v);
72 ++i;
73 }
74 result = min(result, sum / 2);
75 }
76 return result;
77 }
78 };
***********************

150. Transform to Chessboard(Python)


***********************

1 # Time: O(n^2)
2 # Space: O(n^2), used by Counter, this could be reduced to O(n) by skipping invalid input
3
4 import collections
5 import itertools
6
7
8 class Solution(object):
9 def movesToChessboard(self, board):
10 """
11 :type board: List[List[int]]
12 :rtype: int
13 """
14 N = len(board)
15 result = 0
16 for count in (collections.Counter(map(tuple, board)), \
17 collections.Counter(itertools.izip(*board))):
18 if len(count) != 2 or \
19 sorted(count.values()) != [N/2, (N+1)/2]:
20 return -1
21
22 seq1, seq2 = count
23 if any(x == y for x, y in itertools.izip(seq1, seq2)):
24 return -1
25 begins = [int(seq1.count(1) * 2 > N)] if N%2 else [0, 1]
26 result += min(sum(int(i%2 != v) for i, v in enumerate(seq1, begin)) \
27 for begin in begins) / 2
28 return result
29
****************************

151. K-th Smallest Prime Fraction


****************************

You are given a sorted integer arrayarr containing 1 and prime numbers, where all the integers of arr are unique. You are
also given an integer k .

For every i and j where 0 <= i < j < arr.length , we consider the fractionarr[i] / arr[j] .

Return the k th smallest fraction considered. Return your answer as an array of integers of size2, where answer[0] == arr[i] and
answer[1] == arr[j].

Example 1:

Input: arr = [1,2,3,5], k = 3


Output: [2,5]
Explanation: The fractions to be considered in sorted order are:
1/5, 1/3, 2/5, 1/2, 3/5, and 2/3.
The third fraction is 2/5.

Example 2:

Input: arr = [1,7], k = 1


Output: [1,7]

Constraints:

2 <= arr.length <= 1000


1 <= arr[i] <= 3 * 10 4
arr[0] == 1
arr[i] is a prime number for i > 0 .
All the numbers of arr are unique and sorted in strictly increasing order.
1 <= k <= arr.length * (arr.length - 1) / 2
****************************

151. K-th Smallest Prime Fraction(C++)


****************************

1 // Time: O(nlogr)
2 // Space: O(1)
3
4 // Another cool O(n) solution by using quick select with median of median could be found here:
5 // https://leetcode.com/problems/k-th-smallest-prime-fraction/discuss/115545/O(n)
6
7 class Solution {
8 public:
9 vector kthSmallestPrimeFraction(vector& A, int K) {
10 vector result;
11 double left = 0.0, right = 1.0;
12 while (right - left > 1e-8) {
13 double mid = left + (right - left) / 2.0;
14 if (check(mid, A, K, &result)) {
15 right = mid;
16 } else {
17 left = mid;
18 }
19 if (!result.empty()) {
20 break;
21 }
22 }
23 return result;
24 }
25
26 private:
27 bool check(double mid, const vector& A, int K, vector *result) {
28 vector tmp(2);
29 int count = 0;
30 for (int i = 0, j = 0; i < A.size(); ++i) {
31 for (; j < A.size(); ++j) {
32 if (i < j && A[i] < A[j] * mid) {
33 if (tmp[0] == 0 || tmp[0] * A[j] < tmp[1] * A[i]) {
34 tmp[0] = A[i];
35 tmp[1] = A[j];
36 }
37 break;
38 }
39 }
40 count += A.size() - j;
41 }
42 if (count == K) {
43 *result = move(tmp);
44 }
45 return count >= K;
46 }
47 };
****************************

151. K-th Smallest Prime Fraction(Python)


****************************

1 # Time: O(nlogr)
2 # Space: O(1)
3
4 class Solution(object):
5 def kthSmallestPrimeFraction(self, A, K):
6 """
7 :type A: List[int]
8 :type K: int
9 :rtype: List[int]
10 """
11 def check(mid, A, K, result):
12 tmp = [0]*2
13 count = 0
14 j = 0
15 for i in xrange(len(A)):
16 while j < len(A):
17 if i < j and A[i] < A[j]*mid:
18 if tmp[0] == 0 or \
19 tmp[0]*A[j] < tmp[1]*A[i]:
20 tmp[0] = A[i]
21 tmp[1] = A[j]
22 break
23 j += 1
24 count += len(A)-j
25 if count == K:
26 result[:] = tmp
27 return count >= K
28
29 result = []
30 left, right = 0.0, 1.0
31 while right-left > 1e-8:
32 mid = left + (right-left) / 2.0
33 if check(mid, A, K, result):
34 right = mid
35 else:
36 left = mid
37 if result:
38 break
39 return result
40
******************************************

152. Preimage Size of Factorial Zeroes Function


******************************************

Let f(x) be the number of zeroes at the end ofx!. Recall that x! = 1 * 2 * 3 * ... * x and by convention, 0! = 1 .

For example, f(3) = 0 because 3! = 6 has no zeroes at the end, whilef(11) = 2 because 11! = 39916800 has two zeroes at the
end.

Given an integer k , return the number of non-negative integersx have the property that f(x) = k .

Example 1:

Input: k = 0
Output: 5
Explanation: 0!, 1!, 2!, 3!, and 4! end with k = 0 zeroes.

Example 2:

Input: k = 5
Output: 0
Explanation: There is no x such that x! ends in k = 5 zeroes.

Example 3:

Input: k = 3
Output: 5

Constraints:

0 <= k <= 10 9
******************************************

152. Preimage Size of Factorial Zeroes Function(C++)


******************************************

1 // Time: O((logn)^2)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int preimageSizeFZF(int K) {
7 const int p = 5;
8 int left = 0, right = p * K;
9 while (left <= right) {
10 const int mid = left + (right - left) / 2;
11 if (countOfFactorialPrimes(mid, p) >= K) {
12 right = mid - 1;
13 } else {
14 left = mid + 1;
15 }
16 }
17 return countOfFactorialPrimes(left, p) == K ? p : 0;
18 }
19
20 private:
21 int countOfFactorialPrimes(int n, int p) {
22 int cnt = 0;
23 for (; n > 0; n /= p) {
24 cnt += n / p;
25 }
26 return cnt;
27 }
28 };
******************************************

152. Preimage Size of Factorial Zeroes Function(Python)


******************************************

1 # Time: O((logn)^2)
2 # Space: O(1)
3
4 class Solution(object):
5 def preimageSizeFZF(self, K):
6 """
7 :type K: int
8 :rtype: int
9 """
10 def count_of_factorial_primes(n, p):
11 cnt = 0
12 while n > 0:
13 cnt += n//p
14 n //= p
15 return cnt
16
17 p = 5
18 left, right = 0, p*K
19 while left <= right:
20 mid = left + (right-left)//2
21 if count_of_factorial_primes(mid, p) >= K:
22 right = mid-1
23 else:
24 left = mid+1
25 return p if count_of_factorial_primes(left, p) == K else 0
26
************************************

153. Smallest Rotation with Highest Score


************************************

You are given an array nums. You can rotate it by a non-negative integerk so that the array becomes [nums[k], nums[k + 1], ...
nums[nums.length - 1], nums[0], nums[1], ..., nums[k-1]]. Afterward, any entries that are less than or equal to their index are worth one
point.

For example, if we have nums = [2,4,1,3,0] , and we rotate by k = 2 , it becomes [1,3,0,2,4]. This is worth 3 points because 1 > 0
[no points], 3 > 1 [no points], 0 <= 2 [one point], 2 <= 3 [one point], 4 <= 4 [one point].

Return the rotation index k that corresponds to the highest score we can achieve if we rotatednums by it. If there are multiple
answers, return the smallest such index k .

Example 1:

Input: nums = [2,3,1,4,0]


Output: 3
Explanation: Scores for each k are listed below:
k = 0, nums = [2,3,1,4,0], score 2
k = 1, nums = [3,1,4,0,2], score 3
k = 2, nums = [1,4,0,2,3], score 3
k = 3, nums = [4,0,2,3,1], score 4
k = 4, nums = [0,2,3,1,4], score 3
So we should choose k = 3, which has the highest score.

Example 2:

Input: nums = [1,3,0,2,4]


Output: 0
Explanation: nums will always have 3 points no matter how it shifts.
So we will choose the smallest k, which is 0.

Constraints:

1 <= nums.length <= 10 5


0 <= nums[i] < nums.length
************************************

153. Smallest Rotation with Highest Score(C++)


************************************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int bestRotation(vector& A) {
7 const int N = A.size();
8 vector change(N);
9 for (int i = 0; i < N; ++i) {
10 --change[(i - A[i] + 1 + N) % N];
11 }
12 for (int i = 1; i < N; ++i) {
13 change[i] += change[i - 1] + 1;
14 }
15 return distance(change.begin(), max_element(change.begin(), change.begin() + N));
16 }
17 };
************************************

153. Smallest Rotation with Highest Score(Python)


************************************

1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 def bestRotation(self, A):
6 """
7 :type A: List[int]
8 :rtype: int
9 """
10 N = len(A)
11 change = [1] * N
12 for i in xrange(N):
13 change[(i-A[i]+1)%N] -= 1
14 for i in xrange(1, N):
15 change[i] += change[i-1]
16 return change.index(max(change))
17
18
***********************

154. Bricks Falling When Hit


***********************

You are given an m x n binary grid, where each 1 represents a brick and 0 represents an empty space. A brick is stable if:

It is directly connected to the top of the grid, or


At least one other brick in its four adjacent cells isstable.

You are also given an array hits, which is a sequence of erasures we want to apply. Each time we want to erase the brick at
the location hits[i] = (row i, col i). The brick on that location (if it exists) will disappear. Some other bricks may no longer be stable
because of that erasure and will fall. Once a brick falls, it is immediately erased from the grid (i.e., it does not land on other
stable bricks).

Return an array result, where each result[i] is the number of bricks that will fall after the ith erasure is applied.

Note that an erasure may refer to a location with no brick, and if it does, no bricks drop.

Example 1:

Input: grid = [[1,0,0,0],[1,1,1,0]], hits = [[1,0]]


Output: [2]
Explanation: Starting with the grid:
[[1,0,0,0],
[1,1,1,0]]
We erase the underlined brick at (1,0), resulting in the grid:
[[1,0,0,0],
[0,1,1,0]]
The two underlined bricks are no longer stable as they are no longer connected to the top nor adjacent to another stable brick, so they will
[[1,0,0,0],
[0,0,0,0]]
Hence the result is [2].

Example 2:

Input: grid = [[1,0,0,0],[1,1,0,0]], hits = [[1,1],[1,0]]


Output: [0,0]
Explanation: Starting with the grid:
[[1,0,0,0],
[1,1,0,0]]
We erase the underlined brick at (1,1), resulting in the grid:
[[1,0,0,0],
[1,0,0,0]]
All remaining bricks are still stable, so no bricks fall. The grid remains the same:
[[1,0,0,0],
[1,0,0,0]]
Next, we erase the underlined brick at (1,0), resulting in the grid:
[[1,0,0,0],
[0,0,0,0]]
Once again, all remaining bricks are still stable, so no bricks fall.
Hence the result is [0,0].

Constraints:

m == grid.length
n == grid[i].length
1 <= m, n <= 200
grid[i][j] is 0 or 1.
1 <= hits.length <= 4 * 10 4
hits[i].length == 2
0 <= x i <= m - 1
0 <= yi <= n - 1
All (xi, y i) are unique.
***********************

154. Bricks Falling When Hit(C++)


***********************

1 // Time: O(r * c)
2 // Space: O(r * c)
3
4 class Solution {
5 public:
6 vector hitBricks(vector>& grid, vector>& hits) {
7 static const vector> directions{{-1, 0}, { 1, 0},
8 { 0, 1}, { 0, -1}};
9 const int R = grid.size();
10 const int C = grid[0].size();
11 const auto index = [&C](int r, int c) { return r * C + c; };
12
13 vector> hit_grid(grid);
14 for (const auto& hit : hits) {
15 hit_grid[hit[0]][hit[1]] = 0;
16 }
17
18 UnionFind union_find(R * C);
19 for (int r = 0; r < hit_grid.size(); ++r) {
20 for (int c = 0; c < hit_grid[r].size(); ++c) {
21 if (!hit_grid[r][c]) {
22 continue;
23 }
24 if (r == 0) {
25 union_find.union_set(index(r, c), R * C);
26 }
27 if (r && hit_grid[r - 1][c]) {
28 union_find.union_set(index(r, c), index(r - 1, c));
29 }
30 if (c && hit_grid[r][c - 1]) {
31 union_find.union_set(index(r, c), index(r, c - 1));
32 }
33 }
34 }
35
36 vector result;
37 for (int i = hits.size() - 1; i >= 0; --i) {
38 const auto r = hits[i][0], c = hits[i][1];
39 const auto prev_roof = union_find.top();
40 if (grid[r][c] == 0) {
41 result.emplace_back(0);
42 continue;
43 }
44 for (const auto& d : directions) {
45 const auto nr = r + d.first, nc = c + d.second;
46 if (0 <= nr && nr < R &&
47 0 <= nc && nc < C &&
48 hit_grid[nr][nc]) {
49 union_find.union_set(index(r, c), index(nr, nc));
50 }
51 }
52 if (r == 0) {
53 union_find.union_set(index(r, c), R * C);
54 }
55 hit_grid[r][c] = 1;
56 result.emplace_back(max(0, union_find.top() - prev_roof - 1));
57 }
58 reverse(result.begin(), result.end());
59 return result;
60 }
61
62 private:
63 class UnionFind {
64 public:
65 UnionFind(const int n) : set_(n + 1), size_(n + 1, 1) {
66 iota(set_.begin(), set_.end(), 0);
67 size_.back() = 0;
68 }
69
70 int find_set(const int x) {
71 if (set_[x] != x) {
72 set_[x] = find_set(set_[x]); // Path compression.
73 }
74 return set_[x];
75 }
76
77 bool union_set(const int x, const int y) {
78 int x_root = find_set(x), y_root = find_set(y);
79 if (x_root == y_root) {
80 return false;
81 }
82 set_[min(x_root, y_root)] = max(x_root, y_root);
83 size_[max(x_root, y_root)] += size_[min(x_root, y_root)];
84 return true;
85 }
86
87 int top() {
88 return size_[find_set(size_.size() - 1)];
89 }
90
91 private:
92 vector set_;
93 vector size_;
94 };
95 };
***********************

154. Bricks Falling When Hit(Python)


***********************
1 # Time: O(r * c)
2 # Space: O(r * c)
3
4 class UnionFind(object):
5 def __init__(self, n):
6 self.set = range(n+1)
7 self.size = [1]*(n+1)
8 self.size[-1] = 0
9
10 def find_set(self, x):
11 if self.set[x] != x:
12 self.set[x] = self.find_set(self.set[x]) # path compression.
13 return self.set[x]
14
15 def union_set(self, x, y):
16 x_root, y_root = map(self.find_set, (x, y))
17 if x_root == y_root:
18 return False
19 self.set[min(x_root, y_root)] = max(x_root, y_root)
20 self.size[max(x_root, y_root)] += self.size[min(x_root, y_root)]
21 return True
22
23 def top(self):
24 return self.size[self.find_set(len(self.size)-1)]
25
26
27 class Solution(object):
28 def hitBricks(self, grid, hits):
29 """
30 :type grid: List[List[int]]
31 :type hits: List[List[int]]
32 :rtype: List[int]
33 """
34 def index(C, r, c):
35 return r*C+c
36
37 directions = [(0, -1), (0, 1), (-1, 0), (1, 0)]
38 R, C = len(grid), len(grid[0])
39
40 hit_grid = [row[:] for row in grid]
41 for i, j in hits:
42 hit_grid[i][j] = 0
43
44 union_find = UnionFind(R*C)
45 for r, row in enumerate(hit_grid):
46 for c, val in enumerate(row):
47 if not val:
48 continue
49 if r == 0:
50 union_find.union_set(index(C, r, c), R*C)
51 if r and hit_grid[r-1][c]:
52 union_find.union_set(index(C, r, c), index(C, r-1, c))
53 if c and hit_grid[r][c-1]:
54 union_find.union_set(index(C, r, c), index(C, r, c-1))
55
56 result = []
57 for r, c in reversed(hits):
58 prev_roof = union_find.top()
59 if grid[r][c] == 0:
60 result.append(0)
61 continue
62 for d in directions:
63 nr, nc = (r+d[0], c+d[1])
64 if 0 <= nr < R and 0 <= nc < C and hit_grid[nr][nc]:
65 union_find.union_set(index(C, r, c), index(C, nr, nc))
66 if r == 0:
67 union_find.union_set(index(C, r, c), R*C)
68 hit_grid[r][c] = 1
69 result.append(max(0, union_find.top()-prev_roof-1))
70 return result[::-1]
71
*****************************

155. Split Array With Same Average


*****************************

You are given an integer array nums.

You should move each element of nums into one of the two arrays A and B such that A and B are non-empty, and average(A) ==
average(B).

Return true if it is possible to achieve that and false otherwise.

Note that for an array arr, average(arr) is the sum of all the elements ofarr over the length of arr.

Example 1:

Input: nums = [1,2,3,4,5,6,7,8]


Output: true
Explanation: We can split the array into [1,4,5,8] and [2,3,6,7], and both of them have an average of 4.5.

Example 2:

Input: nums = [3,1]


Output: false

Constraints:

1 <= nums.length <= 30


0 <= nums[i] <= 10 4
*****************************

155. Split Array With Same Average(C++)


*****************************

1 // Time: O(n^4)
2 // Space: O(n^3)
3
4 class Solution {
5 public:
6 bool splitArraySameAverage(vector& A) {
7 const int n = A.size();
8 const int sum = accumulate(A.cbegin(), A.cend(), 0);
9 if (!possible(n, sum)) {
10 return false;
11 }
12
13 vector> sums(n / 2 + 1);
14 sums[0].emplace(0);
15 for (const auto& num: A) { // O(n) times
16 for (int i = n / 2; i >= 1; --i) { // O(n) times
17 for (const auto& prev : sums[i - 1]) { // O(1) + O(2) + ... O(n/2) = O(n^2) times
18 sums[i].emplace(prev + num);
19 }
20 }
21 }
22 for (int i = 1; i <= n / 2; ++i) {
23 if (sum * i % n == 0 &&
24 sums[i].count(sum * i / n)) {
25 return true;
26 }
27 }
28 return false;
29 }
30
31 private:
32 bool possible(int n, int sum) {
33 for (int i = 1; i <= n / 2; ++i) {
34 if (sum * i % n == 0) {
35 return true;
36 }
37 }
38 return false;
39 }
40 };
*****************************

155. Split Array With Same Average(Python)


*****************************

1 # Time: O(n^4)
2 # Space: O(n^3)
3
4 class Solution(object):
5 def splitArraySameAverage(self, A):
6 """
7 :type A: List[int]
8 :rtype: bool
9 """
10 def possible(total, n):
11 for i in xrange(1, n//2+1):
12 if total*i%n == 0:
13 return True
14 return False
15 n, s = len(A), sum(A)
16 if not possible(n, s):
17 return False
18
19 sums = [set() for _ in xrange(n//2+1)]
20 sums[0].add(0)
21 for num in A: # O(n) times
22 for i in reversed(xrange(1, n//2+1)): # O(n) times
23 for prev in sums[i-1]: # O(1) + O(2) + ... O(n/2) = O(n^2) times
24 sums[i].add(prev+num)
25 for i in xrange(1, n//2+1):
26 if s*i%n == 0 and s*i//n in sums[i]:
27 return True
28 return False
29
*******************

156. Chalkboard XOR Game


*******************

You are given an array of integersnums represents the numbers written on a chalkboard.

Alice and Bob take turns erasing exactly one number from the chalkboard, with Alice starting first. If erasing a number
causes the bitwise XOR of all the elements of the chalkboard to become 0, then that player loses. The bitwise XOR of one
element is that element itself, and the bitwise XOR of no elements is 0.

Also, if any player starts their turn with the bitwise XOR of all the elements of the chalkboard equal to0, then that player
wins.

Return true if and only if Alice wins the game, assuming both players play optimally.

Example 1:

Input: nums = [1,1,2]


Output: false
Explanation:
Alice has two choices: erase 1 or erase 2.
If she erases 1, the nums array becomes [1, 2]. The bitwise XOR of all the elements of the chalkboard is 1 XOR 2 = 3. Now Bob can remove any
If Alice erases 2 first, now nums become [1, 1]. The bitwise XOR of all the elements of the chalkboard is 1 XOR 1 = 0. Alice will lose.

Example 2:

Input: nums = [0,1]


Output: true

Example 3:

Input: nums = [1,2,3]


Output: true

Constraints:

1 <= nums.length <= 1000


0 <= nums[i] < 2 16
*******************

156. Chalkboard XOR Game(Python)


*******************

1 # Time: O(n)
2 # Space: O(1)
3
4 from operator import xor
5 from functools import reduce
6
7
8 class Solution(object):
9 def xorGame(self, nums):
10 """
11 :type nums: List[int]
12 :rtype: bool
13 """
14 return reduce(xor, nums) == 0 or \
15 len(nums) % 2 == 0
16
**********

157. Bus Routes


**********

You are given an array routes representing bus routes where routes[i] is a bus route that the ith bus repeats forever.

For example, if routes[0] = [1, 5, 7] , this means that the 0th bus travels in the sequence 1 -> 5 -> 7 -> 1 -> 5 -> 7 -> 1 -> ...
forever.

You will start at the bus stopsource (You are not on any bus initially), and you want to go to the bus stoptarget. You can travel
between bus stops by buses only.

Return the least number of buses you must take to travel fromsource to target. Return -1 if it is not possible.

Example 1:

Input: routes = [[1,2,7],[3,6,7]], source = 1, target = 6


Output: 2
Explanation: The best strategy is take the first bus to the bus stop 7, then take the second bus to the bus stop 6.

Example 2:

Input: routes = [[7,12],[4,5,15],[6],[15,19],[9,12,13]], source = 15, target = 12


Output: -1

Constraints:

1 <= routes.length <= 500 .


1 <= routes[i].length <= 10 5
All the values of routes[i] are unique.
sum(routes[i].length) <= 105
0 <= routes[i][j] < 10 6
0 <= source, target < 10 6
**********

157. Bus Routes(C++)


**********

1 // Time: O(|V| + |E|)


2 // Space: O(|V| + |E|)
3
4 class Solution {
5 public:
6 int numBusesToDestination(vector>& routes, int S, int T) {
7 if (S == T) {
8 return 0;
9 }
10 unordered_map> to_route;
11 for (int i = 0; i < routes.size(); ++i) {
12 for (const auto& stop : routes[i]) {
13 to_route[stop].emplace(i);
14 }
15 }
16
17 int result = 1;
18 vector q{S};
19 unordered_set lookup{S};
20 while (!q.empty()) {
21 vector next_q;
22 for (const auto& stop : q) {
23 for (const auto& i : to_route[stop]) {
24 for (const auto& next_stop : routes[i]) {
25 if (lookup.count(next_stop)) {
26 continue;
27 }
28 if (next_stop == T) {
29 return result;
30 }
31 next_q.emplace_back(next_stop);
32 to_route[next_stop].erase(i);
33 lookup.emplace(next_stop);
34 }
35 }
36 }
37 swap(q, next_q);
38 ++result;
39 }
40 return -1;
41 }
42 };
**********

157. Bus Routes(Python)


**********

1 # Time: O(|V| + |E|)


2 # Space: O(|V| + |E|)
3
4 import collections
5
6
7 class Solution(object):
8 def numBusesToDestination(self, routes, S, T):
9 """
10 :type routes: List[List[int]]
11 :type S: int
12 :type T: int
13 :rtype: int
14 """
15 if S == T:
16 return 0
17
18 to_route = collections.defaultdict(set)
19 for i, route in enumerate(routes):
20 for stop in route:
21 to_route[stop].add(i)
22
23 result = 1
24 q = [S]
25 lookup = set([S])
26 while q:
27 next_q = []
28 for stop in q:
29 for i in to_route[stop]:
30 for next_stop in routes[i]:
31 if next_stop in lookup:
32 continue
33 if next_stop == T:
34 return result
35 next_q.append(next_stop)
36 to_route[next_stop].remove(i)
37 lookup.add(next_stop)
38 q = next_q
39 result += 1
40
41 return -1
42
********

158. Race Car


********

Your car starts at position 0 and speed +1 on an infinite number line. Your car can go into negative positions. Your car drives
automatically according to a sequence of instructions 'A' (accelerate) and 'R' (reverse):

When you get an instruction 'A', your car does the following:
position += speed
speed *= 2
When you get an instruction 'R', your car does the following:
If your speed is positive then speed = -1
otherwise speed = 1
Your position stays the same.

For example, after commands "AAR", your car goes to positions 0 --> 1 --> 3 --> 3 , and your speed goes to 1 --> 2 --> 4 --> -1 .

Given a target position target, return the length of the shortest sequence of instructions to get there.

Example 1:

Input: target = 3
Output: 2
Explanation:
The shortest instruction sequence is "AA".
Your position goes from 0 --> 1 --> 3.

Example 2:

Input: target = 6
Output: 5
Explanation:
The shortest instruction sequence is "AAARA".
Your position goes from 0 --> 1 --> 3 --> 7 --> 7 --> 6.

Constraints:

1 <= target <= 10 4


********

158. Race Car(C++)


********

1 // Time : O(nlogn), n is the value of the target


2 // Space: O(n)
3
4 class Solution {
5 public:
6 int racecar(int target) {
7 vector dp(target + 1);
8 for (int i = 1; i <= target; ++i) {
9 int k = bitLength(i);
10 if (i == (1 << k) - 1) {
11 dp[i] = k;
12 continue;
13 }
14 dp[i] = dp[(1 << k) - 1 - i] + k + 1;
15 for (int j = 0; j < k; ++j) {
16 dp[i] = min(dp[i], dp[i - (1 << (k - 1)) + (1 << j)] + k + j + 1);
17 }
18 }
19 return dp.back();
20 }
21
22 private:
23 uint32_t bitLength(uint32_t n) {
24 uint32_t left = 1, right = 32;
25 while (left <= right) {
26 auto mid = left + (right - left) / 2;
27 if ((1 << mid) > n) {
28 right = mid - 1;
29 } else {
30 left = mid + 1;
31 }
32 }
33 return left;
34 }
35 };
********

158. Race Car(Python)


********

1 # Time : O(nlogn), n is the value of the target


2 # Space: O(n)
3
4
5 class Solution(object):
6 def racecar(self, target):
7 dp = [0] * (target+1)
8 for i in xrange(1, target+1):
9 # 2^(k-1) <= i < 2^k
10 k = i.bit_length()
11
12 # case 1. drive exactly i at best
13 # seq(i) = A^k
14 if i == 2**k-1:
15 dp[i] = k
16 continue
17
18 # case 2. drive cross i at 2^k-1, and turn back to i
19 # seq(i) = A^k -> R -> seq(2^k-1 - i)
20 dp[i] = k+1 + dp[2**k-1 - i]
21
22 # case 3. drive less then 2^k-1, and turn back some distance,
23 # and turn back again to make the direction is the same
24 # seq(i) = shortest(seq(i), A^(k-1) -> R -> A^j -> R ->
25 # seq(i - (2^(k-1)-1) + (2^j-1)),
26 # where 0 <= j < k-1)
27 # => dp[i] = min(dp[i], (k-1) + 1 + j + 1 +
28 # dp[i - (2**(k-1)-1) + (2**j-1)])
29 for j in xrange(k-1):
30 dp[i] = min(dp[i], k+j+1 + dp[i - 2**(k-1) + 2**j])
31
32 return dp[-1]
33
*********************

159. Making A Large Island


*********************

You are given an n x n binary matrix grid. You are allowed to changeat most one 0 to be 1.

Return the size of the largest island in grid after applying this operation.

An island is a 4-directionally connected group of 1s.

Example 1:

Input: grid = [[1,0],[0,1]]


Output: 3
Explanation: Change one 0 to 1 and connect two 1s, then we get an island with area = 3.

Example 2:

Input: grid = [[1,1],[1,0]]


Output: 4
Explanation: Change the 0 to 1 and make the island bigger, only one island with area = 4.

Example 3:

Input: grid = [[1,1],[1,1]]


Output: 4
Explanation: Can't change any 0 to 1, only one island with area = 4.

Constraints:

n == grid.length
n == grid[i].length
1 <= n <= 500
grid[i][j] is either 0 or 1.
*********************

159. Making A Large Island(C++)


*********************

1 // Time: O(n^2)
2 // Space: O(n^2)
3
4 class Solution {
5 public:
6 int largestIsland(vector>& grid) {
7 int result = 0;
8 unordered_map area;
9 int index = 2;
10 for (int r = 0; r < grid.size(); ++r) {
11 for (int c = 0; c < grid[r].size(); ++c) {
12 if (grid[r][c] != 1) {
13 continue;
14 }
15 area[index] = dfs(r, c, index, &grid);
16 result = max(result, area[index++]);
17 }
18 }
19
20 for (int r = 0; r < grid.size(); ++r) {
21 for (int c = 0; c < grid[r].size(); ++c) {
22 if (grid[r][c] != 0) {
23 continue;
24 }
25 unordered_set seen;
26 for (const auto& d :directions) {
27 int nr = r + d.first, nc = c + d.second;
28 if (0 <= nr && nr < grid.size() &&
29 0 <= nc && nc < grid[0].size() &&
30 grid[nr][nc] > 1) {
31 seen.emplace(grid[nr][nc]);
32 }
33 }
34 int sum = 0;
35 for (const auto& i : seen) {
36 sum += area[i];
37 }
38 result = max(result, 1 + sum);
39 }
40 }
41 return result;
42 }
43
44 private:
45 const vector> directions{{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
46
47 int dfs(int r, int c, int index, vector> *grid) {
48 if (!(0 <= r && r < grid->size() &&
49 0 <= c && c < (*grid)[0].size() &&
50 (*grid)[r][c] == 1)) {
51 return 0;
52 }
53 int result = 1;
54 (*grid)[r][c] = index;
55 for (const auto& d :directions) {
56 result += dfs(r + d.first, c + d.second, index, grid);
57 }
58 return result;
59 }
60 };
*********************

159. Making A Large Island(Python)


*********************

1 # Time: O(n^2)
2 # Space: O(n^2)
3
4
5 class Solution(object):
6 def largestIsland(self, grid):
7 """
8 :type grid: List[List[int]]
9 :rtype: int
10 """
11 directions = [(0, -1), (0, 1), (-1, 0), (1, 0)]
12
13 def dfs(r, c, index, grid):
14 if not (0 <= r < len(grid) and
15 0 <= c < len(grid[0]) and
16 grid[r][c] == 1):
17 return 0
18 result = 1
19 grid[r][c] = index
20 for d in directions:
21 result += dfs(r+d[0], c+d[1], index, grid)
22 return result
23
24 area = {}
25 index = 2
26 for r in xrange(len(grid)):
27 for c in xrange(len(grid[r])):
28 if grid[r][c] == 1:
29 area[index] = dfs(r, c, index, grid)
30 index += 1
31
32 result = max(area.values() or [0])
33 for r in xrange(len(grid)):
34 for c in xrange(len(grid[r])):
35 if grid[r][c] == 0:
36 seen = set()
37 for d in directions:
38 nr, nc = r+d[0], c+d[1]
39 if not (0 <= nr < len(grid) and
40 0 <= nc < len(grid[0]) and
41 grid[nr][nc] > 1):
42 continue
43 seen.add(grid[nr][nc])
44 result = max(result, 1 + sum(area[i] for i in seen))
45 return result
46
***********************************************************

160. Count Unique Characters of All Substrings of a


Given String
***********************************************************

Let's define a function countUniqueChars(s) that returns the number of unique characters on s .

For example if s = "LEETCODE" then "L", "T", "C", "O", "D" are the unique characters since they appear only once ins ,
therefore countUniqueChars(s) = 5 .

Given a string s , return the sum of countUniqueChars(t) where t is a substring of s.

Notice that some substrings can be repeated so in this case you have to count the repeated ones too.

Example 1:

Input: s = "ABC"
Output: 10
Explanation: All possible substrings are: "A","B","C","AB","BC" and "ABC".
Evey substring is composed with only unique letters.
Sum of lengths of all substring is 1 + 1 + 1 + 2 + 2 + 3 = 10

Example 2:

Input: s = "ABA"
Output: 8
Explanation: The same as example 1, except countUniqueChars("ABA") = 1.

Example 3:

Input: s = "LEETCODE"
Output: 92

Constraints:

1 <= s.length <= 105


s consists of uppercase English letters only.
***********************************************************

160. Count Unique Characters of All Substrings of a


Given String(C++)
***********************************************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int uniqueLetterString(string S) {
7 static const int M = 1e9 + 7;
8 int result = 0;
9 vector> index(26, vector(2, -1));
10 for (int i = 0; i < S.length(); ++i) {
11 int c = S[i] - 'A';
12 result = (result + (i - index[c][1]) *
13 (index[c][1] - index[c][0])) % M;
14 index[c][0] = index[c][1];
15 index[c][1] = i;
16 }
17 for (int c = 0; c < 26; ++c) {
18 result = (result + (S.length() - index[c][1]) *
19 (index[c][1] - index[c][0])) % M;
20 }
21 return result;
22 }
23 };
***********************************************************

160. Count Unique Characters of All Substrings of a


Given String(Python)
***********************************************************

1 # Time: O(n)
2 # Space: O(1)
3
4 import string
5
6
7 class Solution(object):
8 def uniqueLetterString(self, S):
9 """
10 :type S: str
11 :rtype: int
12 """
13 M = 10**9 + 7
14 index = {c: [-1, -1] for c in string.ascii_uppercase}
15 result = 0
16 for i, c in enumerate(S):
17 k, j = index[c]
18 result += (i-j) * (j-k)
19 index[c] = [j, i]
20 for c in index:
21 k, j = index[c]
22 result += (len(S)-j) * (j-k)
23 return result % M
24
************************

161. Sum of Distances in Tree


************************

There is an undirected connected tree with n nodes labeled from 0 to n - 1 and n - 1 edges.

You are given the integer n and the array edges where edges[i] = [a i, b i] indicates that there is an edge between nodes ai and bi in
the tree.

Return an array answer of length n where answer[i] is the sum of the distances between theith node in the tree and all other
nodes.

Example 1:

Input: n = 6, edges = [[0,1],[0,2],[2,3],[2,4],[2,5]]


Output: [8,12,6,10,10,10]
Explanation: The tree is shown above.
We can see that dist(0,1) + dist(0,2) + dist(0,3) + dist(0,4) + dist(0,5)
equals 1 + 1 + 2 + 2 + 2 = 8.
Hence, answer[0] = 8, and so on.

Example 2:

Input: n = 1, edges = []
Output: [0]

Example 3:

Input: n = 2, edges = [[1,0]]


Output: [1,1]
Constraints:

1 <= n <= 3 * 10 4
edges.length == n - 1
edges[i].length == 2
0 <= ai, b i < n
ai != b i
The given input represents a valid tree.
************************

161. Sum of Distances in Tree(C++)


************************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 vector sumOfDistancesInTree(int N, vector>& edges) {
7 unordered_map> graph;
8 for (const auto& edge : edges) {
9 graph[edge[0]].emplace_back(edge[1]);
10 graph[edge[1]].emplace_back(edge[0]);
11 }
12
13 vector count(N, 1);
14 vector result(N, 0);
15
16 dfs(graph, 0, -1, &count, &result);
17 dfs2(graph, 0, -1, &count, &result);
18 return result;
19 }
20
21 private:
22 void dfs(const unordered_map>& graph,
23 int node, int parent,
24 vector *count, vector *result) {
25 if (!graph.count(node)) {
26 return;
27 }
28 for (const auto& nei : graph.at(node)) {
29 if (nei != parent) {
30 dfs(graph, nei, node, count, result);
31 (*count)[node] += (*count)[nei];
32 (*result)[node] += (*result)[nei] + (*count)[nei];
33 }
34 }
35 }
36
37 void dfs2(const unordered_map>& graph,
38 int node, int parent,
39 vector *count, vector *result) {
40 if (!graph.count(node)) {
41 return;
42 }
43 for (const auto& nei : graph.at(node)) {
44 if (nei != parent) {
45 (*result)[nei] = (*result)[node] - (*count)[nei] +
46 count->size() - (*count)[nei];
47 dfs2(graph, nei, node, count, result);
48 }
49 }
50 }
51 };
************************

161. Sum of Distances in Tree(Python)


************************

1 # Time: O(n)
2 # Space: O(n)
3
4 import collections
5
6
7 class Solution(object):
8 def sumOfDistancesInTree(self, N, edges):
9 """
10 :type N: int
11 :type edges: List[List[int]]
12 :rtype: List[int]
13 """
14 def dfs(graph, node, parent, count, result):
15 for nei in graph[node]:
16 if nei != parent:
17 dfs(graph, nei, node, count, result)
18 count[node] += count[nei]
19 result[node] += result[nei]+count[nei]
20
21 def dfs2(graph, node, parent, count, result):
22 for nei in graph[node]:
23 if nei != parent:
24 result[nei] = result[node]-count[nei] + \
25 len(count)-count[nei]
26 dfs2(graph, nei, node, count, result)
27
28 graph = collections.defaultdict(list)
29 for u, v in edges:
30 graph[u].append(v)
31 graph[v].append(u)
32
33 count = [1] * N
34 result = [0] * N
35
36 dfs(graph, 0, None, count, result)
37 dfs2(graph, 0, None, count, result)
38 return result
39
*********************

162. Similar String Groups


*********************

Two strings X and Y are similar if we can swap two letters (in different positions) ofX, so that it equals Y. Also two strings X
and Y are similar if they are equal.

For example, "tars" and "rats" are similar (swapping at positions 0 and 2), and "rats" and "arts" are similar, but "star" is not similar
to "tars", "rats", or "arts".

Together, these form two connected groups by similarity: {"tars", "rats", "arts"} and {"star"} . Notice that "tars" and "arts" are in the
same group even though they are not similar. Formally, each group is such that a word is in the group if and only if it is
similar to at least one other word in the group.

We are given a list strs of strings where every string in strs is an anagram of every other string instrs. How many groups are
there?

Example 1:

Input: strs = ["tars","rats","arts","star"]


Output: 2

Example 2:

Input: strs = ["omv","ovm"]


Output: 1

Constraints:

1 <= strs.length <= 300


1 <= strs[i].length <= 300
strs[i] consists of lowercase letters only.
All words in strs have the same length and are anagrams of each other.
*********************

162. Similar String Groups(C++)


*********************

1 // Time: O(n^2 * l), l is the average length of words


2 // Space: O(n)
3
4 class Solution {
5 public:
6 int numSimilarGroups(vector& A) {
7 UnionFind union_find(A.size());
8 for (int i = 0; i < A.size(); ++i) {
9 for (int j = 0; j < i; ++j) {
10 if (isSimilar(A[i], A[j])) {
11 union_find.union_set(i, j);
12 }
13 }
14 }
15 return union_find.size();
16 }
17
18 private:
19 bool isSimilar(const string& a, const string& b) {
20 int diff = 0;
21 for (int i = 0; i < a.length(); ++i) {
22 if (a[i] != b[i]) {
23 if (++diff > 2) {
24 return false;
25 }
26 }
27 }
28 return diff == 2;
29 }
30
31 class UnionFind {
32 public:
33 UnionFind(const int n) : set_(n), size_(n) {
34 iota(set_.begin(), set_.end(), 0);
35 }
36
37 int find_set(const int x) {
38 if (set_[x] != x) {
39 set_[x] = find_set(set_[x]); // Path compression.
40 }
41 return set_[x];
42 }
43
44 bool union_set(const int x, const int y) {
45 int x_root = find_set(x), y_root = find_set(y);
46 if (x_root == y_root) {
47 return false;
48 }
49 set_[min(x_root, y_root)] = max(x_root, y_root);
50 --size_;
51 return true;
52 }
53
54 int size() const {
55 return size_;
56 }
57
58 private:
59 vector set_;
60 int size_;
61 };
62 };
63
64 // Time: O(n^2 * l) ~ O(n * l^4)
65 // Space: O(n) ~ O(n * l^3)
66 class Solution_MLE {
67 public:
68 int numSimilarGroups(vector& A) {
69 const int N = A.size(), L = A[0].length();
70 UnionFind union_find(A.size());
71 if (N < L*L) {
72 for (int i = 0; i < N; ++i) {
73 for (int j = 0; j < i; ++j) {
74 if (isSimilar(A[i], A[j])) {
75 union_find.union_set(i, j);
76 }
77 }
78 }
79 } else {
80 unordered_map> buckets;
81 unordered_set lookup;
82 for (int i = 0; i < A.size(); ++i) {
83 auto word = A[i];
84 if (!lookup.count(word)) {
85 buckets[word].emplace_back(i);
86 lookup.emplace(word);
87 }
88 for (int j1 = 0; j1 < L; ++j1) {
89 for (int j2 = 0; j2 < j1; ++j2) {
90 swap(word[j1], word[j2]);
91 buckets[word].emplace_back(i);
92 swap(word[j1], word[j2]);
93 }
94 }
95 }
96 for (const auto& word : A) {
97 for (int i = 0; i < buckets[word].size(); ++i) {
98 for (int j = 0; j < i; ++j) {
99 union_find.union_set(buckets[word][i], buckets[word][j]);
100 }
101 }
102 }
103 }
104 return union_find.size();
105 }
106
107 private:
108 bool isSimilar(const string& a, const string& b) {
109 int diff = 0;
110 for (int i = 0; i < a.length(); ++i) {
111 if (a[i] != b[i]) {
112 if (++diff > 2) {
113 return false;
114 }
115 }
116 }
117 return diff == 2;
118 }
119
120 class UnionFind {
121 public:
122 UnionFind(const int n) : set_(n), size_(n) {
123 iota(set_.begin(), set_.end(), 0);
124 }
125
126 int find_set(const int x) {
127 if (set_[x] != x) {
128 set_[x] = find_set(set_[x]); // Path compression.
129 }
130 return set_[x];
131 }
132
133 bool union_set(const int x, const int y) {
134 int x_root = find_set(x), y_root = find_set(y);
135 if (x_root == y_root) {
135 if (x_root == y_root) {
136 return false;
137 }
138 set_[min(x_root, y_root)] = max(x_root, y_root);
139 --size_;
140 return true;
141 }
142
143 int size() const {
144 return size_;
145 }
146
147 private:
148 vector set_;
149 int size_;
150 };
151 };
*********************

162. Similar String Groups(Python)


*********************
1 # Time: O(n^2 * l) ~ O(n * l^4)
2 # Space: O(n) ~ O(n * l^3)
3
4 import collections
5 import itertools
6
7
8 class UnionFind(object):
9 def __init__(self, n):
10 self.set = range(n)
11 self.__size = n
12
13 def find_set(self, x):
14 if self.set[x] != x:
15 self.set[x] = self.find_set(self.set[x]) # path compression.
16 return self.set[x]
17
18 def union_set(self, x, y):
19 x_root, y_root = map(self.find_set, (x, y))
20 if x_root == y_root:
21 return False
22 self.set[min(x_root, y_root)] = max(x_root, y_root)
23 self.__size -= 1
24 return True
25
26 def size(self):
27 return self.__size
28
29
30 class Solution(object):
31 def numSimilarGroups(self, A):
32 def isSimilar(a, b):
33 diff = 0
34 for x, y in itertools.izip(a, b):
35 if x != y:
36 diff += 1
37 if diff > 2:
38 return False
39 return diff == 2
40
41 N, L = len(A), len(A[0])
42 union_find = UnionFind(N)
43 if N < L*L:
44 for (i1, word1), (i2, word2) in \
45 itertools.combinations(enumerate(A), 2):
46 if isSimilar(word1, word2):
47 union_find.union_set(i1, i2)
48 else:
49 buckets = collections.defaultdict(list)
50 lookup = set()
51 for i in xrange(len(A)):
52 word = list(A[i])
53 if A[i] not in lookup:
54 buckets[A[i]].append(i)
55 lookup.add(A[i])
56 for j1, j2 in itertools.combinations(xrange(L), 2):
57 word[j1], word[j2] = word[j2], word[j1]
58 buckets["".join(word)].append(i)
59 word[j1], word[j2] = word[j2], word[j1]
60 for word in A: # Time: O(n * l^4)
61 for i1, i2 in itertools.combinations(buckets[word], 2):
62 union_find.union_set(i1, i2)
63 return union_find.size()
64
**************

163. Guess the Word


**************

This is an interactive problem.

You are given an array of unique strings wordlist where wordlist[i] is 6 letters long, and one word in this list is chosen as secret.

You may call Master.guess(word) to guess a word. The guessed word should have typestring and must be from the original list
with 6 lowercase letters.

This function returns an integer type, representing the number of exact matches (value and position) of your guess to the
secret word. Also, if your guess is not in the given wordlist, it will return-1 instead.

For each test case, you have exactly 10 guesses to guess the word. At the end of any number of calls, if you have made10
or fewer calls to Master.guess and at least one of these guesses was secret, then you pass the test case.

Example 1:

Input: secret = "acckzz", wordlist = ["acckzz","ccbazz","eiowzz","abcczz"], numguesses = 10


Output: You guessed the secret word correctly.
Explanation:
master.guess("aaaaaa") returns -1, because "aaaaaa" is not in wordlist.
master.guess("acckzz") returns 6, because "acckzz" is secret and has all 6 matches.
master.guess("ccbazz") returns 3, because "ccbazz" has 3 matches.
master.guess("eiowzz") returns 2, because "eiowzz" has 2 matches.
master.guess("abcczz") returns 4, because "abcczz" has 4 matches.
We made 5 calls to master.guess and one of them was the secret, so we pass the test case.

Example 2:

Input: secret = "hamada", wordlist = ["hamada","khaled"], numguesses = 10


Output: You guessed the secret word correctly.

Constraints:

1 <= wordlist.length <= 100


wordlist[i].length == 6
wordlist[i] consist of lowercase English letters.
All the strings of wordlist are unique.
secret exists in wordlist.
numguesses == 10
**************

163. Guess the Word(C++)


**************

1 // Time: O(n)
2 // Space: O(n)
3
4 /**
5 * // This is the Master's API interface.
6 * // You should not implement it, or speculate about its implementation
7 * class Master {
8 * public:
9 * int guess(string word);
10 * };
11 */
12 class Solution {
13 public:
14 void findSecretWord(vector& wordlist, Master& master) {
15 vector possible(size(wordlist));
16 iota(begin(possible), end(possible), 0);
17 int n = 0;
18 while (n < 6) {
19 auto guess = find_guess_with_most_frequent_chars(wordlist, possible);
20 n = master.guess(wordlist[guess]);
21 vector new_possible;
22 for (const auto& j : possible) {
23 if (match(wordlist[guess], wordlist[j]) == n) {
24 new_possible.emplace_back(j);
25 }
26 }
27 possible = move(new_possible);
28 }
29 }
30
31 private:
32 int find_guess_with_most_frequent_chars(
33 const vector& wordlist,
34 const vector& possible) {
35 vector> count(6, vector(26));
36 for (int i = 0; i < 6; ++i) {
37 for (const auto& p : possible) {
38 ++count[i][wordlist[p][i] - 'a'];
39 }
40 }
41 int guess = 0, max_score = 0;
42 for (const auto& p : possible) {
43 int score = 0;
44 for (int i = 0; i < 6; ++i) {
45 score += count[i][wordlist[p][i] - 'a'];
46 }
47 if (score > max_score) {
48 max_score = score;
49 guess = p;
50 }
51 }
52 return guess;
53 }
54
55 int match(const string& a, const string& b) {
56 int matches = 0;
57 for (int i = 0; i < size(a); ++i) {
58 if (a[i] == b[i]) {
59 ++matches;
60 }
61 }
62 return matches;
63 }
64 };
65
66 // Time: O(n^2)
67 // Space: O(n)
68 class Solution2 {
69 public:
70 void findSecretWord(vector& wordlist, Master& master) {
71 vector> H(size(wordlist), vector(size(wordlist)));
72 for (int i = 0; i < size(wordlist); ++i) {
73 for (int j = 0; j < size(wordlist); ++j) {
74 H[i][j] = match(wordlist[i], wordlist[j]);
75 }
76 }
77
78 vector possible(size(wordlist));
79 iota(begin(possible), end(possible), 0);
80 int n = 0;
81 while (n < 6) {
82 auto guess = solve(H, possible);
83 n = master.guess(wordlist[guess]);
84 vector new_possible;
85 for (const auto& j : possible) {
86 if (H[guess][j] == n) {
87 new_possible.emplace_back(j);
88 }
89 }
90 possible = move(new_possible);
91 }
92 }
93
94 private:
95 int solve(const vector>& H,
96 const vector& possible) {
97
98 int min_max_size = size(possible);
99 int best_guess = -1;
100 for (const auto& guess : possible) {
101 vector> groups(7);
102 for (const auto& j : possible) {
103 if (j != guess) {
104 groups[H[guess][j]].emplace_back(j);
105 }
106 }
107 int max_group_i = 0;
108 for (int i = 0; i < size(groups); ++i) {
109 if (size(groups[i]) > size(groups[max_group_i])) {
110 max_group_i = i;
111 }
112 }
113 if (size(groups[max_group_i]) < min_max_size) {
114 min_max_size = size(groups[max_group_i]);
115 best_guess = guess;
116 }
117 }
118 return best_guess;
119 }
120
121 int match(const string& a, const string& b) {
122 int matches = 0;
123 for (int i = 0; i < size(a); ++i) {
124 if (a[i] == b[i]) {
125 ++matches;
126 }
127 }
128 return matches;
129 }
130 };
131
132 // Time: O(n^2)
133 // Space: O(n)
134 class Solution3 {
135 public:
135 public:
136 void findSecretWord(vector& wordlist, Master& master) {
137 vector> H(size(wordlist), vector(size(wordlist)));
138 for (int i = 0; i < size(wordlist); ++i) {
139 for (int j = 0; j < size(wordlist); ++j) {
140 H[i][j] = match(wordlist[i], wordlist[j]);
141 }
142 }
143
144 vector possible(size(wordlist));
145 iota(begin(possible), end(possible), 0);
146 int n = 0;
147 while (n < 6) {
148 auto guess = solve(H, possible);
149 n = master.guess(wordlist[guess]);
150 vector new_possible;
151 for (const auto& j : possible) {
152 if (H[guess][j] == n) {
153 new_possible.emplace_back(j);
154 }
155 }
156 possible = move(new_possible);
157 }
158 }
159
160 private:
161 int solve(const vector>& H,
162 const vector& possible) {
163
164 int min_max_size = size(possible);
165 int best_guess = -1;
166 for (const auto& guess : possible) {
167 vector> groups(7);
168 for (const auto& j : possible) {
169 if (j != guess) {
170 groups[H[guess][j]].emplace_back(j);
171 }
172 }
173 int max_group_i = 0; // assumed the size of the other groups equals to the size of 0-group
174 if (size(groups[max_group_i]) < min_max_size) {
175 min_max_size = size(groups[max_group_i]);
176 best_guess = guess;
177 }
178 }
179 return best_guess;
180 }
181
182 int match(const string& a, const string& b) {
183 int matches = 0;
184 for (int i = 0; i < size(a); ++i) {
185 if (a[i] == b[i]) {
186 ++matches;
187 }
188 }
189 return matches;
190 }
191 };
**************

163. Guess the Word(Python)


**************

1 # Time: O(n)
2 # Space: O(n)
3
4 import collections
5 import itertools
6
7
8 class Solution(object):
9 def findSecretWord(self, wordlist, master):
10 """
11 :type wordlist: List[Str]
12 :type master: Master
13 :rtype: None
14 """
15 possible = range(len(wordlist))
16 n = 0
17 while n < 6:
18 count = [collections.Counter(w[i] for w in wordlist) for i in xrange(6)]
19 guess = max(possible, key=lambda x: sum(count[i][c] for i, c in enumerate(wordlist[x])))
20 n = master.guess(wordlist[guess])
21 possible = [j for j in possible if sum(a == b for a, b in itertools.izip(wordlist[guess], wordlist[j])) == n]
22
23
24 # Time: O(n^2)
25 # Space: O(n)
26 class Solution2(object):
27 def findSecretWord(self, wordlist, master):
28 """
29 :type wordlist: List[Str]
30 :type master: Master
31 :rtype: None
32 """
33 def solve(H, possible):
34 min_max_group, best_guess = possible, None
35 for guess in possible:
36 groups = [[] for _ in xrange(7)]
37 for j in possible:
38 if j != guess:
39 groups[H[guess][j]].append(j)
40 max_group = max(groups, key=len)
41 if len(max_group) < len(min_max_group):
42 min_max_group, best_guess = max_group, guess
43 return best_guess
44
45 H = [[sum(a == b for a, b in itertools.izip(wordlist[i], wordlist[j]))
46 for j in xrange(len(wordlist))]
47 for i in xrange(len(wordlist))]
48 possible = range(len(wordlist))
49 n = 0
50 while n < 6:
51 guess = solve(H, possible)
52 n = master.guess(wordlist[guess])
53 possible = [j for j in possible if H[guess][j] == n]
54
55
56 # Time: O(n^2)
57 # Space: O(n)
58 class Solution3(object):
59 def findSecretWord(self, wordlist, master):
60 """
61 :type wordlist: List[Str]
62 :type master: Master
63 :rtype: None
64 """
65 def solve(H, possible):
66 min_max_group, best_guess = possible, None
67 for guess in possible:
68 groups = [[] for _ in xrange(7)]
69 for j in possible:
70 if j != guess:
71 groups[H[guess][j]].append(j)
72 max_group = groups[0]
73 if len(max_group) < len(min_max_group):
74 min_max_group, best_guess = max_group, guess
75 return best_guess
76
77 H = [[sum(a == b for a, b in itertools.izip(wordlist[i], wordlist[j]))
78 for j in xrange(len(wordlist))]
79 for i in xrange(len(wordlist))]
80 possible = range(len(wordlist))
81 n = 0
82 while n < 6:
83 guess = solve(H, possible)
84 n = master.guess(wordlist[guess])
85 possible = [j for j in possible if H[guess][j] == n]
86
********************************

164. Shortest Path Visiting All Nodes


********************************

You have an undirected, connected graph of n nodes labeled from 0 to n - 1. You are given an array graph where graph[i] is a list
of all the nodes connected with node i by an edge.

Return the length of the shortest path that visits every node. You may start and stop at any node, you may revisit nodes
multiple times, and you may reuse edges.

Example 1:

Input: graph = [[1,2,3],[0],[0],[0]]


Output: 4
Explanation: One possible path is [1,0,2,0,3]

Example 2:

Input: graph = [[1],[0,2,4],[1,3,4],[2],[1,2]]


Output: 4
Explanation: One possible path is [0,1,4,2,3]

Constraints:

n == graph.length
1 <= n <= 12
0 <= graph[i].length < n
graph[i] does not contain i.
If graph[a] contains b, then graph[b]
contains a.
The input graph is always connected.
********************************

164. Shortest Path Visiting All Nodes(C++)


********************************

1 // Time: O(n * 2^n)


2 // Space: O(n * 2^n)
3
4 class Solution {
5 public:
6 int shortestPathLength(vector>& graph) {
7 static const auto& INF = numeric_limits::max();
8 vector> dp(1 << graph.size(),
9 vector(graph.size(), INF));
10 queue> q;
11 for (int i = 0; i < graph.size(); ++i) {
12 dp[1 << i][i] = 0;
13 q.emplace(1 << i, i);
14 }
15 while (!q.empty()) {
16 int state, node;
17 tie(state, node) = q.front(); q.pop();
18 auto steps = dp[state][node];
19 for (const auto& nei : graph[node]) {
20 auto new_state = state | (1 << nei);
21 if (dp[new_state][nei] == INF) {
22 dp[new_state][nei] = steps + 1;
23 q.emplace(new_state, nei);
24 }
25 }
26 }
27 return *min_element(dp.back().cbegin(), dp.back().cend());
28 }
29 };
********************************

164. Shortest Path Visiting All Nodes(Python)


********************************

1 # Time: O(n * 2^n)


2 # Space: O(n * 2^n)
3
4 import collections
5
6
7 class Solution(object):
8 def shortestPathLength(self, graph):
9 """
10 :type graph: List[List[int]]
11 :rtype: int
12 """
13 dp = [[float("inf")]*(len(graph))
14 for _ in xrange(1 << len(graph))]
15 q = collections.deque()
16 for i in xrange(len(graph)):
17 dp[1 << i][i] = 0
18 q.append((1 << i, i))
19 while q:
20 state, node = q.popleft()
21 steps = dp[state][node]
22 for nei in graph[node]:
23 new_state = state | (1 << nei)
24 if dp[new_state][nei] == float("inf"):
25 dp[new_state][nei] = steps+1
26 q.append((new_state, nei))
27 return min(dp[-1])
28
*****************

165. Rectangle Area II


*****************

We are given a list of (axis-aligned) rectangles. Each rectangle[i] = [x i1 , y i1 , x i2 , y i2 ] , where (xi1 , y i1 ) are the coordinates of the
bottom-left corner, and (xi2 , y i2 ) are the coordinates of the top-right corner of theith rectangle.

Find the total area covered by all rectangles in the plane. Since the answer may be too large, return itmodulo 109 + 7 .

Example 1:

Input: rectangles = [[0,0,2,2],[1,0,2,3],[1,0,3,1]]


Output: 6
Explanation: As illustrated in the picture.

Example 2:

Input: rectangles = [[0,0,1000000000,1000000000]]


Output: 49
Explanation: The answer is 1018 modulo (109 + 7), which is (109)2 = (-7)2 = 49.

Constraints:

1 <= rectangles.length <= 200


rectanges[i].length = 4
0 <= rectangles[i][j] <= 10 9
The total area covered by all rectangles will never exceed 263 - 1 and thus will fit in a 64-bit signed integer.
*****************

165. Rectangle Area II(C++)


*****************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 enum { OPEN = 1, CLOSE = -1};
7
8 int rectangleArea(vector>& rectangles) {
9 vector> events;
10 set Xvals;
11 for (const auto& rec: rectangles) {
12 events.emplace_back(vector{rec[1], OPEN, rec[0], rec[2]});
13 events.emplace_back(vector{rec[3], CLOSE, rec[0], rec[2]});
14 Xvals.emplace(rec[0]);
15 Xvals.emplace(rec[2]);
16 }
17 sort(events.begin(), events.end());
18 vector X(Xvals.cbegin(), Xvals.cend());
19 unordered_map Xi;
20 for (int i = 0; i < X.size(); ++i) {
21 Xi[X[i]] = i;
22 }
23
24 auto st = new SegmentTreeNode(0, X.size() - 1, X);
25 int64_t result = 0;
26 int64_t cur_x_sum = 0;
27 int cur_y = events[0][0];
28 for (const auto& event: events) {
29 int y = event[0], type = event[1], x1 = event[2], x2 = event[3];
30 result += cur_x_sum * (y - cur_y);
31 cur_x_sum = st->update(Xi[x1], Xi[x2], type);
32 cur_y = y;
33 }
34 return result % static_cast(1e9 + 7);
35 }
36
37 class SegmentTreeNode {
38 public:
39 SegmentTreeNode(int start, int end, const vector& X) :
40 start_(start),
41 end_(end),
42 X_(X),
43 left_(nullptr),
44 right_(nullptr),
45 count_(0),
46 total_(0) {
47 }
48
49 int mid() const {
50 return start_ + (end_ - start_) / 2;
51 }
52
53 SegmentTreeNode *left() {
54 if (left_ == nullptr) {
55 left_ = new SegmentTreeNode(start_, mid(), X_);
56 }
57 return left_;
58 }
59
60 SegmentTreeNode *right() {
61 if (right_ == nullptr) {
62 right_ = new SegmentTreeNode(mid(), end_, X_);
63 }
64 return right_;
65 }
66
67 int64_t total() const {
68 return total_;
69 }
70
71 int64_t update(int i, int j, int val) {
72 if (i >= j) {
73 return 0;
74 }
75 if (start_ == i && end_ == j) {
76 count_ += val;
77 } else {
78 left()->update(i, min(mid(), j), val);
79 right()->update(max(mid(), i), j, val);
80 }
81 if (count_ > 0) {
82 total_ = X_[end_] - X_[start_];
83 } else {
84 total_ = left()->total() + right()->total();
85 }
86 return total_;
87 }
88
89 private:
90 int start_, end_;
91 const vector& X_;
92 SegmentTreeNode *left_, *right_;
93 int count_;
94 int64_t total_;
95 };
96 };
*****************

165. Rectangle Area II(Python)


*****************
1 # Time: O(nlogn)
2 # Space: O(n)
3
4 class SegmentTreeNode(object):
5 def __init__(self, start, end):
6 self.start, self.end = start, end
7 self.total = self.count = 0
8 self._left = self._right = None
9
10 def mid(self):
11 return (self.start+self.end) // 2
12
13 def left(self):
14 self._left = self._left or SegmentTreeNode(self.start, self.mid())
15 return self._left
16
17 def right(self):
18 self._right = self._right or SegmentTreeNode(self.mid(), self.end)
19 return self._right
20
21 def update(self, X, i, j, val):
22 if i >= j:
23 return 0
24 if self.start == i and self.end == j:
25 self.count += val
26 else:
27 self.left().update(X, i, min(self.mid(), j), val)
28 self.right().update(X, max(self.mid(), i), j, val)
29 if self.count > 0:
30 self.total = X[self.end]-X[self.start]
31 else:
32 self.total = self.left().total + self.right().total
33 return self.total
34
35
36 class Solution(object):
37 def rectangleArea(self, rectangles):
38 """
39 :type rectangles: List[List[int]]
40 :rtype: int
41 """
42 OPEN, CLOSE = 1, -1
43 events = []
44 X = set()
45 for x1, y1, x2, y2 in rectangles:
46 events.append((y1, OPEN, x1, x2))
47 events.append((y2, CLOSE, x1, x2))
48 X.add(x1)
49 X.add(x2)
50 events.sort()
51 X = sorted(X)
52 Xi = {x: i for i, x in enumerate(X)}
53
54 st = SegmentTreeNode(0, len(X)-1)
55 result = 0
56 cur_x_sum = 0
57 cur_y = events[0][0]
58 for y, typ, x1, x2 in events:
59 result += cur_x_sum * (y-cur_y)
60 cur_x_sum = st.update(X, Xi[x1], Xi[x2], typ)
61 cur_y = y
62 return result % (10**9+7)
63
*****************

166. K-Similar Strings


*****************

Strings s1 and s2 are k -similar (for some non-negative integer k ) if we can swap the positions of two letters ins1 exactly k
times so that the resulting string equals s2.

Given two anagrams s1 and s2, return the smallest k for which s1 and s2 are k -similar.

Example 1:

Input: s1 = "ab", s2 = "ba"


Output: 1

Example 2:

Input: s1 = "abc", s2 = "bca"


Output: 2

Example 3:

Input: s1 = "abac", s2 = "baca"


Output: 2

Example 4:

Input: s1 = "aabc", s2 = "abca"


Output: 2

Constraints:

1 <= s1.length <= 20


s2.length == s1.length
s1 and s2 contain only lowercase letters from the set {'a', 'b', 'c', 'd', 'e', 'f'} .
s2 is an anagram of s1.
*****************

166. K-Similar Strings(C++)


*****************

1 // Time: O(n * n!/(c_a!*...*c_z!), n is the length of A, B,


2 // c_a...c_z is the count of each alphabet,
3 // n = sum(c_a...c_z)
4 // Space: O(n * n!/(c_a!*...*c_z!)
5
6 class Solution {
7 public:
8 int kSimilarity(string A, string B) {
9 queue q;
10 unordered_set lookup;
11
12 lookup.emplace(A);
13 q.emplace(A);
14 int result = 0;
15 while (!q.empty()) {
16 for (int size = q.size() - 1; size >= 0; --size) {
17 auto s = q.front(); q.pop();
18 if (s == B) {
19 return result;
20 }
21 int i;
22 for (i = 0; s[i] == B[i]; ++i);
23 for (int j = i + 1; j < s.length(); ++j){
24 if (s[j] == B[j] || s[i] != B[j]) {
25 continue;
26 }
27 swap(s[i], s[j]);
28 if (!lookup.count(s)) {
29 lookup.emplace(s);
30 q.emplace(s);
31 }
32 swap(s[i], s[j]);
33 }
34 }
35 ++result;
36 }
37 return result;
38 }
39 };
*****************

166. K-Similar Strings(Python)


*****************

1 # Time: O(n * n!/(c_a!*...*c_z!), n is the length of A, B,


2 # c_a...c_z is the count of each alphabet,
3 # n = sum(c_a...c_z)
4 # Space: O(n * n!/(c_a!*...*c_z!)
5
6 import collections
7
8
9 class Solution(object):
10 def kSimilarity(self, A, B):
11 """
12 :type A: str
13 :type B: str
14 :rtype: int
15 """
16 def neighbors(s, B):
17 for i, c in enumerate(s):
18 if c != B[i]:
19 break
20 t = list(s)
21 for j in xrange(i+1, len(s)):
22 if t[j] == B[i]:
23 t[i], t[j] = t[j], t[i]
24 yield "".join(t)
25 t[j], t[i] = t[i], t[j]
26
27 q = collections.deque([A])
28 lookup = set()
29 result = 0
30 while q:
31 for _ in xrange(len(q)):
32 s = q.popleft()
33 if s == B:
34 return result
35 for t in neighbors(s, B):
36 if t not in lookup:
37 lookup.add(t)
38 q.append(t)
39 result += 1
40
******************************

167. Minimum Cost to Hire K Workers


******************************

There are n workers. You are given two integer arraysquality and wage where quality[i] is the quality of the ith worker and wage[i]
is the minimum wage expectation for the ith worker.

We want to hire exactly k workers to form a paid group. To hire a group ofk workers, we must pay them according to the
following rules:

1. Every worker in the paid group should be paid in the ratio of their quality compared to other workers in the paid group.
2. Every worker in the paid group must be paid at least their minimum-wage expectation.

Given the integer k , return the least amount of money needed to form a paid group satisfying the above conditions. Answers
within 10-5 of the actual answer will be accepted.

Example 1:

Input: quality = [10,20,5], wage = [70,50,30], k = 2


Output: 105.00000
Explanation: We pay 70 to 0th worker and 35 to 2nd worker.

Example 2:

Input: quality = [3,1,10,10,1], wage = [4,8,2,2,7], k = 3


Output: 30.66667
Explanation: We pay 4 to 0th worker, 13.33333 to 2nd and 3rd workers separately.

Constraints:

n == quality.length == wage.length
1 <= k <= n <= 10 4
1 <= quality[i], wage[i] <= 10 4
******************************

167. Minimum Cost to Hire K Workers(C++)


******************************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 double mincostToHireWorkers(vector& quality, vector& wage, int K) {
7 vector> workers;
8 for (int i = 0; i < quality.size(); ++i) {
9 workers.emplace_back(static_cast(wage[i]) / quality[i], quality[i]);
10 }
11 sort(begin(workers), end(workers));
12 auto result = numeric_limits::max();
13 auto sum = 0.0;
14 priority_queue max_heap;
15 for (const auto& [ratio, q]: workers) {
16 sum += q;
17 max_heap.emplace(q);
18 if (max_heap.size() > K) { // keep k smallest q to make sum as small as possible
19 sum -= max_heap.top(), max_heap.pop();
20 }
21 if (max_heap.size() == K) {
22 result = min(result, sum * ratio);
23 }
24 }
25 return result;
26 }
27 };
******************************

167. Minimum Cost to Hire K Workers(Python)


******************************

1 # Time: O(nlogn)
2 # Space : O(n)
3
4 import itertools
5 import heapq
6
7
8 class Solution(object):
9 def mincostToHireWorkers(self, quality, wage, K):
10 """
11 :type quality: List[int]
12 :type wage: List[int]
13 :type K: int
14 :rtype: float
15 """
16 result, qsum = float("inf"), 0
17 max_heap = []
18 for r, q in sorted([float(w)/q, q] for w, q in itertools.izip(wage, quality)):
19 qsum += q
20 heapq.heappush(max_heap, -q)
21 if len(max_heap) > K:
22 qsum -= -heapq.heappop(max_heap)
23 if len(max_heap) == K:
24 result = min(result, qsum*r)
25 return result
26
*************************************

168. Shortest Subarray with Sum at Least K


*************************************

Given an integer array nums and an integer k , return the length of the shortest non-empty subarray of nums with a sum of at
least k . If there is no such subarray, return -1.

A subarray is a contiguous part of an array.

Example 1:

Input: nums = [1], k = 1


Output: 1

Example 2:

Input: nums = [1,2], k = 4


Output: -1

Example 3:

Input: nums = [2,-1,2], k = 3


Output: 3

Constraints:

1 <= nums.length <= 10 5


-105 <= nums[i] <= 10 5
1 <= k <= 10 9
*************************************

168. Shortest Subarray with Sum at Least K(C++)


*************************************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int shortestSubarray(vector& A, int K) {
7 vector accumulated_sum(A.size() + 1, 0);
8 partial_sum(A.cbegin(), A.cend(), next(accumulated_sum.begin()), plus());
9
10 int result = numeric_limits::max();
11 deque mono_increasing_q;
12 for (int i = 0; i < accumulated_sum.size(); ++i) {
13 while (!mono_increasing_q.empty() &&
14 accumulated_sum[i] <= accumulated_sum[mono_increasing_q.back()]) {
15 mono_increasing_q.pop_back();
16 }
17 while (!mono_increasing_q.empty() &&
18 accumulated_sum[i] - accumulated_sum[mono_increasing_q.front()] >= K) {
19 result = min(result, i - mono_increasing_q.front());
20 mono_increasing_q.pop_front();
21 }
22 mono_increasing_q.emplace_back(i);
23 }
24 return result != numeric_limits::max() ? result : -1;
25 }
26 };
*************************************

168. Shortest Subarray with Sum at Least K(Python)


*************************************

1 # Time: O(n)
2 # Space: O(n)
3
4 import collections
5
6
7 class Solution(object):
8 def shortestSubarray(self, A, K):
9 """
10 :type A: List[int]
11 :type K: int
12 :rtype: int
13 """
14 accumulated_sum = [0]*(len(A)+1)
15 for i in xrange(len(A)):
16 accumulated_sum[i+1] = accumulated_sum[i]+A[i]
17
18 result = float("inf")
19 mono_increasing_q = collections.deque()
20 for i, curr in enumerate(accumulated_sum):
21 while mono_increasing_q and curr <= \
22 accumulated_sum[mono_increasing_q[-1]]:
23 mono_increasing_q.pop()
24 while mono_increasing_q and \
25 curr-accumulated_sum[mono_increasing_q[0]] >= K:
26 result = min(result, i-mono_increasing_q.popleft())
27 mono_increasing_q.append(i)
28 return result if result != float("inf") else -1
29
**************************

169. Random Pick with Blacklist


**************************

You are given an m x n grid grid where:

'.' is an empty cell.


'#' is a wall.
'@' is the starting point.
Lowercase letters represent keys.
Uppercase letters represent locks.

You start at the starting point and one move consists of walking one space in one of the four cardinal directions. You cannot
walk outside the grid, or walk into a wall.

If you walk over a key, you can pick it up and you cannot walk over a lock unless you have its corresponding key.

For some 1 <= k <= 6 , there is exactly one lowercase and one uppercase letter of the firstk letters of the English alphabet in
the grid. This means that there is exactly one key for each lock, and one lock for each key; and also that the letters used to
represent the keys and locks were chosen in the same order as the English alphabet.

Return the lowest number of moves to acquire all keys. If it is impossible, return -1.

Example 1:

Input: grid = ["@.a.#","###.#","b.A.B"]


Output: 8
Explanation: Note that the goal is to obtain all the keys not to open all the locks.

Example 2:
Input: grid = ["@..aA","..B#.","....b"]
Output: 6

Example 3:

Input: grid = ["@Aa"]


Output: -1

Constraints:

m == grid.length
n == grid[i].length
1 <= m, n <= 30
grid[i][j] is either
an English letter, '.', '#', or '@'.
The number of keys in the grid is in the range[1, 6].
Each key in the grid is unique.
Each key in the grid has a matching lock.
**************************

169. Random Pick with Blacklist(C++)


**************************
1 // Time: ctor: O(b)
2 // pick: O(1)
3 // Space: O(b)
4
5 class Solution {
6 public:
7 Solution(int N, vector blacklist) :
8 n_(N - blacklist.size()) {
9 unordered_set whitelist;
10 for (int i = n_; i < N; ++i) {
11 whitelist.emplace(i);
12 }
13 for (const auto& black : blacklist) {
14 whitelist.erase(black);
15 }
16 auto white = whitelist.cbegin();
17 for (const auto& black : blacklist) {
18 if (black < n_) {
19 lookup_[black] = *(white++);
20 }
21 }
22 }
23
24 int pick() {
25 int index = rand() % n_;
26 return lookup_.count(index) ? lookup_[index] : index;
27 }
28
29 private:
30 int n_;
31 unordered_map lookup_;
32 };
33
34 // Time: ctor: O(blogb)
35 // pick: O(logb)
36 // Space: O(b)
37 class Solution2 {
38 public:
39 Solution(int N, vector blacklist) :
40 n_(N - blacklist.size()),
41 blacklist_(blacklist) {
42
43 sort(blacklist_.begin(), blacklist_.end());
44 }
45
46 int pick() {
47 int index = rand() % n_;
48 int left = 0, right = blacklist_.size() - 1;
49 while (left <= right) {
50 auto mid = left + (right - left) / 2;
51 if (index + mid < blacklist_[mid]) {
52 right = mid - 1;
53 } else {
54 left = mid + 1;
55 }
56 }
57 return index + left;
58 }
59
60 private:
61 int n_;
62 vector blacklist_;
63 };
64
65 /**
66 * Your Solution object will be instantiated and called as such:
67 * Solution obj = new Solution(N, blacklist);
68 * int param_1 = obj.pick();
69 */
**************************

169. Random Pick with Blacklist(Python)


**************************
1 # Time: ctor: O(b)
2 # pick: O(1)
3 # Space: O(b)
4
5 import random
6
7
8 class Solution(object):
9
10 def __init__(self, N, blacklist):
11 """
12 :type N: int
13 :type blacklist: List[int]
14 """
15 self.__n = N-len(blacklist)
16 self.__lookup = {}
17 white = iter(set(range(self.__n, N))-set(blacklist))
18 for black in blacklist:
19 if black < self.__n:
20 self.__lookup[black] = next(white)
21
22
23 def pick(self):
24 """
25 :rtype: int
26 """
27 index = random.randint(0, self.__n-1)
28 return self.__lookup[index] if index in self.__lookup else index
29
30
31 # Time: ctor: O(blogb)
32 # pick: O(logb)
33 # Space: O(b)
34 import random
35
36 class Solution2(object):
37
38 def __init__(self, N, blacklist):
39 """
40 :type N: int
41 :type blacklist: List[int]
42 """
43 self.__n = N-len(blacklist)
44 blacklist.sort()
45 self.__blacklist = blacklist
46
47 def pick(self):
48 """
49 :rtype: int
50 """
51 index = random.randint(0, self.__n-1)
52 left, right = 0, len(self.__blacklist)-1
53 while left <= right:
54 mid = left+(right-left)//2
55 if index+mid < self.__blacklist[mid]:
56 right = mid-1
57 else:
58 left = mid+1
59 return index+left
60
61
62
*****************************

170. Shortest Path to Get All Keys


*****************************

Given the root of a binary tree, the depth of each node is the shortest distance to the root.

Return the smallest subtree such that it contains all the deepest nodes in the original tree.

A node is called the deepest if it has the largest depth possible among any node in the entire tree.

The subtree of a node is tree consisting of that node, plus the set of all descendants of that node.

Note: This question is the same as 1123: https://leetcode.com/problems/lowest-common-ancestor-of-deepest-leaves/

Example 1:

Input: root = [3,5,1,6,2,0,8,null,null,7,4]


Output: [2,7,4]
Explanation: We return the node with value 2, colored in yellow in the diagram.
The nodes coloured in blue are the deepest nodes of the tree.
Notice that nodes 5, 3 and 2 contain the deepest nodes in the tree but node 2 is the smallest subtree among them, so we return it.

Example 2:

Input: root = [1]


Output: [1]
Explanation: The root is the deepest node in the tree.

Example 3:
Input: root = [0,1,3,null,2]
Output: [2]
Explanation: The deepest node in the tree is 2, the valid subtrees are the subtrees of nodes 2, 1 and 0 but the subtree of node 2 is the smal

Constraints:

The number of nodes in the tree will be in the range[1, 500].


0 <= Node.val <= 500
The values of the nodes in the tree areunique.
*****************************

170. Shortest Path to Get All Keys(C++)


*****************************

1 // Time: O(k*r*c + |E|log|V|) = O(k*r*c + (k*|V|)*log|V|)


2 // = O(k*r*c + (k*(k*2^k))*log(k*2^k))
3 // = O(k*r*c + (k*(k*2^k))*(logk + k*log2))
4 // = O(k*r*c + (k*(k*2^k))*k)
5 // = O(k*r*c + k^3*2^k)
6 // Space: O(|V|) = O(k*2^k)
7
8 class Solution {
9 public:
10 int shortestPathAllKeys(vector& grid) {
11 unordered_map> locations;
12 for (int r = 0; r < grid.size(); ++r) {
13 for (int c = 0; c < grid[0].size(); ++c) {
14 if (string(".#").find(grid[r][c]) == string::npos) {
15 locations[grid[r][c]] = make_pair(r, c);
16 }
17 }
18 }
19 unordered_map> dists;
20 for (const auto& kvp : locations) {
21 dists[kvp.first] = bfs(grid, kvp.first, locations);
22 }
23
24 // Dijkstra's algorithm
25 using T = tuple;
26 priority_queue, greater> min_heap;
27 min_heap.emplace(0, '@', 0);
28 unordered_map> best;
29 best['@'][0] = 0;
30 int count = 0;
31 for (const auto& kvp : locations) {
32 if (islower(kvp.first)) {
33 ++count;
34 }
35 }
36 uint32_t target_state = (1 << count) - 1;
37 while (!min_heap.empty()) {
38 int cur_d, state;
39 char place;
40 tie(cur_d, place, state) = min_heap.top(); min_heap.pop();
41 if (best.count(place) &&
42 best[place].count(state) &&
43 best[place][state] < cur_d) {
44 continue;
45 }
46 if (state == target_state) {
47 return cur_d;
48 }
49 for (const auto& kvp : dists[place]) {
50 int dest, d;
51 tie(dest, d) = kvp;
52 auto next_state = state;
53 if (islower(dest)) {
54 next_state |= (1 << (dest - 'a'));
55 } else if (isupper(dest)) {
56 if (!(state & (1 << (dest - 'A')))) {
57 continue;
58 }
59 }
60 if (!best.count(dest) ||
61 !best[dest].count(next_state) ||
62 cur_d + d < best[dest][next_state]) {
63 best[dest][next_state] = cur_d + d;
64 min_heap.emplace(cur_d + d, dest, next_state);
65 }
66 }
67 }
68 return -1;
69 }
70
71 private:
72 unordered_map bfs(const vector&grid,
73 char source,
74 const unordered_map>& locations) {
75 static const vector> directions{{0, -1}, {0, 1},
76 {-1, 0}, {1, 0}};
77 int r, c;
78 tie(r, c) = locations.at(source);
79 vector> lookup(grid.size(), vector(grid[0].size()));
80 lookup[r][c] = true;
81 queue> q;
82 q.emplace(r, c, 0);
83 unordered_map dist;
84 while (!q.empty()) {
85 int r, c, d;
86 tie(r, c, d) = q.front(); q.pop();
87 if (source != grid[r][c] && grid[r][c] != '.') {
88 dist[grid[r][c]] = d;
89 continue;
90 }
91 for (const auto& dir : directions) {
92 int cr = r + dir.first, cc = c + dir.second;
93 if (!((0 <= cr && cr < grid.size()) &&
94 (0 <= cc && cc < grid[0].size()))) {
95 continue;
96 }
97 if (grid[cr][cc] != '#' && !lookup[cr][cc]) {
98 lookup[cr][cc] = true;
99 q.emplace(cr, cc, d + 1);
100 }
101 }
102 }
103 return dist ;
104 }
105 };
*****************************

170. Shortest Path to Get All Keys(Python)


*****************************
1 # Time: O(k*r*c + |E|log|V|) = O(k*r*c + (k*|V|)*log|V|)
2 # = O(k*r*c + (k*(k*2^k))*log(k*2^k))
3 # = O(k*r*c + (k*(k*2^k))*(logk + k*log2))
4 # = O(k*r*c + (k*(k*2^k))*k)
5 # = O(k*r*c + k^3*2^k)
6 # Space: O(|V|) = O(k*2^k)
7
8 import collections
9 import heapq
10
11
12 class Solution(object):
13 def shortestPathAllKeys(self, grid):
14 """
15 :type grid: List[str]
16 :rtype: int
17 """
18 directions = [(0, -1), (0, 1), (-1, 0), (1, 0)]
19
20 def bfs(grid, source, locations):
21 r, c = locations[source]
22 lookup = [[False]*(len(grid[0])) for _ in xrange(len(grid))]
23 lookup[r][c] = True
24 q = collections.deque([(r, c, 0)])
25 dist = {}
26 while q:
27 r, c, d = q.popleft()
28 if source != grid[r][c] != '.':
29 dist[grid[r][c]] = d
30 continue
31 for direction in directions:
32 cr, cc = r+direction[0], c+direction[1]
33 if not ((0 <= cr < len(grid)) and
34 (0 <= cc < len(grid[cr]))):
35 continue
36 if grid[cr][cc] != '#' and not lookup[cr][cc]:
37 lookup[cr][cc] = True
38 q.append((cr, cc, d+1))
39 return dist
40
41 locations = {place: (r, c)
42 for r, row in enumerate(grid)
43 for c, place in enumerate(row)
44 if place not in '.#'}
45 dists = {place: bfs(grid, place, locations) for place in locations}
46
47 # Dijkstra's algorithm
48 min_heap = [(0, '@', 0)]
49 best = collections.defaultdict(lambda: collections.defaultdict(
50 lambda: float("inf")))
51 best['@'][0] = 0
52 target_state = 2**sum(place.islower() for place in locations)-1
53 while min_heap:
54 cur_d, place, state = heapq.heappop(min_heap)
55 if best[place][state] < cur_d:
56 continue
57 if state == target_state:
58 return cur_d
59 for dest, d in dists[place].iteritems():
60 next_state = state
61 if dest.islower():
62 next_state |= (1 << (ord(dest)-ord('a')))
63 elif dest.isupper():
64 if not (state & (1 << (ord(dest)-ord('A')))):
65 continue
66 if cur_d+d < best[dest][next_state]:
67 best[dest][next_state] = cur_d+d
68 heapq.heappush(min_heap, (cur_d+d, dest, next_state))
69 return -1
70
*********************************

171. Minimum Number of Refueling Stops


*********************************

A car travels from a starting position to a destination which istarget miles east of the starting position.

There are gas stations along the way. The gas stations are represented as an arraystations where stations[i] = [position i, fuel i]
indicates that the ith gas station is positioni miles east of the starting position and hasfueli liters of gas.

The car starts with an infinite tank of gas, which initially hasstartFuel liters of fuel in it. It uses one liter of gas per one mile that
it drives. When the car reaches a gas station, it may stop and refuel, transferring all the gas from the station into the car.

Return the minimum number of refueling stops the car must make in order to reach its destination
. If it cannot reach the
destination, return -1.

Note that if the car reaches a gas station with0 fuel left, the car can still refuel there. If the car reaches the destination with0
fuel left, it is still considered to have arrived.

Example 1:

Input: target = 1, startFuel = 1, stations = []


Output: 0
Explanation: We can reach the target without refueling.

Example 2:

Input: target = 100, startFuel = 1, stations = [[10,100]]


Output: -1
Explanation: We can not reach the target (or even the first gas station).

Example 3:

Input: target = 100, startFuel = 10, stations = [[10,60],[20,30],[30,30],[60,40]]


Output: 2
Explanation: We start with 10 liters of fuel.
We drive to position 10, expending 10 liters of fuel. We refuel from 0 liters to 60 liters of gas.
Then, we drive from position 10 to position 60 (expending 50 liters of fuel),
and refuel from 10 liters to 50 liters of gas. We then drive to and reach the target.
We made 2 refueling stops along the way, so we return 2.

Constraints:

1 <= target, startFuel <= 10 9


0 <= stations.length <= 500
0 <= position i <= position i+1 < target
1 <= fuel i < 10 9
*********************************

171. Minimum Number of Refueling Stops(C++)


*********************************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int minRefuelStops(int target, int startFuel, vector>& stations) {
7 priority_queue max_heap;
8 stations.push_back(vector{target, numeric_limits::min()});
9
10 int result = 0, prev = 0;
11 for (const auto& station : stations) {
12 startFuel -= station[0] - prev;
13 while (!max_heap.empty() && startFuel < 0) {
14 startFuel += max_heap.top(); max_heap.pop();
15 ++result;
16 }
17 if (startFuel < 0) {
18 return -1;
19 }
20 max_heap.emplace(station[1]);
21 prev = station[0];
22 }
23 return result;
24 }
25 };
*********************************

171. Minimum Number of Refueling Stops(Python)


*********************************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 import heapq
5
6
7 class Solution(object):
8 def minRefuelStops(self, target, startFuel, stations):
9 """
10 :type target: int
11 :type startFuel: int
12 :type stations: List[List[int]]
13 :rtype: int
14 """
15 max_heap = []
16 stations.append((target, float("inf")))
17
18 result = prev = 0
19 for location, capacity in stations:
20 startFuel -= location - prev
21 while max_heap and startFuel < 0:
22 startFuel += -heapq.heappop(max_heap)
23 result += 1
24 if startFuel < 0:
25 return -1
26 heapq.heappush(max_heap, -capacity)
27 prev = location
28
29 return result
30
******************

172. Nth Magical Number


******************

A positive integer is magical if it is divisible by either a or b.

Given the three integers n, a, and b, return the nth magical number. Since the answer may be very large,return it modulo 109
+ 7.

Example 1:

Input: n = 1, a = 2, b = 3
Output: 2

Example 2:

Input: n = 4, a = 2, b = 3
Output: 6

Example 3:

Input: n = 5, a = 2, b = 4
Output: 10

Example 4:

Input: n = 3, a = 6, b = 4
Output: 8

Constraints:

1 <= n <= 10 9
2 <= a, b <= 4 * 10 4
******************

172. Nth Magical Number(C++)


******************

1 // Time: O(logn)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int nthMagicalNumber(int N, int A, int B) {
7 static const int M = 1000000007;
8 const uint64_t a = A, b = B;
9 const auto lcm = a * b / gcd(a, b);
10
11 auto left = min(a, b), right = max(a, b) * N;
12 while (left <= right) {
13 const auto mid = left + (right - left) / 2;
14 if (check(A, B, N, lcm, mid)) {
15 right = mid - 1;
16 } else {
17 left = mid + 1;
18 }
19 }
20 return left % M;
21 }
22
23 private:
24 bool check(uint64_t a, uint64_t b, uint64_t N, uint64_t lcm, uint64_t target) {
25 return target / a + target / b - target / lcm >= N;
26 }
27
28 uint64_t gcd(uint64_t a, uint64_t b) {
29 while (b != 0) {
30 int tmp = b;
31 b = a % b;
32 a = tmp;
33 }
34 return a;
35 }
36 };
******************

172. Nth Magical Number(Python)


******************

1 # Time: O(logn)
2 # Space: O(1)
3
4 class Solution(object):
5 def nthMagicalNumber(self, N, A, B):
6 """
7 :type N: int
8 :type A: int
9 :type B: int
10 :rtype: int
11 """
12 def gcd(a, b):
13 while b:
14 a, b = b, a % b
15 return a
16
17 def check(A, B, N, lcm, target):
18 return target//A + target//B - target//lcm >= N
19
20 lcm = A*B // gcd(A, B)
21 left, right = min(A, B), max(A, B)*N
22 while left <= right:
23 mid = left + (right-left)//2
24 if check(A, B, N, lcm, mid):
25 right = mid-1
26 else:
27 left = mid+1
28 return left % (10**9 + 7)
29
******************

173. Profitable Schemes


******************

There is a group of n members, and a list of various crimes they could commit. Theith crime generates a profit[i] and requires
group[i] members to participate in it. If a member participates in one crime, that member can't participate in another crime.

Let's call a profitable scheme any subset of these crimes that generates at leastminProfit profit, and the total number of
members participating in that subset of crimes is at most n.

Return the number of schemes that can be chosen. Since the answer may be very large,return it modulo 109 + 7 .

Example 1:

Input: n = 5, minProfit = 3, group = [2,2], profit = [2,3]


Output: 2
Explanation: To make a profit of at least 3, the group could either commit crimes 0 and 1, or just crime 1.
In total, there are 2 schemes.

Example 2:

Input: n = 10, minProfit = 5, group = [2,3,5], profit = [6,7,8]


Output: 7
Explanation: To make a profit of at least 5, the group could commit any crimes, as long as they commit one.
There are 7 possible schemes: (0), (1), (2), (0,1), (0,2), (1,2), and (0,1,2).

Constraints:

1 <= n <= 100


0 <= minProfit <= 100
1 <= group.length <= 100
1 <= group[i] <= 100
profit.length == group.length
0 <= profit[i] <= 100
******************

173. Profitable Schemes(C++)


******************

1 // Time: O(n * p * g)
2 // Space: O(p * g)
3
4 class Solution {
5 public:
6 int profitableSchemes(int G, int P, vector& group, vector& profit) {
7 static const int M = 1000000007;
8 vector> dp(P + 1, vector(G + 1));
9 dp[0][0] = 1;
10 int result = 0;
11 for (int k = 0; k < group.size(); ++k) {
12 int g = group[k], p = profit[k];
13 for (int i = P; i >= 0; --i)
14 for (int j = G - g; j >= 0; --j)
15 dp[min(i + p, P)][j + g] = (dp[min(i + p, P)][j + g] + dp[i][j]) % M;
16 }
17 for (const auto& p : dp[P]) {
18 result = (result + p) % M;
19 }
20 return result;
21 }
22 };
******************

173. Profitable Schemes(Python)


******************

1 # Time: O(n * p * g)
2 # Space: O(p * g)
3
4 import itertools
5
6
7 class Solution(object):
8 def profitableSchemes(self, G, P, group, profit):
9 """
10 :type G: int
11 :type P: int
12 :type group: List[int]
13 :type profit: List[int]
14 :rtype: int
15 """
16 dp = [[0 for _ in xrange(G+1)] for _ in xrange(P+1)]
17 dp[0][0] = 1
18 for p, g in itertools.izip(profit, group):
19 for i in reversed(xrange(P+1)):
20 for j in reversed(xrange(G-g+1)):
21 dp[min(i+p, P)][j+g] += dp[i][j]
22 return sum(dp[P]) % (10**9 + 7)
23
***********************************

174. Reachable Nodes In Subdivided Graph


***********************************

You are given an undirected graph (the "original graph") with n nodes labeled from 0 to n - 1. You decide to subdivide each
edge in the graph into a chain of nodes, with the number of new nodes varying between each edge.

The graph is given as a 2D array ofedges where edges[i] = [u i, v i, cnti] indicates that there is an edge between nodes ui and v i in
the original graph, and cnti is the total number of new nodes that you willsubdivide the edge into. Note that cnti == 0 means
you will not subdivide the edge.

To subdivide the edge [ui, v i], replace it with (cnti + 1) new edges and cnti new nodes. The new nodes are x 1, x 2, ..., x cnti, and the
new edges are [ui, x 1], [x1, x 2], [x2, x 3], ..., [xcnti+1 , x cnti], [xcnti, v i].

In this new graph, you want to know how many nodes arereachable from the node 0, where a node is reachable if the
distance is maxMoves or less.

Given the original graph and maxMoves, return the number of nodes that are reachable from node 0 in the new graph.

Example 1:

Input: edges = [[0,1,10],[0,2,1],[1,2,2]], maxMoves = 6, n = 3


Output: 13
Explanation: The edge subdivisions are shown in the image above.
The nodes that are reachable are highlighted in yellow.

Example 2:

Input: edges = [[0,1,4],[1,2,6],[0,2,8],[1,3,1]], maxMoves = 10, n = 4


Output: 23

Example 3:

Input: edges = [[1,2,4],[1,4,5],[1,3,1],[2,3,4],[3,4,5]], maxMoves = 17, n = 5


Output: 1
Explanation: Node 0 is disconnected from the rest of the graph, so only node 0 is reachable.

Constraints:

0 <= edges.length <= min(n * (n - 1) / 2, 10 4)


edges[i].length == 3
0 <= ui < v i < n
There are no multiple edges in the graph.
0 <= cnti <= 104
0 <= maxMoves <= 10 9
1 <= n <= 3000
***********************************

174. Reachable Nodes In Subdivided Graph(C++)


***********************************

1 // Time: O((|E| + |V|) * log|V|) = O(|E| * log|V|),


2 // if we can further to use Fibonacci heap, it would be O(|E| + |V| * log|V|)
3 // Space: O(|E| + |V|) = O(|E|)
4
5 class Solution {
6 public:
7 int reachableNodes(vector>& edges, int M, int N) {
8 using P = pair;
9 vector> adj(N);
10 for (const auto& edge: edges) {
11 int u = edge[0], v = edge[1], w = edge[2];
12 adj[u].emplace_back(v, w);
13 adj[v].emplace_back(u, w);
14 }
15 unordered_map best;
16 best[0] = 0;
17 unordered_map> count;
18 int result = 0;
19 priority_queue, greater

> min_heap; min_heap.emplace(0, 0); while (!min_heap.empty()) { int curr_total, u; tie(curr_total, u) = min_heap.top();
min_heap.pop(); if (best.count(u) && best[u] < curr_total) { continue; } ++result; for (const auto& kvp: adj[u]) { int v,
w; tie(v, w) = kvp; count[u][v] = min(w, M - curr_total); int next_total = curr_total + w + 1; if (next_total <= M &&
(!best.count(v) || next_total < best[v])) { best[v] = next_total; min_heap.emplace(next_total, v); } } } for (const auto&
edge: edges) { int u = edge[0], v = edge[1], w = edge[2]; result += min(w, count[u][v] + count[v][u]); } return result; }
};
***********************************

174. Reachable Nodes In Subdivided Graph(Python)


***********************************

1 # Time: O((|E| + |V|) * log|V|) = O(|E| * log|V|),


2 # if we can further to use Fibonacci heap, it would be O(|E| + |V| * log|V|)
3 # Space: O(|E| + |V|) = O(|E|)
4
5 import collections
6 import heapq
7
8 class Solution(object):
9 def reachableNodes(self, edges, M, N):
10 """
11 :type edges: List[List[int]]
12 :type M: int
13 :type N: int
14 :rtype: int
15 """
16 adj = [[] for _ in xrange(N)]
17 for u, v, w in edges:
18 adj[u].append((v, w))
19 adj[v].append((u, w))
20
21 min_heap = [(0, 0)]
22 best = collections.defaultdict(lambda: float("inf"))
23 best[0] = 0
24 count = collections.defaultdict(lambda: collections.defaultdict(int))
25 result = 0
26 while min_heap:
27 curr_total, u = heapq.heappop(min_heap) # O(|V|*log|V|) in total
28 if best[u] < curr_total:
29 continue
30 result += 1
31 for v, w in adj[u]:
32 count[u][v] = min(w, M-curr_total)
33 next_total = curr_total+w+1
34 if next_total <= M and next_total < best[v]:
35 best[v] = next_total
36 heapq.heappush(min_heap, (next_total, v)) # binary heap O(|E|*log|V|) in total
37 # Fibonacci heap O(|E|) in total
38 for u, v, w in edges:
39 result += min(w, count[u][v]+count[v][u])
40 return result
41
**************

175. Super Egg Drop


**************

You are given k identical eggs and you have access to a building with n floors labeled from 1 to n.

You know that there exists a floor f where 0 <= f <= n such that any egg dropped at a floor higher than f will break, and any
egg dropped at or below floor f will not break.

Each move, you may take an unbroken egg and drop it from any floorx (where 1 <= x <= n ). If the egg breaks, you can no
longer use it. However, if the egg does not break, you may reuse it in future moves.

Return the minimum number of moves that you need to determine with certainty what the value of f is.

Example 1:

Input: k = 1, n = 2
Output: 2
Explanation:
Drop the egg from floor 1. If it breaks, we know that f = 0.
Otherwise, drop the egg from floor 2. If it breaks, we know that f = 1.
If it does not break, then we know f = 2.
Hence, we need at minimum 2 moves to determine with certainty what the value of f is.

Example 2:

Input: k = 2, n = 6
Output: 3

Example 3:

Input: k = 3, n = 14
Output: 4

Constraints:

1 <= k <= 100


1 <= n <= 10 4
**************

175. Super Egg Drop(C++)


**************

1 // Time: O(klogn)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int superEggDrop(int K, int N) {
7 int left = 1, right = N;
8 while (left <= right) {
9 const auto mid = left + (right - left) / 2;
10 if (check(mid, K, N)) {
11 right = mid - 1;
12 } else {
13 left = mid + 1;
14 }
15 }
16 return left;
17 }
18
19 private:
20 bool check(int n, int K, int N) {
21 // let f(n, K) be the max number of floors could be solved by n moves and K eggs,
22 // we want to do binary search to find min of n, s.t. f(n, K) >= N,
23 // if we use one move to drop egg with X floors
24 // 1. if it breaks, we can search new X in the range [X+1, X+f(n-1, K-1)]
25 // 2. if it doesn't break, we can search new X in the range [X-f(n-1, K), X-1]
26 // => f(n, K) = (X+f(n-1, K-1))-(X-f(n-1, K))+1 = f(n-1, K-1)+f(n-1, K)+1
27 // => (1) f(n, K) = f(n-1, K) +1+f(n-1, K-1)
28 // (2) f(n, K-1) = f(n-1, K-1)+1+f(n-1, K-2)
29 // let g(n, K) = f(n, K)-f(n, K-1), and we subtract (1) by (2)
30 // => g(n, K) = g(n-1, K)+g(n-1, K-1), obviously, it is binomial coefficient
31 // => C(n, K) = g(n, K) = f(n, K)-f(n, K-1),
32 // which also implies if we have one more egg with n moves and x-1 egges, we can have more C(n, x) floors solvable
33 // => f(n, K) = C(n, K)+f(n, K-1) = C(n, K) + C(n, K-1) + ... + C(n, 1) + f(n, 0) = sum(C(n, k) for k in [1, K])
34 // => all we have to do is to check sum(C(n, k) for k in [1, K]) >= N,
35 // if true, there must exist a 1-to-1 mapping from each F in [1, N] to each sucess and failure sequence of every C(n, k) comb
36 int total = 0, c = 1;
37 for (int k = 1; k <= K; ++k) {
38 c *= n - k + 1;
39 c /= k;
40 total += c;
41 if (total >= N) {
42 return true;
43 }
44 }
45 return false;
46 }
47 };
**************

175. Super Egg Drop(Python)


**************

1 # Time: O(klogn)
2 # Space: O(1)
3
4 class Solution(object):
5 def superEggDrop(self, K, N):
6 """
7 :type K: int
8 :type N: int
9 :rtype: int
10 """
11 def check(n, K, N):
12 # let f(n, K) be the max number of floors could be solved by n moves and K eggs,
13 # we want to do binary search to find min of n, s.t. f(n, K) >= N,
14 # if we use one move to drop egg with X floors
15 # 1. if it breaks, we can search new X in the range [X+1, X+f(n-1, K-1)]
16 # 2. if it doesn't break, we can search new X in the range [X-f(n-1, K), X-1]
17 # => f(n, K) = (X+f(n-1, K-1))-(X-f(n-1, K))+1 = f(n-1, K-1)+f(n-1, K)+1
18 # => (1) f(n, K) = f(n-1, K) +1+f(n-1, K-1)
19 # (2) f(n, K-1) = f(n-1, K-1)+1+f(n-1, K-2)
20 # let g(n, K) = f(n, K)-f(n, K-1), and we subtract (1) by (2)
21 # => g(n, K) = g(n-1, K)+g(n-1, K-1), obviously, it is binomial coefficient
22 # => C(n, K) = g(n, K) = f(n, K)-f(n, K-1),
23 # which also implies if we have one more egg with n moves and x-1 egges, we can have more C(n, x) floors solvable
24 # => f(n, K) = C(n, K)+f(n, K-1) = C(n, K) + C(n, K-1) + ... + C(n, 1) + f(n, 0) = sum(C(n, k) for k in [1, K])
25 # => all we have to do is to check sum(C(n, k) for k in [1, K]) >= N,
26 # if true, there must exist a 1-to-1 mapping from each F in [1, N] to each sucess and failure sequence of every C(n, k) c
27 total, c = 0, 1
28 for k in xrange(1, K+1):
29 c *= n-k+1
30 c //= k
31 total += c
32 if total >= N:
33 return True
34 return False
35
36 left, right = 1, N
37 while left <= right:
38 mid = left + (right-left)//2
39 if check(mid, K, N):
40 right = mid-1
41 else:
42 left = mid+1
43 return left
44
*************************

176. Sum of Subsequence Widths


*************************

The width of a sequence is the difference between the maximum and minimum elements in the sequence.

Given an array of integers nums, return the sum of the widths of all the non-empty subsequences of nums. Since the answer
may be very large, return it modulo 109 + 7 .

A subsequence is a sequence that can be derived from an array by deleting some or no elements without changing the
order of the remaining elements. For example, [3,6,2,7] is a subsequence of the array [0,3,1,6,2,2,7].

Example 1:

Input: nums = [2,1,3]


Output: 6
Explanation: The subsequences are [1], [2], [3], [2,1], [2,3], [1,3], [2,1,3].
The corresponding widths are 0, 0, 0, 1, 1, 2, 2.
The sum of these widths is 6.

Example 2:

Input: nums = [2]


Output: 0

Constraints:

1 <= nums.length <= 10 5


1 <= nums[i] <= 10 5
*************************

176. Sum of Subsequence Widths(C++)


*************************

1 // Time: O(n)
2 // Spce: O(1)
3
4 class Solution {
5 public:
6 int sumSubseqWidths(vector& A) {
7 static const int M = 1e9 + 7;
8 sort(A.begin(), A.end());
9 // sum(A[i] * (2^i - 2^(len(A)-1-i))), i = 0..len(A)-1
10 // <=>
11 // sum(((A[i] - A[len(A)-1-i]) * 2^i), i = 0..len(A)-1
12 int64_t result = 0l, c = 1l;
13 for (int i = 0; i < A.size(); ++i, c = (c << 1) % M) {
14 result = (result + (A[i] - A[A.size() - 1 - i]) * c % M) % M;
15 }
16 return (result + M) % M;
17 }
18 };
*************************

176. Sum of Subsequence Widths(Python)


*************************

1 # Time: O(n)
2 # Spce: O(1)
3
4 class Solution(object):
5 def sumSubseqWidths(self, A):
6 """
7 :type A: List[int]
8 :rtype: int
9 """
10 M = 10**9+7
11 # sum(A[i] * (2^i - 2^(len(A)-1-i))), i = 0..len(A)-1
12 # <=>
13 # sum(((A[i] - A[len(A)-1-i]) * 2^i), i = 0..len(A)-1
14 result, c = 0, 1
15 A.sort()
16 for i in xrange(len(A)):
17 result = (result + (A[i]-A[len(A)-1-i])*c % M) % M
18 c = (c<<1) % M
19 return result
20
***********************

177. Maximum Frequency Stack


***********************

Design a stack-like data structure to push elements to the stack and pop the most frequent element from the stack.

Implement the FreqStack class:

FreqStack() constructs an empty frequency stack.


void push(int val) pushes an integer val onto the top of the stack.
int pop() removes and returns the most frequent element in the stack.
If there is a tie for the most frequent element, the element closest to the stack's top is removed and returned.

Example 1:

Input
["FreqStack", "push", "push", "push", "push", "push", "push", "pop", "pop", "pop", "pop"]
[[], [5], [7], [5], [7], [4], [5], [], [], [], []]
Output
[null, null, null, null, null, null, null, 5, 7, 5, 4]

Explanation
FreqStack freqStack = new FreqStack();
freqStack.push(5); // The stack is [5]
freqStack.push(7); // The stack is [5,7]
freqStack.push(5); // The stack is [5,7,5]
freqStack.push(7); // The stack is [5,7,5,7]
freqStack.push(4); // The stack is [5,7,5,7,4]
freqStack.push(5); // The stack is [5,7,5,7,4,5]
freqStack.pop(); // return 5, as 5 is the most frequent. The stack becomes [5,7,5,7,4].
freqStack.pop(); // return 7, as 5 and 7 is the most frequent, but 7 is closest to the top. The stack becomes [5,7,5,4].
freqStack.pop(); // return 5, as 5 is the most frequent. The stack becomes [5,7,4].
freqStack.pop(); // return 4, as 4, 5 and 7 is the most frequent, but 4 is closest to the top. The stack becomes [5,7].

Constraints:

0 <= val <= 10 9


At most 2 * 104 calls will be made to push and pop.
It is guaranteed that there will be at least one element in the stack before callingpop.
***********************

177. Maximum Frequency Stack(C++)


***********************

1 // Time: O(1)
2 // Space: O(n)
3
4 class FreqStack {
5 public:
6 FreqStack()
7 : max_freq_(0) {
8
9 }
10
11 void push(int x) {
12 ++freq_[x];
13 if (freq_[x] > max_freq_) {
14 max_freq_ = freq_[x];
15 }
16 group_[freq_[x]].emplace_back(x);
17 }
18
19 int pop() {
20 auto x = group_[max_freq_].back(); group_[max_freq_].pop_back();
21 if (group_[max_freq_].empty()) {
22 group_.erase(max_freq_);
23 --max_freq_;
24 }
25 --freq_[x];
26 if (freq_[x] == 0) {
27 freq_.erase(x);
28 }
29 return x;
30 }
31
32 private:
33 unordered_map freq_;
34 unordered_map> group_;
35 int max_freq_;
36
37 };
38
39 /**
40 * Your FreqStack object will be instantiated and called as such:
41 * FreqStack obj = new FreqStack();
42 * obj.push(x);
43 * int param_2 = obj.pop();
44 */
***********************

177. Maximum Frequency Stack(Python)


***********************

1 # Time: O(1)
2 # Space: O(n)
3
4 import collections
5
6
7 class FreqStack(object):
8
9 def __init__(self):
10 self.__freq = collections.Counter()
11 self.__group = collections.defaultdict(list)
12 self.__maxfreq = 0
13
14 def push(self, x):
15 """
16 :type x: int
17 :rtype: void
18 """
19 self.__freq[x] += 1
20 if self.__freq[x] > self.__maxfreq:
21 self.__maxfreq = self.__freq[x]
22 self.__group[self.__freq[x]].append(x)
23
24 def pop(self):
25 """
26 :rtype: int
27 """
28 x = self.__group[self.__maxfreq].pop()
29 if not self.__group[self.__maxfreq]:
30 self.__group.pop(self.__maxfreq)
31 self.__maxfreq -= 1
32 self.__freq[x] -= 1
33 if not self.__freq[x]:
34 self.__freq.pop(x)
35 return x
36
37
38
*************

178. Orderly Queue


*************

You are given a string s and an integer k . You can choose one of the first k letters of s and append it at the end of the string..

Return the lexicographically smallest string you could have after applying the mentioned step any number of moves.

Example 1:

Input: s = "cba", k = 1
Output: "acb"
Explanation:
In the first move, we move the 1st character 'c' to the end, obtaining the string "bac".
In the second move, we move the 1st character 'b' to the end, obtaining the final result "acb".

Example 2:

Input: s = "baaca", k = 3
Output: "aaabc"
Explanation:
In the first move, we move the 1st character 'b' to the end, obtaining the string "aacab".
In the second move, we move the 3rd character 'c' to the end, obtaining the final result "aaabc".

Constraints:

1 <= k <= s.length <= 1000


s consist of lowercase English letters.
*************

178. Orderly Queue(C++)


*************

1 // Time: O(n^2)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 string orderlyQueue(string S, int K) {
7 if (K == 1) {
8 auto result{S};
9 for (int i = 1; i < S.length(); ++i) {
10 result = min(result, S.substr(i) + S.substr(0, i));
11 }
12 return result;
13 }
14 sort(S.begin(), S.end());
15 return S;
16 }
17 };
*************

178. Orderly Queue(Python)


*************

1 # Time: O(n^2)
2 # Space: O(n)
3
4 class Solution(object):
5 def orderlyQueue(self, S, K):
6 """
7 :type S: str
8 :type K: int
9 :rtype: str
10 """
11 if K == 1:
12 return min(S[i:] + S[:i] for i in xrange(len(S)))
13 return "".join(sorted(S))
14
*********************************

179. Numbers At Most N Given Digit Set


*********************************

Given an array of digits which is sorted in non-decreasing order. You can write numbers using each digits[i] as many times as
we want. For example, if digits = ['1','3','5'] , we may write numbers such as '13', '551', and '1351315'.

Return the number of positive integers that can be generated that are less than or equal to a given integern.

Example 1:

Input: digits = ["1","3","5","7"], n = 100


Output: 20
Explanation:
The 20 numbers that can be written are:
1, 3, 5, 7, 11, 13, 15, 17, 31, 33, 35, 37, 51, 53, 55, 57, 71, 73, 75, 77.

Example 2:

Input: digits = ["1","4","9"], n = 1000000000


Output: 29523
Explanation:
We can write 3 one digit numbers, 9 two digit numbers, 27 three digit numbers,
81 four digit numbers, 243 five digit numbers, 729 six digit numbers,
2187 seven digit numbers, 6561 eight digit numbers, and 19683 nine digit numbers.
In total, this is 29523 integers that can be written using the digits array.

Example 3:

Input: digits = ["7"], n = 8


Output: 1

Constraints:

1 <= digits.length <= 9


digits[i].length == 1
digits[i] is a digit from '1' to '9'.
All the values in digits are unique.
digits is sorted in non-decreasing order.
1 <= n <= 10 9
*********************************

179. Numbers At Most N Given Digit Set(C++)


*********************************

1 // Time: O(logn)
2 // Space: O(logn)
3
4 class Solution {
5 public:
6 int atMostNGivenDigitSet(vector& D, int N) {
7 string str_N = to_string(N);
8 unordered_set set_D(D.cbegin(), D.cend());
9 int result = 0;
10 for (int i = 1 ; i < str_N.length() ; ++i) {
11 result += pow(D.size(), i); // x, xx, xxx
12 }
13 int i = 0;
14 // assume N = 1234, D = 1, 2, 3, 4
15 for (i = 0 ; i < str_N.length() ; ++i) {
16 for (const auto& d : D) {
17 if (d[0] < str_N[i]) {
18 // 11xx; 121x, 122x; 1231, 1232, 1233;
19 result += pow(D.size(), str_N.length() - i - 1);
20 } else {
21 break;
22 }
23 }
24 if (!set_D.count(string(1, str_N[i]))) {
25 break;
26 }
27 }
28 return result + int(i == str_N.length()); // 1234
29 }
30 };
*********************************

179. Numbers At Most N Given Digit Set(Python)


*********************************

1 # Time: O(logn)
2 # Space: O(logn)
3
4 class Solution(object):
5 def atMostNGivenDigitSet(self, D, N):
6 """
7 :type D: List[str]
8 :type N: int
9 :rtype: int
10 """
11 str_N = str(N)
12 set_D = set(D)
13 result = sum(len(D)**i for i in xrange(1, len(str_N)))
14 i = 0
15 while i < len(str_N):
16 result += sum(c < str_N[i] for c in D) * (len(D)**(len(str_N)-i-1))
17 if str_N[i] not in set_D:
18 break
19 i += 1
20 return result + int(i == len(str_N))
21
**********************************

180. Valid Permutations for DI Sequence


**********************************

You are given a string s of length n where s[i] is either:

'D' means decreasing, or


'I' means increasing.

A permutation perm of n + 1 integers of all the integers in the range[0, n] is called a valid permutation if for all valid i:

If s[i] == 'D' , then perm[i] > perm[i + 1] , and


If s[i] == 'I' , then perm[i] < perm[i + 1] .

Return the number of valid permutations perm . Since the answer may be large, return it modulo 109 + 7 .

Example 1:

Input: s = "DID"
Output: 5
Explanation: The 5 valid permutations of (0, 1, 2, 3) are:
(1, 0, 3, 2)
(2, 0, 3, 1)
(2, 1, 3, 0)
(3, 0, 2, 1)
(3, 1, 2, 0)

Example 2:

Input: s = "D"
Output: 1

Constraints:

n == s.length
1 <= n <= 200
s[i] is either 'I' or 'D'.
**********************************

180. Valid Permutations for DI Sequence(C++)


**********************************

1 // Time: O(n^2)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int numPermsDISequence(string S) {
7 const int M = 1e9 + 7;
8 vector> dp(2, vector(S.length() + 1, 1));
9 for (int i = 0; i < S.length(); ++i) {
10 if (S[i] == 'I') {
11 dp[(i + 1) % 2][0] = dp[i % 2][0];
12 for (int j = 1; j < S.length() - i; ++j) {
13 dp[(i + 1) % 2][j] = (dp[(i + 1) % 2][j - 1] + dp[i % 2][j]) % M;
14 }
15 } else {
16 dp[(i + 1) % 2][S.length() - i - 1] = dp[i % 2][S.length() - i];
17 for (int j = S.length() - i - 2; j >= 0; --j) {
18 dp[(i + 1) % 2][j] = (dp[(i + 1) % 2][j + 1] + dp[i % 2][j + 1]) % M;
19 }
20 }
21 }
22 return dp[S.length() % 2][0];
23 }
24 };
**********************************

180. Valid Permutations for DI Sequence(Python)


**********************************

1 # Time: O(n^2)
2 # Space: O(n)
3
4 class Solution(object):
5 def numPermsDISequence(self, S):
6 """
7 :type S: str
8 :rtype: int
9 """
10 dp = [1]*(len(S)+1)
11 for c in S:
12 if c == "I":
13 dp = dp[:-1]
14 for i in xrange(1, len(dp)):
15 dp[i] += dp[i-1]
16 else:
17 dp = dp[1:]
18 for i in reversed(xrange(len(dp)-1)):
19 dp[i] += dp[i+1]
20 return dp[0] % (10**9+7)
21
*****************

181. Super Palindromes


*****************

Let's say a positive integer is a super-palindrome if it is a palindrome, and it is also the square of a palindrome.

Given two positive integers left and right represented as strings, return the number of super-palindromes integers in the
inclusive range [left, right] .

Example 1:

Input: left = "4", right = "1000"


Output: 4
Explanation: 4, 9, 121, and 484 are superpalindromes.
Note that 676 is not a superpalindrome: 26 * 26 = 676, but 26 is not a palindrome.

Example 2:

Input: left = "1", right = "2"


Output: 1

Constraints:

1 <= left.length, right.length <= 18


left and right consist of only digits.
left and right cannot have leading zeros.
left and right represent integers in the range [1, 1018 - 1] .
left is less than or equal to right.
*****************

181. Super Palindromes(C++)


*****************

1 // Time: O(n^0.25 * logn)


2 // Space: O(logn)
3
4 class Solution {
5 public:
6 int superpalindromesInRange(string L, string R) {
7 const auto K = static_cast(pow(10, (R.length() + 1) * 0.25));
8 const int64_t l = stol(L), r = stol(R);
9 int result = 0;
10
11 // count odd length
12 for (int k = 0; k < K; ++k) {
13 const string s = to_string(k), rev_s(s.rbegin(), s.rend());
14 int64_t v = stol(s + rev_s.substr(1));
15 v *= v;
16 if (v > r) {
17 break;
18 }
19 if (v >= l && is_palindrome(v)) {
20 ++result;
21 }
22 }
23
24 // count even length
25 for (int k = 0; k < K; ++k) {
26 const string s = to_string(k), rev_s(s.rbegin(), s.rend());
27 int64_t v = stol(s + rev_s);
28 v *= v;
29 if (v > r) {
30 break;
31 }
32 if (v >= l && is_palindrome(v)) {
33 ++result;
34 }
35 }
36
37 return result;
38 }
39
40 private:
41 bool is_palindrome(int64_t k) {
42 const string s = to_string(k), rev_s(s.rbegin(), s.rend());
43 return s == rev_s;
44 }
45 };
*****************

181. Super Palindromes(Python)


*****************

1 # Time: O(n^0.25 * logn)


2 # Space: O(logn)
3
4 class Solution(object):
5 def superpalindromesInRange(self, L, R):
6 """
7 :type L: str
8 :type R: str
9 :rtype: int
10 """
11 def is_palindrome(k):
12 return str(k) == str(k)[::-1]
13
14 K = int((10**((len(R)+1)*0.25)))
15 l, r = int(L), int(R)
16
17 result = 0
18
19 # count odd length
20 for k in xrange(K):
21 s = str(k)
22 t = s + s[-2::-1]
23 v = int(t)**2
24 if v > r:
25 break
26 if v >= l and is_palindrome(v):
27 result += 1
28
29 # count even length
30 for k in xrange(K):
31 s = str(k)
32 t = s + s[::-1]
33 v = int(t)**2
34 if v > r:
35 break
36 if v >= l and is_palindrome(v):
37 result += 1
38
39 return result
40
*************

182. Cat and Mouse


*************

A game on an undirected graph is played by two players, Mouse and Cat, who alternate turns.

The graph is given as follows: graph[a] is a list of all nodes b such that ab is an edge of the graph.

The mouse starts at node 1 and goes first, the cat starts at node 2 and goes second, and there is a hole at node 0.

During each player's turn, they must travel along one edge of the graph that meets where they are. For example, if the
Mouse is at node 1, it must travel to any node in graph[1].

Additionally, it is not allowed for the Cat to travel to the Hole (node 0.)

Then, the game can end in three ways:

If ever the Cat occupies the same node as the Mouse, the Cat wins.
If ever the Mouse reaches the Hole, the Mouse wins.
If ever a position is repeated (i.e., the players are in the same position as a previous turn, and it is the same player's
turn to move), the game is a draw.

Given a graph, and assuming both players play optimally, return

1 if the mouse wins the game,


2 if the cat wins the game, or
0 if the game is a draw.

Example 1:

Input: graph = [[2,5],[3],[0,4,5],[1,4,5],[2,3],[0,2,3]]


Output: 0

Example 2:
Input: graph = [[1,3],[0],[3],[0,2]]
Output: 1

Constraints:

3 <= graph.length <= 50


1 <= graph[i].length < graph.length
0 <= graph[i][j] < graph.length
graph[i][j] != i
graph[i] is unique.
The mouse and the cat can always move.
*************

182. Cat and Mouse(C++)


*************

1 // Time: O(n^3)
2 // Space: O(n^2)
3
4 class Solution {
5 private:
6 enum Location {HOLE, MOUSE_START, CAT_START};
7 enum Result {DRAW, MOUSE, CAT};
8
9 public:
10 int catMouseGame(vector>& graph) {
11 vector>> degree(size(graph), vector>(size(graph), vector(2)));
12 unordered_set ignore(cbegin(graph[HOLE]), cend(graph[HOLE]));
13 for (int m = 0; m < size(graph); ++m) {
14 for (int c = 0; c < size(graph); ++c) {
15 degree[m][c][MOUSE - 1] = size(graph[m]);
16 degree[m][c][CAT - 1] = size(graph[c]) - ignore.count(c);
17 }
18 }
19 vector>> color(size(graph), vector>(size(graph), vector(2)));
20 queue> q;
21 for (int i = 0; i < size(graph); ++i) {
22 if (i == HOLE) {
23 continue;
24 }
25 color[HOLE][i][CAT - 1] = MOUSE;
26 q.emplace(HOLE, i, CAT, MOUSE);
27 for (const auto& t : {MOUSE, CAT}) {
28 color[i][i][t - 1] = CAT;
29 q.emplace(i, i, t, CAT);
30 }
31 }
32 while (!empty(q)) {
33 const auto [i, j, t, c] = q.front(); q.pop();
34 for (const auto& [ni, nj, nt] : parents(graph, i, j, t)) {
35 if (color[ni][nj][nt - 1] != DRAW) {
36 continue;
37 }
38 if (nt == c) {
39 color[ni][nj][nt - 1] = c;
40 q.emplace(ni, nj, nt, c);
41 continue;
42 }
43 --degree[ni][nj][nt - 1];
44 if (!degree[ni][nj][nt - 1]) {
45 color[ni][nj][nt - 1]= c;
46 q.emplace(ni, nj, nt, c);
47 }
48 }
49 }
50 return color[MOUSE_START][CAT_START][MOUSE - 1];
51 }
52
53 private:
54 vector> parents(const vector>& graph,
55 int m, int c, int t) {
56 vector> result;
57 if (t == CAT) {
58 for (const auto& nm : graph[m]) {
59 result.emplace_back(nm, c, MOUSE ^ CAT ^ t);
60 }
61 } else {
62 for (const auto& nc : graph[c]) {
63 if (nc != HOLE) {
64 result.emplace_back(m, nc, MOUSE ^ CAT ^ t);
65 }
66 }
67 }
68 return result;
69 }
70 };
71
72 // Time: O(n^3)
73 // Space: O(n^2)
74 class Solution2 {
75 private:
76 enum Location {HOLE, MOUSE_START, CAT_START};
77 enum Result {DRAW, MOUSE, CAT};
78
79 public:
80 int catMouseGame(vector>& graph) {
81 vector>> degree(size(graph), vector>(size(graph), vector(2)));
82 unordered_set ignore(cbegin(graph[HOLE]), cend(graph[HOLE]));
83 for (int m = 0; m < size(graph); ++m) {
84 for (int c = 0; c < size(graph); ++c) {
85 degree[m][c][MOUSE - 1] = size(graph[m]);
86 degree[m][c][CAT - 1] = size(graph[c]) - ignore.count(c);
87 }
88 }
89 vector>> color(size(graph), vector>(size(graph), vector(2)));
90 queue> q1;
91 queue> q2;
92 for(int i = 0; i < size(graph); ++i) {
93 if (i == HOLE) {
94 continue;
95 }
96 color[HOLE][i][CAT - 1] = MOUSE;
97 q1.emplace(HOLE, i, CAT);
98 for (const auto& t : {MOUSE, CAT}) {
99 color[i][i][t - 1] = CAT;
100 q2.emplace(i, i, t);
101 }
102 }
103 while (!empty(q1)) {
104 const auto [i, j, t] = q1.front(); q1.pop();
105 for (const auto& [ni, nj, nt] : parents(graph, i, j, t)) {
106 if (color[ni][nj][nt - 1] != DRAW) {
107 continue;
108 }
109 if (t == CAT) {
110 color[ni][nj][nt - 1] = MOUSE;
111 q1.emplace(ni, nj, nt);
112 continue;
113 }
114 --degree[ni][nj][nt - 1];
115 if (!degree[ni][nj][nt - 1]) {
116 color[ni][nj][nt - 1] = MOUSE;
117 q1.emplace(ni, nj, nt);
118 }
119 }
120 }
121 while (!empty(q2)) {
122 const auto [i, j, t] = q2.front(); q2.pop();
123 for (const auto& [ni, nj, nt] : parents(graph, i, j, t)) {
124 if (color[ni][nj][nt - 1] != DRAW) {
125 continue;
126 }
127 if (t == MOUSE) {
128 color[ni][nj][nt - 1] = CAT;
129 q2.emplace(ni, nj, nt);
130 continue;
131 }
132 --degree[ni][nj][nt - 1];
133 if (!degree[ni][nj][nt - 1]) {
134 color[ni][nj][nt - 1] = CAT;
135 q2.emplace(ni, nj, nt);
135 q2.emplace(ni, nj, nt);
136 }
137 }
138 }
139 return color[MOUSE_START][CAT_START][MOUSE - 1];
140 }
141
142 private:
143 vector> parents(const vector>& graph,
144 int m, int c, int t) {
145 vector> result;
146 if (t == CAT) {
147 for (const auto& nm : graph[m]) {
148 result.emplace_back(nm, c, MOUSE ^ CAT ^ t);
149 }
150 } else {
151 for (const auto& nc : graph[c]) {
152 if (nc != HOLE) {
153 result.emplace_back(m, nc, MOUSE ^ CAT ^ t);
154 }
155 }
156 }
157 return result;
158 }
159 };
*************

182. Cat and Mouse(Python)


*************

1 # Time: O(n^3)
2 # Space: O(n^2)
3
4 import collections
5
6
7 class Solution(object):
8 def catMouseGame(self, graph):
9 """
10 :type graph: List[List[int]]
11 :rtype: int
12 """
13 HOLE, MOUSE_START, CAT_START = range(3)
14 DRAW, MOUSE, CAT = range(3)
15 def parents(m, c, t):
16 if t == CAT:
17 for nm in graph[m]:
18 yield nm, c, MOUSE^CAT^t
19 else:
20 for nc in graph[c]:
21 if nc != HOLE:
22 yield m, nc, MOUSE^CAT^t
23
24 degree = {}
25 ignore = set(graph[HOLE])
26 for m in xrange(len(graph)):
27 for c in xrange(len(graph)):
28 degree[m, c, MOUSE] = len(graph[m])
29 degree[m, c, CAT] = len(graph[c])-(c in ignore)
30 color = collections.defaultdict(int)
31 q = collections.deque()
32 for i in xrange(len(graph)):
33 if i == HOLE:
34 continue
35 color[HOLE, i, CAT] = MOUSE
36 q.append((HOLE, i, CAT, MOUSE))
37 for t in [MOUSE, CAT]:
38 color[i, i, t] = CAT
39 q.append((i, i, t, CAT))
40 while q:
41 i, j, t, c = q.popleft()
42 for ni, nj, nt in parents(i, j, t):
43 if color[ni, nj, nt] != DRAW:
44 continue
45 if nt == c:
46 color[ni, nj, nt] = c
47 q.append((ni, nj, nt, c))
48 continue
49 degree[ni, nj, nt] -= 1
50 if not degree[ni, nj, nt]:
51 color[ni, nj, nt] = c
52 q.append((ni, nj, nt, c))
53 return color[MOUSE_START, CAT_START, MOUSE]
54
55
56 # Time: O(n^3)
57 # Space: O(n^2)
58 import collections
59
60
61 class Solution2(object):
62 def catMouseGame(self, graph):
63 """
64 :type graph: List[List[int]]
65 :rtype: int
66 """
67 HOLE, MOUSE_START, CAT_START = range(3)
68 DRAW, MOUSE, CAT = range(3)
69 def parents(m, c, t):
70 if t == CAT:
71 for nm in graph[m]:
72 yield nm, c, MOUSE^CAT^t
73 else:
74 for nc in graph[c]:
75 if nc != HOLE:
76 yield m, nc, MOUSE^CAT^t
77
78 color = collections.defaultdict(int)
79 degree = {}
80 ignore = set(graph[HOLE])
81 for m in xrange(len(graph)):
82 for c in xrange(len(graph)):
83 degree[m, c, MOUSE] = len(graph[m])
84 degree[m, c, CAT] = len(graph[c])-(c in ignore)
85 q1 = collections.deque()
86 q2 = collections.deque()
87 for i in xrange(len(graph)):
88 if i == HOLE:
89 continue
90 color[HOLE, i, CAT] = MOUSE
91 q1.append((HOLE, i, CAT))
92 for t in [MOUSE, CAT]:
93 color[i, i, t] = CAT
94 q2.append((i, i, t))
95 while q1:
96 i, j, t = q1.popleft()
97 for ni, nj, nt in parents(i, j, t):
98 if color[ni, nj, nt] != DRAW:
99 continue
100 if t == CAT:
101 color[ni, nj, nt] = MOUSE
102 q1.append((ni, nj, nt))
103 continue
104 degree[ni, nj, nt] -= 1
105 if not degree[ni, nj, nt]:
106 color[ni, nj, nt] = MOUSE
107 q1.append((ni, nj, nt))
108 while q2:
109 i, j, t = q2.popleft()
110 for ni, nj, nt in parents(i, j, t):
111 if color[ni, nj, nt] != DRAW:
112 continue
113 if t == MOUSE:
114 color[ni, nj, nt] = CAT
115 q2.append((ni, nj, nt))
116 continue
117 degree[ni, nj, nt] -= 1
118 if not degree[ni, nj, nt]:
119 color[ni, nj, nt] = CAT
120 q2.append((ni, nj, nt))
121 return color[MOUSE_START, CAT_START, MOUSE]
*************************

183. Number of Music Playlists


*************************

Your music player contains n different songs. You want to listen togoal songs (not necessarily different) during your trip. To
avoid boredom, you will create a playlist so that:

Every song is played at least once.


A song can only be played again only if k other songs have been played.

Given n, goal , and k , return the number of possible playlists that you can create. Since the answer can be very large, return it
modulo 109 + 7 .

Example 1:

Input: n = 3, goal = 3, k = 1
Output: 6
Explanation: There are 6 possible playlists: [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], and [3, 2, 1].

Example 2:

Input: n = 2, goal = 3, k = 0
Output: 6
Explanation: There are 6 possible playlists: [1, 1, 2], [1, 2, 1], [2, 1, 1], [2, 2, 1], [2, 1, 2], and [1, 2, 2].

Example 3:

Input: n = 2, goal = 3, k = 1
Output: 2
Explanation: There are 2 possible playlists: [1, 2, 1] and [2, 1, 2].

Constraints:

0 <= k < n <= goal <= 100


*************************

183. Number of Music Playlists(C++)


*************************

1 // Time: O(n * l)
2 // Space: O(l)
3
4 // Another better solution (generating function), you could refer to
5 // https://leetcode.com/problems/number-of-music-playlists/solution/
6 class Solution {
7 public:
8 int numMusicPlaylists(int N, int L, int K) {
9 static const int M = 1000000007;
10 vector> dp(2, vector(1 + L, 0ull));
11 dp[0][0] = dp[1][1] = 1;
12 for (int n = 1; n <= N; ++n) {
13 dp[n % 2][n] = (dp[(n - 1) % 2][n - 1] * n) % M;
14 for (int l = n + 1; l <= L; ++l) {
15 dp[n % 2][l] = ((dp[n % 2][l - 1] * max(n - K, 0)) % M +
16 (dp[(n - 1) % 2][l - 1] * n) % M) % M;
17 }
18 }
19 return dp[N % 2][L];
20 }
21 };
*************************

183. Number of Music Playlists(Python)


*************************

1 # Time: O(n * l)
2 # Space: O(l)
3
4 class Solution(object):
5 def numMusicPlaylists(self, N, L, K):
6 """
7 :type N: int
8 :type L: int
9 :type K: int
10 :rtype: int
11 """
12 M = 10**9+7
13 dp = [[0 for _ in xrange(1+L)] for _ in xrange(2)]
14 dp[0][0] = dp[1][1] = 1
15 for n in xrange(1, N+1):
16 dp[n % 2][n] = (dp[(n-1) % 2][n-1] * n) % M
17 for l in xrange(n+1, L+1):
18 dp[n % 2][l] = ((dp[n % 2][l-1] * max(n-K, 0)) % M + \
19 (dp[(n-1) % 2][l-1] * n) % M) % M
20 return dp[N % 2][L]
21
***********************

184. Minimize Malware Spread


***********************

You are given a network of n nodes represented as an n x n adjacency matrix graph, where the ith node is directly connected to
the jth node if graph[i][j] == 1.

Some nodes initial are initially infected by malware. Whenever two nodes are directly connected, and at least one of those
two nodes is infected by malware, both nodes will be infected by malware. This spread of malware will continue until no
more nodes can be infected in this manner.

Suppose M(initial) is the final number of nodes infected with malware in the entire network after the spread of malware stops.
We will remove exactly one node from initial.

Return the node that, if removed, would minimize M(initial). If multiple nodes could be removed to minimizeM(initial), return
such a node with the smallest index.

Note that if a node was removed from the initial list of infected nodes, it might still be infected later due to the malware
spread.

Example 1:

Input: graph = [[1,1,0],[1,1,0],[0,0,1]], initial = [0,1]


Output: 0

Example 2:

Input: graph = [[1,0,0],[0,1,0],[0,0,1]], initial = [0,2]


Output: 0

Example 3:

Input: graph = [[1,1,1],[1,1,1],[1,1,1]], initial = [1,2]


Output: 1

Constraints:

n == graph.length
n == graph[i].length
2 <= n <= 300
graph[i][j] is 0 or 1.
graph[i][j] == graph[j][i]
graph[i][i] == 1
1 <= initial.length <= n
0 <= initial[i] <= n - 1
All the integers in initial are unique.
***********************

184. Minimize Malware Spread(C++)


***********************

1 // Time: O(n^2)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int minMalwareSpread(vector>& graph, vector& initial) {
7 UnionFind union_find(graph.size());
8 for (int i = 0; i < graph.size(); ++i) {
9 for (int j = i + 1; j < graph.size(); ++j) {
10 if (graph[i][j] == 1) {
11 union_find.union_set(i, j);
12 }
13 }
14 }
15 unordered_map union_size;
16 for (int i = 0; i < graph.size(); ++i) {
17 ++union_size[union_find.find_set(i)];
18 }
19 unordered_map malware_count;
20 for (const auto& i : initial) {
21 ++malware_count[union_find.find_set(i)];
22 }
23 return *min_element(initial.cbegin(), initial.cend(),
24 [&](const int& a, const int& b) {
25 return make_tuple(malware_count[union_find.find_set(a)] > 1 ? 1 : 0,
26 -union_size[union_find.find_set(a)],
27 a) <
28 make_tuple(malware_count[union_find.find_set(b)] > 1 ? 1 : 0,
29 -union_size[union_find.find_set(b)],
30 b);
31 });
32 }
33
34 private:
35 class UnionFind {
36 public:
37 UnionFind(const int n) : set_(n) {
38 iota(set_.begin(), set_.end(), 0);
39 }
40
41 int find_set(const int x) {
42 if (set_[x] != x) {
43 set_[x] = find_set(set_[x]); // Path compression.
44 }
45 return set_[x];
46 }
47
48 bool union_set(const int x, const int y) {
49 int x_root = find_set(x), y_root = find_set(y);
50 if (x_root == y_root) {
51 return false;
52 }
53 set_[min(x_root, y_root)] = max(x_root, y_root);
54 return true;
55 }
56
57 private:
58 vector set_;
59 };
60 };
***********************

184. Minimize Malware Spread(Python)


***********************

1 # Time: O(n^2)
2 # Space: O(n)
3
4 import collections
5
6
7 class UnionFind(object):
8 def __init__(self, n):
9 self.set = range(n)
10
11 def find_set(self, x):
12 if self.set[x] != x:
13 self.set[x] = self.find_set(self.set[x]) # path compression.
14 return self.set[x]
15
16 def union_set(self, x, y):
17 x_root, y_root = map(self.find_set, (x, y))
18 if x_root == y_root:
19 return False
20 self.set[min(x_root, y_root)] = max(x_root, y_root)
21 return True
22
23
24 class Solution(object):
25 def minMalwareSpread(self, graph, initial):
26 """
27 :type graph: List[List[int]]
28 :type initial: List[int]
29 :rtype: int
30 """
31 union_find = UnionFind(len(graph))
32 for i in xrange(len(graph)):
33 for j in xrange(i+1, len(graph)):
34 if graph[i][j] == 1:
35 union_find.union_set(i, j)
36 union_size = collections.Counter(union_find.find_set(i) for i in xrange(len(graph)))
37 malware_count = collections.Counter(union_find.find_set(i) for i in initial)
38 return min(initial, key=lambda x: [malware_count[union_find.find_set(x)] > 1,
39 -union_size[union_find.find_set(x)],
40 x])
*****************

185. Three Equal Parts


*****************

You are given an array arr which consists of only zeros and ones, divide the array intothree non-empty parts such that all
of these parts represent the same binary value.

If it is possible, return any [i, j] with i + 1 < j , such that:

arr[0], arr[1], ..., arr[i] is the first part,


arr[i + 1], arr[i + 2], ..., arr[j - 1] is the second part, and
arr[j], arr[j + 1], ..., arr[arr.length - 1] is the third part.
All three parts have equal binary values.

If it is not possible, return [-1, -1] .

Note that the entire part is used when considering what binary value it represents. For example,[1,1,0] represents 6 in
decimal, not 3. Also, leading zeros are allowed, so [0,1,1] and [1,1] represent the same value.

Example 1:

Input: arr = [1,0,1,0,1]


Output: [0,3]

Example 2:

Input: arr = [1,1,0,1,1]


Output: [-1,-1]

Example 3:

Input: arr = [1,1,0,0,1]


Output: [0,2]

Constraints:

3 <= arr.length <= 3 * 10 4


arr[i] is 0 or 1
*****************

185. Three Equal Parts(C++)


*****************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 vector threeEqualParts(vector& A) {
7 int total = accumulate(A.cbegin(), A.cend(), 0);
8 if (total % 3 != 0) {
9 return {-1, -1};
10 }
11 if (total == 0) {
12 return {0, A.size() - 1};
13 }
14
15 const auto count = total / 3;
16 vector nums(3);
17 int c = 0;
18 for (int i = 0; i < A.size(); ++i) {
19 if (A[i] == 1) {
20 if (c % count == 0) {
21 nums[c / count] = i;
22 }
23 ++c;
24 }
25 }
26
27 while (nums[2] != A.size()) {
28 if (A[nums[0]] != A[nums[1]] ||
29 A[nums[0]] != A[nums[2]]) {
30 return {-1, -1};
31 }
32 ++nums[0], ++nums[1], ++nums[2];
33 }
34 return {nums[0] - 1, nums[1]};
35 }
36 };
*****************

185. Three Equal Parts(Python)


*****************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def threeEqualParts(self, A):
6 """
7 :type A: List[int]
8 :rtype: List[int]
9 """
10 total = sum(A)
11 if total % 3 != 0:
12 return [-1, -1]
13 if total == 0:
14 return [0, len(A)-1]
15
16 count = total//3
17 nums = [0]*3
18 c = 0
19 for i in xrange(len(A)):
20 if A[i] == 1:
21 if c % count == 0:
22 nums[c//count] = i
23 c += 1
24
25 while nums[2] != len(A):
26 if not A[nums[0]] == A[nums[1]] == A[nums[2]]:
27 return [-1, -1]
28 nums[0] += 1
29 nums[1] += 1
30 nums[2] += 1
31 return [nums[0]-1, nums[1]]
**************************

186. Minimize Malware Spread II


**************************

You are given a network of n nodes represented as an n x n adjacency matrix graph, where the ith node is directly connected to
the jth node if graph[i][j] == 1.

Some nodes initial are initially infected by malware. Whenever two nodes are directly connected, and at least one of those
two nodes is infected by malware, both nodes will be infected by malware. This spread of malware will continue until no
more nodes can be infected in this manner.

Suppose M(initial) is the final number of nodes infected with malware in the entire network after the spread of malware stops.

We will remove exactly one node from initial, completely removing it and any connections from this node to any other
node.

Return the node that, if removed, would minimize M(initial). If multiple nodes could be removed to minimizeM(initial), return
such a node with the smallest index.

Example 1:

Input: graph = [[1,1,0],[1,1,0],[0,0,1]], initial = [0,1]


Output: 0

Example 2:

Input: graph = [[1,1,0],[1,1,1],[0,1,1]], initial = [0,1]


Output: 1

Example 3:

Input: graph = [[1,1,0,0],[1,1,1,0],[0,1,1,1],[0,0,1,1]], initial = [0,1]


Output: 1

Constraints:

n == graph.length
n == graph[i].length
2 <= n <= 300
graph[i][j] is 0 or 1.
graph[i][j] == graph[j][i]
graph[i][i] == 1
1 <= initial.length < n
0 <= initial[i] <= n - 1
All the integers in initial are unique.
**************************

186. Minimize Malware Spread II(C++)


**************************

1 // Time: O(n^2)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int minMalwareSpread(vector>& graph, vector& initial) {
7 unordered_set initial_set(initial.cbegin(), initial.cend());
8 vector clean;
9 for (int i = 0; i < graph.size(); ++i) {
10 if (!initial_set.count(i)) {
11 clean.emplace_back(i);
12 }
13 }
14 UnionFind union_find(graph.size());
15 for (int i = 0; i < clean.size(); ++i) {
16 for (int j = i + 1; j < clean.size(); ++j) {
17 if (graph[clean[i]][clean[j]] == 1) {
18 union_find.union_set(clean[i], clean[j]);
19 }
20 }
21 }
22 unordered_map union_size;
23 for (int i = 0; i < graph.size(); ++i) {
24 ++union_size[union_find.find_set(i)];
25 }
26
27 unordered_map> shared_union;
28 for (const auto& i: initial) {
29 for (const auto& j : clean) {
30 if (graph[i][j] == 1) {
31 auto x = union_find.find_set(j);
32 shared_union[x].emplace(i);
33 }
34 }
35 }
36
37 int result = numeric_limits::max();
38 int total = numeric_limits::min();
39 for (const auto& i : initial) {
40 unordered_set lookup;
41 int curr = 0;
42 for (const auto& j : clean) {
43 if (graph[i][j] == 1) {
44 auto x = union_find.find_set(j);
45 if (shared_union[x].size() == 1 &&
46 !lookup.count(x)) {
47 curr += union_size[x];
48 lookup.emplace(x);
49 }
50 }
51 }
52 if (curr > total ||
53 (curr == total && i < result)) {
54 total = curr;
55 result = i;
56 }
57 }
58 return result;
59 }
60
61 private:
62 class UnionFind {
63 public:
64 UnionFind(const int n) : set_(n) {
65 iota(set_.begin(), set_.end(), 0);
66 }
67
68 int find_set(const int x) {
69 if (set_[x] != x) {
70 set_[x] = find_set(set_[x]); // Path compression.
71 }
72 return set_[x];
73 }
74
75 bool union_set(const int x, const int y) {
76 int x_root = find_set(x), y_root = find_set(y);
77 if (x_root == y_root) {
78 return false;
79 }
80 set_[min(x_root, y_root)] = max(x_root, y_root);
81 return true;
82 }
83
84 private:
85 vector set_;
86 };
87 };
**************************

186. Minimize Malware Spread II(Python)


**************************
1 # Time: O(n^2)
2 # Space: O(n)
3
4 import collections
5
6
7 class UnionFind(object):
8 def __init__(self, n):
9 self.set = range(n)
10
11 def find_set(self, x):
12 if self.set[x] != x:
13 self.set[x] = self.find_set(self.set[x]) # path compression.
14 return self.set[x]
15
16 def union_set(self, x, y):
17 x_root, y_root = map(self.find_set, (x, y))
18 if x_root == y_root:
19 return False
20 self.set[min(x_root, y_root)] = max(x_root, y_root)
21 return True
22
23
24 class Solution(object):
25 def minMalwareSpread(self, graph, initial):
26 """
27 :type graph: List[List[int]]
28 :type initial: List[int]
29 :rtype: int
30 """
31 initial_set = set(initial)
32 clean = [i for i in xrange(len(graph)) if i not in initial_set]
33 union_find = UnionFind(len(graph))
34 for i in xrange(len(clean)):
35 for j in xrange(i+1, len(clean)):
36 if graph[clean[i]][clean[j]] == 1:
37 union_find.union_set(clean[i], clean[j])
38 union_size = collections.Counter(union_find.find_set(i) for i in xrange(len(graph)))
39
40 shared_union = collections.defaultdict(set)
41 for i in initial:
42 for j in clean:
43 if graph[i][j] == 1:
44 x = union_find.find_set(j)
45 shared_union[x].add(i)
46
47 result, total = float("inf"), float("-inf")
48 for i in initial:
49 lookup = set()
50 curr = 0
51 for j in clean:
52 if graph[i][j] == 1:
53 x = union_find.find_set(j)
54 if len(shared_union[x]) == 1 and \
55 x not in lookup:
56 curr += union_size[x]
57 lookup.add(x)
58 if curr > total or \
59 (curr == total and i < result):
60 total = curr
61 result = i
62 return result
*********************

187. Stamping The Sequence


*********************

You are given two strings stamp and target. Initially, there is a string s of length target.length with all s[i] == '?' .

In one turn, you can place stamp over s and replace every letter in the s with the corresponding letter from stamp.

For example, if stamp = "abc" and target = "abcba" , then s is "?????" initially. In one turn you can:
place stamp at index 0 of s to obtain "abc??",
place stamp at index 1 of s to obtain "?abc?", or
place stamp at index 2 of s to obtain "??abc".
Note that stamp must be fully contained in the boundaries ofs in order to stamp (i.e., you cannot placestamp at index 3
of s ).

We want to convert s to target using at most 10 * target.length turns.

Return an array of the index of the left-most letter being stamped at each turn. If we cannot obtain target from s within 10 *
target.length turns, return an empty array.

Example 1:

Input: stamp = "abc", target = "ababc"


Output: [0,2]
Explanation: Initially s = "?????".
- Place stamp at index 0 to get "abc??".
- Place stamp at index 2 to get "ababc".
[1,0,2] would also be accepted as an answer, as well as some other answers.

Example 2:

Input: stamp = "abca", target = "aabcaca"


Output: [3,0,1]
Explanation: Initially s = "???????".
- Place stamp at index 3 to get "???abca".
- Place stamp at index 0 to get "abcabca".
- Place stamp at index 1 to get "aabcaca".

Constraints:

1 <= stamp.length <= target.length <= 1000


stamp and target consist of lowercase English letters.
*********************

187. Stamping The Sequence(C++)


*********************
1 // Time: O((n - m) * m)
2 // Space: O((n - m) * m)
3
4 class Solution {
5 public:
6 vector movesToStamp(string stamp, string target) {
7 const int M = stamp.size(), N = target.size();
8
9 queue q;
10 vector lookup(N);
11 vector result;
12 vector, unordered_set>> A;
13 for (int i = 0; i < N - M + 1; ++i) {
14 unordered_set made, todo;
15 for (int j = 0; j < M; ++j) {
16 if (stamp[j] == target[i + j]) {
17 made.emplace(i + j);
18 } else {
19 todo.emplace(i + j);
20 }
21 }
22 A.emplace_back(made, todo);
23 if (!todo.empty()) {
24 continue;
25 }
26 result.emplace_back(i);
27 for (const auto& m : made) {
28 if (lookup[m]) {
29 continue;
30 }
31 q.emplace(m);
32 lookup[m] = true;
33 }
34 }
35
36 while (!q.empty()) {
37 auto i = q.front(); q.pop();
38 for (int j = max(0, i - M + 1); j < min(N - M, i) + 1; ++j) {
39 unordered_set& made = A[j].first;
40 unordered_set& todo = A[j].second;
41 if (!todo.count(i)) {
42 continue;
43 }
44 todo.erase(i);
45 if (!todo.empty()) {
46 continue;
47 }
48 result.emplace_back(j);
49 for (const auto& m : made) {
50 if (lookup[m]) {
51 continue;
52 }
53 q.emplace(m);
54 lookup[m] = true;
55 }
56 }
57 }
58 if (std::all_of(lookup.cbegin(), lookup.cend(), [](bool i){ return i; })) {
59 reverse(result.begin(), result.end());
60 return result;
61 }
62 return {};
63 }
64 };
*********************

187. Stamping The Sequence(Python)


*********************

1 # Time: O((n - m) * m)
2 # Space: O((n - m) * m)
3
4 import collections
5
6
7 class Solution(object):
8 def movesToStamp(self, stamp, target):
9 M, N = len(stamp), len(target)
10
11 q = collections.deque()
12 lookup = [False]*N
13 result = []
14 A = []
15 for i in xrange(N-M+1):
16 made, todo = set(), set()
17 for j, c in enumerate(stamp):
18 if c == target[i+j]:
19 made.add(i+j)
20 else:
21 todo.add(i+j)
22 A.append((made, todo))
23 if todo:
24 continue
25 result.append(i)
26 for m in made:
27 if lookup[m]:
28 continue
29 q.append(m)
30 lookup[m] = True
31
32 while q:
33 i = q.popleft()
34 for j in xrange(max(0, i-M+1), min(N-M, i)+1):
35 made, todo = A[j]
36 if i not in todo:
37 continue
38 todo.discard(i)
39 if todo:
40 continue
41 result.append(j)
42 for m in made:
43 if lookup[m]:
44 continue
45 q.append(m)
46 lookup[m] = True
47 return result[::-1] if all(lookup) else []
************************

188. Distinct Subsequences II


************************

Given a string s, return the number of distinct non-empty subsequences of s . Since the answer may be very large, return
it modulo 109 + 7 .

A subsequence of a string is a new string that is formed from the original string by deleting some (can be none) of the
characters without disturbing the relative positions of the remaining characters. (i.e., "ace" is a subsequence of "abcde" while
"aec" is not.

Example 1:

Input: s = "abc"
Output: 7
Explanation: The 7 distinct subsequences are "a", "b", "c", "ab", "ac", "bc", and "abc".

Example 2:

Input: s = "aba"
Output: 6
Explanation: The 7 distinct subsequences are "a", "b", "c", "ab", "ac", "bc", and "abc".

Example 3:

Input: s = "aaa"
Output: 3
Explanation: The 3 distinct subsequences are "a", "aa" and "aaa".

Constraints:

1 <= s.length <= 2000


s consists of lowercase English letters.
************************

188. Distinct Subsequences II(C++)


************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int distinctSubseqII(string S) {
7 static const int M = 1e9 + 7;
8 vector dp(26);
9 int result = 0; // sum of dp
10 for (const auto& c : S) {
11 tie(result, dp[c - 'a']) =
12 make_pair(((2 * result) % M - dp[c - 'a'] + 1) % M,
13 (result + 1) % M);
14 }
15 return (result + M) % M;
16 }
17 };
************************

188. Distinct Subsequences II(Python)


************************

1 # Time: O(n)
2 # Space: O(1)
3
4 import collections
5
6
7 class Solution(object):
8 def distinctSubseqII(self, S):
9 """
10 :type S: str
11 :rtype: int
12 """
13 M = 10**9 + 7
14 result, dp = 0, [0]*26
15 for c in S:
16 result, dp[ord(c)-ord('a')] = 2*result-dp[ord(c)-ord('a')]+1, result+1
17 return result % M
*****************************

189. Find the Shortest Superstring


*****************************

Given an array of strings words, return the smallest string that contains each string in words as a substring. If there are multiple
valid strings of the smallest length, return any of them.

You may assume that no string in words is a substring of another string in words.

Example 1:

Input: words = ["alex","loves","leetcode"]


Output: "alexlovesleetcode"
Explanation: All permutations of "alex","loves","leetcode" would also be accepted.

Example 2:

Input: words = ["catg","ctaagt","gcta","ttca","atgcatc"]


Output: "gctaagttcatgcatc"

Constraints:

1 <= words.length <= 12


1 <= words[i].length <= 20
words[i] consists of lowercase English letters.
All the strings of words are unique.
*****************************

189. Find the Shortest Superstring(C++)


*****************************
1 // Time: O(n^2 * (l^2 + 2^n))
2 // Space: O(n^2)
3
4 class Solution {
5 public:
6 string shortestSuperstring(vector& A) {
7 const int n = A.size();
8 vector> overlaps(n, vector(n));
9 for (int i = 0; i < n; ++i) {
10 for (int j = 0; j < n; ++j) {
11 for (int l = min(A[i].length(), A[j].length());
12 l >= 0; --l) {
13 if (A[i].substr(A[i].length() - l) == A[j].substr(0, l)) {
14 overlaps[i][j] = l;
15 break;
16 }
17 }
18 }
19 }
20
21 vector> dp(1 << n, vector(n));
22 vector> prev(1 << n, vector(n, -1));
23 for (int mask = 1; mask < 1 << n; ++mask) {
24 for (int bit = 0; bit < n; ++bit) {
25 if (((mask >> bit) & 1) == 0) {
26 continue;
27 }
28 auto prev_mask = mask ^ (1 << bit);
29 for (int i = 0; i < n; ++i) {
30 if (((prev_mask >> i) & 1) == 0) {
31 continue;
32 }
33 auto value = dp[prev_mask][i] + overlaps[i][bit];
34 if (value > dp[mask][bit]) {
35 dp[mask][bit] = value;
36 prev[mask][bit] = i;
37 }
38 }
39 }
40 }
41
42 int bit = -1;
43 for (int i = 0; i < n; ++i) {
44 if (bit == -1 ||
45 dp.back()[i] > dp.back()[bit]) {
46 bit = i;
47 }
48 }
49 vector words;
50 for (int mask = (1 << n) - 1; bit != -1;) {
51 words.emplace_back(bit);
52 tie(mask, bit) = make_pair(mask ^ (1 << bit),
53 prev[mask][bit]);
54 }
55 reverse(words.begin(), words.end());
56 unordered_set lookup(words.begin(), words.end());
57 for (int i = 0; i < n; ++i) {
58 if (!lookup.count(i)) {
59 words.emplace_back(i);
60 }
61 }
62
63 auto result = A[words[0]];
64 for (int i = 1; i < words.size(); ++i) {
65 auto overlap = overlaps[words[i - 1]][words[i]];
66 result += A[words[i]].substr(overlap);
67 }
68 return result;
69 }
70 };
*****************************

189. Find the Shortest Superstring(Python)


*****************************

1 # Time: O(n^2 * (l^2 + 2^n))


2 # Space: O(n^2)
3
4 class Solution(object):
5 def shortestSuperstring(self, A):
6 """
7 :type A: List[str]
8 :rtype: str
9 """
10 n = len(A)
11 overlaps = [[0]*n for _ in xrange(n)]
12 for i, x in enumerate(A):
13 for j, y in enumerate(A):
14 for l in reversed(xrange(min(len(x), len(y)))):
15 if y[:l].startswith(x[len(x)-l:]):
16 overlaps[i][j] = l
17 break
18
19 dp = [[0]*n for _ in xrange(1<>bit) & 1) == 0:
20 continue
21 prev_mask = mask^(1<>i) & 1) == 0:
22 continue
23 value = dp[prev_mask][i] + overlaps[i][bit]
24 if value > dp[mask][bit]:
25 dp[mask][bit] = value
26 prev[mask][bit] = i
27
28 bit = max(xrange(n), key = dp[-1].__getitem__)
29 words = []
30 mask = (1<
***************************************

190. Largest Component Size by Common Factor


***************************************

You are given an integer array of unique positive integersnums. Consider the following graph:

There are nums.length nodes, labeled nums[0] to nums[nums.length - 1] ,


There is an undirected edge between nums[i] and nums[j] if nums[i] and nums[j] share a common factor greater than 1.

Return the size of the largest connected component in the graph.

Example 1:

Input: nums = [4,6,15,35]


Output: 4

Example 2:

Input: nums = [20,50,9,63]


Output: 2

Example 3:

Input: nums = [2,3,6,7,4,12,21,39]


Output: 8

Constraints:

1 <= nums.length <= 2 * 10 4


1 <= nums[i] <= 10 5
All the values of nums are unique.
***************************************

190. Largest Component Size by Common Factor(C++)


***************************************

1 // Time: O(f * n), f is the max number of unique prime factors


2 // Soace: O(p + n), p is the total number of unique primes
3
4 class Solution {
5 public:
6 int largestComponentSize(vector& A) {
7 UnionFind union_find(A.size());
8 unordered_map nodesWithCommonFactor;
9 for (int i = 0; i < A.size(); ++i) {
10 for (const auto& factor : primeFactors(A[i])) {
11 if (!nodesWithCommonFactor.count(factor)) {
12 nodesWithCommonFactor[factor] = i;
13 }
14 union_find.union_set(nodesWithCommonFactor[factor], i);
15 }
16 }
17 return union_find.max_size();
18 }
19
20 private:
21 vector primeFactors(int i) const {
22 vector result;
23 int d = 2;
24 if (i % d == 0) {
25 while (i % d == 0) {
26 i /= d;
27 }
28 result.emplace_back(d);
29 }
30 d = 3;
31 for (d = 3; d * d <= i; d += 2) {
32 if (i % d == 0) {
33 while (i % d == 0) {
34 i /= d;
35 }
36 result.emplace_back(d);
37 }
38 }
39 if (i > 2) {
40 result.emplace_back(i);
41 }
42 return result;
43 }
44
45 class UnionFind {
46 public:
47 UnionFind(const int n) : set_(n), size_(n, 1) {
48 iota(set_.begin(), set_.end(), 0);
49 }
50
51 int find_set(const int x) {
52 if (set_[x] != x) {
53 set_[x] = find_set(set_[x]); // Path compression.
54 }
55 return set_[x];
56 }
57
58 bool union_set(const int x, const int y) {
59 int x_root = find_set(x), y_root = find_set(y);
60 if (x_root == y_root) {
61 return false;
62 }
63 set_[min(x_root, y_root)] = max(x_root, y_root);
64 size_[max(x_root, y_root)] += size_[min(x_root, y_root)];
65 return true;
66 }
67
68 int max_size() const {
69 return *max_element(size_.cbegin(), size_.cend());
70 }
71
72 private:
73 vector set_;
74 vector size_;
75 };
76 };
***************************************

190. Largest Component Size by Common Factor(Python)


***************************************

1 # Time: O(f * n), f is the max number of unique prime factors


2 # Space: O(p + n), p is the total number of unique primes
3
4 import collections
5
6
7 class UnionFind(object):
8 def __init__(self, n):
9 self.set = range(n)
10 self.size = [1]*n
11
12 def find_set(self, x):
13 if self.set[x] != x:
14 self.set[x] = self.find_set(self.set[x]) # path compression.
15 return self.set[x]
16
17 def union_set(self, x, y):
18 x_root, y_root = map(self.find_set, (x, y))
19 if x_root == y_root:
20 return False
21 self.set[min(x_root, y_root)] = max(x_root, y_root)
22 self.size[max(x_root, y_root)] += self.size[min(x_root, y_root)]
23 return True
24
25
26 class Solution(object):
27 def largestComponentSize(self, A):
28 """
29 :type A: List[int]
30 :rtype: int
31 """
32 def primeFactors(i): # prime factor decomposition
33 result = []
34 d = 2
35 if i%d == 0:
36 while i%d == 0:
37 i //= d
38 result.append(d)
39 d = 3
40 while d*d <= i:
41 if i%d == 0:
42 while i%d == 0:
43 i //= d
44 result.append(d)
45 d += 2
46 if i > 2:
47 result.append(i)
48 return result
49
50 union_find = UnionFind(len(A))
51 nodesWithCommonFactor = collections.defaultdict(int)
52 for i in xrange(len(A)):
53 for factor in primeFactors(A[i]):
54 if factor not in nodesWithCommonFactor:
55 nodesWithCommonFactor[factor] = i
56 union_find.union_set(nodesWithCommonFactor[factor], i)
57 return max(union_find.size)
*****************

191. Tallest Billboard


*****************

You are installing a billboard and want it to have the largest height. The billboard will have two steel supports, one on each
side. Each steel support must be an equal height.

You are given a collection of rods that can be welded together. For example, if you have rods of lengths1, 2, and 3, you can
weld them together to make a support of length 6.

Return the largest possible height of your billboard installation. If you cannot support the billboard, return 0.

Example 1:

Input: rods = [1,2,3,6]


Output: 6
Explanation: We have two disjoint subsets {1,2,3} and {6}, which have the same sum = 6.

Example 2:

Input: rods = [1,2,3,4,5,6]


Output: 10
Explanation: We have two disjoint subsets {2,3,5} and {4,6}, which have the same sum = 10.

Example 3:

Input: rods = [1,2]


Output: 0
Explanation: The billboard cannot be supported, so we return 0.

Constraints:

1 <= rods.length <= 20


1 <= rods[i] <= 1000
sum(rods[i]) <= 5000
*****************

191. Tallest Billboard(C++)


*****************

1 // Time: O(n * 3^(n/2))


2 // Space: O(3^(n/2))
3
4 class Solution {
5 public:
6 int tallestBillboard(vector& rods) {
7 auto left = dp(rods.cbegin(), rods.cbegin() + rods.size() / 2);
8 auto right = dp(rods.cbegin() + rods.size() / 2, rods.cend());
9 int result = 0;
10 for (const auto& kvp : left) {
11 if (right.count(kvp.first)) {
12 result = max(result,
13 left[kvp.first] + right[kvp.first] + kvp.first);
14 }
15 }
16 return result;
17 }
18
19 private:
20 unordered_map dp(vector::const_iterator it,
21 vector::const_iterator end) {
22 unordered_map lookup;
23 lookup[0] = 0;
24 for (; it != end; ++it) {
25 unordered_map tmp(lookup);
26 for (const auto& kvp : tmp) {
27 lookup[kvp.first + *it] = max(lookup[kvp.first + *it], kvp.second);
28 lookup[abs(kvp.first - *it)] = max(lookup[abs(kvp.first - *it)],
29 kvp.second + min(kvp.first, *it));
30 }
31 }
32 return lookup;
33 }
34 };
*****************

191. Tallest Billboard(Python)


*****************

1 # Time: O(n * 3^(n/2))


2 # Space: O(3^(n/2))
3
4 import collections
5
6
7 class Solution(object):
8 def tallestBillboard(self, rods):
9 """
10 :type rods: List[int]
11 :rtype: int
12 """
13 def dp(A):
14 lookup = collections.defaultdict(int)
15 lookup[0] = 0
16 for x in A:
17 for d, y in lookup.items():
18 lookup[d+x] = max(lookup[d+x], y)
19 lookup[abs(d-x)] = max(lookup[abs(d-x)], y + min(d, x))
20 return lookup
21
22 left, right = dp(rods[:len(rods)//2]), dp(rods[len(rods)//2:])
23 return max(left[d]+right[d]+d for d in left if d in right)
*********************************

192. Delete Columns to Make Sorted III


*********************************

You are given an array of n strings strs, all of the same length.

We may choose any deletion indices, and we delete all the characters in those indices for each string.

For example, if we have strs = ["abcdef","uvwxyz"] and deletion indices {0, 2, 3} , then the final array after deletions is["bef", "vyz"].

Suppose we chose a set of deletion indicesanswer such that after deletions, the final array hasevery string (row) in
lexicographic order. (i.e., (strs[0][0] <= strs[0][1] <= ... <= strs[0][strs[0].length - 1]) , and (strs[1][0] <= strs[1][1] <= ... <= strs[1][strs[1].length - 1]) ,
and so on). Return the minimum possible value of answer.length.

Example 1:

Input: strs = ["babca","bbazb"]


Output: 3
Explanation: After deleting columns 0, 1, and 4, the final array is strs = ["bc", "az"].
Both these rows are individually in lexicographic order (ie. strs[0][0] <= strs[0][1] and strs[1][0] <= strs[1][1]).
Note that strs[0] > strs[1] - the array strs is not necessarily in lexicographic order.

Example 2:

Input: strs = ["edcba"]


Output: 4
Explanation: If we delete less than 4 columns, the only row will not be lexicographically sorted.

Example 3:

Input: strs = ["ghi","def","abc"]


Output: 0
Explanation: All rows are already lexicographically sorted.

Constraints:

n == strs.length
1 <= n <= 100
1 <= strs[i].length <= 100
strs[i] consists of lowercase English letters.
*********************************

192. Delete Columns to Make Sorted III(C++)


*********************************

1 // Time: O(n * l^2)


2 // Space: O(l)
3
4 class Solution {
5 public:
6 int minDeletionSize(vector& A) {
7 vector dp(A[0].length(), 1);
8 for (int j = 0; j < A[0].length(); ++j) {
9 for (int i = 0; i < j; ++i) {
10 int k = 0;
11 for (; k < A.size(); ++k) {
12 if (A[k][i] > A[k][j]) {
13 break;
14 }
15 }
16 if (k == A.size()) {
17 dp[j] = max(dp[j], dp[i] + 1);
18 }
19 }
20 }
21 return A[0].length() - *max_element(dp.begin(), dp.end());
22 }
23 };
*********************************

192. Delete Columns to Make Sorted III(Python)


*********************************

1 # Time: O(n * l^2)


2 # Space: O(l)
3
4 class Solution(object):
5 def minDeletionSize(self, A):
6 """
7 :type A: List[str]
8 :rtype: int
9 """
10 dp = [1] * len(A[0])
11 for j in xrange(1, len(A[0])):
12 for i in xrange(j):
13 if all(A[k][i] <= A[k][j] for k in xrange(len(A))):
14 dp[j] = max(dp[j], dp[i]+1)
15 return len(A[0]) - max(dp)
*********************************

193. Least Operators to Express Number


*********************************

Given a single positive integer x , we will write an expression of the formx (op1) x (op2) x (op3) x ... where each operator op1, op2,
etc. is either addition, subtraction, multiplication, or division (+, -, *, or /). For example, with x = 3 , we might write 3 * 3 / 3 + 3 - 3
which is a value of 3.

When writing such an expression, we adhere to the following conventions:

The division operator (/) returns rational numbers.


There are no parentheses placed anywhere.
We use the usual order of operations: multiplication and division happen before addition and subtraction.
It is not allowed to use the unary negation operator (-). For example, "x - x " is a valid expression as it only uses
subtraction, but "-x + x " is not because it uses negation.

We would like to write an expression with the least number of operators such that the expression equals the giventarget.
Return the least number of operators used.

Example 1:

Input: x = 3, target = 19
Output: 5
Explanation: 3 * 3 + 3 * 3 + 3 / 3.
The expression contains 5 operations.

Example 2:

Input: x = 5, target = 501


Output: 8
Explanation: 5 * 5 * 5 * 5 - 5 * 5 * 5 + 5 / 5.
The expression contains 8 operations.

Example 3:

Input: x = 100, target = 100000000


Output: 3
Explanation: 100 * 100 * 100 * 100.
The expression contains 3 operations.

Constraints:

2 <= x <= 100


1 <= target <= 2 * 10 8
*********************************

193. Least Operators to Express Number(C++)


*********************************

1 // Time: O(logn/logx) = O(1)


2 // Space: O(logn) = O(1)
3
4 class Solution {
5 public:
6 int leastOpsExpressTarget(int x, int target) {
7 int pos = 0, neg = 0, k;
8 for (k = 0; target > 0; ++k, target /= x) {
9 int r = target % x;
10 if (k > 0) {
11 tie(pos, neg) = make_pair(
12 min(r * k + pos, (r + 1) * k + neg),
13 min((x - r) * k + pos, (x - r - 1) * k + neg)
14 );
15 } else {
16 tie(pos, neg) = make_pair(r * 2, (x - r) * 2);
17 }
18 }
19 return min(pos, k + neg) - 1;
20 }
21 };
*********************************

193. Least Operators to Express Number(Python)


*********************************

1 # Time: O(logn/logx) = O(1)


2 # Space: O(logn) = O(1)
3
4 class Solution(object):
5 def leastOpsExpressTarget(self, x, target):
6 """
7 :type x: int
8 :type target: int
9 :rtype: int
10 """
11 pos, neg, k = 0, 0, 0
12 while target:
13 target, r = divmod(target, x)
14 if k:
15 pos, neg = min(r*k + pos, (r+1)*k + neg), \
16 min((x-r)*k + pos, (x-r-1)*k + neg)
17 else:
18 pos, neg = r*2, (x-r)*2
19 k += 1
20 return min(pos, k+neg) - 1
*******************

194. Binary Tree Cameras


*******************

You are given the root of a binary tree. We install cameras on the tree nodes where each camera at a node can monitor its
parent, itself, and its immediate children.

Return the minimum number of cameras needed to monitor all nodes of the tree.

Example 1:

Input: root = [0,0,null,0,0]


Output: 1
Explanation: One camera is enough to monitor all nodes if placed as shown.

Example 2:

Input: root = [0,0,null,0,null,0,null,null,0]


Output: 2
Explanation: At least two cameras are needed to monitor all nodes of the tree. The above image shows one of the valid configurations of camer

Constraints:

The number of nodes in the tree is in the range[1, 1000].


Node.val == 0
*******************

194. Binary Tree Cameras(C++)


*******************

1 // Time: O(n)
2 // Space: O(h)
3
4 /**
5 * Definition for a binary tree node.
6 * struct TreeNode {
7 * int val;
8 * TreeNode *left;
9 * TreeNode *right;
10 * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
11 * };
12 */
13 class Solution {
14 public:
15 int minCameraCover(TreeNode* root) {
16 int result = 0;
17 if (dfs(root, &result) == UNCOVERED) {
18 ++result;
19 }
20 return result;
21 }
22
23 private:
24 int dfs(TreeNode* root, int *result) {
25 int left = root->left ? dfs(root->left, result) : COVERED;
26 int right = root->right ? dfs(root->right, result) : COVERED;
27 if (left == UNCOVERED || right == UNCOVERED) {
28 ++(*result);
29 return CAMERA;
30 }
31 if (left == CAMERA || right == CAMERA) {
32 return COVERED;
33 }
34 return UNCOVERED;
35 }
36
37 enum NODE {
38 UNCOVERED, COVERED, CAMERA
39 };
40 };
*******************

194. Binary Tree Cameras(Python)


*******************

1 # Time: O(n)
2 # Space: O(h)
3
4 # Definition for a binary tree node.
5 class TreeNode(object):
6 def __init__(self, x):
7 self.val = x
8 self.left = None
9 self.right = None
10
11
12 class Solution(object):
13 def minCameraCover(self, root):
14 """
15 :type root: TreeNode
16 :rtype: int
17 """
18 UNCOVERED, COVERED, CAMERA = range(3)
19 def dfs(root, result):
20 left = dfs(root.left, result) if root.left else COVERED
21 right = dfs(root.right, result) if root.right else COVERED
22 if left == UNCOVERED or right == UNCOVERED:
23 result[0] += 1
24 return CAMERA
25 if left == CAMERA or right == CAMERA:
26 return COVERED
27 return UNCOVERED
28
29 result = [0]
30 if dfs(root, result) == UNCOVERED:
31 result[0] += 1
32 return result[0]
**********************

195. Equal Rational Numbers


**********************

Given two strings s and t, each of which represents a non-negative rational number, returntrue if and only if they represent
the same number. The strings may use parentheses to denote the repeating part of the rational number.

A rational number can be represented using up to three parts:<IntegerPart>, <NonRepeatingPart>, and a <RepeatingPart>. The
number will be represented in one of the following three ways:

<IntegerPart>
For example, 12, 0, and 123.
<IntegerPart><.><NonRepeatingPart>
For example, 0.5, 1., 2.12, and 123.0001.
<IntegerPart><.><NonRepeatingPart><(><RepeatingPart><)>
For example, 0.1(6), 1.(9), 123.00(1212).

The repeating portion of a decimal expansion is conventionally denoted within a pair of round brackets. For example:

1/6 = 0.16666666... = 0.1(6) = 0.1666(6) = 0.166(66) .

Example 1:

Input: s = "0.(52)", t = "0.5(25)"


Output: true
Explanation: Because "0.(52)" represents 0.52525252..., and "0.5(25)" represents 0.52525252525..... , the strings represent the same number.

Example 2:

Input: s = "0.1666(6)", t = "0.166(66)"


Output: true

Example 3:

Input: s = "0.9(9)", t = "1."


Output: true
Explanation: "0.9(9)" represents 0.999999999... repeated forever, which equals 1. [See this link for an explanation.]
"1." represents the number 1, which is formed correctly: (IntegerPart) = "1" and (NonRepeatingPart) = "".

Constraints:

Each part consists only of digits.


The <IntegerPart> does not have leading zeros (except for the zero itself).
1 <= <IntegerPart>.length <= 4
0 <= <NonRepeatingPart>.length <= 4
1 <= <RepeatingPart>.length <= 4
**********************

195. Equal Rational Numbers(C++)


**********************

1 // Time: O(1)
2 // Space: O(1)
3
4 class Fraction {
5 public:
6 Fraction() = default;
7 Fraction(int64_t n)
8 : Fraction(n, 1)
9 {
10 }
11 Fraction(int64_t n, int64_t d)
12 : numerator_(n)
13 , denominator_(d)
14 , integer_(0)
15 {
16 reduce();
17 }
18 ~Fraction() = default;
19
20 void set_num(int64_t value) { numerator_ = value; }
21 void set_den(int64_t value) { denominator_ = value; }
22 void set_int(int64_t value) { integer_ = value; }
23 int64_t get_num() const { return numerator_; }
24 int64_t get_den() const { return denominator_; }
25 int64_t get_int() const { return integer_; }
26 void reduce();
27 int64_t calculate_gcd(int64_t, int64_t) const;
28
29 Fraction& operator+=(const Fraction& rhs);
30 private:
31 int64_t numerator_, denominator_, integer_;
32 };
33
34 void Fraction::reduce()
35 {
36 const auto gcd = calculate_gcd(numerator_, denominator_);
37 numerator_ = numerator_ / gcd;
38 denominator_ = denominator_ / gcd;
39 integer_ += numerator_ / denominator_;
40 numerator_ %= denominator_;
41 }
42
43 int64_t Fraction::calculate_gcd(int64_t a, int64_t b) const
44 {
45 a = std::abs(a);
46 b = std::abs(b);
47 while (b != 0) {
48 int64_t tmp = b;
49 b = a % b;
50 a = tmp;
51 }
52 return a;
53 }
54
55 Fraction& Fraction::operator+=(const Fraction& rhs)
56 {
57 set_num((get_num() * rhs.get_den()) + (get_den() * rhs.get_num()));
58 set_den(get_den() * rhs.get_den());
59 set_int(get_int() + rhs.get_int());
60 reduce();
61 return *this;
62 }
63
64 bool operator==(const Fraction &lhs, const Fraction &rhs) {
65 return lhs.get_num() == rhs.get_num() &&
66 lhs.get_den() == rhs.get_den() &&
67 lhs.get_int() == rhs.get_int();
68 }
69
70 std::ostream &operator<<(std::ostream &os, const Fraction &value) {
71 os << value.get_int() << ".(" << value.get_num() << "/" << value.get_den() << ")";
72 return os;
73 }
74
75 class Solution {
76 public:
77 bool isRationalEqual(string S, string T) {
78 return frac(S) == frac(T);
79 }
80
81 private:
82 Fraction frac(const string& S) {
83 auto i = S.find('.');
84 if (i == string::npos) {
85 return Fraction(stol(S));
86 }
87
88 Fraction result(stol(S.substr(0, i)), 1);
89 const auto& non_int_part = S.substr(i + 1);
90 i = non_int_part.find('(');
91 if (i == string::npos) {
92 if (!non_int_part.empty()) {
93 result += Fraction(stol(non_int_part),
94 static_cast(pow(10, non_int_part.length())));
95 }
96 return result;
97 }
98
99 if (i > 0) {
100 result += Fraction(stol(non_int_part.substr(0, i)),
101 static_cast(pow(10, i)));
102 }
103 const auto& repeat_part = non_int_part.substr(i + 1, non_int_part.length() - i - 2);
104 result += Fraction(stol(repeat_part),
105 static_cast(pow(10, i)) *
106 (static_cast(pow(10, repeat_part.length())) - 1));
107 return result;
108 }
109 };
110
**********************

195. Equal Rational Numbers(Python)


**********************

1 # Time: O(1)
2 # Space: O(1)
3
4 from fractions import Fraction
5
6
7 class Solution(object):
8 def isRationalEqual(self, S, T):
9 """
10 :type S: str
11 :type T: str
12 :rtype: bool
13 """
14 def frac(S):
15 if '.' not in S:
16 return Fraction(int(S), 1)
17
18 i = S.index('.')
19 result = Fraction(int(S[:i]), 1)
20 non_int_part = S[i+1:]
21 if '(' not in non_int_part:
22 if non_int_part:
23 result += Fraction(int(non_int_part), 10**len(non_int_part))
24 return result
25
26 i = non_int_part.index('(')
27 if i:
28 result += Fraction(int(non_int_part[:i]), 10**i)
29 repeat_part = non_int_part[i+1:-1]
30 result += Fraction(int(repeat_part), 10**i * (10**len(repeat_part)-1))
31 return result
32
33 return frac(S) == frac(T)
*************

196. Odd Even Jump


*************

You are given an integer array arr. From some starting index, you can make a series of jumps. The (1st, 3rd , 5th, ...) jumps in
the series are called odd-numbered jumps, and the (2nd, 4th, 6th, ...) jumps in the series are called even-numbered jumps.
Note that the jumps are numbered, not the indices.

You may jump forward from index i to index j (with i < j ) in the following way:

During odd-numbered jumps (i.e., jumps 1, 3, 5, ...), you jump to the indexj such that arr[i] <= arr[j] and arr[j] is the
smallest possible value. If there are multiple such indices j, you can only jump to the smallest such index j.
During even-numbered jumps (i.e., jumps 2, 4, 6, ...), you jump to the indexj such that arr[i] >= arr[j] and arr[j] is the
largest possible value. If there are multiple such indices j, you can only jump to the smallest such index j.
It may be the case that for some index i, there are no legal jumps.

A starting index is good if, starting from that index, you can reach the end of the array (indexarr.length - 1) by jumping some
number of times (possibly 0 or more than once).

Return the number of good starting indices.

Example 1:

Input: arr = [10,13,12,14,15]


Output: 2
Explanation:
From starting index i = 0, we can make our 1st jump to i = 2 (since arr[2] is the smallest among arr[1], arr[2], arr[3], arr[4] that is great
From starting index i = 1 and i = 2, we can make our 1st jump to i = 3, then we cannot jump any more.
From starting index i = 3, we can make our 1st jump to i = 4, so we have reached the end.
From starting index i = 4, we have reached the end already.
In total, there are 2 different starting indices i = 3 and i = 4, where we can reach the end with some number of
jumps.

Example 2:

Input: arr = [2,3,1,1,4]


Output: 3
Explanation:
From starting index i = 0, we make jumps to i = 1, i = 2, i = 3:
During our 1st jump (odd-numbered), we first jump to i = 1 because arr[1] is the smallest value in [arr[1], arr[2], arr[3], arr[4]] that is g
During our 2nd jump (even-numbered), we jump from i = 1 to i = 2 because arr[2] is the largest value in [arr[2], arr[3], arr[4]] that is less
During our 3rd jump (odd-numbered), we jump from i = 2 to i = 3 because arr[3] is the smallest value in [arr[3], arr[4]] that is greater than
We can't jump from i = 3 to i = 4, so the starting index i = 0 is not good.
In a similar manner, we can deduce that:
From starting index i = 1, we jump to i = 4, so we reach the end.
From starting index i = 2, we jump to i = 3, and then we can't jump anymore.
From starting index i = 3, we jump to i = 4, so we reach the end.
From starting index i = 4, we are already at the end.
In total, there are 3 different starting indices i = 1, i = 3, and i = 4, where we can reach the end with some
number of jumps.

Example 3:
Input: arr = [5,1,3,4,2]
Output: 3
Explanation: We can reach the end from starting indices 1, 2, and 4.

Constraints:

1 <= arr.length <= 2 * 10 4


0 <= arr[i] < 10 5
*************

196. Odd Even Jump(C++)


*************
1 // Time: O(nlogn)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int oddEvenJumps(vector& A) {
7 vector idx(A.size());
8 iota(idx.begin(), idx.end(), 0);
9
10 sort(idx.begin(), idx.end(),
11 [&](int a, int b) {
12 return A[a] != A[b] ? A[a] < A[b] : a < b;
13 });
14 const auto& next_higher = findNext(idx);
15 sort(idx.begin(), idx.end(),
16 [&](int a, int b) {
17 return A[a] != A[b] ? A[a] > A[b] : a < b;
18 });
19 const auto& next_lower = findNext(idx);
20
21 vector odd(A.size()), even(A.size());
22 odd.back() = even.back() = true;
23 for (int i = A.size() - 2; i >= 0; --i) {
24 if (next_higher[i] != -1) {
25 odd[i] = even[next_higher[i]];
26 }
27 if (next_lower[i] != -1) {
28 even[i] = odd[next_lower[i]];
29 }
30 }
31 return count(odd.cbegin(), odd.cend(), true);
32 }
33
34 private:
35 vector findNext(const vector& idx) {
36 vector result(idx.size(), -1);
37 vector stack;
38 for (const auto& i : idx) {
39 while (!stack.empty() && stack.back() < i) {
40 result[stack.back()] = i, stack.pop_back();
41 }
42 stack.emplace_back(i);
43 }
44 return result;
45 }
46 };
47
48 // Time: O(nlogn)
49 // Space: O(n)
50 class Solution2 {
51 public:
52 int oddEvenJumps(vector& A) {
53 vector odd(A.size()), even(A.size());
54 odd.back() = even.back() = true;
55 map reachables{{A.back(), A.size() - 1}};
56 for (int i = A.size() - 2; i >= 0; --i) {
57 auto high = reachables.lower_bound(A[i]);
58 if (high != reachables.cend()) {
59 odd[i] = even[high->second];
60 }
61 auto low = reachables.upper_bound(A[i]);
62 if (low != reachables.cbegin()) {
63 even[i] = odd[prev(low)->second];
64 }
65 reachables[A[i]] = i;
66 }
67 return count(odd.cbegin(), odd.cend(), true);
68 }
69 };
*************

196. Odd Even Jump(Python)


*************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 class Solution(object):
5 def oddEvenJumps(self, A):
6 """
7 :type A: List[int]
8 :rtype: int
9 """
10 def findNext(idx):
11 result = [None]*len(idx)
12 stack = []
13 for i in idx:
14 while stack and stack[-1] < i:
15 result[stack.pop()] = i
16 stack.append(i)
17 return result
18
19 idx = sorted(range(len(A)), key = lambda i: A[i])
20 next_higher = findNext(idx)
21 idx.sort(key = lambda i: -A[i])
22 next_lower = findNext(idx)
23
24 odd, even = [False]*len(A), [False]*len(A)
25 odd[-1], even[-1] = True, True
26 for i in reversed(xrange(len(A)-1)):
27 if next_higher[i]:
28 odd[i] = even[next_higher[i]]
29 if next_lower[i]:
30 even[i] = odd[next_lower[i]]
31 return sum(odd)
****************

197. Unique Paths III


****************

You are given an m x n integer array grid where grid[i][j] could be:

1 representing the starting square. There is exactly one starting square.


2 representing the ending square. There is exactly one ending square.
0 representing empty squares we can walk over.
-1 representing obstacles that we cannot walk over.

Return the number of 4-directional walks from the starting square to the ending square, that walk over every non-obstacle
square exactly once.

Example 1:

Input: grid = [[1,0,0,0],[0,0,0,0],[0,0,2,-1]]


Output: 2
Explanation: We have the following two paths:
1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2)
2. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2)

Example 2:

Input: grid = [[1,0,0,0],[0,0,0,0],[0,0,0,2]]


Output: 4
Explanation: We have the following four paths:
1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2),(2,3)
2. (0,0),(0,1),(1,1),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),(0,3),(1,3),(2,3)
3. (0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(1,1),(0,1),(0,2),(0,3),(1,3),(2,3)
4. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2),(2,3)
Example 3:

Input: grid = [[0,1],[2,0]]


Output: 0
Explanation: There is no path that walks over every empty square exactly once.
Note that the starting and ending square can be anywhere in the grid.

Constraints:

m == grid.length
n == grid[i].length
1 <= m, n <= 20
1 <= m * n <= 20
-1 <= grid[i][j] <= 2
There is exactly one starting cell and one ending cell.
****************

197. Unique Paths III(C++)


****************

1 // Time: O(m * n * 2^(m * n))


2 // Space: O(m * n * 2^(m * n))
3
4 class Solution {
5 private:
6 template
7 struct PairHash {
8 size_t operator()(const pair& p) const {
9 size_t seed = 0;
10 seed ^= std::hash{}(p.first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
11 seed ^= std::hash{}(p.second) + 0x9e3779b9 + (seed<<6) + (seed>>2);
12 return seed;
13 }
14 };
15 using Lookup = unordered_map, int, PairHash>;
16
17 public:
18 int uniquePathsIII(vector>& grid) {
19 int todo = 0;
20 pair src, dst;
21 for (int r = 0; r < grid.size(); ++r) {
22 for (int c = 0; c < grid[0].size(); ++c) {
23 if (grid[r][c] % 2 == 0) {
24 todo |= index(grid, r, c);
25 }
26 if (grid[r][c] == 1) {
27 src = make_pair(r, c);
28 } else if (grid[r][c] == 2) {
29 dst = make_pair(r, c);
30 }
31 }
32 }
33 Lookup lookup;
34 return dp(grid, src, dst, todo, &lookup);
35 }
36
37 private:
38 int dp(const vector>& grid,
39 const pair& src,
40 const pair& dst,
41 int todo,
42 Lookup *lookup) {
43 if (src == dst) {
44 return (todo == 0);
45 }
46 const auto& key = make_pair(index(grid, src.first, src.second), todo);
47 if (lookup->count(key)) {
48 return (*lookup)[key];
49 }
50
51 static const vector> directions =
52 {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
53 int result = 0;
54 for (const auto& d : directions) {
55 int r = src.first + d.first, c = src.second + d.second;
56 if (0 <= r && r < grid.size() &&
57 0 <= c && c < grid[0].size() &&
58 grid[r][c] % 2 == 0 &&
59 todo & index(grid, r, c)) {
60
61 result += dp(grid, make_pair(r, c), dst,
62 todo ^ index(grid, r, c), lookup);
63 }
64 }
65
66 (*lookup)[key] = result;
67 return (*lookup)[key];
68 }
69
70 int index(const vector>& grid, int r, int c) {
71 return 1 << (r * grid[0].size() + c);
72 }
73 };
****************

197. Unique Paths III(Python)


****************

1 # Time: O(m * n * 2^(m * n))


2 # Space: O(m * n * 2^(m * n))
3
4 class Solution(object):
5 def uniquePathsIII(self, grid):
6 """
7 :type grid: List[List[int]]
8 :rtype: int
9 """
10 directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
11
12 def index(grid, r, c):
13 return 1 << (r*len(grid[0])+c)
14
15 def dp(grid, src, dst, todo, lookup):
16 if src == dst:
17 return int(todo == 0)
18 key = (src, todo)
19 if key in lookup:
20 return lookup[key]
21
22 result = 0
23 for d in directions:
24 r, c = src[0]+d[0], src[1]+d[1]
25 if 0 <= r < len(grid) and 0 <= c < len(grid[0]) and \
26 grid[r][c] % 2 == 0 and \
27 todo & index(grid, r, c):
28 result += dp(grid, (r, c), dst, todo ^ index(grid, r, c), lookup)
29
30 lookup[key] = result
31 return lookup[key]
32
33 todo = 0
34 src, dst = None, None
35 for r, row in enumerate(grid):
36 for c, val in enumerate(row):
37 if val % 2 == 0:
38 todo |= index(grid, r, c)
39 if val == 1:
40 src = (r, c)
41 elif val == 2:
42 dst = (r, c)
43 return dp(grid, src, dst, todo, {})
**************************************

198. Triples with Bitwise AND Equal To Zero


**************************************

Given an integer array nums, return the number of AND triples.

An AND triple is a triple of indices (i, j, k) such that:

0 <= i < nums.length


0 <= j < nums.length
0 <= k < nums.length
nums[i] & nums[j] & nums[k] == 0 , where & represents the bitwise-AND operator.

Example 1:

Input: nums = [2,1,3]


Output: 12
Explanation: We could choose the following i, j, k triples:
(i=0, j=0, k=1) : 2 & 2 & 1
(i=0, j=1, k=0) : 2 & 1 & 2
(i=0, j=1, k=1) : 2 & 1 & 1
(i=0, j=1, k=2) : 2 & 1 & 3
(i=0, j=2, k=1) : 2 & 3 & 1
(i=1, j=0, k=0) : 1 & 2 & 2
(i=1, j=0, k=1) : 1 & 2 & 1
(i=1, j=0, k=2) : 1 & 2 & 3
(i=1, j=1, k=0) : 1 & 1 & 2
(i=1, j=2, k=0) : 1 & 3 & 2
(i=2, j=0, k=1) : 3 & 2 & 1
(i=2, j=1, k=0) : 3 & 1 & 2

Example 2:

Input: nums = [0,0,0]


Output: 27

Constraints:

1 <= nums.length <= 1000


0 <= nums[i] < 2 16
**************************************

198. Triples with Bitwise AND Equal To Zero(C++)


**************************************

1 // Time: O(nlogn), n is the max of A


2 // Space: O(n)
3
4 // Reference: https://blog.csdn.net/john123741/article/details/76576925
5 // FWT solution
6 class Solution {
7 public:
8 int countTriplets(vector& A) {
9 static const int k = 3;
10 const auto max_A = *max_element(A.cbegin(), A.cend());
11 int n = 1;
12 for (; n <= max_A; n <<= 1);
13 vector B(n);
14 for (const auto& x : A) {
15 ++B[x];
16 }
17
18 FWT(&B, 1);
19 for(auto& x : B) {
20 x = pow(x, k);
21 }
22 FWT(&B, -1);
23
24 return B[0];
25 }
26
27 private:
28 void FWT(vector *A, int v) {
29 for (int d = 1; d < A->size(); d <<= 1) {
30 for (int m = d << 1, i = 0; i < A->size(); i += m) {
31 for (int j = 0; j < d ; ++j) {
32 (*A)[i + j] += (*A)[i + j + d] * v;
33 }
34 }
35 }
36 }
37 };
38
39 // Time: O(n^3), n is the length of A
40 // Space: O(n^2)
41 class Solution2 {
42 public:
43 int countTriplets(vector& A) {
44 unordered_map count;
45 for (int i = 0 ;i < A.size(); ++i) {
46 for (int j = 0; j < A.size(); ++j) {
47 ++count[A[i] & A[j]];
48 }
49 }
50 int result = 0;
51 for (int k = 0; k < A.size(); ++k) {
52 for (const auto& kvp : count) {
53 if ((A[k] & kvp.first) == 0) {
54 result += kvp.second;
55 }
56 }
57 }
58 return result;
59 }
60 };
**************************************

198. Triples with Bitwise AND Equal To Zero(Python)


**************************************

1 # Time: O(nlogn), n is the max of A


2 # Space: O(n)
3
4 import collections
5
6
7 # Reference: https://blog.csdn.net/john123741/article/details/76576925
8 # FWT solution
9 class Solution(object):
10 def countTriplets(self, A):
11 """
12 :type A: List[int]
13 :rtype: int
14 """
15 def FWT(A, v):
16 B = A[:]
17 d = 1
18 while d < len(B):
19 for i in xrange(0, len(B), d << 1):
20 for j in xrange(d):
21 B[i+j] += B[i+j+d] * v
22 d <<= 1
23 return B
24
25 k = 3
26 n, max_A = 1, max(A)
27 while n <= max_A:
28 n *= 2
29 count = collections.Counter(A)
30 B = [count[i] for i in xrange(n)]
31 C = FWT(map(lambda x : x**k, FWT(B, 1)), -1)
32 return C[0]
33
34
35 # Time: O(n^3), n is the length of A
36 # Space: O(n^2)
37 import collections
38
39
40 class Solution2(object):
41 def countTriplets(self, A):
42 """
43 :type A: List[int]
44 :rtype: int
45 """
46 count = collections.defaultdict(int)
47 for i in xrange(len(A)):
48 for j in xrange(len(A)):
49 count[A[i]&A[j]] += 1
50 result = 0
51 for k in xrange(len(A)):
52 for v in count:
53 if A[k]&v == 0:
54 result += count[v]
55 return result
***********************************

199. Subarrays with K Different Integers


***********************************

Given an integer array nums and an integer k , return the number of good subarrays of nums.

A good array is an array where the number of different integers in that array is exactlyk .

For example, [1,2,3,1,2] has 3 different integers: 1, 2, and 3.

A subarray is a contiguous part of an array.

Example 1:

Input: nums = [1,2,1,2,3], k = 2


Output: 7
Explanation: Subarrays formed with exactly 2 different integers: [1,2], [2,1], [1,2], [2,3], [1,2,1], [2,1,2], [1,2,1,2]

Example 2:

Input: nums = [1,2,1,3,4], k = 3


Output: 3
Explanation: Subarrays formed with exactly 3 different integers: [1,2,1,3], [2,1,3], [1,3,4].

Constraints:

1 <= nums.length <= 2 * 10 4


1 <= nums[i], k <= nums.length
***********************************

199. Subarrays with K Different Integers(C++)


***********************************

1 // Time: O(n)
2 // Space: O(k)
3
4 class Solution {
5 public:
6 int subarraysWithKDistinct(vector& A, int K) {
7 return atMostK(A, K) - atMostK(A, K - 1);
8 }
9
10 private:
11 int atMostK(const vector& A, int K) {
12 int result = 0, left = 0;
13 unordered_map count;
14 for (int right = 0; right < A.size(); ++right) {
15 ++count[A[right]];
16 while (count.size() > K) {
17 if (!--count[A[left]]) {
18 count.erase(A[left]);
19 }
20 ++left;
21 }
22 result += right - left + 1;
23 }
24 return result;
25 }
26 };
27
28 // Time: O(n)
29 // Space: O(k)
30 class Solution2 {
31 public:
32 int subarraysWithKDistinct(vector& A, int K) {
33 Window window1, window2;
34 int result = 0, left1 = 0, left2 = 0;
35 for (const auto& i : A) {
36 window1.add(i);
37 while (window1.size() > K) {
38 window1.remove(A[left1]);
39 ++left1;
40 }
41 window2.add(i);
42 while (window2.size() >= K) {
43 window2.remove(A[left2]);
44 ++left2;
45 }
46 result += left2 - left1;
47 }
48 return result;
49 }
50
51 private:
52 class Window {
53 public:
54 void add(int x) {
55 ++count_[x];
56 }
57
58 void remove(int x) {
59 --count_[x];
60 if (count_[x] == 0) {
61 count_.erase(x);
62 }
63 }
64
65 size_t size() const {
66 return count_.size();
67 }
68
69 private:
70 unordered_map count_;
71 };
72 };
***********************************

199. Subarrays with K Different Integers(Python)


***********************************
1 # Time: O(n)
2 # Space: O(k)
3
4 import collections
5
6
7 class Solution(object):
8 def subarraysWithKDistinct(self, A, K):
9 """
10 :type A: List[int]
11 :type K: int
12 :rtype: int
13 """
14 def atMostK(A, K):
15 count = collections.defaultdict(int)
16 result, left = 0, 0
17 for right in xrange(len(A)):
18 count[A[right]] += 1
19 while len(count) > K:
20 count[A[left]] -= 1
21 if count[A[left]] == 0:
22 count.pop(A[left])
23 left += 1
24 result += right-left+1
25 return result
26
27 return atMostK(A, K) - atMostK(A, K-1)
28
29
30 # Time: O(n)
31 # Space: O(k)
32 class Window(object):
33 def __init__(self):
34 self.__count = collections.defaultdict(int)
35
36 def add(self, x):
37 self.__count[x] += 1
38
39 def remove(self, x):
40 self.__count[x] -= 1
41 if self.__count[x] == 0:
42 self.__count.pop(x)
43
44 def size(self):
45 return len(self.__count)
46
47
48 class Solution2(object):
49 def subarraysWithKDistinct(self, A, K):
50 """
51 :type A: List[int]
52 :type K: int
53 :rtype: int
54 """
55 window1, window2 = Window(), Window()
56 result, left1, left2 = 0, 0, 0
57 for i in A:
58 window1.add(i)
59 while window1.size() > K:
60 window1.remove(A[left1])
61 left1 += 1
62 window2.add(i)
63 while window2.size() >= K:
64 window2.remove(A[left2])
65 left2 += 1
66 result += left2-left1
67 return result
*****************************************

200. Minimum Number of K Consecutive Bit Flips


*****************************************

You are given a binary array nums and an integer k .

A k-bit flip is choosing a subarray of length k from nums and simultaneously changing every 0 in the subarray to 1, and every
1 in the subarray to 0.

Return the minimum number of k-bit flips required so that there is no 0 in the array. If it is not possible, return -1.

A subarray is a contiguous part of an array.

Example 1:

Input: nums = [0,1,0], k = 1


Output: 2
Explanation: Flip nums[0], then flip nums[2].

Example 2:

Input: nums = [1,1,0], k = 2


Output: -1
Explanation: No matter how we flip subarrays of size 2, we cannot make the array become [1,1,1].

Example 3:

Input: nums = [0,0,0,1,0,1,1,0], k = 3


Output: 3
Explanation:
Flip nums[0],nums[1],nums[2]: nums becomes [1,1,1,1,0,1,1,0]
Flip nums[4],nums[5],nums[6]: nums becomes [1,1,1,1,1,0,0,0]
Flip nums[5],nums[6],nums[7]: nums becomes [1,1,1,1,1,1,1,1]

Constraints:

1 <= nums.length <= 3 * 10 4


1 <= k <= nums.length
*****************************************

200. Minimum Number of K Consecutive Bit Flips(C++)


*****************************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int minKBitFlips(vector& A, int K) {
7 int result = 0, curr = 0;
8 for (int i = 0; i < A.size(); ++i) {
9 if (i >= K) {
10 curr -= A[i - K] / 2;
11 }
12 if (curr & 1 ^ A[i] == 0) {
13 if (i + K > A.size()) {
14 return -1;
15 }
16 A[i] += 2;
17 ++curr;
18 ++result;
19 }
20 }
21 return result;
22 }
23 };
*****************************************

200. Minimum Number of K Consecutive Bit Flips(Python)


*****************************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def minKBitFlips(self, A, K):
6 """
7 :type A: List[int]
8 :type K: int
9 :rtype: int
10 """
11 result, curr = 0, 0
12 for i in xrange(len(A)):
13 if i >= K:
14 curr -= A[i-K]//2
15 if curr & 1 ^ A[i] == 0:
16 if i+K > len(A):
17 return -1
18 A[i] += 2
19 curr, result = curr+1, result+1
20 return result
**************************

201. Number of Squareful Arrays


**************************

An array is squareful if the sum of every pair of adjacent elements is aperfect square.

Given an integer array nums, return the number of permutations of nums that are squareful.

Two permutations perm1 and perm2 are different if there is some index i such that perm1[i] != perm2[i] .

Example 1:

Input: nums = [1,17,8]


Output: 2
Explanation: [1,8,17] and [17,8,1] are the valid permutations.

Example 2:

Input: nums = [2,2,2]


Output: 1

Constraints:

1 <= nums.length <= 12


0 <= nums[i] <= 10 9
**************************

201. Number of Squareful Arrays(C++)


**************************

1 // Time: O(n!)
2 // Space: O(n^2)
3
4 class Solution {
5 public:
6 int numSquarefulPerms(vector& A) {
7 unordered_map count;
8 for (const auto& a : A) {
9 ++count[a];
10 }
11 unordered_map> candidate;
12 for (const auto& i : count) {
13 for (const auto& j : count) {
14 int x = i.first, y = j.first, s = sqrt(x + y);
15 if (s * s == x + y) {
16 candidate[x].emplace(y);
17 }
18 }
19 }
20
21 int result = 0;
22 for (const auto& i : count) {
23 dfs(candidate, i.first, A.size() - 1, &count, &result);
24 }
25 return result;
26 }
27
28 private:
29 void dfs(const unordered_map>& candidate,
30 int x,
31 int left,
32 unordered_map *count,
33 int *result) {
34
35 --(*count)[x];
36 if (!left) {
37 ++(*result);
38 }
39 if (candidate.count(x)) {
40 for (const auto& y : candidate.at(x)) {
41 if ((*count)[y] > 0) {
42 dfs(candidate, y, left - 1, count, result);
43 }
44 }
45 }
46 ++(*count)[x];
47 }
48 };
**************************

201. Number of Squareful Arrays(Python)


**************************

1 # Time: O(n!)
2 # Space: O(n^2)
3
4 import collections
5
6
7 class Solution(object):
8 def numSquarefulPerms(self, A):
9 """
10 :type A: List[int]
11 :rtype: int
12 """
13 def dfs(candidate, x, left, count, result):
14 count[x] -= 1
15 if left == 0:
16 result[0] += 1
17 for y in candidate[x]:
18 if count[y]:
19 dfs(candidate, y, left-1, count, result)
20 count[x] += 1
21
22 count = collections.Counter(A)
23 candidate = {i: {j for j in count if int((i+j)**0.5) ** 2 == i+j}
24 for i in count}
25
26 result = [0]
27 for x in count:
28 dfs(candidate, x, len(A)-1, count, result)
29 return result[0]
****************************

202. Minimum Cost to Merge Stones


****************************

There are n piles of stones arranged in a row. The ith pile has stones[i] stones.

A move consists of merging exactly k consecutive piles into one pile, and the cost of this move is equal to the total number
of stones in these k piles.

Return the minimum cost to merge all piles of stones into one pile. If it is impossible, return -1.

Example 1:

Input: stones = [3,2,4,1], k = 2


Output: 20
Explanation: We start with [3, 2, 4, 1].
We merge [3, 2] for a cost of 5, and we are left with [5, 4, 1].
We merge [4, 1] for a cost of 5, and we are left with [5, 5].
We merge [5, 5] for a cost of 10, and we are left with [10].
The total cost was 20, and this is the minimum possible.

Example 2:

Input: stones = [3,2,4,1], k = 3


Output: -1
Explanation: After any merge operation, there are 2 piles left, and we can't merge anymore. So the task is impossible.

Example 3:

Input: stones = [3,5,1,2,6], k = 3


Output: 25
Explanation: We start with [3, 5, 1, 2, 6].
We merge [5, 1, 2] for a cost of 8, and we are left with [3, 8, 6].
We merge [3, 8, 6] for a cost of 17, and we are left with [17].
The total cost was 25, and this is the minimum possible.

Constraints:

n == stones.length
1 <= n <= 30
1 <= stones[i] <= 100
2 <= k <= 30
****************************

202. Minimum Cost to Merge Stones(C++)


****************************

1 // Time: O(n^3 / k)
2 // Space: O(n^2)
3
4 class Solution {
5 public:
6 int mergeStones(vector& stones, int K) {
7 if ((stones.size() - 1) % (K - 1)) {
8 return -1;
9 }
10 vector prefix(stones.size() + 1, 0);
11 partial_sum(cbegin(stones), cend(stones), next(begin(prefix)), plus());
12
13 vector > dp(stones.size(), vector(stones.size()));
14 for (int l = K - 1; l < stones.size(); ++l) {
15 for (int i = 0; i + l < stones.size(); ++i) {
16 dp[i][i + l] = numeric_limits::max();
17 for (int j = i; j + 1 <= i + l; j += K - 1) {
18 dp[i][i + l] = min(dp[i][i + l], dp[i][j] + dp[j + 1][i + l]);
19 }
20 if (l % (K - 1) == 0) {
21 dp[i][i + l] += prefix[i + l + 1] - prefix[i];
22 }
23 }
24 }
25 return dp[0][stones.size() - 1];
26 }
27 };
****************************

202. Minimum Cost to Merge Stones(Python)


****************************

1 # Time: O(n^3 / k)
2 # Space: O(n^2)
3
4 class Solution(object):
5 def mergeStones(self, stones, K):
6 """
7 :type stones: List[int]
8 :type K: int
9 :rtype: int
10 """
11 if (len(stones)-1) % (K-1):
12 return -1
13 prefix = [0]
14 for x in stones:
15 prefix.append(prefix[-1]+x)
16 dp = [[0]*len(stones) for _ in xrange(len(stones))]
17 for l in xrange(K-1, len(stones)):
18 for i in xrange(len(stones)-l):
19 dp[i][i+l] = min(dp[i][j]+dp[j+1][i+l] for j in xrange(i, i+l, K-1))
20 if l % (K-1) == 0:
21 dp[i][i+l] += prefix[i+l+1] - prefix[i]
22 return dp[0][len(stones)-1]
*****************

203. Grid Illumination


*****************

There is a 2D grid of size n x n where each cell of this grid has a lamp that is initially turned off.

You are given a 2D array of lamp positionslamps, where lamps[i] = [row i, col i] indicates that the lamp at grid[rowi][coli] is turned on.
Even if the same lamp is listed more than once, it is turned on.

When a lamp is turned on, it illuminates its cell and all other cells in the same row, column, or diagonal.

You are also given another 2D arrayqueries, where queries[j] = [row j, col j]. For the jth query, determine whether grid[rowj][colj] is
illuminated or not. After answering the jth query, turn off the lamp at grid[rowj][colj] and its 8 adjacent lamps if they exist. A
lamp is adjacent if its cell shares either a side or corner with grid[rowj][colj].

Return an array of integers ans, where ans[j] should be 1 if the cell in the jth query was illuminated, or 0 if the lamp was not.

Example 1:

Input: n = 5, lamps = [[0,0],[4,4]], queries = [[1,1],[1,0]]


Output: [1,0]
Explanation: We have the initial grid with all lamps turned off. In the above picture we see the grid after turning on the lamp at grid[0][0]
The 0th query asks if the lamp at grid[1][1] is illuminated or not (the blue square). It is illuminated, so set ans[0] = 1. Then, we turn off

The 1st query asks if the lamp at grid[1][0] is illuminated or not (the blue square). It is not illuminated, so set ans[1] = 0. Then, we turn

Example 2:

Input: n = 5, lamps = [[0,0],[4,4]], queries = [[1,1],[1,1]]


Output: [1,1]

Example 3:

Input: n = 5, lamps = [[0,0],[0,4]], queries = [[0,4],[0,1],[1,4]]


Output: [1,1,0]

Constraints:

1 <= n <= 10 9
0 <= lamps.length <= 20000
0 <= queries.length <= 20000
lamps[i].length == 2
0 <= row i, col i < n
queries[j].length == 2
0 <= row j, col j < n
*****************

203. Grid Illumination(C++)


*****************
1 // Time: O(l + q)
2 // Space: O(l)
3
4 class Solution {
5 public:
6 template
7 struct PairHash {
8 size_t operator()(const pair& p) const {
9 size_t seed = 0;
10 seed ^= std::hash{}(p.first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
11 seed ^= std::hash{}(p.second) + 0x9e3779b9 + (seed<<6) + (seed>>2);
12 return seed;
13 }
14 };
15
16 public:
17 vector gridIllumination(int N, vector>& lamps, vector>& queries) {
18 static const vector> directions =
19 {{0, -1}, {0, 1}, {-1, 0}, {1, 0},
20 {-1, -1}, {1, -1}, {1, -1}, {1, 1}};
21
22 unordered_set, PairHash> lookup;
23 unordered_map row;
24 unordered_map col;
25 unordered_map diag;
26 unordered_map anti;
27 for (const auto& lamp : lamps) {
28 int r, c;
29 tie(r, c) = make_pair(lamp[0], lamp[1]);
30 lookup.emplace(r, c);
31 ++row[r];
32 ++col[c];
33 ++diag[r - c];
34 ++anti[r + c];
35 }
36
37 vector result;
38 for (const auto& query : queries) {
39 int r, c;
40 tie(r, c) = make_pair(query[0], query[1]);
41 if (row[r] || col[c] ||
42 diag[r - c] || anti[r + c]) {
43 result.emplace_back(1);
44 } else {
45 result.emplace_back(0);
46 }
47 for (const auto& d : directions) {
48 int nr, nc;
49 tie(nr, nc) = make_pair(r + d.first, c + d.second);
50 if (!(0 <= nr && nr < N && 0 <= nc && nc < N &&
51 lookup.count(make_pair(nr, nc)))) {
52 continue;
53 }
54 lookup.erase(make_pair(nr, nc));
55 --row[nr];
56 --col[nc];
57 --diag[nr - nc];
58 --anti[nr + nc];
59 }
60 }
61 return result;
62 }
63 };
*****************

203. Grid Illumination(Python)


*****************

1 # Time: O(l + q)
2 # Space: O(l)
3
4 import collections
5
6
7 class Solution(object):
8 def gridIllumination(self, N, lamps, queries):
9 """
10 :type N: int
11 :type lamps: List[List[int]]
12 :type queries: List[List[int]]
13 :rtype: List[int]
14 """
15 directions = [(0, -1), (0, 1), (-1, 0), (1, 0),
16 (-1, -1), (1, -1), (1, -1), (1, 1)]
17
18 lookup = set()
19 row = collections.defaultdict(int)
20 col = collections.defaultdict(int)
21 diag = collections.defaultdict(int)
22 anti = collections.defaultdict(int)
23
24 for r, c in lamps:
25 lookup.add((r, c))
26 row[r] += 1
27 col[c] += 1
28 diag[r-c] += 1
29 anti[r+c] += 1
30
31 result = []
32 for r, c in queries:
33 if row[r] or col[c] or \
34 diag[r-c] or anti[r+c]:
35 result.append(1)
36 else:
37 result.append(0)
38 for d in directions:
39 nc, nr = r+d[0], c+d[1]
40 if not (0 <= nr < N and 0 <= nc < N and \
41 (nr, nc) in lookup):
42 continue
43 lookup.remove((nr, nc))
44 row[nr] -= 1
45 col[nc] -= 1
46 diag[nr-nc] -= 1
47 anti[nr+nc] -= 1
48 return result
****************************

204. Numbers With Repeated Digits


****************************

Given an integer n, return the number of positive integers in the range[1, n] that have at least one repeated digit.

Example 1:

Input: n = 20
Output: 1
Explanation: The only positive number (<= 20) with at least 1 repeated digit is 11.

Example 2:

Input: n = 100
Output: 10
Explanation: The positive numbers (<= 100) with atleast 1 repeated digit are 11, 22, 33, 44, 55, 66, 77, 88, 99, and 100.

Example 3:

Input: n = 1000
Output: 262

Constraints:

1 <= n <= 10 9
****************************

204. Numbers With Repeated Digits(C++)


****************************

1 // Time: O(logn)
2 // Space: O(logn)
3
4 class Solution {
5 public:
6 int numDupDigitsAtMostN(int N) {
7 const auto& digits = to_string(N + 1);
8 int result = 0;
9
10 // Given 321
11 //
12 // 1. count numbers without repeated digits:
13 // - X
14 // - XX
15 for (int i = 1; i < digits.length(); ++i) {
16 result += P(9, 1) * P(9, i - 1);
17 }
18
19 // 2. count numbers without repeated digits:
20 // - 1XX ~ 3XX
21 // - 30X ~ 32X
22 // - 320 ~ 321
23 unordered_set prefix_set;
24 for (int i = 0; i < digits.length(); ++i) {
25 for (int d = (i == 0) ? 1 : 0; d < digits[i] - '0'; ++d) {
26 if (prefix_set.count(d)) {
27 continue;
28 }
29 result += P(9 - i, digits.length() - i - 1);
30 }
31 if (prefix_set.count(digits[i] - '0')) {
32 break;
33 }
34 prefix_set.emplace(digits[i] - '0');
35 }
36 return N - result;
37 }
38
39 private:
40 int P(int m, int n) const {
41 int result = 1;
42 while (n > 0) {
43 result *= m - n + 1;
44 --n;
45 }
46 return result;
47 }
48 };
****************************

204. Numbers With Repeated Digits(Python)


****************************

1 # Time: O(logn)
2 # Space: O(logn)
3
4 class Solution(object):
5 def numDupDigitsAtMostN(self, N):
6 """
7 :type N: int
8 :rtype: int
9 """
10 def P(m, n):
11 result = 1
12 while n > 0:
13 result *= m-n+1
14 n -= 1
15 return result
16
17 digits = map(int, str(N+1))
18 result = 0
19
20 # Given 321
21 #
22 # 1. count numbers without repeated digits:
23 # - X
24 # - XX
25 for i in xrange(1, len(digits)):
26 result += P(9, 1)*P(9, i-1)
27
28 # 2. count numbers without repeated digits:
29 # - 1XX ~ 3XX
30 # - 30X ~ 32X
31 # - 320 ~ 321
32 prefix_set = set()
33 for i, x in enumerate(digits):
34 for y in xrange(1 if i == 0 else 0, x):
35 if y in prefix_set:
36 continue
37 result += P(9-i, len(digits)-i-1)
38 if x in prefix_set:
39 break
40 prefix_set.add(x)
41 return N-result
**************************************

205. Recover a Tree From Preorder Traversal


**************************************

We run a preorder depth-first search (DFS) on the root of a binary tree.

At each node in this traversal, we output D dashes (where D is the depth of this node), then we output the value of this node.
If the depth of a node is D, the depth of its immediate child is D + 1 . The depth of the root node is 0.

If a node has only one child, that child is guaranteed to bethe left child.

Given the output traversal of this traversal, recover the tree and return its root.

Example 1:

Input: traversal = "1-2--3--4-5--6--7"


Output: [1,2,5,3,4,6,7]

Example 2:

Input: traversal = "1-2--3---4-5--6---7"


Output: [1,2,5,3,null,6,null,4,null,7]

Example 3:
Input: traversal = "1-401--349---90--88"
Output: [1,401,null,349,88,90]

Constraints:

The number of nodes in the original tree is in the range[1, 1000].


1 <= Node.val <= 10 9
**************************************

205. Recover a Tree From Preorder Traversal(C++)


**************************************
1 // Time: O(n)
2 // Space: O(h)
3
4 /**
5 * Definition for a binary tree node.
6 * struct TreeNode {
7 * int val;
8 * TreeNode *left;
9 * TreeNode *right;
10 * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
11 * };
12 */
13
14 // iterative stack solution
15 class Solution {
16 public:
17 TreeNode* recoverFromPreorder(string S) {
18 int i = 0;
19 vector stack;
20 while (i < S.length()) {
21 int j = S.find_first_not_of("-", i);
22 int level = j - i;
23 i = j;
24 while (stack.size() > level) {
25 stack.pop_back();
26 }
27 j = S.find_first_of("-", i);
28 auto node = new TreeNode(stoi(S.substr(i, j - i)));
29 i = j;
30 if (!stack.empty()) {
31 if (!stack.back()->left) {
32 stack.back()->left = node;
33 } else{
34 stack.back()->right = node;
35 }
36 }
37 stack.emplace_back(node);
38 }
39 return stack.front();
40 }
41 };
42
43 // Time: O(n)
44 // Space: O(h)
45 // recursive solution
46 class Solution2 {
47 public:
48 TreeNode* recoverFromPreorder(string S) {
49 int i = 0;
50 return recoverFromPreorderHelper(S, 0, &i);
51 }
52
53 private:
54 TreeNode* recoverFromPreorderHelper(const string& S, int level, int *i) {
55 int j = S.find_first_not_of("-", *i);
56 if (level != j - *i) {
57 return nullptr;
58 }
59 *i = j;
60 j = S.find_first_of("-", *i);
61 auto node = new TreeNode(stoi(S.substr(*i, j - *i)));
62 *i = j;
63 node->left = recoverFromPreorderHelper(S, level + 1, i);
64 node->right = recoverFromPreorderHelper(S, level + 1, i);
65 return node;
66 }
67 };
**************************************

205. Recover a Tree From Preorder Traversal(Python)


**************************************
1 # Time: O(n)
2 # Space: O(h)
3
4 # Definition for a binary tree node.
5 class TreeNode(object):
6 def __init__(self, x):
7 self.val = x
8 self.left = None
9 self.right = None
10
11
12 # iterative stack solution
13 class Solution(object):
14 def recoverFromPreorder(self, S):
15 """
16 :type S: str
17 :rtype: TreeNode
18 """
19 i = 0
20 stack = []
21 while i < len(S):
22 level = 0
23 while i < len(S) and S[i] == '-':
24 level += 1
25 i += 1
26 while len(stack) > level:
27 stack.pop()
28 val = []
29 while i < len(S) and S[i] != '-':
30 val.append(S[i])
31 i += 1
32 node = TreeNode(int("".join(val)))
33 if stack:
34 if stack[-1].left is None:
35 stack[-1].left = node
36 else:
37 stack[-1].right = node
38 stack.append(node)
39 return stack[0]
40
41
42 # Time: O(n)
43 # Space: O(h)
44 # recursive solution
45 class Solution2(object):
46 def recoverFromPreorder(self, S):
47 """
48 :type S: str
49 :rtype: TreeNode
50 """
51 def recoverFromPreorderHelper(S, level, i):
52 j = i[0]
53 while j < len(S) and S[j] == '-':
54 j += 1
55 if level != j - i[0]:
56 return None
57 i[0] = j
58 while j < len(S) and S[j] != '-':
59 j += 1
60 node = TreeNode(int(S[i[0]:j]))
61 i[0] = j
62 node.left = recoverFromPreorderHelper(S, level+1, i)
63 node.right = recoverFromPreorderHelper(S, level+1, i)
64 return node
65
66 return recoverFromPreorderHelper(S, 0, [0])
********************

206. Stream of Characters


********************

Design an algorithm that accepts a stream of characters and checks if a suffix of these characters is a string of a given array
of strings words.

For example, if words = ["abc", "xyz"] and the stream added the four characters (one by one)'a', 'x', 'y', and 'z', your algorithm
should detect that the suffix "xyz" of the characters "axyz" matches "xyz" from words.

Implement the StreamChecker class:

StreamChecker(String[] words) Initializes the object with the strings arraywords .


boolean query(char letter) Accepts a new character from the stream and returns true if any non-empty suffix from the stream
forms a word that is in words.

Example 1:

Input
["StreamChecker", "query", "query", "query", "query", "query", "query", "query", "query", "query", "query", "query", "query"]
[[["cd", "f", "kl"]], ["a"], ["b"], ["c"], ["d"], ["e"], ["f"], ["g"], ["h"], ["i"], ["j"], ["k"], ["l"]]
Output
[null, false, false, false, true, false, true, false, false, false, false, false, true]

Explanation
StreamChecker streamChecker = new StreamChecker(["cd", "f", "kl"]);
streamChecker.query("a"); // return False
streamChecker.query("b"); // return False
streamChecker.query("c"); // return False
streamChecker.query("d"); // return True, because 'cd' is in the wordlist
streamChecker.query("e"); // return False
streamChecker.query("f"); // return True, because 'f' is in the wordlist
streamChecker.query("g"); // return False
streamChecker.query("h"); // return False
streamChecker.query("i"); // return False
streamChecker.query("j"); // return False
streamChecker.query("k"); // return False
streamChecker.query("l"); // return True, because 'kl' is in the wordlist

Constraints:

1 <= words.length <= 2000


1 <= words[i].length <= 2000
words[i] consists of lowercase English letters.
letter is a lowercase English letter.
At most 4 * 104 calls will be made to query.
********************

206. Stream of Characters(C++)


********************

1 // Time: ctor: O(n + p^2), n is the total size of patterns


2 // , p is the number of patterns
3 // query: O(m + z), m is the total size of query string
4 // , z is the number of all matched strings
5 // , query time would be O(m) if we don't use all the matched patterns
6 // Space: O(t + p^2), t is the total size of ac automata trie
7 // , space could be further improved by DAT (double-array trie)
8
9 // Aho–Corasick automata
10 // reference:
11 // 1. http://web.stanford.edu/class/archive/cs/cs166/cs166.1166/lectures/02/Small02.pdf
12 // 2. http://algo.pw/algo/64/python
13
14 struct AhoNode {
15 vector children;
16 AhoNode *suffix;
17 vector outputs;
18 AhoNode() :
19 children(26, nullptr),
20 suffix(nullptr) {}
21 };
22
23 class AhoTrie {
24 public:
25 AhoTrie(const vector& patterns) : root_(createACTrie(patterns)) {
26 node_ = createACSuffixAndOutputLinks(root_);
27 }
28
29 vector *step(char letter) {
30 while (node_ && !node_->children[letter - 'a']) {
31 node_ = node_->suffix;
32 }
33 node_ = node_ ? node_->children[letter - 'a'] : root_;
34 return &node_->outputs; // Time: O(z), it would be O(1) if we don't use all the matched patterns
35 }
36
37 private:
38 AhoNode *createACTrie(const vector& patterns) { // Time: O(n), Space: O(t)
39 auto root = new AhoNode();
40 for (int i = 0; i < patterns.size(); ++i) {
41 auto node = root;
42 for (const auto& c : patterns[i]) {
43 if (!node->children[c - 'a']) {
44 node->children[c - 'a'] = new AhoNode();
45 }
46 node = node->children[c - 'a'];
47 }
48 node->outputs.emplace_back(i);
49 }
50 return root;
51 }
52
53 AhoNode *createACSuffixAndOutputLinks(AhoNode *root) { // Time: O(n + p^2), Space: O(t + p^2)
54 queue q;
55 for (auto node : root->children) {
56 if (!node) {
57 continue;
58 }
59 q.emplace(node);
60 node->suffix = root;
61 }
62
63 while (!q.empty()) {
64 auto node = q.front(); q.pop();
65 for (int c = 0; c < node->children.size(); ++c) {
66 if (!node->children[c]) {
67 continue;
68 }
69 auto child = node->children[c];
70 q.emplace(child);
71 auto suffix = node->suffix;
72 while (suffix && !suffix->children[c]) {
73 suffix = suffix->suffix;
74 }
75 child->suffix = suffix ? suffix->children[c] : root;
76 copy(child->suffix->outputs.cbegin(),
77 child->suffix->outputs.cend(),
78 back_inserter(child->outputs)); // Time: O(p^2)
79 }
80 }
81
82 return root;
83 }
84
85 AhoNode * const root_;
86 AhoNode *node_;
87 };
88
89 class StreamChecker {
90 public:
91 StreamChecker(vector& words) : trie_(words) {
92 }
93
94 bool query(char letter) { // O(m) times
95 return !trie_.step(letter)->empty();
96 }
97
98 private:
99 AhoTrie trie_;
100 };
101
102 /**
103 * Your StreamChecker object will be instantiated and called as such:
104 * StreamChecker* obj = new StreamChecker(words);
105 * bool param_1 = obj->query(letter);
106 */
********************

206. Stream of Characters(Python)


********************

1 # Time: ctor: O(n + p^2), n is the total size of patterns


2 # , p is the number of patterns
3 # query: O(m + z), m is the total size of query string
4 # , z is the number of all matched strings
5 # , query time would be O(m) if we don't use all the matched patterns
6 # Space: O(t + p^2), t is the total size of ac automata trie
7 # , space could be further improved by DAT (double-array trie)
8
9 # Aho–Corasick automata
10 # reference:
11 # - http://web.stanford.edu/class/archive/cs/cs166/cs166.1166/lectures/02/Small02.pdf
12 # - http://algo.pw/algo/64/python
13
14 import collections
15
16
17 class AhoNode(object):
18 def __init__(self):
19 self.children = collections.defaultdict(AhoNode)
20 self.suffix = None
21 self.outputs = []
22
23
24 class AhoTrie(object):
25
26 def step(self, letter):
27 while self.__node and letter not in self.__node.children:
28 self.__node = self.__node.suffix
29 self.__node = self.__node.children[letter] if self.__node else self.__root
30 return self.__node.outputs # Time: O(z), it would be O(m) if we don't use all the matched patterns
31
32 def __init__(self, patterns):
33 self.__root = self.__create_ac_trie(patterns)
34 self.__node = self.__create_ac_suffix_and_output_links(self.__root)
35
36 def __create_ac_trie(self, patterns): # Time: O(n), Space: O(t)
37 root = AhoNode()
38 for i, pattern in enumerate(patterns):
39 node = root
40 for c in pattern:
41 node = node.children[c]
42 node.outputs.append(i)
43 return root
44
45 def __create_ac_suffix_and_output_links(self, root): # Time: O(n + p^2), Space: O(t + p^2)
46 queue = collections.deque()
47 for node in root.children.itervalues():
48 queue.append(node)
49 node.suffix = root
50
51 while queue:
52 node = queue.popleft()
53 for c, child in node.children.iteritems():
54 queue.append(child)
55 suffix = node.suffix
56 while suffix and c not in suffix.children:
57 suffix = suffix.suffix
58 child.suffix = suffix.children[c] if suffix else root
59 child.outputs += child.suffix.outputs # Time: O(p^2)
60
61 return root
62
63
64 class StreamChecker(object):
65
66 def __init__(self, words):
67 """
68 :type words: List[str]
69 """
70 self.__trie = AhoTrie(words)
71
72 def query(self, letter): # O(m) times
73 """
74 :type letter: str
75 :rtype: bool
76 """
77 return len(self.__trie.step(letter)) > 0
78
79
80 # Your StreamChecker object will be instantiated and called as such:
81 # obj = StreamChecker(words)
82 # param_1 = obj.query(letter)
*******************

207. Escape a Large Maze


*******************

There is a 1 million by 1 million grid on an XY-plane, and the coordinates of each grid square are(x, y).

We start at the source = [s x, s y] square and want to reach the target = [t x, t y] square. There is also an array of blocked squares,
where each blocked[i] = [x i, y i] represents a blocked square with coordinates (xi, y i).

Each move, we can walk one square north, east, south, or west if the square isnot in the array of blocked squares. We are
also not allowed to walk outside of the grid.

Return true if and only if it is possible to reach thetarget square from the source square through a sequence of valid moves.

Example 1:

Input: blocked = [[0,1],[1,0]], source = [0,0], target = [0,2]


Output: false
Explanation: The target square is inaccessible starting from the source square because we cannot move.
We cannot move north or east because those squares are blocked.
We cannot move south or west because we cannot go outside of the grid.

Example 2:

Input: blocked = [], source = [0,0], target = [999999,999999]


Output: true
Explanation: Because there are no blocked cells, it is possible to reach the target square.

Constraints:

0 <= blocked.length <= 200


blocked[i].length == 2
0 <= x i, y i < 10 6
source.length == target.length == 2
0 <= s x, s y, t x, t y < 10 6
source != target
It is guaranteed that source and target are not blocked.
*******************

207. Escape a Large Maze(C++)


*******************
1 // Time: O(n^2), n is the number of blocked
2 // Space: O(n)
3
4 class Solution {
5 public:
6 template
7 struct PairHash {
8 size_t operator()(const pair& p) const {
9 size_t seed = 0;
10 seed ^= std::hash{}(p.first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
11 seed ^= std::hash{}(p.second) + 0x9e3779b9 + (seed<<6) + (seed>>2);
12 return seed;
13 }
14 };
15
16 bool isEscapePossible(vector>& blocked, vector& source, vector& target) {
17 unordered_set, PairHash> blocks;
18 for (const auto& block : blocked) {
19 blocks.emplace(block[0], block[1]);
20 }
21 return bfs(blocks, make_pair(source[0], source[1]), make_pair(target[0], target[1])) &&
22 bfs(blocks, make_pair(target[0], target[1]), make_pair(source[0], source[1]));
23 }
24
25 private:
26 bool bfs(const unordered_set, PairHash>& blocks,
27 const pair& source, const pair& target) {
28 static const int R = 1e6;
29 static const int C = 1e6;
30 static const vector> directions{{0, -1}, {0, 1},
31 {-1, 0}, {1, 0}};
32
33 const auto& max_area_surrounded_by_blocks = blocks.size() * (blocks.size() - 1) / 2;
34 unordered_set, PairHash> lookup{source};
35 if (lookup.size() > max_area_surrounded_by_blocks) {
36 return true;
37 }
38 queue> q({source});
39 while (!q.empty()) {
40 auto source = q.front(); q.pop();
41 if (source == target) {
42 return true;
43 }
44 for (const auto& dir : directions) {
45 const auto nr = source.first + dir.first, nc = source.second + dir.second;
46
47 if (!((0 <= nr && nr < R) &&
48 (0 <= nc && nc < C) &&
49 !lookup.count(make_pair(nr, nc)) &&
50 !blocks.count(make_pair(nr, nc)))) {
51 continue;
52 }
53 lookup.emplace(nr, nc);
54 if (lookup.size() > max_area_surrounded_by_blocks) {
55 return true;
56 }
57 q.emplace(nr, nc);
58 }
59 }
60 return false;
61 }
62 };
*******************

207. Escape a Large Maze(Python)


*******************

1 # Time: O(n^2), n is the number of blocked


2 # Space: O(n)
3
4 import collections
5
6
7 class Solution(object):
8 def isEscapePossible(self, blocked, source, target):
9 """
10 :type blocked: List[List[int]]
11 :type source: List[int]
12 :type target: List[int]
13 :rtype: bool
14 """
15 R, C = 10**6, 10**6
16 directions = [(0, -1), (0, 1), (-1, 0), (1, 0)]
17
18 def bfs(blocks, source, target):
19 max_area_surrounded_by_blocks = len(blocks)*(len(blocks)-1)//2
20 lookup = set([source])
21 if len(lookup) > max_area_surrounded_by_blocks:
22 return True
23 q = collections.deque([source])
24 while q:
25 source = q.popleft()
26 if source == target:
27 return True
28 for direction in directions:
29 nr, nc = source[0]+direction[0], source[1]+direction[1]
30 if not ((0 <= nr < R) and
31 (0 <= nc < C) and
32 (nr, nc) not in lookup and
33 (nr, nc) not in blocks):
34 continue
35 lookup.add((nr, nc))
36 if len(lookup) > max_area_surrounded_by_blocks:
37 return True
38 q.append((nr, nc))
39 return False
40
41 return bfs(set(map(tuple, blocked)), tuple(source), tuple(target)) and \
42 bfs(set(map(tuple, blocked)), tuple(target), tuple(source))
***************************

208. Longest Duplicate Substring


***************************

Given a string s , consider all duplicated substrings: (contiguous) substrings of s that occur 2 or more times. The
occurrences may overlap.

Return any duplicated substring that has the longest possible length. If s does not have a duplicated substring, the answer is
"".

Example 1:

Input: s = "banana"
Output: "ana"

Example 2:

Input: s = "abcd"
Output: ""

Constraints:

2 <= s.length <= 3 * 10 4


s consists of lowercase English letters.
***************************

208. Longest Duplicate Substring(C++)


***************************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 // 1. other solution is to apply kasai's algorithm, refer to the link below:
5 // - https://leetcode.com/problems/longest-duplicate-substring/discuss/290852/Suffix-array-clear-solution
6 // 2. the best solution is to apply ukkonen's algorithm, refer to the link below:
7 // - https://leetcode.com/problems/longest-duplicate-substring/discuss/312999/best-java-on-complexity-and-on-space-solution-suffix-tree-
8
9
10 class Solution {
11 public:
12 string longestDupSubstring(string S) {
13 auto left = 1ul, right = S.length() - 1;
14 while (left <= right) {
15 const auto mid = left + (right - left) / 2;
16 if (!check(S, mid)) {
17 right = mid - 1;
18 } else {
19 left = mid + 1;
20 }
21 }
22 return S.substr(check(S, right), right);
23 }
24
25 private:
26 uint64_t check(const string& S, uint64_t L) {
27 static const uint64_t M = 1e9 + 7;
28 static const uint64_t D = 26;
29 uint64_t p = power(D, L, M);
30 uint64_t curr = 0;
31 for (uint64_t i = 0; i < L; ++i) {
32 curr = ((D * curr) % M + S[i] - 'a') % M;
33 }
34 unordered_map> lookup;
35 lookup[curr].emplace_back(L - 1);
36 for (uint64_t i = L; i < S.length(); ++i) {
37 curr = (D * curr) % M;
38 curr = (curr + (S[i] - 'a')) % M;
39 curr = (curr + (M - ((S[i - L] - 'a') * p) % M)) % M;
40 if (lookup.count(curr)) {
41 for (const auto& j : lookup[curr]) { // check if string is the same when hash is the same
42 if (S.substr(j - L + 1, L) == S.substr(i - L + 1, L)) {
43 return i - L + 1;
44 }
45 }
46 }
47 lookup[curr].emplace_back(i);
48 }
49 return 0;
50 }
51
52 uint64_t power(uint64_t D, uint64_t L, uint64_t M) {
53 uint64_t result = 1;
54 for (uint64_t i = 0; i < L; ++i) {
55 result = (result * D) % M;
56 }
57 return result;
58 }
59 };
***************************

208. Longest Duplicate Substring(Python)


***************************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 # 1. other solution is to apply kasai's algorithm, refer to the link below:
5 # - https://leetcode.com/problems/longest-duplicate-substring/discuss/290852/Suffix-array-clear-solution
6 # 2. the best solution is to apply ukkonen's algorithm, refer to the link below:
7 # - https://leetcode.com/problems/longest-duplicate-substring/discuss/312999/best-java-on-complexity-and-on-space-solution-suffix-tree-6
8
9 import collections
10
11
12 class Solution(object):
13 def longestDupSubstring(self, S):
14 """
15 :type S: str
16 :rtype: str
17 """
18 M = 10**9+7
19 D = 26
20
21 def check(S, L):
22 p = pow(D, L, M)
23 curr = reduce(lambda x, y: (D*x+ord(y)-ord('a')) % M, S[:L], 0)
24 lookup = collections.defaultdict(list)
25 lookup[curr].append(L-1)
26 for i in xrange(L, len(S)):
27 curr = ((D*curr) % M + ord(S[i])-ord('a') -
28 ((ord(S[i-L])-ord('a'))*p) % M) % M
29 if curr in lookup:
30 for j in lookup[curr]: # check if string is the same when hash is the same
31 if S[j-L+1:j+1] == S[i-L+1:i+1]:
32 return i-L+1
33 lookup[curr].append(i)
34 return 0
35
36 left, right = 1, len(S)-1
37 while left <= right:
38 mid = left + (right-left)//2
39 if not check(S, mid):
40 right = mid-1
41 else:
42 left = mid+1
43 result = check(S, right)
44 return S[result:result + right]
*************************

209. Number of Valid Subarrays


*************************

Given an integer array nums, return the number of non-empty subarrays with the leftmost element of the subarray not larger
than other elements in the subarray.

A subarray is a contiguous part of an array.

Example 1:

Input: nums = [1,4,2,5,3]


Output: 11
Explanation: There are 11 valid subarrays: [1],[4],[2],[5],[3],[1,4],[2,5],[1,4,2],[2,5,3],[1,4,2,5],[1,4,2,5,3].

Example 2:

Input: nums = [3,2,1]


Output: 3
Explanation: The 3 valid subarrays are: [3],[2],[1].

Example 3:

Input: nums = [2,2,2]


Output: 6
Explanation: There are 6 valid subarrays: [2],[2],[2],[2,2],[2,2],[2,2,2].

Constraints:

1 <= nums.length <= 5 * 10 4


0 <= nums[i] <= 10 5
*************************

209. Number of Valid Subarrays(C++)


*************************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int validSubarrays(vector& nums) {
7 int result = 0;
8 vector s;
9 for (const auto& num : nums) {
10 while (!s.empty() && s.back() > num) {
11 s.pop_back();
12 }
13 s.emplace_back(num);
14 result += s.size();
15 }
16 return result;
17 }
18 };
*************************

209. Number of Valid Subarrays(Python)


*************************

1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 def validSubarrays(self, nums):
6 """
7 :type nums: List[int]
8 :rtype: int
9 """
10 result = 0
11 s = []
12 for num in nums:
13 while s and s[-1] > num:
14 s.pop()
15 s.append(num);
16 result += len(s)
17 return result
********************

210. Digit Count in Range


********************

Given a single-digit integer d and two integers low and high , return the number of times that d occurs as a digit in all integers in
the inclusive range [low, right] .

Example 1:

Input: d = 1, low = 1, high = 13


Output: 6
Explanation: The digit d = 1 occurs 6 times in 1, 10, 11, 12, 13.
Note that the digit d = 1 occurs twice in the number 11.

Example 2:

Input: d = 3, low = 100, high = 250


Output: 35
Explanation: The digit d = 3 occurs 35 times in 103,113,123,130,131,...,238,239,243.

Constraints:

0 <= d <= 9
1 <= low <= high <= 2 * 10 8
********************

210. Digit Count in Range(C++)


********************

1 // Time: O(logn)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int digitsCount(int d, int low, int high) {
7 return digitsCount(high, d) - digitsCount(low - 1, d);
8 }
9
10 private:
11 int digitsCount(int n, int k) {
12 int result = 0;
13 int64_t pivot = 1;
14 while (n >= pivot) {
15 result += n / (10 * pivot) * pivot +
16 min(pivot, max(n % (10 * pivot) - k * pivot + 1, 0l));
17 if (k == 0) {
18 result -= pivot;
19 }
20 pivot *= 10;
21 }
22 return result;
23 }
24 };
********************

210. Digit Count in Range(Python)


********************

1 # Time: O(logn)
2 # Space: O(1)
3
4 class Solution(object):
5 def digitsCount(self, d, low, high):
6 """
7 :type d: int
8 :type low: int
9 :type high: int
10 :rtype: int
11 """
12 def digitsCount(n, k):
13 pivot, result = 1, 0
14 while n >= pivot:
15 result += (n//(10*pivot))*pivot + \
16 min(pivot, max(n%(10*pivot) - k*pivot + 1, 0))
17 if k == 0:
18 result -= pivot
19 pivot *= 10
20 return result+1
21
22 return digitsCount(high, d) - digitsCount(low-1, d)
****************************************

211. Number of Submatrices That Sum to Target


****************************************

Given a matrix and a target, return the number of non-empty submatrices that sum totarget.

A submatrix x1, y1, x2, y2 is the set of all cells matrix[x][y] with x1 <= x <= x2 and y1 <= y <= y2 .

Two submatrices (x1, y1, x2, y2) and (x1', y1', x2', y2') are different if they have some coordinate that is different: for example, ifx1
!= x1'.

Example 1:

Input: matrix = [[0,1,0],[1,1,1],[0,1,0]], target = 0


Output: 4
Explanation: The four 1x1 submatrices that only contain 0.

Example 2:

Input: matrix = [[1,-1],[-1,1]], target = 0


Output: 5
Explanation: The two 1x2 submatrices, plus the two 2x1 submatrices, plus the 2x2 submatrix.

Example 3:

Input: matrix = [[904]], target = 0


Output: 0

Constraints:

1 <= matrix.length <= 100


1 <= matrix[0].length <= 100
-1000 <= matrix[i] <= 1000
-10^8 <= target <= 10^8
****************************************

211. Number of Submatrices That Sum to Target(C++)


****************************************

1 // Time: O(m^2*n), m is min(r, c), n is max(r, c)


2 // Space: O(n), which doesn't include transposed space
3
4 class Solution {
5 public:
6 int numSubmatrixSumTarget(vector>& matrix, int target) {
7 if (matrix.size() > matrix[0].size()) {
8 const auto& transposed = transpose(matrix);
9 return numSubmatrixSumTarget(const_cast>&>(transposed),
10 target);
11 }
12
13 for (int i = 0; i < matrix.size(); ++i) {
14 for (int j = 0; j < matrix[i].size() - 1; ++j) {
15 matrix[i][j + 1] += matrix[i][j];
16 }
17 }
18
19 int result = 0;
20 for (int i = 0; i < matrix.size(); ++i) {
21 vector prefix_sum(matrix[i].size());
22 for (int j = i; j < matrix.size(); ++j) {
23 unordered_map lookup;
24 ++lookup[0];
25 for (int k = 0; k < matrix[i].size(); ++k) {
26 prefix_sum[k] += matrix[j][k];
27 if (lookup.count(prefix_sum[k] - target)) {
28 result += lookup[prefix_sum[k] - target];
29 }
30 ++lookup[prefix_sum[k]];
31 }
32 }
33 }
34 return result;
35 }
36
37 private:
38 vector> transpose(const vector>& matrix) {
39 vector> result(matrix[0].size(),
40 vector(matrix.size()));
41 for (int i = 0; i < matrix.size(); ++i) {
42 for (int j = 0; j < matrix[i].size(); ++j) {
43 result[j][i] = matrix[i][j];
44 }
45 }
46 return result;
47 }
48 };
****************************************

211. Number of Submatrices That Sum to Target(Python)


****************************************

1 # Time: O(m^2*n), m is min(r, c), n is max(r, c)


2 # Space: O(n), which doesn't include transposed space
3
4 import collections
5
6
7 class Solution(object):
8 def numSubmatrixSumTarget(self, matrix, target):
9 """
10 :type matrix: List[List[int]]
11 :type target: int
12 :rtype: int
13 """
14 if len(matrix) > len(matrix[0]):
15 return self.numSubmatrixSumTarget(map(list, zip(*matrix)), target)
16
17 for i in xrange(len(matrix)):
18 for j in xrange(len(matrix[i])-1):
19 matrix[i][j+1] += matrix[i][j]
20
21 result = 0
22 for i in xrange(len(matrix)):
23 prefix_sum = [0]*len(matrix[i])
24 for j in xrange(i, len(matrix)):
25 lookup = collections.defaultdict(int)
26 lookup[0] = 1
27 for k in xrange(len(matrix[j])):
28 prefix_sum[k] += matrix[j][k]
29 if prefix_sum[k]-target in lookup:
30 result += lookup[prefix_sum[k]-target]
31 lookup[prefix_sum[k]] += 1
32 return result
*******************

212. Confusing Number II


*******************

A confusing number is a number that when rotated 180 degrees becomes a different number with each digit valid.

We can rotate digits of a number by 180 degrees to form new digits.

When 0, 1, 6, 8, and 9 are rotated 180 degrees, they become 0, 1, 9, 8, and 6 respectively.
When 2, 3, 4, 5, and 7 are rotated 180 degrees, they become invalid.

Note that after rotating a number, we can ignore leading zeros.

For example, after rotating 8000, we have 0008 which is considered as just 8.

Given an integer n, return the number of confusing numbers in the inclusive range [1, n].

Example 1:

Input: n = 20
Output: 6
Explanation: The confusing numbers are [6,9,10,16,18,19].
6 converts to 9.
9 converts to 6.
10 converts to 01 which is just 1.
16 converts to 91.
18 converts to 81.
19 converts to 61.

Example 2:

Input: n = 100
Output: 19
Explanation: The confusing numbers are [6,9,10,16,18,19,60,61,66,68,80,81,86,89,90,91,98,99,100].

Constraints:

1 <= n <= 10 9
*******************

212. Confusing Number II(C++)


*******************

1 // Time: O(logn)
2 // Space: O(logn)
3
4 class Solution {
5 public:
6 int confusingNumberII(int n) {
7 return totalCount(n) - validCountInLessLength(n) - validCountInFullLength(n);
8 }
9
10 private:
11 int totalCount(int n) { // count all numbers in the pattern of [01689]{1,len(n)} in the range of [1, n]
12 const auto& s = to_string(n);
13 int total = 0;
14 int p = pow(lookup.size(), s.length() - 1);
15 for (int i = 0; i <= s.length(); ++i, p /= lookup.size()) {
16 if (i == s.length()) {
17 ++total;
18 break;
19 }
20 int smaller = 0;
21 for (const auto& kvp : lookup) {
22 smaller += int(kvp.first < s[i]);
23 }
24 total += smaller * p;
25 if (!lookup.count(s[i])) {
26 break;
27 }
28 }
29 return total - 1; // exclude 0
30 }
31
32 int validCountInLessLength(int n) { // count unconfusing numbers in the pattern of [01689]{1,len(n)-1} in the range of [1, n]
33 const auto& s = to_string(n);
34 int valid = 0;
35 int total = centers.size();
36 for (int i = 1; i < s.length(); i += 2) { // count unconfusing numbers for each odd length less than s
37 if (i == 1) {
38 valid += accumulate(cbegin(centers), cend(centers), 0,
39 [](const auto& total, const auto& kvp) {
40 return total + (kvp.first != '0');
41 });
42 } else {
43 valid += total * (lookup.size() - 1);
44 total *= lookup.size();
45 }
46 }
47 total = 1;
48 for (int i = 2; i < s.length(); i += 2) { // count unconfusing numbers for each even length less than s
49 valid += total * (lookup.size() - 1);
50 total *= lookup.size();
51 }
52 return valid;
53 }
54
55 int validCountInFullLength(int n) { // count unconfusing numbers in the pattern of [01689]{len(n)} in the range of [1, n]
56 const auto& s = to_string(n);
57 const auto& half_s = s.substr(0, (s.length() + 1) / 2);
58 int total = 0;
59 const auto& choices = (s.length() % 2) ? centers : lookup;
60 int p = pow(lookup.size(), int(half_s.length()) - 2) * choices.size();
61 for (int i = 0; i < half_s.length(); ++i, p /= lookup.size()) {
62 if (i == half_s.length() - 1) {
63 for (const auto& kvp : choices) {
64 if (kvp.first == '0' && i == 0) {
65 continue;
66 }
67 total += int(kvp.first < half_s[i]);
68 }
69 if (!choices.count(half_s[i])) {
70 break;
71 }
72 string tmp(half_s);
73 for (int i = half_s.length() - 1 - (s.length() % 2); i >= 0; --i) {
74 tmp.push_back(lookup.at(half_s[i]));
75 }
76 if (stoull(tmp) <= n && n != 0) {
77 ++total;
78 }
79 break;
80 }
81 int smaller = 0;
82 for (const auto& kvp : lookup) {
83 if (kvp.first == '0' && i == 0) {
84 continue;
85 }
86 smaller += int(kvp.first < half_s[i]);
87 }
88 total += smaller * p;
89 if (!lookup.count(half_s[i])) {
90 break;
91 }
92 }
93 return total;
94 }
95
96 const unordered_map lookup = {{'0', '0'}, {'1', '1'}, {'6', '9'},
97 {'8', '8'}, {'9', '6'}};
98 const unordered_map centers = {{'0', '0'}, {'1', '1'}, {'8', '8'}};
99 };
100
101
102 // Time: O(logn)
103 // Space: O(logn)
104 class Solution2 {
105 public:
106 int confusingNumberII(int n) {
107 return f(n) - f(0); // f(0) is always 0 and could be ignored
108 }
109
110 private:
111 int f(int n) { // count confusing numbers in the range of [0, n]
112 return totalCount(n) - validCountInLessLength(n) - validCountInFullLength(n);
113 }
114
115 int totalCount(int n) { // count all numbers in the pattern of [01689]{1,len(n)} in the range of [0, n]
116 const auto& s = to_string(n);
117 int total = 0;
118 int p = pow(lookup.size(), s.length() - 1);
119 for (int i = 0; i <= s.length(); ++i, p /= lookup.size()) {
120 if (i == s.length()) {
121 ++total;
122 break;
123 }
124 int smaller = 0;
125 for (const auto& kvp : lookup) {
126 smaller += int(kvp.first < s[i]);
127 }
128 total += smaller * p;
129 if (!lookup.count(s[i])) {
130 break;
131 }
132 }
133 return total;
134 }
135
135
136 int validCountInLessLength(int n) { // count unconfusing numbers in the pattern of [01689]{1,len(n)-1} in the range of [0, n]
137 const auto& s = to_string(n);
138 int valid = 0;
139 int total = centers.size();
140 for (int i = 1; i < s.length(); i += 2) { // count unconfusing numbers for each odd length less than s
141 if (i == 1) {
142 valid += centers.size();
143 } else {
144 valid += total * (lookup.size() - 1);
145 total *= lookup.size();
146 }
147 }
148 total = 1;
149 for (int i = 2; i < s.length(); i += 2) { // count unconfusing numbers for each even length less than s
150 valid += total * (lookup.size() - 1);
151 total *= lookup.size();
152 }
153 return valid;
154 }
155
156 int validCountInFullLength(int n) { // count unconfusing numbers in the pattern of [01689]{len(n)} in the range of [0, n]
157 const auto& s = to_string(n);
158 const auto& half_s = s.substr(0, (s.length() + 1) / 2);
159 int total = 0;
160 const auto& choices = (s.length() % 2) ? centers : lookup;
161 int p = pow(lookup.size(), int(half_s.length()) - 2) * choices.size();
162 for (int i = 0; i < half_s.length(); ++i, p /= lookup.size()) {
163 if (i == half_s.length() - 1) {
164 for (const auto& kvp : choices) {
165 if (kvp.first == '0' && s.length() == 2) {
166 continue;
167 }
168 total += int(kvp.first < half_s[i]);
169 }
170 if (!choices.count(half_s[i])) {
171 break;
172 }
173 string tmp(half_s);
174 for (int i = half_s.length() - 1 - (s.length() % 2); i >= 0; --i) {
175 tmp.push_back(lookup.at(half_s[i]));
176 }
177 if (stoull(tmp) <= n) {
178 ++total;
179 }
180 break;
181 }
182 int smaller = 0;
183 for (const auto& kvp : lookup) {
184 if (kvp.first == '0' && i == 0) {
185 continue;
186 }
187 smaller += int(kvp.first < half_s[i]);
188 }
189 total += smaller * p;
190 if (!lookup.count(half_s[i])) {
191 break;
192 }
193 }
194 return total;
195 }
196
197 const unordered_map lookup = {{'0', '0'}, {'1', '1'}, {'6', '9'},
198 {'8', '8'}, {'9', '6'}};
199 const unordered_map centers = {{'0', '0'}, {'1', '1'}, {'8', '8'}};
200 };
*******************

212. Confusing Number II(Python)


*******************

1 # Time: O(logn)
2 # Space: O(logn)
3
4 class Solution(object):
5 def confusingNumberII(self, n):
6 """
7 :type n: int
8 :rtype: int
9 """
10 lookup = {"0":"0", "1":"1", "6":"9", "8":"8", "9":"6"}
11 centers = {"0":"0", "1":"1", "8":"8"}
12 def totalCount(n): # count all numbers in the pattern of [01689]{1,len(n)} in the range of [1, n]
13 s = str(n)
14 total = 0
15 p = len(lookup)**(len(s)-1)
16 for i in xrange(len(s)+1):
17 if i == len(s):
18 total += 1
19 break
20 smaller = sum(int(c < s[i]) for c in lookup.iterkeys())
21 total += smaller * p
22 if s[i] not in lookup:
23 break
24 p //= len(lookup)
25 return total-1 # exclude 0
26
27 def validCountInLessLength(n): # count unconfusing numbers in the pattern of [01689]{1,len(n)-1} in the range of [1, n]
28 s = str(n)
29 valid = 0
30 total = len(centers)
31 for i in xrange(1, len(s), 2): # count unconfusing numbers for each odd length less than s
32 if i == 1:
33 valid += len({c for c in centers.iterkeys() if c != '0'})
34 else:
35 valid += total * (len(lookup)-1)
36 total *= len(lookup)
37 total = 1
38 for i in xrange(2, len(s), 2): # count unconfusing numbers for each even length less than s
39 valid += total * (len(lookup)-1)
40 total *= len(lookup)
41 return valid
42
43 def validCountInFullLength(n): # count unconfusing numbers in the pattern of [01689]{len(n)} in the range of [1, n]
44 s = str(n)
45 half_s = s[:(len(s)+1)//2]
46 total = 0
47 choices = centers if (len(s) % 2) else lookup
48 p = int(len(lookup)**(len(half_s)-2) * len(choices))
49 for i in xrange(len(half_s)):
50 if i == len(half_s)-1:
51 total += sum(int(c < half_s[i]) for c in choices.iterkeys() if i != 0 or c != '0')
52 if half_s[i] not in choices:
53 break
54 tmp = list(half_s)+[lookup[half_s[i]] for i in reversed(xrange(len(half_s)-(len(s) % 2)))]
55 total += 0 < int("".join(tmp)) <= n
56 break
57 smaller = sum(int(c < half_s[i]) for c in lookup.iterkeys() if i != 0 or c != '0')
58 total += smaller * p
59 if half_s[i] not in lookup:
60 break
61 p //= len(lookup)
62 return total
63
64 return totalCount(n) - validCountInLessLength(n) - validCountInFullLength(n)
65
66
67 # Time: O(logn)
68 # Space: O(logn)
69 class Solution2(object):
70 def confusingNumberII(self, n):
71 """
72 :type n: int
73 :rtype: int
74 """
75 lookup = {"0":"0", "1":"1", "6":"9", "8":"8", "9":"6"}
76 centers = {"0":"0", "1":"1", "8":"8"}
77 def totalCount(n): # count all numbers in the pattern of [01689]{1,len(n)} in the range of [0, n]
78 s = str(n)
79 total = 0
80 p = len(lookup)**(len(s)-1)
81 for i in xrange(len(s)+1):
82 if i == len(s):
83 total += 1
84 break
85 smaller = sum(int(c < s[i]) for c in lookup.iterkeys())
86 total += smaller * p
87 if s[i] not in lookup:
88 break
89 p //= len(lookup)
90 return total
91
92 def validCountInLessLength(n): # count unconfusing numbers in the pattern of [01689]{1,len(n)-1} in the range of [0, n]
93 s = str(n)
94 valid = 0
95 total = len(centers)
96 for i in xrange(1, len(s), 2): # count unconfusing numbers for each odd length less than s
97 if i == 1:
98 valid += len(centers)
99 else:
100 valid += total * (len(lookup)-1)
101 total *= len(lookup)
102 total = 1
103 for i in xrange(2, len(s), 2): # count unconfusing numbers for each even length less than s
104 valid += total * (len(lookup)-1)
105 total *= len(lookup)
106 return valid
107
108 def validCountInFullLength(n): # count unconfusing numbers in the pattern of [01689]{len(n)} in the range of [0, n]
109 s = str(n)
110 half_s = s[:(len(s)+1)//2]
111 total = 0
112 choices = centers if (len(s) % 2) else lookup
113 p = int(len(lookup)**(len(half_s)-2) * len(choices))
114 for i in xrange(len(half_s)):
115 if i == len(half_s)-1:
116 total += sum(int(c < half_s[i]) for c in choices.iterkeys() if len(s) != 2 or c != '0')
117 if half_s[i] not in choices:
118 break
119 tmp = list(half_s)+[lookup[half_s[i]] for i in reversed(xrange(len(half_s)-(len(s) % 2)))]
120 total += int("".join(tmp)) <= n
121 break
122 smaller = sum(int(c < half_s[i]) for c in lookup.iterkeys() if i != 0 or c != '0')
123 total += smaller * p
124 if half_s[i] not in lookup:
125 break
126 p //= len(lookup)
127 return total
128
129 def f(n): # count confusing numbers in the range of [0, n]
130 return totalCount(n) - validCountInLessLength(n) - validCountInFullLength(n)
131
132 return f(n) - f(0) # f(0) is always 0 and could be ignored
*****************************

213. Shortest Common Supersequence


*****************************

Given two strings str1 and str2, return the shortest string that has both str1 and str2 as subsequences. If there are multiple
valid strings, return any of them.

A string s is a subsequence of string t if deleting some number of characters from t (possibly 0) results in the string s .

Example 1:

Input: str1 = "abac", str2 = "cab"


Output: "cabac"
Explanation:
str1 = "abac" is a subsequence of "cabac" because we can delete the first "c".
str2 = "cab" is a subsequence of "cabac" because we can delete the last "ac".
The answer provided is the shortest such string that satisfies these properties.

Example 2:

Input: str1 = "aaaaaaaa", str2 = "aaaaaaaa"


Output: "aaaaaaaa"

Constraints:

1 <= str1.length, str2.length <= 1000


str1 and str2 consist of lowercase English letters.
*****************************

213. Shortest Common Supersequence(C++)


*****************************

1 // Time: O(m * n)
2 // Space: O(m * n)
3
4 class Solution {
5 public:
6 string shortestCommonSupersequence(string str1, string str2) {
7 vector> dp(2, vector(str2.size() + 1));
8 vector>> bt(str1.size() + 1,
9 vector>(str2.size() + 1));
10 for (int i = 0; i < str1.length(); ++i) {
11 bt[i + 1][0] = {i, 0, str1[i]};
12 }
13 for (int j = 0; j < str2.length(); ++j) {
14 bt[0][j + 1] = {0, j, str2[j]};
15 }
16 for (int i = 0; i < str1.length(); ++i) {
17 for (int j = 0; j < str2.length(); ++j) {
18 if (dp[i % 2][j + 1] > dp[(i + 1) % 2][j]) {
19 dp[(i + 1) % 2][j + 1] = dp[i % 2][j + 1];
20 bt[i + 1][j + 1] = {i, j + 1, str1[i]};
21 } else {
22 dp[(i + 1) % 2][j + 1] = dp[(i + 1) % 2][j];
23 bt[i + 1][j + 1] = {i + 1, j, str2[j]};
24 }
25 if (str1[i] != str2[j]) {
26 continue;
27 }
28 if (dp[i % 2][j] + 1 > dp[(i + 1) % 2][j + 1]) {
29 dp[(i + 1) % 2][j + 1] = dp[i % 2][j] + 1;
30 bt[i + 1][j + 1] = {i, j, str1[i]};
31 }
32 }
33 }
34
35 int i = str1.length(), j = str2.length();
36 char c = 0;
37 string result;
38 while (i != 0 || j != 0) {
39 tie(i, j, c) = bt[i][j];
40 result.push_back(c);
41 }
42 reverse(result.begin(), result.end());
43 return result;
44 }
45 };
*****************************

213. Shortest Common Supersequence(Python)


*****************************

1 # Time: O(m * n)
2 # Space: O(m * n)
3
4 class Solution(object):
5 def shortestCommonSupersequence(self, str1, str2):
6 """
7 :type str1: str
8 :type str2: str
9 :rtype: str
10 """
11 dp = [[0 for _ in xrange(len(str2)+1)] for _ in xrange(2)]
12 bt = [[None for _ in xrange(len(str2)+1)] for _ in xrange(len(str1)+1)]
13 for i, c in enumerate(str1):
14 bt[i+1][0] = (i, 0, c)
15 for j, c in enumerate(str2):
16 bt[0][j+1] = (0, j, c)
17 for i in xrange(len(str1)):
18 for j in xrange(len(str2)):
19 if dp[i % 2][j+1] > dp[(i+1) % 2][j]:
20 dp[(i+1) % 2][j+1] = dp[i % 2][j+1]
21 bt[i+1][j+1] = (i, j+1, str1[i])
22 else:
23 dp[(i+1) % 2][j+1] = dp[(i+1) % 2][j]
24 bt[i+1][j+1] = (i+1, j, str2[j])
25 if str1[i] != str2[j]:
26 continue
27 if dp[i % 2][j]+1 > dp[(i+1) % 2][j+1]:
28 dp[(i+1) % 2][j+1] = dp[i % 2][j]+1
29 bt[i+1][j+1] = (i, j, str1[i])
30
31 i, j = len(str1), len(str2)
32 result = []
33 while i != 0 or j != 0:
34 i, j, c = bt[i][j]
35 result.append(c)
36 result.reverse()
37 return "".join(result)
**********************

214. Find in Mountain Array


**********************

(This problem is an interactive problem.)

You may recall that an array A is a mountain array if and only if:

A.length >= 3
There exists some i with 0 < i < A.length - 1 such that:
A[0] < A[1] < ... A[i-1] < A[i]
A[i] > A[i+1] > ... > A[A.length - 1]

Given a mountain array mountainArr, return the minimum index such that mountainArr.get(index) == target. If such an index doesn't
exist, return -1.

You can't access the mountain array directly. You may only access the array using aMountainArray interface:

MountainArray.get(k) returns the element of the array at indexk (0-indexed).


MountainArray.length() returns the length of the array.

Submissions making more than 100 calls to MountainArray.get will be judged Wrong Answer. Also, any solutions that attempt to
circumvent the judge will result in disqualification.

Example 1:

Input: array = [1,2,3,4,5,3,1], target = 3


Output: 2
Explanation: 3 exists in the array, at index=2 and index=5. Return the minimum index, which is 2.

Example 2:

Input: array = [0,1,2,4,2,1], target = 3


Output: -1
Explanation: 3 does not exist in the array, so we return -1.

Constraints:

3 <= mountain_arr.length() <= 10000


0 <= target <= 10^9
0 <= mountain_arr.get(index) <= 10^9
**********************

214. Find in Mountain Array(C++)


**********************

1 // Time: O(logn)
2 // Space: O(1)
3
4 /**
5 * // This is the MountainArray's API interface.
6 * // You should not implement it, or speculate about its implementation
7 * class MountainArray {
8 * public:
9 * int get(int index);
10 * int length();
11 * };
12 */
13 class Solution {
14 public:
15 int findInMountainArray(int target, MountainArray &mountainArr) {
16 int peak = binarySearch(mountainArr, 0, mountainArr.length()-1,
17 [&](int x) { return mountainArr.get(x) >= mountainArr.get(x + 1); });
18 int left = binarySearch(mountainArr, 0, peak,
19 [&](int x) { return mountainArr.get(x) >= target; });
20 if (left <= peak && mountainArr.get(left) == target) {
21 return left;
22 }
23 int right = binarySearch(mountainArr, peak, mountainArr.length() - 1,
24 [&](int x) { return mountainArr.get(x) <= target; });
25 if (right <= mountainArr.length() - 1 && mountainArr.get(right) == target) {
26 return right;
27 }
28 return -1;
29 }
30
31 private:
32 int binarySearch(MountainArray &A, int left, int right,
33 const function& check) {
34 while (left <= right) {
35 const auto& mid = left + (right - left) / 2;
36 if (check(mid)) {
37 right = mid - 1;
38 } else {
39 left = mid + 1;
40 }
41 }
42 return left;
43 }
44 };
**********************

214. Find in Mountain Array(Python)


**********************

1 # Time: O(logn)
2 # Space: O(1)
3
4 # """
5 # This is MountainArray's API interface.
6 # You should not implement it, or speculate about its implementation
7 # """
8 class MountainArray(object):
9 def get(self, index):
10 """
11 :type index: int
12 :rtype int
13 """
14 pass
15
16 def length(self):
17 """
18 :rtype int
19 """
20 pass
21
22
23 class Solution(object):
24 def findInMountainArray(self, target, mountain_arr):
25 """
26 :type target: integer
27 :type mountain_arr: MountainArray
28 :rtype: integer
29 """
30 def binarySearch(A, left, right, check):
31 while left <= right:
32 mid = left + (right-left)//2
33 if check(mid):
34 right = mid-1
35 else:
36 left = mid+1
37 return left
38
39 peak = binarySearch(mountain_arr, 0, mountain_arr.length()-1,
40 lambda x: mountain_arr.get(x) >= mountain_arr.get(x+1))
41 left = binarySearch(mountain_arr, 0, peak,
42 lambda x: mountain_arr.get(x) >= target)
43 if left <= peak and mountain_arr.get(left) == target:
44 return left
45 right = binarySearch(mountain_arr, peak, mountain_arr.length()-1,
46 lambda x: mountain_arr.get(x) <= target)
47 if right <= mountain_arr.length()-1 and mountain_arr.get(right) == target:
48 return right
49 return -1
******************

215. Brace Expansion II


******************

Under the grammar given below, strings can represent a set of lowercase words. Let's useR(expr) to denote the set of words
the expression represents.

Grammar can best be understood through simple examples:

Single letters represent a singleton set containing that word.


R("a") = {"a"}
R("w") = {"w"}
When we take a comma-delimited list of two or more expressions, we take the union of possibilities.
R("{a,b,c}") = {"a","b","c"}
R("{{a,b},{b,c}}") = {"a","b","c"} (notice the final set only contains each word at most once)
When we concatenate two expressions, we take the set of possible concatenations between two words where the first
word comes from the first expression and the second word comes from the second expression.
R("{a,b}{c,d}") = {"ac","ad","bc","bd"}
R("a{b,c}{d,e}f{g,h}") = {"abdfg", "abdfh", "abefg", "abefh", "acdfg", "acdfh", "acefg", "acefh"}

Formally, the three rules for our grammar:

For every lowercase letter x , we have R(x) = {x} .


For expressions e1, e 2, ... , e k with k >= 2 , we have R({e1, e 2, ...}) = R(e 1) ∪ R(e2) ∪ ...
For expressions e1 and e2, we have R(e1 + e 2) = {a + b for (a, b) in R(e 1) × R(e 2)}, where + denotes concatenation, and ×
denotes the cartesian product.

Given an expression representing a set of words under the given grammar, returnthe sorted list of words that the
expression represents.

Example 1:

Input: expression = "{a,b}{c,{d,e}}"


Output: ["ac","ad","ae","bc","bd","be"]

Example 2:

Input: expression = "{{a,z},a{b,c},{ab,z}}"


Output: ["a","ab","ac","z"]
Explanation: Each distinct word is written only once in the final answer.

Constraints:

1 <= expression.length <= 60


expression[i] consists of '{', '}', ',' or lowercase English letters.
The given expression represents a set of words based on the grammar given in the description.
******************

215. Brace Expansion II(C++)


******************

1 // Time: O(p*l * log(p*l)), p is the production of all number of options


2 // , l is the length of a word
3 // Space: O(p*l)
4
5 class Solution {
6 public:
7 vector braceExpansionII(string expression) {
8 int i = 0;
9 return generateWords(expression, &i);
10 }
11
12 private:
13 vector generateWords(const string& expr, int *i) {
14 vector> options;
15 while (*i != expr.length() &&
16 string(",}").find(expr[*i]) == string::npos) {
17 vector tmp;
18 if (string("{,}").find(expr[*i]) == string::npos) {
19 tmp.emplace_back(string(1, expr[*i]));
20 ++(*i); // a-z
21 } else if (expr[*i] == '{') {
22 tmp = generateOption(expr, i);
23 }
24 options.emplace_back(move(tmp));
25 }
26 return formWords(options);
27 }
28
29 vector generateOption(const string& expr, int *i) {
30 set option_set;
31 while (*i != expr.length() && expr[*i] != '}') {
32 ++(*i); // { or ,
33 for (const auto& option : generateWords(expr, i)) {
34 option_set.emplace(option);
35 }
36 }
37 ++(*i); // }
38 return vector(option_set.cbegin(), option_set.cend());
39 }
40
41 vector formWords(const vector>& options) {
42 set words_set;
43 int total = 1;
44 for (const auto& opt : options) {
45 total *= opt.size();
46 }
47 for (int i = 0; i < total; ++i) {
48 vector tmp;
49 int curr = i;
50 for (int j = options.size() - 1; j >= 0; --j) {
51 tmp.emplace_back(options[j][curr % options[j].size()]);
52 curr /= options[j].size();
53 }
54 reverse(tmp.begin(), tmp.end());
55 words_set.emplace(accumulate(tmp.cbegin(), tmp.cend(), string()));
56 }
57 return vector(words_set.cbegin(), words_set.cend());
58 }
59 };
******************

215. Brace Expansion II(Python)


******************

1 # Time: O(p*l * log(p*l)), p is the production of all number of options


2 # , l is the length of a word
3 # Space: O(p*l)
4
5 import itertools
6
7
8 class Solution(object):
9 def braceExpansionII(self, expression):
10 """
11 :type expression: str
12 :rtype: List[str]
13 """
14 def form_words(options):
15 words = map("".join, itertools.product(*options))
16 words.sort()
17 return words
18
19 def generate_option(expr, i):
20 option_set = set()
21 while i[0] != len(expr) and expr[i[0]] != "}":
22 i[0] += 1 # { or ,
23 for option in generate_words(expr, i):
24 option_set.add(option)
25 i[0] += 1 # }
26 option = list(option_set)
27 option.sort()
28 return option
29
30 def generate_words(expr, i):
31 options = []
32 while i[0] != len(expr) and expr[i[0]] not in ",}":
33 tmp = []
34 if expr[i[0]] not in "{,}":
35 tmp.append(expr[i[0]])
36 i[0] += 1 # a-z
37 elif expr[i[0]] == "{":
38 tmp = generate_option(expr, i)
39 options.append(tmp)
40 return form_words(options)
41
42 return generate_words(expression, [0])
43
44
45 class Solution2(object):
46 def braceExpansionII(self, expression):
47 """
48 :type expression: str
49 :rtype: List[str]
50 """
51 def form_words(options):
52 words = []
53 total = 1
54 for opt in options:
55 total *= len(opt)
56 for i in xrange(total):
57 tmp = []
58 for opt in reversed(options):
59 i, c = divmod(i, len(opt))
60 tmp.append(opt[c])
61 tmp.reverse()
62 words.append("".join(tmp))
63 words.sort()
64 return words
65
66 def generate_option(expr, i):
67 option_set = set()
68 while i[0] != len(expr) and expr[i[0]] != "}":
69 i[0] += 1 # { or ,
70 for option in generate_words(expr, i):
71 option_set.add(option)
72 i[0] += 1 # }
73 option = list(option_set)
74 option.sort()
75 return option
76
77 def generate_words(expr, i):
78 options = []
79 while i[0] != len(expr) and expr[i[0]] not in ",}":
80 tmp = []
81 if expr[i[0]] not in "{,}":
82 tmp.append(expr[i[0]])
83 i[0] += 1 # a-z
84 elif expr[i[0]] == "{":
85 tmp = generate_option(expr, i)
86 options.append(tmp)
87 return form_words(options)
88
89 return generate_words(expression, [0])
********************

216. Game Play Analysis V


********************

Table: Activity

+--------------+---------+
| Column Name | Type |
+--------------+---------+
| player_id | int |
| device_id | int |
| event_date | date |
| games_played | int |
+--------------+---------+
(player_id, event_date) is the primary key of this table.
This table shows the activity of players of some game.
Each row is a record of a player who logged in and played a number of games (possibly 0) before logging out on some day using some device.

We define the install date of a player to be the first login day of that player.

We also define day 1 retention of some date X to be the number of players whose install date is X and they logged back in
on the day right after X, divided by the number of players whose install date isX, rounded to 2 decimal places.

Write an SQL query that reports for each install date, the number of players that installed the game on that day and the
day 1 retention.

The query result format is in the following example:

Activity table:
+-----------+-----------+------------+--------------+
| player_id | device_id | event_date | games_played |
+-----------+-----------+------------+--------------+
| 1 | 2 | 2016-03-01 | 5 |
| 1 | 2 | 2016-03-02 | 6 |
| 2 | 3 | 2017-06-25 | 1 |
| 3 | 1 | 2016-03-01 | 0 |
| 3 | 4 | 2016-07-03 | 5 |
+-----------+-----------+------------+--------------+

Result table:
+------------+----------+----------------+
| install_dt | installs | Day1_retention |
+------------+----------+----------------+
| 2016-03-01 | 2 | 0.50 |
| 2017-06-25 | 1 | 0.00 |
+------------+----------+----------------+
Player 1 and 3 installed the game on 2016-03-01 but only player 1 logged back in on 2016-03-02 so the day 1 retention of 2016-03-01 is 1 / 2
Player 2 installed the game on 2017-06-25 but didn't log back in on 2017-06-26 so the day 1 retention of 2017-06-25 is 0 / 1 = 0.00
********************

216. Game Play Analysis V(Shell)


********************

1 # Time: O(n^2)
2 # Space: O(n)
3
4 SELECT install_dt,
5 Count(player_id) AS installs,
6 Round(Count(next_day) / Count(player_id), 2) AS Day1_retention
7 FROM (SELECT a.player_id,
8 a.install_dt,
9 b.event_date AS next_day
10 FROM (SELECT player_id,
11 Min(event_date) AS install_dt
12 FROM activity
13 GROUP BY player_id) AS a
14 LEFT JOIN activity AS b
15 ON Datediff(b.event_date, a.install_dt) = 1
16 AND a.player_id = b.player_id ) AS t
17 GROUP BY install_dt;
****************************

217. Parsing A Boolean Expression


****************************

Return the result of evaluating a given boolean expression, represented as a string.

An expression can either be:

"t", evaluating to True;


"f", evaluating to False;
"!(expr)", evaluating to the logical NOT of the inner expressionexpr;
"&(expr1,expr2,...)", evaluating to the logical AND of 2 or more inner expressionsexpr1, expr2, ... ;
"|(expr1,expr2,...)", evaluating to the logical OR of 2 or more inner expressionsexpr1, expr2, ...

Example 1:

Input: expression = "!(f)"


Output: true

Example 2:

Input: expression = "|(f,t)"


Output: true

Example 3:

Input: expression = "&(t,f)"


Output: false

Example 4:

Input: expression = "|(&(t,f,t),!(t))"


Output: false

Constraints:

1 <= expression.length <= 20000


expression[i] consists of characters in {'(', ')', '&', '|', '!', 't', 'f', ','} .
expression is a valid expression representing a boolean, as given in the description.
****************************

217. Parsing A Boolean Expression(C++)


****************************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 bool parseBoolExpr(string expression) {
7 int i = 0;
8 return parse(expression, &i);
9 }
10
11 private:
12 bool parse(const string& expression, int *i) {
13 static const string ops = "&|!";
14 if (ops.find(expression[*i]) == string::npos) {
15 bool result = expression[*i] == 't';
16 ++(*i);
17 return result;
18 }
19 const auto& op = expression[*i];
20 *i += 2;
21 vector stk;
22 while (expression[*i] != ')') {
23 if (expression[*i] == ',') {
24 ++(*i);
25 continue;
26 }
27 stk.emplace_back(parse(expression, i));
28 }
29 ++(*i);
30 if (op == '&') {
31 return all_of(stk.cbegin(), stk.cend(),
32 [](bool val) { return val; });
33 }
34 if (op == '|') {
35 return any_of(stk.cbegin(), stk.cend(),
36 [](bool val) { return val; });
37 }
38 return !stk[0];
39 }
40 };
****************************

217. Parsing A Boolean Expression(Python)


****************************

1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 def parseBoolExpr(self, expression):
6 """
7 :type expression: str
8 :rtype: bool
9 """
10 def parse(expression, i):
11 if expression[i[0]] not in "&|!":
12 result = expression[i[0]] == 't'
13 i[0] += 1
14 return result
15 op = expression[i[0]]
16 i[0] += 2
17 stk = []
18 while expression[i[0]] != ')':
19 if expression[i[0]] == ',':
20 i[0] += 1
21 continue
22 stk.append(parse(expression, i))
23 i[0] += 1
24 if op == '&':
25 return all(stk)
26 if op == '|':
27 return any(stk)
28 return not stk[0]
29
30 return parse(expression, [0])
************

218. Building H2O


************

There are two kinds of threads: oxygen and hydrogen. Your goal is to group these threads to form water molecules.

There is a barrier where each thread has to wait until a complete molecule can be formed. Hydrogen and oxygen threads
will be given releaseHydrogen and releaseOxygen methods respectively, which will allow them to pass the barrier. These threads
should pass the barrier in groups of three, and they must immediately bond with each other to form a water molecule. You
must guarantee that all the threads from one molecule bond before any other threads from the next molecule do.

In other words:

If an oxygen thread arrives at the barrier when no hydrogen threads are present, it must wait for two hydrogen threads.
If a hydrogen thread arrives at the barrier when no other threads are present, it must wait for an oxygen thread and
another hydrogen thread.

We do not have to worry about matching the threads up explicitly; the threads do not necessarily know which other threads
they are paired up with. The key is that threads pass the barriers in complete sets; thus, if we examine the sequence of
threads that bind and divide them into groups of three, each group should contain one oxygen and two hydrogen threads.

Write synchronization code for oxygen and hydrogen molecules that enforces these constraints.

Example 1:

Input: water = "HOH"


Output: "HHO"
Explanation: "HOH" and "OHH" are also valid answers.

Example 2:

Input: water = "OOHHHH"


Output: "HHOHHO"
Explanation: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" and "OHHOHH" are also valid answers.

Constraints:

3 * n == water.length
1 <= n <= 20
water[i] is either 'H'
or 'O'.
There will be exactly 2 * n 'H' in water.
There will be exactly n 'O' in water.
************

218. Building H2O(C++)


************

1 // Time: O(n)
2 // Space: O(1)
3
4 class H2O {
5 public:
6 H2O() {
7 }
8
9 void hydrogen(function releaseHydrogen) {
10 unique_lock l(m_);
11 releaseHydrogen_ = releaseHydrogen;
12 ++nH_;
13 output();
14 }
15
16 void oxygen(function releaseOxygen) {
17 unique_lock l(m_);
18 releaseOxygen_ = releaseOxygen;
19 ++nO_;
20 output();
21 }
22
23 private:
24 void output() {
25 while (nH_ >= 2 && nO_ >= 1) {
26 nH_ -= 2;
27 nO_ -= 1;
28 releaseHydrogen_();
29 releaseHydrogen_();
30 releaseOxygen_();
31 }
32 }
33
34 int nH_ = 0;
35 int nO_ = 0;
36 function releaseHydrogen_ = nullptr;
37 function releaseOxygen_ = nullptr;
38 mutex m_;
39 };
40
41 // Time: O(n)
42 // Space: O(1)
43 class H2O2 {
44 public:
45 H2O2() {
46 }
47
48 void hydrogen(function releaseHydrogen) {
49 {
50 unique_lock l(m_);
51 cv_.wait(l, [this]() { return (nH_ + 1) - 2 * nO_ <= 2; });
52 ++nH_;
53 // releaseHydrogen() outputs "H". Do not change or remove this line.
54 releaseHydrogen();
55 }
56 cv_.notify_all();
57 }
58
59 void oxygen(function releaseOxygen) {
60 {
61 unique_lock l(m_);
62 cv_.wait(l, [this]() { return 2 * (nO_ + 1) - nH_ <= 2; });
63 ++nO_;
64 // releaseOxygen() outputs "O". Do not change or remove this line.
65 releaseOxygen();
66 }
67 cv_.notify_all();
68 }
69
70 private:
71 int nH_ = 0;
72 int nO_ = 0;
73 mutex m_;
74 condition_variable cv_;
75 };
76
77 // Time: O(n)
78 // Space: O(1)
79 // this is much like single thread execution
80 class H2O3 {
81 public:
82 H2O3(): curr_(2) {
83 m2_.lock();
84 }
85
86 void hydrogen(function releaseHydrogen) {
87 m1_.lock();
88 // releaseHydrogen() outputs "H". Do not change or remove this line.
89 releaseHydrogen();
90 if (--curr_) {
91 m1_.unlock();
92 } else {
93 m2_.unlock();
94 }
95 }
96
97 void oxygen(function releaseOxygen) {
98 m2_.lock();
99 // releaseOxygen() outputs "O". Do not change or remove this line.
100 releaseOxygen();
101 curr_ = 2;
102 m1_.unlock();
103 }
104
105 private:
106 int curr_ = 0;
107 mutex m1_, m2_;
108 };
************

218. Building H2O(Python)


************
1 # Time: O(n)
2 # Space: O(1)
3
4 import threading
5
6
7 class H2O(object):
8 def __init__(self):
9 self.__l = threading.Lock()
10 self.__nH = 0
11 self.__nO = 0
12 self.__releaseHydrogen = None
13 self.__releaseOxygen = None
14
15 def hydrogen(self, releaseHydrogen):
16 with self.__l:
17 self.__releaseHydrogen = releaseHydrogen
18 self.__nH += 1
19 self.__output()
20
21 def oxygen(self, releaseOxygen):
22 with self.__l:
23 self.__releaseOxygen = releaseOxygen
24 self.__nO += 1
25 self.__output()
26
27 def __output(self):
28 while self.__nH >= 2 and \
29 self.__nO >= 1:
30 self.__nH -= 2
31 self.__nO -= 1
32 self.__releaseHydrogen()
33 self.__releaseHydrogen()
34 self.__releaseOxygen()
35
36
37 # Time: O(n)
38 # Space: O(1)
39 # TLE
40 class H2O2(object):
41 def __init__(self):
42 self.__nH = 0
43 self.__nO = 0
44 self.__cv = threading.Condition()
45
46 def hydrogen(self, releaseHydrogen):
47 """
48 :type releaseHydrogen: method
49 :rtype: void
50 """
51 with self.__cv:
52 while (self.__nH+1) - 2*self.__nO > 2:
53 self.__cv.wait()
54 self.__nH += 1
55 # releaseHydrogen() outputs "H". Do not change or remove this line.
56 releaseHydrogen()
57 self.__cv.notifyAll()
58
59 def oxygen(self, releaseOxygen):
60 """
61 :type releaseOxygen: method
62 :rtype: void
63 """
64 with self.__cv:
65 while 2*(self.__nO+1) - self.__nH > 2:
66 self.__cv.wait()
67 self.__nO += 1
68 # releaseOxygen() outputs "O". Do not change or remove this line.
69 releaseOxygen()
70 self.__cv.notifyAll()
**************************************

219. Divide Array Into Increasing Sequences


**************************************

Given an integer array nums sorted in non-decreasing order and an integerk , return true if this array can be divided into one or
more disjoint increasing subsequences of length at least k , or false otherwise.

Example 1:

Input: nums = [1,2,2,3,3,4,4], k = 3


Output: true
Explanation: The array can be divided into two subsequences [1,2,3,4] and [2,3,4] with lengths at least 3 each.

Example 2:

Input: nums = [5,6,6,7,8], k = 3


Output: false
Explanation: There is no way to divide the array using the conditions required.

Constraints:

1 <= k <= nums.length <= 10 5


1 <= nums[i] <= 10 5
nums is sorted in non-decreasing order.
**************************************

219. Divide Array Into Increasing Sequences(C++)


**************************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 bool canDivideIntoSubsequences(vector& nums, int K) {
7 int curr = 1, max_count = 1;
8 for (int i = 1; i < nums.size(); ++i) {
9 curr = (nums[i - 1] < nums[i]) ? 1 : curr + 1;
10 max_count = max(max_count, curr);
11 }
12 return K * max_count <= nums.size();
13 }
14 };
**************************************

219. Divide Array Into Increasing Sequences(Python)


**************************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def canDivideIntoSubsequences(self, nums, K):
6 """
7 :type nums: List[int]
8 :type K: int
9 :rtype: bool
10 """
11 curr, max_count = 1, 1
12 for i in xrange(1, len(nums)):
13 curr = 1 if nums[i-1] < nums[i] else curr+1
14 max_count = max(max_count, curr)
15 return K*max_count <= len(nums)
************************

220. Smallest Sufficient Team


************************

In a project, you have a list of required skills req_skills, and a list of people. The ith person people[i] contains a list of skills that
the person has.

Consider a sufficient team: a set of people such that for every required skill inreq_skills, there is at least one person in the
team who has that skill. We can represent these teams by the index of each person.

For example, team = [0, 1, 3] represents the people with skills people[0], people[1], and people[3].

Return any sufficient team of the smallest possible size, represented by the index of each person. You may return the
answer in any order.

It is guaranteed an answer exists.

Example 1:

Input: req_skills = ["java","nodejs","reactjs"], people = [["java"],["nodejs"],["nodejs","reactjs"]]


Output: [0,2]

Example 2:

Input: req_skills = ["algorithms","math","java","reactjs","csharp","aws"], people = [["algorithms","math","java"],["algorithms","math","react


Output: [1,2]

Constraints:

1 <= req_skills.length <= 16


1 <= req_skills[i].length <= 16
req_skills[i] consists of lowercase English letters.
All the strings of req_skills are unique.
1 <= people.length <= 60
0 <= people[i].length <= 16
1 <= people[i][j].length <= 16
people[i][j] consists of lowercase English letters.
All the strings of people[i] are unique.
Every skill in people[i] is a skill in req_skills.
It is guaranteed a sufficient team exists.
************************

220. Smallest Sufficient Team(C++)


************************

1 // Time: O(m * 2^n), n is the number of skills


2 // m is the number of people
3 // Space: O(2^n)
4
5 class Solution {
6 public:
7 vector smallestSufficientTeam(vector& req_skills, vector>& people) {
8 unordered_map lookup;
9 for (int i = 0; i < req_skills.size(); ++i) {
10 lookup[req_skills[i]] = i;
11 }
12 unordered_map> dp;
13 dp[0];
14 for (int i = 0; i < people.size(); ++ i) {
15 int his_skill_set = 0;
16 for (const auto& skill : people[i]) {
17 if (lookup.count(skill)) {
18 his_skill_set |= 1 << lookup[skill];
19 }
20 }
21 auto tmp(dp);
22 for (const auto& [skill_set, people] : tmp) {
23 const auto with_him_set = skill_set | his_skill_set;
24 if (with_him_set == skill_set) {
25 continue;
26 }
27 if (!dp.count(with_him_set) ||
28 dp[with_him_set].size() > people.size() + 1) {
29 dp[with_him_set] = move(people);
30 dp[with_him_set].emplace_back(i);
31 }
32 }
33 }
34 return dp[(1 << req_skills.size()) - 1];
35 }
36 };
************************

220. Smallest Sufficient Team(Python)


************************

1 # Time: O(m * 2^n), n is the number of skills


2 # m is the number of people
3 # Space: O(2^n)
4
5 class Solution(object):
6 def smallestSufficientTeam(self, req_skills, people):
7 """
8 :type req_skills: List[str]
9 :type people: List[List[str]]
10 :rtype: List[int]
11 """
12 lookup = {v: i for i, v in enumerate(req_skills)}
13 dp = {0: []}
14 for i, p in enumerate(people):
15 his_skill_set = 0
16 for skill in p:
17 if skill in lookup:
18 his_skill_set |= 1 << lookup[skill]
19 for skill_set, people in dp.items():
20 with_him = skill_set | his_skill_set
21 if with_him == skill_set: continue
22 if with_him not in dp or \
23 len(dp[with_him]) > len(people)+1:
24 dp[with_him] = people + [i]
25 return dp[(1<
**********************

221. User Purchase Platform


**********************

Table: Spending

+-------------+---------+
| Column Name | Type |
+-------------+---------+
| user_id | int |
| spend_date | date |
| platform | enum |
| amount | int |
+-------------+---------+
The table logs the spendings history of users that make purchases from an online shopping website which has a desktop and a mobile applicatio
(user_id, spend_date, platform) is the primary key of this table.
The platform column is an ENUM type of ('desktop', 'mobile').

Write an SQL query to find the total number of users and the total amount spent using mobileonly, desktop only and both
mobile and desktop together for each date.

The query result format is in the following example:

Spending table:
+---------+------------+----------+--------+
| user_id | spend_date | platform | amount |
+---------+------------+----------+--------+
| 1 | 2019-07-01 | mobile | 100 |
| 1 | 2019-07-01 | desktop | 100 |
| 2 | 2019-07-01 | mobile | 100 |
| 2 | 2019-07-02 | mobile | 100 |
| 3 | 2019-07-01 | desktop | 100 |
| 3 | 2019-07-02 | desktop | 100 |
+---------+------------+----------+--------+

Result table:
+------------+----------+--------------+-------------+
| spend_date | platform | total_amount | total_users |
+------------+----------+--------------+-------------+
| 2019-07-01 | desktop | 100 | 1 |
| 2019-07-01 | mobile | 100 | 1 |
| 2019-07-01 | both | 200 | 1 |
| 2019-07-02 | desktop | 100 | 1 |
| 2019-07-02 | mobile | 100 | 1 |
| 2019-07-02 | both | 0 | 0 |
+------------+----------+--------------+-------------+
On 2019-07-01, user 1 purchased using both desktop and mobile, user 2 purchased using mobile only and user 3 purchased using desktop only.
On 2019-07-02, user 2 purchased using mobile only, user 3 purchased using desktop only and no one purchased using both platforms.
**********************

221. User Purchase Platform(Shell)


**********************

1 # Time: O(n)
2 # Space: O(n)
3
4 SELECT t1.spend_date,
5 'both' AS platform,
6 Sum(Ifnull(t.sum_amount, 0)) AS total_amount,
7 Count(t.user_id) AS total_users
8 FROM (SELECT spend_date,
9 user_id,
10 Sum(amount) AS sum_amount
11 FROM spending
12 GROUP BY spend_date,
13 user_id
14 HAVING Count(platform) = 2) AS t
15 RIGHT JOIN (SELECT DISTINCT spend_date
16 FROM spending) AS t1
17 ON t.spend_date = t1.spend_date
18 GROUP BY t1.spend_date
19 UNION
20 SELECT t2.spend_date,
21 'mobile' AS platform,
22 Sum(Ifnull(t.amount, 0)) AS total_amount,
23 Count(t.user_id) AS total_users
24 FROM (SELECT spend_date,
25 user_id,
26 platform,
27 amount
28 FROM spending
29 GROUP BY spend_date,
30 user_id
31 HAVING Count(platform) < 2) AS t
32 RIGHT JOIN (SELECT DISTINCT spend_date
33 FROM spending) AS t2
34 ON t.spend_date = t2.spend_date
35 AND t.platform = 'mobile'
36 GROUP BY t2.spend_date
37 UNION
38 SELECT t3.spend_date,
39 'desktop' AS platform,
40 Sum(Ifnull(t.amount, 0)) AS total_amount,
41 Count(t.user_id) AS total_users
42 FROM (SELECT spend_date,
43 user_id,
44 platform,
45 amount
46 FROM spending
47 GROUP BY spend_date,
48 user_id
49 HAVING Count(platform) < 2) AS t
50 RIGHT JOIN (SELECT DISTINCT spend_date
51 FROM spending) AS t3
52 ON t.spend_date = t3.spend_date
53 AND t.platform = 'desktop'
54 GROUP BY t3.spend_date
****************

222. Parallel Courses


****************

You are given an integer n, which indicates that there are n courses labeled from 1 to n. You are also given an arrayrelations
where relations[i] = [prevCourse i, nextCoursei], representing a prerequisite relationship between course prevCoursei and course
nextCoursei: course prevCoursei has to be taken before course nextCoursei.

In one semester, you can take any number of courses as long as you have taken all the prerequisites in theprevious
semester for the courses you are taking.

Return the minimum number of semesters needed to take all courses. If there is no way to take all the courses, return-1.

Example 1:

Input: n = 3, relations = [[1,3],[2,3]]


Output: 2
Explanation: The figure above represents the given graph.
In the first semester, you can take courses 1 and 2.
In the second semester, you can take course 3.

Example 2:

Input: n = 3, relations = [[1,2],[2,3],[3,1]]


Output: -1
Explanation: No course can be studied because they are prerequisites of each other.

Constraints:

1 <= n <= 5000


1 <= relations.length <= 5000
relations[i].length == 2
1 <= prevCoursei, nextCourse i <= n
prevCoursei != nextCoursei
All the pairs [prevCoursei, nextCoursei] are unique.
****************

222. Parallel Courses(C++)


****************

1 // Time: O(|V| + |E|)


2 // Space: O(|E|)
3
4 class Solution {
5 public:
6 int minimumSemesters(int N, vector>& relations) {
7 unordered_map> g;
8 vector in_degree(N);
9 for (const auto& r : relations) {
10 g[r[0] - 1].emplace_back(r[1] - 1);
11 ++in_degree[r[1] - 1];
12 }
13 queue> q;
14 for (int i = 0; i < N; ++i) {
15 if (!in_degree[i]) {
16 q.emplace(1, i);
17 }
18 }
19
20 int result = 0;
21 int count = N;
22 while (!q.empty()) {
23 int level, u;
24 tie(level, u) = q.front(); q.pop();
25 --count;
26 result = level;
27 for (const auto& v : g[u]) {
28 --in_degree[v];
29 if (!in_degree[v]) {
30 q.emplace(level+1, v);
31 }
32 }
33 }
34 return count == 0 ? result : -1;
35 }
36 };
****************

222. Parallel Courses(Python)


****************

1 # Time: O(|V| + |E|)


2 # Space: O(|E|)
3
4 import collections
5
6
7 class Solution(object):
8 def minimumSemesters(self, N, relations):
9 """
10 :type N: int
11 :type relations: List[List[int]]
12 :rtype: int
13 """
14 g = collections.defaultdict(list)
15 in_degree = [0]*N
16 for x, y in relations:
17 g[x-1].append(y-1)
18 in_degree[y-1] += 1
19 q = collections.deque([(1, i) for i in xrange(N) if not in_degree[i]])
20
21 result = 0
22 count = N
23 while q:
24 level, u = q.popleft()
25 count -= 1
26 result = level
27 for v in g[u]:
28 in_degree[v] -= 1
29 if not in_degree[v]:
30 q.append((level+1, v))
31 return result if count == 0 else -1
****************************************

223. Longest Chunked Palindrome Decomposition


****************************************

You are given a string text. You should split it to k substrings(subtext1, subtext 2, ..., subtext k) such that:

subtexti is a non-empty string.


The concatenation of all the substrings is equal to text (i.e., subtext1 + subtext 2 + ... + subtext k == text ).
subtexti == subtext k - i + 1 for all valid values of i (i.e., 1 <= i <= k ).

Return the largest possible value of k .

Example 1:

Input: text = "ghiabcdefhelloadamhelloabcdefghi"


Output: 7
Explanation: We can split the string on "(ghi)(abcdef)(hello)(adam)(hello)(abcdef)(ghi)".

Example 2:

Input: text = "merchant"


Output: 1
Explanation: We can split the string on "(merchant)".

Example 3:

Input: text = "antaprezatepzapreanta"


Output: 11
Explanation: We can split the string on "(a)(nt)(a)(pre)(za)(tpe)(za)(pre)(a)(nt)(a)".

Example 4:

Input: text = "aaa"


Output: 3
Explanation: We can split the string on "(a)(a)(a)".

Constraints:

1 <= text.length <= 1000


text consists only of lowercase English characters.
****************************************

223. Longest Chunked Palindrome Decomposition(C++)


****************************************

1 // Time: O(n)
2 // Space: O(1)
3
4 // Rabin-Karp Algorithm
5 class Solution {
6 public:
7 int longestDecomposition(string text) {
8 static const uint64_t MOD = 1e9 + 7;
9 static const uint64_t D = 26;
10 int result = 0;
11 int left = 0, right = 0, l = 0;
12 uint64_t pow_D = 1;
13 for (int i = 0; i < text.length(); ++i) {
14 left = (D * left + (text[i] - 'a')) % MOD;
15 right = (pow_D * (text[text.length() - 1 - i] - 'a') + right) % MOD;
16 ++l;
17 pow_D = (pow_D * D) % MOD;
18 if (left == right &&
19 compare(text, l, i - l + 1, text.length() - 1 - i)) {
20 ++result;
21 left = 0, right = 0, l = 0, pow_D = 1;
22 }
23 }
24 return result;
25 }
26
27 private:
28 bool compare(const string& text, size_t l, int s1, int s2) {
29 for (int i = 0; i < l; ++i) {
30 if (text[s1 + i] != text[s2 + i]) {
31 return false;
32 }
33 }
34 return true;
35 }
36 };
****************************************

223. Longest Chunked Palindrome


Decomposition(Python)
****************************************

1 # Time: O(n)
2 # Space: O(1)
3
4 # Rabin-Karp Algorithm
5 class Solution(object):
6 def longestDecomposition(self, text):
7 """
8 :type text: str
9 :rtype: int
10 """
11 def compare(text, l, s1, s2):
12 for i in xrange(l):
13 if text[s1+i] != text[s2+i]:
14 return False
15 return True
16
17 MOD = 10**9+7
18 D = 26
19 result = 0
20 left, right, l, pow_D = 0, 0, 0, 1
21 for i in xrange(len(text)):
22 left = (D*left + (ord(text[i])-ord('a'))) % MOD
23 right = (pow_D*(ord(text[-1-i])-ord('a')) + right) % MOD
24 l += 1
25 pow_D = (pow_D*D) % MOD
26 if left == right and compare(text, l, i-l+1, len(text)-1-i):
27 result += 1
28 left, right, l, pow_D = 0, 0, 0, 1
29 return result
*************************************

224. String Transforms Into Another String


*************************************

Given two strings str1 and str2 of the same length, determine whether you can transformstr1 into str2 by doing zero or more
conversions.

In one conversion you can convert all occurrences of one character in str1 to any other lowercase English character.

Return true if and only if you can transform str1 into str2.

Example 1:

Input: str1 = "aabcc", str2 = "ccdee"


Output: true
Explanation: Convert 'c' to 'e' then 'b' to 'd' then 'a' to 'c'. Note that the order of conversions matter.

Example 2:

Input: str1 = "leetcode", str2 = "codeleet"


Output: false
Explanation: There is no way to transform str1 to str2.

Constraints:

1 <= str1.length == str2.length <= 10 4


str1 and str2 contain only lowercase English letters.
*************************************

224. String Transforms Into Another String(C++)


*************************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 bool canConvert(string str1, string str2) {
7 if (str1 == str2) {
8 return true;
9 }
10 unordered_map lookup;
11 for (int i = 0; i < str1.size(); ++i) {
12 lookup.emplace(str1[i], str2[i]);
13 if (lookup[str1[i]] != str2[i]) {
14 return false;
15 }
16 }
17 unordered_set count(str2.cbegin(), str2.cend());
18 return count.size() < 26;
19 }
20 };
*************************************

224. String Transforms Into Another String(Python)


*************************************

1 # Time: O(n)
2 # Space: O(1)
3
4 import itertools
5
6
7 class Solution(object):
8 def canConvert(self, str1, str2):
9 """
10 :type str1: str
11 :type str2: str
12 :rtype: bool
13 """
14 if str1 == str2:
15 return True
16 lookup = {}
17 for i, j in itertools.izip(str1, str2):
18 if lookup.setdefault(i, j) != j:
19 return False
20 return len(set(str2)) < 26
***********************************

225. Online Majority Element In Subarray


***********************************

Design a data structure that efficiently finds the majority element of a given subarray.

The majority element of a subarray is an element that occurs threshold times or more in the subarray.

Implementing the MajorityChecker class:

MajorityChecker(int[] arr) Initializes the instance of the class with the given arrayarr.
int query(int left, int right, int threshold) returns the element in the subarray arr[left...right] that occurs at least threshold times, or -1
if no such element exists.

Example 1:

Input
["MajorityChecker", "query", "query", "query"]
[[[1, 1, 2, 2, 1, 1]], [0, 5, 4], [0, 3, 3], [2, 3, 2]]
Output
[null, 1, -1, 2]

Explanation
MajorityChecker majorityChecker = new MajorityChecker([1, 1, 2, 2, 1, 1]);
majorityChecker.query(0, 5, 4); // return 1
majorityChecker.query(0, 3, 3); // return -1
majorityChecker.query(2, 3, 2); // return 2

Constraints:

1 <= arr.length <= 2 * 10 4


1 <= arr[i] <= 2 * 10 4
0 <= left <= right < arr.length
threshold <= right - left + 1
2 * threshold > right - left + 1
At most 104 calls will be made to query.
***********************************

225. Online Majority Element In Subarray(C++)


***********************************

1 // Time: ctor: O(n)


2 // query: O(klogn), k = log2(Q/ERROR_RATE)
3 // Space: O(n)
4
5 class MajorityChecker {
6 public:
7 MajorityChecker(vector& arr)
8 : arr_(arr)
9 , gen_((random_device())())
10 {
11 for (int i = 0; i < arr_.size(); ++i) {
12 inv_idx_[arr_[i]].emplace_back(i);
13 }
14 }
15
16 int query(int left, int right, int threshold) {
17 for (int i = 0; i < K; ++i) {
18 const auto& m = arr_[uniform_int_distribution{left, right}(gen_)];
19 if (count(inv_idx_, m, left, right) >= threshold) {
20 return m;
21 }
22 }
23 return -1;
24 }
25
26 private:
27 int count(const unordered_map>& inv_idx, int m, int left, int right) {
28 const auto& l = lower_bound(inv_idx_[m].cbegin(), inv_idx_[m].cend(), left);
29 const auto& r = upper_bound(inv_idx_[m].cbegin(), inv_idx_[m].cend(), right);
30 return r - l;
31 }
32
33 static constexpr int Q = 10000;
34 static constexpr double ERROR_RATE = 0.001;
35 static constexpr int K = log(Q / ERROR_RATE) / log(2) + 1;
36 const vector& arr_;
37 unordered_map> inv_idx_;
38 default_random_engine gen_;
39 };
40
41 // Time: ctor: O(n)
42 // query: O(sqrt(n) * logn)
43 // Space: O(n)
44 class MajorityChecker2 {
45 public:
46 MajorityChecker2(vector& arr)
47 : arr_(arr)
48 , bound_(round(sqrt(arr_.size())))
49 {
50 for (int i = 0; i < arr_.size(); ++i) {
51 inv_idx_[arr_[i]].emplace_back(i);
52 }
53 for (const auto& [i, group] : inv_idx_) {
54 if (group.size() >= bound_) {
55 majorities_.emplace_back(i);
56 }
57 }
58 }
59
60 int query(int left, int right, int threshold) {
61 if (right - left + 1 < bound_) {
62 const auto& m = boyer_moore_majority_vote(arr_, left, right);
63 if (count(inv_idx_, m, left, right) >= threshold) {
64 return m;
65 }
66 } else {
67 for (const auto& m : majorities_) {
68 if (count(inv_idx_, m, left, right) >= threshold) {
69 return m;
70 }
71 }
72 }
73 return -1;
74 }
75
76 private:
77 int count(const unordered_map>& inv_idx, int m, int left, int right) {
78 const auto& l = lower_bound(inv_idx_[m].cbegin(), inv_idx_[m].cend(), left);
79 const auto& r = upper_bound(inv_idx_[m].cbegin(), inv_idx_[m].cend(), right);
80 return r - l;
81 }
82
83 int boyer_moore_majority_vote(const vector& nums, int left, int right) {
84 int m = nums[left], cnt = 1;
85 for (int i = left; i <= right; ++i) {
86 if (m == nums[i]) {
87 ++cnt;
88 } else {
89 --cnt;
90 if (cnt == 0) {
91 m = nums[i];
92 cnt = 1;
93 }
94 }
95 }
96 return m;
97 }
98
99 const vector& arr_;
100 const int bound_;
101 unordered_map> inv_idx_;
102 vector majorities_;
103 };
104
105 // Time: ctor: O(nlogn)
106 // query: O((logn)^2)
107 // Space: O(n)
108 class MajorityChecker3 {
109 private:
110 struct SegmentTree {
111 public:
112 SegmentTree(const vector& nums,
113 const function& count)
114 : original_length_(nums.size())
115 , count_(count)
116 {
117 int size = 1;
118 while (size <= original_length_) {
119 size *= 2;
120 }
121 if (original_length_ & (original_length_ - 1)) {
122 size *= 2;
123 }
124 tree_ = vector(size - 1, -1);
125 constructTree(nums, 0, original_length_ - 1, 0);
126 }
127
128 pair query(int i, int j) const {
129 return queryRange(i, j, 0, original_length_- 1, 0);
130 }
131
132 private:
133 void constructTree(const vector& nums, int left, int right, int idx) {
134 if (left > right) {
135 return;
135 return;
136 }
137 if (left == right) {
138 tree_[idx] = nums[left];
139 return;
140 }
141 const auto& mid = left + (right - left) / 2;
142 constructTree(nums, left, mid, idx * 2 + 1);
143 constructTree(nums, mid+1, right, idx * 2 + 2);
144 if (tree_[idx * 2 + 1] != -1 &&
145 count_(tree_[idx * 2 + 1], left, right) * 2 > right - left + 1) {
146 tree_[idx] = tree_[idx * 2 + 1];
147 } else if (tree_[idx * 2 + 2] != -1 &&
148 count_(tree_[idx * 2 + 2], left, right) * 2 > right - left + 1) {
149 tree_[idx] = tree_[idx * 2 + 2];
150 }
151 }
152
153 pair queryRange(int range_left, int range_right,
154 int left, int right, int idx) const {
155 if (left > right) {
156 return {-1, -1};
157 }
158 if (right < range_left || left > range_right) {
159 return {-1, -1};
160 }
161 if (range_left <= left && right <= range_right) {
162 if (tree_[idx] != -1) {
163 const auto& c = count_(tree_[idx], range_left, range_right);
164 if (c * 2 > range_right - range_left + 1) {
165 return {tree_[idx], c};
166 }
167 }
168 } else {
169 const auto& mid = left + (right - left) / 2;
170 auto result = queryRange(range_left, range_right, left, mid, idx * 2 + 1);
171 if (result.first != -1) {
172 return result;
173 }
174 result = queryRange(range_left, range_right, mid + 1, right, idx * 2 + 2);
175 if (result.first != -1) {
176 return result;
177 }
178 }
179 return {-1, -1};
180 }
181
182 private:
183 const int original_length_;
184 const function count_;
185 vector tree_;
186 };
187
188 int count(const unordered_map>& inv_idx, int m, int left, int right) {
189 const auto& l = lower_bound(inv_idx_[m].cbegin(), inv_idx_[m].cend(), left);
190 const auto& r = upper_bound(inv_idx_[m].cbegin(), inv_idx_[m].cend(), right);
191 return r - l;
192 }
193
194 public:
195 MajorityChecker3(vector& arr)
196 : arr_(arr)
197 {
198 for (int i = 0; i < arr_.size(); ++i) {
199 inv_idx_[arr_[i]].push_back(i);
200 }
201 segment_tree_ = make_unique(arr,
202 bind(&MajorityChecker3::count, this, cref(inv_idx_),
203 placeholders::_1,
204 placeholders::_2,
205 placeholders::_3));
206 }
207
208 int query(int left, int right, int threshold) {
208 int query(int left, int right, int threshold) {
209 const auto& result = segment_tree_->query(left, right);
210 if (result.second >= threshold) {
211 return result.first;
212 }
213 return -1;
214 }
215
216 private:
217 const vector& arr_;
218 unordered_map> inv_idx_;
219 unique_ptr segment_tree_;
220 };
221
222 // Time: ctor: O(n)
223 // query: O(sqrt(n) * logn)
224 // Space: O(n)
225 class MajorityChecker4 {
226 public:
227 MajorityChecker4(vector& arr)
228 : arr_(arr)
229 , bucket_size_(round(sqrt(arr_.size())))
230 {
231 for (int i = 0; i < arr_.size(); ++i) {
232 inv_idx_[arr_[i]].emplace_back(i);
233 }
234 for (int left = 0; left < arr_.size(); left += bucket_size_) {
235 const auto right = min(left + bucket_size_ - 1, int(arr_.size()) - 1);
236 bucket_majorities_.emplace_back(boyer_moore_majority_vote(arr_, left, right));
237 }
238 }
239
240 int query(int left, int right, int threshold) {
241 int l = left / bucket_size_;
242 int r = right / bucket_size_;
243 if (l == r) {
244 const auto& m = boyer_moore_majority_vote(arr_, left, right);
245 if (count(inv_idx_, m, left, right) >= threshold) {
246 return m;
247 }
248 return -1;
249 }
250 else {
251 int m = boyer_moore_majority_vote(arr_, left, (l + 1) * bucket_size_ - 1);
252 if (count(inv_idx_, m, left, right) >= threshold) {
253 return m;
254 }
255 m = boyer_moore_majority_vote(arr_, r * bucket_size_, right);
256 if (count(inv_idx_, m, left, right) >= threshold) {
257 return m;
258 }
259 for (int i = l + 1; i < r; ++i) {
260 if (count(inv_idx_, bucket_majorities_[i], left, right) >= threshold) {
261 return bucket_majorities_[i];
262 }
263 }
264 return -1;
265 }
266 }
267
268 private:
269 int count(const unordered_map>& inv_idx, int m, int left, int right) {
270 const auto& l = lower_bound(inv_idx_[m].cbegin(), inv_idx_[m].cend(), left);
271 const auto& r = upper_bound(inv_idx_[m].cbegin(), inv_idx_[m].cend(), right);
272 return r - l;
273 }
274
275 int boyer_moore_majority_vote(const vector& nums, int left, int right) {
276 int m = nums[left], cnt = 1;
277 for (int i = left; i <= right; ++i) {
278 if (m == nums[i]) {
279 ++cnt;
280 } else {
281 --cnt;
282 if (cnt == 0) {
283 m = nums[i];
284 cnt = 1;
285 }
286 }
287 }
288 return m;
289 }
290
291 const vector& arr_;
292 const int bucket_size_;
293 unordered_map> inv_idx_;
294 vector bucket_majorities_;
295 };
***********************************

225. Online Majority Element In Subarray(Python)


***********************************

1 # Time: ctor: O(n)


2 # query: O(klogn), k = log2(Q/ERROR_RATE)
3 # Space: O(n)
4
5 import collections
6 import random
7 import bisect
8
9
10 class MajorityChecker(object):
11
12 def __init__(self, arr):
13 """
14 :type arr: List[int]
15 """
16 Q, ERROR_RATE = 10000, 0.001
17 self.__K = int(Q/ERROR_RATE).bit_length() # floor(log2(Q/ERROR_RATE))+1 = 24
18 self.__arr = arr
19 self.__inv_idx = collections.defaultdict(list)
20 for i, x in enumerate(self.__arr):
21 self.__inv_idx[x].append(i)
22
23 def query(self, left, right, threshold):
24 """
25 :type left: int
26 :type right: int
27 :type threshold: int
28 :rtype: int
29 """
30 def count(inv_idx, m, left, right):
31 return bisect.bisect_right(inv_idx[m], right) - \
32 bisect.bisect_left(inv_idx[m], left)
33
34 for _ in xrange(self.__K):
35 m = self.__arr[random.randint(left, right)]
36 if count(self.__inv_idx, m, left, right) >= threshold:
37 return m
38 return -1
39
40
41 # Time: ctor: O(n)
42 # query: O(sqrt(n)*logn)
43 # Space: O(n)
44 import collections
45 import bisect
46
47
48 class MajorityChecker2(object):
49
50 def __init__(self, arr):
51 """
52 :type arr: List[int]
53 """
54 self.__arr = arr
55 self.__inv_idx = collections.defaultdict(list)
56 for i, x in enumerate(self.__arr):
57 self.__inv_idx[x].append(i)
58 self.__bound = int(round((len(arr)**0.5)))
59 self.__majorities = [i for i, group in self.__inv_idx.iteritems() if len(group) >= self.__bound]
60
61 def query(self, left, right, threshold):
62 """
63 :type left: int
64 :type right: int
65 :type threshold: int
66 :rtype: int
67 """
68 def count(inv_idx, m, left, right):
69 return bisect.bisect_right(inv_idx[m], right) - \
70 bisect.bisect_left(inv_idx[m], left)
71
72 def boyer_moore_majority_vote(nums, left, right):
73 m, cnt = nums[left], 1
74 for i in xrange(left+1, right+1):
75 if m == nums[i]:
76 cnt += 1
77 else:
78 cnt -= 1
79 if cnt == 0:
80 m = nums[i]
81 cnt = 1
82 return m
83
84 if right-left+1 < self.__bound:
85 m = boyer_moore_majority_vote(self.__arr, left, right)
86 if count(self.__inv_idx, m, left, right) >= threshold:
87 return m
88 else:
89 for m in self.__majorities:
90 if count(self.__inv_idx, m, left, right) >= threshold:
91 return m
92 return -1
93
94
95 # Time: ctor: O(nlogn)
96 # query: O((logn)^2)
97 # Space: O(n)
98 import functools
99
100
101 class SegmentTreeRecu(object): # 0-based index
102 def __init__(self, nums, count):
103 """
104 initialize your data structure here.
105 :type nums: List[int]
106 """
107 N = len(nums)
108 self.__original_length = N
109 self.__tree_length = 2**(N.bit_length() + (N&(N-1) != 0))-1
110 self.__tree = [-1 for _ in range(self.__tree_length)]
111 self.__count = count
112 self.__constructTree(nums, 0, self.__original_length-1, 0)
113
114 def query(self, i, j):
115 return self.__queryRange(i, j, 0, self.__original_length-1, 0)
116
117 def __constructTree(self, nums, left, right, idx):
118 if left > right:
119 return
120 if left == right:
121 self.__tree[idx] = nums[left]
122 return
123 mid = left + (right-left)//2
124 self.__constructTree(nums, left, mid, idx*2 + 1)
125 self.__constructTree(nums, mid+1, right, idx*2 + 2)
126 if self.__tree[idx*2 + 1] != -1 and \
127 self.__count(self.__tree[idx*2 + 1], left, right)*2 > right-left+1:
128 self.__tree[idx] = self.__tree[idx*2 + 1]
129 elif self.__tree[idx*2 + 2] != -1 and \
130 self.__count(self.__tree[idx*2 + 2], left, right)*2 > right-left+1:
131 self.__tree[idx] = self.__tree[idx*2 + 2]
132
133 def __queryRange(self, range_left, range_right, left, right, idx):
134 if left > right:
135 return (-1, -1)
135 return (-1, -1)
136 if right < range_left or left > range_right:
137 return (-1, -1)
138 if range_left <= left and right <= range_right:
139 if self.__tree[idx] != -1:
140 c = self.__count(self.__tree[idx], range_left, range_right)
141 if c*2 > range_right-range_left+1:
142 return (self.__tree[idx], c)
143 else:
144 mid = left + (right-left)//2
145 result = self.__queryRange(range_left, range_right, left, mid, idx*2 + 1)
146 if result[0] != -1:
147 return result
148 result = self.__queryRange(range_left, range_right, mid + 1, right, idx*2 + 2)
149 if result[0] != -1:
150 return result
151 return (-1, -1)
152
153
154 class MajorityChecker3(object):
155
156 def __init__(self, arr):
157 """
158 :type arr: List[int]
159 """
160 def count(inv_idx, m, left, right):
161 return bisect.bisect_right(inv_idx[m], right) - \
162 bisect.bisect_left(inv_idx[m], left)
163
164 self.__arr = arr
165 self.__inv_idx = collections.defaultdict(list)
166 for i, x in enumerate(self.__arr):
167 self.__inv_idx[x].append(i)
168 self.__segment_tree = SegmentTreeRecu(arr, functools.partial(count, self.__inv_idx))
169
170 def query(self, left, right, threshold):
171 """
172 :type left: int
173 :type right: int
174 :type threshold: int
175 :rtype: int
176 """
177 result = self.__segment_tree.query(left, right)
178 if result[1] >= threshold:
179 return result[0]
180 return -1
181
182
183 # Time: ctor: O(n)
184 # query: O(sqrt(n)*logn)
185 # Space: O(n)
186 import collections
187 import bisect
188
189
190 class MajorityChecker4(object):
191
192 def __init__(self, arr):
193 """
194 :type arr: List[int]
195 """
196 self.__arr = arr
197 self.__inv_idx = collections.defaultdict(list)
198 for i, x in enumerate(self.__arr):
199 self.__inv_idx[x].append(i)
200 self.__bucket_size = int(round((len(arr)**0.5)))
201 self.__bucket_majorities = []
202 for left in xrange(0, len(self.__arr), self.__bucket_size):
203 right = min(left+self.__bucket_size-1, len(self.__arr)-1)
204 self.__bucket_majorities.append(self.__boyer_moore_majority_vote(self.__arr, left, right))
205
206 def query(self, left, right, threshold):
207 """
208 :type left: int
208 :type left: int
209 :type right: int
210 :type threshold: int
211 :rtype: int
212 """
213 def count(inv_idx, m, left, right):
214 return bisect.bisect_right(inv_idx[m], right) - \
215 bisect.bisect_left(inv_idx[m], left)
216
217 l, r = left//self.__bucket_size, right//self.__bucket_size;
218 if l == r:
219 m = self.__boyer_moore_majority_vote(self.__arr, left, right)
220 if count(self.__inv_idx, m, left, right) >= threshold:
221 return m
222 return -1
223 else:
224 m = self.__boyer_moore_majority_vote(self.__arr, left, (l+1)*self.__bucket_size-1)
225 if count(self.__inv_idx, m, left, right) >= threshold:
226 return m
227 m = self.__boyer_moore_majority_vote(self.__arr, r*self.__bucket_size, right)
228 if count(self.__inv_idx, m, left, right) >= threshold:
229 return m;
230 for i in xrange(l+1, r):
231 if count(self.__inv_idx, self.__bucket_majorities[i], left, right) >= threshold:
232 return self.__bucket_majorities[i]
233 return -1
234
235 def __boyer_moore_majority_vote(self, nums, left, right):
236 m, cnt = nums[left], 1
237 for i in xrange(left+1, right+1):
238 if m == nums[i]:
239 cnt += 1
240 else:
241 cnt -= 1
242 if cnt == 0:
243 m = nums[i]
244 cnt = 1
245 return m
******************

226. Market Analysis II


******************

Table: Users

+----------------+---------+
| Column Name | Type |
+----------------+---------+
| user_id | int |
| join_date | date |
| favorite_brand | varchar |
+----------------+---------+
user_id is the primary key of this table.
This table has the info of the users of an online shopping website where users can sell and buy items.

Table: Orders

+---------------+---------+
| Column Name | Type |
+---------------+---------+
| order_id | int |
| order_date | date |
| item_id | int |
| buyer_id | int |
| seller_id | int |
+---------------+---------+
order_id is the primary key of this table.
item_id is a foreign key to the Items table.
buyer_id and seller_id are foreign keys to the Users table.

Table: Items

+---------------+---------+
| Column Name | Type |
+---------------+---------+
| item_id | int |
| item_brand | varchar |
+---------------+---------+
item_id is the primary key of this table.

Write an SQL query to find for each user, whether the brand of the second item (by date) they sold is their favorite brand. If a
user sold less than two items, report the answer for that user as no.

It is guaranteed that no seller sold more than one item on a day.

The query result format is in the following example:


Users table:
+---------+------------+----------------+
| user_id | join_date | favorite_brand |
+---------+------------+----------------+
| 1 | 2019-01-01 | Lenovo |
| 2 | 2019-02-09 | Samsung |
| 3 | 2019-01-19 | LG |
| 4 | 2019-05-21 | HP |
+---------+------------+----------------+

Orders table:
+----------+------------+---------+----------+-----------+
| order_id | order_date | item_id | buyer_id | seller_id |
+----------+------------+---------+----------+-----------+
| 1 | 2019-08-01 | 4 | 1 | 2 |
| 2 | 2019-08-02 | 2 | 1 | 3 |
| 3 | 2019-08-03 | 3 | 2 | 3 |
| 4 | 2019-08-04 | 1 | 4 | 2 |
| 5 | 2019-08-04 | 1 | 3 | 4 |
| 6 | 2019-08-05 | 2 | 2 | 4 |
+----------+------------+---------+----------+-----------+

Items table:
+---------+------------+
| item_id | item_brand |
+---------+------------+
| 1 | Samsung |
| 2 | Lenovo |
| 3 | LG |
| 4 | HP |
+---------+------------+

Result table:
+-----------+--------------------+
| seller_id | 2nd_item_fav_brand |
+-----------+--------------------+
| 1 | no |
| 2 | yes |
| 3 | yes |
| 4 | no |
+-----------+--------------------+

The answer for the user with id 1 is no because they sold nothing.
The answer for the users with id 2 and 3 is yes because the brands of their second sold items are their favorite brands.
The answer for the user with id 4 is no because the brand of their second sold item is not their favorite brand.
******************

226. Market Analysis II(Shell)


******************

1 # Time: O(m + n), m is the number of users, n is the number of orders


2 # Space: O(m + n)
3
4 SELECT user_id AS seller_id,
5 IF(item_brand = favorite_brand, 'yes', 'no') AS 2nd_item_fav_brand
6 FROM (SELECT user_id,
7 favorite_brand,
8 (SELECT item_id
9 FROM orders o
10 WHERE user_id = o.seller_id
11 ORDER BY order_date limit 1, 1) item_id
12 FROM users) u
13 LEFT JOIN items i
14 ON u.item_id = i.item_id
***************************************

227. Last Substring in Lexicographical Order


***************************************

Given a string s , return the last substring of s in lexicographical order.

Example 1:

Input: s = "abab"
Output: "bab"
Explanation: The substrings are ["a", "ab", "aba", "abab", "b", "ba", "bab"]. The lexicographically maximum substring is "bab".

Example 2:

Input: s = "leetcode"
Output: "tcode"

Constraints:

1 <= s.length <= 4 * 10 5


s contains only lowercase English letters.
***************************************

227. Last Substring in Lexicographical Order(C++)


***************************************
1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 string lastSubstring(string s) {
7 int left = 0, right = 1, l = 0;
8 while (right + l < size(s)) {
9 if (s[left + l] == s[right + l]) {
10 ++l;
11 continue;
12 }
13 if (s[left + l] > s[right + l]) {
14 right += l + 1;
15 } else {
16 left = max(right, left + l + 1);
17 right = left + 1;
18 }
19 l = 0;
20 }
21 return s.substr(left);
22 }
23 };
24
25 // Time: O(n)
26 // Space: O(n)
27 class Solution2 {
28 public:
29 string lastSubstring(string s) {
30 unordered_map> count;
31 for (size_t i = 0; i < s.length(); ++i) {
32 count[s[i]].emplace_back(i);
33 }
34
35 const auto& max_c = max_element(count.cbegin(), count.cend(),
36 [](const auto& a, const auto& b) {
37 return a.first < b.first;
38 })->first;
39 unordered_map starts;
40 for (const auto& i : count[max_c]) {
41 starts[i] = i + 1;
42 }
43 while (starts.size() > 1) {
44 unordered_set lookup;
45 unordered_map> next_count;
46 for (const auto& [start, end] : starts) {
47 if (end == s.length()) { // finished
48 lookup.emplace(start);
49 continue;
50 }
51 next_count[s[end]].emplace_back(start);
52 if (starts.count(end)) { // overlapped
53 lookup.emplace(end);
54 }
55 }
56 unordered_map next_starts;
57 const auto& max_c = max_element(next_count.cbegin(), next_count.cend(),
58 [](const auto& a, const auto& b) {
59 return a.first < b.first;
60 })->first;
61 for (const auto& start : next_count[max_c]) {
62 if (!lookup.count(start)) {
63 next_starts[start] = starts[start] + 1;
64 }
65 }
66 starts = move(next_starts);
67 }
68 return s.substr(starts.cbegin()->first);
69 }
70 };
***************************************

227. Last Substring in Lexicographical Order(Python)


***************************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def lastSubstring(self, s):
6 """
7 :type s: str
8 :rtype: str
9 """
10 left, right, l = 0, 1, 0
11 while right+l < len(s):
12 if s[left+l] == s[right+l]:
13 l += 1
14 continue
15 if s[left+l] > s[right+l]:
16 right += l+1
17 else:
18 left = max(right, left+l+1)
19 right = left+1
20 l = 0
21 return s[left:]
22
23
24 # Time: O(n)
25 # Space: O(n)
26 import collections
27
28
29 class Solution2(object):
30 def lastSubstring(self, s):
31 """
32 :type s: str
33 :rtype: str
34 """
35 count = collections.defaultdict(list)
36 for i in xrange(len(s)):
37 count[s[i]].append(i)
38
39 max_c = max(count.iterkeys())
40 starts = {}
41 for i in count[max_c]:
42 starts[i] = i+1
43 while len(starts)-1 > 0:
44 lookup = set()
45 next_count = collections.defaultdict(list)
46 for start, end in starts.iteritems():
47 if end == len(s): # finished
48 lookup.add(start)
49 continue
50 next_count[s[end]].append(start)
51 if end in starts: # overlapped
52 lookup.add(end)
53 next_starts = {}
54 max_c = max(next_count.iterkeys())
55 for start in next_count[max_c]:
56 if start not in lookup:
57 next_starts[start] = starts[start]+1
58 starts = next_starts
59 return s[next(starts.iterkeys()):]
****************************************

228. Optimize Water Distribution in a Village


****************************************

There are n houses in a village. We want to supply water for all the houses by building wells and laying pipes.

For each house i, we can either build a well inside it directly with costwells[i - 1] (note the -1 due to 0-indexing), or pipe in
water from another well to it. The costs to lay pipes between houses are given by the array pipes, where each pipes[j] = [house1 j,
house2 j, cost j] represents the cost to connect house1 j and house2 j together using a pipe. Connections are bidirectional.

Return the minimum total cost to supply water to all houses.

Example 1:

Input: n = 3, wells = [1,2,2], pipes = [[1,2,1],[2,3,1]]


Output: 3
Explanation:
The image shows the costs of connecting houses using pipes.
The best strategy is to build a well in the first house with cost 1 and connect the other houses to it with cost 2 so the total cost is 3.

Constraints:

1 <= n <= 10 4
wells.length == n
0 <= wells[i] <= 10 5
1 <= pipes.length <= 10 4
pipes[j].length == 3
1 <= house1 j, house2 j <= n
0 <= cost j <= 105
house1 j != house2 j
****************************************

228. Optimize Water Distribution in a Village(C++)


****************************************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int minCostToSupplyWater(int n, vector& wells, vector>& pipes) {
7 vector> nodes;
8 for (int i = 0; i < wells.size(); ++i) {
9 nodes.emplace_back(wells[i], 0, i + 1);
10 }
11 for (int i = 0; i < pipes.size(); ++i) {
12 nodes.emplace_back(pipes[i][2], pipes[i][0], pipes[i][1]);
13 }
14 sort(nodes.begin(), nodes.end());
15 int result = 0;
16 UnionFind union_find(n + 1);
17 for (const auto& [c, x, y] : nodes) {
18 if (!union_find.union_set(x, y)) {
19 continue;
20 }
21 result += c;
22 if (union_find.count() == 1) {
23 break;
24 }
25 }
26 return result;
27 }
28
29 private:
30 class UnionFind {
31 public:
32 UnionFind(const int n) : set_(n), count_(n) {
33 iota(set_.begin(), set_.end(), 0);
34 }
35
36 int find_set(const int x) {
37 if (set_[x] != x) {
38 set_[x] = find_set(set_[x]); // Path compression.
39 }
40 return set_[x];
41 }
42
43 bool union_set(const int x, const int y) {
44 int x_root = find_set(x), y_root = find_set(y);
45 if (x_root == y_root) {
46 return false;
47 }
48 set_[min(x_root, y_root)] = max(x_root, y_root);
49 --count_;
50 return true;
51 }
52
53 int count() const {
54 return count_;
55 }
56
57 private:
58 vector set_;
59 int count_;
60 };
61 };
****************************************

228. Optimize Water Distribution in a Village(Python)


****************************************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 class UnionFind(object):
5 def __init__(self, n):
6 self.set = range(n)
7 self.count = n
8
9 def find_set(self, x):
10 if self.set[x] != x:
11 self.set[x] = self.find_set(self.set[x]) # path compression.
12 return self.set[x]
13
14 def union_set(self, x, y):
15 x_root, y_root = map(self.find_set, (x, y))
16 if x_root == y_root:
17 return False
18 self.set[max(x_root, y_root)] = min(x_root, y_root)
19 self.count -= 1
20 return True
21
22
23 class Solution(object):
24 def minCostToSupplyWater(self, n, wells, pipes):
25 """
26 :type n: int
27 :type wells: List[int]
28 :type pipes: List[List[int]]
29 :rtype: int
30 """
31 w = [[c, 0, i] for i, c in enumerate(wells, 1)]
32 p = [[c, i, j] for i, j, c in pipes]
33 result = 0
34 union_find = UnionFind(n+1)
35 for c, x, y in sorted(w+p):
36 if not union_find.union_set(x, y):
37 continue
38 result += c
39 if union_find.count == 1:
40 break
41 return result
*******************

229. Dinner Plate Stacks


*******************

You have an infinite number of stacks arranged in a row and numbered (left to right) from0, each of the stacks has the same
maximum capacity.

Implement the DinnerPlates class:

DinnerPlates(int capacity) Initializes the object with the maximum capacity of the stackscapacity .
void push(int val) Pushes the given integer val into the leftmost stack with a size less thancapacity .
int pop() Returns the value at the top of the rightmost non-empty stack and removes it from that stack, and returns-1 if
all the stacks are empty.
int popAtStack(int index) Returns the value at the top of the stack with the given indexindex and removes it from that stack
or returns -1 if the stack with that given index is empty.

Example 1:

Input
["DinnerPlates", "push", "push", "push", "push", "push", "popAtStack", "push", "push", "popAtStack", "popAtStack", "pop", "pop", "pop", "pop"
[[2], [1], [2], [3], [4], [5], [0], [20], [21], [0], [2], [], [], [], [], []]
Output
[null, null, null, null, null, null, 2, null, null, 20, 21, 5, 4, 3, 1, -1]

Explanation:
DinnerPlates D = DinnerPlates(2); // Initialize with capacity = 2
D.push(1);
D.push(2);
D.push(3);
D.push(4);
D.push(5); // The stacks are now: 2 4
1 3 5
﹈ ﹈ ﹈
D.popAtStack(0); // Returns 2. The stacks are now: 4
1 3 5
﹈ ﹈ ﹈
D.push(20); // The stacks are now: 20 4
1 3 5
﹈ ﹈ ﹈
D.push(21); // The stacks are now: 20 4 21
1 3 5
﹈ ﹈ ﹈
D.popAtStack(0); // Returns 20. The stacks are now: 4 21
1 3 5
﹈ ﹈ ﹈
D.popAtStack(2); // Returns 21. The stacks are now: 4
1 3 5
﹈ ﹈ ﹈
D.pop() // Returns 5. The stacks are now: 4
1 3
﹈ ﹈
D.pop() // Returns 4. The stacks are now: 1 3
﹈ ﹈
D.pop() // Returns 3. The stacks are now: 1
﹈
D.pop() // Returns 1. There are no stacks.
D.pop() // Returns -1. There are still no stacks.

Constraints:
1 <= capacity <= 2 * 10 4
1 <= val <= 2 * 10 4
0 <= index <= 10 5
At most 2 * 105 calls will be made to push, pop, and popAtStack.
*******************

229. Dinner Plate Stacks(C++)


*******************

1 // Time: push: O(logn)


2 // pop: O(1), amortized
3 // popAtStack: O(logn)
4 // Space: O(n * c)
5
6 class DinnerPlates {
7 public:
8 DinnerPlates(int capacity) : c_(capacity) {
9 }
10
11 void push(int val) {
12 if (!min_heap_.empty()) {
13 const auto l = min_heap_.top(); min_heap_.pop();
14 if (l < stks_.size()) {
15 stks_[l].emplace_back(val);
16 return;
17 }
18 min_heap_ = {}; // nothing is valid in min heap
19 }
20 if (stks_.empty() || stks_.back().size() == c_) {
21 stks_.emplace_back();
22 }
23 stks_.back().emplace_back(val);
24 }
25
26 int pop() {
27 while (!stks_.empty() && stks_.back().empty()) {
28 stks_.pop_back();
29 }
30 if (stks_.empty()) {
31 return -1;
32 }
33 auto result = stks_.back().back(); stks_.back().pop_back();
34 return result;
35 }
36
37 int popAtStack(int index) {
38 if (index >= stks_.size() || stks_[index].empty()) {
39 return -1;
40 }
41 min_heap_.emplace(index);
42 auto result = stks_[index].back(); stks_[index].pop_back();
43 return result;
44 }
45
46 private:
47 vector> stks_;
48 int c_;
49 priority_queue, greater> min_heap_;
50 };
*******************

229. Dinner Plate Stacks(Python)


*******************

1 # Time: push: O(logn)


2 # pop: O(1), amortized
3 # popAtStack: O(logn)
4 # Space: O(n * c)
5
6 import heapq
7
8
9 class DinnerPlates(object):
10
11 def __init__(self, capacity):
12 """
13 :type capacity: int
14 """
15 self.__stks = []
16 self.__c = capacity
17 self.__min_heap = []
18
19 def push(self, val):
20 """
21 :type val: int
22 :rtype: None
23 """
24 if self.__min_heap:
25 l = heapq.heappop(self.__min_heap)
26 if l < len(self.__stks):
27 self.__stks[l].append(val)
28 return
29 self.__min_heap = [] # nothing is valid in min heap
30 if not self.__stks or len(self.__stks[-1]) == self.__c:
31 self.__stks.append([])
32 self.__stks[-1].append(val)
33
34 def pop(self):
35 """
36 :rtype: int
37 """
38 while self.__stks and not self.__stks[-1]:
39 self.__stks.pop()
40 if not self.__stks:
41 return -1
42 return self.__stks[-1].pop()
43
44 def popAtStack(self, index):
45 """
46 :type index: int
47 :rtype: int
48 """
49 if index >= len(self.__stks) or not self.__stks[index]:
50 return -1
51 heapq.heappush(self.__min_heap, index)
52 return self.__stks[index].pop()
*************************************

230. Number of Valid Words for Each Puzzle


*************************************

With respect to a given puzzle string, a word is valid if both the following conditions are satisfied:

word contains the first letter of puzzle .


For each letter in word, that letter is in puzzle .
For example, if the puzzle is "abcdefg", then valid words are "faced", "cabbage", and "baggage"; while invalid words
are "beefed" (doesn't include "a") and "based" (includes "s" which isn't in the puzzle).

Return an array answer, where answer[i] is the number of words in the given word listwords that are valid with respect to the
puzzle puzzles[i].

Example :

Input:
words = ["aaaa","asas","able","ability","actt","actor","access"],
puzzles = ["aboveyz","abrodyz","abslute","absoryz","actresz","gaswxyz"]
Output: [1,1,3,2,4,0]
Explanation:
1 valid word for "aboveyz" : "aaaa"
1 valid word for "abrodyz" : "aaaa"
3 valid words for "abslute" : "aaaa", "asas", "able"
2 valid words for "absoryz" : "aaaa", "asas"
4 valid words for "actresz" : "aaaa", "asas", "actt", "access"
There're no valid words for "gaswxyz" cause none of the words in the list contains letter 'g'.

Constraints:

1 <= words.length <= 10^5


4 <= words[i].length <= 50
1 <= puzzles.length <= 10^4
puzzles[i].length == 7
words[i][j], puzzles[i][j] are English lowercase letters.
Each puzzles[i] doesn't contain repeated characters.
*************************************

230. Number of Valid Words for Each Puzzle(C++)


*************************************

1 // Time: O(n*l + m*L), m is the number of puzzles, L is the length of puzzles


2 // , n is the number of words, l is the max length of words
3 // Space: O(L!)
4
5 class Solution {
6 public:
7 vector findNumOfValidWords(vector& words, vector& puzzles) {
8 static const int L = 7;
9 TrieNode trie;
10 for (const auto& word : words) {
11 vector count(26);
12 for (const auto& c: word) {
13 count[c - 'a'] = 1;
14 }
15 const auto& total = accumulate(count.cbegin(), count.cend(), 0);
16 if (total > L) {
17 continue;
18 }
19 trie.insert(count);
20 }
21 vector result;
22 for (auto puzzle: puzzles) {
23 const auto first = puzzle[0];
24 sort(puzzle.begin(), puzzle.end());
25 result.emplace_back(search(&trie, puzzle, 0, first, false));
26 }
27 return result;
28 }
29
30 private:
31 struct TrieNode;
32
33 int search(TrieNode* node, const string& puzzle, int start, char first, bool met_first) {
34 int result = 0;
35 if (met_first) {
36 result += node->end_count;
37 }
38 for (int i = start; i < puzzle.length(); ++i) {
39 if (node->children[puzzle[i] - 'a'] == nullptr) {
40 continue;
41 }
42 result += search(node->children[puzzle[i] - 'a'], puzzle, i + 1,
43 first, met_first || (puzzle[i] == first));
44 }
45 return result;
46 }
47
48 struct TrieNode {
49 int end_count;
50 vector children;
51
52 TrieNode() : end_count{0}, children(26) {}
53
54 void insert(const vector& count) {
55 auto* p = this;
56 for (int i = 0; i < count.size(); ++i) {
57 if (!count[i]) {
58 continue;
59 }
60 if (!p->children[i]) {
61 p->children[i] = new TrieNode;
62 }
63 p = p->children[i];
64 }
65 ++p->end_count;
66 }
67
68 ~TrieNode() {
69 for (auto& node : children) {
70 if (node) {
71 delete node;
72 }
73 }
74 }
75 };
76 };
77
78 // Time: O(m*2^(L-1) + n*(l+m)), m is the number of puzzles, L is the length of puzzles
79 // , n is the number of words, l is the max length of words
80 // Space: O(m*2^(L-1))
81 class Solution2 {
82 public:
83 vector findNumOfValidWords(vector& words, vector& puzzles) {
84 static const int L = 7;
85 unordered_map> lookup;
86 for (int i = 0; i < puzzles.size(); ++i) {
87 vector bits;
88 const auto& base = 1 << (puzzles[i][0] - 'a');
89 for (int j = 1; j < L; ++j) {
90 bits.emplace_back(puzzles[i][j] - 'a');
91 }
92 for (int k = 0; k < 1 << bits.size(); ++k) {
93 int bitset = base;
94 for (int j = 0; j < bits.size(); ++j) {
95 if (k & (1 << j)) {
96 bitset |= 1 << bits[j];
97 }
98 }
99 lookup[bitset].emplace_back(i);
100 }
101 }
102 vector result(puzzles.size());
103 for (const auto& word : words) {
104 int bitset = 0;
105 for (const auto& c : word) {
106 bitset |= 1 << (c - 'a');
107 }
108 if (!lookup.count(bitset)) {
109 continue;
110 }
111 for (const auto& i : lookup[bitset]) {
112 ++result[i];
113 }
114 }
115 return result;
116 }
117 };
*************************************

230. Number of Valid Words for Each Puzzle(Python)


*************************************
1 # Time: O(n*l + m*L), m is the number of puzzles, L is the length of puzzles
2 # , n is the number of words, l is the max length of words
3 # Space: O(L!)
4
5 class Solution(object):
6 def findNumOfValidWords(self, words, puzzles):
7 """
8 :type words: List[str]
9 :type puzzles: List[str]
10 :rtype: List[int]
11 """
12 L = 7
13 def search(node, puzzle, start, first, met_first):
14 result = 0
15 if "_end" in node and met_first:
16 result += node["_end"];
17 for i in xrange(start, len(puzzle)):
18 if puzzle[i] not in node:
19 continue
20 result += search(node[puzzle[i]], puzzle, i+1,
21 first, met_first or (puzzle[i] == first))
22 return result
23
24 _trie = lambda: collections.defaultdict(_trie)
25 trie = _trie()
26 for word in words:
27 count = set(word)
28 if len(count) > L:
29 continue
30 word = sorted(count)
31 end = reduce(dict.__getitem__, word, trie)
32 end["_end"] = end["_end"]+1 if "_end" in end else 1
33 result = []
34 for puzzle in puzzles:
35 first = puzzle[0]
36 result.append(search(trie, sorted(puzzle), 0, first, False))
37 return result
38
39
40 # Time: O(m*2^(L-1) + n*(l+m)), m is the number of puzzles, L is the length of puzzles
41 # , n is the number of words, l is the max length of words
42 # Space: O(m*2^(L-1))
43 import collections
44
45
46 class Solution2(object):
47 def findNumOfValidWords(self, words, puzzles):
48 """
49 :type words: List[str]
50 :type puzzles: List[str]
51 :rtype: List[int]
52 """
53 L = 7
54 lookup = collections.defaultdict(list)
55 for i in xrange(len(puzzles)):
56 bits = []
57 base = 1 << (ord(puzzles[i][0])-ord('a'))
58 for j in xrange(1, L):
59 bits.append(ord(puzzles[i][j])-ord('a'))
60 for k in xrange(2**len(bits)):
61 bitset = base
62 for j in xrange(len(bits)):
63 if k & (1<
**********************

231. Maximum Number of Ones


**********************

Consider a matrix M with dimensions width * height, such that every cell has value 0 or 1, and any square sub-matrix of M of
size sideLength * sideLength has at most maxOnes ones.

Return the maximum possible number of ones that the matrixM can have.

Example 1:

Input: width = 3, height = 3, sideLength = 2, maxOnes = 1


Output: 4
Explanation:
In a 3*3 matrix, no 2*2 sub-matrix can have more than 1 one.
The best solution that has 4 ones is:
[1,0,1]
[0,0,0]
[1,0,1]

Example 2:

Input: width = 3, height = 3, sideLength = 2, maxOnes = 2


Output: 6
Explanation:
[1,0,1]
[1,0,1]
[1,0,1]

Constraints:

1 <= width, height <= 100


1 <= sideLength <= width, height
0 <= maxOnes <= sideLength * sideLength
**********************

231. Maximum Number of Ones(C++)


**********************

1 // Time: O(1)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int maximumNumberOfOnes(int width, int height, int sideLength, int maxOnes) {
7 if (width < height) {
8 swap(width, height);
9 }
10
11 const auto& R = height / sideLength, &r = height % sideLength;
12 const auto& C = width / sideLength, &c = width % sideLength;
13 assert(R <= C);
14 vector> area_counts = {{r * c, (R + 1) * (C + 1)},
15 {r * (sideLength - c), (R + 1) * C},
16 {(sideLength - r) * c, R * (C + 1)},
17 {(sideLength - r) * (sideLength - c), R * C}};
18 int result = 0;
19 for (const auto& [area, count] : area_counts) {
20 result += count * min(maxOnes, area);
21 maxOnes -= min(maxOnes, area);
22 if (!maxOnes) {
23 break;
24 }
25 }
26 return result;
27 }
28 };
**********************

231. Maximum Number of Ones(Python)


**********************

1 # Time: O(1)
2 # Space: O(1)
3
4 class Solution(object):
5 def maximumNumberOfOnes(self, width, height, sideLength, maxOnes):
6 """
7 :type width: int
8 :type height: int
9 :type sideLength: int
10 :type maxOnes: int
11 :rtype: int
12 """
13 if width < height:
14 width, height = height, width
15
16 # 1. split matrix by SxS tiles
17 # 2. split each SxS tile into four parts
18 # (r, c), (r, S-c), (S-r, c), (S-r, S-c)
19 # 3. for each count of tile part in matrix is
20 # (R+1)*(C+1), (R+1)*C, R*(C+1), R*C (already in descending order)
21 # 4. fill one into matrix by tile part of which count is in descending order
22 # until number of ones in a tile comes to maxOnes
23 #
24 # ps. area of a tile and its count in matrix are as follows:
25 #
26 # |<---- c ---->|<-- S-c -->|
27 # ^ | |
28 # | | |
29 # r (R+1)*(C+1) | (R+1)*C |
30 # | | |
31 # v | |
32 # ---------------------------
33 # ^ | |
34 # | | |
35 # S-r R*(C+1) | R*C |
36 # | | |
37 # v | |
38 # ---------------------------
39 #
40
41 R, r = divmod(height, sideLength)
42 C, c = divmod(width, sideLength)
43 assert(R <= C)
44 area_counts = [(r*c, (R+1)*(C+1)), \
45 (r*(sideLength-c), (R+1)*C), \
46 ((sideLength-r)*c, R*(C+1)), \
47 ((sideLength-r)*(sideLength-c), R*C)]
48 result = 0
49 for area, count in area_counts:
50 area = min(maxOnes, area)
51 result += count*area
52 maxOnes -= area
53 if not maxOnes:
54 break
55 return result
******************************

232. Make Array Strictly Increasing


******************************

Given two integer arrays arr1 and arr2, return the minimum number of operations (possibly zero) needed to makearr1 strictly
increasing.

In one operation, you can choose two indices 0 <= i < arr1.length and 0 <= j < arr2.length and do the assignment arr1[i] = arr2[j] .

If there is no way to make arr1 strictly increasing, return -1.

Example 1:

Input: arr1 = [1,5,3,6,7], arr2 = [1,3,2,4]


Output: 1
Explanation: Replace 5 with 2, then arr1 = [1, 2, 3, 6, 7].

Example 2:

Input: arr1 = [1,5,3,6,7], arr2 = [4,3,1]


Output: 2
Explanation: Replace 5 with 3 and then replace 3 with 4. arr1 = [1, 3, 4, 6, 7].

Example 3:

Input: arr1 = [1,5,3,6,7], arr2 = [1,6,3,3]


Output: -1
Explanation: You can't make arr1 strictly increasing.

Constraints:

1 <= arr1.length, arr2.length <= 2000


0 <= arr1[i], arr2[i] <= 10^9
******************************

232. Make Array Strictly Increasing(C++)


******************************

1 // Time: O(n^2 * logn)


2 // Space: O(n)
3
4 class Solution {
5 public:
6 int makeArrayIncreasing(vector& arr1, vector& arr2) {
7 std::sort(arr2.begin(), arr2.end());
8 arr2.erase(unique(arr2.begin(), arr2.end()), arr2.end());
9 unordered_map dp = {{0, -1}}; // dp[min_cost] = end_with_val
10 for (const auto& val1 : arr1) {
11 unordered_map next_dp;
12 for (const auto& [cost, val] : dp) {
13 if (val < val1) {
14 if (!next_dp.count(cost)) {
15 next_dp[cost] = val1;
16 } else {
17 next_dp[cost] = min(next_dp[cost], val1);
18 }
19 }
20 const auto& it = upper_bound(arr2.cbegin(), arr2.cend(), val);
21 if (it != arr2.cend()) {
22 if (!next_dp.count(cost + 1)) {
23 next_dp[cost + 1] = *it;
24 } else {
25 next_dp[cost + 1] = min(next_dp[cost + 1], *it);
26 }
27 }
28 }
29 dp = move(next_dp);
30 if (dp.empty()) {
31 return -1;
32 }
33 }
34 return min_element(dp.cbegin(), dp.cend())->first;
35 }
36 };
******************************

232. Make Array Strictly Increasing(Python)


******************************

1 # Time: O(n^2 * logn)


2 # Space: O(n)
3
4 import collections
5 import bisect
6
7
8 class Solution(object):
9 def makeArrayIncreasing(self, arr1, arr2):
10 """
11 :type arr1: List[int]
12 :type arr2: List[int]
13 :rtype: int
14 """
15 arr2 = sorted(set(arr2))
16 dp = {0: -1} # dp[min_cost] = end_with_val
17 for val1 in arr1:
18 next_dp = collections.defaultdict(lambda: float("inf"))
19 for cost, val in dp.iteritems():
20 if val < val1:
21 next_dp[cost] = min(next_dp[cost], val1)
22 k = bisect.bisect_right(arr2, val)
23 if k == len(arr2):
24 continue
25 next_dp[cost+1] = min(next_dp[cost+1], arr2[k])
26 dp = next_dp
27 if not dp:
28 return -1
29 return min(dp.iterkeys())
*********************************

233. Critical Connections in a Network


*********************************

There are n servers numbered from 0 to n - 1 connected by undirected server-to-server connections forming a network where
connections[i] = [a i, b i] represents a connection between servers ai and bi. Any server can reach other servers directly or indirectly
through the network.

A critical connection is a connection that, if removed, will make some servers unable to reach some other server.

Return all critical connections in the network in any order.

Example 1:

Input: n = 4, connections = [[0,1],[1,2],[2,0],[1,3]]


Output: [[1,3]]
Explanation: [[3,1]] is also accepted.

Constraints:

2 <= n <= 10 5
n - 1 <= connections.length <= 10 5
0 <= ai, b i <= n - 1
ai != b i
There are no repeated connections.
*********************************

233. Critical Connections in a Network(C++)


*********************************

1 // Time: O(|V| + |E|)


2 // Space: O(|V| + |E|)
3
4 // variant of Tarjan's algorithm (https://www.geeksforgeeks.org/bridge-in-a-graph/)
5 class Solution {
6 public:
7 vector> criticalConnections(int n, vector>& connections) {
8 vector> edges(n);
9 int idx = 0;
10 vector lowlinks(n);
11 vector lookup(n);
12 vector> result;
13 for (const auto& c : connections) {
14 edges[c.front()].emplace_back(c.back());
15 edges[c.back()].emplace_back(c.front());
16 }
17 dfs(edges, -1, 0, &idx, &lowlinks, &lookup, &result);
18 return result;
19 }
20
21 private:
22 void dfs(const vector>& edges,
23 int parent, int u,
24 int *idx, vector *lowlinks,
25 vector *lookup, vector> *result) {
26
27 if ((*lookup)[u]) {
28 return;
29 }
30 (*lookup)[u] = true;
31 const auto curr_idx = (*lowlinks)[u] = (*idx)++;
32 for (const auto& v : edges[u]) {
33 if (v == parent) {
34 continue;
35 }
36 dfs(edges, u, v, idx, lowlinks, lookup, result);
37 (*lowlinks)[u] = min((*lowlinks)[u], (*lowlinks)[v]);
38 if ((*lowlinks)[v] > curr_idx) {
39 // if any lowlink of neighbors is larger than curr_idx
40 result->push_back({u, v});
41 }
42 }
43 }
44 };
*********************************

233. Critical Connections in a Network(Python)


*********************************

1 # Time: O(|V| + |E|)


2 # Space: O(|V| + |E|)
3
4 # variant of Tarjan's algorithm (https://www.geeksforgeeks.org/bridge-in-a-graph/)
5 class Solution(object):
6 def criticalConnections(self, n, connections):
7 """
8 :type n: int
9 :type connections: List[List[int]]
10 :rtype: List[List[int]]
11 """
12 def dfs(edges, parent, u, idx, lowlinks, lookup, result):
13 if lookup[u]:
14 return
15 lookup[u] = True
16 curr_idx = lowlinks[u] = idx[0]
17 idx[0] += 1
18 for v in edges[u]:
19 if v == parent:
20 continue
21 dfs(edges, u, v, idx, lowlinks, lookup, result)
22 lowlinks[u] = min(lowlinks[u], lowlinks[v])
23 if lowlinks[v] > curr_idx:
24 # if any lowlink of neighbors is larger than curr_idx
25 result.append([u, v])
26
27 edges = [[] for _ in xrange(n)]
28 idx, lowlinks, lookup = [0], [0]*n, [False]*n
29 result = []
30 for u, v in connections:
31 edges[u].append(v)
32 edges[v].append(u)
33 dfs(edges, -1, 0, idx, lowlinks, lookup, result)
34 return result
******************

234. Tournament Winners


******************

Table: Players

+-------------+-------+
| Column Name | Type |
+-------------+-------+
| player_id | int |
| group_id | int |
+-------------+-------+
player_id is the primary key of this table.
Each row of this table indicates the group of each player.

Table: Matches

+---------------+---------+
| Column Name | Type |
+---------------+---------+
| match_id | int |
| first_player | int |
| second_player | int |
| first_score | int |
| second_score | int |
+---------------+---------+
match_id is the primary key of this table.
Each row is a record of a match, first_player and second_player contain the player_id of each match.
first_score and second_score contain the number of points of the first_player and second_player respectively.
You may assume that, in each match, players belongs to the same group.

The winner in each group is the player who scored the maximum total points within the group. In the case of a tie, the
lowest player_id wins.

Write an SQL query to find the winner in each group.

The query result format is in the following example:


Players table:
+-----------+------------+
| player_id | group_id |
+-----------+------------+
| 15 | 1 |
| 25 | 1 |
| 30 | 1 |
| 45 | 1 |
| 10 | 2 |
| 35 | 2 |
| 50 | 2 |
| 20 | 3 |
| 40 | 3 |
+-----------+------------+

Matches table:
+------------+--------------+---------------+-------------+--------------+
| match_id | first_player | second_player | first_score | second_score |
+------------+--------------+---------------+-------------+--------------+
| 1 | 15 | 45 | 3 | 0 |
| 2 | 30 | 25 | 1 | 2 |
| 3 | 30 | 15 | 2 | 0 |
| 4 | 40 | 20 | 5 | 2 |
| 5 | 35 | 50 | 1 | 1 |
+------------+--------------+---------------+-------------+--------------+

Result table:
+-----------+------------+
| group_id | player_id |
+-----------+------------+
| 1 | 15 |
| 2 | 35 |
| 3 | 40 |
+-----------+------------+
******************

234. Tournament Winners(Shell)


******************

1 # Time: O(m + n + nlogn)


2 # Space: P(m + n)
3
4 SELECT group_id,
5 player_id
6 FROM (SELECT p.group_id,
7 ps.player_id,
8 Sum(ps.score) AS score
9 FROM players p INNER JOIN
10 (SELECT first_player AS player_id,
11 first_score AS score
12 FROM matches
13 UNION ALL
14 SELECT second_player AS player_id,
15 second_score AS score
16 FROM matches) ps
17 ON p.player_id = ps.player_id
18 GROUP BY ps.player_id
19 ORDER BY group_id,
20 score DESC,
21 player_id) top_scores
22 GROUP BY group_id
****************************

235. Minimum Time to Build Blocks


****************************

You are given a list of blocks, where blocks[i] = t means that the i-th block needs t units of time to be built. A block can only be
built by exactly one worker.

A worker can either split into two workers (number of workers increases by one) or build a block then go home. Both
decisions cost some time.

The time cost of spliting one worker into two workers is given as an integersplit. Note that if two workers split at the same
time, they split in parallel so the cost would be split.

Output the minimum time needed to build all blocks.

Initially, there is only one worker.

Example 1:

Input: blocks = [1], split = 1


Output: 1
Explanation: We use 1 worker to build 1 block in 1 time unit.

Example 2:

Input: blocks = [1,2], split = 5


Output: 7
Explanation: We split the worker into 2 workers in 5 time units then assign each of them to a block so the cost is 5 + max(1, 2) = 7.

Example 3:

Input: blocks = [1,2,3], split = 1


Output: 4
Explanation: Split 1 worker into 2, then assign the first worker to the last block and split the second worker into 2.
Then, use the two unassigned workers to build the first two blocks.
The cost is 1 + max(3, 1 + max(1, 2)) = 4.

Constraints:

1 <= blocks.length <= 1000


1 <= blocks[i] <= 10^5
1 <= split <= 100
****************************

235. Minimum Time to Build Blocks(C++)


****************************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int minBuildTime(vector& blocks, int split) {
7 priority_queue, greater> min_heap(blocks.cbegin(), blocks.cend());
8 while (min_heap.size() != 1) {
9 min_heap.pop();
10 const auto y = min_heap.top(); min_heap.pop();
11 min_heap.emplace(y + split);
12 }
13 return min_heap.top();
14 }
15 };
****************************

235. Minimum Time to Build Blocks(Python)


****************************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 import heapq
5
6
7 class Solution(object):
8 def minBuildTime(self, blocks, split):
9 """
10 :type blocks: List[int]
11 :type split: int
12 :rtype: int
13 """
14 heapq.heapify(blocks)
15 while len(blocks) != 1:
16 x, y = heapq.heappop(blocks), heapq.heappop(blocks)
17 heapq.heappush(blocks, y+split)
18 return heapq.heappop(blocks)
********************************************

236. Sort Items by Groups Respecting Dependencies


********************************************

There are n items each belonging to zero or one of m groups where group[i] is the group that the i-th item belongs to and it's
equal to -1 if the i-th item belongs to no group. The items and the groups are zero indexed. A group can have no item
belonging to it.

Return a sorted list of the items such that:

The items that belong to the same group are next to each other in the sorted list.
There are some relations between these items where beforeItems[i] is a list containing all the items that should come
before the i-th item in the sorted array (to the left of thei-th item).

Return any solution if there is more than one solution and return anempty list if there is no solution.

Example 1:

Input: n = 8, m = 2, group = [-1,-1,1,0,0,1,0,-1], beforeItems = [[],[6],[5],[6],[3,6],[],[],[]]


Output: [6,3,4,1,5,2,0,7]

Example 2:

Input: n = 8, m = 2, group = [-1,-1,1,0,0,1,0,-1], beforeItems = [[],[6],[5],[6],[3],[],[4],[]]


Output: []
Explanation: This is the same as example 1 except that 4 needs to be before 6 in the sorted list.

Constraints:

1 <= m <= n <= 3 * 10 4


group.length == beforeItems.length == n
-1 <= group[i] <= m - 1
0 <= beforeItems[i].length <= n - 1
0 <= beforeItems[i][j] <= n - 1
i != beforeItems[i][j]
beforeItems[i] does not contain duplicates elements.
********************************************

236. Sort Items by Groups Respecting


Dependencies(C++)
********************************************

1 // Time: O(n + e)
2 // Space: O(n + e)
3
4 class Solution {
5 public:
6 vector sortItems(int n, int m, vector& group_id, vector>& beforeItems) {
7 for (int i = 0; i < n; ++i) {
8 if (group_id[i] == -1) {
9 group_id[i] = m++;
10 }
11 }
12 Topo global_group;
13 for (int i = 0; i < m; ++i) {
14 global_group.addNode(i);
15 }
16 unordered_map local_groups;
17 for (int i = 0; i < n; ++i) {
18 local_groups[group_id[i]].addNode(i);
19 }
20 for (int i = 0; i < n; ++i) {
21 for (const auto& j : beforeItems[i]) {
22 if (group_id[i] == group_id[j]) {
23 local_groups[group_id[i]].addEdge(j, i);
24 } else {
25 global_group.addEdge(group_id[j], group_id[i]);
26 }
27 }
28 }
29 vector result;
30 const auto& global_order = global_group.sort();
31 if (!global_order) {
32 return {};
33 }
34 for (const auto& i : *global_order) {
35 const auto& local_order = local_groups[i].sort();
36 if (!local_order) {
37 return {};
38 }
39 for (const auto& x : *local_order) {
40 result.emplace_back(x);
41 }
42 }
43 return result;
44 }
45
46 private:
47 class Topo {
48 public:
49 void addNode(int node) {
50 nodes_.emplace(node);
51 }
52
53 void addEdge(int from, int to) {
54 addNode(from), addNode(to);
55 in_degree_[to].emplace(from);
56 out_degree_[from].emplace(to);
57 }
58
59 unique_ptr> sort() {
60 queue q;
60
61 auto result = make_unique>();
62 for (const auto& node : nodes_) {
63 if (!in_degree_.count(node)) {
64 q.emplace(node);
65 }
66 }
67 while (!q.empty()) {
68 auto node = q.front(); q.pop();
69 result->emplace_back(node);
70 for (const auto& nei : out_degree_[node]) {
71 in_degree_[nei].erase(node);
72 if (in_degree_[nei].empty()) {
73 in_degree_.erase(nei);
74 q.emplace(nei);
75 }
76 }
77 }
78 if (result->size() < nodes_.size()) {
79 return nullptr;
80 }
81 return result;
82 }
83
84 private:
85 unordered_set nodes_;
86 unordered_map> in_degree_;
87 unordered_map> out_degree_;
88 };
89 };
********************************************

236. Sort Items by Groups Respecting


Dependencies(Python)
********************************************

1 # Time: O(n + e)
2 # Space: O(n + e)
3
4 import collections
5
6
7 class Topo(object):
8 def __init__(self):
9 self.__nodes = set()
10 self.__in_degree = collections.defaultdict(set)
11 self.__out_degree = collections.defaultdict(set)
12
13 def add_node(self, node):
14 self.__nodes.add(node)
15
16 def add_edge(self, src, dst):
17 self.add_node(src), self.add_node(dst)
18 self.__in_degree[dst].add(src)
19 self.__out_degree[src].add(dst)
20
21 def sort(self):
22 q = collections.deque()
23 result = []
24 for node in self.__nodes:
25 if node not in self.__in_degree:
26 q.append(node)
27 while q:
28 node = q.popleft()
29 result.append(node)
30 for nei in self.__out_degree[node]:
31 self.__in_degree[nei].remove(node)
32 if not self.__in_degree[nei]:
33 self.__in_degree.pop(nei)
34 q.append(nei)
35 if len(result) < len(self.__nodes):
36 return
37 return result
38
39
40 class Solution(object):
41 def sortItems(self, n, m, group, beforeItems):
42 """
43 :type n: int
44 :type m: int
45 :type group: List[int]
46 :type beforeItems: List[List[int]]
47 :rtype: List[int]
48 """
49 for i in xrange(n):
50 if group[i] == -1:
51 group[i] = m
52 m += 1
53 global_group = Topo()
54 for i in xrange(m):
55 global_group.add_node(i)
56 local_groups = collections.defaultdict(Topo)
57 for i in xrange(n):
58 local_groups[group[i]].add_node(i)
59 for i in xrange(n):
60 for j in beforeItems[i]:
60
61 if group[i] == group[j]:
62 local_groups[group[i]].add_edge(j, i)
63 else:
64 global_group.add_edge(group[j], group[i]);
65 result = []
66 global_order = global_group.sort()
67 if global_order is None:
68 return []
69 for i in global_order:
70 local_order = local_groups[i].sort();
71 if local_order is None:
72 return []
73 for x in local_order:
74 result.append(x)
75 return result
***************

237. Design Skiplist


***************

Design a Skiplist without using any built-in libraries.

A skiplist is a data structure that takes O(log(n)) time to add, erase and search. Comparing with treap and red-black tree
which has the same function and performance, the code length of Skiplist can be comparatively short and the idea behind
Skiplists is just simple linked lists.

For example, we have a Skiplist containing [30,40,50,60,70,90] and we want to add 80 and 45 into it. The Skiplist works this way:

Artyom Kalinin [CC BY-SA 3.0], via Wikimedia Commons

You can see there are many layers in the Skiplist. Each layer is a sorted linked list. With the help of the top layers, add,
erase and search can be faster than O(n). It can be proven that the average time complexity for each operation is O(log(n)) and
space complexity is O(n).

See more about Skiplist: https://en.wikipedia.org/wiki/Skip_list

Implement the Skiplist class:

Skiplist() Initializes the object of the skiplist.


bool search(int target) Returns true if the integer target exists in the Skiplist or false otherwise.
void add(int num) Inserts the value num into the SkipList.
bool erase(int num) Removes the value num from the Skiplist and returns true. If num does not exist in the Skiplist, do
nothing and return false. If there exist multiple num values, removing any one of them is fine.

Note that duplicates may exist in the Skiplist, your code needs to handle this situation.

Example 1:

Input
["Skiplist", "add", "add", "add", "search", "add", "search", "erase", "erase", "search"]
[[], [1], [2], [3], [0], [4], [1], [0], [1], [1]]
Output
[null, null, null, null, false, null, true, false, true, false]

Explanation
Skiplist skiplist = new Skiplist();
skiplist.add(1);
skiplist.add(2);
skiplist.add(3);
skiplist.search(0); // return False
skiplist.add(4);
skiplist.search(1); // return True
skiplist.erase(0); // return False, 0 is not in skiplist.
skiplist.erase(1); // return True
skiplist.search(1); // return False, 1 has already been erased.
Constraints:

0 <= num, target <= 2 * 10 4


At most 5 * 104 calls will be made to search, add, and erase.
***************

237. Design Skiplist(C++)


***************

1 // Time: O(logn) on average for each operation


2 // Space: O(n)
3
4 // see proof in references:
5 // 1. https://kunigami.blog/2012/09/25/skip-lists-in-python/
6 // 2. https://opendatastructures.org/ods-cpp/4_4_Analysis_Skiplists.html
7 // 3. https://brilliant.org/wiki/skip-lists/
8 class Skiplist {
9 private:
10 class SkipNode {
11 public:
12 SkipNode() : SkipNode(0, -1) {
13
14 }
15
16 SkipNode(int level, int num)
17 : num(num)
18 , nexts(level) {
19
20 }
21
22 int num;
23 vector nexts;
24 };
25
26 public:
27 Skiplist()
28 : gen_((random_device())())
29 , len_(0)
30 , head_(new SkipNode()) {
31
32 }
33
34 ~Skiplist() {
35 if (head_->nexts.empty()) {
36 return;
37 }
38 auto curr = head_->nexts[0];
39 while (curr) {
40 auto next = curr->nexts[0];
41 delete curr;
42 curr = next;
43 }
44 }
45
46 bool search(int target) const {
47 return find(target, find_prev_nodes(target)) != nullptr;
48 }
49
50 void add(int num) {
51 auto node = new SkipNode(random_level(), num);
52 if (head_->nexts.size() < node->nexts.size()) {
53 head_->nexts.resize(node->nexts.size());
54 }
55 auto prevs = find_prev_nodes(num);
56 for (int i = 0; i < node->nexts.size(); ++i) {
57 node->nexts[i] = prevs[i]->nexts[i];
58 prevs[i]->nexts[i] = node;
59 }
60 ++len_;
61 }
62
63 bool erase(int num) {
64 auto prevs = find_prev_nodes(num);
65 auto curr = find(num, prevs);
66 if (!curr) {
67 return false;
68 }
69 --len_;
70 for (int i = curr->nexts.size() - 1; i >= 0; --i) {
71 prevs[i]->nexts[i] = curr->nexts[i];
72 if (!head_->nexts[i]) {
73 head_->nexts.pop_back();
74 }
75 }
76 delete curr;
77 return true;
78 }
79
80 int size() const {
81 return len_;
82 }
83
84 private:
85 SkipNode *find(int num, const vector& prevs) const {
86 if (!prevs.empty()) {
87 auto candidate = prevs[0]->nexts[0];
88 if (candidate && candidate->num == num) {
89 return candidate;
90 }
91 }
92 return nullptr;
93 }
94
95 vector find_prev_nodes(int num) const {
96 vector prevs(head_->nexts.size());
97 auto curr = head_;
98 for (int i = head_->nexts.size() - 1; i >= 0; --i) {
99 while (curr->nexts[i] && curr->nexts[i]->num < num) {
100 curr = curr->nexts[i];
101 }
102 prevs[i] = curr;
103 }
104 return prevs;
105 }
106
107 int random_level() {
108 static const int P_NUMERATOR = 1;
109 static const int P_DENOMINATOR = 2; // P = 1/4 in redis implementation
110 static const int MAX_LEVEL = 32; // enough for 2^32 elements
111 int level = 1;
112 while (uniform_int_distribution{1, P_DENOMINATOR}(gen_) <= P_NUMERATOR &&
113 level < MAX_LEVEL) {
114 ++level;
115 }
116 return level;
117 }
118
119 void print_list() const {
120 for (int i = head_->nexts.size() - 1; i >= 0; --i) {
121 auto curr = head_->nexts[i];
122 cout << curr->num;
123 curr = curr->nexts[i];
124 while (curr) {
125 cout << "->" << curr->num;
126 curr = curr->nexts[i];
127 }
128 cout << endl;
129 }
130 }
131
132 default_random_engine gen_;
133 int len_;
134 SkipNode *head_;
135 };
135 };
136
137 // Time: O(logn) on average for each operation
138 // Space: O(n)
139 // smart pointer version (a little bit slower)
140 class Skiplist2 {
141 private:
142 class SkipNode {
143 public:
144 SkipNode() : SkipNode(0, -1) {
145
146 }
147
148 SkipNode(int level, int num)
149 : num(num)
150 , nexts(level) {
151
152 }
153
154 int num;
155 vector> nexts;
156 };
157
158 public:
159 Skiplist2()
160 : gen_((random_device())())
161 , len_(0)
162 , head_(make_shared()) {
163
164 }
165
166 bool search(int target) const {
167 return find(target, find_prev_nodes(target)) != nullptr;
168 }
169
170 void add(int num) {
171 auto node = make_shared(random_level(), num);
172 if (head_->nexts.size() < node->nexts.size()) {
173 head_->nexts.resize(node->nexts.size());
174 }
175 auto prevs = find_prev_nodes(num);
176 for (int i = 0; i < node->nexts.size(); ++i) {
177 node->nexts[i] = prevs[i]->nexts[i];
178 prevs[i]->nexts[i] = node;
179 }
180 ++len_;
181 }
182
183 bool erase(int num) {
184 auto prevs = find_prev_nodes(num);
185 auto curr = find(num, prevs);
186 if (!curr) {
187 return false;
188 }
189 --len_;
190 for (int i = curr->nexts.size() - 1; i >= 0; --i) {
191 prevs[i]->nexts[i] = curr->nexts[i];
192 if (!head_->nexts[i]) {
193 head_->nexts.pop_back();
194 }
195 }
196 return true;
197 }
198
199 int size() const {
200 return len_;
201 }
202
203 private:
204 shared_ptr find(int num, const vector>& prevs) const {
205 if (!prevs.empty()) {
206 auto candidate = prevs[0]->nexts[0];
207 if (candidate && candidate->num == num) {
208 return candidate;
208 return candidate;
209 }
210 }
211 return nullptr;
212 }
213
214 vector> find_prev_nodes(int num) const {
215 vector> prevs(head_->nexts.size());
216 auto curr = head_;
217 for (int i = head_->nexts.size() - 1; i >= 0; --i) {
218 while (curr->nexts[i] && curr->nexts[i]->num < num) {
219 curr = curr->nexts[i];
220 }
221 prevs[i] = curr;
222 }
223 return prevs;
224 }
225
226 int random_level() {
227 static const int P_NUMERATOR = 1;
228 static const int P_DENOMINATOR = 2; // P = 1/4 in redis implementation
229 static const int MAX_LEVEL = 32; // enough for 2^32 elements
230 int level = 1;
231 while (uniform_int_distribution{1, P_DENOMINATOR}(gen_) <= P_NUMERATOR &&
232 level < MAX_LEVEL) {
233 ++level;
234 }
235 return level;
236 }
237
238 void print_list() const {
239 for (int i = head_->nexts.size() - 1; i >= 0; --i) {
240 auto curr = head_->nexts[i];
241 cout << curr->num;
242 curr = curr->nexts[i];
243 while (curr) {
244 cout << "->" << curr->num;
245 curr = curr->nexts[i];
246 }
247 cout << endl;
248 }
249 }
250
251 default_random_engine gen_;
252 int len_;
253 shared_ptr head_;
254 };
***************

237. Design Skiplist(Python)


***************

1 # Time: O(logn) on average for each operation


2 # Space: O(n)
3
4 # see proof in references:
5 # 1. https://kunigami.blog/2012/09/25/skip-lists-in-python/
6 # 2. https://opendatastructures.org/ods-cpp/4_4_Analysis_Skiplists.html
7 # 3. https://brilliant.org/wiki/skip-lists/
8 import random
9
10
11 class SkipNode(object):
12 def __init__(self, level=0, num=None):
13 self.num = num
14 self.nexts = [None]*level
15
16
17 class Skiplist(object):
18 P_NUMERATOR, P_DENOMINATOR = 1, 2 # P = 1/4 in redis implementation
19 MAX_LEVEL = 32 # enough for 2^32 elements
20
21 def __init__(self):
22 self.__head = SkipNode()
23 self.__len = 0
24
25 def search(self, target):
26 """
27 :type target: int
28 :rtype: bool
29 """
30 return True if self.__find(target, self.__find_prev_nodes(target)) else False
31
32 def add(self, num):
33 """
34 :type num: int
35 :rtype: None
36 """
37 node = SkipNode(self.__random_level(), num)
38 if len(self.__head.nexts) < len(node.nexts):
39 self.__head.nexts.extend([None]*(len(node.nexts)-len(self.__head.nexts)))
40 prevs = self.__find_prev_nodes(num)
41 for i in xrange(len(node.nexts)):
42 node.nexts[i] = prevs[i].nexts[i]
43 prevs[i].nexts[i] = node
44 self.__len += 1
45
46 def erase(self, num):
47 """
48 :type num: int
49 :rtype: bool
50 """
51 prevs = self.__find_prev_nodes(num)
52 curr = self.__find(num, prevs)
53 if not curr:
54 return False
55 self.__len -= 1
56 for i in reversed(xrange(len(curr.nexts))):
57 prevs[i].nexts[i] = curr.nexts[i]
58 if not self.__head.nexts[i]:
59 self.__head.nexts.pop()
60 return True
61
62 def __find(self, num, prevs):
63 if prevs:
64 candidate = prevs[0].nexts[0]
65 if candidate and candidate.num == num:
66 return candidate
67 return None
68
69 def __find_prev_nodes(self, num):
70 prevs = [None]*len(self.__head.nexts)
71 curr = self.__head
72 for i in reversed(xrange(len(self.__head.nexts))):
73 while curr.nexts[i] and curr.nexts[i].num < num:
74 curr = curr.nexts[i]
75 prevs[i] = curr
76 return prevs
77
78 def __random_level(self):
79 level = 1
80 while random.randint(1, Skiplist.P_DENOMINATOR) <= Skiplist.P_NUMERATOR and \
81 level < Skiplist.MAX_LEVEL:
82 level += 1
83 return level
84
85 def __len__(self):
86 return self.__len
87
88 def __str__(self):
89 result = []
90 for i in reversed(xrange(len(self.__head.nexts))):
91 result.append([])
92 curr = self.__head.nexts[i]
93 while curr:
94 result[-1].append(str(curr.num))
95 curr = curr.nexts[i]
96 return "\n".join(map(lambda x: "->".join(x), result))
********************************************

238. Minimum Moves to Reach Target with Rotations


********************************************

In an n*n grid, there is a snake that spans 2 cells and starts moving from the top left corner at(0, 0) and (0, 1) . The grid has
empty cells represented by zeros and blocked cells represented by ones. The snake wants to reach the lower right corner
at (n-1, n-2) and (n-1, n-1) .

In one move the snake can:

Move one cell to the right if there are no blocked cells there. This move keeps the horizontal/vertical position of the
snake as it is.
Move down one cell if there are no blocked cells there. This move keeps the horizontal/vertical position of the snake
as it is.
Rotate clockwise if it's in a horizontal position and the two cells under it are both empty. In that case the snake moves
from (r, c) and (r, c+1) to (r, c) and (r+1, c) .

Rotate counterclockwise if it's in a vertical position and the two cells to its right are both empty. In that case the snake
moves from (r, c) and (r+1, c) to (r, c) and (r, c+1) .

Return the minimum number of moves to reach the target.

If there is no way to reach the target, return-1.

Example 1:
Input: grid = [[0,0,0,0,0,1],
[1,1,0,0,1,0],
[0,0,0,0,1,1],
[0,0,1,0,1,0],
[0,1,1,0,0,0],
[0,1,1,0,0,0]]
Output: 11
Explanation:
One possible solution is [right, right, rotate clockwise, right, down, down, down, down, rotate counterclockwise, right, down].

Example 2:

Input: grid = [[0,0,1,1,1,1],


[0,0,0,0,1,1],
[1,1,0,0,0,1],
[1,1,1,0,0,1],
[1,1,1,0,0,1],
[1,1,1,0,0,0]]
Output: 9

Constraints:

2 <= n <= 100


0 <= grid[i][j] <= 1
It is guaranteed that the snake starts at empty cells.
********************************************

238. Minimum Moves to Reach Target with


Rotations(C++)
********************************************
1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 private:
6 template
7 struct TupleHash {
8 size_t operator()(const tuple& p) const {
9 size_t seed = 0;
10 A a; B b; C c;
11 tie(a, b, c) = p;
12 seed ^= std::hash{}(a) + 0x9e3779b9 + (seed<<6) + (seed>>2);
13 seed ^= std::hash{}(b) + 0x9e3779b9 + (seed<<6) + (seed>>2);
14 seed ^= std::hash{}(c) + 0x9e3779b9 + (seed<<6) + (seed>>2);
15 return seed;
16 }
17 };
18
19 public:
20 int minimumMoves(vector>& grid) {
21 int level = 0;
22 vector> q = {{0, 0, false}};
23 unordered_set, TupleHash> lookup;
24 while (!q.empty()) {
25 vector> next_q;
26 for (const auto& [r, c, is_vertical] : q) {
27 if (lookup.count(make_tuple(r, c, is_vertical))) {
28 continue;
29 }
30 if (make_tuple(r, c, is_vertical) ==
31 make_tuple(grid.size() - 1, grid.size() - 2, false)) {
32 return level;
33 }
34 lookup.emplace(r, c, is_vertical);
35 if (!is_vertical) {
36 if (c + 2 != grid[0].size() && grid[r][c + 2] == 0) {
37 next_q.emplace_back(r, c + 1, is_vertical);
38 }
39 if (r + 1 != grid.size() &&
40 grid[r + 1][c] == 0 && grid[r + 1][c + 1] == 0) {
41 next_q.emplace_back(r + 1, c, is_vertical);
42 next_q.emplace_back(r, c, !is_vertical);
43 }
44 } else {
45 if (r + 2 != grid.size() && grid[r + 2][c] == 0) {
46 next_q.emplace_back(r + 1, c, is_vertical);
47 }
48 if (c + 1 != grid[0].size() &&
49 grid[r][c + 1] == 0 && grid[r + 1][c + 1] == 0) {
50 next_q.emplace_back(r, c + 1, is_vertical);
51 next_q.emplace_back(r, c, !is_vertical);
52 }
53 }
54 }
55 q = move(next_q);
56 ++level;
57 }
58 return -1;
59 }
60 };
********************************************

238. Minimum Moves to Reach Target with


Rotations(Python)
********************************************

1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 def minimumMoves(self, grid):
6 """
7 :type grid: List[List[int]]
8 :rtype: int
9 """
10 level, q, lookup = 0, [(0, 0, False)], set()
11 while q:
12 next_q = []
13 for r, c, is_vertical in q:
14 if (r, c, is_vertical) in lookup:
15 continue
16 if (r, c, is_vertical) == (len(grid)-1, len(grid)-2, False):
17 return level
18 lookup.add((r, c, is_vertical))
19 if not is_vertical:
20 if c+2 != len(grid[0]) and grid[r][c+2] == 0:
21 next_q.append((r, c+1, is_vertical))
22 if r+1 != len(grid) and grid[r+1][c] == 0 and grid[r+1][c+1] == 0:
23 next_q.append((r+1, c, is_vertical))
24 next_q.append((r, c, not is_vertical))
25 else:
26 if r+2 != len(grid) and grid[r+2][c] == 0:
27 next_q.append((r+1, c, is_vertical))
28 if c+1 != len(grid) and grid[r][c+1] == 0 and grid[r+1][c+1] == 0:
29 next_q.append((r, c+1, is_vertical))
30 next_q.append((r, c, not is_vertical))
31 q = next_q
32 level += 1
33 return -1
********************

239. Valid Palindrome III


********************

Given a string s and an integer k , return true if s is a k -palindrome.

A string is k -palindrome if it can be transformed into a palindrome by removing at mostk characters from it.

Example 1:

Input: s = "abcdeca", k = 2
Output: true
Explanation: Remove 'b' and 'e' characters.

Example 2:

Input: s = "abbababa", k = 1
Output: true

Constraints:

1 <= s.length <= 1000


s consists of only lowercase English letters.
1 <= k <= s.length
********************

239. Valid Palindrome III(C++)


********************

1 // Time: O(n^2)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 bool isValidPalindrome(string s, int k) {
7 if (s == string(s.rbegin(), s.rend())) { // optional, to optimize special case
8 return true;
9 }
10
11 vector> dp(2, vector(s.size(), 1));
12 for (int i = s.length() - 2; i >= 0; --i) {
13 for (int j = i + 1; j < s.length(); ++j) {
14 if (s[i] == s[j]) {
15 dp[i % 2][j] = (i + 1 <= j - 1) ? 2 + dp[(i + 1) % 2][j - 1] : 2;
16 } else {
17 dp[i % 2][j] = max(dp[(i + 1) % 2][j], dp[i % 2][j - 1]);
18 }
19 }
20 }
21 return s.length() <= k +dp[0][s.length() - 1];
22 }
23 };
********************

239. Valid Palindrome III(Python)


********************

1 # Time: O(n^2)
2 # Space: O(n)
3
4 class Solution(object):
5 def isValidPalindrome(self, s, k):
6 """
7 :type s: str
8 :type k: int
9 :rtype: bool
10 """
11 if s == s[::-1]: # optional, to optimize special case
12 return True
13
14 dp = [[1] * len(s) for _ in xrange(2)]
15 for i in reversed(xrange(len(s))):
16 for j in xrange(i+1, len(s)):
17 if s[i] == s[j]:
18 dp[i%2][j] = 2 + dp[(i+1)%2][j-1] if i+1 <= j-1 else 2
19 else:
20 dp[i%2][j] = max(dp[(i+1)%2][j], dp[i%2][j-1])
21 return len(s) <= k + dp[0][-1]
************************

240. Count Vowels Permutation


************************

Given an integer n, your task is to count how many strings of lengthn can be formed under the following rules:

Each character is a lower case vowel ('a', 'e', 'i', 'o', 'u')
Each vowel 'a' may only be followed by an 'e'.
Each vowel 'e' may only be followed by an 'a' or an 'i'.
Each vowel 'i' may not be followed by another 'i'.
Each vowel 'o' may only be followed by an 'i' or a 'u'.
Each vowel 'u' may only be followed by an 'a'.

Since the answer may be too large, return it modulo10^9 + 7.

Example 1:

Input: n = 1
Output: 5
Explanation: All possible strings are: "a", "e", "i" , "o" and "u".

Example 2:

Input: n = 2
Output: 10
Explanation: All possible strings are: "ae", "ea", "ei", "ia", "ie", "io", "iu", "oi", "ou" and "ua".

Example 3:

Input: n = 5
Output: 68

Constraints:

1 <= n <= 2 * 10^4


************************

240. Count Vowels Permutation(C++)


************************

1 // Time: O(logn)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int countVowelPermutation(int n) {
7 vector> T = {{0, 1, 1, 0, 1},
8 {1, 0, 1, 0, 0},
9 {0, 1, 0, 1, 0},
10 {0, 0, 1, 0, 0},
11 {0, 0, 1, 1, 0}};
12
13 const auto& result = matrixExpo(T, n - 1);
14 return accumulate(result.cbegin(), result.cend(), 0,
15 [&](int total, const vector& row) {
16 return (total +
17 accumulate(row.cbegin(), row.cend(), 0,
18 [&](int sum, int val) {
19 return (sum + val) % MOD;
20 })) % MOD;
21 });
22 }
23
24 private:
25 vector> matrixExpo(const vector>& A, int pow) {
26 vector> result(A.size(), vector(A.size()));
27 vector> A_exp(A);
28 for (int i = 0; i < A.size(); ++i) {
29 result[i][i] = 1;
30 }
31 while (pow) {
32 if (pow % 2 == 1) {
33 result = matrixMult(result, A_exp);
34 }
35 A_exp = matrixMult(A_exp, A_exp);
36 pow /= 2;
37 }
38 return result;
39 }
40
41 vector> matrixMult(const vector>& A, const vector>& B) {
42 vector> result(A.size(), vector(B[0].size()));
43 for (int i = 0; i < A.size(); ++i) {
44 for (int j = 0; j < B[0].size(); ++j) {
45 int64_t entry = 0;
46 for (int k = 0; k < B.size(); ++k) {
47 entry = (static_cast(A[i][k]) * B[k][j] % MOD + entry) % MOD;
48 }
49 result[i][j] = static_cast(entry);
50 }
51 }
52 return result;
53 }
54 const int MOD = 1e9 + 7;
55 };
56
57 // Time: O(n)
58 // Space: O(1)
59 class Solution2 {
60 public:
61 int countVowelPermutation(int n) {
62 int a = 1, e = 1, i = 1, o = 1, u = 1;
63 for (int x = 1; x < n; ++x) {
64 tie(a, e, i, o, u) = make_tuple(((e + i) % MOD + u) % MOD,
65 (a + i) % MOD,
66 (e + o) % MOD,
67 i,
68 (i + o) % MOD);
69 }
70 return (((a + e) % MOD + (i + o) % MOD) % MOD + u) % MOD;
71 }
72
73 private:
74 const int MOD = 1e9 + 7;
75 };
************************

240. Count Vowels Permutation(Python)


************************

1 # Time: O(logn)
2 # Space: O(1)
3
4 import itertools
5
6
7 class Solution(object):
8 def countVowelPermutation(self, n):
9 """
10 :type n: int
11 :rtype: int
12 """
13 def matrix_expo(A, K):
14 result = [[int(i==j) for j in xrange(len(A))] \
15 for i in xrange(len(A))]
16 while K:
17 if K % 2:
18 result = matrix_mult(result, A)
19 A = matrix_mult(A, A)
20 K /= 2
21 return result
22
23 def matrix_mult(A, B):
24 ZB = zip(*B)
25 return [[sum(a*b for a, b in itertools.izip(row, col)) % MOD \
26 for col in ZB] for row in A]
27
28 MOD = 10**9 + 7
29 T = [[0, 1, 1, 0, 1],
30 [1, 0, 1, 0, 0],
31 [0, 1, 0, 1, 0],
32 [0, 0, 1, 0, 0],
33 [0, 0, 1, 1, 0]]
34 return sum(map(sum, matrix_expo(T, n-1))) % MOD
35
36
37 # Time: O(n)
38 # Space: O(1)
39 class Solution2(object):
40 def countVowelPermutation(self, n):
41 """
42 :type n: int
43 :rtype: int
44 """
45 MOD = 10**9 + 7
46 a, e, i, o, u = 1, 1, 1, 1, 1
47 for _ in xrange(1, n):
48 a, e, i, o, u = (e+i+u) % MOD, (a+i) % MOD, (e+o) % MOD, i, (i+o) % MOD
49 return (a+e+i+o+u) % MOD
***********************

241. Maximum Equal Frequency


***********************

Given an array nums of positive integers, return the longest possible length of an array prefix ofnums, such that it is possible
to remove exactly one element from this prefix so that every number that has appeared in it will have the same number of
occurrences.

If after removing one element there are no remaining elements, it's still considered that every appeared number has the
same number of ocurrences (0).

Example 1:

Input: nums = [2,2,1,1,5,3,3,5]


Output: 7
Explanation: For the subarray [2,2,1,1,5,3,3] of length 7, if we remove nums[4]=5, we will get [2,2,1,1,3,3], so that each number will appear

Example 2:

Input: nums = [1,1,1,2,2,2,3,3,3,4,4,4,5]


Output: 13

Example 3:

Input: nums = [1,1,1,2,2,2]


Output: 5

Example 4:

Input: nums = [10,2,8,9,3,8,1,5,2,3,7,6]


Output: 8

Constraints:

2 <= nums.length <= 10^5


1 <= nums[i] <= 10^5
***********************

241. Maximum Equal Frequency(C++)


***********************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int maxEqualFreq(vector& nums) {
7 int result = 0;
8 unordered_map count;
9 vector freq(nums.size() + 1);
10 for (int i = 0; i < nums.size(); ++i) {
11 --freq[count[nums[i]]];
12 ++freq[count[nums[i]] + 1];
13 const auto c = ++count[nums[i]];
14 if (freq[c] * c == (i + 1) && (i + 1) < nums.size()) {
15 result = (i + 1) + 1;
16 }
17 const auto& remain = (i + 1) - freq[c] * c;
18 if (freq[remain] == 1 && (remain == 1 || remain == c + 1)) {
19 result = (i + 1);
20 }
21 }
22 return result;
23 }
24 };
***********************

241. Maximum Equal Frequency(Python)


***********************

1 # Time: O(n)
2 # Space: O(n)
3
4 import collections
5
6
7 class Solution(object):
8 def maxEqualFreq(self, nums):
9 """
10 :type nums: List[int]
11 :rtype: int
12 """
13 result = 0
14 count = collections.Counter()
15 freq = [0 for _ in xrange(len(nums)+1)]
16 for i, n in enumerate(nums, 1):
17 freq[count[n]] -= 1
18 freq[count[n]+1] += 1
19 count[n] += 1
20 c = count[n]
21 if freq[c]*c == i and i < len(nums):
22 result = i+1
23 remain = i-freq[c]*c
24 if freq[remain] == 1 and remain in [1, c+1]:
25 result = i
26 return result
***********************

242. Report Contiguous Dates


***********************

Table: Failed

+--------------+---------+
| Column Name | Type |
+--------------+---------+
| fail_date | date |
+--------------+---------+
Primary key for this table is fail_date.
Failed table contains the days of failed tasks.

Table: Succeeded

+--------------+---------+
| Column Name | Type |
+--------------+---------+
| success_date | date |
+--------------+---------+
Primary key for this table is success_date.
Succeeded table contains the days of succeeded tasks.

A system is running one task every day. Every task is independent of the previous tasks. The tasks can fail or succeed.

Write an SQL query to generate a report of period_state for each continuous interval of days in the period from2019-01-01 to
2019-12-31.

is 'failed' if tasks in this interval failed or 'succeeded' if tasks in this interval succeeded. Interval of days are
period_state
retrieved as start_date and end_date.

Order result by start_date.

The query result format is in the following example:


Failed table:
+-------------------+
| fail_date |
+-------------------+
| 2018-12-28 |
| 2018-12-29 |
| 2019-01-04 |
| 2019-01-05 |
+-------------------+

Succeeded table:
+-------------------+
| success_date |
+-------------------+
| 2018-12-30 |
| 2018-12-31 |
| 2019-01-01 |
| 2019-01-02 |
| 2019-01-03 |
| 2019-01-06 |
+-------------------+

Result table:
+--------------+--------------+--------------+
| period_state | start_date | end_date |
+--------------+--------------+--------------+
| succeeded | 2019-01-01 | 2019-01-03 |
| failed | 2019-01-04 | 2019-01-05 |
| succeeded | 2019-01-06 | 2019-01-06 |
+--------------+--------------+--------------+

The report ignored the system state in 2018 as we care about the system in the period 2019-01-01 to 2019-12-31.
From 2019-01-01 to 2019-01-03 all tasks succeeded and the system state was "succeeded".
From 2019-01-04 to 2019-01-05 all tasks failed and system state was "failed".
From 2019-01-06 to 2019-01-06 all tasks succeeded and system state was "succeeded".
***********************

242. Report Contiguous Dates(Shell)


***********************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 SELECT state AS period_state,
5 Min(date) AS start_date,
6 Max(date) AS end_date
7 FROM (SELECT state,
8 date,
9 @rank := CASE
10 WHEN @prev = state THEN @rank
11 ELSE @rank + 1
12 end AS rank,
13 @prev := state AS prev
14 FROM (SELECT *
15 FROM (SELECT fail_date AS date,
16 "failed" AS state
17 FROM failed
18 UNION ALL
19 SELECT success_date AS date,
20 "succeeded" AS state
21 FROM succeeded) a
22 WHERE date BETWEEN '2019-01-01' AND '2019-12-31'
23 ORDER BY date ASC) b,
24 (SELECT @rank := 0,
25 @prev := "unknown") c) d
26 GROUP BY d.rank
27 ORDER BY start_date ASC
****************

243. Divide Chocolate


****************

You have one chocolate bar that consists of some chunks. Each chunk has its own sweetness given by the arraysweetness.

You want to share the chocolate with yourk friends so you start cutting the chocolate bar intok + 1 pieces using k cuts, each
piece consists of some consecutive chunks.

Being generous, you will eat the piece with theminimum total sweetness and give the other pieces to your friends.

Find the maximum total sweetness of the piece you can get by cutting the chocolate bar optimally.

Example 1:

Input: sweetness = [1,2,3,4,5,6,7,8,9], k = 5


Output: 6
Explanation: You can divide the chocolate to [1,2,3], [4,5], [6], [7], [8], [9]

Example 2:

Input: sweetness = [5,6,7,8,9,1,2,3,4], k = 8


Output: 1
Explanation: There is only one way to cut the bar into 9 pieces.

Example 3:

Input: sweetness = [1,2,2,1,2,2,1,2,2], k = 2


Output: 5
Explanation: You can divide the chocolate to [1,2,2], [1,2,2], [1,2,2]

Constraints:

0 <= k < sweetness.length <= 10 4


1 <= sweetness[i] <= 105
****************

243. Divide Chocolate(C++)


****************

1 // Time: O(nlogn)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int maximizeSweetness(vector& sweetness, int K) {
7 int left = *min_element(sweetness.cbegin(), sweetness.cend());
8 int right = accumulate(sweetness.cbegin(), sweetness.cend(), 0) / (K + 1);
9 while (left <= right) {
10 const auto& mid = left + (right - left) / 2;
11 if (!check(sweetness, K, mid)) {
12 right = mid - 1;
13 } else {
14 left = mid + 1;
15 }
16 }
17 return right;
18 }
19
20 private:
21 bool check(const vector& sweetness, int K, int x) {
22 int curr = 0, cuts = 0;
23 for (const auto& s : sweetness) {
24 curr += s;
25 if (curr >= x) {
26 ++cuts;
27 curr = 0;
28 }
29 }
30 return cuts >= K + 1;
31 }
32 };
****************

243. Divide Chocolate(Python)


****************

1 # Time: O(nlogn)
2 # Space: O(1)
3
4 class Solution(object):
5 def maximizeSweetness(self, sweetness, K):
6 """
7 :type sweetness: List[int]
8 :type K: int
9 :rtype: int
10 """
11 def check(sweetness, K, x):
12 curr, cuts = 0, 0
13 for s in sweetness:
14 curr += s
15 if curr >= x:
16 cuts += 1
17 curr = 0
18 return cuts >= K+1
19
20 left, right = min(sweetness), sum(sweetness)//(K+1)
21 while left <= right:
22 mid = left + (right-left)//2
23 if not check(sweetness, K, mid):
24 right = mid-1
25 else:
26 left = mid+1
27 return right
********************************

244. Maximum Profit in Job Scheduling


********************************

We have n jobs, where every job is scheduled to be done from startTime[i] to endTime[i], obtaining a profit of profit[i].

You're given the startTime, endTime and profit arrays, return the maximum profit you can take such that there are no two jobs in
the subset with overlapping time range.

If you choose a job that ends at time X you will be able to start another job that starts at timeX.

Example 1:

Input: startTime = [1,2,3,3], endTime = [3,4,5,6], profit = [50,10,40,70]


Output: 120
Explanation: The subset chosen is the first and fourth job.
Time range [1-3]+[3-6] , we get profit of 120 = 50 + 70.

Example 2:

Input: startTime = [1,2,3,4,6], endTime = [3,5,10,6,9], profit = [20,20,100,70,60]


Output: 150
Explanation: The subset chosen is the first, fourth and fifth job.
Profit obtained 150 = 20 + 70 + 60.

Example 3:

Input: startTime = [1,1,1], endTime = [2,3,4], profit = [5,6,4]


Output: 6

Constraints:
1 <= startTime.length == endTime.length == profit.length <= 5 * 10 4
1 <= startTime[i] < endTime[i] <= 10 9
1 <= profit[i] <= 10 4
********************************

244. Maximum Profit in Job Scheduling(C++)


********************************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int jobScheduling(vector& startTime, vector& endTime, vector& profit) {
7 vector> jobs;
8 for (int i = 0; i < startTime.size(); ++i) {
9 jobs.emplace_back(endTime[i], startTime[i], profit[i]);
10 }
11 sort(jobs.begin(), jobs.end());
12 vector> dp = {{0, 0}};
13 for (const auto& [e, s, p] : jobs) {
14 const auto& it = prev(upper_bound(dp.cbegin(),
15 dp.cend(),
16 make_pair(s + 1, 0)));
17 if (it->second + p > dp.back().second) {
18 dp.emplace_back(e, it->second + p);
19 }
20 }
21 return dp.back().second;
22 }
23 };
24
25
26 // Time: O(nlogn)
27 // Space: O(n)
28 class Solution2 {
29 public:
30 int jobScheduling(vector& startTime, vector& endTime, vector& profit) {
31 vector> min_heap;
32 for (int i = 0; i < startTime.size(); ++i) {
33 min_heap.emplace_back(startTime[i], endTime[i], profit[i]);
34 }
35 make_heap(min_heap.begin(), min_heap.end(), greater<>());
36 int result = 0;
37 while (!min_heap.empty()) {
38 const auto [s, e, p] = min_heap.front();
39 pop_heap(begin(min_heap), end(min_heap), greater<>()); min_heap.pop_back();
40 if (s < e) {
41 min_heap.emplace_back(e, s, result + p); push_heap(begin(min_heap), end(min_heap), greater<>());
42 } else {
43 result = max(result, p);
44 }
45 }
46 return result;
47 }
48 };
********************************

244. Maximum Profit in Job Scheduling(Python)


********************************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 import itertools
5 import bisect
6
7
8 class Solution(object):
9 def jobScheduling(self, startTime, endTime, profit):
10 """
11 :type startTime: List[int]
12 :type endTime: List[int]
13 :type profit: List[int]
14 :rtype: int
15 """
16 jobs = sorted(itertools.izip(endTime, startTime, profit))
17 dp = [(0, 0)]
18 for e, s, p in jobs:
19 i = bisect.bisect_right(dp, (s+1, 0))-1
20 if dp[i][1]+p > dp[-1][1]:
21 dp.append((e, dp[i][1]+p))
22 return dp[-1][1]
23
24
25 # Time: O(nlogn)
26 # Space: O(n)
27 import heapq
28 class Solution(object):
29 def jobScheduling(self, startTime, endTime, profit):
30 """
31 :type startTime: List[int]
32 :type endTime: List[int]
33 :type profit: List[int]
34 :rtype: int
35 """
36 min_heap = zip(startTime, endTime, profit)
37 heapq.heapify(min_heap)
38 result = 0
39 while min_heap:
40 s, e, p = heapq.heappop(min_heap)
41 if s < e:
42 heapq.heappush(min_heap, (e, s, result+p))
43 else:
44 result = max(result, p)
45 return result
******************************************

245. Tiling a Rectangle with the Fewest Squares


******************************************

Given a rectangle of size n x m, find the minimum number of integer-sided squares that tile the rectangle.

Example 1:

Input: n = 2, m = 3
Output: 3
Explanation: 3 squares are necessary to cover the rectangle.
2 (squares of 1x1)
1 (square of 2x2)

Example 2:

Input: n = 5, m = 8
Output: 5

Example 3:

Input: n = 11, m = 13
Output: 6

Constraints:

1 <= n <= 13
1 <= m <= 13
******************************************

245. Tiling a Rectangle with the Fewest Squares(C++)


******************************************

1 // Time: O(n^2 * m^2 * m^(n * m)), given m < n


2 // Space: O(n * m)
3
4 class Solution {
5 public:
6 int tilingRectangle(int n, int m) {
7 if (m > n) {
8 return tilingRectangle(m, n);
9 }
10 vector> board(n, vector(m));
11 int result = numeric_limits::max();
12 backtracking(&board, 0, &result);
13 return result;
14 }
15
16 private:
17 pair find_next(const vector>& board) {
18 for (int i = 0; i < board.size(); ++i) {
19 for (int j = 0; j < board[0].size(); ++j) {
20 if (!board[i][j]) {
21 return {i, j};
22 }
23 }
24 }
25 return {-1, -1};
26 }
27
28 int find_max_length(const vector>& board, int i, int j) {
29 int max_length = 1;
30 while (i + max_length - 1 < board.size() &&
31 j + max_length - 1 < board[0].size()) {
32 for (int r = i; r < i + max_length - 1; ++r) {
33 if (board[r][j + max_length - 1]) {
34 return max_length - 1;
35 }
36 }
37 for (int c = j; c < j + max_length; ++c) {
38 if (board[i + max_length - 1][c]) {
39 return max_length - 1;
40 }
41 }
42 ++max_length;
43 }
44 return max_length - 1;
45 }
46
47 void fill(vector> *board,
48 int i, int j, int length, int val) {
49 for (int r = i; r < i + length; ++r) {
50 for (int c = j; c < j + length; ++c) {
51 (*board)[r][c] = val;
52 }
53 }
54 }
55
56 void backtracking(vector> *board,
57 int count, int *result) {
58 if (count >= *result) { // pruning
59 return;
60 }
61 const auto& [i, j] = find_next(*board);
62 if (i == -1 && j == -1) { // finished
63 *result = min(*result, count);
64 return;
65 }
66 const auto& max_length = find_max_length(*board, i, j);
67 for (int k = max_length; k >= 1; --k) {
68 fill(board, i, j, k, 1);
69 backtracking(board, count + 1, result);
70 fill(board, i, j, k, 0);
71 }
72 }
73 };
******************************************

245. Tiling a Rectangle with the Fewest Squares(Python)


******************************************

1 # Time: O(n^2 * m^2 * m^(n * m)), given m < n


2 # Space: O(n * m)
3
4 class Solution(object):
5 def tilingRectangle(self, n, m):
6 """
7 :type n: int
8 :type m: int
9 :rtype: int
10 """
11 def find_next(board):
12 for i in xrange(len(board)):
13 for j in xrange(len(board[0])):
14 if not board[i][j]:
15 return i, j
16 return -1, -1
17
18 def find_max_length(board, i, j):
19 max_length = 1
20 while i+max_length-1 < len(board) and \
21 j+max_length-1 < len(board[0]):
22 for r in xrange(i, i+max_length-1):
23 if board[r][j+max_length-1]:
24 return max_length-1
25 for c in xrange(j, j+max_length):
26 if board[i+max_length-1][c]:
27 return max_length-1
28 max_length += 1
29 return max_length-1
30
31 def fill(board, i, j, length, val):
32 for r in xrange(i, i+length):
33 for c in xrange(j, j+length):
34 board[r][c] = val
35
36 def backtracking(board, count, result):
37 if count >= result[0]: # pruning
38 return
39 i, j = find_next(board)
40 if (i, j) == (-1, -1): # finished
41 result[0] = min(result[0], count)
42 return
43 max_length = find_max_length(board, i, j)
44 for k in reversed(xrange(1, max_length+1)):
45 fill(board, i, j, k, 1)
46 backtracking(board, count+1, result)
47 fill(board, i, j, k, 0)
48
49 if m > n:
50 return self.tilingRectangle(m, n)
51 board = [[0]*m for _ in xrange(n)]
52 result = [float("inf")]
53 backtracking(board, 0, result)
54 return result[0]
******************

246. Palindrome Removal


******************

Given an integer array arr, in one move you can select a palindromic subarray arr[i], arr[i+1], ..., arr[j] where i <= j , and remove
that subarray from the given array. Note that after removing a subarray, the elements on the left and on the right of that
subarray move to fill the gap left by the removal.

Return the minimum number of moves needed to remove all numbers from the array.

Example 1:

Input: arr = [1,2]


Output: 2

Example 2:

Input: arr = [1,3,4,1,5]


Output: 3
Explanation: Remove [4] then remove [1,3,1] then remove [5].

Constraints:

1 <= arr.length <= 100


1 <= arr[i] <= 20
******************

246. Palindrome Removal(C++)


******************

1 // Time: O(n^3)
2 // Space: O(n^2)
3
4 class Solution {
5 public:
6 int minimumMoves(vector& arr) {
7 vector> dp(arr.size() + 1, vector(arr.size()));
8 for (int l = 1; l <= arr.size(); ++l) {
9 for (int i = 0; i + l - 1 < arr.size(); ++i) {
10 int j = i + l - 1;
11 if (l == 1) {
12 dp[i][j] = 1;
13 } else {
14 dp[i][j] = 1 + dp[i + 1][j];
15 if (arr[i] == arr[i + 1]) {
16 dp[i][j] = min(dp[i][j], 1 + dp[i + 2][j]);
17 }
18 for (int k = i + 2; k <= j; ++k) {
19 if (arr[i] == arr[k]) {
20 dp[i][j] = min(dp[i][j], dp[i + 1][k - 1] + dp[k + 1][j]);
21 }
22 }
23 }
24 }
25 }
26 return dp[0][arr.size() - 1];
27 }
28 };
******************

246. Palindrome Removal(Python)


******************

1 # Time: O(n^3)
2 # Space: O(n^2)
3
4 class Solution(object):
5 def minimumMoves(self, arr):
6 """
7 :type arr: List[int]
8 :rtype: int
9 """
10 dp = [[0 for _ in xrange(len(arr)+1)] for _ in xrange(len(arr)+1)]
11 for l in xrange(1, len(arr)+1):
12 for i in xrange(len(arr)-l+1):
13 j = i+l-1
14 if l == 1:
15 dp[i][j] = 1
16 else:
17 dp[i][j] = 1+dp[i+1][j]
18 if arr[i] == arr[i+1]:
19 dp[i][j] = min(dp[i][j], 1+dp[i+2][j])
20 for k in xrange(i+2, j+1):
21 if arr[i] == arr[k]:
22 dp[i][j] = min(dp[i][j], dp[i+1][k-1] + dp[k+1][j])
23 return dp[0][len(arr)-1]
***************************

247. Check If It Is a Good Array


***************************

Given an array nums of positive integers. Your task is to select some subset ofnums, multiply each element by an integer and
add all these numbers. The array is said to be good if you can obtain a sum of 1 from the array by any possible subset and
multiplicand.

Return True if the array is good otherwise return False.

Example 1:

Input: nums = [12,5,7,23]


Output: true
Explanation: Pick numbers 5 and 7.
5*3 + 7*(-2) = 1

Example 2:

Input: nums = [29,6,10]


Output: true
Explanation: Pick numbers 29, 6 and 10.
29*1 + 6*(-3) + 10*(-1) = 1

Example 3:

Input: nums = [3,6]


Output: false

Constraints:

1 <= nums.length <= 10^5


1 <= nums[i] <= 10^9
***************************

247. Check If It Is a Good Array(C++)


***************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 bool isGoodArray(vector& nums) {
7 // Bézout's identity
8 int result = nums[0];
9 for (const auto& num : nums) {
10 result = std::gcd(result, num); // built-in gcd since C++17, O(logn)
11 if (result == 1) {
12 break;
13 }
14 }
15 return result == 1;
16 }
17 };
***************************

247. Check If It Is a Good Array(Python)


***************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def isGoodArray(self, nums):
6 """
7 :type nums: List[int]
8 :rtype: bool
9 """
10 def gcd(a, b):
11 while b:
12 a, b = b, a%b
13 return a
14
15 # Bézout's identity
16 result = nums[0]
17 for num in nums:
18 result = gcd(result, num)
19 if result == 1:
20 break
21 return result == 1
*************************************

248. Maximum Score Words Formed by Letters


*************************************

Given a list of words, list of single letters (might be repeating) and score of every character.

Return the maximum score of any valid set of words formed by using the given letters (words[i] cannot be used two or more
times).

It is not necessary to use all characters in letters and each letter can only be used once. Score of letters 'a', 'b', 'c', ... ,'z' is given
by score[0], score[1], ... , score[25] respectively.

Example 1:

Input: words = ["dog","cat","dad","good"], letters = ["a","a","c","d","d","d","g","o","o"], score = [1,0,9,5,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,0,


Output: 23
Explanation:
Score a=1, c=9, d=5, g=3, o=2
Given letters, we can form the words "dad" (5+1+5) and "good" (3+2+2+5) with a score of 23.
Words "dad" and "dog" only get a score of 21.

Example 2:

Input: words = ["xxxz","ax","bx","cx"], letters = ["z","a","b","c","x","x","x"], score = [4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,1


Output: 27
Explanation:
Score a=4, b=4, c=4, x=5, z=10
Given letters, we can form the words "ax" (4+5), "bx" (4+5) and "cx" (4+5) with a score of 27.
Word "xxxz" only get a score of 25.

Example 3:

Input: words = ["leetcode"], letters = ["l","e","t","c","o","d"], score = [0,0,1,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0]


Output: 0
Explanation:
Letter "e" can only be used once.

Constraints:

1 <= words.length <= 14


1 <= words[i].length <= 15
1 <= letters.length <= 100
letters[i].length == 1
score.length == 26
0 <= score[i] <= 10
words[i], letters[i] contains only lower case English letters.
*************************************

248. Maximum Score Words Formed by Letters(C++)


*************************************

1 // Time: O(n * 2^n)


2 // Space: O(n)
3
4 class Solution {
5 public:
6 int maxScoreWords(vector& words, vector& letters, vector& score) {
7 unordered_map letter_count;
8 vector> word_counts(words.size());
9 vector word_scores(words.size());
10 for (const auto& c : letters) {
11 ++letter_count[c];
12 }
13 for (int i = 0; i < words.size(); ++i) {
14 for (const auto& c : words[i]) {
15 ++word_counts[i][c];
16 word_scores[i] += score[c - 'a'];
17 }
18 }
19 int result = 0;
20 backtracking(words, word_scores, word_counts, 0, 0, &letter_count, &result);
21 return result;
22 }
23
24 private:
25 void backtracking(const vector& words,
26 const vector& word_scores,
27 const vector>& word_counts,
28 int curr,
29 int curr_score,
30 unordered_map *letter_count,
31 int *result) {
32 *result = max(*result, curr_score);
33 for (int i = curr; i < words.size(); ++i) {
34 if (any_of(word_counts[i].cbegin(), word_counts[i].cend(),
35 [&letter_count](const auto& x) {
36 return (*letter_count)[x.first] < x.second;
37 })) {
38 continue;
39 }
40 for (const auto& [k, v] : word_counts[i]) {
41 (*letter_count)[k] -= v;
42 }
43 backtracking(words, word_scores, word_counts,
44 i + 1, curr_score + word_scores[i], letter_count, result);
45 for (const auto& [k, v] : word_counts[i]) {
46 (*letter_count)[k] += v;
47 }
48 }
49 }
50 };
*************************************

248. Maximum Score Words Formed by Letters(Python)


*************************************

1 # Time: O(n * 2^n)


2 # Space: O(n)
3
4 import collections
5
6
7 class Solution(object):
8 def maxScoreWords(self, words, letters, score):
9 """
10 :type words: List[str]
11 :type letters: List[str]
12 :type score: List[int]
13 :rtype: int
14 """
15 def backtracking(words, word_scores, word_counts, curr, curr_score, letter_count, result):
16 result[0] = max(result[0], curr_score)
17 for i in xrange(curr, len(words)):
18 if any(letter_count[c] < word_counts[i][c] for c in word_counts[i]):
19 continue
20 backtracking(words, word_scores, word_counts, i+1,
21 curr_score+word_scores[i], letter_count-word_counts[i],
22 result)
23
24 letter_count = collections.Counter(letters)
25 word_counts = map(collections.Counter, words)
26 word_scores = [sum(score[ord(c)-ord('a')] for c in words[i])
27 for i in xrange(len(words))]
28 result = [0]
29 backtracking(words, word_scores, word_counts, 0, 0, letter_count, result)
30 return result[0]
***************************

249. Handshakes That Don't Cross


***************************

You are given an even number of people num_people that stand around a circle and each person shakes hands with someone
else, so that there are num_people / 2 handshakes total.

Return the number of ways these handshakes could occur such that none of the handshakes cross.

Since this number could be very big, return the answer mod 10^9 + 7

Example 1:

Input: num_people = 2
Output: 1

Example 2:

Input: num_people = 4
Output: 2
Explanation: There are two ways to do it, the first way is [(1,2),(3,4)] and the second one is [(2,3),(4,1)].

Example 3:
Input: num_people = 6
Output: 5

Example 4:

Input: num_people = 8
Output: 14

Constraints:
2 <= num_people <= 1000
num_people % 2 == 0
***************************

249. Handshakes That Don't Cross(C++)


***************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int numberOfWays(int num_people) {
7 static const int MOD = 1e9 + 7;
8 int n = num_people / 2;
9 return 1ULL * nCr(2 * n, n, MOD) * inv(n + 1, MOD) % MOD; // Catalan number
10 }
11
12 private:
13 int nCr(int n, int k, int m) {
14 if (n - k < k) {
15 return nCr(n, n - k, m);
16 }
17 uint64_t result = 1;
18 for (int i = 1; i <= k; ++i) {
19 result = (result * (n - k + i) % m) * inv(i, m) % m;
20 }
21 return result;
22 }
23
24 int inv(int x, int m) { // Euler's Theorem
25 return pow(x, m - 2, m);
26 }
27
28 int pow(uint64_t a, int b, int m) { // O(logMOD) = O(1)
29 a %= m;
30 uint64_t result = 1;
31 while (b) {
32 if (b & 1) {
33 result = (result * a) % m;
34 }
35 a = (a * a) % m;
36 b >>= 1;
37 }
38 return result;
39 }
40 };
41
42 // Time: O(n^2)
43 // Space: O(n)
44 class Solution2 {
45 public:
46 int numberOfWays(int num_people) {
47 static const int MOD = 1e9 + 7;
48 vector dp(num_people / 2 + 1);
49 dp[0] = 1ULL;
50 for (int k = 1; k <= num_people / 2; ++k) {
51 for (int i = 0; i < k; ++i) {
52 dp[k] = (dp[k] + dp[i] * dp[k - 1 - i]) % MOD;
53 }
54 }
55 return dp[num_people / 2];
56 }
57 };
***************************

249. Handshakes That Don't Cross(Python)


***************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def numberOfWays(self, num_people):
6 """
7 :type num_people: int
8 :rtype: int
9 """
10 MOD = 10**9+7
11 def inv(x, m): # Euler's Theorem
12 return pow(x, m-2, m) # O(logMOD) = O(1)
13
14 def nCr(n, k, m):
15 if n-k < k:
16 return nCr(n, n-k, m)
17 result = 1
18 for i in xrange(1, k+1):
19 result = result*(n-k+i)*inv(i, m)%m
20 return result
21
22 n = num_people//2
23 return nCr(2*n, n, MOD)*inv(n+1, MOD) % MOD # Catalan number
24
25
26 # Time: O(n^2)
27 # Space: O(n)
28 class Solution2(object):
29 def numberOfWays(self, num_people):
30 """
31 :type num_people: int
32 :rtype: int
33 """
34 MOD = 10**9+7
35 dp = [0]*(num_people//2+1)
36 dp[0] = 1
37 for k in xrange(1, num_people//2+1):
38 for i in xrange(k):
39 dp[k] = (dp[k] + dp[i]*dp[k-1-i]) % MOD
40 return dp[num_people//2]
****************************************************

250. Minimum Moves to Move a Box to Their Target


Location
****************************************************

Storekeeper is a game in which the player pushes boxes around in a warehouse trying to get them to target locations.

The game is represented by a grid of size m x n , where each element is a wall, floor, or a box.

Your task is move the box 'B' to the target position 'T' under the following rules:

Player is represented by character 'S' and can move up, down, left, right in thegrid if it is a floor (empy cell).
Floor is represented by character '.' that means free cell to walk.
Wall is represented by character '#' that means obstacle (impossible to walk there).
There is only one box 'B' and one target cell 'T' in the grid.
The box can be moved to an adjacent free cell by standing next to the box and then moving in the direction of the box.
This is a push.
The player cannot walk through the box.

Return the minimum number of pushes to move the box to the target. If there is no way to reach the target, return-1.

Example 1:

Input: grid = [["#","#","#","#","#","#"],


["#","T","#","#","#","#"],
["#",".",".","B",".","#"],
["#",".","#","#",".","#"],
["#",".",".",".","S","#"],
["#","#","#","#","#","#"]]
Output: 3
Explanation: We return only the number of times the box is pushed.

Example 2:
Input: grid = [["#","#","#","#","#","#"],
["#","T","#","#","#","#"],
["#",".",".","B",".","#"],
["#","#","#","#",".","#"],
["#",".",".",".","S","#"],
["#","#","#","#","#","#"]]
Output: -1

Example 3:

Input: grid = [["#","#","#","#","#","#"],


["#","T",".",".","#","#"],
["#",".","#","B",".","#"],
["#",".",".",".",".","#"],
["#",".",".",".","S","#"],
["#","#","#","#","#","#"]]
Output: 5
Explanation: push the box down, left, left, up and up.

Example 4:

Input: grid = [["#","#","#","#","#","#","#"],


["#","S","#",".","B","T","#"],
["#","#","#","#","#","#","#"]]
Output: -1

Constraints:

m == grid.length
n == grid[i].length
1 <= m <= 20
1 <= n <= 20
grid contains only
characters '.', '#', 'S' , 'T', or 'B'.
There is only one character 'S', 'B' and 'T' in the grid.
****************************************************

250. Minimum Moves to Move a Box to Their Target


Location(C++)
****************************************************

1 // Time: O(m^2 * n^2)


2 // Space: O(m^2 * n^2)
3
4 // A* Search Algorithm without heap
5 class Solution {
6 public:
7 template
8 struct PairHash {
9 size_t operator()(const pair& p) const {
10 size_t seed = 0;
11 seed ^= std::hash{}(p.first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
12 seed ^= std::hash{}(p.second) + 0x9e3779b9 + (seed<<6) + (seed>>2);
13 return seed;
14 }
15 };
16
17 int minPushBox(vector>& grid) {
18 pair b, p, t;
19 for (int i = 0; i < grid.size(); ++i) {
20 for (int j = 0; j < grid[0].size(); ++j) {
21 if (grid[i][j] == 'B') {
22 b = {i, j};
23 } else if (grid[i][j] == 'S') {
24 p = {i, j};
25 } else if (grid[i][j] == 'T') {
26 t = {i, j};
27 }
28 }
29 }
30 return a_star(grid, b, p, t);
31 }
32
33 private:
34 int a_star(const vector>& grid,
35 const pair& b,
36 const pair& p,
37 const pair& t) {
38
39 int f = g(b, t), dh = 2;
40 vector, pair>> closer{{b, p}}, detour;
41 unordered_set, PairHash> lookup;
42 while (!closer.empty() || !detour.empty()) {
43 if (closer.empty()) {
44 f += dh;
45 swap(closer, detour);
46 }
47 const auto [b, p] = closer.back(); closer.pop_back();
48 if (b == t) {
49 return f;
50 }
51 if (lookup.count({b.first * grid[0].size() + b.second,
52 p.first * grid[0].size() + p.second})) {
53 continue;
54 }
55 lookup.emplace(b.first * grid[0].size() + b.second,
56 p.first * grid[0].size() + p.second);
57 for (const auto& [dx, dy] : directions) {
58 pair nb = {b.first + dx, b.second + dy}, np = {b.first - dx, b.second - dy};
59 if (!(0 <= nb.first && nb.first < grid.size() &&
60 0 <= nb.second && nb.second < grid[0].size() &&
60
61 0 <= np.first && np.first < grid.size() &&
62 0 <= np.second && np.second < grid[0].size() &&
63 grid[nb.first][nb.second] != '#' && grid[np.first][np.second] != '#' &&
64 !lookup.count({nb.first * grid[0].size() + nb.second,
65 b.first * grid[0].size() + b.second}) &&
66 can_reach(grid, b, p, np))) {
67 continue;
68 }
69 if (dot({dx, dy}, {t.first - b.first, t.second - b.second}) > 0) {
70 closer.emplace_back(nb, b);
71 } else {
72 detour.emplace_back(nb, b);
73 }
74 }
75 }
76 return -1;
77 }
78
79 inline int g(const pair& a,
80 const pair& b) {
81 return abs(a.first - b.first) + abs(a.second - b.second);
82 }
83
84 int can_reach(const vector>& grid,
85 const pair& b,
86 const pair& p,
87 const pair& t) {
88
89 vector> closer{p}, detour;
90 unordered_set lookup = {b.first * grid[0].size() + b.second};
91 while (!closer.empty() || !detour.empty()) {
92 if (closer.empty()) {
93 swap(closer, detour);
94 }
95 auto p = closer.back(); closer.pop_back();
96 if (p == t) {
97 return true;
98 }
99 if (lookup.count(p.first * grid[0].size() + p.second)) {
100 continue;
101 }
102 lookup.emplace(p.first * grid[0].size() + p.second);
103 for (const auto& [dx, dy] : directions) {
104 pair np = {p.first + dx, p.second + dy};
105 if (!(0 <= np.first && np.first < grid.size() &&
106 0 <= np.second && np.second < grid[0].size() &&
107 grid[np.first][np.second] != '#' &&
108 !lookup.count(np.first * grid[0].size() + np.second))) {
109 continue;
110 }
111 if (dot({dx, dy}, {t.first - p.first, t.second - p.second}) > 0) {
112 closer.emplace_back(np);
113 } else {
114 detour.emplace_back(np);
115 }
116 }
117 }
118 return false;
119 }
120
121 inline int dot(const pair& a,
122 const pair& b) {
123 return a.first * b.first + a.second * b.second;
124 }
125
126 static const vector> directions;
127 };
128
129 const vector> Solution::directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
****************************************************

250. Minimum Moves to Move a Box to Their Target


Location(Python)
****************************************************
1 # Time: O(m^2 * n^2)
2 # Space: O(m^2 * n^2)
3
4 # A* Search Algorithm without heap
5 class Solution(object):
6 def minPushBox(self, grid):
7 """
8 :type grid: List[List[str]]
9 :rtype: int
10 """
11 directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
12 def dot(a, b):
13 return a[0]*b[0]+a[1]*b[1]
14
15 def can_reach(grid, b, p, t):
16 closer, detour = [p], []
17 lookup = set([b])
18 while closer or detour:
19 if not closer:
20 closer, detour = detour, closer
21 p = closer.pop()
22 if p == t:
23 return True
24 if p in lookup:
25 continue
26 lookup.add(p)
27 for dx, dy in directions:
28 np = (p[0]+dx, p[1]+dy)
29 if not (0 <= np[0] < len(grid) and 0 <= np[1] < len(grid[0]) and
30 grid[np[0]][np[1]] != '#' and np not in lookup):
31 continue
32 (closer if dot((dx, dy), (t[0]-p[0], t[1]-p[1])) > 0 else detour).append(np)
33 return False
34
35 def g(a, b):
36 return abs(a[0]-b[0])+abs(a[1]-b[1])
37
38 def a_star(grid, b, p, t):
39 f, dh = g(b, t), 2
40 closer, detour = [(b, p)], []
41 lookup = set()
42 while closer or detour:
43 if not closer:
44 f += dh
45 closer, detour = detour, closer
46 b, p = closer.pop()
47 if b == t:
48 return f
49 if (b, p) in lookup:
50 continue
51 lookup.add((b, p))
52 for dx, dy in directions:
53 nb, np = (b[0]+dx, b[1]+dy), (b[0]-dx, b[1]-dy)
54 if not (0 <= nb[0] < len(grid) and 0 <= nb[1] < len(grid[0]) and
55 0 <= np[0] < len(grid) and 0 <= np[1] < len(grid[0]) and
56 grid[nb[0]][nb[1]] != '#' and grid[np[0]][np[1]] != '#' and
57 (nb, b) not in lookup and can_reach(grid, b, p, np)):
58 continue
59 (closer if dot((dx, dy), (t[0]-b[0], t[1]-b[1])) > 0 else detour).append((nb, b))
60 return -1
61
62 b, p, t = None, None, None
63 for i in xrange(len(grid)):
64 for j in xrange(len(grid[0])):
65 if grid[i][j] == 'B':
66 b = (i, j)
67 elif grid[i][j] == 'S':
68 p = (i, j)
69 elif grid[i][j] == 'T':
70 t = (i, j)
71 return a_star(grid, b, p, t)
*********************************************************

251. Number of Ways to Stay in the Same Place After


Some Steps
*********************************************************

You have a pointer at index 0 in an array of size arrLen . At each step, you can move 1 position to the left, 1 position to the
right in the array, or stay in the same place (The pointer should not be placed outside the array at any time).

Given two integers steps and arrLen , return the number of ways such that your pointer still at index0 after exactly steps steps.
Since the answer may be too large, return it modulo 109 + 7 .

Example 1:

Input: steps = 3, arrLen = 2


Output: 4
Explanation: There are 4 differents ways to stay at index 0 after 3 steps.
Right, Left, Stay
Stay, Right, Left
Right, Stay, Left
Stay, Stay, Stay

Example 2:

Input: steps = 2, arrLen = 4


Output: 2
Explanation: There are 2 differents ways to stay at index 0 after 2 steps
Right, Left
Stay, Stay

Example 3:

Input: steps = 4, arrLen = 2


Output: 8

Constraints:

1 <= steps <= 500


1 <= arrLen <= 10 6
*********************************************************

251. Number of Ways to Stay in the Same Place After


Some Steps(C++)
*********************************************************

1 // Time: O(n^2), n is the number of steps


2 // Space: O(n)
3
4 class Solution {
5 public:
6 int numWays(int steps, int arrLen) {
7 static const int MOD = 1000000007;
8 const int l = min(1 + steps / 2, arrLen);
9 vector dp(l + 2);
10 dp[1] = 1;
11 while (steps-- > 0) {
12 vector new_dp(l + 2);
13 for (int i = 1; i <= l; ++i) {
14 new_dp[i] = (uint64_t(dp[i]) + dp[i - 1] + dp[i + 1]) % MOD;
15 }
16 dp = move(new_dp);
17 }
18 return dp[1];
19 }
20 };
*********************************************************

251. Number of Ways to Stay in the Same Place After


Some Steps(Python)
*********************************************************

1 # Time: O(n^2), n is the number of steps


2 # Space: O(n)
3
4 class Solution(object):
5 def numWays(self, steps, arrLen):
6 """
7 :type steps: int
8 :type arrLen: int
9 :rtype: int
10 """
11 MOD = int(1e9+7)
12 l = min(1+steps//2, arrLen)
13 dp = [0]*(l+2)
14 dp[1] = 1
15 while steps > 0:
16 steps -= 1
17 new_dp = [0]*(l+2)
18 for i in xrange(1, l+1):
19 new_dp[i] = (dp[i] + dp[i-1] + dp[i+1]) % MOD
20 dp = new_dp
21 return dp[1]
******************************

252. Number of Ships in a Rectangle


******************************

(This problem is an interactive problem.)

Each ship is located at an integer point on the sea represented by a cartesian plane, and each integer point may contain at
most 1 ship.

You have a function Sea.hasShips(topRight, bottomLeft) which takes two points as arguments and returns true If there is at least
one ship in the rectangle represented by the two points, including on the boundary.

Given two points: the top right and bottom left corners of a rectangle, return the number of ships present in that rectangle. It
is guaranteed that there are at most 10 ships in that rectangle.

Submissions making more than 400 calls to hasShips will be judged Wrong Answer. Also, any solutions that attempt to
circumvent the judge will result in disqualification.

Example :

Input:
ships = [[1,1],[2,2],[3,3],[5,5]], topRight = [4,4], bottomLeft = [0,0]
Output: 3
Explanation: From [0,0] to [4,4] we can count 3 ships within the range.

Constraints:

On the input ships is only given to initialize the map internally. You must solve this problem "blindfolded". In other
words, you must find the answer using the given hasShips API, without knowing the ships position.
0 <= bottomLeft[0] <= topRight[0] <= 1000
0 <= bottomLeft[1] <= topRight[1] <= 1000
topRight != bottomLeft
******************************

252. Number of Ships in a Rectangle(C++)


******************************

1 // Time: O(s * log(m * n)), s is the max number of ships, which is 10 in this problem
2 // Space: O(log(m * n))
3
4 /**
5 * // This is Sea's API interface.
6 * // You should not implement it, or speculate about its implementation
7 * class Sea {
8 * public:
9 * bool hasShips(vector topRight, vector bottomLeft);
10 * };
11 */
12
13 class Solution {
14 public:
15 int countShips(Sea sea, vector topRight, vector bottomLeft) {
16 int result = 0;
17 if (topRight[0] >= bottomLeft[0] &&
18 topRight[1] >= bottomLeft[1] &&
19 sea.hasShips(topRight, bottomLeft)) {
20 if (topRight == bottomLeft) {
21 return 1;
22 }
23 const auto& mid_x = (topRight[0] + bottomLeft[0]) / 2;
24 const auto& mid_y = (topRight[1] + bottomLeft[1]) / 2;
25 result += countShips(sea, topRight, {mid_x + 1, mid_y + 1});
26 result += countShips(sea, {mid_x, topRight[1]}, {bottomLeft[0], mid_y + 1});
27 result += countShips(sea, {topRight[0], mid_y}, {mid_x + 1, bottomLeft[1]});
28 result += countShips(sea, {mid_x, mid_y}, bottomLeft);
29 }
30 return result;
31 }
32 };
******************************

252. Number of Ships in a Rectangle(Python)


******************************

1 # Time: O(s * log(m * n)), s is the max number of ships, which is 10 in this problem
2 # Space: O(log(m * n))
3
4 # """
5 # This is Sea's API interface.
6 # You should not implement it, or speculate about its implementation
7 # """
8 class Sea(object):
9 def hasShips(self, topRight, bottomLeft):
10 """
11 :type topRight: Point
12 :type bottomLeft: Point
13 :rtype bool
14 """
15 pass
16
17 class Point(object):
18 def __init__(self, x, y):
19 self.x = x
20 self.y = y
21
22 class Solution(object):
23 def countShips(self, sea, topRight, bottomLeft):
24 """
25 :type sea: Sea
26 :type topRight: Point
27 :type bottomLeft: Point
28 :rtype: integer
29 """
30 result = 0
31 if topRight.x >= bottomLeft.x and \
32 topRight.y >= bottomLeft.y and \
33 sea.hasShips(topRight, bottomLeft):
34 if (topRight.x, topRight.y) == (bottomLeft.x, bottomLeft.y):
35 return 1
36 mid_x, mid_y = (topRight.x+bottomLeft.x)//2, (topRight.y+bottomLeft.y)//2
37 result += self.countShips(sea, topRight, Point(mid_x+1, mid_y+1))
38 result += self.countShips(sea, Point(mid_x, topRight.y), Point(bottomLeft.x, mid_y+1))
39 result += self.countShips(sea, Point(topRight.x, mid_y), Point(mid_x+1, bottomLeft.y))
40 result += self.countShips(sea, Point(mid_x, mid_y), bottomLeft)
41 return result
***************************

253. Palindrome Partitioning III


***************************

You are given a string s containing lowercase letters and an integer k . You need to :

First, change some characters of s to other lowercase English letters.


Then divide s into k non-empty disjoint substrings such that each substring is a palindrome.

Return the minimal number of characters that you need to change to divide the string.

Example 1:

Input: s = "abc", k = 2
Output: 1
Explanation: You can split the string into "ab" and "c", and change 1 character in "ab" to make it palindrome.

Example 2:

Input: s = "aabbc", k = 3
Output: 0
Explanation: You can split the string into "aa", "bb" and "c", all of them are palindrome.

Example 3:

Input: s = "leetcode", k = 8
Output: 0

Constraints:

1 <= k <= s.length <= 100 .


s only contains lowercase English letters.
***************************

253. Palindrome Partitioning III(C++)


***************************

1 // Time: O(k * n^2)


2 // Space: O(n^2)
3
4 class Solution {
5 public:
6 int palindromePartition(string s, int k) {
7 // dp1[i][j]: minimum number of changes to make s[i, j] palindrome
8 vector> dp1(s.length(), vector(s.length()));
9 for (int l = 1; l <= s.length(); ++l) {
10 for (int i = 0; i + l <= s.length(); ++i) {
11 int j = i + l - 1;
12 if (i == j - 1) {
13 dp1[i][j] = s[i] == s[j] ? 0 : 1;
14 } else if (i != j) {
15 dp1[i][j] = s[i] == s[j] ? dp1[i + 1][j - 1] : dp1[i + 1][j - 1] + 1;
16 }
17 }
18 }
19 // dp2[d][i]: minimum number of changes to divide s[0, i] into d palindromes
20 vector> dp2(2, vector(s.length(), numeric_limits::max()));
21 dp2[1] = dp1[0];
22 for (int d = 2; d <= k; ++d) {
23 dp2[d % 2] = vector(s.length(), numeric_limits::max());
24 for (int i = d - 1; i < s.length(); ++i) {
25 for (int j = d - 2; j < i; ++j) {
26 dp2[d % 2][i] = min(dp2[d % 2][i], dp2[(d - 1) % 2][j] + dp1[j + 1][i]);
27 }
28 }
29 }
30 return dp2[k % 2][s.length() - 1];
31 }
32 };
***************************

253. Palindrome Partitioning III(Python)


***************************

1 # Time: O(k * n^2)


2 # Space: O(n^2)
3
4 class Solution(object):
5 def palindromePartition(self, s, k):
6 """
7 :type s: str
8 :type k: int
9 :rtype: int
10 """
11 # dp1[i][j]: minimum number of changes to make s[i, j] palindrome
12 dp1 = [[0]*len(s) for _ in xrange(len(s))]
13 for l in xrange(1, len(s)+1):
14 for i in xrange(len(s)-l+1):
15 j = i+l-1
16 if i == j-1:
17 dp1[i][j] = 0 if s[i] == s[j] else 1
18 elif i != j:
19 dp1[i][j] = dp1[i+1][j-1] if s[i] == s[j] else dp1[i+1][j-1]+1
20
21 # dp2[d][i]: minimum number of changes to divide s[0, i] into d palindromes
22 dp2 = [[float("inf")]*len(s) for _ in xrange(2)]
23 dp2[1] = dp1[0][:]
24 for d in xrange(2, k+1):
25 dp2[d%2] = [float("inf")]*len(s)
26 for i in xrange(d-1, len(s)):
27 for j in xrange(d-2, i):
28 dp2[d%2][i] = min(dp2[d%2][i], dp2[(d-1)%2][j]+dp1[j+1][i])
29 return dp2[k%2][len(s)-1]
***************************************************************

254. Minimum Number of Flips to Convert Binary Matrix


to Zero Matrix
***************************************************************

Given a m x n binary matrix mat. In one step, you can choose one cell and flip it and all the four neighbors of it if they exist
(Flip is changing 1 to 0 and 0 to 1). A pair of cells are called neighbors if they share one edge.

Return the minimum number of steps required to convert mat to a zero matrix or -1 if you cannot.

A binary matrix is a matrix with all cells equal to 0 or 1 only.

A zero matrix is a matrix with all cells equal to 0.

Example 1:

Input: mat = [[0,0],[0,1]]


Output: 3
Explanation: One possible solution is to flip (1, 0) then (0, 1) and finally (1, 1) as shown.

Example 2:

Input: mat = [[0]]


Output: 0
Explanation: Given matrix is a zero matrix. We don't need to change it.

Example 3:

Input: mat = [[1,1,1],[1,0,1],[0,0,0]]


Output: 6

Example 4:

Input: mat = [[1,0,0],[1,0,0]]


Output: -1
Explanation: Given matrix can't be a zero matrix

Constraints:

m == mat.length
n == mat[i].length
1 <= m, n <= 3
mat[i][j] is either 0 or 1.
***************************************************************

254. Minimum Number of Flips to Convert Binary Matrix


to Zero Matrix(C++)
***************************************************************

1 // Time: O((m * n) * 2^(m * n))


2 // Space: O((m * n) * 2^(m * n))
3
4 class Solution {
5 public:
6 int minFlips(vector>& mat) {
7 static const vector> directions{{0, 0}, {0, 1}, {1, 0}, {0, -1}, {-1, 0}};
8 int start = 0;
9 for (int r = 0; r < mat.size(); ++r) {
10 for (int c = 0; c < mat[0].size(); ++c) {
11 start |= mat[r][c] << r * mat[0].size() + c;
12 }
13 }
14 queue> q({{start, 0}});
15 unordered_set lookup = {start};
16 while (!q.empty()) {
17 const auto [state, step] = q.front(); q.pop();
18 if (!state) {
19 return step;
20 }
21 for (int r = 0; r < mat.size(); ++r) {
22 for (int c = 0; c < mat[0].size(); ++c) {
23 int new_state = state;
24 for (const auto& [dr, dc] : directions) {
25 const auto& [nr, nc] = make_pair(r + dr, c + dc);
26 if (0 <= nr && nr < mat.size() &&
27 0 <= nc && nc < mat[0].size()) {
28 new_state ^= 1 << nr * mat[0].size() + nc;
29 }
30 }
31 if (lookup.count(new_state)) {
32 continue;
33 }
34 lookup.emplace(new_state);
35 q.emplace(new_state, step + 1);
36 }
37 }
38 }
39 return -1;
40 }
41 };
***************************************************************

254. Minimum Number of Flips to Convert Binary Matrix


to Zero Matrix(Python)
***************************************************************

1 # Time: O((m * n) * 2^(m * n))


2 # Space: O((m * n) * 2^(m * n))
3
4 import collections
5
6
7 class Solution(object):
8 def minFlips(self, mat):
9 """
10 :type mat: List[List[int]]
11 :rtype: int
12 """
13 directions = [(0, 0), (0, 1), (1, 0), (0, -1), (-1, 0)]
14 start = sum(val << r*len(mat[0])+c for r, row in enumerate(mat) for c, val in enumerate(row))
15 q = collections.deque([(start, 0)])
16 lookup = {start}
17 while q:
18 state, step = q.popleft()
19 if not state:
20 return step
21 for r in xrange(len(mat)):
22 for c in xrange(len(mat[0])):
23 new_state = state
24 for dr, dc in directions:
25 nr, nc = r+dr, c+dc
26 if 0 <= nr < len(mat) and 0 <= nc < len(mat[0]):
27 new_state ^= 1 << nr*len(mat[0])+nc
28 if new_state in lookup:
29 continue
30 lookup.add(new_state)
31 q.append((new_state, step+1))
32 return -1
***************************

255. Minimum Falling Path Sum II


***************************

Given a square grid of integers arr, a falling path with non-zero shifts is a choice of exactly one element from each row of arr,
such that no two elements chosen in adjacent rows are in the same column.

Return the minimum sum of a falling path with non-zero shifts.

Example 1:

Input: arr = [[1,2,3],[4,5,6],[7,8,9]]


Output: 13
Explanation:
The possible falling paths are:
[1,5,9], [1,5,7], [1,6,7], [1,6,8],
[2,4,8], [2,4,9], [2,6,7], [2,6,8],
[3,4,8], [3,4,9], [3,5,7], [3,5,9]
The falling path with the smallest sum is [1,5,7], so the answer is 13.

Constraints:

1 <= arr.length == arr[i].length <= 200


-99 <= arr[i][j] <= 99
***************************

255. Minimum Falling Path Sum II(C++)


***************************

1 // Time: O(m * n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int minFallingPathSum(vector>& arr) {
7 for (int i = 1; i < arr.size(); ++i) {
8 const auto& smallest_two = nsmallest(2, arr[i - 1]);
9 for (int j = 0; j < arr[0].size(); ++j) {
10 arr[i][j] += (arr[i - 1][j] == smallest_two[0]) ? smallest_two[1] : smallest_two[0];
11 }
12 }
13 return *min_element(arr.back().cbegin(), arr.back().cend());
14 }
15
16 private:
17 vector nsmallest(int k, const vector& arr) {
18 priority_queue max_heap;
19 for (const auto& x : arr) {
20 max_heap.emplace(x);
21 if (max_heap.size() > k) {
22 max_heap.pop();
23 }
24 }
25 vector result;
26 while (!max_heap.empty()) {
27 result.emplace_back(max_heap.top()); max_heap.pop();
28 }
29 return {result.crbegin(), result.crend()};
30 }
31 };
***************************

255. Minimum Falling Path Sum II(Python)


***************************

1 # Time: O(m * n)
2 # Space: O(1)
3
4 import heapq
5
6
7 class Solution(object):
8 def minFallingPathSum(self, arr):
9 """
10 :type arr: List[List[int]]
11 :rtype: int
12 """
13 for i in xrange(1, len(arr)):
14 smallest_two = heapq.nsmallest(2, arr[i-1])
15 for j in xrange(len(arr[0])):
16 arr[i][j] += smallest_two[1] if arr[i-1][j] == smallest_two[0] else smallest_two[0]
17 return min(arr[-1])
**************************************************

256. Shortest Path in a Grid with Obstacles Elimination


**************************************************

You are given an m x n integer matrix grid where each cell is either 0 (empty) or 1 (obstacle). You can move up, down, left, or
right from and to an empty cell in one step.

Return the minimum number of steps to walk from the upper left corner(0, 0) to the lower right corner (m - 1, n - 1) given that
you can eliminate at most k obstacles. If it is not possible to find such walk return-1.

Example 1:

Input:
grid =
[[0,0,0],
[1,1,0],
[0,0,0],
[0,1,1],
[0,0,0]],
k = 1
Output: 6
Explanation:
The shortest path without eliminating any obstacle is 10.
The shortest path with one obstacle elimination at position (3,2) is 6. Such path is (0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (3,2) -> (4

Example 2:

Input:
grid =
[[0,1,1],
[1,1,1],
[1,0,0]],
k = 1
Output: -1
Explanation:
We need to eliminate at least two obstacles to find such a walk.

Constraints:

m == grid.length
n == grid[i].length
1 <= m, n <= 40
1 <= k <= m * n
grid[i][j] == 0 or 1
grid[0][0] == grid[m - 1][n - 1] == 0
**************************************************

256. Shortest Path in a Grid with Obstacles


Elimination(C++)
**************************************************
1 // Time: O(m * n * k)
2 // Space: O(m * n)
3
4 // A* Search Algorithm without heap
5 class Solution {
6 public:
7 int shortestPath(vector>& grid, int k) {
8 pair b = {0, 0};
9 pair t = {grid.size() - 1, grid[0].size() - 1};
10 return a_star(grid, b, t, k);
11 }
12
13 private:
14 int a_star(const vector>& grid,
15 const pair& b,
16 const pair& t,
17 int k) {
18
19 int f = g(b, t), dh = 2;
20 vector, int>> closer{{b, k}}, detour;
21 unordered_map lookup;
22 while (!closer.empty() || !detour.empty()) {
23 if (closer.empty()) {
24 f += dh;
25 swap(closer, detour);
26 }
27 const auto [b, k] = closer.back(); closer.pop_back();
28 if (b == t) {
29 return f;
30 }
31 if (lookup.count(b.first * grid[0].size() + b.second) &&
32 lookup[b.first * grid[0].size() + b.second] >= k) {
33 continue;
34 }
35 lookup[b.first * grid[0].size() + b.second] = k;
36 for (const auto& [dx, dy] : directions) {
37 pair nb = {b.first + dx, b.second + dy};
38 if (!(0 <= nb.first && nb.first < grid.size() &&
39 0 <= nb.second && nb.second < grid[0].size() &&
40 (grid[nb.first][nb.second] == 0 || k > 0) &&
41 (!lookup.count(nb.first * grid[0].size() + nb.second) ||
42 lookup[nb.first * grid[0].size() + nb.second] < k))) {
43 continue;
44 }
45 if (dot({dx, dy}, {t.first - b.first, t.second - b.second}) > 0) {
46 closer.emplace_back(nb, k - int(grid[nb.first][nb.second] != 0));
47 } else {
48 detour.emplace_back(nb, k - int(grid[nb.first][nb.second] != 0));
49 }
50 }
51 }
52 return -1;
53 }
54
55 inline int g(const pair& a,
56 const pair& b) {
57 return abs(a.first - b.first) + abs(a.second - b.second);
58 }
59
60 inline int dot(const pair& a,
61 const pair& b) {
62 return a.first * b.first + a.second * b.second;
63 }
64
65 static const vector> directions;
66 };
67
68 const vector> Solution::directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
**************************************************

256. Shortest Path in a Grid with Obstacles


Elimination(Python)
**************************************************

1 # Time: O(m * n * k)
2 # Space: O(m * n)
3
4 # A* Search Algorithm without heap
5 class Solution(object):
6 def shortestPath(self, grid, k):
7 """
8 :type grid: List[List[int]]
9 :type k: int
10 :rtype: int
11 """
12 directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
13 def dot(a, b):
14 return a[0]*b[0]+a[1]*b[1]
15
16 def g(a, b):
17 return abs(a[0]-b[0])+abs(a[1]-b[1])
18
19 def a_star(grid, b, t, k):
20 f, dh = g(b, t), 2
21 closer, detour = [(b, k)], []
22 lookup = {}
23 while closer or detour:
24 if not closer:
25 f += dh
26 closer, detour = detour, closer
27 b, k = closer.pop()
28 if b == t:
29 return f
30 if b in lookup and lookup[b] >= k:
31 continue
32 lookup[b] = k
33 for dx, dy in directions:
34 nb = (b[0]+dx, b[1]+dy)
35 if not (0 <= nb[0] < len(grid) and 0 <= nb[1] < len(grid[0]) and
36 (grid[nb[0]][nb[1]] == 0 or k > 0) and
37 (nb not in lookup or lookup[nb] < k)):
38 continue
39 (closer if dot((dx, dy), (t[0]-b[0], t[1]-b[1])) > 0 else detour).append((nb, k-int(grid[nb[0]][nb[1]] ==
40 return -1
41
42 return a_star(grid, (0, 0), (len(grid)-1, len(grid[0])-1), k)
**************************************

257. Maximum Candies You Can Get from Boxes


**************************************

Given n boxes, each box is given in the format[status, candies, keys, containedBoxes] where:

status[i]: an integer which is 1 if box[i] is open and 0 if box[i] is closed.


candies[i]: an integer representing the number of candies inbox[i].
keys[i]: an array contains the indices of the boxes you can open with the key inbox[i].
containedBoxes[i]: an array contains the indices of the boxes found inbox[i].

You will start with some boxes given ininitialBoxes array. You can take all the candies in any open box and you can use the
keys in it to open new boxes and you also can use the boxes you find in it.

Return the maximum number of candies you can get following the rules above.

Example 1:

Input: status = [1,0,1,0], candies = [7,5,4,100], keys = [[],[],[1],[]], containedBoxes = [[1,2],[3],[],[]], initialBoxes = [0]
Output: 16
Explanation: You will be initially given box 0. You will find 7 candies in it and boxes 1 and 2. Box 1 is closed and you don't have a key for
In box 1, you will find 5 candies and box 3 but you will not find a key to box 3 so box 3 will remain closed.
Total number of candies collected = 7 + 4 + 5 = 16 candy.

Example 2:

Input: status = [1,0,0,0,0,0], candies = [1,1,1,1,1,1], keys = [[1,2,3,4,5],[],[],[],[],[]], containedBoxes = [[1,2,3,4,5],[],[],[],[],[]], i


Output: 6
Explanation: You have initially box 0. Opening it you can find boxes 1,2,3,4 and 5 and their keys. The total number of candies will be 6.

Example 3:

Input: status = [1,1,1], candies = [100,1,100], keys = [[],[0,2],[]], containedBoxes = [[],[],[]], initialBoxes = [1]
Output: 1

Example 4:

Input: status = [1], candies = [100], keys = [[]], containedBoxes = [[]], initialBoxes = []
Output: 0

Example 5:

Input: status = [1,1,1], candies = [2,3,2], keys = [[],[],[]], containedBoxes = [[],[],[]], initialBoxes = [2,1,0]
Output: 7

Constraints:

1 <= status.length <= 1000


status.length == candies.length == keys.length == containedBoxes.length == n
status[i] is 0 or 1.
1 <= candies[i] <= 1000
0 <= keys[i].length <= status.length
0 <= keys[i][j] < status.length
All values in keys[i] are unique.
0 <= containedBoxes[i].length <= status.length
0 <= containedBoxes[i][j] < status.length
All values in containedBoxes[i] are unique.
Each box is contained in one box at most.
0 <= initialBoxes.length <= status.length
0 <= initialBoxes[i] < status.length
**************************************

257. Maximum Candies You Can Get from Boxes(C++)


**************************************

1 // Time: O(n^2)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int maxCandies(vector& status, vector& candies, vector>& keys, vector>& containedBoxes, vector& initialBoxes) {
7 int result = 0;
8 queue q;
9 for (const auto& box : initialBoxes) {
10 q.emplace(box);
11 }
12 while (!q.empty()) {
13 bool changed = false;
14 for (int i = q.size() - 1; i >= 0; --i) {
15 const auto box = q.front(); q.pop();
16 if (!status[box]) {
17 q.emplace(box);
18 continue;
19 }
20 changed = true;
21 result += candies[box];
22 for (const auto& contained_key : keys[box]) {
23 status[contained_key] = 1;
24 }
25 for (const auto& contained_box : containedBoxes[box]) {
26 q.emplace(contained_box);
27 }
28 }
29 if (!changed) {
30 break;
31 }
32 }
33 return result;
34 }
35 };
**************************************

257. Maximum Candies You Can Get from Boxes(Python)


**************************************

1 # Time: O(n^2)
2 # Space: O(n)
3
4 import collections
5
6
7 class Solution(object):
8 def maxCandies(self, status, candies, keys, containedBoxes, initialBoxes):
9 """
10 :type status: List[int]
11 :type candies: List[int]
12 :type keys: List[List[int]]
13 :type containedBoxes: List[List[int]]
14 :type initialBoxes: List[int]
15 :rtype: int
16 """
17 result = 0
18 q = collections.deque(initialBoxes)
19 while q:
20 changed = False
21 for _ in xrange(len(q)):
22 box = q.popleft()
23 if not status[box]:
24 q.append(box)
25 continue
26 changed = True
27 result += candies[box]
28 for contained_key in keys[box]:
29 status[contained_key] = 1
30 for contained_box in containedBoxes[box]:
31 q.append(contained_box)
32 if not changed:
33 break
34 return result
******************************

258. Number of Paths with Max Score


******************************

You are given a square board of characters. You can move on the board starting at the bottom right square marked with the
character 'S'.

You need to reach the top left square marked with the character'E'. The rest of the squares are labeled either with a numeric
character 1, 2, ..., 9 or with an obstacle 'X'. In one move you can go up, left or up-left (diagonally) only if there is no obstacle
there.

Return a list of two integers: the first integer is the maximum sum of numeric characters you can collect, and the second is
the number of such paths that you can take to get that maximum sum, taken modulo 10^9 + 7 .

In case there is no path, return [0, 0].

Example 1:

Input: board = ["E23","2X2","12S"]


Output: [7,1]

Example 2:

Input: board = ["E12","1X1","21S"]


Output: [4,2]

Example 3:

Input: board = ["E11","XXX","11S"]


Output: [0,0]

Constraints:

2 <= board.length == board[i].length <= 100


******************************

258. Number of Paths with Max Score(C++)


******************************

1 // Time: O(n^2)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 vector pathsWithMaxScore(vector& board) {
7 static const int MOD = 1e9 + 7;
8 static const vector> directions{{1, 0}, {0, 1}, {1, 1}};
9
10 vector>> dp(2, vector>(board[0].size() + 1, vector(2)));
11 dp[(board.size() - 1) % 2][board[0].size() - 1] = {0, 1};
12 for (int r = board.size() - 1; r >= 0; --r) {
13 for (int c = board[0].size() - 1; c >= 0; --c) {
14 if (board[r][c] == 'S' || board[r][c] == 'X') {
15 continue;
16 }
17 dp[r % 2][c] = {0, 0};
18 for (const auto& [dr, dc] : directions) {
19 if (dp[r % 2][c][0] < dp[(r + dr) % 2][c + dc][0]) {
20 dp[r % 2][c] = dp[(r + dr) % 2][c + dc];
21 } else if (dp[r % 2][c][0] == dp[(r + dr) % 2][c + dc][0]) {
22 dp[r % 2][c][1] = (dp[r % 2][c][1]+dp[(r + dr) % 2][c + dc][1]) % MOD;
23 }
24 }
25 if (dp[r % 2][c][1] && board[r][c] != 'E') {
26 dp[r % 2][c][0] += board[r][c] - '0';
27 }
28 }
29 }
30 return dp[0][0];
31 }
32 };
******************************

258. Number of Paths with Max Score(Python)


******************************

1 # Time: O(n^2)
2 # Space: O(n)
3
4 class Solution(object):
5 def pathsWithMaxScore(self, board):
6 """
7 :type board: List[str]
8 :rtype: List[int]
9 """
10 MOD = 10**9+7
11 directions = [[1, 0], [0, 1], [1, 1]]
12 dp = [[[0, 0] for r in xrange(len(board[0])+1)]
13 for r in xrange(2)]
14 dp[(len(board)-1)%2][len(board[0])-1] = [0, 1]
15 for r in reversed(xrange(len(board))):
16 for c in reversed(xrange(len(board[0]))):
17 if board[r][c] in "XS":
18 continue
19 dp[r%2][c] = [0, 0]
20 for dr, dc in directions:
21 if dp[r%2][c][0] < dp[(r+dr)%2][c+dc][0]:
22 dp[r%2][c] = dp[(r+dr)%2][c+dc][:]
23 elif dp[r%2][c][0] == dp[(r+dr)%2][c+dc][0]:
24 dp[r%2][c][1] = (dp[r%2][c][1]+dp[(r+dr)%2][c+dc][1]) % MOD
25 if dp[r%2][c][1] and board[r][c] != 'E':
26 dp[r%2][c][0] += int(board[r][c])
27 return dp[0][0]
************************

259. Verbal Arithmetic Puzzle


************************

Given an equation, represented by words on left side and the result on right side.

You need to check if the equation is solvable under the following rules:

Each character is decoded as one digit (0 - 9).


Every pair of different characters they must map to different digits.
Each words[i] and result are decoded as one number without leading zeros.
Sum of numbers on left side (words) will equal to the number on right side r(esult).

Return True if the equation is solvable otherwise return False.

Example 1:

Input: words = ["SEND","MORE"], result = "MONEY"


Output: true
Explanation: Map 'S'-> 9, 'E'->5, 'N'->6, 'D'->7, 'M'->1, 'O'->0, 'R'->8, 'Y'->'2'
Such that: "SEND" + "MORE" = "MONEY" , 9567 + 1085 = 10652

Example 2:

Input: words = ["SIX","SEVEN","SEVEN"], result = "TWENTY"


Output: true
Explanation: Map 'S'-> 6, 'I'->5, 'X'->0, 'E'->8, 'V'->7, 'N'->2, 'T'->1, 'W'->'3', 'Y'->4
Such that: "SIX" + "SEVEN" + "SEVEN" = "TWENTY" , 650 + 68782 + 68782 = 138214

Example 3:

Input: words = ["THIS","IS","TOO"], result = "FUNNY"


Output: true

Example 4:

Input: words = ["LEET","CODE"], result = "POINT"


Output: false

Constraints:

2 <= words.length <= 5


1 <= words[i].length, result.length <= 7
words[i], result contain only uppercase
English letters.
The number of different characters used in the expression is at most10.
************************

259. Verbal Arithmetic Puzzle(C++)


************************
1 // Time: O(10!* n * l)
2 // Space: O(n * l)
3
4 class Solution {
5 public:
6 bool isSolvable(vector& words, string result) {
7 for (auto& w : words) {
8 reverse(w.begin(), w.end());
9 }
10 reverse(result.begin(), result.end());
11 unordered_map lookup;
12 unordered_set used;
13 return backtracking(words, result, 0, 0, 0, &lookup, &used);
14 }
15
16 private:
17 bool backtracking(const vector& words, const string& result,
18 int i, int j, int carry,
19 unordered_map *lookup,
20 unordered_set *used) {
21 if (j == result.length()) {
22 return carry == 0;
23 }
24
25 if (i != words.size()) {
26 if (j >= words[i].length() || lookup->count(words[i][j])) {
27 return backtracking(words, result, i + 1, j, carry, lookup, used);
28 }
29 for (int val = 0; val < 10; ++val) {
30 if (used->count(val) || (val == 0 && j == words[i].length() - 1)) {
31 continue;
32 }
33 (*lookup)[words[i][j]] = val;
34 used->emplace(val);
35 if (backtracking(words, result, i + 1, j, carry, lookup, used)) {
36 return true;
37 }
38 used->erase(val);
39 lookup->erase(words[i][j]);
40 }
41 return false;
42 }
43
44 const auto& total = accumulate(words.cbegin(), words.cend(), carry,
45 [&j, &lookup](const auto& x, const auto& y) {
46 return (j < y.length()) ? x + (*lookup)[y[j]] : x;
47 });
48 carry = total / 10;
49 int val = total % 10;
50 if (lookup->count(result[j])) {
51 return val == (*lookup)[result[j]] &&
52 backtracking(words, result, 0, j + 1, carry, lookup, used);
53 }
54 if (used->count(val) || (val == 0 && j == result.length() - 1)) {
55 return false;
56 }
57 (*lookup)[result[j]] = val;
58 used->emplace(val);
59 if (backtracking(words, result, 0, j + 1, carry, lookup, used)) {
60 return true;
61 }
62 used->erase(val);
63 lookup->erase(result[j]);
64 return false;
65 }
66 };
************************

259. Verbal Arithmetic Puzzle(Python)


************************

1 # Time: O(10! * n * l)
2 # Space: O(n * l)
3
4 import collections
5
6
7 class Solution(object):
8 def isSolvable(self, words, result):
9 """
10 :type words: List[str]
11 :type result: str
12 :rtype: bool
13 """
14 def backtracking(words, result, i, j, carry, lookup, used):
15 if j == len(result):
16 return carry == 0
17
18 if i != len(words):
19 if j >= len(words[i]) or words[i][j] in lookup:
20 return backtracking(words, result, i+1, j, carry, lookup, used)
21 for val in xrange(10):
22 if val in used or (val == 0 and j == len(words[i])-1):
23 continue
24 lookup[words[i][j]] = val
25 used.add(val)
26 if backtracking(words, result, i+1, j, carry, lookup, used):
27 return True
28 used.remove(val)
29 del lookup[words[i][j]]
30 return False
31
32 carry, val = divmod(carry + sum(lookup[w[j]] for w in words if j < len(w)), 10)
33 if result[j] in lookup:
34 return val == lookup[result[j]] and \
35 backtracking(words, result, 0, j+1, carry, lookup, used)
36 if val in used or (val == 0 and j == len(result)-1):
37 return False
38 lookup[result[j]] = val
39 used.add(val)
40 if backtracking(words, result, 0, j+1, carry, lookup, used):
41 return True
42 used.remove(val)
43 del lookup[result[j]]
44 return False
45
46 return backtracking([w[::-1] for w in words], result[::-1], 0, 0, 0, {}, set())
***************************************************

260. Minimum Insertion Steps to Make a String


Palindrome
***************************************************

Given a string s . In one step you can insert any character at any index of the string.

Return the minimum number of steps to make s palindrome.

A Palindrome String is one that reads the same backward as well as forward.

Example 1:

Input: s = "zzazz"
Output: 0
Explanation: The string "zzazz" is already palindrome we don't need any insertions.

Example 2:

Input: s = "mbadm"
Output: 2
Explanation: String can be "mbdadbm" or "mdbabdm".

Example 3:

Input: s = "leetcode"
Output: 5
Explanation: Inserting 5 characters the string becomes "leetcodocteel".

Example 4:

Input: s = "g"
Output: 0

Example 5:

Input: s = "no"
Output: 1

Constraints:

1 <= s.length <= 500


All characters of s are lower case English letters.
***************************************************

260. Minimum Insertion Steps to Make a String


Palindrome(C++)
***************************************************

1 // Time: O(n^2)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int minInsertions(string s) {
7 const string reversed_s(s.crbegin(), s.crend());
8 return s.length() - longestCommonSubsequence(s, reversed_s);
9 }
10
11 private:
12 int longestCommonSubsequence(const string& text1, const string& text2) {
13 if (text1.length() < text2.length()) {
14 return longestCommonSubsequence(text2, text1);
15 }
16 vector> dp(2, vector(text2.length() + 1));
17 for (int i = 1; i <= text1.length(); ++i) {
18 for (int j = 1; j <= text2.length(); ++j) {
19 dp[i % 2][j] = (text1[i - 1] == text2[j - 1])
20 ? dp[(i - 1) % 2][j - 1] + 1
21 : max(dp[(i - 1) % 2][j], dp[i % 2][j - 1]);
22
23 }
24 }
25 return dp[text1.length() % 2][text2.length()];
26 }
27 };
***************************************************

260. Minimum Insertion Steps to Make a String


Palindrome(Python)
***************************************************

1 # Time: O(n^2)
2 # Space: O(n)
3
4 class Solution(object):
5 def minInsertions(self, s):
6 """
7 :type s: str
8 :rtype: int
9 """
10 def longestCommonSubsequence(text1, text2):
11 if len(text1) < len(text2):
12 return self.longestCommonSubsequence(text2, text1)
13 dp = [[0 for _ in xrange(len(text2)+1)] for _ in xrange(2)]
14 for i in xrange(1, len(text1)+1):
15 for j in xrange(1, len(text2)+1):
16 dp[i%2][j] = dp[(i-1)%2][j-1]+1 if text1[i-1] == text2[j-1] \
17 else max(dp[(i-1)%2][j], dp[i%2][j-1])
18 return dp[len(text1)%2][len(text2)]
19
20 return len(s)-longestCommonSubsequence(s, s[::-1])
************************

261. Distinct Echo Substrings


************************

Return the number of distinct non-empty substrings of text that can be written as the concatenation of some string with itself
(i.e. it can be written as a + a where a is some string).

Example 1:

Input: text = "abcabcabc"


Output: 3
Explanation: The 3 substrings are "abcabc", "bcabca" and "cabcab".

Example 2:

Input: text = "leetcodeleetcode"


Output: 2
Explanation: The 2 substrings are "ee" and "leetcodeleetcode".

Constraints:

1 <= text.length <= 2000


text has only lowercase English letters.
************************

261. Distinct Echo Substrings(C++)


************************

1 // Time: O(n^2 + d), d is the duplicated of result substrings size


2 // Space: O(r), r is the size of result substrings set
3
4 class Solution {
5 public:
6 int distinctEchoSubstrings(string text) {
7 unordered_set result;
8 int l = text.length() - 1;
9 for (int i = 0; i < l; ++i) { // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcdefabcdefabcdef
10 const auto& substr_len = KMP(text, i, &result);
11 if (substr_len != numeric_limits::max()) {
12 l = min(l, i + substr_len);
13 }
14 }
15 return result.size();
16 }
17
18 private:
19 int KMP(const string& text, int l, unordered_set *result) {
20 vector prefix(text.length() - l, -1);
21 int j = -1;
22 for (int i = 1; i < prefix.size(); ++i) {
23 while (j > -1 && text[l + j + 1] != text[l + i]) {
24 j = prefix[j];
25 }
26 if (text[l + j + 1] == text[l + i]) {
27 ++j;
28 }
29 prefix[i] = j;
30 if ((j + 1) && (i + 1) % ((i + 1) - (j + 1)) == 0 &&
31 (i + 1) / ((i + 1) - (j + 1)) % 2 == 0) {
32 result->emplace(text.substr(l, i + 1));
33 }
34 }
35 return (prefix.back() + 1 && (prefix.size() % (prefix.size() - (prefix.back() + 1)) == 0))
36 ? (prefix.size() - (prefix.back() + 1))
37 : numeric_limits::max();
38 }
39 };
40
41 // Time: O(n^2 + d), d is the duplicated of result substrings size
42 // Space: O(r), r is the size of result substrings set
43 class Solution2 {
44 public:
45 int distinctEchoSubstrings(string text) {
46 unordered_set result;
47 for (int l = 1; l <= text.length() / 2; ++l) {
48 int count = 0;
49 for (int i = 0; i < l; ++i) {
50 count += int(text[i] == text[i + l]);
51 }
52 for (int i = 0; i < text.length() - 2 * l; ++i) {
53 if (count == l) {
54 result.emplace(text.substr(i, l));
55 }
56 count += int(text[i + l] == text[i + l + l]) - int(text[i] == text[i + l]);
57 }
58 if (count == l) {
59 result.emplace(text.substr(text.length() - 2 * l, l));
60 }
61 }
62 return result.size();
63 }
64 };
65
66 // Time: O(n^2 + d), d is the duplicated of result substrings size
67 // Space: O(r), r is the size of result substrings set
68 class Solution3 {
69 public:
70 int distinctEchoSubstrings(string text) {
71 static int MOD = 1e9 + 7;
72 int D = 27; // a-z and ''
73 unordered_set result;
74 for (int i = 0; i < text.length(); ++i) {
75 uint64_t left = 0, right = 0, pow_D = 1;
76 for (int l = 1; l < min(i + 2, int(text.length()) - i); ++l) {
77 left = (D * left + text[i - l + 1] - 'a' + 1) % MOD;
78 right = (pow_D * (text[i + l] - 'a' + 1) % MOD + right) % MOD;
79 if (left == right) { // assumed no collision
80 result.emplace(left);
81 }
82 pow_D = (pow_D * D) % MOD;
83 }
84 }
85 return result.size();
86 }
87 };
88
89 // Time: O(n^3 + d), d is the duplicated of result substrings size
90 // Space: O(r), r is the size of result substrings set
91 class Solution_TLE {
92 public:
93 int distinctEchoSubstrings(string text) {
94 static int MOD = 1e9 + 7;
95 int D = 27; // a-z and ''
96 unordered_set result;
97 for (int i = 0; i < text.length(); ++i) {
98 uint64_t left = 0, right = 0, pow_D = 1;
99 for (int l = 1; l < min(i + 2, int(text.length()) - i); ++l) {
100 left = (D * left + text[i - l + 1] - 'a' + 1) % MOD;
101 right = (pow_D * (text[i + l] - 'a' + 1) % MOD + right) % MOD;
102 if (left == right && compare(text, l, i - l + 1, i + 1)) {
103 result.emplace(text.substr(i + 1, l));
104 }
105 pow_D = (pow_D * D) % MOD;
106 }
107 }
108 return result.size();
109 }
110
111 private:
112 bool compare(const string& text, size_t l, int s1, int s2) {
113 for (int i = 0; i < l; ++i) {
114 if (text[s1 + i] != text[s2 + i]) {
115 return false;
116 }
117 }
118 return true;
119 }
120 };
************************

261. Distinct Echo Substrings(Python)


************************

1 # Time: O(n^2 + d), d is the duplicated of result substrings size


2 # Space: O(r), r is the size of result substrings set
3
4 class Solution(object):
5 def distinctEchoSubstrings(self, text):
6 """
7 :type text: str
8 :rtype: int
9 """
10 def KMP(text, l, result):
11 prefix = [-1]*(len(text)-l)
12 j = -1
13 for i in xrange(1, len(prefix)):
14 while j > -1 and text[l+j+1] != text[l+i]:
15 j = prefix[j]
16 if text[l+j+1] == text[l+i]:
17 j += 1
18 prefix[i] = j
19 if (j+1) and (i+1) % ((i+1) - (j+1)) == 0 and \
20 (i+1) // ((i+1) - (j+1)) % 2 == 0:
21 result.add(text[l:l+i+1])
22 return len(prefix)-(prefix[-1]+1) \
23 if prefix[-1]+1 and len(prefix) % (len(prefix)-(prefix[-1]+1)) == 0 \
24 else float("inf")
25
26 result = set()
27 i, l = 0, len(text)-1
28 while i < l: # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcdefabcdefabcdef
29 l = min(l, i + KMP(text, i, result));
30 i += 1
31 return len(result)
32
33
34 # Time: O(n^2 + d), d is the duplicated of result substrings size
35 # Space: O(r), r is the size of result substrings set
36 class Solution2(object):
37 def distinctEchoSubstrings(self, text):
38 """
39 :type text: str
40 :rtype: int
41 """
42 result = set()
43 for l in xrange(1, len(text)//2+1):
44 count = sum(text[i] == text[i+l] for i in xrange(l))
45 for i in xrange(len(text)-2*l):
46 if count == l:
47 result.add(text[i:i+l])
48 count += (text[i+l] == text[i+l+l]) - (text[i] == text[i+l])
49 if count == l:
50 result.add(text[len(text)-2*l:len(text)-2*l+l])
51 return len(result)
52
53
54 # Time: O(n^2 + d), d is the duplicated of result substrings size
55 # Space: O(r), r is the size of result substrings set
56 class Solution3(object):
57 def distinctEchoSubstrings(self, text):
58 """
59 :type text: str
60 :rtype: int
61 """
62 MOD = 10**9+7
63 D = 27 # a-z and ''
64 result = set()
65 for i in xrange(len(text)-1):
66 left, right, pow_D = 0, 0, 1
67 for l in xrange(1, min(i+2, len(text)-i)):
68 left = (D*left + (ord(text[i-l+1])-ord('a')+1)) % MOD
69 right = (pow_D*(ord(text[i+l])-ord('a')+1) + right) % MOD
70 if left == right: # assumed no collision
71 result.add(left)
72 pow_D = (pow_D*D) % MOD
73 return len(result)
74
75
76 # Time: O(n^3 + d), d is the duplicated of result substrings size
77 # Space: O(r), r is the size of result substrings set
78 class Solution_TLE(object):
79 def distinctEchoSubstrings(self, text):
80 """
81 :type text: str
82 :rtype: int
83 """
84 def compare(text, l, s1, s2):
85 for i in xrange(l):
86 if text[s1+i] != text[s2+i]:
87 return False
88 return True
89
90 MOD = 10**9+7
91 D = 27 # a-z and ''
92 result = set()
93 for i in xrange(len(text)):
94 left, right, pow_D = 0, 0, 1
95 for l in xrange(1, min(i+2, len(text)-i)):
96 left = (D*left + (ord(text[i-l+1])-ord('a')+1)) % MOD
97 right = (pow_D*(ord(text[i+l])-ord('a')+1) + right) % MOD
98 if left == right and compare(text, l, i-l+1, i+1):
99 result.add(text[i+1:i+1+l])
100 pow_D = (pow_D*D) % MOD
101 return len(result)
*************************************************

262. Minimum Distance to Type a Word Using Two


Fingers
*************************************************

You have a keyboard layout as shown above in theX-Y plane, where each English uppercase letter is located at some
coordinate.

For example, the letter 'A' is located at coordinate (0, 0) , the letter 'B' is located at coordinate (0, 1) , the letter 'P' is located
at coordinate (2, 3) and the letter 'Z' is located at coordinate (4, 1) .

Given the string word, return the minimum total distance to type such string using only two fingers.

The distance between coordinates (x1, y 1) and (x2, y 2) is |x1 - x 2| + |y 1 - y 2|.

Note that the initial positions of your two fingers are considered free so do not count towards your total distance, also your
two fingers do not have to start at the first letter or the first two letters.

Example 1:

Input: word = "CAKE"


Output: 3
Explanation:
Using two fingers, one optimal way to type "CAKE" is:
Finger 1 on letter 'C' -> cost = 0
Finger 1 on letter 'A' -> cost = Distance from letter 'C' to letter 'A' = 2
Finger 2 on letter 'K' -> cost = 0
Finger 2 on letter 'E' -> cost = Distance from letter 'K' to letter 'E' = 1
Total distance = 3

Example 2:

Input: word = "HAPPY"


Output: 6
Explanation:
Using two fingers, one optimal way to type "HAPPY" is:
Finger 1 on letter 'H' -> cost = 0
Finger 1 on letter 'A' -> cost = Distance from letter 'H' to letter 'A' = 2
Finger 2 on letter 'P' -> cost = 0
Finger 2 on letter 'P' -> cost = Distance from letter 'P' to letter 'P' = 0
Finger 1 on letter 'Y' -> cost = Distance from letter 'A' to letter 'Y' = 4
Total distance = 6

Example 3:
Input: word = "NEW"
Output: 3

Example 4:

Input: word = "YEAR"


Output: 7

Constraints:

2 <= word.length <= 300


word consists of uppercase English letters.
*************************************************

262. Minimum Distance to Type a Word Using Two


Fingers(C++)
*************************************************

1 // Time: O(26n)
2 // Space: O(26)
3
4 class Solution {
5 public:
6 int minimumDistance(string word) {
7 vector dp(26);
8 for (int i = 0; i < word.length() - 1; ++i) {
9 int b = word[i] - 'A', c = word[i + 1] - 'A';
10 for (int a = 0; a < 26; ++a) {
11 dp[b] = max(dp[b], dp[a] - distance(a, c) + distance(b, c));
12 }
13 }
14 int result = 0;
15 for (int i = 0; i < word.length() - 1; ++i) {
16 result += distance(word[i] - 'A', word[i + 1] - 'A');
17 }
18 return result - *max_element(dp.cbegin(), dp.cend());
19 }
20
21 private:
22 int distance(int a, int b) {
23 return abs(a / 6 - b / 6) + abs(a % 6 - b % 6);
24 }
25 };
26
27 // Time: O(52n)
28 // Space: O(52)
29 class Solution2 {
30 private:
31 template
32 struct PairHash {
33 size_t operator()(const pair& p) const {
34 size_t seed = 0;
35 seed ^= std::hash{}(p.first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
36 seed ^= std::hash{}(p.second) + 0x9e3779b9 + (seed<<6) + (seed>>2);
37 return seed;
38 }
39 };
40
41 public:
42 int minimumDistance(string word) {
43 unordered_map, int, PairHash> dp = {{{-1, -1}, 0}};
44 for (const auto& w : word) {
45 int c = w - 'A';
46 unordered_map, int, PairHash> new_dp;
47 for (const auto& [p, v] : dp) {
48 const auto& [a, b] = p;
49 if (!new_dp.count(make_pair(c, b)) ||
50 v + distance(a, c) < new_dp[make_pair(c, b)]) {
51 new_dp[make_pair(c, b)] = v + distance(a, c);
52 }
53 if (!new_dp.count(make_pair(a, c)) ||
54 v + distance(b, c) < new_dp[make_pair(a, c)]) {
55 new_dp[make_pair(a, c)] = v + distance(b, c);
56 };
57 }
58 dp = move(new_dp);
59 }
60 return min_element(dp.cbegin(), dp.cend(),
60
61 [](const auto&a, const auto& b) {
62 return a.second < b.second;
63 })->second;
64 }
65
66 private:
67 int distance(int a, int b) {
68 if (a == -1 || b == -1) {
69 return 0;
70 }
71 return abs(a / 6 - b / 6) + abs(a % 6 - b % 6);
72 }
73 };
*************************************************

262. Minimum Distance to Type a Word Using Two


Fingers(Python)
*************************************************

1 # Time: O(26n)
2 # Space: O(26)
3
4 class Solution(object):
5 def minimumDistance(self, word):
6 """
7 :type word: str
8 :rtype: int
9 """
10 def distance(a, b):
11 return abs(a//6 - b//6) + abs(a%6 - b%6)
12
13 dp = [0]*26
14 for i in xrange(len(word)-1):
15 b, c = ord(word[i])-ord('A'), ord(word[i+1])-ord('A')
16 dp[b] = max(dp[a] - distance(a, c) + distance(b, c) for a in xrange(26))
17 return sum(distance(ord(word[i])-ord('A'), ord(word[i+1])-ord('A')) for i in xrange(len(word)-1)) - max(dp)
18
19
20 # Time: O(52n)
21 # Space: O(52)
22 class Solution2(object):
23 def minimumDistance(self, word):
24 """
25 :type word: str
26 :rtype: int
27 """
28 def distance(a, b):
29 if -1 in [a, b]:
30 return 0
31 return abs(a//6 - b//6) + abs(a%6 - b%6)
32
33 dp = {(-1, -1): 0}
34 for c in word:
35 c = ord(c)-ord('A')
36 new_dp = {}
37 for a, b in dp:
38 new_dp[c, b] = min(new_dp.get((c, b), float("inf")), dp[a, b] + distance(a, c))
39 new_dp[a, c] = min(new_dp.get((a, c), float("inf")), dp[a, b] + distance(b, c))
40 dp = new_dp
41 return min(dp.itervalues())
************************************************

263. Minimum Number of Taps to Open to Water a Garden


************************************************

There is a one-dimensional garden on the x-axis. The garden starts at the point0 and ends at the point n. (i.e The length of
the garden is n).

There are n + 1 taps located at points [0, 1, ..., n] in the garden.

Given an integer n and an integer array ranges of length n + 1 where ranges[i] (0-indexed) means the i-th tap can water the area [i
- ranges[i], i + ranges[i]] if it was open.

Return the minimum number of taps that should be open to water the whole garden, If the garden cannot be watered return-
1.

Example 1:

Input: n = 5, ranges = [3,4,1,1,0,0]


Output: 1
Explanation: The tap at point 0 can cover the interval [-3,3]
The tap at point 1 can cover the interval [-3,5]
The tap at point 2 can cover the interval [1,3]
The tap at point 3 can cover the interval [2,4]
The tap at point 4 can cover the interval [4,4]
The tap at point 5 can cover the interval [5,5]
Opening Only the second tap will water the whole garden [0,5]

Example 2:

Input: n = 3, ranges = [0,0,0,0]


Output: -1
Explanation: Even if you activate all the four taps you cannot water the whole garden.

Example 3:

Input: n = 7, ranges = [1,2,1,0,2,1,0,1]


Output: 3

Example 4:
Input: n = 8, ranges = [4,0,0,0,0,0,0,0,4]
Output: 2

Example 5:

Input: n = 8, ranges = [4,0,0,0,4,0,0,0,4]


Output: 1

Constraints:

1 <= n <= 10^4


ranges.length == n + 1
0 <= ranges[i] <= 100
************************************************

263. Minimum Number of Taps to Open to Water a


Garden(C++)
************************************************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int minTaps(int n, vector& ranges) {
7 vector max_range(n + 1);
8 for (int i = 0; i < ranges.size(); ++i) {
9 int left = max(i - ranges[i], 0), right = min(i + ranges[i], n);
10 max_range[left] = max(max_range[left], right - left);
11 }
12 return jumpGame(max_range);
13 }
14
15 private:
16 int jumpGame(const vector& A) {
17 int jump_count = 0, reachable = 0, curr_reachable = 0;
18 for (int i = 0; i < A.size(); ++i) {
19 if (i > reachable) {
20 return -1;
21 }
22 if (i > curr_reachable) {
23 curr_reachable = reachable;
24 ++jump_count;
25 }
26 reachable = max(reachable, i + A[i]);
27 }
28 return jump_count;
29 }
30 };
************************************************

263. Minimum Number of Taps to Open to Water a


Garden(Python)
************************************************

1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 def minTaps(self, n, ranges):
6 """
7 :type n: int
8 :type ranges: List[int]
9 :rtype: int
10 """
11 def jump_game(A):
12 jump_count, reachable, curr_reachable = 0, 0, 0
13 for i, length in enumerate(A):
14 if i > reachable:
15 return -1
16 if i > curr_reachable:
17 curr_reachable = reachable
18 jump_count += 1
19 reachable = max(reachable, i+length)
20 return jump_count
21
22 max_range = [0]*(n+1)
23 for i, r in enumerate(ranges):
24 left, right = max(i-r, 0), min(i+r, n)
25 max_range[left] = max(max_range[left], right-left)
26 return jump_game(max_range)
****************************************

264. Reverse Subarray To Maximize Array Value


****************************************

You are given an integer array nums. The value of this array is defined as the sum of|nums[i]-nums[i+1]| for all 0 <= i < nums.length-
1.

You are allowed to select any subarray of the given array and reverse it. You can perform this operationonly once.

Find maximum possible value of the final array.

Example 1:

Input: nums = [2,3,1,5,4]


Output: 10
Explanation: By reversing the subarray [3,1,5] the array becomes [2,5,1,3,4] whose value is 10.

Example 2:

Input: nums = [2,4,9,24,2,1,10]


Output: 68

Constraints:

1 <= nums.length <= 3*10^4


-10^5 <= nums[i] <= 10^5
****************************************

264. Reverse Subarray To Maximize Array Value(C++)


****************************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int maxValueAfterReverse(vector& nums) {
7 int result = 0, add = 0;
8 int max_pair = numeric_limits::min(), min_pair = numeric_limits::max();
9 for (int i = 1; i < nums.size(); ++i) {
10 result += abs(nums[i-1] - nums[i]);
11 add = max({add,
12 abs(nums[0] - nums[i]) - abs(nums[i - 1] - nums[i]),
13 abs(nums.back() - nums[i - 1]) - abs(nums[i - 1] - nums[i])});
14 min_pair = min(min_pair, max(nums[i - 1], nums[i]));
15 max_pair = max(max_pair, min(nums[i - 1], nums[i]));
16 }
17 return result + max(add, (max_pair - min_pair) * 2);
18 }
19 };
****************************************

264. Reverse Subarray To Maximize Array Value(Python)


****************************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def maxValueAfterReverse(self, nums):
6 """
7 :type nums: List[int]
8 :rtype: int
9 """
10 result, add, max_pair, min_pair = 0, 0, float("-inf"), float("inf")
11 for i in xrange(1, len(nums)):
12 result += abs(nums[i-1]-nums[i])
13 add = max(add,
14 abs(nums[0]-nums[i]) - abs(nums[i-1]-nums[i]),
15 abs(nums[-1]-nums[i-1]) - abs(nums[i-1]-nums[i]))
16 min_pair = min(min_pair, max(nums[i-1], nums[i]))
17 max_pair = max(max_pair, min(nums[i-1], nums[i]))
18 return result + max(add, (max_pair-min_pair)*2)
************************************

265. Minimum Difficulty of a Job Schedule


************************************

You want to schedule a list of jobs ind days. Jobs are dependent (i.e To work on the i-th job, you have to finish all the jobsj
where 0 <= j < i ).

You have to finish at least one task every day. The difficulty of a job schedule is the sum of difficulties of each day of thed
days. The difficulty of a day is the maximum difficulty of a job done in that day.

Given an array of integers jobDifficulty and an integer d. The difficulty of the i-th job is jobDifficulty[i].

Return the minimum difficulty of a job schedule. If you cannot find a schedule for the jobs return-1.

Example 1:

Input: jobDifficulty = [6,5,4,3,2,1], d = 2


Output: 7
Explanation: First day you can finish the first 5 jobs, total difficulty = 6.
Second day you can finish the last job, total difficulty = 1.
The difficulty of the schedule = 6 + 1 = 7

Example 2:

Input: jobDifficulty = [9,9,9], d = 4


Output: -1
Explanation: If you finish a job per day you will still have a free day. you cannot find a schedule for the given jobs.

Example 3:

Input: jobDifficulty = [1,1,1], d = 3


Output: 3
Explanation: The schedule is one job per day. total difficulty will be 3.

Example 4:
Input: jobDifficulty = [7,1,7,1,7,1], d = 3
Output: 15

Example 5:

Input: jobDifficulty = [11,111,22,222,33,333,44,444], d = 6


Output: 843

Constraints:

1 <= jobDifficulty.length <= 300


0 <= jobDifficulty[i] <= 1000
1 <= d <= 10
************************************

265. Minimum Difficulty of a Job Schedule(C++)


************************************

1 // Time: O(d * n^2)


2 // Space: O(d * n)
3
4 class Solution {
5 public:
6 int minDifficulty(vector& jobDifficulty, int d) {
7 if (jobDifficulty.size() < d) {
8 return -1;
9 }
10
11 vector> dp(d,
12 vector(jobDifficulty.size(),
13 numeric_limits::max()));
14 dp[0][0] = jobDifficulty[0];
15 for (int i = 1; i < jobDifficulty.size(); ++i) {
16 dp[0][i] = max(dp[0][i - 1], jobDifficulty[i]);
17 }
18 for (int i = 1; i < d; ++i) {
19 for (int j = i; j < jobDifficulty.size(); ++j) {
20 int curr_max = jobDifficulty[j];
21 for (int k = j; k >= i; --k) {
22 curr_max = max(curr_max, jobDifficulty[k]);
23 if (dp[i - 1][k - 1] != numeric_limits::max()) {
24 dp[i][j] = min(dp[i][j], dp[i - 1][k - 1] + curr_max);
25 }
26 }
27 }
28 }
29 return dp[d - 1][jobDifficulty.size() - 1];
30 }
31 };
************************************

265. Minimum Difficulty of a Job Schedule(Python)


************************************

1 # Time: O(d * n^2)


2 # Space: O(d * n)
3
4 class Solution(object):
5 def minDifficulty(self, jobDifficulty, d):
6 """
7 :type jobDifficulty: List[int]
8 :type d: int
9 :rtype: int
10 """
11 if len(jobDifficulty) < d:
12 return -1;
13
14 dp = [[float("inf")]*len(jobDifficulty) for _ in xrange(d)]
15 dp[0][0] = jobDifficulty[0]
16 for i in xrange(1, len(jobDifficulty)):
17 dp[0][i] = max(dp[0][i-1], jobDifficulty[i])
18 for i in xrange(1, d):
19 for j in xrange(i, len(jobDifficulty)):
20 curr_max = jobDifficulty[j]
21 for k in reversed(xrange(i, j+1)):
22 curr_max = max(curr_max, jobDifficulty[k])
23 dp[i][j] = min(dp[i][j], dp[i-1][k-1] + curr_max)
24 return dp[d-1][len(jobDifficulty)-1]
***********

266. Jump Game V


***********

Given an array of integers arr and an integer d. In one step you can jump from index i to index:

i + x where: i + x < arr.length and 0 < x <= d.


i - x where: i - x >= 0 and 0 < x <= d.

In addition, you can only jump from index i to index j if arr[i] > arr[j] and arr[i] > arr[k] for all indices k between i and j (More formally
min(i, j) < k < max(i, j) ).

You can choose any index of the array and start jumping. Returnthe maximum number of indices you can visit.

Notice that you can not jump outside of the array at any time.

Example 1:

Input: arr = [6,4,14,6,8,13,9,7,10,6,12], d = 2


Output: 4
Explanation: You can start at index 10. You can jump 10 --> 8 --> 6 --> 7 as shown.
Note that if you start at index 6 you can only jump to index 7. You cannot jump to index 5 because 13 > 9. You cannot jump to index 4 because
Similarly You cannot jump from index 3 to index 2 or index 1.

Example 2:

Input: arr = [3,3,3,3,3], d = 3


Output: 1
Explanation: You can start at any index. You always cannot jump to any index.

Example 3:
Input: arr = [7,6,5,4,3,2,1], d = 1
Output: 7
Explanation: Start at index 0. You can visit all the indicies.

Example 4:

Input: arr = [7,1,7,1,7,1], d = 2


Output: 2

Example 5:

Input: arr = [66], d = 1


Output: 1

Constraints:

1 <= arr.length <= 1000


1 <= arr[i] <= 10^5
1 <= d <= arr.length
***********

266. Jump Game V(C++)


***********

1 // Time: O(n)
2 // Space: O(n)
3
4 // sliding window + top-down dp
5 class Solution {
6 public:
7 int maxJumps(vector& arr, int d) {
8 vector> left(arr.size());
9 deque decreasing_dq;
10 for (int i = 0; i < arr.size(); ++i) {
11 if (!decreasing_dq.empty() && i - decreasing_dq.front() == d + 1) {
12 decreasing_dq.pop_front();
13 }
14 while (!decreasing_dq.empty() && arr[decreasing_dq.back()] < arr[i]) {
15 if (!left[i].empty() && arr[left[i].back()] != arr[decreasing_dq.back()]) {
16 left[i].clear();
17 }
18 left[i].emplace_back(decreasing_dq.back());
19 decreasing_dq.pop_back();
20 }
21 decreasing_dq.emplace_back(i);
22 }
23 vector> right(arr.size());
24 decreasing_dq.clear();
25 for (int i = arr.size() - 1; i >= 0; --i) {
26 if (!decreasing_dq.empty() && decreasing_dq.front() - i == d + 1) {
27 decreasing_dq.pop_front();
28 }
29 while (!decreasing_dq.empty() && arr[decreasing_dq.back()] < arr[i]) {
30 if (!right[i].empty() && arr[right[i].back()] != arr[decreasing_dq.back()]) {
31 right[i].clear();
32 }
33 right[i].emplace_back(decreasing_dq.back());
34 decreasing_dq.pop_back();
35 }
36 decreasing_dq.emplace_back(i);
37 }
38
39 int result = 0;
40 vector lookup(arr.size());
41 for (int i = 0; i < arr.size(); ++i) {
42 result = max(result, dp(arr, d, i, left, right, &lookup));
43 }
44 return result;
45 }
46
47 private:
48 int dp(const vector& arr, int d, int i,
49 const vector>& left, const vector>& right,
50 vector *lookup) {
51 if ((*lookup)[i]) {
52 return (*lookup)[i];
53 }
54 (*lookup)[i] = 1;
55 // each dp[j] will be visited at most twice
56 for (const auto& j : left[i]) {
57 (*lookup)[i] = max((*lookup)[i], dp(arr, d, j, left, right, lookup) + 1);
58 }
59 for (const auto& j : right[i]) {
60 (*lookup)[i] = max((*lookup)[i], dp(arr, d, j, left, right, lookup) + 1);
61 }
62 return (*lookup)[i];
63 }
64 };
65
66 // Time: O(nlogn)
67 // Space: O(n)
68 // mono stack + bottom-up dp
69 class Solution2 {
70 public:
71 int maxJumps(vector& arr, int d) {
72 vector> left(arr.size());
73 vector decreasing_stk;
74 for (int i = 0; i < arr.size(); ++i) {
75 while (!decreasing_stk.empty() && arr[decreasing_stk.back()] < arr[i]) {
76 if (i - decreasing_stk.back() <= d) {
77 if (!left[i].empty() && arr[left[i].back()] != arr[decreasing_stk.back()]) {
78 left[i].clear();
79 }
80 left[i].emplace_back(decreasing_stk.back());
81 }
82 decreasing_stk.pop_back();
83 }
84 decreasing_stk.emplace_back(i);
85 }
86 vector> right(arr.size());
87 decreasing_stk.clear();
88 for (int i = arr.size() - 1; i >= 0; --i) {
89 while (!decreasing_stk.empty() && arr[decreasing_stk.back()] < arr[i]) {
90 if (decreasing_stk.back() - i <= d) {
91 if (!right[i].empty() && arr[right[i].back()] != arr[decreasing_stk.back()]) {
92 right[i].clear();
93 }
94 right[i].emplace_back(decreasing_stk.back());
95 }
96 decreasing_stk.pop_back();
97 }
98 decreasing_stk.emplace_back(i);
99 }
100
101 vector> sorted_arr;
102 for (int i = 0; i < arr.size(); ++i) {
103 sorted_arr.emplace_back(arr[i], i);
104 }
105 sort(sorted_arr.begin(), sorted_arr.end());
106 vector dp(arr.size(), 1);
107 for (const auto& [_, i] : sorted_arr) {
108 dp[i] = 1;
109 // each dp[j] will be visited at most twice
110 for (const auto& j : left[i]) {
111 dp[i] = max(dp[i], dp[j] + 1);
112 }
113 for (const auto& j : right[i]) {
114 dp[i] = max(dp[i], dp[j] + 1);
115 }
116 }
117 return *max_element(dp.cbegin(), dp.cend());
118 }
119 };
120
121 // Time: O(nlogn)
122 // Space: O(n)
123 // mono stack + bottom-up dp + segment tree
124 class Solution3 {
125 public:
126 int maxJumps(vector& arr, int d) {
127 vector left(arr.size()), decreasing_stk;
128 iota(left.begin(), left.end(), 0);
129 for (int i = 0; i < arr.size(); ++i) {
130 while (!decreasing_stk.empty() && arr[decreasing_stk.back()] < arr[i]) {
131 if (i - decreasing_stk.back() <= d) {
132 left[i] = decreasing_stk.back();
133 }
134 decreasing_stk.pop_back();
135 }
135 }
136 decreasing_stk.emplace_back(i);
137 }
138 vector right(arr.size());
139 decreasing_stk.clear();
140 iota(right.begin(), right.end(), 0);
141 for (int i = arr.size() - 1; i >= 0; --i) {
142 while (!decreasing_stk.empty() && arr[decreasing_stk.back()] < arr[i]) {
143 if (decreasing_stk.back() - i <= d) {
144 right[i] = decreasing_stk.back();
145 }
146 decreasing_stk.pop_back();
147 }
148 decreasing_stk.emplace_back(i);
149 }
150
151 vector> sorted_arr;
152 for (int i = 0; i < arr.size(); ++i) {
153 sorted_arr.emplace_back(arr[i], i);
154 }
155 sort(sorted_arr.begin(), sorted_arr.end());
156 SegmentTree segment_tree(arr.size());
157 for (const auto& [_, i] : sorted_arr) {
158 segment_tree.update(i, i, segment_tree.query(left[i], right[i]) + 1);
159 }
160 return segment_tree.query(0, arr.size() - 1);
161 }
162
163 private:
164 class SegmentTree {
165 public:
166 SegmentTree(int N)
167 : N_(N),
168 tree_(2 * N),
169 lazy_(N)
170 {
171 H_ = 1;
172 while ((1 << H_) < N) {
173 ++H_;
174 }
175 }
176
177 void update(int L, int R, int h) {
178 L += N_; R += N_;
179 int L0 = L, R0 = R;
180 while (L <= R) {
181 if ((L & 1) == 1) {
182 apply(L++, h);
183 }
184 if ((R & 1) == 0) {
185 apply(R--, h);
186 }
187 L >>= 1; R >>= 1;
188 }
189 pull(L0); pull(R0);
190 }
191
192 int query(int L, int R) {
193 auto result = 0;
194 if (L > R) {
195 return result;
196 }
197 L += N_; R += N_;
198 push(L); push(R);
199 while (L <= R) {
200 if ((L & 1) == 1) {
201 result = max(result, tree_[L++]);
202 }
203 if ((R & 1) == 0) {
204 result = max(result, tree_[R--]);
205 }
206 L >>= 1; R >>= 1;
207 }
208 return result;
208 return result;
209 }
210
211 private:
212 int N_, H_;
213 vector tree_, lazy_;
214
215 void apply(int x, int val) {
216 tree_[x] = val;
217 if (x < N_) {
218 lazy_[x] = val;
219 }
220 }
221
222 void pull(int x) {
223 while (x > 1) {
224 x >>= 1;
225 tree_[x] = max(tree_[x * 2], tree_[x * 2 + 1]);
226 if (lazy_[x] != 0) {
227 tree_[x] = lazy_[x];
228 }
229 }
230 }
231
232 void push(int x) {
233 for (int h = H_; h > 0; --h) {
234 int y = x >> h;
235 if (lazy_[y] != 0) {
236 apply(y * 2, lazy_[y]);
237 apply(y * 2 + 1, lazy_[y]);
238 lazy_[y] = 0;
239 }
240 }
241 }
242 };
243 };
***********

266. Jump Game V(Python)


***********

1 # Time: O(n)
2 # Space: O(n)
3
4 import collections
5 import itertools
6
7
8 # sliding window + top-down dp
9 class Solution(object):
10 def maxJumps(self, arr, d):
11 """
12 :type arr: List[int]
13 :type d: int
14 :rtype: int
15 """
16 def dp(arr, d, i, left, right, lookup):
17 if lookup[i]:
18 return lookup[i]
19 lookup[i] = 1
20 for j in itertools.chain(left[i], right[i]):
21 # each dp[j] will be visited at most twice
22 lookup[i] = max(lookup[i], dp(arr, d, j, left, right, lookup)+1)
23 return lookup[i]
24
25 left, decreasing_dq = [[] for _ in xrange(len(arr))], collections.deque()
26 for i in xrange(len(arr)):
27 if decreasing_dq and i - decreasing_dq[0] == d+1:
28 decreasing_dq.popleft()
29 while decreasing_dq and arr[decreasing_dq[-1]] < arr[i]:
30 if left[i] and arr[left[i][-1]] != arr[decreasing_dq[-1]]:
31 left[i] = []
32 left[i].append(decreasing_dq.pop())
33 decreasing_dq.append(i)
34 right, decreasing_dq = [[] for _ in xrange(len(arr))], collections.deque()
35 for i in reversed(xrange(len(arr))):
36 if decreasing_dq and decreasing_dq[0] - i == d+1:
37 decreasing_dq.popleft()
38 while decreasing_dq and arr[decreasing_dq[-1]] < arr[i]:
39 if right[i] and arr[right[i][-1]] != arr[decreasing_dq[-1]]:
40 right[i] = []
41 right[i].append(decreasing_dq.pop())
42 decreasing_dq.append(i)
43
44 lookup = [0]*len(arr)
45 return max(itertools.imap(lambda x: dp(arr, d, x, left, right, lookup), xrange(len(arr))))
46
47
48 # Time: O(nlogn)
49 # Space: O(n)
50 # mono stack + bottom-up dp
51 class Solution2(object):
52 def maxJumps(self, arr, d):
53 """
54 :type arr: List[int]
55 :type d: int
56 :rtype: int
57 """
58 left, decreasing_stk = [[] for _ in xrange(len(arr))], []
59 for i in xrange(len(arr)):
60 while decreasing_stk and arr[decreasing_stk[-1]] < arr[i]:
61 if i - decreasing_stk[-1] <= d:
62 if left[i] and arr[left[i][-1]] != arr[decreasing_stk[-1]]:
63 left[i] = []
64 left[i].append(decreasing_stk[-1])
65 decreasing_stk.pop()
66 decreasing_stk.append(i)
67 right, decreasing_stk = [[] for _ in xrange(len(arr))], []
68 for i in reversed(xrange(len(arr))):
69 while decreasing_stk and arr[decreasing_stk[-1]] < arr[i]:
70 if decreasing_stk[-1] - i <= d:
71 if right[i] and arr[right[i][-1]] != arr[decreasing_stk[-1]]:
72 right[i] = []
73 right[i].append(decreasing_stk[-1])
74 decreasing_stk.pop()
75 decreasing_stk.append(i)
76
77 dp = [0]*len(arr)
78 for a, i in sorted([a, i] for i, a in enumerate(arr)):
79 dp[i] = 1
80 for j in itertools.chain(left[i], right[i]):
81 # each dp[j] will be visited at most twice
82 dp[i] = max(dp[i], dp[j]+1)
83 return max(dp)
84
85
86 # Template:
87 # https://github.com/kamyu104/FacebookHackerCup-2018/blob/master/Final%20Round/the_claw.py
88 class SegmentTree(object):
89 def __init__(self, N,
90 build_fn=lambda x, y: [y]*(2*x),
91 query_fn=max,
92 update_fn=lambda x, y: y,
93 default_val=0):
94 self.N = N
95 self.H = (N-1).bit_length()
96 self.query_fn = query_fn
97 self.update_fn = update_fn
98 self.default_val = default_val
99 self.tree = build_fn(N, default_val)
100 self.lazy = [None]*N
101
102 def __apply(self, x, val):
103 self.tree[x] = self.update_fn(self.tree[x], val)
104 if x < self.N:
105 self.lazy[x] = self.update_fn(self.lazy[x], val)
106
107 def update(self, L, R, h): # Time: O(logN), Space: O(N)
108 def pull(x):
109 while x > 1:
110 x //= 2
111 self.tree[x] = self.query_fn(self.tree[x*2], self.tree[x*2+1])
112 if self.lazy[x] is not None:
113 self.tree[x] = self.update_fn(self.tree[x], self.lazy[x])
114 L += self.N
115 R += self.N
116 L0, R0 = L, R
117 while L <= R:
118 if L & 1: # is right child
119 self.__apply(L, h)
120 L += 1
121 if R & 1 == 0: # is left child
122 self.__apply(R, h)
123 R -= 1
124 L //= 2
125 R //= 2
126 pull(L0)
127 pull(R0)
128
129 def query(self, L, R): # Time: O(logN), Space: O(N)
130 def push(x):
131 n = 2**self.H
132 while n != 1:
133 y = x // n
134 if self.lazy[y] is not None:
135 self.__apply(y*2, self.lazy[y])
135 self.__apply(y*2, self.lazy[y])
136 self.__apply(y*2 + 1, self.lazy[y])
137 self.lazy[y] = None
138 n //= 2
139
140 result = self.default_val
141 if L > R:
142 return result
143
144 L += self.N
145 R += self.N
146 push(L)
147 push(R)
148 while L <= R:
149 if L & 1: # is right child
150 result = self.query_fn(result, self.tree[L])
151 L += 1
152 if R & 1 == 0: # is left child
153 result = self.query_fn(result, self.tree[R])
154 R -= 1
155 L //= 2
156 R //= 2
157 return result
158
159 def __str__(self):
160 showList = []
161 for i in xrange(self.N):
162 showList.append(self.query(i, i))
163 return ",".join(map(str, showList))
164
165
166 # Time: O(nlogn)
167 # Space: O(n)
168 # mono stack + bottom-up dp + segment tree
169 class Solution3(object):
170 def maxJumps(self, arr, d):
171 """
172 :type arr: List[int]
173 :type d: int
174 :rtype: int
175 """
176 left, decreasing_stk = range(len(arr)), []
177 for i in xrange(len(arr)):
178 while decreasing_stk and arr[decreasing_stk[-1]] < arr[i]:
179 if i - decreasing_stk[-1] <= d:
180 left[i] = decreasing_stk[-1]
181 decreasing_stk.pop()
182 decreasing_stk.append(i)
183 right, decreasing_stk = range(len(arr)), []
184 for i in reversed(xrange(len(arr))):
185 while decreasing_stk and arr[decreasing_stk[-1]] < arr[i]:
186 if decreasing_stk[-1] - i <= d:
187 right[i] = decreasing_stk[-1]
188 decreasing_stk.pop()
189 decreasing_stk.append(i)
190
191 segment_tree = SegmentTree(len(arr))
192 for _, i in sorted([x, i] for i, x in enumerate(arr)):
193 segment_tree.update(i, i, segment_tree.query(left[i], right[i]) + 1)
194 return segment_tree.query(0, len(arr)-1)
************

267. Jump Game IV


************

Given an array of integers arr, you are initially positioned at the first index of the array.

In one step you can jump from index i to index:

i + 1 where: i + 1 < arr.length .


i - 1 where: i - 1 >= 0 .
j where: arr[i] == arr[j] and i != j .

Return the minimum number of steps to reach the last index of the array.

Notice that you can not jump outside of the array at any time.

Example 1:

Input: arr = [100,-23,-23,404,100,23,23,23,3,404]


Output: 3
Explanation: You need three jumps from index 0 --> 4 --> 3 --> 9. Note that index 9 is the last index of the array.

Example 2:

Input: arr = [7]


Output: 0
Explanation: Start index is the last index. You don't need to jump.

Example 3:

Input: arr = [7,6,9,6,9,6,9,7]


Output: 1
Explanation: You can jump directly from index 0 to index 7 which is last index of the array.

Example 4:

Input: arr = [6,1,9]


Output: 2

Example 5:

Input: arr = [11,22,7,7,7,7,7,7,7,22,13]


Output: 3

Constraints:

1 <= arr.length <= 5 * 10 4


-108 <= arr[i] <= 10 8
************

267. Jump Game IV(C++)


************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int minJumps(vector& arr) {
7 unordered_map> groups;
8 for (int i = 0; i < arr.size(); ++i) {
9 groups[arr[i]].emplace_back(i);
10 }
11 int result = 0;
12 queue> q({{0, 0}});
13 unordered_set lookup = {0};
14 while (!q.empty()) {
15 const auto [pos, step] = q.front(); q.pop();
16 if (pos == arr.size() - 1) {
17 result = step;
18 break;
19 }
20 unordered_set neighbors(groups[arr[pos]].cbegin(),
21 groups[arr[pos]].cend());
22 groups[arr[pos]].clear();
23 neighbors.emplace(pos - 1), neighbors.emplace(pos + 1);
24 for (const auto& p : neighbors) {
25 if (0 <= p && p < arr.size() && !lookup.count(p)) {
26 lookup.emplace(p);
27 q.emplace(p, step + 1);
28 }
29 }
30 }
31 return result;
32 }
33 };
************

267. Jump Game IV(Python)


************

1 # Time: O(n)
2 # Space: O(n)
3
4 import collections
5
6
7 class Solution(object):
8 def minJumps(self, arr):
9 """
10 :type arr: List[int]
11 :rtype: int
12 """
13 groups = collections.defaultdict(list)
14 for i, x in enumerate(arr):
15 groups[x].append(i)
16 q = collections.deque([(0, 0)])
17 lookup = set([0])
18 while q:
19 pos, step = q.popleft()
20 if pos == len(arr)-1:
21 break
22 neighbors = set(groups[arr[pos]] + [pos-1, pos+1])
23 groups[arr[pos]] = []
24 for p in neighbors:
25 if p in lookup or not 0 <= p < len(arr):
26 continue
27 lookup.add(p)
28 q.append((p, step+1))
29 return step
****************************

268. Maximum Students Taking Exam


****************************

Given a m * n matrix seats that represent seats distributions in a classroom. If a seat is broken, it is denoted by '#' character
otherwise it is denoted by a '.' character.

Students can see the answers of those sitting next to the left, right, upper left and upper right, but he cannot see the
answers of the student sitting directly in front or behind him. Return the maximum number of students that can take the
exam together without any cheating being possible..

Students must be placed in seats in good condition.

Example 1:

Input: seats = [["#",".","#","#",".","#"],


[".","#","#","#","#","."],
["#",".","#","#",".","#"]]
Output: 4
Explanation: Teacher can place 4 students in available seats so they don't cheat on the exam.

Example 2:

Input: seats = [[".","#"],


["#","#"],
["#","."],
["#","#"],
[".","#"]]
Output: 3
Explanation: Place all students in available seats.

Example 3:

Input: seats = [["#",".",".",".","#"],


[".","#",".","#","."],
[".",".","#",".","."],
[".","#",".","#","."],
["#",".",".",".","#"]]
Output: 10
Explanation: Place students in available seats in column 1, 3 and 5.

Constraints:
seats contains only characters '.' and'#'.
m == seats.length
n == seats[i].length
1 <= m <= 8
1 <= n <= 8
****************************

268. Maximum Students Taking Exam(C++)


****************************

1 // Time: O(m * n * sqrt(m * n))


2 // Space: O(m * n)
3
4 // template from https://www.geeksforgeeks.org/hopcroft-karp-algorithm-for-maximum-matching-set-2-implementation/
5 static const int NIL = 0;
6 static const int INF = numeric_limits::max();
7
8 // A class to represent Bipartite graph for Hopcroft
9 // Karp implementation
10 // Time: O(E * sqrt(V))
11 // Space: O(V)
12 class BipGraph
13 {
14 // m and n are number of vertices on left
15 // and right sides of Bipartite Graph
16 int m, n;
17
18 // adj[u] stores adjacents of left side
19 // vertex 'u'. The value of u ranges from 1 to m.
20 // 0 is used for dummy vertex
21 list *adj;
22
23 // These are basically pointers to arrays needed
24 // for hopcroftKarp()
25 int *pairU, *pairV, *dist;
26
27 public:
28 BipGraph(int m, int n); // Constructor
29 void addEdge(int u, int v); // To add edge
30
31 // Returns true if there is an augmenting path
32 bool bfs();
33
34 // Adds augmenting path if there is one beginning
35 // with u
36 bool dfs(int u);
37
38 // Returns size of maximum matcing
39 int hopcroftKarp();
40 };
41
42 // Returns size of maximum matching
43 int BipGraph::hopcroftKarp()
44 {
45 // pairU[u] stores pair of u in matching where u
46 // is a vertex on left side of Bipartite Graph.
47 // If u doesn't have any pair, then pairU[u] is NIL
48 pairU = new int[m+1];
49
50 // pairV[v] stores pair of v in matching. If v
51 // doesn't have any pair, then pairU[v] is NIL
52 pairV = new int[n+1];
53
54 // dist[u] stores distance of left side vertices
55 // dist[u] is one more than dist[u'] if u is next
56 // to u'in augmenting path
57 dist = new int[m+1];
58
59 // Initialize NIL as pair of all vertices
60 for (int u=0; u<=m; u++)
61 pairU[u] = NIL;
62 for (int v=0; v<=n; v++)
63 pairV[v] = NIL;
64
65 // Initialize result
66 int result = 0;
67
68 // Keep updating the result while there is an
69 // augmenting path.
70 while (bfs())
71 {
72 // Find a free vertex
73 for (int u=1; u<=m; u++)
74
75 // If current vertex is free and there is
76 // an augmenting path from current vertex
77 if (pairU[u]==NIL && dfs(u))
78 result++;
79 }
80 return result;
81 }
82
83 // Returns true if there is an augmenting path, else returns
84 // false
85 bool BipGraph::bfs()
86 {
87 queue Q; //an integer queue
88
89 // First layer of vertices (set distance as 0)
90 for (int u=1; u<=m; u++)
91 {
92 // If this is a free vertex, add it to queue
93 if (pairU[u]==NIL)
94 {
95 // u is not matched
96 dist[u] = 0;
97 Q.push(u);
98 }
99
100 // Else set distance as infinite so that this vertex
101 // is considered next time
102 else dist[u] = INF;
103 }
104
105 // Initialize distance to NIL as infinite
106 dist[NIL] = INF;
107
108 // Q is going to contain vertices of left side only.
109 while (!Q.empty())
110 {
111 // Dequeue a vertex
112 int u = Q.front();
113 Q.pop();
114
115 // If this node is not NIL and can provide a shorter path to NIL
116 if (dist[u] < dist[NIL])
117 {
118 // Get all adjacent vertices of the dequeued vertex u
119 list::iterator i;
120 for (i=adj[u].begin(); i!=adj[u].end(); ++i)
121 {
122 int v = *i;
123
124 // If pair of v is not considered so far
125 // (v, pairV[V]) is not yet explored edge.
126 if (dist[pairV[v]] == INF)
127 {
128 // Consider the pair and add it to queue
129 dist[pairV[v]] = dist[u] + 1;
130 Q.push(pairV[v]);
131 }
132 }
133 }
134 }
135
135
136 // If we could come back to NIL using alternating path of distinct
137 // vertices then there is an augmenting path
138 return (dist[NIL] != INF);
139 }
140
141 // Returns true if there is an augmenting path beginning with free vertex u
142 bool BipGraph::dfs(int u)
143 {
144 if (u != NIL)
145 {
146 list::iterator i;
147 for (i=adj[u].begin(); i!=adj[u].end(); ++i)
148 {
149 // Adjacent to u
150 int v = *i;
151
152 // Follow the distances set by BFS
153 if (dist[pairV[v]] == dist[u]+1)
154 {
155 // If dfs for pair of v also returns
156 // true
157 if (dfs(pairV[v]) == true)
158 {
159 pairV[v] = u;
160 pairU[u] = v;
161 return true;
162 }
163 }
164 }
165
166 // If there is no augmenting path beginning with u.
167 dist[u] = INF;
168 return false;
169 }
170 return true;
171 }
172
173 // Constructor
174 BipGraph::BipGraph(int m, int n)
175 {
176 this->m = m;
177 this->n = n;
178 adj = new list[m+1];
179 }
180
181 // To add edge from u to v and v to u
182 void BipGraph::addEdge(int u, int v)
183 {
184 adj[u].push_back(v); // Add u to v’s list.
185 }
186
187 // Hopcroft-Karp bipartite matching
188 class Solution {
189 public:
190 int maxStudents(vector>& seats) {
191 static vector> directions = {{-1, -1}, {0, -1}, {1, -1},
192 {-1, 1}, {0, 1}, {1, 1}};
193 unordered_map lookup;
194 int u = 0, v = 0;
195 for (int i = 0; i < seats.size(); ++i) {
196 for (int j = 0; j < seats[0].size(); ++j) {
197 if (seats[i][j] != '.') {
198 continue;
199 }
200 lookup[i * seats[0].size() + j] = (j % 2 == 0) ? ++u : ++v;
201 }
202 }
203 BipGraph g(seats.size() * seats[0].size(), seats.size() * seats[0].size());
204 for (int i = 0; i < seats.size(); ++i) {
205 for (int j = 0; j < seats[0].size(); j += 2) {
206 if (seats[i][j] != '.') {
207 continue;
208 }
208 }
209 for (const auto& [dx, dy] : directions) {
210 const auto& [ni, nj] = make_pair(i + dx, j + dy);
211 if (0 <= ni && ni < seats.size() &&
212 0 <= nj && nj < seats[0].size() &&
213 seats[ni][nj] == '.') {
214 g.addEdge(lookup[i * seats[0].size() + j],
215 lookup[ni * seats[0].size() + nj]);
216 }
217 }
218 }
219 }
220 return u + v - g.hopcroftKarp();
221 }
222 };
223
224 // Time: O(|V| * |E|) = O(m^2 * n^2)
225 // Space: O(|V| + |E|) = O(m * n)
226 // Hungarian bipartite matching
227 class Solution2 {
228 public:
229 int maxStudents(vector>& seats) {
230 int count = 0;
231 for (int i = 0; i < seats.size(); ++i) {
232 for (int j = 0; j < seats[0].size(); ++j) {
233 if (seats[i][j] != '.') {
234 continue;
235 }
236 ++count;
237 }
238 }
239 return count - Hungarian(seats);
240 }
241
242 private:
243 int Hungarian(const vector>& seats) {
244 int result = 0;
245 vector>> matching(seats.size(),
246 vector>(seats[0].size(), {-1, -1}));
247 for (int i = 0; i < seats.size(); ++i) {
248 for (int j = 0; j < seats[0].size(); j += 2) {
249 if (seats[i][j] != '.') {
250 continue;
251 }
252 vector> lookup(seats.size(),
253 vector(seats[0].size(), false));
254 if (dfs(seats, {i, j}, &lookup, &matching)) {
255 ++result;
256 }
257 }
258 }
259 return result;
260 }
261
262 int dfs(const vector>& seats,
263 const pair& e,
264 vector> *lookup,
265 vector>> *matching) {
266 static vector> directions = {{-1, -1}, {0, -1}, {1, -1},
267 {-1, 1}, {0, 1}, {1, 1}};
268 const auto& [i, j] = e;
269 for (const auto& [dx, dy] : directions) {
270 const auto& [ni, nj] = make_pair(i + dx, j + dy);
271 if (0 <= ni && ni < seats.size() &&
272 0 <= nj && nj < seats[0].size() &&
273 seats[ni][nj] == '.' &&
274 !(*lookup)[ni][nj]) {
275 (*lookup)[ni][nj] = true;
276 if ((*matching)[ni][nj].first == -1 ||
277 dfs(seats, (*matching)[ni][nj], lookup, matching)) {
278 (*matching)[ni][nj] = e;
279 return true;
280 }
281 }
282 }
283 return false;
284 }
285 };
286
287 // Time: O(m * 2^n * 2^n) = O(m * 4^n)
288 // Space: O(2^n)
289 // dp solution
290 class Solution3 {
291 public:
292 int maxStudents(vector>& seats) {
293 const int state_size = 1 << seats[0].size();
294 unordered_map dp;
295 dp[0] = 0;
296 for (const auto& row : seats) {
297 int invalid_mask = 0;
298 for (int i = 0; i < row.size(); ++i) {
299 if (row[i] == '#') {
300 invalid_mask |= 1 << i;
301 }
302 }
303 unordered_map new_dp;
304 for (const auto& [mask1, v1] : dp) {
305 for (int mask2 = 0; mask2 < state_size; ++mask2) {
306 if ((mask2 & invalid_mask) ||
307 (mask2 & (mask1 << 1)) || (mask2 & (mask1 >> 1)) ||
308 (mask2 & (mask2 << 1)) || (mask2 & (mask2 >> 1))) {
309 continue;
310 }
311 new_dp[mask2] = max(new_dp.count(mask2) ? new_dp[mask2] : 0,
312 v1 + __builtin_popcount(mask2));
313 }
314 }
315 dp = move(new_dp);
316 }
317 return dp.empty() ? 0 : max_element(dp.cbegin(), dp.cend(),
318 [](const auto& a, const auto& b) {
319 return a.second < b.second;
320 })->second;
321 }
322 };
****************************

268. Maximum Students Taking Exam(Python)


****************************

1 # Time: O(m * n * sqrt(m * n))


2 # Space: O(m * n)
3
4 # the problem is the same as google codejam 2008 round 3 problem C
5 # https://github.com/kamyu104/GoogleCodeJam-2008/blob/master/Round%203/no_cheating.py
6
7 import collections
8
9
10 from functools import partial
11
12 # Time: O(E * sqrt(V))
13 # Space: O(V)
14 # Source code from http://code.activestate.com/recipes/123641-hopcroft-karp-bipartite-matching/
15 # Hopcroft-Karp bipartite max-cardinality matching and max independent set
16 # David Eppstein, UC Irvine, 27 Apr 2002
17 def bipartiteMatch(graph):
18 '''Find maximum cardinality matching of a bipartite graph (U,V,E).
19 The input format is a dictionary mapping members of U to a list
20 of their neighbors in V. The output is a triple (M,A,B) where M is a
21 dictionary mapping members of V to their matches in U, A is the part
22 of the maximum independent set in U, and B is the part of the MIS in V.
23 The same object may occur in both U and V, and is treated as two
24 distinct vertices if this happens.'''
25
26 # initialize greedy matching (redundant, but faster than full search)
27 matching = {}
28 for u in graph:
29 for v in graph[u]:
30 if v not in matching:
31 matching[v] = u
32 break
33
34 while 1:
35 # structure residual graph into layers
36 # pred[u] gives the neighbor in the previous layer for u in U
37 # preds[v] gives a list of neighbors in the previous layer for v in V
38 # unmatched gives a list of unmatched vertices in final layer of V,
39 # and is also used as a flag value for pred[u] when u is in the first layer
40 preds = {}
41 unmatched = []
42 pred = dict([(u,unmatched) for u in graph])
43 for v in matching:
44 del pred[matching[v]]
45 layer = list(pred)
46
47 # repeatedly extend layering structure by another pair of layers
48 while layer and not unmatched:
49 newLayer = {}
50 for u in layer:
51 for v in graph[u]:
52 if v not in preds:
53 newLayer.setdefault(v,[]).append(u)
54 layer = []
55 for v in newLayer:
56 preds[v] = newLayer[v]
57 if v in matching:
58 layer.append(matching[v])
59 pred[matching[v]] = v
60 else:
61 unmatched.append(v)
62
63 # did we finish layering without finding any alternating paths?
64 if not unmatched:
65 unlayered = {}
66 for u in graph:
67 for v in graph[u]:
68 if v not in preds:
69 unlayered[v] = None
70 return (matching,list(pred),list(unlayered))
71
72 # recursively search backward through layers to find alternating paths
73 # recursion returns true if found path, false otherwise
74 def recurse(v):
75 if v in preds:
76 L = preds[v]
77 del preds[v]
78 for u in L:
79 if u in pred:
80 pu = pred[u]
81 del pred[u]
82 if pu is unmatched or recurse(pu):
83 matching[v] = u
84 return 1
85 return 0
86
87 def recurse_iter(v):
88 def divide(v):
89 if v not in preds:
90 return
91 L = preds[v]
92 del preds[v]
93 for u in L :
94 if u in pred and pred[u] is unmatched: # early return
95 del pred[u]
96 matching[v] = u
97 ret[0] = True
98 return
99 stk.append(partial(conquer, v, iter(L)))
100
101 def conquer(v, it):
102 for u in it:
103 if u not in pred:
104 continue
105 pu = pred[u]
106 del pred[u]
107 stk.append(partial(postprocess, v, u, it))
108 stk.append(partial(divide, pu))
109 return
110
111 def postprocess(v, u, it):
112 if not ret[0]:
113 stk.append(partial(conquer, v, it))
114 return
115 matching[v] = u
116
117 ret, stk = [False], []
118 stk.append(partial(divide, v))
119 while stk:
120 stk.pop()()
121 return ret[0]
122
123 for v in unmatched: recurse_iter(v)
124
125
126 # Hopcroft-Karp bipartite matching
127 class Solution(object):
128 def maxStudents(self, seats):
129 """
130 :type seats: List[List[str]]
131 :rtype: int
132 """
133 directions = [(-1, -1), (0, -1), (1, -1), (-1, 1), (0, 1), (1, 1)]
134 E, count = collections.defaultdict(list), 0
135 for i in xrange(len(seats)):
135 for i in xrange(len(seats)):
136 for j in xrange(len(seats[0])):
137 if seats[i][j] != '.':
138 continue
139 count += 1
140 if j%2:
141 continue
142 for dx, dy in directions:
143 ni, nj = i+dx, j+dy
144 if 0 <= ni < len(seats) and \
145 0 <= nj < len(seats[0]) and \
146 seats[ni][nj] == '.':
147 E[i*len(seats[0])+j].append(ni*len(seats[0])+nj)
148 return count-len(bipartiteMatch(E)[0])
149
150
151 # Time: O(|V| * |E|) = O(m^2 * n^2)
152 # Space: O(|V| + |E|) = O(m * n)
153 # Hungarian bipartite matching
154 class Solution2(object):
155 def maxStudents(self, seats):
156 """
157 :type seats: List[List[str]]
158 :rtype: int
159 """
160 directions = [(-1, -1), (0, -1), (1, -1), (-1, 1), (0, 1), (1, 1)]
161 def dfs(seats, e, lookup, matching):
162 i, j = e
163 for dx, dy in directions:
164 ni, nj = i+dx, j+dy
165 if 0 <= ni < len(seats) and 0 <= nj < len(seats[0]) and \
166 seats[ni][nj] == '.' and not lookup[ni][nj]:
167 lookup[ni][nj] = True
168 if matching[ni][nj] == -1 or dfs(seats, matching[ni][nj], lookup, matching):
169 matching[ni][nj] = e
170 return True
171 return False
172
173 def Hungarian(seats):
174 result = 0
175 matching = [[-1]*len(seats[0]) for _ in xrange(len(seats))]
176 for i in xrange(len(seats)):
177 for j in xrange(0, len(seats[0]), 2):
178 if seats[i][j] != '.':
179 continue
180 lookup = [[False]*len(seats[0]) for _ in xrange(len(seats))]
181 if dfs(seats, (i, j), lookup, matching):
182 result += 1
183 return result
184
185 count = 0
186 for i in xrange(len(seats)):
187 for j in xrange(len(seats[0])):
188 if seats[i][j] == '.':
189 count += 1
190 return count-Hungarian(seats)
191
192
193 # Time: O(m * 2^n * 2^n) = O(m * 4^n)
194 # Space: O(2^n)
195 # dp solution
196 class Solution3(object):
197 def maxStudents(self, seats):
198 """
199 :type seats: List[List[str]]
200 :rtype: int
201 """
202 def popcount(n):
203 result = 0
204 while n:
205 n &= n - 1
206 result += 1
207 return result
208
208
209 dp = {0: 0}
210 for row in seats:
211 invalid_mask = sum(1 << c for c, v in enumerate(row) if v == '#')
212 new_dp = {}
213 for mask1, v1 in dp.iteritems():
214 for mask2 in xrange(1 << len(seats[0])):
215 if (mask2 & invalid_mask) or \
216 (mask2 & (mask1 << 1)) or (mask2 & (mask1 >> 1)) or \
217 (mask2 & (mask2 << 1)) or (mask2 & (mask2 >> 1)):
218 continue
219 new_dp[mask2] = max(new_dp.get(mask2, 0), v1+popcount(mask2))
220 dp = new_dp
221 return max(dp.itervalues()) if dp else 0
*****************************************

269. Construct Target Array With Multiple Sums


*****************************************

You are given an array target of n integers. From a starting arrayarr consisting of n 1's, you may perform the following
procedure :

let x be the sum of all elements currently in your array.


choose index i, such that 0 <= i < n and set the value of arr at index i to x .
You may repeat this procedure as many times as needed.

Return true if it is possible to construct the target array from arr, otherwise, return false.

Example 1:

Input: target = [9,3,5]


Output: true
Explanation: Start with arr = [1, 1, 1]
[1, 1, 1], sum = 3 choose index 1
[1, 3, 1], sum = 5 choose index 2
[1, 3, 5], sum = 9 choose index 0
[9, 3, 5] Done

Example 2:

Input: target = [1,1,1,2]


Output: false
Explanation: Impossible to create target array from [1,1,1,1].

Example 3:

Input: target = [8,5]


Output: true

Constraints:

n == target.length
1 <= n <= 5 * 10 4
1 <= target[i] <= 109
*****************************************

269. Construct Target Array With Multiple Sums(C++)


*****************************************

1 // Time: O(log(max(t)) * logn)


2 // Space: O(n)
3
4 class Solution {
5 public:
6 bool isPossible(vector& target) {
7 // (1) x + remain = y
8 // (2) y + remain = total
9 // (1) - (2) => x - y = y - total
10 // => x = 2*y - total
11 auto total = accumulate(cbegin(target), cend(target), 0ll);
12 priority_queue max_heap(cbegin(target), cend(target));
13 while (total != target.size()) {
14 const auto y = max_heap.top(); max_heap.pop();
15 const auto& remain = total - y;
16 auto x = y - remain;
17 if (x <= 0) {
18 return false;
19 }
20 if (x > remain) { // for case [1, 1000000000]
21 x = x % remain + remain;
22 }
23 max_heap.emplace(x);
24 total = x + remain;
25 }
26 return true;
27 }
28 };
*****************************************

269. Construct Target Array With Multiple Sums(Python)


*****************************************

1 # Time: O(log(max(t)) * logn)


2 # Space: O(n)
3
4 import heapq
5
6
7 class Solution(object):
8 def isPossible(self, target):
9 """
10 :type target: List[int]
11 :rtype: bool
12 """
13 # (1) x + remain = y
14 # (2) y + remain = total
15 # (1) - (2) => x - y = y - total
16 # => x = 2*y - total
17 total = sum(target)
18 max_heap = [-x for x in target]
19 heapq.heapify(max_heap)
20 while total != len(target):
21 y = -heapq.heappop(max_heap)
22 remain = total-y
23 x = y-remain
24 if x <= 0:
25 return False
26 if x > remain: # for case [1, 1000000000]
27 x = x%remain + remain
28 heapq.heappush(max_heap, -x)
29 total = x+remain
30 return True
*******************************************

270. Count All Valid Pickup and Delivery Options


*******************************************

Given n orders, each order consist in pickup and delivery services.

Count all valid pickup/delivery possible sequences such that delivery(i) is always after of pickup(i).

Since the answer may be too large, return it modulo 10^9 + 7.

Example 1:

Input: n = 1
Output: 1
Explanation: Unique order (P1, D1), Delivery 1 always is after of Pickup 1.

Example 2:

Input: n = 2
Output: 6
Explanation: All possible orders:
(P1,P2,D1,D2), (P1,P2,D2,D1), (P1,D1,P2,D2), (P2,P1,D1,D2), (P2,P1,D2,D1) and (P2,D2,P1,D1).
This is an invalid order (P1,D2,P2,D1) because Pickup 2 is after of Delivery 2.

Example 3:

Input: n = 3
Output: 90

Constraints:

1 <= n <= 500


*******************************************

270. Count All Valid Pickup and Delivery Options(C++)


*******************************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int countOrders(int n) {
7 static const int MOD = 1e9 + 7;
8 int64_t result = 1ll;
9 for (int i = 2 * n; i > 0; i -= 2) {
10 result = result * i * (i - 1) / 2 % MOD;
11 }
12 return result;
13 }
14 };
*******************************************

270. Count All Valid Pickup and Delivery Options(Python)


*******************************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def countOrders(self, n):
6 """
7 :type n: int
8 :rtype: int
9 """
10 MOD = 10**9+7
11 result = 1
12 for i in reversed(xrange(2, 2*n+1, 2)):
13 result = result * i*(i-1)//2 % MOD
14 return result
*************************

271. Largest Multiple of Three


*************************

Given an integer array of digits, return the largest multiple of three that can be formed by concatenating some of the given
digits in any order.

Since the answer may not fit in an integer data type, return the answer as a string.

If there is no answer return an empty string.

Example 1:

Input: digits = [8,1,9]


Output: "981"

Example 2:

Input: digits = [8,6,7,1,0]


Output: "8760"

Example 3:

Input: digits = [1]


Output: ""

Example 4:

Input: digits = [0,0,0,0,0,0]


Output: "0"

Constraints:

1 <= digits.length <= 10^4


0 <= digits[i] <= 9
The returning answer must not contain unnecessary leading zeros.
*************************

271. Largest Multiple of Three(C++)


*************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 string largestMultipleOfThree(vector& digits) {
7 static const unordered_map>> lookup = {
8 {0, {}},
9 {1, {{1}, {4}, {7}, {2, 2}, {5, 2}, {5, 5}, {8, 2}, {8, 5}, {8, 8}}},
10 {2, {{2}, {5}, {8}, {1, 1}, {4, 1}, {4, 4}, {7, 1}, {7, 4}, {7, 7}}}
11 };
12 unordered_map count = counter(digits);
13 const auto& r = accumulate(cbegin(digits), cend(digits), 0) % 3;
14 for (const auto& deletes : lookup.at(r)) {
15 if (remove(deletes, &count)) {
16 break;
17 }
18 }
19 string result;
20 for (int d = 9; d >= 0; --d) {
21 result += string(count[d], '0' + d);
22 }
23 return !result.empty() && result[0] == '0' ? "0" : result;
24 }
25
26 private:
27 bool remove(const vector& deletes, unordered_map *count) {
28 const auto& delete_count = counter(deletes);
29 if (all_of(cbegin(delete_count), cend(delete_count),
30 [&count](const auto& kvp) {
31 return (*count)[kvp.first] >= kvp.second;
32 })) {
33 for (const auto& [k, v] : delete_count) {
34 (*count)[k] -= v;
35 }
36 return true;
37 }
38 return false;
39 }
40
41 unordered_map counter(const vector & digits) {
42 unordered_map result;
43 for (const auto& i : digits) {
44 ++result[i];
45 }
46 return result;
47 }
48 };
49
50 // Time: O(n)
51 // Space: O(1)
52 class Solution2 {
53 public:
54 string largestMultipleOfThree(vector& digits) {
55 unordered_map count = counter(digits);
56 const auto& r = accumulate(cbegin(digits), cend(digits), 0) % 3;
57 if (r) {
58 bool is_found = false;
59 for (int i = 0; i < 10; ++i) {
60 vector deletes = {i};
61 if (remove(deletes, r, &count)) {
62 is_found = true;
63 break;
64 }
65 }
66 if (!is_found) {
67 for (int i = 0; i < 10; ++i) {
68 for (int j = 0; j <= i; ++j) {
69 vector deletes = {i, j};
70 if (remove(deletes, r, &count)) {
71 break;
72 }
73 }
74 }
75 }
76 }
77 string result;
78 for (int d = 9; d >= 0; --d) {
79 result += string(count[d], '0' + d);
80 }
81 return !result.empty() && result[0] == '0' ? "0" : result;
82 }
83
84 private:
85 bool remove(const vector& deletes, int r, unordered_map *count) {
86 const auto& delete_count = counter(deletes);
87 if (accumulate(cbegin(deletes), cend(deletes), 0) % 3 == r &&
88 all_of(cbegin(delete_count), cend(delete_count),
89 [&count](const auto& kvp) {
90 return (*count)[kvp.first] >= kvp.second;
91 })) {
92 for (const auto& [k, v] : delete_count) {
93 (*count)[k] -= v;
94 }
95 return true;
96 }
97 return false;
98 }
99
100 unordered_map counter(const vector & digits) {
101 unordered_map result;
102 for (const auto& i : digits) {
103 ++result[i];
104 }
105 return result;
106 }
107 };
*************************

271. Largest Multiple of Three(Python)


*************************

1 # Time: O(n)
2 # Space: O(1)
3
4 import collections
5
6
7 class Solution(object):
8 def largestMultipleOfThree(self, digits):
9 """
10 :type digits: List[int]
11 :rtype: str
12 """
13 lookup = {0: [],
14 1: [(1,), (4,), (7,), (2, 2), (5, 2), (5, 5), (8, 2), (8, 5), (8, 8)],
15 2: [(2,), (5,), (8,), (1, 1), (4, 1), (4, 4), (7, 1), (7, 4), (7, 7)]}
16 count = collections.Counter(digits)
17 for deletes in lookup[sum(digits)%3]:
18 delete_count = collections.Counter(deletes)
19 if all(count[k] >= v for k, v in delete_count.iteritems()):
20 for k, v in delete_count.iteritems():
21 count[k] -= v
22 break
23 result = "".join(str(d)*count[d] for d in reversed(xrange(10)))
24 return "0" if result and result[0] == '0' else result
25
26
27 # Time: O(n)
28 # Space: O(1)
29 class Solution2(object):
30 def largestMultipleOfThree(self, digits):
31 """
32 :type digits: List[int]
33 :rtype: str
34 """
35 def candidates_gen(r):
36 if r == 0:
37 return
38 for i in xrange(10):
39 yield [i]
40 for i in xrange(10):
41 for j in xrange(i+1):
42 yield [i, j]
43
44 count, r = collections.Counter(digits), sum(digits)%3
45 for deletes in candidates_gen(r):
46 delete_count = collections.Counter(deletes)
47 if sum(deletes)%3 == r and \
48 all(count[k] >= v for k, v in delete_count.iteritems()):
49 for k, v in delete_count.iteritems():
50 count[k] -= v
51 break
52 result = "".join(str(d)*count[d] for d in reversed(xrange(10)))
53 return "0" if result and result[0] == '0' else result
******************************************************

272. Minimum Cost to Make at Least One Valid Path in a


Grid
******************************************************

Given a m x n grid. Each cell of the grid has a sign pointing to the next cell you should visit if you are currently in this cell. The
sign of grid[i][j] can be:

1 which means go to the cell to the right. (i.e go fromgrid[i][j] to grid[i][j + 1] )


2 which means go to the cell to the left. (i.e go fromgrid[i][j] to grid[i][j - 1])
3 which means go to the lower cell. (i.e go fromgrid[i][j] to grid[i + 1][j] )
4 which means go to the upper cell. (i.e go fromgrid[i][j] to grid[i - 1][j])

Notice that there could be some invalid signs on the cells of the grid which points outside the grid.

You will initially start at the upper left cell(0,0). A valid path in the grid is a path which starts from the upper left cell(0,0) and
ends at the bottom-right cell (m - 1, n - 1) following the signs on the grid. The valid pathdoesn't have to be the shortest.

You can modify the sign on a cell withcost = 1 . You can modify the sign on a cellone time only.

Return the minimum cost to make the grid have at least one valid path.

Example 1:

Input: grid = [[1,1,1,1],[2,2,2,2],[1,1,1,1],[2,2,2,2]]


Output: 3
Explanation: You will start at point (0, 0).
The path to (3, 3) is as follows. (0, 0) --> (0, 1) --> (0, 2) --> (0, 3) change the arrow to down with cost = 1 --> (1, 3) --> (1, 2) --> (1
The total cost = 3.
Example 2:

Input: grid = [[1,1,3],[3,2,2],[1,1,4]]


Output: 0
Explanation: You can follow the path from (0, 0) to (2, 2).

Example 3:

Input: grid = [[1,2],[4,3]]


Output: 1

Example 4:

Input: grid = [[2,2,2],[2,2,2]]


Output: 3

Example 5:

Input: grid = [[4]]


Output: 0
Constraints:

m == grid.length
n == grid[i].length
1 <= m, n <= 100
******************************************************

272. Minimum Cost to Make at Least One Valid Path in a


Grid(C++)
******************************************************

1 // Time: O(m * n)
2 // Space: O(m * n)
3
4 // A* Search Algorithm without heap
5 class Solution {
6 public:
7 int minCost(vector>& grid) {
8 const pair b = {0, 0}, t = {grid.size() - 1, grid[0].size() - 1};
9 return a_star(grid, b, t);
10 }
11
12 private:
13 int a_star(const vector>& grid,
14 const pair& b,
15 const pair& t) {
16
17 static const vector> directions = {{1, 0, 1}, {2, 0, -1},
18 {3, 1, 0}, {4, -1, 0}};
19 int f = 0, dh = 1;
20 vector> closer = {b}, detour;
21 unordered_set lookup;
22 while (!closer.empty() || !detour.empty()) {
23 if (closer.empty()) {
24 f += dh;
25 swap(closer, detour);
26 }
27 const auto b = closer.back(); closer.pop_back();
28 if (b == t) {
29 return f;
30 }
31 if (lookup.count(b.first * grid[0].size() + b.second)) {
32 continue;
33 }
34 lookup.emplace(b.first * grid[0].size() + b.second);
35 for (const auto& [nd, dr, dc] : directions) {
36 const pair& nb = {b.first + dr, b.second + dc};
37 if (!(0 <= nb.first && nb.first < grid.size() &&
38 0 <= nb.second && nb.second < grid[0].size() &&
39 !lookup.count(nb.first * grid[0].size() + nb.second))) {
40 continue;
41 }
42 if (nd == grid[b.first][b.second]) {
43 closer.emplace_back(nb);
44 } else {
45 detour.emplace_back(nb);
46 }
47 }
48 }
49 return -1;
50 }
51 };
52
53 // Time: O(m * n)
54 // Space: O(m * n)
55 // 0-1 bfs solution
56 class Solution2 {
57 public:
58 int minCost(vector>& grid) {
59 static const vector> directions = {{1, 0, 1}, {2, 0, -1},
60 {3, 1, 0}, {4, -1, 0}};
60
61 const pair b = {0, 0}, t = {grid.size() - 1, grid[0].size() - 1};
62 deque, int>> dq = {{b, 0}};
63 unordered_map lookup = {{b.first * grid[0].size() + b.second, 0}};
64 while (!dq.empty()) {
65 const auto [b, d] = dq.front(); dq.pop_front();
66 if (b == t) {
67 return d;
68 }
69 if (lookup[b.first * grid[0].size() + b.second] < d) {
70 continue;
71 }
72 for (const auto& [nd, dr, dc] : directions) {
73 const auto& nb = make_pair(b.first + dr, b.second + dc);
74 const auto& cost = nd != grid[b.first][b.second] ? 1 : 0;
75 if (!(0 <= nb.first && nb.first < grid.size() &&
76 0 <= nb.second && nb.second < grid[0].size() &&
77 (!lookup.count(nb.first * grid[0].size() + nb.second) ||
78 lookup[nb.first * grid[0].size() + nb.second] > d + cost))) {
79 continue;
80 }
81 lookup[nb.first * grid[0].size() + nb.second] = d + cost;
82 if (!cost) {
83 dq.emplace_front(nb, d);
84 } else {
85 dq.emplace_back(nb, d + cost);
86 }
87 }
88 }
89 return -1; // never reach here
90 }
91 };
******************************************************

272. Minimum Cost to Make at Least One Valid Path in a


Grid(Python)
******************************************************
1 # Time: O(m * n)
2 # Space: O(m * n)
3
4 import collections
5
6
7 # A* Search Algorithm without heap
8 class Solution(object):
9 def minCost(self, grid):
10 """
11 :type grid: List[List[int]]
12 :rtype: int
13 """
14 directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
15 def a_star(grid, b, t):
16 R, C = len(grid), len(grid[0])
17 f, dh = 0, 1
18 closer, detour = [b], []
19 lookup = set()
20 while closer or detour:
21 if not closer:
22 f += dh
23 closer, detour = detour, closer
24 b = closer.pop()
25 if b == t:
26 return f
27 if b in lookup:
28 continue
29 lookup.add(b)
30 for nd, (dr, dc) in enumerate(directions, 1):
31 nb = (b[0]+dr, b[1]+dc)
32 if not (0 <= nb[0] < R and 0 <= nb[1] < C and nb not in lookup):
33 continue
34 (closer if nd == grid[b[0]][b[1]] else detour).append(nb)
35 return -1
36
37 return a_star(grid, (0, 0), (len(grid)-1, len(grid[0])-1))
38
39
40 # Time: O(m * n)
41 # Space: O(m * n)
42 # 0-1 bfs solution
43 class Solution2(object):
44 def minCost(self, grid):
45 """
46 :type grid: List[List[int]]
47 :rtype: int
48 """
49 directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
50 R, C = len(grid), len(grid[0])
51 b, t = (0, 0), (R-1, C-1)
52 dq = collections.deque([(b, 0)])
53 lookup = {b: 0}
54 while dq:
55 b, d = dq.popleft()
56 if b == t:
57 return d
58 if lookup[b] < d:
59 continue
60 for nd, (dr, dc) in enumerate(directions, 1):
61 nb = (b[0]+dr, b[1]+dc)
62 cost = 1 if nd != grid[b[0]][b[1]] else 0
63 if not (0 <= nb[0] < R and 0 <= nb[1] < C and
64 (nb not in lookup or lookup[nb] > d+cost)):
65 continue
66 lookup[nb] = d+cost
67 if not cost:
68 dq.appendleft((nb, d))
69 else:
70 dq.append((nb, d+cost))
71 return -1 # never reach here
***********************************

273. Get the Second Most Recent Activity


***********************************

Table: UserActivity

+---------------+---------+
| Column Name | Type |
+---------------+---------+
| username | varchar |
| activity | varchar |
| startDate | Date |
| endDate | Date |
+---------------+---------+
This table does not contain primary key.
This table contain information about the activity performed of each user in a period of time.
A person with username performed a activity from startDate to endDate.

Write an SQL query to show the second most recent activity of each user.

If the user only has one activity, return that one.

A user can't perform more than one activity at the same time. Return the result table inany order.

The query result format is in the following example:

UserActivity table:
+------------+--------------+-------------+-------------+
| username | activity | startDate | endDate |
+------------+--------------+-------------+-------------+
| Alice | Travel | 2020-02-12 | 2020-02-20 |
| Alice | Dancing | 2020-02-21 | 2020-02-23 |
| Alice | Travel | 2020-02-24 | 2020-02-28 |
| Bob | Travel | 2020-02-11 | 2020-02-18 |
+------------+--------------+-------------+-------------+

Result table:
+------------+--------------+-------------+-------------+
| username | activity | startDate | endDate |
+------------+--------------+-------------+-------------+
| Alice | Dancing | 2020-02-21 | 2020-02-23 |
| Bob | Travel | 2020-02-11 | 2020-02-18 |
+------------+--------------+-------------+-------------+

The most recent activity of Alice is Travel from 2020-02-24 to 2020-02-28, before that she was dancing from 2020-02-21 to 2020-02-23.
Bob only has one record, we just take that one.
***********************************

273. Get the Second Most Recent Activity(Shell)


***********************************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 SELECT *
5 FROM UserActivity
6 GROUP BY username
7 HAVING COUNT(1) = 1
8
9 UNION ALL
10
11 SELECT a.username,
12 a.activity,
13 a.startDate,
14 a.endDate
15 FROM
16 (SELECT @accu := (CASE
17 WHEN username = @prev THEN @accu + 1
18 ELSE 1
19 END) AS n,
20 @prev := username AS username,
21 activity,
22 startDate,
23 endDate
24 FROM
25 (SELECT @accu := 0, @prev := 0) AS init,
26 UserActivity AS u
27 ORDER BY username,
28 endDate DESC) AS a
29 WHERE n = 2;
******************************

274. Maximum Sum BST in Binary Tree


******************************

Given a binary tree root, return the maximum sum of all keys ofany sub-tree which is also a Binary Search Tree (BST).

Assume a BST is defined as follows:

The left subtree of a node contains only nodes with keysless than the node's key.
The right subtree of a node contains only nodes with keysgreater than the node's key.
Both the left and right subtrees must also be binary search trees.

Example 1:

Input: root = [1,4,3,2,4,2,5,null,null,null,null,null,null,4,6]


Output: 20
Explanation: Maximum sum in a valid Binary search tree is obtained in root node with key equal to 3.

Example 2:

Input: root = [4,3,null,1,2]


Output: 2
Explanation: Maximum sum in a valid Binary search tree is obtained in a single root node with key equal to 2.

Example 3:

Input: root = [-4,-2,-5]


Output: 0
Explanation: All values are negatives. Return an empty BST.

Example 4:
Input: root = [2,1,3]
Output: 6

Example 5:

Input: root = [5,4,8,3,null,6,3]


Output: 7

Constraints:

The number of nodes in the tree is in the range[1, 4 * 104].


-4 * 104 <= Node.val <= 4 * 10 4
******************************

274. Maximum Sum BST in Binary Tree(C++)


******************************

1 // Time: O(n)
2 // Space: O(h)
3
4 /**
5 * Definition for a binary tree node.
6 * struct TreeNode {
7 * int val;
8 * TreeNode *left;
9 * TreeNode *right;
10 * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
11 * };
12 */
13
14 // dfs solution with stack
15 class Solution {
16 public:
17 int maxSumBST(TreeNode* root) {
18 using RET = tuple;
19 int result = 0;
20 RET ret;
21 vector>, RET *>> stk = {{root, nullptr, &ret}};
22 while (!stk.empty()) {
23 const auto [node, tmp, ret] = stk.back(); stk.pop_back();
24 if (tmp) {
25 const auto& [lvalid, lsum, lmin, lmax] = (*tmp)[0];
26 const auto& [rvalid, rsum, rmin, rmax] = (*tmp)[1];
27 if (lvalid && rvalid && lmax < node->val && node->val < rmin) {
28 const auto& total = lsum + node->val + rsum;
29 result = max(result, total);
30 *ret = {true, total, min(lmin, node->val), max(node->val, rmax)};
31 continue;
32 }
33 *ret = {false, 0, 0, 0};
34 continue;
35 }
36 if (!node) {
37 *ret = {true, 0,
38 numeric_limits::max(),
39 numeric_limits::min()};
40 continue;
41 }
42 const auto& new_tmp = make_shared>(2);
43 stk.emplace_back(node, new_tmp, ret);
44 stk.emplace_back(node->right, nullptr, &((*new_tmp)[1]));
45 stk.emplace_back(node->left, nullptr, &((*new_tmp)[0]));
46 }
47 return result;
48 }
49 };
50
51 // Time: O(n)
52 // Space: O(h)
53 // dfs solution with recursion
54 class Solution2 {
55 public:
56 int maxSumBST(TreeNode* root) {
57 int result = 0;
58 dfs(root, &result);
59 return result;
60 }
61
62 private:
63 tuple dfs(TreeNode *node, int *result) {
64 if (!node) {
65 return {true, 0,
66 numeric_limits::max(),
67 numeric_limits::min()};
68 }
69 const auto& [lvalid, lsum, lmin, lmax] = dfs(node->left, result);
70 const auto& [rvalid, rsum, rmin, rmax] = dfs(node->right, result);
71 if (lvalid && rvalid && lmax < node->val && node->val < rmin) {
72 const auto& total = lsum + node->val + rsum;
73 *result = max(*result, total);
74 return {true, total, min(lmin, node->val), max(node->val, rmax)};
75 }
76 return {false, 0, 0, 0};
77 }
78 };
******************************

274. Maximum Sum BST in Binary Tree(Python)


******************************
1 # Time: O(n)
2 # Space: O(h)
3
4 # Definition for a binary tree node.
5 class TreeNode(object):
6 def __init__(self, x):
7 self.val = x
8 self.left = None
9 self.right = None
10
11
12 # dfs solution with stack
13 class Solution(object):
14 def maxSumBST(self, root):
15 """
16 :type root: TreeNode
17 :rtype: int
18 """
19 result = 0
20 stk = [[root, None, []]]
21 while stk:
22 node, tmp, ret = stk.pop()
23 if tmp:
24 lvalid, lsum, lmin, lmax = tmp[0]
25 rvalid, rsum, rmin, rmax = tmp[1]
26 if lvalid and rvalid and lmax < node.val < rmin:
27 total = lsum + node.val + rsum
28 result = max(result, total)
29 ret[:] = [True, total, min(lmin, node.val), max(node.val, rmax)]
30 continue
31 ret[:] = [False, 0, 0, 0]
32 continue
33 if not node:
34 ret[:] = [True, 0, float("inf"), float("-inf")]
35 continue
36 new_tmp = [[], []]
37 stk.append([node, new_tmp, ret])
38 stk.append([node.right, None, new_tmp[1]])
39 stk.append([node.left, None, new_tmp[0]])
40 return result
41
42
43 # Time: O(n)
44 # Space: O(h)
45 # dfs solution with recursion
46 class Solution2(object):
47 def maxSumBST(self, root):
48 """
49 :type root: TreeNode
50 :rtype: int
51 """
52 def dfs(node, result):
53 if not node:
54 return True, 0, float("inf"), float("-inf")
55 lvalid, lsum, lmin, lmax = dfs(node.left, result)
56 rvalid, rsum, rmin, rmax = dfs(node.right, result)
57 if lvalid and rvalid and lmax < node.val < rmin:
58 total = lsum + node.val + rsum
59 result[0] = max(result[0], total)
60 return True, total, min(lmin, node.val), max(node.val, rmax)
61 return False, 0, 0, 0
62
63 result = [0]
64 dfs(root, result)
65 return result[0]
*****************************

275. Frog Position After T Seconds


*****************************

Given an undirected tree consisting of n vertices numbered from 1 to n. A frog starts jumping from vertex 1. In one second,
the frog jumps from its current vertex to another unvisited vertex if they are directly connected. The frog can not jump back
to a visited vertex. In case the frog can jump to several vertices, it jumps randomly to one of them with the same probability.
Otherwise, when the frog can not jump to any unvisited vertex, it jumps forever on the same vertex.

The edges of the undirected tree are given in the arrayedges, where edges[i] = [a i, b i] means that exists an edge connecting the
vertices ai and bi.

Return the probability that after t seconds the frog is on the vertex target.

Example 1:

Input: n = 7, edges = [[1,2],[1,3],[1,7],[2,4],[2,6],[3,5]], t = 2, target = 4


Output: 0.16666666666666666
Explanation: The figure above shows the given graph. The frog starts at vertex 1, jumping with 1/3 probability to the vertex 2 after second 1

Example 2:

Input: n = 7, edges = [[1,2],[1,3],[1,7],[2,4],[2,6],[3,5]], t = 1, target = 7


Output: 0.3333333333333333
Explanation: The figure above shows the given graph. The frog starts at vertex 1, jumping with 1/3 = 0.3333333333333333 probability to the ve

Example 3:
Input: n = 7, edges = [[1,2],[1,3],[1,7],[2,4],[2,6],[3,5]], t = 20, target = 6
Output: 0.16666666666666666

Constraints:

1 <= n <= 100


edges.length == n - 1
edges[i].length == 2
1 <= ai, b i <= n
1 <= t <= 50
1 <= target <= n
Answers within 10-5 of the actual value will be accepted as correct.
*****************************

275. Frog Position After T Seconds(C++)


*****************************

1 // Time: O(n)
2 // Space: O(n)
3
4 // bfs solution with better precision
5 class Solution {
6 public:
7 double frogPosition(int n, vector>& edges, int t, int target) {
8 unordered_map> G;
9 G[1] = {};
10 for (const auto& edge : edges) {
11 G[edge[0]].emplace_back(edge[1]);
12 G[edge[1]].emplace_back(edge[0]);
13 }
14
15 vector> stk = {{t, 1, 0, 1}};
16 while (!stk.empty()) {
17 vector> new_stk;
18 while (!stk.empty()) {
19 const auto [t, node, parent, choices] = stk.back(); stk.pop_back();
20 if (!t || !(G.at(node).size() - int(parent != 0))) {
21 if (node == target) {
22 return 1.0 / choices;
23 }
24 continue;
25 }
26 for (const auto& child : G.at(node)) {
27 if (child == parent) {
28 continue;
29 }
30 new_stk.emplace_back(t - 1, child, node,
31 choices * (G.at(node).size() - int(parent != 0)));
32 }
33 }
34 stk = move(new_stk);
35 }
36 return 0.0;
37 }
38 };
39
40 // Time: O(n)
41 // Space: O(n)
42 // dfs solution with stack with better precision
43 class Solution2 {
44 public:
45 double frogPosition(int n, vector>& edges, int t, int target) {
46 unordered_map> G;
47 G[1] = {};
48 for (const auto& edge : edges) {
49 G[edge[0]].emplace_back(edge[1]);
50 G[edge[1]].emplace_back(edge[0]);
51 }
52
53 vector> stk = {{t, 1, 0, 1}};
54 while (!stk.empty()) {
55 const auto [t, node, parent, choices] = stk.back(); stk.pop_back();
56 if (!t || !(G.at(node).size() - int(parent != 0))) {
57 if (node == target) {
58 return 1.0 / choices;
59 }
60 continue;
61 }
62 for (const auto& child : G.at(node)) {
63 if (child == parent) {
64 continue;
65 }
66 stk.emplace_back(t - 1, child, node,
67 choices * (G.at(node).size() - int(parent != 0)));
68 }
69 }
70 return 0.0;
71 }
72 };
73
74 // Time: O(n)
75 // Space: O(n)
76 // dfs solution with recursion with better precision
77 class Solution3 {
78 public:
79 double frogPosition(int n, vector>& edges, int t, int target) {
80 unordered_map> G;
81 G[1] = {};
82 for (const auto& edge : edges) {
83 G[edge[0]].emplace_back(edge[1]);
84 G[edge[1]].emplace_back(edge[0]);
85 }
86 int choices = dfs(G, target, t, 1, 0);
87 return choices ? 1.0 / choices : 0.0;
88 }
89
90 private:
91 int dfs(const unordered_map>& G,
92 int target, int t, int node, int parent) {
93 if (!t || !(G.at(node).size() - int(parent != 0))) {
94 return (node == target);
95 }
96 int result = 0;
97 for (const auto& child : G.at(node)) {
98 if (child == parent) {
99 continue;
100 }
101 if (result = dfs(G, target, t - 1, child, node)) {
102 break;
103 }
104 }
105 return result * (G.at(node).size() - int(parent != 0));
106 }
107 };
108
109 // Time: O(n)
110 // Space: O(n)
111 // dfs solution with recursion
112 class Solution4 {
113 public:
114 double frogPosition(int n, vector>& edges, int t, int target) {
115 unordered_map> G;
116 G[1] = {};
117 for (const auto& edge : edges) {
118 G[edge[0]].emplace_back(edge[1]);
119 G[edge[1]].emplace_back(edge[0]);
120 }
121 return dfs(G, target, t, 1, 0);
122 }
123
124 private:
125 double dfs(const unordered_map>& G,
126 int target, int t, int node, int parent) {
127 if (!t || !(G.at(node).size() - int(parent != 0))) {
128 return (node == target);
129 }
130 double result = 0.0;
131 for (const auto& child : G.at(node)) {
132 if (child == parent) {
133 continue;
134 }
135 if (result = dfs(G, target, t - 1, child, node)) {
135 if (result = dfs(G, target, t - 1, child, node)) {
136 break;
137 }
138 }
139 return result / (G.at(node).size() - int(parent != 0));
140 }
141 };
*****************************

275. Frog Position After T Seconds(Python)


*****************************

1 # Time: O(n)
2 # Space: O(n)
3
4 import collections
5
6
7 # bfs solution with better precision
8 class Solution(object):
9 def frogPosition(self, n, edges, t, target):
10 """
11 :type n: int
12 :type edges: List[List[int]]
13 :type t: int
14 :type target: int
15 :rtype: float
16 """
17 G = collections.defaultdict(list)
18 for u, v in edges:
19 G[u].append(v)
20 G[v].append(u)
21
22 stk = [(t, 1, 0, 1)]
23 while stk:
24 new_stk = []
25 while stk:
26 t, node, parent, choices = stk.pop()
27 if not t or not (len(G[node])-(parent != 0)):
28 if node == target:
29 return 1.0/choices
30 continue
31 for child in G[node]:
32 if child == parent:
33 continue
34 new_stk.append((t-1, child, node,
35 choices*(len(G[node])-(parent != 0))))
36 stk = new_stk
37 return 0.0
38
39
40 # Time: O(n)
41 # Space: O(n)
42 # dfs solution with stack with better precision
43 class Solution2(object):
44 def frogPosition(self, n, edges, t, target):
45 """
46 :type n: int
47 :type edges: List[List[int]]
48 :type t: int
49 :type target: int
50 :rtype: float
51 """
52 G = collections.defaultdict(list)
53 for u, v in edges:
54 G[u].append(v)
55 G[v].append(u)
56
57 stk = [(t, 1, 0, 1)]
58 while stk:
59 t, node, parent, choices = stk.pop()
60 if not t or not (len(G[node])-(parent != 0)):
61 if node == target:
62 return 1.0/choices
63 continue
64 for child in G[node]:
65 if child == parent:
66 continue
67 stk.append((t-1, child, node,
68 choices*(len(G[node])-(parent != 0))))
69 return 0.0
70
71
72 # Time: O(n)
73 # Space: O(n)
74 # dfs solution with recursion with better precision
75 class Solution3(object):
76 def frogPosition(self, n, edges, t, target):
77 """
78 :type n: int
79 :type edges: List[List[int]]
80 :type t: int
81 :type target: int
82 :rtype: float
83 """
84 def dfs(G, target, t, node, parent):
85 if not t or not (len(G[node])-(parent != 0)):
86 return int(node == target)
87 result = 0
88 for child in G[node]:
89 if child == parent:
90 continue
91 result = dfs(G, target, t-1, child, node)
92 if result:
93 break
94 return result*(len(G[node])-(parent != 0))
95
96 G = collections.defaultdict(list)
97 for u, v in edges:
98 G[u].append(v)
99 G[v].append(u)
100 choices = dfs(G, target, t, 1, 0)
101 return 1.0/choices if choices else 0.0
102
103
104 # Time: O(n)
105 # Space: O(n)
106 # dfs solution with recursion
107 class Solution4(object):
108 def frogPosition(self, n, edges, t, target):
109 """
110 :type n: int
111 :type edges: List[List[int]]
112 :type t: int
113 :type target: int
114 :rtype: float
115 """
116 def dfs(G, target, t, node, parent):
117 if not t or not (len(G[node])-(parent != 0)):
118 return float(node == target)
119 for child in G[node]:
120 if child == parent:
121 continue
122 result = dfs(G, target, t-1, child, node)
123 if result:
124 break
125 return result/(len(G[node])-(parent != 0))
126
127 G = collections.defaultdict(list)
128 for u, v in edges:
129 G[u].append(v)
130 G[v].append(u)
131 return dfs(G, target, t, 1, 0)
*****************************

276. Maximum Performance of a Team


*****************************

You are given two integers n and k and two integer arrays speed and efficiency both of length n. There are n engineers
numbered from 1 to n. speed[i] and efficiency[i] represent the speed and efficiency of the ith engineer respectively.

Choose at most k different engineers out of the n engineers to form a team with the maximumperformance.

The performance of a team is the sum of their engineers' speeds multiplied by the minimum efficiency among their
engineers.

Return the maximum performance of this team. Since the answer can be a huge number, return it modulo 109 + 7 .

Example 1:

Input: n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 2


Output: 60
Explanation:
We have the maximum performance of the team by selecting engineer 2 (with speed=10 and efficiency=4) and engineer 5 (with speed=5 and efficie

Example 2:

Input: n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 3


Output: 68
Explanation:
This is the same example as the first but k = 3. We can select engineer 1, engineer 2 and engineer 5 to get the maximum performance of the te

Example 3:

Input: n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 4


Output: 72

Constraints:

1 <= k <= n <= 10 5


speed.length == n
efficiency.length == n
1 <= speed[i] <= 105
1 <= efficiency[i] <= 10 8
*****************************

276. Maximum Performance of a Team(C++)


*****************************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int maxPerformance(int n, vector& speed, vector& efficiency, int k) {
7 static const int MOD = 1e9 + 7;
8 uint64_t result = 0, s_sum = 0;
9 vector> engineers;
10 for (int i = 0; i < speed.size(); ++i) {
11 engineers.emplace_back(efficiency[i], speed[i]);
12 }
13 sort(engineers.begin(), engineers.end(), greater>());
14 priority_queue, greater> min_heap;
15 for (const auto& [e, s] : engineers) {
16 s_sum += s;
17 min_heap.emplace(s);
18 if (min_heap.size() > k) {
19 s_sum -= min_heap.top(); min_heap.pop();
20 }
21 result = max(result, s_sum * e);
22 }
23 return result % MOD;
24 }
25 };
*****************************

276. Maximum Performance of a Team(Python)


*****************************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 import itertools
5 import heapq
6
7
8 class Solution(object):
9 def maxPerformance(self, n, speed, efficiency, k):
10 """
11 :type n: int
12 :type speed: List[int]
13 :type efficiency: List[int]
14 :type k: int
15 :rtype: int
16 """
17 MOD = 10**9 + 7
18 result, s_sum = 0, 0
19 min_heap = []
20 for e, s in sorted(itertools.izip(efficiency, speed), reverse=True):
21 s_sum += s
22 heapq.heappush(min_heap, s)
23 if len(min_heap) > k:
24 s_sum -= heapq.heappop(min_heap)
25 result = max(result,s_sum*e)
26 return result % MOD
**************************

277. Total Sales Amount by Year


**************************

Table: Product

+---------------+---------+
| Column Name | Type |
+---------------+---------+
| product_id | int |
| product_name | varchar |
+---------------+---------+
product_id is the primary key for this table.
product_name is the name of the product.

Table: Sales

+---------------------+---------+
| Column Name | Type |
+---------------------+---------+
| product_id | int |
| period_start | date |
| period_end | date |
| average_daily_sales | int |
+---------------------+---------+
product_id is the primary key for this table.
period_start and period_end indicates the start and end date for sales period, both dates are inclusive.
The average_daily_sales column holds the average daily sales amount of the items for the period.

Write an SQL query to report the Total sales amount of each item for each year, with corresponding product
name, product_id, product_name and report_year.

Dates of the sales years are between 2018 to 2020. Return the result tableordered by product_id and report_year.

The query result format is in the following example:


Product table:
+------------+--------------+
| product_id | product_name |
+------------+--------------+
| 1 | LC Phone |
| 2 | LC T-Shirt |
| 3 | LC Keychain |
+------------+--------------+

Sales table:
+------------+--------------+-------------+---------------------+
| product_id | period_start | period_end | average_daily_sales |
+------------+--------------+-------------+---------------------+
| 1 | 2019-01-25 | 2019-02-28 | 100 |
| 2 | 2018-12-01 | 2020-01-01 | 10 |
| 3 | 2019-12-01 | 2020-01-31 | 1 |
+------------+--------------+-------------+---------------------+

Result table:
+------------+--------------+-------------+--------------+
| product_id | product_name | report_year | total_amount |
+------------+--------------+-------------+--------------+
| 1 | LC Phone | 2019 | 3500 |
| 2 | LC T-Shirt | 2018 | 310 |
| 2 | LC T-Shirt | 2019 | 3650 |
| 2 | LC T-Shirt | 2020 | 10 |
| 3 | LC Keychain | 2019 | 31 |
| 3 | LC Keychain | 2020 | 31 |
+------------+--------------+-------------+--------------+
LC Phone was sold for the period of 2019-01-25 to 2019-02-28, and there are 35 days for this period. Total amount 35*100 = 3500.
LC T-shirt was sold for the period of 2018-12-01 to 2020-01-01, and there are 31, 365, 1 days for years 2018, 2019 and 2020 respectively.
LC Keychain was sold for the period of 2019-12-01 to 2020-01-31, and there are 31, 31 days for years 2019 and 2020 respectively.
**************************

277. Total Sales Amount by Year(Shell)


**************************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 SELECT product_id,
5 product_name,
6 report_year,
7 (DATEDIFF(
8 CASE WHEN YEAR(period_end) > report_year THEN CONCAT(report_year, '-12-31') ELSE period_end END,
9 CASE WHEN YEAR(period_start) < report_year THEN CONCAT(report_year, '-01-01') ELSE period_start END
10 ) + 1) * average_daily_sales AS total_amount
11 FROM (SELECT s.product_id,
12 product_name,
13 period_start,
14 period_end,
15 average_daily_sales
16 FROM sales s
17 INNER JOIN product p
18 ON s.product_id = p.product_id
19 ) AS r,
20 (SELECT "2018" AS report_year
21 UNION ALL
22 SELECT "2019"
23 UNION ALL
24 SELECT "2020"
25 ) AS y
26 WHERE YEAR(period_start) <= report_year AND
27 YEAR(period_end) >= report_year
28 GROUP BY product_id,
29 report_year
30 ORDER BY product_id,
31 report_year;
32
33
34 # Time: O(nlogn)
35 # Space: O(n)
36 SELECT r.product_id,
37 product_name,
38 report_year,
39 total_amount
40 FROM ((SELECT product_id,
41 '2018' AS report_year,
42 days * average_daily_sales AS total_amount
43 FROM (SELECT product_id,
44 average_daily_sales,
45 DATEDIFF(
46 CASE WHEN period_end > '2018-12-31' THEN '2018-12-31' ELSE period_end END,
47 CASE WHEN period_start < '2018-01-01' THEN '2018-01-01' ELSE period_start END
48 ) + 1 AS days
49 FROM sales s) tmp
50 WHERE days > 0)
51 UNION ALL
52 (SELECT product_id,
53 '2019' AS report_year,
54 days * average_daily_sales AS total_amount
55 FROM (SELECT product_id,
56 average_daily_sales,
57 DATEDIFF(
58 CASE WHEN period_end > '2019-12-31' THEN '2019-12-31' ELSE period_end END,
59 CASE WHEN period_start < '2019-01-01' THEN '2019-01-01' ELSE period_start END
60 ) + 1 AS days
61 FROM sales s) tmp
62 WHERE days > 0)
63 UNION ALL
64 (SELECT product_id,
65 '2020' AS report_year,
66 days * average_daily_sales AS total_amount
67 FROM (SELECT product_id,
68 average_daily_sales,
69 DATEDIFF(
70 CASE WHEN period_end > '2020-12-31' THEN '2020-12-31' ELSE period_end END,
71 CASE WHEN period_start < '2020-01-01' THEN '2020-01-01' ELSE period_start END
72 ) + 1 AS days
73 FROM sales s) tmp
74 WHERE days > 0)
75 ) r
76 INNER JOIN product p
77 ON r.product_id = p.product_id
78 ORDER BY r.product_id,
79 report_year ;
********************

278. Pizza With 3n Slices


********************

There is a pizza with 3n slices of varying size, you and your friends will take slices of pizza as follows:

You will pick any pizza slice.


Your friend Alice will pick next slice in anti clockwise direction of your pick.
Your friend Bob will pick next slice in clockwise direction of your pick.
Repeat until there are no more slices of pizzas.

Sizes of Pizza slices is represented by circular arrayslices in clockwise direction.

Return the maximum possible sum of slice sizes which you can have.

Example 1:

Input: slices = [1,2,3,4,5,6]


Output: 10
Explanation: Pick pizza slice of size 4, Alice and Bob will pick slices with size 3 and 5 respectively. Then Pick slices with size 6, finally

Example 2:

Input: slices = [8,9,8,6,1,1]


Output: 16
Output: Pick pizza slice of size 8 in each turn. If you pick slice with size 9 your partners will pick slices of size 8.

Example 3:
Input: slices = [4,1,2,5,8,3,1,9,7]
Output: 21

Example 4:

Input: slices = [3,1,2]


Output: 3

Constraints:

1 <= slices.length <= 500


slices.length % 3 == 0
1 <= slices[i] <= 1000
********************

278. Pizza With 3n Slices(C++)


********************

1 // Time: O(n^2)
2 // Space: O(n)
3
4 // [observation]
5 // 1. we can never take two adjacent slices
6 // 2. if we want some set of N / 3 non-adjacent slices, there is always a way to take
7 //
8 // [proof]
9 // - for N = 3, it is obviously true.
10 // - for N' = N + 3,
11 // - because it's impossible to have only one unwanted slices between all wanted slices.
12 // if it's true, there will be 3N'/2 unwanted slices rather than 2N' unwanted ones, -><-
13 // - so we can always find a sequence of two unwanted slices with one wanted slice
14 // to take firstly, then we can find a way to take the remaining N ones by induction, QED
15
16 // better optimized space
17 class Solution {
18 public:
19 int maxSizeSlices(vector& slices) {
20 return max(maxSizeSlicesLinear(slices, 0, slices.size() - 1),
21 maxSizeSlicesLinear(slices, 1, slices.size()));
22 }
23
24 private:
25 int maxSizeSlicesLinear(const vector& slices, int start, int end) {
26 vector> dp(2, vector(slices.size() / 3 + 1));
27 for (int i = start; i < end; ++i) {
28 for (int j = min(((i - start + 1) - 1) / 2 + 1, int(slices.size()) / 3);
29 j >= 1;
30 --j) {
31 dp[i % 2][j] = max(dp[(i - 1 + 2) % 2][j],
32 dp[(i - 2 + 2) % 2][j - 1] + slices[i]);
33 }
34 }
35 return dp[(end - 1) % 2][slices.size() / 3];
36 }
37 };
38
39 // Time: O(n^2)
40 // Space: O(n)
41 class Solution2 {
42 public:
43 int maxSizeSlices(vector& slices) {
44 return max(maxSizeSlicesLinear(slices, 0, slices.size() - 1),
45 maxSizeSlicesLinear(slices, 1, slices.size()));
46 }
47
48 private:
49 int maxSizeSlicesLinear(const vector& slices, int start, int end) {
50 vector> dp(3, vector(slices.size() / 3 + 1));
51 for (int i = start; i < end; ++i) {
52 for (int j = 1;
53 j <= min(((i - start + 1) - 1) / 2 + 1, int(slices.size()) / 3);
54 ++j) {
55 dp[i % 3][j] = max(dp[(i - 1 + 3) % 3][j],
56 dp[(i - 2 + 3) % 3][j - 1] + slices[i]);
57 }
58 }
59 return dp[(end - 1) % 3][slices.size() / 3];
60 }
61 };
********************

278. Pizza With 3n Slices(Python)


********************

1 # Time: O(n^2)
2 # Space: O(n)
3
4 # [observation]
5 # 1. we can never take two adjacent slices
6 # 2. if we want some set of N / 3 non-adjacent slices, there is always a way to take
7 #
8 # [proof]
9 # - for N = 3, it is obviously true.
10 # - for N' = N + 3,
11 # - because it's impossible to have only one unwanted slices between all wanted slices.
12 # if it's true, there will be 3N'/2 unwanted slices rather than 2N' unwanted ones, -><-
13 # - so we can always find a sequence of two unwanted slices with one wanted slice
14 # to take firstly, then we can find a way to take the remaining N ones by induction, QED
15
16 # better optimized space
17 class Solution(object):
18 def maxSizeSlices(self, slices):
19 """
20 :type slices: List[int]
21 :rtype: int
22 """
23 def maxSizeSlicesLinear(slices, start, end):
24 dp = [[0]*(len(slices)//3+1) for _ in xrange(2)]
25 for i in xrange(start, end):
26 for j in reversed(xrange(1, min(((i-start+1)-1)//2+1, len(slices)//3)+1)):
27 dp[i%2][j] = max(dp[(i-1)%2][j], dp[(i-2)%2][j-1] + slices[i])
28 return dp[(end-1)%2][len(slices)//3]
29
30 return max(maxSizeSlicesLinear(slices, 0, len(slices)-1),
31 maxSizeSlicesLinear(slices, 1, len(slices)))
32
33
34 # Time: O(n^2)
35 # Space: O(n)
36 class Solution2(object):
37 def maxSizeSlices(self, slices):
38 """
39 :type slices: List[int]
40 :rtype: int
41 """
42 def maxSizeSlicesLinear(slices, start, end):
43 dp = [[0]*(len(slices)//3+1) for _ in xrange(3)]
44 for i in xrange(start, end):
45 for j in xrange(1, min(((i-start+1)-1)//2+1, len(slices)//3)+1):
46 dp[i%3][j] = max(dp[(i-1)%3][j], dp[(i-2)%3][j-1] + slices[i])
47 return dp[(end-1)%3][len(slices)//3]
48
49 return max(maxSizeSlicesLinear(slices, 0, len(slices)-1),
50 maxSizeSlicesLinear(slices, 1, len(slices)))
********************

279. Longest Happy Prefix


********************

A string is called a happy prefix if is a non-empty prefix which is also a suffix (excluding itself).

Given a string s , return the longest happy prefix of s . Return an empty string "" if no such prefix exists.

Example 1:

Input: s = "level"
Output: "l"
Explanation: s contains 4 prefix excluding itself ("l", "le", "lev", "leve"), and suffix ("l", "el", "vel", "evel"). The largest prefix which

Example 2:

Input: s = "ababab"
Output: "abab"
Explanation: "abab" is the largest prefix which is also suffix. They can overlap in the original string.

Example 3:

Input: s = "leetcodeleet"
Output: "leet"

Example 4:

Input: s = "a"
Output: ""

Constraints:

1 <= s.length <= 105


s contains only lowercase English letters.
********************

279. Longest Happy Prefix(C++)


********************

1 // Time: O(n)
2 // Space: O(n)
3
4 // kmp solution
5 class Solution {
6 public:
7 string longestPrefix(string s) {
8 return s.substr(0, getPrefix(s).back() + 1);
9 }
10
11 private:
12 vector getPrefix(const string& pattern) {
13 vector prefix(pattern.length(), -1);
14 int j = -1;
15 for (int i = 1; i < pattern.length(); ++i) {
16 while (j != -1 && pattern[j + 1] != pattern[i]) {
17 j = prefix[j];
18 }
19 if (pattern[j + 1] == pattern[i]) {
20 ++j;
21 }
22 prefix[i] = j;
23 }
24 return prefix;
25 }
26 };
27
28
29 // Time: O(n) on average
30 // Space: O(1)
31 // rolling-hash solution
32 class Solution2 {
33 public:
34 string longestPrefix(string s) {
35 static const int M = 1e9 + 7;
36 static const int D = 26;
37 int result = 0;
38 uint64_t prefix = 0, suffix = 0, power = 1;
39 for (int i = 0; i + 1 < s.length(); ++i) {
40 prefix = (prefix * D % M + (s[s.length() - (i + 1)] - 'a')) % M;
41 suffix = (suffix + (s[i] - 'a') * power % M) % M;
42 power = (power * D) % M;
43 if (prefix == suffix) {
44 // we assume M is a very large prime without hash collision
45 // assert(check(i + 1, s));
46 result = i + 1;
47 }
48 }
49 return s.substr(0, result);
50 }
51
52 private:
53 bool check(int l, const string& s) {
54 for (int i = 0; i < l; ++i) {
55 if (s[i] != s[s.length() - l + i]) {
56 return false;
57 }
58 }
59 return true;
60 }
61 };
********************

279. Longest Happy Prefix(Python)


********************

1 # Time: O(n)
2 # Space: O(n)
3
4 # kmp solution
5 class Solution(object):
6 def longestPrefix(self, s):
7 """
8 :type s: str
9 :rtype: str
10 """
11 def getPrefix(pattern):
12 prefix = [-1]*len(pattern)
13 j = -1
14 for i in xrange(1, len(pattern)):
15 while j != -1 and pattern[j+1] != pattern[i]:
16 j = prefix[j]
17 if pattern[j+1] == pattern[i]:
18 j += 1
19 prefix[i] = j
20 return prefix
21
22 return s[:getPrefix(s)[-1]+1]
23
24
25 # Time: O(n) on average
26 # Space: O(1)
27 # rolling-hash solution
28 class Solution2(object):
29 def longestPrefix(self, s):
30 """
31 :type s: str
32 :rtype: str
33 """
34 M = 10**9+7
35 D = 26
36 def check(l, s):
37 for i in xrange(l):
38 if s[i] != s[len(s)-l+i]:
39 return False
40 return True
41
42 result, prefix, suffix, power = 0, 0, 0, 1
43 for i in xrange(len(s)-1):
44 prefix = (prefix*D + (ord(s[i])-ord('a'))) % M
45 suffix = (suffix + (ord(s[len(s)-(i+1)])-ord('a'))*power) % M
46 power = (power*D)%M
47 if prefix == suffix:
48 # we assume M is a very large prime without hash collision
49 # assert(check(i+1, s))
50 result = i+1
51 return s[:result]
*********************

280. Find All Good Strings


*********************

Given the strings s1 and s2 of size n and the string evil, return the number of good strings.

A good string has size n, it is alphabetically greater than or equal tos1, it is alphabetically smaller than or equal to s2, and it
does not contain the string evil as a substring. Since the answer can be a huge number, return thismodulo 109 + 7 .

Example 1:

Input: n = 2, s1 = "aa", s2 = "da", evil = "b"


Output: 51
Explanation: There are 25 good strings starting with 'a': "aa","ac","ad",...,"az". Then there are 25 good strings starting with 'c': "ca","cc

Example 2:

Input: n = 8, s1 = "leetcode", s2 = "leetgoes", evil = "leet"


Output: 0
Explanation: All strings greater than or equal to s1 and smaller than or equal to s2 start with the prefix "leet", therefore, there is not an

Example 3:

Input: n = 2, s1 = "gx", s2 = "gz", evil = "x"


Output: 2

Constraints:

s1.length == n
s2.length == n
s1 <= s2
1 <= n <= 500
1 <= evil.length <= 50
All strings consist of lowercase English letters.
*********************

280. Find All Good Strings(C++)


*********************

1 // Time: O(m * n)
2 // Space: O(m)
3
4 class Solution {
5 public:
6 int findGoodStrings(int n, string s1, string s2, string evil) {
7 const auto& prefix = getPrefix(evil);
8 vector>>> dp(
9 2, vector>>(
10 2, vector>(
11 2, vector(evil.length()))));
12 dp[0][0][0][0] = 1;
13 for (int i = 0; i < n; ++i) {
14 dp[(i + 1) % 2] = vector>>(
15 2, vector>(
16 2, vector(evil.length())));
17 for (int j = 0; j < 2; ++j) {
18 for (int k = 0; k < 2; ++k) {
19 const auto min_c = j ? 'a' : s1[i];
20 const auto max_c = k ? 'z' : s2[i];
21 for (int l = 0; l < evil.length(); ++l) {
22 if (!dp[i % 2][j][k][l]) {
23 continue;
24 }
25 for (char c = min_c; c <= max_c; ++c) {
26 int m = l - 1;
27 while (m != -1 && evil[m + 1] != c) {
28 m = prefix[m];
29 }
30 if (evil[m + 1] == c) {
31 ++m;
32 }
33 if (m + 1 == evil.length()) {
34 continue;
35 }
36 add(&dp[(i + 1) % 2][j || c != s1[i]][k || c != s2[i]][m + 1], dp[i % 2][j][k][l]);
37 }
38 }
39 }
40 }
41 }
42 int result = 0;
43 for (int j = 0; j < 2; ++j) {
44 for (int k = 0; k < 2; ++k) {
45 for (int l = 0; l < evil.length(); ++l) {
46 add(&result, dp[n % 2][j][k][l]);
47 }
48 }
49 }
50 return result;
51 }
52
53 private:
54 vector getPrefix(const string& pattern) {
55 vector prefix(pattern.length(), -1);
56 int j = -1;
57 for (int i = 1; i < pattern.length(); ++i) {
58 while (j != -1 && pattern[j + 1] != pattern[i]) {
59 j = prefix[j];
60 }
61 if (pattern[j + 1] == pattern[i]) {
62 ++j;
63 }
64 prefix[i] = j;
65 }
66 return prefix;
67 }
68
69 void add(int *x, int y) {
70 static const int MOD = 1e9 + 7;
71 *x = (*x + y) % MOD;
72 }
73 };
*********************

280. Find All Good Strings(Python)


*********************

1 # Time: O(m * n)
2 # Space: O(m)
3
4 class Solution(object):
5 def findGoodStrings(self, n, s1, s2, evil):
6 """
7 :type n: int
8 :type s1: str
9 :type s2: str
10 :type evil: str
11 :rtype: int
12 """
13 MOD = 10**9+7
14 def getPrefix(pattern):
15 prefix = [-1]*len(pattern)
16 j = -1
17 for i in xrange(1, len(pattern)):
18 while j != -1 and pattern[j+1] != pattern[i]:
19 j = prefix[j]
20 if pattern[j+1] == pattern[i]:
21 j += 1
22 prefix[i] = j
23 return prefix
24
25 prefix = getPrefix(evil)
26 dp = [[[[0]*len(evil) for _ in xrange(2)] for _ in xrange(2)] for _ in xrange(2)]
27 dp[0][0][0][0] = 1
28 for i in xrange(n):
29 dp[(i+1)%2] = [[[0]*len(evil) for _ in xrange(2)] for _ in xrange(2)]
30 for j in xrange(2):
31 for k in xrange(2):
32 min_c = 'a' if j else s1[i]
33 max_c = 'z' if k else s2[i]
34 for l in xrange(len(evil)):
35 if not dp[i%2][j][k][l]:
36 continue
37 for c in xrange(ord(min_c)-ord('a'), ord(max_c)-ord('a')+1):
38 c = chr(c+ord('a'))
39 m = l-1
40 while m != -1 and evil[m+1] != c:
41 m = prefix[m]
42 if evil[m+1] == c:
43 m += 1
44 if m+1 == len(evil):
45 continue
46 dp[(i+1)%2][j or (s1[i] != c)][k or (s2[i] != c)][m+1] = \
47 (dp[(i+1)%2][j or (s1[i] != c)][k or (s2[i] != c)][m+1] + dp[i%2][j][k][l]) % MOD
48 result = 0
49 for j in xrange(2):
50 for k in xrange(2):
51 for l in xrange(len(evil)):
52 result = (result + dp[n%2][j][k][l]) % MOD
53 return result
***************

281. Reducing Dishes


***************

A chef has collected data on the satisfaction level of his n dishes. Chef can cook any dish in 1 unit of time.

Like-time coefficient of a dish is defined as the time taken to cook that dish including previous dishes multiplied by its
satisfaction level i.e. time[i]*satisfaction[i]

Return the maximum sum of Like-time coefficient that the chef can obtain after dishes preparation.

Dishes can be prepared in any order and the chef can discard some dishes to get this maximum value.

Example 1:

Input: satisfaction = [-1,-8,0,5,-9]


Output: 14
Explanation: After Removing the second and last dish, the maximum total Like-time coefficient will be equal to (-1*1 + 0*2 + 5*3 = 14). Each

Example 2:

Input: satisfaction = [4,3,2]


Output: 20
Explanation: Dishes can be prepared in any order, (2*1 + 3*2 + 4*3 = 20)

Example 3:

Input: satisfaction = [-1,-4,-5]


Output: 0
Explanation: People don't like the dishes. No dish is prepared.

Example 4:

Input: satisfaction = [-2,5,-1,0,3,-3]


Output: 35

Constraints:

n == satisfaction.length
1 <= n <= 500
-10^3 <= satisfaction[i] <= 10^3
***************

281. Reducing Dishes(C++)


***************

1 // Time: O(nlogn)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int maxSatisfaction(vector& satisfaction) {
7 sort(begin(satisfaction), end(satisfaction), greater());
8 int result = 0;
9 for (int i = 0, curr = 0; i < satisfaction.size() && curr + satisfaction[i] > 0; ++i) {
10 curr += satisfaction[i];
11 result += curr;
12 }
13 return result;
14 }
15 };
***************

281. Reducing Dishes(Python)


***************

1 # Time: O(nlogn)
2 # Space: O(1)
3
4 class Solution(object):
5 def maxSatisfaction(self, satisfaction):
6 """
7 :type satisfaction: List[int]
8 :rtype: int
9 """
10 satisfaction.sort(reverse=True)
11 result, curr = 0, 0
12 for x in satisfaction:
13 curr += x
14 if curr <= 0:
15 break
16 result += curr
17 return result
**************

282. Stone Game III


**************

Alice and Bob continue their games with piles of stones. There are several stonesarranged in a row, and each stone has
an associated value which is an integer given in the array stoneValue.

Alice and Bob take turns, with Alice starting first. On each player's turn, that player can take1, 2 or 3 stones from the first
remaining stones in the row.

The score of each player is the sum of values of the stones taken. The score of each player is0 initially.

The objective of the game is to end with the highest score, and the winner is the player with the highest score and there
could be a tie. The game continues until all the stones have been taken.

Assume Alice and Bob play optimally.

Return "Alice" if Alice will win, "Bob" if Bob will win or "Tie" if they end the game with the same score.

Example 1:

Input: values = [1,2,3,7]


Output: "Bob"
Explanation: Alice will always lose. Her best move will be to take three piles and the score become 6. Now the score of Bob is 7 and Bob wins

Example 2:

Input: values = [1,2,3,-9]


Output: "Alice"
Explanation: Alice must choose all the three piles at the first move to win and leave Bob with negative score.
If Alice chooses one pile her score will be 1 and the next move Bob's score becomes 5. The next move Alice will take the pile with value = -9
If Alice chooses two piles her score will be 3 and the next move Bob's score becomes 3. The next move Alice will take the pile with value = -
Remember that both play optimally so here Alice will choose the scenario that makes her win.

Example 3:

Input: values = [1,2,3,6]


Output: "Tie"
Explanation: Alice cannot win this game. She can end the game in a draw if she decided to choose all the first three piles, otherwise she wil

Example 4:

Input: values = [1,2,3,-1,-2,-3,7]


Output: "Alice"

Example 5:

Input: values = [-1,-2,-3]


Output: "Tie"
Constraints:

1 <= values.length <= 50000


-1000 <= values[i] <= 1000
**************

282. Stone Game III(C++)


**************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 string stoneGameIII(vector& stoneValue) {
7 vector dp(3, numeric_limits::min());
8 dp[stoneValue.size() % 3] = 0;
9 for (int i = stoneValue.size() - 1; i >= 0; --i) {
10 int max_dp = numeric_limits::min();
11 for (int j = 0, curr = 0; j < 3 && i + j < stoneValue.size(); ++j) {
12 curr += stoneValue[i + j];
13 max_dp = max(max_dp, curr - dp[(i + j + 1) % 3]);
14 }
15 dp[i % 3] = max_dp;
16 }
17 return dp[0] == 0 ? "Tie" : (dp[0] > 0 ? "Alice" : "Bob");
18 }
19 };
**************

282. Stone Game III(Python)


**************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def stoneGameIII(self, stoneValue):
6 """
7 :type stoneValue: List[int]
8 :rtype: str
9 """
10 dp = [float("-inf")]*3
11 dp[len(stoneValue)%3] = 0
12 for i in reversed(xrange(len(stoneValue))):
13 max_dp, curr = float("-inf"), 0
14 for j in xrange(min(3, len(stoneValue)-i)):
15 curr += stoneValue[i+j]
16 max_dp = max(max_dp, curr-dp[(i+j+1)%3])
17 dp[i%3] = max_dp
18 return ["Tie", "Alice", "Bob"][cmp(dp[0], 0)]
**********************************

283. Number of Ways to Paint N × 3 Grid


**********************************

You have a grid of size n x 3 and you want to paint each cell of the grid with exactly one of the three colors:Red, Yellow, or
Green while making sure that no two adjacent cells have the same color (i.e., no two cells that share vertical or horizontal
sides have the same color).

Given n the number of rows of the grid, returnthe number of ways you can paint this grid. As the answer may grow large, the
answer must be computed modulo 109 + 7 .

Example 1:

Input: n = 1
Output: 12
Explanation: There are 12 possible way to paint the grid as shown.

Example 2:

Input: n = 2
Output: 54

Example 3:

Input: n = 3
Output: 246

Example 4:

Input: n = 7
Output: 106494

Example 5:

Input: n = 5000
Output: 30228214
Constraints:

n == grid.length
grid[i].length == 3
1 <= n <= 5000
**********************************

283. Number of Ways to Paint N × 3 Grid(C++)


**********************************

1 // Time: O(logn)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int numOfWays(int n) {
7 static const vector> T = {{3, 2},
8 {2, 2}};
9 const auto result = matrixMult({{6, 6}}, matrixExpo(T, n - 1))[0]; // [a1, a0] * T^(n-1)
10 return (result[0] + result[1]) % MOD;
11 }
12
13 private:
14 vector> matrixExpo(const vector>& A, int pow) {
15 vector> result(A.size(), vector(A.size()));
16 vector> A_exp(A);
17 for (int i = 0; i < A.size(); ++i) {
18 result[i][i] = 1;
19 }
20 while (pow) {
21 if (pow % 2 == 1) {
22 result = matrixMult(result, A_exp);
23 }
24 A_exp = matrixMult(A_exp, A_exp);
25 pow /= 2;
26 }
27 return result;
28 }
29
30 vector> matrixMult(const vector>& A, const vector>& B) {
31 vector> result(A.size(), vector(B[0].size()));
32 for (int i = 0; i < A.size(); ++i) {
33 for (int j = 0; j < B[0].size(); ++j) {
34 int64_t entry = 0;
35 for (int k = 0; k < B.size(); ++k) {
36 entry = (static_cast(A[i][k]) * B[k][j] % MOD + entry) % MOD;
37 }
38 result[i][j] = static_cast(entry);
39 }
40 }
41 return result;
42 }
43 const int MOD = 1e9 + 7;
44 };
45
46 // Time: O(n)
47 // Space: O(1)
48 class Solution2 {
49 public:
50 int numOfWays(int n) {
51 static const int MOD = 1e9 + 7;
52 uint64_t aba = 6, abc = 6;
53 for (int i = 1; i < n; ++i) {
54 tie(aba, abc) = pair((3 * aba % MOD + 2 * abc % MOD) % MOD,
55 (2 * abc % MOD + 2 * aba % MOD) %MOD);
56 }
57 return (aba + abc) % MOD;
58 }
59 };
**********************************

283. Number of Ways to Paint N × 3 Grid(Python)


**********************************

1 # Time: O(logn)
2 # Space: O(1)
3
4 import itertools
5
6
7 class Solution(object):
8 def numOfWays(self, n):
9 """
10 :type n: int
11 :rtype: int
12 """
13 def matrix_expo(A, K):
14 result = [[int(i==j) for j in xrange(len(A))]
15 for i in xrange(len(A))]
16 while K:
17 if K % 2:
18 result = matrix_mult(result, A)
19 A = matrix_mult(A, A)
20 K /= 2
21 return result
22
23 def matrix_mult(A, B):
24 ZB = zip(*B)
25 return [[sum(a*b % MOD for a, b in itertools.izip(row, col)) % MOD
26 for col in ZB] for row in A]
27
28 MOD = 10**9 + 7
29 T = [[3, 2],
30 [2, 2]]
31 return sum(matrix_mult([[6, 6]], matrix_expo(T, n-1))[0]) % MOD # [a1, a0] * T^(n-1)
32
33
34 # Time: O(n)
35 # Space: O(1)
36 class Solution2(object):
37 def numOfWays(self, n):
38 """
39 :type n: int
40 :rtype: int
41 """
42 MOD = 10**9 + 7
43 aba, abc = 6, 6
44 for _ in xrange(n-1):
45 aba, abc = (3*aba%MOD + 2*abc%MOD)%MOD, \
46 (2*abc%MOD + 2*aba%MOD)%MOD
47 return (aba+abc)%MOD
************************************

284. Find the Quiet Students in All Exams


************************************

Table: Student

+---------------------+---------+
| Column Name | Type |
+---------------------+---------+
| student_id | int |
| student_name | varchar |
+---------------------+---------+
student_id is the primary key for this table.
student_name is the name of the student.

Table: Exam

+---------------+---------+
| Column Name | Type |
+---------------+---------+
| exam_id | int |
| student_id | int |
| score | int |
+---------------+---------+
(exam_id, student_id) is the primary key for this table.
Student with student_id got score points in exam with id exam_id.

A "quite" student is the one who took at least one exam and didn't score neither the high score nor the low score.

Write an SQL query to report the students (student_id, student_name) being "quiet" inALL exams.

Don't return the student who has never taken any exam. Return the result tableordered by student_id.

The query result format is in the following example.


Student table:
+-------------+---------------+
| student_id | student_name |
+-------------+---------------+
| 1 | Daniel |
| 2 | Jade |
| 3 | Stella |
| 4 | Jonathan |
| 5 | Will |
+-------------+---------------+

Exam table:
+------------+--------------+-----------+
| exam_id | student_id | score |
+------------+--------------+-----------+
| 10 | 1 | 70 |
| 10 | 2 | 80 |
| 10 | 3 | 90 |
| 20 | 1 | 80 |
| 30 | 1 | 70 |
| 30 | 3 | 80 |
| 30 | 4 | 90 |
| 40 | 1 | 60 |
| 40 | 2 | 70 |
| 40 | 4 | 80 |
+------------+--------------+-----------+

Result table:
+-------------+---------------+
| student_id | student_name |
+-------------+---------------+
| 2 | Jade |
+-------------+---------------+

For exam 1: Student 1 and 3 hold the lowest and high score respectively.
For exam 2: Student 1 hold both highest and lowest score.
For exam 3 and 4: Studnet 1 and 4 hold the lowest and high score respectively.
Student 2 and 5 have never got the highest or lowest in any of the exam.
Since student 5 is not taking any exam, he is excluded from the result.
So, we only return the information of Student 2.
************************************

284. Find the Quiet Students in All Exams(Shell)


************************************

1 # Time: O(m + nlogn)


2 # Space: O(m + n)
3
4 SELECT s.student_id,
5 s.student_name
6 FROM student s
7 INNER JOIN (SELECT a.student_id,
8 Count(a.exam_id) AS total_exam,
9 Sum(CASE
10 WHEN a.score > min_score
11 AND a.score < max_score THEN 1
12 ELSE 0
13 END) AS quite_exam
14 FROM exam a
15 INNER JOIN (SELECT exam_id,
16 Min(score) AS min_score,
17 Max(score) AS max_score
18 FROM exam
19 GROUP BY exam_id
20 ORDER BY NULL) b
21 ON a.exam_id = b.exam_id
22 GROUP BY a.student_id
23 ORDER BY NULL) c
24 ON s.student_id = c.student_id
25 WHERE c.total_exam = c.quite_exam
26 ORDER BY s.student_id;
*****************

285. Restore The Array


*****************

A program was supposed to print an array of integers. The program forgot to print whitespaces and the array is printed as a
string of digits s and all we know is that all integers in the array were in the range[1, k] and there are no leading zeros in the
array.

Given the string s and the integer k , return the number of the possible arrays that can be printed ass using the mentioned
program. Since the answer may be very large, return itmodulo 109 + 7 .

Example 1:

Input: s = "1000", k = 10000


Output: 1
Explanation: The only possible array is [1000]

Example 2:

Input: s = "1000", k = 10
Output: 0
Explanation: There cannot be an array that was printed this way and has all integer >= 1 and <= 10.

Example 3:

Input: s = "1317", k = 2000


Output: 8
Explanation: Possible arrays are [1317],[131,7],[13,17],[1,317],[13,1,7],[1,31,7],[1,3,17],[1,3,1,7]

Example 4:

Input: s = "2020", k = 30
Output: 1
Explanation: The only possible array is [20,20]. [2020] is invalid because 2020 > 30. [2,020] is ivalid because 020 contains leading zeros.

Example 5:

Input: s = "1234567890", k = 90
Output: 34

Constraints:

1 <= s.length <= 105


s consists of only digits and does not contain leading zeros.
1 <= k <= 10 9
*****************

285. Restore The Array(C++)


*****************

1 // Time: O(nlogk)
2 // Space: O(logk)
3
4 class Solution {
5 public:
6 int numberOfArrays(string s, int k) {
7 static const int MOD = 1e9 + 7;
8 int klen = to_string(k).length();
9 vector dp(klen + 1);
10 dp[s.length() % dp.size()] = 1;
11 for (int i = s.length() - 1; i >= 0; --i) {
12 dp[i % dp.size()] = 0;
13 if (s[i] == '0') {
14 continue;
15 }
16 for (uint64_t j = i, curr = 0; j < min(uint64_t(i + klen), s.length()); ++j) {
17 curr = curr * 10 + s[j] - '0';
18 if (curr > k) {
19 break;
20 }
21 dp[i % dp.size()] = (dp[i % dp.size()] + dp[(j + 1) % dp.size()]) % MOD;
22 }
23 }
24 return dp[0];
25 }
26 };
*****************

285. Restore The Array(Python)


*****************

1 # Time: O(nlogk)
2 # Space: O(logk)
3
4 class Solution(object):
5 def numberOfArrays(self, s, k):
6 """
7 :type s: str
8 :type k: int
9 :rtype: int
10 """
11 MOD = 10**9 + 7
12 klen = len(str(k))
13 dp = [0]*(klen+1)
14 dp[len(s)%len(dp)] = 1
15 for i in reversed(xrange(len(s))):
16 dp[i%len(dp)] = 0
17 if s[i] == '0':
18 continue
19 curr = 0
20 for j in xrange(i, min(i+klen, len(s))):
21 curr = 10*curr + int(s[j])
22 if curr > k:
23 break
24 dp[i%len(dp)] = (dp[i%len(dp)] + dp[(j+1)%len(dp)])%MOD
25 return dp[0]
****************************************************************

286. Build Array Where You Can Find The Maximum


Exactly K Comparisons
****************************************************************

Given three integers n, m and k . Consider the following algorithm to find the maximum element of an array of positive
integers:

You should build the array arr which has the following properties:

arr has exactly n integers.


1 <= arr[i] <= m where (0 <= i < n) .
After applying the mentioned algorithm to arr, the value search_cost is equal to k .

Return the number of ways to build the array arr under the mentioned conditions. As the answer may grow large, the
answer must be computed modulo 10^9 + 7 .

Example 1:

Input: n = 2, m = 3, k = 1
Output: 6
Explanation: The possible arrays are [1, 1], [2, 1], [2, 2], [3, 1], [3, 2] [3, 3]

Example 2:

Input: n = 5, m = 2, k = 3
Output: 0
Explanation: There are no possible arrays that satisify the mentioned conditions.

Example 3:

Input: n = 9, m = 1, k = 1
Output: 1
Explanation: The only possible array is [1, 1, 1, 1, 1, 1, 1, 1, 1]
Example 4:

Input: n = 50, m = 100, k = 25


Output: 34549172
Explanation: Don't forget to compute the answer modulo 1000000007

Example 5:

Input: n = 37, m = 17, k = 7


Output: 418930126

Constraints:

1 <= n <= 50
1 <= m <= 100
0 <= k <= n
****************************************************************

286. Build Array Where You Can Find The Maximum


Exactly K Comparisons(C++)
****************************************************************

1 // Time: O(n * m * k)
2 // Space: O(m * k)
3
4 class Solution {
5 public:
6 int numOfArrays(int n, int m, int k) {
7 static const int MOD = 1e9 + 7;
8 // dp[l][i][j] = number of ways of constructing array length l with max element i at search cost j
9 vector>> dp(2, vector>(m + 1, vector(k + 1)));
10 // prefix_dp[l][i][j] = sum(dp[l][i][j] for i in [1..i])
11 vector>> prefix_dp(2, vector>(m + 1, vector(k + 1)));
12 for (uint64_t i = 1; i <= m; ++i) {
13 dp[1][i][1] = 1;
14 prefix_dp[1][i][1] = (prefix_dp[1][i - 1][1] + dp[1][i][1]) % MOD;
15 }
16 for (uint64_t l = 2; l <= n; ++l) {
17 for (uint64_t i = 1; i <= m; ++i) {
18 for (uint64_t j = 1; j <= k; ++j) {
19 dp[l % 2][i][j] = (i * dp[(l - 1) % 2][i][j] % MOD + prefix_dp[(l - 1) % 2][i - 1][j - 1]) % MOD;
20 prefix_dp[l % 2][i][j] = (prefix_dp[l % 2][i - 1][j] + dp[l % 2][i][j]) % MOD;
21 }
22 }
23 }
24 return prefix_dp[n % 2][m][k];
25 }
26 };
****************************************************************

286. Build Array Where You Can Find The Maximum


Exactly K Comparisons(Python)
****************************************************************

1 # Time: O(n * m * k)
2 # Space: O(m * k)
3
4 class Solution(object):
5 def numOfArrays(self, n, m, k):
6 """
7 :type n: int
8 :type m: int
9 :type k: int
10 :rtype: int
11 """
12 MOD = 10**9 + 7
13 # dp[l][i][j] = number of ways of constructing array length l with max element i at search cost j
14 dp = [[[0]*(k+1) for _ in xrange(m+1)] for _ in xrange(2)]
15 # prefix_dp[l][i][j] = sum(dp[l][i][j] for i in [1..i])
16 prefix_dp = [[[0]*(k+1) for _ in xrange(m+1)] for _ in xrange(2)]
17 for i in xrange(1, m+1):
18 dp[1][i][1] = 1
19 prefix_dp[1][i][1] = (prefix_dp[1][i-1][1] + dp[1][i][1])%MOD
20 for l in xrange(2, n+1):
21 for i in xrange(1, m+1):
22 for j in xrange(1, k+1):
23 dp[l%2][i][j] = (i*dp[(l-1)%2][i][j]%MOD + prefix_dp[(l-1)%2][i-1][j-1])%MOD
24 prefix_dp[l%2][i][j] = (prefix_dp[l%2][i-1][j] + dp[l%2][i][j])%MOD
25 return prefix_dp[n%2][m][k]
**********************

287. Constrained Subset Sum


**********************

Given an integer array nums and an integer k , return the maximum sum of anon-empty subsequence of that array such that
for every two consecutive integers in the subsequence, nums[i] and nums[j], where i < j , the condition j - i <= k is satisfied.

A subsequence of an array is obtained by deleting some number of elements (can be zero) from the array, leaving the
remaining elements in their original order.

Example 1:

Input: nums = [10,2,-10,5,20], k = 2


Output: 37
Explanation: The subsequence is [10, 2, 5, 20].

Example 2:

Input: nums = [-1,-2,-3], k = 1


Output: -1
Explanation: The subsequence must be non-empty, so we choose the largest number.

Example 3:

Input: nums = [10,-2,-10,-5,20], k = 2


Output: 23
Explanation: The subsequence is [10, -2, -5, 20].

Constraints:

1 <= k <= nums.length <= 10 5


-104 <= nums[i] <= 10 4
**********************

287. Constrained Subset Sum(C++)


**********************

1 // Time: O(n)
2 // Space: O(k)
3
4 class Solution {
5 public:
6 int constrainedSubsetSum(vector& nums, int k) {
7 int result = numeric_limits::min();
8 deque> dq;
9 for (int i = 0; i < nums.size(); ++i) {
10 if (!dq.empty() && i - dq.front().first == k + 1) {
11 dq.pop_front();
12 }
13 const auto& curr = nums[i] + (!dq.empty() ? dq.front().second : 0);
14 while (!dq.empty() && dq.back().second <= curr) {
15 dq.pop_back();
16 }
17 if (curr > 0) {
18 dq.emplace_back(i, curr);
19 }
20 result = max(result, curr);
21 }
22 return result;
23 }
24 };
**********************

287. Constrained Subset Sum(Python)


**********************

1 # Time: O(n)
2 # Space: O(k)
3
4 import collections
5
6
7 class Solution(object):
8 def constrainedSubsetSum(self, nums, k):
9 """
10 :type nums: List[int]
11 :type k: int
12 :rtype: int
13 """
14 result, dq = float("-inf"), collections.deque()
15 for i in xrange(len(nums)):
16 if dq and i-dq[0][0] == k+1:
17 dq.popleft()
18 curr = nums[i] + (dq[0][1] if dq else 0)
19 while dq and dq[-1][1] <= curr:
20 dq.pop()
21 if curr > 0:
22 dq.append((i, curr))
23 result = max(result, curr)
24 return result
***************************************************

288. Number of Ways to Wear Different Hats to Each


Other
***************************************************

There are n people and 40 types of hats labeled from 1 to 40.

Given a list of list of integers hats , where hats[i] is a list of all hats preferred by the i-th person.

Return the number of ways that the n people wear different hats to each other.

Since the answer may be too large, return it modulo 10^9 + 7 .

Example 1:

Input: hats = [[3,4],[4,5],[5]]


Output: 1
Explanation: There is only one way to choose hats given the conditions.
First person choose hat 3, Second person choose hat 4 and last one hat 5.

Example 2:

Input: hats = [[3,5,1],[3,5]]


Output: 4
Explanation: There are 4 ways to choose hats
(3,5), (5,3), (1,3) and (1,5)

Example 3:

Input: hats = [[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]


Output: 24
Explanation: Each person can choose hats labeled from 1 to 4.
Number of Permutations of (1,2,3,4) = 24.

Example 4:

Input: hats = [[1,2,3],[2,3,5,6],[1,3,7,9],[1,8,9],[2,5,7]]


Output: 111

Constraints:

n == hats.length
1 <= n <= 10
1 <= hats[i].length <= 40
1 <= hats[i][j] <= 40
hats[i] contains a list of unique integers.
***************************************************

288. Number of Ways to Wear Different Hats to Each


Other(C++)
***************************************************

1 // Time: O(h * 2^n)


2 // Space: O(2^n)
3
4 class Solution {
5 public:
6 int numberWays(vector>& hats) {
7 static const int MOD = 1e9 + 7;
8 static const int HAT_SIZE = 40;
9
10 vector> hat_to_people(HAT_SIZE);
11 for (int i = 0; i < hats.size(); ++i) {
12 for (const auto& hat: hats[i]) {
13 hat_to_people[hat - 1].emplace_back(i);
14 }
15 }
16 vector dp(1 << hats.size());
17 dp[0] = 1;
18 for (const auto& people : hat_to_people) {
19 for (int mask = dp.size() - 1; mask >= 0; --mask) {
20 for (const int& p: people) {
21 if (mask & (1 << p)) {
22 continue;
23 }
24 dp[mask | (1 << p)] += dp[mask];
25 dp[mask | (1 << p)] %= MOD;
26 }
27 }
28 }
29 return dp.back();
30 }
31 };
***************************************************

288. Number of Ways to Wear Different Hats to Each


Other(Python)
***************************************************

1 # Time: O(h * 2^n)


2 # Space: O(2^n)
3
4 class Solution(object):
5 def numberWays(self, hats):
6 """
7 :type hats: List[List[int]]
8 :rtype: int
9 """
10 MOD = 10**9 + 7
11 HAT_SIZE = 40
12 hat_to_people = [[] for _ in xrange(HAT_SIZE)]
13 for i in xrange(len(hats)):
14 for h in hats[i]:
15 hat_to_people[h-1].append(i)
16 dp = [0]*(1<
**************************************************************************

289. Longest Continuous Subarray With Absolute Diff


Less Than or Equal to Limit
**************************************************************************

Given an array of integers nums and an integer limit, return the size of the longestnon-empty subarray such that the absolute
difference between any two elements of this subarray is less than or equal to limit.

Example 1:

Input: nums = [8,2,4,7], limit = 4


Output: 2
Explanation: All subarrays are:
[8] with maximum absolute diff |8-8| = 0 <= 4.
[8,2] with maximum absolute diff |8-2| = 6 > 4.
[8,2,4] with maximum absolute diff |8-2| = 6 > 4.
[8,2,4,7] with maximum absolute diff |8-2| = 6 > 4.
[2] with maximum absolute diff |2-2| = 0 <= 4.
[2,4] with maximum absolute diff |2-4| = 2 <= 4.
[2,4,7] with maximum absolute diff |2-7| = 5 > 4.
[4] with maximum absolute diff |4-4| = 0 <= 4.
[4,7] with maximum absolute diff |4-7| = 3 <= 4.
[7] with maximum absolute diff |7-7| = 0 <= 4.
Therefore, the size of the longest subarray is 2.

Example 2:

Input: nums = [10,1,2,4,7,2], limit = 5


Output: 4
Explanation: The subarray [2,4,7,2] is the longest since the maximum absolute diff is |2-7| = 5 <= 5.

Example 3:

Input: nums = [4,2,2,2,4,4,2,2], limit = 0


Output: 3

Constraints:

1 <= nums.length <= 10 5


1 <= nums[i] <= 10 9
0 <= limit <= 10 9
**************************************************************************

289. Longest Continuous Subarray With Absolute Diff


Less Than or Equal to Limit(C++)
**************************************************************************
1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int longestSubarray(vector& nums, int limit) {
7 deque max_dq, min_dq;
8 int left = 0;
9 for (int right = 0; right < nums.size(); ++right) {
10 while (!max_dq.empty() && nums[max_dq.back()] <= nums[right]) {
11 max_dq.pop_back();
12 }
13 max_dq.emplace_back(right);
14 while (!min_dq.empty() && nums[min_dq.back()] >= nums[right]) {
15 min_dq.pop_back();
16 }
17 min_dq.emplace_back(right);
18 if (nums[max_dq[0]] - nums[min_dq[0]] > limit) {
19 if (max_dq[0] == left) {
20 max_dq.pop_front();
21 }
22 if (min_dq[0] == left) {
23 min_dq.pop_front();
24 }
25 ++left; // advance left by one to not count in result
26 }
27 }
28 return nums.size() - left;
29 }
30 };
31
32 // Time: O(n)
33 // Space: O(n)
34 class Solution2 {
35 public:
36 int longestSubarray(vector& nums, int limit) {
37 deque max_dq, min_dq;
38 int result = 0, left = 0;
39 for (int right = 0; right < nums.size(); ++right) {
40 while (!max_dq.empty() && nums[max_dq.back()] <= nums[right]) {
41 max_dq.pop_back();
42 }
43 max_dq.emplace_back(right);
44 while (!min_dq.empty() && nums[min_dq.back()] >= nums[right]) {
45 min_dq.pop_back();
46 }
47 min_dq.emplace_back(right);
48 while (nums[max_dq[0]] - nums[min_dq[0]] > limit) { // both always exist "right" element
49 if (max_dq[0] == left) {
50 max_dq.pop_front();
51 }
52 if (min_dq[0] == left) {
53 min_dq.pop_front();
54 }
55 ++left;
56 }
57 result = max(result, right - left + 1);
58 }
59 return result;
60 }
61 };
**************************************************************************

289. Longest Continuous Subarray With Absolute Diff


Less Than or Equal to Limit(Python)
**************************************************************************
1 # Time: O(n)
2 # Space: O(n)
3
4 import collections
5
6
7 class Solution(object):
8 def longestSubarray(self, nums, limit):
9 """
10 :type nums: List[int]
11 :type limit: int
12 :rtype: int
13 """
14 max_dq, min_dq = collections.deque(), collections.deque()
15 left = 0
16 for right, num in enumerate(nums):
17 while max_dq and nums[max_dq[-1]] <= num:
18 max_dq.pop()
19 max_dq.append(right)
20 while min_dq and nums[min_dq[-1]] >= num:
21 min_dq.pop()
22 min_dq.append(right)
23 if nums[max_dq[0]]-nums[min_dq[0]] > limit:
24 if max_dq[0] == left:
25 max_dq.popleft()
26 if min_dq[0] == left:
27 min_dq.popleft()
28 left += 1 # advance left by one to not count in result
29 return len(nums)-left
30
31
32 # Time: O(n)
33 # Space: O(n)
34 import collections
35
36
37 class Solution2(object):
38 def longestSubarray(self, nums, limit):
39 """
40 :type nums: List[int]
41 :type limit: int
42 :rtype: int
43 """
44 max_dq, min_dq = collections.deque(), collections.deque()
45 result, left = 0, 0
46 for right, num in enumerate(nums):
47 while max_dq and nums[max_dq[-1]] <= num:
48 max_dq.pop()
49 max_dq.append(right)
50 while min_dq and nums[min_dq[-1]] >= num:
51 min_dq.pop()
52 min_dq.append(right)
53 while nums[max_dq[0]]-nums[min_dq[0]] > limit: # both always exist "right" element
54 if max_dq[0] == left:
55 max_dq.popleft()
56 if min_dq[0] == left:
57 min_dq.popleft()
58 left += 1
59 result = max(result, right-left+1)
60 return result
******************************************************

290. Find the Kth Smallest Sum of a Matrix With Sorted


Rows
******************************************************

You are given an m * n matrix, mat, and an integer k , which has its rows sorted in non-decreasing order.

You are allowed to choose exactly 1 element from each row to form an array. Return the Kthsmallest array sum among all
possible arrays.

Example 1:

Input: mat = [[1,3,11],[2,4,6]], k = 5


Output: 7
Explanation: Choosing one element from each row, the first k smallest sum are:
[1,2], [1,4], [3,2], [3,4], [1,6]. Where the 5th sum is 7.

Example 2:

Input: mat = [[1,3,11],[2,4,6]], k = 9


Output: 17

Example 3:

Input: mat = [[1,10,10],[1,4,5],[2,3,6]], k = 7


Output: 9
Explanation: Choosing one element from each row, the first k smallest sum are:
[1,1,2], [1,1,3], [1,4,2], [1,4,3], [1,1,6], [1,5,2], [1,5,3]. Where the 7th sum is 9.

Example 4:

Input: mat = [[1,1,10],[2,2,9]], k = 7


Output: 12

Constraints:

m == mat.length
n == mat.length[i]
1 <= m, n <= 40
1 <= k <= min(200, n ^ m)
1 <= mat[i][j] <= 5000
mat[i] is a non decreasing array.
******************************************************

290. Find the Kth Smallest Sum of a Matrix With Sorted


Rows(C++)
******************************************************

1 // Time: O(m * klogk)


2 // Space: O(k)
3
4 class Solution {
5 public:
6 int kthSmallest(vector>& mat, int k) {
7 auto result = mat[0];
8 for (int r = 1; r < mat.size(); ++r) {
9 result = kSmallestPairs(result, mat[r], k);
10 }
11 return result[k - 1];
12 }
13
14 private:
15 vector kSmallestPairs(const vector& nums1, const vector& nums2, int k) {
16 vector result;
17 priority_queue, vector>, greater>> min_heap;
18 for (int c = 0; c < min(int(nums1.size()), k); ++c) {
19 min_heap.emplace(nums1[c] + nums2[0], 0);
20 }
21 while (result.size() != k && !min_heap.empty()) {
22 const auto [total, c] = min_heap.top(); min_heap.pop();
23 result.emplace_back(total);
24 if (c + 1 == nums2.size()) {
25 continue;
26 }
27 min_heap.emplace(total - nums2[c] + nums2[c + 1], c + 1);
28 }
29 return result;
30 }
31 };
32
33 // Time: O((k + m) * log(m * MAX_NUM)) ~ O(k * m * log(m * MAX_NUM))
34 // Space: O(m)
35 class Solution2 {
36 public:
37 int kthSmallest(vector>& mat, int k) {
38 static const int MAX_NUM = 5000;
39 int left = mat.size(), right = mat.size() * MAX_NUM;
40 while (left <= right) {
41 const auto& mid = left + (right - left) / 2;
42 const auto& cnt = countArraysHaveSumLessOrEqual(mat, k, 0, mid);
43 if (cnt >= k) {
44 right = mid - 1;
45 } else {
46 left = mid + 1;
47 }
48 }
49 return left;
50 }
51
52 private:
53 int countArraysHaveSumLessOrEqual(const vector>& mat, int k, int r, int target) { // Time: O(k + m) ~ O(k * m)
54 if (target < 0) {
55 return 0;
56 }
57 if (r == mat.size()) {
58 return 1;
59 }
60 int result = 0;
60
61 for (int c = 0; c < mat[0].size(); ++c) {
62 int cnt = countArraysHaveSumLessOrEqual(mat, k - result, r + 1, target - mat[r][c]);
63 if (!cnt) {
64 break;
65 }
66 result += cnt;
67 if (result > k) {
68 break;
69 }
70 }
71 return result;
72 }
73 };
******************************************************

290. Find the Kth Smallest Sum of a Matrix With Sorted


Rows(Python)
******************************************************
1 # Time: O(m * klogk)
2 # Space: O(k)
3
4 import heapq
5
6
7 class Solution(object):
8 def kthSmallest(self, mat, k):
9 """
10 :type mat: List[List[int]]
11 :type k: int
12 :rtype: int
13 """
14 def kSmallestPairs(nums1, nums2, k):
15 result, min_heap = [], []
16 for c in xrange(min(len(nums1), k)):
17 heapq.heappush(min_heap, (nums1[c]+nums2[0], 0))
18 c += 1
19 while len(result) != k and min_heap:
20 total, c = heapq.heappop(min_heap)
21 result.append(total)
22 if c+1 == len(nums2):
23 continue
24 heapq.heappush(min_heap, (total-nums2[c]+nums2[c+1], c+1))
25 return result
26
27 result = mat[0]
28 for r in xrange(1, len(mat)):
29 result = kSmallestPairs(result, mat[r], k)
30 return result[k-1]
31
32
33 # Time: O((k + m) * log(m * MAX_NUM)) ~ O(k * m * log(m * MAX_NUM))
34 # Space: O(m)
35 class Solution2(object):
36 def kthSmallest(self, mat, k):
37 """
38 :type mat: List[List[int]]
39 :type k: int
40 :rtype: int
41 """
42 def countArraysHaveSumLessOrEqual(mat, k, r, target): # Time: O(k + m) ~ O(k * m)
43 if target < 0:
44 return 0
45 if r == len(mat):
46 return 1
47 result = 0
48 for c in xrange(len(mat[0])):
49 cnt = countArraysHaveSumLessOrEqual(mat, k-result, r+1, target-mat[r][c])
50 if not cnt:
51 break
52 result += cnt
53 if result > k:
54 break
55 return result
56
57 MAX_NUM = 5000
58 left, right = len(mat), len(mat)*MAX_NUM
59 while left <= right:
60 mid = left + (right-left)//2
61 cnt = countArraysHaveSumLessOrEqual(mat, k, 0, mid)
62 if cnt >= k:
63 right = mid-1
64 else:
65 left = mid+1
66 return left
67
*********************************

291. Number of Ways of Cutting a Pizza


*********************************

Given a rectangular pizza represented as a rows x cols matrix containing the following characters: 'A' (an apple) and '.' (empty
cell) and given the integer k . You have to cut the pizza intok pieces using k-1 cuts.

For each cut you choose the direction: vertical or horizontal, then you choose a cut position at the cell boundary and cut the
pizza into two pieces. If you cut the pizza vertically, give the left part of the pizza to a person. If you cut the pizza
horizontally, give the upper part of the pizza to a person. Give the last piece of pizza to the last person.

Return the number of ways of cutting the pizza such that each piece containsat least one apple. Since the answer can be a
huge number, return this modulo 10^9 + 7.

Example 1:

Input: pizza = ["A..","AAA","..."], k = 3


Output: 3
Explanation: The figure above shows the three ways to cut the pizza. Note that pieces must contain at least one apple.

Example 2:

Input: pizza = ["A..","AA.","..."], k = 3


Output: 1

Example 3:

Input: pizza = ["A..","A..","..."], k = 1


Output: 1

Constraints:

1 <= rows, cols <= 50


rows == pizza.length
cols == pizza[i].length
1 <= k <= 10
pizza consists of characters 'A' and '.' only.
*********************************

291. Number of Ways of Cutting a Pizza(C++)


*********************************

1 // Time: O(m * n * k * (m + n))


2 // Space: O(m * n * k)
3
4 class Solution {
5 public:
6 int ways(vector& pizza, int k) {
7 static int MOD = 1e9 + 7;
8 vector> prefix(pizza.size(), vector(pizza[0].size()));
9 for (int j = pizza[0].size() - 1; j >= 0; --j) {
10 for (int accu = 0, i = pizza.size() - 1; i >= 0; --i) {
11 accu += pizza[i][j] == 'A';
12 prefix[i][j] = ((j + 1 != pizza[0].size()) ? prefix[i][j + 1] : 0) + accu;
13 }
14 }
15 vector>> dp(pizza.size(),
16 vector>(pizza[0].size(),
17 vector(k)));
18 for (int i = pizza.size() - 1; i >= 0; --i) {
19 for (int j = pizza[0].size() - 1; j >= 0; --j) {
20 dp[i][j][0] = 1;
21 for (int m = 1; m < k; ++m) {
22 for (int n = i + 1; n < pizza.size() && prefix[n][j]; ++n) {
23 if (prefix[i][j] == prefix[n][j]) {
24 continue;
25 }
26 dp[i][j][m] = (dp[i][j][m] + dp[n][j][m - 1]) % MOD;
27 }
28 for (int n = j + 1; n < pizza[0].size() && prefix[i][n]; ++n) {
29 if (prefix[i][j] == prefix[i][n]) {
30 continue;
31 }
32 dp[i][j][m] = (dp[i][j][m] + dp[i][n][m - 1]) % MOD;
33 }
34 }
35 }
36 }
37 return dp[0][0][k - 1];
38 }
39 };
*********************************

291. Number of Ways of Cutting a Pizza(Python)


*********************************

1 # Time: O(m * n * k * (m + n))


2 # Space: O(m * n * k)
3
4 class Solution(object):
5 def ways(self, pizza, k):
6 """
7 :type pizza: List[str]
8 :type k: int
9 :rtype: int
10 """
11 MOD = 10**9+7
12 prefix = [[0]*len(pizza[0]) for _ in xrange(len(pizza))]
13 for j in reversed(xrange(len(pizza[0]))):
14 accu = 0
15 for i in reversed(xrange(len(pizza))):
16 accu += int(pizza[i][j] == 'A')
17 prefix[i][j] = (prefix[i][j+1] if (j+1 < len(pizza[0])) else 0) + accu
18 dp = [[[0]*k for _ in xrange(len(pizza[0]))] for _ in xrange(len(pizza))]
19 for i in reversed(xrange(len(pizza))):
20 for j in reversed(xrange(len(pizza[0]))):
21 dp[i][j][0] = 1
22 for m in xrange(1, k):
23 for n in xrange(i+1, len(pizza)):
24 if prefix[i][j] == prefix[n][j]:
25 continue
26 if prefix[n][j] == 0:
27 break
28 dp[i][j][m] = (dp[i][j][m] + dp[n][j][m-1]) % MOD
29 for n in xrange(j+1, len(pizza[0])):
30 if prefix[i][j] == prefix[i][n]:
31 continue
32 if prefix[i][n] == 0:
33 break
34 dp[i][j][m] = (dp[i][j][m] + dp[i][n][m-1]) % MOD
35 return dp[0][0][k-1]
******************************************************

292. Form Largest Integer With Digits That Add up to


Target
******************************************************

Given an array of integers cost and an integer target. Return the maximum integer you can paint under the following rules:

The cost of painting a digit (i+1) is given by cost[i] (0 indexed).


The total cost used must be equal to target.
Integer does not have digits 0.

Since the answer may be too large, return it as string.

If there is no way to paint any integer given the condition, return "0".

Example 1:

Input: cost = [4,3,2,5,6,7,2,5,5], target = 9


Output: "7772"
Explanation: The cost to paint the digit '7' is 2, and the digit '2' is 3. Then cost("7772") = 2*3+ 3*1 = 9. You could also paint "977", but
Digit cost
1 -> 4
2 -> 3
3 -> 2
4 -> 5
5 -> 6
6 -> 7
7 -> 2
8 -> 5
9 -> 5

Example 2:

Input: cost = [7,6,5,5,5,6,8,7,8], target = 12


Output: "85"
Explanation: The cost to paint the digit '8' is 7, and the digit '5' is 5. Then cost("85") = 7 + 5 = 12.

Example 3:

Input: cost = [2,4,6,2,4,6,4,4,4], target = 5


Output: "0"
Explanation: It's not possible to paint any integer with total cost equal to target.

Example 4:

Input: cost = [6,10,15,40,40,40,40,40,40], target = 47


Output: "32211"

Constraints:

cost.length == 9
1 <= cost[i] <= 5000
1 <= target <= 5000
******************************************************

292. Form Largest Integer With Digits That Add up to


Target(C++)
******************************************************
1 // Time: O(t)
2 // Space: O(t)
3
4 class Solution {
5 public:
6 string largestNumber(vector& cost, int target) {
7 vector dp(1);
8 dp[0] = 0;
9 for (int t = 1; t <= target; ++t) {
10 dp.emplace_back(-1);
11 for (int i = 0; i < 9; ++i) {
12 if (t < cost[i] || dp[t - cost[i]] < 0) {
13 continue;
14 }
15 dp[t] = max(dp[t], dp[t - cost[i]] + 1);
16 }
17 }
18 if (dp[target] < 0) {
19 return "0";
20 }
21 string result;
22 for (int i = 8; i >= 0; --i) {
23 while (target >= cost[i] && dp[target] == dp[target - cost[i]] + 1) {
24 target -= cost[i];
25 result.push_back('1' + i);
26 }
27 }
28 return result;
29 }
30 };
31
32 // Time: O(t)
33 // Space: O(t)
34 class Solution2 {
35 public:
36 string largestNumber(vector& cost, int target) {
37 const auto& key = [](const auto& a) {
38 return pair{accumulate(cbegin(a), cend(a), 0), a};
39 };
40 vector> dp = {vector(9)};
41 for (int t = 1; t <= target; ++t) {
42 dp.emplace_back();
43 for (int i = 0; i < 9; ++i) {
44 if (t < cost[i] || dp[t - cost[i]].empty()) {
45 continue;
46 }
47 auto curr = dp[t - cost[i]];
48 ++curr[8 - i];
49 if (key(curr) > key(dp[t])) {
50 dp[t] = move(curr);
51 }
52 }
53 }
54 if (dp.back().empty()) {
55 return "0";
56 }
57 string result;
58 for (int i = 0; i < dp.back().size(); ++i) {
59 result += string(dp.back()[i], '1' + 8 - i);
60 }
61 return result;
62 }
63 };
******************************************************

292. Form Largest Integer With Digits That Add up to


Target(Python)
******************************************************
1 # Time: O(t)
2 # Space: O(t)
3
4 class Solution(object):
5 def largestNumber(self, cost, target):
6 """
7 :type cost: List[int]
8 :type target: int
9 :rtype: str
10 """
11 dp = [0]
12 for t in xrange(1, target+1):
13 dp.append(-1)
14 for i, c in enumerate(cost):
15 if t-c < 0 or dp[t-c] < 0:
16 continue
17 dp[t] = max(dp[t], dp[t-c]+1)
18 if dp[target] < 0:
19 return "0"
20 result = []
21 for i in reversed(xrange(9)):
22 while target >= cost[i] and dp[target] == dp[target-cost[i]]+1:
23 target -= cost[i]
24 result.append(i+1)
25 return "".join(map(str, result))
26
27
28 # Time: O(t)
29 # Space: O(t)
30 class Solution2(object):
31 def largestNumber(self, cost, target):
32 """
33 :type cost: List[int]
34 :type target: int
35 :rtype: str
36 """
37 def key(bag):
38 return sum(bag), bag
39
40 dp = [[0]*9]
41 for t in xrange(1, target+1):
42 dp.append([])
43 for d, c in enumerate(cost):
44 if t < c or not dp[t-c]:
45 continue
46 curr = dp[t-c][:]
47 curr[~d] += 1
48 if key(curr) > key(dp[t]):
49 dp[-1] = curr
50 if not dp[-1]:
51 return "0"
52 return "".join(str(9-i)*c for i, c in enumerate(dp[-1]))
53
54
55 # Time: O(t^2)
56 # Space: O(t^2)
57 class Solution3(object):
58 def largestNumber(self, cost, target):
59 """
60 :type cost: List[int]
61 :type target: int
62 :rtype: str
63 """
64 dp = [0]
65 for t in xrange(1, target+1):
66 dp.append(-1)
67 for i, c in enumerate(cost):
68 if t-c < 0:
69 continue
70 dp[t] = max(dp[t], dp[t-c]*10 + i+1)
71 return str(max(dp[t], 0))
******************************************************

293. Maximum Number of Darts Inside of a Circular


Dartboard
******************************************************

You have a very large square wall and a circular dartboard placed on the wall. You have been challenged to throw darts into
the board blindfolded. Darts thrown at the wall are represented as an array of points on a 2D plane.

Return the maximum number of points that are within or lie on any circular dartboard of radius r.

Example 1:

Input: points = [[-2,0],[2,0],[0,2],[0,-2]], r = 2


Output: 4
Explanation: Circle dartboard with center in (0,0) and radius = 2 contain all points.

Example 2:

Input: points = [[-3,0],[3,0],[2,6],[5,4],[0,9],[7,8]], r = 5


Output: 5
Explanation: Circle dartboard with center in (0,4) and radius = 5 contain all points except the point (7,8).

Example 3:

Input: points = [[-2,0],[2,0],[0,2],[0,-2]], r = 1


Output: 1

Example 4:

Input: points = [[1,2],[3,5],[1,-1],[2,3],[4,1],[1,3]], r = 2


Output: 4
Constraints:

1 <= points.length <= 100


points[i].length == 2
-10^4 <= points[i][0], points[i][1] <= 10^4
1 <= r <= 5000
******************************************************

293. Maximum Number of Darts Inside of a Circular


Dartboard(C++)
******************************************************

1 // Time: O(n^2 * logn)


2 // Space: O(n)
3
4 // angle sweep solution
5 // great explanation:
6 // https://leetcode.com/problems/maximum-number-of-darts-inside-of-a-circular-dartboard/discuss/636345/Python-O(n3)-and-O(n2logn)-soluti
7 class Solution {
8 public:
9 int numPoints(vector>& points, int r) {
10 int result = 0;
11 for (int i = 0; i < points.size(); ++i) {
12 result = max(result, countPoints(points, r, i));
13 }
14 return result;
15 }
16
17 private:
18 int countPoints(const vector>& points, int r, int i) {
19 vector> angles;
20 for (int j = 0; j < points.size(); ++j) {
21 if (j == i) {
22 continue;
23 }
24 int dx = points[i][0] - points[j][0];
25 int dy = points[i][1] - points[j][1];
26 const auto d = sqrt(dx * dx + dy * dy);
27 if (d > 2 * r) {
28 continue;
29 }
30 const auto delta = acos(d / (2 * r));
31 const auto angle = atan2(dy, dx);
32 angles.emplace_back(angle - delta, false);
33 angles.emplace_back(angle + delta, true);
34 }
35 sort(begin(angles), end(angles));
36 int result = 1, count = 1;
37 for (const auto& [_, is_closed] : angles) { // angle sweep
38 if (!is_closed) {
39 ++count;
40 } else {
41 --count;
42 }
43 result = max(result, count);
44 }
45 return result;
46 }
47 };
******************************************************

293. Maximum Number of Darts Inside of a Circular


Dartboard(Python)
******************************************************

1 # Time: O(n^2 * logn)


2 # Space: O(n)
3
4 import math
5
6
7 # angle sweep solution
8 # great explanation:
9 # https://leetcode.com/problems/maximum-number-of-darts-inside-of-a-circular-dartboard/discuss/636345/Python-O(n3)-and-O(n2logn)-solutio
10 class Solution(object):
11 def numPoints(self, points, r):
12 """
13 :type points: List[List[int]]
14 :type r: int
15 :rtype: int
16 """
17 def count_points(points, r, i):
18 angles = []
19 for j in xrange(len(points)):
20 if i == j:
21 continue
22 dx, dy = points[i][0]-points[j][0], points[i][1]-points[j][1]
23 d = math.sqrt(dx**2 + dy**2)
24 if d > 2*r:
25 continue
26 delta, angle = math.acos(d/(2*r)), math.atan2(dy, dx)
27 angles.append((angle-delta, 0)), angles.append((angle+delta, 1))
28 angles.sort()
29 result, count = 1, 1
30 for _, is_closed in angles: # angle sweep
31 if not is_closed:
32 count += 1
33 else:
34 count -= 1
35 result = max(result, count)
36 return result
37
38 return max(count_points(points, r, i) for i in xrange(len(points)))
***********************************

294. Max Dot Product of Two Subsequences


***********************************

Given two arrays nums1 and nums2.

Return the maximum dot product between non-empty subsequences of nums1 and nums2 with the same length.

A subsequence of a array is a new array which is formed from the original array by deleting some (can be none) of the
characters without disturbing the relative positions of the remaining characters. (ie, [2,3,5] is a subsequence of [1,2,3,4,5] while
[1,5,3] is not).

Example 1:

Input: nums1 = [2,1,-2,5], nums2 = [3,0,-6]


Output: 18
Explanation: Take subsequence [2,-2] from nums1 and subsequence [3,-6] from nums2.
Their dot product is (2*3 + (-2)*(-6)) = 18.

Example 2:

Input: nums1 = [3,-2], nums2 = [2,-6,7]


Output: 21
Explanation: Take subsequence [3] from nums1 and subsequence [7] from nums2.
Their dot product is (3*7) = 21.

Example 3:

Input: nums1 = [-1,-1], nums2 = [1,1]


Output: -1
Explanation: Take subsequence [-1] from nums1 and subsequence [1] from nums2.
Their dot product is -1.

Constraints:

1 <= nums1.length, nums2.length <= 500


-1000 <= nums1[i], nums2[i] <= 1000
***********************************

294. Max Dot Product of Two Subsequences(C++)


***********************************

1 // Time: O(m * n)
2 // Space: O(min(m, n))
3
4 class Solution {
5 public:
6 int maxDotProduct(vector& nums1, vector& nums2) {
7 if (nums1.size() < nums2.size()) {
8 return maxDotProduct(nums2, nums1);
9 }
10 vector> dp(2, vector(nums2.size()));
11 for (int i = 0; i < nums1.size(); ++i) {
12 for (int j = 0; j < nums2.size(); ++j) {
13 dp[i % 2][j] = int64_t(nums1[i]) * nums2[j];
14 if (i && j) {
15 dp[i % 2][j] += max(dp[(i - 1) % 2][j - 1], int64_t(0));
16 }
17 if (i) {
18 dp[i % 2][j] = max(dp[i % 2][j], dp[(i - 1) % 2][j]);
19 }
20 if (j) {
21 dp[i % 2][j] = max(dp[i % 2][j], dp[i % 2][j - 1]);
22 }
23 }
24 }
25 return dp[(nums1.size() - 1) % 2].back();
26 }
27 };
***********************************

294. Max Dot Product of Two Subsequences(Python)


***********************************

1 # Time: O(m * n)
2 # Space: O(min(m, n))
3
4 class Solution(object):
5 def maxDotProduct(self, nums1, nums2):
6 """
7 :type nums1: List[int]
8 :type nums2: List[int]
9 :rtype: int
10 """
11 if len(nums1) < len(nums2):
12 return self.maxDotProduct(nums2, nums1)
13 dp = [[0]*len(nums2) for i in xrange(2)]
14 for i in xrange(len(nums1)):
15 for j in xrange(len(nums2)):
16 dp[i%2][j] = nums1[i]*nums2[j]
17 if i and j:
18 dp[i%2][j] += max(dp[(i-1)%2][j-1], 0)
19 if i:
20 dp[i%2][j] = max(dp[i%2][j], dp[(i-1)%2][j])
21 if j:
22 dp[i%2][j] = max(dp[i%2][j], dp[i%2][j-1])
23 return dp[(len(nums1)-1)%2][-1]
****************

295. Cherry Pickup II


****************

Given a rows x cols matrix grid representing a field of cherries. Each cell in grid represents the number of cherries that you can
collect.

You have two robots that can collect cherries for you, Robot #1 is located at the top-left corner (0,0) , and Robot #2 is
located at the top-right corner (0, cols-1) of the grid.

Return the maximum number of cherries collection using both robots by following the rules below:

From a cell (i,j), robots can move to cell (i+1, j-1) , (i+1, j) or (i+1, j+1).
When any robot is passing through a cell, It picks it up all cherries, and the cell becomes an empty cell (0).
When both robots stay on the same cell, only one of them takes the cherries.
Both robots cannot move outside of the grid at any moment.
Both robots should reach the bottom row in thegrid.

Example 1:

Input: grid = [[3,1,1],[2,5,1],[1,5,5],[2,1,1]]


Output: 24
Explanation: Path of robot #1 and #2 are described in color green and blue respectively.
Cherries taken by Robot #1, (3 + 2 + 5 + 2) = 12.
Cherries taken by Robot #2, (1 + 5 + 5 + 1) = 12.
Total of cherries: 12 + 12 = 24.

Example 2:
Input: grid = [[1,0,0,0,0,0,1],[2,0,0,0,0,3,0],[2,0,9,0,0,0,0],[0,3,0,5,4,0,0],[1,0,2,3,0,0,6]]
Output: 28
Explanation: Path of robot #1 and #2 are described in color green and blue respectively.
Cherries taken by Robot #1, (1 + 9 + 5 + 2) = 17.
Cherries taken by Robot #2, (1 + 3 + 4 + 3) = 11.
Total of cherries: 17 + 11 = 28.

Example 3:

Input: grid = [[1,0,0,3],[0,0,0,3],[0,0,3,3],[9,0,3,3]]


Output: 22

Example 4:

Input: grid = [[1,1],[1,1]]


Output: 4

Constraints:

rows == grid.length
cols == grid[i].length
2 <= rows, cols <= 70
0 <= grid[i][j] <= 100
****************

295. Cherry Pickup II(C++)


****************
1 // Time: O(m * n^2)
2 // Space: O(n^2)
3
4 class Solution {
5 public:
6 int cherryPickup(vector>& grid) {
7 vector>> dp(2,
8 vector>(grid[0].size() + 2,
9 vector(grid[0].size() + 2, numeric_limits::min())));
10
11 dp[0][1][grid[0].size()] = grid[0][0] + grid[0][grid[0].size() - 1];
12 int result = 0;
13 for (int i = 1; i < grid.size(); ++i) {
14 for (int j = 1; j <= grid[0].size(); ++j) {
15 for (int k = 1; k <= grid[0].size(); ++k) {
16 int max_prev_dp = numeric_limits::min();
17 for (int d1 = -1; d1 <= 1; ++d1) {
18 for (int d2 = -1; d2 <= 1; ++d2) {
19 max_prev_dp = max(max_prev_dp, dp[(i - 1) % 2][j + d1][k + d2]);
20 }
21 }
22 dp[i % 2][j][k] = (max_prev_dp == numeric_limits::min()) ? numeric_limits::min() :
23 max_prev_dp + ((j != k) ? (grid[i][j - 1] + grid[i][k - 1]) : grid[i][j - 1]);
24 result = max(result, dp[i % 2][j][k]);
25 }
26 }
27 }
28 return result;
29 }
30 };
31
32 // Time: O(m * n^2)
33 // Space: O(n^2)
34 class Solution2 {
35 public:
36 int cherryPickup(vector>& grid) {
37 vector>> dp(2,
38 vector>(grid[0].size(),
39 vector(grid[0].size(), numeric_limits::min())));
40
41 dp[0][0][grid[0].size() - 1] = grid[0][0] + grid[0][grid[0].size() - 1];
42 int result = 0;
43 for (int i = 1; i < grid.size(); ++i) {
44 for (int j = 0; j < grid[0].size(); ++j) {
45 for (int k = 0; k < grid[0].size(); ++k) {
46 int max_prev_dp = numeric_limits::min();
47 for (int d1 = -1; d1 <= 1; ++d1) {
48 if (!(0 <= j + d1 && j + d1 < grid[0].size())) {
49 continue;
50 }
51 for (int d2 = -1; d2 <= 1; ++d2) {
52 if (!(0 <= k + d2 && k + d2 < grid[0].size())) {
53 continue;
54 }
55 max_prev_dp = max(max_prev_dp, dp[(i - 1) % 2][j + d1][k + d2]);
56 }
57 }
58 dp[i % 2][j][k] = (max_prev_dp == numeric_limits::min()) ? numeric_limits::min() :
59 max_prev_dp + ((j != k) ? (grid[i][j] + grid[i][k]) : grid[i][j]);
60 result = max(result, dp[i % 2][j][k]);
61 }
62 }
63 }
64 return result;
65 }
66 };
****************

295. Cherry Pickup II(Python)


****************

1 # Time: O(m * n^2)


2 # Space: O(n^2)
3
4 import itertools
5
6
7 class Solution(object):
8 def cherryPickup(self, grid):
9 """
10 :type grid: List[List[int]]
11 :rtype: int
12 """
13 dp = [[[float("-inf")]*(len(grid[0])+2) for _ in xrange(len(grid[0])+2)] for _ in xrange(2)]
14 dp[0][1][len(grid[0])] = grid[0][0] + grid[0][len(grid[0])-1]
15 for i in xrange(1, len(grid)):
16 for j in xrange(1, len(grid[0])+1):
17 for k in xrange(1, len(grid[0])+1):
18 dp[i%2][j][k] = max(dp[(i-1)%2][j+d1][k+d2] for d1 in xrange(-1, 2) for d2 in xrange(-1, 2)) + \
19 ((grid[i][j-1]+grid[i][k-1]) if j != k else grid[i][j-1])
20 return max(itertools.imap(max, *dp[(len(grid)-1)%2]))
21
22
23 # Time: O(m * n^2)
24 # Space: O(n^2)
25 import itertools
26
27
28 class Solution2(object):
29 def cherryPickup(self, grid):
30 """
31 :type grid: List[List[int]]
32 :rtype: int
33 """
34 dp = [[[float("-inf")]*len(grid[0]) for _ in xrange(len(grid[0]))] for _ in xrange(2)]
35 dp[0][0][len(grid[0])-1] = grid[0][0] + grid[0][len(grid[0])-1]
36 for i in xrange(1, len(grid)):
37 for j in xrange(len(grid[0])):
38 for k in xrange(len(grid[0])):
39 dp[i%2][j][k] = max(dp[(i-1)%2][j+d1][k+d2] for d1 in xrange(-1, 2) for d2 in xrange(-1, 2)
40 if 0 <= j+d1 < len(grid[0]) and 0 <= k+d2 < len(grid[0])) + \
41 ((grid[i][j]+grid[i][k]) if j != k else grid[i][j])
42 return max(itertools.imap(max, *dp[(len(grid)-1)%2]))
*******************************************************************

296. Probability of a Two Boxes Having The Same


Number of Distinct Balls
*******************************************************************

Given 2n balls of k distinct colors. You will be given an integer arrayballs of size k where balls[i] is the number of balls of color
i.

All the balls will be shuffled uniformly at random, then we will distribute the first n balls to the first box and the remaining n
balls to the other box (Please read the explanation of the second example carefully).

Please note that the two boxes are considered different. For example, if we have two balls of colorsa and b, and two boxes []
and (), then the distribution [a] (b) is considered different than the distribution [b] (a) (Please read the explanation of the
first example carefully).

We want to calculate the probability that the two boxes have the same number of distinct balls.

Example 1:

Input: balls = [1,1]


Output: 1.00000
Explanation: Only 2 ways to divide the balls equally:
- A ball of color 1 to box 1 and a ball of color 2 to box 2
- A ball of color 2 to box 1 and a ball of color 1 to box 2
In both ways, the number of distinct colors in each box is equal. The probability is 2/2 = 1

Example 2:

Input: balls = [2,1,1]


Output: 0.66667
Explanation: We have the set of balls [1, 1, 2, 3]
This set of balls will be shuffled randomly and we may have one of the 12 distinct shuffles with equale probability (i.e. 1/12):
[1,1 / 2,3], [1,1 / 3,2], [1,2 / 1,3], [1,2 / 3,1], [1,3 / 1,2], [1,3 / 2,1], [2,1 / 1,3], [2,1 / 3,1], [2,3 / 1,1], [3,1 / 1,2], [3,1 / 2,1]
After that we add the first two balls to the first box and the second two balls to the second box.
We can see that 8 of these 12 possible random distributions have the same number of distinct colors of balls in each box.
Probability is 8/12 = 0.66667

Example 3:

Input: balls = [1,2,1,2]


Output: 0.60000
Explanation: The set of balls is [1, 2, 2, 3, 4, 4]. It is hard to display all the 180 possible random shuffles of this set but it is easy to
Probability = 108 / 180 = 0.6

Example 4:

Input: balls = [3,2,1]


Output: 0.30000
Explanation: The set of balls is [1, 1, 1, 2, 2, 3]. It is hard to display all the 60 possible random shuffles of this set but it is easy to
Probability = 18 / 60 = 0.3
Example 5:

Input: balls = [6,6,6,6,6,6]


Output: 0.90327

Constraints:

1 <= balls.length <= 8


1 <= balls[i] <= 6
sum(balls) is even.
Answers within 10^-5 of the actual value will be accepted as correct.
*******************************************************************

296. Probability of a Two Boxes Having The Same


Number of Distinct Balls(C++)
*******************************************************************

1 // Time: O(k^3 * n^2)


2 // Space: O(k^2 * n)
3
4 class Solution {
5 public:
6 double getProbability(vector& balls) {
7 unordered_map, uint64_t, PairHash> dp;
8 dp[pair(0, 0)] = 1; // dp[i, j] is the ways of number difference i and color difference j
9 for (const auto& n : balls) { // O(k) times
10 unordered_map, uint64_t, PairHash> new_dp;
11 for (const auto& kvp : dp) { // O(k^2 * n) times
12 const auto& [ndiff, cdiff] = kvp.first;
13 for (int k = 0, new_count = 1; k <= n; ++k, new_count *= n - k + 1, new_count /= k) { // O(n) times
14 const auto& new_ndiff = ndiff + (k - (n - k));
15 const auto& new_cdiff = (k == 0) ? cdiff - 1 : ((k == n) ? cdiff + 1 : cdiff);
16 new_dp[pair(new_ndiff, new_cdiff)] += kvp.second * new_count;
17 }
18 }
19 dp = move(new_dp);
20 }
21 const auto& total = accumulate(cbegin(balls), cend(balls), 0);
22 return double(dp[pair(0, 0)]) / nCr(total, total / 2);
23 }
24
25 private:
26 uint64_t nCr(int n, int r) { // Time: O(n), Space: O(1)
27 if (n - r < r) {
28 return nCr(n, n - r);
29 }
30 uint64_t c = 1;
31 for (int k = 1; k <= r; ++k) {
32 c *= n - k + 1;
33 c /= k;
34 }
35 return c;
36 }
37
38 template
39 struct PairHash {
40 size_t operator()(const pair& p) const {
41 size_t seed = 0;
42 seed ^= std::hash{}(p.first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
43 seed ^= std::hash{}(p.second) + 0x9e3779b9 + (seed<<6) + (seed>>2);
44 return seed;
45 }
46 };
47 };
*******************************************************************

296. Probability of a Two Boxes Having The Same


Number of Distinct Balls(Python)
*******************************************************************

1 # Time: O(k^3 * n^2)


2 # Space: O(k^2 * n)
3
4 import collections
5
6
7 class Solution(object):
8 def getProbability(self, balls):
9 """
10 :type balls: List[int]
11 :rtype: float
12 """
13 def nCrs(n): # Time: O(n), Space: O(1)
14 c = 1
15 for k in xrange(n+1):
16 yield c
17 c *= n-(k+1)+1
18 c //= k+1
19
20 def nCr(n, r): # Time: O(n), Space: O(1)
21 if n-r < r:
22 return nCr(n, n-r)
23 c = 1
24 for k in xrange(1, r+1):
25 c *= n-k+1
26 c //= k
27 return c
28
29 dp = collections.defaultdict(int)
30 dp[0, 0] = 1 # dp[i, j] is the number of ways with number difference i and color difference j
31 for n in balls: # O(k) times
32 new_dp = collections.defaultdict(int)
33 for (ndiff, cdiff), count in dp.iteritems(): # O(k^2 * n) times
34 for k, new_count in enumerate(nCrs(n)): # O(n) times
35 new_ndiff = ndiff+(k-(n-k))
36 new_cdiff = cdiff-1 if k == 0 else (cdiff+1 if k == n else cdiff)
37 new_dp[new_ndiff, new_cdiff] += count*new_count
38 dp = new_dp
39 total = sum(balls)
40 return float(dp[0, 0])/nCr(total, total//2)
***************

297. Paint House III


***************

There is a row of m houses in a small city, each house must be painted with one of then colors (labeled from 1 to n), some
houses that have been painted last summer should not be painted again.

A neighborhood is a maximal group of continuous houses that are painted with the same color.

For example: houses = [1,2,2,3,3,2,1,1] contains 5 neighborhoods [{1}, {2,2}, {3,3}, {2}, {1,1}].

Given an array houses, an m x n matrix cost and an integer target where:

houses[i]: is the color of the house i, and 0 if the house is not painted yet.
cost[i][j]: is the cost of paint the house i with the color j + 1 .

Return the minimum cost of painting all the remaining houses in such a way that there are exactlytarget neighborhoods. If it is
not possible, return -1.

Example 1:

Input: houses = [0,0,0,0,0], cost = [[1,10],[10,1],[10,1],[1,10],[5,1]], m = 5, n = 2, target = 3


Output: 9
Explanation: Paint houses of this way [1,2,2,1,1]
This array contains target = 3 neighborhoods, [{1}, {2,2}, {1,1}].
Cost of paint all houses (1 + 1 + 1 + 1 + 5) = 9.

Example 2:

Input: houses = [0,2,1,2,0], cost = [[1,10],[10,1],[10,1],[1,10],[5,1]], m = 5, n = 2, target = 3


Output: 11
Explanation: Some houses are already painted, Paint the houses of this way [2,2,1,2,2]
This array contains target = 3 neighborhoods, [{2,2}, {1}, {2,2}].
Cost of paint the first and last house (10 + 1) = 11.

Example 3:

Input: houses = [0,0,0,0,0], cost = [[1,10],[10,1],[1,10],[10,1],[1,10]], m = 5, n = 2, target = 5


Output: 5

Example 4:

Input: houses = [3,1,2,3], cost = [[1,1,1],[1,1,1],[1,1,1],[1,1,1]], m = 4, n = 3, target = 3


Output: -1
Explanation: Houses are already painted with a total of 4 neighborhoods [{3},{1},{2},{3}] different of target = 3.

Constraints:

m == houses.length == cost.length
n == cost[i].length
1 <= m <= 100
1 <= n <= 20
1 <= target <= m
0 <= houses[i] <= n
1 <= cost[i][j] <= 10^4
***************

297. Paint House III(C++)


***************

1 // Time: O(m * t * n^2)


2 // Space: O(t * n)
3
4 class Solution {
5 public:
6 int minCost(vector& houses, vector>& cost, int m, int n, int target) {
7 // dp[i][j][k]: i means the ith house, j means j neighbor groups, k means the kth color
8 vector>> dp(2,
9 vector>(target,
10 vector(n, numeric_limits::max())));
11 for (int i = 0; i < m; ++i) {
12 dp[i % 2] = vector>(target, vector(n, numeric_limits::max()));
13 for (int j = 0; j < min(target, i + 1); ++j) {
14 for (int k = 0; k < n; ++k) {
15 if (houses[i] && houses[i] - 1 != k) {
16 continue;
17 }
18 int same = 0;
19 if (i - 1 >= 0) {
20 same = dp[(i - 1) % 2][j][k];
21 }
22 int diff = 0;
23 if (i - 1 >= 0) {
24 diff = numeric_limits::max();
25 if (j - 1 >= 0) {
26 for (int nk = 0; nk < n; ++nk) {
27 if (nk == k) {
28 continue;
29 }
30 diff = min(diff, dp[(i - 1) % 2][j - 1][nk]);
31 }
32 }
33 }
34 dp[i % 2][j][k] = min(same, diff);
35 if (dp[i % 2][j][k] != numeric_limits::max() && !houses[i]) {
36 dp[i % 2][j][k] += cost[i][k];
37 }
38 }
39 }
40 }
41 int result = *min_element(begin(dp[(m - 1) % 2].back()), end(dp[(m - 1) % 2].back()));
42 return (result != numeric_limits::max()) ? result : -1;
43 }
44 };
45
46 // Time: O(m * t * n^2)
47 // Space: O(t * n)
48 class Solution2 {
49 public:
50 int minCost(vector& houses, vector>& cost, int m, int n, int target) {
51 const auto& hash = [&](int a, int b) {
52 return a * (n + 1) + b;
53 };
54 const auto& unhash = [&](int a_b) {
55 return pair(a_b / (n + 1), a_b % (n + 1));
56 };
57 unordered_map dp = {{hash(0, 0), 0}};
58 for (int i = 0; i < houses.size(); ++i) {
59 unordered_map new_dp;
60 int left = houses[i], right = houses[i];
61 if (!houses[i]) {
62 left = 1, right = n;
63 }
64 for (int nk = left; nk <= right; ++nk) {
65 for (const auto& [j_k, _] : dp) {
66 const auto& [j, k] = unhash(j_k);
67 int nj = j + int(k != nk);
68 if (nj > target) {
69 continue;
70 }
71 new_dp[hash(nj, nk)] = min(new_dp.count(hash(nj, nk)) ? new_dp[hash(nj, nk)]
72 : numeric_limits::max(),
73 dp[hash(j, k)] + ((nk != houses[i]) ? cost[i][nk - 1] : 0));
74 }
75 }
76 dp = move(new_dp);
77 }
78 int result = numeric_limits::max();
79 for (const auto& [j_k, v] : dp) {
80 if (unhash(j_k).first == target) {
81 result = min(result, v);
82 }
83 }
84 return (result != numeric_limits::max()) ? result : -1;
85 }
86 };
***************

297. Paint House III(Python)


***************

1 # Time: O(m * t * n^2)


2 # Space: O(t * n)
3
4 class Solution(object):
5 def minCost(self, houses, cost, m, n, target):
6 """
7 :type houses: List[int]
8 :type cost: List[List[int]]
9 :type m: int
10 :type n: int
11 :type target: int
12 :rtype: int
13 """
14 # dp[i][j][k]: cost of covering i+1 houses with j+1 neighbor groups and the (k+1)th color
15 dp = [[[float("inf") for _ in xrange(n)] for _ in xrange(target)] for _ in xrange(2)]
16 for i in xrange(m):
17 dp[i%2] = [[float("inf") for _ in xrange(n)] for _ in xrange(target)]
18 for j in xrange(min(target, i+1)):
19 for k in xrange(n):
20 if houses[i] and houses[i]-1 != k:
21 continue
22 same = dp[(i-1)%2][j][k] if i-1 >= 0 else 0
23 diff = (min([dp[(i-1)%2][j-1][nk] for nk in xrange(n) if nk != k] or [float("inf")]) if j-1 >= 0 else float
24 paint = cost[i][k] if not houses[i] else 0
25 dp[i%2][j][k] = min(same, diff)+paint
26 result = min(dp[(m-1)%2][-1])
27 return result if result != float("inf") else -1
28
29
30 # Time: O(m * t * n^2)
31 # Space: O(t * n)
32 class Solution2(object):
33 def minCost(self, houses, cost, m, n, target):
34 """
35 :type houses: List[int]
36 :type cost: List[List[int]]
37 :type m: int
38 :type n: int
39 :type target: int
40 :rtype: int
41 """
42 dp = {(0, 0): 0}
43 for i, p in enumerate(houses):
44 new_dp = {}
45 for nk in (xrange(1, n+1) if not p else [p]):
46 for j, k in dp:
47 nj = j + (k != nk)
48 if nj > target:
49 continue
50 new_dp[nj, nk] = min(new_dp.get((nj, nk), float("inf")), dp[j, k] + (cost[i][nk-1] if nk != p else 0))
51 dp = new_dp
52 return min([dp[j, k] for j, k in dp if j == target] or [-1])
******************

298. Allocate Mailboxes


******************

Given the array houses and an integer k . where houses[i] is the location of the ith house along a street, your task is to allocatek
mailboxes in the street.

Return the minimum total distance between each house and its nearest mailbox.

The answer is guaranteed to fit in a 32-bit signed integer.

Example 1:

Input: houses = [1,4,8,10,20], k = 3


Output: 5
Explanation: Allocate mailboxes in position 3, 9 and 20.
Minimum total distance from each houses to nearest mailboxes is |3-1| + |4-3| + |9-8| + |10-9| + |20-20| = 5

Example 2:

Input: houses = [2,3,5,12,18], k = 2


Output: 9
Explanation: Allocate mailboxes in position 3 and 14.
Minimum total distance from each houses to nearest mailboxes is |2-3| + |3-3| + |5-3| + |12-14| + |18-14| = 9.

Example 3:

Input: houses = [7,4,6,1], k = 1


Output: 8

Example 4:

Input: houses = [3,6,14,10], k = 4


Output: 0
Constraints:

n == houses.length
1 <= n <= 100
1 <= houses[i] <= 10^4
1 <= k <= n
Array houses contain unique integers.
******************

298. Allocate Mailboxes(C++)


******************

1 // Time: O(m * n^2)


2 // Space: O(n)
3
4 class Solution {
5 public:
6 int minDistance(vector& houses, int k) {
7 sort(begin(houses), end(houses));
8 vector prefix(houses.size() + 1);
9 for (int i = 0; i < houses.size(); ++i) {
10 prefix[i + 1] = prefix[i] + houses[i];
11 }
12 vector dp(houses.size());
13 for (int j = 0; j < houses.size(); ++j) {
14 dp[j] = cost(prefix, 0, j);
15 }
16 for (int m = 1; m < k; ++m) {
17 for (int j = houses.size() - 1; j >= 0; --j) {
18 for (int i = m; i <= j; ++i) {
19 dp[j] = min(dp[j], dp[i - 1] + cost(prefix, i, j));
20 }
21 }
22 }
23 return dp.back();
24 }
25
26 private:
27 int cost(const vector& prefix, int i, int j) {
28 return (prefix[j + 1] - prefix[(i + j + 1) / 2]) -
29 (prefix[(i + j) / 2 + 1] - prefix[i]);
30 }
31 };
******************

298. Allocate Mailboxes(Python)


******************

1 # Time: O(m * n^2)


2 # Space: O(n)
3
4 class Solution(object):
5 def minDistance(self, houses, k):
6 """
7 :type houses: List[int]
8 :type k: int
9 :rtype: int
10 """
11 def cost(prefix, i, j):
12 return (prefix[j+1]-prefix[(i+j+1)//2])-(prefix[(i+j)//2+1]-prefix[i])
13
14 houses.sort()
15 prefix = [0]*(len(houses)+1)
16 for i, h in enumerate(houses):
17 prefix[i+1] = prefix[i]+h
18 dp = [cost(prefix, 0, j) for j in xrange(len(houses))]
19 for m in xrange(1, k):
20 for j in reversed(xrange(m, len(houses))):
21 for i in xrange(m, j+1):
22 dp[j] = min(dp[j], dp[i-1]+cost(prefix, i, j))
23 return dp[-1]
************************

299. Sales by Day of the Week


************************

Table: Orders

+---------------+---------+
| Column Name | Type |
+---------------+---------+
| order_id | int |
| customer_id | int |
| order_date | date |
| item_id | varchar |
| quantity | int |
+---------------+---------+
(ordered_id, item_id) is the primary key for this table.
This table contains information of the orders placed.
order_date is the date when item_id was ordered by the customer with id customer_id.

Table: Items

+---------------------+---------+
| Column Name | Type |
+---------------------+---------+
| item_id | varchar |
| item_name | varchar |
| item_category | varchar |
+---------------------+---------+
item_id is the primary key for this table.
item_name is the name of the item.
item_category is the category of the item.

You are the business owner and would like to obtain a sales report for category items and day of the week.

Write an SQL query to report how many units in each category have been ordered on eachday of the week.

Return the result table ordered by category.

The query result format is in the following example:


Orders table:
+------------+--------------+-------------+--------------+-------------+
| order_id | customer_id | order_date | item_id | quantity |
+------------+--------------+-------------+--------------+-------------+
| 1 | 1 | 2020-06-01 | 1 | 10 |
| 2 | 1 | 2020-06-08 | 2 | 10 |
| 3 | 2 | 2020-06-02 | 1 | 5 |
| 4 | 3 | 2020-06-03 | 3 | 5 |
| 5 | 4 | 2020-06-04 | 4 | 1 |
| 6 | 4 | 2020-06-05 | 5 | 5 |
| 7 | 5 | 2020-06-05 | 1 | 10 |
| 8 | 5 | 2020-06-14 | 4 | 5 |
| 9 | 5 | 2020-06-21 | 3 | 5 |
+------------+--------------+-------------+--------------+-------------+

Items table:
+------------+----------------+---------------+
| item_id | item_name | item_category |
+------------+----------------+---------------+
| 1 | LC Alg. Book | Book |
| 2 | LC DB. Book | Book |
| 3 | LC SmarthPhone | Phone |
| 4 | LC Phone 2020 | Phone |
| 5 | LC SmartGlass | Glasses |
| 6 | LC T-Shirt XL | T-Shirt |
+------------+----------------+---------------+

Result table:
+------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
| Category | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday |
+------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
| Book | 20 | 5 | 0 | 0 | 10 | 0 | 0 |
| Glasses | 0 | 0 | 0 | 0 | 5 | 0 | 0 |
| Phone | 0 | 0 | 5 | 1 | 0 | 0 | 10 |
| T-Shirt | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
On Monday (2020-06-01, 2020-06-08) were sold a total of 20 units (10 + 10) in the category Book (ids: 1, 2).
On Tuesday (2020-06-02) were sold a total of 5 units in the category Book (ids: 1, 2).
On Wednesday (2020-06-03) were sold a total of 5 units in the category Phone (ids: 3, 4).
On Thursday (2020-06-04) were sold a total of 1 unit in the category Phone (ids: 3, 4).
On Friday (2020-06-05) were sold 10 units in the category Book (ids: 1, 2) and 5 units in Glasses (ids: 5).
On Saturday there are no items sold.
On Sunday (2020-06-14, 2020-06-21) were sold a total of 10 units (5 +5) in the category Phone (ids: 3, 4).
There are no sales of T-Shirt.
************************

299. Sales by Day of the Week(Shell)


************************

1 # Time: O(m + n)
2 # Space: O(n)
3
4 SELECT a.item_category AS 'CATEGORY',
5 sum(CASE
6 WHEN weekday(b.order_date) = 0 THEN b.quantity
7 ELSE 0
8 END) AS 'MONDAY',
9 sum(CASE
10 WHEN weekday(b.order_date) = 1 THEN b.quantity
11 ELSE 0
12 END) AS 'TUESDAY',
13 sum(CASE
14 WHEN weekday(b.order_date) = 2 THEN b.quantity
15 ELSE 0
16 END) AS 'WEDNESDAY',
17 sum(CASE
18 WHEN weekday(b.order_date) = 3 THEN b.quantity
19 ELSE 0
20 END) AS 'THURSDAY',
21 sum(CASE
22 WHEN weekday(b.order_date) = 4 THEN b.quantity
23 ELSE 0
24 END) AS 'FRIDAY',
25 sum(CASE
26 WHEN weekday(b.order_date) = 5 THEN b.quantity
27 ELSE 0
28 END) AS 'SATURDAY',
29 sum(CASE
30 WHEN weekday(b.order_date) = 6 THEN b.quantity
31 ELSE 0
32 END) AS 'SUNDAY'
33 FROM items a
34 LEFT JOIN orders b ON a.item_id = b.item_id
35 GROUP BY a.item_category
36 ORDER BY a.item_category;
***************************

300. Kth Ancestor of a Tree Node


***************************

You are given a tree with n nodes numbered from 0 to n - 1 in the form of a parent arrayparent where parent[i] is the parent of ith
node. The root of the tree is node 0. Find the k th ancestor of a given node.

The k th ancestor of a tree node is the k th node in the path from that node to the root node.

Implement the TreeAncestor class:

TreeAncestor(int n, int[] parent) Initializes the object with the number of nodes in the tree and the parent array.
int getKthAncestor(int node, int k) return the k th ancestor of the given node node. If there is no such ancestor, return -1.

Example 1:

Input
["TreeAncestor", "getKthAncestor", "getKthAncestor", "getKthAncestor"]
[[7, [-1, 0, 0, 1, 1, 2, 2]], [3, 1], [5, 2], [6, 3]]
Output
[null, 1, 0, -1]

Explanation
TreeAncestor treeAncestor = new TreeAncestor(7, [-1, 0, 0, 1, 1, 2, 2]);
treeAncestor.getKthAncestor(3, 1); // returns 1 which is the parent of 3
treeAncestor.getKthAncestor(5, 2); // returns 0 which is the grandparent of 5
treeAncestor.getKthAncestor(6, 3); // returns -1 because there is no such ancestor

Constraints:

1 <= k <= n <= 5 * 10 4


parent.length == n
parent[0] == -1
0 <= parent[i] < n for all 0 < i < n
0 <= node < n
There will be at most 5 * 104 queries.
***************************

300. Kth Ancestor of a Tree Node(C++)


***************************

1 // Time: ctor: O(n * logh)


2 // get: O(logh)
3 // Space: O(n * logh)
4
5 // binary jump solution (frequently used in competitive programming)
6 class TreeAncestor {
7 public:
8 TreeAncestor(int n, vector& parent) {
9 vector q;
10 for (const auto& p : parent) {
11 parent_.emplace_back(vector(p != -1, p));
12 if (p != -1) {
13 q.emplace_back(parent_.size() - 1);
14 }
15 }
16 for (int i = 0; !q.empty(); ++i) {
17 vector new_q;
18 for (const auto& curr : q) {
19 if (!(i < parent_[parent_[curr][i]].size())) {
20 continue;
21 }
22 parent_[curr].emplace_back(parent_[parent_[curr][i]][i]);
23 new_q.emplace_back(curr);
24 }
25 q = move(new_q);
26 }
27 }
28
29 int getKthAncestor(int node, int k) {
30 for (; k; k -= k & ~(k - 1)) {
31 int i = __builtin_ctz(k & ~(k - 1));
32 if (!(i < parent_[node].size())) {
33 return -1;
34 }
35 node = parent_[node][i];
36 }
37 return node;
38 }
39
40 private:
41 vector> parent_;
42 };
***************************

300. Kth Ancestor of a Tree Node(Python)


***************************

1 # Time: ctor: O(n * logh)


2 # get: O(logh)
3 # Space: O(n * logh)
4
5 # binary jump solution (frequently used in competitive programming)
6 # Template:
7 # https://github.com/kamyu104/FacebookHackerCup-2019/blob/master/Final%20Round/little_boat_on_the_sea.py
8 class TreeAncestor(object):
9
10 def __init__(self, n, parent):
11 """
12 :type n: int
13 :type parent: List[int]
14 """
15 par = [[p] if p != -1 else [] for p in parent]
16 q = [par[i] for i, p in enumerate(parent) if p != -1]
17 i = 0
18 while q:
19 new_q = []
20 for p in q:
21 if not (i < len(par[p[i]])):
22 continue
23 p.append(par[p[i]][i])
24 new_q.append(p)
25 q = new_q
26 i += 1
27 self.__parent = par
28
29 def getKthAncestor(self, node, k):
30 """
31 :type node: int
32 :type k: int
33 :rtype: int
34 """
35 par, i, pow_i_of_2 = self.__parent, 0, 1
36 while pow_i_of_2 <= k:
37 if k & pow_i_of_2:
38 if not (i < len(par[node])):
39 return -1
40 node = par[node][i]
41 i += 1
42 pow_i_of_2 *= 2
43 return node
****************************************************************

301. Find Critical and Pseudo-Critical Edges in Minimum


Spanning Tree
****************************************************************

Given a weighted undirected connected graph with n vertices numbered from 0 to n - 1, and an array edges where edges[i] = [a i,
bi, weight i] represents a bidirectional and weighted edge between nodes ai and bi. A minimum spanning tree (MST) is a subset
of the graph's edges that connects all vertices without cycles and with the minimum possible total edge weight.

Find all the critical and pseudo-critical edges in the given graph's minimum spanning tree (MST). An MST edge whose
deletion from the graph would cause the MST weight to increase is called a critical edge. On the other hand, a pseudo-
critical edge is that which can appear in some MSTs but not all.

Note that you can return the indices of the edges in any order.

Example 1:

Input: n = 5, edges = [[0,1,1],[1,2,1],[2,3,2],[0,3,2],[0,4,3],[3,4,3],[1,4,6]]


Output: [[0,1],[2,3,4,5]]
Explanation: The figure above describes the graph.
The following figure shows all the possible MSTs:

Notice that the two edges 0 and 1 appear in all MSTs, therefore they are critical edges, so we return them in the first list of the output.
The edges 2, 3, 4, and 5 are only part of some MSTs, therefore they are considered pseudo-critical edges. We add them to the second list of t

Example 2:
Input: n = 4, edges = [[0,1,1],[1,2,1],[2,3,1],[0,3,1]]
Output: [[],[0,1,2,3]]
Explanation: We can observe that since all 4 edges have equal weight, choosing any 3 edges from the given 4 will yield an MST. Therefore all

Constraints:

2 <= n <= 100


1 <= edges.length <= min(200, n * (n - 1) / 2)
edges[i].length == 3
0 <= ai < b i < n
1 <= weight i <= 1000
All pairs (a i, b i) are distinct.
****************************************************************

301. Find Critical and Pseudo-Critical Edges in Minimum


Spanning Tree(C++)
****************************************************************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 vector> findCriticalAndPseudoCriticalEdges(int n, vector>& edges) {
7 for (int i = 0; i < edges.size(); ++i) {
8 edges[i].push_back(i);
9 }
10 sort(begin(edges), end(edges),
11 [](const auto& a, const auto& b) {
12 return a[2] < b[2];
13 });
14 int mst = MST(n, edges);
15 vector> result(2);
16 for (int i = 0; i < edges.size(); ++i) {
17 if (mst < MST(n, edges, i)) {
18 result[0].emplace_back(edges[i][3]);
19 } else if (mst == MST(n, edges, -1, i)) {
20 result[1].emplace_back(edges[i][3]);
21 }
22 }
23 return result;
24 }
25
26 private:
27 int MST(const int n, const vector>& edges,
28 int unused = -1, int used = -1) {
29 UnionFind union_find(n);
30 int weight = 0;
31 if (used != -1) {
32 const auto& edge = edges[used];
33 if (union_find.union_set(edge[0], edge[1])) {
34 weight += edge[2];
35 }
36 }
37 for (int i = 0; i < edges.size(); ++i) {
38 if (i == unused) {
39 continue;
40 }
41 const auto& edge = edges[i];
42 if (union_find.union_set(edge[0], edge[1])) {
43 weight += edge[2];
44 }
45 }
46 return union_find.size() == 1 ? weight : numeric_limits::max();
47 }
48
49 class UnionFind {
50 public:
51 UnionFind(const int n) : set_(n), size_(n) {
52 iota(set_.begin(), set_.end(), 0);
53 }
54
55 int find_set(const int x) {
56 if (set_[x] != x) {
57 set_[x] = find_set(set_[x]); // Path compression.
58 }
59 return set_[x];
60 }
60
61
62 bool union_set(const int x, const int y) {
63 int x_root = find_set(x), y_root = find_set(y);
64 if (x_root == y_root) {
65 return false;
66 }
67 set_[min(x_root, y_root)] = max(x_root, y_root);
68 --size_;
69 return true;
70 }
71
72 int size() const {
73 return size_;
74 }
75
76 private:
77 vector set_;
78 int size_;
79 };
80 };
****************************************************************

301. Find Critical and Pseudo-Critical Edges in Minimum


Spanning Tree(Python)
****************************************************************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 class UnionFind(object):
5 def __init__(self, n):
6 self.set = range(n)
7 self.count = n
8
9 def find_set(self, x):
10 if self.set[x] != x:
11 self.set[x] = self.find_set(self.set[x]) # path compression.
12 return self.set[x]
13
14 def union_set(self, x, y):
15 x_root, y_root = map(self.find_set, (x, y))
16 if x_root == y_root:
17 return False
18 self.set[max(x_root, y_root)] = min(x_root, y_root)
19 self.count -= 1
20 return True
21
22
23 class Solution(object):
24 def findCriticalAndPseudoCriticalEdges(self, n, edges):
25 """
26 :type n: int
27 :type edges: List[List[int]]
28 :rtype: List[List[int]]
29 """
30 def MST(n, edges, unused=None, used=None):
31 union_find = UnionFind(n)
32 weight = 0
33 if used is not None:
34 u, v, w, _ = edges[used]
35 if union_find.union_set(u, v):
36 weight += w
37 for i, (u, v, w, _) in enumerate(edges):
38 if i == unused:
39 continue
40 if union_find.union_set(u, v):
41 weight += w
42 return weight if union_find.count == 1 else float("inf")
43
44 for i, edge in enumerate(edges):
45 edge.append(i)
46 edges.sort(key=lambda x: x[2])
47 mst = MST(n, edges)
48 result = [[], []]
49 for i, edge in enumerate(edges):
50 if mst < MST(n, edges, unused=i):
51 result[0].append(edge[3])
52 elif mst == MST(n, edges, used=i):
53 result[1].append(edge[3])
54 return result
*******************

302. Parallel Courses II


*******************

You are given an integer n, which indicates that there are n courses labeled from 1 to n. You are also given an arrayrelations
where relations[i] = [prevCourse i, nextCoursei], representing a prerequisite relationship between course prevCoursei and course
nextCoursei: course prevCoursei has to be taken before course nextCoursei. Also, you are given the integer k .

In one semester, you can take at most k courses as long as you have taken all the prerequisites in theprevious semester
for the courses you are taking.

Return the minimum number of semesters needed to take all courses. The testcases will be generated such that it is
possible to take every course.

Example 1:

Input: n = 4, dependencies = [[2,1],[3,1],[1,4]], k = 2


Output: 3
Explanation: The figure above represents the given graph.
In the first semester, you can take courses 2 and 3.
In the second semester, you can take course 1.
In the third semester, you can take course 4.

Example 2:

Input: n = 5, dependencies = [[2,1],[3,1],[4,1],[1,5]], k = 2


Output: 4
Explanation: The figure above represents the given graph.
In the first semester, you can take courses 2 and 3 only since you cannot take more than two per semester.
In the second semester, you can take course 4.
In the third semester, you can take course 1.
In the fourth semester, you can take course 5.

Example 3:
Input: n = 11, dependencies = [], k = 2
Output: 6

Constraints:

1 <= n <= 15
1 <= k <= n
0 <= relations.length <= n * (n-1) / 2
relations[i].length == 2
1 <= prevCoursei, nextCourse i <= n
prevCoursei != nextCoursei
All the pairs [prevCoursei, nextCoursei] are unique.
The given graph is a directed acyclic graph.
*******************

302. Parallel Courses II(C++)


*******************

1 // Time: O((n * C(c, min(c, k))) * 2^n)


2 // Space: O(2^n)
3
4 // concise dp solution
5 class Solution {
6 public:
7 int minNumberOfSemesters(int n, vector>& dependencies, int k) {
8 vector reqs(n);
9 for (const auto& d : dependencies) {
10 reqs[d[1] - 1] |= 1 << (d[0] - 1);
11 }
12 vector dp(1 << n, n);
13 dp[0] = 0;
14 for (int mask = 0; mask < dp.size(); ++mask) {
15 vector candidates;
16 for (int v = 0; v < n; ++v) {
17 if ((mask & (1 << v)) == 0 && (mask & reqs[v]) == reqs[v]) {
18 candidates.emplace_back(v);
19 }
20 }
21 const auto r = min(int(candidates.size()), k);
22 combinations(candidates.size(), min(int(candidates.size()), k),
23 [&dp, &mask, &candidates](const vector& idxs) {
24 auto new_mask = mask;
25 new_mask |= accumulate(cbegin(idxs), cend(idxs), 0,
26 [&candidates](const auto& a, const auto& b) {
27 return a | (1 << candidates[b]);
28 });
29 dp[new_mask] = min(dp[new_mask], dp[mask] + 1);
30 });
31 }
32 return dp.back();
33 }
34
35 private:
36 void combinations(int n, int k, const function&)>& callback) {
37 static const auto& next_pos =
38 [](const auto& n, const auto& k, const auto& idxs) {
39 int i = k - 1;
40 for (; i >= 0; --i) {
41 if (idxs[i] != i + n - k) {
42 break;
43 }
44 }
45 return i;
46 };
47
48 vector idxs(k);
49 iota(begin(idxs), end(idxs), 0);
50 callback(idxs);
51 for (int i; (i = next_pos(n, k, idxs)) >= 0;) {
52 ++idxs[i];
53 for (int j = i + 1; j < k; ++j) {
54 idxs[j] = idxs[j - 1] + 1;
55 }
56 callback(idxs);
57 }
58 }
59 };
60
61 // Time: O((n * C(c, min(c, k))) * 2^n)
62 // Space: O(2^n)
63 // embedded combination dp solution
64 class Solution2 {
65 public:
66 int minNumberOfSemesters(int n, vector>& dependencies, int k) {
67 static const auto& choice_mask =
68 [](const auto& nums, const auto& idxs) {
69 return accumulate(cbegin(idxs), cend(idxs), 0,
70 [&nums](const auto& a, const auto& b) {
71 return a | (1 << nums[b]);
72 });
73 };
74 static const auto& next_pos =
75 [](const auto& n, const auto& r, const auto& idxs) {
76 int i = r - 1;
77 for (; i >= 0; --i) {
78 if (idxs[i] != i + n - r) {
79 break;
80 }
81 }
82 return i;
83 };
84
85 vector reqs(n);
86 for (const auto& d : dependencies) {
87 reqs[d[1] - 1] |= 1 << (d[0] - 1);
88 }
89 vector dp(1 << n, n);
90 dp[0] = 0;
91 for (int mask = 0; mask < dp.size(); ++mask) {
92 vector candidates;
93 for (int v = 0; v < n; ++v) {
94 if ((mask & (1 << v)) == 0 && (mask & reqs[v]) == reqs[v]) {
95 candidates.emplace_back(v);
96 }
97 }
98 const auto r = min(int(candidates.size()), k);
99 vector idxs(r);
100 iota(begin(idxs), end(idxs), 0);
101 const auto& new_mask = (mask | choice_mask(candidates, idxs));
102 dp[new_mask] = min(dp[new_mask], dp[mask] + 1);
103 for (int i; (i = next_pos(candidates.size(), r, idxs)) >= 0;) {
104 ++idxs[i];
105 for (int j = i + 1; j < k; ++j) {
106 idxs[j] = idxs[j - 1] + 1;
107 }
108 const auto& new_mask = (mask | choice_mask(candidates, idxs));
109 dp[new_mask] = min(dp[new_mask], dp[mask] + 1);
110 }
111 }
112 return dp.back();
113 }
114 };
115
116 // Time: O(nlogn + e), e is the number of edges in graph
117 // Space: O(n + e)
118 // wrong greedy solution
119 // since the priority of courses are hard to decide especially for those courses with zero indegrees are of the same outdegrees and dept
120 // e.x.
121 // 9
122 // [[1,4],[1,5],[3,5],[3,6],[2,6],[2,7],[8,4],[8,5],[9,6],[9,7]]
123 // 3
124 class Solution_WA {
125 public:
126 int minNumberOfSemesters(int n, vector>& dependencies, int k) {
127 unordered_map> graph;
128 vector degrees(n);
129 for (const auto &d: dependencies) {
130 graph[d[0] - 1].emplace_back(d[1] - 1);
131 ++degrees[d[1] - 1];
132 }
133 vector depths(n, -1);
134 for (int i = 0; i < n; ++i) {
135 dfs(graph, i, &depths);
135 dfs(graph, i, &depths);
136 }
137 priority_queue> max_heap;
138 for (int i = 0; i < n; ++i) {
139 if (!degrees[i]) {
140 max_heap.emplace(depths[i], i);
141 }
142 }
143 int result = 0;
144 while (!max_heap.empty()) {
145 vector new_q;
146 for (int i = 0; !max_heap.empty() && i < k; ++i) {
147 const auto [depth, node] = max_heap.top(); max_heap.pop();
148 for (const auto& child : graph[node]) {
149 if (!--degrees[child]) {
150 new_q.emplace_back(child);
151 }
152 }
153 }
154 ++result;
155 for (const auto& node : new_q) {
156 max_heap.emplace(depths[node], node);
157 }
158 }
159 return result;
160 }
161
162 private:
163 int dfs(const unordered_map> &graph,
164 int i, vector *depths) {
165 if ((*depths)[i] == -1) {
166 int depth = 0;
167 if (graph.count(i)) {
168 for (const auto& child : graph.at(i)) {
169 depth = max(depth, dfs(graph, child, depths));
170 }
171 }
172 (*depths)[i] = depth + 1;
173 }
174 return (*depths)[i];
175 }
176 };
*******************

302. Parallel Courses II(Python)


*******************

1 # Time: O((n * C(c, min(c, k))) * 2^n)


2 # Space: O(2^n)
3
4 import itertools
5
6
7 class Solution(object):
8 def minNumberOfSemesters(self, n, dependencies, k):
9 """
10 :type n: int
11 :type dependencies: List[List[int]]
12 :type k: int
13 :rtype: int
14 """
15 reqs = [0]*n
16 for u, v in dependencies:
17 reqs[v-1] |= 1 << (u-1)
18 dp = [n]*(1<
*********************

303. Max Value of Equation


*********************

You are given an array points containing the coordinates of points on a 2D plane, sorted by the x-values, wherepoints[i] = [x i, y i]
such that x i < x j for all 1 <= i < j <= points.length . You are also given an integerk .

Return the maximum value of the equationy i + y j + |x i - x j| where |xi - x j| <= k and 1 <= i < j <= points.length .

It is guaranteed that there exists at least one pair of points that satisfy the constraint|xi - x j| <= k .

Example 1:

Input: points = [[1,3],[2,0],[5,10],[6,-10]], k = 1


Output: 4
Explanation: The first two points satisfy the condition |xi - xj| <= 1 and if we calculate the equation we get 3 + 0 + |1 - 2| = 4. Third and
No other pairs satisfy the condition, so we return the max of 4 and 1.

Example 2:

Input: points = [[0,0],[3,0],[9,2]], k = 3


Output: 3
Explanation: Only the first two points have an absolute difference of 3 or less in the x-values, and give the value of 0 + 0 + |0 - 3| = 3.

Constraints:

2 <= points.length <= 10 5


points[i].length == 2
-108 <= x i, y i <= 108
0 <= k <= 2 * 10 8
x i < x j for all 1 <= i < j <= points.length
xi form a strictly increasing sequence.
*********************

303. Max Value of Equation(C++)


*********************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int findMaxValueOfEquation(vector>& points, int k) {
7 int result = numeric_limits::min();
8 deque dq;
9 for (int i = 0; i < points.size(); ++i) {
10 const auto& x = points[i][0], &y = points[i][1];
11 while(!dq.empty() && points[dq.front()][0] < x - k) {
12 dq.pop_front();
13 }
14 if (!dq.empty()) {
15 result = max(result, points[dq.front()][1] - points[dq.front()][0] + y + x);
16 }
17 while(!dq.empty() && points[dq.back()][1] - points[dq.back()][0] <= y - x) {
18 dq.pop_back();
19 }
20 dq.emplace_back(i);
21 }
22 return result;
23 }
24 };
*********************

303. Max Value of Equation(Python)


*********************

1 # Time: O(n)
2 # Space: O(n)
3
4 import collections
5
6
7 class Solution(object):
8 def findMaxValueOfEquation(self, points, k):
9 """
10 :type points: List[List[int]]
11 :type k: int
12 :rtype: int
13 """
14 result = float("-inf")
15 dq = collections.deque()
16 for i, (x, y) in enumerate(points):
17 while dq and points[dq[0]][0] < x-k:
18 dq.popleft()
19 if dq:
20 result = max(result, (points[dq[0]][1]-points[dq[0]][0])+y+x)
21 while dq and points[dq[-1]][1]-points[dq[-1]][0] <= y-x:
22 dq.pop()
23 dq.append(i)
24 return result
*****************************************************************

304. Minimum Possible Integer After at Most K Adjacent


Swaps On Digits
*****************************************************************

Given a string num representing the digits of a very large integer and an integer k .

You are allowed to swap any two adjacent digits of the integerat most k times.

Return the minimum integer you can obtain also as a string.

Example 1:

Input: num = "4321", k = 4


Output: "1342"
Explanation: The steps to obtain the minimum integer from 4321 with 4 adjacent swaps are shown.

Example 2:

Input: num = "100", k = 1


Output: "010"
Explanation: It's ok for the output to have leading zeros, but the input is guaranteed not to have any leading zeros.

Example 3:

Input: num = "36789", k = 1000


Output: "36789"
Explanation: We can keep the number without any swaps.

Example 4:

Input: num = "22", k = 22


Output: "22"

Example 5:

Input: num = "9438957234785635408", k = 23


Output: "0345989723478563548"

Constraints:

1 <= num.length <= 30000


num contains digits only and doesn't have leading zeros.
1 <= k <= 10^9
*****************************************************************

304. Minimum Possible Integer After at Most K Adjacent


Swaps On Digits(C++)
*****************************************************************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 class BIT { // Fenwick Tree, 1-indexed
5 public:
6 BIT(int n) : bit_(n) {
7
8 }
9
10 void add(int i, int val) {
11 for (; i < bit_.size(); i += lower_bit(i)) {
12 bit_[i] += val;
13 }
14 }
15
16 int sum(int i) {
17 int sum = 0;
18 for (; i > 0; i -= lower_bit(i)) {
19 sum += bit_[i];
20 }
21 return sum;
22 }
23
24 inline int lower_bit(int i) {
25 return i & -i;
26 }
27
28 private:
29 vector bit_;
30 };
31
32 class Solution {
33 public:
34 string minInteger(string num, int k) {
35 unordered_map> lookup;
36 BIT bit(num.length() + 1);
37 for (int i = num.length() - 1; i >= 0; --i) {
38 lookup[num[i] - '0'].emplace_back(i + 1);
39 bit.add(i + 1, 1);
40 }
41 string result;
42 for (int i = 0; i < num.length(); ++i) {
43 for (int d = 0; d <= 9; ++d) {
44 if (!lookup[d].empty() && bit.sum(lookup[d].back() - 1) <= k) {
45 k -= bit.sum(lookup[d].back() - 1);
46 bit.add(lookup[d].back(), -1);
47 lookup[d].pop_back();
48 result.push_back('0' + d);
49 break;
50 }
51 }
52 }
53 return result;
54 }
55 };
*****************************************************************

304. Minimum Possible Integer After at Most K Adjacent


Swaps On Digits(Python)
*****************************************************************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 import collections
5
6
7 class BIT(object): # Fenwick Tree, 1-indexed
8 def __init__(self, n):
9 self.__bit = [0] * n
10
11 def add(self, i, val):
12 while i < len(self.__bit):
13 self.__bit[i] += val
14 i += (i & -i)
15
16 def sum(self, i):
17 result = 0
18 while i > 0:
19 result += self.__bit[i]
20 i -= (i & -i)
21 return result
22
23
24 class Solution(object):
25 def minInteger(self, num, k):
26 """
27 :type num: str
28 :type k: int
29 :rtype: str
30 """
31 lookup = collections.defaultdict(list)
32 bit = BIT(len(num)+1)
33 for i in reversed(xrange(len(num))):
34 bit.add(i+1, 1)
35 lookup[int(num[i])].append(i+1)
36 result = []
37 for _ in xrange(len(num)):
38 for d in xrange(10):
39 if lookup[d] and bit.sum(lookup[d][-1]-1) <= k:
40 k -= bit.sum(lookup[d][-1]-1)
41 bit.add(lookup[d].pop(), -1)
42 result.append(d)
43 break
44 return "".join(map(str, result))
*************

305. Stone Game IV


*************

Alice and Bob take turns playing a game, with Alice starting first.

Initially, there are n stones in a pile. On each player's turn, that player makes amove consisting of removing any non-zero
square number of stones in the pile.

Also, if a player cannot make a move, he/she loses the game.

Given a positive integer n. Return True if and only if Alice wins the game otherwise returnFalse, assuming both players play
optimally.

Example 1:

Input: n = 1
Output: true
Explanation: Alice can remove 1 stone winning the game because Bob doesn't have any moves.

Example 2:

Input: n = 2
Output: false
Explanation: Alice can only remove 1 stone, after that Bob removes the last one winning the game (2 -> 1 -> 0).

Example 3:

Input: n = 4
Output: true
Explanation: n is already a perfect square, Alice can win with one move, removing 4 stones (4 -> 0).

Example 4:

Input: n = 7
Output: false
Explanation: Alice can't win the game if Bob plays optimally.
If Alice starts removing 4 stones, Bob will remove 1 stone then Alice should remove only 1 stone and finally Bob removes the last one (7 -> 3
If Alice starts removing 1 stone, Bob will remove 4 stones then Alice only can remove 1 stone and finally Bob removes the last one (7 -> 6 ->

Example 5:

Input: n = 17
Output: false
Explanation: Alice can't win the game if Bob plays optimally.

Constraints:

1 <= n <= 10^5


*************

305. Stone Game IV(C++)


*************

1 // Time: O(n * sqrt(n))


2 // Space: O(n)
3
4 class Solution {
5 public:
6 bool winnerSquareGame(int n) {
7 vector dp(n + 1);
8 for (int i = 1; i <= n; ++i) {
9 for (int j = 1; j * j <= i; ++j) {
10 if (!dp[i - j * j]) {
11 dp[i] = true;
12 break;
13 }
14 }
15 }
16 return dp.back();
17 }
18 };
*************

305. Stone Game IV(Python)


*************

1 # Time: O(n * sqrt(n))


2 # Space: O(n)
3
4 class Solution(object):
5 def winnerSquareGame(self, n):
6 """
7 :type n: int
8 :rtype: bool
9 """
10 dp = [False]*(n+1)
11 for i in xrange(1, n+1):
12 j = 1
13 while j*j <= i:
14 if not dp[i-j*j]:
15 dp[i] = True
16 break
17 j += 1
18 return dp[-1]
**********************************

306. Best Position for a Service Centre


**********************************

A delivery company wants to build a new service centre in a new city. The company knows the positions of all the customers
in this city on a 2D-Map and wants to build the new centre in a position such that the sum of the euclidean distances to all
customers is minimum.

Given an array positions where positions[i] = [x i, y i] is the position of the ith customer on the map, return the minimum sum of the
euclidean distances to all customers.

In other words, you need to choose the position of the service centre[xcentre , y centre ] such that the following formula is
minimized:

Answers within 10^-5 of the actual value will be accepted.

Example 1:

Input: positions = [[0,1],[1,0],[1,2],[2,1]]


Output: 4.00000
Explanation: As shown, you can see that choosing [xcentre, ycentre] = [1, 1] will make the distance to each customer = 1, the sum of all dist

Example 2:
Input: positions = [[1,1],[3,3]]
Output: 2.82843
Explanation: The minimum possible sum of distances = sqrt(2) + sqrt(2) = 2.82843

Example 3:

Input: positions = [[1,1]]


Output: 0.00000

Example 4:

Input: positions = [[1,1],[0,0],[2,0]]


Output: 2.73205
Explanation: At the first glance, you may think that locating the centre at [1, 0] will achieve the minimum sum, but locating it at [1, 0] wi
Try to locate the centre at [1.0, 0.5773502711] you will see that the sum of distances is 2.73205.
Be careful with the precision!

Example 5:

Input: positions = [[0,1],[3,2],[4,5],[7,6],[8,9],[11,1],[2,12]]


Output: 32.94036
Explanation: You can use [4.3460852395, 4.9813795505] as the position of the centre.

Constraints:

1 <= positions.length <= 50


positions[i].length == 2
0 <= positions[i][0], positions[i][1] <= 100
**********************************

306. Best Position for a Service Centre(C++)


**********************************

1 // Time: O(n * iter), iter is the number of iterations


2 // Space: O(1)
3
4 // see reference:
5 // - https://en.wikipedia.org/wiki/Geometric_median
6 // - https://wikimedia.org/api/rest_v1/media/math/render/svg/b3fb215363358f12687100710caff0e86cd9d26b
7 // Weiszfeld's algorithm
8 class Solution {
9 public:
10 double getMinDistSum(vector>& positions) {
11 static const double EPS = 1e-6;
12 pair median;
13 median.first = (accumulate(cbegin(positions), cend(positions), 0.0,
14 [](const auto& a, const auto& b) {
15 return a + b[0];
16 }) / positions.size());
17 median.second = (accumulate(cbegin(positions), cend(positions), 0.0,
18 [](const auto& a, const auto& b) {
19 return a + b[1];
20 }) / positions.size());
21 pair prev_median = {-1.0, -1.0};
22 while (prev_median.first < 0 || norm(median, prev_median) * positions.size() > EPS) {
23 const auto& [stopped, new_median] = geometry_median(positions, median);
24 if (stopped) {
25 break;
26 }
27 prev_median = median;
28 median = new_median;
29 }
30 return accumulate(cbegin(positions), cend(positions), 0.0,
31 [this, &median](const auto& a, const auto& b) {
32 return a + norm(median, pair(b[0], b[1]));
33 });
34 }
35
36 private:
37 double norm(const pair& p1,
38 const pair& p2) {
39 return sqrt((p1.first - p2.first) * (p1.first - p2.first) +
40 (p1.second - p2.second) * (p1.second - p2.second));
41 }
42
43 pair> geometry_median(
44 const vector>& positions,
45 const pair& median) {
46 pair numerator = {0.0, 0.0};
47 double denominator = 0.0;
48 for (const auto& p : positions) {
49 const auto& l = norm(median, pair(p[0], p[1]));
50 if (!l) {
51 continue;
52 }
53 numerator.first += p[0] / l;
54 numerator.second += p[1] / l;
55 denominator += 1 / l;
56 }
57 if (denominator == 0.0) {
58 return {true, {0.0, 0.0}};
59 }
60 return {false, {numerator.first / denominator, numerator.second / denominator}};
61 }
62 };
63
64 // Time: O(n * iter), iter is the number of iterations
65 // Space: O(1)
66 class Solution2 {
67 public:
68 double getMinDistSum(vector>& positions) {
69 static const double EPS = 1e-6;
70 static const vector> DIRECTIONS = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
71 pair median;
72 median.first = (accumulate(cbegin(positions), cend(positions), 0.0,
73 [](const auto& a, const auto& b) {
74 return a + b[0];
75 }) / positions.size());
76 median.second = (accumulate(cbegin(positions), cend(positions), 0.0,
77 [](const auto& a, const auto& b) {
78 return a + b[1];
79 }) / positions.size());
80 double result = dist(positions, median);
81 double delta = max((*max_element(cbegin(positions), cend(positions),
82 [](const auto& x, const auto& y) { return x[0] < y[0]; }))[0],
83 (*max_element(cbegin(positions), cend(positions),
84 [](const auto& x, const auto& y) { return x[1] < y[1]; }))[1]) -
85 min((*min_element(cbegin(positions), cend(positions),
86 [](const auto& x, const auto& y) { return x[0] < y[0]; }))[0],
87 (*min_element(cbegin(positions), cend(positions),
88 [](const auto& x, const auto& y) { return x[1] < y[1]; }))[1]);
89 while (delta > EPS) {
90 bool found = false;
91 for (const auto& [dx, dy] : DIRECTIONS) {
92 pair new_median = {median.first + delta * dx, median.second + delta * dy};
93 const auto& nd = dist(positions, new_median);
94 if (nd < result) {
95 result = nd;
96 median = new_median;
97 found = true;
98 break;
99 }
100 }
101 if (!found) {
102 delta /= 2.0;
103 }
104 }
105 return result ;
106 }
107
108 private:
109 double dist(const vector>& positions,
110 const pair& p) {
111 return accumulate(cbegin(positions), cend(positions), 0.0,
112 [&p](const auto& a, const auto& b) {
113 return a + sqrt((p.first - b[0]) * (p.first - b[0]) +
114 (p.second - b[1]) * (p.second - b[1]));
115 });
116 }
117 };
**********************************

306. Best Position for a Service Centre(Python)


**********************************

1 # Time: O(n * iter), iter is the number of iterations


2 # Space: O(1)
3
4 # see reference:
5 # - https://en.wikipedia.org/wiki/Geometric_median
6 # - https://wikimedia.org/api/rest_v1/media/math/render/svg/b3fb215363358f12687100710caff0e86cd9d26b
7 # Weiszfeld's algorithm
8 class Solution(object):
9 def getMinDistSum(self, positions):
10 """
11 :type positions: List[List[int]]
12 :rtype: float
13 """
14 EPS = 1e-6
15 def norm(p1, p2):
16 return ((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)**0.5
17
18 def geometry_median(positions, median):
19 numerator, denominator = [0.0, 0.0], 0.0
20 for p in positions:
21 l = norm(median, p)
22 if not l:
23 continue
24 numerator[0] += p[0]/l
25 numerator[1] += p[1]/l
26 denominator += 1/l
27 if denominator == 0.0:
28 return True, None
29 return False, [numerator[0]/denominator, numerator[1]/denominator]
30
31 median = [float(sum(p[0] for p in positions))/len(positions),
32 float(sum(p[1] for p in positions))/len(positions)]
33 prev_median = [float("-inf"), float("-inf")]
34 while norm(median, prev_median)*len(positions) > EPS:
35 stopped, new_median = geometry_median(positions, median)
36 if stopped:
37 break
38 median, prev_median = new_median, median
39 return sum(norm(median, p) for p in positions)
40
41
42 # Time: O(n * iter), iter is the number of iterations
43 # Space: O(1)
44 class Solution2(object):
45 def getMinDistSum(self, positions):
46 """
47 :type positions: List[List[int]]
48 :rtype: float
49 """
50 DIRECTIONS = [(0, 1), (1, 0), (0, -1), (-1, 0)]
51 EPS = 1e-6
52 def dist(positions, p):
53 return sum(((p[0]-x)**2 + (p[1]-y)**2)**0.5 for x, y in positions)
54
55 median = [0.0, 0.0]
56 median[0] = float(sum(x for x, _ in positions))/len(positions)
57 median[1] = float(sum(y for _, y in positions))/len(positions)
58 result = dist(positions, median)
59 delta = float(max(max(positions, key=lambda x: x[0])[0],
60 max(positions, key=lambda x: x[1])[1])) - \
61 float(min(min(positions, key=lambda x: x[0])[0],
62 min(positions, key=lambda x: x[1])[1]))
63 while delta > EPS:
64 for dx, dy in DIRECTIONS:
65 new_median = [median[0] + delta*dx, median[1] + delta*dy]
66 nd = dist(positions, new_median)
67 if nd < result:
68 result = nd
69 median = new_median
70 break
71 else:
72 delta /= 2.0
73 return result
***************************

307. Move Sub-Tree of N-Ary Tree


***************************

Given the root of an N-ary tree of unique values, and two nodes of the tree p and q.

You should move the subtree of the nodep to become a direct child of node q. If p is already a direct child of q, don't change
anything. Node p must be the last child in the children list of nodeq.

Return the root of the tree after adjusting it.

There are 3 cases for nodes p and q:

1. Node q is in the sub-tree of node p.


2. Node p is in the sub-tree of node q.
3. Neither node p is in the sub-tree of node q nor node q is in the sub-tree of node p.

In cases 2 and 3, you just need to move p (with its sub-tree) to be a child of q, but in case 1 the tree may be disconnected,
thus you need to reconnect the tree again. Please read the examples carefully before solving this problem.

Nary-Tree input serialization is represented in their level order traversal, each group of children is separated by the null
value (See examples).

For example, the above tree is serialized as [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14].

Example 1:

Input: root = [1,null,2,3,null,4,5,null,6,null,7,8], p = 4, q = 1


Output: [1,null,2,3,4,null,5,null,6,null,7,8]
Explanation: This example follows the second case as node p is in the sub-tree of node q. We move node p with its sub-tree to be a direct chi
Notice that node 4 is the last child of node 1.
Example 2:

Input: root = [1,null,2,3,null,4,5,null,6,null,7,8], p = 7, q = 4


Output: [1,null,2,3,null,4,5,null,6,null,7,8]
Explanation: Node 7 is already a direct child of node 4. We don't change anything.

Example 3:

Input: root = [1,null,2,3,null,4,5,null,6,null,7,8], p = 3, q = 8


Output: [1,null,2,null,4,5,null,7,8,null,null,null,3,null,6]
Explanation: This example follows case 3 because node p is not in the sub-tree of node q and vice-versa. We can move node 3 with its sub-tree

Example 4:
Input: root = [1,null,2,3,null,4,5,null,6,null,7,8], p = 2, q = 7
Output: [1,null,7,3,null,2,null,6,null,4,5,null,null,8]
Explanation: Node q is in the sub-tree of node p, so this is case 1.
The first step, we move node p (with all of its sub-tree except for node q) and add it as a child to node q.
Then we will see that the tree is disconnected, you need to reconnect node q to replace node p as shown.

Example 5:

Input: root = [1,null,2,3,null,4,5,null,6,null,7,8], p = 1, q = 2


Output: [2,null,4,5,1,null,7,8,null,null,3,null,null,null,6]
Explanation: Node q is in the sub-tree of node p, so this is case 1.
The first step, we move node p (with all of its sub-tree except for node q) and add it as a child to node q.
As node p was the root of the tree, node q replaces it and becomes the root of the tree.

Constraints:

The total number of nodes is between [2, 1000].


Each node has a unique value.
p != null
q != null
p and q are two different nodes (i.e. p != q).
***************************

307. Move Sub-Tree of N-Ary Tree(C++)


***************************

1 // Time: O(n)
2 // Space: O(h)
3
4 /*
5 // Definition for a Node.
6 class Node {
7 public:
8 int val;
9 vector children;
10
11 Node() {}
12
13 Node(int _val) {
14 val = _val;
15 }
16
17 Node(int _val, vector _children) {
18 val = _val;
19 children = _children;
20 }
21 };
22 */
23
24 // one pass solution without recursion
25 class Solution {
26 public:
27 Node* moveSubTree(Node* root, Node* p, Node* q) {
28 unordered_map lookup;
29 const auto& is_ancestor = iter_find_parents(root, nullptr, p, q, false, &lookup);
30 if (lookup.count(p) && lookup[p] == q) {
31 return root;
32 }
33 q->children.emplace_back(p);
34 if (!is_ancestor) {
35 lookup[p]->children.erase(find(begin(lookup[p]->children), end(lookup[p]->children), p));
36 } else {
37 lookup[q]->children.erase(find(begin(lookup[q]->children), end(lookup[q]->children), q));
38 if (p == root) {
39 root = q;
40 } else {
41 *find(begin(lookup[p]->children), end(lookup[p]->children), p) = q;
42 }
43 }
44 return root;
45 }
46
47 private:
48 bool iter_find_parents(Node *node, Node *parent, Node *p, Node *q,
49 bool is_ancestor,
50 unordered_map *lookup) {
51 vector> stk = {tuple(1, node, parent, is_ancestor, -1)};
52 while (!stk.empty()) {
53 const auto [step, node, parent, is_ancestor, i] = stk.back(); stk.pop_back();
54 if (step == 1) {
55 if (node == p || node == q) {
56 (*lookup)[node] = parent;
57 if (lookup->size() == 2) {
58 return is_ancestor;
59 }
60 }
61 stk.emplace_back(2, node, parent, is_ancestor, node->children.size() - 1);
62 } else {
63 if (i < 0) {
64 continue;
65 }
66 stk.emplace_back(2, node, parent, is_ancestor, i - 1);
67 stk.emplace_back(1, node->children[i], node, is_ancestor || node == p, -1);
68 }
69 }
70 assert(false);
71 return false;
72 }
73 };
74
75 // Time: O(n)
76 // Space: O(h)
77 // one pass solution with recursion
78 class Solution_Recu {
79 public:
80 Node* moveSubTree(Node* root, Node* p, Node* q) {
81 unordered_map lookup;
82 const auto& [_, is_ancestor] = find_parents(root, nullptr, p, q, false, &lookup);
83 if (lookup.count(p) && lookup[p] == q) {
84 return root;
85 }
86 q->children.emplace_back(p);
87 if (!is_ancestor) {
88 lookup[p]->children.erase(find(begin(lookup[p]->children), end(lookup[p]->children), p));
89 } else {
90 lookup[q]->children.erase(find(begin(lookup[q]->children), end(lookup[q]->children), q));
91 if (p == root) {
92 root = q;
93 } else {
94 *find(begin(lookup[p]->children), end(lookup[p]->children), p) = q;
95 }
96 }
97 return root;
98 }
99
100 private:
101 pair find_parents(Node *node, Node *parent, Node *p, Node *q,
102 bool is_ancestor,
103 unordered_map *lookup) {
104 if (node == p || node == q) {
105 (*lookup)[node] = parent;
106 if (lookup->size() == 2) {
107 return {true, is_ancestor};
108 }
109 }
110 for (const auto& child : node->children) {
111 const auto& [found, result] = find_parents(child, node, p, q, is_ancestor || node == p, lookup);
112 if (found) {
113 return {true, result};
114 }
115 }
116 return {false, false};
117 }
118 };
119
120 // Time: O(n)
121 // Space: O(h)
122 // two pass solution without recursion
123 class Solution2 {
124 public:
125 Node* moveSubTree(Node* root, Node* p, Node* q) {
126 unordered_map lookup;
127 iter_find_parents(root, nullptr, p, q, &lookup);
128 if (lookup.count(p) && lookup[p] == q) {
129 return root;
130 }
131 q->children.emplace_back(p);
132 if (!iter_is_ancestor(p, q)) {
133 lookup[p]->children.erase(find(begin(lookup[p]->children), end(lookup[p]->children), p));
134 } else {
135 lookup[q]->children.erase(find(begin(lookup[q]->children), end(lookup[q]->children), q));
135 lookup[q]->children.erase(find(begin(lookup[q]->children), end(lookup[q]->children), q));
136 if (p == root) {
137 root = q;
138 } else {
139 *find(begin(lookup[p]->children), end(lookup[p]->children), p) = q;
140 }
141 }
142 return root;
143 }
144
145 private:
146 void iter_find_parents(Node *node, Node *parent, Node *p, Node *q,
147 unordered_map *lookup) {
148 vector> stk = {tuple(1, node, parent, -1)};
149 while (!stk.empty()) {
150 const auto [step, node, parent, i] = stk.back(); stk.pop_back();
151 if (step == 1) {
152 if (node == p || node == q) {
153 (*lookup)[node] = parent;
154 if (lookup->size() == 2) {
155 return;
156 }
157 }
158 stk.emplace_back(2, node, parent, node->children.size() - 1);
159 } else {
160 if (i < 0) {
161 continue;
162 }
163 stk.emplace_back(2, node, parent, i - 1);
164 stk.emplace_back(1, node->children[i], node, -1);
165 }
166 }
167 }
168
169 bool iter_is_ancestor(Node *node, Node *q) {
170 vector> stk = {tuple(1, node, -1)};
171 while (!stk.empty()) {
172 const auto [step, node, i] = stk.back(); stk.pop_back();
173 if (step == 1) {
174 stk.emplace_back(2, node, node->children.size() - 1);
175 } else {
176 if (i < 0) {
177 continue;
178 }
179 if (node->children[i] == q) {
180 return true;
181 }
182 stk.emplace_back(2, node, i - 1);
183 stk.emplace_back(1, node->children[i], -1);
184 }
185 }
186 return false;
187 }
188 };
189
190 // Time: O(n)
191 // Space: O(h)
192 // two pass solution with recursion
193 class Solution2_Recu {
194 public:
195 Node* moveSubTree(Node* root, Node* p, Node* q) {
196 unordered_map lookup;
197 find_parents(root, nullptr, p, q, &lookup);
198 if (lookup.count(p) && lookup[p] == q) {
199 return root;
200 }
201 q->children.emplace_back(p);
202 if (!is_ancestor(p, q)) {
203 lookup[p]->children.erase(find(begin(lookup[p]->children), end(lookup[p]->children), p));
204 } else {
205 lookup[q]->children.erase(find(begin(lookup[q]->children), end(lookup[q]->children), q));
206 if (p == root) {
207 root = q;
208 } else {
208 } else {
209 *find(begin(lookup[p]->children), end(lookup[p]->children), p) = q;
210 }
211 }
212 return root;
213 }
214
215 private:
216 bool find_parents(Node *node, Node *parent, Node *p, Node *q, unordered_map *lookup) {
217 if (node == p || node == q) {
218 (*lookup)[node] = parent;
219 if (lookup->size() == 2) {
220 return true;
221 }
222 }
223 for (const auto& child : node->children) {
224 if (find_parents(child, node, p, q, lookup)) {
225 return true;
226 }
227 }
228 return false;
229 }
230
231 bool is_ancestor(Node *node, Node *q) {
232 for (const auto& child : node->children) {
233 if (child == q || is_ancestor(child, q)) {
234 return true;
235 }
236 }
237 return false;
238 }
239 };
***************************

307. Move Sub-Tree of N-Ary Tree(Python)


***************************

1 # Time: O(n)
2 # Space: O(h)
3
4 # Definition for a Node.
5 class Node(object):
6 def __init__(self, val=None, children=None):
7 self.val = val
8 self.children = children if children is not None else []
9
10
11 # one pass solution without recursion
12 class Solution(object):
13 def moveSubTree(self, root, p, q):
14 """
15 :type root: Node
16 :type p: Node
17 :type q: Node
18 :rtype: Node
19 """
20 def iter_find_parents(node, parent, p, q, is_ancestor, lookup):
21 stk = [(1, [node, None, False])]
22 while stk:
23 step, params = stk.pop()
24 if step == 1:
25 node, parent, is_ancestor = params
26 if node in (p, q):
27 lookup[node] = parent
28 if len(lookup) == 2:
29 return is_ancestor
30 stk.append((2, [node, is_ancestor, reversed(node.children)]))
31 else:
32 node, is_ancestor, it = params
33 child = next(it, None)
34 if not child:
35 continue
36 stk.append((2, [node, is_ancestor, it]))
37 stk.append((1, [child, node, is_ancestor or node == p]))
38 assert(False)
39 return False
40
41 lookup = {}
42 is_ancestor = iter_find_parents(root, None, p, q, False, lookup)
43 if p in lookup and lookup[p] == q:
44 return root
45 q.children.append(p)
46 if not is_ancestor:
47 lookup[p].children.remove(p)
48 else:
49 lookup[q].children.remove(q)
50 if p == root:
51 root = q
52 else:
53 lookup[p].children[lookup[p].children.index(p)] = q
54 return root
55
56
57 # Time: O(n)
58 # Space: O(h)
59 # one pass solution with recursion (bad in deep tree)
60 class Solution_Recu(object):
61 def moveSubTree(self, root, p, q):
62 """
63 :type root: Node
64 :type p: Node
65 :type q: Node
66 :rtype: Node
67 """
68 def find_parents(node, parent, p, q, is_ancestor, lookup):
69 if node in (p, q):
70 lookup[node] = parent
71 if len(lookup) == 2:
72 return True, is_ancestor
73 for child in node.children:
74 found, new_is_ancestor = find_parents(child, node, p, q, is_ancestor or node == p, lookup)
75 if found:
76 return True, new_is_ancestor
77 return False, False
78
79 lookup = {}
80 is_ancestor = find_parents(root, None, p, q, False, lookup)[1]
81 if p in lookup and lookup[p] == q:
82 return root
83 q.children.append(p)
84 if not is_ancestor:
85 lookup[p].children.remove(p)
86 else:
87 lookup[q].children.remove(q)
88 if p == root:
89 root = q
90 else:
91 lookup[p].children[lookup[p].children.index(p)] = q
92 return root
93
94
95 # Time: O(n)
96 # Space: O(h)
97 # two pass solution without recursion
98 class Solution2(object):
99 def moveSubTree(self, root, p, q):
100 """
101 :type root: Node
102 :type p: Node
103 :type q: Node
104 :rtype: Node
105 """
106 def iter_find_parents(node, parent, p, q, lookup):
107 stk = [(1, [node, None])]
108 while stk:
109 step, params = stk.pop()
110 if step == 1:
111 node, parent = params
112 if node in (p, q):
113 lookup[node] = parent
114 if len(lookup) == 2:
115 return
116 stk.append((2, [node, reversed(node.children)]))
117 else:
118 node, it = params
119 child = next(it, None)
120 if not child:
121 continue
122 stk.append((2, [node, it]))
123 stk.append((1, [child, node]))
124
125 def iter_is_ancestor(node, q):
126 stk = [(1, [node])]
127 while stk:
128 step, params = stk.pop()
129 if step == 1:
130 node = params[0]
131 stk.append((2, [reversed(node.children)]))
132 else:
133 it = params[0]
134 child = next(it, None)
135 if not child:
135 if not child:
136 continue
137 if child == q:
138 return True
139 stk.append((2, [it]))
140 stk.append((1, [child]))
141 return False
142
143 lookup = {}
144 iter_find_parents(root, None, p, q, lookup)
145 if p in lookup and lookup[p] == q:
146 return root
147 q.children.append(p)
148 if not iter_is_ancestor(p, q):
149 lookup[p].children.remove(p)
150 else:
151 lookup[q].children.remove(q)
152 if p == root:
153 root = q
154 else:
155 lookup[p].children[lookup[p].children.index(p)] = q
156 return root
157
158
159 # Time: O(n)
160 # Space: O(h)
161 # two pass solution with recursion (bad in deep tree)
162 class Solution2_Recu(object):
163 def moveSubTree(self, root, p, q):
164 """
165 :type root: Node
166 :type p: Node
167 :type q: Node
168 :rtype: Node
169 """
170 def find_parents(node, parent, p, q, lookup):
171 if node in (p, q):
172 lookup[node] = parent
173 if len(lookup) == 2:
174 return True
175 for child in node.children:
176 if find_parents(child, node, p, q, lookup):
177 return True
178 return False
179
180 def is_ancestor(node, q):
181 for child in node.children:
182 if node == q or is_ancestor(child, q):
183 return True
184 return False
185
186 lookup = {}
187 find_parents(root, None, p, q, lookup)
188 if p in lookup and lookup[p] == q:
189 return root
190 q.children.append(p)
191 if not is_ancestor(p, q):
192 lookup[p].children.remove(p)
193 else:
194 lookup[q].children.remove(q)
195 if p == root:
196 root = q
197 else:
198 lookup[p].children[lookup[p].children.index(p)] = q
199 return root
*******************************************************

308. Find a Value of a Mysterious Function Closest to


Target
*******************************************************

Winston was given the above mysterious function func . He has an integer array arr and an integer target and he wants to find
the values l and r that make the value |func(arr, l, r) - target| minimum possible.

Return the minimum possible value of |func(arr, l, r) - target| .

Notice that func should be called with the values l and r where 0 <= l, r < arr.length .

Example 1:

Input: arr = [9,12,3,7,15], target = 5


Output: 2
Explanation: Calling func with all the pairs of [l,r] = [[0,0],[1,1],[2,2],[3,3],[4,4],[0,1],[1,2],[2,3],[3,4],[0,2],[1,3],[2,4],[0,3],[1,4],

Example 2:

Input: arr = [1000000,1000000,1000000], target = 1


Output: 999999
Explanation: Winston called the func with all possible values of [l,r] and he always got 1000000, thus the min difference is 999999.

Example 3:

Input: arr = [1,2,4,8,16], target = 0


Output: 0

Constraints:

1 <= arr.length <= 10 5


1 <= arr[i] <= 10 6
0 <= target <= 10 7
*******************************************************

308. Find a Value of a Mysterious Function Closest to


Target(C++)
*******************************************************

1 // Time: O(nlogm), m is the max value of arr


2 // Space: O(logm)
3
4 class Solution {
5 public:
6 int closestToTarget(std::vector& arr, int target) {
7 static const int LOGM = 20;
8 BitCount count(LOGM);
9 int result = numeric_limits::max();
10 for (int left = 0, right = 0; right < arr.size(); ++right) {
11 count += arr[right];
12 while (left <= right) {
13 const auto& f = count.bitAnd();
14 result = min(result, abs(f - target));
15 if (f >= target) {
16 break;
17 }
18 count -= arr[left++];
19 }
20 }
21 return result;
22 }
23
24 private:
25 class BitCount {
26 public:
27 BitCount(int n)
28 : l_(0)
29 , n_(n)
30 , count_(n) {
31
32 }
33
34 int bitAnd() const {
35 int num = 0;
36 for (int i = 0; i < n_; ++i) {
37 if (count_[i] == l_) {
38 num |= 1 << i;
39 }
40 }
41 return num;
42 }
43
44 void operator+=(int num) {
45 ++l_;
46 for (int i = 0; i < n_; ++i) {
47 if (num & (1 << i)) {
48 ++count_[i];
49 }
50 }
51 }
52
53 void operator-=(int num) {
54 --l_;
55 for (int i = 0; i < n_; ++i) {
56 if (num & (1 << i)) {
57 --count_[i];
58 }
59 }
60 }
60
61
62 private:
63 int l_;
64 int n_;
65 vector count_;
66 };
67 };
68
69 // Time: O(nlogm), m is the max value of arr
70 // Space: O(logm)
71 class Solution2 {
72 public:
73 int closestToTarget(vector& arr, int target) {
74 int result = numeric_limits::max();
75 unordered_set dp; // at most O(logm) dp states
76 for (const auto& x : arr) {
77 unordered_set new_dp = {x};
78 for (const auto& f: dp) {
79 new_dp.emplace(f & x);
80 }
81 for (const auto& f : new_dp) {
82 result = min(result, abs(f - target));
83 }
84 dp = move(new_dp);
85 }
86 return result;
87 }
88 };
*******************************************************

308. Find a Value of a Mysterious Function Closest to


Target(Python)
*******************************************************

1 # Time: O(nlogm), m is the max value of arr


2 # Space: O(logm)
3
4 class BitCount(object):
5 def __init__(self, n):
6 self.__l = 0
7 self.__n = n
8 self.__count = [0]*n
9
10 def __iadd__(self, num):
11 self.__l += 1
12 base = 1
13 for i in xrange(self.__n):
14 if num&base:
15 self.__count[i] += 1
16 base <<= 1
17 return self
18
19 def __isub__(self, num):
20 self.__l -= 1
21 base = 1
22 for i in xrange(self.__n):
23 if num&base:
24 self.__count[i] -= 1
25 base <<= 1
26 return self
27
28 def bit_and(self):
29 num, base = 0, 1
30 for i in xrange(self.__n):
31 if self.__count[i] == self.__l:
32 num |= base
33 base <<= 1
34 return num
35
36
37 class Solution(object):
38 def closestToTarget(self, arr, target):
39 """
40 :type arr: List[int]
41 :type target: int
42 :rtype: int
43 """
44 count = BitCount(max(arr).bit_length())
45 result, left = float("inf"), 0
46 for right in xrange(len(arr)):
47 count += arr[right]
48 while left <= right:
49 f = count.bit_and()
50 result = min(result, abs(f-target))
51 if f >= target:
52 break
53 count -= arr[left]
54 left += 1
55 return result
56
57
58 # Time: O(nlogm), m is the max value of arr
59 # Space: O(logm)
60 class Solution2(object):
60
61 def closestToTarget(self, arr, target):
62 """
63 :type arr: List[int]
64 :type target: int
65 :rtype: int
66 """
67 result, dp = float("inf"), set() # at most O(logm) dp states
68 for x in arr:
69 dp = {x}|{f&x for f in dp}
70 for f in dp:
71 result = min(result, abs(f-target))
72 return result
****************************************************************

309. Minimum Number of Increments on Subarrays to


Form a Target Array
****************************************************************

Given an array of positive integers target and an array initial of same size with all zeros.

Return the minimum number of operations to form atarget array from initial if you are allowed to do the following operation:

Choose any subarray from initial and increment each value by one.

The answer is guaranteed to fit within the range of a 32-bit signed integer.

Example 1:

Input: target = [1,2,3,2,1]


Output: 3
Explanation: We need at least 3 operations to form the target array from the initial array.
[0,0,0,0,0] increment 1 from index 0 to 4 (inclusive).
[1,1,1,1,1] increment 1 from index 1 to 3 (inclusive).
[1,2,2,2,1] increment 1 at index 2.
[1,2,3,2,1] target array is formed.

Example 2:

Input: target = [3,1,1,2]


Output: 4
Explanation: (initial)[0,0,0,0] -> [1,1,1,1] -> [1,1,1,2] -> [2,1,1,2] -> [3,1,1,2] (target).

Example 3:

Input: target = [3,1,5,4,2]


Output: 7
Explanation: (initial)[0,0,0,0,0] -> [1,1,1,1,1] -> [2,1,1,1,1] -> [3,1,1,1,1]
-> [3,1,2,2,2] -> [3,1,3,3,2] -> [3,1,4,4,2] -> [3,1,5,4,2] (target).

Example 4:

Input: target = [1,1,1,1]


Output: 1

Constraints:

1 <= target.length <= 10^5


1 <= target[i] <= 10^5
****************************************************************

309. Minimum Number of Increments on Subarrays to


Form a Target Array(C++)
****************************************************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int minNumberOperations(vector& target) {
7 int result = target[0];
8 for (int i = 1; i < target.size(); ++i) {
9 result += max(target[i] - target[i - 1], 0);
10 }
11 return result;
12 }
13 };
****************************************************************

309. Minimum Number of Increments on Subarrays to


Form a Target Array(Python)
****************************************************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def minNumberOperations(self, target):
6 """
7 :type target: List[int]
8 :rtype: int
9 """
10 return target[0]+sum(max(target[i]-target[i-1], 0) for i in xrange(1, len(target)))
11
12
13 # Time: O(n)
14 # Space: O(n)
15 import itertools
16
17
18 class Solution2(object):
19 def minNumberOperations(self, target):
20 """
21 :type target: List[int]
22 :rtype: int
23 """
24 return sum(max(b-a, 0) for b, a in itertools.izip(target, [0]+target))
*********************

310. String Compression II


*********************

Run-length encoding is a string compression method that works by replacing consecutive identical characters (repeated 2 or
more times) with the concatenation of the character and the number marking the count of the characters (length of the run).
For example, to compress the string "aabccc" we replace "aa" by "a2" and replace "ccc" by "c3". Thus the compressed string
becomes "a2bc3".

Notice that in this problem, we are not adding'1' after single characters.

Given a string s and an integer k . You need to delete at most k characters from s such that the run-length encoded version
of s has minimum length.

Find the minimum length of the run-length encoded version of s after deleting at most k characters.

Example 1:

Input: s = "aaabcccd", k = 2
Output: 4
Explanation: Compressing s without deleting anything will give us "a3bc3d" of length 6. Deleting any of the characters 'a' or 'c' would at mo

Example 2:

Input: s = "aabbaa", k = 2
Output: 2
Explanation: If we delete both 'b' characters, the resulting compressed string would be "a4" of length 2.

Example 3:

Input: s = "aaaaaaaaaaa", k = 0
Output: 3
Explanation: Since k is zero, we cannot delete anything. The compressed string is "a11" of length 3.

Constraints:

1 <= s.length <= 100


0 <= k <= s.length
s contains only lowercase English letters.
*********************

310. String Compression II(C++)


*********************

1 // Time: O(n^2 * k)
2 // Space: O(n * k)
3
4 class Solution {
5 public:
6 int getLengthOfOptimalCompression(string s, int k) {
7 vector> dp(s.length() + 1, vector(k + 1, s.length()));
8 dp[0][0] = 0;
9 for (int i = 1; i <= s.length(); ++i) {
10 for (int j = 0; j <= k; ++j) {
11 if (i - 1 >= 0 && j - 1 >= 0) {
12 dp[i][j] = min(dp[i][j], dp[i - 1][j - 1]);
13 }
14 int keep = 0, del = 0;
15 for (int m = i; m <= s.length(); ++m) {
16 if (s[i - 1] == s[m - 1]) {
17 ++keep;
18 } else {
19 ++del;
20 }
21 if (j + del <= k) {
22 dp[m][j + del] = min(dp[m][j + del], dp[i - 1][j] + length(keep));
23 }
24 }
25 }
26 }
27 return dp[s.length()][k];
28 }
29
30 private:
31 int length(int cnt) {
32 int l = ((cnt >= 2) ? 2 : 1);
33 for (; cnt >= 10; cnt /= 10, ++l);
34 return l;
35 }
36 };
*********************

310. String Compression II(Python)


*********************

1 # Time: O(n^2 * k)
2 # Space: O(n * k)
3
4 class Solution(object):
5 def getLengthOfOptimalCompression(self, s, k):
6 """
7 :type s: str
8 :type k: int
9 :rtype: int
10 """
11 def length(cnt):
12 l = 2 if cnt >= 2 else 1
13 while cnt >= 10:
14 l += 1
15 cnt //= 10
16 return l
17
18 dp = [[len(s)]*(k+1) for _ in xrange(len(s)+1)]
19 dp[0][0] = 0
20 for i in xrange(1, len(s)+1):
21 for j in xrange(k+1):
22 if i-1 >= 0 and j-1 >= 0:
23 dp[i][j] = min(dp[i][j], dp[i-1][j-1])
24 keep = delete = 0
25 for m in xrange(i, len(s)+1):
26 if s[i-1] == s[m-1]:
27 keep += 1
28 else:
29 delete += 1
30 if j+delete <= k:
31 dp[m][j+delete] = min(dp[m][j+delete], dp[i-1][j]+length(keep));
32 return dp[len(s)][k]
*********************

311. Get the Maximum Score


*********************

You are given two sorted arrays of distinct integers nums1 and nums2.

A valid path is defined as follows:

Choose array nums1 or nums2 to traverse (from index-0).


Traverse the current array from left to right.
If you are reading any value that is present innums1 and nums2 you are allowed to change your path to the other array.
(Only one repeated value is considered in the valid path).

Score is defined as the sum of uniques values in a valid path.

Return the maximum score you can obtain of all possible valid paths.

Since the answer may be too large, return it modulo 10^9 + 7.

Example 1:

Input: nums1 = [2,4,5,8,10], nums2 = [4,6,8,9]


Output: 30
Explanation: Valid paths:
[2,4,5,8,10], [2,4,5,8,9], [2,4,6,8,9], [2,4,6,8,10], (starting from nums1)
[4,6,8,9], [4,5,8,10], [4,5,8,9], [4,6,8,10] (starting from nums2)
The maximum is obtained with the path in green [2,4,6,8,10].

Example 2:

Input: nums1 = [1,3,5,7,9], nums2 = [3,5,100]


Output: 109
Explanation: Maximum sum is obtained with the path [1,3,5,100].

Example 3:

Input: nums1 = [1,2,3,4,5], nums2 = [6,7,8,9,10]


Output: 40
Explanation: There are no common elements between nums1 and nums2.
Maximum sum is obtained with the path [6,7,8,9,10].

Example 4:

Input: nums1 = [1,4,5,8,9,11,19], nums2 = [2,3,4,11,12]


Output: 61
Constraints:

1 <= nums1.length <= 10^5


1 <= nums2.length <= 10^5
1 <= nums1[i], nums2[i] <= 10^7
nums1 and nums2 are strictly increasing.
*********************

311. Get the Maximum Score(C++)


*********************

1 // Time: O(m + n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 int maxSum(vector& nums1, vector& nums2) {
7 static const int MOD = 1e9 + 7;
8 uint64_t result = 0, sum1 = 0, sum2 = 0;
9 for (int i = 0, j = 0; i != nums1.size() || j != nums2.size();) {
10 if (i != nums1.size() && (j == nums2.size() || nums1[i] < nums2[j])) {
11 sum1 += nums1[i];
12 ++i;
13 } else if (j != nums2.size() && (i == nums1.size() || nums1[i] > nums2[j])) {
14 sum2 += nums2[j];
15 ++j;
16 } else {
17 result = (result + (max(sum1, sum2) + nums1[i])) % MOD;
18 sum1 = sum2 = 0;
19 ++i, ++j;
20 }
21 }
22 return (result + max(sum1, sum2)) % MOD;
23 }
24 };
*********************

311. Get the Maximum Score(Python)


*********************

1 # Time: O(m + n)
2 # Space: O(1)
3
4 class Solution(object):
5 def maxSum(self, nums1, nums2):
6 """
7 :type nums1: List[int]
8 :type nums2: List[int]
9 :rtype: int
10 """
11 MOD = 10**9+7
12 i, j = 0, 0
13 result, sum1, sum2 = 0, 0, 0,
14 while i != len(nums1) or j != len(nums2):
15 if i != len(nums1) and (j == len(nums2) or nums1[i] < nums2[j]):
16 sum1 += nums1[i]
17 i += 1
18 elif j != len(nums2) and (i == len(nums1) or nums1[i] > nums2[j]):
19 sum2 += nums2[j]
20 j += 1
21 else:
22 result = (result + (max(sum1, sum2) + nums1[i])) % MOD
23 sum1, sum2 = 0, 0
24 i += 1
25 j += 1
26 return (result + max(sum1, sum2)) % MOD
******************************

312. Find Longest Awesome Substring


******************************

Given a string s . An awesome substring is a non-empty substring of s such that we can make any number of swaps in order
to make it palindrome.

Return the length of the maximum length awesome substring of s .

Example 1:

Input: s = "3242415"
Output: 5
Explanation: "24241" is the longest awesome substring, we can form the palindrome "24142" with some swaps.

Example 2:

Input: s = "12345678"
Output: 1

Example 3:

Input: s = "213123"
Output: 6
Explanation: "213123" is the longest awesome substring, we can form the palindrome "231132" with some swaps.

Example 4:

Input: s = "00"
Output: 2

Constraints:

1 <= s.length <= 10^5


s consists only of digits.
******************************

312. Find Longest Awesome Substring(C++)


******************************

1 // Time: O(10 * n)
2 // Space: O(1024)
3
4 class Solution {
5 public:
6 int longestAwesome(string s) {
7 static const int ALPHABET_SIZE = 10;
8 int result = 0, mask = 0;
9 vector lookup(1 << ALPHABET_SIZE, s.length());
10 lookup[0] = -1;
11 for (int i = 0; i < s.length(); ++i) {
12 mask ^= 1 << (s[i] - '0');
13 if (lookup[mask] == s.length()) {
14 lookup[mask] = i;
15 }
16 result = max(result, i - lookup[mask]); // no middle
17 for (int d = 0; d < ALPHABET_SIZE; ++d) {
18 result = max(result, i - lookup[mask ^ (1 << d)]); // as middle
19 }
20 lookup[mask] = min(lookup[mask], i);
21 }
22 return result;
23 }
24 };
******************************

312. Find Longest Awesome Substring(Python)


******************************

1 # Time: O(10 * n)
2 # Space: O(1024)
3
4 class Solution(object):
5 def longestAwesome(self, s):
6 """
7 :type s: str
8 :rtype: int
9 """
10 ALPHABET_SIZE = 10
11 result, mask, lookup = 0, 0, [len(s)]*(2**ALPHABET_SIZE)
12 lookup[0] = -1
13 for i, ch in enumerate(s):
14 mask ^= 2**(ord(ch)-ord('0'))
15 if lookup[mask] == len(s):
16 lookup[mask] = i
17 result = max(result, i - lookup[mask])
18 for d in xrange(ALPHABET_SIZE):
19 result = max(result, i - lookup[mask^(2**d)])
20 return result
***************************

313. Minimum Cost to Cut a Stick


***************************

Given a wooden stick of length n units. The stick is labelled from 0 to n. For example, a stick of length 6 is labelled as follows:

Given an integer array cuts where cuts[i] denotes a position you should perform a cut at.

You should perform the cuts in order, you can change the order of the cuts as you wish.

The cost of one cut is the length of the stick to be cut, the total cost is the sum of costs of all cuts. When you cut a stick, it
will be split into two smaller sticks (i.e. the sum of their lengths is the length of the stick before the cut). Please refer to the
first example for a better explanation.

Return the minimum total cost of the cuts.

Example 1:

Input: n = 7, cuts = [1,3,4,5]


Output: 16
Explanation: Using cuts order = [1, 3, 4, 5] as in the input leads to the following scenario:

The first cut is done to a rod of length 7 so the cost is 7. The second cut is done to a rod of length 6 (i.e. the second part of the first c
Rearranging the cuts to be [3, 5, 1, 4] for example will lead to a scenario with total cost = 16 (as shown in the example photo 7 + 4 + 3 + 2

Example 2:

Input: n = 9, cuts = [5,6,1,4,2]


Output: 22
Explanation: If you try the given cuts ordering the cost will be 25.
There are much ordering with total cost <= 25, for example, the order [4, 6, 5, 2, 1] has total cost = 22 which is the minimum possible.
Constraints:

2 <= n <= 10^6


1 <= cuts.length <= min(n - 1, 100)
1 <= cuts[i] <= n - 1
All the integers in cuts array are distinct.
***************************

313. Minimum Cost to Cut a Stick(C++)


***************************

1 // Time: O(n^3)
2 // Space: O(n^2)
3
4 class Solution {
5 public:
6 int minCost(int n, vector& cuts) {
7 vector sorted_cuts(cbegin(cuts), cend(cuts));
8 sorted_cuts.emplace_back(0);
9 sorted_cuts.emplace_back(n);
10 sort(begin(sorted_cuts), end(sorted_cuts));
11
12 vector> dp(sorted_cuts.size(), vector(sorted_cuts.size()));
13 for (int l = 2; l < sorted_cuts.size(); ++l) {
14 for (int i = 0; i + l < sorted_cuts.size(); ++i) {
15 dp[i][i + l] = numeric_limits::max();
16 for (int j = i + 1; j < i + l; ++j) {
17 dp[i][i + l] = min(dp[i][i + l], dp[i][j] + dp[j][i + l] +
18 sorted_cuts[i + l] - sorted_cuts[i]);
19 }
20 }
21 }
22 return dp[0][sorted_cuts.size() - 1];
23 }
24 };
***************************

313. Minimum Cost to Cut a Stick(Python)


***************************

1 # Time: O(n^3)
2 # Space: O(n^2)
3
4 class Solution(object):
5 def minCost(self, n, cuts):
6 """
7 :type n: int
8 :type cuts: List[int]
9 :rtype: int
10 """
11 sorted_cuts = sorted(cuts + [0, n])
12 dp = [[0]*len(sorted_cuts) for _ in xrange(len(sorted_cuts))]
13 for l in xrange(2, len(sorted_cuts)):
14 for i in xrange(len(sorted_cuts)-l):
15 dp[i][i+l] = min(dp[i][j]+dp[j][i+l] for j in xrange(i+1, i+l)) + \
16 sorted_cuts[i+l]-sorted_cuts[i]
17 return dp[0][len(sorted_cuts)-1]
********************************

314. The Most Similar Path in a Graph


********************************

We have n cities and m bi-directional roads where roads[i] = [a i, b i] connects city ai with city bi. Each city has a name consisting of
exactly 3 upper-case English letters given in the string array names. Starting at any city x , you can reach any city y where y != x
(i.e. the cities and the roads are forming an undirected connected graph).

You will be given a string arraytargetPath. You should find a path in the graph of thesame length and with the minimum edit
distance to targetPath.

You need to return the order of the nodes in the path with the minimum edit distance, The path should be of the same length
of targetPath and should be valid (i.e. there should be a direct road betweenans[i] and ans[i + 1] ). If there are multiple answers
return any one of them.

The edit distance is defined as follows:

Follow-up: If each node can be visited only once in the path, What should you change in your solution?

Example 1:
Input: n = 5, roads = [[0,2],[0,3],[1,2],[1,3],[1,4],[2,4]], names = ["ATL","PEK","LAX","DXB","HND"], targetPath = ["ATL","DXB","HND","LAX"]
Output: [0,2,4,2]
Explanation: [0,2,4,2], [0,3,0,2] and [0,3,1,2] are accepted answers.
[0,2,4,2] is equivalent to ["ATL","LAX","HND","LAX"] which has edit distance = 1 with targetPath.
[0,3,0,2] is equivalent to ["ATL","DXB","ATL","LAX"] which has edit distance = 1 with targetPath.
[0,3,1,2] is equivalent to ["ATL","DXB","PEK","LAX"] which has edit distance = 1 with targetPath.

Example 2:

Input: n = 4, roads = [[1,0],[2,0],[3,0],[2,1],[3,1],[3,2]], names = ["ATL","PEK","LAX","DXB"], targetPath = ["ABC","DEF","GHI","JKL","MNO","


Output: [0,1,0,1,0,1,0,1]
Explanation: Any path in this graph has edit distance = 8 with targetPath.

Example 3:
Input: n = 6, roads = [[0,1],[1,2],[2,3],[3,4],[4,5]], names = ["ATL","PEK","LAX","ATL","DXB","HND"], targetPath = ["ATL","DXB","HND","DXB","
Output: [3,4,5,4,3,2,1]
Explanation: [3,4,5,4,3,2,1] is the only path with edit distance = 0 with targetPath.
It's equivalent to ["ATL","DXB","HND","DXB","ATL","LAX","PEK"]

Constraints:

2 <= n <= 100


m == roads.length
n - 1 <= m <= (n * (n - 1) / 2)
0 <= ai, b i <= n - 1
ai != b i
The graph is guaranteed to be connected and each pair of nodes may have at most one direct road.
names.length == n
names[i].length == 3
names[i] consists of
upper-case English letters.
There can be two cities with the same name.
1 <= targetPath.length <= 100
targetPath[i].length == 3
targetPath[i] consists of upper-case English letters.
********************************

314. The Most Similar Path in a Graph(C++)


********************************

1 // Time: O(n^2 * m), m is the length of targetPath


2 // Space: O(n * m)
3
4 class Solution {
5 public:
6 vector mostSimilar(int n, vector>& roads, vector& names, vector& targetPath) {
7 vector> adj(n);
8 for (const auto& road : roads) {
9 adj[road[0]].emplace_back(road[1]);
10 adj[road[1]].emplace_back(road[0]);
11 }
12
13 vector> dp(targetPath.size() + 1, vector(n));
14 for (int i = 1; i <= targetPath.size(); ++i) {
15 for (int v = 0; v < n; ++v) {
16 dp[i][v] = targetPath.size();
17 for (const auto& u : adj[v]) {
18 dp[i][v] = min(dp[i][v], dp[i - 1][u]);
19 }
20 dp[i][v] += int(names[v] != targetPath[i - 1]);
21 }
22 }
23
24 vector path = {static_cast(distance(cbegin(dp.back()),
25 min_element(cbegin(dp.back()), cend(dp.back()))))};
26 for (int i = targetPath.size(); i >= 2; --i) {
27 for (const auto& u : adj[path.back()]) {
28 if (dp[i - 1][u] + int(names[path.back()] != targetPath[i - 1]) == dp[i][path.back()]) {
29 path.emplace_back(u);
30 break;
31 }
32 }
33 }
34 reverse(begin(path), end(path));
35 return path;
36 }
37 };
********************************

314. The Most Similar Path in a Graph(Python)


********************************

1 # Time: O(n^2 * m), m is the length of targetPath


2 # Space: O(n * m)
3
4 class Solution(object):
5 def mostSimilar(self, n, roads, names, targetPath):
6 """
7 :type n: int
8 :type roads: List[List[int]]
9 :type names: List[str]
10 :type targetPath: List[str]
11 :rtype: List[int]
12 """
13 adj = [[] for _ in xrange(n)]
14 for u, v in roads:
15 adj[u].append(v)
16 adj[v].append(u)
17
18 dp = [[0]*n for _ in xrange(len(targetPath)+1)]
19 for i in xrange(1, len(targetPath)+1):
20 for v in xrange(n):
21 dp[i][v] = (names[v] != targetPath[i-1]) + min(dp[i-1][u] for u in adj[v])
22
23 path = [dp[-1].index(min(dp[-1]))]
24 for i in reversed(xrange(2, len(targetPath)+1)):
25 for u in adj[path[-1]]:
26 if dp[i-1][u]+(names[path[-1]] != targetPath[i-1]) == dp[i][path[-1]]:
27 path.append(u)
28 break
29 return path[::-1]
***************************************

315. Minimum Number of Days to Eat N Oranges


***************************************

There are n oranges in the kitchen and you decided to eat some of these oranges every day as follows:

Eat one orange.


If the number of remaining oranges (n) is divisible by 2 then you can eat n/2 oranges.
If the number of remaining oranges (n) is divisible by 3 then you can eat 2*(n/3) oranges.

You can only choose one of the actions per day.

Return the minimum number of days to eatn oranges.

Example 1:

Input: n = 10
Output: 4
Explanation: You have 10 oranges.
Day 1: Eat 1 orange, 10 - 1 = 9.
Day 2: Eat 6 oranges, 9 - 2*(9/3) = 9 - 6 = 3. (Since 9 is divisible by 3)
Day 3: Eat 2 oranges, 3 - 2*(3/3) = 3 - 2 = 1.
Day 4: Eat the last orange 1 - 1 = 0.
You need at least 4 days to eat the 10 oranges.

Example 2:

Input: n = 6
Output: 3
Explanation: You have 6 oranges.
Day 1: Eat 3 oranges, 6 - 6/2 = 6 - 3 = 3. (Since 6 is divisible by 2).
Day 2: Eat 2 oranges, 3 - 2*(3/3) = 3 - 2 = 1. (Since 3 is divisible by 3)
Day 3: Eat the last orange 1 - 1 = 0.
You need at least 3 days to eat the 6 oranges.

Example 3:

Input: n = 1
Output: 1

Example 4:

Input: n = 56
Output: 6

Constraints:

1 <= n <= 2*10^9


***************************************

315. Minimum Number of Days to Eat N Oranges(C++)


***************************************

1 // Time: O((logn)^2)
2 // Space: O((logn)^2)
3
4 // complexity analysis: see https://leetcode.com/problems/minimum-number-of-days-to-eat-n-oranges/discuss/794847/Polylogarithmic-solutio
5 class Solution {
6 public:
7 int minDays(int n) {
8 unordered_map lookup;
9 return memoization(n, &lookup);
10 }
11
12 private:
13 int memoization(int i, unordered_map *lookup) {
14 if (i <= 1) {
15 return i;
16 }
17 if (!lookup->count(i)) {
18 (*lookup)[i] = 1 + min(i % 2 + memoization(i / 2, lookup),
19 i % 3 + memoization(i / 3, lookup));
20 }
21 return (*lookup)[i];
22 }
23 };
24
25 // Time: O((logn)^2)
26 // Space: O((logn)^2)
27 class Solution2 {
28 public:
29 int minDays(int n) {
30 int result = 0;
31 vector q = {n};
32 unordered_set lookup = {n};
33 while (!q.empty()) {
34 vector new_q;
35 for (const auto& i : q) {
36 if (i == 0) {
37 return result;
38 }
39 if (!lookup.count(i - 1)) {
40 lookup.emplace(i - 1);
41 new_q.emplace_back(i - 1);
42 }
43 if (i % 2 == 0 && !lookup.count(i / 2)) {
44 lookup.emplace(i / 2);
45 new_q.emplace_back(i / 2);
46 }
47 if (i % 3 == 0 && !lookup.count(i / 3)) {
48 lookup.emplace(i / 3);
49 new_q.emplace_back(i / 3);
50 }
51 }
52 ++result;
53 q = move(new_q);
54 }
55 return result;
56 }
57 };
***************************************

315. Minimum Number of Days to Eat N Oranges(Python)


***************************************

1 # Time: O((logn)^2)
2 # Space: O((logn)^2)
3
4 # complexity analysis: see https://leetcode.com/problems/minimum-number-of-days-to-eat-n-oranges/discuss/794847/Polylogarithmic-solution
5 class Solution(object):
6 def minDays(self, n):
7 """
8 :type n: int
9 :rtype: int
10 """
11 def memoization(lookup, i):
12 if i <= 1:
13 return i
14 if i not in lookup:
15 lookup[i] = 1+min(i%2+memoization(lookup, i//2),
16 i%3+memoization(lookup, i//3))
17 return lookup[i]
18
19 lookup = {}
20 return memoization(lookup, n)
21
22
23 # Time: O((logn)^2)
24 # Space: O((logn)^2)
25 class Solution2(object):
26 def minDays(self, n):
27 result = 0
28 q, lookup = [n], set([n])
29 while q:
30 new_q = []
31 for i in q:
32 if not i:
33 return result
34 if i-1 not in lookup:
35 lookup.add(i-1)
36 new_q.append(i-1)
37 if i%2 == 0 and i//2 not in lookup:
38 lookup.add(i//2)
39 new_q.append(i//2)
40 if i%3 == 0 and i//3 not in lookup:
41 lookup.add(i//3)
42 new_q.append(i//3)
43 result += 1
44 q = new_q
45 return result
************************

316. Detect Cycles in 2D Grid


************************

Given a 2D array of characters grid of size m x n , you need to find if there exists any cycle consisting of thesame
value in grid.

A cycle is a path of length 4 or more in the grid that starts and ends at the same cell. From a given cell, you can move to
one of the cells adjacent to it - in one of the four directions (up, down, left, or right), if it has the same value of the current
cell.

Also, you cannot move to the cell that you visited in your last move. For example, the cycle(1, 1) -> (1, 2) -> (1, 1) is invalid
because from (1, 2) we visited (1, 1) which was the last visited cell.

Return true if any cycle of the same value exists ingrid, otherwise, return false.

Example 1:

Input: grid = [["a","a","a","a"],["a","b","b","a"],["a","b","b","a"],["a","a","a","a"]]


Output: true
Explanation: There are two valid cycles shown in different colors in the image below:

Example 2:

Input: grid = [["c","c","c","a"],["c","d","c","c"],["c","c","e","c"],["f","c","c","c"]]


Output: true
Explanation: There is only one valid cycle highlighted in the image below:

Example 3:
Input: grid = [["a","b","b"],["b","z","b"],["b","b","a"]]
Output: false

Constraints:

m == grid.length
n == grid[i].length
1 <= m <= 500
1 <= n <= 500
grid consists only of lowercase English letters.
************************

316. Detect Cycles in 2D Grid(C++)


************************

1 // Time: O(m * n * α(n)) ~= O(m * n)


2 // Space: O(m * n)
3
4 class Solution {
5 public:
6 bool containsCycle(vector>& grid) {
7 UnionFind union_find(grid.size() * grid[0].size());
8 for (int i = 0; i < grid.size(); ++i) {
9 for (int j = 0; j < grid[0].size(); ++j) {
10 if (i && j &&
11 grid[i][j] == grid[i - 1][j] &&
12 grid[i][j] == grid[i][j - 1] &&
13 union_find.find_set(index(grid[0].size(), i - 1, j)) ==
14 union_find.find_set(index(grid[0].size(), i, j - 1))) {
15 return true;
16 }
17 if (i && grid[i][j] == grid[i - 1][j]) {
18 union_find.union_set(index(grid[0].size(), i - 1, j),
19 index(grid[0].size(), i, j));
20 }
21 if (j && grid[i][j] == grid[i][j - 1]) {
22 union_find.union_set(index(grid[0].size(), i, j - 1),
23 index(grid[0].size(), i, j));
24 }
25 }
26 }
27 return false;
28 }
29
30 private:
31 class UnionFind {
32 public:
33 UnionFind(const int n) : set_(n), count_(n) {
34 iota(set_.begin(), set_.end(), 0);
35 }
36
37 int find_set(const int x) {
38 if (set_[x] != x) {
39 set_[x] = find_set(set_[x]); // Path compression.
40 }
41 return set_[x];
42 }
43
44 void union_set(const int x, const int y) {
45 int x_root = find_set(x), y_root = find_set(y);
46 if (x_root != y_root) {
47 set_[min(x_root, y_root)] = max(x_root, y_root);
48 --count_;
49 }
50 }
51
52 int size() const {
53 return count_;
54 }
55
56 private:
57 vector set_;
58 int count_;
59 };
60
61 int index(int n, int i, int j) {
62 return i * n + j;
63 }
64 };
65
66 // Time: O(m * n)
67 // Space: O(m * n)
68 class Solution2 {
69 public:
70 bool containsCycle(vector>& grid) {
71 static const vector> directions{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
72 for (int i = 0; i < grid.size(); ++i) {
73 for (int j = 0; j < grid[i].size(); ++j) {
74 if (!grid[i][j]) {
75 continue;
76 }
77 char val = grid[i][j];
78 vector> q = {{i, j}};
79 while (!q.empty()) {
80 vector> new_q;
81 for (const auto& [r, c] : q) {
82 if (!grid[r][c]) {
83 return true;
84 }
85 grid[r][c] = 0;
86 for (const auto& d : directions) {
87 const auto nr = r + d.first;
88 const auto nc = c + d.second;
89 if (!(0 <= nr && nr < grid.size() &&
90 0 <= nc && nc < grid[0].size() &&
91 grid[nr][nc] == val)) {
92 continue;
93 }
94 new_q.emplace_back(nr, nc);
95 }
96 }
97 q = move(new_q);
98 }
99 }
100 }
101 return false;
102 }
103 };
************************

316. Detect Cycles in 2D Grid(Python)


************************

1 # Time: O(m * n * α(n)) ~= O(m * n)


2 # Space: O(m * n)
3
4 class UnionFind(object):
5 def __init__(self, n):
6 self.set = range(n)
7 self.count = n
8
9 def find_set(self, x):
10 if self.set[x] != x:
11 self.set[x] = self.find_set(self.set[x]) # path compression.
12 return self.set[x]
13
14 def union_set(self, x, y):
15 x_root, y_root = map(self.find_set, (x, y))
16 if x_root != y_root:
17 self.set[min(x_root, y_root)] = max(x_root, y_root)
18 self.count -= 1
19
20
21 class Solution(object):
22 def containsCycle(self, grid):
23 """
24 :type grid: List[List[str]]
25 :rtype: bool
26 """
27 def index(n, i, j):
28 return i*n + j
29
30 union_find = UnionFind(len(grid)*len(grid[0]))
31 for i in xrange(len(grid)):
32 for j in xrange(len(grid[0])):
33 if i and j and grid[i][j] == grid[i-1][j] == grid[i][j-1] and \
34 union_find.find_set(index(len(grid[0]), i-1, j)) == \
35 union_find.find_set(index(len(grid[0]), i, j-1)):
36 return True
37 if i and grid[i][j] == grid[i-1][j]:
38 union_find.union_set(index(len(grid[0]), i-1, j),
39 index(len(grid[0]),i, j))
40 if j and grid[i][j] == grid[i][j-1]:
41 union_find.union_set(index(len(grid[0]), i, j-1),
42 index(len(grid[0]), i, j))
43 return False
44
45
46 # Time: O(m * n)
47 # Space: O(m * n)
48 class Solution2(object):
49 def containsCycle(self, grid):
50 """
51 :type grid: List[List[str]]
52 :rtype: bool
53 """
54 directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
55 for i in xrange(len(grid)):
56 for j in xrange(len(grid[0])):
57 if not grid[i][j]:
58 continue
59 val = grid[i][j]
60 q = [(i, j)]
61 while q:
62 new_q = []
63 for r, c in q:
64 if not grid[r][c]:
65 return True
66 grid[r][c] = 0
67 for dr, dc in directions:
68 nr, nc = r+dr, c+dc
69 if not (0 <= nr < len(grid) and
70 0 <= nc < len(grid[0]) and
71 grid[nr][nc] == val):
72 continue
73 new_q.append((nr, nc))
74 q = new_q
75 return False
************

317. Stone Game V


************

There are several stones arranged in a row, and each stone has an associated value which is an integer given in the
array stoneValue.

In each round of the game, Alice divides the row intotwo non-empty rows (i.e. left row and right row), then Bob calculates
the value of each row which is the sum of the values of all the stones in this row. Bob throws away the row which has the
maximum value, and Alice's score increases by the value of the remaining row. If the value of the two rows are equal, Bob
lets Alice decide which row will be thrown away. The next round starts with the remaining row.

The game ends when there is only one stone remaining. Alice's is initially zero.

Return the maximum score that Alice can obtain.

Example 1:

Input: stoneValue = [6,2,3,4,5,5]


Output: 18
Explanation: In the first round, Alice divides the row to [6,2,3], [4,5,5]. The left row has the value 11 and the right row has value 14. Bob
In the second round Alice divides the row to [6], [2,3]. This time Bob throws away the left row and Alice's score becomes 16 (11 + 5).
The last round Alice has only one choice to divide the row which is [2], [3]. Bob throws away the right row and Alice's score is now 18 (16 +

Example 2:

Input: stoneValue = [7,7,7,7,7,7,7]


Output: 28

Example 3:

Input: stoneValue = [4]


Output: 0

Constraints:

1 <= stoneValue.length <= 500


1 <= stoneValue[i] <= 10^6
************

317. Stone Game V(C++)


************

1 // Time: O(n^2)
2 // Space: O(n^2)
3
4 class Solution {
5 public:
6 int stoneGameV(vector& stoneValue) {
7 const int n = stoneValue.size();
8 vector prefix(n + 1);
9 partial_sum(cbegin(stoneValue), cend(stoneValue), begin(prefix) + 1);
10
11 vector mid(n);
12 iota(begin(mid), end(mid), 0);
13
14 vector> dp(n, vector(n));
15 for (int i = 0; i < n; ++i) {
16 dp[i][i] = stoneValue[i];
17 }
18
19 int max_score = 0;
20 for (int l = 2; l <= n; ++l) {
21 for (int i = 0; i <= n - l; ++i) {
22 const int j = i + l - 1;
23 while (prefix[mid[i]] - prefix[i] < prefix[j + 1] - prefix[mid[i]]) {
24 ++mid[i]; // Time: O(n^2) in total
25 }
26 const int p = mid[i];
27 max_score = 0;
28 if (prefix[p] - prefix[i] == prefix[j + 1] - prefix[p]) {
29 max_score = max(dp[i][p - 1], dp[j][p]);
30 } else {
31 if (i <= p - 2) {
32 max_score = max(max_score, dp[i][p - 2]);
33 }
34 if (p <= j) {
35 max_score = max(max_score, dp[j][p]);
36 }
37 }
38 dp[i][j] = max(dp[i][j - 1], (prefix[j + 1] - prefix[i]) + max_score);
39 dp[j][i] = max(dp[j][i + 1], (prefix[j + 1] - prefix[i]) + max_score);
40 }
41 }
42 return max_score;
43 }
44 };
45
46
47 // Time: O(n^2)
48 // Space: O(n^2)
49 class Solution2 {
50 public:
51 int stoneGameV(vector& stoneValue) {
52 const int n = stoneValue.size();
53 vector prefix(n + 1);
54 partial_sum(cbegin(stoneValue), cend(stoneValue), begin(prefix) + 1);
55
56 vector> mid(n, vector(n));
57 for (int l = 1; l <= n; ++l) {
58 for (int i = 0; i <= n - l; ++i) {
59 const int j = i + l - 1;
60 int p = (l == 1) ? i : mid[i][j - 1];
61 while (prefix[p] - prefix[i] < prefix[j + 1] - prefix[p]) {
62 ++p; // Time: O(n^2) in total
63 }
64 mid[i][j] = p;
65 }
66 }
67
68 vector> rmq(n, vector(n));
69 for (int i = 0; i < n; ++i) {
70 rmq[i][i] = stoneValue[i];
71 }
72
73 vector> dp(n, vector(n));
74 for (int l = 2; l <= n; ++l) {
75 for (int i = 0; i <= n - l; ++i) {
76 const int j = i + l - 1;
77 const int p = mid[i][j];
78 int max_score = 0;
79 if (prefix[p] - prefix[i] == prefix[j + 1] - prefix[p]) {
80 max_score = max(rmq[i][p - 1], rmq[j][p]);
81 } else {
82 if (i <= p - 2) {
83 max_score = max(max_score, rmq[i][p - 2]);
84 }
85 if (p <= j) {
86 max_score = max(max_score, rmq[j][p]);
87 }
88 }
89 dp[i][j] = max_score;
90 rmq[i][j] = max(rmq[i][j - 1], (prefix[j + 1] - prefix[i]) + max_score);
91 rmq[j][i] = max(rmq[j][i + 1], (prefix[j + 1] - prefix[i]) + max_score);
92 }
93 }
94 return dp[0][n - 1];
95 }
96 };
************

317. Stone Game V(Python)


************

1 # Time: O(n^2)
2 # Space: O(n^2)
3
4 class Solution(object):
5 def stoneGameV(self, stoneValue):
6 """
7 :type stoneValue: List[int]
8 :rtype: int
9 """
10 n = len(stoneValue)
11 prefix = [0]
12 for v in stoneValue:
13 prefix.append(prefix[-1] + v)
14
15 mid = range(n)
16
17 dp = [[0]*n for _ in xrange(n)]
18 for i in xrange(n):
19 dp[i][i] = stoneValue[i]
20
21 max_score = 0
22 for l in xrange(2, n+1):
23 for i in xrange(n-l+1):
24 j = i+l-1
25 while prefix[mid[i]]-prefix[i] < prefix[j+1]-prefix[mid[i]]:
26 mid[i] += 1 # Time: O(n^2) in total
27 p = mid[i]
28 max_score = 0
29 if prefix[p]-prefix[i] == prefix[j+1]-prefix[p]:
30 max_score = max(dp[i][p-1], dp[j][p])
31 else:
32 if i <= p-2:
33 max_score = max(max_score, dp[i][p-2])
34 if p <= j:
35 max_score = max(max_score, dp[j][p])
36 dp[i][j] = max(dp[i][j-1], (prefix[j+1]-prefix[i]) + max_score)
37 dp[j][i] = max(dp[j][i+1], (prefix[j+1]-prefix[i]) + max_score)
38 return max_score
39
40
41 # Time: O(n^2)
42 # Space: O(n^2)
43 class Solution2(object):
44 def stoneGameV(self, stoneValue):
45 """
46 :type stoneValue: List[int]
47 :rtype: int
48 """
49 n = len(stoneValue)
50 prefix = [0]
51 for v in stoneValue:
52 prefix.append(prefix[-1] + v)
53
54 mid = [[0]*n for _ in xrange(n)]
55 for l in xrange(1, n+1):
56 for i in xrange(n-l+1):
57 j = i+l-1
58 p = i if l == 1 else mid[i][j-1]
59 while prefix[p]-prefix[i] < prefix[j+1]-prefix[p]:
60 p += 1 # Time: O(n^2) in total
61 mid[i][j] = p
62
63 rmq = [[0]*n for _ in xrange(n)]
64 for i in xrange(n):
65 rmq[i][i] = stoneValue[i]
66
67 dp = [[0]*n for _ in xrange(n)]
68 for l in xrange(2, n+1):
69 for i in xrange(n-l+1):
70 j = i+l-1
71 p = mid[i][j]
72 max_score = 0
73 if prefix[p]-prefix[i] == prefix[j+1]-prefix[p]:
74 max_score = max(rmq[i][p-1], rmq[j][p])
75 else:
76 if i <= p-2:
77 max_score = max(max_score, rmq[i][p-2])
78 if p <= j:
79 max_score = max(max_score, rmq[j][p])
80 dp[i][j] = max_score
81 rmq[i][j] = max(rmq[i][j-1], (prefix[j+1]-prefix[i]) + max_score)
82 rmq[j][i] = max(rmq[j][i+1], (prefix[j+1]-prefix[i]) + max_score)
83 return dp[0][n-1]
***********************************************

318. Number of Ways to Reorder Array to Get Same BST


***********************************************

Given an array nums that represents a permutation of integers from 1 to n. We are going to construct a binary search tree
(BST) by inserting the elements of nums in order into an initially empty BST. Find the number of different ways to reorder
nums so that the constructed BST is identical to that formed from the original array nums.

For example, given nums = [2,1,3] , we will have 2 as the root, 1 as a left child, and 3 as a right child. The array[2,3,1] also yields
the same BST but [3,2,1] yields a different BST.

Return the number of ways to reorder nums such that the BST formed is identical to the original BST formed fromnums.

Since the answer may be very large, return it modulo 10^9 + 7 .

Example 1:

Input: nums = [2,1,3]


Output: 1
Explanation: We can reorder nums to be [2,3,1] which will yield the same BST. There are no other ways to reorder nums which will yield the sa

Example 2:

Input: nums = [3,4,5,1,2]


Output: 5
Explanation: The following 5 arrays will yield the same BST:
[3,1,2,4,5]
[3,1,4,2,5]
[3,1,4,5,2]
[3,4,1,2,5]
[3,4,1,5,2]

Example 3:
Input: nums = [1,2,3]
Output: 0
Explanation: There are no other orderings of nums that will yield the same BST.

Example 4:

Input: nums = [3,1,2,5,4,6]


Output: 19

Example 5:

Input: nums = [9,4,2,1,3,6,5,7,8,14,11,10,12,13,16,15,17,18]


Output: 216212978
Explanation: The number of ways to reorder nums to get the same BST is 3216212999. Taking this number modulo 10^9 + 7 gives 216212978.

Constraints:

1 <= nums.length <= 1000


1 <= nums[i] <= nums.length
All integers in nums are distinct.
***********************************************

318. Number of Ways to Reorder Array to Get Same


BST(C++)
***********************************************

1 // Time: O(n)
2 // Space: O(1)
3
4 class Solution {
5 public:
6 bool containsPattern(vector& arr, int m, int k) {
7 int cnt = 0;
8 for (int i = 0; i + m < arr.size(); ++i) {
9 if (arr[i] != arr[i + m]) {
10 cnt = 0;
11 continue;
12 }
13 if (++cnt == (k - 1) * m) {
14 return true;
15 }
16 }
17 return false;
18 }
19 };
***********************************************

318. Number of Ways to Reorder Array to Get Same


BST(Python)
***********************************************

1 # Time: O(n)
2 # Space: O(1)
3
4 class Solution(object):
5 def containsPattern(self, arr, m, k):
6 """
7 :type arr: List[int]
8 :type m: int
9 :type k: int
10 :rtype: bool
11 """
12 cnt = 0
13 for i in xrange(len(arr)-m):
14 if arr[i] != arr[i+m]:
15 cnt = 0
16 continue
17 cnt += 1
18 if cnt == (k-1)*m:
19 return True
20 return False
*************************

319. Count All Possible Routes


*************************

You are given an array of distinct positive integers locations where locations[i] represents the position of city i. You are also
given integers start, finish and fuel representing the starting city, ending city, and the initial amount of fuel you have,
respectively.

At each step, if you are at city i, you can pick any city j such that j != i and 0 <= j < locations.length and move to city j. Moving from
city i to city j reduces the amount of fuel you have by |locations[i] - locations[j]| . Please notice that |x| denotes the absolute value
of x .

Notice that fuel cannot become negative at any point in time, and that you areallowed to visit any city more than once
(including start and finish).

Return the count of all possible routes from start to finish.

Since the answer may be too large, return it modulo 10^9 + 7 .

Example 1:

Input: locations = [2,3,6,8,4], start = 1, finish = 3, fuel = 5


Output: 4
Explanation: The following are all possible routes, each uses 5 units of fuel:
1 -> 3
1 -> 2 -> 3
1 -> 4 -> 3
1 -> 4 -> 2 -> 3

Example 2:

Input: locations = [4,3,1], start = 1, finish = 0, fuel = 6


Output: 5
Explanation: The following are all possible routes:
1 -> 0, used fuel = 1
1 -> 2 -> 0, used fuel = 5
1 -> 2 -> 1 -> 0, used fuel = 5
1 -> 0 -> 1 -> 0, used fuel = 3
1 -> 0 -> 1 -> 0 -> 1 -> 0, used fuel = 5

Example 3:

Input: locations = [5,2,1], start = 0, finish = 2, fuel = 3


Output: 0
Explanation: It's impossible to get from 0 to 2 using only 3 units of fuel since the shortest route needs 4 units of fuel.

Example 4:

Input: locations = [2,1,5], start = 0, finish = 0, fuel = 3


Output: 2
Explanation: There are two possible routes, 0 and 0 -> 1 -> 0.

Example 5:
Input: locations = [1,2,3], start = 0, finish = 2, fuel = 40
Output: 615088286
Explanation: The total number of possible routes is 2615088300. Taking this number modulo 10^9 + 7 gives us 615088286.

Constraints:

2 <= locations.length <= 100


1 <= locations[i] <= 10^9
All integers in locations are distinct.
0 <= start, finish < locations.length
1 <= fuel <= 200
*************************

319. Count All Possible Routes(C++)


*************************

1 // Time: O(nlogn + n * f)
2 // Space: O(n * f)
3
4 class Solution {
5 public:
6 int countRoutes(vector& locations, int start, int finish, int fuel) {
7 static const int MOD = 1e9 + 7;
8
9 int s = locations[start];
10 int f = locations[finish];
11 sort(begin(locations), end(locations));
12 start = distance(cbegin(locations), lower_bound(cbegin(locations), cend(locations), s));
13 finish = distance(cbegin(locations), lower_bound(cbegin(locations), cend(locations), f));
14
15 vector> left(locations.size(), vector(fuel + 1)); // left[i][f], last move is toward left to location i by f fuel
16 vector> right(locations.size(), vector(fuel + 1)); // right[i][f], last move is toward right to location i by f fuel
17 for (int f = 1; f <= fuel; ++f) {
18 for (int j = 0; j < locations.size() - 1; ++j) {
19 int d = locations[j + 1] - locations[j];
20 if (f > d) {
21 // left[j][f] = right[j+1][f-d(j, j+1)] + 2*right[j+2][f-d(j, j+2)] + ... + 2^(k-1)*right[j+k][f-d(j, j+k)]
22 // => left[j+1][f] = (ight[j+2][f-d(j+1, j+2)] + 2*right[j+3][f-d(j+1, j+3)] + ... + 2^(k-2)*right[j+1+k-1][f-d(j+1,
23 // => left[j+1][f-d(j, j+1)] = right[j+2][f-d(j, j+2)] + 2*right[j+3][f-d(j, j+3)] + ... + 2^(k-2)*right[j+k][f-d(j,
24 // => left[j][f] = right[j+1][f-d(j, j+1)] + 2*left[j+1][f-d(j, j+1)]
25 left[j][f] = (right[j + 1][f - d] + 2 * left[j + 1][f - d] % MOD) % MOD;
26 } else if (f == d) {
27 left[j][f] = int(j + 1 == start);
28 }
29 }
30 for (int j = 1; j < locations.size(); ++j) {
31 int d = locations[j] - locations[j - 1];
32 if (f > d) {
33 // right[j][f] = left[j-1][f-d(j, j-1)] + 2*left[j-2][f-d(j, j-2)] + ... + 2^(k-1)*left[j-k][f-d(j, j-k)]
34 // => right[j-1][f] = left[j-2][f-d(j-1, j-2)] + 2*left[j-3][f-d(j-1, j-3)] + ... + 2^(k-2)*left[j-1-k+1][f-d(j-1, j
35 // => right[j-1][f-d(j, j-1)] = left[j-2][f-d(j, j-2)] + 2*left[j-3][f-d(j, j-3)] + ... + 2^(k-2)*left[j-k][f-d(j, j
36 // => right[j][f] = left[j-1][f-d(j, j-1)] + 2*right[j-1][f-d(j, j-1)]
37 right[j][f] = (left[j - 1][f - d] + 2 * right[j - 1][f - d] % MOD) % MOD;
38 } else if (f == d) {
39 right[j][f] = int(j - 1 == start);
40 }
41 }
42 }
43 int result = int(start == finish);
44 for (int f = 1; f <= fuel; ++f) {
45 result = ((result + left[finish][f]) % MOD + right[finish][f]) % MOD;
46 }
47 return result;
48 }
49 };
50
51 // Time: O(n^2 * f)
52 // Space: O(n * f)
53 class Solution2 {
54 public:
55 int countRoutes(vector& locations, int start, int finish, int fuel) {
56 static const int MOD = 1e9 + 7;
57
58 vector> dp(locations.size(), vector(fuel + 1));
59 dp[start][0] = 1;
60 for (int f = 1; f <= fuel; ++f) {
61 for (int i = 0; i < locations.size(); ++i) {
62 for (int j = 0; j < locations.size(); ++j) {
63 if (i == j) {
64 continue;
65 }
66 int d = abs(locations[i] - locations[j]);
67 if (f - d < 0) {
68 continue;
69 }
70 dp[i][f] = (static_cast(dp[i][f]) + dp[j][f - d]) % MOD;
71 }
72 }
73 }
74 return accumulate(cbegin(dp[finish]), cend(dp[finish]), 0LL,
75 [&](const int64_t a, const int b) {
76 return (a + b) % MOD;
77 });
78 }
79 };
*************************

319. Count All Possible Routes(Python)


*************************

1 # Time: O(nlogn + n * f)
2 # Space: O(n * f)
3
4 import bisect
5
6
7 class Solution(object):
8 def countRoutes(self, locations, start, finish, fuel):
9 """
10 :type locations: List[int]
11 :type start: int
12 :type finish: int
13 :type fuel: int
14 :rtype: int
15 """
16 MOD = 10**9+7
17
18 s, f = locations[start], locations[finish];
19 locations.sort()
20 start, finish = bisect.bisect_left(locations, s), bisect.bisect_left(locations, f)
21
22 left = [[0]*(fuel+1) for _ in xrange(len(locations))] # left[i][f], last move is toward left to location i by f fuel
23 right = [[0]*(fuel+1) for _ in xrange(len(locations))] # right[i][f], last move is toward right to location i by f fuel
24 for f in xrange(1, fuel+1):
25 for j in xrange(len(locations)-1):
26 d = locations[j+1]-locations[j]
27 if f > d:
28 # left[j][f] = right[j+1][f-d(j, j+1)] + 2*right[j+2][f-d(j, j+2)] + ... + 2^(k-1)*right[j+k][f-d(j, j+k)]
29 # => left[j+1][f] = (ight[j+2][f-d(j+1, j+2)] + 2*right[j+3][f-d(j+1, j+3)] + ... + 2^(k-2)*right[j+1+k-1][f-d(j+1,
30 # => left[j+1][f-d(j, j+1)] = right[j+2][f-d(j, j+2)] + 2*right[j+3][f-d(j, j+3)] + ... + 2^(k-2)*right[j+k][f-d(j,
31 # => left[j][f] = right[j+1][f-d(j, j+1)] + 2*left[j+1][f-d(j, j+1)]
32 left[j][f] = (right[j+1][f-d] + 2*left[j+1][f-d] % MOD) % MOD;
33 elif f == d:
34 left[j][f] = int(j+1 == start)
35 for j in xrange(1, len(locations)):
36 d = locations[j]-locations[j-1]
37 if f > d:
38 # right[j][f] = left[j-1][f-d(j, j-1)] + 2*left[j-2][f-d(j, j-2)] + ... + 2^(k-1)*left[j-k][f-d(j, j-k)]
39 # => right[j-1][f] = left[j-2][f-d(j-1, j-2)] + 2*left[j-3][f-d(j-1, j-3)] + ... + 2^(k-2)*left[j-1-k+1][f-d(j-1, j-
40 # => right[j-1][f-d(j, j-1)] = left[j-2][f-d(j, j-2)] + 2*left[j-3][f-d(j, j-3)] + ... + 2^(k-2)*left[j-k][f-d(j, j-
41 # => right[j][f] = left[j-1][f-d(j, j-1)] + 2*right[j-1][f-d(j, j-1)]
42 right[j][f] = (left[j-1][f-d] + 2*right[j-1][f-d] % MOD) % MOD
43 elif f == d:
44 right[j][f] = int(j-1 == start)
45 result = int(start == finish)
46 for f in xrange(1, fuel+1):
47 result = ((result + left[finish][f]) % MOD + right[finish][f]) % MOD
48 return result
49
50
51 # Time: O(n^2 * f)
52 # Space: O(n * f)
53 class Solution2(object):
54 def countRoutes(self, locations, start, finish, fuel):
55 """
56 :type locations: List[int]
57 :type start: int
58 :type finish: int
59 :type fuel: int
60 :rtype: int
61 """
62 MOD = 10**9+7
63 dp = [[0]*(fuel+1) for _ in xrange(len(locations))]
64 dp[start][0] = 1
65 for f in xrange(fuel+1):
66 for i in xrange(len(locations)):
67 for j in xrange(len(locations)):
68 if i == j:
69 continue
70 d = abs(locations[i]-locations[j])
71 if f-d < 0:
72 continue
73 dp[i][f] = (dp[i][f]+dp[j][f-d])%MOD
74 return reduce(lambda x, y: (x+y)%MOD, dp[finish])
**********************************************************

320. Remove Max Number of Edges to Keep Graph Fully


Traversable
**********************************************************

Alice and Bob have an undirected graph of n nodes and 3 types of edges:

Type 1: Can be traversed by Alice only.


Type 2: Can be traversed by Bob only.
Type 3: Can by traversed by both Alice and Bob.

Given an array edges where edges[i] = [type i, u i, v i] represents a bidirectional edge of type type i between nodes ui and v i, find the
maximum number of edges you can remove so that after removing the edges, the graph can still be fully traversed by both
Alice and Bob. The graph is fully traversed by Alice and Bob if starting from any node, they can reach all other nodes.

Return the maximum number of edges you can remove, or return-1 if it's impossible for the graph to be fully traversed by
Alice and Bob.

Example 1:

Input: n = 4, edges = [[3,1,2],[3,2,3],[1,1,3],[1,2,4],[1,1,2],[2,3,4]]


Output: 2
Explanation: If we remove the 2 edges [1,1,2] and [1,1,3]. The graph will still be fully traversable by Alice and Bob. Removing any additiona

Example 2:

Input: n = 4, edges = [[3,1,2],[3,2,3],[1,1,4],[2,1,4]]


Output: 0
Explanation: Notice that removing any edge will not make the graph fully traversable by Alice and Bob.

Example 3:
Input: n = 4, edges = [[3,2,3],[1,1,2],[2,3,4]]
Output: -1
Explanation: In the current graph, Alice cannot reach node 4 from the other nodes. Likewise, Bob cannot reach 1. Therefore it's impossible to

Constraints:

1 <= n <= 10^5


1 <= edges.length <= min(10^5, 3 * n * (n-1) / 2)
edges[i].length == 3
1 <= edges[i][0] <= 3
1 <= edges[i][1] < edges[i][2] <= n
All tuples (typei, u i, v i) are distinct.
**********************************************************

320. Remove Max Number of Edges to Keep Graph Fully


Traversable(C++)
**********************************************************
1 // Time: O(n + m * α(n)) ~= O(n + m)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int maxNumEdgesToRemove(int n, vector>& edges) {
7 int result = 0;
8 UnionFind union_find_a(n), union_find_b(n);
9 for (const auto& edge : edges) {
10 int t = edge[0], i = edge[1], j = edge[2];
11 if (t != 3) {
12 continue;
13 }
14 bool a = union_find_a.union_set(i - 1, j - 1);
15 bool b = union_find_b.union_set(i - 1, j - 1);
16 if (!a && !b) {
17 ++result;
18 }
19 }
20 for (const auto& edge : edges) {
21 int t = edge[0], i = edge[1], j = edge[2];
22 if (t == 1) {
23 if (!union_find_a.union_set(i - 1, j - 1)) {
24 ++result;
25 }
26 } else if (t == 2) {
27 if (!union_find_b.union_set(i - 1, j - 1)) {
28 ++result;
29 }
30 }
31 }
32 return union_find_a.size() == 1 && union_find_b.size() == 1 ? result : -1;
33 }
34
35 private:
36 class UnionFind {
37 public:
38 UnionFind(const int n) : set_(n), size_(n) {
39 iota(set_.begin(), set_.end(), 0);
40 }
41
42 int find_set(const int x) {
43 if (set_[x] != x) {
44 set_[x] = find_set(set_[x]); // Path compression.
45 }
46 return set_[x];
47 }
48
49 bool union_set(const int x, const int y) {
50 int x_root = find_set(x), y_root = find_set(y);
51 if (x_root == y_root) {
52 return false;
53 }
54 set_[max(x_root, y_root)] = min(x_root, y_root);
55 --size_;
56 return true;
57 }
58
59 int size() const {
60 return size_;
61 }
62
63 private:
64 vector set_;
65 int size_;
66 };
67 };
**********************************************************

320. Remove Max Number of Edges to Keep Graph Fully


Traversable(Python)
**********************************************************

1 # Time: O(n + m * α(n)) ~= O(n + m)


2 # Space: O(n)
3
4 class UnionFind(object):
5 def __init__(self, n):
6 self.set = range(n)
7 self.count = n
8
9 def find_set(self, x):
10 if self.set[x] != x:
11 self.set[x] = self.find_set(self.set[x]) # path compression.
12 return self.set[x]
13
14 def union_set(self, x, y):
15 x_root, y_root = map(self.find_set, (x, y))
16 if x_root == y_root:
17 return False
18 self.set[max(x_root, y_root)] = min(x_root, y_root)
19 self.count -= 1
20 return True
21
22
23 class Solution(object):
24 def maxNumEdgesToRemove(self, n, edges):
25 """
26 :type n: int
27 :type edges: List[List[int]]
28 :rtype: int
29 """
30 result = 0
31 union_find_a, union_find_b = UnionFind(n), UnionFind(n)
32 for t, i, j in edges:
33 if t != 3:
34 continue
35 a = union_find_a.union_set(i-1, j-1)
36 b = union_find_b.union_set(i-1, j-1)
37 if not a and not b:
38 result += 1
39 for t, i, j in edges:
40 if t == 1:
41 if not union_find_a.union_set(i-1, j-1):
42 result += 1
43 elif t == 2:
44 if not union_find_b.union_set(i-1, j-1):
45 result += 1
46 return result if union_find_a.count == union_find_b.count == 1 else -1
***************************************************************

321. Check If String Is Transformable With Substring Sort


Operations
***************************************************************

Given two strings s and t, you want to transform string s into string t using the following operation any number of times:

Choose a non-empty substring in s and sort it in-place so the characters are in ascending order.

For example, applying the operation on the underlined substring in "14234" results in "12344".

Return true if it is possible to transform string s into string t. Otherwise, return false.

A substring is a contiguous sequence of characters within a string.

Example 1:

Input: s = "84532", t = "34852"


Output: true
Explanation: You can transform s into t using the following sort operations:
"84532" (from index 2 to 3) -> "84352"
"84352" (from index 0 to 2) -> "34852"

Example 2:

Input: s = "34521", t = "23415"


Output: true
Explanation: You can transform s into t using the following sort operations:
"34521" -> "23451"
"23451" -> "23415"

Example 3:

Input: s = "12345", t = "12435"


Output: false

Example 4:

Input: s = "1", t = "2"


Output: false

Constraints:

s.length == t.length
1 <= s.length <= 105
s and t only contain digits from '0' to '9'.
***************************************************************

321. Check If String Is Transformable With Substring Sort


Operations(C++)
***************************************************************

1 // Time: O(n)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 bool isTransformable(string s, string t) {
7 vector> idxs(10);
8 for (int i = size(s) - 1; i >= 0; --i) {
9 idxs[s[i] - '0'].emplace_back(i);
10 }
11 for (const auto& c : t) {
12 int d = c - '0';
13 if (empty(idxs[d])) {
14 return false;
15 }
16 for (int i = 0; i < d; ++i) { // a char can be moved left to the current position if it meets no smaller one
17 if (!empty(idxs[i]) && idxs[i].back() < idxs[d].back()) {
18 return false;
19 }
20 }
21 idxs[d].pop_back();
22 }
23 return true;
24 }
25 };
***************************************************************

321. Check If String Is Transformable With Substring Sort


Operations(Python)
***************************************************************

1 # Time: O(n)
2 # Space: O(n)
3
4 class Solution(object):
5 def isTransformable(self, s, t):
6 """
7 :type s: str
8 :type t: str
9 :rtype: bool
10 """
11 idxs = [[] for _ in xrange(10)]
12 for i in reversed(xrange(len(s))):
13 idxs[int(s[i])].append(i)
14 for c in t:
15 d = int(c)
16 if not idxs[d]:
17 return False
18 for k in xrange(d): # a char can be moved left to the current position if it meets no smaller one
19 if idxs[k] and idxs[k][-1] < idxs[d][-1]:
20 return False
21 idxs[d].pop()
22 return True
******************

322. Strange Printer II


******************

There is a strange printer with the following two special requirements:

On each turn, the printer will print a solid rectangular pattern of a single color on the grid. This will cover up the existing
colors in the rectangle.
Once the printer has used a color for the above operation,the same color cannot be used again.

You are given a m x n matrix targetGrid, where targetGrid[row][col] is the color in the position (row, col) of the grid.

Return true if it is possible to print the matrix targetGrid, otherwise, return false.

Example 1:

Input: targetGrid = [[1,1,1,1],[1,2,2,1],[1,2,2,1],[1,1,1,1]]


Output: true

Example 2:

Input: targetGrid = [[1,1,1,1],[1,1,3,3],[1,1,3,4],[5,5,1,4]]


Output: true

Example 3:

Input: targetGrid = [[1,2,1],[2,1,2],[1,2,1]]


Output: false
Explanation: It is impossible to form targetGrid because it is not allowed to print the same color in different turns.

Example 4:
Input: targetGrid = [[1,1,1],[3,1,3]]
Output: false

Constraints:

m == targetGrid.length
n == targetGrid[i].length
1 <= m, n <= 60
1 <= targetGrid[row][col] <= 60
******************

322. Strange Printer II(C++)


******************

1 // Time: O(c * m * n + e), c is the number of colors


2 // , e is the number of edges in adj, at most O(c^2)
3 // Space: O(e)
4
5 class Solution {
6 public:
7 bool isPrintable(vector>& targetGrid) {
8 unordered_map> boxes;
9 for (int r = 0; r < size(targetGrid); ++r) {
10 for (int c = 0; c < size(targetGrid[r]); ++c) {
11 int color = targetGrid[r][c];
12 if (!boxes.count(color)) {
13 boxes[color] = {r, c, r, c};
14 } else {
15 boxes[color][0] = min(boxes[color][0], r);
16 boxes[color][1] = min(boxes[color][1], c);
17 boxes[color][2] = max(boxes[color][2], r);
18 boxes[color][3] = max(boxes[color][3], c);
19 }
20 }
21 }
22 unordered_map> adj;
23 for (const auto& [color, box] : boxes) {
24 for (int r = box[0]; r <= box[2]; ++r) {
25 for (int c = box[1]; c <= box[3]; ++c) {
26 if (targetGrid[r][c] != color) {
27 adj[color].emplace(targetGrid[r][c]);
28 }
29 }
30 }
31 }
32 unordered_map lookup;
33 for (const auto& [color, _] : boxes) {
34 if (lookup.count(color)) {
35 continue;
36 }
37 if (hasCycle(adj, color, &lookup)) {
38 return false;
39 }
40 }
41 return true;
42 }
43
44 private:
45 enum State {VISITING, VISITED};
46
47 bool hasCycle(const unordered_map>& adj,
48 int color,
49 unordered_map *lookup) {
50 vector> stk = {{1, color}};
51 while (!empty(stk)) {
52 const auto [step, color] = stk.back(); stk.pop_back();
53 if (step == 1) {
54 (*lookup)[color] = VISITING;
55 stk.emplace_back(2, color);
56 if (!adj.count(color)) {
57 continue;
58 }
59 for (const auto& new_color : adj.at(color)) {
60 if (lookup->count(new_color)) {
61 if ((*lookup)[new_color] == VISITED) {
62 continue;
63 }
64 return true; // VISITING
65 }
66 stk.emplace_back(1, new_color);
67 }
68 } else {
69 (*lookup)[color] = VISITED;
70 }
71 }
72 return false;
73 }
74 };
75
76 // Time: O(c * m * n + e), c is the number of colors
77 // , e is the number of edges in adj, at most O(c^2)
78 // Space: O(e)
79 class Solution2 {
80 public:
81 bool isPrintable(vector>& targetGrid) {
82 static const int MAX_COLOR = 60;
83
84 unordered_map> adj;
85 for (int color = 1; color <= MAX_COLOR; ++color) {
86 int min_r = size(targetGrid);
87 int min_c = size(targetGrid[0]);
88 int max_r = -1;
89 int max_c = -1;
90 for (int r = 0; r < size(targetGrid); ++r) {
91 for (int c = 0; c < size(targetGrid[r]); ++c) {
92 if (targetGrid[r][c] == color) {
93 min_r = min(min_r, r);
94 min_c = min(min_c, c);
95 max_r = max(max_r, r);
96 max_c = max(max_c, c);
97 }
98 }
99 }
100 for (int r = min_r; r <= max_r; ++r) {
101 for (int c = min_c; c <= max_c; ++c) {
102 if (targetGrid[r][c] != color) {
103 adj[color].emplace(targetGrid[r][c]);
104 }
105 }
106 }
107 }
108 unordered_map lookup;
109 for (int color = 1; color <= MAX_COLOR; ++color) {
110 if (lookup.count(color)) {
111 continue;
112 }
113 if (hasCycle(adj, color, &lookup)) {
114 return false;
115 }
116 }
117 return true;
118 }
119
120 private:
121 enum State {VISITING, VISITED};
122
123 bool hasCycle(const unordered_map>& adj,
124 int color,
125 unordered_map *lookup) {
126 (*lookup)[color] = VISITING;
127 if (adj.count(color)) {
128 for (const auto& new_color : adj.at(color)) {
129 if ((!lookup->count(new_color) && hasCycle(adj, new_color, lookup)) ||
130 (*lookup)[new_color] == VISITING) {
131 return true;
132 }
133 }
134 }
135 (*lookup)[color] = VISITED;
135 (*lookup)[color] = VISITED;
136 return false;
137 }
138 };
******************

322. Strange Printer II(Python)


******************

1 # Time: O(c * m * n + e), c is the number of colors


2 # , e is the number of edges in adj, at most O(c^2)
3 # Space: O(e)
4
5 import collections
6
7
8 class Solution(object):
9 def isPrintable(self, targetGrid):
10 """
11 :type targetGrid: List[List[int]]
12 :rtype: bool
13 """
14 VISITING, VISITED = range(2)
15 def has_cycle(adj, color, lookup):
16 stk = [(1, color)]
17 while stk:
18 step, color = stk.pop()
19 if step == 1:
20 lookup[color] = VISITING
21 stk.append((2, color))
22 for new_color in adj[color]:
23 if new_color in lookup:
24 if lookup[new_color] == VISITED:
25 continue
26 return True # VISITING
27 stk.append((1, new_color))
28 elif step == 2:
29 lookup[color] = VISITED
30 return False
31
32 boxes = collections.defaultdict(lambda:[len(targetGrid), len(targetGrid[0]), -1, -1])
33 for r, row in enumerate(targetGrid):
34 for c, color in enumerate(row):
35 boxes[color][0] = min(boxes[color][0], r)
36 boxes[color][1] = min(boxes[color][1], c)
37 boxes[color][2] = max(boxes[color][2], r)
38 boxes[color][3] = max(boxes[color][3], c)
39 adj = collections.defaultdict(set)
40 for color, (min_r, min_c, max_r, max_c) in boxes.iteritems():
41 for r in xrange(min_r, max_r+1):
42 for c in xrange(min_c, max_c+1):
43 if targetGrid[r][c] != color:
44 adj[color].add(targetGrid[r][c])
45
46 lookup = {}
47 return all(color in lookup or not has_cycle(adj, color, lookup) for color in boxes.iterkeys())
48
49
50 # Time: O(c * m * n + e), c is the number of colors
51 # , e is the number of edges in adj, at most O(c^2)
52 # Space: O(e)
53 class Solution2(object):
54 def isPrintable(self, targetGrid):
55 """
56 :type targetGrid: List[List[int]]
57 :rtype: bool
58 """
59 VISITING, VISITED = range(2)
60 def has_cycle(adj, color, lookup):
61 lookup[color] = VISITING
62 for new_color in adj[color]:
63 if (new_color not in lookup and has_cycle(adj, new_color, lookup)) or \
64 lookup[new_color] == VISITING:
65 return True
66 lookup[color] = VISITED
67 return False
68
69 MAX_COLOR = 60
70 adj = collections.defaultdict(set)
71 for color in xrange(1, MAX_COLOR+1):
72 min_r = len(targetGrid)
73 min_c = len(targetGrid[0])
74 max_r = -1
75 max_c = -1
76 for r in xrange(len(targetGrid)):
77 for c in xrange(len(targetGrid[r])):
78 if targetGrid[r][c] == color:
79 min_r = min(min_r, r)
80 min_c = min(min_c, c)
81 max_r = max(max_r, r)
82 max_c = max(max_c, c)
83 for r in xrange(min_r, max_r+1):
84 for c in xrange(min_c, max_c+1):
85 if targetGrid[r][c] != color:
86 adj[color].add(targetGrid[r][c])
87
88 lookup = {}
89 return all(color in lookup or not has_cycle(adj, color, lookup) for color in xrange(1, MAX_COLOR+1))
********************************************

323. Minimum Cost to Connect Two Groups of Points


********************************************

You are given two groups of points where the first group hassize1 points, the second group has size2 points, and size1 >= size 2.

The cost of the connection between any two points are given in ansize1 x size 2 matrix where cost[i][j] is the cost of connecting
point i of the first group and point j of the second group. The groups are connected ifeach point in both groups is
connected to one or more points in the opposite group. In other words, each point in the first group must be connected
to at least one point in the second group, and each point in the second group must be connected to at least one point in the
first group.

Return the minimum cost it takes to connect the two groups.

Example 1:

Input: cost = [[15, 96], [36, 2]]


Output: 17
Explanation: The optimal way of connecting the groups is:
1--A
2--B
This results in a total cost of 17.

Example 2:
Input: cost = [[1, 3, 5], [4, 1, 1], [1, 5, 3]]
Output: 4
Explanation: The optimal way of connecting the groups is:
1--A
2--B
2--C
3--A
This results in a total cost of 4.
Note that there are multiple points connected to point 2 in the first group and point A in the second group. This does not matter as there is

Example 3:

Input: cost = [[2, 5, 1], [3, 4, 7], [8, 1, 2], [6, 2, 4], [3, 8, 8]]
Output: 10

Constraints:

size1 == cost.length
size2 == cost[i].length
1 <= size1, size 2 <= 12
size1 >= size 2
0 <= cost[i][j] <= 100
********************************************

323. Minimum Cost to Connect Two Groups of


Points(C++)
********************************************

1 // Time: O(m * n * 2^n)


2 // Space: O(2^n)
3
4 // dp with rolling window
5 class Solution {
6 public:
7 int connectTwoGroups(vector>& cost) {
8 int total = 1 << size(cost[0]);
9 vector> dp(2, vector(total, numeric_limits::max()));
10 dp[0][0] = 0;
11 for (int i = 0; i < size(cost); ++i) {
12 dp[(i + 1) % 2] = vector(total, numeric_limits::max());
13 for (int mask = 0; mask < total; ++mask) {
14 for (int j = 0, base = 1; j < size(cost[0]); ++j, base <<= 1) {
15 if (dp[i % 2][mask] > numeric_limits::max() - cost[i][j]) {
16 continue;
17 }
18 dp[i % 2][mask | base] = min(dp[i % 2][mask | base], cost[i][j] + dp[i % 2][mask]);
19 dp[(i + 1) % 2][mask | base] = min(dp[(i + 1) % 2][mask | base], cost[i][j] + dp[i % 2][mask]);
20 }
21 }
22 }
23 return dp[size(cost) % 2].back();
24 }
25 };
********************************************

323. Minimum Cost to Connect Two Groups of


Points(Python)
********************************************

1 # Time: O(m * n * 2^n)


2 # Space: O(2^n)
3
4 # dp with rolling window
5 class Solution(object):
6 def connectTwoGroups(self, cost):
7 """
8 :type cost: List[List[int]]
9 :rtype: int
10 """
11 total = 2**len(cost[0])
12 dp = [[float("inf")]*total for _ in xrange(2)]
13 dp[0][0] = 0
14 for i in xrange(len(cost)):
15 dp[(i+1)%2] = [float("inf")]*total
16 for mask in xrange(total):
17 base = 1
18 for j in xrange(len(cost[0])):
19 dp[i%2][mask|base] = min(dp[i%2][mask|base], cost[i][j]+dp[i%2][mask])
20 dp[(i+1)%2][mask|base] = min(dp[(i+1)%2][mask|base], cost[i][j]+dp[i%2][mask])
21 base <<= 1
22 return dp[len(cost)%2][-1]
**********************************************

324. Maximum Number of Achievable Transfer Requests


**********************************************

We have n buildings numbered from 0 to n - 1. Each building has a number of employees. It's transfer season, and some
employees want to change the building they reside in.

You are given an array requests where requests[i] = [from i, to i] represents an employee's request to transfer from buildingfromi to
building toi.

All buildings are full, so a list of requests is achievable only if for each building, thenet change in employee transfers is
zero. This means the number of employeesleaving is equal to the number of employees moving in. For example if n = 3
and two employees are leaving building 0, one is leaving building 1, and one is leaving building 2, there should be two
employees moving to building 0, one employee moving to building 1, and one employee moving to building 2.

Return the maximum number of achievable requests.

Example 1:

Input: n = 5, requests = [[0,1],[1,0],[0,1],[1,2],[2,0],[3,4]]


Output: 5
Explantion: Let's see the requests:
From building 0 we have employees x and y and both want to move to building 1.
From building 1 we have employees a and b and they want to move to buildings 2 and 0 respectively.
From building 2 we have employee z and they want to move to building 0.
From building 3 we have employee c and they want to move to building 4.
From building 4 we don't have any requests.
We can achieve the requests of users x and b by swapping their places.
We can achieve the requests of users y, a and z by swapping the places in the 3 buildings.

Example 2:
Input: n = 3, requests = [[0,0],[1,2],[2,1]]
Output: 3
Explantion: Let's see the requests:
From building 0 we have employee x and they want to stay in the same building 0.
From building 1 we have employee y and they want to move to building 2.
From building 2 we have employee z and they want to move to building 1.
We can achieve all the requests.

Example 3:

Input: n = 4, requests = [[0,3],[3,1],[1,2],[2,0]]


Output: 4

Constraints:

1 <= n <= 20
1 <= requests.length <= 16
requests[i].length == 2
0 <= from i, to i < n
**********************************************

324. Maximum Number of Achievable Transfer


Requests(C++)
**********************************************

1 // Time: O((n + r) * 2^r)


2 // Space: O(n + r)
3
4 // early return solution
5 class Solution {
6 public:
7 int maximumRequests(int n, vector>& requests) {
8 const auto& check =
9 [&n, &requests](const auto& idx) {
10 vector change(n);
11 for (const auto& i : idx) {
12 --change[requests[i][0]];
13 ++change[requests[i][1]];
14 }
15 return all_of(cbegin(change), cend(change),
16 [](const auto& x) {
17 return x == 0;
18 });
19 };
20
21 for (int k = size(requests); k > 0; --k) {
22 if (combinations(size(requests), k, check)) {
23 return k; // early return
24 }
25 }
26 return 0;
27 }
28
29 private:
30 bool combinations(int n, int k, const function&)>& callback) {
31 static const auto& next_pos =
32 [](const auto& n, const auto& k, const auto& idxs) {
33 int i = k - 1;
34 for (; i >= 0; --i) {
35 if (idxs[i] != i + n - k) {
36 break;
37 }
38 }
39 return i;
40 };
41
42 vector idxs(k);
43 iota(begin(idxs), end(idxs), 0);
44 if (callback(idxs)) {
45 return true;
46 }
47 for (int i; (i = next_pos(n, k, idxs)) >= 0;) {
48 ++idxs[i];
49 for (int j = i + 1; j < k; ++j) {
50 idxs[j] = idxs[j - 1] + 1;
51 }
52 if (callback(idxs)) {
53 return true;
54 }
55 }
56 return false;
57 }
58 };
59
60 // Time: O((n + r) * 2^r)
60
61 // Space: O(n + r)
62 // full search solution (much slower)
63 class Solution2 {
64 public:
65 int maximumRequests(int n, vector>& requests) {
66 const auto& evaluate =
67 [&n, &requests](const auto& mask) {
68 vector change(n);
69 int count = 0;
70 for (int i = 0, base = 1; i < size(requests); ++i, base <<= 1) {
71 if (base & mask) {
72 --change[requests[i][0]];
73 ++change[requests[i][1]];
74 ++count;
75 }
76 }
77 return all_of(cbegin(change), cend(change),
78 [](const auto& x) {
79 return x == 0;
80 }) ? count : 0;
81 };
82
83 const auto& total = 1 << size(requests);
84 int result = 0;
85 for (int mask = 0; mask < total; ++mask) {
86 result = max(result, evaluate(mask));
87 }
88 return result;
89 }
90 };
**********************************************

324. Maximum Number of Achievable Transfer


Requests(Python)
**********************************************

1 # Time: O((n + r) * 2^r)


2 # Space: O(n + r)
3
4 import itertools
5
6
7 # early return solution
8 class Solution(object):
9 def maximumRequests(self, n, requests):
10 """
11 :type n: int
12 :type requests: List[List[int]]
13 :rtype: int
14 """
15 for k in reversed(xrange(1, len(requests)+1)):
16 for c in itertools.combinations(xrange(len(requests)), k):
17 change = [0]*n
18 for i in c:
19 change[requests[i][0]] -= 1
20 change[requests[i][1]] += 1
21 if all(c == 0 for c in change):
22 return k # early return
23 return 0
24
25
26 # Time: O((n + r) * 2^r)
27 # Space: O(n + r)
28 # full search solution (much slower)
29 class Solution2(object):
30 def maximumRequests(self, n, requests):
31 """
32 :type n: int
33 :type requests: List[List[int]]
34 :rtype: int
35 """
36 def evaluate(n, requests, mask):
37 change = [0]*n
38 base, count = 1, 0
39 for i in xrange(len(requests)):
40 if base & mask:
41 change[requests[i][0]] -= 1
42 change[requests[i][1]] += 1
43 count += 1
44 base <<= 1
45 return count if all(c == 0 for c in change) else 0
46
47 return max(evaluate(n, requests, i) for i in xrange(1 << len(requests)))
*************************************************

325. Find Servers That Handled Most Number of


Requests
*************************************************

You have k servers numbered from 0 to k-1 that are being used to handle multiple requests simultaneously. Each server has
infinite computational capacity but cannot handle more than one request at a time. The requests are assigned to servers
according to a specific algorithm:

The ith (0-indexed) request arrives.


If all servers are busy, the request is dropped (not handled at all).
If the (i % k) th server is available, assign the request to that server.
Otherwise, assign the request to the next available server (wrapping around the list of servers and starting from 0 if
necessary). For example, if the ith server is busy, try to assign the request to the(i+1)th server, then the (i+2)th server,
and so on.

You are given a strictly increasing array arrival of positive integers, where arrival[i] represents the arrival time of the ith
request, and another array load , where load[i] represents the load of the ith request (the time it takes to complete). Your goal is
to find the busiest server(s). A server is considered busiest if it handled the most number of requests successfully among
all the servers.

Return a list containing the IDs (0-indexed) of the busiest server(s). You may return the IDs in any order.

Example 1:

Input: k = 3, arrival = [1,2,3,4,5], load = [5,2,3,3,3]


Output: [1]
Explanation:
All of the servers start out available.
The first 3 requests are handled by the first 3 servers in order.
Request 3 comes in. Server 0 is busy, so it's assigned to the next available server, which is 1.
Request 4 comes in. It cannot be handled since all servers are busy, so it is dropped.
Servers 0 and 2 handled one request each, while server 1 handled two requests. Hence server 1 is the busiest server.

Example 2:

Input: k = 3, arrival = [1,2,3,4], load = [1,2,1,2]


Output: [0]
Explanation:
The first 3 requests are handled by first 3 servers.
Request 3 comes in. It is handled by server 0 since the server is available.
Server 0 handled two requests, while servers 1 and 2 handled one request each. Hence server 0 is the busiest server.

Example 3:
Input: k = 3, arrival = [1,2,3], load = [10,12,11]
Output: [0,1,2]
Explanation: Each server handles a single request, so they are all considered the busiest.

Example 4:

Input: k = 3, arrival = [1,2,3,4,8,9,10], load = [5,2,10,3,1,2,2]


Output: [1]

Example 5:

Input: k = 1, arrival = [1], load = [1]


Output: [0]

Constraints:

1 <= k <= 10 5
1 <= arrival.length, load.length <= 10 5
arrival.length == load.length
1 <= arrival[i], load[i] <= 10 9
arrival is strictly increasing.
*************************************************

325. Find Servers That Handled Most Number of


Requests(C++)
*************************************************

1 // Time: O(nlogk)
2 // Space: O(k)
3
4 class Solution {
5 public:
6 vector busiestServers(int k, vector& arrival, vector& load) {
7 priority_queue, vector>, greater>> min_heap_of_endtimes;
8 priority_queue, greater> min_heap_of_nodes_after_curr;
9 priority_queue, greater> min_heap_of_nodes_before_curr;
10 for (int i = 0; i < k; ++i) {
11 min_heap_of_nodes_before_curr.emplace(i);
12 }
13 vector count(k);
14 for (int i = 0; i < size(arrival); ++i) {
15 if (i % k == 0) {
16 min_heap_of_nodes_after_curr = move(min_heap_of_nodes_before_curr);
17 }
18 while (!empty(min_heap_of_endtimes) && min_heap_of_endtimes.top().first <= arrival[i]) {
19 const auto [_, free] = min_heap_of_endtimes.top(); min_heap_of_endtimes.pop();
20 if (free < i % k) {
21 min_heap_of_nodes_before_curr.emplace(free);
22 } else {
23 min_heap_of_nodes_after_curr.emplace(free);
24 }
25 }
26 auto& min_heap_of_candidates = !empty(min_heap_of_nodes_after_curr) ? min_heap_of_nodes_after_curr : min_heap_of_nodes_befo
27 if (empty(min_heap_of_candidates)) {
28 continue;
29 }
30 const auto node = min_heap_of_candidates.top(); min_heap_of_candidates.pop();
31 ++count[node];
32 min_heap_of_endtimes.emplace(arrival[i] + load[i], node);
33 }
34 int max_count = *max_element(cbegin(count), cend(count));
35 vector result;
36 for (int i = 0; i < k; ++i) {
37 if (count[i] == max_count) {
38 result.emplace_back(i);
39 }
40 }
41 return result;
42 }
43 };
44
45 // Time: O(nlogk)
46 // Space: O(k)
47 class Solution2 {
48 public:
49 vector busiestServers(int k, vector& arrival, vector& load) {
50 priority_queue, vector>, greater>> min_heap_of_endtimes;
51 set availables;
52 for (int i = 0; i < k; ++i) {
53 availables.emplace(i);
54 }
55 vector count(k);
56 for (int i = 0; i < size(arrival); ++i) {
57 while (!empty(min_heap_of_endtimes) && min_heap_of_endtimes.top().first <= arrival[i]) {
58 const auto [_, free] = min_heap_of_endtimes.top(); min_heap_of_endtimes.pop();
59 availables.emplace(free);
60 }
60
61 if (empty(availables)) {
62 continue;
63 }
64 auto it = availables.lower_bound(i % k);
65 if (it == end(availables)) {
66 it = begin(availables);
67 }
68 ++count[*it];
69 min_heap_of_endtimes.emplace(arrival[i] + load[i], *it);
70 availables.erase(it);
71 }
72 int max_count = *max_element(cbegin(count), cend(count));
73 vector result;
74 for (int i = 0; i < k; ++i) {
75 if (count[i] == max_count) {
76 result.emplace_back(i);
77 }
78 }
79 return result;
80 }
81 };
*************************************************

325. Find Servers That Handled Most Number of


Requests(Python)
*************************************************
1 # Time: O(nlogk)
2 # Space: O(k)
3
4 import itertools
5 import heapq
6
7
8 class Solution(object):
9 def busiestServers(self, k, arrival, load):
10 """
11 :type k: int
12 :type arrival: List[int]
13 :type load: List[int]
14 :rtype: List[int]
15 """
16 count = [0]*k
17 min_heap_of_endtimes = []
18 min_heap_of_nodes_after_curr = []
19 min_heap_of_nodes_before_curr = range(k)
20 for i, (t, l) in enumerate(itertools.izip(arrival, load)):
21 if i % k == 0:
22 min_heap_of_nodes_before_curr, min_heap_of_nodes_after_curr = [], min_heap_of_nodes_before_curr
23 while min_heap_of_endtimes and min_heap_of_endtimes[0][0] <= t:
24 _, free = heapq.heappop(min_heap_of_endtimes)
25 if free < i % k:
26 heapq.heappush(min_heap_of_nodes_before_curr, free)
27 else:
28 heapq.heappush(min_heap_of_nodes_after_curr, free)
29 min_heap_of_candidates = min_heap_of_nodes_after_curr if min_heap_of_nodes_after_curr else min_heap_of_nodes_before_curr
30 if not min_heap_of_candidates:
31 continue
32 node = heapq.heappop(min_heap_of_candidates)
33 count[node] += 1
34 heapq.heappush(min_heap_of_endtimes, (t+l, node))
35 max_count = max(count)
36 return [i for i in xrange(k) if count[i] == max_count]
37
38
39 # Time: O(nlogk)
40 # Space: O(k)
41 import sortedcontainers # required to do pip install
42 import itertools
43 import heapq
44
45
46 # reference: http://www.grantjenks.com/docs/sortedcontainers/sortedlist.html
47 class Solution2(object):
48 def busiestServers(self, k, arrival, load):
49 """
50 :type k: int
51 :type arrival: List[int]
52 :type load: List[int]
53 :rtype: List[int]
54 """
55 count = [0]*k
56 min_heap_of_endtimes = []
57 availables = sortedcontainers.SortedList(xrange(k)) # O(klogk)
58 for i, (t, l) in enumerate(itertools.izip(arrival, load)):
59 while min_heap_of_endtimes and min_heap_of_endtimes[0][0] <= t:
60 _, free = heapq.heappop(min_heap_of_endtimes) # O(logk)
61 availables.add(free) # O(logk)
62 if not availables:
63 continue
64 idx = availables.bisect_left(i % k) % len(availables) # O(logk)
65 node = availables.pop(idx) # O(logk)
66 count[node] += 1
67 heapq.heappush(min_heap_of_endtimes, (t+l, node)) # O(logk)
68 max_count = max(count)
69 return [i for i in xrange(k) if count[i] == max_count]
********************************

326. Maximum Number of Visible Points


********************************

You are given an array points, an integer angle, and your location, where location = [pos x, pos y] and points[i] = [x i, y i] both denote
integral coordinates on the X-Y plane.

Initially, you are facing directly east from your position. Youcannot move from your position, but you can rotate. In other
words, posx and posy cannot be changed. Your field of view indegrees is represented by angle, determining how wide you can
see from any given view direction. Let d be the amount in degrees that you rotate counterclockwise. Then, your field of view
is the inclusive range of angles [d - angle/2, d + angle/2] .

Your browser does not support the video tag or this video format.

You can see some set of points if, for each point, theangle formed by the point, your position, and the immediate east
direction from your position is in your field of view.

There can be multiple points at one coordinate. There may be points at your location, and you can always see these points
regardless of your rotation. Points do not obstruct your vision to other points.

Return the maximum number of points you can see.

Example 1:

Input: points = [[2,1],[2,2],[3,3]], angle = 90, location = [1,1]


Output: 3
Explanation: The shaded region represents your field of view. All points can be made visible in your field of view, including [3,3] even thou

Example 2:

Input: points = [[2,1],[2,2],[3,4],[1,1]], angle = 90, location = [1,1]


Output: 4
Explanation: All points can be made visible in your field of view, including the one at your location.

Example 3:
Input: points = [[1,0],[2,1]], angle = 13, location = [1,1]
Output: 1
Explanation: You can only see one of the two points, as shown above.

Constraints:

1 <= points.length <= 10 5


points[i].length == 2
location.length == 2
0 <= angle < 360
0 <= pos x, pos y, x i, y i <= 100
********************************

326. Maximum Number of Visible Points(C++)


********************************

1 // Time: O(nlogn)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 int visiblePoints(vector>& points, int angle, vector& location) {
7 static const double PI = atan2(0, -1);
8
9 vector arr;
10 int extra = 0;
11 for (const auto& p : points) {
12 if (p == location) {
13 ++extra;
14 continue;
15 }
16 arr.emplace_back(atan2(p[1] - location[1], p[0] - location[0]));
17 }
18 sort(begin(arr), end(arr));
19 const int n = size(arr);
20 for (int i = 0; i < n; ++i) { // make it circular
21 arr.emplace_back(arr[i] + 2.0 * PI);
22 }
23 const double d = 2.0 * PI * (angle / 360.0);
24 int result = 0;
25 for (int left = 0, right = 0; right < size(arr); ++right) {
26 while (arr[right] - arr[left] > d) {
27 ++left;
28 }
29 result = max(result, right - left + 1);
30 }
31 return result + extra;
32 }
33 };
********************************

326. Maximum Number of Visible Points(Python)


********************************

1 # Time: O(nlogn)
2 # Space: O(n)
3
4 import math
5
6
7 class Solution(object):
8 def visiblePoints(self, points, angle, location):
9 """
10 :type points: List[List[int]]
11 :type angle: int
12 :type location: List[int]
13 :rtype: int
14 """
15 arr, extra = [], 0
16 for p in points:
17 if p == location:
18 extra += 1
19 continue
20 arr.append(math.atan2(p[1]-location[1], p[0]-location[0]))
21 arr.sort()
22 arr.extend([x + 2.0*math.pi for x in arr]) # make it circular
23 d = 2.0*math.pi * (angle/360.0)
24 left = result = 0
25 for right in xrange(len(arr)):
26 while arr[right]-arr[left] > d:
27 left += 1
28 result = max(result, right-left+1)
29 return result + extra
************************************************

327. Minimum One Bit Operations to Make Integers Zero


************************************************

Given an integer n, you must transform it into 0 using the following operations any number of times:

Change the rightmost (0th) bit in the binary representation of n.


Change the ith bit in the binary representation of n if the (i-1) th bit is set to 1 and the (i-2) th through 0th bits are set to 0.

Return the minimum number of operations to transformn into 0.

Example 1:

Input: n = 0
Output: 0

Example 2:

Input: n = 3
Output: 2
Explanation: The binary representation of 3 is "11".
"11" -> "01" with the 2nd operation since the 0th bit is 1.
"01" -> "00" with the 1st operation.

Example 3:

Input: n = 6
Output: 4
Explanation: The binary representation of 6 is "110".
"110" -> "010" with the 2nd operation since the 1st bit is 1 and 0th through 0th bits are 0.
"010" -> "011" with the 1st operation.
"011" -> "001" with the 2nd operation since the 0th bit is 1.
"001" -> "000" with the 1st operation.

Example 4:

Input: n = 9
Output: 14

Example 5:

Input: n = 333
Output: 393

Constraints:

0 <= n <= 10 9
************************************************

327. Minimum One Bit Operations to Make Integers


Zero(C++)
************************************************
1 // Time: O(logn)
2 // Space: O(1)
3
4 // reference: https://en.wikipedia.org/wiki/Gray_code
5 class Solution {
6 public:
7 int minimumOneBitOperations(int n) {
8 // [observation]
9 // n f(n)
10 // 000 0
11 // 001 1
12 // 011 2
13 // 010 3
14 // 110 4
15 // 111 5
16 // 101 6
17 // 100 7
18 // f(0XX...X) + f(1XX...X) = f(100...0) implies n is a gray code
19 // => f(n) is actually the inverse of gray code
20 return gray_to_binary(n);
21 }
22
23 private:
24 int gray_to_binary(int n) {
25 int result = 0;
26 for (; n > 0; n >>= 1) {
27 result ^= n;
28 }
29 return result;
30 }
31 };
32
33 // Time: O(logn)
34 // Space: O(1)
35 class Solution2 {
36 public:
37 int minimumOneBitOperations(int n) {
38 // [observation1]:
39 // f(1) = 1
40 // f(10) = 2 * f(1) + 1 = 3
41 // f(100) = 2 * f(10) + 1 = 7
42 // by mathematical induction
43 // => f(2^k) = 2^(k+1)-1
44 //
45 // [observation2]:
46 // n f(n)
47 // 000 0
48 // 001 1
49 // 011 2
50 // 010 3
51 // 110 4
52 // 111 5
53 // 101 6
54 // 100 7
55 // let pos be an array of positions where the bit is 1 in ascending order:
56 // f(0XX...X) + f(1XX...X) = f(100...0)
57 // f(1XX...X) = f(100...0) - f(0XX...X)
58 // = (2^(pos[k-1]+1)-1) - f(0XX...X)
59 // by mathematical induction
60 // => f(n) = (2^(pos[k-1]+1)-1) - (2^(pos[k-2])+1) + ... + (-1)^(k-1) * (2^(pos[0]+1)-1)
61 int result = 0;
62 for (; n > 0; n &= n - 1) {
63 result = -(result + (n ^ (n - 1)));
64 }
65 return abs(result);
66 }
67 };
************************************************

327. Minimum One Bit Operations to Make Integers


Zero(Python)
************************************************
1 # Time: O(logn)
2 # Space: O(1)
3
4 # reference: https://en.wikipedia.org/wiki/Gray_code
5 class Solution(object):
6 def minimumOneBitOperations(self, n):
7 """
8 :type n: int
9 :rtype: int
10 """
11 def gray_to_binary(n):
12 result = 0
13 while n:
14 result ^= n
15 n >>= 1
16 return result
17
18 # [observation]
19 # n f(n)
20 # 000 0
21 # 001 1
22 # 011 2
23 # 010 3
24 # 110 4
25 # 111 5
26 # 101 6
27 # 100 7
28 # f(0XX...X) + f(1XX...X) = f(100...0) implies n is a gray code
29 # => f(n) is actually the inverse of gray code
30 return gray_to_binary(n)
31
32
33 # Time: O(logn)
34 # Space: O(1)
35 class Solution2(object):
36 def minimumOneBitOperations(self, n):
37 """
38 :type n: int
39 :rtype: int
40 """
41 # [observation1]:
42 # f(1) = 1
43 # f(10) = 2 * f(1) + 1 = 3
44 # f(100) = 2 * f(10) + 1 = 7
45 # by mathematical induction
46 # => f(2^k) = 2^(k+1)-1
47 #
48 # [observation2]
49 # n f(n)
50 # 000 0
51 # 001 1
52 # 011 2
53 # 010 3
54 # 110 4
55 # 111 5
56 # 101 6
57 # 100 7
58 # let pos be an array of positions where the bit is 1 in ascending order:
59 # f(0XX...X) + f(1XX...X) = f(100...0)
60 # f(1XX...X) = f(100...0) - f(0XX...X)
61 # = (2^(pos[k-1]+1)-1) - f(0XX...X)
62 # by mathematical induction
63 # => f(n) = (2^(pos[k-1]+1)-1) - (2^(pos[k-2])+1) + ... + (-1)^(k-1) * (2^(pos[0]+1)-1)
64 result = 0
65 while n:
66 result = -result - (n^(n-1)) # 2^(pos[i]+1)-1
67 n &= n-1
68 return abs(result)
***********************************************

328. Count Subtrees With Max Distance Between Cities


***********************************************

There are n cities numbered from 1 to n. You are given an array edges of size n-1, where edges[i] = [u i, v i] represents a
bidirectional edge between cities ui and v i. There exists a unique path between each pair of cities. In other words, the cities
form a tree.

A subtree is a subset of cities where every city is reachable from every other city in the subset, where the path between
each pair passes through only the cities from the subset. Two subtrees are different if there is a city in one subtree that is
not present in the other.

For each d from 1 to n-1, find the number of subtrees in which themaximum distance between any two cities in the subtree
is equal to d.

Return an array of size n-1 where the dth element (1-indexed) is the number of subtrees in which themaximum distance
between any two cities is equal to d.

Notice that the distance between the two cities is the number of edges in the path between them.

Example 1:

Input: n = 4, edges = [[1,2],[2,3],[2,4]]


Output: [3,4,0]
Explanation:
The subtrees with subsets {1,2}, {2,3} and {2,4} have a max distance of 1.
The subtrees with subsets {1,2,3}, {1,2,4}, {2,3,4} and {1,2,3,4} have a max distance of 2.
No subtree has two nodes where the max distance between them is 3.

Example 2:

Input: n = 2, edges = [[1,2]]


Output: [1]

Example 3:

Input: n = 3, edges = [[1,2],[2,3]]


Output: [2,1]

Constraints:

2 <= n <= 15
edges.length == n-1
edges[i].length == 2
1 <= ui, v i <= n
All pairs (u i, v i) are distinct.
***********************************************

328. Count Subtrees With Max Distance Between


Cities(C++)
***********************************************

1 // Time: O(n^6)
2 // Space: O(n^3)
3
4 class Solution {
5 public:
6 vector countSubgraphsForEachDiameter(int n, vector>& edges) {
7 vector> adj(n);
8 for (const auto& edge : edges) {
9 int u = edge[0] - 1, v = edge[1] - 1;
10 adj[u].emplace_back(v);
11 adj[v].emplace_back(u);
12 }
13 vector lookup(n), result(n - 1);
14 for (int i = 0; i < n; ++i) { // Time: sum(O(k^5) for k in [1, n]) = O(n^6)
15 vector>> dp(n, vector>(n, vector(n)));
16 vector count(n, 1);
17 dfs(n, adj, i, -1, lookup, &count, &dp); // Time: O(k^5), k is the number of the remaining cities
18 lookup[i] = 1;
19 for (int d = 1; d < n; ++d) { // for each depth from city i
20 for (int max_d = d; max_d < min(2 * d + 1, n); ++max_d) { // for each max distance
21 result[max_d - 1] += dp[i][d][max_d];
22 }
23 }
24 }
25 return result;
26 }
27
28 private:
29 void dfs(int n, const vector>& adj,
30 int curr, int parent,
31 const vector& lookup,
32 vector *count,
33 vector>> *dp) {
34
35 for (const auto& child : adj[curr]) {
36 if (child == parent || lookup[child]) {
37 continue;
38 }
39 dfs(n, adj, child, curr, lookup, count, dp);
40 }
41 (*dp)[curr][0][0] = 1;
42 for (const auto& child : adj[curr]) {
43 if (child == parent || lookup[child]) {
44 continue;
45 }
46 vector> new_dp_curr = (*dp)[curr];
47 for (int curr_d = 0; curr_d < (*count)[curr]; ++curr_d) {
48 for (int curr_max_d = curr_d; curr_max_d < min(2 * curr_d + 1, (*count)[curr]); ++curr_max_d) {
49 if (!(*dp)[curr][curr_d][curr_max_d]) { // pruning
50 continue;
51 }
52 for (int child_d = 0; child_d < (*count)[child]; ++child_d) {
53 for (int child_max_d = child_d; child_max_d < min(2 * child_d + 1, (*count)[child]); ++child_max_d) {
54 new_dp_curr[max(curr_d, child_d + 1)][max({curr_max_d, child_max_d, curr_d + child_d + 1})] +=
55 (*dp)[curr][curr_d][curr_max_d] * (*dp)[child][child_d][child_max_d]; // count subtrees with new chil
56 }
57 }
58 }
59 }
60 (*count)[curr] += (*count)[child]; // merge new child
60
61 (*dp)[curr] = move(new_dp_curr);
62 }
63 }
64 };
65
66 // Time: O(n * 2^n)
67 // Space: O(n)
68 class Solution2 {
69 public:
70 vector countSubgraphsForEachDiameter(int n, vector>& edges) {
71 vector> adj(n);
72 for (const auto& edge : edges) {
73 int u = edge[0] - 1, v = edge[1] - 1;
74 adj[u].emplace_back(v);
75 adj[v].emplace_back(u);
76 }
77 vector result(n - 1);
78 int total = 1 << n;
79 for (int mask = 1; mask < total; ++mask) {
80 int max_d = maxDistance(n, edges, adj, mask);
81 if (max_d - 1 >= 0) {
82 ++result[max_d - 1];
83 }
84 }
85 return result;
86 }
87
88 private:
89 int maxDistance(int n,
90 const vector>& edges,
91 const vector>& adj,
92 int mask) {
93 const auto& [is_valid, farthest, max_d] = bfs(n, adj, mask, log(mask & -mask) / log(2));
94 return is_valid ? get<2>(bfs(n, adj, mask, farthest)) : 0;
95 }
96
97 tuple bfs(int n, const vector>& adj,
98 int mask, int start) {
99 queue> q({{start, 0}});
100 int lookup = (1 << start);
101 int count = __builtin_popcount(mask) - 1, u = -1, d = -1;
102 while (!empty(q)) {
103 tie(u, d) = move(q.front()); q.pop();
104 for (const auto& v : adj[u]) {
105 if (!(mask & (1 << v)) || (lookup & (1 << v))) {
106 continue;
107 }
108 lookup |= (1 << v);
109 --count;
110 q.emplace(v, d + 1);
111 }
112 }
113 return {count == 0, u, d};
114 }
115 };
***********************************************

328. Count Subtrees With Max Distance Between


Cities(Python)
***********************************************

1 # Time: O(n^6)
2 # Space: O(n^3)
3
4 import collections
5
6
7 class Solution(object):
8 def countSubgraphsForEachDiameter(self, n, edges):
9 """
10 :type n: int
11 :type edges: List[List[int]]
12 :rtype: List[int]
13 """
14 def dfs(n, adj, curr, parent, lookup, count, dp):
15 for child in adj[curr]:
16 if child == parent or lookup[child]:
17 continue
18 dfs(n, adj, child, curr, lookup, count, dp)
19 dp[curr][0][0] = 1
20 for child in adj[curr]:
21 if child == parent or lookup[child]:
22 continue
23 new_dp_curr = [row[:] for row in dp[curr]]
24 for curr_d in xrange(count[curr]):
25 for curr_max_d in xrange(curr_d, min(2*curr_d+1, count[curr])):
26 if not dp[curr][curr_d][curr_max_d]: # pruning
27 continue
28 for child_d in xrange(count[child]):
29 for child_max_d in xrange(child_d, min(2*child_d+1, count[child])):
30 new_dp_curr[max(curr_d, child_d+1)][max(curr_max_d, child_max_d, curr_d+child_d+1)] += \
31 dp[curr][curr_d][curr_max_d]*dp[child][child_d][child_max_d] # count subtrees with new child
32 count[curr] += count[child] # merge new child
33 dp[curr] = new_dp_curr
34
35 adj = collections.defaultdict(list)
36 for u, v in edges:
37 u -= 1
38 v -= 1
39 adj[u].append(v)
40 adj[v].append(u)
41 lookup, result = [0]*n, [0]*(n-1)
42 for i in xrange(n): # Time: sum(O(k^5) for k in [1, n]) = O(n^6)
43 dp = [[[0]*n for _ in xrange(n)] for _ in xrange(n)]
44 count = [1]*n
45 dfs(n, adj, i, -1, lookup, count, dp) # Time: O(k^5), k is the number of the remaining cities
46 lookup[i] = 1
47 for d in xrange(1, n): # for each depth from city i
48 for max_d in xrange(d, min(2*d+1, n)): # for each max distance
49 result[max_d-1] += dp[i][d][max_d]
50 return result
51
52
53 # Time: O(n * 2^n)
54 # Space: O(n)
55 import collections
56 import math
57
58
59 class Solution2(object):
60 def countSubgraphsForEachDiameter(self, n, edges):
60
61 """
62 :type n: int
63 :type edges: List[List[int]]
64 :rtype: List[int]
65 """
66 def popcount(mask):
67 count = 0
68 while mask:
69 mask &= mask-1
70 count += 1
71 return count
72
73 def bfs(adj, mask, start):
74 q = collections.deque([(start, 0)])
75 lookup = 1<= 0:
76 result[max_d-1] += 1
77 return result
78
**************

329. Fancy Sequence


**************

Write an API that generates fancy sequences using theappend, addAll, and multAll operations.

Implement the Fancy class:

Fancy() Initializes the object with an empty sequence.


void append(val) Appends an integer val to the end of the sequence.
void addAll(inc) Increments all existing values in the sequence by an integerinc .
void multAll(m) Multiplies all existing values in the sequence by an integerm.
Gets the current value at index idx (0-indexed) of the sequence modulo 109 + 7 . If the index is greater or
int getIndex(idx)
equal than the length of the sequence, return -1.

Example 1:

Input
["Fancy", "append", "addAll", "append", "multAll", "getIndex", "addAll", "append", "multAll", "getIndex", "getIndex", "getIndex"]
[[], [2], [3], [7], [2], [0], [3], [10], [2], [0], [1], [2]]
Output
[null, null, null, null, null, 10, null, null, null, 26, 34, 20]

Explanation
Fancy fancy = new Fancy();
fancy.append(2); // fancy sequence: [2]
fancy.addAll(3); // fancy sequence: [2+3] -> [5]
fancy.append(7); // fancy sequence: [5, 7]
fancy.multAll(2); // fancy sequence: [5*2, 7*2] -> [10, 14]
fancy.getIndex(0); // return 10
fancy.addAll(3); // fancy sequence: [10+3, 14+3] -> [13, 17]
fancy.append(10); // fancy sequence: [13, 17, 10]
fancy.multAll(2); // fancy sequence: [13*2, 17*2, 10*2] -> [26, 34, 20]
fancy.getIndex(0); // return 26
fancy.getIndex(1); // return 34
fancy.getIndex(2); // return 20

Constraints:

1 <= val, inc, m <= 100


0 <= idx <= 10 5
At most 105 calls total will be made to append, addAll, multAll, and getIndex.
**************

329. Fancy Sequence(C++)


**************

1 // Time: O(1)
2 // Space: O(n)
3
4 // #define USE_UINT64_T
5
6 class Fancy {
7 public:
8 Fancy() : ops_{{1, 0}} {
9
10 }
11
12 void append(int val) {
13 arr_.emplace_back(val);
14 ops_.emplace_back(ops_.back());
15 }
16
17 void addAll(int inc) {
18 ops_.back().second = addmod(ops_.back().second, inc, MOD);
19 }
20
21 void multAll(int m) {
22 ops_.back().first = mulmod(ops_.back().first, m, MOD);
23 ops_.back().second = mulmod(ops_.back().second, m, MOD);
24 }
25
26 int getIndex(int idx) {
27 if (idx >= size(arr_)) {
28 return -1;
29 }
30 const auto& [a1, b1] = ops_[idx];
31 const auto& [a2, b2] = ops_.back();
32 int a = mulmod(a2, powmod(a1, MOD - 2, MOD), MOD);
33 int b = submod(b2, mulmod(a, b1, MOD), MOD);
34 return addmod(mulmod(arr_[idx], a, MOD), b, MOD);
35 }
36
37 private:
38 uint32_t addmod(uint32_t a, uint32_t b, uint32_t mod) { // avoid overflow
39 // a %= mod, b %= mod; // assumed a, b have been mod
40 if (mod - a <= b) {
41 b -= mod; // relied on unsigned integer overflow in order to give the expected results
42 }
43 return a + b;
44 }
45
46 uint32_t submod(uint32_t a, uint32_t b, uint32_t mod) {
47 // a %= mod, b %= mod; // assumed a, b have been mod
48 return addmod(a, mod - b, mod);
49 }
50
51 // reference: https://stackoverflow.com/questions/12168348/ways-to-do-modulo-multiplication-with-primitive-types
52 uint32_t mulmod(uint32_t a, uint32_t b, uint32_t mod) { // avoid overflow
53 #ifdef USE_UINT64_T
54 return uint64_t(a) * b % mod; // speed up if we can use uint64_t
55 #else
56 uint32_t result = 0;
57 if (a < b) {
58 swap(a, b);
59 }
60 while (b > 0) {
61 if (b % 2 == 1) {
62 result = addmod(result, a, mod);
63 }
64 a = addmod(a, a, mod);
65 b /= 2;
66 }
67 return result;
68 #endif
69 }
70
71 uint32_t powmod(uint32_t a, uint32_t b, uint32_t mod) {
72 a %= mod;
73 uint64_t result = 1;
74 while (b) {
75 if (b & 1) {
76 result = mulmod(result, a, mod);
77 }
78 a = mulmod(a, a, mod);
79 b >>= 1;
80 }
81 return result;
82 }
83
84 static const int MOD = 1e9 + 7;
85 vector arr_;
86 vector> ops_;
87 };
88
89 // Time: O(1)
90 // Space: O(n)
91 class Fancy2 {
92 public:
93 Fancy2() : op_{1, 0} {
94
95 }
96
97 void append(int val) {
98 arr_.emplace_back(mulmod(submod(val, op_.second, MOD), powmod(op_.first, MOD - 2, MOD), MOD));
99 }
100
101 void addAll(int inc) {
102 op_.second = addmod(op_.second, inc, MOD);
103 }
104
105 void multAll(int m) {
106 op_.first = mulmod(op_.first, m, MOD);
107 op_.second = mulmod(op_.second, m, MOD);
108 }
109
110 int getIndex(int idx) {
111 if (idx >= size(arr_)) {
112 return -1;
113 }
114 return addmod(mulmod(arr_[idx], op_.first, MOD), op_.second, MOD);
115 }
116
117 private:
118 uint32_t addmod(uint32_t a, uint32_t b, uint32_t mod) { // avoid overflow
119 // a %= mod, b %= mod; // assumed a, b have been mod
120 if (mod - a <= b) {
121 b -= mod; // relied on unsigned integer overflow in order to give the expected results
122 }
123 return a + b;
124 }
125
126 uint32_t submod(uint32_t a, uint32_t b, uint32_t mod) {
127 // a %= mod, b %= mod; // assumed a, b have been mod
128 return addmod(a, mod - b, mod);
129 }
130
131 // reference: https://stackoverflow.com/questions/12168348/ways-to-do-modulo-multiplication-with-primitive-types
132 uint32_t mulmod(uint32_t a, uint32_t b, uint32_t mod) { // avoid overflow
133 #ifdef USE_UINT64_T
134 return uint64_t(a) * b % mod; // speed up if we can use uint64_t
135 #else
135 #else
136 uint32_t result = 0;
137 if (a < b) {
138 swap(a, b);
139 }
140 while (b > 0) {
141 if (b % 2 == 1) {
142 result = addmod(result, a, mod);
143 }
144 a = addmod(a, a, mod);
145 b /= 2;
146 }
147 return result;
148 #endif
149 }
150
151 uint32_t powmod(uint32_t a, uint32_t b, uint32_t mod) {
152 a %= mod;
153 uint32_t result = 1;
154 while (b) {
155 if (b & 1) {
156 result = mulmod(result, a, mod);
157 }
158 a = mulmod(a, a, mod);
159 b >>= 1;
160 }
161 return result;
162 }
163
164 static const int MOD = 1e9 + 7;
165 vector arr_;
166 pair op_;
167 };
**************

329. Fancy Sequence(Python)


**************

1 # Time: O(1)
2 # Space: O(n)
3
4 MOD = 10**9+7
5
6 class Fancy(object):
7
8 def __init__(self):
9 self.__arr = []
10 self.__ops = [[1, 0]]
11
12 def append(self, val):
13 """
14 :type val: int
15 :rtype: None
16 """
17 self.__arr.append(val)
18 self.__ops.append(self.__ops[-1][:])
19
20 def addAll(self, inc):
21 """
22 :type inc: int
23 :rtype: None
24 """
25 self.__ops[-1][1] = (self.__ops[-1][1]+inc) % MOD
26
27 def multAll(self, m):
28 """
29 :type m: int
30 :rtype: None
31 """
32 self.__ops[-1] = [(self.__ops[-1][0]*m) % MOD, (self.__ops[-1][1]*m) % MOD]
33
34 def getIndex(self, idx):
35 """
36 :type idx: int
37 :rtype: int
38 """
39 if idx >= len(self.__arr):
40 return -1
41 a1, b1 = self.__ops[idx]
42 a2, b2 = self.__ops[-1]
43 a = a2*pow(a1, MOD-2, MOD)%MOD # O(logMOD), we treat it as O(1) here
44 b = (b2 - b1*a) % MOD
45 return (self.__arr[idx]*a + b) % MOD
46
47
48 # Time: O(1)
49 # Space: O(n)
50 class Fancy2(object):
51
52 def __init__(self):
53 self.__arr = []
54 self.__op = [1, 0]
55
56 def append(self, val):
57 """
58 :type val: int
59 :rtype: None
60 """
61 self.__arr.append((val-self.__op[1])*pow(self.__op[0], MOD-2, MOD)%MOD) # O(logMOD), we treat it as O(1) here
62
63 def addAll(self, inc):
64 """
65 :type inc: int
66 :rtype: None
67 """
68 self.__op[1] = (self.__op[1]+inc) % MOD
69
70 def multAll(self, m):
71 """
72 :type m: int
73 :rtype: None
74 """
75 self.__op = [(self.__op[0]*m) % MOD, (self.__op[1]*m) % MOD]
76
77 def getIndex(self, idx):
78 """
79 :type idx: int
80 :rtype: int
81 """
82 if idx >= len(self.__arr):
83 return -1
84 a, b = self.__op
85 return (self.__arr[idx]*a + b) % MOD
*********************************

330. Graph Connectivity With Threshold


*********************************

We have n cities labeled from 1 to n. Two different cities with labels x and y are directly connected by a bidirectional road if
and only if x and y share a common divisor strictly greater than some threshold. More formally, cities with labelsx and y have
a road between them if there exists an integer z such that all of the following are true:

x % z == 0 ,
y % z == 0 , and
z > threshold .

Given the two integers, n and threshold, and an array of queries, you must determine for each queries[i] = [a i, b i] if cities ai and bi are
connected directly or indirectly. (i.e. there is some path between them).

Return an array answer, where answer.length == queries.length and answer[i] is true if for the ith query, there is a path between ai and
bi, or answer[i] is false if there is no path.

Example 1:

Input: n = 6, threshold = 2, queries = [[1,4],[2,5],[3,6]]


Output: [false,false,true]
Explanation: The divisors for each number:
1: 1
2: 1, 2
3: 1, 3
4: 1, 2, 4
5: 1, 5
6: 1, 2, 3, 6
Using the underlined divisors above the threshold, only cities 3 and 6 share a common divisor, so they are the
only ones directly connected. The result of each query:
[1,4] 1 is not connected to 4
[2,5] 2 is not connected to 5
[3,6] 3 is connected to 6 through path 3--6

Example 2:
Input: n = 6, threshold = 0, queries = [[4,5],[3,4],[3,2],[2,6],[1,3]]
Output: [true,true,true,true,true]
Explanation: The divisors for each number are the same as the previous example. However, since the threshold is 0,
all divisors can be used. Since all numbers share 1 as a divisor, all cities are connected.

Example 3:

Input: n = 5, threshold = 1, queries = [[4,5],[4,5],[3,2],[2,3],[3,4]]


Output: [false,false,false,false,false]
Explanation: Only cities 2 and 4 share a common divisor 2 which is strictly greater than the threshold 1, so they are the only ones directly
Please notice that there can be multiple queries for the same pair of nodes [x, y], and that the query [x, y] is equivalent to the query [y,

Constraints:

2 <= n <= 10 4
0 <= threshold <= n
1 <= queries.length <= 10 5
queries[i].length == 2
1 <= ai, b i <= cities
ai != b i
*********************************

330. Graph Connectivity With Threshold(C++)


*********************************
1 // Time: O((nlogn + q) * α(n)) ~= O(nlogn + q)
2 // Space: O(n)
3
4 class Solution {
5 public:
6 vector areConnected(int n, int threshold, vector>& queries) {
7 UnionFind union_find(n);
8 for (int i = threshold + 1; i <= n; ++i) {
9 // https://stackoverflow.com/questions/25905118/finding-big-o-of-the-harmonic-series
10 // sum of harmonic series is O(logn)
11 for (int j = 2 * i; j <= n; j += i) {
12 union_find.union_set(i - 1, j - 1);
13 }
14 }
15 vector result;
16 for (const auto& q : queries) {
17 result.emplace_back(union_find.find_set(q[0] - 1) == union_find.find_set(q[1] - 1));
18 }
19 return result;
20 }
21
22 private:
23 class UnionFind {
24 public:
25 UnionFind(const int n) : set_(n), rank_(n), count_(n) {
26 iota(set_.begin(), set_.end(), 0);
27 }
28
29 int find_set(const int x) {
30 if (set_[x] != x) {
31 set_[x] = find_set(set_[x]); // Path compression.
32 }
33 return set_[x];
34 }
35
36 bool union_set(const int x, const int y) {
37 int x_root = find_set(x), y_root = find_set(y);
38 if (x_root == y_root) {
39 return false;
40 }
41 if (rank_[x_root] < rank_[y_root]) { // Union by rank.
42 set_[x_root] = y_root;
43 } else if (rank_[x_root] > rank_[y_root]) {
44 set_[y_root] = x_root;
45 } else {
46 set_[y_root] = x_root;
47 ++rank_[x_root];
48 }
49 --count_;
50 return true;
51 }
52
53 int size() const {
54 return count_;
55 }
56
57 private:
58 vector set_;
59 vector rank_;
60 int count_;
61 };
62 };
*********************************

330. Graph Connectivity With Threshold(Python)


*********************************

1 # Time: O((nlogn + q) * α(n)) ~= O(nlogn + q)


2 # Space: O(n)
3
4 class UnionFind(object): # Time: (n * α(n)), Space: O(n)
5 def __init__(self, n):
6 self.set = range(n)
7 self.rank = [0]*n
8
9 def find_set(self, x):
10 stk = []
11 while self.set[x] != x: # path compression
12 stk.append(x)
13 x = self.set[x]
14 while stk:
15 self.set[stk.pop()] = x
16 return x
17
18 def union_set(self, x, y):
19 x_root, y_root = map(self.find_set, (x, y))
20 if x_root == y_root:
21 return False
22 if self.rank[x_root] < self.rank[y_root]: # union by rank
23 self.set[x_root] = y_root
24 elif self.rank[x_root] > self.rank[y_root]:
25 self.set[y_root] = x_root
26 else:
27 self.set[y_root] = x_root
28 self.rank[x_root] += 1
29 return True
30
31
32 class Solution(object):
33 def areConnected(self, n, threshold, queries):
34 """
35 :type n: int
36 :type threshold: int
37 :type queries: List[List[int]]
38 :rtype: List[bool]
39 """
40 union_find = UnionFind(n)
41 for i in xrange(threshold+1, n+1):
42 # https://stackoverflow.com/questions/25905118/finding-big-o-of-the-harmonic-series
43 # sum of harmonic series is O(logn)
44 for j in xrange(2*i, n+1, i): # step by i
45 union_find.union_set(i-1, j-1)
46 return [union_find.find_set(q[0]-1) == union_find.find_set(q[1]-1) for q in queries]
**************************

331. Rank Transform of a Matrix


**************************

Given an m x n matrix, return a new matrix answer where answer[row][col] is the rank of matrix[row][col] .

The rank is an integer that represents how large an element is compared to other elements. It is calculated using the
following rules:

The rank is an integer starting from 1.


If two elements p and q are in the same row or column, then:
If p < q then rank(p) < rank(q)
If p == q then rank(p) == rank(q)
If p > q then rank(p) > rank(q)
The rank should be as small as possible.

It is guaranteed that answer is unique under the given rules.

Example 1:

Input: matrix = [[1,2],[3,4]]


Output: [[1,2],[2,3]]
Explanation:
The rank of matrix[0][0] is 1 because it is the smallest integer in its row and column.
The rank of matrix[0][1] is 2 because matrix[0][1] > matrix[0][0] and matrix[0][0] is rank 1.
The rank of matrix[1][0] is 2 because matrix[1][0] > matrix[0][0] and matrix[0][0] is rank 1.
The rank of matrix[1][1] is 3 because matrix[1][1] > matrix[0][1], matrix[1][1] > matrix[1][0], and both matrix[0][1] and matrix[1][0] are ra

Example 2:

Input: matrix = [[7,7],[7,7]]


Output: [[1,1],[1,1]]

Example 3:
Input: matrix = [[20,-21,14],[-19,4,19],[22,-47,24],[-19,4,19]]
Output: [[4,2,3],[1,3,4],[5,1,6],[1,3,4]]

Example 4:

Input: matrix = [[7,3,6],[1,4,5],[9,8,2]]


Output: [[5,1,4],[1,2,3],[6,3,1]]

Constraints:

m == matrix.length
n == matrix[i].length
1 <= m, n <= 500
-109 <= matrix[row][col] <= 10 9
**************************

331. Rank Transform of a Matrix(C++)


**************************

1 // Time: O(m * n * log(m * n) + m * n * α(m * n)) = O(m * n * log(m * n))


2 // Space: O(m * n)
3
4 class Solution {
5 public:
6 vector> matrixRankTransform(vector>& matrix) {
7 map>> lookup;
8 for (int i = 0; i < size(matrix); ++i) {
9 for (int j = 0; j < size(matrix[0]); ++j) {
10 lookup[matrix[i][j]].emplace_back(i, j);
11 }
12 }
13 vector rank(size(matrix) + size(matrix[0]));
14 for (const auto& [x, pairs] : lookup) {
15 vector new_rank(rank);
16 const auto& cb = [&new_rank](int x, int y, int z) {
17 new_rank[x] = max(new_rank[y], new_rank[z]);
18 };
19 UnionFind union_find(size(matrix) + size(matrix[0]), cb);
20 for (const auto& [i, j] : pairs) {
21 union_find.union_set(i, j + size(matrix));
22 }
23 for (const auto& [i, j] : pairs) {
24 matrix[i][j] = rank[i] = rank[j + size(matrix)] = new_rank[union_find.find_set(i)] + 1;
25 }
26 }
27 return matrix;
28 }
29
30 private:
31 class UnionFind {
32 public:
33 UnionFind(const int n, function cb)
34 : set_(n)
35 , rank_(n)
36 , count_(n)
37 , cb_(cb) {
38 iota(set_.begin(), set_.end(), 0);
39 }
40
41 int find_set(const int x) {
42 if (set_[x] != x) {
43 set_[x] = find_set(set_[x]); // Path compression.
44 }
45 return set_[x];
46 }
47
48 bool union_set(const int x, const int y) {
49 int x_root = find_set(x), y_root = find_set(y);
50 if (x_root == y_root) {
51 return false;
52 }
53 if (rank_[x_root] < rank_[y_root]) { // Union by rank.
54 set_[x_root] = y_root;
55 cb_(y_root, x_root, y_root);
56 } else if (rank_[x_root] > rank_[y_root]) {
57 set_[y_root] = x_root;
58 cb_(x_root, x_root, y_root);
59 } else {
60 set_[y_root] = x_root;
61 ++rank_[x_root];
62 cb_(x_root, x_root, y_root);
63 }
64 --count_;
65 return true;
66 }
67
68 int size() const {
69 return count_;
70 }
71
72 private:
73 vector set_;
74 vector rank_;
75 int count_;
76 function cb_;
77 };
78 };
**************************

331. Rank Transform of a Matrix(Python)


**************************

1 # Time: O(m * n * log(m * n) + m * n * α(m * n)) = O(m * n * log(m * n))


2 # Space: O(m * n)
3
4 import collections
5
6
7 class UnionFind(object): # Time: (n * α(n)), Space: O(n)
8 def __init__(self, n, cb):
9 self.set = range(n)
10 self.rank = [0]*n
11 self.cb = cb
12
13 def find_set(self, x):
14 stk = []
15 while self.set[x] != x: # path compression
16 stk.append(x)
17 x = self.set[x]
18 while stk:
19 self.set[stk.pop()] = x
20 return x
21
22 def union_set(self, x, y):
23 x_root, y_root = map(self.find_set, (x, y))
24 if x_root == y_root:
25 return False
26 if self.rank[x_root] < self.rank[y_root]: # union by rank
27 self.set[x_root] = y_root
28 self.cb(y_root, x_root, y_root)
29 elif self.rank[x_root] > self.rank[y_root]:
30 self.set[y_root] = x_root
31 self.cb(x_root, x_root, y_root)
32 else:
33 self.set[y_root] = x_root
34 self.rank[x_root] += 1
35 self.cb(x_root, x_root, y_root)
36 return True
37
38
39 class Solution(object):
40 def matrixRankTransform(self, matrix):
41 """
42 :type matrix: List[List[int]]
43 :rtype: List[List[int]]
44 """
45 def cb(x, y, z):
46 new_rank[x] = max(new_rank[y], new_rank[z])
47
48 lookup = collections.defaultdict(list)
49 for i in xrange(len(matrix)):
50 for j in xrange(len(matrix[0])):
51 lookup[matrix[i][j]].append([i, j])
52 rank = [0]*(len(matrix)+len(matrix[0]))
53 for x in sorted(lookup):
54 new_rank = rank[:]
55 union_find = UnionFind(len(matrix)+len(matrix[0]), cb)
56 for i, j in lookup[x]:
57 union_find.union_set(i, j+len(matrix))
58 for i, j in lookup[x]:
59 matrix[i][j] = rank[i] = rank[j+len(matrix)] = new_rank[union_find.find_set(i)]+1
60 return matrix

You might also like