├── .gitignore ├── ACM ├── input └── main.py ├── AdvancedPython ├── class.py ├── coroutine.py ├── decorator.py ├── default_argument.py ├── encapsulation.py ├── function.py ├── generator.py ├── id.py ├── iterator.py ├── lambda.py ├── namespace.py ├── os.py ├── producer-consumer.py ├── thread.py └── with.py ├── Algorithm ├── DisjointSet.py ├── Graph.py ├── Heap.py ├── KMP.py ├── PrefixSum.py ├── QuickSort.py ├── ReservoirSampling.py ├── Search.py ├── Sort.py └── TopologicalSorting.py ├── Bash ├── Manual ├── log ├── log.py └── script.sh ├── InterviewProblem ├── Catalog.txt ├── JZ_Offer │ ├── JZ10 │ │ └── JZ10.py │ ├── JZ11 │ │ └── JZ11.py │ ├── JZ12 │ │ └── JZ12.py │ ├── JZ13 │ │ └── JZ13.py │ ├── JZ14 │ │ └── JZ14.py │ ├── JZ15 │ │ └── JZ15.py │ ├── JZ16 │ │ └── JZ16.py │ ├── JZ17 │ │ └── JZ17.py │ ├── JZ18 │ │ └── JZ18.py │ ├── JZ19 │ │ └── JZ19.py │ ├── JZ20 │ │ └── JZ20.py │ ├── JZ21 │ │ └── JZ21.py │ ├── JZ22 │ │ └── JZ22.py │ ├── JZ23 │ │ └── JZ23.py │ ├── JZ24 │ │ └── JZ24.py │ ├── JZ25 │ │ └── JZ25.py │ ├── JZ26 │ │ └── JZ26.py │ ├── JZ27 │ │ └── JZ27.py │ ├── JZ28 │ │ └── JZ28.py │ ├── JZ29 │ │ └── JZ29.py │ ├── JZ3 │ │ └── JZ3.py │ ├── JZ30 │ │ └── JZ30.py │ ├── JZ31 │ │ └── JZ31.py │ ├── JZ32 │ │ └── JZ32.py │ ├── JZ33 │ │ └── JZ33.py │ ├── JZ34 │ │ └── JZ34.py │ ├── JZ35 │ │ └── JZ35.py │ ├── JZ36 │ │ └── JZ36.py │ ├── JZ37 │ │ └── JZ37.py │ ├── JZ38 │ │ └── JZ38.py │ ├── JZ39 │ │ └── JZ39.py │ ├── JZ4 │ │ └── JZ4.py │ ├── JZ40 │ │ └── JZ40.py │ ├── JZ41 │ │ └── JZ41.py │ ├── JZ42 │ │ └── JZ42.py │ ├── JZ43 │ │ └── JZ43.py │ ├── JZ44 │ │ └── JZ44.py │ ├── JZ45 │ │ └── JZ45.py │ ├── JZ46 │ │ └── JZ46.py │ ├── JZ47 │ │ └── JZ47.py │ ├── JZ48 │ │ └── JZ48.py │ ├── JZ49 │ │ └── JZ49.py │ ├── JZ5 │ │ └── JZ5.py │ ├── JZ50 │ │ └── JZ50.py │ ├── JZ51 │ │ └── JZ51.py │ ├── JZ52 │ │ └── JZ52.py │ ├── JZ53 │ │ └── JZ53.py │ ├── JZ54 │ │ └── JZ54.py │ ├── JZ55 │ │ └── JZ55.py │ ├── JZ56 │ │ └── JZ56.py │ ├── JZ57 │ │ └── JZ57.py │ ├── JZ58 │ │ └── JZ58.py │ ├── JZ59 │ │ └── JZ59.py │ ├── JZ6 │ │ └── JZ6.py │ ├── JZ61 │ │ └── JZ61.py │ ├── JZ62 │ │ └── JZ62.py │ ├── JZ63 │ │ └── JZ63.py │ ├── JZ64 │ │ └── JZ64.py │ ├── JZ65 │ │ └── JZ65.py │ ├── JZ66 │ │ └── JZ66.py │ ├── JZ67 │ │ └── JZ67.py │ ├── JZ68 │ │ └── JZ68.py │ ├── JZ69 │ │ └── JZ69.py │ ├── JZ7 │ │ └── JZ7.py │ ├── JZ70 │ │ └── JZ70.py │ ├── JZ71 │ │ └── JZ71.py │ ├── JZ73 │ │ └── JZ73.py │ ├── JZ74 │ │ └── JZ74.py │ ├── JZ75 │ │ └── JZ75.py │ ├── JZ76 │ │ └── JZ76.py │ ├── JZ77 │ │ └── JZ77.py │ ├── JZ78 │ │ └── JZ78.py │ ├── JZ79 │ │ └── JZ79.py │ ├── JZ8 │ │ └── JZ8.py │ ├── JZ81 │ │ └── JZ81.py │ ├── JZ82 │ │ └── JZ82.py │ ├── JZ83 │ │ └── JZ83.py │ ├── JZ84 │ │ └── JZ84.py │ ├── JZ85 │ │ └── JZ85.py │ ├── JZ86 │ │ └── JZ86.py │ ├── JZ9 │ │ └── JZ9.py │ └── Questions Index.txt ├── LeetCode │ ├── LC1 Two Sum │ │ └── LC1.py │ ├── LC10 Regular Expression Matching │ │ └── LC10.py │ ├── LC1002 Find Common Characters │ │ └── LC1002.py │ ├── LC101 Symmetric Tree │ │ └── LC101.py │ ├── LC1013 Partition Array Into Three Parts With Equal Sum │ │ └── LC1013.py │ ├── LC102 Binary Tree Level Order Traversal │ │ └── LC102.py │ ├── LC103 Binary Tree Zigzag Level Order Traversal │ │ └── LC103.py │ ├── LC104 Maximum Depth of Binary Tree │ │ └── LC104.py │ ├── LC105 Construct Binary Tree from Preorder and Inorder Traversal │ │ └── LC105.py │ ├── LC107 Binary Tree Level Order Traversal II │ │ └── LC107.py │ ├── LC108 Convert Sorted Array to Binary Tree │ │ └── LC108.py │ ├── LC1087 Brace Expansion │ │ └── LC1087.py │ ├── LC109 Convert Sorted List to Binary Search Tree │ │ └── LC109.py │ ├── LC11 Container With Most Water │ │ └── LC11.py │ ├── LC110 Balanced Binary Tree │ │ └── LC110.py │ ├── LC1109 Corporate Flight Bookings │ │ └── LC1109.py │ ├── LC111 Minimum Depth of Binary Tree │ │ └── LC111.py │ ├── LC112 Path Sum │ │ └── LC112.py │ ├── LC113 Path Sum II │ │ └── LC113.py │ ├── LC114 Flatten Binary Tree to Linked List │ │ └── LC114.py │ ├── LC115 Distinct Subsequences │ │ └── LC115.py │ ├── LC116 Populating Next Right Pointers in Each Node │ │ └── LC116.py │ ├── LC117 Populating Next Right Pointers in Each Node II │ │ └── LC117.py │ ├── LC12 Integer to Roman │ │ └── LC12.py │ ├── LC120 Triangle │ │ └── LC120.py │ ├── LC121 Best Time to Buy and Sell Stock │ │ └── LC121.py │ ├── LC122 Best Time to Buy and Sell Stock II │ │ └── LC122.py │ ├── LC123 Best Time to Buy and Sell Stock III │ │ └── LC123.py │ ├── LC124 Binary Tree Maximum Path Sum │ │ └── LC124.py │ ├── LC126 Word Ladder II │ │ └── LC126.py │ ├── LC1262 Greatest Sum Divisible by Three │ │ └── LC1262.py │ ├── LC127 Word Ladder │ │ └── LC127.py │ ├── LC128 Longest Consecutive Sequence │ │ └── LC128.py │ ├── LC1287 Element Apearing More Than 25% In Sorted Array │ │ └── LC1287.py │ ├── LC13 Roman to Integer │ │ └── LC13.py │ ├── LC130 Surrounded Regions │ │ └── LC130.py │ ├── LC1306 Jump Game III │ │ └── LC1306.py │ ├── LC1307 Verbal Arithmetic Puzzle │ │ └── LC1307.py │ ├── LC1314 Matrix Block Sum │ │ └── LC1314.py │ ├── LC133 Clone Graph │ │ └── LC133.py │ ├── LC134 Gas Station │ │ └── LC134.py │ ├── LC136 Single Number │ │ └── LC136.py │ ├── LC138 Copy List with Random Pointer │ │ └── LC138.py │ ├── LC1382 Blance a Binary Search Tree │ │ └── LC1382.py │ ├── LC139 Word Break │ │ └── LC139.py │ ├── LC14 Longest Common Prefix │ │ └── LC14.py │ ├── LC140 Word Break II │ │ └── LC140.py │ ├── LC141 Linked List Cycle │ │ └── LC141.py │ ├── LC142 Linked List Cycle II │ │ └── LC142.py │ ├── LC143 Reorder List │ │ └── LC143.py │ ├── LC144 Binary Tree Preorder Traversal │ │ └── LC144.py │ ├── LC145 Binary Tree Postorder Traversal │ │ └── LC145.py │ ├── LC146 LRU Cache │ │ └── LC146.py │ ├── LC147 Insertion Sort List │ │ └── LC147.py │ ├── LC148 Sort List │ │ └── LC148.py │ ├── LC15 3Sum │ │ └── LC15.py │ ├── LC152 Maximum Product Subarray │ │ └── LC152.py │ ├── LC153 Find Minimum in Rotated Sorted Array │ │ └── LC153.py │ ├── LC154 Find Minimum in Rotated Sorted Array II │ │ └── LC154.py │ ├── LC155 Min Stack │ │ └── LC155.py │ ├── LC157 Read N Characters Given Read4 │ │ └── LC157.py │ ├── LC158 Read N Characters Given read4 II - Call Multiple Times │ │ └── LC158.py │ ├── LC16 3Sum Closest │ │ └── LC16.py │ ├── LC160 Intersection of Two Linked Lists │ │ └── LC160.py │ ├── LC161 One Edit Distance │ │ └── LC161.py │ ├── LC162 Find Peak Element │ │ └── LC162.py │ ├── LC163 Missing Rangers │ │ └── LC163.py │ ├── LC166 Fraction to Recurring Decimal │ │ └── LC166.py │ ├── LC167 Two Sum II - Input Array Is Sorted │ │ └── LC167.py │ ├── LC168 Excel Sheet Column Title │ │ └── LC168 │ ├── LC169 Majority Element │ │ └── LC169.py │ ├── LC1696 Jump Game VI │ │ └── LC1696.py │ ├── LC17 Letter Combinations of a Phone Number │ │ └── LC17.py │ ├── LC170 Two Sum III - Data structure design │ │ └── LC170.py │ ├── LC171 Excel Sheet Column Number │ │ └── LC171.py │ ├── LC173 Binary Search Tree Iterator │ │ └── LC173.py │ ├── LC1730 Shortest Path to Get Food │ │ └── LC1730.py │ ├── LC174 Dungeon Game │ │ └── LC174.py │ ├── LC179 Largest Number │ │ └── LC179.py │ ├── LC18 4Sum │ │ └── LC18.py │ ├── LC1871 Jump Game VII │ │ └── LC1871.py │ ├── LC19 Remove Nth Node From End of List │ │ └── LC19.py │ ├── LC190 Reverse Bits │ │ └── LC190.py │ ├── LC1901 Find a Peak Element II │ │ └── LC1901.py │ ├── LC198 House Robber │ │ └── LC198.py │ ├── LC199 Binary Tree Right Side View │ │ └── LC199.py │ ├── LC2 Add Two Numbers │ │ └── LC2.py │ ├── LC20 Valid Parentheses │ │ └── LC20.py │ ├── LC200 Number of Islands │ │ └── LC200.py │ ├── LC204 Count Primes │ │ └── LC204.py │ ├── LC205 Isomorphic Strings │ │ └── LC205.py │ ├── LC206 Reverse Linked List │ │ └── LC206.py │ ├── LC207 Course Schedule │ │ └── LC207.py │ ├── LC208 Implement Trie (Prefix Tree) │ │ └── LC208.py │ ├── LC2080 Range Frequency Queries │ │ └── LC2080.py │ ├── LC209 Minimum Size Subarray Sum │ │ └── LC209.py │ ├── LC21 Merge Two Sorted Lists │ │ └── LC21.py │ ├── LC210 Course Schedule II │ │ └── LC210.py │ ├── LC213 House Robber II │ │ └── LC213.py │ ├── LC215 Kth Largest Element in an Array │ │ └── LC215.py │ ├── LC217 Contains Duplicate │ │ └── LC217.py │ ├── LC219 Contains Duplicate II │ │ └── LC219.py │ ├── LC22 Generate Parentheses │ │ └── LC22.py │ ├── LC220 Contains Duplicate III │ │ └── LC220.py │ ├── LC221 Maximal Square │ │ └── LC221.py │ ├── LC224 Basic Calculator │ │ └── LC224.py │ ├── LC225 Implement Stack using Queues │ │ └── LC225.py │ ├── LC226 Invert Binary Tree │ │ └── LC226.py │ ├── LC227 Basic Calculator II │ │ └── LC227.py │ ├── LC23 Merge k Sorted Lists │ │ └── LC23.py │ ├── LC230 Kth Smallest Element in a BST │ │ └── LC230.py │ ├── LC231 Power of Two │ │ └── LC231.py │ ├── LC232 Implement Queue with Stacks │ │ └── LC232.py │ ├── LC234 Palindrome Linked List │ │ └── LC234.py │ ├── LC235 owest Common Ancestor of a Binary Search Tree │ │ └── LC235.py │ ├── LC236 Lowest Common Ancestor of a Binary Tree │ │ └── LC236.py │ ├── LC238 Product of Array Except Self │ │ └── LC238.py │ ├── LC239 Sliding WIndow Maximum │ │ └── LC239.py │ ├── LC24 Swap Nodes in Pairs │ │ └── LC24.py │ ├── LC240 Search a 2D Matrix II │ │ └── LC240.py │ ├── LC25 Reverse Nodes in k-Group │ │ └── LC25.py │ ├── LC252 Meeting Rooms │ │ └── LC252.py │ ├── LC253 Meeting Rooms II │ │ └── LC253.py │ ├── LC259 3Sum Smaller │ │ └── LC259.py │ ├── LC26 Remove Duplicates from Sorted Array │ │ └── LC26.py │ ├── LC268 Missing Number │ │ └── LC268.py │ ├── LC27 Remove Element │ │ └── LC27.py │ ├── LC279 Perfect Squares │ │ └── LC279.py │ ├── LC28 Implement strStr │ │ └── LC28.py │ ├── LC283 Move Zeros │ │ └── LC283.py │ ├── LC285 Inorder Successor in BST │ │ └── LC285.py │ ├── LC287 Find the Duplicate Number │ │ └── LC287.py │ ├── LC289 Game of Life │ │ └── LC289.py │ ├── LC29 Devide Two Integers │ │ └── LC29.py │ ├── LC297 Serialize and Deserialize Binary Tree │ │ └── LC297.py │ ├── LC3 Longest Substring Without Repeating Characters │ │ └── LC3.py │ ├── LC30 Substring with Concatenation of All Words │ │ └── LC30.py │ ├── LC300 Longest Increasing Subsequence │ │ └── LC300.py │ ├── LC301 Remove Invalid Parentheses │ │ └── LC301.py │ ├── LC309 Best Time to Buy and Sell Stock with Cooldown │ │ └── LC309.py │ ├── LC31 Next Permutation │ │ └── LC31.py │ ├── LC312 Burst Ballons │ │ └── LC312.py │ ├── LC315 Count of Smaller Number After Self │ │ └── LC315.py │ ├── LC32 Longest Valid Parentheses │ │ └── LC32.py │ ├── LC322 Coin Change │ │ └── LC322.py │ ├── LC323 Number of Connected Components in an Undirected Graph │ │ └── LC323.py │ ├── LC325 Maximum Size Subarray Sum Equals k │ │ └── LC325.py │ ├── LC329 Longest Increasing Path in a Matrix │ │ └── LC329.py │ ├── LC33 Search in Rotated Sorted Array │ │ └── LC33.py │ ├── LC337 House Robber III │ │ └── LC337.py │ ├── LC338 Counting Bits │ │ └── LC338.py │ ├── LC34 Find First and Last Position of Element in Sorted Array │ │ └── LC34.py │ ├── LC347 Top K Frequent Elements │ │ └── LC347.py │ ├── LC35 Search Insert Position │ │ └── LC35.py │ ├── LC354 Russian Doll Envelopes │ │ └── LC354.py │ ├── LC36 Valid Sudoku │ │ └── LC36.py │ ├── LC369 Plus One Linked List │ │ └── LC369.py │ ├── LC37 Sudoku Solver │ │ └── LC37.py │ ├── LC387 First Unique Character in a String │ │ └── LC387.py │ ├── LC39 Combination Sum │ │ └── LC39.py │ ├── LC392 Is Subsequence │ │ └── LC392.py │ ├── LC394 Decode String │ │ └── LC394.py │ ├── LC398 Random Pick Index │ │ └── LC398.py │ ├── LC399 Evaluate Division │ │ └── LC399.py │ ├── LC4 Median of Two Sorted Array │ │ └── LC4.py │ ├── LC40 Combination Sum II │ │ └── LC40.py │ ├── LC402 Remove K Digits │ │ └── LC402.py │ ├── LC406 Queue Reconstruction by Height │ │ └── LC406.py │ ├── LC41 First Missing Positive │ │ └── LC41.py │ ├── LC414 Third Maximum Number │ │ └── LC414.py │ ├── LC416 Partition Equal Subset Sum │ │ └── LC416.py │ ├── LC42 Trapping Rain Water │ │ └── LC42.py │ ├── LC426 Convert Binary Search Tree to Sorted Doubly Linked List │ │ └── LC426.py │ ├── LC428 Serialize and Deserialize N-ary Tree │ │ └── LC428.py │ ├── LC429 N-ary Tree Level Order Traversal │ │ └── LC429.py │ ├── LC43 Multiply String │ │ └── LC43.py │ ├── LC437 Path Sum III │ │ └── LC437.py │ ├── LC438 Find All Anagrams in a String │ │ └── LC438.py │ ├── LC44 Wildcard Matching │ │ └── LC44.py │ ├── LC442 Find All Duplicates in an Array │ │ └── LC442.py │ ├── LC448 Find All Numbers Disappeared in an Array │ │ └── LC448.py │ ├── LC449 Serialize and Deserialize BST │ │ └── LC449.py │ ├── LC45 Jump Game II │ │ └── LC45.py │ ├── LC450 Delete Node in a BST │ │ └── LC450.py │ ├── LC46 Permutations │ │ └── LC46.py │ ├── LC460 LFU Cache │ │ └── LC460.py │ ├── LC461 Hamming Distance │ │ └── LC461.py │ ├── LC47 Permutations II │ │ └── LC47.py │ ├── LC470 Implement Rand10 Using Rand7 │ │ └── LC470.py │ ├── LC48 Rotate Image │ │ └── LC48.py │ ├── LC49 Group Anagrams │ │ └── LC49.py │ ├── LC493 Reverse Pairs │ │ └── LC493.py │ ├── LC494 Target Sum │ │ └── LC494.py │ ├── LC5 Longest Palindromic Substring │ │ └── LC5.py │ ├── LC50 Pow(x,n) │ │ └── LC50.py │ ├── LC51 N-Queens │ │ └── LC51.py │ ├── LC510 Inorder Successor in BST II │ │ └── LC510.py │ ├── LC518 Coin Change II │ │ └── LC518.py │ ├── LC529 Minesweeper │ │ └── LC529.py │ ├── LC53 Maximum Subarray │ │ └── LC53.py │ ├── LC538 Convert BST to Greater Tree │ │ └── LC538.py │ ├── LC54 Spiral Matrix │ │ └── LC54.py │ ├── LC543 Diameter of Binary Tree │ │ └── LC543.py │ ├── LC547 Number of Provinces │ │ └── LC547.py │ ├── LC55 Jump Game │ │ └── LC55.py │ ├── LC56 Merge Intervals │ │ └── LC56.py │ ├── LC560 Subarray Sum Equals K │ │ └── LC560.py │ ├── LC57 Insert Interval │ │ └── LC57.py │ ├── LC581 Shortest Unsorted Continuous Subarray │ │ └── LC581.py │ ├── LC59 Spiral Matrix II │ │ └── LC59.py │ ├── LC60 Permutation Sequence │ │ └── LC60.py │ ├── LC61 Rotate List │ │ └── LC61.py │ ├── LC617 Merge Two Binary Tree │ │ └── LC617.py │ ├── LC62 Unique Paths │ │ └── LC62.py │ ├── LC621 Task Scheduler │ │ └── LC621.py │ ├── LC63 Unique Path II │ │ └── LC63.py │ ├── LC630 Course Schedule III │ │ └── LC630.py │ ├── LC64 Minimum Path Sum │ │ └── LC64.py │ ├── LC647 Palindromic Substrings │ │ └── LC647.py │ ├── LC65 Valid Number │ │ └── LC65.py │ ├── LC653 Two Sum IV - Input is a BST │ │ └── LC653.py │ ├── LC67 Add Binary │ │ └── LC67.py │ ├── LC68 Text Justification │ │ └── LC68.py │ ├── LC684 Redundant Connection │ │ └── LC684.py │ ├── LC69 Sqrt(x) │ │ └── LC69.py │ ├── LC7 Reverse Integer │ │ └── LC7.py │ ├── LC70 Climbing Stairs │ │ └── LC70.py │ ├── LC71 Simplify Path │ │ └── LC71.py │ ├── LC718 Maximum Length of Repeated Subarray │ │ └── LC718.py │ ├── LC72 Edit Distance │ │ └── LC72.py │ ├── LC73 Set Matrix Zeros │ │ └── LC73.py │ ├── LC739 Daily Temperatures │ │ └── LC739.py │ ├── LC74 Search a 2D Matrix │ │ └── LC74.py │ ├── LC75 Sort Colors │ │ └── LC75.py │ ├── LC752 Open the Lock │ │ └── LC752.py │ ├── LC76 Minimum Window Substring │ │ └── LC76.py │ ├── LC769 Max Chunks To Make Sorted │ │ └── LC769.py │ ├── LC77 Combinations │ │ └── LC77.py │ ├── LC772 Basic Calculator III │ │ └── LC772.py │ ├── LC78 Subsets │ │ └── LC78.py │ ├── LC79 Word Search │ │ └── LC79.py │ ├── LC8 String to Integer (atoi) │ │ └── LC8.py │ ├── LC80 Remove Duplicates from Sorted Array II │ │ └── LC80.py │ ├── LC81 Search in Rotated Sorted Array II │ │ └── LC81.py │ ├── LC82 Remove Duplicates from Sorted List II │ │ └── LC82.py │ ├── LC83 Remove Duplicates from Sorted List │ │ └── LC83.py │ ├── LC84 Largest Rectangle in Histogram │ │ └── LC84.py │ ├── LC844 Backspace String Compare │ │ └── LC844.py │ ├── LC85 Maximal Rectangle │ │ └── LC85.py │ ├── LC862 Shortest Subarray with Sum at Least K │ │ └── LC862.py │ ├── LC87 Scramble String │ │ └── LC87.py │ ├── LC88 Merge Sorted Array │ │ └── LC88.py │ ├── LC889 Construct Binary Tree from Preorder and Postorder Traversal │ │ └── LC889.py │ ├── LC89 Grey Code │ │ └── LC89.py │ ├── LC90 Subsets II │ │ └── LC90.py │ ├── LC91 Decode Ways │ │ └── LC91.py │ ├── LC92 Reverse Linked List II │ │ └── LC92.py │ ├── LC93 Restore IP Address │ │ └── LC93.py │ ├── LC94 Binary Tree Inorder Traversal │ │ └── LC94.py │ ├── LC96 Unqiue Binary Search Trees │ │ └── LC96.py │ ├── LC97 Interleaving String │ │ └── LC97.py │ ├── LC98 Validate Binary Search Tree │ │ └── LC98.py │ ├── LC986 Interval List Intersections │ │ └── LC986.py │ ├── LC987 Vertical Order Traversal of a Binary Tree │ │ └── LC987.py │ └── Template └── SomeProblems.py ├── README.md └── SomeImplementation ├── Kmeans.py └── LR.py /ACM/input: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 3 | 4 -------------------------------------------------------------------------------- /ACM/main.py: -------------------------------------------------------------------------------- 1 | ### python3 main.py < input 2 | import sys 3 | 4 | line = sys.stdin.readline() 5 | line = sys.stdin.readline() 6 | print(line.split()) 7 | 8 | val = 1 9 | print(f"{val:.2f}") -------------------------------------------------------------------------------- /AdvancedPython/coroutine.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | def job1(): 4 | while True: 5 | print("job1") 6 | time.sleep(1) 7 | yield 8 | 9 | 10 | def job2(): 11 | while True: 12 | print("job2") 13 | time.sleep(1) 14 | yield 15 | 16 | j1 = job1() 17 | j2 = job2() 18 | 19 | 20 | 21 | start = time.perf_counter() ### get the most accurate timestamp that python can get 22 | for _ in range(5): 23 | next(j1) 24 | next(j2) 25 | end = time.perf_counter() 26 | print(f"Time: {round(end-start, 1)}") 27 | -------------------------------------------------------------------------------- /AdvancedPython/default_argument.py: -------------------------------------------------------------------------------- 1 | import time 2 | from datetime import datetime 3 | 4 | 5 | # def display_time(t=datetime.now()): 6 | # print(t) 7 | 8 | # print(display_time.__defaults__) 9 | # display_time() 10 | # time.sleep(1) 11 | # display_time() 12 | # time.sleep(1) 13 | 14 | 15 | ### if the default argument is mutable, it will be initialized when the function is defined 16 | def add(x, array=[]): 17 | array.append(x) 18 | print(array) 19 | 20 | add(1) 21 | add(2) 22 | add(3) -------------------------------------------------------------------------------- /AdvancedPython/encapsulation.py: -------------------------------------------------------------------------------- 1 | class Sample: 2 | def __init__(self): 3 | self.__private = 0 4 | self.public = 1 5 | self.__getPrivate() 6 | 7 | def __getPrivate(self): 8 | print(self.__private) 9 | 10 | def getPublic(self): 11 | print(self.public) 12 | 13 | def __test__(self): 14 | print("OK") 15 | 16 | 17 | test = Sample() 18 | # test.__getPrivate() ### attribute and method with __ prefix can not be called outside the class 19 | # test.getPublic() 20 | test.__test__() -------------------------------------------------------------------------------- /AdvancedPython/function.py: -------------------------------------------------------------------------------- 1 | def foo(arg, *args, **kwargs): 2 | print(arg) 3 | print("args", args) 4 | print("kwargs", kwargs, kwargs.keys(), kwargs.values()) 5 | 6 | # foo(1,2,3,4,5, key1=1, key2=2) 7 | 8 | arg = [1,2,3] 9 | # foo(arg) 10 | foo(*arg) 11 | 12 | ### 高阶函数(函数的函数) 13 | def func(): 14 | print("OK") 15 | 16 | def ffunc(func): 17 | func() 18 | 19 | # ffunc(func) 20 | 21 | ''' 22 | Python内置的高阶函数: map, filter, sort 23 | ''' 24 | # print(list(map(lambda x:x**2, [i for i in range(1, 11)]))) 25 | # print(list(filter(lambda x:x<6, [i for i in range(1, 11)]))) 26 | 27 | # arr = [-2,-1,3,-5,1,0] 28 | # arr.sort(key=lambda x:abs(x)) 29 | # print(arr) -------------------------------------------------------------------------------- /AdvancedPython/generator.py: -------------------------------------------------------------------------------- 1 | import time 2 | import os 3 | import psutil 4 | 5 | ### generator is a function return a iterator 6 | ### generator' object is not subscriptable 7 | 8 | def List(n=10000000): 9 | res = [] 10 | for i in range(n): 11 | res.append(i) 12 | return res 13 | 14 | def Generator(n=10000000): 15 | for i in range(n): 16 | yield i 17 | 18 | start = time.perf_counter() ### get the most accurate timestamp that python can get 19 | 20 | # test = [i for i in range(10000000)] 21 | test = (i for i in range(10000000)) ### generator 22 | 23 | end = time.perf_counter() 24 | 25 | print(f"Time: {round(end-start, 1)}") 26 | 27 | process = psutil.Process(os.getpid()) 28 | print(f"Memory usage: {process.memory_info().rss // 1024 // 1024}MB") ### in bytes 29 | 30 | 31 | -------------------------------------------------------------------------------- /AdvancedPython/id.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | a = [1,2,3] 5 | b = [1,2,4] 6 | print(id(a[1]) == id(b[1])) ### small constant int is constant in the memory 7 | 8 | c = None 9 | d = True 10 | print(id(None) == id(c)) 11 | print(d is True) 12 | 13 | i = 1 14 | print(type(i)) 15 | print(id(i) == id(a[0])) 16 | print(sys.getsizeof(i)) -------------------------------------------------------------------------------- /AdvancedPython/iterator.py: -------------------------------------------------------------------------------- 1 | ### generator is a function return a iterator 2 | ### generator' object is not subscriptable 3 | 4 | # names = ["Peter Parker", "Clark Kent", "Wade Wilson", "Bruce Wayne"] 5 | # heros = ["Spiderman", "Superman", "Deadpool", "Batman"] 6 | # identities = zip(names, heros) 7 | # # print(list(identities)) 8 | # for identity in identities: 9 | # print(identity) 10 | 11 | # test = range(10) ### iterable but not a iterator(lazy iterable only allow one-pass) 12 | 13 | arr = [i for i in range(3)] 14 | iterator = iter(arr) 15 | print(iterator) ### iterator object 16 | print(next(iterator)) 17 | print(next(iterator)) 18 | print(next(iterator)) 19 | # next(iterator) ### StopIteration error 20 | print(next(iterator, "EOF")) ### set the end 21 | print(next(iterator, "EOF")) ### set the end 22 | 23 | 24 | 25 | 26 | 27 | ### enumerate is just a fancy iterator 28 | # def abc(): 29 | # letters = ['a', 'b', 'c'] 30 | # for letter in letters: 31 | # yield letter 32 | 33 | # for i, letter in enumerate(abc()): 34 | # print(i, letter) -------------------------------------------------------------------------------- /AdvancedPython/lambda.py: -------------------------------------------------------------------------------- 1 | ### lambda arg1, arg2, ... : expersion 2 | ### lambda匿名函数,可以接受任意数量的参数,但只能有一个表达式 3 | ### 使用场景:你所要做的操作是不重要的(函数不值得起一个名字) 4 | add = lambda x,y : x+y 5 | print(add(1,1)) 6 | 7 | arr = [3,2,5,1,6,4,0] 8 | # sorted_arr = sorted(arr, key=lambda x: -x) 9 | # sorted_arr = sorted(arr) 10 | # print(sorted_arr) 11 | 12 | arr.sort(key=lambda x:-x) 13 | print(arr) 14 | 15 | from collections import defaultdict 16 | graph = defaultdict(lambda: set()) 17 | 18 | ### Only __lt__ is needed by Python for sorting 19 | ### if we want to use heap for some objects that do not support to compare 20 | ### we can re-implement __lt__ 21 | class Node: 22 | def __init__(self, val=-1): 23 | self.val = val 24 | def __lt__(self, other): ### less than 25 | return self.val < other.val 26 | 27 | node1 = Node(1) 28 | node2 = Node(2) 29 | from heapq import * 30 | heap = [] 31 | heap.append(node2) 32 | heap.append(node1) 33 | heapify(heap) 34 | print(heappop(heap).val) 35 | -------------------------------------------------------------------------------- /AdvancedPython/namespace.py: -------------------------------------------------------------------------------- 1 | ### is identity 2 | ### == equality 3 | 4 | print("Ab" is "Ab") 5 | 6 | a = "Ab" 7 | b = "Ab" 8 | 9 | print(id(a)) 10 | print(id(b)) -------------------------------------------------------------------------------- /AdvancedPython/os.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # print(os.getcwd()) 4 | # os.chdir('/Users/Charles/Desktop') 5 | # print(os.getcwd()) 6 | 7 | # os.mkdir("New Folder") 8 | # os.rmdir("New Folder") 9 | # os.mkdir("Dir1/Dir2") ### can not handle sub-folder 10 | # os.makedirs("Dir1/Dir2") ### can handle sub-folder 11 | # os.removedirs("Dir1/Dir2") 12 | 13 | # os.rename("New Folder", "test") 14 | 15 | # print(os.listdir()) 16 | 17 | 18 | for dirpath, dirnames, filenames in os.walk("/Users/Charles/Documents"): 19 | print("Current Path:", dirpath) 20 | print("Directories:", dirnames) 21 | print("Files:", filenames) -------------------------------------------------------------------------------- /AdvancedPython/producer-consumer.py: -------------------------------------------------------------------------------- 1 | import random 2 | import threading 3 | from threading import Thread 4 | import multiprocessing 5 | from queue import Queue ### Queue in Python is a thread-safe to get and put data 6 | 7 | def display(msg): 8 | threadName = threading.current_thread().name 9 | processName = multiprocessing.current_process().name 10 | print(f"{processName}/{threadName}: {msg}") 11 | 12 | ### Producer 13 | def produce_job(queue, n_jobs): 14 | global finished 15 | for i in range(1, n_jobs+1): ### produce N jobs 16 | val = random.randint(1, 100) 17 | queue.put(val) 18 | display(f"Producing {i}: {val}") 19 | finished = True 20 | display(f"Finished producing {n_jobs} jobs.") 21 | 22 | ### Consumer 23 | def consume_job(queue): 24 | global finished 25 | counter = 0 26 | while True: 27 | if not queue.empty(): 28 | counter += 1 29 | val = queue.get() 30 | display(f"Consuming {counter}: {val}") 31 | else: 32 | if finished == True: 33 | break 34 | display(f"Finished consuming {counter} jobs.") 35 | 36 | n_jobs = 10 37 | jobs = Queue() 38 | finished = False 39 | 40 | producer = Thread(target=produce_job, args=[jobs, n_jobs], daemon=True) 41 | consumer1 = Thread(target=consume_job, args=[jobs], daemon=True) 42 | consumer2 = Thread(target=consume_job, args=[jobs], daemon=True) 43 | 44 | producer.start() 45 | consumer1.start() 46 | consumer2.start() 47 | 48 | producer.join() 49 | consumer1.join() 50 | consumer2.join() 51 | 52 | -------------------------------------------------------------------------------- /AdvancedPython/with.py: -------------------------------------------------------------------------------- 1 | ### the object which can be handled by 'with' must have __enter__() and __exit__() methods 2 | 3 | class Sample: 4 | def __enter__(self): 5 | print("enter") 6 | return 0 7 | 8 | def __exit__(self, exc_type, exc_val, exc_tb): ### must have these arguments 9 | ### exc_type is error type; exc_val is error value; exc_tb is the location where the error happened 10 | print("exit") 11 | 12 | 13 | with Sample() as sample: 14 | print("sample", sample) -------------------------------------------------------------------------------- /Algorithm/PrefixSum.py: -------------------------------------------------------------------------------- 1 | ''' 2 | ### Prefix Sum 前缀和 3 | sum(nums[i:j]) = sum(nums[:j]) - sum(nums[:i]) = prefix[j] - prefix[i] 4 | 5 | ### 差分数组 6 | 差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行加减。 7 | diff[0] = nums[0] 8 | diff[i] = nums[i] - nums[i-1] 9 | The original array nums can be retrieved from difference array. 10 | 11 | If we want to add x to nums[i:j], we only need to update diff[i] += x and diff[j+1] -= x 12 | diff[i] += x equals to adding x for nums[i:] 13 | diff[j+1] -= x equals to substracting x for nums[j:] 14 | ''' 15 | 16 | 17 | -------------------------------------------------------------------------------- /Bash/Manual: -------------------------------------------------------------------------------- 1 | chmod [target][-/+/=][permission] filename 2 | 3 | [target] 4 | - u: user 5 | - g: group 6 | - o: other 7 | - a: all 8 | 9 | [permission] 10 | - r: read 100 4 11 | - w: write 010 2 12 | - x: execute 001 1 13 | 14 | -------------------------------------------------------------------------------- /Bash/log.py: -------------------------------------------------------------------------------- 1 | import time 2 | import datetime 3 | import logging 4 | import sys 5 | import os 6 | 7 | 8 | ### [INFO] 2022/09/17 23:13:58 "GET / HTTP/1.1" 200 "address: https://www.baidu.com" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)" 9 | ### [WARNING] 2022/09/17 23:13:60 "GET / HTTP/1.1" 404 "address: https://www.google.com" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)" 10 | def log(type="INFO"): 11 | addr_1 = "https://www.baidu.com" 12 | addr_2 = "https://www.google.com" 13 | content = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)" 14 | 15 | addr = addr_1 if type == "INFO" else addr_2 16 | status = 200 if type == "INFO" else 404 17 | 18 | curTime = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S') 19 | 20 | return f"[{type}] {curTime} \"GET / HTTP/1.1\" {status} \"address: {addr}\" \"{content}\"\n" 21 | 22 | 23 | N = 30 24 | interval = 5 25 | 26 | filename = "log" 27 | for i in range(N): 28 | with open(filename, 'a+') as file: 29 | file.write(log("INFO" if i % 5 != 0 else "WARNING")) 30 | time.sleep(interval) 31 | file.close() -------------------------------------------------------------------------------- /Bash/script.sh: -------------------------------------------------------------------------------- 1 | LOG_FILE="log" 2 | 3 | ### [INFO] 2022/09/17 23:13:58 "GET / HTTP/1.1" 200 "address: https://www.google.com" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)" 4 | ### [WARNING] 2022/09/17 23:13:60 "GET / HTTP/1.1" 404 "address: https://www.google.com.cn" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)" 5 | 6 | ### Filter keyword from log flow 7 | tail -f "$LOG_FILE" | while read -r line ; do 8 | if [[ $line =~ .*\"GET\ /\ HTTP/1.1\"\ (404)\ \"address:\ (.*)\"\ .*$ ]] 9 | then 10 | echo "${BASH_REMATCH[2]}" ### BASH_REMATCH[0]: the whole string BASH_REMATCH[i] the ith group (i>0) 11 | fi 12 | done 13 | 14 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ10/JZ10.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ10 斐波那契数列 3 | 4 | 描述: 5 | 大家都知道斐波那契数列,现在要求输入一个正整数 n ,请你输出斐波那契数列的第 n 项。 6 | ''' 7 | 8 | # @param n int整型 9 | # @return int整型 10 | 11 | ### Replicated computation TC: O(2^n) 12 | class Solution: 13 | def Fibonacci(self, n): 14 | if n <= 2: 15 | return 1 16 | return self.Fibonacci(n-1) + self.Fibonacci(n-2) 17 | 18 | ### TC: O(n) and SC: O(n) 19 | class Solution: 20 | def __init__(self): 21 | self.DP_table = [0] * 50 22 | 23 | def Fibonacci(self , n): 24 | if n <= 2: 25 | return 1 26 | if self.DP_table[n] > 0: 27 | return self.DP_table[n] 28 | else: 29 | self.DP_table[n] = self.Fibonacci(n-1) + self.Fibonacci(n-2) 30 | return self.DP_table[n] 31 | 32 | ### TC: O(n) and SC: O(1) 33 | class Solution: 34 | def Fibonacci(self, n): 35 | if n <= 2: 36 | return 1 37 | prev1 = 1 38 | prev2 = 1 39 | ans = None 40 | for i in range(3, n+1): 41 | ans = prev1 + prev2 42 | prev1, prev2 = prev2, ans 43 | return ans -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ14/JZ14.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ14 剪绳子 3 | 4 | 描述: 5 | 6 | 给你一根长度为 n 的绳子,请把绳子剪成整数长的 m 段( m 、 n 都是整数, n > 1 并且 m > 1 , m <= n ), 7 | 每段绳子的长度记为 k[1],...,k[m] 。请问 k[1]*k[2]*...*k[m] 可能的最大乘积是多少? 8 | 例如,当绳子的长度是 8 时,我们把它剪成长度分别为 2、3、3 的三段,此时得到的最大乘积是 18 。 9 | ''' 10 | 11 | # @param number int 12 | # @return int 13 | 14 | ### TC: O(n^2) and SC: O(n) 15 | class Solution: 16 | DP_table = [0] * 60 17 | def cutRope(self, number): ### return DP[n], if DP[n] is empty, it will update DP[n] 18 | if number <= 2: 19 | return 1 20 | if self.DP_table[number] > 0: ### DP[n] has been calculated 21 | return self.DP_table[number] 22 | else: 23 | MAX = 0 24 | for i in range(1, number): ### how long can one cut be (1 <= cut < number) 25 | MAX = max(MAX, i * max(self.cutRope(number-i), number-i)) ### trick: i * max(self.cutRope(number-i), number-i) 26 | ### cutRope(n) will return DP[n], if DP[n] is empty, it will calculate DP[n] 27 | ### DP[n] at least cut one time, so we need i * max(cutRope(number-i), number-i). number - i means no cut 28 | self.DP_table[number] = MAX 29 | return MAX 30 | 31 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ15/JZ15.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ15 二进制中1的个数 3 | 4 | 描述: 5 | 输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。 6 | ''' 7 | 8 | ''' 9 | 正数和0 的补码就是该数字本身。 负数的补码则是将其对应正数按位取反再加1,代码实现:n & 0xffffffff。 10 | 补码系统的最大优点是可以在加法或减法处理中,不需因为数字的正负而使用不同的计算方式。 11 | ''' 12 | 13 | # @param n int 14 | # @return int 15 | 16 | class Solution: 17 | def NumberOf1(self, n): 18 | ans = 0 19 | if n<0: 20 | n = n & 0xffffffff ### Negative number converted to Two's complement 21 | while n != 0: 22 | if n & 1: 23 | ans += 1 24 | n = n >> 1 25 | return ans -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ16/JZ16.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ16 数值的整数次方 3 | 描述: 4 | 实现函数 double Power(double base, int exponent),求base的exponent次方。 5 | ''' 6 | 7 | # @param base float 8 | # @param exponent int 9 | # @return float 10 | 11 | ### TC: O(logn) and SC: O(1) 12 | class Solution: 13 | def Power(self, base, exponent): 14 | if exponent < 0: 15 | base = 1/base 16 | exponent = -exponent 17 | 18 | ''' 19 | Fast Power: 20 | bin(11) = '0b1011' 21 | a^11 = a^(2^0) * a^(2^1) * a^(2^3) 22 | = a * a^2 * a^2^2^2 23 | ''' 24 | def fastPower(b, n): 25 | ans = 1 26 | while n: 27 | if n&1: ### last bit is 1 28 | ans *= b 29 | b *= b ### base 30 | n >>= 1 31 | return ans 32 | 33 | return fastPower(base, exponent) 34 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ17/JZ17.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ17 打印从1到最大的n位数 3 | 4 | 描述: 5 | 输入正整数 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。 6 | 用返回一个整数列表来代替打印 7 | ''' 8 | 9 | # @param n int 10 | # @return List[int] 11 | 12 | class Solution: 13 | def printNumbers(self, n): 14 | N = 10**n 15 | res = [] 16 | for i in range(1,N): 17 | res.append(i) 18 | return res -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ18/JZ18.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ18 删除链表的节点 3 | 4 | 描述: 5 | 给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。返回删除后的链表的头节点。链表中节点的值互不相同。 6 | ''' 7 | 8 | # class ListNode: 9 | # def __init__(self, x): 10 | # self.val = x 11 | # self.next = None 12 | 13 | # @param head ListNode 14 | # @param val int 15 | # @return ListNode 16 | 17 | class Solution: 18 | def deleteNode(self, head, val): 19 | if head.val == val: ### corner case 20 | return head.next 21 | prev = head 22 | cur = head.next 23 | while cur: 24 | if cur.val == val: 25 | prev.next = cur.next 26 | del cur ### c/c++ style 27 | break 28 | prev = cur 29 | cur = cur.next 30 | return head -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ20/JZ20.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ20 表示数值的字符串 3 | 4 | 描述: 5 | 请实现一个函数用来判断字符串str是否表示数值(包括科学计数法的数字,小数和整数)。 6 | 7 | 科学计数法的数字(按顺序)可以分成以下几个部分: 8 | 1.若干空格 9 | 2.一个整数或者小数 10 | 3.(可选)一个 'e' 或 'E' ,后面跟着一个整数(可正可负) 11 | 4.若干空格 12 | 13 | 小数(按顺序)可以分成以下几个部分: 14 | 1.若干空格 15 | 2.(可选)一个符号字符('+' 或 '-') 16 | 3. 可能是以下描述格式之一: 17 | 3.1 至少一位数字,后面跟着一个点 '.' 18 | 3.2 至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字 19 | 3.3 一个点 '.' ,后面跟着至少一位数字 20 | 4.若干空格 21 | 22 | 整数(按顺序)可以分成以下几个部分: 23 | 1.若干空格 24 | 2.(可选)一个符号字符('+' 或 '-') 25 | 3. 至少一位数字 26 | 4.若干空格 27 | ''' 28 | 29 | import re 30 | 31 | class Solution: 32 | def isNumeric(self, str): 33 | match_Obj = re.match('^\s*[+-]{0,1}((\d)+((\.)(\d)+){0,1}|((\.)(\d)+)|((\d)+(\.)))([eE][+-]{0,1}[\d]+){0,1}\s*$',str) 34 | if match_Obj: 35 | return True 36 | else: 37 | return False -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ21/JZ21.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ21 调整数组顺序使奇数位于偶数前面(一) 3 | 4 | 描述: 5 | 输入一个长度为 n 整数数组,数组里面不含有相同的元素,实现一个函数来调整该数组中数字的顺序, 6 | 使得所有的奇数位于数组的前面部分,所有的偶数位于数组的后面部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。 7 | ''' 8 | 9 | # @param array List[int] 10 | # @return List[int] 11 | 12 | ### TC: O(n) and SC: O(n) 13 | class Solution: 14 | def reOrderArray(self, array): 15 | odd = [] 16 | even = [] 17 | for i in range(len(array)): 18 | if array[i] % 2 ==0: 19 | even.append(array[i]) 20 | else: 21 | odd.append(array[i]) 22 | return odd + even 23 | 24 | 25 | ### TC: O(n^2) and SC: O(1) 26 | class Solution: 27 | def reOrderArray(self, array): 28 | loc = -1 # last odd location 29 | for i in range(len(array)): 30 | if array[i] % 2 == 1: # odd 31 | odd = array[i] 32 | for j in range(i-1, loc, -1): ### trick: move from right to left to maintain the relative position 33 | array[j+1] = array[j] ### shift all even numbers 34 | loc += 1 35 | array[loc] = odd 36 | 37 | return array 38 | 39 | 40 | class Solution: 41 | def reOrderArray(self, array): 42 | loc = 0 43 | for i in range(len(array)): 44 | if array[i] % 2 == 1: # odd 45 | odd = array[i] 46 | for j in range(i-1, loc-1, -1): ### trick: move from right to left to maintain the relative position 47 | array[j+1] = array[j] ### shift all even numbers 48 | array[loc] = odd 49 | loc += 1 50 | return array -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ22/JZ22.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ22 链表中倒数最后k个结点 3 | 4 | 描述: 5 | 输入一个长度为 n 的链表,返回该链表中倒数第k个节点。 6 | 如果该链表长度小于k,请返回一个长度为 0 的链表。 7 | ''' 8 | 9 | # class ListNode: 10 | # def __init__(self, x): 11 | # self.val = x 12 | # self.next = None 13 | 14 | # @param pHead ListNode 15 | # @param k int 16 | # @return ListNode 17 | 18 | ### Intuitive Stack Solution 19 | ### TC: O(n) and SC: O(n) 20 | class Solution: 21 | def FindKthToTail(self, pHead, k): 22 | stack = [] 23 | cur = pHead 24 | while cur: 25 | stack.append(cur) 26 | cur = cur.next 27 | if len(stack) < k or k == 0: ### corner cases 28 | return None 29 | else: 30 | return stack[-k] 31 | 32 | ### Fast and Slow Pointer Solution 33 | ### TC: O(n) and SC: O(1) 34 | class Solution: 35 | def FindKthToTail(self, pHead, k): 36 | if k == 0 or not pHead: ### corner case 37 | return None 38 | 39 | fast = pHead 40 | for i in range(k): 41 | if not fast: 42 | return None 43 | fast = fast.next 44 | 45 | slow = pHead 46 | while fast: 47 | slow = slow.next 48 | fast = fast.next 49 | 50 | return slow 51 | 52 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ23/JZ23.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ23 链表中环的入口结点 3 | 4 | 描述: 5 | 给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。 6 | ''' 7 | 8 | ''' 9 | If the purpose of using the fast & slow pointer is to find the cycle in a linked list, it is very intuitive to set the stride of fast pointer as 2. 10 | S1 = a + b + x*cycle 11 | S2 = v2/v1 * S1 = a + b + y*cycle 12 | (v2/v1 - 1)*S1 = (y-x)*cycle 13 | We don't want to waste resource. So, the x should be 0. To ensure the divisibility, v2/v1 - 1 should be 1. 14 | 15 | Stop as the same node and catch up and then surpass both can prove two pointers meet. 16 | But surpassing case need extra space to record the nodes pointers visit each stride. 17 | 18 | a b 19 | 20 | -[ ] - [ ] - [ ] - [ ] - [ ] - [ ] 21 | | | 22 | [ ] [ ] 23 | | | 24 | [ ] - [ ] - [ ] 25 | 26 | ''' 27 | 28 | # class ListNode: 29 | # def __init__(self, x): 30 | # self.val = x 31 | # self.next = None 32 | 33 | # @param pHead ListNode 34 | # @return ListNode 35 | 36 | ### TC: O(n) and SC: O(1) 37 | class Solution: 38 | def EntryNodeOfLoop(self, pHead): 39 | slow = pHead 40 | fast = pHead 41 | hasCycle = False 42 | while fast and fast.next: 43 | slow = slow.next 44 | fast = fast.next.next 45 | if slow == fast: 46 | hasCycle = True 47 | break 48 | if hasCycle: 49 | fast = pHead 50 | while slow != fast: 51 | slow = slow.next 52 | fast = fast.next 53 | return fast 54 | else: 55 | return None -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ24/JZ24.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ24 反转链表 3 | 4 | 描述: 5 | 给定一个单链表的头结点pHead,长度为n,反转该链表后,返回新链表的表头。 6 | ''' 7 | 8 | # class ListNode: 9 | # def __init__(self, x): 10 | # self.val = x 11 | # self.next = None 12 | 13 | # @param head ListNode 14 | # @return ListNode 15 | 16 | ### TC: O(n) and SC: O(1) 17 | class Solution: 18 | def ReverseList(self, head): 19 | temp = ListNode(None) 20 | prev = None 21 | cur = head 22 | while cur: 23 | temp.next = cur 24 | cur = cur.next 25 | temp.next.next = prev 26 | prev = temp.next 27 | return temp.next -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ25/JZ25.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JC25 合并两个排序的链表 3 | 4 | 描述: 5 | 输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。 6 | ''' 7 | 8 | # class ListNode: 9 | # def __init__(self, x): 10 | # self.val = x 11 | # self.next = None 12 | 13 | # @param pHead1 ListNode 14 | # @param pHead2 ListNode类 15 | # @return ListNode 16 | 17 | ### TC: O(n) and SC: O(1) 18 | class Solution: 19 | def Merge(self, pHead1, pHead2): 20 | 21 | temp = ListNode(None) 22 | cur = temp 23 | 24 | while pHead1 and pHead2: 25 | if pHead1.val < pHead2.val: 26 | cur.next = pHead1 27 | pHead1 = pHead1.next 28 | else: 29 | cur.next = pHead2 30 | pHead2 = pHead2.next 31 | cur = cur.next 32 | 33 | if pHead1: 34 | cur.next = pHead1 35 | else: 36 | cur.next = pHead2 37 | 38 | return temp.next 39 | 40 | 41 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ26/JZ26.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ26 树的子结构 3 | 4 | 描述: 5 | 输入两棵二叉树A,B,判断B是不是A的子结构。(我们约定空树不是任意一个树的子结构) 6 | ''' 7 | 8 | # class TreeNode: 9 | # def __init__(self, x): 10 | # self.val = x 11 | # self.left = None 12 | # self.right = None 13 | 14 | # @param pRoot1 TreeNode 15 | # @param pRoot2 TreeNode 16 | # @return bool 17 | 18 | ### TC: O(mn) and SC: O(n) 19 | class Solution: 20 | def HasSubtree(self, pRoot1, pRoot2): 21 | def isSame(p1, p2): 22 | if p1: ### p2 must not be None 23 | if p1.val == p2.val: 24 | left = isSame(p1.left, p2.left) if p2.left else True 25 | right = isSame(p1.right, p2.right) if p2.right else True 26 | return left and right 27 | 28 | else: 29 | return False 30 | else: ### p2 must not be None, so if p1 is None, return False 31 | return False 32 | 33 | if pRoot2 is None: ### corner case: empty tree is not considered as a sub-tree 34 | return False 35 | 36 | if pRoot1: 37 | res = False 38 | if pRoot1.val == pRoot2.val: 39 | res = isSame(pRoot1, pRoot2) 40 | if not res: 41 | res = self.HasSubtree(pRoot1.left, pRoot2) 42 | if not res: 43 | res = self.HasSubtree(pRoot1.right, pRoot2) 44 | return res 45 | else: 46 | return False -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ27/JZ27.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ27 二叉树的镜像 3 | 4 | 描述: 5 | 操作给定的二叉树,将其变换为原二叉树的镜像。 6 | ''' 7 | 8 | # class TreeNode: 9 | # def __init__(self, x): 10 | # self.val = x 11 | # self.left = None 12 | # self.right = None 13 | 14 | # @param pRoot TreeNode 15 | # @return TreeNode 16 | 17 | ### TC: O(n) and SC: O(n) 18 | class Solution: 19 | def Mirror(self, pRoot): 20 | if pRoot: 21 | pRoot.left, pRoot.right = pRoot.right, pRoot.left 22 | self.Mirror(pRoot.left) 23 | self.Mirror(pRoot.right) 24 | 25 | return pRoot -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ28/JZ28.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ28 对称的二叉树 3 | 4 | 描述: 5 | 给定一棵二叉树,判断其是否是自身的镜像(即:是否对称) 6 | ''' 7 | 8 | # class TreeNode: 9 | # def __init__(self, x): 10 | # self.val = x 11 | # self.left = None 12 | # self.right = None 13 | 14 | # @param pRoot TreeNode 15 | # @return bool 16 | 17 | class Solution: 18 | def isSymmetrical(self, pRoot): 19 | def mirror(r1, r2): 20 | if r1 and r2: 21 | if r1.val == r2.val: 22 | return mirror(r1.left, r2.right) and mirror(r1.right, r2.left) 23 | else: 24 | return False 25 | elif r1 or r2: 26 | return False 27 | else: 28 | return True 29 | return mirror(pRoot, pRoot) -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ29/JZ29.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ29 顺时针打印矩阵 3 | 4 | 描述: 5 | 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。 6 | ''' 7 | 8 | # @param matrix List[List[int]] 9 | # @return List[int] 10 | 11 | class Solution: 12 | def printMatrix(self, matrix): 13 | ans = [] 14 | 15 | h, w = len(matrix), len(matrix[0]) 16 | up = 0 17 | bottom = h-1 18 | left = 0 19 | right = w-1 20 | 21 | while len(ans) < h*w: ### Trick 1: loop end condition 22 | ''' 23 | Trick 2: 24 | —————————— 25 | | | 26 | | | 27 | | | 28 | —————————— 29 | ''' 30 | for i in range(left, right+1): ### print whole up line (to avoid dead lock) 31 | ans.append(matrix[up][i]) 32 | for i in range(up+1, bottom): 33 | ans.append(matrix[i][right]) 34 | if bottom > up: ### Trick 3: avoid replicated print 35 | for i in range(right, left-1, -1): 36 | ans.append(matrix[bottom][i]) 37 | if left < right: 38 | for i in range(bottom-1, up, -1): 39 | ans.append(matrix[i][left]) 40 | up += 1 41 | bottom -= 1 42 | left += 1 43 | right -= 1 44 | return ans -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ30/JZ30.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ30 包含min函数的栈 3 | 4 | 描述: 5 | 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的 min 函数,输入操作时保证 pop、top 和 min 函数操作时,栈中一定有元素。 6 | 此栈包含的方法有: 7 | push(value):将value压入栈中 8 | pop():弹出栈顶元素 9 | top():获取栈顶元素 10 | min():获取栈中最小元素 11 | ''' 12 | 13 | ''' 14 | | | | | 15 | | | | | 16 | | | | | 17 | | 4 | | 4 | 18 | |—————| |—————| 19 | stack min 20 | 21 | | | | | 22 | | | | | 23 | | 2 | | 2 | 24 | | 4 | | 4 | 25 | |—————| |—————| 26 | stack min 27 | 28 | | | | | 29 | | 3 | | 2 | 30 | | 2 | | 2 | 31 | | 4 | | 4 | 32 | |—————| |—————| 33 | stack min 34 | 35 | | 1 | | 1 | 36 | | 3 | | 2 | 37 | | 2 | | 2 | 38 | | 4 | | 4 | 39 | |—————| |—————| 40 | stack min 41 | 42 | ''' 43 | 44 | ### TC: O(1) and SC: O(n) 45 | class Solution: 46 | 47 | stack = [] 48 | MIN = [] 49 | 50 | def push(self, node): 51 | if len(self.stack) == 0: 52 | self.MIN.append(node) 53 | else: 54 | self.MIN.append(min(node, self.MIN[-1])) 55 | self.stack.append(node) 56 | 57 | def pop(self): 58 | self.MIN.pop() 59 | return self.stack.pop() 60 | 61 | def top(self): 62 | return self.stack[-1] 63 | 64 | def min(self): 65 | return self.MIN[-1] -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ31/JZ31.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ31 栈的压入、弹出序列 3 | 4 | 描述: 5 | 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。 6 | popV 的所有数字均在 pushV里面出现过 7 | pushV 的所有数字均不相同 8 | 9 | input : [1,2,3,4,5] [4,5,3,2,1] 10 | output: True 11 | 可以通过 push(1)=>push(2)=>push(3)=>push(4)=>pop()=>push(5)=>pop()=>pop()=>pop()=>pop() 12 | ''' 13 | 14 | # @param pushV List[int] 15 | # @param popV List[int] 16 | # @return bool 17 | 18 | ''' 19 | Simulate the push process and maintain the stack. When a number is pushed, check the popV whether the number is popped immediately. 20 | If any pop happened, check whether other value in popV can be popped from the stack 21 | ''' 22 | 23 | ### TC: O(n) and SC: O(n) 24 | class Solution: 25 | def IsPopOrder(self, pushV, popV): 26 | stack = [] 27 | j = 0 28 | for i in range(len(pushV)): ### We are simulating the push process, so we iterate through the pushV 29 | if pushV[i] == popV[j]: 30 | j += 1 31 | while len(stack) > 0 and stack[-1] == popV[j]: ### keep popping if possible 32 | stack.pop() 33 | j += 1 34 | else: 35 | stack.append(pushV[i]) 36 | 37 | for i in range(len(stack)): 38 | if popV[j] == stack.pop(): 39 | j += 1 40 | else: 41 | return False 42 | 43 | return True 44 | 45 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ32/JZ32.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ32 从上往下打印二叉树 3 | 4 | 描述: 5 | 不分行从上往下打印出二叉树的每个节点,同层节点从左至右打印。 6 | ''' 7 | 8 | # class TreeNode: 9 | # def __init__(self, x): 10 | # self.val = x 11 | # self.left = None 12 | # self.right = None 13 | 14 | # @param root TreeNode 15 | # @return List[int] 16 | 17 | ### TC: O(n) and SC: O(n) 18 | class Solution: 19 | def PrintFromTopToBottom(self , root): 20 | res = [] 21 | queue = [] 22 | 23 | if root is None: ### corner case 24 | return res 25 | 26 | queue.append(root) 27 | while queue: 28 | cur = queue.pop(0) 29 | res.append(cur.val) 30 | if cur.left: 31 | queue.append(cur.left) 32 | if cur.right: 33 | queue.append(cur.right) 34 | 35 | return res 36 | 37 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ36/JZ36.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ36 二叉搜索树与双向链表 3 | 4 | 描述: 5 | 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。 6 | ''' 7 | 8 | # class TreeNode: 9 | # def __init__(self, x): 10 | # self.val = x 11 | # self.left = None 12 | # self.right = None 13 | 14 | # @param pRootOfTree TreeNode 15 | # @return TreeNode 16 | 17 | ''' 18 | The inorder traversal sequence of a binary search tree is sorted. 19 | So what we need to do is to inorder traverse the binary search tree and link the node with its predecessor 20 | ''' 21 | ### TC: O(n) and SC: O(1) 22 | class Solution: 23 | prev = None 24 | def Convert(self, pRootOfTree): 25 | 26 | def inorder(node): 27 | if node is None: 28 | return 29 | else: 30 | inorder(node.left) 31 | node.left = self.prev ### handle the link 32 | if self.prev: 33 | self.prev.right = node ### handle the link 34 | self.prev = node ### update prev 35 | inorder(node.right) 36 | 37 | 38 | if pRootOfTree is None: ### corner case: empty tree 39 | return None 40 | 41 | MIN = pRootOfTree ### the leftmost node is the head of the linked list 42 | while MIN.left: 43 | MIN = MIN.left 44 | 45 | inorder(pRootOfTree) 46 | 47 | return MIN 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ38/JZ38.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ38 字符串的排列 3 | 4 | 描述: 5 | 输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组。 6 | ''' 7 | 8 | # @param string str 9 | # @return List[str] 10 | 11 | from collections import Counter 12 | 13 | class Solution: 14 | def Permutation(self , string): 15 | ans = [] 16 | def forward(perm, counter): 17 | if len(perm) == len(string): 18 | ans.append(perm) 19 | else: 20 | for char in counter: 21 | if counter[char] > 0: 22 | counter[char] -= 1 23 | forward(perm + char, counter) 24 | counter[char] += 1 25 | forward("", Counter(string)) 26 | return ans -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ39/JZ39.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ39 数组中出现次数超过一半的数字 3 | 4 | 描述: 5 | 给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 6 | ''' 7 | 8 | # @param numbers List[int] 9 | # @return int 10 | 11 | 12 | ### Intuitive solutions: 1. Hash Table 2. Sort 13 | 14 | ''' 15 | Candidate Solution: 16 | If a number occupies more than half of the array, it can use the 'perish together' strategy to beat all other numbers. 17 | ''' 18 | ### TC: O(n) and SC: O(1) 19 | class Solution: 20 | def MoreThanHalfNum_Solution(self, numbers): 21 | candidate = None 22 | vote = 0 23 | 24 | for n in numbers: 25 | if vote == 0: 26 | candidate = n 27 | vote += 1 28 | else: 29 | if candidate != n: 30 | vote -= 1 31 | else: 32 | vote += 1 33 | 34 | winCondition = len(numbers) // 2 35 | k = 0 36 | ### check whether the candidate is the mode 37 | for n in numbers: 38 | if n == candidate: 39 | k += 1 40 | if k >= winCondition: 41 | return candidate 42 | return -1 ### there is no number whose occuring times are more than half the length of the array 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ4/JZ4.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ4 二维数组中的查找 3 | 4 | 描述: 5 | 在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 6 | [ 7 | [1,2,8,9], 8 | [2,4,9,12], 9 | [4,7,10,13], 10 | [6,8,11,15] 11 | ] 12 | 给定 target = 7,返回 true。 13 | 给定 target = 3,返回 false。 14 | ''' 15 | 16 | # @param target int 17 | # @param array List[List[int]] 18 | # @return bool 19 | 20 | ''' 21 | Searching all kinds of sorted arrays should be implemented with binary search. 22 | The key to this problem is to find the pivot (which we can help us know which side to go. 23 | Arr 0 1 2 3 4 24 | 0 < < < < pivot 25 | 1 > 26 | 2 > 27 | 3 tar > 28 | 4 > 29 | 30 | We can eliminate one row or column at a time. 31 | ''' 32 | 33 | ### TC: O(n+m) and SC: O(1) 34 | class Solution: 35 | def Find(self, target, array): 36 | h, w = len(array), len(array[0]) 37 | i, j = 0, w-1 38 | while i < h and j >= 0: ### start at right-upper corner of the array 39 | pivot = array[i][j] 40 | if pivot == target: 41 | return True 42 | elif pivot < target: ### go down 43 | i += 1 44 | else: # pivot > target ### go left 45 | j -= 1 46 | return False 47 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ42/JZ42.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ42 连续子数组的最大和 3 | 4 | 描述: 5 | 输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。 6 | ''' 7 | 8 | # @param array List[int] 9 | # @return int 10 | 11 | ### TC: O(n) and SC: O(1) 12 | class Solution: 13 | def FindGreatestSumOfSubArray(self, array): 14 | MAX = array[0] 15 | cur = array[0] 16 | 17 | for n in array[1:]: 18 | cur = max(n, cur+n) 19 | MAX = max(cur, MAX) 20 | return MAX 21 | 22 | ''' 23 | Intuitive DP Solution 24 | DP[i] Maximum sum of sub-array ending at i ### the key point: sub-array ending at i 25 | State transition equation: DP[i] = max(DP[i-1]+array[i], array[i]) 26 | ''' 27 | ### TC: O(n) and SC: O(n) 28 | class Solution: 29 | def FindGreatestSumOfSubArray(self, array): 30 | DP_table = [0]*len(array) 31 | DP_table[0] = array[0] 32 | for i in range(1, len(array)): 33 | DP_table[i] = max(array[i], DP_table[i-1] + array[i]) 34 | return max(DP_table) -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ43/JZ43.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ43 整数中1出现的次数(从1到n整数中1出现的次数) 3 | 4 | 描述: 5 | 输入一个整数 n ,求 1~n 这 n 个整数的十进制表示中 1 出现的次数 6 | 例如, 1~13 中包含 1 的数字有 1 、 10 、 11 、 12 、 13 因此共出现 6 次 7 | 注意:11 这种情况算两次 8 | ''' 9 | 10 | ''' 11 | 什么几把题,无不无聊。 12 | 13 | 用数学归纳法证明这个规律: 14 | 0-9(1个9)中有1*10^0个1 15 | 0-99(2个9)中有2*10^1个1 16 | 0-999(3个9)中有3*10^2个1 17 | 0-9999(4个9)中有4*10^3个1 18 | ... 19 | ''' 20 | 21 | # @param n int 22 | # @return int 23 | 24 | class Solution: 25 | def NumberOf1Between1AndN_Solution(self, n): 26 | res = 0 27 | for i in range(1,n+1): 28 | while i > 0: 29 | if i % 10 == 1: 30 | res += 1 31 | i = i // 10 32 | return res 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ44/JZ44.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ44 数字序列中某一位的数字 3 | 4 | 描述: 5 | 数字以 0123456789101112131415... 的格式作为一个字符序列,在这个序列中第 2 位(从下标 0 开始计算)是 2 , 6 | 第 10 位是 1 ,第 13 位是 1 ,以此类题,请你输出第 k 位对应的数字。 7 | ''' 8 | 9 | # @param k int 10 | # @return int 11 | 12 | class Solution: 13 | def findNthDigit(self, k): 14 | i = 1 15 | while i * (10 ** i) < k: 16 | k += 10 ** i 17 | i += 1 18 | return int(str(k//i)[k % i]) 19 | 20 | ''' 21 | i 表示当前k位中最高包含到几位数 22 | 比如 k = 9, 1*(10^1) > 9 表示k最多包含到1位数(0123456789) 23 | 如果 k = 12, 1*(10^1) < 12 表示k不只包含了全部的1位数(012345678910) 24 | k += 10^1 是给全部的一位数补一位,补成2位数 25 | k // i代表了补完位数之后,一共有多少个i位数(因为index是从0开始的,所以是k//i) 26 | ''' -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ45/JZ45.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ45 把数组排成最小的数 3 | 4 | 描述: 5 | 输入一个非负整数数组numbers,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。 6 | 例如输入数组[3,32,321],则打印出这三个数字能排成的最小数字为321323。 7 | 1.输出结果可能非常大,所以你需要返回一个字符串而不是整数 8 | 2.拼接起来的数字可能会有前导 0,最后结果不需要去掉前导 0 9 | ''' 10 | 11 | # @param numbers List[int] 12 | # @return str 13 | 14 | ### TC: O(nlogn) and SC: O(n) 15 | import functools ### python3 cancel the sort(cmp = lambda x,y f(x,y)) 16 | def cmp(a,b): 17 | if a+b > b+a: 18 | return 1 19 | elif a+b < b+a: 20 | return -1 21 | else: 22 | return 0 23 | 24 | class Solution: 25 | def PrintMinNumber(self, numbers): 26 | strings = [str(n) for n in numbers] 27 | strings.sort(key=functools.cmp_to_key(cmp)) 28 | return ''.join(strings) -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ46/JZ46.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ46 把数字翻译成字符串 3 | 4 | 描述: 5 | 有一种将字母编码成数字的方式:'a'->1, 'b->2', ... , 'z->26'。 6 | 现在给一串数字,返回有多少种可能的译码结果 7 | ''' 8 | 9 | ''' 10 | 牛客网这题傻逼,册那0都没对应字母 11 | ''' 12 | 13 | # @param nums str 14 | # @return int 15 | 16 | ### TC: O(n) and SC: O(n) 17 | class Solution: 18 | def solve(self, nums): 19 | if nums[0] == '0': ### corner case 20 | return 0 21 | DP_table = [0] * (len(nums)+1) ### DP table can be optimize to O(1) space complexity by only store DP[i-1] and DP[i-2] 22 | DP_table[0], DP_table[1] = 1, 1 ### DP[i] represents until the ith bit, how many kinds of representations 23 | for i in range(1,len(nums)): 24 | if nums[i-1:i+1] == "00": ### so stupid, without considering 0 25 | return 0 26 | 27 | if "11" <= nums[i-1:i+1] and nums[i-1:i+1] <= "26" and nums[i-1:i+1] != "20": ### so stupid, no letter corresponds to 0, so 20 can only be represented by t 28 | DP_table[i+1] = DP_table[i] + DP_table[i-1] 29 | else: 30 | DP_table[i+1] = DP_table[i] 31 | return DP_table[len(nums)] 32 | 33 | ''' 34 | 力扣版本: 35 | 字母编码方式改成:'a'->0, 'b->1', ... , 'z->25'。 36 | ''' 37 | 38 | # @param num int 39 | # @return int 40 | 41 | ### TC: O(n) and SC: O(1) 42 | class Solution: 43 | def translateNum(self, num): 44 | prev_1 = 1 45 | prev_2 = 1 46 | for i in range(1, len(str(num))): 47 | temp = num % 100 48 | if 10 <= temp and temp <= 25: 49 | prev_1, prev_2 = prev_2, prev1+prev_2 50 | else: 51 | prev_1 = prev_2 52 | num = num // 10 53 | return prev_2 -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ47/JZ47.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ47 礼物的最大价值 3 | 4 | 描述 5 | 在一个m×n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。 6 | 你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。 7 | 给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物? 8 | ''' 9 | 10 | # @param grid List[List[int]] 11 | # @return int 12 | 13 | class Solution: 14 | def maxValue(self, grid): 15 | n_row = len(grid) 16 | n_col = len(grid[0]) 17 | DP_table = [[None for _ in range(n_col)] for _ in range(n_row)] 18 | 19 | DP_table[0][0] = grid[0][0] ### initialize the DP_table 20 | ### the agent can only move right or down 21 | for i in range(1, n_row): 22 | DP_table[i][0] = DP_table[i-1][0] + grid[i][0] ### we can assert that the agent can only move down 23 | 24 | for i in range(1, n_col): 25 | DP_table[0][i] = DP_table[0][i-1] + grid[0][i] ### we can assert that the agent can only move right 26 | 27 | for i in range(1, n_row): 28 | for j in range(1, n_col): 29 | DP_table[i][j] = max(DP_table[i-1][j], DP_table[i][j-1]) + grid[i][j] 30 | 31 | return DP_table[n_row-1][n_col-1] -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ48/JZ48.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ48 最长不含重复字符的子字符串 3 | 4 | 描述: 5 | 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。 6 | ''' 7 | 8 | # @param s str 9 | # @return int 10 | 11 | ### Sliding window solution 12 | ### TC: O(n) and SC: O(n) 13 | class Solution: 14 | def lengthOfLongestSubstring(self, s): 15 | MAX = 0 16 | hashTable = [0] * 128 ### ASIIC 17 | j = 0 ### left boundary 18 | for i in range(len(s)): 19 | cur = s[i] 20 | hashTable[ord(cur)] += 1 21 | while hashTable[ord(cur)] > 1: ### keeping narrowing the interval 22 | hashTable[ord(s[j])] -= 1 23 | j += 1 24 | MAX = max(MAX, i - j + 1) 25 | return MAX 26 | 27 | 28 | 29 | ### Skip solution 30 | ### TC: O(n) and SC: O(n) 31 | class Solution: 32 | def lengthOfLongestSubstring(self, s): 33 | MAX = 0 34 | hashTable = [-1] * 128 ### ASIIC 35 | j = 0 ### left boundary 36 | for i in range(len(s)): 37 | cur = s[i] 38 | if hashTable[ord(cur)] >= j: ### the repeated char occurs in the window 39 | j = hashTable[ord(cur)] + 1 40 | hashTable[ord(cur)] = i 41 | MAX = max(MAX, i - j + 1) 42 | return MAX -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ49/JZ49.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ49 丑数 3 | 4 | 描述: 5 | 把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第 n个丑数。 6 | ''' 7 | 8 | # @param index int 9 | # @return int 10 | 11 | ''' 12 | Ugly Number: 2^x*3^y*5^z 13 | ''' 14 | 15 | class Solution: 16 | def GetUglyNumber_Solution(self, index): 17 | ### the first 6 ugly number: 1 2 3 4 5 6 18 | if index <= 6: 19 | return index 20 | 21 | res = [1] 22 | p_2 = 0 ### which res factor 2 should multiply 23 | p_3 = 0 ### which res factor 3 should multiply 24 | p_5 = 0 ### which res factor 5 should multiply 25 | 26 | 27 | ### uglyNum = 2^p_2 * 3^p_3 * 5^p_5 28 | 29 | for i in range(1, index): 30 | nextUglyNum = min(res[p_2]*2, res[p_3]*3, res[p_5]*5) 31 | if nextUglyNum == res[p_2]*2: ### cannot use if else, must use three if to pass over duplicate uglyNum 32 | p_2 += 1 33 | if nextUglyNum == res[p_3]*3: ### cannot use if else, must use three if to pass over duplicate uglyNum 34 | p_3 += 1 35 | if nextUglyNum == res[p_5]*5: ### cannot use if else, must use three if to pass over duplicate uglyNum 36 | p_5 += 1 37 | 38 | res.append(nextUglyNum) 39 | 40 | return res[-1] 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ5/JZ5.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ4 二维数组中的查找 3 | 4 | 描述: 5 | 请实现一个函数,将一个字符串s中的每个空格替换成“%20”。 6 | 例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。 7 | ''' 8 | 9 | # @param s string 10 | # @return string 11 | 12 | ### TC: O(n) and SC: O(n) 13 | class Solution: 14 | def replaceSpace(self, s): 15 | chars = s.split(' ') 16 | return "%20".join(chars) -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ50/JZ50.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ50 第一个只出现一次的字符 3 | 4 | 描述: 5 | 在一个字符串中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回-1。 6 | ''' 7 | 8 | # @param str string字符串 9 | # @return int整型 10 | 11 | ### TC: O(n) and SC: O(n) 12 | class Solution: 13 | def FirstNotRepeatingChar(self, string): 14 | hashTable = {} 15 | for i in range(len(string)): 16 | char = string[i] 17 | if char in hashTable: 18 | hashTable[char] += 1 19 | else: 20 | hashTable[char] = 1 21 | 22 | for i in range(len(string)): 23 | if hashTable[string[i]] == 1: 24 | return i 25 | return -1 ### corner case -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ52/JZ52.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ52 两个链表的第一个公共结点 3 | 4 | 描述: 5 | 输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。 6 | ''' 7 | 8 | # class ListNode: 9 | # def __init__(self, x): 10 | # self.val = x 11 | # self.next = None 12 | 13 | # @param pHead1 ListNode 14 | # @param pHead2 ListNode 15 | # @return ListNode 16 | 17 | ''' 18 | The first thing we need to do when we are handing linked list is that check whether there could be a cycle. 19 | 20 | l1 21 | [] - [] - [] 22 | \ 23 | [] - [] - [] 24 | / l0 25 | [] - [] 26 | l2 27 | 28 | Two pointers move forward until to the end. When they come to end, start from the other's start. 29 | Both pointers will move l1+l2+l0 when they come to the intersection node. 30 | ''' 31 | 32 | ### TC: O(n) and SC: O(1) 33 | class Solution: 34 | def FindFirstCommonNode(self, pHead1, pHead2): 35 | p1 = pHead1 36 | p2 = pHead2 37 | if p1 is None or p2 is None: ### corner case 38 | return 39 | while p1 != p2: 40 | if p1: 41 | p1 = p1.next 42 | else: 43 | p1 = pHead2 44 | if p2: 45 | p2 = p2.next 46 | else: 47 | p2 = pHead1 48 | return p1 49 | 50 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ54/JZ54.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ54 二叉搜索树的第k个节点 3 | 4 | 5 | 描述: 6 | 给定一棵结点数为n 二叉搜索树,请找出其中的第 k 小的TreeNode结点值。 7 | 1.返回第k小的节点值即可 8 | 2.不能查找的情况,如二叉树为空,则返回-1,或者k大于n等等,也返回-1 9 | 3.保证n个节点的值不一样 10 | ''' 11 | 12 | # class TreeNode: 13 | # def __init__(self, x): 14 | # self.val = x 15 | # self.left = None 16 | # self.right = None 17 | 18 | # @param proot TreeNode 19 | # @param k int 20 | # @return int 21 | 22 | ### TC: O(n) and SC: O(n) 23 | class Solution: 24 | n = 0 25 | def KthNode(self, proot, k): 26 | self.n = 0 27 | def inorder(root): 28 | if root: 29 | temp = inorder(root.left) 30 | if temp != -1: 31 | return temp 32 | self.n += 1 33 | if self.n == k: 34 | return root.val 35 | temp = inorder(root.right) 36 | if temp != -1: 37 | return temp 38 | return -1 39 | return inorder(proot) 40 | 41 | 42 | ### Non-recursive version 43 | class Solution: 44 | def KthNode(self, proot, k): 45 | if proot: 46 | n = 0 47 | stack = [proot] 48 | nextToVisit = proot 49 | 50 | while stack: 51 | while nextToVisit.left: 52 | stack.append(nextToVisit.left) 53 | nextToVisit = nextToVisit.left 54 | 55 | cur = stack.pop() 56 | n += 1 57 | if n == k: 58 | return cur.val 59 | 60 | if cur.right: 61 | stack.append(cur.right) 62 | nextToVisit = cur.right 63 | 64 | return -1 -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ55/JZ55.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ55 二叉树的深度 3 | 4 | 描述: 5 | 输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度,根节点的深度视为 1 。 6 | ''' 7 | 8 | # class TreeNode: 9 | # def __init__(self, x): 10 | # self.val = x 11 | # self.left = None 12 | # self.right = None 13 | 14 | # @param pRoot TreeNode 15 | # @return int 16 | 17 | ### TC: O(n) and SC: O(n) 18 | class Solution: 19 | def TreeDepth(self, pRoot): 20 | if pRoot: 21 | return max(self.TreeDepth(pRoot.left), self.TreeDepth(pRoot.right)) + 1 22 | else: 23 | return 0 24 | 25 | class Solution: 26 | res = 0 27 | def TreeDepth(self, pRoot): 28 | self.res = 0 29 | def DFS(node, depth): 30 | if node: 31 | self.res = max(self.res, depth + 1) 32 | DFS(node.left, depth + 1) 33 | DFS(node.right, depth + 1) 34 | DFS(pRoot, 0) 35 | return self.res 36 | 37 | class Solution: 38 | def TreeDepth(self, pRoot): 39 | if pRoot is None: ### corner case: empty tree 40 | return 0 41 | 42 | stack = [(pRoot, 1)] 43 | MAX_depth = float("-inf") 44 | while stack: 45 | node, depth = stack.pop() 46 | if node.left or node.right: 47 | if node.left: 48 | stack.append((node.left, depth+1)) 49 | if node.right: 50 | stack.append((node.right, depth+1)) 51 | else: 52 | MAX_depth = max(MAX_depth, depth) 53 | return MAX_depth 54 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ56/JZ56.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ56 数组中只出现一次的两个数字 3 | 4 | 描述: 5 | 一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 6 | 7 | 提示:输出时按非降序排列。 8 | ''' 9 | 10 | # @param array List[int] 11 | # @return List[int] 12 | 13 | ### Intuitive Solution: Hash Table: TC: O(n) but SC: O(n) and Sort: SC: O(1) but TC: O(nlogn) 14 | class Solution: 15 | def FindNumsAppearOnce(self, array): 16 | hashTable = {} 17 | for num in array: 18 | if num in hashTable: 19 | hashTable[num] += 1 20 | else: 21 | hashTable[num] = 1 22 | ans = [] 23 | for num in hashTable: 24 | if hashTable[num] == 1: 25 | ans.append(num) 26 | return sorted(ans) 27 | 28 | 29 | ''' 30 | A XOR 0 = A 31 | A XOR A = 0 32 | A XOR B = B XOR A 33 | (A XOR B) XOR C = A XOR (B XOR C) 34 | ''' 35 | ### If there is only one number occurs once(LC136), we can use XOR to achieve TC O(n) and SC O(1) 36 | def findNumsAppearOnce(array): 37 | res = 0 38 | for num in array: 39 | res ^= num 40 | return res 41 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ57/JZ57.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ57 和为S的两个数字 3 | 4 | 描述: 5 | 输入一个递增排序的数组array和一个数字S,在数组中查找两个数,使得他们的和正好是S, 6 | 如果有多对数字的和等于S,返回任意一组即可,如果无法找出这样的数字,返回一个空数组即可。 7 | ''' 8 | 9 | # @param array List[int] 10 | # @param s int 11 | # @return List[int] 12 | 13 | ### TC: O(n) and SC: O(1) 14 | class Solution: 15 | def FindNumbersWithSum(self, array, s): 16 | ### since the array is sorted, we can use two pointers 17 | lp = 0 18 | rp = len(array) - 1 19 | ans = [] 20 | while lp < rp: 21 | if array[lp] + array[rp] > s: 22 | rp -= 1 23 | elif array[lp] + array[rp] < s: 24 | lp += 1 25 | else: 26 | ans = [array[lp], array[rp]] 27 | break 28 | return ans -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ58/JZ58.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ58 左旋转字符串 3 | 4 | 描述: 5 | 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列 S , 6 | 请你把其循环左移 K 位后的序列输出。例如,字符序列 S = ”abcXYZdef” , 要求输出循环左移 3 位后的结果,即 “XYZdefabc” 7 | ''' 8 | 9 | # @param string str 10 | # @param n int 11 | # @return str 12 | 13 | ### TC: O(n) and SC: O(n) 14 | class Solution: 15 | def LeftRotateString(self, string, n): 16 | if len(string) <= 1: ### corner case 17 | return string 18 | for i in range(n): 19 | string = string[1:] + string[0] 20 | return string -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ59/JZ59.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ59 滑动窗口的最大值 3 | 4 | 描述: 5 | 给定一个长度为 n 的数组 num 和滑动窗口的大小 size ,找出所有滑动窗口里数值的最大值。 6 | 7 | 例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 8 | 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: 9 | {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。 10 | 11 | 窗口大于数组长度或窗口长度为0的时候,返回空。 12 | ''' 13 | 14 | # @param nums List[int] 15 | # @param size int 16 | # @return List[int] 17 | 18 | ### TC: O(n) and SC: O(k) 19 | class Solution: 20 | def maxInWindows(self, nums, size): 21 | if len(nums) == 0 or size == 0: ### corner case 22 | return [] 23 | ans = [] 24 | 25 | aux = [] ### maintain a sorted sliding window, storing the index of the number 26 | 27 | for i in range(len(nums)): 28 | ### maintain aux array sorted 29 | while aux and nums[aux[-1]] < nums[i]: 30 | aux.pop() ### this numbers are not important, we only care the max in current window 31 | aux.append(i) ### store the index 32 | 33 | ### check whether the max is expired 34 | if aux[0] + size == i: 35 | aux.pop(0) 36 | 37 | if i+1 >= size: 38 | ans.append(nums[aux[0]]) 39 | 40 | return ans 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ6/JZ6.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ6 从尾到头打印链表 3 | 4 | 描述: 5 | 输入一个链表的头节点,按链表从尾到头的顺序返回每个节点的值(用数组返回)。 6 | ''' 7 | 8 | # class ListNode: 9 | # def __init__(self, x): 10 | # self.val = x 11 | # self.next = None 12 | 13 | # @param listNode ListNode 14 | # @return List[int] 15 | 16 | ### TC: O(n) and SC: O(n) 17 | class Solution: 18 | def __init__(self): 19 | self.ans = [] 20 | 21 | def traverse(self, listNode): ### recursive 22 | if listNode: 23 | self.traverse(listNode.next) 24 | self.ans.append(listNode.val) 25 | else: 26 | return 27 | 28 | def printListFromTailToHead(self, listNode): 29 | self.traverse(listNode) 30 | return self.ans 31 | 32 | 33 | class Solution: 34 | def printListFromTailToHead(self, listNode): 35 | ans = [] 36 | while listNode: 37 | ans.append(listNode.val) 38 | ans.reverse() 39 | return ans 40 | 41 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ61/JZ61.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ61 扑克牌顺子 3 | 4 | 描述: 5 | 现在有2副扑克牌,从扑克牌中随机五张扑克牌,我们需要来判断一下是不是顺子。 6 | 有如下规则: 7 | 1. A为1,J为11,Q为12,K为13,A不能视为14 8 | 2. 大、小王为 0,0可以看作任意牌 9 | 3. 如果给出的五张牌能组成顺子(即这五张牌是连续的)就输出true,否则就输出false。 10 | 4.数据保证每组5个数字,每组最多含有4个零,数组的数取值为 [0, 13] 11 | ''' 12 | 13 | ''' 14 | 无不无聊啊 15 | ''' 16 | 17 | # @param numbers List[int] 18 | # @return bool 19 | 20 | class Solution: 21 | def IsContinuous(self, numbers): 22 | numbers.sort() 23 | n_zeros = 0 24 | ### check whether there is any duplicate (except for 0) 25 | for i in range(0, 4): 26 | if numbers[i] == 0: 27 | n_zeros += 1 28 | elif numbers[i] == numbers[i+1]: 29 | return False 30 | 31 | gap = 0 32 | for i in range(n_zeros+1, 5): 33 | gap += numbers[i] - numbers[i-1] - 1 34 | 35 | if gap <= n_zeros: 36 | return True 37 | else: 38 | return False 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ63/JZ63.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ63 买卖股票的最好时机(一) 3 | 4 | 5 | 描述: 6 | 假设你有一个数组prices,长度为n,其中prices[i]是股票在第i天的价格,请根据这个价格数组,返回买卖股票能获得的最大收益 7 | 1.你可以买入一次股票和卖出一次股票,并非每天都可以买入或卖出一次,总共只能买入和卖出一次,且买入必须在卖出的前面的某一天 8 | 2.如果不能获取到任何利润,请返回0 9 | 3.假设买入卖出均无手续费 10 | ''' 11 | 12 | # @param prices List[int] 13 | # @return int 14 | 15 | ### TC: O(n) and SC: O(1) 16 | class Solution: 17 | def maxProfit(self, prices): 18 | low = float("inf") 19 | MAX = 0 20 | for p in prices: 21 | low = min(p, low) 22 | MAX = max(MAX, p - low) 23 | return MAX 24 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ64/JZ64.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ64 求1+2+3+...+n 3 | 4 | 描述: 5 | 求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。 6 | ''' 7 | 8 | ''' 9 | 这都是什么几把玩意儿 10 | ''' 11 | 12 | # @param n int 13 | # @return int 14 | 15 | class Solution: 16 | def Sum_Solution(self, n): 17 | ''' 18 | exp1 and exp2 19 | if exp1 == False, exp2 will not be executed 20 | ''' 21 | return n and n + self.Sum_Solution(n-1) ### ex1 and exp2 ... and exp_n will return the exp_n 22 | 23 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ65/JZ65.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ65 不用加减乘除做加法 3 | 4 | 描述: 5 | 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。 6 | ''' 7 | 8 | ''' 9 | 无不无聊啊,我真的操了 10 | ''' 11 | 12 | # @param num1 int 13 | # @param num2 int 14 | # @return int 15 | 16 | class Solution: 17 | def Add(self, num1, num2): 18 | return sum([num1, num2]) -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ67/JZ67.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ67 把字符串转换成整数 3 | 4 | 描述: 5 | 写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。传入的字符串可能有以下部分组成: 6 | 1.若干空格 7 | 2.(可选)一个符号字符('+' 或 '-') 8 | 3. 数字,字母,符号,空格组成的字符串表达式 9 | 4. 若干空格 10 | 11 | 转换算法如下: 12 | 1.去掉无用的前导空格 13 | 2.第一个非空字符为+或者-号时,作为该整数的正负号,如果没有符号,默认为正数 14 | 3.判断整数的有效部分: 15 | 3.1 确定符号位之后,与之后面尽可能多的连续数字组合起来成为有效整数数字,如果没有有效的整数部分,那么直接返回0 16 | 3.2 将字符串前面的整数部分取出,后面可能会存在存在多余的字符(字母,符号,空格等),这些字符可以被忽略,它们对于函数不应该造成影响 17 | 3.3 整数超过 32 位有符号整数范围 [−231, 231 − 1] ,需要截断这个整数,使其保持在这个范围内。 18 | 具体来说,小于 −231的整数应该被调整为 −231 ,大于 231 − 1 的整数应该被调整为 231 − 1 19 | 4.去掉无用的后导空格 20 | ''' 21 | 22 | # @param s str 23 | # @return int 24 | 25 | class Solution: 26 | def StrToInt(self, s): 27 | s = s.strip() ### remove empty space 28 | if not s: ### corner case 29 | return 0 30 | 31 | sign = -1 if s[0] == '-' else 1 32 | if s[0] == '-' or s[0] == '+': 33 | s = s[1:] 34 | 35 | num = 0 36 | for i in s: 37 | if i.isdigit(): 38 | num *= 10 39 | num += ord(i) - 48 ### ASIIC 40 | else: 41 | break 42 | return min(max(sign * num, -2 ** 31), 2 ** 31 - 1) -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ69/JZ69.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ69 跳台阶 3 | 4 | 描述: 5 | 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法(先后次序不同算不同的结果)。 6 | ''' 7 | 8 | # @param number int 9 | # @return int 10 | 11 | ### DP Table Solution 12 | ### TC: O(n) and SC: O(n) 13 | class Solution: 14 | def jumpFloor(self, number): 15 | if number == 1: 16 | return 1 17 | DP_table = [0]*number ### DP[i] denotes the number of ways to reach on ith step 18 | DP_table[0] = 1 19 | DP_table[1] = 2 20 | for i in range(2, number): 21 | DP_table[i] = DP_table[i-1] + DP_table[i-2] 22 | return DP_table[number-1] 23 | 24 | 25 | ### DP Space Complexity Optimized Solution 26 | ### TC: O(n) and SC: O(1) 27 | class Solution: 28 | def jumpFloor(self, number): 29 | if number == 1: 30 | return 1 31 | prev = 1 32 | cur = 2 33 | for i in range(2, number): 34 | cur, prev = cur+prev, cur 35 | return cur -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ70/JZ70.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ70 矩形覆盖 3 | 4 | 描述: 5 | 我们可以用 2*1 的小矩形横着或者竖着去覆盖更大的矩形。请问用 n 个 2*1 的小矩形无重叠地覆盖一个 2*n 的大矩形,从同一个方向看总共有多少种不同的方法? 6 | ''' 7 | 8 | # @param number int 9 | # @return int 10 | 11 | 12 | ''' 13 | Similar to climbing stairs problem 14 | ''' 15 | ### TC O(n) and SC: O(1) 16 | class Solution: 17 | def rectCover(self, number): 18 | if number == 0: ### corner case 19 | return 0 20 | prev = 1 21 | cur = 1 22 | for i in range(1, number): 23 | cur, prev = prev+cur, cur 24 | return cur -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ71/JZ71.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ71 跳台阶扩展问题 3 | 4 | 描述: 5 | 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶(n为正整数)总共有多少种跳法。 6 | ''' 7 | 8 | # @param number int 9 | # @return int 10 | 11 | ''' 12 | f[n] = f[n-1] + f[n-2] + .. + f[1] + f[0] 13 | f[n-1] = f[n-2] + .. + f[1] + f[0] 14 | f[n] = 2 * f[n-1] 15 | ''' 16 | 17 | class Solution: 18 | def jumpFloorII(self, number): 19 | return 2**(number-1) -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ73/JZ73.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ73 翻转单词序列 3 | 4 | 描述: 5 | 牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看, 6 | 但却读不懂它的意思。例如,“nowcoder. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a nowcoder.”。 7 | Cat对一一的翻转这些单词顺序可不在行,你能帮助他么? 8 | ''' 9 | 10 | # @param string str 11 | # @return str 12 | 13 | ### TCL O(n) and SC: O(n) 14 | class Solution: 15 | def ReverseSentence(self, string): 16 | words = string.split() 17 | words.reverse() 18 | return ' '.join(words) -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ74/JZ74.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ74 和为S的连续正数序列 3 | 4 | 描述: 5 | 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。 6 | 但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。 7 | 没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? 8 | ''' 9 | 10 | # @param s int 11 | # @return List[List[int]] 12 | 13 | ### Two Pointer Solution 14 | ### TC: O(n) and SC: O(1) 15 | class Solution: 16 | def FindContinuousSequence(self, s): 17 | ans = [] 18 | def seq_sum(i,j): 19 | return (i+j)*(j-i+1)/2 20 | lp = 1 ### lp <= rp 21 | rp = 1 22 | while lp <= s//2: 23 | if seq_sum(lp,rp) == s: 24 | ans.append([i for i in range(lp, rp+1)]) 25 | lp += 1 26 | elif seq_sum(lp,rp) < s: 27 | rp += 1 28 | else: 29 | lp += 1 30 | return ans -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ75/JZ75.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ75 字符流中第一个不重复的字符 3 | 4 | 描述: 5 | 请实现一个函数用来找出字符流中第一个只出现一次的字符。 6 | 例如,当从字符流中只读出前两个字符 "go" 时,第一个只出现一次的字符是 "g" 。当从该字符流中读出前六个字符 “google" 时,第一个只出现一次的字符是"l"。 7 | 8 | 如果当前字符流没有存在出现一次的字符,返回#字符。 9 | ''' 10 | 11 | class Solution: 12 | hashTable = [0]*128 13 | queue = [] 14 | def FirstAppearingOnce(self): 15 | while self.queue: ### can not use for char in queue because queue can not be modified while iteration 16 | char = self.queue[0] 17 | if self.hashTable[ord(char)] > 1: 18 | self.queue.pop(0) 19 | else: 20 | return char 21 | return '#' 22 | 23 | 24 | def Insert(self, char): 25 | if self.hashTable[ord(char)] == 0: 26 | self.queue.append(char) 27 | self.hashTable[ord(char)] += 1 28 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ76/JZ76.py: -------------------------------------------------------------------------------- 1 | ''' 2 | ### JZ76 删除链表中重复的结点 3 | 4 | 描述: 5 | 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表 1->2->3->3->4->4->5 处理后为 1->2->5 6 | ''' 7 | 8 | # class ListNode: 9 | # def __init__(self, x): 10 | # self.val = x 11 | # self.next = None 12 | 13 | # @param pHead ListNode 14 | # @return ListNode 15 | 16 | ### TC: O(n) and SC: O(1) 17 | class Solution: 18 | def deleteDuplication(self, pHead): 19 | temp = ListNode(None) 20 | temp.next = pHead 21 | cur = pHead 22 | prev = temp 23 | while cur: 24 | if cur.next and cur.next.val == cur.val: 25 | while cur.next: 26 | if cur.next.val == cur.val: 27 | cur.next = cur.next.next 28 | else: 29 | break 30 | prev.next = cur.next 31 | cur = prev.next 32 | else: 33 | prev = cur 34 | cur = cur.next 35 | return temp.next -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ77/JZ77.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ77 按之字形顺序打印二叉树 3 | 4 | 描述: 5 | 给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替) 6 | ''' 7 | 8 | # class TreeNode: 9 | # def __init__(self, x): 10 | # self.val = x 11 | # self.left = None 12 | # self.right = None 13 | 14 | # @param pRoot TreeNode 15 | # @return List[List[int]] 16 | 17 | ### BFS Solution 18 | ### TC: O(n) and SC: O(n) 19 | class Solution: 20 | def Print(self, pRoot): 21 | if pRoot is None: ### corner case: empty tree 22 | return 23 | ans = [] 24 | queue = [(pRoot, 1)] ### BFS 25 | while queue: 26 | node, depth = queue.pop(0) 27 | if len(ans) < depth: ### enter a new level 28 | ans.append([]) 29 | ans[depth-1].append(node.val) 30 | if node.left: 31 | queue.append((node.left,depth+1)) 32 | if node.right: 33 | queue.append((node.right, depth+1)) 34 | for i in range(1, len(ans), 2): ### reverse for even number level 35 | ans[i].reverse() 36 | return ans 37 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ78/JZ78.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ78 把二叉树打印成多行 3 | 4 | 描述: 5 | 给定一个节点数为 n 二叉树,要求从上到下按层打印二叉树的 val 值,同一层结点从左至右输出, 6 | 每一层输出一行,将输出的结果存放到一个二维数组中返回。 7 | ''' 8 | 9 | # class TreeNode: 10 | # def __init__(self, x): 11 | # self.val = x 12 | # self.left = None 13 | # self.right = None 14 | 15 | # @param pRoot TreeNode 16 | # @return List[List[int]] 17 | 18 | ### TC: O(n) and SC: O(n) 19 | class Solution: 20 | def Print(self, pRoot): 21 | ans = [] 22 | queue = [(pRoot, 1)] ### BFS 23 | while queue: 24 | node, depth = queue.pop(0) 25 | if node: 26 | if len(ans) < depth: 27 | ans.append([]) 28 | ans[depth-1].append(node.val) 29 | queue.append((node.left, depth+1)) 30 | queue.append((node.right, depth+1)) 31 | return ans -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ79/JZ79.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ79 判断是不是平衡二叉树 3 | 4 | 描述: 5 | 输入一棵节点数为 n 二叉树,判断该二叉树是否是平衡二叉树。 6 | 在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树 7 | 平衡二叉树(Balanced Binary Tree),具有以下性质: 8 | 它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。 9 | ''' 10 | 11 | # class TreeNode: 12 | # def __init__(self, x): 13 | # self.val = x 14 | # self.left = None 15 | # self.right = None 16 | 17 | # @param pRoot TreeNode 18 | # @return bool 19 | 20 | ### Easy to understand 21 | class Solution: 22 | def IsBalanced_Solution(self, pRoot): 23 | def depth(node): 24 | if node: 25 | return max(depth(node.left), depth(node.right)) + 1 26 | else: 27 | return 0 28 | 29 | if pRoot is None: 30 | return True 31 | 32 | if abs(depth(pRoot.left) - depth(pRoot.right)) > 1: 33 | return False 34 | return self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right) 35 | 36 | ### TC: O(n) and SC: O(n) 37 | class Solution: 38 | def IsBalanced_Solution(self, pRoot): 39 | def depth(node): 40 | if node is None: 41 | return 0 42 | left = depth(node.left) 43 | right = depth(node.right) 44 | if left == -1 or right == -1: 45 | return -1 ### not balance 46 | else: 47 | if abs(left - right) > 1: 48 | return -1 ### not balance 49 | else: 50 | return max(left, right) + 1 51 | 52 | return depth(pRoot) != -1 53 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ81/JZ81.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ81 调整数组顺序使奇数位于偶数前面(二) 3 | 4 | 描述: 5 | 输入一个长度为 n 整数数组,数组里面可能含有相同的元素,实现一个函数来调整该数组中数字的顺序, 6 | 使得所有的奇数位于数组的前面部分,所有的偶数位于数组的后面部分,对奇数和奇数,偶数和偶数之间的相对位置不做要求。 7 | ''' 8 | 9 | # @param array List[int] 10 | # @return List[int] 11 | 12 | 13 | ### TC: O(n) and SC: O(1) 14 | class Solution: 15 | def reOrderArrayTwo(self, array): 16 | j = 0 ### leftmost even number 17 | for i in range(len(array)): 18 | if array[i] % 2 == 1: # odd 19 | array[i], array[j] = array[j], array[i] ### similar to quick sort 20 | j += 1 21 | return array 22 | 23 | ### One common TC O(n) and SC O(1) solution for array related problem is two pointers. 24 | ### TC: O(n) and SC: O(1) 25 | class Solution: 26 | def reOrderArrayTwo(self, array): 27 | lp = 0 28 | rp = len(array) - 1 29 | while lp < rp: ### similar to quick sort 30 | while array[lp] % 2 != 0 and lp < rp: 31 | lp += 1 32 | while array[rp] % 2 == 0 and lp < rp: 33 | rp -=1 34 | array[lp], array[rp] = array[rp], array[lp] ### swap 35 | return array -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ84/JZ84.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ 84 二叉树中和为某一值的路径(三) 3 | 4 | 描述: 5 | 给定一个二叉树root和一个整数值 sum ,求该树有多少路径的的节点值之和等于 sum 。 6 | 该题路径定义不需要从根节点开始,也不需要在叶子节点结束,但是一定是从父亲节点往下到孩子节点 7 | ''' 8 | 9 | # class TreeNode: 10 | # def __init__(self, x): 11 | # self.val = x 12 | # self.left = None 13 | # self.right = None 14 | 15 | # @param root TreeNode 16 | # @param target int 17 | # @return int 18 | 19 | class Solution: 20 | res = 0 21 | def FindPath(self, root, target): 22 | self.res = 0 23 | def DFS(node, target): 24 | if node is None: 25 | return 26 | else: 27 | target -= node.val 28 | if target == 0: 29 | self.res += 1 30 | DFS(node.left, target) ### the former path still counts 31 | DFS(node.right, target) ### the former path still counts 32 | 33 | if root: 34 | DFS(root, target) 35 | self.FindPath(root.left, target) ### path is not required to start from root 36 | self.FindPath(root.right, target) ### path is not required to start from root 37 | 38 | return self.res 39 | -------------------------------------------------------------------------------- /InterviewProblem/JZ_Offer/JZ85/JZ85.py: -------------------------------------------------------------------------------- 1 | ''' 2 | JZ85 连续子数组的最大和(二) 3 | 4 | 描述: 5 | 输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组,找到一个具有最大和的连续子数组。 6 | 1.子数组是连续的,比如[1,3,5,7,9]的子数组有[1,3],[3,5,7]等等,但是[1,3,7]不是子数组 7 | 2.如果存在多个最大和的连续子数组,那么返回其中长度最长的,该题数据保证这个最长的只存在一个 8 | 3.该题定义的子数组的最小长度为1,不存在为空的子数组,即不存在[]是某个数组的子数组 9 | 4.返回的数组不计入空间复杂度计算 10 | ''' 11 | 12 | # @param array List[int] 13 | # @return List[int] 14 | 15 | ### TC: O(n) and SC: O(1) 16 | class Solution: 17 | def FindGreatestSumOfSubArray(self, array): 18 | MAX = array[0] 19 | cur = array[0] 20 | lp = 0 21 | rp = 1 22 | cur_lp = 0 23 | cur_rp = 1 24 | 25 | for i in range(1, len(array)): 26 | ### if array[i] + cur < array[i]: ### refer to JZ42 27 | if array[i] + cur < 0 or cur < 0: 28 | cur_lp = i 29 | cur_rp = i+1 30 | else: 31 | cur_rp += 1 32 | cur = max(array[i], cur+array[i]) 33 | if cur > MAX: 34 | lp = cur_lp 35 | rp = cur_rp 36 | MAX = cur 37 | elif cur == MAX: 38 | if rp - lp < cur_rp - cur_lp: ### keep the longer sub-sequence 39 | lp = cur_lp 40 | rp = cur_rp 41 | 42 | return array[lp:rp] -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC1 Two Sum/LC1.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 1. Two Sum 3 | 4 | Description: 5 | Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target. 6 | 7 | You may assume that each input would have exactly one solution, and you may not use the same element twice. 8 | 9 | You can return the answer in any order. 10 | ''' 11 | 12 | # @param nums List[int] 13 | # @param target int 14 | # @return List[int] 15 | 16 | ### TC: O(n) and SC: O(n) 17 | class Solution: 18 | def twoSum(self, nums, target): 19 | hashTable = {} 20 | for i in range(len(nums)): 21 | complement = target - nums[i] ### to achieve one pass 22 | if complement in hashTable: 23 | return [i, hashTable[complement]] 24 | ''' 25 | 如果不是因为题目要求返回两个数的index,其实用set就可以了,hash已经包含了complement的信息 26 | 3sum那题就可以用hashTable[complement]记录pivot的index用来判断这个解是不是重复的 27 | ''' 28 | hashTable[nums[i]] = i 29 | 30 | ### Follow up: if there are multiple solutions 31 | from collections import defaultdict 32 | class Solution: 33 | def twoSum(self, nums, target): 34 | res = [] 35 | hashTable = defaultdict(list) 36 | for i in range(len(nums)): 37 | complement = target - nums[i] ### to achieve one pass 38 | if complement in hashTable: 39 | for j in hashTable[complement]: 40 | res.append([i, j]) 41 | hashTable[nums[i]].append(i) 42 | return res 43 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC1002 Find Common Characters/LC1002.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 1002. Find Common Characters 3 | 4 | Description: 5 | Given a string array words, return an array of all characters that show up in all strings within the words (including duplicates). 6 | You may return the answer in any order. 7 | ''' 8 | 9 | # @param words List[str] 10 | # @return List[str] 11 | 12 | ''' 13 | Choose a word as reference, keep shrinking the counter dictionary 14 | ''' 15 | ### TC: O(n) and SC: O(k) where k is the length of a single word 16 | from collections import * 17 | class Solution: 18 | def commonChars(self, words): 19 | ans = [] 20 | if words: 21 | counter = Counter(words[0]) ### can be optimized to find the shortest word as initial counter 22 | for word in words[1:]: 23 | temp = Counter(word) 24 | toDel = [] 25 | for char in counter: 26 | if char in temp: 27 | counter[char] = min(counter[char], temp[char]) 28 | else: 29 | toDel.append(char) 30 | for char in toDel: ### during iteration dictionary size can not be changed 31 | del counter[char] 32 | for char in counter: 33 | for i in range(counter[char]): 34 | ans.append(char) 35 | return ans 36 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC101 Symmetric Tree/LC101.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 101. Symmetric Tree 3 | 4 | Description: 5 | Given the root of a binary tree, check whether it is a mirror of itself (i.e., symmetric around its center). 6 | ''' 7 | 8 | # class TreeNode: 9 | # def __init__(self, val=0, left=None, right=None): 10 | # self.val = val 11 | # self.left = left 12 | # self.right = right 13 | 14 | # @param root TreeNode 15 | # @return bool 16 | 17 | ''' 18 | 要比得两棵树放一起比,不能自己和自己比。 19 | ''' 20 | 21 | ### TC: O(n) and SC: O(n) 22 | class Solution: 23 | def isSymmetric(self, root): 24 | def isMirror(t1, t2): 25 | if t1 is None and t2 is None: 26 | return True 27 | elif t1 is None or t2 is None: 28 | return False 29 | else: 30 | if t1.val == t2.val: 31 | return isMirror(t1.left, t2.right) and isMirror(t1.right, t2.left) ### punchline 32 | else: 33 | return False 34 | return isMirror(root, root) 35 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC1013 Partition Array Into Three Parts With Equal Sum/LC1013.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 1013. Partition Array Into Three Parts With Equal Sum 3 | 4 | Description: 5 | Given an array of integers arr, return true if we can partition the array into three non-empty parts with equal sums. 6 | 7 | Formally, we can partition the array if we can find indexes i + 1 < j with 8 | (arr[0] + arr[1] + ... + arr[i] == arr[i + 1] + arr[i + 2] + ... + arr[j - 1] == arr[j] + arr[j + 1] + ... + arr[arr.length - 1]) 9 | ''' 10 | 11 | # @param s str 12 | # @return int 13 | 14 | ### TC: O(n) and SC: O(1) 15 | class Solution: 16 | def canThreePartsEqualSum(self, arr: List[int]) -> bool: 17 | S = sum(arr) 18 | if S % 3 != 0: 19 | return False 20 | 21 | s = S / 3 22 | 23 | count = 0 24 | cur = 0 25 | for n in arr: 26 | cur += n 27 | if cur == s: 28 | count += 1 29 | cur = 0 30 | 31 | if count >= 3: ### case: 0 0 0 0 32 | return True -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC102 Binary Tree Level Order Traversal/LC102.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 102. Binary Tree Level Order Traversal 3 | 4 | Description: 5 | Given the root of a binary tree, return the level order traversal of its nodes' values. (i.e., from left to right, level by level). 6 | 7 | Example: 8 | Input: root = [3,9,20,null,null,15,7] 9 | Output: [[3],[9,20],[15,7]] 10 | ''' 11 | 12 | # class TreeNode: 13 | # def __init__(self, val=0, left=None, right=None): 14 | # self.val = val 15 | # self.left = left 16 | # self.right = right 17 | 18 | # @param root TreeNode 19 | # @return List[List[int]] 20 | 21 | ### Queue Solution 22 | class Solution: 23 | def levelOrder(self, root): 24 | result = [] 25 | if root is None: ### corner case 26 | return result 27 | 28 | queue = [(root,0)] 29 | 30 | while queue: 31 | root, level = queue.pop(0) 32 | if len(result) <= level: 33 | result.append([]) 34 | result[level].append(root.val) 35 | if root.left: 36 | queue.append((root.left,level+1)) 37 | if root.right: 38 | queue.append((root.right,level+1)) 39 | return result 40 | 41 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC103 Binary Tree Zigzag Level Order Traversal/LC103.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 103. Binary Tree Zigzag Level Order Traversal 3 | 4 | Description: 5 | Given the root of a binary tree, return the zigzag level order traversal of its nodes' values. 6 | (i.e., from left to right, then right to left for the next level and alternate between). 7 | ''' 8 | 9 | # class TreeNode: 10 | # def __init__(self, val=0, left=None, right=None): 11 | # self.val = val 12 | # self.left = left 13 | # self.right = right 14 | 15 | # @param root TreeNode 16 | # @return List[List[int]] 17 | 18 | ### DFS Solution 19 | ### TC: O(n) and SC: O(n) 20 | class Solution: 21 | def zigzagLevelOrder(self, root): 22 | if root is None: 23 | return [] 24 | else: 25 | res = [] 26 | def DFS(node, depth): 27 | if depth >= len(res): 28 | res.append([node.val]) 29 | else: 30 | if depth % 2 == 1: 31 | res[depth].insert(0, node.val) 32 | else: 33 | res[depth].append(node.val) 34 | 35 | if node.left: 36 | DFS(node.left, depth+1) 37 | if node.right: 38 | DFS(node.right, depth+1) 39 | 40 | DFS(root, 0) 41 | return res 42 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC105 Construct Binary Tree from Preorder and Inorder Traversal/LC105.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 105. Construct Binary Tree from Preorder and Inorder Traversal 3 | 4 | Description: 5 | Given two integer arrays preorder and inorder where preorder is the preorder traversal of a binary tree and 6 | inorder is the inorder traversal of the same tree, construct and return the binary tree. 7 | ''' 8 | 9 | # class TreeNode: 10 | # def __init__(self, val=0, left=None, right=None): 11 | # self.val = val 12 | # self.left = left 13 | # self.right = right 14 | 15 | # @param preorder List[int] 16 | # @param inorder List[int] 17 | # @return TreeNode 18 | 19 | ### Recursive Solution 20 | ### TC: O(n) and SC: O(n) 21 | class Solution: 22 | def buildTree(self, preorder, inorder): 23 | if preorder: 24 | root = TreeNode(preorder[0]) 25 | idx = inorder.index(preorder[0]) 26 | root.left = self.buildTree(preorder[1:idx+1], inorder[:idx]) 27 | root.right = self.buildTree(preorder[idx+1:], inorder[idx+1:]) 28 | return root 29 | else: 30 | return None 31 | 32 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC107 Binary Tree Level Order Traversal II/LC107.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 107. Binary Tree Level Order Traversal II 3 | 4 | Description: 5 | Given the root of a binary tree, return the bottom-up level order traversal of its nodes' values. 6 | (i.e., from left to right, level by level from leaf to root). 7 | ''' 8 | 9 | # @param root TreeNode 10 | # @return List[List[int]] 11 | 12 | # class TreeNode: 13 | # def __init__(self, val=0, left=None, right=None): 14 | # self.val = val 15 | # self.left = left 16 | # self.right = right 17 | 18 | ### TC: O(n) and SC: O(n) 19 | class Solution: 20 | def levelOrderBottom(self, root): 21 | ans = [] 22 | if root: 23 | queue = [(root,0)] 24 | while queue: 25 | node, depth = queue.pop(0) 26 | if len(ans) <= depth: 27 | ans.append([]) 28 | ans[depth].append(node.val) 29 | if node.left: 30 | queue.append((node.left, depth+1)) 31 | if node.right: 32 | queue.append((node.right, depth+1)) 33 | ans.reverse() 34 | return ans -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC108 Convert Sorted Array to Binary Tree/LC108.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 108. Convert Sorted Array to Binary Search Tree 3 | 4 | Description: 5 | Given an integer array nums where the elements are sorted in ascending order, 6 | convert it to a height-balanced binary search tree. 7 | 8 | A height-balanced binary tree is a binary tree in which 9 | the depth of the two subtrees of every node never differs by more than one. 10 | ''' 11 | 12 | # class TreeNode: 13 | # def __init__(self, val=0, left=None, right=None): 14 | # self.val = val 15 | # self.left = left 16 | # self.right = right 17 | 18 | # @param nums List[int] 19 | # @return TreeNode 20 | 21 | ''' 22 | 这题要求height-balanced 23 | ''' 24 | 25 | ### TC: O(n) and SC: O(n) 26 | class Solution: 27 | def sortedArrayToBST(self, nums): 28 | def build(arr): 29 | if len(arr) == 0: 30 | return None 31 | if len(arr) == 1: 32 | return TreeNode(arr[0]) 33 | 34 | mid = len(arr) // 2 35 | root = TreeNode(arr[mid]) 36 | root.left = build(arr[:mid]) 37 | root.right = build(arr[mid+1:]) 38 | return root 39 | 40 | return build(nums) 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC11 Container With Most Water/LC11.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 11. Container With Most Water 3 | 4 | Description: 5 | You are given an integer array height of length n. There are n vertical lines drawn such that the two endpoints of the ith line are (i, 0) and (i, height[i]). 6 | 7 | Find two lines that together with the x-axis form a container, such that the container contains the most water. 8 | 9 | Return the maximum amount of water a container can store. 10 | 11 | Notice that you may not slant the container. 12 | ''' 13 | 14 | # @param height List[int] 15 | # @return int 16 | 17 | ### Two Pointer Solution 18 | ### TC: O(n) and SC: O(1) 19 | class Solution: 20 | def maxArea(self, height): 21 | lp = 0 22 | rp = len(height) - 1 23 | MAX = 0 24 | while lp < rp: 25 | MAX = max(MAX, (rp-lp)*min(height[lp], height[rp])) 26 | if height[lp] > height[rp]: 27 | rp -= 1 28 | else: 29 | lp += 1 30 | 31 | return MAX -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC115 Distinct Subsequences /LC115.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 115. Distinct Subsequences 3 | 4 | Description: 5 | Given two strings s and t, return the number of distinct subsequences of s which equals t. 6 | 7 | A string's subsequence is a new string formed from the original string 8 | by deleting some (can be none) of the characters without disturbing 9 | the remaining characters' relative positions. (i.e., "ACE" is a subsequence of "ABCDE" while "AEC" is not). 10 | 11 | The test cases are generated so that the answer fits on a 32-bit signed integer. 12 | ''' 13 | 14 | # @param s str 15 | # @param t str 16 | # @return int 17 | 18 | ### DP Solution 19 | ### TC: O(mn) and SC: O(mn) 20 | class Solution: 21 | def numDistinct(self, s, t): 22 | DP_table = [[0]*(len(t)) for _ in range(len(s))] ### DP[i][j] : # distinct subseq of s[:i] equals to t[:j] 23 | if s[0] == t[0]: 24 | DP_table[0][0] = 1 25 | ### Base Case 26 | for i in range(1, len(s)): ### first column of the DP table 27 | DP_table[i][0] = DP_table[i-1][0] + (1 if s[i] == t[0] else 0) 28 | 29 | for i in range(1, len(s)): 30 | for j in range(1, min(i+1, len(t))): ### DP[i][j] = 0 where j > i 31 | DP_table[i][j] = DP_table[i-1][j] + (DP_table[i-1][j-1] if s[i] == t[j] else 0) 32 | 33 | return DP_table[-1][-1] 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC121 Best Time to Buy and Sell Stock/LC121.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 121. Best Time to Buy and Sell Stock 3 | 4 | Description: 5 | You are given an array prices where prices[i] is the price of a given stock on the ith day. 6 | 7 | You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock. 8 | 9 | Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0. 10 | ''' 11 | 12 | # @param prices List[int] 13 | # @return int 14 | 15 | ''' 16 | Since we can only buy and sell once. To make the profit max, we need to buy at the lowest price and sell at the highest price. 17 | ''' 18 | 19 | ### TC: O(n) and SC: O(1) 20 | class Solution: 21 | def maxProfit(self, prices): 22 | low = float("inf") 23 | MAX = 0 24 | for p in prices: ### new price can always substruct the previous low price 25 | low = min(p, low) ### will keep updating the current lowest price 26 | MAX = max(MAX, p - low) ### only the current price will substract the lowest price 27 | return MAX 28 | 29 | 30 | ### Reverse Version 31 | ### TC: O(n) and SC: O(1) 32 | class Solution: 33 | def maxProfit(self, prices): 34 | high = float("-inf") 35 | MAX = 0 36 | for p in prices[::-1]: 37 | high = max(p, high) ### will keep updating the current highest price 38 | MAX = max(MAX, high - p) ### only the current price will be substracted the highest price 39 | return MAX -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC122 Best Time to Buy and Sell Stock II/LC122.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 122. Best Time to Buy and Sell Stock II 3 | 4 | Description: 5 | You are given an integer array prices where prices[i] is the price of a given stock on the ith day. 6 | 7 | On each day, you may decide to buy and/or sell the stock. You can only hold at most one share of the stock at any time. 8 | However, you can buy it then immediately sell it on the same day. 9 | 10 | Find and return the maximum profit you can achieve. 11 | ''' 12 | 13 | # @param prices List[int] 14 | # @return int 15 | 16 | ''' 17 | Difference from LC121, we can buy and sell for any times. So we can take the greedy strategy: make money when there is any profit 18 | ''' 19 | 20 | ### TC: O(n) and SC: O(1) 21 | class Solution: 22 | def maxProfit(self, prices): 23 | res = 0 24 | for i in range(1, len(prices)): 25 | if prices[i] > prices[i-1]: ### greedy strategy 26 | res += prices[i] - prices[i-1] 27 | return res -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC1287 Element Apearing More Than 25% In Sorted Array/LC1287.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 1287. Element Appearing More Than 25% In Sorted Array 3 | 4 | Description: 5 | Given an integer array sorted in non-decreasing order, 6 | there is exactly one integer in the array that occurs more than 25% of the time, return that integer. 7 | ''' 8 | 9 | # @param arr List[int] 10 | # @return int 11 | 12 | ### IntuitiveSolution 13 | ### TC: O(n) and SC: O(1) 14 | class Solution: 15 | def findSpecialInteger(self, arr): 16 | gap = len(arr) // 4 17 | for i in range(len(arr)): 18 | if i+ gap > len(arr)-1: 19 | break ### in this problem, the mode must exist, this branch will never enter 20 | if arr[i+gap] == arr[i]: 21 | return arr[i] 22 | 23 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC133 Clone Graph/LC133.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 133. Clone Graph 3 | 4 | Description: 5 | Given a reference of a node in a connected undirected graph. 6 | Return a deep copy (clone) of the graph. 7 | 8 | Each node in the graph contains a value (int) and a list (List[Node]) of its neighbors. 9 | ''' 10 | 11 | # class Node: 12 | # def __init__(self, val = 0, neighbors = None): 13 | # self.val = val 14 | # self.neighbors = neighbors if neighbors is not None else [] 15 | 16 | # @param node Node 17 | # @return Node 18 | 19 | ### TC: O(n) and SC: O(n) 20 | class Solution: 21 | def cloneGraph(self, node): 22 | self.visited = {} ### trick: if node has been visited, return it from the visited dictionary 23 | def clone(node): 24 | if node in self.visited: 25 | return self.visited[node] 26 | 27 | copy = Node(node.val, []) 28 | self.visited[node] = copy 29 | if node.neighbors: 30 | copy.neighbors = [clone(n) for n in node.neighbors] 31 | 32 | return copy 33 | 34 | if node: 35 | return clone(node) 36 | else: 37 | return None 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC136 Single Number/LC136.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 136. Single Number 3 | 4 | Description: 5 | Given a non-empty array of integers nums, every element appears twice except for one. Find that single one. 6 | 7 | You must implement a solution with a linear runtime complexity and use only constant extra space. 8 | ''' 9 | 10 | # @param nums List[int] 11 | # @return int 12 | 13 | ''' 14 | A XOR 0 = A 15 | A XOR A = 0 16 | A XOR B = B XOR A 17 | (A XOR B) XOR C = A XOR (B XOR C) 18 | ''' 19 | 20 | ### TC: O(n) and SC: O(1) 21 | class Solution: 22 | def singleNumber(self, nums): 23 | res = 0 24 | for n in nums: 25 | res ^= n 26 | return res -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC1382 Blance a Binary Search Tree/LC1382.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 1382. Balance a Binary Search Tree 3 | 4 | Description: 5 | Given the root of a binary search tree, return a balanced binary search tree with the same node values. 6 | If there is more than one answer, return any of them. 7 | 8 | A binary search tree is balanced if the depth of the two subtrees of every node never differs by more than 1. 9 | ''' 10 | 11 | # class TreeNode: 12 | # def __init__(self, val=0, left=None, right=None): 13 | # self.val = val 14 | # self.left = left 15 | # self.right = right 16 | 17 | # @param root TreeNode 18 | # @return TreeNode 19 | 20 | ### TC: O(n) and SC: O(n) 21 | class Solution: 22 | def balanceBST(self, root): 23 | array = [] 24 | def inorder(node): ### inorder of BST is a sorted array 25 | if node: 26 | inorder(node.left) 27 | array.append(node.val) 28 | inorder(node.right) 29 | 30 | 31 | def build(arr): 32 | if len(arr) == 0: 33 | return None 34 | if len(arr) == 1: 35 | return TreeNode(arr[0]) 36 | 37 | mid = len(arr) // 2 38 | root = TreeNode(arr[mid]) 39 | root.left = build(arr[:mid]) 40 | root.right = build(arr[mid+1:]) 41 | return root 42 | 43 | inorder(root) ### convert this problem into LC108: convert a sorted array to a balanced BST 44 | 45 | return build(array) -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC14 Longest Common Prefix/LC14.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 14. Longest Common Prefix 3 | 4 | Description: 5 | Write a function to find the longest common prefix string amongst an array of strings. 6 | If there is no common prefix, return an empty string "". 7 | ''' 8 | 9 | # @param strs List[str] 10 | # @return str 11 | 12 | ### TC: O(n) and SC: O(1) 13 | class Solution: 14 | def longestCommonPrefix(self, strs): 15 | idx = 0 16 | while True: 17 | if len(strs[0]) <= idx: 18 | break 19 | 20 | cur = strs[0][idx] 21 | matched = True 22 | for s in strs: 23 | if len(s) <= idx: 24 | matched = False 25 | break 26 | if s[idx] != cur: 27 | matched = False 28 | break 29 | if matched: 30 | idx += 1 31 | else: 32 | break 33 | return strs[0][:idx] -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC140 Word Break II/LC140.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 140. Word Break II 3 | 4 | Description: 5 | Given a string s and a dictionary of strings wordDict, add spaces in s to construct a sentence 6 | where each word is a valid dictionary word. Return all such possible sentences in any order. 7 | 8 | Note that the same word in the dictionary may be reused multiple times in the segmentation. 9 | ''' 10 | 11 | # @param s str 12 | # @param wordDict List[str] 13 | # @return List[str] 14 | 15 | ''' 16 | LC139&LC140 类似于 LC127&LC126的关系 17 | ''' 18 | 19 | class Solution: 20 | def wordBreak(self, s, wordDict): 21 | def generatePath(path): 22 | if path: 23 | res = s[:path[0]] 24 | if len(path) > 1: 25 | for i in range(1, len(path)): 26 | res += " " 27 | res += s[path[i-1]:path[i]] 28 | return res 29 | 30 | ans = [] 31 | wordDict = set(wordDict) 32 | stack = [[0, []]] 33 | while stack: 34 | idx, path = stack.pop() 35 | if idx == len(s): 36 | ans.append(generatePath(path)) 37 | continue 38 | for i in range(idx, len(s)): 39 | if s[idx:i+1] in wordDict: 40 | stack.append([i+1, path+[i+1]]) 41 | return ans 42 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC144 Binary Tree Preorder Traversal/LC144.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 144. Binary Tree Preorder Traversal 3 | 4 | Description: 5 | Given the root of a binary tree, return the preorder traversal of its nodes' values. 6 | ''' 7 | 8 | # class TreeNode: 9 | # def __init__(self, val=0, left=None, right=None): 10 | # self.val = val 11 | # self.left = left 12 | # self.right = right 13 | 14 | # @param root TreeNode 15 | # @return List[int] 16 | 17 | ### Recursion Solution 18 | ### TC: O(n) and SC: O(n) 19 | class Solution: 20 | def preorderTraversal(self, root): 21 | ans = [] 22 | def preorder(node): 23 | if node: 24 | ans.append(node.val) 25 | preorder(node.left) 26 | preorder(node.right) 27 | preorder(root) 28 | return ans 29 | 30 | 31 | ### Stack Solution 32 | ### TC: O(n) and SC: O(n) 33 | class Solution: 34 | def preorderTraversal(self, root): 35 | if root is None: ### corner case 36 | return [] 37 | ans = [] 38 | stack = [root] 39 | while stack: 40 | node = stack.pop() 41 | ans.append(node.val) 42 | if node.right: ### trick: push right node first, LIFO 43 | stack.append(node.right) 44 | if node.left: 45 | stack.append(node.left) 46 | return ans -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC145 Binary Tree Postorder Traversal/LC145.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 145. Binary Tree Postorder Traversal 3 | 4 | Description: 5 | Given the root of a binary tree, return the postorder traversal of its nodes' values. 6 | ''' 7 | 8 | # class TreeNode: 9 | # def __init__(self, val=0, left=None, right=None): 10 | # self.val = val 11 | # self.left = left 12 | # self.right = right 13 | 14 | # @param root TreeNode 15 | # @return List[int] 16 | 17 | ### Recursion Solution 18 | ### TC: O(n) and SC: O(n) 19 | class Solution: 20 | def postorderTraversal(self, root): 21 | ans = [] 22 | def postorder(node): 23 | if node: 24 | postorder(node.left) 25 | postorder(node.right) 26 | ans.append(node.val) 27 | postorder(root) 28 | return ans 29 | 30 | 31 | ### Stack Solution 32 | ### TC: O(n) and SC: O(n) 33 | class Solution: 34 | def postorderTraversal(self, root): 35 | if root is None: ### corner case 36 | return [] 37 | ans = [] 38 | stack = [(root, False)] 39 | while stack: 40 | node, done = stack.pop() 41 | if done: 42 | ans.append(node.val) 43 | else: 44 | stack.append((node, True)) 45 | if node.right: 46 | stack.append((node.right, False)) 47 | if node.left: 48 | stack.append((node.left, False)) 49 | return ans 50 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC147 Insertion Sort List/LC147.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 147. Insertion Sort List 3 | 4 | Description: 5 | Given the head of a singly linked list, sort the list using insertion sort, and return the sorted list's head. 6 | The steps of the insertion sort algorithm: 7 | 1. Insertion sort iterates, consuming one input element each repetition and growing a sorted output list. 8 | 2. At each iteration, insertion sort removes one element from the input data, 9 | finds the location it belongs within the sorted list and inserts it there. 10 | 3. It repeats until no input elements remain. 11 | 12 | The following is a graphical example of the insertion sort algorithm. 13 | The partially sorted list (black) initially contains only the first element in the list. 14 | One element (red) is removed from the input data and inserted in-place into the sorted list with each iteration. 15 | ''' 16 | 17 | # class ListNode: 18 | # def __init__(self, val=0, next=None): 19 | # self.val = val 20 | # self.next = next 21 | 22 | # @param head ListNode 23 | # @return ListNode 24 | 25 | ### TC: O(n^2) and SC: O(1) 26 | class Solution: 27 | def insertionSortList(self, head): 28 | idle = ListNode() 29 | node = head 30 | while node: 31 | cur = idle 32 | while cur.next: 33 | if node.val > cur.next.val: 34 | cur = cur.next 35 | else: 36 | break 37 | temp = cur.next 38 | cur.next = node 39 | node = node.next 40 | cur.next.next = temp 41 | return idle.next 42 | 43 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC16 3Sum Closest/LC16.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 16. 3Sum Closest 3 | 4 | Description: 5 | Given an integer array nums of length n and an integer target, find three integers in nums such that the sum is closest to target. 6 | 7 | Return the sum of the three integers. 8 | 9 | You may assume that each input would have exactly one solution. 10 | ''' 11 | 12 | # @param nums List[int] 13 | # @param target int 14 | # @return int 15 | 16 | ### TC: O(n^2) and SC: O(n) 17 | class Solution: 18 | def threeSumClosest(self, nums, target): 19 | nums.sort() 20 | MIN_diff = float("inf") ### min diff 21 | 22 | for i in range(len(nums)): 23 | pivot = nums[i] 24 | lp = i + 1 25 | rp = len(nums)-1 26 | while lp < rp: 27 | temp = pivot + nums[lp] + nums[rp] 28 | diff = temp - target 29 | 30 | if abs(diff) < abs(MIN_diff): 31 | MIN_diff = diff 32 | 33 | if temp > target: 34 | rp -= 1 35 | elif temp < target: 36 | lp += 1 37 | else: 38 | return target 39 | 40 | return target + MIN_diff 41 | 42 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC161 One Edit Distance/LC161.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 161. One Edit Distance 3 | 4 | Description: 5 | Given two strings s and t, return true if they are both one edit distance apart, otherwise return false. 6 | A string s is said to be one distance apart from a string t if you can: 7 | - Insert exactly one character into s to get t. 8 | - Delete exactly one character from s to get t. 9 | - Replace exactly one character of s with a different character to get t. 10 | ''' 11 | 12 | # @param s str 13 | # @param t str 14 | # @return bool 15 | 16 | ### TC: O(n) and SC: O(n) 17 | class Solution: 18 | def isOneEditDistance(self, s, t): 19 | if abs(len(s)-len(t)) > 1: 20 | return False 21 | if len(t) > len(s): 22 | s, t = t, s 23 | 24 | if len(s) == len(t): 25 | n_diff = 0 26 | for i in range(len(s)): 27 | if s[i] != t[i]: 28 | n_diff += 1 29 | return n_diff == 1 30 | else: 31 | n_diff = 0 32 | j = 0 33 | for i in range(len(s)): ### len(s) = len(t) + 1 34 | if j < len(t) and s[i] == t[j]: 35 | j += 1 36 | else: 37 | n_diff += 1 38 | continue 39 | return n_diff == 1 40 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC163 Missing Rangers/LC163.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 163. Missing Ranges 3 | 4 | Description: 5 | You are given an inclusive range [lower, upper] and a sorted unique integer array nums, where all elements are in the inclusive range. 6 | 7 | A number x is considered missing if x is in the range [lower, upper] and x is not in nums. 8 | 9 | Return the smallest sorted list of ranges that cover every missing number exactly. That is, no element of nums is in any of the ranges, 10 | and each missing number is in one of the ranges. 11 | 12 | Each range [a,b] in the list should be output as: 13 | - "a->b" if a != b 14 | - "a" if a == b 15 | ''' 16 | 17 | # @param nums List[int] 18 | # @param lower int 19 | # @param upper int 20 | # @return List[str] 21 | 22 | ### TC: O(n) and SC: O(1) 23 | class Solution: 24 | def findMissingRanges(self, nums, lower, upper): 25 | def missingRange(low, high): 26 | if high <= low + 1: 27 | return [] 28 | elif high == low+2: 29 | return [str(low+1)] 30 | else: 31 | return [str(low+1)+"->"+str(high-1)] 32 | 33 | p = lower-1 ### trick 34 | ans = [] 35 | for n in nums: 36 | ans += missingRange(p,n) 37 | p = n 38 | ans += missingRange(p, high+1) 39 | return ans -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC167 Two Sum II - Input Array Is Sorted/LC167.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 167. Two Sum II - Input Array Is Sorted 3 | 4 | Description: 5 | Given a 1-indexed array of integers numbers that is already sorted in non-decreasing order, 6 | find two numbers such that they add up to a specific target number. 7 | Let these two numbers be numbers[index1] and numbers[index2] where 1 <= index1 < index2 <= numbers.length. 8 | 9 | Return the indices of the two numbers, index1 and index2, added by one as an integer array [index1, index2] of length 2. 10 | 11 | The tests are generated such that there is exactly one solution. You may not use the same element twice. 12 | ''' 13 | 14 | # @param nums List[int] 15 | # @param target int 16 | # @return List[int] 17 | 18 | ### TC: O(n) and SC: O(1) 19 | class Solution: 20 | def twoSum(self, nums, target): 21 | lp = 0 22 | rp = len(nums)-1 23 | 24 | while lp < rp: 25 | temp = nums[lp] + nums[rp] 26 | if temp == target: 27 | return [lp+1, rp+1] ### stupid requirement 28 | elif temp < target: 29 | lp += 1 30 | else: 31 | rp -= 1 32 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC169 Majority Element/LC169.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 169. Majority Element 3 | 4 | Description: 5 | Given an array nums of size n, return the majority element. 6 | 7 | The majority element is the element that appears more than n // 2 times. 8 | You may assume that the majority element always exists in the array. 9 | ''' 10 | 11 | # @param nums List[int] 12 | # @return int 13 | 14 | ### Intuitive solutions: 1. Hash Table 2. Sort 15 | 16 | ''' 17 | Candidate Solution: 18 | If a number occupies more than half of the array, it can use the 'perish together' strategy to beat all other numbers. 19 | ''' 20 | ### TC: O(n) and SC: O(1) 21 | class Solution: 22 | def majorityElement(self, nums): 23 | candidate = None 24 | vote = 0 25 | for n in nums: 26 | if vote == 0: 27 | candidate = n 28 | vote += 1 29 | else: 30 | if candidate == n: 31 | vote += 1 32 | else: 33 | vote -= 1 34 | 35 | ''' 36 | Leetcode version does not need to check whether the condidate is the mode 37 | ''' 38 | winCondition = len(nums) // 2 39 | k = 0 40 | for n in nums: 41 | if n == candidate: 42 | k += 1 43 | if k >= winCondition: 44 | return candidate 45 | 46 | return -1 47 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC17 Letter Combinations of a Phone Number/LC17.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 17. Letter Combinations of a Phone Number 3 | 4 | Description: 5 | Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent. Return the answer in any order. 6 | ''' 7 | 8 | # @param digits str 9 | # @return List[str] 10 | 11 | class Solution: 12 | def letterCombinations(self, digits): 13 | letters = {"2": "abc", "3": "def", "4": "ghi", "5": "jkl", 14 | "6": "mno", "7": "pqrs", "8": "tuv", "9": "wxyz"} 15 | 16 | ans = [] 17 | def DFS(path, depth): 18 | if depth == len(digits): 19 | ans.append(''.join(path)) 20 | return 21 | cur = digits[depth] 22 | for char in letters[cur]: 23 | path[depth] = char 24 | DFS(path, depth+1) 25 | 26 | if digits: ### corner case 27 | DFS([None for _ in range(len(digits))], 0) 28 | 29 | return ans -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC171 Excel Sheet Column Number/LC171.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 171. Excel Sheet Column Number 3 | 4 | Description: 5 | Given a string columnTitle that represents the column title as appears in an Excel sheet, 6 | return its corresponding column number. 7 | ''' 8 | 9 | # @param columnTitle str 10 | # @return int 11 | 12 | ''' 13 | Refer to LC168 14 | ''' 15 | 16 | class Solution: 17 | def titleToNumber(self, columnTitle): 18 | table = { 19 | "A":1, 20 | "B":2, 21 | "C":3, 22 | "D":4, 23 | "E":5, 24 | "F":6, 25 | "G":7, 26 | "H":8, 27 | "I":9, 28 | "J":10, 29 | "K":11, 30 | "L":12, 31 | "M":13, 32 | "N":14, 33 | "O":15, 34 | "P":16, 35 | "Q":17, 36 | "R":18, 37 | "S":19, 38 | "T":20, 39 | "U":21, 40 | "V":22, 41 | "W":23, 42 | "X":24, 43 | "Y":25, 44 | "Z":26, 45 | } 46 | ans = 0 47 | power = 1 48 | for char in columnTitle[::-1]: 49 | ans += table[char]*power 50 | power *= 26 51 | return ans 52 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC179 Largest Number/LC179.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 179. Largest Number 3 | 4 | Description: 5 | Given a list of non-negative integers nums, arrange them such that they form the largest number and return it. 6 | 7 | Since the result may be very large, so you need to return a string instead of an integer. 8 | ''' 9 | 10 | # @param nums List[int] 11 | # @return str 12 | 13 | ### TC: O(nlogn) and SC: O(n) 14 | class Solution: 15 | def largestNumber(self, nums): 16 | class uStr(str): 17 | def __lt__(self, other): 18 | return self+other > other+self 19 | 20 | ans = ''.join(sorted(map(str, nums), key=uStr)) 21 | if ans[0] == '0': ### corner case: [0, 0] 22 | return '0' 23 | else: 24 | return ans -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC19 Remove Nth Node From End of List/LC19.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 19. Remove Nth Node From End of List 3 | 4 | Description: 5 | Given the head of a linked list, remove the nth node from the end of the list and return its head. 6 | ''' 7 | 8 | # class ListNode: 9 | # def __init__(self, val=0, next=None): 10 | # self.val = val 11 | # self.next = next 12 | 13 | # @param head ListNode 14 | # @param n int 15 | # @return ListNode 16 | 17 | ### TC: O(n) and SC: O(1) 18 | class Solution: 19 | def removeNthFromEnd(self, head, n): 20 | temp = ListNode() 21 | temp.next = head 22 | fast = head 23 | for i in range(n): 24 | fast = fast.next 25 | slow = head 26 | prev = temp 27 | while fast: 28 | prev, slow = slow, slow.next 29 | fast = fast.next 30 | prev.next = slow.next 31 | return temp.next -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC190 Reverse Bits/LC190.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 190. Reverse Bits 3 | 4 | Description: 5 | Reverse bits of a given 32 bits unsigned integer. 6 | 7 | Note: 8 | 9 | Note that in some languages, such as Java, there is no unsigned integer type. 10 | In this case, both input and output will be given as a signed integer type. 11 | They should not affect your implementation, as the integer's internal binary representation is the same, 12 | whether it is signed or unsigned. 13 | In Java, the compiler represents the signed integers using 2's complement notation. 14 | Therefore, in Example 2 above, the input represents the signed integer -3 and 15 | the output represents the signed integer -1073741825. 16 | ''' 17 | 18 | # @param n int 19 | # @return int 20 | 21 | ### TC: O(n) and SC: O(n) 22 | class Solution: 23 | def reverseBits(self, n): 24 | res = 0 25 | power = 31 26 | while n != 0: 27 | res += (n & 1) << power 28 | n = n >> 1 29 | power -= 1 30 | return res 31 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC2 Add Two Numbers/LC2.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 2. Add Two Numbers 3 | 4 | Description: 5 | You are given two non-empty linked lists representing two non-negative integers. 6 | The digits are stored in reverse order, and each of their nodes contains a single digit. 7 | Add the two numbers and return the sum as a linked list. 8 | 9 | You may assume the two numbers do not contain any leading zero, except the number 0 itself. 10 | ''' 11 | 12 | # class ListNode: 13 | # def __init__(self, val=0, next=None): 14 | # self.val = val 15 | # self.next = next 16 | 17 | 18 | # @param l1 ListNode 19 | # @param l2 ListNode 20 | # @return ListNode 21 | 22 | ### TC: O(n) and SC: O(1) 23 | class Solution: 24 | def addTwoNumbers(self, l1, l2): 25 | res = ListNode() 26 | cur = res 27 | carry = 0 ### addition carry 28 | while l1 or l2 or carry: 29 | cur.next = ListNode() 30 | cur = cur.next 31 | 32 | temp = (l1.val if l1 is not None else 0) + (l2.val if l2 is not None else 0) 33 | if temp + carry >= 10: 34 | cur.val = temp + carry -10 35 | carry = 1 36 | else: 37 | cur.val = temp + carry 38 | carry = 0 39 | 40 | if l1 is not None: 41 | l1 = l1.next 42 | if l2 is not None: 43 | l2 = l2.next 44 | return res.next 45 | 46 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC20 Valid Parentheses/LC20.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 20. Valid Parentheses 3 | 4 | Description: 5 | Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. 6 | 7 | An input string is valid if: 8 | - Open brackets must be closed by the same type of brackets. 9 | - Open brackets must be closed in the correct order. 10 | ''' 11 | 12 | # @param s str 13 | # @return bool 14 | 15 | ### TC: O(n) and SC: O(n) 16 | class Solution: 17 | def isValid(self, s): 18 | 19 | stack = [] 20 | 21 | for i in range(len(s)): 22 | if s[i] == "(" or s[i] == "[" or s[i] == "{": 23 | stack.append(s[i]) 24 | 25 | elif s[i] == ")": 26 | if len(stack) == 0: 27 | return False 28 | prev = stack.pop() 29 | if prev != "(": 30 | return False 31 | 32 | elif s[i] == "}": 33 | if len(stack) == 0: 34 | return False 35 | prev = stack.pop() 36 | if prev != "{": 37 | return False 38 | 39 | elif s[i] == "]": 40 | if len(stack) == 0: 41 | return False 42 | prev = stack.pop() 43 | if prev != "[": 44 | return False 45 | 46 | if len(stack) > 0: 47 | return False 48 | else: 49 | return True -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC204 Count Primes/LC204.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 204. Count Primes 3 | 4 | Description: 5 | Given an integer n, return the number of prime numbers that are strictly less than n. 6 | ''' 7 | 8 | # @param n int 9 | # @return int 10 | 11 | ### Brute Solution 12 | class Solution: 13 | def countPrimes(self, n): 14 | if n <= 2: 15 | return 0 16 | count = 0 17 | for p in range(2, n): 18 | flag = 0 19 | for div in range(2, p): 20 | if p % div == 0: 21 | flag = 1 22 | break 23 | if flag == 0: 24 | count += 1 25 | return count 26 | 27 | ### Optimized Solution 28 | class Solution: 29 | def countPrimes(self, n): 30 | primes = [False, False] + [True] * (n - 2) 31 | for p in range(2, int(sqrt(n)) + 1): ### trick: to save time complexity 32 | if primes[p]: 33 | # for multiple in range(p * 2, n, p): ### set all multiples of p to False 34 | for multiple in range(p * p, n, p): ### can start from p*p because p * k where k < p has been checked 35 | primes[multiple] = False 36 | 37 | return sum(primes) ### the remaining true is primes -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC206 Reverse Linked List/LC206.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 206. Reverse Linked List 3 | 4 | Description: 5 | Given the head of a singly linked list, reverse the list, and return the reversed list. 6 | ''' 7 | 8 | # class ListNode: 9 | # def __init__(self, val=0, next=None): 10 | # self.val = val 11 | # self.next = next 12 | 13 | # @param head ListNode 14 | # @return ListNode 15 | 16 | ### TC: O(n) and SC: O(1) 17 | class Solution: 18 | def reverseList(self, head): 19 | dummy = ListNode() 20 | cur = head 21 | while cur: 22 | temp = cur.next 23 | cur.next = dummy.next 24 | dummy.next = cur 25 | cur = temp 26 | return dummy.next -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC209 Minimum Size Subarray Sum/LC209.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 209. Minimum Size Subarray Sum 3 | 4 | Description: 5 | Given an array of positive integers nums and a positive integer target, 6 | return the minimal length of a contiguous subarray [nums_l, nums_l+1, ..., nums_r-1, nums_r] 7 | of which the sum is greater than or equal to target. If there is no such subarray, return 0 instead. 8 | ''' 9 | 10 | # @param target int 11 | # @param nums List[int] 12 | # @return int 13 | 14 | ''' 15 | In this problem, all numbers are postive and we need to find the contiguous subarray 16 | ''' 17 | ### TC: O(n) and SC: O(n) 18 | class Solution: 19 | def minSubArrayLen(self, target, nums): 20 | ans = float("inf") 21 | curLength = 0 22 | cur = 0 23 | lp = 0 24 | for n in nums: 25 | cur += n 26 | curLength += 1 27 | if cur >= target: 28 | while cur - nums[lp] >= target: 29 | cur -= nums[lp] 30 | lp += 1 31 | curLength -= 1 32 | ans = min(ans, curLength) 33 | 34 | return 0 if ans == float("inf") else ans 35 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC21 Merge Two Sorted Lists/LC21.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 21. Merge Two Sorted Lists 3 | 4 | Description: 5 | You are given the heads of two sorted linked lists list1 and list2. 6 | 7 | Merge the two lists in a one sorted list. The list should be made by splicing together the nodes of the first two lists. 8 | 9 | Return the head of the merged linked list. 10 | ''' 11 | 12 | # class ListNode: 13 | # def __init__(self, val=0, next=None): 14 | # self.val = val 15 | # self.next = next 16 | 17 | # @param l1 ListNode 18 | # @param l2 ListNode 19 | # @return ListNode 20 | 21 | ### TC: O(n) and SC: O(1) 22 | class Solution: 23 | def mergeTwoLists(self, l1, l2): 24 | temp = ListNode() 25 | cur = temp 26 | while l1 and l2: 27 | if l1.val < l2.val: 28 | cur.next = l1 29 | l1 = l1.next 30 | else: 31 | cur.next = l2 32 | l2 = l2.next 33 | cur = cur.next 34 | cur.next = l1 if l1 else l2 35 | return temp.next -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC217 Contains Duplicate/LC217.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 217. Contains Duplicate 3 | 4 | Description: 5 | Given an integer array nums, return true if any value appears at least twice in the array, 6 | and return false if every element is distinct. 7 | ''' 8 | 9 | # @param nums List[int] 10 | # @return bool 11 | 12 | ### Hash Table Solution 13 | ### TC: O(n) and SC: O(n) 14 | class Solution: 15 | def containsDuplicate(self, nums): 16 | hashTable = set() 17 | for n in nums: 18 | if n in hashTable: 19 | return True 20 | else: 21 | hashTable.add(n) 22 | return False 23 | 24 | ### Sort Solution 25 | ### TC: O(nlogn) and SC: O(1) 26 | class Solution: 27 | def containsDuplicate(self, nums): 28 | def quickSort(arr, low, high): 29 | if low < high: 30 | import random 31 | r = random.randint(low, high) 32 | arr[r], arr[high] = arr[high], arr[r] 33 | 34 | pivot = arr[high] 35 | j = low ### the first number larger than pivot 36 | for i in range(low, high): 37 | if arr[i] < pivot: 38 | arr[i], arr[j] = arr[j], arr[i] 39 | j += 1 ### arr[j] is used, so we need to move j 40 | 41 | arr[j], arr[high] = arr[high], arr[j] 42 | 43 | quickSort(arr, low, j-1) 44 | quickSort(arr, j+1, high) 45 | 46 | quickSort(nums, 0, len(nums)-1) 47 | for i in range(len(nums)-1): 48 | if nums[i] == nums[i+1]: 49 | return True 50 | return False 51 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC219 Contains Duplicate II/LC219.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 219. Contains Duplicate II 3 | 4 | Description: 5 | Given an integer array nums and an integer k, 6 | return true if there are two distinct indices i and j in the array such that nums[i] == nums[j] and abs(i - j) <= k. 7 | ''' 8 | 9 | # @param nums List[int] 10 | # @param k int 11 | # @return bool 12 | 13 | ### Brute Solution 14 | ### TC: O(nk) and SC: O(1) 15 | class Solution: 16 | def containsNearbyDuplicate(self, nums, k): 17 | for i in range(len(nums)-1): 18 | for j in range(1,k+1): 19 | if i+j < len(nums): 20 | if nums[i] == nums[i+j]: 21 | return True 22 | else: 23 | break 24 | 25 | return False 26 | 27 | 28 | ### Hash Table Solution 29 | ### TC: O(n) and SC: O(k) 30 | class Solution: 31 | def containsNearbyDuplicate(self, nums, k): 32 | hashTable = set() 33 | for i in range(len(nums)): 34 | if nums[i] in hashTable: 35 | return True 36 | hashTable.add(nums[i]) 37 | if i >= k: 38 | hashTable.remove(nums[i-k]) 39 | 40 | return False -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC22 Generate Parentheses/LC22.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 22. Generate Parentheses 3 | 4 | Description: 5 | Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. 6 | ''' 7 | 8 | # @param n int 9 | # @return List[str] 10 | 11 | class Solution: 12 | def generateParenthesis(self, n): 13 | ans = [] 14 | def forward(path, n_lp, n_rp): 15 | if n_lp == n and n_rp == n: 16 | ans.append(''.join(path)) 17 | return 18 | if n_lp < n: 19 | path[n_lp+n_rp] = '(' 20 | forward(path, n_lp+1, n_rp) 21 | if n_rp < n_lp: 22 | path[n_lp+n_rp] = ')' 23 | forward(path, n_lp, n_rp+1) 24 | forward([None for _ in range(2*n)], 0, 0) 25 | return ans 26 | 27 | ### another version 28 | class Solution: 29 | def generateParenthesis(self, n: int) -> List[str]: 30 | ans = [] 31 | def forward(path, n_lp, n_rp): 32 | if n_lp == 0 and n_rp == 0: 33 | ans.append(''.join(path)) 34 | return 35 | else: 36 | if n_lp < n_rp: 37 | path[2*n-n_lp-n_rp] = ')' 38 | forward(path, n_lp, n_rp-1) 39 | if n_lp > 0: 40 | path[2*n-n_lp-n_rp] = '(' 41 | forward(path, n_lp-1, n_rp) 42 | forward([None for _ in range(2*n)], n, n) 43 | return ans -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC220 Contains Duplicate III/LC220.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 220. Contains Duplicate III 3 | 4 | Description: 5 | Given an integer array nums and two integers k and t, 6 | return true if there are two distinct indices i and j in the array such that abs(nums[i] - nums[j]) <= t and abs(i - j) <= k. 7 | ''' 8 | 9 | # @param nums List[int] 10 | # @param k int 11 | # @param t int 12 | # @return bool 13 | 14 | ''' 15 | Bucket Sort: 16 | Find the min and max is O(n). When we get the range of the data. 17 | We can divide the range into k buckets. 18 | We place each data in a bucket. And sort the bucket and concatenate the buckets. 19 | ''' 20 | 21 | ''' 22 | The trick of this problem is to store num // t in the hash table, this way we can mark the 23 | open interval [num, num + t), but we still need to check the left neighbour interval and num+t 24 | ''' 25 | ### TC: O(n) and SC: O(k) 26 | class Solution: 27 | def containsNearbyAlmostDuplicate(self, nums, k, t): 28 | hashTable = {} 29 | div = t if t > 0 else 1 ### corner case: t = 0 30 | for i in range(len(nums)): 31 | 32 | if nums[i] // div in hashTable: 33 | return True 34 | if nums[i] // div + 1 in hashTable: 35 | if hashTable[nums[i] // div + 1] - nums[i] == t: ### check the border of open interval 36 | return True 37 | if nums[i] // div - 1 in hashTable: 38 | 39 | if hashTable[nums[i] // div - 1] - nums[i] >= -t: ### check left neighbour interval 40 | return True 41 | hashTable[nums[i] // div] = nums[i] 42 | 43 | if i >= k: 44 | del hashTable[nums[i-k] // div] 45 | return False 46 | 47 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC226 Invert Binary Tree/LC226.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 226. Invert Binary Tree 3 | 4 | Description: 5 | Given the root of a binary tree, invert the tree, and return its root. 6 | ''' 7 | 8 | # class TreeNode: 9 | # def __init__(self, val=0, left=None, right=None): 10 | # self.val = val 11 | # self.left = left 12 | # self.right = right 13 | 14 | # @param root TreeNode 15 | # @return TreeNode 16 | 17 | ### TC: O(n) and SC: O(n) 18 | class Solution: 19 | def invertTree(self, root): 20 | if root: 21 | root.left, root.right = root.right, root.left 22 | self.invertTree(root.left) 23 | self.invertTree(root.right) 24 | return root 25 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC230 Kth Smallest Element in a BST/LC230.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 230. Kth Smallest Element in a BST 3 | 4 | Description: 5 | Given the root of a binary search tree, and an integer k, return the kth smallest value (1-indexed) of all the values of the nodes in the tree. 6 | ''' 7 | 8 | # class TreeNode: 9 | # def __init__(self, val=0, left=None, right=None): 10 | # self.val = val 11 | # self.left = left 12 | # self.right = right 13 | 14 | # @param root TreeNode 15 | # @param k int 16 | # @return int 17 | 18 | ### TC: O(k) and SC: O(k) 19 | class Solution: 20 | def kthSmallest(self, root, k): 21 | if root: 22 | n = 0 23 | stack = [root] 24 | nextToVisit = root 25 | ans = [] 26 | while stack: 27 | while nextToVisit.left: 28 | 29 | stack.append(nextToVisit.left) 30 | nextToVisit = nextToVisit.left 31 | 32 | 33 | cur = stack.pop() 34 | ans.append(cur.val) 35 | n += 1 36 | if n == k: 37 | return cur.val 38 | 39 | if cur.right: 40 | stack.append(cur.right) 41 | nextToVisit = cur.right 42 | return -1 -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC231 Power of Two/LC231.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 231. Power of Two 3 | 4 | Description: 5 | Given an integer n, return true if it is a power of two. Otherwise, return false. 6 | 7 | An integer n is a power of two, if there exists an integer x such that n == 2^x. 8 | ''' 9 | 10 | # @param n int 11 | # @return bool 12 | 13 | ''' 14 | Power of two has just one 1-bit. 15 | ''' 16 | ### TC: O(n) and SC: O(n) 17 | class Solution: 18 | def isPowerOfTwo(self, n): 19 | if n == 0: 20 | return False 21 | return n & (n - 1) == 0 -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC235 owest Common Ancestor of a Binary Search Tree/LC235.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 235. Lowest Common Ancestor of a Binary Search Tree 3 | 4 | Description: 5 | Given a binary search tree (BST), find the lowest common ancestor (LCA) node of two given nodes in the BST. 6 | According to the definition of LCA on Wikipedia: 7 | “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants 8 | where we allow a node to be a descendant of itself.” 9 | ''' 10 | 11 | # class TreeNode: 12 | # def __init__(self, x): 13 | # self.val = x 14 | # self.left = None 15 | # self.right = None 16 | 17 | # @param root TreeNode 18 | # @param p TreeNode 19 | # @param q TreeNode 20 | # @return TreeNode 21 | 22 | ### Iterative Solution 23 | ### TC: O(n) and SC: O(1) 24 | class Solution: 25 | def lowestCommonAncestor(self, root, p, q): 26 | node = root 27 | while node: 28 | parent_val = node.val 29 | if node.val == p.val or node.val == q.val: ### the first time a node's val equals to p or q, it means that the LCA has been found 30 | return node 31 | elif node.val < p.val and node.val < q.val: 32 | node = node.right 33 | elif node.val > p.val and node.val > q.val: 34 | node = node.left 35 | else: ### Trick: if p and q are not in the same side, then we find the LCA 36 | return node -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC24 Swap Nodes in Pairs/LC24.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 24. Swap Nodes in Pairs 3 | 4 | Description: 5 | Given a linked list, swap every two adjacent nodes and return its head. 6 | You must solve the problem without modifying the values in the list's nodes (i.e., only nodes themselves may be changed.) 7 | ''' 8 | 9 | # class ListNode: 10 | # def __init__(self, val=0, next=None): 11 | # self.val = val 12 | # self.next = next 13 | 14 | # @param head ListNode 15 | # @return ListNode 16 | 17 | ### TC: O(n) and SC: O(1) 18 | class Solution: 19 | def swapPairs(self, head): 20 | dummy = ListNode() 21 | dummy.next = head 22 | prev = dummy 23 | 24 | slow = head 25 | fast = head 26 | 27 | while fast and fast.next: 28 | fast = fast.next.next 29 | prev.next = slow.next 30 | prev.next.next = slow 31 | slow.next = fast 32 | prev = prev.next.next 33 | slow = fast 34 | 35 | return dummy.next 36 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC240 Search a 2D Matrix II/LC240.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 240. Search a 2D Matrix II 3 | 4 | Description: 5 | Write an efficient algorithm that searches for a target value in an m x n integer matrix. The matrix has the following properties: 6 | - Integers in each row are sorted in ascending from left to right. 7 | - Integers in each column are sorted in ascending from top to bottom. 8 | ''' 9 | 10 | # @param matrix List[List[int]] 11 | # @param target int 12 | # @return bool 13 | 14 | ''' 15 | Searching all kinds of sorted arrays should be implemented with binary search. 16 | The key to this problem is to find the pivot (which we can help us know which side to go. 17 | Arr 0 1 2 3 4 18 | 0 < < < < pivot 19 | 1 > 20 | 2 > 21 | 3 tar > 22 | 4 > 23 | 24 | We can eliminate one row or column at a time. 25 | ''' 26 | 27 | ### TC: O(m+n) and SC: O(1) 28 | class Solution: 29 | def searchMatrix(self, matrix, target): 30 | m, n = len(matrix), len(matrix[0]) 31 | x = 0 32 | y = n-1 33 | while x < m and y >= 0: 34 | pivot = matrix[x][y] 35 | if pivot == target: 36 | return True 37 | elif pivot < target: 38 | x += 1 39 | else: 40 | y -= 1 41 | return False 42 | 43 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC252 Meeting Rooms/LC252.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 252. Meeting Rooms 3 | 4 | Description: 5 | Given an array of meeting time intervals where intervals[i] = [start_i, end_i], determine if a person could attend all meetings. 6 | 7 | Example 1 8 | Input: intervals = [[0,30],[5,10],[15,20]] 9 | Output: false 10 | 11 | Example 2 12 | Input: intervals = [[7,10],[2,4]] 13 | Output: true 14 | ''' 15 | 16 | # @param intervals List[List[int]] 17 | # @return bool 18 | 19 | ### Intuitive Sort Solution 20 | ### TC: O(nlogn) and SC: O(1) 21 | class Solution: 22 | def canAttendMeetings(self, intervals): 23 | intervals.sort(key = lambda x: x[0]) 24 | for i in range(len(intervals) - 1): 25 | if intervals[i][1] > intervals[i+1][0]: 26 | return False 27 | return True 28 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC26 Remove Duplicates from Sorted Array/LC26.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 26. Remove Duplicates from Sorted Array 3 | 4 | Description: 5 | Given an integer array nums sorted in non-decreasing order, remove the duplicates in-place such that each unique element appears only once. 6 | The relative order of the elements should be kept the same. 7 | 8 | Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums. 9 | More formally, if there are k elements after removing the duplicates, then the first k elements of nums should hold the final result. It does not matter what you leave beyond the first k elements. 10 | 11 | Return k after placing the final result in the first k slots of nums. 12 | 13 | Do not allocate extra space for another array. You must do this by modifying the input array in-place with O(1) extra memory. 14 | ''' 15 | 16 | # @param nums List[int] 17 | # @return int 18 | 19 | ### TC: O(n) and SC: O(1) 20 | class Solution: 21 | def removeDuplicates(self, nums): 22 | j = 0 ### prev 23 | i = 1 ### cur 24 | originLen = len(nums) 25 | while i < len(nums): 26 | if nums[i] == nums[j]: 27 | del nums[i] 28 | originLen -= 1 29 | else: 30 | j += 1 31 | i += 1 32 | return originLen -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC268 Missing Number/LC268.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 268. Missing Number 3 | 4 | Description: 5 | Given an array nums containing n distinct numbers in the range [0, n], return the only number in the range that is missing from the array. 6 | ''' 7 | 8 | # @param nums List[int] 9 | # @return int 10 | 11 | ### Sort Solution 12 | ### TC: O(nlogn) and SC: O(1) 13 | class Solution: 14 | def missingNumber(self, nums): 15 | nums.sort() 16 | for i in range(len(nums)): 17 | if nums[i] != i: 18 | return i 19 | return len(nums) ### the only left one is n 20 | 21 | ### Hash Set Solution 22 | ### TC: O(n) and SC: O(n) 23 | class Solution: 24 | def missingNumber(self, nums): 25 | hashTable = set(nums) 26 | for i in range(len(nums)+1): 27 | if i not in hashTable: 28 | return i 29 | 30 | ### Sum Solution 31 | ### TC: O(n) and SC: O(1) 32 | class Solution: 33 | def missingNumber(self, nums): 34 | n = len(nums) 35 | S = int(n * (n+1) / 2) 36 | return S - sum(nums) 37 | 38 | ### XOR Solution 39 | ### TC: O(n) and SC: O(1) 40 | class Solution: 41 | def missingNumber(self, nums): 42 | res = 0 43 | for i in range(1, len(nums)+1): 44 | res ^= i 45 | 46 | for n in nums: 47 | res ^= n 48 | 49 | return res -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC27 Remove Element/LC27.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 27. Remove Element 3 | 4 | Description: 5 | Given an integer array nums and an integer val, remove all occurrences of val in nums in-place. 6 | The relative order of the elements may be changed. 7 | 8 | Since it is impossible to change the length of the array in some languages, 9 | you must instead have the result be placed in the first part of the array nums. 10 | More formally, if there are k elements after removing the duplicates, 11 | then the first k elements of nums should hold the final result. 12 | It does not matter what you leave beyond the first k elements. 13 | 14 | Return k after placing the final result in the first k slots of nums. 15 | 16 | Do not allocate extra space for another array. You must do this by modifying the input array in-place with O(1) extra memory. 17 | ''' 18 | 19 | # @param nums List[int] 20 | # @param val int 21 | # @return int 22 | 23 | ### TC: O(n) and SC: O(1) 24 | class Solution: 25 | def removeElement(self, nums, val): 26 | j = 0 27 | for i in range(len(nums)): 28 | if nums[i] != val: 29 | nums[i], nums[j] = nums[j], nums[i] 30 | j += 1 31 | return j -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC283 Move Zeros/LC283.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 283. Move Zeroes 3 | 4 | Description: 5 | Given an integer array nums, move all 0's to the end of it while maintaining the relative order of the non-zero elements. 6 | 7 | Note that you must do this in-place without making a copy of the array. 8 | ''' 9 | 10 | # @param nums List[int] 11 | # @return None 12 | 13 | ### TC: O(n) and SC: O(1) 14 | class Solution: 15 | def moveZeroes(self, nums): 16 | lp = 0 ### refer to quick sort 17 | for rp in range(len(nums)): 18 | if nums[rp] != 0: 19 | nums[lp], nums[rp] = nums[rp], nums[lp] 20 | lp += 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC285 Inorder Successor in BST/LC285.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 285. Inorder Successor in BST 3 | 4 | Description: 5 | Given the root of a binary search tree and a node p in it, return the in-order successor of that node in the BST. 6 | If the given node has no in-order successor in the tree, return null. 7 | 8 | The successor of a node p is the node with the smallest key greater than p.val. 9 | ''' 10 | 11 | # class TreeNode: 12 | # def __init__(self, x): 13 | # self.val = x 14 | # self.left = None 15 | # self.right = None 16 | 17 | # @param root TreeNode 18 | # @param p TreeNode 19 | # @return TreeNode 20 | 21 | ### TC: O(n) and SC: O(1) if the BST is balanced, TC will be O(logn) 22 | class Solution: 23 | def inorderSuccessor(self, root, p): 24 | successor = None 25 | while root: 26 | if root.val <= p.val: 27 | root = root.right 28 | else: 29 | successor = root 30 | root = root.left 31 | return successor 32 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC287 Find the Duplicate Number/LC287.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 287. Find the Duplicate Number 3 | 4 | Description: 5 | Given an array of integers nums containing n + 1 integers where each integer is in the range [1, n] inclusive. 6 | 7 | There is only one repeated number in nums, return this repeated number. 8 | 9 | You must solve the problem without modifying the array nums and uses only constant extra space. 10 | ''' 11 | 12 | # @param nums List[int] 13 | # @return int 14 | 15 | 16 | ''' 17 | Negative Mark 18 | ''' 19 | ### TC: O(n) and SC: O(1) 20 | class Solution: 21 | def findDuplicate(self, nums): 22 | for i in range(len(nums)): 23 | if nums[abs(nums[i])] < 0: 24 | return abs(nums[i]) 25 | else: 26 | nums[abs(nums[i])] = -nums[abs(nums[i])] 27 | 28 | ''' 29 | [2,4,3,1,1] 30 | ''' 31 | ### Linked List Cycle (Floyd's Tortoise and Hare) 32 | ### TC: O(n) and SC: O(1) 33 | class Solution: 34 | def findDuplicate(self, nums): 35 | fast = nums[0] 36 | slow = nums[0] 37 | while True: 38 | fast = nums[nums[fast]] 39 | slow = nums[slow] 40 | if slow == fast: 41 | break 42 | 43 | ### find the entrance of the cycle. 44 | slow = nums[0] 45 | while slow != fast: 46 | slow = nums[slow] 47 | fast = nums[fast] 48 | 49 | return fast -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC30 Substring with Concatenation of All Words/LC30.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 30. Substring with Concatenation of All Words 3 | 4 | Description: 5 | You are given a string s and an array of strings words of the same length. 6 | Return all starting indices of substring(s) in s that is a concatenation of each word in words exactly once, in any order, and without any intervening characters. 7 | 8 | You can return the answer in any order. 9 | 10 | Example 11 | Input: s = "barfoothefoobarman", words = ["foo","bar"] 12 | Output: [0,9] 13 | Explanation: Substrings starting at index 0 and 9 are "barfoo" and "foobar" respectively. 14 | ''' 15 | 16 | # @param s str 17 | # @param words List[str] 18 | # @return List[int] 19 | 20 | ### TC: O(n^2logn) and SC: O(n) 21 | class Solution: 22 | def findSubstring(self, s, words): 23 | n, w = len(words), len(words[0]) 24 | words.sort() 25 | def check(string): 26 | combo = [] 27 | for i in range(0,len(string), w): 28 | combo.append(string[i:i+w]) 29 | return sorted(combo) == words 30 | 31 | ans = [] 32 | lp = 0 33 | for rp in range(w*n, len(s)+1): 34 | if check(s[lp:rp]): 35 | ans.append(lp) 36 | lp += 1 37 | return ans 38 | 39 | 40 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC325 Maximum Size Subarray Sum Equals k/LC325.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 325. Maximum Size Subarray Sum Equals k 3 | 4 | Description: 5 | Given an integer array nums and an integer k, return the maximum length of a subarray that sums to k. 6 | If there is not one, return 0 instead. 7 | ''' 8 | 9 | # @param nums List[int] 10 | # @param k int 11 | # @return int 12 | 13 | 14 | ''' 15 | Refer to LC560 16 | sum(arr[i:j]) = sum(arr[:j]) - sum(arr[:i]) 17 | target = sum(arr[:j]) - sum(arr[:i]) 18 | complement = sum(arr[:j]) - target 19 | If we use hash table to store all cumulative sums, we can check complement to target k in O(1) and we can achieve one pass iteration. 20 | ''' 21 | ### TC: O(n) and SC: O(n) 22 | class Solution: 23 | def maxSubArrayLen(self, nums, k): 24 | hashTable = {0:-1} ### sum[:i] : i 25 | ans = 0 26 | cur = 0 27 | for i, num in enumerate(nums): 28 | cur += num 29 | if cur - k in hashTable: 30 | ans = max(ans, i-hashTable[cur - k]) 31 | if cur not in hashTable: 32 | hashTable[cur] = i 33 | 34 | return ans -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC329 Longest Increasing Path in a Matrix/LC329.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 329. Longest Increasing Path in a Matrix 3 | 4 | Description: 5 | Given an m x n integers matrix, return the length of the longest increasing path in matrix. 6 | 7 | From each cell, you can either move in four directions: left, right, up, or down. 8 | You may not move diagonally or move outside the boundary (i.e., wrap-around is not allowed). 9 | ''' 10 | 11 | # @param matrix List[List[int]] 12 | # @return int 13 | 14 | ''' 15 | 这题因为是找递增,所以其实是个有向图 16 | ''' 17 | ### Recursion with memoization 18 | ### TC: O(mn) and SC: O(mn) 19 | class Solution: 20 | def longestIncreasingPath(self, matrix): 21 | visited = {} 22 | ans = 1 23 | m, n = len(matrix), len(matrix[0]) 24 | def DFS(x,y): 25 | nonlocal m, n, visited 26 | if (x,y) in visited: 27 | return visited[(x,y)] 28 | 29 | directions = [(1,0), (-1,0), (0,1), (0,-1)] 30 | curMAX = 1 31 | for dx, dy in directions: 32 | X, Y = x+dx, y+dy 33 | if 0 <= X < m and 0 <= Y < n and matrix[X][Y] > matrix[x][y]: 34 | curMAX = max(curMAX, DFS(X, Y)+1) 35 | 36 | visited[(x,y)] = curMAX ### memorization 37 | 38 | return curMAX 39 | 40 | 41 | for i in range(m): 42 | for j in range(n): 43 | ans = max(ans, DFS(i,j)) 44 | 45 | return ans 46 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC338 Counting Bits/LC338.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 338. Counting Bits 3 | 4 | Description: 5 | Given an integer n, return an array ans of length n + 1 such that for each i (0 <= i <= n), ans[i] is the number of 1's in the binary representation of i. 6 | 7 | Example 8 | Input: n = 5 9 | Output: [0,1,1,2,1,2] 10 | ans[0] : 0 0 11 | ans[1] : 1 1 12 | ans[2] : 2 10 13 | ans[3] : 3 11 14 | ans[4] : 4 100 15 | ans[5] : 5 101 16 | ''' 17 | 18 | # @param n int 19 | # @return List[int] 20 | 21 | ### Brute Solution 22 | ### TC: O(nlogn) and SC: O(1) 23 | class Solution: 24 | def countBits(self, n): 25 | ans = [] 26 | for i in range(n+1): 27 | count = 0 28 | while i: 29 | if i & 1: ### whether the last bit is 1 30 | count += 1 31 | i = i >> 1 32 | ans.append(count) 33 | return ans 34 | 35 | 36 | ''' 37 | x = 1001011101 38 | x >> 1 = 100101110 39 | 40 | DP[x] = DP[x >> 1] + x & 1 41 | ''' 42 | ### DP Solution 43 | ### TC: O(n) and SC: O(1) 44 | class Solution: 45 | def countBits(self, n): 46 | ans = [0] * (n + 1) 47 | for i in range(n+1): 48 | ans[i] = ans[i >> 1] + (i & 1) 49 | return ans -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC35 Search Insert Position/LC35.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 35. Search Insert Position 3 | 4 | Description: 5 | Given a sorted array of distinct integers and a target value, return the index if the target is found. 6 | If not, return the index where it would be if it were inserted in order. 7 | 8 | You must write an algorithm with O(log n) runtime complexity. 9 | ''' 10 | 11 | # @param nums List[int] 12 | # @param target int 13 | # @return int 14 | 15 | ### TC: O(logn) and SC: O(1) 16 | class Solution: 17 | def searchInsert(self, nums, target): 18 | lp = 0 19 | rp = len(nums)-1 20 | while lp <= rp: 21 | mid = (lp + rp) // 2 22 | if nums[mid] == target: 23 | return mid 24 | elif nums[mid] < target: 25 | lp = mid + 1 26 | else: 27 | rp = mid - 1 28 | return lp 29 | 30 | ### Another Version 31 | class Solution: 32 | def searchInsert(self, nums, target): 33 | lp = 0 34 | rp = len(nums)-1 35 | while lp < rp: 36 | mid = (lp + rp) // 2 37 | if nums[mid] == target: 38 | return mid 39 | elif nums[mid] > target: 40 | rp = mid 41 | else: 42 | lp = mid + 1 43 | if nums[lp] < target: 44 | return lp + 1 45 | else: 46 | return lp -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC387 First Unique Character in a String/LC387.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 387. First Unique Character in a String 3 | 4 | Description: 5 | Given a string s, find the first non-repeating character in it and return its index. If it does not exist, return -1. 6 | ''' 7 | 8 | # @param s str 9 | # @return int 10 | 11 | ### TC: O(n) and SC: O(1) (Because the number of chars is limited) 12 | class Solution: 13 | def firstUniqChar(self, s): 14 | hashTable = [0]*26 ### English alphabet only has 26 letters 15 | for char in s: 16 | hashTable[ord(char)-ord('a')] += 1 17 | 18 | for idx, char in enumerate(len(s)): 19 | if hashTable[ord(char)-ord('a')] == 1: 20 | return idx 21 | 22 | return -1 -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC39 Combination Sum/LC39.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 39. Combination Sum 3 | 4 | Description: 5 | Given an array of distinct positive integers candidates and a target integer target, 6 | return a list of all unique combinations of candidates where the chosen numbers sum to target. 7 | You may return the combinations in any order. 8 | 9 | The same number may be chosen from candidates an unlimited number of times. 10 | Two combinations are unique if the frequency of at least one of the chosen numbers is different. 11 | 12 | It is guaranteed that the number of unique combinations that sum up to target is less than 150 combinations for the given input. 13 | ''' 14 | 15 | ''' 16 | Must all positive, if there is negative number and the same number can be use for any times, this problem can not be solved. 17 | ''' 18 | 19 | # @param candidates List[int] 20 | # @param target int 21 | # @return List[List[int]] 22 | 23 | 24 | class Solution: 25 | def combinationSum(self, candidates, target): 26 | ans = [] 27 | # candidates.sort() ### important: sort all numbers and incrementally build the combination 28 | def DFS(res, path, idx): 29 | if res == 0: 30 | ans.append(path[:]) 31 | return 32 | 33 | for i in range(idx, len(candidates)): 34 | if res - candidates[i] < 0: 35 | # break ### other options are larger than current one, if we have sorted the array 36 | continue 37 | else: 38 | path.append(candidates[i]) 39 | DFS(res-candidates[i], path, i) 40 | path.pop() ### backtrack 41 | DFS(target, [], 0) 42 | return ans 43 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC392 Is Subsequence/LC392.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 392. Is Subsequence 3 | 4 | Description: 5 | Given two strings s and t, return true if s is a subsequence of t, or false otherwise. 6 | 7 | A subsequence of a string is a new string that is formed from the original string 8 | by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. 9 | i.e., "ace" is a subsequence of "abcde" while "aec" is not 10 | ''' 11 | 12 | # @param s str 13 | # @param t str 14 | # @return bool 15 | 16 | ### Two Pointer Solution 17 | ### TC: O(n) and SC: O(1) 18 | class Solution: 19 | def isSubsequence(self, s, t): 20 | p1 = 0 21 | p2 = 0 22 | while p1 < len(s) and p2 < len(t): 23 | if s[p1] == t[p2]: 24 | p1 += 1 25 | p2 += 1 26 | return p1 == len(s) -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC402 Remove K Digits/LC402.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 402. Remove K Digits 3 | 4 | Description: 5 | Given string num representing a non-negative integer num, and an integer k, 6 | return the smallest possible integer after removing k digits from num. 7 | ''' 8 | 9 | # @param num str 10 | # @param k int 11 | # @return str 12 | 13 | ### Monotonic Stack 14 | ### TC: O(n) and SC: O(n) 15 | class Solution: 16 | def removeKdigits(self, num, k): 17 | if k >= len(num): ### corner case 18 | return '0' 19 | if k == 0: ### corner case 20 | return num 21 | 22 | stack = [] 23 | for digit in num: 24 | while stack and stack[-1] > digit and k: ### trick 25 | stack.pop() 26 | k -= 1 27 | stack.append(digit) 28 | 29 | if k > 0: 30 | stack = stack[:-k] ### at this time, stack is ascending, we just remove the last k digits 31 | 32 | while stack and stack[0] == '0': 33 | stack.pop(0) 34 | 35 | return ''.join(stack) if stack else '0' 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC41 First Missing Positive/LC41.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 3 | 4 | Description: 5 | Given an unsorted integer array nums, return the smallest missing positive integer. 6 | 7 | You must implement an algorithm that runs in O(n) time and uses constant extra space. 8 | 9 | Example 1 10 | Input: nums = [3,4,-1,1] 11 | Output: 2 12 | 13 | Example 2 14 | Input: nums = [1,2,0] 15 | Output: 3 16 | ''' 17 | 18 | # @param nums List[int] 19 | # @return int 20 | 21 | ### 这题难在会有负数和0 22 | 23 | ### TC: O(n) and SC: O(1) 24 | class Solution: 25 | def firstMissingPositive(self, nums): 26 | i = 0 27 | while i < len(nums): 28 | cur = nums[i] 29 | if 0 < cur <= len(nums) and nums[cur-1] != cur: 30 | nums[i], nums[cur-1] = nums[cur-1], nums[i] ### we can not move forward after swapping, because we don't know what number is swapped to here e.g. [0,4,2,1] 31 | ### trick: i remains the same 32 | else: 33 | i += 1 34 | 35 | curMAX = len(nums)+1 ### trick: default answer is len(nums)+1 因为最极端的情况每个index对应的数都有,那这时候最小的缺失正数就是n+1 36 | for i in range(len(nums)): 37 | if nums[i] != i+1: ### 如果有index对应的正数没被标记,说明这个正数缺失的,但这题不能用negative mark因为数组中可能存在负数 38 | curMAX = i+1 39 | break 40 | return curMAX 41 | 42 | class Solution: 43 | def firstMissingPositive(self, nums): 44 | n = len(nums) 45 | nums = set(nums) 46 | for i in range(1, n+1): 47 | if i not in nums: 48 | return i 49 | return n+1 50 | 51 | 52 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC414 Third Maximum Number/LC414.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 414. Third Maximum Number 3 | 4 | Description: 5 | Given an integer array nums, return the third distinct maximum number in this array. 6 | If the third maximum does not exist, return the maximum number. 7 | ''' 8 | 9 | # @param nums List[int] 10 | # @return int 11 | 12 | 13 | ### Intuitive Solution 14 | ### TC: O(n) and SC: O(n) 15 | class Solution: 16 | def thirdMax(self, nums): 17 | nums = set(nums) ### use set to find 3 maximums to achieve efficiency 18 | if len(nums) < 3: ### corner case 19 | return max(nums) 20 | 21 | MAX = max(nums) 22 | nums.remove(MAX) ### delete the first maximum 23 | 24 | MAX = max(nums) 25 | nums.remove(MAX) ### delete the second maximum 26 | 27 | return max(nums) 28 | 29 | ### Optimized Solution 30 | ### TC: O(n) and SC: O(1) 31 | class Solution: 32 | def thirdMax(self, nums): 33 | maximums = set() ### maintain three maximums 34 | for n in nums: 35 | if len(maximums) < 3: 36 | maximums.add(n) 37 | else: 38 | if n not in maximums and n > min(maximums): ### trick 39 | maximums.remove(min(maximums)) 40 | maximums.add(n) 41 | 42 | if len(maximums) < 3: 43 | return max(maximums) 44 | else: 45 | return min(maximums) -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC429 N-ary Tree Level Order Traversal/LC429.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 429. N-ary Tree Level Order Traversal 3 | 4 | Description: 5 | Given an n-ary tree, return the level order traversal of its nodes' values. 6 | 7 | Nary-Tree input serialization is represented in their level order traversal, 8 | each group of children is separated by the null value (See examples). 9 | 10 | Example: 11 | 1 12 | 2 3 4 5 13 | 6 7 8 9 10 14 | 11 12 13 15 | 14 16 | Input: root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14] 17 | Output: [[1],[2,3,4,5],[6,7,8,9,10],[11,12,13],[14]] 18 | ''' 19 | 20 | ### LC428 Serialize and Deserialize N-ary Tree 21 | 22 | # class Node: 23 | # def __init__(self, val=None, children=None): 24 | # self.val = val 25 | # self.children = children 26 | 27 | # @param root Node 28 | # @return List[List[int]] 29 | 30 | ### TC: O(n) and SC: O(n) 31 | from collections import deque 32 | class Solution: 33 | def levelOrder(self, root): 34 | res = [] 35 | if root is None: ### corner case 36 | return res 37 | cur_level = deque([root]) 38 | while cur_level: 39 | next_level = deque() 40 | res.append([]) 41 | while cur_level: 42 | cur = cur_level.popleft() 43 | if cur: 44 | res[-1].append(cur.val) 45 | if cur.children: 46 | next_level.extend(cur.children) 47 | 48 | cur_level = next_level 49 | return res 50 | 51 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC437 Path Sum III/LC437.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 437. Path Sum III 3 | 4 | Description: 5 | Given the root of a binary tree and an integer targetSum, return the number of paths where the sum of the values along the path equals targetSum. 6 | 7 | The path does not need to start or end at the root or a leaf, but it must go downwards (i.e., traveling only from parent nodes to child nodes). 8 | ''' 9 | 10 | # class TreeNode: 11 | # def __init__(self, val=0, left=None, right=None): 12 | # self.val = val 13 | # self.left = left 14 | # self.right = right 15 | 16 | # @param root TreeNode 17 | # @param targetSum int 18 | # @return int 19 | 20 | class Solution: 21 | res = 0 22 | def pathSum(self, root, targetSum): 23 | self.res = 0 24 | def DFS(node, curSum): 25 | if node: 26 | curSum += node.val 27 | if curSum == targetSum: 28 | self.res += 1 29 | DFS(node.left, curSum) ### keep searching 30 | DFS(node.right, curSum) ### keep searching 31 | 32 | def startPathFrom(node): 33 | if node: 34 | DFS(node, 0) 35 | startPathFrom(node.left) 36 | startPathFrom(node.right) 37 | 38 | startPathFrom(root) 39 | return self.res 40 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC448 Find All Numbers Disappeared in an Array/LC448.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 448. Find All Numbers Disappeared in an Array 3 | 4 | Description: 5 | Given an array nums of n integers where nums[i] is in the range [1, n], 6 | return an array of all the integers in the range [1, n] that do not appear in nums. 7 | ''' 8 | 9 | # @param nums List[int] 10 | # @return List[int] 11 | 12 | ### Intuitive Hash Table Solution 13 | ### TC: O(n) and SC: O(n) 14 | class Solution: 15 | def findDisappearedNumbers(self, nums): 16 | hashTable = [0]*len(nums) 17 | for num in nums: 18 | hashTable[num-1] += 1 19 | ans = [] 20 | for i in range(len(nums)): 21 | if hashTable[i] == 0: 22 | ans.append(i+1) 23 | return ans 24 | 25 | ### Inplace Solution (refer to JZ3) 26 | ### TC: O(n) and SC: O(1) 27 | class Solution: 28 | def findDisappearedNumbers(self, nums): 29 | for i in range(len(nums)): 30 | if nums[abs(nums[i])-1] > 0: ### each index corresponds to a number 31 | nums[abs(nums[i])-1] = - nums[abs(nums[i])-1] ### use negative value to mark whether the number is visited 32 | ans = [] 33 | for i in range(len(nums)): 34 | if nums[i] > 0: 35 | ans.append(i+1) 36 | return ans -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC45 Jump Game II/LC45.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 45. Jump Game II 3 | 4 | Description: 5 | Given an array of non-negative integers nums, you are initially positioned at the first index of the array. 6 | 7 | Each element in the array represents your maximum jump length at that position. 8 | 9 | Your goal is to reach the last index in the minimum number of jumps. 10 | 11 | You can assume that you can always reach the last index. 12 | ''' 13 | 14 | # @param nums List[int] 15 | # @return int 16 | 17 | ### Greedy Solution 18 | ### TC: O(n) and SC: O(1) 19 | class Solution: 20 | def jump(self, nums): 21 | jumps = 0 22 | currentJumpEnd = 0 23 | canReach = 0 24 | for i in range(len(nums)-1): ### trick: we will end at the last index, we will not consider it 25 | canReach = max(canReach, i + nums[i]) 26 | if i == currentJumpEnd: ### [2 5 1 0 0] 27 | jumps += 1 ### jumps update when i = 0 and i = 2 (have to move) 28 | currentJumpEnd = canReach 29 | return jumps 30 | 31 | 32 | ### DP Solution 33 | class Solution: 34 | def jump(self, nums): 35 | DP_table = [float("inf")] * len(nums) ### inf means unreachable 36 | DP_table[0] = 0 37 | 38 | for i in range(len(nums)): 39 | for j in range(i): 40 | if DP_table[j] != float("inf") and j + nums[j] >= i: ### can access i from j 41 | DP_table[i] = min(DP_table[i], DP_table[j] + 1) 42 | return DP_table[-1] -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC46 Permutations/LC46.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 46. Permutations 3 | 4 | Description: 5 | Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order. 6 | ''' 7 | 8 | # @param nums List[int] 9 | # @return List[List[int]] 10 | 11 | 12 | ''' 13 | This problem is easy, all numbers are different. 14 | ''' 15 | class Solution: 16 | def permute(self, nums): 17 | ans = [] 18 | def forward(idx): 19 | if idx == len(nums): 20 | ans.append(nums[:]) 21 | else: 22 | for i in range(idx, len(nums)): ### start from idx, because each number can choose to stay the same, not to swap 23 | nums[i], nums[idx] = nums[idx], nums[i] ### swap 24 | forward(idx+1) 25 | nums[i], nums[idx] = nums[idx], nums[i] ### backtrack 26 | forward(0) 27 | return ans 28 | 29 | 30 | ### Counter Solution 31 | from collections import Counter 32 | class Solution: 33 | def permute(self, nums): 34 | ans = [] 35 | def forward(perm, counter): 36 | if len(perm) == len(nums): 37 | ans.append(perm[:]) 38 | else: 39 | for n in counter: 40 | if counter[n] > 0: ### still can put in the permutation 41 | perm.append(n) 42 | counter[n] -= 1 43 | 44 | forward(perm, counter) 45 | 46 | perm.pop() ### backtrack 47 | counter[n] += 1 48 | 49 | forward([], Counter(nums)) 50 | return ans -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC461 Hamming Distance/LC461.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 461. Hamming Distance 3 | 4 | Description: 5 | The Hamming distance between two integers is the number of positions at which the corresponding bits are different. 6 | 7 | Given two integers x and y, return the Hamming distance between them. 8 | 9 | Example: 10 | Input: x = 1 (0 0 0 1), y = 4 (0 1 0 0) 11 | Output: 2 12 | ''' 13 | 14 | # @param x int 15 | # @param y int 16 | # @return int 17 | 18 | class Solution: 19 | def hammingDistance(self, x, y): 20 | # return bin(x ^ y).count('1') 21 | xor = x ^ y 22 | distance = 0 23 | while xor: 24 | # mask out the rest bits 25 | if xor & 1: 26 | distance += 1 27 | xor = xor >> 1 28 | return distance 29 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC470 Implement Rand10 Using Rand7/LC470.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 470. Implement Rand10() Using Rand7() 3 | 4 | Description: 5 | Given the API rand7() that generates a uniform random integer in the range [1, 7], 6 | write a function rand10() that generates a uniform random integer in the range [1, 10]. 7 | You can only call the API rand7(), and you shouldn't call any other API. Please do not use a language's built-in random API. 8 | 9 | Each test case will have one internal argument n, the number of times that your implemented function rand10() will be called while testing. 10 | Note that this is not an argument passed to rand10(). 11 | ''' 12 | 13 | # @return int 14 | 15 | import random 16 | 17 | ''' 18 | p = 40/ 49 19 | E(# loops) = 1 * p + 2 * (1-p) * p + 3 * (1-p)^2 * p + ... 20 | ''' 21 | ### Rejection Samping 22 | class Solution: 23 | def rand10(self): 24 | flag = True 25 | while flag: 26 | bit_1 = random.randint(1,7) 27 | bit_2 = random.randint(1,7) 28 | idx = bit_1 + (bit_2-1) * 7 ### trick 29 | 30 | if idx > 40: ### (7*7 // 10) * 10 31 | continue 32 | else: 33 | return idx % 10 + 1 34 | 35 | 36 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC48 Rotate Image/LC48.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 48. Rotate Image 3 | 4 | Description: 5 | You are given an n x n 2D matrix representing an image, rotate the image by 90 degrees (clockwise). 6 | 7 | You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation. 8 | ''' 9 | 10 | # @param matrix List[List[int]] 11 | # @return None 12 | 13 | ''' 14 | rotate 15 | 1 2 3 7 4 1 16 | 4 5 6 -> 8 5 2 17 | 7 8 9 9 6 3 18 | 19 | transpose mirrot 20 | 1 2 3 1 4 7 7 4 1 21 | 4 5 6 -> 2 5 8 -> 8 5 2 22 | 7 8 9 3 6 9 9 6 3 23 | 24 | ''' 25 | 26 | class Solution: 27 | def rotate(self, matrix): 28 | def transpose(matrix): 29 | n = len(matrix) 30 | for i in range(n): 31 | for j in range(i, n): 32 | matrix[j][i], matrix[i][j] = matrix[i][j], matrix[j][i] 33 | 34 | def transpose(matrix): 35 | m, n = len(matrix), len(matrix) 36 | matrixT = [[None]*m for _ in range(n)] 37 | for i in range(n): 38 | for j in range(m): 39 | matrixT[i][j] = matrix[j][i] 40 | return matrixT 41 | 42 | 43 | def mirror(matrix): 44 | n = len(matrix) 45 | for i in range(n): 46 | for j in range(n // 2): 47 | matrix[i][j], matrix[i][-j - 1] = matrix[i][-j - 1], matrix[i][j] 48 | 49 | matrix = transpose(matrix) 50 | mirror(matrix) # transpose then mirrot 51 | 52 | 53 | ''' 54 | Transpose: 55 | 56 | 1 2 3 57 | 4 5 6 58 | 59 | 1 4 60 | 2 5 61 | 3 6 62 | 63 | 64 | ''' 65 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC49 Group Anagrams/LC49.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 49. Group Anagrams 3 | 4 | Description: 5 | Given an array of strings strs, group the anagrams together. You can return the answer in any order. 6 | An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once. 7 | ''' 8 | 9 | # @param strs List[str] 10 | # @return List[List[str]] 11 | 12 | ### Brute Solution 13 | ### TC: O(nklogk) and SC: O(nk) 14 | class Solution: 15 | def groupAnagrams(self, strs): 16 | Dict = {} 17 | for s in strs: 18 | pattern = tuple(sorted(s)) 19 | if pattern in Dict: 20 | Dict[pattern].append(s) 21 | else: 22 | Dict[pattern] = [s] 23 | return Dict.values() 24 | 25 | ### Optimized Solution 26 | ### TC: O(nk) and SC: O(nk) 27 | class Solution: 28 | def groupAnagrams(self, strs): 29 | Dict = {} 30 | for s in strs: 31 | count = [0]*26 ### we can not use Counter because it is unhashable 32 | for char in s: 33 | count[ord(char) - ord('a')] += 1 34 | count = tuple(count) 35 | if count in Dict: 36 | Dict[count].append(s) 37 | else: 38 | Dict[count] = [s] 39 | return Dict.values() -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC50 Pow(x,n)/LC50.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 50. Pow(x, n) 3 | 4 | Description: 5 | Implement pow(x, n), which calculates x raised to the power n (i.e. x^n) 6 | ''' 7 | 8 | # @param x float 9 | # @param n int 10 | # @return float 11 | 12 | ### TC: O(logn) and SC: O(1) 13 | class Solution: 14 | def myPow(self, x, n): 15 | if n < 0: 16 | x = 1/x 17 | n = -n 18 | ''' 19 | Fast Power: 20 | bin(11) = '0b1011' 21 | a^11 = a^(2^0) * a^(2^1) * a^(2^3) 22 | = a * a^2 * a^2^2^2 23 | ''' 24 | def fastPower(b, n): 25 | ans = 1 26 | while n: 27 | if n&1: ### last bit is 1 28 | ans *= b 29 | b *= b ### base 30 | n >>= 1 31 | return ans 32 | 33 | return fastPower(x, n) -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC510 Inorder Successor in BST II/LC510.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 510. Inorder Successor in BST II 3 | 4 | Description: 5 | Given a node in a binary search tree, return the in-order successor of that node in the BST. If that node has no in-order successor, return null. 6 | 7 | The successor of a node is the node with the smallest key greater than node.val. 8 | 9 | You will have direct access to the node but not to the root of the tree. Each node will have a reference to its parent node. 10 | ''' 11 | 12 | # class Node: 13 | # def __init__(self, val): 14 | # self.val = val 15 | # self.left = None 16 | # self.right = None 17 | # self.parent = None 18 | 19 | # @param node Node 20 | # @return Node 21 | 22 | ### TC: O(H) and SC: O(1) 23 | class Solution: 24 | def inorderSuccessor(self, node): 25 | successor = None 26 | if node: 27 | if node.right: 28 | node = node.right 29 | while node: 30 | successor = node 31 | node = node.left 32 | else: 33 | while node.parent and node.parent.right == node: 34 | node = node.parent 35 | successor = node.parent 36 | 37 | return successor -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC518 Coin Change II/LC518.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 518. Coin Change 2 3 | 4 | Description: 5 | You are given an integer array coins representing coins of different 6 | denominations and an integer amount representing a total amount of money. 7 | Return the number of combinations that make up that amount. 8 | If that amount of money cannot be made up by any combination of the coins, return 0. 9 | You may assume that you have an infinite number of each kind of coin. 10 | The answer is guaranteed to fit into a signed 32-bit integer. 11 | ''' 12 | 13 | # @param amount int 14 | # @param coins List[int] 15 | # @return int 16 | 17 | ''' 18 | 19 | ''' 20 | ### DP Solution 21 | ### TC: O(S*n) and SC: O(S) where S is the amount, n is denomination count 22 | class Solution: 23 | def change(self, amount, coins): 24 | DP_Table = [0] * (amount + 1) 25 | DP_Table[0] = 1 26 | 27 | for c in coins: ### only use one type of coin 28 | for n in range(c, amount + 1): ### when we currently make up n dollars, we then add c dollors 29 | DP_Table[n] += DP_Table[n - c] ### if the last coin is c, how many ways to make up n dollors 30 | return DP_Table[-1] 31 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC53 Maximum Subarray/LC53.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 53. Maximum Subarray 3 | 4 | Description: 5 | Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. 6 | A subarray is a contiguous part of an array. 7 | ''' 8 | 9 | # @param nums List[int] 10 | # @return int 11 | 12 | ### TC: O(n) and SC: O(1) 13 | class Solution: 14 | def maxSubArray(self, nums): 15 | MAX = nums[0] 16 | cur = nums[0] 17 | for n in nums[1:]: 18 | curMAX = max(n, curMAX+n) 19 | MAX = max(curMAX, MAX) 20 | return MAX 21 | 22 | ''' 23 | Intuitive DP Solution 24 | DP[i] Maximum sum of sub-array ending at i ### the key point: sub-array ending at i 25 | State transition equation: DP[i] = max(DP[i-1]+array[i], array[i]) array[i] must be included 26 | ''' 27 | ### TC: O(n) and SC: O(n) 28 | class Solution: 29 | def maxSubArray(self, nums): 30 | DP_table = [0]*len(nums) 31 | DP_table[0] = nums[0] 32 | for i in range(1, len(nums)): 33 | DP_table[i] = max(nums[i], DP_table[i-1] + nums[i]) 34 | return max(DP_table) 35 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC54 Spiral Matrix/LC54.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 54. Spiral Matrix 3 | 4 | Description: 5 | Given an m x n matrix, return all elements of the matrix in spiral order. 6 | ''' 7 | 8 | # @param matrix List[List[int]] 9 | # @return List[int] 10 | 11 | class Solution: 12 | def spiralOrder(self, matrix): 13 | ans = [] 14 | 15 | h, w = len(matrix), len(matrix[0]) 16 | up = 0 17 | bottom = h-1 18 | left = 0 19 | right = w-1 20 | 21 | # while up <= bottom and left <= right: 22 | while len(ans) < h*w: ### Trick 1: loop end condition 23 | ''' 24 | Trick 2: 25 | —————————— 26 | | | 27 | | | 28 | | | 29 | —————————— 30 | ''' 31 | for i in range(left, right+1): ### print whole up line (to avoid dead lock) 32 | ans.append(matrix[up][i]) 33 | for i in range(up+1, bottom): 34 | ans.append(matrix[i][right]) 35 | if bottom > up: ### Trick 3: avoid replicated print 36 | for i in range(right, left-1, -1): 37 | ans.append(matrix[bottom][i]) 38 | if left < right: 39 | for i in range(bottom-1, up, -1): 40 | ans.append(matrix[i][left]) 41 | up += 1 42 | bottom -= 1 43 | left += 1 44 | right -= 1 45 | return ans 46 | 47 | 48 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC543 Diameter of Binary Tree/LC543.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 543. Diameter of Binary Tree 3 | 4 | Description: 5 | Given the root of a binary tree, return the length of the diameter of the tree. 6 | The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root. 7 | The length of a path between two nodes is represented by the number of edges between them. 8 | ''' 9 | 10 | # class TreeNode: 11 | # def __init__(self, val=0, left=None, right=None): 12 | # self.val = val 13 | # self.left = left 14 | # self.right = right 15 | 16 | # @param root TreeNode 17 | # @return int 18 | 19 | ''' 20 | Similar to LC124 21 | ''' 22 | ''' 23 | 1 24 | / \ 25 | 2 5 26 | / \ 27 | 3 4 28 | 29 | ''' 30 | 31 | 32 | ### TC: O(n) and SC: O(n) 33 | class Solution: 34 | MAX = 0 35 | def diameterOfBinaryTree(self, root): 36 | self.MAX = 0 37 | def maxHalfPath(node): 38 | if node is None: 39 | return -1 40 | leftPath = maxHalfPath(node.left) 41 | rightPath = maxHalfPath(node.right) 42 | ### left -> root -> right is always longer than left -> root or right -> root 43 | self.MAX = max(self.MAX, leftPath + rightPath + 2) ### trick: leftPath + rightPath (without + 1), middle node has no contribution to the length of path 44 | return max(leftPath, rightPath) + 1 45 | 46 | maxHalfPath(root) 47 | return self.MAX -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC55 Jump Game/LC55.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 55. Jump Game 3 | 4 | Description: 5 | You are given an integer array nums. You are initially positioned at the array's first index, 6 | and each element in the array represents your maximum jump length at that position. 7 | 8 | Return true if you can reach the last index, or false otherwise. 9 | ''' 10 | 11 | # @param nums List[int] 12 | # @return bool 13 | 14 | ### Greedy Solution 15 | ### TC: O(n) and SC: O(1) 16 | class Solution: 17 | def canJump(self, nums): 18 | canReach = 0 19 | cur = 0 20 | while cur <= canReach and cur < len(nums): 21 | if canReach >= len(nums)-1: 22 | return True 23 | canReach = max(canReach, cur+nums[cur]) 24 | cur += 1 25 | return False 26 | 27 | ### TC: O(n) and SC: O(1) 28 | class Solution: 29 | def canJump(self, nums): 30 | canReach = 0 31 | for i in range(len(nums)): 32 | if i > canReach: ### cannot reach here 33 | return False 34 | canReach = max(nums[i]+i, canReach) 35 | if canReach >= len(nums)-1: 36 | return True -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC56 Merge Intervals/LC56.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 56. Merge Intervals 3 | 4 | Description: 5 | Given an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals, 6 | and return an array of the non-overlapping intervals that cover all the intervals in the input. 7 | ''' 8 | 9 | # @param intervals List[List[int]] 10 | # @return List[List[int]] 11 | 12 | ### TC: O(nlogn) and SC: O(n) 13 | class Solution: 14 | def merge(self, intervals): 15 | intervals.sort(key = lambda x: x[0]) ### [[1,3], [5,7], [6,8], [8,10]] 16 | ans = [intervals[0]] 17 | for i in range(1, len(intervals)): 18 | cur = intervals[i] 19 | if cur[0] >= ans[-1][0] and cur[0] <= ans[-1][1]: 20 | ans[-1][1] = max(ans[-1][1], cur[1]) 21 | else: 22 | ans.append(cur) 23 | return ans 24 | 25 | 26 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC59 Spiral Matrix II/LC59.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 59. Spiral Matrix II 3 | 4 | Description: 5 | Given a positive integer n, generate an n x n matrix filled with elements from 1 to n2 in spiral order. 6 | ''' 7 | 8 | # @param n int 9 | # @return List[List[int]] 10 | 11 | ### TC: O(n) and SC: O(n) 12 | class Solution: 13 | def generateMatrix(self, n): 14 | matrix = [[0]*n for _ in range(n)] 15 | 16 | up = 0 17 | down = n-1 18 | left = 0 19 | right = n-1 20 | n = 1 21 | while up <= down and left <= right: 22 | for i in range(left, right+1): 23 | matrix[up][i] = n 24 | n += 1 25 | for i in range(up+1, down): 26 | matrix[i][right] = n 27 | n += 1 28 | if up < down: 29 | for i in range(right, left-1, -1): 30 | matrix[down][i] = n 31 | n += 1 32 | if left < right: 33 | for i in range(down-1, up, -1): 34 | matrix[i][left] = n 35 | n += 1 36 | 37 | up += 1 38 | down -= 1 39 | left += 1 40 | right -= 1 41 | 42 | return matrix -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC61 Rotate List/LC61.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 61. Rotate List 3 | 4 | Description: 5 | Given the head of a linked list, rotate the list to the right by k places. 6 | ''' 7 | 8 | # class ListNode: 9 | # def __init__(self, val=0, next=None): 10 | # self.val = val 11 | # self.next = next 12 | 13 | # @param head ListNode 14 | # @param k int 15 | # @return ListNode 16 | 17 | ### TC: O(n) and SC: O(1) 18 | class Solution: 19 | def rotateRight(self, head, k): 20 | if head is None: ### corner case 21 | return None 22 | 23 | dummy = ListNode() 24 | dummy.next = head 25 | 26 | fast = dummy 27 | length = 0 28 | while fast.next: 29 | length += 1 30 | fast = fast.next 31 | ### leetcode定义的旋转次数,每旋转一次把最后一个node放到最前面,(所以可以无限转下去) 32 | k = k % length ### trick: to avoid repeated iteration 33 | 34 | if k == 0: ### trick: the new head is the same as the old head 35 | return head 36 | 37 | fast = dummy 38 | slow = dummy 39 | i = 0 40 | while i < k: 41 | fast = fast.next ### fast move advance k steps 42 | i += 1 43 | 44 | while fast.next: ### find pivot 45 | fast = fast.next 46 | slow = slow.next 47 | 48 | newTail = slow 49 | newHead = slow.next 50 | tail = fast 51 | 52 | if newHead == head: 53 | return head 54 | 55 | newTail.next = None 56 | tail.next = head 57 | 58 | return newHead 59 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC62 Unique Paths/LC62.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 62. Unique Paths 3 | 4 | Description: 5 | There is a robot on an m x n grid. The robot is initially located at the top-left corner (i.e., grid[0][0]). 6 | The robot tries to move to the bottom-right corner (i.e., grid[m - 1][n - 1]). The robot can only move either down or right at any point in time. 7 | 8 | Given the two integers m and n, return the number of possible unique paths that the robot can take to reach the bottom-right corner. 9 | ''' 10 | 11 | # @param m int 12 | # @param n int 13 | # @return int 14 | 15 | ### DP Solution 16 | ### TC: O(mn) and SC: O(mn) 17 | class Solution: 18 | def uniquePaths(self, m, n): 19 | DP_table = [[1] * n for _ in range(m)] ### DP[i][j] how many ways can robot come to here 20 | ### The robot can only move down or right, so DP[0][:] and DP[0][:] are 1 21 | for col in range(1, m): 22 | for row in range(1, n): 23 | DP_table[col][row] = DP_table[col - 1][row] + DP_table[col][row - 1] 24 | return DP_table[m - 1][n - 1] 25 | 26 | ### Math Solution 27 | ### TC: O(m) and SC: O(1) 28 | class Solution: 29 | def uniquePaths(self, m: int, n: int) -> int: 30 | def factorial(n): 31 | res = 1 32 | for i in range(1,n+1): 33 | res *= i 34 | return int(res) 35 | return int(factorial(m+n-2)/(factorial(m-1)*factorial(n-1))) -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC630 Course Schedule III/LC630.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 630. Course Schedule III 3 | 4 | Description: 5 | There are n different online courses numbered from 1 to n. 6 | You are given an array courses where courses[i] = [durationi, lastDayi] indicate that 7 | the ith course should be taken continuously for durationi days and must be finished before or on lastDayi. 8 | 9 | You will start on the 1st day and you cannot take two or more courses simultaneously. 10 | 11 | Return the maximum number of courses that you can take. 12 | 13 | Example: 14 | Input: courses = [[100,200],[200,1300],[1000,1250],[2000,3200]] 15 | Output: 3 (taking course 0, 1 and 2) 16 | ''' 17 | 18 | # @param courses List[List[int]] 19 | # @return int 20 | 21 | ### Greedy Solution 22 | ### TC: O(nlogn) and SC: O(n) 23 | from heapq import * 24 | class Solution: 25 | def scheduleCourse(self, courses): 26 | courses.sort(key=lambda x:x[1]) ### trick: sort according to the deadline 27 | 28 | maxHeap = [] 29 | cur_time = 0 30 | for time, deadline in courses: 31 | if cur_time + time <= deadline: ### greedy, as long as we can take the course, we take it 32 | heappush(maxHeap, -time) ### trick: max heap 33 | cur_time += time 34 | else: ### cur_time + time > deadline 35 | if maxHeap and -maxHeap[0] > time: 36 | heappush(maxHeap, -time) ### trick: max heap 37 | cur_time += time 38 | cur_time -= -heappop(maxHeap) ### remove older course with longer time 39 | 40 | return len(maxHeap) -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC64 Minimum Path Sum/LC64.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 64. Minimum Path Sum 3 | 4 | Description: 5 | Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right, 6 | which minimizes the sum of all numbers along its path. 7 | 8 | Note: You can only move either down or right at any point in time. 9 | ''' 10 | 11 | # @param grid List[List[int]] 12 | # @return int 13 | 14 | ### DP Solution 15 | ### TC: O(mn) and SC: O(mn) 16 | class Solution: 17 | def minPathSum(self, grid): 18 | m = len(grid) 19 | n = len(grid[0]) 20 | 21 | DP_table = [[None]*n for _ in range(m)] ### DP[i][j] the min path to (i,j) 22 | ### We can only move down or right, so DP[0][:] and DP[0][:] are fixed 23 | DP_table[0][0] = grid[0][0] 24 | for i in range(1, m): 25 | DP_table[i][0] = DP_table[i-1][0] + grid[i][0] 26 | for i in range(1, n): 27 | DP_table[0][i] = DP_table[0][i-1] + grid[0][i] 28 | 29 | for i in range(1, m): 30 | for j in range(1, n): 31 | DP_table[i][j] = min(DP_table[i-1][j], DP_table[i][j-1]) + grid[i][j] 32 | 33 | return DP_table[m-1][n-1] 34 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC67 Add Binary/LC67.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 67. Add Binary 3 | 4 | Description: 5 | Given two binary strings a and b, return their sum as a binary string. 6 | ''' 7 | 8 | # @param a str 9 | # @param b str 10 | # @return str 11 | 12 | ### TC: O(n) and SC: O(1) 13 | from itertools import zip_longest 14 | class Solution: 15 | def addBinary(self, a: str, b: str) -> str: 16 | ans = [] 17 | a = a[::-1] 18 | b = b[::-1] 19 | carry = 0 20 | for n1, n2 in zip_longest(a,b, fillvalue=0): 21 | temp = int(n1) + int(n2) + carry 22 | ans.append(temp % 2) 23 | carry = temp // 2 24 | if carry == 1: 25 | ans.append(1) 26 | ans.reverse() 27 | return "".join([str(n) for n in ans]) 28 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC7 Reverse Integer/LC7.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 7. Reverse Integer 3 | 4 | Description: 5 | Given a signed 32-bit integer x, return x with its digits reversed. If reversing x causes the value to go outside the signed 32-bit integer range [-231, 231 - 1], then return 0. 6 | 7 | Assume the environment does not allow you to store 64-bit integers (signed or unsigned). 8 | ''' 9 | 10 | # @param x int 11 | # @return int 12 | 13 | class Solution: 14 | def reverse(self, x): 15 | if x == 0: 16 | return 0 17 | sign = 1 if x >= 0 else -1 18 | res = 0 19 | if sign == -1: 20 | x = -x 21 | ### skip zeors in the tail 22 | while x % 10 == 0: 23 | x = x // 10 24 | while x != 0: 25 | if res > (pow(2,31)-1)//10 or (res == (pow(2,31)-1)//10 and x % 10 > pow(2,31) % 10): 26 | return 0 27 | res = res * 10 + x % 10 28 | x = x // 10 29 | 30 | return res * sign -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC70 Climbing Stairs/LC70.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 70. Climbing Stairs 3 | 4 | 描述: 5 | You are climbing a staircase. It takes n steps to reach the top. 6 | Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? 7 | ''' 8 | 9 | # @param n int 10 | # @return int 11 | 12 | ### DP Table Solution 13 | ### TC: O(n) and SC: O(n) 14 | class Solution: 15 | def climbStairs(self, n): 16 | if n == 1: 17 | return 1 18 | DP_table = [0]*n ### DP[i] denotes the number of ways to reach on ith step 19 | DP_table[0] = 1 20 | DP_table[1] = 2 21 | for i in range(2, n): 22 | DP_table[i] = DP_table[i-1] + DP_table[i-2] 23 | return DP_table[-1] 24 | 25 | ### DP Space Complexity Optimized Solution 26 | ### TC: O(n) and SC: O(1) 27 | class Solution: 28 | def climbStairs(self, n): 29 | if n == 1: 30 | return 1 31 | prev = 1 32 | cur = 2 33 | for i in range(2, n): 34 | cur, prev = cur+prev, cur 35 | return cur -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC71 Simplify Path/LC71.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 71. Simplify Path 3 | 4 | Description: 5 | Given a string path, which is an absolute path (starting with a slash '/') 6 | to a file or directory in a Unix-style file system, convert it to the simplified canonical path. 7 | In a Unix-style file system, a period '.' refers to the current directory, 8 | a double period '..' refers to the directory up a level, 9 | and any multiple consecutive slashes (i.e. '//') are treated as a single slash '/'. 10 | For this problem, any other format of periods such as '...' are treated as file/directory names. 11 | 12 | The canonical path should have the following format: 13 | The path starts with a single slash '/'. 14 | - Any two directories are separated by a single slash '/'. 15 | - The path does not end with a trailing '/'. 16 | - The path only contains the directories on the path from the root 17 | directory to the target file or directory (i.e., no period '.' or double period '..') 18 | Return the simplified canonical path. 19 | ''' 20 | 21 | # @param path str 22 | # @return str 23 | 24 | class Solution: 25 | def simplifyPath(self, path): 26 | stack = [] 27 | 28 | dirs = path.split('/') 29 | for d in dirs: 30 | if d == '..': 31 | if stack: 32 | stack.pop() 33 | elif d == '.' or not d: 34 | continue 35 | else: 36 | stack.append(d) 37 | 38 | res = '/' + '/'.join(stack) 39 | return res -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC72 Edit Distance/LC72.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 72. Edit Distance 3 | 4 | Description: 5 | Given two strings word1 and word2, return the minimum number of operations required to convert word1 to word2. 6 | 7 | You have the following three operations permitted on a word: 8 | - Insert a character 9 | - Delete a character 10 | - Replace a character 11 | ''' 12 | 13 | # @param word1 str 14 | # @param word2 str 15 | # @return int 16 | 17 | ### DP Solution 18 | ### TC: O(mn) and SC: O(mn) 19 | class Solution: 20 | def minDistance(self, word1, word2): 21 | m = len(word1) 22 | n = len(word2) 23 | ### start from the empty string 24 | DP_table = [[0]*(n+1) for _ in range(m+1)] ### DP[i][j]: the edit distance between word1[:i] and word2[:j] 25 | ''' 26 | It turns out that one could compute D[i][j], knowing D[i - 1][j], D[i][j - 1] and D[i - 1][j - 1]. 27 | If word1[i] == word2[j]: 28 | DP[i][j] = min(DP[i-1][j]+1, DP[i][j-1]+1, DP[i-1][j-1]) 29 | else: 30 | DP[i][j] = min(DP[i-1][j]+1, DP[i][j-1]+1, DP[i-1][j-1]+1) 31 | ''' 32 | 33 | for i in range(m+1): ### word2 is empty, so the distance is i 34 | DP_table[i][0] = i 35 | 36 | for i in range(n+1): ### word1 is empty, so the distance is i 37 | DP_table[0][i] = i 38 | 39 | for i in range(1,m+1): 40 | for j in range(1,n+1): 41 | if word1[i-1] == word2[j-1]: 42 | DP_table[i][j] = min(DP_table[i-1][j]+1, DP_table[i][j-1]+1, DP_table[i-1][j-1]) 43 | else: 44 | DP_table[i][j] = min(DP_table[i-1][j]+1, DP_table[i][j-1]+1, DP_table[i-1][j-1]+1) 45 | 46 | return DP_table[m][n] -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC739 Daily Temperatures/LC739.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 739. Daily Temperatures 3 | 4 | Description: 5 | Given an array of integers temperatures represents the daily temperatures, 6 | return an array answer such that answer[i] is the number of days you have to wait after the ith day to get a warmer temperature. 7 | If there is no future day for which this is possible, keep answer[i] == 0 instead. 8 | 9 | Example 10 | Input: temperatures = [73,74,75,71,69,72,76,73] 11 | Output: [1,1,4,2,1,1,0,0] 12 | ''' 13 | 14 | # @param temperatures List[int] 15 | # @return List[int] 16 | 17 | ### Stack Solution 18 | ### TC: O(n) and SC: O(n) 19 | class Solution: 20 | def dailyTemperatures(self, temperatures): 21 | ### We are going to maintain a monotonic(sorted) stack 22 | ans = [0]*len(temperatures) ### default 0 23 | stack = [] ### descending, only store the day which does not have warmer temperature yet 24 | for day in range(len(temperatures)): 25 | while stack and temperatures[stack[-1]] < temperatures[day]: 26 | prev_day = stack.pop() 27 | ans[prev_day] = day - prev_day 28 | stack.append(day) 29 | return ans 30 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC74 Search a 2D Matrix/LC74.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 74. Search a 2D Matrix 3 | 4 | Description: 5 | Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties: 6 | - Integers in each row are sorted from left to right. 7 | - The first integer of each row is greater than the last integer of the previous row. 8 | ''' 9 | 10 | # @param matrix List[List[int]] 11 | # @param target int 12 | # @return bool 13 | 14 | ### Binary Search 15 | ### TC: O(log(mn)) and SC: O(1) 16 | class Solution: 17 | def searchMatrix(self, matrix, target): 18 | m, n = len(matrix), len(matrix[0]) 19 | def idx2coord(idx): 20 | return idx // n, idx % n 21 | 22 | lp = 0 23 | rp = m*n - 1 24 | 25 | while lp <= rp: 26 | mid = (lp + rp) // 2 27 | x,y = idx2coord(mid) 28 | if matrix[x][y] == target: 29 | return True 30 | elif matrix[x][y] < target: 31 | lp = mid + 1 32 | else: 33 | rp = mid - 1 34 | return False -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC75 Sort Colors/LC75.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 75. Sort Colors 3 | 4 | Description: 5 | Given an array nums with n objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, 6 | with the colors in the order red, white, and blue. 7 | We will use the integers 0, 1, and 2 to represent the color red, white, and blue, respectively. 8 | 9 | You must solve this problem without using the library's sort function. 10 | ''' 11 | 12 | # @param nums List[int] 13 | # @return None 14 | 15 | ''' 16 | The trick of this problem is that there are only three colors (0,1,2. 17 | We put 0 on the left, 2 on the right and 1 in the middle. 18 | Maintain 3 pointers, lp is the rightmost boundary of 0, rp is the leftmost boundary of 1. 19 | Iterate the array, if arr[i] == 0, swap with arr[lp], if arr[i] == 2, swap with arr[rp] 20 | ''' 21 | 22 | ### TC: O(n) and SC: O(1) 23 | class Solution: 24 | def sortColors(self, nums): 25 | lp = 0 ### last 0's index 26 | rp = len(nums)-1 ### last 2's index 27 | cur = 0 28 | while cur <= rp: ### trick: cur <= rp 29 | if nums[cur] == 0: 30 | nums[lp], nums[cur] = nums[cur], nums[lp] 31 | lp += 1 32 | cur += 1 33 | elif nums[cur] == 2: ### trick: cur stays 34 | nums[rp], nums[cur] = nums[cur], nums[rp] 35 | rp -= 1 ### cur stays because we have not checked the number swapped to cur 36 | else: 37 | cur += 1 -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC77 Combinations/LC77.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 77. Combinations 3 | 4 | Description: 5 | Given two integers n and k, return all possible combinations of k numbers out of the range [1, n]. 6 | You may return the answer in any order. 7 | ''' 8 | 9 | # @param n int 10 | # @param k int 11 | # @return List[List[int]] 12 | 13 | class Solution: 14 | def combine(self, n, k): 15 | ans = [] 16 | def DFS(path, candidates): 17 | if len(path) == k: 18 | ans.append(path[:]) 19 | return 20 | else: 21 | for i in range(len(candidates)): 22 | path.append(candidates[i]) 23 | DFS(path, candidates[i+1:]) 24 | path.pop() 25 | return 26 | DFS([], [i for i in range(1, n+1)]) 27 | return ans 28 | 29 | ### Optimized Version 30 | class Solution: 31 | def combine(self, n, k): 32 | ans = [] 33 | def DFS(path, start): 34 | if len(path) == k: 35 | ans.append(path[:]) 36 | return 37 | else: 38 | for i in range(start, n+1): 39 | path.append(i) 40 | DFS(path, i+1) ### trick, exclude the former numbers 41 | path.pop() 42 | return 43 | DFS([], 1) 44 | return ans -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC78 Subsets/LC78.py: -------------------------------------------------------------------------------- 1 | 2 | ''' 3 | Leetcode 78. Subsets 4 | 5 | Description: 6 | Given an integer array nums of unique elements, return all possible subsets (the power set). 7 | 8 | The solution set must not contain duplicate subsets. Return the solution in any order. 9 | ''' 10 | 11 | # @param nums List[int] 12 | # @return List[List[int]] 13 | 14 | ### A more general solution is in LC90 15 | 16 | class Solution: 17 | def subsets(self, nums): 18 | ans = [] 19 | def DFS(path, idx): 20 | if idx == len(nums): 21 | ans.append(path[:]) 22 | return 23 | else: 24 | DFS(path, idx+1) ### skip current number 25 | DFS(path+[nums[idx]], idx+1) 26 | DFS([], 0) 27 | return ans -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC80 Remove Duplicates from Sorted Array II/LC80.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 80. Remove Duplicates from Sorted Array II 3 | 4 | Description: 5 | Given an integer array nums sorted in non-decreasing order, 6 | remove some duplicates in-place such that each unique element appears at most twice. 7 | The relative order of the elements should be kept the same. 8 | 9 | Since it is impossible to change the length of the array in some languages, 10 | you must instead have the result be placed in the first part of the array nums. 11 | More formally, if there are k elements after removing the duplicates, 12 | then the first k elements of nums should hold the final result. 13 | It does not matter what you leave beyond the first k elements. 14 | 15 | Return k after placing the final result in the first k slots of nums. 16 | 17 | Do not allocate extra space for another array. 18 | You must do this by modifying the input array in-place with O(1) extra memory. 19 | ''' 20 | 21 | # @param nums List[int] 22 | # @return int 23 | 24 | ### TC: O(n) and SC: O(1) 25 | class Solution: 26 | def removeDuplicates(self, nums): 27 | lp = 1 28 | count = 1 29 | prev = nums[0] 30 | for i in range(1,len(nums)): 31 | if nums[i] == prev: 32 | if count < 2: 33 | nums[lp], nums[i] = nums[i], nums[lp] 34 | lp += 1 35 | count += 1 36 | else: 37 | prev = nums[i] 38 | coun = 1 39 | nums[lp], nums[i] = nums[i], nums[lp] 40 | lp += 1 41 | return lp 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC83 Remove Duplicates from Sorted List/LC83.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 83. Remove Duplicates from Sorted List 3 | 4 | Description: 5 | Given the head of a sorted linked list, delete all duplicates such that each element appears only once. Return the linked list sorted as well. 6 | ''' 7 | 8 | # class ListNode: 9 | # def __init__(self, val=0, next=None): 10 | # self.val = val 11 | # self.next = next 12 | 13 | # @param head ListNode 14 | # @return ListNode 15 | 16 | ### TC: O(n) and SC: O(1) 17 | class Solution: 18 | def deleteDuplicates(self, head): 19 | if head is None: 20 | return None 21 | prev = head 22 | cur = head.next 23 | while cur: 24 | while cur and cur.val == prev.val: 25 | cur = cur.next 26 | prev.next = cur 27 | prev = prev.next 28 | if cur: 29 | cur = cur.next 30 | return head 31 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC844 Backspace String Compare/LC844.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 844. Backspace String Compare 3 | 4 | Description: 5 | Given two strings s and t, return true if they are equal when both are typed into empty text editors. 6 | '#' means a backspace(删除) character. 7 | 8 | Note that after backspacing an empty text, the text will continue empty. 9 | ''' 10 | 11 | # @param s str 12 | # @param t str 13 | # @return bool 14 | 15 | ### Stack Solution 16 | ### TC: O(n) and SC: O(n) 17 | class Solution: 18 | def backspaceCompare(self, s: str, t: str) -> bool: 19 | def parse(s): 20 | stack = [] 21 | for char in s: 22 | if char == '#': 23 | if len(stack) > 0: 24 | stack.pop() 25 | else: 26 | stack.append(char) 27 | return ''.join(stack) 28 | return parse(s) == parse(t) 29 | 30 | ### Iterator Solution 31 | ### TC: O(n) and SC: O(1) 32 | class Solution: 33 | def backspaceCompare(self, s: str, t: str) -> bool: 34 | def curChar(s): 35 | skip = 0 36 | for char in s[::-1]: 37 | if char == '#': 38 | skip += 1 39 | else: 40 | if skip > 0: 41 | skip -= 1 42 | else: 43 | yield char 44 | 45 | sIter, tIter = curChar(s), curChar(t) ### iterator 46 | while True: 47 | s = next(sIter, "EOF") 48 | t = next(tIter, "EOF") 49 | if s == "EOF" and t == "EOF": 50 | return True 51 | elif s != t: 52 | return False 53 | else: 54 | continue -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC88 Merge Sorted Array/LC88.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 88. Merge Sorted Array 3 | 4 | Description: 5 | You are given two integer arrays nums1 and nums2, sorted in non-decreasing order, 6 | and two integers m and n, representing the number of elements in nums1 and nums2 respectively. 7 | 8 | Merge nums1 and nums2 into a single array sorted in non-decreasing order. 9 | 10 | The final sorted array should not be returned by the function, but instead be stored inside the array nums1. 11 | To accommodate this, nums1 has a length of m + n, where the first m elements denote the elements that should be merged, 12 | and the last n elements are set to 0 and should be ignored. nums2 has a length of n. 13 | ''' 14 | 15 | # @param nums1 List[int] 16 | # @param m int 17 | # @param nums2 List[int] 18 | # @param n int 19 | # @return None 20 | 21 | ''' 22 | 这题的nums1长度是m+n,难点在于如何做到SC = O(1) 23 | ''' 24 | 25 | ### Place the number in reverse order 26 | ### TC: O(n) and SC: O(1) 27 | class Solution: 28 | def merge(self, nums1, m, nums2, n): 29 | p1 = m-1 30 | p2 = n-1 31 | 32 | for i in range(n+m-1,-1,-1): 33 | if p2 < 0 : ### the left number in nums1 are all set 34 | break 35 | elif p1 < 0: 36 | nums1[i] = nums2[p2] 37 | p2 -= 1 38 | else: 39 | if nums1[p1] <= nums2[p2]: 40 | nums1[i] = nums2[p2] 41 | p2 -= 1 42 | else: 43 | nums1[i] = nums1[p1] 44 | p1 -= 1 -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC889 Construct Binary Tree from Preorder and Postorder Traversal/LC889.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 889. Construct Binary Tree from Preorder and Postorder Traversal 3 | 4 | Description: 5 | Given two integer arrays, preorder and postorder where preorder is the preorder traversal of a binary tree of distinct values 6 | and postorder is the postorder traversal of the same tree, reconstruct and return the binary tree. 7 | 8 | If there exist multiple answers, you can return any of them. 9 | ''' 10 | 11 | # class TreeNode: 12 | # def __init__(self, val=0, left=None, right=None): 13 | # self.val = val 14 | # self.left = left 15 | # self.right = right 16 | 17 | # @param s str 18 | # @return int 19 | 20 | ### TC: O(n) and SC: O(n) 21 | class Solution: 22 | def constructFromPrePost(self, pre, post): 23 | if len(pre) == 0: 24 | return None 25 | root = TreeNode(pre[0]) 26 | 27 | if len(pre) > 1: 28 | leftBranch = pre[1] ### assume it has left branch 29 | loc = post.index(leftBranch) 30 | root.left = self.constructFromPrePost(pre[1:loc+1+1], post[:loc+1]) 31 | root.right = self.constructFromPrePost(pre[loc+1+1:], post[loc+1: len(post)-1]) 32 | return root -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC89 Grey Code/LC89.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 89. Gray Code(格雷编码) 3 | 4 | Description: 5 | An n-bit gray code sequence is a sequence of 2n integers where: 6 | - Every integer is in the inclusive range [0, 2^n - 1], 7 | - The first integer is 0, 8 | - An integer appears no more than once in the sequence, 9 | - The binary representation of every pair of adjacent integers differs by exactly one bit 10 | - The binary representation of the first and last integers differs by exactly one bit. 11 | Given an integer n, return any valid n-bit gray code sequence. 12 | 13 | Example: 14 | Input: n = 2 15 | Output: [0,1,3,2] (which is [00,01,11,10]) or [0, 2, 3, 1] (which is [00,10,11,01]) 16 | ''' 17 | 18 | # @param n int 19 | # @return List[int] 20 | 21 | ''' 22 | 格雷码有很多构造方法,比较好记的一种是镜像法 23 | n = 0 : 0 24 | 25 | n = 1 : (0)0 26 | ----- 27 | (0)1 28 | 29 | n = 2 : 0 0 30 | 1 0 31 | --- 32 | 1 1 33 | 0 1 34 | 35 | n = 3: 00 0 36 | 10 0 37 | 11 0 38 | 01 0 39 | ---- 40 | 01 1 41 | 11 1 42 | 10 1 43 | 00 1 44 | ''' 45 | ### TC: O(2^n) and SC: O(2^n) 46 | class Solution: 47 | def grayCode(self, n): 48 | def helper(n): 49 | if n == 0: 50 | return [0] 51 | if n == 1: 52 | return [0,1] 53 | else: 54 | res = helper(n-1) 55 | res = res + res[::-1] 56 | for i in range(len(res)//2): 57 | res[i] = int(res[i] * 2) 58 | for i in range(len(res)//2, len(res)): 59 | res[i] = int(res[i] * 2 + 1) 60 | return res 61 | 62 | return helper(n) -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC90 Subsets II/LC90.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 90. Subsets II 3 | 4 | Description: 5 | Given an integer array nums that may contain duplicates, return all possible subsets (the power set). 6 | 7 | The solution set must not contain duplicate subsets. Return the solution in any order. 8 | ''' 9 | 10 | # @param nums List[int] 11 | # @return List[List[int]] 12 | 13 | ### Backtrack Solution 14 | class Solution: 15 | def subsetsWithDup(self, nums): 16 | nums.sort() 17 | ans = [] 18 | def DFS(path, idx): 19 | ans.append(path[:]) ### trick 20 | for i in range(idx, len(nums)): 21 | if i > idx and nums[i] == nums[i-1]: 22 | continue 23 | else: 24 | path.append(nums[i]) 25 | DFS(path, i+1) 26 | path.pop() 27 | DFS([], 0) 28 | return ans 29 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC92 Reverse Linked List II/LC92.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 92. Reverse Linked List II 3 | 4 | Description: 5 | Given the head of a singly linked list and two integers left and right where left <= right, 6 | reverse the nodes of the list from position left to position right, and return the reversed list. 7 | 8 | Example: 9 | Input: head = [1,2,3,4,5], left = 2, right = 4 10 | Output: [1,4,3,2,5] 11 | ''' 12 | 13 | # class ListNode: 14 | # def __init__(self, val=0, next=None): 15 | # self.val = val 16 | # self.next = next 17 | 18 | # @param head ListNode 19 | # @param left int 20 | # @param right int 21 | # @return ListNode 22 | 23 | ### TC: O(n) and SC: O(1) 24 | class Solution: 25 | def reverseBetween(self, head, left, right): 26 | 27 | dummy = ListNode() 28 | dummy.next = head ### trick: help to generalize all cases 29 | 30 | end = dummy 31 | i = 0 32 | while i < right+1: 33 | end = end.next 34 | i += 1 35 | 36 | start = dummy 37 | i = 0 38 | while i < left-1: 39 | start = start.next 40 | i += 1 41 | 42 | cur = start.next 43 | prev = end 44 | i = 0 45 | while i < right - left + 1: 46 | temp = cur 47 | start.next = cur 48 | cur = cur.next 49 | temp.next = prev 50 | prev = start.next 51 | i += 1 52 | 53 | return dummy.next 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/LC96 Unqiue Binary Search Trees/LC96.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 96. Unique Binary Search Trees 3 | 4 | Description: 5 | Given an integer n, return the number of structurally unique BST's (binary search trees) which has exactly n nodes of unique values from 1 to n. 6 | ''' 7 | 8 | # @param num int 9 | # @return int 10 | 11 | ''' 12 | BST is a recursive structure. For a sorted list of numbers, as long as we selected the root, 13 | 1 2 3 ... r-1 | r | r+1 ... n-1 n 14 | 1:r-1 will be the left branch, r+1:n will be the right branch 15 | The branch of BST is also a BST. 16 | DP[n] = F(1,n) + F(2,n) + ... + F(n,n) 17 | F(i,n) is the number of BST structures when the root is set as i 18 | F(i,n) = G(i-1)*G(n-i) 19 | ''' 20 | ### DP Solution 21 | ### TC: O(n^2) and SC: O(n) 22 | class Solution: 23 | def numTrees(self, num): 24 | DP_table = [0]*(num+1) 25 | DP_table[0] = 1 ### trick: empty tree counts for one structure 26 | DP_table[1] = 1 27 | for n in range(2, num+1): ### iterate different root DP[i] 28 | for i in range(1, n+1): ### F(i,n) 29 | DP_table[n] += DP_table[i-1] * DP_table[n-i] 30 | return DP_table[num] -------------------------------------------------------------------------------- /InterviewProblem/LeetCode/Template: -------------------------------------------------------------------------------- 1 | ''' 2 | Leetcode 3 | 4 | Description: 5 | 6 | ''' 7 | 8 | # @param s str 9 | # @return int 10 | 11 | ### TC: O(n) and SC: O(n) 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Leetcode -------------------------------------------------------------------------------- /SomeImplementation/Kmeans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import random 3 | 4 | X = np.random.rand(10, 2) 5 | K = 3 6 | r = random.sample(range(9), K) 7 | 8 | centroids = [X[i] for i in r] 9 | 10 | def converge(centroids1, centroids2): 11 | for i in range(len(centroids1)): 12 | if centroids1[i].all() != centroids2[i].all(): 13 | return False 14 | return True 15 | 16 | while True: 17 | clusters = [[] for _ in range(K)] 18 | for x in X: 19 | label = 0 20 | minDist = float("inf") 21 | for k in range(K): 22 | d = np.linalg.norm(x-centroids[k]) 23 | if d < minDist: 24 | minDist = d 25 | label = k 26 | clusters[label].append(x) 27 | 28 | ### new centroids 29 | newCentroids = [] 30 | for k in range(K): 31 | meanX = np.mean([clusters[k][i][0] for i in range(len(clusters[k]))]) 32 | meanY = np.mean([clusters[k][i][1] for i in range(len(clusters[k]))]) 33 | newCentroids.append(np.array([meanX, meanY])) 34 | 35 | 36 | 37 | if converge(newCentroids, centroids): 38 | centroids = newCentroids 39 | break 40 | else: 41 | centroids = newCentroids 42 | 43 | print(centroids) 44 | --------------------------------------------------------------------------------