├── .DS_Store ├── .vscode ├── launch.json └── settings.json ├── 3341. Find Minimum Time to Reach Last Room I.py ├── AVL Tree └── AVL.py ├── Array ├── 1013. Partition Array Into Three Parts With Equal Sum.py ├── 1051. Height Checker.py ├── 1267. Count Servers that Communicate.py ├── 1299. Replace Elements with Greatest Element on Right Side.py ├── 1389_target_array.py ├── 1395. Count Number of Teams.py ├── 1503. Last Moment Before All Ants Fall Out of a Plank.py ├── 169. Majority Element.py ├── 1701. Average Waiting Time.py ├── 1752_check_array_sorted_rotated.py ├── 1800. Maximum Ascending Subarray Sum.py ├── 189. Rotate Array.py ├── 2073. Time Needed to Buy Tickets.py ├── 229. Majority Element II.py ├── 2332. The Latest Time to Catch a Bus.py ├── 2340. Minimum Adjacent Swaps to Make a Valid Array.py ├── 2656. Maximum Sum With Exactly K Elements .py ├── 2657. Find the Prefix Common Array of Two Arrays.py ├── 2659. Make Array Empty.py ├── 2672. Number of Adjacent Elements With the Same Color.py ├── 2679. Sum in a Matrix.py ├── 2681. Power of Heroes.py ├── 2682. Find the Losers of the Circular Game.py ├── 2706. Buy Two Chocolates.py ├── 2733. Neither Minimum nor Maximum.py ├── 2739. Total Distance Traveled.py ├── 2740. Find the Value of the Partition.py ├── 2780. Minimum Index of a Valid Split.py ├── 287. Find the Duplicate Number.py ├── 2946. Matrix Similarity After Cyclic Shifts.py ├── 2948. Make Lexicographically Smallest Array by Swapping Elements.py ├── 3011. Find if Array Can Be Sorted.py ├── 3012. Minimize Length of Array Using Operations.py ├── 3100. Water Bottles II.py ├── 3105. Longest Strictly Increasing or Strictly Decreasing Subarray.py ├── 3151. Special Array I.py ├── 3168. Minimum Number of Chairs in a Waiting Room.py ├── 3175. Find The First Player to win K Games in a Row.py ├── 3178. Find the Child Who Has the Ball After K Seconds.py ├── 41. First Missing Positive.py ├── 414. Third Maximum Number.py ├── 73. Set Matrix Zeroes.py ├── 845. Longest Mountain in Array.py ├── 989. Add to Array-Form of Integer.py ├── Birthday Party and Return Gift.py ├── Count distinct connections.py ├── Longest subsequence having equal numbers of 0 and 1.py ├── Minimum steps to get desired array.py ├── Multiply Matrices.py ├── Python program to make a list even odd parity.py ├── Reorder an array according to given indexes.py ├── Sort according to an Array.py └── program to make a list even odd parity.py ├── Back_Tracking ├── 1079. Letter Tile Possibilities.py ├── 1219. Path with Maximum Gold.py ├── 1255. Maximum Score Words Formed by Letters.py ├── 131. Palindrome Partitioning.py ├── 140. Word Break II.py ├── 1601. Maximum Number of Achievable Transfer Requests.py ├── 17. Letter Combinations of a Phone Number.py ├── 1718. Construct the Lexicographically Largest Valid Sequence.py ├── 1723. Find Minimum Time to Finish All Jobs.py ├── 216. Combination Sum III.py ├── 22. Generate Parentheses.py ├── 2305. Fair Distribution of Cookies.py ├── 2698. Find the Punishment Number of an Integer.py ├── 282. Expression Add Operators.py ├── 351. Android Unlock Patterns.py ├── 37. Sudoku Solver.py ├── 39. Combination Sum.py ├── 40. Combination Sum II.py ├── 46. Permutations.py ├── 47. Permutations II.py ├── 473. Matchsticks to Square.py ├── 51. N-Queens.py ├── 60. Permutation Sequence.py ├── 62. Unique Paths.py ├── 63. Unique Paths II.py ├── 698. Partition to K Equal Sum Subsets.py ├── 77. Combinations.py ├── 78. Subsets.py ├── 784. Letter Case Permutation.py ├── 79. Word Search.py ├── 90. Subsets II.py ├── 93. Restore IP Addresses.py ├── M-Coloring Problem.py ├── N_Knights.py ├── No of ways to get a given sum in a dice.py ├── Permutation with Spaces.py ├── Possible paths in grid.py ├── Print N-bit binary numbers having more 1s than 0s.py ├── Rat in a Maze Problem - I.py ├── paths_in_grid_with_DLRU.PY ├── printing_subsequences.py ├── subsequences with ascii.py ├── subsequences with sum k.py └── tempCodeRunnerFile.py ├── Basic Math ├── binary_decimal_4.py ├── factors_1.py ├── hcf_lcm_3.py ├── newton_sqrt.py └── prime_num_2.py ├── Binary_Search ├── 1011. Capacity To Ship Packages Within D Days.py ├── 1044. Longest Duplicate Substring.py ├── 1095. Find in Mountain Array.py ├── 1146. Snapshot Array.py ├── 1201. Ugly Number III.py ├── 1231.Divide-Chocolate.py ├── 1283. Find the Smallest Divisor Given a Threshold.py ├── 1287. Element Appearing More Than 25% In Sorted Array.py ├── 1351. Count Negative Numbers in a Sorted Matrix.py ├── 1482. Minimum Number of Days to Make m Bouquets.py ├── 153. Find Minimum in Rotated Sorted Array.py ├── 1539. Kth Missing Positive Number.py ├── 1552. Magnetic Force Between Two Balls.py ├── 162. Find Peak Element.py ├── 1755. Closest Subsequence Sum.py ├── 1760. Minimum Limit of Balls in a Bag.py ├── 1802. Maximum Value at a Given Index in a Bounded Array.py ├── 1870. Minimum Speed to Arrive on Time.py ├── 1970. Last Day Where You Can Still Cross.py ├── 2035. Partition Array Into Two Arrays to Minimize Sum Difference.py ├── 2141. Maximum Running Time of N Computers.py ├── 2187. Minimum Time to Complete Trips.py ├── 2251. Number of Flowers in Full Bloom.py ├── 2300. Successful Pairs of Spells and Potions.py ├── 240. Search a 2D Matrix II.py ├── 2448. Minimum Cost to Make Array Equal.py ├── 2485. Find the Pivot Integer.py ├── 2513. Minimize the Maximum of Two Arrays.py ├── 2560. House Robber IV.py ├── 2594. Minimum Time to Repair Cars.py ├── 2602. Minimum Operations to Make All Array Elements Equal.py ├── 2616. Minimize the Maximum Difference of Pairs.py ├── 278. First Bad Version.py ├── 2861. Maximum Number of Alloys.py ├── 33. Search in Rotated Sorted Array.py ├── 34_first_last_position.py ├── 374. Guess Number Higher or Lower.py ├── 378. Kth Smallest Element in a Sorted Matrix.py ├── 4. Median of Two Sorted Arrays.py ├── 400. Nth Digit.py ├── 410. Split Array Largest Sum.py ├── 441. Arranging Coins.py ├── 540. Single Element in a Sorted Array.py ├── 658. Find K Closest Elements.py ├── 668. Kth Smallest Number in Multiplication Table.py ├── 69. Sqrt(x).py ├── 704. Binary Search.py ├── 719. Find K-th Smallest Pair Distance.py ├── 729. My Calendar I.py ├── 74. Search a 2D Matrix.py ├── 744. Find Smallest Letter Greater Than Target.py ├── 774-minimize-max-distance-to-gas-station.py ├── 786. K-th Smallest Prime Fraction.py ├── 792. Number of Matching Subsequences.py ├── 81. Search in Rotated Sorted Array II.py ├── 852. Peak Index in a Mountain Array.py ├── 875. Koko Eating Bananas.py ├── 878. Nth Magical Number.py ├── 981. Time Based Key-Value Store.py ├── Aggressive Cows.py ├── Allocate minimum number of pages.py ├── Ceiling of a number in sorted array.py ├── Counting elements in two arrays.py ├── Find median in row wise sorted matrix.py ├── Find position of an element in a sorted array of infinite numbers.py ├── Find the Rotation Count in Rotated Sorted array.py ├── Find the index of first 1 in an infinite sorted array of 0s and 1s.py ├── Find the row with maximum number of 1s.py ├── Floor of a number in a sorted array.py ├── K-th Element of Two Sorted Arrays.py ├── Nth Root Of M.py ├── Row with Maximum 1's.py ├── Search in an almost sorted array.py ├── The Painter's Partition Problem-II.py ├── linear_search.py ├── max_in_rotated_sorted_array.py ├── min_diff_ele.py ├── minimum waiting time.py └── tempCodeRunnerFile.py ├── Bitwise_Manipulation ├── 1318. Minimum Flips to Make a OR b Equal to c.py ├── 1356. Sort Integers by The Number of 1 Bits.py ├── 136_Single_number.py ├── 137. Single Number II.py ├── 1404. Number of Steps to Reduce a Number in Binary Representation to One.py ├── 1611. Minimum One Bit Operations to Make Integers Zero.py ├── 1832. Check if the Sentence Is Pangram.py ├── 190. Reverse Bits.py ├── 191. Number of 1 Bits.py ├── 1915. Number of Wonderful Substrings.py ├── 231. Power of Two.py ├── 2438. Range Product Queries of Powers.py ├── 260. Single Number III.py ├── 268. Missing Number.py ├── 2680. Maximum OR.py ├── 2683. Neighboring Bitwise XOR.py ├── 2997. Minimum Number of Operations to Make Array XOR Equal to K.py. Minimum Number of Operations to Make Array XOR Equal to K.py ├── 3007. Maximum Number That Sum of the Prices Is Less Than or Equal to K.py ├── 3068. Find the Maximum Sum of Node Values.py ├── 3097. Shortest Subarray With OR at Least K II.py ├── 318. Maximum Product of Word Lengths.py ├── 326. Power of Three.py ├── 338. Counting Bits.py ├── 342. Power of Four.py ├── 371. Sum of Two Integers.py ├── 405. Convert a Number to Hexadecimal.py ├── 421. Maximum XOR of Two Numbers in an Array.py ├── 476. Number Complement.py ├── 477. Total Hamming Distance.py ├── 50_power_x_to_n.py ├── 7. Reverse Integer.py ├── 78_subsets.py ├── 832. Flipping an Image.py ├── Find XOR of numbers from the range [L, R].py ├── No_bits.py ├── Repeat and Missing Number Array.py ├── Toggle_kth_bit.py ├── XOR of 1 to n Numbers.py ├── check_kth_bit_set.py ├── even_odd.py ├── kth_bit_from_right.py ├── nth_magical no.py ├── position_rightmost_set_bit.py ├── reset_kth_bit.py ├── set_kth_bit.py └── sum_till_nth_row_pascal_tri.py ├── Concurrency & Multithreading └── 1116. Print Zero Even Odd.py ├── Disjoint Set Union ├── 1101.The Earliest Moment When Everyone Become Friends.py ├── 128. Longest Consecutive Sequence.py ├── 1319. Number of Operations to Make Network Connected.py ├── 1361. Validate Binary Tree Nodes.py ├── 200. Number of Islands.py ├── 305 Number of Islands II.py ├── 3108. Minimum Cost Walk in Weighted Graph.py ├── 547. Number of Provinces.py ├── 684. Redundant Connection.py ├── 721. Accounts Merge.py ├── 827. Making A Large Island.py ├── 947. Most Stones Removed with Same Row or Column.py ├── 959. Regions Cut By Slashes.py ├── Implementation DSU.PY └── krushkal.py ├── Dynamic Programming ├── .DS_Store ├── 0_1_knapsack │ ├── 0 - 1 Knapsack Problem.py │ ├── 1049. Last Stone Weight II.py │ ├── 1105. Filling Bookcase Shelves.py │ ├── 1235. Maximum Profit in Job Scheduling.py │ ├── 1639. Number of Ways to Form a Target String Given a Dictionary.py │ ├── 1751. Maximum Number of Events That Can Be Attended II.py │ ├── 2742. Painting the Walls.py │ ├── 3098. Find the Sum of Subsequence Powers.py │ ├── 416. Partition Equal Subset Sum.py │ ├── 494. Target Sum.py │ ├── 956. Tallest Billboard.py │ ├── Count of Subsets with given Difference.py │ ├── Count of subsets with sum equal to X.py │ ├── Minimum sum partition.py │ ├── Subset Sum Problem.py │ └── tempCodeRunnerFile.py ├── DP + BitMasking │ ├── 1125. Smallest Sufficient Team.py │ ├── 1349. Maximum Students Taking Exam.py │ ├── 1434. Number of Ways to Wear Different Hats to Each Other.py │ ├── 1494. Parallel Courses II.py │ ├── 1799. Maximize Score After N Operations.py │ ├── 1986. Minimum Number of Work Sessions to Finish the Tasks.py │ ├── 2305. Fair Distribution of Cookies.py │ ├── 2741. Special Permutations.PY │ ├── 526. Beautiful Arrangement.py │ └── 698. Partition to K Equal Sum Subsets.py ├── DP + Graph │ └── 1220. Count Vowels Permutation.py ├── DP + Hashing │ ├── 2063. Vowels of All Substrings.py │ ├── 2262. Total Appeal of A String.py │ └── 828. Count Unique Characters of All Substrings of a Given String.py ├── DP + Stack │ ├── 1335. Minimum Difficulty of a Job Schedule.py │ └── 2355. Maximum Number of Books You Can Take.py ├── DP On Game │ ├── 1140. Stone Game II.py │ ├── 1406. Stone Game III.py │ ├── 486. Predict the Winner.py │ ├── 799. Champagne Tower.py │ └── 877. Stone Game.py ├── DP On Shapes │ ├── 1277. Count Square Submatrices with All Ones.py │ ├── 2088. Count Fertile Pyramids in a Land.py │ ├── 221. Maximal Square.py │ ├── 363. Max Sum of Rectangle No Larger Than K.py │ ├── 85_maximal_rectangle.py │ └── Maximum sum Rectangle.py ├── DP on Probabilities │ ├── 688. Knight Probability in Chessboard.py │ ├── 808. Soup Servings.py │ └── 837. New 21 Game.py ├── Digit DP │ ├── 233. Number of Digit One.py │ ├── 2719. Count of Integers.py │ └── No having exactly k non_zero digits.py ├── Fibonacci Based │ ├── 198. House Robber.py │ ├── 213. House Robber II.py │ ├── 276 - Paint Fence.py │ ├── 2770. Maximum Number of Jumps to Reach the Last Index.py │ ├── 2944. Minimum Number of Coins for Fruits.py │ ├── 3186. Maximum Total Damage With Spell Casting.py │ ├── 337. House Robber III.py │ ├── 403. Frog Jump.py │ ├── 70. Climbing Stairs.py │ ├── 740. Delete and Earn.py │ ├── 746. Min Cost Climbing Stairs.py │ ├── 873. Length of Longest Fibonacci Subsequence.py │ ├── Frog Jump StairCase.py │ ├── Frog Jump with k Distances.py │ ├── Ninja Training.py │ ├── count_children.py │ └── fibonacci.py ├── Front Partitioning │ ├── 1043. Partition Array for Maximum Sum.py │ ├── 132. Palindrome Partitioning II.py │ ├── 139. Word Break.py │ ├── 2266. Count Number of Texts.py │ ├── 2707. Extra Characters in a String.py │ ├── 2767. Partition String Into Minimum Beautiful Substrings.py │ ├── 472. Concatenated Words.PY │ ├── 91. Decode Ways.py │ └── 97. Interleaving String.py ├── Grid Problem │ ├── 120. Triangle.py │ ├── 1575. Count All Possible Routes.py │ ├── 2328. Number of Increasing Paths in a Grid.py │ ├── 2435. Paths in Matrix Whose Sum Is Divisible by K.py │ ├── 2684. Maximum Number of Moves in a Grid.py │ ├── 2713. Maximum Strictly Increasing Cells in a Matrix.py │ ├── 329. Longest Increasing Path in a Matrix.py │ ├── 62. Unique Paths.py │ ├── 63. Unique Paths II.py │ ├── 64. Minimum Path Sum.py │ ├── 741. Cherry Pickup.py │ ├── 931. Minimum Falling Path Sum.py │ ├── 980. Unique Paths III.py │ ├── Chocolate Pickup.py │ ├── Maximum path sum in matrix.py │ ├── Possible paths in grid.py │ └── paths_in_grid_with_DLRU.PY ├── Kedane's Alogorithm │ ├── 1014. Best Sightseeing Pair.py │ ├── 121. Best Time to Buy and Sell Stock.py │ ├── 122. Best Time to Buy and Sell Stock II.py │ ├── 123. Best Time to Buy and Sell Stock III.py │ ├── 152. Maximum Product Subarray.PY │ ├── 188. Best Time to Buy and Sell Stock IV.py │ ├── 1937. Maximum Number of Points with Cost │ ├── 2272. Substring With Largest Variance.py │ ├── 309. Best Time to Buy and Sell Stock with Cooldown.py │ ├── 53. Maximum Subarray.py │ ├── 714. Best Time to Buy and Sell Stock with Transaction Fee.py │ ├── 918. Maximum Sum Circular Subarray.py │ └── Print the Maximum Subarray Sum.py ├── Longest Inceasing Subsequence │ ├── 1027. Longest Arithmetic Subsequence.py │ ├── 1048. Longest String Chain.py │ ├── 1187. Make Array Strictly Increasing.py │ ├── 1671. Minimum Number of Removals to Make Mountain Array.py │ ├── 1691. Maximum Height by Stacking Cuboids.py │ ├── 2501. Longest Square Streak in an Array.py │ ├── 300. Longest Increasing Subsequence.py │ ├── 3177. Find the Maximum Length of a Good Subsequence II.py │ ├── 354. Russian Doll Envelopes.py │ ├── 368. Largest Divisible Subset.py │ ├── 673. Number of Longest Increasing Subsequence.py │ ├── 960. Delete Columns to Make Sorted III.py │ ├── Longest Bitonic subsequence.py │ ├── Maximum sum increasing subsequence.py │ └── printing LIS.py ├── Longest_Common_Subsequence │ ├── 1062. Longest Repeating Substring.py │ ├── 1092_shortest_common_supersequence.py │ ├── 1143. Longest Common Subsequence.py │ ├── 1458. Max Dot Product of Two Subsequences.py │ ├── 392_is_subsequence.py │ ├── 583_Delete_operations.py │ ├── 712. Minimum ASCII Delete Sum for Two Strings.py │ ├── Longest Common Substring.py │ ├── Longest Repeating Subsequence.py │ ├── Shortest Uncommon Subsequence.py │ ├── print_all_longest_common_subsequences.py │ └── tempCodeRunnerFile.py ├── Matrix_Chain_Multiplication │ ├── 1000. Minimum Cost to Merge Stones.py │ ├── 1039. Minimum Score Triangulation of Polygon.py │ ├── 1130. Minimum Cost Tree From Leaf Values.py │ ├── 1547. Minimum Cost to Cut a Stick.py │ ├── 1884. Egg Drop With 2 Eggs and N Floors.py │ ├── 241. Different Ways to Add Parentheses.py │ ├── 312. Burst Balloons.py │ ├── 375. Guess Number Higher or Lower II.py │ ├── 546. Remove Boxes.py │ ├── 664. Strange Printer.py │ ├── 87. Scramble String.py │ ├── 887. Super Egg Drop.py │ ├── 894. All Possible Full Binary Trees.py │ ├── 95. Unique Binary Search Trees II.py │ ├── 96. Unique Binary Search Trees.py │ ├── Boolean Parenthesization.py │ └── Matrix Chain Multiplication.py ├── Palindromic Subsequences │ ├── 1312. Minimum Insertion Steps to Make a String Palindrome.py │ ├── 1771. Maximize Palindrome Length From Subsequences.py │ ├── 2484. Count Palindromic Subsequences.py │ ├── 5. Longest Palindromic Substring.py │ ├── 516. Longest Palindromic Subsequence.py │ ├── 647. Palindromic Substrings.py │ ├── Count Palindromic Subsequences.py │ └── Minimum number of deletions to make a string palindrome.py ├── Some more Q on DP │ ├── 1478. Allocate Mailboxes.py │ ├── 1553. Minimum Number of Days to Eat N Oranges.py │ ├── 1653. Minimum Deletions to Make String Balanced.py │ ├── 2338. Count the Number of Ideal Arrays.py │ ├── 2369. Check if There is a Valid Partition For The Array.py │ ├── 2597. The Number of Beautiful Subsets.py │ ├── 2746. Decremental String Concatenation.py │ ├── 2771. Longest Non-decreasing Subarray From Two Arrays.py │ ├── 2998. Minimum Number of Operations to Make X and Y Equal.py │ ├── 552. Student Attendance Record II.py │ ├── 920. Number of Music Playlists.py │ ├── 926. Flip String to Monotone Increasing.py │ ├── 975. Odd Even Jump.py │ └── 983. Minimum Cost For Tickets.py ├── String Matching │ ├── 10. Regular Expression Matching.py │ ├── 115. Distinct Subsequences.py │ ├── 2222. Number of Ways to Select Buildings.py │ ├── 44. Wildcard Matching.py │ └── 72. Edit Distance.py ├── Take and notTake DP │ ├── 2212. Maximum Points in an Archery Competition.py │ ├── 2901. Longest Unequal Adjacent Groups Subsequence II.py │ └── 3180. Maximum Total Reward Using Operations I.py └── Unbounded_knapsack │ ├── 2466. Count Ways To Build Good Strings.py │ ├── 322. Coin Change.py │ ├── 377. Combination Sum IV.py │ ├── 518. Coin Change II.py │ ├── 650. 2 Keys Keyboard.py │ ├── Number of ways to get a given sum with n number of m-faced dices.py │ ├── Rod_Cutting.py │ └── Unbounded Knapsack.py ├── Graph ├── .DS_Store ├── Basic Graph │ ├── 1791. Find Center of Star Graph.py │ ├── BFS.py │ ├── DFS.py │ ├── adjacency_list.py │ └── adjacency_matrix.py ├── Bellman Ford Algorithm │ ├── 787. Cheapest Flights Within K Stops.py │ └── Bellman Ford Algorithm.py ├── Bfs Dfs │ ├── 1293. Shortest Path in a Grid with Obstacles Elimination.py │ ├── 1306. Jump Game III.py │ ├── 133. Clone Graph.py │ ├── 1553. Minimum Number of Days to Eat N Oranges.py │ ├── 2192. All Ancestors of a Node in a Directed Acyclic Graph.py │ ├── 2477. Minimum Fuel Cost to Report to the Capital.py │ ├── 2617. Minimum Number of Visited Cells in a Grid.py │ ├── 2998. Minimum Number of Operations to Make X and Y Equal.py │ ├── 463. Island Perimeter.py │ ├── 733. Flood Fill.py │ ├── 773. Sliding Puzzle.py │ ├── 818. Race Car.py │ ├── 841. Keys and Rooms.py │ ├── 847. Shortest Path Visiting All Nodes.py │ ├── 909. Snakes and Ladders.py │ ├── Minimum Multiplications to reach End.py │ └── shortest_path_S_D_unweighted_graph.py ├── Bfs Visit More than Once │ ├── 1129. Shortest Path with Alternating Colors.py │ └── 864. Shortest Path to Get All Keys.py ├── Bridges and Articulation Point │ ├── 1192. Critical Connections in a Network.py │ └── Articulation point.py ├── Connected Component Bfs Dfs │ ├── 1042. Flower Planting With No Adjacent.py │ ├── 200. Number of Islands.py │ ├── 2101. Detonate the Maximum Bombs.py │ ├── 2658. Maximum Number of Fish in a Grid.py │ ├── 2685. Count the Number of Complete Components.py │ ├── 2709. Greatest Common Divisor Traversal.py │ ├── 399. Evaluate Division.py │ ├── 694. Number of Distinct Islands.py │ ├── 695. Max Area of Island.py │ ├── 785. Is Graph Bipartite.py │ ├── 934. Shortest Bridge.py │ └── Strongly_connected_components.py ├── Cycle Detection │ ├── 2127. Maximum Employees to Be Invited to a Meeting.py │ ├── 2360. Longest Cycle in a Graph.py │ ├── 2608. Shortest Cycle in a Graph.py │ ├── 261 Valid Graph Tree.py │ ├── 802. Find Eventual Safe States.py │ ├── Cycle_detection_directed_graph.py │ ├── Cycle_detection_undirected.py │ └── Minimum Swaps to Sort.py ├── Dijkstra Algorithm.py ├── Eulerian Path │ ├── 2097. Valid Arrangement of Pairs.py │ └── 332. Reconstruct Itinerary.py ├── Floyd Warshall Algorithm │ ├── 1334. Find the City With the Smallest Number of Neighbors at a Threshold Distance.py │ ├── 2959. Number of Possible Sets of Closing Branches.py │ ├── 2976. Minimum Cost to Convert String I.py │ └── Floyd Warshall.py ├── Indegree Topological order │ ├── 1136. Parallel Courses.py │ ├── 1203. Sort Items by Groups Respecting Dependencies.py │ ├── 1361. Validate Binary Tree Nodes.py │ ├── 1462. Course Schedule IV.py │ ├── 1557. Minimum Number of Vertices to Reach All Nodes.py │ ├── 1615. Maximal Network Rank.py │ ├── 2050. Parallel Courses III.py │ ├── 207. Course Schedule.py │ ├── 210. Course Schedule II.py │ ├── 2285. Maximum Total Importance of Roads.py │ ├── 269· Alien Dictionary.py │ ├── 444 . Sequence Reconstruction.py │ └── Topological_sort.py ├── Minimum Spanning Tree │ ├── 1101.The Earliest Moment When Everyone Become Friends.py │ ├── 1168 - Optimize Water Distribution in a Village.py │ ├── 1489. Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree.py │ ├── 1584. Min Cost to Connect All Points.py │ ├── krushkal.py │ └── prim.py ├── Multisource Bfs │ ├── 1020. Number of Enclaves.py │ ├── 1091. Shortest Path in Binary Matrix.py │ ├── 1162. As Far from Land as Possible.py │ ├── 1197. Minimum Knight Moves.py │ ├── 126. Word Ladder II.py │ ├── 127. Word Ladder.py │ ├── 130. Surrounded Regions.PY │ ├── 1345. Jump Game IV.py │ ├── 1765. Map of Highest Peak.py │ ├── 1970. Last Day Where You Can Still Cross.py │ ├── 286 walls and gates.py │ ├── 417. Pacific Atlantic Water Flow.py │ ├── 542. 01 Matrix.py │ ├── 752. Open the Lock.py │ ├── 815. Bus Routes.py │ └── 994. Rotting Oranges.py ├── Re-rooting │ └── 2858. Minimum Edge Reversals So Every Node Is Reachable.py ├── Shortest Path and Dijkastra │ ├── 1376. Time Needed to Inform All Employees.py │ ├── 1514. Path with Maximum Probability.py │ ├── 1631. Path With Minimum Effort.py │ ├── 1976. Number of Ways to Arrive at Destination.py │ ├── 2092. Find All People With Secret.py │ ├── 2577. Minimum Time to Visit a Cell In a Grid.py │ ├── 2642. Design Graph With Shortest Path Calculator.py │ ├── 2662. Minimum Cost of a Path With Special Roads.py │ ├── 2699. Modify Graph Edge Weights.py │ ├── 2812. Find the Safest Path in a Grid.py │ ├── 3112. Minimum Time to Visit Disappearing Nodes.py │ ├── 3341. Find Minimum Time to Reach Last Room I.py │ ├── 3342. Find Minimum Time to Reach Last Room II.py │ ├── 743. Network Delay Time.py │ ├── 778. Swim in Rising Water.py │ └── minimum_chocolate_cost └── tempCodeRunnerFile.py ├── Greedy ├── 1024. Video Stitching.py ├── 121. Best Time to Buy and Sell Stock.py ├── 122. Best Time to Buy and Sell Stock II.py ├── 1326. Minimum Number of Taps to Open to Water a Garden.py ├── 1328. Break a Palindrome.py ├── 134. Gas Station.PY ├── 135. Candy.py ├── 152. Maximum Product Subarray.py ├── 1526. Minimum Number of Increments on Subarrays to Form a Target Array.py ├── 1567. Maximum Length of Subarray With Positive Product.py ├── 1647. Minimum Deletions to Make Character Frequencies Unique.py ├── 1754. Largest Merge Of Two Strings.py ├── 1899. Merge Triplets to Form Target Triplet.py ├── 2037. Minimum Number of Moves to Seat Everyone.py ├── 2038. Remove Colored Pieces if Both Neighbors are the Same Color.py ├── 2087. Minimum Cost Homecoming of a Robot in a Grid.py ├── 2294. Partition Array Such That Maximum Difference Is K.py ├── 2366. Minimum Replacements to Sort the Array.py ├── 2384. Largest Palindromic Number.py ├── 2498. Frog Jump II.py ├── 252· Meeting Rooms.py ├── 253 · Meeting Rooms II.py ├── 2551. Put Marbles in Bags.py ├── 2712. Minimum Cost to Make All Characters Equal.py ├── 2717. Semi-Ordered Permutation.py ├── 2735. Collecting Chocolates.py ├── 2842. Count K-Subsequences of a String With Maximum Beauty.py ├── 2957. Remove Adjacent Almost-Equal Characters.py ├── 2971. Find Polygon With the Largest Perimeter.py ├── 3191. Minimum Operations to Make Binary Array Elements Equal to One I.PY ├── 3207. Maximum Points After Enemy Battles.py ├── 330. Patching Array.py ├── 435. Non-overlapping Intervals.py ├── 45. Jump Game II.py ├── 452. Minimum Number of Arrows to Burst Balloons.py ├── 517. Super Washing Machines.py ├── 53. Maximum Subarray.py ├── 55. Jump Game.py ├── 56. Merge Intervals.py ├── 57. Insert Interval.py ├── 646. Maximum Length of Pair Chain.py ├── 649. Dota2 Senate.py ├── 678. Valid Parenthesis String.py ├── 763. Partition Labels.py ├── 846. Hand of Straights.py ├── 861. Score After Flipping Matrix.py ├── 910. Smallest Range II.py ├── Job Sequencing Problem.py ├── Minimum Platforms.py └── N meetings in one room.py ├── Hashing ├── 1. Two Sum.py ├── 1002. Find Common Characters.py ├── 1010. Pairs of Songs With Total Durations Divisible by 60.py ├── 1207. Unique Number of Occurrences.py ├── 1218. Longest Arithmetic Subsequence of Given Difference.py ├── 128. Longest Consecutive Sequence.py ├── 1282. Group the People Given the Group Size They Belong To.py ├── 13. Roman to Integer.py ├── 1396. Design Underground System.py ├── 1400. Construct K Palindrome Strings.py ├── 1442. Count Triplets That Can Form Two Arrays of Equal XOR.py ├── 1460. Make Two Arrays Equal by Reversing Subarrays.py ├── 149. Max Points on a Line.py ├── 1497. Check If Array Pairs Are Divisible by k.py ├── 1540. Can Convert String in K Moves.py ├── 1640. Check Array Formation Through Concatenation.py ├── 166. Fraction to Recurring Decimal.py ├── 1679. Max Number of K-Sum Pairs.py ├── 1726. Tuple with Same Product.py ├── 1832. Check if the Sentence Is Pangram .py ├── 1930. Unique Length-3 Palindromic Subsequences.py ├── 2006. Count Number of Pairs With Absolute Difference K.py ├── 2023. Number of Pairs of Strings With Concatenation Equal to Target.py ├── 205. Isomorphic Strings.py ├── 2053. Kth Distinct String in an Array.py ├── 2094. Finding 3-Digit Even Numbers.py ├── 2131. Longest Palindrome by Concatenating Two Letter Words.py ├── 2154. Keep Multiplying Found Values by Two.py ├── 217. Contains Duplicate.py ├── 2183. Count Array Pairs Divisible by K.py ├── 2244. Minimum Rounds to Complete All Tasks.py ├── 2342. Max Sum of a Pair With Equal Sum of Digits.py ├── 2349. Design a Number Container System.py ├── 2352. Equal Row and Column Pairs.py ├── 2364. Count Number of Bad Pairs.py ├── 242. Valid Anagram.py ├── 2453. Destroy Sequential Targets.py ├── 2610. Convert an Array Into a 2D Array With Conditions.py ├── 2615. Sum of Distances.py ├── 2661. First Completely Painted Row or Column.py ├── 2670. Find the Distinct Difference Array.py ├── 2671. Frequency Tracker.py ├── 2718. Sum of Matrix After Queries.py ├── 2766. Relocate Marbles.py ├── 2933. High-Access Employees.py ├── 2955. Number of Same-End Substrings.py ├── 2964 - Number of Divisible Triplet Sums.py ├── 2982. Find Longest Special Substring That Occurs Thrice II.py ├── 3016. Minimum Number of Pushes to Type Word II.py ├── 3026. Maximum Good Subarray Sum.py ├── 3143. Maximum Points Inside the Square.py ├── 3160. Find the Number of Distinct Colors Among the Balls.py ├── 3164. Find the Number of Good Pairs II.py ├── 3167. Better Compression of String.py ├── 3185. Count Pairs That Form a Complete Day II.py ├── 3223. Minimum Length of String After Operations.py ├── 336. Palindrome Pairs.py ├── 350. Intersection of Two Arrays II.py ├── 359 · Logger Rate Limiter.py ├── 36. Valid Sudoku.py ├── 380. Insert Delete GetRandom O(1).py ├── 387. First Unique Character in a String.py ├── 409. Longest Palindrome.py ├── 49. Group Anagrams.py ├── 519. Random Flip Matrix.py ├── 532. K-diff Pairs in an Array.py ├── 554. Brick Wall.py ├── 659. Split Array into Consecutive Subsequences.py ├── 706. Design HashMap.py ├── 916. Word Subsets.py ├── Check if an array is subset of another array.py ├── Find first non-repeating character of given String.py ├── Hit most Balloons.py ├── Maximum distance between two occurrences of same element in array.py ├── Minimum operation to make all elements equal in array.py └── Print all unique pairs with given sum.py ├── Heap ├── 1046. Last Stone Weight.py ├── 1086. High Five.py ├── 1296. Divide Array in Sets of K Consecutive Numbers.py ├── 1353. Maximum Number of Events That Can Be Attended.py ├── 1508. Range Sum of Sorted Subarray Sums.py ├── 1636. Sort Array by Increasing Frequency.py ├── 1642. Furthest Building You Can Reach.py ├── 1675. Minimize Deviation in Array.py ├── 1851. Minimum Interval to Include Each Query.py ├── 2102. Sequentially Ordinal Rank Tracker.py ├── 215. Kth Largest Element in an Array.py ├── 2233. Maximum Product After K Increments.py ├── 2343. Query Kth Smallest Trimmed Number.py ├── 2402. Meeting Rooms III.py ├── 2462. Total Cost to Hire K Workers.py ├── 2542. Maximum Subsequence Score.py ├── 295. Find Median from Data Stream.py ├── 347. Top K Frequent Elements.py ├── 355. Design Twitter.py ├── 373. Find K Pairs with Smallest Sums.py ├── 480. Sliding Window Median.py ├── 502. IPO.py ├── 621. Task Scheduler.py ├── 692. Top K Frequent Words.py ├── 703. Kth Largest Element in a Stream.py ├── 767. Reorganize String.py ├── 857. Minimum Cost to Hire K Workers.py ├── 871. Minimum Number of Refueling Stops.py ├── 973. K Closest Points to Origin.py ├── K_Closest_Unsorted.py ├── K’th Smallest Element in Unsorted Array.py ├── Maximum Sum Combinations.py ├── Merge k Sorted Arrays.py ├── Sort_k_sorted_array.py ├── Sum of all elements between k1’th and k2’th smallest elements.py ├── connect_n_ropes.py ├── heapq1.py ├── maxHeap.py └── min_heap_sort.py ├── Line Sweep Algorithm ├── 1109. Corporate Flight Bookings.py ├── 1854. Maximum Population Year.py ├── 2381. Shifting Letters II.py └── 2848. Points That Intersect With Cars.py ├── LinkList ├── 1171. Remove Zero Sum Consecutive Nodes from Linked List.py ├── 138. Copy List with Random Pointer.py ├── 141. Linked List Cycle.py ├── 142. Linked List Cycle II.py ├── 143. Reorder List.py ├── 146. LRU Cache.py ├── 147. Insertion Sort List.py ├── 148. Sort List.py ├── 160. Intersection of Two Linked Lists.py ├── 1721. Swapping Nodes in a Linked List.py ├── 1836. Remove Duplicates From an Unsorted Linked List.py ├── 19. Remove Nth Node From End of List.py ├── 2. Add Two Numbers.py ├── 2058. Find the Minimum and Maximum Number of Nodes Between Critical Points.py ├── 206. Reverse Linked List.py ├── 21. Merge Two Sorted Lists.py ├── 2130. Maximum Twin Sum of a Linked List.py ├── 2181. Merge Nodes in Between Zeros.py ├── 23. Merge k Sorted Lists.py ├── 234. Palindrome Linked List.py ├── 237. Delete Node in a Linked List.py ├── 24. Swap Nodes in Pairs.py ├── 2487. Remove Nodes From Linked List.py ├── 25 Reverse Nodes in K-group.py ├── 2816. Double a Number Represented as a Linked List.py ├── 287. Find the Duplicate Number.py ├── 328. Odd Even Linked List.py ├── 430. Flatten a Multilevel Doubly Linked List.py ├── 445. Add Two Numbers II.py ├── 460. LFU Cache.py ├── 61. Rotate List.py ├── 725. Split Linked List in Parts.py ├── 82. Remove Duplicates from Sorted List II.py ├── 83. Remove Duplicates from Sorted List.py ├── 86. Partition List.py ├── 876. Middle of the Linked List.py ├── 92. Reverse Linked List II.py ├── Doubly_linklist.py ├── Nth_node_last.py ├── Reverse first K elements of given linked list.py ├── remove_duplicates_unsorted_list.py ├── singly_link_list.py ├── swapping k and k+1 node from end.py └── tempCodeRunnerFile.py ├── Maths and Geometry ├── 1041. Robot Bounded In Circle.py ├── 118. Pascal's Triangle.py ├── 12. Integer to Roman.py ├── 1232. Check If It Is a Straight Line.py ├── 1359. Count All Valid Pickup and Delivery Options.py ├── 1502. Can Make Arithmetic Progression From Sequence.py ├── 1509. Minimum Difference Between Largest and Smallest Value in Three Moves.py ├── 1551. Minimum Operations to Make Array Equal.py ├── 168. Excel Sheet Column Title.py ├── 172. Factorial Trailing Zeroes.py ├── 1823. Find the Winner of the Circular Game.py ├── 1922. Count Good Numbers.py ├── 2013. Detect Squares.py ├── 202. Happy Number.py ├── 204. Count Primes.py ├── 2541. Minimum Operations to Make Array Equal II.py ├── 2543. Check if Point Is Reachable.py ├── 2550. Count Collisions of Monkeys on a Polygon.py ├── 2591. Distribute Money to Maximum Children.py ├── 263. Ugly Number.py ├── 2654. Minimum Number of Operations to Make All Array Elements Equal to 1.py ├── 2708. Maximum Strength of a Group.py ├── 2761. Prime Pairs With Target Sum.py ├── 2849. Determine if a Cell Is Reachable at a Given Time.py ├── 2862. Maximum Element-Sum of a Complete Subset of Indices.py ├── 2870. Minimum Number of Operations to Make Array Empty.py ├── 2929. Distribute Candies Among Children II.py ├── 2943. Maximize Area of Square Hole in Grid.py ├── 296. Best Meeting Point.py ├── 2967. Minimum Cost to Make Array Equalindromic.py ├── 2975. Maximum Square Area by Removing Fences From a Field.py ├── 3001. Minimum Moves to Capture The Queen.py ├── 3002. Maximum Size of a Set After Removals.py ├── 3101. Count Alternating Subarrays.py ├── 3107. Minimum Operations to Make Median of Array Equal to K.py ├── 343. Integer Break.py ├── 43. Multiply Strings.py ├── 453. Minimum Moves to Equal Array Elements.py ├── 462. Minimum Moves to Equal Array Elements II.py ├── 48. Rotate Image.py ├── 592. Fraction Addition and Subtraction.py ├── 657. Robot Return to Origin.py ├── 66. Plus One.py ├── 667. Beautiful Arrangement II.py ├── 780. Reaching Points.py ├── 939. Minimum Area Rectangle.py ├── Maximum GCD Pair.py ├── Minimum operations to make GCD of array a multiple of k.py └── Nth catalan number.py ├── Prefix Sum ├── 1074. Number of Submatrices That Sum to Target.py ├── 1365. How Many Numbers Are Smaller Than the Current Number.py ├── 1413. Minimum Value to Get Positive Step by Step Sum.py ├── 1422. Maximum Score After Splitting a String.py ├── 1769. Minimum Number of Operations to Move All Balls to Each Box.py ├── 2017. Grid Game.py ├── 2025. Maximum Number of Ways to Partition an Array.py ├── 2270. Number of Ways to Split Array.py ├── 238. Product of Array Except Self.py ├── 2420. Find All Good Indices.py ├── 2483. Minimum Penalty for a Shop.py ├── 2559. Count Vowel Strings in Ranges.py ├── 2640. Find the Score of All Prefixes of an Array.py ├── 2711. Difference of Number of Distinct Values on Diagonals.py ├── 2731. Movement of Robots.py ├── 2874. Maximum Value of an Ordered Triplet II.py ├── 304. Range Sum Query 2D - Immutable.py ├── 3096. Minimum Levels to Gain More Points ├── Cumulative Sum Query.py └── Maximum points covered.py ├── Probability and Statistics └── 470. Implement Rand10() Using Rand7().py ├── Queue ├── 1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit.py ├── 1825. Finding MK Average.py ├── 622. Design Circular Queue.py ├── 641. Design Circular Deque.py ├── 862. Shortest Subarray with Sum at Least K.py ├── 950. Reveal Cards In Increasing Order.py ├── 995. Minimum Number of K Consecutive Bit Flips.py └── Circular_Q_Lists.py ├── Recursion_and_String ├── 1910. Remove All Occurrences of a Substring.py ├── 316_remove_duplicates.py ├── move_all_x_to_end.py ├── remove_a_specific_char.py ├── replace_pi_by_value.py └── tempCodeRunnerFile.py ├── Segment Tree ├── 2736. Maximum Sum Queries.py ├── 307. Range Sum Query - Mutable.py ├── 406. Queue Reconstruction by Height.py └── min_max_sumQuery.py ├── Sliding Window ├── .DS_Store ├── Fixed Size Sliding Window │ ├── 1052. Grumpy Bookstore Owner.py │ ├── 1151. Minimum Swaps to Group All 1's Together.py │ ├── 1423. Maximum Points You Can Obtain from Cards.py │ ├── 1425. Constrained Subsequence Sum.py │ ├── 1st_neg_int.py │ ├── 2090. K Radius Subarray Averages.py │ ├── 2134. Minimum Swaps to Group All 1's Together II.py │ ├── 219. Contains Duplicate II.py │ ├── 239. Sliding Window Maximum.py │ ├── 2461. Maximum Sum of Distinct Subarrays With Length K.py │ ├── 2653. Sliding Subarray Beauty.py │ ├── 2660. Determine the Winner of a Bowling Game.py │ ├── 2772. Apply Operations to Make All Array Elements Equal to Zero.py │ ├── 438. Find All Anagrams in a String.py │ ├── 567. Permutation in String.py │ └── Max Sum Subarray of size K.py └── Variable Size Sliding Window │ ├── 1004. Max Consecutive Ones III.py │ ├── 1208. Get Equal Substrings Within Budget.py │ ├── 1248. Count Number of Nice Subarrays.py │ ├── 1493. Longest Subarray of 1's After Deleting One Element.py │ ├── 1658. Minimum Operations to Reduce X to Zero.py │ ├── 2009. Minimum Number of Operations to Make Array Continuous.py │ ├── 2024. Maximize the Confusion of an Exam.py │ ├── 209. Minimum Size Subarray Sum.py │ ├── 2302. Count Subarrays With Score Less Than K.py │ ├── 2398. Maximum Number of Robots Within Budget.py │ ├── 2444. Count Subarrays With Fixed Bounds.py │ ├── 2743. Count Substrings Without Repeating Character.py │ ├── 2762. Continuous Subarrays.py │ ├── 2765. Longest Alternating Subarray.py │ ├── 2779. Maximum Beauty of an Array After Applying Operation.py │ ├── 2857. Count Pairs of Points With Distance k.py │ ├── 2947. Count Beautiful Substrings I.py │ ├── 2949. Count Beautiful Substrings II.py │ ├── 2958. Length of Longest Subarray With at Most K Frequency.py │ ├── 2962. Count Subarrays Where Max Element Appears at Least K Times.py │ ├── 3. Longest Substring Without Repeating Characters.py │ ├── 3208. Alternating Groups II.py │ ├── 340-longest-substring-with-at-most-k-distinct-characters.py │ ├── 424. Longest Repeating Character Replacement.py │ ├── 523. Continuous Subarray Sum.py │ ├── 525. Contiguous Array.py │ ├── 560. Subarray Sum Equals K.py │ ├── 696. Count Binary Substrings.py │ ├── 713. Subarray Product Less Than K.py │ ├── 76. Minimum Window Substring.py │ ├── 862. Shortest Subarray with Sum at Least K.py │ ├── 930. Binary Subarrays With Sum.py │ ├── 974. Subarray Sums Divisible by K.py │ ├── 992. Subarrays with K Different Integers.py │ ├── Longest Subarray having sum of elements atmost k.py │ ├── Longest sub-array having sum k.py │ ├── Number of subarrays having sum less than K.py │ ├── Smallest Subarray with Sum K.py │ ├── Smallest subarray with sum greater than x.py │ ├── Subarray with given XOR.py │ └── longest substring with k unique characters.py ├── Sorting ├── 1122. Relative Sort Array.py ├── 1608. Special Array With X Elements Greater Than or Equal X.py ├── 2191. Sort the Jumbled Numbers.py ├── 2418. Sort the People.py ├── 3075. Maximize Happiness of Selected Children.py ├── 3111. Minimum Rectangles to Cover Points.py ├── 315. Count of Smaller Numbers After Self.py ├── 493. Reverse Pairs.py ├── 506. Relative Ranks.py ├── 775. Global and Local Inversions.py ├── 826. Most Profit Assigning Work.py ├── 945. Minimum Increment to Make Array Unique.py ├── Inversion count in Array .py ├── Minimum Swaps to Sort.py ├── bubble_sort.py ├── counting_sort.py ├── findkthSmallestVulnerability.py ├── heap_sort.py ├── heapq1.py ├── insertion_sort.py ├── max_heap_sort.py ├── merge_sort.py ├── min_heap_sort.py ├── quick_select.py ├── quick_sort.py └── selection_sort.py ├── Stack ├── 1047. Remove All Adjacent Duplicates In String.py ├── 1130. Minimum Cost Tree From Leaf Values.py ├── 1190. Reverse Substrings Between Each Pair of Parentheses.py ├── 1209. Remove All Adjacent Duplicates in String II.py ├── 1249. Minimum Remove to Make Valid Parentheses.py ├── 150. Evaluate Reverse Polish Notation(Evaluation of Postfix Expression).py ├── 155_Min_Stack.py ├── 1598. Crawler Log Folder.py ├── 1673. Find the Most Competitive Subsequence.py ├── 1717. Maximum Score From Removing Substrings.py ├── 1793. Maximum Score of a Good Subarray.py ├── 1966. Binary Searchable Numbers in an Unsorted Array.py ├── 20_Valid _Parentheses.py ├── 2116. Check if a Parentheses String Can Be Valid.py ├── 224. Basic Calculator.py ├── 225. Implement Stack using Queues.py ├── 227. Basic Calculator II.py ├── 2281. Sum of Total Strength of Wizards.py ├── 232. Implement Queue using Stacks.py ├── 2390. Removing Stars From a String.py ├── 2751. Robot Collisions.py ├── 2866. Beautiful Towers II.py ├── 316. Remove Duplicate Letters.py ├── 3174. Clear Digits.py ├── 32. Longest Valid Parentheses.py ├── 394. Decode String.py ├── 402. Remove K Digits.py ├── 456. 132 Pattern.py ├── 496. Next Greater Element I.py ├── 503. Next Greater Element II.py ├── 735. Asteroid Collision.py ├── 739. Daily Temperatures.py ├── 772 · Basic Calculator III.py ├── 84. Largest Rectangle in Histogram.py ├── 85. Maximal Rectangle in Binary Matrix.py ├── 853. Car Fleet.py ├── 856. Score of Parentheses.py ├── 895. Maximum Frequency Stack.py ├── 901. Online Stock Span.py ├── 907. Sum of Subarray Minimums.py ├── Encode given string by replacing substrings with prefix same as itself with star.py ├── Infix To Prefix.py ├── Infix to Postfix.py ├── Maximum of minimum for every window size.py ├── Next element with greater frequency.py ├── Next_greater_smaller_all_types.py ├── Prefix Evaluation .py └── The Celebrity Problem.py ├── String ├── 1427. Perform String Shifts.py ├── 1432. Max Difference You Can Get From Changing an Integer.py ├── 1507. Reformat Date.py ├── 1614. Maximum Nesting Depth of the Parentheses.py ├── 1790. Check if One String Swap Can Make Strings Equal.py ├── 2223. Sum of Scores of Built Strings.py ├── 2405. Optimal Partition of String.py ├── 2446. Determine if Two Events Have Conflict.py ├── 2645. Minimum Additions to Make Valid String.py ├── 271.Encode and Decode Strings.py ├── 2716. Minimize String Length.py ├── 2729. Check if The Number is Fascinating.py ├── 2734. Lexicographically Smallest String After Substring Operation.py ├── 2744. Find Maximum Number of String Pairs.py ├── 2745. Construct the Longest New String.py ├── 28. Find the Index of the First Occurrence in a String.py ├── 3008. Find Beautiful Indices in the Given Array II.py ├── 3106. Lexicographically Smallest String After Operations With Constraint.py ├── 3114. Latest Time You Can Obtain After Replacing Characters.py ├── 3163. String Compression III.py ├── 38. Count and Say.py ├── 443. String Compression.py ├── 522. Longest Uncommon Subsequence II.py ├── 68. Text Justification.py ├── 843. Guess the Word.py ├── 880. Decoded String at Index.py ├── Find smallest number formed by inserting given digit.py └── Good Binary Strings.py ├── Tree ├── .DS_Store ├── Binary Search Tree │ ├── 1008. Construct Binary Search Tree from Preorder Traversal.py │ ├── 1038. Binary Search Tree to Greater Sum Tree.py │ ├── 108. Convert Sorted Array to Binary Search Tree.py │ ├── 1373. Maximum Sum BST in Binary Tree.py │ ├── 1382. Balance a Binary Search Tree.py │ ├── 1569. Number of Ways to Reorder Array to Get Same BST.py │ ├── 173. Binary Search Tree Iterator.py │ ├── 230. Kth Smallest Element in a BST.py │ ├── 235. Lowest Common Ancestor of a Binary Search Tree.py │ ├── 333. Largest BST Subtree.py │ ├── 450. Delete Node in a BST.py │ ├── 530. Minimum Absolute Difference in BST.py │ ├── 653. Two Sum IV - Input is a BST.py │ ├── 701. Insert into a Binary Search Tree.py │ ├── 98. Validate Binary Search Tree.py │ ├── 99. Recover Binary Search Tree.py │ ├── Ancestors_of_a_node.py │ ├── BST operations.py │ ├── Construct BST from Postorder.py │ ├── Floor and Ceil from a BST.py │ ├── Kth largest element in BST.py │ └── Merge two BST 's.py ├── Binary Tree │ ├── 100. Same Tree.py │ ├── 1008. Construct Binary Search Tree from Preorder Traversal.py │ ├── 101. Symmetric Tree.py │ ├── 102. Binary Tree Level Order Traversal.py │ ├── 103. Binary Tree Zigzag Level Order Traversal.py │ ├── 104. Maximum Depth of Binary Tree.py │ ├── 105. Construct Binary Tree from Preorder and Inorder Traversal.py │ ├── 106. Construct Binary Tree from Inorder and Postorder Traversal.py │ ├── 110. Balanced Binary Tree.py │ ├── 111. Minimum Depth of Binary Tree.py │ ├── 1110. Delete Nodes And Return Forest.py │ ├── 113. Path Sum II.py │ ├── 114. Flatten Binary Tree to Linked List.py │ ├── 116. Populating Next Right Pointers in Each Node.py │ ├── 1161. Maximum Level Sum of a Binary Tree.py │ ├── 124. Binary Tree Maximum Path Sum.py │ ├── 129. Sum Root to Leaf Numbers.py │ ├── 1325. Delete Leaves With a Given Value.py │ ├── 1367. Linked List in Binary Tree.py │ ├── 1372. Longest ZigZag Path in a Binary Tree.py │ ├── 1448. Count Good Nodes in Binary Tree.py │ ├── 1609. Even Odd Tree.py │ ├── 199. Binary Tree Right Side View.py │ ├── 2096. Step-By-Step Directions From a Binary Tree Node to Another.py │ ├── 2196. Create Binary Tree From Descriptions.py │ ├── 222. Count Complete Tree Nodes.py │ ├── 2246. Longest Path With Different Adjacent Characters.py │ ├── 226. Invert Binary Tree.py │ ├── 2265. Count Nodes Equal to Average of Subtree.py │ ├── 226_Invert_Binary_Tree.py │ ├── 2331. Evaluate Boolean Binary Tree.py │ ├── 236. Lowest Common Ancestor of a Binary Tree.py │ ├── 2385. Amount of Time for Binary Tree to Be Infected.py │ ├── 2458. Height of Binary Tree After Subtree Removal Queries.py │ ├── 257. Binary Tree Paths.py │ ├── 2641. Cousins in Binary Tree II.py │ ├── 2673. Make Costs of Paths Equal in a Binary Tree.py │ ├── 297. Serialize and Deserialize Binary Tree.py │ ├── 2973. Find Number of Coins to Place in Tree Nodes.py │ ├── 427. Construct Quad Tree.py │ ├── 437. Path Sum III.py │ ├── 543. Diameter of Binary Tree.py │ ├── 545. Boundary of Binary Tree.py │ ├── 572. Subtree of Another Tree.py │ ├── 617. Merge Two Binary Trees.py │ ├── 623. Add One Row to Tree.py │ ├── 652. Find Duplicate Subtrees.py │ ├── 662. Maximum Width of Binary Tree.py │ ├── 814. Binary Tree Pruning.py │ ├── 863. All Nodes Distance K in Binary Tree.py │ ├── 958. Check Completeness of a Binary Tree.py │ ├── 968. Binary Tree Cameras.py │ ├── 971. Flip Binary Tree To Match Preorder Traversal.py │ ├── 979. Distribute Coins in Binary Tree.py │ ├── 987. Vertical Order Traversal of a Binary Tree.py │ ├── 988. Smallest String Starting From Leaf.py │ ├── 993. Cousins in Binary Tree.py │ ├── Bottom View of Binary Tree.py │ ├── Burn the binary tree starting from the target node.py │ ├── Burning Tree.py │ ├── Children Sum Property.py │ ├── Diagonal Traversal of Binary Tree.py │ ├── Leaves_total_depth.py │ ├── Left View of a Binary Tree.py │ ├── Min distance between two given nodes of a Binary Tree.PY │ ├── Morris Traversal Inorder and Preorder.py │ ├── Preorder inorder postorder in a single traversal.py │ ├── Sum Tree.py │ ├── Top View of Binary Tree.py │ ├── Tree Traversals.py │ └── path from root to a given node in a binary tree.py └── N-Ary Tree │ └── 590. N-ary Tree Postorder Traversal.py ├── Tries ├── 14. Longest Common Prefix.py ├── 1698. Number of Distinct Substrings in a String.py ├── 1707. Maximum XOR With an Element From Array.py ├── 1803. Count Pairs With XOR in a Range.py ├── 1804. Implement Trie II (Prefix Tree).py ├── 1858. Longest word with all prefixes.py ├── 208. Implement Trie (Prefix Tree).py ├── 211. Design Add and Search Words Data Structure.py ├── 212. Word Search II.py ├── 2185. Counting Words With a Given Prefix.py ├── 2781. Length of the Longest Valid Substring.py ├── 3076. Shortest Uncommon Substring in an Array.py ├── 421. Maximum XOR of Two Numbers in an Array.py ├── 648. Replace Words.py ├── 677. Map Sum Pairs.py ├── 720. Longest Word in Dictionary.py ├── Implement a Phone Directory.py └── Maximum XOR.py ├── Two Pointer ├── 11. Container With Most Water.py ├── 125. Valid Palindrome.py ├── 1498. Number of Subsequences That Satisfy the Given Sum Condition.py ├── 15. 3Sum.py ├── 151. Reverse Words in a String.py ├── 165. Compare Version Numbers.py ├── 167. Two Sum II - Input Array Is Sorted.py ├── 1750. Minimum Length of String After Deleting Similar Ends.py ├── 179. Largest Number.py ├── 18. 4Sum.py ├── 2018. Check if Word Can Be Placed In Crossword.py ├── 2193. Minimum Number of Moves to Make Palindrome.py ├── 2486. Append Characters to String to Make Subsequence.py ├── 2526. Find Consecutive Integers from a Data Stream.py ├── 2540. Minimum Common Value.py ├── 26. Remove Duplicates from Sorted Array.py ├── 264. Ugly Number II.py ├── 2697. Lexicographically Smallest Palindrome.py ├── 2730. Find the Longest Semi-Repetitive Substring.py ├── 283. Move Zeroes.py ├── 2856. Minimum Array Length After Pair Removals.py ├── 2972. Count the Number of Incremovable Subarrays II.py ├── 31. Next Permutation.py ├── 392. Is Subsequence.py ├── 415. Add Strings.py ├── 42. Trapping Rain Water.py ├── 54. Spiral Matrix.py ├── 556. Next Greater Element III.py ├── 581. Shortest Unsorted Continuous Subarray.py ├── 59. Spiral Matrix II.py ├── 633. Sum of Square Numbers.py ├── 75. Sort Colors.py ├── 844. Backspace String Compare.py ├── 88. Merge Sorted Array.py ├── 881. Boats to Save People.py ├── 885. Spiral Matrix III.py ├── 905. Sort Array By Parity.py ├── 948. Bag of Tokens.py ├── 977. Squares of a Sorted Array.py ├── Count pairs Sum in matrices.py ├── Count pairs in a sorted array whose sum is less than x.py ├── Count the triplets.py ├── Find pair for a sum in sorted rotated array.py ├── Find the closest pair from two sorted arrays.py ├── Merge Without Extra Space.py ├── Print alternate odd even in given order.py ├── Rearrange positive and negative numbers alternately.py └── Smallest Difference pair of values between two unsorted Arrays.py └── recursion ├── 1342_steps_to_reudce_to_zero.py ├── 344_string_reverse.py ├── 50. Pow(x, n).py ├── array _sorted_or_not.py ├── basic.py ├── binary_search.py ├── linear_search.py ├── reverse_a_number.py ├── steps ├── tempCodeRunnerFile.py └── tower_hanoi.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ravi-0412/DSA-Program-And-Notes/3961bd7499d9a3e2623207ebfab8a34ba40b50c2/.DS_Store -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Python: Current File", 9 | "type": "python", 10 | "request": "launch", 11 | "program": "${file}", 12 | "console": "integratedTerminal", 13 | "justMyCode": true 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "iostream": "cpp" 4 | } 5 | } -------------------------------------------------------------------------------- /3341. Find Minimum Time to Reach Last Room I.py: -------------------------------------------------------------------------------- 1 | # Just similar logic as : "778. Swim in Rising Water" 2 | 3 | # time: O(4*n*m) , we can visit same cell four time from four different directions. 4 | 5 | class Solution: 6 | def minTimeToReach(self, moveTime: List[List[int]]) -> int: 7 | n, m = len(moveTime), len(moveTime[0]) 8 | directions = [[0, -1], [0, 1], [-1, 0], [1, 0]] # left, right, up , down 9 | minTime = [[float('inf') for j in range(m)] for i in range(n)] 10 | minHeap = [] 11 | heapq.heappush(minHeap, (0, 0, 0)) 12 | visited = set() 13 | while minHeap: 14 | time, r, c = heapq.heappop(minHeap) 15 | if r == n - 1 and c == m - 1: 16 | return time 17 | visited.add((r, c)) 18 | for dr, dc in directions: 19 | r1, c1 = r + dr , c + dc 20 | if 0 <= r1 < n and 0 <= c1 < m and (r1, c1) not in visited: 21 | min_time_required = max(moveTime[r1][c1], time) + 1 22 | if minTime[r1][c1] > min_time_required: 23 | heapq.heappush(minHeap, (min_time_required, r1, c1)) 24 | minTime[r1][c1] = min_time_required 25 | 26 | 27 | # Related q: 28 | # 1) 3342. Find Minimum Time to Reach Last Room II 29 | -------------------------------------------------------------------------------- /Array/1389_target_array.py: -------------------------------------------------------------------------------- 1 | # 1st method: 2 | # time= o(n^2) ,space= o(n) 3 | 4 | class Solution: 5 | def createTargetArray(self, nums: List[int], index: List[int]) -> List[int]: 6 | n= len(nums) 7 | target=[] 8 | for i in range(n): 9 | target.insert(index[i],nums[i]) # O(n) each time 10 | return target 11 | 12 | 13 | # Method 2: Best 14 | # Time: O(n*logn) 15 | # Can done by method of Q : "315. Count of Smaller Numbers After Self". 16 | # Time: O(n* logn) 17 | 18 | # Link: https://leetcode.com/problems/create-target-array-in-the-given-order/solutions/549583/o-nlogn-based-on-smaller-elements-after-self/ 19 | -------------------------------------------------------------------------------- /Array/1800. Maximum Ascending Subarray Sum.py: -------------------------------------------------------------------------------- 1 | # Time : O(n), space: O(1) 2 | 3 | class Solution: 4 | def maxAscendingSum(self, nums: List[int]) -> int: 5 | curr = ans = nums[0] 6 | for i in range(1, len(nums)): 7 | curr = curr + nums[i] if nums[i] > nums[i-1] else nums[i] 8 | ans = max(ans, curr) 9 | return ans 10 | 11 | # Java 12 | """ 13 | class Solution { 14 | public int maxAscendingSum(int[] nums) { 15 | int curr = nums[0], ans = nums[0]; 16 | for (int i = 1; i < nums.length; i++) { 17 | curr = nums[i] > nums[i - 1] ? curr + nums[i] : nums[i]; 18 | ans = Math.max(ans, curr); 19 | } 20 | return ans; 21 | } 22 | } 23 | """ 24 | -------------------------------------------------------------------------------- /Array/2073. Time Needed to Buy Tickets.py: -------------------------------------------------------------------------------- 1 | # Logic; On left of 'k' , maximum we can add time = tickets[k] for each ticket. 2 | # On left,maximum we can add time = tickets[k] - 1 for each ticket. 3 | 4 | 5 | class Solution: 6 | def timeRequiredToBuy(self, tickets: List[int], k: int) -> int: 7 | n = len(tickets) 8 | ans = tickets[k] 9 | for i in range(k): 10 | ans += min(tickets[k] , tickets[i]) 11 | for i in range(k+1, n): 12 | ans += min(tickets[k] - 1, tickets[i]) 13 | return ans -------------------------------------------------------------------------------- /Array/2656. Maximum Sum With Exactly K Elements .py: -------------------------------------------------------------------------------- 1 | # to get the maximum sum in 'k' operation we will pick each time max ele only. 2 | # for this 1st find the max ele and then each operation we have to incr this. 3 | 4 | # Time = Max(n, k) 5 | 6 | class Solution: 7 | def maximizeSum(self, nums: List[int], k: int) -> int: 8 | max_ele= max(nums) 9 | sum= 0 10 | for i in range(k): 11 | sum+= max_ele 12 | max_ele+= 1 # incr each time max_ele by 1 13 | return sum 14 | 15 | # Other way 16 | # Logic: Find maximum element + formula 17 | class Solution: 18 | def maximizeSum(self, n: List[int], k: int) -> int: 19 | return k * max(n) + k * (k - 1) // 2; 20 | -------------------------------------------------------------------------------- /Array/2679. Sum in a Matrix.py: -------------------------------------------------------------------------------- 1 | # Logic: just sort all 1D array. 2 | # Then go column wise and take max ele of that column and add it to ans. 3 | # time: O(r*c*logc) 4 | class Solution: 5 | def matrixSum(self, nums: List[List[int]]) -> int: 6 | r, c= len(nums), len( nums[0]) 7 | for i in range(r): 8 | nums[i].sort() 9 | ans= 0 10 | for i in range(c): 11 | mx= float('-inf') 12 | for j in range(r): 13 | mx= max(mx, nums[j][i]) 14 | ans+= mx 15 | return ans 16 | -------------------------------------------------------------------------------- /Array/2706. Buy Two Chocolates.py: -------------------------------------------------------------------------------- 1 | # Logic: Just find the first two minimum and its sum. 2 | 3 | # time: O(n) 4 | 5 | class Solution: 6 | def buyChoco(self, prices: List[int], money: int) -> int: 7 | firstMin, secondMin = 10**5 + 1, 10**5 + 1 8 | for num in prices: 9 | if num < firstMin: 10 | secondMin = firstMin 11 | firstMin = num 12 | elif num < secondMin: 13 | secondMin = num 14 | return money if firstMin + secondMin > money else money - (firstMin + secondMin) -------------------------------------------------------------------------------- /Array/2739. Total Distance Traveled.py: -------------------------------------------------------------------------------- 1 | # logic: After every 5 litre consumption we will add '1' more litre from additional only if additional will be present. 2 | 3 | class Solution: 4 | def distanceTraveled(self, mainTank: int, additionalTank: int) -> int: 5 | if mainTank <= 4: 6 | return mainTank * 10 7 | ans = 0 8 | while mainTank >= 5 and additionalTank > 0: 9 | ans += 5 * 10 10 | mainTank = mainTank - 5 + 1 11 | additionalTank -= 1 12 | ans += mainTank * 10 13 | return ans 14 | 15 | 16 | # METHOD 2: 17 | # very short . Before i was thinking in somewhat this way only. 18 | 19 | # Logic: main tank me kitna extra fuel add hoga. 20 | # Har 5 ke bad 1 litre means agar '5' litre use kiya to actual me main tank se '4' litre hi jayeya 21 | # kyonki hm 1 litre add kar denge except 1st time(isliye '-1'). 22 | 23 | 24 | class Solution: 25 | def distanceTraveled(self, mainTank: int, additionalTank: int) -> int: 26 | return (mainTank + min((mainTank -1)//4, additionalTank)) * 10 27 | 28 | # similar q: 29 | # 1) 3100. Water Bottles II -------------------------------------------------------------------------------- /Array/3100. Water Bottles II.py: -------------------------------------------------------------------------------- 1 | # Just same as :"2739. Total Distance Traveled" 2 | 3 | class Solution: 4 | def numWaterBottles(self, numBottles: int, numExchange: int) -> int: 5 | ans = numBottles 6 | # Run till we can exchange 7 | while numBottles >= numExchange: 8 | numBottles = numBottles - numExchange + 1 9 | ans += 1 10 | return ans 11 | 12 | # Method 2: 13 | # in one line 14 | # 'numExchange' empty karne pe '1' bottle mil hi jayega isliye actual me 'numExchange - 1' empty hoga, 15 | # except 1st time(isliye '-1'). 16 | 17 | class Solution: 18 | def numWaterBottles(self, numBottles: int, numExchange: int) -> int: 19 | return numBottles + (numBottles - 1) // (numExchange - 1) 20 | -------------------------------------------------------------------------------- /Array/3105. Longest Strictly Increasing or Strictly Decreasing Subarray.py: -------------------------------------------------------------------------------- 1 | # Method 1: 2 | class Solution: 3 | def longestMonotonicSubarray(self, nums: List[int]) -> int: 4 | if not nums: 5 | return 0 6 | max_len = inc = dec = 1 7 | for i in range(1, len(nums)): 8 | if nums[i] > nums[i-1]: 9 | inc += 1 # ↗️ Case 10 | dec = 1 11 | elif nums[i] < nums[i-1]: 12 | dec += 1 # ↘️ Case 13 | inc = 1 14 | else: 15 | inc = dec = 1 # 🟡 Case 16 | max_len = max(max_len, inc, dec) # Update ans 17 | return max_len 18 | 19 | # Method 2: 20 | class Solution: 21 | def longestMonotonicSubarray(self, nums: List[int]) -> int: 22 | n, ans, inc, dec=len(nums), 1, 1, 1 23 | for i in range(1, n): 24 | A=nums[i] > nums[i-1] # A = 1 if condition follows, else 0 25 | B=nums[i] < nums[i-1] # B = 1 if condition follows, else 0 26 | inc=A*inc+1 27 | dec=B*dec+1 28 | ans=max(ans, dec, inc) 29 | return ans 30 | -------------------------------------------------------------------------------- /Array/3168. Minimum Number of Chairs in a Waiting Room.py: -------------------------------------------------------------------------------- 1 | # Logic: 2 | """ 3 | # we need to keep track of how many people are in the waiting room at any given time and 4 | # determine the peak number of people present simultaneously. This peak value will 5 | # represent the minimum number of chairs required since every person needs a chair when they enter. 6 | """ 7 | # How to do? 8 | # maximum no of chair = max value of count 9 | # where we increase count by '1' when any person enter 'E' and decrease by '1' 10 | # when any person leave 'L'. 11 | 12 | class Solution(object): 13 | def minimumChairs(self, s): 14 | res = 0 15 | max_chairs = 0 16 | for i in s: 17 | if i == 'E': 18 | res += 1 19 | max_chairs = max(res, max_chairs) 20 | else: 21 | res -= 1 22 | return max_chairs 23 | -------------------------------------------------------------------------------- /Array/Birthday Party and Return Gift.py: -------------------------------------------------------------------------------- 1 | def findKid(N, T, D): 2 | # first find the anser for 0- based indexing in this type of cyclic question. 3 | # (D + T- 1) : last one will be this person only because it will start from 'Dth person' so subtracting '-1'. 4 | ans = ((D + T- 1) -1) % N # Again subtracting '-1' for bring into '0 - based' indexing. 5 | # for converting into 1-based indexing add '1'. 6 | return ans + 1 7 | -------------------------------------------------------------------------------- /Array/Longest subsequence having equal numbers of 0 and 1.py: -------------------------------------------------------------------------------- 1 | # logic: 2 | """ 3 | count zeros & ones in a binary array and last return minimum between count of zeros & ones by multiplying it with 2. 4 | Reason: Since binary array and we are asked to find subsequence(not subarray), so we can take take min(no_one, no_zero) 5 | and make a valid subsequence from those numbers. so ans = min(no_one, no_zero) * 2. 6 | 7 | Note: Same Question for longest subarray. (525. Contiguous Array) 8 | """ 9 | 10 | # Time = O(n), space = O(1) 11 | 12 | def largestSubsequence(arr,n): 13 | # store count of zeros and one 14 | countzero = 0 15 | countone = 0 16 | 17 | # traverse binary array and count 18 | # zeros and ones 19 | for i in range(n): 20 | if arr[i]: 21 | countone += 1 22 | else: 23 | countzero += 1 24 | return min(countone, countzero) * 2 25 | 26 | 27 | arr = [ 1, 0, 0, 1, 0, 0, 0, 1 ] 28 | n = len(arr) 29 | print("largest Subsequences having" + 30 | " equal number of 0 & 1 is ", 31 | largestSubsequence(arr, n)) 32 | -------------------------------------------------------------------------------- /Array/Python program to make a list even odd parity.py: -------------------------------------------------------------------------------- 1 | # Logic: 2 | """ 3 | first element can be either odd or even". 4 | so find ans taking 1st element as odd and 1st element as even. 5 | And for final answer take minimum of both cases. 6 | """ 7 | # time : O(n* logn) 8 | def helper(items, expected): 9 | countOp = 0 10 | for i in items: 11 | while i % 2 != expected: 12 | if not i: 13 | # if expected is 1 and i is 0 (not i) then, only in this case it will execute 14 | return float("inf") # Not possible 15 | i //= 2 16 | countOp += 1 17 | expected = 1 - expected # or 1 ^ expected 18 | return countOp 19 | 20 | def getMinimumOperations(items): 21 | return min(helper(items, 1), helper(items, 0)) 22 | 23 | items = [6, 5, 9, 7, 3] 24 | print("ans = ", getMinimumOperations(items)) -------------------------------------------------------------------------------- /Back_Tracking/1723. Find Minimum Time to Finish All Jobs.py: -------------------------------------------------------------------------------- 1 | # Exacly same as "2305. Fair Distribution of Cookies". 2 | 3 | # Logic: Cur job can be assigned to any worker. 4 | 5 | # Time: O(n^k) 6 | 7 | class Solution: 8 | def minimumTimeRequired(self, jobs: List[int], k: int) -> int: 9 | n = len(jobs) 10 | self.ans = float('inf') 11 | # jobs.sort(reverse = True) 12 | sums = [0]*k 13 | 14 | def backtrack(i): 15 | if i == n: 16 | # we have to update ans 17 | # first find the max sum of all partition and then update the ans. 18 | maxSum = max(sums) 19 | self.ans = min(self.ans, maxSum) 20 | return 21 | for j in range(k): 22 | if sums[j] + jobs[i] < self.ans: # optimisation 23 | sums[j] += jobs[i] 24 | backtrack(i + 1) 25 | sums[j] -= jobs[i] 26 | if sums[j] == 0: # optimisation 27 | return 28 | 29 | backtrack(0) 30 | return self.ans -------------------------------------------------------------------------------- /Back_Tracking/216. Combination Sum III.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def combinationSum3(self, k: int, n: int) -> List[List[int]]: 3 | ans = [] 4 | 5 | def dfs(i, n, combination): 6 | if i >= 10: 7 | return 8 | if n == 0: 9 | if len(combination) == k: 10 | ans.append(combination) 11 | return 12 | dfs(i + 1, n, combination) 13 | if n >= i: 14 | dfs(i + 1, n - i , combination + [i]) 15 | 16 | dfs(1, n, []) 17 | return ans 18 | -------------------------------------------------------------------------------- /Back_Tracking/93. Restore IP Addresses.py: -------------------------------------------------------------------------------- 1 | # time: O(3^4) 2 | 3 | # maximum recursion depth will go: '4' because we only need to form '4' dots. 4 | 5 | class Solution: 6 | def restoreIpAddresses(self, s: str) -> List[str]: 7 | if len(s) > 12 : 8 | return [] 9 | ans= [] 10 | 11 | def backtrack(i, dots, curIP): 12 | if dots== 4 and i== len(s): 13 | ans.append(curIP[:-1]) # to remove the last dot 14 | return 15 | if dots > 4 : 16 | return 17 | # for next dot we only need to check the next three char because 4 char together will be sure > 255. 18 | for j in range(i, min(i+3, len(s))): 19 | # checking integer value must be <= 255 and there is no leading zeroes. 20 | # for leading zeroes: # take 1 digit is always good 21 | #take 2 or 3 digits etc, first digit cannot be '0' 22 | if int(s[i: j+1]) <= 255 and (i== j or s[i] != "0"): 23 | backtrack(j+1, dots + 1, curIP + s[i: j+1] + ".") 24 | 25 | backtrack(0, 0, "") 26 | return ans 27 | -------------------------------------------------------------------------------- /Back_Tracking/No of ways to get a given sum in a dice.py: -------------------------------------------------------------------------------- 1 | 2 | # Here we can throw same dice again and again 3 | 4 | # in notes 5 | def Form_Num(num,ans): 6 | res= [] 7 | if num==0: 8 | return [ans] 9 | for i in range(1,num+1): # add num <= given and call the fn again for remaining no. This is just like calling the same dice again & again. 10 | res+= Form_Num(num-i,ans+ str(i)) 11 | return res 12 | 13 | print(Form_Num(4,"")) 14 | # print(Form_Num(6,"")) -------------------------------------------------------------------------------- /Back_Tracking/Rat in a Maze Problem - I.py: -------------------------------------------------------------------------------- 1 | # totally same as "path_in_grid_with_DLRU" 2 | -------------------------------------------------------------------------------- /Back_Tracking/tempCodeRunnerFile.py: -------------------------------------------------------------------------------- 1 | arr= [17, 18, 6, 11, 2, 4] 2 | # k = 6 3 | # PrintSubsequence4(arr,[],k) -------------------------------------------------------------------------------- /Basic Math/binary_decimal_4.py: -------------------------------------------------------------------------------- 1 | # 1: Converting decimal to binary 2 | # print(bin(n).replace("0b","")) # to convert decimal to binary 3 | # e.g: 4 | print(bin(10).replace("0b","")) 5 | 6 | # by normal method: 7 | def DecimalToBinary(num): 8 | if num >= 1: 9 | DecimalToBinary(num // 2) 10 | print(num%2, end="") 11 | # OR 12 | # def DecimalToBinary(num): 13 | # if num ==0: 14 | # return 15 | # DecimalToBinary(num // 2) 16 | # print(num%2, end="") 17 | 18 | # 2: converting binary to decimal 19 | # print(int('n',2)) # to convert binary to decimal , 20 | # '2' is any base from which you want to convert to decimal equivalent 21 | # e.g: 22 | print(int('1010',2)) 23 | print(int('1010',3)) # will convert '1010' in base 3 to decimal 24 | 25 | 26 | # to calculate the hamming distance between two numbers 27 | a=6 28 | b=9 29 | c=a^b 30 | print(bin(c).replace("0b","").count('1')) # will calculate the hamming distance bw two +ve integer -------------------------------------------------------------------------------- /Basic Math/factors_1.py: -------------------------------------------------------------------------------- 1 | # time complexity: sqrt(n) 2 | # logic: take n= 20, if 2 divides 20 , then 3 | # 10 will also divide 20 as 2*10= 20 4 | # so no need to check for 10 again & so on for other no.. only to check till 5 | 6 | def factors(n): 7 | i= 1 8 | ans= [] # to print into sorted and proper order 9 | while(i*i<=n): 10 | if n%i== 0: 11 | j= n/i 12 | print(i, end=" ") # smaller factor printing and larger factors storing in ans to print at last 13 | # print(int(j), end=" ") # will print in improper order 14 | ans.append(j) # will store in descending order 15 | i+= 1 16 | # now print the 'upper' from right side to get all factors in ascending order 17 | for i in range(len(ans)-1,-1,-1): 18 | print(int(ans[i]),end=" ") 19 | 20 | factors(20) 21 | 22 | -------------------------------------------------------------------------------- /Basic Math/hcf_lcm_3.py: -------------------------------------------------------------------------------- 1 | # hcf by euclid's algo 2 | # time: O(log(min(a, b)) 3 | # just same as we calculate the hcf on paper 4 | def hcf(a,b): 5 | if a==0: 6 | return b 7 | return hcf((b%a),a) # or hcf(a,(a%b)) 8 | 9 | # other method ,diff is working same as '%' 10 | # same logic as above, here we are taking difference instead of '%' 11 | # so checking which one is greater first 12 | def hcf(a,b): 13 | if a==0: 14 | return b 15 | if b==0: 16 | return a 17 | if a==b: 18 | return a 19 | if a>b: 20 | return hcf((a-b),b) 21 | return hcf(a,b-a) 22 | # or use the same above logic with DP 23 | 24 | 25 | def lcm(a,b): 26 | return (int((a*b)/(hcf(a,b)))) # By 'Lcm*Hcf= Product of two number' 27 | 28 | print(hcf(6,32)) 29 | print(lcm(9,18)) 30 | -------------------------------------------------------------------------------- /Basic Math/newton_sqrt.py: -------------------------------------------------------------------------------- 1 | # other two methods are by 'Binary Search' 2 | # method3: by Newton Raph son method 3 | # formaula: root= (x +N/x)/2, where root is the actual root and 4 | # x is the root we have assumed 5 | # logic: take x= n itsef for 1st time, and cal the root 6 | # if fabs(root-x) 'num' then means we have to divide 'nums[i]' 6 | # and no of operations required to divide will be equal to : ceil(nums[i] / num) - 1 7 | # '-1' because for getting 'n+1' numbers from a single number we need 'n' operations. 8 | 9 | # Time : O(n *log(max(nums))) 10 | 11 | class Solution: 12 | def minimumSize(self, nums: List[int], maxOperations: int) -> int: 13 | 14 | # is it possible to divide 'nums' having maximum value as 'num' in 'maxOperations' ? 15 | def isPossible(num): 16 | operation = 0 17 | for i in range(len(nums)): 18 | if nums[i] > num: 19 | operation += ceil(nums[i] / num) - 1 20 | return operation <= maxOperations 21 | 22 | start , end = 1, max(nums) # maximum value we can get = max(nums) 23 | while start < end: 24 | mid = start + (end - start) // 2 25 | if isPossible(mid): 26 | end = mid 27 | else: 28 | start = mid + 1 29 | return start -------------------------------------------------------------------------------- /Binary_Search/278. First Bad Version.py: -------------------------------------------------------------------------------- 1 | # submitted on lintcode 2 | def findFirstBadVersion(self, n): 3 | low, up= 1, n 4 | while low < up: 5 | mid= low + (up- low)//2 6 | if SVNRepo.isBadVersion(mid): # then search for even more smaller 7 | up= mid 8 | else: # else we have to find the greater one. 9 | low= mid+ 1 10 | return low 11 | -------------------------------------------------------------------------------- /Binary_Search/374. Guess Number Higher or Lower.py: -------------------------------------------------------------------------------- 1 | # time; O(logn) 2 | class Solution: 3 | def guessNumber(self, n: int) -> int: 4 | start, end= 1, n 5 | while start <= end: 6 | mid= start + (end- start)//2 7 | if guess(mid)== 0: # for calling predefined api no need to call with 'self'. 8 | return mid 9 | elif guess(mid)== -1: 10 | end= mid -1 11 | else: 12 | start= mid + 1 13 | 14 | # Alternate way: 15 | # template 2 16 | class Solution: 17 | def guessNumber(self, n: int) -> int: 18 | start, end= 1, n 19 | while start < end: 20 | mid= start + (end- start)//2 21 | if guess(mid) <=0: #if num >= picked. search for even more smaller 22 | end= mid 23 | else: 24 | start= mid + 1 25 | return start -------------------------------------------------------------------------------- /Binary_Search/400. Nth Digit.py: -------------------------------------------------------------------------------- 1 | # logic: 2 | # Straight forward way to solve the problem in 3 steps: 3 | 4 | # find the length of the number where the nth digit is from 5 | # find the actual number where the nth digit is from 6 | # find the nth digit and return 7 | 8 | # time:O(logn) 9 | 10 | class Solution: 11 | def findNthDigit(self, n: int) -> int: 12 | length= 1 # will give the number of digits in the target number 13 | start= 1 # will give the first number in which 'n' lies 14 | count= 9 # no of '1' length no = 9, '2' length = 90 , '3' length = 900 and so on 15 | # 1st find the length of digit in target number i.e range in which our target number lies. 16 | while n > length *count: 17 | n-= length * count 18 | count*= 10 # 9, 90, 900, 9000 19 | start*= 10 # 1, 10, 100, 1000,.... 20 | length+= 1 #1, 2, 3,.... 21 | # Now find the target number. Target number is 'n' digit aheead from the start i.e 1st number in range. 22 | number= start + ((n-1) //length) # '0' indexing in digit (0-9) 23 | # find the index that we have to get in final number 24 | index= ((n-1) % length) 25 | # find the required digit. 26 | return int(str(number)[index]) 27 | 28 | -------------------------------------------------------------------------------- /Binary_Search/410. Split Array Largest Sum.py: -------------------------------------------------------------------------------- 1 | # just exactly same as "Allocate minimum no of pages". 2 | class Solution: 3 | def splitArray(self, nums: List[int], m: int) -> int: 4 | start, end, n= max(nums), sum(nums), len(nums) 5 | while start< end: 6 | mid= start + (end-start)//2 7 | if self.IsValid(nums,n,m,mid): 8 | end= mid 9 | else: 10 | start= mid + 1 11 | return start 12 | 13 | def IsValid(self, a, n, m, max_sum): 14 | k, sum= 1, 0 15 | for i in range(n): 16 | sum+= a[i] 17 | if sum > max_sum: # in this case we will increase the no of student 18 | # and start allocating the books to the new student 19 | k+= 1 20 | sum= a[i] 21 | # and at last we we will compare the no of students with M(# student given in the Q) 22 | # if < M means allocation is possible otherwise not possible 23 | return False if k > m else True 24 | -------------------------------------------------------------------------------- /Binary_Search/744. Find Smallest Letter Greater Than Target.py: -------------------------------------------------------------------------------- 1 | # exactly same as binary search 2 | # just like we find the last position of an element. 3 | class Solution: 4 | def nextGreatestLetter(self,letters, target): 5 | n= len(letters) 6 | low= 0 7 | high= n-1 8 | while(low<= high): 9 | mid = low+ (high- low)//2 10 | if letters[mid] <= target: # in case if equal also then we will search for next greater 11 | 12 | # and for this we have to update low= mid+1 13 | low = mid+ 1 14 | else: 15 | high = mid-1 16 | return letters[(low)%n] # taking modulus to handle the case when ans doesn't exist. 17 | # in this case low will be= n and we have to return the 0th index letter only and 18 | # if exist then low will give the ans directly. 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Binary_Search/792. Number of Matching Subsequences.py: -------------------------------------------------------------------------------- 1 | # Logic: 1) Store all the indices of a character in a list. 2 | # 2) for each word check if all character indexes are in increasing order. 3 | # if in increasing order then that is one of the subseqence. 4 | 5 | class Solution: 6 | def numMatchingSubseq(self, s: str, words: List[str]) -> int: 7 | indexes = collections.defaultdict(list) 8 | # store indices of all character in a list 9 | for i, c in enumerate(s): 10 | indexes[c].append(i) 11 | ans = 0 12 | for word in words: 13 | pre = -1 14 | isSub = True 15 | for c in word: 16 | # find if any index exist for 'c' which is >= pre. 17 | next = bisect.bisect_right(indexes[c] , pre) 18 | if next >= len(indexes[c]): 19 | # No possible index 20 | isSub = False 21 | break 22 | else: 23 | # update pre 24 | pre = indexes[c][next] 25 | ans = ans + 1 if isSub else ans 26 | return ans 27 | 28 | 29 | # Note: Say given any char occur maxium 2 times. 30 | # then we only need to store the 1st and last index. 31 | # then , for each char check first with its first index then with 2nd index for increasing order of indexes. -------------------------------------------------------------------------------- /Binary_Search/852. Peak Index in a Mountain Array.py: -------------------------------------------------------------------------------- 1 | 2 | # Note: exact same as '162. FindPeakIndex'. in this there will be only one peak ele 3 | # other things are totally same as '162. find peak index'. 4 | 5 | # method 2: 6 | 7 | class Solution: 8 | def peakIndexInMountainArray(self, nums: List[int]) -> int: 9 | start= 0 10 | end= len(nums)-1 11 | while start < end: 12 | mid= start+ (end-start)//2 13 | # in which direction we should move 14 | # will depend on the value of arr[mid] and arr[mid+1] 15 | if nums[mid] > nums[mid+1]: 16 | # means we are in decr part of array 17 | # so our ans will lie on the left hand side of mid including 'mid' 18 | end= mid 19 | else: # peak(maximum ele) will be on left side of mid including mid 20 | start= mid +1 21 | return start 22 | 23 | 24 | # Later learn and do by 'Golden-section search'. 25 | # Last solution of link : https://leetcode.com/problems/peak-index-in-a-mountain-array/solutions/139848/c-java-python-better-than-binary-search/ -------------------------------------------------------------------------------- /Binary_Search/Counting elements in two arrays.py: -------------------------------------------------------------------------------- 1 | # logic: find the 'index of first greater ele in arr2 for each number num in arr1'. 2 | # this will give the number of ele in arr2 which is <= each number in arr1. 3 | 4 | # for this we need to sort 'arr2' and then search the index using binary search. 5 | 6 | # Time Complexity: O((m + n) * log n) 7 | 8 | class Solution: 9 | def countEleLessThanOrEqual(self,arr1,n1,arr2,n2): 10 | arr2.sort() 11 | ans= [] 12 | 13 | def lastIndex(num): 14 | start, end= 0, len(arr2) -1 15 | while start <= end: 16 | mid= start + (end - start)//2 17 | if arr2[mid] <= num: 18 | start= mid + 1 19 | else: 20 | end= mid - 1 21 | return start 22 | 23 | for num in arr1: 24 | ind= lastIndex(num) # find the last index of 'num' into arr2. 25 | ans.append(ind) 26 | return ans 27 | -------------------------------------------------------------------------------- /Binary_Search/Find median in row wise sorted matrix.py: -------------------------------------------------------------------------------- 1 | # just find the no of elements greater than each 'mid' like "378.kth smallest ele" 2 | # any ele is greater than half of the ele then that will be the median. 3 | 4 | # here k = 'm*n' // 2 5 | -------------------------------------------------------------------------------- /Binary_Search/Find the Rotation Count in Rotated Sorted array.py: -------------------------------------------------------------------------------- 1 | # no of rotation will be equal to index of minimum element in the array 2 | # so just we have to find the minimum element index 3 | # minimum/max ele will always exist in the unsorted part 4 | class Solution: 5 | def findKRotation(self,nums, n): 6 | left, right = 0, len(nums)-1 7 | while left < right: 8 | mid = (left + right) // 2 9 | if nums[mid] > nums[right]: # means array from 'mid' to 'right' is unsorted 10 | left = mid + 1 # so minimum will lie in this part only i.e beyond mid 11 | 12 | else: 13 | # here it will guarantee that array from 14 | # mid to right is sorted and start to mid is unsorted and mid can also be minimum 15 | right = mid 16 | return left # returning the index of minimum ele -------------------------------------------------------------------------------- /Binary_Search/Find the row with maximum number of 1s.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ravi-0412/DSA-Program-And-Notes/3961bd7499d9a3e2623207ebfab8a34ba40b50c2/Binary_Search/Find the row with maximum number of 1s.py -------------------------------------------------------------------------------- /Binary_Search/Nth Root Of M.py: -------------------------------------------------------------------------------- 1 | # submitted on codeStudio but give incorrect ans for one test case(6th decimal place incorrect only) 2 | 3 | def findNthRootOfM(n,m): 4 | low, up= 1, m 5 | precision= 10**-7 # we have to find till 6 decimal places 6 | while up - low> precision: # just like while low< up => while up-low>0 instead of '0' we are comapring with precision. 7 | mid= float(low + (up-low)/2) 8 | if multiply(mid, n) >= m: 9 | up= mid 10 | else: 11 | low= mid+ precision 12 | return ('%.6f' % low) # to return ans with '6' decimal places 13 | 14 | def multiply(number, n): 15 | ans= 1 16 | for i in range(n): 17 | ans*= number 18 | return ans 19 | 20 | # can use the same logic to find the square root of a number with decimal places. 21 | -------------------------------------------------------------------------------- /Binary_Search/The Painter's Partition Problem-II.py: -------------------------------------------------------------------------------- 1 | # Just exactly same as 'Allocate minimum no of pages'. 2 | -------------------------------------------------------------------------------- /Binary_Search/linear_search.py: -------------------------------------------------------------------------------- 1 | def linear_search(arr,key): 2 | n= len(arr) 3 | flag=0 4 | for i in range(n): 5 | if(arr[i]==key): 6 | print("element is present at index: ",i) 7 | flag=1 8 | if(flag==0): 9 | print("element is not present") 10 | 11 | 12 | lst= [] 13 | n= int(input("enter the number of elements \n")) 14 | print("enter the elements") 15 | for i in range(n): 16 | ele= int(input()) 17 | lst.append(ele) 18 | 19 | key= int(input("enter the element to search: ")) 20 | linear_search(lst,key) 21 | -------------------------------------------------------------------------------- /Binary_Search/min_diff_ele.py: -------------------------------------------------------------------------------- 1 | https://www.callicoder.com/minimum-difference-element-in-sorted-array/#:~:text=Given%20an%20array%20of%20integers,'5'%20is%20the%20minimum.`` -------------------------------------------------------------------------------- /Binary_Search/minimum waiting time.py: -------------------------------------------------------------------------------- 1 | 2 | # time:O(n*logn) 3 | class Solution: 4 | def minimumWaitTime(self, n, m, c, arr): 5 | 6 | def isPossible(mid): 7 | check= arr[0] 8 | bus, student, capacity= 1, 1, 1 9 | for i in range(1, n): 10 | if arr[i] - check <= mid: 11 | student+= 1 12 | capacity+= 1 13 | if capacity > c : 14 | check= arr[i] 15 | bus+= 1 16 | capacity= 1 17 | else: 18 | check= arr[i] 19 | bus+= 1 20 | capacity= 1 21 | 22 | # print(mid, bus) 23 | return bus <= m 24 | 25 | arr.sort() 26 | start, end= 0, max(arr) 27 | while start < end: 28 | mid= start + (end- start)//2 29 | if isPossible(mid): 30 | end= mid 31 | else: 32 | start= mid + 1 33 | return start -------------------------------------------------------------------------------- /Binary_Search/tempCodeRunnerFile.py: -------------------------------------------------------------------------------- 1 | 2 | # # so now apply binary search in this range to find the position -------------------------------------------------------------------------------- /Bitwise_Manipulation/1832. Check if the Sentence Is Pangram.py: -------------------------------------------------------------------------------- 1 | # Method 1: Using set 2 | # Time = space = O(n) 3 | """ 4 | public boolean checkIfPangram(String sentence) { 5 | Set s = new HashSet<>(); 6 | for (int i = 0; i < sentence.length(); ++i) 7 | s.add(sentence.charAt(i)); 8 | return s.size() == 26; 9 | } 10 | """ 11 | 12 | # Method 2: Best 13 | # Time: O(n), space = O(1) 14 | 15 | """ 16 | class Solution { 17 | public boolean checkIfPangram(String sentence) { 18 | int seen = 0; 19 | for(char c : sentence.toCharArray()) { 20 | int ci = c - 'a'; 21 | seen = seen | (1 << ci); 22 | } 23 | return seen == ((1 << 26) - 1); 24 | } 25 | } 26 | """ -------------------------------------------------------------------------------- /Bitwise_Manipulation/190. Reverse Bits.py: -------------------------------------------------------------------------------- 1 | # Note: Input is passed as a Integer only 2 | 3 | class Solution: 4 | def reverseBits(self, n: int) -> int: 5 | ans= 0 6 | for i in range(32): 7 | rightMostBit= (n >> i) & 1 8 | # now we have to move this bit to the left 9 | # after that to keep this bit at left like if 0->0 and 1->1 keeping all the other bit same we will take OR with the ans 10 | ans= ans | rightMostBit<<(31-i) # to this position we have to move the bit 11 | return ans 12 | -------------------------------------------------------------------------------- /Bitwise_Manipulation/2683. Neighboring Bitwise XOR.py: -------------------------------------------------------------------------------- 1 | # logic: 2 | 3 | """ 4 | orginal: A[0], A[1], .... A[n-1] 5 | derived: A[0]^A[1], A[1]^A[2] .... A[n-1]^A[0] 6 | 7 | xor(derived) = (A[0]^A[1])^(A[1]^A[2])^ .... ^(A[n-1]^A[0]) = 0 8 | 9 | The necessary and sufficient condition for derived to have an original is 10 | xor(derived) == 0 11 | 12 | And this will be only = 0 if all numbers will be present in even freqeuency. 13 | But since here array is binary so we can also say that frequency of one should be even. 14 | or 'sum(derived) % 2 == 0'. 15 | 16 | So When original and derived is binary sequence, 17 | this equals to sum(derived) % 2 == 0. 18 | 19 | Note: this can apply to any q of this type. 20 | """ 21 | 22 | # time: O(n) 23 | class Solution: 24 | def doesValidArrayExist(self, derived: List[int]) -> bool: 25 | return sum(derived) % 2== 0 26 | -------------------------------------------------------------------------------- /Bitwise_Manipulation/2997. Minimum Number of Operations to Make Array XOR Equal to K.py. Minimum Number of Operations to Make Array XOR Equal to K.py: -------------------------------------------------------------------------------- 1 | # Logic: Find the xor of whole 'xorr' and then compare bit of 'xorr' with 'k'. 2 | # If bit is different then increment by ans by '1'. 3 | 4 | class Solution: 5 | def minOperations(self, nums: List[int], k: int) -> int: 6 | xorr = 0 7 | for num in nums: 8 | xorr ^= num 9 | ans = 0 10 | for i in range(32): 11 | bit1 = (k >> i) & 1 12 | bit2 = (xorr >> i) & 1 13 | if bit1 != bit2: 14 | ans += 1 15 | return ans 16 | -------------------------------------------------------------------------------- /Bitwise_Manipulation/326. Power of Three.py: -------------------------------------------------------------------------------- 1 | # Method 1: 2 | """ 3 | public boolean isPowerOfThree(int n) { 4 | return n>0 && (n==1 || (n%3==0 && isPowerOfThree(n/3))); 5 | } 6 | """ 7 | 8 | # Method 2: 9 | # Note : works only when the base is prime. For example, we cannot use this algorithm 10 | # to check if a number is a power of 4 or 6 or any other composite number. 11 | 12 | """ 13 | public class Solution { 14 | public boolean isPowerOfThree(int n) { 15 | // 1162261467 is 3^19, 3^20 is bigger than int 16 | return ( n>0 && 1162261467%n==0); 17 | } 18 | """ -------------------------------------------------------------------------------- /Bitwise_Manipulation/405. Convert a Number to Hexadecimal.py: -------------------------------------------------------------------------------- 1 | # first convert into positive equavalent value if number is negative using 2's complement logic. 2 | # i.e positive value of 2's complement. e.g: for num == -1 => 2^32(1111....) 3 | 4 | # For this add '2^32' to given number. 5 | 6 | # earn about 2's complement representation from link in sheet. 7 | 8 | class Solution: 9 | def toHex(self, num: int) -> str: 10 | if num == 0: 11 | return "0" 12 | if num < 0 : 13 | # will return positive value after converting into 2's complement. 14 | # i.e positive value of 2's complement. e.g: for num == -1 => 2^32(1111....) 15 | num = num + (1 << 32) 16 | intToLetter = {10: "a" , 11 : "b" , 12 : "c" , 13 : "d" , 14 : "e", 15 : "f"} 17 | ans = "" 18 | while num : 19 | remainder = num % 16 20 | if remainder < 10: 21 | ans = str(remainder) + ans 22 | else: 23 | ans = intToLetter[remainder] + ans 24 | num = num // 16 25 | return ans 26 | 27 | 28 | # decimal to binary 29 | def toBinary(n): 30 | ans = "" 31 | while n >= 2 : 32 | remainder = n % 2 33 | ans = str(remainder) + ans 34 | n = n // 2 35 | print(str(n) + ans) 36 | -------------------------------------------------------------------------------- /Bitwise_Manipulation/476. Number Complement.py: -------------------------------------------------------------------------------- 1 | # Logic: 2 | """ 3 | whenever you have to do complement of a bit just think of xor with '1'. 4 | And here we need to complement every bit so we will take xor with 111111..... 5 | But keep no of 1 in xor = no of digit in given number. 6 | """ 7 | 8 | class Solution: 9 | def findComplement(self, num: int) -> int: 10 | temp = num 11 | noBits = 0 12 | while num: 13 | noBits += 1 14 | num //= 2 15 | mask = (1<< noBits) - 1 16 | return temp ^ mask 17 | 18 | # My mkstake 19 | # took xor with '1111111.....' and got wrong ans. 20 | class Solution: 21 | def findComplement(self, num: int) -> int: 22 | return num ^ (1 << 31) 23 | 24 | -------------------------------------------------------------------------------- /Bitwise_Manipulation/78_subsets.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def subsets(self, nums: List[int]) -> List[List[int]]: 3 | ans, n= [], len(nums) 4 | total_possible_subsets= 1 << n 5 | # write in binary form of all the possible subsets like for n= 3 ,write from 0 to 7 6 | # har possbile subset num(0 to 7 e.g) ke liye set bit find karo or 7 | # jis position pe set bit ho, us position wale ele ko ans me add kar do us possible subset num ke liye 8 | for i in range(total_possible_subsets): 9 | temp= [] 10 | # check whether the bit is set or not at 'jth' position for each 'i' 11 | for j in range(n): 12 | # if set then add the num at that index to the 'temp' 13 | if i & (1 << j): 14 | temp.append(nums[j]) 15 | ans.append(temp) 16 | return ans 17 | # 18 | 19 | # a lot of approaches also there in recusrion topic for this Q -------------------------------------------------------------------------------- /Bitwise_Manipulation/832. Flipping an Image.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def flipAndInvertImage(self, image: List[List[int]]) -> List[List[int]]: 3 | # reverse the matrix and to invert the no take 'XOR' with '1' 4 | # return [[row[-i]^1 for i in range(1,len(row)+1)] for row in image] 5 | 6 | # return [[i^1 for i in reversed(row)] for row in image] 7 | 8 | # return [[1-i for i in row[::-1]] for row in image] # better one full with basic 9 | -------------------------------------------------------------------------------- /Bitwise_Manipulation/No_bits.py: -------------------------------------------------------------------------------- 1 | # 1st method: 2 | # just take log2(n) and add '1' 3 | 4 | 5 | # 2nd method: 6 | # just do right shift till number becomes equal to zero and add '1' -------------------------------------------------------------------------------- /Bitwise_Manipulation/Toggle_kth_bit.py: -------------------------------------------------------------------------------- 1 | # for toggling use the concept of xor at that position with '1' 2 | # since xor of any number with '1' is the negation of that number and 3 | # xor of any no with 'zero' is that number itself 4 | 5 | # so first bring '1' at that position keeping all the position '0' 6 | 7 | def Toggle_kth(n,k): 8 | return n^(1<< k-1) 9 | -------------------------------------------------------------------------------- /Bitwise_Manipulation/XOR of 1 to n Numbers.py: -------------------------------------------------------------------------------- 1 | # just write down and take xor till 8 or 12 ,you will see it is 2 | # following a sequence of repitition with below conclusions 3 | 4 | def xor_n(n): 5 | if n==0: 6 | return 0 7 | elif n% 4== 0: 8 | return n 9 | elif n%4==1: 10 | return 1 11 | elif n%4== 2: 12 | return n+1 13 | else: # if n%4== 3 14 | return 0 15 | 16 | print(xor_n(8)) 17 | print(xor_n(5)) 18 | 19 | # Java Code 20 | """ 21 | class Solution { 22 | public static int xor_n(int n) { 23 | if (n == 0) return 0; 24 | else if (n % 4 == 0) return n; 25 | else if (n % 4 == 1) return 1; 26 | else if (n % 4 == 2) return n + 1; 27 | else return 0; // n % 4 == 3 28 | } 29 | 30 | public static void main(String[] args) { 31 | System.out.println(xor_n(8)); 32 | System.out.println(xor_n(5)); 33 | } 34 | } 35 | """ 36 | 37 | # C++ Code 38 | """ 39 | #include 40 | 41 | using namespace std; 42 | 43 | int xor_n(int n) { 44 | if (n == 0) return 0; 45 | else if (n % 4 == 0) return n; 46 | else if (n % 4 == 1) return 1; 47 | else if (n % 4 == 2) return n + 1; 48 | else return 0; // n % 4 == 3 49 | } 50 | 51 | int main() { 52 | cout << xor_n(8) << endl; 53 | cout << xor_n(5) << endl; 54 | return 0; 55 | } 56 | """ -------------------------------------------------------------------------------- /Bitwise_Manipulation/check_kth_bit_set.py: -------------------------------------------------------------------------------- 1 | # submitted on gfg 2 | # index start from 0 from LSB 3 | class Solution: 4 | #Function to check if Kth bit is set or not. 5 | def checkKthBit(self, n,k): 6 | if ((n & (1<< k)) >> k)==0: 7 | return False 8 | return True 9 | -------------------------------------------------------------------------------- /Bitwise_Manipulation/even_odd.py: -------------------------------------------------------------------------------- 1 | # logic: 2 | # in binary if last bit(LSB) is '1' then it means odd 3 | # otherewise even 4 | 5 | # and 'AND' of any no with all '1' is no itself 6 | # but we only need to check the last bit 7 | # so take the 'AND' of the no with '1' 8 | # if 'AND'==1 then means odd otherwise means even 9 | 10 | def even_odd(n): 11 | # if n & 1==1: 12 | # print("odd") 13 | # else: 14 | # print("even") 15 | print("even") if n & 1== 0 else print("odd") 16 | even_odd(5) 17 | even_odd(10) 18 | 19 | -------------------------------------------------------------------------------- /Bitwise_Manipulation/kth_bit_from_right.py: -------------------------------------------------------------------------------- 1 | 2 | # Logic: Right shift the number 'k-1' times then the kth bit wil come at rightmost side. 3 | # Now return 0 if number is even else 1 OR simply return this curr number by taking '&' with '1' 4 | 5 | # this same logic we can return (N |(1<< K)) in above method also 6 | 7 | -------------------------------------------------------------------------------- /Bitwise_Manipulation/nth_magical no.py: -------------------------------------------------------------------------------- 1 | # for finding the nth magical number , write 'n' in binary and add the sum of value of powers with base '5' taht will be the ans. 2 | # e.g: if n==1(001) then ans= 0*5^3 + 0*5^2 + 1*5^1= 5, if n= 3(011) then ans= ans= 0*5^3 + 1*5^2 + 1*5^1= 30 3 | # just like we convert binary to decimal but here base= '5' and powers count will start from rightmost side with '1,2,3....' . 4 | 5 | def nth_magical(n): 6 | # multiply the rightmost bit till number becomes '0' by power of 7 | # '5' by incr power by '1' in each iteration 8 | 9 | # for getting the rightmost bit in each iteration 10 | # '&'with '1' 11 | 12 | i=1 13 | num=0 14 | while(n>0): 15 | right_most= n & 1 16 | num+= right_most*pow(5,i) 17 | i+= 1 18 | n= n>>1 # do right shift one to get next right most bit 19 | return num 20 | 21 | print(nth_magical(5)) 22 | print(nth_magical(6)) 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Bitwise_Manipulation/reset_kth_bit.py: -------------------------------------------------------------------------------- 1 | # index start from '1' from LSB 2 | # for reset we use 'AND' with '0'. 3 | # to get '0' keeping other bit same with '&'. we must get '0' at kth position and 4 | # all other position it must be '1' since we are doing '&' we want bit at remaining position as it is. 5 | 6 | # shift '1' by 'k-1' and negate it(1's complement: 0->1, 1->0) 7 | # after that take 'AND' of this with the number given 8 | 9 | # for toggling use the concept of xor at that position with '1' 10 | # since xor of any number with '1' is the negation of that number 11 | 12 | def reset_kth(n,k): 13 | return (~(1<< k-1) & n) 14 | 15 | print(reset_kth(5,1)) 16 | print(reset_kth(5,2)) 17 | 18 | 19 | -------------------------------------------------------------------------------- /Bitwise_Manipulation/set_kth_bit.py: -------------------------------------------------------------------------------- 1 | # for setting we always use 'OR' with '1' at that position i.e keep 1 at that position and 2 | # keep '0' at all other position. 3 | 4 | # and for reset we use 'AND' with '0'. 5 | 6 | # matlab kisi tarah se hmko '1' kth position pe lake given number ke saath '|' le lena h. 7 | 8 | # for getting one at kth position do left shift '1' 9 | # 'k' time(if last bit start from zero) 10 | # after that take 'OR' 11 | 12 | # submitted on GFG 13 | class Solution: 14 | def setKthBit(self, N, K): 15 | return (N |(1<< K)) # 'k' times since start with zero 16 | 17 | -------------------------------------------------------------------------------- /Bitwise_Manipulation/sum_till_nth_row_pascal_tri.py: -------------------------------------------------------------------------------- 1 | # Q: find sum of all ele till nth row in pascals triangle 2 | # sum= 2^n -1 3 | def sum(n): 4 | sum=0 5 | for i in range(n): 6 | sum+= 1< int: 9 | n = len(nums) 10 | nums.sort() 11 | 12 | @lru_cache(None) 13 | def dp(ind, last, mn, left): 14 | if left == 0: 15 | return mn 16 | if ind == n: 17 | return 0 18 | return dp(ind + 1, nums[ind], min(mn, nums[ind] - last), left - 1) + dp(ind + 1, last, mn, left) 19 | 20 | return dp(0, -float('inf'), float('inf'), k) % (10**9 + 7) 21 | # 1) Passing last as '-float('inf')' to handle case when no element is included till now. 22 | # This will make difference very large and will included from ans automatically. 23 | -------------------------------------------------------------------------------- /Dynamic Programming/0_1_knapsack/tempCodeRunnerFile.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def NoOfSubsets2(self, N, arr, sum): 3 | dp= [[-1 for i in range(sum+1)] for i in range(N +1)] 4 | ans= self.helper(N, arr, sum, dp) 5 | return ans 6 | 7 | def helper(self, n, arr, sum, dp): 8 | if n== 1: 9 | if sum== 0 and arr[0]== 0: 10 | return 2 11 | if sum==0 or sum== arr[0]: # in actual sum== 0 and arr[0] != 0 or sum== arr[0] 12 | return 1 13 | else: 14 | return 0 15 | if dp[n][sum]!= -1: 16 | return dp[n][sum] 17 | if arr[n-1]> sum: 18 | dp[n][sum]= self.helper(n-1,arr,sum, dp) 19 | else: 20 | dp[n][sum]= self.helper(n-1,arr,sum- arr[n-1], dp) + self.helper(n-1,arr,sum, dp) 21 | return dp[n][sum] -------------------------------------------------------------------------------- /Dynamic Programming/DP + BitMasking/526. Beautiful Arrangement.py: -------------------------------------------------------------------------------- 1 | # mask will tell whether that number has been used in cur permutation or not. 2 | 3 | # time complexity is O(N*2^N). Space complexity is O(2^N). 4 | 5 | class Solution: 6 | def countArrangement(self, n: int) -> int: 7 | 8 | @lru_cache(None) 9 | def dp(mask, place): 10 | if place== 0: 11 | return 1 12 | ans= 0 13 | for num in range(1, n+ 1): 14 | # try to put each number from '1' to 'n' on this place if that number is not used at this place 15 | # and follow the property of beautiful arrangements. 16 | if mask & (1 << num) == 0 and ((num) % place== 0 or place % (num)==0 ): 17 | # mark this num is used in the curent per 18 | ans+= dp(mask | (1 << num), place -1) 19 | return ans 20 | 21 | return dp(0, n) 22 | -------------------------------------------------------------------------------- /Dynamic Programming/DP On Game/799. Champagne Tower.py: -------------------------------------------------------------------------------- 1 | # Logic: Value in cur row will depend on pre row values. 2 | # juist similar as "pascal's triangle". 3 | 4 | # Do on paper then you will find a pattern. 5 | 6 | class Solution: 7 | def champagneTower(self, poured: int, query_row: int, query_glass: int) -> float: 8 | if query_row == 0 and query_glass == 0: 9 | return poured if poured <= 1 else 1 10 | pre = [poured] # 0th glass in 0th row will have this much quantity before releasing excess liquid. 11 | # starting from 1st row 12 | for row in range(1, query_row + 1): 13 | cur = [0]* (row + 1) # 1th row will have 2 glass and so on. 14 | for glass in range(row + 1): 15 | if glass == 0: 16 | # Taking max so avoid negative values. 17 | # subracting '1' because it will get only the half of excess quantity. 18 | cur[glass] = max(0, (pre[glass] - 1) /2) 19 | elif glass == row: 20 | cur[glass] = max(0, (pre[glass -1] - 1) /2) 21 | else: 22 | cur[glass] = max(0, (pre[glass] - 1) /2) + max(0, (pre[glass -1] - 1) /2) 23 | if query_row == row and query_glass == glass: 24 | return cur[glass] if cur[glass] <= 1 else 1 25 | pre = cur.copy() -------------------------------------------------------------------------------- /Dynamic Programming/DP on Probabilities/808. Soup Servings.py: -------------------------------------------------------------------------------- 1 | # Have to understand properly why it will tend to '1' when n > 4800(even n > 3300). 2 | # watch this after 10:30: https://www.youtube.com/watch?v=XNLJS-uDIqU 3 | 4 | # Time = space= O(n^2) 5 | # n= 10^9 but it will get accepted because we will return '1' when n > 3300. 6 | 7 | class Solution: 8 | def soupServings(self, n: int) -> float: 9 | 10 | @lru_cache(None) 11 | def dfs(a , b): 12 | # if both becomes empty simultaneously 13 | if a <= 0 and b <= 0: 14 | return 0.5 15 | # if b is empty 16 | if b <= 0 : 17 | return 0 18 | # if 'a' is empty 19 | if a <= 0 : 20 | return 1 21 | # Add all possible choices probability 22 | return 0.25 *(dfs(a - 100, b) + dfs(a - 75, b- 25) + dfs(a - 50, b -50) + dfs(a - 25, b - 75)) 23 | 24 | return 1 if n > 3300 else dfs(n, n) 25 | 26 | -------------------------------------------------------------------------------- /Dynamic Programming/Fibonacci Based/213. House Robber II.py: -------------------------------------------------------------------------------- 1 | # was easy only but thought to the point 2 | # logic: since first and last ele are neighbour so both can't be the part of ans simultaneously. 3 | # i.e ans will be condition only one of them 4 | # so ans will equal to the max(when we don't rob the first house, when we don't rob the last house). 5 | 6 | class Solution: 7 | def rob(self, nums: List[int]) -> int: 8 | n= len(nums) 9 | if n== 1: 10 | return nums[0] 11 | ans_excluding_last= self.helper(nums[: n-1]) 12 | ans_excluding_first= self.helper(nums[1: ]) 13 | return max(ans_excluding_last, ans_excluding_first) 14 | 15 | def helper(self, nums): 16 | n= len(nums) 17 | non_adj= 0 # intially it will be zero. 18 | adj= nums[0] # initially it will be nums[0]. 19 | ans= nums[0] # in case only one ele is present and also this will be the minimum profit 20 | for i in range(2,n+1): 21 | ans= max(ans, nums[i-1]+ non_adj, adj) # when you rob the current house or when you rob the next house 22 | # update adj and non_adj. 23 | adj, non_adj= ans, adj 24 | return ans -------------------------------------------------------------------------------- /Dynamic Programming/Fibonacci Based/3186. Maximum Total Damage With Spell Casting.py: -------------------------------------------------------------------------------- 1 | # just extension of q: "740. Delete and Earn". 2 | # Here you need to skip 'i+1' or 'i + 2' based on condition. 3 | 4 | class Solution: 5 | def maximumTotalDamage(self, nums: List[int]) -> int: 6 | freq = Counter(nums) 7 | nums = sorted(list(set(nums))) 8 | n = len(nums) 9 | 10 | @lru_cache(None) 11 | def solve(i): 12 | if i >= n: 13 | return 0 14 | notTake = solve(i + 1) 15 | take = freq[nums[i]] * nums[i] 16 | # first check if we can take 'i+1' as next or not. 'i+ 1' can have value = nums[i] + 1 or nums[i] + 2 17 | if (i + 1 < n and nums[i + 1] != nums[i] + 1 and nums[i + 1] != nums[i] + 2) : 18 | take += solve(i + 1) 19 | # if can't take 'i+1', check if we can take 'i+2'. in this we only need to check case 'nums[i + 2] != nums[i] + 2'. 20 | elif i + 2 < n and nums[i + 2] != nums[i] + 2: 21 | take += solve(i + 2) 22 | # if can't take both 'i+1' or 'i +2' then, take 'i +3' skipping 'i+1' and 'i+2'. 23 | else: 24 | take += solve(i + 3) 25 | return max(take, notTake) 26 | 27 | return solve(0) -------------------------------------------------------------------------------- /Dynamic Programming/Fibonacci Based/740. Delete and Earn.py: -------------------------------------------------------------------------------- 1 | # Logic: we can convert this problem into: " 198. House Robber" 2 | # for this just take only distinct ele and sort. 3 | 4 | # then we only need to check with next index 'i+1' if that has value = nums[i] + 1 or not. 5 | # if has then skip or take that. 6 | 7 | # Note: We can take all the occurence of any ele if we take that. 8 | # for this store the frequency also if you take then points = freq[nums[i]] * nums[i]. 9 | 10 | # Time; O(n*logn) 11 | 12 | class Solution: 13 | def deleteAndEarn(self, nums: List[int]) -> int: 14 | freq = Counter(nums) 15 | nums = sorted(list(set(nums))) 16 | n = len(nums) 17 | 18 | @lru_cache(None) 19 | def solve(i): 20 | if i >= n: 21 | return 0 22 | notTake = solve(i + 1) 23 | take = freq[nums[i]] * nums[i] 24 | take += solve(i + 1) if i + 1 < n and nums[i + 1] != nums[i] + 1 else solve(i + 2) 25 | return max(take, notTake) 26 | 27 | return solve(0) -------------------------------------------------------------------------------- /Dynamic Programming/Fibonacci Based/746. Min Cost Climbing Stairs.py: -------------------------------------------------------------------------------- 1 | # Time : O(n) 2 | 3 | class Solution: 4 | def minCostClimbingStairs(self, cost: List[int]) -> int: 5 | cost = [0] + cost # ho handle the corner case for 1st move so that no need to call for index '0' and index '1' separately. 6 | n = len(cost) 7 | 8 | @lru_cache(None) 9 | def solve(ind): 10 | if ind >= n: 11 | return 0 12 | return cost[ind] + min(solve(ind + 1) , solve(ind + 2)) 13 | 14 | return solve(0) 15 | 16 | 17 | # Note: How above method will take care of not_take case i.e skip case? 18 | # Ans: When we are at index 'i' and if we include ans of 'i+2' (called 'i + 2') then we have skipped 'i+1'. 19 | 20 | # If say you can jump upto 'k' then we have to take minimum of next 'k' index after adding the cost of cur_index. 21 | # Related Q: 22 | # 1) 2944. Minimum Number of Coins for Fruits 23 | -------------------------------------------------------------------------------- /Dynamic Programming/Fibonacci Based/Frog Jump with k Distances.py: -------------------------------------------------------------------------------- 1 | # Recursive way 2 | def frogJump(n, heights,k) : 3 | if n==1: # means we have reached the destination so simply return '0' 4 | return 0 5 | 6 | # just do by minimal base case and check condition while calling the function 7 | # if n==2: # only we have to go one step 8 | # return abs(heights[1] - heights[0]) 9 | mn= float('inf') 10 | for i in range(1,k+1): 11 | if n-i >=1: 12 | mn= min(mn, abs(heights[n-1]-heights[n-i-1]) + frogJump(n-i,heights, k)) # height idexing is starting from '0' but stair count from 1 13 | return mn 14 | 15 | # heights= [10,30,40,50,20] 16 | heights= [10,20,10] 17 | n= len(heights) 18 | # print(frogJump(n, heights,3)) 19 | 20 | print(frogJump(n, heights,1)) 21 | 22 | 23 | # memoization 24 | # time: O(n*k) 25 | -------------------------------------------------------------------------------- /Dynamic Programming/Grid Problem/980. Unique Paths III.py: -------------------------------------------------------------------------------- 1 | # Just normal way we do 2 | # time: O(m*n) as problem will overlap also and we can use dp to memoise. 3 | 4 | class Solution: 5 | def uniquePathsIII(self, grid: List[List[int]]) -> int: 6 | m ,n = len(grid), len(grid[0]) 7 | self.walkableCell = 1 # including the starting cell . without self it's not acting as global varibale 8 | start_x, start_y = None, None 9 | for i in range(m): 10 | for j in range(n): 11 | if grid[i][j] == 0: 12 | self.walkableCell += 1 13 | if grid[i][j] == 1: 14 | start_x, start_y = i, j 15 | 16 | directions =[[0, 1], [0, -1], [-1, 0],[1, 0]] 17 | 18 | def dfs(r, c): 19 | if r >= m or r < 0 or c >= n or c < 0 or grid[r][c] == -1: 20 | return 0 21 | if grid[r][c] == 2: 22 | return self.walkableCell == 0 23 | ans = 0 24 | temp = grid[r][c] 25 | grid[r][c] = -1 # marking visited 26 | self.walkableCell -= 1 27 | for dr, dc in directions: 28 | nr, nc = r + dr, c + dc 29 | ans += dfs(nr, nc) 30 | self.walkableCell += 1 31 | grid[r][c] = temp 32 | return ans 33 | 34 | return dfs(start_x, start_y) -------------------------------------------------------------------------------- /Dynamic Programming/Kedane's Alogorithm/1014. Best Sightseeing Pair.py: -------------------------------------------------------------------------------- 1 | # method 1: Brute force 2 | # check every pair 3 | # Time : O(n^2) 4 | 5 | # method 2: Optimising to O(n) 6 | # Using similar logic as : "121. Best Time to Buy and Sell Stock". 7 | 8 | # Logic: 9 | """ 10 | Maintain two variable that will store curMaxPoint and curMaxPointIndex . 11 | At each index we can decide whether we to update our 'curMaxPoint and curMaxPointIndex' to 'values[j] and j' 12 | or forward the same 'curMaxPoint and curMaxPointIndex' to next index. 13 | 14 | For this we will check 'if values[j] > curMaxPoint - (j - curMaxPointIndex)' then we will update curMaxPointIndex' to 'values[j] and j'. 15 | Why this because for next index curMaxPoint value will decrease by 'curMaxPoint - (j - curMaxPointIndex)'. 16 | """ 17 | 18 | class Solution: 19 | def maxScoreSightseeingPair(self, values: List[int]) -> int: 20 | n = len(values) 21 | curMaxPoint = values[0] 22 | curMaxPointIndex = 0 23 | ans = 0 24 | for j in range(1, n): 25 | ans = max(ans , curMaxPoint + values[j] - (j - curMaxPointIndex)) 26 | if values[j] > curMaxPoint - (j - curMaxPointIndex): 27 | curMaxPoint = values[j] 28 | curMaxPointIndex = j 29 | return ans 30 | -------------------------------------------------------------------------------- /Dynamic Programming/Kedane's Alogorithm/123. Best Time to Buy and Sell Stock III.py: -------------------------------------------------------------------------------- 1 | # just same as pre Q: 122 2 | # here we can only buy and sell if transaction is allowed, otherwise simply return zero 3 | # so for checking the remaining txn we will need one more parameter. 4 | class Solution: 5 | def maxProfit(self, prices: List[int]) -> int: 6 | return self.helper(prices, 0, 1, 2) # 2nd para: ind, 3rd: buying is allowed or not, 4th: no of transactions allowed 7 | 8 | def helper(self, prices, ind, buy, txn): 9 | if txn== 0 or ind == len(prices): 10 | return 0 11 | if buy: 12 | return max(-prices[ind] + self.helper(prices, ind+1, 0, txn ), 0+ self.helper(prices, ind+1, 1, txn)) 13 | else: 14 | return max(prices[ind] + self.helper(prices, ind+1, 1, txn-1), 0+ self.helper(prices, ind+1, 0, txn)) 15 | 16 | 17 | # did all other things in Q: 188. totally same 18 | # just replace k->2 19 | 20 | 21 | -------------------------------------------------------------------------------- /Dynamic Programming/Kedane's Alogorithm/714. Best Time to Buy and Sell Stock with Transaction Fee.py: -------------------------------------------------------------------------------- 1 | # just copy pasted the code of Q: 122 and while selling subtracted the transaction fee that's it. 2 | 3 | class Solution: 4 | def maxProfit(self, prices: List[int], fee: int) -> int: 5 | return self.helper(prices, 0, 1, fee) # 2nd parameter is ind, 3rd telling buying is allowed or not 6 | 7 | def helper(self, prices, ind, buy, fee): 8 | if ind== len(prices): 9 | return 0 10 | if buy: 11 | return max(-prices[ind] + self.helper(prices, ind+1, 0, fee), 0+ self.helper(prices, ind+1, 1, fee)) 12 | else: # just subtract the transaction fee when you sell, this is teh only change we have to do. 13 | return max(prices[ind] - fee + self.helper(prices, ind+1, 1, fee), 0+ self.helper(prices, ind+1, 0, fee)) 14 | -------------------------------------------------------------------------------- /Dynamic Programming/Kedane's Alogorithm/Print the Maximum Subarray Sum.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Time: O(n) 4 | # space: O(1) 5 | 6 | def printSubarraySum(arr): 7 | ansStart, ansEnd= 0, 0 # store the start and endIndex of final ans subArray. 8 | curSum= 0 9 | start= 0 10 | maxSum= float('-inf') 11 | for i, n in enumerate(arr): 12 | if curSum < 0: 13 | start= i 14 | curSum= n 15 | else: 16 | curSum+= n 17 | # update our ans index , and maxSum 18 | if curSum > maxSum: 19 | ansStart= start 20 | ansEnd= i 21 | maxSum= curSum 22 | 23 | print("maximum SubArray sum: ", arr[ansStart: ansEnd+ 1]) 24 | 25 | arr = [-2, -3, 4, -1, -2, 1, 5, -3] 26 | # arr = [-2, -5, 6, -2, -3, 1, 5, -6] 27 | # arr= [-2,-3,-4, -1] 28 | printSubarraySum(arr) -------------------------------------------------------------------------------- /Dynamic Programming/Longest Inceasing Subsequence/Maximum sum increasing subsequence.py: -------------------------------------------------------------------------------- 1 | # Exactly same as "Find the length of Longest increasing subsequence". 2 | # Here instead of increasing length , just increase the sum. 3 | 4 | # Time: O(n^2) 5 | 6 | class Solution: 7 | def maxSumIS(self, Arr, n): 8 | dp = [Arr[i] for i in range(n)] 9 | for i in range(n): 10 | for j in range(i): 11 | if Arr[i] > Arr[j]: 12 | dp[i] = max(dp[i], Arr[i] + dp[j]) 13 | return max(dp) 14 | 15 | # Java 16 | """ 17 | import java.util.Arrays; 18 | 19 | public class Solution { 20 | public int maxSumIS(int[] arr, int n) { 21 | int[] dp = new int[n]; 22 | for (int i = 0; i < n; i++) { 23 | dp[i] = arr[i]; 24 | } 25 | 26 | for (int i = 0; i < n; i++) { 27 | for (int j = 0; j < i; j++) { 28 | if (arr[i] > arr[j]) { 29 | dp[i] = Math.max(dp[i], arr[i] + dp[j]); 30 | } 31 | } 32 | } 33 | 34 | return Arrays.stream(dp).max().getAsInt(); 35 | } 36 | } 37 | """ 38 | -------------------------------------------------------------------------------- /Dynamic Programming/Longest_Common_Subsequence/1458. Max Dot Product of Two Subsequences.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxDotProduct(self, nums1: List[int], nums2: List[int]) -> int: 3 | n, m = len(nums1), len(nums2) 4 | dp = [[float('-inf')] * m for _ in range(n)] 5 | 6 | def solve(i, j): 7 | if i == n or j == m: 8 | return float('-inf') 9 | 10 | if dp[i][j] != float('-inf'): 11 | return dp[i][j] 12 | 13 | dp[i][j] = max( 14 | nums1[i] * nums2[j] + max(solve(i + 1, j + 1), 0), 15 | solve(i + 1, j), 16 | solve(i, j + 1), 17 | ) 18 | 19 | return dp[i][j] 20 | 21 | return solve(0, 0) 22 | -------------------------------------------------------------------------------- /Dynamic Programming/Longest_Common_Subsequence/712. Minimum ASCII Delete Sum for Two Strings.py: -------------------------------------------------------------------------------- 1 | # Exactly same as : "583. Delete Operation for Two Strings". 2 | # Just we need to add the 'Ascii value' of char we are deleting. 3 | 4 | # Exactly written same code of above Q only. 5 | 6 | # Time: O(n^2) 7 | 8 | class Solution: 9 | @lru_cache(None) 10 | def minimumDeleteSum(self, word1: str, word2: str) -> int: 11 | if not word1 or not word2: 12 | sum = 0 13 | if word1: 14 | for c in word1: 15 | sum += ord(c) 16 | 17 | if word2: 18 | for c in word2: 19 | sum += ord(c) 20 | return sum 21 | ans = 0 22 | if word1[0] == word2[0]: 23 | ans = self.minimumDeleteSum(word1[1 : ], word2[1: ]) 24 | else: 25 | ans = min(ord(word1[0]) + self.minimumDeleteSum(word1[1 : ], word2), ord(word2[0]) + self.minimumDeleteSum(word1, word2[1: ])) 26 | return ans 27 | 28 | -------------------------------------------------------------------------------- /Dynamic Programming/Longest_Common_Subsequence/tempCodeRunnerFile.py: -------------------------------------------------------------------------------- 1 | # ans+= s1[i-1] # when you will print then this will give incorrect ans due to else condition 2 | -------------------------------------------------------------------------------- /Dynamic Programming/Palindromic Subsequences/1312. Minimum Insertion Steps to Make a String Palindrome.py: -------------------------------------------------------------------------------- 1 | # just find the length of longest palindromic subsequence and 2 | # subtract this from the length of the string as these are extra char 3 | # beyond longest palindromic sequence so we have to insert copy of these characters 4 | # only to make the whole string palindrome 5 | # that will be the ans 6 | 7 | # ans will be same for only deletion OR only insertion to make a string palindrome. 8 | class Solution: 9 | def minInsertions(self, s: str) -> int: 10 | s1= s[::-1] 11 | # print(S) 12 | x,y= len(s), len(s) 13 | longest_palindrome_length= self.Lcs(x,y,s,s1) 14 | char_to_insert= len(s)- longest_palindrome_length 15 | return char_to_insert 16 | 17 | def Lcs(self,x,y,s1,s2): 18 | dp= [[0 for i in range(y+1)] for i in range(x+1)] 19 | for i in range(1,x+1): 20 | for j in range(1, y+1): 21 | if s1[i-1]== s2[j-1]: 22 | dp[i][j]= 1+ dp[i-1][j-1] 23 | else: 24 | dp[i][j]= max(dp[i][j-1], dp[i-1][j]) 25 | return dp[x][y] 26 | -------------------------------------------------------------------------------- /Dynamic Programming/Palindromic Subsequences/Minimum number of deletions to make a string palindrome.py: -------------------------------------------------------------------------------- 1 | # Note: if only deletion is allowed , then for making both string same . Make both equal to lcs(here longest palindromic subsequence ) 2 | # just find the length of longest palindromic subsequence and 3 | # subtract this from the length of the string as these are extra char 4 | # beyond longest palindromic sequence so we have to delete this only 5 | # that will be the ans 6 | class Solution: 7 | def minDeletions(self, Str, n): 8 | S1= Str[::-1] 9 | # print(S) 10 | x,y= n, n 11 | longest_palindrome_length= self.Lcs(x,y,Str,S1) 12 | char_to_delete= n- longest_palindrome_length 13 | return char_to_delete 14 | def Lcs(self,x,y,s1,s2): 15 | dp= [[0 for i in range(y+1)] for i in range(x+1)] 16 | for i in range(1,x+1): 17 | for j in range(1, y+1): 18 | if s1[i-1]== s2[j-1]: 19 | dp[i][j]= 1+ dp[i-1][j-1] 20 | else: 21 | dp[i][j]= max(dp[i][j-1], dp[i-1][j]) 22 | return dp[x][y] 23 | 24 | -------------------------------------------------------------------------------- /Dynamic Programming/Some more Q on DP/2746. Decremental String Concatenation.py: -------------------------------------------------------------------------------- 1 | # Logic: Don't worry about forming the actual string. 2 | # Just find how many maximum char we can delete. 3 | # vvi: what does matter is only first and the last character. 4 | 5 | # first is the first character of the actual concatenated string 6 | # last is the last character of the actual concatenated string 7 | # index is the index of the word in the array words which we are processing. 8 | 9 | # We can only delete either last== w[0] or w[-1] == first & we have to take maximum of both. 10 | 11 | class Solution: 12 | def minimizeConcatenatedLength(self, words: List[str]) -> int: 13 | @lru_cache(None) 14 | def solve(ind, first, last): 15 | if ind >= len(words): 16 | return 0 17 | w= words[ind] 18 | # we have two choices for merging i.e join(x, y) or join(y, x) 19 | # And we will take where we can delete the maximum 20 | return max((last == w[0]) + solve(ind + 1, first , w[-1]) , (w[-1] == first) + solve(ind + 1, w[0] , last)) 21 | 22 | 23 | max_delete = solve(1, words[0][0], words[0][-1]) # we will start checking from index '1'. 24 | return len("".join(words)) - max_delete # total length of words - max_delete -------------------------------------------------------------------------------- /Dynamic Programming/Some more Q on DP/926. Flip String to Monotone Increasing.py: -------------------------------------------------------------------------------- 1 | # Just exact same q as: "926. Flip String to Monotone Increasing" 2 | # Time = O(n). space = O(1) 3 | 4 | class Solution: 5 | def minFlipsMonoIncr(self, s: str) -> int: 6 | cnt1 = 0 7 | res = 0 8 | for x in s: 9 | if x == '0': 10 | res = min(res + 1, cnt1) 11 | elif x == '1': 12 | # Fine for 'b' in the tail 13 | cnt1 += 1 14 | return res 15 | -------------------------------------------------------------------------------- /Dynamic Programming/String Matching/2222. Number of Ways to Select Buildings.py: -------------------------------------------------------------------------------- 1 | # Ans: There will be only two possibility i.e '101' and '010' so Q reduces to 2 | # find the number of distinct subsequences of '101' and '010' in string and add them. 3 | 4 | # Which is same as Question: "115. Distinct Subsequences". 5 | -------------------------------------------------------------------------------- /Dynamic Programming/Unbounded_knapsack/650. 2 Keys Keyboard.py: -------------------------------------------------------------------------------- 1 | # similar to unbounded knapsack. 2 | 3 | # Logic: At each step check if copied and paste allowed or not using two variables. 4 | # And take minimum of both cases when copy and paste is allowed. 5 | 6 | # Recursive method got accepted . But we can optimise using DP. 7 | 8 | class Solution: 9 | def minSteps(self, n: int) -> int: 10 | 11 | def noOfSteps(char_on_screen, copy_allowed, paste_allowed, copied_char): 12 | if char_on_screen == n: 13 | return 0 14 | ans = float('inf') 15 | if copy_allowed and char_on_screen * 2 <= n: 16 | # copied_char will become = char_on_screen 17 | ans = min(ans, 1+ noOfSteps(char_on_screen , False, True, char_on_screen)) 18 | if paste_allowed and char_on_screen + copied_char <= n: 19 | # in this we can copy same no of character again and again i.e copied_Char. 20 | ans = min(ans, 1 + noOfSteps(char_on_screen + copied_char, True, True, copied_char)) 21 | return ans 22 | 23 | return noOfSteps(1, True, False, 1) -------------------------------------------------------------------------------- /Dynamic Programming/Unbounded_knapsack/Number of ways to get a given sum with n number of m-faced dices.py: -------------------------------------------------------------------------------- 1 | # Note: Basically asking the number of ways to get sum = x in 'n' operations 2 | # (or using 'n' numbers) such that all numbers are in range from 1 to m. 3 | 4 | # Recursive way 5 | 6 | def ways(n, sum): 7 | if sum == 0: 8 | return n == 0 9 | if n <= 0: 10 | return 0 11 | ans = 0 12 | for i in range(1, min(m, sum) + 1): # will avoid getting sum negative. 13 | ans += ways(n - 1, sum - i) 14 | return ans 15 | 16 | # n = 2 17 | # m = 4 18 | # X = 4 19 | 20 | n = 3 21 | m = 6 22 | X = 12 23 | 24 | print("No of ways: ", ways(n, X)) 25 | 26 | 27 | # Method 2: 28 | # We can reduce this problem to unbounded knapsack where numbers are from '1' to 'm' and 29 | # We can use any number any number of times such that total number used must be = n. 30 | # So we can solve using dp also. Just convert above solutio into dp. 31 | 32 | -------------------------------------------------------------------------------- /Graph/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ravi-0412/DSA-Program-And-Notes/3961bd7499d9a3e2623207ebfab8a34ba40b50c2/Graph/.DS_Store -------------------------------------------------------------------------------- /Graph/Basic Graph/1791. Find Center of Star Graph.py: -------------------------------------------------------------------------------- 1 | # Method 1: 2 | # center node must have maximum indegree value.\ 3 | # time = space = O(n) 4 | class Solution: 5 | def findCenter(self, edges: List[List[int]]) -> int: 6 | n = len(edges) + 1 7 | indegree = [0] * n 8 | for u, v in edges: 9 | indegree[u - 1] += 1 10 | indegree[v - 1] += 1 11 | return indegree.index(max(indegree)) + 1 # return node having max indegree value 12 | 13 | 14 | # method 2: 15 | # Logic: A center node must appear in every edge. 16 | 17 | class Solution: 18 | def findCenter(self, edges: List[List[int]]) -> int: 19 | if edges[0][0] == edges[1][0] or edges[0][0] == edges[1][1]: 20 | return edges[0][0] 21 | return edges[0][1] -------------------------------------------------------------------------------- /Graph/Basic Graph/adjacency_matrix.py: -------------------------------------------------------------------------------- 1 | class Graph: 2 | def __init__(self,n): 3 | self.adjMatrix= [] 4 | for i in range(n): 5 | self.adjMatrix.append([0 for i in range(n)]) # intilaise all ele with '0' 6 | # add the add 7 | def addEdge(self,v1,v2): 8 | if v1==v2: 9 | print("both the vertices are same") 10 | else: 11 | self.adjMatrix[v1][v2]= 1 12 | self.adjMatrix[v2][v1]= 1 # since making for undirected graph 13 | # so it will be symmetric 14 | # function to print the matrix 15 | def print_matrix(self): 16 | for row in self.adjMatrix: 17 | print(row) 18 | print() 19 | 20 | def remove_edge(self,v1,v2): 21 | if self.adjMatrix[v1][v2]==0: 22 | print("no edge exist bw these vertices") 23 | else: 24 | self.adjMatrix[v1][v2]= 0 25 | self.adjMatrix[v2][v1]= 0 26 | 27 | g= Graph(8) 28 | g.addEdge(0,1) 29 | g.addEdge(1,2) 30 | g.addEdge(2,3) 31 | g.addEdge(3,4) 32 | g.addEdge(3,5) 33 | g.addEdge(4,5) 34 | g.addEdge(4,7) 35 | g.addEdge(5,6) 36 | g.addEdge(5,7) 37 | g.addEdge(6,7) 38 | g.print_matrix() 39 | # g.remove_edge(0,2) 40 | # g.print_matrix() 41 | 42 | -------------------------------------------------------------------------------- /Graph/Bfs Dfs/1553. Minimum Number of Days to Eat N Oranges.py: -------------------------------------------------------------------------------- 1 | # Just simple multisource bfs (can do using single source using extra parameter). 2 | # But multisource will help in avoiding 'memory limit exceeded'. 3 | 4 | # Note vvi: Whenever you are give some fixed no of operations for each state(step) and telling to find the 5 | # Minimum no of steps/days (or something) then think of multisource bfs and Dynamic Programming. 6 | 7 | class Solution: 8 | def minDays(self, n: int) -> int: 9 | q = deque() 10 | q.append(n) 11 | steps=0 12 | visited=set() 13 | 14 | while q: 15 | for _ in range(len(q)): 16 | x = q.popleft() 17 | if x == 0: 18 | return steps 19 | if x % 3 == 0 and x//3 not in visited: 20 | q.append(x//3) 21 | visited.add(x//3) 22 | if x % 2== 0 and x//2 not in visited: 23 | visited.add(x//2) 24 | q.append(x//2) 25 | if x - 1 not in visited: 26 | visited.add(x -1) 27 | q.append(x -1) 28 | 29 | steps += 1 30 | 31 | # Did by DP also. 32 | # THis is best solution 33 | 34 | 35 | # Related q: 36 | # 1) 2998. Minimum Number of Operations to Make X and Y Equal 37 | # 2) -------------------------------------------------------------------------------- /Graph/Bfs Dfs/733. Flood Fill.py: -------------------------------------------------------------------------------- 1 | # Think value of matric = color 2 | 3 | # Logic: Just you have to make value of cells = given color if that cell is directly or indirectly connected to given cell and image_value of those cells are same. 4 | # i.e they are are forming a connected components with same value then make value of those cells = given color. 5 | 6 | class Solution: 7 | def floodFill(self, image: List[List[int]], sr: int, sc: int, color: int) -> List[List[int]]: 8 | src_color = image[sr][sc] 9 | q= deque([(sr,sc)]) 10 | while q: 11 | for i in range(len(q)): 12 | r, c = q.popleft() # clr= pixel at that (r,c) 13 | image[r][c]= color # can update when we will see for 1st time also 14 | directions= [[-1,0],[1,0],[0,-1],[0,1]] # up,down,left,right 15 | for dr,dc in directions: 16 | row,col= r+ dr, c+ dc 17 | # if in range and image_of_cur_cell = source image value and already not colored with given color(just working as visited) 18 | if 0 <=row < len(image) and 0<= col < len(image[0]) and image[row][col] == src_color and image[row][col]!=color: 19 | q.append((row, col)) 20 | return image 21 | 22 | 23 | # Can do by single source bfs and dfs also. 24 | # better do by this only. -------------------------------------------------------------------------------- /Graph/Bfs Dfs/Minimum Multiplications to reach End.py: -------------------------------------------------------------------------------- 1 | # how to think of bfs? 2 | # Ans: we have given a source node and initial step (0) and we have to reach the destination with the help of the these fixed nodes. 3 | # And also we will encounter diff diff states(numbers) and every time we have to check for these states now. 4 | 5 | # Note: we will get the ans for generating number at 1st time we will get that number. 6 | 7 | # for visited set: we only need to mark the generating num(curr_num) as visited at 1st time 8 | # since that will be minimum no of steps for that number. 9 | 10 | import collections 11 | class Solution: 12 | def minimumMultiplications(self, arr : List[int], start : int, end : int) -> int: 13 | q= collections.deque() 14 | mod= 100000 15 | q.append((start, 0)) 16 | visited= set() 17 | visited.add(start) 18 | while q: 19 | n, steps= q.popleft() 20 | for num in arr: 21 | cur_num= (num * n) % 100000 22 | if cur_num== end: 23 | return steps + 1 24 | if cur_num not in visited: 25 | visited.add(cur_num) 26 | q.append((cur_num, steps + 1)) 27 | return -1 -------------------------------------------------------------------------------- /Graph/Indegree Topological order/1361. Validate Binary Tree Nodes.py: -------------------------------------------------------------------------------- 1 | # Method 1: 2 | 3 | # Explanation: 4 | # a) binary tree will have exactly one root node i.e only one node will have indegree == 0 i.e root. 5 | # b ) from root, all nodes can be traversed exactly once. 6 | # c ) all nodes will have indegree exactly equal to 1. 7 | # d ) tree should have exactly n-1 edge. 8 | # Space complexity: O(n) 9 | # time complexity: O(n+e) 10 | 11 | # Note: If you will check only these two conditions 12 | # a) There should be one node with in-degree = 0 13 | # b) All the other nodes should have in-degree =1 14 | 15 | # Won't work in case of more than one component. 16 | 17 | # Note: Checking for no cycle and single component will wrong ans because 18 | # in this one node can more than two children. 19 | 20 | 21 | # method 2: 22 | # https://leetcode.com/problems/validate-binary-tree-nodes/solutions/939381/python-clean-bfs-96-faster-timecomplexity-o-n-space-complexity-o-n/?envType=daily-question&envId=2023-10-17 23 | # https://leetcode.com/problems/validate-binary-tree-nodes/solutions/4176803/87-44-easy-soluiton-with-explanation/?envType=daily-question&envId=2023-10-17 24 | -------------------------------------------------------------------------------- /Graph/Indegree Topological order/1557. Minimum Number of Vertices to Reach All Nodes.py: -------------------------------------------------------------------------------- 1 | # logic: Nodes having indegree '0' won't be reachable by any other nodes, 2 | # And other nodes having indegree > 0 will be reachable by nodes having indegree = 0. 3 | 4 | # so Q reduces to: "Find the nodes having indegree= 0". 5 | 6 | # time: O(n + E) 7 | 8 | class Solution: 9 | def findSmallestSetOfVertices(self, n: int, edges: List[List[int]]) -> List[int]: 10 | indegree= [0]*n 11 | for u, v in edges: 12 | indegree[v]+= 1 13 | ans= [] 14 | for i in range(n): 15 | if indegree[i]== 0: 16 | ans.append(i) 17 | return ans 18 | 19 | 20 | # Note: Think if graph is cyclic? -------------------------------------------------------------------------------- /Graph/Indegree Topological order/1615. Maximal Network Rank.py: -------------------------------------------------------------------------------- 1 | # Just we need to find the indegree of all the nodes then, 2 | # network rank(a, b) = indegree[a] + indegree[b] if (a,b) is not conected and 3 | # network rank(a, b) = indegree[a] + indegree[b] - 1, if (a,b) is connected 4 | 5 | # And our ans will be max of any network rank. 6 | 7 | #storing the edges in set to check if there is edge between any two node in O(1) 8 | # Or you can use 2d matrix(adjacency matrix) and if any edge make value = 1 9 | 10 | # Time: O(n^2) 11 | 12 | class Solution: 13 | def maximalNetworkRank(self, n: int, roads: List[List[int]]) -> int: 14 | indegree = [0] *n 15 | roadsEgdes = set() 16 | for a, b in roads: 17 | indegree[a] += 1 18 | indegree[b] += 1 19 | roadsEgdes.add((a, b)) # no need to add other pair (b, a) since bidirectional 20 | 21 | ans = 0 22 | for i in range(n): 23 | for j in range(i + 1, n): 24 | if (i, j) in roadsEgdes: 25 | ans = max(ans, indegree[i] + indegree[j] -1) 26 | else: 27 | ans = max(ans, indegree[i] + indegree[j]) 28 | return ans -------------------------------------------------------------------------------- /Graph/Multisource Bfs/1197. Minimum Knight Moves.py: -------------------------------------------------------------------------------- 1 | # Note: just normal multisource bfs. 2 | # we can also do by single source by storing minSteps also with coordinate in q. 3 | 4 | # 1st time when we will see any cell that will be the minimum no of steps required to reach that cell 5 | 6 | # time: O(n*n) 7 | 8 | from collections import deque 9 | 10 | class Solution: 11 | def minStepToReachTarget(self, KnightPos, TargetPos, N): 12 | if KnightPos== TargetPos: 13 | return 0 14 | q= deque([]) 15 | visited= set() 16 | minSteps= 0 17 | r1,c1 = KnightPos 18 | q.append((r1,c1)) 19 | visited.add((r1,c1)) 20 | while q: 21 | for i in range(len(q)): 22 | r, c= q.popleft() 23 | directions= [[r-1, c+2], [r+1, c+2],[r-1, c-2], [r+1, c-2],[r-2, c+1], [r-2, c-1],[r+2, c+1], [r+2, c-1]] 24 | # right-up, right-left, left-up, left-down, up-right, up-left, down-right, down-left 25 | for nr, nc in directions: 26 | if 1<= nr <= N and 1<= nc <= N and (nr, nc) not in visited: 27 | if nr== TargetPos[0] and nc== TargetPos[1]: 28 | return minSteps +1 29 | q.append((nr, nc)) 30 | visited.add((nr, nc)) 31 | minSteps+= 1 32 | return -1 33 | -------------------------------------------------------------------------------- /Graph/Shortest Path and Dijkastra/3112. Minimum Time to Visit Disappearing Nodes.py: -------------------------------------------------------------------------------- 1 | # Logic: Just exact Dijkastra, just before adding into 'minHeap' check if that node is already disappeared in that time. If not disappeared then only add into 'minHeap'. 2 | 3 | 4 | class Solution: 5 | def minimumTime(self, n: int, edges: List[List[int]], disappear: List[int]) -> List[int]: 6 | adj = collections.defaultdict(list) 7 | for u, v, length in edges: 8 | adj[u].append((v, length)) 9 | adj[v].append((u, length)) 10 | 11 | ans = [-1] * n 12 | minHeap = [(0, 0)] 13 | while minHeap: 14 | time, node = heapq.heappop(minHeap) 15 | if ans[node] != -1: 16 | # already this node is relaxed 17 | continue 18 | ans[node] = time 19 | for nei, t in adj[node]: 20 | if time + t < disappear[nei]: 21 | # If 'nei' has not disappeared till this time then only add 22 | # i.e we can only use 'nei' for shortest time if it has not disappeared 23 | heapq.heappush(minHeap, (time + t, nei)) 24 | return ans -------------------------------------------------------------------------------- /Graph/Shortest Path and Dijkastra/3341. Find Minimum Time to Reach Last Room I.py: -------------------------------------------------------------------------------- 1 | # Just similar logic as : "778. Swim in Rising Water" 2 | 3 | # time: O(4*n*m) , we can visit same cell four time from four different directions. 4 | 5 | class Solution: 6 | def minTimeToReach(self, moveTime: List[List[int]]) -> int: 7 | n, m = len(moveTime), len(moveTime[0]) 8 | directions = [[0, -1], [0, 1], [-1, 0], [1, 0]] # left, right, up , down 9 | minTime = [[float('inf') for j in range(m)] for i in range(n)] 10 | minHeap = [] 11 | heapq.heappush(minHeap, (0, 0, 0)) 12 | visited = set() 13 | while minHeap: 14 | time, r, c = heapq.heappop(minHeap) 15 | if r == n - 1 and c == m - 1: 16 | return time 17 | visited.add((r, c)) 18 | for dr, dc in directions: 19 | r1, c1 = r + dr , c + dc 20 | if 0 <= r1 < n and 0 <= c1 < m and (r1, c1) not in visited: 21 | min_time_required = max(moveTime[r1][c1], time) + 1 22 | if minTime[r1][c1] > min_time_required: 23 | heapq.heappush(minHeap, (min_time_required, r1, c1)) 24 | minTime[r1][c1] = min_time_required 25 | 26 | 27 | # Related q: 28 | # 1) 3342. Find Minimum Time to Reach Last Room II 29 | -------------------------------------------------------------------------------- /Graph/tempCodeRunnerFile.py: -------------------------------------------------------------------------------- 1 | 2 | for via in range(n): -------------------------------------------------------------------------------- /Greedy/1024. Video Stitching.py: -------------------------------------------------------------------------------- 1 | # time: O(n*logn) 2 | 3 | # Just same as '45. Jump Game 2'. 4 | 5 | class Solution: 6 | def videoStitching(self, clips: List[List[int]], time: int) -> int: 7 | n = len(clips) 8 | clips.sort() 9 | i = 0 # will tell on which clip we are currently 10 | cnt = 0 # no of clips we have taken 11 | end = 0 # max we have reached taking 'cnt' no of clips. 12 | farthestWeCanReach = 0 # will tell farthest we can reach in next step taking all the clips having start_time <= end. 13 | while end < time: 14 | cnt += 1 # taken one more clip 15 | # check which all clips we can take after reaching end 16 | # we can take all those clips which will have start_time <= end. 17 | while i < n and clips[i][0] <= end: 18 | # if reachable then update 'fathestWeCanReach' with end time of cur clip. 19 | farthestWeCanReach = max(farthestWeCanReach, clips[i][1]) 20 | i += 1 21 | # check we have moved forward or not taking all the possible clips 22 | if end == farthestWeCanReach: 23 | # then it means not possible to cover all events 24 | return -1 25 | # else update end 26 | end = farthestWeCanReach 27 | return cnt -------------------------------------------------------------------------------- /Greedy/1328. Break a Palindrome.py: -------------------------------------------------------------------------------- 1 | # Time Complexity: O(N) 2 | # Space Complexity: O(1) 3 | 4 | # Logic: 5 | """ 6 | Note: it's better to replace any character with 'a' from start if not 'a'. 7 | if all 'a' in 1st half then replace last character with 'b'. 8 | so: 9 | Check half of the string, 10 | replace a non 'a' character to 'a'. 11 | 12 | If only one character, return empty string. 13 | Otherwise repalce the last character to 'b' 14 | """ 15 | 16 | def break_palindrome(palindrome: str) -> str: 17 | s = list(palindrome) 18 | n = len(s) 19 | 20 | for i in range(n // 2): 21 | if s[i] != 'a': 22 | s[i] = 'a' 23 | return ''.join(s) 24 | 25 | # If all characters are 'a' 26 | s[n - 1] = 'b' 27 | return "" if n < 2 else ''.join(s) 28 | 29 | 30 | # java 31 | """ 32 | public String breakPalindrome(String palindrome) { 33 | char[] s = palindrome.toCharArray(); 34 | int n = s.length; 35 | 36 | for (int i = 0; i < n / 2; i++) { 37 | if (s[i] != 'a') { 38 | s[i] = 'a'; 39 | return String.valueOf(s); 40 | } 41 | } 42 | s[n - 1] = 'b'; //if all 'a' 43 | return n < 2 ? "" : String.valueOf(s); 44 | } 45 | """ -------------------------------------------------------------------------------- /Greedy/152. Maximum Product Subarray.py: -------------------------------------------------------------------------------- 1 | """ 2 | logic: negative no is making problem like if product till now is min but next time it can become the ans if next ele will be negative. 3 | that's why maintaining two varaibel to store the curr_max and curr_min till now. 4 | here we are becoming greedy as we can get our ans from both like curr_min and curr_max. 5 | 6 | """ 7 | class Solution: 8 | def maxProduct(self, nums: List[int]) -> int: 9 | ans= nums[0] 10 | curr_max, curr_min= 1, 1 # for multiplication '1' won't effect the ans 11 | for n in nums: 12 | temp= curr_max*n # have to update curr_min acc to prev value only 13 | # for curr_max: 1) n is +ve and curr_max is +ve 2) n is -ve and curr_min is -ve 3) if for input like: [-1, 8] 14 | curr_max= max(n* curr_max, n*curr_min, n) 15 | # for curr_min: 1) n is -ve and curr_max is +ve 2) n is +ve and curr_min is -ve 3) if for input like: [-1, -8] 16 | curr_min= min(temp, n*curr_min, n) 17 | ans= max(ans, curr_max) 18 | return ans 19 | 20 | -------------------------------------------------------------------------------- /Greedy/2037. Minimum Number of Moves to Seat Everyone.py: -------------------------------------------------------------------------------- 1 | # logic: we jus have to make both the array equal. 2 | # for minimum operation , we have to match smallest to smallest and largest to largest. 3 | # so just sort both the arrays and add the difference of abs value in ans. 4 | 5 | class Solution: 6 | def minMovesToSeat(self, seats: List[int], students: List[int]) -> int: 7 | seats.sort() 8 | students.sort() 9 | ans = 0 10 | for i in range(len(seats)): 11 | ans += abs(seats[i] - students[i]) 12 | return ans 13 | -------------------------------------------------------------------------------- /Greedy/2087. Minimum Cost Homecoming of a Robot in a Grid.py: -------------------------------------------------------------------------------- 1 | # observation : we must cross each row and each column between given positions to go 2 | # from the startPos to the homePos. 3 | # So, we will always incur cost of each row and column between home and start positions atleast once. 4 | 5 | # It must also be observed that it's always best to travel through rows and column in the direction 6 | # of start to end position and never beneficial to go in the opposite direction since we would then 7 | # incur costs twice with no benefits. That is, we must traverse the shortest path from start to end. 8 | 9 | # In the below solution, we are travelling from end to start just to avoid extra condition 10 | # (as we incur cost of rows & columns of ending cell but not of the start cell). 11 | 12 | class Solution: 13 | def minCost(self, startPos, homePos, rowCosts, colCosts): 14 | ans, i, j = 0, homePos[0], homePos[1] 15 | while i != startPos[0]: 16 | ans += rowCosts[i] 17 | i += -1 if i > startPos[0] else 1 18 | while j != startPos[1]: 19 | ans += colCosts[j] 20 | j += -1 if j > startPos[1] else 1 21 | return ans -------------------------------------------------------------------------------- /Greedy/2294. Partition Array Such That Maximum Difference Is K.py: -------------------------------------------------------------------------------- 1 | # logic: 2 | # Iterate each element A[i] in the input array, 3 | # and we try to add it into the current subsequence. 4 | 5 | # We need to check if the differnce is still good. 6 | # So we firstly update the value of mn and mx 7 | # mn = min(mn, a) 8 | # mx = max(mx, a). 9 | 10 | # If mx - mn > k, 11 | # this means the difference between the maximum and minimum values, 12 | # is bigger than k in current subsequence, 13 | 14 | # A[i] cannot be added to the subsequence, 15 | # so we start a new subsequence with A[i] as the first element, 16 | # thus increment res and update mn = mx = a. 17 | 18 | # Note: was asking for subsequence and only minimum and maximum will matter, 19 | # so we can sort to check the difference easily. 20 | 21 | # vvi: if asked for subarray then we can't sort because in subarray order matters. 22 | # And in subsequence order doesn't matter so we can sort. 23 | 24 | # time:O(n*logn) 25 | 26 | class Solution: 27 | def partitionArray(self, nums: List[int], k: int) -> int: 28 | nums.sort() 29 | ans= 1 30 | minNo = maxNo= nums[0] 31 | for num in nums: 32 | minNo= min(minNo, num) 33 | maxNo= max(maxNo, num) 34 | if maxNo - minNo > k: 35 | ans+= 1 36 | minNo= maxNo= num # starting of new subsequence 37 | return ans 38 | -------------------------------------------------------------------------------- /Greedy/2712. Minimum Cost to Make All Characters Equal.py: -------------------------------------------------------------------------------- 1 | # Approach 2 | # start traversing through the array 3 | # a. If you encounter different element i.e s[i] != s[i-1]: 4 | # check from which side it is feasible for us to take less move to make it equal i.e 5 | # i.e 1) either make 'i-1'th char equal to 'i'th char by flipping till index 'i-1' from front with cost of 'i' OR 6 | # 2) make 'i'th char equal to 'i-1'th char with cost by flipping till index 'i' from back with cost of 'n-i'. 7 | 8 | # Maintain a variable ans and keep on adding the min value required for us. 9 | 10 | # time: O(n) 11 | 12 | class Solution: 13 | def minimumCost(self, s: str) -> int: 14 | ans= 0 15 | n= len(s) 16 | for i in range(1, n): 17 | if s[i] != s[i-1]: 18 | ans+= min(i, n-i) 19 | return ans 20 | 21 | 22 | # method 2: Try to do by this method also 23 | # https://leetcode.com/problems/minimum-cost-to-make-all-characters-equal/solutions/3570183/cpp-prefix-and-suffix-sum/ 24 | 25 | -------------------------------------------------------------------------------- /Greedy/2717. Semi-Ordered Permutation.py: -------------------------------------------------------------------------------- 1 | # time: o(n) 2 | class Solution: 3 | def semiOrderedPermutation(self, nums: List[int]) -> int: 4 | n= len(nums) 5 | i1= nums.index(1) # index of '1' 6 | i2= nums.index(n) # index of 'n' 7 | if i2 > i1 : 8 | # then ans= Bringing '1' to index '0' + Bringing 'n' to index 'n-1' 9 | return i1 + (n -1 - i2) 10 | # either bring i1 to index '0' then bring 'n' to index 'n-1' but while bringing '1' to index '0' 'n' will move one step right so '-1' more and same if we bring first 'n' to 'n-1'....our ans will be minimum of both 11 | return min(i1 + (n- 1 - i2 -1), (n -1 - i2) + (i1 -1)) 12 | -------------------------------------------------------------------------------- /Greedy/3191. Minimum Operations to Make Binary Array Elements Equal to One I.PY: -------------------------------------------------------------------------------- 1 | # Logic: what if nums[0] = 0 ? 2 | # If nums[0] is 0, then the only way to change it to 1 is by doing an operation on the first 3 elements of the array. 3 | 4 | # so just do the same for every element. 5 | # if you see any element = 0 then flip next 2 elements. 6 | 7 | class Solution { 8 | public int minOperations(int[] nums) { 9 | int n = nums.length; 10 | int ans = 0; 11 | for(int i = 0 ; i < n; i ++) { 12 | if(nums[i] == 0) { 13 | if(i + 2 >= n) 14 | // No sufficient elements to flip to make value at this index = 1 15 | return -1 ; 16 | nums[i] = 1; # No need of this 17 | nums[i + 1] ^= 1; 18 | nums[i + 2] ^= 1; 19 | ans += 1 ; 20 | } 21 | } 22 | return ans; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Greedy/Minimum Platforms.py: -------------------------------------------------------------------------------- 1 | # Logic: Exactly same as "253. meeting Rooms II" 2 | # except here in case of same arrival and depart time we will need one platform. 3 | # (Given: At any given instance of time, same platform can not be used for both departure of a train and arrival of another train. In such cases, we need different platforms.) 4 | 5 | # Replace platform -> rooms 6 | 7 | # Just copied pasted code of "253. meeting Rooms II". 8 | 9 | class Solution: 10 | def minimumPlatform(self,n,arr,dep): 11 | start= sorted(arr) 12 | end= sorted(dep) 13 | ans, count= 0, 0 14 | s, e= 0, 0 # pointer to start and end array 15 | while s < len(start): # till we have started all the meetings 16 | # overlapping so we will need one new room. 17 | if start[s] <= end[e]: 18 | count+= 1 # allocated new room for overlapping meeting 19 | s+= 1 # started one so incr 's' by '1'. 20 | ans= max(ans, count) 21 | else: 22 | # one meeting ended. now the previous can be used for different meeting so decr total no of room required. 23 | count -= 1 24 | e += 1 25 | return ans -------------------------------------------------------------------------------- /Hashing/1207. Unique Number of Occurrences.py: -------------------------------------------------------------------------------- 1 | # Python 2 | class Solution: 3 | def uniqueOccurrences(self, arr: List[int]) -> bool: 4 | freq = {} 5 | for x in arr: 6 | freq[x] = freq.get(x, 0) + 1 7 | 8 | return len(freq) == len(set(freq.values())) 9 | 10 | 11 | # java 12 | """ 13 | class Solution { 14 | public boolean uniqueOccurrences(int[] arr) { 15 | Map freq = new HashMap<>(); 16 | for (int x : arr) { 17 | freq.put(x, freq.getOrDefault(x, 0) + 1); 18 | } 19 | 20 | Set s = new HashSet<>(); 21 | for (int x : freq.values()) { 22 | s.add(x); 23 | } 24 | 25 | return freq.size() == s.size(); 26 | } 27 | } 28 | """ -------------------------------------------------------------------------------- /Hashing/1282. Group the People Given the Group Size They Belong To.py: -------------------------------------------------------------------------------- 1 | # Time : O(n) 2 | 3 | class Solution: 4 | def groupThePeople(self, groupSizes: List[int]) -> List[List[int]]: 5 | noOfPeopleInGroup = collections.defaultdict(list) # will keep track of people that should belong to a given gr size. 6 | for i, groupSize in enumerate(groupSizes): 7 | noOfPeopleInGroup[groupSize].append(i) 8 | 9 | ans = [] 10 | for groupSize , people in noOfPeopleInGroup.items(): 11 | # no = len(people) 12 | # noOfGroup = no //groupSize # No of group needed for this gr size 13 | 14 | # har people ko gr array me dalte jao. maximum gr ka len = groupSize 15 | cur = [] 16 | for p in people: 17 | cur.append(p) 18 | if len(cur) == groupSize: 19 | ans.append(cur) 20 | cur = [] 21 | return ans 22 | -------------------------------------------------------------------------------- /Hashing/1460. Make Two Arrays Equal by Reversing Subarrays.py: -------------------------------------------------------------------------------- 1 | # Logic: 2 | """ 3 | kitne bhi size ka subarray ko reverse kar sakte h. 4 | iska matlab agar har element ka frequency same h dono array me then, dono ko equal bna sakte h. 5 | """ 6 | 7 | # Time= space = O(n) 8 | class Solution: 9 | def canBeEqual(self, target: List[int], arr: List[int]) -> bool: 10 | count1 = Counter(target) 11 | for num in arr: 12 | if count1[num] <= 0: 13 | return False 14 | count1[num] -= 1 15 | return True 16 | -------------------------------------------------------------------------------- /Hashing/149. Max Points on a Line.py: -------------------------------------------------------------------------------- 1 | # Same Q as "Hit most balloons" only difference here is no duplicate points i.e no two points having same both 'x' and 'y' coordinate. 2 | # same code as "Hit Most ballons" just removed the lines that for counting the same point. 3 | 4 | # Time: O(n^2) 5 | 6 | class Solution: 7 | def maxPoints(self, points: List[List[int]]) -> int: 8 | N= len(points) 9 | ans= 1 # minimum possible ans can be '1'. 10 | for i in range(N-1): 11 | slopeCount= collections.defaultdict(int) # will count the points having same slope. 12 | x1, y1= points[i] 13 | for j in range(i+1, N): 14 | x2, y2= points[j] 15 | 16 | dy= (y2 - y1) 17 | dx= (x2- x1) 18 | if dx== 0: # handling if slope is "infinity". 19 | slopeCount[10**4]+= 1 # just any very large value. max val of x or y can be= 10**9 so slope can't be more than this 20 | continue 21 | slope= dy/dx 22 | slopeCount[slope]+= 1 23 | 24 | for key,val in slopeCount.items(): 25 | ans= max(ans, val + 1) # '1' for current point. 26 | return ans -------------------------------------------------------------------------------- /Hashing/1679. Max Number of K-Sum Pairs.py: -------------------------------------------------------------------------------- 1 | # method 1: sort the array and apply "Two Sum for sorted array" 2 | # time: O(n*logn) 3 | 4 | # method 2: 5 | 6 | # just applied normal two sum. 7 | # but instead of storing 'index' as value, storing frequency since there can be more than same pair. 8 | 9 | # when we find any pair then we will incr the ans += 1 10 | # And we will decr the frequency count of 'remainingSum' and in this case we won't incr the count of curr 'n', 11 | # because this pair got used in the ans. 12 | 13 | class Solution: 14 | def maxOperations(self, nums: List[int], k: int) -> int: 15 | numFrequency= collections.defaultdict(int) 16 | count= 0 17 | for n in nums: 18 | remainingSum = k - n 19 | if remainingSum in numFrequency: 20 | count+= 1 21 | numFrequency[remainingSum]-= 1 22 | if numFrequency[remainingSum]== 0: 23 | del numFrequency[remainingSum] 24 | else: # if pair not found then only incr the count. 25 | numFrequency[n]+= 1 26 | 27 | return count 28 | 29 | 30 | # Note: Whenever you are asked to find pairs then think of 'Two sum' logic and 31 | # Store the 'frequency' as value because pair at different index will also add to ans. -------------------------------------------------------------------------------- /Hashing/1832. Check if the Sentence Is Pangram .py: -------------------------------------------------------------------------------- 1 | # using set 2 | # logic: Add each eleemnt you see into set. Then at last length of set must be = 26 3 | 4 | class Solution: 5 | def checkIfPangram(self, sentence: str) -> bool: 6 | return len(set(s)) == 26 7 | 8 | # java 9 | """ 10 | class Solution { 11 | public boolean checkIfPangram(String sentence) { 12 | Set s = new HashSet<>(); 13 | for (int i = 0; i < sentence.length(); ++i) 14 | s.add(sentence.charAt(i)); 15 | return s.size() == 26; 16 | 17 | } 18 | } 19 | """ 20 | 21 | # Method 2: Best one 22 | # without set or map 23 | 24 | # Logic: for each char you see make bit_value = 1 in 'seen' 25 | # e.g: char = e then make 'bit_value' = 1 at 4th position ('e' - 'a') 26 | 27 | # Then 'seen' value at must be equal to '(1 << 26) - 1' if all 26 characters are present. 28 | 29 | """ 30 | class Solution { 31 | public boolean checkIfPangram(String sentence) { 32 | int seen = 0; 33 | for(char c : sentence.toCharArray()) { 34 | int ci = c - 'a'; 35 | seen = seen | (1 << ci); 36 | } 37 | return seen == ((1 << 26) - 1); 38 | } 39 | } 40 | """ 41 | 42 | -------------------------------------------------------------------------------- /Hashing/2053. Kth Distinct String in an Array.py: -------------------------------------------------------------------------------- 1 | # Just sam elogic as :" 387. First Unique Character in a String" 2 | 3 | class Solution: 4 | def kthDistinct(self, arr: List[str], k: int) -> str: 5 | m = {} 6 | for s in arr: 7 | if s in m: 8 | m[s] += 1 9 | else: 10 | m[s] = 1 11 | 12 | for s in arr: 13 | if m[s] == 1: 14 | k -= 1 15 | if k == 0: 16 | return s 17 | 18 | return "" -------------------------------------------------------------------------------- /Hashing/2154. Keep Multiplying Found Values by Two.py: -------------------------------------------------------------------------------- 1 | # 2 | """" 3 | class Solution { 4 | public int findFinalValue(int[] nums, int original) { 5 | boolean[] m = new boolean[1001]; // Boolean array to mark the presence of numbers 6 | // Mark the presence of numbers in the nums array 7 | for (int num : nums) { 8 | m[num] = true; 9 | } 10 | // Double the original value while it is present in the array 11 | while (original <= 1000 && m[original]) { 12 | original *= 2; 13 | } 14 | return original; // Return the final value of original 15 | } 16 | } 17 | """ 18 | 19 | # method 2: 20 | """" 21 | import java.util.HashSet; 22 | 23 | class Solution { 24 | public int findFinalValue(int[] nums, int original) { 25 | HashSet set = new HashSet<>(); 26 | // Add all elements from nums to the set 27 | for (int num : nums) { 28 | set.add(num); 29 | } 30 | // Double the original value as long as it's found in the set 31 | while (set.contains(original)) { 32 | original *= 2; 33 | } 34 | return original; 35 | } 36 | """ -------------------------------------------------------------------------------- /Hashing/217. Contains Duplicate.py: -------------------------------------------------------------------------------- 1 | """ 2 | class Solution { 3 | public boolean containsDuplicate(int[] nums) { 4 | Set s = new HashSet<>(); 5 | for(int num: nums){ 6 | if(s.contains(num)) 7 | return true; 8 | s.add(num) ; 9 | } 10 | return false; 11 | 12 | } 13 | } 14 | 15 | """ -------------------------------------------------------------------------------- /Hashing/2244. Minimum Rounds to Complete All Tasks.py: -------------------------------------------------------------------------------- 1 | # Logic: Just find the freq of task for each level(store in hashmap). 2 | # Then traverse the hashmap, if val < 2 then not possible so return -1. 3 | # else minimum no of rounds needed to complete those taks at same level = ceil(val / 3) . dividing by '3' for minimum round. 4 | 5 | # Time = space = O(n) 6 | 7 | class Solution: 8 | def minimumRounds(self, tasks: List[int]) -> int: 9 | freq = Counter(tasks) 10 | ans = 0 11 | for key, val in freq.items(): 12 | if val < 2 : 13 | return -1 14 | ans += ceil(val / 3) 15 | return ans -------------------------------------------------------------------------------- /Hashing/2352. Equal Row and Column Pairs.py: -------------------------------------------------------------------------------- 1 | # Method 1: Brute force 2 | # For each pair of row and col, check all elements. 3 | 4 | # Time: O(n^3) 5 | 6 | 7 | # Method 2: 8 | 9 | # time: O(n^2) 10 | class Solution: 11 | def equalPairs(self, grid: List[List[int]]) -> int: 12 | n = len(grid) 13 | sameRowCount = collections.defaultdict(int) 14 | for r in range(n): 15 | sameRowCount[tuple(grid[r])] += 1 16 | # now check each col, how many times it is present as row. 17 | # that much pair we can form with this col with all those rows. 18 | ans = 0 19 | for c in range(n): 20 | col = [] 21 | for r in range(n): 22 | col.append(grid[r][c]) 23 | ans += sameRowCount[tuple(col)] 24 | return ans 25 | 26 | -------------------------------------------------------------------------------- /Hashing/2610. Convert an Array Into a 2D Array With Conditions.py: -------------------------------------------------------------------------------- 1 | # row should not contain duplicate and we need only miniml number of rows. 2 | 3 | # logic: This means no of row must be= max(freq) of any ele to have all distinct ele in each row. 4 | # And for filling up each row traverse each distinct ele(key in dictionary) and check if its freq >=1 (still some ele remaining to include) 5 | # then include the cur ele in row(curAns) 6 | 7 | # time: no_row * no_distinct_ele. 8 | 9 | class Solution: 10 | def findMatrix(self, nums: List[int]) -> List[List[int]]: 11 | freq= Counter(nums) 12 | row_no= max(freq.values()) # shortcut to get val in dictionary 13 | 14 | ans= [] 15 | for i in range(row_no): 16 | curAns= [] 17 | for key, val in freq.items(): 18 | if val >= 1: 19 | curAns.append(key) 20 | # val-= 1 # won't change the value 21 | freq[key]-= 1 22 | ans.append(curAns) 23 | return ans 24 | 25 | 26 | # no need of numset, w -------------------------------------------------------------------------------- /Hashing/2766. Relocate Marbles.py: -------------------------------------------------------------------------------- 1 | # Logic: store in set to do 'add' and 'remove' in O(1). 2 | # moveFrom : means marbles won't be at this position, so remove this position 3 | # moveTo : means marble will come at this position, so add this position 4 | 5 | # At last return the sorted list. 6 | 7 | class Solution: 8 | def relocateMarbles(self, nums: List[int], moveFrom: List[int], moveTo: List[int]) -> List[int]: 9 | numSet= set(nums) 10 | for i in range(len(moveFrom)): 11 | numSet.remove(moveFrom[i]) 12 | numSet.add(moveTo[i]) 13 | ans = list(numSet) 14 | ans.sort() 15 | return ans 16 | 17 | -------------------------------------------------------------------------------- /Hashing/3185. Count Pairs That Form a Complete Day II.py: -------------------------------------------------------------------------------- 1 | # Logic: Find the number of pairs divisible by 'k' where k = 24. 2 | 3 | # How to do? 4 | # for each number 'nums[i]' how can we get the pairs ? 5 | # => find the remainder 'nums[i] % k' then number we will need to make sum divisble by 'k' i.e needed = '(k - remainder) % k' 6 | # so add the count of 'needed' for each number. 7 | 8 | # and for 'remainder' increase the count. 9 | 10 | # Tim : O(n) 11 | 12 | class Solution: 13 | def countCompleteDayPairs(self, hours: List[int]) -> int: 14 | k = 24 15 | n = len(hours) 16 | count = collections.defaultdict(int) 17 | ans = 0 18 | for i in range(n): 19 | remainder = hours[i] % k 20 | needed = (k - remainder) % k 21 | ans += count[needed] 22 | count[remainder] += 1 23 | return ans -------------------------------------------------------------------------------- /Hashing/3223. Minimum Length of String After Operations.py: -------------------------------------------------------------------------------- 1 | # logic: 2 | """ 3 | suppose any char has freq 'v' then all will get cancelled except either one or two character. 4 | If 'v' is even then : 2 char will be remaining else only '1' char 5 | """ 6 | 7 | # time = space = O(n) 8 | 9 | from collections import Counter 10 | class Solution: 11 | def minimumLength(self, s: str) -> int: 12 | freq = Counter(s) 13 | ans = 0 14 | for val in freq.values(): 15 | ans += 2 if val % 2 == 0 else 1 16 | return ans 17 | 18 | # Java 19 | """ 20 | import java.util.HashMap; 21 | 22 | class Solution { 23 | public int minimumLength(String s) { 24 | HashMap freq = new HashMap<>(); 25 | int ans = 0; 26 | 27 | // Count frequency of each character in the string 28 | for (char ch : s.toCharArray()) { 29 | freq.put(ch, freq.getOrDefault(ch, 0) + 1); 30 | } 31 | 32 | // Calculate the result based on frequencies 33 | for (int val : freq.values()) { 34 | ans += (val % 2 == 0) ? 2 : 1; 35 | } 36 | 37 | return ans; 38 | } 39 | } 40 | """ 41 | -------------------------------------------------------------------------------- /Hashing/359 · Logger Rate Limiter.py: -------------------------------------------------------------------------------- 1 | # Logic: A message should be printed if and only if it has not been printed in the last 10 seconds i.e 2 | # message printed at timestamp t will prevent other identical messages from being printed until timestamp t + 10. 3 | 4 | # 1) if message is coming for 1st time then , it will get printed. 5 | # store the timestamp in this case 6 | 7 | # 2) if message is already there: 8 | # i) if time difference < 10 then it won't get printed, simply return False. No need to update timestamp in this case. 9 | # ii) else will get printed and update the timestamp. 10 | 11 | # Time: O(n) 12 | 13 | class Logger: 14 | 15 | def __init__(self): 16 | self.lastPrintedTime = collections.defaultdict(int) 17 | 18 | def could_print_message(self, timestamp: int, message: str) -> bool: 19 | if message not in self.lastPrintedTime: 20 | self.lastPrintedTime[message] = timestamp 21 | return True 22 | else: 23 | if timestamp - self.lastPrintedTime[message] < 10: # q definition is this only. 24 | return False 25 | else: 26 | self.lastPrintedTime[message] = timestamp 27 | return True 28 | -------------------------------------------------------------------------------- /Hashing/554. Brick Wall.py: -------------------------------------------------------------------------------- 1 | # our ans will will be minimum when max_no of bricks will end at same point(from left to right) 2 | # vvi: so now our Q reduces to find the max_no of bricks that end at same point. 3 | # we can use hashmap for this. 4 | 5 | # endPoints will be start from each row and bricks width will get added to the endPoints. 6 | # after that we will update our hashmap for that endpoint 7 | # then our ans= row - max_Count(of bricks at any end point). 8 | 9 | # time: O(row * width), where width= sum of any row since width is equal for each row. 10 | 11 | class Solution: 12 | def leastBricks(self, wall: List[List[int]]) -> int: 13 | row= len(wall) 14 | bricksEndingPoints= collections.defaultdict(list) # [endPoint : no_brick_in_diff_row_that_end_at_this_point] 15 | max_freq= 0 16 | for bricks in wall: 17 | endPoint= 0 18 | for i in range(len(bricks)- 1): # "-1" for ignoring the last endPoint 19 | width= bricks[i] 20 | endPoint+= width 21 | bricksEndingPoints[endPoint]= 1 + bricksEndingPoints.get(endPoint, 0) 22 | max_freq= max(max_freq, bricksEndingPoints[endPoint]) 23 | return row - max_freq -------------------------------------------------------------------------------- /Hashing/Check if an array is subset of another array.py: -------------------------------------------------------------------------------- 1 | # Subset means: arr1 should contain all ele of arr2 and quantity of all those ele in arr1 must be >= arr2. 2 | 3 | # time= space= O(n) 4 | from collections import Counter 5 | def isSubset( a1, a2, n, m): 6 | hashmap1= Counter(a1) 7 | hashmap2= Counter(a2) 8 | for key, val in hashmap2.items(): 9 | if val > hashmap1[key]: 10 | return "No" 11 | return "Yes" 12 | 13 | 14 | # same way we can check "Two array is equal or not". 15 | # frequency must be equal of each ele. 16 | 17 | # Note: If order also mattering then it won't work. 18 | 19 | from collections import Counter 20 | class Solution: 21 | def check(self,A,B,N): 22 | hashmap1= Counter(A) 23 | hashmap2= Counter(B) 24 | for key, val in hashmap2.items(): 25 | if val != hashmap1[key]: 26 | return False 27 | return True 28 | -------------------------------------------------------------------------------- /Hashing/Find first non-repeating character of given String.py: -------------------------------------------------------------------------------- 1 | # 1) count the freq of each char 2 | # 2) then check the count of each char of = 1 then return that index. 3 | # because we are checking from start only so if 1st time we will get freq= 1 that will be ans. 4 | 5 | from collections import Counter 6 | class Solution: 7 | def firstUniqChar(self, s: str) -> int: 8 | freq= Counter(s) 9 | for i, c in enumerate(s): 10 | if freq[c]== 1: 11 | return i 12 | return -1 13 | 14 | -------------------------------------------------------------------------------- /Hashing/Minimum operation to make all elements equal in array.py: -------------------------------------------------------------------------------- 1 | # Note: we can add, subtract, multiply, divide by any number. 2 | 3 | # logic: we can make all array equal in max 'n-1' operation if all ele will be distinct 4 | # by addition or subtraction operation or any other operation. 5 | 6 | # so if all ele are distinct , we will need 'n-1' operation no matter what ele we choose as target. 7 | 8 | # Note vvi: if there are duplicates elements then for minimum no of operation we will choose the ele with max frequency as target and 9 | # will make all ele to this target ele either by 'addition' or subtraction. 10 | 11 | # so problem reduces to "find the max freq of any ele in arr" say = max_freq 12 | # then our ans= n- max_freq. 13 | 14 | # time= space= O(n) 15 | -------------------------------------------------------------------------------- /Heap/703. Kth Largest Element in a Stream.py: -------------------------------------------------------------------------------- 1 | # add will give ans in O(1) only 2 | 3 | import heapq 4 | class KthLargest: 5 | def __init__(self, k: int, nums: List[int]): 6 | self.k= k 7 | self.nums= nums 8 | heapq.heapify(self.nums) 9 | 10 | def add(self, val: int) -> int: 11 | heapq.heappush(self.nums, val) 12 | while len(self.nums) > self.k: # will run 'n-k' times only as there will be only one extra ele in heap always 13 | heapq.heappop(self.nums) 14 | return self.nums[0] 15 | 16 | # java 17 | """ 18 | import java.util.PriorityQueue; 19 | 20 | class KthLargest { 21 | private int k; 22 | private PriorityQueue heap; 23 | 24 | public KthLargest(int k, int[] nums) { 25 | this.k = k; 26 | this.heap = new PriorityQueue<>(); 27 | for (int num : nums) { 28 | add(num); 29 | } 30 | } 31 | 32 | public int add(int val) { 33 | heap.offer(val); 34 | if (heap.size() > k) { 35 | heap.poll(); 36 | } 37 | return heap.peek(); 38 | } 39 | } 40 | 41 | """ -------------------------------------------------------------------------------- /Heap/857. Minimum Cost to Hire K Workers.py: -------------------------------------------------------------------------------- 1 | # Logic: in notes , page no: 61 2 | 3 | # Similar to q : "2542. Maximum Subsequence Score" . 4 | # In that q: first sort in descending order + then apply minHeap 5 | 6 | # Here 'first sort in ascending order + then apply maxHeap'. 7 | 8 | # Time: O(n*logn + n*logk) 9 | 10 | class Solution: 11 | def mincostToHireWorkers(self, quality: List[int], wage: List[int], k: int) -> float: 12 | pairs = [] # (ratio / quality) 13 | for i in range(len(quality)): 14 | pairs.append((wage[i]/quality[i], quality[i])) 15 | pairs.sort(key = lambda x : x[0]) # sorting based on rate 16 | ans = float('inf') 17 | total_quality = 0 # of workers seen till now 18 | maxHeap = [] 19 | for rate, q in pairs: 20 | heapq.heappush(maxHeap, -1*q) 21 | total_quality += q 22 | if len(maxHeap) > k: 23 | max_q = -1 * heapq.heappop(maxHeap) 24 | total_quality -= max_q 25 | if len(maxHeap) == k: 26 | ans = min(ans, total_quality * rate) 27 | return ans -------------------------------------------------------------------------------- /Heap/K’th Smallest Element in Unsorted Array.py: -------------------------------------------------------------------------------- 1 | 2 | # 1st method: selection sort 3 | # run the outer loop k times 4 | # time: O(n^2) 5 | 6 | 7 | # 2nd method: sort the elements and return the 'arr[k-1]' 8 | # time: O(nlogn) 9 | arr=[1,3,5,7,9,2] 10 | k=2 11 | arr.sort() 12 | print(arr[k-1]) 13 | 14 | 15 | # 3rd method: make a min heap and delete the k-1 element 16 | # after that return the top ele of the array, that will be the kth smallest element 17 | 18 | 19 | # third method: use max heap 20 | # python has only inbuilt function for minHeap so for implementing maxHeap using minHeap 21 | # just add/remove the number in/from the minheap switching its sign(multiply by '-1') 22 | # time: O(n*logk) 23 | import heapq 24 | def KthSmallest(arr,k): 25 | heap= [] 26 | for num in arr: 27 | heapq.heappush(heap,-num) 28 | if len(heap)> k: 29 | heapq.heappop(heap) 30 | return (-heap[0]) 31 | 32 | arr = [7,4,6,3,9,1] 33 | print(KthSmallest(arr,3)) 34 | 35 | 36 | # method 4: try to do by Quick Select 37 | 38 | 39 | arr = [7,4,6,3,9,1] 40 | n= len(arr) 41 | print(KthSmallest(arr,0,n-1,3)) 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Heap/Maximum Sum Combinations.py: -------------------------------------------------------------------------------- 1 | # Exact same as: "373. Find K Pairs with Smallest Sums". 2 | 3 | # Just sort both the arrays and apply same logic. 4 | 5 | import heapq 6 | class Solution: 7 | def solve(self, a, b, k): 8 | n = len(a) 9 | a.sort() 10 | b.sort() 11 | maxHeap = [(-1*(a[n-1] + b[n-1]), n-1, n-1)] 12 | cnt = 0 13 | ans = [] 14 | visited = set() 15 | visited.add((n-1, n-1)) 16 | while cnt < k : 17 | sum, i, j = heapq.heappop(maxHeap) 18 | ans.append(-1*sum) 19 | cnt += 1 20 | # visited.add((i, j)) # Marking visited after poping will give duplicate ans. 21 | if j > 0 and (i, j-1) not in visited: 22 | heapq.heappush(maxHeap, (-1*(a[i] + b[j-1]), i, j-1)) 23 | visited.add((i, j-1)) 24 | if i > 0 and (i-1, j) not in visited: 25 | heapq.heappush(maxHeap, (-1*(a[i -1] + b[j]), i -1, j)) 26 | visited.add((i-1, j)) 27 | return ans 28 | -------------------------------------------------------------------------------- /Heap/Sort_k_sorted_array.py: -------------------------------------------------------------------------------- 1 | # method 1: using Insertion sort 2 | # time complexity: O(N*K) as inner loop will run only 'k' times 3 | 4 | 5 | # just like 'finding kth largest' . 6 | # to get the first smallest ele , We may have to traverse till 'k+1' ele of the array 7 | # as 1st ele can go till this point only. 8 | # So after inserting k+1 element in heap , you will start getting the smallest ele at top in heap. 9 | # after loop end just do the same for remaining ele in heap 10 | import heapq 11 | def Sort_K_Sorted(arr,k): 12 | heap, ans= [], [] 13 | for num in arr: 14 | heapq.heappush(heap,num) 15 | if len(heap)> k: # for getting 16 | ans.append(heapq.heappop(heap)) 17 | # After this all elements except k largest element will get sorted 18 | # arr will contain only 'k largest ele' 19 | while(heap): 20 | ans.append(heapq.heappop(heap)) 21 | return ans 22 | 23 | arr= [6, 5, 3, 2, 8, 10, 9] 24 | print("sorted array is: ") 25 | print(Sort_K_Sorted(arr, 3)) 26 | -------------------------------------------------------------------------------- /Heap/Sum of all elements between k1’th and k2’th smallest elements.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | class Solution: 3 | def sumBetweenTwoKth(self, A, N, K1, K2): 4 | heapq.heapify(A) # will make a min heap 5 | count= 0 6 | sum1= 0 7 | while(len(A)): 8 | temp= heapq.heappop(A) 9 | count+= 1 10 | if count== K2: 11 | return sum1 12 | if count > K1 and count < K2: # this will be our one of the ans 13 | sum1+= temp 14 | 15 | 16 | # using maxHEap 17 | import heapq 18 | class Solution: 19 | def sumBetweenTwoKth(self, A, N, K1, K2): 20 | heap= [] 21 | for i in range(N): 22 | heapq.heappush(heap, -1*A[i]) 23 | if len(heap)> K2-1: 24 | heapq.heappop(heap) 25 | ans= 0 26 | while heap: 27 | if len(heap)== K1: # because after poping in above 'for' it may reach to 'k1' also 28 | return ans 29 | temp = -1*heapq.heappop(heap) 30 | ans+= temp -------------------------------------------------------------------------------- /Line Sweep Algorithm/1854. Maximum Population Year.py: -------------------------------------------------------------------------------- 1 | # Logic: We don't need to take space of size '2050' because year is varying from 1950 to 2050. 2 | # So space of size '101' will be fine. 3 | 4 | 5 | # java 6 | """ 7 | class Solution { 8 | public int maximumPopulation(int[][] logs) { 9 | int[] year = new int[101]; 10 | // O(n) -> n is log.length 11 | 12 | for(int[] log : logs){ 13 | year[log[0] - 1950]++; 14 | year[log[1] - 1950]--; 15 | } 16 | 17 | int maxNum = year[0], maxYear = 1950; 18 | 19 | for(int i = 1; i < year.length; i++){ 20 | year[i] += year[i - 1]; // Generating Prefix Sum 21 | if(year[i] > maxNum){ 22 | maxNum = year[i]; 23 | maxYear = i + 1950; 24 | } 25 | } 26 | return maxYear; 27 | 28 | } 29 | } 30 | """ 31 | 32 | # Related Q: 33 | # 1) 2848. Points That Intersect With Cars 34 | # just apply same logic and add count of point whose value > 0. 35 | 36 | # 2) -------------------------------------------------------------------------------- /Line Sweep Algorithm/2848. Points That Intersect With Cars.py: -------------------------------------------------------------------------------- 1 | # just apply same logic as '1854. Maximum Population Year' and add count of point whose value > 0. -------------------------------------------------------------------------------- /LinkList/2181. Merge Nodes in Between Zeros.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def mergeNodes(self, head: ListNode) -> ListNode: 3 | dummy = head 4 | pre, cur = dummy, head.next # pre: pointer to pre value in answer 5 | while cur and cur.next : 6 | cur_sum = 0 7 | while cur.val != 0: 8 | cur_sum += cur.val 9 | cur = cur.next 10 | node = ListNode(cur_sum) 11 | pre.next = node 12 | pre = pre.next 13 | cur = cur.next 14 | return dummy.next 15 | 16 | 17 | # Java 18 | """ 19 | class Solution { 20 | public ListNode mergeNodes(ListNode head) { 21 | ListNode dummy = head; 22 | ListNode pre = dummy; 23 | ListNode cur = head.next; 24 | while(cur != null && cur.next != null) { 25 | int curSum = 0 ; 26 | while(cur.val != 0) { 27 | curSum += cur.val; 28 | cur = cur.next; 29 | } 30 | ListNode node = new ListNode(curSum); 31 | pre.next = node; 32 | pre = pre.next; 33 | cur = cur.next; 34 | } 35 | return dummy.next; 36 | } 37 | } 38 | """ -------------------------------------------------------------------------------- /LinkList/237. Delete Node in a Linked List.py: -------------------------------------------------------------------------------- 1 | # logic: just copy the next node val into the node that we have to delete 2 | # and after that delete the next node 3 | 4 | class Solution: 5 | def deleteNode(self, node): 6 | node.val= node.next.val 7 | node.next= node.next.next 8 | 9 | # my mistake: Didn't read the Q properly, i was thinking to delete the node itself and got stuck 10 | # but Q is something else, doesn't mean that node should be deleted from the memory 11 | 12 | # Note: Read all the Q proeprly then only try to solve according to the meaning of Q, don't go on the way you were solving the Q always -------------------------------------------------------------------------------- /LinkList/Nth_node_last.py: -------------------------------------------------------------------------------- 1 | # best method: in only one swap(submitted on geeksforgeeks) 2 | # traverse the whole linklist till end and keep on incr first 3 | # and when count become>= n then after that start incr 'second' aslo 4 | # this will ensure first-second= n-1 and thus 'second' will point to the 5 | # nth node from the last 6 | def getNthFromLast(head,n): 7 | first, second= head,head 8 | count= 0 9 | while first.next: 10 | first= first.next 11 | count+= 1 12 | if count>=n: # after count becomes equal to n 13 | second= second.next 14 | if count+1 no of elements in the link list 15 | return -1 16 | else: 17 | return second.data 18 | 19 | # 2nd method: Brute force method 20 | # this will take two traversal 21 | # 1st to count no of elements and 2nd to get the nth element from the last 22 | 23 | -------------------------------------------------------------------------------- /LinkList/tempCodeRunnerFile.py: -------------------------------------------------------------------------------- 1 | 2 | def show(self): -------------------------------------------------------------------------------- /Maths and Geometry/1509. Minimum Difference Between Largest and Smallest Value in Three Moves.py: -------------------------------------------------------------------------------- 1 | # Logic: If we can do 0 move, return max(A) - min(A) 2 | # If we can do 1 move, return min(the second max(A) - min(A), the max(A) - second min(A)) & so on. 3 | 4 | # So we need to consider all possibility like: 5 | # i) remove 3 smallest number 6 | # ii) 2 smallest and 1 largest 7 | # iii) 1 smallest and 2 largest 8 | # iv) 0 smallest and 3 largest 9 | 10 | # Ans = min(all_four_possibility) 11 | 12 | class Solution: 13 | def minDifference(self, nums: List[int]) -> int: 14 | n = len(nums) 15 | if n <= 4: # in case n == 4 make all element = any one ele so ans = 0 16 | return 0 17 | nums.sort() 18 | return min(nums[n -1] - nums[3], nums[n - 2] - nums[2], nums[n - 3] - nums[1], nums[n - 4] - nums[0]) 19 | 20 | # Java 21 | """ 22 | class Solution { 23 | public int minDifference(int[] nums) { 24 | int n = nums.length; 25 | if (n <= 4) { 26 | return 0; 27 | } 28 | Arrays.sort(nums); 29 | return Math.min( 30 | Math.min(nums[n - 1] - nums[3], nums[n - 2] - nums[2]), 31 | Math.min(nums[n - 3] - nums[1], nums[n - 4] - nums[0]) 32 | ); 33 | } 34 | } 35 | """ -------------------------------------------------------------------------------- /Maths and Geometry/204. Count Primes.py: -------------------------------------------------------------------------------- 1 | # Already done in basic math. 2 | 3 | class Solution: 4 | def countPrimes(self, n: int) -> int: 5 | if n <= 2: 6 | return 0 7 | 8 | # Create a list to mark non-prime numbers 9 | not_prime = [False] * n 10 | count = 0 11 | 12 | for i in range(2, n): 13 | if not not_prime[i]: 14 | # if 'i' is prime then all it's multiple will be non-prime 15 | count += 1 16 | j = 2 17 | while i *j < n: 18 | not_prime[i * j] = True 19 | j += 1 20 | 21 | return count 22 | 23 | """ 24 | public class Solution { 25 | public int countPrimes(int n) { 26 | boolean[] notPrime = new boolean[n]; 27 | int count = 0; 28 | for (int i = 2; i < n; i++) { 29 | if (notPrime[i] == false) { 30 | count++; 31 | for (int j = 2; i*j < n; j++) { 32 | notPrime[i*j] = true; 33 | } 34 | } 35 | } 36 | 37 | return count; 38 | } 39 | } 40 | """ -------------------------------------------------------------------------------- /Maths and Geometry/263. Ugly Number.py: -------------------------------------------------------------------------------- 1 | 2 | # just like we reduce the num into its prime factors with power. 3 | # Here factors are given i.e 2,3,5. 4 | # We will try to reduce 'num' using these factors to '1'. 5 | # first we will reduce by 2 then by 3 and then by 5 and last check if num== 1. 6 | # vvi: Agar hm num ko '1' tak leke chal jate h powers of 2,3,5 ko use karke then wo ugly number hoga. 7 | 8 | # time: O(a + b + c) where num= 2^a + 3^b + 5^c 9 | class Solution: 10 | def is_ugly(self, num: int) -> bool: 11 | if num > 0: 12 | for n in [2,3, 5]: 13 | while num % n== 0: # divide by same number till it is divisible. just like we are finding the power of 'n' in prime factors. 14 | num/= n 15 | return num== 1 16 | 17 | 18 | # we can also write like this. 19 | class Solution: 20 | def is_ugly(self, num: int) -> bool: 21 | if num > 0: 22 | for n in range(2, 6): # only four is extra but 4 means 2^2 so will not affect our ans. 23 | while num % n== 0: 24 | num/= n 25 | return num== 1 26 | 27 | 28 | # Extended version: "264. Ugly Number II". -------------------------------------------------------------------------------- /Maths and Geometry/2849. Determine if a Cell Is Reachable at a Given Time.py: -------------------------------------------------------------------------------- 1 | # Logic: From a given point we can reach any other point in minimum time if we go diagonally. 2 | # For this you will have to go minimum = max distance between source and destination in either direction(say distance) 3 | # because while going diagonally you can take maximum '1' step in each direction. 4 | 5 | # Observation: So if t is >= distance then we can reach destination through any path in time >= 't' 6 | # Because we can take any adjacent path. 7 | # Note: we can take the same path again. 8 | 9 | # One corner case: 10 | # if source and destination both are same then, 11 | # we can reach the destination same point if t != 1 because if t = 1 then you must be outside of destination. 12 | # And t== 0(already at destination) or if t > 1 then you can reach destination again through any path. 13 | 14 | # Time : O(1) 15 | 16 | class Solution: 17 | def isReachableAtTime(self, sx: int, sy: int, fx: int, fy: int, t: int) -> bool: 18 | # max distance between source and destination in either direction 19 | distance = max(abs(fx - sx), abs(fy - sy)) 20 | if distance == 0: 21 | return t != 1 22 | return t >= distance -------------------------------------------------------------------------------- /Maths and Geometry/3002. Maximum Size of a Set After Removals.py: -------------------------------------------------------------------------------- 1 | # time: O(n) = space = O(n) 2 | 3 | # Logic: we should include common element only one time. 4 | # for first find the common ele. 5 | 6 | # Then find the maximum unique ele we can include from both set of ararys without common one. 7 | # and then add common one to get the final ans. 8 | 9 | class Solution: 10 | def maximumSetSize(self, nums1: List[int], nums2: List[int]) -> int: 11 | n = len(nums1) 12 | s1 = set(nums1) 13 | s2 = set(nums2) 14 | inter = s1.intersection(s2) 15 | # find out the element we can include from both excluding common one 16 | eleFromS1 = min((len(s1) - len(inter)), n //2) # we can't include more than half 17 | eleFromS2 = min((len(s2) - len(inter)), n //2) 18 | return min(eleFromS1 + eleFromS2 + len(inter), n) 19 | -------------------------------------------------------------------------------- /Maths and Geometry/3101. Count Alternating Subarrays.py: -------------------------------------------------------------------------------- 1 | # Logic: 2 | """ 3 | At each index, find the length of alternating subarray. 4 | Say length = n after adding cur ele 'i; then we will get 'n' new subarray. 5 | 6 | e.g: 7 | 8 | [1, 0, 1, 0, 1] 9 | [0, 1, 0, 1] 10 | [1, 0, 1] 11 | [0, 1] 12 | [1] 13 | """ 14 | # Time = O(n), space = O(1) 15 | class Solution: 16 | def countAlternatingSubarrays(self, nums: List[int]) -> int: 17 | n = len(nums) 18 | size, ans, i = 1 , 1, 1 19 | while i < n: 20 | if nums[i] != nums[i - 1]: 21 | size += 1 22 | ans += size 23 | else: 24 | size = 1 25 | ans += size 26 | i += 1 27 | return ans 28 | -------------------------------------------------------------------------------- /Maths and Geometry/657. Robot Return to Origin.py: -------------------------------------------------------------------------------- 1 | # Logic: 2 | """ 3 | Net move in horizontal(left and right) and net move in vertical(up & down) must be zero. 4 | """ 5 | 6 | # java 7 | """ 8 | public class Solution { 9 | public boolean judgeCircle(String moves) { 10 | int x = 0; 11 | int y = 0; 12 | for (char ch : moves.toCharArray()) { 13 | if (ch == 'U') y++; 14 | else if (ch == 'D') y--; 15 | else if (ch == 'R') x++; 16 | else if (ch == 'L') x--; 17 | } 18 | return x == 0 && y == 0; 19 | } 20 | } 21 | """ -------------------------------------------------------------------------------- /Maths and Geometry/66. Plus One.py: -------------------------------------------------------------------------------- 1 | # Just same as " 445. Add Two Numbers II". 2 | 3 | # Apply same logic as above Q. 4 | 5 | class Solution: 6 | def plusOne(self, digits: List[int]) -> List[int]: 7 | n = len(digits) 8 | carry = 1 # we have to add '+1'. 9 | for i in range(n - 1, -1, -1): 10 | carry , num = divmod(digits[i] + carry , 10) 11 | digits[i] = num 12 | return [1] + digits if carry else digits # if carry == 1 add '1' to start of array 13 | -------------------------------------------------------------------------------- /Maths and Geometry/Minimum operations to make GCD of array a multiple of k.py: -------------------------------------------------------------------------------- 1 | # logic: if we can make every ele a multiple of "k" then gcd of array will be in multiple of 'k'. 2 | 3 | # for minimum no of operation we can make every ele val= nearest multiple of k. 4 | # this we can get either by removing or adding some element. 5 | 6 | # time: O(n) 7 | def minOperation(arr, k): 8 | ans= 0 9 | for num in arr: 10 | # to_remove= num % k # we can make by subtracting this 11 | # to_add= k - to_remove # we make make by adding this. 12 | # cost= min(to_remove, to_add) 13 | # ans+= cost 14 | ans += min(num % k , k - (num % k)) # in short 15 | return ans 16 | 17 | arr= [4,5,6] 18 | k= 5 19 | 20 | # arr= [4,9,6] 21 | # k= 5 22 | print(minOperation(arr, k)) -------------------------------------------------------------------------------- /Prefix Sum/1413. Minimum Value to Get Positive Step by Step Sum.py: -------------------------------------------------------------------------------- 1 | # Logic: 2 | """ 3 | just find the minimum prefix sum. 4 | Then for ans : if min_sum = 0 return 1 else return abs(min_sum) + 1 5 | """ 6 | 7 | # java 8 | """ 9 | public int minStartValue(int[] nums) { 10 | int sum = 0, min_sum = 0; 11 | for (var n : nums) { 12 | sum += n; 13 | min_sum = Math.min(min_sum, sum); 14 | } 15 | return 1 - min_sum; // will handle both the cases 16 | } 17 | """ -------------------------------------------------------------------------------- /Prefix Sum/2270. Number of Ways to Split Array.py: -------------------------------------------------------------------------------- 1 | # time: O(n), space: O(1) 2 | 3 | class Solution: 4 | def waysToSplitArray(self, nums: List[int]) -> int: 5 | n = len(nums) 6 | total = sum(nums) 7 | curSum, ans = 0, 0 8 | for i in range(n-1): 9 | curSum += nums[i] 10 | ans += curSum >= (total - curSum) 11 | return ans 12 | -------------------------------------------------------------------------------- /Prefix Sum/2711. Difference of Number of Distinct Values on Diagonals.py: -------------------------------------------------------------------------------- 1 | # method 1: Brute force 2 | 3 | # Iterate towards i+1, j+1 for the lower digonal element and put them in a set. 4 | # Similarly iterate i-1, j-1 for the upper left diagonal element and put then in another set. 5 | # Take absolute difference of the both the size of the sets as ans of each cell. 6 | 7 | # time: O((m*n) * min(m, n)) 8 | 9 | class Solution: 10 | def differenceOfDistinctValues(self, grid: List[List[int]]) -> List[List[int]]: 11 | m, n= len(grid), len(grid[0]) 12 | def solve(row, col): 13 | r, c= row -1, col -1 14 | top_left= set() 15 | while r >= 0 and c >= 0: 16 | top_left.add(grid[r][c]) 17 | r-= 1 18 | c-= 1 19 | 20 | bottom_right= set() 21 | r, c= row + 1, col + 1 22 | while r < m and c < n: 23 | bottom_right.add(grid[r][c]) 24 | r+= 1 25 | c+= 1 26 | return abs(len(top_left) - len(bottom_right)) 27 | 28 | ans= [[0 for j in range(n)] for i in range(m)] 29 | 30 | for i in range(m): 31 | for j in range(n): 32 | ans[i][j]= solve(i, j) 33 | return ans 34 | 35 | 36 | # method 2: optimised one 37 | # ty to do in O(m*n) 38 | # links in sheet -------------------------------------------------------------------------------- /Prefix Sum/Cumulative Sum Query.py: -------------------------------------------------------------------------------- 1 | # ans of query (i, j)= prefixSum[j]- preixSum[i-1] 2 | 3 | # time: O(n) 4 | import collections 5 | def RangeSum(arr, query): 6 | n= len(arr) 7 | prefixSum= {} # [index: sumTillIndex] 8 | prefixSum= {-1: 0} # to handle the case (i,j) when i== 0 9 | curSum= 0 10 | for i , num in enumerate(arr): 11 | curSum+= num 12 | prefixSum[i]= curSum 13 | 14 | ans= [] 15 | for i, j in query: 16 | curAns= prefixSum[j] - prefixSum[i-1] 17 | ans.append(curAns) 18 | return ans 19 | 20 | arr= [1, 4, 1] 21 | query= [[1,1], [1,2], [0,2]] 22 | print(RangeSum(arr, query)) 23 | 24 | # Note: Whenever there is something related to 'sum in a range', apply prefix sum. 25 | # Can you array also instead of hashmap of size 'n' or 'n + 1' depending upon Q. 26 | 27 | # Related q: -------------------------------------------------------------------------------- /Queue/1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit.py: -------------------------------------------------------------------------------- 1 | # Method using sortedList in python 2 | 3 | from sortedcontainers import SortedList 4 | class Solution: 5 | def longestSubarray(self, nums: List[int], limit: int) -> int: 6 | n = len(nums) 7 | subArr = SortedList() 8 | i, j = 0, 0 9 | ans = 0 10 | while j < n: 11 | subArr.add(nums[j]) 12 | while subArr[-1] - subArr[0] > limit: 13 | subArr.remove(nums[i]) 14 | i += 1 15 | ans = max(ans, j - i + 1) 16 | j += 1 17 | return ans 18 | 19 | 20 | # Method 2: Using Two heaps i.e minHeap and maxHeap. 21 | # time: O(n* logk) 22 | """ 23 | from sortedcontainers import SortedList 24 | class Solution: 25 | def longestSubarray(self, nums: List[int], limit: int) -> int: 26 | n = len(nums) 27 | subArr = SortedList() 28 | i, j = 0, 0 29 | ans = 0 30 | while j < n: 31 | subArr.add(nums[j]) 32 | while subArr[-1] - subArr[0] > limit: 33 | subArr.remove(nums[i]) 34 | i += 1 35 | ans = max(ans, j - i + 1) 36 | j += 1 37 | return ans 38 | """ 39 | 40 | 41 | # Method 3: Try by Queue later 42 | # Time: O(n) -------------------------------------------------------------------------------- /Recursion_and_String/remove_a_specific_char.py: -------------------------------------------------------------------------------- 1 | 2 | # def remove_char(str1,ch,ans): 3 | # if not str1: # if 'str1' is empty 4 | # return ans 5 | # if str1[0]!=ch: # if deosn't match 6 | # ans+= str1[0] # add to the ans 7 | # return remove_char(str1[1:],ch,ans) # now call the function again from next index 8 | 9 | # method 2: 10 | def remove_char(str,ch): 11 | ans= "" 12 | if not str: 13 | return "" 14 | if str[0]!= ch: # hmko 'ch' nhi mila isliye add kar diye bhai 15 | ans+= str[0] 16 | return ans+ remove_char(str[1:],ch) # baki tmko agar nhi mile to add karke hmko send kar dena 17 | 18 | 19 | str1= input("enter any string: ") 20 | ch= input("enter the char to remove: ") 21 | ans= "" 22 | print(remove_char(str1,ch)) 23 | 24 | -------------------------------------------------------------------------------- /Recursion_and_String/replace_pi_by_value.py: -------------------------------------------------------------------------------- 1 | # check for 1st and 2nd ele of the passing string 2 | # if 1st== p and 2nd == i then call the fn after next two position 3 | # else call after next one position 4 | def ReplacePi(str1): 5 | ans= "" 6 | if len(str1)<2: 7 | return str1 8 | elif str1[0]== 'p' and str1[1]== 'i': 9 | ans+= "3.14" + ReplacePi(str1[2:]) 10 | else: 11 | ans+= str1[0] + ReplacePi(str1[1:]) 12 | return ans 13 | 14 | print(ReplacePi("pippxxppiixipi")) 15 | print(ReplacePi("pippppiiiipi")) 16 | 17 | 18 | # you can use the same logic as 'Q no: 1910'. 19 | 20 | 21 | -------------------------------------------------------------------------------- /Recursion_and_String/tempCodeRunnerFile.py: -------------------------------------------------------------------------------- 1 | # when you include any ele incr the sum also 2 | # time: O(2*n) 3 | # space: O(n) 4 | def subsetSums(arr,sum): 5 | if not arr: 6 | print(sum,end=" ") 7 | return 8 | subsetSums(arr[1:],sum + arr[0]) 9 | subsetSums(arr[1:],sum) 10 | 11 | arr= [5,2,1] 12 | subsetSums(arr,0) # no need to take ans and find the sum 13 | 14 | -------------------------------------------------------------------------------- /Segment Tree/2736. Maximum Sum Queries.py: -------------------------------------------------------------------------------- 1 | # Brute Force (TLE) 2 | class Solution: 3 | def maximumSumQueries(self, nums1: List[int], nums2: List[int], queries: List[List[int]]) -> List[int]: 4 | n , q = len(nums1), len(queries) 5 | ans = [-1] * q 6 | for j, (x, y) in enumerate(queries): 7 | cur_max = -1 8 | for i in range(n): 9 | if nums1[i] >= x and nums2[i] >= y: 10 | cur_max = max(cur_max, nums1[i] + nums2[i]) 11 | ans[j] = cur_max 12 | return ans 13 | -------------------------------------------------------------------------------- /Segment Tree/406. Queue Reconstruction by Height.py: -------------------------------------------------------------------------------- 1 | # Method 1: Sorting 2 | 3 | # Logic: 1)We are fine with passing shorter person than us. 4 | # So let shorter person com enad choose their desire place. 5 | # 2) for this sort based on height and in case of equal height sort according to 'people having more no taller person allowed should come first'. 6 | # because for which 'no of taller person is less allowed' should choose their desire place so they should come later. 7 | 8 | # 3) Now traverse the sorted array and insert people at their own position. 9 | # Just like insertion sort. 10 | 11 | # Time : O(n^2) 12 | 13 | class Solution: 14 | def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]: 15 | # sort the people from tall to short 16 | # insert from tall to short (insert at index = p[1]) 17 | # people.sort(key=lambda p: p[0], reverse = True) # in case p[0] is equal it will first bring smaller p[1] but we want greater p1[1] in case p[0] is smaller 18 | people.sort(key = lambda p : (- p[0], p[1])) 19 | res = [] 20 | for p in people: 21 | res.insert(p[1], p) 22 | return res 23 | 24 | 25 | # later optimise uisng segment tree to O(nlogn). 26 | # solution in sheet -------------------------------------------------------------------------------- /Sliding Window/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ravi-0412/DSA-Program-And-Notes/3961bd7499d9a3e2623207ebfab8a34ba40b50c2/Sliding Window/.DS_Store -------------------------------------------------------------------------------- /Sliding Window/Fixed Size Sliding Window/1052. Grumpy Bookstore Owner.py: -------------------------------------------------------------------------------- 1 | # Logic: 1) if we can include all customers value when owner is not grumpy 2 | # i.e when grumpy[i] == 0 3 | # so first store sum of such value say 'initialSum' 4 | 5 | # 2) Now question reduces to how many maximum '1' we can include to the initial sum. 6 | # for this just we have to find the maximum sum of subarray(customers) having size 'minutes' 7 | # when owner is grumpy i.e grumpy[i] == 1. 8 | 9 | # just same as 'maximum sum of a subarray of size k'. 10 | 11 | class Solution: 12 | def maxSatisfied(self, customers: List[int], grumpy: List[int], minutes: int) -> int: 13 | n = len(customers) 14 | initialSum = 0 15 | for i in range(n): 16 | initialSum += customers[i] if grumpy[i] == 0 else 0 17 | curSum = 0 18 | i, j = 0 , 0 19 | ans = initialSum 20 | while j < n: 21 | if grumpy[j] == 1: 22 | curSum += customers[j] 23 | if j - i + 1 >= minutes: 24 | ans = max(ans, initialSum + curSum) 25 | # remove the value of ith index if 'grumpy[i] == 1' 26 | if grumpy[i] == 1: 27 | curSum -= customers[i] 28 | i += 1 29 | j += 1 30 | return ans 31 | -------------------------------------------------------------------------------- /Sliding Window/Fixed Size Sliding Window/1151. Minimum Swaps to Group All 1's Together.py: -------------------------------------------------------------------------------- 1 | # Logic: 2 | """ 3 | Note: There is no condition on swapping, we can swap with any index with any index. 4 | we can check answer for each subarray of size 'k' in given array where k = totalOne. 5 | # answer for this subarray = no of zero 6 | """ 7 | 8 | class Solution: 9 | def minSwaps(self, data: List[int]) -> int: 10 | n = len(data) 11 | oneCount = 0 12 | for num in data: 13 | if num == 1: 14 | oneCount += 1 15 | i, j = 0, 0 16 | zeroCount = 0 17 | ans = oneCount 18 | while j < n: 19 | if data[j] == 0: 20 | zeroCount += 1 21 | # check each subarray of size 'oneCount' starting from index 'i' and ending at index 'j'. 22 | if j - i + 1 >= oneCount: # or 'j + 1 >= oneCount' 23 | ans = min(ans, zeroCount) 24 | if data[i] == 0: 25 | zeroCount -= 1 26 | i += 1 27 | j += 1 28 | return ans -------------------------------------------------------------------------------- /Sliding Window/Fixed Size Sliding Window/2134. Minimum Swaps to Group All 1's Together II.py: -------------------------------------------------------------------------------- 1 | # Logic: 2 | """ 3 | just same as :"1151. Minimum Swaps to Group All 1's Together' except this is circular. 4 | how to handle circular case? 5 | => if subarray starts from last index then it will need 'k-1' element from start to checking. 6 | where k = total_no_one. 7 | for this just append first 'k-1' element into data at last and apply same logic as '"1151. Minimum Swaps to Group All 1's Together'. 8 | """ 9 | 10 | class Solution: 11 | def minSwaps(self, data: List[int]) -> int: 12 | oneCount = 0 13 | for num in data: 14 | if num == 1: 15 | oneCount += 1 16 | for i in range(oneCount - 1): 17 | data.append(data[i]) 18 | n = len(data) 19 | i, j = 0, 0 20 | zeroCount = 0 21 | ans = oneCount 22 | while j < n: 23 | if data[j] == 0: 24 | zeroCount += 1 25 | if j + 1 >= oneCount: 26 | ans = min(ans, zeroCount) 27 | if data[i] == 0: 28 | zeroCount -= 1 29 | i += 1 30 | j += 1 31 | return ans 32 | -------------------------------------------------------------------------------- /Sliding Window/Fixed Size Sliding Window/2461. Maximum Sum of Distinct Subarrays With Length K.py: -------------------------------------------------------------------------------- 1 | # just like "max sum subarray of size k" 2 | # Here when we find any subarray of size= 'k' then first we will check if all elements are distinct or not. 3 | # For this we will store the frequency count in hashmap. 4 | # if len(hashmap)== k in window then update the ans. 5 | 6 | # after reaching any window we will subtract the frequency count of 'nums[i]' also like we used to subtract 'nums[i]' from curSum. 7 | # and if frequency becomes '0' after subtarcting then delete 'nums[i]' from hashmap. 8 | 9 | # time= space= O(n) 10 | 11 | class Solution: 12 | def maximumSubarraySum(self, nums: List[int], k: int) -> int: 13 | frequency= collections.defaultdict(int) 14 | i, j= 0, 0 15 | curSum= 0 16 | maxSum= 0 # all number is +ve only 17 | while j < len(nums): 18 | n= nums[j] 19 | curSum+= n 20 | frequency[n]= 1+ frequency.get(n, 0) 21 | if j - i + 1 >= k: 22 | if len(frequency)== k : 23 | maxSum= max(maxSum, curSum) 24 | 25 | curSum-= nums[i] 26 | frequency[nums[i]]-= 1 27 | if frequency[nums[i]]== 0: 28 | del frequency[nums[i]] 29 | 30 | i+= 1 31 | j+= 1 32 | return maxSum 33 | 34 | -------------------------------------------------------------------------------- /Sliding Window/Fixed Size Sliding Window/567. Permutation in String.py: -------------------------------------------------------------------------------- 1 | # fully 100% same as "438. Find All Anagrams in a String" only 2 | # here if you find any anargam then return true else return False instead of adding them into ans 3 | -------------------------------------------------------------------------------- /Sliding Window/Fixed Size Sliding Window/Max Sum Subarray of size K.py: -------------------------------------------------------------------------------- 1 | # 1st method by brute force: O(n*k) 2 | 3 | # 2nd method: By Sliding Window 4 | # time: O(n) 5 | 6 | # little concise way of writing the above code 7 | # once you reach that window size, just keep updating your ans and remove the ele at 'i'th index from sum and incr 'i' 8 | def maximumSumSubarray (self,K,Arr,N): 9 | i,j,sum1,max_sum= 0,0,0,-9999999999 10 | while j=K: # or j -i + 1 >= k: 13 | # Now we have reached the size 'k' so we can start updating our ans. 14 | max_sum= max(sum1, max_sum) 15 | sum1-= Arr[i] 16 | i+= 1 17 | j+= 1 18 | return max_sum 19 | 20 | 21 | # Note vvvvi: At any instant curSum= sum of ele till index 'j' - sum of ele before index 'i'. 22 | # it just represents sum of ele from index 'i' to index 'j'. i.e prefixSum[j] - prefixSum[i-1] 23 | 24 | -------------------------------------------------------------------------------- /Sliding Window/Variable Size Sliding Window/1208. Get Equal Substrings Within Budget.py: -------------------------------------------------------------------------------- 1 | # Time: O(n), space : O(1) 2 | 3 | class Solution: 4 | def equalSubstring(self, s: str, t: str, maxCost: int) -> int: 5 | n = len(s) 6 | i , j = 0, 0 7 | ans = 0 8 | curCost = 0 9 | while j < n: 10 | curCost += abs(ord(s[j]) - ord(t[j])) 11 | # reomev from left till curCost > maxCost 12 | while curCost > maxCost: 13 | curCost -= abs(ord(s[i]) - ord(t[i])) 14 | i += 1 15 | ans = max(ans, j - i + 1) 16 | j += 1 17 | return ans 18 | 19 | 20 | # Java 21 | """ 22 | class Solution { 23 | public int equalSubstring(String s, String t, int maxCost) { 24 | int n = s.length() ; 25 | int i = 0 , j = 0; 26 | int curCost = 0 ; 27 | int ans = 0 ; 28 | while(j < n) { 29 | curCost += Math.abs((int)s.charAt(j) - (int)t.charAt(j)) ; 30 | while(curCost > maxCost){ 31 | curCost -= Math.abs((int)s.charAt(i) - (int)t.charAt(i)) ; 32 | i += 1 ; 33 | } 34 | ans = Math.max(ans, j - i + 1) ; 35 | j += 1 ; 36 | } 37 | return ans; 38 | } 39 | } 40 | """ -------------------------------------------------------------------------------- /Sliding Window/Variable Size Sliding Window/1248. Count Number of Nice Subarrays.py: -------------------------------------------------------------------------------- 1 | # Logic: if we replace every even number -> 0 and odd number -> 1 then 2 | # our q reduces to : Find no of subarray having sum = k i.e "560. Subarray Sum Equals K". 3 | 4 | # Note: if we were asked to find the no of subarray having count of even number is 'k' then we 5 | # will replace even number by '1' because here count of even number matters. 6 | 7 | # Note vvi: Whenever you are asked to find answer based on odd & even 8 | # try to convert them into '0/'1' depending upon question like whether to replace odd by '1' or even by '1'. 9 | # And think of any logic. 10 | 11 | # Time : O(n), 12 | # space : O(1) 13 | 14 | # No need to change array , just add '1' when you see odd else '0' to curSum. 15 | 16 | class Solution: 17 | def numberOfSubarrays(self, nums: List[int], k: int) -> int: 18 | ans,curr_sum= 0,0 19 | prefix_sum= {0:1} # [sum: count_of_sum] 20 | for n in nums: 21 | curr_sum += 1 if n % 2 == 1 else 0 22 | diff = curr_sum - k 23 | ans += prefix_sum.get(diff, 0) 24 | prefix_sum[curr_sum] = 1+ prefix_sum.get(curr_sum, 0) 25 | return ans 26 | 27 | 28 | # Method 2: 29 | # Time: O(n), space : O(1) 30 | 31 | # Just exact same logic of q: "930. Binary Subarrays With Sum" 32 | -------------------------------------------------------------------------------- /Sliding Window/Variable Size Sliding Window/1658. Minimum Operations to Reduce X to Zero.py: -------------------------------------------------------------------------------- 1 | # Observation: After removing combination of ele from start and end with sum = 'x' (if exist), 2 | # We will be left with an subarray whose sum will be 'sum(nums) - x'. 3 | 4 | # So now our q reduces to : "Find the length of longest subarray whose sum = "sum(nums) - x" 5 | # for minimum no of operations say 'maxLen'. 6 | 7 | # Then ans = n - maxLen if subarray exist else -1. 8 | 9 | # Note: constarint of ele is +ve. So no need to use map. 10 | 11 | # Time = O(n) , space = O(1) 12 | 13 | class Solution: 14 | def minOperations(self, nums: List[int], x: int) -> int: 15 | n = len(nums) 16 | maxLen = -1 # any min value that can't be ans 17 | i, j = 0, 0 18 | curSum = 0 19 | target = sum(nums) - x 20 | while j < n: 21 | curSum += nums[j] 22 | while i <= j and curSum > target: 23 | curSum -= nums[i] 24 | i += 1 25 | if curSum == target: 26 | maxLen = max(maxLen , j - i + 1) 27 | j += 1 28 | return -1 if maxLen == -1 else n - maxLen 29 | -------------------------------------------------------------------------------- /Sliding Window/Variable Size Sliding Window/2302. Count Subarrays With Score Less Than K.py: -------------------------------------------------------------------------------- 1 | # Just exactly same logic as "713. Subarray Product Less Than K". 2 | # After adding each ele, just find the length of valid subarray then that add to 'count'. 3 | 4 | # How to take care of CurScore? 5 | # Ans: After adding any ele, find the curScore= (curSum)*(length of subarray) 6 | # when you will move 'i' then update the curSCore also after updating curSum and 'i'. 7 | 8 | # time: O(n) 9 | class Solution: 10 | def countSubarrays(self, nums: List[int], k: int) -> int: 11 | n= len(nums) 12 | i, j= 0, 0 13 | curSum= 0 14 | count= 0 15 | while j < n: 16 | curSum+= nums[j] 17 | curScore= curSum * (j- i + 1) # current score 18 | # i should go till 'j' because if there is any ele >='k' itself then we will have to remove all. 19 | while i<= j and curScore >= k: 20 | curSum-= nums[i] 21 | i+= 1 22 | curScore= curSum * (j- i + 1) # update the CurScore 23 | count+= j - i + 1 24 | j+= 1 25 | return count 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Sliding Window/Variable Size Sliding Window/2743. Count Substrings Without Repeating Character.py: -------------------------------------------------------------------------------- 1 | # Just same as '3. Longest Substring Without Repeating Characters'. 2 | # Here we only have to count the number. 3 | 4 | # After each character check for valid substring then no of new substring formed 5 | # will be equal to the length of substring. 6 | # Because for that valid substring all combination will be part of answer. 7 | 8 | from collections import defaultdict 9 | def countSub(s): 10 | n = len(s) 11 | count = defaultdict(int) 12 | ans = 0 13 | i, j = 0, 0 14 | while j < n: 15 | count[s[j]] += 1 16 | while j- i + 1 > len(count): 17 | count[s[i]] -= 1 18 | if count[s[i]] == 0: 19 | del count[s[i]] 20 | i += 1 21 | ans += j - i + 1 22 | j += 1 23 | return ans 24 | 25 | # s = "gffg" 26 | s = "gfg" 27 | print("no of substring is : ", countSub(s)) 28 | 29 | 30 | -------------------------------------------------------------------------------- /Sliding Window/Variable Size Sliding Window/2949. Count Beautiful Substrings II.py: -------------------------------------------------------------------------------- 1 | # Logic of "2949. Count Beautiful Substrings I" won't work. 2 | # Have to understand the solution properly(in sheet). 3 | -------------------------------------------------------------------------------- /Sliding Window/Variable Size Sliding Window/2958. Length of Longest Subarray With at Most K Frequency.py: -------------------------------------------------------------------------------- 1 | # Just similar logic to : "713. Subarray Product Less Than K". 2 | # Logic: Traverse the array and keep updating the frequency of cur number. 3 | # After updating the frequency slide the window from left till frequency[cur_num] > k. 4 | # Then update the ans. 5 | # Time : O(n) 6 | 7 | class Solution: 8 | def maxSubarrayLength(self, nums: List[int], k: int) -> int: 9 | n = len(nums) 10 | i, j = 0, 0 11 | ans = 0 12 | freq = collections.defaultdict(int) 13 | while j < n: 14 | freq[nums[j]] += 1 15 | while i < j and freq[nums[j]] > k: 16 | freq[nums[i]] -= 1 17 | i += 1 18 | ans= max(ans, j - i + 1) 19 | j += 1 20 | return ans -------------------------------------------------------------------------------- /Sliding Window/Variable Size Sliding Window/Number of subarrays having sum less than K.py: -------------------------------------------------------------------------------- 1 | # just excatly same code as "713. Subarray Product Less Than K". 2 | # After adding each ele, just find the length of valid subarray then that add to 'count'. 3 | 4 | def NoOfSubarray(arr, k): 5 | n= len(arr) 6 | i, j= 0, 0 7 | curSum= 0 8 | count= 0 9 | while j < n: 10 | curSum+= arr[j] 11 | # i should go till 'j' because if there is any ele greater than 'k' itself then we will have to remove all. 12 | while i<= j and curSum >= k: 13 | curSum-= arr[i] 14 | i+= 1 15 | count+= j - i + 1 16 | j+= 1 17 | return count 18 | 19 | 20 | # arr= [1, 11, 2, 3, 15] 21 | arr= [2, 5, 6] 22 | k = 10 23 | print(NoOfSubarray(arr, k)) 24 | 25 | -------------------------------------------------------------------------------- /Sliding Window/Variable Size Sliding Window/Smallest subarray with sum greater than x.py: -------------------------------------------------------------------------------- 1 | # Just try to reduce the subarray size after finding a valid answer. 2 | # same as :"Smallest subarray with sum greater than x" 3 | 4 | class Solution: 5 | def smallestSubWithSum(self, x, arr): 6 | n = len(arr) 7 | ans = float('inf') 8 | curSum = 0 9 | i , j = 0, 0 10 | while j < n: 11 | curSum += arr[j] 12 | while curSum > x: 13 | ans = min(ans, j - i + 1) 14 | curSum -= arr[i] 15 | i += 1 16 | j += 1 17 | return ans if ans != float('inf') else 0 -------------------------------------------------------------------------------- /Sliding Window/Variable Size Sliding Window/longest substring with k unique characters.py: -------------------------------------------------------------------------------- 1 | # for max ans, longest ke liye jitna se jitna char repeat karne chahiye with 2 | 3 | # Note: To check the number of unique char at any point of time we will use hashmap. 4 | # len(ahshmap): will tell no of unique char at any point of time. 5 | 6 | # time: O(n)= space 7 | 8 | # shorter way and concise way. 9 | # Note: Try to solve every variable sliding window problem like this only. 10 | # After seeing every char check for valid substring and update ans. 11 | 12 | class Solution: 13 | def longestKSubstr(self, s, k): 14 | freq= {} 15 | i, j= 0, 0 16 | ans= -1 17 | longest= "" # will give any such string 18 | while j < len(s): 19 | freq[s[j]]= 1 + freq.get(s[j], 0) 20 | while len(freq) > k: 21 | freq[s[i]]-= 1 22 | if freq[s[i]]== 0: 23 | del freq[s[i]] 24 | i+= 1 25 | if len(freq)== k and j - i + 1 > ans: 26 | longest= s[i: j +1] 27 | ans= max(ans, j- i+ 1) 28 | j+= 1 29 | return ans 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Sorting/3075. Maximize Happiness of Selected Children.py: -------------------------------------------------------------------------------- 1 | # lOGIC: We have to select maximum number only . for this sort in reverse order. 2 | # But if we are selecting any number as ith number then it's value = nums[i] - i 3 | 4 | class Solution: 5 | def maximumHappinessSum(self, happiness: List[int], k: int) -> int: 6 | happiness.sort(reverse = True) 7 | ans = 0 8 | for i in range(k): 9 | ans += max(0, happiness[i] - i) 10 | return ans 11 | -------------------------------------------------------------------------------- /Sorting/3111. Minimum Rectangles to Cover Points.py: -------------------------------------------------------------------------------- 1 | # Logic: We need to take care only 'x' coordinates. 2 | # So just sort according to x coordinate and when difference of 'x' coordinates is greater than 'w' 3 | # then increase the count and initialize starting 'x' coordinate = x-coordinate of cur point. 4 | 5 | class Solution: 6 | def minRectanglesToCoverPoints(self, points: List[List[int]], w: int) -> int: 7 | points.sort() 8 | mn = points[0][0] 9 | cnt = 1 10 | for i in range(1, len(points)): 11 | if points[i][0] - mn > w: 12 | cnt += 1 13 | mn = points[i][0] 14 | return cnt 15 | -------------------------------------------------------------------------------- /Sorting/826. Most Profit Assigning Work.py: -------------------------------------------------------------------------------- 1 | # Just zip(difficulty, profit) for maintaining the index and sort. 2 | # Now sort worker and check for each worker we can assign the maximum difficulty. 3 | # Note: Worker having more value of worker[i] will surely can get >= difficulty than working having less 'worker[i]'. 4 | 5 | # So we can use two pointer to find the maximum difficulty we can assign to each worker. 6 | # sorted worker only to use this logic i.e two pointer. 7 | 8 | # Time: O(n*logn) 9 | 10 | class Solution: 11 | def maxProfitAssignment(self, difficulty: List[int], profit: List[int], worker: List[int]) -> int: 12 | jobs = sorted(zip(difficulty, profit)) 13 | worker.sort() 14 | ans = 0 15 | best = 0 16 | i , j = 0, 0 17 | while i < len(worker): 18 | while j < len(jobs) and worker[i] >= jobs[j][0]: 19 | best = max(best, jobs[j][1]) 20 | j += 1 21 | ans += best 22 | i += 1 23 | return ans 24 | -------------------------------------------------------------------------------- /Sorting/945. Minimum Increment to Make Array Unique.py: -------------------------------------------------------------------------------- 1 | # Logic: 2 | """ 3 | Answer will be equal to make all element in strictly increasing order. 4 | for this sort the array & try to make next element = prev + 1. 5 | we need moves = (pre - nums[i]) + 1 to make current(nums[i]) one greater than prev. 6 | """ 7 | # 8 | 9 | # Time: O(n*logn) 10 | 11 | class Solution: 12 | def minIncrementForUnique(self, nums: List[int]) -> int: 13 | nums.sort() 14 | pre = nums[0] 15 | ans = 0 16 | for i in range(1, len(nums)): 17 | moves = 0 18 | if nums[i] <= pre: 19 | moves = (pre - nums[i]) + 1 20 | ans += moves 21 | pre = nums[i] + moves 22 | return ans 23 | 24 | # Note: Later try by other approaches in sheet. -------------------------------------------------------------------------------- /Sorting/findkthSmallestVulnerability.py: -------------------------------------------------------------------------------- 1 | # You can solve this in O(N log K) time where N is size of array. 2 | 3 | # First notice that if we solve problem for min, the solution for max is same, just multiply original array elements by -1. 4 | 5 | # So to solve this we need a data structure that supports: additions, deletions, 6 | # finding k-th item in collection, then we can just loop over all needed intervals 7 | # using sliding window, adding and deleting items when needed. 8 | 9 | # Actually there are lots of structures that can support all those operations in O(log N) time, 10 | # you can use segment tree, min/max heaps, order statistic tree (a type of B-tree) and some others. 11 | 12 | # In python, we use: 'sortedList' and in java we use 'TreeSet'. 13 | 14 | 15 | from sortedcontainers import SortedList 16 | 17 | def findKthVulnerability(k, m, arr): 18 | ans = [] 19 | n = len(arr) 20 | sorted_list = SortedList(arr[:m]) 21 | j = 0 22 | for i in range(m, n - m + 1): 23 | ans.append(sorted_list[k -1]) 24 | sorted_list.remove(arr[j]) 25 | sorted_list.add(arr[i]) 26 | j += 1 27 | return ans 28 | 29 | k , m = 3, 4 30 | vulnerability = [4, 2, 3, 1, 1] 31 | print(findKthVulnerability(k, m, vulnerability)) -------------------------------------------------------------------------------- /Stack/1190. Reverse Substrings Between Each Pair of Parentheses.py: -------------------------------------------------------------------------------- 1 | # Time: O(n^2) 2 | 3 | class Solution: 4 | def reverseParentheses(self, s: str) -> str: 5 | stack = [""] # Addding empty string to get original string only when we append something to it. 6 | # otherwise we won't be able to add the current pop string with stack top because stack will be empty. 7 | for c in s: 8 | if c == '(': 9 | stack.append("") 10 | elif c == ')': 11 | # reverse the string on top of stack 12 | temp = stack.pop()[::-1] 13 | # then add the reversed string to stack top 14 | stack[-1] += temp 15 | else: 16 | stack[-1] += c # add with stack top 17 | return stack.pop() 18 | 19 | # Later do in O(n), link in sheet -------------------------------------------------------------------------------- /Stack/3174. Clear Digits.py: -------------------------------------------------------------------------------- 1 | # Just same method as: "1047. Remove All Adjacent Duplicates In String". 2 | class Solution: 3 | def clearDigits(self, s: str) -> str: 4 | stack = [] 5 | for c in s: 6 | if c.isdigit(): 7 | stack.pop() 8 | else: 9 | stack.append(c) 10 | return "".join(stack) -------------------------------------------------------------------------------- /Stack/496. Next Greater Element I.py: -------------------------------------------------------------------------------- 1 | # Method 1: 2 | # Brute force 3 | # Time: O(m*n) 4 | 5 | # Method 2: 6 | # Time : O(m + n) 7 | 8 | # Logic: We only need to care about actual value if that number is present in nums2. 9 | # So we will store the actual value in ans. 10 | # And to check that number is present in nums2 or not in O(1), 11 | # we need either dictionary or set. 12 | 13 | # Using dictionary we can check also and store ans also and later return also easily. 14 | 15 | # Here dictionary will store ans for numbers that have answer. 16 | # Note: For number that is present in nums2 but has no answer then at last 17 | # while returning we will automatically get '-1'. 18 | 19 | 20 | class Solution: 21 | def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]: 22 | st, d = [], {} 23 | for n in nums2: 24 | # 'n' will ans for all ele of stack till stack top < n. 25 | while st and st[-1] < n: 26 | d[st.pop()] = n # pop as we have found the greater ele for num on top of the stack 27 | st.append(n) 28 | return [d.get(x, -1) for x in nums1] # if there is value of 'x' then 29 | # return that otherwise return '-1' 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Stack/739. Daily Temperatures.py: -------------------------------------------------------------------------------- 1 | # Just we have to find the 'Next greater right' 2 | 3 | class Solution: 4 | def dailyTemperatures(self, temperatures: List[int]) -> List[int]: 5 | n, stack, ans= len(temperatures), [], [] 6 | for i in range(n-1,-1,-1): 7 | while stack and temperatures[stack[-1]]<= temperatures[i]: 8 | stack.pop() 9 | if stack== []: 10 | ans.append(0) 11 | else: # means stack top is greater than arr[i] 12 | ans.append(stack[-1] -i) 13 | stack.append(i) 14 | return ans[::-1] 15 | -------------------------------------------------------------------------------- /String/2716. Minimize String Length.py: -------------------------------------------------------------------------------- 1 | # logic: All duplicate will get discarded, only distinct char will left. 2 | # time: O(n) 3 | 4 | class Solution: 5 | def minimizedStringLength(self, s: str) -> int: 6 | return len(set(s)) 7 | 8 | # java 9 | """ 10 | class Solution { 11 | public int minimizedStringLength(String s) { 12 | return new HashSet() {{ 13 | for (char c : s.toCharArray()) add(c); 14 | }}.size(); 15 | } 16 | } 17 | """ 18 | 19 | """ 20 | class Solution { 21 | public int minimizedStringLength(String s) { 22 | HashSet uniqueChars = new HashSet<>(); 23 | for (char c : s.toCharArray()) { 24 | uniqueChars.add(c); 25 | } 26 | return uniqueChars.size(); 27 | } 28 | 29 | """ 30 | 31 | # C++ Code 32 | """ 33 | #include 34 | #include 35 | 36 | using namespace std; 37 | 38 | class Solution { 39 | public: 40 | int minimizedStringLength(string s) { 41 | return unordered_set(s.begin(), s.end()).size(); 42 | } 43 | }; 44 | """ -------------------------------------------------------------------------------- /String/2744. Find Maximum Number of String Pairs.py: -------------------------------------------------------------------------------- 1 | # Time : O(2*n) 2 | 3 | class Solution: 4 | def maximumNumberOfStringPairs(self, words: List[str]) -> int: 5 | visited= set() # To check the reverse pair 6 | count = 0 7 | for w in words: 8 | if w[::-1] in visited: 9 | count += 1 10 | visited.add(w) 11 | return count 12 | -------------------------------------------------------------------------------- /String/2745. Construct the Longest New String.py: -------------------------------------------------------------------------------- 1 | # logic in notes 2 | # page: 96 3 | 4 | # 'z' and come after 'z' so need to worry about 'z'. 5 | # All 'z' an be utilised. 6 | 7 | # for 'x' and 'y', they will come in pair eithex 'xy' or 'yx' of x > y and x < y respectively. 8 | 9 | # 1) if x > y: 10 | # then we can form 'xy' pair i.e xyxyxy... 11 | # One more 'x' can come as last of pair so no of 'xy' pair = min(x, y) 12 | # and one more occurence of 'x' at last. 13 | 14 | # All 'z' can come at 1st together. 15 | # So final string = zzzz....xyxyxy....x 16 | 17 | # 2) if y > x: 18 | # then we can form 'yx' pair i.e yxyxyx..... 19 | # One more 'y' can come as last of pair so no of 'yx' pair = min(x, y) 20 | # and one more occurence of 'y' at last. 21 | 22 | # All 'z' can come at last together. 23 | # So final string = yxyx....yzzzz..... 24 | 25 | # 3) if x == y 26 | # then any of '1' or '2' will be valid but one extra 'x' or 'y' won't come. 27 | 28 | class Solution: 29 | def longestString(self, x: int, y: int, z: int) -> int: 30 | if x > y: 31 | return (y*2+ 1 + z) *2 32 | if y > x: 33 | return (x*2 + 1 + z)*2 34 | if x == y: 35 | return (x + y+z)*2 36 | -------------------------------------------------------------------------------- /String/3106. Lexicographically Smallest String After Operations With Constraint.py: -------------------------------------------------------------------------------- 1 | # Just try to replace each char with smallest possible char from 'a' to 'z'. 2 | 3 | class Solution: 4 | def getSmallestString(self, s: str, k: int) -> str: 5 | ans = "" 6 | n = len(s) 7 | for c1 in s: 8 | replaced = False 9 | # check if we can replace c1 with smallest lexographically 10 | # we can only replace if we have sufficient available 'k'/ 11 | for i in range(97, 123): 12 | # only replace if chr(i) is smaller and there is suficient 'k' either linearly or circular 13 | if i < ord(c1) and (ord(c1) - i <= k or 26 - (ord(c1) - i) <= k) : 14 | ans += chr(i) 15 | k -= min(ord(c1) - i , 26 - (ord(c1) - i)) 16 | replaced = True 17 | break 18 | if replaced == False: 19 | # If we can't replace then add the same char 20 | ans += c1 21 | return ans -------------------------------------------------------------------------------- /String/3114. Latest Time You Can Obtain After Replacing Characters.py: -------------------------------------------------------------------------------- 1 | # Logic: Just think how can you make maximum 2 | 3 | class Solution: 4 | def findLatestTime(self, s: str) -> str: 5 | first , second, third, fourth = s[0] , s[1], s[3], s[4] 6 | # Handling the hour case 7 | if first == "?" and second == "?": 8 | first = second = "1" 9 | elif second == "?": 10 | if first == "0": 11 | second = "9" 12 | else: 13 | second = "1" 14 | elif first == "?": 15 | if second == "1" or second == "0": 16 | first = "1" 17 | else: 18 | first = "0" 19 | 20 | # Handling minute case 21 | if third == "?" and fourth == "?": 22 | third = "5" 23 | fourth = "9" 24 | elif fourth == "?": 25 | fourth = "9" 26 | elif third == "?": 27 | third = "5" 28 | return first + second + ":" + third + fourth 29 | 30 | # Shortcut of above 31 | class Solution: 32 | def findLatestTime(self, s: str) -> str: 33 | s = list(s) 34 | if s[0] == '?': 35 | s[0] = '1' if s[1] == '?' or s[1] <= '1' else '0' 36 | if s[1] == '?': 37 | s[1] = '1' if s[0] == '1' else '9' 38 | if s[3] == '?': s[3] = '5' 39 | if s[4] == '?': s[4] = '9' 40 | return ''.join(s) -------------------------------------------------------------------------------- /String/38. Count and Say.py: -------------------------------------------------------------------------------- 1 | # just did seeing the pattern. 2 | 3 | # for visualisation: 4 | # n = 1: return 1 is the base case 5 | # n = 2: return count of last entry i.e. 1 1 6 | # n = 3: return count of last entry i.e. two 1's so 21 7 | # n=4: we have one 2 and one 1 so 1211 8 | # n=5: , we have one 1 and one 2 and two 1's so -> 111221 9 | # n=6: we have three 1's, two 2's and one 1 so -> 312211 10 | # n = 7: we have one 3, one 1, two 2's and two 1's -> 13112221 11 | # ... 12 | # n = i: return counts in front of the number for entry of i-1 case 13 | 14 | class Solution: 15 | def countAndSay(self, n: int) -> str: 16 | pre= "1" 17 | for i in range(2, n+1): 18 | cur= "" 19 | j= 0 # will traverse each char in pre string to find the ans for next sequence 20 | while j < len(pre): 21 | ch= pre[j] 22 | count= 1 # default it will be '1' for each char. 23 | k= j+1 24 | while k < len(pre) and pre[k]== ch: 25 | count+= 1 26 | k+= 1 27 | cur+= str(count) + ch 28 | j= k 29 | 30 | pre= cur 31 | return pre -------------------------------------------------------------------------------- /String/Good Binary Strings.py: -------------------------------------------------------------------------------- 1 | # This Q is only observation in detail. 2 | # solution in Notes. page no: 94 3 | 4 | # LOGIC: Target the index directly and observe. 5 | # time: O(1) 6 | def goodBinaryString(s): 7 | n= len(s) 8 | if s[0]!= s[n-1]: 9 | return 2 10 | return n-2 11 | 12 | s= "10100" 13 | # s= "11111" 14 | 15 | print(goodBinaryString(s)) 16 | 17 | 18 | # for codechef 19 | tc = int(input()) # no of test cases 20 | for t in range(tc) : 21 | s = input() # each test case input 22 | n= len(s) 23 | if s[0]!= s[-1]: 24 | print(2) 25 | else: 26 | print(n-2) -------------------------------------------------------------------------------- /Tree/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ravi-0412/DSA-Program-And-Notes/3961bd7499d9a3e2623207ebfab8a34ba40b50c2/Tree/.DS_Store -------------------------------------------------------------------------------- /Tree/Binary Search Tree/1373. Maximum Sum BST in Binary Tree.py: -------------------------------------------------------------------------------- 1 | # Just applied 3rd method of Q: "98. Validate Binary Search Tree" 2 | # Only one difference: just return 'sum' also with minimum and maximum value 3 | 4 | 5 | class Solution: 6 | def maxSumBST(self, root: Optional[TreeNode]) -> int: 7 | self.ans = 0 # Taken '0' instead of 'float('-inf') because in case of all negative values we have to return '0' only(empty bst) 8 | 9 | def check(root): 10 | if not root: 11 | return [float('inf'), float('-inf'), 0] # [minimum, maximum, sum]. For base case return such value which will be valid always 12 | min1, max1, sum1 = check(root.left) 13 | min2, max2, sum2 = check(root.right) 14 | if root.val <= max1 or root.val >= min2: 15 | # not valid so return such values which will be invalid always 16 | return [float('-inf'), float('inf'), 0] 17 | self.ans = max(self.ans, sum1 + sum2 + root.val) 18 | return [min(min1, root.val), max(root.val, max2), sum1 + sum2 + root.val] 19 | 20 | check(root) 21 | return self.ans 22 | -------------------------------------------------------------------------------- /Tree/Binary Search Tree/701. Insert into a Binary Search Tree.py: -------------------------------------------------------------------------------- 1 | # logic: any ele will always get inserted at leaf 2 | # so keep on going using bst property till you reach any leaf 3 | 4 | class Solution: 5 | def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]: 6 | if root== None: 7 | return TreeNode(val) 8 | if root.val> val: 9 | root.left= self.insertIntoBST(root.left,val) 10 | else: 11 | root.right= self.insertIntoBST(root.right,val) 12 | return root -------------------------------------------------------------------------------- /Tree/Binary Search Tree/Ancestors_of_a_node.py: -------------------------------------------------------------------------------- 1 | # logic is same as we search for element 2 | # this is for bst 3 | # but not working 4 | def Ancestors(self, root,target): 5 | if root== None or root.data== target: 6 | return 7 | if target < root.data and root.left!= None: 8 | self.Ancestors(root.left,target) 9 | print(root.left.data, end=" ") 10 | elif target > root.data and root.right!= None: 11 | self.Ancestors(root.right,target) 12 | print(root.right.data, end=" ") 13 | 14 | 15 | # this i don't know why not working , giving error on gfg 16 | # this is for binary tree 17 | def Ancestors(self, root,target): 18 | if root== None: 19 | return False 20 | if root.data== target: 21 | return True 22 | if (self.Ancestors(root.left,target) or self.Ancestors(root.right,target)): 23 | print(root.data,end=" ") 24 | return True 25 | return False -------------------------------------------------------------------------------- /Tree/Binary Search Tree/Kth largest element in BST.py: -------------------------------------------------------------------------------- 1 | # Just same as 'Kth smallest element in BST". 2 | # Logic: Largest node will be the rightmost node. 3 | # so once you find '.right' of any node = None then that will be the largest node as of now. 4 | # And to get the next largest node , move to its left. 5 | 6 | # If it's left is also None then it will do backtrack function call to previous node and calculate in same way. 7 | 8 | class Solution: 9 | def kthLargest(self,root, k): 10 | 11 | def findKthLargest(root): 12 | if root.right: 13 | findKthLargest(root.right) 14 | self.count -= 1 15 | if self.count == 0: 16 | self.ans = root.data 17 | return 18 | # next greater we will get from left side of root 19 | if root.left: 20 | findKthLargest(root.left) 21 | 22 | self.ans = -1 23 | self.count = k 24 | findKthLargest(root) 25 | return self.ans -------------------------------------------------------------------------------- /Tree/Binary Tree/104. Maximum Depth of Binary Tree.py: -------------------------------------------------------------------------------- 1 | # One liner 2 | class Solution: 3 | def maxDepth(self, root: Optional[TreeNode]) -> int: 4 | return 1 + max(self.maxDepth(root.left),self.maxDepth(root.right)) if root else 0 5 | 6 | # method 2: 7 | # more readable and better than above 8 | class Solution: 9 | def maxDepth(self, root: Optional[TreeNode]) -> int: 10 | if root== None: 11 | return 0 12 | return 1 + max(self.maxDepth(root.left),self.maxDepth(root.right)) 13 | 14 | 15 | # Little more expansion 16 | class Solution: 17 | def maxDepth(self, root: Optional[TreeNode]) -> int: 18 | if root== None: 19 | return 0 20 | l= self.maxDepth(root.left) 21 | r= self.maxDepth(root.right) 22 | return 1+ max(l,r) 23 | 24 | 25 | # java 26 | """ 27 | // method 2: 28 | 29 | class Solution { 30 | public int maxDepth(TreeNode root) { 31 | if(root == null) 32 | return 0; 33 | return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)); 34 | } 35 | } 36 | """ -------------------------------------------------------------------------------- /Tree/Binary Tree/111. Minimum Depth of Binary Tree.py: -------------------------------------------------------------------------------- 1 | # Logic: just same logic as "104. maximum depth" 2 | # But here in case of skew tree at any node ,we have to take the skew tree path. 3 | 4 | # If both left and right subtree has node then return min(l, r). 5 | # Otherwise move in the direction that have node. 6 | 7 | # Time : O(n) 8 | 9 | class Solution: 10 | def minDepth(self, root: Optional[TreeNode]) -> int: 11 | if not root: 12 | return 0 13 | l = self.minDepth(root.left) 14 | r = self.minDepth(root.right) 15 | if l and r: 16 | return 1 + min(l, r) 17 | if l: 18 | return 1 + l 19 | return 1 + r 20 | 21 | 22 | 23 | # doing like this will give error. 24 | # Reason: if at node if skew tree starts then, it will return '0' for that node. 25 | # Bt we should move towards skew tree. 26 | 27 | # Rectified this mistake using the condition in above solution. 28 | 29 | class Solution: 30 | def minDepth(self, root: Optional[TreeNode]) -> int: 31 | if not root: 32 | return 0 33 | l = self.minDepth(root.left) 34 | r = self.minDepth(root.right) 35 | return 1 + min(l, r) -------------------------------------------------------------------------------- /Tree/Binary Tree/1325. Delete Leaves With a Given Value.py: -------------------------------------------------------------------------------- 1 | # LOgic: Just go bottom- up , return according to question and modify the child of current root. 2 | # Time: O(n) 3 | 4 | class Solution: 5 | def removeLeafNodes(self, root: Optional[TreeNode], target: int) -> Optional[TreeNode]: 6 | if root == None: 7 | return None 8 | if root.left == None and root.right == None: 9 | # if leaf and val = target 10 | return None if root.val == target else root 11 | l = self.removeLeafNodes(root.left, target) 12 | r = self.removeLeafNodes(root.right, target) 13 | # Now make 'l' and 'r' as left and right child of 'root'. 14 | root.left , root.right = l, r 15 | # Check if we need to delete root also. 16 | # we only need to delete if root becomes leaf and root.val = target 17 | return None if l == None and r == None and root.val == target else root 18 | -------------------------------------------------------------------------------- /Tree/Binary Tree/1609. Even Odd Tree.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isEvenOddTree(self, root: Optional[TreeNode]) -> bool: 3 | level= 0 4 | q= deque([root]) 5 | while q: 6 | pre= None 7 | for i in range(len(q)): 8 | curr= q.popleft() 9 | if level % 2== 0: 10 | if curr.val % 2== 0 or (i>0 and pre >= curr.val): 11 | return False 12 | else: 13 | if curr.val % 2== 1 or ( i>0 and pre <= curr.val): 14 | return False 15 | pre= curr.val 16 | if curr.left: 17 | q.append(curr.left) 18 | if curr.right: 19 | q.append(curr.right) 20 | level+= 1 21 | return True 22 | 23 | -------------------------------------------------------------------------------- /Tree/Binary Tree/2096. Step-By-Step Directions From a Binary Tree Node to Another.py: -------------------------------------------------------------------------------- 1 | # Logic: 1) Make adjacency list and add also 'L' /'R'/'U' to 2 | # identify which path we have taken. 3 | 4 | # 2) Apply bfs as usual and taking path parameter also with nodeValue. 5 | class Solution: 6 | def getDirections(self, root: Optional[TreeNode], startValue: int, destValue: int) -> str: 7 | adj = collections.defaultdict(list) 8 | 9 | def preorder(root): 10 | if root.left: 11 | adj[root.val].append([root.left.val, "L"]) 12 | adj[root.left.val].append([root.val, "U"]) 13 | preorder(root.left) 14 | if root.right: 15 | adj[root.val].append([root.right.val, "R"]) 16 | adj[root.right.val].append([root.val, "U"]) 17 | preorder(root.right) 18 | 19 | preorder(root) 20 | 21 | dq = deque([(startValue, "")]) 22 | visited = set() 23 | visited.add(startValue) 24 | while dq: 25 | node, path = dq.popleft() 26 | if node == destValue: 27 | return path 28 | for nei, dir in adj[node]: 29 | if nei not in visited: 30 | dq.append((nei, path + dir)) 31 | visited.add(nei) 32 | 33 | # later try by 'LCA' also -------------------------------------------------------------------------------- /Tree/Binary Tree/226. Invert Binary Tree.py: -------------------------------------------------------------------------------- 1 | # just write what problem is saying us to do. 2 | 3 | class Solution: 4 | def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: 5 | if root == None: 6 | return None 7 | root.left , root.right = root.right, root.left 8 | self.invertTree(root.left) 9 | self.invertTree(root.right) 10 | return root 11 | 12 | # Java 13 | """ 14 | class Solution { 15 | public TreeNode invertTree(TreeNode root) { 16 | if (root == null) { 17 | return null; 18 | } 19 | 20 | // Swap the left and right child 21 | TreeNode temp = root.left; 22 | root.left = root.right; 23 | root.right = temp; 24 | 25 | // Recursively invert left and right subtrees 26 | invertTree(root.left); 27 | invertTree(root.right); 28 | 29 | return root; 30 | } 31 | } 32 | """ 33 | -------------------------------------------------------------------------------- /Tree/Binary Tree/2331. Evaluate Boolean Binary Tree.py: -------------------------------------------------------------------------------- 1 | # Logic: Just traverse bottom-up and evaluate for each node. 2 | # time: O(n) 3 | class Solution: 4 | def evaluateTree(self, root: Optional[TreeNode]) -> bool: 5 | if root.left == None and root.right == None: 6 | # if leaf 7 | return True if root.val == 1 else False 8 | l = self.evaluateTree(root.left) 9 | r = self.evaluateTree(root.right) 10 | # if root val = 2 then take 'OR' else take 'AND' and return 11 | return (l | r) if root.val == 2 else (l & r) -------------------------------------------------------------------------------- /Tree/Binary Tree/617. Merge Two Binary Trees.py: -------------------------------------------------------------------------------- 1 | # time: O(n) 2 | 3 | # logic: if any of the tree is None simply return the not_None tree. 4 | # else make a node with node.val= sum of cur node value of both the tree and call for left and right part. 5 | 6 | # same as we construct BST and other tree. when told to construct any tree think like this way first. 7 | class Solution: 8 | def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]: 9 | if root1== None or root2== None: 10 | return root1 or root2 11 | # means both are not None. 12 | node= TreeNode(root1.val + root2.val) 13 | node.left= self.mergeTrees(root1.left, root2.left) 14 | node.right= self.mergeTrees(root1.right, root2.right) 15 | return node 16 | -------------------------------------------------------------------------------- /Tree/Binary Tree/662. Maximum Width of Binary Tree.py: -------------------------------------------------------------------------------- 1 | # my mistaek: i didn't get the q properly 2 | 3 | """ 4 | logic: just you have to find the max width at each level. 5 | And if we number all the nodes using array notation then, 6 | width at that level= num(right most node i.e last node at that level)- num(leftmost node i.e first node) + 1 7 | 8 | for this we can use Level Order Traversal. easiest one 9 | """ 10 | 11 | class Solution: 12 | def widthOfBinaryTree(self, root: Optional[TreeNode]) -> int: 13 | q= collections.deque([(root, 1)]) 14 | ans= 1 # minimum can be this ans. 15 | while q: 16 | n= len(q) 17 | ans= max(ans, q[n -1][1] - q[0][1] + 1) # width at each level= num(right most node i.e last node at that level)- num(leftmost node i.e first node) + 1 18 | for i in range(n): # we have to print level by level in a list 19 | curr, ind= q.popleft() 20 | if curr.left: 21 | q.append((curr.left, 2*ind)) # left node will at 2*i in '1' based indexing 22 | if curr.right: 23 | q.append((curr.right, 2*ind + 1)) # right node will at 2*i + 1 in '1' based indexing 24 | return ans 25 | -------------------------------------------------------------------------------- /Tree/Binary Tree/814. Binary Tree Pruning.py: -------------------------------------------------------------------------------- 1 | # logic: just go Bottom up and if you have find any '1' either from its child or cur node itslef then 2 | # we will include that node in ans. 3 | 4 | # else will return None (remove subtree starting from that node). 5 | 6 | # time: O(n) 7 | 8 | class Solution: 9 | def pruneTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: 10 | if not root: 11 | return None 12 | root.left= self.pruneTree(root.left) 13 | root.right= self.pruneTree(root.right) 14 | if root.left== None and root.right== None and root.val== 0: 15 | return None 16 | return root 17 | -------------------------------------------------------------------------------- /Tree/Binary Tree/971. Flip Binary Tree To Match Preorder Traversal.py: -------------------------------------------------------------------------------- 1 | # time: O(n) 2 | 3 | class Solution: 4 | def flipMatchVoyage(self, root: Optional[TreeNode], voyage: List[int]) -> List[int]: 5 | self.ans, self.ind= [], 0 6 | # ind: will tell which value to chekc from voyage for current root. 7 | 8 | def dfs(root): 9 | if not root or self.ind >= len(voyage): 10 | return 11 | if root.val != voyage[self.ind] : 12 | # means it is not possible to get the desired order from here. 13 | # root ka value equal to hona hi chahiye nhi to possible nhi hoga. 14 | self.ans.append(None) 15 | return 16 | dr= 1 17 | self.ind+= 1 18 | if root.left and root.left.val != voyage[self.ind]: 19 | # means we have to swap left and right child. 20 | self.ans.append(root.val) 21 | dr= -1 # change the direction also because after swap we will have to move right to left. 22 | 23 | for child in [root.left, root.right][::dr] : 24 | dfs(child) 25 | 26 | dfs(root) 27 | return [-1] if None in self.ans else self.ans 28 | -------------------------------------------------------------------------------- /Tree/Binary Tree/Burn the binary tree starting from the target node.py: -------------------------------------------------------------------------------- 1 | # Just same as: "863. All Nodes Distance K in Binary Tree". 2 | # Just print nodes at each level one by one. -------------------------------------------------------------------------------- /Tree/Binary Tree/Burning Tree.py: -------------------------------------------------------------------------------- 1 | # just same as rotten oranges 2 | # first convert the tree into graph and then apply multisource bfs 3 | -------------------------------------------------------------------------------- /Tree/Binary Tree/Leaves_total_depth.py: -------------------------------------------------------------------------------- 1 | # 1) Total nodes 2 | 3 | def TotalNodes(self, root): 4 | if root== None: 5 | return 0 6 | return 1+ self.TotalNodes(root.left) + self.TotalNodes(root.right) 7 | 8 | # Later try by iterative way 9 | 10 | # 2) Leaf Nodes 11 | def LeafNode(self, root): 12 | if root== None: 13 | return 0 14 | if root.left== None and root.right== None: 15 | return 1 16 | return self.LeafNode(root.left) + self.LeafNode(root.right) 17 | # Later try by iterative way 18 | 19 | # 3) Depth / Height 20 | def Depth(self,root): 21 | if root== None: 22 | return 0 23 | return 1 + max(self.Depth(root.left), self.Depth(root.right)) 24 | 25 | # max depth that submitted on leetcode 26 | class Solution: 27 | def maxDepth(self, root: Optional[TreeNode]) -> int: 28 | if root== None: 29 | return 0 30 | l= self.maxDepth(root.left) 31 | r= self.maxDepth(root.right) 32 | return 1+ max(l,r) 33 | 34 | -------------------------------------------------------------------------------- /Tree/Binary Tree/Left View of a Binary Tree.py: -------------------------------------------------------------------------------- 1 | # just same as "Right view" 2 | # here instead of printing the last node at each level 3 | # print the 1st node at each level that's it i.e first node from left at each level 4 | 5 | # can do by all the methods we did in "Right view" 6 | 7 | 8 | -------------------------------------------------------------------------------- /Tree/Binary Tree/path from root to a given node in a binary tree.py: -------------------------------------------------------------------------------- 1 | # same Q: Search a given node in binary tree 2 | # or "Path sum 2" 3 | 4 | # these all methods checked on leetcode giving correct output. 5 | # here you have to stop once you find the node 6 | # so for this if we get True we are simply just returning that. 7 | 8 | # method 1: 9 | def Path(root,key): 10 | ans= [] 11 | if helper(root,key,ans)== False: 12 | print("not present") 13 | return ans 14 | 15 | def helper(self,root,key,ans): 16 | if root== None: 17 | return False 18 | ans.append(root.val) # simply add the node you visit 19 | if root.val== key: 20 | return True 21 | if helper(root.left,key,ans) or helper(root.right,key,ans): # means key has path from the given root 22 | return True 23 | # if key has not path from the curr root(neither left nor right return True) then pop root from the ans and return False 24 | ans.pop() 25 | return False 26 | 27 | # No need to take 'ans' in function call, can take as global variable. 28 | 29 | # Q: for printing the depth of a node from a root 30 | 31 | # just keep 'depth' also as parameter and once you find the node return the depth. 32 | -------------------------------------------------------------------------------- /Two Pointer/151. Reverse Words in a String.py: -------------------------------------------------------------------------------- 1 | # Time = O(n) 2 | # Space = O(n), excluding answer one. 3 | 4 | class Solution: 5 | def reverseWords(self, s: str) -> str: 6 | # return " ".join(list(s.strip().split(" "))[::-1]) 7 | # return " ".join(list(s.strip().split())[::-1]) 8 | # return " ".join(s.strip().split()[::-1]) 9 | return " ".join(s.split()[::-1]) 10 | -------------------------------------------------------------------------------- /Two Pointer/2486. Append Characters to String to Make Subsequence.py: -------------------------------------------------------------------------------- 1 | # Just exact logic as :"392. Is Subsequence" 2 | 3 | # Logic: Just find till which index in 't' you are able to find subsequence in 's'. 4 | # For this we can apply same logic as : "392. Is Subsequence". 5 | # Suppose from index 'j' you are not able to find then 6 | # you have to append 'len(t) - j' char at the end. 7 | 8 | # Time: O(n) 9 | 10 | class Solution: 11 | def appendCharacters(self, s: str, t: str) -> int: 12 | m, n = len(s), len(t) 13 | i , j = 0, 0 14 | while i < m and j < n: 15 | if s[i] == t[j]: 16 | i += 1 17 | j += 1 18 | else: 19 | i += 1 20 | return n - j -------------------------------------------------------------------------------- /Two Pointer/2540. Minimum Common Value.py: -------------------------------------------------------------------------------- 1 | # Logic: Given both ararys sorted in increasing order. 2 | # So apply two pointer and if equal then return ans because that will be the smallest one only. 3 | # else incr pointer of array whose value is small to find more bigger element for comparison. 4 | 5 | # Time: O(m+ n) 6 | 7 | class Solution: 8 | def getCommon(self, nums1: List[int], nums2: List[int]) -> int: 9 | i , j = 0, 0 10 | while i < len(nums1) and j < len(nums2): 11 | if nums1[i] == nums2[j]: 12 | return nums1[i] 13 | if nums1[i] > nums2[j]: 14 | j += 1 15 | else: 16 | i += 1 17 | return -1 18 | -------------------------------------------------------------------------------- /Two Pointer/2697. Lexicographically Smallest Palindrome.py: -------------------------------------------------------------------------------- 1 | # logic: we have to make char same from start and end where char_at_start <= char_at_end. 2 | 3 | # so, just check char from left and right like we do in case of palindrome. 4 | # if equal simply skip else make char same where char_at_start <=char_at_end 5 | 6 | class Solution: 7 | def makeSmallestPalindrome(self, s: str) -> str: 8 | lst= list(s) 9 | n= len(s) 10 | l, r= 0, n-1 11 | while l < r: 12 | if lst[l]== lst[r]: 13 | # skip 14 | l,r= l+1, r-1 15 | continue 16 | if lst[l] > lst[r]: 17 | # bring smaller one at start and both equal 18 | lst[l]= lst[r] 19 | else: 20 | # make end= start because we have to find the samllest alphabetical. 21 | lst[r]= lst[l] 22 | l,r= l+1, r-1 23 | return "".join(lst) 24 | 25 | 26 | -------------------------------------------------------------------------------- /Two Pointer/415. Add Strings.py: -------------------------------------------------------------------------------- 1 | # just same as we do addition of two linklist using two pointer. 2 | 3 | # time: O(n+ m) 4 | 5 | class Solution: 6 | def addStrings(self, X: str, Y: str) -> str: 7 | carry= 0 8 | n, m = len(X), len(Y) 9 | i, j= n-1, m-1 10 | ans= "" 11 | while i >= 0 or j >= 0 or carry: 12 | curSum= carry 13 | if i >= 0: 14 | curSum+= ord(X[i])- ord('0') # instead of 'curSum+= int(X[i])'. 15 | i-= 1 16 | if j >= 0: 17 | curSum+= ord(Y[j])- ord('0') 18 | j-= 1 19 | carry, num= divmod(curSum, 10) 20 | ans= str(num) + ans 21 | return ans -------------------------------------------------------------------------------- /Two Pointer/881. Boats to Save People.py: -------------------------------------------------------------------------------- 1 | # Logic: Since each boat carries at most two people at the same time. 2 | # so for minimum we will try to take one person having maximum value and one person having minimum value. 3 | 4 | # For taking like this sort the person and apply two pointer from start and end. 5 | 6 | class Solution: 7 | def numRescueBoats(self, people: List[int], limit: int) -> int: 8 | n = len(people) 9 | people.sort() 10 | ans = 0 11 | i, j = 0 , n -1 12 | while i <= j : 13 | if people[i] + people[j] > limit: 14 | # Take only larger person i.e 'j'th person on the boat 15 | j -= 1 16 | else: 17 | # Take both person on the boat 18 | i += 1 19 | j -= 1 20 | ans += 1 21 | return ans -------------------------------------------------------------------------------- /Two Pointer/948. Bag of Tokens.py: -------------------------------------------------------------------------------- 1 | # logic: 1) If has enough power then do 'Face-up' with minimal value of token so that 2 | # we can increase score by '1' with minimal use of power. 3 | # Here we need to get unplayed token having minimum token value. 4 | 5 | # 2) If not enough power then if score is > 0 then increase your score by as much as possible 6 | # reducing score by '1'. Here we need to get unplayed token having maximum token value. 7 | 8 | # From these we get intution of sorting + Two pointer. 9 | 10 | class Solution: 11 | def bagOfTokensScore(self, tokens: List[int], power: int) -> int: 12 | tokens.sort() 13 | n = len(tokens) 14 | score = 0 15 | ans = 0 16 | i, j = 0, n - 1 # 'i' will denote minimum unused token and 'j': will denote max unused token . 17 | while i <= j: 18 | if power >= tokens[i] : 19 | score += 1 20 | ans = max(ans, score) 21 | power -= tokens[i] 22 | i += 1 23 | elif score > 0: 24 | power += tokens[j] 25 | score -= 1 26 | j -= 1 27 | else: 28 | break 29 | return ans -------------------------------------------------------------------------------- /Two Pointer/Count pairs in a sorted array whose sum is less than x.py: -------------------------------------------------------------------------------- 1 | # just apply two sum and when you find "sum< target" 2 | # then you can take start index ele with any of the ele from 'start+1' to 'end' all pair will give sum < target. 3 | # So incr count= count + 'end- start' and update both start and end pointer. 4 | 5 | # But it will also print duplicates. 6 | # for avoiding duplicates, just move start pointer to next distinct ele like "15. sum". 7 | 8 | def countPairs(arr, target): 9 | n= len(arr) 10 | count= 0 11 | start, end= 0, n-1 12 | while start< end: 13 | if arr[start] + arr[end] >= target: 14 | # until you find sum < target. 15 | end-= 1 16 | else: # means < target 17 | count+= end- start 18 | start+= 1 19 | end-= 1 20 | return count 21 | 22 | 23 | # arr= [1, 2, 3, 4, 5, 6, 7, 8] 24 | arr= [1, 3, 7, 9, 10, 11] 25 | target= 7 26 | print(countPairs(arr, target)) -------------------------------------------------------------------------------- /Two Pointer/Count the triplets.py: -------------------------------------------------------------------------------- 1 | # logic: The third ele must must be greatest among three. 2 | # and we will get the 3rd ele on right side if we sort the array. 3 | 4 | # so if we sort the array and for every ele on right side(after sorting max one will be on right side) say at index 'i' 5 | # Then our Q reduces to "find no of combination of two element from index '0' to index 'i-1' such that their sum= arr[i] ". 6 | 7 | # time: O(n^2), space= O(1) 8 | 9 | class Solution: 10 | def countTriplet(self, arr, n): 11 | arr.sort() 12 | count= 0 13 | i= n -1 14 | while i > 1: 15 | target = arr[i] 16 | # nowe we have to find the pair whose sum= arr[i]= target 17 | start= 0 18 | end= i -1 19 | while start < end: 20 | if arr[start] + arr[end]== target: 21 | count+= 1 22 | start+= 1 23 | end-= 1 24 | elif arr[start] + arr[end] > target: 25 | end-= 1 26 | else: 27 | start+= 1 28 | i-= 1 29 | 30 | return count 31 | 32 | 33 | # Note: The above will give duplicate triplet also if duplicate no is also allowed. 34 | # # for removing duplicates do exactly same as "15. 3Sum". -------------------------------------------------------------------------------- /Two Pointer/Find the closest pair from two sorted arrays.py: -------------------------------------------------------------------------------- 1 | # just "two sum logic" 2 | 3 | # here closest_pair_sum can be greater or lesser than 'k'. 4 | # so after every possible sum update 'minDiff'. 5 | 6 | # Time : O(n) 7 | 8 | def printClosest(arr1, arr2, k): 9 | m, n= len(arr1), len(arr2) 10 | minDiff= float('inf') 11 | ele1, ele2= 0, 0 # to store the ans 12 | l= 0 # will point to 1st index in arr1 13 | r= n-1 # will point to the last index in arr2 14 | while l < m and r >=0: 15 | sum= arr1[l] + arr2[r] 16 | diff= abs(k- sum) 17 | if diff < minDiff: 18 | minDiff= diff 19 | ele1, ele2= arr1[l], arr2[r] 20 | if diff== 0: 21 | break 22 | if sum > k: 23 | r-= 1 24 | else: 25 | l += 1 26 | print("pair is: ", ele1, ele2) 27 | 28 | 29 | arr1= [1, 4, 5, 7] 30 | arr2= [10, 20, 30, 40] 31 | # x= 32 32 | x= 50 33 | 34 | printClosest(arr1, arr2, x) 35 | 36 | -------------------------------------------------------------------------------- /Two Pointer/Smallest Difference pair of values between two unsorted Arrays.py: -------------------------------------------------------------------------------- 1 | # Logic: i) Sort both arrays 2 | # ii) take two pointer 'i' and 'j' pointing to start of arr1 and arr2. 3 | # iii) Keep pointer of that array whose value is less to minimise the difference. -------------------------------------------------------------------------------- /recursion/1342_steps_to_reudce_to_zero.py: -------------------------------------------------------------------------------- 1 | 2 | # time: ~ O(logn) 3 | class Solution: 4 | def numberOfSteps(self, num: int) -> int: 5 | if num==0: 6 | return 0 7 | if num%2== 0: # if even 8 | return 1+ self.numberOfSteps(num//2) 9 | # if odd 10 | return 1+ self.numberOfSteps(num-1) 11 | 12 | 13 | # method 2 : 14 | # logic: 15 | # For the binary representation from right to left(until we find the leftmost 1) 16 | # if we meet 0, result += 1 because we are doing divide; 17 | # if we meet 1, result += 2 because we first do "-1" then do a divide; 18 | # ony exception is the leftmost 1, we just do a "-1" and it becomse 0 already. 19 | 20 | 21 | class Solution: 22 | def numberOfSteps(self, num: int) -> int: 23 | if num==0: 24 | return 0 25 | ans= 0 26 | while num: 27 | if num & 1: # if odd 28 | ans += 2 29 | else: 30 | ans += 1 31 | num = num >> 1 32 | return ans - 1 -------------------------------------------------------------------------------- /recursion/array _sorted_or_not.py: -------------------------------------------------------------------------------- 1 | # method 1: just check if any element on right side 2 | # is greater than the ele on its lfet side 3 | # submitted on GFG 4 | # class Solution: 5 | # def arraySortedOrNot(self, arr, n): 6 | # for i in range(n-1): 7 | # if arr[i]>arr[i+1]: 8 | # return False 9 | # return True 10 | 11 | 12 | #another way of writing recursion function(better one) 13 | # def sortedOrNot(arr, index): 14 | # if index== len(arr)-1: # if index is the index of last ele of the array then True 15 | # # as last ele will be always sorted 16 | # return True 17 | # # check the value of next ele and call the function for next index 18 | # return (arr[index]<=arr[index+1]) and sortedOrNot(arr,index+1) 19 | # # arr= [2,4,4,5,6,7,8] 20 | # arr= [1,5,3,9,10,54] 21 | # # print(sortedOrNot(arr,0)) 22 | 23 | 24 | # another method: best one 25 | def sorted(arr): 26 | if len(arr)==1: 27 | return True 28 | return arr[0]<=arr[1] and sorted(arr[1:]) 29 | 30 | # arr1= [2,4,4,5,6,7] 31 | # arr1= [1,5,3,9,10,54] 32 | # print(sorted(arr1)) 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /recursion/binary_search.py: -------------------------------------------------------------------------------- 1 | # binary search using recursion 2 | def BinarySearch(arr,key,start,end): 3 | if start> end: 4 | return -1 5 | mid= start + (end-start)//2 6 | if arr[mid]== key: 7 | return mid 8 | if arr[mid]>key: 9 | return BinarySearch(arr,key,start,mid-1) 10 | return BinarySearch(arr,key,mid+1,end) 11 | 12 | arr= [2,4,5,7,9,10,15,22] 13 | print(BinarySearch(arr,11,0,len(arr)-1)) -------------------------------------------------------------------------------- /recursion/steps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ravi-0412/DSA-Program-And-Notes/3961bd7499d9a3e2623207ebfab8a34ba40b50c2/recursion/steps -------------------------------------------------------------------------------- /recursion/tempCodeRunnerFile.py: -------------------------------------------------------------------------------- 1 | def reverse(n): 2 | # ans= "" -------------------------------------------------------------------------------- /recursion/tower_hanoi.py: -------------------------------------------------------------------------------- 1 | 2 | # Solution: 3 | # the tower from which you are moving the disc that will the source 4 | # and to which you are moving that will be the destination, 5 | # and tower that will be remaining at any moment that will work as helper. 6 | 7 | def toh(n, s, d, h): 8 | m= 2**n -1 # will print the total no of move at last 9 | if n==0: # if n is zero simply return 10 | return 11 | else: 12 | toh(n-1,s,h,d) # 1st move the 'n-1' disc to the helper with the help of destination 13 | print("{}[{}->{}]".format(n,s,d)) # move the nth disc directly from source to destination as only largest disc will be on 14 | # after this largest disc will be getting placed at the destination 15 | toh(n-1,h,d,s) # now move the 'n-1' disc from the helper to the destination with the help of source 16 | return m 17 | 18 | print(toh(3,'s','d','h')) # '3' means [3,2,1] on the first disc , here on source 's'. and we have move first three disc from top . 19 | --------------------------------------------------------------------------------