Repository: apachecn/apachecn-algo-zh
Branch: master
Commit: ca52c3b38633
Files: 696
Total size: 1.2 MB
Directory structure:
gitextract_q9u5mspj/
├── .gitignore
├── .nojekyll
├── 404.html
├── CNAME
├── Dockerfile
├── NAV.md
├── README.md
├── SUMMARY.md
├── asset/
│ ├── back-to-top.css
│ ├── back-to-top.js
│ ├── dark-mode.css
│ ├── dark-mode.js
│ ├── docsify-apachecn-footer.js
│ ├── docsify-baidu-push.js
│ ├── docsify-baidu-stat.js
│ ├── docsify-clicker.js
│ ├── docsify-cnzz.js
│ ├── docsify-quick-page.css
│ ├── docsify-quick-page.js
│ ├── edit.css
│ ├── edit.js
│ ├── prism-darcula.css
│ ├── share.css
│ ├── share.js
│ ├── style.css
│ └── vue.css
├── docs/
│ ├── jianzhioffer/
│ │ └── java/
│ │ ├── 03_01_DuplicationInArray.md
│ │ ├── 03_02_DuplicationInArrayNoEdit.md
│ │ ├── 04_FindInPartiallySortedMatrix.md
│ │ ├── 05_ReplaceSpaces.md
│ │ ├── 06_PrintListInReversedOrder.md
│ │ ├── 07_ConstructBinaryTree.md
│ │ ├── 08_NextNodeInBinaryTrees.md
│ │ ├── 09_01_QueueWithTwoStacks.md
│ │ ├── 09_02_StackWithTwoQueues.md
│ │ ├── 10_01_Fibonacci.md
│ │ ├── 10_02_JumpFloor.md
│ │ ├── 10_03_JumpFloorII.md
│ │ ├── 10_04_RectCover.md
│ │ ├── 11_MinNumberInRotatedArray.md
│ │ ├── 12_StringPathInMatrix.md
│ │ ├── 13_RobotMove.md
│ │ ├── 14_CuttingRope.md
│ │ ├── 15_NumberOf1InBinary.md
│ │ ├── 16_Power.md
│ │ ├── 17_Print1ToMaxOfNDigits.md
│ │ ├── 18_01_DeleteNodeInList.md
│ │ ├── 18_02_DeleteDuplicatedNode.md
│ │ ├── 19_RegularExpressionsMatching.md
│ │ ├── 20_NumericStrings.md
│ │ ├── 21_ReorderArray.md
│ │ ├── 22_KthNodeFromEnd.md
│ │ ├── 23_EntryNodeInListLoop.md
│ │ ├── 24_ReverseList.md
│ │ ├── 25_MergeSortedLists.md
│ │ ├── 26_SubstructureInTree.md
│ │ ├── 27_MirrorOfBinaryTree.md
│ │ ├── 28_SymmetricalBinaryTree.md
│ │ ├── 29_PrintMatrix.md
│ │ ├── 30_MinInStack.md
│ │ ├── 31_StackPushPopOrder.md
│ │ ├── 32_01_PrintTreeFromTopToBottom.md
│ │ ├── 32_02_PrintTreesInLines.md
│ │ ├── 32_03_PrintTreesInZigzag.md
│ │ ├── 33_SquenceOfBST.md
│ │ ├── 34_PathInTree.md
│ │ ├── 35_CopyComplexList.md
│ │ ├── 36_ConvertBinarySearchTree.md
│ │ ├── 37_SerializeBinaryTrees.md
│ │ ├── 38_StringPermutation.md
│ │ ├── 39_MoreThanHalfNumber.md
│ │ ├── 40_KLeastNumbers.md
│ │ ├── 41_StreamMedian.md
│ │ ├── 42_GreatestSumOfSubarrays.md
│ │ ├── 43_NumberOf1.md
│ │ ├── 44_DigitsInSequence.md
│ │ ├── 45_SortArrayForMinNumber.md
│ │ ├── 46_TranslateNumbersToStrings.md
│ │ ├── 47_MaxValueOfGifts.md
│ │ ├── 48_LongestSubstringWithoutDup.md
│ │ ├── 49_UglyNumber.md
│ │ ├── 50_01_FirstNotRepeatingChar.md
│ │ ├── 50_02_FristCharacterInStream.md
│ │ ├── 52_FirstCommonNodesInLists.md
│ │ ├── 53_01_NumberOfK.md
│ │ ├── 53_02_MissingNumber.md
│ │ ├── 53_03_IntegerIdenticalToIndex.md
│ │ ├── 54_KthNodeInBST.md
│ │ ├── 55_01_TreeDepth.md
│ │ ├── 55_02_BalancedBinaryTree.md
│ │ ├── 56_01_NumbersAppearOnce.md
│ │ ├── 56_02_NumberAppearingOnce.md
│ │ ├── 57_01_TwoNumbersWithSum.md
│ │ ├── 57_02_ContinuousSquenceWithSum.md
│ │ ├── 58_01_ReverseWordsInSentence.md
│ │ ├── 58_02_LeftRotateString.md
│ │ ├── 59_01_MaxInSlidingWindow.md
│ │ ├── 61_ContinousCards.md
│ │ ├── README.md
│ │ └── SUMMARY.md
│ ├── leetcode/
│ │ ├── cpp/
│ │ │ ├── 0001._Two_Sum.md
│ │ │ ├── 0002._Add_Two_Numbers.md
│ │ │ ├── 0003._Longest_Substring_Without_Repeating_Characters.md
│ │ │ ├── 0004._Median_of_Two_Sorted_Arrays.md
│ │ │ ├── 0005._Longest_Palindromic_Substring.md
│ │ │ ├── 0006._ZigZag_Conversion.md
│ │ │ ├── 0007._Reverse_Integer.md
│ │ │ ├── 0008._String_to_Integer_(atoi).md
│ │ │ ├── 0009._Palindrome_Number.md
│ │ │ ├── 0010._Regular_Expression_Matching.md
│ │ │ ├── 0011._Container_With_Most_Water.md
│ │ │ ├── 0012._Integer_to_Roman.md
│ │ │ ├── 0014._Longest_Common_Prefix.md
│ │ │ ├── 0015._3sum.md
│ │ │ ├── 0016._3Sum_Closest.md
│ │ │ ├── 0017._Letter_Combinations_of_a_Phone_Number.md
│ │ │ ├── 0018._4Sum.md
│ │ │ ├── 0019._Remove_Nth_Node_From_End_of_List.md
│ │ │ ├── 0020._Valid_Parentheses.md
│ │ │ ├── 0021._Merge_Two_Sorted_Lists.md
│ │ │ ├── 0022._Generate_Parentheses.md
│ │ │ ├── 0023._Merge_K_Sorted_Lists.md
│ │ │ ├── 0024._Swap_Nodes_in_Pairs.md
│ │ │ ├── 0025._Reverse_Nodes_In_K_Group.md
│ │ │ ├── 0026._Remove_Duplicates_From_Sorted_Array.md
│ │ │ ├── 0027._Remove_Element.md
│ │ │ ├── 0028._Implement_Strstr.md
│ │ │ ├── 0029._Divide_Two_Integers.md
│ │ │ ├── 0030._Substring_With_Concatenation_Of_All_Words.md
│ │ │ ├── 0031._Next_Permutatio.md
│ │ │ ├── 0032._Longest_Valid_Parentheses.md
│ │ │ ├── 0033._Search_in_Rotated_Sorted_Array.md
│ │ │ ├── 0034._Find_First_and_Last_Position_of_Element_in_Sorted_Array.md
│ │ │ ├── 0035._Search_Insert_Position.md
│ │ │ ├── 0036._Valid_Sudoku.md
│ │ │ ├── 0038._Count_and_Say.md
│ │ │ ├── 0039._Combination_Sum.md
│ │ │ ├── 0040._Combination_Sum_II.md
│ │ │ ├── 0041._First_Missing_Positive.md
│ │ │ ├── 0042._Trapping_Rain_Water.md
│ │ │ ├── 0043._Multiply_Strings.md
│ │ │ ├── 0044._Wildcard_Matching.md
│ │ │ ├── 0045._Jump_Game_II.md
│ │ │ ├── 0046._Permutations.md
│ │ │ ├── 0047._Permutations_II.md
│ │ │ ├── 0048._Rotate_Image.md
│ │ │ ├── 0049._Group_Anagrams.md
│ │ │ ├── 0050._powx_n.md
│ │ │ ├── 0051._N-Queens.md
│ │ │ ├── 0052._N-Queens_II.md
│ │ │ ├── 0053._Maximum_Subarray.md
│ │ │ ├── 0054._Spiral_Matrix.md
│ │ │ ├── 0055._Jump_Game.md
│ │ │ ├── 0056._Merge_Intervals.md
│ │ │ ├── 0057._Insert_Interval.md
│ │ │ ├── 0058._Length_of_Last_Word.md
│ │ │ ├── 0059._Spiral_Matrix_II.md
│ │ │ ├── 0060._Permutation_Sequence.md
│ │ │ ├── 0061._Rotate_List.md
│ │ │ ├── 0062._Unique_Paths.md
│ │ │ ├── 0063._Unique_Paths_II.md
│ │ │ ├── 0064._Minimum_Path_Sum.md
│ │ │ ├── 0065._Valid_Number.md
│ │ │ ├── 0066._Plus_One.md
│ │ │ ├── 0068._Text_Justification.md
│ │ │ ├── 0069._Sqr(x).md
│ │ │ ├── 0072._Edit_Distance.md
│ │ │ ├── 0075._Sort_Colors.md
│ │ │ ├── 0076._Minimum_Window_Substring.md
│ │ │ ├── 0077._combinations.md
│ │ │ ├── 0078._subsets.md
│ │ │ ├── 0081._Search_in_Rotated_Sorted_Array_II.md
│ │ │ ├── 0083._Remove_Duplicates_From_Sorted_Lists.md
│ │ │ ├── 0084._Largest_Rectangle_in_Histogram.md
│ │ │ ├── 0085._Maximal_Rectangle.md
│ │ │ ├── 0087._Scramble_String.md
│ │ │ ├── 0088._Merge_Sorted_Array.md
│ │ │ ├── 0090._Subsets_II.md
│ │ │ ├── 0094._binary_tree_inorder_traversal.md
│ │ │ ├── 0096._Unique_Binary_Search_Trees.md
│ │ │ ├── 0097._Interleaving_String.md
│ │ │ ├── 0099._Recover_Binary_Search_Tree.md
│ │ │ ├── 0100._same_tree.md
│ │ │ ├── 0101._Symmetric_Tree.md
│ │ │ ├── 0102._Binary_Tree_Level_Order_Traversal.md
│ │ │ ├── 0104._Maximum_Depth_of_Binary_Tree.md
│ │ │ ├── 0105._Construct_Binary_Tree_from_Preorder_and_Inorder_Traversal.md
│ │ │ ├── 0106._Construct_Binary_Tree_from_Inorder_and_Postorder_Traversal.md
│ │ │ ├── 0107._Binary_Tree_Level_Order_Traversal_II.md
│ │ │ ├── 0108._Convert_Sorted_Array_to_Binary_Search_Tree.md
│ │ │ ├── 0109._Convert_Sorted_List_to_Binary_Search_Tree.md
│ │ │ ├── 0110._Balanced_Binary_Tree.md
│ │ │ ├── 0111._Minimum_Depth_Of_Binary_Tree.md
│ │ │ ├── 0112._Path_Sum.md
│ │ │ ├── 0114._Flatten_Binary_Tree_to_Linked_List.md
│ │ │ ├── 0115._Distinct_Subsequences.md
│ │ │ ├── 0118._Pascals_Triangle.md
│ │ │ ├── 0119._Pascals_Triangle-II.md
│ │ │ ├── 0120._Triangle.md
│ │ │ ├── 0121._Best_Tim_to_Buy_and_Sell_Stock.md
│ │ │ ├── 0122._Best_Time_to_Buy_and_Sell_Stock_II.md
│ │ │ ├── 0123._Best_Time_to_Buy_and_Sell_Stock_III.md
│ │ │ ├── 0124._Binary_Tree_Maximum_Path_Sum.md
│ │ │ ├── 0127._Word_Ladde.md
│ │ │ ├── 0128._Longest_Consecutive_Sequence.md
│ │ │ ├── 0129._Sum_Root_to_Leaf_Numbers.md
│ │ │ ├── 0131._Palindrome_Partitioning.md
│ │ │ ├── 0136._Single_Numbe.md
│ │ │ ├── 0137._Single_Number_II.md
│ │ │ ├── 0141._Linked_List_Cycle.md
│ │ │ ├── 0142._Linked_List_Cycle_II.md
│ │ │ ├── 0144._Binary_Tree_Preorder_Traversal.md
│ │ │ ├── 0145._Binary_Tree_Postorder_Traversal.md
│ │ │ ├── 0147._Insert_on_Sort_List.md
│ │ │ ├── 0148._Sort_list.md
│ │ │ ├── 0151._Reverse_Words_in_a_String.md
│ │ │ ├── 0153._Find_Minimum_in_Rotated_Sorted_Array.md
│ │ │ ├── 0154._Find_Minimum_in_Rotated_Sorted_Array-II.md
│ │ │ ├── 0160._Intersection_Of_Two_Linked_Lists.md
│ │ │ ├── 0164._Maximum_Gap.md
│ │ │ ├── 0166._Fraction_to_Recurring_Decimal.md
│ │ │ ├── 0167._Two_Sum_II-Input_array_is_sorted.md
│ │ │ ├── 0199._Binary_Tree_Right_Side_View.md
│ │ │ ├── 0216._Combination_Sum_III.md
│ │ │ ├── 0230._Kth_Smallest_Element_in_a_BST.md
│ │ │ ├── 0260._Single_Number_III.md
│ │ │ ├── 0287._Find_the_Duplicate_Number.md
│ │ │ ├── 0326._Power_Of_Three.md
│ │ │ ├── 0328._Odd_Even_Linked_List.md
│ │ │ ├── 0329._Longest_Increasing_Path_in_a_Matrix.md
│ │ │ ├── 0338._Counting_Bits.md
│ │ │ ├── 0413._Arithmetic_Slices.md
│ │ │ ├── 0442._Find_All_Duplicates_in_an_Array.md
│ │ │ ├── 0513._Find_Bottom_Left_Tree_Value.md
│ │ │ ├── 0515._Find_Largest_Value_in_Each_Tree_Row.md
│ │ │ ├── 0540._Single_Element_in_a_Sorted_Array.md
│ │ │ ├── 0581._Shortest_Unsorted_Continuous_Subarray.md
│ │ │ ├── 0629._K_Inverse_Pairs_Array.md
│ │ │ ├── 0632._Smallest_Range.md
│ │ │ ├── 0654._maximum_binary_tree.md
│ │ │ ├── 0668._Kth_Smallest_Number_in_Multiplication_Table.md
│ │ │ ├── 0701._Insert_into_a_Binary_Search_Tree.md
│ │ │ ├── 0715._Range_Module.md
│ │ │ ├── 0719._Find_K-th_Smallest_Pair_Distance.md
│ │ │ ├── 0739._Daily_Temperatures.md
│ │ │ ├── 0797._All_Paths_From_Source_To_Target.md
│ │ │ ├── 0814._Binary_Tree_Pruning.md
│ │ │ ├── 0841._Keys_and_Rooms.md
│ │ │ ├── 0877._Stone_Game.md
│ │ │ ├── 0945._Minimum_Increment_to_Make_Array_Unique.md
│ │ │ ├── 0946._Validate_Stack_Sequences.md
│ │ │ ├── 0947._Most_Stones_Removed_with_Same_Row_or_Column.md
│ │ │ ├── 0948._Bag_of_Tokens.md
│ │ │ ├── 0949._Largest_Time_for_Given_Digits.md
│ │ │ ├── 0950._Reveal_Cards_In_Increasing_Order.md
│ │ │ ├── 0951._Flip_Equivalent_Binary_Trees.md
│ │ │ ├── 0952._Largest_Component_Size_by_Common_Factor.md
│ │ │ ├── README.md
│ │ │ └── SUMMARY.md
│ │ ├── java/
│ │ │ ├── 0001._Two_Sum.md
│ │ │ ├── 0002._add_two_numbers.md
│ │ │ ├── 0003._Longest_Substring_Without_Repeating_Characters.md
│ │ │ ├── 0004._Median_of_Two_Sorted_Arrays.md
│ │ │ ├── 0005._Longest_Palindromic_Substring.md
│ │ │ ├── 0006._ZigZag_Conversion.md
│ │ │ ├── 0007._Reverse_Integer.md
│ │ │ ├── 0023._Merge_K_Sorted_Lists.md
│ │ │ ├── 0141._linked_list_cycle.md
│ │ │ ├── 0218._The_Skyline_Problem.md
│ │ │ ├── 0238._product_of_array_except_self.md
│ │ │ ├── 0342._Power_of_Four.md
│ │ │ ├── 0403._Frog_Jump.md
│ │ │ ├── 0757._Set_Intersection_Size_At_Least_Two.md
│ │ │ ├── 0768._Max_Chunks_To_Make_Sorted_II.md
│ │ │ ├── 0780._Reaching_Points.md
│ │ │ ├── 0793._Preimage_Size_of_Factorial_Zeroes_Function.md
│ │ │ ├── 0827._Making_A_Large_Island.md
│ │ │ ├── 0828._Unique_Letter_String.md
│ │ │ ├── 0834._Sum_of_Distances_in_Tree.md
│ │ │ ├── 0843._Guess_the_Word.md
│ │ │ ├── 0847._Shortest_Path_Visiting_All_Nodes.md
│ │ │ ├── 0850._Rectangle_Area_II.md
│ │ │ ├── 0854._K-Similar_Strings.md
│ │ │ ├── 0857._Minimum_Cost_to_Hire_K_Workers.md
│ │ │ ├── 0862._Shortest_Subarray_with_Sum_at_Least_K.md
│ │ │ ├── 0864._Shortest_Path_to_Get_All_Keys.md
│ │ │ ├── 0871._Minimum_Number_of_Refueling_Stops.md
│ │ │ ├── 0878._Nth_Magical_Number.md
│ │ │ ├── 0879._Profitable_Schemes.md
│ │ │ ├── 0882._Reachable_Nodes_In_Subdivided_Graph.md
│ │ │ ├── 0887._Super_Egg_Drop.md
│ │ │ ├── 0891._Sum_of_Subsequence_Widths.md
│ │ │ ├── 0895._Maximum_Frequency_Stack.md
│ │ │ ├── 0899._Orderly_Queue.md
│ │ │ ├── 0902._Numbers_At_Most_N_Given_Digit_Set.md
│ │ │ ├── 0903._Valid_Permutations_for_DI_Sequence.md
│ │ │ ├── 0906._Super_Palindromes.md
│ │ │ ├── 0913._Cat_and_Mouse.md
│ │ │ ├── 0920._Number_of_Music_Playlists.md
│ │ │ ├── README.md
│ │ │ └── SUMMARY.md
│ │ ├── javascript/
│ │ │ ├── 0001._Two_Sum.md
│ │ │ ├── 0002._Add_Two_Numbers.md
│ │ │ ├── 0003._Longest_Substring_without_Repeating_Characters.md
│ │ │ ├── 0005._Longest_Palindromic_Substring.md
│ │ │ ├── 0007._Reverse_Integer.md
│ │ │ ├── 0008._String_to_Integer.md
│ │ │ ├── 0009._Palindrome_Number.md
│ │ │ ├── 0011._Container_With_Most_Water.md
│ │ │ ├── 0012._Integer_To_Roman.md
│ │ │ ├── 0013._Roman_To_Integer.md
│ │ │ ├── 0014._Longest_Common_Prefix.md
│ │ │ ├── 0015._Three_Sum.md
│ │ │ ├── 0016._3_Sum_Closest.md
│ │ │ ├── 0017._Letter_Combinations_Of_A_Phone_Number.md
│ │ │ ├── 0019._Remove_Nth_Node_From_End_Of_List.md
│ │ │ ├── 0020._Valid_Parentheses.md
│ │ │ ├── 0021._Merge_Two_Sorted_Lists.md
│ │ │ ├── 0022._Generate_Parentheses.md
│ │ │ ├── 0024._Swap_Nodes_In_Pairs.md
│ │ │ ├── 0027._Remove_Element.md
│ │ │ ├── 0031._Next_Permutation.md
│ │ │ ├── 0035._Search_Insert_Position.md
│ │ │ ├── 0053._Maximum_Subarray.md
│ │ │ ├── 0054._Spiral_Matrix.md
│ │ │ ├── 0055._Jump_Game.md
│ │ │ ├── 0056._Merge_Intervals.md
│ │ │ ├── 0058._Length_of_Last_Word.md
│ │ │ ├── 0061._Rotate_List.md
│ │ │ ├── 0062._Unique_Paths.md
│ │ │ ├── 0064._Minimum_Path_Sum.md
│ │ │ ├── 0066._Plus_One.md
│ │ │ ├── 0067._Add_Binary.md
│ │ │ ├── 0074._Search_a_2D_Matrix.md
│ │ │ ├── 0077._Combinations.md
│ │ │ ├── 0079._Search_Word.md
│ │ │ ├── 0083._Remove_Duplicates_From_Sorted_List.md
│ │ │ ├── 0094._Binary_Tree_Inorder_Traversal.md
│ │ │ ├── 0098._Validate_Binary_Search_Tree.md
│ │ │ ├── 0100._Same_Tree.md
│ │ │ ├── 0101._Symmetric_Tree.md
│ │ │ ├── 0104._Maximum_Depth_of_Binary_Tree.md
│ │ │ ├── 0106._Construct_Binary_Tree_From_Inorder_And_Postorder_Traversal.md
│ │ │ ├── 0120._Triangle.md
│ │ │ ├── 0121._Best_Time_To_Buy_And_Sell_Stock.md
│ │ │ ├── 0141._Linked_List_Cycle.md
│ │ │ ├── 0146._LRU_Cache.md
│ │ │ ├── 0167._Two_Sum_II_-_Input_array_is_sorted.md
│ │ │ ├── 0167._Two_Sum_II_Input_Array_is_Sorted.md
│ │ │ ├── 0171._Excel_Sheet_Column_Number.md
│ │ │ ├── 0179._Largest_Number.md
│ │ │ ├── 0198._House_Robber.md
│ │ │ ├── 0203._Remove_Linked_List_Elements.md
│ │ │ ├── 0206._Reverse_Linked_List.md
│ │ │ ├── 0209._Minimum_Size_Subarray_Sum.md
│ │ │ ├── 0258._Add_Digits.md
│ │ │ ├── 0320._Coin_Change.md
│ │ │ ├── 0347._Top_K_Frequent_Elements.md
│ │ │ ├── 0402._Remove_K_Digits.md
│ │ │ ├── 0406._Queue_Reconstruction_By_Height.md
│ │ │ ├── 0485._Max_Consecutive_Ones.md
│ │ │ ├── 0539._Minimum_Time_Difference.md
│ │ │ ├── 0581._Shortest_Unsorted_Continuous_Subarray.md
│ │ │ ├── 0881._Boats_to_Save_People.md
│ │ │ ├── 0997._Find_The_Town_Judge.md
│ │ │ ├── 1025._Divisor_Game.md
│ │ │ ├── 1130._Minimum_Cost_Tree_From_Leaf_Values.md
│ │ │ ├── 303._Range_Sum_Query_Immutable.md
│ │ │ ├── README.md
│ │ │ ├── SUMMARY.md
│ │ │ └── book.json
│ │ └── python/
│ │ ├── 001._two_sum.md
│ │ ├── 002._add_two_numbers.md
│ │ ├── 003._longest_substring_without_repeating_characters.md
│ │ ├── 004._median_of_two_sorted_arrays.md
│ │ ├── 005._longest_palindromic_substring.md
│ │ ├── 006._ZigZag_Conversion.md
│ │ ├── 007._Reverse_Integer.md
│ │ ├── 008._string_to_integer_(atoi).md
│ │ ├── 009._Palindrome_Number.md
│ │ ├── 010._regular_expression_matching.md
│ │ ├── 011._container_with_most_water.md
│ │ ├── 012._Integer_to_Roman.md
│ │ ├── 013._Roman_to_Integer.md
│ │ ├── 014._longest_common_prefix.md
│ │ ├── 015._3sum.md
│ │ ├── 016._3sum_closest.md
│ │ ├── 017._letter_combinations_of_a_phone_number.md
│ │ ├── 018._4sum.md
│ │ ├── 019._remove_nth_node_from_end_of_list.md
│ │ ├── 020._valid_parentheses.md
│ │ ├── 021._merge_two_sorted_lists.md
│ │ ├── 022._generate_parentheses.md
│ │ ├── 023._merge_k_sorted_lists.md
│ │ ├── 024._swap_nodes_in_pairs.md
│ │ ├── 026._Remove_Duplicates_from_Sorted_Array.md
│ │ ├── 027._Remove_Element.md
│ │ ├── 028._implement_strstr.md
│ │ ├── 030._Substring_with_Concatenation_of_All_Words.md
│ │ ├── 031._next_permutation.md
│ │ ├── 032._longest_valid_parentheses.md
│ │ ├── 033._search_in_rotated_sorted_array.md
│ │ ├── 034._Search_for_a_Range.md
│ │ ├── 035._search_insert_position.md
│ │ ├── 038._Count_and_Say.md
│ │ ├── 039._combination_sum.md
│ │ ├── 040._combination_sum_ii.md
│ │ ├── 041._First_Missing_Positive.md
│ │ ├── 042._trapping_rain_water.md
│ │ ├── 043._multiply_strings.md
│ │ ├── 044._wildcard_matching.md
│ │ ├── 045._Jump_Game_II.md
│ │ ├── 046._permutations.md
│ │ ├── 047._permutations_ii.md
│ │ ├── 048._rotate_image.md
│ │ ├── 049._group_anagrams_python.md
│ │ ├── 050._pow(x,_n).md
│ │ ├── 051._n-queens.md
│ │ ├── 052._n-queens_ii.md
│ │ ├── 053._maximum_subarray.md
│ │ ├── 054._spiral_matrix.md
│ │ ├── 055._jump_game.md
│ │ ├── 056._Merge_Intervals.md
│ │ ├── 058._length_of_last_word.md
│ │ ├── 059._spiral_matrix_ii.md
│ │ ├── 060._permutation_sequence.md
│ │ ├── 061._rotate_list.md
│ │ ├── 062._unique_paths.md
│ │ ├── 064._minimum_path_sum.md
│ │ ├── 065.unique_paths_ii.md
│ │ ├── 066._plus_one.md
│ │ ├── 067._add_binary.md
│ │ ├── 069._sqrt(x).md
│ │ ├── 070._Climbing_Stairs.md
│ │ ├── 072._edit_distance.md
│ │ ├── 073._Set_Matrix_Zeroes.md
│ │ ├── 074._search_a_2d_matrix.md
│ │ ├── 075._sort_colors.md
│ │ ├── 076._Minimum_Window_Substring.md
│ │ ├── 077._combinations.md
│ │ ├── 078._Subsets.md
│ │ ├── 079._word_search.md
│ │ ├── 082._remove_duplicates_from_sorted_list_ii.md
│ │ ├── 083._remove_duplicates_from_sorted_list.md
│ │ ├── 086._partition_list.md
│ │ ├── 088._merge_sorted_array.md
│ │ ├── 089._gray_code.md
│ │ ├── 090._subsets_ii.md
│ │ ├── 091._decode_ways.md
│ │ ├── 092._reverse_linked_list_ii.md
│ │ ├── 093._restore_ip_addresses.md
│ │ ├── 094._binary_tree_inorder_traversal.md
│ │ ├── 096._unique_binary_search_trees.md
│ │ ├── 098._validate_binary_search_tree.md
│ │ ├── 100._same_tree.md
│ │ ├── 101._symmetric_tree.md
│ │ ├── 102._binary_tree_level_order_traversal.md
│ │ ├── 103._binary_tree_zigzag_level_order_traversal.md
│ │ ├── 104._maximum_depth_of_binary_tree.md
│ │ ├── 105._construct_binary_tree_from_preorder_and_inorder_traversal.md
│ │ ├── 106._construct_binary_tree_from_inorder_and_postorder_traversal.md
│ │ ├── 107._binary_tree_level_order_traversal_ii.md
│ │ ├── 108._convert_sorted_array_to_binary_search_tree.md
│ │ ├── 109._convert_sorted_list_to_binary_search_tree.md
│ │ ├── 110._balanced_binary_tree.md
│ │ ├── 111._minimum_depth_of_binary_tree.md
│ │ ├── 112._path_sum.md
│ │ ├── 113._path_sum_ii.md
│ │ ├── 114._flatten_binary_tree_to_linked_list.md
│ │ ├── 116._populating_next_right_pointers_in_each_node.md
│ │ ├── 117._Populating_Next_Right_Pointers_in_Each_Node_II.md
│ │ ├── 118._pascal's_triangle.md
│ │ ├── 119._Pascal's_Triangle_II.md
│ │ ├── 120._Triangle.md
│ │ ├── 121._Best_Time_to_Buy_and_Sell_Stock.md
│ │ ├── 124._Binary_Tree_Maximum_Path_Sum.md
│ │ ├── 125._valid_palindrome.md
│ │ ├── 126._Word_Ladder_II.md
│ │ ├── 127._word_ladder.md
│ │ ├── 128._Longest_Consecutive_Sequence.md
│ │ ├── 129._sum_root_to_leaf_numbers.md
│ │ ├── 130._surrounded_regions.md
│ │ ├── 131._palindrome_partitioning.md
│ │ ├── 133._clone_graph.md
│ │ ├── 136._single_number.md
│ │ ├── 139._word_break.md
│ │ ├── 140._word_break_ii.md
│ │ ├── 141._linked_list_cycle.md
│ │ ├── 142_Linked_List_Cycle_II.md
│ │ ├── 143._reorder_list.md
│ │ ├── 144._binary_tree_preorder_traversal.md
│ │ ├── 145._binary_tree_postorder_traversal.md
│ │ ├── 147._insertion_sort_list.md
│ │ ├── 148._sort_list.md
│ │ ├── 150._evaluate_reverse_polish_notation.md
│ │ ├── 151._reverse_words_in_a_string.md
│ │ ├── 152._maximum_product_subarray.md
│ │ ├── 153._find_minimum_in_rotated_sorted_array.md
│ │ ├── 155._min_stack.md
│ │ ├── 157._Read_N_Characters_Given_Read4.md
│ │ ├── 158._Read_N_Characters_Given_Read4_II_-_Call_multiple_times.md
│ │ ├── 159._Longest_Substring_with_At_Most_Two_Distinct_Characters.md
│ │ ├── 160._intersection_of_two_linked_lists.md
│ │ ├── 162._find_peak_element.md
│ │ ├── 165._compare_version_numbers.md
│ │ ├── 166._Fraction_to_Recurring_Decimal.md
│ │ ├── 167._two_sum_ii_-_input_array_is_sorted.md
│ │ ├── 168._excel_sheet_column_title.md
│ │ ├── 169._majority_element.md
│ │ ├── 171._excel_sheet_column_number.md
│ │ ├── 173._binary_search_tree_iterator.md
│ │ ├── 179._Largest_Number.md
│ │ ├── 182._duplicate_emails.md
│ │ ├── 189._rotate_array.md
│ │ ├── 191._number_of_1_bits.md
│ │ ├── 198._house_robber.md
│ │ ├── 199._binary_tree_right_side_view.md
│ │ ├── 200._number_of_islands.md
│ │ ├── 203._remove_linked_list_elements.md
│ │ ├── 204._count_primes.md
│ │ ├── 205._isomorphic_strings.md
│ │ ├── 206._reverse_linked_list.md
│ │ ├── 207._course_schedule.md
│ │ ├── 208._implement_trie_(prefix_tree).md
│ │ ├── 210._course_schedule_ii.md
│ │ ├── 211._Add_and_Search_Word_-_Data_structure_design.md
│ │ ├── 213._house_robber_ii.md
│ │ ├── 216._combination_sum_iii.md
│ │ ├── 217._contains_duplicate.md
│ │ ├── 218._The_Skyline_Problem.md
│ │ ├── 219._contains_duplicate_ii.md
│ │ ├── 221._maximal_square.md
│ │ ├── 222._count_complete_tree_nodes.md
│ │ ├── 223._rectangle_area.md
│ │ ├── 224._Basic_Calculator.md
│ │ ├── 225._implement_stack_using_queues.md
│ │ ├── 226._invert_binary_tree.md
│ │ ├── 227._basic_calculator_ii.md
│ │ ├── 228._summary_ranges.md
│ │ ├── 229._majority_element_ii.md
│ │ ├── 230._kth_smallest_element_in_a_bst.md
│ │ ├── 231._Power_of_Two.md
│ │ ├── 232._implement_queue_using_stacks.md
│ │ ├── 234._palindrome_linked_list.md
│ │ ├── 235._lowest_common_ancestor_of_a_binary_search_tree.md
│ │ ├── 236._lowest_common_ancestor_of_a_binary_tree.md
│ │ ├── 237._delete_node_in_a_linked_list.md
│ │ ├── 238._product_of_array_except_self.md
│ │ ├── 240._search_a_2d_matrix_ii.md
│ │ ├── 242._valid_anagram.md
│ │ ├── 249._Group_Shifted_Strings.md
│ │ ├── 252._Meeting_Rooms.md
│ │ ├── 255._Verify_Preorder_Sequence_in_Binary_Search_Tree.md
│ │ ├── 256._Paint_House.md
│ │ ├── 257._binary_tree_paths.md
│ │ ├── 258._Add_Digits.md
│ │ ├── 261._Graph_Valid_Tree.md
│ │ ├── 263._ugly_number.md
│ │ ├── 264._ugly_number_ii.md
│ │ ├── 265._Paint_House_II.md
│ │ ├── 266._Palindrome_Permutation.md
│ │ ├── 267._Palindrome_Permutation_II.md
│ │ ├── 268._missing_number.md
│ │ ├── 270._Closest_Binary_Search_Tree_Value.md
│ │ ├── 276._Paint_Fence.md
│ │ ├── 277._Find_the_Celebrity.md
│ │ ├── 278._First_Bad_Version.md
│ │ ├── 279._perfect_squares.md
│ │ ├── 280._Wiggle_Sort.md
│ │ ├── 283._move_zeroes.md
│ │ ├── 285._inorder_successor_in_bst.md
│ │ ├── 286._Walls_and_Gates.md
│ │ ├── 287._Find_the_Duplicate_Number.md
│ │ ├── 289._game_of_life.md
│ │ ├── 290._word_pattern.md
│ │ ├── 292._nim_game.md
│ │ ├── 293._Flip_Game.md
│ │ ├── 296._Best_Meeting_Point.md
│ │ ├── 298._Binary_Tree_Longest_Consecutive_Sequence.md
│ │ ├── 299._bulls_and_cows.md
│ │ ├── 300._longest_increasing_subsequence.md
│ │ ├── 303._range_sum_query_-_immutable.md
│ │ ├── 316._Remove_Duplicate_Letters.md
│ │ ├── 319._Bulb_Switcher.md
│ │ ├── 322._Coin_Change.md
│ │ ├── 323._number_of_connected_components_in_an_undirected_graph.md
│ │ ├── 324._Wiggle_Sort_II.md
│ │ ├── 326._power_of_three.md
│ │ ├── 328._odd_even_linked_list.md
│ │ ├── 334._increasing_triplet_subsequence.md
│ │ ├── 337._house_robber_iii.md
│ │ ├── 338._Counting_Bits.md
│ │ ├── 339._Nested_List_Weight_Sum.md
│ │ ├── 341._Flatten_Nested_List_Iterator.md
│ │ ├── 342._Power_of_Four.md
│ │ ├── 344._reverse_string.md
│ │ ├── 345._Reverse_Vowels_of_a_String.md
│ │ ├── 349._intersection_of_two_arrays.md
│ │ ├── 350._intersection_of_two_arrays_ii.md
│ │ ├── 353._Design_Snake_Game.md
│ │ ├── 361._Bomb_Enemy.md
│ │ ├── 364._Nested_List_Weight_Sum_II.md
│ │ ├── 366._Find_Leaves_of_Binary_Tree.md
│ │ ├── 367._valid_perfect_square.md
│ │ ├── 369._Plus_One_Linked_List.md
│ │ ├── 371._sum_of_two_integers.md
│ │ ├── 374._Guess_Number_Higher_or_Lower.md
│ │ ├── 377._combination_sum_iv.md
│ │ ├── 378._kth_smallest_element_in_a_sorted_matrix.md
│ │ ├── 380._Insert_Delete_GetRandom_O(1).md
│ │ ├── 381._Insert_Delete_GetRandom_O(1)_-_Duplicates_allowed.md
│ │ ├── 382._linked_list_random_node.md
│ │ ├── 383._ransom_note.md
│ │ ├── 384._Shuffle_an_Array.md
│ │ ├── 386._Lexicographical_Numbers.md
│ │ ├── 387._first_unique_character_in_a_string.md
│ │ ├── 388._Longest_Absolute_File_Path.md
│ │ ├── 389._find_the_difference.md
│ │ ├── 392._is_subsequence.md
│ │ ├── 394._decode_string.md
│ │ ├── 400._Nth_Digit.md
│ │ ├── 401._binary_watch.md
│ │ ├── 404._sum_of_left_leaves.md
│ │ ├── 405._Convert_a_Number_to_Hexadecimal.md
│ │ ├── 406._Queue_Reconstruction_by_Height.md
│ │ ├── 412._fizz_buzz.md
│ │ ├── 413._Arithmetic_Slices.md
│ │ ├── 414._third_maximum_number.md
│ │ ├── 415._add_strings.md
│ │ ├── 416._Partition_Equal_Subset_Sum.md
│ │ ├── 421._Maximum_XOR_of_Two_Numbers_in_an_Array.md
│ │ ├── 422._Valid_Word_Square.md
│ │ ├── 434._number_of_segments_in_a_string.md
│ │ ├── 435._Non-overlapping_Intervals.md
│ │ ├── 437._path_sum_iii.md
│ │ ├── 438._Find_All_Anagrams_in_a_String.md
│ │ ├── 439._Ternary_Expression_Parser.md
│ │ ├── 441._arranging_coins.md
│ │ ├── 448._Find_All_Numbers_Disappeared_in_an_Array.md
│ │ ├── 450._Delete_Node_in_a_BST.md
│ │ ├── 453._Minimum_Moves_to_Equal_Array_Elements.md
│ │ ├── 459._Repeated_Substring_Pattern.md
│ │ ├── 461._Hamming_Distance.md
│ │ ├── 463._Island_Perimeter.md
│ │ ├── 467._Unique_Substrings_in_Wraparound_String.md
│ │ ├── 469._Convex_Polygon.md
│ │ ├── 476._Number_Complement.md
│ │ ├── 477._Total_Hamming_Distance.md
│ │ ├── 485._Max_Consecutive_Ones.md
│ │ ├── 494._Target_Sum.md
│ │ ├── 536._Construct_Binary_Tree_from_String.md
│ │ ├── 587._Erect_the_Fence.md
│ │ ├── 599._Minimum_Index_Sum_of_Two_Lists.md
│ │ ├── 606._Construct_String_from_Binary_Tree.md
│ │ ├── 611._Valid_Triangle_Number.md
│ │ ├── 646._Maximum_Length_of_Pair_Chain.md
│ │ ├── 647._Palindromic_Substrings.md
│ │ ├── 657._Judge_Route_Circle.md
│ │ ├── 665._Non-decreasing_Array.md
│ │ ├── 672._Bulb_Switcher_II.md
│ │ ├── 681._Next_Closest_Time.md
│ │ ├── 682._Baseball_Game.md
│ │ ├── 685._Redundant_Connection_II.md
│ │ ├── 687._Longest_Univalue_Path.md
│ │ ├── 693._Binary_Number_with_Alternating_Bits.md
│ │ ├── 701._Insert_into_a_Binary_Search_Tree.md
│ │ ├── 707._Design_Linked_List.md
│ │ ├── 740._delete_and_earn.md
│ │ ├── 760._Find_Anagram_Mappings.md
│ │ ├── 774._Minimize_Max_Distance_to_Gas_Station.md
│ │ ├── 777._Swap_Adjacent_in_LR_String.md
│ │ ├── 844._Backspace_String_Compare.md
│ │ ├── README.md
│ │ └── SUMMARY.md
│ └── think-dast-zh/
│ ├── 0.md
│ ├── 1.md
│ ├── 10.md
│ ├── 11.md
│ ├── 12.md
│ ├── 13.md
│ ├── 14.md
│ ├── 15.md
│ ├── 16.md
│ ├── 17.md
│ ├── 2.md
│ ├── 3.md
│ ├── 4.md
│ ├── 5.md
│ ├── 6.md
│ ├── 7.md
│ ├── 8.md
│ ├── 9.md
│ ├── README.md
│ └── SUMMARY.md
├── index.html
└── update.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# dotenv
.env
# virtualenv
.venv
venv/
ENV/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.DS_Store
# gitbook
_book
# node.js
node_modules
# windows
Thumbs.db
# word
~$*.docx
~$*.doc
================================================
FILE: .nojekyll
================================================
================================================
FILE: 404.html
================================================
---
permalink: /404.html
---
================================================
FILE: CNAME
================================================
algo.apachecn.org
================================================
FILE: Dockerfile
================================================
FROM httpd:2.4
COPY ./ /usr/local/apache2/htdocs/
================================================
FILE: NAV.md
================================================
+ 编程
+ [JavaTPoint 编程语言中文教程📚](https://apachecn.github.io/javatpoint-prog-zh)
+ [JavaTPoint .NET 中文教程📚](https://apachecn.github.io/javatpoint-dotnet-zh)
+ [JavaTPoint Java 中文教程📚](https://apachecn.github.io/javatpoint-java-zh)
+ [JavaTPoint Python 中文教程📚](https://apachecn.github.io/javatpoint-python-zh)
+ [GeeksForGeeks 编程语言杂项中文教程📚](https://apachecn.github.io/geeksforgeeks-lang-misc-zh)
+ [GeeksForGeeks C# 中文教程📚](https://apachecn.github.io/geeksforgeeks-csharp-zh)
+ [GeeksForGeeks Scala 中文教程📚](https://apachecn.github.io/geeksforgeeks-scala-zh)
+ [GeeksForGeeks Python 中文教程📚](https://apachecn.github.io/geeksforgeeks-python-zh)
+ [GeeksForGeeks C/C++ 中文教程📚](https://apachecn.github.io/geeksforgeeks-c-cpp-zh)
+ [GeeksForGeeks Java 中文教程📚](https://apachecn.github.io/geeksforgeeks-java-zh)
+ [GeeksForGeeks JavaScript 中文教程📚](https://apachecn.github.io/geeksforgeeks-js-zh)
+ [ApacheCN C# 译文集📚](https://apachecn.github.io/apachecn-csharp-zh)
+ [ApacheCN C# 译文集(二)📚](https://apachecn.github.io/apachecn-csharp-zh-pt2)
+ [ApacheCN C# 译文集(三)📚](https://apachecn.github.io/apachecn-csharp-zh-pt3)
+ [ApacheCN C# 译文集(四)📚](https://apachecn.github.io/apachecn-csharp-zh-pt4)
+ [ApacheCN Golang 译文集📚](https://apachecn.github.io/apachecn-golang-zh)
+ [ApacheCN Golang 译文集(二)📚](https://apachecn.github.io/apachecn-golang-zh-pt2)
+ [ApacheCN C/C++ 译文集📚](https://apachecn.github.io/apachecn-c-cpp-zh)
+ [ApacheCN C/C++ 译文集(二)📚](https://apachecn.github.io/apachecn-c-cpp-zh-pt2)
+ [ApacheCN C/C++ 译文集(三)📚](https://apachecn.github.io/apachecn-c-cpp-zh-pt3)
+ [ApacheCN Java 译文集📚](https://apachecn.github.io/apachecn-java-zh)
+ [ApacheCN Java 译文集(二)📚](https://apachecn.github.io/apachecn-java-zh-pt2)
+ [ApacheCN Java 译文集(三)📚](https://apachecn.github.io/apachecn-java-zh-pt3)
+ [ApacheCN JavaScript 译文集📚](https://apachecn.github.io/apachecn-js-zh)
+ [ApacheCN JavaScript 译文集(二)📚](https://apachecn.github.io/apachecn-js-zh-pt2)
+ [ApacheCN JavaScript 译文集(三)📚](https://apachecn.github.io/apachecn-js-zh-pt3)
+ [ApacheCN JavaScript 译文集(四)📚](https://apachecn.github.io/apachecn-js-zh-pt4)
+ [ApacheCN Python 译文集📚](https://apachecn.github.io/apachecn-python-zh)
+ [ApacheCN Python 译文集(二)📚](https://apachecn.github.io/apachecn-python-zh-pt2)
+ [ApacheCN Python 译文集(三)📚](https://apachecn.github.io/apachecn-python-zh-pt3)
+ [ApacheCN Python 译文集(四)📚](https://apachecn.github.io/apachecn-python-zh-pt4)
+ [ApacheCN Ruby 译文集📚](https://apachecn.github.io/apachecn-ruby-zh)
+ [BeginnersBook 中文系列教程📚](https://apachecn.github.io/beginnersbook-zh)
+ [JavaScript 编程精解 中文第三版](https://apachecn.github.io/eloquent-js-3e-zh)
+ [Guru99 中文系列教程📚🚧](https://apachecn.github.io/guru99-zh)
+ [HowToDoInJava 中文系列教程📚](https://apachecn.github.io/howtodoinjava-zh)
+ [OverIQ 中文系列教程📚](https://apachecn.github.io/overiq-zh)
+ [LearnETutroials 中文系列教程📚](https://apachecn.github.io/learnetutorials-zh)
+ [StudyTonight 中文系列教程📚](https://apachecn.github.io/studytonight-zh)
+ [TutorialGateway 中文系列教程📚](https://apachecn.github.io/tutorialgateway-zh)
+ [TutorialGateway BI 中文系列教程📚](https://apachecn.github.io/tutorialgateway-bi-zh)
+ [TutorialsTeacher 中文系列教程📚](https://apachecn.github.io/tutorialsteacher-zh)
+ [通过示例学 Golang 2020 中文版](https://apachecn.github.io/golang-by-example-2020-zh)
+ [写给不耐烦程序员的 JavaScript🚧](https://apachecn.github.io/impatient-js-zh)
+ [JavaBeginnersTutorial 中文系列教程📚](https://apachecn.github.io/jbt-zh)
+ [JavaTutorialNetwork 中文系列教程📚](https://apachecn.github.io/jtn-zh)
+ [笨办法学C 中文版](https://apachecn.github.io/lcthw-zh)
+ [笨办法学 Python · 续 中文版](https://apachecn.github.io/lmpythw-zh)
+ [Programiz 中文系列教程📚](https://apachecn.github.io/programiz-zh)
+ [PythonBasics 中文系列教程📚](https://apachecn.github.io/pythonbasics-zh)
+ [PythonGuru 中文系列教程📚](https://apachecn.github.io/pythonguru-zh)
+ [PythonSpot 中文系列教程📚](https://apachecn.github.io/pythonspot-zh)
+ [Think Python](https://apachecn.github.io/think-py-2e-zh)
+ [ZetCode 中文系列教程📚](https://apachecn.github.io/zetcode-zh)
+ 前端
+ [JavaTPoint 移动开发中文教程📚](https://apachecn.github.io/javatpoint-mobi-zh)
+ [GeeksForGeeks Web 杂项中文教程📚](https://apachecn.github.io/geeksforgeeks-web-misc-zh)
+ [GeeksForGeeks Angular/Vue/React 中文教程📚](https://apachecn.github.io/geeksforgeeks-ng-vue-react-zh)
+ [GeeksForGeeks jQuery 中文教程📚](https://apachecn.github.io/geeksforgeeks-jquery-zh)
+ [GeeksForGeeks CSS 中文教程📚](https://apachecn.github.io/geeksforgeeks-css-zh)
+ [GeeksForGeeks HTML 中文教程📚](https://apachecn.github.io/geeksforgeeks-html-zh)
+ [ApacheCN Vue 译文集📚](https://apachecn.github.io/apachecn-vue-zh)
+ [ApacheCN Angular 译文集📚](https://apachecn.github.io/apachecn-angular-zh)
+ [ApacheCN React 译文集📚](https://apachecn.github.io/apachecn-react-zh)
+ [ApacheCN jQuery 译文集📚](https://apachecn.github.io/apachecn-jquery-zh)
+ [ApacheCN jQuery 译文集(二)📚](https://apachecn.github.io/apachecn-jquery-zh-pt2)
+ 后端/大数据
+ [JavaTPoint 大数据中文教程📚](https://apachecn.github.io/javatpoint-bigdata-zh)
+ [JavaTPoint Web 开发中文教程📚](https://apachecn.github.io/javatpoint-web-zh)
+ [JavaTPoint 数据库中文教程📚](https://apachecn.github.io/javatpoint-db-zh)
+ [JavaTPoint PHP 中文教程📚](https://apachecn.github.io/javatpoint-php-zh)
+ [GeeksForGeeks ASP 中文教程📚](https://apachecn.github.io/geeksforgeeks-asp-zh)
+ [GeeksForGeeks SQL 中文教程📚](https://apachecn.github.io/geeksforgeeks-sql-zh)
+ [GeeksForGeeks NodeJS 中文教程📚](https://apachecn.github.io/geeksforgeeks-nodejs-zh)
+ [GeeksForGeeks PHP 中文教程📚](https://apachecn.github.io/geeksforgeeks-php-zh)
+ [ApacheCN 数据库译文集📚](https://apachecn.github.io/apachecn-db-zh)
+ [ApacheCN 数据库译文集(二)📚](https://apachecn.github.io/apachecn-db-zh-pt2)
+ [ApacheCN Python Web 译文集📚](https://apachecn.github.io/apachecn-pythonweb-zh)
+ [ApacheCN Python Web 译文集(二)📚](https://apachecn.github.io/apachecn-pythonweb-zh-pt2)
+ [ApacheCN Asp.NET 译文集📚](https://apachecn.github.io/apachecn-asp-dotnet-zh)
+ [ApacheCN Asp.NET 译文集(二)📚](https://apachecn.github.io/apachecn-asp-dotnet-zh-pt2)
+ [ApacheCN Asp.NET 译文集(三)📚](https://apachecn.github.io/apachecn-asp-dotnet-zh-pt3)
+ [ApacheCN Asp.NET 译文集(四)📚](https://apachecn.github.io/apachecn-asp-dotnet-zh-pt4)
+ [ApacheCN NodeJS 译文集📚](https://apachecn.github.io/apachecn-node-zh)
+ [ApacheCN NodeJS 译文集(二)📚](https://apachecn.github.io/apachecn-node-zh-pt2)
+ [ApacheCN PHP 译文集📚](https://apachecn.github.io/apachecn-php-zh)
+ [ApacheCN PHP 译文集(二)📚](https://apachecn.github.io/apachecn-php-zh-pt2)
+ [ApacheCN 大数据译文集(二)📚](https://apachecn.github.io/apachecn-bigdata-zh-pt2)
+ [ApacheCN 大数据译文集(三)📚](https://apachecn.github.io/apachecn-bigdata-zh-pt3)
+ [ApacheCN 大数据译文集📚](https://apachecn.github.io/apachecn-bigdata-zh)
+ [ApacheCN Java Web 译文集📚](https://apachecn.github.io/apachecn-javaweb-zh)
+ [ApacheCN Java Web 译文集(二)📚](https://apachecn.github.io/apachecn-javaweb-zh-pt2)
+ [Airflow 中文文档](https://apachecn.github.io/airflow-doc-zh)
+ [Elasticsearch 5.4 中文文档](https://apachecn.github.io/elasticsearch-doc-zh)
+ [Flink 中文文档](https://apachecn.github.io/flink-doc-zh)
+ [HBase™ 中文参考指南 3.0🚧](https://apachecn.github.io/hbase-doc-zh)
+ [HighScalability 中文示例📚🚧](https://apachecn.github.io/highscalability-examples-zh)
+ [Kibana 5.2 中文文档](https://apachecn.github.io/kibana-doc-zh)
+ [Kudu 1.4.0 中文文档](https://apachecn.github.io/kudu-doc-zh)
+ [Apache Spark 官方文档中文版](https://apachecn.github.io/spark-doc-zh)
+ [Apache Kafka 官方文档中文版](https://apachecn.github.io/kafka-site-zh)
+ [Spring Boot 1.5.2 中文文档](https://apachecn.github.io/spring-boot-doc-zh)
+ [Storm 1.1.0 中文文档](https://apachecn.github.io/storm-doc-zh)
+ [Zeppelin 0.7.2 中文文档](https://apachecn.github.io/zeppelin-doc-zh)
+ 工具
+ [JavaTPoint 实用工具中文教程📚](https://apachecn.github.io/javatpoint-util-zh)
+ [ApacheCN DevOps 译文集📚](https://apachecn.github.io/apachecn-devops-zh)
+ [ApacheCN DevOps 译文集(二)📚](https://apachecn.github.io/apachecn-devops-zh-pt2)
+ [ApacheCN DevOps 译文集(三)📚](https://apachecn.github.io/apachecn-devops-zh-pt3)
+ [ApacheCN DevOps 译文集(四)📚](https://apachecn.github.io/apachecn-devops-zh-pt4)
+ [ApacheCN DevOps 译文集(五)📚](https://apachecn.github.io/apachecn-devops-zh-pt5)
+ [ApacheCN Linux 译文集📚](https://apachecn.github.io/apachecn-linux-zh)
+ [ApacheCN Linux 译文集(二)📚](https://apachecn.github.io/apachecn-linux-zh-pt2)
+ [ApacheCN Linux 译文集(三)📚](https://apachecn.github.io/apachecn-linux-zh-pt3)
+ [Cython 3.0 中文文档🚧](https://apachecn.github.io/cython-doc-zh)
+ [Git 中文参考🚧](https://apachecn.github.io/git-doc-zh)
+ [Gitlab 中文文档🚧](https://apachecn.github.io/gitlab-doc-zh)
+ [笨办法学 Linux 中文版](https://apachecn.github.io/llthw-zh)
+ [Numba 0.44 中文文档🚧](https://apachecn.github.io/numba-doc-zh)
+ [PyQt4 中文文档🚧](https://apachecn.github.io/pyqt4-doc-zh)
+ [Scrapy 1.6 中文文档](https://apachecn.github.io/scrapy-doc-zh)
+ 数据科学
+ [ApacheCN 数据科学译文集📚](https://apachecn.github.io/apachecn-ds-zh)
+ [ApacheCN 数据科学译文集(二)📚](https://apachecn.github.io/apachecn-ds-zh-pt2)
+ [ApacheCN 数据科学译文集(三)📚](https://apachecn.github.io/apachecn-ds-zh-pt3)
+ [ApacheCN 数据科学译文集📚](https://apachecn.github.io/apachecn-ds-zh)
+ [MIT 18.03 面向初学者的微积分🚧](https://apachecn.github.io/calc4b-zh)
+ [UCB Data8 计算与推断思维](https://apachecn.github.io/data8-textbook-zh)
+ [数据可视化的基础知识](https://apachecn.github.io/dataviz-zh)
+ [数据科学和人工智能技术笔记](https://apachecn.github.io/ds-ai-tech-notes)
+ [数据科学 IPython 笔记本📚](https://apachecn.github.io/ds-ipynb-zh)
+ [UCB DS100 数据科学的原理与技巧🚧](https://apachecn.github.io/ds100-textbook-zh)
+ [ApacheCN 数据科学和人工智能知识库](https://apachecn.github.io/dsai-wiki)
+ [Matplotlib 用户指南](https://apachecn.github.io/matplotlib-doc-zh)
+ [MIT 18.06 线性代数笔记](https://apachecn.github.io/mit-18.06-linalg-notes)
+ [利用 Python 进行数据分析 · 第 2 版](https://apachecn.github.io/pyda-2e-zh)
+ [QuantLearning](https://apachecn.github.io/quant-learning)
+ [seaborn 0.9 中文文档](https://apachecn.github.io/seaborn-doc-zh)
+ [社交媒体挖掘 - 翻译版](https://apachecn.github.io/socialmediamining-zh)
+ [斯坦福 Stats60 21 世纪的统计思维🚧](https://apachecn.github.io/stats-thinking-21-zh)
+ [复杂性思维 中文第二版](https://apachecn.github.io/think-comp-2e-zh)
+ [PyMiner 开发者指南](https://apachecn.github.io/pyminer-dev-guide)
+ 人工智能
+ [JavaTPoint 数据科学与人工智能中文教程📚](https://apachecn.github.io/javatpoint-dsai-zh)
+ [GeeksForGeeks 人工智能中文教程📚](https://apachecn.github.io/geeksforgeeks-ai-zh)
+ [AILearning📚](https://apachecn.github.io/ailearning)
+ [ApacheCN 计算机视觉译文集📚](https://apachecn.github.io/apachecn-cv-zh)
+ [ApacheCN 计算机视觉译文集(二)📚](https://apachecn.github.io/apachecn-cv-zh-pt2)
+ [ApacheCN 深度学习译文集📚](https://apachecn.github.io/apachecn-dl-zh)
+ [ApacheCN 深度学习译文集(二)📚](https://apachecn.github.io/apachecn-dl-zh-pt2)
+ [ApacheCN 深度学习译文集(三)📚](https://apachecn.github.io/apachecn-dl-zh-pt3)
+ [ApacheCN 机器学习译文集📚](https://apachecn.github.io/apachecn-ml-zh)
+ [ApacheCN 机器学习译文集(二)📚](https://apachecn.github.io/apachecn-ml-zh-pt2)
+ [ApacheCN 机器学习译文集(三)📚](https://apachecn.github.io/apachecn-ml-zh-pt3)
+ [FastText 中文文档](https://apachecn.github.io/fasttext-doc-zh)
+ [面向机器学习的特征工程](https://apachecn.github.io/fe4ml-zh)
+ [Gensim 中文文档](https://apachecn.github.io/gensim-doc-zh)
+ [Sklearn 与 TensorFlow 机器学习实用指南第二版](https://apachecn.github.io/hands-on-ml-2e-zh)
+ [LightGBM 中文文档](https://apachecn.github.io/lightgbm-doc-zh)
+ [Machine Learning Mastery 博客文章翻译📚🚧](https://apachecn.github.io/ml-mastery-zh)
+ [Machine Learning Mastery 博客文章翻译(二)📚🚧](https://apachecn.github.io/ml-mastery-zh-pt2)
+ [Python 自然语言处理 第二版](https://apachecn.github.io/nlp-py-2e-zh)
+ [PyTorch 自然语言处理](https://apachecn.github.io/nlp-pytorch-zh)
+ [台湾大学林轩田机器学习笔记](https://apachecn.github.io/ntu-hsuantienlin-ml)
+ [OpenCV 中文文档 4.0.0](https://apachecn.github.io/opencv-doc-zh)
+ [PythonProgramming.net 系列教程📚](https://apachecn.github.io/python-programming-net-zh)
+ [PyTorch 中文教程](https://apachecn.github.io/pytorch-doc-zh)
+ [scikit-learn (sklearn) 官方文档中文版](https://apachecn.github.io/sklearn-doc-zh)
+ [XGBoost 中文文档](https://apachecn.github.io/xgboost-doc-zh)
+ 计算机科学
+ [JavaTPoint 计算机科学中文教程📚](https://apachecn.github.io/javatpoint-cs-zh)
+ [ApacheCN 数据结构与算法译文集📚](https://apachecn.github.io/apachecn-algo-zh)
+ [ApacheCN 计算机系统译文集📚](https://apachecn.github.io/apachecn-sys-zh)
+ [NUS CS1101s SICP JavaScript 描述🚧](https://apachecn.github.io/sicp-js-zh)
+ [UCB CS61a SICP Python 描述](https://apachecn.github.io/sicp-py-zh)
+ [数据结构思维中文版](https://apachecn.github.io/think-dast-zh)
+ [UIUC CS241 系统编程中文讲义🚧](https://apachecn.github.io/uiuc-cs241-notes-zh)
+ 安全
+ [ApacheCN Kali Linux 译文集📚](https://apachecn.github.io/apachecn-kali-zh)
+ [ApacheCN 网络安全译文集📚](https://apachecn.github.io/apachecn-sec-zh)
+ [ApacheCN 网络安全译文集(二)📚](https://apachecn.github.io/apachecn-sec-zh-pt2)
+ [SecLearning——零组文库备份📚](https://apachecn.github.io/sec-learning)
+ [ApacheCN 安全知识库📚](https://apachecn.github.io/sec-wiki)
+ [Web Hacking 101 中文版](https://apachecn.github.io/web-hacking-101-zh)
+ 其它
+ [生化环材劝退文集](https://apachecn.github.io/bio-chem-env-mat-discourage)
+ [5 分钟商学院精细笔记](https://apachecn.github.io/business-5min-notes)
+ [iBooker 布客](https://apachecn.github.io/home)
+ [iBooker 布客老实人报](https://apachecn.github.io/ibooker-plain-dealer)
+ [使用 Qiskit 学习量子计算 - 翻译版](https://apachecn.github.io/lqcuq-zh)
+ [原则 · 中文版](https://apachecn.github.io/principles-zh)
+ [斯坦福 CS183 & YC 创业课系列中文笔记📚](https://apachecn.github.io/stanford-cs183-notes)
+ [iBooker 团队知识库📚](https://apachecn.github.io/team-wiki)
+ [ApacheCN 技术评论](https://apachecn.github.io/tech-review)
+ [通往财富自由之路精细笔记](https://apachecn.github.io/the-way-to-wealth-freedom-notes)
================================================
FILE: README.md
================================================
# ApacheCN 数据结构与算法译文集
> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
>
> 程序员的双手是魔术师的双手,他们把枯燥无味的代码变成了丰富多彩的软件。——《疯狂的程序员》
* [在线阅读](https://algo.apachecn.org)
* [在线阅读(Gitee)](https://apachecn.gitee.io/apachecn-algo-zh/)
* [ApacheCN 学习资源](http://docs.apachecn.org/)
## 目录
+ [数据结构思维中文版](docs/think-dast-zh/SUMMARY.md)
+ [Leetcode C++ 题解](docs/leetcode/cpp/SUMMARY.md)
+ [Leetcode Java 题解](docs/leetcode/java/SUMMARY.md)
+ [Leetcode JavaScript 题解](docs/leetcode/javascript/SUMMARY.md)
+ [Leetcode Python 题解](docs/leetcode/python/SUMMARY.md)
+ [剑指 Offer Java 题解](docs/jianzhioffer/java/SUMMARY.md)
## 贡献指南
为了不断改进翻译质量,我们特此启动了【翻译、校对、笔记整理活动】,开设了多个校对项目。贡献者校对一章之后可以领取千字2\~4元的奖励。进行中的校对活动请见[活动列表](https://home.apachecn.org/#/docs/activity/docs-activity)。更多详情请联系飞龙(Q562826179,V:wizardforcel)。
## 联系方式
### 负责人
* [飞龙](https://github.com/wizardforcel): 562826179
### 其他
* 在我们的 [apachecn/apachecn-algo-zh](https://github.com/apachecn/apachecn-algo-zh) github 上提 issue.
* 发邮件到 Email: `apachecn@163.com`.
* 在我们的 [组织学习交流群](http://www.apachecn.org/organization/348.html) 中联系群主/管理员即可.
## 下载
### Docker
```
docker pull apachecn0/apachecn-algo-zh
docker run -tid -p :80 apachecn0/apachecn-algo-zh
# 访问 http://localhost:{port} 查看文档
```
### PYPI
```
pip install apachecn-algo-zh
apachecn-algo-zh
# 访问 http://localhost:{port} 查看文档
```
### NPM
```
npm install -g apachecn-algo-zh
apachecn-algo-zh
# 访问 http://localhost:{port} 查看文档
```
## 赞助我们

================================================
FILE: SUMMARY.md
================================================
+ [数据结构思维中文版](docs/think-dast-zh/README.md)
+ [前言](docs/think-dast-zh/0.md)
+ [第一章 接口](docs/think-dast-zh/1.md)
+ [第二章 算法分析](docs/think-dast-zh/2.md)
+ [第三章 `ArrayList`](docs/think-dast-zh/3.md)
+ [第四章 `LinkedList`](docs/think-dast-zh/4.md)
+ [第五章 双链表](docs/think-dast-zh/5.md)
+ [第六章 树的遍历](docs/think-dast-zh/6.md)
+ [第七章 到达哲学](docs/think-dast-zh/7.md)
+ [第八章 索引器](docs/think-dast-zh/8.md)
+ [第九章 `Map`接口](docs/think-dast-zh/9.md)
+ [第十章 哈希](docs/think-dast-zh/10.md)
+ [第十一章 `HashMap`](docs/think-dast-zh/11.md)
+ [第十二章 `TreeMap`](docs/think-dast-zh/12.md)
+ [第十三章 二叉搜索树](docs/think-dast-zh/13.md)
+ [第十四章 持久化](docs/think-dast-zh/14.md)
+ [第十五章 爬取维基百科](docs/think-dast-zh/15.md)
+ [第十六章 布尔搜索](docs/think-dast-zh/16.md)
+ [第十七章 排序](docs/think-dast-zh/17.md)
+ [Leetcode C++ 题解](docs/leetcode/cpp/README.md)
+ [1. Two Sum](docs/leetcode/cpp/0001._Two_Sum.md)
+ [2. Add Two Numbers](docs/leetcode/cpp/0002._Add_Two_Numbers.md)
+ [3. Longest Substring Without Repeating Characters](docs/leetcode/cpp/0003._Longest_Substring_Without_Repeating_Characters.md)
+ [004. Median of Two Sorted Arrays](docs/leetcode/cpp/0004._Median_of_Two_Sorted_Arrays.md)
+ [5. Longest Palindromic Substring](docs/leetcode/cpp/0005._Longest_Palindromic_Substring.md)
+ [6. ZigZag Conversion](docs/leetcode/cpp/0006._ZigZag_Conversion.md)
+ [7. Reverse Integer](docs/leetcode/cpp/0007._Reverse_Integer.md)
+ [8. String to Integer (atoi)](docs/leetcode/cpp/0008._String_to_Integer_(atoi).md)
+ [9. Palindrome Number](docs/leetcode/cpp/0009._Palindrome_Number.md)
+ [10. Regular Expression Matching](docs/leetcode/cpp/0010._Regular_Expression_Matching.md)
+ [11. container with most water](docs/leetcode/cpp/0011._Container_With_Most_Water.md)
+ [12. Integer to Roman](docs/leetcode/cpp/0012._Integer_to_Roman.md)
+ [14. Longest Common Prefix](docs/leetcode/cpp/0014._Longest_Common_Prefix.md)
+ [15. 3sum](docs/leetcode/cpp/0015._3sum.md)
+ [16. 3Sum Closest](docs/leetcode/cpp/0016._3Sum_Closest.md)
+ [17. Letter Combinations of a Phone Number](docs/leetcode/cpp/0017._Letter_Combinations_of_a_Phone_Number.md)
+ [18. 4Sum](docs/leetcode/cpp/0018._4Sum.md)
+ [19. Remove Nth Node From End of List](docs/leetcode/cpp/0019._Remove_Nth_Node_From_End_of_List.md)
+ [20. Valid Parentheses](docs/leetcode/cpp/0020._Valid_Parentheses.md)
+ [21. Merge Two Sorted Lists](docs/leetcode/cpp/0021._Merge_Two_Sorted_Lists.md)
+ [22. Generate Parentheses](docs/leetcode/cpp/0022._Generate_Parentheses.md)
+ [23. merge k sorted lists](docs/leetcode/cpp/0023._Merge_K_Sorted_Lists.md)
+ [24. Swap Nodes in Pairs](docs/leetcode/cpp/0024._Swap_Nodes_in_Pairs.md)
+ [25.reverse nodes in k group](docs/leetcode/cpp/0025._Reverse_Nodes_In_K_Group.md)
+ [26.Remove Duplicates From Sorted Array](docs/leetcode/cpp/0026._Remove_Duplicates_From_Sorted_Array.md)
+ [27.Remove Element](docs/leetcode/cpp/0027._Remove_Element.md)
+ [28.implement strstr](docs/leetcode/cpp/0028._Implement_Strstr.md)
+ [29.divide two integers](docs/leetcode/cpp/0029._Divide_Two_Integers.md)
+ [30.substring with concatenation of all words](docs/leetcode/cpp/0030._Substring_With_Concatenation_Of_All_Words.md)
+ [31.Next Permutatio](docs/leetcode/cpp/0031._Next_Permutatio.md)
+ [32. Longest Valid Parentheses](docs/leetcode/cpp/0032._Longest_Valid_Parentheses.md)
+ [033. Search in Rotated Sorted Array](docs/leetcode/cpp/0033._Search_in_Rotated_Sorted_Array.md)
+ [34. Find First and Last Position of Element in Sorted Array](docs/leetcode/cpp/0034._Find_First_and_Last_Position_of_Element_in_Sorted_Array.md)
+ [???????](docs/leetcode/cpp/0035._Search_Insert_Position.md)
+ [36. Valid Sudoku](docs/leetcode/cpp/0036._Valid_Sudoku.md)
+ [38. Count and Say](docs/leetcode/cpp/0038._Count_and_Say.md)
+ [39. Combination Sum](docs/leetcode/cpp/0039._Combination_Sum.md)
+ [40. Combination Sum II](docs/leetcode/cpp/0040._Combination_Sum_II.md)
+ [041.First Missing Positive](docs/leetcode/cpp/0041._First_Missing_Positive.md)
+ [42. Trapping Rain Water](docs/leetcode/cpp/0042._Trapping_Rain_Water.md)
+ [43. Multiply Strings](docs/leetcode/cpp/0043._Multiply_Strings.md)
+ [44. Wildcard Matching](docs/leetcode/cpp/0044._Wildcard_Matching.md)
+ [045. Jump Game II](docs/leetcode/cpp/0045._Jump_Game_II.md)
+ [46. Permutations](docs/leetcode/cpp/0046._Permutations.md)
+ [47. Permutations II](docs/leetcode/cpp/0047._Permutations_II.md)
+ [49. Group Anagrams](docs/leetcode/cpp/0048._Rotate_Image.md)
+ [49. Group Anagrams](docs/leetcode/cpp/0049._Group_Anagrams.md)
+ [50. powx n](docs/leetcode/cpp/0050._powx_n.md)
+ [51. N-Queens](docs/leetcode/cpp/0051._N-Queens.md)
+ [52. N-Queens II](docs/leetcode/cpp/0052._N-Queens_II.md)
+ [053. Maximum Subarray](docs/leetcode/cpp/0053._Maximum_Subarray.md)
+ [54. Spiral Matrix](docs/leetcode/cpp/0054._Spiral_Matrix.md)
+ [55. Jump Game](docs/leetcode/cpp/0055._Jump_Game.md)
+ [56. Merge Intervals](docs/leetcode/cpp/0056._Merge_Intervals.md)
+ [57. Insert Interval](docs/leetcode/cpp/0057._Insert_Interval.md)
+ [058. Length of Last Word](docs/leetcode/cpp/0058._Length_of_Last_Word.md)
+ [59. Spiral Matrix II](docs/leetcode/cpp/0059._Spiral_Matrix_II.md)
+ [60. Permutation Sequence](docs/leetcode/cpp/0060._Permutation_Sequence.md)
+ [61. Rotate List](docs/leetcode/cpp/0061._Rotate_List.md)
+ [62. Unique Paths](docs/leetcode/cpp/0062._Unique_Paths.md)
+ [63. Unique Paths II](docs/leetcode/cpp/0063._Unique_Paths_II.md)
+ [64. Minimum Path Sum](docs/leetcode/cpp/0064._Minimum_Path_Sum.md)
+ [65. Valid Number](docs/leetcode/cpp/0065._Valid_Number.md)
+ [66. Plus One](docs/leetcode/cpp/0066._Plus_One.md)
+ [68. Text Justification](docs/leetcode/cpp/0068._Text_Justification.md)
+ [69. Sqrt(x)](docs/leetcode/cpp/0069._Sqr(x).md)
+ [72. Edit Distance](docs/leetcode/cpp/0072._Edit_Distance.md)
+ [75. Sort Colors](docs/leetcode/cpp/0075._Sort_Colors.md)
+ [76. Minimum Window Substring](docs/leetcode/cpp/0076._Minimum_Window_Substring.md)
+ [77. Combinations](docs/leetcode/cpp/0077._combinations.md)
+ [78. Subsets](docs/leetcode/cpp/0078._subsets.md)
+ [81. Search in Rotated Sorted Array II](docs/leetcode/cpp/0081._Search_in_Rotated_Sorted_Array_II.md)
+ [???????](docs/leetcode/cpp/0083._Remove_Duplicates_From_Sorted_Lists.md)
+ [84. Largest Rectangle in Histogram](docs/leetcode/cpp/0084._Largest_Rectangle_in_Histogram.md)
+ [85. Maximal Rectangle](docs/leetcode/cpp/0085._Maximal_Rectangle.md)
+ [87. Scramble String](docs/leetcode/cpp/0087._Scramble_String.md)
+ [88.Merge Sorted Array](docs/leetcode/cpp/0088._Merge_Sorted_Array.md)
+ [90. Subsets II](docs/leetcode/cpp/0090._Subsets_II.md)
+ [94. Binary Tree Inorder Traversal](docs/leetcode/cpp/0094._binary_tree_inorder_traversal.md)
+ [96. Unique Binary Search Trees](docs/leetcode/cpp/0096._Unique_Binary_Search_Trees.md)
+ [97. Interleaving String](docs/leetcode/cpp/0097._Interleaving_String.md)
+ [99. Recover Binary Search Tree](docs/leetcode/cpp/0099._Recover_Binary_Search_Tree.md)
+ [100. same tree](docs/leetcode/cpp/0100._same_tree.md)
+ [101. Symmetric Tree](docs/leetcode/cpp/0101._Symmetric_Tree.md)
+ [102. Binary Tree Level Order Traversal](docs/leetcode/cpp/0102._Binary_Tree_Level_Order_Traversal.md)
+ [104. Maximum Depth of Binary Tree](docs/leetcode/cpp/0104._Maximum_Depth_of_Binary_Tree.md)
+ [105. Construct Binary Tree from Preorder and Inorder Traversal](docs/leetcode/cpp/0105._Construct_Binary_Tree_from_Preorder_and_Inorder_Traversal.md)
+ [106. Construct Binary Tree from Inorder and Postorder Traversal](docs/leetcode/cpp/0106._Construct_Binary_Tree_from_Inorder_and_Postorder_Traversal.md)
+ [107.Binary Tree Level Order Traversal II](docs/leetcode/cpp/0107._Binary_Tree_Level_Order_Traversal_II.md)
+ [108. Convert Sorted Array to Binary Search Tree](docs/leetcode/cpp/0108._Convert_Sorted_Array_to_Binary_Search_Tree.md)
+ [109. Convert Sorted List to Binary Search Tree](docs/leetcode/cpp/0109._Convert_Sorted_List_to_Binary_Search_Tree.md)
+ [110.Balanced Binary Tree](docs/leetcode/cpp/0110._Balanced_Binary_Tree.md)
+ [111. Minimum Depth of Binary Tree](docs/leetcode/cpp/0111._Minimum_Depth_Of_Binary_Tree.md)
+ [112. Path Sum](docs/leetcode/cpp/0112._Path_Sum.md)
+ [114. Flatten Binary Tree to Linked List](docs/leetcode/cpp/0114._Flatten_Binary_Tree_to_Linked_List.md)
+ [115.Distinct Subsequences](docs/leetcode/cpp/0115._Distinct_Subsequences.md)
+ [118. Pascal's Triangle](docs/leetcode/cpp/0118._Pascals_Triangle.md)
+ [119. Pascal's Triangle II](docs/leetcode/cpp/0119._Pascals_Triangle-II.md)
+ [120. Triangle](docs/leetcode/cpp/0120._Triangle.md)
+ [121. Best Time to Buy and Sell Stock](docs/leetcode/cpp/0121._Best_Tim_to_Buy_and_Sell_Stock.md)
+ [122. Best Time to Buy and Sell Stock II](docs/leetcode/cpp/0122._Best_Time_to_Buy_and_Sell_Stock_II.md)
+ [123. Best Time to Buy and Sell Stock III](docs/leetcode/cpp/0123._Best_Time_to_Buy_and_Sell_Stock_III.md)
+ [124. Binary Tree Maximum Path Sum](docs/leetcode/cpp/0124._Binary_Tree_Maximum_Path_Sum.md)
+ [127. Word Ladder](docs/leetcode/cpp/0127._Word_Ladde.md)
+ [128. Longest Consecutive Sequence](docs/leetcode/cpp/0128._Longest_Consecutive_Sequence.md)
+ [129. Sum Root to Leaf Numbers](docs/leetcode/cpp/0129._Sum_Root_to_Leaf_Numbers.md)
+ [131. Palindrome Paritionaing](docs/leetcode/cpp/0131._Palindrome_Partitioning.md)
+ [136. Single Numbe](docs/leetcode/cpp/0136._Single_Numbe.md)
+ [137.Single Number II](docs/leetcode/cpp/0137._Single_Number_II.md)
+ [???????](docs/leetcode/cpp/0141._Linked_List_Cycle.md)
+ [142. linked list cycle II](docs/leetcode/cpp/0142._Linked_List_Cycle_II.md)
+ [144. Binary Tree Preorder Traversal](docs/leetcode/cpp/0144._Binary_Tree_Preorder_Traversal.md)
+ [145. Binary Tree Postorder Traversal](docs/leetcode/cpp/0145._Binary_Tree_Postorder_Traversal.md)
+ [147. Insertion Sort List](docs/leetcode/cpp/0147._Insert_on_Sort_List.md)
+ [148.Sort list](docs/leetcode/cpp/0148._Sort_list.md)
+ [151. Reverse Words in a String](docs/leetcode/cpp/0151._Reverse_Words_in_a_String.md)
+ [153. Find Minimum in Rotated Sorted Array](docs/leetcode/cpp/0153._Find_Minimum_in_Rotated_Sorted_Array.md)
+ [154. Find Minimum in Rotated Sorted Array II](docs/leetcode/cpp/0154._Find_Minimum_in_Rotated_Sorted_Array-II.md)
+ [160 intersection_of_Two_Linked_Lists](docs/leetcode/cpp/0160._Intersection_Of_Two_Linked_Lists.md)
+ [164. Maximum Gap](docs/leetcode/cpp/0164._Maximum_Gap.md)
+ [166. Fraction to Recurring Decimal](docs/leetcode/cpp/0166._Fraction_to_Recurring_Decimal.md)
+ [167. Two Sum II - Input array is sorted](docs/leetcode/cpp/0167._Two_Sum_II-Input_array_is_sorted.md)
+ [199. Binary Tree Right Side View](docs/leetcode/cpp/0199._Binary_Tree_Right_Side_View.md)
+ [216. Combination Sum III](docs/leetcode/cpp/0216._Combination_Sum_III.md)
+ [230. Kth Smallest Element in a BST](docs/leetcode/cpp/0230._Kth_Smallest_Element_in_a_BST.md)
+ [260. Single Number III](docs/leetcode/cpp/0260._Single_Number_III.md)
+ [287. Find the Duplicate Number](docs/leetcode/cpp/0287._Find_the_Duplicate_Number.md)
+ [326. Power_of_Three](docs/leetcode/cpp/0326._Power_Of_Three.md)
+ [328. Odd Even Linked List](docs/leetcode/cpp/0328._Odd_Even_Linked_List.md)
+ [329. Longest Increasing Path in a Matrix](docs/leetcode/cpp/0329._Longest_Increasing_Path_in_a_Matrix.md)
+ [338. Counting Bits ](docs/leetcode/cpp/0338._Counting_Bits.md)
+ [413. Arithmetic Slices](docs/leetcode/cpp/0413._Arithmetic_Slices.md)
+ [442. Find All Duplicates in an Array](docs/leetcode/cpp/0442._Find_All_Duplicates_in_an_Array.md)
+ [513. Find Bottom Left Tree Value](docs/leetcode/cpp/0513._Find_Bottom_Left_Tree_Value.md)
+ [515. Find Largest Value in Each Tree Row](docs/leetcode/cpp/0515._Find_Largest_Value_in_Each_Tree_Row.md)
+ [540. Single Element in a Sorted Array](docs/leetcode/cpp/0540._Single_Element_in_a_Sorted_Array.md)
+ [581. Shortest Unsorted Continuous Subarray](docs/leetcode/cpp/0581._Shortest_Unsorted_Continuous_Subarray.md)
+ [793. K Inverse Pairs Array](docs/leetcode/cpp/0629._K_Inverse_Pairs_Array.md)
+ [632. Smallest Range](docs/leetcode/cpp/0632._Smallest_Range.md)
+ [654. Maximum Binary Tree ](docs/leetcode/cpp/0654._maximum_binary_tree.md)
+ [668. Kth Smallest Number in Multiplication Table](docs/leetcode/cpp/0668._Kth_Smallest_Number_in_Multiplication_Table.md)
+ [701. Insert into a Binary Search Tree](docs/leetcode/cpp/0701._Insert_into_a_Binary_Search_Tree.md)
+ [715. Range Module](docs/leetcode/cpp/0715._Range_Module.md)
+ [793. Find K-th Smallest Pair Distance](docs/leetcode/cpp/0719._Find_K-th_Smallest_Pair_Distance.md)
+ [739. Daily Temperatures](docs/leetcode/cpp/0739._Daily_Temperatures.md)
+ [797. All Paths From Source to Target](docs/leetcode/cpp/0797._All_Paths_From_Source_To_Target.md)
+ [814. Binary Tree Pruning](docs/leetcode/cpp/0814._Binary_Tree_Pruning.md)
+ [841. Keys and Rooms](docs/leetcode/cpp/0841._Keys_and_Rooms.md)
+ [877. Stone Game](docs/leetcode/cpp/0877._Stone_Game.md)
+ [945. Minimum Increment to Make Array Unique](docs/leetcode/cpp/0945._Minimum_Increment_to_Make_Array_Unique.md)
+ [946. Validate Stack Sequences](docs/leetcode/cpp/0946._Validate_Stack_Sequences.md)
+ [947. Most Stones Removed with Same Row or Column](docs/leetcode/cpp/0947._Most_Stones_Removed_with_Same_Row_or_Column.md)
+ [948. Bag of Tokens](docs/leetcode/cpp/0948._Bag_of_Tokens.md)
+ [949. Largest Time for Given Digits](docs/leetcode/cpp/0949._Largest_Time_for_Given_Digits.md)
+ [950. Reveal Cards In Increasing Order](docs/leetcode/cpp/0950._Reveal_Cards_In_Increasing_Order.md)
+ [951. Flip Equivalent Binary Trees](docs/leetcode/cpp/0951._Flip_Equivalent_Binary_Trees.md)
+ [952. Largest Component Size by Common Factor](docs/leetcode/cpp/0952._Largest_Component_Size_by_Common_Factor.md)
+ [Leetcode Java 题解](docs/leetcode/java/README.md)
+ [1. Two Sum](docs/leetcode/java/0001._Two_Sum.md)
+ [2. Add Two Numbers](docs/leetcode/java/0002._add_two_numbers.md)
+ [3. Longest Substring Without Repeating Characters](docs/leetcode/java/0003._Longest_Substring_Without_Repeating_Characters.md)
+ [4. Median of Two Sorted Arrays](docs/leetcode/java/0004._Median_of_Two_Sorted_Arrays.md)
+ [5. Longest Palindromic Substring](docs/leetcode/java/0005._Longest_Palindromic_Substring.md)
+ [6. ZigZag Conversion](docs/leetcode/java/0006._ZigZag_Conversion.md)
+ [7. Reverse Integer](docs/leetcode/java/0007._Reverse_Integer.md)
+ [23. Merge K Sorted Lists](docs/leetcode/java/0023._Merge_K_Sorted_Lists.md)
+ [141. Linked List Cycle](docs/leetcode/java/0141._linked_list_cycle.md)
+ [218. The Skyline Problem](docs/leetcode/java/0218._The_Skyline_Problem.md)
+ [238. Product of Array Except Self](docs/leetcode/java/0238._product_of_array_except_self.md)
+ [342. Power of Four](docs/leetcode/java/0342._Power_of_Four.md)
+ [403. Frog Jump](docs/leetcode/java/0403._Frog_Jump.md)
+ [757. Set Intersection Size At Least Two](docs/leetcode/java/0757._Set_Intersection_Size_At_Least_Two.md)
+ [768. Max Chunks To Make Sorted II](docs/leetcode/java/0768._Max_Chunks_To_Make_Sorted_II.md)
+ [780. Reaching Points](docs/leetcode/java/0780._Reaching_Points.md)
+ [793. Preimage Size of Factorial Zeroes Function](docs/leetcode/java/0793._Preimage_Size_of_Factorial_Zeroes_Function.md)
+ [827. Making A Large Island](docs/leetcode/java/0827._Making_A_Large_Island.md)
+ [828. Unique Letter String](docs/leetcode/java/0828._Unique_Letter_String.md)
+ [834. Sum of Distances in Tree](docs/leetcode/java/0834._Sum_of_Distances_in_Tree.md)
+ [843. Guess the Word](docs/leetcode/java/0843._Guess_the_Word.md)
+ [847. Shortest Path Visiting All Nodes](docs/leetcode/java/0847._Shortest_Path_Visiting_All_Nodes.md)
+ [850. Rectangle Area II](docs/leetcode/java/0850._Rectangle_Area_II.md)
+ [854. K-Similar Strings](docs/leetcode/java/0854._K-Similar_Strings.md)
+ [857. Minimum Cost to Hire K Workers](docs/leetcode/java/0857._Minimum_Cost_to_Hire_K_Workers.md)
+ [862. Shortest Subarray with Sum at Least K](docs/leetcode/java/0862._Shortest_Subarray_with_Sum_at_Least_K.md)
+ [864. Shortest Path to Get All Keys](docs/leetcode/java/0864._Shortest_Path_to_Get_All_Keys.md)
+ [871. Minimum Number of Refueling Stops](docs/leetcode/java/0871._Minimum_Number_of_Refueling_Stops.md)
+ [878. Nth Magical Number](docs/leetcode/java/0878._Nth_Magical_Number.md)
+ [879. Profitable Schemes](docs/leetcode/java/0879._Profitable_Schemes.md)
+ [899. Reachable Nodes In Subdivided Graph](docs/leetcode/java/0882._Reachable_Nodes_In_Subdivided_Graph.md)
+ [887. Super Egg Drop](docs/leetcode/java/0887._Super_Egg_Drop.md)
+ [891. Sum of Subsequence Widths](docs/leetcode/java/0891._Sum_of_Subsequence_Widths.md)
+ [895. Maximum Frequency Stack](docs/leetcode/java/0895._Maximum_Frequency_Stack.md)
+ [899. Orderly Queue](docs/leetcode/java/0899._Orderly_Queue.md)
+ [902. Numbers At Most N Given Digit Set](docs/leetcode/java/0902._Numbers_At_Most_N_Given_Digit_Set.md)
+ [903. Valid Permutations for DI Sequence](docs/leetcode/java/0903._Valid_Permutations_for_DI_Sequence.md)
+ [906. Super Palindromes](docs/leetcode/java/0906._Super_Palindromes.md)
+ [913. Cat and Mouse](docs/leetcode/java/0913._Cat_and_Mouse.md)
+ [920. Number of Music Playlists](docs/leetcode/java/0920._Number_of_Music_Playlists.md)
+ [Leetcode JavaScript 题解](docs/leetcode/javascript/README.md)
+ [0001 Two Sum](docs/leetcode/javascript/0001._Two_Sum.md)
+ [0002 Add Two Numbers](docs/leetcode/javascript/0002._Add_Two_Numbers.md)
+ [0003 Longest Substring without Repeating Characters](docs/leetcode/javascript/0003._Longest_Substring_without_Repeating_Characters.md)
+ [0007 Reverse Integer](docs/leetcode/javascript/0007._Reverse_Integer.md)
+ [0008 String to Integer](docs/leetcode/javascript/0008._String_to_Integer.md)
+ [0009 Palindrome Number](docs/leetcode/javascript/0009._Palindrome_Number.md)
+ [0011 Container With Most Water](docs/leetcode/javascript/0011._Container_With_Most_Water.md)
+ [0012 Integer To Roman](docs/leetcode/javascript/0012._Integer_To_Roman.md)
+ [0013 Roman To Integer](docs/leetcode/javascript/0013._Roman_To_Integer.md)
+ [0014 Longest Common Prefix](docs/leetcode/javascript/0014._Longest_Common_Prefix.md)
+ [0015 Three Sum](docs/leetcode/javascript/0015._Three_Sum.md)
+ [0016 3 Sum Closest](docs/leetcode/javascript/0016._3_Sum_Closest.md)
+ [0017 Letter Combinations Of A Phone Number](docs/leetcode/javascript/0017._Letter_Combinations_Of_A_Phone_Number.md)
+ [0019 Remove Nth Node From End Of List](docs/leetcode/javascript/0019._Remove_Nth_Node_From_End_Of_List.md)
+ [0020 Valid Parentheses](docs/leetcode/javascript/0020._Valid_Parentheses.md)
+ [0021 Merge Two Sorted Lists](docs/leetcode/javascript/0021._Merge_Two_Sorted_Lists.md)
+ [0022 Generate Parentheses](docs/leetcode/javascript/0022._Generate_Parentheses.md)
+ [0024 Swap Nodes In Pairs](docs/leetcode/javascript/0024._Swap_Nodes_In_Pairs.md)
+ [0027 Remove Element](docs/leetcode/javascript/0027._Remove_Element.md)
+ [0031 Next Permutation](docs/leetcode/javascript/0031._Next_Permutation.md)
+ [0035 Search Insert Position](docs/leetcode/javascript/0035._Search_Insert_Position.md)
+ [0054 Spiral Matrix](docs/leetcode/javascript/0054._Spiral_Matrix.md)
+ [0055 Jump Game](docs/leetcode/javascript/0055._Jump_Game.md)
+ [0056 Merge Intervals](docs/leetcode/javascript/0056._Merge_Intervals.md)
+ [0058 Length of Last Word](docs/leetcode/javascript/0058._Length_of_Last_Word.md)
+ [0061 Rotate List](docs/leetcode/javascript/0061._Rotate_List.md)
+ [0062 Unique Paths](docs/leetcode/javascript/0062._Unique_Paths.md)
+ [0066 Plus One](docs/leetcode/javascript/0066._Plus_One.md)
+ [0067 Add Binary](docs/leetcode/javascript/0067._Add_Binary.md)
+ [0074 Search a 2D Matrix](docs/leetcode/javascript/0074._Search_a_2D_Matrix.md)
+ [0079 Search Word](docs/leetcode/javascript/0079._Search_Word.md)
+ [0083 Remove Duplicates From Sorted List](docs/leetcode/javascript/0083._Remove_Duplicates_From_Sorted_List.md)
+ [0094 Binary Tree Inorder Traversal](docs/leetcode/javascript/0094._Binary_Tree_Inorder_Traversal.md)
+ [0098 Validate Binary Search Tree](docs/leetcode/javascript/0098._Validate_Binary_Search_Tree.md)
+ [0100 Same Tree](docs/leetcode/javascript/0100._Same_Tree.md)
+ [0101 Symmetric Tree](docs/leetcode/javascript/0101._Symmetric_Tree.md)
+ [0104 Maximum Depth of Binary Tree](docs/leetcode/javascript/0104._Maximum_Depth_of_Binary_Tree.md)
+ [0106 Construct Binary Tree From Inorder And Postorder Traversal](docs/leetcode/javascript/0106._Construct_Binary_Tree_From_Inorder_And_Postorder_Traversal.md)
+ [0141 Linked List Cycle](docs/leetcode/javascript/0141._Linked_List_Cycle.md)
+ [0146 LRU Cache](docs/leetcode/javascript/0146._LRU_Cache.md)
+ [0167 Two Sum II - Input array is sorted](docs/leetcode/javascript/0167._Two_Sum_II_-_Input_array_is_sorted.md)
+ [0167 Two Sum II Input Array is Sorted](docs/leetcode/javascript/0167._Two_Sum_II_Input_Array_is_Sorted.md)
+ [0171 Excel Sheet Column Number](docs/leetcode/javascript/0171._Excel_Sheet_Column_Number.md)
+ [0179 Largest Number](docs/leetcode/javascript/0179._Largest_Number.md)
+ [0203 Remove Linked List Elements](docs/leetcode/javascript/0203._Remove_Linked_List_Elements.md)
+ [0206 Reverse-Linked-List](docs/leetcode/javascript/0206._Reverse-Linked-List.md)
+ [0209 Minimum Size Subarray Sum](docs/leetcode/javascript/0209._Minimum_Size_Subarray_Sum.md)
+ [0258 Add Digits](docs/leetcode/javascript/0258._Add_Digits.md)
+ [0347 Top K Frequent Elements](docs/leetcode/javascript/0347._Top_K_Frequent_Elements.md)
+ [0402 Remove K Digits](docs/leetcode/javascript/0402._Remove_K_Digits.md)
+ [0406 Queue Reconstruction By Height](docs/leetcode/javascript/0406._Queue_Reconstruction_By_Height.md)
+ [0485 Max Consecutive Ones](docs/leetcode/javascript/0485._Max_Consecutive_Ones.md)
+ [0539 Minimum Time Difference](docs/leetcode/javascript/0539._Minimum_Time_Difference.md)
+ [0581 Shortest Unsorted Continuous Subarray](docs/leetcode/javascript/0581._Shortest_Unsorted_Continuous_Subarray.md)
+ [0881 Boats to Save People](docs/leetcode/javascript/0881._Boats_to_Save_People.md)
+ [0997 Find The Town Judge](docs/leetcode/javascript/0997._Find_The_Town_Judge.md)
+ [1130 Minimum Cost Tree From Leaf Values](docs/leetcode/javascript/1130._Minimum_Cost_Tree_From_Leaf_Values.md)
+ [Leetcode Python 题解](docs/leetcode/python/README.md)
+ [001 two sum](docs/leetcode/python/001._two_sum.md)
+ [002 add two numbers](docs/leetcode/python/002._add_two_numbers.md)
+ [003 longest substring without repeating characters](docs/leetcode/python/003._longest_substring_without_repeating_characters.md)
+ [004 median of two sorted arrays](docs/leetcode/python/004._median_of_two_sorted_arrays.md)
+ [005 longest palindromic substring](docs/leetcode/python/005._longest_palindromic_substring.md)
+ [006 ZigZag Conversion](docs/leetcode/python/006._ZigZag_Conversion.md)
+ [007 Reverse Integer](docs/leetcode/python/007._Reverse_Integer.md)
+ [008 string to integer (atoi)](docs/leetcode/python/008._string_to_integer_(atoi).md)
+ [009 Palindrome Number](docs/leetcode/python/009._Palindrome_Number.md)
+ [010 regular expression matching](docs/leetcode/python/010._regular_expression_matching.md)
+ [011 container with most water](docs/leetcode/python/011._container_with_most_water.md)
+ [012 Integer to Roman](docs/leetcode/python/012._Integer_to_Roman.md)
+ [013 Roman to Integer](docs/leetcode/python/013._Roman_to_Integer.md)
+ [014 longest common prefix](docs/leetcode/python/014._longest_common_prefix.md)
+ [015 3sum](docs/leetcode/python/015._3sum.md)
+ [016 3sum closest](docs/leetcode/python/016._3sum_closest.md)
+ [017 letter combinations of a phone number](docs/leetcode/python/017._letter_combinations_of_a_phone_number.md)
+ [018 4sum](docs/leetcode/python/018._4sum.md)
+ [019 remove nth node from end of list](docs/leetcode/python/019._remove_nth_node_from_end_of_list.md)
+ [020 valid parentheses](docs/leetcode/python/020._valid_parentheses.md)
+ [021 merge two sorted lists](docs/leetcode/python/021._merge_two_sorted_lists.md)
+ [022 generate parentheses](docs/leetcode/python/022._generate_parentheses.md)
+ [023 merge k sorted lists](docs/leetcode/python/023._merge_k_sorted_lists.md)
+ [024 swap nodes in pairs](docs/leetcode/python/024._swap_nodes_in_pairs.md)
+ [026 Remove Duplicates from Sorted Array](docs/leetcode/python/026._Remove_Duplicates_from_Sorted_Array.md)
+ [027 Remove Element](docs/leetcode/python/027._Remove_Element.md)
+ [028 implement strstr()](docs/leetcode/python/028._implement_strstr.md)
+ [030 Substring with Concatenation of All Words](docs/leetcode/python/030._Substring_with_Concatenation_of_All_Words.md)
+ [031 next permutation](docs/leetcode/python/031._next_permutation.md)
+ [032 longest valid parentheses](docs/leetcode/python/032._longest_valid_parentheses.md)
+ [033 search in rotated sorted array](docs/leetcode/python/033._search_in_rotated_sorted_array.md)
+ [034 Search for a Range](docs/leetcode/python/034._Search_for_a_Range.md)
+ [035 search insert position](docs/leetcode/python/035._search_insert_position.md)
+ [038 Count and Say](docs/leetcode/python/038._Count_and_Say.md)
+ [039 combination sum](docs/leetcode/python/039._combination_sum.md)
+ [040 combination sum ii](docs/leetcode/python/040._combination_sum_ii.md)
+ [041 First Missing Positive](docs/leetcode/python/041._First_Missing_Positive.md)
+ [042 trapping rain water](docs/leetcode/python/042._trapping_rain_water.md)
+ [043 multiply strings](docs/leetcode/python/043._multiply_strings.md)
+ [044 wildcard matching](docs/leetcode/python/044._wildcard_matching.md)
+ [045 Jump Game II](docs/leetcode/python/045._Jump_Game_II.md)
+ [046 permutations](docs/leetcode/python/046._permutations.md)
+ [047 permutations ii](docs/leetcode/python/047._permutations_ii.md)
+ [048 rotate image](docs/leetcode/python/048._rotate_image.md)
+ [049 group anagrams python](docs/leetcode/python/049._group_anagrams_python.md)
+ [050 pow(x, n)](docs/leetcode/python/050._pow(x,_n).md)
+ [051 n-queens](docs/leetcode/python/051._n-queens.md)
+ [052 n-queens ii](docs/leetcode/python/052._n-queens_ii.md)
+ [053 maximum subarray](docs/leetcode/python/053._maximum_subarray.md)
+ [054 spiral matrix](docs/leetcode/python/054._spiral_matrix.md)
+ [055 jump game](docs/leetcode/python/055._jump_game.md)
+ [056 Merge Intervals](docs/leetcode/python/056._Merge_Intervals.md)
+ [058 length of last word](docs/leetcode/python/058._length_of_last_word.md)
+ [059 spiral matrix ii](docs/leetcode/python/059._spiral_matrix_ii.md)
+ [060 permutation sequence](docs/leetcode/python/060._permutation_sequence.md)
+ [061 rotate list](docs/leetcode/python/061._rotate_list.md)
+ [062 unique paths](docs/leetcode/python/062._unique_paths.md)
+ [064 minimum path sum](docs/leetcode/python/064._minimum_path_sum.md)
+ [065 unique paths ii](docs/leetcode/python/065.unique_paths_ii.md)
+ [066 plus one](docs/leetcode/python/066._plus_one.md)
+ [067 add binary](docs/leetcode/python/067._add_binary.md)
+ [069 sqrt(x)](docs/leetcode/python/069._sqrt(x).md)
+ [070 Climbing Stairs](docs/leetcode/python/070._Climbing_Stairs.md)
+ [072 edit distance](docs/leetcode/python/072._edit_distance.md)
+ [073 Set Matrix Zeroes](docs/leetcode/python/073._Set_Matrix_Zeroes.md)
+ [074 search a 2d matrix](docs/leetcode/python/074._search_a_2d_matrix.md)
+ [075 sort colors](docs/leetcode/python/075._sort_colors.md)
+ [076 Minimum Window Substring](docs/leetcode/python/076._Minimum_Window_Substring.md)
+ [077 combinations](docs/leetcode/python/077._combinations.md)
+ [078 Subsets](docs/leetcode/python/078._Subsets.md)
+ [079 word search](docs/leetcode/python/079._word_search.md)
+ [082 remove duplicates from sorted list ii](docs/leetcode/python/082._remove_duplicates_from_sorted_list_ii.md)
+ [083 remove duplicates from sorted list](docs/leetcode/python/083._remove_duplicates_from_sorted_list.md)
+ [086 partition list](docs/leetcode/python/086._partition_list.md)
+ [088 merge sorted array](docs/leetcode/python/088._merge_sorted_array.md)
+ [089 gray code](docs/leetcode/python/089._gray_code.md)
+ [090 subsets ii](docs/leetcode/python/090._subsets_ii.md)
+ [091 decode ways](docs/leetcode/python/091._decode_ways.md)
+ [092 reverse linked list ii](docs/leetcode/python/092._reverse_linked_list_ii.md)
+ [093 restore ip addresses](docs/leetcode/python/093._restore_ip_addresses.md)
+ [094 binary tree inorder traversal](docs/leetcode/python/094._binary_tree_inorder_traversal.md)
+ [096 unique binary search trees](docs/leetcode/python/096._unique_binary_search_trees.md)
+ [098 validate binary search tree](docs/leetcode/python/098._validate_binary_search_tree.md)
+ [100 same tree](docs/leetcode/python/100._same_tree.md)
+ [101 symmetric tree](docs/leetcode/python/101._symmetric_tree.md)
+ [102 binary tree level order traversal](docs/leetcode/python/102._binary_tree_level_order_traversal.md)
+ [103 binary tree zigzag level order traversal](docs/leetcode/python/103._binary_tree_zigzag_level_order_traversal.md)
+ [104 maximum depth of binary tree](docs/leetcode/python/104._maximum_depth_of_binary_tree.md)
+ [105 construct binary tree from preorder and inorder traversal](docs/leetcode/python/105._construct_binary_tree_from_preorder_and_inorder_traversal.md)
+ [106 construct binary tree from inorder and postorder traversal](docs/leetcode/python/106._construct_binary_tree_from_inorder_and_postorder_traversal.md)
+ [107 binary tree level order traversal ii](docs/leetcode/python/107._binary_tree_level_order_traversal_ii.md)
+ [108 convert sorted array to binary search tree](docs/leetcode/python/108._convert_sorted_array_to_binary_search_tree.md)
+ [109 convert sorted list to binary search tree](docs/leetcode/python/109._convert_sorted_list_to_binary_search_tree.md)
+ [110 balanced binary tree](docs/leetcode/python/110._balanced_binary_tree.md)
+ [111 minimum depth of binary tree](docs/leetcode/python/111._minimum_depth_of_binary_tree.md)
+ [112 path sum](docs/leetcode/python/112._path_sum.md)
+ [113 path sum ii](docs/leetcode/python/113._path_sum_ii.md)
+ [114 flatten binary tree to linked list](docs/leetcode/python/114._flatten_binary_tree_to_linked_list.md)
+ [116 populating next right pointers in each node](docs/leetcode/python/116._populating_next_right_pointers_in_each_node.md)
+ [117 Populating Next Right Pointers in Each Node II](docs/leetcode/python/117._Populating_Next_Right_Pointers_in_Each_Node_II.md)
+ [118 pascal's triangle](docs/leetcode/python/118._pascal's_triangle.md)
+ [119 Pascal's Triangle II](docs/leetcode/python/119._Pascal's_Triangle_II.md)
+ [120 Triangle](docs/leetcode/python/120._Triangle.md)
+ [121 Best Time to Buy and Sell Stock](docs/leetcode/python/121._Best_Time_to_Buy_and_Sell_Stock.md)
+ [124 Binary Tree Maximum Path Sum](docs/leetcode/python/124._Binary_Tree_Maximum_Path_Sum.md)
+ [125 valid palindrome](docs/leetcode/python/125._valid_palindrome.md)
+ [126 Word Ladder II](docs/leetcode/python/126._Word_Ladder_II.md)
+ [127 word ladder](docs/leetcode/python/127._word_ladder.md)
+ [128 Longest Consecutive Sequence](docs/leetcode/python/128._Longest_Consecutive_Sequence.md)
+ [129 sum root to leaf numbers](docs/leetcode/python/129._sum_root_to_leaf_numbers.md)
+ [130 surrounded regions](docs/leetcode/python/130._surrounded_regions.md)
+ [131 palindrome partitioning](docs/leetcode/python/131._palindrome_partitioning.md)
+ [133 clone graph](docs/leetcode/python/133._clone_graph.md)
+ [136 single number](docs/leetcode/python/136._single_number.md)
+ [139 word break](docs/leetcode/python/139._word_break.md)
+ [140 word break ii](docs/leetcode/python/140._word_break_ii.md)
+ [141 linked list cycle](docs/leetcode/python/141._linked_list_cycle.md)
+ [142_Linked_List_Cycle_II md](docs/leetcode/python/142_Linked_List_Cycle_II.md)
+ [143 reorder list](docs/leetcode/python/143._reorder_list.md)
+ [144 binary tree preorder traversal](docs/leetcode/python/144._binary_tree_preorder_traversal.md)
+ [145 binary tree postorder traversal](docs/leetcode/python/145._binary_tree_postorder_traversal.md)
+ [147 insertion sort list](docs/leetcode/python/147._insertion_sort_list.md)
+ [148 sort list](docs/leetcode/python/148._sort_list.md)
+ [150 evaluate reverse polish notation](docs/leetcode/python/150._evaluate_reverse_polish_notation.md)
+ [151 reverse words in a string](docs/leetcode/python/151._reverse_words_in_a_string.md)
+ [152 maximum product subarray](docs/leetcode/python/152._maximum_product_subarray.md)
+ [153 find minimum in rotated sorted array](docs/leetcode/python/153._find_minimum_in_rotated_sorted_array.md)
+ [155 min stack](docs/leetcode/python/155._min_stack.md)
+ [157 Read N Characters Given Read4](docs/leetcode/python/157._Read_N_Characters_Given_Read4.md)
+ [158 Read N Characters Given Read4 II - Call multiple times](docs/leetcode/python/158._Read_N_Characters_Given_Read4_II_-_Call_multiple_times.md)
+ [159 Longest Substring with At Most Two Distinct Characters](docs/leetcode/python/159._Longest_Substring_with_At_Most_Two_Distinct_Characters.md)
+ [160 intersection of two linked lists](docs/leetcode/python/160._intersection_of_two_linked_lists.md)
+ [162 find peak element](docs/leetcode/python/162._find_peak_element.md)
+ [165 compare version numbers](docs/leetcode/python/165._compare_version_numbers.md)
+ [166 Fraction to Recurring Decimal](docs/leetcode/python/166._Fraction_to_Recurring_Decimal.md)
+ [167 two sum ii - input array is sorted](docs/leetcode/python/167._two_sum_ii_-_input_array_is_sorted.md)
+ [168 excel sheet column title](docs/leetcode/python/168._excel_sheet_column_title.md)
+ [169 majority element](docs/leetcode/python/169._majority_element.md)
+ [171 excel sheet column number](docs/leetcode/python/171._excel_sheet_column_number.md)
+ [173 binary search tree iterator](docs/leetcode/python/173._binary_search_tree_iterator.md)
+ [179 Largest Number](docs/leetcode/python/179._Largest_Number.md)
+ [182 duplicate emails](docs/leetcode/python/182._duplicate_emails.md)
+ [189 rotate array](docs/leetcode/python/189._rotate_array.md)
+ [191 number of 1 bits](docs/leetcode/python/191._number_of_1_bits.md)
+ [198 house robber](docs/leetcode/python/198._house_robber.md)
+ [199 binary tree right side view](docs/leetcode/python/199._binary_tree_right_side_view.md)
+ [200 number of islands](docs/leetcode/python/200._number_of_islands.md)
+ [203 remove linked list elements](docs/leetcode/python/203._remove_linked_list_elements.md)
+ [204 count primes](docs/leetcode/python/204._count_primes.md)
+ [205 isomorphic strings](docs/leetcode/python/205._isomorphic_strings.md)
+ [206 reverse linked list](docs/leetcode/python/206._reverse_linked_list.md)
+ [207 course schedule](docs/leetcode/python/207._course_schedule.md)
+ [208 implement trie (prefix tree)](docs/leetcode/python/208._implement_trie_(prefix_tree).md)
+ [210 course schedule ii](docs/leetcode/python/210._course_schedule_ii.md)
+ [211 Add and Search Word - Data structure design](docs/leetcode/python/211._Add_and_Search_Word_-_Data_structure_design.md)
+ [213 house robber ii](docs/leetcode/python/213._house_robber_ii.md)
+ [216 combination sum iii](docs/leetcode/python/216._combination_sum_iii.md)
+ [217 contains duplicate](docs/leetcode/python/217._contains_duplicate.md)
+ [218 The Skyline Problem](docs/leetcode/python/218._The_Skyline_Problem.md)
+ [219 contains duplicate ii](docs/leetcode/python/219._contains_duplicate_ii.md)
+ [221 maximal square](docs/leetcode/python/221._maximal_square.md)
+ [222 count complete tree nodes](docs/leetcode/python/222._count_complete_tree_nodes.md)
+ [223 rectangle area](docs/leetcode/python/223._rectangle_area.md)
+ [224 Basic Calculator](docs/leetcode/python/224._Basic_Calculator.md)
+ [225 implement stack using queues](docs/leetcode/python/225._implement_stack_using_queues.md)
+ [226 invert binary tree](docs/leetcode/python/226._invert_binary_tree.md)
+ [227 basic calculator ii](docs/leetcode/python/227._basic_calculator_ii.md)
+ [228 summary ranges](docs/leetcode/python/228._summary_ranges.md)
+ [229 majority element ii](docs/leetcode/python/229._majority_element_ii.md)
+ [230 kth smallest element in a bst](docs/leetcode/python/230._kth_smallest_element_in_a_bst.md)
+ [231 Power of Two](docs/leetcode/python/231._Power_of_Two.md)
+ [232 implement queue using stacks](docs/leetcode/python/232._implement_queue_using_stacks.md)
+ [234 palindrome linked list](docs/leetcode/python/234._palindrome_linked_list.md)
+ [235 lowest common ancestor of a binary search tree](docs/leetcode/python/235._lowest_common_ancestor_of_a_binary_search_tree.md)
+ [236 lowest common ancestor of a binary tree](docs/leetcode/python/236._lowest_common_ancestor_of_a_binary_tree.md)
+ [237 delete node in a linked list](docs/leetcode/python/237._delete_node_in_a_linked_list.md)
+ [238 product of array except self](docs/leetcode/python/238._product_of_array_except_self.md)
+ [240 search a 2d matrix ii](docs/leetcode/python/240._search_a_2d_matrix_ii.md)
+ [242 valid anagram](docs/leetcode/python/242._valid_anagram.md)
+ [249 Group Shifted Strings](docs/leetcode/python/249._Group_Shifted_Strings.md)
+ [252 Meeting Rooms](docs/leetcode/python/252._Meeting_Rooms.md)
+ [255 Verify Preorder Sequence in Binary Search Tree](docs/leetcode/python/255._Verify_Preorder_Sequence_in_Binary_Search_Tree.md)
+ [256 Paint House](docs/leetcode/python/256._Paint_House.md)
+ [257 binary tree paths](docs/leetcode/python/257._binary_tree_paths.md)
+ [258_Add_Digits md](docs/leetcode/python/258._Add_Digits.md)
+ [261 Graph Valid Tree](docs/leetcode/python/261._Graph_Valid_Tree.md)
+ [263 ugly number](docs/leetcode/python/263._ugly_number.md)
+ [264 ugly number ii](docs/leetcode/python/264._ugly_number_ii.md)
+ [265 Paint House II](docs/leetcode/python/265._Paint_House_II.md)
+ [266 Palindrome Permutation](docs/leetcode/python/266._Palindrome_Permutation.md)
+ [267 Palindrome Permutation II](docs/leetcode/python/267._Palindrome_Permutation_II.md)
+ [268 missing number](docs/leetcode/python/268._missing_number.md)
+ [270 Closest Binary Search Tree Value](docs/leetcode/python/270._Closest_Binary_Search_Tree_Value.md)
+ [276 Paint Fence](docs/leetcode/python/276._Paint_Fence.md)
+ [277 Find the Celebrity](docs/leetcode/python/277._Find_the_Celebrity.md)
+ [278 First Bad Version](docs/leetcode/python/278._First_Bad_Version.md)
+ [279 perfect squares](docs/leetcode/python/279._perfect_squares.md)
+ [280 Wiggle Sort](docs/leetcode/python/280._Wiggle_Sort.md)
+ [283 move zeroes](docs/leetcode/python/283._move_zeroes.md)
+ [285 inorder successor in bst](docs/leetcode/python/285._inorder_successor_in_bst.md)
+ [286 Walls and Gates](docs/leetcode/python/286._Walls_and_Gates.md)
+ [287 Find the Duplicate Number](docs/leetcode/python/287._Find_the_Duplicate_Number.md)
+ [289 game of life](docs/leetcode/python/289._game_of_life.md)
+ [290 word pattern](docs/leetcode/python/290._word_pattern.md)
+ [292 nim game](docs/leetcode/python/292._nim_game.md)
+ [293 Flip Game](docs/leetcode/python/293._Flip_Game.md)
+ [296 Best Meeting Point](docs/leetcode/python/296._Best_Meeting_Point.md)
+ [298 Binary Tree Longest Consecutive Sequence](docs/leetcode/python/298._Binary_Tree_Longest_Consecutive_Sequence.md)
+ [299 bulls and cows](docs/leetcode/python/299._bulls_and_cows.md)
+ [300 longest increasing subsequence](docs/leetcode/python/300._longest_increasing_subsequence.md)
+ [303 range sum query - immutable](docs/leetcode/python/303._range_sum_query_-_immutable.md)
+ [316 Remove Duplicate Letters](docs/leetcode/python/316._Remove_Duplicate_Letters.md)
+ [319 Bulb Switcher](docs/leetcode/python/319._Bulb_Switcher.md)
+ [322 Coin Change](docs/leetcode/python/322._Coin_Change.md)
+ [323 number of connected components in an undirected graph](docs/leetcode/python/323._number_of_connected_components_in_an_undirected_graph.md)
+ [324 Wiggle Sort II](docs/leetcode/python/324._Wiggle_Sort_II.md)
+ [326 power of three](docs/leetcode/python/326._power_of_three.md)
+ [328 odd even linked list](docs/leetcode/python/328._odd_even_linked_list.md)
+ [334 increasing triplet subsequence](docs/leetcode/python/334._increasing_triplet_subsequence.md)
+ [337 house robber iii](docs/leetcode/python/337._house_robber_iii.md)
+ [338 Counting Bits](docs/leetcode/python/338._Counting_Bits.md)
+ [339 Nested List Weight Sum](docs/leetcode/python/339._Nested_List_Weight_Sum.md)
+ [341 Flatten Nested List Iterator](docs/leetcode/python/341._Flatten_Nested_List_Iterator.md)
+ [342 Power of Four](docs/leetcode/python/342._Power_of_Four.md)
+ [344 reverse string](docs/leetcode/python/344._reverse_string.md)
+ [345 Reverse Vowels of a String](docs/leetcode/python/345._Reverse_Vowels_of_a_String.md)
+ [349 intersection of two arrays](docs/leetcode/python/349._intersection_of_two_arrays.md)
+ [350 intersection of two arrays ii](docs/leetcode/python/350._intersection_of_two_arrays_ii.md)
+ [353 Design Snake Game](docs/leetcode/python/353._Design_Snake_Game.md)
+ [361 Bomb Enemy](docs/leetcode/python/361._Bomb_Enemy.md)
+ [364 Nested List Weight Sum II](docs/leetcode/python/364._Nested_List_Weight_Sum_II.md)
+ [366 Find Leaves of Binary Tree](docs/leetcode/python/366._Find_Leaves_of_Binary_Tree.md)
+ [367 valid perfect square](docs/leetcode/python/367._valid_perfect_square.md)
+ [369 Plus One Linked List](docs/leetcode/python/369._Plus_One_Linked_List.md)
+ [371 sum of two integers](docs/leetcode/python/371._sum_of_two_integers.md)
+ [374 Guess Number Higher or Lower](docs/leetcode/python/374._Guess_Number_Higher_or_Lower.md)
+ [377 combination sum iv](docs/leetcode/python/377._combination_sum_iv.md)
+ [378 kth smallest element in a sorted matrix](docs/leetcode/python/378._kth_smallest_element_in_a_sorted_matrix.md)
+ [380 Insert Delete GetRandom O(1)](docs/leetcode/python/380._Insert_Delete_GetRandom_O(1).md)
+ [381 Insert Delete GetRandom O(1) - Duplicates allowed](docs/leetcode/python/381._Insert_Delete_GetRandom_O(1)_-_Duplicates_allowed.md)
+ [382 linked list random node](docs/leetcode/python/382._linked_list_random_node.md)
+ [383 ransom note](docs/leetcode/python/383._ransom_note.md)
+ [384 Shuffle an Array](docs/leetcode/python/384._Shuffle_an_Array.md)
+ [386 Lexicographical Numbers](docs/leetcode/python/386._Lexicographical_Numbers.md)
+ [387 first unique character in a string](docs/leetcode/python/387._first_unique_character_in_a_string.md)
+ [388 Longest Absolute File Path](docs/leetcode/python/388._Longest_Absolute_File_Path.md)
+ [389 find the difference](docs/leetcode/python/389._find_the_difference.md)
+ [392 is subsequence](docs/leetcode/python/392._is_subsequence.md)
+ [394 decode string](docs/leetcode/python/394._decode_string.md)
+ [400 Nth Digit](docs/leetcode/python/400._Nth_Digit.md)
+ [401 binary watch](docs/leetcode/python/401._binary_watch.md)
+ [404 sum of left leaves](docs/leetcode/python/404._sum_of_left_leaves.md)
+ [405 Convert a Number to Hexadecimal](docs/leetcode/python/405._Convert_a_Number_to_Hexadecimal.md)
+ [406 Queue Reconstruction by Height](docs/leetcode/python/406._Queue_Reconstruction_by_Height.md)
+ [412 fizz buzz](docs/leetcode/python/412._fizz_buzz.md)
+ [413 Arithmetic Slices](docs/leetcode/python/413._Arithmetic_Slices.md)
+ [414 third maximum number](docs/leetcode/python/414._third_maximum_number.md)
+ [415 add strings](docs/leetcode/python/415._add_strings.md)
+ [416 Partition Equal Subset Sum](docs/leetcode/python/416._Partition_Equal_Subset_Sum.md)
+ [421 Maximum XOR of Two Numbers in an Array](docs/leetcode/python/421._Maximum_XOR_of_Two_Numbers_in_an_Array.md)
+ [422 Valid Word Square](docs/leetcode/python/422._Valid_Word_Square.md)
+ [434 number of segments in a string](docs/leetcode/python/434._number_of_segments_in_a_string.md)
+ [435 Non-overlapping Intervals](docs/leetcode/python/435._Non-overlapping_Intervals.md)
+ [437 path sum iii](docs/leetcode/python/437._path_sum_iii.md)
+ [438 Find All Anagrams in a String](docs/leetcode/python/438._Find_All_Anagrams_in_a_String.md)
+ [439 Ternary Expression Parser](docs/leetcode/python/439._Ternary_Expression_Parser.md)
+ [441 arranging coins](docs/leetcode/python/441._arranging_coins.md)
+ [448 Find All Numbers Disappeared in an Array](docs/leetcode/python/448._Find_All_Numbers_Disappeared_in_an_Array.md)
+ [450 Delete Node in a BST](docs/leetcode/python/450._Delete_Node_in_a_BST.md)
+ [453 Minimum Moves to Equal Array Elements](docs/leetcode/python/453._Minimum_Moves_to_Equal_Array_Elements.md)
+ [459 Repeated Substring Pattern](docs/leetcode/python/459._Repeated_Substring_Pattern.md)
+ [461 Hamming Distance](docs/leetcode/python/461._Hamming_Distance.md)
+ [463 Island Perimeter](docs/leetcode/python/463._Island_Perimeter.md)
+ [467 Unique Substrings in Wraparound String](docs/leetcode/python/467._Unique_Substrings_in_Wraparound_String.md)
+ [469 Convex Polygon](docs/leetcode/python/469._Convex_Polygon.md)
+ [476 Number Complement](docs/leetcode/python/476._Number_Complement.md)
+ [477 Total Hamming Distance](docs/leetcode/python/477._Total_Hamming_Distance.md)
+ [485 Max Consecutive Ones](docs/leetcode/python/485._Max_Consecutive_Ones.md)
+ [494 Target Sum](docs/leetcode/python/494._Target_Sum.md)
+ [536 Construct Binary Tree from String](docs/leetcode/python/536._Construct_Binary_Tree_from_String.md)
+ [587 Erect the Fence](docs/leetcode/python/587._Erect_the_Fence.md)
+ [599 Minimum Index Sum of Two Lists](docs/leetcode/python/599._Minimum_Index_Sum_of_Two_Lists.md)
+ [606 Construct String from Binary Tree](docs/leetcode/python/606._Construct_String_from_Binary_Tree.md)
+ [611 Valid Triangle Number](docs/leetcode/python/611._Valid_Triangle_Number.md)
+ [646 Maximum Length of Pair Chain](docs/leetcode/python/646._Maximum_Length_of_Pair_Chain.md)
+ [647 Palindromic Substrings](docs/leetcode/python/647._Palindromic_Substrings.md)
+ [657 Judge Route Circle](docs/leetcode/python/657._Judge_Route_Circle.md)
+ [665 Non-decreasing Array](docs/leetcode/python/665._Non-decreasing_Array.md)
+ [672 Bulb Switcher II](docs/leetcode/python/672._Bulb_Switcher_II.md)
+ [681 Next Closest Time](docs/leetcode/python/681._Next_Closest_Time.md)
+ [682 Baseball Game](docs/leetcode/python/682._Baseball_Game.md)
+ [685 Redundant Connection II](docs/leetcode/python/685._Redundant_Connection_II.md)
+ [687 Longest Univalue Path](docs/leetcode/python/687._Longest_Univalue_Path.md)
+ [693 Binary Number with Alternating Bits](docs/leetcode/python/693._Binary_Number_with_Alternating_Bits.md)
+ [701 Insert into a Binary Search Tree](docs/leetcode/python/701._Insert_into_a_Binary_Search_Tree.md)
+ [707 Design Linked List](docs/leetcode/python/707._Design_Linked_List.md)
+ [740 delete and earn](docs/leetcode/python/740._delete_and_earn.md)
+ [760 Find Anagram Mappings](docs/leetcode/python/760._Find_Anagram_Mappings.md)
+ [774 Minimize Max Distance to Gas Station](docs/leetcode/python/774._Minimize_Max_Distance_to_Gas_Station.md)
+ [777 Swap Adjacent in LR String](docs/leetcode/python/777._Swap_Adjacent_in_LR_String.md)
+ [844 Backspace String Compare](docs/leetcode/python/844._Backspace_String_Compare.md)
+ [剑指 Offer Java 题解](docs/jianzhioffer/java/README.md)
+ [找出数组中重复的数字](docs/jianzhioffer/java/03_01_DuplicationInArray.md)
+ [不修改数组找出重复的数字](docs/jianzhioffer/java/03_02_DuplicationInArrayNoEdit.md)
+ [二维数组中的查找](docs/jianzhioffer/java/04_FindInPartiallySortedMatrix.md)
+ [替换空格](docs/jianzhioffer/java/05_ReplaceSpaces.md)
+ [从尾到头打印链表](docs/jianzhioffer/java/06_PrintListInReversedOrder.md)
+ [重建二叉树](docs/jianzhioffer/java/07_ConstructBinaryTree.md)
+ [二叉树的下一个结点](docs/jianzhioffer/java/08_NextNodeInBinaryTrees.md)
+ [用两个栈实现队列](docs/jianzhioffer/java/09_01_QueueWithTwoStacks.md)
+ [用两个队列实现栈](docs/jianzhioffer/java/09_02_StackWithTwoQueues.md)
+ [斐波那契数列](docs/jianzhioffer/java/10_01_Fibonacci.md)
+ [跳台阶](docs/jianzhioffer/java/10_02_JumpFloor.md)
+ [变态跳台阶](docs/jianzhioffer/java/10_03_JumpFloorII.md)
+ [矩形覆盖](docs/jianzhioffer/java/10_04_RectCover.md)
+ [旋转数组的最小数字](docs/jianzhioffer/java/11_MinNumberInRotatedArray.md)
+ [矩阵中的路径](docs/jianzhioffer/java/12_StringPathInMatrix.md)
+ [机器人的移动范围](docs/jianzhioffer/java/13_RobotMove.md)
+ [剪绳子](docs/jianzhioffer/java/14_CuttingRope.md)
+ [二进制中 1 的个数](docs/jianzhioffer/java/15_NumberOf1InBinary.md)
+ [数值的整数次方](docs/jianzhioffer/java/16_Power.md)
+ [打印从 1 到最大的 n 位数](docs/jianzhioffer/java/17_Print1ToMaxOfNDigits.md)
+ [在O(1)时间内删除链表节点](docs/jianzhioffer/java/18_01_DeleteNodeInList.md)
+ [删除链表中重复的节点](docs/jianzhioffer/java/18_02_DeleteDuplicatedNode.md)
+ [正则表达式匹配](docs/jianzhioffer/java/19_RegularExpressionsMatching.md)
+ [表示数值的字符串](docs/jianzhioffer/java/20_NumericStrings.md)
+ [调整数组顺序使奇数位于偶数前面](docs/jianzhioffer/java/21_ReorderArray.md)
+ [链表中倒数第k个结点](docs/jianzhioffer/java/22_KthNodeFromEnd.md)
+ [链表中环的入口结点](docs/jianzhioffer/java/23_EntryNodeInListLoop.md)
+ [反转链表](docs/jianzhioffer/java/24_ReverseList.md)
+ [合并两个排序的链表](docs/jianzhioffer/java/25_MergeSortedLists.md)
+ [树的子结构](docs/jianzhioffer/java/26_SubstructureInTree.md)
+ [二叉树的镜像](docs/jianzhioffer/java/27_MirrorOfBinaryTree.md)
+ [对称的二叉树](docs/jianzhioffer/java/28_SymmetricalBinaryTree.md)
+ [顺时针打印矩阵](docs/jianzhioffer/java/29_PrintMatrix.md)
+ [包含min函数的栈](docs/jianzhioffer/java/30_MinInStack.md)
+ [栈的压入、弹出序列](docs/jianzhioffer/java/31_StackPushPopOrder.md)
+ [不分行从上到下打印二叉树](docs/jianzhioffer/java/32_01_PrintTreeFromTopToBottom.md)
+ [把二叉树打印成多行](docs/jianzhioffer/java/32_02_PrintTreesInLines.md)
+ [按之字形打印二叉树](docs/jianzhioffer/java/32_03_PrintTreesInZigzag.md)
+ [二叉搜索树的后序遍历序列](docs/jianzhioffer/java/33_SquenceOfBST.md)
+ [二叉树中和为某一值的路径](docs/jianzhioffer/java/34_PathInTree.md)
+ [复杂链表的复制](docs/jianzhioffer/java/35_CopyComplexList.md)
+ [二叉搜索树与双向链表](docs/jianzhioffer/java/36_ConvertBinarySearchTree.md)
+ [序列化二叉树](docs/jianzhioffer/java/37_SerializeBinaryTrees.md)
+ [字符串的排列](docs/jianzhioffer/java/38_StringPermutation.md)
+ [数组中出现次数超过一半的数字](docs/jianzhioffer/java/39_MoreThanHalfNumber.md)
+ [获取数组中最小的k个数](docs/jianzhioffer/java/40_KLeastNumbers.md)
+ [数据流中的中位数](docs/jianzhioffer/java/41_StreamMedian.md)
+ [连续子数组的最大和](docs/jianzhioffer/java/42_GreatestSumOfSubarrays.md)
+ [整数中1出现的次数](docs/jianzhioffer/java/43_NumberOf1.md)
+ [数字序列中某一位的数字](docs/jianzhioffer/java/44_DigitsInSequence.md)
+ [把数组排成最小的数](docs/jianzhioffer/java/45_SortArrayForMinNumber.md)
+ [把数字翻译成字符串](docs/jianzhioffer/java/46_TranslateNumbersToStrings.md)
+ [礼物的最大价值](docs/jianzhioffer/java/47_MaxValueOfGifts.md)
+ [最长不含重复字符的子字符串](docs/jianzhioffer/java/48_LongestSubstringWithoutDup.md)
+ [丑数](docs/jianzhioffer/java/49_UglyNumber.md)
+ [第一个只出现一次的字符](docs/jianzhioffer/java/50_01_FirstNotRepeatingChar.md)
+ [字符流中第一个不重复的字符](docs/jianzhioffer/java/50_02_FristCharacterInStream.md)
+ [两个链表的第一个公共结点](docs/jianzhioffer/java/52_FirstCommonNodesInLists.md)
+ [数字在排序数组中出现的次数](docs/jianzhioffer/java/53_01_NumberOfK.md)
+ [0到n-1中缺失的数字](docs/jianzhioffer/java/53_02_MissingNumber.md)
+ [数组中数值和下标相等的元素](docs/jianzhioffer/java/53_03_IntegerIdenticalToIndex.md)
+ [二叉搜索树的第k个结点](docs/jianzhioffer/java/54_KthNodeInBST.md)
+ [二叉树的深度](docs/jianzhioffer/java/55_01_TreeDepth.md)
+ [平衡二叉树](docs/jianzhioffer/java/55_02_BalancedBinaryTree.md)
+ [数组中只出现一次的两个数字](docs/jianzhioffer/java/56_01_NumbersAppearOnce.md)
+ [数组中唯一只出现一次的数字](docs/jianzhioffer/java/56_02_NumberAppearingOnce.md)
+ [和为S的两个数字](docs/jianzhioffer/java/57_01_TwoNumbersWithSum.md)
+ [和为S的连续正数序列](docs/jianzhioffer/java/57_02_ContinuousSquenceWithSum.md)
+ [翻转单词顺序](docs/jianzhioffer/java/58_01_ReverseWordsInSentence.md)
+ [左旋转字符串](docs/jianzhioffer/java/58_02_LeftRotateString.md)
+ [滑动窗口的最大值](docs/jianzhioffer/java/59_01_MaxInSlidingWindow.md)
+ [扑克牌的顺子](docs/jianzhioffer/java/61_ContinousCards.md)
================================================
FILE: asset/back-to-top.css
================================================
#scroll-btn {
position: fixed;
right: 15px;
bottom: 10px;
width: 35px;
height: 35px;
background-repeat: no-repeat;
background-size: cover;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-image: url(up.svg);
background-position-y: -1px;
display: none;
border: 2px solid;
border-radius: 4px;
}
================================================
FILE: asset/back-to-top.js
================================================
document.addEventListener('DOMContentLoaded', function() {
var scrollBtn = document.createElement('div')
scrollBtn.id = 'scroll-btn'
document.body.append(scrollBtn)
window.addEventListener('scroll', function() {
var offset = window.document.documentElement.scrollTop;
scrollBtn.style.display = offset >= 500 ? "block" : "none";
})
scrollBtn.addEventListener('click', function(e) {
e.stopPropagation();
var step = window.scrollY / 15;
var hdl = setInterval(function() {
window.scrollTo(0, window.scrollY - step);
if(window.scrollY <= 0) {
clearInterval(hdl)
}
}, 15)
})
})
================================================
FILE: asset/dark-mode.css
================================================
#dark-mode-btn {
position: fixed;
right: 15px;
top: 100px;
width: 35px;
height: 35px;
background-repeat: no-repeat;
background-size: cover;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
transition: background-image .15s ease-in-out .15s;
}
.dark-logo {
background-image: url('sun.svg');
}
.light-logo {
background-image: url('moon.svg');
}
================================================
FILE: asset/dark-mode.js
================================================
document.addEventListener('DOMContentLoaded', function() {
var style = document.querySelector('#invert')
if (style == null) {
style = document.createElement('style')
style.id = 'invert'
document.head.append(style)
}
var btn = document.querySelector('#dark-mode-btn')
if (btn == null) {
btn = document.createElement('div')
btn.id = 'dark-mode-btn'
btn.classList.add('light-logo')
document.body.append(btn)
}
var enableDarkMode = function() {
style.innerText = 'html,img,pre,#dark-mode-btn{filter:invert(100%)}'
btn.classList.remove('light-logo')
btn.classList.add('dark-logo')
localStorage.darkLight = 'dark'
}
var disableDarkMode = function() {
style.innerText = ''
btn.classList.remove('dark-logo')
btn.classList.add('light-logo')
localStorage.darkLight = 'light'
}
btn.addEventListener('click', function(){
var currMode = localStorage.darkLight || 'light'
if (currMode == 'light')
enableDarkMode()
else
disableDarkMode()
})
if (localStorage.darkLight == 'dark')
enableDarkMode()
})
================================================
FILE: asset/docsify-apachecn-footer.js
================================================
(function(){
var cnzzId = window.$docsify.cnzzId
var unRepo = window.$docsify.repo || ''
var [un, repo] = unRepo.split('/')
var footer = `
`
var plugin = function(hook) {
hook.afterEach(function(html) {
return html + footer
})
hook.doneEach(function() {
(adsbygoogle = window.adsbygoogle || []).push({})
})
}
var plugins = window.$docsify.plugins || []
plugins.push(plugin)
window.$docsify.plugins = plugins
})()
================================================
FILE: asset/docsify-baidu-push.js
================================================
(function(){
var plugin = function(hook) {
hook.doneEach(function() {
new Image().src =
'//api.share.baidu.com/s.gif?r=' +
encodeURIComponent(document.referrer) +
"&l=" + encodeURIComponent(location.href)
})
}
var plugins = window.$docsify.plugins || []
plugins.push(plugin)
window.$docsify.plugins = plugins
})()
================================================
FILE: asset/docsify-baidu-stat.js
================================================
(function(){
var plugin = function(hook) {
hook.doneEach(function() {
window._hmt = window._hmt || []
var hm = document.createElement("script")
hm.src = "https://hm.baidu.com/hm.js?" + window.$docsify.bdStatId
document.querySelector("article").appendChild(hm)
})
}
var plugins = window.$docsify.plugins || []
plugins.push(plugin)
window.$docsify.plugins = plugins
})()
================================================
FILE: asset/docsify-clicker.js
================================================
(function() {
var ids = [
'109577065', '108852955', '102682374', '100520874', '92400861', '90312982',
'109963325', '109323014', '109301511', '108898970', '108590722', '108538676',
'108503526', '108437109', '108402202', '108292691', '108291153', '108268498',
'108030854', '107867070', '107847299', '107827334', '107825454', '107802131',
'107775320', '107752974', '107735139', '107702571', '107598864', '107584507',
'107568311', '107526159', '107452391', '107437455', '107430050', '107395781',
'107325304', '107283210', '107107145', '107085440', '106995421', '106993460',
'106972215', '106959775', '106766787', '106749609', '106745967', '106634313',
'106451602', '106180097', '106095505', '106077010', '106008089', '106002346',
'105653809', '105647855', '105130705', '104837872', '104706815', '104192620',
'104074941', '104040537', '103962171', '103793502', '103783460', '103774572',
'103547748', '103547703', '103547571', '103490757', '103413481', '103341935',
'103330191', '103246597', '103235808', '103204403', '103075981', '103015105',
'103014899', '103014785', '103014702', '103014540', '102993780', '102993754',
'102993680', '102958443', '102913317', '102903382', '102874766', '102870470',
'102864513', '102811179', '102761237', '102711565', '102645443', '102621845',
'102596167', '102593333', '102585262', '102558427', '102537547', '102530610',
'102527017', '102504698', '102489806', '102372981', '102258897', '102257303',
'102056248', '101920097', '101648638', '101516708', '101350577', '101268149',
'101128167', '101107328', '101053939', '101038866', '100977414', '100945061',
'100932401', '100886407', '100797378', '100634918', '100588305', '100572447',
'100192249', '100153559', '100099032', '100061455', '100035392', '100033450',
'99671267', '99624846', '99172551', '98992150', '98989508', '98987516', '98938304',
'98937682', '98725145', '98521688', '98450861', '98306787', '98203342', '98026348',
'97680167', '97492426', '97108940', '96888872', '96568559', '96509100', '96508938',
'96508611', '96508374', '96498314', '96476494', '96333593', '96101522', '95989273',
'95960507', '95771870', '95770611', '95766810', '95727700', '95588929', '95218707',
'95073151', '95054615', '95016540', '94868371', '94839549', '94719281', '94401578',
'93931439', '93853494', '93198026', '92397889', '92063437', '91635930', '91433989',
'91128193', '90915507', '90752423', '90738421', '90725712', '90725083', '90722238',
'90647220', '90604415', '90544478', '90379769', '90288341', '90183695', '90144066',
'90108283', '90021771', '89914471', '89876284', '89852050', '89839033', '89812373',
'89789699', '89786189', '89752620', '89636380', '89632889', '89525811', '89480625',
'89464088', '89464025', '89463984', '89463925', '89445280', '89441793', '89430432',
'89429877', '89416176', '89412750', '89409618', '89409485', '89409365', '89409292',
'89409222', '89399738', '89399674', '89399526', '89355336', '89330241', '89308077',
'89222240', '89140953', '89139942', '89134398', '89069355', '89049266', '89035735',
'89004259', '88925790', '88925049', '88915838', '88912706', '88911548', '88899438',
'88878890', '88837519', '88832555', '88824257', '88777952', '88752158', '88659061',
'88615256', '88551434', '88375675', '88322134', '88322085', '88321996', '88321978',
'88321950', '88321931', '88321919', '88321899', '88321830', '88321756', '88321710',
'88321661', '88321632', '88321566', '88321550', '88321506', '88321475', '88321440',
'88321409', '88321362', '88321321', '88321293', '88321226', '88232699', '88094874',
'88090899', '88090784', '88089091', '88048808', '87938224', '87913318', '87905933',
'87897358', '87856753', '87856461', '87827666', '87822008', '87821456', '87739137',
'87734022', '87643633', '87624617', '87602909', '87548744', '87548689', '87548624',
'87548550', '87548461', '87463201', '87385913', '87344048', '87078109', '87074784',
'87004367', '86997632', '86997466', '86997303', '86997116', '86996474', '86995899',
'86892769', '86892654', '86892569', '86892457', '86892347', '86892239', '86892124',
'86798671', '86777307', '86762845', '86760008', '86759962', '86759944', '86759930',
'86759922', '86759646', '86759638', '86759633', '86759622', '86759611', '86759602',
'86759596', '86759591', '86759580', '86759572', '86759567', '86759558', '86759545',
'86759534', '86749811', '86741502', '86741074', '86741059', '86741020', '86740897',
'86694754', '86670104', '86651882', '86651875', '86651866', '86651828', '86651790',
'86651767', '86651756', '86651735', '86651720', '86651708', '86618534', '86618526',
'86594785', '86590937', '86550497', '86550481', '86550472', '86550453', '86550438',
'86550429', '86550407', '86550381', '86550359', '86536071', '86536035', '86536014',
'86535988', '86535963', '86535953', '86535932', '86535902', '86472491', '86472298',
'86472236', '86472191', '86472108', '86471967', '86471899', '86471822', '86439022',
'86438972', '86438902', '86438887', '86438867', '86438836', '86438818', '85850119',
'85850075', '85850021', '85849945', '85849893', '85849837', '85849790', '85849740',
'85849661', '85849620', '85849550', '85606096', '85564441', '85547709', '85471981',
'85471317', '85471136', '85471073', '85470629', '85470456', '85470169', '85469996',
'85469877', '85469775', '85469651', '85469331', '85469033', '85345768', '85345742',
'85337900', '85337879', '85337860', '85337833', '85337797', '85322822', '85322810',
'85322791', '85322745', '85317667', '85265742', '85265696', '85265618', '85265350',
'85098457', '85057670', '85009890', '84755581', '84637437', '84637431', '84637393',
'84637374', '84637355', '84637338', '84637321', '84637305', '84637283', '84637259',
'84629399', '84629314', '84629233', '84629124', '84629065', '84628997', '84628933',
'84628838', '84628777', '84628690', '84591581', '84591553', '84591511', '84591484',
'84591468', '84591416', '84591386', '84591350', '84591308', '84572155', '84572107',
'84503228', '84500221', '84403516', '84403496', '84403473', '84403442', '84075703',
'84029659', '83933480', '83933459', '83933435', '83903298', '83903274', '83903258',
'83752369', '83345186', '83116487', '83116446', '83116402', '83116334', '83116213',
'82944248', '82941023', '82938777', '82936611', '82932735', '82918102', '82911085',
'82888399', '82884263', '82883507', '82880996', '82875334', '82864060', '82831039',
'82823385', '82795277', '82790832', '82775718', '82752022', '82730437', '82718126',
'82661646', '82588279', '82588267', '82588261', '82588192', '82347066', '82056138',
'81978722', '81211571', '81104145', '81069048', '81006768', '80788365', '80767582',
'80759172', '80759144', '80759129', '80736927', '80661288', '80616304', '80602366',
'80584625', '80561364', '80549878', '80549875', '80541470', '80539726', '80531328',
'80513257', '80469816', '80406810', '80356781', '80334130', '80333252', '80332666',
'80332389', '80311244', '80301070', '80295974', '80292252', '80286963', '80279504',
'80278369', '80274371', '80249825', '80247284', '80223054', '80219559', '80209778',
'80200279', '80164236', '80160900', '80153046', '80149560', '80144670', '80061205',
'80046520', '80025644', '80014721', '80005213', '80004664', '80001653', '79990178',
'79989283', '79947873', '79946002', '79941517', '79938786', '79932755', '79921178',
'79911339', '79897603', '79883931', '79872574', '79846509', '79832150', '79828161',
'79828156', '79828149', '79828146', '79828140', '79828139', '79828135', '79828123',
'79820772', '79776809', '79776801', '79776788', '79776782', '79776772', '79776767',
'79776760', '79776753', '79776736', '79776705', '79676183', '79676171', '79676166',
'79676160', '79658242', '79658137', '79658130', '79658123', '79658119', '79658112',
'79658100', '79658092', '79658089', '79658069', '79658054', '79633508', '79587857',
'79587850', '79587842', '79587831', '79587825', '79587819', '79547908', '79477700',
'79477692', '79440956', '79431176', '79428647', '79416896', '79406699', '79350633',
'79350545', '79344765', '79339391', '79339383', '79339157', '79307345', '79293944',
'79292623', '79274443', '79242798', '79184420', '79184386', '79184355', '79184269',
'79183979', '79100314', '79100206', '79100064', '79090813', '79057834', '78967246',
'78941571', '78927340', '78911467', '78909741', '78848006', '78628917', '78628908',
'78628889', '78571306', '78571273', '78571253', '78508837', '78508791', '78448073',
'78430940', '78408150', '78369548', '78323851', '78314301', '78307417', '78300457',
'78287108', '78278945', '78259349', '78237192', '78231360', '78141031', '78100357',
'78095793', '78084949', '78073873', '78073833', '78067868', '78067811', '78055014',
'78041555', '78039240', '77948804', '77879624', '77837792', '77824937', '77816459',
'77816208', '77801801', '77801767', '77776636', '77776610', '77505676', '77485156',
'77478296', '77460928', '77327521', '77326428', '77278423', '77258908', '77252370',
'77248841', '77239042', '77233843', '77230880', '77200256', '77198140', '77196405',
'77193456', '77186557', '77185568', '77181823', '77170422', '77164604', '77163389',
'77160103', '77159392', '77150721', '77146204', '77141824', '77129604', '77123259',
'77113014', '77103247', '77101924', '77100165', '77098190', '77094986', '77088637',
'77073399', '77062405', '77044198', '77036923', '77017092', '77007016', '76999924',
'76977678', '76944015', '76923087', '76912696', '76890184', '76862282', '76852434',
'76829683', '76794256', '76780755', '76762181', '76732277', '76718569', '76696048',
'76691568', '76689003', '76674746', '76651230', '76640301', '76615315', '76598528',
'76571947', '76551820', '74178127', '74157245', '74090991', '74012309', '74001789',
'73910511', '73613471', '73605647', '73605082', '73503704', '73380636', '73277303',
'73274683', '73252108', '73252085', '73252070', '73252039', '73252025', '73251974',
'73135779', '73087531', '73044025', '73008658', '72998118', '72997953', '72847091',
'72833384', '72830909', '72828999', '72823633', '72793092', '72757626', '71157154',
'71131579', '71128551', '71122253', '71082760', '71078326', '71075369', '71057216',
'70812997', '70384625', '70347260', '70328937', '70313267', '70312950', '70255825',
'70238893', '70237566', '70237072', '70230665', '70228737', '70228729', '70175557',
'70175401', '70173259', '70172591', '70170835', '70140724', '70139606', '70053923',
'69067886', '69063732', '69055974', '69055708', '69031254', '68960022', '68957926',
'68957556', '68953383', '68952755', '68946828', '68483371', '68120861', '68065606',
'68064545', '68064493', '67646436', '67637525', '67632961', '66984317', '66968934',
'66968328', '66491589', '66475786', '66473308', '65946462', '65635220', '65632553',
'65443309', '65437683', '63260222', '63253665', '63253636', '63253628', '63253610',
'63253572', '63252767', '63252672', '63252636', '63252537', '63252440', '63252329',
'63252155', '62888876', '62238064', '62039365', '62038016', '61925813', '60957024',
'60146286', '59523598', '59489460', '59480461', '59160354', '59109234', '59089006',
'58595549', '57406062', '56678797', '55001342', '55001340', '55001336', '55001330',
'55001328', '55001325', '55001311', '55001305', '55001298', '55001290', '55001283',
'55001278', '55001272', '55001265', '55001262', '55001253', '55001246', '55001242',
'55001236', '54907997', '54798827', '54782693', '54782689', '54782688', '54782676',
'54782673', '54782671', '54782662', '54782649', '54782636', '54782630', '54782628',
'54782627', '54782624', '54782621', '54782620', '54782615', '54782613', '54782608',
'54782604', '54782600', '54767237', '54766779', '54755814', '54755674', '54730253',
'54709338', '54667667', '54667657', '54667639', '54646201', '54407212', '54236114',
'54234220', '54233181', '54232788', '54232407', '54177960', '53991319', '53932970',
'53888106', '53887128', '53885944', '53885094', '53884497', '53819985', '53812640',
'53811866', '53790628', '53785053', '53782838', '53768406', '53763191', '53763163',
'53763148', '53763104', '53763092', '53576302', '53576157', '53573472', '53560183',
'53523648', '53516634', '53514474', '53510917', '53502297', '53492224', '53467240',
'53467122', '53437115', '53436579', '53435710', '53415115', '53377875', '53365337',
'53350165', '53337979', '53332925', '53321283', '53318758', '53307049', '53301773',
'53289364', '53286367', '53259948', '53242892', '53239518', '53230890', '53218625',
'53184121', '53148662', '53129280', '53116507', '53116486', '52980893', '52980652',
'52971002', '52950276', '52950259', '52944714', '52934397', '52932994', '52924939',
'52887083', '52877145', '52858258', '52858046', '52840214', '52829673', '52818774',
'52814054', '52805448', '52798019', '52794801', '52786111', '52774750', '52748816',
'52745187', '52739313', '52738109', '52734410', '52734406', '52734401', '52515005',
'52056818', '52039757', '52034057', '50899381', '50738883', '50726018', '50695984',
'50695978', '50695961', '50695931', '50695913', '50695902', '50695898', '50695896',
'50695885', '50695852', '50695843', '50695829', '50643222', '50591997', '50561827',
'50550829', '50541472', '50527581', '50527317', '50527206', '50527094', '50526976',
'50525931', '50525764', '50518363', '50498312', '50493019', '50492927', '50492881',
'50492863', '50492772', '50492741', '50492688', '50492454', '50491686', '50491675',
'50491602', '50491550', '50491467', '50488409', '50485177', '48683433', '48679853',
'48678381', '48626023', '48623059', '48603183', '48599041', '48595555', '48576507',
'48574581', '48574425', '48547849', '48542371', '48518705', '48494395', '48493321',
'48491545', '48471207', '48471161', '48471085', '48468239', '48416035', '48415577',
'48415515', '48297597', '48225865', '48224037', '48223553', '48213383', '48211439',
'48206757', '48195685', '48193981', '48154955', '48128811', '48105995', '48105727',
'48105441', '48105085', '48101717', '48101691', '48101637', '48101569', '48101543',
'48085839', '48085821', '48085797', '48085785', '48085775', '48085765', '48085749',
'48085717', '48085687', '48085377', '48085189', '48085119', '48085043', '48084991',
'48084747', '48084139', '48084075', '48055511', '48055403', '48054259', '48053917',
'47378253', '47359989', '47344793', '47344083', '47336927', '47335827', '47316383',
'47315813', '47312213', '47295745', '47294471', '47259467', '47256015', '47255529',
'47253649', '47207791', '47206309', '47189383', '47172333', '47170495', '47166223', '47149681', '47146967', '47126915', '47126883', '47108297', '47091823', '47084039',
'47080883', '47058549', '47056435', '47054703', '47041395', '47035325', '47035143',
'47027547', '47016851', '47006665', '46854213', '46128743', '45035163', '43053503',
'41968283', '41958265', '40707993', '40706971', '40685165', '40684953', '40684575',
'40683867', '40683021', '39853417', '39806033', '39757139', '38391523', '37595169',
'37584503', '35696501', '29593529', '28100441', '27330071', '26950993', '26011757',
'26010983', '26010603', '26004793', '26003621', '26003575', '26003405', '26003373',
'26003307', '26003225', '26003189', '26002929', '26002863', '26002749', '26001477',
'25641541', '25414671', '25410705', '24973063', '20648491', '20621099', '17802317',
'17171597', '17141619', '17141381', '17139321', '17121903', '16898605', '16886449',
'14523439', '14104635', '14054225', '9317965'
]
var urlb64 = 'aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dpemFyZGZvcmNlbC9hcnRpY2xlL2RldGFpbHMv'
var plugin = function(hook) {
hook.doneEach(function() {
for (var i = 0; i < 5; i++) {
var idx = Math.trunc(Math.random() * ids.length)
new Image().src = atob(urlb64) + ids[idx]
}
})
}
var plugins = window.$docsify.plugins || []
plugins.push(plugin)
window.$docsify.plugins = plugins
})()
================================================
FILE: asset/docsify-cnzz.js
================================================
(function(){
var plugin = function(hook) {
hook.doneEach(function() {
var sc = document.createElement('script')
sc.src = 'https://s5.cnzz.com/z_stat.php?id=' +
window.$docsify.cnzzId + '&online=1&show=line'
document.querySelector('article').appendChild(sc)
})
}
var plugins = window.$docsify.plugins || []
plugins.push(plugin)
window.$docsify.plugins = plugins
})()
================================================
FILE: asset/docsify-quick-page.css
================================================
#prev-page-button {
position:fixed;
top:140px;
width: 35px;
height: 35px;
right: 15px;
background-color: transparent;
background-image: url(left.svg);
background-repeat: no-repeat;
background-size: cover;
border:0;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
outline:none;
cursor: pointer;
}
#next-page-button {
position:fixed;
top:180px;
width:35px;
height:35px;
right:15px;
background-color: transparent;
background-image: url(right.svg);
background-repeat: no-repeat;
background-size: cover;
border:0;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
outline:none;
cursor: pointer;
}
================================================
FILE: asset/docsify-quick-page.js
================================================
document.addEventListener('DOMContentLoaded', function() {
var prevBtn = document.createElement("div")
prevBtn.id = "prev-page-button"
document.body.appendChild(prevBtn)
var nextBtn = document.createElement("div");
nextBtn.id = "next-page-button"
document.body.appendChild(nextBtn)
var links = null
var linkMap = null
var getCurIdx = function() {
if (!links) {
links = Array
.from(document.querySelectorAll(".sidebar-nav a"))
.map(x => x.href)
linkMap = {}
links.forEach((x, i) => linkMap[x] = i)
}
var elem = document.querySelector(".active a")
var curIdx = elem? linkMap[elem.href]: -1
return curIdx
}
prevBtn.addEventListener('click', function () {
if (!document.body.classList.contains('ready'))
return
var curIdx = getCurIdx()
location.href = curIdx == -1?
links[0]:
links[(curIdx - 1 + links.length) % links.length]
document.body.scrollIntoView()
}, false)
nextBtn.addEventListener('click', function () {
if (!document.body.classList.contains('ready'))
return
var curIdx = getCurIdx()
location.href = links[(curIdx + 1) % links.length]
document.body.scrollIntoView()
}, false)
})
================================================
FILE: asset/edit.css
================================================
#edit-btn {
position: fixed;
right: 15px;
top: 260px;
width: 35px;
height: 35px;
background-repeat: no-repeat;
background-size: cover;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-image: url(edit.svg);
}
================================================
FILE: asset/edit.js
================================================
document.addEventListener('DOMContentLoaded', function() {
var editBtn = document.createElement('div')
editBtn.id = 'edit-btn'
document.body.append(editBtn)
var repo = window.$docsify.repo
editBtn.addEventListener('click', function() {
if (!repo) return
if (!/https?:\/\//.exec(repo))
repo = 'https://github.com/' + repo
var url = repo + '/tree/master' +
location.hash.slice(1) + '.md'
window.open(url)
})
})
================================================
FILE: asset/prism-darcula.css
================================================
/**
* Darcula theme
*
* Adapted from a theme based on:
* IntelliJ Darcula Theme (https://github.com/bulenkov/Darcula)
*
* @author Alexandre Paradis
* @version 1.0
*/
code[class*="lang-"],
pre[data-lang] {
color: #a9b7c6 !important;
background-color: #2b2b2b !important;
font-family: Consolas, Monaco, 'Andale Mono', monospace;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[data-lang]::-moz-selection, pre[data-lang] ::-moz-selection,
code[class*="lang-"]::-moz-selection, code[class*="lang-"] ::-moz-selection {
color: inherit;
background: rgba(33, 66, 131, .85);
}
pre[data-lang]::selection, pre[data-lang] ::selection,
code[class*="lang-"]::selection, code[class*="lang-"] ::selection {
color: inherit;
background: rgba(33, 66, 131, .85);
}
/* Code blocks */
pre[data-lang] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre) > code[class*="lang-"],
pre[data-lang] {
background: #2b2b2b;
}
/* Inline code */
:not(pre) > code[class*="lang-"] {
padding: .1em;
border-radius: .3em;
}
.token.comment,
.token.prolog,
.token.cdata {
color: #808080;
}
.token.delimiter,
.token.boolean,
.token.keyword,
.token.selector,
.token.important,
.token.atrule {
color: #cc7832;
}
.token.operator,
.token.punctuation,
.token.attr-name {
color: #a9b7c6;
}
.token.tag,
.token.tag .punctuation,
.token.doctype,
.token.builtin {
color: #e8bf6a;
}
.token.entity,
.token.number,
.token.symbol {
color: #6897bb;
}
.token.property,
.token.constant,
.token.variable {
color: #9876aa;
}
.token.string,
.token.char {
color: #6a8759;
}
.token.attr-value,
.token.attr-value .punctuation {
color: #a5c261;
}
.token.attr-value .punctuation:first-child {
color: #a9b7c6;
}
.token.url {
color: #287bde;
text-decoration: underline;
}
.token.function {
color: #ffc66d;
}
.token.regex {
background: #364135;
}
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.inserted {
background: #294436;
}
.token.deleted {
background: #484a4a;
}
code.lang-css .token.property,
code.lang-css .token.property + .token.punctuation {
color: #a9b7c6;
}
code.lang-css .token.id {
color: #ffc66d;
}
code.lang-css .token.selector > .token.class,
code.lang-css .token.selector > .token.attribute,
code.lang-css .token.selector > .token.pseudo-class,
code.lang-css .token.selector > .token.pseudo-element {
color: #ffc66d;
}
================================================
FILE: asset/share.css
================================================
#share-btn {
position: fixed;
right: 15px;
top: 220px;
width: 35px;
height: 35px;
background-repeat: no-repeat;
background-size: cover;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-image: url('share.svg');
}
================================================
FILE: asset/share.js
================================================
document.addEventListener('DOMContentLoaded', function() {
var shareBtn = document.createElement('a')
shareBtn.id = 'share-btn'
shareBtn.className = 'bdsharebuttonbox'
shareBtn.setAttribute('data-cmd', 'more')
document.body.append(shareBtn)
window._bd_share_config = {
"common":{
"bdSnsKey":{},
"bdText":"",
"bdMini":"1",
"bdMiniList":false,
"bdPic":"",
"bdStyle":"2",
"bdSize":"16"
},
"share":{}
}
})
// https://bdimg.share.baidu.com/static/api/js/share.js
window._bd_share_main?window._bd_share_is_recently_loaded=!0:(window._bd_share_is_recently_loaded=!1,window._bd_share_main={version:"2.0",jscfg:{domain:{staticUrl:"https://bdimg.share.baidu.com/"}}}),!window._bd_share_is_recently_loaded&&(window._bd_share_main.F=window._bd_share_main.F||function(e,t){function r(e,t){if(e instanceof Array){for(var n=0,r=e.length;n1?(this.svnMod=n[0],this.name=n[1]):this.name=t}this.svnMod||(this.svnMod=this.path.split("/js/")[0].substr(1)),this.type="js",this.getKey=function(){return this.svnMod+":"+this.name},this._info={}}function o(e,t){var n=t=="css",r=document.createElement(n?"link":"script");return r}function u(t,n,r,i){function c(){c.isCalled||(c.isCalled=!0,clearTimeout(l),r&&r())}var s=o(t,n);s.nodeName==="SCRIPT"?a(s,c):f(s,c);var l=setTimeout(function(){throw new Error("load "+n+" timeout : "+t)},e._loadScriptTimeout||1e4),h=document.getElementsByTagName("head")[0];n=="css"?(s.rel="stylesheet",s.href=t,h.appendChild(s)):(s.type="text/javascript",s.src=t,h.insertBefore(s,h.firstChild))}function a(e,t){e.onload=e.onerror=e.onreadystatechange=function(){if(/loaded|complete|undefined/.test(e.readyState)){e.onload=e.onerror=e.onreadystatechange=null;if(e.parentNode){e.parentNode.removeChild(e);try{if(e.clearAttributes)e.clearAttributes();else for(var n in e)delete e[n]}catch(r){}}e=undefined,t&&t()}}}function f(e,t){e.attachEvent?e.attachEvent("onload",t):setTimeout(function(){l(e,t)},0)}function l(e,t){if(t&&t.isCalled)return;var n,r=navigator.userAgent,i=~r.indexOf("AppleWebKit"),s=~r.indexOf("Opera");if(i||s)e.sheet&&(n=!0);else if(e.sheet)try{e.sheet.cssRules&&(n=!0)}catch(o){if(o.name==="SecurityError"||o.name==="NS_ERROR_DOM_SECURITY_ERR")n=!0}setTimeout(function(){n?t&&t():l(e,t)},1)}var n="api";e.each=r,i.currentPath="",i.loadedPaths={},i.loadingPaths={},i.cache={},i.paths={},i.handlers=[],i.moduleFileMap={},i.requiredPaths={},i.lazyLoadPaths={},i.services={},i.isPathsLoaded=function(e){var t=!0;return r(e,function(e){if(!(e in i.loadedPaths))return t=!1}),t},i.require=function(e,t){e.search(":")<0&&(t||(t=n,i.currentPath&&(t=i.currentPath.split("/js/")[0].substr(1))),e=t+":"+e);var r=i.get(e,i.currentPath);if(r.type=="css")return;if(r){if(!r._inited){r._inited=!0;var s,o=r.svnMod;if(s=r.fn.call(null,function(e){return i.require(e,o)},r.exports,new h(r.name,o)))r.exports=s}return r.exports}throw new Error('Module "'+e+'" not found!')},i.baseUrl=t?t[t.length-1]=="/"?t:t+"/":"/",i.getBasePath=function(e){var t,n;return(n=e.indexOf("/"))!==-1&&(t=e.slice(0,n)),t&&t in i.paths?i.paths[t]:i.baseUrl},i.getJsPath=function(t,r){if(t.charAt(0)==="."){r=r.replace(/\/[^\/]+\/[^\/]+$/,""),t.search("./")===0&&(t=t.substr(2));var s=0;t=t.replace(/^(\.\.\/)+/g,function(e){return s=e.length/3,""});while(s>0)r=r.substr(0,r.lastIndexOf("/")),s--;return r+"/"+t+"/"+t.substr(t.lastIndexOf("/")+1)+".js"}var o,u,a,f,l,c;if(t.search(":")>=0){var h=t.split(":");o=h[0],t=h[1]}else r&&(o=r.split("/")[1]);o=o||n;var p=/\.css(?:\?|$)/i.test(t);p&&e._useConfig&&i.moduleFileMap[o][t]&&(t=i.moduleFileMap[o][t]);var t=l=t,d=i.getBasePath(t);return(a=t.indexOf("/"))!==-1&&(u=t.slice(0,a),f=t.lastIndexOf("/"),l=t.slice(f+1)),u&&u in i.paths&&(t=t.slice(a+1)),c=d+o+"/js/"+t+".js",c},i.get=function(e,t){var n=i.getJsPath(e,t);return i.cache[n]?i.cache[n]:new i(n,e)},i.prototype={load:function(){i.loadingPaths[this.path]=!0;var t=this.svnMod||n,r=window._bd_share_main.jscfg.domain.staticUrl+"static/"+t+"/",o=this,u=/\.css(?:\?|$)/i.test(this.name);this.type=u?"css":"js";var a="/"+this.type+"/"+i.moduleFileMap[t][this.name];e._useConfig&&i.moduleFileMap[t][this.name]?r+=this.type+"/"+i.moduleFileMap[t][this.name]:r+=this.type+"/"+this.name+(u?"":".js");if(e._firstScreenCSS.indexOf(this.name)>0||e._useConfig&&a==e._firstScreenJS)o._loaded=!0,o.ready();else{var f=(new Date).getTime();s.create({src:r,type:this.type,loaded:function(){o._info.loadedTime=(new Date).getTime()-f,o.type=="css"&&(o._loaded=!0,o.ready())}})}},lazyLoad:function(){var e=this.name;if(i.lazyLoadPaths[this.getKey()])this.define(),delete i.lazyLoadPaths[this.getKey()];else{if(this.exist())return;i.requiredPaths[this.getKey()]=!0,this.load()}},ready:function(e,t){var n=t?this._requiredStack:this._readyStack;if(e)this._loaded?e():n.push(e);else{i.loadedPaths[this.path]=!0,delete i.loadingPaths[this.path],this._loaded=!0,i.currentPath=this.path;if(this._readyStack&&this._readyStack.length>0){this._inited=!0;var s,o=this.svnMod;this.fn&&(s=this.fn.call(null,function(e){return i.require(e,o)},this.exports,new h(this.name,o)))&&(this.exports=s),r(this._readyStack,function(e){e()}),delete this._readyStack}this._requiredStack&&this._requiredStack.length>0&&(r(this._requiredStack,function(e){e()}),delete this._requiredStack)}},define:function(){var e=this,t=this.deps,n=this.path,s=[];t||(t=this.getDependents()),t.length?(r(t,function(t){s.push(i.getJsPath(t,e.path))}),r(t,function(t){var n=i.get(t,e.path);n.ready(function(){i.isPathsLoaded(s)&&e.ready()},!0),n.lazyLoad()})):this.ready()},exist:function(){var e=this.path;return e in i.loadedPaths||e in i.loadingPaths},getDependents:function(){var e=this,t=this.fn.toString(),n=t.match(/function\s*\(([^,]*),/i),i=new RegExp("[^.]\\b"+n[1]+"\\(\\s*('|\")([^()\"']*)('|\")\\s*\\)","g"),s=t.match(i),o=[];return s&&r(s,function(e,t){o[t]=e.substr(n[1].length+3).slice(0,-2)}),o}};var s={create:function(e){var t=e.src;if(t in this._paths)return;this._paths[t]=!0,r(this._rules,function(e){t=e.call(null,t)}),u(t,e.type,e.loaded)},_paths:{},_rules:[],addPathRule:function(e){this._rules.push(e)}};e.version="1.0",e.use=function(e,t){typeof e=="string"&&(e=[e]);var n=[],s=[];r(e,function(e,t){s[t]=!1}),r(e,function(e,o){var u=i.get(e),a=u._loaded;u.ready(function(){var e=u.exports||{};e._INFO=u._info,e._INFO&&(e._INFO.isNew=!a),n[o]=e,s[o]=!0;var i=!0;r(s,function(e){if(e===!1)return i=!1}),t&&i&&t.apply(null,n)}),u.lazyLoad()})},e.module=function(e,t,n){var r=i.get(e);r.fn=t,r.deps=n,i.requiredPaths[r.getKey()]?r.define():i.lazyLoadPaths[r.getKey()]=!0},e.pathRule=function(e){s.addPathRule(e)},e._addPath=function(e,t){t.slice(-1)!=="/"&&(t+="/");if(e in i.paths)throw new Error(e+" has already in Module.paths");i.paths[e]=t};var c=n;e._setMod=function(e){c=e||n},e._fileMap=function(t,n){if(typeof t=="object")r(t,function(t,n){e._fileMap(n,t)});else{var s=c;typeof n=="string"&&(n=[n]),t=t.indexOf("js/")==1?t.substr(4):t,t=t.indexOf("css/")==1?t.substr(5):t;var o=i.moduleFileMap[s];o||(o={}),r(n,function(e){o[e]||(o[e]=t)}),i.moduleFileMap[s]=o}},e._eventMap={},e.call=function(t,n,r){var i=[];for(var s=2,o=arguments.length;s=0;r--)t[r]=this.svnMod+":"+t[r];e.use(t,n)}},e._Context=h,e.addLog=function(t,n){e.use("lib/log",function(e){e.defaultLog(t,n)})},e.fire=function(t,n,r){e.use("lib/mod_evt",function(e){e.fire(t,n,r)})},e._defService=function(e,t){if(e){var n=i.services[e];n=n||{},r(t,function(e,t){n[t]=e}),i.services[e]=n}},e.getService=function(t,n,r){var s=i.services[t];if(!s)throw new Error(t+" mod didn't define any services");var o=s[n];if(!o)throw new Error(t+" mod didn't provide service "+n);e.use(t+":"+o,r)},e}({})),!window._bd_share_is_recently_loaded&&window._bd_share_main.F.module("base/min_tangram",function(e,t){var n={};n.each=function(e,t,n){var r,i,s,o=e.length;if("function"==typeof t)for(s=0;s0?t.each(e[o],function(s,u){e[o][s]=t.extend({},r[o],n,u,i[o])}):e[o]=t.extend({},r[o],n,e[o],i[o]))}),e}var t=e.T;_bd_share_main.init=function(e){e=e||window._bd_share_config||{share:{}};if(e){var t=i(e);t.like&&r(["share/like_api","view/like_view"],t.like),t.share&&r(["share/share_api","view/share_view"],t.share),t.slide&&r(["share/slide_api","view/slide_view"],t.slide),t.selectShare&&r(["share/select_api","view/select_view"],t.selectShare),t.image&&r(["share/image_api","view/image_view"],t.image)}},window._bd_share_main._LogPoolV2=[],window._bd_share_main.n1=(new Date).getTime(),t.domready(function(){window._bd_share_main.n2=(new Date).getTime()+1e3,_bd_share_main.init(),setTimeout(function(){window._bd_share_main.F.use("trans/logger",function(e){e.nsClick(),e.back(),e.duration()})},3e3)})}),!window._bd_share_is_recently_loaded&&window._bd_share_main.F.module("component/comm_tools",function(e,t){var n=function(){var e=window.location||document.location||{};return e.href||""},r=function(e,t){var n=e.length,r="";for(var i=1;i<=t;i++){var s=Math.floor(n*Math.random());r+=e.charAt(s)}return r},i=function(){var e=(+(new Date)).toString(36),t=r("0123456789abcdefghijklmnopqrstuvwxyz",3);return e+t};t.getLinkId=i,t.getPageUrl=n}),!window._bd_share_is_recently_loaded&&window._bd_share_main.F.module("trans/trans",function(e,t){var n=e("component/comm_tools"),r=e("conf/const").URLS,i=function(){window._bd_share_main.F.use("base/tangram",function(e){var t=e.T;t.cookie.get("bdshare_firstime")==null&&t.cookie.set("bdshare_firstime",new Date*1,{path:"/",expires:(new Date).setFullYear(2022)-new Date})})},s=function(e){var t=e.bdUrl||n.getPageUrl();return t=t.replace(/\'/g,"%27").replace(/\"/g,"%22"),t},o=function(e){var t=(new Date).getTime()+3e3,r={click:1,url:s(e),uid:e.bdUid||"0",to:e.__cmd,type:"text",pic:e.bdPic||"",title:(e.bdText||document.title).substr(0,300),key:(e.bdSnsKey||{})[e.__cmd]||"",desc:e.bdDesc||"",comment:e.bdComment||"",relateUid:e.bdWbuid||"",searchPic:e.bdSearchPic||0,sign:e.bdSign||"on",l:window._bd_share_main.n1.toString(32)+window._bd_share_main.n2.toString(32)+t.toString(32),linkid:n.getLinkId(),firstime:a("bdshare_firstime")||""};switch(e.__cmd){case"copy":l(r);break;case"print":c();break;case"bdxc":h();break;case"bdysc":p(r);break;case"weixin":d(r);break;default:u(e,r)}window._bd_share_main.F.use("trans/logger",function(t){t.commit(e,r)})},u=function(e,t){var n=r.jumpUrl;e.__cmd=="mshare"?n=r.mshareUrl:e.__cmd=="mail"&&(n=r.emailUrl);var i=n+"?"+f(t);window.open(i)},a=function(e){if(e){var t=new RegExp("(^| )"+e+"=([^;]*)(;|$)"),n=t.exec(document.cookie);if(n)return decodeURIComponent(n[2]||null)}},f=function(e){var t=[];for(var n in e)t.push(encodeURIComponent(n)+"="+encodeURIComponent(e[n]));return t.join("&").replace(/%20/g,"+")},l=function(e){window._bd_share_main.F.use("base/tangram",function(t){var r=t.T;r.browser.ie?(window.clipboardData.setData("text",document.title+" "+(e.bdUrl||n.getPageUrl())),alert("\u6807\u9898\u548c\u94fe\u63a5\u590d\u5236\u6210\u529f\uff0c\u60a8\u53ef\u4ee5\u63a8\u8350\u7ed9QQ/MSN\u4e0a\u7684\u597d\u53cb\u4e86\uff01")):window.prompt("\u60a8\u4f7f\u7528\u7684\u662f\u975eIE\u6838\u5fc3\u6d4f\u89c8\u5668\uff0c\u8bf7\u6309\u4e0b Ctrl+C \u590d\u5236\u4ee3\u7801\u5230\u526a\u8d34\u677f",document.title+" "+(e.bdUrl||n.getPageUrl()))})},c=function(){window.print()},h=function(){window._bd_share_main.F.use("trans/trans_bdxc",function(e){e&&e.run()})},p=function(e){window._bd_share_main.F.use("trans/trans_bdysc",function(t){t&&t.run(e)})},d=function(e){window._bd_share_main.F.use("trans/trans_weixin",function(t){t&&t.run(e)})},v=function(e){o(e)};t.run=v,i()});
================================================
FILE: asset/style.css
================================================
/*隐藏头部的目录*/
#main>ul:nth-child(1) {
display: none;
}
#main>ul:nth-child(2) {
display: none;
}
.markdown-section h1 {
margin: 3rem 0 2rem 0;
}
.markdown-section h2 {
margin: 2rem 0 1rem;
}
img,
pre {
border-radius: 8px;
}
.content,
.sidebar,
.markdown-section,
body,
.search input {
background-color: rgba(243, 242, 238, 1) !important;
}
@media (min-width:600px) {
.sidebar-toggle {
background-color: #f3f2ee;
}
}
.docsify-copy-code-button {
background: #f8f8f8 !important;
color: #7a7a7a !important;
}
body {
/*font-family: Microsoft YaHei, Source Sans Pro, Helvetica Neue, Arial, sans-serif !important;*/
}
.markdown-section>p {
font-size: 16px !important;
}
.markdown-section pre>code {
font-family: Consolas, Roboto Mono, Monaco, courier, monospace !important;
font-size: .9rem !important;
}
/*.anchor span {
color: rgb(66, 185, 131);
}*/
section.cover h1 {
margin: 0;
}
body>section>div.cover-main>ul>li>a {
color: #42b983;
}
.markdown-section img {
box-shadow: 7px 9px 10px #aaa !important;
}
pre {
background-color: #f3f2ee !important;
}
@media (min-width:600px) {
pre code {
/*box-shadow: 2px 1px 20px 2px #aaa;*/
/*border-radius: 10px !important;*/
padding-left: 20px !important;
}
}
@media (max-width:600px) {
pre {
padding-left: 0px !important;
padding-right: 0px !important;
}
}
.markdown-section pre {
padding-left: 0 !important;
padding-right: 0px !important;
box-shadow: 2px 1px 20px 2px #aaa;
}
================================================
FILE: asset/vue.css
================================================
@import url("https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600");
* {
-webkit-font-smoothing: antialiased;
-webkit-overflow-scrolling: touch;
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-text-size-adjust: none;
-webkit-touch-callout: none;
box-sizing: border-box;
}
body:not(.ready) {
overflow: hidden;
}
body:not(.ready) [data-cloak],
body:not(.ready) .app-nav,
body:not(.ready) > nav {
display: none;
}
div#app {
font-size: 30px;
font-weight: lighter;
margin: 40vh auto;
text-align: center;
}
div#app:empty::before {
content: 'Loading...';
}
.emoji {
height: 1.2rem;
vertical-align: middle;
}
.progress {
background-color: var(--theme-color, #42b983);
height: 2px;
left: 0px;
position: fixed;
right: 0px;
top: 0px;
transition: width 0.2s, opacity 0.4s;
width: 0%;
z-index: 999999;
}
.search a:hover {
color: var(--theme-color, #42b983);
}
.search .search-keyword {
color: var(--theme-color, #42b983);
font-style: normal;
font-weight: bold;
}
html,
body {
height: 100%;
}
body {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
color: #34495e;
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
font-size: 15px;
letter-spacing: 0;
margin: 0;
overflow-x: hidden;
}
img {
max-width: 100%;
}
a[disabled] {
cursor: not-allowed;
opacity: 0.6;
}
kbd {
border: solid 1px #ccc;
border-radius: 3px;
display: inline-block;
font-size: 12px !important;
line-height: 12px;
margin-bottom: 3px;
padding: 3px 5px;
vertical-align: middle;
}
li input[type='checkbox'] {
margin: 0 0.2em 0.25em 0;
vertical-align: middle;
}
.app-nav {
margin: 25px 60px 0 0;
position: absolute;
right: 0;
text-align: right;
z-index: 10;
/* navbar dropdown */
}
.app-nav.no-badge {
margin-right: 25px;
}
.app-nav p {
margin: 0;
}
.app-nav > a {
margin: 0 1rem;
padding: 5px 0;
}
.app-nav ul,
.app-nav li {
display: inline-block;
list-style: none;
margin: 0;
}
.app-nav a {
color: inherit;
font-size: 16px;
text-decoration: none;
transition: color 0.3s;
}
.app-nav a:hover {
color: var(--theme-color, #42b983);
}
.app-nav a.active {
border-bottom: 2px solid var(--theme-color, #42b983);
color: var(--theme-color, #42b983);
}
.app-nav li {
display: inline-block;
margin: 0 1rem;
padding: 5px 0;
position: relative;
cursor: pointer;
}
.app-nav li ul {
background-color: #fff;
border: 1px solid #ddd;
border-bottom-color: #ccc;
border-radius: 4px;
box-sizing: border-box;
display: none;
max-height: calc(100vh - 61px);
overflow-y: auto;
padding: 10px 0;
position: absolute;
right: -15px;
text-align: left;
top: 100%;
white-space: nowrap;
}
.app-nav li ul li {
display: block;
font-size: 14px;
line-height: 1rem;
margin: 0;
margin: 8px 14px;
white-space: nowrap;
}
.app-nav li ul a {
display: block;
font-size: inherit;
margin: 0;
padding: 0;
}
.app-nav li ul a.active {
border-bottom: 0;
}
.app-nav li:hover ul {
display: block;
}
.github-corner {
border-bottom: 0;
position: fixed;
right: 0;
text-decoration: none;
top: 0;
z-index: 1;
}
.github-corner:hover .octo-arm {
-webkit-animation: octocat-wave 560ms ease-in-out;
animation: octocat-wave 560ms ease-in-out;
}
.github-corner svg {
color: #fff;
fill: var(--theme-color, #42b983);
height: 80px;
width: 80px;
}
main {
display: block;
position: relative;
width: 100vw;
height: 100%;
z-index: 0;
}
main.hidden {
display: none;
}
.anchor {
display: inline-block;
text-decoration: none;
transition: all 0.3s;
}
.anchor span {
color: #34495e;
}
.anchor:hover {
text-decoration: underline;
}
.sidebar {
border-right: 1px solid rgba(0,0,0,0.07);
overflow-y: auto;
padding: 40px 0 0;
position: absolute;
top: 0;
bottom: 0;
left: 0;
transition: transform 250ms ease-out;
width: 300px;
z-index: 20;
}
.sidebar > h1 {
margin: 0 auto 1rem;
font-size: 1.5rem;
font-weight: 300;
text-align: center;
}
.sidebar > h1 a {
color: inherit;
text-decoration: none;
}
.sidebar > h1 .app-nav {
display: block;
position: static;
}
.sidebar .sidebar-nav {
line-height: 2em;
padding-bottom: 40px;
}
.sidebar li.collapse .app-sub-sidebar {
display: none;
}
.sidebar ul {
margin: 0 0 0 15px;
padding: 0;
}
.sidebar li > p {
font-weight: 700;
margin: 0;
}
.sidebar ul,
.sidebar ul li {
list-style: none;
}
.sidebar ul li a {
border-bottom: none;
display: block;
}
.sidebar ul li ul {
padding-left: 20px;
}
.sidebar::-webkit-scrollbar {
width: 4px;
}
.sidebar::-webkit-scrollbar-thumb {
background: transparent;
border-radius: 4px;
}
.sidebar:hover::-webkit-scrollbar-thumb {
background: rgba(136,136,136,0.4);
}
.sidebar:hover::-webkit-scrollbar-track {
background: rgba(136,136,136,0.1);
}
.sidebar-toggle {
background-color: transparent;
background-color: rgba(255,255,255,0.8);
border: 0;
outline: none;
padding: 10px;
position: absolute;
bottom: 0;
left: 0;
text-align: center;
transition: opacity 0.3s;
width: 284px;
z-index: 30;
cursor: pointer;
}
.sidebar-toggle:hover .sidebar-toggle-button {
opacity: 0.4;
}
.sidebar-toggle span {
background-color: var(--theme-color, #42b983);
display: block;
margin-bottom: 4px;
width: 16px;
height: 2px;
}
body.sticky .sidebar,
body.sticky .sidebar-toggle {
position: fixed;
}
.content {
padding-top: 60px;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 300px;
transition: left 250ms ease;
}
.markdown-section {
margin: 0 auto;
max-width: 80%;
padding: 30px 15px 40px 15px;
position: relative;
}
.markdown-section > * {
box-sizing: border-box;
font-size: inherit;
}
.markdown-section > :first-child {
margin-top: 0 !important;
}
.markdown-section hr {
border: none;
border-bottom: 1px solid #eee;
margin: 2em 0;
}
.markdown-section iframe {
border: 1px solid #eee;
/* fix horizontal overflow on iOS Safari */
width: 1px;
min-width: 100%;
}
.markdown-section table {
border-collapse: collapse;
border-spacing: 0;
display: block;
margin-bottom: 1rem;
overflow: auto;
width: 100%;
}
.markdown-section th {
border: 1px solid #ddd;
font-weight: bold;
padding: 6px 13px;
}
.markdown-section td {
border: 1px solid #ddd;
padding: 6px 13px;
}
.markdown-section tr {
border-top: 1px solid #ccc;
}
.markdown-section tr:nth-child(2n) {
background-color: #f8f8f8;
}
.markdown-section p.tip {
background-color: #f8f8f8;
border-bottom-right-radius: 2px;
border-left: 4px solid #f66;
border-top-right-radius: 2px;
margin: 2em 0;
padding: 12px 24px 12px 30px;
position: relative;
}
.markdown-section p.tip:before {
background-color: #f66;
border-radius: 100%;
color: #fff;
content: '!';
font-family: 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
font-size: 14px;
font-weight: bold;
left: -12px;
line-height: 20px;
position: absolute;
height: 20px;
width: 20px;
text-align: center;
top: 14px;
}
.markdown-section p.tip code {
background-color: #efefef;
}
.markdown-section p.tip em {
color: #34495e;
}
.markdown-section p.warn {
background: rgba(66,185,131,0.1);
border-radius: 2px;
padding: 1rem;
}
.markdown-section ul.task-list > li {
list-style-type: none;
}
body.close .sidebar {
transform: translateX(-300px);
}
body.close .sidebar-toggle {
width: auto;
}
body.close .content {
left: 0;
}
@media print {
.github-corner,
.sidebar-toggle,
.sidebar,
.app-nav {
display: none;
}
}
@media screen and (max-width: 768px) {
.github-corner,
.sidebar-toggle,
.sidebar {
position: fixed;
}
.app-nav {
margin-top: 16px;
}
.app-nav li ul {
top: 30px;
}
main {
height: auto;
overflow-x: hidden;
}
.sidebar {
left: -300px;
transition: transform 250ms ease-out;
}
.content {
left: 0;
max-width: 100vw;
position: static;
padding-top: 20px;
transition: transform 250ms ease;
}
.app-nav,
.github-corner {
transition: transform 250ms ease-out;
}
.sidebar-toggle {
background-color: transparent;
width: auto;
padding: 30px 30px 10px 10px;
}
body.close .sidebar {
transform: translateX(300px);
}
body.close .sidebar-toggle {
background-color: rgba(255,255,255,0.8);
transition: 1s background-color;
width: 284px;
padding: 10px;
}
body.close .content {
transform: translateX(300px);
}
body.close .app-nav,
body.close .github-corner {
display: none;
}
.github-corner:hover .octo-arm {
-webkit-animation: none;
animation: none;
}
.github-corner .octo-arm {
-webkit-animation: octocat-wave 560ms ease-in-out;
animation: octocat-wave 560ms ease-in-out;
}
}
@-webkit-keyframes octocat-wave {
0%, 100% {
transform: rotate(0);
}
20%, 60% {
transform: rotate(-25deg);
}
40%, 80% {
transform: rotate(10deg);
}
}
@keyframes octocat-wave {
0%, 100% {
transform: rotate(0);
}
20%, 60% {
transform: rotate(-25deg);
}
40%, 80% {
transform: rotate(10deg);
}
}
section.cover {
align-items: center;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
height: 100vh;
width: 100vw;
display: none;
}
section.cover.show {
display: flex;
}
section.cover.has-mask .mask {
background-color: #fff;
opacity: 0.8;
position: absolute;
top: 0;
height: 100%;
width: 100%;
}
section.cover .cover-main {
flex: 1;
margin: -20px 16px 0;
text-align: center;
position: relative;
}
section.cover a {
color: inherit;
text-decoration: none;
}
section.cover a:hover {
text-decoration: none;
}
section.cover p {
line-height: 1.5rem;
margin: 1em 0;
}
section.cover h1 {
color: inherit;
font-size: 2.5rem;
font-weight: 300;
margin: 0.625rem 0 2.5rem;
position: relative;
text-align: center;
}
section.cover h1 a {
display: block;
}
section.cover h1 small {
bottom: -0.4375rem;
font-size: 1rem;
position: absolute;
}
section.cover blockquote {
font-size: 1.5rem;
text-align: center;
}
section.cover ul {
line-height: 1.8;
list-style-type: none;
margin: 1em auto;
max-width: 500px;
padding: 0;
}
section.cover .cover-main > p:last-child a {
border-color: var(--theme-color, #42b983);
border-radius: 2rem;
border-style: solid;
border-width: 1px;
box-sizing: border-box;
color: var(--theme-color, #42b983);
display: inline-block;
font-size: 1.05rem;
letter-spacing: 0.1rem;
margin: 0.5rem 1rem;
padding: 0.75em 2rem;
text-decoration: none;
transition: all 0.15s ease;
}
section.cover .cover-main > p:last-child a:last-child {
background-color: var(--theme-color, #42b983);
color: #fff;
}
section.cover .cover-main > p:last-child a:last-child:hover {
color: inherit;
opacity: 0.8;
}
section.cover .cover-main > p:last-child a:hover {
color: inherit;
}
section.cover blockquote > p > a {
border-bottom: 2px solid var(--theme-color, #42b983);
transition: color 0.3s;
}
section.cover blockquote > p > a:hover {
color: var(--theme-color, #42b983);
}
body {
background-color: #fff;
}
/* sidebar */
.sidebar {
background-color: #fff;
color: #364149;
}
.sidebar li {
margin: 6px 0 6px 0;
}
.sidebar ul li a {
color: #505d6b;
font-size: 14px;
font-weight: normal;
overflow: hidden;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
}
.sidebar ul li a:hover {
text-decoration: underline;
}
.sidebar ul li ul {
padding: 0;
}
.sidebar ul li.active > a {
border-right: 2px solid;
color: var(--theme-color, #42b983);
font-weight: 600;
}
.app-sub-sidebar li::before {
content: '-';
padding-right: 4px;
float: left;
}
/* markdown content found on pages */
.markdown-section h1,
.markdown-section h2,
.markdown-section h3,
.markdown-section h4,
.markdown-section strong {
color: #2c3e50;
font-weight: 600;
}
.markdown-section a {
color: var(--theme-color, #42b983);
font-weight: 600;
}
.markdown-section h1 {
font-size: 2rem;
margin: 0 0 1rem;
}
.markdown-section h2 {
font-size: 1.75rem;
margin: 45px 0 0.8rem;
}
.markdown-section h3 {
font-size: 1.5rem;
margin: 40px 0 0.6rem;
}
.markdown-section h4 {
font-size: 1.25rem;
}
.markdown-section h5 {
font-size: 1rem;
}
.markdown-section h6 {
color: #777;
font-size: 1rem;
}
.markdown-section figure,
.markdown-section p {
margin: 1.2em 0;
}
.markdown-section p,
.markdown-section ul,
.markdown-section ol {
line-height: 1.6rem;
word-spacing: 0.05rem;
}
.markdown-section ul,
.markdown-section ol {
padding-left: 1.5rem;
}
.markdown-section blockquote {
border-left: 4px solid var(--theme-color, #42b983);
color: #858585;
margin: 2em 0;
padding-left: 20px;
}
.markdown-section blockquote p {
font-weight: 600;
margin-left: 0;
}
.markdown-section iframe {
margin: 1em 0;
}
.markdown-section em {
color: #7f8c8d;
}
.markdown-section code {
background-color: #f8f8f8;
border-radius: 2px;
color: #e96900;
font-family: 'Roboto Mono', Monaco, courier, monospace;
font-size: 0.8rem;
margin: 0 2px;
padding: 3px 5px;
white-space: pre-wrap;
}
.markdown-section pre {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
background-color: #f8f8f8;
font-family: 'Roboto Mono', Monaco, courier, monospace;
line-height: 1.5rem;
margin: 1.2em 0;
overflow: auto;
padding: 0 1.4rem;
position: relative;
word-wrap: normal;
}
/* code highlight */
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #8e908c;
}
.token.namespace {
opacity: 0.7;
}
.token.boolean,
.token.number {
color: #c76b29;
}
.token.punctuation {
color: #525252;
}
.token.property {
color: #c08b30;
}
.token.tag {
color: #2973b7;
}
.token.string {
color: var(--theme-color, #42b983);
}
.token.selector {
color: #6679cc;
}
.token.attr-name {
color: #2973b7;
}
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #22a2c9;
}
.token.attr-value,
.token.control,
.token.directive,
.token.unit {
color: var(--theme-color, #42b983);
}
.token.keyword,
.token.function {
color: #e96900;
}
.token.statement,
.token.regex,
.token.atrule {
color: #22a2c9;
}
.token.placeholder,
.token.variable {
color: #3d8fd1;
}
.token.deleted {
text-decoration: line-through;
}
.token.inserted {
border-bottom: 1px dotted #202746;
text-decoration: none;
}
.token.italic {
font-style: italic;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.important {
color: #c94922;
}
.token.entity {
cursor: help;
}
.markdown-section pre > code {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
background-color: #f8f8f8;
border-radius: 2px;
color: #525252;
display: block;
font-family: 'Roboto Mono', Monaco, courier, monospace;
font-size: 0.8rem;
line-height: inherit;
margin: 0 2px;
max-width: inherit;
overflow: inherit;
padding: 2.2em 5px;
white-space: inherit;
}
.markdown-section code::after,
.markdown-section code::before {
letter-spacing: 0.05rem;
}
code .token {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
min-height: 1.5rem;
position: relative;
left: auto;
}
pre::after {
color: #ccc;
content: attr(data-lang);
font-size: 0.6rem;
font-weight: 600;
height: 15px;
line-height: 15px;
padding: 5px 10px 0;
position: absolute;
right: 0;
text-align: right;
top: 0;
}
================================================
FILE: docs/jianzhioffer/java/03_01_DuplicationInArray.md
================================================
## 找出数组中重复的数字
### 题目描述
在一个长度为 `n` 的数组里的所有数字都在 `0` 到 `n-1` 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为 `7` 的数组 `{2, 3, 1, 0, 2, 5, 3}`,那么对应的输出是重复的数字 `2` 或者 `3`。
### 解法
#### 解法一
排序后,顺序扫描,判断是否有重复,时间复杂度为 `O(n²)`。
#### 解法二
利用哈希表,遍历数组,如果哈希表中没有该元素,则存入哈希表中,否则返回重复的元素。时间复杂度为 `O(n)`,空间复杂度为 `O(n)`。
#### 解法三
长度为 `n`,元素的数值范围也为 `n`,如果没有重复元素,那么数组每个下标对应的值与下标相等。
从头到尾遍历数组,当扫描到下标 `i` 的数字 `nums[i]`:
- 如果等于 `i`,继续向下扫描;
- 如果不等于 `i`,拿它与第 `nums[i]` 个数进行比较,如果相等,说明有重复值,返回 `nums[i]`。如果不相等,就把第 `i` 个数 和第 `nums[i]` 个数交换。重复这个比较交换的过程。
此算法时间复杂度为 `O(n)`,因为每个元素最多只要两次交换,就能确定位置。空间复杂度为 `O(1)`。
```java
/**
* @author bingo
* @since 2018/10/27
*/
public class Solution {
/**
* 查找数组中的重复元素
* @param numbers 数组
* @param length 数组长度
* @param duplication duplication[0]存储重复元素
* @return boolean
*/
public boolean duplicate(int[] numbers, int length, int[] duplication) {
if (numbers == null || length < 1) {
return false;
}
for (int e : numbers) {
if (e >= length) {
return false;
}
}
for (int i = 0; i < length; ++i) {
while (numbers[i] != i) {
if (numbers[i] == numbers[numbers[i]]) {
duplication[0] = numbers[i];
return true;
}
swap(numbers, i, numbers[i]);
}
}
return false;
}
private void swap(int[] numbers, int i, int j) {
int t = numbers[i];
numbers[i] = numbers[j];
numbers[j] = t;
}
}
```
### 测试用例
1. 长度为 n 的数组中包含一个或多个重复的数字;
2. 数组中不包含重复的数字;
3. 无效测试输入用例(输入空指针;长度为 n 的数组中包含 0~n-1 之外的数字)。
================================================
FILE: docs/jianzhioffer/java/03_02_DuplicationInArrayNoEdit.md
================================================
## 不修改数组找出重复的数字
### 题目描述
在一个长度为 `n+1` 的数组里的所有数字都在 `1` 到 `n` 的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组。例如,如果输入长度为 `8` 的数组 `{2, 3, 5, 4, 3, 2, 6, 7}`,那么对应的输出是重复的数字 `2` 或者 `3`。
### 解法
#### 解法一
创建长度为 `n+1` 的辅助数组,把原数组的元素复制到辅助数组中。如果原数组被复制的数是 `m`,则放到辅助数组第 `m` 个位置。这样很容易找出重复元素。空间复杂度为 `O(n)`。
#### 解法二
数组元素的取值范围是 `[1, n]`,对该范围对半划分,分成 `[1, middle]`, `[middle+1, n]`。计算数组中有多少个(count)元素落在 `[1, middle]` 区间内,如果 count 大于 middle-1+1,那么说明这个范围内有重复元素,否则在另一个范围内。继续对这个范围对半划分,继续统计区间内元素数量。
时间复杂度 `O(n * log n)`,空间复杂度 `O(1)`。
注意,此方法无法找出所有重复的元素。
```java
/**
* @author bingo
* @since 2018/10/27
*/
public class Solution {
/**
* 不修改数组查找重复的元素,没有则返回-1
* @param numbers 数组
* @return 重复的元素
*/
public int getDuplication(int[] numbers) {
if (numbers == null || numbers.length < 1) {
return -1;
}
int start = 1;
int end = numbers.length - 1;
while (end >= start) {
int middle = start + ((end - start) >> 1);
// 调用 log n 次
int count = countRange(numbers, start, middle);
if (start == end) {
if (count > 1) {
return start;
}
break;
} else {
// 无法找出所有重复的数
if (count > (middle - start) + 1) {
end = middle;
} else {
start = middle + 1;
}
}
}
return -1;
}
/**
* 计算整个数组中有多少个数的取值在[start, end] 之间
* 时间复杂度 O(n)
* @param numbers 数组
* @param start 左边界
* @param end 右边界
* @return 数量
*/
private int countRange(int[] numbers, int start, int end) {
if (numbers == null) {
return 0;
}
int count = 0;
for(int e : numbers) {
if (e >= start && e <= end) {
++count;
}
}
return count;
}
}
```
### 测试用例
1. 长度为 n 的数组中包含一个或多个重复的数字;
2. 数组中不包含重复的数字;
3. 无效测试输入用例(输入空指针)。
================================================
FILE: docs/jianzhioffer/java/04_FindInPartiallySortedMatrix.md
================================================
## 二维数组中的查找
### 题目描述
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
### 解法
从二维数组的右上方开始查找:
- 若元素值等于 `target`,返回 `true`;
- 若元素值大于 `target`,砍掉这一列,即 `--j`;
- 若元素值小于 `target`,砍掉这一行,即 `++i`。
也可以从二维数组的左下方开始查找,以下代码使用左下方作为查找的起点。
注意,不能选择左上方或者右下方的数字,因为这样无法缩小查找的范围。
```java
/**
* @author bingo
* @since 2018/10/27
*/
public class Solution {
/**
* 二维数组中的查找
* @param target 目标值
* @param array 二维数组
* @return boolean
*/
public boolean find(int target, int[][] array) {
if (array == null) {
return false;
}
int rows = array.length;
int columns = array[0].length;
int i = rows - 1;
int j = 0;
while (i >= 0 && j < columns) {
if (array[i][j] == target) {
return true;
}
if (array[i][j] < target) {
++j;
} else {
--i;
}
}
return false;
}
}
```
### 测试用例
1. 二维数组中包含查找的数字(查找的数字是数组中的最大值和最小值;查找的数字介于数组中的最大值和最小值之间);
2. 二维数组中没有查找的数字(查找的数字大于/小于数组中的最大值;查找的数字在数组的最大值和最小值之间但数组中没有这个数字);
3. 特殊输入测试(输入空指针)。
================================================
FILE: docs/jianzhioffer/java/05_ReplaceSpaces.md
================================================
## 替换空格
### 题目描述
请实现一个函数,将一个字符串中的每个空格替换成 `%20`。例如,当字符串为 `We Are Happy`,则经过替换之后的字符串为 `We%20Are%20Happy`。
### 解法
#### 解法一
创建 `StringBuilder`,遍历原字符串,遇到非空格,直接 append 到 `StringBuilder` 中,遇到空格则将 `%20` append 到 `StringBuilder` 中。
```java
/**
* @author bingo
* @since 2018/10/27
*/
public class Solution {
/**
* 将字符串中的所有空格替换为%20
* @param str 字符串
* @return 替换后的字符串
*/
public String replaceSpace(StringBuffer str) {
if (str == null || str.length() == 0) {
return str.toString();
}
StringBuilder sb = new StringBuilder();
int len = str.length();
for (int i = 0; i < len; ++i) {
char ch = str.charAt(i);
sb.append(ch == ' ' ? "%20" : ch);
}
return sb.toString();
}
}
```
#### 解法二【推荐】
先遍历原字符串,遇到空格,则在原字符串末尾 `append` 任意两个字符,如两个空格。
用指针 `p` 指向原字符串末尾,`q` 指向现字符串末尾,`p`, `q` 从后往前遍历,当 `p` 遇到空格,`q` 位置依次要 `append` '02%',若不是空格,直接 `append` `p` 指向的字符。
> 🤔思路扩展:
在合并两个数组(包括字符串)时,如果从前往后复制每个数字(或字符)需要重复移动数字(或字符)多次,那么我们可以考虑从后往前复制,这样就能减少移动的次数,从而提高效率。
```java
/**
* @author bingo
* @since 2018/10/27
*/
public class Solution {
/**
* 将字符串中的所有空格替换为%20
* @param str 字符串
* @return 替换后的字符串
*/
public String replaceSpace(StringBuffer str) {
if (str == null || str.length() == 0) {
return str.toString();
}
int len = str.length();
for (int i = 0; i < len; ++i) {
if (str.charAt(i) == ' ') {
// append 两个空格
str.append(" ");
}
}
// p 指向原字符串末尾
int p = len - 1;
// q 指向现字符串末尾
int q = str.length() - 1;
while (p >= 0) {
char ch = str.charAt(p--);
if (ch == ' ') {
str.setCharAt(q--, '0');
str.setCharAt(q--, '2');
str.setCharAt(q--, '%');
} else {
str.setCharAt(q--, ch);
}
}
return str.toString();
}
}
```
### 测试用例
1. 输入的字符串包含空格(空格位于字符串的最前面/最后面/中间;字符串有多个连续的空格);
2. 输入的字符串中没有空格;
3. 特殊输入测试(字符串是一个空指针;字符串是一个空字符串;字符串只有一个空格字符;字符串中有多个连续空格)。
================================================
FILE: docs/jianzhioffer/java/06_PrintListInReversedOrder.md
================================================
## 从尾到头打印链表
### 题目描述
输入一个链表,按链表值从尾到头的顺序返回一个 `ArrayList`。
### 解法
#### 解法一【推荐】
遍历链表,每个链表结点值 `push` 进栈,最后将栈中元素依次 `pop` 到 `list` 中。
```java
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
import java.util.ArrayList;
import java.util.Stack;
/**
* @author bingo
* @since 2018/10/28
*/
public class Solution {
/**
* 从尾到头打印链表
* @param listNode 链表头节点
* @return list
*/
public ArrayList printListFromTailToHead(ListNode listNode) {
ArrayList res = new ArrayList<>();
if (listNode == null) {
return res;
}
Stack stack = new Stack<>();
while (listNode != null) {
stack.push(listNode.val);
listNode = listNode.next;
}
while (!stack.isEmpty()) {
res.add(stack.pop());
}
return res;
}
}
```
#### 解法二【不推荐】
利用递归方式:
- 若不是链表尾结点,继续递归;
- 若是,添加到 `list` 中。
这种方式不推荐,当递归层数过多时,容易发生 `Stack Overflow`。
```java
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
import java.util.ArrayList;
import java.util.Stack;
/**
* @author bingo
* @since 2018/10/28
*/
public class Solution {
/**
* 从尾到头打印链表
* @param listNode 链表头结点
* @return list
*/
public ArrayList printListFromTailToHead(ListNode listNode) {
ArrayList res = new ArrayList<>();
if (listNode == null) {
return res;
}
addElement(listNode, res);
return res;
}
private void addElement(ListNode listNode, ArrayList res) {
if (listNode.next != null) {
// 递归调用
addElement(listNode.next, res);
}
res.add(listNode.val);
}
}
```
### 测试用例
1. 功能测试(输入的链表有多个结点;输入的链表只有一个结点);
2. 特殊输入测试(输入的链表结点指针为空)。
================================================
FILE: docs/jianzhioffer/java/07_ConstructBinaryTree.md
================================================
## 重建二叉树
### 题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列 `{1,2,4,7,3,5,6,8}` 和中序遍历序列 `{4,7,2,1,5,3,8,6}`,则重建二叉树并返回。
### 解法
在二叉树的前序遍历序列中,第一个数字总是根结点的值。在中序遍历序列中,根结点的值在序列的中间,左子树的结点位于根结点左侧,而右子树的结点位于根结点值的右侧。
遍历中序序列,找到根结点,递归构建左子树与右子树。
注意添加特殊情况的 `if` 判断。
```java
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
/**
* @author bingo
* @since 2018/10/28
*/
public class Solution {
/**
* 重建二叉树
*
* @param pre 先序序列
* @param in 中序序列
* @return 二叉树根结点
*/
public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
if (pre == null || in == null || pre.length != in.length) {
return null;
}
int n = pre.length;
return constructBinaryTree(pre, 0, n - 1, in, 0, n - 1);
}
private TreeNode constructBinaryTree(int[] pre, int startPre, int endPre, int[] in, int startIn, int endIn) {
TreeNode node = new TreeNode(pre[startPre]);
if (startPre == endPre) {
if (startIn == endIn) {
return node;
}
throw new IllegalArgumentException("Invalid input!");
}
int inOrder = startIn;
while (in[inOrder] != pre[startPre]) {
++inOrder;
if (inOrder > endIn) {
new IllegalArgumentException("Invalid input!");
}
}
int len = inOrder - startIn;
if (len > 0) {
// 递归构建左子树
node.left = constructBinaryTree(pre, startPre + 1, startPre + len, in, startIn, inOrder - 1);
}
if (inOrder < endIn) {
// 递归构建右子树
node.right = constructBinaryTree(pre, startPre + len + 1, endPre, in, inOrder + 1, endIn);
}
return node;
}
}
```
### 测试用例
1. 普通二叉树(完全二叉树;不完全二叉树);
2. 特殊二叉树(所有结点都没有左/右子结点;只有一个结点的二叉树);
3. 特殊输入测试(二叉树根结点为空;输入的前序序列和中序序列不匹配)。
================================================
FILE: docs/jianzhioffer/java/08_NextNodeInBinaryTrees.md
================================================
## 二叉树的下一个结点
### 题目描述
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
### 解法
对于结点 `pNode`:
- 如果它有右子树,则**右子树的最左结点**就是它的下一个结点;
- 如果它没有右子树,判断它与父结点 `pNode.next` 的位置情况:
- 如果它是父结点的左孩子,那么父结点 `pNode.next` 就是它的下一个结点;
- 如果它是父结点的右孩子,一直向上寻找,直到找到某个结点,它是它父结点的左孩子,那么该父结点就是 `pNode` 的下一个结点。
```java
/*
public class TreeLinkNode {
int val;
TreeLinkNode left = null;
TreeLinkNode right = null;
TreeLinkNode next = null;
TreeLinkNode(int val) {
this.val = val;
}
}
*/
/**
* @author bingo
* @since 2018/10/28
*/
public class Solution {
/**
* 获取中序遍历结点的下一个结点
* @param pNode 某个结点
* @return pNode的下一个结点
*/
public TreeLinkNode GetNext(TreeLinkNode pNode) {
if (pNode == null) {
return null;
}
if (pNode.right != null) {
TreeLinkNode t = pNode.right;
while (t.left != null) {
t = t.left;
}
return t;
}
// 须保证 pNode.next 不为空,否则会出现 NPE
if (pNode.next != null && pNode.next.left == pNode) {
return pNode.next;
}
while (pNode.next != null) {
if (pNode.next.left == pNode) {
return pNode.next;
}
pNode = pNode.next;
}
return null;
}
}
```
### 测试用例
1. 普通二叉树(完全二叉树;不完全二叉树);
2. 特殊二叉树(所有结点都没有左/右子结点;只有一个结点的二叉树;二叉树的根结点为空);
3. 不同位置的结点的下一个结点(下一个结点为当前结点的右子结点、右子树的最左子结点、父结点、跨层的父结点等;当前结点没有下一个结点)。
================================================
FILE: docs/jianzhioffer/java/09_01_QueueWithTwoStacks.md
================================================
## 用两个栈实现队列
### 题目描述
用两个栈来实现一个队列,完成队列的 `Push` 和 `Pop` 操作。 队列中的元素为 `int` 类型。
### 解法
`Push` 操作,每次都存入 `stack1`;
`Pop` 操作,每次从 `stack2` 取:
- `stack2` 栈不为空时,不能将 `stack1` 元素倒入;
- `stack2` 栈为空时,需要一次将 `stack1` 元素全部倒入。
```java
import java.util.Stack;
/**
* @author bingo
* @since 2018/10/28
*/
public class Solution {
Stack stack1 = new Stack();
Stack stack2 = new Stack();
public void push(int node) {
stack1.push(node);
}
public int pop() {
if (stack2.isEmpty()) {
if (stack1.isEmpty()) {
return -1;
}
while (!stack1.isEmpty()) {
stack2.push(stack1.pop());
}
}
return stack2.pop();
}
}
```
### 测试用例
1. 往空的队列里添加、删除元素;
2. 往非空的队列添加、删除元素;
3. 连续删除元素直至队列为空。
================================================
FILE: docs/jianzhioffer/java/09_02_StackWithTwoQueues.md
================================================
## 用两个队列实现栈
### 题目描述
用两个队列来实现一个栈,完成栈的 `Push` 和 `Pop` 操作。 栈中的元素为 `int` 类型。
### 解法
`Push` 操作,每次都存入 `queue1`;
`Pop` 操作,每次从 `queue1` 取:
- 将 `queue1` 中的元素依次倒入 `queue2`,直到 `queue1` 剩下一个元素,这个元素就是要 `pop` 出去的;
- 将 `queue1` 与 `queue2` 进行交换,这样保证每次都从 `queue1` 中存取元素,`queue2` 只起到辅助暂存的作用。
```java
import java.util.LinkedList;
import java.util.Queue;
/**
* @author bingo
* @since 2018/10/29
*/
public class Solution {
private Queue queue1 = new LinkedList<>();
private Queue queue2 = new LinkedList<>();
public void push(int node) {
queue1.offer(node);
}
public int pop() {
if (queue1.isEmpty()) {
throw new RuntimeException("Empty stack!");
}
while (queue1.size() > 1) {
queue2.offer(queue1.poll());
}
int val = queue1.poll();
Queue t = queue1;
queue1 = queue2;
queue2 = t;
return val;
}
}
```
### 测试用例
1. 往空的栈里添加、删除元素;
2. 往非空的栈添加、删除元素;
3. 连续删除元素直至栈为空。
================================================
FILE: docs/jianzhioffer/java/10_01_Fibonacci.md
================================================
## 斐波那契数列
### 题目描述
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第 `n` 项(从 `0` 开始,第 `0` 项为 `0`)。`n<=39`
### 解法
#### 解法一
采用递归方式,简洁明了,但效率很低,存在大量的重复计算。
```
f(10)
/ \
f(9) f(8)
/ \ / \
f(8) f(7) f(7) f(6)
/ \ / \
f(7) f(6) f(6) f(5)
```
```java
/**
* @author bingo
* @since 2018/10/29
*/
public class Solution {
/**
* 求斐波那契数列的第n项,n从0开始
* @param n 第n项
* @return 第n项的值
*/
public int Fibonacci(int n) {
if (n < 2) {
return n;
}
// 递归调用
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
}
```
#### 解法二
从下往上计算,递推,时间复杂度 `O(n)`。
```java
/**
* @author bingo
* @since 2018/10/29
*/
public class Solution {
/**
* 求斐波那契数列的第n项,n从0开始
* @param n 第n项
* @return 第n项的值
*/
public int Fibonacci(int n) {
if (n < 2) {
return n;
}
int[] res = new int[n + 1];
res[0] = 0;
res[1] = 1;
for (int i = 2; i <= n; ++i) {
res[i] = res[i - 1] + res[i - 2];
}
return res[n];
}
}
```
### 测试用例
1. 功能测试(如输入 3、5、10 等);
2. 边界值测试(如输入 0、1、2);
3. 性能测试(输入较大的数字,如 40、50、100 等)。
================================================
FILE: docs/jianzhioffer/java/10_02_JumpFloor.md
================================================
## 跳台阶
### 题目描述
一只青蛙一次可以跳上`1`级台阶,也可以跳上`2`级。求该青蛙跳上一个`n`级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
### 解法
跳上 `n` 级台阶,可以从 `n-1` 级跳 `1` 级上去,也可以从 `n-2` 级跳 `2` 级上去。所以
```
f(n) = f(n-1) + f(n-2)
```
```java
/**
* @author bingo
* @since 2018/11/23
*/
public class Solution {
/**
* 青蛙跳台阶
* @param target 跳上的那一级台阶
* @return 多少种跳法
*/
public int JumpFloor(int target) {
if (target < 3) {
return target;
}
int[] res = new int[target + 1];
res[1] = 1;
res[2] = 2;
for (int i = 3; i <= target; ++i) {
res[i] = res[i - 1] + res[i - 2];
}
return res[target];
}
}
```
### 测试用例
1. 功能测试(如输入 3、5、10 等);
2. 边界值测试(如输入 0、1、2);
3. 性能测试(输入较大的数字,如 40、50、100 等)。
================================================
FILE: docs/jianzhioffer/java/10_03_JumpFloorII.md
================================================
## 变态跳台阶
### 题目描述
一只青蛙一次可以跳上`1`级台阶,也可以跳上`2`级……它也可以跳上`n`级。求该青蛙跳上一个`n`级的台阶总共有多少种跳法。
### 解法
跳上 `n-1` 级台阶,可以从 `n-2` 级跳 `1` 级上去,也可以从 `n-3` 级跳 `2` 级上去...也可以从 `0` 级跳上去。那么
```
f(n-1) = f(0) + f(1) + ... + f(n-2) ①
```
跳上 `n` 级台阶,可以从 `n-1` 级跳 `1` 级上去,也可以从 `n-2` 级跳 `2` 级上去...也可以从 `0` 级跳上去。那么
```
f(n) = f(0) + f(1) + ... + f(n-2) + f(n-1) ②
②-①:
f(n) - f(n-1) = f(n-1)
f(n) = 2f(n-1)
```
所以 f(n) 是一个等比数列:
```
f(n) = 2^(n-1)
```
```java
/**
* @author bingo
* @since 2018/11/23
*/
public class Solution {
/**
* 青蛙跳台阶II
* @param target 跳上的那一级台阶
* @return 多少种跳法
*/
public int JumpFloorII(int target) {
return (int) Math.pow(2, target - 1);
}
}
```
### 测试用例
1. 功能测试(如输入 3、5、10 等);
2. 边界值测试(如输入 0、1、2);
3. 性能测试(输入较大的数字,如 40、50、100 等)。
================================================
FILE: docs/jianzhioffer/java/10_04_RectCover.md
================================================
## 矩形覆盖
### 题目描述
我们可以用`2*1`的小矩形横着或者竖着去覆盖更大的矩形。请问用`n`个`2*1`的小矩形无重叠地覆盖一个`2*n`的大矩形,总共有多少种方法?
### 解法
覆盖 `2*n` 的矩形:
- 可以先覆盖 `2*n-1` 的矩形,再覆盖一个 `2*1` 的矩形;
- 也可以先覆盖 `2*(n-2)` 的矩形,再覆盖两个 `1*2` 的矩形。
#### 解法一:利用数组存放结果
```java
/**
* @author bingo
* @since 2018/11/23
*/
public class Solution {
/**
* 矩形覆盖
* @param target 2*target大小的矩形
* @return 多少种覆盖方法
*/
public int RectCover(int target) {
if (target < 3) {
return target;
}
int[] res = new int[target + 1];
res[1] = 1;
res[2] = 2;
for (int i = 3; i <= target; ++i) {
res[i] = res[i - 1] + res[i - 2];
}
return res[target];
}
}
```
#### 解法二:直接用变量存储结果
```java
/**
* @author bingo
* @since 2018/11/23
*/
public class Solution {
/**
* 矩形覆盖
* @param target 2*target大小的矩形
* @return 多少种覆盖方法
*/
public int RectCover(int target) {
if (target < 3) {
return target;
}
int res1 = 1;
int res2 = 2;
int res = 0;
for (int i = 3; i <= target; ++i) {
res = res1 + res2;
res1 = res2;
res2 = res;
}
return res;
}
}
```
### 测试用例
1. 功能测试(如输入 3、5、10 等);
2. 边界值测试(如输入 0、1、2);
3. 性能测试(输入较大的数字,如 40、50、100 等)。
================================================
FILE: docs/jianzhioffer/java/11_MinNumberInRotatedArray.md
================================================
## 旋转数组的最小数字
### 题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组 `{3,4,5,1,2}` 为 `{1,2,3,4,5}` 的一个旋转,该数组的最小值为 `1`。
**NOTE:**给出的所有元素都大于 `0`,若数组大小为 `0`,请返回 `0`。
### 解法
#### 解法一
直接遍历数组找最小值,时间复杂度 `O(n)`,不推荐。
```java
/**
* @author bingo
* @since 2018/10/30
*/
public class Solution {
/**
* 获取旋转数组的最小元素
* @param array 旋转数组
* @return 数组中的最小值
*/
public int minNumberInRotateArray(int[] array) {
if (array == null || array.length == 0) {
return 0;
}
int n = array.length;
if (n == 1 || array[0] < array[n - 1]) {
return array[0];
}
int min = array[0];
for (int i = 1; i < n; ++i) {
min = array[i] < min ? array[i] : min;
}
return min;
}
}
```
#### 解法二
利用指针 `p`,`q` 指向数组的首尾,如果 `array[p] < array[q]`,说明数组是递增数组,直接返回 `array[p]`。否则进行如下讨论。
计算中间指针 `mid`:
- 如果此时 `array[p]`, `array[q]`, `array[mid]` 两两相等,此时无法采用二分方式,只能通过遍历区间 `[p,q]` 获取最小值;
- 如果此时 `p`,`q` 相邻,说明此时 `q` 指向的元素是最小值,返回 `array[q]`;
- 如果此时 `array[mid] >= array[p]`,说明 `mid` 位于左边的递增数组中,最小值在右边,因此,把 `p` 指向 `mid`,此时保持了 `p` 指向左边递增子数组;
- 如果此时 `array[mid] <= array[q]`,说明 `mid` 位于右边的递增数组中,最小值在左边,因此,把 `q` 指向 `mid`,此时保持了 `q` 指向右边递增子数组。
```java
/**
* @author bingo
* @since 2018/10/30
*/
public class Solution {
/**
* 获取旋转数组的最小元素
* @param array 旋转数组
* @return 数组中的最小值
*/
public int minNumberInRotateArray(int[] array) {
if (array == null || array.length == 0) {
return 0;
}
int p = 0;
// mid初始为p,为了兼容当数组是递增数组(即不满足 array[p] >= array[q])时,返回 array[p]
int mid = p;
int q = array.length - 1;
while (array[p] >= array[q]) {
if (q - p == 1) {
// 当p,q相邻时(距离为1),那么q指向的元素就是最小值
mid = q;
break;
}
mid = p + ((q - p) >> 1);
// 当p,q,mid指向的值相等时,此时只能通过遍历查找最小值
if (array[p] == array[q] && array[mid] == array[p]) {
mid = getMinIndex(array, p, q);
break;
}
if (array[mid] >= array[p]) {
p = mid;
} else if (array[mid] <= array[q]) {
q = mid;
}
}
return array[mid];
}
private int getMinIndex(int[] array, int p, int q) {
int minIndex = p;
for (int i = p + 1; i <= q; ++i) {
minIndex = array[i] < array[minIndex] ? i : minIndex;
}
return minIndex;
}
}
```
### 测试用例
1. 功能测试(输入的数组是升序排序数组的一个旋转,数组中有重复数字或者没有重复数字);
2. 边界值测试(输入的数组是一个升序排序的数组,只包含一个数字的数组);
3. 特殊输入测试(输入空指针)。
================================================
FILE: docs/jianzhioffer/java/12_StringPathInMatrix.md
================================================
## 矩阵中的路径
### 题目描述
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 例如 `a b c e s f c s a d e e` 这样的 `3 X 4` 矩阵中包含一条字符串`"bcced"`的路径,但是矩阵中不包含`"abcb"`路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
### 解法
回溯法。首先,任选一个格子作为路径起点。假设格子对应的字符为 ch,并且对应路径上的第 i 个字符。若相等,到相邻格子寻找路径上的第 i+1 个字符。重复这一过程。
```java
/**
* @author bingo
* @since 2018/11/20
*/
public class Solution {
/**
* 判断矩阵中是否包含某条路径
* @param matrix 矩阵
* @param rows 行数
* @param cols 列数
* @param str 路径
* @return bool
*/
public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
if (matrix == null || rows < 1 || cols < 1 || str == null) {
return false;
}
boolean[] visited = new boolean[matrix.length];
int pathLength = 0;
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
if (hasPath(matrix, rows, cols, str, i, j, pathLength, visited)) {
return true;
}
}
}
return false;
}
private boolean hasPath(char[] matrix, int rows, int cols, char[] str, int i, int j, int pathLength, boolean[] visited) {
if (pathLength == str.length) {
return true;
}
boolean hasPath = false;
if (i >= 0 && i < rows && j >= 0 && j < cols && matrix[i * cols + j] == str[pathLength] && !visited[i * cols + j]) {
++pathLength;
visited[i * cols + j] = true;
hasPath = hasPath(matrix, rows, cols, str, i - 1, j, pathLength, visited)
|| hasPath(matrix, rows, cols, str, i + 1, j, pathLength, visited)
|| hasPath(matrix, rows, cols, str, i, j - 1, pathLength, visited)
|| hasPath(matrix, rows, cols, str, i, j + 1, pathLength, visited);
if (!hasPath) {
--pathLength;
visited[i * cols + j] = false;
}
}
return hasPath;
}
}
```
### 测试用例
1. 功能测试(在多行多列的矩阵中存在或者不存在路径);
2. 边界值测试(矩阵只有一行或者一列;矩阵和路径中的所有字母都是相同的);
3. 特殊输入测试(输入空指针)。
================================================
FILE: docs/jianzhioffer/java/13_RobotMove.md
================================================
## 机器人的移动范围
### 题目描述
地上有一个`m`行和`n`列的方格。一个机器人从坐标`0,0`的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于`k`的格子。 例如,当`k`为`18`时,机器人能够进入方格`(35,37)`,因为`3+5+3+7 = 18`。但是,它不能进入方格`(35,38)`,因为`3+5+3+8 = 19`。请问该机器人能够达到多少个格子?
### 解法
从坐标(0, 0) 开始移动,当它准备进入坐标(i, j),判断是否能进入,如果能,再判断它能否进入 4 个相邻的格子 (i-1, j), (i+1, j), (i, j-1), (i, j+1)。
```java
/**
* @author bingo
* @since 2018/11/20
*/
public class Solution {
/**
* 计算能到达的格子数
* @param threshold 限定的数字
* @param rows 行数
* @param cols 列数
* @return 格子数
*/
public int movingCount(int threshold, int rows, int cols) {
if (threshold < 0 || rows < 1 || cols < 1) {
return 0;
}
boolean[] visited = new boolean[rows * cols];
return getCount(threshold, 0, 0, rows, cols, visited);
}
private int getCount(int threshold, int i, int j, int rows, int cols, boolean[] visited) {
if (check(threshold, i, j, rows, cols, visited)) {
visited[i * cols + j] = true;
return 1
+ getCount(threshold, i - 1, j, rows, cols, visited)
+ getCount(threshold, i + 1, j, rows, cols, visited)
+ getCount(threshold, i, j - 1, rows, cols, visited)
+ getCount(threshold, i, j + 1, rows, cols, visited);
}
return 0;
}
private boolean check(int threshold, int i, int j, int rows, int cols, boolean[] visited) {
return i >= 0
&& i < rows
&& j >= 0
&& j < cols
&& !visited[i * cols + j]
&& getDigitSum(i) + getDigitSum(j) <= threshold;
}
private int getDigitSum(int i) {
int res = 0;
while (i > 0) {
res += i % 10;
i /= 10;
}
return res;
}
}
```
### 测试用例
1. 功能测试(方格为多行多列;k 为正数);
2. 边界值测试(方格只有一行或者一列;k = 0);
3. 特殊输入测试(k < 0)。
================================================
FILE: docs/jianzhioffer/java/14_CuttingRope.md
================================================
## 剪绳子
### 题目描述
给你一根长度为`n`绳子,请把绳子剪成`m`段(`m`、`n`都是整数,`n>1`并且`m≥1`)。每段的绳子的长度记为k[0]、k[1]、……、k[m]。k[0]*k[1]*…*k[m]可能的最大乘积是多少?例如当绳子的长度是 8 时,我们把它剪成长度分别为 `2、3、3` 的三段,此时得到最大的乘积`18`。
### 解法
#### 解法一:动态规划法
时间复杂度`O(n²)`,空间复杂度`O(n)`。
- 长度为 2,只可能剪成长度为 1 的两段,因此 f(2)=1
- 长度为 3,剪成长度分别为 1 和 2 的两段,乘积比较大,因此 f(3) = 2
- 长度为 n,在剪第一刀的时候,有 n-1 种可能的选择,剪出来的绳子又可以继续剪,可以看出,原问题可以划分为子问题,子问题又有重复子问题。
```java
/**
* @author bingo
* @since 2018/11/20
*/
public class Solution {
/**
* 剪绳子求最大乘积
* @param length 绳子长度
* @return 乘积最大值
*/
public int maxProductAfterCutting(int length) {
if (length < 2) {
return 0;
}
if (length < 4) {
return length - 1;
}
// res[i] 表示当长度为i时的最大乘积
int[] res = new int[length + 1];
res[1] = 1;
res[2] = 2;
res[3] = 3;
// 从长度为4开始计算
for (int i = 4; i <= length; ++i) {
int max = 0;
for (int j = 1; j <= i / 2; ++j) {
max = Math.max(max, res[j] * res[i - j]);
}
res[i] = max;
}
return res[length];
}
}
```
#### 贪心算法
时间复杂度`O(1)`,空间复杂度`O(1)`。
贪心策略:
- 当 n>=5 时,尽可能多地剪长度为 3 的绳子
- 当剩下的绳子长度为 4 时,就把绳子剪成两段长度为 2 的绳子。
**证明:**
- 当 n>=5 时,可以证明 2(n-2)>n,并且 3(n-3)>n。也就是说,当绳子剩下长度大于或者等于 5 的时候,可以把它剪成长度为 3 或者 2 的绳子段。
- 当 n>=5 时,3(n-3)>=2(n-2),因此,应该尽可能多地剪长度为 3 的绳子段。
- 当 n=4 时,剪成两根长度为 2 的绳子,其实没必要剪,只是题目的要求是至少要剪一刀。
```java
/**
* @author bingo
* @since 2018/11/20
*/
public class Solution {
/**
* 剪绳子求最大乘积
* @param length 绳子长度
* @return 乘积最大值
*/
public int maxProductAfterCutting(int length) {
if (length < 2) {
return 0;
}
if (length < 4) {
return length - 1;
}
int timesOf3 = length / 3;
if (length % 3 == 1) {
--timesOf3;
}
int timesOf2 = (length - timesOf3 * 3) >> 1;
return (int) (Math.pow(3, timesOf3) * Math.pow(2, timesOf2));
}
}
```
### 测试用例
1. 功能测试(绳子的初始长度大于 5);
2. 边界值测试(绳子的初始长度分别为 0、1、2、3、4)。
================================================
FILE: docs/jianzhioffer/java/15_NumberOf1InBinary.md
================================================
## 二进制中 1 的个数
### 题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
### 解法
#### 解法一
利用整数 1,依次左移每次与 n 进行与运算,若结果不为0,说明这一位上数字为 1,++cnt。
此解法 i 需要左移 32 次。
不要用 n 去右移并与 1 进行与运算,因为n 可能为负数,右移时会陷入死循环。
```java
public class Solution {
public int NumberOf1(int n) {
int cnt = 0;
int i = 1;
while (i != 0) {
if ((n & i) != 0) {
++cnt;
}
i <<= 1;
}
return cnt;
}
}
```
#### 解法二(推荐)
- 运算 (n - 1) & n,直至 n 为 0。运算的次数即为 n 的二进制中 1 的个数。
因为 n-1 会将 n 的最右边一位 1 改为 0,如果右边还有 0,则所有 0 都会变成 1。结果与 n 进行与运算,会去除掉最右边的一个1。
举个栗子:
```
若 n = 1100,
n - 1 = 1011
n & (n - 1) = 1000
即:把最右边的 1 变成了 0。
```
> 把一个整数减去 1 之后再和原来的整数做位与运算,得到的结果相当于把整数的二进制表示中最右边的 1 变成 0。很多二进制的问题都可以用这种思路解决。
```java
/**
* @author bingo
* @since 2018/11/20
*/
public class Solution {
/**
* 计算整数的二进制表示里1的个数
* @param n 整数
* @return 1的个数
*/
public int NumberOf1(int n) {
int cnt = 0;
while (n != 0) {
n = (n - 1 ) & n;
++cnt;
}
return cnt;
}
}
```
### 测试用例
1. 正数(包括边界值 1、0x7FFFFFFF);
2. 负数(包括边界值 0x80000000、0xFFFFFFFF);
3. 0。
================================================
FILE: docs/jianzhioffer/java/16_Power.md
================================================
## 数值的整数次方
### 题目描述
给定一个 `double` 类型的浮点数 `base` 和 `int` 类型的整数 `exponent`。求 `base`的 `exponent` 次方。
### 解法
注意判断值数是否小于 0。另外 0 的 0 次方没有意义,也需要考虑一下,看具体题目要求。
```java
/**
* @author bingo
* @since 2018/11/20
*/
public class Solution {
/**
* 计算数值的整数次方
* @param base 底数
* @param exponent 指数
* @return 数值的整数次方
*/
public double Power(double base, int exponent) {
double result = 1.0;
int n = Math.abs(exponent);
for (int i = 0; i < n; ++i) {
result *= base;
}
return exponent < 0 ? 1.0 / result : result;
}
}
```
### 测试用例
1. 把底数和指数分别设为正数、负数和零。
================================================
FILE: docs/jianzhioffer/java/17_Print1ToMaxOfNDigits.md
================================================
## 打印从 1 到最大的 n 位数
### 题目描述
输入数字 `n`,按顺序打印出从 `1` 最大的 `n` 位十进制数。比如输入 `3`,则打印出 `1、2、3` 一直到最大的 3 位数即 999。
### 解法
此题需要注意 n 位数构成的数字可能超出最大的 int 或者 long long 能表示的范围。因此,采用字符数组来存储数字。
关键是:
- 对字符数组表示的数进行递增操作
- 输出数字(0开头的需要把0去除)
```java
/**
* @author bingo
* @since 2018/11/20
*/
public class Solution {
/**
* 打印从1到最大的n位数
* @param n n位
*/
public void print1ToMaxOfNDigits(int n) {
if (n < 1) {
return;
}
char[] chars = new char[n];
for (int i = 0; i < n; ++i) {
chars[i] = '0';
}
while (!increment(chars)) {
printNumber(chars);
}
}
/**
* 打印数字(去除前面的0)
* @param chars 数字数组
*/
private void printNumber(char[] chars) {
int index = 0;
int n = chars.length;
for (char ch : chars) {
if (ch != '0') {
break;
}
++index;
}
StringBuilder sb = new StringBuilder();
for (int i = index; i < n; ++i) {
sb.append(chars[i]);
}
System.out.println(sb.toString());
}
/**
* 数字加1
* @param chars 数字数组
* @return 是否溢出
*/
private boolean increment(char[] chars) {
boolean flag = false;
int n = chars.length;
int carry = 1;
for (int i = n - 1; i >= 0; --i) {
int num = chars[i] - '0' + carry;
if (num > 9) {
if (i == 0) {
flag = true;
break;
}
chars[i] = '0';
} else {
++chars[i];
break;
}
}
return flag;
}
}
```
### 测试用例
1. 功能测试(输入 1、2、3......);
2. 特殊输入测试(输入 -1、0)。
================================================
FILE: docs/jianzhioffer/java/18_01_DeleteNodeInList.md
================================================
## 在O(1)时间内删除链表节点
### 题目描述
给定单向链表的头指针和一个节点指针,定义一个函数在 O(1) 时间内删除该节点。
### 解法
判断要删除的节点是否是尾节点,若是,直接删除;若不是,把要删除节点的下一个节点赋给要删除的节点即可。
### ```进行n次操作,平均时间复杂度为:( (n-1) * O(1) + O(n) ) / n = O(1),所以符合题目上说的O(1)```
```java
/**
* @author bingo
* @since 2018/11/20
*/
public class Solution {
class ListNode {
int val;
ListNode next;
}
/**
* 删除链表的节点
* @param head 链表头节点
* @param tobeDelete 要删除的节点
*/
public ListNode deleteNode(ListNode head, ListNode tobeDelete) {
if (head == null || tobeDelete == null) {
return head;
}
// 删除的不是尾节点
if (tobeDelete.next != null) {
tobeDelete.val = tobeDelete.next.val;
tobeDelete.next = tobeDelete.next.next;
}
// 链表中仅有一个节点
else if (head == tobeDelete) {
head = null;
}
// 删除的是尾节点
else {
ListNode ptr = head;
while (ptr.next != tobeDelete) {
ptr = ptr.next;
}
ptr.next = null;
}
return head;
}
}
```
### 测试用例
1. 功能测试(从有多个节点的链表的中间/头部/尾部删除一个节点;从只有一个节点的链表中删除唯一的节点);
2. 特殊输入测试(指向链表头节点的为空指针;指向要删除节点的为空指针)。
================================================
FILE: docs/jianzhioffer/java/18_02_DeleteDuplicatedNode.md
================================================
## 删除链表中重复的节点
### 题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表`1->2->3->3->4->4->5` 处理后为 `1->2->5`。
### 解法
#### 解法一:递归
```java
/**
* @author bingo
* @since 2018/11/21
*/
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
/**
* 删除链表重复的节点
* @param pHead 链表头节点
* @return 删除节点后的链表
*/
public ListNode deleteDuplication(ListNode pHead) {
if (pHead == null || pHead.next == null) {
return pHead;
}
if (pHead.val == pHead.next.val) {
if (pHead.next.next == null) {
return null;
}
if (pHead.next.next.val == pHead.val) {
return deleteDuplication(pHead.next);
}
return deleteDuplication(pHead.next.next);
}
pHead.next = deleteDuplication(pHead.next);
return pHead;
}
}
```
#### 解法二
```java
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode deleteDuplication(ListNode pHead) {
if (pHead == null || pHead.next == null) {
return pHead;
}
ListNode pre = null;
ListNode cur = pHead;
while (cur != null) {
if (cur.next != null && cur.next.val == cur.val) {
int val = cur.val;
while (cur.next != null && cur.next.val == val) {
cur = cur.next;
}
if (pre == null) {
pHead = cur.next;
} else {
pre.next = cur.next;
}
} else {
pre = cur;
}
cur = cur.next;
}
return pHead;
}
}
```
### 测试用例
1. 功能测试(重复的节点位于链表的头部/中间/尾部;链表中没有重复的节点);
2. 特殊输入测试(指向链表头节点的为空指针;链表中所有节点都是重复的)。
================================================
FILE: docs/jianzhioffer/java/19_RegularExpressionsMatching.md
================================================
## 正则表达式匹配
### 题目描述
请实现一个函数用来匹配包括`.`和`*`的正则表达式。模式中的字符`.`表示任意一个字符,而`*`表示它前面的字符可以出现任意次(包含`0`次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串`aaa`与模式`a.a`和`ab*ac*a`匹配,但是与`aa.a`和`ab*a`均不匹配。
### 解法
判断模式中第二个字符是否是 `*`:
- 若是,看如果模式串第一个字符与字符串第一个字符是否匹配:
- 1. 若不匹配,在模式串上向右移动两个字符`j+2`,相当于 a* 被忽略
- 2. 若匹配,字符串后移`i+1`。此时模式串可以移动两个字符`j+2`,也可以不移动`j`。
- 若不是,看当前字符与模式串的当前字符是否匹配,即 str[i] == pattern[j] || pattern[j] == '.':
- 1. 若匹配,则字符串与模式串都向右移动一位,`i+1`,`j+1`。
- 2. 若不匹配,返回 fasle。
```java
/**
* @author bingo
* @since 2018/11/21
*/
public class Solution {
/**
* 判断字符串是否与模式串匹配
* @param str 字符串
* @param pattern 模式串
* @return 是否匹配
*/
public boolean match(char[] str, char[] pattern) {
if (str == null || pattern == null) {
return false;
}
return match(str, 0, str.length, pattern, 0, pattern.length);
}
private boolean match(char[] str, int i, int len1,
char[] pattern, int j, int len2) {
if (i == len1 && j == len2) {
return true;
}
// "",".*"
if (i != len1 && j == len2) {
return false;
}
if (j + 1 < len2 && pattern[j + 1] == '*') {
if (i < len1 && (str[i] == pattern[j] || pattern[j] == '.')) {
return match(str, i, len1, pattern, j + 2, len2)
|| match(str, i + 1, len1, pattern, j, len2)
|| match(str, i + 1, len1, pattern,j + 2, len2);
}
// "",".*"
return match(str, i, len1, pattern, j + 2, len2);
}
if (i < len1 && (str[i] == pattern[j] || pattern[j] == '.')) {
return match(str, i + 1, len1, pattern, j + 1, len2);
}
return false;
}
}
```
### 测试用例
1. 功能测试(模式字符串里包含普通字符、`.`、`*`;模式字符串和输入字符串匹配/不匹配);
2. 特殊输入测试(输入字符串和模式字符串是空指针、空字符串)。
================================================
FILE: docs/jianzhioffer/java/20_NumericStrings.md
================================================
## 表示数值的字符串
### 题目描述
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
### 解法
#### 解法一
利用正则表达式匹配即可。
```
[] : 字符集合
() : 分组
? : 重复 0 ~ 1
+ : 重复 1 ~ n
* : 重复 0 ~ n
. : 任意字符
\\. : 转义后的 .
\\d : 数字
```
```java
/**
* @author bingo
* @since 2018/11/21
*/
public class Solution {
/**
* 判断是否是数字
* @param str
* @return
*/
public boolean isNumeric(char[] str) {
return str != null
&& str.length != 0
&& new String(str).matches("[+-]?\\d*(\\.\\d+)?([eE][+-]?\\d+)?");
}
}
```
#### 解法二【剑指offer解法】
表示数值的字符串遵循模式`A[.[B]][e|EC]`或者`.B[e|EC]`,其中A为数值的整数部分,B紧跟小数点为数值的小数部分,C紧跟着e或者E为数值的指数部分。上述A和C都有可能以 `+` 或者 `-` 开头的0~9的数位串,B也是0~9的数位串,但前面不能有正负号。
```java
/**
* @author mcrwayfun
* @version v1.0
* @date Created in 2018/12/29
* @description
*/
public class Solution {
private int index = 0;
/**
* 判断是否是数值
* @param str
* @return
*/
public boolean isNumeric(char[] str) {
if (str == null || str.length < 1) {
return false;
}
// 判断是否存在整数
boolean flag = scanInteger(str);
// 小数部分
if (index < str.length && str[index] == '.') {
index++;
// 小数部分可以有整数或者没有整数
// 所以使用 ||
flag = scanUnsignedInteger(str) || flag;
}
if (index < str.length && (str[index] == 'e' || str[index] == 'E')) {
index++;
// e或E前面必须有数字
// e或者E后面必须有整数
// 所以使用 &&
flag = scanInteger(str) && flag;
}
return flag && index == str.length;
}
private boolean scanInteger(char[] str) {
// 去除符号
while (index < str.length && (str[index] == '+' || str[index] == '-')) {
index++;
}
return scanUnsignedInteger(str);
}
private boolean scanUnsignedInteger(char[] str) {
int start = index;
while (index < str.length && str[index] >= '0' && str[index] <= '9') {
index++;
}
// 判断是否存在整数
return index > start;
}
}
```
### 测试用例
1. 功能测试(正数或者负数;包含或者不包含整数部分的数值;包含或者不包含效数部分的值;包含或者不包含指数部分的值;各种不能表达有效数值的字符串);
2. 特殊输入测试(输入字符串和模式字符串是空指针、空字符串)。
================================================
FILE: docs/jianzhioffer/java/21_ReorderArray.md
================================================
## 调整数组顺序使奇数位于偶数前面
### 题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
### 解法
#### 解法一
计算出奇数的个数,就很容易写出来了。
```java
import java.util.Arrays;
/**
* @author bingo
* @since 2018/11/21
*/
public class Solution {
/**
* 调整数组元素顺序,使得奇数元素位于偶数元素前面,且保证奇数和奇数,偶数和偶数之间的相对位置不变。
* @param array 数组
*/
public void reOrderArray(int [] array) {
if (array == null || array.length < 2) {
return;
}
int numsOfOdd = 0;
for (int val : array) {
if (val % 2 == 1) {
++numsOfOdd;
}
}
int[] bak = Arrays.copyOf(array, array.length);
int i = 0, j = numsOfOdd;
for (int val : bak) {
if (val % 2 == 1) {
array[i++] = val;
} else {
array[j++] = val;
}
}
}
}
```
#### 解法二
```java
import java.util.Arrays;
public class Solution {
public void reOrderArray(int [] array) {
if (array == null || array.length < 2) {
return;
}
Integer[] bak = new Integer[array.length];
Arrays.setAll(bak, i -> array[i]);
Arrays.sort(bak, (x, y) -> (y & 1) - (x & 1));
Arrays.setAll(array, i -> bak[i]);
}
}
```
### 测试用例
1. 功能测试(输入数组中的奇数、偶数交替出现;输入的数组中所有偶数都出现在奇数的前面;输入的数组中所有偶数都出现在奇数的前面;输入的数组中所有奇数都出现在偶数的前面);
2. 特殊输入测试(输入空指针;输入的数组只包含一个数字)。
================================================
FILE: docs/jianzhioffer/java/22_KthNodeFromEnd.md
================================================
## 链表中倒数第k个结点
### 题目描述
输入一个链表,输出该链表中倒数第k个结点。
### 解法
pre 指针走 `k-1` 步。之后 cur 指针指向 phead,然后两个指针同时走,直至 pre 指针到达尾结点。
> 当用一个指针遍历链表不能解决问题的时候,可以尝试用两个指针来遍历链表。可以让其中一个指针遍历的速度快一些。
此题需要考虑一些特殊情况。比如 k 的值小于 0 或者大于链表长度。
```java
/**
* @author bingo
* @since 2018/11/21
*/
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
/**
* 找出链表倒数第k个节点,k从1开始
* @param head 链表头部
* @param k 第k个节点
* @return 倒数第k个节点
*/
public ListNode FindKthToTail(ListNode head,int k) {
if (head == null || k < 1) {
return null;
}
ListNode pre = head;
for (int i = 0; i < k - 1; ++i) {
if (pre.next != null) {
pre = pre.next;
} else {
return null;
}
}
ListNode cur = head;
while (pre.next != null) {
pre = pre.next;
cur = cur.next;
}
return cur;
}
}
```
### 测试用例
1. 功能测试(第 k 个节点在链表的中间/头部/尾部);
2. 特殊输入测试(输入空指针;链表的节点总数小于 k;k=0)。
================================================
FILE: docs/jianzhioffer/java/23_EntryNodeInListLoop.md
================================================
## 链表中环的入口结点
### 题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出`null`。
### 解法
- 先利用快慢指针。若能相遇,说明存在环,且相遇点一定是在环上;若没有相遇,说明不存在环,返回 `null`。
- 固定当前相遇点,用一个指针继续走,同时累积结点数。计算出环的结点个数 `cnt`。
- 指针 p1 先走 `cnt` 步,p2 指向链表头部,之后 `p1`,`p2` 同时走,相遇时,相遇点一定是在环的入口处。因为 `p1` 比 `p2` 多走了环的一圈。
```java
/**
* @author bingo
* @since 2018/11/22
*/
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
/**
* 求链表环的入口,若没有环,返回null
* @param pHead 链表头
* @return 环的入口点
*/
public ListNode EntryNodeOfLoop(ListNode pHead) {
if (pHead == null || pHead.next == null) {
return null;
}
ListNode fast = pHead;
ListNode slow = pHead;
boolean flag = false;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (fast == slow) {
flag = true;
break;
}
}
// 快指针与慢指针没有相遇,说明无环,返回 null
if (!flag) {
return null;
}
ListNode cur = slow.next;
// 求出环中结点个数
int cnt = 1;
while (cur != slow) {
cur = cur.next;
++cnt;
}
// 指针p1先走cnt步
ListNode p1 = pHead;
for (int i = 0; i < cnt; ++i) {
p1 = p1.next;
}
// p2指向链表头,然后p1/p2同时走,首次相遇的地方就是环的入口
ListNode p2 = pHead;
while (p1 != p2) {
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
}
```
### 测试用例
1. 功能测试(链表中包含/不包含环;链表中有多个或者只有一个节点);
2. 特殊输入测试(链表头节点为空指针)。
================================================
FILE: docs/jianzhioffer/java/24_ReverseList.md
================================================
## 反转链表
### 题目描述
输入一个链表,反转链表后,输出新链表的表头。
### 解法
#### 解法一
利用头插法解决。
```java
/**
* @author bingo
* @since 2018/11/22
*/
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
/**
* 反转链表
* @param head 链表头部
* @return 反转后的链表
*/
public ListNode ReverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode dummy = new ListNode(-1);
dummy.next = null;
ListNode p1 = head;
ListNode p2 = p1.next;
while (p1 != null) {
p1.next = dummy.next;
dummy.next = p1;
p1 = p2;
if (p1 == null) {
break;
}
p2 = p1.next;
}
return dummy.next;
}
}
```
#### 解法二:递归
```java
/**
* @author bingo
* @since 2018/11/22
*/
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode ReverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode next = ReverseList(head.next);
ListNode cur = next;
while (cur.next != null) {
cur = cur.next;
}
cur.next = head;
head.next = null;
return next;
}
}
```
### 测试用例
1. 功能测试(链表中有多个结点/只有一个节点);
2. 特殊输入测试(链表头节点为空指针)。
================================================
FILE: docs/jianzhioffer/java/25_MergeSortedLists.md
================================================
## 合并两个排序的链表
### 题目描述
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
### 解法
#### 解法一
同时遍历两链表进行 `merge`。
```java
/**
* @author bingo
* @since 2018/11/22
*/
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
/**
* 合并两个排序链表
* @param list1 链表1
* @param list2 链表2
* @return 合并后的单调不递减链表
*/
public ListNode Merge(ListNode list1, ListNode list2) {
if (list1 == null) {
return list2;
}
if (list2 == null) {
return list1;
}
ListNode dummy = new ListNode(-1);
ListNode cur = dummy;
ListNode p1 = list1;
ListNode p2 = list2;
while (p1 != null && p2 != null) {
if (p1.val < p2.val) {
ListNode t = p1.next;
cur.next = p1;
p1.next = null;
p1 = t;
} else {
ListNode t = p2.next;
cur.next = p2;
p2.next = null;
p2 = t;
}
cur = cur.next;
}
cur.next = p1 == null ? p2 : p1;
return dummy.next;
}
}
```
#### 解法二:递归
```java
/**
* @author bingo
* @since 2018/11/22
*/
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
/**
* 合并两个排序链表
* @param list1 链表1
* @param list2 链表2
* @return 合并后的单调不递减链表
*/
public ListNode Merge(ListNode list1, ListNode list2) {
if (list1 == null) {
return list2;
}
if (list2 == null) {
return list1;
}
if (list1.val < list2.val) {
list1.next = Merge(list1.next, list2);
return list1;
}
list2.next = Merge(list1, list2.next);
return list2;
}
}
```
### 测试用例
1. 功能测试(输入的两个链表有多个节点;节点的值互不相同或者存在值相等的多个节点);
2. 特殊输入测试(两个链表的一个或者两个头节点为空指针;两个链表中只有一个节点)。
================================================
FILE: docs/jianzhioffer/java/26_SubstructureInTree.md
================================================
## 树的子结构
### 题目描述
输入两棵二叉树`A`,`B`,判断`B`是不是`A`的子结构。(ps:我们约定空树不是任意一个树的子结构)
### 解法
递归方式遍历:
- 在树A中找到和树B的根结点值一样的结点R
- 判断树A以R为根结点的子树是否包含与树B一样的结构
这道题的time complexity应该为O(n * m),其中n为root1的节点数,m为root2的节点数。
```java
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
/**
* @author mcrwayfun
* @version v1.0
* @date Created in 2019/01/01
* @description
*/
public class Solution {
public boolean HasSubtree(TreeNode root1, TreeNode root2) {
if (root1 == null || root2 == null) {
return false;
}
return isSame(root1, root2) ||
HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
}
private boolean isSame(TreeNode root1, TreeNode root2) {
if (root2 == null) {
return true;
}
// 在root2,root1遍历完成后,仍未找到符合的结构,返回false
if (root1 == null) {
return false;
}
if (root1.val != root2.val) {
return false;
}
return isSame(root1.left, root2.left) && isSame(root1.right, root2.right);
}
}
```
### 测试用例
1. 功能测试(树A和树B都是普通的二叉树;树B是/不是树A的子结构);
2. 特殊输入测试(两棵二叉树的一个或者两个根结点为空指针,二叉树的所有结点都没有左/右子树)。
================================================
FILE: docs/jianzhioffer/java/27_MirrorOfBinaryTree.md
================================================
## 二叉树的镜像
### 题目描述
操作给定的二叉树,将其变换为源二叉树的镜像。
```
源二叉树
8
/ \
6 10
/ \ / \
5 7 9 11
镜像二叉树
8
/ \
10 6
/ \ / \
11 9 7 5
```
### 解法
将根结点的左右孩子互换,之后递归左右孩子。
```java
/**
* @author bingo
* @since 2018/11/22
*/
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
/**
* 将二叉树转换为它的镜像
* @param root 二叉树的根结点
*/
public void Mirror(TreeNode root) {
if (root == null || !hasChild(root)) {
return;
}
TreeNode t = root.left;
root.left = root.right;
root.right = t;
Mirror(root.left);
Mirror(root.right);
}
private boolean hasChild(TreeNode root) {
return root.left != null || root.right != null;
}
}
```
### 测试用例
1. 功能测试(普通的二叉树;二叉树的所有结点都没有左/右子树;只有一个结点的二叉树);
2. 特殊输入测试(二叉树的根结点为空指针)。
================================================
FILE: docs/jianzhioffer/java/28_SymmetricalBinaryTree.md
================================================
## 对称的二叉树
### 题目描述
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
### 解法
比较二叉树的前序遍历序列和对称前序遍历序列是否一样,若是,说明是对称的。
```java
/**
* @author bingo
* @since 2018/11/22
*/
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
/**
* 判断是否是对称二叉树
* @param pRoot 二叉树的根结点
* @return 是否为对称二叉树
*/
boolean isSymmetrical(TreeNode pRoot) {
return isSymmetrical(pRoot, pRoot);
}
private boolean isSymmetrical(TreeNode pRoot1, TreeNode pRoot2) {
if (pRoot1 == null && pRoot2 == null) {
return true;
}
if (pRoot1 == null || pRoot2 == null) {
return false;
}
if (pRoot1.val != pRoot2.val) {
return false;
}
return isSymmetrical(pRoot1.left, pRoot2.right) && isSymmetrical(pRoot1.right, pRoot2.left);
}
}
```
### 测试用例
1. 功能测试(对称的二叉树;因结构而不对称的二叉树;结构对称但节点的值不对称的二叉树);
2. 特殊输入测试(二叉树的根结点为空指针;只有一个节点的二叉树;所有节点的值都相同的二叉树)。
================================================
FILE: docs/jianzhioffer/java/29_PrintMatrix.md
================================================
## 顺时针打印矩阵
### 题目描述
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下 `4 X 4` 矩阵:
```
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
```
则依次打印出数字:
```
1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
```
### 解法
剑指offer上的思路有点复杂,需要考虑坐标变换太多,考虑用另一种思路来解决。
在矩阵中,使用左上角坐标(tR,tC)和右下角的坐标(dR,dC)就可以表示一个矩阵。比如题目中的矩阵,当(tR,tC) = (0,0)和(dR,dC) = (3,3)时,表示的子矩阵就是整个矩阵:
```java
1 2 3 4
5 8
9 12
13 14 15 16
```
当外层循环遍历后,可以令tR和tC加1,dR和dC减1,执行内层循环。当左上角的坐标跑到右下角坐标的右方或者下方,则整个过程就终止。
```java
/**
* @author mcrwayfun
* @version 1.0
* @description
* @date Created in 2019/1/2
*/
public class Solution {
/**
* 转圈打印矩阵
* @param matrix 矩阵
* @return 存放结果的list
*/
public ArrayList printMatrix(int[][] matrix) {
ArrayList reList = new ArrayList<>();
if (matrix == null) {
return reList;
}
int tR = 0;
int tC = 0;
int dR = matrix.length - 1;
int dC = matrix[0].length - 1;
while (tR <= dR && tC <= dC) {
printMatrix(matrix, tR++, tC++, dR--, dC--, reList);
}
return reList;
}
public void printMatrix(int[][] matrix, int tR, int tC, int dR, int dC, ArrayList reList) {
// 只有一行
if (tR == dR) {
for (int i = tC; i <= dC; i++) {
reList.add(matrix[tR][i]);
}
}
// 只有一列
else if (tC == dC) {
for (int i = tR; i <= dR; i++) {
reList.add(matrix[i][tC]);
}
} else {
int curR = tR;
int curC = tC;
// 从左到右
while (curC != dC) {
reList.add(matrix[tR][curC]);
curC++;
}
// 从上到下
while (curR != dR) {
reList.add(matrix[curR][dC]);
curR++;
}
// 从右到左
while (curC != tC) {
reList.add(matrix[dR][curC]);
curC--;
}
// 从下到上
while (curR != tR) {
reList.add(matrix[curR][tC]);
curR--;
}
}
}
}
```
### 测试用例
1. 数组中有多行多列;数组中只有一行;数组中只有一列;数组中只有一行一列。
================================================
FILE: docs/jianzhioffer/java/30_MinInStack.md
================================================
## 包含min函数的栈
### 题目描述
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为`O(1)`)。
### 解法
定义两个`stack`。
压栈时,先将元素`node`压入`stack1`。然后判断`stack2`的情况:
- `stack2`栈为空或者栈顶元素大于`node`,则将`node`压入`stack2`中。
- `stack2`栈不为空且栈定元素小于`node`,则重复压入栈顶元素。
获取最小元素时,从`stack2`中获取栈顶元素即可。
```java
import java.util.Stack;
/**
* @author bingo
* @since 2018/11/22
*/
public class Solution {
private Stack stack1 = new Stack<>();
private Stack stack2 = new Stack<>();
/**
* 压栈
* @param node 待压入的元素
*/
public void push(int node) {
stack1.push(node);
if (stack2.isEmpty() || stack2.peek() >= node) {
stack2.push(node);
} else {
stack2.push(stack2.peek());
}
}
public void pop() {
stack1.pop();
stack2.pop();
}
public int top() {
return stack2.peek();
}
/**
* O(1)获取栈中最小值
* @return 最小值
*/
public int min() {
return stack2.peek();
}
}
```
### 测试用例
1. 新压入栈的数字比之前的最小值大/小。
2. 弹出栈的数字是/不是最小元素。
================================================
FILE: docs/jianzhioffer/java/31_StackPushPopOrder.md
================================================
## 栈的压入、弹出序列
### 题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列`1,2,3,4,5`是某栈的压入顺序,序列`4,5,3,2,1`是该压栈序列对应的一个弹出序列,但`4,3,5,1,2`就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
### 解法
判断下一个要弹出的元素:
- 如果刚好是栈顶元素,直接弹出。
- 如果不在栈顶,则把压栈序列中还没有入栈的数字压入栈,直到待弹出的数字压入栈顶。
- 如果所有数字都压入栈顶后依然没有后找到下一个弹出的数字,则不可能是弹出序列。
```java
import java.util.Stack;
/**
* @author bingo
* @since 2018/11/22
*/
public class Solution {
/**
* 判断是否是弹出序列
* @param pushA 压栈序列
* @param popA 弹栈序列
* @return 是否是弹出序列
*/
public boolean IsPopOrder(int[] pushA,int[] popA) {
if (pushA == null || popA == null || pushA.length != popA.length) {
return false;
}
Stack stack = new Stack<>();
int i = 0;
int n = pushA.length;
boolean flag = false;
for (int val : popA) {
while (stack.isEmpty() || stack.peek() != val) {
if (i >= n) {
flag = true;
break;
}
stack.push(pushA[i++]);
}
if (flag) {
break;
}
stack.pop();
}
return stack.isEmpty();
}
}
```
### 测试用例
1. 功能测试(输入的两个数组含有多个数字或者只有一个数字:第二个数组是/不是第一个数组表示的压入序列对应的栈的弹出序列);
2. 特殊输入测试(输入两个空指针)。
================================================
FILE: docs/jianzhioffer/java/32_01_PrintTreeFromTopToBottom.md
================================================
## 不分行从上到下打印二叉树
### 题目描述
从上往下打印出二叉树的每个节点,同层节点从左至右打印。
### 解法
先将根节点进入队列。
队头元素出队,将值存入 list,判断该元素是否有左/右子树,有的话依次进入队列中。队列为空时结束。
```java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
/**
* @author bingo
* @since 2018/11/23
*/
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
/**
* 从上到下打印二叉树
* @param root 二叉树根节点
* @return 结果list
*/
public ArrayList PrintFromTopToBottom(TreeNode root) {
ArrayList list = new ArrayList<>();
if (root == null) {
return list;
}
Queue queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
list.add(node.val);
}
return list;
}
}
```
### 测试用例
1. 功能测试(完全二叉树;所有节点只有左/右子树);
2. 特殊输入测试(二叉树根节点为空指针;只有一个节点的二叉树)。
================================================
FILE: docs/jianzhioffer/java/32_02_PrintTreesInLines.md
================================================
## 把二叉树打印成多行
### 题目描述
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
### 解法
与上一题类似,只不过需要用变量记录每一层要打印多少个节点。
```java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
/**
* @author bingo
* @since 2018/11/23
*/
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
/**
* 把二叉树打印成多行
* @param pRoot 二叉树根节点
* @return 结果list
*/
ArrayList > Print(TreeNode pRoot) {
ArrayList> list = new ArrayList<>();
if (pRoot == null) {
return list;
}
Queue queue = new LinkedList<>();
queue.offer(pRoot);
int cnt = 1;
while (cnt > 0) {
int num = cnt;
cnt = 0;
ArrayList res = new ArrayList<>();
for (int i = 0; i < num; ++i) {
TreeNode node = queue.poll();
if (node.left != null) {
queue.offer(node.left);
++cnt;
}
if (node.right != null) {
queue.offer(node.right);
++cnt;
}
res.add(node.val);
}
list.add(res);
}
return list;
}
}
```
### 测试用例
1. 功能测试(完全二叉树;所有节点只有左/右子树);
2. 特殊输入测试(二叉树根节点为空指针;只有一个节点的二叉树)。
================================================
FILE: docs/jianzhioffer/java/32_03_PrintTreesInZigzag.md
================================================
## 按之字形打印二叉树
### 题目描述
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
如二叉树:
```
1
/ \
2 3
/ \ / \
4 5 6 7
```
打印结果为:
```
1
3 2
4 5 6 7
```
### 解法
对于上述二叉树:
首先访问根结点,之后把2、3存入某结构。打印的时候,先打印3、2。这不就是栈?
依次弹出栈元素,分别是3、2。弹出时需要把3、2的子结点存入结构。由于访问时顺序是`4 5 6 7`。所以也需要用栈来存放。而且,此时需要先存放右孩子,再存放左孩子。(奇数层/偶数层存放左右孩子的顺序不同)
这里需要用两个栈来实现。如果只用一个栈,那么当弹出3、2 时,先将 3 的孩子节点压入栈。之后弹栈的时候不是先弹出 2,而是弹出了 3 的 孩子节点,就错了。
```java
import java.util.ArrayList;
import java.util.Stack;
/**
* @author bingo
* @since 2018/11/23
*/
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
/**
* 按之字形打印二叉树
* @param pRoot 二叉树的根节点
* @return 结果list
*/
public ArrayList> Print(TreeNode pRoot) {
ArrayList> res = new ArrayList<>();
if (pRoot == null) {
return res;
}
Stack stack1 = new Stack<>();
Stack stack2 = new Stack<>();
stack1.push(pRoot);
int i = 1;
Stack stack = stack1;
while (!stack.isEmpty()) {
ArrayList list = new ArrayList<>();
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
list.add(node.val);
if (i % 2 == 1) {
if (node.left != null) {
stack2.push(node.left);
}
if (node.right != null) {
stack2.push(node.right);
}
} else {
if (node.right != null) {
stack1.push(node.right);
}
if (node.left != null) {
stack1.push(node.left);
}
}
}
res.add(list);
++i;
stack = stack1.isEmpty() ? stack2 : stack1;
}
return res;
}
}
```
### 测试用例
1. 功能测试(完全二叉树;所有节点只有左/右子树);
2. 特殊输入测试(二叉树根节点为空指针;只有一个节点的二叉树)。
================================================
FILE: docs/jianzhioffer/java/33_SquenceOfBST.md
================================================
## 二叉搜索树的后序遍历序列
### 题目描述
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出`Yes`,否则输出`No`。假设输入的数组的任意两个数字都互不相同。
### 解法
序列的最后一个元素是二叉搜索树的根节点。
在序列中从左到右找到根节点的左子树(比根节点小)、右子树(比根节点大)。
- 如果右子树中出现比根节点小的元素,那么为 false。
- 否则递归左右子树。
```java
/**
* @author bingo
* @since 2018/11/23
*/
public class Solution {
/**
* 判断数组是否是某个二叉搜索树的后序遍历序列
*
* @param sequence 数组
* @return 是否属于某二叉搜索树的后序遍历序列
*/
public boolean VerifySquenceOfBST(int[] sequence) {
if (sequence == null || sequence.length < 1) {
return false;
}
return verify(sequence, 0, sequence.length - 1);
}
private boolean verify(int[] sequence, int start, int end) {
if (start >= end) {
return true;
}
int val = sequence[end];
int i = start;
for (; i <= end; ++i) {
if (sequence[i] >= val) {
break;
}
}
for (int j = i; j < end; ++j) {
if (sequence[j] < val) {
return false;
}
}
return verify(sequence, start, i - 1) && verify(sequence, i, end - 1);
}
}
```
### 测试用例
1. 功能测试(输入的后序遍历序列对应一棵二叉树,包括完全二叉树、所有节点都没有左/右子树的二叉树、只有一个节点的二叉树;输入的后续遍历序列没有对应一棵二叉树);
2. 特殊输入测试(后序遍历序列为空指针)。
================================================
FILE: docs/jianzhioffer/java/34_PathInTree.md
================================================
## 二叉树中和为某一值的路径
### 题目描述
输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的`list`中,数组长度大的数组靠前)
### 解法
```java
import java.util.ArrayList;
/**
* @author bingo
* @since 2018/11/23
*/
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
private ArrayList> res = new ArrayList<>();
/**
* 找出二叉树中和为某一值的路径(必须从根节点到叶节点)
*
* @param root 二叉树的根结点
* @param target 目标值
* @return 结果list
*/
public ArrayList> FindPath(TreeNode root, int target) {
findPath(root, target, new ArrayList<>());
return res;
}
private void findPath(TreeNode root, int target, ArrayList list) {
if (root == null) {
return;
}
list.add(root.val);
target -= root.val;
if (target == 0 && root.left == null && root.right == null) {
res.add(new ArrayList<>(list));
} else {
findPath(root.left, target, list);
findPath(root.right, target, list);
}
list.remove(list.size() - 1);
}
}
```
### 测试用例
1. 功能测试(二叉树中有一条、多条符合要求的路径;二叉树中没有符合要求的路径);
2. 特殊输入测试(指向二叉树根节点的指针为空指针)。
================================================
FILE: docs/jianzhioffer/java/35_CopyComplexList.md
================================================
## 复杂链表的复制
### 题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的 `head`。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
### 解法
可以分为3步:
1. 复制每个节点,并插入到被复制节点的后面。比如1->2->3 clone 1->1->2->2->3->3
2. 复制随机节点。当遍历到的当前节点存在随机节点时,则其复制节点也应该存在随机节点。比如当前节点`cur.random != null`,则`RandomListNode clone = cur.next;clone.random = cur.random.next;`
3. 分离两个链表。其中奇数链表为原链表,偶数链表为复制的链表
这道题的time complexity为O(n)。
```java
/**
* @author bingo
* @since 2018/11/24
*/
/*
public class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
}
*/
public class Solution {
/**
* 复杂链表的复制
* @param pHead 链表头结点
* @return 复制的链表
*/
public RandomListNode Clone(RandomListNode pHead) {
if (pHead == null) {
return null;
}
RandomListNode cur = pHead;
while (cur != null) {
RandomListNode node = new RandomListNode(cur.label);
node.next = cur.next;
cur.next = node;
cur = node.next;
}
cur = pHead;
while (cur != null) {
RandomListNode clone = cur.next;
if (cur.random != null) {
clone.random = cur.random.next;
}
cur = clone.next;
}
cur = pHead;
RandomListNode cloneHead = pHead.next;
while (cur.next != null) {
RandomListNode clone = cur.next;
cur.next = clone.next;
cur = clone;
}
return cloneHead;
}
}
```
### 测试用例
1. 功能测试(结点中的 random 指针指向结点自身;两个结点的 random 形成环状结构;链表中只有一个结点);
2. 特殊输入测试(指向链表头结点的指针为空指针)。
================================================
FILE: docs/jianzhioffer/java/36_ConvertBinarySearchTree.md
================================================
## 二叉搜索树与双向链表
### 题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
### 解法
由于是二叉搜索树,因此中序遍历的结果就是排序的。
中序遍历利用栈来实现。遍历时,前一个结点的 right 指向后一个结点,后一个结点的 left 指向前一个结点。
```java
pre.right = cur
cur.left = pre
```
```java
import java.util.Stack;
/**
* @author bingo
* @since 2018/11/24
*/
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
/**
* 将二叉搜索树转换为双向链表
*
* @param pRootOfTree
* @return
*/
public TreeNode Convert(TreeNode pRootOfTree) {
if (pRootOfTree == null) {
return null;
}
Stack stack = new Stack<>();
TreeNode cur = pRootOfTree;
TreeNode res = null;
TreeNode pre = null;
while (cur != null || !stack.isEmpty()) {
if (cur != null) {
stack.push(cur);
cur = cur.left;
} else {
cur = stack.pop();
if (pre == null) {
pre = cur;
res = pre;
} else {
pre.right = cur;
cur.left = pre;
pre = cur;
}
cur = cur.right;
}
}
return res;
}
}
```
### 测试用例
1. 功能测试(输入的二叉树是完全二叉树;所有结点都没有左/右子树;只有一个结点的二叉树);
2. 特殊输入测试(指向二叉树根结点的指针为空指针)。
================================================
FILE: docs/jianzhioffer/java/37_SerializeBinaryTrees.md
================================================
## 序列化二叉树
### 题目描述
请实现两个函数,分别用来序列化和反序列化二叉树。使用前序遍历实现,空节点使用字符`#` 表示。
比如有如下二叉树:
```java
1
2 3
4 # 5 6
# # # # # #
```
序列化的结果为 `1,2,4,#,#,#,3,5,#,#,6,#,#`
反序列化的结果为上述二叉树
### 解法
使用前序遍历进行序列化和反序列化。对格式没有要求,只要序列化得到的结果,再反序列化后能与原树相同即可。
```java
/**
* @author mcrwayfun
* @version 1.0
* @description
* @date Created in 2019/1/12
*/
public class Solution {
public String Serialize(TreeNode root) {
StringBuilder res = new StringBuilder();
if (root == null) {
return res.toString();
}
serializeHelper(root, res);
// 移除最后一个的符号","
res.deleteCharAt(res.lastIndexOf(","));
return res.toString();
}
private void serializeHelper(TreeNode root, StringBuilder res) {
if (root == null) {
res.append("#");
res.append(",");
return;
}
res.append(root.val);
res.append(",");
serializeHelper(root.left, res);
serializeHelper(root.right, res);
}
private int index = -1;
public TreeNode Deserialize(String str) {
if (str == null || str.length() == 0) {
return null;
}
String[] treeNodeStr = str.split(",");
return deserializeHelper(treeNodeStr);
}
private TreeNode deserializeHelper(String[] treeNodeStr) {
index++;
TreeNode node = null;
// index不越界并且当前节点不为#
if (index < treeNodeStr.length && !"#".equals(treeNodeStr[index])) {
node = new TreeNode(Integer.valueOf(treeNodeStr[index]));
node.left = deserializeHelper(treeNodeStr);
node.right = deserializeHelper(treeNodeStr);
}
return node;
}
}
```
### 测试用例
1. 功能测试(输入的二叉树是完全二叉树;所有节点都没有左/右子树的二叉树;只有一个节点的二叉树;所有节点的值都相同的二叉树);
2. 特殊输入测试(指向二叉树根结点的指针为空指针)。
================================================
FILE: docs/jianzhioffer/java/38_StringPermutation.md
================================================
## 字符串的排列
### 题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。(输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母)。ps:牛客上的测试用例对返回的list要排序。
### 解法
对整个字符串的排列可以看成两部分。第一步求所有可能出现在第一个位置的字符,即把第一个字符与后面所有非重复的字符进行交换。第二步固定第一个字符,求后面所有字符的排列;第二步中后面的所有字符又可以看成一个完整的字符,继续执行这两个步骤。
注意存在重复值得情况,比如输入字符串bab,将首字符b作为固定字符串,对于将第2个下标的b换到首位仍然是bab,所有这种情况无需输出。
**这道题的时间复杂度应该为O(n!)**
```java
/**
* @author mcrwayfun
* @version 1.0
* @description
* @date Created in 2019/1/14
*/
public class Solution {
public ArrayList Permutation(String str) {
ArrayList reList = new ArrayList<>();
if (str == null || str.length() == 0) {
return reList;
}
char[] chars = str.toCharArray();
// 递归输出字符串排列
permutationHelper(chars, 0, reList);
Collections.sort(reList);
return reList;
}
private void permutationHelper(char[] chars, int index, ArrayList list) {
if (index == chars.length - 1) {
list.add(new String(chars));
return;
}
Set set = new HashSet<>();
// 确定交换的字符,包括自己[index,length-1]
for (int i = index; i < chars.length; i++) {
// 排除出现重复字符
// hash表,查询花费O(1)
if (!set.contains(chars[i])) {
set.add(chars[i]);
// 固定字符index
swap(chars, i, index);
// 递归固定剩余字符[index+1,length-1]
permutationHelper(chars, index + 1, list);
// 恢复原数组
swap(chars, index, i);
}
}
}
private void swap(char[] chars, int x, int y) {
char temp = chars[x];
chars[x] = chars[y];
chars[y] = temp;
}
}
```
### 测试用例
1. 功能测试(输入的字符串有一个或多个字符);
2. 特殊输入测试(输入的字符串为nullptr指针或者内容为空)。
================================================
FILE: docs/jianzhioffer/java/39_MoreThanHalfNumber.md
================================================
## 数组中出现次数超过一半的数字
### 题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为 9 的数组 `{1,2,3,2,2,2,5,4,2}`。由于数字 2 在数组中出现了 5 次,超过数组长度的一半,因此输出 2。如果不存在则输出 0。
### 解法
#### 解法一
利用快排中的 partition 思想。
数组中有一个数字出现次数超过了数组长度的一半,那么排序后,数组中间的数字一定就是我们要找的数字。我们随机选一个数字,利用 partition() 函数,使得比选中数字小的数字都排在它左边,比选中数字大的数字都排在它的右边。
判断选中数字的下标 `index`:
- 如果 `index = n/2`,那么这个数字就是中位数。
- 如果 `index > n/2`,那么接着在 index 的左边进行 partition。
- 如果 `index < n/2`,则在 index 的右边继续进行 partition。
**注意:**这种方法会修改输入的数组。时间复杂度为 `O(n)`。
```java
/**
* @author bingo
* @since 2018/12/6
*/
public class Solution {
/**
* 查找数组中出现次数超过一次的数字
*
* @param array 数组
* @return 返回该数,不存在则返回0
*/
public int MoreThanHalfNum_Solution(int[] array) {
if (array == null || array.length == 0) {
return 0;
}
int n = array.length;
int start = 0, end = n - 1;
int mid = n >> 1;
int index = partition(array, start, end);
while (index != mid) {
if (index > mid) {
end = index - 1;
} else {
start = index + 1;
}
index = partition(array, start, end);
}
return isMoreThanHalf(array, array[index]) ? array[index] : 0;
}
/**
* 快排中的 partition 方法
*
* @param array 数组
* @param start 开始位置
* @param end 结束位置
* @return
*/
private int partition(int[] array, int start, int end) {
int small = start - 1;
for (int i = start; i < end; ++i) {
if (array[i] < array[end]) {
swap(array, i, ++small);
}
}
++small;
swap(array, small, end);
return small;
}
private void swap(int[] array, int i, int j) {
int t = array[i];
array[i] = array[j];
array[j] = t;
}
/**
* 判断val元素是否真的超过数组元素个数的一半
*
* @param array 数组
* @param val 某元素
* @return boolean
*/
private boolean isMoreThanHalf(int[] array, int val) {
int cnt = 0;
for (int e : array) {
if (e == val) {
++cnt;
}
}
return cnt * 2 > array.length;
}
}
```
#### 解法二
利用多数投票算法,从头到尾遍历数组,遇到两个不一样的数就把这两个数同时除去。除去的两个数可能都不是 majority,也可能一个是 majority 另一个不是,但是因为 majority 总数大于一半,所以这么删完最后剩下的肯定是 majority。
此方法时间复杂度为 `O(n)`,且不会改变数组。
```java
/**
* @author bingo
* @since 2018/12/6
*/
public class Solution {
/**
* 查找数组中出现次数超过一次的数字
*
* @param array 数组
* @return 返回该数,不存在则返回0
*/
public int MoreThanHalfNum_Solution(int[] array) {
if (array == null || array.length == 0) {
return 0;
}
int res = array[0];
int times = 1;
for (int i = 1; i < array.length; ++i) {
if (times == 0) {
res = array[i];
times = 1;
} else if (array[i] == res) {
++times;
} else {
--times;
}
}
return isMoreThanHalf(array, res) ? res : 0;
}
/**
* 判断val元素是否真的超过数组元素个数的一半
*
* @param array 数组
* @param val 某元素
* @return boolean
*/
private boolean isMoreThanHalf(int[] array, int val) {
int cnt = 0;
for (int e : array) {
if (e == val) {
++cnt;
}
}
return cnt * 2 > array.length;
}
}
```
### 测试用例
1. 功能测试(输入的数组中存在/不存在一个出现次数超过数组长度一半的数字);
2. 特殊输入测试(输入的数组只有一个数字;输入空指针)。
================================================
FILE: docs/jianzhioffer/java/40_KLeastNumbers.md
================================================
## 获取数组中最小的k个数
### 题目描述
输入 n 个整数,找出其中最小的 K 个数。例如输入 `4,5,1,6,2,7,3,8` 这 8 个数字,则最小的 4 个数字是 `1,2,3,4`。
### 解法
#### 解法一
利用快排中的 partition 思想。
数组中有一个数字出现次数超过了数组长度的一半,那么排序后,数组中间的数字一定就是我们要找的数字。我们随机选一个数字,利用 partition() 函数,使得比选中数字小的数字都排在它左边,比选中数字大的数字都排在它的右边。
判断选中数字的下标 `index`:
- 如果 `index = k-1`,结束循环,返回前 k 个数。
- 如果 `index > k-1`,那么接着在 index 的左边进行 partition。
- 如果 `index < k-1`,则在 index 的右边继续进行 partition。
**注意**,这种方法会修改输入的数组。时间复杂度为 `O(n)`。
```java
import java.util.ArrayList;
/**
* @author bingo
* @since 2018/12/6
*/
public class Solution {
/**
* 获取数组中最小的k个数
*
* @param input 输入的数组
* @param k 元素个数
* @return 最小的k的数列表
*/
public ArrayList GetLeastNumbers_Solution(int[] input, int k) {
ArrayList res = new ArrayList<>();
if (input == null || input.length == 0 || input.length < k || k < 1) {
return res;
}
int n = input.length;
int start = 0, end = n - 1;
int index = partition(input, start, end);
while (index != k - 1) {
if (index > k - 1) {
end = index - 1;
} else {
start = index + 1;
}
index = partition(input, start, end);
}
for (int i = 0; i < k; ++i) {
res.add(input[i]);
}
return res;
}
private int partition(int[] input, int start, int end) {
int index = start - 1;
for (int i = start; i < end; ++i) {
if (input[i] < input[end]) {
swap(input, i, ++index);
}
}
++index;
swap(input, index, end);
return index;
}
private void swap(int[] array, int i, int j) {
int t = array[i];
array[i] = array[j];
array[j] = t;
}
}
```
#### 解法二
利用大根堆,存储最小的 k 个数,最后返回即可。
此方法时间复杂度为 `O(nlogk)`。虽然慢一点,但是它不会改变输入的数组,并且它**适合海量数据的输入**。
假设题目要求从海量的数据中找出最小的 k 个数,由于内存的大小是有限的,有可能不能把这些海量的数据一次性全部载入内存。这个时候,用这种方法是最合适的。就是说它适合 n 很大并且 k 较小的问题。
```java
import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue;
/**
* @author bingo
* @since 2018/12/6
*/
public class Solution {
/**
* 获取数组中最小的k个数
*
* @param input 输入的数组
* @param k 元素个数
* @return 最小的k的数列表
*/
public ArrayList GetLeastNumbers_Solution(int[] input, int k) {
ArrayList res = new ArrayList<>();
if (input == null || input.length == 0 || input.length < k || k < 1) {
return res;
}
PriorityQueue maxHeap = new PriorityQueue<>(k, Comparator.reverseOrder());
System.out.println(maxHeap.size());
for (int e : input) {
if (maxHeap.size() < k) {
maxHeap.add(e);
} else {
if (maxHeap.peek() > e) {
maxHeap.poll();
maxHeap.add(e);
}
}
}
res.addAll(maxHeap);
return res;
}
}
```
### 测试用例
1. 功能测试(输入的数组中存在/不存在一个出现次数超过数组长度一半的数字);
2. 特殊输入测试(输入的数组只有一个数字;输入空指针)。
================================================
FILE: docs/jianzhioffer/java/41_StreamMedian.md
================================================
## 数据流中的中位数
### 题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用`Insert()`方法读取数据流,使用`GetMedian()`方法获取当前读取数据的中位数。
### 解法
利用大根堆存放较小的一半元素,小根堆存放较大的一半元素。维持大小堆的元素个数差不超过 1。
```java
import java.util.Comparator;
import java.util.PriorityQueue;
/**
* @author bingo
* @since 2018/12/7
*/
public class Solution {
private PriorityQueue minHeap = new PriorityQueue<>();
private PriorityQueue maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
/**
* 插入一个数
*
* @param num 数
*/
public void Insert(Integer num) {
if (maxHeap.isEmpty() || num < maxHeap.peek()) {
maxHeap.offer(num);
if (maxHeap.size() - minHeap.size() > 1) {
minHeap.offer(maxHeap.poll());
}
} else {
minHeap.offer(num);
if (minHeap.size() - maxHeap.size() > 1) {
maxHeap.offer(minHeap.poll());
}
}
}
/**
* 获取中位数
*
* @return 中位数
*/
public Double GetMedian() {
int size1 = maxHeap.size();
int size2 = minHeap.size();
if (size1 > size2) {
return (double) maxHeap.peek();
}
if (size1 < size2) {
return (double) minHeap.peek();
}
return (maxHeap.peek() + minHeap.peek()) / 2.0;
}
}
```
### 测试用例
1. 功能测试(从数据流中读出奇数/偶数个数字);
2. 边界值测试(从数据流中读出 0/1/2 个数字)。
================================================
FILE: docs/jianzhioffer/java/42_GreatestSumOfSubarrays.md
================================================
## 连续子数组的最大和
### 题目描述
输入一个**非空**整型数组,数组里的数可能为正,也可能为负。
数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。
要求时间复杂度为`O(n)`。
### 解法
动态规划法。
res[i] 表示以第 i 个数字结尾的子数组的最大和,那么求出 `max(res[i])` 即可。
- `res[i] = array[i]`, if `res[i - 1] < 0`
- `res[i] = res[i - 1] + array[i]`, if `res[i - 1] >= 0`
```java
/**
* @author bingo
* @since 2018/12/7
*/
public class Solution {
/**
* 求连续子数组的最大和
*
* @param array 数组
* @return 最大和
*/
public int FindGreatestSumOfSubArray(int[] array) {
int n = array.length;
int[] res = new int[n];
res[0] = array[0];
int max = res[0];
for (int i = 1; i < n; ++i) {
res[i] = res[i - 1] > 0 ? res[i - 1] + array[i] : array[i];
max = Math.max(max, res[i]);
}
return max;
}
}
```
### 测试用例
1. 功能测试(输入的数组中有正数也有负数;输入的数组中全是正数;输入的数组中全是负数);
2. 特殊输入测试(表示数组的指针位为空指针)。
================================================
FILE: docs/jianzhioffer/java/43_NumberOf1.md
================================================
## 整数中1出现的次数
### 题目描述
求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
### 解法
- 编程之美上给出的规律:
1. 如果第i位(自右至左,从1开始标号)上的数字为0,则第i位可能出现1的次数由更高位决定(若没有高位,视高位为0),等于更高位数字X当前位数的权重10^(i-1)。
2. 如果第i位上的数字为1,则第i位上可能出现1的次数不仅受更高位影响,还受低位影响(若没有低位,视低位为0),等于更高位数字X当前位数的权重10^(i-1)+(低位数字+1)。
3. 如果第i位上的数字大于1,则第i位上可能出现1的次数仅由更高位决定(若没有高位,视高位为0),等于(更高位数字+1)X当前位数的权重10^(i-1)。
总结一下以上的算法,可以看到,当计算右数第 i 位包含的 X 的个数时:
1. 取第 i 位左边(高位)的数字,乘以 10i−1,得到**基础值** a。
2. 取第 i 位数字,计算**修正值**:
1. 如果大于 X,则结果为 a+10i−1。
2. 如果小于 X,则结果为 a。
3. 如果等 X,则取第 i 位右边(低位)数字,设为 b,最后结果为 a+b+1。
相应的代码非常简单,效率也非常高,时间复杂度只有 O(logn)。
```java
/**
* @author mcrwayfun
* @version 1.0
* @description
* @date Created in 2019/1/17
*/
public class Solution {
public int NumberOf1Between1AndN_Solution(int n) {
if (n < 1) {
return 0;
}
int high, low, curr, tmp, i = 1;
high = n;
int number = 0;
while (high != 0) {
// 获取第i位的高位
high = n / (int) Math.pow(10, i);
tmp = n % (int) Math.pow(10, i);
// 获取第i位
curr = tmp / (int) Math.pow(10, i - 1);
// 获取第i位的低位
low = tmp % (int) Math.pow(10, i - 1);
if (curr == 1) {
number += high * (int) Math.pow(10, i - 1) + low + 1;
} else if (curr < 1) {
number += high * (int) Math.pow(10, i - 1);
} else {
number += (high + 1) * (int) Math.pow(10, i - 1);
}
i++;
}
return number;
}
}
```
### 测试用例
1. 功能测试(输入1~n的数字);
2. 特殊输入测试(输入的数字小于0)。
================================================
FILE: docs/jianzhioffer/java/44_DigitsInSequence.md
================================================
## 数字序列中某一位的数字
### 题目描述
数字以 `0123456789101112131415…` 的格式序列化到一个字符序列中。
在这个序列中,第 5 位(从 0 开始计数)是 5,第 13 位是 1,第 19 位是 4,等等。
请写一个函数求任意位对应的数字。
### 解法
举个栗子,求序列第 1001 位。
序列的前 10 位是 `0~9`, 这 10 个只有一位的数字。显然第 1001 位在这 10 个数字之后,因此这 10 个数字可以直接跳过。再从后面序列中找第 991(991=1001-10) 位的数字。接下来有 90 个两位数,共 180 位,由于 991>180,所以继续跳过。从 881 找...最后可以找到对应的数字以及数字的某一位。
```java
/**
* @author bingo
* @since 2018/12/7
*/
public class Solution {
/**
* 求数字序列中某一位的数字
*
* @param n 第n位
* @return 第n位的数字
*/
public int digitAtIndex(int n) {
if (n < 0) {
return -1;
}
int digits = 1;
while (true) {
long numbers = countOfIntegers(digits);
if (n < digits * numbers) {
break;
}
n -= numbers * digits;
++digits;
}
return digitAtIndex(digits, n);
}
private long countOfIntegers(int digits) {
return digits == 1
? 10
: (int) (9 * Math.pow(10, digits - 1));
}
private int digitAtIndex(int digits, int n) {
int beginNumber = getBeginNumber(digits);
int val = beginNumber + n / digits;
int indexFromRight = digits - n % digits;
for (int i = 1; i < indexFromRight; ++i) {
val /= 10;
}
return val % 10;
}
private int getBeginNumber(int digits) {
return digits == 1
? 0
: (int) Math.pow(10, digits - 1);
}
}
```
### 测试用例
1. 功能测试(输入 10、190、1000);
2. 边界值测试(输入 0、1)。
================================================
FILE: docs/jianzhioffer/java/45_SortArrayForMinNumber.md
================================================
## 把数组排成最小的数
### 题目描述
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
例如输入数组 `[3, 32, 321]`,则打印出这3个数字能排成的最小数字`321323`。
### 解法
```java
import java.util.Arrays;
/**
* @author bingo
* @since 2018/12/8
*/
class Solution {
/**
* 打印数组元素组成的最小的数字
*
* @param nums 数组
* @return 最小的数字
*/
public String printMinNumber(int[] nums) {
if (nums == null || nums.length == 0) {
return "";
}
int n = nums.length;
String[] strNums = new String[n];
for (int i = 0; i < n; ++i) {
strNums[i] = String.valueOf(nums[i]);
}
Arrays.sort(strNums, (o1, o2) -> (o1 + o2).compareTo(o2 + o1));
StringBuilder sb = new StringBuilder();
for (String str : strNums) {
sb.append(str);
}
return sb.toString();
}
}
```
### 测试用例
1. 功能测试(输入的数组中有多个数字;输入的数组中的数字有重复的数位;输入的数组中只有一个数字);
2. 特殊输入测试(表示数组的指针为空指针)。
================================================
FILE: docs/jianzhioffer/java/46_TranslateNumbersToStrings.md
================================================
## 把数字翻译成字符串
### 题目描述
给定一个数字,我们按照如下规则把它翻译为字符串:
0 翻译成 ”a”,1 翻译成 ”b”,……,11 翻译成 ”l”,……,25 翻译成 ”z”。
一个数字可能有多个翻译。例如 12258 有 5 种不同的翻译,它们分别是 ”bccfi”、”bwfi”、”bczi”、”mcfi”和”mzi”。
请编程实现一个函数用来计算一个数字有多少种不同的翻译方法。
### 解法
先写入递推式,res 表示共有多少种翻译方法。看最后一个字符,判断它与前一个字符能否构成有效翻译,计算 res[i]:
- 能,那么 `res[i] = res[i - 1] + res[i - 2]`;
- 不能,那么 `res[i] = res[i - 1]`。
```java
/**
* @author bingo
* @since 2018/12/8
*/
class Solution {
/**
* 获取翻译字符串的方法个数
*
* @param s 字符串
* @return 个数
*/
public int getTranslationCount(String s) {
if (s == null || s.length() < 2) {
return 1;
}
char[] chars = s.toCharArray();
int n = chars.length;
int[] res = new int[n];
res[0] = 1;
res[1] = isInRange(chars[0], chars[1]) ? 2 : 1;
for (int i = 2; i < n; ++i) {
res[i] = res[i - 1] + (isInRange(chars[i - 1], chars[i]) ? res[i - 2] : 0);
}
return res[n - 1];
}
private boolean isInRange(char a, char b) {
int s = (a - '0') * 10 + (b -'0');
return s >= 10 && s <= 25;
}
}
```
### 测试用例
1. 功能测试(只有一位数字;包含多位数字);
2. 特殊输入测试(负数;0;包含 25、26 的数字)。
================================================
FILE: docs/jianzhioffer/java/47_MaxValueOfGifts.md
================================================
## 礼物的最大价值
### 题目描述
在一个 `m×n` 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。
你可以从棋盘的左上角开始拿格子里的礼物,并每次向左或者向下移动一格直到到达棋盘的右下角。
给定一个棋盘及其上面的礼物,请计算你最多能拿到多少价值的礼物?
### 解法
写出递推式,res 表示获得的最大礼物。
```java
res[i][j] = Math.max(res[i - 1][j], res[i][j - 1]) + grid[i][j];
```
```java
/**
* @author bingo
* @since 2018/12/8
*/
class Solution {
/**
* 获取礼物的最大价值
*
* @param grid 数组
* @return 最大价值
*/
public int getMaxValue(int[][] grid) {
if (grid == null || grid.length == 0) {
return 0;
}
int m = grid.length;
int n = grid[0].length;
int[][] res = new int[m][n];
res[0][0] = grid[0][0];
for (int j = 1; j < n; ++j) {
res[0][j] = res[0][j - 1] + grid[0][j];
}
for (int i = 1; i < m; ++i) {
res[i][0] = res[i - 1][0] + grid[i][0];
}
for (int i = 1; i < m; ++i) {
for (int j = 1; j < n; ++j) {
res[i][j] = Math.max(res[i - 1][j], res[i][j - 1]) + grid[i][j];
}
}
return res[m - 1][n - 1];
}
}
```
### 测试用例
1. 功能测试(多行多列的矩阵;一行或者一列的矩阵;只有一个数字的矩阵);
2. 特殊输入测试(指向矩阵数组的指针为空指针)。
================================================
FILE: docs/jianzhioffer/java/48_LongestSubstringWithoutDup.md
================================================
## 最长不含重复字符的子字符串
### 题目描述
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
假设字符串中只包含从 `a` 到 `z`的字符。
### 解法
动态规划。
`res[i]` 表示以 `s[i]` 字符结尾的最长不重复字符串的长度。判断 `s[i]`:
- 若 `s[i]` 在前面没出现过,那么 `res[i] = res[i - 1] + 1`;
- 若 `s[i]` 在前面有出现过,判断它上一次出现的位置 `index` 到 `i` 的距离 `d` 与 `res[i - 1]` 的大小关系:
- 若 `d <= res[i - 1]`,说明它被包含在 `res[i - 1]` 构成的子串中,那么 `res[i] = d`;
- 若 `d > res[i - 1]`,说明它在 `res[i - 1]` 构成的子串的左侧,那么 `res[i] = res[i - 1] + 1`。
需要用一个数组 t 记录一下当前出现的字符在哪个位置。
```java
/**
* @author bingo
* @since 2018/12/8
*/
class Solution {
/**
* 最长不含重复字符的子字符串
*
* @param s 字符串
* @return 最长不重复字符子串
*/
public int longestSubstringWithoutDuplication(String s) {
if (s == null || s.length() == 0) {
return 0;
}
char[] chars = s.toCharArray();
int[] t = new int[26];
for (int i = 0; i < 26; ++i) {
t[i] = -1;
}
t[chars[0] - 'a'] = 0;
int n = chars.length;
int[] res = new int[n];
res[0] = 1;
int max = res[0];
for (int i = 1; i < n; ++i) {
int index = t[chars[i] - 'a'];
int d = i - index;
res[i] = (index == -1 || d > res[i - 1])
? res[i - 1] + 1
: d;
t[chars[i] - 'a'] = i;
max = Math.max(max, res[i]);
}
return max;
}
}
```
### 测试用例
1. 功能测试(包含多个字符的字符串;只有一个字符的字符串;所有字符都唯一的字符串;所有字符都相同的字符串);
2. 特殊输入测试(空字符串)。
================================================
FILE: docs/jianzhioffer/java/49_UglyNumber.md
================================================
## 丑数
### 题目描述
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
### 解法1
由题目可以得知,丑数必定可以整除2、3或者5(除了丑数1之外),也就是说,如果一个数能够被2整除,就连续除以2;能够被3整除,就连续除以3;能够被5整除,就连续除以5;如果最后得到1,那么这个数便是丑数。因此我们可以使用暴力的方式遍历到第N个丑数。
该解法的time complexity为O(count),比如第1500个丑数为859963392,那么就需要枚举1到859963392
```java
/**
* @author mcrwayfun
* @version v1.0
* @date Created in 2019/01/23
* @description
*/
public class Solution {
private boolean isUgly(int number){
if(number % 2 == 0)
number /= 2;
if(number % 3 == 0)
number /= 3;
if(number % 5 == 0)
number /= 5;
return number == 1;
}
public int GetUglyNumber_Solution(int index){
if(index <= 0)
return 0;
int number = 0;
int count = 0;
while(count < index){
number++;
if(isUgly(number)){
count++;
}
}
return number;
}
}
```
### 解法2
把15以内的丑数列出来:`1、2、3、4、5、6、8、9、10、12、15` ,你会发现新丑数必定是旧丑数乘以因子2、3或者5得来的。所以可以使用一个list来存储已经出现的丑数以此来计算出新的丑数,从而避免对非丑数的计算。
通过维护3个下标i2,i3,i5和它们对应的值m2,m3,m5,每次向list中添加的为m2,m3,m5中的最小值,以此来维护list的有序性。
该解法的time complexity为O(n),space complexity为O(n),属于典型的用空间换时间的解决方法。
```java
/**
* @author mcrwayfun
* @version v1.0
* @date Created in 2019/01/23
* @description
*/
public class Solution {
public int GetUglyNumber_Solution(int index) {
if (index <= 0)
return 0;
List reList = new ArrayList<>();
// 第一个丑数为1
reList.add(1);
int i2 = 0, i3 = 0, i5 = 0;
while (reList.size() < index) {
int m2 = reList.get(i2) * 2;
int m3 = reList.get(i3) * 3;
int m5 = reList.get(i5) * 5;
// 求出m2、m3、m5中的最小值,该值为加入list的丑数
int min = Math.min(m2, Math.min(m3, m5));
if (m2 == min) {
i2++;
}
if (m3 == min) {
i3++;
}
if (m5 == min) {
i5++;
}
reList.add(min);
}
// O(1)
return reList.get(reList.size() - 1);
}
}
```
### 测试用例
1. 功能测试(输入2、3、4、5、6等)。
2. 特殊输入测试(边界值1;无效输入0)。
3. 性能测试(输入较大的数字,比如1500)。
================================================
FILE: docs/jianzhioffer/java/50_01_FirstNotRepeatingChar.md
================================================
## 第一个只出现一次的字符
### 题目描述
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).
### 解法1
使用HashMap来统计字符出现的次数,因为字符的多少是固定的(大小写字母一共52个),所以可以认为使用HashMap的空间复杂度为O(1)。该解法时间复杂度为O(n)。
```java
/**
* @author mcrwayfun
* @version v1.0
* @date Created in 2019/01/24
* @description
*/
public class Solution {
public int FirstNotRepeatingChar(String str) {
if (str == null || str.length() == 0) {
return -1;
}
Map characterMap = new HashMap<>();
// hashMap is HashTable,search cost O(1)
for (int i = 0; i < str.length(); i++) {
characterMap.put(str.charAt(i), characterMap.getOrDefault(str.charAt(i), 0) + 1);
}
for (int i = 0; i < str.length(); i++) {
if (characterMap.get(str.charAt(i)) == 1) {
return i;
}
}
return -1;
}
}
```
### 测试用例
1. 功能测试(字符串中仅存在只出现一次的字符;字符串中不存在只出现一次的字符;字符串中所有字符都只出现一次)。
2. 特殊输入测试(字符串为null)。
================================================
FILE: docs/jianzhioffer/java/50_02_FristCharacterInStream.md
================================================
## 字符流中第一个不重复的字符
### 题目描述
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。如果当前字符流没有存在出现一次的字符,返回#字符。
### 解法1
与上一道题的思路是一致的。
```java
/**
* @author mcrwayfun
* @version v1.0
* @date Created in 2019/01/25
* @description
*/
public class Solution {
private StringBuilder res = new StringBuilder();
private Map characterMap = new HashMap<>();
// Insert one char from stringstream
public void Insert(char ch) {
res.append(ch);
characterMap.put(ch, characterMap.getOrDefault(ch, 0) + 1);
}
// return the first appearence once char in current stringstream
public char FirstAppearingOnce() {
for (char c : res.toString().toCharArray()) {
if (characterMap.get(c) == 1) {
return c;
}
}
return '#';
}
}
```
### 测试用例
1. 功能测试(读入一个字符;读入多个字符;读入的所有字符都是唯一的;读入的所有字符都是重复出现的)。
2. 特殊输入测试(读入0个字符)。
================================================
FILE: docs/jianzhioffer/java/52_FirstCommonNodesInLists.md
================================================
## 两个链表的第一个公共结点
### 题目描述
输入两个链表,找出它们的第一个公共结点。
**样例**
```
给出两个链表如下所示:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
输出第一个公共节点c1
```
### 解法
先遍历两链表,求出两链表的长度,再求长度差 `|n1 - n2|`。
较长的链表先走 `|n1 - n2|` 步,之后两链表再同时走,首次相遇时的节点即为两链表的第一个公共节点。
```java
/**
* @author bingo
* @since 2018/12/8
*/
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
class Solution {
/**
* 求两链表第一个公共节点
*
* @param headA 链表A
* @param headB 链表B
* @return 第一个公共节点
*/
public ListNode findFirstCommonNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
}
int n1 = len(headA), n2 = len(headB);
ListNode p1 = headA, p2 = headB;
if (n1 > n2) {
for (int i = 0; i < n1 - n2; ++i) {
p1 = p1.next;
}
} else if (n1 < n2) {
for (int i = 0; i < n2 - n1; ++i) {
p2 = p2.next;
}
}
while (p1 != p2 && p1 != null && p2 != null) {
p1 = p1.next;
p2 = p2.next;
}
return (p1 == null || p2 == null) ? null : p1;
}
private int len(ListNode head) {
int n = 0;
ListNode cur = head;
while (cur != null) {
++n;
cur = cur.next;
}
return n;
}
}
```
### 测试用例
1. 功能测试(输入的两个链表有公共节点;第一个公共节点在链表的中间,第一个公共节点在链表的末尾,第一个公共节点是链表的头节点;输入的两个链表没有公共节点);
2. 特殊输入测试(输入的链表头节点是空指针)。
================================================
FILE: docs/jianzhioffer/java/53_01_NumberOfK.md
================================================
## 数字在排序数组中出现的次数
### 题目描述
统计一个数字在排序数组中出现的次数。
例如输入排序数组 `[1, 2, 3, 3, 3, 3, 4, 5]` 和数字 3,由于 3 在这个数组中出现了 4 次,因此输出 4。
**样例**
```
输入:[1, 2, 3, 3, 3, 3, 4, 5] , 3
输出:4
```
### 解法
找出第一个 k 和最后一个 k 出现的位置。
找第一个 k 时,利用二分法,如果 `nums[m] == k`,判断它的前一个位置是不是也是 k,如果不是,说明这是第一个 k,直接返回。如果是,那么递归在左边查找第一个 k。
找最后一个 k 也同理。
```java
/**
* @author bingo
* @since 2018/12/8
*/
class Solution {
/**
* 求数字k在排序数组中出现的次数
*
* @param nums 数组
* @param k 数字k
* @return k在数组中出现的次数
*/
public int getNumberOfK(int[] nums, int k) {
if (nums == null || nums.length == 0) {
return 0;
}
int start = 0, end = nums.length - 1;
int first = getFirstK(nums, start, end, k);
int last = getLastK(nums, start, end, k);
if (first > -1 && last > -1) {
return last - first + 1;
}
return 0;
}
private int getFirstK(int[] nums, int start, int end, int k) {
if (start > end) {
return -1;
}
int m = start + ((end - start) >> 1);
if (nums[m] == k) {
if (m == 0 || (m > 0 && nums[m - 1] != k)) {
return m;
} else {
end = m - 1;
}
} else {
if (nums[m] > k) {
end = m - 1;
} else {
start = m + 1;
}
}
return getFirstK(nums, start, end, k);
}
private int getLastK(int[] nums, int start, int end, int k) {
if (start > end) {
return -1;
}
int m = start + ((end - start) >> 1);
if (nums[m] == k) {
if (m == nums.length - 1 || (m < nums.length - 1 && nums[m + 1] != k)) {
return m;
} else {
start = m + 1;
}
} else {
if (nums[m] > k) {
end = m - 1;
} else {
start = m + 1;
}
}
return getLastK(nums, start, end, k);
}
}
```
### 测试用例
1. 功能测试(数组中包含要查找的数字;数组中没有要查找的数字;要查找的数字在数组中出现一次/多次);
2. 边界值测试(查找数组中的最大值、最小值;数组中只有一个数字);
3. 特殊输入测试(表示数组的指针为空指针)。
================================================
FILE: docs/jianzhioffer/java/53_02_MissingNumber.md
================================================
## 0到n-1中缺失的数字
### 题目描述
一个长度为 `n-1` 的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围 `0` 到 `n-1` 之内。
在范围 `0` 到 `n-1` 的 `n` 个数字中有且只有一个数字不在该数组中,请找出这个数字。
**样例**
```
输入:[0,1,2,4]
输出:3
```
### 解法
找出第一个与下标不对应的数字即可。
特殊情况:
- 下标都对应,那么应该返回 `最后一个数+1`;
- 缺失的数字是第一个,那么返回 0。
```java
/**
* @author bingo
* @since 2018/12/8
*/
class Solution {
/**
* 获取0~n-1缺失的数字
*
* @param nums 数组
* @return 缺失的数字
*/
public int getMissingNumber(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int n = nums.length;
int start = 0, end = n - 1;
while (start <= end) {
int mid = start + ((end - start) >> 1);
if (nums[mid] != mid) {
if (mid == 0 || nums[mid - 1] == mid - 1) {
return mid;
}
end = mid - 1;
} else {
start = mid + 1;
}
}
return start == n ? n : -1;
}
}
```
### 测试用例
1. 功能测试(缺失的数字位于数组的开始、中间或者末尾);
2. 边界值测试(数组中只有一个数字 0);
3. 特殊输入测试(表示数组的指针为空指针)。
================================================
FILE: docs/jianzhioffer/java/53_03_IntegerIdenticalToIndex.md
================================================
## 数组中数值和下标相等的元素
### 题目描述
假设一个单调递增的数组里的每个元素都是整数并且是唯一的。
请编程实现一个函数找出数组中任意一个数值等于其下标的元素。
例如,在数组 `[-3, -1, 1, 3, 5]` 中,数字 3 和它的下标相等。
**样例**
```
输入:[-3, -1, 1, 3, 5]
输出:3
```
**注意**:如果不存在,则返回 -1。
### 解法
二分法查找。
- 当前元素等于对应的下标,直接返回该下标;
- 当前元素大于该下标,在左边查找;
- 当前元素小于该下标,在右边查找。
```java
/**
* @author bingo
* @since 2018/12/10
*/
class Solution {
/**
* 找出单调递增数组中数值和下标相等的元素
*
* @param nums 数组
* @return 数值与下标相等的元素
*/
public int getNumberSameAsIndex(int[] nums) {
if (nums == null || nums.length == 0) {
return -1;
}
int start = 0, end = nums.length - 1;
while (start <= end) {
int mid = start + ((end - start) >> 1);
if (nums[mid] == mid) {
return mid;
}
if (nums[mid] < mid) {
start = mid + 1;
} else {
end = mid - 1;
}
}
return -1;
}
}
```
### 测试用例
1. 功能测试(数组中包含或者不包含数值和下标相等的元素);
2. 边界值测试(数组中只有一个数字;数值和下标相等的元素位于数组的开头或者结尾);
3. 特殊输入测试(表示数组的指针为空指针)。
================================================
FILE: docs/jianzhioffer/java/54_KthNodeInBST.md
================================================
## 二叉搜索树的第k个结点
### 题目描述
给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4
### 解法
因为BST的中序遍历得到的是一个升序的列表,所以在进行中序遍历行进行判断即可。所以该算法的时间复杂度为O(logn)
```java
/**
* @author mcrwayfun
* @version 1.0
* @description
* @date Created in 2019/1/28
*/
class Solution {
private int count = 0;
public TreeNode KthNode(TreeNode pRoot, int k) {
if (pRoot == null || k == 0) {
return null;
}
// 左递归
TreeNode retNode = KthNode(pRoot.left, k);
if (retNode != null) {
return retNode;
}
// 符合条件则返回
count++;
if (count == k) {
return pRoot;
}
// 右递归
retNode = KthNode(pRoot.right, k);
if (retNode != null) {
return retNode;
}
return null;
}
}
```
### 测试用例
1. 功能测试(各种形态不同的二叉搜索树);
2. 边界值测试(输入k为0、1、二叉搜索树的结点数、二叉搜索树的结点数+1);
3. 特殊输入测试(指向二叉搜索树的节点的指针为空指针)。
================================================
FILE: docs/jianzhioffer/java/55_01_TreeDepth.md
================================================
## 二叉树的深度
### 题目描述
输入一棵二叉树的根结点,求该树的深度。
从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
**样例**
```
输入:二叉树[8, 12, 2, null, null, 6, 4, null, null, null, null]如下图所示:
8
/ \
12 2
/ \
6 4
输出:3
```
### 解法
递归即可。
```java
/**
* @author bingo
* @since 2018/12/10
*/
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
/**
* 求二叉树的深度
*
* @param root 二叉树根结点
* @return 深度
*/
public int treeDepth(TreeNode root) {
if (root == null) {
return 0;
}
int lDepth = treeDepth(root.left);
int rDepth = treeDepth(root.right);
return 1 + Math.max(lDepth, rDepth);
}
}
```
### 测试用例
1. 功能测试(输入普通的二叉树;二叉树中所有节点都没有左/右子树);
2. 特殊输入测试(二叉树只有一个节点;二叉树的头节点为空指针)。
================================================
FILE: docs/jianzhioffer/java/55_02_BalancedBinaryTree.md
================================================
## 平衡二叉树
### 题目描述
输入一棵二叉树的根结点,判断该树是不是平衡二叉树。
如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
**注意:**
- 规定空树也是一棵平衡二叉树。
**样例**
```
输入:二叉树[5,7,11,null,null,12,9,null,null,null,null]如下所示,
5
/ \
7 11
/ \
12 9
输出:true
```
### 解法
#### 解法一
求每个节点左右孩子的深度,判断该节点是否平衡。
这种方法需要重复遍历节点多次,不推荐。
```java
/**
* @author bingo
* @since 2018/12/10
*/
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
/**
* 判断是否是平衡二叉树
*
* @param root 二叉树根结点
* @return 是否是平衡二叉树
*/
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}
if (Math.abs(treeDepth(root.left) - treeDepth(root.right)) > 1) {
return false;
}
return isBalanced(root.left) && isBalanced(root.right);
}
private int treeDepth(TreeNode root) {
if (root == null) {
return 0;
}
int lDepth = treeDepth(root.left);
int rDepth = treeDepth(root.right);
return 1 + Math.max(lDepth, rDepth);
}
}
```
#### 解法二
```java
/**
* @author bingo
* @since 2018/12/10
*/
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
private boolean isBalanced;
/**
* 判断是否是平衡二叉树
*
* @param root 二叉树根结点
* @return 是否是平衡二叉树
*/
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}
isBalanced = true;
treeDepth(root);
return isBalanced;
}
private int treeDepth(TreeNode root) {
if (root == null || !isBalanced) {
return 0;
}
int lDepth = treeDepth(root.left);
int rDepth = treeDepth(root.right);
if (Math.abs(lDepth - rDepth) > 1) {
isBalanced = false;
}
return 1 + Math.max(lDepth, rDepth);
}
}
```
### 测试用例
1. 功能测试(平衡的二叉树;不是平衡的二叉树;二叉树中所有节点都没有左/右子树);
2. 特殊输入测试(二叉树只有一个节点;二叉树的头节点为空指针)。
================================================
FILE: docs/jianzhioffer/java/56_01_NumbersAppearOnce.md
================================================
## 数组中只出现一次的两个数字
### 题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。
请写程序找出这两个只出现一次的数字。
你可以假设这两个数字一定存在。
**样例**
```
输入:[1,2,3,3,4,4]
输出:[1,2]
```
### 解法
如果数组有一个数字出现一次,其它数字都出现两次。那么我们很容易通过异或 `^` 运算求出来。
而现在是有两个数字出现一次,那么我们考虑一下怎么将这两个数字隔开,之后我们对隔开的数组分别进行异或,不就求出来了?
我们先异或,求得的结果是两个不相同的数字异或的结果,结果一定不为 0。那么它的二进制表示中一定有 1。我们根据这个 1 在二进制中出现的位置。将数组划分,这样,两个只出现一次的数字就会被隔开,之后求异或即可。
```java
/**
* @author bingo
* @since 2018/12/10
*/
class Solution {
/**
* 求数组中只出现一次的两个数字
*
* @param nums 数字
* @return 两个数字组成的数组
*/
public int[] findNumsAppearOnce(int[] nums) {
if (nums == null || nums.length < 2) {
return null;
}
int xorRes = 0;
for (int e : nums) {
xorRes ^= e;
}
int[] res = new int[2];
int index = indexOf1(xorRes);
for (int e : nums) {
if (isBit1(e, index)) {
res[0] ^= e;
} else {
res[1] ^= e;
}
}
return res;
}
private int indexOf1(int val) {
int index = 0;
while ((val & 1) == 0) {
val = val >> 1;
++index;
}
return index;
}
private boolean isBit1(int val, int index) {
val = val >> index;
return (val & 1) == 1;
}
}
```
### 测试用例
1. 功能测试(数组中有多对重复的数字;数组中没有重复的数字)。
================================================
FILE: docs/jianzhioffer/java/56_02_NumberAppearingOnce.md
================================================
## 数组中唯一只出现一次的数字
### 题目描述
在一个数组中除了一个数字只出现一次之外,其他数字都出现了三次。
请找出那个只出现一次的数字。
你可以假设满足条件的数字一定存在。
**思考题:**
- 如果要求只使用 `O(n)` 的时间和额外 `O(1)` 的空间,该怎么做呢?
### 解法
分别累加数组中每个元素的二进制中出现的数字,那么出现三次的数字,二进制位上最后累加的结果一定能被 3 整除。不能被 3 整除的位,就属于只出现一次的数字。
```java
/**
* @author bingo
* @since 2018/12/10
*/
class Solution {
/**
* 找出数组中只出现一次的数字,其它数字都出现三次
*
* @param nums 数字
* @return 只出现一次的数字
*/
public int findNumberAppearingOnce(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int[] bits = new int[32];
int n = nums.length;
for (int i = 0; i < n; ++i) {
int val = nums[i];
for (int j = 0; j < 32; ++j) {
bits[j] += (val & 1);
val = val >> 1;
}
}
int res = 0;
for (int i = 0; i < 32; ++i) {
if (bits[i] % 3 != 0) {
res += Math.pow(2, i);
}
}
return res;
}
}
```
### 测试用例
1. 功能测试(唯一只出现一次的数字分别是 0、正数、负数;重复出现三次的数字分别是 0、正数、负数)。
================================================
FILE: docs/jianzhioffer/java/57_01_TwoNumbersWithSum.md
================================================
## 和为S的两个数字
### 题目描述
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。ps:对应每个测试案例,输出两个数,小的先输出。
### 解法
定义两个指针,start指向数组头,end指向数组末尾。如果:
- `sum == array[start] + array[end]`,则返回结果
- `sum > array[start] + array[end]`,则start++,因为数组是递增的,所以从小数右边找一个大数与 `array[end]` 求和再次判断
- 否则 end--
```java
/**
* @author mcrwayfun
* @version v1.0
* @date Created in 2019/02/02
* @description
*/
public class Solution {
public ArrayList FindNumbersWithSum(int[] array, int sum) {
ArrayList reList = new ArrayList<>();
if (array == null || array.length < 2 || sum <= array[0]) {
return reList;
}
int start = 0;
int end = array.length - 1;
while (start < end) {
int curSum = array[start] + array[end];
if (curSum == sum) {
reList.add(array[start]);
reList.add(array[end]);
return reList;
} else if (curSum < sum) {
start++;
} else {
end--;
}
}
// 查无
return reList;
}
}
```
### 测试用例
1. 功能测试(数组中存在和为 s 的两个数;数组中不存在和为 s 的两个数);
2. 特殊输入测试(表示数组的指针为空指针)。
================================================
FILE: docs/jianzhioffer/java/57_02_ContinuousSquenceWithSum.md
================================================
## 和为S的连续正数序列
### 题目描述
输入一个正数 s,打印出所有和为 s 的连续正数序列(至少含有两个数)。
例如输入 15,由于 `1+2+3+4+5=4+5+6=7+8=15`,所以结果打印出 3 个连续序列 1~5、4~6 和 7~8。
**样例**
```
输入:15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
```
### 解法
这道题同样利用两个指针left和right,将(1,2)作为初始序列。当序列和大于所求值,则left向前走,把最小的数排除了;当序列和小于所求值,则right向前走,把一个更大的数包进序列中;如果序列和等于所求值,则求值区间[left,right]中的所有数并加入到列表中,并且right向前走,把一个更大的值包入序列中。循环直到 `left < (sum + 1)/2` 。
这道题的time complexity为O(n^2),space complexity为O(1)
```java
/**
* @author mcrwayfun
* @version v1.0
* @date Created in 2019/02/03
* @description
*/
public class Solution {
public List> findContinuousSequence(int sum) {
List> reList = new ArrayList<>();
if (sum < 3) {
return reList;
}
int left = 1;
int right = 2;
int mid = (sum + 1) / 2;
int curSum = left + right;
// left小于sum一半即可(1/2n)
while (left < mid) {
// 等与sum则加入列表中(2~1/2n)
if (curSum == sum) {
reList.add(getListFromleftToright(left, right));
// right增加并重新寻找序列
right++;
curSum += right;
} else if (curSum > sum) {
curSum -= left;
left++;
} else {
right++;
curSum += right;
}
}
return reList;
}
private List getListFromleftToright(int left, int right) {
List tempList = new ArrayList<>();
for (int i = left; i <= right; i++) {
tempList.add(i);
}
return tempList;
}
}
```
### 测试用例
1. 功能测试(存在和为 s 的连续序列,如 9、100 等;不存在和为 s 的连续序列,如 4、0 等);
2. 边界值测试(连续序列的最小和 3)。
================================================
FILE: docs/jianzhioffer/java/58_01_ReverseWordsInSentence.md
================================================
## 翻转单词顺序
### 题目描述
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。
为简单起见,标点符号和普通字母一样处理。
例如输入字符串 `"I am a student."`,则输出 `"student. a am I"`。
**样例**
```
输入:"I am a student."
输出:"student. a am I"
```
### 解法
先对字符串按空格切割成数组,再逆序数组后,最后将元素拼接并返回。
```java
/**
* @author bingo
* @since 2018/12/12
*/
class Solution {
/**
* 翻转单词
*
* @param s 字符串
* @return 翻转后的字符串
*/
public String reverseWords(String s) {
if (s == null || s.length() == 0 || s.trim().equals("")) {
return s;
}
String[] arr = s.split(" ");
int p = 0, q = arr.length - 1;
while (p < q) {
swap(arr, p++, q--);
}
return String.join(" ", arr);
}
private void swap(String[] arr, int p, int q) {
String t = arr[p];
arr[p] = arr[q];
arr[q] = t;
}
}
```
### 测试用例
1. 功能测试(句子中有多个单词;句子中只有一个单词);
2. 特殊输入测试(字符串指针为空指针;字符串的内容为空;字符串中只有空格)。
================================================
FILE: docs/jianzhioffer/java/58_02_LeftRotateString.md
================================================
## 左旋转字符串
### 题目描述
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。
请定义一个函数实现字符串左旋转操作的功能。
比如输入字符串 `"abcdefg"` 和数字 2,该函数将返回左旋转 2 位得到的结果 `"cdefgab"`。
**注意:**
- 数据保证 n 小于等于输入字符串的长度。
**样例**
```
输入:"abcdefg" , n=2
输出:"cdefgab"
```
### 解法
先翻转前 n 个字符,再翻转后面的字符,最后整体翻转。
```java
/**
* @author bingo
* @since 2018/12/12
*/
class Solution {
/**
* 左旋转字符串
*
* @param str 字符串
* @param n 左旋的位数
* @return 旋转后的字符串
*/
public String leftRotateString(String str, int n) {
if (str == null || n < 1 || n > str.length()) {
return str;
}
char[] chars = str.toCharArray();
int len = chars.length;
reverse(chars, 0, n - 1);
reverse(chars, n, len - 1);
reverse(chars, 0, len - 1);
return new String(chars);
}
private void reverse(char[] chars, int p, int q) {
while (p < q) {
swap(chars, p++, q--);
}
}
private void swap(char[] chars, int p, int q) {
char t = chars[p];
chars[p] = chars[q];
chars[q] = t;
}
}
```
### 测试用例
1. 功能测试(把长度为 n 的字符串左旋转 0/1/2/n-1/n/n+1 个字符);
2. 特殊输入测试(字符串指针为空指针)。
================================================
FILE: docs/jianzhioffer/java/59_01_MaxInSlidingWindow.md
================================================
## 滑动窗口的最大值
### 题目描述
给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。
例如,如果输入数组 `[2, 3, 4, 2, 6, 2, 5, 1]` 及滑动窗口的大小 3,那么一共存在 6 个滑动窗口,它们的最大值分别为 `[4, 4, 6, 6, 6, 5]`。
**注意:**
- 数据保证 k 大于 0,且 k 小于等于数组长度。
**样例**
```
输入:[2, 3, 4, 2, 6, 2, 5, 1] , k=3
输出: [4, 4, 6, 6, 6, 5]
```
### 解法
使用一个双端队列,保证队首存放的是窗口最大值的下标。遍历数组,
1. 队尾元素比要入队的元素小,则把其移除(因为不可能成为窗口最大值)。
2. 队首下标对应的元素不在窗口内(即窗口最大值),将其从队列中移除。
3. 把每次滑动值的下标加入队列中(经过步骤1、2,此时加入队列的下标要么是当前窗口最大值的下标,要么是小于窗口最大值的下标)。
4. 滑动窗口的首地址i大于size就写入窗口最大值。
time complexity:O(n)
space complexity:O(k) , k is the size
```java
/**
* @author mcrwayfun
* @version v1.0
* @date Created in 2019/02/05
* @description
*/
class Solution {
public ArrayList maxInWindows(int[] num, int size) {
ArrayList reList = new ArrayList<>();
if (num == null || num.length < size || size < 1) {
return reList;
}
Deque deque = new LinkedList<>();
for (int i = 0; i < num.length; i++) {
// 队尾元素比要入队的元素小,则把其移除(因为不可能成为窗口最大值)
while (!deque.isEmpty() && num[deque.getLast()] <= num[i]) {
deque.pollLast();
}
// 队首下标对应的元素不在窗口内(即窗口最大值),将其从队列中移除
while (!deque.isEmpty() && (i - deque.getFirst() + 1 > size)) {
deque.pollFirst();
}
// 把每次滑动的值加入到队列中
deque.add(i);
// 滑动窗口的首地址i大于size就写入窗口最大值
if (!deque.isEmpty() && i + 1 >= size) {
reList.add(num[deque.getFirst()]);
}
}
return reList;
}
}
```
### 测试用例
1. 功能测试(输入数组的数字大小无序;输入数组的数字单调递增;输入数组的数字单调递减);
2. 边界值测试(滑动窗口的大小为 0、1、等于输入数组的长度、大于输入数组的长度);
3. 特殊输入测试(输入数组为空)。
================================================
FILE: docs/jianzhioffer/java/61_ContinousCards.md
================================================
## 扑克牌的顺子
### 题目描述
从扑克牌中随机抽 `5` 张牌,判断是不是一个顺子,即这5张牌是不是连续的。
`2~10` 为数字本身,`A` 为`1`,`J` 为 `11`,`Q` 为 `12`,`K` 为 `13`,大小王可以看做任意数字。
为了方便,大小王均以 `0` 来表示,并且假设这副牌中大小王均有两张。
**样例1**
```
输入:[8,9,10,11,12]
输出:true
```
**样例2**
```
输入:[0,8,9,11,12]
输出:true
```
### 解法
- 对数组排序;
- 计算出 0 的个数 `zeroCount`;
- 从第一个不是 0 的数字开始遍历,与后一个数字比较,如果相等,直接返回 `false`;否则累计 `gap`;
- 判断 `zeroCount` 是否大于等于 `gap`。
```java
import java.util.Arrays;
/**
* @author bingo
* @since 2018/12/12
*/
class Solution {
/**
* 判断是否是连续的数字
*
* @param numbers 数组
* @return 是否是顺子
*/
public boolean isContinuous(int [] numbers) {
if (numbers == null || numbers.length == 0) {
return false;
}
int zeroCount = 0;
Arrays.sort(numbers);
for (int e : numbers) {
if (e > 0) {
break;
}
++zeroCount;
}
int p = zeroCount, q = p + 1, n = numbers.length;
int gap = 0;
while (q < n) {
if (numbers[p] == numbers[q]) {
return false;
}
gap += (numbers[q] - numbers[p] - 1);
p = q;
++q;
}
return gap <= zeroCount;
}
}
```
### 测试用例
1. 功能测试(抽出的牌中有一个或者多个大、小王;抽出的牌中没有大、小王;抽出的牌中有对子);
2. 特殊输入测试(输入空指针)。
================================================
FILE: docs/jianzhioffer/java/README.md
================================================
# 剑指 Offer Java 题解
> 来源:[《剑指 Offer》 Java 版实现](https://github.com/doocs/coding-interview)
| # | Title |
|---|---|
| 03_01 | [Find Duplication In Array](/docs/剑指offer/Java/03_01_DuplicationInArray) |
| 03_02 | [Find Duplication In Array II](/docs/剑指offer/Java/03_02_DuplicationInArrayNoEdit) |
| 04 | [Find In Partially Sorted Matrix](/docs/剑指offer/Java/04_FindInPartiallySortedMatrix) |
| 05 | [Replace Spaces](/docs/剑指offer/Java/05_ReplaceSpaces) |
| 06 | [Print List In Reversed Order](/docs/剑指offer/Java/06_PrintListInReversedOrder) |
| 07 | [Construct Binary Tree](/docs/剑指offer/Java/07_ConstructBinaryTree) |
| 08 | [Next Node In Binary Trees](/docs/剑指offer/Java/08_NextNodeInBinaryTrees) |
| 09_01 | [Queue With Two Stacks](/docs/剑指offer/Java/09_01_QueueWithTwoStacks) |
| 09_02 | [Stack With Two Queues](/docs/剑指offer/Java/09_02_StackWithTwoQueues) |
| 10_01 | [Fibonacci](/docs/剑指offer/Java/10_01_Fibonacci) |
| 10_02 | [Jump Floor](/docs/剑指offer/Java/10_02_JumpFloor) |
| 10_03 | [Jump Floor II](/docs/剑指offer/Java/10_03_JumpFloorII) |
| 10_04 | [Rect Cover](/docs/剑指offer/Java/10_04_RectCover) |
| 11 | [Min Number In Rotated Array](/docs/剑指offer/Java/11_MinNumberInRotatedArray) |
| 12 | [String Path In Matrix](/docs/剑指offer/Java/12_StringPathInMatrix) |
| 13 | [Robot Move](/docs/剑指offer/Java/13_RobotMove) |
| 14 | [Cutting Rope](/docs/剑指offer/Java/14_CuttingRope) |
| 15 | [Number Of 1 In Binary](/docs/剑指offer/Java/15_NumberOf1InBinary) |
| 16 | [Power](/docs/剑指offer/Java/16_Power) |
| 17 | [Print 1 To Max Of N Digits](/docs/剑指offer/Java/17_Print1ToMaxOfNDigits) |
| 18_01 | [Delete Node In List](/docs/剑指offer/Java/18_01_DeleteNodeInList) |
| 18_02 | [Delete Duplicated Node](/docs/剑指offer/Java/18_02_DeleteDuplicatedNode) |
| 19 | [Regular Expressions Matching](/docs/剑指offer/Java/19_RegularExpressionsMatching) |
| 20 | [Numeric Strings](/docs/剑指offer/Java/20_NumericStrings) |
| 21 | [Reorder Array](/docs/剑指offer/Java/21_ReorderArray) |
| 22 | [Kth Node From End](/docs/剑指offer/Java/22_KthNodeFromEnd) |
| 23 | [Entry Node In List Loop](/docs/剑指offer/Java/23_EntryNodeInListLoop) |
| 24 | [Reverse List](/docs/剑指offer/Java/24_ReverseList) |
| 25 | [Merge Sorted Lists](/docs/剑指offer/Java/25_MergeSortedLists) |
| 26 | [Substructure In Tree](/docs/剑指offer/Java/26_SubstructureInTree) |
| 27 | [Mirror Of Binary Tree](/docs/剑指offer/Java/27_MirrorOfBinaryTree) |
| 28 | [Symmetrical Binary Tree](/docs/剑指offer/Java/28_SymmetricalBinaryTree) |
| 29 | [Print Matrix](/docs/剑指offer/Java/29_PrintMatrix) |
| 30 | [Min In Stack](/docs/剑指offer/Java/30_MinInStack) |
| 31 | [Stack Push Pop Order](/docs/剑指offer/Java/31_StackPushPopOrder) |
| 32_01 | [Print Tree From Top To Bottom](/docs/剑指offer/Java/32_01_PrintTreeFromTopToBottom) |
| 32_02 | [Print Trees In Lines](/docs/剑指offer/Java/32_02_PrintTreesInLines) |
| 32_03 | [Print Trees In Zigzag](/docs/剑指offer/Java/32_03_PrintTreesInZigzag) |
| 33 | [Squence Of BST](/docs/剑指offer/Java/33_SquenceOfBST) |
| 34 | [Path In Tree](/docs/剑指offer/Java/34_PathInTree) |
| 35 | [Copy Complex List](/docs/剑指offer/Java/35_CopyComplexList) |
| 36 | [Convert Binary Search Tree](/docs/剑指offer/Java/36_ConvertBinarySearchTree) |
| 39 | [More Than Half Number](/docs/剑指offer/Java/39_MoreThanHalfNumber) |
| 40 | [K Least Numbers](/docs/剑指offer/Java/40_KLeastNumbers) |
| 41 | [Stream Median](/docs/剑指offer/Java/41_StreamMedian) |
| 42 | [Greatest Sum Of Subarrays](/docs/剑指offer/Java/42_GreatestSumOfSubarrays) |
| 44 | [Digits In Sequence](/docs/剑指offer/Java/44_DigitsInSequence) |
| 45 | [Sort Array For Min Number](/docs/剑指offer/Java/45_SortArrayForMinNumber) |
| 46 | [Translate Numbers To Strings](/docs/剑指offer/Java/46_TranslateNumbersToStrings) |
| 47 | [Max Value Of Gifts](/docs/剑指offer/Java/47_MaxValueOfGifts) |
| 48 | [Longest Substring Without Dup](/docs/剑指offer/Java/48_LongestSubstringWithoutDup) |
| 52 | [First Common Nodes In Lists](/docs/剑指offer/Java/52_FirstCommonNodesInLists) |
| 53_01 | [Number Of K](/docs/剑指offer/Java/53_01_NumberOfK) |
| 53_02 | [Missing Number](/docs/剑指offer/Java/53_02_MissingNumber) |
| 53_03 | [Integer Identical To Index](/docs/剑指offer/Java/53_03_IntegerIdenticalToIndex) |
| 55_01 | [Tree Depth](/docs/剑指offer/Java/55_01_TreeDepth) |
| 55_02 | [Balanced Binary Tree](/docs/剑指offer/Java/55_02_BalancedBinaryTree) |
| 56_01 | [Numbers Appear Once](/docs/剑指offer/Java/56_01_NumbersAppearOnce) |
| 56_02 | [Number Appearing Once](/docs/剑指offer/Java/56_02_NumberAppearingOnce) |
| 57_01 | [Two Numbers With Sum](/docs/剑指offer/Java/57_01_TwoNumbersWithSum) |
| 57_02 | [Continuous Squence With Sum](/docs/剑指offer/Java/57_02_ContinuousSquenceWithSum) |
| 58_01 | [Reverse Words In Sentence](/docs/剑指offer/Java/58_01_ReverseWordsInSentence) |
| 58_02 | [Left Rotate String](/docs/剑指offer/Java/58_02_LeftRotateString) |
| 59_01 | [Max In Sliding Window](/docs/剑指offer/Java/59_01_MaxInSlidingWindow) |
| 61 | [Continous Cards](/docs/剑指offer/Java/61_ContinousCards) |
================================================
FILE: docs/jianzhioffer/java/SUMMARY.md
================================================
+ [剑指 Offer Java 题解](README.md)
+ [找出数组中重复的数字](03_01_DuplicationInArray.md)
+ [不修改数组找出重复的数字](03_02_DuplicationInArrayNoEdit.md)
+ [二维数组中的查找](04_FindInPartiallySortedMatrix.md)
+ [替换空格](05_ReplaceSpaces.md)
+ [从尾到头打印链表](06_PrintListInReversedOrder.md)
+ [重建二叉树](07_ConstructBinaryTree.md)
+ [二叉树的下一个结点](08_NextNodeInBinaryTrees.md)
+ [用两个栈实现队列](09_01_QueueWithTwoStacks.md)
+ [用两个队列实现栈](09_02_StackWithTwoQueues.md)
+ [斐波那契数列](10_01_Fibonacci.md)
+ [跳台阶](10_02_JumpFloor.md)
+ [变态跳台阶](10_03_JumpFloorII.md)
+ [矩形覆盖](10_04_RectCover.md)
+ [旋转数组的最小数字](11_MinNumberInRotatedArray.md)
+ [矩阵中的路径](12_StringPathInMatrix.md)
+ [机器人的移动范围](13_RobotMove.md)
+ [剪绳子](14_CuttingRope.md)
+ [二进制中 1 的个数](15_NumberOf1InBinary.md)
+ [数值的整数次方](16_Power.md)
+ [打印从 1 到最大的 n 位数](17_Print1ToMaxOfNDigits.md)
+ [在O(1)时间内删除链表节点](18_01_DeleteNodeInList.md)
+ [删除链表中重复的节点](18_02_DeleteDuplicatedNode.md)
+ [正则表达式匹配](19_RegularExpressionsMatching.md)
+ [表示数值的字符串](20_NumericStrings.md)
+ [调整数组顺序使奇数位于偶数前面](21_ReorderArray.md)
+ [链表中倒数第k个结点](22_KthNodeFromEnd.md)
+ [链表中环的入口结点](23_EntryNodeInListLoop.md)
+ [反转链表](24_ReverseList.md)
+ [合并两个排序的链表](25_MergeSortedLists.md)
+ [树的子结构](26_SubstructureInTree.md)
+ [二叉树的镜像](27_MirrorOfBinaryTree.md)
+ [对称的二叉树](28_SymmetricalBinaryTree.md)
+ [顺时针打印矩阵](29_PrintMatrix.md)
+ [包含min函数的栈](30_MinInStack.md)
+ [栈的压入、弹出序列](31_StackPushPopOrder.md)
+ [不分行从上到下打印二叉树](32_01_PrintTreeFromTopToBottom.md)
+ [把二叉树打印成多行](32_02_PrintTreesInLines.md)
+ [按之字形打印二叉树](32_03_PrintTreesInZigzag.md)
+ [二叉搜索树的后序遍历序列](33_SquenceOfBST.md)
+ [二叉树中和为某一值的路径](34_PathInTree.md)
+ [复杂链表的复制](35_CopyComplexList.md)
+ [二叉搜索树与双向链表](36_ConvertBinarySearchTree.md)
+ [序列化二叉树](37_SerializeBinaryTrees.md)
+ [字符串的排列](38_StringPermutation.md)
+ [数组中出现次数超过一半的数字](39_MoreThanHalfNumber.md)
+ [获取数组中最小的k个数](40_KLeastNumbers.md)
+ [数据流中的中位数](41_StreamMedian.md)
+ [连续子数组的最大和](42_GreatestSumOfSubarrays.md)
+ [整数中1出现的次数](43_NumberOf1.md)
+ [数字序列中某一位的数字](44_DigitsInSequence.md)
+ [把数组排成最小的数](45_SortArrayForMinNumber.md)
+ [把数字翻译成字符串](46_TranslateNumbersToStrings.md)
+ [礼物的最大价值](47_MaxValueOfGifts.md)
+ [最长不含重复字符的子字符串](48_LongestSubstringWithoutDup.md)
+ [丑数](49_UglyNumber.md)
+ [第一个只出现一次的字符](50_01_FirstNotRepeatingChar.md)
+ [字符流中第一个不重复的字符](50_02_FristCharacterInStream.md)
+ [两个链表的第一个公共结点](52_FirstCommonNodesInLists.md)
+ [数字在排序数组中出现的次数](53_01_NumberOfK.md)
+ [0到n-1中缺失的数字](53_02_MissingNumber.md)
+ [数组中数值和下标相等的元素](53_03_IntegerIdenticalToIndex.md)
+ [二叉搜索树的第k个结点](54_KthNodeInBST.md)
+ [二叉树的深度](55_01_TreeDepth.md)
+ [平衡二叉树](55_02_BalancedBinaryTree.md)
+ [数组中只出现一次的两个数字](56_01_NumbersAppearOnce.md)
+ [数组中唯一只出现一次的数字](56_02_NumberAppearingOnce.md)
+ [和为S的两个数字](57_01_TwoNumbersWithSum.md)
+ [和为S的连续正数序列](57_02_ContinuousSquenceWithSum.md)
+ [翻转单词顺序](58_01_ReverseWordsInSentence.md)
+ [左旋转字符串](58_02_LeftRotateString.md)
+ [滑动窗口的最大值](59_01_MaxInSlidingWindow.md)
+ [扑克牌的顺子](61_ContinousCards.md)
================================================
FILE: docs/leetcode/cpp/0001._Two_Sum.md
================================================
# 1. Two Sum
**难度: Easy**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/two-sum
* https://leetcode-cn.com/problems/two-sum
> 内容描述
```
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
```
## 解题方案
> 思路 1
******- 时间复杂度: O(NlgN)******- 空间复杂度: O(N)******
采用双指针法,先将数组排序形成了一个有序的区间,指针i,j分别指向头尾,
```
当 nums1[i] + nums[j] > traget 时,j--,
nums[i] + nums[j] < target 时,i++,
直到 nums[i] + nums[j] == target
```
```cpp
class Solution
{
public:
vector twoSum(vector& nums, int target)
{
vector > nums1;
for(int i = 0;i < nums.size();++i)
nums1.push_back(make_pair(nums[i],i));
sort(nums1.begin(),nums1.end());
int i = 0,j = nums1.size() - 1;
vector ret;
while(i < j)
{
if(nums1[i].first + nums1[j].first == target)
{
ret.push_back(nums1[i].second);
ret.push_back(nums1[j].second);
return ret;
}
nums1[i].first +nums1[j].first < target ? ++i : --j;
}
}
};
```
> 思路 2
******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
c++中提供了 unordered_map 的容器,unordered_map 中的元素没有按照它们的键值或映射值的任何顺序排序,
而是根据它们的散列值组织成桶以允许通过它们的键值直接快速访问单个元素(具有常数平均时间复杂度)
将先出现的元素储存在 unorder_map 中,遍历数组,每次查找 target - nums[i] 是否存在即可。
```cpp
class Solution
{
public:
vector twoSum(vector& nums, int target)
{
unordered_map m;
vector res;
for (int i = 0; i < nums.size(); ++i) {
m[nums[i]] = i;
}
for (int i = 0; i < nums.size(); ++i) {
int t = target - nums[i];
if (m.count(t) && m[t] != i) {
res.push_back(i);
res.push_back(m[t]);
break;
}
}
return res;
}
};
```
================================================
FILE: docs/leetcode/cpp/0002._Add_Two_Numbers.md
================================================
# 2. Add Two Numbers
**难度:Medium**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/add-two-numbers
> 内容描述
```
给定两个链表代表两个非负数,求这两个数的和
(2 -> 4 -> 3) + (5 -> 6 -> 4)
因为 342 + 465 = 807
所以返回 7 -> 0 -> 8
```
## 解题方案
> 思路
这题的的关键在于链表的数储存是倒序的,因此只要从链表头相加,再将所得数挨个储存即可,但是要注意两数相加有可能大于10要进一位。
```cpp
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* current;
ListNode* ret = nullptr;
int num = 0;
while(l1 && l2)
{
int sum = l1 ->val + l2 ->val + num;
ListNode* node = new ListNode(sum % 10);
num = sum / 10;
ret ? current ->next = node : ret = node;
current = node;
l1 = l1 ->next;
l2 = l2 ->next;
}
if(l2)
l1 = l2;
while(l1)
{
int sum = num + l1 ->val;
ListNode* node = new ListNode(sum % 10);
num = sum / 10;
current ->next = node;
current = node;
l1 = l1 ->next;
}
if(num)
{
ListNode* node = new ListNode(num);
current ->next = node;
}
return ret;
}
};
```
================================================
FILE: docs/leetcode/cpp/0003._Longest_Substring_Without_Repeating_Characters.md
================================================
# 3. Longest Substring Without Repeating Characters
**难度:Medium**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/longest-substring-without-repeating-characters
> 内容描述
```
Given a string, find the length of the longest substring without repeating characters.
Example 1:
Input: "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.
Example 2:
Input: "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.
Example 3:
Input: "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3.
Note that the answer must be a substring, "pwke" is a subsequence and not a substring.
```
## 解题方案
> 思路 1
******- 时间复杂度: O(NlgN)******- 空间复杂度: O(N)******
用 map储存 key为字符,value 为这个字符的位置,我们可以维护一个子字符串(无重复字符),记录它的起始位置,遍历 string s 当无法在map中找到字符或者小于子字符串的起始位置,就是没有在这个字符串中出现,反之则字符重复,不过 map查找为 O(lgn),因此总的时间复杂度为O(NlgN)
```cpp
class Solution {
public:
int lengthOfLongestSubstring(string s) {
map m;
int beg = 0,length = s.length(),ll = 0,ans = 0;
for(int i = 0;i < length;++i)
{
if(m.find(s[i]) == m.end() || m[s[i]] < beg)
ll++;
else
{
int pos = m[s[i]];
ans = max(ll,ans);
ll = ll - (pos - beg);
beg = pos + 1;
}
m[s[i]] = i;
}
ans = max(ans,ll);
return ans;
}
};
```
> 思路 2
******- 时间复杂度: O(NlgN)******- 空间复杂度: O(1)******
这个思路和上面差不多,用到了一个小窍门,因为储存的是字符,char为8位,因此能储存的最大数为256,这样空间复杂度就为O(1)
```cpp
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int m[256];
for(int i = 0;i < 256;++i)
m[i] = -1;
int beg = 0,length = s.length(),ll = 0,ans = 0;
for(int i = 0;i < length;++i)
{
if(m[s[i]] < beg)
ll++;
else
{
int pos = m[s[i]];
ans = max(ll,ans);
ll = ll - (pos - beg);
beg = pos + 1;
}
m[s[i]] = i;
}
ans = max(ans,ll);
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0004._Median_of_Two_Sorted_Arrays.md
================================================
# 004. Median of Two Sorted Arrays
**难度Hard**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/median-of-two-sorted-arrays/submissions/
> 内容描述
```
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
You may assume nums1 and nums2 cannot be both empty.
Example 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
```
> 思路1
******- 时间复杂度: O(n + m)******- 空间复杂度: O(1)******
直接用暴利搜索,类似与归并两个有序的数组。遍历两个数组,当总长度等于(m+n)/ 2,注意区分总长度奇数和偶数
```cpp
class Solution {
public:
double findMedianSortedArrays(vector& nums1, vector& nums2) {
int temp = (nums1.size() + nums2.size()) / 2,count1 = 0,i = 0,j = 0,current,pre;
while(i < nums1.size() && j < nums2.size() && count1 <= temp)
{
pre = current;
if(nums1[i] > nums2[j])
current = nums2[j++];
else
current = nums1[i++];
++count1;
}
if(count1 <= temp)
{
if(i < nums1.size())
while(count1 <= temp)
{
pre = current;
current = nums1[i++];
++count1;
}
else
while(count1 <= temp)
{
pre = current;
current = nums2[j++];
++count1;
}
}
if((nums1.size() + nums2.size()) % 2)
return current;
double ans = (current + pre) / 2.0;
return ans;
}
};
```
> 思路2
******- 时间复杂度: O(lg(min(n.m)))******- 空间复杂度: O(1)******
我们可以通过二分查找优化算法,利用中位数的定义,将两个数组划分为左右两个部分,nums1左半部分加nums2左半部分等于nums1右半部分加nums2的右半部分,如果总长度为偶数,那么nums1左半部分加nums2左半部分等于nums1右半部分加nums2的右半部分加1。并且```max(nums1[i],nums2[j]) <= max(nums1[i + 1],nums2[j + 1])```,接下来我们只要二分查找找i,并且要注意边界情况
```cpp
class Solution {
public:
double findMedianSortedArrays(vector& nums1, vector& nums2) {
int m = nums1.size(),n = nums2.size(),sum = m + n;
if(!nums1.size())
return sum % 2 ? nums2[sum / 2] : (nums2[sum /2] + nums2[sum / 2 - 1]) / 2.0;
if(!nums2.size())
return sum % 2 ? nums1[sum / 2] : (nums1[sum /2] + nums1[sum / 2 - 1]) / 2.0;
if(m > n)
return findMedianSortedArrays(nums2,nums1);
int l = 0,r = m - 1;
while(l < r)
{
int mid = (l + r) / 2;
int j = (sum + 1) / 2 - mid - 2;
int min1 = max(nums1[mid],nums2[j]),max1 = min(nums1[mid + 1],nums2[j + 1]);
if(min1 <= max1)
return sum % 2 ? min1 : (min1 + max1) / 2.0;
else if(nums1[mid] > nums2[j])
r = mid - 1;
else
l = mid + 1;
}
int j = (sum + 1) / 2 - l - 2;
int min1,max1;
if(j < 0)
min1 = nums1[l];
else
min1 = max(nums1[l],nums2[j]);
if(l == nums1.size() - 1)
max1 = nums2[j + 1];
else
max1 = min(nums1[l + 1],nums2[j + 1]);
if(min1 <= max1)
return sum % 2 ? min1 : (min1 + max1) / 2.0;
j++;
if(j < nums2.size() - 1)
max1 = min(nums1[l],nums2[j + 1]);
else
max1 = nums1[l];
min1 = nums2[j];
return sum % 2 ? min1 : (min1 + max1) / 2.0;
}
};
```
> 思路3
******- 时间复杂度: O(lg(n+m))******- 空间复杂度: O(1)******
由于题目中建议我们在时间复杂度O(lg(m+n))中完成,我们可以把这题看成寻找第k大的值,这样我们可以递归的去做,每次查找k/2,知道k等于1,注意边界值的处理
```cpp
class Solution {
public:
int getKth(vector nums1, int start1, int end1, vector nums2, int start2, int end2, int k) {
int len1 = end1 - start1 + 1;
int len2 = end2 - start2 + 1;
if (len1 > len2) return getKth(nums2, start2, end2, nums1, start1, end1, k);
if (len1 == 0) return nums2[start2 + k - 1];
if (k == 1) return min(nums1[start1], nums2[start2]);
int i = start1 + min(len1, k / 2) - 1;
int j = start2 + min(len2, k / 2) - 1;
if (nums1[i] > nums2[j]) {
return getKth(nums1, start1, end1, nums2, j + 1, end2, k - (j - start2 + 1));
}
else {
return getKth(nums1, i + 1, end1, nums2, start2, end2, k - (i - start1 + 1));
}
}
double findMedianSortedArrays(vector nums1, vector nums2) {
int n = nums1.size();
int m = nums2.size();
int left = (n + m + 1) / 2;
int right = (n + m + 2) / 2;
return (getKth(nums1, 0, n - 1, nums2, 0, m - 1, left) + getKth(nums1, 0, n - 1, nums2, 0, m - 1, right)) * 0.5;
}
};
```
================================================
FILE: docs/leetcode/cpp/0005._Longest_Palindromic_Substring.md
================================================
# 5. Longest Palindromic Substring
**难度:Medium**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/longest-palindromic-substring
> 内容描述
```
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example 1:
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.
Example 2:
Input: "cbbd"
Output: "bb"
```
## 解题方案
> 思路 1
******- 时间复杂度: O(N^2)******- 空间复杂度: O(N^2)******
这题如果用单纯暴力的解法,时间复杂度为 O(n ^ 3),肯定超时,那么就要对这个算法进行优化,这里采用的是DP思想,定义 p(i,j)为s中的第i个数到s中的第j个数的子串,不难看出 p(i,j)中的子串有重复计算,接下来就可以写出状态转移方程 P(i,j)=(P(i+1,j?1) and S[i] == S[j])
```cpp
class Solution {
public:
int dp[1000][1000] = {0};
string longestPalindrome(string s) {
int beg = 0,en = 1,ans = 0;
int length = s.length();
for(int i = 0;i < length;++i)
{
dp[i][i] = 1;
if(i + 1 < length && s[i] == s[i + 1])
dp[i][i + 1] = 1;
}
for(int i = 0;i < length;++i)
for(int j = 0;j <= i;++j)
{
if(i > j + 1)
dp[j][i] = (dp[j + 1][i - 1] && s[i] == s[j]);
if(dp[j][i] && i - j + 1 > ans)
{
ans = i - j + 1;
beg = j;
en = i + 1;
}
}
string ret(s.begin() + beg,s.begin() + en);
return ret;
}
};
```
================================================
FILE: docs/leetcode/cpp/0006._ZigZag_Conversion.md
================================================
# 6. ZigZag Conversion
**难度:Medium**
## 刷题内容
> 原题连接
*https://leetcode.com/problems/zigzag-conversion
*
> 内容描述
```
The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P A H N
A P L S I I G
Y I R
And then read line by line: "PAHNAPLSIIGYIR"
Write the code that will take a string and make this conversion given a number of rows:
string convert(string s, int numRows);
Example 1:
Input: s = "PAYPALISHIRING", numRows = 3
Output: "PAHNAPLSIIGYIR"
Example 2:
Input: s = "PAYPALISHIRING", numRows = 4
Output: "PINALSIGYAHRPI"
Explanation:
P I N
A L S I G
Y A H R
P I
```
## 解题方案
> 思路1
******- 时间复杂度: O(N)******- 空间复杂度: O(N + numRows)******
这道题理解了题目意思其实不难,一般人可能会开一个二维数组,然后就按题目意思储存,这样做的话时间复杂度和空间复杂度都比较大,这里我用的方法先用一个 string 类型变量 str ,resize 和输入的 s 长度相等,接着只要遍历找到 s[i] 在 str 中的位置即可
```cpp
class Solution {
public:
string convert(string s, int numRows) {
string newStr;
if(!s.length() || numRows == 1)
return s;
newStr.resize(s.length());
int num = numRows * 2 - 2,col = s.length() / num,rem = (s.length() - 1) % num;
vector rowNum;
for(int i = 0;i < numRows;++i)
if(!i)
s.length() % num ? rowNum.push_back(col + 1) : rowNum.push_back(col);
else
{
if(i == numRows - 1)
rem >= i ? rowNum.push_back(rowNum[i - 1] + (s.length() - 1) / num + 1) : rowNum.push_back(rowNum[i - 1] + (s.length() - 1) / num);
else
{
int temp = 2 * numRows - i - 2,col1 = (s.length() - 1) / num;
if(rem >= temp)
rowNum.push_back(rowNum[i - 1] + (col1 + 1) * 2);
else if(rem >= i)
rowNum.push_back(rowNum[i - 1] + col1 * 2 + 1);
else
rowNum.push_back(rowNum[i - 1] + col1 * 2);
}
}
for(int i = 0;i < s.length();++i)
{
int index1 = i % num;
int index2 = i / num;
if(!index1)
newStr[index2] = s[i];
else if(index1 == numRows - 1)
newStr[index2 + rowNum[index1 - 1]] = s[i];
else if(index1 < numRows)
newStr[index2 * 2 + rowNum[index1 - 1]] = s[i];
else
{
int index3 = 2 * numRows - index1 - 2;
newStr[index2 * 2 + 1 + rowNum[index3 - 1]] = s[i];
}
}
return newStr;
}
};
```
================================================
FILE: docs/leetcode/cpp/0007._Reverse_Integer.md
================================================
# 7. Reverse Integer
**Ѷ:Easy**
## ˢ
> ԭ
* https://leetcode.com/problems/reverse-integer/
>
```
Given a 32-bit signed integer, reverse digits of an integer.
Example 1:
Input: 123
Output: 321
Example 2:
Input: -123
Output: -321
Example 3:
Input: 120
Output: 21
Note:
Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [?231, 231 ? 1]. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows.
```
> ˼·1
******- ʱ临Ӷ: O(n)******- ռ临Ӷ: O(1)******
һeasyĿμλҪעⳬintķΧ
```cpp
class Solution {
public:
int reverse(int x) {
long long val = 0;
do
{
val = val * 10 + x % 10;
x /= 10;
} while (x);
return (val > INT_MAX || val < INT_MIN) ? 0 : val;
}
};
```
================================================
FILE: docs/leetcode/cpp/0008._String_to_Integer_(atoi).md
================================================
# 8. String to Integer (atoi)
**Ѷ:Medium**
## ˢ
> ԭ
* https://leetcode.com/problems/string-to-integer-atoi/
>
```
Implement atoi which converts a string to an integer.
The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
If no valid conversion could be performed, a zero value is returned.
Note:
Only the space character ' ' is considered as whitespace character.
Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [?231, 231 ? 1]. If the numerical value is out of the range of representable values, INT_MAX (231 ? 1) or INT_MIN (?231) is returned.
Example 1:
Input: "42"
Output: 42
Example 2:
Input: " -42"
Output: -42
Explanation: The first non-whitespace character is '-', which is the minus sign.
Then take as many numerical digits as possible, which gets 42.
Example 3:
Input: "4193 with words"
Output: 4193
Explanation: Conversion stops at digit '3' as the next character is not a numerical digit.
Example 4:
Input: "words and 987"
Output: 0
Explanation: The first non-whitespace character is 'w', which is not a numerical
digit or a +/- sign. Therefore no valid conversion could be performed.
Example 5:
Input: "-91283472332"
Output: -2147483648
Explanation: The number "-91283472332" is out of the range of a 32-bit signed integer.
Thefore INT_MIN (?231) is returned.
```
> ˼·
******- ʱ临Ӷ: O(N)******- ռ临Ӷ: O(N)******
һַתַֻֻ֣Ҫַתint͵ּɣģҪעֵ߽жֵΪЧʡȼ1032η10nηֵ
```cpp
class Solution {
public:
int myAtoi(string str) {
int i = 0,count1 = 0;
long long arr[34];
arr[0] = 1;
for(int i = 1;i < 34;++i)
arr[i] = arr[i - 1] * 10;
while(str[i] == ' ')
i++;
if(str[i] == '-' || str[i] == '+')
{
if(str[i] == '-')
count1 = 1;
i++;
}
if(!isdigit(str[i]))
return 0;
while(str[i] == '0')
i++;
long long num = 0;
int j = i;
while(j < str.length() && isdigit(str[j]))
j++;
if(j - i > 33)
return count1 ? INT_MIN : INT_MAX;
j--;
int t = 0;
while(j >= i)
{
num += (str[j] - '0') * arr[t++];
if(!count1 && num > INT_MAX)
return INT_MAX;
if(count1 && num * -1 < INT_MIN)
return INT_MIN;
j--;
}
if(count1)
num *= -1;
return num;
}
};
```
================================================
FILE: docs/leetcode/cpp/0009._Palindrome_Number.md
================================================
# 9. Palindrome Number
**难度:Medium**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/palindrome-number
*
> 内容描述
```
Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same backward as forward.
Example 1:
Input: 121
Output: true
Example 2:
Input: -121
Output: false
Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.
Example 3:
Input: 10
Output: false
Explanation: Reads 01 from right to left. Therefore it is not a palindrome.
Follow up:
Coud you solve it without converting the integer to a string?
```
## 解题方案
> 思路1
******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
这题的难度不大,由于是数字,判断回文只需要求出倒过来的数字,判断两者是否相等,不过要注意负数一定不是回文
```cpp
class Solution {
public:
bool isPalindrome(int x) {
long long ret = 0;
int num = x;
if(x < 0)
return false;
while(num)
{
ret = 10 * ret + num % 10;
num /= 10;
}
if(ret == x)
return true;
return false;
}
};
```
> 思路2
******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
计算出数字的长度,用双指针法,一个指针指向头,另一个指向尾,相等就前一个指针加一,后一个指针减一,若不相等则返回 false
```cpp
class Solution {
public:
bool isPalindrome(int x) {
if (x < 0)
return false;
int cnt = 0;
long fac = 1;
int div = INT_MAX;
while (div != 0) {
cnt++;
fac *= 10;
div = x/fac;
}
fac /= 10;
for (int i=0; i难度: Hard**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/regular-expression-matching
> 内容描述
```
Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'.
'.' Matches any single character.
'*' Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
Note:
s could be empty and contains only lowercase letters a-z.
p could be empty and contains only lowercase letters a-z, and characters like . or *.
Example 1:
Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".
Example 2:
Input:
s = "aa"
p = "a*"
Output: true
Explanation: '*' means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".
Example 3:
Input:
s = "ab"
p = ".*"
Output: true
Explanation: ".*" means "zero or more (*) of any character (.)".
Example 4:
Input:
s = "aab"
p = "c*a*b"
Output: true
Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore it matches "aab".
Example 5:
Input:
s = "mississippi"
p = "mis*is*p*."
Output: false
```
## 解题方案
> 思路1
******- 时间复杂度: O(n^2)******- 空间复杂度: O(n^2)******
用动态规划的思路去解,dp[i][j]代表字符串s中第i个字符之前的字符串与p中第j个字符串之前的字符是否匹配。写出状态转移方程。当```s[i] == p[j] || p[j] == '.'```时。```dp[i + 1][j + 1] = dp[i][j]```。当```p[j] == '*'```时,可以匹配0个,1个或多个之前相同的字符。当之前的字符```s[i] == p[j - 1] || p[j - 1] == '*'```时。```dp[i + 1][j + 1] = dp[i][j] || dp[i][j + 1]```表示匹配1个或者多个。还可匹配0个。因此```dp[i + 1][j + 1] = dp[i + 1][j + 1] || dp[i + 1][j - 1]```
```cpp
class Solution {
public:
bool isMatch(string s, string p) {
s.push_back(' ');
p.push_back(' ');
int len1 = s.length(),len2 = p.length();
int dp[len1 + 1][len2 + 1];
memset(dp,0,sizeof(dp));
dp[0][0] = 1;
for(int i = 1;i < len2;++i)
if(p[i] == '*')
dp[0][i + 1] = dp[0][i - 1];
for(int i = 0;i < len1;++i)
for(int j = 0;j < len2;++j)
if(j && p[j] == '*')
{
dp[i + 1][j + 1] = (p[j - 1] == s[i] || p[j - 1] == '.') && (dp[i][j] || dp[i][j + 1]);
dp[i + 1][j + 1] = dp[i + 1][j + 1] || dp[i + 1][j - 1];
}
else if(s[i] == p[j] || p[j] == '.')
dp[i + 1][j + 1] = dp[i][j];
return dp[len1][len2];
}
};
```
================================================
FILE: docs/leetcode/cpp/0011._Container_With_Most_Water.md
================================================
# 11. container with most water
**难度:Medium**
## 刷题内容
> 原题连接
*https://leetcode.com/problems/container-with-most-water/
*
> 内容描述
```
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.
Note: You may not slant the container and n is at least 2.
```
## 解题方案
> 思路
******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
这道题刚开始很容易想到用暴力的方法去解,但是时间复杂度为 O(n^2) 测试之后发现是 TLE,那么我们就要对算法进行优化,这里我们用双指针法,定义两个指针,一个指向头,另一个指向尾部,比较两个指针指向的数的大小,若头部的大,则指向头部的指针向后移动一位,反之,则指向尾部的指针向前移动一位。
```cpp
class Solution {
public:
int maxArea(vector& height) {
int i = 0,j = height.size() - 1,ans = INT_MIN;
while(i < j)
{
int t = min(height[i],height[j]);
ans = max(ans,t * (j - i));
height[i] < height[j] ? i++ : j--;
}
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0012._Integer_to_Roman.md
================================================
# 12. Integer to Roman
**Ѷ:Medium**
## ˢ
> ԭ
* https://leetcode.com/problems/rotate-list/
>
```
Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M.
Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
For example, two is written as II in Roman numeral, just two one's added together. Twelve is written as, XII, which is simply X + II. The number twenty seven is written as XXVII, which is XX + V + II.
Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:
I can be placed before V (5) and X (10) to make 4 and 9.
X can be placed before L (50) and C (100) to make 40 and 90.
C can be placed before D (500) and M (1000) to make 400 and 900.
Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 to 3999.
Example 1:
Input: 3
Output: "III"
Example 2:
Input: 4
Output: "IV"
Example 3:
Input: 9
Output: "IX"
Example 4:
Input: 58
Output: "LVIII"
Explanation: L = 50, V = 5, III = 3.
Example 5:
Input: 1994
Output: "MCMXCIV"
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.
```
> ˼·1
******- ʱ临Ӷ: O(n)******- ռ临Ӷ: O(n)******
Ŀѣֱһֱд
```cpp
class Solution {
public:
string intToRoman(int num) {
string ans;
vector table;
int a = 0;
int count = 0;
while(num){
a = num%10;
num /= 10;
++count;
if(count==1){
if(a==1) table.push_back("I");
else if(a==2) table.push_back("II");
else if(a==3) table.push_back("III");
else if(a==4) table.push_back("IV");
else if(a==5) table.push_back("V");
else if(a==6) table.push_back("VI");
else if(a==7) table.push_back("VII");
else if(a==8) table.push_back("VIII");
else if(a==9) table.push_back("IX");
}
else if(count==2){
if(a==1) table.push_back("X");
else if(a==2) table.push_back("XX");
else if(a==3) table.push_back("XXX");
else if(a==4) table.push_back("XL");
else if(a==5) table.push_back("L");
else if(a==6) table.push_back("LX");
else if(a==7) table.push_back("LXX");
else if(a==8) table.push_back("LXXX");
else if(a==9) table.push_back("XC");
}
else if(count==3){
if(a==1) table.push_back("C");
else if(a==2) table.push_back("CC");
else if(a==3) table.push_back("CCC");
else if(a==4) table.push_back("CD");
else if(a==5) table.push_back("D");
else if(a==6) table.push_back("DC");
else if(a==7) table.push_back("DCC");
else if(a==8) table.push_back("DCCC");
else if(a==9) table.push_back("CM");
}
else if(count==4){
if(a==1) table.push_back("M");
else if(a==2) table.push_back("MM");
else if(a==3) table.push_back("MMM");
}
}
for(int i = table.size()-1; i >= 0; --i){
ans += table[i];
}
return ans;
}
};
```
> ˼·2
******- ʱ临Ӷ: O(n)******- ռ临Ӷ: O(1)******
̫if elseIJÿǿԻһָŵдôÿ
```cpp
class Solution {
public:
int arr[7] = {'I','V','X','L','C','D','M'};
int arr1[13] = {1,4,5,9,10,40,50,90,100,400,500,900,1000};
void f(int& num,int i,string& ans)
{
if(i % 2)
{
ans.push_back(arr[i / 4 * 2]);
ans.push_back(arr[i / 2 + 1]);
}
else
ans.push_back(arr[i / 2]);
num -= arr1[i];
}
string intToRoman(int num) {
string ans;
while(num)
{
int i;
for(i = 0;i < 13;++i)
if(num < arr1[i])
{
f(num,i - 1,ans);
break;
}
if(i == 13)
f(num,i - 1,ans);
}
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0014._Longest_Common_Prefix.md
================================================
# 14. Longest Common Prefix
**Ѷ:Easy**
## ˢ
> ԭ
* https://leetcode.com/problems/longest-common-prefix/
>
```
Write a function to find the longest common prefix string amongst an array of strings.
If there is no common prefix, return an empty string "".
Example 1:
Input: ["flower","flow","flight"]
Output: "fl"
Example 2:
Input: ["dog","racecar","car"]
Output: ""
Explanation: There is no common prefix among the input strings.
Note:
All given inputs are in lowercase letters a-z.
```
> ˼·1
******- ʱ临Ӷ: O(n^2)******- ռ临Ӷ: O(1)******
ǰӴֻбӴӴɣҪעܴڿַ
```cpp
class Solution {
public:
string longestCommonPrefix(vector& strs) {
string temp;
if(!strs.size() || !strs[0].length())
return temp;
int j = 0;
while(1)
{
int i = 0;
int ch = strs[0][j];
for(;i < strs.size();++i)
if(j >= strs[i].length() || strs[i][j] != ch)
break;
if(i != strs.size())
break;
temp.push_back(strs[0][j++]);
}
return temp;
}
};
```
================================================
FILE: docs/leetcode/cpp/0015._3sum.md
================================================
# 15. 3sum
**难度:Medium**
## 刷题内容
> 原题连接
*https://leetcode.com/problems/3sum
*
> 内容描述
```
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
```
## 解题方案
> 思路
******- 时间复杂度: O(N ^ 2)******- 空间复杂度: O(N)******
之前做过两个数之和等于某个数的题目,其实这题也差不多,三数之和等于0,那么我们只要让另外两个数之和等于第三个数的相反数即可,不过这里要注意会存在重复,所以要去重
```cpp
class Solution {
public:
vector> threeSum(vector& nums) {
vector > ret;
sort(nums.begin(),nums.end());
for(int i = 0;i < nums.size();++i)
{
int t1 = i + 1,t2 = nums.size() - 1;
if(i && nums[i] == nums[i - 1])
continue;
while(t1 < t2)
if(nums[t1] + nums[t2] == -nums[i])
{
vector v;
v.push_back(nums[i]);
v.push_back(nums[t1]);
v.push_back(nums[t2]);
ret.push_back(v);
++t1;
--t2;
}
else if(nums[t1] + nums[t2] < -nums[i])
++t1;
else
--t2;
}
auto pos = unique(ret.begin(),ret.end());
ret.erase(pos,ret.end());
return ret;
}
};
```
================================================
FILE: docs/leetcode/cpp/0016._3Sum_Closest.md
================================================
## 16. 3Sum Closest
难度:Medium
## 内容
> 原题链接:https://leetcode.com/problems/3sum-closest
Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
Example:
```
Given array nums = [-1, 2, 1, -4], and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
```
## 思路
先排序,遍历第一个数,第二和第三个数通过双指针查找,转化为2sum closest的问题。如果遇到和等于target的三个数,直接返回target。
## 代码
```
class Solution {
public:
int threeSumClosest(vector& nums, int target) {
std::sort(nums.begin(), nums.end());
int min_distance{INT_MAX}, sum{0}, cur_sum{0};
for (auto it = nums.cbegin(); it != nums.cend(); ++it)
for (auto left_idx = std::next(it), right_idx = std::prev(nums.cend()); left_idx < right_idx; cur_sum > target ? --right_idx : ++left_idx) {
cur_sum = *it + *left_idx + *right_idx;
auto cur_distance = std::abs(cur_sum - target);
if (cur_sum == target)
return target;
else if (cur_distance < min_distance) {
min_distance = cur_distance;
sum = cur_sum;
}
}
return sum;
}
};
```
================================================
FILE: docs/leetcode/cpp/0017._Letter_Combinations_of_a_Phone_Number.md
================================================
# 17. Letter Combinations of a Phone Number
**Ѷ:Medium**
## ˢ
> ԭ
* https://leetcode.com/problems/letter-combinations-of-a-phone-number/
>
```
Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent.
A mapping of digit to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters.
Example:
Input: "23"
Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
Note:
Although the above answer is in lexicographical order, your answer could be in any order you want.
```
> ˼·1
******- ʱ临Ӷ: O(2^n)******- ռ临Ӷ: O(1)******
ûݷȥ⣬Ƚַת֡79ֶ֮3ĸÿִĸûݷ
```cpp
class Solution {
public:
void DFS(string& s,int i,vector& ans,string& temp)
{
if(i == s.length())
{
ans.push_back(temp);
return;
}
int t = s[i] - '2';
int ch_beg;
if(t < 6)
ch_beg = 'a' + t * 3;
else
ch_beg = 'a' + (t - 1) * 3 + 4;
int en = 3;
if(t == 5 || t == 7)
en = 4;
for(int j = 0;j < en;++j)
{
temp.push_back(ch_beg + j);
DFS(s,i + 1,ans,temp);
temp.pop_back();
}
}
vector letterCombinations(string digits) {
vector ans;
if(!digits.size())
return ans;
string temp;
DFS(digits,0,ans,temp);
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0018._4Sum.md
================================================
## 18. 4Sum
难度:Medium
## 内容
题目链接:https://leetcode.com/problems/4sum
Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
The solution set must not contain duplicate quadruplets.
Example:
```
Given array nums = [1, 0, -1, 0, -2, 2], and target = 0.
A solution set is:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
```
## 思路
思路和 3Sum 类似,多了一层for循环。为了避免重复,在存储结果的时候使用STL的set。
## 代码
```
class Solution {
public:
vector> fourSum(vector& nums, int target) {
if (nums.size() < 4) return vector>{};
std::set> res;
std::sort(nums.begin(), nums.end());
for (size_t i = 0; i < nums.size() - 3; ++i)
for (size_t j = i + 1; j < nums.size() - 2; ++j) {
auto left_idx = j + 1; auto right_idx = nums.size() - 1;
int sum = 0;
for (left_idx = j + 1, right_idx = nums.size() - 1; left_idx < right_idx; sum > target ? --right_idx : ++left_idx) {
sum = nums[i] + nums[j] + nums[left_idx] + nums[right_idx];
if (sum == target) {
vector res_single{nums[i], nums[j], nums[left_idx], nums[right_idx]};
res.insert(res_single);
}
}
}
return vector>(res.begin(), res.end());
}
};
```
================================================
FILE: docs/leetcode/cpp/0019._Remove_Nth_Node_From_End_of_List.md
================================================
# 19. Remove Nth Node From End of List
**Ѷ:Medium**
## ˢ
> ԭ
* https://leetcode.com/problems/remove-nth-node-from-end-of-list/
>
```
Given a linked list, remove the n-th node from the end of list and return its head.
Example:
Given linked list: 1->2->3->4->5, and n = 2.
After removing the second node from the end, the linked list becomes 1->2->3->5.
```
> ˼·
******- ʱ临Ӷ: O(n)******- ռ临Ӷ: O(1)******
ɾnΪ˷ֹΪ1ʱĿָ쳣ȲһͷֻҪȱܳȣܳȼȥ n ҪɾǰһͷijȣֻҪøѭҵɾҪɾĽڵ㼴ɡ
```cpp
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* current = head;
int num = 0;
while(current)
{
num++;
current = current ->next;
}
ListNode* n1 = new ListNode(0);
n1 ->next = head;
current = n1;
num -= n;
while(num)
{
num--;
current = current ->next;
}
ListNode* temp = current ->next;
current ->next = temp ->next;
return n1 ->next;
}
};
```
================================================
FILE: docs/leetcode/cpp/0020._Valid_Parentheses.md
================================================
## 20. Valid Parentheses
**难度: Easy**
## 刷题内容
> 原题连接
* https://leetcode-cn.com/problems/valid-parentheses/
> 内容描述
```
Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
An input string is valid if:
Open brackets must be closed by the same type of brackets.
Open brackets must be closed in the correct order.
Note that an empty string is also considered valid.
### Example
1. Input: "()" -> Output: true
2. Input: "()[]{}" -> Output: true
3. Input: "(]" -> Output: false
4. Input: "([)]" -> Output: false
5. Input: "{[]}" -> Output: true
```
## 解题方案
> 思路:
```
利用栈先进后出的先天优势,解决匹配问题。
```
```cpp
bool isValid(string s) {
stack stacks;
for(int i=0;i难度:Easy**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/merge-two-sorted-lists
*
> 内容描述
```
Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
Example:
Input: 1->2->4, 1->3->4
Output: 1->1->2->3->4->4
```
## 解题方案
> 思路
******- 时间复杂度: O(N + M)******- 空间复杂度: O(1)******
首先这两个链表是排序好的,那么我们先定义一个空链表,再定义两个指针 i,j,按照顺序比较两个链表,如果 i 指向的数字小于 j指向的数字,i 指向的节点插入新链表中,i = i -> next,反之则操作 j。不过要注意其中一个链表可能会先结束,所以另一个未结束的链表直接插入新链表即可
```cpp
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* h1 = l1;
ListNode* h2 = l2;
ListNode* t = new ListNode(0);
ListNode* curr = t;
while (h1 && h2)
{
if (h1->val <= h2->val) {
curr->next = h1;
h1 = h1->next;
}
else{
curr->next = h2;
h2 = h2->next;
}
curr = curr->next;
}
while (h1)
{
curr->next = h1;
h1 = h1->next;
curr = curr->next;
}
while(h2)
{
curr->next = h2;
h2 = h2->next;
curr = curr->next;
}
ListNode* res = t->next;
delete t;
return res;
}
};
```
================================================
FILE: docs/leetcode/cpp/0022._Generate_Parentheses.md
================================================
# 22. Generate Parentheses
**难度: Medium**
## 刷题内容
> 原题连接
* https://leetcode-cn.com/problems/generate-parentheses/
> 内容描述
```
给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n = 3,生成结果为:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
```
## 解题方案
> 思路 1
```
回溯法
```
```cpp
void dfs(int left, int total, string path, vector& ans){
if(total==0&&left==0){
ans.push_back(path);
return ;
}
if(left>0)
dfs(left-1, total-1, path+"(", ans);
if(left generateParenthesis(int n) {
vector ans;
string path="";
dfs(n, n*2, path, ans);
return ans;
}
```
================================================
FILE: docs/leetcode/cpp/0023._Merge_K_Sorted_Lists.md
================================================
# 23. merge k sorted lists
**难度: Hard**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/merge-k-sorted-lists/
> 内容描述
```
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
```
## 解题方案
> 思路1
******- 时间复杂度: O(Nlg(K))******- 空间复杂度: O(K)******
这里运用最小堆,先去每个链表的第一个元素构建最小堆,由于链表都是已排序的,因此,每次堆的顶部都是最小的元素,这里用优先队列实现最小堆。
```cpp
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
struct cmp
{
bool operator()(ListNode* a, ListNode* b) const
{
return a ->val > b ->val;
}
};
ListNode* mergeKLists(vector& lists) {
priority_queue,cmp> pq;
ListNode* ret = nullptr;
ListNode* current = nullptr;
for(int i = 0;i < lists.size();++i)
if(lists[i])
pq.push(lists[i]);
while(pq.size())
{
ListNode* temp = pq.top();
pq.pop();
if(!ret)
ret = temp;
else
current ->next = temp;
current = temp;
if(temp ->next)
pq.push(temp ->next);
}
return ret;
}
};
```
> 思路2
******- 时间复杂度: O(Nlg(K))******- 空间复杂度: O(1)******
这个思路用分治思想,我们可以通过归并排序解决,首先前面已经做过了两个有序链表的排序,我们可以把链表看做元素,只要对数组 Lists进行归并排序即可。
```cpp
class Solution {
public:
ListNode* merge(ListNode* list1, ListNode* list2) {
ListNode head(0);
ListNode* tail = &head;
auto cur1 = list1;
auto cur2 = list2;
while (cur1 != nullptr && cur2 != nullptr) {
if (cur1->val < cur2->val) {
tail->next = cur1;
tail = tail->next;
cur1 = cur1->next;
} else {
tail->next = cur2;
tail = tail->next;
cur2 = cur2->next;
}
}
auto cur = cur1 == nullptr ? cur2 : cur1;
while (cur != nullptr) {
tail->next = cur;
tail = tail->next;
cur = cur->next;
}
return head.next;
}
ListNode* mergeSort(vector& lists, int start, int end) {
if (start > end) {
return nullptr;
}
if (start == end) {
return lists[start];
}
int mid = start + (end - start) / 2;
auto list1 = mergeSort(lists, start, mid);
auto list2 = mergeSort(lists, mid + 1, end);
return merge(list1, list2);
}
ListNode* mergeKLists(vector& lists) {
int n = lists.size();
return mergeSort(lists, 0, n - 1);
}
};
```
================================================
FILE: docs/leetcode/cpp/0024._Swap_Nodes_in_Pairs.md
================================================
# 24. Swap Nodes in Pairs
**难度: Medium**
## 刷题内容
> 原题连接
* https://leetcode-cn.com/problems/swap-nodes-in-pairs/
> 内容描述
```
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
示例:
给定 1->2->3->4, 你应该返回 2->1->4->3.
说明:
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
```
## 解题方案
> 思路 1
```
链表反转
```
```cpp
ListNode* swapPairs(ListNode* head) {
if(head==NULL||head->next==NULL)
return head;
ListNode* slow=head;
ListNode* fast=head->next;
ListNode* pre=new ListNode(0);
ListNode* ans = pre;
while(slow&&fast){
slow->next = fast->next;
fast->next = slow;
pre->next = fast;
if(slow->next==NULL||slow->next->next==NULL){
break;
}
fast = slow->next->next;
pre = slow;
slow = slow->next;
}
return ans->next;
}
```
================================================
FILE: docs/leetcode/cpp/0025._Reverse_Nodes_In_K_Group.md
================================================
# 25.reverse nodes in k group
**ѶHard**
## ˢ
> ԭ
* https://leetcode.com/problems/reverse-nodes-in-k-group/
>
```
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
Example:
Given this linked list: 1->2->3->4->5
For k = 2, you should return: 2->1->4->3->5
For k = 3, you should return: 3->2->1->4->5
Note:
Only constant extra memory is allowed.
You may not alter the values in the list's nodes, only nodes itself may be changed.
```
> ˼·1
******- ʱ临Ӷ: O(N)******- ռ临Ӷ: O(1)******
Ŀѣ˵ݹķȥ⣬Ŀеnote˵жĴռ䣬ݹɸĿռ䣬ѵݹijѭ»ǵݹİ汾
```cpp
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
if(!head)
return head;
ListNode* current = head,*next1,*pre = nullptr;
int m = 1;
while(m <= k && current)
{
next1 = current ->next;
current ->next = pre;
pre = current;
current = next1;
++m;
}
if(m <= k)
{
while(current != head)
{
ListNode* temp = pre ->next;
pre ->next = current;
current = pre;
pre = temp;
}
pre = head;
}
else
head ->next = reverseKGroup(current,k);
return pre;
}
};
```
================================================
FILE: docs/leetcode/cpp/0026._Remove_Duplicates_From_Sorted_Array.md
================================================
# 26.Remove Duplicates From Sorted Array
**ѶEasy**
## ˢ
> ԭ
* https://leetcode.com/problems/remove-duplicates-from-sorted-array/
>
```
Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
Example 1:
Given nums = [1,1,2],
Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.
It doesn't matter what you leave beyond the returned length.
Example 2:
Given nums = [0,0,1,1,1,2,2,3,3,4],
Your function should return length = 5, with the first five elements of nums being modified to 0, 1, 2, 3, and 4 respectively.
It doesn't matter what values are set beyond the returned length.
Clarification:
Confused why the returned value is an integer but your answer is an array?
Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well.
Internally you can think of this:
// nums is passed in by reference. (i.e., without making a copy)
int len = removeDuplicates(nums);
// any modification to nums in your function would be known by the caller.
// using the length returned by your function, it prints the first len elements.
for (int i = 0; i < len; i++) {
print(nums[i]);
}
```
> ˼·
******- ʱ临Ӷ: O(N)******- ռ临Ӷ: O(1)******
Ѿõģֱӱ飬һָ i ָʼһ j ָڶ j ָ i ָ```++i,++j```ֻ```++j```
```cpp
class Solution {
public:
int removeDuplicates(vector& nums) {
int j = 0;
if(!nums.size())
return 0;
for(int i = 1;i < nums.size();)
{
while(nums[j] == nums[i] && i < nums.size())
++i;
if(i == nums.size())
break;
swap(nums[++j],nums[i++]);
}
return j + 1;
}
};
```
================================================
FILE: docs/leetcode/cpp/0027._Remove_Element.md
================================================
# 27.Remove Element
**ѶEasy**
## ˢ
> ԭ
* https://leetcode.com/problems/remove-element/
>
```
Given an array nums and a value val, remove all instances of that value in-place and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
The order of elements can be changed. It doesn't matter what you leave beyond the new length.
Example 1:
Given nums = [3,2,2,3], val = 3,
Your function should return length = 2, with the first two elements of nums being 2.
It doesn't matter what you leave beyond the returned length.
Example 2:
Given nums = [0,1,2,2,3,0,4,2], val = 2,
Your function should return length = 5, with the first five elements of nums containing 0, 1, 3, 0, and 4.
Note that the order of those five elements can be arbitrary.
It doesn't matter what values are set beyond the returned length.
Clarification:
Confused why the returned value is an integer but your answer is an array?
Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well.
Internally you can think of this:
// nums is passed in by reference. (i.e., without making a copy)
int len = removeElement(nums, val);
// any modification to nums in your function would be known by the caller.
// using the length returned by your function, it prints the first len elements.
for (int i = 0; i < len; i++) {
print(nums[i]);
}
```
> ˼·
******- ʱ临Ӷ: O(n)******- ռ临Ӷ: O(1)******
ǿԱ飬ѵ val ŵĺ벿־Сǿ˫ָʵ֡ nums[i] != val ʱnums[j++] = nums[i]
```cpp
class Solution {
public:
int removeElement(vector& nums, int val) {
int i ,count = 0,j = 0,numsSize = nums.size();
for(i = 0;i < numsSize;i++)
{
if(nums[i] == val)
{
count++;
}
else
nums[j++] = nums[i];
}
return numsSize - count;
}
};
```
================================================
FILE: docs/leetcode/cpp/0028._Implement_Strstr.md
================================================
# 28.implement strstr
**ѶEasy**
## ˢ
> ԭ
* https://leetcode.com/problems/implement-strstr/
>
```
Implement strStr().
Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
Example 1:
Input: haystack = "hello", needle = "ll"
Output: 2
Example 2:
Input: haystack = "aaaaa", needle = "bba"
Output: -1
Clarification:
What should we return when needle is an empty string? This is a great question to ask during an interview.
For the purpose of this problem, we will return 0 when needle is an empty string. This is consistent to C's strstr() and Java's indexOf().
```
> ˼·
******- ʱ临Ӷ: O(N)******- ռ临Ӷ: O(1)******
ֱӱ haystack ƥ䵽 needle һַʱͱ needleȽַ
```cpp
class Solution {
public:
int strStr(string haystack, string needle) {
int j = 0,i = 0,index= 0;
while(i < haystack.size() && j < needle.size())
{
if(haystack[i] == needle[j])
{
if(!j)
index = i;
j++;
i++;
}
else
{
i = ++index;
j = 0;
}
}
if(j == needle.size())
return index;
return -1;
}
};
```
================================================
FILE: docs/leetcode/cpp/0029._Divide_Two_Integers.md
================================================
# 29.divide two integers
**ѶMedium**
## ˢ
> ԭ
* https://leetcode.com/problems/divide-two-integers/
>
```
Given two integers dividend and divisor, divide two integers without using multiplication, division and mod operator.
Return the quotient after dividing dividend by divisor.
The integer division should truncate toward zero.
Example 1:
Input: dividend = 10, divisor = 3
Output: 3
Example 2:
Input: dividend = 7, divisor = -3
Output: -2
Note:
Both dividend and divisor will be 32-bit signed integers.
The divisor will never be 0.
Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [?231, 231 ? 1]. For the purpose of this problem, assume that your function returns 231 ? 1 when the division result overflows.
```
> ˼·
******- ʱ临Ӷ: O(N)******- ռ临Ӷ: O(1)******
ֱñķ϶ʱ˿ռ任ʱ䣬 int Ϊ2^31 - 1 ĴСҲǹ̶ġñȶһres = 0ÿζ res += divisor * 2^n ֱdividend ٴ res = divisor * 2^(n-1)ʼֱijres + divisor > dividend
```cpp
class Solution {
public:
int divide(int dividend, int divisor) {
if(!dividend)
return 0;
long long arr[33];
arr[0] = 1;
for(int i = 1;i < 33;++i)
arr[i] = arr[i - 1] * 2;
long long temp1 = dividend,temp2 = divisor;
if(temp1 < 0)
temp1 *= -1;
if(temp2 < 0)
temp2 *= -1;
long long res,pre = 0,ret = 0;
int count1 = 0;
while(1)
{
res = pre + arr[count1] * temp2;
if(res > temp1)
{
if(!count1)
break;
pre = pre + arr[count1 - 1] * temp2;
ret += arr[count1 - 1];
count1 = 0;
}
else
count1++;
}
if(dividend < 0)
ret *= -1;
if(divisor < 0)
ret *= -1;
if(ret == 2147483648)
return ret - 1;
return ret;
}
};
```
================================================
FILE: docs/leetcode/cpp/0030._Substring_With_Concatenation_Of_All_Words.md
================================================
# 30.substring with concatenation of all words
**难度Hard**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/substring-with-concatenation-of-all-words/
> 内容描述
```
You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.
Example 1:
Input:
s = "barfoothefoobarman",
words = ["foo","bar"]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are "barfoor" and "foobar" respectively.
The output order does not matter, returning [9,0] is fine too.
Example 2:
Input:
s = "wordgoodstudentgoodword",
words = ["word","student"]
Output: []
```
> 思路
******- 时间复杂度: O(mlgn)******- 空间复杂度: O(m+n)******
这题可以两个 map 来解决,第一个 map 中存放了 words 中的所有单词和出现的次数,接下来遍历字符串,固定区间的大小为 words 的长度,存入另一个map,两个 map 相等就放入返回数组中
```cpp
class Solution {
public:
vector findSubstring(string s, vector& words) {
vector ans;
if(!s.length() || !words.size())
return ans;
unordered_map m1;
int len = words.size(),wl = words[0].length(),sl = s.length();
for(int i = 0;i < words.size();++i)
m1[words[i]]++;
int count1 = 0,reLen = wl * len,left = 0;
for(int i = 0;i < sl - wl * len + 1;++i)
{
unordered_map m2;
for(int j = 0,left = i;j < len;j ++)
{
string temp = s.substr(left,wl);
left += wl;
m2[temp]++;
}
if(m2 == m1)
ans.push_back(i);
}
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0031._Next_Permutatio.md
================================================
# 31.Next Permutatio
**难度Medium**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/next-permutation/
> 内容描述
```
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
The replacement must be in-place and use only constant extra memory.
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
```
> 思路
******- 时间复杂度: O(n)******- 空间复杂度: O(1)******
我们可以用两个指针表示需要交换的两个数,遍历数组。这题的最坏的情况下,数组降序排列,排序算法的复杂度也是O(n)。
```cpp
class Solution {
public:
void nextPermutation(vector& nums) {
int n1 = 0,n2 = 0;
for(int i = 1;i < nums.size();++i)
if(nums[i] > nums[n2])
{
n1 = n2;
n2 = i;
}
else if((nums[i] < nums[n2] && nums[i] > nums[n1]) || nums[i] == nums[n2])
n2 = i;
else if(nums[i] <= nums[n1])
{
int j = i;
for(;j < nums.size() - 1;++j)
if(nums[j + 1] > nums[j])
{
n1 = j;
n2 = j + 1;
break;
}
i = j + 1;
}
if(n1 == n2)
sort(nums.begin(),nums.end());
else
{
swap(nums[n1],nums[n2]);
sort(nums.begin() + n1 + 1,nums.end());
}
}
};
```
================================================
FILE: docs/leetcode/cpp/0032._Longest_Valid_Parentheses.md
================================================
# 32. Longest Valid Parentheses
**Ѷ:Hard**
## ˢ
> ԭ
* https://leetcode.com/problems/longest-valid-parentheses/
>
```
Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.
Example 1:
Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"
Example 2:
Input: ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()"
```
> ˼·1
******- ʱ临Ӷ: O(n)******- ռ临Ӷ: O(n)******
DPķ⡣һջȥߵIJ֣'('λãֱһ')'ʱͼ¼ջ'('λãǾͿд״̬תƷ̡dp[i]ַеiԶλáһ')'ʱdp[i] = ջ'('λáڿԴţdp[dp[i] - 1]ڣdp[i] = dp[dp[i] - 1]Ҫע߽缴ɡ
```cpp
class Solution {
public:
int longestValidParentheses(string s) {
int len = s.length();
if(!len)
return 0;
int dp[len];
memset(dp,-1,sizeof(dp));
int ans = 0;
vector v;
for(int i = 0;i < len;++i)
if(s[i] == '(')
v.push_back(i);
else if(s[i] == ')' && v.size())
{
dp[i] = v[v.size() - 1];
if(dp[i] && dp[dp[i] - 1] >= 0)
dp[i] = dp[dp[i] - 1];
ans = max(ans,i - dp[i] + 1);
v.pop_back();
}
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0033._Search_in_Rotated_Sorted_Array.md
================================================
# 033. Search in Rotated Sorted Array
**难度Medium**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/search-in-rotated-sorted-array/
> 内容描述
```
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).
You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.
Your algorithm's runtime complexity must be in the order of O(log n).
Example 1:
Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4
Example 2:
Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1
```
> 思路1
******- 时间复杂度: O(n)******- 空间复杂度: O(1)******
第一个方法是直接遍历数组,找到返回数组下标,找不到就返回-1
```cpp
class Solution {
public:
int search(vector& nums, int target) {
for(int i = 0;i < nums.size();++i)
if(nums[i] == target)
return i;
return -1;
}
};
```
> 思路2
******- 时间复杂度: O(lgn)*****- 空间复杂度: O(1)******
第二个方法是用二分法找到旋转轴,再用二分法找到目标数
```cpp
class Solution {
public:
int search(vector& nums, int target) {
int i = 0,j = nums.size() - 1;
if(!nums.size())
return -1;
while(i < j - 1)
{
int mid = (i + j) / 2;
if(nums[i] < nums[mid])
i = mid;
else
j = mid;
//cout << i << j << endl;
}
if(nums[i] <= nums[j])
j = i;
//cout << j;
auto pos = lower_bound(nums.begin(),nums.begin() + j,target);
if(pos != nums.end() && (*pos) == target)
return pos - nums.begin();
pos = lower_bound(nums.begin() + j,nums.end(),target);
if(pos != nums.end() && (*pos) == target)
return pos - nums.begin();
return -1;
}
};
```
================================================
FILE: docs/leetcode/cpp/0034._Find_First_and_Last_Position_of_Element_in_Sorted_Array.md
================================================
# 34. Find First and Last Position of Element in Sorted Array
**Ѷ:Medium**
## ˢ
> ԭ
* https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/
>
```
Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.
Your algorithm's runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1].
Example 1:
Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]
Example 2:
Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]
```
> ˼·1
******- ʱ临Ӷ: O(lgn)******- ռ临Ӷ: O(1)******
͵ĶȲĿǷtargetڷֱҵһֵtargetһtarget
```cpp
class Solution {
public:
vector searchRange(vector& nums, int target) {
int l = 0,r = nums.size();
vector ans = {-1,-1};
int mid = -1;
while(l < r)
{
mid = (r + l) / 2;
if(nums[mid] < target)
l = mid + 1;
else if(nums[mid] > target)
r = mid;
else
break;
}
if(mid == -1 || nums[mid] != target)
return ans;
int mid1 = l = mid;
r = nums.size();
while(l < r)
{
mid = (r + l) / 2;
if(mid == nums.size())
break;
if(nums[mid] > target)
r = mid;
else
l = mid + 1;
}
if(nums[mid] > target)
mid--;
ans[1] = mid;
l = 0;
r = mid1 + 1;
while(l < r)
{
mid = (r + l) / 2;
if(nums[mid] < target)
l = mid + 1;
else
r = mid;
}
if(nums[mid] < target)
mid++;
ans[0] = mid;
return ans;
}
};
```
> ˼·2
******- ʱ临Ӷ: O(lgn)******- ռ临Ӷ: O(1)******
õc++lower_boundupper_bound
```cpp
class Solution {
public:
vector searchRange(vector& nums, int target) {
auto pos1 = lower_bound(nums.begin(),nums.end(),target);
vector ans = {-1,-1};
if(pos1 == nums.end() || (*pos1) != target)
return ans;
ans[0] = pos1 - nums.begin();
auto pos2 = upper_bound(nums.begin(),nums.end(),target);
ans[1] = pos2 - nums.begin() - 1;
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0035._Search_Insert_Position.md
================================================
# 35.search insert position
**难度:Easy**
## 刷题内容
> 原题连接
*https://leetcode.com/problems/search-insert-position/
*
> 内容描述
```
Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
You may assume no duplicates in the array.
```
> 思路1
******- 时间复杂度: O(lgN)******- 空间复杂度: O(1)******
由于数组是已经排序好的,这就是一个很典型的二分法
```cpp
class Solution {
public:
int searchInsert(vector& nums, int target) {
int first = 0,last = nums.size() - 1;
while(last > (first + 1))
{
int medium = (last + first) / 2;
if(nums[medium] == target)
return medium;
else if(nums[medium] < target)
first = medium;
else
last = medium;
}
if(target > nums[last])
return last + 1;
else if((target < nums[first]) || (target == nums[first]))
return first;
else
return last;
}
};
```
> 思路2
******- 时间复杂度: O(lgN)******- 空间复杂度: O(1)******
其实这个思路也是二分法,只不过c++中已经给我们封装好了lower_bound,我们直接调用即可
代码看上去也简洁很多
```cpp
class Solution {
public:
int searchInsert(vector& nums, int target) {
auto pos = lower_bound(nums.begin(),nums.end(),target);
return pos - nums.begin();
}
};
```
================================================
FILE: docs/leetcode/cpp/0036._Valid_Sudoku.md
================================================
# 36. Valid Sudoku
**Ѷ:Medium**
## ˢ
> ԭ
* https://leetcode.com/problems/valid-sudoku/
>
```
Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:
Each row must contain the digits 1-9 without repetition.
Each column must contain the digits 1-9 without repetition.
Each of the 9 3x3 sub-boxes of the grid must contain the digits 1-9 without repetition.
A partially filled sudoku which is valid.
The Sudoku board could be partially filled, where empty cells are filled with the character '.'.
Example 1:
Input:
[
["5","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]
]
Output: true
Example 2:
Input:
[
["8","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]
]
Output: false
Explanation: Same as Example 1, except with the 5 in the top left corner being
modified to 8. Since there are two 8's in the top left 3x3 sub-box, it is invalid.
Note:
A Sudoku board (partially filled) could be valid but is not necessarily solvable.
Only the filled cells need to be validated according to the mentioned rules.
The given board contain only digits 1-9 and the character '.'.
The given board size is always 9x9.
```
> ˼·1
******- ʱ临Ӷ: O(n^2)******- ռ临Ӷ: O(1)******
board9x9ģʵʵʱ临ӶҲ9x9ġֻҪֱжÿÿкÿ9СǷظɡѶȲ
```cpp
class Solution {
public:
bool isValidSudoku(vector>& board) {
int arr[9][9];
int arr1[9][9];
int arr2[9][9];
memset(arr,0,sizeof(arr));
memset(arr2,0,sizeof(arr1));
memset(arr1,0,sizeof(arr1));
for(int i = 0;i < 9;++i)
for(int j = 0;j < 9;++j)
if(board[i][j] != '.')
{
if(arr[i][board[i][j] - '1'] || arr1[j][board[i][j] -'1'] || arr2[3 * (i / 3) + (j / 3)][board[i][j] -'1'])
return 0;
arr[i][board[i][j] - '1'] = 1;
arr1[j][board[i][j] -'1'] = 1;
arr2[3 * (i / 3) + (j / 3)][board[i][j] -'1'] = 1;
}
return 1;
}
};
```
================================================
FILE: docs/leetcode/cpp/0038._Count_and_Say.md
================================================
# 38. Count and Say
**Ѷ:Easy**
## ˢ
> ԭ
* https://leetcode.com/problems/count-and-say/
>
```
The count-and-say sequence is the sequence of integers with the first five terms as following:
1. 1
2. 11
3. 21
4. 1211
5. 111221
1 is read off as "one 1" or 11.
11 is read off as "two 1s" or 21.
21 is read off as "one 2, then one 1" or 1211.
Given an integer n where 1 n 30, generate the nth term of the count-and-say sequence.
Note: Each term of the sequence of integers will be represented as a string.
Example 1:
Input: 1
Output: "1"
Example 2:
Input: 4
Output: "1211"
```
> ˼·
******- ʱ临Ӷ: O(n)******- ռ临Ӷ: O(1)******
ҪŪĿ˼n == 1ʱ1һ1 one 1n == 2ʱǡ1121 two 1n == 3ʱǡ211211 one 2 one 1n == 4ʱǡ1211ƣдѭģIJɡ
```cpp
class Solution {
public:
string countAndSay(int n) {
string str;
str.push_back('0' + 1);
n--;
while(n)
{
string temp;
for(int i = 0;i < str.length();)
{
int j = 0;
while(i + j < str.length() && str[i] == str[j + i])
++j;
temp.push_back('0' + j);
temp.push_back(str[i]);
i += j;
}
--n;
str = temp;
}
return str;
}
};
```
================================================
FILE: docs/leetcode/cpp/0039._Combination_Sum.md
================================================
# 39. Combination Sum
**难度: Middle**
## 刷题内容
> 原题连接
* https://leetcode-cn.com/problems/combination-sum/
> 内容描述
```
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例 1:
输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
示例 2:
输入: candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
```
## 解题方案
> 思路 1
```
回溯
```
```cpp
void dfs(vector& candidates, int target, int index, vector& path, vector>& ans){
if(target<0)
return ;
if(target == 0){
ans.push_back(path);
return ;
}
for(int i=index;i> combinationSum(vector& candidates, int target) {
sort(candidates.begin(), candidates.end());
vector> ans;
vector path;
dfs(candidates, target, 0, path, ans);
return ans;
}
```
================================================
FILE: docs/leetcode/cpp/0040._Combination_Sum_II.md
================================================
# 40. Combination Sum II
**难度: Medium**
## 刷题内容
> 原题连接
* https://leetcode-cn.com/problems/combination-sum-ii/
> 内容描述
```
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明:
所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
[1,2,2],
[5]
]
```
## 解题方案
> 思路 1
```
回溯
```
```cpp
void dfs(vector& candidates, int target, int index, vector& path, vector>& ans){
if(target<0)
return ;
if(target == 0){
ans.push_back(path);
return ;
}
for(int i=index;i index && candidates[i] == candidates[i - 1]) continue;
path.push_back(candidates[i]);
dfs(candidates, target-candidates[i], i+1, path, ans);
path.pop_back();
}
}
vector> combinationSum2(vector& candidates, int target) {
vector> ans;
vector path;
sort(candidates.begin(), candidates.end());
dfs(candidates, target, 0, path, ans);
return ans;
}
```
================================================
FILE: docs/leetcode/cpp/0041._First_Missing_Positive.md
================================================
# 041.First Missing Positive
**ѶHard**
## ˢ
> ԭ
* https://leetcode.com/problems/first-missing-positive/
>
```
Given an unsorted integer array, find the smallest missing positive integer.
Example 1:
Input: [1,2,0]
Output: 3
Example 2:
Input: [3,4,-1,1]
Output: 2
Example 3:
Input: [7,8,9,11,12]
Output: 1
```
> ˼·
******- ʱ临Ӷ: O(n)******- ռ临Ӷ: O(1)******
տʼĿ˼ˣ֮ACˡʵĴռ䣬Ӧû뵽ֱ hash УǿԱ飬1ĵһ12ڣĵڶλӣ
```cpp
class Solution {
public:
int firstMissingPositive(vector& nums) {
if(!nums.size())
return 1;
for(int i = 0;i < nums.size();)
{
if(nums[i] < nums.size() && nums[i] != nums[nums[i] - 1])
swap(nums[i],nums[nums[i] - 1]);
else
++i;
}
for(int i = 0;i < nums.size();++i)
if(nums[i] != i + 1)
return i + 1;
return nums.size() + 1;
}
};
```
================================================
FILE: docs/leetcode/cpp/0042._Trapping_Rain_Water.md
================================================
# 42. Trapping Rain Water
**ѶHard**
## ˢ
> ԭ
* https://leetcode.com/problems/trapping-rain-water/
>
```
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.
Example:
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
```
¼ l = 0飬 height[i] < height[l],˵λˮ¼ˮ height[i] >= height[l]˵[i,l]ڿԻˮȻȥˮǻˮ֮ l != height.size() - 1飬衣
> ˼·
******- ʱ临Ӷ: O(N)******- ռ临Ӷ: O(1)******
```cpp
class Solution {
public:
int trap(vector& height) {
int l = 0,sum1 = 0,water = 0,i;
for(i = 1;i < height.size();++i)
if(height[i] >= height[l])
{
water = water + height[l] * (i - l - 1) - sum1;
l = i;
sum1 = 0;
}
else
sum1 += height[i];
if(l != (height.size() - 1))
{
int temp = l;
sum1 = 0;
for(i = height.size() - 2,l = height.size() - 1;i >= temp;--i)
if(height[i] >= height[l])
{
water = water + height[l] * (l- i - 1) - sum1;
l = i;
sum1 = 0;
}
else
sum1 += height[i];
}
return water;
}
};
```
================================================
FILE: docs/leetcode/cpp/0043._Multiply_Strings.md
================================================
# 43. Multiply Strings
**Ѷ:Medium**
## ˢ
> ԭ
* https://leetcode.com/problems/multiply-strings/
>
```
Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2, also represented as a string.
Example 1:
Input: num1 = "2", num2 = "3"
Output: "6"
Example 2:
Input: num1 = "123", num2 = "456"
Output: "56088"
Note:
The length of both num1 and num2 is < 110.
Both num1 and num2 contain only digits 0-9.
Both num1 and num2 do not contain any leading zero, except the number 0 itself.
You must not use any built-in BigInteger library or convert the inputs to integer directly.
```
> ˼·1
******- ʱ临Ӷ: O(n^2)******- ռ临Ӷ: O(1)******
ֱȽϴlong longֵ˲ת֣ģֵij˷ÿһλ¼һַС
```cpp
class Solution {
public:
string multiply(string num1, string num2) {
string ans;
int d[120][120];
memset(d,0,sizeof(d));
for(int i = num2.size() - 1;i >= 0;--i)
{
int count1 = 0;
for(int j = num1.size()- 1;j >= 0;--j)
{
int pro_ans = (num1[j] - '0') * (num2[i] - '0');
d[num2.size() - 1 - i][num1.size() - j - 1] = pro_ans % 10 + count1;
count1 = pro_ans / 10;
if(d[num2.size() - 1 - i][num1.size() - j - 1] >= 10)
{
count1++;
d[num2.size() - 1 - i][num1.size() - j - 1] %= 10;
}
}
d[num2.size() - 1 - i][num1.size()] = count1;
}
int count1 = 0;
for(int j = 0;j < num1.size() + num2.size();++j)
{
for(int i = 0;i <= num2.size();++i)
if(j - i >= 0 && j - i <= num1.size())
count1 += d[i][j - i];
ans.push_back(count1 % 10 + '0');
count1 /= 10;
}
while(ans.length() > 1 && ans[ans.length() - 1] == '0')
ans.pop_back();
reverse(ans.begin(),ans.end());
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0044._Wildcard_Matching.md
================================================
# 44. Wildcard Matching
**Ѷ:Hard**
## ˢ
> ԭ
* https://leetcode.com/problems/wildcard-matching/
>
```
Given an input string (s) and a pattern (p), implement wildcard pattern matching with support for '?' and '*'.
'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).
The matching should cover the entire input string (not partial).
Note:
s could be empty and contains only lowercase letters a-z.
p could be empty and contains only lowercase letters a-z, and characters like ? or *.
Example 1:
Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".
Example 2:
Input:
s = "aa"
p = "*"
Output: true
Explanation: '*' matches any sequence.
Example 3:
Input:
s = "cb"
p = "?a"
Output: false
Explanation: '?' matches 'c', but the second letter is 'a', which does not match 'b'.
Example 4:
Input:
s = "adceb"
p = "*a*b"
Output: true
Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".
Example 5:
Input:
s = "acdcb"
p = "a*c?b"
Output: false
```
> ˼·
******- ʱ临Ӷ: O(n^2)******- ռ临Ӷ: O(n^2)******
տʼʱΪһģ⣬ʱŷֿDPʹDPʱҵ״̬תƷ̡Ƕdp[i][j]ʾַ p е i - 1ĸ֮ǰַַ s еĵ j - 1ĸ֮ǰӴƥ䣬ǾͿдӦ״̬תƷ̵p[i] == '?'p[i] == s[j]ʱdp[i + 1][j + 1] = dp[i][j],p[i] == '*'ʱj < p.length(),dp[i + 1][j + 1] = dp[i][j],dp[i + 1][j] = dp[i][j],dp[p.length()][s.length() - 1]
```cpp
class Solution {
public:
bool isMatch(string s, string p) {
if(!p.length())
return !s.length();
s.push_back(' ');
int dp[p.length() + 1][s.length() + 1];
for(int i =0;i <= p.length();++i)
for(int j = 0;j <= s.length();++j)
dp[i][j] = 0;
int count1 = 1;
dp[0][0] = 1;
for(int i = 0;i < p.length();++i)
{
for(int j = 0;j < s.length();++j)
if(p[i] == '?' || p[i] == s[j])
dp[i + 1][j + 1] = dp[i][j];
else if(p[i] == '*' && dp[i][j])
{
dp[i + 1][j + 1] = 1;
dp[i + 1][j] = 1;
++j;
while(j < s.length())
{
dp[i + 1][j + 1] = 1;
++j;
}
}
}
return dp[p.length()][s.length() - 1];
}
};
```
================================================
FILE: docs/leetcode/cpp/0045._Jump_Game_II.md
================================================
# 045. Jump Game II
**ѶHard**
## ˢ
> ԭ
* https://leetcode.com/problems/jump-game-ii/
>
```
Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Your goal is to reach the last index in the minimum number of jumps.
Example:
Input: [2,3,1,1,4]
Output: 2
Explanation: The minimum number of jumps to reach the last index is 2.
Jump 1 step from index 0 to 1, then 3 steps to the last index.
```
> ˼·
******- ʱ临Ӷ: O(n)*****- ռ临Ӷ: O(1)******
տʼ뵽ʹö̬滮ʱ临ӶΪO(n)TLEˣʵO(n)ʱ临Ӷɵġ飬ÿζߵnums[i]ķΧߵԶľ롣¼ans
```cpp
class Solution {
public:
int jump(vector& nums) {
int i = 0,length = nums.size(),next = nums[0],ans = 0;
if(length < 2)
return 0;
while(i < length)
{
++ans;
if(next >= length - 1)
return ans;
int current = i;
for(int j = current+1;j <= min(next,length - 1);++j)
{
i = max(i,nums[j] + j);
cout << i << " ";
}
swap(i,next);
cout << i << " "<< next << endl;
}
}
};
```
================================================
FILE: docs/leetcode/cpp/0046._Permutations.md
================================================
# 46. Permutations
**Ѷ:Medium**
## ˢ
> ԭ
* https://leetcode.com/problems/permutations/
>
```
Given a collection of distinct integers, return all possible permutations.
Example:
Input: [1,2,3]
Output:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
```
> ˼·1
******- ʱ临Ӷ: O(n!*n)******- ռ临Ӷ: O(n)******
ܲĿݹһ⣬ÿζһ֮ɡ
```cpp
class Solution {
public:
vector> permute(vector& nums) {
vector > ans;
if(!nums.size())
return ans;
if(nums.size() == 1)
ans.push_back(nums);
for(int i = 0;i < nums.size();++i)
{
swap(nums[0],nums[i]);
vector v(nums.begin() + 1,nums.end());
vector > ret = permute(v);
for(int i = 0;i < ret.size();++i)
{
ret[i].push_back(nums[0]);
ans.push_back(ret[i]);
}
swap(nums[0],nums[i]);
}
return ans;
}
};
```
> ˼·2
******- ʱ临Ӷ: O(n!)******- ռ临Ӷ: O(n)******
ǿԶ㷨ŻDFSķÿμ¼Ѿֽеݹ鼴
```cpp
class Solution {
public:
void DFS(int* visited,vector& nums,vector >& ans,vector temp)
{
int count1 = 0;
for(int i = 0;i < nums.size();++i)
if(!visited[i])
{
temp.push_back(nums[i]);
visited[i] = 1;
DFS(visited,nums,ans,temp);
temp.pop_back();
visited[i] = 0;
count1 = 1;
}
if(!count1)
ans.push_back(temp);
}
vector> permute(vector& nums) {
vector > ans;
int visited[nums.size()];
memset(visited,0,sizeof(visited));
vector temp;
for(int i = 0; i < nums.size();++i)
{
visited[i] = 1;
temp.push_back(nums[i]);
DFS(visited,nums,ans,temp);
temp.pop_back();
visited[i] = 0;
}
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0047._Permutations_II.md
================================================
# 47. Permutations II
**Ѷ:Medium**
## ˢ
> ԭ
* https://leetcode.com/problems/permutations-ii/
>
```
Given a collection of numbers that might contain duplicates, return all possible unique permutations.
Example:
Input: [1,1,2]
Output:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
```
> ˼·1
******- ʱ临Ӷ: O(n!*nlgn)******- ռ临Ӷ: O(n)******
ǰǵеƣԲο֮ǰĽ֮ⷨǰĿֱӾsetȥˣȻͨˣʱ临ӶȱȽϸߣҪŻ
```cpp
class Solution {
public:
void DFS(int* visited,vector& nums,set >& ans,vector temp)
{
int count1 = 0;
for(int i = 0;i < nums.size();++i)
if(!visited[i])
{
temp.push_back(nums[i]);
visited[i] = 1;
DFS(visited,nums,ans,temp);
temp.pop_back();
visited[i] = 0;
count1 = 1;
}
if(!count1)
ans.insert(temp);
}
vector> permuteUnique(vector& nums) {
vector > ans;
int visited[nums.size()];
memset(visited,0,sizeof(visited));
set > s;
vector temp;
for(int i = 0; i < nums.size();++i)
{
visited[i] = 1;
temp.push_back(nums[i]);
DFS(visited,nums,s,temp);
temp.pop_back();
visited[i] = 0;
}
for(auto pos = s.begin();pos != s.end();++pos)
ans.push_back(*pos);
return ans;
}
};
```
> ˼·2
******- ʱ临Ӷ: O(n!)******- ռ临Ӷ: O(n)******
֮ǰǵľ顣ҲͨDFSķȥ⣬и⣬ͬ־ͻظȶͬ־ͻһȻDFSʱǴҽеģ˵һ֮ǰȲ֮ǰѾˣôǾͲ
```cpp
class Solution {
public:
vector> permuteUnique(vector& nums) {
const int n = nums.size();
sort(nums.begin(), nums.end());
vector> ret;
vector visited(n, 0), arr;
dfs(nums, ret, arr, visited);
return ret;
}
void dfs(vector& nums, vector>& ret, vector& arr, vector& visited) {
if (arr.size() == nums.size()) {
ret.push_back(arr);
return;
}
for (int i = 0; i < nums.size(); ++i) {
if (visited[i]) {continue;}
if (i -1 >= 0 && nums[i] == nums[i-1] && !visited[i-1]) {continue;}
arr.push_back(nums[i]);
visited[i] = 1;
dfs(nums, ret, arr, visited);
arr.pop_back();
visited[i] = 0;
}
}
};
```
================================================
FILE: docs/leetcode/cpp/0048._Rotate_Image.md
================================================
# 49. Group Anagrams
**难度: Medium**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/rotate-image/submissions/
> 内容描述
```
给你一个矩阵,让你顺时针旋转90° 思路: 不讨论复制一个数组然后在旋转的方法,因为太简单了。 下面的方法都是in-place的:。
示例:
输入:
[
[1,2,3],
[4,5,6],
[7,8,9]
],
输出:
[
[7,4,1],
[8,5,2],
[9,6,3]
]
说明:
必须直接修改输入的2D矩阵。
不要分配另一个2D矩阵并进行旋转。
```
## 解题方案
> 思路 1
```
直接设置top, bottom, left, right四个变量,表示圈定当前要旋转的正方形范围,
然后按偏移计算位置,比如左上角的先和右上角交换,然后继续左上角和右下角交换这样即可.
```
```cpp
class Solution {
public:
void rotate(vector>& matrix) {
if(matrix.empty())
return;
int top = 0, bottom = matrix.size() - 1;
int left = 0, right = matrix[0].size() - 1;
for(;top < bottom && left < right; ++top, ++left, --bottom, --right){
for(int i = left; i < right; ++i){
int dis = i - left;
int row = top + dis;
int col = right;
swap(matrix[top][i], matrix[row][col]);
row = bottom;
col = right - dis;
swap(matrix[top][i], matrix[row][col]);
row = bottom - dis;
col = left;
swap(matrix[top][i], matrix[row][col]);
}
}
}
};
```
================================================
FILE: docs/leetcode/cpp/0049._Group_Anagrams.md
================================================
# 49. Group Anagrams
**难度: Medium**
## 刷题内容
> 原题连接
* https://leetcode-cn.com/problems/group-anagrams/submissions/
> 内容描述
```
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
说明:
所有输入均为小写字母。
不考虑答案输出的顺序。
```
## 解题方案
> 思路 1
```
不同的组别字符串元素相同,顺序不同,所以排序后相同
把排序后相同的元素映射到同一个vector
所有vector的组合就是结果
```
```cpp
vector> groupAnagrams(vector& strs) {
vector> ans;
map> maps;
for(int i=0;i难度:Medium**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/powx-n/
> 内容描述
```
mplement pow(x, n), which calculates x raised to the power n (xn).
Example 1:
Input: 2.00000, 10
Output: 1024.00000
Example 2:
Input: 2.10000, 3
Output: 9.26100
Example 3:
Input: 2.00000, -2
Output: 0.25000
Explanation: 2-2 = 1/22 = 1/4 = 0.25
Note:
-100.0 < x < 100.0
n is a 32-bit signed integer, within the range [?2^31, 2^31 ? 1]
```
> 思路1
******- 时间复杂度: O(lgN)******- 空间复杂度: O(1)******
求一个数的n次方是我们经常用的函数,一般刚开始可能会用暴力的方法去求,做了n次循环,但由于这里的n非常大,单纯的暴力会TLE,这里可以用分治的思想,比如``2*2*2*2``,我们前面已经计算过``2*2``了,那么后面就不用再计算依次,就相当于``2*2*(2*2)``,这样时间复杂度就变成了lgN,接下来只要主要幂次是负数的情况即可
```cpp
class Solution {
public:
double Pow(double x, long long n)
{
if(!n)
return 1;
if(n == 1)
return x;
double temp = Pow(x,(n)/ 2);
double ret;
if(n&1)
ret = temp * temp * x;
else
ret = temp * temp;
return ret;
}
double myPow(double x, int n) {
long long k = n;
if(n < 0)
x = 1 / x;
return Pow(x,n);
}
};
```
================================================
FILE: docs/leetcode/cpp/0051._N-Queens.md
================================================
# 51. N-Queens
**Ѷ:Hard**
## ˢ
> ԭ
* https://leetcode.com/problems/n-queens/
>
```
The n-queens puzzle is the problem of placing n queens on an nn chessboard such that no two queens attack each other.
Given an integer n, return all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.
Example:
Input: 4
Output: [
[".Q..", // Solution 1
"...Q",
"Q...",
"..Q."],
["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."]
]
Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above.
```
> ˼·1
******- ʱ临Ӷ: O(2^n)******- ռ临Ӷ: O(n)******
ûݷȥ⡣ʵľͼʵľͻˣֱ¼ֱбϷбϷǷлʺ
```cpp
class Solution {
public:
void travel(int* d,vector& ret,int level,int n,vector >& ans,int* l,int* r)
{
if(level >= n)
ans.push_back(ret);
for(int i = 0;i < n;++i)
if(!d[i] && !r[level + i] && !l[i - level + n])
{
d[i] = 1;
r[level + i] = 1;
l[i- level + n] = 1;
ret[level][i] = 'Q';
travel(d,ret,level + 1,n,ans,l,r);
d[i] = 0;
r[level + i] = 0;
l[i- level + n] = 0;
ret[level][i] = '.';
}
}
vector> solveNQueens(int n) {
int d[n];
int l[2 * n];
int r[2 * n];
memset(d,0,sizeof(d));
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
vector temp;
vector > ans;
string s(n,'.');
for(int i = 0;i < n;++i)
temp.push_back(s);
for(int i = 0;i < n;++i)
{
temp[0][i] ='Q';
d[i] = 1;
r[i] = 1;
l[i + n] = 1;
travel(d,temp,1,n,ans,l,r);
temp[0][i] = '.';
d[i] = 0;
r[i] = 0;
l[i + n] = 0;
}
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0052._N-Queens_II.md
================================================
# 52. N-Queens II
**Ѷ:Hard**
## ˢ
> ԭ
* https://leetcode.com/problems/n-queens-ii/
>
```
The n-queens puzzle is the problem of placing n queens on an nn chessboard such that no two queens attack each other.
Given an integer n, return the number of distinct solutions to the n-queens puzzle.
Example:
Input: 4
Output: 2
Explanation: There are two distinct solutions to the 4-queens puzzle as shown below.
[
[".Q..", // Solution 1
"...Q",
"Q...",
"..Q."],
["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."]
]
```
> ˼·1
******- ʱ临Ӷ: O(2^n)******- ռ临Ӷ: O(n)******
һһֻĶһ¾ͺãIJ˵
```cpp
class Solution {
public:
int travel(int* d,int level,int n,int* l,int* r)
{
if(level >= n)
return 1;
int ans = 0;
for(int i = 0;i < n;++i)
if(!d[i] && !r[level + i] && !l[i - level + n])
{
d[i] = 1;
r[level + i] = 1;
l[i- level + n] = 1;
ans += travel(d,level + 1,n,l,r);
d[i] = 0;
r[level + i] = 0;
l[i- level + n] = 0;
}
return ans;
}
int totalNQueens(int n) {
int d[n];
int l[2 * n];
int r[2 * n];
memset(d,0,sizeof(d));
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
int ans = 0;
for(int i = 0;i < n;++i)
{
d[i] = 1;
r[i] = 1;
l[i + n] = 1;
ans += travel(d,1,n,l,r);
d[i] = 0;
r[i] = 0;
l[i + n] = 0;
}
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0053._Maximum_Subarray.md
================================================
# 053. Maximum Subarray
**ѶEasy**
## ˢ
> ԭ
* https://leetcode.com/problems/maximum-subarray/
>
```
Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
Example:
Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
Follow up:
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
```
> ˼·1
******- ʱ临Ӷ: O(lgn)*****- ռ临Ӷ: O(1)******
ñķȥ⣬˶뵽ǿԶ㷨Ż÷η˼룬Ϊ飬ֵ[left,mid]䣬[mid + 1,right]ںmidڣֻҪȡֵɡ
```cpp
class Solution {
public:
int findArray(vector& nums,int beg,int en)
{
if(beg == en)
return nums[en];
int mid = (beg + en) / 2;
int temp = max(findArray(nums,beg,mid),findArray(nums,mid + 1,en));
int sum = 0,max1 = INT_MIN,max2 = INT_MIN;
for(int i = mid;i >= beg;--i)
{
sum += nums[i];
max1 = max(max1,sum);
}
sum = 0;
for(int i = mid + 1;i <= en;++i)
{
sum += nums[i];
max2 = max(max2,sum);
}
return max(temp,max1 + max2);
}
int maxSubArray(vector& nums) {
return findArray(nums,0,nums.size() - 1);
}
};
```
> ˼·2
******- ʱ临Ӷ: O(n)*****- ռ临Ӷ: O(1)******
ﻹO(n)ʱ临Ӷ⣬飬ret > 0,ret =nums[i]
ret += nums[i]
```cpp
class Solution {
public:
int maxSubArray(vector& nums) {
int length = nums.size(),ret = nums[0],ans = nums[0];
for(int i = 1;i < length;++i)
{
if(ret <= 0)
ret = nums[i];
else
ret += nums[i];
ans = max(ans,ret);
}
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0054._Spiral_Matrix.md
================================================
# 54. Spiral Matrix
**Ѷ:Medium**
## ˢ
> ԭ
* https://leetcode.com/problems/spiral-matrix/submissions/
>
```
Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.
Example 1:
Input:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
Output: [1,2,3,6,9,8,7,4,5]
Example 2:
Input:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
Output: [1,2,3,4,8,12,11,10,9,5,6,7]
```
> ˼·1
******- ʱ临Ӷ: O(n*m)******- ռ临Ӷ: O(1)******
飬ҵɾУûʲôѶ
```cpp
class Solution {
public:
vector spiralOrder(vector>& matrix) {
vector ans;
if(!matrix.size())
return ans;
int row = matrix[0].size(),colunm = matrix.size();
for(int i = 0;i < (matrix.size() + 1) / 2;++i)
{
if(row < 1 || colunm < 1)
break;
for(int j = 0;j < row;++j)
ans.push_back(matrix[i][i + j]);
if(colunm <= 1)
break;
for(int j = 1;j < colunm;++j)
ans.push_back(matrix[i + j][row + i - 1]);
if(row <= 1)
break;
for(int j = 1;j < row;++j)
ans.push_back(matrix[i + colunm - 1][row + i - 1 - j]);
for(int j = 1;j < colunm - 1;++j)
ans.push_back(matrix[i + colunm - 1 - j][i]);
row -= 2;
colunm -= 2;
}
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0055._Jump_Game.md
================================================
# 55. Jump Game
**Ѷ:Medium**
## ˢ
> ԭ
* https://leetcode.com/problems/jump-game/submissions/
>
```
Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Determine if you are able to reach the last index.
Example 1:
Input: [2,3,1,1,4]
Output: true
Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
Example 2:
Input: [3,2,1,0,4]
Output: false
Explanation: You will always arrive at index 3 no matter what. Its maximum
jump length is 0, which makes it impossible to reach the last index.
```
> ˼·
******- ʱ临Ӷ: O(N)******- ռ临Ӷ: O(1)******
տʼ뵽ľDPķDPĻʱ临ӶΪO(n^2)ȻǿԶ㷨Ż,ʱ临ӶO(n)ɡֻҪжÿһߵԶľ뼴ɣ[2,3,1,1,4]һֻߵ0ڶ[12]ԶľΪ4
```cpp
class Solution {
public:
bool canJump(vector& nums) {
if(nums.size() <= 1)
return 1;
for(int i = 0,r = 0;i < nums.size() - 1;)
{
int max1 = 0;
while(i <= r)
{
max1 = max(max1,i + nums[i]);
++i;
}
//cout << max1 << endl;
if(max1 >= nums.size() - 1)
return 1;
if(max1 <= r)
return 0;
r = max1;
}
}
};
```
================================================
FILE: docs/leetcode/cpp/0056._Merge_Intervals.md
================================================
# 56. Merge Intervals
**Ѷ:Medium**
## ˢ
> ԭ
* https://leetcode.com/problems/merge-intervals/
>
```
Given a collection of intervals, merge all overlapping intervals.
Example 1:
Input: [[1,3],[2,6],[8,10],[15,18]]
Output: [[1,6],[8,10],[15,18]]
Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].
Example 2:
Input: [[1,4],[4,5]]
Output: [[1,5]]
Explanation: Intervals [1,4] and [4,5] are considered overlapping.
```
> ˼·1
******- ʱ临Ӷ: O(nlgn)******- ռ临Ӷ: O(1)******
Ҫȶstartͱõ飬ཻͽ䶼ansཻͽϲIJans
```cpp
/**
* Definition for an interval.
* struct Interval {
* int start;
* int end;
* Interval() : start(0), end(0) {}
* Interval(int s, int e) : start(s), end(e) {}
* };
*/
class Solution {
public:
vector merge(vector& intervals) {
vector ans;
if(!intervals.size())
return ans;
sort(intervals.begin(),intervals.end(),[](Interval a, Interval b){return a.start < b.start;});
for(int i = 0;i < intervals.size() - 1;++i)
if(intervals[i + 1].start <= intervals[i].end)
{
intervals[i + 1].start = intervals[i].start;
intervals[i].end = max(intervals[i].end,intervals[i + 1].end);
intervals[i + 1].end = intervals[i].end;
}
else
ans.push_back(intervals[i]);
ans.push_back(intervals[intervals.size() - 1]);
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0057._Insert_Interval.md
================================================
# 57. Insert Interval
**Ѷ:Hard**
## ˢ
> ԭ
* https://leetcode.com/problems/insert-interval/
>
```
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).
You may assume that the intervals were initially sorted according to their start times.
Example 1:
Input: intervals = [[1,3],[6,9]], newInterval = [2,5]
Output: [[1,5],[6,9]]
Example 2:
Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
Output: [[1,2],[3,10],[12,16]]
Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10].
```
> ˼·
******- ʱ临Ӷ: O(N)******- ռ临Ӷ: O(N)******
ȼԭеλá飬αȽ䡣¼ l rֱҪӵյ㡣õλ֮ҵ intervals[i].end < l,ӽ飬[l,r] intervals[i].start > r䡣
```cpp
/**
* Definition for an interval.
* struct Interval {
* int start;
* int end;
* Interval() : start(0), end(0) {}
* Interval(int s, int e) : start(s), end(e) {}
* };
*/
class Solution {
public:
vector insert(vector& intervals, Interval newInterval) {
int beg = newInterval.start,en = newInterval.end,l = beg,r = en;
int comp = beg;
for(int i = 0;i < intervals.size();++i)
{
if(comp < intervals[i].start)
{
comp == beg ? l = beg : r = en;
comp = comp == beg ? en : beg;
if(comp == en && en < intervals[i].start)
{
r = en;
break;
}
if(comp == beg)
break;
}
if(comp <= intervals[i].end)
{
comp == beg ? l = intervals[i].start : r = intervals[i].end;
comp = comp == beg ? en : beg;
if(comp == en && en <= intervals[i].end)
{
r = intervals[i].end;
break;
}
if(comp == beg)
break;
}
}
int i = 0;
vector ans;
for(;i < intervals.size();++i)
if(intervals[i].end < l)
ans.push_back(intervals[i]);
else
break;
Interval i1(l,r);
ans.push_back(i1);
for(;i < intervals.size();++i)
if(intervals[i].start > r)
break;
for(;i < intervals.size();++i)
ans.push_back(intervals[i]);
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0058._Length_of_Last_Word.md
================================================
# 058. Length of Last Word
**难度Easy**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/length-of-last-word/
> 内容描述
```
Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the length of last word in the string.
If the last word does not exist, return 0.
```
> 思路
******- 时间复杂度: O(n)*****- 空间复杂度: O(1)******
这题我们只要从字符串的末尾开始向前找到第一个单词即可
```cpp
class Solution {
public:
int lengthOfLastWord(string s) {
int i = s.length() - 1,length = s.length() - 1;
while((s[i] == ' ') &&(i >= 0))
{
--i;
--length;
}
while((s[i] != ' ') && (i >= 0))
--i;
return length- i;
}
};
```
================================================
FILE: docs/leetcode/cpp/0059._Spiral_Matrix_II.md
================================================
# 59. Spiral Matrix II
**Ѷ:Medium**
## ˢ
> ԭ
* https://leetcode.com/problems/spiral-matrix-ii/
>
```
Given a positive integer n, generate a square matrix filled with elements from 1 to n2 in spiral order.
Example:
Input: 3
Output:
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
]
```
> ˼·1
******- ʱ临Ӷ: O(n^2)******- ռ临Ӷ: O(n^2)******
֮ǰתһķֻҪȷһ棬Ϊvector鲻ò
```cpp
class Solution {
public:
vector> generateMatrix(int n) {
int temp[n][n];
int range = n,cur = 1;
for(int i = 0;i < (n + 1) / 2 ;++i)
{
for(int j = 0;j < range;++j)
temp[i][j + i] = cur++;
for(int j = 1;j < range;++j)
temp[i + j][i + range - 1] = cur++;
for(int j = 1;j < range;++j)
temp[i + range - 1][range + i - 1 -j] = cur++;
for(int j = 1;j < range - 1;++j)
temp[range + i - 1 - j][i] = cur++;
range -= 2;
}
vector > ans;
for(int i = 0;i < n;++i)
{
vector v;
for(int j = 0;j < n;++j)
v.push_back(temp[i][j]);
ans.push_back(v);
}
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0060._Permutation_Sequence.md
================================================
# 60. Permutation Sequence
**Ѷ:Medium**
## ˢ
> ԭ
* https://leetcode.com/problems/permutation-sequence/
>
```
The set [1,2,3,...,n] contains a total of n! unique permutations.
By listing and labeling all of the permutations in order, we get the following sequence for n = 3:
"123"
"132"
"213"
"231"
"312"
"321"
Given n and k, return the kth permutation sequence.
Note:
Given n will be between 1 and 9 inclusive.
Given k will be between 1 and n! inclusive.
Example 1:
Input: n = 3, k = 3
Output: "213"
Example 2:
Input: n = 4, k = 9
Output: "2314"
```
> ˼·1
******- ʱ临Ӷ: O(n^2)******- ռ临Ӷ: O(n)******
Ƚ˳иַУȻѭnΣÿҵȷearseʱ临ӶΪnܵʱ临ӶΪn^2
```cpp
class Solution {
public:
string getPermutation(int n, int k){
int arr[n + 1];
string ans,org;
for(int i = 1;i <= n;++i)
{
org.push_back(i + '0');
i == 1 ? arr[i] = 1 : arr[i] = arr[i - 1] * i;
}
for(int i = n - 1;i > 0;--i)
{
int t = k / arr[i];
cout<< t<< endl;
k = (k) % arr[i];
if(!k)
{
k = arr[i];
t--;
}
ans.push_back(org[t]);
org.erase(org.begin() + t);
arr[i] = 0;
}
ans.push_back(org[0]);
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0061._Rotate_List.md
================================================
# 61. Rotate List
**Ѷ:Medium**
## ˢ
> ԭ
* https://leetcode.com/problems/rotate-list/
>
```
Given a linked list, rotate the list to the right by k places, where k is non-negative.
Example 1:
Input: 1->2->3->4->5->NULL, k = 2
Output: 4->5->1->2->3->NULL
Explanation:
rotate 1 steps to the right: 5->1->2->3->4->NULL
rotate 2 steps to the right: 4->5->1->2->3->NULL
Example 2:
Input: 0->1->2->NULL, k = 4
Output: 2->0->1->NULL
Explanation:
rotate 1 steps to the right: 2->0->1->NULL
rotate 2 steps to the right: 1->2->0->NULL
rotate 3 steps to the right: 0->1->2->NULL
rotate 4 steps to the right: 2->0->1->NULL
```
> ˼·1
******- ʱ临Ӷ: O(n)******- ռ临Ӷ: O(n)******
nָijȣknijȡ࣬Ϊkij֮һѭҪظ
```cpp
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
int len = 0;
ListNode* h = head;
ListNode* pre;
while(h)
{
++len;
pre = h;
h = h ->next;
}
if(!len)
return head;
int count1 = len - k % len;
if(count1 == len)
return head;
h = head;
ListNode* tail;
while(count1)
{
tail = h;
h = h ->next;
--count1;
}
pre ->next = head;
tail ->next = nullptr;
return h;
}
};
```
================================================
FILE: docs/leetcode/cpp/0062._Unique_Paths.md
================================================
# 62. Unique Paths
**难度: Medium**
## 刷题内容
> 原题连接
* https://leetcode-cn.com/problems/unique-paths/
> 内容描述
```
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
问总共有多少条不同的路径?
例如,上图是一个7 x 3 的网格。有多少可能的路径?
说明:m 和 n 的值均不超过 100。
示例 1:
输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右
示例 2:
输入: m = 7, n = 3
输出: 28
```
## 解题方案
> 思路 1
```
动态规划,走到(i,j)可以从(i-1,j),(i, j-1)两个方向
最优子结构:
dp[i, j] = dp[i-1, j]+dp[i, j-1]
```
```cpp
int uniquePaths(int m, int n) {
vector> dp(m, vector(n, 0));
for(int i=0;i难度:Medium**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/unique-paths-ii/
> 内容描述
```
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
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).
Now consider if some obstacles are added to the grids. How many unique paths would there be?
An obstacle and empty space is marked as 1 and 0 respectively in the grid.
Note: m and n will be at most 100.
Example 1:
Input:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
Output: 2
Explanation:
There is one obstacle in the middle of the 3x3 grid above.
There are two ways to reach the bottom-right corner:
1. Right -> Right -> Down -> Down
2. Down -> Down -> Right -> Right
```
> 思路1
******- 时间复杂度: O(n^2)******- 空间复杂度: O(n^2)******
运用动态规划的思想,写出状态转移方程,d(i,j) = d(i + 1,j) + d(i,j + 1),不过要注意边界值
```cpp
class Solution {
public:
int uniquePathsWithObstacles(vector>& obstacleGrid) {
int length1 = obstacleGrid.size(),length2 = obstacleGrid[0].size();
long long dp[length1][length2];
memset(dp,0,sizeof(dp));
for(int i = length1 - 1;i >= 0;--i)
for(int j = length2 - 1;j >= 0;--j)
{
if(!obstacleGrid[i][j])
{
if(i == length1 - 1 && j == length2 - 1)
dp[i][j] = 1;
else
{
if(i == length1 - 1)
dp[i][j] = dp[i][j + 1];
else if(j == length2 - 1)
dp[i][j] = dp[i + 1][j];
else
dp[i][j] = dp[i][j + 1] + dp[i + 1][j];
}
}
}
return dp[0][0];
}
};
```
================================================
FILE: docs/leetcode/cpp/0064._Minimum_Path_Sum.md
================================================
# 64. Minimum Path Sum
**难度: Middle**
## 刷题内容
> 原题连接
* https://leetcode-cn.com/problems/minimum-path-sum/
> 内容描述
```
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
```
## 解题方案
> 思路 1
```
dp:
1. 首行首列的路径只有一种,累加
2. 其他都有两种方法,走到i,j的最小路径等于min(sum[i][j-1], sum[i-1][j])+grid[i][j]
```
```cpp
int minPathSum(vector>& grid) {
int m = grid.size(), n = grid[0].size();
int dp[m][n];
dp[0][0] = grid[0][0];
for (int i = 1; i < m; ++i) dp[i][0] = grid[i][0] + dp[i - 1][0];
for (int i = 1; i < n; ++i) dp[0][i] = grid[0][i] + dp[0][i - 1];
for (int i = 1; i < m; ++i) {
for (int j = 1; j < n; ++j) {
dp[i][j] = grid[i][j] + min(dp[i - 1][j], dp[i][j - 1]);
}
}
return dp[m - 1][n - 1];
}
```
================================================
FILE: docs/leetcode/cpp/0065._Valid_Number.md
================================================
# 65. Valid Number
**Ѷ:Hard**
## ˢ
> ԭ
* https://leetcode.com/problems/valid-number/
>
```
Validate if a given string can be interpreted as a decimal number.
Some examples:
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true
" -90e3 " => true
" 1e" => false
"e3" => false
" 6e-1" => true
" 99e2.5 " => false
"53.5e93" => true
" --6 " => false
"-+3" => false
"95a54e53" => false
Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one. However, here is a list of characters that can be in a valid decimal number:
Numbers 0-9
Exponent - "e"
Positive/negative sign - "+"/"-"
Decimal point - "."
Of course, the context of these characters also matters in the input.
```
> ˼·
******- ʱ临Ӷ: O(N)******- ռ临Ӷ: O(1)******
õģĿʵҪַҪɣҪеǽȥnumberǰɸո.1"1.ںϷ֡
```cpp
class Solution {
public:
void blank(int& i,string& s)
{
while(i < s.length() && s[i] == ' ')
i++;
}
bool firstHalf(int& i,string& s)
{
int num = 0;
for(;i < s.length();++i)
if(isdigit(s[i]))
continue;
else if(s[i] == '.')
{
if(num)
return 0;
num++;
}
else if(s[i] == 'e' || s[i] == ' ')
return 1;
else
return 0;
return 1;
}
bool secondHalf(int& i,string& s)
{
if(i == s.length())
return 0;
if(s[i] =='-' || s[i] == '+')
++i;
if(!isdigit(s[i]))
return 0;
for(;i < s.length();++i)
if(!isdigit(s[i]))
{
if(s[i] == ' ')
return 1;
return 0;
}
return 1;
}
bool isNumber(string s) {
int i = 0;
if(!s.length())
return 0;
blank(i,s);
if(i == s.length())
return 0;
if(s[i] == '-' || s[i] == '+')
++i;
int temp = i;
if(!firstHalf(i,s))
return 0;
if(i == temp)
return 0;
if(i - 1 == temp && s[i - 1] == '.')
return 0;
if(i == s.length())
return 1;
if(s[i] == 'e')
{
i++;
if(!secondHalf(i,s))
return 0;
}
blank(i,s);
return i == s.length();
}
};
```
================================================
FILE: docs/leetcode/cpp/0066._Plus_One.md
================================================
# 66. Plus One
**Ѷ:Easy**
## ˢ
> ԭ
* https://leetcode.com/problems/plus-one/
>
```
Given a non-empty array of digits representing a non-negative integer, plus one to the integer.
The digits are stored such that the most significant digit is at the head of the list, and each element in the array contain a single digit.
You may assume the integer does not contain any leading zero, except the number 0 itself.
Example 1:
Input: [1,2,3]
Output: [1,2,4]
Explanation: The array represents the integer 123.
Example 2:
Input: [4,3,2,1]
Output: [4,3,2,2]
Explanation: The array represents the integer 4321.
```
> ˼·1
******- ʱ临Ӷ: O(n)******- ռ临Ӷ: O(1)******
ַתּɣҪעпܻһ
```cpp
class Solution {
public:
vector plusOne(vector& digits) {
int i = digits.size() - 1;
while((i >= 0) && (digits[i] == 9))
{
digits[i] = 0;
--i;
}
if(i < 0)
digits.insert(digits.begin(),1);
else
++digits[i];
return digits;
}
};
```
================================================
FILE: docs/leetcode/cpp/0068._Text_Justification.md
================================================
# 68. Text Justification
**Ѷ:Hard**
## ˢ
> ԭ
* https://leetcode.com/problems/text-justification/
>
```
Given an array of words and a width maxWidth, format the text such that each line has exactly maxWidth characters and is fully (left and right) justified.
You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pad extra spaces ' ' when necessary so that each line has exactly maxWidth characters.
Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line do not divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right.
For the last line of text, it should be left justified and no extra space is inserted between words.
Note:
A word is defined as a character sequence consisting of non-space characters only.
Each word's length is guaranteed to be greater than 0 and not exceed maxWidth.
The input array words contains at least one word.
Example 1:
Input:
words = ["This", "is", "an", "example", "of", "text", "justification."]
maxWidth = 16
Output:
[
"This is an",
"example of text",
"justification. "
]
Example 2:
Input:
words = ["What","must","be","acknowledgment","shall","be"]
maxWidth = 16
Output:
[
"What must be",
"acknowledgment ",
"shall be "
]
Explanation: Note that the last line is "shall be " instead of "shall be",
because the last line must be left-justified instead of fully-justified.
Note that the second line is also left-justified becase it contains only one word.
Example 3:
Input:
words = ["Science","is","what","we","understand","well","enough","to","explain",
"to","a","computer.","Art","is","everything","else","we","do"]
maxWidth = 20
Output:
[
"Science is what we",
"understand well",
"enough to explain to",
"a computer. Art is",
"everything else we",
"do "
]
```
> ˼·
******- ʱ临Ӷ: O(n)******- ռ临Ӷ: O(n)******
ĿѣĿ˼ȼһɶٵʣÿ֮һոָͿԼÿɶٵʡÿеȷʽܹĿոԼܿոԼΪ0Ϊ֮Ŀո r Ϊ0ͷʼ r ո1ʣµIJ䡣һҪעÿ֮ĿոΪ1ַmaxWidthʣµÿո䡣
```cpp
class Solution {
public:
vector fullJustify(vector& words, int maxWidth) {
int l = 0,r = 0,sum = 0;
vector ans;
for(int i = 0;i < words.size();++i)
{
sum += words[i].length();
if(sum <= maxWidth)
{
sum += 1;
r++;
}
else
{
string temp;
sum -= (r - l + words[i].length());
int residue = 0, divide = (maxWidth - words[l].length());
if(l + 1 != r)
{
residue = (maxWidth - sum) % (r - l - 1);
divide = (maxWidth - sum - residue) / (r - l - 1);
}
temp.append(words[l].begin(),words[l].end());
for(int j = l + 1;j < r - 1;++j)
{
int k = residue > 0 ? divide + 1 : divide;
while(k)
{
temp.push_back(' ');
--k;
}
temp.append(words[j].begin(),words[j].end());
residue--;
}
int k = residue > 0 ? divide +1 : divide;
while(k)
{
temp.push_back(' ');
--k;
}
if(l + 1 != r)
temp.append(words[r - 1].begin(),words[r - 1].end());
ans.push_back(temp);
l = r++;
sum = words[i].length() + 1;
}
}
sum -= 1;
string temp;
temp.append(words[l].begin(),words[l].end());
for(int i = l + 1;i < r;++i)
{
temp.push_back(' ');
temp.append(words[i].begin(),words[i].end());
}
int k = maxWidth - sum;
while(k)
{
temp.push_back(' ');
--k;
}
ans.push_back(temp);
return ans;
}
};
```
================================================
FILE: docs/leetcode/cpp/0069._Sqr(x).md
================================================
# 69. Sqrt(x)
**Ѷ:Easy**
## ˢ
> ԭ
* https://leetcode.com/problems/sqrtx/
>
```
Implement int sqrt(int x).
Compute and return the square root of x, where x is guaranteed to be a non-negative integer.
Since the return type is an integer, the decimal digits are truncated and only the integer part of the result is returned.
Example 1:
Input: 4
Output: 2
Example 2:
Input: 8
Output: 2
Explanation: The square root of 8 is 2.82842..., and since
the decimal part is truncated, 2 is returned.
```
> ˼·1
******- ʱ临Ӷ: O(n)******- ռ临Ӷ: O(1)******
0xЩƽֱx
```cpp
class Solution {
public:
int mySqrt(int x) {
int i = 0;
if(!x || x == 1)
return x;
for(;i < x;++i)
if((long long)i * i > x)
break;
return i - 1;
}
};
```
> ˼·2
******- ʱ临Ӷ: O(lgn)******- ռ临Ӷ: O(1)******
ԣҿԽһŻöַ0Ϊ½磬xΪϽ磬ͿԽж
```cpp
class Solution {
public:
int mySqrt(int x) {
int l = 0, r= x;
while(l < r)
{
long long mid = (l + r) / 2,temp = mid * mid;
if(temp == x)
return mid;
if(temp < x)
l = mid + 1;
else
r = mid - 1;
}
return l * l <= x ? l : l - 1;
}
};
```
================================================
FILE: docs/leetcode/cpp/0072._Edit_Distance.md
================================================
# 72. Edit Distance
**难度Hard**
## 刷题内容
> 原题连接
* https://leetcode.com/problems/edit-distance/
> 内容描述
```
You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.
Example 1:
Input:
s = "barfoothefoobarman",
words = ["foo","bar"]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are "barfoor" and "foobar" respectively.
The output order does not matter, returning [9,0] is fine too.
Example 2:
Input:
s = "wordgoodstudentgoodword",
words = ["word","student"]
Output: []
```
> 思路
******- 时间复杂度: O(n^2)******- 空间复杂度: O(n^2)******
这题可以动态规划的思想去解决,首先定义两个指针 i 和 j,分别指向字符串的末尾。从两个字符串的末尾开始比较,相等,则```--i,--j```。若不相等,有三种情况,删除 i 指向的字符,在 i 指向的字符之后增加一个字符,替换 i 指向的字符, 接着比较这三次的操作的次数,取最小值即可,不过这里要注意递归操作时会重复计算,所以我们用一个数组 dp[i][j],表示 i 在words1中的位置,j 在 words2 的位置。由于c++对动态数组的支持不是很好,这里我用 vector 代替,在效率上可能较欠缺。
```cpp
class Solution {
public:
vector > dp;
int minLen(string& w1,string& w2,int i,int j)
{
if(i < 0)
return j + 1;
if(j < 0)
return i + 1;
if(dp[i][j])
return dp[i][j];
if(w1[i] == w2[j])
{
dp[i][j] = minLen(w1,w2,i - 1,j - 1);
return dp[i][j];
}
int temp1 = min(minLen(w1,w2,i - 1,j) + 1,minLen(w1,w2,i - 1,j - 1) + 1);
dp[i][j] = min(minLen(w1,w2,i,j - 1) + 1,temp1);
return dp[i][j];
}
int minDistance(string word1, string word2) {
int i = word1.length() - 1,j = word2.length() - 1;
for(int t1 = 0;t1 <= i;++t1)
{
vector