├── .gitignore ├── LICENSE ├── README - Copy.md ├── README.md ├── String ├── .DS_Store ├── alien_dictionary.md ├── anagrams.md ├── compare_strings.md ├── compare_version_numbers.md ├── count_and_say.md ├── different_ways_to_add_parentheses.md ├── encode_and_decode_strings.md ├── excel_sheet_column_title.md ├── generate_parentheses.md ├── group_anagrams.md ├── group_shifted_strings.md ├── implement_strstr.md ├── isomorphic_strings.md ├── length_of_last_word.md ├── length_of_last_word_i.md ├── letter_combinations_of_a_phone_number.md ├── longest_common_prefix.md ├── longest_substring_with_at_most_k_distinct_characters.md ├── longest_substring_without_repeating_characters.md ├── longest_valid_parentheses.md ├── maximum_product_of_word_lengths.md ├── minimum_window_substring.md ├── multiply_strings.md ├── one_edit_distance.md ├── palindrome_permutation.md ├── palindrome_permutation_ii.md ├── regular_expression_matching.md ├── remove_duplicate_letters.md ├── remove_invalid_parentheses.md ├── repeated_dna_sequences.md ├── string_shift.md ├── string_to_integer_atoi.md ├── strobogrammatic_number.md ├── strobogrammatic_number_ii.md ├── strobogrammatic_number_iii.md ├── substring_with_concatenation_of_all_words.md ├── summary_ranges.md ├── unique_word_abbreviation.md ├── valid_anagram.md ├── valid_palindrome.md ├── valid_parentheses.md ├── wildcard_matching.md ├── word_pattern.md ├── word_pattern_ii.md ├── word_search.md ├── word_search_ii.md └── zigzag_conversion.md ├── amazon.md ├── array.md ├── array ├── .DS_Store ├── 2_sum.md ├── 3sum_smaller.md ├── 4_sum.md ├── bitwise_and_of_numbers_range.md ├── contains_duplicate.md ├── contains_duplicate_iii.md ├── contains_duplicates_ii.md ├── continuous_subarray_sum.md ├── continuous_subarray_sum_ii.md ├── find_all_numbers_in_a_given_array_that_occur_odd_n.md ├── find_minimum_in_rotated_sorted_array.md ├── find_minimum_in_rotated_sorted_array_ii.md ├── find_peak_element.md ├── find_second_largest_number.md ├── find_the_duplicate_number.md ├── find_top_k_elements_in_array.md ├── first_bad_version.md ├── first_missing_positive.md ├── flatten_2d_vector.md ├── h-index.md ├── h-index_ii.md ├── interleaving_positive_and_negative_numbers.md ├── kth_largest_element_in_an_array.md ├── largest_number.md ├── longest_consecutive_sequence.md ├── longest_continuous_increasing_subsequence.md ├── majority_number.md ├── majority_number_ii.md ├── maximum_gap.md ├── maximum_product_subarray.md ├── maximum_size_subarray_sum_equals_k.md ├── maximum_subarray.md ├── maximum_subarray_difference.md ├── maximum_subarray_iii.md ├── median_of_two_sorted_arrays.md ├── merge_intervals.md ├── merge_sorted_array.md ├── minimum_size_subarray_sum.md ├── minimum_subarray.md ├── missing_ranges.md ├── move_zeros.md ├── nth_smallest_number_in_matrix.md ├── partition_array_by_odd_and_even.md ├── product_of_array_exclude_itself.md ├── range_sum_query_-_immutable.md ├── range_sum_query_2d_-_immutable.md ├── range_sum_query_2d_-_mutable.md ├── read_n_characters_given_read4.md ├── recover_rotated_sorted_array.md ├── remove_duplicates_from_sorted_array.md ├── remove_element.md ├── rotate_image.md ├── search_a_2d_array.md ├── search_for_a_range.md ├── search_in_a_big_sorted_array.md ├── search_in_rotated_sorted_array.md ├── search_in_rotated_sorted_array_ii.md ├── search_insert_position.md ├── shortest_word_distance.md ├── shortest_word_distance_ii.md ├── shortest_word_distance_iii.md ├── single_number.md ├── single_number_ii.md ├── single_number_iii.md ├── sorrounded_regions.md ├── sort_color_ii.md ├── sort_colors.md ├── spiral_matrix.md ├── spiral_matrix_ii.md ├── subarray_sum.md ├── subarray_sum_closest.md ├── subarray_sum_ii.md ├── submatrix_sum.md ├── the_smallest_difference.md ├── triangle.md ├── two_sum_iii_-_data_structure_design.md ├── valid_sudoku.md ├── wiggle_sort.md └── wiggle_sort_ii.md ├── binary_tree.md ├── binary_tree ├── .DS_Store ├── README.md ├── balanced_binary_tree.md ├── binary_search_tree_iterator.md ├── binary_tree_level_order_traversal.md ├── binary_tree_level_order_traversal_ii.md ├── binary_tree_longest_consecutive_sequence.md ├── binary_tree_maximum_path_sum.md ├── binary_tree_path.md ├── binary_tree_postorder_traversal.md ├── binary_tree_preorder_traversal.md ├── binary_tree_right_side_view.md ├── binary_tree_upside_down.md ├── binary_tree_vertical_order_traversal.md ├── binary_tree_zigzag_level_order_traversal.md ├── closest_binary_search_tree_value.md ├── closest_binary_search_tree_value_ii.md ├── construct_binary_tree_from_inorder_and_postorder_traversal.md ├── construct_binary_tree_from_preorder_and_inorder_traversal.md ├── convert_sorted_array_to_binary_search_tree_with_minimal_height.md ├── count_complete_tree_nodes.md ├── count_univalue_subtrees.md ├── flatten_binary_tree_to_linked_list.md ├── inorder_successor_in_bst.md ├── inorder_traversal.md ├── insert_node_in_a_binary_search_tree.md ├── invert_binary_tree.md ├── kth_smallest_element_in_a_bst.md ├── lowest_common_ancestor.md ├── maximum_depth_of_binary_tree.md ├── minimum_depth_of_binary_tree.md ├── path_sum.md ├── path_sum_ii.md ├── path_sum_iii.md ├── populating_next_right_pointers_in_each_node.md ├── populating_next_right_pointers_in_each_node_ii.md ├── recover_binary_search_tree.md ├── remove_node_in_binary_search_tree.md ├── same_tree.md ├── search_range_in_binary_search_tree.md ├── serialize_and_deserialize_binary_tree.md ├── subtree.md ├── sum_root_to_leaf_numbers.md ├── symmetric_tree.md ├── template.md ├── unique_binary_search_tree.md ├── unique_binary_search_trees_ii.md ├── uniquebinary_search_trees.md ├── valid_binary_search_tree.md └── verify_preorder_sequence_in_binary_search_tree.md ├── bit_manipulation.md ├── bit_manipulation ├── binary_representation.md ├── flip_bits.md ├── number_of_1_bits.md ├── reverse_bits.md └── update_bits.md ├── bst_successor_predecessor.md ├── bubble-sort.gif ├── design.md ├── design ├── amazon.md ├── deck.md ├── deck2.md ├── filesystem.md ├── hashfunction.md ├── jukebox.md ├── onlinereadersystem.md └── parkinglot.md ├── difficult_problems.md ├── difficult_problems ├── basic_calculator.md ├── basic_calculator_ii.md ├── binary_tree_maximum_path_sum.md ├── binary_tree_traversal.md ├── binary_tree_upside_down.md ├── count_of_smaller_numbers_after_self.md ├── count_univalue_subtrees.md ├── course_schedule.md ├── decode_ways.md ├── expression_add_operators.md ├── graph_valid_tree.md ├── kth_largest_element_in_an_array.md ├── lru_cache.md ├── maximal_square.md ├── maximum_gap.md ├── palindrome_permutation_ii.md ├── permutation_sequence.md ├── range_sum_query_2d_-_immutable.md ├── remove_invalid_parentheses.md ├── reverse_linked_list_ii.md ├── reverse_nodes_in_k-group.md ├── reverse_words_in_a_string.md ├── scramble_string.md ├── serialize_and_deserialize_binary_tree.md ├── shortest_palindrome.md ├── smallest_rectangle_enclosing_black_pixels.md ├── substring_with_concatenation_of_all_words.md ├── the_skyline_problem.md ├── wildcard_matching.md ├── word_break_ii.md └── word_ladder_ii.md ├── difficult_questions └── verify_preorder_sequence_in_binary_search_tree.md ├── dynamic_programming.md ├── dynamic_programming ├── .DS_Store ├── best_time_to_buy_and_sell_stock_with_cooldown.md ├── candy.md ├── climbing_stairs.md ├── coin_change.md ├── coins_in_a_line.md ├── coins_in_a_line_ii.md ├── coins_in_a_line_iii.md ├── copy_books.md ├── decode_ways.md ├── dungeon_game.md ├── edit_distance.md ├── flip_game.md ├── flip_game_ii.md ├── house_robber.md ├── house_robber_ii.md ├── interleaving_string.md ├── jump_game.md ├── jump_game_ii.md ├── longest_common_substring.md ├── longest_increasing_continuous_subsequence_ii.md ├── longest_increasing_subsequence.md ├── longest_palindrome_substring.md ├── maximal_square.md ├── minimum_adjustment_cost.md ├── minimum_path_sum.md ├── nim_game.md ├── paint_fence.md ├── paint_house.md ├── paint_house_ii.md ├── palindrome_partition.md ├── palindrome_partition_ii.md ├── post_office_problem.md ├── scramble_string.md ├── triangle.md ├── unique_paths.md ├── unique_paths_ii.md ├── word_break.md └── word_break_ii.md ├── graph.md ├── graph ├── .DS_Store ├── building_outline.md ├── clone_graph.md ├── container_with_most_water.md ├── course_schedule.md ├── find_the_connected_component_in_the_undirected_graph.md ├── find_the_connected_set_in_the_directed_graph.md ├── graph_valid_tree.md ├── meeting_room.md ├── meeting_room_ii.md ├── minimum_height_tree.md ├── number_of_connected_components_in_an_undirected_gr.md ├── number_of_islands.md ├── number_of_islands_ii.md ├── route_between_two_nodes_in_graph.md ├── shortest_distance_from_all_buildings.md ├── trapping_rain_water.md ├── trapping_rain_water_ii.md └── walls_and_gates.md ├── heap.md ├── heap ├── .DS_Store ├── data_stream_median.md └── heapify.md ├── high_frequency.md ├── high_frequency ├── .DS_Store ├── 2_sum.md ├── 3_sum.md ├── 3sum_closest_md.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 ├── k_sum.md ├── k_sum_ii.md ├── number_of_airplanes_in_the_sky.md ├── sum.md ├── text_justification.md ├── the_skyline_problem.md └── triangle_count.md ├── insertion-sort.gif ├── interview_questions_collection.md ├── iterator.md ├── iterator ├── peeking_iterator.md └── zigzag_iterator.md ├── knowledge.md ├── knowledge ├── basic_concept.md ├── data_structure.md ├── design_pattern.md ├── java_knowledge.md ├── network.md └── sorting.md ├── linked_list.md ├── linked_list ├── .DS_Store ├── add_two_numbers.md ├── convert_sorted_list_to_binary_search_tree.md ├── copy_list_with_random_pointer.md ├── delete_node_in_the_middle_of_singly_linked_list.md ├── insertion_sort_list.md ├── intersection_of_two_linked_lists.md ├── list_cycle.md ├── list_cycle_ii.md ├── merge_k_sorted_lists.md ├── merge_two_sorted_lists.md ├── odd_even_linked_list.md ├── palindrome_linked_list.md ├── partition_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_lis.md ├── reorder_list.md ├── reverse_linked_list.md ├── reverse_linked_list_ii.md ├── reverse_nodes_in_k-group.md ├── rotate_list.md ├── sort_list.md └── swap_nodes_in_pairs.md ├── math.md ├── math ├── a_+_b_problem.md ├── add_binary.md ├── add_digits.md ├── basic_calculator.md ├── basic_calculator_ii.md ├── best_meeting_point.md ├── bulb_switcher.md ├── cosine_similarity.md ├── count_primes.md ├── delete_digits.md ├── digit_count.md ├── divide_two_integer.md ├── expression_add_operators.md ├── expression_evaluator.md ├── find_the_missing_number.md ├── gray_code.md ├── happy_number.md ├── insert_interval.md ├── integer_to_roman.md ├── max_points_in_a_line.md ├── palindrome_number.md ├── pascal_triangle.md ├── pascal_triangle_ii.md ├── perfect_number.md ├── perfect_squares.md ├── permutation.md ├── permutation_ii.md ├── permutation_index.md ├── permutation_index_ii.md ├── permutation_sequence.md ├── plus_one.md ├── power_of_three.md ├── powx,n.md ├── print_numbers_by_recursion.md ├── rectangle_area.md ├── reverse_integer.md ├── roman_to_integer.md ├── sparse_matrix_multiplication.md ├── sqrtx.md ├── strobogrammatic_number.md ├── strobogrammatic_number_ii.md ├── super_ugly_number.md ├── trailing_zeros.md ├── triangle.md ├── ugly_number.md ├── ugly_number_ii.md └── valid_number.md ├── matrix └── set_matrix_zeroes.md ├── merge-sort.gif ├── pom.xml ├── quick-sort.gif ├── quick-sort.html ├── segment_tree.md ├── segment_tree ├── .DS_Store ├── count_of_smaller_number.md ├── count_of_smaller_number_before_itself.md ├── count_of_smaller_numbers_after_itself.md ├── interval_minimum_number.md ├── interval_sum.md ├── interval_sum_ii.md ├── range_sum_query_-_mutable.md ├── segment_tree_build.md ├── segment_tree_build_ii.md ├── segment_tree_modify.md ├── segment_tree_query.md └── segment_tree_query_ii.md ├── selection-sort.gif ├── sliding_window.md ├── sliding_window ├── sliding_window_maximum.md └── sliding_window_median.md ├── sql.md ├── sql ├── SQLInterview.pdf ├── SQL_question_set 1 ├── SQL_question_set 2 ├── combine_two_tables.md ├── nth_highest_salary.md ├── rank_scores.md └── second_highest_salary.md ├── src └── main │ └── java │ └── com │ └── zhokhov │ └── interview │ ├── data │ ├── ArrayList.java │ ├── BinaryTree.java │ ├── HashMap.java │ ├── LinkedList.java │ ├── Queue.java │ └── Stack.java │ ├── sorting │ ├── BubbleSort.java │ ├── InsertionSort.java │ ├── MergeSort.java │ ├── QuickSort.java │ └── SelectionSort.java │ └── util │ └── Console.java ├── stack.md ├── stack ├── evaluate_reverse_polish_notation.md ├── expression_tree_build.md ├── implement_queue_using_stacks.md ├── implement_stack_using_queues.md ├── largest_rectangle_in_histogram.md ├── max_tree.md ├── maximal_square.md ├── min_stack.md └── simplify_path.md ├── string.md ├── tech-vids.md ├── template.md ├── trie.md └── trie ├── add_and_search_word_-_data_structure_design.md └── implement_trie.md /String/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/String/.DS_Store -------------------------------------------------------------------------------- /String/compare_strings.md: -------------------------------------------------------------------------------- 1 | #Compare Strings 2 | 3 | 解題思路:利用一個陣列代表字串中出現的字元,若出現在 s 字串,則陣列該位置加一,若出現在 t 字串,則陣列該位置減一,最後利用一個循環確保陣列中每個值皆為零即可。 4 | 5 | ```java 6 | private boolean isAnagram(String s, String t) { 7 | 8 | if (s.length() != t.length()) { 9 | return false; 10 | } 11 | 12 | int[] map = new int[256]; 13 | for (int i = 0; i < s.length(); i++) { 14 | map[s.charAt(i) - 'a']++; 15 | map[t.charAt(i) - 'a']--; 16 | } 17 | 18 | for (int i = 0; i < 256; i++) { 19 | if (map[i] != 0) { 20 | return false; 21 | } 22 | } 23 | 24 | return true; 25 | } 26 | ``` 27 | 28 | >Time Complexity:O(n) -------------------------------------------------------------------------------- /String/count_and_say.md: -------------------------------------------------------------------------------- 1 | #Count and Say 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/count-and-say/) 4 | 5 | 題意: 6 | 7 | The count-and-say sequence is the sequence of integers beginning as follows: 8 | 9 | ```1, 11, 21, 1211, 111221, ...``` 10 | 11 | 1 is read off as "one 1" or 11. 12 | 13 | 11 is read off as "two 1s" or 21. 14 | 15 | 21 is read off as "one 2, then one 1" or 1211. 16 | 17 | Given an integer n, generate the nth sequence. 18 | 19 | 解題思路: 20 | 21 | 一開始題目看不太懂,其實就是第 i 個字串是把第 i-1 個字串數完個數並念出來, 22 | 23 | 如 i = 2 時,因seq[0] = "1",就是一個1,則 seq[1] = "11", 24 | 25 | 當 i = 3 時,因seq[1] = "11",就是兩個1,則 seq[2] = "21", 26 | 27 | 程式碼如下: 28 | 29 | 30 | ```java 31 | public String countAndSay(int n) { 32 | 33 | String prev = "1"; 34 | 35 | for (int i = 2; i <= n; i++) { 36 | StringBuilder cur = new StringBuilder(); 37 | int count = 1; 38 | for (int j = 1; j < prev.length(); j++) { 39 | if (prev.charAt(j - 1) == prev.charAt(j)) { 40 | count++; 41 | } else { 42 | cur.append(count).append(prev.charAt(j - 1)); 43 | count = 1; 44 | } 45 | } 46 | 47 | // 為了處理最後一位,加上若 prev的長度只有一位的話。 48 | cur.append(count).append(prev.charAt(prev.length() - 1)); 49 | prev = cur.toString(); 50 | } 51 | 52 | return prev; 53 | } 54 | ``` 55 | --- 56 | ###Reference 57 | 1. http://fisherlei.blogspot.com/2013/01/leetcode-count-and-say-solution.html 58 | 2. http://jane4532.blogspot.com/2013/10/count-and-sayleetcode.html -------------------------------------------------------------------------------- /String/excel_sheet_column_title.md: -------------------------------------------------------------------------------- 1 | # Excel Sheet Column TItle 2 | 3 | [Leetcode 1](https://leetcode.com/problems/excel-sheet-column-title/) 4 | 5 | [Leetcode 2](https://leetcode.com/problems/excel-sheet-column-number/) 6 | 7 | 題意: 8 | 9 | Given a positive integer, return its corresponding column title as appear in an Excel sheet. 10 | 11 | For example: 12 | ``` 13 | 1 -> A 14 | 2 -> B 15 | 3 -> C 16 | ... 17 | 26 -> Z 18 | 27 -> AA 19 | 28 -> AB 20 | ``` 21 | 22 | 解題思路: 23 | 24 | 數字轉字串 25 | 26 | ```java 27 | public class Solution { 28 | public String convertToTitle(int n) { 29 | StringBuilder sb = new StringBuilder(); 30 | while (n != 0) { 31 | int remainder = n % 26; 32 | n = n / 26; 33 | if (remainder == 0) { 34 | sb.append('Z'); 35 | n--; 36 | } else { 37 | char c = (char)(remainder - 1 + 'A'); 38 | sb.append(c); 39 | } 40 | } 41 | 42 | return sb.reverse().toString(); 43 | } 44 | } 45 | ``` 46 | 47 | 48 | 字串轉數字 49 | 50 | ```java 51 | public class Solution { 52 | public int titleToNumber(String s) { 53 | int sum = 0; 54 | if (s == null || s.length() == 0) { 55 | return 0; 56 | } 57 | int twentySix = 26; 58 | int pow = 0; 59 | for (int i = s.length() - 1; i >= 0; i--) { 60 | int cur = (int) (s.charAt(i) - 'A' + 1); 61 | sum += cur * Math.pow(twentySix, pow); 62 | pow++; 63 | } 64 | return sum; 65 | } 66 | } 67 | ``` -------------------------------------------------------------------------------- /String/group_anagrams.md: -------------------------------------------------------------------------------- 1 | # Group Anagrams 2 | 3 | [Leetcode](https://leetcode.com/problems/anagrams/) 4 | 5 | 題意: 6 | 7 | 8 | 解題思路: 9 | 10 | 使用hashmap,key為排序後的字串,value為所有擁有相同排序結果的字串們。 11 | 12 | 程式碼如下,時間複雜度為 $$(N*KlogK)$$: 13 | 14 | ```java 15 | public class Solution { 16 | public List> groupAnagrams(String[] strs) { 17 | HashMap> map = new HashMap>(); 18 | List> res = new ArrayList>(); 19 | Arrays.sort(strs); //很重要,因test case會比較這個順序 20 | 21 | if (strs == null || strs.length == 0) { 22 | return res; 23 | } 24 | 25 | // key則為每個字串排序後的值,value則為相同值的字串們 26 | for (int i = 0; i < strs.length; i++) { 27 | char[] charArray = strs[i].toCharArray(); 28 | Arrays.sort(charArray); // 把字串排序後轉為key 29 | String key = new String(charArray); 30 | 31 | if (map.containsKey(key)) { 32 | map.get(key).add(strs[i]); 33 | } else { 34 | map.put(key, new ArrayList()); 35 | map.get(key).add(strs[i]); 36 | } 37 | } 38 | 39 | // 把所有value都放進res即可 40 | for (List list : map.values()) { 41 | res.add(list); 42 | } 43 | 44 | return res; 45 | } 46 | } 47 | ``` -------------------------------------------------------------------------------- /String/implement_strstr.md: -------------------------------------------------------------------------------- 1 | # Implement strStr() 2 | 3 | [Leetcode](https://leetcode.com/problems/implement-strstr/) 4 | 5 | 題意: 6 | 7 | Implement strStr(). 8 | 9 | Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. 10 | 11 | 解題思路: 12 | 13 | brute force,注意,一但needle為空時,直接返回0而非-1。 14 | 15 | ```java 16 | public class Solution { 17 | public int strStr(String haystack, String needle) { 18 | if (haystack == null || needle == null) { 19 | return -1; 20 | } 21 | if (needle.length() == 0) { 22 | return 0; 23 | } 24 | 25 | int hLen = haystack.length(); 26 | int nLen = needle.length(); 27 | for (int i = 0; i < hLen - nLen + 1; i++) { 28 | int j; 29 | for (j = 0; j < nLen; j++) { 30 | if (haystack.charAt(i + j) != needle.charAt(j)) { 31 | break; 32 | } 33 | } 34 | if (j == nLen) { 35 | return i; 36 | } 37 | } 38 | return -1; 39 | } 40 | } 41 | ``` 42 | 43 | kmp 有機會要理解 -------------------------------------------------------------------------------- /String/isomorphic_strings.md: -------------------------------------------------------------------------------- 1 | # Isomorphic Strings 2 | 3 | [Leetcode](https://leetcode.com/problems/isomorphic-strings/) 4 | 5 | 題意: 6 | 7 | Given two strings s and t, determine if they are isomorphic. 8 | 9 | Two strings are isomorphic if the characters in s can be replaced to get t. 10 | 11 | All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character but a character may map to itself. 12 | 13 | For example, 14 | Given "egg", "add", return true. 15 | 16 | Given "foo", "bar", return false. 17 | 18 | Given "paper", "title", return true. 19 | 20 | 21 | 解題思路: 22 | 23 | 使用hashmap來幫助我們解決這道題,不斷的把s字元對應到相對應的t字元,一但發現不同時,即返回false,最後還需要檢查是否value的數目與key的數目相同。為了避免"ab"與"ab"的問題,其程式碼如下: 24 | 25 | ```java 26 | public class Solution { 27 | public boolean isIsomorphic(String s, String t) { 28 | HashMap map = new HashMap(); 29 | if (s == null || t == null || s.length() != t.length()) { 30 | return false; 31 | } 32 | 33 | for (int i = 0; i < s.length(); i++) { 34 | char cS = s.charAt(i); 35 | char cT = t.charAt(i); 36 | if (!map.containsKey(cS)) { 37 | map.put(cS, cT); 38 | } else { 39 | if (map.get(cS) != cT) { 40 | return false; 41 | } 42 | } 43 | } 44 | 45 | return map.values().size()== new HashSet<>(map.values()).size(); 46 | } 47 | } 48 | ``` 49 | --- 50 | ###Reference 51 | 1. https://leetcode.com/discuss/68132/simple-java-solution-clean-code -------------------------------------------------------------------------------- /String/length_of_last_word_i.md: -------------------------------------------------------------------------------- 1 | # Length of Last Word 2 | 3 | [Leetcode](https://leetcode.com/problems/length-of-last-word/) 4 | 5 | 6 | 題意: 7 | 8 | Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the length of last word in the string. 9 | 10 | If the last word does not exist, return 0. 11 | 12 | Note: A word is defined as a character sequence consists of non-space characters only. 13 | 14 | For example, 15 | 16 | Given s = "Hello World", 17 | 18 | return 5. 19 | 20 | 解題思路: 21 | 22 | 從後面往前找,找到第一個空格之後,即返回len,否則len++,字串裡沒空格也沒關係,他會遇到字串頭即跳出for loop,最後再返回len。 23 | 24 | ```java 25 | public class Solution { 26 | public int lengthOfLastWord(String s) { 27 | if (s == null || s.length() == 0) { 28 | return 0; 29 | } 30 | 31 | int len = 0; 32 | for (int i = s.length() - 1; i >= 0; i--) { 33 | if (s.charAt(i) != ' ') { 34 | len++; 35 | } 36 | 37 | if (s.charAt(i) == ' ' && len != 0) { 38 | return len; 39 | } 40 | } 41 | return len; 42 | } 43 | } 44 | ``` 45 | --- 46 | ###Reference 47 | 1. http://www.cnblogs.com/springfor/p/3872326.html -------------------------------------------------------------------------------- /String/longest_common_prefix.md: -------------------------------------------------------------------------------- 1 | #Longest Common Prefix 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/longest-common-prefix/) 4 | 5 | 題意:給予一個字串陣列,找出最長的共同 prefix。 6 | 7 | 解題思路:拿第一個字串的第 i 個字元與陣列中其他所有元素的第 i 個字元相比,若都相同,則進行第 i + 1 個字元的比對,若不同,則返回當前的最優解,為了避免耗費太多比對動作,與 out of bound 錯誤,我們必須找出最短的字串長度,其程式碼如下: 8 | 9 | ```java 10 | public String longestCommonPrefix(String[] strs) { 11 | 12 | if (strs == null || strs.length == 0) { 13 | return ""; 14 | } 15 | 16 | int shortestLength = Integer.MAX_VALUE; 17 | for (int i = 0; i < strs.length; i++) { 18 | if (strs[i].length() < shortestLength) { 19 | shortestLength = strs[i].length(); 20 | } 21 | } 22 | 23 | String res = ""; 24 | for (int i = 0; i < shortestLength; i++) { 25 | char c = strs[0].charAt(i); 26 | for (int j = 1; j < strs.length; j++) { 27 | if (c != strs[j].charAt(i)) { 28 | return res; 29 | } 30 | } 31 | 32 | res = strs[0].substring(0, i + 1); 33 | } 34 | 35 | return res; 36 | } 37 | ``` -------------------------------------------------------------------------------- /String/longest_substring_without_repeating_characters.md: -------------------------------------------------------------------------------- 1 | #Longest Substring Without Repeating Characters 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/longest-substring-without-repeating-characters/) 4 | 5 | 題意:給定一個字串,找出最長的子字串其中不含重複字元 6 | 7 | 解題思路:與 [Minimum Size Subarray Sum](array/minimum_size_subarray_sum.md)一樣使用兩根指針的模板。假設字符為 ASCII 編碼,因此利用一個256大小的陣列來紀錄當前字符的出現次數即可。 8 | 原本使用了 hashmap ,但是維護 hashmap 需要花大量的時間,會超時。 9 | 10 | ```java 11 | public int lengthOfLongestSubstring(String s) { 12 | if (s == null || s.length() == 0) { 13 | return 0; 14 | } 15 | 16 | int length = 0; 17 | int[] map = new int[256]; 18 | 19 | for (int i = 0, j = 0; i < s.length(); i++) { 20 | 21 | while (j < s.length() && map[s.charAt(j)] == 0) { 22 | map[s.charAt(j)] += 1; 23 | j++; 24 | } 25 | 26 | length = Math.max(length, j - i); 27 | 28 | map[s.charAt(i)] -= 1; 29 | } 30 | 31 | return length; 32 | } 33 | ``` 34 | 35 | >Time Complexity:$$O(N)$$ -------------------------------------------------------------------------------- /String/string_shift.md: -------------------------------------------------------------------------------- 1 | # String Shift 2 | 3 | input: String, key(int value), 4 | e.g. input: "aAa!", key = 3, return "dDd!" 5 | 6 | 7 | 8 | ```java 9 | public String shift(String s, int key) { 10 | String res = ""; 11 | for (int i = 0; i < s.length(); i++) { 12 | char c = s.charAt(i);. 13 | if (c >= 'a' && c <= 'z') { 14 | res = res + (char) ((c - 'a' + key) % 26 + 'a'); 15 | } else if (c >= 'A' && c <= 'Z') { 16 | res = res + (char) ((c - 'A' + key) % 26 + 'A'); 17 | } else { 18 | res = res + c; 19 | } 20 | } 21 | return res; 22 | } 23 | 24 | ``` -------------------------------------------------------------------------------- /String/strobogrammatic_number.md: -------------------------------------------------------------------------------- 1 | # Strobogrammatic Number 2 | 3 | [Leetcode](https://leetcode.com/problems/strobogrammatic-number/) 4 | 5 | 題意: 6 | 7 | A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down). 8 | 9 | Write a function to determine if a number is strobogrammatic. The number is represented as a string. 10 | 11 | For example, the numbers "69", "88", and "818" are all strobogrammatic. 12 | 13 | 解題思路: 14 | 15 | 用hashmap先建立對應關係,再用檢查palindrome的方式來一一檢查,程式碼如下: 16 | 17 | ```java 18 | public class Solution { 19 | public boolean isStrobogrammatic(String num) { 20 | HashMap map = new HashMap(); 21 | map.put('0', '0'); 22 | map.put('1', '1'); 23 | map.put('6', '9'); 24 | map.put('8', '8'); 25 | map.put('9', '6'); 26 | 27 | int start = 0; 28 | int end = num.length() - 1; 29 | while (start <= end) { 30 | char sChar = num.charAt(start); 31 | char eChar = num.charAt(end); 32 | if (!map.containsKey(sChar) || !map.containsKey(eChar) || map.get(sChar) != eChar) { 33 | return false; 34 | } 35 | start++; 36 | end--; 37 | } 38 | 39 | return true; 40 | } 41 | } 42 | ``` -------------------------------------------------------------------------------- /String/summary_ranges.md: -------------------------------------------------------------------------------- 1 | # Summary Ranges 2 | 3 | [Leetcode](https://leetcode.com/problems/summary-ranges/) 4 | 5 | 題意: 6 | 7 | Given a sorted integer array without duplicates, return the summary of its ranges. 8 | 9 | For example, given [0,1,2,4,5,7], return ["0->2","4->5","7"]. 10 | 11 | 12 | 解題思路: 13 | 14 | 使用兩根指針,一但遇到gap,則插入新的range,接著繼續往下一個開始搜尋,其程式碼如下: 15 | 16 | ```java 17 | public class Solution { 18 | public List summaryRanges(int[] nums) { 19 | List res = new ArrayList(); 20 | 21 | if (nums == null || nums.length == 0) { 22 | return res; 23 | } 24 | 25 | int s = 0; 26 | int e = 0; 27 | while (e < nums.length) { 28 | while (e + 1 < nums.length && nums[e] + 1 == nums[e + 1]) { 29 | e++; 30 | } 31 | 32 | if (s == e) { 33 | String str = Integer.toString(nums[e]); 34 | res.add(str); 35 | } else { 36 | String str = nums[s] + "->" + nums[e]; 37 | res.add(str); 38 | } 39 | e++; 40 | 41 | s = e; 42 | } 43 | 44 | return res; 45 | } 46 | } 47 | ``` 48 | 49 | --- 50 | ###Reference 51 | 1. http://blog.csdn.net/xudli/article/details/46645087 -------------------------------------------------------------------------------- /String/valid_anagram.md: -------------------------------------------------------------------------------- 1 | # Valid Anagram 2 | 3 | [Leetcode](https://leetcode.com/problems/valid-anagram/) 4 | 5 | 6 | 題意: 7 | 8 | Given two strings s and t, write a function to determine if t is an anagram of s. 9 | 10 | For example, 11 | s = "anagram", t = "nagaram", return true. 12 | s = "rat", t = "car", return false. 13 | 14 | **Note:** 15 | You may assume the string contains only lowercase alphabets. 16 | 17 | **Follow up:** 18 | What if the inputs contain unicode characters? How would you adapt your solution to such case? 19 | 20 | 解題思路: 21 | 22 | 如果是使用ascii編碼,則使用一個長度為256的陣列即可。 23 | 24 | ```java 25 | public class Solution { 26 | public boolean isAnagram(String s, String t) { 27 | if (s.length() != t.length()) { 28 | return false; 29 | } 30 | 31 | int[] count = new int[256]; 32 | for (int i = 0; i < s.length(); i++) { 33 | count[s.charAt(i) - 'a']++; 34 | count[t.charAt(i) - 'a']--; 35 | } 36 | 37 | for (int i = 0; i < 256; i++) { 38 | if (count[i] != 0) { 39 | return false; 40 | } 41 | } 42 | 43 | return true; 44 | } 45 | } 46 | ``` -------------------------------------------------------------------------------- /String/valid_palindrome.md: -------------------------------------------------------------------------------- 1 | # Valid Palindrome 2 | 3 | [Leetcode](https://leetcode.com/problems/valid-palindrome/) 4 | 5 | 題意: 6 | 7 | Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. 8 | 9 | For example, 10 | "A man, a plan, a canal: Panama" is a palindrome. 11 | "race a car" is not a palindrome. 12 | 13 | Note: 14 | Have you consider that the string might be empty? This is a good question to ask during an interview. 15 | 16 | For the purpose of this problem, we define empty string as valid palindrome. 17 | 18 | 19 | 解題思路: 20 | 21 | 只比較數字與字母,用兩根指針向中間夾擊,程式碼如下: 22 | 23 | ```java 24 | public class Solution { 25 | public boolean isPalindrome(String s) { 26 | if (s == null || s.length() < 2) { 27 | return true; 28 | } 29 | 30 | int left = 0; 31 | int right = s.length() - 1; 32 | while (left <= right) { 33 | while (left <= right && !Character.isLetter(s.charAt(left)) && !Character.isDigit(s.charAt(left))) { 34 | left++; 35 | } 36 | while (left <= right && !Character.isLetter(s.charAt(right)) && !Character.isDigit(s.charAt(right))) { 37 | right--; 38 | } 39 | if (left <= right) { 40 | char leftChar = Character.toLowerCase(s.charAt(left)); 41 | char rightChar = Character.toLowerCase(s.charAt(right)); 42 | if (leftChar != rightChar) { 43 | return false; 44 | } 45 | left++; 46 | right--; 47 | } 48 | 49 | } 50 | return true; 51 | } 52 | } 53 | ``` -------------------------------------------------------------------------------- /String/valid_parentheses.md: -------------------------------------------------------------------------------- 1 | # Valid Parentheses 2 | 3 | [Leetcode](https://leetcode.com/problems/valid-parentheses/) 4 | 5 | 6 | 題意: 7 | 8 | Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. 9 | 10 | The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not. 11 | 12 | Show Company Tags 13 | Show Tags 14 | Show Similar Problems 15 | 16 | 17 | 解題思路: 18 | 19 | 20 | 使用stack與hashmap來輔助我們作這道題,最後得檢查stack是否為空。 21 | 22 | 23 | ```java 24 | public class Solution { 25 | public boolean isValid(String s) { 26 | HashMap map = new HashMap(); 27 | map.put('(',')'); 28 | map.put('{','}'); 29 | map.put('[',']'); 30 | 31 | Stack st = new Stack(); 32 | for (int i = 0; i < s.length(); i++) { 33 | char cur = s.charAt(i); 34 | if (map.containsKey(cur)) { 35 | st.push(cur); 36 | } else { 37 | if (st.empty() || map.get(st.pop()) != cur) { 38 | return false; 39 | } 40 | } 41 | } 42 | 43 | return st.empty(); 44 | } 45 | } 46 | ``` -------------------------------------------------------------------------------- /String/word_pattern.md: -------------------------------------------------------------------------------- 1 | # Word Pattern 2 | 3 | [Leetcode](https://leetcode.com/problems/word-pattern/) 4 | 5 | 6 | ```java 7 | public class Solution { 8 | public boolean wordPattern(String pattern, String str) { 9 | if (str == null || str.length() == 0 || pattern == null || pattern.length() == 0) { 10 | return false; 11 | } 12 | 13 | HashMap map = new HashMap(); 14 | HashSet set = new HashSet(); 15 | String[] strs = str.split("\\s"); 16 | if (pattern.length() != strs.length) { 17 | return false; 18 | } 19 | 20 | for (int i = 0; i < pattern.length(); i++) { 21 | char c = pattern.charAt(i); 22 | if (!map.containsKey(c)) { 23 | if(map.containsValue(strs[i])) { 24 | return false; 25 | } 26 | map.put(c, strs[i]); 27 | set.add(strs[i]); 28 | } else { 29 | if (!map.get(c).equals(strs[i])) { 30 | return false; 31 | } 32 | } 33 | } 34 | return true; 35 | } 36 | } 37 | ``` -------------------------------------------------------------------------------- /String/zigzag_conversion.md: -------------------------------------------------------------------------------- 1 | #ZigZag Conversion 2 | 3 | [原題網址](https://leetcode.com/problems/zigzag-conversion/) 4 | 5 | 題意: 6 | 7 | The string **"PAYPALISHIRING"** is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility) 8 | 9 | ```plain 10 | P A H N 11 | A P L S I I G 12 | Y I R 13 | ``` 14 | 15 | And then read line by line: **"PAHNAPLSIIGYIR"** 16 | Write the code that will take a string and make this conversion given a number of rows: 17 | 18 | **convert("PAYPALISHIRING", 3)** should return **"PAHNAPLSIIGYIR"**. 19 | 20 | 解題思路: 21 | 22 | 把字轉換成index來看就快多了,假設 n = 3 23 | 24 | ``` plain 25 | P A 26 | A P L 27 | Y I 28 | ``` 29 | ``` 30 | 0 4 31 | 1 3 5 32 | 2 6 33 | ``` 34 | 以列來看(先不看斜的),則每一列的前後兩個值的index便差了 2*n - 2,而斜的值便是 j + n - 2 * i,j 代表 column ,i 代表 row 。 35 | 36 | 原始碼如下: 37 | 38 | ```java 39 | public String convert(String s, int numRows) { 40 | 41 | if (numRows <= 1) { 42 | return s; 43 | } 44 | 45 | StringBuilder str = new StringBuilder(); 46 | int size = numRows * 2 - 2; 47 | 48 | for (int i = 0; i < numRows; i++) { 49 | for (int j = i; j < s.length(); j += size) { 50 | str.append(s.charAt(j)); 51 | if (i > 0 && i < numRows - 1) { 52 | // 重點怎麼處理斜的部份 53 | int temp = j + size - 2 * i; 54 | if (temp < s.length()) { 55 | str.append(s.charAt(temp)); 56 | } 57 | } 58 | } 59 | } 60 | 61 | return str.toString(); 62 | } 63 | ``` 64 | --- 65 | ###Reference 66 | 1. http://www.cnblogs.com/springfor/p/3893499.html#3209156 -------------------------------------------------------------------------------- /array.md: -------------------------------------------------------------------------------- 1 | # Array 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /array/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/array/.DS_Store -------------------------------------------------------------------------------- /array/3sum_smaller.md: -------------------------------------------------------------------------------- 1 | # 3Sum Smaller 2 | 3 | [Leetcode](https://leetcode.com/problems/3sum-smaller/) 4 | 5 | 題意: 6 | 7 | Given an array of n integers nums and a target, find the number of index triplets i, j, k with 0 <= i < j < k < n that satisfy the condition nums[i] + nums[j] + nums[k] < target. 8 | 9 | For example, given ```nums = [-2, 0, 1, 3]```, and target = 2. 10 | 11 | Return 2. Because there are two triplets which sums are less than 2: 12 | ``` 13 | [-2, 0, 1] 14 | [-2, 0, 3] 15 | ``` 16 | Follow up: 17 | Could you solve it in O(n2) runtime? 18 | 19 | 20 | 解題思路: 21 | 22 | 此題題意沒說清楚,重複的解答也要算在進去。 23 | 24 | 暴力法就花O(N^3)全部比對一遍 25 | 26 | O(N^2)法就是先把陣列排序後,用3sum的方法來算,特別的地方如下 27 | 28 | >如果sum >= target 則 j-- 29 | 30 | >如果sum < target 那麼 j - i 都是解 31 | 32 | 程式碼如下: 33 | 34 | ```java 35 | public class Solution { 36 | 37 | public int threeSumSmaller(int[] nums, int target) { 38 | if (nums == null || nums.length < 3) { 39 | return 0; 40 | } 41 | 42 | Arrays.sort(nums); 43 | int count = 0; 44 | for (int i = 0; i < nums.length - 2; i++) { 45 | int left = i + 1; 46 | int right = nums.length - 1; 47 | while (left < right) { 48 | int sum = nums[i] + nums[left] + nums[right]; 49 | // 重點在此,一旦sum小於target,則nums[right]搭配nums[left~(right-1)]這些都是解 50 | if (sum < target) { 51 | count += right - left; 52 | left++; 53 | } else if (sum >= target) { 54 | right--; 55 | } 56 | } 57 | } 58 | 59 | return count; 60 | } 61 | } 62 | ``` 63 | 64 | --- 65 | ###Reference 66 | 1. http://meetqun.com/thread-10672-1-1.html 67 | 68 | -------------------------------------------------------------------------------- /array/bitwise_and_of_numbers_range.md: -------------------------------------------------------------------------------- 1 | #Bitwise AND of Numbers Range 2 | 3 | [Leetcode](https://leetcode.com/problems/bitwise-and-of-numbers-range/) 4 | 5 | 題意: 6 | 7 | Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive. 8 | 9 | For example, given the range [5, 7], you should return 4. 10 | 11 | 解題思路: 12 | 13 | 網友 [grandyang](http://www.cnblogs.com/grandyang/p/4431646.html) 提供以下兩種思路: 14 | 15 | [5, 7]裡共有三個數字,分別寫出它們的二進製為: 16 | 17 | 101  110  111 18 | 19 | 相與後的結果為100,仔細觀察我們可以得出,最後的數是該數字範圍內所有的數的左邊共同的部分,如果上面那個例子不太明顯,我們再來看一個範圍[26, 30],它們的二進制如下: 20 | 21 | 11010  11011  11100  11101  11110 22 | 23 | 發現了規律後,我們只要寫程式碼找到左邊公共的部分即可,我們可以從建立一個32位都是1的mask,然後每次向左移一位,比較m和n是否相同,不同再繼續左移一位,直至相同,然後把m和mask相與就是最終結果,程式碼如下: 24 | 25 | ```java 26 | public class Solution { 27 | public int rangeBitwiseAnd(int m, int n) { 28 | int mask = Integer.MAX_VALUE; 29 | while ((m & mask) != (n & mask)) { 30 | mask <<= 1; 31 | } 32 | 33 | return (mask == 0) ? 0 : m & mask; 34 | } 35 | } 36 | ``` 37 | 38 | 此題還有另一種解法,不需要用mask,直接平移m和n,每次向右移一位,直到m和n相等,記錄下所有平移的次數i,然後再把m左移i位即為最終結果,程式碼如下: 39 | 40 | ```java 41 | public class Solution { 42 | public int rangeBitwiseAnd(int m, int n) { 43 | int count = 0; 44 | while (m != n) { 45 | count++; 46 | m >>= 1; 47 | n >>= 1; 48 | } 49 | return m < set = new HashSet(); 20 | for (int i = 0; i < nums.length; i++) { 21 | if (set.contains(nums[i])) { 22 | return true; 23 | } 24 | set.add(nums[i]); 25 | } 26 | return false; 27 | } 28 | } 29 | ``` -------------------------------------------------------------------------------- /array/contains_duplicate_iii.md: -------------------------------------------------------------------------------- 1 | # Contains Duplicate III 2 | 3 | []() 4 | 5 | 題意: 6 | 7 | Given an array of integers, find out whether there are two distinct indices i and j in the array such that the difference between nums[i] and nums[j] is at most t and the difference between i and j is at most k. 8 | 9 | 10 | 解題思路: 11 | 12 | >The ```ceilingKey(K key)``` method is used to return the least key greater than or equal to the given key, or null if there is no such key. 13 | 14 | 由[網友](https://codesolutiony.wordpress.com/2015/06/01/leetcode-contains-duplicate-iii/) 提供以下思路: 15 | 16 | > 用BST來維護前k個數,因此對於每個數,刪除第i-k-1個數是lgn,得到ceiling和lower key分別是lgn,最後將當前數加入BST是lgn。 17 | 18 | ```java 19 | public class Solution { 20 | public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { 21 | if (nums == null) { 22 | return false; 23 | } 24 | 25 | TreeMap map = new TreeMap(); 26 | 27 | for (int i = 0; i < nums.length; i++) { 28 | if (i > k) { 29 | map.remove((long)nums[i - k - 1]); 30 | } 31 | long val = (long)nums[i]; 32 | Long greater = map.ceilingKey(val); 33 | if (greater != null && greater - val <= t) { 34 | return true; 35 | } 36 | Long smaller = map.lowerKey(val); 37 | if (smaller != null && val - smaller <= t) { 38 | return true; 39 | } 40 | map.put(val, i); 41 | } 42 | return false; 43 | } 44 | } 45 | ``` 46 | 47 | --- 48 | ###Reference 49 | 1. https://codesolutiony.wordpress.com/2015/06/01/leetcode-contains-duplicate-iii/ -------------------------------------------------------------------------------- /array/contains_duplicates_ii.md: -------------------------------------------------------------------------------- 1 | # Contains Duplicates II 2 | 3 | [Leetcode](https://leetcode.com/problems/contains-duplicate-ii/) 4 | 5 | 6 | 題意: 7 | 8 | Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that **nums[i] = nums[j]** and the difference between i and j is at most k. 9 | 10 | 解題思路: 11 | 12 | 一樣用set,一但i大於k時,每加一個前要先刪掉一個set中最前面的元素。 13 | 14 | ```java 15 | public class Solution { 16 | public boolean containsNearbyDuplicate(int[] nums, int k) { 17 | if (nums == null || nums.length == 0 || k == 0) { 18 | return false; 19 | } 20 | 21 | HashSet set = new HashSet(); 22 | for (int i = 0; i < nums.length; i++) { 23 | if ( i > k) { 24 | set.remove(nums[i - k - 1]); 25 | } 26 | if (!set.add(nums[i])) { 27 | return true; 28 | } 29 | } 30 | 31 | return false; 32 | } 33 | } 34 | ``` -------------------------------------------------------------------------------- /array/find_all_numbers_in_a_given_array_that_occur_odd_n.md: -------------------------------------------------------------------------------- 1 | # Find all numbers in a given array that occur odd number of times 2 | 3 | ```java 4 | public List find(List nums) { 5 | List result = new ArrayList<>(); 6 | if (nums == null) { 7 | return result; 8 | } 9 | 10 | Collections.sort(nums); 11 | int length = nums.size(); 12 | 13 | for (int i = 0; i < length; i++) { 14 | int count = 1; 15 | int val = nums.get(i); 16 | while (i + 1 < length && nums.get(i) == nums.get(i + 1)) { 17 | i++; 18 | count++; 19 | } 20 | if (count % 2 == 1) { 21 | result.add(val); 22 | } 23 | } 24 | 25 | return result; 26 | } 27 | ``` -------------------------------------------------------------------------------- /array/find_minimum_in_rotated_sorted_array.md: -------------------------------------------------------------------------------- 1 | # Find Minimum in Rotated Sorted Array 2 | 3 | [Lintcode](http://www.lintcode.com/en/problem/find-minimum-in-rotated-sorted-array/) 4 | 5 | 題意: 6 | 7 | Medium Find Minimum in Rotated Sorted Array Show result 8 | 9 | 10 | Suppose a sorted array is rotated at some pivot unknown to you beforehand. 11 | 12 | (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). 13 | 14 | Find the minimum element. 15 | 16 | 17 | Given [4, 5, 6, 7, 0, 1, 2] return 0 18 | 19 | Note 20 | You may assume no duplicate exists in the array. 21 | 22 | 解題思路: 23 | 24 | 因陣列會旋轉,我們需要固定一點 target(在此選陣列中最後一個元素)不斷的拿中間元素與該點比較,會有以下兩個狀況: 25 | 26 | 1. 若 num[mid] <= target,則 mid在右下,最小值可能在左半邊,移動 end 來繼續找左半邊 27 | 2. 若 num[mid] > target,則 mid 在左上,最小值可能在右半邊,移動 start來繼續找右半邊 28 | 29 | ```java 30 | public int findMin(int[] nums) { 31 | // write your code here 32 | if (nums.length == 0) { 33 | return 0; 34 | } 35 | int start = 0; 36 | int end = nums.length - 1; 37 | int mid; 38 | while (start + 1 < end) { 39 | mid = start + (end - start) / 2; 40 | //拿end與mid比 41 | //若mid比end小,代表最小在左半邊,移動end 42 | //若mid比end大,代表最小在右半邊,移動start 43 | if (nums[mid] < nums[end]) { 44 | end = mid; 45 | } else { 46 | start = mid; 47 | } 48 | } 49 | //最後剩兩個數,直接比較 50 | if (nums[start] < nums[end]) { 51 | return nums[start]; 52 | } else { 53 | return nums[end]; 54 | } 55 | } 56 | ``` 57 | 58 | --- 59 | ###Reference 60 | 1. http://www.jiuzhang.com/solutions/find-minimum-in-rotated-sorted-array/ 61 | -------------------------------------------------------------------------------- /array/find_minimum_in_rotated_sorted_array_ii.md: -------------------------------------------------------------------------------- 1 | # Find Minimum in Rotated Sorted Array II 2 | 3 | [Leetcode](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii/) 4 | 5 | 題意: 6 | 7 | >Follow up for "Find Minimum in Rotated Sorted Array": 8 | What if duplicates are allowed? 9 | 10 | >Would this affect the run-time complexity? How and why? 11 | Suppose a sorted array is rotated at some pivot unknown to you beforehand. 12 | 13 | (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). 14 | 15 | Find the minimum element. 16 | 17 | The array may contain duplicates. 18 | 19 | 20 | 解題思路: 21 | 22 | 23 | ```java 24 | public class Solution { 25 | public int findMin(int[] nums) { 26 | int left = 0; 27 | int right = nums.length - 1; 28 | 29 | while (left + 1 < right) { 30 | int mid = left + (right - left) / 2; 31 | 32 | if (nums[mid] < nums[right]) { 33 | right = mid; 34 | } else if (nums[mid] > nums[right]) { 35 | left = mid; 36 | } else { 37 | right--; 38 | } 39 | } 40 | 41 | return Math.min(nums[left], nums[right]); 42 | } 43 | } 44 | ``` -------------------------------------------------------------------------------- /array/find_peak_element.md: -------------------------------------------------------------------------------- 1 | # Find Peak Element 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/find-peak-element/) 4 | 5 | ```java 6 | public int findPeak(int[] A) { 7 | // write your code here 8 | 9 | int start = 1; 10 | int end = A.length - 2; 11 | int mid; 12 | // 用start + 1是代表start 與end中間至少要有一個mid 13 | while (start + 1 < end) { 14 | mid = start + (end - start) / 2; 15 | //拿mid與兩邊比小,若mid比左邊小,代表左邊有峰值 16 | //若mid比右邊小,代表右邊有峰值 17 | //若else,代表mid比左邊大,且比右邊大,則mid本身可能是峰值。 18 | if (A[mid] < A[mid - 1]) { 19 | end = mid; 20 | } else if (A[mid] < A[mid + 1]) { 21 | start = mid; 22 | } else { 23 | end = mid; 24 | } 25 | } 26 | //最後要double check一下誰是peak 27 | if (A[start] > A[end]) { 28 | return start; 29 | } else { 30 | return end; 31 | } 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /array/find_second_largest_number.md: -------------------------------------------------------------------------------- 1 | # Find Second Largest Number 2 | 3 | []() 4 | 5 | 6 | 題意: 7 | 8 | 在未排序的陣列中,找出第二大的數 9 | 10 | 解題思路: 11 | 12 | ```java 13 | class Solution{ 14 | public int findSecondLargest(int[] nums) { 15 | if (nums == null || nums.length < 2) { 16 | return -1; 17 | } 18 | 19 | int first = Integer.MIN_VALUE; 20 | int second = Integer.MIN_VALUE; 21 | 22 | for (int i = 0; i < nums.length; i++) { 23 | if (nums[i] > first) { 24 | second = first; 25 | first = nums[i]; 26 | } else if (nums[i] > second) { 27 | second = nums[i]; 28 | } 29 | } 30 | 31 | return second; 32 | } 33 | } 34 | ``` -------------------------------------------------------------------------------- /array/find_top_k_elements_in_array.md: -------------------------------------------------------------------------------- 1 | # Find Top K Elements in Array 2 | 3 | []() 4 | 5 | 題意: 6 | 7 | 8 | 解題思路: 9 | 10 | 使用min heap。 11 | 12 | ```java 13 | class Solution { 14 | public List findTopKElement(int[] nums, int k) { 15 | if (nums == null || nums.length < k || k == 0) { 16 | return -1; 17 | } 18 | 19 | PriorityQueue q = new PriorityQueue(); 20 | for (int i = 0; i < nums.length, i++) { 21 | if (i > k && nums[i] > q.peek()) { 22 | q.poll(); 23 | } 24 | q.offer(nums[i]); 25 | } 26 | 27 | List res = new ArrayList<>(); 28 | for (int i = 0; i < k; i++) { 29 | res.add(q.poll()); 30 | } 31 | 32 | return res; 33 | } 34 | } 35 | ``` -------------------------------------------------------------------------------- /array/first_bad_version.md: -------------------------------------------------------------------------------- 1 | # First Bad Version 2 | [原題網址](http://www.lintcode.com/en/problem/first-bad-version/) 3 | 4 | >解法:其實這題就是二分搜尋的變形 5 | 6 | ```java 7 | public int findFirstBadVersion(int n) { 8 | if ( n == 1 ) { 9 | if (VersionControl.isBadVersion(1)) 10 | return 1; 11 | else 12 | return 0; 13 | } 14 | 15 | int start = 1; 16 | int end = n; 17 | int mid; 18 | boolean midIsBad; 19 | while (start + 1 < end) { 20 | mid = start + (end - start) / 2; 21 | midIsBad = VersionControl.isBadVersion(mid); 22 | //若mid是bad,則第一個bad在前半段 23 | //否則bad會發生在後半段 24 | if (midIsBad) { 25 | end = mid; 26 | } else { 27 | start = mid; 28 | } 29 | } 30 | if (VersionControl.isBadVersion(start)) { 31 | return start; 32 | } 33 | if (VersionControl.isBadVersion(end)) { 34 | return end; 35 | } 36 | return 0; 37 | } 38 | 39 | ``` 40 | -------------------------------------------------------------------------------- /array/h-index.md: -------------------------------------------------------------------------------- 1 | #H-Index 2 | 3 | [原題網址](https://leetcode.com/problems/h-index/) 4 | 5 | 題意: 6 | A scientist has index h if h of his/her N papers have at least h citations each, and the other N − h papers have no more than h citations each. 7 | 8 | 解題思路: 9 | 10 | 1. 將其發表的所有SCI論文按被引次數從高到低排序; 11 | 2. 從前往後查找排序後的列表,直到某篇論文的序號大於該論文被引次數 12 | 3. 所得序號減一即為H指數。 13 | 14 | ```java 15 | public int hIndex(int[] citations) { 16 | 17 | if (citations == null || citations.length == 0) { 18 | return 0; 19 | } 20 | 21 | int len = citations.length; 22 | Arrays.sort(citations); 23 | for (int i = 0; i < len; i++) { 24 | if (citations[i] >= len - i) { 25 | return len - i; 26 | } 27 | } 28 | return 0; 29 | } 30 | ``` -------------------------------------------------------------------------------- /array/h-index_ii.md: -------------------------------------------------------------------------------- 1 | # H-Index II 2 | 3 | [Leetcode](https://leetcode.com/problems/h-index-ii/) 4 | 5 | 6 | 題意: 7 | 8 | Follow up for H-Index: What if the citations array is sorted in ascending order? Could you optimize your algorithm? 9 | 10 | **Hint:** 11 | 12 | Expected runtime complexity is in O(log n) and the input is sorted. 13 | 14 | 15 | 解題思路: 16 | 17 | 使用二分搜尋法,程式碼如下: 18 | 19 | ```java 20 | public class Solution { 21 | public int hIndex(int[] citations) { 22 | if (citations == null || citations.length == 0) { 23 | return 0; 24 | } 25 | 26 | int len = citations.length; 27 | int start = 0; 28 | int end = citations.length - 1; 29 | while (start <= end) { 30 | int mid = start + (end - start) / 2; 31 | if (citations[mid] >= len - mid) { 32 | end = mid - 1; 33 | } else { 34 | start = mid + 1; 35 | } 36 | } 37 | 38 | return len - start; 39 | } 40 | } 41 | ``` 42 | --- 43 | ###Reference 44 | 1. https://leetcode.com/discuss/56279/concise-standard-binary-search-solution-detailed-explanation -------------------------------------------------------------------------------- /array/longest_continuous_increasing_subsequence.md: -------------------------------------------------------------------------------- 1 | #Longest Continuous Increasing Subsequence 2 | 3 | [原題連結](http://www.lintcode.com/en/problem/longest-increasing-continuous-subsequence/) 4 | 5 | **題意**:找出一個最長連續遞增/減的子序列。 6 | 7 | Example 8 | 9 | For ```[5, 4, 2, 1, 3]```, the LICS is ```[5, 4, 2, 1]```, return 4. 10 | 11 | For ```[5, 1, 2, 3, 4]```, the LICS is ```[1, 2, 3, 4]```, return 4. 12 | 13 | **解題思路**:可以使用二維陣列與動態規劃來作,但是時間與空間各需花 $$O(N^{2})$$ ,我們使用掃法,由左掃到右,利用 count 來紀錄當前的最長連續子陣列的長度,只要遇到遞增即更新 count ,否則重設 count 由於遞增與遞減都算,所以掃了兩次。 14 | 15 | ```java 16 | public int longestIncreasingContinuousSubsequence(int[] A) { 17 | 18 | if (A == null || A.length == 0) { 19 | return 0; 20 | } 21 | 22 | int count = 0; 23 | 24 | for(int i = 0, j = 0; i < A.length;) { 25 | int temp = 1; 26 | while (j < A.length - 1 && A[j + 1] >= A[j]) { 27 | temp++; 28 | j++; 29 | } 30 | count = temp > count ? temp : count; 31 | j = j + 1; 32 | i = j; 33 | } 34 | } 35 | ``` 36 | 37 | >Time Complexity:$$O(2N) = O(N)$$ ,因為掃了兩次。 38 | 39 | >Space Complexity: $$O(1)$$,因只用了幾個變數來紀錄當前的狀況。 -------------------------------------------------------------------------------- /array/majority_number.md: -------------------------------------------------------------------------------- 1 | # Majority Number 2 | 3 | [Leetcode](https://leetcode.com/problems/majority-element/) 4 | 5 | 題意: 6 | 7 | Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times. 8 | 9 | You may assume that the array is non-empty and the majority element always exist in the array. 10 | 11 | 12 | 解題思路: 13 | 14 | ```java 15 | public class Solution { 16 | public int majorityElement(int[] nums) { 17 | if (nums == null || nums.length == 0) { 18 | return 0; 19 | } 20 | 21 | int count = 1; 22 | int candidate = nums[0]; 23 | 24 | for (int i = 1; i < nums.length; i++) { 25 | if (nums[i] == candidate) { 26 | count++; 27 | } else { 28 | count--; 29 | if (count == 0) { 30 | candidate = nums[i]; 31 | count = 1; 32 | } 33 | } 34 | } 35 | 36 | return candidate; 37 | } 38 | } 39 | ``` -------------------------------------------------------------------------------- /array/majority_number_ii.md: -------------------------------------------------------------------------------- 1 | #Majority Number II 2 | 3 | [原題連結](http://www.lintcode.com/en/problem/majority-number-ii/) 4 | 5 | 題意:其中有一個元素出現次數大於1/3,找出該元素。 6 | 7 | 解題思路: 8 | 9 | ```java 10 | public int majorityNumber(ArrayList nums) { 11 | if (nums == null || nums.size() == 0) { 12 | return 0; 13 | } 14 | // 分別使用四個變數,來紀錄當前的兩個候選人是誰以及當下的count為多少 15 | int candidate1 = 0; 16 | int candidate2 = 0; 17 | int count1 = 0; 18 | int count2 = 0; 19 | 20 | for (int i = 0; i < nums.size(); i++) { 21 | if (nums.get(i) == candidate1) { 22 | count1++; 23 | } else if (nums.get(i) == candidate2) { 24 | count2--; 25 | } else if (count1 == 0) { 26 | candidate1 = nums.get(i); 27 | count1 = 1; 28 | } else if (count2 == 0) { 29 | candidate2 = nums.get(i); 30 | count2 = 1; 31 | } else { 32 | count1--; 33 | count2--; 34 | } 35 | } 36 | 37 | // 再go through一次來確認 38 | count1 = 0; 39 | count2 = 0; 40 | for (int i = 0; i < nums.size(); i++) { 41 | if (nums.get(i) == candidate1) { 42 | count1++; 43 | } else if (nums.get(i) == candidate2) { 44 | count2++; 45 | } 46 | } 47 | 48 | return count1 > count2 ? candidate1 : candidate2; 49 | } 50 | ``` -------------------------------------------------------------------------------- /array/maximum_product_subarray.md: -------------------------------------------------------------------------------- 1 | #Maximum Product Subarray 2 | 3 | [原題連結](http://www.lintcode.com/en/problem/maximum-product-subarray/) 4 | 5 | 題意:給一個陣列,找出一個子陣列其乘積為最大。 6 | 7 | 解題思路:也是與 [Maximum Subarray](array/maximum_subarray.md),類似不斷的維護全局的最大值,與 local 的最大與最小值,來求得最終結果。但這裡需要特別注意的地方是,原本很小的負數,可能因為乘了另一個負數,變成一個很大的正數,因此也要紀錄local min的部份,程式碼如下: 8 | 9 | ```java 10 | public int maxProduct(int[] nums) { 11 | 12 | if (nums == null || nums.length == 0) { 13 | return 1; 14 | } 15 | 16 | int global = nums[0]; 17 | int localMax = nums[0]; 18 | int localMin = nums[0]; 19 | for (int i = 1; i < nums.length; i++) { 20 | 21 | // localMax會被改變,因此得先存下來。 22 | int localMaxCopy = localMax; 23 | 24 | // 作比較時,也需與當前陣列元素作比較,來決定是否放棄前面的乘積 25 | localMax = Math.max(Math.max(localMax * nums[i], localMin * nums[i]), nums[i]); 26 | localMin = Math.min(Math.min(localMin *nums[i], localMaxCopy * nums[i]), nums[i]); 27 | global = Math.max(global, localMax); 28 | } 29 | 30 | return global; 31 | } 32 | ``` 33 | 34 | >Time Complexity: $$O(N)$$,因只需遍歷陣列一次。 35 | 36 | --- 37 | ###Reference 38 | 1. http://blog.csdn.net/linhuanmars/article/details/21314059 -------------------------------------------------------------------------------- /array/maximum_size_subarray_sum_equals_k.md: -------------------------------------------------------------------------------- 1 | # Maximum Size Subarray Sum Equals k 2 | 3 | [Leetcode](https://leetcode.com/problems/maximum-size-subarray-sum-equals-k/) 4 | 5 | 題意: 6 | 7 | Given an array nums and a target value k, find the maximum length of a subarray that sums to k. If there isn't one, return 0 instead. 8 | 9 | Example 1: 10 | Given nums = [1, -1, 5, -2, 3], k = 3, 11 | return 4. (because the subarray [1, -1, 5, -2] sums to 3 and is the longest) 12 | 13 | Example 2: 14 | Given nums = [-2, -1, 2, 1], k = 1, 15 | return 2. (because the subarray [-1, 2] sums to 1 and is the longest) 16 | 17 | Follow Up: 18 | Can you do it in O(n) time? 19 | 20 | 解題思路: 21 | 22 | 通常不能排序加上需要O(N)的話,需要額外的空間來幫助我們簡化。 23 | 24 | 我們使用一個hash map,key為nums[0] - nums[i] 的總和,i 為最一開始的i,一但map裡面有key的話,就不要再變動了。 25 | 26 | 程式碼如下: 27 | 28 | ```java 29 | public class Solution { 30 | public int maxSubArrayLen(int[] nums, int k) { 31 | if (nums == null || nums.length == 0) { 32 | return 0; 33 | } 34 | 35 | Map map = new HashMap<>(); 36 | int maxLength = 0; 37 | int sum = 0; 38 | for (int i = 0; i < nums.length; i++) { 39 | sum += nums[i]; 40 | if (sum == k) { 41 | maxLength = i + 1; 42 | } else if (map.containsKey(sum - k)) { 43 | maxLength = Math.max(maxLength, i - map.get(sum - k)); 44 | } 45 | if (!map.containsKey(sum)) { 46 | map.put(sum, i); 47 | } 48 | } 49 | 50 | return maxLength; 51 | } 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /array/maximum_subarray.md: -------------------------------------------------------------------------------- 1 | #Maximum Subarray 2 | 3 | []() 4 | 5 | 題意:給予一陣列,找出子陣列之和為最大 6 | 7 | 解題思路:此為 [Minimum Subarray](array/minimum_subarray.md) 的變形,使用相同方式即可。另有 Prefix Sum 方式也能解此題。 8 | 9 | ```java 10 | public int maxSubArray(ArrayList nums) { 11 | if (nums == null || nums.size() == 0) { 12 | return 0; 13 | } 14 | 15 | //解法:先把第一個數加入current與設為max 16 | // 接著就一直不斷的先判斷current再決定丟棄前面的結果 17 | // 或是原本結果加上新的數 18 | int max = nums.get(0); 19 | int current = nums.get(0); 20 | for (int i = 1; i < nums.size(); i++) { 21 | if (current < 0) { 22 | current = nums.get(i); 23 | } else { 24 | current += nums.get(i); 25 | } 26 | max = (current > max) ? current : max; 27 | } 28 | return max; 29 | } 30 | ``` 31 | 32 | >Time Complexity:$$O(N)$$ 33 | 34 | --- 35 | ###Prefix Sum 解法 36 | 37 | 解題思路: 38 | 利用一個 ```sum``` 陣列,```sum[i]``` 代表```nums[0] + ... + nums[i]```的和,若要求```sum[i..j]```的話,直接求 ```sum[j] - sum[i - 1]```即可。空間複雜度為$$O(N)$$,下面程式解法只利用一個```sum```與```minSum```變數來記錄當前的最小下限為多少,利用```minSum```來當作```sum[i-1]```,```sum```即為```sum[j]```。 39 | 40 | ```java 41 | public int maxSubArray(int[] A) { 42 | if (A == null || A.length == 0){ 43 | return 0; 44 | } 45 | 46 | int max = Integer.MIN_VALUE, sum = 0, minSum = 0; 47 | for (int i = 0; i < A.length; i++) { 48 | sum += A[i]; 49 | max = Math.max(max, sum - minSum); 50 | minSum = Math.min(minSum, sum); 51 | } 52 | 53 | return max; 54 | } 55 | ``` 56 | >Time Complexity:$$O(N)$$ -------------------------------------------------------------------------------- /array/median_of_two_sorted_arrays.md: -------------------------------------------------------------------------------- 1 | # Median of Two Sorted Arrays 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/median-of-two-sorted-arrays/) 4 | 5 | ```java 6 | class Solution { 7 | 8 | public double findMedianSortedArrays(int[] A, int[] B) { 9 | int len = A.length + B.length; 10 | if (len % 2 == 1) { 11 | return helper(A, 0, B, 0, len / 2 + 1); 12 | } else { 13 | return (helper(A, 0, B, 0, len / 2) + helper(A, 0, B, 0, len / 2 + 1)) / 2.0; 14 | } 15 | } 16 | 17 | public int helper(int[] A, int startA, int[] B, int startB, int k) { 18 | // 因A已拿不出任何東西,直接往B取 19 | if (startA >= A.length) { 20 | return B[startB + k - 1]; 21 | } 22 | if (startB >= B.length) { 23 | return A[startA + k - 1]; 24 | } 25 | // 只差一步就到k了,因此取較小的值即可 26 | if (k == 1) { 27 | return Integer.min(A[startA], B[startB]); 28 | } 29 | 30 | // 拿出目前index往後算第k/2的數來比較,取max value是為了不影響後面call function的問題,就是讓它必輸就是了。 31 | // -1 則是因為取值,index由0開始算。 32 | int keyA = startA + k / 2 - 1 < A.length ? A[startA + k / 2 - 1] : Integer.MAX_VALUE; 33 | int keyB = startB + k / 2 - 1 < B.length ? B[startB + k / 2 - 1] : Integer.MAX_VALUE; 34 | 35 | if (keyA < keyB) { 36 | return helper(A, startA + k / 2, B, startB, k - k / 2); 37 | } else { 38 | return helper(A, startA, B, startB + k / 2, k - k / 2); 39 | } 40 | } 41 | } 42 | ``` 43 | -------------------------------------------------------------------------------- /array/merge_sorted_array.md: -------------------------------------------------------------------------------- 1 | # Merge Sorted Array I 2 | [原題網址](http://www.lintcode.com/en/problem/merge-sorted-array/) 3 | 4 | ```java 5 | public void mergeSortedArray(int[] A, int m, int[] B, int n) { 6 | // 從後面倒過來作 7 | int posA = m - 1; 8 | int posB = n - 1; 9 | int idx = m + n - 1; 10 | while (posA >= 0 && posB >= 0) { 11 | if (A[posA] > B[posB]) { 12 | A[idx--] = A[posA--]; 13 | } else { 14 | A[idx--] = B[posB--]; 15 | } 16 | } 17 | //處理剩下的element 18 | while (posA >= 0) { 19 | A[idx--] = A[posA--]; 20 | } 21 | while (posB >= 0) { 22 | A[idx--] = B[posB--]; 23 | } 24 | } 25 | ``` 26 | 27 | # Merge Sorted Array II 28 | [原題網址](http://www.lintcode.com/en/problem/merge-sorted-array-ii/) 29 | 30 | ```java 31 | public ArrayList mergeSortedArray(ArrayList A, ArrayList B) { 32 | ArrayList res = new ArrayList(); 33 | if (A == null || A.size() == 0) { 34 | return B; 35 | } 36 | if (B == null || B.size() == 0) { 37 | return A; 38 | } 39 | 40 | int pointA = 0; 41 | int pointB = 0; 42 | while (pointA < A.size() && pointB < B.size()) { 43 | if (A.get(pointA) <= B.get(pointB)) { 44 | res.add(A.get(pointA++)); 45 | } else { 46 | res.add(B.get(pointB++)); 47 | } 48 | } 49 | while (pointA < A.size()) { 50 | res.add(A.get(pointA++)); 51 | } 52 | while (pointB < B.size()) { 53 | res.add(B.get(pointB++)); 54 | } 55 | 56 | return res; 57 | } 58 | ``` 59 | -------------------------------------------------------------------------------- /array/minimum_size_subarray_sum.md: -------------------------------------------------------------------------------- 1 | #Minimum Size Subarray Sum 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/minimum-size-subarray-sum/) 4 | 5 | 題意,給一個陣列與一個目標值,找出最少連續元素個數總和大於目標值。 6 | 7 | 解題思路: 8 | 9 | 可用暴力法枚舉所有可能性但需花 $$O(N^2)$$ 的時間複雜度,且含有許多重複運算的動作。 10 | 11 | 另外使用兩個指針方法來優化,一開始固定 i ,當未滿足條件時,不斷的移動 j ,一但滿足了條件,再慢慢移動 i 去縮短路徑長度。 12 | 13 | 14 | ```java 15 | public int minimumSize(int[] nums, int s) { 16 | 17 | if (nums == null || nums.length == 0) { 18 | return -1; 19 | } 20 | 21 | int sum = 0; 22 | int min = Integer.MAX_VALUE; 23 | 24 | for (int i = 0, j = 0; i < nums.length; i++) { 25 | 26 | while (j < nums.length && sum < s) { 27 | sum += nums[j]; 28 | j++; 29 | } 30 | 31 | if (sum >= s) { 32 | min = Math.min(min, j - i); 33 | } 34 | 35 | sum -= nums[i]; 36 | } 37 | 38 | if (min == Integer.MAX_VALUE) { 39 | return -1; 40 | } else { 41 | return min; 42 | } 43 | 44 | } 45 | ``` 46 | >Time Complexity:$$O(2N) = O(N)$$,因 i 與 j 各需移動N次 47 | 48 | 網友 [Grandyang]() 提供了以下 O(N) 解法的思路: 49 | 50 | "這個解法要用到二分查找法,思路是,我們建立一個比原數組長一位的sums數組,其中sums[i]表示nums數組中[0, i - 1]的和,然後我們對於sums中每一個值sums[i],用二分查找法找到子數組的右邊界位置,使該子數組之和大於sums[i] + s,然後我們更新最短長度的距離即可。" 51 | 52 | 53 | 54 | 55 | --- 56 | ###Reference 57 | 1. http://www.cnblogs.com/grandyang/p/4501934.html 58 | -------------------------------------------------------------------------------- /array/minimum_subarray.md: -------------------------------------------------------------------------------- 1 | #Minimum Subarray 2 | 3 | []() 4 | 5 | 題意:此為Maximum Subarray的變形,給予一個陣列,找出一個子陣列其中的和是最小的 6 | 7 | 解題思路:使用兩個變數 cur 與 min 分別紀錄當前的和,與當前的最小值,會有以下兩個狀況。 8 | 9 | + 若 cur + nums[i] 比當前的 nums[i] 還來得大的話,代表目前值包含之前的和的話,總和會變大,之前的總和反而幫了倒忙,由於此題是求最小,因此放棄前面的總和,從 i 開始繼續再找。 10 | + 若 cur + nums[i] 比當前的 nums[i] 小的話,則代表之前的 cur有用,把cur留著與目前的 nums[i] 相加,接著比較一下有沒有比當前的 min小,若有,則更新。 11 | 12 | ```java 13 | public int minSubArray(ArrayList nums) { 14 | if (nums == null || nums.size() == 0) { 15 | return 0; 16 | } 17 | 18 | int min = nums.get(0); 19 | int cur = nums.get(0); 20 | // 與Maximum Subarray 大同小異,但在這裡要比的是當下的值是否比cur+當下值來得小, 21 | // 若是,則直接從當下值重新開始算 22 | // 若否,則把當下值累積繼續下一步 23 | for (int i = 1; i < nums.size(); i++) { 24 | if (nums.get(i) < cur + nums.get(i)) { 25 | cur = nums.get(i); 26 | } else { 27 | cur += nums.get(i); 28 | } 29 | min = Math.min(cur, min); 30 | } 31 | return min; 32 | } 33 | ``` 34 | 35 | >Time Complexity:$$O(N)$$,因只需遍歷一次陣列即可。 -------------------------------------------------------------------------------- /array/missing_ranges.md: -------------------------------------------------------------------------------- 1 | # Missing Ranges 2 | 3 | [Leetcode(https://leetcode.com/problems/missing-ranges/) 4 | 5 | 題意: 6 | 7 | Given a sorted integer array where the range of elements are [lower, upper] inclusive, return its missing ranges. 8 | 9 | For example, given [0, 1, 3, 50, 75], lower = 0 and upper = 99, return ["2", "4->49", "51->74", "76->99"]. 10 | 11 | 12 | 解題思路: 13 | 14 | 使用previous與current兩個指針分別紀錄前後的值,若兩者差距大於1的話,則使用get range的function來產生出需要插入的string。 15 | 16 | ```java 17 | //lower = 5, upper = 10 18 | //nums = 7, 19 | //res ["5-6", "8-10"]; 20 | 21 | public class Solution { 22 | public List findMissingRanges(int[] nums, int lower, int upper) { 23 | List res = new ArrayList(); 24 | int len = nums.length; 25 | 26 | //start from lower - 1 27 | int previous = lower - 1; 28 | for (int i = 0 ; i <= len; i++) { 29 | //take care of boundary condition 30 | int cur = (i == len) ? upper + 1 : nums[i]; 31 | if (cur - previous > 1) { 32 | res.add(getRange(previous + 1, cur - 1)); 33 | } 34 | previous = cur; 35 | } 36 | return res; 37 | } 38 | 39 | private String getRange(int from, int to) { 40 | return (from == to) ? String.valueOf(from) : from + "->" + to; 41 | } 42 | } 43 | ``` 44 | -------------------------------------------------------------------------------- /array/partition_array_by_odd_and_even.md: -------------------------------------------------------------------------------- 1 | # Partition Array by Odd and Even 2 | 3 | ```java 4 | public void partitionArray(int[] nums) { 5 | 6 | if (nums == null || nums.length == 0) { 7 | return; 8 | } 9 | 10 | int start = 0; 11 | int end = nums.length - 1; 12 | 13 | while (start < end) { 14 | while (start < end && nums[start] % 2 != 0) { 15 | start++; 16 | } 17 | 18 | while (start < end && nums[end] % 2 == 0) { 19 | end--; 20 | } 21 | 22 | if (start < end) { 23 | int temp = nums[start]; 24 | nums[start] = nums[end]; 25 | nums[end] = temp; 26 | start++; 27 | end--; 28 | } 29 | 30 | } 31 | } 32 | ``` -------------------------------------------------------------------------------- /array/range_sum_query_-_immutable.md: -------------------------------------------------------------------------------- 1 | # Range Sum Query - Immutable 2 | 3 | [Leetcode](https://leetcode.com/problems/range-sum-query-immutable/) 4 | 5 | 題意: 6 | 7 | Given an integer array nums, find the sum of the elements between indices i and j (i ≦ j), inclusive. 8 | 9 | **Example:** 10 | ``` 11 | Given nums = [-2, 0, 3, -5, 2, -1] 12 | 13 | sumRange(0, 2) -> 1 14 | sumRange(2, 5) -> -1 15 | sumRange(0, 5) -> -3 16 | ``` 17 | **Note:** 18 | 1. You may assume that the array does not change. 19 | 2. There are many calls to sumRange function. 20 | 21 | 22 | 解題思路: 23 | 24 | 維護一個len + 1的sum array,sum[i] 表示從 nums[0] 到 nums[i - 1]的總和。 25 | 26 | ```java 27 | public class NumArray { 28 | 29 | int[] sums; 30 | public NumArray(int[] nums) { 31 | if (nums == null || nums.length == 0) { 32 | return; 33 | } 34 | int len = nums.length; 35 | sums = new int[len + 1]; 36 | int sum = 0; 37 | for (int i = 1; i <= len; i++) { 38 | sums[i] = sums[i - 1] + nums[i - 1]; 39 | } 40 | } 41 | 42 | public int sumRange(int i, int j) { 43 | if (i < 0 || j >= sums.length) { 44 | return 0; 45 | } 46 | return sums[j + 1] - sums[i]; 47 | } 48 | } 49 | 50 | 51 | // Your NumArray object will be instantiated and called as such: 52 | // NumArray numArray = new NumArray(nums); 53 | // numArray.sumRange(0, 1); 54 | // numArray.sumRange(1, 2); 55 | ``` -------------------------------------------------------------------------------- /array/read_n_characters_given_read4.md: -------------------------------------------------------------------------------- 1 | # Read N Characters Given Read4 2 | 3 | [Leetcode](https://leetcode.com/problems/read-n-characters-given-read4/) 4 | 5 | 6 | 題意:要讀進一段文字,但只能用一個function 一次讀4個char 7 | 8 | 9 | 解題思路: 10 | 11 | 12 | ```java 13 | /* The read4 API is defined in the parent class Reader4. 14 | int read4(char[] buf); */ 15 | 16 | public class Solution extends Reader4 { 17 | /** 18 | * @param buf Destination buffer 19 | * @param n Maximum number of characters to read 20 | * @return The number of characters read 21 | */ 22 | public int read(char[] buf, int n) { 23 | int totalRead = 0; 24 | char[] buffer = new char[4]; 25 | 26 | while(true) { 27 | int currentCount = read4(buffer); 28 | int currentLength = Math.min(currentCount, n - totalRead); 29 | for (int i = 0; i < currentLength; i++) { 30 | buf[totalRead + i] = buffer[i]; 31 | } 32 | 33 | totalRead += currentLength; 34 | if (currentCount < 4 || totalRead == n) { 35 | return totalRead; 36 | } 37 | } 38 | } 39 | } 40 | ``` -------------------------------------------------------------------------------- /array/recover_rotated_sorted_array.md: -------------------------------------------------------------------------------- 1 | #Recover Rotated Sorted Array 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/recover-rotated-sorted-array/) 4 | 5 | 6 | 7 | ```java 8 | public class Solution { 9 | 10 | public void recoverRotatedSortedArray(ArrayList nums) { 11 | 12 | // 首先找出最小值的前一位,即分割點 13 | int pos = 0; 14 | for (int i = 0; i < nums.size() - 1; i++) { 15 | if (nums.get(i) > nums.get(i+1)) { 16 | pos = i; 17 | break; 18 | } 19 | } 20 | // 避免sorted array 21 | // 反轉前半段 22 | // 反轉後半段 23 | // 整個反轉 24 | if (pos != 0) { 25 | reverseArray(nums, 0, pos); 26 | reverseArray(nums, pos + 1, nums.size() - 1); 27 | reverseArray(nums, 0, nums.size() - 1); 28 | } 29 | } 30 | 31 | 32 | public void reverseArray(ArrayList nums, int start, int end) { 33 | while (start < end) { 34 | Collections.swap(nums, start, end); 35 | start++; 36 | end--; 37 | } 38 | } 39 | } 40 | ``` 41 | >Time Complexity : O(n) -------------------------------------------------------------------------------- /array/remove_element.md: -------------------------------------------------------------------------------- 1 | # Remove Element 2 | 3 | [Lintcode](http://www.lintcode.com/en/problem/remove-element/) 4 | [Leetcode](https://leetcode.com/problems/remove-element/) 5 | 6 | 題意: 7 | 8 | Given an array and a value, remove all instances of that value in place and return the new length. 9 | 10 | The order of elements can be changed. It doesn't matter what you leave beyond the new length. 11 | 12 | 13 | 解題思路: 14 | 15 | Updated on 2015.12.20 16 | 17 | ```java 18 | public class Solution { 19 | public int removeElement(int[] nums, int val) { 20 | if (nums == null || nums.length == 0) { 21 | return 0; 22 | } 23 | 24 | int pos = 0; 25 | for (int i = 0; i < nums.length; i++) { 26 | if (nums[i] != val) { 27 | nums[pos++] = nums[i]; 28 | } 29 | } 30 | 31 | return pos; 32 | } 33 | } 34 | ``` 35 | 36 | 使用兩根指針 i 與 j ,j負責走訪整個陣列,i負責指向最後一個不重複的元素,程式碼如下: 37 | 38 | ```java 39 | public class Solution { 40 | /** 41 | *@param A: A list of integers 42 | *@param elem: An integer 43 | *@return: The new length after remove 44 | */ 45 | public int removeElement(int[] A, int elem) { 46 | int i = 0; 47 | int j = 0; 48 | while (j < A.length) { 49 | if (A[j] == elem) { 50 | j++; 51 | } else { 52 | A[i] = A[j]; 53 | j++; 54 | i++; 55 | } 56 | } 57 | return i; 58 | } 59 | } 60 | 61 | 62 | ``` -------------------------------------------------------------------------------- /array/search_a_2d_array.md: -------------------------------------------------------------------------------- 1 | #Search a 2D Array 2 | 3 | 4 | ```java 5 | public boolean searchMatrix(int[][] matrix, int target) { 6 | 7 | if (matrix.length == 0) { 8 | return false; 9 | } 10 | 11 | int start = 0; 12 | int rows = matrix.length; 13 | int cols = matrix[0].length; 14 | int end = rows * cols - 1; 15 | int mid; 16 | 17 | while (start + 1 < end) { 18 | mid = start + (end - start) / 2; 19 | int midValue = matrix[mid / cols][mid % cols]; 20 | if (midValue == target) { 21 | return true; 22 | } else if (midValue > target) { 23 | end = mid; 24 | } else if (midValue < target) { 25 | start = mid; 26 | } 27 | } 28 | 29 | int startValue = matrix[start / cols][start % cols]; 30 | int endValue = matrix[end / cols][end % cols]; 31 | 32 | if (startValue == target || endValue == target) { 33 | return true; 34 | } else { 35 | return false; 36 | } 37 | } 38 | ``` -------------------------------------------------------------------------------- /array/search_in_a_big_sorted_array.md: -------------------------------------------------------------------------------- 1 | # Search in a Big Sorted Array 2 | 3 | [Lintcode](http://www.lintcode.com/en/problem/search-in-a-big-sorted-array/) 4 | 5 | 題意: 6 | 7 | 陣列太大無法知道end,要如何找到要的 target。 8 | 9 | 解題思路: 10 | 11 | 使用不斷延伸去探測 end在哪裡,再用binary search 即可。 12 | 13 | 程式碼如下: 14 | 15 | ```java 16 | /** 17 | * Definition of ArrayReader: 18 | * 19 | * class ArrayReader { 20 | * // get the number at index, return -1 if not exists. 21 | * public int get(int index); 22 | * } 23 | */ 24 | public class Solution { 25 | /** 26 | * @param reader: An instance of ArrayReader. 27 | * @param target: An integer 28 | * @return : An integer which is the index of the target number 29 | */ 30 | public int searchBigSortedArray(ArrayReader reader, int target) { 31 | 32 | int start = 0; 33 | int end = 0; 34 | while ((reader.get(end) != -1) && (reader.get(end) < target)) { 35 | end = end * 2 + 1; 36 | } 37 | 38 | while (start + 1 < end) { 39 | int mid = start + (end - start) / 2; 40 | if (reader.get(mid) < target) { 41 | start = mid; 42 | } else { 43 | end = mid; 44 | } 45 | } 46 | 47 | if (reader.get(start) == target) { 48 | return start; 49 | } else if (reader.get(end) == target) { 50 | return end; 51 | } else { 52 | return -1; 53 | } 54 | 55 | } 56 | } 57 | 58 | ``` 59 | 60 | --- 61 | ### Reference 62 | 1. http://www.jiuzhang.com/solutions/search-in-a-big-sorted-array/ -------------------------------------------------------------------------------- /array/shortest_word_distance_iii.md: -------------------------------------------------------------------------------- 1 | # Shortest Word Distance III 2 | 3 | [Leetcode](https://leetcode.com/problems/shortest-word-distance-iii/) 4 | 5 | 6 | 題意: 7 | 8 | This is a follow up of Shortest Word Distance. The only difference is now word1 could be the same as word2. 9 | 10 | Given a list of words and two words word1 and word2, return the shortest distance between these two words in the list. 11 | 12 | word1 and word2 may be the same and they represent two individual words in the list. 13 | 14 | For example, 15 | Assume that words = ["practice", "makes", "perfect", "coding", "makes"]. 16 | 17 | Given word1 = 「makes」, word2 = 「coding」, return 1. 18 | Given word1 = "makes", word2 = "makes", return 3. 19 | 20 | Note: 21 | You may assume word1 and word2 are both in the list. 22 | 23 | 24 | 25 | 解題思路: 26 | 27 | 與1相同,但此時word1可能與word2相同,其程式碼大致相同,只有在第8行的判稍作改變,程式碼如下: 28 | 29 | 30 | ```java 31 | public class Solution { 32 | public int shortestWordDistance(String[] words, String word1, String word2) { 33 | int index = -1; 34 | int minDistance = Integer.MAX_VALUE; 35 | for (int i = 0; i < words.length; i++) { 36 | if (words[i].equals(word1) || words[i].equals(word2)) { 37 | if (index != -1) { 38 | if (index != i && (!words[index].equals(words[i]) || word1.equals(word2))) { 39 | minDistance = Math.min(minDistance, i - index); 40 | } 41 | } 42 | index = i; 43 | } 44 | } 45 | return minDistance; 46 | } 47 | } 48 | ``` 49 | 50 | --- 51 | ###Reference 52 | 1. https://leetcode.com/discuss/50715/12-16-lines-java-c -------------------------------------------------------------------------------- /array/single_number.md: -------------------------------------------------------------------------------- 1 | # Single Number 2 | 3 | [原題連結](http://www.lintcode.com/en/problem/single-number/) 4 | 5 | 題意:給定一個陣列,其中每個元素皆出現兩次,只有一個元素出現一次,找出那個元素。 6 | 7 | 解題思路:此題可用暴力法加一個hashmap完成,但是需要花到$$O(N)$$的空間複雜度,因此我們使用了XOR的特性來幫助我們解決這道題,因 ``` a xor a = 0```,所以我們只需要把所有數全XOR起來就是答案了。程式碼如下: 8 | 9 | ```java 10 | public int singleNumber(int[] A) { 11 | if (A.length == 0) { 12 | return 0; 13 | } 14 | 15 | int n = A[0]; 16 | for(int i = 1; i < A.length; i++) { 17 | n = n ^ A[i]; 18 | } 19 | 20 | return n; 21 | } 22 | ``` 23 | 24 | >Time Complexity:$$O(N)$$,因只需遍歷一次陣列即可。 25 | 26 | updated on 2016.1.9 27 | 28 | O(NlogN)的解法,先排序後再兩個兩個比較 29 | 30 | ```java 31 | public class Solution { 32 | public int singleNumber(int[] nums) { 33 | if (nums == null || nums.length == 0) { 34 | return 0; 35 | } 36 | 37 | Arrays.sort(nums); 38 | for (int i = 1; i < nums.length; i = i + 2) { 39 | if (nums[i - 1] != nums[i]) { 40 | return nums[i - 1]; 41 | } 42 | } 43 | 44 | return nums[nums.length - 1]; 45 | } 46 | } 47 | ``` -------------------------------------------------------------------------------- /array/single_number_iii.md: -------------------------------------------------------------------------------- 1 | #Single Number III 2 | 3 | [原題連結](http://www.lintcode.com/en/problem/single-number-iii/) 4 | 5 | 題意:給予 $$2N + 2$$ 個元素,每個元素皆出現兩次,但其中兩個元素(假設是a與b)各出現一 次,找出那兩個數。 6 | 7 | 解題思路:所要思考就是怎麼把 $$2N+2$$ 的問題轉換成兩個 $$2N+1$$ 的問題,當我們把所有元素全 XOR 起來時,其實就等於 ``` c = a ^ b```,而要如何把這兩個元素分開,因他們兩個數不同,所以在二進制的情況下,該位元若等於一,則代表兩數在該位元不同,我們只要利用該位元來將所有元素分成兩堆即可。此時分別將兩堆利用Single Number I的方法來處理即可。 8 | 9 | >在這裡我們使用了以下技巧來將最後一個位元1取出來:假設我們XOR的結果為6(1010),我們要取出(0010),首先使用```result & (result - 1)```而得到1000,皆著再用原本的result去與剛剛的結果相減,即得到1010-1000 = 0010,為我們需要的數。 10 | 11 | ```java 12 | public List singleNumberIII(int[] A) { 13 | int len = A.length; 14 | int result = 0; 15 | // 先把所有數都xor起來,會得到a^b 16 | for (int i = 0; i < len; i++) { 17 | result ^= A[i]; 18 | } 19 | 20 | // 接著用這個方法來找出最後一個不一樣的位元 21 | // 靠這個位元來決定每個數要放到哪個group 22 | // 等於轉成兩個2n+1的問題來解 23 | // 之後把這兩個值加到list回傳即可 24 | // result & (result - 1) 會把最後一個1去掉 25 | // 再用result去減可以得到最後一個1 26 | // 接著直接去比這個bit即可 27 | int lastBit = result - (result & (result - 1)); 28 | int group1 = 0; 29 | int group2 = 0; 30 | 31 | for (int i = 0; i < len; i++) { 32 | if ((A[i] & lastBit) == 0) { 33 | group1 ^= A[i]; 34 | } else { 35 | group2 ^= A[i]; 36 | } 37 | } 38 | 39 | List list = new ArrayList(); 40 | list.add(group1); 41 | list.add(group2); 42 | 43 | return list; 44 | } 45 | ``` 46 | 47 | >Time Complexity:$$O(N)$$ -------------------------------------------------------------------------------- /array/sort_colors.md: -------------------------------------------------------------------------------- 1 | # Sort Colors 2 | [原題網址](http://www.lintcode.com/en/problem/sort-colors/) 3 | 4 | 題意:陣列中只有三個顏色(0, 1, 2),將此三個顏色排序 5 | 6 | 解題思路: 7 | 8 | 利用三個 pointer (left, right, point),接著透過point以下三種情況作處理 9 | left 代表0 10 | point 代表1,並作indicator去走訪整個陣列 11 | right 代表2 12 | 13 | 1. nums[point] == 0:表示需要往前移,因此跟left的值作交換,此時nums[left] 已確定是0,直接left與point往下移 14 | 2. nums[point] == 1:表示放在正確的位置,直接point往下移 15 | 3. nums[point] == 2:表示需要與right作交換,但由於當下的right也指向2,與point換了之後,point還是指向另一個二,因此只移動right。 16 | 17 | ```java 18 | class Solution { 19 | 20 | public void sortColors(int[] nums) { 21 | if (nums == null || nums.length == 0) { 22 | return; 23 | } 24 | int left = 0; 25 | int right = nums.length - 1; 26 | int point = 0; 27 | // 利用三個指針,left, right, point 28 | // left負責0,point負責1,right負責2 29 | while (point <= right) { 30 | 31 | if (nums[point] == 0) { 32 | swap(nums, left, point); 33 | left++; 34 | point++; 35 | } else if (nums[point] == 1) { 36 | point++; 37 | } else { 38 | swap(nums, point, right); 39 | right--; //只移動right,因可能當下right指向的值也是2,要在下一輪繼續處理 40 | 41 | } 42 | } 43 | } 44 | 45 | private void swap(int[] A, int idxA, int idxB) { 46 | int temp = A[idxA]; 47 | A[idxA] = A[idxB]; 48 | A[idxB] = temp; 49 | } 50 | } 51 | 52 | ``` 53 | -------------------------------------------------------------------------------- /array/subarray_sum.md: -------------------------------------------------------------------------------- 1 | #Subarray Sum 2 | 3 | [原題連結](http://www.lintcode.com/en/problem/subarray-sum/) 4 | 5 | 題意: 6 | 7 | 給定一個整數矩陣,請找出一個子矩陣,使得其數字之和等於0.輸出答案時,請返回左上數字和右下數字的坐標。 8 | 9 | 給定矩陣 10 | ``` 11 | [ 12 | [1 ,5 ,7], 13 | [3 ,7 ,-8], 14 | [4 ,-8 ,9], 15 | ] 16 | ``` 17 | 返回 ```[(1,1), (2,2)]``` 18 | 19 | 挑戰 20 | O(n3) 時間複雜度。 21 | 22 | 解題思路: 23 | 24 | 網友 [Yu Zhang](http://www.cnblogs.com/yuzhangcmu/p/4174507.html)提供以下解法 25 | 26 | 使用Map 來記錄index, sum的值。當遇到兩個index的sum相同時,表示從index1+1到index2是一個解。 27 | 28 | 注意:添加一個index = -1作為虛擬節點。這樣我們才可以記錄index1 = 0的解。 29 | 30 | 空間複雜度:O(N) 31 | 32 | ```java 33 | public ArrayList subarraySum(int[] nums) { 34 | 35 | ArrayList res = new ArrayList(); 36 | 37 | if (nums == null || nums.length == 0) { 38 | return res; 39 | } 40 | 41 | int len = nums.length; 42 | HashMap map = new HashMap(); 43 | int sum = 0; 44 | map.put(0, -1); 45 | 46 | for (int i = 0; i < len; i++) { 47 | sum += nums[i]; 48 | if (map.containsKey(sum)) { 49 | res.add(map.get(sum) + 1); 50 | res.add(i); 51 | break; 52 | } 53 | 54 | map.put(sum, i); 55 | } 56 | 57 | return res; 58 | } 59 | ``` 60 | 61 | --- 62 | ###Reference 63 | 1. http://www.cnblogs.com/yuzhangcmu/p/4174507.html -------------------------------------------------------------------------------- /array/subarray_sum_ii.md: -------------------------------------------------------------------------------- 1 | #Subarray Sum II 2 | 3 | 題意: 4 | 5 | 給定一個矩陣,與一個 range,找出該矩陣所有符合該 range 的 子矩陣和的個數。 6 | 7 | Example 8 | Given [1,2,3,4] and interval = [1,3], return 4. The possible answers are: 9 | ``` 10 | [0, 0] 11 | [0, 1] 12 | [1, 1] 13 | [2, 2] 14 | ``` 15 | 16 | 解題思路:先預處理一個 sumArray來存放前i個元素和,接著再枚舉所有可能的搭配,若 sum[i] - sum[j] 在範圍內的話,則 count 加一,其代碼如下: 17 | 18 | ```java 19 | public int subarraySumII(int[] A, int start, int end) { 20 | 21 | if (A == null || A.length == 0) { 22 | return 0; 23 | } 24 | 25 | //sumArray[i] 表示前i個元素和 26 | int[] sumArray = new int[A.length]; 27 | sumArray[0] = 0; // 為了避免第一個元素在range裡,因此加了此元素。 28 | int sum = 0; 29 | for (int i = 1; i <= A.length; i++) { 30 | sum += A[i - 1]; 31 | sumArray[i] = sum; 32 | } 33 | 34 | int count = 0; 35 | for (int i = 0; i <= A.length; i++) { 36 | for (int j = i; j <= A.length; j++) { 37 | int diff = sumArray[j] - sumArray[i]; 38 | if (diff >= start && diff <= end) { 39 | count++; 40 | } 41 | } 42 | } 43 | 44 | return count; 45 | } 46 | ``` 47 | --- 48 | Time Complexity:$$O(N^{2})$$ -------------------------------------------------------------------------------- /array/the_smallest_difference.md: -------------------------------------------------------------------------------- 1 | #The Smallest Difference 2 | 3 | [原題連結](http://www.lintcode.com/en/problem/the-smallest-difference/) 4 | 5 | 題意:給兩個陣列 A 與 B 在兩個陣列中各選一個元素相減,找出最小的差。 6 | 7 | 解題思路:可用暴力法一一比對,花 $$O(N^{2})$$ 時間複雜度,但可以透過排序兩個陣列,利用兩個指針來幫助我們計算出最小差,程式碼如下: 8 | 9 | ```java 10 | public int smallestDifference(int[] A, int[] B) { 11 | 12 | Arrays.sort(A); 13 | Arrays.sort(B); 14 | 15 | int i = 0; 16 | int j = 0; 17 | int minDiff = Integer.MAX_VALUE; 18 | while ( i < A.length && j < B.length) { 19 | int curDiff = Math.abs(A[i] - B[j]); 20 | minDiff = (curDiff < minDiff) ? curDiff : minDiff; 21 | if (A[i] > B[j]) { 22 | j++; 23 | } else { 24 | i++; 25 | } 26 | } 27 | 28 | return minDiff; 29 | } 30 | ``` 31 | >Time Complexity:$$O(NlogN)$$ -------------------------------------------------------------------------------- /array/triangle.md: -------------------------------------------------------------------------------- 1 | #Triangle 2 | 3 | [原題連結](http://www.lintcode.com/en/problem/triangle/) 4 | 5 | 題意:Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. 6 | 7 | For example, given the following triangle 8 | 9 | [ 10 | [2], 11 | [3,4], 12 | [6,5,7], 13 | [4,1,8,3] 14 | ] 15 | 16 | The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11). 17 | 18 | 解題思路:由下往上作,每一層找出下一層相鄰且較小成本的點,把該點成本與本身的成本相加即可,程式碼如下: 19 | 20 | ```java 21 | public int minimumTotal(ArrayList> triangle) { 22 | 23 | if (triangle == null || triangle.size() == 0) { 24 | return 0; 25 | } 26 | 27 | for (int i = triangle.size() - 2; i >= 0; i--) { 28 | 29 | for (int j = 0; j < triangle.get(i).size(); j++) { 30 | int candidateOne = triangle.get(i+1).get(j); 31 | int candidateTwo = triangle.get(i+1).get(j+1); 32 | int minCost = Math.min(candidateOne, candidateTwo) + triangle.get(i).get(j); 33 | triangle.get(i).set(j, minCost); 34 | } 35 | } 36 | 37 | return triangle.get(0).get(0); 38 | } 39 | ``` -------------------------------------------------------------------------------- /array/two_sum_iii_-_data_structure_design.md: -------------------------------------------------------------------------------- 1 | # Two Sum III - Data structure design 2 | 3 | [Leetcode](https://leetcode.com/problems/two-sum-iii-data-structure-design/) 4 | 5 | 題意: 6 | 7 | Design and implement a TwoSum class. It should support the following operations: add and find. 8 | 9 | ```add``` - Add the number to an internal data structure. 10 | ```find``` - Find if there exists any pair of numbers which sum is equal to the value. 11 | 12 | For example, 13 | ``` 14 | add(1); add(3); add(5); 15 | find(4) -> true 16 | find(7) -> false 17 | ``` 18 | 19 | 解題思路: 20 | 21 | 主要運用到map.entry這個方法把所有key皆找出來,key value分別代表number 與count,程式碼如下: 22 | 23 | ```java 24 | public class TwoSum { 25 | 26 | // Add the number to an internal data structure. 27 | HashMap map = new HashMap(); 28 | public void add(int number) { 29 | if (map.containsKey(number)) { 30 | map.put(number, map.get(number) + 1); 31 | } else { 32 | map.put(number, 1); 33 | } 34 | } 35 | 36 | // Find if there exists any pair of numbers which sum is equal to the value. 37 | public boolean find(int value) { 38 | for (Map.Entry entry : map.entrySet()) { 39 | int i = entry.getKey(); 40 | int j = value - i; 41 | if (i == j && entry.getValue() > 1 || (i != j && map.containsKey(j))) { 42 | return true; 43 | } 44 | } 45 | return false; 46 | } 47 | } 48 | ``` -------------------------------------------------------------------------------- /array/wiggle_sort_ii.md: -------------------------------------------------------------------------------- 1 | # Wiggle Sort II 2 | 3 | []() 4 | 5 | 6 | 題意: 7 | 8 | Given an unsorted array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3].... 9 | 10 | Example: 11 | 1. Given nums = [1, 5, 1, 1, 6, 4], one possible answer is [1, 4, 1, 5, 1, 6]. 12 | 2. Given nums = [1, 3, 2, 2, 3, 1], one possible answer is [2, 3, 1, 3, 1, 2]. 13 | 14 | Note: 15 | You may assume all input has valid answer. 16 | 17 | Follow Up: 18 | Can you do it in O(n) time and/or in-place with O(1) extra space? 19 | 20 | 21 | 解題思路: 22 | 23 | O(nlogn) + O(n) 法: 24 | 25 | 先把原陣列排序,接著找出中間點,偶數index塞中間點前的數,奇數點塞中間點後的數。 26 | 27 | ```java 28 | public class Solution { 29 | public void wiggleSort(int[] nums) { 30 | if (nums == null || nums.length < 2) { 31 | return; 32 | } 33 | 34 | int len = nums.length; 35 | int[] temp = new int[len]; 36 | Arrays.sort(nums); 37 | System.arraycopy(nums, 0, temp, 0, nums.length); 38 | 39 | int mid = (temp.length - 1) / 2; 40 | 41 | for (int i = 0; i <= mid; i++) { 42 | nums[2 * i] = temp[i]; 43 | if ((2 * i + 1) < temp.length) { 44 | nums[2 * i + 1] = temp[mid + 1 + i]; 45 | } 46 | } 47 | } 48 | } 49 | ``` -------------------------------------------------------------------------------- /binary_tree/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/binary_tree/.DS_Store -------------------------------------------------------------------------------- /binary_tree/README.md: -------------------------------------------------------------------------------- 1 | #Binary Tree 2 | 3 | ```java 4 | public class Solution { 5 | /** 6 | * @param root: The root of binary tree. 7 | * @return: An integer. 8 | */ 9 | // singlePath:由root往下走到任何點的最大路徑,可以不包含root 10 | // maxPath: 整顆樹上目前任何點到任何點的最大路徑,至少包含一個點。 11 | // 使用一個resulttype class來不斷update這兩個值 12 | public class ResultType { 13 | int singlePath; 14 | int maxPath; 15 | public ResultType(int singlePath, int maxPath) { 16 | this.singlePath = singlePath; 17 | this.maxPath = maxPath; 18 | } 19 | } 20 | public int maxPathSum(TreeNode root) { 21 | // write your code here 22 | 23 | ResultType res = helper(root); 24 | return res.maxPath; 25 | } 26 | 27 | public ResultType helper(TreeNode root) { 28 | if (root == null) { 29 | return new ResultType(0, Integer.MIN_VALUE); 30 | } 31 | 32 | ResultType left = helper(root.left); 33 | ResultType right = helper(root.right); 34 | 35 | //檢查由此root往下走的最大path,看是往右走較大還是往左走較大 36 | //記得,可以不含root,因此拿結果與0來比較 37 | int singlePath = Math.max(left.singlePath, right.singlePath) + root.val; 38 | singlePath = Math.max(0, singlePath); 39 | 40 | //此地方包含了三個情況 41 | //最大sum在左子樹,最大sum在右子樹或是包含左右子樹且跨過root 42 | int maxPath = Math.max(left.maxPath, right.maxPath); 43 | maxPath = Math.max(maxPath, left.singlePath + right.singlePath + root.val); 44 | return new ResultType(singlePath, maxPath); 45 | } 46 | } 47 | ``` 48 | 49 | -------------------------------------------------------------------------------- /binary_tree/balanced_binary_tree.md: -------------------------------------------------------------------------------- 1 | # Balanced Binary Tree 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/balanced-binary-tree/) 4 | 5 | 可利用修改過後的maxdepth程式來達到我們要的目的 ,因maxdepth可幫我們算出高度, 6 | 因此我們只要去比較高度是否差一即可,程式如下: 7 | 8 | ```java 9 | public class Solution { 10 | public boolean isBalanced(TreeNode root) { 11 | if (root == null) { 12 | return true; 13 | } 14 | return maxDepth(root) != -1; 15 | } 16 | 17 | public int maxDepth(TreeNode root) { 18 | if (root == null) { 19 | return 0; 20 | } 21 | int left = maxDepth(root.left); 22 | int right = maxDepth(root.right); 23 | 24 | if (left == -1 || right == -1 || Math.abs(left - right) > 1) { 25 | return -1; 26 | } 27 | return Math.max(left, right) + 1; 28 | } 29 | } 30 | ``` 31 | >時間複雜度:O(n) 32 | 33 | ```java 34 | public boolean isBalanced(TreeNode root) { 35 | return maxDepth(root) != -1; 36 | } 37 | 38 | public int maxDepth(TreeNode root) { 39 | if( root == null ) { 40 | return 0; 41 | } 42 | 43 | int left = maxDepth(root.left); 44 | int right = maxDepth(root.right); 45 | 46 | if( left == -1 || right == -1 || Math.abs(left-right) > 1 ) { 47 | return -1; 48 | } 49 | 50 | return Math.max(left, right) + 1; 51 | } 52 | ``` -------------------------------------------------------------------------------- /binary_tree/binary_tree_level_order_traversal.md: -------------------------------------------------------------------------------- 1 | # Binary Tree Level Order Traversal 2 | 3 | 用BFS來解,標準模板 4 | 5 | ```java 6 | public class Solution { 7 | public ArrayList> levelOrder(TreeNode root) { 8 | // write your code here 9 | ArrayList> res = new ArrayList>(); 10 | Queue queue = new LinkedList(); 11 | 12 | if (root == null) { 13 | return res; 14 | } 15 | queue.offer(root); 16 | while(!queue.isEmpty()) { 17 | int size = queue.size(); 18 | ArrayList tempRes = new ArrayList(); 19 | //用size來判斷上一層節點有幾個,來決定要poll幾次 20 | for (int i = 0; i < size; i++) { 21 | TreeNode curNode = queue.poll(); 22 | if (curNode.left != null) { 23 | queue.offer(curNode.left); 24 | } 25 | if (curNode.right != null) { 26 | queue.offer(curNode.right); 27 | } 28 | tempRes.add(curNode.val); 29 | } 30 | res.add(new ArrayList(tempRes)); 31 | } 32 | 33 | return res; 34 | } 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /binary_tree/binary_tree_upside_down.md: -------------------------------------------------------------------------------- 1 | # Binary Tree Upside Down 2 | 3 | [Leetcode](https://leetcode.com/problems/binary-tree-upside-down/) 4 | 5 | 6 | 題意: 7 | 8 | Given a binary tree where all the right nodes are either leaf nodes with a sibling (a left node that shares the same parent node) or empty, flip it upside down and turn it into a tree where the original right nodes turned into left leaf nodes. Return the new root. 9 | 10 | For example: 11 | Given a binary tree {1,2,3,4,5}, 12 | ``` 13 | 1 14 | / \ 15 | 2 3 16 | / \ 17 | 4 5 18 | ``` 19 | return the root of the binary tree [4,5,2,#,#,3,1]. 20 | ``` 21 | 4 22 | / \ 23 | 5 2 24 | / \ 25 | 3 1 26 | ``` 27 | 28 | 29 | 解題思路: 30 | 31 | 目前還是搞不太清楚怎弄,先記錄下來。 32 | 33 | [分析] 34 | 起始對於每一個節點,相應的操作為: 35 | - p.left = parent.right; 36 | - p.right = parent; 37 | - 38 | ```java 39 | /** 40 | * Definition for a binary tree node. 41 | * public class TreeNode { 42 | * int val; 43 | * TreeNode left; 44 | * TreeNode right; 45 | * TreeNode(int x) { val = x; } 46 | * } 47 | */ 48 | public class Solution { 49 | public TreeNode upsideDownBinaryTree(TreeNode root) { 50 | TreeNode p = root; 51 | TreeNode parent = null; 52 | TreeNode parentRight = null; 53 | while (p != null) { 54 | TreeNode left = p.left; 55 | p.left = parentRight; 56 | parentRight = p.right; 57 | p.right = parent; 58 | parent = p; 59 | p = left; 60 | } 61 | return parent; 62 | } 63 | } 64 | ``` 65 | 66 | --- 67 | ###Reference 68 | 1. http://www.danielbit.com/blog/puzzle/leetcode/leetcode-binary-tree-upside-down 69 | 2. http://blog.csdn.net/whuwangyi/article/details/43186045 -------------------------------------------------------------------------------- /binary_tree/construct_binary_tree_from_inorder_and_postorder_traversal.md: -------------------------------------------------------------------------------- 1 | # Construct Binary Tree from Inorder and Postorder Traversal 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/construct-binary-tree-from-inorder-and-postorder-traversal/) 4 | 5 | > Given inorder and postorder traversal of a tree, construct the binary tree. 6 | 7 | > 給你一顆二元樹的後序遍歷和後續遍歷,要把原本的樹重新構建出來。 8 | 9 | 想法跟[Construct Binary Tree from Preorder and Inorder Traversal](construct_binary_tree_from_preorder_and_inorder_traversal.md)一模一樣 10 | 11 | 12 | ```java 13 | public TreeNode buildTree(int[] inorder, int[] postorder) { 14 | if ( inorder == null || postorder == null || inorder.length != postorder.length ) { 15 | return null; 16 | } 17 | return helper(inorder, 0, inorder.length-1, postorder, 0, postorder.length-1); 18 | } 19 | 20 | public TreeNode helper(int[] inorder, int inStart, int inEnd, int[] postorder, int postStart, int postEnd) { 21 | if ( inStart > inEnd || postStart > postEnd ) { 22 | return null; 23 | } 24 | 25 | TreeNode root = new TreeNode(postorder[postEnd]); 26 | int position = findPosition(inorder, postorder[postEnd], inStart, inEnd); 27 | 28 | root.left = helper(inorder, inStart, position-1, postorder, postStart, postStart+position-inStart-1); 29 | root.right = helper(inorder, position+1, inEnd, postorder, postEnd-inEnd+position, postEnd-1); 30 | 31 | return root; 32 | } 33 | 34 | public int findPosition(int[] array, int key, int start, int end) { 35 | for ( int i = start ; i <= end ; i++ ) { 36 | if ( array[i] == key ) { 37 | return i; 38 | } 39 | } 40 | return -1; 41 | } 42 | ``` 43 | 44 | -------------------------------------------------------------------------------- /binary_tree/construct_binary_tree_from_preorder_and_inorder_traversal.md: -------------------------------------------------------------------------------- 1 | # Construct Binary Tree from Preorder and Inorder Traversal 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/construct-binary-tree-from-preorder-and-inorder-traversal/) 4 | 5 | > Given preorder and inorder traversal of a tree, construct the binary tree. 6 | 7 | > 給你一顆二元樹的前序遍歷和後續遍歷,要把原本的樹重新構建出來。 8 | 9 | 這道題無法直接拿出筆畫圖想一個完美的規律。解題關鍵在於善加利用中序遍歷帶來的優勢。回想中序遍歷在任一節點上的定義:`左子樹 -> 節點 -> 右子樹`,可以發現 10 | 11 | 12 | ```java 13 | public TreeNode buildTree(int[] preorder, int[] inorder) { 14 | if ( preorder == null || inorder == null || preorder.length != inorder.length ) { 15 | return null; 16 | } 17 | return helper(inorder, 0, inorder.length-1, preorder, 0, preorder.length-1); 18 | } 19 | 20 | public TreeNode helper(int[] inorder, int inStart, int inEnd, int[] preorder, int preStart, int preEnd) { 21 | if ( inStart > inEnd || preStart > preEnd ) { 22 | return null; 23 | } 24 | 25 | TreeNode root = new TreeNode(preorder[preStart]); 26 | int position = findPosition(inorder, preorder[preStart], inStart, inEnd); 27 | 28 | root.left = helper(inorder, inStart, position-1, preorder, preStart+1, preEnd-inEnd+position); 29 | root.right = helper(inorder, position+1, inEnd, preorder, preEnd-inEnd+position+1, preEnd); 30 | 31 | return root; 32 | } 33 | 34 | public int findPosition(int[] array, int key, int start, int end) { 35 | for ( int i = start ; i <= end ; i++ ) { 36 | if ( array[i] == key ) { 37 | return i; 38 | } 39 | } 40 | return -1; 41 | } 42 | ``` 43 | 44 | -------------------------------------------------------------------------------- /binary_tree/convert_sorted_array_to_binary_search_tree_with_minimal_height.md: -------------------------------------------------------------------------------- 1 | #Convert Sorted Array to Binary Search Tree With Minimal Height 2 | 3 | [原題連結](http://www.lintcode.com/en/problem/convert-sorted-array-to-binary-search-tree-with-minimal-height/#) 4 | 5 | 題意:利用排序好的陣列建出平衡二元搜尋樹 6 | 7 | 解題思路:用遞迴作即可,但需注意分割時的邊界,左子樹為start 到 mid -1 ,右子樹為 mid + 1 到 end ,程式碼如下: 8 | 9 | ```java 10 | public class Solution { 11 | /** 12 | * @param A: an integer array 13 | * @return: a tree node 14 | */ 15 | public TreeNode sortedArrayToBST(int[] A) { 16 | if (A == null || A.length == 0) { 17 | return null; 18 | } 19 | 20 | return build(A, 0, A.length - 1); 21 | } 22 | 23 | private TreeNode build(int[] A, int start, int end) { 24 | if (start > end) { 25 | return null; 26 | } 27 | 28 | int mid = start + (end - start) / 2; 29 | TreeNode root = new TreeNode(A[mid]); 30 | 31 | root.left = build(A, start, mid-1); 32 | root.right = build(A, mid+1, end); 33 | 34 | return root; 35 | } 36 | } 37 | ``` -------------------------------------------------------------------------------- /binary_tree/count_univalue_subtrees.md: -------------------------------------------------------------------------------- 1 | # Count Univalue Subtrees 2 | 3 | [Leetcode](https://leetcode.com/problems/count-univalue-subtrees/) 4 | 5 | 題意: 6 | 7 | 找出所有subtree值全一樣的個數。 8 | 9 | 10 | Given a binary tree, count the number of uni-value subtrees. 11 | 12 | A Uni-value subtree means all nodes of the subtree have the same value. 13 | 14 | For example: 15 | Given binary tree, 16 | ``` 17 | 5 18 | / \ 19 | 1 5 20 | / \ \ 21 | 5 5 5 22 | ``` 23 | return 4. 24 | 25 | 26 | 解題思路: 27 | 28 | 使用遞迴去作,不斷的把root的val傳下去作比較,一但比到錯的,則返回false。 29 | 30 | ```java 31 | /** 32 | * Definition for a binary tree node. 33 | * public class TreeNode { 34 | * int val; 35 | * TreeNode left; 36 | * TreeNode right; 37 | * TreeNode(int x) { val = x; } 38 | * } 39 | */ 40 | public class Solution { 41 | public int countUnivalSubtrees(TreeNode root) { 42 | if (root == null) { 43 | return 0; 44 | } 45 | int[] counter = new int[1]; 46 | count(root, counter, root.val); 47 | return counter[0]; 48 | } 49 | 50 | private boolean count(TreeNode root, int[] counter, int val) { 51 | if (root == null) { 52 | return true; 53 | } 54 | boolean left = count(root.left, counter, root.val); 55 | boolean right = count(root.right, counter, root.val); 56 | 57 | if (left && right) { 58 | counter[0]++; 59 | } 60 | 61 | return left && right && root.val == val; 62 | } 63 | 64 | } 65 | ``` 66 | --- 67 | ###Reference 68 | 1. https://leetcode.com/discuss/55213/my-ac-java-code -------------------------------------------------------------------------------- /binary_tree/inorder_successor_in_bst.md: -------------------------------------------------------------------------------- 1 | # Inorder Successor in BST 2 | 3 | [Leetcode](https://leetcode.com/problems/inorder-successor-in-bst/) 4 | 5 | 6 | 題意: 7 | 8 | Given a binary search tree and a node in it, find the in-order successor of that node in the BST. 9 | 10 | Note: If the given node has no in-order successor in the tree, return null. 11 | 12 | 13 | 解題思路: 14 | 15 | 是要找bst中某個節點的中序後繼者,如果是往左走,則當下的root有可能是該節點的後繼者,需紀錄下來,若是往右走,則後繼者不變,程式碼如下: 16 | 17 | 18 | ```java 19 | /** 20 | * Definition for a binary tree node. 21 | * public class TreeNode { 22 | * int val; 23 | * TreeNode left; 24 | * TreeNode right; 25 | * TreeNode(int x) { val = x; } 26 | * } 27 | */ 28 | public class Solution { 29 | public TreeNode inorderSuccessor(TreeNode root, TreeNode p) { 30 | if (root == null) { 31 | return root; 32 | } 33 | 34 | TreeNode succ = null; 35 | while (root != null) { 36 | if (p.val < root.val) { 37 | succ = root; 38 | root = root.left; 39 | } else { 40 | root = root.right; 41 | } 42 | } 43 | 44 | return succ; 45 | } 46 | } 47 | ``` 48 | --- 49 | ###Reference 50 | 1. https://leetcode.com/discuss/61105/java-python-solution-o-h-time-and-o-1-space-iterative 51 | 2. https://leetcode.com/discuss/59787/share-my-java-recursive-solution -------------------------------------------------------------------------------- /binary_tree/maximum_depth_of_binary_tree.md: -------------------------------------------------------------------------------- 1 | # Maximum Depth of Binary Tree 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/maximum-depth-of-binary-tree/) 4 | 5 | > Given a binary tree, find its maximum depth. 6 | 7 | > The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. 8 | 9 | > 題目要求一棵樹的最大深度。 10 | 11 | 解題關鍵在於,一個樹任一點的最大深度是由 `左子樹的深度` 與 `右子樹的深度` 看誰大再 +1 而獲得,所以可以輕鬆利用 Divide & Conquer 將問題分成 `左子樹` 跟 `右子樹` 在合併時取最大值 +1。程式如下: 12 | 13 | ```java 14 | public int maxDepth(TreeNode root) { 15 | if (root == null) { // 邊界條件 16 | return 0; 17 | } 18 | // Divide 19 | int left = maxDepth(root.left); 20 | int right = maxDepth(root.right); 21 | // Conquer 22 | return Math.max(left, right) + 1; 23 | } 24 | ``` 25 | 再次提醒,當使用 Divide & Conquer 時,一定要將邊界條件 (Boundary Condition) 寫在前面,這樣才不會出現程式跳不出、停不住而導致的 Runtime Error! 26 | 27 | 分析一下時間複雜度,由於每個點我們都會走過一次,複雜度取決於這棵樹上有多少節點 n 可得: 28 | 29 | >時間複雜度 O(n) 30 | 31 | 32 | updated on 2015.12.26 33 | 34 | Iterative solution 35 | ```java 36 | public int maxDepth(TreeNode root) { 37 | if (root == null) 38 | return 0; 39 | 40 | Deque stack = new LinkedList(); 41 | 42 | stack.push(root); 43 | int count = 0; 44 | 45 | while (!stack.isEmpty()) { 46 | int size = stack.size(); 47 | while (size-- > 0) { 48 | TreeNode cur = stack.pop(); 49 | if (cur.left != null) 50 | stack.addLast(cur.left); 51 | if (cur.right != null) 52 | stack.addLast(cur.right); 53 | } 54 | count++; 55 | 56 | } 57 | return count; 58 | 59 | } 60 | ``` 61 | -------------------------------------------------------------------------------- /binary_tree/minimum_depth_of_binary_tree.md: -------------------------------------------------------------------------------- 1 | # Minimum Depth of Binary Tree 2 | 3 | [Leetcode](https://leetcode.com/problems/minimum-depth-of-binary-tree/) 4 | 5 | 題意: 6 | 7 | Given a binary tree, find its minimum depth. 8 | 9 | The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. 10 | 11 | 12 | 解題思路: 13 | 14 | 中間兩個if需要,因為要防止 [1,2]這種情況 15 | 16 | ```java 17 | /** 18 | * Definition for a binary tree node. 19 | * public class TreeNode { 20 | * int val; 21 | * TreeNode left; 22 | * TreeNode right; 23 | * TreeNode(int x) { val = x; } 24 | * } 25 | */ 26 | public class Solution { 27 | public int minDepth(TreeNode root) { 28 | if (root == null) { 29 | return 0; 30 | } 31 | if (root.left == null) { 32 | return minDepth(root.right) + 1; 33 | } 34 | if (root.right == null) { 35 | return minDepth(root.left) + 1; 36 | } 37 | return Math.min(minDepth(root.left), minDepth(root.right)) + 1; 38 | } 39 | } 40 | ``` -------------------------------------------------------------------------------- /binary_tree/path_sum.md: -------------------------------------------------------------------------------- 1 | # Path Sum 2 | 3 | [Leetcode](https://leetcode.com/problems/path-sum/) 4 | 5 | 題意: 6 | 7 | Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. 8 | 9 | For example: 10 | Given the below binary tree and sum = 22, 11 | ``` 12 | 5 13 | / \ 14 | 4 8 15 | / / \ 16 | 11 13 4 17 | / \ \ 18 | 7 2 1 19 | ``` 20 | return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22. 21 | 22 | 解題思路: 23 | 24 | ```java 25 | /** 26 | * Definition for a binary tree node. 27 | * public class TreeNode { 28 | * int val; 29 | * TreeNode left; 30 | * TreeNode right; 31 | * TreeNode(int x) { val = x; } 32 | * } 33 | */ 34 | public class Solution { 35 | public boolean hasPathSum(TreeNode root, int sum) { 36 | if (root == null) { 37 | return false; 38 | } 39 | if (root.left == null && root.right == null) { 40 | if (root.val == sum) { 41 | return true; 42 | } 43 | return false; 44 | } 45 | return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val); 46 | } 47 | } 48 | ``` -------------------------------------------------------------------------------- /binary_tree/path_sum_iii.md: -------------------------------------------------------------------------------- 1 | # Path Sum III 2 | 3 | 4 | 5 | 題意: 6 | 7 | 解題思路: 8 | 9 | ```java 10 | 11 | public class Solution{ 12 | public void findSum(TreeNode node, int sum, int[] path, int level) { 13 | if (node == null) { 14 | return; 15 | } 16 | 17 | path[level] = node.data; 18 | 19 | int t = 0; 20 | for (int i = level; i >= 0; i--) { 21 | t += path[i]; 22 | if (t == sum) { 23 | print(path, i, level); 24 | } 25 | } 26 | 27 | findSum(node.left, sum, path, level + 1); 28 | findSum(node.right, sum, path, level + 1); 29 | 30 | path[level] = Integer.MIN_VALUE; 31 | } 32 | 33 | public void findSum(TreeNode node, int sum) { 34 | int depth = depth(node); 35 | int[] path = new int[depth]; 36 | findSum(node, sum, path, 0); 37 | } 38 | 39 | public static void print(int[] path, int start, int end) { 40 | for (int i = start, i <= end; i++) { 41 | System.outprintln(path[i] + " "); 42 | } 43 | System.out.println(); 44 | } 45 | 46 | public int depth(TreeNode node) { 47 | if (node == null) { 48 | return 0; 49 | } else { 50 | return 1 + Math.max(depth(node.left), depth(node.right)); 51 | } 52 | } 53 | } 54 | ``` 55 | -------------------------------------------------------------------------------- /binary_tree/recover_binary_search_tree.md: -------------------------------------------------------------------------------- 1 | # Recover Binary Search Tree 2 | 3 | []() 4 | 5 | 題意: 6 | 7 | Two elements of a binary search tree (BST) are swapped by mistake. 8 | 9 | Recover the tree without changing its structure. 10 | 11 | 12 | 解題思路: 13 | 14 | 對於bst作中序遍歷,使用兩個list,分別紀錄節點與節點的值,最後再根據對應的位置 assign 對應的值,時間複雜度為O(NlogN),空間複雜度為O(N),其程式碼如下: 15 | 16 | 17 | ```java 18 | /** 19 | * Definition for a binary tree node. 20 | * public class TreeNode { 21 | * int val; 22 | * TreeNode left; 23 | * TreeNode right; 24 | * TreeNode(int x) { val = x; } 25 | * } 26 | */ 27 | public class Solution { 28 | List nodes = new ArrayList(); 29 | List values = new ArrayList(); 30 | public void recoverTree(TreeNode root) { 31 | if (root == null) { 32 | return; 33 | } 34 | inorderTraversal(root); 35 | Collections.sort(values); 36 | for (int i = 0; i < nodes.size(); i++) { 37 | nodes.get(i).val = values.get(i); 38 | } 39 | } 40 | 41 | 42 | public void inorderTraversal(TreeNode root) { 43 | if (root == null) { 44 | return; 45 | } 46 | inorderTraversal(root.left); 47 | nodes.add(root); 48 | values.add(root.val); 49 | inorderTraversal(root.right); 50 | 51 | } 52 | } 53 | ``` 54 | 55 | 另有O(1)空間複雜度與O(N)時間複雜度的解法 56 | 57 | --- 58 | ###Reference 59 | 1. http://fisherlei.blogspot.com/2012/12/leetcode-recover-binary-search-tree.html -------------------------------------------------------------------------------- /binary_tree/search_range_in_binary_search_tree.md: -------------------------------------------------------------------------------- 1 | # Search Range in Binary Search Tree 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/search-range-in-binary-search-tree/) 4 | 5 | Divide & Conquer 6 | 7 | ```java 8 | public ArrayList searchRange(TreeNode root, int k1, int k2) { 9 | // write your code here 10 | ArrayList result = new ArrayList(); 11 | if ( root == null ) { 12 | return result; 13 | } 14 | 15 | if ( root.val >= k1 && root.val <= k2 ) { 16 | ArrayList left = searchRange(root.left, k1, root.val-1); 17 | ArrayList right = searchRange(root.right, root.val+1, k2 ); 18 | 19 | result.addAll(left); 20 | result.add(root.val); 21 | result.addAll(right); 22 | } else if ( root.val > k1) { 23 | ArrayList left = searchRange(root.left, k1, k2); 24 | 25 | result.addAll(left); 26 | } else { 27 | ArrayList right = searchRange(root.right, k1, k2); 28 | 29 | result.addAll(right); 30 | } 31 | 32 | return result; 33 | 34 | } 35 | ``` -------------------------------------------------------------------------------- /binary_tree/subtree.md: -------------------------------------------------------------------------------- 1 | #Subtree 2 | 3 | []() 4 | 5 | 題意:給定兩棵樹 T1 與 T2 ,檢查 T2 是否為 T1 的子樹。 6 | 7 | 8 | 解題思路:使用 Divide and Conquer 來解這道題,其中還需要另一個副程式來檢查 以 T1 的根節來遞迴檢查是否相等,首先先檢查以 T1 為根的樹是否含有與 T2 相同的子樹,若不是的話,則再往 T1 的左節點再往下遞迴,再找不到的話,就再往 T1 的右節點找,其程式碼如下: 9 | 10 | ```java 11 | public class Solution { 12 | /** 13 | * @param T1, T2: The roots of binary tree. 14 | * @return: True if T2 is a subtree of T1, or false. 15 | */ 16 | public boolean isSubtree(TreeNode T1, TreeNode T2) { 17 | if (T2 == null) { 18 | return true; 19 | } 20 | 21 | if (T1 == null) { 22 | return false; 23 | } 24 | 25 | return isSameTree(T1, T2) || isSubtree(T1.left, T2) || isSubtree(T1.right, T2); 26 | } 27 | 28 | private boolean isSameTree(TreeNode T1, TreeNode T2) { 29 | if (T1 == null && T2 == null) { 30 | return true; 31 | } 32 | 33 | if (T1 == null || T2 == null || T1.val != T2.val) { 34 | return false; 35 | } 36 | 37 | return isSameTree(T1.left, T2.left) && isSameTree(T1.right, T2.right); 38 | } 39 | } 40 | ``` 41 | 42 | --- 43 | ###Reference 44 | 1. 劍指 Offer 第三章 45 | 2. http://cherylintcode.blogspot.com/2015/06/subtree.html 46 | 3. -------------------------------------------------------------------------------- /binary_tree/template.md: -------------------------------------------------------------------------------- 1 | # Template 2 | 3 | 1. Traversal(DFS) 4 | Build a traverse function and call it in main function 5 | ```java 6 | // preorder example 7 | public void traverse( resultType result, TreeNode node) { 8 | if ( node == null ) { -> condition for leaves 9 | return; 10 | } 11 | result.add(node.val); -> add the value 12 | traverse(result, node.left); 13 | traverse(result, node.right); 14 | } 15 | ``` 16 | 17 | 2. Divide and Conquer (DFS) 18 | 分別去跑,最後再把結果合起來 19 | 20 | ```java 21 | public class Solution { 22 | public ArrayList preorderTraversal(TreeNode root) { 23 | ArrayList result = new ArrayList(); 24 | // null or leaf 25 | if (root == null) { 26 | return result; 27 | } 28 | 29 | // Divide 30 | ArrayList left = preorderTraversal(root.left); 31 | ArrayList right = preorderTraversal(root.right); 32 | 33 | // Conquer 34 | result.add(root.val); 35 | result.addAll(left); 36 | result.addAll(right); 37 | return result; 38 | } 39 | } 40 | ``` 41 | -------------------------------------------------------------------------------- /bit_manipulation.md: -------------------------------------------------------------------------------- 1 | # Bit Manipulation 2 | 3 | -------------------------------------------------------------------------------- /bit_manipulation/flip_bits.md: -------------------------------------------------------------------------------- 1 | # Flip Bits 2 | 3 | [Lintcode](http://www.lintcode.com/en/problem/flip-bits/) 4 | 5 | 題意: 6 | 7 | Determine the number of bits required to flip if you want to convert integer n to integer m. 8 | 9 | Given n = 31 (11111), m = 14 (01110), return 2. 10 | 11 | Note 12 | 13 | Both n and m are 32-bit integers. 14 | 15 | 解題思路: 16 | 17 | 一一比較每個位元,若有不同則count++,需要特別注意的就是正負號的問題。若其中只有一個為負數,則 count 需要再加 1 ,為2 的補數關係。 18 | 19 | ```java 20 | class Solution { 21 | /** 22 | *@param a, b: Two integer 23 | *return: An integer 24 | */ 25 | public static int bitSwapRequired(int a, int b) { 26 | int count = 0; 27 | for (int i = 0; i < 31; i++) { 28 | int aBit = a >> i & 1; 29 | int bBit = b >> i & 1; 30 | if (aBit != bBit) { 31 | count++; 32 | } 33 | } 34 | 35 | if (a < 0 && b < 0) { 36 | return count; 37 | } 38 | if (a < 0 || b < 0) { 39 | count++; 40 | } 41 | return count; 42 | } 43 | }; 44 | ``` -------------------------------------------------------------------------------- /bit_manipulation/number_of_1_bits.md: -------------------------------------------------------------------------------- 1 | # Number of 1 Bits 2 | 3 | [Leetcode](https://leetcode.com/problems/number-of-1-bits/) 4 | 5 | 題意: 6 | 7 | Write a function that takes an unsigned integer and returns the number of 』1' bits it has (also known as the Hamming weight). 8 | 9 | For example, the 32-bit integer 』11' has binary representation ```00000000000000000000000000001011```, so the function should return 3. 10 | 11 | 12 | 解題思路: 13 | 14 | ```java 15 | public class Solution { 16 | // you need to treat n as an unsigned value 17 | public int hammingWeight(int n) { 18 | int count = 0; 19 | while (n != 0) { 20 | count++; 21 | n = n & (n - 1); 22 | } 23 | return count; 24 | } 25 | } 26 | ``` -------------------------------------------------------------------------------- /bit_manipulation/reverse_bits.md: -------------------------------------------------------------------------------- 1 | # Reverse Bits 2 | 3 | [Leetcode](https://leetcode.com/problems/reverse-bits/) 4 | 5 | 題意: 6 | 7 | Reverse bits of a given 32 bits unsigned integer. 8 | 9 | For example, given input 43261596 (represented in binary as **00000010100101000001111010011100**), return 964176192 (represented in binary as **00111001011110000010100101000000**). 10 | 11 | **Follow up:** 12 | 13 | If this function is called many times, how would you optimize it? 14 | 15 | 16 | 解題思路: 17 | 18 | 利用一個count值從31往1到數,來決定取出來的bit要往右shift幾格,程式碼如下: 19 | 20 | ```java 21 | public class Solution { 22 | // you need treat n as an unsigned value 23 | public int reverseBits(int n) { 24 | int sum = 0; 25 | int count = 31; 26 | while (n != 0) { 27 | if ((n & 1) == 1) { 28 | sum += 1 << count; 29 | } 30 | count--; 31 | n >>>= 1; 32 | } 33 | return sum; 34 | } 35 | } 36 | ``` 37 | 38 | --- 39 | ###Reference 40 | 1. https://leetcode.com/discuss/57618/simply-great-performance-java-solution -------------------------------------------------------------------------------- /bst_successor_predecessor.md: -------------------------------------------------------------------------------- 1 | # BST Successor Predecessor 2 | 3 | **Successor** 4 | ``` 5 | public TreeNode successor(TreeNode root, TreeNode p) { 6 | if (root == null) 7 | return null; 8 | 9 | if (root.val <= p.val) { 10 | return successor(root.right, p); 11 | } else { 12 | TreeNode left = successor(root.left, p); 13 | return (left != null) ? left : root; 14 | } 15 | } 16 | ``` 17 | **Predecessor** 18 | ``` 19 | public TreeNode predecessor(TreeNode root, TreeNode p) { 20 | if (root == null) 21 | return null; 22 | 23 | if (root.val >= p.val) { 24 | return predecessor(root.left, p); 25 | } else { 26 | TreeNode right = predecessor(root.right, p); 27 | return (right != null) ? right : root; 28 | } 29 | } 30 | ``` 31 | --- 32 | ###Refernce 33 | 1. https://leetcode.com/discuss/59787/share-my-java-recursive-solution -------------------------------------------------------------------------------- /bubble-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/bubble-sort.gif -------------------------------------------------------------------------------- /design.md: -------------------------------------------------------------------------------- 1 | # Design 2 | 3 | -------------------------------------------------------------------------------- /design/amazon.md: -------------------------------------------------------------------------------- 1 | # Amazon 2 | 3 | 1. design library, track records of books, CDs (cc150) 4 | 5 | 2. chess game [Link 1](http://amitcodes.com/2014/02/04/object-oriented-design-for-chess-game/) [Link 2](http://stackoverflow.com/questions/4168002/object-oriented-design-for-a-chess-game) 6 | 7 | 3. hotel management system (similar to online reader system in cc150, libary contains rooms, active room, active user) 8 | 9 | 4. online booking system (cc150) 10 | 11 | 5. animal kingdom, animal zoo 12 | 13 | 6. file system (cc150) 14 | 15 | 7. deck (cc150, or deck.java) 16 | 17 | 8. wallet 18 | 19 | 9. design hashtable (cc150) -------------------------------------------------------------------------------- /design/deck.md: -------------------------------------------------------------------------------- 1 | # Deck 2 | 3 | ```java 4 | 5 | public enum Suit { 6 | Club (0), Diamond (1), Heart (2), Spade (3); 7 | private int value; 8 | private Suit(int v) { 9 | this.value = v; 10 | } 11 | 12 | public int getValue() { 13 | return this.value; 14 | } 15 | 16 | public static Suit getSuitFromValue(int value) {}; 17 | } 18 | 19 | public class Deck { 20 | private ArrayList cards; 21 | private int dealltIndex = 0; 22 | 23 | public void setDeckOfCards(ArrayList deckOfCards) {} 24 | 25 | public void shuffle() {} 26 | public int remainingCards() { 27 | return cards.size() - dealtIndex; 28 | } 29 | 30 | public T[] dealHand(int number) {} 31 | public T dealCard() {} 32 | } 33 | 34 | public abstract class Card { 35 | private boolean available = true; 36 | 37 | protected int faceValue; 38 | protected Suit suit; 39 | 40 | public Card(int c, Suit s) { 41 | faceValue = c; 42 | suit = s; 43 | } 44 | } 45 | 46 | public class Hand { 47 | protected ArrayList cards = new ArrayList(); 48 | 49 | public int score() { 50 | int score = 0; 51 | for (T card : cards) { 52 | score += card.value(); 53 | } 54 | 55 | return score; 56 | } 57 | 58 | public void addCard(T card) { 59 | cards.add(card); 60 | } 61 | } 62 | 63 | 64 | 65 | 66 | ``` -------------------------------------------------------------------------------- /design/hashfunction.md: -------------------------------------------------------------------------------- 1 | # HashFunction 2 | 3 | ```java 4 | 5 | 6 | public class Hash { 7 | private final int MAX_SIZE = 10; 8 | List>[] items; 9 | 10 | public Hash() { 11 | items = (LinkedList>[]) new LinkedList[MAX_SIZE]; 12 | } 13 | 14 | public int hashCodeOfKey(K key) { 15 | return key.toString().length() % items.length; 16 | } 17 | 18 | public void put(K key, V value) { 19 | int x = hashCodeOfKey(key); 20 | if (items[x] == null) { 21 | items[x] = new Linked>(); 22 | } 23 | 24 | LinkedList> collided = items[x]; 25 | 26 | for (Cell> c : collided) { 27 | if (c.equivalent(key)) { 28 | collided.remove(c); 29 | break; 30 | } 31 | } 32 | 33 | Cell cell = new Cell(key, value); 34 | collided.add(cell); 35 | } 36 | 37 | public V get(K key) { 38 | int x = hashCodeOfKey(key); 39 | if (items[x] == null) { 40 | return null; 41 | } 42 | LinkedList> collided = items[x]; 43 | for (Cell c : collided) { 44 | if (c.equivalent(key)) { 45 | return c.getValue(); 46 | } 47 | } 48 | 49 | return null; 50 | } 51 | } 52 | 53 | public class Cell { 54 | private K key; 55 | private V value; 56 | public Cell(K key, V value) { 57 | this.key = key; 58 | this.value = value; 59 | } 60 | 61 | public boolean equivalent(Cell c) { 62 | return equivalent(c.getKey()); 63 | } 64 | 65 | public boolean equivalent(K k) { 66 | return key.equals(k); 67 | } 68 | 69 | public K getKey() { return key;} 70 | public V getValue() { return value;} 71 | } 72 | ``` -------------------------------------------------------------------------------- /difficult_problems.md: -------------------------------------------------------------------------------- 1 | # Difficult Problems 2 | 3 | -------------------------------------------------------------------------------- /difficult_problems/binary_tree_upside_down.md: -------------------------------------------------------------------------------- 1 | # Binary Tree Upside Down 2 | 3 | [Leetcode](https://leetcode.com/problems/binary-tree-upside-down/) 4 | 5 | 6 | 題意: 7 | 8 | Given a binary tree where all the right nodes are either leaf nodes with a sibling (a left node that shares the same parent node) or empty, flip it upside down and turn it into a tree where the original right nodes turned into left leaf nodes. Return the new root. 9 | 10 | For example: 11 | Given a binary tree {1,2,3,4,5}, 12 | ``` 13 | 1 14 | / \ 15 | 2 3 16 | / \ 17 | 4 5 18 | ``` 19 | return the root of the binary tree [4,5,2,#,#,3,1]. 20 | ``` 21 | 4 22 | / \ 23 | 5 2 24 | / \ 25 | 3 1 26 | ``` 27 | 28 | 29 | 解題思路: 30 | 31 | 目前還是搞不太清楚怎弄,先記錄下來。 32 | 33 | [分析] 34 | 起始對於每一個節點,相應的操作為: 35 | - p.left = parent.right; 36 | - p.right = parent; 37 | - 38 | ```java 39 | /** 40 | * Definition for a binary tree node. 41 | * public class TreeNode { 42 | * int val; 43 | * TreeNode left; 44 | * TreeNode right; 45 | * TreeNode(int x) { val = x; } 46 | * } 47 | */ 48 | public class Solution { 49 | public TreeNode upsideDownBinaryTree(TreeNode root) { 50 | TreeNode p = root; 51 | TreeNode parent = null; 52 | TreeNode parentRight = null; 53 | while (p != null) { 54 | TreeNode left = p.left; 55 | p.left = parentRight; 56 | parentRight = p.right; 57 | p.right = parent; 58 | parent = p; 59 | p = left; 60 | } 61 | return parent; 62 | } 63 | } 64 | ``` 65 | 66 | --- 67 | ###Reference 68 | 1. http://www.danielbit.com/blog/puzzle/leetcode/leetcode-binary-tree-upside-down 69 | 2. http://blog.csdn.net/whuwangyi/article/details/43186045 -------------------------------------------------------------------------------- /difficult_problems/count_univalue_subtrees.md: -------------------------------------------------------------------------------- 1 | # Count Univalue Subtrees 2 | 3 | [Leetcode](https://leetcode.com/problems/count-univalue-subtrees/) 4 | 5 | 題意: 6 | 7 | 找出所有subtree值全一樣的個數。 8 | 9 | 10 | Given a binary tree, count the number of uni-value subtrees. 11 | 12 | A Uni-value subtree means all nodes of the subtree have the same value. 13 | 14 | For example: 15 | Given binary tree, 16 | ``` 17 | 5 18 | / \ 19 | 1 5 20 | / \ \ 21 | 5 5 5 22 | ``` 23 | return 4. 24 | 25 | 26 | 解題思路: 27 | 28 | 使用遞迴去作,不斷的把root的val傳下去作比較,一但比到錯的,則返回false。 29 | 30 | ```java 31 | /** 32 | * Definition for a binary tree node. 33 | * public class TreeNode { 34 | * int val; 35 | * TreeNode left; 36 | * TreeNode right; 37 | * TreeNode(int x) { val = x; } 38 | * } 39 | */ 40 | public class Solution { 41 | public int countUnivalSubtrees(TreeNode root) { 42 | if (root == null) { 43 | return 0; 44 | } 45 | int[] counter = new int[1]; 46 | count(root, counter, root.val); 47 | return counter[0]; 48 | } 49 | 50 | private boolean count(TreeNode root, int[] counter, int val) { 51 | if (root == null) { 52 | return true; 53 | } 54 | boolean left = count(root.left, counter, root.val); 55 | boolean right = count(root.right, counter, root.val); 56 | 57 | if (left && right) { 58 | counter[0]++; 59 | } 60 | 61 | return left && right && root.val == val; 62 | } 63 | 64 | } 65 | ``` 66 | --- 67 | ###Reference 68 | 1. https://leetcode.com/discuss/55213/my-ac-java-code -------------------------------------------------------------------------------- /difficult_problems/shortest_palindrome.md: -------------------------------------------------------------------------------- 1 | # Shortest Palindrome 2 | 3 | [Leetcode](https://leetcode.com/problems/shortest-palindrome/) 4 | 5 | 題意: 6 | 7 | Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. Find and return the shortest palindrome you can find by performing this transformation. 8 | 9 | For example: 10 | 11 | Given "aacecaaa", return "aaacecaaa". 12 | 13 | Given "abcd", return "dcbabcd". 14 | 15 | 解題思路: 16 | 17 | 18 | ```java 19 | public class Solution { 20 | public String shortestPalindrome(String s) { 21 | if (s == null || s.length() == 0) { 22 | return ""; 23 | } 24 | 25 | int len = s.length(); 26 | int left; 27 | int right; 28 | int maxLen = 0; 29 | for (int i = 0; i < len;) { 30 | 每次從string的中心往兩旁延伸 31 | left = right = i; 32 | 33 | // 往右延伸一樣的數 34 | while (right < len - 1 && s.charAt(right) == s.charAt(right + 1)) { 35 | right++; 36 | } 37 | 38 | i = right + 1; 39 | 40 | 向左右延伸 41 | while (left > 0 && right < len - 1 && s.charAt(left - 1) == s.charAt(right + 1)) { 42 | left--; 43 | right++; 44 | } 45 | 46 | if (left == 0 && maxLen < right + 1) { 47 | maxLen = right + 1; 48 | } 49 | } 50 | 51 | String prefix = new StringBuilder(s.substring(maxLen)).reverse().toString(); 52 | 53 | return prefix + s; 54 | } 55 | } 56 | ``` -------------------------------------------------------------------------------- /dynamic_programming.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/dynamic_programming.md -------------------------------------------------------------------------------- /dynamic_programming/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/dynamic_programming/.DS_Store -------------------------------------------------------------------------------- /dynamic_programming/climbing_stairs.md: -------------------------------------------------------------------------------- 1 | # Climbing Stairs 2 | 3 | [Leetcode](https://leetcode.com/problems/climbing-stairs/) 4 | 5 | 題意: 6 | 7 | You are climbing a stair case. It takes n steps to reach to the top. 8 | 9 | Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? 10 | 11 | 解題思路: 12 | 13 | 其實就是fibonacci number,可用遞迴作法,也可以用動規來幫簡化複雜度 14 | 15 | >res[i] = res[i - 1] + res[i - 2] 16 | 17 | 其程式碼如下: 18 | 19 | ```java 20 | public class Solution { 21 | public int climbStairs(int n) { 22 | if (n <= 2) { 23 | return n; 24 | } 25 | 26 | int[] result = new int[n]; 27 | result[0] = 1; 28 | result[1] = 2; 29 | 30 | for (int i = 2; i < n; i++) { 31 | result[i] = result[i-1] + result[i-2]; 32 | } 33 | return result[n-1]; 34 | } 35 | } 36 | ``` -------------------------------------------------------------------------------- /dynamic_programming/coin_change.md: -------------------------------------------------------------------------------- 1 | # Coin Change 2 | 3 | [Leetcode](https://leetcode.com/problems/coin-change/) 4 | 5 | 題意: 6 | 7 | You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1. 8 | 9 | Example 1: 10 | coins = [1, 2, 5], amount = 11 11 | return 3 (11 = 5 + 5 + 1) 12 | 13 | Example 2: 14 | coins = [2], amount = 3 15 | return -1. 16 | 17 | Note: 18 | You may assume that you have an infinite number of each kind of coin. 19 | 20 | 解題思路: 21 | 22 | 使用dp來解 23 | 24 | > dp[i] 代表目前現有的coins能換成i的最少張數 25 | > dp[i] = min(dp[i - coin[j]) + 1; 26 | 27 | ```java 28 | public class Solution { 29 | public int coinChange(int[] coins, int amount) { 30 | 31 | if (coins == null || coins.length == 0 || amount == 0) { 32 | return 0; 33 | } 34 | 35 | int[] dp = new int[amount + 1]; 36 | dp[0] = 0; 37 | for (int i = 1; i <= amount; i++) { 38 | 39 | dp[i] = Integer.MAX_VALUE; 40 | 41 | } 42 | 43 | for (int i = 1; i <= amount; i++) { 44 | for (int j = 0; j < coins.length; j++) { 45 | //要注意是否該dp無法換,即等於Integer.MAX_VALUE 46 | if (coins[j] > i || dp[i - coins[j]] == Integer.MAX_VALUE) { 47 | continue; 48 | } 49 | 50 | int cur = dp[i - coins[j]] + 1; 51 | dp[i] = Math.min(dp[i], cur); 52 | } 53 | } 54 | 55 | return (dp[amount] == Integer.MAX_VALUE) ? -1 : dp[amount]; 56 | } 57 | } 58 | ``` -------------------------------------------------------------------------------- /dynamic_programming/flip_game.md: -------------------------------------------------------------------------------- 1 | # Flip Game 2 | 3 | [Leetcode](https://leetcode.com/problems/flip-game/) 4 | 5 | 6 | 題意: 7 | 8 | You are playing the following Flip Game with your friend: Given a string that contains only these two characters: + and -, you and your friend take turns to flip two consecutive "++" into "--". The game ends when a person can no longer make a move and therefore the other person will be the winner. 9 | 10 | Write a function to compute all possible states of the string after one valid move. 11 | 12 | For example, given s = "++++", after one move, it may become one of the following states: 13 | ``` 14 | [ 15 | "--++", 16 | "+--+", 17 | "++--" 18 | ] 19 | ``` 20 | If there is no valid move, return an empty list []. 21 | 22 | Show Company Tags 23 | Show Tags 24 | Show Similar Problems 25 | 26 | 27 | 28 | 解題思路: 29 | 30 | 找出所有連續兩個+的子字串,接著把它們改掉存到res中即可。 31 | 32 | ```java 33 | public class Solution { 34 | public List generatePossibleNextMoves(String s) { 35 | List res = new ArrayList(); 36 | for (int i = 0; i < s.length() - 1; i++) { 37 | if (s.charAt(i) == '+' && s.charAt(i + 1) == '+') { 38 | String str = s.substring(0, i) + "--" + s.substring(i + 2, s.length()); 39 | res.add(str); 40 | } 41 | } 42 | 43 | return res; 44 | } 45 | } 46 | ``` -------------------------------------------------------------------------------- /dynamic_programming/flip_game_ii.md: -------------------------------------------------------------------------------- 1 | # Flip Game II 2 | 3 | [Leetcode](https://leetcode.com/problems/flip-game-ii/) 4 | 5 | 6 | 題意: 7 | 8 | You are playing the following Flip Game with your friend: Given a string that contains only these two characters: + and -, you and your friend take turns to flip two consecutive "++" into "--". The game ends when a person can no longer make a move and therefore the other person will be the winner. 9 | 10 | Write a function to determine if the starting player can guarantee a win. 11 | 12 | For example, given s = "++++", return true. The starting player can guarantee a win by flipping the middle "++" to become "+--+". 13 | 14 | Follow up: 15 | Derive your algorithm's runtime complexity. 16 | 17 | 18 | 解題思路: 19 | 20 | 使用dfs的方式遞迴去作,一旦找到一個方式能讓對手輸的話,則返回true,否則返回false。 21 | 22 | ```java 23 | public class Solution { 24 | public boolean canWin(String s) { 25 | if (s == null || s.length() < 2) { 26 | return false; 27 | } 28 | 29 | for (int i = 0; i < s.length() - 1; i++) { 30 | if (s.charAt(i) == '+' && s.charAt(i + 1) == '+') { 31 | String str = s.substring(0, i) + "--" + s.substring(i + 2); 32 | 33 | if (!canWin(str)) { 34 | return true; 35 | } 36 | } 37 | } 38 | 39 | return false; 40 | } 41 | } 42 | ``` -------------------------------------------------------------------------------- /dynamic_programming/longest_common_substring.md: -------------------------------------------------------------------------------- 1 | #Longest Common Substring 2 | 3 | 4 | [原題網址](http://www.lintcode.com/en/problem/longest-common-substring/) 5 | 6 | 解法:相同斜上再加一,不同則歸零,因不同則歸零,所以不需要初始化第0行與第0列。 7 | 8 | ```java 9 | public int longestCommonSubstring(String A, String B) { 10 | 11 | if (A.length() == 0 || B.length() == 0) { 12 | return 0; 13 | } 14 | 15 | int[][] result = new int[A.length() + 1][B.length() + 1]; 16 | 17 | int max = 0; 18 | for (int i = 1; i <= A.length(); i++) { 19 | for (int j = 1; j <= B.length(); j++) { 20 | if (A.charAt(i-1) == B.charAt(j-1)) { 21 | result[i][j] = result[i-1][j-1] + 1; 22 | if (result[i][j] > max) { 23 | max = result[i][j]; 24 | } 25 | } else { 26 | result[i][j] = 0; 27 | } 28 | } 29 | } 30 | 31 | return max; 32 | } 33 | ``` 34 | 35 | >Time Complexity:O(n^2) -------------------------------------------------------------------------------- /dynamic_programming/minimum_path_sum.md: -------------------------------------------------------------------------------- 1 | # Minimum Path Sum 2 | 3 | [Minimum Path Sum](https://leetcode.com/problems/minimum-path-sum/) 4 | 5 | 題意: 6 | 7 | Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path. 8 | 9 | Note: You can only move either down or right at any point in time. 10 | 11 | 解題思路: 12 | 13 | 使用dp加滾動陣列來作,程式碼如下: 14 | 15 | >dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j] 16 | 17 | ```java 18 | public class Solution { 19 | public int minPathSum(int[][] grid) { 20 | if (grid == null || grid.length == 0) { 21 | return 0; 22 | } 23 | 24 | int rows = grid.length; 25 | int cols = grid[0].length; 26 | int[] dp = new int[cols]; 27 | dp[0] = grid[0][0]; 28 | for (int i = 1; i < cols; i++) { 29 | dp[i] = dp[i - 1] + grid[0][i]; 30 | } 31 | 32 | for (int i = 1; i < rows; i++) { 33 | dp[0] = dp[0] + grid[i][0]; 34 | for (int j = 1; j < cols; j++) { 35 | dp[j] = Math.min(dp[j], dp[j - 1]) + grid[i][j]; 36 | } 37 | } 38 | 39 | return dp[cols - 1]; 40 | } 41 | } 42 | ``` -------------------------------------------------------------------------------- /dynamic_programming/nim_game.md: -------------------------------------------------------------------------------- 1 | # Nim Game 2 | 3 | [Leetcode](https://leetcode.com/problems/nim-game/) 4 | 5 | 題意: 6 | 7 | You are playing the following Nim Game with your friend: There is a heap of stones on the table, each time one of you take turns to remove 1 to 3 stones. The one who removes the last stone will be the winner. You will take the first turn to remove the stones. 8 | 9 | Both of you are very clever and have optimal strategies for the game. Write a function to determine whether you can win the game given the number of stones in the heap. 10 | 11 | For example, if there are 4 stones in the heap, then you will never win the game: no matter 1, 2, or 3 stones you remove, the last stone will always be removed by your friend. 12 | 13 | 14 | 解題思路: 15 | 16 | 其實只有在n為4的倍數時先手才會輸,其他不管怎麼樣,先手都會贏,因此只要判斷是否為4的倍數即可,程式碼如下: 17 | 18 | ```java 19 | public class Solution { 20 | public boolean canWinNim(int n) { 21 | if (n % 4 == 0) { 22 | return false; 23 | } else { 24 | return true; 25 | } 26 | } 27 | } 28 | ``` -------------------------------------------------------------------------------- /dynamic_programming/paint_fence.md: -------------------------------------------------------------------------------- 1 | # Paint Fence 2 | 3 | [Leetcode](https://leetcode.com/problems/paint-fence/) 4 | 5 | 題意: 6 | 7 | There is a fence with n posts, each post can be painted with one of the k colors. 8 | 9 | You have to paint all the posts such that **no more than two adjacent fence posts have the same color**. 10 | 11 | Return the total number of ways you can paint the fence. 12 | 13 | Note: 14 | n and k are non-negative integers. 15 | 16 | 17 | 解題思路: 18 | 19 | 題目要看清楚,一開始理解錯誤,主要是最多兩個相鄰的板子可以不同顏色。 20 | 21 | 這題可以使用dp來作,主要使用了兩個編數來紀錄, 22 | 23 | >LastD:紀錄最後兩塊板子顏色不同的情況數 24 | 25 | >LastD = (k - 1) * (lastS + lastD) 因為最後兩塊板子顏色可以不同,因此最新那塊板子有k - 1個顏色可以選擇,加上到數第二塊與第三塊也有不同情況分別為LastS與LastD。 26 | 27 | >LastS:紀錄最後兩塊板子顏色相同的情況數,因為最後兩塊相同,所以只要把上一層的LastD assign即可。 28 | 29 | ```java 30 | public class Solution { 31 | public int numWays(int n, int k) { 32 | // 如果板子小於一塊,或是沒半個顏色,則直接返回n * k 33 | if (n <= 1 || k == 0) { 34 | return n * k; 35 | } 36 | 37 | int lastS = k; // 最後兩塊板子顏色相同 38 | int lastD = k * (k - 1); // 最後兩塊板子顏色不同 39 | for (int i = 2; i < n; i++) { 40 | int tempD = (k - 1) * (lastS + lastD); // 最後兩塊板子顏色不同,因此最新那塊板子有k - 1個顏色可選 41 | lastS = lastD; // 最後兩塊板子顏色相同,因此直接取lastD 42 | lastD = tempD; 43 | } 44 | 45 | return lastS + lastD; // 最後把兩個情況加總即可 46 | } 47 | } 48 | ``` 49 | 50 | --- 51 | ###Reference 52 | 1. http://blog.csdn.net/pointbreak1/article/details/48779787 -------------------------------------------------------------------------------- /dynamic_programming/paint_house.md: -------------------------------------------------------------------------------- 1 | # Paint House 2 | 3 | [Leetcode](https://leetcode.com/problems/paint-house/) 4 | 5 | 6 | 題意: 7 | 8 | There are a row of n houses, each house can be painted with one of the three colors: red, blue or green. The cost of painting each house with a certain color is different. You have to paint all the houses such that no two adjacent houses have the same color. 9 | 10 | The cost of painting each house with a certain color is represented by a n x 3 cost matrix. For example, costs[0][0] is the cost of painting house 0 with color red; costs[1][2] is the cost of painting house 1 with color green, and so on... Find the minimum cost to paint all houses. 11 | 12 | Note: 13 | All costs are positive integers. 14 | 15 | 16 | 解題思路: 17 | 18 | 19 | >dp[i][0] = costs[i][0] + min(costs[i - 1][1], costs[i - 1][2]) 20 | 21 | >表示第i個房子上紅色的最小成本,因為第i個房子上了紅色,所以他之前的房子只可能上綠色與藍色。 22 | 23 | ```java 24 | public int minCost(int[][] costs) { 25 | if(costs != null && costs.length == 0) return 0; 26 | for(int i = 1; i < costs.length; i++){ 27 | // 涂第一種顏色的話,上一個房子就不能涂第一種顏色,這樣我們要在上一個房子的第二和第三個顏色的最小開銷中找最小的那個加上 28 | costs[i][0] = costs[i][0] + Math.min(costs[i - 1][1], costs[i - 1][2]); 29 | // 涂第二或者第三種顏色同理 30 | costs[i][1] = costs[i][1] + Math.min(costs[i - 1][0], costs[i - 1][2]); 31 | costs[i][2] = costs[i][2] + Math.min(costs[i - 1][0], costs[i - 1][1]); 32 | } 33 | // 返回涂三種顏色中開銷最小的那個 34 | return Math.min(costs[costs.length - 1][0], Math.min(costs[costs.length - 1][1], costs[costs.length - 1][2])); 35 | } 36 | ``` 37 | 38 | --- 39 | ###Refernce 40 | 1. http://massivealgorithms.blogspot.com/2015/06/leetcode-256-painting-house-neverlandly.html -------------------------------------------------------------------------------- /dynamic_programming/triangle.md: -------------------------------------------------------------------------------- 1 | #Triangle 2 | [原題網址](http://www.lintcode.com/en/problem/triangle/) 3 | 4 | ```java 5 | public int minimumTotal(ArrayList> triangle) { 6 | 7 | if (triangle == null || triangle.get(0) == null | triangle.get(0).get(0) == null) { 8 | return 0; 9 | } 10 | 11 | int size = triangle.size(); 12 | int[][] res = new int[size][size]; 13 | 14 | for (int i = 0; i < size; i++) { 15 | res[size - 1][i] = triangle.get(size-1).get(i); 16 | } 17 | 18 | for (int i = size - 2; i >= 0; i--) { 19 | ArrayList curList = triangle.get(i); 20 | for (int j = 0; j < curList.size(); j++) { 21 | res[i][j] = Math.min(res[i+1][j], res[i+1][j+1]) + curList.get(j); 22 | } 23 | } 24 | 25 | return res[0][0]; 26 | } 27 | ``` 28 | >Time Complexity:O(N) -------------------------------------------------------------------------------- /dynamic_programming/unique_paths.md: -------------------------------------------------------------------------------- 1 | # Unique Paths 2 | 3 | [Leetcode](https://leetcode.com/problems/unique-paths/) 4 | 5 | 題意: 6 | 7 | A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). 8 | 9 | The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). 10 | 11 | How many possible unique paths are there? 12 | 13 | 解題思路: 14 | 15 | 使用一維陣列的dp來解 16 | 17 | ```java 18 | public class Solution { 19 | public int uniquePaths(int m, int n) { 20 | if (m < 0 || n < 0) { 21 | return 0; 22 | } 23 | 24 | int[] res = new int[n]; 25 | res[0] = 1; 26 | for (int i = 0; i < m; i++) { 27 | for (int j = 1; j < n; j++) { 28 | res[j] += res[j - 1]; 29 | } 30 | } 31 | 32 | return res[n - 1]; 33 | } 34 | } 35 | ``` 36 | 37 | 使用二維陣列來解 38 | 39 | ```java 40 | public class Solution { 41 | public int uniquePaths(int m, int n) { 42 | if (m == 0 || n == 0) { 43 | return 1; 44 | } 45 | 46 | int[][] count = new int[m][n]; 47 | for (int i = 0; i < m; i++) { 48 | count[i][0] = 1; 49 | } 50 | 51 | for (int i = 1; i < n; i++) { 52 | count[0][i] = 1; 53 | } 54 | 55 | for (int i = 1; i < m; i++) { 56 | for (int j = 1; j < n; j++) { 57 | count[i][j] = count[i - 1][j] + count[i][j - 1]; 58 | } 59 | } 60 | 61 | return count[m - 1][n - 1]; 62 | } 63 | } 64 | ``` -------------------------------------------------------------------------------- /dynamic_programming/word_break.md: -------------------------------------------------------------------------------- 1 | #Word Break 2 | 3 | ```java 4 | public class Solution { 5 | /** 6 | * @param s: A string s 7 | * @param dict: A dictionary of words dict 8 | */ 9 | public boolean wordBreak(String s, Set dict) { 10 | 11 | if (s == null || s.length() == 0) { 12 | return true; 13 | } 14 | 15 | boolean[] res = new boolean[s.length() + 1]; 16 | Arrays.fill(res, false); 17 | res[0] = true; 18 | int max = getMaxLength(dict); 19 | 20 | for (int i = 1; i <= s.length(); i++) { 21 | //取j=1與j<=i是因為java substring吃不到第i個char 22 | for (int j = 1; j <= i && j <= max; j++) { 23 | if (!res[i - j]) { 24 | continue; 25 | } 26 | String curString = s.substring(i - j, i); 27 | if (dict.contains(curString)) { 28 | //有則break省時間 29 | res[i] = true; 30 | break; 31 | } 32 | } 33 | } 34 | 35 | return res[s.length()]; 36 | } 37 | 38 | //會超時,因此先算好dict裡面最長的字串是哪個 39 | private int getMaxLength(Set dict) { 40 | 41 | int max = 0; 42 | for (String s : dict) { 43 | if (max < s.length()) { 44 | max = s.length(); 45 | } 46 | } 47 | 48 | return max; 49 | } 50 | } 51 | ``` -------------------------------------------------------------------------------- /graph.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/graph.md -------------------------------------------------------------------------------- /graph/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/graph/.DS_Store -------------------------------------------------------------------------------- /graph/meeting_room.md: -------------------------------------------------------------------------------- 1 | # Meeting Room 2 | 3 | [Leetcode](https://leetcode.com/problems/meeting-rooms/) 4 | 5 | 題意: 6 | 7 | Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), determine if a person could attend all meetings. 8 | 9 | For example, 10 | Given [[0, 30],[5, 10],[15, 20]], 11 | return false. 12 | 13 | 解題思路: 14 | 15 | 排序後一一比較是否有重疊即可,時間複雜度O(nlogn),程式碼如下: 16 | 17 | ```java 18 | /** 19 | * Definition for an interval. 20 | * public class Interval { 21 | * int start; 22 | * int end; 23 | * Interval() { start = 0; end = 0; } 24 | * Interval(int s, int e) { start = s; end = e; } 25 | * } 26 | */ 27 | public class Solution { 28 | 29 | public class IntervalComparator implements Comparator { 30 | @Override 31 | public int compare (Interval iOne, Interval iTwo) { 32 | if (iOne.start != iTwo.start) { 33 | return iOne.start - iTwo.start; 34 | } else { 35 | return iOne.end - iTwo.end; 36 | } 37 | } 38 | } 39 | public boolean canAttendMeetings(Interval[] intervals) { 40 | if (intervals == null || intervals.length == 0) { 41 | return true; 42 | } 43 | Arrays.sort(intervals, new IntervalComparator()); 44 | for (int i = 1; i < intervals.length; i++) { 45 | if (intervals[i - 1].end > intervals[i].start) { 46 | return false; 47 | } 48 | } 49 | return true; 50 | } 51 | } 52 | ``` -------------------------------------------------------------------------------- /graph/number_of_connected_components_in_an_undirected_gr.md: -------------------------------------------------------------------------------- 1 | # Number of Connected Components in an Undirected Graph 2 | 3 | [Leetcode](https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph/) 4 | 5 | 題意: 6 | 7 | 8 | 解題思路: 9 | 10 | 11 | 可以使用dfs,bfs,或是union & find來解, 在此我們先用union & find來解。 12 | 13 | 1. 先初始化每個節點的父親是自己 14 | 2. 不斷的把相連的兩個點作union 15 | 3. 把father的數量算出來即可 16 | 17 | 18 | ```java 19 | public class Solution { 20 | 21 | int[] father; 22 | public int countComponents(int n, int[][] edges) { 23 | father = new int[n]; 24 | 25 | for (int i = 0; i < n; i++) { 26 | father[i] = i; 27 | } 28 | 29 | for (int i = 0; i < edges.length; i++) { 30 | union(edges[i][0], edges[i][1]); 31 | } 32 | 33 | Set set = new HashSet(); 34 | for (int i = 0; i < n; i++) { 35 | set.add(find(i)); 36 | } 37 | 38 | return set.size(); 39 | 40 | } 41 | 42 | 43 | private int find(int node) { 44 | if (father[node] == node) { 45 | return node; 46 | } 47 | 48 | while (father[node] != node) { 49 | node = father[father[node]]; 50 | } 51 | 52 | return node; 53 | } 54 | 55 | private int union(int nodeOne, int nodeTwo) { 56 | int fatherOne = find(nodeOne); 57 | int fatherTwo = find(nodeTwo); 58 | if (fatherOne != fatherTwo) { 59 | father[fatherOne] = fatherTwo; 60 | } 61 | 62 | return fatherTwo; 63 | } 64 | } 65 | ``` 66 | 67 | --- 68 | ###Reference 69 | 1. https://leetcode.com/discuss/76508/ac-java-code-union-find -------------------------------------------------------------------------------- /heap.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/heap.md -------------------------------------------------------------------------------- /heap/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/heap/.DS_Store -------------------------------------------------------------------------------- /heap/heapify.md: -------------------------------------------------------------------------------- 1 | #Heapify 2 | 3 | [原題連結](http://www.lintcode.com/en/problem/heapify/) 4 | 5 | 題意:把任何一陣列,經過heapify後,使得陣列滿足堆(heap)的條件,即根節點必定小於或大於所有左右子樹的節點。 6 | 7 | 解題思路:因葉節點無法作sift down,從最小的非葉子節點開始,從後面往前一次作sift down操作,不斷的確認下層保持堆的特性。 8 | 9 | 10 | 對於一個有n節點的樹,其葉節點至少有n/2 -1個。 11 | 12 | ```java 13 | public class Solution { 14 | /** 15 | * @param A: Given an integer array 16 | * @return: void 17 | */ 18 | public void heapify(int[] A) { 19 | for (int i = A.length / 2; i >= 0; i--) { 20 | siftdown(A, i); 21 | } 22 | } 23 | 24 | private void siftdown(int[] A, int k) { 25 | int smallest = k; 26 | int len = A.length; 27 | //k代表是root,接著不斷拿root去與左右子樹的root比,若子樹的值較小, 28 | //則與k交換,接著k指向到被交換的點,就是不斷去追縱一開始的ROOT 29 | //請注意,比的是值,smallest紀錄的是當前最小值的index 30 | while ( k < len) { 31 | if (k * 2 + 1 < len && A[k * 2 + 1] < A[smallest]) { 32 | smallest = k * 2 + 1; 33 | } 34 | if (k * 2 + 2 < len && A[k * 2 + 2] < A[smallest]) { 35 | smallest = k * 2 + 2; 36 | } 37 | if (smallest == k) { 38 | break; 39 | } 40 | 41 | int temp = A[k]; 42 | A[k] = A[smallest]; 43 | A[smallest] = temp; 44 | k = smallest; 45 | } 46 | } 47 | } 48 | ``` -------------------------------------------------------------------------------- /high_frequency.md: -------------------------------------------------------------------------------- 1 | # 高頻題 2 | 3 | Sum 大集合 4 | 5 | 2 Sum 6 | 7 | 3 Sum 8 | 9 | 3 Sum closest 10 | 11 | 4 Sum 12 | 13 | k Sum 14 | 15 | -------------------------------------------------------------------------------- /high_frequency/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/high_frequency/.DS_Store -------------------------------------------------------------------------------- /high_frequency/3sum_closest_md.md: -------------------------------------------------------------------------------- 1 | # 3 Sum Closest 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/3-sum-closest/) 4 | 5 | 題意:給於一個陣列,與一個目標值,找出陣列中任三元素和最接近目標值 6 | 7 | 解題思路:類似 3 Sum,需要不斷檢查元素和與目標值的差值,若較小則更新結果。需要注意的是移動前後指針時,只需移動其中之一,因是找最接近的,如果兩個指針都移動的話,可能會遺漏掉可能的結果,程式碼如下: 8 | 9 | 10 | ```java 11 | public int threeSumClosest(int[] numbers ,int target) { 12 | 13 | if (numbers == null || numbers.length == 0) { 14 | return 0; 15 | } 16 | 17 | // 解法類似3sum,只是需要用兩個變數來判斷最接近的值, 18 | // 固定一點i,接著後面的數組用雙指針來一一比對 19 | Arrays.sort(numbers); 20 | int minDiff = Integer.MAX_VALUE; 21 | int result = 0; 22 | 23 | for (int i = 0; i < numbers.length - 2; i++) { 24 | 25 | int start = i + 1; 26 | int end = numbers.length - 1;; 27 | 28 | while (start < end) { 29 | 30 | int curSum = numbers[i] + numbers[start] + numbers[end]; 31 | int diff = Math.abs(target - curSum); 32 | 33 | if (diff < minDiff) { 34 | result = curSum; 35 | minDiff = diff; 36 | } 37 | 38 | // 只移動單一pointer,與3Sum不同,因此題是找最接近的, 39 | // 如果兩個pointer皆移動的話,可能會遺漏可能的結果。 40 | if (curSum > target) { 41 | end--; 42 | } else { 43 | start++; 44 | } 45 | } 46 | } 47 | 48 | return result; 49 | } 50 | ``` -------------------------------------------------------------------------------- /high_frequency/best_time_to_buy_and_sell_stock.md: -------------------------------------------------------------------------------- 1 | # Best Time to Buy and Sell Stock 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/best-time-to-buy-and-sell-stock/) 4 | 5 | 題意:給定一個陣列,陣列中每個元素代表著股價,假設只能買賣股票一次,找出最大的獲利值 6 | 7 | 解題思路:這題其實是 Maximum Subarray 的變形,在這個程式,我們只要利用一個minsum變數來記錄最小的值(逢低買進),接著如果能創造更高的獲利,則更新獲利值。 8 | 9 | ```java 10 | public int maxProfit(int[] prices) { 11 | if (prices == null || prices.length <= 1) { 12 | return 0; 13 | } 14 | int maxDiff = prices[1] - prices[0]; 15 | int minValue = prices[0]; 16 | for (int i = 1; i < prices.length; i++) { 17 | if (prices[i] - minValue > maxDiff) { 18 | maxDiff = prices[i] - minValue; 19 | } 20 | if (prices[i] < minValue) { 21 | minValue = prices[i]; 22 | } 23 | } 24 | if (maxDiff < 0) { 25 | return 0; 26 | } else { 27 | return maxDiff; 28 | } 29 | 30 | } 31 | ``` 32 | 33 | 34 | --- 35 | ```java 36 | public int maxProfit(int[] prices) { 37 | 38 | if (prices == null || prices.length == 0) { 39 | return 0; 40 | } 41 | 42 | int min = Integer.MAX_VALUE; 43 | int profit = 0; 44 | 45 | for (int i = 0; i < prices.length; i++) { 46 | profit = Math.max(profit, prices[i] - min); 47 | min = Math.min(min, prices[i]); 48 | } 49 | 50 | return profit; 51 | } 52 | ``` 53 | -------------------------------------------------------------------------------- /high_frequency/best_time_to_buy_and_sell_stock_ii.md: -------------------------------------------------------------------------------- 1 | # Best Time to Buy and Sell Stock II 2 | 3 | [原題連結](http://www.lintcode.com/en/problem/best-time-to-buy-and-sell-stock-ii/) 4 | 5 | 題意:與 [Best Time to Buy and Sell Stock](high_frequency/best_time_to_buy_and_sell_stock.md) 類似,但是你可以作無限多次的買賣,唯一的限制是在賣之前你必須先買。 6 | 7 | 解題思路:因為你可以作無限多次的買賣,因此只要不斷檢查今天的股價是否比前一天高,若是,則購買,否則放棄,程式碼如下。 8 | 9 | ```java 10 | public int maxProfit(int[] prices) { 11 | 12 | int profit = 0; 13 | 14 | for (int i = 1; i < prices.length; i++) { 15 | if (prices[i - 1] < prices[i]) { 16 | profit += prices[i] - prices[i - 1]; 17 | } 18 | } 19 | 20 | return profit; 21 | } 22 | ``` 23 | 24 | >Time Complexity:$$O(N)$$,因只需遍歷陣列一次。 -------------------------------------------------------------------------------- /high_frequency/best_time_to_buy_and_sell_stock_iii.md: -------------------------------------------------------------------------------- 1 | #Best Time to Buy and Sell Stock III 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/best-time-to-buy-and-sell-stock-iii/) 4 | 5 | 題意:最多可以作兩次買賣,找出最大獲利值 6 | 7 | 解題思路:從左掃到右,找出左邊最大獲利值,再從右掃到左,找右邊最大獲利值,接著找出 i ,使得 right[i] + left[i] 為最大。 8 | 9 | [注意] 在初始化 max 值時,不能取 Integer.MIN_VALUE,會出錯,目前仍不解,日後有想法再更新。 10 | 11 | [更新] 將 min 初始化為 prices[0],會比較一致。 12 | 13 | ```java 14 | public int maxProfit(int[] prices) { 15 | 16 | if (prices == null || prices.length == 0) { 17 | return 0; 18 | } 19 | 20 | int len = prices.length; 21 | int[] left = new int[len]; 22 | int[] right = new int[len]; 23 | 24 | int profit = 0; 25 | int min = prices[0]; 26 | 27 | for (int i = 0; i < len; i++) { 28 | profit = Math.max(profit, prices[i] - min); 29 | min = Math.min(min, prices[i]); 30 | left[i] = profit; 31 | } 32 | 33 | profit = 0; 34 | int max = prices[len - 1]; 35 | for (int i = len - 1; i >= 0; i--) { 36 | profit = Math.max(profit, max - prices[i]); 37 | max = Math.max(max, prices[i]); 38 | right[i] = profit; 39 | } 40 | 41 | int maxProfit = 0; 42 | for (int i = 0; i < len - 1; i++) { 43 | maxProfit = Math.max(maxProfit, left[i] + right[i]); 44 | } 45 | 46 | return maxProfit; 47 | } 48 | ``` 49 | 50 | >Time Complexity:$$O(N)$$ 51 | 52 | --- 53 | 除了上題的作法,還可以使用動態規劃來幫助我們解決這題, 54 | -------------------------------------------------------------------------------- /high_frequency/k_sum_ii.md: -------------------------------------------------------------------------------- 1 | # K Sum II 2 | 3 | [Lintcode](http://www.lintcode.com/en/problem/k-sum-ii/) 4 | 5 | 題意: 6 | 7 | Given n unique integers, number k (1<=k<=n) and target. Find all possible k integers where their sum is target. 8 | 9 | 10 | 解題思路: 11 | 12 | 使用 dfs 來解,其實這題就是[Combination Sum](high_frequency/combination_sum.md) 的變形,但我們不需要略過重複的數,只要確定當下的結果元素個數等於k且和為target即可。 13 | 14 | 程式碼如下: 15 | 16 | ```java 17 | public class Solution { 18 | /** 19 | * @param A: an integer array. 20 | * @param k: a positive integer (k <= length(A)) 21 | * @param target: a integer 22 | * @return a list of lists of integer 23 | */ 24 | ArrayList> res = new ArrayList>(); 25 | 26 | public ArrayList> kSumII(int A[], int k, int target) { 27 | if (A == null || A.length == 0 || target < 0) { 28 | return res; 29 | } 30 | 31 | helper(new ArrayList(), A, k , target, 0); 32 | return res; 33 | } 34 | 35 | private void helper(ArrayList tempRes, int[] A, int k, int remain, int pos) { 36 | if (tempRes.size() == k) { 37 | if (remain == 0) { 38 | res.add(new ArrayList(tempRes)); 39 | } 40 | return; 41 | } else { 42 | for (int i = pos; i < A.length; i++) { 43 | tempRes.add(A[i]); 44 | helper(tempRes, A, k, remain - A[i], i + 1); 45 | tempRes.remove(tempRes.size() - 1); 46 | } 47 | } 48 | } 49 | } 50 | ``` 51 | 52 | --- 53 | ###Reference 54 | 1. http://www.cnblogs.com/EdwardLiu/p/4314783.html -------------------------------------------------------------------------------- /high_frequency/sum.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/high_frequency/sum.md -------------------------------------------------------------------------------- /high_frequency/triangle_count.md: -------------------------------------------------------------------------------- 1 | #Triangle Count 2 | 3 | []() 4 | 5 | 題意:給定一個陣列,陣列中每個元素代表邊長,找出陣列中能組合成合法三角形的總數。 6 | 7 | 解題思路:合法三角形就是選三個邊,任兩邊合必大於第三邊,原本若使用暴力法需花費 $$O(N^{3})$$ 的時間複雜度。我們可以透過排序後陣列升序的特性。 8 | 原本需要檢查三次才能確保合法性,但陣列已排序過,i <= j <= k,我們只需要檢查 i + j > k即可,程式碼如下: 9 | 10 | >需要注意的地方,我們固定第 $$i$$ 邊為三角形的最大邊,在 $$○$$ 到 $$i-1$$ 中找出所有可能性。 11 | 12 | ```java 13 | public int triangleCount(int S[]) { 14 | 15 | if (S == null || S.length <= 2) { 16 | return 0; 17 | } 18 | 19 | Arrays.sort(S); 20 | int count = 0; 21 | int len = S.length; 22 | 23 | for (int i = 0; i < len; i++) { 24 | int start = 0; 25 | int end = i - 1; 26 | while (start < end) { 27 | if (S[start] + S[end] > S[i]) { 28 | count += (end - start); // 關鍵 29 | end--; 30 | } else { 31 | start++; 32 | } 33 | } 34 | } 35 | 36 | return count; 37 | } 38 | ``` 39 | 40 | >Time Complexity:$$O(Nlog{N} + N^{2})$$,此為花在排序的時間,與後面兩根指針運算。 -------------------------------------------------------------------------------- /insertion-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/insertion-sort.gif -------------------------------------------------------------------------------- /iterator.md: -------------------------------------------------------------------------------- 1 | # Iterator 2 | 3 | -------------------------------------------------------------------------------- /knowledge.md: -------------------------------------------------------------------------------- 1 | # Knowledge 2 | 3 | -------------------------------------------------------------------------------- /knowledge/network.md: -------------------------------------------------------------------------------- 1 | # Network 2 | 3 | 1. What happens when you type in a URL in browser 4 | Ans : 5 | 6 | 1. browser checks cache; if requested object is in cache and is fresh, skip to #9 7 | 2. browser asks OS for server's IP address 8 | 3. OS makes a DNS lookup and replies the IP address to the browser 9 | 4. browser opens a TCP connection to server (this step is much more complex with HTTPS) 10 | 5. browser sends the HTTP request through TCP connection 11 | 6. browser receives HTTP response and may close the TCP connection, or reuse it for another request 12 | 7. browser checks if the response is a redirect or a conditional response (3xx result status codes), authorization request (401), error (4xx and 5xx), etc.; these are handled differently from normal responses (2xx) 13 | 8. if cacheable, response is stored in cache 14 | 9. browser decodes response (e.g. if it's gzipped) 15 | 10. browser determines what to do with response (e.g. is it a HTML page, is it an image, is it a sound clip?) 16 | 11. browser renders response, or offers a download dialog for unrecognized types 17 | 18 | 19 | --- 20 | ###Reference 21 | 1. http://stackoverflow.com/questions/2092527/what-happens-when-you-type-in-a-url-in-browser -------------------------------------------------------------------------------- /linked_list.md: -------------------------------------------------------------------------------- 1 | 2 | # Linked List 3 | 4 | 什麼是Linked List 5 | 6 | 7 | #### Single List 8 | ```java 9 | // Definition for ListNode. 10 | public class ListNode { 11 | int val; 12 | ListNode next; 13 | ListNode(int val) { 14 | this.val = val; 15 | this.next = null; 16 | } 17 | } 18 | ``` 19 | #### Double List 20 | 21 | 22 | How to implement Linked List data structure 23 | 24 | - - - 25 | ####LinkedList Template 26 | 27 | 當在處理 Linked List 的時候,最常寫下的片段如下: 28 | 29 | ```java 30 | while ( head != null ) { 31 | // 自己的程式碼 32 | head = head.next; 33 | } 34 | ``` 35 | 36 | 這個片段就會讓程式從 Linked List 的頭節點走到最後一個節點 (null),但切記別在 head 更新成下一個節點 head.next 之前,就擅自對 head 或是 head.next 進行改變。如果一定要對 head 或是 head.next做改變,可以利用一個暫時的 Linked List 節點存下 head.next ,最後再將 head 更新成暫時的節點,程式碼如下: 37 | 38 | ```java 39 | while ( head != null ) { 40 | LinkedList temp = head.next; 41 | // 自己的程式碼 42 | 43 | head = temp; 44 | } 45 | ``` 46 | 這個用法我們將會在反轉 Linked List ([Reverse Linked List](./linked_list/reverse_linked_list.md)) 題目中見到。 47 | - - - 48 | common mistake in Linked List 49 | 50 | LinkedList 特殊解法 ( Dummy Node, Fast-n-Slow pointer ) 51 | 52 | Linked List 題目 53 | -------------------------------------------------------------------------------- /linked_list/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/linked_list/.DS_Store -------------------------------------------------------------------------------- /linked_list/delete_node_in_the_middle_of_singly_linked_list.md: -------------------------------------------------------------------------------- 1 | #Delete Node in the Middle of Singly Linked List 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/delete-node-in-the-middle-of-singly-linked-list/) 4 | 5 | 題意: 6 | 7 | 刪除鏈結中的第m個節點,且當下只能存取該節點,無法得知之前的節點是什麼。 8 | 9 | 解題思路: 10 | 11 | 把下一點的值複製到當前節點,再把下一節點刪除即可,代碼如下: 12 | 13 | ```java 14 | public void deleteNode(ListNode node) { 15 | 16 | if (node == null || node.next == null) { 17 | return; 18 | } 19 | 20 | node.val = node.next.val; 21 | node.next = node.next.next; 22 | } 23 | ``` -------------------------------------------------------------------------------- /linked_list/insertion_sort_list.md: -------------------------------------------------------------------------------- 1 | # Insertion Sort List 2 | 3 | [Lintcode](http://www.lintcode.com/en/problem/insertion-sort-list/) 4 | 5 | 題意: 6 | 7 | Sort a linked list using insertion sort. 8 | 9 | Example 10 | 11 | Given 1->3->2->0->null, return 0->1->2->3->null. 12 | 13 | 解題思路: 14 | 15 | 每次把head節點往前找到適合的位置往前插,再繼續head下一個節點,找位置時記得從頭開始找。 16 | 17 | 其程式碼如下: 18 | 19 | ```java 20 | /** 21 | * Definition for ListNode. 22 | * public class ListNode { 23 | * int val; 24 | * ListNode next; 25 | * ListNode(int val) { 26 | * this.val = val; 27 | * this.next = null; 28 | * } 29 | * } 30 | */ 31 | public class Solution { 32 | /** 33 | * @param head: The first node of linked list. 34 | * @return: The head of linked list. 35 | */ 36 | public ListNode insertionSortList(ListNode head) { 37 | 38 | if (head == null || head.next == null) { 39 | return head; 40 | } 41 | 42 | ListNode dummy = new ListNode(0); 43 | ListNode prev = dummy; 44 | 45 | while (head != null) { 46 | ListNode next = head.next; 47 | prev = dummy; // 每次都要從頭開始找,所以記得assign到dummy 48 | while (prev.next != null && prev.next.val <= head.val) { 49 | prev = prev.next; 50 | } 51 | // 把cur插到prev的下一個 52 | head.next = prev.next; 53 | prev.next = head; 54 | head = next; 55 | } 56 | return dummy.next; 57 | } 58 | } 59 | 60 | ``` 61 | --- 62 | ###Reference 63 | 1. http://blog.csdn.net/linhuanmars/article/details/21144553 -------------------------------------------------------------------------------- /linked_list/list_cycle.md: -------------------------------------------------------------------------------- 1 | # List Cycle 2 | 3 | [Leetcode](https://leetcode.com/problems/linked-list-cycle/) 4 | 5 | 題意: 6 | 7 | Given a linked list, determine if it has a cycle in it. 8 | 9 | Follow up: 10 | Can you solve it without using extra space? 11 | 12 | 13 | 解題思路: 14 | 15 | ```java 16 | /** 17 | * Definition for singly-linked list. 18 | * class ListNode { 19 | * int val; 20 | * ListNode next; 21 | * ListNode(int x) { 22 | * val = x; 23 | * next = null; 24 | * } 25 | * } 26 | */ 27 | public class Solution { 28 | public boolean hasCycle(ListNode head) { 29 | if (head == null) { 30 | return false; 31 | } 32 | 33 | ListNode slow = head; 34 | ListNode fast = head; 35 | 36 | while (fast.next != null && fast.next.next != null) { 37 | slow = slow.next; 38 | fast = fast.next.next; 39 | if (slow.val == fast.val) { 40 | return true; 41 | } 42 | 43 | } 44 | return false; 45 | } 46 | } 47 | ``` -------------------------------------------------------------------------------- /linked_list/merge_two_sorted_lists.md: -------------------------------------------------------------------------------- 1 | #Merge Two Sorted Lists 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/merge-two-sorted-lists/) 4 | 5 | 題意:合併兩個有序鏈表 6 | 7 | 解題思路: 8 | 9 | 代碼如下: 10 | 11 | ```java 12 | public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 13 | 14 | if (l1 == null) { 15 | return l2; 16 | } 17 | 18 | if (l2 == null) { 19 | return l1; 20 | } 21 | 22 | ListNode dummy = new ListNode(0); 23 | ListNode cur = dummy; 24 | 25 | while (l1 != null && l2 != null) { 26 | if (l1.val < l2.val) { 27 | cur.next = l1; 28 | l1 = l1.next; 29 | } else { 30 | cur.next = l2; 31 | l2 = l2.next; 32 | } 33 | cur = cur.next; 34 | } 35 | if (l1 == null) { 36 | cur.next = l2; 37 | } else { 38 | cur.next = l1; 39 | } 40 | return dummy.next; 41 | } 42 | ``` 43 | -------------------------------------------------------------------------------- /linked_list/odd_even_linked_list.md: -------------------------------------------------------------------------------- 1 | # Odd Even Linked List 2 | 3 | [Leetcode](https://leetcode.com/problems/odd-even-linked-list/) 4 | 5 | 6 | 題意: 7 | 8 | Given a singly linked list, group all odd nodes together followed by the even nodes. Please note here we are talking about the node number and not the value in the nodes. 9 | 10 | You should try to do it in place. The program should run in O(1) space complexity and O(nodes) time complexity. 11 | 12 | Example: 13 | - Given 1->2->3->4->5->NULL, 14 | - return 1->3->5->2->4->NULL. 15 | 16 | Note: 17 | The relative order inside both the even and odd groups should remain as it was in the input. 18 | The first node is considered odd, the second node even and so on ... 19 | 20 | 21 | 22 | 23 | 24 | 解題思路: 25 | 26 | ```java 27 | /** 28 | * Definition for singly-linked list. 29 | * public class ListNode { 30 | * int val; 31 | * ListNode next; 32 | * ListNode(int x) { val = x; } 33 | * } 34 | */ 35 | public class Solution { 36 | public ListNode oddEvenList(ListNode head) { 37 | if (head != null) { 38 | 39 | ListNode odd = head, even = head.next, evenHead = even; 40 | 41 | while (even != null && even.next != null) { 42 | odd.next = odd.next.next; 43 | even.next = even.next.next; 44 | odd = odd.next; 45 | even = even.next; 46 | } 47 | odd.next = evenHead; 48 | } 49 | return head; 50 | } 51 | } 52 | ``` 53 | 54 | --- 55 | ###Reference 56 | 1. https://leetcode.com/discuss/80315/simple-o-n-time-o-1-space-java-solution -------------------------------------------------------------------------------- /linked_list/partition_list.md: -------------------------------------------------------------------------------- 1 | #Partition List 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/partition-list/) 4 | 5 | 題意: 6 | 7 | 給定一鏈表,與值 x,將鏈表中所有比 x 小的元素放在鏈表的左邊,比 x 大的元素放在右邊。 8 | 9 | 解題思路: 10 | 11 | 分別建兩個鏈表,分別存放比 x 小的元素與比 x 大的元素,最後將兩個鏈表接起來即可,原始碼如下: 12 | 13 | 14 | >記得要把greater的下一個斷掉,否則會變成loop 15 | 16 | 17 | ```java 18 | 19 | public ListNode partition(ListNode head, int x) { 20 | 21 | if (head == null) { 22 | return null; 23 | } 24 | 25 | ListNode dummyLesser = new ListNode(0); 26 | ListNode dummyGreater = new ListNode(0); 27 | ListNode curLesser = dummyLesser; 28 | ListNode curGreater = dummyGreater; 29 | 30 | while (head != null) { 31 | if (head.val < x) { 32 | curLesser.next = head; 33 | curLesser = curLesser.next; 34 | } else { 35 | curGreater.next = head; 36 | curGreater = curGreater.next; 37 | } 38 | head = head.next; 39 | } 40 | 41 | curGreater.next = null; 42 | curLesser.next = dummyGreater.next; 43 | return dummyLesser.next; 44 | } 45 | ``` 46 | --- 47 | >Time Complexity:O(N) -------------------------------------------------------------------------------- /linked_list/remove_duplicates_from_sorted_list.md: -------------------------------------------------------------------------------- 1 | #Remove Duplicates from Sorted List 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/remove-duplicates-from-sorted-list/) 4 | 5 | 題意:即實作 Linked List 的 Unique 方法,重複的元素只留一個。 6 | 7 | 解題思路:不斷的拿當前的 node 去與下一個 node 來比 8 | * 若一樣,則改變 node.next 指到 node.next.next , 9 | * 若不同,則直接移動 node 到下一個, 10 | 11 | 由於head並不會變,所以不需要dummy node來輔助,程式碼如下: 12 | 13 | ```java 14 | public static ListNode deleteDuplicates(ListNode head) { 15 | 16 | if (head == null) { 17 | return head; 18 | } 19 | 20 | ListNode node = head; 21 | while (node.next != null) { 22 | if (node.val == node.next.val) { 23 | node.next = node.next.next; 24 | } else { 25 | node = node.next; 26 | } 27 | } 28 | return head; 29 | } 30 | ``` 31 | 32 | --- 33 | Reference: 34 | 35 | 1. http://www.jiuzhang.com/solutions/remove-duplicates-from-sorted-list/ -------------------------------------------------------------------------------- /linked_list/remove_linked_list_elements.md: -------------------------------------------------------------------------------- 1 | # Remove Linked List Elements 2 | 3 | [Lintcode](http://www.lintcode.com/en/problem/remove-linked-list-elements/) 4 | 5 | 題意: 6 | 7 | Remove all elements from a linked list of integers that have value val. 8 | 9 | Example 10 | ``` 11 | Given 1->2->3->3->4->5->3, val = 3, you should return the list as 1->2->4->5 12 | ``` 13 | 14 | 解題思路: 15 | 16 | updated on 2016.1.8 17 | 18 | **Recursive:** 19 | ```java 20 | public class Solution { 21 | public ListNode removeElements(ListNode head, int val) { 22 | if (head == null) { 23 | return null; 24 | } 25 | 26 | head.next = removeElements(head.next, val); 27 | 28 | return head.val == val ? head.next : head; 29 | } 30 | } 31 | ``` 32 | 33 | **Iterative:** 34 | 35 | ```java 36 | /** 37 | * Definition for singly-linked list. 38 | * public class ListNode { 39 | * int val; 40 | * ListNode next; 41 | * ListNode(int x) { val = x; } 42 | * } 43 | */ 44 | public class Solution { 45 | /** 46 | * @param head a ListNode 47 | * @param val an integer 48 | * @return a ListNode 49 | */ 50 | public ListNode removeElements(ListNode head, int val) { 51 | if (head == null) { 52 | return head; 53 | } 54 | 55 | ListNode dummy = new ListNode(0); 56 | dummy.next = head; 57 | ListNode prev = dummy; 58 | while (head != null) { 59 | if (head.val != val) { 60 | prev.next = head; 61 | prev = prev.next; 62 | } 63 | head = head.next; 64 | } 65 | // 記得作這個動作,否則prev可能還指向等於val的節點 66 | prev.next = head; 67 | return dummy.next; 68 | } 69 | } 70 | 71 | ``` -------------------------------------------------------------------------------- /linked_list/remove_nth_node_from_end_of_lis.md: -------------------------------------------------------------------------------- 1 | # Remove Nth Node From End of List 2 | [原題網址](http://www.lintcode.com/en/problem/remove-nth-node-from-end-of-list) 3 | 4 | Given a linked list, remove the nth node from the end of list and return its head. 5 | 6 | Definition for ListNode. 7 | ``` 8 | public class ListNode { 9 | int val; 10 | ListNode next; 11 | ListNode(int val) { 12 | this.val = val; 13 | this.next = null; 14 | } 15 | } 16 | 17 | ``` 18 | 19 | 20 | ``` 21 | @param head: The first node of linked list. 22 | @param n: An integer. 23 | @return: The head of linked list. 24 | ``` 25 | ## Solutions 26 | 27 | ```java 28 | ListNode removeNthFromEnd(ListNode head, int n) { 29 | // write your code here 30 | 31 | ListNode dummy = new ListNode(0); 32 | dummy.next = head; 33 | ListNode slow = dummy; 34 | 35 | while ( head != null && n > 0 ) { 36 | head = head.next; 37 | n--; 38 | } 39 | if ( n > 0 ) { 40 | return null; 41 | } 42 | while ( head != null ) { 43 | slow = slow.next; 44 | head = head.next; 45 | } 46 | slow.next = slow.next.next; 47 | return dummy.next; 48 | } 49 | ``` 50 | 第二種解法 51 | ```java 52 | ListNode removeNthFromEnd(ListNode head, int n) { 53 | 54 | ListNode dummy = new ListNode(0); 55 | dummy.next = head; 56 | ListNode target = dummy; 57 | 58 | for ( int i = 0 ; i < n ; i ++ ) { 59 | if ( head == null ) { 60 | return null; 61 | } 62 | head = head.next; 63 | } 64 | 65 | while ( head != null ) { 66 | target = target.next; 67 | head = head.next; 68 | } 69 | target.next = target.next.next; 70 | return dummy.next; 71 | } 72 | ``` 73 | -------------------------------------------------------------------------------- /linked_list/sort_list.md: -------------------------------------------------------------------------------- 1 | # Sort List 2 | [Lintcode](http://www.lintcode.com/en/problem/sort-list/) 3 | 4 | [Leetcode](https://leetcode.com/problems/sort-list/) 5 | 6 | 題意: 7 | 8 | Sort a linked list in O(n log n) time using constant space complexity. 9 | 10 | 11 | 解題思路: 12 | 13 | 不斷的把list切兩半用merge sort,記住要先處理後半段再把中間斷掉,再處理前半段,否則會無限循環。 14 | ```java 15 | public ListNode sortList(ListNode head) { 16 | 17 | if ( head == null || head.next == null ) { 18 | return head; 19 | } 20 | 21 | ListNode mid = findMiddle(head); 22 | ListNode right = sortList(mid.next); 23 | mid.next = null; 24 | ListNode left = sortList(head); 25 | 26 | return mergeLists(left, right); 27 | } 28 | 29 | public ListNode findMiddle(ListNode head) { 30 | ListNode slow = head, fast = head.next; 31 | while ( fast != null && fast.next != null ) { 32 | slow = slow.next; 33 | fast = fast.next.next; 34 | } 35 | return slow; 36 | } 37 | 38 | public ListNode mergeLists(ListNode head1, ListNode head2) { 39 | ListNode dummy = new ListNode(0); 40 | ListNode head = dummy; 41 | while ( head1 != null && head2 != null ) { 42 | if ( head1.val < head2.val ) { 43 | head.next = head1; 44 | head1 = head1.next; 45 | } else { 46 | head.next = head2; 47 | head2 = head2.next; 48 | } 49 | head = head.next; 50 | } 51 | if ( head1 != null ) { 52 | head.next = head1; 53 | } 54 | if ( head2 != null ) { 55 | head.next = head2; 56 | } 57 | return dummy.next; 58 | } 59 | ``` 60 | -------------------------------------------------------------------------------- /linked_list/swap_nodes_in_pairs.md: -------------------------------------------------------------------------------- 1 | # Swap Nodes in Pairs 2 | 3 | [Lintcode](http://www.lintcode.com/en/problem/swap-nodes-in-pairs/) 4 | 5 | 題意: 6 | 7 | Given a linked list, swap every two adjacent nodes and return its head. 8 | 9 | Example 10 | ``` 11 | Given 1->2->3->4, you should return the list as 2->1->4->3. 12 | ``` 13 | 14 | Challenge 15 | 16 | Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed. 17 | 18 | 解題思路: 19 | 20 | 因head可能會改變,因此用dummy node來紀錄一下,利用 四個指針分別記錄 prev, head, head next, next next, 接著再不斷的作改變指針的行為,最後返回 dummy.next,程式碼如下: 21 | 22 | ```java 23 | /** 24 | * Definition for singly-linked list. 25 | * public class ListNode { 26 | * int val; 27 | * ListNode next; 28 | * ListNode(int x) { val = x; } 29 | * } 30 | */ 31 | public class Solution { 32 | /** 33 | * @param head a ListNode 34 | * @return a ListNode 35 | */ 36 | public ListNode swapPairs(ListNode head) { 37 | if (head == null || head.next == null) { 38 | return head; 39 | } 40 | 41 | ListNode dummy = new ListNode(0); 42 | dummy.next = head; 43 | ListNode prev = dummy; 44 | while (head != null && head.next != null) { 45 | ListNode nextnext = head.next.next; 46 | prev.next = head.next; 47 | head.next.next = head; 48 | head.next = nextnext; 49 | prev = head; 50 | head = head.next; 51 | } 52 | return dummy.next; 53 | } 54 | } 55 | 56 | ``` -------------------------------------------------------------------------------- /math.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/math.md -------------------------------------------------------------------------------- /math/a_+_b_problem.md: -------------------------------------------------------------------------------- 1 | # A + B Problem 2 | 3 | [Lintcode](http://www.lintcode.com/en/problem/a-b-problem/) 4 | 5 | 題意: 6 | 7 | Write a function that add two numbers A and B. You should not use + or any arithmetic operators. 8 | 9 | **Note** 10 | 11 | There is no need to read data from standard input stream. Both parameters are given in function aplusb, you job is to calculate the sum and return it. 12 | 13 | **Challenge** 14 | 15 | Of course you can just return a + b to get accepted. But Can you challenge not do it like that? 16 | 17 | **Clarification** 18 | 19 | Are a and b both 32-bit integers? 20 | 21 | Yes. 22 | 23 | Can I use bit operation? 24 | 25 | Sure you can. 26 | 27 | 解題思路: 28 | 29 | 一個bit一個bit 的慢慢判斷,其程式碼如下: 30 | 31 | ```java 32 | class Solution { 33 | /* 34 | * param a: The first integer 35 | * param b: The second integer 36 | * return: The sum of a and b 37 | */ 38 | public int aplusb(int a, int b) { 39 | int carry = 0; 40 | int sum = 0; 41 | for (int i = 0; i < 32; i++) { 42 | int aBit = (a >> i) & 1; 43 | int bBit = (b >> i) & 1; 44 | sum |= (aBit ^ bBit ^ carry) << i; 45 | if ((aBit == 1 && bBit == 1) || ((aBit == 1 || bBit == 1) && carry == 1)) { 46 | carry = 1; 47 | } else { 48 | carry = 0; 49 | } 50 | } 51 | 52 | return sum; 53 | } 54 | }; 55 | 56 | ``` 57 | ###Reference 58 | 59 | 1. http://www.cnblogs.com/EdwardLiu/p/4269079.html -------------------------------------------------------------------------------- /math/add_digits.md: -------------------------------------------------------------------------------- 1 | #Add Digits 2 | 3 | [原題連結](https://leetcode.com/problems/add-digits/) 4 | 5 | 題意: 6 | 7 | Given a non-negative integer num, repeatedly add all its digits until the result has only one digit. 8 | 9 | For example: 10 | 11 | Given ```num = 38```, the process is like: ```3 + 8 = 11, 1 + 1 = 2```. Since 2 has only one digit, return it. 12 | 13 | Follow up: 14 | Could you do it without any loop/recursion in $$O(1)$$ runtime? 15 | 16 | 解法一(循環),程式碼如下: 17 | 18 | ```java 19 | public int addDigits(int num) { 20 | 21 | if (num < 10) { 22 | return num; 23 | } 24 | 25 | while (num >= 10) { 26 | int temp = num; 27 | int result = 0; 28 | while (temp > 0) { 29 | result += temp % 10; 30 | temp /= 10; 31 | } 32 | 33 | num = result; 34 | } 35 | 36 | return num; 37 | } 38 | ``` 39 | > Time Complexity:待分解 40 | 41 | --- 42 | 網友 [書影](http://bookshadow.com/weblog/2015/08/16/leetcode-add-digits/) 提供以下觀查法 43 | 44 | 方法II:觀察法 45 | 46 | 根據提示,由於結果只有一位數,因此其可能的數字為0 - 9 47 | 48 | 使用方法I的代碼循環輸出0 - 19的運行結果: 49 | ``` 50 | in out in out 51 | 0 0 10 1 52 | 1 1 11 2 53 | 2 2 12 3 54 | 3 3 13 4 55 | 4 4 14 5 56 | 5 5 15 6 57 | 6 6 16 7 58 | 7 7 17 8 59 | 8 8 18 9 60 | 9 9 19 1 61 | ``` 62 | 可以發現輸出與輸入的關係為: 63 | 64 | >out = (in - 1) % 9 + 1 65 | 66 | 67 | ```java 68 | public int addDigits2(int num) { 69 | 70 | if (num < 10) { 71 | return num; 72 | } 73 | 74 | return (num % 9 != 0) ? num % 9 : 9; 75 | } 76 | ``` 77 | 78 | > Time Complexity:$$O(1)$$ 79 | 80 | --- 81 | ###Reference 82 | 1. http://bookshadow.com/weblog/2015/08/16/leetcode-add-digits/ -------------------------------------------------------------------------------- /math/bulb_switcher.md: -------------------------------------------------------------------------------- 1 | # Bulb Switcher 2 | 3 | []() 4 | 5 | 6 | 題意: 7 | 8 | There are n bulbs that are initially off. You first turn on all the bulbs. Then, you turn off every second bulb. On the third round, you toggle every third bulb (turning on if it's off or turning off if it's on). For the nth round, you only toggle the last bulb. Find how many bulbs are on after n rounds. 9 | 10 | Example: 11 | 12 | Given n = 3. 13 | ``` 14 | At first, the three bulbs are [off, off, off]. 15 | After first round, the three bulbs are [on, on, on]. 16 | After second round, the three bulbs are [on, off, on]. 17 | After third round, the three bulbs are [on, off, off]. 18 | ``` 19 | So you should return 1, because there is only one bulb is on. 20 | 21 | 解題思路: 22 | 23 | 1. 如果該數為質數,只會被switch兩次,第一輪與他們自己那一輪 24 | 2. 其他的數會被開關odd次,要嘛開要嘛關,所以主要我們要找到那些數會被開關odd次以及那些sqrt(n)的數。 25 | 26 | >// For prime numbers, they must be off because we can reach them only twice (The first round and their own round). 27 | /* For other numbers, if we can reach them odd times, then they are on; otherwise, they are off. So only 28 | those numbers who have square root will be reached odd times and there are sqrt(n) of them because 29 | for every x > sqrt(n), x*x > n and thus should not be considered as the answer. */ 30 | 31 | 32 | ```java 33 | public class Solution { 34 | public int bulbSwitch(int n) { 35 | int count = 0; 36 | for (int i = 1; i *i <= n; i++) { 37 | count++; 38 | } 39 | 40 | return count; 41 | } 42 | } 43 | ``` -------------------------------------------------------------------------------- /math/find_the_missing_number.md: -------------------------------------------------------------------------------- 1 | #Find The Missing Number 2 | 3 | [Leetcode](https://leetcode.com/problems/missing-number/) 4 | 5 | 題意:給定一陣列有N個元素,找出在 0...N 中不在陣列裡的那個元素。 6 | 7 | Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array. 8 | 9 | For example, 10 | Given nums = [0, 1, 3] return 2. 11 | 12 | **Note:** 13 | Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity? 14 | 15 | 解題思路: 16 | 17 | 1. 先利用梯形公式把原本應該的總數算出來,接著再把元素和與總數相減即可得出消失的數,原始碼如下: 18 | 19 | ```java 20 | public int findMissing(int[] nums) { 21 | 22 | if (nums == null || nums.length == 0) { 23 | return 0; 24 | } 25 | 26 | int len = nums.length; 27 | int total = len * (len + 1) / 2; 28 | int sum = 0; 29 | for (int i = 0; i < nums.length; i++) { 30 | sum += nums[i]; 31 | } 32 | 33 | return total - sum; 34 | } 35 | ``` 36 | 37 | >Time Complexity:$$O(N)$$ 38 | 39 | --- 40 | 2.利用 ```xor``` 的特性來幫助我們解這道題,有點類似 [Single Number](array/single_number.md) 那道題,把所有元素全xor起來,接著再xor從0到N,最後把這兩個相 xor 即可得到消失的數,原始碼如下: 41 | 42 | ```java 43 | public int findMissing(int[] nums) { 44 | 45 | if (nums == null || nums.length == 0) { 46 | return 0; 47 | } 48 | 49 | int len = nums.length; 50 | int total = len * (len + 1) / 2; 51 | int xorOne = nums[0]; 52 | for (int i = 1; i < len; i++) { 53 | xorOne ^= nums[i]; 54 | } 55 | 56 | int xorTwo = 1; 57 | for (int i = 2; i <= len; i++) { 58 | xorTwo ^= i; 59 | } 60 | 61 | return xorTwo ^ xorOne; 62 | } 63 | ``` 64 | >Time Complexity:$$O(N)$$ -------------------------------------------------------------------------------- /math/gray_code.md: -------------------------------------------------------------------------------- 1 | #Gray Code 2 | 3 | []() 4 | 5 | 題意: 6 | 7 | 格雷編碼是一個二進制數字系統,在該系統中,兩個連續的數值僅有一個二進制的差異。 8 | 9 | 給定一個非負整數 n ,表示該代碼中所有二進制的總數,請找出其格雷編碼順序。一個格雷編碼順序必須以 0 開始,並覆蓋所有的 $$2^{n}$$ 個整數。 10 | 11 | 樣例 12 | 給定 n = 2, 返回 ```[0,1,3,2]```。其格雷編碼順序為: 13 | 14 | ``` 15 | 00 - 0 16 | 01 - 1 17 | 11 - 3 18 | 10 - 2 19 | ``` 20 | 21 | 解題思路: 22 | 23 | 以下為網友 [愛作飯的小瑩子](http://www.cnblogs.com/springfor/p/3889222.html) 提供的思路 24 | 25 | 可以看到n位的格雷碼由兩部分構成,一部分是n-1位格雷碼,再加上 1<<(n-1)和n-1位格雷碼的逆序(整個格雷碼逆序) 26 | 27 | 1位格雷碼有兩個碼字 28 | (n+1)位格雷碼中的前2^n個碼字等於n位格雷碼的碼字,按順序書寫,加前綴0 29 | (n+1)位格雷碼中的後2^n個碼字等於n位格雷碼的碼字,按逆序書寫,加前綴1。 30 | 31 | 由於是二進制,在最高位加0跟原來的數本質沒有改變,所以取得上一位算出的格雷碼結果,再加上逆序添1的方法就是當前這位格雷碼的結果了。 32 | 33 | n = 0時,[0] 34 | 35 | n = 1時,[0,1] 36 | 37 | n = 2時,[00,01,11,10] 38 | 39 | n = 3時,[000,001,011,010,110,111,101,100] 40 | 41 | 其程式碼如下: 42 | 43 | ```java 44 | public ArrayList grayCode(int n) { 45 | 46 | ArrayList res = new ArrayList(); 47 | 48 | if (n < 0) { 49 | return res; 50 | } 51 | 52 | res.add(0); 53 | for (int i = 0; i < n; i++) { 54 | int length = res.size(); 55 | int hiBit = 1 << i; 56 | 57 | for (int j = length - 1; j >= 0; j--) { 58 | res.add(res.get(j) + hiBit); 59 | } 60 | } 61 | 62 | return res; 63 | } 64 | ``` 65 | 66 | --- 67 | ###Reference 68 | 1. http://www.cnblogs.com/springfor/p/3889222.html 69 | 70 | 71 | -------------------------------------------------------------------------------- /math/happy_number.md: -------------------------------------------------------------------------------- 1 | # Happy Number 2 | 3 | [Leetcode](https://leetcode.com/problems/happy-number/) 4 | 5 | 6 | 題意: 7 | 8 | Write an algorithm to determine if a number is "happy". 9 | 10 | A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers. 11 | 12 | Example: 19 is a happy number 13 | 14 | $$1^2 + 9^2 = 82$$ 15 | 16 | $$8^2 + 2^2 = 68$$ 17 | 18 | $$6^2 + 8^2 = 100$$ 19 | 20 | 21 | $$1^2 + 0^2 + 0^2 = 1$$ 22 | 23 | 24 | 解題思路: 25 | 26 | 一個數是happy number只以下兩個條件 27 | 28 | 1. 數有循環,且數中不包含1 29 | 2. 或是數最後走到1 30 | 31 | ```java 32 | public class Solution { 33 | public boolean isHappy(int n) { 34 | 35 | HashSet set = new HashSet(); 36 | while (n != 1 && !set.contains(n)) { 37 | set.add(n); 38 | int sum = 0; 39 | while (n != 0) { 40 | sum += Math.pow(n % 10, 2); 41 | n /= 10; 42 | } 43 | n = sum; 44 | } 45 | return n == 1; 46 | } 47 | } 48 | ``` 49 | 50 | --- 51 | ###Reference 52 | 1. http://bookshadow.com/weblog/2015/04/22/leetcode-happy-number/ -------------------------------------------------------------------------------- /math/palindrome_number.md: -------------------------------------------------------------------------------- 1 | # Palindrome Number 2 | 3 | [Leetcode](https://leetcode.com/problems/palindrome-number/) 4 | 5 | 題意: 6 | 7 | Determine whether an integer is a palindrome. Do this without extra space. 8 | 9 | 10 | 11 | Some hints: 12 | 13 | Could negative integers be palindromes? (ie, -1) 14 | 15 | If you are thinking of converting the integer to string, note the restriction of using extra space. 16 | 17 | You could also try reversing an integer. However, if you have solved the problem "Reverse Integer", you know that the reversed integer might overflow. How would you handle such case? 18 | 19 | There is a more generic way of solving this problem. 20 | 21 | 22 | 解題思路: 23 | 24 | 不斷地取第一位和最後一位(10進制下)進行比較,相等則取第二位和倒數第二位,直到完成比較或者中途找到了不一致的位。 25 | 26 | 程式碼如下: 27 | 28 | ```java 29 | public class Solution { 30 | public boolean isPalindrome(int x) { 31 | if (x < 0) { 32 | return false; 33 | } 34 | 35 | int div = 1; 36 | while (x / div >= 10) { 37 | div *= 10; 38 | } 39 | 40 | while (x > 0) { 41 | int l = x / div; 42 | int r = x % 10; 43 | if (l != r) { 44 | return false; 45 | } 46 | x = x % div / 10; 47 | div /= 100; 48 | } 49 | 50 | return true; 51 | } 52 | } 53 | ``` 54 | --- 55 | ###Reference 56 | 1. http://fisherlei.blogspot.com/2012/12/leetcode-palindrome-number.html 57 | -------------------------------------------------------------------------------- /math/pascal_triangle.md: -------------------------------------------------------------------------------- 1 | # Pascal Triangle 2 | 3 | [Leetcode](https://leetcode.com/problems/pascals-triangle/) 4 | 5 | 題意: 6 | 7 | Given numRows, generate the first numRows of Pascal's triangle. 8 | 9 | For example, given numRows = 5, 10 | Return 11 | 12 | ``` 13 | [ 14 | [1], 15 | [1,1], 16 | [1,2,1], 17 | [1,3,3,1], 18 | [1,4,6,4,1] 19 | ] 20 | ``` 21 | 22 | 解題思路: 23 | 24 | ```java 25 | public class Solution { 26 | public List> generate(int numRows) { 27 | List> res = new ArrayList>(); 28 | if (numRows == 0) { 29 | return res; 30 | } 31 | List pre = new ArrayList(); 32 | pre.add(1); 33 | res.add(pre); 34 | for (int i = 2; i <= numRows; i++) { 35 | List cur = new ArrayList(); 36 | cur.add(1); 37 | for(int j = 0; j < pre.size() - 1; j++) { 38 | cur.add(pre.get(j) + pre.get(j + 1)); 39 | } 40 | cur.add(1); 41 | pre = cur; 42 | res.add(cur); 43 | } 44 | 45 | return res; 46 | } 47 | } 48 | ``` 49 | --- 50 | ###Reference 51 | 1. http://blog.csdn.net/linhuanmars/article/details/23311527 -------------------------------------------------------------------------------- /math/pascal_triangle_ii.md: -------------------------------------------------------------------------------- 1 | # Pascal Triangle II 2 | 3 | [Leetcode](https://leetcode.com/problems/pascals-triangle-ii/) 4 | 5 | 題意: 6 | 7 | Given an index k, return the kth row of the Pascal's triangle. 8 | 9 | For example, given k = 3, 10 | Return [1,3,3,1]. 11 | 12 | Note: 13 | 14 | Could you optimize your algorithm to use only O(k) extra space? 15 | 16 | 17 | 解題思路: 18 | 19 | 每次從最後面加1,再由後往前更新即可。 20 | 21 | ```java 22 | public class Solution { 23 | public List getRow(int rowIndex) { 24 | List res = new ArrayList(); 25 | 26 | for (int i = 0; i <= rowIndex; i++) { 27 | res.add(1); 28 | 29 | for (int j = i-1; j > 0; j--) { 30 | res.set(j, res.get(j-1) + res.get(j)); 31 | } 32 | } 33 | return res; 34 | } 35 | } 36 | ``` -------------------------------------------------------------------------------- /math/perfect_number.md: -------------------------------------------------------------------------------- 1 | # Perfect Number 2 | 3 | []() 4 | 5 | 6 | 題意: 7 | 8 | 找出特定區間的所有perfect number,perfect number的定義是所有質因數相加是否等於原本的數。 9 | 10 | 11 | 解題思路: 12 | 13 | 14 | ```java 15 | import java.io.IOException; 16 | 17 | // Finding perfect numbers in a range using Java 18 | public class PerfectNumbersInRange { 19 | 20 | public static void main(String[] args) throws IOException { 21 | int starting_number = 1; 22 | int ending_number = 10000; 23 | System.out.println("Perfect Numbers between "+starting_number+ " and "+ending_number); 24 | for (int i = starting_number; i <= ending_number; i++) { 25 | if (isPerfectNumber(i)) { 26 | System.out.println(i+" is a perfect number"); 27 | } 28 | } 29 | } 30 | 31 | /** 32 | * Checks whether the given number is a perfect number 33 | * @param number 34 | * @return 35 | */ 36 | public static boolean isPerfectNumber(int number) { 37 | int sum=0; 38 | for(int i=1; i<=number/2; i++) { 39 | if(number%i == 0) { 40 | sum += i; 41 | } 42 | } 43 | 44 | if(sum==number) { 45 | return true; 46 | }else { 47 | return false; 48 | } 49 | } 50 | 51 | } 52 | ``` -------------------------------------------------------------------------------- /math/permutation.md: -------------------------------------------------------------------------------- 1 | #Permutation 2 | 3 | 4 | 5 | ```java 6 | class Solution { 7 | /** 8 | * @param nums: A list of integers. 9 | * @return: A list of permutations. 10 | */ 11 | 12 | ArrayList> res; 13 | boolean[] visited; 14 | public ArrayList> permute(ArrayList nums) { 15 | 16 | res = new ArrayList>(); 17 | if (nums == null || nums.size() == 0) { 18 | return res; 19 | } 20 | 21 | visited = new boolean[nums.size()]; 22 | Collections.sort(nums); 23 | helper(nums, new ArrayList(), nums.size()); 24 | return res; 25 | 26 | } 27 | 28 | private void helper(ArrayList nums, List tempList, int n) { 29 | if (tempList.size() == n) { 30 | res.add(new ArrayList(tempList)); 31 | return; 32 | } 33 | 34 | for (int i = 0; i < n; i++) { 35 | if (visited[i] == false) { 36 | visited[i] = true; 37 | tempList.add(nums.get(i)); 38 | helper(nums, tempList, n); 39 | tempList.remove(tempList.size() - 1); 40 | visited[i] = false; 41 | } 42 | } 43 | } 44 | } 45 | 46 | 47 | ``` -------------------------------------------------------------------------------- /math/plus_one.md: -------------------------------------------------------------------------------- 1 | # Plus One 2 | 3 | [Leetcode](https://leetcode.com/problems/plus-one/) 4 | 5 | 題意: 6 | 7 | Given a non-negative number represented as an array of digits, plus one to the number. 8 | 9 | The digits are stored such that the most significant digit is at the head of the list. 10 | 11 | 12 | 解題思路: 13 | 14 | 參考以下comments,程式碼如下: 15 | 16 | ```java 17 | public class Solution { 18 | public int[] plusOne(int[] digits) { 19 | int len = digits.length; 20 | 21 | for(int i = len - 1; i >= 0; i--) { 22 | if (digits[i] < 9) { 23 | // 因為小於9的話表示後面的數不會再進位 24 | // 直接返回即可 25 | digits[i]++; 26 | return digits; 27 | } 28 | // 到這裡表示 digits[i] == 9加一會變10進位 29 | digits[i] = 0; 30 | 31 | } 32 | 33 | // 到這裡表示每一位都是9,會進位成長度為len + 1的數 34 | // 建新的len + 1陣列,並且把most significant bit設為1 35 | int[] newNumber = new int[len + 1]; 36 | newNumber[0] = 1; 37 | return newNumber; 38 | } 39 | } 40 | ``` 41 | 42 | --- 43 | ###Reference 44 | 1. https://leetcode.com/discuss/58149/my-simple-java-solution -------------------------------------------------------------------------------- /math/power_of_three.md: -------------------------------------------------------------------------------- 1 | # Power of Three 2 | 3 | [Leetcode](https://leetcode.com/problems/power-of-three/) 4 | 5 | 題意: 6 | 7 | Given an integer, write a function to determine if it is a power of three. 8 | 9 | Follow up: 10 | Could you do it without using any loop / recursion? 11 | 12 | 13 | 解題思路: 14 | 15 | 其實這是個數學題,如果n為power of 3的話,n可以表示為$$ n = 3^x$$,兩邊取log後變成 $$log(n) = x *log(3)$$移項後變成$$ x = log(n) / log(3)$$,接下來我們只要再把x當成power去比較 $$n == 3^n$$與否即可。 16 | 17 | 18 | ```java 19 | public class Solution { 20 | public boolean isPowerOfThree(int n) { 21 | return n == 0 ? false : n == Math.pow(3, Math.round(Math.log(n) / Math.log(3))); 22 | } 23 | } 24 | ``` -------------------------------------------------------------------------------- /math/powx,n.md: -------------------------------------------------------------------------------- 1 | # Pow(x,n) 2 | 3 | [Leetcode](https://leetcode.com/problems/powx-n/) 4 | 5 | 題意: 6 | 7 | Implement pow(x, n). $$x^n$$ 8 | 9 | 10 | 解題思路: 11 | 12 | ```java 13 | public class Solution { 14 | public double myPow(double x, int n) { 15 | double res = 1.0; 16 | int pow = n; 17 | if (n < 0) { 18 | pow = -n; //轉為正的來處理 19 | x = 1.0 / x; 20 | } 21 | 22 | while (pow > 0) { 23 | if (pow % 2 == 1){ 24 | res *= x; 25 | } 26 | x *= x; 27 | pow = pow >> 1; 28 | } 29 | 30 | return res; 31 | } 32 | } 33 | ``` 34 | 35 | updated on 2015.12.23 36 | 37 | 遞迴作法,會超時 38 | 39 | ```java 40 | public class Solution { 41 | public double myPow(double x, int n) { 42 | if (x == 0) { 43 | return 0; 44 | } 45 | if (n == 0) { 46 | return 1.0; 47 | } 48 | if (n % 2 == 0) { 49 | return myPow(x, n / 2) * myPow(x, n / 2); 50 | } else { 51 | return myPow(x, n / 2) * myPow(x, n / 2) * x; 52 | } 53 | } 54 | } 55 | ``` -------------------------------------------------------------------------------- /math/rectangle_area.md: -------------------------------------------------------------------------------- 1 | # Rectangle Area 2 | 3 | [Leetcode]https://leetcode.com/problems/rectangle-area/ 4 | 5 | 題意: 6 | 7 | ind the total area covered by two rectilinear rectangles in a 2D plane. 8 | 9 | Each rectangle is defined by its bottom left corner and top right corner as shown in the figure. 10 | 11 | 解題思路: 12 | 13 | 14 | ```java 15 | public class Solution { 16 | public int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) { 17 | int sums = (C - A) * (D - B) + (G - E) * (H - F); 18 | 19 | if (D < F || H < B) { 20 | return sums; 21 | } 22 | 23 | if (C < E || G < A) { 24 | return sums; 25 | } 26 | 27 | int right = Math.min(C, G); 28 | int left = Math.max(A, E); 29 | int top = Math.min(H, D); 30 | int bottom = Math.max(F, B); 31 | 32 | return sums - (right - left) * (top - bottom); 33 | } 34 | } 35 | ``` 36 | 37 | --- 38 | ###Reference 39 | 1. http://www.programcreek.com/2014/06/leetcode-rectangle-area-java/ -------------------------------------------------------------------------------- /math/reverse_integer.md: -------------------------------------------------------------------------------- 1 | # Reverse Integer 2 | 3 | [Leetcode](https://leetcode.com/problems/reverse-integer/) 4 | 5 | 6 | 題意: 7 | 8 | Reverse digits of an integer. 9 | ``` 10 | Example1: x = 123, return 321 11 | Example2: x = -123, return -321 12 | ``` 13 | 14 | 15 | Have you thought about this? 16 | 17 | Here are some good questions to ask before coding. Bonus points for you if you have already thought through this! 18 | 19 | If the integer's last digit is 0, what should the output be? ie, cases such as 10, 100. 20 | 21 | Did you notice that the reversed integer might overflow? Assume the input is a 32-bit integer, then the reverse of 1000000003 overflows. How should you handle such cases? 22 | 23 | For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows. 24 | 25 | 解題思路: 26 | 27 | 題目不難,重點是考慮到 overflow的問題,在這裡我們不斷的根據Integer.MAX_VALUE / 10來與當下的 val來作比較,如果當下已經大於MAX_VALUE / 10了,表示待會乘以10時必定會overflow。 28 | 29 | 程式碼如下: 30 | 31 | ```java 32 | public class Solution { 33 | public int reverse(int x) { 34 | boolean negative = false; 35 | if (x < 0) { 36 | negative = true; 37 | } 38 | 39 | int val = 0; 40 | while (x != 0) { 41 | if (negative && val < (Integer.MIN_VALUE / 10)) { 42 | return 0; 43 | } 44 | if (!negative && val > (Integer.MAX_VALUE / 10)) { 45 | return 0; 46 | } 47 | val = val * 10 + x % 10; 48 | x /= 10; 49 | } 50 | 51 | return val; 52 | } 53 | } 54 | ``` -------------------------------------------------------------------------------- /math/roman_to_integer.md: -------------------------------------------------------------------------------- 1 | #Roman to Integer 2 | 3 | [原題連結](http://www.lintcode.com/en/problem/roman-to-integer/) 4 | 5 | 題意: 6 | 7 | Given a roman numeral, convert it to an integer. 8 | 9 | The answer is guaranteed to be within the range from 1 to 3999. 10 | 11 | Have you met this question in a real interview? Yes 12 | Example 13 | IV -> 4 14 | 15 | XII -> 12 16 | 17 | XXI -> 21 18 | 19 | XCIX -> 99 20 | 21 | Clarification 22 | What is Roman Numeral? 23 | 24 | https://en.wikipedia.org/wiki/Roman_numerals 25 | https://zh.wikipedia.org/wiki/%E7%BD%97%E9%A9%AC%E6%95%B0%E5%AD%97 26 | http://baike.baidu.com/view/42061.htm 27 | 28 | 解題思路:羅馬數字的規則即左減右加,一但當前數並上一個數還大,代表是減,因此除了不斷累加當前的數,一但遇到需要減的數,,減掉兩倍該數,因該數在上一步驟已加上了,需減掉。 29 | 30 | ```java 31 | public int romanToInt(String s) { 32 | if (s == null || s.length() == 0) { 33 | return 0; 34 | } 35 | 36 | HashMap map = new HashMap(); 37 | map.put('I', 1); 38 | map.put('V', 5); 39 | map.put('X', 10); 40 | map.put('L', 50); 41 | map.put('C', 100); 42 | map.put('D', 500); 43 | map.put('M', 1000); 44 | 45 | int result = 0; 46 | for (int i = 0; i < s.length(); i++) { 47 | char c = s.charAt(i); 48 | result += map.get(c); 49 | if (i != 0) { 50 | char prev = s.charAt(i-1); 51 | if (map.get(c) > map.get(prev)) { 52 | result -= map.get(prev) * 2; 53 | } 54 | } 55 | } 56 | return result; 57 | } 58 | ``` 59 | >Time Complexity..$$O(N)$$ 60 | -------------------------------------------------------------------------------- /math/sqrtx.md: -------------------------------------------------------------------------------- 1 | #Sqrt(x) 2 | 3 | [Leetcode](https://leetcode.com/problems/sqrtx/) 4 | 5 | 題意: 6 | 7 | Implement int sqrt(int x). 8 | 9 | Compute and return the square root of x. 10 | 11 | 12 | 解題思路: 13 | 14 | 用二分法來作,不斷的驗證 mid * mid 是否等於 x,由於 mid * mid 可能會溢位,所以我們移項改驗證 mid 是否等於 x / mid,其程式碼如下: 15 | 16 | ```java 17 | public class Solution { 18 | public int mySqrt(int x) { 19 | if (x <= 0) { 20 | return x; 21 | } 22 | 23 | int l = 1; 24 | int r = x; 25 | int res = 1; 26 | 27 | while (l < r) { 28 | int mid = l + (r - l) / 2; 29 | if (mid > x / mid) { 30 | r = mid; 31 | } else { 32 | res = mid; 33 | l = mid + 1; 34 | } 35 | } 36 | 37 | return res; 38 | 39 | } 40 | } 41 | ``` 42 | 43 | -------------------------------------------------------------------------------- /math/strobogrammatic_number.md: -------------------------------------------------------------------------------- 1 | # Strobogrammatic Number 2 | 3 | [Leetcode](https://leetcode.com/problems/strobogrammatic-number/) 4 | 5 | 題意: 6 | 7 | A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down). 8 | 9 | Write a function to determine if a number is strobogrammatic. The number is represented as a string. 10 | 11 | For example, the numbers "69", "88", and "818" are all strobogrammatic. 12 | 13 | 解題思路: 14 | 15 | 先把相對應的數字放到hashmap中,再用兩根指針往中間夾,如果遇到不在map中的值,或是map.get(start) != end,則返回false。 16 | 17 | 18 | ```java 19 | public class Solution { 20 | public boolean isStrobogrammatic(String num) { 21 | HashMap map = new HashMap(); 22 | map.put('0', '0'); 23 | map.put('1', '1'); 24 | map.put('9', '6'); 25 | map.put('6', '9'); 26 | map.put('8', '8'); 27 | 28 | int start = 0; 29 | int end = num.length() - 1; 30 | while (start <= end) { 31 | char cStart = num.charAt(start); 32 | char cEnd = num.charAt(end); 33 | if (!map.containsKey(cStart) || !map.containsKey(cEnd) || map.get(cStart) != cEnd) { 34 | return false; 35 | } 36 | start++; 37 | end--; 38 | } 39 | 40 | return true; 41 | } 42 | } 43 | ``` 44 | -------------------------------------------------------------------------------- /math/strobogrammatic_number_ii.md: -------------------------------------------------------------------------------- 1 | # Strobogrammatic Number II 2 | 3 | [Leetcode](https://leetcode.com/problems/strobogrammatic-number-ii/) 4 | 5 | 題意: 6 | 7 | A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down). 8 | 9 | Find all strobogrammatic numbers that are of length = n. 10 | 11 | For example, 12 | 13 | Given n = 2, return ```["11","69","88","96"]```. 14 | 15 | **Hint:** 16 | 17 | Try to use recursion and notice that it should recurse with n - 2 instead of n - 1. 18 | 19 | 解題思路: 20 | 21 | 22 | 使用遞迴去作,由於n可能是奇數或偶數,因此終止條件有0與1兩個,且需要特別處理一下00這個數,此數不是Strobogrammatic number,因此加了個條件當n != m時才在前後加上00 23 | 24 | 25 | ```java 26 | public class Solution { 27 | public List findStrobogrammatic(int n) { 28 | return helper(n, n); 29 | } 30 | 31 | private List helper(int n, int m) { 32 | if (n == 0) { 33 | return new ArrayList(Arrays.asList("")); 34 | } 35 | if (n == 1) { 36 | return new ArrayList(Arrays.asList("0","1","8")); 37 | } 38 | 39 | List list = helper(n - 2, m); 40 | List res = new ArrayList(); 41 | for (int i = 0; i < list.size(); i++) { 42 | String cur = list.get(i); 43 | 44 | //重點,防止"00"這種corner case 45 | if (n != m) { 46 | res.add("0" + cur + "0"); 47 | } 48 | 49 | res.add("1" + cur + "1"); 50 | res.add("6" + cur + "9"); 51 | res.add("8" + cur + "8"); 52 | res.add("9" + cur + "6"); 53 | } 54 | 55 | return res; 56 | } 57 | } 58 | ``` 59 | --- 60 | ###Reference 61 | 1. https://leetcode.com/discuss/50412/ac-clean-java-solution -------------------------------------------------------------------------------- /math/trailing_zeros.md: -------------------------------------------------------------------------------- 1 | #Trailing Zeros 2 | 3 | 題意:給予一個數 $$n$$ ,求 $$n!$$ 有多少個零。 4 | 5 | 解題思路:會構成 $$0$$ 只有兩個 factor,5 與 2,由於 2 的個數一定比 5 多,因此只需要求有幾個5就好了,但是不能直接只除以5,5 的倍數 25,125,625…皆要考慮進去。 6 | 7 | 原本使用以下解法會出現超時的錯誤 8 | 9 | ```java 10 | public long trailingZeros(long n) { 11 | long count = 0; 12 | for (int i = 5; i <= n; i = i * 5) { 13 | count += n / i; 14 | } 15 | return count; 16 | } 17 | ``` 18 | 19 | 因此改用遞迴的方式實作,程式碼如下: 20 | 21 | ```java 22 | public long trailingZeros(long n) { 23 | 24 | if (n < 5) { 25 | return 0; 26 | } 27 | 28 | return n / 5 + trailingZeros(n / 5); 29 | } 30 | ``` -------------------------------------------------------------------------------- /math/triangle.md: -------------------------------------------------------------------------------- 1 | #Triangle 2 | 3 | []() 4 | 5 | 題意:找出由頂到底的最少成本路徑 6 | 7 | 解題思路:從底部往上算, 不斷透過以下方程式更新陣列,最後回傳triangle[0][0]即可。 8 | 9 | >```triangle[i][j] = min(triangle[i+1][j], triangle[i+1][j+1]) + triangle[i][j]``` 10 | 11 | ```java 12 | public int minimumTotal(List> triangle) { 13 | 14 | if (triangle == null || triangle.size() == 0) { 15 | return 0; 16 | } 17 | 18 | for (int i = triangle.size() - 2; i >= 0; i--) { 19 | List cur = triangle.get(i); 20 | List child = triangle.get(i+1); 21 | for (int j = 0; j < cur.size(); j++) { 22 | int min = Math.min(child.get(j), child.get(j+1)); 23 | cur.set(j, min + cur.get(j)); 24 | } 25 | } 26 | 27 | return triangle.get(0).get(0); 28 | } 29 | ``` -------------------------------------------------------------------------------- /math/ugly_number.md: -------------------------------------------------------------------------------- 1 | #Ugly Number 2 | 3 | [原題網址](https://leetcode.com/problems/ugly-number/) 4 | 5 | 題意: 6 | 7 | Ugly Number的定義,他的 facto 只能夠是 3,5,7。 8 | 9 | 給定一個數 n ,判斷該數是否為 ugly number 10 | 11 | 解題思路: 12 | 13 | 使用遞回去作,一方面判斷 n 除以 3 5 7 的餘數是否為0 ,若是的話,則繼續往下判斷,其程式碼如下: 14 | 15 | ```java 16 | public boolean isUgly(int n) { 17 | if (n < 1) 18 | return false; 19 | if (n == 1) 20 | return true; 21 | 22 | return ((n % 2 == 0) && isUgly(n / 2)) || 23 | ((n % 3 == 0) && isUgly(n / 3)) || 24 | ((n % 5 == 0) && isUgly(n / 5)); 25 | } 26 | ``` 27 | 28 | 29 | 非遞迴 30 | 31 | ```java 32 | public class Solution { 33 | public boolean isUgly(int num) { 34 | if (num == 1) { 35 | return true; 36 | } 37 | if (num == 0) { 38 | return false; 39 | } 40 | 41 | while (num % 2 == 0) { 42 | num /= 2; 43 | } 44 | 45 | while (num % 3 == 0) { 46 | num /= 3; 47 | } 48 | 49 | while (num % 5 == 0) { 50 | num /= 5; 51 | } 52 | 53 | return num == 1; 54 | } 55 | } 56 | ``` 57 | -------------------------------------------------------------------------------- /matrix/set_matrix_zeroes.md: -------------------------------------------------------------------------------- 1 | #Set Matrix Zeroes 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/set-matrix-zeroes/) 4 | 5 | 題意: 6 | 7 | 8 | 解題思路:如果直接在原矩陣上把為0的元素之該行該列設為0 ,到最後整個矩陣都會為0 ,我們利用一個 list 來存放為0 的元素,接著再遍歷一次該 list,把list中所有元素的該行與該列設為0即可,程式碼如下: 9 | 10 | ```java 11 | public class Solution { 12 | /** 13 | * @param matrix: A list of lists of integers 14 | * @return: Void 15 | */ 16 | 17 | public class Pair { 18 | int x; 19 | int y; 20 | public Pair(int x, int y) { 21 | this.x = x; 22 | this.y = y; 23 | } 24 | } 25 | 26 | public void setZeroes(int[][] matrix) { 27 | 28 | if (matrix == null || matrix.length == 0) { 29 | return; 30 | } 31 | 32 | ArrayList pairs = new ArrayList(); 33 | int rows = matrix.length; 34 | int cols = matrix[0].length; 35 | 36 | for (int i = 0; i < rows; i++) { 37 | for (int j = 0; j < cols; j++) { 38 | if (matrix[i][j] == 0) { 39 | pairs.add(new Pair(i, j)); 40 | } 41 | } 42 | } 43 | 44 | for (int i = 0; i < pairs.size(); i++) { 45 | Pair p = pairs.get(i); 46 | for (int j = 0; j < rows; j++) { 47 | matrix[j][p.y] = 0; 48 | } 49 | for (int j = 0; j < cols; j++) { 50 | matrix[p.x][j] = 0; 51 | } 52 | } 53 | } 54 | } 55 | ``` 56 | > Time Complexity:$$O(N^{2})$$ 57 | > Space Complexity:$$O(2M)$$,M代表元素為 的個數。 58 | 59 | --- 60 | -------------------------------------------------------------------------------- /merge-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/merge-sort.gif -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.zhokhov 5 | interview 6 | jar 7 | 1.0-SNAPSHOT 8 | interview 9 | http://maven.apache.org 10 | 11 | -------------------------------------------------------------------------------- /quick-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/quick-sort.gif -------------------------------------------------------------------------------- /segment_tree.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/segment_tree.md -------------------------------------------------------------------------------- /segment_tree/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/segment_tree/.DS_Store -------------------------------------------------------------------------------- /segment_tree/interval_sum.md: -------------------------------------------------------------------------------- 1 | #Interval Sum I 2 | [原題網址](http://www.lintcode.com/en/problem/interval-sum/) 3 | 4 | 求某區間內的總和,因陣列不會改變,因此可以另外建立一個 sum 的陣列,sum[i] 代表由 A[0] 加到A[i]的總和。 5 | 6 | 若區間為 (x , y),等同求 sum[y] - sum[x-1],程式碼如下。 7 | 8 | ```java 9 | public ArrayList intervalSum(int[] A, 10 | ArrayList queries) { 11 | 12 | ArrayList res = new ArrayList(); 13 | 14 | if (A == null || A.length == 0 || queries == null || queries.size() == 0) { 15 | return res; 16 | } 17 | 18 | long[] sum = new long[A.length]; 19 | sum[0] = A[0]; 20 | 21 | for (int i = 1; i < A.length; i++) { 22 | sum[i] = A[i] + sum[i-1]; 23 | } 24 | 25 | for (int i = 0; i < queries.size(); i++) { 26 | Interval cur = queries.get(i); 27 | int start = cur.start; 28 | int end = cur.end; 29 | long curRes; 30 | 31 | if (start >= 0 && start < A.length && end >= 0 && end < A.length) { 32 | if (start == 0) { 33 | curRes = sum[end]; 34 | } else { 35 | curRes = sum[end] - sum[start - 1]; 36 | } 37 | res.add(curRes); 38 | } 39 | } 40 | 41 | return res; 42 | } 43 | ``` 44 | -------------------------------------------------------------------------------- /segment_tree/segment_tree_build.md: -------------------------------------------------------------------------------- 1 | #Segment Tree Build I 2 | 只建區間,尚未回溯回填該區間的最大或最小值 3 | 4 | [原題網址](http://www.lintcode.com/en/problem/segment-tree-build/) 5 | 6 | ```java 7 | public SegmentTreeNode build(int start, int end) { 8 | 9 | //記得處理corner case,否則會無限遞迴 10 | if (start > end) { 11 | return null; 12 | } 13 | 14 | // start == end代表達到leaf,直接產生一個新leaf回傳即可 15 | if (start == end) { 16 | SegmentTreeNode newNode = new SegmentTreeNode(start, end); 17 | return newNode; 18 | } 19 | 20 | // 否則還要繼續遞迴下去,分別遞迴左右子樹之後再回傳 21 | int mid = (start + end) / 2; 22 | SegmentTreeNode root = new SegmentTreeNode(start, end); 23 | root.left = build(start, mid); 24 | root.right = build(mid + 1, end); 25 | 26 | return root; 27 | 28 | } 29 | 30 | ``` 31 | --- 32 | #Segment Tree Build II 33 | 除了與第一部份一樣之外,還需回傳該區間的最大或最小值 34 | 35 | -------------------------------------------------------------------------------- /segment_tree/segment_tree_build_ii.md: -------------------------------------------------------------------------------- 1 | #Segment Tree Build II 2 | 3 | [原題連結](http://www.lintcode.com/en/problem/segmemt-tree-build-ii/) 4 | 5 | 題意:為[Segment Tree Build I](segment_tree/segment_tree_build_i.md) 的延伸,此為max segment tree,多一個max欄位來儲存該區段的最大值。 6 | 7 | 解題思路:程式碼如下 8 | 9 | 10 | ```java 11 | public class Solution { 12 | /** 13 | *@param A: a list of integer 14 | *@return: The root of Segment Tree 15 | */ 16 | public SegmentTreeNode build(int[] A) { 17 | 18 | if (A == null || A.length == 0) { 19 | return null; 20 | } 21 | 22 | return buildST(A, 0, A.length - 1); 23 | } 24 | 25 | private SegmentTreeNode buildST(int[] A, int start, int end) { 26 | if (start > end) { 27 | return null; 28 | } 29 | 30 | SegmentTreeNode root; 31 | if (start == end) { 32 | root = new SegmentTreeNode(start, end, A[start]); 33 | } else { 34 | int mid = start + (end - start) /2; 35 | root = new SegmentTreeNode(start, end, 0); 36 | root.left = buildST(A, start, mid); 37 | root.right = buildST(A, mid + 1, end); 38 | root.max = Math.max(root.left.max, root.right.max); 39 | } 40 | 41 | return root; 42 | } 43 | } 44 | ``` -------------------------------------------------------------------------------- /segment_tree/segment_tree_modify.md: -------------------------------------------------------------------------------- 1 | #Segment Tree Modify 2 | 3 | 找到需要更改的葉節點,並將更新後的最大值回遡上來 4 | 5 | [原題網址](http://www.lintcode.com/en/problem/segment-tree-modify/) 6 | ```java 7 | public void modify(SegmentTreeNode root, int index, int value) { 8 | 9 | if (root.start == index && root.end == index) { 10 | root.max = value; 11 | return; 12 | } 13 | 14 | int mid = (root.start + root.end) / 2; 15 | 16 | if (index <= mid) { 17 | modify(root.left, index, value); 18 | } else { 19 | modify(root.right, index, value); 20 | } 21 | 22 | root.max = Math.max(root.left.max, root.right.max); 23 | } 24 | ``` -------------------------------------------------------------------------------- /segment_tree/segment_tree_query.md: -------------------------------------------------------------------------------- 1 | #Segment Tree Query 2 | 3 | [原題網址](http://www.lintcode.com/en/problem/segment-tree-query/) 4 | 5 | 解題思路: 6 | 7 | 首先需要知道樹是怎麼對切的: 8 | 9 | 左邊的index 的上限是到mid,右邊的index的下限是mid + 1,之後就好作了,但請記得以下兩個條件: 10 | 11 | 1. 是比較 root.start == root.end來判斷終止條件,而非 start == end。 12 | 2. 切mid是用 root.start 與 root.end而非 start 與 end 13 | 14 | 接著判斷start 與 end範圍是否在左邊、右邊或跨區域。 15 | 16 | ```java 17 | public int query(SegmentTreeNode root, int start, int end) { 18 | 19 | if (root.start == start && root.end == end) { 20 | return root.max; 21 | } 22 | 23 | int mid = (root.start + root.end) / 2; 24 | int leftMax = Integer.MIN_VALUE; 25 | int rightMax = Integer.MIN_VALUE; 26 | 27 | // 左半邊 28 | // 因往左半邊搜的upper bound是mid 29 | // 因此檢查是否start <= mid 30 | if (start <= mid) { 31 | // 如果end比mid小的話,則表示只需找右半邊,且不需分裂 32 | // 若比end比mid大的話,則右邊也有值要查找, 33 | if (end < mid) { 34 | leftMax = query(root.left, start, end); 35 | } else { 36 | leftMax = query(root.left, start, mid); 37 | } 38 | } 39 | 40 | // 右半邊 41 | // 因右半邊的lower bound是mid+1,所以要確保end有大於mid 42 | if (end > mid) { 43 | // 如果start有小於或等於mid的話,代表左半邊也有值要查找, 44 | // 直接從mid+1到end找,再與左半邊合併 45 | // 若start比mid大,代表一定所有可能值一定在右半邊 46 | if (start <= mid) { 47 | rightMax = query(root.right, mid + 1, end); 48 | } else { 49 | rightMax = query(root.right, start, end); 50 | } 51 | } 52 | 53 | return Math.max(leftMax, rightMax); 54 | } 55 | ``` 56 | 57 | 58 | #Segment Tree Query II 59 | 60 | 請注意,此題為求和型線段樹,與第一題不同 61 | 62 | [原題網址](http://www.lintcode.com/en/problem/segment-tree-query-ii/) 63 | 64 | -------------------------------------------------------------------------------- /segment_tree/segment_tree_query_ii.md: -------------------------------------------------------------------------------- 1 | #Segment Tree Query II 2 | 3 | 此為計數型線段樹, 4 | 5 | ```java 6 | public int query(SegmentTreeNode root, int start, int end) { 7 | 8 | if (start > end || root == null) { 9 | return 0; 10 | } 11 | 12 | //注意這裡,與傳統型線段樹不同! 13 | if (start <= root.start && root.end <= end) { 14 | return root.count; 15 | } 16 | 17 | int mid = (root.start + root.end) / 2; 18 | int leftCount = 0; 19 | int rightCount = 0; 20 | 21 | if (start <= mid) { 22 | if (mid < end) { 23 | leftCount = query(root.left, start, mid); 24 | } else { 25 | leftCount = query(root.left, start, end); 26 | } 27 | } 28 | 29 | if (mid < end) { 30 | if (start <= mid) { 31 | rightCount = query(root.right, mid + 1, end); 32 | } else { 33 | rightCount = query(root.right, start, end); 34 | } 35 | } 36 | 37 | return leftCount + rightCount; 38 | 39 | } 40 | ``` -------------------------------------------------------------------------------- /selection-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/selection-sort.gif -------------------------------------------------------------------------------- /sliding_window.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/sliding_window.md -------------------------------------------------------------------------------- /sql/SQLInterview.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/sql/SQLInterview.pdf -------------------------------------------------------------------------------- /sql/SQL_question_set 2: -------------------------------------------------------------------------------- 1 | --1. Write query to get all employee detail from EmployeeDetail table. 2 | SELECT * from EmployeeDetail; 3 | 4 | --2. Write query to get only first name column from EmployeeDetail table. 5 | SELECT firstname from EmployeeDetail; 6 | 7 | --3. Write query to get first name in upper case as "First Name". 8 | SELECT UPPER(firstname) AS First Name From EmployeeDetail; 9 | 10 | --4. Write query to get first name in lower case as "First Name". 11 | SELECT LOWER(firstname) AS First Name From EmployeeDetail; 12 | 13 | --5. Write a query for combine first name and last name as "Name", (also include white space between first name and last name) 14 | SELECT firstname + '' +lastname AS Name From EmployeeDetail; 15 | 16 | --6. SELECT employee detail whose name is "Vikas". 17 | SELECT * From EmployeeDetail WHERE firstname= 'Vikas'; 18 | 19 | --7. Get all employee detail whoes name start with letter a. 20 | SELECT * From EmployeeDetail Where firstname LIKE 'a%'; 21 | 22 | --8. Get all employee detail whoes name contains letter k. 23 | SELECT * From EmployeeDetail WHERE firstname LIKE '%k%'; 24 | 25 | --9. Get all employee detail whoes name end with letter h. 26 | SELECT * From EmployeeDetail WHERE firstname LIKE '%h'; 27 | 28 | --10. Get all employee detail whoes name start with any single letter between a-p. 29 | SELECT * From EmployeeDetail WHERE firstname LIKE '[a-p]%'; 30 | 31 | --11. Get all employee detail whoes name not start with any single letter between a-p. 32 | SELECT * From EmployeeDetail WHERE firstname LIKE '[^a-p]%'; 33 | 34 | -------------------------------------------------------------------------------- /sql/combine_two_tables.md: -------------------------------------------------------------------------------- 1 | # Combine Two Tables 2 | 3 | [Leetcode](https://leetcode.com/problems/combine-two-tables/) 4 | 5 | **題意:** 6 | 7 | **Table: Person** 8 | ``` 9 | +-------------+---------+ 10 | | Column Name | Type | 11 | +-------------+---------+ 12 | | PersonId | int | 13 | | FirstName | varchar | 14 | | LastName | varchar | 15 | +-------------+---------+ 16 | ``` 17 | PersonId is the primary key column for this table. 18 | 19 | **Table: Address** 20 | ``` 21 | +-------------+---------+ 22 | | Column Name | Type | 23 | +-------------+---------+ 24 | | AddressId | int | 25 | | PersonId | int | 26 | | City | varchar | 27 | | State | varchar | 28 | +-------------+---------+ 29 | ``` 30 | AddressId is the primary key column for this table. 31 | 32 | Write a SQL query for a report that provides the following information for each person in the Person table, regardless if there is an address for each of those people: 33 | ``` 34 | FirstName, LastName, City, State 35 | ``` 36 | 37 | **解題思路:** 38 | 39 | 在這裡使用left join來幫助我們解這道題,left join表示以左邊的表格為主,加上用on 的keyword把符合條件的合起來。 40 | 41 | ```sql 42 | SELECT Person.FirstName, Person.LastName, Address.City, Address.State 43 | FROM Person LEFT JOIN Address ON Person.PersonId = Address.PersonId; 44 | 45 | ``` 46 | 47 | 48 | --- 49 | ###Reference 50 | 1. https://leetcode.com/discuss/21216/its-a-simple-question-of-left-join-my-solution-attached -------------------------------------------------------------------------------- /sql/nth_highest_salary.md: -------------------------------------------------------------------------------- 1 | # Nth Highest Salary 2 | 3 | [Leetcode](https://leetcode.com/problems/nth-highest-salary/) 4 | 5 | **題意:** 6 | 7 | Write a SQL query to get the nth highest salary from the Employee table. 8 | ``` 9 | +----+--------+ 10 | | Id | Salary | 11 | +----+--------+ 12 | | 1 | 100 | 13 | | 2 | 200 | 14 | | 3 | 300 | 15 | +----+--------+ 16 | ``` 17 | For example, given the above Employee table, the nth highest salary where n = 2 is 200. If there is no nth highest salary, then the query should return null. 18 | 19 | **解題思路:** 20 | 21 | 需要注意的就是我們先定義一個變數m,表示取出的資料中,要跳過M個之後,再選1個出來,即是我們要的數。 22 | 23 | >LIMIT N-1, 1 :表示跳過n-1個數之後1挑1個數出來。 24 | 25 | ```sql 26 | CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT 27 | BEGIN 28 | DECLARE M INT; 29 | SET M = N - 1; 30 | RETURN ( 31 | # Write your MySQL query statement below. 32 | SELECT DISTINCT Salary FROM Employee ORDER BY Salary DESC LIMIT M, 1 33 | ); 34 | END 35 | ``` 36 | 37 | --- 38 | ###Reference 39 | 1. https://leetcode.com/discuss/21311/accpted-solution-for-the-nth-highest-salary -------------------------------------------------------------------------------- /sql/rank_scores.md: -------------------------------------------------------------------------------- 1 | # Rank Scores 2 | 3 | [Leetcode](https://leetcode.com/problems/rank-scores/) 4 | 5 | **題意:** 6 | 7 | Write a SQL query to rank scores. If there is a tie between two scores, both should have the same ranking. Note that after a tie, the next ranking number should be the next consecutive integer value. In other words, there should be no "holes" between ranks. 8 | ``` 9 | +----+-------+ 10 | | Id | Score | 11 | +----+-------+ 12 | | 1 | 3.50 | 13 | | 2 | 3.65 | 14 | | 3 | 4.00 | 15 | | 4 | 3.85 | 16 | | 5 | 4.00 | 17 | | 6 | 3.65 | 18 | +----+-------+ 19 | ``` 20 | For example, given the above Scores table, your query should generate the following report (order by highest score): 21 | ``` 22 | +-------+------+ 23 | | Score | Rank | 24 | +-------+------+ 25 | | 4.00 | 1 | 26 | | 4.00 | 1 | 27 | | 3.85 | 2 | 28 | | 3.65 | 3 | 29 | | 3.65 | 3 | 30 | | 3.50 | 4 | 31 | +-------+------+ 32 | ``` 33 | 34 | **解題思路:** 35 | 36 | 37 | ```sql 38 | SELECT 39 | Score, 40 | (SELECT count(DISTINCT Score) FROM Scores WHERE Score >= s.Score) AS Rank 41 | FROM Scores AS s 42 | ORDER BY Score DESC 43 | ``` 44 | 45 | --- 46 | ###Reference 47 | 1. https://leetcode.com/discuss/40116/simple-short-fast 48 | -------------------------------------------------------------------------------- /sql/second_highest_salary.md: -------------------------------------------------------------------------------- 1 | # Second Highest Salary 2 | 3 | [Leetcode](https://leetcode.com/problems/second-highest-salary/) 4 | 5 | 題意: 6 | 7 | Write a SQL query to get the second highest salary from the Employee table. 8 | ``` 9 | +----+--------+ 10 | | Id | Salary | 11 | +----+--------+ 12 | | 1 | 100 | 13 | | 2 | 200 | 14 | | 3 | 300 | 15 | +----+--------+ 16 | ``` 17 | For example, given the above Employee table, the second highest salary is 200. If there is no second highest salary, then the query should return null. 18 | 19 | 解題思路: 20 | 21 | 從所有小於最大值的所有元素中選出最大的即可。 22 | 23 | ```sql 24 | SELECT MAX(Salary) 25 | FROM Employee 26 | WHERE Salary < (SELECT MAX(Salary) FROM Employee) 27 | ``` 28 | 29 | 30 | --- 31 | ###Reference 32 | 1. https://leetcode.com/discuss/23759/my-tidy-soution -------------------------------------------------------------------------------- /stack.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/stack.md -------------------------------------------------------------------------------- /stack/evaluate_reverse_polish_notation.md: -------------------------------------------------------------------------------- 1 | #Evaluate Reverse Polish Notation 2 | 3 | [原題連結](http://www.lintcode.com/en/problem/evaluate-reverse-polish-notation/) 4 | 5 | ```java 6 | public class Solution { 7 | /** 8 | * @param tokens The Reverse Polish Notation 9 | * @return the value 10 | */ 11 | public int evalRPN(String[] tokens) { 12 | 13 | if (tokens == null || tokens.length == 0) { 14 | return 0; 15 | } 16 | 17 | Stack stack = new Stack(); 18 | String operators = "+-*/"; 19 | 20 | for (int i = 0; i < tokens.length; i++) { 21 | 22 | String cur = tokens[i]; 23 | 24 | if (operators.contains(cur)) { 25 | int b = stack.pop(); 26 | int a = stack.pop(); 27 | stack.push(calculate(a, b, cur.charAt(0))); 28 | } else { 29 | int value = Integer.parseInt(tokens[i]); 30 | stack.push(value); 31 | } 32 | } 33 | 34 | return stack.pop(); 35 | } 36 | 37 | private int calculate(int a, int b, char operator) { 38 | 39 | switch(operator) { 40 | case '+': 41 | return a + b; 42 | case '-': 43 | return a - b; 44 | case '*': 45 | return a * b; 46 | case '/': 47 | return a / b; 48 | } 49 | return 0; 50 | } 51 | } 52 | 53 | ``` -------------------------------------------------------------------------------- /stack/implement_stack_using_queues.md: -------------------------------------------------------------------------------- 1 | # Implement Stack using Queues 2 | 3 | [Leetcode](https://leetcode.com/problems/implement-stack-using-queues/) 4 | 5 | 題意: 6 | 7 | Implement the following operations of a stack using queues. 8 | 9 | - push(x) -- Push element x onto stack. 10 | - pop() -- Removes the element on top of the stack. 11 | - top() -- Get the top element. 12 | - empty() -- Return whether the stack is empty. 13 | 14 | **Notes:** 15 | 16 | - You must use only standard operations of a queue -- which means only push to back, peek/pop from front, size, and is empty operations are valid. 17 | 18 | - Depending on your language, queue may not be supported natively. You may simulate a queue by using a list or deque (double-ended queue), as long as you use only standard operations of a queue. 19 | - You may assume that all operations are valid (for example, no pop or top operations will be called on an empty stack). 20 | 21 | 22 | 23 | 解題思路: 24 | 25 | 一旦插入新值時,要把前面的所有值不斷poll offer到queue的尾端。 26 | 27 | ```java 28 | class MyStack { 29 | // Push element x onto stack. 30 | Queue q = new LinkedList(); 31 | public void push(int x) { 32 | q.offer(x); 33 | for (int i = 0; i < q.size() - 1; i++) { 34 | q.offer(q.poll()); 35 | } 36 | } 37 | 38 | // Removes the element on top of the stack. 39 | public void pop() { 40 | q.poll(); 41 | } 42 | 43 | // Get the top element. 44 | public int top() { 45 | return q.peek(); 46 | } 47 | 48 | // Return whether the stack is empty. 49 | public boolean empty() { 50 | return q.isEmpty(); 51 | } 52 | } 53 | ``` 54 | 55 | --- 56 | ###Reference 57 | 1. https://leetcode.com/discuss/46975/a-simple-c-solution -------------------------------------------------------------------------------- /stack/min_stack.md: -------------------------------------------------------------------------------- 1 | # Min Stack 2 | 3 | [Leetcode](https://leetcode.com/problems/min-stack/) 4 | 5 | 題意: 6 | 7 | Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. 8 | 9 | - push(x) -- Push element x onto stack. 10 | - pop() -- Removes the element on top of the stack. 11 | - top() -- Get the top element. 12 | - getMin() -- Retrieve the minimum element in the stack. 13 | 14 | 15 | 解題思路: 16 | 17 | 18 | ```java 19 | 20 | class MinStack { 21 | 22 | Stack stack = new Stack<>(); 23 | Stack mStack = new Stack<>(); 24 | public void push(int x) { 25 | stack.push(x); 26 | if (mStack.isEmpty() || mStack.peek() >= x) { 27 | mStack.push(x); 28 | } 29 | } 30 | 31 | public void pop() { 32 | if (!stack.isEmpty()) { 33 | int val = stack.pop(); 34 | if (!mStack.isEmpty() && val == mStack.peek()) { 35 | mStack.pop(); 36 | } 37 | } 38 | } 39 | 40 | public int top() { 41 | if (!stack.isEmpty()) { 42 | return stack.peek(); 43 | } 44 | return -1; 45 | } 46 | 47 | public int getMin() { 48 | if (!mStack.isEmpty()) { 49 | return mStack.peek(); 50 | } 51 | return -1; 52 | } 53 | } 54 | 55 | ``` -------------------------------------------------------------------------------- /string.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Data-Structures/47491839a726fa05a304ebe1d359f9c717e1e8b0/string.md -------------------------------------------------------------------------------- /template.md: -------------------------------------------------------------------------------- 1 | # Template 2 | 3 | -------------------------------------------------------------------------------- /trie.md: -------------------------------------------------------------------------------- 1 | # Trie 2 | 3 | --------------------------------------------------------------------------------