├── .gitignore
├── .travis.yml
├── CNAME
├── LANGS.md
├── README.md
├── book.json
├── codes
└── algorithm-java
│ ├── .gitignore
│ ├── pom.xml
│ └── src
│ ├── main
│ ├── java
│ │ └── basic
│ │ │ └── DataStructure.java
│ └── resources
│ │ └── log4j.properties
│ └── test
│ └── java
│ └── basic
│ ├── DataStructureTest.java
│ ├── QueueTest.java
│ └── StackTest.java
├── conf
├── 10-latin.conf
├── 15-noto-cjksc.conf
├── 20-noto-cjk.conf
└── qiniu_sync.json
├── contributing.md
├── cover.jpg
├── cover_small.jpg
├── en
├── README.md
├── SUMMARY.md
├── basics_data_structure
│ ├── README.md
│ └── string.md
├── basics_sorting
│ └── quick_sort.md
├── binary_search
│ └── search_in_rotated_sorted_array.md
├── cover.jpg
├── cover_small.jpg
├── faq
│ ├── README.md
│ └── guidelines_for_contributing.md
├── integer_array
│ ├── kth_largest_element.md
│ └── partition_array_by_odd_and_even.md
├── linked_list
│ ├── README.md
│ └── reverse_linked_list.md
├── part_i_basics
│ └── README.md
├── string
│ ├── README.md
│ └── strstr.md
├── styles
│ └── website.css
└── tags.md
├── scripts
├── check_summary.py
├── gitls.sh
├── main.py
├── parse_md.py
├── rename_ebook.sh
├── sitemap
│ ├── __init__.py
│ └── templates
│ │ └── sitemap.xml
├── sitemap_gen.py
└── util.py
├── shared-files
├── README.md
├── SUMMARY.md
├── docs
│ └── oj_templates
│ │ └── cpp_templates.cpp
└── images
│ ├── Binary-reflected_Gray_code_construction.png
│ ├── Heapsort-example.gif
│ ├── alipay_billryan_qr15x15.jpg
│ ├── binary_tree_summary.png
│ ├── binary_tree_traversal.png
│ ├── bipatial_graph_part_i_1.png
│ ├── bipatial_graph_part_i_2.png
│ ├── bubble_sort.gif
│ ├── copy_list_with_random_pointer.jpg
│ ├── gitbook_editor.png
│ ├── huffman_algorithm.gif
│ ├── insertion_sort.gif
│ ├── insertion_sort_list.png
│ ├── linked_list_cycle.png
│ ├── linked_list_cycle_ii.png
│ ├── linked_list_summary.png
│ ├── linked_list_summary_en.png
│ ├── merge_sort.gif
│ ├── problem_b_professor_qs_software.png
│ ├── qsort1.png
│ ├── qsort2.png
│ ├── qsort3.gif
│ ├── remove_duplicates_from_sorted_list.jpg
│ ├── resume-zh_CN.png
│ ├── reverse_linked_list_i.jpg
│ ├── rotated_array.png
│ ├── selection_sort.gif
│ ├── subsets.jpg
│ ├── topological-sorting.jpeg
│ ├── topological_sorting.jpeg
│ ├── tree_diameter.gif
│ ├── valid-sudoku.png
│ └── wechat_billryan_qr15x15.jpg
├── zh-hans
├── GLOSSARY.md
├── README.md
├── SUMMARY.md
├── appendix_i_interview_and_resume
│ ├── README.md
│ ├── interview.md
│ └── resume.md
├── basics_algorithm
│ ├── README.md
│ ├── binary_search.md
│ ├── bitmap.md
│ ├── divide_and_conquer.md
│ ├── knapsack.md
│ ├── math
│ │ ├── README.md
│ │ ├── gcd.md
│ │ └── prime.md
│ └── probability
│ │ ├── README.md
│ │ └── shuffle.md
├── basics_data_structure
│ ├── README.md
│ ├── binary_tree.md
│ ├── graph.md
│ ├── heap.md
│ ├── huffman_compression.md
│ ├── linked_list.md
│ ├── map.md
│ ├── queue.md
│ ├── set.md
│ ├── stack.md
│ └── string.md
├── basics_misc
│ ├── README.md
│ └── bit_manipulation.md
├── basics_sorting
│ ├── README.md
│ ├── bubble_sort.md
│ ├── bucket_sort.md
│ ├── counting_sort.md
│ ├── heap_sort.md
│ ├── insertion_sort.md
│ ├── merge_sort.md
│ ├── quick_sort.md
│ ├── radix_sort.md
│ └── selection_sort.md
├── bigdata
│ ├── README.md
│ ├── k_closest_points.md
│ ├── top_k_frequent_words.md
│ ├── top_k_frequent_words_ii.md
│ ├── top_k_frequent_words_map_reduce.md
│ ├── top_k_largest_numbers.md
│ └── top_k_largest_numbers_ii.md
├── binary_search
│ ├── README.md
│ ├── find_minimum_in_rotated_sorted_array.md
│ ├── find_minimum_in_rotated_sorted_array_ii.md
│ ├── find_peak_element.md
│ ├── first_bad_version.md
│ ├── first_position_of_target.md
│ ├── median_of_two_sorted_arrays.md
│ ├── search_a_2d_matrix.md
│ ├── search_a_2d_matrix_ii.md
│ ├── search_for_a_range.md
│ ├── search_in_rotated_sorted_array.md
│ ├── search_in_rotated_sorted_array_ii.md
│ ├── search_insert_position.md
│ ├── sqrt_x.md
│ └── wood_cut.md
├── binary_search_tree
│ ├── README.md
│ ├── binary_search_tree_iterator.md
│ ├── convert_sorted_array_to_binary_search_tree.md
│ ├── convert_sorted_list_to_binary_search_tree.md
│ ├── insert_node_in_a_binary_search_tree.md
│ ├── minimum_absolute_difference_in_bst.md
│ ├── search_range_in_binary_search_tree.md
│ └── validate_binary_search_tree.md
├── binary_tree
│ ├── README.md
│ ├── balanced_binary_tree.md
│ ├── binary_tree_inorder_traversal.md
│ ├── binary_tree_level_order_traversal.md
│ ├── binary_tree_level_order_traversal_ii.md
│ ├── binary_tree_maximum_path_sum.md
│ ├── binary_tree_postorder_traversal.md
│ ├── binary_tree_preorder_traversal.md
│ ├── binary_tree_serialization.md
│ ├── binary_tree_zigzag_level_order_traversal.md
│ ├── construct_binary_tree_from_inorder_and_postorder_traversal.md
│ ├── construct_binary_tree_from_preorder_and_inorder_traversal.md
│ ├── diameter_of_a_binary_tree.md
│ ├── invert_binary_tree.md
│ ├── lowest_common_ancestor.md
│ ├── maximum_depth_of_binary_tree.md
│ └── subtree.md
├── cover.jpg
├── cover_small.jpg
├── data_structure
│ ├── README.md
│ ├── heapify.md
│ ├── implement_queue_by_two_stacks.md
│ ├── longest_words.md
│ ├── min_stack.md
│ └── sliding_window_maximum.md
├── dynamic_programming
│ ├── README.md
│ ├── backpack.md
│ ├── backpack_ii.md
│ ├── best_time_to_buy_and_sell_stock.md
│ ├── best_time_to_buy_and_sell_stock_ii.md
│ ├── best_time_to_buy_and_sell_stock_iii.md
│ ├── best_time_to_buy_and_sell_stock_iv.md
│ ├── climbing_stairs.md
│ ├── distinct_subsequences.md
│ ├── edit_distance.md
│ ├── interleaving_string.md
│ ├── jump_game.md
│ ├── jump_game_ii.md
│ ├── longest_common_subsequence.md
│ ├── longest_increasing_continuous_subsequence.md
│ ├── longest_increasing_continuous_subsequence_ii.md
│ ├── longest_increasing_subsequence.md
│ ├── matrix.md
│ ├── maximal_square.md
│ ├── maximum_subarray.md
│ ├── maximum_subarray_ii.md
│ ├── minimum_path_sum.md
│ ├── palindrome_partitioning_ii.md
│ ├── triangle.md
│ ├── unique_paths.md
│ ├── unique_paths_ii.md
│ └── word_break.md
├── exhaustive_search
│ ├── README.md
│ ├── combination_sum.md
│ ├── combination_sum_ii.md
│ ├── combinations.md
│ ├── minimum_depth_of_binary_tree.md
│ ├── next_permutation.md
│ ├── palindrome_partitioning.md
│ ├── permutation_index.md
│ ├── permutation_index_ii.md
│ ├── permutation_sequence.md
│ ├── permutations.md
│ ├── permutations_ii.md
│ ├── previous_permuation.md
│ ├── subsets.md
│ ├── unique_binary_search_trees_ii.md
│ ├── unique_subsets.md
│ └── word_search.md
├── faq
│ ├── README.md
│ └── guidelines_for_contributing.md
├── google_apac
│ ├── README.md
│ ├── google_apac_2015_round_b
│ │ ├── A-large-practice.in
│ │ ├── A-small-practice.in
│ │ ├── README.md
│ │ ├── Solution.java
│ │ └── problem_a_password_attacker.md
│ └── google_apac_2016_round_d
│ │ ├── A-large-practice.in
│ │ ├── A-small-practice.in
│ │ ├── README.md
│ │ ├── Solution.java
│ │ └── problem_a_dynamic_grid.md
├── graph
│ ├── README.md
│ ├── bipartial_graph_part_i.md
│ ├── find_the_connected_component_in_the_undirected_graph.md
│ ├── route_between_two_nodes_in_graph.md
│ ├── topological_sorting.md
│ └── word_ladder.md
├── integer_array
│ ├── 2_sum.md
│ ├── 3_sum.md
│ ├── 3_sum_closest.md
│ ├── README.md
│ ├── first_missing_positive.md
│ ├── kth_largest_element.md
│ ├── median.md
│ ├── merge_sorted_array.md
│ ├── merge_sorted_array_ii.md
│ ├── partition_array.md
│ ├── partition_array_by_odd_and_even.md
│ ├── product_of_array_exclude_itself.md
│ ├── recover_rotated_sorted_array.md
│ ├── remove_duplicates_from_sorted_array.md
│ ├── remove_duplicates_from_sorted_array_ii.md
│ ├── remove_element.md
│ ├── subarray_sum_closest.md
│ ├── subarray_sum_k.md
│ └── zero_sum_subarray.md
├── interview
│ ├── facebook_interview.md
│ └── google_interview.md
├── linked_list
│ ├── README.md
│ ├── add_two_numbers.md
│ ├── copy_list_with_random_pointer.md
│ ├── insertion_sort_list.md
│ ├── linked_list_cycle.md
│ ├── linked_list_cycle_ii.md
│ ├── lru_cache.md
│ ├── merge_k_sorted_lists.md
│ ├── merge_two_sorted_lists.md
│ ├── palindrome_linked_list.md
│ ├── partition_list.md
│ ├── remove_duplicates_from_an_unsorted_linked_list.md
│ ├── remove_duplicates_from_sorted_list.md
│ ├── remove_duplicates_from_sorted_list_ii.md
│ ├── remove_linked_list_elements.md
│ ├── remove_nth_node_from_end_of_list.md
│ ├── reorder_list.md
│ ├── reverse_linked_list.md
│ ├── reverse_linked_list_ii.md
│ ├── rotate_list.md
│ ├── sort_list.md
│ ├── swap_nodes_in_pairs.md
│ └── two_lists_sum_advanced.md
├── math_and_bit_manipulation
│ ├── README.md
│ ├── a_plus_b_problem.md
│ ├── count_1_in_binary.md
│ ├── digit_counts.md
│ ├── factorial_trailing_zeroes.md
│ ├── fast_power.md
│ ├── fibonacci.md
│ ├── flip_bits.md
│ ├── happy_number.md
│ ├── hash_function.md
│ ├── majority_number.md
│ ├── majority_number_ii.md
│ ├── majority_number_iii.md
│ ├── o1_check_power_of_2.md
│ ├── palindrome_number.md
│ ├── plus_one.md
│ ├── print_numbers_by_recursion.md
│ ├── single_number.md
│ ├── single_number_ii.md
│ ├── single_number_iii.md
│ ├── task_scheduler.md
│ ├── ugly_number.md
│ ├── unique_binary_search_trees.md
│ └── update_bits.md
├── microsoft
│ ├── README.md
│ ├── mstest2015april
│ │ ├── README.md
│ │ ├── problem_a_magic_box.md
│ │ ├── problem_b_professor_qs_software.md
│ │ ├── problem_c_islands_travel.md
│ │ └── problem_d_recruitment.md
│ ├── mstest2015april2
│ │ ├── README.md
│ │ ├── problem_a_lucky_substrings.md
│ │ ├── problem_b_numeric_keypad.md
│ │ └── problem_c_spring_outing.md
│ └── mstest2015sept2
│ │ ├── README.md
│ │ └── problem_a_farthest_point.md
├── part_i_basics
│ └── README.md
├── part_ii_coding
│ └── README.md
├── part_iii_contest
│ └── README.md
├── problem_misc
│ ├── README.md
│ ├── add_binary.md
│ ├── continuous_subarray_sum.md
│ ├── continuous_subarray_sum_ii.md
│ ├── find_the_missing_number.md
│ ├── gray_code.md
│ ├── insert_interval.md
│ ├── longest_consecutive_sequence.md
│ ├── matrix_zigzag_traversal.md
│ ├── merge_intervals.md
│ ├── minimum_subarray.md
│ ├── minimum_window_substring.md
│ ├── nuts_and_bolts_problem.md
│ ├── reverse_integer.md
│ ├── string_to_integer.md
│ └── valid_sudoku.md
├── string
│ ├── README.md
│ ├── compare_strings.md
│ ├── count_and_say.md
│ ├── group_anagrams.md
│ ├── length_of_last_word.md
│ ├── longest_common_substring.md
│ ├── longest_palindromic_substring.md
│ ├── reverse_words_in_a_string.md
│ ├── rotate_string.md
│ ├── space_replacement.md
│ ├── strstr.md
│ ├── two_strings_are_anagrams.md
│ ├── valid_palindrome.md
│ └── wildcard_matching.md
├── styles
│ └── website.css
└── tags.md
└── zh-tw
├── README.md
├── SUMMARY.md
├── appendix_i_interview_and_resume
└── README.md
├── basics_algorithm
├── README.md
├── binary_search.md
├── bitmap.md
├── divide_and_conquer.md
├── math
│ ├── README.md
│ ├── gcd.md
│ └── prime.md
└── probability
│ ├── README.md
│ └── shuffle.md
├── basics_data_structure
├── README.md
├── binary_tree.md
├── graph.md
├── heap.md
├── huffman_compression.md
├── linked_list.md
├── map.md
├── priority_queue.md
├── queue.md
├── set.md
├── stack.md
└── string.md
├── basics_misc
├── README.md
└── bit_manipulation.md
├── basics_sorting
├── README.md
├── bubble_sort.md
├── bucket_sort.md
├── counting_sort.md
├── heap_sort.md
├── insertion_sort.md
├── merge_sort.md
├── radix_sort.md
└── selection_sort.md
├── binary_search
├── README.md
├── binary_search.md
├── find_peak_element.md
├── first_bad_version.md
├── search_for_a_range.md
├── search_insert_position.md
└── sqrt_x.md
├── binary_search_tree
├── README.md
└── insert_node_in_a_binary_search_tree.md
├── binary_tree
├── README.md
├── binary_tree_inorder_traversal.md
├── binary_tree_level_order_traversal.md
├── binary_tree_level_order_traversal_ii.md
├── binary_tree_postorder_traversal.md
├── binary_tree_preorder_traversal.md
├── invert_binary_tree.md
└── maximum_depth_of_binary_tree.md
├── cover.jpg
├── cover_small.jpg
├── data_structure
└── README.md
├── dynamic_programming
├── README.md
├── backpack.md
├── climbing_stairs.md
└── triangle.md
├── exhaustive_search
├── README.md
├── minimum_depth_of_binary_tree.md
├── next_permutation.md
└── subsets.md
├── faq
├── README.md
└── guidelines_for_contributing.md
├── graph
└── README.md
├── integer_array
├── 2_sum.md
├── 3_sum.md
├── 3_sum_closest.md
├── README.md
├── first_missing_positive.md
├── merge_sorted_array.md
├── merge_sorted_array_ii.md
├── remove_duplicates_from_sorted_array.md
├── remove_duplicates_from_sorted_array_ii.md
└── remove_element.md
├── linked_list
├── README.md
├── linked_list_cycle.md
├── merge_two_sorted_lists.md
├── remove_duplicates_from_sorted_list.md
├── remove_duplicates_from_sorted_list_ii.md
├── remove_linked_list_elements.md
├── reverse_linked_list.md
└── two_lists_sum.md
├── math_and_bit_manipulation
├── a_plus_b_problem.md
├── count_1_in_binary.md
└── plus_one.md
├── part_i_basics
└── README.md
├── part_ii_coding
└── README.md
├── part_iii_contest
└── README.md
├── problem_misc
├── README.md
├── add_binary.md
├── find_the_missing_number.md
├── minimum_subarray.md
├── reverse_integer.md
├── string_to_integer.md
└── valid_sudoku.md
├── string
├── README.md
├── compare_strings.md
├── count_and_say.md
├── longest_palindromic_substring.md
├── rotate_string.md
├── space_replacement.md
├── strstr.md
├── two_strings_are_anagrams.md
└── valid_palindrome.md
├── styles
└── website.css
└── tags.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Node rules:
2 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
3 | .grunt
4 |
5 | ## Dependency directory
6 | ## Commenting this out is preferred by some people, see
7 | ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git
8 | node_modules
9 |
10 | # Book build output
11 | _book
12 |
13 | *.log
14 |
15 | # MAC OS X
16 | **/.DS_Store
17 |
18 | # Python
19 | *.py[cod]
20 | *$py.class
21 | .python-version
22 |
23 | # Auth
24 | #######
25 | scripts/auth.conf
26 |
--------------------------------------------------------------------------------
/CNAME:
--------------------------------------------------------------------------------
1 | algorithm.yuanbin.me
2 |
--------------------------------------------------------------------------------
/LANGS.md:
--------------------------------------------------------------------------------
1 | * [English](en/)
2 | * [繁體中文](zh-tw/)
3 | * [简体中文](zh-hans/)
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Data Structure and Algorithm/leetcode/lintcode
2 |
3 | [](https://travis-ci.org/billryan/algorithm-exercise)
4 | [](https://slackin4ds-algo.herokuapp.com/)
5 | [](https://ds-algo.slack.com/)
6 |
7 | This book is notes about learning data structure and algorithm. It was written in Simplified Chinese but other languages such as English and Traditional Chinese are also working in progress. Contributions are welcome!
8 |
9 | - [English](https://algorithm.yuanbin.me/en/), rarely updated
10 | - [简体中文](https://algorithm.yuanbin.me/zh-hans/), frequently updated
11 | - [繁體中文](https://algorithm.yuanbin.me/zh-tw/), rarely updated
12 |
13 | ## Introduction
14 |
15 | 1. Part I is some brief introduction of basic data structures and algorithm, such as linked lists, stack, queues, trees, sorting.
16 | 2. Part II is the analysis and summary of programming problems, and most of the programming problems come from , , , , .
17 | 3. Part III is the appendix of resume and other supplements.
18 |
19 | This project is hosted on and rendered by [GitBook](https://www.gitbook.com/book/yuanbin/algorithm/details). You can star the repository on the GitHub to keep track of updates. Another choice is to subscribe channel `#github_commit` via Slack .
20 |
21 | Feel free to access with Slack invite automation.
22 |
23 | You can view/search this document online or offline, feel free to read it. :)
24 |
25 | - Online(Rendered by GitBook):
26 | - Site Search via Google: `keywords site:algorithm.yuanbin.me`
27 | - Site Search via Algolia: Click `Type to search` on the top left corner of webpages
28 | - Offline(Compiled by GitBook on Travis-CI): ePub, PDF, MOBI
29 |
30 | ## License
31 |
32 | This work is licensed under the **Creative Commons Attribution-ShareAlike 4.0 International License**. To view a copy of this license, please visit
33 |
34 | ## To Do
35 |
36 | - [ ] add multiple languages support
37 | - [ ] add implementations of `Python`, `C++`, `Go` and `Java` code
38 | - [x] add time and space complexity analysis
39 | - [x] add proper Chinese fonts for PDF output
40 |
--------------------------------------------------------------------------------
/book.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "disqus",
4 | "ga",
5 | "katex",
6 | "richquotes",
7 | "sitemap2",
8 | "github",
9 | "edit-link",
10 | "feed",
11 | "etoc",
12 | "algolia",
13 | "tags"
14 | ],
15 | "pluginsConfig": {
16 | "disqus": {
17 | "shortName": "algorithm4bill"
18 | },
19 | "ga": {
20 | "token": "UA-32317667-7"
21 | },
22 | "richquotes": {
23 | "todos": true
24 | },
25 | "sitemap2": {
26 | "hostname": "http://algorithm.yuanbin.me/"
27 | },
28 | "github": {
29 | "url": "https://github.com/billryan/algorithm-exercise"
30 | },
31 | "edit-link": {
32 | "base": "https://github.com/billryan/algorithm-exercise/edit/master",
33 | "label": {
34 | "en": "Edit Page",
35 | "zh-hans": "编辑此页",
36 | "zh-tw": "編輯此頁"
37 | }
38 | },
39 | "feed": {
40 | "title": "Data Structure and Algorithm notes",
41 | "description": "Data Structure and Algorithm notes/数据结构与算法学习笔记/leetcode/lintcode 题解",
42 | "hostname": "https://algorithm.yuanbin.me",
43 | "author": "billryan",
44 | "categories": [
45 | "programming",
46 | "algorithm",
47 | "leetcode"
48 | ]
49 | },
50 | "algolia": {
51 | "index": "algorithm",
52 | "applicationID": "9YBMOZR89J",
53 | "publicKey": "5860a3e55ee72831917b1b9e2a4649ca",
54 | "freeAccount": "true"
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/codes/algorithm-java/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .idea/
3 | *.iml
4 | project/
5 |
6 | out/
7 | target/
8 |
9 | .DS_Store
10 |
11 |
--------------------------------------------------------------------------------
/codes/algorithm-java/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | me.yuanbin
8 | algorithm-java
9 | 1.0-SNAPSHOT
10 |
11 |
12 | 1.8
13 | 1.8
14 | 4.12
15 | 1.7.25
16 | 1.18.8
17 |
18 |
19 |
20 |
21 | org.projectlombok
22 | lombok
23 | ${lombok.version}
24 | provided
25 |
26 |
27 |
28 | org.slf4j
29 | slf4j-log4j12
30 | ${slf4j.version}
31 | provided
32 |
33 |
34 |
35 | junit
36 | junit
37 | ${junit.version}
38 | test
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-compiler-plugin
48 | 3.8.1
49 |
50 |
51 |
52 | org.apache.maven.plugins
53 | maven-shade-plugin
54 | 3.2.1
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/codes/algorithm-java/src/main/java/basic/DataStructure.java:
--------------------------------------------------------------------------------
1 | package basic;
2 |
3 | import lombok.Data;
4 | import lombok.NoArgsConstructor;
5 |
6 | import java.util.ArrayDeque;
7 | import java.util.Deque;
8 | import java.util.LinkedList;
9 | import java.util.Queue;
10 |
11 | /**
12 | * Basic data structure including queue, stack, graph...
13 | *
14 | * @author billryan
15 | * @date 2019-06-22
16 | */
17 | @Data
18 | @NoArgsConstructor
19 | public class DataStructure {
20 | private Queue queue = new LinkedList<>();
21 | private Deque stack = new ArrayDeque<>();
22 | }
23 |
--------------------------------------------------------------------------------
/codes/algorithm-java/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | # Root logger option
2 | # By default, everything goes to console and file
3 | log4j.rootLogger=INFO, stdout
4 |
5 | # Direct log messages to stdout
6 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
7 | log4j.appender.stdout.Target=System.out
8 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
9 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
10 |
--------------------------------------------------------------------------------
/codes/algorithm-java/src/test/java/basic/DataStructureTest.java:
--------------------------------------------------------------------------------
1 | package basic;
2 |
3 | import org.junit.Test;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | /**
8 | * @author billryan
9 | * @date 10/8/2019 10:59
10 | */
11 | public class DataStructureTest {
12 |
13 | private static final Logger log = LoggerFactory.getLogger(DataStructureTest.class);
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/codes/algorithm-java/src/test/java/basic/QueueTest.java:
--------------------------------------------------------------------------------
1 | package basic;
2 |
3 | import org.junit.Test;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import java.util.LinkedList;
8 | import java.util.Queue;
9 |
10 | /**
11 | * @author billryan
12 | * @date 10/8/2019 12:05
13 | */
14 | public class QueueTest {
15 |
16 | private static final Logger log = LoggerFactory.getLogger(QueueTest.class);
17 |
18 | @Test
19 | public void testQueue() {
20 | Queue queue = new LinkedList<>();
21 | queue.offer(1);
22 | queue.offer(2);
23 | queue.offer(3);
24 |
25 | int peek = 1;
26 | while (!queue.isEmpty()) {
27 | int queuePeek = queue.poll();
28 | log.info("queue peek: {}", queuePeek);
29 | assert peek == queuePeek;
30 | peek++;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/codes/algorithm-java/src/test/java/basic/StackTest.java:
--------------------------------------------------------------------------------
1 | package basic;
2 |
3 | import org.junit.Test;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import java.util.ArrayDeque;
8 | import java.util.Deque;
9 |
10 | /**
11 | * @author billryan
12 | * @date 10/8/2019 12:04
13 | */
14 | public class StackTest {
15 |
16 | private static final Logger log = LoggerFactory.getLogger(StackTest.class);
17 |
18 | @Test
19 | public void testStack() {
20 | Deque stack = new ArrayDeque<>();
21 | stack.push(1);
22 | stack.push(2);
23 | stack.push(3);
24 |
25 | int peek = 3;
26 | while (!stack.isEmpty()) {
27 | int stackPeek = stack.pop();
28 | log.info("stack peek: {}", stackPeek);
29 | assert peek == stackPeek;
30 | peek--;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/conf/10-latin.conf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | serif
5 |
6 |
7 | Noto Serif
8 | Noto Sans
9 |
10 |
11 |
12 |
13 |
14 | sans-serif
15 |
16 |
17 | Noto Sans
18 |
19 |
20 |
21 |
22 |
23 | monospace
24 |
25 |
26 | Source Code Pro
27 |
28 |
29 |
--------------------------------------------------------------------------------
/conf/15-noto-cjksc.conf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | serif
5 |
6 |
7 | Noto Sans CJK SC
8 |
9 |
10 |
11 |
12 |
13 | sans-serif
14 |
15 |
16 | Noto Sans CJK SC
17 |
18 |
19 |
20 |
21 |
22 | monospace
23 |
24 |
25 | Source Code Pro
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/conf/20-noto-cjk.conf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | serif
5 |
6 |
7 | Noto Sans T Chinese
8 | Noto Sans S Chinese
9 | Noto Sans Japanese
10 | Noto Sans Korean
11 |
12 |
13 |
14 |
15 | sans-serif
16 |
17 |
18 | Noto Sans T Chinese
19 | Noto Sans S Chinese
20 | Noto Sans Japanese
21 | Noto Sans Korean
22 |
23 |
24 |
25 |
26 | monospace
27 |
28 |
29 | Noto Sans T Chinese
30 | Noto Sans S Chinese
31 | Noto Sans Japanese
32 | Noto Sans Korean
33 |
34 |
35 |
--------------------------------------------------------------------------------
/conf/qiniu_sync.json:
--------------------------------------------------------------------------------
1 | {
2 | "src": "/home/travis/upload",
3 | "dest": "qiniu:access_key=AccessKey&secret_key=SecretKey&bucket=pub4bill&key_prefix=docs/algorithm-exercise/",
4 | "deletable": 0,
5 | "debug_level": 1
6 | }
7 |
--------------------------------------------------------------------------------
/contributing.md:
--------------------------------------------------------------------------------
1 | # Guidelines for Contributing
2 |
3 | - Access English via [Guidelines for Contributing](http://algorithm.yuanbin.me/en/faq/guidelines_for_contributing.html)
4 | - 繁體中文請移步 [貢獻指南](http://algorithm.yuanbin.me/zh-tw/faq/guidelines_for_contributing.html)
5 | - 简体中文请移步 [贡献指南](http://algorithm.yuanbin.me/zh-hans/faq/guidelines_for_contributing.html)
6 |
--------------------------------------------------------------------------------
/cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/cover.jpg
--------------------------------------------------------------------------------
/cover_small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/cover_small.jpg
--------------------------------------------------------------------------------
/en/basics_data_structure/README.md:
--------------------------------------------------------------------------------
1 | # Data Structure
2 |
3 | This chapter describes the fundamental data structures and their implementations.
4 |
--------------------------------------------------------------------------------
/en/basics_data_structure/string.md:
--------------------------------------------------------------------------------
1 | # String
2 |
3 | String-related problems often appear in interview questions. In actual
4 | development, strings are also frequently used. Summarized here are common uses
5 | of strings in C++, Java, and Python.
6 |
7 | ## Python
8 |
9 | ```python
10 | s1 = str()
11 | # in python, `''` and `""` are the same
12 | s2 = "shaunwei" # 'shaunwei'
13 | s2len = len(s2)
14 | # last 3 chars
15 | s2[-3:] # wei
16 | s2[5:8] # wei
17 | s3 = s2[:5] # shaun
18 | s3 += 'wei' # return 'shaunwei'
19 | # list in python is same as ArrayList in java
20 | s2list = list(s3)
21 | # string at index 4
22 | s2[4] # 'n'
23 | # find index at first
24 | s2.index('w') # return 5, if not found, throw ValueError
25 | s2.find('w') # return 5, if not found, return -1
26 | ```
27 |
28 | In Python, there's no StringBuffer or StringBuilder. However, string manipulations
29 | are fairly efficient already.
30 |
31 | ## Java
32 |
33 | ```java
34 | String s1 = new String();
35 | String s2 = "billryan";
36 | int s2Len = s2.length();
37 | s2.substring(4, 8); // return "ryan"
38 | StringBuilder s3 = new StringBuilder(s2.substring(4, 8));
39 | s3.append("bill");
40 | String s2New = s3.toString(); // return "ryanbill"
41 | // convert String to char array
42 | char[] s2Char = s2.toCharArray();
43 | // char at index 4
44 | char ch = s2.charAt(4); // return 'r'
45 | // find index at first
46 | int index = s2.indexOf('r'); // return 4. if not found, return -1
47 | ```
48 |
49 | The difference between StringBuffer and StringBuilder is that the former guarantees
50 | thread safety. In a single-threaded environment, StringBuilder is more efficient.
51 |
--------------------------------------------------------------------------------
/en/cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/en/cover.jpg
--------------------------------------------------------------------------------
/en/cover_small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/en/cover_small.jpg
--------------------------------------------------------------------------------
/en/faq/README.md:
--------------------------------------------------------------------------------
1 | # FAQ - Frequently Asked Question
2 |
3 | Some guidelines for contributing and other questions are listed here.
4 |
5 | ## How to Contribute?
6 |
7 | - Access [Guidelines for Contributing](http://algorithm.yuanbin.me/en/faq/guidelines_for_contributing.html) for details.
8 |
--------------------------------------------------------------------------------
/en/faq/guidelines_for_contributing.md:
--------------------------------------------------------------------------------
1 | # Guidelines for Contributing
2 |
3 | - Access English via [Guidelines for Contributing](http://algorithm.yuanbin.me/en/faq/guidelines_for_contributing.html)
4 | - 繁體中文請移步 [貢獻指南](http://algorithm.yuanbin.me/zh-tw/faq/guidelines_for_contributing.html)
5 | - 简体中文请移步 [贡献指南](http://algorithm.yuanbin.zh-hans/faq/guidelines_for_contributing.html)
6 |
--------------------------------------------------------------------------------
/en/integer_array/partition_array_by_odd_and_even.md:
--------------------------------------------------------------------------------
1 | # Partition Array by Odd and Even
2 |
3 | ## Question
4 |
5 | - lintcode: [(373) Partition Array by Odd and Even](http://www.lintcode.com/en/problem/partition-array-by-odd-and-even/)
6 | - [Segregate Even and Odd numbers - GeeksforGeeks](http://www.geeksforgeeks.org/segregate-even-and-odd-numbers/)
7 |
8 | ```
9 | Partition an integers array into odd number first and even number second.
10 |
11 | Example
12 | Given [1, 2, 3, 4], return [1, 3, 2, 4]
13 |
14 | Challenge
15 | Do it in-place.
16 | ```
17 |
18 | ## Solution
19 |
20 | Use **two pointers** to keep the odd before the even, and swap when necessary.
21 |
22 | ### Java
23 |
24 | ```java
25 | public class Solution {
26 | /**
27 | * @param nums: an array of integers
28 | * @return: nothing
29 | */
30 | public void partitionArray(int[] nums) {
31 | if (nums == null) return;
32 |
33 | int left = 0, right = nums.length - 1;
34 | while (left < right) {
35 | // odd number
36 | while (left < right && nums[left] % 2 != 0) {
37 | left++;
38 | }
39 | // even number
40 | while (left < right && nums[right] % 2 == 0) {
41 | right--;
42 | }
43 | // swap
44 | if (left < right) {
45 | int temp = nums[left];
46 | nums[left] = nums[right];
47 | nums[right] = temp;
48 | }
49 | }
50 | }
51 | }
52 | ```
53 |
54 | ### C++
55 |
56 | ```c++
57 | void partitionArray(vector &nums) {
58 | if (nums.empty()) return;
59 |
60 | int i=0, j=nums.size()-1;
61 | while (i **Note**
6 | In order to re-use most of the memory of an existing data structure, internal implementation of string is immutable in most programming languages(Java, Python). Take care if you want to modify character in place.
7 |
--------------------------------------------------------------------------------
/en/styles/website.css:
--------------------------------------------------------------------------------
1 | .book .book-summary, .book .book-body {
2 | font-family: "Helvetica Neue", Helvetica, Arial, "Microsoft YaHei UI", "Microsoft Yahei", "PingFang SC", "Lantinghei SC", "Hiragino Sans GB", "WenQuanYi Micro Hei", "WenQuanYi Zen Hei", "Noto Sans CJK SC", "Microsoft JhengHei UI", "Microsoft JhengHei", "PingFang TC", "Lantinghei TC", "Noto Sans CJK TC", sans-serif;
3 | }
4 |
--------------------------------------------------------------------------------
/en/tags.md:
--------------------------------------------------------------------------------
1 | # Tags
2 |
--------------------------------------------------------------------------------
/scripts/gitls.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | git ls-tree -r --name-only HEAD | while read filename; do
4 | echo "$(git log -1 --format="%ad" --date=short -- $filename) $filename"
5 | done
6 |
--------------------------------------------------------------------------------
/scripts/parse_md.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import os
5 | import re
6 |
7 | class parseMD:
8 | def __init__(self, fname, isSummary=False):
9 | self.fname = fname
10 | self.isSummary = isSummary
11 |
12 | def get_title(self):
13 | lines = open(self.fname)
14 | for line in lines:
15 | if re.match('^# ', line):
16 | title = re.split(' - ', line)[2:]
17 | break
18 |
19 | return title
20 |
--------------------------------------------------------------------------------
/scripts/rename_ebook.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | for old_file in book*
4 | do
5 | new_file="$(echo ${old_file} | sed s/^book/algorithm-ebook/)"
6 | mv "${old_file}" "${new_file}"
7 | done
8 |
--------------------------------------------------------------------------------
/scripts/sitemap/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/scripts/sitemap/__init__.py
--------------------------------------------------------------------------------
/scripts/sitemap/templates/sitemap.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | {% for page in pages %}
4 |
5 | {{root_url}}/{{page['url']}}
6 | {{page['lastmod']}}
7 | {{freq}}
8 |
9 | {% endfor %}
10 |
11 |
--------------------------------------------------------------------------------
/scripts/sitemap_gen.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import os
5 | from shutil import copyfile
6 | from pathlib import Path
7 | from jinja2 import Environment, FileSystemLoader
8 | from subprocess import check_output
9 |
10 | BASE_DIR = os.path.abspath(os.path.dirname(__file__))
11 | ROOT_DIR = os.path.abspath(os.path.join(BASE_DIR, os.pardir))
12 |
13 |
14 | def sitemap(suffix='.md'):
15 | # ensure we are in the ROOT_DIR
16 | os.chdir(ROOT_DIR)
17 | multilang = ['en/', 'zh-hans/', 'zh-tw/']
18 | pages = []
19 | raw_bytes = check_output('scripts/gitls.sh')
20 | # ignore last blank string
21 | raw_strs = raw_bytes.decode("utf-8").split('\n')[:-1]
22 | for raw_str in raw_strs:
23 | date, raw_f = raw_str.split(' ')
24 | for lang in multilang:
25 | if raw_f.startswith(lang) and raw_f.endswith(suffix):
26 | if raw_f == lang + 'SUMMARY.md':
27 | continue
28 | p = Path(raw_f)
29 | # rename README with index
30 | if p.name == 'README.md':
31 | p = p.with_name('index.md')
32 | p = p.with_suffix('.html')
33 | fn = p.as_posix().lower()
34 | page = {}
35 | page['lastmod'] = date
36 | page['url'] = fn
37 | pages.append(page)
38 | root_url = 'http://algorithm.yuanbin.me'
39 | templates = os.path.join(BASE_DIR, 'sitemap' + os.sep + 'templates')
40 | env = Environment(loader=FileSystemLoader(templates))
41 | template = env.get_template('sitemap.xml')
42 | sitemap_xml = template.render(root_url=root_url, pages=pages, freq='daily')
43 | sitemap_fn = os.path.join(ROOT_DIR, 'sitemap.xml')
44 | with open(sitemap_fn, 'w') as sf:
45 | sf.write(sitemap_xml)
46 | sitemap_txt_fn = os.path.join(ROOT_DIR, 'sitemap.txt')
47 | with open(sitemap_txt_fn, 'w') as sf:
48 | urls = [root_url + '/' + page['url'] + '\n' for page in pages]
49 | sf.writelines(urls)
50 | # gitbook do not serve static files under root dir
51 | sitemap_en_fn = os.path.join(ROOT_DIR, 'en' + os.sep + 'sitemap.xml')
52 | copyfile(sitemap_fn, sitemap_en_fn)
53 |
54 |
55 | if __name__ == "__main__":
56 | sitemap()
57 |
--------------------------------------------------------------------------------
/scripts/util.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import os
5 | import errno
6 |
7 | def mkdir_p(path):
8 | try:
9 | os.makedirs(path)
10 | except OSError as exc: # Python >2.5
11 | if exc.errno == errno.EEXIST and os.path.isdir(path):
12 | pass
13 | else:
14 | raise
15 |
16 |
17 | def par_dir(path):
18 | return os.path.abspath(os.path.join(path, os.pardir))
--------------------------------------------------------------------------------
/shared-files/README.md:
--------------------------------------------------------------------------------
1 | # Shared Files
2 |
3 | This folder exists for files sharing of Multilingual site.
4 |
--------------------------------------------------------------------------------
/shared-files/SUMMARY.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/SUMMARY.md
--------------------------------------------------------------------------------
/shared-files/docs/oj_templates/cpp_templates.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | using namespace std;
6 |
7 | int main(int argc, char *argv[])
8 | {
9 | // t: total cases
10 | int t;
11 | cin >> t;
12 | for (int i = 0; i < t; ++i) {
13 | // m: test case lines in total
14 | int m;
15 | cin >> m;
16 | }
17 |
18 | return 0;
19 | }
20 |
--------------------------------------------------------------------------------
/shared-files/images/Binary-reflected_Gray_code_construction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/Binary-reflected_Gray_code_construction.png
--------------------------------------------------------------------------------
/shared-files/images/Heapsort-example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/Heapsort-example.gif
--------------------------------------------------------------------------------
/shared-files/images/alipay_billryan_qr15x15.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/alipay_billryan_qr15x15.jpg
--------------------------------------------------------------------------------
/shared-files/images/binary_tree_summary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/binary_tree_summary.png
--------------------------------------------------------------------------------
/shared-files/images/binary_tree_traversal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/binary_tree_traversal.png
--------------------------------------------------------------------------------
/shared-files/images/bipatial_graph_part_i_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/bipatial_graph_part_i_1.png
--------------------------------------------------------------------------------
/shared-files/images/bipatial_graph_part_i_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/bipatial_graph_part_i_2.png
--------------------------------------------------------------------------------
/shared-files/images/bubble_sort.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/bubble_sort.gif
--------------------------------------------------------------------------------
/shared-files/images/copy_list_with_random_pointer.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/copy_list_with_random_pointer.jpg
--------------------------------------------------------------------------------
/shared-files/images/gitbook_editor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/gitbook_editor.png
--------------------------------------------------------------------------------
/shared-files/images/huffman_algorithm.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/huffman_algorithm.gif
--------------------------------------------------------------------------------
/shared-files/images/insertion_sort.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/insertion_sort.gif
--------------------------------------------------------------------------------
/shared-files/images/insertion_sort_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/insertion_sort_list.png
--------------------------------------------------------------------------------
/shared-files/images/linked_list_cycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/linked_list_cycle.png
--------------------------------------------------------------------------------
/shared-files/images/linked_list_cycle_ii.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/linked_list_cycle_ii.png
--------------------------------------------------------------------------------
/shared-files/images/linked_list_summary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/linked_list_summary.png
--------------------------------------------------------------------------------
/shared-files/images/linked_list_summary_en.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/linked_list_summary_en.png
--------------------------------------------------------------------------------
/shared-files/images/merge_sort.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/merge_sort.gif
--------------------------------------------------------------------------------
/shared-files/images/problem_b_professor_qs_software.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/problem_b_professor_qs_software.png
--------------------------------------------------------------------------------
/shared-files/images/qsort1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/qsort1.png
--------------------------------------------------------------------------------
/shared-files/images/qsort2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/qsort2.png
--------------------------------------------------------------------------------
/shared-files/images/qsort3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/qsort3.gif
--------------------------------------------------------------------------------
/shared-files/images/remove_duplicates_from_sorted_list.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/remove_duplicates_from_sorted_list.jpg
--------------------------------------------------------------------------------
/shared-files/images/resume-zh_CN.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/resume-zh_CN.png
--------------------------------------------------------------------------------
/shared-files/images/reverse_linked_list_i.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/reverse_linked_list_i.jpg
--------------------------------------------------------------------------------
/shared-files/images/rotated_array.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/rotated_array.png
--------------------------------------------------------------------------------
/shared-files/images/selection_sort.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/selection_sort.gif
--------------------------------------------------------------------------------
/shared-files/images/subsets.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/subsets.jpg
--------------------------------------------------------------------------------
/shared-files/images/topological-sorting.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/topological-sorting.jpeg
--------------------------------------------------------------------------------
/shared-files/images/topological_sorting.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/topological_sorting.jpeg
--------------------------------------------------------------------------------
/shared-files/images/tree_diameter.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/tree_diameter.gif
--------------------------------------------------------------------------------
/shared-files/images/valid-sudoku.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/valid-sudoku.png
--------------------------------------------------------------------------------
/shared-files/images/wechat_billryan_qr15x15.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/shared-files/images/wechat_billryan_qr15x15.jpg
--------------------------------------------------------------------------------
/zh-hans/GLOSSARY.md:
--------------------------------------------------------------------------------
1 | ## TLE
2 |
3 | Time Limit Exceeded 的简称。你的程序在 OJ 上的运行时间太长了,超过了对应题目的时间限制。
4 |
5 | ## DFS
6 |
7 | Depth-First Search, 深度优先搜索
8 |
9 | ## BFS
10 |
11 | Breadth-First Search, 广度优先搜索
12 |
13 | ## DP_Sequence
14 |
15 | 单序列动态规划,通常使用 f[i] 表示前i个位置/数字/字母... 使用 f[n-1] 表示最后返回结果。
16 |
17 | ## DP_Two_Sequence
18 |
19 | 一般有两个数组或者两个字符串,计算其匹配关系. 通常可用 `f[i][j]`表示第一个数组的前 i 位和第二个数组的前 j 位的关系。
20 |
21 | ## DP_Matrix
22 |
23 | 根据动态规划解题的四要素,矩阵类动态规划问题通常可用 f[x][y] 表示从起点走到坐标(x,y)的值
24 |
--------------------------------------------------------------------------------
/zh-hans/appendix_i_interview_and_resume/README.md:
--------------------------------------------------------------------------------
1 | # Appendix I Interview and Resume
2 |
3 | 本章主要总结一些技术面试和撰写简历方面的注意事项。
4 |
5 |
--------------------------------------------------------------------------------
/zh-hans/appendix_i_interview_and_resume/resume.md:
--------------------------------------------------------------------------------
1 | # Resume
2 |
3 | 本小节主要总结一些**技术简历**相关的优质资源。具体的还可以参考前一节中 Facebook 提供的简历撰写指南,除了这些简短的资源外还强烈推荐下 Gayle 写的 *The Google Resume*,极其详细!干货超多!
4 |
5 | ## Resume Template
6 |
7 | 推荐使用 Markdown 或者 Latex 撰写简历,可以使用 sharelatex 在线写简历,从 [CV or Resume](https://www.sharelatex.com/templates/cv-or-resume) 模板中挑,modernCV 的那些模板要写在一页里比较困难,这个 [Professional CV](https://www.sharelatex.com/templates/cv-or-resume/professional-cv) 相对紧凑一些,[LaTeX Templates » Curricula Vitae/Résumés](http://www.latextemplates.com/cat/curricula-vitae) 上还有更多更好的选择。另外推荐下自己写的一个还算简洁优雅的简历模板——[billryan/resume](https://github.com/billryan/resume), 同时支持中英文和 FontAwesome 字体,欢迎试用~ 中文的样式大概长成下面这个样子。
8 |
9 | 
10 | 
11 |
12 | ## Reference
13 |
14 | - *The Google Resume* - 书名虽为简历,但本书可不只是教你写简历那么简单,除了教你如何写优秀简历外还总结了技术面试以及找工作过程中的方方面面。甚至连职业规划都有涉及!**力荐!**
15 | - [如何写好技术简历 —— 实例、模板及工具 | @Get社区](http://get.jobdeer.com/744.get) - 挺不错的技术简历实战。
16 | - [精益技术简历之道——改善技术简历的47条原则 - Lucida](http://zh.lucida.me/blog/lean-technical-resume/) - 『Effective 简历』系列。
17 | - [如何把简历写进一页 - V2EX](https://www.v2ex.com/t/175250) - 众人支招助萌妹纸优化简历。
18 | - *Cracking the coding interview* 『写好简历』一节。
19 |
--------------------------------------------------------------------------------
/zh-hans/basics_algorithm/README.md:
--------------------------------------------------------------------------------
1 | # Basics Algorithm
2 |
3 | 本章主要介绍一些常用的基本算法,后序章节介绍一些高级算法。
4 |
--------------------------------------------------------------------------------
/zh-hans/basics_algorithm/bitmap.md:
--------------------------------------------------------------------------------
1 | # Bitmap
2 |
3 | 最开始接触 bitmap 是在《编程珠玑》这本书上,书中所述的方法有点简单粗暴,不过思想倒是挺好——从信息论的角度来解释就是信息压缩了。即将原来32位表示一个 int 变为一位表示一个 int. 从空间的角度来说就是巨大的节省了(1/32)。可能的应用有**大数据排序/查找(非负整数)**。核心思想为根据最大非负整数确定位数,对应的位依次排序。
4 |
5 | C++ 中有`bitset`容器,其他语言可用类似方法实现。
6 |
7 | ## Implementation
8 |
9 | ### C
10 |
11 | ```c
12 | #include
13 | #include
14 |
15 | /*
16 | * @param bits: uint array, i: num i of original array
17 | */
18 | void setbit(unsigned int *bits, unsigned int i, int BIT_LEN)
19 | {
20 | bits[i / BIT_LEN] |= 1 << (i % BIT_LEN);
21 | }
22 |
23 | /*
24 | * @param bits: uint array, i: num i of original array
25 | */
26 | int testbit(unsigned int *bits, unsigned int i, int BIT_LEN)
27 | {
28 | return bits[i / BIT_LEN] & (1 << (i % BIT_LEN));
29 | }
30 |
31 | int main(int argc, char *argv[])
32 | {
33 | const int BIT_LEN = sizeof(int) * 8;
34 | const unsigned int N = 1 << (BIT_LEN - 1);
35 | unsigned int *bits = (unsigned int *)calloc(N / BIT_LEN, sizeof(int));
36 | for (unsigned int i = 0; i < N; i++) {
37 | if (i % 10000001 == 0) setbit(bits, i, BIT_LEN);
38 | }
39 |
40 | for (unsigned int i = 0; i < N; i++) {
41 | if (testbit(bits, i, BIT_LEN) != 0) printf("i = %u exists.\n", i);
42 | }
43 | free(bits);
44 | bits = NULL;
45 |
46 | return 0;
47 | }
48 | ```
49 |
50 | ### 源码分析
51 |
52 | 核心为两个函数方法的使用,`setbit`用于将非负整数`i`置于指定的位。可用分区分位的方式来理解位图排序的思想,即将非负整数`i`放到它应该在的位置。比如16,其可以位于第一个 int 型的第17位,具体实现即将第17位置一,细节见上面代码。测试某个数是否存在于位图中也可以采用类似方法。
53 |
--------------------------------------------------------------------------------
/zh-hans/basics_algorithm/divide_and_conquer.md:
--------------------------------------------------------------------------------
1 | # Divide and Conquer - 分治法
2 |
3 | 在计算机科学中,分治法是一种很重要的算法。分治法即『分而治之』,把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个思想是很多高效算法的基础,如排序算法(快速排序,归并排序)等。
4 |
5 | ## 分治法思想
6 |
7 | 分治法所能解决的问题一般具有以下几个特征:
8 |
9 | 1. 问题的规模缩小到一定的程度就可以容易地解决。
10 | 2. 问题可以分解为若干个规模较小的相同问题,即该问题具有**最优子结构**性质。
11 | 3. 利用该问题分解出的子问题的解可以合并为该问题的解。
12 | 4. 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。
13 |
14 | 分治法的三个步骤是:
15 |
16 | 1. 分解(Divide):将原问题分解为若干子问题,这些子问题都是原问题规模较小的实例。
17 | 2. 解决(Conquer):递归地求解各子问题。如果子问题规模足够小,则直接求解。
18 | 3. 合并(Combine):将所有子问题的解合并为原问题的解。
19 |
20 | 分治法的经典题目:
21 |
22 | 1. 二分搜索
23 | 2. 大整数乘法
24 | 3. Strassen矩阵乘法
25 | 4. 棋盘覆盖
26 | 5. 归并排序
27 | 6. 快速排序
28 | 7. 循环赛日程表
29 | 8. 汉诺塔
30 |
--------------------------------------------------------------------------------
/zh-hans/basics_algorithm/math/README.md:
--------------------------------------------------------------------------------
1 | # Math
2 |
3 | 本小节总结一些与数学(尤其是数论部分)有关的基础,主要总结了《挑战程序设计竞赛》第二章。主要包含以下内容:
4 |
5 | 1. Greatest Common Divisor(最大公约数)
6 | 2. Prime(素数基础理论)
7 | 3. Modulus(求模运算)
8 | 4. Fast Power(快速幂运算)
9 |
10 | ## Modulus - 求模运算
11 |
12 | 有时计算结果可能会溢出,此时往往需要对结果取余。如果有`a % m = c % m` 和 `b % m = d % m`, 那么有以下模运算成立。
13 |
14 | - `(a + b) % m = (c + d) % m`
15 | - `(a - b) % m = (c - d) % m`
16 | - `(a × b) % m = (c × d) % m`
17 |
18 | 需要注意的是没有除法运算,另外由于最终结果可能溢出,故需要使用更大范围的类型来保存求模之前的结果。另外若`a`是负数时往往需要改写为 `a % m + m`, 这样就保证结果在`[0, m - 1]`范围内了。
19 |
20 | ## Fast Power - 快速幂运算
21 |
22 | 快速幂运算的核心思想为反复平方法,将幂指数表示为2的幂次的和,等价于二进制进行移位计算(不断取幂的最低位),比如 $$x^{22} = x^{16} x^4 x^2$$.
23 |
24 | ### Java
25 |
26 | ```java
27 | import java.util.*;
28 |
29 | public class FastPow {
30 | public static long fastModPow(long x, long n, long mod) {
31 | long res = 1 % mod;
32 | while (n > 0) {
33 | // if lowest bit is 1
34 | if ((n & 1) != 0) res = res * x % mod;
35 | x = x * x % mod;
36 | n >>= 1;
37 | }
38 | return res;
39 | }
40 |
41 | public static void main(String[] args) {
42 | if (args.length != 2 && args.length != 3) return;
43 |
44 | long x = Long.parseLong(args[0]);
45 | long n = Long.parseLong(args[1]);
46 | long mod = Long.MAX_VALUE;
47 | if (args.length == 3) {
48 | mod = Long.parseLong(args[2]);
49 | }
50 | System.out.println(fastModPow(x, n, mod));
51 | }
52 | }
53 | ```
54 |
--------------------------------------------------------------------------------
/zh-hans/basics_algorithm/probability/README.md:
--------------------------------------------------------------------------------
1 | # Probability
2 |
--------------------------------------------------------------------------------
/zh-hans/basics_data_structure/README.md:
--------------------------------------------------------------------------------
1 | # Data Structure - 数据结构
2 |
3 | 本章主要介绍一些基本的数据结构和算法。
4 |
--------------------------------------------------------------------------------
/zh-hans/basics_data_structure/graph.md:
--------------------------------------------------------------------------------
1 | # Graph - 图
2 |
3 | 图的表示通常使用**邻接矩阵和邻接表**,前者易实现但是对于稀疏矩阵会浪费较多空间,后者使用链表的方式存储信息但是对于图搜索时间复杂度较高。
4 |
5 | ## 编程实现
6 |
7 | ### 邻接矩阵
8 |
9 | 设顶点个数为 V, 那么邻接矩阵可以使用 V × V 的二维数组来表示。
10 | `g[i][j]`表示顶点`i`和顶点`j`的关系,对于无向图可以使用0/1表示是否有连接,对于带权图则需要使用`INF`来区分。有重边时保存边数或者权值最大/小的边即可。
11 |
12 | #### Python
13 | ```python
14 | g = [[0 for _ in range(V)] for _ in range(V)]
15 | ```
16 |
17 | #### Java
18 | ```java
19 | /* Java Definition */
20 | int[][] g = new int[V][V];
21 | ```
22 |
23 |
24 | ### 邻接表
25 |
26 | 邻接表通过表示从顶点`i`出发到其他所有可能能到的边。
27 |
28 | ### 有向图
29 |
30 | #### Python
31 |
32 | ```python
33 | class DirectedGraphNode:
34 | def __init__(self, x):
35 | self.label = x
36 | self.neighbors = []
37 | ```
38 |
39 | #### Java
40 |
41 | ```java
42 | /* Java Definition */
43 | class DirectedGraphNode {
44 | int label;
45 | ArrayList neighbors;
46 | DirectedGraphNode(int x) {
47 | label = x;
48 | neighbors = new ArrayList();
49 | }
50 | }
51 | ```
52 |
53 | ### 无向图同上,只不过在建图时双向同时加。
54 |
55 | #### Python
56 |
57 | ```python
58 | class UndirectedGraphNode:
59 | def __init__(self, x):
60 | self.label = x
61 | self.neighbors = []
62 | ```
63 |
64 |
65 | #### Java
66 |
67 | ```java
68 | class UndirectedGraphNode {
69 | int label;
70 | ArrayList neighbors;
71 | UndirectedGraphNode(int x) {
72 | this.label = x;
73 | this.neighbors = new ArrayList();
74 | }
75 | }
76 | ```
77 |
--------------------------------------------------------------------------------
/zh-hans/basics_data_structure/map.md:
--------------------------------------------------------------------------------
1 | # Map - 哈希表
2 |
3 | Map 是一种关联数组的数据结构,也常被称为字典或键值对。
4 |
5 | ## 编程实现
6 |
7 | ### Python
8 |
9 | 在 Python 中 `dict`(Map) 是一种基本的数据结构。
10 |
11 | ```python
12 | # map 在 python 中是一个keyword
13 | hash_map = {} # or dict()
14 | hash_map['shaun'] = 98
15 | hash_map['wei'] = 99
16 | exist = 'wei' in hash_map # check existence
17 | point = hash_map['shaun'] # get value by key
18 | point = hash_map.pop('shaun') # remove by key, return value
19 | keys = hash_map.keys() # return key list
20 | # iterate dictionary(map)
21 | for key, value in hash_map.items():
22 | # do something with k, v
23 | pass
24 | ```
25 |
26 | ### Java
27 |
28 | Java 的实现中 Map 是一种将对象与对象相关联的设计。常用的实现有`HashMap`和`TreeMap`, `HashMap`被用来快速访问,而`TreeMap`则保证『键』始终有序。Map 可以返回键的 Set, 值的 Collection, 键值对的 Set.
29 |
30 | ```java
31 | Map map = new HashMap();
32 | map.put("bill", 98);
33 | map.put("ryan", 99);
34 | boolean exist = map.containsKey("ryan"); // check key exists in map
35 | int point = map.get("bill"); // get value by key
36 | int point = map.remove("bill") // remove by key, return value
37 | Set set = map.keySet();
38 | // iterate Map
39 | for (Map.Entry entry : map.entrySet()) {
40 | String key = entry.getKey();
41 | int value = entry.getValue();
42 | // do some thing
43 | }
44 | ```
45 |
--------------------------------------------------------------------------------
/zh-hans/basics_data_structure/set.md:
--------------------------------------------------------------------------------
1 | # Set
2 |
3 | Set 是一种用于保存不重复元素的数据结构。常被用作测试归属性,故其查找的性能十分重要。
4 |
5 | ## 编程实现
6 |
7 | ### Python
8 |
9 | `Set` 是`python`自带的基本数据结构, 有多种初始化方式。 `Python`的`set`跟`dict`的Implementation方式类似, 可以认为`set`是只有`key`的`dict`.
10 |
11 | ```python
12 | s = set()
13 | s1 = {1, 2, 3}
14 | s.add('shaunwei')
15 | 'shaun' in s # return true
16 | s.remove('shaunwei')
17 | ```
18 |
19 |
20 | ### Java
21 |
22 | Set 与 Collection 具有安全一样的接口,通常有`HashSet`, `TreeSet` 或 `LinkedHashSet`三种实现。`HashSet`基于散列函数实现,无序,查询速度最快;`TreeSet`基于红-黑树实现,有序。
23 |
24 | ```java
25 | Set hash = new HashSet();
26 | hash.add("billryan");
27 | hash.contains("billryan");
28 | ```
29 |
30 | 在不允许重复元素时可当做哈希表来用。
31 |
--------------------------------------------------------------------------------
/zh-hans/basics_data_structure/stack.md:
--------------------------------------------------------------------------------
1 | # Stack - 栈
2 |
3 | 栈是一种 LIFO(Last In First Out) 的数据结构,常用方法有添加元素,取栈顶元素,弹出栈顶元素,判断栈是否为空。
4 |
5 | ## 编程实现
6 |
7 | ### Python
8 | ```python
9 | stack = []
10 | len(stack) # size of stack
11 |
12 | # more efficient stack
13 | import collections
14 | stack = collections.deque()
15 | ```
16 |
17 | `list`作为最基本的`python`数据结构之一, 可以很轻松的实现`stack`。 如果需要更高效的`stack`, 建议使用`deque`。
18 |
19 | #### Methods
20 |
21 | - `len(stack) != 0` - 判断`stack`是否为空
22 | - `stack[-1]` - 取栈顶元素,不移除
23 | - `pop()` - 移除栈顶元素并返回该元素
24 | - `append(item)` - 向栈顶添加元素
25 |
26 |
27 | ### Java
28 |
29 | ```java
30 | Deque stack = new ArrayDeque();
31 | s.size(); // size of stack
32 | ```
33 |
34 | JDK doc 中建议使用`Deque`代替`Stack`实现栈,因为`Stack`继承自`Vector`,需要`synchronized`,性能略低。
35 |
36 | #### Methods
37 |
38 | - `boolean isEmpty()` - 判断栈是否为空,若使用 Stack 类构造则为 empty()
39 | - `E peek()` - 取栈顶元素,不移除
40 | - `E pop()` - 移除栈顶元素并返回该元素
41 | - `E push(E item)` - 向栈顶添加元素
42 |
--------------------------------------------------------------------------------
/zh-hans/basics_data_structure/string.md:
--------------------------------------------------------------------------------
1 | # String
2 |
3 | String 相关的题常出现在面试题中,实际开发也经常用到,这里总结下 C++, Java, Python 中字符串常用的方法。
4 |
5 | ## Python
6 |
7 | ```python
8 | s1 = str()
9 | # in python `''` or `""` is the same
10 | s2 = "shaunwei" # 'shaunwei'
11 | s2len = len(s2)
12 | # last 3 chars
13 | s2[-3:] # wei
14 | s2[5:8] # wei
15 | s3 = s2[:5] # shaun
16 | s3 += 'wei' # return 'shaunwei'
17 | # list in python is same as ArrayList in java
18 | s2list = list(s3)
19 | # string at index 4
20 | s2[4] # 'n'
21 | # find index at first
22 | s2.index('w') # return 5, if not found, throw ValueError
23 | s2.find('w') # return 5, if not found, return -1
24 | ```
25 |
26 | 在Python里面,没有StringBuffer 或者 StringBuilder。 但是在Python 里面处理String本身就比较 cheap。
27 |
28 | ## Java
29 |
30 | ```java
31 | String s1 = new String();
32 | String s2 = "billryan";
33 | int s2Len = s2.length();
34 | s2.substring(4, 8); // return "ryan"
35 | StringBuilder s3 = new StringBuilder(s2.substring(4, 8));
36 | s3.append("bill");
37 | String s2New = s3.toString(); // return "ryanbill"
38 | // convert String to char array
39 | char[] s2Char = s2.toCharArray();
40 | // char at index 4
41 | char ch = s2.charAt(4); // return 'r'
42 | // find index at first
43 | int index = s2.indexOf('r'); // return 4. if not found, return -1
44 | ```
45 |
46 | StringBuffer 与 StringBuilder, 前者保证线程安全,后者不是,但单线程下效率高一些,一般使用 StringBuilder.
47 |
--------------------------------------------------------------------------------
/zh-hans/basics_misc/README.md:
--------------------------------------------------------------------------------
1 | # Basics Miscellaneous
2 |
3 | 杂项部分,涉及「位操作」等。
4 |
--------------------------------------------------------------------------------
/zh-hans/basics_misc/bit_manipulation.md:
--------------------------------------------------------------------------------
1 | # Bit Manipulation
2 |
3 | 位操作有按位与、或、非、左移n位和右移n位等操作。
4 |
5 | ### XOR - 异或
6 |
7 | > 异或:相同为0,不同为1。也可用「不进位加法」来理解。
8 |
9 | 异或操作的一些特点:
10 | ```
11 | x ^ 0 = x
12 | x ^ 1s = ~x // 1s = ~0
13 | x ^ (~x) = 1s
14 | x ^ x = 0 // interesting and important!
15 | a ^ b = c => a ^ c = b, b ^ c = a // swap
16 | a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c // associative
17 | ```
18 |
19 | ### 移位操作
20 |
21 | 移位操作可近似为乘以/除以2的幂。`0b0010 * 0b0110`等价于`0b0110 << 2`. 下面是一些常见的移位组合操作。从低位向高位看过去,个位为1,那么有:
22 |
23 | 1. 将`x`最右边的`n`位清零 - `x & (~0 << n)`
24 | 2. 获取`x`的第`n`位值(0或者1) - `(x >> n) & 1`
25 | 2. 获取`x`的第`n`位的幂值 - `x & (1 << (n - 1))`
26 | 3. 仅将第`n`位置为`1` - `x | (1 << n)`
27 | 4. 仅将第`n`位置为`0` - `x & (~(1 << n))`
28 | 5. 将`x`最高位至第`n`位(含)清零 - `x & ((1 << n) - 1)`
29 | 6. 将第`n`位至第0位(含)清零 - `x & (~((1 << (n + 1)) - 1))`
30 | 7. 仅更新第`n`位,写入值为`v`; `v`为1则更新为1,否则为0 - `mask = ~(1 << n); x = (x & mask) | (v << i)`
31 |
32 |
33 | ## Reference
34 |
35 | - [位运算应用技巧(1) » NoAlGo博客](http://noalgo.info/344.html)
36 | - [位运算应用技巧(2) » NoAlGo博客](http://noalgo.info/353.html)
37 | - [位运算简介及实用技巧(一):基础篇 | Matrix67: The Aha Moments](http://www.matrix67.com/blog/archives/263)
38 | - *cc150* chapter 8.5 and chapter 9.5
39 | - 《编程珠玑2》
40 | - 《Elementary Algorithms》 Larry LIU Xinyu
41 |
--------------------------------------------------------------------------------
/zh-hans/basics_sorting/README.md:
--------------------------------------------------------------------------------
1 | # Basics Sorting - 基础排序算法
2 |
3 | # 算法复习——排序
4 |
5 | 时间限制为1s时,大O为10000000时勉强可行,100,000,000时很悬。
6 |
7 | ## 算法分析
8 |
9 | 1. 时间复杂度-执行时间(比较和交换次数)
10 | 2. 空间复杂度-所消耗的额外内存空间
11 | - 使用小堆栈或表
12 | - 使用链表或指针、数组索引来代表数据
13 | - 排序数据的副本
14 |
15 | 对具有重键的数据(同一组数按不同键多次排序)进行排序时,需要考虑排序方法的稳定性,在非稳定性排序算法中需要稳定性时可考虑加入小索引。
16 |
17 | 稳定性:如果排序后文件中拥有相同键的项的相对位置不变,这种排序方式是稳定的。
18 |
19 | 常见的排序算法根据是否需要比较可以分为如下几类:
20 |
21 | - Comparison Sorting
22 | 1. Bubble Sort
23 | 2. Selection Sort
24 | 3. Insertion Sort
25 | 4. Shell Sort
26 | 5. Merge Sort
27 | 6. Quck Sort
28 | 7. Heap Sort
29 | - Bucket Sort
30 | - Counting Sort
31 | - Radix Sort
32 |
33 | 从稳定性角度考虑可分为如下两类:
34 | - 稳定
35 | - 非稳定
36 |
37 | ## Reference
38 |
39 | - [常用排序算法总结(性能+代码) - SegmentFault](http://segmentfault.com/a/1190000002595152#articleHeader15)
40 | - [Sorting algorithm - Wikipedia, the free encyclopedia](http://en.wikipedia.org/wiki/Sorting_algorithm) - 各类排序算法的「平均、最好、最坏时间复杂度」总结。
41 | - [经典排序算法总结与实现 | Jark's Blog](http://wuchong.me/blog/2014/02/09/algorithm-sort-summary/) - 基于 Python 的较为清晰的总结。
42 | - [【面经】硅谷前沿Startup面试经验-排序算法总结及快速排序算法代码_九章算法](http://blog.sina.com.cn/s/blog_eb52001d0102v1k8.html) - 总结了一些常用常问的排序算法。
43 |
--------------------------------------------------------------------------------
/zh-hans/basics_sorting/bubble_sort.md:
--------------------------------------------------------------------------------
1 | # Bubble Sort - 冒泡排序
2 |
3 | 核心:**冒泡**,持续比较相邻元素,大的挪到后面,因此大的会逐步往后挪,故称之为冒泡。
4 |
5 | 
6 |
7 | ## Implementation
8 |
9 | ### Python
10 |
11 | ```python
12 | #!/usr/bin/env python
13 |
14 |
15 | def bubbleSort(alist):
16 | for i in xrange(len(alist)):
17 | print(alist)
18 | for j in xrange(1, len(alist) - i):
19 | if alist[j - 1] > alist[j]:
20 | alist[j - 1], alist[j] = alist[j], alist[j - 1]
21 |
22 | return alist
23 |
24 | unsorted_list = [6, 5, 3, 1, 8, 7, 2, 4]
25 | print(bubbleSort(unsorted_list))
26 | ```
27 |
28 | ### Java
29 |
30 | ```java
31 | public class Sort {
32 | public static void main(String[] args) {
33 | int[] unsortedArray = new int[]{6, 5, 3, 1, 8, 7, 2, 4};
34 | bubbleSort(unsortedArray);
35 | System.out.println("After sort: ");
36 | for (int item : unsortedArray) {
37 | System.out.print(item + " ");
38 | }
39 | }
40 |
41 | public static void bubbleSort(int[] nums) {
42 | int len = nums.length;
43 | for (int i = 0; i < len; i++) {
44 | for (int num : nums) {
45 | System.out.print(num + " ");
46 | }
47 | System.out.println();
48 | for (int j = 1; j < len - i; j++) {
49 | if (nums[j - 1] > nums[j]) {
50 | int temp = nums[j - 1];
51 | nums[j - 1] = nums[j];
52 | nums[j] = temp;
53 | }
54 | }
55 | }
56 | }
57 | }
58 | ```
59 |
60 | ### 复杂度分析
61 |
62 | 平均情况与最坏情况均为 $$O(n^2)$$, 使用了 temp 作为临时交换变量,空间复杂度为 $$O(1)$$.
63 |
64 | ## Reference
65 |
66 | - [冒泡排序 - 维基百科,自由的百科全书](http://zh.wikipedia.org/wiki/%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F)
67 |
--------------------------------------------------------------------------------
/zh-hans/basics_sorting/bucket_sort.md:
--------------------------------------------------------------------------------
1 | # Bucket Sort
2 |
3 | 桶排序和归并排序有那么点点类似,也使用了归并的思想。大致步骤如下:
4 |
5 | 1. 设置一个定量的数组当作空桶。
6 | 2. Divide - 从待排序数组中取出元素,将元素按照一定的规则塞进对应的桶子去。
7 | 3. 对每个非空桶进行排序,通常可在塞元素入桶时进行插入排序。
8 | 4. Conquer - 从非空桶把元素再放回原来的数组中。
9 |
10 | ## Reference
11 |
12 | - [Bucket Sort Visualization](http://www.cs.usfca.edu/~galles/visualization/BucketSort.html) - 动态演示。
13 | - [桶排序 - 维基百科,自由的百科全书](http://zh.wikipedia.org/wiki/%E6%A1%B6%E6%8E%92%E5%BA%8F)
14 |
--------------------------------------------------------------------------------
/zh-hans/basics_sorting/counting_sort.md:
--------------------------------------------------------------------------------
1 | # Counting Sort
2 |
3 | 计数排序,顾名思义,就是对待排序数组按元素进行计数。使用前提是需要先知道待排序数组的元素范围,将这些一定范围的元素置于新数组中,新数组的大小为待排序数组中最大元素与最小元素的差值。
4 |
5 | 维基上总结的四个步骤如下:
6 |
7 | 1. 定新数组大小——找出待排序的数组中最大和最小的元素
8 | 2. 统计次数——统计数组中每个值为i的元素出现的次数,存入新数组C的第i项
9 | 3. 对统计次数逐个累加——对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)
10 | 4. 反向填充目标数组——将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1
11 |
12 | 其中反向填充主要是为了避免重复元素落入新数组的同一索引处。
13 |
14 | ## Reference
15 |
16 | - [计数排序 - 维基百科,自由的百科全书](http://zh.wikipedia.org/wiki/%E8%AE%A1%E6%95%B0%E6%8E%92%E5%BA%8F) - 中文版的维基感觉比英文版的好理解些。
17 | - [Counting Sort Visualization](https://www.cs.usfca.edu/~galles/visualization/CountingSort.html) - 动画真心不错~ 结合着看一遍就理解了。
18 |
--------------------------------------------------------------------------------
/zh-hans/basics_sorting/radix_sort.md:
--------------------------------------------------------------------------------
1 | # Radix Sort
2 |
3 | 经典排序算法 - 基数排序Radix sort
4 |
5 | 原理类似桶排序,这里总是需要10个桶,多次使用
6 |
7 | 首先以个位数的值进行装桶,即个位数为1则放入1号桶,为9则放入9号桶,暂时忽视十位数
8 |
9 | 例如
10 |
11 | 待排序数组[62,14,59,88,16]简单点五个数字
12 |
13 | 分配10个桶,桶编号为0-9,以个位数数字为桶编号依次入桶,变成下边这样
14 |
15 | | 0 | 0 | 62 | 0 | 14 | 0 | 16 | 0 | 88 | 59 |
16 |
17 | | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |桶编号
18 |
19 | 将桶里的数字顺序取出来,
20 |
21 | 输出结果:[62,14,16,88,59]
22 |
23 | 再次入桶,不过这次以十位数的数字为准,进入相应的桶,变成下边这样:
24 |
25 | 由于前边做了个位数的排序,所以当十位数相等时,个位数字是由小到大的顺序入桶的,就是说,入完桶还是有序
26 |
27 | | 0 | 14,16 | 0 | 0 | 0 | 59 | 62 | 0 | 88 | 0 |
28 |
29 | | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |桶编号
30 |
31 |
32 |
33 |
34 | 因为没有大过100的数字,没有百位数,所以到这排序完毕,顺序取出即可
35 |
36 | 最后输出结果:[14,16,59,62,88]
37 |
38 |
39 | 文章引用自
40 | http://www.cnblogs.com/kkun/archive/2011/11/23/2260275.html
41 |
--------------------------------------------------------------------------------
/zh-hans/basics_sorting/selection_sort.md:
--------------------------------------------------------------------------------
1 | # Selection Sort - 选择排序
2 |
3 | 核心:不断地选择剩余元素中的最小者。
4 |
5 | 1. 找到数组中最小元素并将其和数组第一个元素交换位置。
6 | 2. 在剩下的元素中找到最小元素并将其与数组第二个元素交换,直至整个数组排序。
7 |
8 | 性质:
9 |
10 | - 比较次数=(N-1)+(N-2)+(N-3)+...+2+1~N^2/2
11 | - 交换次数=N
12 | - 运行时间与输入无关
13 | - 数据移动最少
14 |
15 | 下图来源为 [File:Selection-Sort-Animation.gif - IB Computer Science](http://wiki.ibcsstudent.org/index.php?title=File:Selection-Sort-Animation.gif)
16 |
17 | 
18 |
19 | ## Implementation
20 |
21 | ### Python
22 |
23 | ```python
24 | #!/usr/bin/env python
25 |
26 |
27 | def selectionSort(alist):
28 | for i in xrange(len(alist)):
29 | print(alist)
30 | min_index = i
31 | for j in xrange(i + 1, len(alist)):
32 | if alist[j] < alist[min_index]:
33 | min_index = j
34 | alist[min_index], alist[i] = alist[i], alist[min_index]
35 | return alist
36 |
37 | unsorted_list = [8, 5, 2, 6, 9, 3, 1, 4, 0, 7]
38 | print(selectionSort(unsorted_list))
39 | ```
40 |
41 | ### Java
42 |
43 | ```java
44 | public class Sort {
45 | public static void main(String[] args) {
46 | int unsortedArray[] = new int[]{8, 5, 2, 6, 9, 3, 1, 4, 0, 7};
47 | selectionSort(unsortedArray);
48 | System.out.println("After sort: ");
49 | for (int item : unsortedArray) {
50 | System.out.print(item + " ");
51 | }
52 | }
53 |
54 | public static void selectionSort(int[] array) {
55 | int len = array.length;
56 | for (int i = 0; i < len; i++) {
57 | for (int item : array) {
58 | System.out.print(item + " ");
59 | }
60 | System.out.println();
61 | int min_index = i;
62 | for (int j = i + 1; j < len; j++) {
63 | if (array[j] < array[min_index]) {
64 | min_index = j;
65 | }
66 | }
67 | int temp = array[min_index];
68 | array[min_index] = array[i];
69 | array[i] = temp;
70 | }
71 | }
72 | }
73 | ```
74 |
75 | ## Reference
76 |
77 | - [选择排序 - 维基百科,自由的百科全书](http://zh.wikipedia.org/wiki/%E9%80%89%E6%8B%A9%E6%8E%92%E5%BA%8F)
78 | - [The Selection Sort — Problem Solving with Algorithms and Data Structures](http://interactivepython.org/runestone/static/pythonds/SortSearch/TheSelectionSort.html)
79 |
--------------------------------------------------------------------------------
/zh-hans/bigdata/README.md:
--------------------------------------------------------------------------------
1 | 本小节主要总结 bigdata 相关的题,涉及 MapReduce, Top K 等经典问题。
--------------------------------------------------------------------------------
/zh-hans/bigdata/top_k_largest_numbers.md:
--------------------------------------------------------------------------------
1 | ---
2 | difficulty: Medium
3 | tags:
4 | - Priority Queue
5 | - Heap
6 | title: Top k Largest Numbers
7 | ---
8 |
9 | # Top k Largest Numbers
10 |
11 | ## Problem
12 |
13 | ### Metadata
14 |
15 | - tags: Priority Queue, Heap
16 | - difficulty: Medium
17 | - source(lintcode):
18 |
19 | ### Description
20 |
21 | Given an integer array, find the top *k* largest numbers in it.
22 |
23 | #### Example
24 |
25 | Given `[3,10,1000,-99,4,100]` and *k* = `3`.
26 | Return `[1000, 100, 10]`.
27 |
28 | ## 题解
29 |
30 | 简单题,使用堆即可。
31 |
32 | ### Java
33 |
34 | ```java
35 | public class Solution {
36 | /**
37 | * @param nums: an integer array
38 | * @param k: An integer
39 | * @return: the top k largest numbers in array
40 | */
41 | public int[] topk(int[] nums, int k) {
42 | if (nums == null || nums.length <= 1) return nums;
43 |
44 | PriorityQueue pq = new PriorityQueue(nums.length, Collections.reverseOrder());
45 | for (int num : nums) {
46 | pq.offer(num);
47 | }
48 |
49 | int[] maxK = new int[k];
50 | for (int i = 0; i < k; i++) {
51 | maxK[i] = pq.poll();
52 | }
53 |
54 | return maxK;
55 | }
56 | }
57 | ```
58 |
59 | ### 源码分析
60 |
61 | 略
62 |
63 | ### 复杂度分析
64 |
65 | 略
--------------------------------------------------------------------------------
/zh-hans/bigdata/top_k_largest_numbers_ii.md:
--------------------------------------------------------------------------------
1 | ---
2 | difficulty: Medium
3 | tags:
4 | - Priority Queue
5 | - Heap
6 | - Data Stream
7 | title: Top k Largest Numbers II
8 | ---
9 |
10 | # Top k Largest Numbers II
11 |
12 | ## Problem
13 |
14 | ### Metadata
15 |
16 | - tags: Priority Queue, Heap, Data Stream
17 | - difficulty: Medium
18 | - source(lintcode):
19 |
20 | ### Description
21 |
22 | Implement a data structure, provide two interfaces:
23 |
24 | 1. `add(number)`. Add a new number in the data structure.
25 | 2. `topk()`. Return the top *k* largest numbers in this data structure. *k* is given when we create the data structure.
26 |
27 | #### Example
28 |
29 | ```
30 | s = new Solution(3);
31 | >> create a new data structure.
32 | s.add(3)
33 | s.add(10)
34 | s.topk()
35 | >> return [10, 3]
36 | s.add(1000)
37 | s.add(-99)
38 | s.topk()
39 | >> return [1000, 10, 3]
40 | s.add(4)
41 | s.topk()
42 | >> return [1000, 10, 4]
43 | s.add(100)
44 | s.topk()
45 | >> return [1000, 100, 10]
46 | ```
47 |
48 | ## 题解
49 |
50 | 此题只用堆的话在最后的排序输出会比较难受,最后用 List 的排序也可以。
51 |
52 | ### Java
53 |
54 | ```java
55 | public class Solution {
56 | private int k = -1;
57 | private Queue heap = null;
58 | /*
59 | * @param k: An integer
60 | */public Solution(int k) {
61 | // do intialization if necessary
62 | this.k = k;
63 | heap = new PriorityQueue(k);
64 | }
65 |
66 | /*
67 | * @param num: Number to be added
68 | * @return: nothing
69 | */
70 | public void add(int num) {
71 | // write your code here
72 | if (heap.size() < k) {
73 | heap.offer(num);
74 | } else if (heap.peek() < num) {
75 | heap.poll();
76 | heap.offer(num);
77 | }
78 | }
79 |
80 | /*
81 | * @return: Top k element
82 | */
83 | public List topk() {
84 | // write your code here
85 | List result = new ArrayList<>(k);
86 | Iterator it = heap.iterator();
87 | while(it.hasNext()) {
88 | result.add(it.next());
89 | }
90 | result.sort(Collections.reverseOrder());
91 | return result;
92 | }
93 | }
94 | ```
95 |
96 | ### 源码分析
97 |
98 | 略
99 |
100 | ### 复杂度分析
101 |
102 | 略
--------------------------------------------------------------------------------
/zh-hans/binary_search/README.md:
--------------------------------------------------------------------------------
1 | # Search - 搜索
2 |
3 | 本章主要总结二分搜索相关的题。
4 |
5 | - 能使用二分搜索的前提是数组已排序。
6 | - 二分查找的使用场景:(1)可转换为find the first/last position of...(2)时间复杂度至少为O(lgn)。
7 | - 递归和迭代的使用场景:能用迭代就用迭代,特别复杂时采用递归。
8 |
--------------------------------------------------------------------------------
/zh-hans/binary_search/first_position_of_target.md:
--------------------------------------------------------------------------------
1 | # First Position of Target
2 |
3 | ## Question
4 |
5 | - lintcode: [First Position of Target](http://www.lintcode.com/en/problem/first-position-of-target)
6 |
7 | ### Problem Statement
8 |
9 | For a given sorted array (ascending order) and a `target` number, find the
10 | first index of this number in `O(log n)` time complexity.
11 |
12 | If the target number does not exist in the array, return `-1`.
13 |
14 | #### Example
15 |
16 | If the array is `[1, 2, 3, 3, 4, 5, 10]`, for given target `3`, return `2`.
17 |
18 | #### Challenge
19 |
20 | If the count of numbers is bigger than $$2^{32}$$, can your code work properly?
21 |
22 | ## 题解
23 |
24 | 对于已排序升序(升序)数组,使用二分查找可满足复杂度要求,注意数组中可能有重复值,所以需要使用类似`lower_bound`中提到的方法。
25 |
26 | ### Java
27 |
28 | ```java
29 | class Solution {
30 | /**
31 | * @param nums: The integer array.
32 | * @param target: Target to find.
33 | * @return: The first position of target. Position starts from 0.
34 | */
35 | public int binarySearch(int[] nums, int target) {
36 | if (nums == null || nums.length == 0) {
37 | return -1;
38 | }
39 |
40 | int start = -1, end = nums.length;
41 | int mid;
42 | while (start + 1 < end) {
43 | // avoid overflow when (end + start)
44 | mid = start + (end - start) / 2;
45 | if (nums[mid] < target) {
46 | start = mid;
47 | } else {
48 | end = mid;
49 | }
50 | }
51 |
52 | if (end == nums.length || nums[end] != target) {
53 | return -1;
54 | } else {
55 | return end;
56 | }
57 | }
58 | }
59 |
60 | ```
61 |
62 | ### 源码分析
63 |
64 | 1. 首先对输入做异常处理,数组为空或者长度为0。
65 | 2. 初始化 `start, end, mid`三个变量,这里`start`初始化为`-1`主要是考虑到`end`为`1`。注意mid的求值方法,可以防止两个整型值相加时溢出。
66 | 3. **使用迭代而不是递归**进行二分查找,因为工程中递归写法存在潜在溢出的可能。
67 | 4. while终止条件应为`start + 1 < end`而不是`start <= end`,`start == end`时可能出现死循环。**即循环终止条件是相邻或相交元素时退出。**由于这里初始化时`start < end`,所以一定是`start + 1 == end`时退出循环。
68 | 5. 迭代终止时有两种情况,一种是在原数组中找到了,这种情况下一定是`end`, 因为`start`的更新只在`nums[mid] < target`.
69 | 6. 最后判断`end`和`target`的关系,先排除`end`为数组长度这种会引起越界的情况,然后再判断和目标值是否相等。
70 |
71 | ### 复杂度分析
72 |
73 | 时间复杂度 $$O(\log n)$$, 空间复杂度 $$(1)$$.
74 | 对于题中的 follow up, Java 中数组不允许使用 long 型,如果使用 long 型,那么数组大小可大 17GB 之巨!!几乎没法用。
75 |
76 | ## Reference
77 |
78 | - 《挑战程序设计竞赛》3.1节
79 |
--------------------------------------------------------------------------------
/zh-hans/binary_search_tree/README.md:
--------------------------------------------------------------------------------
1 | # Binary Search Tree - 二叉搜索树
2 |
3 | 二叉搜索树的定义及简介在 [Binary Search Trees](http://algorithm.yuanbin.me/zh-hans/basics_data_structure/binary_search_tree.html) 中已经有所介绍。简单来说就是当前节点的值大于等于左子结点的值,而小于右子节点的值。
4 |
--------------------------------------------------------------------------------
/zh-hans/binary_tree/README.md:
--------------------------------------------------------------------------------
1 | Maximum Depth of Binary Tree# Binary Tree - 二叉树
2 |
3 | 二叉树的基本概念在 [Binary Tree | Algorithm](http://algorithm.yuanbin.me/zh-hans/basics_data_structure/binary_tree.html) 中有简要的介绍,这里就二叉树的一些应用做一些实战演练。
4 |
5 | 二叉树的遍历大致可分为前序、中序、后序三种方法。
6 |
7 |
8 | 下图是把本章中所有出现的题目归类总结了一下,便于记忆
9 |
10 | 
--------------------------------------------------------------------------------
/zh-hans/binary_tree/diameter_of_a_binary_tree.md:
--------------------------------------------------------------------------------
1 | # Diameter of a Binary Tree
2 |
3 | ## Question
4 |
5 | - [Diameter of a Binary Tree - GeeksforGeeks](http://www.geeksforgeeks.org/diameter-of-a-binary-tree/)
6 |
7 | ```
8 | The diameter of a tree (sometimes called the width) is the number of nodes
9 | on the longest path between two leaves in the tree.
10 | The diagram below shows two trees each with diameter nine,
11 | the leaves that form the ends of a longest path are shaded
12 | (note that there is more than one path in each tree of length nine,
13 | but no path longer than nine nodes).
14 | ```
15 |
16 | 
17 |
18 | ## 题解
19 |
20 | 和题 [Lowest Common Ancestor](http://algorithm.yuanbin.me/zh-hans/binary_tree/lowest_common_ancestor.html) 分析思路特别接近。
21 |
22 | ### Java
23 |
24 | ```java
25 | class TreeNode {
26 | int val;
27 | TreeNode left, right;
28 | TreeNode(int val) {
29 | this.val = val;
30 | this.left = null;
31 | this.right = null;
32 | }
33 | }
34 |
35 | public class Solution {
36 | public int diameter(TreeNode root) {
37 | if (root == null) return 0;
38 |
39 | // left, right height
40 | int leftHight = getHeight(root.left);
41 | int rightHight = getHeight(root.right);
42 |
43 | // left, right subtree diameter
44 | int leftDia = diameter(root.left);
45 | int rightDia = diameter(root.right);
46 |
47 | int maxSubDia = Math.max(leftDia, rightDia);
48 | return Math.max(maxSubDia, leftHight + 1 + rightHight);
49 | }
50 |
51 | private int getHeight(TreeNode root) {
52 | if (root == null) return 0;
53 |
54 | return 1 + Math.max(getHeight(root.left), getHeight(root.right));
55 | }
56 |
57 | public static void main(String[] args) {
58 | TreeNode root = new TreeNode(1);
59 | root.left = new TreeNode(2);
60 | root.right = new TreeNode(3);
61 | root.left.left = new TreeNode(4);
62 | root.left.right = new TreeNode(5);
63 | root.left.right.left = new TreeNode(6);
64 | root.left.right.left.right = new TreeNode(7);
65 | root.left.left.left = new TreeNode(8);
66 |
67 | Solution sol = new Solution();
68 | int maxDistance = sol.diameter(root);
69 | System.out.println("Max Distance: " + maxDistance);
70 | }
71 | }
72 | ```
73 |
74 | ## Reference
75 |
76 | - [Diameter of a Binary Tree - GeeksforGeeks](http://www.geeksforgeeks.org/diameter-of-a-binary-tree/)
77 | - [Diameter of a Binary Tree | Algorithms](http://algorithms.tutorialhorizon.com/diameter-of-a-binary-tree/)
78 |
--------------------------------------------------------------------------------
/zh-hans/binary_tree/subtree.md:
--------------------------------------------------------------------------------
1 | # Subtree
2 |
3 | ## Question
4 |
5 | - lintcode: [(245) Subtree](http://www.lintcode.com/en/problem/subtree/#)
6 |
7 | ```
8 | You have two every large binary trees: T1,
9 | with millions of nodes, and T2, with hundreds of nodes.
10 | Create an algorithm to decide if T2 is a subtree of T1.
11 |
12 | Example
13 | T2 is a subtree of T1 in the following case:
14 | 1 3
15 | / \ /
16 | T1 = 2 3 T2 = 4
17 | /
18 | 4
19 | T2 isn't a subtree of T1 in the following case:
20 | 1 3
21 | / \ \
22 | T1 = 2 3 T2 = 4
23 | /
24 | 4
25 | Note
26 | A tree T2 is a subtree of T1 if there exists a node n in T1 such that
27 | the subtree of n is identical to T2.
28 | That is, if you cut off the tree at node n,
29 | the two trees would be identical.
30 | ```
31 |
32 | ## 题解
33 |
34 | 判断 T2是否是 T1的子树,首先应该在 T1中找到 T2的根节点,找到根节点后两棵子树必须完全相同。所以整个思路分为两步走:找根节点,判断两棵树是否全等。咋看起来极其简单,但实际实现中还是比较精妙的,尤其是递归的先后顺序及条件与条件或的处理。
35 |
36 | ### Java
37 |
38 | ```java
39 | /**
40 | * Definition of TreeNode:
41 | * public class TreeNode {
42 | * public int val;
43 | * public TreeNode left, right;
44 | * public TreeNode(int val) {
45 | * this.val = val;
46 | * this.left = this.right = null;
47 | * }
48 | * }
49 | */
50 | public class Solution {
51 | /**
52 | * @param T1, T2: The roots of binary tree.
53 | * @return: True if T2 is a subtree of T1, or false.
54 | */
55 | public boolean isSubtree(TreeNode T1, TreeNode T2) {
56 | if (T2 == null) return true;
57 | if (T1 == null) return false;
58 | return identical(T1, T2) || isSubtree(T1.left, T2) || isSubtree(T1.right, T2);
59 | }
60 |
61 | private boolean identical(TreeNode T1, TreeNode T2) {
62 | if (T1 == null && T2 == null) return true;
63 | if (T1 == null || T2 == null) return false;
64 | if (T1.val != T2.val) return false;
65 | return identical(T1.left, T2.left) && identical(T1.right, T2.right);
66 | }
67 | }
68 | ```
69 |
70 | ### 源码分析
71 |
72 | 这道题的异常处理相对 trick 一点,需要理解 null 对子树的含义。另外需要先调用`identical`再递归调用`isSubtree`判断左右子树的情况。方法`identical`中调用`.val`前需要判断是否为 null, 而后递归调用判断左右子树是否 identical。
73 |
74 | ### 复杂度分析
75 |
76 | identical 的调用,时间复杂度近似 $$O(n)$$, 查根节点的时间复杂度随机,平均为 $$O(m)$$, 故总的时间复杂度可近似为 $$O(mn)$$.
77 |
78 | ## Reference
79 |
80 | - [LintCode: Subtree](http://cherylintcode.blogspot.com/2015/06/subtree.html)
81 |
--------------------------------------------------------------------------------
/zh-hans/cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/zh-hans/cover.jpg
--------------------------------------------------------------------------------
/zh-hans/cover_small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/billryan/algorithm-exercise/ff1ae6c218ef1e554cba0a3f88aa265240db7d54/zh-hans/cover_small.jpg
--------------------------------------------------------------------------------
/zh-hans/data_structure/README.md:
--------------------------------------------------------------------------------
1 | # Data Structure
2 |
3 | 本章主要总结数据结构如 Queue, Stack 等相关的题。
4 |
--------------------------------------------------------------------------------
/zh-hans/data_structure/implement_queue_by_two_stacks.md:
--------------------------------------------------------------------------------
1 | # Implement Queue by Two Stacks
2 |
3 | ## Question
4 |
5 | - lintcode: [(40) Implement Queue by Two Stacks](http://www.lintcode.com/en/problem/implement-queue-by-two-stacks/)
6 |
7 | ```
8 | As the title described, you should only use two stacks to implement a queue's actions.
9 |
10 | The queue should support push(element),
11 | pop() and top() where pop is pop the first(a.k.a front) element in the queue.
12 |
13 | Both pop and top methods should return the value of first element.
14 |
15 | Example
16 | For push(1), pop(), push(2), push(3), top(), pop(), you should return 1, 2 and 2
17 |
18 | Challenge
19 | implement it by two stacks, do not use any other data structure and push,
20 | pop and top should be O(1) by AVERAGE.
21 | ```
22 |
23 | ## 题解
24 |
25 | 两个栈模拟队列,栈是 LIFO, 队列是 FIFO, 故用两个栈模拟队列时可结合栈1和栈2, LIFO + LIFO ==> FIFO, 即先将一个栈元素全部 push 到另一个栈,效果即等价于 Queue.
26 |
27 | ### Java
28 |
29 | ```java
30 | public class Solution {
31 | private Stack stack1;
32 | private Stack stack2;
33 |
34 | public Solution() {
35 | // source stack
36 | stack1 = new Stack();
37 | // target stack
38 | stack2 = new Stack();
39 | }
40 |
41 | public void push(int element) {
42 | stack1.push(element);
43 | }
44 |
45 | public int pop() {
46 | if (stack2.empty()) {
47 | stack1ToStack2(stack1, stack2);
48 | }
49 | return stack2.pop();
50 | }
51 |
52 | public int top() {
53 | if (stack2.empty()) {
54 | stack1ToStack2(stack1, stack2);
55 | }
56 | return stack2.peek();
57 | }
58 |
59 | private void stack1ToStack2(Stack stack1, Stack stack2) {
60 | while (!stack1.empty()) {
61 | stack2.push(stack1.pop());
62 | }
63 | }
64 | }
65 | ```
66 |
67 | ### 源码分析
68 |
69 | 将栈1作为原始栈,将栈1元素压入栈2是公共方法,故写成一个私有方法。
70 |
71 | ### 复杂度分析
72 |
73 | 视连续 push 的元素而定,时间复杂度近似为 $$O(1)$$.
74 |
75 | ## Reference
76 |
77 | - [Implement Queue by Two Stacks 参考程序 Java/C++/Python](http://www.jiuzhang.com/solutions/implement-queue-by-two-stacks/)
78 |
--------------------------------------------------------------------------------
/zh-hans/data_structure/longest_words.md:
--------------------------------------------------------------------------------
1 | # Longest Words
2 |
3 | ## Question
4 |
5 | - lintcode: [(133) Longest Words](http://www.lintcode.com/en/problem/longest-words/)
6 |
7 | ```
8 | Given a dictionary, find all of the longest words in the dictionary.
9 |
10 | Example
11 | Given
12 |
13 | {
14 | "dog",
15 | "google",
16 | "facebook",
17 | "internationalization",
18 | "blabla"
19 | }
20 | the longest words are(is) ["internationalization"].
21 |
22 | Given
23 |
24 | {
25 | "like",
26 | "love",
27 | "hate",
28 | "yes"
29 | }
30 | the longest words are ["like", "love", "hate"].
31 |
32 | Challenge
33 | It's easy to solve it in two passes, can you do it in one pass?
34 | ```
35 |
36 | ## 题解
37 |
38 | 简单题,容易想到的是首先遍历以便,找到最长的字符串,第二次遍历时取最长的放到最终结果中。但是如果只能进行一次遍历呢?一次遍历意味着需要维护当前遍历的最长字符串,这必然有比较与更新删除操作,这种情况下使用双端队列最为合适,这道题稍微特殊一点,不必从尾端插入,只需在遍历时若发现比数组中最长的元素还长时删除整个列表。
39 |
40 | ### Java
41 |
42 | ```java
43 | class Solution {
44 | /**
45 | * @param dictionary: an array of strings
46 | * @return: an arraylist of strings
47 | */
48 | ArrayList longestWords(String[] dictionary) {
49 | ArrayList result = new ArrayList();
50 | if (dictionary == null || dictionary.length == 0) return result;
51 |
52 | for (String str : dictionary) {
53 | // combine empty and shorter length
54 | if (result.isEmpty() || str.length() > result.get(0).length()) {
55 | result.clear();
56 | result.add(str);
57 | } else if (str.length() == result.get(0).length()) {
58 | result.add(str);
59 | }
60 | }
61 |
62 | return result;
63 | }
64 | }
65 | ```
66 |
67 | ### 源码分析
68 |
69 | 熟悉变长数组的常用操作。
70 |
71 | ### 复杂度分析
72 |
73 | 时间复杂度 $$O(n)$$, 最坏情况下需要保存 n - 1个字符串,空间复杂度 $$O(n)$$.
74 |
75 | ## Reference
76 |
77 | - [Lintcode: Longest Words | codesolutiony](https://codesolutiony.wordpress.com/2015/06/07/lintcode-longest-words/)
78 |
--------------------------------------------------------------------------------
/zh-hans/data_structure/min_stack.md:
--------------------------------------------------------------------------------
1 | # Min Stack
2 |
3 | ## Question
4 |
5 | - lintcode: [(12) Min Stack](http://www.lintcode.com/en/problem/min-stack/)
6 |
7 | ```
8 | Implement a stack with min() function,
9 | which will return the smallest number in the stack.
10 |
11 | It should support push, pop and min operation all in O(1) cost.
12 |
13 | Example
14 | Operations: push(1), pop(), push(2), push(3), min(), push(1), min() Return: 1, 2, 1
15 |
16 | Note
17 | min operation will never be called if there is no number in the stack
18 | ```
19 |
20 | ## 题解
21 |
22 | 『最小』栈,要求在栈的基础上实现可以在 $$O(1)$$ 的时间内找出最小值,一般这种 $$O(1)$$的实现往往就是哈希表或者哈希表的变体,这里简单起见可以另外克隆一个栈用以跟踪当前栈的最小值。
23 |
24 | ### Java
25 |
26 | ```java
27 | public class Solution {
28 | public Solution() {
29 | stack1 = new Stack();
30 | stack2 = new Stack();
31 | }
32 |
33 | public void push(int number) {
34 | stack1.push(number);
35 | if (stack2.empty()) {
36 | stack2.push(number);
37 | } else {
38 | stack2.push(Math.min(number, stack2.peek()));
39 | }
40 | }
41 |
42 | public int pop() {
43 | stack2.pop();
44 | return stack1.pop();
45 | }
46 |
47 | public int min() {
48 | return stack2.peek();
49 | }
50 |
51 | private Stack stack1; // original stack
52 | private Stack stack2; // min stack
53 | }
54 | ```
55 |
56 | ### 源码分析
57 |
58 | 取最小栈的栈顶值时需要先判断是否为空栈(而不仅是 null)。
59 |
60 | ### 复杂度分析
61 |
62 | 均为 $$O(1)$$.
63 |
--------------------------------------------------------------------------------
/zh-hans/dynamic_programming/climbing_stairs.md:
--------------------------------------------------------------------------------
1 | # Climbing Stairs
2 |
3 | ## Question
4 |
5 | - lintcode: [(111) Climbing Stairs](http://www.lintcode.com/en/problem/climbing-stairs/)
6 |
7 | ```
8 | You are climbing a stair case. It takes n steps to reach to the top.
9 |
10 | Each time you can either climb 1 or 2 steps.
11 | In how many distinct ways can you climb to the top?
12 |
13 | Example
14 | Given an example n=3 , 1+1+1=2+1=1+2=3
15 |
16 | return 3
17 | ```
18 |
19 | ## 题解
20 |
21 | 题目问的是到达顶端的方法数,我们采用序列类问题的通用分析方法,可以得到如下四要素:
22 |
23 | 1. State: f[i] 爬到第i级的方法数
24 | 2. Function: f[i]=f[i-1]+f[i-2]
25 | 3. Initialization: f[0]=1,f[1]=1
26 | 4. Answer: f[n]
27 |
28 | 尤其注意状态转移方程的写法,f[i]只可能由两个中间状态转化而来,一个是f[i-1],由f[i-1]到f[i]其方法总数并未增加;另一个是f[i-2],由f[i-2]到f[i]隔了两个台阶,因此有1+1和2两个方法,因此容易写成 f[i]=f[i-1]+f[i-2]+1,但仔细分析后能发现,由f[i-2]到f[i]的中间状态f[i-1]已经被利用过一次,故f[i]=f[i-1]+f[i-2]. 使用动规思想解题时需要分清『重叠子状态』, 如果有重复的需要去重。
29 |
30 | ### C++
31 |
32 | ```c++
33 | class Solution {
34 | public:
35 | /**
36 | * @param n: An integer
37 | * @return: An integer
38 | */
39 | int climbStairs(int n) {
40 | if (n < 1) {
41 | return 0;
42 | }
43 |
44 | vector ret(n + 1, 1);
45 |
46 | for (int i = 2; i != n + 1; ++i) {
47 | ret[i] = ret[i - 1] + ret[i - 2];
48 | }
49 |
50 | return ret[n];
51 | }
52 | };
53 | ```
54 |
55 | 1. 异常处理
56 | 2. 初始化n+1个元素,初始值均为1。之所以用n+1个元素是下标分析起来更方便
57 | 3. 状态转移方程
58 | 4. 返回ret[n]
59 |
60 | 初始化ret[0]也为1,可以认为到第0级也是一种方法。
61 |
62 | 以上答案的空间复杂度为 $$O(n)$$,仔细观察后可以发现在状态转移方程中,我们可以使用三个变量来替代长度为n+1的数组。具体代码可参考 [climbing-stairs | 九章算法 ](http://www.jiuzhang.com/solutions/climbing-stairs/)
63 |
64 | ### Python
65 | ```python
66 | class Solution:
67 | def climbStairs(n):
68 | if n < 1:
69 | return 0
70 |
71 | l = r = 1
72 | for _ in xrange(n - 1):
73 | l, r = r, r + l
74 | return r
75 | ```
76 |
77 | ### C++
78 |
79 | ```c++
80 | class Solution {
81 | public:
82 | /**
83 | * @param n: An integer
84 | * @return: An integer
85 | */
86 | int climbStairs(int n) {
87 | if (n < 1) {
88 | return 0;
89 | }
90 |
91 | int ret0 = 1, ret1 = 1, ret2 = 1;
92 |
93 | for (int i = 2; i != n + 1; ++i) {
94 | ret0 = ret1 + ret2;
95 | ret2 = ret1;
96 | ret1 = ret0;
97 | }
98 |
99 | return ret0;
100 | }
101 | };
102 | ```
103 |
--------------------------------------------------------------------------------
/zh-hans/dynamic_programming/matrix.md:
--------------------------------------------------------------------------------
1 | # Matrix
2 |
3 | 本节主要总结矩阵类动态规划问题,
4 |
--------------------------------------------------------------------------------
/zh-hans/dynamic_programming/unique_paths.md:
--------------------------------------------------------------------------------
1 | # Unique Paths
2 |
3 | - tags: [DP_Matrix]
4 |
5 | ## Question
6 |
7 | - lintcode: [(114) Unique Paths](http://www.lintcode.com/en/problem/unique-paths/)
8 |
9 | ```
10 | A robot is located at the top-left corner of a m x n grid
11 | (marked 'Start' in the diagram below).
12 |
13 | The robot can only move either down or right at any point in time.
14 | The robot is trying to reach the bottom-right corner of the grid
15 | (marked 'Finish' in the diagram below).
16 |
17 | How many possible unique paths are there?
18 |
19 | Note
20 | m and n will be at most 100.
21 | ```
22 |
23 | ## 题解
24 |
25 | 题目要求:给定*m x n*矩阵,求左上角到右下角的路径总数,每次只能向左或者向右前进。按照动态规划中矩阵类问题的通用方法:
26 |
27 | 1. State: f[m][n] 从起点到坐标(m,n)的路径数目
28 | 2. Function: f[m][n] = f[m-1][n] + f[m][n-1] 分析终点与左边及右边节点的路径数,发现从左边或者右边到达终点的路径一定不会重合,相加即为唯一的路径总数
29 | 3. Initialization: f[i][j] = 1, 到矩阵中任一节点均至少有一条路径,其实关键之处在于给第0行和第0列初始化,免去了单独遍历第0行和第0列进行初始化
30 | 4. Answer: f[m - 1][n - 1]
31 |
32 | ### C++
33 |
34 | ```c++
35 | class Solution {
36 | public:
37 | /**
38 | * @param n, m: positive integer (1 <= n ,m <= 100)
39 | * @return an integer
40 | */
41 | int uniquePaths(int m, int n) {
42 | if (m < 1 || n < 1) {
43 | return 0;
44 | }
45 |
46 | vector > ret(m, vector(n, 1));
47 |
48 | for (int i = 1; i != m; ++i) {
49 | for (int j = 1; j != n; ++j) {
50 | ret[i][j] = ret[i - 1][j] + ret[i][j - 1];
51 | }
52 | }
53 |
54 | return ret[m - 1][n - 1];
55 | }
56 | };
57 | ```
58 |
59 | ### 源码分析
60 |
61 | 1. 异常处理,虽然题目有保证为正整数,但还是判断一下以防万一
62 | 2. 初始化二维矩阵,值均为1
63 | 3. 按照转移矩阵函数进行累加
64 | 4. 任何`ret[m - 1][n - 1]`
65 |
--------------------------------------------------------------------------------
/zh-hans/exhaustive_search/README.md:
--------------------------------------------------------------------------------
1 | # Exhaustive Search - 穷竭搜索
2 |
3 | 穷竭搜索又称暴力搜索,指代将所有可能性列出来,然后再在其中寻找满足题目条件的解。常用求解方法和工具有:
4 |
5 | 1. 递归函数
6 | 2. 栈
7 | 3. 队列
8 | 4. 深度优先搜索(DFS, Depth-First Search),又常称为回溯法
9 | 5. 广度优先搜索(BFS, Breadth-First Search)
10 |
11 | 1, 2, 3 往往在深搜或者广搜中体现。
12 |
13 | ## DFS
14 |
15 | DFS 通常从某个状态开始,根据特定的规则转移状态,直至无法转移(节点为空),然后回退到之前一步状态,继续按照指定规则转移状态,直至遍历完所有状态。
16 |
17 | 回溯法包含了多类问题,模板类似。
18 |
19 | 排列组合模板->搜索问题(是否要排序,哪些情况要跳过)
20 |
21 | 使用回溯法的一般步骤:
22 |
23 | 1. 确定所给问题的解空间:首先应明确定义问题的解空间,解空间中至少包含问题的一个解。
24 | 2. 确定结点的扩展搜索规则
25 | 3. 以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
26 |
27 | ### BFS
28 |
29 | BFS 从某个状态开始,搜索**所有可以到达的状态**,转移顺序为『初始状态->只需一次转移就可到达的所有状态->只需两次转移就可到达的所有状态->...』,所以对于同一个状态,BFS 只搜索一次,故时间复杂度为 $$O(states \times transfer\_methods)$$. BFS 通常配合队列一起使用,搜索时先将状态加入到队列中,然后从队列顶端不断取出状态,再把从该状态可转移到的状态中尚未访问过的部分加入队列,知道队列为空或已找到解。因此 BFS 适合用于『由近及远』的搜索,比较适合用于求解最短路径、最少操作之类的问题。
30 |
31 | ## Reference
32 |
33 | - 《挑战程序设计竞赛》Chaper 2.1 p26 最基础的“穷竭搜索”
34 | - [Steven Skiena: Lecture15 - Backtracking](http://7xojrx.com1.z0.glb.clouddn.com/docs/algorithm-exercise/docs/lecture15-backtracking.pdf)
35 | - [全面解析回溯法:算法框架与问题求解 - 五岳 - 博客园](http://www.cnblogs.com/wuyuegb2312/p/3273337.html)
36 | - [五大常用算法之四:回溯法 - 红脸书生 - 博客园](http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741376.html)
37 | - [演算法筆記 - Backtracking](http://www.csie.ntnu.edu.tw/~u91029/Backtracking.html)
38 |
--------------------------------------------------------------------------------
/zh-hans/exhaustive_search/combinations.md:
--------------------------------------------------------------------------------
1 | # Combinations
2 |
3 | ## Question
4 |
5 | - leetcode: [Combinations | LeetCode OJ](https://leetcode.com/problems/combinations/)
6 | - lintcode: [(152) Combinations](http://www.lintcode.com/en/problem/combinations/)
7 |
8 | ### Problem Statement
9 |
10 | Given two integers n and k,
11 | return all possible combinations of k numbers out of 1 ... n.
12 |
13 | #### Example
14 |
15 | For example,
16 | If n = 4 and k = 2, a solution is:
17 | `[[2,4],[3,4],[2,3],[1,2],[1,3],[1,4]]`
18 |
19 | ## 题解
20 |
21 | 套用 [Permutations](http://algorithm.yuanbin.me/zh-hans/exhaustive_search/permutations.html) 模板。
22 |
23 | ### Java
24 |
25 | ```java
26 | public class Solution {
27 | public List> combine(int n, int k) {
28 | assert(n >= 1 && n >= k && k >= 1);
29 |
30 | List> result = new ArrayList>();
31 | List list = new ArrayList();
32 | dfs(n, k, 1, list, result);
33 |
34 | return result;
35 | }
36 |
37 | private void dfs(int n, int k, int pos, List list,
38 | List> result) {
39 |
40 | if (list.size() == k) {
41 | result.add(new ArrayList(list));
42 | return;
43 | }
44 | for (int i = pos; i <= n; i++) {
45 | list.add(i);
46 | dfs(n, k, i + 1, list, result);
47 | list.remove(list.size() - 1);
48 | }
49 | }
50 | }
51 | ```
52 |
53 | ### 源码分析
54 |
55 | 注意递归`helper(n, k, i + 1, list, result);`中的`i + 1`,不是`pos + 1`。
56 |
57 | ### 复杂度分析
58 |
59 | 状态数 $$C_n^2$$, 每组解有两个元素,故时间复杂度应为 $$O(n^2)$$. list 只保留最多两个元素,空间复杂度 $$O(1)$$.
60 |
--------------------------------------------------------------------------------
/zh-hans/exhaustive_search/minimum_depth_of_binary_tree.md:
--------------------------------------------------------------------------------
1 | # Minimum Depth of Binary Tree
2 |
3 | ## Question
4 |
5 | - leetcode: [Minimum Depth of Binary Tree | LeetCode OJ](https://leetcode.com/problems/minimum-depth-of-binary-tree/)
6 | - lintcode: [(155) Minimum Depth of Binary Tree](http://www.lintcode.com/en/problem/minimum-depth-of-binary-tree/)
7 |
8 | ```
9 | Given a binary tree, find its minimum depth.
10 |
11 | The minimum depth is the number of nodes along the shortest path
12 | from the root node down to the nearest leaf node.
13 |
14 | Example
15 | Given a binary tree as follow:
16 |
17 | 1
18 |
19 | / \
20 |
21 | 2 3
22 |
23 | / \
24 |
25 | 4 5
26 | The minimum depth is 2
27 | ```
28 |
29 | ## 题解
30 |
31 | 注意审题,题中的最小深度指的是从根节点到**最近的叶子节点(因为题中的最小深度是the number of nodes,故该叶子节点不能是空节点)**,所以需要单独处理叶子节点为空的情况。此题使用 DFS 递归实现比较简单。
32 |
33 | ### Java
34 |
35 | ```java
36 | /**
37 | * Definition of TreeNode:
38 | * public class TreeNode {
39 | * public int val;
40 | * public TreeNode left, right;
41 | * public TreeNode(int val) {
42 | * this.val = val;
43 | * this.left = this.right = null;
44 | * }
45 | * }
46 | */
47 | public class Solution {
48 | /**
49 | * @param root: The root of binary tree.
50 | * @return: An integer.
51 | */
52 | public int minDepth(TreeNode root) {
53 | if (root == null) return 0;
54 |
55 | int leftDepth = minDepth(root.left);
56 | int rightDepth = minDepth(root.right);
57 |
58 | // current node is not leaf node
59 | if (root.left == null) {
60 | return 1 + rightDepth;
61 | } else if (root.right == null) {
62 | return 1 + leftDepth;
63 | }
64 |
65 | return 1 + Math.min(leftDepth, rightDepth);
66 | }
67 | }
68 | ```
69 |
70 | ### 源码分析
71 |
72 | 建立好递归模型即可,左右子节点为空时需要单独处理下。
73 |
74 | ### 复杂度分析
75 |
76 | 每个节点遍历一次,时间复杂度 $$O(n)$$. 不计栈空间的话空间复杂度 $$O(1)$$.
77 |
--------------------------------------------------------------------------------
/zh-hans/faq/README.md:
--------------------------------------------------------------------------------
1 | # FAQ - 常见问题答疑
2 |
3 | 本节主要整理一些常见问题,如『如何贡献』、『有疑问如何讨论』和授权协议等。
4 |
5 | ## 能说一下项目的背景吗?
6 |
7 | 最开始的维护者为 [@billryan](https://github.com/billryan), 由于他在学习算法的过程中需要使用 markdown 记录自己的学习心得,正好发现 Gitbook 很好地满足了他对使用 markdown 写技术笔记的所有幻想。
8 |
9 | ## 在网页上发现有错误的地方怎么办?
10 |
11 | 有两种相对轻量级一点的方式:disqus 评论和 GitHub 的 Web 界面更改。markdown 标记语言简明清晰,不会成为贡献内容的障碍。
12 |
13 | ### GitHub Edit Link
14 |
15 | 最简单的方式是通过网页最上方的『改进此页』在 GitHub 的 Web 界面上更改并提交 Pull Request. 也许你之前并没有 git 相关经验,没关系,下面的截图视频教你怎么玩儿。
16 |
17 | 
18 |
19 | 总结下来就是:
20 |
21 | 1. 点击『改进此页』
22 | 2. 跳转至 GitHub 登陆界面认证后在 Web 上更改你觉得有问题的地方
23 | 3. 改好后在下方的 comment 处简要说一下更改的理由
24 | 4. Pull Request
25 |
26 | 不要告诉我你没有 GitHub 账号...
27 |
28 | ### Disqus
29 |
30 | 如果你实在是不想在 GitHub 的 Contributor 处青史留名,那就通过这种方式吧!Maintainer 稍微辛苦点就是...
31 | 另外你也可以通过 Disqus 在相应网页下提出你的疑问。
32 | disqus 的评论处直接粘贴代码十分难看,参考 [syntax highlighting](https://help.disqus.com/customer/portal/articles/665057-syntax-highlighting) 改进。
33 |
34 | ## 我想成为重量级贡献者!
35 |
36 | 不要犹豫!快到碗里来!猛戳 [贡献指南](http://algorithm.yuanbin.me/zh-hans/faq/guidelines_for_contributing.html)
37 |
38 | ## 有暂时没出现在网页上的问题怎么办?
39 |
40 | 有两种方式:GitHub issues 和 Slack.
41 | 你可以加入 Slack 群 - 和我们一起讨论。
42 |
43 | ## 如何订阅更新的内容?
44 |
45 | 本项目托管在 由 [Gitbook](https://www.gitbook.com/book/yuanbin/algorithm/details) 渲染生成 HTML 页面。
46 | 你可以在 GitHub 中 star 该项目手动查看更新,也可以订阅 中的 `#github_commit` channel 在邮件中查看更新细节,~~RSS 种子功能正在开发中~~。
47 |
48 | Slack 的自助邀请注册功能已启用,访问 即刻开启~
49 | Gitbook 虽然也有 star 和 subscribe 功能,但目前来看还是非常鸡肋,通过 Slack 的 `#github_commit` channel 你可以看到对单文件`diff`级别的改动。
50 |
51 | **号外:Slack 的 [shua-shua-shua](https://ds-algo.slack.com/messages/shua-shua-shua/details/) channel 用于刷题小组讨论,大家可以在这个 channel 里一起讨论学习算法。**
52 |
53 | ## 我觉得这个文档整理的真好,接受捐助吗?
54 |
55 | 当然!除了 GitHub 上 star 或者帮助改进内容外,你还可以以现金或者其他实物激励我们创造出更好的内容!
56 |
57 | ### 邮寄明信片
58 |
59 | @billryan 喜欢收集各种明信片,来者不拒~ 邮寄的话可以邮寄至 `上海市闵行区上海交通大学闵行校区电院群楼5号楼307`,收件人:`袁斌`。
60 |
61 | ### 送书
62 |
63 | 除了邮寄明信片,你还可以买本书送给各位贡献者,@billryan 的地址见上节。
64 |
65 | ### 支付宝
66 |
67 | 
68 |
69 | 账户名:yuanbin2014(at)gmail.com 金额随意
70 |
71 | ### Wechat
72 |
73 | 
74 |
75 | 金额随意
76 |
77 | ### PayPal
78 |
79 | 账户名:yuanbin2014(at)gmail.com 金额随意,付款时选择 friends and family
80 |
--------------------------------------------------------------------------------
/zh-hans/google_apac/README.md:
--------------------------------------------------------------------------------
1 | # Google APAC
2 |
3 | 本章总结 Google APAC 的一些题。
4 |
--------------------------------------------------------------------------------
/zh-hans/google_apac/google_apac_2015_round_b/A-large-practice.in:
--------------------------------------------------------------------------------
1 | 100
2 | 1 1
3 | 3 4
4 | 5 5
5 | 15 15
6 | 100 100
7 | 66 100
8 | 77 97
9 | 7 11
10 | 36 47
11 | 10 41
12 | 31 35
13 | 4 42
14 | 81 85
15 | 41 84
16 | 20 85
17 | 46 95
18 | 17 30
19 | 6 25
20 | 2 4
21 | 2 2
22 | 71 99
23 | 12 12
24 | 27 65
25 | 6 39
26 | 9 15
27 | 3 22
28 | 2 51
29 | 47 63
30 | 5 17
31 | 6 28
32 | 40 53
33 | 42 64
34 | 40 100
35 | 5 37
36 | 47 53
37 | 42 65
38 | 65 88
39 | 90 99
40 | 37 50
41 | 1 15
42 | 3 67
43 | 32 65
44 | 7 55
45 | 20 56
46 | 23 24
47 | 1 25
48 | 6 9
49 | 14 58
50 | 24 79
51 | 6 15
52 | 12 36
53 | 31 34
54 | 8 8
55 | 3 27
56 | 9 68
57 | 11 25
58 | 40 81
59 | 46 55
60 | 50 67
61 | 5 7
62 | 33 45
63 | 7 18
64 | 41 74
65 | 4 12
66 | 39 72
67 | 10 34
68 | 24 58
69 | 9 82
70 | 29 51
71 | 21 25
72 | 30 53
73 | 25 56
74 | 83 89
75 | 3 68
76 | 26 72
77 | 37 49
78 | 2 8
79 | 13 20
80 | 39 92
81 | 15 84
82 | 25 61
83 | 36 74
84 | 27 89
85 | 9 86
86 | 1 19
87 | 5 13
88 | 6 11
89 | 4 4
90 | 15 82
91 | 1 6
92 | 28 97
93 | 16 20
94 | 33 71
95 | 47 89
96 | 4 26
97 | 20 29
98 | 19 45
99 | 5 8
100 | 7 13
101 | 12 76
102 |
--------------------------------------------------------------------------------
/zh-hans/google_apac/google_apac_2015_round_b/A-small-practice.in:
--------------------------------------------------------------------------------
1 | 15
2 | 1 1
3 | 3 4
4 | 5 5
5 | 7 7
6 | 4 7
7 | 4 4
8 | 6 6
9 | 1 7
10 | 1 2
11 | 1 6
12 | 2 4
13 | 1 5
14 | 6 7
15 | 5 5
16 | 3 4
17 |
--------------------------------------------------------------------------------
/zh-hans/google_apac/google_apac_2015_round_b/README.md:
--------------------------------------------------------------------------------
1 | # APAC 2015 Round B
2 |
3 | - [Dashboard - Round B APAC Test - Google Code Jam](https://code.google.com/codejam/contest/4214486/dashboard)
4 |
--------------------------------------------------------------------------------
/zh-hans/google_apac/google_apac_2015_round_b/Solution.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 |
3 | public class Solution {
4 | public static void main(String[] args) {
5 | Scanner in = new Scanner(System.in);
6 | int T = in.nextInt();
7 | // System.out.println("T = " + T);
8 | for (int t = 1; t <= T; t++) {
9 | int M = in.nextInt(), N = in.nextInt();
10 | long ans = solve(M, N);
11 | // System.out.printf("M = %d, N = %d\n", M, N);
12 | System.out.printf("Case #%d: %d\n", t, ans);
13 | }
14 | }
15 |
16 | public static long solve(int M, int N) {
17 | long[][] dp = new long[1 + M][1 + N];
18 | long mod = 1000000007;
19 | for (int j = 1; j <= N; j++) {
20 | dp[1][j] = 1;
21 | }
22 | for (int i = 2; i <= M; i++) {
23 | for (int j = i; j <= N; j++) {
24 | dp[i][j] = i * (dp[i][j - 1] + dp[i - 1][j - 1]);
25 | dp[i][j] %= mod;
26 | }
27 | }
28 |
29 | return dp[M][N];
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/zh-hans/google_apac/google_apac_2016_round_d/README.md:
--------------------------------------------------------------------------------
1 | # APAC 2016 Round D
2 |
3 | - [Dashboard - Round D APAC Test 2016 - Google Code Jam](https://code.google.com/codejam/contest/11214486/dashboard)
4 |
--------------------------------------------------------------------------------
/zh-hans/google_apac/google_apac_2016_round_d/Solution.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 |
3 | public class Solution {
4 | public static void main(String[] args) {
5 | Scanner in = new Scanner(System.in);
6 | int T = in.nextInt();
7 | // System.out.println("T = " + T);
8 | for (int t = 1; t <= T; t++) {
9 | int R = in.nextInt(), C = in.nextInt();
10 | int[][] grid = new int[R][C];
11 | // System.out.println("R = " + R + ", C = " + C);
12 | in.nextLine();
13 | for (int r = 0; r < R; r++) {
14 | String row = in.nextLine();
15 | // System.out.println(row);
16 | for (int c = 0; c < C; c++) {
17 | int z = Character.getNumericValue(row.charAt(c));
18 | grid[r][c] = z;
19 | }
20 | }
21 | int N = in.nextInt();
22 | in.nextLine();
23 | System.out.printf("Case #%d:\n", t);
24 | int[][] gridNew = new int[R][C];
25 | for (int i = 0; i < N; i++) {
26 | String[] tokens = in.nextLine().split(" ");
27 | if (tokens[0].equals("Q")) {
28 | for (int r = 0; r < R; r++) {
29 | for (int c = 0; c < C; c++) {
30 | gridNew[r][c] = grid[r][c];
31 | }
32 | }
33 | int ans = solve(gridNew);
34 | // System.out.printf("M = %d, N = %d\n", M, N);
35 | System.out.println(ans);
36 | } else {
37 | int tx = Integer.parseInt(tokens[1]);
38 | int ty = Integer.parseInt(tokens[2]);
39 | int tz = Integer.parseInt(tokens[3]);
40 | grid[tx][ty] = tz;
41 | }
42 | }
43 | }
44 | }
45 |
46 | public static int solve(int[][] grid) {
47 | if (grid == null || grid.length == 0) {
48 | return -1;
49 | }
50 |
51 | int R = grid.length, C = grid[0].length;
52 | int res = 0;
53 | for (int r = 0; r < R; r++) {
54 | for (int c = 0; c < C; c++) {
55 | if (grid[r][c] == 1) {
56 | dfs(grid, r, c);
57 | res++;
58 | }
59 | }
60 | }
61 | return res;
62 | }
63 |
64 | private static void dfs(int[][] grid, int x, int y) {
65 | int R = grid.length, C = grid[0].length;
66 | grid[x][y] = 0;
67 | for (int dx = -1; dx <= 1; dx++) {
68 | for (int dy = -1; dy <= 1; dy++) {
69 | int nx = x + dx, ny = y + dy;
70 | // up, down, left, right
71 | if (Math.abs(nx + ny - x - y) != 1) continue;
72 | if (0 <= nx && nx < R && 0 <= ny && ny < C) {
73 | if (grid[nx][ny] == 1) dfs(grid, nx, ny);
74 | }
75 | }
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/zh-hans/graph/README.md:
--------------------------------------------------------------------------------
1 | # Graph
2 |
3 | 本章主要总结图与搜索相关题目。
4 |
--------------------------------------------------------------------------------
/zh-hans/integer_array/README.md:
--------------------------------------------------------------------------------
1 | # Integer Array - 整型数组
2 |
3 | 本章主要总结与整型数组相关的题。
4 |
--------------------------------------------------------------------------------
/zh-hans/integer_array/partition_array_by_odd_and_even.md:
--------------------------------------------------------------------------------
1 | # Partition Array by Odd and Even
2 |
3 | ## Question
4 |
5 | - lintcode: [(373) Partition Array by Odd and Even](http://www.lintcode.com/en/problem/partition-array-by-odd-and-even/)
6 | - [Segregate Even and Odd numbers - GeeksforGeeks](http://www.geeksforgeeks.org/segregate-even-and-odd-numbers/)
7 |
8 | ```
9 | Partition an integers array into odd number first and even number second.
10 |
11 | Example
12 | Given [1, 2, 3, 4], return [1, 3, 2, 4]
13 |
14 | Challenge
15 | Do it in-place.
16 | ```
17 |
18 | ## 题解
19 |
20 | 将数组中的奇数和偶数分开,使用『两根指针』的方法最为自然,奇数在前,偶数在后,若不然则交换之。
21 |
22 | ### Java
23 |
24 | ```java
25 | public class Solution {
26 | /**
27 | * @param nums: an array of integers
28 | * @return: nothing
29 | */
30 | public void partitionArray(int[] nums) {
31 | if (nums == null) return;
32 |
33 | int left = 0, right = nums.length - 1;
34 | while (left < right) {
35 | // odd number
36 | while (left < right && nums[left] % 2 != 0) {
37 | left++;
38 | }
39 | // even number
40 | while (left < right && nums[right] % 2 == 0) {
41 | right--;
42 | }
43 | // swap
44 | if (left < right) {
45 | int temp = nums[left];
46 | nums[left] = nums[right];
47 | nums[right] = temp;
48 | }
49 | }
50 | }
51 | }
52 | ```
53 |
54 | ### C++
55 | ``` c++
56 | void partitionArray(vector &nums) {
57 | if (nums.empty()) return;
58 |
59 | int i=0, j=nums.size()-1;
60 | while (i &nums) {
37 | if (nums.size() <= 1) return nums.size();
38 |
39 | int len = nums.size();
40 | int newIndex = 0;
41 | for (int i = 1; i< len; ++i) {
42 | if (nums[i] != nums[newIndex]) {
43 | newIndex++;
44 | nums[newIndex] = nums[i];
45 | }
46 | }
47 |
48 | return newIndex + 1;
49 | }
50 | };
51 | ```
52 |
53 | ### Java
54 |
55 | ```java
56 | public class Solution {
57 | /**
58 | * @param A: a array of integers
59 | * @return : return an integer
60 | */
61 | public int removeDuplicates(int[] nums) {
62 | if (nums == null) return -1;
63 | if (nums.length <= 1) return nums.length;
64 |
65 | int newIndex = 0;
66 | for (int i = 1; i < nums.length; i++) {
67 | if (nums[i] != nums[newIndex]) {
68 | newIndex++;
69 | nums[newIndex] = nums[i];
70 | }
71 | }
72 |
73 | return newIndex + 1;
74 | }
75 | }
76 | ```
77 |
78 | ### 源码分析
79 |
80 | 注意最后需要返回的是索引值加1。
81 |
82 | ### 复杂度分析
83 |
84 | 遍历一次数组,时间复杂度 $$O(n)$$, 空间复杂度 $$O(1)$$.
85 |
--------------------------------------------------------------------------------
/zh-hans/integer_array/remove_duplicates_from_sorted_array_ii.md:
--------------------------------------------------------------------------------
1 | # Remove Duplicates from Sorted Array II
2 |
3 | ## Question
4 |
5 | - leetcode: [Remove Duplicates from Sorted Array II | LeetCode OJ](https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/)
6 | - lintcode: [(101) Remove Duplicates from Sorted Array II](http://www.lintcode.com/en/problem/remove-duplicates-from-sorted-array-ii/)
7 |
8 | ```
9 | Follow up for "Remove Duplicates":
10 | What if duplicates are allowed at most twice?
11 |
12 | For example,
13 | Given sorted array A = [1,1,1,2,2,3],
14 |
15 | Your function should return length = 5, and A is now [1,1,2,2,3].
16 | Example
17 | ```
18 |
19 | ## 题解
20 |
21 | 在上题基础上加了限制条件元素最多可重复出现两次。~~因此可以在原题的基础上添加一变量跟踪元素重复出现的次数,小于指定值时执行赋值操作。但是需要注意的是重复出现次数`occurence`的初始值(从1开始,而不是0)和reset的时机。~~这种方法比较复杂,谢谢 @meishenme 提供的简洁方法,核心思想仍然是两根指针,只不过此时新索引自增的条件是当前遍历的数组值和『新索引』或者『新索引-1』两者之一不同。
22 |
23 | ### C++
24 |
25 | ```c++
26 | class Solution {
27 | public:
28 | /**
29 | * @param A: a list of integers
30 | * @return : return an integer
31 | */
32 | int removeDuplicates(vector &nums) {
33 | if (nums.size() <= 2) return nums.size();
34 |
35 | int len = nums.size();
36 | int newIndex = 1;
37 | for (int i = 2; i < len; ++i) {
38 | if (nums[i] != nums[newIndex] || nums[i] != nums[newIndex - 1]) {
39 | ++newIndex;
40 | nums[newIndex] = nums[i];
41 | }
42 | }
43 |
44 | return newIndex + 1;
45 | }
46 | };
47 | ```
48 |
49 | ### Java
50 |
51 | ```java
52 | public class Solution {
53 | /**
54 | * @param A: a array of integers
55 | * @return : return an integer
56 | */
57 | public int removeDuplicates(int[] nums) {
58 | if (nums == null) return -1;
59 | if (nums.length <= 2) return nums.length;
60 |
61 | int newIndex = 1;
62 | for (int i = 2; i < nums.length; i++) {
63 | if (nums[i] != nums[newIndex] || nums[i] != nums[newIndex - 1]) {
64 | newIndex++;
65 | nums[newIndex] = nums[i];
66 | }
67 | }
68 |
69 | return newIndex + 1;
70 | }
71 | }
72 | ```
73 |
74 | ### 源码分析
75 |
76 | 遍历数组时 i 从2开始,newIndex 初始化为1便于分析。
77 |
78 | ### 复杂度分析
79 |
80 | 时间复杂度 $$O(n)$$, 空间复杂度 $$O(1)$$.
81 |
--------------------------------------------------------------------------------
/zh-hans/interview/facebook_interview.md:
--------------------------------------------------------------------------------
1 | # Facebook Technical Coding Interview
2 |
3 | Frank Qixing Du shared his experience of coding interview and writing resume.
4 |
5 | - Detailed notes: [Facebook学长交流分享 - biaobiaoqi](http://www.cnblogs.com/biaobiaoqi/p/3753750.html)
6 | - [Frank DU | LinkedIn](https://www.linkedin.com/pub/frank-du/4/790/3b8)
7 |
--------------------------------------------------------------------------------
/zh-hans/interview/google_interview.md:
--------------------------------------------------------------------------------
1 | # Google interview experience
2 |
3 | ## Brief self-introduction
4 |
5 | 1. Name, school, major
6 | 2. Previous projects and internships
7 | 3. Major accomplishments, etc.
8 |
9 | ## Technical assessment
10 |
11 | 1. Building and developing algorithms
12 | 2. Coding
13 | 3. Basic CS knowledge
14 | 4. Data Structure
15 | 5. Read-world problem solving
16 |
17 | ## Other Reference
18 |
19 | - [面试体验:Google 篇 - Cat Chen - 博客园](http://www.cnblogs.com/cathsfz/archive/2012/08/08/google-interview-experience.html)
20 |
--------------------------------------------------------------------------------
/zh-hans/linked_list/README.md:
--------------------------------------------------------------------------------
1 | # Linked List - 链表
2 |
3 | 本节包含链表的一些常用操作,如删除、插入和合并等。
4 |
5 | 常见错误有 遍历链表不向前递推节点,遍历链表前未保存头节点,返回链表节点指针错误。
6 |
7 |
8 | 下图是把本章中所有出现的题目归类总结了一下,便于记忆
9 |
10 | 
--------------------------------------------------------------------------------
/zh-hans/linked_list/lru_cache.md:
--------------------------------------------------------------------------------
1 | # LRU Cache
2 |
3 | ## Question
4 |
5 | - leetcode: [LRU Cache | LeetCode OJ](https://leetcode.com/problems/lru-cache/)
6 | - lintcode: [(134) LRU Cache](http://www.lintcode.com/en/problem/lru-cache/)
7 |
8 | ### Problem Statement
9 |
10 |
11 | Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: `get` and `set`.
12 |
13 | `get(key)` - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
14 |
15 | `set(key, value)` - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
16 |
17 | ## 题解
18 |
19 | ### Java
20 |
21 | ```java
22 | public class Solution {
23 | private int capacity;
24 | private HashMap map = new HashMap<>();
25 | private Node head = new Node(-1, -1), tail = new Node(-1, -1);
26 |
27 | private class Node {
28 | Node prev, next;
29 | int val, key;
30 |
31 | public Node(int key, int val) {
32 | this.val = val;
33 | this.key = key;
34 | prev = null;
35 | next = null;
36 | }
37 |
38 | // @Override
39 | // public String toString() {
40 | // return "(" + key + ", " + val + ") " + "last:"
41 | // + (prev == null ? "null" : "node");
42 | // }
43 | }
44 |
45 | public Solution(int capacity) {
46 | this.capacity = capacity;
47 | tail.prev = head;
48 | head.next = tail;
49 | }
50 |
51 | public int get(int key) {
52 | if (!map.containsKey(key)) {
53 | return -1;
54 | }
55 | // remove current
56 | Node currentNode = map.get(key);
57 | currentNode.prev.next = currentNode.next;
58 | currentNode.next.prev = currentNode.prev;
59 |
60 | // move current to tail;
61 | moveToTail(currentNode);
62 |
63 | return map.get(key).val;
64 | }
65 |
66 | public void set(int key, int value) {
67 | if (get(key) != -1) {
68 | map.get(key).val = value;
69 | return;
70 | }
71 | if (map.size() == capacity) {
72 | map.remove(head.next.key);
73 | head.next = head.next.next;
74 | head.next.prev = head;
75 | }
76 | Node insert = new Node(key, value);
77 | map.put(key, insert);
78 | moveToTail(insert);
79 | }
80 |
81 | private void moveToTail(Node current) {
82 | current.prev = tail.prev;
83 | tail.prev = current;
84 | current.prev.next = current;
85 | current.next = tail;
86 | }
87 | }
88 |
89 | ```
90 |
--------------------------------------------------------------------------------
/zh-hans/linked_list/remove_linked_list_elements.md:
--------------------------------------------------------------------------------
1 | # Remove Linked List Elements
2 |
3 | ## Question
4 |
5 | - leetcode: [Remove Linked List Elements | LeetCode OJ](https://leetcode.com/problems/remove-linked-list-elements/)
6 | - lintcode: [(452) Remove Linked List Elements](http://www.lintcode.com/en/problem/remove-linked-list-elements/)
7 |
8 | ### Problem Statement
9 |
10 | Remove all elements from a linked list of integers that have value `val`.
11 |
12 | #### Example
13 |
14 | Given `1->2->3->3->4->5->3`, val = 3, you should return the list as
15 | `1->2->4->5`
16 |
17 | ## 题解
18 |
19 | 删除链表中指定值,找到其前一个节点即可,将 next 指向下一个节点即可。
20 |
21 | ### Python
22 |
23 | ```python
24 | # Definition for singly-linked list.
25 | # class ListNode(object):
26 | # def __init__(self, x):
27 | # self.val = x
28 | # self.next = None
29 |
30 | class Solution(object):
31 | def removeElements(self, head, val):
32 | """
33 | :type head: ListNode
34 | :type val: int
35 | :rtype: ListNode
36 | """
37 | dummy = ListNode(0)
38 | dummy.next = head
39 | curr = dummy
40 | while curr.next is not None:
41 | if curr.next.val == val:
42 | curr.next = curr.next.next
43 | else:
44 | curr = curr.next
45 |
46 | return dummy.next
47 | ```
48 |
49 | ### Java
50 |
51 | ```java
52 | /**
53 | * Definition for singly-linked list.
54 | * public class ListNode {
55 | * int val;
56 | * ListNode next;
57 | * ListNode(int x) { val = x; }
58 | * }
59 | */
60 | public class Solution {
61 | /**
62 | * @param head a ListNode
63 | * @param val an integer
64 | * @return a ListNode
65 | */
66 | public ListNode removeElements(ListNode head, int val) {
67 | ListNode dummy = new ListNode(0);
68 | dummy.next = head;
69 | ListNode curr = dummy;
70 | while (curr.next != null) {
71 | if (curr.next.val == val) {
72 | curr.next = curr.next.next;
73 | } else {
74 | curr = curr.next;
75 | }
76 | }
77 |
78 | return dummy.next;
79 | }
80 | }
81 | ```
82 |
83 | ### 源码分析
84 |
85 | while 循环中使用`curr.next`较为方便,if 语句中比较时也使用`curr.next.val`也比较简洁,如果使用`curr`会比较难处理。
86 |
87 | ### 复杂度分析
88 |
89 | 略
90 |
--------------------------------------------------------------------------------
/zh-hans/linked_list/rotate_list.md:
--------------------------------------------------------------------------------
1 | # Rotate List
2 |
3 | ## Question
4 |
5 | - leetcode: [Rotate List | LeetCode OJ](https://leetcode.com/problems/rotate-list/)
6 | - lintcode: [(170) Rotate List](http://www.lintcode.com/en/problem/rotate-list/)
7 |
8 | ### Problem Statement
9 |
10 | Given a list, rotate the list to the right by _k_ places, where _k_ is non-
11 | negative.
12 |
13 | #### Example
14 |
15 | Given `1->2->3->4->5` and k = `2`, return `4->5->1->2->3`.
16 |
17 | ## 题解
18 |
19 | 旋转链表,链表类问题通常需要找到需要处理节点处的前一个节点。因此我们只需要找到旋转节点和最后一个节点即可。需要注意的细节是 k 有可能比链表长度还要大,此时需要取模,另一个 corner case 则是链表长度和 k 等长。
20 |
21 | ### Java
22 |
23 | ```java
24 | /**
25 | * Definition for singly-linked list.
26 | * public class ListNode {
27 | * int val;
28 | * ListNode next;
29 | * ListNode(int x) {
30 | * val = x;
31 | * next = null;
32 | * }
33 | * }
34 | */
35 | public class Solution {
36 | /**
37 | * @param head: the List
38 | * @param k: rotate to the right k places
39 | * @return: the list after rotation
40 | */
41 | public ListNode rotateRight(ListNode head, int k) {
42 | if (head == null) return head;
43 | ListNode fast = head, slow = head;
44 | int len = 1;
45 | for (len = 1; fast.next != null && len <= k; len++) {
46 | fast = fast.next;
47 | }
48 | // k mod len if k > len
49 | if (len <= k) {
50 | k = k % len;
51 | fast = head;
52 | for (int i = 0; i < k; i++) {
53 | fast = fast.next;
54 | }
55 | }
56 | // forward slow and fast
57 | while (fast.next != null) {
58 | fast = fast.next;
59 | slow = slow.next;
60 | }
61 | // return new head
62 | fast.next = head;
63 | head = slow.next;
64 | slow.next = null;
65 |
66 | return head;
67 | }
68 | }
69 | ```
70 |
71 | ### 源码分析
72 |
73 | 由于需要处理的是节点的前一个节点,故最终的`while` 循环使用`fast.next != null`. k 与链表等长时包含在`len <= k`中。
74 |
75 | ### 复杂度分析
76 |
77 | 时间复杂度 $$O(n)$$, 空间复杂度 $$O(1)$$.
78 |
--------------------------------------------------------------------------------
/zh-hans/linked_list/two_lists_sum_advanced.md:
--------------------------------------------------------------------------------
1 | # Two Lists Sum Advanced
2 |
3 | ## Question
4 |
5 | - CC150 - [Add two numbers represented by linked lists | Set 2 - GeeksforGeeks](http://www.geeksforgeeks.org/sum-of-two-linked-lists/)
6 |
7 | ```
8 | Given two numbers represented by two linked lists, write a function that returns sum list.
9 | The sum list is linked list representation of addition of two input numbers.
10 |
11 | Example
12 |
13 | Input:
14 | First List: 5->6->3 // represents number 563
15 | Second List: 8->4->2 // represents number 842
16 | Output
17 | Resultant list: 1->4->0->5 // represents number 1405
18 |
19 | Challenge
20 |
21 | Not allowed to modify the lists.
22 | Not allowed to use explicit extra space.
23 | ```
24 |
25 | ## 题解1 - 反转链表
26 |
27 | 在题 [Two Lists Sum | Data Structure and Algorithm](http://algorithm.yuanbin.me/zh-hans/linked_list/two_lists_sum.html) 的基础上改了下数位的表示方式,前者低位在前,高位在后,这个题的高位在前,低位在后。很自然地可以联想到先将链表反转,而后再使用 Two Lists Sum 的解法。
28 |
29 | ## Reference
30 |
31 | - [Add two numbers represented by linked lists | Set 2 - GeeksforGeeks](http://www.geeksforgeeks.org/sum-of-two-linked-lists/)
32 |
--------------------------------------------------------------------------------
/zh-hans/math_and_bit_manipulation/README.md:
--------------------------------------------------------------------------------
1 | # Bit Manipulation
2 |
3 | 位运算的题大多较为灵活,涉及较多的按位与/或/异或等特性。
4 |
5 | ## Reference
6 |
7 | - [位运算简介及实用技巧(一):基础篇 | Matrix67: The Aha Moments](http://www.matrix67.com/blog/archives/263)
8 | - *cc150* chapter 8.5 and chapter 9.5
9 |
--------------------------------------------------------------------------------
/zh-hans/math_and_bit_manipulation/a_plus_b_problem.md:
--------------------------------------------------------------------------------
1 | # A plus B Problem
2 |
3 | ## Question
4 |
5 | - lintcode: [(1) A + B Problem](http://www.lintcode.com/en/problem/a-b-problem/)
6 |
7 | ```
8 | Write a function that add two numbers A and B.
9 | You should not use + or any arithmetic operators.
10 |
11 |
12 | Example
13 | Given a=1 and b=2 return 3
14 |
15 | Note
16 | There is no need to read data from standard input stream.
17 | Both parameters are given in function aplusb,
18 | you job is to calculate the sum and return it.
19 | Challenge
20 | Of course you can just return a + b to get accepted.
21 | But Can you challenge not do it like that?
22 | Clarification
23 | Are a and b both 32-bit integers?
24 | Yes.
25 | Can I use bit operation?
26 |
27 | Sure you can.
28 | ```
29 |
30 | ## 题解
31 |
32 | 不用加减法实现加法,类似数字电路中的全加器,异或求得部分和,相与求得进位,最后将进位作为加法器的输入,典型的递归实现思路。
33 |
34 | ### Java
35 |
36 | ```java
37 | class Solution {
38 | /*
39 | * param a: The first integer
40 | * param b: The second integer
41 | * return: The sum of a and b
42 | */
43 | public int aplusb(int a, int b) {
44 | int result = a ^ b;
45 | int carry = a & b;
46 | carry <<= 1;
47 | if (carry != 0) {
48 | result = aplusb(result, carry);
49 | }
50 |
51 | return result;
52 | }
53 | }
54 | ```
55 |
56 | ### 源码分析
57 |
58 | 递归步为进位是否为0,为0时返回。
59 |
60 | ### 复杂度分析
61 |
62 | 取决于进位,近似为 $$O(1)$$. 使用了部分额外变量,空间复杂度为 $$O(1)$$.
63 |
--------------------------------------------------------------------------------
/zh-hans/math_and_bit_manipulation/count_1_in_binary.md:
--------------------------------------------------------------------------------
1 | # Count 1 in Binary
2 |
3 | ## Question
4 |
5 | - lintcode: [(365) Count 1 in Binary](http://www.lintcode.com/en/problem/count-1-in-binary/)
6 |
7 | ```
8 | Count how many 1 in binary representation of a 32-bit integer.
9 |
10 | Example
11 | Given 32, return 1
12 |
13 | Given 5, return 2
14 |
15 | Given 1023, return 9
16 |
17 | Challenge
18 | If the integer is n bits with m 1 bits. Can you do it in O(m) time?
19 | ```
20 |
21 | ## 题解
22 |
23 | 题 [O1 Check Power of 2](http://algorithm.yuanbin.me/zh-hans/math_and_bit_manipulation/o1_check_power_of_2.html) 的进阶版,`x & (x - 1)` 的含义为去掉二进制数中1的最后一位,无论 x 是正数还是负数都成立。
24 |
25 | ### C++
26 | ``` c++
27 | class Solution {
28 | public:
29 | /**
30 | * @param num: an integer
31 | * @return: an integer, the number of ones in num
32 | */
33 | int countOnes(int num) {
34 | int count=0;
35 | while (num) {
36 | num &= num-1;
37 | count++;
38 | }
39 | return count;
40 | }
41 | };
42 | ```
43 |
44 | ### Java
45 |
46 | ```java
47 | public class Solution {
48 | /**
49 | * @param num: an integer
50 | * @return: an integer, the number of ones in num
51 | */
52 | public int countOnes(int num) {
53 | int count = 0;
54 | while (num != 0) {
55 | num = num & (num - 1);
56 | count++;
57 | }
58 |
59 | return count;
60 | }
61 | }
62 | ```
63 |
64 | ### 源码分析
65 |
66 | 累加计数器即可。
67 |
68 | ### 复杂度分析
69 |
70 | 这种算法依赖于数中1的个数,时间复杂度为 $$O(m)$$. 空间复杂度 $$O(1)$$.
71 |
72 | ## Reference
73 |
74 | - [Number of 1 bits | LeetCode](http://articles.leetcode.com/2010/09/number-of-1-bits.html) - 评论中有关于不同算法性能的讨论
75 |
--------------------------------------------------------------------------------
/zh-hans/math_and_bit_manipulation/digit_counts.md:
--------------------------------------------------------------------------------
1 | # Digit Counts
2 |
3 | ## Question
4 |
5 | - leetcode: [Number of Digit One | LeetCode OJ](https://leetcode.com/problems/number-of-digit-one/)
6 | - lintcode: [(3) Digit Counts](http://www.lintcode.com/en/problem/digit-counts/)
7 |
8 | ```
9 | Count the number of k's between 0 and n. k can be 0 - 9.
10 |
11 | Example
12 | if n=12, k=1 in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
13 | we have FIVE 1's (1, 10, 11, 12)
14 | ```
15 |
16 | ## 题解
17 |
18 | leetcode 上的有点简单,这里以 Lintcode 上的为例进行说明。找出从0至整数 n 中出现数位k的个数,与整数有关的题大家可能比较容易想到求模求余等方法,但其实很多与整数有关的题使用字符串的解法更为便利。将整数 i 分解为字符串,然后遍历之,自增 k 出现的次数即可。
19 |
20 | ### C++
21 | ```c++
22 | class Solution {
23 | public:
24 | /*
25 | * param k : As description.
26 | * param n : As description.
27 | * return: How many k's between 0 and n.
28 | */
29 | int digitCounts(int k, int n) {
30 | char c = k + '0';
31 | int count = 0;
32 | for (int i = k; i <= n; i++) {
33 | for (auto s : to_string(i)) {
34 | if (s == c) count++;
35 | }
36 | }
37 | return count;
38 | }
39 | };
40 | ```
41 |
42 | ### Java
43 |
44 | ```java
45 | class Solution {
46 | /*
47 | * param k : As description.
48 | * param n : As description.
49 | * return: An integer denote the count of digit k in 1..n
50 | */
51 | public int digitCounts(int k, int n) {
52 | int count = 0;
53 | char kChar = (char)(k + '0');
54 | for (int i = k; i <= n; i++) {
55 | char[] iChars = Integer.toString(i).toCharArray();
56 | for (char iChar : iChars) {
57 | if (kChar == iChar) count++;
58 | }
59 | }
60 |
61 | return count;
62 | }
63 | }
64 | ```
65 |
66 | ### 源码分析
67 |
68 | 太简单了,略
69 |
70 | ### 复杂度分析
71 |
72 | 时间复杂度 $$O(n \times L)$$, L 为n 的最大长度,拆成字符数组,空间复杂度 $$O(L)$$.
73 |
--------------------------------------------------------------------------------
/zh-hans/math_and_bit_manipulation/fibonacci.md:
--------------------------------------------------------------------------------
1 | # Fibonacci
2 |
3 | ## Question
4 |
5 | - lintcode: [(366) Fibonacci](http://www.lintcode.com/en/problem/fibonacci/)
6 |
7 | ### Problem Statement
8 |
9 | Find the _N_th number in Fibonacci sequence.
10 |
11 | A Fibonacci sequence is defined as follow:
12 |
13 | * The first two numbers are 0 and 1.
14 | * The _i_ th number is the sum of _i_-1 th number and _i_-2 th number.
15 |
16 | The first ten numbers in Fibonacci sequence is:
17 |
18 | `0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ...`
19 |
20 | #### Example
21 |
22 | Given `1`, return `0`
23 |
24 | Given `2`, return `1`
25 |
26 | Given `10`, return `34`
27 |
28 | #### Note
29 |
30 | The _N_th fibonacci number won't exceed the max value of signed 32-bit integer
31 | in the test cases.
32 |
33 | ## 题解
34 |
35 | 斐波那契数列使用递归极其容易实现,其实使用非递归的方法也很容易,不断向前滚动即可。
36 |
37 | ### C++
38 | ```c++
39 | class Solution{
40 | public:
41 | /**
42 | * @param n: an integer
43 | * @return an integer f(n)
44 | */
45 | int fibonacci(int n) {
46 | if (n <= 0) return -1;
47 | if (n == 1) return 0;
48 | if (n == 2) return 1;
49 |
50 | int fn = 0, fn1 = 0, fn2 = 1;
51 | for (int i = 3; i <= n; i++) {
52 | fn = fn1 + fn2;
53 | fn1 = fn2;
54 | fn2 = fn;
55 | }
56 | return fn;
57 | }
58 | };
59 | ```
60 |
61 | ### Java
62 |
63 | ```java
64 | class Solution {
65 | /**
66 | * @param n: an integer
67 | * @return an integer f(n)
68 | */
69 | public int fibonacci(int n) {
70 | if (n <= 0) return -1;
71 | if (n == 1) return 0;
72 | if (n == 2) return 1;
73 |
74 | int fn = 0, fn1 = 1, fn2 = 0;
75 | for (int i = 3; i <= n; i++) {
76 | fn = fn1 + fn2;
77 | fn2 = fn1;
78 | fn1 = fn;
79 | }
80 |
81 | return fn;
82 | }
83 | }
84 | ```
85 |
86 | ### 源码分析
87 |
88 | 1. corner cases
89 | 2. 初始化 fn, fn1, fn2, 建立地推关系。
90 | 3. 注意 fn, fn2, fn1的递推顺序。
91 |
92 | ### 复杂度分析
93 |
94 | 遍历一次,时间复杂度为 $$O(n)$$, 使用了两个额外变量,空间复杂度为 $$O(1)$$.
95 |
--------------------------------------------------------------------------------
/zh-hans/math_and_bit_manipulation/happy_number.md:
--------------------------------------------------------------------------------
1 | # Happy Number
2 |
3 | Tags: Hash Table, Math, Easy
4 |
5 | ## Question
6 |
7 | - leetcode: [Happy Number](https://leetcode.com/problems/happy-number/)
8 | - lintcode: [Happy Number](http://www.lintcode.com/en/problem/happy-number/)
9 |
10 | ### Problem Statement
11 |
12 | Write an algorithm to determine if a number is "happy".
13 |
14 | A happy number is a number defined by the following process: Starting with any
15 | positive integer, replace the number by the sum of the squares of its digits,
16 | and repeat the process until the number equals 1 (where it will stay), or it
17 | loops endlessly in a cycle which does not include 1. Those numbers for which
18 | this process ends in 1 are happy numbers.
19 |
20 | **Example: ** 19 is a happy number
21 |
22 | * $$1^2 + 9^2 = 82$$
23 | * $$8^2 + 2^2 = 68$$
24 | * $$6^2 + 8^2 = 100$$
25 | * $$1^2 + 0^2 + 0^2 = 1$$
26 |
27 | **Credits:**
28 | Special thanks to [@mithmatt](https://leetcode.com/discuss/user/mithmatt) and
29 | [@ts](https://leetcode.com/discuss/user/ts) for adding this problem and
30 | creating all test cases.
31 |
32 | ## 题解
33 |
34 | 根据指定运算规则判断输入整数是否为『happy number』,容易推断得知最终要么能求得1,要么为环形队列不断循环。
35 | 第一种情况容易判断,第二种情况即判断得到的数是否为环形队列,也就是说是否重复出现,这种场景使用哈希表轻易解决。
36 |
37 | ### Java
38 |
39 | ```java
40 | public class Solution {
41 | public boolean isHappy(int n) {
42 | if (n < 0) return false;
43 |
44 | Set set = new HashSet();
45 | set.add(n);
46 | while (n != 1) {
47 | n = digitsSquareSum(n);
48 | if (n == 1) {
49 | return true;
50 | } else if (set.contains(n)) {
51 | return false;
52 | } else {
53 | set.add(n);
54 | }
55 | }
56 |
57 | return true;
58 | }
59 |
60 | private int digitsSquareSum(int n) {
61 | int sum = 0;
62 | for (; n > 0; n /= 10) {
63 | sum += (n % 10) * (n % 10);
64 | }
65 | return sum;
66 | }
67 | }
68 | ```
69 |
70 | ### 源码分析
71 |
72 | 辅助方法计算数字平方和。
73 |
74 | ### 复杂度分析
75 |
76 | 有限迭代次数一定终止,时间和空间复杂度均为 $$O(1)$$.
--------------------------------------------------------------------------------
/zh-hans/math_and_bit_manipulation/majority_number.md:
--------------------------------------------------------------------------------
1 | # Majority Number
2 |
3 | ## Question
4 |
5 | - leetcode: [Majority Element | LeetCode OJ](https://leetcode.com/problems/majority-element/)
6 | - lintcode: [(46) Majority Number](http://www.lintcode.com/en/problem/majority-number/)
7 |
8 | ```
9 | Given an array of integers, the majority number is
10 | the number that occurs more than half of the size of the array. Find it.
11 |
12 | Example
13 | Given [1, 1, 1, 1, 2, 2, 2], return 1
14 |
15 | Challenge
16 | O(n) time and O(1) extra space
17 | ```
18 |
19 | ## 题解
20 |
21 | 找出现次数超过一半的数,使用哈希表统计不同数字出现的次数,超过二分之一即返回当前数字。这种方法非常简单且容易实现,但会占据过多空间,注意到题中明确表明要找的数会超过二分之一,这里的隐含条件不是那么容易应用。既然某个数超过二分之一,那么用这个数和其他数进行 PK,不同的计数器都减一**(核心在于两两抵消)**,相同的则加1,最后返回计数器大于0的即可。综上,我们需要一辅助数据结构如`pair`.
22 |
23 | ### C++
24 | ```c++
25 | int majorityNumber(vector nums) {
26 | if (nums.empty()) return -1;
27 |
28 | int k = -1, count = 0;
29 | for (auto n : nums) {
30 | if (!count) k = n;
31 | if (k == n) count++;
32 | else count--;
33 | }
34 | return k;
35 | }
36 | ```
37 |
38 | ### Java
39 |
40 | ```java
41 | public class Solution {
42 | /**
43 | * @param nums: a list of integers
44 | * @return: find a majority number
45 | */
46 | public int majorityNumber(ArrayList nums) {
47 | if (nums == null || nums.isEmpty()) return -1;
48 |
49 | // pair
50 | int key = -1, count = 0;
51 | for (int num : nums) {
52 | // re-initialize
53 | if (count == 0) {
54 | key = num;
55 | count = 1;
56 | continue;
57 | }
58 | // increment/decrement count
59 | if (key == num) {
60 | count++;
61 | } else {
62 | count--;
63 | }
64 | }
65 |
66 | return key;
67 | }
68 | }
69 | ```
70 |
71 | ### 源码分析
72 |
73 | 初始化`count = 0`, 遍历数组时需要先判断`count == 0`以重新初始化。
74 |
75 | ### 复杂度分析
76 |
77 | 时间复杂度 $$O(n)$$, 空间复杂度 $$O(1)$$.
78 |
--------------------------------------------------------------------------------
/zh-hans/math_and_bit_manipulation/o1_check_power_of_2.md:
--------------------------------------------------------------------------------
1 | # O(1) Check Power of 2
2 |
3 | ## Question
4 |
5 | - lintcode: [(142) O(1) Check Power of 2](http://www.lintcode.com/en/problem/o1-check-power-of-2/)
6 |
7 | ```
8 | Using O(1) time to check whether an integer n is a power of 2.
9 |
10 | Example
11 | For n=4, return true;
12 |
13 | For n=5, return false;
14 |
15 | Challenge
16 | O(1) time
17 | ```
18 |
19 | ## 题解
20 |
21 | 咋看起来挺简单的一道题目,可之前若是没有接触过神奇的位运算技巧遇到这种题就有点不知从哪入手了,咳咳,我第一次接触到这个题就是在七牛的笔试题中看到的,泪奔 :-(
22 |
23 | 简单点来考虑可以连除2求余,看最后的余数是否为1,但是这种方法无法在 $$O(1)$$ 的时间内解出,所以我们必须要想点别的办法了。2的整数幂若用二进制来表示,则其中必只有一个1,其余全是0,那么怎么才能用一个式子把这种特殊的关系表示出来了?传统的位运算如按位与、按位或和按位异或等均无法直接求解,我就不卖关子了,比较下`x - 1`和`x`的关系试试?以`x=4`为例。
24 |
25 | ```
26 | 0100 ==> 4
27 | 0011 ==> 3
28 | ```
29 |
30 | 两个数进行按位与就为0了!如果不是2的整数幂则无上述关系,反证法可证之。
31 |
32 | ### Python
33 |
34 | ```python
35 | class Solution:
36 | """
37 | @param n: An integer
38 | @return: True or false
39 | """
40 | def checkPowerOf2(self, n):
41 | if n < 1:
42 | return False
43 | else:
44 | return (n & (n - 1)) == 0
45 | ```
46 |
47 | ### C++
48 |
49 | ```c++
50 | class Solution {
51 | public:
52 | /*
53 | * @param n: An integer
54 | * @return: True or false
55 | */
56 | bool checkPowerOf2(int n) {
57 | if (1 > n) {
58 | return false;
59 | } else {
60 | return 0 == (n & (n - 1));
61 | }
62 | }
63 | };
64 | ```
65 |
66 | ### Java
67 |
68 | ```java
69 | class Solution {
70 | /*
71 | * @param n: An integer
72 | * @return: True or false
73 | */
74 | public boolean checkPowerOf2(int n) {
75 | if (n < 1) {
76 | return false;
77 | } else {
78 | return (n & (n - 1)) == 0;
79 | }
80 | }
81 | };
82 | ```
83 |
84 | ### 源码分析
85 |
86 | 除了考虑正整数之外,其他边界条件如小于等于0的整数也应考虑在内。在比较0和`(n & (n - 1))`的值时,需要用括号括起来避免优先级结合的问题。
87 |
88 | ### 复杂度分析
89 |
90 | $$O(1)$$.
91 |
92 | ## 扩展
93 |
94 | 关于2的整数幂还有一道有意思的题,比如 [Next Power of 2 - GeeksforGeeks](http://www.geeksforgeeks.org/next-power-of-2/),有兴趣的可以去围观下。
95 |
--------------------------------------------------------------------------------
/zh-hans/math_and_bit_manipulation/print_numbers_by_recursion.md:
--------------------------------------------------------------------------------
1 | # Print Numbers by Recursion
2 |
3 | ## Question
4 |
5 | - lintcode: [(371) Print Numbers by Recursion](http://www.lintcode.com/en/problem/print-numbers-by-recursion/)
6 |
7 | ```
8 | Print numbers from 1 to the largest number with N digits by recursion.
9 |
10 | Example
11 | Given N = 1, return [1,2,3,4,5,6,7,8,9].
12 |
13 | Given N = 2, return [1,2,3,4,5,6,7,8,9,10,11,12,...,99].
14 |
15 | Note
16 | It's pretty easy to do recursion like:
17 |
18 | recursion(i) {
19 | if i > largest number:
20 | return
21 | results.add(i)
22 | recursion(i + 1)
23 | }
24 | however this cost a lot of recursion memory as the recursion depth maybe very large.
25 | Can you do it in another way to recursive with at most N depth?
26 |
27 | Challenge
28 | Do it in recursion, not for-loop.
29 | ```
30 |
31 | ## 题解
32 |
33 | 从小至大打印 N 位的数列,正如题目中所提供的 `recursion(i)`, 解法简单粗暴,但问题在于 N 稍微大一点时栈就溢出了,因为递归深度太深了。能联想到的方法大概有两种,一种是用排列组合的思想去解释,把0~9当成十个不同的数(字符串表示),塞到 N 个坑位中,这个用 DFS 来解应该是可行的;另一个则是使用数学方法,依次递归递推,比如 N=2 可由 N=1递归而来,具体方法则是乘10进位加法。题中明确要求递归深度最大不超过 N, 故 DFS 方法比较危险。
34 |
35 | ### Java
36 |
37 | ```java
38 | public class Solution {
39 | /**
40 | * @param n: An integer.
41 | * return : An array storing 1 to the largest number with n digits.
42 | */
43 | public List numbersByRecursion(int n) {
44 | List result = new ArrayList();
45 | if (n <= 0) {
46 | return result;
47 | }
48 | helper(n, result);
49 | return result;
50 | }
51 |
52 | private void helper(int n, List ret) {
53 | if (n == 0) return;
54 | helper(n - 1, ret);
55 | // current base such as 10, 20, 30...
56 | int base = (int)Math.pow(10, n - 1);
57 | // get List size before for loop
58 | int size = ret.size();
59 | for (int i = 1; i < 10; i++) {
60 | // add 10, 100, 1000...
61 | ret.add(i * base);
62 | for (int j = 0; j < size; j++) {
63 | // add 11, 12, 13...
64 | ret.add(ret.get(j) + base * i);
65 | }
66 | }
67 | }
68 | }
69 | ```
70 |
71 | ### 源码分析
72 |
73 | 递归步的截止条件`n == 0`, 由于需要根据之前 N-1 位的数字递推,`base` 每次递归一层都需要乘10,`size`需要在`for`循环之前就确定。
74 |
75 | ### 复杂度分析
76 |
77 | 添加 $$10^n$$ 个元素,时间复杂度 $$O(10^n)$$, 空间复杂度 $$O(1)$$.
78 |
79 | ## Reference
80 |
81 | - [Lintcode: Print Numbers by Recursion | codesolutiony](https://codesolutiony.wordpress.com/2015/05/21/lintcode-print-numbers-by-recursion/)
82 |
--------------------------------------------------------------------------------
/zh-hans/math_and_bit_manipulation/single_number.md:
--------------------------------------------------------------------------------
1 | # Single Number
2 |
3 | Tags: Hash Table, Bit Manipulation, Easy
4 |
5 | ## Question
6 |
7 | - leetcode: [Single Number](https://leetcode.com/problems/single-number/)
8 | - lintcode: [Single Number](http://www.lintcode.com/en/problem/single-number/)
9 |
10 | ### Problem Statement
11 |
12 | Given an array of integers, every element appears _twice_ except for one. Find
13 | that single one.
14 |
15 | **Note:**
16 | Your algorithm should have a linear runtime complexity. Could you implement it
17 | without using extra memory?
18 |
19 | ## 题解
20 |
21 | 「找单数」系列题,技巧性较强,需要灵活运用位运算的特性。根据题意,共有`2*n + 1`个数,且有且仅有一个数落单,要找出相应的「单数」。鉴于有空间复杂度的要求,不可能使用另外一个数组来保存每个数出现的次数,考虑到异或运算的特性,根据`x ^ x = 0`和`x ^ 0 = x`可将给定数组的所有数依次异或,最后保留的即为结果。
22 |
23 | ### C++
24 |
25 | ```c++
26 | class Solution {
27 | public:
28 | /**
29 | * @param A: Array of integers.
30 | * return: The single number.
31 | */
32 | int singleNumber(vector &A) {
33 | if (A.empty()) {
34 | return -1;
35 | }
36 | int result = 0;
37 |
38 | for (vector::iterator iter = A.begin(); iter != A.end(); ++iter) {
39 | result = result ^ *iter;
40 | }
41 |
42 | return result;
43 | }
44 | };
45 | ```
46 |
47 | ### Java
48 |
49 | ```java
50 | public class Solution {
51 | public int singleNumber(int[] nums) {
52 | if (nums == null || nums.length == 0) return -1;
53 |
54 | int result = 0;
55 | for (int num : nums) {
56 | result ^= num;
57 | }
58 |
59 | return result;
60 | }
61 | }
62 | ```
63 |
64 | ### 源码分析
65 |
66 | 1. 异常处理(OJ上对于空vector的期望结果为0,但个人认为-1更为合理)
67 | 2. 初始化返回结果`result`为0,因为`x ^ 0 = x`
68 |
--------------------------------------------------------------------------------
/zh-hans/math_and_bit_manipulation/single_number_iii.md:
--------------------------------------------------------------------------------
1 | # Single Number III
2 |
3 | ## Question
4 |
5 | - lintcode: [(84) Single Number III](http://www.lintcode.com/en/problem/single-number-iii/)
6 |
7 | ```
8 | Given 2*n + 2 numbers, every numbers occurs twice except two, find them.
9 |
10 | Example
11 | Given [1,2,2,3,4,4,5,3] return 1 and 5
12 |
13 | Challenge
14 | O(n) time, O(1) extra space.
15 | ```
16 |
17 | ## 题解
18 |
19 | 题 [Single Number](http://algorithm.yuanbin.me/zh-hans/math_and_bit_manipulation/single_number.html) 的 follow up, 不妨设最后两个只出现一次的数分别为 `x1, x2`. 那么遍历数组时根据两两异或的方法可得最后的结果为 `x1 ^ x2`, 如果我们要分别求得 `x1` 和 `x2`, 我们可以根据 `x1 ^ x2 ^ x1 = x2` 求得 `x2`, 同理可得 `x_1`. 那么问题来了,如何得到`x1`和`x2`呢?看起来似乎是个死循环。大多数人一般也就能想到这一步(比如我...)。
20 |
21 | 这道题的巧妙之处在于利用`x1 ^ x2`的结果对原数组进行了分组,进而将`x1`和`x2`分开了。具体方法则是利用了`x1 ^ x2`不为0的特性,如果`x1 ^ x2`不为0,那么`x1 ^ x2`的结果必然存在某一二进制位不为0(即为1),我们不妨将最低位的1提取出来,由于在这一二进制位上`x1`和`x2`必然相异,即`x1`, `x2`中相应位一个为0,另一个为1,所以我们可以利用这个最低位的1将`x1`和`x2`分开。又由于除了`x1`和`x2`之外其他数都是成对出现,故与最低位的1异或时一定会抵消,十分之精妙!
22 |
23 | ### Java
24 |
25 | ```java
26 | public class Solution {
27 | /**
28 | * @param A : An integer array
29 | * @return : Two integers
30 | */
31 | public List singleNumberIII(int[] A) {
32 | ArrayList nums = new ArrayList();
33 | if (A == null || A.length == 0) return nums;
34 |
35 | int x1xorx2 = 0;
36 | for (int i : A) {
37 | x1xorx2 ^= i;
38 | }
39 |
40 | // get the last 1 bit of x1xorx2, e.g. 1010 ==> 0010
41 | int last1Bit = x1xorx2 - (x1xorx2 & (x1xorx2 - 1));
42 | int single1 = 0, single2 = 0;
43 | for (int i : A) {
44 | if ((last1Bit & i) == 0) {
45 | single1 ^= i;
46 | } else {
47 | single2 ^= i;
48 | }
49 | }
50 |
51 | nums.add(single1);
52 | nums.add(single2);
53 | return nums;
54 | }
55 | }
56 | ```
57 |
58 | ### 源码分析
59 |
60 | 求一个数二进制位1的最低位方法为 `x1xorx2 - (x1xorx2 & (x1xorx2 - 1))`, 其他位运算的总结可参考 [Bit Manipulation](http://algorithm.yuanbin.me/zh-hans/basics_misc/bit_manipulation.html)。利用`last1Bit`可将数组的数分为两组,一组是相应位为0,另一组是相应位为1.
61 |
62 | ### 复杂度分析
63 |
64 | 两次遍历数组,时间复杂度 $$O(n)$$, 使用了部分额外空间,空间复杂度 $$O(1)$$.
65 |
66 | ## Reference
67 |
68 | - [Single Number III 参考程序 Java/C++/Python](http://www.jiuzhang.com/solutions/single-number-iii/)
69 |
--------------------------------------------------------------------------------
/zh-hans/microsoft/README.md:
--------------------------------------------------------------------------------
1 | # Microsoft
2 |
3 | 本章总结 Microsoft 校招的一些题。
4 |
--------------------------------------------------------------------------------
/zh-hans/microsoft/mstest2015april/README.md:
--------------------------------------------------------------------------------
1 | # Microsoft 2015 April
2 |
3 | 本小节总结 Microsoft 2015年四月第一次招实习生的题,题目列表见 [hihoCoder](http://hihocoder.com/contest/mstest2015april/problems).
4 |
--------------------------------------------------------------------------------
/zh-hans/microsoft/mstest2015april/problem_a_magic_box.md:
--------------------------------------------------------------------------------
1 | # Problem A. Magic Box
2 |
3 | ## Source
4 |
5 | - [hihoCoder](http://hihocoder.com/contest/mstest2015april/problem/1)
6 |
7 | ### Problem
8 |
9 | 时间限制:10000ms
10 |
11 | 单点时限:1000ms
12 |
13 | 内存限制:256MB
14 |
15 | ### 描述
16 |
17 | The circus clown Sunny has a magic box. When the circus is performing, Sunny
18 | puts some balls into the box one by one. The balls are in three colors:
19 | red(R), yellow(Y) and blue(B). Let Cr, Cy, Cb denote the numbers of red,
20 | yellow, blue balls in the box. Whenever the differences among Cr, Cy, Cb
21 | happen to be x, y, z, all balls in the box vanish. Given x, y, z and the
22 | sequence in which Sunny put the balls, you are to find what is the maximum
23 | number of balls in the box **ever**.
24 |
25 | For example, let's assume x=1, y=2, z=3 and the sequence is RRYBRBRYBRY. After
26 | Sunny puts the first 7 balls, RRYBRBR, into the box, Cr, Cy, Cb are 4, 1, 2
27 | respectively. The differences are exactly 1, 2, 3. (|Cr-Cy|=3, |Cy-Cb|=1, |Cb-
28 | Cr|=2) Then all the 7 balls vanish. Finally there are 4 balls in the box,
29 | after Sunny puts the remaining balls. So the box contains 7 balls at most,
30 | after Sunny puts the first 7 balls and before they vanish.
31 |
32 | #### 输入
33 |
34 | Line 1: x y z
35 |
36 | Line 2: the sequence consisting of only three characters 'R', 'Y' and 'B'.
37 |
38 | For 30% data, the length of the sequence is no more than 200.
39 |
40 | For 100% data, the length of the sequence is no more than 20,000, 0 <= x,
41 | y, z <= 20.
42 |
43 | ### 输出
44 |
45 | The maximum number of balls in the box **ever**.
46 |
47 | ### 提示
48 |
49 | Another Sample
50 |
51 | Sample Input| Sample Output
52 | ---|---
53 | (0 0 0)RBYRRBY | 4
54 |
55 | 样例输入
56 |
57 | 1 2 3
58 | RRYBRBRYBRY
59 |
60 | 样例输出
61 |
62 | 7
63 |
--------------------------------------------------------------------------------
/zh-hans/microsoft/mstest2015april/problem_c_islands_travel.md:
--------------------------------------------------------------------------------
1 | # Problem C. Islands Travel
2 |
3 | ## Source
4 |
5 | - [hihoCoder](http://hihocoder.com/contest/mstest2015april/problem/3)
6 |
7 | ### Problem
8 |
9 | 时间限制:10000ms
10 |
11 | 单点时限:1000ms
12 |
13 | 内存限制:256MB
14 |
15 | ### 描述
16 |
17 | There are N islands on a planet whose coordinates are (X1, Y1), (X2, Y2), (X3,
18 | Y3) ..., (XN, YN). You starts at the 1st island (X1, Y1) and your destination
19 | is the n-th island (XN, YN). Travelling between i-th and j-th islands will
20 | cost you min{|Xi-Xj|, |Yi-Yj|} (|a| denotes the absolute value of a. min{a, b}
21 | denotes the smaller value between a and b) gold coins. You want to know what
22 | is the minimum cost to travel from the 1st island to the n-th island.
23 |
24 | ### 输入
25 |
26 | Line 1: an integer N.
27 |
28 | Line 2~N+1: each line contains two integers Xi and Yi.
29 |
30 |
31 |
32 | For 40% data, N<=1000,0<=Xi,Yi<=100000.
33 |
34 | For 100% data, N<=100000,0<=Xi,Yi<=1000000000.
35 |
36 | ### 输出
37 |
38 | Output the minimum cost.
39 |
40 | 样例输入
41 |
42 |
43 |
44 |
45 | 3
46 | 2 2
47 | 1 7
48 | 7 6
49 |
50 | 样例输出
51 |
52 |
53 |
54 |
55 | 2
56 |
57 |
58 |
--------------------------------------------------------------------------------
/zh-hans/microsoft/mstest2015april2/README.md:
--------------------------------------------------------------------------------
1 | # Microsoft 2015 April 2
2 |
3 | 本小节总结 Microsoft 2015年四月第二次招实习生的题,题目列表见 [hihoCoder](http://hihocoder.com/contest/mstest2015april2/problems).
4 |
--------------------------------------------------------------------------------
/zh-hans/microsoft/mstest2015april2/problem_b_numeric_keypad.md:
--------------------------------------------------------------------------------
1 | # Problem B. Numeric Keypad
2 |
3 | ## Source
4 |
5 | - [hihoCoder](http://hihocoder.com/contest/mstest2015april2/problem/2)
6 |
7 | ### Problem
8 |
9 | 时间限制:10000ms
10 |
11 | 单点时限:1000ms
12 |
13 | 内存限制:256MB
14 |
15 | ### 描述
16 |
17 | The numberic keypad on your mobile phone looks like below:
18 |
19 |
20 |
21 | 1 2 3
22 | 4 5 6
23 | 7 8 9
24 | 0
25 |
26 |
27 | Suppose you are holding your mobile phone with single hand. Your thumb points
28 | at digit 1. Each time you can 1) press the digit your thumb pointing at, 2)
29 | move your thumb right, 3) move your thumb down. Moving your thumb left or up
30 | is not allowed.
31 |
32 | By using the numeric keypad under above constrains, you can produce some
33 | numbers like 177 or 480 while producing other numbers like 590 or 52 is
34 | impossible.
35 |
36 | Given a number K, find out the maximum number less than or equal to K that can
37 | be produced.
38 |
39 | ### 输入
40 |
41 | The first line contains an integer T, the number of testcases.
42 |
43 | Each testcase occupies a single line with an integer K.
44 |
45 |
46 |
47 | For 50% of the data, 1 <= K <= 999.
48 |
49 | For 100% of the data, 1 <= K <= 10500, t <= 20.
50 |
51 | ### 输出
52 |
53 | For each testcase output one line, the maximum number less than or equal to
54 | the corresponding K that can be produced.
55 |
56 | 样例输入
57 |
58 |
59 |
60 |
61 | 3
62 | 25
63 | 83
64 | 131
65 |
66 | 样例输出
67 |
68 |
69 |
70 |
71 | 25
72 | 80
73 | 129
74 |
75 |
76 |
--------------------------------------------------------------------------------
/zh-hans/microsoft/mstest2015sept2/README.md:
--------------------------------------------------------------------------------
1 | # Microsoft 2015 September 2
2 |
3 | 本小节总结 Microsoft 2015年九月第一次大规模校招的题,题目列表见 [hihoCoder](http://hihocoder.com/contest/mstest2015sept2/problems). 这一场的题目感觉偏难。
4 |
--------------------------------------------------------------------------------
/zh-hans/part_i_basics/README.md:
--------------------------------------------------------------------------------
1 | # Part I - Basics
2 |
3 | 第一部分主要总结一些算法和数据结构方面的基础知识,如基本的数据结构和常见基础算法。
4 |
5 | 本节主要由以下章节构成。
6 | - Basic Data Structure
7 | - Basic Sorting
8 | - Basic Algorithm
9 | - Basic Misc
10 |
11 | ## Reference
12 |
13 | - [VisuAlgo - visualising data structures and algorithms through animation](http://www.comp.nus.edu.sg/~stevenha/visualization/index.html) - 相当碉堡的数据结构和算法可视化。
14 | - [Data Structure Visualization](http://www.cs.usfca.edu/~galles/visualization/Algorithms.html) - 相当碉堡的动画演示!!涵盖了常用的各种数据结构/排序/算法。
15 |
--------------------------------------------------------------------------------
/zh-hans/part_ii_coding/README.md:
--------------------------------------------------------------------------------
1 | # Part II - Coding
2 |
3 | 本节主要总结一些leetcode等题目的实战经验。
4 |
5 | 主要有以下章节构成。
6 |
--------------------------------------------------------------------------------
/zh-hans/part_iii_contest/README.md:
--------------------------------------------------------------------------------
1 | # Part III - Contest
2 |
3 | 本节主要总结一些如 Google APAC, Microsoft 校招等在线测试的题。
4 |
--------------------------------------------------------------------------------
/zh-hans/problem_misc/README.md:
--------------------------------------------------------------------------------
1 | # Problem Misc
2 |
3 | 本章主要总结暂时不方便归到其他章节的题目。
4 |
--------------------------------------------------------------------------------
/zh-hans/problem_misc/add_binary.md:
--------------------------------------------------------------------------------
1 | # Add Binary
2 |
3 | ## Question
4 |
5 | - leetcode: [Add Binary | LeetCode OJ](https://leetcode.com/problems/add-binary/)
6 | - lintcode: [(408) Add Binary](http://www.lintcode.com/en/problem/add-binary/)
7 |
8 | ```
9 | Given two binary strings, return their sum (also a binary string).
10 |
11 | For example,
12 | a = "11"
13 | b = "1"
14 | Return "100".
15 | ```
16 |
17 | ## 题解
18 |
19 | 用字符串模拟二进制的加法,加法操作一般使用自后往前遍历的方法,不同位大小需要补零。
20 |
21 | ### Java
22 |
23 | ```java
24 | public class Solution {
25 | /**
26 | * @param a a number
27 | * @param b a number
28 | * @return the result
29 | */
30 | public String addBinary(String a, String b) {
31 | if (a == null || a.length() == 0) return b;
32 | if (b == null || b.length() == 0) return a;
33 |
34 | StringBuilder sb = new StringBuilder();
35 | int aLen = a.length(), bLen = b.length();
36 |
37 | int carry = 0;
38 | for (int ia = aLen - 1, ib = bLen - 1; ia >= 0 || ib >= 0; ia--, ib--) {
39 | // replace with 0 if processed
40 | int aNum = (ia < 0) ? 0 : a.charAt(ia) - '0';
41 | int bNum = (ib < 0) ? 0 : b.charAt(ib) - '0';
42 |
43 | int num = (aNum + bNum + carry) % 2;
44 | carry = (aNum + bNum + carry) / 2;
45 | sb.append(num);
46 | }
47 | if (carry == 1) sb.append(1);
48 |
49 | // important!
50 | sb.reverse();
51 | String result = sb.toString();
52 | return result;
53 | }
54 | }
55 | ```
56 |
57 | ### 源码分析
58 |
59 | 用到的技巧主要有两点,一是两个数位数大小不一时用0补上,二是最后需要判断最高位的进位是否为1。最后需要反转字符串,因为我们是从低位往高位迭代的。虽然可以使用 insert 避免最后的 reverse 操作,但如此一来时间复杂度就从 $$O(n)$$ 变为 $$O(n^2)$$ 了。
60 |
61 | ### 复杂度分析
62 |
63 | 遍历两个字符串,时间复杂度 $$O(n)$$. reverse 操作时间复杂度 $$O(n)$$, 故总的时间复杂度 $$O(n)$$. 使用了 StringBuilder 作为临时存储对象,空间复杂度 $$O(n)$$.
64 |
--------------------------------------------------------------------------------
/zh-hans/problem_misc/continuous_subarray_sum.md:
--------------------------------------------------------------------------------
1 | # Continuous Subarray Sum
2 |
3 | ## Question
4 |
5 | - lintcode: [(402) Continuous Subarray Sum](http://www.lintcode.com/en/problem/continuous-subarray-sum/)
6 |
7 | ### Problem Statement
8 |
9 | Given an integer array, find a continuous subarray where the sum of numbers is
10 | the biggest. Your code should return the index of the first number and the
11 | index of the last number. (If their are duplicate answer, return anyone)
12 |
13 | #### Example
14 |
15 | Give `[-3, 1, 3, -3, 4]`, return `[1,4]`.
16 |
17 | ## 题解
18 |
19 | 和题 [Maximum Subarray](http://algorithm.yuanbin.me/zh-hans/dynamic_programming/maximum_subarray.html) 几乎一模一样,只是返回值要求不一样。由于需要返回区间索引值,那么显然需要额外变量记录区间起止处。若使用题解2中提到的`sum - minSum`的区间和更新方式,索引终止处容易得知是`sum - minSum > maxSub`时的`i`, 问题是索引起始处如何确定。容易得知索引起始处如果更新,必然在`minSum > sum`时,但问题在于满足此条件的可能不止一处,所以我们需要先记录这个索引值并在`sum - minSum > maxSub`时判定索引终止值是否大于索引起始值,不小于则更新。
20 |
21 | 此题难以一次 bug-free, 需要小心更新索引值。
22 |
23 | ### Java
24 |
25 | ```java
26 | public class Solution {
27 | /**
28 | * @param A an integer array
29 | * @return A list of integers includes the index of the first number and the index of the last number
30 | */
31 | public ArrayList continuousSubarraySum(int[] A) {
32 | ArrayList result = new ArrayList();
33 | if (A == null || A.length == 0) return result;
34 |
35 | int sum = 0, minSum = 0, maxSub = Integer.MIN_VALUE;
36 | int first = 0, last = 0;
37 | int first2 = 0; // candidate for first
38 | for (int i = 0; i < A.length; i++) {
39 | if (minSum > sum) {
40 | minSum = sum;
41 | first2 = i;
42 | }
43 | sum += A[i];
44 | if (sum - minSum > maxSub) {
45 | maxSub = sum - minSum;
46 | last = i;
47 | // update first if valid
48 | if (first2 <= last) first = first2;
49 | }
50 | }
51 |
52 | result.add(first);
53 | result.add(last);
54 | return result;
55 | }
56 | }
57 | ```
58 |
59 | ### 源码分析
60 |
61 | 除了最后要求的`first`和`last`, 我们还需要引入`first2`作为`first`可能的候选变量值。
62 |
63 | ### 复杂度分析
64 |
65 | 略
66 |
--------------------------------------------------------------------------------
/zh-hans/problem_misc/gray_code.md:
--------------------------------------------------------------------------------
1 | # Gray Code
2 |
3 | ## Question
4 |
5 | - leetcode: [Gray Code | LeetCode OJ](https://leetcode.com/problems/gray-code/)
6 | - lintcode: [(411) Gray Code](http://www.lintcode.com/en/problem/gray-code/)
7 |
8 | ### Problem Statement
9 |
10 | The gray code is a binary numeral system where two successive values differ in only one bit.
11 | Given a non-negative integer n representing the total number of bits in the code, find the sequence of gray code. A gray code sequence must begin with 0 and with cover all $$2^n$$ integers.
12 |
13 | #### Example
14 |
15 | Given `n = 2`, return `[0,1,3,2]`. Its gray code sequence is:
16 |
17 | ```
18 | 00 - 0
19 | 01 - 1
20 | 11 - 3
21 | 10 - 2
22 | ```
23 |
24 | #### Note
25 |
26 | For a given n, a gray code sequence is not uniquely defined.
27 |
28 | `[0,2,3,1]` is also a valid gray code sequence according to the above definition.
29 |
30 | #### Challenge
31 |
32 | $$O(2^n)$$ time.
33 |
34 | ## 题解
35 |
36 | 第一次遇到这个题是在腾讯的在线笔试中,当时找到了规律,用的是递归,但是实现似乎有点问题... 直接从 n 位的格雷码分析不太好分析,比如题中`n = 2`的格雷码,我们不妨试试从小到大分析,以 `n = 1` 往后递推。
37 |
38 | 
39 |
40 | 从图中我们可以看出n 位的格雷码可由 n-1位的格雷码递推,在最高位前顺序加0,逆序加1即可。实际实现时我们可以省掉在最高位加0的过程,因为其在数值上和前 n-1位格雷码相同。另外一点则是初始化的处理,图中为从1开始,但若从0开始可进一步简化程序。而且根据 [格雷码](https://zh.wikipedia.org/wiki/%E6%A0%BC%E9%9B%B7%E7%A0%81) 的定义,n=0时确实应该返回0.
41 |
42 | ### Java
43 |
44 | ```java
45 | public class Solution {
46 | /**
47 | * @param n a number
48 | * @return Gray code
49 | */
50 | public ArrayList grayCode(int n) {
51 | if (n < 0) return null;
52 |
53 | ArrayList currGray = new ArrayList();
54 | currGray.add(0);
55 |
56 | for (int i = 0; i < n; i++) {
57 | int msb = 1 << i;
58 | // backward - symmetry
59 | for (int j = currGray.size() - 1; j >= 0; j--) {
60 | currGray.add(msb | currGray.get(j));
61 | }
62 | }
63 |
64 | return currGray;
65 | }
66 | }
67 | ```
68 |
69 | ### 源码分析
70 |
71 | 加0 的那一部分已经在前一组格雷码中出现,故只需将前一组格雷码镜像后在最高位加1即可。第二重 for 循环中需要注意的是`currGray.size() - 1`并不是常量,只能用于给 j 初始化。本应该使用 $$2^n$$ 和上一组格雷码相加,这里考虑到最高位为1的特殊性,使用位运算模拟加法更好。
72 |
73 | ### 复杂度分析
74 |
75 | 生成n 位的二进制码,时间复杂度 $$O(2^n)$$, 使用了`msb`代表最高位的值便于后续相加,空间复杂度 $$O(1)$$.
76 |
77 | ## Reference
78 |
79 | - Soulmachine 的 leetcode 题解
80 |
--------------------------------------------------------------------------------
/zh-hans/problem_misc/longest_consecutive_sequence.md:
--------------------------------------------------------------------------------
1 | # Longest Consecutive Sequence
2 |
3 | Tags: Array, Union Find, Hard
4 |
5 | ## Question
6 |
7 | - leetcode: [Longest Consecutive Sequence](https://leetcode.com/problems/longest-consecutive-sequence/)
8 | - lintcode: [Longest Consecutive Sequence](https://www.lintcode.com/problem/longest-consecutive-sequence/)
9 |
10 | ### Problem Statement
11 |
12 | Given an unsorted array of integers, find the length of the longest
13 | consecutive elements sequence.
14 |
15 | Your algorithm should run in O(_n_) complexity.
16 |
17 | **Example:**
18 |
19 |
20 |
21 | **Input:** [100, 4, 200, 1, 3, 2]
22 | **Output:** 4
23 | **Explanation:** The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4.
24 |
25 | ## 题解
26 |
27 | 首先看题要求,时间复杂度为 $$O(n)$$, 如果排序,基于比较的实现为 $$n \log n$$, 基数排序需要数据有特征。故排序无法达到复杂度要求。接下来可以联想空间换时间的做法,其中以哈希表为代表。这个题要求返回最长连续序列,不要求有序,非常符合哈希表的用法。**由于给定一个数其连续的数要么比它小1,要么大1,那么我们只需往左往右搜索知道在数组中找不到数为止。**结合哈希表查找为 $$O(1)$$ 的特性即可满足要求。
28 |
29 | ### Java
30 |
31 | ```java
32 | class Solution {
33 | public int longestConsecutive(int[] nums) {
34 | if (nums == null || nums.length <= 0) return 0;
35 | Set sets = new HashSet<>(nums.length);
36 | for (int num : nums) {
37 | sets.add(num);
38 | }
39 |
40 | int result = 1;
41 | for (int num : nums) {
42 | int seq = 1;
43 | int right = num, left = num;
44 | // right
45 | while (sets.contains(++right)) {
46 | seq++;
47 | sets.remove(right);
48 | }
49 | // left
50 | while (sets.contains(--left)) {
51 | seq++;
52 | sets.remove(left);
53 | }
54 | sets.remove(num);
55 | if (seq > result) result = seq;
56 | }
57 |
58 | return result;
59 | }
60 | }
61 | ```
62 |
63 | ### 源码分析
64 |
65 | 首先使用 HashSet 建哈希表,然后遍历数组,依次往左往右搜相邻数,搜到了就从 Set 中删除。末尾更新最大值。
66 |
67 | ### 复杂度分析
68 |
69 | 时间复杂度和空间复杂度均为 $$O(n)$$.
70 |
--------------------------------------------------------------------------------
/zh-hans/problem_misc/minimum_subarray.md:
--------------------------------------------------------------------------------
1 | # Minimum Subarray
2 |
3 | ## Question
4 |
5 | - lintcode: [(44) Minimum Subarray](http://www.lintcode.com/en/problem/minimum-subarray/)
6 |
7 | ```
8 | Given an array of integers, find the subarray with smallest sum.
9 |
10 | Return the sum of the subarray.
11 |
12 | Example
13 | For [1, -1, -2, 1], return -3
14 |
15 | Note
16 | The subarray should contain at least one integer.
17 | ```
18 |
19 | ## 题解
20 |
21 | 题 [Maximum Subarray](http://algorithm.yuanbin.me/zh-hans/dynamic_programming/maximum_subarray.html) 的变形,使用区间和容易理解和实现。
22 |
23 | ### Java
24 |
25 | ```java
26 | public class Solution {
27 | /**
28 | * @param nums: a list of integers
29 | * @return: A integer indicate the sum of minimum subarray
30 | */
31 | public int minSubArray(ArrayList nums) {
32 | if (nums == null || nums.isEmpty()) return -1;
33 |
34 | int sum = 0, maxSum = 0, minSub = Integer.MAX_VALUE;
35 | for (int num : nums) {
36 | maxSum = Math.max(maxSum, sum);
37 | sum += num;
38 | minSub = Math.min(minSub, sum - maxSum);
39 | }
40 |
41 | return minSub;
42 | }
43 | }
44 | ```
45 |
46 | ### 源码分析
47 |
48 | 略
49 |
50 | ### 复杂度分析
51 |
52 | 略
53 |
--------------------------------------------------------------------------------
/zh-hans/problem_misc/reverse_integer.md:
--------------------------------------------------------------------------------
1 | # Reverse Integer
2 |
3 | ## Question
4 |
5 | - leetcode: [Reverse Integer | LeetCode OJ](https://leetcode.com/problems/reverse-integer/)
6 | - lintcode: [(413) Reverse Integer](http://www.lintcode.com/en/problem/reverse-integer/)
7 |
8 | ### Problem Statement
9 |
10 | Reverse digits of an integer. Returns 0 when the reversed integer overflows (signed 32-bit integer).
11 |
12 | #### Example
13 |
14 | Given x = 123, return 321
15 |
16 | Given x = -123, return -321
17 |
18 | ## 题解
19 |
20 | 初看这道题觉得先将其转换为字符串然后转置以下就好了,但是仔细一想这种方法存在两种缺陷,一是负号需要单独处理,而是转置后开头的0也需要处理。另一种方法是将原数字逐个弹出,然后再将弹出的数字组装为新数字,咋看以为需要用到栈,实际上却是队列... 所以根本不需要辅助数据结构。关于正负号的处理,我最开始是单独处理的,后来看其他答案时才发现根本就不用分正负考虑。因为`-1 / 10 = 0`.
21 |
22 | ### Java
23 |
24 | ```java
25 | public class Solution {
26 | /**
27 | * @param n the integer to be reversed
28 | * @return the reversed integer
29 | */
30 | public int reverseInteger(int n) {
31 | long result = 0;
32 | while (n != 0) {
33 | result = n % 10 + 10 * result;
34 | n /= 10;
35 | }
36 |
37 | if (result < Integer.MIN_VALUE || result > Integer.MAX_VALUE) {
38 | return 0;
39 | }
40 | return (int)result;
41 | }
42 | }
43 | ```
44 |
45 | ### 源码分析
46 |
47 | 注意 lintcode 和 leetcode 的方法名不一样。使用 long 型保存中间结果,最后判断是否溢出。
48 |
49 | ## Reference
50 |
51 | - [LeetCode-Sol-Res/ReverseInt.java at master · FreeTymeKiyan/LeetCode-Sol-Res](https://github.com/FreeTymeKiyan/LeetCode-Sol-Res/blob/master/Easy/ReverseInt.java)
52 |
--------------------------------------------------------------------------------
/zh-hans/problem_misc/string_to_integer.md:
--------------------------------------------------------------------------------
1 | # String to Integer
2 |
3 | ## Question
4 |
5 | - leetcode: [String to Integer (atoi) | LeetCode OJ](https://leetcode.com/problems/string-to-integer-atoi/)
6 | - lintcode: [(54) String to Integer(atoi)](http://www.lintcode.com/en/problem/string-to-integer-ii/)
7 |
8 | ```
9 | Implement function atoi to convert a string to an integer.
10 |
11 | If no valid conversion could be performed, a zero value is returned.
12 |
13 | If the correct value is out of the range of representable values,
14 | INT_MAX (2147483647) or INT_MIN (-2147483648) is returned.
15 |
16 | Example
17 | "10" => 10
18 |
19 | "-1" => -1
20 |
21 | "123123123123123" => 2147483647
22 |
23 | "1.0" => 1
24 | ```
25 |
26 | ## 题解
27 |
28 | 经典的字符串转整数题,边界条件比较多,比如是否需要考虑小数点,空白及非法字符的处理,正负号的处理,科学计数法等。最先处理的是空白字符,然后是正负号,接下来只要出现非法字符(包含正负号,小数点等,无需对这两类单独处理)即退出,否则按照正负号的整数进位加法处理。
29 |
30 | ### Java
31 |
32 | ```java
33 | public class Solution {
34 | /**
35 | * @param str: A string
36 | * @return An integer
37 | */
38 | public int atoi(String str) {
39 | if (str == null || str.length() == 0) return 0;
40 |
41 | // trim left and right spaces
42 | String strTrim = str.trim();
43 | int len = strTrim.length();
44 | // sign symbol for positive and negative
45 | int sign = 1;
46 | // index for iteration
47 | int i = 0;
48 | if (strTrim.charAt(i) == '+') {
49 | i++;
50 | } else if (strTrim.charAt(i) == '-') {
51 | sign = -1;
52 | i++;
53 | }
54 |
55 | // store the result as long to avoid overflow
56 | long result = 0;
57 | while (i < len) {
58 | if (strTrim.charAt(i) < '0' || strTrim.charAt(i) > '9') {
59 | break;
60 | }
61 | result = 10 * result + sign * (strTrim.charAt(i) - '0');
62 | // overflow
63 | if (result > Integer.MAX_VALUE) {
64 | return Integer.MAX_VALUE;
65 | } else if (result < Integer.MIN_VALUE) {
66 | return Integer.MIN_VALUE;
67 | }
68 | i++;
69 | }
70 |
71 | return (int)result;
72 | }
73 | }
74 | ```
75 |
76 | ### 源码分析
77 |
78 | 符号位使用整型表示,便于后期相乘相加。在 while 循环中需要注意判断是否已经溢出,如果放在 while 循环外面则有可能超过 long 型范围。
79 |
80 | ### 复杂度分析
81 |
82 | 略
83 |
84 | ## Reference
85 |
86 | - [String to Integer (atoi) 参考程序 Java/C++/Python](http://www.jiuzhang.com/solutions/string-to-integer-atoi/)
87 |
--------------------------------------------------------------------------------
/zh-hans/string/README.md:
--------------------------------------------------------------------------------
1 | # String - 字符串
2 |
3 | 本章主要介绍字符串相关题目。
4 |
5 | > 处理字符串操作相关问题时,常见的做法是从字符串尾部开始编辑,从后往前逆向操作。这么做的原因是因为字符串的尾部往往有足够空间,可以直接修改而不用担心覆盖字符串前面的数据。
6 |
7 | 摘自《程序员面试金典》
8 |
--------------------------------------------------------------------------------
/zh-hans/styles/website.css:
--------------------------------------------------------------------------------
1 | .book .book-summary, .book .book-body {
2 | font-family: "Microsoft YaHei UI", "Microsoft Yahei", "PingFang SC", "Lantinghei SC", "Hiragino Sans GB", "WenQuanYi Micro Hei", "WenQuanYi Zen Hei", "Noto Sans CJK SC", "Microsoft JhengHei UI", "Microsoft JhengHei", "PingFang TC", "Lantinghei TC", "Noto Sans CJK TC", "Helvetica Neue", Helvetica, Arial, sans-serif;
3 | }
4 |
--------------------------------------------------------------------------------
/zh-hans/tags.md:
--------------------------------------------------------------------------------
1 | # Tags
2 |
--------------------------------------------------------------------------------
/zh-tw/appendix_i_interview_and_resume/README.md:
--------------------------------------------------------------------------------
1 | # Appendix I Interview and Resume
2 |
3 | 本章主要總結一些技術面試和撰寫履歷方面的注意事項。
4 |
5 |
--------------------------------------------------------------------------------
/zh-tw/basics_algorithm/README.md:
--------------------------------------------------------------------------------
1 | # Basics Algorithm
2 |
3 | 本章主要介紹一些常用的基本演算法,後序章節介紹一些高級演算法。
4 |
--------------------------------------------------------------------------------
/zh-tw/basics_algorithm/bitmap.md:
--------------------------------------------------------------------------------
1 | # Bitmap
2 |
3 | 最開始接觸 bitmap 是在 Jon Bentley 所著《Programming Pearls》 (無繁體中文版,簡體中文版書名為《編程珠璣》) 這本書上,書中所述的方法有點簡單粗暴,不過思想倒是不錯——從 Information Theory 的角度來解釋就是信息壓縮了。即將原來32位表示一個 int 變爲一位表示一個 int. 從空間的角度來說就是巨大的節省了(1/32)。可能的應用有**大數據排序/查找(非負整數)**。
4 |
5 | C++ 中有`bitset`容器,其他語言可用類似方法實現。
6 |
7 | ## Implementation
8 |
9 | ### C
10 |
11 | ```c
12 | #include
13 | #include
14 |
15 | /*
16 | * @param bits: uint array, i: num i of original array
17 | */
18 | void setbit(unsigned int *bits, unsigned int i, int BIT_LEN)
19 | {
20 | bits[i / BIT_LEN] |= 1 << (i % BIT_LEN);
21 | }
22 |
23 | /*
24 | * @param bits: uint array, i: num i of original array
25 | */
26 | int testbit(unsigned int *bits, unsigned int i, int BIT_LEN)
27 | {
28 | return bits[i / BIT_LEN] & (1 << (i % BIT_LEN));
29 | }
30 |
31 | int main(int argc, char *argv[])
32 | {
33 | const int BIT_LEN = sizeof(int) * 8;
34 | const unsigned int N = 1 << (BIT_LEN - 1);
35 | unsigned int *bits = (unsigned int *)calloc(N, sizeof(int));
36 | for (unsigned int i = 0; i < N; i++) {
37 | if (i % 10000001 == 0) setbit(bits, i, BIT_LEN);
38 | }
39 |
40 | for (unsigned int i = 0; i < N; i++) {
41 | if (testbit(bits, i, BIT_LEN) != 0) printf("i = %u exists.\n", i);
42 | }
43 | free(bits);
44 | bits = NULL;
45 |
46 | return 0;
47 | }
48 | ```
49 |
50 | ### 源碼分析
51 |
52 | 核心爲兩個函數方法的使用,`setbit`用於將非負整數`i`置於指定的位。可用分區分位的方式來理解位圖排序的思想,即將非負整數`i`放到它應該在的位置。比如16,其可以位於第一個 int 型的第17位,具體實現即將第17位置一,細節見上面代碼。測試某個數是否存在於位圖中也可以採用類似方法。
53 |
--------------------------------------------------------------------------------
/zh-tw/basics_algorithm/divide_and_conquer.md:
--------------------------------------------------------------------------------
1 | # Divide and Conquer - 分治法
2 |
3 | 在計算機科學中,分治法是一種很重要的演算法。分治法即『分而治之』,把一個複雜的問題分成兩個或更多的相同或相似的子問題,再把子問題分成更小的子問題……直到最後子問題可以簡單的直接求解,原問題的解即子問題的解的合併。這個思想是很多高效演算法的基礎,如排序演算法(快速排序,合併排序)等。
4 |
5 | ## 分治法思想
6 |
7 | 分治法所能解決的問題一般具有以下幾個特徵:
8 |
9 | 1. 問題的規模縮小到一定的程度就可以容易地解決。
10 | 2. 問題可以分解爲若干個規模較小的相同問題,即該問題具有**最優子結構**性質。
11 | 3. 利用該問題分解出的子問題的解可以合併爲該問題的解。
12 | 4. 該問題所分解出的各個子問題是相互獨立的,即子問題之間不包含公共的子問題。
13 |
14 | 分治法的三個步驟是:
15 |
16 | 1. 分解(Divide):將原問題分解爲若乾子問題,這些子問題都是原問題規模較小的實例。
17 | 2. 解決(Conquer):遞歸地求解各子問題。如果子問題規模足夠小,則直接求解。
18 | 3. 合併(Combine):將所有子問題的解合併爲原問題的解。
19 |
20 | 分治法的經典題目:
21 |
22 | 1. 二分搜索
23 | 2. 大整數乘法
24 | 3. Strassen矩陣乘法
25 | 4. 棋盤覆蓋
26 | 5. 歸並排序
27 | 6. 快速排序
28 | 7. 循環賽日程表
29 | 8. 河內塔
30 |
--------------------------------------------------------------------------------
/zh-tw/basics_algorithm/math/README.md:
--------------------------------------------------------------------------------
1 | # Math
2 |
3 | 本小節總結一些與數學(尤其是數論部分)有關的基礎,主要總結了《挑戰程序設計競賽》(原文為《プログラミングコンテストチャレンジブック》)第二章。主要包含以下內容:
4 |
5 | 1. Greatest Common Divisor(最大公因數)
6 | 2. Prime(質數基礎理論)
7 | 3. Modulus(取模運算)
8 | 4. Fast Power(快速冪運算)
9 |
10 | ## Modulus - 取模運算
11 |
12 | 有時計算結果可能會溢位,此時往往需要對結果取餘。如果有`a % m = c % m` 和 `b % m = d % m`, 那麼有以下模運算成立。
13 |
14 | - `(a + b) % m = (c + d) % m`
15 | - `(a - b) % m = (c - d) % m`
16 | - `(a × b) % m = (c × d) % m`
17 |
18 | 需要注意的是沒有除法運算,另外由於最終結果可能溢位,故需要使用更大範圍的類型來保存取模之前的結果。另外若`a`是負數時往往需要改寫爲 `a % m + m`, 這樣就保證結果在`[0, m - 1]`範圍內了。
19 |
20 | ## Fast Power - 快速冪運算
21 |
22 | 快速冪運算的核心思想爲反覆平方法,將冪指數表示爲2的冪次的和,等價於二進制進行移位計算(不斷取冪的最低位),比如 $$x^{22} = x^{16} x^4 x^2$$.
23 |
24 | ### C++
25 |
26 | ```C++
27 | long long fastModPow(lont long x, int n, long long mod) {
28 | long long res = 1 % mod;
29 | while(n > 0) {
30 | //if lowest bit is 1, fast judge of even number
31 | if((n & 1) != 0)
32 | res = res * x % mod;
33 | x = x * x % mod;
34 | n >>= 1;
35 | }
36 | return res;
37 | }
38 | ```
39 |
40 | ### Java
41 |
42 | ```java
43 | import java.util.*;
44 |
45 | public class FastPow {
46 | public static long fastModPow(long x, long n, long mod) {
47 | long res = 1 % mod;
48 | while (n > 0) {
49 | // if lowest bit is 1
50 | if ((n & 1) != 0) res = res * x % mod;
51 | x = x * x % mod;
52 | n >>= 1;
53 | }
54 | return res;
55 | }
56 |
57 | public static void main(String[] args) {
58 | if (args.length != 2 && args.length != 3) return;
59 |
60 | long x = Long.parseLong(args[0]);
61 | long n = Long.parseLong(args[1]);
62 | long mod = Long.MAX_VALUE;
63 | if (args.length == 3) {
64 | mod = Long.parseLong(args[2]);
65 | }
66 | System.out.println(fastModPow(x, n, mod));
67 | }
68 | }
69 | ```
70 |
--------------------------------------------------------------------------------
/zh-tw/basics_algorithm/probability/README.md:
--------------------------------------------------------------------------------
1 | # Probability
2 |
--------------------------------------------------------------------------------
/zh-tw/basics_data_structure/README.md:
--------------------------------------------------------------------------------
1 | # Data Structure - 資料結構
2 |
3 | 本章主要介紹一些基本的資料結構和演算法。
4 |
--------------------------------------------------------------------------------
/zh-tw/basics_data_structure/graph.md:
--------------------------------------------------------------------------------
1 | # Graph - 圖
2 |
3 | 圖的表示通常使用**鄰接矩陣和鄰接表**,前者易實現但是對於稀疏矩陣會浪費較多空間,後者使用鏈表的方式存儲資訊但是對於圖搜索時間複雜度較高。
4 |
5 | ## 程式實現
6 |
7 | ### 鄰接矩陣 (Adjacency Matrix)
8 |
9 | 設頂點個數爲 V, 那麼鄰接矩陣可以使用 V × V 的二維陣列來表示。
10 | `g[i][j]`表示頂點`i`和頂點`j`的關係,對於無向圖(undirected graph)可以使用0/1表示是否有連接,對於帶有權重的圖則需要使用`INF`來區分。有重邊時保存邊數或者權值最大/小的邊即可。
11 |
12 | #### Python
13 | ```python
14 | g = [[0 for _ in range(V)] for _ in range(V)]
15 | ```
16 |
17 | #### Java
18 | ```java
19 | /* Java Definition */
20 | int[][] g = new int[V][V];
21 | ```
22 |
23 | #### C++
24 | ```C++
25 | vector> g (V, vector(V, 0));
26 | ```
27 |
28 |
29 | ### 鄰接表 (Adjacency List)
30 |
31 | 鄰接表通過表示從頂點`i`出發到其他所有可能能到的邊。
32 |
33 | ### 有向圖
34 |
35 | #### Python
36 |
37 | ```python
38 | class DirectedGraphNode:
39 | def __init__(self, x):
40 | self.label = x
41 | self.neighbors = []
42 | ```
43 |
44 | #### Java
45 |
46 | ```java
47 | /* Java Definition */
48 | class DirectedGraphNode {
49 | int label;
50 | ArrayList neighbors;
51 | DirectedGraphNode(int x) {
52 | label = x;
53 | neighbors = new ArrayList();
54 | }
55 | }
56 | ```
57 |
58 | #### C++
59 |
60 | ```C++
61 | struct DirectedGraphNode {
62 | int label;
63 | vector neighbors;
64 |
65 | DirectedGraphNode(int x): label(x) { }
66 | };
67 | ```
68 |
69 | ### 無向圖同上,只不過在建圖時雙向同時加。
70 |
71 | #### Python
72 |
73 | ```python
74 | class UndirectedGraphNode:
75 | def __init__(self, x):
76 | self.label = x
77 | self.neighbors = []
78 | ```
79 |
80 |
81 | #### Java
82 |
83 | ```java
84 | class UndirectedGraphNode {
85 | int label;
86 | ArrayList neighbors;
87 | UndirectedGraphNode(int x) {
88 | this.label = x;
89 | this.neighbors = new ArrayList();
90 | }
91 | }
92 | ```
93 |
94 | #### C++
95 |
96 | ```C++
97 | struct UndirectedGraphNode {
98 | int label;
99 | vector neighbors;
100 |
101 | UndirectedGraphNode(int x): label(x) { }
102 | };
103 | ```
--------------------------------------------------------------------------------
/zh-tw/basics_data_structure/heap.md:
--------------------------------------------------------------------------------
1 | # Heap - 堆
2 |
3 | 一般情況下,堆通常指的是**二叉堆**,**二叉堆**是一個近似**完全二元樹**的數據結構,**即披著二元樹羊皮的陣列,**故使用陣列來實現較為便利。子結點的鍵值(key)或索引總是小於(或者大於)它的父節點,且每個節點的左右子樹又是一個**二叉堆**(大根堆(Max Heap)或者小根堆(Min Heap))。根節點最大的堆叫做最大堆或大根堆,根節點最小的堆叫做最小堆或小根堆。**常被用作實現優先隊列(Priority Queue)。**
4 |
5 | ## 特點
6 |
7 | 1. **以陣列表示,但是以完全二元樹的方式理解**。
8 | 2. 唯一能夠同時最優地利用空間和時間的方法——最壞情況下也能保證使用 $$2N \log N$$ 次比較和恒定的額外空間。
9 | 3. 在索引從0開始的陣列中:
10 | - 父節點 `i` 的左子節點在位置`(2*i+1)`
11 | - 父節點 `i` 的右子節點在位置`(2*i+2)`
12 | - 子節點 `i` 的父節點在位置`floor((i-1)/2)`
13 |
14 | ## 堆的基本操作
15 |
16 | 以大根堆為例,堆的常用操作如下。
17 |
18 | 1. 最大堆調整(Max_Heapify):將堆的末端子節點作調整,使得子節點永遠小於父節點
19 | 2. 創建最大堆(Build_Max_Heap):將堆所有數據重新排序
20 | 3. 堆排序(HeapSort):移除位在第一個數據的根節點,並做最大堆調整的遞迴運算
21 |
22 | 其中步驟1是給步驟2和3用的。
23 |
24 | 
25 |
26 | ## Python
27 |
28 | ```python
29 | class MaxHeap:
30 | def __init__(self, array=None):
31 | if array:
32 | self.heap = self._max_heapify(array)
33 | else:
34 | self.heap = []
35 |
36 | def _sink(self, array, i):
37 | # move node down the tree
38 | left, right = 2 * i + 1, 2 * i + 2
39 | max_index = i
40 | if left < len(array) and array[left] > array[max_index]:
41 | max_index = left
42 | if right < len(array) and array[right] > array[max_index]:
43 | max_index = right
44 | if max_index != i:
45 | array[i], array[max_index] = array[max_index], array[i]
46 | self._sink(array, max_index)
47 |
48 | def _swim(self, array, i):
49 | # move node up the tree
50 | if i == 0:
51 | return
52 | father = (i - 1) / 2
53 | if array[father] < array[i]:
54 | array[father], array[i] = array[i], array[father]
55 | self._swim(array, father)
56 |
57 | def _max_heapify(self, array):
58 | for i in xrange(len(array) / 2, -1, -1):
59 | self._sink(array, i)
60 | return array
61 |
62 | def push(self, item):
63 | self.heap.append(item)
64 | self._swim(self.heap, len(self.heap) - 1)
65 |
66 | def pop(self):
67 | self.heap[0], self.heap[-1] = self.heap[-1], self.heap[0]
68 | item = self.heap.pop()
69 | self._sink(self.heap, 0)
70 | return item
71 | ```
72 |
--------------------------------------------------------------------------------
/zh-tw/basics_data_structure/huffman_compression.md:
--------------------------------------------------------------------------------
1 | # Huffman Compression - 霍夫曼壓縮
2 |
3 | 主要思想:放棄文本文件的普通保存方式:不再使用7位或8位二進制數表示每一個字符,而是**用較少的比特表示出現頻率最高的字符,用較多的比特表示出現頻率低的字符**。
4 |
5 | 使用變動長度編碼(variable-length code)來表示字串,勢必會導致編解碼時碼字的唯一性問題,因此需要一種編解碼方式唯一的前綴碼(prefix code),而表示前綴碼的一種簡單方式就是使用單詞搜尋樹,其中最優前綴碼即為Huffman首創。
6 |
7 | 以符號F, O, R, G, E, T為例,其出現的頻次如以下表格所示。
8 |
9 | | Symbol | F | O | R | G | E | T |
10 | | -- | -- | -- | -- | -- | -- | -- |
11 | | Frequence | 2 | 3 | 4 | 4 | 5 | 7 |
12 | | Code | 000 | 001 | 100 | 101 | 01 | 11 |
13 |
14 | 則對各符號進行霍夫曼編碼的動態示例如下圖所示。基本步驟是將出現頻率由小到大排列,組成子樹後頻率相加作為整體再和其他未加入二元樹中的節點頻率比較。加權路徑長為節點的頻率乘以樹的深度。
15 |
16 | 
17 |
18 | 有關霍夫曼編碼的具體步驟可參考 [Huffman 編碼壓縮算法 | 酷 殼 - CoolShell.cn](http://coolshell.cn/articles/7459.html) 和 [霍夫曼編碼 - 維基百科,自由的百科全書](http://zh.wikipedia.org/wiki/%E9%9C%8D%E5%A4%AB%E6%9B%BC%E7%BC%96%E7%A0%81),清晰易懂。
19 |
--------------------------------------------------------------------------------
/zh-tw/basics_data_structure/map.md:
--------------------------------------------------------------------------------
1 | # Map - 關聯容器
2 |
3 | Map 是一種關聯數組的資料結構,也常被稱爲字典(dictionary)或鍵值對(key-value pair)。
4 |
5 | ## 程式實現
6 |
7 | ### Python
8 |
9 | 在 Python 中 `dict`(Map) 是一種基本的資料結構。
10 |
11 | ```python
12 | # map 在 python 中是一個keyword
13 | hash_map = {} # or dict()
14 | hash_map['shaun'] = 98
15 | hash_map['wei'] = 99
16 | exist = 'wei' in hash_map # check existence
17 | point = hash_map['shaun'] # get value by key
18 | point = hash_map.pop('shaun') # remove by key, return value
19 | keys = hash_map.keys() # return key list
20 | # iterate dictionary(map)
21 | for key, value in hash_map.items():
22 | # do something with k, v
23 | pass
24 | ```
25 |
26 | ### C++
27 |
28 | 與 Set 類似,STL提供了 Map 與 Multimap 兩種,提供同一鍵(key)對應單個或多個值(value),自C++11以後,一樣提供兩種實現方式,基於紅-黑樹的`map`與`multimap`,包含在`