├── array ├── 118_pascals_triangle.go ├── 119_pascals_triangle_ii.go ├── 11_container_with_most_water.go ├── 120_triangle.go ├── 121_best_time_to_buy_and_sell_stock.go ├── 122_best_time_to_buy_and_sell_stock_ii.go ├── 153_find_minimum_in_rotated_sorted_array.go ├── 15_3sum.go ├── 162_find_peak_element.go ├── 167_two_sum_ii_input_array_is_sorted.go ├── 169_majority_element.go ├── 16_3sum_closest.go ├── 189_rotate_array.go ├── 18_4sum.go ├── 1_two_sum.go ├── 216_combination_sum_iii.go ├── 217_contains_duplicate.go ├── 219_contains_duplicate_ii.go ├── 228_summary_ranges.go ├── 238_product_of_array_except_self.go ├── 268_missing_number.go ├── 26_remove_duplicates_from_sorted_array.go ├── 27_remove_element.go ├── 283_move_zeroes.go ├── 287_find_the_duplicate_number.go ├── 289_game_of_life.go ├── 31_next_permutation.go ├── 33_search_in_rotated_sorted_array.go ├── 34_find_first_and_last_position_of_element_in_sorted_array.go ├── 35_search_insert_position.go ├── 39_combination_sum.go ├── 41_first_missing_positive.go ├── 42_trapping_rain_water.go ├── 442_find_all_duplicates_in_an_array.go ├── 448_find_all_numbers_disappeared_in_an_array.go ├── 485_max-consecutive_ones.go ├── 48_rotate_image.go ├── 495_teemo_attacking.go ├── 4_median_of_two_sorted_arrays.go ├── 532_k_diff_pairs_in_an_array.go ├── 53_maximum_subarray.go ├── 54_spiral_matrix.go ├── 55_jump_game.go ├── 561_array_partition_i.go ├── 566_reshape_the_matrix.go ├── 581_shortest_unsorted_continuous_subarray.go ├── 59_spiral_matrix_ii.go ├── 605_can_place_flowers.go ├── 611_valid_triangle_number.go ├── 621_task_scheduler.go ├── 628_maximum_product_of_three_numbers.go ├── 62_unique_paths.go ├── 643_maximum_average_subarray_i.go ├── 64_minimum_path_sum.go ├── 661_image_smoother.go ├── 665_non_decreasing_array.go ├── 66_plus_one.go ├── 674__longest_continuous_increasing_subsequence.go ├── 697_degree_of_an_array.go ├── 718_maximum_length_of_repeated_subarray.go ├── 724_find_pivot_index.go ├── 73_set_matrix_zeroes.go ├── 747_largest_number_at_least_twice_of_others.go ├── 766_toeplitz_matrix.go ├── 769_max_chunks_to_make_sorted.go ├── 76_sort_colors.go ├── 78_subsets.go ├── 830_positions_of_large_groups.go ├── 835_image_overlap.go ├── 840_magic_squares_in_grid.go ├── 849_maximize_distance_to_closest_person.go ├── 867_transpose_matrix.go ├── 888_fair_candy_swap.go ├── 88_merge_sorted_array.go ├── 896_monotonic_array.go ├── 905_sort_array_by_parit.go ├── 914_x_of_a_kind_in_a_deck_of_cards.go ├── 915_partition_array_into_disjoint_intervals.go └── utils.go ├── design ├── lfu_cache.go └── lru_cache.go ├── dp ├── 343_integer_break.go ├── 70_climbing_stairs.go └── utils.go ├── heap ├── 215_kth_largest_element_in_an_array.go ├── 347_top_k_frequent_elements.go ├── 451_sort_characters_by_frequency.go ├── 703_kth_largest_element_in_a_stream.go ├── heap_test.go ├── max_heap.go └── min_heap.go ├── linked_list ├── 141_linked_list_cycle.go ├── 19_remove_nth_node_from_end_of_list.go ├── 203_remove_linked_list_elements.go ├── 206_reverse_linked_list.go ├── 21_merge_two_sorted_lists.go ├── 234_palindrome_linked_list.go ├── 237_delete_node_in_a_linked_list.go ├── 24_swap_nodes_in_pairs.go ├── 2_add_two_numbers.go ├── 328_odd_even_linked_list.go ├── 61_rotate_list.go ├── 725_intersection_of_two_linked_lists.go ├── 817_linked_list_components.go ├── 82_remove_duplicates_from_sorted_list_ii.go ├── 83_remove_duplicates_from_sorted_list.go ├── 86_partition_list.go ├── 876_middle_of_the_linked_list.go ├── 92_reverse_linked_list_ii.go └── init.go ├── map └── 864_hand_of_straights.go ├── sql ├── 175_combine_two_tables.sql ├── 176_second_highest_salary.sql └── 178_rank_scores.sql ├── stack ├── 150_evaluate_reverse_polish_notation.go ├── 155_min_stack.go ├── 225_implement_stack_using_queues.go ├── 232_implement_queue_using_stacks.go ├── 394_decode_string.go ├── 496_next_greater_element_i.go ├── 682_baseball_game.go ├── 71_simplify_path.go ├── 739_daily_temperatures.go ├── 844_backspace_string_compare.go ├── 856_score_of_parentheses.go ├── stack.go └── str_stack.go ├── string ├── 125_valid_palindrome.go ├── 12_integer_to_roman.go ├── 13_roman_to_integer.go ├── 14_longest_common_prefix.go ├── 20_valid_parentheses.go ├── 28_implement_strstr.go ├── 344_reverse_string.go ├── 345_reverse_vowels_of_a_string.go ├── 383_ransom_note.go ├── 387_first_unique_character_in_a_string.go ├── 38_count_and_say.go ├── 434_number_of_segments_in_a_string.go ├── 520_detect_capital.go ├── 521_longest_uncommon_subsequence_i.go ├── 541_reverse_string_ii.go ├── 551_student_attendance_record_i.go ├── 557_reverse_words_in_a_string_iii.go ├── 58_length_of_last_word.go ├── 5_longest_palindromic_substring.go ├── 657_robot_return_to_origin.go ├── 67_add_binary.go ├── 686_repeated_string_match.go ├── 696_count_binary_substrings.go ├── 6_zigzag_conversion.go ├── 709_to_lower_case.go ├── 788_rotated_digits.go ├── 819_most_common_word.go ├── 824_goat_latin.go ├── 859_buddy_strings.go ├── 893_groups_of_special_equivalent_strings.go └── 8_string_to_integer_atoi.go ├── tree ├── 100_same_tree.go ├── 101_symmetric_tree.go ├── 102_binary_tree_level_order_traversal.go ├── 104_maximum_depth_of_binary_tree.go ├── 105_construct_binary_tree_from_preorder_and_inorder_traversal.go ├── 106_construct_binary_tree_from_inorder_and_postorder_traversal.go ├── 107_binary_tree_level_order_traversal_ii.go ├── 108_convert_sorted_array_to_binary_search_tree.go ├── 110_balanced_binary_tree.go ├── 111_minimum_depth_of_binary_tree.go ├── 112_path_sum.go ├── 113_path_sum_ii.go ├── 114_flatten_binary_tree_to_linked_list.go ├── 124_binary_tree_maximum_path_sum.go ├── 129_sum_root_to_leaf_numbers.go ├── 144_binary_tree_preorder_traversal.go ├── 145_binary_tree_postorder_traversal.go ├── 199_binary_tree_right_side_view.go ├── 222_count_complete_tree_nodes.go ├── 226_invert_binary_tree.go ├── 230_kth_smallest_element_in_a_bst.go ├── 257_binary_tree_paths.go ├── 404_sum_of_left_leaves.go ├── 450_delete_node_in_a_bst.go ├── 501_find_mode_in_binary_search_tree.go ├── 513_find_bottom_left_tree_value.go ├── 515_find_largest_value_in_each_tree_row.go ├── 538_convert_bst_to_greater_tree.go ├── 543_diameter_of_binary_tree.go ├── 563_binary_tree_tilt.go ├── 572_subtree_of_another_tree.go ├── 606_construct_string_from_binary_tree.go ├── 617_merge_two_binary_trees.go ├── 623_add_one_row_to_tree.go ├── 637_average_of_levels_in_binary_tree.go ├── 652_find_duplicate_subtrees.go ├── 653_two_sum_iv_input_is_a_bst.go ├── 654_maximum_binary_tree.go ├── 662_maximum_width_of_binary_tree.go ├── 669_trim_a_binary_search_tree.go ├── 671_second_minimum_node_in_a_binary_tree.go ├── 700_search_in_a_binary_search_tree.go ├── 701_insert_into_a_binary_search_tree.go ├── 814_binary_tree_pruning.go ├── 872_leaf_similar_trees.go ├── 897_increasing_order_search_tree.go ├── 94_binary_tree_inorder_traversal.go ├── 951_flip_equivalent_binary_trees.go ├── 95_unique_binary_search_trees_ii.go ├── 96_unique_binary_search_trees.go ├── 98_validate_binary_search_tree.go └── tree.go └── trie └── 208_implement_trie_prefix_tree.go /array/118_pascals_triangle.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(generate(0)) 7 | } 8 | 9 | // 观察规律即可 10 | func generate(numRows int) [][]int { 11 | var arrs [][]int 12 | for i := 0; i < numRows; i++ { 13 | arr := make([]int, i+1) 14 | arr[0], arr[i] = 1, 1 15 | for j := 1; j < i; j++ { 16 | arr[j] = arrs[i-1][j-1] + arrs[i-1][j] 17 | } 18 | arrs = append(arrs, arr) 19 | } 20 | return arrs 21 | } 22 | -------------------------------------------------------------------------------- /array/119_pascals_triangle_ii.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(getRow(33)) 7 | } 8 | 9 | func getRow(rowIndex int) []int { 10 | arrs := getTriangle(34) 11 | return arrs[rowIndex] 12 | } 13 | 14 | func getTriangle(numRows int) [][]int { 15 | var arrs [][]int 16 | for i := 0; i < numRows; i++ { 17 | arr := make([]int, i+1) 18 | arr[0], arr[i] = 1, 1 19 | for j := 1; j < i; j++ { 20 | arr[j] = arrs[i-1][j-1] + arrs[i-1][j] 21 | } 22 | arrs = append(arrs, arr) 23 | } 24 | return arrs 25 | } 26 | -------------------------------------------------------------------------------- /array/11_container_with_most_water.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(maxArea1([]int{1, 8, 6, 2, 5, 4, 8, 3, 7})) // 49 7 | fmt.Println(maxArea2([]int{1, 8, 6, 2, 5, 4, 8, 3, 7})) // 49 8 | } 9 | 10 | // 11 | // 暴力遍历 12 | // 13 | func maxArea1(height []int) int { 14 | n := len(height) 15 | if n <= 1 { 16 | return 0 17 | } 18 | maxMulti := 0 19 | for i := 0; i < n-1; i++ { 20 | for j := i + 1; j < n; j++ { 21 | w := j - i // 宽 22 | h := min(height[i], height[j]) // 高 23 | maxMulti = max(maxMulti, w*h) // 比较面积 24 | } 25 | } 26 | return maxMulti 27 | } 28 | 29 | // 30 | // 优化1:双指针法 31 | // 两条线段之间的面积受限与最短的线段,线段间距越长,面积越大 32 | // 使用 2 个指针指向首部和尾部,将短指针向长指针方向移动,看能不能找到更长的线,使面积更大 33 | // 依据:向长线方向每次移动 1 格,虽然宽度-1,但是(高度变高)*(宽度-1) >= 高度*宽度 34 | // 35 | func maxArea2(height []int) int { 36 | maxMulti := 0 37 | left, right := 0, len(height)-1 38 | for left < right { 39 | w := right - left 40 | h := min(height[left], height[right]) 41 | maxMulti = max(maxMulti, w*h) 42 | if height[left] <= height[right] { 43 | left++ // 往右边走找更长的线 44 | } else { 45 | right-- // 往左边走 46 | } 47 | } 48 | return maxMulti 49 | } 50 | -------------------------------------------------------------------------------- /array/120_triangle.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | triangle := [][]int{ 7 | {2}, 8 | {3, 4}, 9 | {6, 5, 7}, 10 | {4, 1, 8, 3}, 11 | 12 | // {-1}, 13 | // {2, 3}, 14 | // {1, -1, -1}, 15 | } 16 | fmt.Println(minimumTotal(triangle)) // 2 3 5 1 17 | } 18 | 19 | // 和 64 题最小路径和很像,都是用简单的动态规划实现 20 | func minimumTotal(triangle [][]int) int { 21 | r := len(triangle) 22 | if r <= 0 { 23 | return 0 24 | } 25 | 26 | // 向下构建 27 | steps := make([][]int, r) 28 | for i := range triangle { 29 | steps[i] = make([]int, i+1) 30 | } 31 | copy(steps, triangle) 32 | 33 | for i := 1; i < r; i++ { 34 | for j := 0; j <= i; j++ { // 第 N 行有 N 个元素 35 | steps[i][j] += min(steps[i-1], j) 36 | } 37 | } 38 | 39 | minStep := steps[r-1][0] 40 | for _, step := range steps[r-1] { 41 | if minStep > step { 42 | minStep = step 43 | } 44 | } 45 | return minStep 46 | } 47 | 48 | // 获取某行指定位置及其左右的最小值 49 | func min(nums []int, c int) (minNum int) { 50 | n := len(nums) 51 | l, mid := c-1, c 52 | 53 | inited := false 54 | if 0 <= l && l <= n-1 { 55 | inited = true 56 | minNum = nums[l] 57 | } 58 | if 0 <= mid && mid <= n-1 { 59 | if inited { 60 | if minNum > nums[mid] { 61 | minNum = nums[mid] 62 | } 63 | } else { 64 | inited = true 65 | minNum = nums[mid] 66 | } 67 | } 68 | return 69 | } 70 | -------------------------------------------------------------------------------- /array/121_best_time_to_buy_and_sell_stock.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(maxProfit([]int{7, 1, 5, 3, 6, 4})) 7 | fmt.Println(maxProfit([]int{7, 6, 4, 3, 1})) 8 | fmt.Println(maxProfit([]int{1,2})) 9 | } 10 | 11 | // 简单的规律 12 | func maxProfit(prices []int) int { 13 | n := len(prices) 14 | max := 0 15 | for i := 0; i < n; i++ { 16 | for j := i + 1; j < n; j++ { 17 | if prices[j]-prices[i] > max { 18 | max = prices[j] - prices[i] 19 | } 20 | } 21 | } 22 | return max 23 | } 24 | -------------------------------------------------------------------------------- /array/122_best_time_to_buy_and_sell_stock_ii.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(maxProfit1([]int{1, 2, 3, 4, 5})) 7 | fmt.Println(maxProfit1([]int{7, 1, 5, 3, 6, 4})) 8 | } 9 | 10 | func maxProfit1(prices []int) int { 11 | i, max := 0, 0 12 | n := len(prices) 13 | for i < n-1 { 14 | buy := i 15 | for i < n-1 && prices[i] < prices[i+1] { 16 | i++ 17 | } 18 | max += prices[i] - prices[buy] // 在最高点抛售 19 | i++ 20 | } 21 | return max 22 | } 23 | -------------------------------------------------------------------------------- /array/153_find_minimum_in_rotated_sorted_array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | // 在数组中查找原本 3 该在的位置,即是发生旋转的值(最小值) 7 | fmt.Println(findMin([]int{3, 4, 5, 1, 2})) 8 | } 9 | 10 | // 排序就能直接搞定,不过扩展的二分思路更有技巧 11 | // 对二分查找顺序、查找完毕时的 l, r 变量的理解一定要深刻 12 | func findMin(nums []int) int { 13 | n := len(nums) 14 | if n <= 1 { 15 | return nums[0] 16 | } 17 | 18 | // 若在最后一个元素上旋转,数组依旧有序 19 | if nums[n-1] > nums[0] { 20 | return nums[0] 21 | } 22 | 23 | target := nums[0] 24 | l, r := 0, n-1 25 | for l < r { 26 | mid := (l + r) / 2 27 | // 不断在无序区找最小值 28 | switch { 29 | case nums[mid] >= target: // 中间值比目标大,前半部分有序,继续在后部分无序区找最小值 30 | l = mid + 1 31 | case nums[mid] < target: // 中间值比目标小,前半部分无序 32 | r = mid 33 | } 34 | } 35 | return nums[r] 36 | } 37 | -------------------------------------------------------------------------------- /array/15_3sum.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(threeSum([]int{-1, 0, 1, 2, -1, -4})) // [[-1 -1 2] [-1 0 1]] 10 | fmt.Println(badTwoSum([]int{-1, 0, 1, 2, -1, -4})) // [[-1 -1 2] [-1 0 1]] 11 | fmt.Println(threeSum([]int{-2, 0, 0, 2, 2})) // [[-2 0 2]] 12 | } 13 | 14 | // 处理结果与元素原顺序无关,可排序预处理,方便去重 15 | // 使用双指针遍历后部分剩余数组 16 | func threeSum(nums []int) [][]int { 17 | sort.Ints(nums) // [-4 -1 -1 0 1 2] // 预排序有 2 个好处:去重 & 指导双指针的下一步方向 18 | n := len(nums) 19 | var res [][]int 20 | for i, num := range nums { 21 | if num > 0 { 22 | break // 优化,再往后三个正数和不可能为 0 23 | } 24 | 25 | // 第一层遍历数向前去重 26 | if i > 0 && nums[i] == nums[i-1] { // 因为双指针从 i 之后取,不能使用 nums[i] == nums[i+1] 向后去重 27 | continue 28 | } 29 | 30 | l, r := i+1, n-1 31 | for l < r { 32 | sum := num + nums[l] + nums[r] 33 | switch { 34 | case sum > 0: 35 | r-- 36 | case sum < 0: 37 | l++ 38 | default: 39 | res = append(res, []int{num, nums[l], nums[r]}) 40 | // 第二层候选数向后去重 41 | for l < r && nums[l] == nums[l+1] { 42 | l++ 43 | } 44 | for r > l && nums[r] == nums[r-1] { 45 | r-- 46 | } 47 | l++ 48 | r-- 49 | } 50 | } 51 | } 52 | return res 53 | } 54 | 55 | // twoSum 的思路,不好 56 | func badTwoSum(nums []int) [][]int { 57 | // 避开全是 0 的 case // ugly 58 | if len(nums) >= 3 { 59 | allZero := true 60 | for _, num := range nums { 61 | if num != 0 { 62 | allZero = false 63 | } 64 | } 65 | if allZero { 66 | return [][]int{{0, 0, 0}} 67 | } 68 | } 69 | 70 | n := len(nums) 71 | num2index := make(map[int]int, n) 72 | for i, num := range nums { 73 | num2index[num] = i 74 | } 75 | 76 | // 获取三元组 77 | var res [][]int 78 | for i := 0; i < n; i++ { 79 | for j := i + 1; j < n; j++ { 80 | remain := 0 - (nums[i] + nums[j]) 81 | if k, ok := num2index[remain]; ok && j != k && i != k { 82 | res = append(res, []int{nums[i], nums[j], remain}) 83 | } 84 | } 85 | } 86 | 87 | // 剔除重复的三元组 88 | m := make(map[string][]int) 89 | for i := range res { 90 | sort.Ints(res[i]) 91 | m[intStr(res[i])] = res[i] 92 | } 93 | 94 | var arrs [][]int 95 | for _, arr := range m { 96 | arrs = append(arrs, arr) 97 | } 98 | return arrs 99 | } 100 | 101 | // trick // 使得整数数组能做 map 的 key 102 | func intStr(nums []int) string { 103 | str := "" 104 | for _, num := range nums { 105 | str += fmt.Sprintf("%d_", num) 106 | } 107 | return str 108 | } 109 | -------------------------------------------------------------------------------- /array/162_find_peak_element.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(findPeakElement([]int{3, 4, 3, 2, 1})) // 1 7 | fmt.Println(findPeakElement([]int{1, 2, 1, 3, 5, 6, 4})) // 5 / 1 8 | } 9 | 10 | // 二分查找的变种 11 | func findPeakElement(nums []int) int { 12 | return findPeak(nums, 0, len(nums)) 13 | } 14 | 15 | func findPeak(nums []int, l, r int) int { 16 | mid := (l + r) / 2 17 | 18 | inLeft, inRight := false, false 19 | if mid > 0 && nums[mid-1] > nums[mid] { // 峰值在左侧 20 | inLeft = true 21 | } 22 | if mid < len(nums)-1 && nums[mid] < nums[mid+1] { // 在右侧 23 | inRight = true 24 | } 25 | 26 | switch { 27 | case inLeft: 28 | return findPeak(nums, l, mid-1) 29 | case inRight: 30 | return findPeak(nums, mid+1, r) 31 | default: 32 | return mid 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /array/167_two_sum_ii_input_array_is_sorted.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(twoSum([]int{}, 10)) 7 | } 8 | 9 | // 遍历就完事儿了 10 | func twoSum(numbers []int, target int) []int { 11 | head, tail := 0, len(numbers)-1 12 | for head <= tail { 13 | switch { 14 | case numbers[head]+numbers[tail] < target: 15 | head++ 16 | case numbers[head]+numbers[tail] > target: 17 | tail-- 18 | default: 19 | return []int{head + 1, tail + 1} 20 | } 21 | } 22 | return nil 23 | } 24 | -------------------------------------------------------------------------------- /array/169_majority_element.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(majorityElement([]int{6, 5, 5})) 7 | // fmt.Println(majorityElement([]int{3, 2, 3})) 8 | // fmt.Println(majorityElement([]int{2, 2, 1, 1, 1, 2, 2})) 9 | } 10 | 11 | func majorityElement(nums []int) int { 12 | m := make(map[int]int) 13 | for _, num := range nums { 14 | m[num]++ 15 | } 16 | major := len(nums) / 2 17 | for num, times := range m { // map 的 range 顺序不定 ok ? 18 | if times > major { 19 | return num 20 | } 21 | } 22 | return 0 23 | } 24 | -------------------------------------------------------------------------------- /array/16_3sum_closest.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(threeSumClosest1([]int{-1, 2, 1, -4}, 1)) // 2 10 | fmt.Println(threeSumClosest([]int{0, 2, 1, -3}, 1)) // 0 11 | fmt.Println(threeSumClosest([]int{1, 2, 4, 8, 16, 32, 64, 128}, 84)) // 84 12 | } 13 | 14 | // 同样也是指针法 15 | // 和 15 一样,排序预处理能知道双指针移动的方向,记录最小 abs 16 | func threeSumClosest(nums []int, target int) int { 17 | sort.Ints(nums) 18 | n := len(nums) 19 | minAbs := 1<<31 - 1 20 | minSum := 0 21 | 22 | for i, num := range nums { 23 | if i > 0 && nums[i] == nums[i-1] { // 优化:可选的去重 24 | continue 25 | } 26 | 27 | l, r := i+1, n-1 28 | for l < r { 29 | sum := num + nums[l] + nums[r] 30 | if abs(target-sum) < minAbs { 31 | minAbs = abs(target - sum) 32 | minSum = sum 33 | } 34 | switch { 35 | case sum < target: 36 | l++ 37 | case sum > target: 38 | r-- 39 | default: 40 | return target 41 | } 42 | } 43 | } 44 | return minSum 45 | } 46 | 47 | // 暴力三层遍历,求解最接近的和 48 | func threeSumClosest1(nums []int, target int) int { 49 | sort.Ints(nums) 50 | n := len(nums) 51 | minAbs := abs(nums[0] + nums[1] + nums[2] - target) 52 | minSum := 0 53 | for i := 0; i < n-2; i++ { 54 | for j := i + 1; j < n-1; j++ { 55 | for k := j + 1; k < n; k++ { 56 | sum := nums[i] + nums[j] + nums[k] 57 | if abs(sum-target) <= minAbs { 58 | minSum = sum 59 | minAbs = abs(sum - target) 60 | } 61 | } 62 | } 63 | } 64 | return minSum 65 | } 66 | -------------------------------------------------------------------------------- /array/189_rotate_array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | nums := []int{-1, -100, 3, 99} 7 | rotate2(nums, 2) 8 | fmt.Println(nums) 9 | } 10 | 11 | // 每次都把最后一个数挪到第一位来即可 12 | func rotate1(nums []int, k int) { 13 | n := len(nums) 14 | for k > 0 { 15 | last := nums[n-1] 16 | for i := n - 1; i > 0; i-- { 17 | nums[i] = nums[i-1] 18 | } 19 | nums[0] = last 20 | k-- 21 | } 22 | } 23 | 24 | func rotate2(nums []int, k int) { 25 | n := len(nums) 26 | step := n - k 27 | 28 | } 29 | -------------------------------------------------------------------------------- /array/18_4sum.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(fourSum([]int{1, 0, -1, 0, -2, 2}, 0)) // [[-2 -1 1 2] [-2 0 0 2] [-1 0 0 1]] 10 | fmt.Println(fourSum([]int{-3, 0, 0, 1, 2,}, 0)) // [[-3 0 1 2]] 11 | fmt.Println(fourSum([]int{0, 0, 0, 0}, 0)) // [[0 0 0 0]] 12 | } 13 | 14 | // 15 | // N 数之和的本质是,在有序数组内,寻找 N 个数的和恰好是 S 16 | // 解决办法还是 3sum 3sum_closest 的双指针法,不过需要外部 N-2 层循环,内部双指针循环即可 17 | // 注意双指针在遍历时外部所有循环要去重,指针移动时也要去重 18 | // 19 | func fourSum(nums []int, target int) [][]int { 20 | sort.Ints(nums) 21 | n := len(nums) 22 | var res [][]int 23 | 24 | for i := 0; i < n-1; i++ { 25 | if i > 0 && nums[i] == nums[i-1] { // 去重1 26 | continue 27 | } 28 | for j := i + 1; j < n; j++ { 29 | if j > i+1 && nums[j] == nums[j-1] { // 去重2 // 注意条件:j>i+1 与 i>0 相同都是为了排除第一个相同数 30 | continue 31 | } 32 | head, tail := j+1, n-1 33 | for head < tail { 34 | sum := nums[i] + nums[j] + nums[head] + nums[tail] 35 | switch { 36 | case sum < target: // 向后走 37 | head++ 38 | case sum > target: // 向前走 39 | tail-- 40 | case sum == target: // 向前向后走 41 | res = append(res, []int{nums[i], nums[j], nums[head], nums[tail]}) 42 | // 去重3:注意 for 循环条件的判断,避开死循环 43 | for head < tail && nums[head] == nums[head+1] { 44 | head++ 45 | } 46 | for head < tail && nums[tail] == nums[tail-1] { 47 | tail-- 48 | } 49 | head++ 50 | tail-- 51 | } 52 | } 53 | } 54 | } 55 | return res 56 | } 57 | -------------------------------------------------------------------------------- /array/1_two_sum.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(twoSum1([]int{2, 7, 11, 15}, 9)) // [0,1] 7 | fmt.Println(twoSum2([]int{3, 2, 4}, 6)) // [1,2] 8 | fmt.Println(twoSum3([]int{3, 3}, 6)) // [0,1] 9 | } 10 | 11 | // 12 | // 暴力双重遍历 13 | // 14 | func twoSum1(nums []int, target int) []int { 15 | n := len(nums) 16 | for i := 0; i < n-1; i++ { 17 | for j := i + 1; j < n; j++ { // 注意 j 的遍历区间 18 | if nums[i]+nums[j] == target { 19 | return []int{i, j} 20 | } 21 | } 22 | } 23 | return nil 24 | } 25 | 26 | // 27 | // 哈希表索引 28 | // 检查数组中是否存在目标元素,若存在则找出索引 29 | // 哈希表特别适合抽象类的配对结构,当要解决问题的数据单元是成对数据关系时,考虑哈希表 map 结构 30 | // 31 | func twoSum2(nums []int, target int) []int { 32 | num2index := make(map[int]int, len(nums)) 33 | for i, num := range nums { 34 | num2index[num] = i 35 | } 36 | for i, num := range nums { 37 | pair := target - num 38 | if j, ok := num2index[pair]; ok && i != j { // 剔除自身相加的情况,使用哈希表需要注意的点:索引重叠时为同一元素 39 | return []int{i, j} 40 | } 41 | } 42 | return nil 43 | } 44 | 45 | // 46 | // 优化后的哈希表索引方式 47 | // 看 twoSum2 会发现进行了2次for循环,可以进行合并优化,一边遍历,一边检查 48 | // 49 | func twoSum3(nums []int, target int) []int { 50 | num2index := make(map[int]int, len(nums)) 51 | for i, num := range nums { 52 | pair := target - num 53 | if j, ok := num2index[pair]; ok && i != j { 54 | return []int{j, i} // 注意返回值顺序,向后遍历 nums,所以 i 在 j 后 55 | } 56 | num2index[num] = i 57 | } 58 | return nil 59 | } 60 | -------------------------------------------------------------------------------- /array/216_combination_sum_iii.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(combinationSum3(4, 24)) // [[8 9 6 1] [8 9 5 2] [7 9 6 2] [8 9 4 3] [7 9 5 3] [7 8 6 3] [6 9 5 4] [7 8 5 4]] 7 | fmt.Println(combinationSum3(3, 7)) // [[2 4 1]] 8 | fmt.Println(combinationSum3(3, 9)) // [[2 6 1] [3 5 1] [3 4 2]] 9 | } 10 | 11 | // 调了一小时才调出来的递归写法阿西吧 12 | // 递归函数必定有退出条件,先分析递归执行到最后如何退出,再去写一般的递归传参逻辑 13 | // 本题是 k 递减到 2 时求两数之和再退出 14 | func combinationSum3(k int, n int) [][]int { 15 | nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} 16 | var res [][]int 17 | 18 | switch { 19 | case k == 0: 20 | return nil 21 | case k == 1: 22 | if 1 <= n && n <= 9 { 23 | return [][]int{{n}} 24 | } 25 | default: 26 | res = append(res, combineSum(k, n, nums)...) 27 | } 28 | 29 | return res 30 | } 31 | 32 | func combineSum(k, target int, nums []int) [][]int { 33 | // fmt.Printf("%v, %v, %v\n", k, target, nums) // 输出入参来调试递归 34 | if k <= 0 || len(nums) <= 0 || target <= 0 { 35 | return nil 36 | } 37 | 38 | // 递归退出条件:k 自减到 2 39 | if k == 2 { 40 | return combineTwoSum(nums, target) 41 | } 42 | 43 | var res [][]int 44 | for i := 0; i < len(nums); i++ { 45 | // 关键的递归步骤:对于当前值 nums[i],再从 nums[i+1:] 余下数组中找和为 target-nums[i] 的 k-1 个数 46 | remains := combineSum(k-1, target-nums[i], nums[i+1:]) 47 | if len(remains) <= 0 { // 没找到 48 | continue 49 | } 50 | for _, remain := range remains { // 找到了,就把 nums[i] 匹配进去 51 | remain = append(remain, nums[i]) 52 | res = append(res, remain) 53 | } 54 | } 55 | 56 | return res 57 | } 58 | 59 | // nums 中所有和为 target 的两数之和 60 | func combineTwoSum(nums []int, target int) [][]int { 61 | m := make(map[int]int) 62 | for i, num := range nums { 63 | m[num] = i 64 | } 65 | 66 | var res [][]int 67 | for _, n := range nums { 68 | if n >= target { 69 | break 70 | } 71 | diff := target - n 72 | if _, ok := m[diff]; ok && n != diff { 73 | res = append(res, []int{n, diff}) 74 | } 75 | } 76 | return res[:len(res)/2] // 去重 77 | } 78 | -------------------------------------------------------------------------------- /array/217_contains_duplicate.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(containsDuplicate([]int{1, 2, 3, 1})) // false 7 | } 8 | 9 | // 没什么好说的,哈希表走你 10 | func containsDuplicate(nums []int) bool { 11 | m := make(map[int]int) 12 | for _, num := range nums { 13 | if _, ok := m[num]; ok { 14 | return true 15 | } 16 | m[num] = 0 17 | } 18 | return false 19 | } 20 | -------------------------------------------------------------------------------- /array/219_contains_duplicate_ii.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(containsNearbyDuplicate([]int{1, 0, 1, 1}, 1)) // true 7 | } 8 | 9 | // 查找还是哈希表比较 ok 10 | func containsNearbyDuplicate(nums []int, k int) bool { 11 | duplicates := make(map[int][]int) 12 | for i, num := range nums { 13 | duplicates[num] = append(duplicates[num], i) // 把索引存起来 14 | } 15 | 16 | for _, dups := range duplicates { 17 | if len(dups) <= 1 { 18 | continue 19 | } 20 | for i := len(dups) - 1; i > 0; i-- { 21 | if dups[i]-dups[i-1] <= k { // 计算彼此的间隔 22 | return true 23 | } 24 | } 25 | } 26 | return false 27 | } 28 | -------------------------------------------------------------------------------- /array/228_summary_ranges.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Printf("%q\n", summaryRanges([]int{0, 1, 2, 4, 5, 7})) // ["0->2" "4->5" "7"] 7 | } 8 | 9 | // 要找到被剔除的数或数序列,判断某个数是否在数组中,自然想到哈希表 10 | func summaryRanges(nums []int) []string { 11 | m := make(map[int]int) 12 | for _, n := range nums { 13 | m[n] = 0 14 | } 15 | 16 | var ranges []string 17 | l, r := -1, -1 18 | for _, num := range nums { 19 | _, preOK := m[num-1] 20 | _, nextOK := m[num+1] 21 | 22 | switch { 23 | case !preOK && nextOK: // num 在左边界 24 | l = num 25 | case preOK && !nextOK: // num 在右边界 26 | r = num 27 | ranges = append(ranges, fmt.Sprintf("%d->%d", l, r)) 28 | case !preOK && !nextOK: // num 是独立的数 29 | ranges = append(ranges, fmt.Sprintf("%d", num)) 30 | } 31 | } 32 | return ranges 33 | } 34 | -------------------------------------------------------------------------------- /array/238_product_of_array_except_self.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(productExceptSelf([]int{1, 2, 3, 4})) // [24 12 8 6] 7 | fmt.Println(productExceptSelf([]int{2, 4, 5, 7})) // [140 70 56 40] 8 | } 9 | 10 | // 其余部分积 = 左子数组积 * 右子数组积 11 | // 遍历方式很巧妙 12 | // 可惜 Golang 实现执行时间貌似都过不了 50000 多个[1, -1, ...]的那个 case 13 | func productExceptSelf(nums []int) []int { 14 | n := len(nums) 15 | res := make([]int, n) 16 | res[0] = 1 17 | for i := 1; i < n; i++ { 18 | res[i] = res[i-1] * nums[i-1] // 把 nums[i] 左测子数组的积存在 res[i] 中 19 | } 20 | // fmt.Println(res) // [1 2 8 40] 21 | 22 | back := 1 23 | for i := n - 1; i >= 0; i-- { 24 | res[i] *= back // res[i] 再乘右侧积 25 | back *= nums[i] 26 | } 27 | return res 28 | } 29 | -------------------------------------------------------------------------------- /array/268_missing_number.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(missingNumber([]int{3, 0, 1})) 10 | fmt.Println(bestMissingNumber([]int{3, 0, 1})) 11 | fmt.Println(bestMissingNumber([]int{0})) 12 | } 13 | 14 | // 让我想起了小学时候学的急转弯... 15 | // 如何计算一个人的体积:把人放入一桶水中,计算桶前后的体积差即可... 16 | // 如果题目给出的已知条件十分地有规律,那解决方法肯定是有规律的,尝试着找出来 17 | func bestMissingNumber(nums []int) int { 18 | curSum := 0 19 | for i := range nums { 20 | curSum += nums[i] 21 | } 22 | n := len(nums) 23 | fullSum := n * (n + 1) / 2 24 | return fullSum - curSum 25 | } 26 | 27 | // 辣鸡解法 28 | func missingNumber(nums []int) int { 29 | sort.Ints(nums) // lgN 30 | for i := 0; i < len(nums); i++ { // N 31 | if nums[i] != i { 32 | return i 33 | } 34 | } 35 | return len(nums) 36 | } 37 | -------------------------------------------------------------------------------- /array/26_remove_duplicates_from_sorted_array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(removeDuplicates1([]int{1, 1, 2})) // 2 7 | fmt.Println(removeDuplicates2([]int{0, 0, 1, 1, 1, 2, 2, 3, 3, 4})) // 5 8 | } 9 | 10 | // 针对有序数组,双指针法是十分常见且有用的 11 | func removeDuplicates1(nums []int) int { 12 | slow, fast := 0, 0 13 | for fast < len(nums)-1 { 14 | if nums[fast] != nums[fast+1] { // 相邻的数不相等 15 | slow++ 16 | fast++ 17 | nums[slow] = nums[fast] // 将最新的新数存储到慢指针的位置 18 | continue 19 | } 20 | fast++ 21 | } 22 | return slow + 1 23 | } 24 | 25 | // 充分利用数组有序的已知条件 26 | func removeDuplicates2(nums []int) int { 27 | n := len(nums) 28 | l, r := 0, 1 29 | for r < n { 30 | if nums[l] < nums[r] { // 比我大就放到我的下一个 31 | l++ 32 | nums[l], nums[r] = nums[r], nums[l] 33 | } 34 | r++ 35 | } 36 | return l + 1 37 | } 38 | -------------------------------------------------------------------------------- /array/27_remove_element.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(removeElement1([]int{3, 2, 2, 3}, 3)) 7 | fmt.Println(removeElement2([]int{0, 1, 2, 2, 3, 0, 4, 2}, 2)) 8 | } 9 | 10 | // 11 | // 遍历数组一如既往地联想到双指针法 12 | // 13 | func removeElement1(nums []int, val int) int { 14 | slow := 0 15 | for fast := 0; fast < len(nums); fast++ { 16 | if nums[fast] != val { 17 | nums[slow] = nums[fast] // 快指针在前,慢指针在后,遇到不等的元素就放到慢指针的位置 18 | slow++ 19 | } 20 | } 21 | return slow 22 | } 23 | 24 | // 类似 26 的解法 25 | func removeElement2(nums []int, val int) int { 26 | slow, fast := 0, 0 27 | for fast < len(nums) { 28 | if nums[fast] != val { 29 | if slow != fast { 30 | nums[slow] = nums[fast] 31 | } 32 | slow++ 33 | fast++ 34 | continue 35 | } 36 | fast++ 37 | } 38 | return slow 39 | } 40 | -------------------------------------------------------------------------------- /array/283_move_zeroes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | moveZeroes([]int{0, 1, 0, 3, 12}) 7 | moveZeroes([]int{0, 0, 1}) 8 | bestMoveZeroes([]int{1, 2, 3, 0, 0, 4}) 9 | } 10 | 11 | // 辣鸡解法 12 | func moveZeroes(nums []int) { 13 | n := len(nums) 14 | rear := n - 1 15 | for i := 0; i < n; i++ { 16 | if nums[i] == 0 { 17 | for j := i; j < rear; j++ { // 后部分全部往前挪动 18 | nums[j] = nums[j+1] 19 | } 20 | nums[rear] = 0 21 | rear-- 22 | i-- // 原来0的位置上,不知道下一个值是不是0,所以 i-- 23 | } 24 | if i >= rear { 25 | break 26 | } 27 | } 28 | fmt.Println(nums) 29 | } 30 | 31 | // 快慢指针 32 | // fast 指针在前把所有不是 0 的元素挪动到 slow 指针上 33 | func bestMoveZeroes(nums []int) { 34 | slow, fast := 0, 0 35 | for fast < len(nums) { 36 | if nums[fast] != 0 { 37 | nums[slow], nums[fast] = nums[fast], nums[slow] 38 | slow++ 39 | } 40 | fast++ 41 | } 42 | fmt.Println(nums) 43 | } 44 | -------------------------------------------------------------------------------- /array/287_find_the_duplicate_number.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(findDuplicate([]int{1, 3, 4, 2, 2})) // 2 7 | fmt.Println(findDuplicate([]int{3, 1, 3, 4, 2})) // 3 8 | } 9 | 10 | // 和 442、448 就比较像,可惜题目要求数组 11 | // 不可修改:不能排序、不能取负值 12 | // 空间复杂度O(1):不能使用 O(N) 的哈希表 13 | // 时间复杂度O(N^2) 14 | func findDuplicate(nums []int) int { 15 | if len(nums) <= 1 { 16 | return 0 17 | } 18 | 19 | slow := nums[0] 20 | fast := nums[slow] 21 | for slow != fast { // 题给必有一个重复值 22 | slow = nums[slow] 23 | fast = nums[nums[fast]] // slow走一步,fast走两步,fast多绕一圈追上了slow,二者指向 loop 的入口 24 | } 25 | fmt.Println(slow, fast) 26 | 27 | fast = 0 // 从头出发去找 loop 的入口 28 | for fast != slow { 29 | fast = nums[fast] 30 | slow = nums[slow] 31 | } 32 | 33 | return slow 34 | } 35 | -------------------------------------------------------------------------------- /array/289_game_of_life.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | board := [][]int{ 7 | {0, 1, 0}, 8 | {0, 0, 1}, 9 | {1, 1, 1}, 10 | {0, 0, 0}, 11 | } 12 | gameOfLife(board) // [[0 0 0] [1 0 1] [0 1 1] [0 1 0]] 13 | } 14 | 15 | // 题目描述长长长... 16 | func gameOfLife(board [][]int) { 17 | backup := make([][]int, len(board)) // 生死同时发生 18 | for i := range board { 19 | backup[i] = make([]int, len(board[0])) 20 | copy(backup[i], board[i]) 21 | } 22 | 23 | for i := range backup { 24 | for j := range backup[i] { 25 | counts := countAround(backup, i, j) 26 | if backup[i][j] == 1 && (counts < 2 || counts > 3) { // 活细胞狗带 27 | board[i][j] = 0 28 | } 29 | 30 | if backup[i][j] == 0 && counts == 3 { // 死细胞复活 31 | board[i][j] = 1 32 | } 33 | } 34 | } 35 | fmt.Println(board) 36 | } 37 | 38 | func countAround(board [][]int, i, j int) int { 39 | 40 | r, c := len(board)-1, len(board[0])-1 41 | count := 0 42 | if i > 0 { 43 | if board[i-1][j] == 1 { // 上 44 | count++ 45 | } 46 | if j > 0 && board[i-1][j-1] == 1 { // 左上 47 | count++ 48 | } 49 | } 50 | if i < r { 51 | if board[i+1][j] == 1 { // 下 52 | count++ 53 | } 54 | if j > 0 && board[i+1][j-1] == 1 { // 左下 55 | count++ 56 | } 57 | } 58 | 59 | if j > 0 { 60 | if board[i][j-1] == 1 { // 左 61 | count++ 62 | } 63 | } 64 | if j < c { 65 | if board[i][j+1] == 1 { // 右 66 | count++ 67 | } 68 | if i > 0 && board[i-1][j+1] == 1 { // 右上 69 | count++ 70 | } 71 | if i < r && board[i+1][j+1] == 1 { // 右下 72 | count++ 73 | } 74 | } 75 | return count 76 | } 77 | -------------------------------------------------------------------------------- /array/31_next_permutation.go: -------------------------------------------------------------------------------- 1 | // 参考 https://goleetcode.io/2018/11/20/array/31-next-permutation 2 | package main 3 | 4 | import "fmt" 5 | 6 | func main() { 7 | nums := []int{1, 2, 7, 4, 3, 1} 8 | nextPermutation(nums) 9 | fmt.Println(nums) // [1 3 1 2 4 7] // bingo 10 | } 11 | 12 | // 数组规律题 13 | // 从后往前找第一个下降点 i,再从后往前找它的 ceil 值,交换 14 | // 再将 [i+1:] 之后的数据从降序反转为升序,为最小序列 15 | func nextPermutation(nums []int) { 16 | // 处理降序的 case 17 | desc := true 18 | n := len(nums) 19 | for i := range nums[:n-1] { 20 | if nums[i] < nums[i+1] { 21 | desc = false 22 | } 23 | } 24 | if desc { 25 | reverse(nums) 26 | return 27 | } 28 | 29 | // 从后向前找第一个下降的点 30 | var i int 31 | for i = n - 1; i > 0; i-- { 32 | if nums[i-1] < nums[i] { 33 | i-- // 找到 2 34 | break 35 | } 36 | } 37 | 38 | // 从后向前,找向上最接近的值 39 | for j := n - 1; j > i; j-- { 40 | if nums[j] > nums[i] { 41 | nums[j], nums[i] = nums[i], nums[j] // 交换 2 和 3 // [1 3 7 4 2 1] 42 | break 43 | } 44 | } 45 | 46 | reverse(nums[i+1:]) // 反转 4 2 1 // [1 3 1 2 4 7] 47 | } 48 | -------------------------------------------------------------------------------- /array/33_search_in_rotated_sorted_array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(search([]int{4, 5, 6, 7, 0, 1, 2}, 0)) // 4 7 | fmt.Println(search([]int{4, 5, 6, 7, 0, 1, 2}, 3)) // -1 8 | } 9 | 10 | // 类二分搜索 11 | // 最左边数 < 中间数则左侧有序,最右边数 > 中间数则右侧有序 12 | // 在缩小搜索区域时,一直只在确定的有序区域内查找 13 | func search(nums []int, target int) int { 14 | l, r := 0, len(nums)-1 15 | for l <= r { 16 | mid := (l + r) / 2 17 | switch { 18 | case nums[mid] == target: // bingo 19 | return mid 20 | case nums[l] <= nums[mid]: // 左侧有序 21 | if nums[l] <= target && target < nums[mid] { // 保证 target 一定在有序的左侧内 22 | r = mid - 1 23 | } else { 24 | l = mid + 1 25 | } 26 | case nums[mid] <= nums[r]: // 右侧有序 27 | if nums[mid] < target && target <= nums[r] { // 保证 target 一定在有序的右侧内 28 | l = mid + 1 29 | } else { 30 | r = mid - 1 31 | } 32 | } 33 | } 34 | return -1 35 | } 36 | -------------------------------------------------------------------------------- /array/34_find_first_and_last_position_of_element_in_sorted_array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(searchRange1([]int{5, 7, 7, 8, 8, 10}, 8)) // [3, 4] 7 | fmt.Println(searchRange2([]int{5, 7, 7, 8, 8, 10}, 8)) // [3, 4] 8 | fmt.Println(searchRange2([]int{1}, 1)) // [0, 0] 9 | } 10 | 11 | // 直接二分查找 12 | // O(N) // not ok 13 | func searchRange1(nums []int, target int) []int { 14 | n := len(nums) 15 | i := binarySearch(nums, 0, n-1, target) 16 | if i == -1 { 17 | return []int{-1, -1} 18 | } 19 | 20 | // 找到后向两侧延伸 21 | l, r := i, i 22 | for j := i - 1; j >= 0; j-- { 23 | if nums[j] == target { 24 | l = j 25 | } 26 | } 27 | for j := i + 1; j < n; j++ { 28 | if nums[j] == target { 29 | r = j 30 | } 31 | } 32 | return []int{l, r} 33 | } 34 | 35 | // 改进的二分搜索 36 | func searchRange2(nums []int, target int) []int { 37 | l := edgeBinSearch(nums, true, target) 38 | r := edgeBinSearch(nums, false, target) 39 | return []int{l, r} 40 | } 41 | 42 | // 普通二分搜索在匹配到 target 时直接 return 43 | // 在本题搜索时在匹配到 target 之后依旧向边缘走当做没匹配到,注意 2 个边界条件 44 | // O(logN) // ok 45 | func edgeBinSearch(nums []int, leftest bool, target int) int { 46 | n := len(nums) 47 | l, r := 0, n-1 48 | for l <= r { 49 | mid := (l + r) / 2 50 | switch { 51 | case target < nums[mid]: 52 | r = mid - 1 53 | case target > nums[mid]: 54 | l = mid + 1 55 | default: 56 | if leftest { 57 | if mid == 0 || nums[mid] > nums[mid-1] { // 不再继续向左走的 2 个边界条件 58 | return mid 59 | } 60 | r = mid - 1 // 继续在左侧找 61 | } else { 62 | if mid == n-1 || nums[mid] < nums[mid+1] { 63 | return mid 64 | } 65 | l = mid + 1 // 继续在右侧找 66 | } 67 | } 68 | } 69 | return -1 70 | } 71 | -------------------------------------------------------------------------------- /array/35_search_insert_position.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(searchInsert([]int{1, 3, 5, 6}, 5)) 7 | fmt.Println(searchInsert([]int{1, 3, 5, 6}, 2)) 8 | fmt.Println(searchInsert([]int{1, 3, 5, 6}, 0)) 9 | } 10 | 11 | // 二分查找 12 | func searchInsert(nums []int, target int) int { 13 | left, right := 0, len(nums)-1 14 | for left <= right { 15 | mid := (right + left) / 2 16 | switch { 17 | case nums[mid] > target: 18 | right = mid - 1 19 | case nums[mid] < target: 20 | left = mid + 1 21 | default: 22 | return mid 23 | } 24 | } 25 | return left 26 | } 27 | -------------------------------------------------------------------------------- /array/39_combination_sum.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(combinationSum([]int{2, 3, 6, 7}, 7)) 10 | } 11 | 12 | func combinationSum(candidates []int, target int) [][]int { 13 | sort.Ints(candidates) 14 | return combine(candidates, target) 15 | } 16 | 17 | func combine(nums []int, target int) [][]int { 18 | var res [][]int 19 | if len(nums) <= 0 { // 递归到最后一个元素,递归结束 20 | return res 21 | } 22 | 23 | subSum := target - nums[0] 24 | 25 | switch { 26 | case subSum < 0: // 向后不存在更大的值,递归结束 27 | return res 28 | case subSum == 0: // 第一个数就是 target 29 | res = append(res, []int{nums[0]}) 30 | case subSum > 0: 31 | remains := combine(nums, subSum) // 寻找所有的子和组合 32 | for _, v := range remains { 33 | way := append([]int{nums[0]}, v...) 34 | res = append(res, way) 35 | } 36 | } 37 | 38 | res = append(res, combine(nums[1:], target)...) // 向后查找其他组合,避免重复 39 | return res 40 | } 41 | -------------------------------------------------------------------------------- /array/41_first_missing_positive.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(firstMissingPositive([]int{3, 4, -1, 1})) // 2 7 | } 8 | 9 | func firstMissingPositive(nums []int) int { 10 | n := len(nums) 11 | 12 | // 对数组进行归位预处理 13 | for i := 0; i < n; i++ { 14 | for nums[i] > 0 && nums[i] <= n && nums[i] != nums[nums[i]-1] { 15 | swap(&nums[i], &nums[nums[i]-1]) 16 | } 17 | } 18 | // fmt.Println(nums) // [1 -1 3 4] 19 | 20 | // 向后检查 21 | for i := 0; i < n; i++ { 22 | if nums[i] != i+1 { 23 | return i + 1 24 | } 25 | } 26 | 27 | // 理想正整数数组 28 | return n + 1 29 | } 30 | 31 | func swap(x, y *int) { 32 | *x, *y = *y, *x 33 | } 34 | -------------------------------------------------------------------------------- /array/42_trapping_rain_water.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(trap([]int{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1})) // 6 7 | } 8 | 9 | func trap(height []int) int { 10 | area := 0 11 | l, r := 0, len(height)-1 12 | lTop, rTop := 0, 0 13 | 14 | for l <= r { 15 | lTop = max(height[l], lTop) 16 | rTop = max(height[r], rTop) 17 | if lTop < rTop { 18 | area += lTop - height[l] // 右侧更高些,往右侧走。一边向右移,一边计算高度差来累计面积(最高点处高度差为 0) 19 | l++ 20 | } else { 21 | area += rTop - height[r] // 向左侧移,用目前右侧最高高度来计算高度差,累计面积 22 | r-- 23 | } 24 | } 25 | return area 26 | } 27 | 28 | func max(x, y int) int { 29 | if x > y { 30 | return x 31 | } 32 | return y 33 | } 34 | -------------------------------------------------------------------------------- /array/442_find_all_duplicates_in_an_array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(findDuplicates([]int{4, 3, 2, 7, 8, 2, 3, 1})) // [2, 3] 7 | } 8 | 9 | // 多么适合用哈希表的题... 10 | // 可惜不能使用额外空间,复杂度 O(N),可能要求在数组原地操作、一次遍历解决 11 | // 解法和下方的 448 很像,充分利用 1~n 的已知条件,十分巧妙 12 | func findDuplicates(nums []int) []int { 13 | var dups []int 14 | for _, num := range nums { 15 | if num < 0 { 16 | num = -num 17 | } 18 | 19 | n := num - 1 20 | if nums[n] < 0 { // 指向的位置以为负值,则重复 21 | dups = append(dups, num) 22 | continue 23 | } 24 | nums[n] = -nums[n] 25 | } 26 | return dups 27 | } 28 | -------------------------------------------------------------------------------- /array/448_find_all_numbers_disappeared_in_an_array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(findDisappearedNumbers([]int{4, 3, 2, 7, 8, 2, 3, 1})) 7 | } 8 | 9 | // 做法比较巧妙 10 | // 充分利用 [1, .., n] 的已知条件 11 | // 为了标记 N 出现过,可以把 nums[N-1] 置为负数 12 | // 最后遍历,没有被标记过的位置 index 即是未出现的数 13 | // 巧妙地利用了标记位置和索引的关系 14 | func findDisappearedNumbers(nums []int) []int { 15 | for _, n := range nums { 16 | if n < 0 { 17 | n = -n // 为了 O(1) 的空间复杂度,避免数组越界 18 | } 19 | if nums[n-1] > 0 { 20 | nums[n-1] = -nums[n-1] 21 | } 22 | } 23 | 24 | var vanishNums []int 25 | for i, n := range nums { 26 | if n > 0 { 27 | vanishNums = append(vanishNums, i+1) 28 | } 29 | } 30 | return vanishNums 31 | } 32 | -------------------------------------------------------------------------------- /array/485_max-consecutive_ones.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(findMaxConsecutiveOnes([]int{})) // 0 7 | fmt.Println(findMaxConsecutiveOnes([]int{1, 1, 0, 1, 1, 1})) // 3 8 | } 9 | 10 | func findMaxConsecutiveOnes(nums []int) int { 11 | n := len(nums) 12 | count, maxCount := 0, 0 13 | for i := 0; i < n; i++ { 14 | if nums[i] == 1 { 15 | count = 1 16 | for j := i + 1; j < n; j++ { // 向后找连续的 1 17 | if nums[j] == 0 { 18 | break 19 | } 20 | count++ 21 | i++ 22 | } 23 | maxCount = max(count, maxCount) 24 | } 25 | } 26 | return maxCount 27 | } 28 | 29 | func max(x, y int) int { 30 | if x > y { 31 | return x 32 | } 33 | return y 34 | } 35 | -------------------------------------------------------------------------------- /array/48_rotate_image.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | matrix := [][]int{ 7 | {5, 1, 9, 11}, 8 | {2, 4, 8, 10}, 9 | {13, 3, 6, 7}, 10 | {15, 14, 12, 16}, 11 | } 12 | matrix = rotate(matrix) 13 | for _, nums := range matrix { 14 | for _, num := range nums { 15 | fmt.Print(num, " ") 16 | } 17 | fmt.Println() 18 | } 19 | } 20 | 21 | // 正方形任意旋转可改为多重折叠 22 | func rotate(matrix [][]int) [][]int { 23 | n := len(matrix) 24 | if n <= 1 { 25 | return matrix 26 | } 27 | // 右侧对角线折叠 28 | for i := 0; i < n; i++ { 29 | for j := i + 1; j < n; j++ { 30 | matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j] 31 | } 32 | } 33 | 34 | // 左右折叠 35 | for i := 0; i < n; i++ { 36 | for j := 0; j < n/2; j++ { 37 | matrix[i][j], matrix[i][n-1-j] = matrix[i][n-1-j], matrix[i][j] 38 | } 39 | } 40 | return matrix 41 | } 42 | -------------------------------------------------------------------------------- /array/495_teemo_attacking.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(findPoisonedDuration([]int{1, 4}, 2)) // 4 7 | fmt.Println(findPoisonedDuration([]int{1, 2}, 2)) // 3 8 | } 9 | 10 | // 对我这种不玩LOL的人来说本题的超长描述就像这句注释一样对题解没啥用... 11 | // 题意:求解重叠区间 12 | func findPoisonedDuration(timeSeries []int, duration int) int { 13 | n := len(timeSeries) 14 | if n <= 0 { 15 | return 0 16 | } 17 | 18 | t := 0 19 | for i := 1; i < n; i++ { 20 | diff := timeSeries[i] - timeSeries[i-1] 21 | if diff > duration { // 未重叠 22 | t += duration 23 | } else { 24 | t += diff // 重叠部分不予处理 25 | } 26 | } 27 | return t + duration // 最后一个数 28 | } 29 | 30 | // 辣鸡的第一反应解法 31 | func findPoisonedDuration2(timeSeries []int, duration int) int { 32 | m := make(map[int]int) 33 | for _, t := range timeSeries { 34 | for i := 0; i < duration; i++ { 35 | m[t+i] = 0 36 | } 37 | } 38 | return len(m) 39 | } 40 | -------------------------------------------------------------------------------- /array/4_median_of_two_sorted_arrays.go: -------------------------------------------------------------------------------- 1 | // 参考 https://goleetcode.io/2018/11/19/array/4-median-of-two-sorted-arrays 2 | package main 3 | 4 | import "fmt" 5 | 6 | func main() { 7 | fmt.Println(findMedianSortedArrays1([]int{}, []int{})) // OJ 无此类异常 case 8 | fmt.Println(findMedianSortedArrays1([]int{1, 3, 5}, []int{2, 4, 6})) // 3.5 9 | fmt.Println(findMedianSortedArrays1([]int{1, 3, 5, 7}, []int{2, 4, 6})) // 4 10 | fmt.Println(findMedianSortedArrays2([]int{1, 3, 5}, []int{2, 4, 6})) // 3.5 11 | } 12 | 13 | // 合并两个数组后直接取中位数即可 14 | // 时间复杂度 O(M+N) // not ok 15 | func findMedianSortedArrays1(nums1 []int, nums2 []int) float64 { 16 | res := merge(nums1, nums2) 17 | n := len(res) 18 | if n == 0 { 19 | return -1 20 | } 21 | if n%2 == 0 { 22 | return float64(res[n/2-1]+res[n/2]) / 2 // len(nums)/2 是中位数 pair 的后一个值 23 | } 24 | return float64(res[n/2]) 25 | } 26 | 27 | // 合并两个有序数组 28 | func merge(nums1, nums2 []int) []int { 29 | n1, n2 := len(nums1), len(nums2) 30 | i, j := 0, 0 31 | res := make([]int, 0, n1+n2) 32 | for i < n1 && j < n2 { 33 | switch { 34 | case nums1[i] < nums2[j]: 35 | res = append(res, nums1[i]) 36 | i++ 37 | case nums1[i] > nums2[j]: 38 | res = append(res, nums2[j]) 39 | j++ 40 | default: 41 | res = append(res, nums1[i], nums2[j]) 42 | i++ 43 | j++ 44 | } 45 | } 46 | 47 | // 处理未合并部分 48 | if i < n1 { 49 | res = append(res, nums1[i:]...) // 循环退出时 i 未被处理,需合并 [i:] 50 | } 51 | if j < n2 { 52 | res = append(res, nums2[j:]...) 53 | } 54 | return res 55 | } 56 | 57 | // 类二分查找分而治之的思路 58 | // O(log(M+N)) // ok 59 | func findMedianSortedArrays2(nums1 []int, nums2 []int) float64 { 60 | n1, n2 := len(nums1), len(nums2) 61 | if n1+n2 == 0 { 62 | return -1 63 | } 64 | if (n1+n2)%2 == 0 { 65 | l := findKth(nums1, nums2, (n1+n2)/2) 66 | r := findKth(nums1, nums2, (n1+n2)/2+1) // 此处 +1 与上边 len(mergedNums)/2 同理 67 | return float64(l+r) / 2 68 | } 69 | return float64(findKth(nums1, nums2, (n1+n2)/2+1)) 70 | } 71 | 72 | // 在两个有序数组中查找第 k 大的数 73 | // 第 k 大的数即 nums 中索引为 k-1 的数,在舍弃区域比较值时都要 -1 处理 74 | func findKth(nums1, nums2 []int, k int) int { 75 | n1, n2 := len(nums1), len(nums2) 76 | if n1 > n2 { 77 | n1, n2 = n2, n1 78 | nums1, nums2 = nums2, nums1 // 为避免数组长度的分类讨论,先做预处理 79 | } 80 | 81 | if n1 == 0 { 82 | return nums2[k-1] // bingo 83 | } 84 | 85 | if k == 1 { 86 | return min(nums1[0], nums2[0]) // bingo 87 | } 88 | 89 | k1 := min(k/2, n1) // 避免越界 90 | k2 := k - k1 // 不能理想的 k/2, k/2 划分 91 | 92 | // fmt.Println(nums1, k1-1, nums2, k2-1) 93 | 94 | switch { 95 | case nums1[k1-1] < nums2[k2-1]: 96 | return findKth(nums1[k1:], nums2, k2) // 彻底舍弃区域 1 97 | case nums1[k1-1] > nums2[k2-1]: 98 | return findKth(nums1, nums2[k2:], k1) // 彻底舍弃区域 3 99 | default: 100 | return nums1[k1-1] // bingo 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /array/532_k_diff_pairs_in_an_array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(findPairs([]int{3, 1, 4, 1, 5}, 2)) // 2 7 | fmt.Println(findPairs([]int{1, 2, 3, 4, 5}, -1)) // 0 8 | } 9 | 10 | // 和 two sum 一样,用哈希表做统计 11 | func findPairs(nums []int, k int) int { 12 | if k < 0 { // 注意这个case... 13 | return 0 14 | } 15 | 16 | freqs := make(map[int]int) 17 | for _, num := range nums { 18 | freqs[num]++ 19 | } 20 | 21 | count := 0 22 | if k == 0 { 23 | for _, freq := range freqs { 24 | if freq > 1 { 25 | count++ 26 | } 27 | } 28 | return count 29 | } 30 | 31 | for num := range freqs { 32 | if _, ok := freqs[num+k]; ok { 33 | count++ 34 | } 35 | } 36 | return count 37 | } 38 | -------------------------------------------------------------------------------- /array/53_maximum_subarray.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(maxSubArray([]int{-3, 4, -1, 3, -5})) 7 | fmt.Println(maxSubArray([]int{-2, -1})) 8 | } 9 | 10 | // 11 | // 跨步遍历的感觉 12 | // 13 | func maxSubArray(nums []int) int { 14 | max := nums[0] 15 | for _, n := range nums { 16 | if n > max { 17 | max = n 18 | } 19 | } 20 | 21 | sum, maxSum := 0, 0 22 | for i := 0; i < len(nums); i++ { 23 | switch { 24 | case nums[i] > 0: 25 | sum += nums[i] 26 | case nums[i] < 0: 27 | if sum+nums[i] > 0 { 28 | sum += nums[i] 29 | } else { 30 | sum = 0 31 | } 32 | } 33 | 34 | if maxSum < sum { 35 | maxSum = sum 36 | } 37 | } 38 | if max < 0 && maxSum > max { 39 | return max 40 | } 41 | return maxSum 42 | } 43 | -------------------------------------------------------------------------------- /array/54_spiral_matrix.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(spiralOrder([][]int{ 7 | // {1, 2, 3, 4}, 8 | // {5, 6, 7, 8}, 9 | // {9, 10, 11, 12}, 10 | 11 | // {1, 2}, 12 | // {3, 4}, 13 | 14 | {2, 3, 4}, 15 | {5, 6, 7}, 16 | {8, 9, 10}, 17 | {11, 12, 13}, 18 | {14, 15, 16}, 19 | })) 20 | } 21 | 22 | func spiralOrder(matrix [][]int) []int { 23 | if len(matrix) <= 0 || len(matrix[0]) <= 0 { 24 | return nil 25 | } 26 | if len(matrix) == 1 { 27 | return matrix[0] 28 | } 29 | return order(matrix, 0, len(matrix[0])-1, 0, len(matrix)-1, []int{}) 30 | } 31 | 32 | func order(matrix [][]int, start, end int, up, down int, nums []int) []int { 33 | if start > end || up > down { 34 | return nums 35 | } 36 | // 向右走 37 | for i := start; i <= end; i++ { 38 | nums = append(nums, matrix[up][i]) 39 | } 40 | 41 | // 向下走 42 | stop := true 43 | for i := up + 1; i <= down; i++ { 44 | nums = append(nums, matrix[i][end]) 45 | stop = false 46 | } 47 | if stop { 48 | return nums // 无路可走 49 | } 50 | 51 | // 向左走 52 | stop = true 53 | for i := end - 1; i >= start; i-- { 54 | nums = append(nums, matrix[down][i]) 55 | stop = false 56 | } 57 | if stop { 58 | return nums // 无路可走 59 | } 60 | 61 | // 向上走 62 | for i := down - 1; i > up; i-- { 63 | if end > 0 { // 单列的情况,下一趟不能往上走 64 | nums = append(nums, matrix[i][start]) 65 | } 66 | } 67 | return order(matrix, start+1, end-1, up+1, down-1, nums) 68 | } 69 | -------------------------------------------------------------------------------- /array/55_jump_game.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(jump([]int{2, 3, 1, 1, 4}, true)) // true 7 | fmt.Println(jump([]int{3, 2, 1, 0, 4}, true)) // false 8 | fmt.Println(jump([]int{1, 2, 3}, true)) // true 9 | fmt.Println(jump([]int{0, 1}, true)) // false 10 | fmt.Println(jump([]int{0, 2, 3}, true)) // false 11 | fmt.Println(jump([]int{2, 0, 0}, true)) // true 12 | fmt.Println(jump([]int{2, 0, 1, 0, 1}, true)) // false 13 | } 14 | 15 | func canJump(nums []int) bool { 16 | return jump(nums, true) 17 | } 18 | 19 | // 要想达到最后一位,数组的前 n-1 个成员必须 >= 直达数组的各成员 20 | // 如 [2 3 1 1] >= [4 3 2 1] 21 | // [2, 3, 1] >= [3 2 1] 22 | // [2, 3] >= [2 1] 23 | // [2] >= [1] 24 | // 效率比较低的递归 25 | func jump(nums []int, ok bool) bool { 26 | n := len(nums) 27 | if !ok { 28 | return false 29 | } 30 | 31 | // 处理遇到 0 的极端情况 32 | for i := n - 1 - 1; i >= 0; i-- { 33 | if nums[i] == 0 { 34 | direct := 1 35 | for j := i - 1; j >= 0; j-- { 36 | // fmt.Println(nums[j], direct) 37 | if nums[j] > direct { 38 | return jump(nums[:i], true) 39 | } 40 | direct++ 41 | } 42 | return jump(nums[:i], false) 43 | } 44 | } 45 | 46 | directs := make([]int, n) 47 | for i := range nums { 48 | directs[i] = n - 1 - i // 每个点都可直达 49 | } 50 | for i := n - 1 - 1; i >= 0; i-- { 51 | // fmt.Println(nums, directs, i, nums[i], directs[i]) 52 | if nums[i] >= directs[i] { // 某个点能直达,找下一个点能否直达 53 | return jump(nums[:i+1], true) 54 | } 55 | return false 56 | } 57 | return true 58 | } 59 | -------------------------------------------------------------------------------- /array/561_array_partition_i.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(arrayPairSum([]int{1, 4, 3, 2})) 10 | } 11 | 12 | // 排序后累加偶数索引上的值,bingo 13 | func arrayPairSum(nums []int) int { 14 | sort.Ints(nums) 15 | sum := 0 16 | for i, num := range nums { 17 | if i%2 == 0 { 18 | sum += num 19 | } 20 | } 21 | return sum 22 | } 23 | -------------------------------------------------------------------------------- /array/566_reshape_the_matrix.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(matrixReshape([][]int{ 7 | {1, 2}, 8 | {3, 4}, 9 | }, 1, 4)) 10 | } 11 | 12 | 13 | // 没什么好说的... 14 | // 将二维数组展开为一维数组,再按段截取 15 | func matrixReshape(nums [][]int, r int, c int) [][]int { 16 | if len(nums) <= 0 || len(nums[0]) <= 0 { 17 | return nil 18 | } 19 | row, column := len(nums), len(nums[0]) 20 | if row*column != r*c { 21 | return nums 22 | } 23 | 24 | allNums := make([]int, 0, row*column) 25 | for _, rowNums := range nums { 26 | allNums = append(allNums, rowNums...) 27 | } 28 | 29 | matrix := make([][]int, r) 30 | for i := 0; i < r; i++ { 31 | matrix[i] = allNums[i*c : (i+1)*c] 32 | } 33 | return matrix 34 | } 35 | -------------------------------------------------------------------------------- /array/581_shortest_unsorted_continuous_subarray.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(findUnsortedSubarray([]int{2, 6, 4, 8, 10, 9, 15})) 10 | fmt.Println(findUnsortedSubarray([]int{2, 1})) 11 | } 12 | 13 | // 先排序,再双指针 ok 14 | func findUnsortedSubarray(nums []int) int { 15 | backup := make([]int, len(nums)) 16 | copy(backup, nums) 17 | 18 | sort.Ints(nums) 19 | start, end := -1, -1 20 | for i, num := range backup { 21 | if nums[i] != num { 22 | start = i 23 | break 24 | } 25 | } 26 | if start == -1 { 27 | return 0 28 | } 29 | 30 | for i := len(backup) - 1; i >= 0; i-- { 31 | if nums[i] != backup[i] { 32 | end = i 33 | break 34 | } 35 | } 36 | 37 | return end - start + 1 38 | } 39 | -------------------------------------------------------------------------------- /array/59_spiral_matrix_ii.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | matrix := generateMatrix(3) 7 | for _, row := range matrix { 8 | for _, num := range row { 9 | fmt.Printf("%d\t", num) // it's ok 10 | } 11 | fmt.Println() 12 | } 13 | } 14 | 15 | // 感觉没啥规律可言啊,只能自己绕圈圈走呗 16 | // 注意换方向时当前行索引的自增、自减 17 | func generateMatrix(n int) [][]int { 18 | matrix := make([][]int, n) 19 | for i := range matrix { 20 | matrix[i] = make([]int, n) 21 | } 22 | 23 | r, c := 0, 0 // 当前行、当前列 24 | for num := 1; num <= n*n; { 25 | // 从左向右 26 | for c < n && matrix[r][c] == 0 { 27 | matrix[r][c] = num 28 | num++ 29 | c++ 30 | } 31 | c-- 32 | r++ 33 | 34 | // 从上到下 35 | for r < n && matrix[r][c] == 0 { 36 | matrix[r][c] = num 37 | num++ 38 | r++ 39 | } 40 | r-- 41 | c-- 42 | 43 | // 从右到左 44 | for c >= 0 && matrix[r][c] == 0 { 45 | matrix[r][c] = num 46 | num++ 47 | c-- 48 | } 49 | r-- 50 | c++ 51 | 52 | // 从下到上 53 | for r >= 0 && matrix[r][c] == 0 { 54 | matrix[r][c] = num 55 | num++ 56 | r-- 57 | } 58 | r++ 59 | c++ 60 | } 61 | return matrix 62 | } 63 | -------------------------------------------------------------------------------- /array/605_can_place_flowers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(canPlaceFlowers([]int{0}, 1)) // true 7 | } 8 | 9 | // 种花的本质是标识 0,即是一边遍历一边修改为 1 10 | func canPlaceFlowers(flowerbed []int, n int) bool { 11 | length := len(flowerbed) 12 | if length == 1 && flowerbed[0] == 0 { 13 | return true 14 | } 15 | 16 | // first blood 17 | if flowerbed[0] == 0 && flowerbed[1] == 0 { 18 | flowerbed[0] = 1 // 种花 19 | n-- 20 | } 21 | for i := 1; i < length; i++ { 22 | // 前后都是 0 就可以种花,注意最后一位的 case 23 | if flowerbed[i-1] == 0 && flowerbed[i] == 0 && (i == length-1 || flowerbed[i+1] == 0) { 24 | flowerbed[i] = 1 25 | n-- 26 | } 27 | } 28 | return n <= 0 29 | } 30 | -------------------------------------------------------------------------------- /array/611_valid_triangle_number.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(triangleNumber([]int{2, 2, 3, 4})) 10 | } 11 | 12 | // 构成三角形的条件:a+b>c, a-b= 0; i-- { 54 | c = cs[i] 55 | bs := counts[c] 56 | for _, b := range bs { 57 | for start, h := range holders { 58 | if h == 0 { // 向后占位 59 | for i := start; c >= 0 && i < len(holders); c-- { 60 | holders[i] = b 61 | i += n + 1 62 | } 63 | break 64 | } 65 | } 66 | } 67 | } 68 | 69 | holders = trimRight(holders) 70 | debug(holders) // A B 0 A B 0 A B 71 | 72 | return len(holders) // 8 73 | } 74 | 75 | func trimRight(bs []byte) []byte { 76 | for i := len(bs) - 1; i >= 0; i-- { 77 | if bs[i] == byte(0) { 78 | bs = bs[:i] 79 | } else { 80 | break 81 | } 82 | } 83 | return bs 84 | } 85 | 86 | func debug(bs []byte) { 87 | s := string(bs) 88 | s = strings.Replace(s, "\x00", "0", -1) 89 | fmt.Println(strings.Join(strings.Split(s, ""), " ")) 90 | } 91 | -------------------------------------------------------------------------------- /array/628_maximum_product_of_three_numbers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(maximumProduct([]int{1, 0, 100})) // 0 10 | fmt.Println(maximumProduct([]int{-4, -3, -2, -1, 60})) // 720 11 | } 12 | 13 | // 注意各种逻辑判断即可 14 | func maximumProduct(nums []int) int { 15 | if len(nums) <= 0 { 16 | return 0 17 | } 18 | 19 | sort.Ints(nums) 20 | maxNegMulti := nums[0] * nums[1] // 最小的两个数之积 21 | 22 | multi := 1 23 | for i := len(nums) - 1; i >= 0 && i > len(nums)-1-3; i-- { 24 | multi *= nums[i] 25 | } 26 | 27 | if maxNegMulti > 0 && multi < maxNegMulti*nums[len(nums)-1] { 28 | return maxNegMulti * nums[len(nums)-1] // 最大负数积乘最大正数 29 | } 30 | 31 | return multi 32 | } 33 | -------------------------------------------------------------------------------- /array/62_unique_paths.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(uniquePaths(7, 3)) // 7列 3行 7 | } 8 | 9 | // 感觉是个数学问题 10 | func uniquePaths(m int, n int) int { 11 | paths := make([][]int, n) 12 | for i := range paths { 13 | paths[i] = make([]int, m) 14 | } 15 | 16 | for r := n - 1; r >= 0; r-- { 17 | paths[r][m-1] = 1 18 | } 19 | for c := m - 1; c >= 0; c-- { 20 | paths[n-1][c] = 1 21 | } 22 | 23 | for r := n - 1 - 1; r >= 0; r-- { // 从倒数第二行向前 24 | for c := m - 1 - 1; c >= 0; c-- { // 每行从后向前走 25 | paths[r][c] = paths[r][c+1] + paths[r+1][c] 26 | } 27 | } 28 | 29 | // fmt.Println(paths) 30 | // [28 21 15 10 6 3 1] 31 | // [7 6 5 4 3 2 1] 32 | // [1 1 1 1 1 1 1] 33 | return paths[0][0] 34 | } 35 | -------------------------------------------------------------------------------- /array/643_maximum_average_subarray_i.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(findMaxAverage([]int{0, 1, 1, 3, 3}, 4)) 7 | } 8 | 9 | // 固定长度的子序列求和,像尺子上的蚯蚓一样向前挪... 10 | func findMaxAverage(nums []int, k int) float64 { 11 | sum := 0 12 | for i := 0; i < k; i++ { 13 | sum += nums[i] 14 | } 15 | 16 | maxSum := sum 17 | for i := k; i < len(nums); i++ { 18 | // 挪动... 19 | sum += nums[i] 20 | sum -= nums[i-k] 21 | if sum > maxSum { 22 | maxSum = sum 23 | } 24 | } 25 | return float64(maxSum) / float64(k) 26 | } 27 | -------------------------------------------------------------------------------- /array/64_minimum_path_sum.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | fmt.Println(minPathSum([][]int{ 9 | {1, 3, 1}, 10 | {1, 5, 1}, 11 | {4, 2, 1}, 12 | })) 13 | } 14 | 15 | // 考虑使用递归实现,到达 grid[i][j] 的最小路径为到达 grid[i-1][j] 和 grid[i][j-1] 的最小值 16 | // 但递归不保存任何已计算出的结果,效率不高,类比斐波那契数列的递归实现 17 | // 使用简单的动态规划,即保存中间计算结果 18 | func minPathSum(grid [][]int) int { 19 | if len(grid) <= 0 || len(grid[0]) <= 0 { 20 | return 0 21 | } 22 | 23 | row, column := len(grid), len(grid[0]) 24 | steps := make([][]int, row) // 存储到达 [i,j] 的最少步数 25 | for i := range steps { 26 | steps[i] = make([]int, column) 27 | } 28 | steps[0][0] = grid[0][0] 29 | 30 | // 只能向下或向左移动,先求解简单值 31 | // 首行 32 | for c := 1; c < column; c++ { 33 | steps[0][c] = grid[0][c] + steps[0][c-1] 34 | } 35 | // 首列 36 | for r := 1; r < row; r++ { 37 | steps[r][0] = grid[r][0] + steps[r-1][0] 38 | } 39 | 40 | // 再根据简单值,逐步求解复杂值 41 | // 从 [1][1] 开始走到右下顶点 42 | for r := 1; r < row; r++ { 43 | for c := 1; c < column; c++ { 44 | // 从上方,左方选最小的权值 45 | steps[r][c] = min(steps[r-1][c], steps[r][c-1]) + grid[r][c] 46 | } 47 | } 48 | 49 | return steps[row-1][column-1] // 累加到右下角的值是最小权值 50 | } 51 | 52 | func min(x, y int) int { 53 | if x > y { 54 | return y 55 | } 56 | return x 57 | } 58 | -------------------------------------------------------------------------------- /array/661_image_smoother.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | m := [][]int{ 7 | // {1, 1, 1}, 8 | // {1, 0, 1}, 9 | // {1, 1, 1}, 10 | 11 | {2, 3, 4}, 12 | {5, 6, 7}, 13 | {8, 9, 10}, 14 | {11, 12, 13}, 15 | {14, 15, 16}, 16 | // [[4 4 5] [5 6 6] [8 9 9] [11 12 12] [13 13 14]] 17 | } 18 | fmt.Println(imageSmoother(m)) 19 | } 20 | 21 | // 免不了一堆判断,取周边和再求平均值 22 | func imageSmoother(M [][]int) [][]int { 23 | if len(M) <= 0 || len(M[0]) <= 0 { 24 | return nil 25 | } 26 | r, c := len(M), len(M[0]) 27 | res := make([][]int, r) 28 | for i := 0; i < r; i++ { 29 | res[i] = make([]int, c) 30 | } 31 | for i := 0; i < r; i++ { 32 | for j := 0; j < c; j++ { 33 | sum := M[i][j] 34 | k := 1 35 | if i > 0 { 36 | sum += M[i-1][j] 37 | k++ 38 | } 39 | if i < r-1 { 40 | sum += M[i+1][j] 41 | k++ 42 | } 43 | if j > 0 { 44 | sum += M[i][j-1] 45 | k++ 46 | } 47 | if j < c-1 { 48 | sum += M[i][j+1] 49 | k++ 50 | } 51 | if i > 0 && j > 0 { 52 | sum += M[i-1][j-1] 53 | k++ 54 | } 55 | if i > 0 && j < c-1 { 56 | sum += M[i-1][j+1] 57 | k++ 58 | } 59 | if i < r-1 && j > 0 { 60 | sum += M[i+1][j-1] 61 | k++ 62 | } 63 | if i < r-1 && j < c-1 { 64 | sum += M[i+1][j+1] 65 | k++ 66 | } 67 | res[i][j] = sum / k 68 | } 69 | } 70 | return res 71 | } 72 | -------------------------------------------------------------------------------- /array/665_non_decreasing_array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(checkPossibility([]int{3, 4, 2, 3})) // false 7 | fmt.Println(checkPossibility([]int{1, 4, 2, 3})) // true 8 | } 9 | 10 | func checkPossibility(nums []int) bool { 11 | smallCount := 0 12 | for i := 1; i < len(nums); i++ { 13 | if nums[i-1] > nums[i] { 14 | if smallCount == 1 { 15 | return false 16 | } 17 | 18 | // 巧妙一步:如果 i-2 的数比 i 的大,就向后延续大数的影响范围 19 | // 3 4 2 3 // 3 4 4 3 20 | // 1 4 2 3 // 1 4 2 3 21 | if i >= 2 && nums[i-2] >= nums[i] { 22 | nums[i] = nums[i-1] 23 | } 24 | // fmt.Println(nums) 25 | smallCount++ 26 | } 27 | } 28 | return true 29 | } 30 | -------------------------------------------------------------------------------- /array/66_plus_one.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | // fmt.Println(plusOne([]int{7, 2, 8, 5, 0, 9, 1, 2, 9, 5, 3, 6, 6, 7, 3, 2, 8, 4, 3, 7, 9, 5, 7, 7, 4, 7, 4, 9, 4, 7, 0, 1, 1, 1, 7, 4, 0, 0, 6})) 9 | fmt.Println(plusOne([]int{4, 3, 2, 1})) 10 | fmt.Println(plusOne([]int{9})) 11 | } 12 | 13 | // 若用 10 的次方做位数,聚合后再拆解,不确定长度的整数一定要考虑溢出,一旦溢出结果必定出错 14 | func plusOne(digits []int) []int { 15 | n := len(digits) 16 | if digits[n-1]+1 < 10 { 17 | digits[n-1]++ 18 | } else { 19 | for i := n - 1; i >= 0; i-- { 20 | if digits[i]+1 < 10 { 21 | digits[i]++ 22 | break 23 | } 24 | digits[i] = 0 25 | if i == 0 { 26 | digits = append([]int{1}, digits...) 27 | } 28 | } 29 | } 30 | return digits 31 | } 32 | -------------------------------------------------------------------------------- /array/674__longest_continuous_increasing_subsequence.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(findLengthOfLCIS([]int{1, 3, 5, 4, 7})) // 3 7 | fmt.Println(findLengthOfLCIS([]int{2, 2, 2, 2, 2})) // 1 8 | } 9 | 10 | // 不要把题意理解成找分差不为 0 的最长等差数列。。。 11 | // 依旧双指针 12 | func findLengthOfLCIS(nums []int) int { 13 | n := len(nums) 14 | if n <= 1 { 15 | return len(nums) 16 | } 17 | slow := 0 18 | maxCount := 0 19 | for slow < n-1 { 20 | count := 1 21 | fast := slow 22 | for fast < n-1 && nums[fast] < nums[fast+1] { 23 | count++ 24 | fast++ 25 | } 26 | slow++ 27 | if count > maxCount { 28 | maxCount = count 29 | } 30 | } 31 | return maxCount 32 | } 33 | -------------------------------------------------------------------------------- /array/697_degree_of_an_array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(findShortestSubArray([]int{1, 2, 2, 3, 1})) // 2 7 | fmt.Println(findShortestSubArray([]int{1, 2, 2, 3, 1, 4, 2})) // 6 8 | } 9 | 10 | 11 | // 辣鸡解法 12 | func findShortestSubArray(nums []int) int { 13 | degrees := make(map[int]int) 14 | for _, num := range nums { 15 | degrees[num]++ 16 | } 17 | maxDegree := 1 18 | var targets []int 19 | for num, degree := range degrees { 20 | if degree >= maxDegree { 21 | maxDegree = degree 22 | targets = append(targets, num) 23 | } 24 | } 25 | 26 | // fmt.Println("maxDegree", maxDegree) 27 | minLen := len(nums) 28 | for _, target := range targets { 29 | for i, num := range nums { 30 | if num == target { 31 | subLen := 1 32 | numCount := 1 33 | for j := i + 1; j < len(nums); j++ { 34 | subLen++ 35 | if nums[j] == target { 36 | numCount++ 37 | } 38 | if numCount >= maxDegree { 39 | break 40 | } 41 | } 42 | // fmt.Println(num, numCount, maxDegree, subLen, minLen) 43 | if numCount >= maxDegree && subLen < minLen { 44 | minLen = subLen 45 | } 46 | } 47 | } 48 | } 49 | return minLen 50 | } 51 | -------------------------------------------------------------------------------- /array/718_maximum_length_of_repeated_subarray.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(findLength([]int{0, 1, 1, 1, 1}, []int{1, 0, 1, 0, 1})) // 2 7 | fmt.Println(findLength([]int{0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, []int{0, 0, 0, 0, 0, 0, 0, 1, 0, 0})) // 9 8 | } 9 | 10 | // 最直观也是最辣鸡的做法 11 | func findLength(A []int, B []int) int { 12 | m := make(map[int][]int) 13 | for i, b := range B { 14 | m[b] = append(m[b], i) // 存储 B 数组中所有元素的索引 15 | } 16 | 17 | maxLen := 0 18 | for i, a := range A { 19 | if _, ok := m[a]; !ok { // 不存在与 B 数组中 20 | continue 21 | } 22 | // 向后遍历 23 | for _, start := range m[a] { 24 | curLen := 0 25 | ai := i 26 | for bi := start; ai < len(A) && bi < len(B); ai, bi = ai+1, bi+1 { // 连续相同的子数组计数 27 | if A[ai] != B[bi] { 28 | break 29 | } 30 | curLen++ 31 | } 32 | if maxLen < curLen { 33 | maxLen = curLen 34 | } 35 | } 36 | } 37 | 38 | return maxLen 39 | } 40 | -------------------------------------------------------------------------------- /array/724_find_pivot_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(pivotIndex([]int{1, 7, 3, 6, 5, 6})) // 3 7 | fmt.Println(pivotIndex([]int{1, 2, 3})) // -1 8 | fmt.Println(pivotIndex([]int{-1, -1, -1, -1, -1, 0})) // 2 9 | fmt.Println(pivotIndex([]int{-1, -1, -1, -1, 0, -1})) // 2 10 | } 11 | 12 | // 左右两端和相等,双指针向中间遍历 13 | // 这里的指针不是索引,而是递增和、递减和 14 | func pivotIndex(nums []int) int { 15 | n := len(nums) 16 | if n <= 2 { 17 | return -1 18 | } 19 | sum := 0 20 | for i := 0; i < n; i++ { 21 | sum += nums[i] 22 | } 23 | 24 | leftSum := 0 25 | for i := 0; i < n; i++ { 26 | if leftSum == sum-nums[i]-leftSum { 27 | return i 28 | } 29 | leftSum += nums[i] 30 | } 31 | return -1 32 | } 33 | -------------------------------------------------------------------------------- /array/73_set_matrix_zeroes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | matrix := [][]int{ 7 | // {1, 1, 1}, 8 | // {1, 0, 1}, 9 | // {1, 1, 1}, 10 | 11 | {0, 1, 2, 0}, 12 | {3, 4, 5, 2}, 13 | {1, 3, 1, 5}, 14 | } 15 | setZeroes(matrix) 16 | 17 | fmt.Println(matrix) // [[0 0 0 0] [0 4 5 0] [0 3 1 0]] 18 | } 19 | 20 | func setZeroes(matrix [][]int) { 21 | rows := make(map[int]int) 22 | columns := make(map[int]int) 23 | for i := range matrix { 24 | for j, num := range matrix[i] { 25 | if num == 0 { 26 | rows[i] ++ 27 | columns[j]++ 28 | } 29 | } 30 | } 31 | for r := range rows { 32 | for c := range matrix[0] { 33 | matrix[r][c] = 0 34 | } 35 | } 36 | for c := range columns { 37 | for r := range matrix { 38 | matrix[r][c] = 0 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /array/747_largest_number_at_least_twice_of_others.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(dominantIndex([]int{3, 6, 1, 0})) // 1 10 | fmt.Println(dominantIndex([]int{1, 2, 3, 4})) // 1 11 | } 12 | 13 | // 辣鸡解法 14 | func dominantIndex(nums []int) int { 15 | n := len(nums) 16 | if n <= 1 { 17 | return 0 18 | } 19 | m := make(map[int]int) 20 | for i, num := range nums { 21 | m[num] = i 22 | } 23 | sort.Ints(nums) 24 | if nums[n-1] >= 2*nums[n-2] { 25 | return m[nums[n-1]] 26 | } 27 | return -1 28 | } 29 | -------------------------------------------------------------------------------- /array/766_toeplitz_matrix.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(isToeplitzMatrix([][]int{ 7 | // {1, 2, 3, 4}, 8 | // {5, 1, 2, 3}, 9 | // {9, 5, 1, 2}, 10 | 11 | // {1, 2}, 12 | // {2, 2}, 13 | {36, 59, 71, 15, 26, 82, 87}, 14 | {56, 36, 59, 71, 15, 26, 82}, 15 | {15, 0, 36, 59, 71, 15, 26}, 16 | })) 17 | } 18 | 19 | // 遍历第一行,对角线检测 20 | // 遍历第一列,对角线检测 21 | // 注意 2 个边界可以少检测 2 次 22 | func isToeplitzMatrix(matrix [][]int) bool { 23 | if len(matrix) <= 1 || len(matrix[0]) <= 1 { 24 | return true 25 | } 26 | 27 | rows, column := len(matrix), len(matrix[0]) 28 | // 横向检测 29 | for i := 0; i < column-1; i++ { 30 | x, y := 0, i 31 | for x+1 < rows && y+1 < column { 32 | if matrix[x][y] != matrix[x+1][y+1] { 33 | return false 34 | } 35 | x++ 36 | y++ 37 | } 38 | } 39 | // 竖向检测 40 | for i := 1; i < rows-1; i++ { 41 | x, y := i, 0 42 | for x+1 < rows && y+1 < column { 43 | if matrix[x][y] != matrix[x+1][y+1] { 44 | return false 45 | } 46 | x++ 47 | y++ 48 | } 49 | } 50 | return true 51 | } 52 | -------------------------------------------------------------------------------- /array/769_max_chunks_to_make_sorted.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(maxChunksToSorted([]int{4, 3, 2, 1, 0})) // 1 7 | fmt.Println(maxChunksToSorted([]int{1, 0, 2, 3, 4})) // 4 8 | } 9 | 10 | // 规律性很强 11 | // 对长度为 n 的排列 [0,..., n-1] 要敏感一些 12 | func maxChunksToSorted(arr []int) int { 13 | max := arr[0] 14 | count := 0 15 | for i, n := range arr { 16 | if n > max { 17 | max = n 18 | } 19 | if max == i { 20 | count++ // 子区间最大值是当前索引,则为独立空间 21 | } 22 | } 23 | return count 24 | } 25 | -------------------------------------------------------------------------------- /array/76_sort_colors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | colors := []int{2, 0, 2, 1, 1, 0} 5 | sortColors(colors) 6 | } 7 | 8 | // 计数...遍历,计数不要一上来就是哈希表,把问题搞复杂了 9 | func sortColors(nums []int) { 10 | zero, one, two := 0, 0, 0 11 | for _, num := range nums { 12 | switch num { 13 | case 0: 14 | zero++ 15 | case 1: 16 | one++ 17 | case 2: 18 | two++ 19 | } 20 | } 21 | for i := 0; i < zero; i++ { 22 | nums[i] = 0 23 | } 24 | for i := zero; i < zero+one; i++ { 25 | nums[i] = 1 26 | } 27 | for i := zero + one; i < len(nums); i++ { 28 | nums[i] = 2 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /array/78_subsets.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(subsets([]int{1, 2, 3})) 7 | fmt.Println(subsets([]int{1, 2, 3, 4})) 8 | } 9 | 10 | // 自创的 4ms 解法阿西吧 11 | // 理解子集的本质,N 个数有 1~N 种组合方式 12 | // 可以直接从后向前遍历,每遇到一个数就把它与所有的现有子集重新 append 成新子集 13 | // 遍历完毕就是所有子集 14 | // 我觉得 ok 15 | func subsets(nums []int) [][]int { 16 | n := len(nums) 17 | seqs := make([][]int, 1) 18 | seqs = append(seqs, []int{nums[n-1]}) 19 | 20 | for i := n - 2; i >= 0; i-- { 21 | for _, seq := range seqs { 22 | nextSeq := append([]int{nums[i]}, seq...) 23 | seqs = append(seqs, nextSeq) 24 | } 25 | } 26 | 27 | return seqs 28 | } 29 | -------------------------------------------------------------------------------- /array/830_positions_of_large_groups.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(largeGroupPositions("aaa")) // [[0,2]] 7 | fmt.Println(largeGroupPositions("abbxxxxzzy")) // [[3,6]] 8 | fmt.Println(largeGroupPositions("abcdddeeeeaabbbcd")) // [[3,5] [6,9] [12,14]] 9 | } 10 | 11 | func largeGroupPositions(S string) [][]int { 12 | n := len(S) 13 | if n <= 2 { 14 | return nil 15 | } 16 | 17 | var locs [][]int 18 | slow, fast := 0, 0 19 | for slow < n { 20 | for fast < n && S[fast] == S[slow] { 21 | fast++ // 注意跳出循环时 S[fast] != S[slow] 22 | } 23 | if fast-slow >= 3 { 24 | locs = append(locs, []int{slow, fast - 1}) 25 | } 26 | 27 | if fast > slow { 28 | slow = fast - 1 // 抵消下边一般 case 的 +1 29 | } 30 | slow++ 31 | fast = slow 32 | } 33 | return locs 34 | } 35 | -------------------------------------------------------------------------------- /array/835_image_overlap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | a := [][]int{ 7 | {1, 1, 0}, 8 | {0, 1, 0}, 9 | {0, 1, 0}, 10 | } 11 | b := [][]int{ 12 | {0, 0, 0}, 13 | {0, 1, 1}, 14 | {0, 0, 1}, 15 | } 16 | fmt.Println(largestOverlap(a, b)) // 3 17 | } 18 | 19 | // n <= 30,暴力遍历可接受 20 | func largestOverlap(A [][]int, B [][]int) int { 21 | max := 0 22 | n := len(A) 23 | for i := 0; i < n; i++ { 24 | for j := 0; j < n; j ++ { 25 | 26 | countA, countB := 0, 0 27 | for r := i; r < n; r++ { 28 | for c := j; c < n; c++ { 29 | 30 | preR, preC := r-i, c-j 31 | if A[r][c] == 1 && B[preR][preC] == 1 { // 重复且为 1 的位置计数 32 | countA += 1 33 | } 34 | if B[r][c] == 1 && A[preR][preC] == 1 { 35 | countB += 1 36 | } 37 | } 38 | } 39 | 40 | if countA > max { 41 | max = countA 42 | } 43 | if countB > max { 44 | max = countB 45 | } 46 | } 47 | } 48 | return max 49 | } 50 | -------------------------------------------------------------------------------- /array/840_magic_squares_in_grid.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(numMagicSquaresInside([][]int{ 7 | {4, 3, 8, 4}, 8 | {9, 5, 1, 9}, 9 | {2, 7, 6, 2}, 10 | })) 11 | 12 | } 13 | 14 | // 1~9 去填充 9 个格子,横、竖、对角线三个方向的和要一致,中间值必须为 5,其余方向的两个数和必须为 10,总和必须为 15 15 | // 代码也是绕得慌... 16 | func numMagicSquaresInside(grid [][]int) int { 17 | if len(grid) < 3 { 18 | return 0 19 | } 20 | 21 | r, c := len(grid)-1, len(grid[0])-1 22 | counts := 0 23 | for i := 1; i < r; i++ { 24 | for j := 1; j < c; j++ { 25 | if grid[i][j] != 5 { 26 | continue 27 | } 28 | 29 | ok := true 30 | m := make([]bool, 9) 31 | m[4] = true 32 | offsets := [][]int{{-1, -1}, {-1, 0}, {0, -1}, {-1, 1}} // 八个方向 33 | 34 | for _, offset := range offsets { 35 | v1 := grid[i+offset[0]][j+offset[1]] 36 | v2 := grid[i-offset[0]][j-offset[1]] 37 | if v1 < 1 || v1 > 9 || v2 < 1 || v2 > 9 || v1+v2 != 10 || m[v1-1] || m[v2-1] { 38 | ok = false 39 | break 40 | } 41 | m[v1-1], m[v2-1] = true, true 42 | } 43 | if ok { 44 | counts++ 45 | } 46 | } 47 | } 48 | return counts 49 | } 50 | -------------------------------------------------------------------------------- /array/849_maximize_distance_to_closest_person.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(maxDistToClosest([]int{1, 0, 0, 0, 1, 0, 1})) // 2 7 | fmt.Println(maxDistToClosest([]int{1, 0, 0, 0})) // 3 8 | fmt.Println(maxDistToClosest([]int{0, 1})) // 1 9 | fmt.Println(maxDistToClosest([]int{0, 1, 1, 1, 0, 0, 1, 0, 0})) // 2 10 | fmt.Println(maxDistToClosest([]int{0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0})) // 3 11 | } 12 | 13 | // 找到最长的 0 序列,按序列边界是否为 1 来决定取中点还是边界 14 | // 双指针 15 | // 辣鸡解法 16 | func maxDistToClosest(seats []int) int { 17 | n := len(seats) 18 | if n <= 0 { 19 | return n 20 | } 21 | 22 | // 0 开头或 0 结尾的两种特殊 case 23 | maxStart, maxEnd := 0, 0 24 | if seats[0] == 0 { 25 | for i := 0; i < n && seats[i] == 0; i++ { 26 | maxStart++ 27 | } 28 | } 29 | if seats[n-1] == 0 { 30 | for i := n - 1; i >= 0 && seats[i] == 0; i-- { 31 | maxEnd ++ 32 | } 33 | } 34 | 35 | // 快慢指针找出位于中间的最长 0 序列 36 | slow := 0 37 | zeroEdges := make([]int, 2) 38 | for slow < n { 39 | fast := slow 40 | for fast < n && seats[fast] == 0 { 41 | fast++ 42 | } 43 | if fast-1 > slow { 44 | if fast-1-slow > zeroEdges[1]-zeroEdges[0] { 45 | zeroEdges[0], zeroEdges[1] = slow, fast-1 46 | } 47 | } 48 | slow++ 49 | } 50 | 51 | return max(maxStart, maxEnd, (zeroEdges[1]-zeroEdges[0])/2+1) 52 | } 53 | 54 | func max(x, y, z int) int { 55 | if x > y { 56 | if x > z { 57 | return x 58 | } 59 | return z 60 | } else { 61 | if y > z { 62 | return y 63 | } 64 | return z 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /array/867_transpose_matrix.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(transpose([][]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}})) 7 | fmt.Println(transpose([][]int{{1, 2, 3}, {4, 5, 6}})) 8 | } 9 | 10 | func transpose(A [][]int) [][]int { 11 | if len(A) <= 0 { 12 | return A 13 | } 14 | n, m := len(A), len(A[0]) 15 | res := make([][]int, m) // 新行数取原列数 16 | for i := 0; i < n; i++ { 17 | for j := 0; j < m; j++ { 18 | res[j] = append(res[j], A[i][j]) 19 | } 20 | } 21 | return res 22 | } 23 | -------------------------------------------------------------------------------- /array/888_fair_candy_swap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | fmt.Println(fairCandySwap([]int{1, 2, 5}, []int{2, 4})) // [5,4] 9 | fmt.Println(fairCandySwap([]int{1, 1}, []int{2, 2})) // [2,1] 10 | fmt.Println(fairCandySwap([]int{32, 38, 8, 1, 9}, []int{63, 92})) 11 | } 12 | 13 | // 交换 a,b 后 sumA==sumB,和大的数组相当于捡了芝麻丢了西瓜,有个两倍的关系在里边 14 | func fairCandySwap(A []int, B []int) []int { 15 | sumA, sumB := sum(A), sum(B) 16 | diff := abs(sumA-sumB) / 2 17 | 18 | m := make(map[int]int) 19 | for _, b := range B { 20 | m[b]++ 21 | } 22 | 23 | for _, a := range A { 24 | target := a - diff 25 | if sumA < sumB { 26 | target = a + diff 27 | } 28 | if _, ok := m[target]; ok { 29 | return []int{a, target} 30 | } 31 | } 32 | return nil 33 | } 34 | 35 | func sum(nums []int) (res int) { 36 | for _, num := range nums { 37 | res += num 38 | } 39 | return 40 | } 41 | 42 | func abs(x int) int { 43 | if x < 0 { 44 | return -x 45 | } 46 | return x 47 | } 48 | -------------------------------------------------------------------------------- /array/88_merge_sorted_array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | nums1 := []int{2} 7 | nums2 := []int{} 8 | merge(nums1, 1, nums2, 0) 9 | fmt.Println(nums1) 10 | } 11 | 12 | // 两个指针指向两个数组,分别向后遍历 13 | // 注意解决未遍历完的数组 14 | func merge(nums1 []int, m int, nums2 []int, n int) { 15 | cpNums := make([]int, 0, m+n) 16 | copy(cpNums, nums1) 17 | 18 | p1, p2 := 0, 0 19 | nums := nums1[:m] 20 | for p1 < m && p2 < n { 21 | if nums[p1] < nums2[p2] { 22 | cpNums = append(cpNums, nums[p1]) 23 | p1++ 24 | } else { 25 | cpNums = append(cpNums, nums2[p2]) 26 | p2++ 27 | } 28 | } 29 | 30 | if p1 < m { 31 | cpNums = append(cpNums, nums[p1:]...) 32 | } 33 | if p2 < n { 34 | cpNums = append(cpNums, nums2[p2:]...) 35 | } 36 | 37 | for i, num := range cpNums { 38 | nums1[i] = num // 函数内部修改 slice 只能之指定索引修改,与指定传指针原理相同 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /array/896_monotonic_array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(isMonotonic([]int{1, 2, 2, 3})) // true 7 | fmt.Println(isMonotonic([]int{1})) // true 8 | } 9 | 10 | func isMonotonic(A []int) bool { 11 | isUp, isDown := true, true 12 | for i := 0; i < len(A)-1; i++ { 13 | if A[i] > A[i+1] { 14 | isUp = false 15 | } 16 | if A[i] < A[i+1] { 17 | isDown = false 18 | } 19 | if !isUp && !isDown { // 优化:提前结束遍历 20 | return false 21 | } 22 | } 23 | return isUp || isDown 24 | } 25 | -------------------------------------------------------------------------------- /array/905_sort_array_by_parit.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(sortArrayByParity([]int{3, 1, 2, 4})) 7 | } 8 | 9 | // 简单的逻辑... 10 | func sortArrayByParity(A []int) []int { 11 | isOdd := func(x int) bool { 12 | return x%2 == 1 13 | } 14 | odds := make([]int, 0, len(A)) 15 | evens := make([]int, 0, len(A)) 16 | for _, a := range A { 17 | if isOdd(a) { 18 | odds = append(odds, a) 19 | continue 20 | } 21 | evens = append(evens, a) 22 | } 23 | return append(evens, odds...) 24 | } 25 | -------------------------------------------------------------------------------- /array/914_x_of_a_kind_in_a_deck_of_cards.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(hasGroupsSizeX([]int{1, 1, 1, 2, 2, 2, 3, 3})) // false 7 | fmt.Println(hasGroupsSizeX([]int{1, 1, 1, 1, 2, 2, 2, 2, 2, 2})) // true 8 | 9 | } 10 | 11 | // 统计各个数字出现的频率,看下频率之间是否能分组(存在公约数) 12 | // 关键要理解分组等价于是否存在公约数 13 | func hasGroupsSizeX(deck []int) bool { 14 | if len(deck) <= 1 { 15 | return false 16 | } 17 | 18 | freqs := make(map[int]int) 19 | for _, num := range deck { 20 | freqs[num]++ 21 | } 22 | 23 | counts := make([]int, 0, len(freqs)) 24 | for _, freq := range freqs { 25 | counts = append(counts, freq) 26 | } 27 | 28 | for i := 0; i < len(counts)-1; i++ { 29 | if gcd(counts[i], counts[i+1]) == 1 { // 不能分组 30 | return false 31 | } 32 | } 33 | 34 | return true 35 | } 36 | 37 | // 辗转相除法求最大公约数 38 | func gcd(x, y int) int { 39 | // for y != 0 { 40 | // x, y = y, x%y 41 | // } 42 | // return x 43 | 44 | if y == 0 { 45 | return x 46 | } 47 | return gcd(y, x%y) 48 | } 49 | -------------------------------------------------------------------------------- /array/915_partition_array_into_disjoint_intervals.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(partitionDisjoint([]int{5, 0, 3, 8, 6})) // 3 7 | } 8 | 9 | // 按题的描述 10 | // 用两个 max 变量记录左侧最大值和数组最大值,类似快慢指针的思路 11 | func partitionDisjoint(A []int) int { 12 | leftMax, curMax, edge := A[0], A[0], 1 13 | for i, a := range A { 14 | // fmt.Println("a", a, "leftMax", leftMax, "curMax", curMax) 15 | if leftMax > a { // 比左侧最大值还小,左小数组向右拉长 16 | leftMax = curMax // 目前的最大值同步到 leftMax 17 | edge = i + 1 18 | } 19 | if a > curMax { 20 | curMax = a 21 | } 22 | } 23 | return edge 24 | } 25 | -------------------------------------------------------------------------------- /array/utils.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func min(vs ...int) int { 4 | if len(vs) == 0 { 5 | panic("func min args empty") 6 | } 7 | m := vs[0] 8 | for _, n := range vs[1:] { 9 | if n < m { 10 | m = n 11 | } 12 | } 13 | return m 14 | } 15 | 16 | func max(vs ...int) int { 17 | if len(vs) == 0 { 18 | panic("func min args empty") 19 | } 20 | m := vs[0] 21 | for _, n := range vs[1:] { 22 | if n > m { 23 | m = n 24 | } 25 | } 26 | return m 27 | } 28 | 29 | func abs(x int) int { 30 | if x < 0 { 31 | return -x 32 | } 33 | return x 34 | } 35 | 36 | func reverse(nums []int) { 37 | for l, r := 0, len(nums)-1; l < r; l, r = l+1, r-1 { 38 | nums[l], nums[r] = nums[r], nums[l] 39 | } 40 | } 41 | 42 | // 递归版的二分查找虽高效,但调用传参时注意,nums 为空时 l,r 应为 0,-1,否则将 panic 43 | func binarySearch(nums []int, l, r int, target int) int { 44 | if l > r { 45 | return -1 46 | } 47 | 48 | mid := (l + r) / 2 49 | switch { 50 | case target < nums[mid]: 51 | return binarySearch(nums, l, mid-1, target) 52 | case target > nums[mid]: 53 | return binarySearch(nums, mid+1, r, target) 54 | default: 55 | return mid 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /design/lfu_cache.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | c := Constructor(2) 7 | c.Put(1, 1) // 1: 1 8 | c.Put(2, 2) // 1: 2->1 9 | fmt.Println(c.Get(1)) // 1: 1->2 10 | c.Put(3, 3) // 2 失效 11 | fmt.Println(c.Get(2)) // -1 12 | fmt.Println(c.Get(3)) // 1: 3->1 13 | c.Put(4, 4) // 1 失效 // 1: 4->3 14 | fmt.Println(c.Get(1)) // -1 15 | fmt.Println(c.Get(3)) // 1: 3->4 16 | fmt.Println(c.Get(4)) // 1: 4->3 17 | } 18 | 19 | type LFUCache struct { 20 | capacity int 21 | minFreq int 22 | items map[int]*Node 23 | freqs map[int]*List 24 | } 25 | 26 | func Constructor(capacity int) LFUCache { 27 | return LFUCache{ 28 | capacity: capacity, 29 | minFreq: 0, 30 | items: make(map[int]*Node), 31 | freqs: make(map[int]*List), 32 | } 33 | } 34 | 35 | func (this *LFUCache) Get(k int) int { 36 | // 未命中 37 | node, ok := this.items[k] 38 | if !ok { 39 | return -1 40 | } 41 | 42 | // 命中 43 | this.freqs[node.freq].Remove(node) // 挪动到下一频率梯队 44 | node.freq++ 45 | if _, ok := this.freqs[node.freq]; !ok { 46 | this.freqs[node.freq] = NewList() 47 | } 48 | newNode := this.freqs[node.freq].Prepend(node) 49 | this.items[k] = newNode 50 | // 注意判断最小梯队 51 | if this.freqs[this.minFreq].Size() == 0 { 52 | this.minFreq++ 53 | } 54 | return node.val 55 | } 56 | 57 | func (this *LFUCache) Put(key, value int) { 58 | if this.capacity == 0 { 59 | return 60 | } 61 | // 命中 62 | if val := this.Get(key); val != -1 { 63 | this.items[key].val = value 64 | return 65 | } 66 | 67 | // 缓存已满 68 | if this.capacity == len(this.items) { 69 | oldest := this.freqs[this.minFreq].Tail() 70 | this.freqs[this.minFreq].Remove(oldest) 71 | delete(this.items, oldest.key) 72 | } 73 | 74 | node := &Node{key: key, val: value, freq: 1} 75 | this.items[key] = node 76 | if _, ok := this.freqs[1]; !ok { 77 | this.freqs[1] = NewList() 78 | } 79 | this.freqs[1].Prepend(node) 80 | this.minFreq = 1 81 | } 82 | 83 | type Node struct { 84 | key int 85 | val int 86 | freq int 87 | prev, next *Node 88 | } 89 | 90 | type List struct { 91 | head, tail *Node 92 | size int 93 | } 94 | 95 | func NewList() *List { 96 | return new(List) 97 | } 98 | 99 | func (l *List) Prepend(node *Node) *Node { 100 | if l.head == nil { 101 | l.head = node 102 | l.tail = node 103 | } else { 104 | node.prev = nil 105 | node.next = l.head 106 | l.head.prev = node 107 | l.head = node 108 | } 109 | l.size++ 110 | return l.head 111 | } 112 | 113 | func (l *List) Remove(node *Node) *Node { 114 | if node == nil { 115 | return nil 116 | } 117 | 118 | prev, next := node.prev, node.next 119 | if prev == nil { 120 | l.head = next 121 | } else { 122 | prev.next = next 123 | } 124 | 125 | if next == nil { 126 | l.tail = prev 127 | } else { 128 | next.prev = prev 129 | } 130 | 131 | node.prev, node.next = nil, nil 132 | l.size-- 133 | return node 134 | } 135 | 136 | func (l *List) Size() int { 137 | return l.size 138 | } 139 | 140 | func (l *List) Tail() *Node { 141 | return l.tail 142 | } 143 | -------------------------------------------------------------------------------- /design/lru_cache.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "container/list" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | lru := Constructor(2) 10 | lru.Put(1, 1) 11 | lru.Put(2, 2) 12 | fmt.Println(lru.Get(1)) // 1 13 | lru.Put(3, 3) // 2 作废 14 | fmt.Println(lru.Get(2)) // -1 15 | lru.Put(4, 4) // 1 作废 16 | fmt.Println(lru.Get(1)) // -1 17 | fmt.Println(lru.Get(3)) // 3 18 | fmt.Println(lru.Get(4)) // 4 19 | } 20 | 21 | type CacheItem struct { 22 | k, v int 23 | } 24 | 25 | type LRUCache struct { 26 | limit int 27 | items *list.List 28 | cache map[int]*list.Element 29 | } 30 | 31 | func Constructor(capacity int) LRUCache { 32 | return LRUCache{ 33 | limit: capacity, 34 | items: list.New(), 35 | cache: make(map[int]*list.Element), 36 | } 37 | } 38 | 39 | func (this *LRUCache) Put(key, value int) { 40 | // 命中 41 | if elem, ok := this.cache[key]; ok { 42 | this.items.MoveToFront(elem) 43 | elem.Value.(*CacheItem).v = value // 更新缓存值 44 | return 45 | } 46 | 47 | // 未命中 48 | newItem := &CacheItem{k: key, v: value} 49 | newElem := this.items.PushFront(newItem) 50 | this.cache[key] = newElem 51 | 52 | // 超过缓存容量 53 | if this.items.Len() > this.limit { 54 | oldest := this.items.Back() 55 | delete(this.cache, oldest.Value.(*CacheItem).k) // 移除最少使用的 item 56 | this.items.Remove(oldest) 57 | } 58 | } 59 | 60 | func (this *LRUCache) Get(key int) int { 61 | if elem, ok := this.cache[key]; ok { // 命中 62 | this.items.MoveToFront(elem) 63 | return elem.Value.(*CacheItem).v 64 | } 65 | 66 | return -1 67 | } 68 | -------------------------------------------------------------------------------- /dp/343_integer_break.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(integerBreak(2)) // 1 7 | fmt.Println(integerBreak(5)) // 6 8 | fmt.Println(integerBreak(10)) // 36 9 | } 10 | 11 | // 和 70 题相似,但需要检查并嵌套两层循环 12 | // 注意 bottom-up 向上存储值时,要取 maxP 和 i 的最大值 13 | func integerBreak(n int) int { 14 | ps := make([]int, n+1) 15 | ps[1] = 1 // 边界值 16 | 17 | for i := 2; i <= n; i++ { 18 | var maxP int 19 | for j := 1; j <= i/2; j++ { 20 | maxP = max(maxP, ps[j]*ps[i-j]) // 状态转移 21 | } 22 | if i == n { 23 | return maxP // bingo 24 | } 25 | 26 | ps[i] = max(maxP, i) // 最优子结构 // 存储中间计算结果 27 | } 28 | 29 | return -1 // 代码不会执行到这 30 | } 31 | -------------------------------------------------------------------------------- /dp/70_climbing_stairs.go: -------------------------------------------------------------------------------- 1 | // 一维 DP 问题 2 | package main 3 | 4 | import "fmt" 5 | 6 | func main() { 7 | fmt.Println(climbStairs1(3)) // 3 8 | fmt.Println(climbStairs2(4)) // 5 9 | fmt.Println(climbStairs3(5)) // 8 10 | } 11 | 12 | // 时间复杂度 O(2^N) // 严重超时 13 | // 空间复杂度 O(1) 14 | func climbStairs1(n int) int { 15 | if n <= 2 { 16 | return n 17 | } 18 | return climbStairs1(n-1) + climbStairs1(n-2) // 存在大量重复计算 19 | } 20 | 21 | // 借助数组保存中间结果,避免重复计算 22 | // O(N) 23 | // O(N) 24 | func climbStairs2(n int) int { 25 | steps := make([]int, n+1) 26 | steps[1], steps[2] = 1, 2 // 边界 27 | 28 | for i := 3; i <= n; i++ { 29 | steps[i] = steps[i-2] + steps[i-1] // 状态转移 30 | } 31 | 32 | return steps[n] // 最优子结构 33 | } 34 | 35 | // 向后累计步数 36 | // O(N) 37 | // O(1) 38 | func climbStairs3(n int) int { 39 | if n == 1 { 40 | return 1 41 | } 42 | 43 | i, j := 1, 2 44 | for n > 2 { 45 | i, j = j, i+j // bottom -> up 46 | n-- 47 | } 48 | return j 49 | } 50 | -------------------------------------------------------------------------------- /dp/utils.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func max(vs ...int) int { 4 | if len(vs) == 0 { 5 | panic("func min args empty") 6 | } 7 | m := vs[0] 8 | for _, n := range vs[1:] { 9 | if n > m { 10 | m = n 11 | } 12 | } 13 | return m 14 | } 15 | -------------------------------------------------------------------------------- /heap/215_kth_largest_element_in_an_array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(findKthLargest([]int{3, 2, 1, 5, 6, 4}, 2)) // 5 7 | } 8 | 9 | func findKthLargest(nums []int, k int) int { 10 | maxHeap := NewMaxHeap(nums) 11 | for k > 1 { 12 | maxHeap.Pop() 13 | k-- 14 | } 15 | return maxHeap.Pop() 16 | } 17 | -------------------------------------------------------------------------------- /heap/347_top_k_frequent_elements.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(topKFrequent([]int{2, 2, 1, 1, 1, 3}, 2)) // [1, 2] 10 | } 11 | 12 | // 和 451 很像 13 | // 自己重新定义优先队列的优先度排序即可 14 | type Priority struct { 15 | n int // num 16 | p int // priority 17 | } 18 | 19 | func topKFrequent(nums []int, k int) []int { 20 | n2p := make(map[int]int) 21 | for _, n := range nums { 22 | n2p[n]++ 23 | } 24 | 25 | var priorities []Priority 26 | for n, p := range n2p { 27 | priorities = append(priorities, Priority{n, p}) 28 | } 29 | 30 | sort.Slice(priorities, func(i, j int) bool { 31 | return priorities[i].p > priorities[j].p 32 | }) 33 | 34 | res := make([]int, k) // 应对 k 做合法校验 35 | for i, p := range priorities[:k] { 36 | res[i] = p.n 37 | } 38 | return res 39 | } 40 | -------------------------------------------------------------------------------- /heap/451_sort_characters_by_frequency.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | "strings" 7 | ) 8 | 9 | func main() { 10 | fmt.Println(badFrequencySort("tree")) // eetr 11 | fmt.Println(frequencySort("tree")) // eetr 12 | } 13 | 14 | // heap 数组实现的优先队列左右子节点的优先度不分大小 15 | // 所以需要重新组织优先度的排序 16 | type Counter struct { 17 | r rune // rune 18 | p int // priority // 出现的次数 19 | } 20 | 21 | func frequencySort(s string) string { 22 | r2c := make(map[rune]int) 23 | for _, r := range s { 24 | r2c[r]++ 25 | } 26 | 27 | var counters []Counter 28 | for r, c := range r2c { 29 | counters = append(counters, Counter{r, c}) 30 | } 31 | 32 | // 自定义优先度排序规则 33 | sort.Slice(counters, func(i, j int) bool { 34 | return counters[i].p > counters[j].p 35 | }) 36 | 37 | s = "" 38 | for _, counter := range counters { 39 | s += strings.Repeat(string(counter.r), counter.p) 40 | } 41 | return s 42 | } 43 | 44 | // 最直观的硬核实现 45 | func badFrequencySort(s string) string { 46 | r2c := make(map[rune]int) 47 | for _, r := range s { 48 | r2c[r]++ 49 | } 50 | 51 | c2rs := make(map[int][]rune) 52 | for r, c := range r2c { 53 | c2rs[c] = append(c2rs[c], r) 54 | } 55 | 56 | counts := make([]int, 0, len(c2rs)) 57 | for c := range c2rs { 58 | counts = append(counts, c) 59 | } 60 | 61 | sort.Ints(counts) 62 | 63 | var res string 64 | for i := len(counts) - 1; i >= 0; i-- { 65 | for _, r := range c2rs[counts[i]] { 66 | res += strings.Repeat(string(r), counts[i]) 67 | } 68 | } 69 | 70 | return res 71 | } 72 | -------------------------------------------------------------------------------- /heap/703_kth_largest_element_in_a_stream.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | arr := []int{4, 5, 8, 2} 10 | kthLargest := Constructor(3, arr) 11 | fmt.Println(kthLargest.Add(3)) // 4 12 | fmt.Println(kthLargest.Add(5)) // 5 13 | fmt.Println(kthLargest.Add(10)) // 5 14 | fmt.Println(kthLargest.Add(9)) // 8 15 | fmt.Println(kthLargest.Add(4)) // 8 16 | } 17 | 18 | type KthLargest struct { 19 | k int 20 | nums []int 21 | } 22 | 23 | func Constructor(k int, nums []int) KthLargest { 24 | sort.Ints(nums) 25 | return KthLargest{k: k, nums: nums} 26 | } 27 | 28 | func (this *KthLargest) Add(val int) int { 29 | insert(&this.nums, val) // 低效 30 | return this.nums[len(this.nums)-this.k] 31 | } 32 | 33 | func insert(nums *[]int, v int) { 34 | ns := *nums 35 | l, r := 0, len(ns)-1 36 | for l <= r { 37 | mid := (l + r) / 2 38 | switch { 39 | case v < ns[mid]: 40 | r = mid - 1 41 | case v >= ns[mid]: 42 | l = mid + 1 43 | } 44 | } 45 | *nums = append(ns[:l], append([]int{v}, ns[l:]...)...) 46 | } 47 | -------------------------------------------------------------------------------- /heap/heap_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestMinHeap(t *testing.T) { 9 | h := NewMinHeap([]int{1, 4, 6, 7, 3}) 10 | fmt.Println(*h) // [1 3 6 7 4] // ok 11 | h.Push(2) 12 | fmt.Println(*h) // [1 3 2 7 4 6] // ok 13 | fmt.Println(h.Pop()) // 1 14 | fmt.Println(*h) // [2 3 6 7 4] // ok 15 | } 16 | 17 | func TestMaxHeap(t *testing.T) { 18 | h := NewMaxHeap([]int{1, 2, 6, 5, 9}) 19 | fmt.Println(*h) // [9 5 6 1 2] 20 | h.Push(8) 21 | fmt.Println(*h) // [9 5 8 1 2 6] 22 | fmt.Println(h.Pop()) 23 | fmt.Println(*h) // [8 5 6 1 2] 24 | } 25 | -------------------------------------------------------------------------------- /heap/max_heap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type MaxHeap []int 4 | 5 | // heapify 6 | func NewMaxHeap(nums []int) *MaxHeap { 7 | hs := MaxHeap(nums) 8 | n := len(hs) 9 | h := &hs 10 | for i := n/2 - 1; i >= 0; i-- { 11 | h.down(i, n) 12 | } 13 | return h 14 | } 15 | 16 | func (h *MaxHeap) Push(v int) { 17 | *h = append(*h, v) 18 | h.up(len(*h) - 1) 19 | } 20 | 21 | func (h *MaxHeap) Pop() int { 22 | hs := *h 23 | max := hs[0] 24 | n := len(hs) 25 | 26 | h.swap(0, n-1) 27 | h.down(0, n-1) // 除最后一个元素外全体下滤 28 | *h = hs[:n-1] 29 | 30 | return max 31 | } 32 | 33 | // 上滤 34 | func (h *MaxHeap) up(i int) { 35 | for { 36 | parent := (i - 1) / 2 37 | if h.more(parent, i) || parent == i { 38 | break 39 | } 40 | h.swap(parent, i) 41 | i = parent 42 | } 43 | } 44 | 45 | // 下滤 46 | func (h *MaxHeap) down(mid, n int) { 47 | for { 48 | l := 2*mid + 1 49 | if l >= n || l < 0 { 50 | break 51 | } 52 | max := l 53 | if r := l + 1; r < n && h.more(r, max) { 54 | max = r 55 | } 56 | if !h.more(max, mid) { 57 | break 58 | } 59 | 60 | h.swap(mid, max) 61 | mid = max 62 | } 63 | } 64 | 65 | func (h *MaxHeap) swap(i, j int) { 66 | hs := *h 67 | hs[i], hs[j] = hs[j], hs[i] 68 | } 69 | 70 | func (h *MaxHeap) more(i, j int) bool { 71 | hs := *h 72 | return hs[i] > hs[j] 73 | } 74 | -------------------------------------------------------------------------------- /heap/min_heap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type MinHeap []int 4 | 5 | // heapify 6 | func NewMinHeap(nums []int) *MinHeap { 7 | hs := MinHeap(nums) 8 | n := len(hs) 9 | heap := &hs 10 | for i := n/2 - 1; i >= 0; i-- { 11 | heap.down(i, n) 12 | } 13 | return heap 14 | } 15 | 16 | func (h *MinHeap) Push(v int) { 17 | *h = append(*h, v) 18 | h.up(len(*h) - 1) 19 | } 20 | 21 | func (h *MinHeap) Pop() int { 22 | hs := *h 23 | min := hs[0] 24 | 25 | n := len(hs) 26 | h.swap(0, n-1) 27 | h.down(0, n-1) // 全体下滤 28 | *h = hs[:n-1] 29 | 30 | return min 31 | } 32 | 33 | // 下滤 34 | func (h *MinHeap) down(mid, n int) { 35 | for { 36 | l := 2*mid + 1 37 | if l >= n { 38 | break 39 | } 40 | 41 | min := l 42 | if r := l + 1; r < n && h.less(r, l) { 43 | min = r 44 | } 45 | if !h.less(min, mid) { 46 | break 47 | } 48 | 49 | h.swap(mid, min) // ok 50 | mid = min 51 | } 52 | } 53 | 54 | // 上滤 55 | func (h *MinHeap) up(i int) { 56 | for { 57 | parent := (i - 1) / 2 58 | if h.less(parent, i) || parent == i { 59 | break 60 | } 61 | h.swap(parent, i) 62 | i = parent 63 | } 64 | } 65 | 66 | func (h *MinHeap) less(i, j int) bool { 67 | hs := *h 68 | return hs[i] < hs[j] 69 | } 70 | 71 | func (h *MinHeap) swap(i, j int) { 72 | hs := *h 73 | // fmt.Println("swap", hs, hs[i], hs[j]) // debug 74 | hs[i], hs[j] = hs[j], hs[i] 75 | } 76 | -------------------------------------------------------------------------------- /linked_list/141_linked_list_cycle.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | head := newList([]int{1, 2, 3}) 7 | fmt.Println(hasCycle(head)) // false 8 | head.Next.Next.Next = head.Next 9 | fmt.Println(hasCycle(head)) // true 10 | } 11 | 12 | // map 是保证集合唯一性很好的选择 13 | func hasCycle(head *ListNode) bool { 14 | if head == nil || head.Next == nil { 15 | return false 16 | } 17 | addresses := make(map[*ListNode]int) // 指针类型(内存地址)是可比较的哟 18 | cur := head 19 | for cur != nil { 20 | if _, ok := addresses[cur]; ok { 21 | return true 22 | } 23 | addresses[cur] = 0 24 | cur = cur.Next 25 | } 26 | return false 27 | } 28 | -------------------------------------------------------------------------------- /linked_list/19_remove_nth_node_from_end_of_list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(removeNthFromEnd(newList([]int{1, 2}), 1)) 7 | // fmt.Println(removeNthFromEnd(newList([]int{1, 2}), 2)) 8 | } 9 | 10 | // 和倒数相关的问题考虑天生有间距的"双指针",一次遍历解决 11 | // 借助哑节点是关键,用于防止删除倒数第 len(nums) 个节点会导致链表丢失 12 | // 若要兼顾正常节点的移动,又要处理头结点的特殊情况,请考虑"哑节点" 13 | func removeNthFromEnd(head *ListNode, n int) *ListNode { 14 | dummyNode := &ListNode{Val: 0, Next: head} 15 | front, rear := dummyNode, dummyNode 16 | for counts := 0; counts <= n; counts++ { 17 | rear = rear.Next 18 | } 19 | for rear != nil { 20 | front = front.Next 21 | rear = rear.Next 22 | } 23 | front.Next = front.Next.Next // 删除节点 24 | return dummyNode.Next 25 | } 26 | -------------------------------------------------------------------------------- /linked_list/203_remove_linked_list_elements.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(removeElements(newList([]int{1, 1}), 1)) 7 | fmt.Println(removeElements(newList([]int{1, 2, 6, 3, 4, 5, 6}), 6)) 8 | } 9 | 10 | // 头节点可能会被删掉,要考虑借助哑节点 11 | // 画图理解就 ok 12 | func removeElements(head *ListNode, val int) *ListNode { 13 | if head == nil { 14 | return head 15 | } 16 | dummy := &ListNode{Next: head} 17 | pre, cur := dummy, head 18 | for cur != nil { 19 | if cur.Val == val { 20 | pre.Next = cur.Next 21 | cur = cur.Next 22 | continue 23 | } 24 | pre = pre.Next 25 | cur = cur.Next 26 | } 27 | return dummy.Next 28 | } 29 | -------------------------------------------------------------------------------- /linked_list/206_reverse_linked_list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(reverseList(newList([]int{1, 2, 3, 4, 5}))) 7 | } 8 | 9 | // 有点栈的味道哦 10 | func reverseList(head *ListNode) *ListNode { 11 | if head == nil || head.Next == nil { 12 | return head 13 | } 14 | newHead := &ListNode{Val: head.Val} 15 | cur := head.Next 16 | for cur != nil { 17 | newHead = prepend(newHead, cur.Val) 18 | cur = cur.Next 19 | } 20 | return newHead 21 | } 22 | 23 | func prepend(head *ListNode, v int) *ListNode { 24 | node := &ListNode{Val: v} 25 | if head == nil { 26 | return node 27 | } 28 | node.Next = head 29 | return node 30 | } 31 | -------------------------------------------------------------------------------- /linked_list/21_merge_two_sorted_lists.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(mergeTwoLists(newList([]int{1}), newList([]int{}))) 7 | } 8 | 9 | // 借助哑节点,万事大吉 10 | func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode { 11 | cur := new(ListNode) 12 | dummy := cur 13 | cur1, cur2 := l1, l2 14 | for cur1 != nil && cur2 != nil { 15 | if cur1.Val < cur2.Val { 16 | cur.Next = cur1 17 | cur1 = cur1.Next 18 | } else { 19 | cur.Next = cur2 20 | cur2 = cur2.Next 21 | } 22 | cur = cur.Next 23 | } 24 | traverse := func(l, remainL *ListNode) { 25 | for remainL != nil { 26 | l.Next = remainL 27 | l = l.Next 28 | remainL = remainL.Next 29 | } 30 | } 31 | traverse(cur, cur1) 32 | traverse(cur, cur2) 33 | return dummy.Next 34 | } 35 | -------------------------------------------------------------------------------- /linked_list/234_palindrome_linked_list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(isPalindrome(newList([]int{1, 2}))) 7 | fmt.Println(isPalindrome(newList([]int{1, 2, 2, 1}))) 8 | fmt.Println(isPalindrome(newList([]int{1, 2, 3, 2, 1}))) 9 | } 10 | 11 | // 将前半段链表反转到新链表,再逐一对比新链表与后半段链表是否一致 12 | func isPalindrome(head *ListNode) bool { 13 | if head == nil || head.Next == nil { 14 | return true // 注意 []、[1] 是回文结构 15 | } 16 | 17 | n := 0 18 | cur := head 19 | for cur != nil { 20 | n++ 21 | cur = cur.Next 22 | } 23 | mid := n / 2 // 找到中间节点 24 | 25 | cur = head 26 | newHead := &ListNode{Val: head.Val} // 遍历新建前半段链表 27 | i := 0 28 | for i < mid-1 { 29 | cur = cur.Next 30 | newHead = prepend(newHead, cur.Val) 31 | i++ 32 | } 33 | 34 | cur = cur.Next // 选取要开始遍历的后半段链表 35 | if n%2 == 1 { 36 | cur = cur.Next 37 | } 38 | 39 | for newHead != nil && cur != nil { 40 | if newHead.Val != cur.Val { 41 | return false 42 | } 43 | cur = cur.Next 44 | newHead = newHead.Next 45 | } 46 | 47 | return true // 对称 48 | } 49 | 50 | // 新增 head 51 | func prepend(head *ListNode, v int) (newHead *ListNode) { 52 | node := &ListNode{Val: v} 53 | if head == nil { 54 | return node 55 | } 56 | node.Next = head 57 | return node 58 | } 59 | -------------------------------------------------------------------------------- /linked_list/237_delete_node_in_a_linked_list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(deleteNode(newList([]int{4, 5, 1, 9}), 5)) 7 | fmt.Println(deleteNode(newList([]int{4, 5, 1, 9}), 9)) 8 | fmt.Println(deleteNode(newList([]int{1, 2}), 1)) 9 | } 10 | 11 | // 注意 break 条件即可 12 | func deleteNode(head *ListNode, v int) *ListNode { 13 | if head == nil || head.Next == nil { 14 | return nil 15 | } 16 | pre, cur := head, head.Next 17 | for { 18 | if cur.Next == nil || cur.Val == v { 19 | break 20 | } 21 | pre = pre.Next 22 | cur = cur.Next 23 | } 24 | pre.Next = cur.Next 25 | return head 26 | } 27 | -------------------------------------------------------------------------------- /linked_list/24_swap_nodes_in_pairs.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(swapPairs(newList([]int{1}))) 7 | fmt.Println(swapPairs(newList([]int{1, 2}))) 8 | fmt.Println(swapPairs(newList([]int{1, 2, 3, 4}))) 9 | } 10 | 11 | // 处理好 2 种异常 case 12 | // 将两两节点视为内部短链表,交换两个节点后返回新的头节点(原第二节点),接到尾巴上即可 13 | // 一般 case:pre->cur->next 经 swap() 调换后 next->pre,手动接上 pre->next->cur 14 | func swapPairs(head *ListNode) *ListNode { 15 | if head == nil || head.Next == nil { // 异常case: [] 或 [1] 16 | return head 17 | } 18 | 19 | newHead := swap(head, head.Next) 20 | pre := head 21 | if pre.Next == nil || pre.Next.Next == nil { // 异常case: [1, 2] 22 | return newHead 23 | } 24 | 25 | cur := pre.Next 26 | next := cur.Next 27 | for cur != nil && next != nil { // 一般case: 两两结对向后遍历 28 | pre.Next = swap(cur, next) // 内部交换 29 | if cur.Next == nil { 30 | break 31 | } 32 | pre = cur 33 | cur = cur.Next 34 | next = cur.Next 35 | } 36 | return newHead 37 | } 38 | 39 | func swap(cur, next *ListNode) *ListNode { 40 | cur.Next = next.Next 41 | next.Next = cur 42 | return next 43 | } 44 | -------------------------------------------------------------------------------- /linked_list/2_add_two_numbers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // go run init.go 2_add_two_numbers.go 6 | func main() { 7 | l1 := newList([]int{8, 9, 9}) // 5 // 9 8 8 | l2 := newList([]int{2}) // 5 // 1 9 | cur := addTwoNumbers(l1, l2) 10 | for cur != nil { 11 | fmt.Print(cur.Val, " ") 12 | cur = cur.Next 13 | } 14 | } 15 | 16 | 17 | // 遍历两个链表,取出各自的数字再相加(难以解决整数溢出的问题,1560 / 1563 个通过测试用例,取值求解不可行) 18 | // 遍历链表,相互相加记进位。注意特殊情况的处理 19 | func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode { 20 | var nums []int 21 | cur1, cur2 := l1, l2 22 | var carryBit bool // 是否要进位 23 | for cur1 != nil && cur2 != nil { 24 | sum := cur1.Val + cur2.Val 25 | if carryBit { 26 | sum++ 27 | } 28 | carryBit = false 29 | if sum >= 10 { 30 | carryBit = true 31 | } 32 | nums = append(nums, sum%10) 33 | cur1 = cur1.Next 34 | cur2 = cur2.Next 35 | } 36 | nums = append(nums, traverse(cur1, carryBit)...) 37 | nums = append(nums, traverse(cur2, carryBit)...) 38 | if cur1 == nil && cur2 == nil && carryBit { 39 | nums = append(nums, 1) 40 | } 41 | return newList(nums) 42 | } 43 | 44 | func traverse(cur *ListNode, carryBit bool) (remainNums []int) { 45 | if cur == nil { 46 | return 47 | } 48 | for cur != nil { 49 | if carryBit { 50 | res := cur.Val + 1 51 | if res >= 10 { 52 | remainNums = append(remainNums, 0) 53 | carryBit = true 54 | } else { 55 | remainNums = append(remainNums, res) 56 | carryBit = false 57 | } 58 | cur = cur.Next 59 | continue 60 | } 61 | remainNums = append(remainNums, cur.Val) 62 | cur = cur.Next 63 | } 64 | if carryBit { 65 | remainNums = append(remainNums, 1) 66 | } 67 | return 68 | } 69 | 70 | -------------------------------------------------------------------------------- /linked_list/328_odd_even_linked_list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(oddEvenList(newList([]int{1, 2, 3, 4, 5, 6, 7, 8, 9}))) 7 | } 8 | 9 | // 小样本发现不了规律,就把数据量设置大一点,走一遍题目要求,就看出规律来了 10 | // 1 2 3 4 5 6 7 8 9 11 | // pre cur target // 不断交换 cur 和 target 的值即可,注意二者的 gap 间距从 1 开始递增 12 | func oddEvenList(head *ListNode) *ListNode { 13 | if head == nil || head.Next == nil || head.Next.Next == nil { 14 | return head 15 | } 16 | gap := 1 17 | pre, cur, target := head, head.Next, head.Next.Next 18 | for { 19 | swap3Nodes(pre, cur, target) 20 | gap++ 21 | for i := 0; target != nil && i <= gap; i++ { 22 | target = target.Next 23 | } 24 | pre = pre.Next 25 | if target == nil { 26 | break 27 | } 28 | } 29 | return head 30 | } 31 | 32 | // 交换 pre->cur->...->target->... 三个节点的值 33 | func swap3Nodes(pre, cur, target *ListNode) { 34 | pre.Next = target 35 | targetNext := target.Next 36 | target.Next = cur 37 | curNext := cur 38 | for curNext.Next != target { 39 | curNext = curNext.Next 40 | } 41 | curNext.Next = targetNext 42 | } 43 | -------------------------------------------------------------------------------- /linked_list/61_rotate_list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(rotateRight(newList([]int{1, 2, 3, 4, 5}), 2)) 7 | fmt.Println(rotateRight(newList([]int{0, 1, 2}), 4)) 8 | } 9 | 10 | // 和 189 类似,注意先取余 11 | func rotateRight(head *ListNode, k int) *ListNode { 12 | if head == nil || head.Next == nil { 13 | return head 14 | } 15 | n := count(head) 16 | step := k % n 17 | for step > 0 { 18 | pre, tail := tailNodes(head) // 获取到倒数二个节点:pre->tail->nil 19 | pre.Next = nil // 删除 tail 20 | tail.Next = head // 将 tail 作为新的 head 21 | head = tail 22 | step-- 23 | } 24 | return head 25 | } 26 | 27 | func tailNodes(head *ListNode) (*ListNode, *ListNode) { 28 | pre, tail := head, head.Next 29 | for tail.Next != nil { 30 | pre = tail 31 | tail = tail.Next 32 | } 33 | return pre, tail 34 | } 35 | 36 | func count(head *ListNode) int { 37 | counts := 0 38 | cur := head 39 | for cur != nil { 40 | counts++ 41 | cur = cur.Next 42 | } 43 | return counts 44 | } 45 | -------------------------------------------------------------------------------- /linked_list/725_intersection_of_two_linked_lists.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | for _, node := range splitListToParts(newList([]int{1, 2, 3, 4, 5, 6, 7}), 3) { 7 | fmt.Println(node) 8 | } 9 | } 10 | 11 | func splitListToParts(root *ListNode, k int) []*ListNode { 12 | // case: [], 3 => [],[],[] 13 | // if root == nil { 14 | // return nil 15 | // } 16 | 17 | n := 0 18 | cur := root 19 | for cur != nil { 20 | n++ 21 | cur = cur.Next 22 | } 23 | nodes := make([]*ListNode, k) 24 | cur = root 25 | 26 | div, remain := n/k, n%k // 商,余数 27 | fmt.Println(div, remain) 28 | for i := 0; i < k && cur != nil; i++ { 29 | nodes[i] = cur 30 | // 十分巧妙的写法,若数组未达到余数那么长,前边每部分部分都要多接一个节点 31 | for j := 1; j < div+bool2int(i < remain); j++ { 32 | cur = cur.Next 33 | } 34 | next := cur.Next 35 | cur.Next = nil 36 | cur = next 37 | } 38 | return nodes 39 | } 40 | 41 | func bool2int(b bool) int { 42 | if b { 43 | return 1 44 | } 45 | return 0 46 | } 47 | -------------------------------------------------------------------------------- /linked_list/817_linked_list_components.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(numComponents(newList([]int{0, 1, 2, 3}), []int{0, 1, 3})) 7 | fmt.Println(numComponents(newList([]int{0, 1, 2, 3, 4}), []int{0, 1, 3, 4})) 8 | } 9 | 10 | // 想起了两数之和,遍历链表时判断值是否在 G 中,使用散列表 map 就很好 11 | // 注意理清楚逻辑就行 12 | func numComponents(head *ListNode, G []int) int { 13 | if head == nil || len(G) == 0 { 14 | return 0 15 | } 16 | nums := make(map[int]int) 17 | for _, g := range G { 18 | nums[g]++ 19 | } 20 | counts := 0 21 | front, rear := head, head 22 | for rear != nil { 23 | if _, ok := nums[front.Val]; !ok { 24 | front = front.Next 25 | rear = rear.Next 26 | continue 27 | } 28 | // 至少找到一个存在的值 29 | counts++ 30 | for rear != nil { 31 | if _, ok := nums[rear.Val]; !ok { 32 | break 33 | } 34 | rear = rear.Next // 跳过所有连续、在 G 中有的值 35 | } 36 | front = rear 37 | } 38 | return counts 39 | } 40 | -------------------------------------------------------------------------------- /linked_list/82_remove_duplicates_from_sorted_list_ii.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | // fmt.Println(deleteDuplicates(newList([]int{1, 2, 3, 3, 4, 4, 5}))) 7 | fmt.Println(deleteDuplicates(newList([]int{1, 1, 1, 2, 2, 3}))) 8 | // fmt.Println(deleteDuplicates(newList([]int{1, 2, 2}))) 9 | } 10 | 11 | // 遇到头节点也需要遍历,而且头节点有可能丢失的情况下,一定要求助于 "哑节点" 12 | func deleteDuplicates(head *ListNode) *ListNode { 13 | if head == nil || head.Next == nil { 14 | return head 15 | } 16 | 17 | dummy := &ListNode{Next: head} 18 | pre := dummy 19 | for pre.Next != nil { 20 | last := pre.Next 21 | for last.Next != nil && last.Val == last.Next.Val { 22 | last = last.Next 23 | } 24 | // 对比每个序列的第一个数和最后一个数(节点)是否相等 25 | if pre.Next != last { 26 | pre.Next = last.Next // 不相等则 pre.Next 指向下一个数字序列的第一个节点 27 | } else { 28 | pre = pre.Next // 相等则 ok 29 | } 30 | } 31 | 32 | return dummy.Next 33 | } 34 | -------------------------------------------------------------------------------- /linked_list/83_remove_duplicates_from_sorted_list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(deleteDuplicates(newList([]int{1, 1, 2}))) 7 | fmt.Println(deleteDuplicates(newList([]int{1, 1, 2, 3, 3}))) 8 | } 9 | 10 | // 遍历即可 11 | func deleteDuplicates(head *ListNode) *ListNode { 12 | if head == nil || head.Next == nil { 13 | return head 14 | } 15 | cur := head 16 | for cur.Next != nil { 17 | if cur.Val == cur.Next.Val { 18 | cur.Next = cur.Next.Next 19 | continue 20 | } 21 | cur = cur.Next 22 | } 23 | return head 24 | } 25 | -------------------------------------------------------------------------------- /linked_list/86_partition_list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(partition(newList([]int{1, 4, 3, 2, 5, 2}), 3)) 7 | } 8 | 9 | // 哑节点是利器啊 10 | func partition(head *ListNode, x int) *ListNode { 11 | if head == nil || head.Next == nil { 12 | return head 13 | } 14 | dummy1, dummy2 := new(ListNode), new(ListNode) 15 | cur1, cur2 := dummy1, dummy2 16 | cur := head 17 | for cur != nil { // 遍历构建 18 | if cur.Val < x { 19 | cur1.Next = cur 20 | cur1 = cur 21 | } else { 22 | cur2.Next = cur 23 | cur2 = cur 24 | } 25 | cur = cur.Next 26 | } 27 | cur1.Next = nil // 截断 28 | cur2.Next = nil 29 | cur1.Next = dummy2.Next // 连接 30 | return dummy1.Next 31 | } 32 | -------------------------------------------------------------------------------- /linked_list/876_middle_of_the_linked_list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(middleNode(newList([]int{1, 2, 3, 4, 5}))) 7 | fmt.Println(middleNode(newList([]int{1, 2, 3, 4, 5, 6}))) 8 | } 9 | 10 | // 考虑遍历的两种普遍问题 11 | // 间距问题:使用2个间距指针 front, rear 12 | // 截取1/N问题:使用2个倍速指针 slow, fast 13 | func middleNode(head *ListNode) *ListNode { 14 | slow, fast := head, head 15 | for fast != nil && fast.Next != nil { 16 | slow = slow.Next 17 | fast = fast.Next.Next 18 | } 19 | return slow 20 | } 21 | 22 | // 先统计节点个数,再将 head 移动到中间节点即可 23 | func middleNode1(head *ListNode) *ListNode { 24 | if head == nil || head.Next == nil { 25 | return head 26 | } 27 | n := 0 28 | cur := head 29 | for cur != nil { 30 | n++ 31 | cur = cur.Next 32 | } 33 | mid := n / 2 34 | for i := 0; i < mid; i++ { 35 | head = head.Next 36 | } 37 | return head 38 | } 39 | -------------------------------------------------------------------------------- /linked_list/92_reverse_linked_list_ii.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(reverseBetween(newList([]int{1, 2, 3, 4, 5}), 2, 4)) 7 | } 8 | 9 | // 更具普遍意义的反转链表,记得借助哑节点以防 head 丢失 10 | func reverseBetween(head *ListNode, m int, n int) *ListNode { 11 | if head == nil || head.Next == nil { 12 | return head 13 | } 14 | 15 | dummy := &ListNode{Next: head} 16 | i := 1 17 | pre, cur := dummy, head 18 | for i < m { 19 | pre = pre.Next 20 | cur = cur.Next 21 | i++ 22 | } 23 | 24 | // 开始反转 25 | newStart := &ListNode{Val: cur.Val} 26 | for i < n { 27 | cur = cur.Next 28 | newStart = prepend(newStart, cur.Val) 29 | i++ 30 | } 31 | cur = cur.Next 32 | pre.Next = newStart 33 | 34 | // 反转完毕,把 [n...] 之后的接上 35 | for i := 0; i < n-m; i++ { 36 | newStart = newStart.Next 37 | } 38 | newStart.Next = cur 39 | 40 | return dummy.Next 41 | } 42 | 43 | func prepend(head *ListNode, v int) *ListNode { 44 | node := &ListNode{Val: v} 45 | if head == nil { 46 | return node 47 | } 48 | node.Next = head 49 | return node 50 | } 51 | -------------------------------------------------------------------------------- /linked_list/init.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // go run init.go xxx.go 6 | type ListNode struct { 7 | Val int 8 | Next *ListNode 9 | } 10 | 11 | func newList(nums []int) *ListNode { 12 | n := len(nums) 13 | if n == 0 { 14 | return nil 15 | } 16 | head := &ListNode{Val: nums[0], Next: nil} 17 | cur := head 18 | for i := 1; i < n; i++ { 19 | newNode := &ListNode{Val: nums[i], Next: nil} 20 | cur.Next = newNode 21 | cur = newNode 22 | } 23 | return head 24 | } 25 | 26 | func (cur *ListNode) String() string { 27 | counts := 0 28 | var nums []int 29 | for cur != nil { 30 | nums = append(nums, cur.Val) 31 | counts++ 32 | cur = cur.Next 33 | } 34 | return fmt.Sprintf("%d nodes: %v", counts, nums) 35 | } 36 | -------------------------------------------------------------------------------- /map/864_hand_of_straights.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | // map first blood 9 | func main() { 10 | fmt.Println(isNStraightHand([]int{1, 2, 3, 6, 2, 3, 4, 7, 8}, 3)) // true 11 | } 12 | 13 | func isNStraightHand(hand []int, W int) bool { 14 | m := make(map[int]int) // 计数 map 15 | for _, h := range hand { 16 | m[h]++ 17 | } 18 | 19 | var ks []int 20 | for k := range m { 21 | ks = append(ks, k) 22 | } 23 | sort.Ints(ks) 24 | 25 | // 好戏开始 26 | for _, k := range ks { 27 | c1 := m[k] 28 | if c1 <= 0 { 29 | continue // 已经被完全拖下水 30 | } 31 | for i := k; i < k+W; i++ { 32 | if c2, ok := m[i]; !ok || c2 < c1 { 33 | return false 34 | } 35 | m[i] -= c1 // 一次走一批 36 | } 37 | } 38 | 39 | return true 40 | } 41 | -------------------------------------------------------------------------------- /sql/175_combine_two_tables.sql: -------------------------------------------------------------------------------- 1 | -- 组合两张表 2 | -- 相比 where 的真过滤,on 是假过滤,会保留一侧的无数据字段为 Null 3 | select FirstName, LastName, City, State 4 | from Person as p left join Address as a 5 | on p.PersonId = a.PersonId; -------------------------------------------------------------------------------- /sql/176_second_highest_salary.sql: -------------------------------------------------------------------------------- 1 | -- 第二高的薪水 2 | -- 倒数第 2 即按倒序排取第 2 个 3 | -- 内部子查询返回空结果,外部 AS 取结果值为 NULL 4 | select 5 | (select distinct Salary from Employee 6 | order by Salary desc limit 1,1) 7 | as SecondHighestSalary; -------------------------------------------------------------------------------- /sql/178_rank_scores.sql: -------------------------------------------------------------------------------- 1 | -- 分数排名 2 | -- 排名即,去重后有多少 rows 比我的值还大 3 | select Score, (select count(distinct Score) from Scores where Score >= s.Score) as Rank 4 | from Scores as s 5 | order by Score desc -------------------------------------------------------------------------------- /stack/150_evaluate_reverse_polish_notation.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(evalRPN([]string{"4", "3", "-"})) // 1 10 | fmt.Println(evalRPN([]string{"10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"})) // 22 11 | } 12 | 13 | // 再加上 () 运算就是完整的表达式计算了 14 | func evalRPN(tokens []string) int { 15 | var s Stack 16 | for _, token := range tokens { 17 | if n, err := strconv.Atoi(token); err == nil { 18 | s.Push(n) 19 | } else { 20 | // 字符运算,注意减除的顺序 21 | l, r := s.Pop(), s.Pop() 22 | switch token { 23 | case "+": 24 | s.Push(l + r) 25 | case "-": 26 | s.Push(r - l) 27 | case "*": 28 | s.Push(l * r) 29 | case "/": 30 | s.Push(r / l) 31 | } 32 | } 33 | } 34 | return s.Pop() 35 | } 36 | -------------------------------------------------------------------------------- /stack/155_min_stack.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | s := MinStack{} 7 | s.Push(1) 8 | s.Push(2) 9 | fmt.Println(s.Top()) // 2 10 | fmt.Println(s.GetMin()) // 1 11 | s.Pop() 12 | fmt.Println(s.GetMin()) // 1 13 | fmt.Println(s.Top()) // 1 14 | } 15 | 16 | // 设计具有 GetMin 操作的最小栈 17 | type MinStack struct { 18 | min int 19 | stack []int 20 | } 21 | 22 | func Constructor() MinStack { 23 | return MinStack{} 24 | } 25 | 26 | func (this *MinStack) Push(x int) { 27 | if len(this.stack) == 0 { 28 | this.min = x 29 | } 30 | if x < this.min { 31 | this.min = x 32 | } 33 | this.stack = append(this.stack, x) 34 | } 35 | 36 | // pop 操作后需要解决 min 的操作 37 | func (this *MinStack) Pop() { 38 | this.stack = this.stack[:len(this.stack)-1] 39 | if len(this.stack) > 0 { 40 | this.min = this.stack[0] 41 | } 42 | for _, elem := range this.stack { 43 | if this.min > elem { 44 | this.min = elem 45 | } 46 | } 47 | } 48 | 49 | func (this *MinStack) Top() int { 50 | return this.stack[len(this.stack)-1] 51 | } 52 | 53 | func (this *MinStack) GetMin() int { 54 | return this.min 55 | } 56 | -------------------------------------------------------------------------------- /stack/225_implement_stack_using_queues.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | s := MyStack{} 7 | fmt.Println(s.Empty()) // true 8 | s.Push(1) 9 | s.Push(2) 10 | s.Push(3) 11 | fmt.Println(s.Pop()) // 3 12 | } 13 | 14 | // 两个队列实现一个栈 15 | // [...enque...] <- 16 | // [...deque...] -> 17 | type MyStack struct { 18 | enque, deque []int 19 | } 20 | 21 | func Constructor() MyStack { 22 | return MyStack{} 23 | } 24 | 25 | func (this *MyStack) Push(x int) { 26 | this.enque = append(this.enque, x) 27 | } 28 | 29 | func (this *MyStack) Pop() int { 30 | // 把 enque 队列元素按顺序 append 到 deque 队列中 31 | n := len(this.enque) 32 | for i := 0; i < n-1; i++ { // 留最后一个元素 33 | this.deque = append(this.deque, this.enque[0]) 34 | this.enque = this.enque[1:] 35 | } 36 | peek := this.enque[0] 37 | this.enque = this.deque 38 | this.deque = nil 39 | return peek 40 | } 41 | 42 | func (this *MyStack) Top() int { 43 | peek := this.Pop() 44 | this.enque = append(this.enque, peek) 45 | return peek 46 | } 47 | 48 | func (this *MyStack) Empty() bool { 49 | return len(this.enque) == 0 50 | } 51 | -------------------------------------------------------------------------------- /stack/232_implement_queue_using_stacks.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | q := Constructor() 7 | q.Push(1) 8 | q.Push(2) 9 | q.Push(3) 10 | fmt.Println(q.Pop()) 11 | } 12 | 13 | // 可以直接使用 []int 来实现 queue 14 | // 比较取巧的方法,用两个栈实现一个队列: x->s1,s2-> 15 | type MyQueue struct { 16 | s1, s2 Stack 17 | } 18 | 19 | func Constructor() MyQueue { 20 | return MyQueue{} 21 | } 22 | 23 | func (this *MyQueue) Push(x int) { 24 | this.s1.Push(x) 25 | } 26 | 27 | func (this *MyQueue) Pop() int { 28 | if this.s2.IsEmpty() { 29 | for !this.s1.IsEmpty() { // 所有元素向前挪动 30 | this.s2.Push(this.s1.Pop()) 31 | } 32 | } 33 | return this.s2.Pop() 34 | } 35 | 36 | func (this *MyQueue) Peek() int { 37 | if this.s2.IsEmpty() { 38 | for !this.s1.IsEmpty() { // 所有元素向前挪动 39 | this.s2.Push(this.s1.Pop()) 40 | } 41 | } 42 | return this.s2.Peek() 43 | } 44 | 45 | func (this *MyQueue) Empty() bool { 46 | return this.s2.IsEmpty() && this.s1.IsEmpty() 47 | } 48 | -------------------------------------------------------------------------------- /stack/394_decode_string.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(decodeString("3[a]2[b4[F]c]")) // aaabFFFFcbFFFFc 7 | } 8 | 9 | // 考虑 case 10 | // 字母大小写 11 | // 数字和字母不止一个,需进行进制和字符的暂存 12 | // 分数字栈、字符栈进行计算,遇到 ] 触发一次计算 13 | 14 | // go run stack.go str_stack.go 394_xxx.go 15 | func decodeString(s string) string { 16 | var ( 17 | n int 18 | res string 19 | nums Stack 20 | str StrStack 21 | ) 22 | for _, r := range s { 23 | switch { 24 | case '0' <= r && r <= '9': 25 | n = 10*n + int(r-'0') 26 | case ('a' <= r && r <= 'z') || ('A' <= r && r <= 'Z'): 27 | res += string(r) 28 | case r == '[': // 双双进栈 29 | nums.Push(n) 30 | n = 0 31 | str.Push(res) 32 | res = "" 33 | case r == ']': // 双双出栈计算值 34 | repeat := res 35 | for i := 0; i < nums.Peek()-1; i++ { 36 | res += repeat 37 | } 38 | res = str.Pop() + res 39 | nums.Pop() 40 | } 41 | } 42 | return res 43 | } 44 | -------------------------------------------------------------------------------- /stack/496_next_greater_element_i.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(nextGreaterElement([]int{4, 1, 2}, []int{1, 3, 4, 2})) // [-1 3 -1] 7 | fmt.Println(bestNextGreaterElement([]int{4, 1, 2}, []int{1, 3, 4, 2})) // [-1 3 -1] 8 | } 9 | 10 | // 使用递减顺序栈,很 ok 11 | func bestNextGreaterElement(findNums []int, nums []int) []int { 12 | m := make(map[int]int) 13 | var s Stack // 递减序列栈 14 | for _, num := range nums { 15 | for !s.IsEmpty() && s.Peek() < num { // 将 nums 中的数依次进栈,一直向下找比栈顶值还大的数 16 | m[s.Pop()] = num // 向上最接近的数 17 | } 18 | s.Push(num) 19 | } 20 | 21 | for i, num := range findNums { 22 | if greater, ok := m[num]; ok { 23 | findNums[i] = greater 24 | } else { 25 | findNums[i] = -1 26 | } 27 | } 28 | return findNums 29 | } 30 | 31 | // 干脆直接的遍历 32 | func nextGreaterElement(findNums []int, nums []int) []int { 33 | n := len(nums) 34 | res := make([]int, 0, len(findNums)) 35 | for _, target := range findNums { 36 | for i, num := range nums { 37 | if num != target { 38 | continue 39 | } 40 | 41 | // 直接向后找第一个比 target 大的数 42 | found := false 43 | for j := i + 1; j < n; j++ { 44 | if nums[j] > target { 45 | found = true 46 | res = append(res, nums[j]) 47 | break 48 | } 49 | } 50 | if !found { 51 | res = append(res, -1) 52 | } 53 | } 54 | } 55 | return res 56 | } 57 | -------------------------------------------------------------------------------- /stack/682_baseball_game.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(calPoints([]string{"5", "2", "C", "D", "+"})) // 30 10 | fmt.Println(calPoints([]string{"5", "-2", "4", "C", "D", "9", "+", "+"})) // 27 11 | } 12 | 13 | // 有点后缀表达式计算值的感觉 14 | func calPoints(ops []string) int { 15 | var s Stack 16 | for _, str := range ops { 17 | switch str { 18 | case "+": 19 | if !s.IsEmpty() { 20 | originPeek := s.Pop() 21 | sum := originPeek + s.Peek() // 所有 case 前两个元素都已是数字 22 | s.Push(originPeek) 23 | s.Push(sum) 24 | } 25 | case "D": 26 | if !s.IsEmpty() { 27 | s.Push(2 * s.Peek()) 28 | } 29 | case "C": 30 | if !s.IsEmpty() { 31 | s.Pop() 32 | } 33 | default: 34 | n, _ := strconv.Atoi(str) 35 | s.Push(n) 36 | } 37 | } 38 | 39 | sum := 0 40 | for !s.IsEmpty() { 41 | sum += s.Pop() 42 | } 43 | 44 | return sum 45 | } 46 | -------------------------------------------------------------------------------- /stack/71_simplify_path.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(simplifyPath("/a/./b/../../c/")) 10 | fmt.Println(simplifyPath("/home//foo/")) 11 | fmt.Println(simplifyPath("/..")) 12 | } 13 | 14 | // package filepath 了解一下 15 | func simplifyPath(path string) string { 16 | var s StrStack 17 | paths := strings.Split(path, "/") 18 | for _, p := range paths { 19 | if len(p) == 0 || p == "." { 20 | continue 21 | } 22 | if p == ".." { 23 | if !s.IsEmpty() { // 注意处理case: "/.." 24 | s.Pop() 25 | } 26 | } else { 27 | s.Push(p) 28 | } 29 | } 30 | return "/" + strings.Join(s, "/") 31 | } 32 | -------------------------------------------------------------------------------- /stack/739_daily_temperatures.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(dailyTemperatures([]int{73, 74, 75, 71, 69, 72, 76, 73})) 7 | } 8 | 9 | // 十分有栈味道的题 10 | // 弄清楚栈在题中如何使用,灵活结合 pop push 等操作解决 11 | func dailyTemperatures(temperatures []int) []int { 12 | res := make([]int, len(temperatures)) 13 | var s Stack // 索引栈 14 | for i, t := range temperatures { 15 | for !s.IsEmpty() { 16 | peek := s.Peek() 17 | if t > temperatures[peek] { // 遇到大数,则把积压的小数全部 pop 出来 18 | res[peek] = i - peek 19 | s.Pop() 20 | } else { 21 | break 22 | } 23 | } 24 | s.Push(i) 25 | } 26 | return res 27 | } 28 | -------------------------------------------------------------------------------- /stack/844_backspace_string_compare.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(backspaceCompare("a#c", "b")) // false 10 | } 11 | 12 | func backspaceCompare(S string, T string) bool { 13 | var s1, s2 Stack 14 | traverse := func(str string, s *Stack) { 15 | for _, r := range str { 16 | if r == '#' { 17 | if !s.IsEmpty() { 18 | s.Pop() 19 | } 20 | } else { 21 | s.Push(int(r)) 22 | } 23 | } 24 | } 25 | 26 | traverse(S, &s1) 27 | traverse(T, &s2) 28 | 29 | var s, t string 30 | for !s1.IsEmpty() { 31 | s += string(rune(s1.Pop())) 32 | } 33 | for !s2.IsEmpty() { 34 | t += string(rune(s2.Pop())) 35 | } 36 | 37 | return strings.EqualFold(s, t) 38 | } 39 | -------------------------------------------------------------------------------- /stack/856_score_of_parentheses.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(scoreOfParentheses("(())")) // 2 7 | } 8 | 9 | // 可以,这很栈 10 | // 简化问题,解决 (()) 和 (()()) 即可 11 | func scoreOfParentheses(S string) int { 12 | var s Stack 13 | for _, r := range S { 14 | switch r { 15 | case '(': 16 | s.Push(-1) 17 | case ')': 18 | cur := 0 19 | for s.Peek() != -1 { 20 | cur += s.Pop() 21 | } 22 | s.Pop() 23 | if cur == 0 { 24 | s.Push(1) 25 | } else { 26 | s.Push(cur * 2) 27 | } 28 | } 29 | } 30 | 31 | sum := 0 32 | for !s.IsEmpty() { 33 | sum += s.Pop() 34 | } 35 | return sum 36 | } 37 | -------------------------------------------------------------------------------- /stack/stack.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "log" 6 | ) 7 | 8 | // 简单的栈定义 9 | // go run stack.go n_xxx.go 10 | type Stack []int 11 | 12 | func (s *Stack) Len() int { 13 | return len(*s) 14 | } 15 | 16 | func (s *Stack) IsEmpty() bool { 17 | return s.Len() == 0 18 | } 19 | 20 | func (s *Stack) Push(elem int) { 21 | *s = append(*s, elem) 22 | } 23 | 24 | var ERR_STACK_EMPTY = errors.New("stack is empty") 25 | 26 | func (s *Stack) Pop() int { 27 | n := s.Len() 28 | if n == 0 { 29 | log.Fatal(ERR_STACK_EMPTY) 30 | } 31 | peek := (*s)[n-1] 32 | *s = (*s)[:n-1] 33 | return peek 34 | } 35 | 36 | func (s *Stack) Peek() int { 37 | n := s.Len() 38 | if n == 0 { 39 | log.Fatal(ERR_STACK_EMPTY) 40 | } 41 | return (*s)[n-1] 42 | } 43 | -------------------------------------------------------------------------------- /stack/str_stack.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // 元素类型不一致,蛋疼 4 | // 可以试试 genny 类型生成器 5 | type StrStack []string 6 | 7 | func (s *StrStack) Len() int { 8 | return len(*s) 9 | } 10 | 11 | func (s *StrStack) IsEmpty() bool { 12 | return s.Len() == 0 13 | } 14 | 15 | func (s *StrStack) Push(elem string) { 16 | *s = append(*s, elem) 17 | } 18 | 19 | func (s *StrStack) Pop() string { 20 | n := s.Len() 21 | peek := (*s)[n-1] 22 | *s = (*s)[:n-1] 23 | return peek 24 | } 25 | 26 | func (s *StrStack) Peek() string { 27 | n := s.Len() 28 | return (*s)[n-1] 29 | } 30 | -------------------------------------------------------------------------------- /string/125_valid_palindrome.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(isPalindrome("0P")) 10 | } 11 | 12 | // 辣鸡解法 13 | // TODO: 优化效率 14 | func isPalindrome(s string) bool { 15 | s = strings.ToLower(s) 16 | str := "" 17 | for _, r := range s { 18 | if r >= 'a' && r <= 'z' || r >= '0' && r <= '9' { 19 | str += string(r) 20 | } 21 | } 22 | head, tail := 0, len(str)-1 23 | for head < tail { 24 | if str[head] != str[tail] { 25 | return false 26 | } 27 | head++ 28 | tail-- 29 | } 30 | return true 31 | } 32 | -------------------------------------------------------------------------------- /string/12_integer_to_roman.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(intToRoman(1994)) // MCMXCIV 7 | fmt.Println(intToRoman(20)) // XX 8 | } 9 | 10 | var ( 11 | m = map[int]string{ 12 | 1: "I", 13 | 4: "IV", 14 | 5: "V", 15 | 9: "IX", 16 | 10: "X", 17 | 40: "XL", 18 | 50: "L", 19 | 90: "XC", 20 | 100: "C", 21 | 400: "CD", 22 | 500: "D", 23 | 900: "CM", 24 | 1000: "M", 25 | } 26 | units = []int{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1} 27 | ) 28 | 29 | func intToRoman(num int) string { 30 | var roman string 31 | for num > 0 { 32 | for _, unit := range units { // 从大到小一个一个匹配 33 | if num/unit > 0 { 34 | roman += m[unit] 35 | num -= unit 36 | break // 匹配上一位,进行下一轮 // 20 是 XX 不是 XIXI(10+9+1) 37 | } 38 | } 39 | } 40 | return roman 41 | } 42 | -------------------------------------------------------------------------------- /string/13_roman_to_integer.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(romanToInt("MCMXCIV")) // 1994 7 | fmt.Println(romanToInt("LVIII")) // 58 8 | } 9 | 10 | var commonNums = map[string]int{ 11 | "I": 1, 12 | "V": 5, 13 | "X": 10, 14 | "L": 50, 15 | "C": 100, 16 | "D": 500, 17 | "M": 1000, 18 | } 19 | 20 | var preNums = map[string]int{ 21 | "IV": 4, 22 | "IX": 9, 23 | "XL": 40, 24 | "XC": 90, 25 | "CD": 400, 26 | "CM": 900, 27 | } 28 | 29 | func romanToInt(s string) int { 30 | n := len(s) 31 | if n == 1 { 32 | return commonNums[s] 33 | } 34 | res := 0 35 | for len(s) > 0 { 36 | if len(s) >= 2 { 37 | if num, ok := preNums[s[:2]]; ok { 38 | res += num 39 | s = s[2:] 40 | continue 41 | } 42 | } 43 | res += commonNums[string(s[:1])] 44 | s = s[1:] 45 | } 46 | return res 47 | } 48 | -------------------------------------------------------------------------------- /string/14_longest_common_prefix.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(longestCommonPrefix([]string{"flower", "fly", "flight"})) // fl 10 | fmt.Println(longestCommonPrefix([]string{"dog", "racecar", "car"})) // "" 11 | } 12 | 13 | // 维护一个前缀库,不断往后遍历,判断前缀逐步剪短前缀库的大小 14 | func longestCommonPrefix(strs []string) string { 15 | if len(strs) <= 0 { 16 | return "" 17 | } 18 | 19 | s1 := strs[0] 20 | prefixes := make([]string, len(s1)) 21 | for i := range s1 { 22 | prefixes[i] = s1[:i+1] 23 | } 24 | 25 | for _, s := range strs { 26 | for i, pre := range prefixes { 27 | if !strings.HasPrefix(s, pre) { 28 | prefixes = prefixes[:i] 29 | break 30 | } 31 | } 32 | } 33 | 34 | if len(prefixes) > 0 { 35 | return prefixes[len(prefixes)-1] 36 | } 37 | return "" 38 | } 39 | -------------------------------------------------------------------------------- /string/20_valid_parentheses.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(isValid("[")) 7 | fmt.Println(isValid("([)]")) 8 | } 9 | 10 | // 类似后缀表达式的匹配过程 11 | func isValid(s string) bool { 12 | var runes []rune 13 | for _, r := range s { 14 | switch r { 15 | case '(', '[', '{': 16 | runes = append(runes, r) 17 | case ')', ']', '}': 18 | if len(runes) > 0 && opposite(r) == runes[len(runes)-1] { 19 | runes = runes[:len(runes)-1] 20 | } else { 21 | return false 22 | } 23 | } 24 | } 25 | if len(runes) > 0 { 26 | return false 27 | } 28 | return true 29 | } 30 | 31 | func opposite(r rune) rune { 32 | switch r { 33 | case ')': 34 | return '(' 35 | case ']': 36 | return '[' 37 | case '}': 38 | return '{' 39 | } 40 | return '\n' 41 | } 42 | -------------------------------------------------------------------------------- /string/28_implement_strstr.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | fmt.Println(strStr("a", "")) 9 | } 10 | 11 | func strStr(haystack string, needle string) int { 12 | if len(needle) <= 0 { 13 | return 0 14 | } 15 | if len(needle) > len(haystack) { 16 | return -1 17 | } 18 | hs, ns := []rune(haystack), []rune(needle) 19 | lh, ln := len(hs), len(ns) 20 | var starts []int 21 | for i, h := range hs { 22 | if h == ns[0] { 23 | starts = append(starts, i) 24 | } 25 | } 26 | for _, start := range starts { 27 | if start+ln > lh { 28 | break 29 | } 30 | if string(hs[start:start+ln]) == needle { 31 | return start 32 | } 33 | } 34 | return -1 35 | } 36 | -------------------------------------------------------------------------------- /string/344_reverse_string.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(reverseString("hello")) 7 | } 8 | 9 | // 字符串可索引,但不可原地更改值 10 | func reverseString(s string) string { 11 | n := len(s) 12 | runes := make([]rune, 0, n) 13 | for i := n - 1; i >= 0; i-- { 14 | runes = append(runes, rune(s[i])) 15 | } 16 | return string(runes) 17 | } 18 | -------------------------------------------------------------------------------- /string/345_reverse_vowels_of_a_string.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(reverseVowels("ai")) 7 | } 8 | 9 | // 和对称相关的,考虑 2 种对称遍历方式 10 | // ... --l, mid, r++ ... // 考虑各种边界问题 11 | // l++, ..., --r // l <= r 相遇即边界 12 | func reverseVowels(s string) string { 13 | if s == "" { 14 | return s 15 | } 16 | runes := []rune(s) 17 | n := len(runes) 18 | l, r := 0, n-1 19 | 20 | for l <= r { 21 | for l < r && !isVowel(runes[l]) { 22 | l++ 23 | } 24 | for r > l && !isVowel(runes[r]) { 25 | r-- 26 | } 27 | if isVowel(runes[l]) && isVowel(runes[r]) { 28 | runes[l], runes[r] = runes[r], runes[l] 29 | } 30 | l++ 31 | r-- 32 | } 33 | return string(runes) 34 | } 35 | 36 | func isVowel(r rune) bool { 37 | switch r { 38 | case 'a', 'A', 'e', 'E', 'i', 'I', 'o', 'O', 'u', 'U': 39 | return true 40 | default: 41 | return false 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /string/383_ransom_note.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(canConstruct("aa", "ab")) 7 | } 8 | 9 | // 理清楚逻辑即可 10 | func canConstruct(ransomNote string, magazine string) bool { 11 | m1, m2 := make(map[rune]int), make(map[rune]int) 12 | for _, r := range ransomNote { 13 | m1[r]++ 14 | } 15 | for _, r := range magazine { 16 | m2[r]++ 17 | } 18 | for r, c1 := range m1 { 19 | if c2, ok := m2[r]; ok { 20 | if c1 > c2 { 21 | return false 22 | } 23 | } else { 24 | return false 25 | } 26 | } 27 | return true 28 | } 29 | -------------------------------------------------------------------------------- /string/387_first_unique_character_in_a_string.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(firstUniqChar("leetcode")) 7 | fmt.Println(firstUniqChar("loveleetcode")) 8 | } 9 | 10 | // 简单直观没啥好说的 11 | func firstUniqChar(s string) int { 12 | runeMap := make(map[rune]int) 13 | for _, r := range s { 14 | runeMap[r]++ 15 | } 16 | for i, r :=range s { 17 | if runeMap[r] == 1 { 18 | return i 19 | } 20 | } 21 | return -1 22 | } 23 | -------------------------------------------------------------------------------- /string/38_count_and_say.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(countAndSay(1)) 10 | fmt.Println(countAndSay(2)) 11 | fmt.Println(countAndSay(3)) 12 | fmt.Println(countAndSay(4)) 13 | } 14 | 15 | // 哈哈哈评论吐槽语体教 16 | // 静下心来读题 "按照上一个数,报数,得到下一个数",报数规则与 1 2 3 不同罢了 17 | func countAndSay(n int) string { 18 | tmp := "1" 19 | for i := 1; i < n; i++ { 20 | tmp = next(tmp) 21 | } 22 | return tmp 23 | } 24 | 25 | func next(s string) (res string) { 26 | nums := strings.Split(s, "") 27 | for i := 0; i < len(nums); { 28 | count := 1 29 | n := nums[i] 30 | for i < len(nums)-1 && nums[i] == nums[i+1] { 31 | count++ 32 | i++ 33 | } 34 | res += fmt.Sprintf("%d%s", count, n) // 计数连数字 35 | i++ 36 | } 37 | return res 38 | } 39 | -------------------------------------------------------------------------------- /string/434_number_of_segments_in_a_string.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "strings" 4 | 5 | func main() { 6 | // ... 我做了假的题 7 | } 8 | 9 | func countSegments(s string) int { 10 | return len(strings.Fields(s)) 11 | } 12 | -------------------------------------------------------------------------------- /string/520_detect_capital.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(detectCapitalUse("USA")) 7 | fmt.Println(detectCapitalUse("Leetcode")) 8 | fmt.Println(detectCapitalUse("mL")) 9 | } 10 | 11 | // 训练逻辑, it's ok 12 | func detectCapitalUse(word string) bool { 13 | if len(word) <= 1 { 14 | return true 15 | } 16 | 17 | firstUp := rune(word[0]) >= 'A' && rune(word[0]) <= 'Z' 18 | allUpCase, allLowCase := true, true 19 | for i := 1; i < len(word); i++ { 20 | r := rune(word[i]) 21 | if r < 'A' || r > 'Z' { 22 | allUpCase = false 23 | } 24 | if r < 'a' || r > 'z' { 25 | allLowCase = false 26 | } 27 | } 28 | 29 | if firstUp && (allUpCase || allLowCase) { 30 | return true 31 | } 32 | if !firstUp && allLowCase { 33 | return true 34 | } 35 | return false 36 | } 37 | -------------------------------------------------------------------------------- /string/521_longest_uncommon_subsequence_i.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(findLUSlength("aba", "cdc")) 7 | } 8 | 9 | // 哈希表长度不大,两两比较是很好的选择 10 | func findLUSlength(a string, b string) int { 11 | m1, m2 := subStr(a), subStr(b) 12 | maxSubSeq := 0 13 | for s := range m1 { 14 | if _, ok := m2[s]; !ok && len(s) > maxSubSeq { 15 | maxSubSeq = len(s) 16 | } 17 | } 18 | for s := range m2 { 19 | if _, ok := m1[s]; !ok && len(s) > maxSubSeq { 20 | maxSubSeq = len(s) 21 | } 22 | } 23 | if maxSubSeq == 0 { 24 | return -1 25 | } 26 | return maxSubSeq 27 | } 28 | 29 | func subStr(s string) map[string]int { 30 | n := len(s) 31 | m := make(map[string]int, (1+n)*n/2) // 等差数列长度 32 | for i := 0; i < n; i++ { 33 | for j := i; j < n; j++ { 34 | m[s[i:j+1]]++ 35 | } 36 | } 37 | return m 38 | } 39 | -------------------------------------------------------------------------------- /string/541_reverse_string_ii.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(reverseStr("abcdefg", 2)) // bacdfeg 7 | } 8 | 9 | // 逻辑... 10 | // 画区间图就简洁明了 11 | func reverseStr(s string, k int) string { 12 | runes := []rune(s) 13 | n := len(runes) 14 | 15 | reverse := func(rs []rune) []rune { 16 | s, e := 0, len(rs)-1 17 | for s <= e { 18 | rs[s], rs[e] = rs[e], rs[s] 19 | s++ 20 | e-- 21 | } 22 | return rs 23 | } 24 | 25 | res := make([]rune, 0, len(runes)) 26 | switch { 27 | case n < k: 28 | res = append(res, reverse(runes[:])...) 29 | case n < 2*k: 30 | res = append(res, reverse(runes[:k])...) 31 | default: 32 | segs := n / (2 * k) 33 | start := 0 34 | for i := 0; i < segs; i ++ { 35 | start = 2 * i * k 36 | res = append(res, reverse(runes[start:start+k])...) // 不断反转 [even*k, even*k+k-1] 偶数起始区间的字符 37 | } 38 | start += 2 * k 39 | remain := n - start 40 | switch { 41 | case remain < k: 42 | res = append(res, reverse(runes[start:])...) 43 | case remain < 2*k: 44 | res = append(res, reverse(runes[start:start+k])...) 45 | } 46 | } 47 | return string(runes) 48 | } 49 | -------------------------------------------------------------------------------- /string/551_student_attendance_record_i.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(checkRecord("PPALLL")) 7 | } 8 | 9 | // 2 个逻辑对应 2 个代码块 10 | func checkRecord(s string) bool { 11 | countA := 0 12 | for i := 0; i < len(s); i++ { 13 | if s[i] == 'A' { 14 | countA++ 15 | } 16 | 17 | if i < len(s)-2 && s[i] == 'L' && s[i+1] == 'L' && s[i+2] == 'L' { 18 | return false 19 | } 20 | } 21 | return countA <= 1 22 | } 23 | -------------------------------------------------------------------------------- /string/557_reverse_words_in_a_string_iii.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(reverseWords("Let's take LeetCode contest")) 10 | } 11 | 12 | // Field Split Join 是好搭档 13 | func reverseWords(s string) string { 14 | reverse := func(word string) string { 15 | n := len(word) 16 | runes := make([]rune, 0, n) 17 | for i := n - 1; i >= 0; i-- { 18 | runes = append(runes, rune(word[i])) 19 | } 20 | return string(runes) 21 | } 22 | words := strings.Fields(s) 23 | res := make([]string, 0, len(words)) 24 | for _, word := range words { 25 | res = append(res, reverse(word)) 26 | } 27 | return strings.Join(res, " ") 28 | } 29 | -------------------------------------------------------------------------------- /string/58_length_of_last_word.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(lengthOfLastWord("Hello World")) 10 | } 11 | 12 | // 捡了个 Golang 标准库的小便宜... 13 | func lengthOfLastWord(s string) int { 14 | words := strings.Fields(s) 15 | if len(words) <= 0 { 16 | return 0 17 | } 18 | return len(words[len(words)-1]) 19 | } 20 | -------------------------------------------------------------------------------- /string/5_longest_palindromic_substring.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(badLongestPalindrome("babad")) // bab 7 | fmt.Println(goodLongestPalindrome("babad")) // bab 8 | fmt.Println(bestLongestPalindrome("babad")) // bab 9 | } 10 | 11 | // 12 | // Manacher 马拉车算法 13 | // O(N) 检测最长回文子串 14 | // 15 | func bestLongestPalindrome(s string) string { 16 | if len(s) <= 1 { 17 | return s 18 | } 19 | 20 | t := "#" 21 | for _, r := range s { 22 | t += string(r) + "#" // 统一将 偶数串/奇数串 -> 奇数串 23 | } 24 | 25 | radius := make([]int, len(t)) // 每个位置的回文半径 26 | maxCenter := 0 // 到目前为止最长回文串的中心位置 27 | maxR := 0 // 到目前位置最长回文串的右边界索引 28 | stopCenter := 0 29 | maxRadius := 0 30 | 31 | for i := 0; i < len(t); i++ { 32 | mirror := 2*maxCenter - i 33 | if i < maxR { // 没有超过最大右边界 34 | radius[i] = min(radius[mirror], maxR-i) // 取 [i,mx] 与 i'半径 的最小值 35 | } 36 | 37 | // 以 i 为中心不断扩充半径,向左右两侧探测回文 38 | // 不要以为这里复杂度为 O(N) 39 | // 若上边 radius[i] = radius[i'],则不会再进入循环扩张半径 40 | for i+1+radius[i] < len(t) && i-1-radius[i] >= 0 && t[i-1-radius[i]] == t[i+1+radius[i]] { 41 | radius[i]++ 42 | } 43 | 44 | // 超出了边缘 45 | if i+radius[i] > maxR { 46 | maxR = i + radius[i] 47 | maxCenter = i 48 | } 49 | 50 | if radius[i] > maxRadius { 51 | maxRadius = radius[i] 52 | stopCenter = i 53 | } 54 | } 55 | l := stopCenter/2 - maxRadius/2 // t->s,索引取中 56 | r := l + maxRadius - 1 // 减掉自身 57 | return string(s[l : r+1]) // bingo 58 | } 59 | 60 | func min(x, y int) int { 61 | if x < y { 62 | return x 63 | } 64 | return y 65 | } 66 | 67 | // 68 | // Golang 的题解中不要使用全局作用域变量,OJ 每个 case 不会予以清零 69 | // O(N^2) 复杂度 70 | // 71 | func goodLongestPalindrome(s string) string { 72 | runes := []rune(s) 73 | var maxLen int 74 | var maxSubStr string 75 | for i := range runes { 76 | length, str := spread(runes, i, i, maxLen) // aba 77 | if length > maxLen { 78 | maxLen = length 79 | maxSubStr = str 80 | } 81 | length, str = spread(runes, i, i+1, maxLen) // abba 82 | if length > maxLen { 83 | maxLen = length 84 | maxSubStr = str 85 | } 86 | } 87 | return maxSubStr 88 | } 89 | 90 | // 以中心点向两侧扩散,获取当前字符为中心的最大回文串 91 | func spread(runes []rune, l, r int, curMaxLen int) (length int, subStr string) { 92 | length = curMaxLen 93 | for ; l >= 0 && r <= len(runes)-1 && runes[l] == runes[r]; l, r = l-1, r+1 { 94 | if r-l+1 >= length { // <= 是因为 OJ 认为 babad 的答案是 aba 而非 bab 95 | length = r - l + 1 96 | subStr = string(runes[l : r+1]) 97 | } 98 | } 99 | return 100 | } 101 | 102 | // 103 | // O(N^3) 复杂度 104 | // 105 | func badLongestPalindrome(s string) string { 106 | runes := []rune(s) 107 | n := len(runes) 108 | if n <= 1 { 109 | return s 110 | } 111 | 112 | maxLen := 0 113 | maxL, maxR := 0, 0 114 | for i := 0; i < n; i++ { 115 | for j := i + 1; j < n; j++ { 116 | if isPalindrome(runes[i:j+1]) && j-i+1 > maxLen { 117 | maxLen = j - i + 1 118 | maxL, maxR = i, j 119 | } 120 | } 121 | } 122 | return string(runes[maxL : maxR+1]) // 注意对空字符串,转换为 "\u0000" 123 | } 124 | 125 | // O(N) 判断是否为回文字符串 126 | func isPalindrome(runes []rune) bool { 127 | l, r := 0, len(runes)-1 128 | for l <= r { 129 | if runes[l] != runes[r] { 130 | return false 131 | } 132 | l++ 133 | r-- 134 | } 135 | return true 136 | } 137 | -------------------------------------------------------------------------------- /string/657_robot_return_to_origin.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(judgeCircle("UD")) 7 | fmt.Println(judgeCircle("LL")) 8 | } 9 | 10 | // 想要回到原点,向左必须抵消向右,向上必须抵消向下 11 | // 代码简洁性不错 12 | func judgeCircle(moves string) bool { 13 | horizontal, vertical := 0, 0 14 | for _, move := range []rune(moves) { 15 | switch move { 16 | case 'R': 17 | horizontal++ 18 | case 'L': 19 | horizontal-- 20 | case 'U': 21 | vertical++ 22 | case 'D': 23 | vertical-- 24 | } 25 | } 26 | return horizontal == 0 && vertical == 0 27 | } 28 | -------------------------------------------------------------------------------- /string/67_add_binary.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | fmt.Println(addBinary("11", "1")) 9 | fmt.Println(addBinary("1010", "1011")) 10 | } 11 | 12 | // 考虑溢出 ok? 不是 strconv.ParseInt(a, 2, 64) 然后相加就能搞定的... 13 | // 任意进制的任意长度数字相加,需从前向后遍历,求和后取余,并考虑进位 14 | func addBinary(a string, b string) string { 15 | i1, i2 := len(a)-1, len(b)-1 16 | res := "" 17 | carry := 0 18 | for i1 >= 0 || i2 >= 0 { 19 | sum := carry 20 | if i1 >= 0 { 21 | sum += int(rune(a[i1]) - '0') // '0' == 49 // ASCII 22 | i1-- 23 | } 24 | if i2 >= 0 { 25 | sum += int(rune(b[i2]) - '0') 26 | i2-- 27 | } 28 | 29 | carry = sum / 2 30 | sum = sum % 2 31 | if sum == 0 { 32 | res += "0" 33 | } else { 34 | res += "1" 35 | } 36 | } 37 | 38 | if carry > 0 { 39 | res += "1" 40 | } 41 | 42 | return reverseStr(res) 43 | } 44 | 45 | func reverseStr(s string) string { 46 | runes := []rune(s) 47 | n := len(runes) 48 | mid := n / 2 49 | for i := 0; i < mid; i++ { 50 | runes[i], runes[n-1-i] = runes[n-1-i], runes[i] 51 | } 52 | return string(runes) 53 | } 54 | -------------------------------------------------------------------------------- /string/686_repeated_string_match.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(repeatedStringMatch("abcd", "abcdabcdabcd")) // 3 10 | fmt.Println(repeatedStringMatch("abc", "cabcabca")) // 4 11 | } 12 | 13 | // b 最多要 a 重复 a+Na+a 次 14 | func repeatedStringMatch(A string, B string) int { 15 | count := 1 16 | a := A 17 | maxCount := len(B)/len(A) + 2 18 | for count <= maxCount { 19 | if strings.Contains(A, B) { 20 | return count 21 | } 22 | A += a 23 | count++ 24 | } 25 | return -1 26 | } 27 | -------------------------------------------------------------------------------- /string/696_count_binary_substrings.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(countBinarySubstrings("00110011")) 7 | } 8 | 9 | // 理解题意:相同数量 0 和 1 的子串 10 | // 统计遍历考虑处理第一个元素后,从第二个开始向前遍历 11 | // 相比于从第一个遍历到倒数第二个要简洁易处理 12 | func countBinarySubstrings(s string) int { 13 | if len(s) <= 0 { 14 | return 0 15 | } 16 | 17 | zeroCount, oneCount := 0, 0 18 | if s[0] == '0' { 19 | zeroCount++ 20 | } else { 21 | oneCount++ 22 | } 23 | 24 | counts := 0 25 | for i := 1; i < len(s); i++ { 26 | switch s[i] { 27 | case '0': 28 | if s[i-1] == '0' { 29 | zeroCount++ 30 | } else { 31 | zeroCount = 1 32 | } 33 | if oneCount >= zeroCount { // 对称 34 | counts++ 35 | } 36 | case '1': 37 | if s[i-1] == '1' { 38 | oneCount++ 39 | } else { 40 | oneCount = 1 41 | } 42 | if zeroCount >= oneCount { 43 | counts++ 44 | } 45 | } 46 | } 47 | return counts 48 | } 49 | -------------------------------------------------------------------------------- /string/6_zigzag_conversion.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(convert("ABCDEFGHIJKLMN", 4)) // AGMBFHLNCEIKDJ 7 | } 8 | 9 | func convert(s string, numRows int) string { 10 | n := len(s) 11 | if n <= 1 || numRows <= 1 { 12 | return s 13 | } 14 | 15 | lines := make([][]rune, numRows) 16 | for i := 0; i < n; { 17 | // 向下走 18 | for r := 0; r <= numRows-1 && i < n; r++ { 19 | lines[r] = append(lines[r], rune(s[i])) 20 | i++ 21 | } 22 | // 向右上方走 23 | for r := numRows - 2; r >= 1 && i < n; r-- { 24 | lines[r] = append(lines[r], rune(s[i])) 25 | i++ 26 | } 27 | } 28 | 29 | var str string 30 | for _, line := range lines { 31 | for _, r := range line { 32 | str += string(r) 33 | } 34 | } 35 | 36 | return str 37 | } 38 | -------------------------------------------------------------------------------- /string/709_to_lower_case.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(toLowerCase("Hello")) 7 | } 8 | 9 | func toLowerCase(str string) string { 10 | const charDiff = 'a' - 'A' 11 | newStr := "" 12 | for _, r := range []rune(str) { 13 | if r < 'A' || r > 'Z' { 14 | newStr += string(r) // 非大写字母 15 | continue 16 | } 17 | newStr += string(r + charDiff) 18 | } 19 | return newStr 20 | } 21 | -------------------------------------------------------------------------------- /string/788_rotated_digits.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(rotatedDigits(2)) 7 | } 8 | 9 | // 审好题,有逻辑就 ok 10 | func rotatedDigits(N int) int { 11 | counts := 0 12 | for n := 1; n <= N; n++ { 13 | if valid, res := rotate(n); valid && n != res { 14 | counts++ 15 | } 16 | } 17 | return counts 18 | } 19 | 20 | func rotate(num int) (valid bool, res int) { 21 | valid = true 22 | var nums []int 23 | for num > 0 { 24 | nums = append(nums, num%10) // 分割 25 | num /= 10 26 | } 27 | 28 | for i, n := range nums { // 旋转 29 | switch n { 30 | case 0, 1, 8: 31 | case 2: 32 | nums[i] = 5 33 | case 5: 34 | nums[i] = 2 35 | case 6: 36 | nums[i] = 9 37 | case 9: 38 | nums[i] = 6 39 | default: 40 | valid = false 41 | } 42 | } 43 | 44 | fmt.Println(nums) 45 | if valid { 46 | for i, n := range nums { // 重组 47 | res += n * pow(10, i) 48 | } 49 | } 50 | return 51 | } 52 | 53 | func pow(x, y int) int { 54 | res := 1 55 | for y > 0 { 56 | res *= x 57 | y-- 58 | } 59 | return res 60 | } 61 | -------------------------------------------------------------------------------- /string/819_most_common_word.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(mostCommonWord("Bob hit a ball, the hit BALL flew far after it was hit.", []string{"hit"})) 10 | } 11 | 12 | // 没啥好说的,无脑哈希表 13 | func mostCommonWord(paragraph string, banned []string) string { 14 | 15 | s := strings.ToLower(paragraph) 16 | words := strings.FieldsFunc(s, func(r rune) bool { 17 | if r >= 'a' && r <= 'z' { 18 | return false 19 | } 20 | return true 21 | }) 22 | 23 | bannedM := make(map[string]interface{}) 24 | for _, word := range banned { 25 | bannedM[word] = nil 26 | } 27 | wordsM := make(map[string]int) 28 | for _, word := range words { 29 | wordsM[word]++ 30 | } 31 | 32 | for word := range wordsM { 33 | if _, ok := bannedM[word]; ok { 34 | delete(wordsM, word) 35 | } 36 | } 37 | 38 | maxCounts, mostCommon := 0, "" 39 | for word, count := range wordsM { 40 | if count > maxCounts { 41 | mostCommon = word 42 | maxCounts = count 43 | } 44 | } 45 | return mostCommon 46 | } 47 | -------------------------------------------------------------------------------- /string/824_goat_latin.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(toGoatLatin("I speak Goat Latin")) 10 | fmt.Println(toGoatLatin("Each word consists of lowercase and uppercase letters only")) 11 | } 12 | 13 | // 主要是捋清楚规则 14 | func toGoatLatin(S string) string { 15 | words := strings.Fields(S) 16 | newWords := make([]string, 0, len(words)) 17 | for i, word := range words { 18 | switch word[0] { 19 | case 'a', 'A', 'e', 'E', 'i', 'I', 'o', 'O', 'u', 'U': // 提及规则的时候,再简单的已知条件(元音:大小写)也要分析清楚 20 | word += "ma" 21 | default: 22 | word = word[1:] + string(word[0]) + "ma" 23 | } 24 | i += 1 25 | for i > 0 { 26 | word += "a" 27 | i-- 28 | } 29 | newWords = append(newWords, word) 30 | } 31 | return strings.Join(newWords, " ") 32 | } 33 | -------------------------------------------------------------------------------- /string/859_buddy_strings.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(buddyStrings("", "")) // false 7 | fmt.Println(buddyStrings("aa", "aa")) // true 8 | fmt.Println(buddyStrings("ab", "ab")) // false 9 | fmt.Println(buddyStrings("abab", "abab")) // true 10 | fmt.Println(buddyStrings("abcd", "abcd")) // false 11 | } 12 | 13 | 14 | // 捋清楚逻辑,找规律... 15 | func buddyStrings(A string, B string) bool { 16 | if len(A) != len(B) || A == "" || B == "" { 17 | return false 18 | } 19 | diff := make([]int, 0, 2) 20 | for index := range B { 21 | if A[index] != B[index] { 22 | diff = append(diff, index) 23 | } 24 | } 25 | switch len(diff) { 26 | case 0: 27 | repeat := false 28 | for i := 1; i < len(A); i++ { 29 | if A[0] == A[i] { 30 | repeat = true 31 | } 32 | } 33 | return repeat 34 | case 1: 35 | return false 36 | case 2: 37 | runes := []rune(A) 38 | runes[diff[0]], runes[diff[1]] = runes[diff[1]], runes[diff[0]] 39 | return string(runes) == B 40 | } 41 | return false 42 | } 43 | -------------------------------------------------------------------------------- /string/893_groups_of_special_equivalent_strings.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | "strings" 7 | ) 8 | 9 | func main() { 10 | fmt.Println(numSpecialEquivGroups([]string{"a", "b", "c"})) // 3 // 自己和自己是特殊等价的 11 | fmt.Println(numSpecialEquivGroups([]string{"abc", "acb", "bac", "bca", "cab", "cba"})) // 3 12 | fmt.Println(numSpecialEquivGroups([]string{"abcd", "cdab", "adcb", "cbad"})) // 1 13 | } 14 | 15 | // 不要暴力的用 map 和 inSlice 的多重遍历去判断,搞复杂了 16 | // 抓住题目本质:特殊等价字符串,即奇数位、偶数位字符数组随意排列组合后仍认为是等价的 17 | // 相同元素的不同排列组合,排序后是一致的。判断 2 个 []string 是否一致也是这个道理 18 | func numSpecialEquivGroups(A []string) int { 19 | m := make(map[string]int, len(A)/2) 20 | // 所有 21 | for _, s := range A { 22 | var evens, odds []string 23 | for i := 0; i < len(s); i += 2 { 24 | evens = append(evens, string(s[i])) 25 | } 26 | for i := 1; i < len(s); i += 2 { 27 | odds = append(odds, string(s[i])) 28 | } 29 | sort.Strings(evens) 30 | sort.Strings(odds) 31 | sortedS := strings.Join(evens, "") + strings.Join(odds, "") 32 | m[sortedS]++ 33 | } 34 | return len(m) 35 | } 36 | -------------------------------------------------------------------------------- /string/8_string_to_integer_atoi.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | fmt.Println(myAtoi("-10")) // -10 10 | fmt.Println(myAtoi("9223372036854775808")) // 2147483647 11 | } 12 | 13 | const ( 14 | INT_MIN = -1 << 31 15 | INT_MAX = 1<<31 - 1 16 | ) 17 | 18 | // 正常的整数字符串只有 3 种case 19 | // 10 20 | // +10 21 | // -10 22 | // 注意处理溢出的情形 23 | func myAtoi(str string) int { 24 | str = strings.TrimSpace(str) 25 | if len(str) == 0 { 26 | return 0 27 | } 28 | 29 | positive := true 30 | switch str[0] { 31 | case '-': 32 | positive = false 33 | str = str[1:] 34 | case '+': 35 | str = str[1:] 36 | } 37 | 38 | var nums []rune 39 | for _, r := range str { 40 | if r < '0' || r > '9' { 41 | break 42 | } 43 | nums = append(nums, r) 44 | } 45 | 46 | var n int 47 | for _, num := range nums { 48 | n = 10*n + int(num-'0') 49 | if positive && n > INT_MAX { 50 | return INT_MAX 51 | } 52 | if !positive && -n < INT_MIN { 53 | return INT_MIN 54 | } 55 | } 56 | 57 | if !positive { 58 | return -n 59 | } 60 | return n 61 | } 62 | -------------------------------------------------------------------------------- /tree/100_same_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | // just bingo 5 | } 6 | 7 | func isSameTree(p *TreeNode, q *TreeNode) bool { 8 | return same(p, q) 9 | } 10 | 11 | func same(node1, node2 *TreeNode) bool { 12 | if node1 == nil && node2 == nil { 13 | return true 14 | } 15 | if node1 == nil || node2 == nil { // 先 && 再 || 相当于 1+2=3 种判断 16 | return false 17 | } 18 | return node1.Val == node2.Val && same(node1.Left, node2.Left) && same(node1.Right, node2.Right) 19 | } 20 | -------------------------------------------------------------------------------- /tree/101_symmetric_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | // just bingo 5 | } 6 | 7 | func isSymmetric(root *TreeNode) bool { 8 | return mirror(root, root) 9 | } 10 | 11 | // 镜像树:递归交换左右子树 12 | func mirror(node1, node2 *TreeNode) bool { 13 | if node1 == nil && node2 == nil { 14 | return true 15 | } 16 | 17 | if node1 == nil || node2 == nil { 18 | return false 19 | } 20 | 21 | // 左子树与右子树值一致 22 | return node1.Val == node2.Val && mirror(node1.Left, node2.Right) && mirror(node1.Right, node2.Left) 23 | } 24 | -------------------------------------------------------------------------------- /tree/102_binary_tree_level_order_traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | tree := &Tree{} 7 | tree.root = &TreeNode{Val: 4} 8 | for _, v := range []int{2, 7, 1, 3, 6, 9} { 9 | tree.BFSInsert(v) 10 | } 11 | fmt.Println(levelOrder(tree.root)) 12 | } 13 | 14 | // 层次遍历(宽度优先遍历) 15 | func levelOrder(root *TreeNode) [][]int { 16 | if root == nil { 17 | return nil 18 | } 19 | 20 | var res [][]int 21 | queue := []*TreeNode{root} 22 | for len(queue) > 0 { 23 | var floor []int 24 | level := len(queue) // level 表示第几层,用于取出当前层的所有值 25 | for i := 0; i < level; i++ { 26 | cur := queue[0] 27 | queue = queue[1:] 28 | if cur.Left != nil { 29 | queue = append(queue, cur.Left) 30 | } 31 | if cur.Right != nil { 32 | queue = append(queue, cur.Right) 33 | } 34 | floor = append(floor, cur.Val) 35 | } 36 | res = append(res, floor) 37 | } 38 | return res 39 | } 40 | -------------------------------------------------------------------------------- /tree/104_maximum_depth_of_binary_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | tree := &Tree{} 7 | tree.root = &TreeNode{Val: 3} 8 | for _, v := range []int{9, 20, -1, -1, 15, 7} { 9 | tree.BFSInsert(v) 10 | } 11 | fmt.Println(maxDepth(tree.root)) // 3 12 | } 13 | 14 | func maxDepth(root *TreeNode) int { 15 | if root == nil { 16 | return 0 17 | } 18 | lDepth := maxDepth(root.Left) 19 | rDepth := maxDepth(root.Right) 20 | if lDepth > rDepth { 21 | return lDepth + 1 22 | } 23 | return rDepth + 1 24 | } 25 | -------------------------------------------------------------------------------- /tree/105_construct_binary_tree_from_preorder_and_inorder_traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | pre := []int{7, 4, 1, 6, 5, 13, 8, 26} 7 | in := []int{1, 4, 6, 5, 7, 8, 13, 26} 8 | root := buildTree(pre, in) 9 | fmt.Println(root.Val) 10 | fmt.Println(root.Left) 11 | fmt.Println(root.Left.Left) 12 | fmt.Println(root.Left.Right) 13 | fmt.Println("----------") 14 | fmt.Println(root.Right) 15 | fmt.Println(root.Right.Left) 16 | fmt.Println(root.Right.Right) 17 | } 18 | 19 | // 还原二叉树 20 | // 根据先序遍历或后序遍历,先找出根节点,确定好左子树与右子树 21 | // 对左子树进行如上递归分析,对右子树进行递归分析 22 | func buildTree(preorder []int, inorder []int) *TreeNode { 23 | return build(preorder, inorder) 24 | } 25 | 26 | func build(preorder []int, inorder []int) *TreeNode { 27 | if len(preorder) == 0 || len(inorder) == 0 { 28 | return nil 29 | } 30 | if len(preorder) == 1 { 31 | return &TreeNode{Val: preorder[0]} 32 | } 33 | if len(inorder) == 1 { 34 | return &TreeNode{Val: inorder[0]} 35 | } 36 | 37 | root := &TreeNode{Val: preorder[0]} 38 | var i int 39 | for ; i < len(inorder); i++ { 40 | if inorder[i] == preorder[0] { 41 | break 42 | } 43 | } 44 | 45 | lPreorder := preorder[1 : i+1] 46 | rPreorder := preorder[i+1:] 47 | root.Left = build(lPreorder, inorder[:i]) 48 | root.Right = build(rPreorder, inorder[i+1:]) 49 | return root 50 | } 51 | -------------------------------------------------------------------------------- /tree/106_construct_binary_tree_from_inorder_and_postorder_traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | post := []int{1, 5, 6, 4, 8, 26, 13, 7} 7 | in := []int{1, 4, 6, 5, 7, 8, 13, 26} 8 | root := buildTree(in, post) 9 | fmt.Println(root.Val) 10 | fmt.Println(root.Left) 11 | fmt.Println(root.Left.Left) 12 | fmt.Println(root.Right) 13 | fmt.Println(root.Right.Right) 14 | } 15 | 16 | func buildTree(inorder []int, postorder []int) *TreeNode { 17 | return build(inorder, postorder) 18 | } 19 | 20 | func build(inorder []int, postorder []int) *TreeNode { 21 | if len(inorder) == 0 || len(postorder) == 0 { 22 | return nil 23 | } 24 | if len(inorder) == 1 { 25 | return &TreeNode{Val: inorder[0]} 26 | } 27 | if len(postorder) == 1 { 28 | return &TreeNode{Val: postorder[0]} 29 | } 30 | 31 | // 后序遍历的最后一个节点为根节点 32 | rootV := postorder[len(postorder)-1] 33 | var i int 34 | for ; i < len(inorder); i++ { 35 | if inorder[i] == rootV { 36 | break 37 | } 38 | } 39 | root := &TreeNode{Val: rootV} 40 | root.Left = build(inorder[:i], postorder[:i]) // inorder 向前为左子树 41 | root.Right = build(inorder[i+1:], postorder[i:len(postorder)-1]) // inorder 向后为右子树 42 | return root 43 | } 44 | -------------------------------------------------------------------------------- /tree/107_binary_tree_level_order_traversal_ii.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | tree := &Tree{} 7 | tree.root = &TreeNode{Val: 3} 8 | for _, v := range []int{9, 20, 15, 7} { 9 | tree.BFSInsert(v) 10 | } 11 | fmt.Println(levelOrderBottom(tree.root)) 12 | } 13 | 14 | func levelOrderBottom(root *TreeNode) [][]int { 15 | if root == nil { 16 | return nil 17 | } 18 | 19 | var res [][]int 20 | queue := []*TreeNode{root} 21 | for len(queue) > 0 { 22 | var floor []int 23 | level := len(queue) 24 | 25 | for i := 0; i < level; i++ { 26 | cur := queue[0] 27 | queue = queue[1:] 28 | floor = append(floor, cur.Val) 29 | 30 | if cur.Left != nil { 31 | queue = append(queue, cur.Left) 32 | } 33 | if cur.Right != nil { 34 | queue = append(queue, cur.Right) 35 | } 36 | } 37 | 38 | res = append(res, floor) 39 | } 40 | 41 | // 反转即可 42 | for i, j := 0, len(res)-1; i < j; i, j = i+1, j-1 { 43 | res[i], res[j] = res[j], res[i] 44 | } 45 | return res 46 | } 47 | -------------------------------------------------------------------------------- /tree/108_convert_sorted_array_to_binary_search_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := sortedArrayToBST([]int{0, 1, 2, 3, 4, 5}) 7 | fmt.Println(root) 8 | fmt.Println(root.Left) 9 | fmt.Println(root.Left.Left) 10 | fmt.Println(root.Left.Right) 11 | fmt.Println(root.Right) 12 | fmt.Println(root.Right.Left) // bingo 13 | } 14 | 15 | func sortedArrayToBST(nums []int) *TreeNode { 16 | return construct(nums) 17 | } 18 | 19 | func construct(nums []int) *TreeNode { 20 | n := len(nums) 21 | if n == 0 { 22 | return nil 23 | } 24 | if n == 1 { 25 | return &TreeNode{Val: nums[0]} 26 | } 27 | 28 | // 尽可能地取中间的值作为根节点 29 | mid := n / 2 30 | root := &TreeNode{Val: nums[mid]} 31 | root.Left = construct(nums[:mid]) // 左子数组作为左子树 32 | root.Right = construct(nums[mid+1:]) // 右子数组作为右子树 // 地达到 AVL 树特点 33 | return root 34 | } 35 | -------------------------------------------------------------------------------- /tree/110_balanced_binary_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | // debug in LeetCode Code editor 5 | } 6 | 7 | // 递归从下往上判断各子树的平衡结果 8 | func isBalanced(root *TreeNode) bool { 9 | if root == nil { 10 | return true 11 | } 12 | 13 | lDepth := depth(root.Left) 14 | rDepth := depth(root.Right) 15 | if abs(lDepth-rDepth) > 1 { // 平衡条件 16 | return false 17 | } 18 | 19 | return isBalanced(root.Left) && isBalanced(root.Right) 20 | } 21 | 22 | // 某子树的深度 23 | func depth(root *TreeNode) int { 24 | if root == nil { 25 | return 0 26 | } 27 | 28 | lDepth := depth(root.Left) + 1 29 | rDepth := depth(root.Right) + 1 // 加节点本身的深度 30 | 31 | if lDepth > rDepth { 32 | return lDepth 33 | } 34 | return rDepth 35 | } 36 | 37 | func abs(x int) int { 38 | if x < 0 { 39 | return -x 40 | } 41 | return x 42 | } 43 | -------------------------------------------------------------------------------- /tree/111_minimum_depth_of_binary_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | tree := &Tree{} 7 | tree.root = &TreeNode{Val: 1} 8 | for _, v := range []int{2} { 9 | tree.BFSInsert(v) // 自己写的破 insert 调试半天 fuck 10 | } 11 | fmt.Println(minDepth(tree.root)) // 2 12 | } 13 | 14 | func minDepth(root *TreeNode) int { 15 | return depth(root) 16 | } 17 | 18 | func depth(root *TreeNode) int { 19 | if root == nil { 20 | return 0 21 | } 22 | 23 | lDepth := depth(root.Left) 24 | rDepth := depth(root.Right) 25 | 26 | if lDepth == 0 { // 左边走到尽头,只能往右边走 27 | return rDepth + 1 28 | } 29 | if rDepth == 0 { // 往左边走 30 | return lDepth + 1 31 | } 32 | 33 | return min(lDepth, rDepth) + 1 // 两边都可以走,选最浅的子树 34 | } 35 | 36 | func min(x, y int) int { 37 | if x > y { 38 | return y 39 | } 40 | return x 41 | } 42 | -------------------------------------------------------------------------------- /tree/112_path_sum.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | tree := &Tree{} 7 | tree.root = &TreeNode{Val: 5} 8 | tree.root.Left = &TreeNode{Val: 4} 9 | tree.root.Right = &TreeNode{Val: 8} 10 | fmt.Println(hasPathSum(tree.root, 13)) // true 11 | } 12 | 13 | func hasPathSum(root *TreeNode, sum int) bool { 14 | var sums []int 15 | traverse(root, &sums) 16 | for _, v := range sums { 17 | if v == sum { 18 | return true 19 | } 20 | } 21 | return false 22 | } 23 | 24 | // 遍历将父节点的值存储到子节点中 25 | // 若是叶子节点则算作一个 sum 26 | func traverse(root *TreeNode, sums *[]int) { 27 | if root == nil { 28 | return 29 | } 30 | 31 | // 叶子节点 32 | if root.Left == nil && root.Right == nil { 33 | *sums = append(*sums, root.Val) // bingo 34 | } 35 | if root.Left != nil { 36 | root.Left.Val += root.Val 37 | } 38 | if root.Right != nil { 39 | root.Right.Val += root.Val 40 | } 41 | traverse(root.Left, sums) 42 | traverse(root.Right, sums) 43 | } 44 | -------------------------------------------------------------------------------- /tree/113_path_sum_ii.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 5} 7 | root.Right = &TreeNode{Val: 8} 8 | root.Right.Right = &TreeNode{Val: 4} 9 | root.Right.Right.Right = &TreeNode{Val: 1} 10 | root.Right.Right.Left = &TreeNode{Val: 5} 11 | 12 | // traverse 内部需要对 curPath 进行 copy 操作,否则结果就是 [[5 8 4 1]] 13 | fmt.Println(pathSum(root, 22)) 14 | } 15 | 16 | func pathSum(root *TreeNode, sum int) [][]int { 17 | var paths [][]int 18 | traverse(root, 0, sum, nil, &paths) 19 | return paths 20 | } 21 | 22 | // 每个节点都只对应一种路径 23 | // 这里 curPath 每个节点对应的值不同,不传指针 24 | func traverse(root *TreeNode, curSum, target int, curPath []int, paths *[][]int) { 25 | if root == nil { 26 | return 27 | } 28 | 29 | curPath = append(curPath, root.Val) 30 | curSum = curSum + root.Val 31 | if root.Left == nil && root.Right == nil && curSum == target { 32 | *paths = append(*paths, curPath) // bingo 33 | return 34 | } 35 | 36 | // Golang 中 slice 是传址引用,必须 copy 后使用 37 | lPath := make([]int, len(curPath)) 38 | copy(lPath, curPath) 39 | rPath := make([]int, len(curPath)) 40 | copy(rPath, curPath) 41 | 42 | traverse(root.Left, curSum, target, lPath, paths) // recording... 43 | traverse(root.Right, curSum, target, rPath, paths) // 一个节点一条路 44 | } 45 | -------------------------------------------------------------------------------- /tree/114_flatten_binary_tree_to_linked_list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 1} 7 | root.Left = &TreeNode{Val: 2} 8 | root.Left.Left = &TreeNode{Val: 3} 9 | root.Left.Right = &TreeNode{Val: 4} 10 | root.Right = &TreeNode{Val: 5} 11 | flatten(root) 12 | 13 | fmt.Println(root) 14 | fmt.Println(root.Right) 15 | fmt.Println(root.Right.Right) 16 | fmt.Println(root.Right.Right.Right) 17 | fmt.Println(root.Right.Right.Right.Right) 18 | } 19 | 20 | // 原地展开,不能先序遍历建新树 21 | // 1 22 | // / \ 23 | // 2 5 24 | 25 | // 1 26 | // \ 27 | // 2 28 | // \ 29 | // 5 30 | func flatten(root *TreeNode) { 31 | if root == nil { 32 | return 33 | } 34 | if root.Left == nil && root.Right == nil { 35 | return 36 | } 37 | 38 | flatten(root.Left) 39 | flatten(root.Right) 40 | 41 | if root.Left != nil { 42 | lastNode := root.Right 43 | root.Right = root.Left // 把左子树挪到右子树上 44 | 45 | cur := root 46 | for cur.Right != nil { 47 | cur = cur.Right 48 | } 49 | cur.Right = lastNode // 把旧右子树接到新右子树 50 | root.Left = nil // 清空左子树 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tree/124_binary_tree_maximum_path_sum.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 1} 7 | root.Left = &TreeNode{Val: 2} 8 | root.Right = &TreeNode{Val: 3} 9 | // root.Right.Left = &TreeNode{Val: 15} 10 | // root.Right.Right = &TreeNode{Val: 7} 11 | fmt.Println(maxPathSum(root)) 12 | } 13 | 14 | func maxPathSum(root *TreeNode) int { 15 | if root == nil { 16 | return 0 17 | } 18 | max := -1 << 31 19 | pathSum(root, &max) 20 | return max 21 | } 22 | 23 | func pathSum(node *TreeNode, maxSum *int) int { 24 | if node == nil { 25 | return 0 26 | } 27 | 28 | lSum := pathSum(node.Left, maxSum) 29 | rSum := pathSum(node.Right, maxSum) 30 | 31 | curSum := node.Val 32 | if lSum > 0 { 33 | curSum += lSum 34 | } 35 | if rSum > 0 { 36 | curSum += rSum 37 | } 38 | 39 | *maxSum = max(*maxSum, curSum) 40 | return max(node.Val, node.Val+lSum, node.Val+rSum) 41 | } 42 | 43 | func max(nums ...int) int { 44 | m := nums[0] 45 | for _, n := range nums[1:] { 46 | if n > m { 47 | m = n 48 | } 49 | } 50 | return m 51 | } 52 | -------------------------------------------------------------------------------- /tree/129_sum_root_to_leaf_numbers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 4} 7 | root.Left = &TreeNode{Val: 9} 8 | root.Right = &TreeNode{Val: 0} 9 | root.Left.Left = &TreeNode{Val: 5} 10 | root.Left.Right = &TreeNode{Val: 1} 11 | fmt.Println(sumNumbers(root)) // 1026 12 | } 13 | 14 | // 和 112 113 一模一样 15 | func sumNumbers(root *TreeNode) int { 16 | var sums []int 17 | traverse(root, 0, &sums) 18 | var sum int 19 | for _, v := range sums { 20 | sum += v 21 | } 22 | return sum 23 | } 24 | 25 | // 遍历求和并取叶子节点即可 26 | func traverse(root *TreeNode, curSum int, nums *[]int) { 27 | if root == nil { 28 | return 29 | } 30 | 31 | curSum *= 10 32 | curSum += root.Val 33 | if root.Left == nil && root.Right == nil { 34 | *nums = append(*nums, curSum) 35 | } 36 | 37 | traverse(root.Left, curSum, nums) 38 | traverse(root.Right, curSum, nums) 39 | } 40 | -------------------------------------------------------------------------------- /tree/144_binary_tree_preorder_traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 4} 7 | root.Left = &TreeNode{Val: 9} 8 | root.Right = &TreeNode{Val: 0} 9 | root.Left.Left = &TreeNode{Val: 5} 10 | root.Left.Right = &TreeNode{Val: 1} 11 | 12 | // 4 13 | // / \ 14 | // 9 0 15 | // / \ 16 | // 5 1 17 | fmt.Println(preorderTraversal(root)) // [4 9 5 1 0] 18 | } 19 | 20 | func preorderTraversal(root *TreeNode) []int { 21 | var nums []int 22 | traverse(root, &nums) 23 | return nums 24 | } 25 | 26 | func traverse(root *TreeNode, nums *[]int) { 27 | if root == nil { 28 | return 29 | } 30 | *nums = append(*nums, root.Val) 31 | traverse(root.Left, nums) 32 | traverse(root.Right, nums) 33 | } 34 | 35 | // TODO 36 | // iteration 37 | -------------------------------------------------------------------------------- /tree/145_binary_tree_postorder_traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 4} 7 | root.Left = &TreeNode{Val: 9} 8 | root.Right = &TreeNode{Val: 0} 9 | root.Left.Left = &TreeNode{Val: 5} 10 | root.Left.Right = &TreeNode{Val: 1} 11 | 12 | // 4 13 | // / \ 14 | // 9 0 15 | // / \ 16 | // 5 1 17 | fmt.Println(postorderTraversal(root)) // [5 1 9 0 4] 18 | } 19 | 20 | func postorderTraversal(root *TreeNode) []int { 21 | var nums []int 22 | traverse(root, &nums) 23 | return nums 24 | } 25 | 26 | func traverse(root *TreeNode, nums *[]int) { 27 | if root == nil { 28 | return 29 | } 30 | traverse(root.Left, nums) 31 | traverse(root.Right, nums) 32 | *nums = append(*nums, root.Val) 33 | } 34 | 35 | // TODO 36 | // iteration 37 | -------------------------------------------------------------------------------- /tree/199_binary_tree_right_side_view.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 1} 7 | root.Left = &TreeNode{Val: 2} 8 | root.Left.Right = &TreeNode{Val: 5} 9 | root.Right = &TreeNode{Val: 3} 10 | root.Right.Right = &TreeNode{Val: 4} 11 | 12 | // 1 <--- 13 | // / \ 14 | // 2 3 <--- 15 | // \ \ 16 | // 5 4 <--- 17 | fmt.Println(rightSideView(root)) // [1 3 4] 18 | } 19 | 20 | // 从右侧看,其实是要求每层的最右侧节点 21 | // 层序遍历每层取最后一个元素即可 22 | func rightSideView(root *TreeNode) []int { 23 | if root == nil { 24 | return nil 25 | } 26 | 27 | var floors [][]int 28 | queue := []*TreeNode{root} 29 | for len(queue) > 0 { 30 | var floor []int // 本层的节点值 31 | counts := len(queue) // 本层的节点数 32 | for i := 0; i < counts; i++ { 33 | cur := queue[0] 34 | queue = queue[1:] 35 | if cur.Left != nil { 36 | queue = append(queue, cur.Left) 37 | } 38 | if cur.Right != nil { 39 | queue = append(queue, cur.Right) 40 | } 41 | floor = append(floor, cur.Val) 42 | } 43 | floors = append(floors, floor) 44 | } 45 | 46 | var nums []int 47 | for _, floor := range floors { 48 | nums = append(nums, floor[len(floor)-1]) // bingo 49 | } 50 | return nums 51 | } 52 | -------------------------------------------------------------------------------- /tree/222_count_complete_tree_nodes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 1} 7 | root.Left = &TreeNode{Val: 2} 8 | root.Left.Left = &TreeNode{Val: 4} 9 | root.Left.Right = &TreeNode{Val: 5} 10 | root.Right = &TreeNode{Val: 3} 11 | root.Right.Right = &TreeNode{Val: 6} 12 | 13 | // 1 14 | // / \ 15 | // 2 3 16 | // / \ / 17 | // 4 5 6 18 | fmt.Println(countNodes(root)) // 6 19 | } 20 | 21 | func countNodes(root *TreeNode) int { 22 | var count int 23 | countNode(root, &count) 24 | return count 25 | } 26 | 27 | // 二叉树计数节点个数 28 | // 应该归为 easy tag... 29 | func countNode(node *TreeNode, count *int) { 30 | if node == nil { 31 | return 32 | } 33 | *count++ 34 | countNode(node.Left, count) 35 | countNode(node.Right, count) 36 | } 37 | -------------------------------------------------------------------------------- /tree/226_invert_binary_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | tree := &Tree{} 7 | tree.root = &TreeNode{Val: 4} 8 | for _, v := range []int{2, 7, 1, 3, 6, 9} { 9 | tree.BFSInsert(v) 10 | } 11 | tree.BFSTraverse(tree.root) // 4 2 7 1 3 6 9 12 | fmt.Println() 13 | invertTree(tree.root) 14 | tree.BFSTraverse(tree.root) // 4 7 2 9 6 3 1 15 | } 16 | 17 | // 反转二叉树其实是镜像翻转 swap 节点操作 18 | func invertTree(root *TreeNode) *TreeNode { 19 | if root == nil { 20 | return nil 21 | } 22 | 23 | invertTree(root.Left) 24 | invertTree(root.Right) 25 | 26 | swapNode := root.Left // 镜像翻转 27 | root.Left = root.Right 28 | root.Right = swapNode 29 | return root 30 | } 31 | -------------------------------------------------------------------------------- /tree/230_kth_smallest_element_in_a_bst.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 3} 7 | root.Left = &TreeNode{Val: 1} 8 | root.Left.Right = &TreeNode{Val: 2} 9 | root.Right = &TreeNode{Val: 4} 10 | 11 | // 3 12 | // / \ 13 | // 1 4 14 | // \ 15 | // 2 16 | fmt.Println(kthSmallest(root, 1)) // 1 17 | } 18 | 19 | // 显然是中序遍历的 stack 迭代遍历,计数取值 20 | func kthSmallest(root *TreeNode, k int) int { 21 | if k == 0 || root == nil { 22 | return -1 23 | } 24 | 25 | var counter int 26 | var stack []*TreeNode 27 | cur := root 28 | for len(stack) > 0 || cur != nil { 29 | if cur != nil { 30 | stack = append(stack, cur) 31 | cur = cur.Left 32 | continue 33 | } 34 | 35 | // 现在左子节点为空 // bingo 36 | parent := stack[len(stack)-1] 37 | stack = stack[:len(stack)-1] // pop 38 | counter++ 39 | if counter == k { 40 | return parent.Val 41 | } 42 | cur = parent.Right 43 | } 44 | return -1 45 | } 46 | -------------------------------------------------------------------------------- /tree/257_binary_tree_paths.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | root := &TreeNode{Val: 1} 10 | root.Left = &TreeNode{Val: 2} 11 | root.Left.Right = &TreeNode{Val: 5} 12 | root.Right = &TreeNode{Val: 3} 13 | 14 | // 1 15 | // / \ 16 | // 2 3 17 | // \ 18 | // 5 19 | fmt.Println(binaryTreePaths(root)) // [1->2->5 1->3] 20 | } 21 | 22 | func binaryTreePaths(root *TreeNode) []string { 23 | var paths [][]int 24 | traverse(root, nil, &paths) 25 | 26 | var res []string 27 | for _, path := range paths { 28 | res = append(res, strings.Trim(strings.Replace(fmt.Sprint(path), " ", "->", -1), "[]")) // cool simple code 29 | } 30 | return res 31 | } 32 | 33 | // 和 113 一样,递归取经 34 | func traverse(root *TreeNode, curPath []int, paths *[][]int) { 35 | if root == nil { 36 | return 37 | } 38 | 39 | curPath = append(curPath, root.Val) 40 | if root.Left == nil && root.Right == nil { 41 | *paths = append(*paths, curPath) 42 | return 43 | } 44 | 45 | lPath := make([]int, len(curPath)) 46 | copy(lPath, curPath) 47 | rPath := make([]int, len(curPath)) 48 | copy(rPath, curPath) 49 | 50 | traverse(root.Left, lPath, paths) 51 | traverse(root.Right, rPath, paths) 52 | } 53 | -------------------------------------------------------------------------------- /tree/404_sum_of_left_leaves.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 3} 7 | root.Left = &TreeNode{Val: 9} 8 | root.Right = &TreeNode{Val: 20} 9 | root.Right.Left = &TreeNode{Val: 15} 10 | root.Right.Right = &TreeNode{Val: 7} 11 | 12 | // 3 13 | // / \ 14 | // 9 20 15 | // / \ 16 | // 15 7 17 | fmt.Println(sumOfLeftLeaves(root)) // 24 // 9+15 18 | } 19 | 20 | // 左叶子则退出递归 ok 21 | func sumOfLeftLeaves(root *TreeNode) int { 22 | var sum int 23 | traverse(root, &sum) 24 | return sum 25 | } 26 | 27 | func traverse(root *TreeNode, sum *int) { 28 | if root == nil { 29 | return 30 | } 31 | if root.Left != nil && root.Left.Left == nil && root.Left.Right == nil { // 左叶子 32 | *sum += root.Left.Val // bingo 33 | } 34 | 35 | traverse(root.Left, sum) 36 | traverse(root.Right, sum) 37 | } 38 | -------------------------------------------------------------------------------- /tree/450_delete_node_in_a_bst.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 5} 7 | root.Left = &TreeNode{Val: 3} 8 | root.Left.Left = &TreeNode{Val: 2} 9 | root.Left.Right = &TreeNode{Val: 4} 10 | root.Right = &TreeNode{Val: 6} 11 | root.Right.Right = &TreeNode{Val: 7} 12 | debug(deleteNode(root, 5)) // 2 3 4 6 7 // ok 13 | } 14 | 15 | func debug(root *TreeNode) { 16 | if root == nil { 17 | return 18 | } 19 | debug(root.Left) 20 | fmt.Print(root.Val, " ") 21 | debug(root.Right) 22 | } 23 | 24 | func deleteNode(root *TreeNode, key int) *TreeNode { 25 | if root == nil { 26 | return nil 27 | } 28 | var parent, cur *TreeNode = nil, root 29 | 30 | // 查找 31 | for cur != nil && cur.Val != key { 32 | parent = cur 33 | if cur.Val > key { 34 | cur = cur.Left 35 | } else { 36 | cur = cur.Right 37 | } 38 | } 39 | 40 | switch { 41 | case cur == nil: // 没找到 42 | return root 43 | case parent == nil: // 需要去掉根节点,则将左子树嫁接到右子树上 44 | return insertNode(root.Right, root.Left) 45 | case cur.Val < parent.Val: 46 | parent.Left = nil 47 | case cur.Val > parent.Val: 48 | parent.Right = nil 49 | } 50 | 51 | // 将左子树和右子树转移到父节点上 52 | if cur.Left != nil { 53 | insertNode(root, cur.Left) 54 | } 55 | if cur.Right != nil { 56 | insertNode(root, cur.Right) 57 | } 58 | return root 59 | } 60 | 61 | func insertNode(root, subNode *TreeNode) *TreeNode { 62 | if root == nil { 63 | return subNode 64 | } 65 | if subNode == nil { 66 | return root 67 | } 68 | var parent, cur *TreeNode = nil, root 69 | for cur != nil { 70 | parent = cur 71 | if cur.Val > subNode.Val { 72 | cur = cur.Left 73 | } else { 74 | cur = cur.Right 75 | } 76 | } 77 | 78 | if parent.Val < subNode.Val { 79 | parent.Right = subNode 80 | } else { 81 | parent.Left = subNode 82 | } 83 | return root 84 | } 85 | -------------------------------------------------------------------------------- /tree/501_find_mode_in_binary_search_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 1} 7 | root.Right = &TreeNode{Val: 2} 8 | root.Right.Left = &TreeNode{Val: 2} 9 | 10 | // 1 11 | // \ 12 | // 2 13 | // / 14 | // 2 15 | fmt.Println(findMode(root)) // 2 16 | } 17 | 18 | // 辣鸡解法是将二叉树随便遍历到计数 map 后,两次遍历求众数即可 19 | // cool solution // 理解本质 20 | func findMode(root *TreeNode) []int { 21 | var res []int 22 | var cur, count, max int 23 | traverseBST(root, &cur, &count, &max, &res) 24 | return res 25 | } 26 | 27 | // 既然是 BST,那就中序遍历取出有序序列,一边遍历一边比较并取众数 28 | func traverseBST(root *TreeNode, cur, count, max *int, res *[]int) { 29 | if root == nil { 30 | return 31 | } 32 | traverseBST(root.Left, cur, count, max, res) 33 | 34 | if root.Val != *cur { 35 | *cur = root.Val // 新值 36 | *count = 1 37 | } else { 38 | *count++ 39 | } 40 | 41 | // 新众数纪录 42 | if *count > *max { 43 | *max = *count 44 | *res = nil // 重来 45 | } 46 | 47 | // 符合众数条件 48 | if *count == *max { 49 | *res = append(*res, root.Val) 50 | } 51 | traverseBST(root.Right, cur, count, max, res) 52 | } 53 | -------------------------------------------------------------------------------- /tree/513_find_bottom_left_tree_value.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | 7 | root := &TreeNode{Val: 1} 8 | root.Left = &TreeNode{Val: 2} 9 | root.Right = &TreeNode{Val: 3} 10 | root.Left.Left = &TreeNode{Val: 4} 11 | root.Right.Left = &TreeNode{Val: 5} 12 | root.Right.Left.Left = &TreeNode{Val: 7} 13 | root.Right.Right = &TreeNode{Val: 6} 14 | // 1 15 | // / \ 16 | // 2 3 17 | // / / \ 18 | // 4 5 6 19 | // / 20 | // 7 21 | fmt.Println(findBottomLeftValue(root)) // 7 22 | } 23 | 24 | // 最左下角的元素,即最底层第一个元素 25 | func findBottomLeftValue(root *TreeNode) int { 26 | var levels []int 27 | traverse(root, 0, &levels) 28 | return levels[len(levels)-1] 29 | } 30 | 31 | // 和 199 层序遍历并存储节点值类似 32 | // 需要用到辅助空间存储与长度判断是否到达下一层 33 | func traverse(root *TreeNode, curLevel int, levels *[]int) { 34 | if root == nil { 35 | return 36 | } 37 | curLevel++ 38 | if curLevel > len(*levels) { // 新一层 39 | *levels = append(*levels, root.Val) 40 | } 41 | traverse(root.Left, curLevel, levels) // 先处理最左节点 42 | traverse(root.Right, curLevel, levels) 43 | } 44 | -------------------------------------------------------------------------------- /tree/515_find_largest_value_in_each_tree_row.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | root := &TreeNode{Val: 1} 10 | root.Left = &TreeNode{Val: 3} 11 | root.Right = &TreeNode{Val: 2} 12 | root.Left.Left = &TreeNode{Val: 5} 13 | root.Left.Right = &TreeNode{Val: 3} 14 | root.Right.Right = &TreeNode{Val: 9} 15 | 16 | // 1 17 | // / \ 18 | // 3 2 19 | // / \ \ 20 | // 5 3 9 21 | fmt.Println(largestValues(root)) // [1 3 9] 22 | } 23 | 24 | func largestValues(root *TreeNode) []int { 25 | var levels [][]int 26 | var traverse func(root *TreeNode, curLevel int) 27 | 28 | // 和 102 一样的层序遍历 29 | // 递归和 queue 都 ok 30 | traverse = func(root *TreeNode, curLevel int) { 31 | if root == nil { 32 | return 33 | } 34 | 35 | // 到了新一层 36 | if curLevel >= len(levels) { 37 | levels = append(levels, []int{}) 38 | } 39 | // 注意此处 levels 直接使用的外部变量,传 *[][]int 参数无法 append 40 | levels[curLevel] = append(levels[curLevel], root.Val) // bingo 41 | 42 | traverse(root.Left, curLevel+1) 43 | traverse(root.Right, curLevel+1) 44 | } 45 | 46 | traverse(root, 0) 47 | 48 | var res []int 49 | for _, level := range levels { 50 | sort.Ints(level) 51 | res = append(res, level[len(level)-1]) 52 | } 53 | return res 54 | } 55 | -------------------------------------------------------------------------------- /tree/538_convert_bst_to_greater_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 5} 7 | root.Left = &TreeNode{Val: 2} 8 | root.Right = &TreeNode{Val: 13} 9 | newRoot := convertBST(root) 10 | fmt.Println(newRoot.Val) // 18 11 | fmt.Println(newRoot.Left.Val) // 20 12 | fmt.Println(newRoot.Right.Val) // 13 13 | } 14 | 15 | func convertBST(root *TreeNode) *TreeNode { 16 | var curSum int 17 | var traverse func(node *TreeNode) 18 | 19 | traverse = func(node *TreeNode) { 20 | if node == nil { 21 | return 22 | } 23 | 24 | traverse(node.Right) // 也是后序遍历,不过方向改了 25 | curSum += node.Val 26 | node.Val = curSum 27 | traverse(node.Left) 28 | } 29 | 30 | traverse(root) 31 | return root 32 | } 33 | -------------------------------------------------------------------------------- /tree/543_diameter_of_binary_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 1} 7 | root.Left = &TreeNode{Val: 2} 8 | root.Right = &TreeNode{Val: 3} 9 | fmt.Println(diameterOfBinaryTree(root)) 10 | } 11 | 12 | // 显然是找左子树最大路径与右子树最长路径 13 | func diameterOfBinaryTree(root *TreeNode) int { 14 | var d int 15 | traverse(root, &d) 16 | return d 17 | } 18 | 19 | // 递归解法比较辣鸡 20 | func traverse(root *TreeNode, maxD *int) { 21 | if root == nil { 22 | return 23 | } 24 | curD := depth(root.Left) + depth(root.Right) 25 | if curD > *maxD { 26 | *maxD = curD 27 | } 28 | 29 | traverse(root.Left, maxD) 30 | traverse(root.Right, maxD) 31 | } 32 | 33 | func depth(root *TreeNode) int { 34 | if root == nil { 35 | return 0 36 | } 37 | 38 | lDepth := depth(root.Left) + 1 39 | rDepth := depth(root.Right) + 1 40 | if lDepth > rDepth { 41 | return lDepth 42 | } 43 | return rDepth 44 | } 45 | -------------------------------------------------------------------------------- /tree/563_binary_tree_tilt.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 1} 7 | root.Left = &TreeNode{Val: 2} 8 | root.Right = &TreeNode{Val: 3} 9 | fmt.Println(findTilt(root)) // 1 10 | } 11 | 12 | func findTilt(root *TreeNode) int { 13 | var titlSum int 14 | var traverse func(node *TreeNode) int 15 | traverse = func(node *TreeNode) int { 16 | if node == nil { 17 | return 0 18 | } 19 | lVal := traverse(node.Left) 20 | rVal := traverse(node.Right) 21 | titlSum += abs(lVal - rVal) // 需要所有差值,不断向上累计 22 | 23 | return node.Val + lVal + rVal // 返回整棵子树和 24 | } 25 | traverse(root) 26 | 27 | return titlSum 28 | } 29 | 30 | func abs(x int) int { 31 | if x < 0 { 32 | return -x 33 | } 34 | return x 35 | } 36 | -------------------------------------------------------------------------------- /tree/572_subtree_of_another_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | s := &TreeNode{Val: 3} 7 | s.Left = &TreeNode{Val: 4} 8 | s.Left.Left = &TreeNode{Val: 1} 9 | s.Left.Right = &TreeNode{Val: 2} 10 | // s.Left.Right.Left = &TreeNode{Val: 0} // false 11 | s.Right = &TreeNode{Val: 5} 12 | 13 | t := &TreeNode{Val: 4} 14 | t.Left = &TreeNode{Val: 1} 15 | t.Right = &TreeNode{Val: 2} 16 | 17 | fmt.Println(isSubtree(s, t)) // true 18 | } 19 | 20 | func isSubtree(s *TreeNode, t *TreeNode) bool { 21 | if isSame(s, t) { 22 | return true // bingo 23 | } 24 | 25 | if s == nil { 26 | return false // 向下不会再相等 27 | } 28 | 29 | return isSubtree(s.Left, t) || isSubtree(s.Right, t) 30 | } 31 | 32 | func isSame(t1, t2 *TreeNode) bool { 33 | if t1 == nil && t2 == nil { 34 | return true 35 | } 36 | if t1 == nil || t2 == nil { 37 | return false 38 | } 39 | 40 | return t1.Val == t2.Val && isSame(t1.Left, t2.Left) && isSame(t1.Right, t2.Right) 41 | } 42 | -------------------------------------------------------------------------------- /tree/606_construct_string_from_binary_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 1} 7 | root.Left = &TreeNode{Val: 2} 8 | root.Left.Right = &TreeNode{Val: 4} 9 | root.Right = &TreeNode{Val: 3} 10 | fmt.Println(tree2str(root)) // 1(2()(4))(3) 11 | } 12 | 13 | func tree2str(t *TreeNode) string { 14 | s := traverse(t) 15 | if len(s) > 2 { 16 | s = s[1 : len(s)-1] 17 | } 18 | return s 19 | } 20 | 21 | func traverse(root *TreeNode) string { 22 | if root == nil { 23 | return "" 24 | } 25 | 26 | l := traverse(root.Left) 27 | r := traverse(root.Right) 28 | 29 | if r != "" && l == "" { // 要左不要右 30 | l = "()" 31 | } 32 | return fmt.Sprintf("(%d%s%s)", root.Val, l, r) 33 | } 34 | -------------------------------------------------------------------------------- /tree/617_merge_two_binary_trees.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | t1 := &TreeNode{ 7 | Val: 1, 8 | Left: &TreeNode{Val: 3, Left: &TreeNode{Val: 5}}, 9 | Right: &TreeNode{Val: 2}, 10 | } 11 | t2 := &TreeNode{ 12 | Val: 2, 13 | Left: &TreeNode{Val: 1, Right: &TreeNode{Val: 4}}, 14 | Right: &TreeNode{Val: 3, Right: &TreeNode{Val: 7}}, 15 | } 16 | t3 := mergeTrees(t1, t2) 17 | fmt.Println(t3.Val) // 3 18 | // also ok 19 | } 20 | 21 | // DP 22 | func mergeTrees(t1 *TreeNode, t2 *TreeNode) *TreeNode { 23 | if t1 == nil { 24 | return t2 25 | } 26 | if t2 == nil { 27 | return t1 28 | } 29 | return &TreeNode{ 30 | Val: t1.Val + t2.Val, 31 | Left: mergeTrees(t1.Left, t2.Left), 32 | Right: mergeTrees(t1.Right, t2.Right), 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tree/623_add_one_row_to_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{ 7 | Val: 4, 8 | Left: &TreeNode{Val: 2}, 9 | Right: &TreeNode{Val: 6}, 10 | } 11 | 12 | newRoot := addOneRow(root, 1, 2) 13 | fmt.Println(newRoot.Val, newRoot.Left.Val, newRoot.Right.Val) // 4 1 1 14 | // also ok 15 | } 16 | 17 | // 层序遍历即可 18 | func addOneRow(root *TreeNode, v int, d int) *TreeNode { 19 | if root == nil { 20 | return nil 21 | } 22 | if d == 1 { 23 | return &TreeNode{Val: v, Left: root} // 特殊 case 24 | } 25 | 26 | depth := 1 27 | q := []*TreeNode{root} 28 | for len(q) > 0 { 29 | counts := len(q) 30 | for i := 0; i < counts; i++ { 31 | cur := q[0] 32 | q = q[1:] 33 | if depth == d-1 { // 注意 -1 34 | cur.Left = &TreeNode{Val: v, Left: cur.Left} 35 | cur.Right = &TreeNode{Val: v, Right: cur.Right} 36 | } 37 | if cur.Left != nil { 38 | q = append(q, cur.Left) 39 | } 40 | if cur.Right != nil { 41 | q = append(q, cur.Right) 42 | } 43 | } 44 | depth++ 45 | } 46 | return root 47 | } 48 | -------------------------------------------------------------------------------- /tree/637_average_of_levels_in_binary_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{ 7 | Val: 3, 8 | Left: &TreeNode{Val: 9}, 9 | Right: &TreeNode{Val: 20}, 10 | } 11 | 12 | fmt.Println(averageOfLevels(root)) // [3 14.5] 13 | } 14 | 15 | // 层序遍历即可 16 | func averageOfLevels(root *TreeNode) []float64 { 17 | if root == nil { 18 | return nil 19 | } 20 | 21 | var avgs []float64 22 | q := []*TreeNode{root} 23 | for len(q) > 0 { 24 | count := len(q) 25 | sum := 0 26 | for i := 0; i < count; i++ { 27 | cur := q[0] 28 | q = q[1:] 29 | sum += cur.Val 30 | if cur.Left != nil { 31 | q = append(q, cur.Left) 32 | } 33 | if cur.Right != nil { 34 | q = append(q, cur.Right) 35 | } 36 | } 37 | avgs = append(avgs, float64(sum)/float64(count)) 38 | } 39 | return avgs 40 | } 41 | -------------------------------------------------------------------------------- /tree/652_find_duplicate_subtrees.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | ) 7 | 8 | func main() { 9 | tree := &TreeNode{Val: 1} 10 | tree.Left = &TreeNode{Val: 2} 11 | tree.Left.Left = &TreeNode{Val: 4} 12 | tree.Right = &TreeNode{Val: 3} 13 | tree.Right.Left = &TreeNode{Val: 2} 14 | tree.Right.Left.Left = &TreeNode{Val: 4} 15 | tree.Right.Right = &TreeNode{Val: 4} 16 | 17 | for _, node := range findDuplicateSubtrees(tree) { 18 | fmt.Println(node.Val) // ok 19 | } 20 | } 21 | 22 | func findDuplicateSubtrees(root *TreeNode) []*TreeNode { 23 | paths := make(map[string]int) 24 | var res []*TreeNode 25 | traverse(root, paths, &res) 26 | return res 27 | } 28 | 29 | // 后序遍历把路径放到 map 中去重 30 | func traverse(root *TreeNode, paths map[string]int, res *[]*TreeNode, ) string { 31 | if root == nil { 32 | return "#" 33 | } 34 | 35 | fullPath := strconv.Itoa(root.Val) + "," + traverse(root.Left, paths, res) + "," + traverse(root.Right, paths, res) 36 | if count, ok := paths[fullPath]; ok && count == 1 { // 计数 count 为 1 37 | *res = append(*res, root) 38 | } 39 | paths[fullPath]++ 40 | 41 | return fullPath 42 | } 43 | -------------------------------------------------------------------------------- /tree/653_two_sum_iv_input_is_a_bst.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 1} 7 | fmt.Println(findTarget(root, 2)) // false 8 | } 9 | 10 | func findTarget(root *TreeNode, k int) bool { 11 | m := make(map[int]int) 12 | return preTraverse(root, k, m) 13 | } 14 | 15 | // 和 two sum 一样 16 | func preTraverse(root *TreeNode, k int, m map[int]int) bool { 17 | if root == nil { 18 | return false 19 | } 20 | 21 | if _, ok := m[k-root.Val]; ok { // 先序遍历保证了去重 22 | return true 23 | } 24 | 25 | m[root.Val]++ 26 | return preTraverse(root.Left, k, m) || preTraverse(root.Right, k, m) 27 | } 28 | -------------------------------------------------------------------------------- /tree/654_maximum_binary_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := constructMaximumBinaryTree([]int{3, 2, 1, 6, 0, 5}) 7 | fmt.Println(root) // ... //ok 8 | } 9 | 10 | // 直接取值恢复 11 | func constructMaximumBinaryTree(nums []int) *TreeNode { 12 | if len(nums) == 0 { 13 | return nil 14 | } 15 | 16 | mid := 0 17 | max := nums[0] 18 | for i, n := range nums { 19 | if n > max { 20 | max = n 21 | mid = i 22 | } 23 | } 24 | 25 | root := &TreeNode{Val: max} 26 | root.Left = constructMaximumBinaryTree(nums[:mid]) 27 | root.Right = constructMaximumBinaryTree(nums[mid+1:]) 28 | return root 29 | } 30 | -------------------------------------------------------------------------------- /tree/662_maximum_width_of_binary_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{ 7 | Val: 1, 8 | Left: &TreeNode{Val: 2}, 9 | Right: &TreeNode{Val: 3}, 10 | } 11 | fmt.Println(widthOfBinaryTree(root)) // 2 12 | } 13 | 14 | // 满二叉树的节点宽度性质 15 | // 1 16 | // 2 3 17 | // 4 5 6 7 18 | // 8 9 10 11 12 13 14 15 19 | 20 | // 理解宽度:最右边与最左边的数值之差 21 | func widthOfBinaryTree(root *TreeNode) int { 22 | if root == nil { 23 | return 0 24 | } 25 | 26 | var width int 27 | q := []*TreeNode{root} 28 | for len(q) > 0 { 29 | counts := len(q) 30 | width = max(width, q[len(q)-1].Val-q[0].Val+1) // 宽度为差值加 1 31 | for i := 0; i < counts; i++ { 32 | cur := q[0] 33 | q = q[1:] 34 | if cur.Left != nil { 35 | cur.Left.Val = cur.Val * 2 36 | q = append(q, cur.Left) 37 | } 38 | if cur.Right != nil { 39 | cur.Right.Val = cur.Val*2 + 1 40 | q = append(q, cur.Right) 41 | } 42 | } 43 | } 44 | return width 45 | } 46 | 47 | func max(x, y int) int { 48 | if x > y { 49 | return x 50 | } 51 | return y 52 | } 53 | -------------------------------------------------------------------------------- /tree/669_trim_a_binary_search_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{ 7 | Val: 1, 8 | Left: &TreeNode{Val: 0}, 9 | Right: &TreeNode{Val: 2}, 10 | } 11 | fmt.Println(trimBST(root, 1, 2)) // ok 12 | } 13 | 14 | func trimBST(root *TreeNode, L int, R int) *TreeNode { 15 | if root == nil { 16 | return nil 17 | } 18 | 19 | // 检查 root 需要 trim 的情况 20 | if root.Val < L { 21 | return trimBST(root.Right, L, R) 22 | } 23 | if root.Val > R { 24 | return trimBST(root.Left, L, R) 25 | } 26 | 27 | root.Left = trimBST(root.Left, L, R) 28 | root.Right = trimBST(root.Right, L, R) 29 | return root 30 | } 31 | -------------------------------------------------------------------------------- /tree/671_second_minimum_node_in_a_binary_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 5} 7 | root.Left = &TreeNode{Val: 5} 8 | root.Right = &TreeNode{Val: 6} 9 | fmt.Println(findSecondMinimumValue(root)) // 6 10 | } 11 | 12 | const MAX = 1 << 31 13 | 14 | // 不动脑筋的做法 15 | func findSecondMinimumValue(root *TreeNode) int { 16 | if root == nil { 17 | return -1 18 | } 19 | 20 | q := []*TreeNode{root} 21 | min := MAX 22 | for len(q) > 0 { 23 | count := len(q) 24 | for i := 0; i < count; i++ { 25 | cur := q[0] 26 | q = q[1:] 27 | if cur.Val != root.Val && cur.Val < min { 28 | min = cur.Val 29 | } 30 | if cur.Left != nil { 31 | q = append(q, cur.Left) 32 | } 33 | if cur.Right != nil { 34 | q = append(q, cur.Right) 35 | } 36 | } 37 | } 38 | if min != MAX && min != root.Val { 39 | return min 40 | } 41 | 42 | return -1 43 | } 44 | -------------------------------------------------------------------------------- /tree/700_search_in_a_binary_search_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 4} 7 | root.Left = &TreeNode{Val: 2} 8 | root.Left.Left = &TreeNode{Val: 1} 9 | root.Left.Right = &TreeNode{Val: 3} 10 | root.Right = &TreeNode{Val: 7} 11 | 12 | // 4 13 | // / \ 14 | // 2 7 15 | // / \ 16 | // 1 3 17 | fmt.Println(searchBST(root, 2)) // 2 18 | } 19 | 20 | // what can I say 21 | func searchBST(root *TreeNode, val int) *TreeNode { 22 | if root != nil { 23 | switch { 24 | case root.Val < val: 25 | return searchBST(root.Right, val) 26 | case root.Val > val: 27 | return searchBST(root.Left, val) 28 | default: 29 | return root 30 | } 31 | } 32 | return nil 33 | } 34 | -------------------------------------------------------------------------------- /tree/701_insert_into_a_binary_search_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 1} 7 | insertIntoBST(root, 2) 8 | fmt.Println(root) 9 | } 10 | 11 | // 递归赋值 12 | func insertIntoBST(root *TreeNode, val int) *TreeNode { 13 | if root == nil { 14 | return &TreeNode{Val: val} 15 | } 16 | 17 | switch { 18 | case root.Val > val: 19 | root.Left = insertIntoBST(root.Left, val) 20 | case root.Val < val: 21 | root.Right = insertIntoBST(root.Right, val) 22 | default: 23 | } 24 | return root // 相同值不予处理 25 | } 26 | -------------------------------------------------------------------------------- /tree/814_binary_tree_pruning.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 1} 7 | root.Right = &TreeNode{Val: 0} 8 | root.Right.Left = &TreeNode{Val: 0} 9 | root.Right.Right = &TreeNode{Val: 1} 10 | newRoot := pruneTree(root) 11 | fmt.Println(newRoot) 12 | fmt.Println(newRoot.Left) 13 | fmt.Println(newRoot.Right) 14 | fmt.Println(newRoot.Right.Left) 15 | fmt.Println(newRoot.Right.Right) // bingo 16 | } 17 | 18 | // 其实就是一个后序遍历,一步一步摘除 0 叶子 19 | func pruneTree(root *TreeNode) *TreeNode { 20 | if root == nil { 21 | return nil 22 | } 23 | root.Left = pruneTree(root.Left) 24 | root.Right = pruneTree(root.Right) 25 | if root.Left == nil && root.Right == nil && root.Val == 0 { 26 | return nil 27 | } 28 | return root 29 | } 30 | -------------------------------------------------------------------------------- /tree/872_leaf_similar_trees.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | // ok 5 | } 6 | 7 | func leafSimilar(root1 *TreeNode, root2 *TreeNode) bool { 8 | var leafs1, leafs2 []int 9 | traverse(root1, &leafs1) 10 | traverse(root2, &leafs2) 11 | if len(leafs1) != len(leafs2) { 12 | return false 13 | } 14 | for i, l1 := range leafs1 { 15 | if l1 != leafs2[i] { 16 | return false 17 | } 18 | } 19 | return true 20 | } 21 | 22 | func traverse(root *TreeNode, leafs *[]int) { 23 | if root == nil { 24 | return 25 | } 26 | traverse(root.Left, leafs) 27 | traverse(root.Right, leafs) 28 | if root.Left == nil && root.Right == nil { 29 | *leafs = append(*leafs, root.Val) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tree/897_increasing_order_search_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | root := &TreeNode{Val: 1} 7 | root.Left = &TreeNode{Val: 0} 8 | fmt.Println(increasingBST(root)) // 0 bingo 9 | } 10 | 11 | // 可以先递归中序遍历把数记在数组,再重建右斜树 12 | // 不过用 stack 可以一边遍历一边建树 13 | func increasingBST(root *TreeNode) *TreeNode { 14 | if root == nil { 15 | return nil 16 | } 17 | 18 | var newRoot *TreeNode 19 | var newCur *TreeNode 20 | 21 | var stack []*TreeNode 22 | cur := root 23 | for cur != nil || len(stack) > 0 { 24 | // 先走到最左节点记下新头节点 25 | if cur != nil { 26 | stack = append(stack, cur) 27 | cur = cur.Left 28 | continue 29 | } 30 | 31 | if newRoot == nil { 32 | newRoot = stack[len(stack)-1] // leftest 33 | newCur = newRoot 34 | } else { 35 | newCur.Right = stack[len(stack)-1] 36 | newCur = newCur.Right 37 | } 38 | stack = stack[:len(stack)-1] // pop 39 | newCur.Left = nil // 把原节点的左子树给砍掉 40 | cur = newCur.Right // 中序遍历 41 | } 42 | 43 | newCur.Right = nil // bingo 44 | return newRoot 45 | } 46 | -------------------------------------------------------------------------------- /tree/94_binary_tree_inorder_traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | tree := &Tree{} 7 | tree.root = &TreeNode{Val: 4} 8 | for _, v := range []int{2, 7, 1, 3, 6, 9} { 9 | tree.BFSInsert(v) 10 | } 11 | tree.BFSTraverse(tree.root) // 4 2 7 1 3 6 9 12 | fmt.Println(inorderTraversal(tree.root)) // 1 2 3 4 6 7 9 13 | } 14 | 15 | func inorderTraversal(root *TreeNode) []int { 16 | var res []int 17 | traverse(root, &res) 18 | return res 19 | } 20 | 21 | // 中序遍历:左子节点 -> 父节点 -> 右子节点 22 | func traverse(node *TreeNode, res *[]int) { 23 | if node == nil { 24 | return 25 | } 26 | if node.Left != nil { 27 | traverse(node.Left, res) 28 | } 29 | *res = append(*res, node.Val) 30 | if node.Right != nil { 31 | traverse(node.Right, res) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tree/951_flip_equivalent_binary_trees.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | t1 := &TreeNode{ 7 | Val: 1, 8 | Left: &TreeNode{Val: 2}, 9 | Right: &TreeNode{Val: 3}, 10 | } 11 | t2 := &TreeNode{ 12 | Val: 1, 13 | Left: &TreeNode{Val: 3}, 14 | Right: &TreeNode{Val: 2}, 15 | } 16 | fmt.Println(flipEquiv(t1, t2)) // true 17 | } 18 | 19 | func flipEquiv(root1 *TreeNode, root2 *TreeNode) bool { 20 | if root1 == nil && root2 == nil { 21 | return true 22 | } 23 | if root1 == nil || root2 == nil { 24 | return false 25 | } 26 | 27 | if root1.Val != root2.Val { 28 | return false 29 | } 30 | 31 | return (flipEquiv(root1.Left, root2.Left) && flipEquiv(root1.Right, root2.Right)) || 32 | (flipEquiv(root1.Left, root2.Right) && flipEquiv(root1.Right, root2.Left)) 33 | } 34 | -------------------------------------------------------------------------------- /tree/95_unique_binary_search_trees_ii.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | // fmt.Println(generateTrees(3)) 5 | } 6 | 7 | func generateTrees(n int) []*TreeNode { 8 | if n == 0 { 9 | return nil 10 | } 11 | return generate(1, n) 12 | } 13 | 14 | func generate(start, end int) []*TreeNode { 15 | var roots []*TreeNode 16 | 17 | switch { 18 | case start > end: // 某一边子树无节点,左斜树或右斜树 19 | roots = append(roots, nil) 20 | 21 | case start == end: // 某一边子树只有一个节点 22 | roots = append(roots, &TreeNode{Val: start}) 23 | 24 | case start < end: 25 | for rootV := start; rootV <= end; rootV++ { // 以 rootV 为根节点 26 | leftTrees := generate(start, rootV-1) 27 | rightTrees := generate(rootV+1, end) 28 | 29 | // 组合左右子树 30 | for _, ltree := range leftTrees { 31 | for _, rtree := range rightTrees { 32 | root := &TreeNode{ // 以 rootV 为根节点的一棵 BST 33 | Val: rootV, 34 | Left: ltree, 35 | Right: rtree, 36 | } 37 | roots = append(roots, root) 38 | } 39 | } 40 | } 41 | } 42 | 43 | return roots 44 | } 45 | -------------------------------------------------------------------------------- /tree/96_unique_binary_search_trees.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println(numTrees(3)) // 5 7 | } 8 | 9 | // 有点类似斐波那契数列的味道 10 | // 1 -> 1 11 | // 2 -> 2 12 | // 3 -> 1*2 + 1*1 + 2*1 = 5 13 | // 4 -> 1*5 + 2*2 + 5*1 = 14 14 | // ... 15 | func numTrees(n int) int { 16 | dp := make([]int, n+1) 17 | dp[0], dp[1] = 1, 1 18 | for i := 2; i <= n; i++ { 19 | for j := 0; j < i; j++ { 20 | dp[i] += dp[j] * dp[i-j-1] // -1 是剔除本体 // 以 i 为根节点的 BST 数 = 两侧子 BST 数乘积 21 | } 22 | } 23 | return dp[n] 24 | } 25 | -------------------------------------------------------------------------------- /tree/98_validate_binary_search_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | tree := &Tree{} 7 | tree.root = &TreeNode{Val: 4} 8 | for _, v := range []int{2, 7, 1, 3, 6, 9} { 9 | tree.BFSInsert(v) 10 | } 11 | fmt.Println(isValidBST(tree.root)) // true 12 | } 13 | 14 | func isValidBST(root *TreeNode) bool { 15 | if root == nil { 16 | return true 17 | } 18 | return verify(root, -1<<63, 1<<63-1) 19 | } 20 | 21 | // min 和 max 一路存储已验证的 bst 最小值和最大值 22 | func verify(node *TreeNode, min, max int) bool { 23 | if node == nil { 24 | return true 25 | } 26 | if node.Val >= max || node.Val <= min { 27 | return false 28 | } 29 | return verify(node.Left, min, node.Val) && verify(node.Right, node.Val, max) 30 | } 31 | -------------------------------------------------------------------------------- /tree/tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // 定义二叉树结构 6 | type Tree struct { 7 | root *TreeNode 8 | } 9 | 10 | type TreeNode struct { 11 | Val int 12 | Left *TreeNode 13 | Right *TreeNode 14 | } 15 | 16 | // 按数组顺序插入节点 17 | func (tree *Tree) BFSInsert(v int) { 18 | if tree.root == nil { 19 | tree.root = &TreeNode{Val: v} 20 | return 21 | } 22 | 23 | q := make([]*TreeNode, 0) 24 | q = append(q, tree.root) 25 | for len(q) > 0 { 26 | curNode := q[0] // 非递归分层遍历 27 | q = q[1:] // pop 28 | 29 | if curNode.Left != nil { // 左子节点 30 | q = append(q, curNode.Left) 31 | } else { 32 | curNode.Left = &TreeNode{Val: v} // 找到合适的插入地点 33 | return 34 | } 35 | 36 | if curNode.Right != nil { 37 | q = append(q, curNode.Right) 38 | } else { 39 | curNode.Right = &TreeNode{Val: v} 40 | return 41 | } 42 | } 43 | } 44 | 45 | // 按层遍历 46 | func (tree *Tree) BFSTraverse(node *TreeNode) { 47 | if node == nil { 48 | return 49 | } 50 | q := []*TreeNode{tree.root} 51 | for len(q) > 0 { 52 | cur := q[0] 53 | q = q[1:] 54 | fmt.Printf("%v ", cur.Val) 55 | if cur.Left != nil { 56 | q = append(q, cur.Left) 57 | } 58 | if cur.Right != nil { 59 | q = append(q, cur.Right) 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /trie/208_implement_trie_prefix_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | trie := Constructor() 7 | trie.Insert("apple") 8 | fmt.Println(trie.Search("apple")) // true 9 | fmt.Println(trie.Search("app")) // false 10 | fmt.Println(trie.StartsWith("app")) // true 11 | trie.Insert("app") 12 | fmt.Println(trie.Search("app")) // true 13 | } 14 | 15 | type Trie struct { 16 | IsWord bool 17 | Next map[rune]*Trie 18 | } 19 | 20 | func Constructor() Trie { 21 | return Trie{ 22 | IsWord: false, 23 | Next: make(map[rune]*Trie), 24 | } 25 | } 26 | 27 | func (this *Trie) Insert(word string) { 28 | cur := this 29 | for _, r := range word { 30 | if next, ok := cur.Next[r]; ok { 31 | cur = next 32 | } else { 33 | if cur.Next == nil { 34 | cur.Next = make(map[rune]*Trie) 35 | } 36 | newNode := &Trie{IsWord: false, Next: nil} 37 | cur.Next[r] = newNode 38 | cur = newNode 39 | } 40 | } 41 | cur.IsWord = true 42 | } 43 | 44 | func (this *Trie) Search(word string) bool { 45 | cur := this 46 | for i := 0; i < len(word) && cur != nil; i++ { 47 | if next, ok := cur.Next[rune(word[i])]; !ok { 48 | return false 49 | } else { 50 | cur = next 51 | } 52 | } 53 | return cur != nil && cur.IsWord 54 | } 55 | 56 | func (this *Trie) StartsWith(prefix string) bool { 57 | cur := this 58 | for i := 0; i < len(prefix) && cur != nil; i++ { 59 | if next, ok := cur.Next[rune(prefix[i])]; !ok { 60 | return false 61 | } else { 62 | cur = next 63 | } 64 | } 65 | return cur != nil 66 | } 67 | --------------------------------------------------------------------------------