├── .gitignore ├── .pre-commit-config.yaml ├── README.org ├── classic150 ├── _001_88.py ├── _002_27.py ├── _003_26.py └── _005_169.py ├── classify ├── Cargo.toml ├── README.md └── src │ ├── lcof_03_shu_zu_zhong_chong_fu_de_shu_zi.rs │ ├── lcof_05_ti_huan_kong_ge.rs │ ├── lcof_13_ji_qi_ren_de_yun_dong_fan_wei.rs │ ├── lcof_45_ba_shu_zu_pai_cheng_zui_xiao_de_shu.rs │ ├── main.rs │ ├── p0001_two_sum.rs │ ├── p0002_add_two_numbers.rs │ ├── p0003_longest_substring_without_repeating_characters.rs │ ├── p0004_median_of_two_sorted_arrays.rs │ ├── p0005_longest_palindromic_substring.rs │ ├── p0007_reverse_integer.rs │ ├── p0008_string_to_integer.rs │ ├── p0009_palindrome_number.rs │ ├── p0011_container_with_most_water.rs │ ├── p0012_integer_to_roman.rs │ ├── p0013_roman_to_integer.rs │ ├── p0014_longest_common_prefix.rs │ ├── p0015_3sum.rs │ ├── p0017_letter_combinations_of_a_phone_number.rs │ ├── p0020_valid_parentheses.rs │ ├── p0021_merge_two_sorted_lists.rs │ ├── p0022_generate_parentheses.rs │ ├── p0026_remove_duplicates_from_sorted_array.rs │ ├── p0027_remove_element.rs │ ├── p0028_implement_strstr.rs │ ├── p0032_longest_valid_parentheses.rs │ ├── p0034_find_first_and_last_position_of_element_in_sorted_array.rs │ ├── p0035_search_insert_position.rs │ ├── p0038_count_and_say.rs │ ├── p0039_combination_sum.rs │ ├── p0041_first_missing_positive.rs │ ├── p0043_multiply_strings.rs │ ├── p0045_jump_game_ii.rs │ ├── p0046_permutations.rs │ ├── p0047_permutations_ii.rs │ ├── p0048_rotate_image.rs │ ├── p0049_group_anagrams.rs │ ├── p0050_pow_x_n.rs │ ├── p0053_maximum_subarray.rs │ ├── p0054_spiral_matrix.rs │ ├── p0055_jump_game.rs │ ├── p0056_merge_intervals.rs │ ├── p0058_length_of_last_word.rs │ ├── p0059_spiral_matrix_ii.rs │ ├── p0062_unique_paths.rs │ ├── p0063_unique_paths_ii.rs │ ├── p0064_minimum_path_sum.rs │ ├── p0066_plus_one.rs │ ├── p0067_add_binary.rs │ ├── p0069_sqrt_x.rs │ ├── p0070_climbing_stairs.rs │ ├── p0071_simplify_path.rs │ ├── p0072_edit_distance.rs │ ├── p0073_set_matrix_zeroes.rs │ ├── p0074_search_a_2d_matrix.rs │ ├── p0075_sort_colors.rs │ ├── p0077_combinations.rs │ ├── p0078_subsets.rs │ ├── p0079_word_search.rs │ ├── p0084_largest_rectangle_in_histogram.rs │ ├── p0088_merge_sorted_array.rs │ ├── p0090_subsets_ii.rs │ ├── p0091_decode_ways.rs │ ├── p0093_restore_ip_addresses.rs │ ├── p0118_pascals_triangle.rs │ ├── p0119_pascals_triangle_ii.rs │ ├── p0120_triangle.rs │ ├── p0121_best_time_to_buy_and_sell_stock.rs │ ├── p0122_best_time_to_buy_and_sell_stock_ii.rs │ ├── p0125_valid_palindrome.rs │ ├── p0127_word_ladder.rs │ ├── p0128_longest_consecutive_sequence.rs │ ├── p0130_surrounded_regions.rs │ ├── p0134_gas_station.rs │ ├── p0136_single_number.rs │ ├── p0137_single_number_ii.rs │ ├── p0139_word_break.rs │ ├── p0144_binary_tree_preorder_traversal.rs │ ├── p0145_binary_tree_postorder_traversal.rs │ ├── p0150_evaluate_reverse_polish_notation.rs │ ├── p0153_find_minimum_in_rotated_sorted_array.rs │ ├── p0154_find_minimum_in_rotated_sorted_array_ii.rs │ ├── p0155_min_stack.rs │ ├── p0167_two_sum_ii_array_is_sorted.rs │ ├── p0168_excel_sheet_column_title.rs │ ├── p0169_majority_element.rs │ ├── p0171_excel_sheet_column_number.rs │ ├── p0172_factorial_trailing_zeroes.rs │ ├── p0189_rotate_array.rs │ ├── p0191_number_of_1_bits.rs │ ├── p0198_house_robber.rs │ ├── p0200_number_of_islands.rs │ ├── p0201_bitwise_and_of_numbers_range.rs │ ├── p0202_happy_number.rs │ ├── p0204_count_primes.rs │ ├── p0205_isomorphic_strings.rs │ ├── p0213_house_robber_ii.rs │ ├── p0215_kth_largest_element_in_an_array.rs │ ├── p0217_contains_duplicate.rs │ ├── p0219_contains_duplicate_ii.rs │ ├── p0225_implement_stack_using_queues.rs │ ├── p0231_power_of_two.rs │ ├── p0238_product_of_array_except_self.rs │ ├── p0242_valid_anagram.rs │ ├── p0258_add_digits.rs │ ├── p0260_single_number_iii.rs │ ├── p0263_ugly_number.rs │ ├── p0264_ugly_number_ii.rs │ ├── p0268_missing_number.rs │ ├── p0279_perfect_squares.rs │ ├── p0283_move_zeroes.rs │ ├── p0292_nim_game.rs │ ├── p0292_nim_game2.rs │ ├── p0300_longest_increasing_subsequence.rs │ ├── p0303_range_sum_query_immutable.rs │ ├── p0322_coin_change.rs │ ├── p0326_power_of_three.rs │ ├── p0338_counting_bits.rs │ ├── p0342_power_of_four.rs │ ├── p0343_integer_break.rs │ ├── p0344_reverse_string.rs │ ├── p0345_reverse_vowels_of_a_string.rs │ ├── p0349_intersection_of_two_arrays.rs │ ├── p0350_intersection_of_two_array_ii.rs │ ├── p0357_count_numbers_with_unique_digits.rs │ ├── p0367_valid_perfect_square.rs │ ├── p0371_sum_of_two_integers.rs │ ├── p0374_top_k_frequent_elements.rs │ ├── p0376_wiggle_subsequence.rs │ ├── p0377_combination_sum_iv.rs │ ├── p0383_ransom_note.rs │ ├── p0387_first_unique_character_in_a_string.rs │ ├── p0389_find_the_difference.rs │ ├── p0392_is_subsequence.rs │ ├── p0394_decode_string.rs │ ├── p0405_convert_a_number_to_hexadecimal.rs │ ├── p0412_fizz_buzz.rs │ ├── p0413_arithmetic_slices.rs │ ├── p0414_third_maximum_number.rs │ ├── p0415_add_strings.rs │ ├── p0416_partition_equal_subset_sum.rs │ ├── p0434_number_of_segments_in_a_string.rs │ ├── p0441_arranging_coins.rs │ ├── p0443_string_compression.rs │ ├── p0448_find_all_numbers_disappeared_in_an_array.rs │ ├── p0453_minimum_moves_to_equal_array_elements.rs │ ├── p0455_assign_cookies.rs │ ├── p0456_132_pattern.rs │ ├── p0461_hamming_distance.rs │ ├── p0462_minimum_moves_to_equal_array_element_ii.rs │ ├── p0494_target_sum.rs │ ├── p0503_next_greater_element_ii.rs │ ├── p0504_base_7.rs │ ├── p0518_coin_change_ii.rs │ ├── p0523_continuous_subarray_sum.rs │ ├── p0524_longest_word_in_dictionary_through_deleting.rs │ ├── p0540_single_element_in_a_sorted_array.rs │ ├── p0551_student_attendance_record_i.rs │ ├── p0560_subarray_sum_equals_k.rs │ ├── p0567_permutation_string.rs │ ├── p0628_maximum_product_of_three_numbers.rs │ ├── p0633_sum_of_square_numbers.rs │ ├── p0646_maximum_length_of_pair_chain.rs │ ├── p0650_2_keys_keyboard.rs │ ├── p0674_longest_continuous_increasing_subsequence.rs │ ├── p0680_valid_palindrome_ii.rs │ ├── p0682_baseball_game.rs │ ├── p0695_max_area_of_island.rs │ ├── p0704_binary_search.rs │ ├── p0724_find_pivot_index.rs │ ├── p0739_daily_temperatures.rs │ ├── p0744_find_smalllest_greater_than_target.rs │ ├── p0746_min_cost_climbing_stairs.rs │ ├── p0856_score_of_parentheses.rs │ ├── p0860_lemonade_change.rs │ ├── p0874_walking_robot_simulation.rs │ ├── p0880_decoded_strnig_at_index.rs │ ├── p0921_minimum_add_to_make_parentheses_valid.rs │ ├── p0929_unique_email_addresses.rs │ ├── p0946_validate_stack_sequences.rs │ ├── p1021_remove_outermost_parentheses.rs │ ├── p1025_divisor_game.rs │ ├── p1047_remove_all_adjacent_duplicates_in_string.rs │ ├── p1091_shortest_path_in_binary_matrix.rs │ ├── p1143_longest_common_subsequence.rs │ ├── p1464_maximum_product_of_two_elements_in_an_array.rs │ ├── p1470_shuffle_the_array.rs │ ├── p1486_xor_operation_in_an_array.rs │ ├── p1487_making_file_names_unique.rs │ ├── p1512_number_of_good_pairs.rs │ ├── p1513_number_of_substrings_with_only_1s.rs │ ├── p1518_water_bottles.rs │ ├── p1528_shuffle_string.rs │ └── p1529_bulb_switcher_iv.rs ├── euler ├── Cargo.toml ├── README.md ├── data │ ├── p0022_names.txt │ └── p0042_words.txt └── src │ ├── main.rs │ ├── p0001_multiples_of_3_and_5.rs │ ├── p0002_even_fibonacci_numbers.rs │ ├── p0003_largest_prime_factor.rs │ ├── p0004_largest_palindrome_product.rs │ ├── p0005_smallest_multiple.rs │ ├── p0006_sum_square_difference.rs │ ├── p0007_10001st_prime.rs │ ├── p0008_largest_product_in_a_series.rs │ ├── p0009_special_pythagorean_triplet.rs │ ├── p0010_summation_of_primes.rs │ ├── p0011_largest_product_in_a_grid.rs │ ├── p0012_highly_divisible_triangular_number.rs │ ├── p0013_large_sum.rs │ ├── p0014_longest_collatz_sequence.rs │ ├── p0015_lattice_paths.rs │ ├── p0016_power_digit_sum.rs │ ├── p0017_number_letter_counts.rs │ ├── p0018_maximum_path_sum_i.rs │ ├── p0019_counting_sundays.rs │ ├── p0020_factorial_digit_sum.rs │ ├── p0021_amicable_numbers.rs │ ├── p0022_names_scores.rs │ ├── p0023_non_abundant_sums.rs │ ├── p0024_lexicographic_permutations.rs │ ├── p0025_1000_digit_fibonacci_number.rs │ ├── p0026_reciprocal_cycles.rs │ ├── p0027_quadratic_primes.rs │ ├── p0028_number_spiral_diagonals.rs │ ├── p0029_distinct_powers.rs │ ├── p0030_digit_fifth_powers.rs │ ├── p0031_coin_sums.rs │ ├── p0032_pandigital_products.rs │ ├── p0033_digit_cancelling_fractions.rs │ ├── p0034_digit_factorials.rs │ ├── p0035_circular_primes.rs │ ├── p0036_double_base_palindromes.rs │ ├── p0037_truncatable_primes.rs │ ├── p0038_pandigital_multiples.rs │ ├── p0039_integer_right_triangles.rs │ ├── p0040_champernownes_constant.rs │ ├── p0041_pandigital_prime.rs │ ├── p0042_coded_triangle_numbers.rs │ ├── p0043_sub_string_divisibility.rs │ ├── p0044_pentagon_numbers.rs │ ├── p0045_triangular_pentagonal_and_hexagonal.rs │ ├── p0046_goldbachs_other_conjecture.rs │ ├── p0047_distinct_primes_factors.rs │ ├── p0048_self_powers.rs │ ├── p0049_prime_permutations.rs │ ├── p0050_consecutive_prime_sum.rs │ └── p0067_maximum_path_sum_ii.rs ├── leetcode75 ├── day10_509.py ├── day10_70.py ├── day11_62.py ├── day11_746.py ├── day12_424.py ├── day12_438.py ├── day13_1.py ├── day13_299.py ├── day14_394.py ├── day14_844.py ├── day15_1046.py ├── day15_692.py ├── day16_1706.py ├── day16_202.py ├── day16_54.py ├── day17_14.py ├── day17_43.py ├── day18_19.py ├── day18_234.py ├── day19_148.py ├── day19_328.py ├── day1_1480.py ├── day1_724.py ├── day20_2131.py ├── day20_621.py ├── day21_110.py ├── day21_226.py ├── day22_437.py ├── day22_543.py ├── day23_33.py ├── day23_74.py ├── day24_108.py ├── day24_173.py ├── day24_230.py ├── day25_417.py ├── day25_417_2.py ├── day25_994.py ├── day26_210.py ├── day26_815.py ├── day27_198.py ├── day27_322.py ├── day28_152.py ├── day28_416.py ├── day29_16.py ├── day29_3.py ├── day29_76.py ├── day2_205.py ├── day2_392.py ├── day30_100.py ├── day30_101.py ├── day30_199.py ├── day31_155.py ├── day31_208.py ├── day31_232.py ├── day32_56.py ├── day32_57.py ├── day33_227.py ├── day33_735.py ├── day34_547.py ├── day34_947.py ├── day35_39.py ├── day35_46.py ├── day3_21.py ├── day3_876.py ├── day4_142.py ├── day4_876.py ├── day5_121.py ├── day5_409.py ├── day6_102.py ├── day7_278.py ├── day7_704.py ├── day8_235.py ├── day8_98.py ├── day9_200.py ├── day9_733.py └── helper.py ├── others ├── char2num_2.py ├── find_max_occur_char_4.py ├── merge_common_datetime.py ├── num2zhcn_3.py ├── parentheses_1.py └── three_sum_5.py ├── pyproject.toml ├── setup.cfg ├── sword-means-offer ├── helper.py ├── offer_005_ii.py ├── offer_008_ii.py ├── offer_04.py ├── offer_06.py ├── offer_07.py ├── offer_09.py ├── offer_10_i.py ├── offer_10_ii.py ├── offer_11.py ├── offer_12.py ├── offer_14_i.py ├── offer_15.py ├── offer_16.py ├── offer_17.py ├── offer_18_i.py ├── offer_18_ii.py ├── offer_20.py ├── offer_21.py ├── offer_22.py ├── offer_24.py ├── offer_25.py ├── offer_26.py ├── offer_27.py ├── offer_28.py ├── offer_30.py ├── offer_31.py ├── offer_32_i.py ├── offer_32_ii.py ├── offer_32_iii.py ├── offer_33.py ├── offer_34.py ├── offer_38.py ├── offer_39.py ├── offer_40.py ├── offer_41.py ├── offer_42.py ├── offer_44.py ├── offer_45.py ├── offer_46.py ├── offer_47.py ├── offer_48.py ├── offer_49.py ├── offer_50.py ├── offer_51.py ├── offer_52.py ├── offer_53_i.py ├── offer_53_ii.py ├── offer_54.py ├── offer_55_i.py ├── offer_55_ii.py ├── offer_56_i.py ├── offer_56_ii.py ├── offer_57.py ├── offer_57_ii.py ├── offer_58_i.py ├── offer_58_ii.py ├── offer_61.py ├── offer_62.py ├── offer_63.py ├── offer_66.py ├── offer_67.py ├── offer_68_i.py └── p0240_search_a_2d_matrix_ii.py └── weekly-contest ├── 379 ├── p1_3000.py ├── p2_3001.py ├── p3_3002.py └── p4_3003.py ├── 380 ├── p1_3005.py ├── p2_3006.py ├── p3_3007.py └── p4_3008.py ├── 381 ├── p1_100191.py ├── p2_100188.py ├── p3_100192.py └── p4_100213.py ├── 382 ├── p1_100215.py ├── p2_100206.py ├── p3_100195.py └── p4_100179.py ├── 121d ├── p1_2996.py ├── p2_2997.py ├── p3_2998.py └── p4_2999.py └── 122d ├── p1_3009.py ├── p2_3010.py ├── p3_3011.py └── p4_3012.py /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/asottile/yesqa 3 | rev: v1.2.2 4 | hooks: 5 | - id: yesqa 6 | 7 | - repo: https://github.com/PyCQA/isort 8 | rev: '5.7.0' 9 | hooks: 10 | - id: isort 11 | 12 | - repo: https://github.com/psf/black 13 | rev: '22.3.0' 14 | hooks: 15 | - id: black 16 | language_version: python3 # Should be a command that runs python3.6+ 17 | args: 18 | - -l 119 19 | 20 | - repo: https://github.com/pre-commit/pre-commit-hooks 21 | rev: v3.4.0 # Use the ref you want to point at 22 | hooks: 23 | - id: check-case-conflict 24 | - id: destroyed-symlinks 25 | - id: debug-statements 26 | - id: check-case-conflict 27 | - id: check-json 28 | - id: check-xml 29 | - id: check-executables-have-shebangs 30 | - id: check-toml 31 | - id: check-xml 32 | - id: check-yaml 33 | - id: check-added-large-files 34 | - id: check-symlinks 35 | - id: debug-statements 36 | - id: end-of-file-fixer 37 | - id: fix-byte-order-marker 38 | - id: fix-encoding-pragma 39 | args: ['--remove'] 40 | - id: forbid-new-submodules 41 | - id: mixed-line-ending 42 | - id: trailing-whitespace 43 | 44 | - repo: https://gitlab.com/pycqa/flake8 45 | rev: "3.8.4" 46 | hooks: 47 | - id: flake8 48 | 49 | - repo: https://github.com/jorisroovers/gitlint 50 | rev: "v0.15.0" 51 | hooks: 52 | - id: gitlint 53 | 54 | default_stages: [commit, push, commit-msg] 55 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | * LeetCode 2 | 3 | - [ ] sword-means-offer, Python3 实现《剑指Offer》 4 | - [ ] leetcode75, Python3 实现 LeetCode75 3 levels 挑战 5 | - [ ] classify, Rust 分类实现经典题 6 | - [ ] euler, Rust 实现 euler project 7 | - [ ] others, 其它代码实现 8 | 9 | 部分题目有在 [[https://space.bilibili.com/472722204][Bili]] 讲解 10 | 11 | 欢迎指正;) 12 | -------------------------------------------------------------------------------- /classic150/_001_88.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.cn/problems/merge-sorted-array/?envType=study-plan-v2&id=top-interview-150 2 | 3 | from typing import List 4 | 5 | 6 | class Solution: 7 | def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None: 8 | """ 9 | Do not return anything, modify nums1 in-place instead. 10 | """ 11 | # 从后往前, 较大的移动到后面,并移动该索引不断向前 12 | start = m + n - 1 13 | while start >= 0 and m > 0 and n > 0: 14 | if nums1[m - 1] > nums2[n - 1]: 15 | nums1[start] = nums1[m - 1] 16 | m -= 1 17 | else: 18 | nums1[start] = nums2[n - 1] 19 | n -= 1 20 | start -= 1 21 | 22 | # m有多余不需要考虑,不需要移动,所以只需要考虑移动剩余的n到 nums1 23 | while start >= 0 and n > 0: 24 | nums1[start] = nums2[n - 1] 25 | n -= 1 26 | start -= 1 27 | 28 | 29 | if __name__ == "__main__": 30 | nums1 = [1, 2, 3, 0, 0, 0] 31 | Solution().merge(nums1=nums1, m=3, nums2=[2, 5, 6], n=3) 32 | assert nums1 == [1, 2, 2, 3, 5, 6] 33 | 34 | nums1 = [1] 35 | Solution().merge(nums1=nums1, m=1, nums2=[], n=0) 36 | assert nums1 == [1] 37 | 38 | nums1 = [0] 39 | Solution().merge(nums1=nums1, m=0, nums2=[1], n=1) 40 | assert nums1 == [1] 41 | 42 | nums1 = [1, 2, 3, 0] 43 | Solution().merge(nums1=nums1, m=3, nums2=[0], n=1) 44 | assert nums1 == [0, 1, 2, 3] 45 | -------------------------------------------------------------------------------- /classic150/_003_26.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def removeDuplicates(self, nums: List[int]) -> int: 6 | index = cur = 0 7 | while cur + 1 < len(nums): 8 | # 找到一个与当前不相同的索引 9 | while cur + 1 < len(nums) and nums[cur + 1] == nums[cur]: 10 | cur = cur + 1 11 | # 找到后,原地赋值,索引往后移动,元素个数加一 12 | # 找不到的 case 表示后面几位一样,不需要操作,由外层 while 结束 13 | if cur + 1 < len(nums): 14 | nums[index + 1] = nums[cur + 1] 15 | cur += 1 16 | index += 1 17 | return index + 1 18 | 19 | 20 | if __name__ == "__main__": 21 | nums = [1, 1, 2] 22 | assert Solution().removeDuplicates(nums=nums) == 2 23 | assert nums[:2] == [1, 2] 24 | 25 | nums = [0, 0, 1, 1, 1, 2, 2, 3, 3, 4] 26 | assert Solution().removeDuplicates(nums=nums) == 5 27 | assert nums[:5] == [0, 1, 2, 3, 4] 28 | 29 | nums = [1] 30 | assert Solution().removeDuplicates(nums=nums) == 1 31 | assert nums[:1] == [1] 32 | 33 | nums = [1, 1] 34 | assert Solution().removeDuplicates(nums=nums) == 1 35 | assert nums[:1] == [1] 36 | 37 | nums = [1, 2, 3, 4] 38 | assert Solution().removeDuplicates(nums=nums) == 4 39 | assert nums[:4] == [1, 2, 3, 4] 40 | # print(nums) 41 | # assert 1 == 2 42 | -------------------------------------------------------------------------------- /classic150/_005_169.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def majorityElement(self, nums: List[int]) -> int: 6 | win = nums[0] 7 | count = 1 8 | for num in nums[1:]: 9 | if win == num: 10 | count += 1 11 | elif win != num: 12 | count -= 1 13 | if count < 0: 14 | win = num 15 | count = 1 16 | return win 17 | 18 | 19 | if __name__ == "__main__": 20 | assert Solution().majorityElement(nums=[3, 2, 3]) == 3 21 | assert Solution().majorityElement(nums=[2, 2, 1, 1, 1, 2, 2]) == 2 22 | -------------------------------------------------------------------------------- /classify/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "leetcode" 3 | version = "0.1.0" 4 | authors = ["wsgggws "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /classify/src/lcof_03_shu_zu_zhong_chong_fu_de_shu_zi.rs: -------------------------------------------------------------------------------- 1 | // 剑指 Offer 03. 数组中重复的数字 2 | // 找出数组中重复的数字。 3 | 4 | 5 | // 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。 6 | 7 | // 示例 1: 8 | 9 | // 输入: 10 | // [2, 3, 1, 0, 2, 5, 3] 11 | // 输出:2 或 3 12 | 13 | 14 | // 限制: 15 | 16 | // 2 <= n <= 100000 17 | 18 | pub struct Solution {} 19 | 20 | impl Solution { 21 | // 1. 排序后查找 O(nlogn) O(1) 22 | // 2. 利用HashSet O(n) O(n) 23 | 24 | // O(n) O(1) 25 | pub fn find_repeat_number(nums: Vec) -> i32 { 26 | let mut array = nums.clone(); 27 | for i in 0..nums.len() { 28 | while array[i] != i as i32 { 29 | let j = array[i] as usize; 30 | if array[i] == array[j] { 31 | return array[i]; 32 | } 33 | array.swap(i, j); 34 | } 35 | } 36 | -1 37 | } 38 | } 39 | 40 | #[cfg(test)] 41 | mod tests { 42 | use super::*; 43 | 44 | #[test] 45 | fn find_repeat_number_test() { 46 | assert_eq!(Solution::find_repeat_number(vec![2, 3, 1, 0, 2, 5, 3]), 2); 47 | assert_eq!(Solution::find_repeat_number(vec![2, 3, 1, 0]), -1); 48 | assert_eq!(Solution::find_repeat_number(vec![2, 3, 3, 0]), 3); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /classify/src/p0001_two_sum.rs: -------------------------------------------------------------------------------- 1 | // 1. Two Sum 2 | // Easy 3 | 4 | // Given an array of integers, return indices of the two numbers such that they add up to a specific target. 5 | 6 | // You may assume that each input would have exactly one solution, and you may not use the same element twice. 7 | 8 | // Example: 9 | 10 | // Given nums = [2, 7, 11, 15], target = 9, 11 | 12 | // Because nums[0] + nums[1] = 2 + 7 = 9, 13 | // return [0, 1]. 14 | 15 | pub struct Solution {} 16 | 17 | use std::collections::HashMap; 18 | impl Solution { 19 | pub fn two_sum(nums: Vec, target: i32) -> Vec { 20 | // 暴力枚举法 21 | // let len = nums.len(); 22 | // for i in 0..len { 23 | // for j in i+1..len { 24 | // if nums[i] + nums[j] == target { 25 | // return vec![i as i32, j as i32]; 26 | // } 27 | // } 28 | // } 29 | // vec![] 30 | 31 | // 利用HashMap, 一次遍历 32 | let mut map = HashMap::new(); 33 | for (index, num) in nums.iter().enumerate() { 34 | if let Some(&other_index) = map.get(&(target - num)) { 35 | return vec![other_index as i32, index as i32] 36 | } else { 37 | map.insert(num, index); 38 | } 39 | } 40 | vec![] 41 | } 42 | } 43 | 44 | #[cfg(test)] 45 | mod tests { 46 | use super::*; 47 | 48 | #[test] 49 | fn two_sum_test() { 50 | assert_eq!(vec![0, 1], Solution::two_sum(vec![2, 7, 11, 15], 9)); 51 | assert_eq!(vec![1, 2], Solution::two_sum(vec![3, 2, 4], 6)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /classify/src/p0011_container_with_most_water.rs: -------------------------------------------------------------------------------- 1 | // 11. Container With Most Water 2 | // Medium 3 | 4 | // Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water. 5 | 6 | // Note: You may not slant the container and n is at least 2. 7 | 8 | // The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49. 9 | 10 | // Example: 11 | 12 | // Input: [1,8,6,2,5,4,8,3,7] 13 | // Output: 49 14 | 15 | pub struct Solution {} 16 | 17 | impl Solution { 18 | pub fn max_area(height: Vec) -> i32 { 19 | let lens = height.len(); 20 | let mut result = 0; 21 | let (mut i, mut j) = (0usize, lens - 1usize); 22 | while i < j { 23 | result = i32::max(result, i32::min(height[i], height[j]) * ((j - i) as i32)); 24 | if height[i] < height[j] { 25 | i += 1; 26 | } else { 27 | j -= 1; 28 | } 29 | } 30 | result 31 | } 32 | } 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use super::*; 37 | 38 | #[test] 39 | fn max_area_test() { 40 | assert_eq!(Solution::max_area(vec![1, 8, 6, 2, 5, 4, 8, 3, 7]), 49); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /classify/src/p0041_first_missing_positive.rs: -------------------------------------------------------------------------------- 1 | // 41. First Missing Positive 2 | // Hard 3 | 4 | // Given an unsorted integer array, find the smallest missing positive integer. 5 | 6 | // Example 1: 7 | 8 | // Input: [1,2,0] 9 | // Output: 3 10 | // Example 2: 11 | 12 | // Input: [3,4,-1,1] 13 | // Output: 2 14 | // Example 3: 15 | 16 | // Input: [7,8,9,11,12] 17 | // Output: 1 18 | // Note: 19 | 20 | // Your algorithm should run in O(n) time and uses constant extra space. 21 | 22 | pub struct Solution {} 23 | 24 | impl Solution { 25 | pub fn first_missing_positive(nums: Vec) -> i32 { 26 | let mut nums = nums.clone(); 27 | for i in 0..nums.len() { 28 | while nums[i] > 0 && nums[i] <= nums.len() as i32 && nums[i] != nums[nums[i] as usize - 1] { 29 | let j = nums[i] as usize - 1; 30 | nums.swap(i, j); 31 | } 32 | } 33 | for i in 0..nums.len() { 34 | if nums[i] != i as i32 + 1 { 35 | return i as i32 + 1; 36 | } 37 | } 38 | nums.len() as i32 + 1 39 | } 40 | } 41 | 42 | #[cfg(test)] 43 | mod tests { 44 | use super::*; 45 | 46 | #[test] 47 | fn first_missing_positive_test() { 48 | assert_eq!(Solution::first_missing_positive(vec![1, 2, 0]), 3); 49 | assert_eq!(Solution::first_missing_positive(vec![1, 2]), 3); 50 | assert_eq!(Solution::first_missing_positive(vec![3, 4, -1, 1]), 2); 51 | assert_eq!(Solution::first_missing_positive(vec![7, 8, 9, 11, 12]), 1); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /classify/src/p0045_jump_game_ii.rs: -------------------------------------------------------------------------------- 1 | // 45. Jump Game II 2 | // Hard 3 | 4 | // 2419 5 | 6 | // 127 7 | 8 | // Add to List 9 | 10 | // Share 11 | // Given an array of non-negative integers, you are initially positioned at the first index of the array. 12 | 13 | // Each element in the array represents your maximum jump length at that position. 14 | 15 | // Your goal is to reach the last index in the minimum number of jumps. 16 | 17 | // Example: 18 | 19 | // Input: [2,3,1,1,4] 20 | // Output: 2 21 | // Explanation: The minimum number of jumps to reach the last index is 2. 22 | // Jump 1 step from index 0 to 1, then 3 steps to the last index. 23 | // Note: 24 | 25 | // You can assume that you can always reach the last index. 26 | 27 | pub struct Solution {} 28 | 29 | impl Solution { 30 | pub fn jump(nums: Vec) -> i32 { 31 | // 题目确保总是可达, 初始化到达index需要index步 32 | // dp[i] 表示到达i所需要的最少步数 33 | // dp[i] = min(dp[i], dp[j]+1) { nums[j] + j >= i } 34 | let mut dp: Vec = (0..nums.len() as i32).collect(); 35 | for i in 1..nums.len() { 36 | for j in 0..i { 37 | if nums[j] + j as i32 >= i as i32 { 38 | dp[i] = i32::min(dp[i],dp[j] + 1); 39 | } 40 | } 41 | } 42 | dp[nums.len() - 1] 43 | } 44 | } 45 | 46 | #[cfg(test)] 47 | mod tests { 48 | use super::*; 49 | 50 | #[test] 51 | fn jump_test() { 52 | assert_eq!(Solution::jump(vec![2, 3, 1, 1, 4]), 2); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /classify/src/p0055_jump_game.rs: -------------------------------------------------------------------------------- 1 | // 55. Jump Game 2 | // Medium 3 | 4 | // Given an array of non-negative integers, you are initially positioned at the first index of the array. 5 | 6 | // Each element in the array represents your maximum jump length at that position. 7 | 8 | // Determine if you are able to reach the last index. 9 | 10 | 11 | 12 | // Example 1: 13 | 14 | // Input: nums = [2,3,1,1,4] 15 | // Output: true 16 | // Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index. 17 | // Example 2: 18 | 19 | // Input: nums = [3,2,1,0,4] 20 | // Output: false 21 | // Explanation: You will always arrive at index 3 no matter what. Its maximum jump length is 0, which makes it impossible to reach the last index. 22 | 23 | pub struct Solution {} 24 | 25 | impl Solution { 26 | pub fn can_jump(nums: Vec) -> bool { 27 | // dp[i] 表示位置i是否可达 28 | // dp[i] = dp[j] && nums[j] + j >= i 29 | let mut dp = vec![false; nums.len()]; 30 | dp[0] = true; 31 | for i in 1..nums.len() { 32 | for j in 0..i { 33 | if dp[j] && nums[j] + j as i32 >= i as i32 { 34 | dp[i] = true; 35 | break; 36 | } 37 | } 38 | } 39 | dp[nums.len() - 1] 40 | } 41 | } 42 | 43 | #[cfg(test)] 44 | mod tests { 45 | use super::*; 46 | 47 | #[test] 48 | fn can_jump_test() { 49 | assert_eq!(Solution::can_jump(vec![2, 3, 1, 1, 4]), true); 50 | assert_eq!(Solution::can_jump(vec![3, 2, 1, 0, 4]), false); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /classify/src/p0058_length_of_last_word.rs: -------------------------------------------------------------------------------- 1 | // 58. Length of Last Word 2 | // Easy 3 | 4 | // Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the length of last word in the string. 5 | 6 | // If the last word does not exist, return 0. 7 | 8 | // Note: A word is defined as a character sequence consists of non-space characters only. 9 | 10 | // Example: 11 | 12 | // Input: "Hello World" 13 | // Output: 5 14 | 15 | pub struct Solution {} 16 | 17 | impl Solution { 18 | pub fn length_of_last_word(s: String) -> i32 { 19 | let splits: Vec<&str> = s.trim().split(" ").collect(); 20 | let len = splits.len(); 21 | let last_word = splits[len - 1].trim(); 22 | last_word.len() as i32 23 | } 24 | } 25 | 26 | #[cfg(test)] 27 | mod tests { 28 | use super::*; 29 | 30 | #[test] 31 | fn length_of_last_word_test() { 32 | // 注意该测试用例,表示只要有字母, 就会有长度 33 | assert_eq!(Solution::length_of_last_word("a ".to_string()), 1); 34 | assert_eq!(Solution::length_of_last_word("Hello World ".to_string()), 5); 35 | assert_eq!(Solution::length_of_last_word("".to_string()), 0); 36 | assert_eq!(Solution::length_of_last_word("Hello World".to_string()), 5); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /classify/src/p0120_triangle.rs: -------------------------------------------------------------------------------- 1 | // 120. Triangle 2 | // Medium 3 | 4 | // Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. 5 | 6 | // For example, given the following triangle 7 | 8 | // [ 9 | // [2], 10 | // [3,4], 11 | // [6,5,7], 12 | // [4,1,8,3] 13 | // ] 14 | // The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11). 15 | 16 | // Note: 17 | 18 | // Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle. 19 | 20 | pub struct Solution {} 21 | 22 | impl Solution { 23 | pub fn minimum_total(triangle: Vec>) -> i32 { 24 | // 自底向上写代码更快 25 | let mut dp = triangle.clone(); 26 | for i in (0..triangle.len() - 1).rev() { 27 | for j in 0..triangle[i].len() { 28 | dp[i][j] = triangle[i][j] + i32::min(dp[i + 1][j], dp[i + 1][j + 1]) 29 | } 30 | } 31 | dp[0][0] 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use super::*; 38 | 39 | #[test] 40 | fn minimum_total_test() { 41 | assert_eq!( 42 | Solution::minimum_total(vec![vec![2], vec![3, 4], vec![6, 5, 7], vec![4, 1, 8, 3]]), 43 | 11 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /classify/src/p0136_single_number.rs: -------------------------------------------------------------------------------- 1 | // 136. Single Number 2 | // Easy 3 | 4 | // Given a non-empty array of integers, every element appears twice except for one. Find that single one. 5 | 6 | // Note: 7 | 8 | // Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? 9 | 10 | // Example 1: 11 | 12 | // Input: [2,2,1] 13 | // Output: 1 14 | // Example 2: 15 | 16 | // Input: [4,1,2,1,2] 17 | // Output: 4 18 | 19 | pub struct Solution {} 20 | 21 | impl Solution { 22 | pub fn single_number(nums: Vec) -> i32 { 23 | // 利用'异或' 位运算 24 | nums.iter().fold(0, |result, num| result ^ num) 25 | 26 | // let mut result = 0; 27 | // for num in &nums { 28 | // result ^= num; 29 | // } 30 | // result 31 | } 32 | } 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use super::*; 37 | 38 | #[test] 39 | fn single_number_test() { 40 | assert_eq!(Solution::single_number(vec![0]), 0); 41 | assert_eq!(Solution::single_number(vec![1]), 1); 42 | assert_eq!(Solution::single_number(vec![2, 2, 1]), 1); 43 | assert_eq!(Solution::single_number(vec![4, 1, 2, 1, 2]), 4); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /classify/src/p0137_single_number_ii.rs: -------------------------------------------------------------------------------- 1 | // 137. Single Number II 2 | // Medium 3 | 4 | // Given a non-empty array of integers, every element appears three times except for one, which appears exactly once. Find that single one. 5 | 6 | // Note: 7 | 8 | // Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? 9 | 10 | // Example 1: 11 | 12 | // Input: [2,2,3,2] 13 | // Output: 3 14 | // Example 2: 15 | 16 | // Input: [0,1,0,1,0,1,99] 17 | // Output: 99 18 | 19 | pub struct Solution {} 20 | 21 | impl Solution { 22 | pub fn single_number(nums: Vec) -> i32 { 23 | let mut result = 0; 24 | for i in 0..32 { 25 | // 依次计算32位中每一个bit为1的和,余3后,剩余的1即为不同的数字 26 | let mut sum_1_of_index_i = 0; 27 | for j in 0..nums.len() { 28 | sum_1_of_index_i += (nums[j] >> i) & 1; 29 | } 30 | result |= (sum_1_of_index_i % 3) << i; 31 | } 32 | result 33 | } 34 | } 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::*; 39 | 40 | #[test] 41 | fn single_number_test() { 42 | assert_eq!(Solution::single_number(vec![2, 2, 3, 2]), 3); 43 | assert_eq!(Solution::single_number(vec![0, 1, 0, 1, 0, 1, 99]), 99); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /classify/src/p0169_majority_element.rs: -------------------------------------------------------------------------------- 1 | // 169. Majority Element 2 | // Easy 3 | 4 | // Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times. 5 | 6 | // You may assume that the array is non-empty and the majority element always exist in the array. 7 | 8 | // Example 1: 9 | 10 | // Input: [3,2,3] 11 | // Output: 3 12 | // Example 2: 13 | 14 | // Input: [2,2,1,1,1,2,2] 15 | // Output: 2 16 | 17 | pub struct Solution {} 18 | 19 | impl Solution { 20 | pub fn majority_element(nums: Vec) -> i32 { 21 | let mut majority = nums[0]; 22 | let mut count = 1; 23 | for num in &nums[1..] { 24 | if count == 0 { 25 | majority = *num; 26 | } 27 | 28 | if majority == *num { 29 | count += 1; 30 | } else { 31 | count -= 1; 32 | } 33 | } 34 | majority 35 | } 36 | } 37 | 38 | #[cfg(test)] 39 | mod tests { 40 | use super::*; 41 | 42 | #[test] 43 | fn majority_element_test() { 44 | assert_eq!(Solution::majority_element(vec![1, 1, 2]), 1); 45 | assert_eq!(Solution::majority_element(vec![2, 2, 1, 1, 1, 2, 2]), 2); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /classify/src/p0171_excel_sheet_column_number.rs: -------------------------------------------------------------------------------- 1 | // 171. Excel Sheet Column Number 2 | // Easy 3 | 4 | // Given a column title as appear in an Excel sheet, return its corresponding column number. 5 | 6 | // For example: 7 | 8 | // A -> 1 9 | // B -> 2 10 | // C -> 3 11 | // ... 12 | // Z -> 26 13 | // AA -> 27 14 | // AB -> 28 15 | // ... 16 | // Example 1: 17 | 18 | // Input: "A" 19 | // Output: 1 20 | // Example 2: 21 | 22 | // Input: "AB" 23 | // Output: 28 24 | // Example 3: 25 | 26 | // Input: "ZY" 27 | // Output: 701 28 | 29 | pub struct Solution {} 30 | 31 | impl Solution { 32 | pub fn title_to_number(s: String) -> i32 { 33 | let chars: Vec = s.chars().rev().collect(); 34 | let mut result = 0; 35 | let mut base = 1; 36 | for ch in chars { 37 | result += (((ch as u8) - ('A' as u8) + 1_u8) as i32) * base; 38 | base *= 26; 39 | } 40 | result 41 | } 42 | } 43 | 44 | #[cfg(test)] 45 | mod tests { 46 | use super::*; 47 | 48 | #[test] 49 | fn title_to_number_test() { 50 | assert_eq!(Solution::title_to_number("A".to_string()), 1); 51 | assert_eq!(Solution::title_to_number("Z".to_string()), 26); 52 | assert_eq!(Solution::title_to_number("AB".to_string()), 28); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /classify/src/p0172_factorial_trailing_zeroes.rs: -------------------------------------------------------------------------------- 1 | // 172. Factorial Trailing Zeroes 2 | // Easy 3 | 4 | // Given an integer n, return the number of trailing zeroes in n!. 5 | 6 | // Example 1: 7 | 8 | // Input: 3 9 | // Output: 0 10 | // Explanation: 3! = 6, no trailing zero. 11 | // Example 2: 12 | 13 | // Input: 5 14 | // Output: 1 15 | // Explanation: 5! = 120, one trailing zero. 16 | // Note: Your solution should be in logarithmic time complexity. 17 | 18 | pub struct Solution {} 19 | 20 | impl Solution { 21 | pub fn trailing_zeroes(n: i32) -> i32 { 22 | let mut n = n; 23 | let mut result = 0; 24 | while n > 0 { 25 | n = n / 5; 26 | result += n; 27 | } 28 | result 29 | } 30 | } 31 | 32 | #[cfg(test)] 33 | mod tests { 34 | use super::*; 35 | 36 | #[test] 37 | fn trailing_zeroes_test() { 38 | assert_eq!(Solution::trailing_zeroes(3), 0); 39 | assert_eq!(Solution::trailing_zeroes(5), 1); 40 | assert_eq!(Solution::trailing_zeroes(10), 2); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /classify/src/p0201_bitwise_and_of_numbers_range.rs: -------------------------------------------------------------------------------- 1 | // 201. Bitwise AND of Numbers Range 2 | // Medium 3 | 4 | // Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive. 5 | 6 | // Example 1: 7 | 8 | // Input: [5,7] 9 | // Output: 4 10 | // Example 2: 11 | 12 | // Input: [0,1] 13 | // Output: 0 14 | 15 | pub struct Solution {} 16 | 17 | impl Solution { 18 | pub fn range_bitwise_and(m: i32, n: i32) -> i32 { 19 | (m..n).fold(n, |result, x| result & x) 20 | } 21 | } 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | use super::*; 26 | 27 | #[test] 28 | fn range_bitwise_and_test() { 29 | assert_eq!(Solution::range_bitwise_and(5, 7), 4); 30 | assert_eq!(Solution::range_bitwise_and(0, 1), 0); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /classify/src/p0204_count_primes.rs: -------------------------------------------------------------------------------- 1 | // 204. Count Primes 2 | // Easy 3 | 4 | // Count the number of prime numbers less than a non-negative number, n. 5 | 6 | // Example: 7 | 8 | // Input: 10 9 | // Output: 4 10 | // Explanation: There are 4 prime numbers less than 10, they are 2, 3, 5, 7. 11 | 12 | pub struct Solution {} 13 | 14 | use std::collections::HashSet; 15 | impl Solution { 16 | pub fn count_primes(n: i32) -> i32 { 17 | let mut primes: HashSet = HashSet::new(); 18 | let mut count = 0; 19 | for index in 2_i64..n as i64 { 20 | if primes.contains(&index) { 21 | continue; 22 | } 23 | count += 1; 24 | let mut j = index * index; 25 | while j < n as i64 { 26 | primes.insert(j); 27 | j += index; 28 | } 29 | } 30 | count 31 | } 32 | } 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use super::Solution; 37 | 38 | #[test] 39 | fn count_primes_test() { 40 | assert_eq!(Solution::count_primes(2), 0); 41 | assert_eq!(Solution::count_primes(3), 1); 42 | assert_eq!(Solution::count_primes(10), 4); 43 | assert_eq!(Solution::count_primes(499979), 41537); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /classify/src/p0217_contains_duplicate.rs: -------------------------------------------------------------------------------- 1 | // 217. Contains Duplicate 2 | // Easy 3 | 4 | // Given an array of integers, find if the array contains any duplicates. 5 | 6 | // Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct. 7 | 8 | // Example 1: 9 | 10 | // Input: [1,2,3,1] 11 | // Output: true 12 | // Example 2: 13 | 14 | // Input: [1,2,3,4] 15 | // Output: false 16 | // Example 3: 17 | 18 | // Input: [1,1,1,3,3,4,3,2,4,2] 19 | // Output: true 20 | 21 | pub struct Solution {} 22 | 23 | use std::collections::HashSet; 24 | impl Solution { 25 | pub fn contains_duplicate(nums: Vec) -> bool { 26 | let sub: HashSet<_> = nums.iter().cloned().collect(); 27 | sub.len() != nums.len() 28 | } 29 | } 30 | 31 | #[cfg(test)] 32 | mod tests { 33 | use super::*; 34 | 35 | #[test] 36 | fn contains_duplicate_test() { 37 | assert_eq!(Solution::contains_duplicate(vec![1, 2, 3, 4]), false); 38 | assert_eq!(Solution::contains_duplicate(vec![1, 1, 3, 4]), true); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /classify/src/p0231_power_of_two.rs: -------------------------------------------------------------------------------- 1 | // 231. Power of Two 2 | // Easy 3 | 4 | // Given an integer, write a function to determine if it is a power of two. 5 | 6 | // Example 1: 7 | 8 | // Input: 1 9 | // Output: true 10 | // Explanation: 20 = 1 11 | // Example 2: 12 | 13 | // Input: 16 14 | // Output: true 15 | // Explanation: 24 = 16 16 | // Example 3: 17 | 18 | // Input: 218 19 | // Output: false 20 | 21 | pub struct Solution {} 22 | 23 | impl Solution { 24 | pub fn is_power_of_two(n: i32) -> bool { 25 | if n <= 0 { 26 | return false; 27 | } 28 | let mut n = n; 29 | while n > 0 { 30 | if n == 1 { 31 | return true; 32 | } 33 | if n % 2 == 1 { 34 | return false; 35 | } 36 | n /= 2; 37 | } 38 | true 39 | } 40 | } 41 | 42 | #[cfg(test)] 43 | mod tests { 44 | use super::*; 45 | 46 | #[test] 47 | fn is_power_of_two_test() { 48 | assert_eq!(Solution::is_power_of_two(16), true); 49 | assert_eq!(Solution::is_power_of_two(1), true); 50 | assert_eq!(Solution::is_power_of_two(218), false); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /classify/src/p0238_product_of_array_except_self.rs: -------------------------------------------------------------------------------- 1 | // 238. Product of Array Except Self 2 | // Medium 3 | 4 | // Given an array nums of n integers where n > 1, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i]. 5 | 6 | // Example: 7 | 8 | // Input: [1,2,3,4] 9 | // Output: [24,12,8,6] 10 | // Note: Please solve it without division and in O(n). 11 | 12 | // Follow up: 13 | // Could you solve it with constant space complexity? (The output array does not count as extra space for the purpose of space complexity analysis.) 14 | 15 | pub struct Solution {} 16 | 17 | impl Solution { 18 | pub fn product_except_self(nums: Vec) -> Vec { 19 | let n = nums.len(); 20 | let mut result: Vec = vec![1; n]; 21 | let mut left = 1; 22 | for index in 1..n { 23 | left *= nums[index - 1]; 24 | result[index] *= left; 25 | } 26 | let mut right = 1; 27 | for index in (0..=n - 2).rev() { 28 | right *= nums[index + 1]; 29 | result[index] *= right; 30 | } 31 | result 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use super::*; 38 | 39 | #[test] 40 | fn product_except_self_test() { 41 | assert_eq!( 42 | Solution::product_except_self(vec![1, 2, 3, 4]), 43 | vec![24, 12, 8, 6] 44 | ); 45 | assert_eq!( 46 | Solution::product_except_self(vec![1, 2, 3, 4, 5]), 47 | vec![120, 60, 40, 30, 24] 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /classify/src/p0242_valid_anagram.rs: -------------------------------------------------------------------------------- 1 | // 242. Valid Anagram 2 | // Easy 3 | 4 | // Given two strings s and t , write a function to determine if t is an anagram of s. 5 | 6 | // Example 1: 7 | 8 | // Input: s = "anagram", t = "nagaram" 9 | // Output: true 10 | // Example 2: 11 | 12 | // Input: s = "rat", t = "car" 13 | // Output: false 14 | // Note: 15 | // You may assume the string contains only lowercase alphabets. 16 | 17 | // Follow up: 18 | // What if the inputs contain unicode characters? How would you adapt your solution to such case? 19 | 20 | pub struct Solution {} 21 | 22 | use std::collections::HashMap; 23 | impl Solution { 24 | pub fn is_anagram(s: String, t: String) -> bool { 25 | Solution::get_hash_map(s) == Solution::get_hash_map(t) 26 | } 27 | 28 | fn get_hash_map(s: String) -> HashMap { 29 | let mut hash_map = HashMap::new(); 30 | for ch in s.chars() { 31 | let counter = hash_map.entry(ch).or_insert(0); 32 | *counter += 1; 33 | } 34 | hash_map 35 | } 36 | } 37 | 38 | #[cfg(test)] 39 | mod tests { 40 | use super::*; 41 | 42 | #[test] 43 | fn is_anagram_test() { 44 | assert_eq!(Solution::is_anagram("anagram".to_owned(), "nagaram".to_owned()), true); 45 | assert_eq!(Solution::is_anagram("rat".to_owned(), "car".to_owned()), false); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /classify/src/p0258_add_digits.rs: -------------------------------------------------------------------------------- 1 | // 258. Add Digits 2 | // Easy 3 | 4 | // Given a non-negative integer num, repeatedly add all its digits until the result has only one digit. 5 | 6 | // Example: 7 | 8 | // Input: 38 9 | // Output: 2 10 | // Explanation: The process is like: 3 + 8 = 11, 1 + 1 = 2. 11 | // Since 2 has only one digit, return it. 12 | // Follow up: 13 | // Could you do it without any loop/recursion in O(1) runtime? 14 | 15 | pub struct Solution {} 16 | 17 | impl Solution { 18 | pub fn add_digits(num: i32) -> i32 { 19 | let mut result = num; 20 | while result > 9 { 21 | result = Solution::calc(result); 22 | } 23 | result 24 | } 25 | fn calc(num: i32) -> i32 { 26 | let mut result = 0; 27 | let mut num = num; 28 | while num > 0 { 29 | result += num % 10; 30 | num /= 10; 31 | } 32 | result 33 | } 34 | } 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::*; 39 | 40 | #[test] 41 | fn add_digits_test() { 42 | assert_eq!(Solution::add_digits(0), 0); 43 | assert_eq!(Solution::add_digits(9), 9); 44 | assert_eq!(Solution::add_digits(10), 1); 45 | assert_eq!(Solution::add_digits(38), 2); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /classify/src/p0260_single_number_iii.rs: -------------------------------------------------------------------------------- 1 | // 260. Single Number III 2 | // Medium 3 | 4 | // Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once. 5 | 6 | // Example: 7 | 8 | // Input: [1,2,1,3,2,5] 9 | // Output: [3,5] 10 | // Note: 11 | 12 | // The order of the result is not important. So in the above example, [5, 3] is also correct. 13 | // Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity? 14 | 15 | pub struct Solution {} 16 | 17 | impl Solution { 18 | pub fn single_number(nums: Vec) -> Vec { 19 | // 先计算a^b, 然后根据最后一个1来区分a或者b 20 | let a_xor_b = nums.iter().fold(0, |result, num| result ^ num); 21 | let mut result = vec![a_xor_b; 2]; 22 | let the_last_diff_1 = a_xor_b & (a_xor_b - 1) ^ a_xor_b; 23 | for i in 0..nums.len() { 24 | match the_last_diff_1 & nums[i] { 25 | 0 => result[0] ^= nums[i], 26 | _ => result[1] ^= nums[i], 27 | } 28 | } 29 | result.sort(); 30 | result 31 | } 32 | } 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use super::*; 37 | 38 | #[test] 39 | fn single_number_test() { 40 | assert_eq!(Solution::single_number(vec![1, 2, 1, 3, 2, 5]), vec![3, 5]); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /classify/src/p0264_ugly_number_ii.rs: -------------------------------------------------------------------------------- 1 | // 264. Ugly Number II 2 | // Medium 3 | 4 | // Write a program to find the n-th ugly number. 5 | 6 | // Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. 7 | 8 | // Example: 9 | 10 | // Input: n = 10 11 | // Output: 12 12 | // Explanation: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers. 13 | // Note: 14 | 15 | // 1 is typically treated as an ugly number. 16 | // n does not exceed 1690. 17 | 18 | pub struct Solution {} 19 | 20 | impl Solution { 21 | pub fn nth_ugly_number(n: i32) -> i32 { 22 | let mut ugly_numbers: Vec = vec![1]; 23 | let (mut index_2, mut index_3, mut index_5) = (0, 0, 0); 24 | for _ in 1..n { 25 | let ugly_2 = ugly_numbers[index_2] * 2; 26 | let ugly_3 = ugly_numbers[index_3] * 3; 27 | let ugly_5 = ugly_numbers[index_5] * 5; 28 | let cur_mins = i32::min(ugly_2, i32::min(ugly_3, ugly_5)); 29 | if cur_mins == ugly_2 { index_2 += 1 } 30 | if cur_mins == ugly_3 { index_3 += 1 } 31 | if cur_mins == ugly_5 { index_5 += 1 } 32 | ugly_numbers.push(cur_mins); 33 | } 34 | ugly_numbers[ugly_numbers.len() - 1] 35 | } 36 | } 37 | 38 | #[cfg(test)] 39 | mod tests { 40 | use super::*; 41 | 42 | #[test] 43 | fn nth_ugly_number_test() { 44 | assert_eq!(Solution::nth_ugly_number(10), 12); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /classify/src/p0268_missing_number.rs: -------------------------------------------------------------------------------- 1 | // 268. Missing Number 2 | // Easy 3 | 4 | // Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array. 5 | 6 | // Example 1: 7 | 8 | // Input: [3,0,1] 9 | // Output: 2 10 | // Example 2: 11 | 12 | // Input: [9,6,4,2,3,5,7,0,1] 13 | // Output: 8 14 | // Note: 15 | // Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity? 16 | 17 | pub struct Solution {} 18 | 19 | impl Solution { 20 | pub fn missing_number(nums: Vec) -> i32 { 21 | let len = nums.len() as i32; 22 | if len == 0 { 23 | return 0; 24 | } 25 | (len * (len + 1)) / 2 - nums.into_iter().sum::() 26 | } 27 | } 28 | 29 | #[cfg(test)] 30 | mod tests { 31 | use super::*; 32 | 33 | #[test] 34 | fn missing_number_test() { 35 | assert_eq!(Solution::missing_number(vec![]), 0); 36 | assert_eq!(Solution::missing_number(vec![3, 0, 1]), 2); 37 | assert_eq!(Solution::missing_number(vec![9, 6, 4, 2, 3, 5, 7, 0, 1]), 8); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /classify/src/p0279_perfect_squares.rs: -------------------------------------------------------------------------------- 1 | // 279. Perfect Squares 2 | // Medium 3 | 4 | // Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n. 5 | 6 | // Example 1: 7 | 8 | // Input: n = 12 9 | // Output: 3 10 | // Explanation: 12 = 4 + 4 + 4. 11 | // Example 2: 12 | 13 | // Input: n = 13 14 | // Output: 2 15 | // Explanation: 13 = 4 + 9. 16 | 17 | pub struct Solution {} 18 | 19 | impl Solution { 20 | pub fn num_squares(n: i32) -> i32 { 21 | let squares: Vec = Solution::get_squares(n); 22 | let mut dp: Vec = vec![0; (n + 1) as usize]; 23 | for i in 1..=n { 24 | dp[i as usize] = std::i32::MAX; 25 | for &square in squares.iter() { 26 | if square > i { 27 | break; 28 | } 29 | dp[i as usize] = i32::min(dp[i as usize], dp[(i - square) as usize] + 1); 30 | } 31 | } 32 | dp[n as usize] 33 | } 34 | 35 | fn get_squares(n: i32) -> Vec { 36 | let mut squares: Vec = Vec::new(); 37 | let mut diff = 3; 38 | let mut square = 1; 39 | while square <= n { 40 | squares.push(square); 41 | square += diff; 42 | diff += 2; 43 | } 44 | squares 45 | } 46 | } 47 | 48 | #[cfg(test)] 49 | mod tests { 50 | use super::*; 51 | 52 | #[test] 53 | fn num_squares_test() { 54 | assert_eq!(Solution::num_squares(12), 3); 55 | assert_eq!(Solution::num_squares(13), 2); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /classify/src/p0292_nim_game.rs: -------------------------------------------------------------------------------- 1 | pub struct Solution {} 2 | 3 | impl Solution { 4 | // 小时候老爸跟我经常玩报数的游戏;) 5 | pub fn can_win_nim(n: i32) -> bool { 6 | n % 4 != 0 7 | } 8 | } 9 | 10 | #[cfg(test)] 11 | mod tests { 12 | use super::*; 13 | 14 | #[test] 15 | fn can_win_nim_test() { 16 | assert_eq!(Solution::can_win_nim(4), false); 17 | assert_eq!(Solution::can_win_nim(1), true); 18 | assert_eq!(Solution::can_win_nim(2), true); 19 | assert_eq!(Solution::can_win_nim(3), true); 20 | assert_eq!(Solution::can_win_nim(5), true); 21 | assert_eq!(Solution::can_win_nim(6), true); 22 | assert_eq!(Solution::can_win_nim(7), true); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /classify/src/p0292_nim_game2.rs: -------------------------------------------------------------------------------- 1 | // 292. Nim Game 2 | // Easy 3 | 4 | // You are playing the following Nim Game with your friend: There is a heap of stones on the table, each time one of you take turns to remove 1 to 3 stones. The one who removes the last stone will be the winner. You will take the first turn to remove the stones. 5 | 6 | // Both of you are very clever and have optimal strategies for the game. Write a function to determine whether you can win the game given the number of stones in the heap. 7 | 8 | // Example: 9 | 10 | // Input: 4 11 | // Output: false 12 | // Explanation: If there are 4 stones in the heap, then you will never win the game; 13 | // No matter 1, 2, or 3 stones you remove, the last stone will always be 14 | // removed by your friend. 15 | 16 | pub struct Solution {} 17 | 18 | impl Solution { 19 | pub fn can_win_nim(n: i32) -> bool { 20 | n % 4 != 0 21 | } 22 | } 23 | 24 | #[cfg(test)] 25 | mod tests { 26 | use super::*; 27 | 28 | #[test] 29 | fn can_win_nim_test() { 30 | assert_eq!(Solution::can_win_nim(4), false); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /classify/src/p0300_longest_increasing_subsequence.rs: -------------------------------------------------------------------------------- 1 | // 300. Longest Increasing Subsequence 2 | // Medium 3 | 4 | // Given an unsorted array of integers, find the length of longest increasing subsequence. 5 | 6 | // Example: 7 | 8 | // Input: [10,9,2,5,3,7,101,18] 9 | // Output: 4 10 | // Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4. 11 | // Note: 12 | 13 | // There may be more than one LIS combination, it is only necessary for you to return the length. 14 | // Your algorithm should run in O(n2) complexity. 15 | // Follow up: Could you improve it to O(n log n) time complexity? 16 | 17 | pub struct Solution {} 18 | 19 | impl Solution { 20 | pub fn length_of_lis(nums: Vec) -> i32 { 21 | let n = nums.len(); 22 | let mut dp: Vec = vec![1; n]; 23 | for i in 0..n { 24 | for j in 0..i { 25 | if nums[i] > nums[j] { 26 | dp[i] = i32::max(dp[i], dp[j] + 1); 27 | } 28 | } 29 | } 30 | // NOTE: nums 可能为[], 故unwrap_or(0) 31 | *dp.iter().max().unwrap_or(&0) 32 | } 33 | // TODO 使用二分查找降低时间复杂度 34 | } 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::*; 39 | 40 | #[test] 41 | fn length_of_lis_test() { 42 | assert_eq!(Solution::length_of_lis(vec![1, 2, 3, 4, 5, 6, 7, 8]), 8); 43 | assert_eq!(Solution::length_of_lis(vec![10, 9, 2, 5, 3, 7, 101, 18]), 4); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /classify/src/p0303_range_sum_query_immutable.rs: -------------------------------------------------------------------------------- 1 | // 303. Range Sum Query - Immutable 2 | // Easy 3 | 4 | // Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. 5 | 6 | // Example: 7 | // Given nums = [-2, 0, 3, -5, 2, -1] 8 | 9 | // sumRange(0, 2) -> 1 10 | // sumRange(2, 5) -> -1 11 | // sumRange(0, 5) -> -3 12 | // Note: 13 | // You may assume that the array does not change. 14 | // There are many calls to sumRange function. 15 | 16 | pub struct NumArray { 17 | pub sums: Vec, 18 | } 19 | 20 | 21 | /** 22 | * `&self` means the method takes an immutable reference. 23 | * If you need a mutable reference, change it to `&mut self` instead. 24 | */ 25 | impl NumArray { 26 | 27 | pub fn new(nums: Vec) -> Self { 28 | let mut sums = vec![0; nums.len() + 1]; 29 | for i in 0..nums.len() { 30 | sums[i+1] = sums[i] + nums[i]; 31 | } 32 | Self { sums } 33 | } 34 | 35 | pub fn sum_range(&self, i: i32, j: i32) -> i32 { 36 | self.sums[j as usize + 1] - self.sums[i as usize] 37 | } 38 | } 39 | 40 | #[cfg(test)] 41 | mod tests { 42 | use super::*; 43 | 44 | #[test] 45 | fn num_array_test() { 46 | let num_array = NumArray::new(vec![-2, 0, 3, -5, 2, -1]); 47 | assert_eq!(num_array.sum_range(0, 2), 1); 48 | assert_eq!(num_array.sum_range(2, 5), -1); 49 | assert_eq!(num_array.sum_range(0, 5), -3); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /classify/src/p0326_power_of_three.rs: -------------------------------------------------------------------------------- 1 | // 326. Power of Three 2 | // Easy 3 | 4 | // Given an integer, write a function to determine if it is a power of three. 5 | 6 | // Example 1: 7 | 8 | // Input: 27 9 | // Output: true 10 | // Example 2: 11 | 12 | // Input: 0 13 | // Output: false 14 | // Example 3: 15 | 16 | // Input: 9 17 | // Output: true 18 | // Example 4: 19 | 20 | // Input: 45 21 | // Output: false 22 | // Follow up: 23 | // Could you do it without using any loop / recursion? 24 | 25 | pub struct Solution {} 26 | 27 | impl Solution { 28 | pub fn is_power_of_three(n: i32) -> bool { 29 | if n <= 0 { 30 | return false; 31 | } 32 | let mut n = n; 33 | while n > 0 { 34 | if n == 1 { 35 | return true; 36 | } 37 | if n % 3 != 0 { 38 | return false; 39 | } 40 | n /= 3; 41 | } 42 | true 43 | } 44 | } 45 | 46 | #[cfg(test)] 47 | mod tests { 48 | use super::*; 49 | 50 | #[test] 51 | fn is_power_of_three_test() { 52 | assert_eq!(Solution::is_power_of_three(1), true); 53 | assert_eq!(Solution::is_power_of_three(9), true); 54 | assert_eq!(Solution::is_power_of_three(10), false); 55 | assert_eq!(Solution::is_power_of_three(27), true); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /classify/src/p0342_power_of_four.rs: -------------------------------------------------------------------------------- 1 | // 342. Power of Four 2 | // Easy 3 | 4 | // Given an integer (signed 32 bits), write a function to check whether it is a power of 4. 5 | 6 | // Example 1: 7 | 8 | // Input: 16 9 | // Output: true 10 | // Example 2: 11 | 12 | // Input: 5 13 | // Output: false 14 | // Follow up: Could you solve it without loops/recursion? 15 | 16 | pub struct Solution {} 17 | 18 | impl Solution { 19 | pub fn is_power_of_four(n: i32) -> bool { 20 | if n <= 0 { 21 | return false; 22 | } 23 | let mut n = n; 24 | while n > 0 { 25 | if n == 1 { 26 | return true; 27 | } 28 | if n % 4 != 0 { 29 | return false; 30 | } 31 | n /= 4; 32 | } 33 | true 34 | } 35 | } 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | use super::*; 40 | 41 | #[test] 42 | fn is_power_of_four_test() { 43 | assert_eq!(Solution::is_power_of_four(1), true); 44 | assert_eq!(Solution::is_power_of_four(4), true); 45 | assert_eq!(Solution::is_power_of_four(16), true); 46 | assert_eq!(Solution::is_power_of_four(25), false); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /classify/src/p0344_reverse_string.rs: -------------------------------------------------------------------------------- 1 | // 344. Reverse String 2 | // Easy 3 | 4 | // Write a function that reverses a string. The input string is given as an array of characters char[]. 5 | 6 | // Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. 7 | 8 | // You may assume all the characters consist of printable ascii characters. 9 | 10 | // Example 1: 11 | 12 | // Input: ["h","e","l","l","o"] 13 | // Output: ["o","l","l","e","h"] 14 | // Example 2: 15 | 16 | // Input: ["H","a","n","n","a","h"] 17 | // Output: ["h","a","n","n","a","H"] 18 | 19 | pub struct Solution {} 20 | 21 | impl Solution { 22 | pub fn reverse_string(s: &mut Vec) { 23 | s.reverse() 24 | } 25 | } 26 | 27 | #[cfg(test)] 28 | mod tests { 29 | use super::*; 30 | 31 | #[test] 32 | fn reverse_string_test() { 33 | let mut arr: Vec = vec!['h', 'e', 'l', 'l', 'o']; 34 | Solution::reverse_string(&mut arr); 35 | assert_eq!(arr, vec!['o', 'l', 'l', 'e', 'h']); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /classify/src/p0349_intersection_of_two_arrays.rs: -------------------------------------------------------------------------------- 1 | // 349. Intersection of Two Arrays 2 | // Easy 3 | 4 | // Given two arrays, write a function to compute their intersection. 5 | 6 | // Example 1: 7 | 8 | // Input: nums1 = [1,2,2,1], nums2 = [2,2] 9 | // Output: [2] 10 | // Example 2: 11 | 12 | // Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4] 13 | // Output: [9,4] 14 | // Note: 15 | 16 | // Each element in the result must be unique. 17 | // The result can be in any order. 18 | 19 | pub struct Solution {} 20 | 21 | // use std::collections::HashSet; 22 | use std::collections::BTreeSet; 23 | impl Solution { 24 | pub fn intersection(nums1: Vec, nums2: Vec) -> Vec { 25 | // let nums_set1: HashSet = nums1.iter().cloned().collect(); 26 | // let nums_set2: HashSet = nums2.iter().cloned().collect(); 27 | let nums_set1: BTreeSet = nums1.iter().cloned().collect(); 28 | let nums_set2: BTreeSet = nums2.iter().cloned().collect(); 29 | nums_set1 30 | .intersection(&nums_set2) 31 | .cloned() 32 | .collect::>() 33 | } 34 | } 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::*; 39 | 40 | #[test] 41 | fn intersection_test() { 42 | assert_eq!(Solution::intersection(vec![], vec![2, 2]), vec![]); 43 | assert_eq!( 44 | Solution::intersection(vec![1, 2, 2, 1], vec![2, 2]), 45 | vec![2] 46 | ); 47 | assert_eq!( 48 | Solution::intersection(vec![4, 9, 5], vec![9, 4, 9, 8, 4]), 49 | vec![4, 9] 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /classify/src/p0357_count_numbers_with_unique_digits.rs: -------------------------------------------------------------------------------- 1 | // 357. Count Numbers with Unique Digits 2 | // Medium 3 | 4 | // Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10n. 5 | 6 | // Example: 7 | 8 | // Input: 2 9 | // Output: 91 10 | // Explanation: The answer should be the total numbers in the range of 0 ≤ x < 100, 11 | // excluding 11,22,33,44,55,66,77,88,99 12 | 13 | pub struct Solution {} 14 | 15 | impl Solution { 16 | pub fn count_numbers_with_unique_digits(n: i32) -> i32 { 17 | let array = [9, 9, 8, 7, 6, 5, 4, 3, 2, 1]; 18 | let mut counts = 1; 19 | let mut tmp = 1; 20 | for i in 0..i32::min(n, 10) { 21 | tmp *= array[i as usize]; 22 | counts += tmp; 23 | } 24 | counts 25 | } 26 | } 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | 32 | #[test] 33 | fn count_numbers_with_unique_digits_test() { 34 | assert_eq!(Solution::count_numbers_with_unique_digits(0), 1); 35 | assert_eq!(Solution::count_numbers_with_unique_digits(1), 10); 36 | assert_eq!(Solution::count_numbers_with_unique_digits(2), 91); 37 | assert_eq!(Solution::count_numbers_with_unique_digits(3), 739); 38 | assert_eq!(Solution::count_numbers_with_unique_digits(10), 8877691); 39 | assert_eq!(Solution::count_numbers_with_unique_digits(13), 8877691); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /classify/src/p0371_sum_of_two_integers.rs: -------------------------------------------------------------------------------- 1 | // 371. Sum of Two Integers 2 | // Easy 3 | 4 | // Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -. 5 | 6 | // Example 1: 7 | 8 | // Input: a = 1, b = 2 9 | // Output: 3 10 | // Example 2: 11 | 12 | // Input: a = -2, b = 3 13 | // Output: 1 14 | 15 | pub struct Solution {} 16 | 17 | // 正数的补码和原码相同,负数的补码为除了第一位符号位之外,其他位0变1,1变0,并且最后再加1 18 | // 以 -1 + 2 = 1 为例 19 | // 11111111 ^ 00000010 = 11111101, (11111111 & 00000010) << 1 = 00000100 20 | // 11111101 ^ 00000100 = 11111001, (11111101 & 00000100) << 1 = 00001000 21 | // 11111001 ^ 00001000 = 11110001, (11111001 & 00001000) << 1 = 00010000 22 | // ... 23 | // 10000001 ^ 10000000 = 00000001, (10000001 & 10000000) << 1 = 00000000 24 | impl Solution { 25 | pub fn get_sum(a: i32, b: i32) -> i32 { 26 | let mut a = a; 27 | let mut b = b; 28 | while b != 0 { 29 | let temp = a ^ b; 30 | b = (a & b) << 1; 31 | a = temp; 32 | } 33 | a 34 | } 35 | } 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | use super::*; 40 | 41 | #[test] 42 | fn get_sum_test() { 43 | assert_eq!(Solution::get_sum(1, 2), 3); 44 | assert_eq!(Solution::get_sum(-2, 3), 1); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /classify/src/p0387_first_unique_character_in_a_string.rs: -------------------------------------------------------------------------------- 1 | // 387. First Unique Character in a String 2 | // Easy 3 | 4 | // Given a string, find the first non-repeating character in it and return it's index. If it doesn't exist, return -1. 5 | 6 | // Examples: 7 | 8 | // s = "leetcode" 9 | // return 0. 10 | 11 | // s = "loveleetcode", 12 | // return 2. 13 | // Note: You may assume the string contain only lowercase letters. 14 | 15 | pub struct Solution {} 16 | 17 | use std::collections::HashMap; 18 | impl Solution { 19 | pub fn first_uniq_char(s: String) -> i32 { 20 | let chars: Vec = s.chars().collect(); 21 | let mut letters = HashMap::new(); 22 | for ch in chars.iter() { 23 | let counter = letters.entry(ch).or_insert(0); 24 | *counter += 1; 25 | } 26 | for (index, ch) in chars.iter().enumerate() { 27 | if letters.get(&ch) == Some(&1) { 28 | return index as i32; 29 | } 30 | } 31 | -1 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use super::*; 38 | 39 | #[test] 40 | fn first_uniq_char_test() { 41 | assert_eq!(Solution::first_uniq_char("leetcode".to_string()), 0); 42 | assert_eq!(Solution::first_uniq_char("eettoo".to_string()), -1); 43 | assert_eq!(Solution::first_uniq_char("loveleetcode".to_string()), 2); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /classify/src/p0434_number_of_segments_in_a_string.rs: -------------------------------------------------------------------------------- 1 | // 434. Number of Segments in a String 2 | // Easy 3 | 4 | // Count the number of segments in a string, where a segment is defined to be a contiguous sequence of non-space characters. 5 | 6 | // Please note that the string does not contain any non-printable characters. 7 | 8 | // Example: 9 | 10 | // Input: "Hello, my name is John" 11 | // Output: 5 12 | 13 | pub struct Solution {} 14 | 15 | impl Solution { 16 | pub fn count_segments(s: String) -> i32 { 17 | let v: Vec<&str> = s.trim().split_whitespace().collect(); 18 | v.len() as i32 19 | } 20 | } 21 | 22 | #[cfg(test)] 23 | mod tests { 24 | use super::*; 25 | 26 | #[test] 27 | fn count_segments_test() { 28 | assert_eq!(Solution::count_segments("".to_owned()), 0); 29 | assert_eq!(Solution::count_segments(" ".to_owned()), 0); 30 | assert_eq!(Solution::count_segments(" abc d ".to_owned()), 2); 31 | assert_eq!( 32 | Solution::count_segments("Hello, my name is John".to_owned()), 33 | 5 34 | ); 35 | assert_eq!( 36 | Solution::count_segments(", , , , a, eaefa".to_owned()), 37 | 6 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /classify/src/p0448_find_all_numbers_disappeared_in_an_array.rs: -------------------------------------------------------------------------------- 1 | // 448. Find All Numbers Disappeared in an Array 2 | // Easy 3 | 4 | // Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once. 5 | 6 | // Find all the elements of [1, n] inclusive that do not appear in this array. 7 | 8 | // Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space. 9 | 10 | // Example: 11 | 12 | // Input: 13 | // [4,3,2,7,8,2,3,1] 14 | 15 | // Output: 16 | // [5,6] 17 | 18 | pub struct Solution {} 19 | 20 | impl Solution { 21 | pub fn find_disappeared_numbers(nums: Vec) -> Vec { 22 | let mut nums = nums; 23 | for i in 0..nums.len() { 24 | let value = i32::abs(nums[i]) as usize - 1_usize; 25 | nums[value] = -i32::abs(nums[value]); 26 | } 27 | let mut result = Vec::new(); 28 | for i in 0..nums.len() { 29 | if nums[i] > 0 { 30 | result.push((i + 1_usize) as i32); 31 | } 32 | } 33 | result 34 | } 35 | } 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | use super::*; 40 | 41 | #[test] 42 | fn find_disappeared_numbers_test() { 43 | assert_eq!( 44 | Solution::find_disappeared_numbers(vec![4, 3, 2, 7, 8, 2, 3, 1]), 45 | vec![5, 6] 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /classify/src/p0461_hamming_distance.rs: -------------------------------------------------------------------------------- 1 | // 461. Hamming Distance 2 | // Easy 3 | 4 | // The Hamming distance between two integers is the number of positions at which the corresponding bits are different. 5 | 6 | // Given two integers x and y, calculate the Hamming distance. 7 | 8 | // Note: 9 | // 0 ≤ x, y < 231. 10 | 11 | // Example: 12 | 13 | // Input: x = 1, y = 4 14 | 15 | // Output: 2 16 | 17 | // Explanation: 18 | // 1 (0 0 0 1) 19 | // 4 (0 1 0 0) 20 | // ↑ ↑ 21 | 22 | // The above arrows point to positions where the corresponding bits are different. 23 | 24 | pub struct Solution {} 25 | 26 | impl Solution { 27 | pub fn hamming_distance(x: i32, y: i32) -> i32 { 28 | let mut xy = x ^ y; 29 | let mut result = 0; 30 | while xy > 0 { 31 | if xy % 2 == 1 { 32 | result += 1; 33 | } 34 | xy /= 2; 35 | } 36 | result 37 | } 38 | } 39 | 40 | #[cfg(test)] 41 | mod tests { 42 | use super::*; 43 | 44 | #[test] 45 | fn hamming_distance_test() { 46 | assert_eq!(Solution::hamming_distance(1, 4), 2); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /classify/src/p0462_minimum_moves_to_equal_array_element_ii.rs: -------------------------------------------------------------------------------- 1 | // 462. Minimum Moves to Equal Array Elements II 2 | // Medium 3 | 4 | // Given a non-empty integer array, find the minimum number of moves required to make all array elements equal, where a move is incrementing a selected element by 1 or decrementing a selected element by 1. 5 | 6 | // You may assume the array's length is at most 10,000. 7 | 8 | // Example: 9 | 10 | // Input: 11 | // [1,2,3] 12 | 13 | // Output: 14 | // 2 15 | 16 | // Explanation: 17 | // Only two moves are needed (remember each move increments or decrements one element): 18 | 19 | // [1,2,3] => [2,2,3] => [2,2,2] 20 | 21 | pub struct Solution {} 22 | 23 | impl Solution { 24 | pub fn min_moves2(nums: Vec) -> i32 { 25 | if nums.len() <= 1usize { 26 | return 0; 27 | } 28 | let mut nums = nums; 29 | nums.sort(); 30 | let (mut i, mut j) = (0usize, nums.len() - 1usize); 31 | let mut result = 0; 32 | while i <= j { 33 | result += nums[j] - nums[i]; 34 | i += 1usize; 35 | j -= 1usize; 36 | } 37 | result 38 | } 39 | } 40 | 41 | #[cfg(test)] 42 | mod tests { 43 | use super::*; 44 | 45 | #[test] 46 | fn min_moves2_test() { 47 | assert_eq!(Solution::min_moves2(vec![1, 2, 3]), 2); 48 | assert_eq!(Solution::min_moves2(vec![2, 1, 3]), 2); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /classify/src/p0504_base_7.rs: -------------------------------------------------------------------------------- 1 | // 504. Base 7 2 | // Easy 3 | 4 | // Given an integer, return its base 7 string representation. 5 | 6 | // Example 1: 7 | // Input: 100 8 | // Output: "202" 9 | // Example 2: 10 | // Input: -7 11 | // Output: "-10" 12 | // Note: The input will be in range of [-1e7, 1e7]. 13 | 14 | pub struct Solution {} 15 | 16 | impl Solution { 17 | pub fn convert_to_base7(num: i32) -> String { 18 | if num == 0 { 19 | return "0".to_owned(); 20 | } 21 | let is_negative = if num < 0 { true } else { false }; 22 | let mut num = if is_negative { -num } else { num }; 23 | let mut result = String::new(); 24 | while num > 0 { 25 | result.push_str(&(num % 7).to_string()); 26 | num /= 7; 27 | } 28 | if is_negative { 29 | result.push('-'); 30 | } 31 | result.chars().rev().collect() 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use super::*; 38 | 39 | #[test] 40 | fn convert_to_base7_test() { 41 | assert_eq!(Solution::convert_to_base7(100), "202".to_owned()); 42 | assert_eq!(Solution::convert_to_base7(-7), "-10".to_owned()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /classify/src/p0540_single_element_in_a_sorted_array.rs: -------------------------------------------------------------------------------- 1 | // 540. Single Element in a Sorted Array 2 | // Medium 3 | 4 | // You are given a sorted array consisting of only integers where every element appears exactly twice, except for one element which appears exactly once. Find this single element that appears only once. 5 | 6 | // Example 1: 7 | 8 | // Input: [1,1,2,3,3,4,4,8,8] 9 | // Output: 2 10 | // Example 2: 11 | 12 | // Input: [3,3,7,7,10,11,11] 13 | // Output: 10 14 | 15 | // Note: Your solution should run in O(log n) time and O(1) space. 16 | 17 | pub struct Solution {} 18 | 19 | impl Solution { 20 | pub fn single_non_duplicate(nums: Vec) -> i32 { 21 | let (mut left, mut right) = (0, nums.len() as i32 - 1); 22 | while left < right { 23 | let mut mid = left + (right - left) / 2; 24 | if mid % 2 == 1 { 25 | mid -= 1; 26 | } 27 | if nums[mid as usize] == nums[mid as usize + 1_usize] { 28 | left += 2; 29 | } else { 30 | right = mid; 31 | } 32 | } 33 | nums[left as usize] 34 | } 35 | } 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | use super::Solution; 40 | 41 | #[test] 42 | fn single_non_duplicate_test() { 43 | assert_eq!( 44 | Solution::single_non_duplicate(vec![1, 1, 2, 3, 3, 4, 4, 8, 8]), 45 | 2 46 | ); 47 | assert_eq!( 48 | Solution::single_non_duplicate(vec![3, 3, 7, 7, 10, 11, 11]), 49 | 10 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /classify/src/p0551_student_attendance_record_i.rs: -------------------------------------------------------------------------------- 1 | // 551. Student Attendance Record I 2 | // Easy 3 | 4 | // You are given a string representing an attendance record for a student. The record only contains the following three characters: 5 | // 'A' : Absent. 6 | // 'L' : Late. 7 | // 'P' : Present. 8 | // A student could be rewarded if his attendance record doesn't contain more than one 'A' (absent) or more than two continuous 'L' (late). 9 | 10 | // You need to return whether the student could be rewarded according to his attendance record. 11 | 12 | // Example 1: 13 | // Input: "PPALLP" 14 | // Output: True 15 | // Example 2: 16 | // Input: "PPALLL" 17 | // Output: False 18 | 19 | pub struct Solution {} 20 | 21 | impl Solution { 22 | pub fn check_record(s: String) -> bool { 23 | let mut count_a = 0; 24 | let chs: Vec = s.chars().collect(); 25 | for i in 0..chs.len() { 26 | if chs[i] == 'A' { 27 | count_a += 1; 28 | if count_a >= 2 { 29 | return false 30 | } 31 | } else if i + 2 < chs.len() && chs[i] == 'L' && chs[i+1] == 'L' && chs[i+2] == 'L' { 32 | return false; 33 | } 34 | } 35 | true 36 | } 37 | } 38 | 39 | #[cfg(test)] 40 | mod tests { 41 | use super::*; 42 | 43 | #[test] 44 | fn check_record_test() { 45 | assert_eq!(Solution::check_record("PPALLP".to_owned()), true); 46 | assert_eq!(Solution::check_record("PPALLL".to_owned()), false); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /classify/src/p0560_subarray_sum_equals_k.rs: -------------------------------------------------------------------------------- 1 | // 560. Subarray Sum Equals K 2 | // Medium 3 | 4 | // Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k. 5 | 6 | // Example 1: 7 | 8 | // Input:nums = [1,1,1], k = 2 9 | // Output: 2 10 | 11 | 12 | // Constraints: 13 | 14 | // The length of the array is in range [1, 20,000]. 15 | // The range of numbers in the array is [-1000, 1000] and the range of the integer k is [-1e7, 1e7]. 16 | 17 | pub struct Solution {} 18 | 19 | impl Solution { 20 | pub fn subarray_sum(nums: Vec, k: i32) -> i32 { 21 | let mut presums = vec![0; nums.len() + 1]; 22 | let mut sum = 0; 23 | for i in 0..nums.len() { 24 | presums[i] = sum; 25 | sum += nums[i]; 26 | } 27 | presums[nums.len()] = sum; 28 | 29 | let mut count = 0; 30 | for i in 0..=nums.len() { 31 | for j in i + 1..=nums.len() { 32 | if presums[j] - presums[i] == k { 33 | count += 1; 34 | } 35 | } 36 | } 37 | count 38 | } 39 | // TODO, 可以使用HashMap进行优化成O(n) 40 | } 41 | 42 | #[cfg(test)] 43 | mod tests { 44 | use super::*; 45 | 46 | #[test] 47 | fn subarray_sum_test() { 48 | assert_eq!(Solution::subarray_sum(vec![1, 1, 1], 2), 2); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /classify/src/p0633_sum_of_square_numbers.rs: -------------------------------------------------------------------------------- 1 | // Given a non-negative integer c, your task is to decide whether there're two integers a and b such that a2 + b2 = c. 2 | 3 | // Example 1: 4 | 5 | // Input: 5 6 | // Output: True 7 | // Explanation: 1 * 1 + 2 * 2 = 5 8 | 9 | // Example 2: 10 | 11 | // Input: 3 12 | // Output: False 13 | 14 | pub struct Solution {} 15 | 16 | impl Solution { 17 | pub fn judge_square_sum(c: i32) -> bool { 18 | // 0 也是整数 19 | let (mut i, mut j) = (0, (c as f32).sqrt() as i32); 20 | while i <= j { 21 | let sum = i * i + j * j; 22 | if sum == c { 23 | return true; 24 | } else if sum > c { 25 | j -= 1; 26 | } else { 27 | i += 1; 28 | } 29 | } 30 | false 31 | } 32 | } 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use super::Solution; 37 | 38 | #[test] 39 | fn judge_square_sum_test() { 40 | assert_eq!(Solution::judge_square_sum(1), true); 41 | assert_eq!(Solution::judge_square_sum(5), true); 42 | assert_eq!(Solution::judge_square_sum(8), true); 43 | assert_eq!(Solution::judge_square_sum(7), false); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /classify/src/p0650_2_keys_keyboard.rs: -------------------------------------------------------------------------------- 1 | // 650. 2 Keys Keyboard 2 | // Medium 3 | 4 | // Initially on a notepad only one character 'A' is present. You can perform two operations on this notepad for each step: 5 | 6 | // Copy All: You can copy all the characters present on the notepad (partial copy is not allowed). 7 | // Paste: You can paste the characters which are copied last time. 8 | 9 | // Given a number n. You have to get exactly n 'A' on the notepad by performing the minimum number of steps permitted. Output the minimum number of steps to get n 'A'. 10 | 11 | // Example 1: 12 | 13 | // Input: 3 14 | // Output: 3 15 | // Explanation: 16 | // Intitally, we have one character 'A'. 17 | // In step 1, we use Copy All operation. 18 | // In step 2, we use Paste operation to get 'AA'. 19 | // In step 3, we use Paste operation to get 'AAA'. 20 | 21 | // Note: 22 | 23 | // The n will be in the range [1, 1000]. 24 | 25 | pub struct Solution {} 26 | 27 | impl Solution { 28 | pub fn min_steps(n: i32) -> i32 { 29 | let mut result = 0; 30 | let mut copy_n = n; 31 | for i in 2..=n { 32 | while copy_n % i == 0 { 33 | result += i; 34 | copy_n /= i; 35 | } 36 | } 37 | result 38 | } 39 | } 40 | 41 | #[cfg(test)] 42 | mod tests { 43 | use super::*; 44 | 45 | #[test] 46 | fn min_steps_test() { 47 | assert_eq!(Solution::min_steps(3), 3); 48 | assert_eq!(Solution::min_steps(4), 4); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /classify/src/p1025_divisor_game.rs: -------------------------------------------------------------------------------- 1 | // 1025. Divisor Game 2 | // Easy 3 | 4 | // Alice and Bob take turns playing a game, with Alice starting first. 5 | 6 | // Initially, there is a number N on the chalkboard. On each player's turn, that player makes a move consisting of: 7 | 8 | // Choosing any x with 0 < x < N and N % x == 0. 9 | // Replacing the number N on the chalkboard with N - x. 10 | // Also, if a player cannot make a move, they lose the game. 11 | 12 | // Return True if and only if Alice wins the game, assuming both players play optimally. 13 | 14 | 15 | 16 | // Example 1: 17 | 18 | // Input: 2 19 | // Output: true 20 | // Explanation: Alice chooses 1, and Bob has no more moves. 21 | // Example 2: 22 | 23 | // Input: 3 24 | // Output: false 25 | // Explanation: Alice chooses 1, Bob chooses 1, and Alice has no more moves. 26 | 27 | 28 | // Note: 29 | 30 | // 1 <= N <= 1000 31 | 32 | pub struct Solution {} 33 | 34 | impl Solution { 35 | pub fn divisor_game(n: i32) -> bool { 36 | n % 2 == 0 37 | } 38 | } 39 | 40 | #[cfg(test)] 41 | mod tests { 42 | use super::*; 43 | 44 | #[test] 45 | fn divisor_game_test() { 46 | assert_eq!(Solution::divisor_game(2), true); 47 | assert_eq!(Solution::divisor_game(3), false); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /classify/src/p1047_remove_all_adjacent_duplicates_in_string.rs: -------------------------------------------------------------------------------- 1 | // 1047. Remove All Adjacent Duplicates In String 2 | // Easy 3 | 4 | // Given a string S of lowercase letters, a duplicate removal consists of choosing two adjacent and equal letters, and removing them. 5 | 6 | // We repeatedly make duplicate removals on S until we no longer can. 7 | 8 | // Return the final string after all such duplicate removals have been made. It is guaranteed the answer is unique. 9 | 10 | 11 | 12 | // Example 1: 13 | 14 | // Input: "abbaca" 15 | // Output: "ca" 16 | // Explanation: 17 | // For example, in "abbaca" we could remove "bb" since the letters are adjacent and equal, and this is the only possible move. The result of this move is that the string is "aaca", of which only "aa" is possible, so the final string is "ca". 18 | 19 | 20 | // Note: 21 | 22 | // 1 <= S.length <= 20000 23 | // S consists only of English lowercase letters. 24 | 25 | pub struct Solution {} 26 | 27 | impl Solution { 28 | pub fn remove_duplicates(s: String) -> String { 29 | let mut stack: Vec = vec![]; 30 | for c in s.chars() { 31 | if stack.len() > 0 && stack[stack.len() -1] == c { 32 | stack.pop(); 33 | } else { 34 | stack.push(c) 35 | } 36 | } 37 | stack.iter().collect() 38 | } 39 | } 40 | 41 | #[cfg(test)] 42 | mod tests { 43 | use super::*; 44 | 45 | #[test] 46 | fn remove_duplicates_test() { 47 | assert_eq!(Solution::remove_duplicates("abbaca".to_owned()), "ca".to_owned()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /classify/src/p1464_maximum_product_of_two_elements_in_an_array.rs: -------------------------------------------------------------------------------- 1 | // 1464. Maximum Product of Two Elements in an Array 2 | // Easy 3 | 4 | // Given the array of integers nums, you will choose two different indices i and j of that array. Return the maximum value of (nums[i]-1)*(nums[j]-1). 5 | 6 | 7 | // Example 1: 8 | 9 | // Input: nums = [3,4,5,2] 10 | // Output: 12 11 | // Explanation: If you choose the indices i=1 and j=2 (indexed from 0), you will get the maximum value, that is, (nums[1]-1)*(nums[2]-1) = (4-1)*(5-1) = 3*4 = 12. 12 | // Example 2: 13 | 14 | // Input: nums = [1,5,4,5] 15 | // Output: 16 16 | // Explanation: Choosing the indices i=1 and j=3 (indexed from 0), you will get the maximum value of (5-1)*(5-1) = 16. 17 | // Example 3: 18 | 19 | // Input: nums = [3,7] 20 | // Output: 12 21 | 22 | 23 | // Constraints: 24 | 25 | // 2 <= nums.length <= 500 26 | // 1 <= nums[i] <= 10^3 27 | 28 | pub struct Solution {} 29 | 30 | impl Solution { 31 | pub fn max_product(nums: Vec) -> i32 { 32 | let mut nums: Vec = nums.iter().map(|a| a-1).collect(); 33 | nums.sort(); 34 | let lens = nums.len(); 35 | i32::max(nums[0] * nums[1], nums[lens-1] * nums[lens-2]) 36 | } 37 | } 38 | 39 | #[cfg(test)] 40 | mod tests { 41 | use super::*; 42 | 43 | #[test] 44 | fn max_product_test() { 45 | assert_eq!(Solution::max_product(vec![1, 5, 4, 5]), 16); 46 | assert_eq!(Solution::max_product(vec![1, 5, 4, 5, -6, -6]), 49); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /classify/src/p1486_xor_operation_in_an_array.rs: -------------------------------------------------------------------------------- 1 | // 1486. XOR Operation in an Array 2 | // Easy 3 | 4 | // Given an integer n and an integer start. 5 | 6 | // Define an array nums where nums[i] = start + 2*i (0-indexed) and n == nums.length. 7 | 8 | // Return the bitwise XOR of all elements of nums. 9 | 10 | 11 | 12 | // Example 1: 13 | 14 | // Input: n = 5, start = 0 15 | // Output: 8 16 | // Explanation: Array nums is equal to [0, 2, 4, 6, 8] where (0 ^ 2 ^ 4 ^ 6 ^ 8) = 8. 17 | // Where "^" corresponds to bitwise XOR operator. 18 | // Example 2: 19 | 20 | // Input: n = 4, start = 3 21 | // Output: 8 22 | // Explanation: Array nums is equal to [3, 5, 7, 9] where (3 ^ 5 ^ 7 ^ 9) = 8. 23 | // Example 3: 24 | 25 | // Input: n = 1, start = 7 26 | // Output: 7 27 | // Example 4: 28 | 29 | // Input: n = 10, start = 5 30 | // Output: 2 31 | 32 | 33 | // Constraints: 34 | 35 | // 1 <= n <= 1000 36 | // 0 <= start <= 1000 37 | // n == nums.length 38 | // Accepted 39 | // 8,786 40 | // Submissions 41 | // 9,743 42 | 43 | pub struct Solution {} 44 | 45 | impl Solution { 46 | pub fn xor_operation(n: i32, start: i32) -> i32 { 47 | (0..n).map(|index| start + 2*index).fold(0, |result, x| result ^ x) 48 | } 49 | } 50 | 51 | #[cfg(test)] 52 | mod tests { 53 | use super::*; 54 | 55 | #[test] 56 | fn xor_operation_test() { 57 | assert_eq!(Solution::xor_operation(5, 0), 8); 58 | assert_eq!(Solution::xor_operation(4, 3), 8); 59 | assert_eq!(Solution::xor_operation(1, 7), 7); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /classify/src/p1512_number_of_good_pairs.rs: -------------------------------------------------------------------------------- 1 | // 1512. Number of Good PairsMy SubmissionsBack to Contest 2 | // Difficulty:Easy 3 | // Given an array of integers nums. 4 | 5 | // A pair (i,j) is called good if nums[i] == nums[j] and i < j. 6 | 7 | // Return the number of good pairs. 8 | 9 | 10 | 11 | // Example 1: 12 | 13 | // Input: nums = [1,2,3,1,1,3] 14 | // Output: 4 15 | // Explanation: There are 4 good pairs (0,3), (0,4), (3,4), (2,5) 0-indexed. 16 | // Example 2: 17 | 18 | // Input: nums = [1,1,1,1] 19 | // Output: 6 20 | // Explanation: Each pair in the array are good. 21 | // Example 3: 22 | 23 | // Input: nums = [1,2,3] 24 | // Output: 0 25 | 26 | 27 | // Constraints: 28 | 29 | // 1 <= nums.length <= 100 30 | // 1 <= nums[i] <= 100 31 | 32 | pub struct Solution {} 33 | 34 | impl Solution { 35 | pub fn num_identical_pairs(nums: Vec) -> i32 { 36 | let mut result = 0; 37 | for i in 0..nums.len() { 38 | for j in i+1..nums.len() { 39 | if nums[i] == nums[j] { 40 | result += 1; 41 | } 42 | } 43 | } 44 | result 45 | } 46 | } 47 | 48 | #[cfg(test)] 49 | mod tests { 50 | use super::*; 51 | 52 | #[test] 53 | fn num_identical_pairs_test() { 54 | assert_eq!(Solution:: num_identical_pairs(vec![1, 2, 3]), 0); 55 | assert_eq!(Solution:: num_identical_pairs(vec![1, 1, 1, 1]), 6); 56 | assert_eq!(Solution:: num_identical_pairs(vec![1, 2, 3, 1, 1, 3]), 4); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /euler/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "euler" 3 | version = "0.1.0" 4 | authors = ["wsgggws "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | permutohedron = "0.2.4" 11 | chrono = "0.4" 12 | -------------------------------------------------------------------------------- /euler/README.md: -------------------------------------------------------------------------------- 1 | # Rust-euler 2 | Project euler solved by Rust 3 | 4 | ## Project euler 5 | - [https://projecteuler.net](https://projecteuler.net/archives) 6 | - rustc: 1.44 7 | 8 | ## Test 9 | - cargo test 10 | 11 | My Own Key: 12 | `1574526_vCbfhdfnB0B45vkObMkAdnU1MVDEU2fO` 13 | -------------------------------------------------------------------------------- /euler/src/p0001_multiples_of_3_and_5.rs: -------------------------------------------------------------------------------- 1 | // Multiples of 3 and 5 2 | // Problem 1 3 | // If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. 4 | 5 | // Find the sum of all the multiples of 3 or 5 below 1000. 6 | 7 | pub struct Solution {} 8 | 9 | impl Solution { 10 | pub fn multiples_of_3_and_5() -> u32 { 11 | (1..1000) 12 | .filter(|x| x%3 == 0 || x%5 == 0) 13 | .sum::() 14 | } 15 | } 16 | 17 | #[cfg(test)] 18 | mod tests { 19 | use super::*; 20 | 21 | #[test] 22 | fn multiples_of_3_and_5_test() { 23 | assert_eq!(Solution::multiples_of_3_and_5(), 233168); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /euler/src/p0002_even_fibonacci_numbers.rs: -------------------------------------------------------------------------------- 1 | // Even Fibonacci numbers 2 | // Problem 2 3 | // Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be: 4 | 5 | // 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... 6 | 7 | // By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms. 8 | 9 | pub struct Solution {} 10 | 11 | struct Fib { 12 | // pre, current 13 | fib: (u64, u64), 14 | } 15 | 16 | impl Fib { 17 | fn new() -> Fib { 18 | Fib { fib: (0, 1) } 19 | } 20 | } 21 | 22 | impl Iterator for Fib { 23 | type Item = u64; 24 | fn next(&mut self) -> Option { 25 | // pre, current = current, current + pre 26 | self.fib = (self.fib.1, self.fib.0 + self.fib.1); 27 | Some(self.fib.1) 28 | } 29 | } 30 | 31 | impl Solution { 32 | pub fn even_fibonacci_numbers(num: u64) -> u64 { 33 | Fib::new() 34 | .take_while(|&a| a<=num) 35 | .filter(|&a| a % 2 == 0) 36 | .sum::() 37 | } 38 | } 39 | 40 | #[cfg(test)] 41 | mod tests { 42 | use super::*; 43 | 44 | #[test] 45 | fn even_fibonacci_numbers_test() { 46 | // 1, 2, 3, 5 => 2 47 | assert_eq!(Solution::even_fibonacci_numbers(5), 2); 48 | // 1, 2, 3, 5, 8 => 2, 8 => 10 49 | assert_eq!(Solution::even_fibonacci_numbers(8), 10); 50 | assert_eq!(Solution::even_fibonacci_numbers(4000000u64), 4613732); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /euler/src/p0003_largest_prime_factor.rs: -------------------------------------------------------------------------------- 1 | // Largest prime factor 2 | // Problem 3 3 | // The prime factors of 13195 are 5, 7, 13 and 29. 4 | 5 | // What is the largest prime factor of the number 600851475143 ? 6 | 7 | pub struct Solution {} 8 | 9 | impl Solution { 10 | pub fn largest_prime_factor(num: u64) -> u64 { 11 | let mut candidates = 2u64..; 12 | let mut n = num; 13 | let mut result = 2u64; 14 | while n > 1u64 { 15 | let x = candidates.next().unwrap(); 16 | while n % x == 0 { 17 | n /= x; 18 | } 19 | result = x; 20 | } 21 | result 22 | } 23 | } 24 | 25 | #[cfg(test)] 26 | mod tests { 27 | use super::*; 28 | 29 | #[test] 30 | fn largest_prime_factor_test() { 31 | assert_eq!(Solution::largest_prime_factor(2), 2); 32 | assert_eq!(Solution::largest_prime_factor(13195), 29); 33 | assert_eq!(Solution::largest_prime_factor(600851475143), 6857); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /euler/src/p0004_largest_palindrome_product.rs: -------------------------------------------------------------------------------- 1 | // Largest palindrome product 2 | // Problem 4 3 | // A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99. 4 | 5 | // Find the largest palindrome made from the product of two 3-digit numbers. 6 | // 7 | 8 | pub struct Solution {} 9 | 10 | impl Solution { 11 | pub fn largest_palindrame_product() -> u64 { 12 | let mut result = 0u64; 13 | for a in (900u64..=999u64).rev(){ 14 | for b in (900u64..=999u64).rev() { 15 | if Solution::is_palindrae_product(a * b){ 16 | result = u64::max(result, a * b); 17 | } 18 | } 19 | } 20 | result 21 | } 22 | 23 | fn is_palindrae_product(num: u64) -> bool { 24 | num.to_string().chars().eq(num.to_string().chars().rev()) 25 | } 26 | } 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | 32 | #[test] 33 | fn largest_palindrame_product_test() { 34 | assert_eq!(Solution::largest_palindrame_product(), 906609); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /euler/src/p0006_sum_square_difference.rs: -------------------------------------------------------------------------------- 1 | // Sum square difference 2 | // Problem 6 3 | // The sum of the squares of the first ten natural numbers is, 4 | 5 | // 12+22+...+102=385 6 | // 12+22+...+102=385 7 | // The square of the sum of the first ten natural numbers is, 8 | 9 | // (1+2+...+10)2=552=3025 10 | // (1+2+...+10)2=552=3025 11 | // Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025−385=26403025−385=2640. 12 | 13 | // Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum. 14 | 15 | pub struct Solution {} 16 | 17 | impl Solution { 18 | pub fn sum_square_difference() -> u64 { 19 | (1..=100u64).sum::().pow(2) - (1..=100u64).map(|num| num * num).sum::() 20 | } 21 | 22 | } 23 | 24 | #[cfg(test)] 25 | mod tests { 26 | use super::*; 27 | 28 | #[test] 29 | fn sum_square_difference_test() { 30 | assert_eq!(Solution::sum_square_difference(), 25164150); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /euler/src/p0007_10001st_prime.rs: -------------------------------------------------------------------------------- 1 | // 10001st prime 2 | // Problem 7 3 | // By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13. 4 | 5 | // What is the 10 001st prime number? 6 | 7 | pub struct Solution {} 8 | 9 | impl Solution { 10 | pub fn get_st_prime(st_value: usize) -> u64 { 11 | // nth(0) returns the first value, nth(1) the second 12 | (2u64..) 13 | .filter(|&num| Solution::is_prime(num)) 14 | .nth(st_value-1usize) 15 | .unwrap() 16 | } 17 | 18 | fn is_prime(num: u64) -> bool { 19 | if num == 2 || num == 3 { 20 | return true; 21 | } 22 | !(2..=(num as f64).sqrt().ceil() as u64) 23 | .any(|value| num % value == 0) 24 | } 25 | } 26 | 27 | #[cfg(test)] 28 | mod tests { 29 | use super::*; 30 | 31 | #[test] 32 | fn get_st_prime_test() { 33 | assert_eq!(Solution::get_st_prime(1), 2); 34 | assert_eq!(Solution::get_st_prime(2), 3); 35 | assert_eq!(Solution::get_st_prime(6), 13); 36 | assert_eq!(Solution::get_st_prime(7), 17); 37 | assert_eq!(Solution::get_st_prime(8), 19); 38 | assert_eq!(Solution::get_st_prime(10001), 104743); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /euler/src/p0009_special_pythagorean_triplet.rs: -------------------------------------------------------------------------------- 1 | // Special Pythagorean triplet 2 | // Problem 9 3 | // A Pythagorean triplet is a set of three natural numbers, a < b < c, for which, 4 | 5 | // a2 + b2 = c2 6 | // For example, 32 + 42 = 9 + 16 = 25 = 52. 7 | 8 | // There exists exactly one Pythagorean triplet for which a + b + c = 1000. 9 | // Find the product abc. 10 | 11 | pub struct Solution {} 12 | 13 | impl Solution { 14 | pub fn special_pythagorean_triplet() -> i32 { 15 | for a in 2..1000 { 16 | for b in a+1..1000 { 17 | let c = 1000 - a - b; 18 | if a * a + b * b == c * c { 19 | return a * b * c; 20 | } 21 | } 22 | } 23 | 0 24 | } 25 | 26 | } 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | 32 | #[test] 33 | fn special_pythagorean_triplet_test() { 34 | assert_eq!(Solution::special_pythagorean_triplet(), 31875000); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /euler/src/p0010_summation_of_primes.rs: -------------------------------------------------------------------------------- 1 | // Summation of primes 2 | // Problem 10 3 | // The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. 4 | 5 | // Find the sum of all the primes below two million. 6 | 7 | pub struct Solution {} 8 | 9 | impl Solution { 10 | pub fn summation_of_primes(max_value: u64) -> u64 { 11 | (2u64..) 12 | .filter(|&num| Solution::is_prime(num)) 13 | .take_while(|&num| num < max_value) 14 | .sum::() 15 | } 16 | 17 | fn is_prime(num: u64) -> bool { 18 | if num == 2 || num == 3 { 19 | return true; 20 | } 21 | !(2..=(num as f64).sqrt().ceil() as u64) 22 | .any(|value| num % value == 0) 23 | } 24 | } 25 | 26 | #[cfg(test)] 27 | mod tests { 28 | use super::*; 29 | 30 | #[test] 31 | fn summation_of_primes_test() { 32 | assert_eq!(Solution::summation_of_primes(2), 0); 33 | assert_eq!(Solution::summation_of_primes(3), 2); 34 | assert_eq!(Solution::summation_of_primes(4), 5); 35 | assert_eq!(Solution::summation_of_primes(5), 5); 36 | assert_eq!(Solution::summation_of_primes(10), 17); 37 | assert_eq!(Solution::summation_of_primes(2000000), 142913828922); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /euler/src/p0019_counting_sundays.rs: -------------------------------------------------------------------------------- 1 | // Counting Sundays 2 | // Problem 19 3 | // You are given the following information, but you may prefer to do some research for yourself. 4 | 5 | // 1 Jan 1900 was a Monday. 6 | // Thirty days has September, 7 | // April, June and November. 8 | // All the rest have thirty-one, 9 | // Saving February alone, 10 | // Which has twenty-eight, rain or shine. 11 | // And on leap years, twenty-nine. 12 | // A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400. 13 | // How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)? 14 | 15 | extern crate chrono; 16 | 17 | use chrono::prelude::*; 18 | use chrono::Duration; 19 | 20 | pub struct Solution {} 21 | 22 | impl Solution { 23 | pub fn counting_sundays() -> u32 { 24 | let mut result = 0; 25 | let mut start = Utc.ymd(1901, 1, 1); 26 | while start <= Utc.ymd(2000, 12, 31) { 27 | if start.weekday() == Weekday::Sun && start.day() == 1 { 28 | result += 1; 29 | } 30 | start = start + Duration::days(1); 31 | } 32 | result 33 | } 34 | } 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::*; 39 | 40 | #[test] 41 | fn counting_sundays_test() { 42 | assert_eq!(Solution::counting_sundays(), 171); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /euler/src/p0028_number_spiral_diagonals.rs: -------------------------------------------------------------------------------- 1 | // Number spiral diagonals 2 | // Problem 28 3 | // Starting with the number 1 and moving to the right in a clockwise direction a 5 by 5 spiral is formed as follows: 4 | 5 | // 21 22 23 24 25 6 | // 20 7 8 9 10 7 | // 19 6 1 2 11 8 | // 18 5 4 3 12 9 | // 17 16 15 14 13 10 | 11 | // It can be verified that the sum of the numbers on the diagonals is 101. 12 | 13 | // What is the sum of the numbers on the diagonals in a 1001 by 1001 spiral formed in the same way? 14 | 15 | pub struct Solution {} 16 | 17 | 18 | impl Solution { 19 | pub fn number_spiral_diagonals(n: usize) -> u64 { 20 | if n % 2 == 0 { 21 | panic!("Plz set n to a odd!"); 22 | } 23 | let mut result = 1u64; 24 | for counts in (3..=n as u64).step_by(2) { 25 | result += ((counts-2)*(counts-2)+(counts-1)..) 26 | .step_by((counts-1) as usize) 27 | .take(4) 28 | .sum::(); 29 | } 30 | result 31 | } 32 | } 33 | 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use super::*; 38 | 39 | #[test] 40 | fn number_spiral_diagonals_test() { 41 | assert_eq!(Solution::number_spiral_diagonals(3), 25); 42 | assert_eq!(Solution::number_spiral_diagonals(5), 101); 43 | assert_eq!(Solution::number_spiral_diagonals(1001), 669171001); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /euler/src/p0030_digit_fifth_powers.rs: -------------------------------------------------------------------------------- 1 | // Digit fifth powers 2 | // Problem 30 3 | // Surprisingly there are only three numbers that can be written as the sum of fourth powers of their digits: 4 | 5 | // 1634 = 14 + 64 + 34 + 44 6 | // 8208 = 84 + 24 + 04 + 84 7 | // 9474 = 94 + 44 + 74 + 44 8 | // As 1 = 14 is not a sum it is not included. 9 | 10 | // The sum of these numbers is 1634 + 8208 + 9474 = 19316. 11 | 12 | // Find the sum of all the numbers that can be written as the sum of fifth powers of their digits. 13 | 14 | pub struct Solution {} 15 | 16 | impl Solution { 17 | pub fn digits_fifth_powers() -> u32 { 18 | 19 | // TODO 如何确定这个上限为200000? 20 | // (10..=200000).filter(|&num| num == Solution::get_sum_of_digits_fifth_powers(num)).count() as u32 21 | 22 | (10..=200000). 23 | filter(|&num| num == Solution::get_sum_of_digits_fifth_powers(num)) 24 | .sum::() 25 | } 26 | 27 | fn get_sum_of_digits_fifth_powers(num: u32) -> u32 { 28 | let mut number = num; 29 | let mut sums = 0; 30 | while number > 0 { 31 | sums += (number % 10).pow(5); 32 | number /= 10; 33 | } 34 | sums 35 | } 36 | } 37 | 38 | #[cfg(test)] 39 | mod tests { 40 | use super::*; 41 | 42 | #[test] 43 | fn digits_fifth_powers_test() { 44 | assert_eq!(Solution::digits_fifth_powers(), 443839); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /euler/src/p0034_digit_factorials.rs: -------------------------------------------------------------------------------- 1 | // Digit factorials 2 | // Problem 34 3 | // 145 is a curious number, as 1! + 4! + 5! = 1 + 24 + 120 = 145. 4 | 5 | // Find the sum of all numbers which are equal to the sum of the factorial of their digits. 6 | 7 | // Note: as 1! = 1 and 2! = 2 are not sums they are not included. 8 | 9 | pub struct Solution {} 10 | 11 | impl Solution { 12 | pub fn digit_factorials() -> u64 { 13 | (10..1000000) 14 | .filter(|&x| Solution::is_digit_factorial(x)) 15 | .sum() 16 | } 17 | 18 | fn is_digit_factorial(x: u64) -> bool { 19 | // 0~9的阶乘 20 | let factorials: Vec = vec![1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]; 21 | let mut num = x; 22 | let mut sum = 0; 23 | while num > 0 { 24 | sum += factorials[(num % 10) as usize]; 25 | num /= 10; 26 | } 27 | sum == x 28 | } 29 | } 30 | 31 | #[cfg(test)] 32 | mod tests { 33 | use super::*; 34 | 35 | #[test] 36 | fn digit_factorials_test() { 37 | assert_eq!(Solution::digit_factorials(), 40730); 38 | } 39 | 40 | #[test] 41 | fn is_digit_factorial_test() { 42 | assert_eq!(Solution::is_digit_factorial(144), false); 43 | assert_eq!(Solution::is_digit_factorial(145), true); 44 | assert_eq!(Solution::is_digit_factorial(40585), true); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /euler/src/p0036_double_base_palindromes.rs: -------------------------------------------------------------------------------- 1 | // Double-base palindromes 2 | // Problem 36 3 | // The decimal number, 585 = 10010010012 (binary), is palindromic in both bases. 4 | 5 | // Find the sum of all numbers, less than one million, which are palindromic in base 10 and base 2. 6 | 7 | // (Please note that the palindromic number, in either base, may not include leading zeros.) 8 | 9 | pub struct Solution {} 10 | 11 | impl Solution { 12 | pub fn double_base_palindromes(n: u64) -> u64 { 13 | (0..n) 14 | .filter(|&x| Solution::is_double_base_palindrome(x)) 15 | .sum() 16 | } 17 | 18 | fn is_double_base_palindrome(x: u64) -> bool { 19 | let base_2_x = format!("{:b}", x); 20 | x.to_string().chars().eq(x.to_string().chars().rev()) && base_2_x.chars().eq(base_2_x.chars().rev()) 21 | } 22 | } 23 | 24 | #[cfg(test)] 25 | mod tests { 26 | use super::*; 27 | 28 | #[test] 29 | fn double_base_palindromes_test() { 30 | assert_eq!(Solution::double_base_palindromes(1000000), 872187); 31 | } 32 | 33 | #[test] 34 | fn is_double_base_palindrome_test() { 35 | assert_eq!(Solution::is_double_base_palindrome(585), true); 36 | assert_eq!(Solution::is_double_base_palindrome(586), false); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /euler/src/p0041_pandigital_prime.rs: -------------------------------------------------------------------------------- 1 | // Pandigital prime 2 | // Problem 41 3 | // We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly once. For example, 2143 is a 4-digit pandigital and is also prime. 4 | 5 | // What is the largest n-digit pandigital prime that exists? 6 | 7 | pub struct Solution {} 8 | 9 | use std::char; 10 | impl Solution { 11 | pub fn pandigital_prime() -> u64 { 12 | // TODO 测试出来的,2.。10000000 超时 13 | (7000000..8000000) 14 | .filter(|&x| Solution::is_prime(x)) 15 | .filter(|&x| Solution::is_pandigital_prime(x)) 16 | .max_by_key(|x| x.to_string().len()) 17 | .unwrap() 18 | } 19 | 20 | fn is_pandigital_prime(prime: u64) -> bool { 21 | let mut chars1 = prime.to_string().chars().collect::>(); 22 | chars1.sort(); 23 | let chars2 = (1u32..=prime.to_string().len() as u32) 24 | .map(|x| char::from_digit(x, 10).unwrap()) 25 | .collect::>(); 26 | chars1 == chars2 27 | } 28 | 29 | fn is_prime(num: u64) -> bool { 30 | if num == 2 || num == 3 { 31 | return true; 32 | } 33 | !(2..=(num as f64).sqrt().ceil() as u64) 34 | .any(|value| num % value == 0) 35 | } 36 | } 37 | 38 | #[cfg(test)] 39 | mod tests { 40 | use super::*; 41 | 42 | #[test] 43 | fn pandigital_prime_test() { 44 | assert_eq!(Solution::pandigital_prime(), 7652413); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /euler/src/p0045_triangular_pentagonal_and_hexagonal.rs: -------------------------------------------------------------------------------- 1 | // Triangular, pentagonal, and hexagonal 2 | // Problem 45 3 | // Triangle, pentagonal, and hexagonal numbers are generated by the following formulae: 4 | 5 | // Triangle Tn=n(n+1)/2 1, 3, 6, 10, 15, ... 6 | // Pentagonal Pn=n(3n−1)/2 1, 5, 12, 22, 35, ... 7 | // Hexagonal Hn=n(2n−1) 1, 6, 15, 28, 45, ... 8 | // It can be verified that T285 = P165 = H143 = 40755. 9 | 10 | // Find the next triangle number that is also pentagonal and hexagonal. 11 | 12 | pub struct Solution {} 13 | 14 | use std::collections::HashSet; 15 | impl Solution { 16 | pub fn triangular_pentagonal_hexagonal() -> u128 { 17 | let pentagonal_numbers_set = (166..100000) 18 | .map(|x| x*(3*x-1)/2) 19 | .collect::>(); 20 | 21 | let hexagonal_nubmers_set = (144..100000) 22 | .map(|x| x*(2*x-1)) 23 | .collect::>(); 24 | 25 | for triangular_number in (286u128..100000).map(|x| x*(x+1)/2) { 26 | if pentagonal_numbers_set.contains(&triangular_number) && hexagonal_nubmers_set.contains(&triangular_number) { 27 | return triangular_number; 28 | } 29 | } 30 | 0 31 | } 32 | } 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use super::*; 37 | 38 | #[test] 39 | fn triangular_pentagonal_hexagonal_test() { 40 | assert_eq!(Solution::triangular_pentagonal_hexagonal(), 1533776805); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /euler/src/p0048_self_powers.rs: -------------------------------------------------------------------------------- 1 | // Self powers 2 | // Problem 48 3 | // The series, 11 + 22 + 33 + ... + 1010 = 10405071317. 4 | 5 | // Find the last ten digits of the series, 11 + 22 + 33 + ... + 10001000. 6 | 7 | pub struct Solution {} 8 | 9 | impl Solution { 10 | pub fn self_powers(n: u64) -> u64 { 11 | (1..=n) 12 | .map(|x| Solution::get_last_ten_digits(x)) 13 | .sum::() % 10_000_000_000 14 | } 15 | 16 | fn get_last_ten_digits(num: u64) -> u64 { 17 | (1..num) 18 | .fold(num, |result, _| result * num % 10_000_000_000) 19 | } 20 | } 21 | 22 | #[cfg(test)] 23 | mod tests { 24 | use super::*; 25 | 26 | #[test] 27 | fn self_powers_test() { 28 | assert_eq!(Solution::self_powers(10), 0405071317); 29 | assert_eq!(Solution::self_powers(100), 9027641920); 30 | assert_eq!(Solution::self_powers(1000), 9110846700); 31 | } 32 | 33 | #[test] 34 | fn get_last_ten_digits_test() { 35 | assert_eq!(Solution::get_last_ten_digits(1), 1); 36 | assert_eq!(Solution::get_last_ten_digits(2), 4); 37 | assert_eq!(Solution::get_last_ten_digits(3), 27); 38 | assert_eq!(Solution::get_last_ten_digits(10), 0); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /euler/src/p0067_maximum_path_sum_ii.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn maximum_path_sum_ii_test() { 3 | assert_eq!("see p0018_maximum_path_sum_i".to_string(), "see p0018_maximum_path_sum_i".to_owned()); 4 | } 5 | -------------------------------------------------------------------------------- /leetcode75/day10_509.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def fib(self, n: int) -> int: 3 | f1, f2 = 0, 1 4 | for _ in range(n): 5 | f1, f2 = f2, f1 + f2 6 | return f1 7 | 8 | 9 | if __name__ == "__main__": 10 | assert Solution().fib(0) == 0 11 | assert Solution().fib(1) == 1 12 | assert Solution().fib(2) == 1 13 | assert Solution().fib(3) == 2 14 | assert Solution().fib(4) == 3 15 | -------------------------------------------------------------------------------- /leetcode75/day10_70.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def climbStairs(self, n: int) -> int: 3 | f1, f2 = 1, 1 4 | for _ in range(n): 5 | f1, f2 = f2, f1 + f2 6 | return f1 7 | 8 | 9 | if __name__ == "__main__": 10 | assert Solution().climbStairs(0) == 1 11 | assert Solution().climbStairs(1) == 1 12 | assert Solution().climbStairs(2) == 2 13 | assert Solution().climbStairs(3) == 3 14 | assert Solution().climbStairs(4) == 5 15 | -------------------------------------------------------------------------------- /leetcode75/day11_62.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def uniquePaths(self, m: int, n: int) -> int: 3 | dp = [[0 for _ in range(n)] for _ in range(m)] 4 | for raw in range(m): 5 | for column in range(n): 6 | if raw == 0 or column == 0: 7 | dp[raw][column] = 1 8 | else: 9 | dp[raw][column] = dp[raw - 1][column] + dp[raw][column - 1] 10 | return dp[m - 1][n - 1] 11 | 12 | 13 | if __name__ == "__main__": 14 | assert Solution().uniquePaths(3, 1) == 1 15 | assert Solution().uniquePaths(1, 3) == 1 16 | assert Solution().uniquePaths(3, 2) == 3 17 | assert Solution().uniquePaths(3, 7) == 28 18 | -------------------------------------------------------------------------------- /leetcode75/day11_746.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def minCostClimbingStairs(self, cost: List[int]) -> int: 6 | steps = len(cost) 7 | dp = [0 for _ in range(steps + 1)] 8 | dp[0] = 0 9 | dp[1] = 0 10 | for i in range(2, steps + 1): 11 | dp[i] = min(dp[i - 2] + cost[i - 2], dp[i - 1] + cost[i - 1]) 12 | return dp[steps] 13 | 14 | 15 | if __name__ == "__main__": 16 | assert Solution().minCostClimbingStairs([10, 15, 20]) == 15 17 | assert Solution().minCostClimbingStairs([1, 100, 1, 1, 1, 100, 1, 1, 100, 1]) == 6 18 | -------------------------------------------------------------------------------- /leetcode75/day12_424.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | 3 | 4 | class Solution: 5 | def characterReplacement(self, s: str, k: int) -> int: 6 | left, right = 0, min(len(s), k + 1) 7 | counter = Counter(s[: k + 1]) 8 | while right < len(s): 9 | counter[s[right]] += 1 10 | max_count = counter.most_common(1)[0][1] 11 | if right - left + 1 - max_count > k: 12 | counter[s[left]] -= 1 13 | left += 1 14 | right += 1 15 | return right - left 16 | 17 | 18 | if __name__ == "__main__": 19 | assert Solution().characterReplacement(s="ABAB", k=2) == 4 20 | assert Solution().characterReplacement(s="AABABBA", k=1) == 4 21 | assert Solution().characterReplacement(s="A", k=0) == 1 22 | assert Solution().characterReplacement(s="A", k=1) == 1 23 | -------------------------------------------------------------------------------- /leetcode75/day12_438.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | from typing import List 3 | 4 | 5 | class Solution: 6 | def findAnagrams(self, s: str, p: str) -> List[int]: 7 | slen, plen = len(s), len(p) 8 | ans = [] 9 | p_counter = Counter(p) 10 | for i in range(slen - plen + 1): 11 | if p_counter == Counter(s[i : i + plen]): 12 | ans.append(i) 13 | return ans 14 | 15 | 16 | if __name__ == "__main__": 17 | assert Solution().findAnagrams(s="cbaebabacd", p="abc") == [0, 6] 18 | assert Solution().findAnagrams(s="abab", p="ab") == [0, 1, 2] 19 | assert Solution().findAnagrams(s="ab", p="abab") == [] 20 | -------------------------------------------------------------------------------- /leetcode75/day13_1.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def twoSum(self, nums: List[int], target: int) -> List[int]: 6 | # O(n*n) 7 | # for i in range(len(nums)): 8 | # for j in range(i + 1, len(nums)): 9 | # if nums[i] + nums[j] == target: 10 | # return [i, j] 11 | 12 | # O(n) 13 | nums: List[tuple[int, int]] = sorted([(num, index) for index, num in enumerate(nums)]) 14 | left, right = 0, len(nums) - 1 15 | while left < right: 16 | num = nums[left][0] + nums[right][0] 17 | if target == num: 18 | break 19 | elif target > num: 20 | left += 1 21 | else: 22 | right -= 1 23 | return [nums[left][1], nums[right][1]] 24 | 25 | 26 | if __name__ == "__main__": 27 | assert Solution().twoSum(nums=[2, 7, 11, 15], target=9) == [0, 1] 28 | assert Solution().twoSum(nums=[3, 2, 4], target=6) == [1, 2] 29 | assert Solution().twoSum(nums=[3, 3], target=6) == [0, 1] 30 | -------------------------------------------------------------------------------- /leetcode75/day13_299.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def getHint(self, secret: str, guess: str) -> str: 6 | bulls, cows = 0, 0 7 | # bulls 8 | eq_indexes: List[int] = [] 9 | for i in range(len(secret)): 10 | if secret[i] == guess[i]: 11 | bulls += 1 12 | eq_indexes.append(i) 13 | # cows 14 | secret: List[str] = sorted([char for i, char in enumerate(secret) if i not in eq_indexes]) 15 | guess: List[str] = sorted([char for i, char in enumerate(guess) if i not in eq_indexes]) 16 | i, j = 0, 0 17 | while i < len(secret) and j < len(guess): 18 | if secret[i] == guess[j]: 19 | cows += 1 20 | i += 1 21 | j += 1 22 | elif secret[i] < guess[j]: 23 | i += 1 24 | else: 25 | j += 1 26 | return f"{bulls}A{cows}B" 27 | 28 | 29 | if __name__ == "__main__": 30 | assert Solution().getHint(secret="1807", guess="7810") == "1A3B" 31 | assert Solution().getHint(secret="1123", guess="0111") == "1A1B" 32 | -------------------------------------------------------------------------------- /leetcode75/day14_844.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def backspaceCompare(self, s: str, t: str) -> bool: 6 | return self.handler(s) == self.handler(t) 7 | 8 | def handler(self, text: str) -> str: 9 | stack: List[str] = [] 10 | left = 0 11 | while left < len(text): 12 | if text[left] == "#": 13 | if stack: 14 | stack.pop() 15 | else: 16 | stack.append(text[left]) 17 | left += 1 18 | return "".join(stack) 19 | 20 | 21 | if __name__ == "__main__": 22 | assert Solution().backspaceCompare(s="ab#c", t="ad#c") is True 23 | assert Solution().backspaceCompare(s="ab##", t="c#d#") is True 24 | assert Solution().backspaceCompare(s="a#c", t="b") is False 25 | assert Solution().backspaceCompare(s="a##c", t="b") is False 26 | assert Solution().backspaceCompare(s="##a#c", t="c") is True 27 | assert Solution().backspaceCompare(s="bxj##tw", t="bxo#j##tw") is True 28 | -------------------------------------------------------------------------------- /leetcode75/day15_1046.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | from typing import List 3 | 4 | 5 | class Solution: 6 | def lastStoneWeight(self, stones: List[int]) -> int: 7 | stones = [-stone for stone in stones] 8 | heapq.heapify(stones) 9 | while len(stones) > 1: 10 | value = heapq.heappop(stones) - heapq.heappop(stones) 11 | if value != 0: 12 | heapq.heappush(stones, value) 13 | return -stones[0] if stones else 0 14 | 15 | 16 | if __name__ == "__main__": 17 | assert Solution().lastStoneWeight([2, 8, 8, 7, 4, 1, 8, 1]) == 1 18 | -------------------------------------------------------------------------------- /leetcode75/day15_692.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | from typing import List 3 | 4 | 5 | class Solution: 6 | def topKFrequent(self, words: List[str], k: int) -> List[str]: 7 | return [_[0] for _ in Counter(sorted(words)).most_common(k)] 8 | 9 | 10 | if __name__ == "__main__": 11 | assert Solution().topKFrequent(words=["i", "a", "a", "love", "leetcode", "i", "love", "coding"], k=2) == [ 12 | "a", 13 | "i", 14 | ] 15 | assert Solution().topKFrequent(["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k=4) == [ 16 | "the", 17 | "is", 18 | "sunny", 19 | "day", 20 | ] 21 | -------------------------------------------------------------------------------- /leetcode75/day16_1706.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def findBall(self, grid: List[List[int]]) -> List[int]: 6 | rows, cols = len(grid), len(grid[0]) 7 | ans = [-1 for _ in range(cols)] 8 | for col in range(cols): 9 | ans[col] = -1 10 | cur_col = col 11 | for row in range(rows): 12 | if grid[row][cur_col] == 1: 13 | if cur_col + 1 < cols and grid[row][cur_col + 1] == 1: 14 | cur_col += 1 15 | else: 16 | break 17 | else: 18 | if cur_col - 1 >= 0 and grid[row][cur_col - 1] == -1: 19 | cur_col -= 1 20 | else: 21 | break 22 | else: 23 | ans[col] = cur_col 24 | return ans 25 | 26 | 27 | if __name__ == "__main__": 28 | assert Solution().findBall( 29 | grid=[[1, 1, 1, -1, -1], [1, 1, 1, -1, -1], [-1, -1, -1, 1, 1], [1, 1, 1, 1, -1], [-1, -1, -1, -1, -1]] 30 | ) == [1, -1, -1, -1, -1] 31 | assert Solution().findBall(grid=[[-1]]) == [-1] 32 | assert Solution().findBall( 33 | grid=[[1, 1, 1, 1, 1, 1], [-1, -1, -1, -1, -1, -1], [1, 1, 1, 1, 1, 1], [-1, -1, -1, -1, -1, -1]] 34 | ) == [0, 1, 2, 3, 4, -1] 35 | -------------------------------------------------------------------------------- /leetcode75/day16_202.py: -------------------------------------------------------------------------------- 1 | from typing import Set 2 | 3 | 4 | class Solution: 5 | def isHappy(self, n: int) -> bool: 6 | nums: Set[int] = set([n]) 7 | while n != 1: 8 | n = sum(int(char) * int(char) for char in str(n)) 9 | if n in nums: 10 | return False 11 | else: 12 | nums.add(n) 13 | return True 14 | 15 | 16 | if __name__ == "__main__": 17 | assert Solution().isHappy(19) is True 18 | assert Solution().isHappy(1) is True 19 | assert Solution().isHappy(2) is False 20 | -------------------------------------------------------------------------------- /leetcode75/day16_54.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def spiralOrder(self, matrix: List[List[int]]) -> List[int]: 6 | rows, cols = len(matrix), len(matrix[0]) 7 | dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)] 8 | visit = [[False for _ in range(cols)] for _ in range(rows)] 9 | cur_i, cur_j = 0, 0 10 | steps, loops = 0, 0 11 | ans = [] 12 | while steps < rows * cols: 13 | while 0 <= cur_i < rows and 0 <= cur_j < cols and visit[cur_i][cur_j] is False: 14 | ans.append(matrix[cur_i][cur_j]) 15 | visit[cur_i][cur_j] = True 16 | steps += 1 17 | cur_i = cur_i + dirs[loops % 4][0] 18 | cur_j = cur_j + dirs[loops % 4][1] 19 | cur_i = cur_i - dirs[loops % 4][0] 20 | cur_j = cur_j - dirs[loops % 4][1] 21 | loops += 1 22 | cur_i = cur_i + dirs[loops % 4][0] 23 | cur_j = cur_j + dirs[loops % 4][1] 24 | return ans 25 | 26 | 27 | if __name__ == "__main__": 28 | assert Solution().spiralOrder(matrix=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]) == [1, 2, 3, 6, 9, 8, 7, 4, 5] 29 | assert Solution().spiralOrder(matrix=[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) == [ 30 | 1, 31 | 2, 32 | 3, 33 | 4, 34 | 8, 35 | 12, 36 | 11, 37 | 10, 38 | 9, 39 | 5, 40 | 6, 41 | 7, 42 | ] 43 | -------------------------------------------------------------------------------- /leetcode75/day17_14.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def longestCommonPrefix(self, strs: List[str]) -> str: 6 | index = 0 7 | while index < min(len(str) for str in strs): 8 | if len(set(str[: index + 1] for str in strs)) != 1: 9 | break 10 | index += 1 11 | return strs[0][:index] 12 | 13 | 14 | if __name__ == "__main__": 15 | assert Solution().longestCommonPrefix(strs=["flower", "flow", "flight"]) == "fl" 16 | assert Solution().longestCommonPrefix(strs=["flower", "flow", ""]) == "" 17 | assert Solution().longestCommonPrefix(strs=["dog", "racecar", "car"]) == "" 18 | -------------------------------------------------------------------------------- /leetcode75/day17_43.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def multiply(self, num1: str, num2: str) -> str: 3 | list1, list2 = list(int(num) for num in num1), list(int(num) for num in num2) 4 | ans = 0 5 | for index1, n1 in enumerate(list1[::-1]): 6 | for index2, n2 in enumerate(list2[::-1]): 7 | ans += 10**index1 * n1 * 10**index2 * n2 8 | return str(ans) 9 | 10 | 11 | if __name__ == "__main__": 12 | assert Solution().multiply("2", "3") == "6" 13 | assert Solution().multiply("0", "3") == "0" 14 | assert Solution().multiply("123", "456") == "56088" 15 | -------------------------------------------------------------------------------- /leetcode75/day18_19.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import ListNode, create_link, trave_link 4 | 5 | 6 | class Solution: 7 | def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]: 8 | fast, slow, pre = head, head, head 9 | while n > 0 and fast: 10 | fast = fast.next 11 | n -= 1 12 | while fast and slow: 13 | fast = fast.next 14 | pre = slow 15 | slow = slow.next 16 | if pre and slow and pre == slow: 17 | head = slow.next 18 | slow.next = None 19 | if pre and slow: 20 | pre.next = slow.next 21 | slow.next = None 22 | return head 23 | 24 | 25 | if __name__ == "__main__": 26 | head = create_link([1, 2, 3, 4, 5]) 27 | assert trave_link(head) == [1, 2, 3, 4, 5] 28 | head = Solution().removeNthFromEnd(head, 2) 29 | assert trave_link(head) == [1, 2, 3, 5] 30 | 31 | head = create_link([1]) 32 | head = Solution().removeNthFromEnd(head, 1) 33 | assert trave_link(head) == [] 34 | 35 | head = create_link([1, 2]) 36 | head = Solution().removeNthFromEnd(head, 1) 37 | assert trave_link(head) == [1] 38 | 39 | head = create_link([1, 2]) 40 | head = Solution().removeNthFromEnd(head, 2) 41 | assert trave_link(head) == [2] 42 | -------------------------------------------------------------------------------- /leetcode75/day18_234.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import ListNode, create_link, trave_link 4 | 5 | 6 | class Solution: 7 | def isPalindrome(self, head: Optional[ListNode]) -> bool: 8 | fast, slow = head, head 9 | while fast: 10 | fast = fast.next 11 | if fast: 12 | fast = fast.next 13 | slow = slow.next 14 | dump = ListNode(-1) 15 | cur = slow 16 | while cur: 17 | next_node = cur.next 18 | cur.next = dump.next 19 | dump.next = cur 20 | cur = next_node 21 | head2 = dump.next 22 | head1 = head 23 | while head1 and head2: 24 | if head1.val != head2.val: 25 | return False 26 | head1 = head1.next 27 | head2 = head2.next 28 | return True 29 | 30 | 31 | if __name__ == "__main__": 32 | head = create_link([1, 2, 3, 4, 5]) 33 | assert trave_link(head) == [1, 2, 3, 4, 5] 34 | assert Solution().isPalindrome(head) is False 35 | 36 | head = create_link([1, 2, 2, 1]) 37 | assert Solution().isPalindrome(head) is True 38 | 39 | head = create_link([1, 2, 3, 2, 1]) 40 | assert Solution().isPalindrome(head) is True 41 | 42 | head = create_link([1, 2]) 43 | assert Solution().isPalindrome(head) is False 44 | 45 | head = create_link([1]) 46 | assert Solution().isPalindrome(head) is True 47 | -------------------------------------------------------------------------------- /leetcode75/day19_328.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import ListNode, create_link, trave_link 4 | 5 | 6 | class Solution: 7 | def oddEvenList(self, head: Optional[ListNode]) -> Optional[ListNode]: 8 | if head is None: 9 | return None 10 | first, second, head2 = head, head.next, head.next 11 | while first and first.next and second and second.next: 12 | first.next = first.next.next 13 | second.next = second.next.next 14 | first = first.next 15 | second = second.next 16 | first.next = head2 17 | return head 18 | 19 | 20 | if __name__ == "__main__": 21 | head = create_link([1, 2, 3, 4, 5]) 22 | assert trave_link(head) == [1, 2, 3, 4, 5] 23 | head = Solution().oddEvenList(head) 24 | assert trave_link(head) == [1, 3, 5, 2, 4] 25 | 26 | head = create_link([1, 2, 3, 4, 5, 6]) 27 | head = Solution().oddEvenList(head) 28 | assert trave_link(head) == [1, 3, 5, 2, 4, 6] 29 | 30 | head = create_link([]) 31 | head = Solution().oddEvenList(head) 32 | assert trave_link(head) == [] 33 | 34 | head = create_link([1]) 35 | head = Solution().oddEvenList(head) 36 | assert trave_link(head) == [1] 37 | 38 | head = create_link([1, 2]) 39 | head = Solution().oddEvenList(head) 40 | assert trave_link(head) == [1, 2] 41 | 42 | head = create_link([1, 2, 3]) 43 | head = Solution().oddEvenList(head) 44 | assert trave_link(head) == [1, 3, 2] 45 | -------------------------------------------------------------------------------- /leetcode75/day1_1480.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def runningSum(self, nums: List[int]) -> List[int]: 6 | result = [] 7 | sum = 0 8 | for num in nums: 9 | sum += num 10 | result.append(sum) 11 | return result 12 | 13 | 14 | if __name__ == "__main__": 15 | s = Solution() 16 | assert s.runningSum([1, 2, 3, 4]) == [1, 3, 6, 10] 17 | assert s.runningSum([1, 1, 1, 1, 1]) == [1, 2, 3, 4, 5] 18 | assert s.runningSum([3, 1, 2, 10, 1]) == [3, 4, 6, 16, 17] 19 | -------------------------------------------------------------------------------- /leetcode75/day1_724.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def pivotIndex(self, nums: List[int]) -> int: 6 | total = sum(nums) 7 | left = 0 8 | for index, num in enumerate(nums): 9 | if left * 2 + nums[index] == total: 10 | return index 11 | left += num 12 | return -1 13 | 14 | 15 | if __name__ == "__main__": 16 | s = Solution() 17 | assert s.pivotIndex([1, 7, 3, 6, 5, 6]) == 3 18 | assert s.pivotIndex([1, 2, 3]) == -1 19 | assert s.pivotIndex([2, 1, -1]) == 0 20 | -------------------------------------------------------------------------------- /leetcode75/day20_2131.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | from typing import List 3 | 4 | 5 | class Solution: 6 | def longestPalindrome(self, words: List[str]) -> int: 7 | """ 8 | 1. “两字符相同”的 9 | a. 有奇数的,取偶数对, 最后加 1 对 10 | b. 无奇数对,取偶数对 11 | 2. “两字符不同“的取 min(count(AB), count(BA)) 12 | """ 13 | counter1 = Counter([word for word in words if word[0] == word[1]]) 14 | counter2 = Counter([word for word in words if word[0] != word[1]]) 15 | ans = 0 16 | # 不相等字符的单词 17 | for word in counter2.keys(): 18 | ans += 2 * min(counter2[word], counter2[word[::-1]]) 19 | # 相等字符的单词 20 | odd = 0 21 | for value in counter1.values(): 22 | if value % 2 == 0: 23 | ans += 2 * value 24 | else: 25 | odd = 1 26 | ans += value // 2 * 2 * 2 27 | ans += 2 * odd 28 | return ans 29 | 30 | 31 | if __name__ == "__main__": 32 | assert Solution().longestPalindrome(words=["lc", "cl", "gg"]) == 6 33 | assert Solution().longestPalindrome(words=["ab", "ty", "yt", "lc", "cl", "ab"]) == 8 34 | assert Solution().longestPalindrome(words=["cc", "ll", "xx"]) == 2 35 | assert Solution().longestPalindrome(words=["cx", "lc", "cx"]) == 0 36 | assert ( 37 | Solution().longestPalindrome( 38 | words=["dd", "aa", "bb", "dd", "aa", "dd", "bb", "dd", "aa", "cc", "bb", "cc", "dd", "cc"] 39 | ) 40 | == 22 41 | ) 42 | -------------------------------------------------------------------------------- /leetcode75/day21_110.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import TreeNode, create_binary_tree 4 | 5 | 6 | class Solution: 7 | def isBalanced(self, root: Optional[TreeNode]) -> bool: 8 | if root is None: 9 | return True 10 | left_height = self.height(root.left) 11 | right_height = self.height(root.right) 12 | return abs(left_height - right_height) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right) 13 | 14 | def height(self, root: Optional[TreeNode]) -> int: 15 | if root is None: 16 | return 0 17 | return max(self.height(root.left), self.height(root.right)) + 1 18 | 19 | 20 | if __name__ == "__main__": 21 | root = create_binary_tree([3, 9, 20, None, None, 15, 7], index=0) 22 | assert Solution().isBalanced(root) is True 23 | 24 | root = create_binary_tree([1, 2, 2, 3, 3, None, None, 4, 4, None, None, None, None], index=0) 25 | assert Solution().isBalanced(root) is False 26 | 27 | root = create_binary_tree([], index=0) 28 | assert Solution().isBalanced(root) is True 29 | -------------------------------------------------------------------------------- /leetcode75/day21_226.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import TreeNode, bfs_binary_tree, create_binary_tree 4 | 5 | 6 | class Solution: 7 | def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: 8 | if root is None or (root.left is None and root.right is None): 9 | return root 10 | root.left, root.right = root.right, root.left 11 | self.invertTree(root.left) 12 | self.invertTree(root.right) 13 | return root 14 | 15 | 16 | if __name__ == "__main__": 17 | root = create_binary_tree([4, 2, 7, 1, 3, 6, 9], index=0) 18 | assert bfs_binary_tree(Solution().invertTree(root)) == [4, 7, 2, 9, 6, 3, 1] 19 | 20 | root = create_binary_tree([2, 1, 3], index=0) 21 | assert bfs_binary_tree(Solution().invertTree(root)) == [2, 3, 1] 22 | 23 | root = create_binary_tree([], index=0) 24 | assert bfs_binary_tree(Solution().invertTree(root)) == [] 25 | -------------------------------------------------------------------------------- /leetcode75/day22_437.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import TreeNode, create_binary_tree 4 | 5 | 6 | class Solution: 7 | ans = 0 8 | 9 | def pathSum(self, root: Optional[TreeNode], targetSum: int) -> int: 10 | self.ans = 0 11 | self._pathSum(root, targetSum) 12 | return self.ans 13 | 14 | def _pathSum(self, root: Optional[TreeNode], targetSum: int): 15 | if root is None: 16 | return 17 | self.dfs(root, targetSum) 18 | self._pathSum(root.left, targetSum) 19 | self._pathSum(root.right, targetSum) 20 | 21 | def dfs(self, root: Optional[TreeNode], targetSum: int): 22 | if root is None: 23 | return 24 | if root.val == targetSum: 25 | self.ans += 1 26 | self.dfs(root.left, targetSum - root.val) 27 | self.dfs(root.right, targetSum - root.val) 28 | 29 | 30 | if __name__ == "__main__": 31 | s = Solution() 32 | root = create_binary_tree([10, 5, -3, 3, 2, None, 11, 3, -2, None, 1], index=0) 33 | assert s.pathSum(root, 8) == 3 34 | 35 | root = create_binary_tree([5, 4, 8, 11, None, 13, 4, 7, 2, None, None, 5, 1], index=0) 36 | assert s.pathSum(root, 22) == 3 37 | -------------------------------------------------------------------------------- /leetcode75/day22_543.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import TreeNode, create_binary_tree 4 | 5 | 6 | class Solution: 7 | def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int: 8 | if root is None: 9 | return 0 10 | return max( 11 | self.height(root.left) + self.height(root.right), 12 | self.diameterOfBinaryTree(root.left), 13 | self.diameterOfBinaryTree(root.right), 14 | ) 15 | 16 | def height(self, root: Optional[TreeNode]) -> int: 17 | if root is None: 18 | return 0 19 | return max(self.height(root.left), self.height(root.right)) + 1 20 | 21 | 22 | if __name__ == "__main__": 23 | root = create_binary_tree([1, 2, 3, 4, 5, None, None], index=0) 24 | assert Solution().diameterOfBinaryTree(root) == 3 25 | -------------------------------------------------------------------------------- /leetcode75/day23_74.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def searchMatrix(self, matrix: List[List[int]], target: int) -> bool: 6 | if len(matrix) == 0 or len(matrix[0]) == 0: 7 | raise KeyError 8 | rows, cols = len(matrix), len(matrix[0]) 9 | row, col = 0, cols - 1 10 | while row < rows and col >= 0: 11 | if matrix[row][col] == target: 12 | return True 13 | elif matrix[row][col] > target: 14 | col -= 1 15 | else: 16 | row += 1 17 | return False 18 | 19 | 20 | if __name__ == "__main__": 21 | assert ( 22 | Solution().searchMatrix( 23 | matrix=[ 24 | [1, 3, 5, 7], 25 | [10, 11, 16, 20], 26 | [23, 30, 34, 60], 27 | ], 28 | target=3, 29 | ) 30 | is True 31 | ) 32 | assert ( 33 | Solution().searchMatrix( 34 | matrix=[ 35 | [1, 3, 5, 7], 36 | [10, 11, 16, 20], 37 | [23, 30, 34, 60], 38 | ], 39 | target=13, 40 | ) 41 | is False 42 | ) 43 | -------------------------------------------------------------------------------- /leetcode75/day24_108.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional 2 | 3 | from helper import TreeNode, bfs_binary_tree 4 | 5 | 6 | class Solution: 7 | def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]: 8 | if len(nums) == 0: 9 | return None 10 | if len(nums) == 1: 11 | return TreeNode(nums[0]) 12 | mid = len(nums) // 2 13 | root = TreeNode(nums[mid]) 14 | root.left = self.sortedArrayToBST(nums[:mid]) 15 | root.right = self.sortedArrayToBST(nums[mid + 1 :]) 16 | return root 17 | 18 | 19 | if __name__ == "__main__": 20 | root = Solution().sortedArrayToBST(nums=[-10, -3, 0, 5, 9]) 21 | assert bfs_binary_tree(root) == [0, -3, 9, -10, None, 5, None] 22 | 23 | root = Solution().sortedArrayToBST(nums=[1, 3]) 24 | assert bfs_binary_tree(root) == [3, 1, None] 25 | 26 | root = Solution().sortedArrayToBST(nums=[1]) 27 | assert bfs_binary_tree(root) == [1] 28 | 29 | root = Solution().sortedArrayToBST(nums=[]) 30 | assert bfs_binary_tree(root) == [] 31 | -------------------------------------------------------------------------------- /leetcode75/day24_173.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional 2 | 3 | from helper import TreeNode, create_binary_tree 4 | 5 | 6 | class BSTIterator: 7 | def __init__(self, root: Optional[TreeNode]): 8 | self.cur: Optional[TreeNode] = root 9 | self.stack: List[TreeNode] = [] 10 | 11 | def next(self) -> int: 12 | while self.cur: 13 | self.stack.append(self.cur) 14 | self.cur = self.cur.left 15 | self.cur = self.stack.pop() 16 | val = self.cur.val 17 | self.cur = self.cur.right 18 | return val 19 | 20 | def hasNext(self) -> bool: 21 | return self.cur is not None or len(self.stack) > 0 22 | 23 | 24 | if __name__ == "__main__": 25 | root = create_binary_tree([7, 3, 15, None, None, 9, 20], index=0) 26 | bSTIterator = BSTIterator(root) 27 | assert bSTIterator.next() == 3 28 | assert bSTIterator.next() == 7 29 | assert bSTIterator.hasNext() is True 30 | assert bSTIterator.next() == 9 31 | assert bSTIterator.hasNext() is True 32 | assert bSTIterator.next() == 15 33 | assert bSTIterator.hasNext() is True 34 | assert bSTIterator.next() == 20 35 | assert bSTIterator.hasNext() is False 36 | -------------------------------------------------------------------------------- /leetcode75/day24_230.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import TreeNode, create_binary_tree 4 | 5 | 6 | class Solution: 7 | def kthSmallest(self, root: Optional[TreeNode], k: int) -> int: 8 | self.ans = -1 9 | self.k = k 10 | self._inorder(root) 11 | if self.ans == -1: 12 | raise KeyError 13 | return self.ans 14 | 15 | def _inorder(self, root: Optional[TreeNode]) -> None: 16 | # 中序 17 | if root is None: 18 | return 19 | self._inorder(root.left) 20 | self.k -= 1 21 | if self.k == 0: 22 | self.ans = root.val 23 | return 24 | self._inorder(root.right) 25 | 26 | 27 | if __name__ == "__main__": 28 | root = create_binary_tree([3, 1, 4, None, 2], index=0) 29 | assert Solution().kthSmallest(root, k=1) == 1 30 | assert Solution().kthSmallest(root, k=2) == 2 31 | assert Solution().kthSmallest(root, k=3) == 3 32 | assert Solution().kthSmallest(root, k=4) == 4 33 | 34 | root = create_binary_tree([5, 3, 6, 2, 4, None, None, 1, None], index=0) 35 | assert Solution().kthSmallest(root, k=1) == 1 36 | assert Solution().kthSmallest(root, k=2) == 2 37 | assert Solution().kthSmallest(root, k=3) == 3 38 | assert Solution().kthSmallest(root, k=4) == 4 39 | assert Solution().kthSmallest(root, k=5) == 5 40 | assert Solution().kthSmallest(root, k=6) == 6 41 | -------------------------------------------------------------------------------- /leetcode75/day27_198.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | # class Solution: 4 | # def rob(self, nums: List[int]) -> int: 5 | # """ 6 | # 2 7 9 3 1 7 | 8 | # 2 9 | # 7 10 | # max(2+9,7) 11 | # 不取9,取9 12 | # """ 13 | # # dp[i]: 0-i 所能获得的最大金钱 14 | # # dp[i] = max(dp[i-2]+nums[i], dp[i-1]) 15 | # if len(nums) <= 1: 16 | # return nums[0] 17 | # dp = [0 for _ in nums] 18 | # dp[0] = nums[0] 19 | # dp[1] = max(nums[0], nums[1]) 20 | # for i in range(2, len(nums)): 21 | # dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]) 22 | # return dp[len(nums) - 1] 23 | 24 | 25 | class Solution: 26 | def rob(self, nums: List[int]) -> int: 27 | if len(nums) <= 1: 28 | return nums[0] 29 | # 状态压缩 30 | dp_0 = nums[0] 31 | dp_1 = max(nums[0], nums[1]) 32 | for i in range(2, len(nums)): 33 | dp_0, dp_1 = dp_1, max(dp_0 + nums[i], dp_1) 34 | return dp_1 35 | 36 | 37 | if __name__ == "__main__": 38 | assert Solution().rob([1]) == 1 39 | assert Solution().rob([1, 2, 3, 1]) == 4 40 | assert Solution().rob([2, 7, 9, 3, 1]) == 12 41 | -------------------------------------------------------------------------------- /leetcode75/day27_322.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def coinChange(self, coins: List[int], amount: int) -> int: 6 | """ 7 | dp[i]: 表示换成i金额所需要的最少硬币个数,则 8 | dp[i] = min(dp[i-coin] + 1 for coin in coins) 9 | """ 10 | dp = [0 for _ in range(amount + 1)] 11 | dp[0] = 0 12 | for i in range(1, amount + 1): 13 | mins = amount + 1 14 | for coin in coins: 15 | if i >= coin: 16 | if dp[i - coin] + 1 < mins: 17 | mins = dp[i - coin] + 1 18 | dp[i] = mins 19 | if dp[amount] == amount + 1: 20 | return -1 21 | return dp[amount] 22 | 23 | 24 | if __name__ == "__main__": 25 | assert Solution().coinChange(coins=[1, 2, 5], amount=11) == 3 26 | assert Solution().coinChange(coins=[2], amount=3) == -1 27 | assert Solution().coinChange(coins=[1], amount=0) == 0 28 | assert Solution().coinChange(coins=[2, 5, 10, 1], amount=27) == 4 29 | assert Solution().coinChange(coins=[2], amount=1) == -1 30 | -------------------------------------------------------------------------------- /leetcode75/day29_16.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def threeSumClosest(self, nums: List[int], target: int) -> int: 6 | """ 7 | 1. i,j,k 暴力破解 8 | 2. 双指针 9 | -4, -1, 1, 2 10 | i s-> <-e 11 | =, return 12 | >, s+1 13 | <, e-1 14 | ><需要考虑记录最接近的值(N*N) 15 | """ 16 | lens = len(nums) 17 | if lens < 3: 18 | raise KeyError 19 | nums.sort() 20 | ans = 0 21 | diff_mins = 100000 22 | for i in range(lens - 2): 23 | start = i + 1 24 | end = lens - 1 25 | while start < end: 26 | three_sum = nums[i] + nums[start] + nums[end] 27 | if three_sum == target: 28 | return target 29 | else: 30 | if three_sum < target: 31 | start += 1 32 | else: 33 | end -= 1 34 | diff = abs(three_sum - target) 35 | if diff < diff_mins: 36 | diff_mins = diff 37 | ans = three_sum 38 | return ans 39 | 40 | 41 | if __name__ == "__main__": 42 | assert Solution().threeSumClosest(nums=[-1, 2, 1, -4], target=1) == 2 43 | assert Solution().threeSumClosest(nums=[0, 0, 0], target=1) == 0 44 | -------------------------------------------------------------------------------- /leetcode75/day29_3.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | 3 | 4 | class Solution: 5 | def lengthOfLongestSubstring(self, s: str) -> int: 6 | """滑动窗口 7 | s s s s s s 8 | pwwkew pwwkew pwwkew pwwkew pwwkew pwwkew 9 | e e e e e e 10 | 11 | max 1 2 1 2 3 3 12 | => 3 13 | """ 14 | maxs = start = end = 0 15 | counter = Counter() 16 | while end < len(s): 17 | if counter[s[end]] <= 0: 18 | counter[s[end]] += 1 19 | else: 20 | while s[start] != s[end]: 21 | counter[s[start]] -= 1 22 | start += 1 23 | start += 1 24 | maxs = max(maxs, end - start + 1) 25 | end += 1 26 | return maxs 27 | 28 | 29 | if __name__ == "__main__": 30 | assert Solution().lengthOfLongestSubstring("abcabcbb") == 3 31 | assert Solution().lengthOfLongestSubstring("bbbb") == 1 32 | assert Solution().lengthOfLongestSubstring("pwwkew") == 3 33 | assert Solution().lengthOfLongestSubstring("tmmzuxt") == 5 34 | -------------------------------------------------------------------------------- /leetcode75/day2_205.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isIsomorphic(self, s: str, t: str) -> bool: 3 | """ 4 | s 没有映射 5 | t 有被映射过 -> False 6 | t 没有被映射过 -> 添加映射 7 | s 有映射 8 | t 的值与与映射值一致 -> continue 9 | t 的值与与映射值不一致 -> False 10 | """ 11 | maps = {} 12 | for s1, t1 in zip(s, t): 13 | if s1 not in maps: 14 | if t1 in maps.values(): 15 | return False 16 | else: 17 | maps[s1] = t1 18 | else: 19 | if t1 != maps[s1]: 20 | return False 21 | else: 22 | continue 23 | return True 24 | 25 | 26 | if __name__ == "__main__": 27 | assert Solution().isIsomorphic("egg", "add") is True 28 | assert Solution().isIsomorphic("foo", "bar") is False 29 | assert Solution().isIsomorphic("paper", "title") is True 30 | assert Solution().isIsomorphic("badc", "baba") is False 31 | -------------------------------------------------------------------------------- /leetcode75/day2_392.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isSubsequence(self, s: str, t: str) -> bool: 3 | si, ti = 0, 0 4 | while ti < len(t) and si < len(s): 5 | if t[ti] == s[si]: 6 | si += 1 7 | ti += 1 8 | return si == len(s) 9 | 10 | 11 | if __name__ == "__main__": 12 | assert Solution().isSubsequence("", "ahbgdc") is True 13 | assert Solution().isSubsequence("abc", "ahbgdc") is True 14 | assert Solution().isSubsequence("abc", "abc") is True 15 | assert Solution().isSubsequence("abc", "ab") is False 16 | assert Solution().isSubsequence("axc", "ahbgdc") is False 17 | -------------------------------------------------------------------------------- /leetcode75/day30_100.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import TreeNode, create_binary_tree 4 | 5 | 6 | class Solution: 7 | def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool: 8 | if p is None and q is None: 9 | return True 10 | elif p and q and p.val == q.val: 11 | return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right) 12 | else: 13 | return False 14 | 15 | 16 | if __name__ == "__main__": 17 | p = create_binary_tree(nums=[1, 2, 3], index=0) 18 | q = create_binary_tree(nums=[1, 2, 3], index=0) 19 | assert Solution().isSameTree(p, q) is True 20 | 21 | p = create_binary_tree(nums=[1, 2, None], index=0) 22 | q = create_binary_tree(nums=[1, None, 2], index=0) 23 | assert Solution().isSameTree(p, q) is False 24 | 25 | p = create_binary_tree(nums=[1, 2, 1], index=0) 26 | q = create_binary_tree(nums=[1, 1, 2], index=0) 27 | assert Solution().isSameTree(p, q) is False 28 | -------------------------------------------------------------------------------- /leetcode75/day30_101.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional 2 | 3 | from helper import TreeNode, create_binary_tree 4 | 5 | 6 | class Solution: 7 | def isSymmetric(self, root: Optional[TreeNode]) -> bool: 8 | if root is None: 9 | return True 10 | queue: List[Optional[TreeNode]] = [root] 11 | while queue: 12 | size = len(queue) 13 | nums: List[Optional[int]] = [] 14 | for i in range(size): 15 | node = queue[i] 16 | if node: 17 | queue.append(node.left) 18 | queue.append(node.right) 19 | nums.append(node.left.val if node.left else None) 20 | nums.append(node.right.val if node.right else None) 21 | start, end = 0, len(nums) - 1 22 | while start < end: 23 | if nums[start] != nums[end]: 24 | return False 25 | start += 1 26 | end -= 1 27 | queue = queue[size:] 28 | return True 29 | 30 | 31 | if __name__ == "__main__": 32 | root = create_binary_tree(nums=[1, 2, 2, 3, 4, 4, 3], index=0) 33 | assert Solution().isSymmetric(root) is True 34 | 35 | root = create_binary_tree(nums=[1, 2, 2, None, 3, None, 3], index=0) 36 | assert Solution().isSymmetric(root) is False 37 | 38 | root = create_binary_tree(nums=[2, 3, 3, 4, 5, 5, 4, None, None, 8, 9, None, None, 9, 8], index=0) 39 | assert Solution().isSymmetric(root) is False 40 | -------------------------------------------------------------------------------- /leetcode75/day31_155.py: -------------------------------------------------------------------------------- 1 | from typing import List, Tuple 2 | 3 | 4 | class MinStack: 5 | """ 6 | stack 7 | (-3, -3) 8 | (0, -2) 9 | (-2, -2) 10 | """ 11 | 12 | def __init__(self): 13 | self.stack: List[Tuple[int, int]] = [] 14 | 15 | def push(self, val: int) -> None: 16 | if len(self.stack) == 0: 17 | self.stack.append((val, val)) 18 | else: 19 | cur_mins = self.stack[-1][1] 20 | if val < cur_mins: 21 | self.stack.append((val, val)) 22 | else: 23 | self.stack.append((val, cur_mins)) 24 | 25 | def pop(self) -> None: 26 | self.stack = self.stack[:-1] 27 | 28 | def top(self) -> int: 29 | if self.stack: 30 | return self.stack[-1][0] 31 | 32 | def getMin(self) -> int: 33 | if self.stack: 34 | return self.stack[-1][1] 35 | 36 | 37 | if __name__ == "__main__": 38 | # Your MinStack object will be instantiated and called as such: 39 | obj = MinStack() 40 | obj.push(-2) 41 | obj.push(0) 42 | obj.push(-3) 43 | assert obj.getMin() == -3 44 | obj.pop() 45 | assert obj.top() == 0 46 | assert obj.getMin() == -2 47 | -------------------------------------------------------------------------------- /leetcode75/day31_208.py: -------------------------------------------------------------------------------- 1 | class Trie: 2 | """ 3 | root {} 4 | 5 | a {a: {}} 6 | 7 | p {a: {p: {}}} 8 | 9 | p {a: {p: {p: {}}}} 10 | 11 | l {a: {p: {p: {l: {}}}}} 12 | 13 | e {a: {p: {p: {l: {e: {}}}}}} 14 | 15 | $ {a: {p: {p: {l: {e: {$:$}}}}}} 16 | 17 | after insert app 18 | {a: {p: {p: { 19 | l: {e: {$:$}}, 20 | $: $ 21 | }}}} 22 | """ 23 | 24 | def __init__(self): 25 | self.root = {} 26 | 27 | def insert(self, word: str) -> None: 28 | root = self.root 29 | for char in word: 30 | if char not in root: 31 | root[char] = {} 32 | root = root[char] 33 | root["$"] = "$" 34 | 35 | def search(self, word: str) -> bool: 36 | root = self.root 37 | for char in word: 38 | if char not in root: 39 | return False 40 | root = root[char] 41 | return root.get("$") == "$" 42 | 43 | def startsWith(self, prefix: str) -> bool: 44 | root = self.root 45 | for char in prefix: 46 | if char not in root: 47 | return False 48 | root = root[char] 49 | return True 50 | 51 | 52 | if __name__ == "__main__": 53 | trie = Trie() 54 | trie.insert("apple") 55 | assert trie.search("apple") is True 56 | assert trie.search("app") is False 57 | assert trie.startsWith("app") is True 58 | trie.insert("app") 59 | assert trie.search("app") is True 60 | -------------------------------------------------------------------------------- /leetcode75/day31_232.py: -------------------------------------------------------------------------------- 1 | class MyQueue: 2 | """ 3 | stack: 后入先出 4 | queue: 先入先出 5 | 6 | stack1 stack2 7 | 8 | | | | | 9 | | 2 | | | 10 | | 1 | | | 11 | 12 | push 操作: 往 stack1 里压 13 | peek 操作: 14 | 1. stack2 空: stack1 所有出栈并依次压入 stack2, 返回 stack2 栈顶 15 | 2. stack2 非空: 直接返回 stack2 栈顶 16 | pop 操作: 17 | 1. stack2 空: stack1 所有出栈并依次压入 stack2, 弹出 stack2 栈顶 18 | 2. stack2 非空: 直接弹出 stack2 栈顶 19 | empty: 20 | stack2 is empty and stack1 is empty 21 | """ 22 | 23 | def __init__(self): 24 | self.stack1 = [] 25 | self.stack2 = [] 26 | 27 | def push(self, x: int) -> None: 28 | self.stack1.append(x) 29 | 30 | def pop(self) -> int: 31 | ans = self.peek() 32 | self.stack2 = self.stack2[:-1] 33 | return ans 34 | 35 | def peek(self) -> int: 36 | if len(self.stack2) == 0: 37 | self.stack2 = self.stack1[::-1] 38 | self.stack1 = [] 39 | if len(self.stack2) > 0: 40 | return self.stack2[-1] 41 | 42 | def empty(self) -> bool: 43 | return len(self.stack1) == len(self.stack2) == 0 44 | 45 | 46 | if __name__ == "__main__": 47 | # Your MyQueue object will be instantiated and called as such: 48 | obj = MyQueue() 49 | obj.push(1) 50 | obj.push(2) 51 | assert obj.peek() == 1 52 | assert obj.pop() == 1 53 | assert obj.empty() is False 54 | assert obj.pop() == 2 55 | assert obj.pop() is None 56 | assert obj.empty() is True 57 | -------------------------------------------------------------------------------- /leetcode75/day32_56.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def merge(self, intervals: List[List[int]]) -> List[List[int]]: 6 | if len(intervals) < 1: 7 | raise KeyError 8 | intervals.sort() 9 | ans = [] 10 | left = 0 11 | while left < len(intervals): 12 | right = left 13 | # note! 这里要记录历史最大值,并且边界也要与该历史最大值比较;) 14 | maxs = intervals[right][1] 15 | while right + 1 < len(intervals) and intervals[right + 1][0] <= maxs: 16 | maxs = max(maxs, intervals[right + 1][1]) 17 | right += 1 18 | ans.append([intervals[left][0], maxs]) 19 | left = right + 1 20 | return ans 21 | 22 | 23 | if __name__ == "__main__": 24 | assert Solution().merge(intervals=[[1, 3], [2, 6], [8, 10], [15, 18]]) == [[1, 6], [8, 10], [15, 18]] 25 | assert Solution().merge(intervals=[[1, 4], [4, 5]]) == [[1, 5]] 26 | assert Solution().merge(intervals=[[1, 3], [4, 5]]) == [[1, 3], [4, 5]] 27 | assert Solution().merge(intervals=[[1, 3]]) == [[1, 3]] 28 | assert Solution().merge(intervals=[[1, 4], [2, 3]]) == [[1, 4]] 29 | assert Solution().merge(intervals=[[2, 3], [4, 5], [6, 7], [8, 9], [1, 10]]) == [[1, 10]] 30 | -------------------------------------------------------------------------------- /leetcode75/day33_227.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def calculate(self, s: str) -> int: 3 | """ 4 | stack: 最后只保留需要相加的数字 5 | *: stack[-1] * num 6 | /: stack[-1] // num 7 | -: -num 8 | +: num 9 | return sum(stack) 10 | """ 11 | stack = [] 12 | s = s.strip() 13 | num = 0 14 | pre_sign = "+" 15 | for i in range(len(s)): 16 | if s[i].isdigit(): 17 | num = num * 10 + int(s[i]) 18 | if s[i] in "+-*/" or i == len(s) - 1: 19 | if pre_sign == "+": 20 | stack.append(num) 21 | elif pre_sign == "-": 22 | stack.append(-num) 23 | elif pre_sign == "*": 24 | stack[-1] = stack[-1] * num 25 | elif pre_sign == "/": 26 | # note! -3 // 2 == -2, 所以对负数需要转成正数处理后再变成负数 27 | stack[-1] = stack[-1] // num if stack[-1] > 0 else -((-stack[-1]) // num) 28 | num = 0 29 | pre_sign = s[i] 30 | return sum(stack) 31 | 32 | 33 | if __name__ == "__main__": 34 | assert Solution().calculate(s="3+2*2") == 7 35 | assert Solution().calculate(s=" 3/2 ") == 1 36 | assert Solution().calculate(s=" 3+5 / 2 ") == 5 37 | assert Solution().calculate(s="14-3/2") == 13 38 | -------------------------------------------------------------------------------- /leetcode75/day34_547.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | from typing import List 3 | 4 | 5 | class Solution: 6 | def findCircleNum(self, isConnected: List[List[int]]) -> int: 7 | """ 8 | 1. 构建有向图 edges: 9 | { 10 | 0: [1], 11 | 1: [0], 12 | 2: [], 13 | } 14 | 2. 广度优先搜索次数即为省份数量 15 | """ 16 | n = len(isConnected) 17 | if n < 1 or len(isConnected[0]) < 1: 18 | raise KeyError 19 | edges = defaultdict(list) 20 | for i in range(n): 21 | for j in range(n): 22 | if i != j and isConnected[i][j] == 1: 23 | edges[i].append(j) 24 | visit = [False for _ in range(n)] 25 | ans = 0 26 | for i in range(n): 27 | if visit[i] is False: 28 | self.bfs(edges, i, visit) 29 | ans += 1 30 | return ans 31 | 32 | def bfs(self, edges, start, visit): 33 | queue = [start] 34 | while queue: 35 | size = len(queue) 36 | for i in range(size): 37 | visit[queue[i]] = True 38 | for city in edges[queue[i]]: 39 | if visit[city] is False: 40 | queue.append(city) 41 | queue = queue[size:] 42 | 43 | 44 | if __name__ == "__main__": 45 | assert Solution().findCircleNum(isConnected=[[1, 1, 0], [1, 1, 0], [0, 0, 1]]) == 2 46 | assert Solution().findCircleNum(isConnected=[[1, 0, 0], [0, 1, 0], [0, 0, 1]]) == 3 47 | -------------------------------------------------------------------------------- /leetcode75/day34_947.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | from typing import List 3 | 4 | 5 | class Solution: 6 | def removeStones(self, stones: List[List[int]]) -> int: 7 | 8 | n = len(stones) 9 | if n < 1: 10 | raise KeyError 11 | edges = defaultdict(list) 12 | for i in range(n): 13 | for j in range(i + 1, n): 14 | if stones[i][0] == stones[j][0] or stones[i][1] == stones[j][1]: 15 | edges[i].append(j) 16 | # notes, 是双向图 17 | edges[j].append(i) 18 | visit = [False for _ in range(n)] 19 | connected = 0 20 | for i in range(n): 21 | if visit[i] is False: 22 | self.bfs(edges, i, visit) 23 | connected += 1 24 | return n - connected 25 | 26 | def bfs(self, edges, start, visit): 27 | queue = [start] 28 | while queue: 29 | size = len(queue) 30 | for i in range(size): 31 | visit[queue[i]] = True 32 | for city in edges[queue[i]]: 33 | if visit[city] is False: 34 | queue.append(city) 35 | queue = queue[size:] 36 | 37 | 38 | if __name__ == "__main__": 39 | assert Solution().removeStones(stones=[[0, 0], [0, 1], [1, 0], [1, 2], [2, 1], [2, 2]]) == 5 40 | assert Solution().removeStones(stones=[[0, 0], [0, 2], [1, 1], [2, 0], [2, 2]]) == 3 41 | assert Solution().removeStones(stones=[[0, 0]]) == 0 42 | assert Solution().removeStones(stones=[[0, 1], [1, 0], [1, 1]]) == 2 43 | -------------------------------------------------------------------------------- /leetcode75/day3_21.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import ListNode, create_link, trave_link 4 | 5 | 6 | class Solution: 7 | def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: 8 | head = ListNode(-1) 9 | h1, h2 = list1, list2 10 | cur = head 11 | while h1 and h2: 12 | if h1.val <= h2.val: 13 | cur.next = h1 14 | h1 = h1.next 15 | else: 16 | cur.next = h2 17 | h2 = h2.next 18 | cur = cur.next 19 | if h1: 20 | cur.next = h1 21 | else: 22 | cur.next = h2 23 | return head.next 24 | 25 | 26 | if __name__ == "__main__": 27 | head1 = create_link([1, 2, 4]) 28 | head2 = create_link([1, 3, 4]) 29 | head = Solution().mergeTwoLists(head1, head2) 30 | assert trave_link(head) == [1, 1, 2, 3, 4, 4] 31 | 32 | head1 = create_link([]) 33 | head2 = create_link([]) 34 | head = Solution().mergeTwoLists(head1, head2) 35 | assert trave_link(head) == [] 36 | 37 | head1 = create_link([1, 2, 4]) 38 | head2 = create_link([]) 39 | head = Solution().mergeTwoLists(head1, head2) 40 | assert trave_link(head) == [1, 2, 4] 41 | 42 | head1 = create_link([1, 2, 4]) 43 | head2 = create_link([3]) 44 | head = Solution().mergeTwoLists(head1, head2) 45 | assert trave_link(head) == [1, 2, 3, 4] 46 | -------------------------------------------------------------------------------- /leetcode75/day3_876.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import ListNode, create_link, trave_link 4 | 5 | 6 | class Solution: 7 | def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]: 8 | slow, fast = head, head 9 | while fast: 10 | fast = fast.next 11 | if not fast: 12 | return slow 13 | fast = fast.next 14 | slow = slow.next 15 | return slow 16 | 17 | 18 | if __name__ == "__main__": 19 | head1 = create_link([1, 2, 3, 4, 5]) 20 | head = Solution().middleNode(head1) 21 | assert trave_link(head) == [3, 4, 5] 22 | 23 | head1 = create_link([1, 2, 3, 4, 5, 6]) 24 | head = Solution().middleNode(head1) 25 | assert trave_link(head) == [4, 5, 6] 26 | 27 | head1 = create_link([1]) 28 | head = Solution().middleNode(head1) 29 | assert trave_link(head) == [1] 30 | 31 | head1 = create_link([1, 2]) 32 | head = Solution().middleNode(head1) 33 | assert trave_link(head) == [2] 34 | -------------------------------------------------------------------------------- /leetcode75/day4_142.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import ListNode, create_ring_link, trave_ring_link 4 | 5 | 6 | class Solution: 7 | def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]: 8 | cycle = False 9 | slow, fast = head, head 10 | while fast and fast.next and slow: 11 | fast = fast.next.next 12 | slow = slow.next 13 | if fast == slow: 14 | cycle = True 15 | break 16 | if cycle is False: 17 | return None 18 | # 有环 19 | result = head 20 | while result and slow and result != slow: 21 | result = result.next 22 | slow = slow.next 23 | return result 24 | 25 | 26 | if __name__ == "__main__": 27 | head1 = create_ring_link([3, 2, 0, 4], 1) 28 | head = Solution().detectCycle(head1) 29 | assert trave_ring_link(head)[:6] == [2, 0, 4, 2, 0, 4] 30 | 31 | head1 = create_ring_link([1, 2], 0) 32 | head = Solution().detectCycle(head1) 33 | assert trave_ring_link(head)[:4] == [1, 2, 1, 2] 34 | 35 | head1 = create_ring_link([1], -1) 36 | head = Solution().detectCycle(head1) 37 | assert trave_ring_link(head) == [] 38 | -------------------------------------------------------------------------------- /leetcode75/day4_876.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import ListNode, create_link, trave_link 4 | 5 | 6 | class Solution: 7 | def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: 8 | dummy = ListNode(-1) 9 | while head: 10 | cur = head 11 | head = head.next 12 | cur.next = dummy.next 13 | dummy.next = cur 14 | return dummy.next 15 | 16 | 17 | if __name__ == "__main__": 18 | head1 = create_link([1, 2, 4]) 19 | head = Solution().reverseList(head1) 20 | assert trave_link(head) == [4, 2, 1] 21 | 22 | head1 = create_link([1]) 23 | head = Solution().reverseList(head1) 24 | assert trave_link(head) == [1] 25 | 26 | head1 = create_link([]) 27 | head = Solution().reverseList(head1) 28 | assert trave_link(head) == [] 29 | -------------------------------------------------------------------------------- /leetcode75/day5_121.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def maxProfit(self, prices: List[int]) -> int: 6 | # dp[i]: 第 i 天卖出能够获得的最大利润 7 | # dp[i] = max(0, dp[i-1]) - prices[i-1] + prices[i] 8 | # dp[0] = 0 9 | dp = [0 for _ in range(len(prices))] 10 | for i in range(1, len(prices)): 11 | dp[i] = max(0, dp[i - 1]) - prices[i - 1] + prices[i] 12 | return max(dp, default=0) 13 | 14 | 15 | if __name__ == "__main__": 16 | assert Solution().maxProfit([1]) == 0 17 | assert Solution().maxProfit([7, 1, 5, 3, 6, 4]) == 5 18 | assert Solution().maxProfit([7, 6, 4, 3, 1]) == 0 19 | -------------------------------------------------------------------------------- /leetcode75/day5_409.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | 3 | 4 | class Solution: 5 | def longestPalindrome(self, s: str) -> int: 6 | counter = Counter(s) 7 | ans = 0 8 | for value in counter.values(): 9 | ans += value // 2 * 2 10 | if value % 2 and ans % 2 == 0: 11 | ans += 1 12 | return ans 13 | 14 | 15 | if __name__ == "__main__": 16 | assert Solution().longestPalindrome("abccccdd") == 7 17 | assert Solution().longestPalindrome("a") == 1 18 | -------------------------------------------------------------------------------- /leetcode75/day6_102.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional 2 | 3 | from helper import TreeNode, create_binary_tree 4 | 5 | 6 | class Solution: 7 | def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: 8 | if root is None: 9 | return [] 10 | ans = [] 11 | queue: List[TreeNode] = [root] 12 | while queue: 13 | count = len(queue) 14 | nums = [] 15 | for index in range(count): 16 | node = queue[index] 17 | nums.append(node.val) 18 | if node.left: 19 | queue.append(node.left) 20 | if node.right: 21 | queue.append(node.right) 22 | ans.append(nums) 23 | queue = queue[count:] 24 | return ans 25 | 26 | 27 | if __name__ == "__main__": 28 | s = Solution() 29 | nums = [] 30 | root = create_binary_tree(nums, 0) 31 | assert s.levelOrder(root) == [] 32 | 33 | nums = [1] 34 | root = create_binary_tree(nums, 0) 35 | assert s.levelOrder(root) == [[1]] 36 | 37 | nums = [3, 9, 20, None, None, 15, 7] 38 | root = create_binary_tree(nums, 0) 39 | assert s.levelOrder(root) == [[3], [9, 20], [15, 7]] 40 | -------------------------------------------------------------------------------- /leetcode75/day7_278.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def search(self, nums: List[int], target: int) -> int: 6 | # [) 7 | left, right = 0, len(nums) 8 | while left < right: 9 | mid = left + (right - left) // 2 10 | if nums[mid] >= target: 11 | right = mid 12 | elif nums[mid] < target: 13 | left = mid + 1 14 | return left 15 | 16 | 17 | if __name__ == "__main__": 18 | assert Solution().search(nums=[-1, 0, 3, 3, 3, 3], target=3) == 2 19 | -------------------------------------------------------------------------------- /leetcode75/day7_704.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def search(self, nums: List[int], target: int) -> int: 6 | # [) 7 | left, right = 0, len(nums) 8 | while left < right: 9 | mid = left + (right - left) // 2 10 | if nums[mid] == target: 11 | return mid 12 | elif nums[mid] < target: 13 | left = mid + 1 14 | else: 15 | right = mid 16 | return -1 17 | 18 | 19 | if __name__ == "__main__": 20 | assert Solution().search(nums=[-1, 0, 3, 5, 9, 12], target=9) == 4 21 | assert Solution().search([-1, 0, 3, 5, 9, 12], target=2) == -1 22 | -------------------------------------------------------------------------------- /leetcode75/day8_235.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import TreeNode, create_binary_tree 4 | 5 | 6 | class Solution: 7 | def lowestCommonAncestor(self, root: Optional[TreeNode], p: TreeNode, q: TreeNode) -> Optional[TreeNode]: 8 | if root and p.val < root.val and q.val < root.val: 9 | return self.lowestCommonAncestor(root.left, p, q) 10 | elif root and p.val > root.val and q.val > root.val: 11 | return self.lowestCommonAncestor(root.right, p, q) 12 | else: 13 | # 三种情况 14 | # p.val < root.val < q.val 15 | # p.val = root.val 16 | # q.val = root.val 17 | return root 18 | 19 | 20 | if __name__ == "__main__": 21 | s = Solution() 22 | nums = [6, 2, 8, 0, 4, 7, 9, None, None, 3, 5, None, None, None, None] 23 | root = create_binary_tree(nums, 0) 24 | assert s.lowestCommonAncestor(root, TreeNode(2), TreeNode(8)).val == 6 25 | assert s.lowestCommonAncestor(root, TreeNode(2), TreeNode(4)).val == 2 26 | -------------------------------------------------------------------------------- /leetcode75/day8_98.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import TreeNode, create_binary_tree 4 | 5 | 6 | class Solution: 7 | def isValidBST(self, root: Optional[TreeNode]) -> bool: 8 | if root is None: 9 | return True 10 | return ( 11 | self.traverse_left(root.left, root.val) 12 | and self.traverse_right(root.right, root.val) 13 | and self.isValidBST(root.left) 14 | and self.isValidBST(root.right) 15 | ) 16 | 17 | def traverse_left(self, root: Optional[TreeNode], value: int) -> bool: 18 | if root is None: 19 | return True 20 | return root.val < value and self.traverse_left(root.left, value) and self.traverse_left(root.right, value) 21 | 22 | def traverse_right(self, root: Optional[TreeNode], value: int) -> bool: 23 | if root is None: 24 | return True 25 | return root.val > value and self.traverse_right(root.left, value) and self.traverse_right(root.right, value) 26 | 27 | 28 | if __name__ == "__main__": 29 | s = Solution() 30 | nums = [2, 1, 3] 31 | root = create_binary_tree(nums, 0) 32 | assert s.isValidBST(root) is True 33 | 34 | nums = [5, 1, 4, None, None, 3, 6] 35 | root = create_binary_tree(nums, 0) 36 | assert s.isValidBST(root) is False 37 | -------------------------------------------------------------------------------- /leetcode75/day9_200.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def numIslands(self, grid: List[List[str]]) -> int: 6 | rows, colums = len(grid), len(grid[0]) 7 | ans = 0 8 | for row in range(rows): 9 | for colum in range(colums): 10 | if grid[row][colum] == "1": 11 | ans += 1 12 | self.DFS(grid, row, colum, rows, colums) 13 | return ans 14 | 15 | def DFS(self, grid: List[List[str]], row: int, colum: int, rows: int, colums: int): 16 | grid[row][colum] = "#" 17 | for direct in [(-1, 0), (0, -1), (1, 0), (0, 1)]: 18 | next_row, next_colum = row + direct[0], colum + direct[1] 19 | if 0 <= next_row < rows and 0 <= next_colum < colums and grid[next_row][next_colum] == "1": 20 | self.DFS(grid, next_row, next_colum, rows, colums) 21 | 22 | 23 | if __name__ == "__main__": 24 | assert ( 25 | Solution().numIslands( 26 | grid=[ 27 | ["1", "1", "1", "1", "0"], 28 | ["1", "1", "0", "1", "0"], 29 | ["1", "1", "0", "0", "0"], 30 | ["0", "0", "0", "0", "0"], 31 | ] 32 | ) 33 | == 1 34 | ) 35 | assert ( 36 | Solution().numIslands( 37 | grid=[ 38 | ["1", "1", "0", "0", "0"], 39 | ["1", "1", "0", "0", "0"], 40 | ["0", "0", "1", "0", "0"], 41 | ["0", "0", "0", "1", "1"], 42 | ] 43 | ) 44 | == 3 45 | ) 46 | -------------------------------------------------------------------------------- /leetcode75/day9_733.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def floodFill(self, image: List[List[int]], sr: int, sc: int, color: int) -> List[List[int]]: 6 | if image[sr][sc] == color: 7 | return image 8 | rows, colums = len(image), len(image[0]) 9 | ans = [[image[row][colum] for colum in range(colums)] for row in range(rows)] 10 | self.DFS(ans, sr, sc, image[sr][sc], color, rows, colums) 11 | return ans 12 | 13 | def DFS(self, ans: List[List[int]], sr: int, sc: int, old_color: int, new_color: int, rows: int, colums: int): 14 | ans[sr][sc] = new_color 15 | for direct in [(-1, 0), (0, -1), (1, 0), (0, 1)]: 16 | next_sr, next_sc = sr + direct[0], sc + direct[1] 17 | if 0 <= next_sr < rows and 0 <= next_sc < colums and ans[next_sr][next_sc] == old_color: 18 | self.DFS(ans, next_sr, next_sc, old_color, new_color, rows, colums) 19 | 20 | 21 | if __name__ == "__main__": 22 | assert Solution().floodFill(image=[[1, 1, 1], [1, 1, 0], [1, 0, 1]], sr=1, sc=1, color=2) == [ 23 | [2, 2, 2], 24 | [2, 2, 0], 25 | [2, 0, 1], 26 | ] 27 | assert Solution().floodFill([[0, 0, 0], [0, 0, 0]], sr=0, sc=0, color=2) == [ 28 | [2, 2, 2], 29 | [2, 2, 2], 30 | ] 31 | 32 | assert Solution().floodFill([[0, 0, 0], [0, 0, 0]], sr=0, sc=0, color=0) == [ 33 | [0, 0, 0], 34 | [0, 0, 0], 35 | ] 36 | -------------------------------------------------------------------------------- /others/find_max_occur_char_4.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | 3 | 4 | def get_max_occur_char(strings: str) -> str: 5 | letter = "" 6 | max_count = 0 7 | counter = Counter() 8 | for char in strings: 9 | counter[char] += 1 10 | if counter[char] > max_count: 11 | max_count = counter[char] 12 | letter = char 13 | 14 | return letter 15 | 16 | 17 | if __name__ == "__main__": 18 | assert get_max_occur_char("a") == "a" 19 | assert get_max_occur_char("abcd") == "a" 20 | assert get_max_occur_char("abbc") == "b" 21 | assert get_max_occur_char("abcbcdc") == "c" 22 | assert get_max_occur_char("aaaaa") == "a" 23 | assert get_max_occur_char("") == "" 24 | -------------------------------------------------------------------------------- /others/parentheses_1.py: -------------------------------------------------------------------------------- 1 | def valid(chars: str) -> bool: 2 | if len(chars) < 2: 3 | return False 4 | maps = { 5 | ")": "(", 6 | "]": "[", 7 | "}": "{", 8 | } 9 | stack = [] 10 | for char in chars: 11 | if char in "([{": 12 | stack.append(char) 13 | elif char in ")]}": 14 | if len(stack) == 0: 15 | return False 16 | top = stack[-1] 17 | if top != maps.get(char): 18 | return False 19 | stack.pop() 20 | else: 21 | return False 22 | 23 | return len(stack) == 0 24 | 25 | 26 | if __name__ == "__main__": 27 | assert valid("()[]{}") is True 28 | assert valid("((({{[]}})))[]{}") is True 29 | assert valid("((({{[]}})))[]{}(") is False 30 | assert valid("()(]{}") is False 31 | assert valid(")()[]{}") is False 32 | assert valid(")") is False 33 | assert valid("([a)") is False 34 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line_length = 119 3 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 119 3 | exclude = .git,__pycache__,.pytest_cache,.venv,.vscode,.idea,.mypy_cache,*.egg-info,venv 4 | extend-ignore = E203 5 | 6 | [isort] 7 | multi_line_output = 3 8 | include_trailing_comma = True 9 | force_grid_wrap = 0 10 | use_parentheses = True 11 | ensure_newline_before_comments = True 12 | line_length = 119 13 | 14 | [tool:pytest] 15 | addopts = -ra --cov-report=term-missing --cov-report=xml 16 | -------------------------------------------------------------------------------- /sword-means-offer/offer_06.py: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 06. 从尾到头打印链表 2 | # 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。 3 | 4 | 5 | # 示例 1: 6 | 7 | # 输入:head = [1,3,2] 8 | # 输出:[2,3,1] 9 | 10 | 11 | # 限制: 12 | 13 | # 0 <= 链表长度 <= 10000 14 | 15 | from typing import List 16 | 17 | 18 | # Definition for singly-linked list. 19 | class ListNode: 20 | def __init__(self, x): 21 | self.val = x 22 | self.next = None 23 | 24 | 25 | class Solution: 26 | def reversePrint(self, head: ListNode) -> List[int]: 27 | """递归实现与非递归实现 28 | 递归调用时后面的变量语句会先压栈, 递归结束时再弹出栈 29 | [] [] 30 | [2] [2] => [] + [2] + [3] + [1] => [2, 3, 1] 31 | [3] [3] 32 | [1] [1] 33 | """ 34 | # if head is None: 35 | # return [] 36 | # return self.reversePrint(head.next) + [head.val] 37 | 38 | stack = [] 39 | 40 | while head is not None: 41 | stack.append(head.val) 42 | head = head.next 43 | 44 | return stack[::-1] 45 | 46 | 47 | if __name__ == "__main__": 48 | head = ListNode(1) 49 | head.next = ListNode(3) 50 | head.next.next = ListNode(2) 51 | s = Solution() 52 | assert s.reversePrint(head) == [2, 3, 1] 53 | -------------------------------------------------------------------------------- /sword-means-offer/offer_09.py: -------------------------------------------------------------------------------- 1 | class CQueue: 2 | """ 3 | s1 s2 4 | value3 5 | value2 6 | value1 ------ 7 | 8 | s1 s2 9 | value1 10 | value2 11 | value3 12 | """ 13 | 14 | def __init__(self): 15 | self.stack1 = [] 16 | self.stack2 = [] 17 | 18 | def appendTail(self, value: int) -> None: 19 | self.stack1.append(value) 20 | 21 | def deleteHead(self) -> int: 22 | if len(self.stack2) > 0: 23 | value = self.stack2.pop() 24 | elif len(self.stack1) > 0: 25 | self.stack2 = self.stack1[::-1] 26 | self.stack1 = [] 27 | value = self.stack2.pop() 28 | else: 29 | value = -1 30 | return value 31 | 32 | 33 | if __name__ == "__main__": 34 | obj = CQueue() 35 | assert obj.deleteHead() == -1 36 | obj.appendTail(5) 37 | obj.appendTail(2) 38 | assert obj.deleteHead() == 5 39 | assert obj.deleteHead() == 2 40 | -------------------------------------------------------------------------------- /sword-means-offer/offer_17.py: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 17. 打印从1到最大的n位数 2 | # 输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。 3 | 4 | # 示例 1: 5 | 6 | # 输入: n = 1 7 | # 输出: [1,2,3,4,5,6,7,8,9] 8 | 9 | 10 | # 说明: 11 | 12 | # 用返回一个整数列表来代替打印 13 | # n 为正整数 14 | 15 | from typing import List 16 | 17 | 18 | class Solution: 19 | def printNumbers(self, n: int) -> List[int]: 20 | return [num for num in range(1, 10**n)] 21 | 22 | 23 | if __name__ == "__main__": 24 | s = Solution() 25 | assert s.printNumbers(1) == [1, 2, 3, 4, 5, 6, 7, 8, 9] 26 | -------------------------------------------------------------------------------- /sword-means-offer/offer_18_i.py: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 18. 删除链表的节点 2 | # 给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。 3 | 4 | # 返回删除后的链表的头节点。 5 | 6 | # 注意:此题对比原题有改动 7 | 8 | # 示例 1: 9 | 10 | # 输入: head = [4,5,1,9], val = 5 11 | # 输出: [4,1,9] 12 | # 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9. 13 | # 示例 2: 14 | 15 | # 输入: head = [4,5,1,9], val = 1 16 | # 输出: [4,5,9] 17 | # 解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9. 18 | 19 | # 说明: 20 | 21 | # 题目保证链表中节点的值互不相同 22 | # 若使用 C 或 C++ 语言,你不需要 free 或 delete 被删除的节点 23 | 24 | 25 | from helper import ListNode, create_link, trave_link 26 | 27 | 28 | class Solution: 29 | def deleteNode(self, head: ListNode, val: int) -> ListNode: 30 | if head is None: 31 | return None 32 | if head.val == val: 33 | return head.next 34 | head.next = self.deleteNode(head.next, val) 35 | return head 36 | 37 | 38 | if __name__ == "__main__": 39 | nums = [4, 5, 1, 9] 40 | head = create_link(nums) 41 | assert trave_link(head) == [4, 5, 1, 9] 42 | s = Solution() 43 | head = s.deleteNode(head, 5) 44 | assert trave_link(head) == [4, 1, 9] 45 | head = s.deleteNode(head, 4) 46 | assert trave_link(head) == [1, 9] 47 | head = s.deleteNode(head, 9) 48 | assert trave_link(head) == [1] 49 | head = s.deleteNode(head, 1) 50 | assert head is None 51 | assert trave_link(head) == [] 52 | nums = [] 53 | head = create_link(nums) 54 | assert trave_link(head) == [] 55 | -------------------------------------------------------------------------------- /sword-means-offer/offer_21.py: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面 2 | # 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。 3 | 4 | 5 | # 示例: 6 | 7 | # 输入:nums = [1,2,3,4] 8 | # 输出:[1,3,2,4] 9 | # 注:[3,1,2,4] 也是正确的答案之一。 10 | 11 | 12 | # 提示: 13 | 14 | # 0 <= nums.length <= 50000 15 | # 0 <= nums[i] <= 10000 16 | 17 | 18 | from typing import List 19 | 20 | 21 | class Solution: 22 | def exchange(self, nums: List[int]) -> List[int]: 23 | left, right = [], [] 24 | for num in nums: 25 | if num % 2 == 1: 26 | left.append(num) 27 | else: 28 | right.append(num) 29 | return left + right 30 | 31 | 32 | if __name__ == "__main__": 33 | s = Solution() 34 | assert s.exchange([1, 2, 3, 4]) == [1, 3, 2, 4] 35 | assert s.exchange([2, 4]) == [2, 4] 36 | -------------------------------------------------------------------------------- /sword-means-offer/offer_22.py: -------------------------------------------------------------------------------- 1 | from helper import ListNode, create_link, trave_link 2 | 3 | 4 | class Solution: 5 | def getKthFromEnd(self, head: ListNode, k: int) -> ListNode: 6 | if k <= 0: 7 | return None 8 | fast = head 9 | slow = head 10 | while k > 0 and fast is not None: 11 | fast = fast.next 12 | k -= 1 13 | 14 | if fast is None and k > 0: 15 | raise KeyError 16 | 17 | while fast is not None: 18 | fast = fast.next 19 | slow = slow.next 20 | 21 | return slow 22 | 23 | 24 | if __name__ == "__main__": 25 | s = Solution() 26 | nums = [1, 2, 3, 4, 5] 27 | head = create_link(nums) 28 | assert trave_link(head) == [1, 2, 3, 4, 5] 29 | node = s.getKthFromEnd(head, 2) 30 | assert trave_link(node) == [4, 5] 31 | 32 | nums = [1, 2, 3, 4, 5, 6] 33 | head = create_link(nums) 34 | node = s.getKthFromEnd(head, 1) 35 | assert trave_link(node) == [6] 36 | node = s.getKthFromEnd(head, 6) 37 | assert trave_link(node) == [1, 2, 3, 4, 5, 6] 38 | try: 39 | node = s.getKthFromEnd(head, 7) 40 | trave_link(node) == [1, 2, 3, 4, 5, 6] 41 | except Exception as e: 42 | assert type(e) == KeyError 43 | -------------------------------------------------------------------------------- /sword-means-offer/offer_25.py: -------------------------------------------------------------------------------- 1 | from helper import ListNode, create_link, trave_link 2 | 3 | 4 | class Solution: 5 | def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: 6 | """ 7 | 1,2,4 8 | 1,3,4 9 | """ 10 | head = ListNode(0) 11 | cur = head 12 | cur1, cur2 = l1, l2 13 | while cur1 and cur2: 14 | if cur1.val <= cur2.val: 15 | cur.next = cur1 16 | cur1 = cur1.next 17 | else: 18 | cur.next = cur2 19 | cur2 = cur2.next 20 | cur = cur.next 21 | if cur1 is not None: 22 | cur.next = cur1 23 | if cur2 is not None: 24 | cur.next = cur2 25 | 26 | return head.next 27 | 28 | 29 | if __name__ == "__main__": 30 | s = Solution() 31 | l1 = create_link([1, 2, 4]) 32 | l2 = create_link([1, 3, 4]) 33 | ans = s.mergeTwoLists(l1, l2) 34 | assert trave_link(ans) == [1, 1, 2, 3, 4, 4] 35 | 36 | l1 = create_link([]) 37 | l2 = create_link([1, 3, 4]) 38 | ans = s.mergeTwoLists(l1, l2) 39 | assert trave_link(ans) == [1, 3, 4] 40 | 41 | l1 = create_link([1, 3, 4]) 42 | l2 = create_link([]) 43 | ans = s.mergeTwoLists(l1, l2) 44 | assert trave_link(ans) == [1, 3, 4] 45 | 46 | l1 = create_link([]) 47 | l2 = create_link([]) 48 | ans = s.mergeTwoLists(l1, l2) 49 | assert trave_link(ans) == [] 50 | -------------------------------------------------------------------------------- /sword-means-offer/offer_26.py: -------------------------------------------------------------------------------- 1 | from helper import TreeNode, create_binary_tree 2 | 3 | 4 | class Solution: 5 | def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool: 6 | # 递归 7 | if A is None or B is None: 8 | return False 9 | return self.compare(A, B) or self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B) 10 | 11 | def compare(self, A: TreeNode, B: TreeNode) -> bool: 12 | if B is None: 13 | return True 14 | if A is None: 15 | return False 16 | return A.val == B.val and self.compare(A.left, B.left) and self.compare(A.right, B.right) 17 | 18 | 19 | if __name__ == "__main__": 20 | s = Solution() 21 | root_a = create_binary_tree([1, 2, 3], 0) 22 | root_b = create_binary_tree([3, 1], 0) 23 | assert s.isSubStructure(root_a, root_b) is False 24 | root_a = create_binary_tree([3, 4, 5, 1, 2], 0) 25 | root_b = create_binary_tree([4, 1], 0) 26 | assert s.isSubStructure(root_a, root_b) is True 27 | 28 | root_a = create_binary_tree([3, 4, 5, 1, 2], 0) 29 | root_b = create_binary_tree([2], 0) 30 | assert s.isSubStructure(root_a, root_b) is True 31 | root_a = create_binary_tree([3, 4, 5, 1, 2], 0) 32 | root_b = create_binary_tree([4, 1, 2], 0) 33 | assert s.isSubStructure(root_a, root_b) is True 34 | root_a = create_binary_tree([3, 4, 5, 1, 2], 0) 35 | root_b = create_binary_tree([4, 1, 2, 0], 0) 36 | assert s.isSubStructure(root_a, root_b) is False 37 | -------------------------------------------------------------------------------- /sword-means-offer/offer_30.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class MinStack: 5 | def __init__(self): 6 | """ 7 | initialize your data structure here. 8 | ----top------- 9 | |(value, min)| 10 | |(value, min)| 11 | |(value2, value2 if value2 < value1 else value1)| 12 | |(value1, value1)| 13 | """ 14 | self.elems: List[(int, int)] = [] 15 | self.count = -1 16 | 17 | def push(self, x: int) -> None: 18 | mins = x 19 | if self.count >= 0 and self.elems[self.count][1] < x: 20 | mins = self.elems[self.count][1] 21 | self.elems.append((x, mins)) 22 | self.count += 1 23 | 24 | def pop(self) -> None: 25 | if self.count >= 0: 26 | self.elems = self.elems[:-1] 27 | self.count -= 1 28 | 29 | def top(self) -> int: 30 | if self.count >= 0: 31 | return self.elems[self.count][0] 32 | 33 | def min(self) -> int: 34 | if self.count >= 0: 35 | return self.elems[self.count][1] 36 | 37 | 38 | if __name__ == "__main__": 39 | obj = MinStack() 40 | assert obj.min() is None 41 | assert obj.top() is None 42 | obj.pop() 43 | 44 | minStack = MinStack() 45 | minStack.push(-2) 46 | minStack.push(0) 47 | minStack.push(-3) 48 | assert minStack.min() == -3 49 | minStack.pop() 50 | assert minStack.top() == 0 51 | assert minStack.min() == -2 52 | -------------------------------------------------------------------------------- /sword-means-offer/offer_32_i.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from helper import TreeNode, create_binary_tree 4 | 5 | 6 | class Solution: 7 | def levelOrder(self, root: TreeNode) -> List[int]: 8 | if root is None: 9 | return [] 10 | results = [] 11 | queue = [root] 12 | while queue: 13 | size = len(queue) 14 | for i in range(size): 15 | # 添加下一层的节点及收集结果 16 | node = queue[i] 17 | if node: 18 | results.append(node.val) 19 | queue.append(node.left) 20 | queue.append(node.right) 21 | queue = queue[size:] 22 | return results 23 | 24 | 25 | if __name__ == "__main__": 26 | s = Solution() 27 | root = create_binary_tree([3, 9, 20, None, None, 15, 7], 0) 28 | assert s.levelOrder(root) == [3, 9, 20, 15, 7] 29 | -------------------------------------------------------------------------------- /sword-means-offer/offer_32_ii.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from helper import TreeNode, create_binary_tree 4 | 5 | 6 | class Solution: 7 | def levelOrder(self, root: TreeNode) -> List[List[int]]: 8 | if root is None: 9 | return [] 10 | results = [] 11 | queue = [root] 12 | while queue: 13 | size = len(queue) 14 | cur_nums = [] 15 | for i in range(size): 16 | # 添加下一层的节点及收集当前层结果 17 | node = queue[i] 18 | if node: 19 | cur_nums.append(node.val) 20 | queue.append(node.left) 21 | queue.append(node.right) 22 | if cur_nums: 23 | results.append(cur_nums) 24 | queue = queue[size:] 25 | return results 26 | 27 | 28 | if __name__ == "__main__": 29 | s = Solution() 30 | root = create_binary_tree([3, 9, 20, None, None, 15, 7], 0) 31 | 32 | assert s.levelOrder(root) == [[3], [9, 20], [15, 7]] 33 | -------------------------------------------------------------------------------- /sword-means-offer/offer_32_iii.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from helper import TreeNode, create_binary_tree 4 | 5 | 6 | class Solution: 7 | def levelOrder(self, root: TreeNode) -> List[List[int]]: 8 | if root is None: 9 | return [] 10 | results = [] 11 | queue = [root] 12 | level = 1 13 | while queue: 14 | size = len(queue) 15 | cur_nums = [] 16 | for i in range(size): 17 | # 添加下一层的节点及收集当前层结果 18 | node = queue[i] 19 | if node: 20 | cur_nums.append(node.val) 21 | queue.append(node.left) 22 | queue.append(node.right) 23 | if cur_nums: 24 | if level % 2 == 0: 25 | results.append(cur_nums[::-1]) 26 | else: 27 | results.append(cur_nums) 28 | queue = queue[size:] 29 | level += 1 30 | return results 31 | 32 | 33 | if __name__ == "__main__": 34 | s = Solution() 35 | root = create_binary_tree([3, 9, 20, None, None, 15, 7], 0) 36 | assert s.levelOrder(root) == [[3], [20, 9], [15, 7]] 37 | -------------------------------------------------------------------------------- /sword-means-offer/offer_33.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def verifyPostorder(self, postorder: List[int]) -> bool: 6 | if len(postorder) <= 1: 7 | return True 8 | root = postorder[-1] 9 | index = 0 10 | # 得出左,右子树 11 | while postorder[index] < root: 12 | index += 1 13 | 14 | left = postorder[:index] 15 | right = postorder[index:-1] 16 | 17 | # 左子树已经全小于 root, 现在检查右子树是否全大于根结点 18 | while postorder[index] > root: 19 | index += 1 20 | return index + 1 == len(postorder) and self.verifyPostorder(left) and self.verifyPostorder(right) 21 | 22 | 23 | if __name__ == "__main__": 24 | s = Solution() 25 | assert s.verifyPostorder([1, 6, 3, 2, 5]) is False 26 | assert s.verifyPostorder([1, 3, 2, 6, 5]) is True 27 | assert s.verifyPostorder([1, 2, 3, 4, 5]) is True 28 | assert s.verifyPostorder([5, 4, 3, 2, 1]) is True 29 | assert s.verifyPostorder([]) is True 30 | -------------------------------------------------------------------------------- /sword-means-offer/offer_34.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from helper import TreeNode, create_binary_tree 4 | 5 | 6 | class Solution: 7 | results = [] 8 | 9 | def pathSum(self, root: TreeNode, target: int) -> List[List[int]]: 10 | self.results = [] 11 | self.DFS(root, target, []) 12 | return self.results 13 | 14 | def DFS(self, root: TreeNode, target: int, nums: List[int]): 15 | if root is None: 16 | return 17 | # if target - root.val < 0: 18 | # return 19 | if root.left is None and root.right is None and root.val == target: 20 | self.results.append(nums + [root.val]) 21 | return 22 | if root.left: 23 | self.DFS(root.left, target - root.val, nums + [root.val]) 24 | if root.right: 25 | self.DFS(root.right, target - root.val, nums + [root.val]) 26 | 27 | 28 | if __name__ == "__main__": 29 | s = Solution() 30 | root = create_binary_tree([5, 4, 8, 11, None, 13, 4, 7, 2, None, None, None, None, 5, 1], 0) 31 | assert s.pathSum(root, 22) == [[5, 4, 11, 2], [5, 8, 4, 5]] 32 | root = create_binary_tree([1, 2, 3], 0) 33 | assert s.pathSum(root, 5) == [] 34 | root = create_binary_tree([1, 2, None], 0) 35 | assert s.pathSum(root, 0) == [] 36 | assert s.pathSum(root, 1) == [] 37 | root = create_binary_tree([1], 0) 38 | assert s.pathSum(root, 1) == [[1]] 39 | root = create_binary_tree([-2, None, -3], 0) 40 | assert s.pathSum(root, -5) == [[-2, -3]] 41 | -------------------------------------------------------------------------------- /sword-means-offer/offer_39.py: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 39. 数组中出现次数超过一半的数字 2 | # 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 3 | 4 | 5 | # 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 6 | 7 | 8 | # 示例 1: 9 | 10 | # 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 11 | # 输出: 2 12 | 13 | 14 | # 限制: 15 | 16 | # 1 <= 数组长度 <= 50000 17 | 18 | from typing import List 19 | 20 | 21 | class Solution: 22 | # def majorityElement(self, nums: List[int]) -> int: 23 | # return sorted(nums)[len(nums) // 2] 24 | 25 | def majorityElement(self, nums: List[int]) -> int: 26 | ans = nums[0] 27 | count = 1 28 | for i in range(1, len(nums)): 29 | if nums[i] == ans: 30 | count += 1 31 | else: 32 | count -= 1 33 | if count == 0: 34 | ans = nums[i] 35 | count = 1 36 | return ans 37 | 38 | 39 | if __name__ == "__main__": 40 | s = Solution() 41 | assert s.majorityElement([2]) == 2 42 | assert s.majorityElement([2, 1, 2]) == 2 43 | assert s.majorityElement([1, 2, 3, 2, 2, 2, 5, 4, 2]) == 2 44 | -------------------------------------------------------------------------------- /sword-means-offer/offer_40.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def getLeastNumbers(self, arr: List[int], k: int) -> List[int]: 6 | max_value = 10000 7 | counter = [0 for _ in range(max_value + 1)] 8 | for num in arr: 9 | counter[num] += 1 10 | ans = [] 11 | for index in range(max_value + 1): 12 | if counter[index] > 0: 13 | while counter[index] > 0 and k > 0: 14 | ans.append(index) 15 | counter[index] -= 1 16 | k -= 1 17 | if k <= 0: 18 | break 19 | return ans 20 | 21 | 22 | if __name__ == "__main__": 23 | s = Solution() 24 | assert s.getLeastNumbers([3, 1, 2], 2) == [1, 2] 25 | assert s.getLeastNumbers([0, 1, 2, 1], 1) == [0] 26 | assert s.getLeastNumbers([0, 1, 2, 1], 0) == [] 27 | -------------------------------------------------------------------------------- /sword-means-offer/offer_45.py: -------------------------------------------------------------------------------- 1 | # 输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。 2 | 3 | # 示例 1: 4 | 5 | # 输入: [10,2] 6 | # 输出: "102" 7 | # 示例 2: 8 | 9 | # 输入: [3,30,34,5,9] 10 | # 输出: "3033459" 11 | # 12 | 13 | # 提示: 14 | 15 | # 0 < nums.length <= 100 16 | # 说明: 17 | 18 | 19 | # 输出结果可能非常大,所以你需要返回一个字符串而不是整数 20 | # 拼接起来的数字可能会有前导 0,最后结果不需要去掉前导 0 21 | import functools 22 | from typing import List 23 | 24 | 25 | class Solution: 26 | def minNumber(self, nums: List[int]) -> str: 27 | """通过比较 {x}{y} {y}{x} 进行排序即可""" 28 | sorted_nums = sorted(nums, key=functools.cmp_to_key(lambda x, y: 1 if f"{x}{y}" > f"{y}{x}" else -1)) 29 | print(sorted_nums) 30 | return "".join(map(lambda num: str(num), sorted_nums)) 31 | 32 | 33 | if __name__ == "__main__": 34 | solution = Solution() 35 | assert solution.minNumber([10, 2]) == "102" 36 | assert solution.minNumber([3, 30, 34, 5, 9]) == "3033459" 37 | -------------------------------------------------------------------------------- /sword-means-offer/offer_46.py: -------------------------------------------------------------------------------- 1 | # 给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。 2 | # 一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。 3 | 4 | # 示例 1: 5 | 6 | # 输入: 12258 7 | # 输出: 5 8 | # 解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi" 9 | # 10 | 11 | # 提示: 12 | 13 | # 0 <= num < 231 14 | 15 | 16 | class Solution: 17 | def translateNum(self, num: int) -> int: 18 | """ 19 | 12 + (25) => 20 | 1 2 (25) 21 | 12 (25) 22 | 122 + (5) => 23 | 1 2 2 (5) 24 | 12 2 (5) 25 | 1 22 (5) 26 | dp[n]: n 个数字所能翻译方法的个数 27 | =》 dp[n] = dp[n-1] + dp[n-2] # 最后面两个字符 <=25, >=10 28 | = dp[n-1] # 否则 29 | """ 30 | text = str(num) 31 | dp = [1 for _ in range(len(text) + 1)] 32 | dp[0] = 1 33 | dp[1] = 1 34 | for i in range(2, len(text) + 1): 35 | if 10 <= int(text[i - 2 : i]) <= 25: 36 | dp[i] = dp[i - 2] + dp[i - 1] 37 | else: 38 | dp[i] = dp[i - 1] 39 | return dp[len(text)] 40 | 41 | 42 | if __name__ == "__main__": 43 | solution = Solution() 44 | assert solution.translateNum(12258) == 5 45 | assert solution.translateNum(1) == 1 46 | assert solution.translateNum(12) == 2 47 | assert solution.translateNum(102) == 2 48 | -------------------------------------------------------------------------------- /sword-means-offer/offer_47.py: -------------------------------------------------------------------------------- 1 | # 在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。 2 | # 你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。 3 | # 给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物? 4 | 5 | # 示例 1: 6 | 7 | # 输入: 8 | # [ 9 | #   [1,3,1], 10 | #   [1,5,1], 11 | #   [4,2,1] 12 | # ] 13 | # 输出: 12 14 | # 解释: 路径 1→3→5→2→1 可以拿到最多价值的礼物 15 | # 16 | 17 | # 提示: 18 | 19 | # 0 < grid.length <= 200 20 | # 0 < grid[0].length <= 200 21 | 22 | from typing import List 23 | 24 | 25 | class Solution: 26 | def maxValue(self, grid: List[List[int]]) -> int: 27 | for n in range(len(grid)): 28 | for m in range(len(grid[0])): 29 | if n == 0 and m > 0: 30 | grid[n][m] += grid[n][m - 1] 31 | elif n > 0 and m == 0: 32 | grid[n][m] += grid[n - 1][m] 33 | elif n > 0 and m > 0: 34 | grid[n][m] += max(grid[n - 1][m], grid[n][m - 1]) 35 | return grid[-1][-1] 36 | 37 | 38 | if __name__ == "__main__": 39 | s = Solution() 40 | grid = [ 41 | [1, 3, 1], 42 | [1, 5, 1], 43 | [4, 2, 1], 44 | ] 45 | assert s.maxValue(grid) == 12 46 | -------------------------------------------------------------------------------- /sword-means-offer/offer_49.py: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 49. 丑数 2 | # 我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。 3 | 4 | 5 | # 示例: 6 | 7 | # 输入: n = 10 8 | # 输出: 12 9 | # 解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。 10 | # 说明: 11 | 12 | # 1 是丑数。 13 | # n 不超过1690。 14 | 15 | 16 | class Solution: 17 | def nthUglyNumber(self, n: int) -> int: 18 | """ 19 | (2, 3, 5) * 丑数 = 丑数 20 | 1 21 | 2 * 1 22 | min 3 * 1 => 2 23 | 5 * 1 24 | 1 2 25 | 2 * 2 26 | min 3 * 1 => 3 27 | 5 * 1 28 | 29 | uglys[index(ugly_2)] * 2 30 | uglys[index(ugly_3)] * 3 min => 下一个丑数, min (ugly_2, ugly_3, ugly_5) + 1 31 | uglys[index(ugly_5)] * 5 32 | """ 33 | uglys = [1] 34 | ugly_2, ugly_3, ugly_5 = 0, 0, 0 35 | for _ in range(n): 36 | a = 2 * uglys[ugly_2] 37 | b = 3 * uglys[ugly_3] 38 | c = 5 * uglys[ugly_5] 39 | mins = min([a, b, c]) 40 | if a == mins: 41 | ugly_2 += 1 42 | if b == mins: 43 | ugly_3 += 1 44 | if c == mins: 45 | ugly_5 += 1 46 | uglys.append(mins) 47 | return uglys[n - 1] 48 | 49 | 50 | if __name__ == "__main__": 51 | s = Solution() 52 | assert s.nthUglyNumber(1) == 1 53 | assert s.nthUglyNumber(10) == 12 54 | assert s.nthUglyNumber(11) == 15 55 | assert s.nthUglyNumber(1690) == 2123366400 56 | -------------------------------------------------------------------------------- /sword-means-offer/offer_50.py: -------------------------------------------------------------------------------- 1 | # 在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。 2 | 3 | # 示例 1: 4 | 5 | # 输入:s = "abaccdeff" 6 | # 输出:'b' 7 | # 示例 2: 8 | 9 | # 输入:s = "" 10 | # 输出:' ' 11 | # 12 | 13 | # 限制: 14 | 15 | # 0 <= s 的长度 <= 50000 16 | 17 | 18 | # from collections import Counter 19 | 20 | 21 | class Solution: 22 | # def firstUniqChar(self, s: str) -> str: 23 | # """ """ 24 | # # O(N+N) = O(2N) 25 | # counter = Counter(s) 26 | # for char in s: 27 | # if counter[char] == 1: 28 | # return char 29 | # return " " 30 | def firstUniqChar(self, s: str) -> str: 31 | """ 32 | O(N) 33 | python3.6 dict 是按插入时间有序的特性,or OrderSet 34 | aabbac 35 | maps = {a:a} 36 | maps = {c:c} 37 | duplicated = {a,b} 38 | """ 39 | maps = {} 40 | duplicated = set() 41 | 42 | for char in s: 43 | if char in maps: 44 | maps.pop(char) 45 | duplicated.add(char) 46 | else: 47 | if char not in duplicated: 48 | maps[char] = char 49 | 50 | for char in maps: 51 | return char 52 | return " " 53 | 54 | 55 | if __name__ == "__main__": 56 | s = Solution() 57 | assert s.firstUniqChar("abaccdefff") == "b" 58 | assert s.firstUniqChar("aabbac") == "c" 59 | assert s.firstUniqChar("") == " " 60 | -------------------------------------------------------------------------------- /sword-means-offer/offer_53_i.py: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 53 - I. 在排序数组中查找数字 I 2 | # 统计一个数字在排序数组中出现的次数。 3 | 4 | 5 | # 示例 1: 6 | 7 | # 输入: nums = [5,7,7,8,8,10], target = 8 8 | # 输出: 2 9 | # 示例 2: 10 | 11 | # 输入: nums = [5,7,7,8,8,10], target = 6 12 | # 输出: 0 13 | 14 | 15 | # 提示: 16 | 17 | # 0 <= nums.length <= 105 18 | # -109 <= nums[i] <= 109 19 | # nums 是一个非递减数组 20 | # -109 <= target <= 109 21 | 22 | 23 | from typing import List 24 | 25 | 26 | class Solution: 27 | def search(self, nums: List[int], target: int) -> int: 28 | # [) 29 | left, right = 0, len(nums) 30 | while left < right: 31 | mid = left + (right - left) // 2 32 | if nums[mid] >= target: 33 | right = mid 34 | elif nums[mid] < target: 35 | left = mid + 1 36 | count = 0 37 | while left < len(nums) and nums[left] == target: 38 | count += 1 39 | left += 1 40 | return count 41 | 42 | 43 | if __name__ == "__main__": 44 | s = Solution() 45 | assert s.search([5, 7, 7, 8, 8, 10], 8) == 2 46 | assert s.search([5, 7, 7, 8, 8, 10], 7) == 2 47 | assert s.search([5, 7, 7, 8, 8, 10], 6) == 0 48 | -------------------------------------------------------------------------------- /sword-means-offer/offer_53_ii.py: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 53 - II. 0~n-1中缺失的数字 2 | # 一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。 3 | 4 | 5 | # 示例 1: 6 | 7 | # 输入: [0,1,3] 8 | # 输出: 2 9 | # 示例 2: 10 | 11 | # 输入: [0,1,2,3,4,5,6,7,9] 12 | # 输出: 8 13 | 14 | from typing import List 15 | 16 | 17 | class Solution: 18 | def missingNumber(self, nums: List[int]) -> int: 19 | # 123 20 | # 321 21 | # (1+3) * 3 22 | return (1 + len(nums)) * len(nums) // 2 - sum(nums) 23 | 24 | 25 | if __name__ == "__main__": 26 | s = Solution() 27 | assert s.missingNumber([0, 1, 3]) == 2 28 | assert s.missingNumber([0, 1, 2, 3, 4, 5, 6, 7, 9]) == 8 29 | -------------------------------------------------------------------------------- /sword-means-offer/offer_55_i.py: -------------------------------------------------------------------------------- 1 | from helper import TreeNode, create_binary_tree 2 | 3 | 4 | class Solution: 5 | def maxDepth(self, root: TreeNode) -> int: 6 | queue = [root] 7 | level = 0 8 | while queue: 9 | size = len(queue) 10 | cur_nums = [] 11 | for i in range(size): 12 | # 添加下一层的节点及收集当前层结果 13 | node = queue[i] 14 | if node: 15 | cur_nums.append(node.val) 16 | queue.append(node.left) 17 | queue.append(node.right) 18 | if cur_nums: 19 | level += 1 20 | queue = queue[size:] 21 | return level 22 | 23 | 24 | if __name__ == "__main__": 25 | s = Solution() 26 | root = create_binary_tree([3, 9, 20, None, None, 15, 7], 0) 27 | assert s.maxDepth(root) == 3 28 | root = create_binary_tree([], 0) 29 | assert s.maxDepth(root) == 0 30 | -------------------------------------------------------------------------------- /sword-means-offer/offer_55_ii.py: -------------------------------------------------------------------------------- 1 | from helper import TreeNode, create_binary_tree 2 | 3 | 4 | class Solution: 5 | # def maxDepth(self, root: TreeNode) -> int: 6 | # queue = [root] 7 | # level = 0 8 | # while queue: 9 | # size = len(queue) 10 | # cur_nums = [] 11 | # for i in range(size): 12 | # # 添加下一层的节点及收集当前层结果 13 | # node = queue[i] 14 | # if node: 15 | # cur_nums.append(node.val) 16 | # queue.append(node.left) 17 | # queue.append(node.right) 18 | # if cur_nums: 19 | # level += 1 20 | # queue = queue[size:] 21 | # return level 22 | 23 | def maxDepth(self, root: TreeNode) -> int: 24 | if root is None: 25 | return 0 26 | return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right)) 27 | 28 | def isBalanced(self, root: TreeNode) -> bool: 29 | if root is None: 30 | return True 31 | if abs(self.maxDepth(root.left) - self.maxDepth(root.right)) <= 1: 32 | return self.isBalanced(root.left) and self.isBalanced(root.right) 33 | return False 34 | 35 | 36 | if __name__ == "__main__": 37 | s = Solution() 38 | root = create_binary_tree([3, 9, 20, None, None, 15, 7], 0) 39 | assert s.isBalanced(root) is True 40 | root = create_binary_tree([1, 2, 2, 3, 3, None, None, 4, 4], 0) 41 | assert s.isBalanced(root) is False 42 | -------------------------------------------------------------------------------- /sword-means-offer/offer_56_i.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def singleNumbers(self, nums: List[int]) -> List[int]: 6 | """ 7 | (1)0001 8 | (6)0110 ^ 9 | ------- 10 | 0111 11 | 说明这两个不同的数,有三位是不一样的 12 | 取最后一位为 1 进行分组,可将数据分成两组 13 | 则这两组中分别时行异或运算可得出两个值 14 | """ 15 | ans = 0 16 | for num in nums: 17 | ans ^= num 18 | index = 0 19 | while ans & 1 == 0: 20 | index += 1 21 | ans >>= 1 22 | num1, num2 = 0, 0 23 | for num in nums: 24 | if (num >> index) & 1 == 1: 25 | num1 ^= num 26 | else: 27 | num2 ^= num 28 | return [num1, num2] 29 | 30 | 31 | if __name__ == "__main__": 32 | s = Solution() 33 | assert sorted(s.singleNumbers([4, 1, 4, 6])) == [1, 6] 34 | assert sorted(s.singleNumbers([1, 2, 10, 4, 1, 4, 3, 3])) == [2, 10] 35 | -------------------------------------------------------------------------------- /sword-means-offer/offer_56_ii.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | from typing import List 3 | 4 | 5 | class Solution: 6 | def singleNumber(self, nums: List[int]) -> int: 7 | counter = Counter(nums) 8 | for value, count in counter.items(): 9 | if count < 3: 10 | return value 11 | 12 | 13 | if __name__ == "__main__": 14 | s = Solution() 15 | assert s.singleNumber([3, 4, 3, 3]) == 4 16 | assert s.singleNumber([9, 1, 7, 9, 7, 9, 7]) == 1 17 | -------------------------------------------------------------------------------- /sword-means-offer/offer_58_ii.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def reverseLeftWords(self, s: str, n: int) -> str: 3 | return s[n:] + s[:n] 4 | 5 | 6 | if __name__ == "__main__": 7 | s = Solution() 8 | assert s.reverseLeftWords("abcdefg", 2) == "cdefgab" 9 | assert s.reverseLeftWords("lrloseumgh", 6) == "umghlrlose" 10 | -------------------------------------------------------------------------------- /sword-means-offer/offer_61.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def isStraight(self, nums: List[int]) -> bool: 6 | zeros = 0 7 | minimum = 100 8 | for num in nums: 9 | if num == 0: 10 | zeros += 1 11 | elif num < minimum: 12 | minimum = num 13 | counts = 0 14 | while True: 15 | if minimum in nums: 16 | counts += 1 17 | elif zeros > 0: 18 | counts += 1 19 | zeros -= 1 20 | else: 21 | break 22 | minimum += 1 23 | return counts == 5 24 | 25 | 26 | if __name__ == "__main__": 27 | s = Solution() 28 | assert s.isStraight([1, 2, 3, 4, 5]) is True 29 | assert s.isStraight([1, 2, 3, 4, 6]) is False 30 | assert s.isStraight([0, 0, 1, 2, 5]) is True 31 | -------------------------------------------------------------------------------- /sword-means-offer/offer_62.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def lastRemaining(self, n: int, m: int) -> int: 3 | if n == 1: 4 | return 0 5 | x = self.lastRemaining(n - 1, m) 6 | return (x + m) % n 7 | 8 | def lastRemaining(self, n: int, m: int) -> int: 9 | 10 | f = [0 for _ in range(n + 1)] 11 | f[1] = 0 12 | for i in range(2, n + 1): 13 | f[i] = (f[i - 1] + m) % i 14 | return f[n] 15 | 16 | 17 | if __name__ == "__main__": 18 | s = Solution() 19 | assert s.lastRemaining(5, 3) == 3 20 | assert s.lastRemaining(10, 17) == 2 21 | -------------------------------------------------------------------------------- /sword-means-offer/offer_63.py: -------------------------------------------------------------------------------- 1 | # 假设把某股票的价格按照时间先后顺序存储在数组中, 2 | # 请问买卖该股票一次可能获得的最大利润是多少? 3 | # 4 | 5 | # 示例 1: 6 | 7 | # 输入: [7,1,5,3,6,4] 8 | # 输出: 5 9 | # 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 10 | # 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。 11 | # 示例 2: 12 | 13 | # 输入: [7,6,4,3,1] 14 | # 输出: 0 15 | # 解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。 16 | # 17 | 18 | # 限制: 19 | 20 | # 0 <= 数组长度 <= 10^5 21 | 22 | 23 | import sys 24 | from typing import List 25 | 26 | 27 | class Solution: 28 | # def maxProfit(self, prices: List[int]) -> int: 29 | # # dp[i] 表示第i天卖出所获得的利润 30 | # dp = [0 for _ in prices] 31 | # for i in range(1, len(prices)): 32 | # dp[i] = max(0, dp[i-1]) - prices[i-1] + prices[i] 33 | # return max(dp, default=0) 34 | 35 | # def maxProfit(self, prices: List[int]) -> int: 36 | # # 优化: current 表示第i天卖出所获得的利润 37 | # current = 0 38 | # maxs = 0 39 | # for i in range(1, len(prices)): 40 | # current = max(0, current) - prices[i-1] + prices[i] 41 | # maxs = max(maxs, current) 42 | # return maxs 43 | 44 | def maxProfit(self, prices: List[int]) -> int: 45 | mins = sys.maxsize 46 | maxs = 0 47 | for price in prices: 48 | mins = min(mins, price) 49 | maxs = max(maxs, price - mins) 50 | return maxs 51 | 52 | 53 | if __name__ == "__main__": 54 | s = Solution() 55 | assert s.maxProfit([]) == 0 56 | assert s.maxProfit([7, 1, 5, 3, 6, 4]) == 5 57 | assert s.maxProfit([7, 6, 4, 3, 1]) == 0 58 | -------------------------------------------------------------------------------- /sword-means-offer/offer_66.py: -------------------------------------------------------------------------------- 1 | # 给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1], 2 | # 其中 B[i] 的值是数组 A 中除了下标 i 以外的元素的积, 3 | # 即 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。 4 | 5 | # 6 | 7 | # 示例: 8 | 9 | # 输入: [1,2,3,4,5] 10 | # 输出: [120,60,40,30,24] 11 | # 12 | 13 | # 提示: 14 | 15 | # 所有元素乘积之和不会溢出 32 位整数 16 | # a.length <= 100000 17 | 18 | 19 | from typing import List 20 | 21 | 22 | class Solution: 23 | def constructArr(self, a: List[int]) -> List[int]: 24 | prefix_muls = [0 for _ in a] 25 | suffix_muls = [0 for _ in a] 26 | 27 | tmp = 1 28 | for i in range(len(a)): 29 | prefix_muls[i] = tmp 30 | tmp *= a[i] 31 | 32 | tmp = 1 33 | for i in reversed(range(len(a))): 34 | suffix_muls[i] = tmp 35 | tmp *= a[i] 36 | 37 | return [prefix_mul * suffix_mul for prefix_mul, suffix_mul in zip(prefix_muls, suffix_muls)] 38 | 39 | 40 | if __name__ == "__main__": 41 | s = Solution() 42 | assert s.constructArr([]) == [] 43 | assert s.constructArr([12]) == [1] 44 | assert s.constructArr([1, 2]) == [2, 1] 45 | assert s.constructArr([1, 2, 3, 4, 5]) == [120, 60, 40, 30, 24] 46 | -------------------------------------------------------------------------------- /sword-means-offer/offer_68_i.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from helper import TreeNode, create_binary_tree 4 | 5 | 6 | class Solution: 7 | # def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode: 8 | # # 递归 9 | # if root.val > p.val and root.val > q.val: 10 | # return self.lowestCommonAncestor(root.left, p, q) 11 | # elif root.val < p.val and root.val < q.val: 12 | # return self.lowestCommonAncestor(root.right, p, q) 13 | # else: 14 | # return root 15 | 16 | def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> Optional[TreeNode]: 17 | # 迭代 18 | node = root 19 | while node: 20 | if node.val > p.val and node.val > q.val: 21 | node = node.left 22 | elif node.val < p.val and node.val < q.val: 23 | node = node.right 24 | else: 25 | break 26 | return node 27 | 28 | 29 | if __name__ == "__main__": 30 | s = Solution() 31 | root = create_binary_tree([6, 2, 8, 0, 4, 7, 9, None, None, 3, 5], 0) 32 | assert s.lowestCommonAncestor(root, TreeNode(2), TreeNode(8)).val == 6 33 | assert s.lowestCommonAncestor(root, TreeNode(2), TreeNode(4)).val == 2 34 | root = create_binary_tree([6, 2], 0) 35 | assert s.lowestCommonAncestor(root, TreeNode(2), TreeNode(6)).val == 6 36 | -------------------------------------------------------------------------------- /weekly-contest/121d/p1_2996.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | """https://leetcode.cn/problems/smallest-missing-integer-greater-than-sequential-prefix-sum/""" 6 | 7 | def missingInteger(self, nums: List[int]) -> int: 8 | prefix_sum = nums[0] 9 | for i in range(1, len(nums)): 10 | if nums[i] == nums[i - 1] + 1: 11 | prefix_sum += nums[i] 12 | else: 13 | break 14 | temp = set(nums) 15 | while prefix_sum in temp: 16 | prefix_sum += 1 17 | return prefix_sum 18 | 19 | 20 | if __name__ == "__main__": 21 | assert Solution().missingInteger([1, 2, 3, 2, 5]) == 6 22 | assert Solution().missingInteger([3, 4, 5, 1, 12, 14, 13]) == 15 23 | -------------------------------------------------------------------------------- /weekly-contest/121d/p2_2997.py: -------------------------------------------------------------------------------- 1 | from functools import reduce 2 | from typing import List 3 | 4 | 5 | class Solution: 6 | def minOperations(self, nums: List[int], k: int) -> int: 7 | value = reduce(lambda x, y: x ^ y, nums) ^ k 8 | count = 0 9 | while value: 10 | if value & 1: 11 | count += 1 12 | value >>= 1 13 | return count 14 | 15 | 16 | if __name__ == "__main__": 17 | assert Solution().minOperations([2, 1, 3, 4], 1) == 2 18 | assert Solution().minOperations([2, 0, 2, 0], 0) == 0 19 | assert Solution().minOperations([4], 7) == 2 20 | -------------------------------------------------------------------------------- /weekly-contest/121d/p4_2999.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def numberOfPowerfulInt(self, start: int, finish: int, limit: int, s: str) -> int: 3 | # TODO: 未完成 4 | # 枚举会超时 5 | # 组合与排列,但如何排队最高位与 limit 相同但又不在 finish 之内的数呢?似乎数量级也在 10**14 会超时 6 | ... 7 | 8 | 9 | if __name__ == "__main__": 10 | assert Solution().numberOfPowerfulInt(start=1, finish=6000, limit=4, s="124") == 5 11 | assert Solution().numberOfPowerfulInt(start=15, finish=215, limit=6, s="10") == 2 12 | assert Solution().numberOfPowerfulInt(start=1000, finish=2000, limit=4, s="3000") == 0 13 | -------------------------------------------------------------------------------- /weekly-contest/122d/p1_3009.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def minimumCost(self, nums: List[int]) -> int: 6 | ans = nums[0] 7 | nums = nums[1:] 8 | x1 = min(nums) 9 | nums.remove(x1) 10 | ans += x1 11 | x2 = min(nums) 12 | ans += x2 13 | nums.remove(x2) 14 | return ans 15 | 16 | 17 | if __name__ == "__main__": 18 | assert Solution().minimumCost(nums=[1, 2, 3, 12]) == 6 19 | assert Solution().minimumCost(nums=[10, 3, 1, 1]) == 12 20 | assert Solution().minimumCost(nums=[5, 4, 3]) == 12 21 | -------------------------------------------------------------------------------- /weekly-contest/122d/p4_3012.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://leetcode.cn/problems/divide-an-array-into-subarrays-with-minimum-cost-ii/description/ 3 | """ 4 | from typing import List 5 | 6 | 7 | class Solution: 8 | def minimumCost(self, nums: List[int], k: int, dist: int) -> int: 9 | # TODO: 10 | ... 11 | 12 | 13 | if __name__ == "__main__": 14 | assert Solution().minimumCost(nums=[1, 3, 2, 6, 4, 2], k=3, dist=3) == 5 15 | assert Solution().minimumCost(nums=[10, 1, 2, 2, 2, 1], k=4, dist=3) == 15 16 | assert Solution().minimumCost(nums=[10, 8, 18, 9], k=3, dist=1) == 36 17 | -------------------------------------------------------------------------------- /weekly-contest/379/p1_3000.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def areaOfMaxDiagonal(self, dimensions: List[List[int]]) -> int: 6 | max_diagonal = 0 7 | max_area = 0 8 | for x, y in dimensions: 9 | diagonal = x * x + y * y 10 | if diagonal > max_diagonal: 11 | max_diagonal = diagonal 12 | max_area = x * y 13 | if diagonal == max_diagonal: 14 | max_area = max(max_area, x * y) 15 | return max_area 16 | 17 | 18 | if __name__ == "__main__": 19 | assert Solution().areaOfMaxDiagonal([[1, 1], [2, 2], [3, 3]]) == 9 20 | assert Solution().areaOfMaxDiagonal(dimensions=[[9, 3], [8, 6]]) == 48 21 | assert Solution().areaOfMaxDiagonal(dimensions=[[3, 4], [4, 3]]) == 12 22 | -------------------------------------------------------------------------------- /weekly-contest/379/p2_3001.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def minMovesToCaptureTheQueen(self, a: int, b: int, c: int, d: int, e: int, f: int) -> int: 3 | # 只有 1 或者 2(抽将也算) 步 4 | # 与车同行 5 | if a == e: 6 | if c != a or not (b < d < f or f < d < b): 7 | return 1 8 | # 与车同列 9 | if b == f: 10 | if d != b or not (a < c < e or e < c < a): 11 | return 1 12 | # 与象同对角线 13 | if f - e == d - c: 14 | if b - a != f - e or not (c < a < e or e < a < c): 15 | return 1 16 | if f + e == d + c: 17 | if b + a != f + e or not (c < a < e or e < a < c): 18 | return 1 19 | # 其它情况 20 | return 2 21 | 22 | 23 | if __name__ == "__main__": 24 | assert Solution().minMovesToCaptureTheQueen(a=1, b=1, c=8, d=8, e=2, f=3) == 2 25 | assert Solution().minMovesToCaptureTheQueen(a=5, b=3, c=3, d=4, e=5, f=2) == 1 26 | -------------------------------------------------------------------------------- /weekly-contest/379/p4_3003.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.cn/problems/maximize-the-number-of-partitions-after-operations/description/ 2 | 3 | 4 | class Solution: 5 | def maxPartitionsAfterOperations(self, s: str, k: int) -> int: 6 | # TODO: 7 | ... 8 | 9 | 10 | if __name__ == "__main__": 11 | assert Solution().maxPartitionsAfterOperations(s="accca", k=2) == 3 12 | assert Solution().maxPartitionsAfterOperations(s="aabaab", k=3) == 1 13 | assert Solution().maxPartitionsAfterOperations(s="xxyz", k=1) == 4 14 | -------------------------------------------------------------------------------- /weekly-contest/380/p1_3005.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | from typing import List 3 | 4 | 5 | class Solution: 6 | def maxFrequencyElements(self, nums: List[int]) -> int: 7 | counter = Counter(nums) 8 | _, times = counter.most_common(1)[0] 9 | return sum(value for key, value in counter.items() if value == times) 10 | 11 | 12 | if __name__ == "__main__": 13 | assert Solution().maxFrequencyElements(nums=[1, 2, 4]) == 3 14 | assert Solution().maxFrequencyElements(nums=[1, 2, 2, 3, 1, 4]) == 4 15 | assert Solution().maxFrequencyElements(nums=[1, 2, 3, 4, 5]) == 5 16 | -------------------------------------------------------------------------------- /weekly-contest/380/p2_3006.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def beautifulIndices(self, s: str, a: str, b: str, k: int) -> List[int]: 6 | a_indexes = self._find_all_indexes(s, a) 7 | b_indexes = self._find_all_indexes(s, b) 8 | ans = [] 9 | for a_index in a_indexes: 10 | if self._find_abs_in_k(a_index, b_indexes, k): 11 | ans.append(a_index) 12 | return ans 13 | 14 | def _find_abs_in_k(self, a_index, b_indexes, k): 15 | for b_index in b_indexes: 16 | if abs(a_index - b_index) <= k: 17 | return True 18 | return False 19 | 20 | def _find_all_indexes(self, text: str, substring: str): 21 | indexes = [] 22 | start = 0 23 | 24 | while True: 25 | try: 26 | index = text.index(substring, start) 27 | indexes.append(index) 28 | start = index + 1 29 | except ValueError: 30 | break 31 | 32 | return indexes 33 | 34 | 35 | if __name__ == "__main__": 36 | assert Solution().beautifulIndices(s="isawsquirrelnearmysquirrelhouseohmy", a="my", b="squirrel", k=15) == [16, 33] 37 | assert Solution().beautifulIndices(s="abcd", a="a", b="a", k=4) == [0] 38 | -------------------------------------------------------------------------------- /weekly-contest/380/p3_3007.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findMaximumNumber(self, k: int, x: int) -> int: 3 | # TODO: 4 | ... 5 | 6 | 7 | if __name__ == "__main__": 8 | assert Solution().findMaximumNumber(k=9, x=1) == 6 9 | assert Solution().findMaximumNumber(k=7, x=2) == 9 10 | -------------------------------------------------------------------------------- /weekly-contest/380/p4_3008.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def beautifulIndices(self, s: str, a: str, b: str, k: int) -> List[int]: 6 | # TODO: 7 | ... 8 | 9 | 10 | if __name__ == "__main__": 11 | assert Solution().beautifulIndices(s="isawsquirrelnearmysquirrelhouseohmy", a="my", b="squirrel", k=15) == [16, 33] 12 | assert Solution().beautifulIndices(s="abcd", a="a", b="a", k=4) == [0] 13 | -------------------------------------------------------------------------------- /weekly-contest/381/p1_100191.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | 3 | 4 | class Solution: 5 | def minimumPushes(self, word: str) -> int: 6 | counter = Counter(word) 7 | times = 1 8 | numbers = 0 9 | ans = 0 10 | while len(counter): 11 | char, count = counter.most_common(1)[0] 12 | ans += count * times 13 | numbers += 1 14 | if numbers == 8: 15 | times += 1 16 | numbers = 0 17 | counter.pop(char) 18 | return ans 19 | 20 | 21 | if __name__ == "__main__": 22 | assert Solution().minimumPushes(word="abcde") == 5 23 | assert Solution().minimumPushes(word="xycdefghij") == 12 24 | -------------------------------------------------------------------------------- /weekly-contest/381/p2_100188.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | from typing import List 3 | 4 | 5 | class Solution: 6 | def countOfPairs(self, n: int, x: int, y: int) -> List[int]: 7 | distances = [[n * 2 + 1 for _ in range(n)] for _ in range(n)] 8 | for i in range(n): 9 | if i + 1 < n: 10 | distances[i][i + 1] = 1 11 | if i - 1 >= 0: 12 | distances[i][i - 1] = 1 13 | if x != y: 14 | distances[x - 1][y - 1] = 1 15 | distances[y - 1][x - 1] = 1 16 | for k in range(n): 17 | for i in range(n): 18 | for j in range(n): 19 | if i != j and distances[i][j] > distances[i][k] + distances[k][j]: 20 | distances[i][j] = distances[i][k] + distances[k][j] 21 | counter = Counter() 22 | for i in range(n): 23 | for j in range(n): 24 | if i != j: 25 | counter[distances[i][j]] += 1 26 | ans = [] 27 | for i in range(n): 28 | ans.append(counter[i + 1]) 29 | return ans 30 | 31 | 32 | if __name__ == "__main__": 33 | assert Solution().countOfPairs(n=3, x=1, y=3) == [6, 0, 0] 34 | assert Solution().countOfPairs(n=4, x=1, y=1) == [6, 4, 2, 0] 35 | assert Solution().countOfPairs(n=5, x=2, y=4) == [10, 8, 2, 0, 0] 36 | assert Solution().countOfPairs(n=6, x=2, y=6) == [12, 14, 4, 0, 0, 0] 37 | assert Solution().countOfPairs(n=1, x=1, y=1) == [0] 38 | -------------------------------------------------------------------------------- /weekly-contest/381/p3_100192.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | 3 | 4 | class Solution: 5 | def minimumPushes(self, word: str) -> int: 6 | counter = Counter(word) 7 | times = 1 8 | numbers = 0 9 | ans = 0 10 | while len(counter): 11 | char, count = counter.most_common(1)[0] 12 | ans += count * times 13 | numbers += 1 14 | if numbers == 8: 15 | times += 1 16 | numbers = 0 17 | counter.pop(char) 18 | return ans 19 | 20 | 21 | if __name__ == "__main__": 22 | assert Solution().minimumPushes(word="abcde") == 5 23 | assert Solution().minimumPushes(word="xycdefghij") == 12 24 | assert Solution().minimumPushes(word="aabbccddeeffgghhiiiiii") == 24 25 | -------------------------------------------------------------------------------- /weekly-contest/381/p4_100213.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def countOfPairs(self, n: int, x: int, y: int) -> List[int]: 6 | # TODO: 7 | # distances = {} 8 | # for i in range(1, n + 1): 9 | # for j in range(i + 1, n + 1): 10 | # distances[(i, j)] = j - i 11 | # distances[(j, i)] = j - i 12 | # if x != y: 13 | # for i in range(y, n + 1): 14 | # distances[(x, i)] = 1 + (i - y) 15 | # distances[(i, x)] = 1 + (i - y) 16 | # for i in range(x, 0, -1): 17 | # distances[(y, i)] = 1 + (x - i) 18 | # distances[(i, y)] = 1 + (x - i) 19 | # print("[/Users/hj.tian/github/leetcode/weekly-contest/381/p2_100188.py:10] distances: ", distances) 20 | # ans = [] 21 | # for i in range(1, n + 1): 22 | # count = sum(1 if value == i else 0 for value in distances.values()) 23 | # ans.append(count) 24 | # print("[/Users/hj.tian/github/leetcode/weekly-contest/381/p2_100188.py:18] ans: ", ans) 25 | # return ans 26 | ... 27 | 28 | 29 | if __name__ == "__main__": 30 | assert Solution().countOfPairs(n=3, x=1, y=3) == [6, 0, 0] 31 | assert Solution().countOfPairs(n=4, x=1, y=1) == [6, 4, 2, 0] 32 | assert Solution().countOfPairs(n=5, x=2, y=4) == [10, 8, 2, 0, 0] 33 | assert Solution().countOfPairs(n=6, x=2, y=6) == [12, 14, 4, 0, 0, 0] 34 | assert Solution().countOfPairs(n=1, x=1, y=1) == [0] 35 | -------------------------------------------------------------------------------- /weekly-contest/382/p1_100215.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def countKeyChanges(self, s: str) -> int: 3 | ans = 0 4 | index = 0 5 | s = s.lower() 6 | pre_char = s[0] 7 | while index < len(s): 8 | if s[index] != pre_char: 9 | ans += 1 10 | pre_char = s[index] 11 | index += 1 12 | return ans 13 | 14 | 15 | if __name__ == "__main__": 16 | assert Solution().countKeyChanges("abc") == 2 17 | assert Solution().countKeyChanges("aAbBcC") == 2 18 | assert Solution().countKeyChanges("AaAaAaaA") == 0 19 | -------------------------------------------------------------------------------- /weekly-contest/382/p2_100206.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def maximumLength(self, nums: List[int]) -> int: 6 | # TODO: 7 | ... 8 | 9 | 10 | if __name__ == "__main__": 11 | assert Solution().maximumLength(nums=[5, 4, 1, 2, 2]) == 3 12 | assert Solution().maximumLength(nums=[1, 3, 2, 4]) == 1 13 | -------------------------------------------------------------------------------- /weekly-contest/382/p3_100195.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def flowerGame(self, n: int, m: int) -> int: 3 | return n * m // 2 4 | 5 | 6 | if __name__ == "__main__": 7 | assert Solution().flowerGame(3, 2) == 3 8 | assert Solution().flowerGame(1, 1) == 0 9 | -------------------------------------------------------------------------------- /weekly-contest/382/p4_100179.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def minOrAfterOperations(self, nums: List[int], k: int) -> int: 6 | # TODO: 7 | ... 8 | 9 | 10 | if __name__ == "__main__": 11 | assert Solution().minOrAfterOperations(nums=[3, 5, 3, 2, 7], k=2) == 3 12 | assert Solution().minOrAfterOperations(nums=[7, 3, 15, 14, 2, 8], k=4) == 2 13 | assert Solution().minOrAfterOperations(nums=[10, 7, 10, 3, 9, 14, 9, 4], k=1) == 15 14 | --------------------------------------------------------------------------------