├── OO design └── Parking_Lot.java ├── README.md ├── _config.yml ├── arithmetic ├── Binary_Representation.java ├── Decode_Ways.java ├── Delete_Digits.java ├── Fast_Power.java ├── First_Bad_Version.java ├── O(1)_Check_Power_of_2.java ├── Perfect_Squares.java ├── Pow(x, n).java ├── Roman_to_Integer.java ├── Sqrt(x).java ├── Super_Ugly_Number.java ├── Ugly_Number_II.java ├── Update_Bits.java └── Valid_Number.java ├── arrays ├── 132_Pattern.java ├── 3_Sum.java ├── 3_Sum_Closest.java ├── 4Sum.java ├── 4_Sum.java ├── Backpack.java ├── Backpack_II.java ├── Backpack_VI.java ├── Best_Time_to_Buy_and_Sell_Stock.java ├── Best_Time_to_Buy_and_Sell_Stock_II.java ├── Best_Time_to_Buy_and_Sell_Stock_III.java ├── Best_Time_to_Buy_and_Sell_Stock_IV.java ├── Building_Outline.java ├── Burst_Balloons.java ├── Candy.java ├── Climbing_Stairs.java ├── Coins_in_a_Line.java ├── Coins_in_a_Line_II.java ├── Combination_Sum.java ├── Combination_Sum_II.java ├── Combinations.java ├── Container_With_Most_Water.java ├── Continuous_Subarray_Sum.java ├── Convert_Expression_to_Reverse_Polish_Notation.java ├── Copy_Books.java ├── Create_Maximum_Number.java ├── Data_Stream_Median.java ├── Dice_Sum.java ├── Digit_Counts.java ├── Expression_Evaluation.java ├── Find_Minimum_in_Rotated_Sorted_Array.java ├── Find_Minimum_in_Rotated_Sorted_Array_II.java ├── Find_Peak_Element.java ├── Find_the_Duplicate_Number.java ├── Find_the_Missing_Number.java ├── First_Missing_Positive.java ├── Flatten_Nested_List_Iterator.java ├── Frog_Jump.java ├── Gas_Station.java ├── Gray_Code.java ├── Guess_Number_Game_II.java ├── Heapify.java ├── House_Robber.java ├── House_Robber_II.java ├── House_Robber_III.java ├── Insert_Delete_GetRandom_O(1).java ├── Interleaving_Positive_and_Negative_Numbers.java ├── Jump_Game.java ├── Jump_Game_II.java ├── K_Sum.java ├── K_Sum_II.java ├── Kth_Largest_Element.java ├── Kth_Smallest_Number_in_Sorted_Matrix.java ├── Largest_Number.java ├── Largest_Rectangle_in_Histogram.java ├── Longest_Consecutive_Sequence.java ├── Longest_Increasing_Subsequence.java ├── Majority_Number.java ├── Majority_Number_II.java ├── Majority_Number_III.java ├── Max_Points_on_a_Line.java ├── Maximal_Rectangle.java ├── Maximal_Square.java ├── Maximum_Gap.java ├── Maximum_Product_Subarray.java ├── Maximum_Subarray_Difference.java ├── Maximum_Subarray_II.java ├── Maximum_Subarray_III.java ├── Median_of_two_Sorted_Arrays.java ├── Minimum_Adjustment_Cost.java ├── Minimum_Path_Sum.java ├── Minimum_Size_Subarray_Sum.java ├── N_Queens.java ├── N_Queens_II.java ├── Next_Permutation.java ├── Next_Permutation_II.java ├── Number_of_Airplanes_in_the_Sky.java ├── Paint_House.java ├── Paint_House_II.java ├── Partition_Array.java ├── Permutation_Index.java ├── Permutation_Index_II.java ├── Permutation_Sequence.java ├── Permutations.java ├── Permutations_II.java ├── Previous_Permutation.java ├── Range_Sum_Query_2D-Immutable.java ├── Rehashing.java ├── Remove_Duplicates_from_Sorted_Array.java ├── Remove_Duplicates_from_Sorted_Array_II.java ├── Reorder_array_to_construct_the_minimum_number.java ├── Reverse_Pairs.java ├── Rotate_Image.java ├── Russian_Doll_Envelopes.java ├── Search_a_2D_Matrix_II.java ├── Search_for_a_Range.java ├── Search_in_Rotated_Sorted_Array.java ├── Search_in_Rotated_Sorted_Array_II.java ├── Set_Matrix_Zeros.java ├── Single_Number_II.java ├── Single_Number_III.java ├── Sliding_Window_Maximum.java ├── Sliding_Window_Median.java ├── Sort_Colors.java ├── Sort_Colors_II.java ├── Sort_Letters_by_Case.java ├── Spiral_Matrix.java ├── Spiral_Matrix_II.java ├── Subarray_Sum_Closest.java ├── Submatrix_Sum.java ├── Subset_With_Target.java ├── Subsets.java ├── Subsets_II.java ├── Surrounded_Regions.java ├── The_Smallest_Difference.java ├── Trapping_Rain_Water.java ├── Trapping_Rain_Water_II.java ├── Triangle.java ├── Triangle_Count.java ├── Two_Sum_II.java ├── Unique_Paths.java ├── Unique_Paths_II.java ├── Wiggle_Sort.java ├── Wood_Cut.java └── qsort.java ├── graph ├── Clone_Graph.java ├── Graph_Valid_Tree.java ├── Route_Between_Two_Nodes_in_Graph.java └── Topological_Sorting.java ├── linked list ├── Add_Two_Numbers_II.java ├── Copy_List_with_Random_Pointer.java ├── Intersection_of_Two_Linked_Lists.java ├── LRU_Cache.java ├── Linked_List_Cycle_I_II.java ├── Merge_K_Sorted_List.java ├── Palindrome_Linked_List.java ├── Remove_Duplicates_from_Sorted_List.java ├── Remove_Duplicates_from_Sorted_List_II.java ├── Reorder_List.java ├── Reverse_Linked_List_II.java ├── Reverse_Nodes_in_k-Group.java ├── Rotate_List.java ├── Sort_List.java └── Swap_Two_Nodes_in_Linked_List.java ├── stack ├── Implement_Queue_by_Two_Stacks.java └── Min_Stack.java ├── string ├── Add_Operators.java ├── Add_and_Search_Word.java ├── Anagrams.java ├── Distinct_Subsequences.java ├── Edit_Distance.java ├── Edit_Distance_II.java ├── Evaluate_Reverse_Polish_Notation.java ├── Expression_Expand.java ├── Generate_Parentheses.java ├── Interleaving_String.java ├── Length_Of_Last_Word.java ├── Letter_Combinations_of_a_Phone_Number.java ├── Longest_Common_Prefix.java ├── Longest_Common_Subsequence.java ├── Longest_Common_Substring.java ├── Longest_Palindromic_Substring.java ├── Longest_Substring_Without_Repeating_Character.java ├── Longest_Substring_Without_Repeating_Characters.java ├── Longest_Substring_with_At_Most_K_Distinct_Characters.java ├── Minimum_Window_Substring.java ├── Palindrome_Partitioning.java ├── Palindrome_Partitioning_II.java ├── Regular_Expression_Matching.java ├── Restore_IP_Address.java ├── Scramble_String.java ├── Simplify_Path.java ├── String_to_Integer_II.java ├── System_Longest_File_Path.java ├── Valid_Parentheses.java ├── Wildcard_Matching.java ├── Word_Break.java ├── Word_Ladder.java ├── Word_Ladder_II.java ├── Word_Search.java └── Word_Search_II.java ├── system design ├── Consistent_Hashing.java ├── Consistent_Hashing_II.java ├── Friendship_Service.java ├── GFS_Client.java ├── Heart_Beat.java ├── Implement_Trie.java ├── Inverted_Index.java ├── LFU_Cache.java ├── LRU_Cache.java ├── Load_Balancer.java ├── Memcache.java ├── Mini_Cassandra.java ├── Mini_Twitter.java ├── Tiny_Url_I_II.java ├── Trie_Serialization.java ├── Trie_Service.java ├── Typeahead.java ├── Url_Parser.java ├── Web_Logger.java ├── Webpage_Crawler.java └── Word_Count_(Map_Reduce).java └── tree ├── Binary_Search_Tree_Iterator.java ├── Binary_Tree_Level_Order_Traversal_II.java ├── Binary_Tree_Maximum_Path_Sum.java ├── Binary_Tree_Serialization.java ├── Binary_Tree_Zigzag_Level_Order_Traversal.java ├── Construct_Binary_Tree_from_Inorder_and_Postorder_Traversal.java ├── Construct_Binary_Tree_from_Preorder_and_Inorder_Traversal.java ├── Convert_Binary_Search_Tree_to_Doubly_Linked_List.java ├── Count_of_Smaller_Number.java ├── Count_of_Smaller_Number_before_itself.java ├── Expression_Tree_Build.java ├── Interval_Minimum_Number.java ├── Interval_Sum.java ├── Interval_Sum_II.java ├── Lowest_Common_Ancestor.java ├── Minimum_Depth_of_Binary_Tree.java ├── Minimum_Spanning_Tree.java ├── Remove_Node_in_Binary_Search_Tree.java ├── Search_Range_in_Binary_Search_Tree.java ├── Segment_Tree_Build.java ├── Segment_Tree_Build_II.java ├── Segment_Tree_Modify.java ├── Segment_Tree_Query.java ├── Segment_Tree_Query_II.java ├── Unique_Binary_Search_Trees.java ├── Unique_Binary_Search_Trees_II.java └── Validate_Binary_Search_Tree.java /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /arithmetic/Decode_Ways.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Decode Ways 4 | 5 | 6 | A message containing letters from A-Z is being encoded to numbers using the following mapping: 7 | 8 | 'A' -> 1 9 | 'B' -> 2 10 | ... 11 | 'Z' -> 26 12 | 13 | Given an encoded message containing digits, determine the total number of ways to decode it. 14 | 15 | 16 | Example 17 | 18 | Given encoded message 12, it could be decoded as AB (1 2) or L (12). 19 | The number of ways decoding 12 is 2. 20 | 21 | 22 | 解: 23 | Dynanmic Programming 24 | 25 | 递推公式: 26 | dp[i]表示从0开始长度为i的substing有多少种解码方法。 27 | 1.如果i不为0,那么i单独解码时有dp[i-1]种方法。 28 | 2.如果i-1和i组合成的数字大于0,小于等于26,且数字i-1不为0(与1中值不一样),那么这个组合可以解码,故有dp[i-2]种方法。 29 | 上面两种可能性相互独立,应当相加。 30 | 31 | 故: 32 | if (oneDigit != 0) { 33 | dp[i] += dp[i - 1]; 34 | } 35 | if (twoDigit <= 26 && twoDigit > 0 && twoDigit != oneDigit) { 36 | dp[i] += dp[i - 2]; 37 | } 38 | 39 | 初始条件: 40 | 由于需要用到dp[i-2],故需要初始化前两个 41 | 当有0个字符时,有1种解码方法即空解。 42 | 当有1个字符时,如果不为‘0’,有1种解码方法。如果为‘0’,该字符串不能解码。 43 | 故: 44 | dp[0] = dp[1] = 1 45 | 46 | 47 | */ 48 | 49 | public class Solution { 50 | /** 51 | * @param s a string, encoded message 52 | * @return an integer, the number of ways decoding 53 | */ 54 | public int numDecodings(String s) { 55 | if (s == null || s.length() == 0 || s.charAt(0) - '0' == 0) { 56 | return 0; 57 | } 58 | 59 | int[] dp = new int[s.length() + 1]; 60 | dp[0] = 1; 61 | dp[1] = 1; 62 | 63 | for (int i = 2; i <= s.length(); i++) { 64 | int oneDigit = s.charAt(i - 1) - '0'; 65 | int twoDigit = Integer.valueOf(s.substring(i - 2, i)); 66 | 67 | if (oneDigit != 0) { 68 | dp[i] += dp[i - 1]; 69 | } 70 | if (twoDigit <= 26 && twoDigit > 0 && twoDigit != oneDigit) { 71 | dp[i] += dp[i - 2]; 72 | } 73 | } 74 | 75 | return dp[s.length()]; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /arithmetic/Delete_Digits.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Delete Digits 4 | 5 | 6 | Given string A representative a positive integer which has N digits, remove any k digits of the number, the remaining digits are arranged according to the original order to become a new positive integer. 7 | 8 | Find the smallest integer after remove k digits. 9 | 10 | N <= 240 and k <= N, 11 | 12 | Example 13 | Given an integer A = "178542", k = 4 14 | 15 | return a string "12" 16 | 17 | 18 | 解: 19 | 要保证结果最小,那就需要尽可能让高位变小。 20 | 从最高位开始,如果某一个数大于其下一位的数,这个数应当删除。 21 | 如果某一个数大于其前一位的数,而小于其下一位的数,则不需要管,因为删除其后面更大的数会使高位变得更小。 22 | 23 | 比如输入1243,k=1,最小结果为123,应当删除4。 24 | 输入1324,k=1,最小结果为124,应当删除3。 25 | 26 | 处理完之后应当删除所有最高位的0。 27 | 28 | */ 29 | 30 | 31 | 32 | public class Solution { 33 | /** 34 | *@param A: A positive integer which has N digits, A is a string. 35 | *@param k: Remove k digits. 36 | *@return: A string 37 | */ 38 | public String DeleteDigits(String A, int k) { 39 | int idx = 0; 40 | StringBuilder a = new StringBuilder(A); 41 | 42 | while (idx < a.length() && k > 0) { 43 | if (idx == a.length() - 1 || (idx >= 0 && a.charAt(idx) > a.charAt(idx + 1))) { 44 | a.deleteCharAt(idx--); 45 | k--; 46 | } else { 47 | idx++; 48 | } 49 | } 50 | 51 | while (a.length() > 0 && a.charAt(0) == '0') { 52 | a.deleteCharAt(0); 53 | } 54 | 55 | return a.toString(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /arithmetic/Fast_Power.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Fast Power 4 | 5 | Calculate the an % b where a, b and n are all 32bit integers. 6 | 7 | 8 | Example 9 | 10 | For 231 % 3 = 2 11 | 12 | For 1001000 % 1000 = 0 13 | 14 | 15 | Challenge 16 | 17 | O(logn) 18 | 19 | 20 | 解: 21 | 二分法 22 | 23 | a^n % b 24 | = ((bm + x)*(bm + x)*(b + y)) % b // 对a^n进行二分,若n为偶数,则分为(bm + x)*(bm + x),若为奇数,则分为(bm + x)*(bm + x)*(b + y)。 25 | = (x*x*y) % b // 由于b乘任何数得到的值都可以被b整除,所以只考虑x和y相乘的情况 26 | = (((x*x) % b) * y) % b // 为了避免x*x*y溢出long,所以分次计算 27 | 28 | 29 | */ 30 | 31 | 32 | 33 | class Solution { 34 | /* 35 | * @param a, b, n: 32bit integers 36 | * @return: An integer 37 | */ 38 | public int fastPower(int a, int b, int n) { 39 | if (n == 1) { 40 | return a % b; 41 | } 42 | if (n == 0) { 43 | return 1 % b; 44 | } 45 | 46 | long x = fastPower(a, b, n / 2); 47 | long y = (n % 2 == 0) ? 1 : a % b; 48 | 49 | return (int)((((x * x) % b) * y) % b); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /arithmetic/First_Bad_Version.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | First Bad Version 4 | 5 | 6 | 7 | The code base version is an integer start from 1 to n. One day, someone committed a bad version in the code case, so it caused this version and the following versions are all failed in the unit tests. Find the first bad version. 8 | 9 | You can call isBadVersion to help you determine which version is the first bad one. The details interface can be found in the code's annotation part. 10 | Notice 11 | 12 | Please read the annotation in code area to get the correct way to call isBadVersion in different language. For example, Java is SVNRepo.isBadVersion(v) 13 | 14 | Example 15 | 16 | Given n = 5: 17 | 18 | isBadVersion(3) -> false 19 | isBadVersion(5) -> true 20 | isBadVersion(4) -> true 21 | 22 | Here we are 100% sure that the 4th version is the first bad version. 23 | Challenge 24 | 25 | You should call isBadVersion as few as possible. 26 | 27 | 28 | 解: 29 | 二分法解就可以。 30 | 31 | 32 | 33 | */ 34 | 35 | 36 | /** 37 | * public class SVNRepo { 38 | * public static boolean isBadVersion(int k); 39 | * } 40 | * you can use SVNRepo.isBadVersion(k) to judge whether 41 | * the kth code version is bad or not. 42 | */ 43 | class Solution { 44 | /** 45 | * @param n: An integers. 46 | * @return: An integer which is the first bad version. 47 | */ 48 | public int findFirstBadVersion(int n) { 49 | long left, right; 50 | left = 1; 51 | right = n; 52 | 53 | while (left < right) { 54 | int mid = (int) ((left + right) / 2); 55 | if (SVNRepo.isBadVersion(mid)) { 56 | right = mid; 57 | } else { 58 | left = mid + 1; 59 | } 60 | } 61 | 62 | return (int)left; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /arithmetic/O(1)_Check_Power_of_2.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Using O(1) time to check whether an integer n is a power of 2. 4 | Have you met this question in a real interview? 5 | Example 6 | 7 | For n=4, return true; 8 | 9 | For n=5, return false; 10 | Challenge 11 | 12 | O(1) time 13 | 14 | 解: 15 | 2的任何次方的二进制表示都只有一个为1的bit。 16 | 所以可以用位运算找出数字中是否有多于一个为1的bit。 17 | 18 | 19 | */ 20 | 21 | class Solution { 22 | /* 23 | * @param n: An integer 24 | * @return: True or false 25 | */ 26 | public boolean checkPowerOf2(int n) { 27 | if (n <= 0) { 28 | return false; 29 | } 30 | 31 | /* n = 10100B 32 | => (n-1) = 10011B 33 | => n & (n - 1) = 10000B 34 | => n - (n & (n - 1)) = 00100B 35 | => 00100B != n 36 | => false 37 | */ 38 | return ((n - (n & (n - 1))) == n); 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /arithmetic/Perfect_Squares.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Perfect Squares 4 | 5 | 6 | Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n. 7 | 8 | Example 9 | Given n = 12, return 3 because 12 = 4 + 4 + 4 10 | Given n = 13, return 2 because 13 = 4 + 9 11 | 12 | 13 | 解: 14 | Dynanmic Programming 15 | 这道题有一个数学解法,任何数都可以由四个或四个以下数的平方和组成。 16 | 由于没有通用性,这里不做讨论。 17 | 18 | 方法一: 19 | 20 | 递推公式: 21 | dp[k]表示k最少可以由几个数的平方和构成。 22 | 假设: 23 | k = i + j * j 24 | 那么: 25 | dp[k] = dp[i] + 1 26 | 由于k可以由多组不同的i和j组成,应当取其中的最小值。 27 | 28 | 故: 29 | dp[i + j * j] = min(dp[i + j * j], dp[i] + 1) 30 | 31 | 32 | 初始条件: 33 | 假设i=0,那么dp[j * j] = dp[0] + 1 = 1。 34 | 故dp[0]=0。 35 | 由于要取最小值,故其他dp[i]全为最大整数。 36 | 37 | */ 38 | 39 | public class Solution { 40 | /** 41 | * @param n a positive integer 42 | * @return an integer 43 | */ 44 | public int numSquares(int n) { 45 | int[] dp = new int[n + 1]; 46 | 47 | Arrays.fill(dp, Integer.MAX_VALUE); 48 | dp[0] = 0; 49 | for (int i = 0; i <= n; i++) { 50 | for (int j = 1; i + j * j <= n; j++) { 51 | dp[i + j * j] = Math.min(dp[i + j * j], dp[i] + 1); 52 | } 53 | } 54 | 55 | return dp[n]; 56 | } 57 | } 58 | 59 | /* 60 | 61 | 方法二: 62 | 递推公式: 63 | dp[k]表示k可以由最少几个数的平方和组成,与方法一一样。 64 | 如果已知dp[i - j * j],那么: 65 | dp[i] = dp[i - j * j] + 1 66 | 67 | 对于每一个i,应当计算所有可能的j,取其中最小的。 68 | 故: 69 | dp[i] = min(dp[i], dp[i - j * j] + 1),j * j <= i 70 | 71 | 72 | 初始条件: 73 | 如果i-j*j=0,那么i=j*j,此时dp[i]=dp[0]+1=1。 74 | 故dp[0]=0。 75 | 由于要求最小值,故其他dp[i]初始为最大整数。 76 | 77 | */ 78 | 79 | 80 | public class Solution { 81 | /** 82 | * @param n a positive integer 83 | * @return an integer 84 | */ 85 | public int numSquares(int n) { 86 | int[] dp = new int[n + 1]; 87 | 88 | dp[0] = 0; 89 | 90 | for (int i = 1; i <= n; i++) { 91 | dp[i] = Integer.MAX_VALUE; 92 | for (int j = 1; j * j <= i; j++) { 93 | dp[i] = Math.min(dp[i], dp[i - j * j] + 1); 94 | } 95 | } 96 | 97 | return dp[n]; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /arithmetic/Pow(x, n).java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Pow(x, n) 4 | 5 | 6 | Implement pow(x, n). 7 | 8 | Notice 9 | 10 | You don't need to care about the precision of your answer, it's acceptable if the expected answer and your answer 's difference is smaller than 1e-3. 11 | 12 | Example 13 | Pow(2.1, 3) = 9.261 14 | Pow(0, 1) = 0 15 | Pow(1, 0) = 1 16 | Challenge 17 | O(logn) time 18 | 19 | 20 | 解: 21 | binary search 22 | 每次把n分成左右两部分分别计算,再把左右两边的计算值相乘。 23 | 24 | */ 25 | 26 | public class Solution { 27 | /** 28 | * @param x the base number 29 | * @param n the power number 30 | * @return the result 31 | */ 32 | public double myPow(double x, int n) { 33 | if (n == 1) { 34 | return x; 35 | } else if (n == 0) { 36 | return 1; 37 | } 38 | 39 | boolean flag = (n < 0) ? true : false; 40 | int left = Math.abs(n) / 2; 41 | int right = Math.abs(n) - left; 42 | double mul = myPow(x, left) * myPow(x, right); 43 | 44 | return flag ? 1 / mul : mul; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /arithmetic/Roman_to_Integer.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Roman to Integer 4 | 5 | Given a roman numeral, convert it to an integer. 6 | 7 | The answer is guaranteed to be within the range from 1 to 3999. 8 | 9 | 10 | 解: 11 | 1.如果一个数字小于它后面的数字,则应该在结果中减去该数字。 12 | 2.否则,结果中加入该数字。 13 | 14 | */ 15 | 16 | public class Solution { 17 | /** 18 | * @param s Roman representation 19 | * @return an integer 20 | */ 21 | public int romanToInt(String s) { 22 | int ret = 0; 23 | char[] sa = s.toCharArray(); 24 | 25 | for (int i = 0; i < sa.length; i++) { 26 | int num = charToInt(sa[i]); 27 | int next = (i == sa.length - 1) ? 0 : charToInt(sa[i + 1]); 28 | 29 | if (num < next) { 30 | ret -= num; 31 | } else { 32 | ret += num; 33 | } 34 | } 35 | 36 | return ret; 37 | } 38 | 39 | private int charToInt(char c) { 40 | switch (c) { 41 | case 'I': 42 | return 1; 43 | case 'V': 44 | return 5; 45 | case 'X': 46 | return 10; 47 | case 'L': 48 | return 50; 49 | case 'C': 50 | return 100; 51 | case 'D': 52 | return 500; 53 | case 'M': 54 | return 1000; 55 | default: 56 | return 0; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /arithmetic/Sqrt(x).java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Sqrt(x) 4 | 5 | 6 | Implement int sqrt(int x). 7 | 8 | Compute and return the square root of x. 9 | 10 | 11 | 12 | Example 13 | 14 | sqrt(3) = 1 15 | 16 | sqrt(4) = 2 17 | 18 | sqrt(5) = 2 19 | 20 | sqrt(10) = 3 21 | 22 | Challenge 23 | 24 | O(log(x)) 25 | 26 | 27 | 解: 28 | 二分法 29 | 注意int乘int的溢出问题。 30 | 31 | 循化在left和right相邻时终止,这时所求的结果一定在范围[left, right]内。 32 | 在这个范围内,先判断right,若right平方不等于x,那精确结果一定是一个大于等于left且小于right的值,这种情况应当返回left。 33 | 其实若x不为1,那么right的平方就不可能等于x,故返回语句可以改成: 34 | 35 | return (x == 1) ? 1 : (int)left; 36 | 37 | */ 38 | 39 | 40 | class Solution { 41 | /** 42 | * @param x: An integer 43 | * @return: The sqrt of x 44 | */ 45 | public int sqrt(int x) { 46 | long left, right; 47 | 48 | left = 0; 49 | right = ((long)x + 1) / 2; 50 | 51 | while (left < right - 1) { 52 | long mid = (left + right) / 2; 53 | long product = mid * mid; 54 | 55 | if (product == x) { 56 | return (int)mid; 57 | } else if (product < x) { 58 | left = mid; 59 | } else { 60 | right = mid; 61 | } 62 | } 63 | 64 | return (right * right == x) ? (int)right : (int)left; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /arithmetic/Update_Bits.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Update Bits 4 | 5 | Given two 32-bit numbers, N and M, and two bit positions, i and j. Write a method to set all bits between i and j in N equal to M (e g , M becomes a substring of N located at i and starting at j) 6 | 7 | Notice 8 | 9 | In the function, the numbers N and M will given in decimal, you should also return a decimal number. 10 | 11 | Clarification 12 | You can assume that the bits j through i have enough space to fit all of M. That is, if M=10011, you can assume that there are at least 5 bits between j and i. You would not, for example, have j=3 and i=2, because M could not fully fit between bit 3 and bit 2. 13 | 14 | Example 15 | Given N=(10000000000)2, M=(10101)2, i=2, j=6 16 | 17 | return N=(10001010100)2 18 | 19 | Challenge 20 | Minimum number of operations? 21 | 22 | 23 | 解: 24 | 要求使用最少的位运算,所以一定不能用循环。 25 | 先计算出一个mask,用来把n中i到j全部清零,然后将m左移i位,并与mask后的n按位或。 26 | 27 | 比较麻烦的是计算高位mask。 28 | 当j小于31时,先把1左移j+1次之后减1,得到一个0到j位全为1的数,之后按位求反即可得到j+1到32位全为1,其他为0的数。 29 | 当j为31时,左移j+1会溢出,故直接把结果0付给高位mask。 30 | 31 | */ 32 | 33 | class Solution { 34 | /** 35 | *@param n, m: Two integer 36 | *@param i, j: Two bit positions 37 | *return: An integer 38 | */ 39 | public int updateBits(int n, int m, int i, int j) { 40 | int high = (j < 31) ? (~((1 << (j + 1)) - 1)) : 0; 41 | int low = (1 << (i)) - 1; 42 | int mask = high | low; 43 | 44 | return (n & mask | (m << i)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /arithmetic/Valid_Number.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Valid Number 4 | 5 | 6 | Validate if a given string is numeric. 7 | 8 | Example 9 | "0" => true 10 | 11 | " 0.1 " => true 12 | 13 | "abc" => false 14 | 15 | "1 a" => false 16 | 17 | "2e10" => true 18 | 19 | 20 | 解: 21 | 这道题难点在于确定哪些是合法数字。 22 | 23 | 合法数字列举如下: 24 | 123 25 | 00 26 | 001 27 | .1 28 | 1. 29 | 0.0 30 | 0e0 31 | 01e01 32 | .1e1 33 | 34 | 非法数字列举如下: 35 | . 36 | e 37 | e1 38 | 1e 39 | 1e0.1 40 | 1e1e1 41 | 0.0.0 42 | 43 | 总结一下: 44 | 1.任意的数字组合都合法。 45 | 2.不能出现两个小数点或者两个e。 46 | 3.e不能作为开头或者结尾。小数点可以作为开头或者结尾。 47 | 4.e后面不能出现小数点。小数点后面可以出现e。 48 | 5.不能只有e和小数点,必须有至少一个数字。 49 | 50 | */ 51 | 52 | public class Solution { 53 | /** 54 | * @param s the string that represents a number 55 | * @return whether the string is a valid number 56 | */ 57 | public boolean isNumber(String s) { 58 | char[] c = s.trim().toCharArray(); 59 | boolean hasE = false; 60 | boolean hasDot = false; 61 | boolean hasNum = false; 62 | 63 | for (int i = 0; i < c.length; i++) { 64 | char cur = c[i]; 65 | 66 | if (cur >= '0' && cur <= '9') { 67 | hasNum = true; 68 | continue; 69 | } else if (cur == 'e') { 70 | if (i == 0 || hasE) { 71 | return false; 72 | } 73 | hasE = true; 74 | hasNum = false; 75 | } else if (cur == '.') { 76 | if (hasDot || hasE) { 77 | return false; 78 | } 79 | hasDot = true; 80 | } 81 | } 82 | 83 | return c.length > 0 && hasNum; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /arrays/Backpack_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Backpack II 4 | 5 | Given n items with size Ai and value Vi, and a backpack with size m. What's the maximum value can you put into the backpack? 6 | 7 | Notice 8 | 9 | You cannot divide item into small pieces and the total size of items you choose should smaller or equal to m. 10 | 11 | Example 12 | 13 | Given 4 items with size [2, 3, 5, 7] and value [1, 5, 2, 4], and a backpack with size 10. The maximum value is 9. 14 | 15 | 16 | 解: 17 | dynanmic programming 18 | 这道题解法和Backpack几乎一致。 19 | 把存入dp数组的值换成物品的价值即可。 20 | 21 | 外层循环遍历物品大小数组,内层循环遍历背包大小从m到0。实际操作时由于背包大小小于当前物品大小时不需要更新dp数组,所以内层循环最小到当前物品大小就行。 22 | 23 | */ 24 | 25 | 26 | public class Solution { 27 | /** 28 | * @param m: An integer m denotes the size of a backpack 29 | * @param A & V: Given n items with size A[i] and value V[i] 30 | * @return: The maximum value 31 | */ 32 | public int backPackII(int m, int[] A, int V[]) { 33 | int[] dp = new int[m + 1]; 34 | 35 | for (int i = 0; i < A.length; i++) { 36 | for (int j = m; j >= A[i]; j--) { 37 | dp[j] = Math.max(dp[j], V[i] + dp[j - A[i]]); 38 | } 39 | } 40 | 41 | return dp[m]; 42 | } 43 | } -------------------------------------------------------------------------------- /arrays/Backpack_VI.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Backpack VI 4 | 5 | 6 | Given an integer array nums with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target. 7 | Notice 8 | 9 | A number in the array can be used multiple times in the combination. 10 | Different orders are counted as different combinations. 11 | Have you met this question in a real interview? 12 | Example 13 | 14 | Given nums = [1, 2, 4], target = 4 15 | 16 | The possible combination ways are: 17 | [1, 1, 1, 1] 18 | [1, 1, 2] 19 | [1, 2, 1] 20 | [2, 1, 1] 21 | [2, 2] 22 | [4] 23 | 24 | return 6 25 | 26 | 27 | 解: 28 | Dynanmic Programming 29 | 30 | 递推公式: 31 | dp[i]表示和为i时有几种组合。 32 | 33 | 若一个数字num+j=i,那么dp[i]就应当为dp[j]。 34 | 如果有组num和j满足该条件,dp[i]应当为所有dp[j]的和。 35 | 36 | 故: 37 | dp[i] = sum(dp[j]), j + num == i, num <= i 38 | 39 | 40 | 初始条件: 41 | 由于可能用到j小于i的所有dp[j],故计算dp[1]时初始化dp[0]即可。 42 | dp[0]有一种数字组合可能,即空集。 43 | 故dp[0]=1。 44 | 45 | 46 | */ 47 | 48 | public class Solution { 49 | /** 50 | * @param nums an integer array and all positive numbers, no duplicates 51 | * @param target an integer 52 | * @return an integer 53 | */ 54 | public int backPackVI(int[] nums, int target) { 55 | if (nums == null || nums.length == 0) { 56 | return 0; 57 | } 58 | 59 | int[] dp = new int[target + 1]; 60 | dp[0] = 1; 61 | for (int i = 1; i <= target; i++) { 62 | for (int num : nums) { 63 | if (num <= i) { 64 | dp[i] += dp[i - num]; 65 | } 66 | } 67 | } 68 | 69 | return dp[target]; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /arrays/Best_Time_to_Buy_and_Sell_Stock.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Best Time to Buy and Sell Stock 4 | 5 | Say you have an array for which the ith element is the price of a given stock on day i. 6 | 7 | If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit. 8 | 9 | 10 | Example 11 | Given array [3,2,3,1,2], return 1. 12 | 13 | 14 | 解: 15 | Greedy 16 | 17 | 在某一个时间区间内,想要通过一笔交易获得最大利益,那么一定是在某个价格最低的时间m买入,并在m之后的某个最高价时间点n卖出。 18 | 19 | 对每个时间点,只要搞清楚在这个时间点之前的最低价格,就可以算出这个时间上可以获得的最大利润。 20 | 21 | 计算每个时间点的最大利润并求出最大值就是想要的结果。 22 | 23 | */ 24 | 25 | 26 | public class Solution { 27 | /** 28 | * @param prices: Given an integer array 29 | * @return: Maximum profit 30 | */ 31 | public int maxProfit(int[] prices) { 32 | if (prices == null || prices.length < 2) { 33 | return 0; 34 | } 35 | 36 | int min, profit; 37 | min = prices[0]; 38 | profit = 0; 39 | 40 | for (int i = 0; i < prices.length; i++) { 41 | min = Math.min(min, prices[i]); 42 | profit = Math.max(profit, prices[i] - min); 43 | } 44 | 45 | return profit; 46 | } 47 | } -------------------------------------------------------------------------------- /arrays/Best_Time_to_Buy_and_Sell_Stock_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Best Time to Buy and Sell Stock II 4 | 5 | 6 | Say you have an array for which the ith element is the price of a given stock on day i. 7 | 8 | Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again). 9 | 10 | 11 | Example 12 | 13 | Given an example [2,1,2,0,1], return 2 14 | 15 | 16 | 解: 17 | 这道题实际要求的是每个上升区间的最高点和最低点的差。 18 | 可以分割成多组一个上升加上一个下降的区间,利用Best Time to Buy and Sell Stock中的方法来计算。 19 | 20 | 即对每个区间中的每个点计算其最大profit,然后对所有profit求和。 21 | 如何分割? 22 | 当profit不断增加时,认为处于一个上升区间中。一旦profit下降,就认为上升区间结束,应当把区间profit加入总profit中,并且把min和区间profit置零,进行下一个区间的计算。 23 | 24 | 在某一个下降区间中,区间profit应当一致为0。只要在每个时间点上先计算min就可以保证这一点。若当前时间点价格低于min,那么min赋值为当前价格,再去计算当前的profit就会得到0。 25 | 26 | 要注意如果最后一个时间点仍处在一个上升区间中,由于后面没有下降区间来触发区间终止条件,所以在循环结束后要将最后一个区间的profit加入总profit。 27 | 28 | 29 | 这道题还可以通过寻找波峰和波谷来求解最大profit。一样要注意最后一个时间点的终止条件问题。 30 | 31 | */ 32 | 33 | 34 | class Solution { 35 | /** 36 | * @param prices: Given an integer array 37 | * @return: Maximum profit 38 | */ 39 | public int maxProfit(int[] prices) { 40 | if (prices == null || prices.length < 2) { 41 | return 0; 42 | } 43 | 44 | int profit, min, subProfit; 45 | profit = 0; 46 | min = prices[0]; 47 | subProfit = 0; 48 | 49 | for (int price : prices) { 50 | min = Math.min(min, price); 51 | int curProfit = price - min; 52 | if (subProfit <= curProfit) { 53 | subProfit = curProfit; 54 | } else { 55 | profit += subProfit; 56 | min = price; 57 | subProfit = 0; 58 | } 59 | } 60 | 61 | if (subProfit > 0) { 62 | profit += subProfit; 63 | } 64 | 65 | return profit; 66 | } 67 | }; -------------------------------------------------------------------------------- /arrays/Best_Time_to_Buy_and_Sell_Stock_III.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Best Time to Buy and Sell Stock III 4 | 5 | 6 | Say you have an array for which the ith element is the price of a given stock on day i. 7 | 8 | Design an algorithm to find the maximum profit. You may complete at most two transactions. 9 | 10 | Notice 11 | 12 | You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again). 13 | 14 | 15 | Example 16 | 17 | Given an example [4,4,6,1,1,4,2,5], return 6. 18 | 19 | 20 | 解: 21 | dynamic programming 22 | 23 | 在某一个时间t,完成两个交易获取最大利益的方法是在0到t之间完成一次最大profit交易,在t+1到最后一天也完成一次最大profit交易。 24 | 需要用到Best Time to Buy and Sell Stock的方法来求dp数组。 25 | maxProfitL[i]表示从0到i的最大profit。利用之前的方法正向从头计算到尾。 26 | maxProfitR[i]表示从i到最后一天的最大profit。一样利用之前的方法从尾计算到头。 27 | 28 | */ 29 | 30 | 31 | class Solution { 32 | /** 33 | * @param prices: Given an integer array 34 | * @return: Maximum profit 35 | */ 36 | public int maxProfit(int[] prices) { 37 | if (prices == null || prices.length < 2) { 38 | return 0; 39 | } 40 | 41 | int[] maxProfitL = new int[prices.length]; 42 | int[] maxProfitR = new int[prices.length]; 43 | int min = prices[0]; 44 | int max = prices[prices.length - 1]; 45 | int profit = 0; 46 | 47 | // find out max profit from left to right 48 | for (int i = 1; i < prices.length; i++) { 49 | min = Math.min(min, prices[i]); 50 | maxProfitL[i] = Math.max(maxProfitL[i - 1], prices[i] - min); 51 | } 52 | 53 | // find out max profit from right to left 54 | for (int i = prices.length - 2; i >= 0; i--) { 55 | max = Math.max(max, prices[i]); 56 | maxProfitR[i] = Math.max(maxProfitR[i + 1], max - prices[i]); 57 | } 58 | 59 | // find out overall max profit 60 | for (int i = 1; i < prices.length - 1; i++) { 61 | profit = Math.max(profit, maxProfitL[i] + maxProfitR[i + 1]); 62 | } 63 | profit = Math.max(profit, maxProfitL[prices.length - 1]); 64 | 65 | return profit; 66 | } 67 | }; -------------------------------------------------------------------------------- /arrays/Candy.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Candy 4 | 5 | 6 | 7 | There are N children standing in a line. Each child is assigned a rating value. 8 | 9 | You are giving candies to these children subjected to the following requirements: 10 | 11 | Each child must have at least one candy. 12 | 13 | Children with a higher rating get more candies than their neighbors. 14 | 15 | What is the minimum candies you must give? 16 | 17 | Example 18 | 19 | Given ratings = [1, 2], return 3. 20 | 21 | Given ratings = [1, 1, 1], return 3. 22 | 23 | Given ratings = [1, 2, 2], return 4. ([1,2,1]). 24 | 25 | 26 | 解: 27 | 这道题首先理解要求: 28 | 1,糖果的数量最小值为1。 29 | 2,如果一个孩子比他前面孩子rating高,那么应当比前面的孩子多至少一个糖果。 30 | 3,如果一个孩子比他后面孩子rating高,那么应当比后面的孩子多至少一个糖果。 31 | 4,如果一个孩子跟他前面的孩子rating一样: 32 | 1)如果这个孩子比后面的孩子rating低或者一样,那么这个孩子只有一个糖果。 33 | 2)如果这个孩子比后面孩子rating高,那么这个孩子有几个糖果取决于规则3。 34 | 35 | 36 | 创建并初始化一个数组tmp,用来表示每个孩子对应的糖果。 37 | 1,从前向后遍历一次,将所有递增区间应有的值填进tmp。暂时不处理任何递减和相等区间。 38 | 2,从后向前遍历一次,将所有递增区间的值填进tmp。根据要求4,注意以下两点: 39 | 1)对于某个rating峰值,也就是高于前后,这个值对应的tmp值在1中应该已经填过一次。这次遍历时填入的值不应当小于之前的值。 40 | 2)对于任意相等值,本次遍历只需要处理最后一个。 41 | 3,对tmp中所有数字求和并返回。 42 | 43 | */ 44 | 45 | 46 | public class Solution { 47 | /** 48 | * @param ratings Children's ratings 49 | * @return the minimum candies you must give 50 | */ 51 | public int candy(int[] ratings) { 52 | if (ratings == null || ratings.length == 0) { 53 | return 0; 54 | } 55 | 56 | int[] tmp = new int[ratings.length]; 57 | int ret = 0; 58 | 59 | Arrays.fill(tmp, 1); 60 | 61 | for (int i = 1; i < ratings.length; i++) { 62 | if (ratings[i] > ratings[i - 1]) { 63 | tmp[i] = tmp[i - 1] + 1; 64 | } 65 | } 66 | 67 | for (int i = ratings.length - 2; i >= 0; i--) { 68 | if (ratings[i] > ratings[i + 1]) { 69 | tmp[i] = Math.max(tmp[i], tmp[i + 1] + 1); 70 | } 71 | } 72 | 73 | for (int i : tmp) { 74 | ret += i; 75 | } 76 | 77 | return ret; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /arrays/Climbing_Stairs.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Climbing Stairs 4 | 5 | 6 | You are climbing a stair case. It takes n steps to reach to the top. 7 | Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? 8 | 9 | 10 | Example 11 | 12 | Given an example n=3 , 1+1+1=2+1=1+2=3 13 | 14 | return 3 15 | 16 | 17 | 解: 18 | dynanmic programming 19 | 20 | 递推公式: 21 | dp[i]表示上到第i级台阶有几种上法。 22 | 由于每次最多上两级,故第i级台阶可以从i-1或者i-2到达。 23 | 从i-1到达时,共有dp[i - 1]种上法,因为从i-1到i并不会增加可能的上法数量。同理从i-2到达时有dp[i - 2]种上法。 24 | dp[i] = dp[i - 1] + dp[i - 2] 25 | 26 | 初始条件: 27 | 由于计算i需要i-1和i-2的结果,所以至少需要有dp[0]和dp[1]作为初始条件。 28 | 第0级和第1级台阶都有1中上法,故: 29 | dp[0] = dp[1] = 1; 30 | 31 | */ 32 | 33 | public class Solution { 34 | /** 35 | * @param n: An integer 36 | * @return: An integer 37 | */ 38 | public int climbStairs(int n) { 39 | if (n < 2) { 40 | return 1; 41 | } 42 | 43 | int[] dp = new int[n + 1]; 44 | dp[0] = 1; 45 | dp[1] = 1; 46 | 47 | for (int i = 2; i <= n; i++) { 48 | dp[i] = dp[i - 2] + dp[i - 1]; 49 | } 50 | 51 | return dp[n]; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /arrays/Combination_Sum_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Combination Sum II 4 | 5 | 6 | Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. 7 | 8 | Each number in C may only be used once in the combination. 9 | 10 | Notice 11 | 12 | All numbers (including target) will be positive integers. 13 | Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak). 14 | The solution set must not contain duplicate combinations. 15 | 16 | 17 | Example 18 | 19 | Given candidate set [10,1,6,7,2,1,5] and target 8, 20 | 21 | A solution set is: 22 | 23 | [ 24 | [1,7], 25 | [1,2,5], 26 | [2,6], 27 | [1,1,6] 28 | ] 29 | 30 | 31 | 解: 32 | DFS 33 | 34 | 这道题与Combination Sum的区别是去重方式不同。 35 | 这道题对于每一个数来说,递归其后面的数组时,同样的数字只能访问一次。这样便可以避免重复的结果。 36 | 37 | 同样可以采取从上到下或者从下到上的方法来求解。 38 | 下面是从上到下求解。 39 | 40 | */ 41 | 42 | 43 | public class Solution { 44 | /** 45 | * @param num: Given the candidate numbers 46 | * @param target: Given the target number 47 | * @return: All the combinations that sum to target 48 | */ 49 | public List> combinationSum2(int[] num, int target) { 50 | List> ret = new ArrayList>(); 51 | 52 | Arrays.sort(num); 53 | helper(num, 0, target, ret, new ArrayList()); 54 | 55 | return ret; 56 | } 57 | 58 | private void helper(int[] num, int start, int target, List> ret, List path) { 59 | if (target == 0) { 60 | ret.add(new ArrayList(path)); 61 | return; 62 | } else if (target < 0) { 63 | return; 64 | } 65 | 66 | for (int i = start; i < num.length; i++) { 67 | if (i > start && num[i] == num[i - 1]) { 68 | continue; 69 | } 70 | path.add(num[i]); 71 | helper(num, i + 1, target - num[i], ret, path); 72 | path.remove(path.size() - 1); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /arrays/Container_With_Most_Water.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Container With Most Water 4 | 5 | Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water. 6 | 7 | Notice 8 | 9 | You may not slant the container. 10 | 11 | Example 12 | Given [1,3,2], the max area of the container is 2. 13 | 14 | 15 | 解: 16 | 双指针。 17 | left从左向右,right从右向左。 18 | heights[left]>heights[right]时,应当right左移。否则如果left右移,下一次计算出的盛水量一定小于本次。 19 | heights[left] heights[left]) { 39 | left++; 40 | } else { 41 | right--; 42 | } 43 | } 44 | 45 | return ret; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /arrays/Continuous_Subarray_Sum.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Continuous Subarray Sum 4 | 5 | Given an integer array, find a continuous subarray where the sum of numbers is the biggest. Your code should return the index of the first number and the index of the last number. (If their are duplicate answer, return anyone) 6 | 7 | Example 8 | Give [-3, 1, 3, -3, 4], return [1,4]. 9 | 10 | 解: 11 | start从0开始,并从start开始累加,如果sum小于0,则sum清零,并且start改成i+1。 12 | 保存sum最大时的start和i。 13 | 14 | */ 15 | 16 | public class Solution { 17 | /** 18 | * @param A an integer array 19 | * @return A list of integers includes the index of the first number and the index of the last number 20 | */ 21 | public ArrayList continuousSubarraySum(int[] A) { 22 | ArrayList ret = null; 23 | int sum = 0; 24 | int start = 0; 25 | int max = Integer.MIN_VALUE; 26 | 27 | for (int i = 0; i < A.length; i++) { 28 | sum += A[i]; 29 | 30 | if (sum >= max) { 31 | ret = new ArrayList(); 32 | ret.add(start); 33 | ret.add(i); 34 | max = sum; 35 | } 36 | 37 | if (sum < 0) { 38 | start = i + 1; 39 | sum = 0; 40 | } 41 | } 42 | 43 | return ret; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /arrays/Copy_Books.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copy Books 4 | 5 | Given n books and the ith book has A[i] pages. You are given k people to copy the n books. 6 | 7 | n books list in a row and each person can claim a continous range of the n books. For example one copier can copy the books from ith to jth continously, but he can not copy the 1st book, 2nd book and 4th book (without 3rd book). 8 | 9 | They start copying books at the same time and they all cost 1 minute to copy 1 page of a book. What's the best strategy to assign books so that the slowest copier can finish at earliest time? 10 | 11 | Example 12 | Given array A = [3,2,4], k = 2. 13 | 14 | Return 5( First person spends 5 minutes to copy book 1 and book 2 and second person spends 4 minutes to copy book 3. ) 15 | 16 | 17 | 解: 18 | Dynanmic Programming 19 | 20 | 递推公式: 21 | dp[i][j]表示i个人读j本书的最快时间。 22 | 可想而知,页数平均分配的时候需要的时间最少。 23 | 24 | i个人读完j本书的时间,取决于i-1个人读完前m-1本书的时间,与最后一个人从m读到j的时间中的最大值。 25 | m从第1本到第j本,取读完j本所需时间的最小值。 26 | 27 | 故: 28 | dp[i][j] = min(dp[i][j], max(dp[i-1][m-1], pages[m]+pages[m+1]+...+pages[j])), m=1~j 29 | 30 | 初始条件: 31 | 0个人读完0本书需要时间为0。 32 | 0个人读完大于0本书需要时间为无穷大。 33 | 故需要初始化dp[0][0]=0,其他值都初始化为Integer.MAX_VALUE即可。 34 | 35 | */ 36 | 37 | 38 | public class Solution { 39 | /** 40 | * @param pages: an array of integers 41 | * @param k: an integer 42 | * @return: an integer 43 | */ 44 | public int copyBooks(int[] pages, int k) { 45 | if (pages == null || pages.length == 0) { 46 | return 0; 47 | } 48 | 49 | int len = pages.length; 50 | int total = 0; 51 | int[][] dp = new int[k + 1][len + 1]; 52 | 53 | for (int[] i : dp) { 54 | Arrays.fill(i, Integer.MAX_VALUE); 55 | } 56 | 57 | dp[0][0] = 0; 58 | for (int i = 1; i <= k; i++) { 59 | total = 0; 60 | for (int j = 1; j <= len; j++) { 61 | total += pages[j - 1]; 62 | int left = total; 63 | 64 | for (int m = 1; m <= j; m++) { 65 | dp[i][j] = Math.min(dp[i][j], Math.max(left, dp[i - 1][m - 1])); 66 | left -= pages[m - 1]; 67 | } 68 | } 69 | } 70 | 71 | return (k > len) ? dp[len][len] : dp[k][len]; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /arrays/Digit_Counts.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Digit Counts 4 | 5 | Count the number of k's between 0 and n. k can be 0 - 9. 6 | 7 | Example 8 | if n = 12, k = 1 in 9 | 10 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] 11 | we have FIVE 1's (1, 10, 11, 12) 12 | 13 | 解: 14 | 遍历从0到n的所有数字,数出每个数字中k出现的个数即可。 15 | 16 | 17 | */ 18 | 19 | class Solution { 20 | 21 | /* 22 | * 23 | * param k : As description. 24 | * 25 | * param n : As description. 26 | * 27 | * return: An integer denote the count of digit k in 1..n 28 | * 29 | */ 30 | 31 | public int digitCounts(int k, int n) { 32 | if (k < 0 || n < 0) { 33 | return 0; 34 | } 35 | 36 | int count = 0; 37 | 38 | for (int i = 0; i <= n; i++) { 39 | int tmp = i; 40 | do { 41 | if (tmp % 10 == k) { 42 | count++; 43 | } 44 | tmp = tmp / 10; 45 | } while (tmp > 0); 46 | } 47 | 48 | return count; 49 | } 50 | }; 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /arrays/Find_Minimum_in_Rotated_Sorted_Array.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Find Minimum in Rotated Sorted Array 4 | 5 | Suppose a sorted array is rotated at some pivot unknown to you beforehand. 6 | 7 | (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). 8 | 9 | Find the minimum element. 10 | 11 | Notice 12 | 13 | You may assume no duplicate exists in the array. 14 | 15 | Have you met this question in a real interview? Yes 16 | Example 17 | Given [4, 5, 6, 7, 0, 1, 2] return 0 18 | 19 | 20 | 解: 21 | 二分法 22 | 任何时候,只要left的值小于right的值,说明left一定指向最小值。 23 | 否则: 24 | 1.如果mid的值大与left和right的值,说明mid在最小值左侧。 25 | 2.入股mid的值小于left和right的值,说明mid在最小值右侧。 26 | 27 | */ 28 | 29 | public class Solution { 30 | /** 31 | * @param nums: a rotated sorted array 32 | * @return: the minimum number in the array 33 | */ 34 | public int findMin(int[] nums) { 35 | if (nums[0] <= nums[nums.length - 1]) { 36 | return nums[0]; 37 | } 38 | 39 | int left, right; 40 | left = 0; 41 | right = nums.length - 1; 42 | 43 | while (left < right - 1) { 44 | int mid = (left + right) / 2; 45 | 46 | if (nums[left] < nums[right]) { 47 | return nums[left]; 48 | } else if (nums[mid] > nums[left] && nums[mid] > nums[right]) { 49 | left = mid; 50 | } else if (nums[mid] < nums[left] && nums[mid] < nums[right]) { 51 | right = mid; 52 | } 53 | } 54 | 55 | return Math.min(nums[left], nums[right]); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /arrays/Find_Minimum_in_Rotated_Sorted_Array_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Find Minimum in Rotated Sorted Array II 4 | 5 | Suppose a sorted array is rotated at some pivot unknown to you beforehand. 6 | 7 | (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). 8 | 9 | Find the minimum element. 10 | 11 | Notice 12 | 13 | The array may contain duplicates. 14 | 15 | Example 16 | Given [4,4,5,6,7,0,1,2] return 0. 17 | 18 | 19 | 解: 20 | 二分法 21 | 与Find Minimum in Rotated Sorted Array思路一致。 22 | 需要额外注意left和right的值相等的情况: 23 | 1.只有当left的值小于right时,left的值才是最小值。 24 | 2.当left和right的值相等时,left右移,直到不相等为止。 25 | 3.当mid的值大于等于left和right的值时,说明mid在最小值左边,left移动到mid。实际上由于left和right的值不相等,mid的值不可能等于right。 26 | 4.当mid的值小于等于left和right的值时,说明mid在最小值右边,right移动到mid。同理由于left和right的值不相等,mid的值不可能等于left。 27 | 28 | */ 29 | 30 | 31 | public class Solution { 32 | /** 33 | * @param nums: a rotated sorted array 34 | * @return: the minimum number in the array 35 | */ 36 | public int findMin(int[] nums) { 37 | int left, right; 38 | left = 0; 39 | right = nums.length - 1; 40 | 41 | while (left < right - 1) { 42 | int mid = (left + right) / 2; 43 | 44 | if (nums[left] == nums[right]) { 45 | left++; 46 | } else if (nums[left] < nums[right]) { 47 | return nums[left]; 48 | } else if (nums[mid] >= nums[left] && nums[mid] > nums[right]) { 49 | left = mid; 50 | } else if (nums[mid] < nums[left] && nums[mid] <= nums[right]) { 51 | right = mid; 52 | } 53 | } 54 | 55 | return Math.min(nums[left], nums[right]); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /arrays/Find_the_Duplicate_Number.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Find the Duplicate Number 4 | 5 | 6 | Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one. 7 | 8 | Notice 9 | 10 | You must not modify the array (assume the array is read only). 11 | You must use only constant, O(1) extra space. 12 | Your runtime complexity should be less than O(n^2). 13 | There is only one duplicate number in the array, but it could be repeated more than once. 14 | Have you met this question in a real interview? Yes 15 | Example 16 | Given nums = [5,5,4,3,2,1] return 5 17 | Given nums = [5,4,4,3,2,1] return 4 18 | 19 | 20 | 解: 21 | 遍历数组,把每个数字i放进位置i-1。 22 | 如果遇到两个数字需要放进同一个位置,那么说明该数字重复。 23 | 24 | 具体来说,遍历到位置i时: 25 | 1.如果nums[i]不等于i+1,说明该数字位置不对,将其与nums[nums[i]]交换。并且下一次继续访问当前位置。 26 | 2.如果交换时发现对方与自己的值一样,即nums[nums[i]] == nums[i],则该数字重复。 27 | 28 | */ 29 | 30 | 31 | public class Solution { 32 | /** 33 | * @param nums an array containing n + 1 integers which is between 1 and n 34 | * @return the duplicate one 35 | */ 36 | public int findDuplicate(int[] nums) { 37 | for (int i = 0; i < nums.length; i++) { 38 | if (nums[i] != i + 1) { 39 | int tmp = nums[nums[i]]; 40 | 41 | if (tmp == nums[i]) { 42 | return tmp; 43 | } 44 | 45 | nums[nums[i]] = nums[i]; 46 | nums[i] = tmp; 47 | i--; 48 | } 49 | } 50 | 51 | return -1; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /arrays/Find_the_Missing_Number.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Find the Missing Number 4 | 5 | 6 | 7 | 8 | Given an array contains N numbers of 0 .. N, find which number doesn't exist in the array. 9 | 10 | 11 | Example 12 | 13 | Given N = 3 and the array [0, 1, 3], return 2. 14 | Challenge 15 | 16 | Do it in-place with O(1) extra memory and O(n) time. 17 | 18 | 19 | 解: 20 | 与First Missing Positive几乎一致。 21 | 如果数字i满足0<=i= 0 && tmp < nums.length && tmp != nums[tmp]) { 37 | int tmp0 = nums[tmp]; 38 | nums[tmp] = tmp; 39 | tmp = tmp0; 40 | } 41 | } 42 | 43 | for (int i = 0; i < nums.length; i++) { 44 | if (nums[i] != i) { 45 | return i; 46 | } 47 | } 48 | 49 | return nums.length; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /arrays/First_Missing_Positive.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | First Missing Positive 4 | 5 | 6 | 7 | Given an unsorted integer array, find the first missing positive integer. 8 | 9 | 10 | Example 11 | 12 | Given [1,2,0] return 3, 13 | and [3,4,-1,1] return 2. 14 | Challenge 15 | 16 | Your algorithm should run in O(n) time and uses constant space. 17 | 18 | 19 | 解: 20 | 把所有正数a,放入A数组的a-1位置。如果a小于等于0,或者大于A的长度,则忽略。 21 | 然后遍历A数组,找到第一个满足A[i] != i+1的i,返回i+1就是缺少的正数。 22 | 如果遍历A也没有找到满足条件的i,说明从1到A.length的正数都存在,则返回A.length+1。 23 | 24 | */ 25 | 26 | 27 | public class Solution { 28 | /** 29 | * @param A: an array of integers 30 | * @return: an integer 31 | */ 32 | public int firstMissingPositive(int[] A) { 33 | if (A == null || A.length == 0) { 34 | return 1; 35 | } 36 | 37 | for (int i = 0; i < A.length; i++) { 38 | int tmp = A[i]; 39 | A[i] = 0; 40 | while (tmp > 0 && tmp <= A.length && A[tmp - 1] != tmp) { 41 | int tmp0 = A[tmp - 1]; 42 | A[tmp - 1] = tmp; 43 | tmp = tmp0; 44 | } 45 | } 46 | 47 | for (int i = 0; i < A.length; i++) { 48 | if (A[i] != i + 1) { 49 | return i + 1; 50 | } 51 | } 52 | 53 | return A.length + 1; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /arrays/Gas_Station.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Gas Station 4 | 5 | 6 | 7 | There are N gas stations along a circular route, where the amount of gas at station i is gas[i]. 8 | 9 | You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations. 10 | 11 | Return the starting gas station's index if you can travel around the circuit once, otherwise return -1. 12 | Notice 13 | 14 | The solution is guaranteed to be unique. 15 | 16 | Example 17 | 18 | Given 4 gas stations with gas[i]=[1,1,3,1], and the cost[i]=[2,2,1,1]. The starting gas station's index is 2. 19 | Challenge 20 | 21 | O(n) time and O(1) extra space 22 | 23 | 24 | 解: 25 | 从最后一点出发,如果可以到到下一个点,则前进,然后再计算能否到达再下一个点。 26 | 如果不能到达下一个点,则让起点后退。从后退之后之后的点到后退之前的点,如果有汽油有剩余,且余量足以使汽车前进到希望到达的点,就继续前进。否则继续后退直到可以到达为止。 27 | 如果退到了希望到达的点,或者前进到了出发点,则推出循环。 28 | 然后判断此时剩余的gas,如果大于等于0则说明可以完成一圈,否则说明不能完成。 29 | 30 | 31 | */ 32 | 33 | 34 | public class Solution { 35 | /** 36 | * @param gas: an array of integers 37 | * @param cost: an array of integers 38 | * @return: an integer 39 | */ 40 | public int canCompleteCircuit(int[] gas, int[] cost) { 41 | if (gas == null || gas.length == 0 || cost == null || cost.length != gas.length) { 42 | return -1; 43 | } 44 | 45 | int start = gas.length - 1; 46 | int cur = 0; 47 | int left = gas[start] - cost[start]; 48 | 49 | while (start > cur) { 50 | if (left >= 0) { 51 | left += gas[cur] - cost[cur]; 52 | cur++; 53 | } else { 54 | start--; 55 | left += gas[start] - cost[start]; 56 | } 57 | } 58 | 59 | return (left >= 0) ? start : -1; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /arrays/Guess_Number_Game_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Guess Number Game II 4 | 5 | 6 | 7 | We are playing the Guess Game. The game is as follows: 8 | I pick a number from 1 to n. You have to guess which number I picked. 9 | Every time you guess wrong, I'll tell you whether the number I picked is higher or lower. 10 | However, when you guess a particular number x, and you guess wrong, you pay $x. You win the game when you guess the number I picked. 11 | 12 | 13 | Example 14 | 15 | Given n = 10, I pick 8. 16 | First round: You guess 5, I tell you that it's higher. You pay $5. 17 | Second round: You guess 7, I tell you that it's higher. You pay $7. 18 | Third round: You guess 9, I tell you that it's lower. You pay $9. 19 | 20 | Game over. 8 is the number I picked. 21 | You end up paying $5 + $7 + $9 = $21. 22 | 23 | Given a particular n ≥ 1, find out how much money you need to have to guarantee a win. 24 | So when n = `10, return16` 25 | 26 | 27 | 28 | 解: 29 | Dynanmic Programming 30 | 31 | 递推公式: 32 | dp[i][j]表示从i到j中猜中任意数字的最小开销。 33 | 假设猜数字k,i A.length / 2) ? 1 : 0; 46 | right = (A.length % 2 == 0) ? A.length - 2 : 47 | (cnt > A.length / 2) ? A.length - 1 : A.length - 2; 48 | 49 | while (left < right) { 50 | swap(A, left, right); 51 | left += 2; 52 | right -= 2; 53 | } 54 | } 55 | 56 | void swap(int[] A, int a, int b) { 57 | int tmp = A[a]; 58 | A[a] = A[b]; 59 | A[b] = tmp; 60 | } 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /arrays/Jump_Game.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Jump Game 4 | 5 | Given an array of non-negative integers, you are initially positioned at the first index of the array. 6 | Each element in the array represents your maximum jump length at that position. 7 | Determine if you are able to reach the last index. 8 | 9 | Notice 10 | 11 | This problem have two method which is Greedy and Dynamic Programming. 12 | The time complexity of Greedy method is O(n). 13 | The time complexity of Dynamic Programming method is O(n^2). 14 | We manually set the small data set to allow you pass the test in both ways. This is just to let you learn how to use this problem in dynamic programming ways. If you finish it in dynamic programming ways, you can try greedy method to make it accept again. 15 | 16 | 17 | 解: 18 | 方法一: 19 | dynamic programming 20 | 21 | 递推公式: 22 | dp[i]表示i点可否到达。 23 | dp[i] = dp[j] && A[j] + j > i, j为小于i的任意一点。 24 | 也就是说,只要i之前的任意一点可达,而且从该点可以到达i,那么dp[i]为真。 25 | 26 | 初始条件: 27 | 第一个点可达,也就是dp[0]为真。 28 | 29 | */ 30 | 31 | public class Solution { 32 | /** 33 | * @param A: A list of integers 34 | * @return: The boolean answer 35 | */ 36 | public boolean canJump(int[] A) { 37 | boolean[] dp = new boolean[A.length]; 38 | dp[0] = true; 39 | 40 | for (int i = 1; i < A.length; i++) { 41 | for (int j = 0; j < i; j++) { 42 | if (dp[j] && A[j] + j >= i) { 43 | dp[i] = true; 44 | break; 45 | } 46 | } 47 | } 48 | 49 | return dp[A.length - 1]; 50 | } 51 | } 52 | 53 | 54 | /* 55 | 56 | 方法二: 57 | greedy 58 | 59 | 用reach保存能跳到的最远距离。 60 | 如果reach大于当前位置,那么比较reach和从当前位置出发能跳到的最远距离,更新reach。 61 | 直到遍历整个数组。 62 | 63 | */ 64 | 65 | 66 | public class Solution { 67 | /** 68 | * @param A: A list of integers 69 | * @return: The boolean answer 70 | */ 71 | public boolean canJump(int[] A) { 72 | int reach = 0; 73 | 74 | for (int i = 0; i < A.length; i++) { 75 | if (reach < i) { 76 | return false; 77 | } 78 | 79 | reach = Math.max(reach, A[i] + i); 80 | } 81 | 82 | return true; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /arrays/Jump_Game_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Jump Game II 4 | 5 | Given an array of non-negative integers, you are initially positioned at the first index of the array. 6 | Each element in the array represents your maximum jump length at that position. 7 | Your goal is to reach the last index in the minimum number of jumps. 8 | 9 | 10 | Example 11 | 12 | Given array A = [2,3,1,1,4] 13 | The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.) 14 | 15 | 16 | 解: 17 | dynanmic programming 18 | 19 | 递推公式: 20 | dp[i]表示跳到当前点最少需要多少次跳跃。 21 | dp[i] = min(dp[j] + 1, j = 0 ~ i - 1, A[j] + j >= i) 22 | 即dp[i]应当为从0到i-1中能够跳到i的点中需要最少的跳跃次数。 23 | 24 | 初始条件: 25 | 跳到第一个点需要0次跳跃,即dp[0] = 0。 26 | 27 | */ 28 | 29 | 30 | public class Solution { 31 | /** 32 | * @param A: A list of lists of integers 33 | * @return: An integer 34 | */ 35 | public int jump(int[] A) { 36 | int[] dp = new int[A.length]; 37 | dp[0] = 0; 38 | 39 | for (int i = 1; i < A.length; i++) { 40 | dp[i] = i; 41 | for (int j = 0; j < i; j++) { 42 | if (A[j] + j >= i) { 43 | dp[i] = Math.min(dp[i], dp[j] + 1); 44 | } 45 | } 46 | } 47 | 48 | return dp[A.length - 1]; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /arrays/K_Sum_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | K Sum II 4 | 5 | 6 | Given n unique integers, number k (1<=k<=n) and target. 7 | 8 | Find all possible k integers where their sum is target. 9 | 10 | Example 11 | Given [1,2,3,4], k = 2, target = 5. Return: 12 | 13 | [ 14 | [1,4], 15 | [2,3] 16 | ] 17 | 18 | 19 | 解: 20 | DFS 21 | 深度优先搜索遍历所有数字,找出所有解即可。 22 | 23 | k等于0时无论target如何都应当返回。 24 | 可以进一步优化,先对A进行递增排序,这样当target-A[i]小于0时就可以打断循环,因为后面的值将会更小。 25 | 26 | */ 27 | 28 | public class Solution { 29 | /** 30 | * @param A: an integer array. 31 | * @param k: a positive integer (k <= length(A)) 32 | * @param target: a integer 33 | * @return a list of lists of integer 34 | */ 35 | public ArrayList> kSumII(int[] A, int k, int target) { 36 | ArrayList> ret = new ArrayList>(); 37 | helper(A, 0, k, target, ret, new ArrayList()); 38 | 39 | return ret; 40 | } 41 | 42 | private void helper(int[] A, int start, int k, int target, ArrayList> ret, ArrayList path) { 43 | if (k == 0) { 44 | if (target == 0) { 45 | ret.add(new ArrayList(path)); 46 | } 47 | return; 48 | } 49 | 50 | for (int i = start; i < A.length; i++) { 51 | path.add(A[i]); 52 | helper(A, i + 1, k - 1, target - A[i], ret, path); 53 | path.remove(path.size() - 1); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /arrays/Kth_Largest_Element.java: -------------------------------------------------------------------------------- 1 | /* 2 | QuickSelect 3 | time: O(n) 4 | space: O(1) 5 | 6 | 类似于快速排序,找出某一个值的位置之后,判断第K大的值应当在其左边还是右边,然后对其左边或者右边的数组进行下一轮查找。 7 | pivotTh表示pivot在输入数组中是第几大。 8 | */ 9 | 10 | class Solution { 11 | /* 12 | * @param k : description of k 13 | * @param nums : array of nums 14 | * @return: description of return 15 | */ 16 | 17 | public int kthLargestElement(int k, int[] nums) { 18 | return kthHelper(k, nums, 0, nums.length - 1); 19 | } 20 | 21 | private int kthHelper(int k, int[] nums, int start, int end) { 22 | int pivot = nums[end]; 23 | int store = start; 24 | 25 | // find out the final position of pivot 26 | for (int i = start; i <= end; i++) { 27 | if (nums[i] <= pivot) { 28 | swap(nums, store++, i); 29 | } 30 | } 31 | 32 | // Note that store points to the index after pivot. Move it back. 33 | store--; 34 | 35 | int pivotTh = end - store + 1; 36 | if (pivotTh == k) { 37 | return nums[store]; 38 | } else if (pivotTh > k) { 39 | return kthHelper(k, nums, store + 1, end); 40 | } else { 41 | return kthHelper(k - pivotTh, nums, start, store - 1); 42 | } 43 | } 44 | 45 | private void swap(int[] nums, int idxA, int idxB) { 46 | int tmp = nums[idxA]; 47 | nums[idxA] = nums[idxB]; 48 | nums[idxB] = tmp; 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /arrays/Largest_Number.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Largest Number 4 | 5 | Given a list of non negative integers, arrange them such that they form the largest number. 6 | 7 | Notice 8 | 9 | The result may be very large, so you need to return a string instead of an integer. 10 | 11 | Example 12 | Given [1, 20, 23, 4, 8], the largest formed number is 8423201. 13 | 14 | Challenge 15 | Do it in O(nlogn) time complexity. 16 | 17 | 18 | 解: 19 | 首先对输入序列进行某种排序,保证高位的数字尽可能的大,然后把排序好的数组依次加入结果字符串。 20 | 21 | 对于任意两个数字,谁在高位可以保证两个组合出的数字最大就应当排在前面。 22 | 于是比较这两个数字的两种不同组合的大小即可决定谁在前谁在后。 23 | 24 | 生成结果字符串之后应当去掉最高位的0。 25 | 26 | */ 27 | 28 | 29 | public class Solution { 30 | /** 31 | *@param num: A list of non negative integers 32 | *@return: A string 33 | */ 34 | public String largestNumber(int[] num) { 35 | StringBuilder ret = new StringBuilder("0"); 36 | String[] nums = new String[num.length]; 37 | 38 | for (int i = 0; i < num.length; i++) { 39 | nums[i] = String.valueOf(num[i]); 40 | } 41 | 42 | Arrays.sort(nums, comp); 43 | 44 | for (String s : nums) { 45 | ret.append(s); 46 | } 47 | 48 | while (ret.length() > 1 && ret.charAt(0) == '0') { 49 | ret.deleteCharAt(0); 50 | } 51 | 52 | return ret.toString(); 53 | } 54 | 55 | private Comparator comp = new Comparator() { 56 | public int compare(String a, String b) { 57 | return (b + a).compareTo(a + b); 58 | } 59 | }; 60 | } 61 | -------------------------------------------------------------------------------- /arrays/Largest_Rectangle_in_Histogram.java: -------------------------------------------------------------------------------- 1 | /* 2 | Largest Rectangle in Histogram 3 | 4 | Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram. 5 | 6 | 解: 7 | Stack 8 | 9 | 首先需要理解,最大矩形一定由某一个高度和其左右比它高的高度组成。 10 | 我们每次如果发现某个高度比栈顶的高度高,那么将该高度直接入队。 11 | 如果发现该高度小于等于栈顶高度,那么说明当前栈内一定是一个递增序列。我们只需要依次计算这个递增序列中比当前高度高的值组成的最大的矩形,并将对应值出栈。然后再将当前高度入栈。 12 | 当一个高度入栈时,栈不一定为空。但由于所有比当前值更高的已经全部出栈,所以栈内依然是一个递增序列。 13 | */ 14 | 15 | 16 | 17 | public class Solution { 18 | /** 19 | * @param height: A list of integer 20 | * @return: The area of largest rectangle in the histogram 21 | */ 22 | public int largestRectangleArea(int[] height) { 23 | Stack stack = new Stack(); 24 | int max = 0; 25 | 26 | for (int i = 0; i <= height.length; i++) { 27 | int curt = (i == height.length) ? 0 : height[i]; 28 | while (!stack.isEmpty() && curt <= height[stack.peek()]) { 29 | int h = height[stack.pop()]; 30 | int w = stack.isEmpty() ? i : i - stack.peek() - 1; 31 | max = Math.max(max, h * w); 32 | } 33 | 34 | stack.push(i); 35 | } 36 | 37 | return max; 38 | } 39 | } -------------------------------------------------------------------------------- /arrays/Longest_Consecutive_Sequence.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Longest Consecutive Sequence 4 | 5 | Given an unsorted array of integers, find the length of the longest consecutive elements sequence. 6 | 7 | Clarification 8 | Your algorithm should run in O(n) complexity. 9 | 10 | Example 11 | 12 | Given [100, 4, 200, 1, 3, 2], 13 | The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4. 14 | 15 | 16 | 解: 17 | 把所有数全部放进一个HashSet,分别判断每个数的前后所有可以连续的数字是否存在于这个Set中,若存在则将其从Set中删去。 18 | 这样便可找出最长序列。 19 | 20 | 这道题提供了一个思路,即判断的条件可以是单纯的某个数字,而非一定要是输入条件中的一个数。 21 | 22 | */ 23 | 24 | 25 | 26 | public class Solution { 27 | /** 28 | * @param nums: A list of integers 29 | * @return an integer 30 | */ 31 | public int longestConsecutive(int[] num) { 32 | HashSet set = new HashSet(); 33 | int max = 0; 34 | 35 | for (int i : num) { 36 | set.add(i); 37 | } 38 | 39 | while (!set.isEmpty()) { 40 | int left, right, center; 41 | 42 | center = ((Integer)set.iterator().next()).intValue(); 43 | left = center - 1; 44 | right = center + 1; 45 | set.remove(center); 46 | 47 | while (set.contains(left)) { 48 | set.remove(left); 49 | left--; 50 | } 51 | 52 | while (set.contains(right)) { 53 | set.remove(right); 54 | right++; 55 | } 56 | 57 | max = Math.max(max, right - left - 1); 58 | } 59 | 60 | return max; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /arrays/Majority_Number.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Majority Number 4 | 5 | Given an array of integers, the majority number is the number that occurs more than half of the size of the array. Find it. 6 | 7 | Notice 8 | 9 | You may assume that the array is non-empty and the majority number always exist in the array. 10 | 11 | Example 12 | Given [1, 1, 1, 1, 2, 2, 2], return 1 13 | 14 | Challenge 15 | O(n) time and O(1) extra space 16 | 17 | 18 | 解: 19 | 用candidate来保存数字,并用cnt来统计该数字的数量。 20 | 当遇到一个跟candidate相同的数字时,cnt加一,否则减一。 21 | 当cnt等于0时,更新candidate为当前的数字,同时cnt不变。 22 | 这样做相当于如果某一个数出现了3次,另外一个数必须出现4次才可以变更candidate。 23 | 24 | 输出最后一个candidate 25 | 26 | 比如输入为: 1,1,1,2,2,2,2,1,1 27 | cnt: 1,2,3,2,1,0,0,0,1 28 | candidate: 1,1,1,1,1,1,2,1,1 29 | 30 | 输入: 1,1,1,1,2,2,2 31 | cnt: 1,2,3,4,3,2,1 32 | candidate: 1,1,1,1,1,1,1 33 | 34 | */ 35 | 36 | public class Solution { 37 | /** 38 | * @param nums: a list of integers 39 | * @return: find a majority number 40 | */ 41 | public int majorityNumber(ArrayList nums) { 42 | int candidate, cnt = 0; 43 | candidate = nums.get(0); 44 | 45 | for (int i = 0; i < nums.size(); i++) { 46 | if (candidate == nums.get(i)) { 47 | cnt++; 48 | } else if (cnt == 0) { 49 | candidate = nums.get(i); 50 | cnt++; 51 | } else { 52 | cnt--; 53 | } 54 | } 55 | 56 | return candidate; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /arrays/Majority_Number_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Majority Number II 4 | 5 | Given an array of integers, the majority number is the number that occurs more than 1/3 of the size of the array. 6 | 7 | Find it. 8 | 9 | Notice 10 | 11 | There is only one majority number in the array. 12 | 13 | Example 14 | 15 | Given [1, 2, 1, 2, 1, 3, 3], return 1. 16 | Challenge 17 | 18 | O(n) time and O(1) extra space. 19 | 20 | 21 | 解: 22 | 利用Majority Number的方法,略微改进。 23 | 使用两个candidate和cnt分别保存两个数字。 24 | 当遇到一个跟里那个个candidate都不同的数字时,两个cnt都减一。 25 | 这意味着每次增加时总体cnt只增加了1,而减少时减了2。以此达到三分的效果。 26 | 27 | 最后两个candidate需要重新统计,超过1/3的那个为最后结果。 28 | 29 | 30 | */ 31 | 32 | public class Solution { 33 | /** 34 | * @param nums: A list of integers 35 | * @return: The majority number that occurs more than 1/3 36 | */ 37 | public int majorityNumber(ArrayList nums) { 38 | int candidate0, candidate1, cnt0, cnt1; 39 | 40 | candidate0 = candidate1 = cnt0 = cnt1 = 0; 41 | for (Integer i : nums) { 42 | if (cnt0 == 0) { 43 | candidate0 = i; 44 | cnt0++; 45 | } else if (candidate0 == i) { 46 | cnt0++; 47 | } else if (cnt1 == 0) { 48 | candidate1 = i; 49 | cnt1++; 50 | } else if (candidate1 == i) { 51 | cnt1++; 52 | } else { 53 | cnt0--; 54 | cnt1--; 55 | } 56 | } 57 | 58 | cnt0 = cnt1 = 0; 59 | for (Integer i : nums) { 60 | if (candidate0 == i) { 61 | cnt0++; 62 | } else if (candidate1 ==i) { 63 | cnt1++; 64 | } 65 | } 66 | 67 | return cnt0 > cnt1 ? candidate0 : candidate1; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /arrays/Majority_Number_III.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Majority Number III 4 | 5 | 6 | 7 | Given an array of integers and a number k, the majority number is the number that occurs more than 1/k of the size of the array. 8 | 9 | Find it. 10 | Notice 11 | 12 | There is only one majority number in the array. 13 | 14 | Example 15 | 16 | Given [3,1,2,3,2,3,3,4,4,4] and k=3, return 3. 17 | Challenge 18 | 19 | O(n) time and O(k) extra space 20 | 21 | 22 | 解: 23 | O(n) time和O(k) space的要求,可以使用一个HashMap来对每个数字进行统计来满足。 24 | 最后只要返回HashMap中统计数量最多的那个数字就可以了。 25 | 26 | */ 27 | public class Solution { 28 | /** 29 | * @param nums: A list of integers 30 | * @param k: As described 31 | * @return: The majority number 32 | */ 33 | public int majorityNumber(ArrayList nums, int k) { 34 | if (nums == null | nums.size() == 0) { 35 | return 0; 36 | } 37 | 38 | /* use map to count every number */ 39 | HashMap map = new HashMap(); 40 | for (int i = 0; i < nums.size(); i++) { 41 | int num = nums.get(i); 42 | if (!map.containsKey(num)) { 43 | map.put(num, 0); 44 | } 45 | map.put(num, map.get(num) + 1); 46 | } 47 | 48 | int maxCnt, max = 0; 49 | maxCnt = Integer.MIN_VALUE; 50 | for (Map.Entry entry : map.entrySet()) { 51 | if (maxCnt < entry.getValue()) { 52 | maxCnt = entry.getValue(); 53 | max = entry.getKey(); 54 | } 55 | } 56 | 57 | return max; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /arrays/Maximal_Rectangle.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Maximal Rectangle 4 | 5 | Given a 2D boolean matrix filled with False and True, find the largest rectangle containing all True and return its area. 6 | 7 | 8 | Example 9 | 10 | Given a matrix: 11 | 12 | [ 13 | [1, 1, 0, 0, 1], 14 | [0, 1, 0, 0, 1], 15 | [0, 0, 1, 1, 1], 16 | [0, 0, 1, 1, 1], 17 | [0, 0, 0, 0, 1] 18 | ] 19 | 20 | return 6. 21 | 22 | 23 | 解: 24 | stack 25 | 26 | 这道题可以数方格,遍历到某个坐标(x,y)上,先右数,记录下来宽度w,并计算此时的最大矩阵(1 * w);然后向下移动一格,再向右数,如果比w小就记录下来,计算最大矩阵(2 * w);如此直到向下移动时遇到false。 27 | 这种方法需要重用前面的计算结果,否则时间复杂度过高。当横向遍历时,如果之前在(x,y)上数过一次,那么x到x+w之间的就不用再数了,因为找到的矩阵一定比之前的得到的小。 28 | 29 | 不推荐这种方法。 30 | 31 | 32 | 这道题实际应当利用Largest Rectangle in Histogram的解法。当遍历某一行时,将这一行以及上方连续为true的格子看作是Histogram,然后求解Largest Rectangle in Histogram。 33 | 为了计算Histogram的高度,用height数组来记录每一行的结果。如果再某一行遇到0,不管上面有多少个true,在此行看来,这一列的高度为0。否则高度加一。 34 | 35 | 下面的实现中内层两个循环可以合并。放在这里为了将算法表达得更清楚。 36 | 37 | 38 | */ 39 | 40 | 41 | 42 | public class Solution { 43 | /** 44 | * @param matrix a boolean 2D matrix 45 | * @return an integer 46 | */ 47 | public int maximalRectangle(boolean[][] matrix) { 48 | if (matrix == null || matrix.length == 0) { 49 | return 0; 50 | } 51 | 52 | int max = 0; 53 | int m = matrix.length; 54 | int n = matrix[0].length; 55 | int[] h = new int[n]; 56 | 57 | for (int i = 0; i < m; i++) { 58 | Stack st = new Stack(); 59 | 60 | for (int j = 0; j <= n; j++) { 61 | if (j < n) { 62 | h[j] = matrix[i][j] ? h[j] + 1 : 0; 63 | } 64 | 65 | while (!st.isEmpty() && (j == n || h[st.peek()] > h[j])) { 66 | int idx = st.pop(); 67 | int w = st.isEmpty() ? j : j - st.peek() - 1; 68 | max = Math.max(h[idx] * w, max); 69 | } 70 | 71 | st.push(j); 72 | } 73 | } 74 | 75 | return max; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /arrays/Maximum_Product_Subarray.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Maximum Product Subarray 4 | 5 | Find the contiguous subarray within an array (containing at least one number) which has the largest product. 6 | 7 | Example 8 | For example, given the array [2,3,-2,4], the contiguous subarray [2,3] has the largest product = 6. 9 | 10 | 11 | 解: 12 | 对于每个数来说,由于可能为正也可能为负,所以应当分别与之前的最大正乘积和最小负乘积相乘,取其中大的与全局最大值比较。 13 | 由此,需要同时保存当前的最大正乘积和最小负乘积。 14 | 15 | 如果遇到一个正数,应当与之前的正乘积相乘获得新的最大正乘积。同时该数与之前的最小负乘积相乘可以获得新的最小负乘积。 16 | 如果遇到一个负数,应当与之前的最小负乘积相乘获得当前的最大正乘积。同时该数与之前的最大正乘积相乘获得新的最小负乘积。 17 | 18 | 如果遇到的第一个数为正,那么最小负乘积为正数,应当忽略并令其为1。 19 | 如果遇到的第一个数为负,那么最大正乘积为负数,应当忽略并令其为1。 20 | 21 | */ 22 | 23 | 24 | public class Solution { 25 | /** 26 | * @param nums: an array of integers 27 | * @return: an integer 28 | */ 29 | public int maxProduct(int[] nums) { 30 | int max, pos, neg; 31 | 32 | if (nums == null || nums.length == 0) { 33 | return 0; 34 | } 35 | 36 | max = nums[0]; 37 | pos = 1; 38 | neg = 1; 39 | 40 | for (int i : nums) { 41 | int tmpPos = Math.max(pos * i, neg * i); 42 | int tmpNeg = Math.min(pos * i, neg * i); 43 | 44 | if (tmpPos <= 0) { 45 | pos = 1; 46 | } else { 47 | pos = tmpPos; 48 | max = Math.max(max, pos); 49 | } 50 | 51 | if (tmpNeg >= 0) { 52 | neg = 1; 53 | } else { 54 | neg = tmpNeg; 55 | } 56 | } 57 | 58 | return max; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /arrays/Maximum_Subarray_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Maximum Subarray II 4 | 5 | Given an array of integers, find two non-overlapping subarrays which have the largest sum. 6 | The number in each subarray should be contiguous. 7 | Return the largest sum. 8 | 9 | Notice 10 | 11 | The subarray should contain at least one number 12 | 13 | Example 14 | For given [1, 3, -1, 2, -1, 2], the two subarrays are [1, 3] and [2, -1, 2] or [1, 3, -1, 2] and [2], they both have the largest sum 7. 15 | 16 | Challenge 17 | Can you do it in time complexity O(n) ? 18 | 19 | 20 | 解: 21 | 这道题理解成将原数组按照某个位置分成左右两半,分别计算左右两边的最大子数组和,使得两个子数组和的和最大。 22 | 取这个位置的最优解。 23 | 24 | 既然要分别找出左右两边的最大和子数组,那么先从左往右计算左边到任意位置i为止的最大子数组和,记为left[i]。 25 | 同理计算从右往左的最大子数组和,记为right[i]。 26 | 然后找出left[i]+right[i+1]的最大值,0<=i nums) { 36 | int[] left = new int[nums.size()]; 37 | int[] right = new int[nums.size()]; 38 | int sum, max; 39 | 40 | max = Integer.MIN_VALUE; 41 | sum = 0; 42 | for (int i = 0; i < nums.size(); i++) { 43 | sum += nums.get(i); 44 | max = Math.max(max, sum); 45 | sum = Math.max(sum, 0); 46 | left[i] = max; 47 | } 48 | 49 | max = Integer.MIN_VALUE; 50 | sum = 0; 51 | for (int i = nums.size() - 1; i >= 0; i--) { 52 | sum += nums.get(i); 53 | max = Math.max(max, sum); 54 | sum = Math.max(sum, 0); 55 | right[i] = max; 56 | } 57 | 58 | max = Integer.MIN_VALUE; 59 | for (int i = 0; i < nums.size() - 1; i++) { 60 | max = Math.max(max, left[i] + right[i + 1]); 61 | } 62 | 63 | return max; 64 | } 65 | } 66 | 67 | 68 | -------------------------------------------------------------------------------- /arrays/Median_of_two_Sorted_Arrays.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Median of two Sorted Arrays 4 | 5 | There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. 6 | 7 | Example 8 | Given A=[1,2,3,4,5,6] and B=[2,3,4,5], the median is 3.5. 9 | 10 | Given A=[1,2,3] and B=[4,5], the median is 3. 11 | 12 | Challenge 13 | The overall run time complexity should be O(log (m+n)). 14 | 15 | 16 | 解: 17 | 若两个数组的总长度为奇数,找到中间那个数即可。 18 | 若两个数组的总长度为偶数,需要找到中间的两个数,然后求平均值。 19 | 20 | 这样实际是要求在两个数组中找出任意第几个数。 21 | 所以首先实现找到第k个数的方法。 22 | 23 | 首先把k分成k/2和k-k/2两部分,分别在两个数组中找出对应的值。 24 | 在A中找第k/2个数a,B中找到第k-k/2个数b,比较两个数的大小。 25 | 26 | 如果a大于b,则说明b以及B数组中b之前的所有数一定都在两个数组的第k个数之前,故下次递归时B数组可以从b后面的一个数继续查找。 27 | 同时下次递归时应当从k中减去k-k/2这部分。 28 | 29 | 如果b大于a,则说明a以及A数组中a之前的所有数一定都在两个数组的第k个数之前,故下次递归时A数组可以从a后面的一个数继续查找。 30 | 同时下次递归时应当从k中减去k/2这部分。 31 | 32 | */ 33 | 34 | 35 | class Solution { 36 | /** 37 | * @param A: An integer array. 38 | * @param B: An integer array. 39 | * @return: a double whose format is *.5 or *.0 40 | */ 41 | public double findMedianSortedArrays(int[] A, int[] B) { 42 | int len = A.length + B.length; 43 | if (len % 2 == 0) { 44 | return (((double)findKth(A, 0, B, 0, len / 2) + (double)findKth(A, 0, B, 0, len / 2 + 1)) / 2.0); 45 | } else { 46 | return findKth(A, 0, B, 0, len / 2 + 1); 47 | } 48 | } 49 | 50 | private int findKth(int[] A, int aStart, int[] B, int bStart, int k) { 51 | if (k == 1) { 52 | if (aStart < A.length && bStart < B.length) { 53 | return Math.min(A[aStart], B[bStart]); 54 | } else if (aStart < A.length) { 55 | return A[aStart]; 56 | } else { 57 | return B[bStart]; 58 | } 59 | } 60 | 61 | int a = (aStart + k / 2 - 1 < A.length) ? A[aStart + k / 2 - 1] : Integer.MAX_VALUE; 62 | int b = (bStart + k - k / 2 - 1 < B.length) ? B[bStart + k - k / 2 - 1] : Integer.MAX_VALUE; 63 | 64 | if (a > b) { 65 | return findKth(A, aStart, B, bStart + k - k / 2, k / 2); 66 | } else { 67 | return findKth(A, aStart + k / 2, B, bStart, k - k / 2); 68 | } 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /arrays/Minimum_Adjustment_Cost.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Minimum Adjustment Cost 4 | 5 | 6 | Given an integer array, adjust each integers so that the difference of every adjacent integers are not greater than a given number target. 7 | 8 | If the array before adjustment is A, the array after adjustment is B, you should minimize the sum of |A[i]-B[i]| 9 | Notice 10 | 11 | You can assume each number in the array is a positive integer and not greater than 100. 12 | 13 | Example 14 | 15 | Given [1,4,2,3] and target = 1, one of the solutions is [2,3,2,3], the adjustment cost is 2 and it's minimal. 16 | 17 | Return 2. 18 | 19 | 20 | 解: 21 | dynanmic programming 22 | 23 | dp[i][j]表示将A[i-1]调整到j时,所需要的最小成本。这个cost包含之前所有数的调整成本。 24 | 25 | 递推公式: 26 | 计算dp[i][j]需要两部分值: 27 | 1.A[i-1]与j的差; 28 | 2.A[i-2]调整到j-target到j+target的区间内的最小成本。 29 | 两部分求和就可以得到dp[i][j]。 30 | 故: 31 | dp[i][j] = abs(A[i-1] - j) + min(dp[i-1][j-target+0], dp[i-1][j-target+1], ..., dp[i-1][j+target]), j-target >= 1 && j+target <=100 32 | 33 | 34 | 初始条件: 35 | dp[0][j]应当为0。 36 | 这样可以保证计算第一个数时,也即计算dp[1][j]时,最小成本就是abs(A[0]-j)。 37 | 38 | */ 39 | 40 | public class Solution { 41 | /** 42 | * @param A: An integer array. 43 | * @param target: An integer. 44 | */ 45 | public int MinAdjustmentCost(ArrayList A, int target) { 46 | int[][] dp = new int[A.size() + 1][101]; 47 | int min = 0; 48 | 49 | for (int i = 1; i <= A.size(); i++) { 50 | min = Integer.MAX_VALUE; 51 | for (int j = 0; j <= 100; j++) { 52 | dp[i][j] = Integer.MAX_VALUE; 53 | for (int k = 0; k <= target; k++) { 54 | if (j + k <= 100) { 55 | dp[i][j] = Math.min(dp[i][j], dp[i - 1][j + k]); 56 | } 57 | if (j - k > 0) { 58 | dp[i][j] = Math.min(dp[i][j], dp[i - 1][j - k]); 59 | } 60 | } 61 | 62 | dp[i][j] += Math.abs(A.get(i - 1) - j); 63 | min = Math.min(dp[i][j], min); 64 | } 65 | } 66 | 67 | return min; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /arrays/Minimum_Path_Sum.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Minimum Path Sum 4 | 5 | Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path. 6 | Notice 7 | 8 | You can only move either down or right at any point in time. 9 | 10 | 11 | 解: 12 | dynanmic programming 13 | 14 | dp[i][j]表示从左上角到grid[i - 1][j - 1]的最小path sum。 15 | 由于只能向右或者向下移动,所以每个坐标的最小path sum一定是上方或者左边的坐标的最小path sum加上当前坐标的值。 16 | 17 | 则:dp[i][j] = min(dp[i - 1][j], dp[j - 1][i]) + grid[i - 1][j - 1] 18 | 19 | 注意初始条件,应当计算grid中第一行和第一列的值。 20 | 21 | */ 22 | 23 | public class Solution { 24 | /** 25 | * @param grid: a list of lists of integers. 26 | * @return: An integer, minimizes the sum of all numbers along its path 27 | */ 28 | public int minPathSum(int[][] grid) { 29 | if (grid == null || grid.length == 0) { 30 | return 0; 31 | } 32 | 33 | int[][] dp = new int[grid.length + 1][grid[0].length + 1]; 34 | 35 | // init 36 | for (int i = 1; i <= grid.length; i++) { 37 | dp[i][1] = dp[i - 1][1] + grid[i - 1][0]; 38 | } 39 | 40 | for (int j = 1; j <= grid[0].length; j++) { 41 | dp[1][j] = dp[1][j - 1] + grid[0][j - 1]; 42 | } 43 | 44 | // calc 45 | for (int i = 2; i <= grid.length; i++) { 46 | for (int j = 2; j <= grid[0].length; j++) { 47 | dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1]; 48 | } 49 | } 50 | 51 | return dp[grid.length][grid[0].length]; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /arrays/Minimum_Size_Subarray_Sum.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Minimum Size Subarray Sum 4 | 5 | 6 | Given an array of n positive integers and a positive integer s, find the minimal length of a subarray of which the sum ≥ s. If there isn't one, return -1 instead. 7 | 8 | Example 9 | Given the array [2,3,1,2,4,3] and s = 7, the subarray [4,3] has the minimal length under the problem constraint. 10 | 11 | Challenge 12 | If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n). 13 | 14 | 15 | 解: 16 | 根Continuous Subarray Sum思路完全一致。 17 | 参照: https://github.com/zxqiu/leetcode-lintcode/blob/master/arrays/Continuous_Subarray_Sum.java 18 | 19 | start从0开始,并从start开始累加,如果sum小于0,则sum清零,并且start改成i+1。 20 | 如果sum大于等于s,将start右移,并用sum减去每一个nums[start],直到sum小于s为止。在这过程中记录sum大于等于s的最小子串长度。 21 | 22 | */ 23 | 24 | public class Solution { 25 | /** 26 | * @param nums: an array of integers 27 | * @param s: an integer 28 | * @return: an integer representing the minimum size of subarray 29 | */ 30 | public int minimumSize(int[] nums, int s) { 31 | int start = 0; 32 | int sum = 0; 33 | int ret = nums.length + 1; 34 | 35 | for (int i = 0; i < nums.length; i++) { 36 | sum += nums[i]; 37 | 38 | while (start <= i && sum >= s) { 39 | ret = Math.min(ret, i - start + 1); 40 | sum -= nums[start++]; 41 | } 42 | 43 | if (sum < 0) { 44 | sum = 0; 45 | start = i + 1; 46 | } 47 | } 48 | 49 | return (ret > nums.length) ? -1 : ret; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /arrays/N_Queens_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | N Queens II 4 | 5 | Follow up for N-Queens problem. 6 | 7 | Now, instead outputting board configurations, return the total number of distinct solutions. 8 | 9 | Example 10 | For n=4, there are 2 distinct solutions. 11 | 12 | 13 | 解: 14 | 跟N Queens思路完全一致。 15 | 不同的是只需要统计可行解数量就行。 16 | 17 | 18 | */ 19 | 20 | class Solution { 21 | /** 22 | * Calculate the total number of distinct N-Queen solutions. 23 | * @param n: The number of queens. 24 | * @return: The total number of distinct solutions. 25 | */ 26 | public int totalNQueens(int n) { 27 | int[] path = new int[n]; 28 | Arrays.fill(path, -1); 29 | return helper(path, 0); 30 | } 31 | 32 | private int helper(int[] path, int depth) { 33 | if (depth == path.length) { 34 | return 1; 35 | } 36 | 37 | int ret = 0; 38 | boolean[] avai = available(path, depth); 39 | for (int i = 0; i < path.length; i++) { 40 | if (!avai[i]) { 41 | continue; 42 | } 43 | 44 | path[depth] = i; 45 | ret += helper(path, depth + 1); 46 | path[depth] = -1; 47 | } 48 | 49 | return ret; 50 | } 51 | 52 | private boolean[] available(int[] path, int depth) { 53 | boolean[] ret = new boolean[path.length]; 54 | Arrays.fill(ret, true); 55 | for (int i = 0; i < path.length; i++) { 56 | if (path[i] == -1) { 57 | continue; 58 | } 59 | int diff = depth - i; 60 | int left = path[i] - diff; 61 | int right = path[i] + diff; 62 | 63 | if (left >= 0) { 64 | ret[left] = false; 65 | } 66 | if (right < path.length) { 67 | ret[right] = false; 68 | } 69 | ret[path[i]] = false; 70 | } 71 | return ret; 72 | } 73 | }; 74 | 75 | 76 | -------------------------------------------------------------------------------- /arrays/Next_Permutation.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Next Permutation 4 | 5 | Given a list of integers, which denote a permutation. 6 | 7 | Find the next permutation in ascending order. 8 | 9 | Notice 10 | 11 | The list may contains duplicate integers. 12 | 13 | Example 14 | For [1,3,2,3], the next permutation is [1,3,3,2] 15 | 16 | For [4,3,2,1], the next permutation is [1,2,3,4] 17 | 18 | 19 | 解: 20 | 与Previous Permutation思路一致。 21 | 设一个pivot,从后向前搜索找到第一个小于前一个数的数,与后面第一个大于pivot的数交换。 22 | 然后将pivot后面的所有数递增排列。 23 | 24 | 25 | */ 26 | 27 | public class Solution { 28 | /** 29 | * @param nums: an array of integers 30 | * @return: An array of integers that's next permuation 31 | */ 32 | public int[] nextPermutation(int[] nums) { 33 | if (nums == null || nums.length == 0) { 34 | return nums; 35 | } 36 | 37 | int pivot = -1; 38 | 39 | for (int i = nums.length - 2; i >= 0; i--) { 40 | if (nums[i] < nums[i + 1]) { 41 | pivot = i; 42 | break; 43 | } 44 | } 45 | 46 | if (pivot > -1) { 47 | int i; 48 | for (i = nums.length - 1; nums[i] <= nums[pivot]; i--); 49 | swap(nums, pivot, i); 50 | } 51 | 52 | for (int i = pivot + 1; i <= (nums.length + pivot) / 2; i++) { 53 | swap(nums, i, nums.length - i + pivot); 54 | } 55 | 56 | return nums; 57 | } 58 | 59 | private void swap(int[] nums, int idx0, int idx1) { 60 | int tmp = nums[idx0]; 61 | nums[idx0] = nums[idx1]; 62 | nums[idx1] = tmp; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /arrays/Next_Permutation_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Next Permutation II 4 | 5 | Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers. 6 | 7 | If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order). 8 | 9 | Example 10 | Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column. 11 | 12 | 1,2,3 → 1,3,2 13 | 14 | 3,2,1 → 1,2,3 15 | 16 | 1,1,5 → 1,5,1 17 | 18 | Challenge 19 | The replacement must be in-place, do not allocate extra memory. 20 | 21 | 22 | 解: 23 | 跟Next Permutation思路一致。 24 | 注意在pivot右侧寻找的是大于nums[pivot]的数字。 25 | 26 | */ 27 | 28 | 29 | public class Solution { 30 | /** 31 | * @param nums: an array of integers 32 | * @return: return nothing (void), do not return anything, modify nums in-place instead 33 | */ 34 | public void nextPermutation(int[] nums) { 35 | int pivot = nums.length - 2; 36 | int left, right; 37 | 38 | if (nums.length < 2) { 39 | return; 40 | } 41 | 42 | for (; pivot >= 0; pivot--) { 43 | if (nums[pivot] < nums[pivot + 1]) { 44 | break; 45 | } 46 | } 47 | 48 | if (pivot >= 0) { 49 | int i = nums.length - 1; 50 | for (; i > pivot && nums[i] <= nums[pivot]; i--); 51 | swap(nums, i, pivot); 52 | } 53 | 54 | left = pivot + 1; 55 | right = nums.length - 1; 56 | while (left < right) { 57 | swap(nums, left++, right--); 58 | } 59 | } 60 | 61 | private void swap(int[] nums, int a, int b) { 62 | int tmp = nums[a]; 63 | nums[a] = nums[b]; 64 | nums[b] = tmp; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /arrays/Number_of_Airplanes_in_the_Sky.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Number of Airplanes in the Sky 4 | 5 | 6 | Given an interval list which are flying and landing time of the flight. How many airplanes are on the sky at most? 7 | 8 | Notice 9 | 10 | If landing and flying happens at the same time, we consider landing should happen at first. 11 | 12 | Example 13 | For interval list 14 | 15 | [ 16 | [1,10], 17 | [2,3], 18 | [5,8], 19 | [4,7] 20 | ] 21 | Return 3 22 | 23 | 解: 24 | scan line问题。 25 | 把所有起降时间放到同一条时间线上,并标记是起飞还是降落。 26 | 扫描这条线,遇到一个起飞就对计数器加一,遇到一个降落就对计数器减一。保存计数器的最大值。 27 | 注意,如果两个飞机在同一时间一个起飞一个降落,这时空中的飞机数量应当不变。所以应当把降落排在起飞前面。 28 | 29 | */ 30 | 31 | /** 32 | * Definition of Interval: 33 | * public classs Interval { 34 | * int start, end; 35 | * Interval(int start, int end) { 36 | * this.start = start; 37 | * this.end = end; 38 | * } 39 | */ 40 | 41 | class Solution { 42 | /** 43 | * @param intervals: An interval array 44 | * @return: Count of airplanes are in the sky. 45 | */ 46 | private class Node { 47 | int time; 48 | boolean isLanding; 49 | 50 | public Node(int time, boolean isLanding) { 51 | this.time = time; 52 | this.isLanding = isLanding; 53 | } 54 | } 55 | 56 | public int countOfAirplanes(List airplanes) { 57 | Queue q = new PriorityQueue(1, new Comparator() { 58 | public int compare(Node a, Node b) { 59 | if (a.time != b.time) { 60 | return a.time - b.time; 61 | } 62 | 63 | if (a.isLanding) { 64 | return -1; 65 | } 66 | 67 | return 1; 68 | } 69 | }); 70 | int cnt = 0; 71 | int max = 0; 72 | 73 | for (Interval i : airplanes) { 74 | q.offer(new Node(i.start, false)); 75 | q.offer(new Node(i.end, true)); 76 | } 77 | 78 | while (!q.isEmpty()) { 79 | if (q.poll().isLanding) { 80 | cnt--; 81 | } else { 82 | cnt++; 83 | } 84 | max = Math.max(max, cnt); 85 | } 86 | 87 | return max; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /arrays/Paint_House.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Paint House 4 | 5 | There are a row of n houses, each house can be painted with one of the three colors: red, blue or green. The cost of painting each house with a certain color is different. You have to paint all the houses such that no two adjacent houses have the same color. 6 | 7 | The cost of painting each house with a certain color is represented by a n x 3 cost matrix. For example, costs[0][0] is the cost of painting house 0 with color red; costs[1][2] is the cost of painting house 1 with color green, and so on... Find the minimum cost to paint all houses. 8 | 9 | Notice 10 | 11 | All costs are positive integers. 12 | 13 | Example 14 | Given costs = [[14,2,11],[11,14,5],[14,3,10]] return 10 15 | 16 | house 0 is blue, house 1 is green, house 2 is blue, 2 + 5 + 3 = 10 17 | 18 | 19 | 解: 20 | Dynanmic Programming 21 | 22 | 递推公式: 23 | dp[i][j]表示第i栋房子涂成j颜色时,包括前面所有房子在内的最小花费。 24 | i涂成j颜色时,只需要直到到i-1为止,除了j以外的两个颜色的最小花费。 25 | 取其中小的那个与i涂成j的花费相加,就得到了dp[i][j]。 26 | 27 | 故: 28 | dp[i][j] = min(dp[i][p], dp[i][q]) + costs[i-1][j], j=0~2,p=0~2,q=0~2, j!=p,j!=q,p!=q 29 | 30 | 31 | 初始条件: 32 | 涂0栋房子时,任何颜色都不需要花钱。 33 | 故dp[0][0~2]=0 34 | 35 | 36 | 计算完成后,取最后一栋房子最便宜的颜色即可。 37 | 38 | */ 39 | 40 | public class Solution { 41 | /** 42 | * @param costs n x 3 cost matrix 43 | * @return an integer, the minimum cost to paint all houses 44 | */ 45 | public int minCost(int[][] costs) { 46 | if (costs == null || costs.length == 0) { 47 | return 0; 48 | } 49 | 50 | int m = costs.length; 51 | int[][] dp = new int[m + 1][3]; 52 | 53 | for (int i = 1; i <= m; i++) { 54 | dp[i][0] = Math.min(dp[i - 1][1], dp[i - 1][2]) + costs[i - 1][0]; 55 | dp[i][1] = Math.min(dp[i - 1][0], dp[i - 1][2]) + costs[i - 1][1]; 56 | dp[i][2] = Math.min(dp[i - 1][0], dp[i - 1][1]) + costs[i - 1][2]; 57 | } 58 | 59 | return Math.min(dp[m][0], Math.min(dp[m][1], dp[m][2])); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /arrays/Partition_Array.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Partition Array 4 | 5 | Given an array nums of integers and an int k, partition the array (i.e move the elements in "nums") such that: 6 | 7 | All elements < k are moved to the left 8 | All elements >= k are moved to the right 9 | Return the partitioning index, i.e the first index i nums[i] >= k. 10 | 11 | Notice 12 | 13 | You should do really partition in array nums instead of just counting the numbers of integers smaller than k. 14 | 15 | If all elements in nums are smaller than k, then return nums.length 16 | 17 | 18 | Example 19 | If nums = [3,2,2,1] and k=2, a valid answer is 1. 20 | 21 | Challenge 22 | Can you partition the array in-place and in O(n)? 23 | 24 | 解: 25 | 这道题考察的实际是quick sort或者quick select。 26 | 两个指针分别指向数组的头和尾。 27 | 1.如果头指针指向的值小于k,头指针向后移动一次。 28 | 2.如果尾指针指向的值大于等于k,尾指针向前移动一次。 29 | 3.否则,说明头指针的值大于或者等于k,而尾指针的值小于k,此时应当交换两个值。 30 | 4.重复1~4直到首尾指针相遇。 31 | 32 | 返回时由于不知道最后一次移动的是头指针还是尾指针,所以需要判断两个指针相遇时的值。 33 | 若小于k则返回下一个位置下标,否则返回相遇时的下标。 34 | 35 | 36 | */ 37 | 38 | 39 | public class Solution { 40 | /** 41 | * param nums: The integer array you should partition 42 | * param k: As description 43 | * return: The index after partition 44 | */ 45 | public int partitionArray(int[] nums, int k) { 46 | if (nums == null || nums.length == 0) { 47 | return 0; 48 | } 49 | 50 | int left = 0; 51 | int right = nums.length - 1; 52 | 53 | while (left < right) { 54 | if (nums[left] < k) { 55 | left++; 56 | } else if (nums[right] >= k) { 57 | right--; 58 | } else { 59 | int tmp = nums[left]; 60 | nums[left] = nums[right]; 61 | nums[right] = tmp; 62 | } 63 | } 64 | 65 | return (nums[left] < k) ? left + 1 : left; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /arrays/Permutation_Index.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Permutation Index 4 | 5 | 6 | Given a permutation which contains no repeated number, find its index in all the permutations of these numbers, which are ordered in lexicographical order. The index begins at 1. 7 | 8 | Example 9 | Given [1,2,4], return 1. 10 | 11 | 解: 12 | 如果有四个数字,总共有4!种排列。 13 | 第一个数字有4种可能,后面有3!种,共有4*3!种。 14 | 对于一个固定的四个数的排列,第一个数字m之后如果有n个小于m的数,该排列之前应当有n*3!+其后的排列数量。 15 | 故总共有 : m0*3!+m1*2!+m2*1!+m1*0! 16 | 17 | m表示该数后面有多少小于该数的数字。 18 | 19 | 20 | */ 21 | 22 | 23 | public class Solution { 24 | /** 25 | * @param A an integer array 26 | * @return a long integer 27 | */ 28 | public long permutationIndex(int[] A) { 29 | long ret = 1; 30 | long fact = 1; 31 | 32 | if (A == null || A.length == 0) { 33 | return 0; 34 | } 35 | 36 | for (int i = A.length - 1; i >= 0; i--) { 37 | int cnt = 0; 38 | 39 | for (int j = i + 1; j < A.length; j++) { 40 | if (A[j] < A[i]) { 41 | cnt++; 42 | } 43 | } 44 | 45 | ret += cnt * fact; 46 | fact *= A.length - i; 47 | } 48 | 49 | return ret; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /arrays/Permutation_Index_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Permutation Index II 4 | 5 | Given a permutation which may contain repeated numbers, find its index in all the permutations of these numbers, which are ordered in lexicographical order. The index begins at 1. 6 | 7 | Example 8 | Given the permutation [1, 4, 2, 2], return 3. 9 | 10 | 11 | 解: 12 | 跟Permutation Index思路一致。 13 | 需要注意的是由于存在重复,所以每个数的结果应当除以包括该数在内每个重复数字数量的阶乘的乘积。 14 | 由于1!=1,所以可以除以每个数字数量阶乘的乘积。其实可以用一个数字每次乘以每次统计的当前数字的数量,就是想要的乘积。 15 | 16 | 比如对于4,1,1,2,2, 17 | 计算到4时的计算公式为:(cnt * 4!) / (1! * 2! * 2!), cnt = 4 18 | 19 | 用HashMap来统计有多少重复的数字。 20 | 21 | */ 22 | 23 | public class Solution { 24 | /** 25 | * @param A an integer array 26 | * @return a long integer 27 | */ 28 | public long permutationIndexII(int[] A) { 29 | long ret = 1; 30 | long fact = 1; 31 | long mulFact = 1; 32 | Map map = new HashMap(); 33 | 34 | if (A == null || A.length == 0) { 35 | return 0; 36 | } 37 | 38 | for (int i = A.length - 1; i >= 0; i--) { 39 | int cnt = 0; 40 | 41 | if (!map.containsKey(A[i])) { 42 | map.put(A[i], 0); 43 | } 44 | map.put(A[i], map.get(A[i]) + 1); 45 | 46 | mulFact *= map.get(A[i]); 47 | 48 | for (int j = i + 1; j < A.length; j++) { 49 | if (A[j] < A[i]) { 50 | cnt++; 51 | } 52 | } 53 | 54 | ret += cnt * fact / mulFact; 55 | fact *= A.length - i; 56 | } 57 | 58 | return ret; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /arrays/Permutation_Sequence.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Permutation Sequence 4 | 5 | 6 | Given n and k, return the k-th permutation sequence. 7 | 8 | Notice 9 | 10 | n will be between 1 and 9 inclusive. 11 | 12 | Example 13 | For n = 3, all permutations are listed as follows: 14 | 15 | "123" 16 | "132" 17 | "213" 18 | "231" 19 | "312" 20 | "321" 21 | If k = 4, the fourth permutation is "231" 22 | 23 | Challenge 24 | O(n*k) in time complexity is easy, can you do it in O(n^2) or less? 25 | 26 | 解: 27 | 分析上面的例子。 28 | 第一个数字后面的数有2!种组合,也就是说第一个数字选定后一共有2!个以该数字开头的组合,故第一个数字应当是{1,2,3}中的第(k-1)/2!个(从第0个到第3个),k-1如果小于0则应当改为0,故: 29 | n = max(0,k-1)/2! = 1 30 | k=3故第一个数字为2。 31 | 第一个数字选定之后,k应当修改为下一个数字是剩余所有数字中的第几个,也就是说k中应当减去2之前所有数字作为第一个数时的所有排列数量: 32 | k -= n*2! = 1 (由于n从0开始,故与当前选定数字之前有几个数相等) 33 | 34 | 同理第二个数字应当为{1,3}中的第n = max(0,k-1)/1!个,此时k=1,故n=0,选中1。 35 | 更新k: 36 | k -= n*1! = 1 37 | 38 | 同理第三个数字应当选中{3}中的第n = max(0,k-1)/1!个,此时k=1,故n=0,选中3。 39 | 40 | */ 41 | 42 | class Solution { 43 | /** 44 | * @param n: n 45 | * @param k: the kth permutation 46 | * @return: return the k-th permutation 47 | */ 48 | public String getPermutation(int n, int k) { 49 | ArrayList factors = new ArrayList(); 50 | ArrayList nums = new ArrayList(); 51 | String ret = ""; 52 | 53 | factors.add(1); // 0! = 1 54 | for (int i = 1; i <= n; i++) { 55 | nums.add(i); 56 | factors.add(factors.get(i - 1) * i); 57 | } 58 | 59 | for (int i = n; i >= 1; i--) { 60 | int idx = Math.max(0, k - 1) / factors.get(i - 1); 61 | k -= idx * factors.get(i - 1); 62 | ret += String.valueOf(nums.get(idx)); 63 | nums.remove(idx); 64 | } 65 | 66 | return ret; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /arrays/Permutations_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Permutations II 4 | 5 | Given a list of numbers with duplicate number in it. Find all unique permutations. 6 | 7 | 8 | Example 9 | For numbers [1,2,2] the unique permutations are: 10 | 11 | [ 12 | [1,2,2], 13 | [2,1,2], 14 | [2,2,1] 15 | ] 16 | 17 | Challenge 18 | Using recursion to do it is acceptable. If you can do it without recursion, that would be great! 19 | 20 | 21 | 解: 22 | DFS 23 | 跟Permutation方法类似,不同的是需要对数组排序,然后在每一层的循环中检查是否有连续两个相同的数被加入队列中。 24 | 25 | */ 26 | 27 | public class Solution { 28 | /* 29 | * @param : A list of integers 30 | * @return: A list of unique permutations 31 | */ 32 | public List> permuteUnique(int[] nums) { 33 | List> ret = new ArrayList>(); 34 | 35 | Arrays.sort(nums); 36 | helper(nums, new int[nums.length], new ArrayList(), ret); 37 | 38 | return ret; 39 | } 40 | 41 | private void helper(int[] nums, int[] used, List cur, List> ret) { 42 | if (cur.size() == nums.length) { 43 | ret.add(new ArrayList(cur)); 44 | return; 45 | } 46 | 47 | int lastIdx = -1; 48 | 49 | for (int i = 0; i < nums.length; i++) { 50 | if (used[i] == 1 || (lastIdx >= 0 && nums[i] == nums[lastIdx])) { 51 | continue; 52 | } 53 | 54 | lastIdx = i; 55 | used[i] = 1; 56 | cur.add(nums[i]); 57 | helper(nums, used, cur, ret); 58 | 59 | used[i] = 0; 60 | cur.remove(cur.size() - 1); 61 | } 62 | } 63 | }; 64 | -------------------------------------------------------------------------------- /arrays/Previous_Permutation.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Previous Permutation 4 | 5 | Given a list of integers, which denote a permutation. 6 | 7 | Find the previous permutation in ascending order. 8 | 9 | Notice 10 | 11 | The list may contains duplicate integers. 12 | 13 | Example 14 | For [1,3,2,3], the previous permutation is [1,2,3,3] 15 | For [1,2,3,4], the previous permutation is [4,3,2,1] 16 | 17 | 18 | 解: 19 | 先考虑一般情况,如果一个数组不是第一个permutation, 20 | 那么首先,其末尾一定存在一个或多个数字按照递增顺序排列, 21 | 其次,在这个递增序列之前一定存在一个数大于其后方的数字。假设这个数字为pivot。 22 | 比如输入1,5,2,3,4,pivot为5,其后数字为递增序列。 23 | 24 | pivot一定为第一个大于其后数字的数字,计算上一个permutation时不需要考虑pivot左边的数字。 25 | 26 | 对于这样的数组,计算其上一个permutation时, 27 | 首先从后向前找到第一个小于pivot指向数字的数,交换该数字与pivot指向数字。由于是第一个小于pivot指向数的数,交换后pivot位置后面的数组依然递增。 28 | 比如1,5,2,3,4变成1,4,2,3,5。 29 | 然后将pivot(交换后pivot位置并不改变)后面的数字由递增改成递减。 30 | 上面数组变成1,4,5,3,2 31 | 这样就得到了previous permutation。 32 | 33 | 如果考虑第一个permutation,比如1,2,3,4,5,只需要直接将数组倒序排列。 34 | 35 | 36 | */ 37 | 38 | public class Solution { 39 | /** 40 | * @param nums: A list of integers 41 | * @return: A list of integers that's previous permuation 42 | */ 43 | public ArrayList previousPermuation(ArrayList nums) { 44 | int pivot = -1; 45 | 46 | /* find pivot */ 47 | for (int i = nums.size() - 2; i >= 0; i--) { 48 | if (nums.get(i) > nums.get(i + 1)) { 49 | pivot = i; 50 | break; 51 | } 52 | } 53 | 54 | /* correct pivot value */ 55 | if (pivot > -1) { 56 | int i = nums.size() - 1; 57 | for (; i > pivot && nums.get(i) >= nums.get(pivot); i--); 58 | swap(nums, pivot, i); 59 | } 60 | 61 | /* sort nums after pivot */ 62 | for (int i = pivot + 1; i <= (nums.size() + pivot) / 2; i++) { 63 | swap(nums, i, nums.size() - i + pivot); 64 | } 65 | 66 | return nums; 67 | } 68 | 69 | private void swap(ArrayList nums, int idx0, int idx1) { 70 | int tmp = nums.get(idx0); 71 | nums.set(idx0, nums.get(idx1)); 72 | nums.set(idx1, tmp); 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /arrays/Remove_Duplicates_from_Sorted_Array.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length. 3 | 4 | Do not allocate extra space for another array, you must do this in place with constant memory. 5 | */ 6 | 7 | 8 | /* 9 | 从第二个数字开始,把新的(不重复)的数字存到store指向的位置。 10 | store从第二个数字开始,每次存入新的数字便增加1。 11 | 重复的数字会不断被覆盖,最后数组最前部分就是不重复的数字。 12 | */ 13 | public class Solution { 14 | /** 15 | ** @param A: a array of integers 16 | ** @return : return an integer 17 | **/ 18 | public int removeDuplicates(int[] nums) { 19 | if (nums == null || nums.length == 0) { 20 | return 0; 21 | } 22 | 23 | int store = 1; 24 | 25 | for (int i = 1; i < nums.length; i++) { 26 | if (nums[i] != nums[i - 1]) { 27 | nums[store++] = nums[i]; 28 | } 29 | } 30 | 31 | return store; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /arrays/Remove_Duplicates_from_Sorted_Array_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | Follow up for "Remove Duplicates": 3 | What if duplicates are allowed at most twice? 4 | 5 | For example, 6 | Given sorted array A = [1,1,1,2,2,3], 7 | 8 | Your function should return length = 5, and A is now [1,1,2,2,3]. 9 | */ 10 | 11 | 12 | /* 13 | 方法一: 判断当前数与上上一个数是否相等。 14 | 注意上上一个数可能被刚保存的数覆盖掉,所以需要在保存之前将其存到别处备用。 15 | */ 16 | 17 | public class Solution { 18 | /** 19 | * @param A: a array of integers 20 | * @return : return an integer 21 | */ 22 | public int removeDuplicates(int[] nums) { 23 | if (nums == null) { 24 | return 0; 25 | } else if (nums.length < 3) { 26 | return nums.length; 27 | } 28 | 29 | int store = 2; 30 | int backup = nums[store]; 31 | for (int i = 2; i < nums.length; i++) { 32 | int cmp = (i - 2 == store - 1) ? backup : nums[i - 2]; 33 | if (nums[i] != cmp) { 34 | backup = nums[store]; 35 | nums[store++] = nums[i]; 36 | } 37 | } 38 | 39 | return store; 40 | } 41 | } 42 | 43 | /* 44 | 方法二: 判断当前数与刚存储的数,以及上一个存储的数是否相等。 45 | 若与刚存储的数不等,则保存; 46 | 若与当前数相等,但是与上一个存储的数不等,则保存; 47 | 若与当前数相等,但是与上一个存储的数相等,则不保存。 48 | */ 49 | public class Solution { 50 | /** 51 | * @param A: a array of integers 52 | * @return : return an integer 53 | */ 54 | public int removeDuplicates(int[] nums) { 55 | if (nums == null) { 56 | return 0; 57 | } else if (nums.length < 3) { 58 | return nums.length; 59 | } 60 | 61 | int cnt = 1; 62 | for (int i = 2; i < nums.length; i++) { 63 | if (nums[i] == nums[cnt] && nums[i] != nums[cnt - 1]) { 64 | nums[++cnt] = nums[i]; 65 | } else if (nums[i] != nums[cnt]) { 66 | nums[++cnt] = nums[i]; 67 | } 68 | } 69 | 70 | return ++cnt; 71 | } 72 | } -------------------------------------------------------------------------------- /arrays/Reorder_array_to_construct_the_minimum_number.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Reorder array to construct the minimum number 4 | 5 | 6 | Construct minimum number by reordering a given non-negative integer array. Arrange them such that they form the minimum number. 7 | 8 | Notice 9 | 10 | The result may be very large, so you need to return a string instead of an integer. 11 | 12 | Example 13 | Given [3, 32, 321], there are 6 possible numbers can be constructed by reordering the array: 14 | 15 | 3+32+321=332321 16 | 3+321+32=332132 17 | 32+3+321=323321 18 | 32+321+3=323213 19 | 321+3+32=321332 20 | 321+32+3=321323 21 | So after reordering, the minimum number is 321323, and return it. 22 | 23 | Challenge 24 | Do it in O(nlogn) time complexity. 25 | 26 | 27 | 解: 28 | 对于任意两个数字a和b,如果ab大于ba,那么a应当放在b前面,否则b应当放在a前面。 29 | 无论a和b之前是否有别的数字,这个条件都成立。 30 | 31 | 所以按照此规则对数组进行排序,然后组成一个字符串。 32 | 33 | */ 34 | 35 | public class Solution { 36 | /** 37 | * @param nums n non-negative integer array 38 | * @return a string 39 | */ 40 | public String minNumber(int[] nums) { 41 | if (nums == null || nums.length == 0) { 42 | return ""; 43 | } 44 | 45 | String ret = ""; 46 | Integer[] in = new Integer[nums.length]; 47 | 48 | for (int i = 0; i < nums.length; i++) { 49 | in[i] = nums[i]; 50 | } 51 | 52 | Arrays.sort(in, comparator); 53 | 54 | for (int i : in) { 55 | if (ret.length() == 0 && i == 0) { 56 | continue; 57 | } 58 | ret += String.valueOf(i); 59 | } 60 | 61 | return ret.length() == 0 ? "0" : ret; 62 | } 63 | 64 | Comparator comparator = new Comparator() { 65 | public int compare(Integer a, Integer b) { 66 | String sA = String.valueOf(a) + String.valueOf(b); 67 | String sB = String.valueOf(b) + String.valueOf(a); 68 | 69 | return sA.compareTo(sB); 70 | } 71 | }; 72 | } 73 | -------------------------------------------------------------------------------- /arrays/Reverse_Pairs.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Reverse Pairs 4 | 5 | 6 | For an array A, if i < j, and A [i] > A [j], called (A [i], A [j]) is a reverse pair. 7 | return total of reverse pairs in A. 8 | 9 | Have you met this question in a real interview? Yes 10 | Example 11 | Given A = [2, 4, 1, 3, 5] , (2, 1), (4, 1), (4, 3) are reverse pairs. return 3 12 | 13 | 14 | 解: 15 | merge sort 16 | 17 | 这道题求有多少组数字满足左边比右边大。 18 | 19 | 对数组进行merge sort。 20 | 将每次递归输入数组分成左右两段,分别统计左右两段内部的reverse pairs,并且在merge时统计左右两边之间的reverse pairs。 21 | 把三个统计结果相加并返回。 22 | 23 | merge时,如果左边当前值比右边当前值大,那么左边从这个数开始后面所有数都比右边当前值大,需要把左边剩余数量加入统计结果。 24 | 25 | */ 26 | 27 | 28 | 29 | public class Solution { 30 | /** 31 | * @param A an array 32 | * @return total of reverse pairs 33 | */ 34 | public long reversePairs(int[] A) { 35 | if (A == null || A.length == 0) { 36 | return 0L; 37 | } 38 | 39 | return mergeSort(A, 0, A.length - 1, new int[A.length]); 40 | } 41 | 42 | private long mergeSort(int[] A, int start, int end, int[] t) { 43 | if (start == end) { 44 | t[0] = A[start]; 45 | return 0; 46 | } 47 | 48 | int mid = (start + end) / 2; 49 | int[] l = new int[mid - start + 1]; 50 | int[] r = new int[end - mid]; 51 | long ret = mergeSort(A, start, mid, l); 52 | ret += mergeSort(A, mid + 1, end, r); 53 | ret += merge(l, r, t); 54 | 55 | return ret; 56 | } 57 | 58 | private long merge(int[] l, int[] r, int[] t) { 59 | int left = 0; 60 | int right = 0; 61 | int i = 0; 62 | long ret = 0; 63 | 64 | while (left < l.length && right < r.length) { 65 | if (l[left] > r[right]) { 66 | ret += l.length - left; 67 | t[i++] = r[right++]; 68 | } else { 69 | t[i++] = l[left++]; 70 | } 71 | } 72 | 73 | while (left < l.length) { 74 | t[i++] = l[left++]; 75 | } 76 | 77 | while (right < r.length) { 78 | t[i++] = r[right++]; 79 | } 80 | 81 | return ret; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /arrays/Rotate_Image.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Rotate Image 4 | 5 | 6 | You are given an n x n 2D matrix representing an image. 7 | Rotate the image by 90 degrees (clockwise). 8 | 9 | Example 10 | Given a matrix 11 | 12 | [ 13 | [1,2], 14 | [3,4] 15 | ] 16 | rotate it by 90 degrees (clockwise), return 17 | 18 | [ 19 | [3,1], 20 | [4,2] 21 | ] 22 | Challenge 23 | Do it in-place. 24 | 25 | 26 | 解: 27 | 把原图按照左上,右上,左下,右下分成四个矩形。然后顺时针移动矩形中的每个点。 28 | 只需要遍历一个矩形,然后分别更新其在其他三个区域的对应点即可。 29 | 30 | */ 31 | 32 | 33 | public class Solution { 34 | /** 35 | * @param matrix: A list of lists of integers 36 | * @return: Void 37 | */ 38 | public void rotate(int[][] matrix) { 39 | int len; 40 | 41 | if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { 42 | return; 43 | } 44 | 45 | len = matrix.length; 46 | 47 | for (int i = 0; i < len / 2; i++) { 48 | for (int j = 0; j < (len + 1) / 2; j++) { 49 | int tmp0, tmp1, x, y; 50 | 51 | x = j; 52 | y = len - 1 - i; 53 | tmp0 = matrix[x][y]; 54 | matrix[x][y] = matrix[i][j]; 55 | 56 | x = len - 1 - i; 57 | y = len - 1 - j; 58 | tmp1 = matrix[x][y]; 59 | matrix[x][y] = tmp0; 60 | 61 | x = len - 1 - j; 62 | y = i; 63 | tmp0 = matrix[x][y]; 64 | matrix[x][y] = tmp1; 65 | 66 | matrix[i][j] = tmp0; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /arrays/Search_a_2D_Matrix_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Search a 2D Matrix II 4 | 5 | Write an efficient algorithm that searches for a value in an m x n matrix, return the occurrence of it. 6 | 7 | This matrix has the following properties: 8 | 9 | Integers in each row are sorted from left to right. 10 | Integers in each column are sorted from up to bottom. 11 | No duplicate integers in each row or column. 12 | 13 | Example 14 | Consider the following matrix: 15 | 16 | [ 17 | [1, 3, 5, 7], 18 | [2, 4, 7, 8], 19 | [3, 5, 9, 10] 20 | ] 21 | Given target = 3, return 2. 22 | 23 | Challenge 24 | O(m+n) time and O(1) extra space 25 | 26 | 解: 27 | 使用一个walker从由上角开始搜索: 28 | 1. 若当前值大于target,由于左边的值一定小于当前值,下方的值一定大于当前值,故向左移动一步; 29 | 2. 若当前值等于target,首先计数器加一。由于下方的值一定大于当前值,左边的值一定小于当前值也一定小于target,故向下移动一步; 30 | 3. 若当前值小于target,由于左边的值一定小于当前值也一定小于target,下方的值一定大于当前值,下方一行左边可能包含target,故向下移动一步。由于右边的值一定大于target,而右下方的值也一定大于target,所以不要向右下方移动。 31 | 32 | 也可以从左下角开始搜索,但是不能从左上角或者右下角开始。 33 | 因为如果从左上角或者右下角开始搜索,每一次判断时选择都不唯一。 34 | 比如从左上角开始向右搜索时,若当前值小于target,右边的值和下边的值都大于当前值,也可能都小于target,此时不能兼顾两种选择,容易出现遗漏。 35 | 36 | */ 37 | 38 | public class Solution { 39 | /** 40 | * @param matrix: A list of lists of integers 41 | * @param: A number you want to search in the matrix 42 | * @return: An integer indicate the occurrence of target in the given matrix 43 | */ 44 | public int searchMatrix(int[][] matrix, int target) { 45 | if (matrix == null || matrix.length == 0) { 46 | return 0; 47 | } 48 | 49 | int x, y, cnt; 50 | 51 | x = 0; 52 | y = matrix[0].length - 1; 53 | cnt = 0; 54 | 55 | while (x < matrix.length && y >= 0) { 56 | if (matrix[x][y] > target) { 57 | y--; 58 | } else if (matrix[x][y] == target) { 59 | cnt++; 60 | x++; 61 | } else if (matrix[x][y] < target) { 62 | x++; 63 | } 64 | } 65 | 66 | return cnt; 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /arrays/Search_for_a_Range.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Search for a Range 4 | 5 | Given a sorted array of n integers, find the starting and ending position of a given target value. 6 | 7 | If the target is not found in the array, return [-1, -1]. 8 | 9 | Example 10 | Given [5, 7, 7, 8, 8, 10] and target value 8, 11 | return [3, 4]. 12 | 13 | Challenge 14 | O(log n) time. 15 | 16 | 17 | 解: 18 | 先用二分法找到任意一个target,然后分别往前后搜索第一个和最后一个target的index。 19 | 20 | */ 21 | 22 | public class Solution { 23 | /** 24 | * @param A : an integer sorted array 25 | * @param target : an integer to be inserted 26 | * return : a list of length 2, [index1, index2] 27 | */ 28 | public int[] searchRange(int[] A, int target) { 29 | int[] ret = {-1, -1}; 30 | int left, right, mid; 31 | 32 | left = mid = 0; 33 | right = A.length - 1; 34 | 35 | while (left <= right) { 36 | mid = (left + right) / 2; 37 | 38 | if (A[mid] == target) { 39 | break; 40 | } else if (A[mid] > target) { 41 | right = mid - 1; 42 | } else { 43 | left = mid + 1; 44 | } 45 | } 46 | 47 | if (left <= right) { 48 | for (left = mid; left >= 0 && A[left] == target; left--); 49 | for (right = mid; right < A.length && A[right] == target; right++); 50 | ret[0] = ++left; 51 | ret[1] = --right; 52 | } 53 | 54 | return ret; 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /arrays/Single_Number_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Single Number II 4 | 5 | 6 | 7 | Given 3*n + 1 numbers, every numbers occurs triple times except one, find it. 8 | 9 | Example 10 | 11 | Given [1,1,2,3,3,3,2,2,4,1] return 4 12 | Challenge 13 | 14 | One-pass, constant extra space. 15 | 16 | 17 | 解: 18 | 按位统计每个数字的每一位。如果某一位的计数器超过3则清零重来。 19 | 由于存在一个单独的数字,故最后留下的就是它。再用位运算还原即可。 20 | 21 | */ 22 | 23 | public class Solution { 24 | /** 25 | * @param A : An integer array 26 | * @return : An integer 27 | */ 28 | public int singleNumberII(int[] A) { 29 | int[] cnt = new int[32]; 30 | int ret = 0; 31 | 32 | for (int a : A) { 33 | for (int i = 0; i < 32; i++) { 34 | cnt[i] = (((a & (1 << i)) >> i) + cnt[i]) % 3; 35 | } 36 | } 37 | 38 | for (int i = 0; i < 32; i++) { 39 | ret |= (cnt[i] << i); 40 | } 41 | 42 | return ret; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /arrays/Single_Number_III.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Single Number III 4 | 5 | 6 | Given 2*n + 2 numbers, every numbers occurs twice except two, find them. 7 | 8 | Example 9 | 10 | Given [1,2,2,3,4,4,5,3] return 1 and 5 11 | Challenge 12 | 13 | O(n) time, O(1) extra space. 14 | 15 | 16 | 解: 17 | 分治法 18 | 19 | 这道题需要拆解成两个Single Number问题。 20 | 21 | 先计算出所有数异或的结果,也就是两个single number的异或结果。 22 | 找出这个结果中任意一个值为1的bit,用该bit把A中所有数分成两组,这两个数分属一组。 23 | 对每组分别进行异或,分别得到的结果就是这两个数。 24 | 25 | */ 26 | 27 | public class Solution { 28 | /** 29 | * @param A : An integer array 30 | * @return : Two integers 31 | */ 32 | public List singleNumberIII(int[] A) { 33 | int xor, diff, candidate0, candidate1; 34 | List ret = new ArrayList(); 35 | 36 | if (A == null || A.length == 0) { 37 | return ret; 38 | } 39 | 40 | xor = candidate0 = candidate1 = 0; 41 | 42 | /* find xor of the two numbers */ 43 | for (int i : A) { 44 | xor ^= i; 45 | } 46 | 47 | /* find last "1" bit to seperate A into two group */ 48 | diff = xor & (xor ^ (xor - 1)); 49 | 50 | /* seperate A into to group and find the two numbers */ 51 | for (int i : A) { 52 | if ((i & diff) == 0) { 53 | candidate0 ^= i; 54 | } else { 55 | candidate1 ^= i; 56 | } 57 | } 58 | 59 | ret.add(candidate0); 60 | ret.add(candidate1); 61 | 62 | return ret; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /arrays/Sliding_Window_Maximum.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Sliding Window Maximum 4 | 5 | 6 | Given an array of n integer with duplicate number, and a moving window(size k), move the window at each iteration from the start of the array, find the maximum number inside the window at each moving. 7 | 8 | Example 9 | For array [1, 2, 7, 7, 8], moving window size k = 3. return [7, 7, 8] 10 | 11 | At first the window is at the start of the array like this 12 | 13 | [|1, 2, 7| ,7, 8] , return the maximum 7; 14 | 15 | then the window move one step forward. 16 | 17 | [1, |2, 7 ,7|, 8], return the maximum 7; 18 | 19 | then the window move one step forward again. 20 | 21 | [1, 2, |7, 7, 8|], return the maximum 8; 22 | 23 | Challenge 24 | o(n) time and O(k) memory 25 | 26 | 27 | 28 | 解: 29 | 用一个双端队列来保存最大值序列的index。 30 | 如果在nums[i]遇到当前窗口i-k+1到i中的最大值,那么之前保存的任何最大值都没有用处了。 31 | 如果Nums[i+1]大于nums[i],那么当窗口运行到i+1时,之前保存的最大值nums[i]也没有用处了,可以从队列中删除。 32 | 33 | 故双端队列中只需要保存有用的值,没用的值可以删掉。 34 | 35 | 1.如果队列头为i-k,说明该值已经在窗口之外,直接删掉。 36 | 2.从后向前删除队列中所有指向值小于nums[i]的index。 37 | 3.把i入队。 38 | 4.如果已经有至少k个数字被处理过,即i>=k-1,将队列头所指向的值(此时应当为队列中的最大值)加入结果队列。 39 | 40 | */ 41 | 42 | public class Solution { 43 | /** 44 | * @param nums: A list of integers. 45 | * @return: The maximum number inside the window at each moving. 46 | */ 47 | public ArrayList maxSlidingWindow(int[] nums, int k) { 48 | ArrayList ret = new ArrayList(); 49 | Deque q = new LinkedList(); 50 | 51 | for (int i = 0; i < nums.length; i++) { 52 | if (!q.isEmpty() && q.peek() == i - k) { 53 | q.removeFirst(); 54 | } 55 | 56 | while (!q.isEmpty() && nums[q.peekLast()] < nums[i]) { 57 | q.removeLast(); 58 | } 59 | 60 | q.offer(i); 61 | 62 | if (i >= k - 1) { 63 | ret.add(nums[q.peek()]); 64 | } 65 | } 66 | 67 | return ret; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /arrays/Sort_Colors.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Sort Colors 4 | 5 | 6 | 7 | Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue. 8 | 9 | Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. 10 | Notice 11 | 12 | You are not suppose to use the library's sort function for this problem. 13 | You should do it in-place (sort numbers in the original array). 14 | 15 | 16 | 17 | Example 18 | 19 | Given [1, 0, 1, 2], sort it in-place to [0, 1, 1, 2]. 20 | 21 | 22 | Challenge 23 | 24 | A rather straight forward solution is a two-pass algorithm using counting sort. 25 | First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's. 26 | 27 | Could you come up with an one-pass algorithm using only constant space? 28 | 29 | 解: 30 | two pointers 31 | 32 | 使用一个left指针指向0保存的位置,right指针指向2保存的位置。 33 | mid指针从左向右遍历数组,遇到0就存到left位置,并右移left,遇到2就存到right位置,并左移right。 34 | 若mid遇到1或者小于left,则自己向右移动。 35 | 36 | */ 37 | 38 | 39 | class Solution { 40 | /** 41 | * @param nums: A list of integer which is 0, 1 or 2 42 | * @return: nothing 43 | */ 44 | public void sortColors(int[] nums) { 45 | int left, right, mid; 46 | 47 | left = 0; 48 | mid = 0; 49 | right = nums.length - 1; 50 | 51 | while (mid <= right) { 52 | if (nums[mid] == 0) { 53 | swap(nums, left++, mid); 54 | } else if (nums[mid] == 2) { 55 | swap(nums, right--, mid); 56 | } 57 | 58 | if (nums[mid] == 1 || mid < left) { 59 | mid++; 60 | } 61 | } 62 | } 63 | 64 | private void swap(int[] nums, int a, int b) { 65 | int tmp = nums[a]; 66 | nums[a] = nums[b]; 67 | nums[b] = tmp; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /arrays/Sort_Letters_by_Case.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Sort Letters by Case 4 | 5 | Given a string which contains only letters. Sort it by lower case first and upper case second. 6 | 7 | Notice 8 | 9 | It's NOT necessary to keep the original order of lower-case letters and upper case letters. 10 | 11 | Example 12 | For "abAcD", a reasonable answer is "acbAD" 13 | 14 | Challenge 15 | Do it in one-pass and in-place. 16 | 17 | 18 | 解: 19 | 这道题使用quick sort或者quick select的方法来解。 20 | 把所有小写字母挪动到数组前端。 21 | 使用一个store指针指向数组头,然后用指针i遍历数组。 22 | i每遇到一个小写字母就跟store指向的字母交换,并把store向后移动一次,直到遍历完毕。 23 | 24 | */ 25 | 26 | public class Solution { 27 | /** 28 | * *@param chars: The letter array you should sort by Case 29 | * *@return: void 30 | * */ 31 | public void sortLetters(char[] chars) { 32 | int store = 0; 33 | 34 | for (int i = 0; i < chars.length; i++) { 35 | if (isLowerCase(chars[i])) { 36 | char tmp = chars[i]; 37 | chars[i] = chars[store]; 38 | chars[store++] = tmp; 39 | } 40 | } 41 | } 42 | 43 | private boolean isLowerCase(char c) { 44 | return (c >= 'a' && c <= 'z'); 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /arrays/Spiral_Matrix.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Spiral Matrix 4 | 5 | Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order. 6 | 7 | Example 8 | Given the following matrix: 9 | 10 | [ 11 | [ 1, 2, 3 ], 12 | [ 4, 5, 6 ], 13 | [ 7, 8, 9 ] 14 | ] 15 | You should return [1,2,3,6,9,8,7,4,5]. 16 | 17 | 18 | 解: 19 | 从(i,i)开始,上下左右转一圈,全部加进结果数组即可。 20 | 注意处理当只剩一行或者一列的情况。 21 | 22 | */ 23 | 24 | public class Solution { 25 | /** 26 | * @param matrix a matrix of m x n elements 27 | * @return an integer list 28 | */ 29 | public List spiralOrder(int[][] matrix) { 30 | if (matrix == null || matrix.length == 0) { 31 | return new ArrayList(); 32 | } 33 | 34 | List ret = new ArrayList(); 35 | int m = matrix.length; 36 | int n = matrix[0].length; 37 | 38 | for (int i = 0; i <= (Math.min(m, n) - 1) / 2; i++) { 39 | int width = n - 2 * i - 1; 40 | int height = m - 2 * i - 1; 41 | int x = i; 42 | int y = i; 43 | 44 | // go right 45 | for (int j = 0; j < width; j++) { 46 | ret.add(matrix[x][y]); 47 | y += 1; 48 | } 49 | 50 | if (height == 0) { 51 | ret.add(matrix[x][y]); 52 | break; 53 | } 54 | 55 | // go down 56 | for (int j = 0; j < height; j++) { 57 | ret.add(matrix[x][y]); 58 | x += 1; 59 | } 60 | 61 | if (width == 0) { 62 | ret.add(matrix[x][y]); 63 | break; 64 | } 65 | 66 | // go left 67 | for (int j = 0; j < width; j++) { 68 | ret.add(matrix[x][y]); 69 | y -= 1; 70 | } 71 | 72 | // go up 73 | for (int j = 0; j < height; j++) { 74 | ret.add(matrix[x][y]); 75 | x -= 1; 76 | } 77 | } 78 | 79 | return ret; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /arrays/Spiral_Matrix_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Spiral Matrix II 4 | 5 | 6 | Given an integer n, generate a square matrix filled with elements from 1 to n^2 in spiral order. 7 | 8 | Notice 9 | 10 | Example 11 | Given n = 3, 12 | 13 | You should return the following matrix: 14 | 15 | [ 16 | [ 1, 2, 3 ], 17 | [ 8, 9, 4 ], 18 | [ 7, 6, 5 ] 19 | ] 20 | 21 | 22 | 解: 23 | 转圈圈写数字。 24 | 每次可以同时写四个边。 25 | 重点在计算每个边的起点和要写的值。 26 | 27 | */ 28 | 29 | 30 | public class Solution { 31 | /** 32 | * @param n an integer 33 | * @return a square matrix 34 | */ 35 | public int[][] generateMatrix(int n) { 36 | int[][] ret = new int[n][n]; 37 | int val = 1; 38 | 39 | for (int i = 0; i <= (n - 1) / 2; i++) { 40 | int len = n - 2 * i - 1; 41 | int[][] idx = {{i, i, val}, 42 | {i, i + len, val + len}, 43 | {i + len, i + len, val + 2 * len}, 44 | {i + len, i, val + 3 * len}}; 45 | int[][] direct = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; 46 | 47 | for (int j = 0; j < len; j++) { 48 | for (int k = 0; k < 4; k++) { 49 | ret[idx[k][0]][idx[k][1]] = idx[k][2]++; 50 | idx[k][0] += direct[k][0]; 51 | idx[k][1] += direct[k][1]; 52 | } 53 | } 54 | 55 | if (len == 0) { 56 | ret[i][i] = val; 57 | } 58 | 59 | val += 4 * len; 60 | } 61 | 62 | return ret; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /arrays/Surrounded_Regions.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Surrounded Regions 4 | 5 | Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. 6 | 7 | A region is captured by flipping all 'O''s into 'X''s in that surrounded region. 8 | 9 | Example 10 | X X X X 11 | X O O X 12 | X X O X 13 | X O X X 14 | After capture all regions surrounded by 'X', the board should be: 15 | 16 | X X X X 17 | X X X X 18 | X X X X 19 | X O X X 20 | 21 | 22 | 解: 23 | DFS 24 | 不能变成X的位置一定跟四条边相通。 25 | 所以扫描四条边,用DFS把所有与四条边相通的O全部变成#。 26 | 然后再扫描所有点,把#变成O,其他所有变成X。 27 | 28 | */ 29 | 30 | 31 | public class Solution { 32 | /** 33 | * @param board a 2D board containing 'X' and 'O' 34 | * @return void 35 | */ 36 | public void surroundedRegions(char[][] board) { 37 | if (board == null || board.length == 0 || board[0].length == 0) { 38 | return; 39 | } 40 | 41 | int m = board.length; 42 | int n = board[0].length; 43 | 44 | // top 45 | for (int i = 0; i < n; i++) { 46 | spread(board, 0, i); 47 | } 48 | 49 | // bottom 50 | for (int i = 0; i < n; i++) { 51 | spread(board, m - 1, i); 52 | } 53 | 54 | // left 55 | for (int i = 0; i < m; i++) { 56 | spread(board, i, 0); 57 | } 58 | 59 | // right 60 | for (int i = 0; i < m; i++) { 61 | spread(board, i, n - 1); 62 | } 63 | 64 | for (int i = 0; i < m; i++) { 65 | for (int j = 0; j < n; j++) { 66 | if (board[i][j] == '#') { 67 | board[i][j] = 'O'; 68 | } else { 69 | board[i][j] = 'X'; 70 | } 71 | } 72 | } 73 | } 74 | 75 | private void spread(char[][] board, int x, int y) { 76 | int[][] direct = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; 77 | int m = board.length; 78 | int n = board[0].length; 79 | 80 | if (x < 0 || x >= m || y < 0 || y >= n || board[x][y] != 'O') { 81 | return; 82 | } 83 | 84 | board[x][y] = '#'; 85 | 86 | for (int[] d : direct) { 87 | spread(board, x + d[0], y + d[1]); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /arrays/The_Smallest_Difference.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | The Smallest Difference 4 | 5 | 6 | Given two array of integers(the first array is array A, the second array is array B), now we are going to find a element in array A which is A[i], and another element in array B which is B[j], so that the difference between A[i] and B[j] (|A[i] - B[j]|) is as small as possible, return their smallest difference. 7 | 8 | Example 9 | For example, given array A = [3,6,7,4], B = [2,8,9,3], return 0 10 | 11 | Challenge 12 | O(n log n) time 13 | 14 | 15 | 解: 16 | 1.对A数组排序。 17 | 2.遍历B数组,得到数组i,用二分查找在B中找到与i最相近的数,并求差。 18 | 3.对每次求得的差求最小值。 19 | 20 | 21 | */ 22 | 23 | public class Solution { 24 | /** 25 | * @param A, B: Two integer arrays. 26 | * @return: Their smallest difference. 27 | */ 28 | public int smallestDifference(int[] A, int[] B) { 29 | int ret = Integer.MAX_VALUE; 30 | 31 | Arrays.sort(A); 32 | 33 | for (int i : B) { 34 | ret = Math.min(ret, smallestDiff(i, A)); 35 | } 36 | 37 | return ret; 38 | } 39 | 40 | private int smallestDiff(int target, int[] A) { 41 | int left = 0; 42 | int right = A.length - 1; 43 | 44 | if (target < A[0]) { 45 | return A[0] - target; 46 | } else if (target > A[A.length - 1]) { 47 | return target - A[A.length - 1]; 48 | } 49 | 50 | while (left < right - 1) { 51 | int mid = (left + right) / 2; 52 | 53 | if (A[mid] == target) { 54 | return 0; 55 | } else if (A[mid] > target) { 56 | right = mid; 57 | } else { 58 | left = mid; 59 | } 60 | } 61 | 62 | return Math.min(target - A[left], A[right] - target); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /arrays/Triangle.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Triangle 4 | 5 | 6 | Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. 7 | 8 | Notice 9 | Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle. 10 | 11 | 12 | Example 13 | 14 | Given the following triangle: 15 | 16 | [ 17 | [2], 18 | [3,4], 19 | [6,5,7], 20 | [4,1,8,3] 21 | ] 22 | 23 | The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11). 24 | 25 | 26 | 从下向上计算,每次选择当前数的左下和右下中较小的那个与当前数相加,保存在row中。 27 | 比如当前行第i个数应当选择与上一行计算结果也就是row中的第i个数和i+1个数中较小的那个相加,存如row[i]。 28 | 由于当前行第i+1个数并不需要使用row[i],所以不需要使用临时的数组来保存当前行的计算结果。 29 | 30 | */ 31 | 32 | 33 | public class Solution { 34 | /** 35 | * @param triangle: a list of lists of integers. 36 | * @return: An integer, minimum path sum. 37 | */ 38 | public int minimumTotal(int[][] triangle) { 39 | if (triangle == null || triangle.length == 0) { 40 | return 0; 41 | } 42 | 43 | int[] row = new int[triangle.length + 1]; 44 | 45 | for (int i = triangle.length - 1; i >= 0; i--) { 46 | for (int j = 0; j < triangle[i].length; j++) { 47 | row[j] = Math.min(row[j], row[j + 1]) + triangle[i][j]; 48 | } 49 | } 50 | 51 | return row[0]; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /arrays/Triangle_Count.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Triangle Count 4 | 5 | 6 | Given an array of integers, how many three numbers can be found in the array, so that we can build an triangle whose three edges length is the three numbers that we find? 7 | 8 | Example 9 | Given array S = [3,4,6,7], return 3. They are: 10 | 11 | [3,4,6] 12 | [3,6,7] 13 | [4,6,7] 14 | Given array S = [4,4,4,4], return 4. They are: 15 | 16 | [4(1),4(2),4(3)] 17 | [4(1),4(2),4(4)] 18 | [4(1),4(3),4(4)] 19 | [4(2),4(3),4(4)] 20 | 21 | 22 | 解: 23 | 1. 对数组从小到大排序。 24 | 2. 从后向前遍历数组,每次获得数字a=S[i]。 25 | 3. 用双指针指向a之前的数子,left=0.right=i-1。得到b=S[left],c=S[right]。 26 | 4. 如果b+c>a,则a,b,c可以组成三角形,并且left到right之间的所有数都可以作为b,一共right-left组,故ret+=right-left。之后应当左移c,也就是right--。 27 | 5. 如果b+c<=a,由于已经从小到大排序,故left应当右移。 28 | 6. 计算直到left==right,重复2,继续遍历。 29 | 30 | */ 31 | 32 | public class Solution { 33 | /** 34 | * @param S: A list of integers 35 | * @return: An integer 36 | */ 37 | public int triangleCount(int S[]) { 38 | if (S == null || S.length ==0) { 39 | return 0; 40 | } 41 | 42 | int ret = 0; 43 | Arrays.sort(S); 44 | 45 | for (int i = S.length - 1; i >= 0; i--) { 46 | int a = S[i]; 47 | int left = 0; 48 | int right = i - 1; 49 | 50 | while (left < right) { 51 | int b = S[left]; 52 | int c = S[right]; 53 | 54 | if (b + c > a) { 55 | ret += right - left; 56 | right--; 57 | } else { 58 | left++; 59 | } 60 | } 61 | } 62 | 63 | return ret; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /arrays/Two_Sum_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Two Sum II (leetcode version) 4 | 5 | Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number. 6 | The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based. 7 | You may assume that each input would have exactly one solution. 8 | 9 | Example: 10 | 11 | Input: numbers={2, 7, 11, 15}, target=9 12 | Output: index1=1, index2=2 13 | 14 | 15 | 解: 16 | 用两个指针分别指向数组的头和尾,算出其和。 17 | 由于数组是有序的,所以如果和大于target,就左移尾指针;如果和小于target,就右移头指针。 18 | 直到找到target。 19 | 20 | */ 21 | 22 | 23 | public class Solution { 24 | public int[] twoSum(int[] numbers, int target) { 25 | int[] ret = new int[2]; 26 | ret[0] = -1; 27 | ret[1] = -1; 28 | 29 | if (numbers == null || numbers.length == 0) { 30 | return ret; 31 | } 32 | 33 | int left, right; 34 | left = 0; 35 | right = numbers.length - 1; 36 | 37 | while (left < right) { 38 | int tmp = numbers[left] + numbers[right]; 39 | if (tmp == target) { 40 | ret[0] = ++left; 41 | ret[1] = ++right; 42 | break; 43 | } else if (tmp > target) { 44 | right--; 45 | } else { 46 | left++; 47 | } 48 | } 49 | 50 | return ret; 51 | } 52 | } -------------------------------------------------------------------------------- /arrays/Unique_Paths.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Unique Paths 4 | 5 | 6 | A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). 7 | 8 | The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). 9 | 10 | How many possible unique paths are there? 11 | Notice 12 | 13 | m and n will be at most 100. 14 | 15 | 16 | 解: 17 | dynamic programming 18 | 与climbing stairs类似。 19 | 20 | 递推公式: 21 | dp[i][j]表示矩阵坐标(i, j)有多少条unique paths可以到达。每个坐标可以从上方或者左边到达。所以每个坐标的unique paths都为上方坐标和左边坐标的unique paths之和。 22 | 由于从上方或者左边到达一个坐标时,并不会增加新的可行路径,所以直接求和即可。 23 | dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 24 | 25 | 初始条件: 26 | 由于每个点都需要上方和左边方坐标的计算结果,所以需要保证最上方一行和最左边一列的坐标计算值被初始化。 27 | 最上方和最左边的任意一个坐标都只可能有一种方式到达,即从左上角的点一路向右,或者一路向下。故全部初始化为1。 28 | 这里为了书写方便,将整个矩阵初始化为1。由于除了最上方一行和最左边一列以外的所有值都会被覆盖,所以不影响计算结果。 29 | 30 | 最后取右下角坐标的计算结果。 31 | 32 | */ 33 | 34 | public class Solution { 35 | /** 36 | * @param n, m: positive integer (1 <= n ,m <= 100) 37 | * @return an integer 38 | */ 39 | public int uniquePaths(int m, int n) { 40 | int[][] dp = new int[m][n]; 41 | 42 | for (int[] row : dp) { 43 | Arrays.fill(row, 1); 44 | } 45 | 46 | for (int i = 1; i < m; i++) { 47 | for (int j = 1; j < n; j++) { 48 | dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; 49 | } 50 | } 51 | 52 | return dp[m - 1][n - 1]; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /arrays/Unique_Paths_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Unique Paths II 4 | 5 | 6 | Follow up for "Unique Paths": 7 | 8 | Now consider if some obstacles are added to the grids. How many unique paths would there be? 9 | 10 | An obstacle and empty space is marked as 1 and 0 respectively in the grid. 11 | 12 | Notice 13 | m and n will be at most 100. 14 | 15 | 16 | Example 17 | 18 | For example, 19 | 20 | There is one obstacle in the middle of a 3x3 grid as illustrated below. 21 | 22 | [ 23 | [0,0,0], 24 | [0,1,0], 25 | [0,0,0] 26 | ] 27 | 28 | The total number of unique paths is 2. 29 | 30 | 31 | 32 | 解: 33 | 该题解法与Unique Path一样,只是多了一个对障碍物的判断。 34 | 对于任何一个坐标来说,只要该坐标上有障碍物,那么该坐标的计算结果一定为0。 35 | 其他分析与Unique Path一致。 36 | 37 | */ 38 | 39 | 40 | 41 | public class Solution { 42 | /** 43 | * @param obstacleGrid: A list of lists of integers 44 | * @return: An integer 45 | */ 46 | public int uniquePathsWithObstacles(int[][] oGrid) { 47 | if (oGrid == null || oGrid.length == 0) { 48 | return 0; 49 | } 50 | 51 | int m = oGrid.length; 52 | int n = oGrid[0].length; 53 | int[][] dp = new int[m][n]; 54 | 55 | // initialize 56 | dp[0][0] = oGrid[0][0] == 1 ? 0 : 1; 57 | for (int i = 1; i < m; i++) { 58 | dp[i][0] = oGrid[i][0] == 1 ? 0 : dp[i - 1][0]; 59 | } 60 | 61 | for (int i = 1; i < n; i++) { 62 | dp[0][i] = oGrid[0][i] == 1 ? 0 : dp[0][i - 1]; 63 | } 64 | 65 | // calculate 66 | for (int i = 1; i < m; i++) { 67 | for (int j = 1; j < n; j++) { 68 | dp[i][j] = oGrid[i][j] == 1 ? 0 : dp[i - 1][j] + dp[i][j - 1]; 69 | } 70 | } 71 | 72 | return dp[m - 1][n - 1]; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /arrays/Wiggle_Sort.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Wiggle Sort 4 | 5 | Given an unsorted array nums, reorder it in-place such that 6 | 7 | nums[0] <= nums[1] >= nums[2] <= nums[3].... 8 | Notice 9 | 10 | Please complete the problem in-place. 11 | 12 | Example 13 | Given nums = [3, 5, 2, 1, 6, 4], one possible answer is [1, 6, 2, 5, 3, 4]. 14 | 15 | 16 | 解: 17 | 方法一: 18 | 先排序,然后从nums[3]开始,每个数字与它前面的数字交换即可。 19 | 20 | 这样做的原理是: 21 | 对于递增序列中的任意三个连续数,例如: 22 | ...a,1,2,3,b,c... 23 | 将2和1交换之后就可以得到: 24 | ...a,2,1,3,b,c... 25 | 这三个数一定大于其前面的任何数字,故满足2大于a且大于1。 26 | 计算完成后i跳到b,进行下一轮,计算序列3,b,c。 27 | 28 | 时间O(nlog(n)) 29 | 30 | */ 31 | 32 | public class Solution { 33 | /** 34 | * @param nums a list of integer 35 | * @return void 36 | */ 37 | public void wiggleSort(int[] nums) { 38 | if (nums == null || nums.length < 2) { 39 | return; 40 | } 41 | 42 | int left, right, len; 43 | 44 | Arrays.sort(nums); 45 | 46 | for (int i = 2; i < nums.length; i += 2) { 47 | int tmp = nums[i]; 48 | nums[i] = nums[i - 1]; 49 | nums[i - 1] = tmp; 50 | } 51 | } 52 | } 53 | 54 | 55 | /* 56 | 57 | 方法二: 58 | 对于任意一个数字,其实只需要考虑其与左边数字的关系即可。 59 | 1.对于i为奇数,应满足nums[i]>=nums[i-1]。 60 | 如果nums[i]nums[i]<=nums[i-2] 62 | 2.对于i为偶数,应满足nums[i]<=nums[i-1] 63 | 如果nums[i]>nums[i-1],直接交换。 64 | 由于nums[i]>nums[i-1]>=nums[i-2],故交换后满足条件:nums[i-1]=nums[i-2] 65 | 66 | 时间O(n) 67 | 68 | */ 69 | 70 | public class Solution { 71 | /** 72 | * @param nums a list of integer 73 | * @return void 74 | */ 75 | public void wiggleSort(int[] nums) { 76 | if (nums == null || nums.length < 2) { 77 | return; 78 | } 79 | 80 | for (int i = 1; i < nums.length; i++) { 81 | if ((i % 2 == 0 && nums[i] > nums[i - 1]) || 82 | (i % 2 == 1 && nums[i] < nums[i - 1])) { 83 | int tmp = nums[i]; 84 | nums[i] = nums[i - 1]; 85 | nums[i - 1] = tmp; 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /arrays/Wood_Cut.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Wood Cut 4 | 5 | Given n pieces of wood with length L[i] (integer array). Cut them into small pieces to guarantee you could have equal or more than k pieces with the same length. What is the longest length you can get from the n pieces of wood? Given L & k, return the maximum length of the small pieces. 6 | 7 | Notice 8 | 9 | You couldn't cut wood into float length. 10 | 11 | If you couldn't get >= k pieces, return 0. 12 | 13 | Example 14 | For L=[232, 124, 456], k=7, return 114. 15 | 16 | Challenge 17 | O(n log Len), where Len is the longest length of the wood. 18 | 19 | 20 | 21 | 解: 22 | 二分法 23 | 对从1到最长木头的长度进行二分搜索,找出满足条件的最大长度。 24 | 对于已知长度len,用每个木头长度除以len的结果相加即可得到能切多少段。 25 | 如果能切多于或者等于k段,则left右移到len,否则right左移到len。 26 | 27 | 终止条件是left小于right-1。也就是说退出循环时left==right-1。 28 | 由于最终要求的是某一个长度大于或者等于k,故只要保证退出循环时left<=len= k) { 53 | return right; 54 | } 55 | 56 | while (left < right - 1) { 57 | int mid = (int)(((long)left + (long)right) / 2); 58 | 59 | if (cut(L, mid) >= k) { 60 | left = mid; 61 | } else { 62 | right = mid; 63 | } 64 | } 65 | 66 | return left; 67 | } 68 | 69 | private long cut(int[] L, int len) { 70 | long cnt = 0; 71 | 72 | for (int i : L) { 73 | cnt += i / len; 74 | } 75 | 76 | return cnt; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /graph/Graph_Valid_Tree.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Graph Valid Tree 4 | 5 | Given a directed graph, design an algorithm to find out whether there is a route between two nodes. 6 | 7 | Example 8 | Given graph: 9 | 10 | A----->B----->C 11 | \ | 12 | \ | 13 | \ | 14 | \ v 15 | ->D----->E 16 | for s = B and t = E, return true 17 | 18 | for s = D and t = C, return false 19 | 20 | 21 | 解: 22 | BFS 23 | 24 | Tree有两个特性: 25 | 1.边的数量为点的数量减一; 26 | 2.不能出现loop。也就是说在满足上一个特性的前提下,以任意一点作为根,应当可以遍历所有点。 27 | 28 | 用HashMap保存每个点及其neigobors。 29 | 用0作为根节点,BFS遍历整个图。 30 | 用visited保存访问过的节点。 31 | 如果结束时visited的不等于n,说明有点没有访问到,也就是说一定存在loop,应当返回false。 32 | 否则返回true。 33 | 34 | */ 35 | 36 | 37 | public class Solution { 38 | /** 39 | * @param n an integer 40 | * @param edges a list of undirected edges 41 | * @return true if it's a valid tree, or false 42 | */ 43 | public boolean validTree(int n, int[][] edges) { 44 | Map> map = new HashMap>(); 45 | Queue queue = new LinkedList(); 46 | Set visited = new HashSet(); 47 | 48 | if (n == 0 || edges.length != n - 1) { 49 | return false; 50 | } 51 | 52 | for (int i = 0; i < n; i++) { 53 | map.put(i, new ArrayList()); 54 | } 55 | 56 | for (int i = 0; i < edges.length; i++) { 57 | int a = edges[i][0]; 58 | int b = edges[i][1]; 59 | 60 | map.get(a).add(b); 61 | map.get(b).add(a); 62 | } 63 | 64 | queue.offer(0); 65 | visited.add(0); 66 | 67 | while (!queue.isEmpty()) { 68 | int cur = queue.poll(); 69 | 70 | for (Integer next : map.get(cur)) { 71 | if (visited.contains(next)) { 72 | continue; 73 | } 74 | 75 | queue.offer(next); 76 | visited.add(next); 77 | } 78 | } 79 | 80 | return (visited.size() == n); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /graph/Route_Between_Two_Nodes_in_Graph.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Route Between Two Nodes in Graph 4 | 5 | Given a directed graph, design an algorithm to find out whether there is a route between two nodes. 6 | 7 | Example 8 | Given graph: 9 | 10 | A----->B----->C 11 | \ | 12 | \ | 13 | \ | 14 | \ v 15 | ->D----->E 16 | for s = B and t = E, return true 17 | 18 | for s = D and t = C, return false 19 | 20 | 21 | 解: 22 | BFS 23 | 用BFS搜索s开始的每个节点的neighbors,把没有处理过的neighbor加入队列。 24 | 如果从队中取出的节点为t,返回true。 25 | 队列为空时返回false。 26 | 27 | */ 28 | 29 | 30 | /** 31 | * Definition for Directed graph. 32 | * class DirectedGraphNode { 33 | * int label; 34 | * ArrayList neighbors; 35 | * DirectedGraphNode(int x) { 36 | * label = x; 37 | * neighbors = new ArrayList(); 38 | * } 39 | * }; 40 | */ 41 | public class Solution { 42 | /** 43 | * @param graph: A list of Directed graph node 44 | * @param s: the starting Directed graph node 45 | * @param t: the terminal Directed graph node 46 | * @return: a boolean value 47 | */ 48 | public boolean hasRoute(ArrayList graph, 49 | DirectedGraphNode s, DirectedGraphNode t) { 50 | Queue queue = new LinkedList(); 51 | Set used = new HashSet(); 52 | 53 | queue.offer(s); 54 | used.add(s); 55 | 56 | while(!queue.isEmpty()) { 57 | DirectedGraphNode node = queue.poll(); 58 | if (node == t) { 59 | return true; 60 | } 61 | 62 | for (DirectedGraphNode neighbor : node.neighbors) { 63 | if (!used.contains(neighbor)) { 64 | queue.offer(neighbor); 65 | used.add(neighbor); 66 | } 67 | } 68 | } 69 | 70 | return false; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /linked list/Add_Two_Numbers_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Add Two Numbers II 4 | 5 | You have two numbers represented by a linked list, where each node contains a single digit. The digits are stored in forward order, such that the 1's digit is at the head of the list. Write a function that adds the two numbers and returns the sum as a linked list. 6 | 7 | Example 8 | Given 6->1->7 + 2->9->5. That is, 617 + 295. 9 | 10 | Return 9->1->2. That is, 912. 11 | 12 | 13 | 解: 14 | 先把输入的两个list翻过来,然后求和并存入新的list。 15 | 16 | */ 17 | 18 | /** 19 | * Definition for singly-linked list. 20 | * public class ListNode { 21 | * int val; 22 | * ListNode next; 23 | * ListNode(int x) { 24 | * val = x; 25 | * next = null; 26 | * } 27 | * } 28 | */ 29 | public class Solution { 30 | /** 31 | * @param l1: the first list 32 | * @param l2: the second list 33 | * @return: the sum list of l1 and l2 34 | */ 35 | public ListNode addLists2(ListNode l1, ListNode l2) { 36 | ListNode dummy = new ListNode(0); 37 | int carry = 0; 38 | 39 | l1 = reverse(l1); 40 | l2 = reverse(l2); 41 | 42 | while (l1 != null || l2 != null || carry != 0) { 43 | ListNode node = new ListNode(0); 44 | int tmp = carry; 45 | 46 | if (l1 != null) { 47 | tmp += l1.val; 48 | l1 = l1.next; 49 | } 50 | if (l2 != null) { 51 | tmp += l2.val; 52 | l2 = l2.next; 53 | } 54 | 55 | if (tmp >= 10) { 56 | tmp -= 10; 57 | carry = 1; 58 | } else { 59 | carry = 0; 60 | } 61 | 62 | node.val = tmp; 63 | node.next = dummy.next; 64 | dummy.next = node; 65 | } 66 | 67 | return dummy.next; 68 | } 69 | 70 | private ListNode reverse(ListNode l) { 71 | ListNode dummy = new ListNode(0); 72 | 73 | while (l != null) { 74 | ListNode tmp = l.next; 75 | l.next = dummy.next; 76 | dummy.next = l; 77 | l = tmp; 78 | } 79 | 80 | return dummy.next; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /linked list/Palindrome_Linked_List.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Palindrome Linked List 4 | 5 | 6 | Implement a function to check if a linked list is a palindrome. 7 | 8 | Example 9 | Given 1->2->1, return true 10 | 11 | Challenge 12 | Could you do it in O(n) time and O(1) space? 13 | 14 | 解: 15 | 把list的后半段翻过来,然后跟前半段比较判断是否时回文。 16 | 可以用slow和fast指针的方法找到list的中点。 17 | 不需要判断list长度奇偶数,只需要判断前后两半长度相同的部分,奇数情况下多出来的一个一定时中间那个节点,可以忽略。 18 | 19 | */ 20 | 21 | /** 22 | * Definition for singly-linked list. 23 | * public class ListNode { 24 | * int val; 25 | * ListNode next; 26 | * ListNode(int x) { val = x; } 27 | * } 28 | */ 29 | public class Solution { 30 | /** 31 | * @param head a ListNode 32 | * @return a boolean 33 | */ 34 | public boolean isPalindrome(ListNode head) { 35 | ListNode fast, slow, tail; 36 | 37 | if (head == null || head.next == null) { 38 | return true; 39 | } 40 | 41 | fast = head; 42 | slow = head; 43 | 44 | while (fast.next != null && fast.next.next != null) { 45 | slow = slow.next; 46 | fast = fast.next.next; 47 | } 48 | 49 | tail = slow.next; 50 | slow.next = null; 51 | tail = reverse(tail); 52 | 53 | while (head != null && tail != null) { 54 | if (head.val != tail.val) { 55 | return false; 56 | } 57 | head = head.next; 58 | tail = tail.next; 59 | } 60 | 61 | return true; 62 | } 63 | 64 | private ListNode reverse(ListNode l) { 65 | ListNode dummy = new ListNode(0); 66 | 67 | while (l != null) { 68 | ListNode tmp = l.next; 69 | l.next = dummy.next; 70 | dummy.next = l; 71 | l = tmp; 72 | } 73 | 74 | return dummy.next; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /linked list/Remove_Duplicates_from_Sorted_List.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Remove Duplicates from Sorted List 4 | 5 | Given a sorted linked list, delete all duplicates such that each element appear only once. 6 | 7 | Example 8 | Given 1->1->2, return 1->2. 9 | Given 1->1->2->3->3, return 1->2->3. 10 | 11 | 解: 12 | 每次对比下一个节点的值和当前节点的值是否相等。 13 | 若相等,移除下一个节点。 14 | 15 | */ 16 | 17 | 18 | /** 19 | * Definition for ListNode 20 | * public class ListNode { 21 | * int val; 22 | * ListNode next; 23 | * ListNode(int x) { 24 | * val = x; 25 | * next = null; 26 | * } 27 | * } 28 | */ 29 | public class Solution { 30 | /** 31 | * @param ListNode head is the head of the linked list 32 | * @return: ListNode head of linked list 33 | */ 34 | public static ListNode deleteDuplicates(ListNode head) { 35 | if (head == null) { 36 | return head; 37 | } 38 | 39 | ListNode iter = head; 40 | while (iter.next != null) { 41 | if (iter.next.val == iter.val) { 42 | iter.next = iter.next.next; 43 | } else { 44 | iter = iter.next; 45 | } 46 | } 47 | 48 | return head; 49 | } 50 | } -------------------------------------------------------------------------------- /linked list/Remove_Duplicates_from_Sorted_List_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Remove Duplicates from Sorted List II 4 | 5 | Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. 6 | 7 | Example 8 | 9 | Given 1->2->3->3->4->4->5, return 1->2->5. 10 | Given 1->1->1->2->3, return 2->3. 11 | 12 | 13 | 14 | 解: 15 | 如何判断重复节点? 16 | 使用一个临时指针指向当前节点,然后从该结点开始向后遍历,若下一个节点的值与当前节点的值相同,则继续向后移动。 17 | 直到下一个节点的值与当前不同。然后判断临时指针是否移动过。 18 | 若移动过,表示从当前节点到临时指针指向的节点为止的所有节点重复,应当丢弃。 19 | 若没有移动过,表示从前节点应当加入新的linked list。 20 | 21 | 22 | */ 23 | 24 | /** 25 | * Definition for ListNode 26 | * public class ListNode { 27 | * int val; 28 | * ListNode next; 29 | * ListNode(int x) { 30 | * val = x; 31 | * next = null; 32 | * } 33 | * } 34 | */ 35 | public class Solution { 36 | /** 37 | * @param ListNode head is the head of the linked list 38 | * @return: ListNode head of the linked list 39 | */ 40 | public static ListNode deleteDuplicates(ListNode head) { 41 | ListNode dummy = new ListNode(0); 42 | ListNode store = dummy; 43 | 44 | while (head != null) { 45 | ListNode iter = head; 46 | while (iter.next != null && iter.next.val == iter.val) { 47 | iter = iter.next; 48 | } 49 | if (iter == head) { 50 | store.next = head; 51 | store = store.next; 52 | } 53 | 54 | head = iter.next; 55 | } 56 | 57 | store.next = null; 58 | return dummy.next; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /linked list/Reverse_Linked_List_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Reverse Linked List II 4 | 5 | Reverse a linked list from position m to n. 6 | 7 | Notice 8 | 9 | Given m, n satisfy the following condition: 1 ≤ m ≤ n ≤ length of list. 10 | 11 | Example 12 | Given 1->2->3->4->5->NULL, m = 2 and n = 4, return 1->4->3->2->5->NULL. 13 | 14 | Challenge 15 | Reverse it in-place and in one-pass 16 | 17 | 18 | 解: 19 | 用一个指针指向第m个结点之前的结点p0,然后把第n个结点以及其之前的结点挪动到p0之后。 20 | 用一个dummy结点指向head,然后令遍历指针p指向dummy。 21 | 用idx表示p的下一个结点的序号,则idx初始值为1,因为p初始指向dummy。当idx等于m时,令p0等与p。 22 | 挪动idx小于等于n的所有结点。 23 | 24 | */ 25 | 26 | /** 27 | * Definition for ListNode 28 | * public class ListNode { 29 | * int val; 30 | * ListNode next; 31 | * ListNode(int x) { 32 | * val = x; 33 | * next = null; 34 | * } 35 | * } 36 | */ 37 | public class Solution { 38 | /** 39 | * @param ListNode head is the head of the linked list 40 | * @oaram m and n 41 | * @return: The head of the reversed ListNode 42 | */ 43 | public ListNode reverseBetween(ListNode head, int m , int n) { 44 | ListNode p0, p, dummy; 45 | int idx = 1; // idx is the index of the p->next 46 | 47 | dummy = new ListNode(0); 48 | dummy.next = head; 49 | p = p0 = dummy; 50 | 51 | while (p.next != null) { 52 | if (idx == m) { 53 | p0 = p; 54 | p = p.next; 55 | } else if (idx > m && idx <= n) { 56 | ListNode node = p.next; 57 | p.next = node.next; 58 | node.next = p0.next; 59 | p0.next = node; 60 | } else { 61 | p = p.next; 62 | } 63 | idx++; 64 | } 65 | 66 | return dummy.next; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /linked list/Rotate_List.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Rotate List 4 | 5 | 6 | 7 | Given a list, rotate the list to the right by k places, where k is non-negative. 8 | 9 | 10 | Example 11 | 12 | Given 1->2->3->4->5 and k = 2, return 4->5->1->2->3. 13 | 14 | 15 | 解: 16 | 首先计算链表长度,并找出最后一个节点。 17 | 根据长度计算出需要把末尾多少个节点移动到链表头,并切断需要移动的部分,移动到表头。 18 | 19 | */ 20 | 21 | 22 | /** 23 | * Definition for singly-linked list. 24 | * public class ListNode { 25 | * int val; 26 | * ListNode next; 27 | * ListNode(int x) { 28 | * val = x; 29 | * next = null; 30 | * } 31 | * } 32 | */ 33 | public class Solution { 34 | /** 35 | * @param head: the List 36 | * @param k: rotate to the right k places 37 | * @return: the list after rotation 38 | */ 39 | public ListNode rotateRight(ListNode head, int k) { 40 | ListNode next, tail; 41 | int len = 1; 42 | 43 | if (head == null) { 44 | return null; 45 | } 46 | 47 | next = head; 48 | while (next.next != null) { 49 | len++; 50 | next = next.next; 51 | } 52 | tail = next; 53 | 54 | len = len - (k % len) - 1; 55 | next = head; 56 | while (len > 0) { 57 | next = next.next; 58 | len--; 59 | } 60 | 61 | tail.next = head; 62 | tail = next; 63 | head = tail.next; 64 | tail.next = null; 65 | 66 | return head; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /stack/Implement_Queue_by_Two_Stacks.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Implement Queue by Two Stacks 4 | 5 | As the title described, you should only use two stacks to implement a queue's actions. 6 | 7 | The queue should support push(element), pop() and top() where pop is pop the first(a.k.a front) element in the queue. 8 | 9 | Both pop and top methods should return the value of first element. 10 | 11 | Example 12 | push(1) 13 | pop() // return 1 14 | push(2) 15 | push(3) 16 | top() // return 2 17 | pop() // return 2 18 | 19 | Challenge 20 | implement it by two stacks, do not use any other data structure and push, pop and top should be O(1) by AVERAGE. 21 | 22 | 23 | 解: 24 | stack in负责存,stack out负责取。 25 | push直接存入in。 26 | pop和top的时候如果out不为空,直接对out进行pop和peek。 27 | 如果out为空,则将in中的元素pop出来push进out中,这样最早push进入in的元素将在out的顶端。 28 | 29 | */ 30 | 31 | 32 | public class MyQueue { 33 | private Stack in; 34 | private Stack out; 35 | 36 | public MyQueue() { 37 | in = new Stack(); 38 | out = new Stack(); 39 | } 40 | 41 | public void push(int element) { 42 | in.push(element); 43 | } 44 | 45 | public int pop() { 46 | if (out.isEmpty()) { 47 | pour(); 48 | } 49 | 50 | return out.pop(); 51 | } 52 | 53 | public int top() { 54 | if (out.isEmpty()) { 55 | pour(); 56 | } 57 | 58 | return out.peek(); 59 | } 60 | 61 | private void pour() { 62 | while (!in.isEmpty()) { 63 | out.push(in.pop()); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /stack/Min_Stack.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Min Stack 4 | 5 | Implement a stack with min() function, which will return the smallest number in the stack. 6 | 7 | It should support push, pop and min operation all in O(1) cost. 8 | 9 | 10 | Notice 11 | 12 | min operation will never be called if there is no number in the stack. 13 | 14 | 15 | 解: 16 | 分析需要哪些数据: 17 | 1. 需要使用一个stack保存原始数据的存入顺序; 18 | 2. 需要使用一个stack保存每一个数据插入时的当前最小值。 19 | 20 | 这道题容易走入需要保存数据排序信息的误区。 21 | 如果保存排序信息,那么最快的方法是使用一个heap,插入和取出的时间复杂度都将增加到O(log(n))。 22 | 23 | 24 | 当每个数据插入时,比较这个数和之前的最小值,即最小值stack顶端数据的大小,将小的那个再次插入最小值stack。 25 | 比如输入数据为: 26 | 8,6,3,7,1,2 27 | 那么最小值stack为: 28 | 8,6,3,3,1,1 29 | 30 | 31 | 可以分析每个值按顺序被取出后最小值序列依然保持着正确的当前最小值。 32 | 33 | */ 34 | 35 | 36 | public class MinStack { 37 | Stack stack; 38 | Stack minSt; 39 | 40 | public MinStack() { 41 | stack = new Stack(); 42 | minSt = new Stack(); 43 | } 44 | 45 | public void push(int number) { 46 | stack.push(number); 47 | 48 | if (minSt.size() == 0 || number < minSt.peek()) { 49 | minSt.push(number); 50 | } else { 51 | minSt.push(minSt.peek()); 52 | } 53 | } 54 | 55 | public int pop() { 56 | minSt.pop(); 57 | return stack.pop(); 58 | } 59 | 60 | public int min() { 61 | return minSt.peek(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /string/Anagrams.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Anagrams 4 | 5 | Given an array of strings, return all groups of strings that are anagrams. 6 | 7 | Notice 8 | 9 | All inputs will be in lower-case 10 | 11 | Example 12 | Given ["lint", "intl", "inlt", "code"], return ["lint", "inlt", "intl"]. 13 | 14 | Given ["ab", "ba", "cd", "dc", "e"], return ["ab", "ba", "cd", "dc"]. 15 | 16 | Challenge 17 | What is Anagram? 18 | - Two strings are anagram if they can be the same after change the order of characters. 19 | 20 | 21 | 解: 22 | 这道题的关键是用某一种方法找出anagrams的hash key,然后把拥有相同key的单词放进一个列表。 23 | 最后如果某一个列表的大小大约1,那么将这个列表里的所有单词都放进结果列表。 24 | 25 | 最简单的方法是把单词里面的字母排序,变成新的单词后作为hash key。 26 | 这样拥有相同字母的单词就会被放进同一个列表。 27 | 28 | */ 29 | 30 | 31 | public class Solution { 32 | /** 33 | * @param strs: A list of strings 34 | * @return: A list of strings 35 | */ 36 | public List anagrams(String[] strs) { 37 | Map> map = new HashMap>(); 38 | List ret = new ArrayList(); 39 | 40 | for (String s : strs) { 41 | char[] c = s.toCharArray(); 42 | String tmp; 43 | 44 | Arrays.sort(c); 45 | tmp = String.valueOf(c); 46 | 47 | if (!map.containsKey(tmp)) { 48 | map.put(tmp, new ArrayList()); 49 | } 50 | 51 | map.get(tmp).add(s); 52 | } 53 | 54 | for (List list : map.values()) { 55 | if (list.size() > 1) { 56 | ret.addAll(list); 57 | } 58 | } 59 | 60 | return ret; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /string/Edit_Distance_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Edit Distance II 4 | 5 | Given two strings S and T, determine if they are both one edit distance apart. 6 | 7 | Example 8 | Given s = "aDb", t = "adb" 9 | return true 10 | 11 | 12 | 解: 13 | 从头逐字符比较两个字符串,统计修改数量为change。 14 | 1.如果s[i]==t[j],那么i++,j++,继续比较。 15 | 2.如果s[i]==t[j],那么有三种情况: 16 | 1)s和t剩余的字符数量相等,则修改当前字符使当前两个字符相等,并且change++。 17 | 2)s剩余字符比t多,那么s中删除一个字符,即i++而j不变,并且change++。 18 | 3)t剩余字符比s多,那么t中删除一个字符,即j++而i不变,并且change++。 19 | 3.如果change大于1,直接返回false。 20 | 4.比较结束后,如果任何一个s或t中的字符没有用完,则应当全部删除,并把操作数加入change中。 21 | 22 | 最后如果总操作数为1则返回true,否则返回false。 23 | 24 | */ 25 | 26 | public class Solution { 27 | /* 28 | * @param s: a string 29 | * @param t: a string 30 | * @return: true if they are both one edit distance apart or false 31 | */ 32 | public boolean isOneEditDistance(String s, String t) { 33 | if (s == null || t == null) { 34 | return false; 35 | } 36 | 37 | int change = 0; 38 | int lens = s.length(); 39 | int lent = t.length(); 40 | char[] sc = s.toCharArray(); 41 | char[] tc = t.toCharArray(); 42 | int i = 0; 43 | int j = 0; 44 | 45 | while (i < lens && j < lent) { 46 | if (sc[i] != tc[j]) { 47 | change++; 48 | if (lens - i == lent - j) { 49 | i++; 50 | j++; 51 | } else if (lens - i > lent - j) { 52 | i++; 53 | } else if (lens - i < lent - j) { 54 | j++; 55 | } 56 | } else { 57 | i++; 58 | j++; 59 | } 60 | 61 | if (change > 1) { 62 | return false; 63 | } 64 | } 65 | 66 | return change + Math.max(lens - i, lent - j) == 1; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /string/Evaluate_Reverse_Polish_Notation.java: -------------------------------------------------------------------------------- 1 | /* 2 | Evaluate Reverse Polish Notation 3 | 4 | Evaluate the value of an arithmetic expression in Reverse Polish Notation. 5 | Valid operators are +, -, *, /. Each operand may be an integer or another expression. 6 | 7 | Example: 8 | ["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9 9 | ["4", "13", "5", "/", "+"] -> (4 + (13 / 5)) -> 6 10 | 11 | 解: 12 | 遍历整个数组,当遇到数字时,放入栈中。 13 | 当遇到操作符号时,从栈中取出两个数字进行运算,再把结果放入栈中。 14 | 15 | */ 16 | 17 | public class Solution { 18 | /** 19 | * @param tokens The Reverse Polish Notation 20 | * @return the value 21 | */ 22 | public int evalRPN(String[] tokens) { 23 | String op = "+-*/"; 24 | Stack stack = new Stack(); 25 | 26 | for (String s : tokens) { 27 | if (op.contains(s)) { 28 | int b = stack.pop(); 29 | int a = stack.pop(); 30 | switch (s.charAt(0)) { 31 | case '+': 32 | stack.push(a + b); 33 | break; 34 | case '-': 35 | stack.push(a - b); 36 | break; 37 | case '*': 38 | stack.push(a * b); 39 | break; 40 | case '/': 41 | stack.push(a / b); 42 | } 43 | } else { 44 | stack.push(Integer.valueOf(s)); 45 | } 46 | } 47 | 48 | return stack.pop(); 49 | } 50 | } -------------------------------------------------------------------------------- /string/Generate_Parentheses.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Generate Parentheses 4 | 5 | 6 | Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. 7 | 8 | Example 9 | Given n = 3, a solution set is: 10 | 11 | "((()))", "(()())", "(())()", "()(())", "()()()" 12 | 13 | 14 | 解: 15 | DFS 16 | 每一个位置可以放置"("或者")"。 17 | 每放置一个"(",后面就可以放置")"。 18 | 19 | 故设置一个")"计数器right, 20 | 1.每当放置一个"(",n减一,right加一。 21 | 2.每放置一个")",n不变,right减一。 22 | 23 | 计算直到n和right都为0,则得到了一个有效解。 24 | 25 | */ 26 | 27 | 28 | public class Solution { 29 | /** 30 | * @param n n pairs 31 | * @return All combinations of well-formed parentheses 32 | */ 33 | public ArrayList generateParenthesis(int n) { 34 | ArrayList ret = new ArrayList(); 35 | 36 | helper(n, 0, "", ret); 37 | return ret; 38 | } 39 | 40 | private void helper(int n, int right, String path, ArrayList ret) { 41 | if (n == 0 && right == 0) { 42 | if (path.length() > 0) { 43 | ret.add(path); 44 | } 45 | return; 46 | } 47 | 48 | if (n > 0) { 49 | helper(n - 1, right + 1, path + "(", ret); 50 | } 51 | 52 | if (right > 0) { 53 | helper(n, right - 1, path + ")", ret); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /string/Length_Of_Last_Word.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Length of last word 4 | 5 | Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the length of last word in the string. 6 | If the last word does not exist, return 0. 7 | 8 | Notice 9 | A word is defined as a character sequence consists of non-space characters only. 10 | 11 | 12 | 解: 13 | 先用trim()去掉字符串两端的空格,然后从后向前找,每遇到一个非空格的字符便给计数器加一,直到遇到一个空格或者遍历整个字符串。 14 | */ 15 | 16 | 17 | 18 | 19 | public class Solution { 20 | /** 21 | * @param s A string 22 | * @return the length of last word 23 | */ 24 | public int lengthOfLastWord(String s) { 25 | int cnt = 0; 26 | String sTrim = s.trim(); 27 | 28 | for (int i = sTrim.length() - 1; i >=0; i--) { 29 | if (sTrim.charAt(i) == ' ') { 30 | break; 31 | } 32 | cnt++; 33 | } 34 | 35 | return cnt; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /string/Letter_Combinations_of_a_Phone_Number.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Letter Combinations of a Phone Number 4 | 5 | 6 | Given a digit string excluded 01, return all possible letter combinations that the number could represent. 7 | 8 | A mapping of digit to letters (just like on the telephone buttons) is given below. 9 | 10 | Cellphone 11 | 12 | Notice 13 | 14 | Although the above answer is in lexicographical order, your answer could be in any order you want. 15 | 16 | Have you met this question in a real interview? Yes 17 | Example 18 | Given "23" 19 | 20 | Return ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"] 21 | 22 | 23 | 解: 24 | 递归做所有组合即可。 25 | 26 | */ 27 | 28 | public class Solution { 29 | /** 30 | * @param digits A digital string 31 | * @return all posible letter combinations 32 | */ 33 | 34 | static final String[] DICT = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; 35 | public ArrayList letterCombinations(String digits) { 36 | ArrayList ret = new ArrayList(); 37 | 38 | if (digits == null || digits.length() == 0) { 39 | return ret; 40 | } 41 | 42 | helper(digits, 0, "", ret); 43 | 44 | return ret; 45 | } 46 | 47 | private void helper(String digits, int idx, String path, ArrayList ret) { 48 | if (idx == digits.length()) { 49 | ret.add(path); 50 | return; 51 | } 52 | 53 | String avai = DICT[digits.charAt(idx) - '0']; 54 | 55 | for (char c : avai.toCharArray()) { 56 | helper(digits, idx + 1, path + String.valueOf(c), ret); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /string/Longest_Common_Prefix.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Longest Common Prefix 4 | 5 | 6 | Given k strings, find the longest common prefix (LCP). 7 | 8 | Example 9 | For strings "ABCD", "ABEF" and "ACEF", the LCP is "A" 10 | 11 | For strings "ABCDEFG", "ABCEFG" and "ABCEFA", the LCP is "ABC" 12 | 13 | 14 | 解: 15 | 这道题只能一个一个字符串的排查。 16 | 因为从信息的角度来讲,必须查找过所有字符串之后,才有可能找出common prefix。 17 | 18 | 可以做一个小优化,在每个字符串长度相差较大时会有不错的效果。 19 | 先遍历字符串数组,找出最短的一个作为初始prefix,这样可以避免初始prefix过长带来的不必要计算。 20 | 21 | 22 | 23 | */ 24 | 25 | public class Solution { 26 | /** 27 | * @param strs: A list of strings 28 | * @return: The longest common prefix 29 | */ 30 | public String longestCommonPrefix(String[] strs) { 31 | if (strs == null || strs.length == 0) { 32 | return ""; 33 | } 34 | 35 | String prefix = strs[0]; 36 | 37 | for (String s : strs) { 38 | if (prefix.length() > s.length()) { 39 | prefix = s; 40 | } 41 | } 42 | 43 | for (String s : strs) { 44 | int i; 45 | for (i = 0; i < prefix.length(); i++) { 46 | if (s.charAt(i) != prefix.charAt(i)) { 47 | break; 48 | } 49 | } 50 | 51 | prefix = prefix.substring(0, i); 52 | } 53 | 54 | return prefix; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /string/Longest_Common_Subsequence.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Longest Common Subsequence 4 | 5 | 6 | Given two strings, find the longest common subsequence (LCS). 7 | 8 | Your code should return the length of LCS. 9 | 10 | Clarification 11 | What's the definition of Longest Common Subsequence? 12 | 13 | https://en.wikipedia.org/wiki/Longest_common_subsequence_problem 14 | http://baike.baidu.com/view/2020307.htm 15 | Example 16 | For "ABCD" and "EDCA", the LCS is "A" (or "D", "C"), return 1. 17 | 18 | For "ABCD" and "EACB", the LCS is "AC", return 2. 19 | 20 | 21 | 22 | 解: 23 | dynanmic programming 24 | 25 | dp[i][j]表示到A[i-1]和B[j-1]为止的最长共同子序列。 26 | 27 | 递推公式: 28 | 如果A[i-1]和B[j-1]相等,那么当前LCS长度应该为去掉A[i-1]和B[j-1]时的LCS长度加1。 29 | 如果不相等,那么应当为去掉A[i-1]或者去掉B[j-1]或者两者都去掉时LCS长度中最大的那个。由于单独去掉A[i-1]或者B[j-1]时的信息多与两者都去掉,所以只要取单独去掉两者中任意一个时的最大LCS。 30 | 故: 31 | dp[i][j] = dp[i-1][j-1], A[i-1] == B[j-1] 32 | dp[i][j] = max(dp[i-1][j], dp[i][j-1]), A[i-1] != B[j-1] 33 | 34 | 初始条件: 35 | 当只有A或者只有B时,最大LCS长度为0。故只需让dp数组的第一行和第一列为0。 36 | 37 | */ 38 | 39 | public class Solution { 40 | /** 41 | * @param A, B: Two strings. 42 | * @return: The length of longest common subsequence of A and B. 43 | */ 44 | public int longestCommonSubsequence(String A, String B) { 45 | int[][] dp = new int[A.length() + 1][B.length() + 1]; 46 | 47 | for (int i = 1; i <= A.length(); i++) { 48 | for (int j = 1; j <= B.length(); j++) { 49 | dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); 50 | if (A.charAt(i - 1) == B.charAt(j - 1)) { 51 | dp[i][j] = dp[i - 1][j - 1] + 1; 52 | } 53 | } 54 | } 55 | 56 | return dp[A.length()][B.length()]; 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /string/Longest_Common_Substring.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Longest Common Substring 4 | 5 | 6 | Given two strings, find the longest common substring. 7 | 8 | Return the length of it. 9 | 10 | Notice 11 | 12 | The characters in substring should occur continuously in original string. This is different with subsequence. 13 | 14 | Example 15 | Given A = "ABCD", B = "CBCE", return 2. 16 | 17 | Challenge 18 | O(n x m) time and memory. 19 | 20 | 21 | 22 | 解: 23 | dynanmic programming 24 | 25 | dp[i][j]表示包含A[i-1]和B[j-1]在内的最长子字符串。 26 | 27 | 递推公式: 28 | 当A[i-1]和B[j-1]相等,应当对之前的子字符串长度加1。 29 | 若不等,则之前的子字符串被截断,当前子字符串长度为0。 30 | 故: 31 | dp[i][j] = dp[i-1][j-1] + 1, A[i-1] == B[j-1] 32 | dp[i][j] = 0, A[i-1] != B[j-1] 33 | 34 | 35 | 初始条件: 36 | 当只取A或者只取B时,共同子字符串不存在,故长度为0。 37 | 即dp的第一行和第一列都为0。 38 | 39 | 40 | */ 41 | 42 | public class Solution { 43 | /** 44 | * @param A, B: Two string. 45 | * @return: the length of the longest common substring. 46 | */ 47 | public int longestCommonSubstring(String A, String B) { 48 | int[][] dp = new int[A.length() + 1][B.length() + 1]; 49 | int max = 0; 50 | 51 | for (int i = 1; i <= A.length(); i++) { 52 | for (int j = 1; j <= B.length(); j++) { 53 | if (A.charAt(i - 1) == B.charAt(j - 1)) { 54 | dp[i][j] = dp[i - 1][j - 1] + 1; 55 | } 56 | max = Math.max(max, dp[i][j]); 57 | } 58 | } 59 | 60 | return max; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /string/Longest_Palindromic_Substring.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Longest Palindromic Substring 4 | 5 | Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. 6 | 7 | Example 8 | Given the string = "abcdzdcab", return "cdzdc". 9 | 10 | Challenge 11 | O(n2) time is acceptable. Can you do it in O(n) time. 12 | 13 | 14 | 解: 15 | Dynanmic Programming 16 | 时间复杂度O(n^2) 17 | 求出任意两点之间的字符串是否为为回文,返回其中最长的。 18 | 19 | 递推公式: 20 | dp[i][j]表示从i到j的字符串是否为回文。 21 | i与j之间的字符串是否为回文,取决于s[i]是否和s[j]相等,以及i+1到j-1是否为回文。 22 | 故: 23 | dp[i][j] = s[i] == s[j] && dp[i+1][j-1] 24 | 25 | 初始条件: 26 | 任意一个字符本是是一个回文: 27 | dp[i][i] = true 28 | 29 | */ 30 | 31 | public class Solution { 32 | /** 33 | * @param s input string 34 | * @return the longest palindromic substring 35 | */ 36 | public String longestPalindrome(String s) { 37 | String longest = ""; 38 | boolean[][] dp = new boolean[s.length()][s.length()]; 39 | 40 | if (s == null || s.length() < 2) { 41 | return s; 42 | } 43 | 44 | for (int i = s.length() - 1; i >= 0; i--) { 45 | dp[i][i] = true; 46 | for (int j = i + 1; j < s.length(); j++) { 47 | if (s.charAt(i) == s.charAt(j) && (dp[i + 1][j - 1] || j == i + 1)) { 48 | dp[i][j] = true; 49 | 50 | if (j - i + 1 > longest.length()) { 51 | longest = s.substring(i, j + 1); 52 | } 53 | } 54 | } 55 | } 56 | 57 | return longest; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /string/Longest_Substring_Without_Repeating_Character.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Longest Substring Without Reapeating Character 4 | 5 | Given a string, find the length of the longest substring without repeating characters. 6 | 7 | Example 8 | 9 | For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. 10 | 11 | For "bbbbb" the longest substring is "b", with the length of 1. 12 | Challenge 13 | 14 | O(n) time 15 | 16 | 17 | 解: 18 | dynanmic programming + HashMap 19 | 20 | 递推公式: 21 | dp[i]表示包含s[i-1]作为字串最后一个字符时的最长子串长度。 22 | 如果s[j] == s[i-1],那么该子串最长长度只能是i-1-j,即从j+1到i-1。 23 | 但是这里还需要考虑从j+1到i-1中可能存在其他重复字符的情况。比如j+1和i-1都是'a',而j+2和i-2都是'b',那么最长字串只能是从j+3到i-1。 24 | 所以,dp[i]还需要考虑dp[i-1],即考虑s[i-2]构成的子串。若s[i-2]构成的子串被j+1到i-1包含在内,则dp[i]只能是dp[i-1]+1,即从上一个子串的开始到s[i-1]。 25 | 26 | 使用HashMap来记录某个字符在s中最后一次出现的位置。 27 | 得到如下公式: 28 | dp[i] = dp[i-1] + 1,map[s[i-1]] >= (i - 1) - dp[i-1],即s[i-1]上次出现的位置不在上一个子串第一个字符之前; 29 | dp[i] = (i - 1) - map[s[i-1]],map[s[i-1]] < (i - 1) - dp[i-1], 即s[i-1]上一次出现的位置在上一个子串第一个字符之前 30 | 31 | 初始条件: 32 | dp[0] = 0 33 | map为空,理解为任意一个字符的初始位置都为无穷小,一定在上一个子串第一个字符出现之前。 34 | 当s中第一个字符被处理时,子串长度为1,该字符还没有出现过,所以dp[1] = dp[0] + 1,只有dp[0] = 0 才可以得到正确结果1。 35 | 36 | 37 | 空间优化: 38 | 由于处理dp[i]只需要用到dp[i-1],所以可以用一个int来记录dp[i-1]。 39 | 但是由于用了HashMap,所以空间复杂度O(n)不变。 40 | 41 | 这里还是用dp数组以便于理解。 42 | 43 | */ 44 | 45 | 46 | public class Solution { 47 | /** 48 | * @param s: a string 49 | * @return: an integer 50 | */ 51 | public int lengthOfLongestSubstring(String s) { 52 | Map map = new HashMap(); 53 | int[] dp = new int[s.length() + 1]; 54 | char[] source = s.toCharArray(); 55 | int max = 0; 56 | 57 | for (int i = 1; i <= s.length(); i++) { 58 | if (map.containsKey(source[i - 1]) && map.get(source[i - 1]) >= i - 1 - dp[i - 1]) { 59 | dp[i] = i - 1 - map.get(source[i - 1]); 60 | } else { 61 | dp[i] = dp[i - 1] + 1; 62 | } 63 | 64 | max = Math.max(max, dp[i]); 65 | map.put(source[i - 1], i - 1); 66 | } 67 | 68 | return max; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /string/Longest_Substring_Without_Repeating_Characters.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Longest Substring Without Repeating Characters 4 | 5 | 6 | Given a string, find the length of the longest substring without repeating characters. 7 | 8 | Example 9 | For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. 10 | 11 | For "bbbbb" the longest substring is "b", with the length of 1. 12 | 13 | Challenge 14 | O(n) time 15 | 16 | 17 | 解: 18 | 把遇到过的字符以及其序号放进一个HashMap。 19 | 每遇到一个重复的字符,就把上一次出现的这个字符以及之前的字符全部删掉。 20 | 每次把HashMap的大小与之前保存的最大值比较,保存较大的那个。 21 | 22 | */ 23 | 24 | public class Solution { 25 | /** 26 | * @param s: a string 27 | * @return: an integer 28 | */ 29 | public int lengthOfLongestSubstring(String s) { 30 | Map map = new HashMap(); 31 | int ret = 0; 32 | char[] c = s.toCharArray(); 33 | 34 | if (s == null || s.length() == 0) { 35 | return 0; 36 | } 37 | 38 | for (int i = 0; i < c.length; i++) { 39 | char key = c[i]; 40 | 41 | if (map.containsKey(key)) { 42 | for (int j = map.get(key); j >= 0; j--) { 43 | if (!map.containsKey(c[j]) || map.get(c[j]) != j) { 44 | break; 45 | } 46 | map.remove(c[j]); 47 | } 48 | } 49 | 50 | map.put(key, i); 51 | ret = Math.max(ret, map.size()); 52 | } 53 | 54 | return ret; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /string/Longest_Substring_with_At_Most_K_Distinct_Characters.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Longest Substring with At Most K Distinct Characters 4 | 5 | 6 | Given a string s, find the length of the longest substring T that contains at most k distinct characters. 7 | 8 | Example 9 | For example, Given s = "eceba", k = 3, 10 | 11 | T is "eceb" which its length is 4. 12 | 13 | Challenge 14 | O(n), n is the size of the string s. 15 | 16 | 17 | 解: 18 | 1.用left和right两个指针确定一个子字符串。 19 | 2.用HashMap统计当前子字符串中每个字符的数量。 20 | 3.每次循环右移right,把新字符放进HashMap中。 21 | 4.如果HashMap的大小超过k,说明字符的种类已经超过k,此时应当把left指向的字符去掉,也就是left右移,并对HashMap中的对应项减一。如果HashMap中某一项值为0,则删掉。 22 | 5.重复4直到HashMap的大小满足条件。 23 | 24 | */ 25 | 26 | public class Solution { 27 | /** 28 | * @param s : A string 29 | * @return : The length of the longest substring 30 | * that contains at most k distinct characters. 31 | */ 32 | public int lengthOfLongestSubstringKDistinct(String s, int k) { 33 | if (s == null || s.length() == 0 || k == 0) { 34 | return 0; 35 | } 36 | 37 | Map map = new HashMap(); 38 | char[] c = s.toCharArray(); 39 | int left = 0; 40 | int right = 0; 41 | int ret = 0; 42 | 43 | while (right < s.length()) { 44 | char key = c[right]; 45 | 46 | /* put the new char in */ 47 | if (!map.containsKey(key)) { 48 | map.put(key, 0); 49 | } 50 | map.put(key, map.get(key) + 1); 51 | 52 | /* remove the excessive ones */ 53 | while (map.size() > k) { 54 | map.put(c[left], map.get(c[left]) - 1); 55 | if (map.get(c[left]) < 1) { 56 | map.remove(c[left]); 57 | } 58 | left++; 59 | } 60 | 61 | ret = Math.max(ret, right - left + 1); 62 | right++; 63 | } 64 | 65 | return ret; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /string/Restore_IP_Address.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Restore IP Address 4 | 5 | 6 | Given a string containing only digits, restore it by returning all possible valid IP address combinations. 7 | 8 | Example 9 | Given "25525511135", return 10 | 11 | [ 12 | "255.255.11.135", 13 | "255.255.111.35" 14 | ] 15 | Order does not matter. 16 | 17 | 18 | 解: 19 | DFS 20 | 按照每段长度进行DFS。 21 | 长度可以是1,2,3,故每次递归中遍历这三种情况。 22 | 递归深度最大为4,因为IP地址有4段。 23 | 24 | 有两种情况一个子字符串不能作为有效地质: 25 | 1.这个子字符串代表的数字大于0,但是以0开头。 26 | 2.这个子字符串代表的数字大于255. 27 | 28 | */ 29 | 30 | 31 | public class Solution { 32 | /** 33 | * @param s the IP string 34 | * @return All possible valid IP addresses 35 | */ 36 | public ArrayList restoreIpAddresses(String s) { 37 | ArrayList ret = new ArrayList(); 38 | 39 | if (s == null || s.length() == 0) { 40 | return ret; 41 | } 42 | 43 | helper(s, 0, "", 0, ret); 44 | 45 | return ret; 46 | } 47 | 48 | private void helper(String s, int idx, String path, int depth, ArrayList ret) { 49 | if (depth == 4) { 50 | if (idx == s.length()) { 51 | ret.add(path.substring(1, path.length())); 52 | } 53 | return; 54 | } else if (s.length() - idx > (4 - depth) * 3 55 | || s.length() - idx < 4 - depth) { 56 | return; 57 | } 58 | 59 | for (int i = 1; i <= 3; i++) { 60 | if (s.length() - idx < i 61 | || (i > 1 && s.charAt(idx) == '0')) { 62 | continue; 63 | } 64 | 65 | String sub = s.substring(idx, idx + i); 66 | 67 | if (Integer.valueOf(sub) > 255) { 68 | break; 69 | } 70 | 71 | helper(s, idx + i, path + "." + sub, depth + 1, ret); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /string/Simplify_Path.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | simplify path 4 | 5 | Given an absolute path for a file (Unix-style), simplify it. 6 | 7 | 解: 8 | 先把输入路径按照“/”来切割成字符串数组,然后遍历该数组。 9 | 当数组中的当前字符串不为“..”也不为“.”或者“”时,入栈该字符串。 10 | 当前字符串为“..”时,若栈不为空,则出栈栈顶元素。 11 | 12 | 如此直到遍历完,然后重组字符串。 13 | 14 | */ 15 | 16 | 17 | 18 | 19 | public class Solution { 20 | /** 21 | * @param path the original path 22 | * @return the simplified path 23 | */ 24 | public String simplifyPath(String path) { 25 | if (path == null) { 26 | return path; 27 | } 28 | 29 | StringBuilder sb = new StringBuilder(); 30 | Stack st = new Stack(); 31 | String[] words = path.split("/"); 32 | 33 | 34 | for (String word : words) { 35 | if (word.equals("..")) { 36 | // "/../" 37 | if (!st.isEmpty()) { 38 | st.pop(); 39 | } 40 | } else if (!word.equals(".") && !word.equals("")) { 41 | st.push(word); 42 | } 43 | } 44 | 45 | // rebuild 46 | while (!st.isEmpty()) { 47 | sb.insert(0, st.pop()); 48 | sb.insert(0, '/'); 49 | } 50 | 51 | return (sb.length() == 0) ? "/" : sb.toString(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /string/String_to_Integer_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | String to Integer II 4 | 5 | Implement function atoi to convert a string to an integer. 6 | 7 | If no valid conversion could be performed, a zero value is returned. 8 | 9 | If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned. 10 | 11 | Example 12 | "10" => 10 13 | "-1" => -1 14 | "123123123123123" => 2147483647 15 | "1.0" => 1 16 | 17 | 18 | 解: 19 | 试吧。 20 | 21 | */ 22 | 23 | public class Solution { 24 | /** 25 | * @param str: A string 26 | * @return An integer 27 | */ 28 | public int atoi(String str) { 29 | if (str == null) { 30 | return 0; 31 | } 32 | char[] in = str.trim().toCharArray(); 33 | 34 | if (in.length == 0) { 35 | return 0; 36 | } 37 | 38 | int flag = (in[0] == '-') ? -1 : 39 | (in[0] == '+') ? 1 : 0; 40 | int isNeg = (flag == 0) ? 1 : flag; 41 | long ret = 0; 42 | 43 | for (int i = Math.abs(flag); i < in.length; i++) { 44 | char c = in[i]; 45 | if (c > '9' || c < '0') { 46 | break; 47 | } 48 | 49 | ret *= 10; 50 | ret += c - '0'; 51 | 52 | if (ret * isNeg >= Integer.MAX_VALUE) { 53 | return Integer.MAX_VALUE; 54 | } else if (ret * isNeg <= Integer.MIN_VALUE) { 55 | return Integer.MIN_VALUE; 56 | } 57 | } 58 | 59 | return (int)ret * isNeg; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /string/Valid_Parentheses.java: -------------------------------------------------------------------------------- 1 | /* 2 | Valid Parentheses 3 | 4 | Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. 5 | 6 | 7 | 解: 8 | 每遇到一个左括号,就放入栈中;每遇到一个右括号,就取出栈顶看是否与其匹配。 9 | 若不匹配则返回false,直到整个字符串被遍历。 10 | */ 11 | 12 | 13 | 14 | public class Solution { 15 | /** 16 | * @param s A string 17 | * @return whether the string is a valid parentheses 18 | */ 19 | public boolean isValidParentheses(String s) { 20 | Stack stack = new Stack(); 21 | 22 | for(int i = 0; i < s.length(); i++) { 23 | char c = s.charAt(i); 24 | if (c == '(' || c == '{' || c == '<' || c == '[' || stack.isEmpty()) { 25 | stack.push(c); 26 | } else { 27 | char c1 = stack.pop(); 28 | if (c == ')' && c1 != '(') { 29 | return false; 30 | } else if (c == '}' && c1 != '{') { 31 | return false; 32 | } else if (c == ']' && c1 != '[') { 33 | return false; 34 | } else if (c == '>' && c1 != '<') { 35 | return false; 36 | } 37 | } 38 | } 39 | 40 | return stack.isEmpty() ? true : false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /string/Word_Break.java: -------------------------------------------------------------------------------- 1 | /* 2 | Word Break 3 | 4 | Given a string s and a dictionary of words dict, determine if s can be break into a space-separated sequence of one or more dictionary words. 5 | 6 | 7 | 解: 8 | 动态规划 9 | 时间O(n^2) 10 | 空间O(n) 11 | 12 | dp[i]表示包含s中第0~i个字符可否满足条件。 13 | 当dp[j](j为小于i的任意index)为真,并且s中第j~i-1个字符可以在字典中找到,则dp[i]为true。 14 | 若j遍历小于i的index之后没有满足条件的j,则dp[i]为false。 15 | */ 16 | 17 | public class Solution { 18 | /** 19 | * @param s: A string s 20 | * @param dict: A dictionary of words dict 21 | */ 22 | public boolean wordBreak(String s, Set dict) { 23 | boolean[] dp = new boolean[s.length() + 1]; 24 | int maxLen = 0; 25 | 26 | if (s == null || dict == null) { 27 | return false; 28 | } 29 | 30 | for (String word : dict) { 31 | maxLen = Math.max(maxLen, word.length()); 32 | } 33 | 34 | dp[0] = true; 35 | for (int i = 1; i <= s.length(); i++) { 36 | for (int j = i - 1; j >= 0 && i - j <= maxLen; j--) { 37 | if (dp[j] && dict.contains(s.substring(j, i))) { 38 | dp[i] = true; 39 | break; 40 | } 41 | } 42 | } 43 | 44 | return dp[s.length()]; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /string/Word_Search.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Word Search 4 | 5 | Given a 2D board and a word, find if the word exists in the grid. 6 | The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once. 7 | 8 | 9 | Example 10 | 11 | Given board = 12 | 13 | [ 14 | "ABCE", 15 | "SFCS", 16 | "ADEE" 17 | ] 18 | word = "ABCCED", -> returns true, 19 | word = "SEE", -> returns true, 20 | word = "ABCB", -> returns false. 21 | 22 | 23 | 解: 24 | 这道题的思路很简单,从矩阵中的每个字符出发,如果该字符和word中第一个字符一致,则继续判断其上下左右四个字符是否与word中下一个字符一致。 25 | 从上下左右中一致的字符再出发进行判断,直到匹配完word,或者遍历完整个矩阵。 26 | 27 | 28 | */ 29 | 30 | 31 | public class Solution { 32 | /** 33 | * @param board: A list of lists of character 34 | * @param word: A string 35 | * @return: A boolean 36 | */ 37 | public boolean exist(char[][] board, String word) { 38 | if (board == null || board.length == 0 || word == null) { 39 | return false; 40 | } 41 | 42 | for (int i = 0; i < board.length; i++) { 43 | for (int j = 0; j < board[0].length; j++) { 44 | if (existHelper(i, j, board, word)) { 45 | return true; 46 | } 47 | } 48 | } 49 | 50 | return false; 51 | } 52 | 53 | public boolean existHelper(int x, int y, char[][] board, String word) { 54 | if (word.length() == 0) { 55 | return true; 56 | } 57 | 58 | if (x < 0 || y < 0 || x >= board.length || y >= board[0].length || 59 | board[x][y] != word.charAt(0)) { 60 | return false; 61 | } 62 | 63 | int[][] travel = {{-1, 0}, {0, 1}, {1, 0}, {0, -1 }}; 64 | char save = board[x][y]; 65 | board[x][y] = '#'; 66 | for (int i = 0; i < 4; i++) { 67 | if (existHelper(x + travel[i][0], y + travel[i][1], board, word.substring(1, word.length()))) { 68 | return true; 69 | } 70 | } 71 | 72 | board[x][y] = save; 73 | return false; 74 | } 75 | } -------------------------------------------------------------------------------- /system design/Inverted_Index.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Inverted Index 4 | 5 | Create an inverted index with given documents. 6 | 7 | Notice 8 | 9 | Ensure that data does not include punctuation. 10 | 11 | Example 12 | 13 | Given a list of documents with id and content. (class Document) 14 | 15 | [ 16 | { 17 | "id": 1, 18 | "content": "This is the content of document 1 it is very short" 19 | }, 20 | { 21 | "id": 2, 22 | "content": "This is the content of document 2 it is very long bilabial bilabial heheh hahaha ..." 23 | }, 24 | ] 25 | Return an inverted index (HashMap with key is the word and value is a list of document ids). 26 | 27 | { 28 | "This": [1, 2], 29 | "is": [1, 2], 30 | ... 31 | } 32 | 33 | 34 | 解: 35 | 这道题只需要把每个document中的每个词作为key放进HashMap中,并且把对应的document id组成一个List放进HashMap的value中。 36 | 注意需要查重,避免同样的id多次放进某一个key的List里面。 37 | 38 | */ 39 | 40 | 41 | /** 42 | * Definition of Document: 43 | * class Document { 44 | * public int id; 45 | * public String content; 46 | * } 47 | */ 48 | public class Solution { 49 | /** 50 | * @param docs a list of documents 51 | * @return an inverted index 52 | */ 53 | public Map> invertedIndex(List docs) { 54 | Map> ret = new HashMap>(); 55 | if (docs == null) { 56 | return ret; 57 | } 58 | 59 | for (Document doc : docs) { 60 | String[] words = doc.content.split(" "); 61 | 62 | for (String word : words) { 63 | if (word.length() == 0) { 64 | continue; 65 | } 66 | if (ret.containsKey(word)) { 67 | if (ret.get(word).contains(doc.id)) { 68 | continue; 69 | } 70 | ret.get(word).add(doc.id); 71 | } else { 72 | List list = new ArrayList(); 73 | list.add(doc.id); 74 | ret.put(word, list); 75 | } 76 | } 77 | } 78 | 79 | return ret; 80 | } 81 | } -------------------------------------------------------------------------------- /system design/Trie_Service.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Trie Service 4 | 5 | Build tries from a list of pairs. Save top 10 for each node. 6 | 7 | Example 8 | 9 | Given a list of 10 | 11 | <"abc", 2> 12 | <"ac", 4> 13 | <"ab", 9> 14 | 15 | Return >c[4]<>>>, and denote the following tree structure: 16 | 17 | Root 18 | / 19 | a(9,4,2) 20 | / \ 21 | b(9,2) c(4) 22 | / 23 | c(2) 24 | 25 | 26 | 27 | 解: 28 | 把输入的单词放进树中,在放入频率的时候按从大到小顺序插入top10 List中即可。 29 | 如果top10 List大小大于10,则删掉最后一个元素。 30 | 31 | */ 32 | 33 | 34 | 35 | /** 36 | * Definition of TrieNode: 37 | * public class TrieNode { 38 | * public NavigableMap children; 39 | * public List top10; 40 | * public TrieNode() { 41 | * children = new TreeMap(); 42 | * top10 = new ArrayList(); 43 | * } 44 | * } 45 | */ 46 | public class TrieService { 47 | 48 | private TrieNode root = null; 49 | 50 | public TrieService() { 51 | root = new TrieNode(); 52 | } 53 | 54 | public TrieNode getRoot() { 55 | // Return root of trie root, and 56 | // lintcode will print the tree struct. 57 | return root; 58 | } 59 | 60 | // @param word a string 61 | // @param frequency an integer 62 | public void insert(String word, int frequency) { 63 | TrieNode iter = root; 64 | 65 | for (int i = 0; i < word.length(); i++) { 66 | char c = word.charAt(i); 67 | if (!iter.children.containsKey(c)) { 68 | iter.children.put(c, new TrieNode()); 69 | } 70 | 71 | TrieNode node = iter.children.get(c); 72 | int insert_idx; 73 | for (insert_idx = 0; insert_idx < node.top10.size(); insert_idx++) { 74 | if (node.top10.get(insert_idx) <= frequency) { 75 | break; 76 | } 77 | } 78 | 79 | node.top10.add(insert_idx, frequency); 80 | 81 | if (node.top10.size() == 11) { 82 | node.top10.remove(10); 83 | } 84 | 85 | iter = node; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /system design/Url_Parser.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Url Parser 4 | 5 | Parse a html page, extract the Urls in it. 6 | 7 | Hint: use regex to parse html. 8 | 9 | Example 10 | 11 | Given the following html page: 12 | 13 | 14 | 15 |
16 | Google 17 | Facebook 18 |
19 |
20 | Linkedin 21 | LintCode 22 |
23 | 24 | 25 | You should return the Urls in it: 26 | 27 | [ 28 | "http://www.google.com", 29 | "http://www.facebook.com", 30 | "https://www.linkedin.com", 31 | "http://github.io" 32 | ] 33 | 34 | 35 | 解: 36 | 这道题的关键是如何组织正则表达式。 37 | 详情可以参考正则表达式教程。 38 | 39 | */ 40 | 41 | 42 | 43 | import java.util.regex.Matcher; 44 | import java.util.regex.Pattern; 45 | 46 | 47 | public class HtmlParser { 48 | /** 49 | * @param content source code 50 | * @return a list of links 51 | */ 52 | public List parseUrls(String content) { 53 | List ret = new ArrayList(); 54 | if (content == null) { 55 | return ret; 56 | } 57 | 58 | Pattern reg = Pattern.compile("\\s*(?i)href\\s*=\\s*[\'\"]?([^\'\" >\\s]*)", Pattern.CASE_INSENSITIVE); 59 | Matcher matcher = reg.matcher(content); 60 | String url = null; 61 | 62 | while (matcher.find()) { 63 | url = matcher.group(1); 64 | if (url.length() == 0 || url.startsWith("#")) { 65 | continue; 66 | } 67 | ret.add(matcher.group(1)); 68 | } 69 | 70 | return ret; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /system design/Word_Count_(Map_Reduce).java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Word Count(Map Reduce) 4 | 5 | Using map reduce to count word frequency. 6 | 7 | https://hadoop.apache.org/docs/r1.2.1/mapred_tutorial.html#Example%3A+WordCount+v1.0 8 | 9 | Example 10 | chunk1: "Google Bye GoodBye Hadoop code" 11 | chunk2: "lintcode code Bye" 12 | 13 | 14 | Get MapReduce result: 15 | Bye: 2 16 | GoodBye: 1 17 | Google: 1 18 | Hadoop: 1 19 | code: 2 20 | lintcode: 1 21 | 22 | 23 | 解: 24 | map步骤是将输入的value拆分成单词,并把每个单词发送给reduce进行处理。 25 | reduce完成统计工作。 26 | 27 | 28 | */ 29 | 30 | 31 | 32 | /** 33 | * Definition of OutputCollector: 34 | * class OutputCollector { 35 | * public void collect(K key, V value); 36 | * // Adds a key/value pair to the output buffer 37 | * } 38 | */ 39 | public class WordCount { 40 | 41 | public static class Map { 42 | public void map(String key, String value, OutputCollector output) { 43 | // Write your code here 44 | // Output the results into output buffer. 45 | // Ps. output.collect(String key, int value); 46 | String[] source = value.split(" "); 47 | for (String s : source) { 48 | output.collect(s, 1); 49 | } 50 | } 51 | } 52 | 53 | public static class Reduce { 54 | public void reduce(String key, Iterator values, 55 | OutputCollector output) { 56 | // Write your code here 57 | // Output the results into output buffer. 58 | // Ps. output.collect(String key, int value); 59 | int cnt = 0; 60 | while (values.hasNext()) { 61 | cnt += values.next(); 62 | } 63 | 64 | output.collect(key, cnt); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /tree/Binary_Search_Tree_Iterator.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Binary Search Tree Iterator 4 | 5 | 6 | 7 | Design an iterator over a binary search tree with the following rules: 8 | 9 | Elements are visited in ascending order (i.e. an in-order traversal) 10 | next() and hasNext() queries run in O(1) time in average. 11 | 12 | 13 | Example 14 | 15 | For the following binary search tree, in-order traversal by using iterator is [1, 6, 10, 11, 12] 16 | 17 | 10 18 | / \ 19 | 1 11 20 | \ \ 21 | 6 12 22 | 23 | Challenge 24 | 25 | Extra memory usage O(h), h is the height of the tree. 26 | 27 | Super Star: Extra memory usage O(1) 28 | 29 | 30 | 31 | 解: 32 | 用一个node来保存每颗子树的root。 33 | 每次next时,若node不为空,则把node的所有左子树包括node在内一并加入栈中。 34 | 然后取栈顶元素的右子树作为新的node,并返回栈顶元素。 35 | 36 | 这样做保证了每个子树的左子树会被加入栈中一次,且不会重复加入。 37 | 38 | */ 39 | 40 | /** 41 | * Definition of TreeNode: 42 | * public class TreeNode { 43 | * public int val; 44 | * public TreeNode left, right; 45 | * public TreeNode(int val) { 46 | * this.val = val; 47 | * this.left = this.right = null; 48 | * } 49 | * } 50 | * Example of iterate a tree: 51 | * BSTIterator iterator = new BSTIterator(root); 52 | * while (iterator.hasNext()) { 53 | * TreeNode node = iterator.next(); 54 | * do something for node 55 | * } 56 | */ 57 | public class BSTIterator { 58 | Stack st; 59 | TreeNode node; 60 | 61 | //@param root: The root of binary tree. 62 | public BSTIterator(TreeNode root) { 63 | st = new Stack(); 64 | node = root; 65 | } 66 | 67 | //@return: True if there has next node, or false 68 | public boolean hasNext() { 69 | return !st.isEmpty() || node != null; 70 | } 71 | 72 | //@return: return next node 73 | public TreeNode next() { 74 | if (st.isEmpty() && node == null) { 75 | return null; 76 | } 77 | 78 | while (node != null) { 79 | st.push(node); 80 | node = node.left; 81 | } 82 | 83 | node = st.peek().right; 84 | 85 | return st.pop(); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /tree/Binary_Tree_Level_Order_Traversal_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Binary Tree Level Order Traversal II 4 | 5 | Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root). 6 | 7 | Example 8 | Given binary tree {3,9,20,#,#,15,7}, 9 | 10 | 3 11 | / \ 12 | 9 20 13 | / \ 14 | 15 7 15 | 16 | 17 | return its bottom-up level order traversal as: 18 | 19 | [ 20 | [15,7], 21 | [9,20], 22 | [3] 23 | ] 24 | 25 | 26 | 解: 27 | 虽说要求自底向上,但实际上真正实现自底向上并不划算。 28 | 还是自上向下level order遍历,但是加入结果数组时每次加在第一个即可。 29 | 30 | 这里虽然使用了两个循环,但是由于每个结点只遍历一次,所以时间复杂度为O(n) 31 | 32 | */ 33 | 34 | /** 35 | * Definition of TreeNode: 36 | * public class TreeNode { 37 | * public int val; 38 | * public TreeNode left, right; 39 | * public TreeNode(int val) { 40 | * this.val = val; 41 | * this.left = this.right = null; 42 | * } 43 | * } 44 | */ 45 | 46 | 47 | public class Solution { 48 | /** 49 | * @param root: The root of binary tree. 50 | * @return: buttom-up level order a list of lists of integer 51 | */ 52 | public ArrayList> levelOrderBottom(TreeNode root) { 53 | ArrayList> ret = new ArrayList>(); 54 | Queue q = new LinkedList(); 55 | 56 | if (root == null) { 57 | return ret; 58 | } 59 | 60 | q.offer(root); 61 | 62 | while (!q.isEmpty()) { 63 | Queue tmpQ = new LinkedList(); 64 | ArrayList list = new ArrayList(); 65 | 66 | while (!q.isEmpty()) { 67 | TreeNode node = q.poll(); 68 | list.add(node.val); 69 | if (node.left != null) { 70 | tmpQ.offer(node.left); 71 | } 72 | if (node.right != null) { 73 | tmpQ.offer(node.right); 74 | } 75 | } 76 | q = tmpQ; 77 | ret.add(0, list); 78 | } 79 | 80 | return ret; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /tree/Binary_Tree_Maximum_Path_Sum.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Binary Tree Maximum Path Sum 4 | 5 | 6 | Given a binary tree, find the maximum path sum. 7 | 8 | The path may start and end at any node in the tree. 9 | 10 | Example 11 | Given the below binary tree: 12 | 13 | 1 14 | / \ 15 | 2 3 16 | return 6. 17 | 18 | 19 | 20 | 解: 21 | divide and conquer 22 | 23 | 后序遍历整个树。 24 | 对于每个子树来说,其最大path sum存在四种可能: 25 | 1.左子树返回值加上自身的值; 26 | 2.右子树返回值加上自身的值; 27 | 3.自身的值什么也不加; 28 | 4.左子树返回值加上右子树返回值加上自身的值。 29 | 30 | 前三中情况可以与该子树的父节点组成新的path sum,故每次递归返回值应当为前三种中最大的。 31 | 最后一种不能于父节点组合,故只存用于计算全局最大path sum。 32 | 33 | */ 34 | 35 | 36 | /** 37 | * Definition of TreeNode: 38 | * public class TreeNode { 39 | * public int val; 40 | * public TreeNode left, right; 41 | * public TreeNode(int val) { 42 | * this.val = val; 43 | * this.left = this.right = null; 44 | * } 45 | * } 46 | */ 47 | public class Solution { 48 | /** 49 | * @param root: The root of binary tree. 50 | * @return: An integer. 51 | */ 52 | 53 | int maxPath; 54 | public int maxPathSum(TreeNode root) { 55 | maxPath = Integer.MIN_VALUE; 56 | /* avoid null root. Keep in mind maxPath must be put after helper */ 57 | return Math.max(helper(root), maxPath); 58 | } 59 | 60 | private int helper(TreeNode root) { 61 | int left, right, max; 62 | 63 | if (root == null) { 64 | return 0; 65 | } 66 | 67 | left = helper(root.left); 68 | right = helper(root.right); 69 | 70 | max = Math.max(root.val, Math.max(left + root.val, right + root.val)); 71 | maxPath = Math.max(maxPath, Math.max(max, left + root.val + right)); 72 | 73 | return max; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tree/Construct_Binary_Tree_from_Preorder_and_Inorder_Traversal.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Construct Binary Tree from Preorder and Inorder Traversal 4 | 5 | 6 | Given preorder and inorder traversal of a tree, construct the binary tree. 7 | Notice 8 | 9 | You may assume that duplicates do not exist in the tree. 10 | 11 | Example 12 | 13 | Given in-order [1,2,3] and pre-order [2,1,3], return a tree: 14 | 15 | 2 16 | / \ 17 | 1 3 18 | 19 | 20 | 21 | 解: 22 | 参照Construct Binary Tree from Preorder and Inorder Traversal。 23 | 把从后向前遍历postorder traversal变成从前向后遍历preorder traversal,同时注意preorder traversal任意一个节点的左子树在其右子树的左边,故先生成左子树。 24 | 25 | */ 26 | 27 | /** 28 | * Definition of TreeNode: 29 | * public class TreeNode { 30 | * public int val; 31 | * public TreeNode left, right; 32 | * public TreeNode(int val) { 33 | * this.val = val; 34 | * this.left = this.right = null; 35 | * } 36 | * } 37 | */ 38 | 39 | 40 | public class Solution { 41 | /** 42 | *@param preorder : A list of integers that preorder traversal of a tree 43 | *@param inorder : A list of integers that inorder traversal of a tree 44 | *@return : Root of a tree 45 | */ 46 | public TreeNode buildTree(int[] preorder, int[] inorder) { 47 | HashMap locator = new HashMap(); 48 | 49 | for (int i = 0; i < inorder.length; i++) { 50 | locator.put(inorder[i], i); 51 | } 52 | 53 | idx = 0; 54 | return helper(locator, 0, inorder.length - 1, preorder); 55 | } 56 | 57 | int idx; 58 | private TreeNode helper(HashMap locator, int start, int end, int[] preorder) { 59 | if (start > end || idx < 0) { 60 | return null; 61 | } 62 | 63 | TreeNode root = new TreeNode(preorder[idx++]); 64 | 65 | root.left = helper(locator, start, locator.get(root.val) - 1, preorder); 66 | root.right = helper(locator, locator.get(root.val) + 1, end, preorder); 67 | 68 | return root; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tree/Convert_Binary_Search_Tree_to_Doubly_Linked_List.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Convert Binary Search Tree to Doubly Linked List 4 | 5 | 6 | Convert a binary search tree to doubly linked list with in-order traversal. 7 | 8 | Example 9 | Given a binary search tree: 10 | 11 | 4 12 | / \ 13 | 2 5 14 | / \ 15 | 1 3 16 | return 1<->2<->3<->4<->5 17 | 18 | 19 | 解: 20 | DFS in order traversal 21 | 22 | */ 23 | 24 | /** 25 | * Definition of TreeNode: 26 | * public class TreeNode { 27 | * public int val; 28 | * public TreeNode left, right; 29 | * public TreeNode(int val) { 30 | * this.val = val; 31 | * this.left = this.right = null; 32 | * } 33 | * } 34 | * Definition for Doubly-ListNode. 35 | * public class DoublyListNode { 36 | * int val; 37 | * DoublyListNode next, prev; 38 | * DoublyListNode(int val) { 39 | * this.val = val; 40 | * this.next = this.prev = null; 41 | * } 42 | * } 43 | */ 44 | public class Solution { 45 | /** 46 | * @param root: The root of tree 47 | * @return: the head of doubly list node 48 | */ 49 | public DoublyListNode bstToDoublyList(TreeNode root) { 50 | if (root == null) { 51 | return null; 52 | } 53 | 54 | DoublyListNode dummy = new DoublyListNode(0); 55 | 56 | helper(dummy, root); 57 | 58 | dummy.next.prev = null; 59 | return dummy.next; 60 | } 61 | 62 | private DoublyListNode helper(DoublyListNode node, TreeNode root) { 63 | if (root == null) { 64 | return node; 65 | } 66 | 67 | node = helper(node, root.left); 68 | 69 | DoublyListNode cur = new DoublyListNode(root.val); 70 | node.next = cur; 71 | cur.prev = node; 72 | 73 | return helper(cur, root.right); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tree/Lowest_Common_Ancestor.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Lowest Common Ancestor 4 | 5 | Given the root and two nodes in a Binary Tree. Find the lowest common ancestor(LCA) of the two nodes. 6 | 7 | The lowest common ancestor is the node with largest depth which is the ancestor of both nodes. 8 | 9 | Notice 10 | 11 | Assume two nodes are exist in tree. 12 | 13 | Example 14 | For the following binary tree: 15 | 16 | 4 17 | / \ 18 | 3 7 19 | / \ 20 | 5 6 21 | LCA(3, 5) = 4 22 | 23 | LCA(5, 6) = 7 24 | 25 | LCA(6, 7) = 7 26 | 27 | 28 | 29 | 解: 30 | first order traverse 31 | 32 | 利用返回值的三种情况来直接完成信息传递: 33 | 1.null。当前节点为空,或者当前节点不是两个目标节点之一,并且左右子树内也不包含目标节点。 34 | 2.目标节点。当前节点为目标节点或者目标节点存在于当前节点的子树中。 35 | 3.LCA。当前节点的左子树和右子树中分别包含两个目标节点。 36 | 37 | 由于题目假设两个目标节点一定存在,所以不需要helper函数直接完成先序遍历即可。 38 | 39 | 40 | */ 41 | 42 | /** 43 | * Definition of TreeNode: 44 | * public class TreeNode { 45 | * public int val; 46 | * public TreeNode left, right; 47 | * public TreeNode(int val) { 48 | * this.val = val; 49 | * this.left = this.right = null; 50 | * } 51 | * } 52 | */ 53 | public class Solution { 54 | /** 55 | * @param root: The root of the binary search tree. 56 | * @param A and B: two nodes in a Binary. 57 | * @return: Return the least common ancestor(LCA) of the two nodes. 58 | */ 59 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) { 60 | if (root == null) { 61 | return null; 62 | } 63 | 64 | if (root == A || root == B) { 65 | return root; 66 | } 67 | 68 | TreeNode left = lowestCommonAncestor(root.left, A, B); 69 | TreeNode right = lowestCommonAncestor(root.right, A, B); 70 | 71 | if ((left == A && right == B) || (left == B && right == A)) { 72 | return root; 73 | } else if (left != null) { 74 | return left; 75 | } else if (right != null) { 76 | return right; 77 | } 78 | 79 | return null; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /tree/Minimum_Depth_of_Binary_Tree.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Minimum Depth of Binary Tree 4 | 5 | Given a binary tree, find its minimum depth. 6 | 7 | The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. 8 | 9 | 10 | Example 11 | Given a binary tree as follow: 12 | 13 | 1 14 | / \ 15 | 2 3 16 | / \ 17 | 4 5 18 | The minimum depth is 2. 19 | 20 | 21 | 解: 22 | Divide and conquer 23 | 24 | 若遇到空节点,直接返回上一级的深度。 25 | 若非空,分别查找左右子树的最小深度,然后根据得到的值确定返回值。 26 | 如果左右都返回当前的深度,说明左右子树都为空,返回当前节点深度。 27 | 如果左右返回值都不是当前节点深度,说明左右子树都不为空,返回其中小的那个。 28 | 如果左右有一个为当前节点深度,则返回不为当前节点深度的那个。 29 | 30 | */ 31 | 32 | 33 | 34 | /** 35 | * Definition of TreeNode: 36 | * public class TreeNode { 37 | * public int val; 38 | * public TreeNode left, right; 39 | * public TreeNode(int val) { 40 | * this.val = val; 41 | * this.left = this.right = null; 42 | * } 43 | * } 44 | */ 45 | public class Solution { 46 | /** 47 | * @param root: The root of binary tree. 48 | * @return: An integer. 49 | */ 50 | 51 | public int minDepth(TreeNode root) { 52 | return helper(root, 1); 53 | } 54 | 55 | private int helper(TreeNode root, int lvl) { 56 | if (root == null) { 57 | return lvl - 1; 58 | } 59 | 60 | int left = helper(root.left, lvl + 1); 61 | int right = helper(root.right, lvl + 1); 62 | 63 | if (left == lvl && right == lvl) { 64 | return lvl; 65 | } else if (left != lvl && right != lvl) { 66 | return Math.min(left, right); 67 | } else { 68 | return left == lvl ? right : left; 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /tree/Search_Range_in_Binary_Search_Tree.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Search Range in Binary Search Tree 4 | 5 | Given two values k1 and k2 (where k1 < k2) and a root pointer to a Binary Search Tree. Find all the keys of tree in range k1 to k2. i.e. print all x such that k1<=x<=k2 and x is a key of given BST. Return all the keys in ascending order. 6 | 7 | Have you met this question in a real interview? Yes 8 | 9 | Example 10 | If k1 = 10 and k2 = 22, then your function should return [12, 20, 22]. 11 | 12 | 20 13 | / \ 14 | 8 22 15 | / \ 16 | 4 12 17 | 18 | 19 | 20 | 解: 21 | 对排序二叉树进行中序遍历即可。 22 | 23 | */ 24 | 25 | 26 | 27 | /** 28 | * Definition of TreeNode: 29 | * public class TreeNode { 30 | * public int val; 31 | * public TreeNode left, right; 32 | * public TreeNode(int val) { 33 | * this.val = val; 34 | * this.left = this.right = null; 35 | * } 36 | * } 37 | */ 38 | 39 | public class Solution { 40 | /** 41 | * @param root: The root of the binary search tree. 42 | * @param k1 and k2: range k1 to k2. 43 | * @return: Return all keys that k1<=key<=k2 in ascending order. 44 | */ 45 | 46 | public ArrayList searchRange(TreeNode root, int k1, int k2) { 47 | ArrayList ret = new ArrayList(); 48 | helper(root, k1, k2, ret); 49 | 50 | return ret; 51 | } 52 | 53 | 54 | 55 | private void helper(TreeNode root, int k1, int k2, ArrayList ret) { 56 | if (root == null) { 57 | return; 58 | } 59 | 60 | helper(root.left, k1, k2, ret); 61 | if (root.val >= k1 && root.val <= k2) { 62 | ret.add(root.val); 63 | } 64 | helper(root.right, k1, k2, ret); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tree/Unique_Binary_Search_Trees.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Unique Binary Search Trees 4 | 5 | Given n, how many structurally unique BSTs (binary search trees) that store values 1...n? 6 | 7 | Have you met this question in a real interview? Yes 8 | Example 9 | Given n = 3, there are a total of 5 unique BST's. 10 | 11 | 1 3 3 2 1 12 | \ / / / \ \ 13 | 3 2 1 1 3 2 14 | / / \ \ 15 | 2 1 2 3 16 | 17 | 18 | 解: 19 | Dynanmic Programming 20 | dp[i]表示1~i可以有多少个独特查找树。 21 | 22 | 递推公式: 23 | 有多少个独特查找数,取决于1~i中每一个数字作为root时,其左右子树有多少种可能性。 24 | 故: 25 | dp[i] = dp[0]*dp[i - 1] + dp[1]*dp[i - 2] + dp[2]*dp[i - 3] + ... + dp[i - 1]*dp[0] 26 | 27 | 初始条件,由于计算dp[i]时涉及到小于i的所有结果,所以至少初始化dp[0]。 28 | 而dp[0]表示空树,只有一种情况,故: 29 | dp[0] = 1 30 | 31 | */ 32 | 33 | 34 | public class Solution { 35 | /** 36 | * @paramn n: An integer 37 | * @return: An integer 38 | */ 39 | public int numTrees(int n) { 40 | int[] dp = new int[n + 1]; 41 | 42 | dp[0] = 1; 43 | 44 | for (int i = 1; i <= n; i++) { 45 | dp[i] = 0; 46 | for (int j = 0; j < i; j++) { 47 | dp[i] += dp[j] * dp[i - 1 - j]; 48 | } 49 | } 50 | 51 | return dp[n]; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tree/Unique_Binary_Search_Trees_II.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Unique Binary Search Trees II 4 | 5 | Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. 6 | 7 | Example 8 | Given n = 3, your program should return all 5 unique BST's shown below. 9 | 10 | 1 3 3 2 1 11 | \ / / / \ \ 12 | 3 2 1 1 3 2 13 | / / \ \ 14 | 2 1 2 3 15 | 16 | 17 | 解: 18 | DFS递归 19 | 辅助函数生成从start到end的BST。 20 | 那么当处理start到end之间的数字i时,应当从start到i-1生成左子树,从i+1到end生成右子树。 21 | 组合所有的左子树和右子树的可能性,并存入结果列表。 22 | 注意: 23 | 当start大于end时,说明应当返回含有空树的列表,而非返回空列表。 24 | 25 | */ 26 | 27 | 28 | /** 29 | * Definition of TreeNode: 30 | * public class TreeNode { 31 | * public int val; 32 | * public TreeNode left, right; 33 | * public TreeNode(int val) { 34 | * this.val = val; 35 | * this.left = this.right = null; 36 | * } 37 | * } 38 | */ 39 | public class Solution { 40 | /** 41 | * @paramn n: An integer 42 | * @return: A list of root 43 | */ 44 | public List generateTrees(int n) { 45 | return helper(1, n); 46 | } 47 | 48 | private List helper(int start, int end) { 49 | List ret = new ArrayList(); 50 | 51 | if (start > end) { 52 | ret.add(null); 53 | return ret; 54 | } 55 | 56 | for (int i = start; i <= end; i++) { 57 | List left = helper(start, i - 1); 58 | List right = helper(i + 1, end); 59 | 60 | for (TreeNode l : left) { 61 | for (TreeNode r : right) { 62 | TreeNode root = new TreeNode(i); 63 | root.left = l; 64 | root.right = r; 65 | ret.add(root); 66 | } 67 | } 68 | } 69 | 70 | return ret; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /tree/Validate_Binary_Search_Tree.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Validate Binary Search Tree 4 | 5 | Given a binary tree, determine if it is a valid binary search tree (BST). 6 | 7 | Assume a BST is defined as follows: 8 | 9 | The left subtree of a node contains only nodes with keys less than the node's key. 10 | The right subtree of a node contains only nodes with keys greater than the node's key. 11 | Both the left and right subtrees must also be binary search trees. 12 | A single node tree is a BST 13 | 14 | Example 15 | An example: 16 | 17 | 2 18 | / \ 19 | 1 4 20 | / \ 21 | 3 5 22 | The above binary tree is serialized as {2,1,4,#,#,3,5} (in level order). 23 | 24 | 25 | 解: 26 | 先序遍历整颗树。 27 | 28 | 设定每个节点的最大值max和最小值min,每个节点的值应当小于max,大于min。否则该次递归返回false。 29 | max和min初始为Long的最大可能值和最小可能值。 30 | 当搜索任意节点的左子树时,由于左子树的任何值都应当小于该结点的值,故max变为该节点的值。 31 | 当搜索任意节点的右子树时,由于右子树的任何值都应当大于该结点的值,故min变为该节点的值。 32 | 33 | 当左右子树任意一个返回false时,该次递归返回false。 34 | 35 | */ 36 | 37 | 38 | /** 39 | * Definition of TreeNode: 40 | * public class TreeNode { 41 | * public int val; 42 | * public TreeNode left, right; 43 | * public TreeNode(int val) { 44 | * this.val = val; 45 | * this.left = this.right = null; 46 | * } 47 | * } 48 | */ 49 | public class Solution { 50 | /** 51 | * @param root: The root of binary tree. 52 | * @return: True if the binary tree is BST, or false 53 | */ 54 | public boolean isValidBST(TreeNode root) { 55 | return helper(root, Long.MAX_VALUE, Long.MIN_VALUE); 56 | } 57 | 58 | private boolean helper(TreeNode root, long max, long min) { 59 | if (root == null) { 60 | return true; 61 | } else if (root.val >= max || root.val <= min) { 62 | return false; 63 | } 64 | 65 | if (helper(root.left, root.val, min)) { 66 | return helper(root.right, max, root.val); 67 | } 68 | 69 | return false; 70 | } 71 | } 72 | --------------------------------------------------------------------------------