├── 0-1_knapsack.cpp ├── 0-sum_subset.cpp ├── 2-exists.cpp ├── 2-for-all.cpp ├── 3-sum-closest.cc ├── 3-sum.cpp ├── 4-sum.cc ├── Add_operators_in_string.cpp ├── AddingCredits.cpp ├── Anagrams.cpp ├── Anonymous_letter.cpp ├── Approximate_sort.cpp ├── Arbitrage.cpp ├── AsyncThread.java ├── BST_lowest_common_ancestor.cpp ├── BST_parent_prototype.h ├── BST_prototype.h ├── BST_prototype_shared_ptr.h ├── BST_sorted_order.cpp ├── BST_to_sorted_doubly_list.cpp ├── Balanced_binary_tree.cpp ├── Ball.java ├── Bentleybsearch.cpp ├── Biggest_product_n-1.cpp ├── Biggest_product_n-1_math.cpp ├── Bignumber_multiplication.cpp ├── BinaryTreeCanonical.java ├── Binary_search_Ai=i.cpp ├── Binary_search_circular_array.cpp ├── Binary_search_circular_array_with_duplicates.cpp ├── Binary_search_first_k.cpp ├── Binary_search_larger_k.cpp ├── Binary_search_unknown_length.cpp ├── Binary_tree_level_order.cpp ├── Binary_tree_lock.cpp ├── Binary_tree_prototype_template.h ├── Binary_tree_to_doubly_linked_list.cpp ├── Binary_tree_utils.h ├── Binary_tree_with_parent_prototype.h ├── Build_BST_from_sorted_array.cpp ├── Can_string_be_palindrome.cpp ├── Can_string_be_palindrome_hash.h ├── Can_string_be_palindrome_sorting.h ├── Celebrity_finding.cpp ├── Checking_cycle.cpp ├── Checking_cycle.h ├── Checking_cycle_alternative.cpp ├── Checking_cycle_template.cpp ├── Circular_queue.cpp ├── Close_search.cpp ├── Closest_int_same_bits.cpp ├── Closest_pair_points.cpp ├── Closest_palindrome.cpp ├── Closest_stars.cpp ├── Closest_to_median.cpp ├── Collatz.java ├── Collatz_conjecture.cpp ├── Compare_k-th_largest_in_heap.cpp ├── Completion_search.cpp ├── Completion_search_space_efficient.cpp ├── Computing_binomial_coefficients.cpp ├── Computing_x^n.cpp ├── Connect_leaves_binary_tree.cpp ├── Convert_base.cpp ├── Copying_postings_list.cpp ├── Copying_skip_list_template.cpp ├── Count_inversions.cpp ├── Count_occurrences_in_sentence.cpp ├── Counting_sort.cpp ├── Deletion_list.cpp ├── Descendant_and_ancestor.cpp ├── Division.cpp ├── Doors.cpp ├── Doors.java ├── Drawing_skylines.cpp ├── Dutch_national_flag.cpp ├── Elias.java ├── Elias_coding.cpp ├── Eliminate_duplicate.cpp ├── EquivClasses.java ├── Equiv_classes.cpp ├── Even_odd_merge_linked_list.cpp ├── Exterior_binary_tree.cpp ├── Find_element_appears_once.cpp ├── Find_k_largest_BST.cpp ├── Find_kth_element_in_two_sorted_arrays.cpp ├── Find_kth_element_in_two_sorted_arrays_AFI.cpp ├── Find_missing_and_duplicate.cpp ├── Find_missing_and_duplicate_XOR.cpp ├── Finding_min_max.cpp ├── GCD.cpp ├── GCD.h ├── Gassing_up.cpp ├── Gaussian_elimination.cpp ├── Gaussian_primes.cpp ├── Generating_a_b_sqrt2.cpp ├── GreatestCommonDivisor.java ├── Hanoi.java ├── Hash_dictionary.cpp ├── Height_determination.cpp ├── House_majority.cpp ├── Huffman_encoding.cpp ├── Image_compression.cpp ├── Inorder_traversal_no_stack.cpp ├── Inorder_traversal_with_parent.cpp ├── Interconverting_string_integer.cpp ├── Intersect_rectangle.cpp ├── Intersect_sorted_arrays.cpp ├── Intersect_sorted_arrays1.h ├── Intersect_sorted_arrays2.h ├── Intersect_sorted_arrays3.h ├── LRUCache.cpp ├── Largest_rectangle_under_skyline.cpp ├── Largest_rectangle_under_skyline.h ├── Levenshtein_distance.cpp ├── Line_most_points.cpp ├── Linked_list_prototype.h ├── Load_balancing.cpp ├── Longest_increasing_subarray.cpp ├── Longest_nondecreasing_subsequence.cpp ├── Longest_nondecreasing_subsequence_n2.h ├── Longest_nondecreasing_subsequence_nlogn.h ├── Longest_subarray_k.cpp ├── Longest_subarray_k_improved_temp.cc ├── Lowest_common_ancestor.cpp ├── Lowest_common_ancestor_hash.cpp ├── Lowest_common_ancestor_no_parent.cpp ├── Matrix_rotation.cpp ├── Matrix_rotation_constant.cpp ├── Matrix_rotation_naive.cpp ├── Matrix_search.cpp ├── Max-sum_subarray.cpp ├── Max_difference_k_pairs.cpp ├── Max_difference_unlimited_pairs.cpp ├── Max_submatrix_rectangle.cpp ├── Max_submatrix_rectangle_brute_force.h ├── Max_submatrix_rectangle_improved.cpp ├── Max_submatrix_square.cpp ├── Maximum_sliding_window_template.cpp ├── Maximum_subarray_in_circular_array.cpp ├── Maximum_subarray_in_circular_array_constant_space.cpp ├── Median_sorted_circular_linked_list.cpp ├── Merge_sorted_arrays.cpp ├── Merge_sorted_arrays.h ├── Merge_sorted_lists.cpp ├── Merge_sorted_lists.h ├── Merge_sorted_lists_template.cpp ├── Merge_two_BSTs.cpp ├── Minimum_distance_3_sorted_arrays.cpp ├── Minimum_subarray_difference.cpp ├── Minimum_waiting_time.cpp ├── Missing_element.cpp ├── Multibet_card_color_game.cpp ├── MultiplyShiftAdd.cpp ├── Nearest_repetition.cpp ├── Nearest_restaurant.cpp ├── Next_permutation.cpp ├── Number_ways.cpp ├── Number_ways_obstacles.cpp ├── Offline_minimum.cpp ├── Offline_sampling.cpp ├── Online_median.cpp ├── Online_sampling.cpp ├── Overlapping_lists.cpp ├── Overlapping_lists_no_cycle.cpp ├── Overlapping_lists_no_cycle.h ├── Painting_iterative.cpp ├── Painting_recursive.cpp ├── Palindrome_linked_list.cpp ├── Parity.cpp ├── Parity1.h ├── Parity2.h ├── Parity3.h ├── Parity4.h ├── Permutation_array.cpp ├── Permutation_array1.h ├── Permutation_array2.h ├── Phone_mnemonic.cpp ├── Picking_up_coins.cpp ├── Picking_up_coins_dont_lose.cpp ├── Planning_fishing.cpp ├── Points_covering_intervals.cpp ├── Points_covering_intervals_alternative.cpp ├── Postings_list_prototype.h ├── Power_set.cpp ├── Power_set_alternative.cpp ├── Pretty_printing.cpp ├── Prime_sieve.cpp ├── PrintMatrixSpiral.java ├── Queue_from_stacks.cpp ├── Queue_using_two_integers.cpp ├── Queue_with_max.cpp ├── Queue_with_max_using_deque.cpp ├── Queue_with_max_using_deque.h ├── RPN.cpp ├── RPN.java ├── RW.java ├── Rearrange.cpp ├── Rebuild_BST_postorder.cpp ├── Rebuild_BST_preorder.cpp ├── Rebuild_BST_preorder_better.cpp ├── Reconstruct_binary_tree_post_in_orders.cpp ├── Reconstruct_binary_tree_pre_in_orders.cpp ├── Reconstruct_preorder_with_null.cpp ├── RegExp.java ├── Regular_expression.cpp ├── Remove_kth_last_list.cpp ├── Rendering_calendar.cpp ├── Replace_and_remove.cpp ├── Reservoir_sampling.cpp ├── Reverse_bits.cpp ├── Reverse_linked_list_iterative.h ├── Reverse_linked_list_iterative_template.cpp ├── Reverse_linked_list_recursive.cpp ├── Reverse_words.cpp ├── Road_network.cpp ├── Robot_battery.cpp ├── Rotate_array.cpp ├── Rotate_array.h ├── Rotate_array_permutation.h ├── Run_length_compression.cpp ├── S1.java ├── S2.java ├── Score_combination.cpp ├── Score_permutation.cpp ├── Search_BST_first_larger_k.cpp ├── Search_BST_for_first_occurrence_iterative.cpp ├── Search_BST_for_first_occurrence_recursive.cpp ├── Search_a_pair_sorted_array.cpp ├── Search_frequent_items.cpp ├── Search_majority.cpp ├── Search_maze.cpp ├── Search_min_first_BST.cpp ├── Search_postings_list_iterative.cpp ├── Search_postings_list_recursive.cpp ├── Search_skip_list_iterative_template.cpp ├── Search_skip_list_recursive_template.cpp ├── Shortest_path_fewest_edges.cpp ├── Shortest_unique_prefix.cpp ├── SimpleWebServer.java ├── Sliding_window.cpp ├── Smallest_subarray_covering_set.cpp ├── Smallest_subarray_covering_set.h ├── Smallest_subarray_covering_set_stream.h ├── SolovayStrassen.java ├── Sorted_list_to_BST.cpp ├── Spiral_matrix.cpp ├── Spiral_matrix_clockwise.cpp ├── Spreadsheet_encoding.cpp ├── Square_root.cpp ├── Stable_assignment.cpp ├── StackSort.java ├── Stack_queue_using_heap.cpp ├── Stack_sorting.cpp ├── Stack_with_max.h ├── Stack_with_max_improved.cpp ├── Stack_with_max_template.cpp ├── StringInMatrix.java ├── String_in_matrix.cpp ├── String_matching_wildcard.cpp ├── SubseqCover.java ├── Subseq_cover.cpp ├── Successor.cpp ├── Successor_BST.cpp ├── SudokuChecker.java ├── SudokuSolver.java ├── Sudoku_check.h ├── Sudoku_solve.cpp ├── Symmetric_binary_tree.cpp ├── Tail.cpp ├── Tail_coin.cpp ├── TaskExecutionWebServer.java ├── Task_assignment.cpp ├── Team_photo_1.cpp ├── Team_photo_2.cpp ├── Theory_of_equality.cpp ├── ThreadPerTaskWebserver.java ├── Three_jugs.cpp ├── Ties_election.cpp ├── Tournament_tree.cpp ├── Transform_string_to_other.cpp ├── Transitive_closure.cpp ├── Tree_diameter.cpp ├── Uniform_random_number_generation.cpp ├── Union_intervals.cpp ├── Update_BST.cpp ├── View_from_above.cpp ├── View_sunset.cpp ├── Wiring_circuit_board.cpp ├── Word_breaking.cpp ├── Zipping_list.cpp ├── add-binary.cc ├── add-two-number-list.cc ├── array-reference-copy.cc ├── average-top-3-scores.cc ├── binary-tree-level-order-bottom-up.cc ├── binary-tree-postorder-traversal-iterative-alternative.cc ├── binary-tree-postorder-traversal-iterative.cc ├── binary-tree-preorder-traversal-iterative.cc ├── binary-tree-zigzag-level-order-traversal.cc ├── bonus-improved.cc ├── bonus.cc ├── climb-stairs.cc ├── clone-graph.cc ├── combinations-unique.cc ├── combinations.cc ├── container-with-most-water.cc ├── cyclic-right-shift.cc ├── distinct-sorted-list.cc ├── execute-shell.h ├── first-missing-positive.cc ├── generate-parentheses.cc ├── generating-a-b-sqrt2-improved.cc ├── gray-code.cc ├── highest-affinity-pairs.cc ├── indirect_sort.cpp ├── insert-interval.cc ├── insertion-sort-list.cc ├── integer-to-roman.cc ├── interleaving-string.cc ├── is_binary_tree_a_BST.cpp ├── is_binary_tree_a_BST_BFS.cpp ├── is_binary_tree_a_BST_const_space.cpp ├── job_assignment.cpp ├── jump-game-min-steps.cc ├── jump-game.cc ├── k-balanced_binary_tree.cpp ├── k-largest-elements-binary-heap.cc ├── k-th_element_streaming.cpp ├── k-th_largest_element.cpp ├── k-th_largest_element_large_n.cpp ├── k-th_node_binary_tree.cpp ├── largearray.c ├── lazy-init.cpp ├── left-justified-text.cc ├── length-of-last-word.cc ├── list-pivoting.cc ├── longest-contained-range.cc ├── longest-subarray-with-distinct-entries.cc ├── longest-substring-without-repeating-characters.cc ├── longest-valid-parentheses.cc ├── look-and-say.cc ├── merge-two-sorted-arrays-in-place.cc ├── n-queens-count.cc ├── n-queens.cc ├── nnChomp.pseudo ├── nonconstructible-change.cc ├── nonuniform_random_number_generation.cpp ├── normalized_pathnames.cpp ├── number-steps.cc ├── palindrome-number.cc ├── palindrome-partitioning-min-cuts.cc ├── palindrome-partitioning.cc ├── pascal-triangle-1.cc ├── pascal-triangle-2.cc ├── path-sum-binary-tree-all.cc ├── path-sum-binary-tree.cc ├── permutations-alternative.cc ├── permutations-unique.cc ├── permutations.cc ├── plus-one.cc ├── populating-next-right-pointers-any-binary-tree.cc ├── populating-next-right-pointers.cc ├── power-x-y.cc ├── prefix-search.cc ├── rabin-karp.cpp ├── reconstruct-almost-bst.cc ├── recover-binary-search-tree-constant-space.cc ├── remove-duplicates-from-sorted-array.cc ├── remove-duplicates-sorted-list.cc ├── remove-element.cc ├── remove-twice-duplicates-from-sorted-array.cc ├── reverse-integer.cc ├── reverse-link-list-from-s-to-f.cc ├── reverse-list-in-k-group.cc ├── roman-to-integer.cc ├── rook-attack.cc ├── scramble-string.cc ├── search-a-range-sorted-array.cc ├── search-insert-position-sorted-array.cc ├── search-rotated-sorted-array-with-duplicates.cc ├── search-rotated-sorted-array.cc ├── snake-string.cc ├── sort-list.cc ├── sort_k-increasing-decreasing_array.cpp ├── square-root-int.cc ├── substring-with-concatenation-of-all-words.cc ├── sum-root-to-leaf-binary-tree.cc ├── surrounded-regions.cc ├── swap_bits.cpp ├── swap_bits.h ├── tmp.cc ├── tower_hanoi.cpp ├── trapping-rain-water.cc ├── triangle.cc ├── unique-binary-trees-all.cc ├── unique-binary-trees.cc ├── valid-IP-address.cc ├── valid-number.cc ├── valid-palindrome.cc ├── valid-parentheses.cc ├── word-breaking-2.cc └── zigzag-conversion.cc /AsyncThread.java: -------------------------------------------------------------------------------- 1 | class Requestor { 2 | public String execute(String req) { 3 | return "response:" + req; 4 | } 5 | public String error(String req) { 6 | return "response:" + req + ":" + "TIMEDOUT"; 7 | } 8 | // @include 9 | public String execute(String req, long delay) { 10 | try { 11 | // simulate the time taken to perform a computation 12 | Thread.sleep(delay); 13 | } catch (InterruptedException e) { 14 | return error(req); 15 | } 16 | return execute(req); 17 | } 18 | // @exclude 19 | public void ProcessResponse(String response) { 20 | System.out.println("ProcessResponse:" + response); 21 | return; 22 | } 23 | } 24 | 25 | public class AsyncThread { 26 | public static final long TIMEOUT = 500L; 27 | 28 | public static void main(String [] args) { 29 | Dispatch(new Requestor(), "t1", 1000L); 30 | Dispatch(new Requestor(), "t2", 100L); 31 | Dispatch(new Requestor(), "t3", 10L); 32 | Dispatch(new Requestor(), "t4", 1L); 33 | Dispatch(new Requestor(), "t5", 200L); 34 | } 35 | 36 | // @include 37 | public static void Dispatch(final Requestor r, final String request, 38 | final long delay) { 39 | Runnable task = new Runnable() { 40 | public void run() { 41 | Runnable actualTask = new Runnable() { 42 | public void run() { 43 | String response = r.execute(request, delay); 44 | r.ProcessResponse(response); 45 | } 46 | }; 47 | Thread innerThread = new Thread(actualTask); 48 | innerThread.start(); 49 | try { 50 | Thread.sleep(TIMEOUT); 51 | innerThread.interrupt(); 52 | } catch(InterruptedException e) { 53 | e.printStackTrace(); 54 | } 55 | } 56 | }; 57 | new Thread(task).start(); 58 | } 59 | // @exclude 60 | } 61 | -------------------------------------------------------------------------------- /BST_lowest_common_ancestor.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | 6 | #include "./BST_prototype.h" 7 | 8 | using std::unique_ptr; 9 | 10 | // @include 11 | BSTNode* find_LCA(const unique_ptr>& x, 12 | const unique_ptr>& s, 13 | const unique_ptr>& b) { 14 | auto* p = x.get(); 15 | while (p->data < s->data || p->data > b->data) { 16 | while (p->data < s->data) { 17 | p = p->right.get(); // LCA must be in p's right child. 18 | } 19 | while (p->data > b->data) { 20 | p = p->left.get(); // LCA must be in p's left child. 21 | } 22 | } 23 | 24 | // p->data >= s->data && p->data <= b->data. 25 | return p; 26 | } 27 | // @exclude 28 | 29 | int main(int argc, char* argv[]) { 30 | // 3 31 | // 2 5 32 | // 1 4 6 33 | unique_ptr> root = unique_ptr>(new BSTNode{3}); 34 | root->left = unique_ptr>(new BSTNode{2}); 35 | root->left->left = unique_ptr>(new BSTNode{1}); 36 | root->right = unique_ptr>(new BSTNode{5}); 37 | root->right->left = unique_ptr>(new BSTNode{4}); 38 | root->right->right = unique_ptr>(new BSTNode{6}); 39 | assert(3 == find_LCA(root, root->left->left, root->right->left)->data); 40 | assert(5 == find_LCA(root, root->right->left, root->right->right)->data); 41 | assert(2 == find_LCA(root, root->left->left, root->left)->data); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /BST_parent_prototype.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_BST_PARENT_PROTOTYPE_H_ 4 | #define SOLUTIONS_BST_PARENT_PROTOTYPE_H_ 5 | 6 | #include 7 | #include 8 | 9 | using std::unique_ptr; 10 | 11 | // @include 12 | template 13 | struct BSTNode { 14 | T data; 15 | unique_ptr> left, right; 16 | BSTNode* parent; 17 | }; 18 | // @exclude 19 | #endif // SOLUTIONS_BST_PARENT_PROTOTYPE_H_ 20 | -------------------------------------------------------------------------------- /BST_prototype.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_BST_PROTOTYPE_H_ 4 | #define SOLUTIONS_BST_PROTOTYPE_H_ 5 | 6 | #include 7 | 8 | using std::unique_ptr; 9 | 10 | // @include 11 | template 12 | struct BSTNode { 13 | T data; 14 | unique_ptr> left, right; 15 | }; 16 | // @exclude 17 | #endif // SOLUTIONS_BST_PROTOTYPE_H_ 18 | -------------------------------------------------------------------------------- /BST_prototype_shared_ptr.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_BST_PROTOTYPE_SHARED_PTR_H_ 4 | #define SOLUTIONS_BST_PROTOTYPE_SHARED_PTR_H_ 5 | 6 | #include 7 | 8 | using std::shared_ptr; 9 | 10 | // @include 11 | template 12 | struct BSTNode { 13 | T data; 14 | shared_ptr> left, right; 15 | }; 16 | // @exclude 17 | #endif // SOLUTIONS_BST_PROTOTYPE_SHARED_PTR_H_ 18 | -------------------------------------------------------------------------------- /BST_sorted_order.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "./BST_prototype.h" 10 | 11 | using std::cout; 12 | using std::endl; 13 | using std::stack; 14 | using std::unique_ptr; 15 | using std::vector; 16 | 17 | vector result; 18 | 19 | // @include 20 | void print_BST_in_sorted_order(const unique_ptr>& r) { 21 | stack*> s; 22 | const BSTNode* curr = r.get(); 23 | 24 | while (!s.empty() || curr) { 25 | if (curr) { 26 | s.push(curr); 27 | curr = curr->left.get(); 28 | } else { 29 | curr = s.top(); 30 | s.pop(); 31 | cout << curr->data << endl; 32 | // @exclude 33 | result.emplace_back(curr->data); 34 | // @include 35 | curr = curr->right.get(); 36 | } 37 | } 38 | } 39 | // @exclude 40 | 41 | int main(int argc, char* argv[]) { 42 | // 3 43 | // 2 5 44 | // 1 4 6 45 | unique_ptr> root = 46 | unique_ptr>(new BSTNode{3, nullptr}); 47 | root->left = unique_ptr>(new BSTNode{2, nullptr}); 48 | root->left->left = unique_ptr>(new BSTNode{1, nullptr}); 49 | root->right = unique_ptr>(new BSTNode{5, nullptr}); 50 | root->right->left = unique_ptr>(new BSTNode{4, nullptr}); 51 | root->right->right = unique_ptr>(new BSTNode{6, nullptr}); 52 | // should output 1 2 3 4 5 6 53 | print_BST_in_sorted_order(root); 54 | vector golden_res = {1, 2, 3, 4, 5, 6}; 55 | assert(golden_res.size() == result.size()); 56 | assert(equal(golden_res.begin(), golden_res.end(), result.begin())); 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /Ball.java: -------------------------------------------------------------------------------- 1 | public class Ball { 2 | 3 | public static final int N = 1000; 4 | public static int cache[][] = new int[N][N]; 5 | 6 | // @include 7 | public static int maxHeight(int c, int d) { 8 | if (d == 0) { 9 | return 0; 10 | } else if (c == 1) { 11 | return d; 12 | } else { 13 | if (cache[c][d] == -1) { 14 | cache[c][d] = maxHeight(c, d - 1) + maxHeight(c - 1, d - 1) + 1; 15 | } 16 | return cache[c][d]; 17 | } 18 | } 19 | // @exclude 20 | 21 | public static void clearCache() { 22 | for (int i = 0 ; i < cache.length; ++i) { 23 | for (int j = 0 ; j < cache[i].length; ++j) { 24 | cache[i][j] = -1; 25 | } 26 | } 27 | } 28 | 29 | public static int testMaxHeight( int B, int D ) { 30 | clearCache(); 31 | int result = -1; 32 | System.out.println("test: B = " + B + ", D = " + D + " max height = " + (result = maxHeight( B, D ) ) ); 33 | return result; 34 | } 35 | 36 | 37 | public static void main(String [] args) { 38 | testMaxHeight( 1, 10 ); 39 | testMaxHeight( 2, 1 ); 40 | testMaxHeight( 2, 2 ); 41 | testMaxHeight( 2, 3 ); 42 | testMaxHeight( 2, 4 ); 43 | testMaxHeight( 2, 5 ); 44 | testMaxHeight( 3, 2 ); 45 | testMaxHeight( 100, 2 ); 46 | testMaxHeight( 3, 5 ); 47 | testMaxHeight( 8, 11 ); 48 | for ( int i = 0 ; i < 100; i++ ) { 49 | if ( testMaxHeight( 3, i ) >= 100 ) { 50 | System.out.println("Success with " + i + " drops"); 51 | break; 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Bentleybsearch.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | 6 | using std::vector; 7 | 8 | // @include 9 | int bsearch(int t, const vector& A) { 10 | int L = 0, U = A.size() - 1; 11 | while (L <= U) { 12 | int M = (L + U) / 2; 13 | if (A[M] < t) { 14 | L = M + 1; 15 | } else if (A[M] == t) { 16 | return M; 17 | } else { 18 | U = M - 1; 19 | } 20 | } 21 | return -1; 22 | } 23 | // @exclude 24 | 25 | int main(int argc, char* argv[]) { 26 | vector A; 27 | A.emplace_back(1); 28 | A.emplace_back(2); 29 | A.emplace_back(2); 30 | A.emplace_back(2); 31 | A.emplace_back(2); 32 | A.emplace_back(3); 33 | A.emplace_back(3); 34 | A.emplace_back(3); 35 | A.emplace_back(5); 36 | A.emplace_back(6); 37 | A.emplace_back(10); 38 | A.emplace_back(100); 39 | assert(0 == bsearch(1, A)); 40 | assert(1 <= bsearch(2, A) && bsearch(2, A) <= 4); 41 | assert(5 <= bsearch(3, A)); 42 | assert(-1 == bsearch(4, A)); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /Binary_search_first_k.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::random_device; 14 | using std::uniform_int_distribution; 15 | using std::vector; 16 | 17 | // @include 18 | int search_first(const vector& A, int k) { 19 | int l = 0, r = A.size() - 1, res = -1; 20 | while (l <= r) { 21 | int m = l + ((r - l) >> 1); 22 | if (A[m] > k) { 23 | r = m - 1; 24 | } else if (A[m] == k) { 25 | // Record the solution and keep searching the left part. 26 | res = m, r = m - 1; 27 | } else { // A[m] < k 28 | l = m + 1; 29 | } 30 | } 31 | return res; 32 | } 33 | // @exclude 34 | 35 | int main(int argc, char* argv[]) { 36 | default_random_engine gen((random_device())()); 37 | for (int times = 0; times < 1000; ++times) { 38 | int n; 39 | if (argc == 2) { 40 | n = atoi(argv[1]); 41 | } else { 42 | uniform_int_distribution dis(1, 100000); 43 | n = dis(gen); 44 | } 45 | vector A; 46 | uniform_int_distribution k_dis(0, n - 1); 47 | int k = k_dis(gen); 48 | for (int i = 0; i < n; ++i) { 49 | uniform_int_distribution dis(0, n - 1); 50 | A.emplace_back(dis(gen)); 51 | } 52 | sort(A.begin(), A.end()); 53 | int ans = search_first(A, k); 54 | cout << "k = " << k << " locates at " << ans << endl; 55 | if (ans != -1) { 56 | cout << "A[k] = " << A[ans] << endl; 57 | } 58 | auto it = find(A.cbegin(), A.cend(), k); 59 | assert((it == A.cend() && ans == -1) || (distance(A.cbegin(), it) == ans)); 60 | } 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /Binary_search_larger_k.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::default_random_engine; 11 | using std::endl; 12 | using std::random_device; 13 | using std::uniform_int_distribution; 14 | using std::vector; 15 | 16 | // @include 17 | int search_first_larger_k(const vector& A, int k) { 18 | int l = 0, r = A.size() - 1, res = -1; 19 | while (l <= r) { 20 | int m = l + ((r - l) >> 1); 21 | if (A[m] > k) { 22 | // Records the solution and keeps searching the left part. 23 | res = m, r = m - 1; 24 | } else { // A[m] <= k. 25 | l = m + 1; 26 | } 27 | } 28 | return res; 29 | } 30 | // @exclude 31 | 32 | int check_ans(const vector& A, int k) { 33 | for (int i = 0; i < A.size(); ++i) { 34 | if (A[i] > k) { 35 | return i; 36 | } 37 | } 38 | return -1; 39 | } 40 | 41 | int main(int argc, char* argv[]) { 42 | default_random_engine gen((random_device())()); 43 | for (int times = 0; times < 1000; ++times) { 44 | int n; 45 | if (argc == 2) { 46 | n = atoi(argv[1]); 47 | } else { 48 | uniform_int_distribution n_dis(1, 10000); 49 | n = n_dis(gen); 50 | } 51 | vector A; 52 | for (int i = 0; i < n; ++i) { 53 | uniform_int_distribution dis(0, n - 1); 54 | A.emplace_back(dis(gen)); 55 | } 56 | sort(A.begin(), A.end()); 57 | uniform_int_distribution k_dis(0, n - 1); 58 | int k = k_dis(gen); 59 | int ans = search_first_larger_k(A, k); 60 | cout << "k = " << k << " locates at " << ans << endl; 61 | if (ans != -1) { 62 | cout << "A[k] = " << A[ans] << endl; 63 | } 64 | assert(ans == check_ans(A, k)); 65 | } 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /Binary_tree_prototype_template.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_BINARY_TREE_PROTOTYPE_TEMPLATE_H_ 4 | #define SOLUTIONS_BINARY_TREE_PROTOTYPE_TEMPLATE_H_ 5 | 6 | #include 7 | 8 | using std::unique_ptr; 9 | 10 | // @include 11 | template 12 | struct BinaryTree { 13 | T data; 14 | unique_ptr> left, right; 15 | }; 16 | // @exclude 17 | #endif // SOLUTIONS_BINARY_TREE_PROTOTYPE_TEMPLATE_H_ 18 | -------------------------------------------------------------------------------- /Binary_tree_to_doubly_linked_list.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | struct BinaryTree { 6 | int data; 7 | BinaryTree* left, *right; 8 | BinaryTree(int val = 0, BinaryTree* l = nullptr, BinaryTree* r = nullptr) 9 | : data(val), left(l), right(r) {} 10 | }; 11 | 12 | // @include 13 | BinaryTree* convert_tree_to_doubly_list(BinaryTree* n) { 14 | if (n == nullptr) { 15 | return nullptr; 16 | } 17 | 18 | BinaryTree* L = convert_tree_to_doubly_list(n->left); 19 | BinaryTree* R = convert_tree_to_doubly_list(n->right); 20 | // Join L and n as a doubly linked list 21 | BinaryTree* L_tail = nullptr; 22 | if (L) { 23 | L_tail = L->left; 24 | L_tail->right = n, n->left = L_tail; 25 | L_tail = n; 26 | } else { 27 | L = L_tail = n; 28 | } 29 | 30 | // Join L and R as a doubly linked list 31 | BinaryTree* R_tail = nullptr; 32 | if (R) { 33 | R_tail = R->left; 34 | L_tail->right = R, R->left = L_tail; 35 | } else { 36 | R_tail = L_tail; 37 | } 38 | R_tail->right = L, L->left = R_tail; 39 | return L; 40 | } 41 | // @exclude 42 | 43 | int main(int argc, char* argv[]) { 44 | // 3 45 | // 2 5 46 | // 1 4 6 47 | BinaryTree* root = new BinaryTree(3); 48 | root->left = new BinaryTree(2); 49 | root->left->left = new BinaryTree(1); 50 | root->right = new BinaryTree(5); 51 | root->right->left = new BinaryTree(4); 52 | root->right->right = new BinaryTree(6); 53 | // should output 1, 2, 3, 4, 5, 6 54 | BinaryTree* head = convert_tree_to_doubly_list(root); 55 | BinaryTree* temp = head; 56 | do { 57 | cout << temp->data << endl; 58 | temp = temp->right; 59 | } while (temp != head); 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /Binary_tree_with_parent_prototype.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_BINARY_TREE_WITH_PARENT_PROTOTYPE_H_ 4 | #define SOLUTIONS_BINARY_TREE_WITH_PARENT_PROTOTYPE_H_ 5 | 6 | #include 7 | 8 | using std::unique_ptr; 9 | 10 | // @include 11 | template 12 | struct BinaryTreeNode { 13 | T data; 14 | unique_ptr> left, right; 15 | BinaryTreeNode* parent; 16 | }; 17 | // @exclude 18 | #endif // SOLUTIONS_BINARY_TREE_WITH_PARENT_PROTOTYPE_H_ 19 | -------------------------------------------------------------------------------- /Can_string_be_palindrome.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "./Can_string_be_palindrome_hash.h" 9 | #include "./Can_string_be_palindrome_sorting.h" 10 | 11 | using std::boolalpha; 12 | using std::cout; 13 | using std::default_random_engine; 14 | using std::endl; 15 | using std::random_device; 16 | using std::string; 17 | using std::uniform_int_distribution; 18 | 19 | string rand_string(int len) { 20 | string ret; 21 | default_random_engine gen((random_device())()); 22 | while (len--) { 23 | uniform_int_distribution dis('a', 'z'); 24 | ret += dis(gen); 25 | } 26 | return ret; 27 | } 28 | 29 | int main(int argc, char *argv[]) { 30 | default_random_engine gen((random_device())()); 31 | for (int times = 0; times < 1000; ++times) { 32 | string s; 33 | if (argc == 2) { 34 | s = argv[1]; 35 | } else { 36 | uniform_int_distribution dis(1, 10); 37 | s = rand_string(dis(gen)); 38 | } 39 | cout << s << endl; 40 | assert(can_string_be_a_palindrome_hash(s) == 41 | can_string_be_a_palindrome_sorting(&s)); 42 | } 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /Can_string_be_palindrome_hash.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_CAN_STRING_BE_PALINDROME_HASH_H_ 4 | #define SOLUTIONS_CAN_STRING_BE_PALINDROME_HASH_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | using std::pair; 11 | using std::string; 12 | using std::unordered_map; 13 | 14 | // @include 15 | bool can_string_be_a_palindrome_hash(const string& s) { 16 | unordered_map hash; 17 | // Insert each char into hash. 18 | for_each(s.begin(), s.end(), [&hash](const char & c) { ++hash[c]; }); 19 | 20 | // A string can be permuted as a palindrome if the number of odd time 21 | // chars <= 1. 22 | int odd_count = 0; 23 | for (const pair& p : hash) { 24 | if (p.second & 1 && ++odd_count > 1) { 25 | break; 26 | } 27 | } 28 | return odd_count <= 1; 29 | } 30 | // @exclude 31 | #endif // SOLUTIONS_CAN_STRING_BE_PALINDROME_HASH_H_ 32 | -------------------------------------------------------------------------------- /Can_string_be_palindrome_sorting.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_CAN_STRING_BE_PALINDROME_SORTING_H_ 4 | #define SOLUTIONS_CAN_STRING_BE_PALINDROME_SORTING_H_ 5 | 6 | #include 7 | #include 8 | 9 | using std::string; 10 | 11 | // @include 12 | bool can_string_be_a_palindrome_sorting(string* s) { 13 | sort(s->begin(), s->end()); 14 | int odd_count = 0, num_curr_char = 1; 15 | 16 | for (int i = 1; i < s->size() && odd_count <= 1; ++i) { 17 | if ((*s)[i] != (*s)[i - 1]) { 18 | if (num_curr_char & 1) { 19 | ++odd_count; 20 | } 21 | num_curr_char = 1; 22 | } else { 23 | ++num_curr_char; 24 | } 25 | } 26 | if (num_curr_char & 1) { 27 | ++odd_count; 28 | } 29 | 30 | // A string can be permuted as a palindrome if the number of odd time 31 | // chars <= 1. 32 | return odd_count <= 1; 33 | } 34 | // @exclude 35 | #endif // SOLUTIONS_CAN_STRING_BE_PALINDROME_SORTING_H_ 36 | -------------------------------------------------------------------------------- /Celebrity_finding.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::default_random_engine; 11 | using std::deque; 12 | using std::endl; 13 | using std::max; 14 | using std::random_device; 15 | using std::uniform_int_distribution; 16 | using std::vector; 17 | 18 | // @include 19 | int celebrity_finding(const vector>& F) { 20 | // Start checking the relation from F[0][1]. 21 | int i = 0, j = 1; 22 | while (j < F.size()) { 23 | if (F[i][j]) { 24 | i = j++; // all candidates j' < j are not celebrity candidates. 25 | } else { // F[i][j] == false. 26 | ++j; // i is still a celebrity candidate but j is not. 27 | } 28 | } 29 | return i; 30 | } 31 | // @exclude 32 | 33 | int main(int argc, char* argv[]) { 34 | default_random_engine gen((random_device())()); 35 | for (int times = 0; times < 1000; ++times) { 36 | int n; 37 | if (argc > 1) { 38 | n = atoi(argv[1]); 39 | } else { 40 | uniform_int_distribution dis(1, 1000); 41 | n = dis(gen); 42 | } 43 | vector> graph(n, deque(n)); 44 | for (size_t i = 0; i < n; ++i) { 45 | for (size_t j = 0; j < n; ++j) { 46 | uniform_int_distribution zero_or_false(0, 1); 47 | graph[i][j] = zero_or_false(gen); 48 | } 49 | graph[i][i] = false; 50 | } 51 | uniform_int_distribution dis(0, n - 1); 52 | int celebrity = dis(gen); 53 | for (size_t i = 0; i < n; ++i) { 54 | graph[i][celebrity] = true; 55 | } 56 | for (size_t j = 0; j < n; ++j) { 57 | graph[celebrity][j] = false; 58 | } 59 | cout << celebrity_finding(graph) << endl; 60 | assert(celebrity == celebrity_finding(graph)); 61 | } 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /Checking_cycle.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "./Checking_cycle.h" 8 | #include "./Linked_list_prototype.h" 9 | 10 | using std::cout; 11 | using std::endl; 12 | using std::make_shared; 13 | 14 | int main(int argc, char* argv[]) { 15 | shared_ptr> L3 = 16 | make_shared>(ListNode{3, nullptr}); 17 | shared_ptr> L2 = 18 | make_shared>(ListNode{2, L3}); 19 | shared_ptr> L1 = 20 | make_shared>(ListNode{1, L2}); 21 | 22 | // should output "L1 does not have cycle." 23 | assert(has_cycle(L1) == nullptr); 24 | cout << "L1 " << (has_cycle(L1) ? "has" : "does not have") << " cycle." 25 | << endl; 26 | 27 | // make it a cycle 28 | L3->next = L2; 29 | // should output "L1 has cycle, located at node has value 2" 30 | assert(has_cycle(L1) != nullptr); 31 | assert(has_cycle(L1)->data == 2); 32 | auto temp = has_cycle(L1); 33 | if (temp) { 34 | cout << "L1 has cycle, located at node has value " << temp->data << endl; 35 | } else { 36 | cout << "L1 does not have cycle" << endl; 37 | } 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /Checking_cycle.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_CHECKING_CYCLE_H_ 4 | #define SOLUTIONS_CHECKING_CYCLE_H_ 5 | 6 | #include 7 | 8 | #include "./Linked_list_prototype.h" 9 | 10 | // @include 11 | shared_ptr> has_cycle(const shared_ptr>& head) { 12 | shared_ptr> fast = head, slow = head; 13 | 14 | while (slow && slow->next && fast && fast->next && fast->next->next) { 15 | slow = slow->next, fast = fast->next->next; 16 | if (slow == fast) { // there is a cycle. 17 | // Calculates the cycle length. 18 | int cycle_len = 0; 19 | do { 20 | ++cycle_len; 21 | fast = fast->next; 22 | } while (slow != fast); 23 | 24 | // Tries to find the start of the cycle. 25 | slow = head, fast = head; 26 | // Fast pointer advances cycle_len first. 27 | while (cycle_len--) { 28 | fast = fast->next; 29 | } 30 | // Both pointers advance at the same time. 31 | while (slow != fast) { 32 | slow = slow->next, fast = fast->next; 33 | } 34 | return slow; // the start of cycle. 35 | } 36 | } 37 | return nullptr; // no cycle. 38 | } 39 | // @exclude 40 | #endif // SOLUTIONS_SWAP_BITS_H_ 41 | -------------------------------------------------------------------------------- /Checking_cycle_template.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "./Checking_cycle.h" 8 | #include "./Linked_list_prototype_template.h" 9 | 10 | using std::cout; 11 | using std::endl; 12 | using std::make_shared; 13 | 14 | int main(int argc, char* argv[]) { 15 | shared_ptr> L3 = 16 | make_shared>(node_t{3, nullptr}); 17 | shared_ptr> L2 = make_shared>(node_t{2, L3}); 18 | shared_ptr> L1 = make_shared>(node_t{1, L2}); 19 | 20 | // should output "L1 does not have cycle." 21 | assert(has_cycle(L1) == nullptr); 22 | cout << "L1 " << (has_cycle(L1) ? "has" : "does not have") << " cycle." 23 | << endl; 24 | 25 | // make it a cycle 26 | L3->next = L2; 27 | // should output "L1 has cycle, located at node has value 2" 28 | assert(has_cycle(L1) != nullptr); 29 | assert(has_cycle(L1)->data == 2); 30 | auto temp = has_cycle(L1); 31 | if (temp) { 32 | cout << "L1 has cycle, located at node has value " << temp->data << endl; 33 | } else { 34 | cout << "L1 does not have cycle" << endl; 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /Close_search.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::default_random_engine; 10 | using std::endl; 11 | using std::random_device; 12 | using std::uniform_int_distribution; 13 | using std::vector; 14 | 15 | // @include 16 | int close_search(const vector& A, int k) { 17 | int idx = 0; 18 | while (idx < A.size() && A[idx] != k) { 19 | idx += abs(A[idx] - k); 20 | } 21 | return idx < A.size() ? idx : -1; // -1 means no result. 22 | } 23 | // @exclude 24 | 25 | int main(int argc, char* argv[]) { 26 | default_random_engine gen((random_device())()); 27 | for (int times = 0; times < 10000; ++times) { 28 | int n; 29 | if (argc == 2) { 30 | n = atoi(argv[1]); 31 | } else { 32 | uniform_int_distribution dis(1, 10000); 33 | n = dis(gen); 34 | } 35 | vector A; 36 | uniform_int_distribution dis(0, 9); 37 | A.emplace_back(dis(gen)); 38 | for (size_t i = 1; i < n; ++i) { 39 | uniform_int_distribution shift_dis(-1, 1); 40 | int shift = shift_dis(gen); 41 | A.emplace_back(A[i - 1] + shift); 42 | } 43 | uniform_int_distribution k_dis(0, 99); 44 | int k = k_dis(gen); 45 | int ans = close_search(A, k); 46 | cout << ans << endl; 47 | if (ans != -1) { 48 | assert(A[ans] == k); 49 | } else { 50 | bool found = false; 51 | for (size_t i = 0; i < A.size(); ++i) { 52 | if (A[i] == k) { 53 | found = true; 54 | break; 55 | } 56 | } 57 | assert(found == false); 58 | } 59 | } 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /Count_occurrences_in_sentence.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::default_random_engine; 10 | using std::endl; 11 | using std::random_device; 12 | using std::string; 13 | using std::uniform_int_distribution; 14 | 15 | // @include 16 | void count_occurrences(string S) { 17 | sort(S.begin(), S.end()); 18 | 19 | int count = 1; 20 | for (int i = 1; i < S.size(); ++i) { 21 | if (S[i] == S[i - 1]) { 22 | ++count; 23 | } else { 24 | cout << '(' << S[i - 1] << ',' << count << "),"; 25 | count = 1; 26 | } 27 | } 28 | cout << '(' << S.back() << ',' << count << ')' << endl; 29 | } 30 | // @exclude 31 | 32 | string rand_string(int len) { 33 | default_random_engine gen((random_device())()); 34 | string ret; 35 | while (len--) { 36 | uniform_int_distribution dis('a', 'z'); 37 | ret += dis(gen); 38 | } 39 | return ret; 40 | } 41 | 42 | int main(int argc, char* argv[]) { 43 | default_random_engine gen((random_device())()); 44 | string S; 45 | if (argc == 2) { 46 | S = argv[1]; 47 | } else { 48 | uniform_int_distribution dis(1, 1000); 49 | S = rand_string(dis(gen)); 50 | } 51 | cout << S << endl; 52 | count_occurrences(S); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /Deletion_list.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "./Linked_list_prototype.h" 8 | 9 | using std::cout; 10 | using std::endl; 11 | using std::make_shared; 12 | using std::shared_ptr; 13 | 14 | // @include 15 | void deletion_from_list(const shared_ptr>& v) { 16 | v->data = v->next->data; 17 | v->next = v->next->next; 18 | } 19 | // @exclude 20 | 21 | int main(int argc, char* argv[]) { 22 | shared_ptr> L; 23 | L = make_shared>(ListNode{ 24 | 1, make_shared>(ListNode{ 25 | 2, make_shared>(ListNode{3, nullptr})})}); 26 | deletion_from_list(L); 27 | assert(L->data == 2 && L->next->data == 3); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /Doors.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::default_random_engine; 9 | using std::deque; 10 | using std::random_device; 11 | using std::uniform_int_distribution; 12 | 13 | // @include 14 | bool is_door_open(int i) { 15 | double sqrt_i = sqrt(i); 16 | int floor_sqrt_i = floor(sqrt_i); 17 | return floor_sqrt_i * floor_sqrt_i == i; 18 | } 19 | // @exclude 20 | 21 | void check_answer(int n) { 22 | deque doors(n + 1, false); // false means closed door. 23 | for (int i = 1; i <= n; ++i) { 24 | int start = 0; 25 | while (start + i <= n) { 26 | start += i; 27 | doors[start] = doors[start] ? false : true; 28 | } 29 | } 30 | 31 | for (int i = 1; i <= n; ++i) { 32 | assert(is_door_open(i) == doors[i]); 33 | } 34 | } 35 | 36 | int main(int argc, char* argv[]) { 37 | default_random_engine gen((random_device())()); 38 | int n; 39 | if (argc == 2) { 40 | n = atoi(argv[1]); 41 | } else { 42 | uniform_int_distribution dis(1, 1000); 43 | n = dis(gen); 44 | } 45 | check_answer(n); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /Doors.java: -------------------------------------------------------------------------------- 1 | public class Doors { 2 | // @include 3 | static boolean isOpen(int i) { 4 | double di = (double)i; 5 | double sqrtdi = Math.sqrt(di); 6 | int sqrti = (int)sqrtdi; 7 | return (sqrti * sqrti == i); 8 | } 9 | // @exclude 10 | 11 | public static void test(int i) { 12 | System.out.println("Door " + i + " is " + ( isOpen( i ) ? "" : "not " ) + "open" ); 13 | } 14 | 15 | public static void main(String args[]) { 16 | for ( int i = 0 ; i < 100; i++ ) { 17 | test(i); 18 | } 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /Elias.java: -------------------------------------------------------------------------------- 1 | import java.util.List; 2 | import java.util.ArrayList; 3 | import java.lang.StringBuffer; 4 | 5 | public class Elias { 6 | 7 | // @include 8 | public static String encode(int [] A) { 9 | List terms = new ArrayList(); 10 | for (int i : A) { 11 | String s = Integer.toString(i); 12 | StringBuffer sb = new StringBuffer(); 13 | for (int j = 0 ; j < s.length() - 1 ;++j) { 14 | sb.append("0"); 15 | } 16 | sb.append(s); 17 | terms.add(sb.toString()); 18 | } 19 | 20 | StringBuffer resultSb = new StringBuffer(); 21 | for (String s : terms) { 22 | resultSb.append(s); 23 | } 24 | return resultSb.toString(); 25 | } 26 | 27 | public static String [] decode(String s) { 28 | List numbers = new ArrayList(); 29 | int offset = 0; 30 | while (offset < s.length()) { 31 | int thisLength = 0; 32 | while (s.charAt(offset) == '0') { 33 | ++offset; 34 | ++thisLength; 35 | } 36 | String thisString = s.substring(offset, offset + thisLength + 1); 37 | offset = offset + thisLength + 1; 38 | numbers.add(thisString); 39 | } 40 | 41 | String [] result = new String[numbers.size()]; 42 | numbers.toArray(result); 43 | return result; 44 | } 45 | // @exclude 46 | 47 | static void printStringArray( String [] sa ) { 48 | for( String s : sa ) { 49 | System.out.println(s); 50 | } 51 | } 52 | 53 | public static void main( String [] args ) { 54 | String s1 = "0110100011100100"; 55 | String [] d1 = decode(s1); 56 | System.out.println("Result of decoding " + s1 ); 57 | printStringArray( d1 ); 58 | int [] i1 = new int[d1.length]; 59 | int index = 0; 60 | for ( String s : d1 ) 61 | i1[index++] = new Integer( s ); 62 | System.out.println("Encoding: " + encode( i1 ) ); 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /Eliminate_duplicate.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::default_random_engine; 11 | using std::endl; 12 | using std::random_device; 13 | using std::uniform_int_distribution; 14 | using std::vector; 15 | 16 | // @include 17 | void eliminate_duplicate(vector* A) { 18 | sort(A->begin(), A->end()); // makes identical elements become neighbors. 19 | // unique() removes adjacent duplicates and returns an iterator to the 20 | // element the follows the last element not removed. The effect of erase() 21 | // is to restrict A to the distinct element. 22 | A->erase(unique(A->begin(), A->end()), A->end()); 23 | } 24 | // @exclude 25 | 26 | void check_ans(const vector& A) { 27 | for (size_t i = 1; i < A.size(); ++i) { 28 | assert(A[i] != A[i - 1]); 29 | } 30 | } 31 | 32 | int main(int argc, char* argv[]) { 33 | default_random_engine gen((random_device())()); 34 | for (int times = 0; times < 1000; ++times) { 35 | int n; 36 | vector A; 37 | if (argc == 2) { 38 | n = atoi(argv[1]); 39 | } else { 40 | uniform_int_distribution dis(0, 100000); 41 | n = dis(gen); 42 | } 43 | for (int i = 0; i < n; ++i) { 44 | uniform_int_distribution dis(0, n - 1); 45 | A.emplace_back(dis(gen)); 46 | } 47 | eliminate_duplicate(&A); 48 | check_ans(A); 49 | } 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /EquivClasses.java: -------------------------------------------------------------------------------- 1 | public class EquivClasses { 2 | 3 | static int N = 7; 4 | static int A[] = {1,2,2,3,5,6}; 5 | static int B[] = {2,4,1,0,2,0}; 6 | 7 | // @include 8 | /* 9 | * A and B encode pairwise equivalences on a cardinality N set whose elements 10 | * are indexed by 0,1,2,...,N-1 11 | * 12 | * For example A[5] = 6 and B[5] = 0 indicates that the sixth and 13 | * zeroth elements are to be grouped into the same equivalence class 14 | * 15 | * We return the weakest equivalence relation implied by A and B in an array 16 | * F of length N; F[i] holds the smallest index of all the elements that 17 | * i is equivalent to. 18 | */ 19 | 20 | public static int [] ComputeEquivalenceClasses(int N, int A[], int B[]) { 21 | int[] F = new int[N]; 22 | int numEquivalentPairs = A.length; 23 | for (int i = 0 ; i < F.length; ++i) { 24 | F[i] = i; 25 | } 26 | 27 | for (int k = 0 ; k < numEquivalentPairs; ++k) { 28 | int i = A[k]; 29 | while (F[i] != i) { 30 | i = F[i]; 31 | } 32 | int j = B[k]; 33 | while (F[j] != j) { 34 | j = F[j]; 35 | } 36 | 37 | if (i != j) { 38 | if (i < j) { 39 | F[j] = i; 40 | } else { 41 | F[i] = j; 42 | } 43 | } 44 | } 45 | 46 | for (int i = 0 ; i < N; ++i) { 47 | while (F[i] != F[F[i]]) { 48 | F[i] = F[F[i]]; 49 | } 50 | } 51 | return F; 52 | } 53 | // @exclude 54 | 55 | public static void main(String[] args) { 56 | int F[] = ComputeEquivalenceClasses(N, A, B); 57 | 58 | for (int i = 0 ; i < N; i++) 59 | System.out.println("F[" + i + "] = " + F[i] ); 60 | } 61 | 62 | static void print(String s, int [] F) { 63 | System.out.println(s); 64 | for (int i = 0 ; i < N; i++) { 65 | System.out.println("F[" + i + "] = " + F[i] ); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Find_element_appears_once.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::default_random_engine; 10 | using std::endl; 11 | using std::random_device; 12 | using std::uniform_int_distribution; 13 | using std::vector; 14 | 15 | // @include 16 | int find_element_appears_once(const vector &A) { 17 | int ones = 0, twos = 0; 18 | int next_ones, next_twos; 19 | for (const int &i : A) { 20 | next_ones = (~i & ones) | (i & ~ones & ~twos); 21 | next_twos = (~i & twos) | (i & ones); 22 | ones = next_ones, twos = next_twos; 23 | } 24 | return ones; 25 | } 26 | // @exclude 27 | 28 | int main(int argc, char *argv[]) { 29 | default_random_engine gen((random_device())()); 30 | for (int times = 0; times < 10000; ++times) { 31 | vector A; 32 | int n; 33 | if (argc == 2) { 34 | n = atoi(argv[1]); 35 | } else { 36 | uniform_int_distribution n_dis(1, 10000); 37 | n = n_dis(gen); 38 | } 39 | uniform_int_distribution dis(0, n - 1); 40 | int single = dis(gen); 41 | for (int i = 0; i < n; ++i) { 42 | A.emplace_back(i); 43 | if (i != single) { 44 | A.emplace_back(i); 45 | A.emplace_back(i); 46 | } 47 | } 48 | cout << "Singleton element: " << find_element_appears_once(A) << endl; 49 | assert(find_element_appears_once(A) == single); 50 | } 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /Find_missing_and_duplicate.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::default_random_engine; 11 | using std::endl; 12 | using std::pair; 13 | using std::random_device; 14 | using std::uniform_int_distribution; 15 | using std::vector; 16 | 17 | // @include 18 | // Return a pair(duplicate, missing). 19 | pair find_duplicate_missing(const vector& A) { 20 | int sum = 0, square_sum = 0; 21 | for (int i = 0; i < A.size(); ++i) { 22 | sum += i - A[i], square_sum += i * i - A[i] * A[i]; 23 | } 24 | return {(square_sum / sum - sum) >> 1, (square_sum / sum + sum) >> 1}; 25 | } 26 | // @exclude 27 | 28 | int main(int argc, char* argv[]) { 29 | default_random_engine gen((random_device())()); 30 | for (int times = 0; times < 1000; ++times) { 31 | int n; 32 | if (argc == 2) { 33 | n = atoi(argv[1]); 34 | } else { 35 | uniform_int_distribution dis(2, 10000); 36 | n = dis(gen); 37 | } 38 | vector A; 39 | for (int i = 0; i < n; ++i) { 40 | A.emplace_back(i); 41 | } 42 | uniform_int_distribution n_dis(0, n - 1); 43 | int missing_idx = n_dis(gen); 44 | int missing = A[missing_idx]; 45 | int dup_idx = n_dis(gen); 46 | while (dup_idx == missing_idx) { 47 | dup_idx = n_dis(gen); 48 | } 49 | int dup = A[dup_idx]; 50 | A[missing_idx] = dup; 51 | pair ans = find_duplicate_missing(A); 52 | cout << "times = " << times << endl; 53 | cout << dup << ' ' << missing << endl; 54 | cout << ans.first << ' ' << ans.second << endl; 55 | assert(ans.first == dup && ans.second == missing); 56 | } 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /GCD.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "./GCD.h" 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::numeric_limits; 14 | using std::random_device; 15 | using std::uniform_int_distribution; 16 | 17 | int main(int argc, char *argv[]) { 18 | long long x = 18, y = 12; 19 | assert(GCD(x, y) == 6); 20 | if (argc == 3) { 21 | x = atoll(argv[1]), y = atoll(argv[2]); 22 | cout << GCD(x, y) << endl; 23 | assert(GCD(x, y) == another_GCD(x, y)); 24 | } else { 25 | default_random_engine gen((random_device())()); 26 | for (int times = 0; times < 1000; ++times) { 27 | uniform_int_distribution 28 | dis(1, numeric_limits::max()); 29 | x = dis(gen), y = dis(gen); 30 | assert(GCD(x, y) == another_GCD(x, y)); 31 | } 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /GCD.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_GCD_H_ 4 | #define SOLUTIONS_GCD_H_ 5 | 6 | // @include 7 | long long GCD(long long x, long long y) { 8 | if (x == 0) { 9 | return y; 10 | } else if (y == 0) { 11 | return x; 12 | } else if (!(x & 1) && !(y & 1)) { // x and y are even. 13 | return GCD(x >> 1, y >> 1) << 1; 14 | } else if (!(x & 1) && y & 1) { // x is even, and y is odd. 15 | return GCD(x >> 1, y); 16 | } else if (x & 1 && !(y & 1)) { // x is odd, and y is even. 17 | return GCD(x, y >> 1); 18 | } else if (x > y) { // both x and y are odd, and x > y. 19 | return GCD(x - y, y); 20 | } 21 | return GCD(x, y - x); // both x and y are odd, and x <= y. 22 | } 23 | // @exclude 24 | 25 | long long another_GCD(long long a, long long b) { 26 | if (b) { 27 | while ((a %= b) && (b %= a)); 28 | } 29 | return a + b; 30 | } 31 | #endif // SOLUTIONS_GCD_H_ 32 | -------------------------------------------------------------------------------- /GreatestCommonDivisor.java: -------------------------------------------------------------------------------- 1 | import java.math.BigInteger; 2 | 3 | public class GreatestCommonDivisor { 4 | 5 | // @include 6 | private static boolean isOdd(BigInteger x) { 7 | return x.testBit(0); 8 | } 9 | 10 | private static boolean isEven(BigInteger x) { 11 | return !isOdd(x); 12 | } 13 | 14 | public static BigInteger GCD(BigInteger x, BigInteger y) { 15 | if (x.equals(BigInteger.ZERO)) { 16 | return y; 17 | } else if (y.equals(BigInteger.ZERO)) { 18 | return x; 19 | } else if (isEven(x) && isEven(y)) { 20 | x = x.shiftRight(1); 21 | y = y.shiftRight(1); 22 | return GCD(x, y).shiftLeft(1); 23 | } else if (isOdd(x) && isEven(y)) { 24 | return GCD(x, y.shiftRight(1)); 25 | } else if (isOdd(y) && isEven(x)) { 26 | return GCD(y, x.shiftRight(1)); 27 | } else if (x.compareTo(y) <= 0) { 28 | return GCD(x, y.subtract(x)); 29 | } else { 30 | return GCD(y, x.subtract(y)); 31 | } 32 | } 33 | // @exclude 34 | 35 | public static void main( String [] args ) { 36 | BigInteger r1 = GCD( new BigInteger("12"), new BigInteger("18") ); 37 | System.out.println("GCD of 12 and 18 is " + r1 ); 38 | BigInteger r2 = GCD( 39 | new BigInteger("12121212121212121212121212121212121212") 40 | .multiply(new BigInteger("181818181818181818181818181818181818183") ), 41 | new BigInteger("121212121212121212121212121212121212120") ); 42 | System.out.println("GCD is " + r2 ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Hanoi.java: -------------------------------------------------------------------------------- 1 | import java.util.List; 2 | import java.util.ArrayList; 3 | 4 | public class Hanoi { 5 | 6 | static final int n = 4; 7 | static final int numPegs = 3; 8 | static int count = 0; 9 | 10 | static List> P = 11 | new ArrayList>(numPegs); 12 | 13 | static void print() { 14 | System.out.print("Stack 0:"); 15 | printStack(P.get(0)); 16 | System.out.print("Stack 1:"); 17 | printStack(P.get(1)); 18 | System.out.print("Stack 2:"); 19 | printStack(P.get(2)); 20 | } 21 | 22 | static void printStack(List p) { 23 | for (Integer i : p) { 24 | System.out.print("\t" + i); 25 | } 26 | System.out.println(); 27 | } 28 | 29 | static void push(List peg, Integer d) { 30 | peg.add(d); 31 | } 32 | 33 | static int pop(List peg) { 34 | return peg.remove(peg.size() - 1); 35 | } 36 | 37 | // @include 38 | static void move(int from, int to) { 39 | ++count; 40 | System.out.println("Move " + from + " to " + to); 41 | push(P.get(to), pop(P.get(from))); 42 | } 43 | 44 | static void transfer(int number, int from, int to, int using) { 45 | if (number > 0) { 46 | transfer(number - 1, from, using, to); 47 | move(from, to); 48 | transfer(number - 1, using, to, from); 49 | } 50 | } 51 | // @exclude 52 | 53 | 54 | public static void main (String args[]) { 55 | P.add(0, new ArrayList(n)); 56 | P.add(1, new ArrayList(n)); 57 | P.add(2, new ArrayList(n)); 58 | 59 | for (int i = 0 ; i < n; ++i) { 60 | P.get(0).add(n - 1 - i); 61 | } 62 | 63 | System.out.println("Initial configuration:"); 64 | print(); 65 | System.out.println("-----"); 66 | transfer(n, 0, 1, 2); 67 | System.out.println("Total number of moves: " + count); 68 | System.exit(0); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Hash_dictionary.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::default_random_engine; 10 | using std::endl; 11 | using std::random_device; 12 | using std::string; 13 | using std::uniform_int_distribution; 14 | 15 | string rand_string(int len) { 16 | string ret; 17 | default_random_engine gen((random_device())()); 18 | while (len--) { 19 | uniform_int_distribution zero_or_one(0, 1); 20 | uniform_int_distribution dis(0, 26); 21 | ret += (zero_or_one(gen) ? 'a' : 'A') + dis(gen); 22 | } 23 | return ret; 24 | } 25 | 26 | // @include 27 | int string_hash(const string& str, int modulus) { 28 | const int kMult = 997; 29 | // @exclude 30 | /* 31 | return accumulate(str.cbegin(), str.cend(), 0, 32 | [kMult, modulus](const int &val, const char &c) -> int { 33 | return (val * kMult + c) % modulus; 34 | }); 35 | */ 36 | // @include 37 | int val = 0; 38 | for (const char& c : str) { 39 | val = (val * kMult + c) % modulus; 40 | } 41 | return val; 42 | } 43 | // @exclude 44 | 45 | int main(int argc, char* argv[]) { 46 | default_random_engine gen((random_device())()); 47 | string str; 48 | if (argc == 2) { 49 | str = argv[1]; 50 | } else { 51 | uniform_int_distribution dis(1, 20); 52 | str = rand_string(dis(gen)); 53 | } 54 | cout << "string = " << str << endl; 55 | cout << string_hash(str, 1 << (16)) << endl; 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /Height_determination.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using std::cout; 8 | using std::endl; 9 | using std::vector; 10 | 11 | int get_height_helper(int c, int d, vector>* F); 12 | 13 | // @include 14 | int get_height(int c, int d) { 15 | vector> F(c + 1, vector(d + 1, -1)); 16 | return get_height_helper(c, d, &F); 17 | } 18 | 19 | int get_height_helper(int c, int d, vector>* F) { 20 | if (c == 0 || d == 0) { 21 | return 0; 22 | } else if (c == 1) { 23 | return d; 24 | } else { 25 | if ((*F)[c][d] == -1) { 26 | (*F)[c][d] = get_height_helper(c, d - 1, F) + 27 | get_height_helper(c - 1, d - 1, F) + 1; 28 | } 29 | return (*F)[c][d]; 30 | } 31 | } 32 | // @exclude 33 | 34 | int main(int argc, char* argv[]) { 35 | assert(get_height(1, 10) == 10); 36 | assert(get_height(2, 1) == 1); 37 | assert(get_height(2, 2) == 3); 38 | assert(get_height(2, 3) == 6); 39 | assert(get_height(2, 4) == 10); 40 | assert(get_height(2, 5) == 15); 41 | assert(get_height(3, 2) == 3); 42 | assert(get_height(100, 2) == 3); 43 | assert(get_height(3, 5) == 25); 44 | assert(get_height(8, 11) == 1980); 45 | assert(get_height(3, 0) == 0); 46 | assert(get_height(3, 1) == 1); 47 | assert(get_height(3, 3) == 7); 48 | assert(get_height(0, 10) == 0); 49 | assert(get_height(0, 0) == 0); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /Inorder_traversal_no_stack.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | 6 | #include "./Binary_tree_prototype_template.h" 7 | 8 | using std::cout; 9 | using std::endl; 10 | using std::unique_ptr; 11 | 12 | // @include 13 | template 14 | void inorder_traversal(const unique_ptr>& root) { 15 | auto* n = root.get(); 16 | while (n) { 17 | if (n->left.get()) { 18 | // Find the predecessor of n. 19 | auto* pre = n->left.get(); 20 | while (pre->right.get() && pre->right.get() != n) { 21 | pre = pre->right.get(); 22 | } 23 | 24 | // Process the successor link. 25 | if (pre->right.get()) { // pre->right.get() == n. 26 | // Revert the successor link if predecessor's successor is n. 27 | pre->right.release(); 28 | cout << n->data << endl; 29 | n = n->right.get(); 30 | } else { // if predecessor's successor is not n. 31 | pre->right.reset(n); 32 | n = n->left.get(); 33 | } 34 | } else { 35 | cout << n->data << endl; 36 | n = n->right.get(); 37 | } 38 | } 39 | } 40 | // @exclude 41 | 42 | int main(int argc, char* argv[]) { 43 | // 3 44 | // 2 5 45 | // 1 4 6 46 | unique_ptr> root = 47 | unique_ptr>(new BinaryTree{3}); 48 | root->left = unique_ptr>(new BinaryTree{2}); 49 | root->left->left = unique_ptr>(new BinaryTree{1}); 50 | root->right = unique_ptr>(new BinaryTree{5}); 51 | root->right->left = unique_ptr>(new BinaryTree{4}); 52 | root->right->right = unique_ptr>(new BinaryTree{6}); 53 | // should output 1 2 3 4 5 6 54 | inorder_traversal(root); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /Intersect_sorted_arrays.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "./Intersect_sorted_arrays1.h" 10 | #include "./Intersect_sorted_arrays2.h" 11 | #include "./Intersect_sorted_arrays3.h" 12 | 13 | using std::cout; 14 | using std::default_random_engine; 15 | using std::endl; 16 | using std::random_device; 17 | using std::uniform_int_distribution; 18 | using std::vector; 19 | 20 | void check_ans(const vector &a, const vector &b, 21 | const vector &c) { 22 | cout << a.size() << ' ' << b.size() << ' ' << c.size() << endl; 23 | assert(a.size() == b.size()); 24 | assert(b.size() == c.size()); 25 | for (int i = 0; i < a.size(); ++i) { 26 | assert(a[i] == b[i]); 27 | assert(b[i] == c[i]); 28 | } 29 | } 30 | 31 | int main(int argc, char *argv[]) { 32 | default_random_engine gen((random_device())()); 33 | for (int times = 0; times < 1000; ++times) { 34 | int n, m; 35 | vector A, B; 36 | if (argc == 3) { 37 | n = atoi(argv[1]), m = atoi(argv[2]); 38 | } else { 39 | uniform_int_distribution dis(1, 10000); 40 | n = dis(gen), m = dis(gen); 41 | } 42 | uniform_int_distribution n_dis(0, n - 1); 43 | for (int i = 0; i < n; ++i) { 44 | A.emplace_back(n_dis(gen)); 45 | } 46 | uniform_int_distribution m_dis(0, m - 1); 47 | for (int j = 0; j < m; ++j) { 48 | B.emplace_back(m_dis(gen)); 49 | } 50 | sort(A.begin(), A.end()); 51 | sort(B.begin(), B.end()); 52 | vector res1 = intersect_arrs1(A, B); 53 | vector res2 = intersect_arrs2(A, B); 54 | vector res3 = intersect_arrs3(A, B); 55 | check_ans(res1, res2, res3); 56 | } 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /Intersect_sorted_arrays1.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_INTERSECT_SORTED_ARRAYS1_H_ 4 | #define SOLUTIONS_INTERSECT_SORTED_ARRAYS1_H_ 5 | 6 | #include 7 | 8 | using std::vector; 9 | 10 | // @include 11 | vector intersect_arrs1(const vector& A, const vector& B) { 12 | vector intersect; 13 | for (int i = 0; i < A.size(); ++i) { 14 | if (i == 0 || A[i] != A[i - 1]) { 15 | for (int j = 0; j < B.size(); ++j) { 16 | if (A[i] == B[j]) { 17 | intersect.emplace_back(A[i]); 18 | break; 19 | } 20 | } 21 | } 22 | } 23 | return intersect; 24 | } 25 | // @exclude 26 | #endif // SOLUTIONS_INTERSECT_SORTED_ARRAYS1_H_ 27 | -------------------------------------------------------------------------------- /Intersect_sorted_arrays2.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_INTERSECT_SORTED_ARRAYS2_H_ 4 | #define SOLUTIONS_INTERSECT_SORTED_ARRAYS2_H_ 5 | 6 | #include 7 | #include 8 | 9 | using std::vector; 10 | 11 | // @include 12 | vector intersect_arrs2(const vector& A, const vector& B) { 13 | vector intersect; 14 | for (int i = 0; i < A.size(); ++i) { 15 | if ((i == 0 || A[i] != A[i - 1]) && 16 | binary_search(B.cbegin(), B.cend(), A[i])) { 17 | intersect.emplace_back(A[i]); 18 | } 19 | } 20 | return intersect; 21 | } 22 | // @exclude 23 | #endif // SOLUTIONS_INTERSECT_SORTED_ARRAYS2_H_ 24 | -------------------------------------------------------------------------------- /Intersect_sorted_arrays3.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_INTERSECT_SORTED_ARRAYS3_H_ 4 | #define SOLUTIONS_INTERSECT_SORTED_ARRAYS3_H_ 5 | 6 | #include 7 | 8 | using std::vector; 9 | 10 | // @include 11 | vector intersect_arrs3(const vector& A, const vector& B) { 12 | vector intersect; 13 | int i = 0, j = 0; 14 | while (i < A.size() && j < B.size()) { 15 | if (A[i] == B[j] && (i == 0 || A[i] != A[i - 1])) { 16 | intersect.emplace_back(A[i]); 17 | ++i, ++j; 18 | } else if (A[i] < B[j]) { 19 | ++i; 20 | } else { // A[i] > B[j]. 21 | ++j; 22 | } 23 | } 24 | return intersect; 25 | } 26 | // @exclude 27 | #endif // SOLUTIONS_INTERSECT_SORTED_ARRAYS3_H_ 28 | -------------------------------------------------------------------------------- /Largest_rectangle_under_skyline.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_LARGEST_RECTANGLE_UNDER_SKYLINE_H_ 4 | #define SOLUTIONS_LARGEST_RECTANGLE_UNDER_SKYLINE_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | using std::max; 11 | using std::stack; 12 | using std::vector; 13 | 14 | int calculate_largest_rectangle_alternative(const vector& A) { 15 | // Calculate L. 16 | stack s; 17 | vector L; 18 | for (int i = 0; i < A.size(); ++i) { 19 | while (!s.empty() && A[s.top()] >= A[i]) { 20 | s.pop(); 21 | } 22 | L.emplace_back(s.empty() ? -1 : s.top()); 23 | s.emplace(i); 24 | } 25 | 26 | // Clear stack for calculating R. 27 | while (!s.empty()) { 28 | s.pop(); 29 | } 30 | vector R(A.size()); 31 | for (int i = A.size() - 1; i >= 0; --i) { 32 | while (!s.empty() && A[s.top()] >= A[i]) { 33 | s.pop(); 34 | } 35 | R[i] = s.empty() ? A.size() : s.top(); 36 | s.emplace(i); 37 | } 38 | 39 | // For each A[i], find its maximum area include it. 40 | int max_area = 0; 41 | for (int i = 0; i < A.size(); ++i) { 42 | max_area = max(max_area, A[i] * (R[i] - L[i] - 1)); 43 | } 44 | return max_area; 45 | } 46 | 47 | // @include 48 | int calculate_largest_rectangle(const vector& A) { 49 | stack s; 50 | int max_area = 0; 51 | for (int i = 0; i <= A.size(); ++i) { 52 | while (!s.empty() && (i == A.size() || A[i] < A[s.top()])) { 53 | int height = A[s.top()]; 54 | s.pop(); 55 | max_area = max(max_area, height * (s.empty() ? i : i - s.top() - 1)); 56 | } 57 | s.emplace(i); 58 | } 59 | return max_area; 60 | } 61 | // @exclude 62 | #endif // SOLUTIONS_LARGEST_RECTANGLE_UNDER_SKYLINE_H_ 63 | -------------------------------------------------------------------------------- /Linked_list_prototype.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_LINKED_LIST_PROTOTYPE_H_ 4 | #define SOLUTIONS_LINKED_LIST_PROTOTYPE_H_ 5 | 6 | #include 7 | 8 | using std::shared_ptr; 9 | 10 | // @include 11 | template 12 | struct ListNode { 13 | T data; 14 | shared_ptr> next; 15 | }; 16 | // @exclude 17 | #endif // SOLUTIONS_LINKED_LIST_PROTOTYPE_H_ 18 | -------------------------------------------------------------------------------- /Longest_nondecreasing_subsequence.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "./Longest_nondecreasing_subsequence_n2.h" 10 | #include "./Longest_nondecreasing_subsequence_nlogn.h" 11 | 12 | using std::cout; 13 | using std::default_random_engine; 14 | using std::endl; 15 | using std::random_device; 16 | using std::uniform_int_distribution; 17 | using std::vector; 18 | 19 | int main(int argc, char *argv[]) { 20 | default_random_engine gen((random_device())()); 21 | for (int times = 0; times < 1000; ++times) { 22 | int n; 23 | vector A; 24 | if (argc == 2) { 25 | n = atoi(argv[1]); 26 | } else { 27 | uniform_int_distribution dis(1, 10000); 28 | n = dis(gen); 29 | } 30 | for (int i = 0; i < n; ++i) { 31 | uniform_int_distribution dis(0, 99999999); 32 | A.emplace_back(dis(gen)); 33 | } 34 | /* 35 | for (int i = 0; i < A.size(); ++i) { 36 | cout << A[i] << ' '; 37 | } 38 | cout << endl; 39 | */ 40 | cout << "n = " << n << endl; 41 | int ret_length = LNS_nlogn::longest_nondecreasing_subsequence(A); 42 | vector output = LNS_n2::longest_nondecreasing_subsequence(A); 43 | assert(ret_length == output.size()); 44 | } 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /Longest_nondecreasing_subsequence_n2.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_LONGEST_NONDECREASING_SUBSEQUENCE_N2_H_ 4 | #define SOLUTIONS_LONGEST_NONDECREASING_SUBSEQUENCE_N2_H_ 5 | 6 | #include 7 | 8 | using std::vector; 9 | 10 | namespace LNS_n2 { 11 | // @include 12 | vector longest_nondecreasing_subsequence(const vector& A) { 13 | // Empty array. 14 | if (A.empty() == true) { 15 | return A; 16 | } 17 | 18 | vector longest_length(A.size(), 1), previous_index(A.size(), -1); 19 | int max_length_idx = 0; 20 | for (int i = 1; i < A.size(); ++i) { 21 | for (int j = 0; j < i; ++j) { 22 | if (A[i] >= A[j] && longest_length[j] + 1 > longest_length[i]) { 23 | longest_length[i] = longest_length[j] + 1; 24 | previous_index[i] = j; 25 | } 26 | } 27 | // Record the index where longest subsequence ends. 28 | if (longest_length[i] > longest_length[max_length_idx]) { 29 | max_length_idx = i; 30 | } 31 | } 32 | 33 | // Build the longest nondecreasing subsequence. 34 | int max_length = longest_length[max_length_idx]; 35 | vector ret(max_length); 36 | while (max_length-- > 0) { 37 | ret[max_length] = A[max_length_idx]; 38 | max_length_idx = previous_index[max_length_idx]; 39 | } 40 | return ret; 41 | } 42 | // @exclude 43 | 44 | } // LNS_n2 45 | 46 | #endif // SOLUTIONS_LONGEST_NONDECREASING_SUBSEQUENCE_N2_H_ 47 | -------------------------------------------------------------------------------- /Longest_nondecreasing_subsequence_nlogn.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_LONGEST_NONDECREASING_SUBSEQUENCE_NLOGN_H_ 4 | #define SOLUTIONS_LONGEST_NONDECREASING_SUBSEQUENCE_NLOGN_H_ 5 | 6 | #include 7 | #include 8 | 9 | using std::vector; 10 | 11 | namespace LNS_nlogn { 12 | 13 | // @include 14 | int longest_nondecreasing_subsequence(const vector& A) { 15 | vector tail_values; 16 | for (const int& a : A) { 17 | auto it = upper_bound(tail_values.begin(), tail_values.end(), a); 18 | if (it == tail_values.end()) { 19 | tail_values.emplace_back(a); 20 | } else { 21 | *it = a; 22 | } 23 | } 24 | return tail_values.size(); 25 | } 26 | // @exclude 27 | 28 | } // LNS_nlogn 29 | 30 | #endif // SOLUTIONS_LONGEST_NONDECREASING_SUBSEQUENCE_NLOGN_H_ 31 | -------------------------------------------------------------------------------- /Max_submatrix_rectangle_brute_force.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_MAX_SUBMATRIX_RECTANGLE_BRUTE_FORCE_H_ 4 | #define SOLUTIONS_MAX_SUBMATRIX_RECTANGLE_BRUTE_FORCE_H_ 5 | 6 | #include 7 | #include 8 | 9 | using std::deque; 10 | using std::vector; 11 | 12 | // O(m^3 n^3) time solution. 13 | int max_rectangle_submatrix_brute_force(const vector> &A) { 14 | int max = 0; 15 | for (int a = 0; a < A.size(); ++a) { 16 | for (int b = 0; b < A[a].size(); ++b) { 17 | for (int c = a; c < A.size(); ++c) { 18 | for (int d = b; d < A[c].size(); ++d) { 19 | bool all_1 = true; 20 | int count = 0; 21 | for (int i = a; i <= c; ++i) { 22 | for (int j = b; j <= d; ++j) { 23 | if (A[i][j] == false) { 24 | all_1 = false; 25 | count = 0; 26 | break; 27 | } else { 28 | ++count; 29 | } 30 | } 31 | if (all_1 == false) { 32 | break; 33 | } 34 | } 35 | if (all_1 == true && count > max) { 36 | max = count; 37 | } 38 | } 39 | } 40 | } 41 | } 42 | return max; 43 | } 44 | #endif // SOLUTIONS_MAX_SUBMATRIX_RECTANGLE_BRUTE_FORCE_H_ 45 | -------------------------------------------------------------------------------- /Merge_sorted_arrays.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "./Merge_sorted_arrays.h" 10 | 11 | using std::cout; 12 | using std::default_random_engine; 13 | using std::endl; 14 | using std::random_device; 15 | using std::uniform_int_distribution; 16 | using std::vector; 17 | 18 | int main(int argc, char* argv[]) { 19 | default_random_engine gen((random_device())()); 20 | for (int times = 0; times < 100; ++times) { 21 | int n; 22 | if (argc == 2) { 23 | n = atoi(argv[1]); 24 | } else { 25 | uniform_int_distribution dis(1, 10000); 26 | n = dis(gen); 27 | } 28 | vector> S(n, vector()); 29 | cout << "n = " << n << endl; 30 | for (size_t i = 0; i < n; ++i) { 31 | uniform_int_distribution dis(1, 500); 32 | S[i].resize(dis(gen)); 33 | for (size_t j = 0; j < S[i].size(); ++j) { 34 | uniform_int_distribution zero_or_one(0, 1); 35 | uniform_int_distribution dis(0, 9999); 36 | S[i][j] = (zero_or_one(gen) ? -1 : 1) * dis(gen); 37 | } 38 | sort(S[i].begin(), S[i].end()); 39 | } 40 | /* 41 | for (size_t i = 0; i < n; ++i) { 42 | for (size_t j = 0; j < S[i].size(); ++j) { 43 | cout << S[i][j] << ' '; 44 | } 45 | cout << endl; 46 | } 47 | */ 48 | vector ans = merge_arrays(S); 49 | for (size_t i = 1; i < ans.size(); ++i) { 50 | assert(ans[i - 1] <= ans[i]); 51 | } 52 | } 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /Merge_sorted_arrays.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_MERGE_SORTED_ARRAYS_H_ 4 | #define SOLUTIONS_MERGE_SORTED_ARRAYS_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using std::pair; 12 | using std::priority_queue; 13 | using std::vector; 14 | 15 | // @include 16 | struct Compare { 17 | bool operator()(const pair& lhs, const pair& rhs) { 18 | return lhs.first > rhs.first; 19 | } 20 | }; 21 | 22 | vector merge_arrays(const vector>& S) { 23 | priority_queue, vector>, Compare> min_heap; 24 | vector S_idx(S.size(), 0); 25 | 26 | // Every array in S puts its smallest element in heap. 27 | for (int i = 0; i < S.size(); ++i) { 28 | if (S[i].size() > 0) { 29 | min_heap.emplace(S[i][0], i); 30 | S_idx[i] = 1; 31 | } 32 | } 33 | 34 | vector ret; 35 | while (!min_heap.empty()) { 36 | pair p = min_heap.top(); 37 | ret.emplace_back(p.first); 38 | // Add the smallest element into heap if possible. 39 | if (S_idx[p.second] < S[p.second].size()) { 40 | min_heap.emplace(S[p.second][S_idx[p.second]++], p.second); 41 | } 42 | min_heap.pop(); 43 | } 44 | return ret; 45 | } 46 | // @exclude 47 | #endif // SOLUTIONS_MERGE_SORTED_ARRAYS_H_ 48 | -------------------------------------------------------------------------------- /Merge_sorted_lists.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include "./Linked_list_prototype.h" 4 | 5 | void append_node_and_advance(shared_ptr>* head, 6 | shared_ptr>* tail, 7 | shared_ptr>* node); 8 | void append_node(const shared_ptr>& node, 9 | shared_ptr>* head, 10 | shared_ptr>* tail); 11 | 12 | // @include 13 | shared_ptr> merge_sorted_linked_lists( 14 | shared_ptr> F, shared_ptr> L) { 15 | shared_ptr> sorted_head = nullptr, tail = nullptr; 16 | 17 | while (F && L) { 18 | append_node_and_advance(&sorted_head, &tail, F->data < L->data ? &F : &L); 19 | } 20 | 21 | // Appends the remaining nodes of F. 22 | if (F) { 23 | append_node(F, &sorted_head, &tail); 24 | } 25 | // Appends the remaining nodes of L. 26 | if (L) { 27 | append_node(L, &sorted_head, &tail); 28 | } 29 | return sorted_head; 30 | } 31 | 32 | void append_node_and_advance(shared_ptr>* head, 33 | shared_ptr>* tail, 34 | shared_ptr>* node) { 35 | append_node(*node, head, tail); 36 | *node = (*node)->next; // advances node. 37 | } 38 | 39 | void append_node(const shared_ptr>& node, 40 | shared_ptr>* head, 41 | shared_ptr>* tail) { 42 | *head ? (*tail)->next = node : *head = node; 43 | *tail = node; // resets tail to the last node. 44 | } 45 | // @exclude 46 | -------------------------------------------------------------------------------- /Minimum_waiting_time.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::default_random_engine; 10 | using std::endl; 11 | using std::random_device; 12 | using std::uniform_int_distribution; 13 | using std::vector; 14 | 15 | // @include 16 | int minimum_waiting_time(vector service_time) { 17 | // Sort the query time in increasing order. 18 | sort(service_time.begin(), service_time.end()); 19 | 20 | int waiting = 0; 21 | for (int i = 0; i < service_time.size(); ++i) { 22 | waiting += service_time[i] * (service_time.size() - (i + 1)); 23 | } 24 | return waiting; 25 | } 26 | // @exclude 27 | 28 | int main(int argc, char* argv[]) { 29 | default_random_engine gen((random_device())()); 30 | int n; 31 | if (argc == 2) { 32 | n = atoi(argv[1]); 33 | } else { 34 | uniform_int_distribution dis(1, 100); 35 | n = dis(gen); 36 | } 37 | vector waiting_time; 38 | for (int i = 0; i < n; ++i) { 39 | uniform_int_distribution dis(0, 999); 40 | waiting_time.push_back(dis(gen)); 41 | } 42 | for (int i = 0; i < n; ++i) { 43 | cout << waiting_time[i] << ' '; 44 | } 45 | cout << endl; 46 | cout << minimum_waiting_time(waiting_time) << endl; 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /Next_permutation.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::default_random_engine; 11 | using std::endl; 12 | using std::random_device; 13 | using std::swap; 14 | using std::uniform_int_distribution; 15 | using std::vector; 16 | 17 | // @include 18 | vector next_permutation(vector p) { 19 | int k = p.size() - 2; 20 | while (k >= 0 && p[k] >= p[k + 1]) { 21 | --k; 22 | } 23 | if (k == -1) { 24 | return {}; // p is the last permutation. 25 | } 26 | 27 | int l; 28 | for (int i = k + 1; i < p.size(); ++i) { 29 | if (p[i] > p[k]) { 30 | l = i; 31 | } else { 32 | break; 33 | } 34 | } 35 | swap(p[k], p[l]); 36 | 37 | // Produce the lexicographically minimal permutation. 38 | reverse(p.begin() + k + 1, p.end()); 39 | return p; 40 | } 41 | // @exclude 42 | 43 | int main(int argc, char *argv[]) { 44 | default_random_engine gen((random_device())()); 45 | for (int times = 0; times < 1000; ++times) { 46 | vector p; 47 | if (argc > 2) { 48 | for (size_t i = 1; i < argc; ++i) { 49 | p.emplace_back(atoi(argv[i])); 50 | } 51 | } else { 52 | uniform_int_distribution dis(1, 100); 53 | int n = (argc == 2 ? atoi(argv[1]) : dis(gen)); 54 | uniform_int_distribution n_dis(0, n - 1); 55 | generate_n(back_inserter(p), n, [&] { return n_dis(gen); }); 56 | } 57 | 58 | vector ans(next_permutation(p)); 59 | // Use built-in function verification. 60 | bool has_next_one = next_permutation(p.begin(), p.end()); 61 | assert((ans.size() == 0 && !has_next_one) || equal(ans.cbegin(), ans.cend(), p.cbegin())); 62 | } 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /Number_ways_obstacles.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::default_random_engine; 10 | using std::deque; 11 | using std::endl; 12 | using std::random_device; 13 | using std::uniform_int_distribution; 14 | using std::vector; 15 | 16 | // @include 17 | // Given the dimensions of A, n and m, and B, return the number of ways 18 | // from A[0][0] to A[n - 1][m - 1] considering obstacles. 19 | int number_of_ways_with_obstacles(int n, int m, 20 | const vector> &B) { 21 | vector> A(n, vector(m, 0)); 22 | if (B[0][0]) { // no way to start from (0, 0) if B[0][0] == true. 23 | return 0; 24 | } else { 25 | A[0][0] = 1; 26 | } 27 | for (int i = 0; i < n; ++i) { 28 | for (int j = 0; j < m; ++j) { 29 | if (B[i][j] == 0) { 30 | A[i][j] += (i < 1 ? 0 : A[i - 1][j]) + (j < 1 ? 0 : A[i][j - 1]); 31 | } 32 | } 33 | } 34 | return A.back().back(); 35 | } 36 | // @exclude 37 | 38 | int main(int argc, char* argv[]) { 39 | default_random_engine gen((random_device())()); 40 | int n, m; 41 | if (argc == 3) { 42 | n = atoi(argv[1]), m = atoi(argv[2]); 43 | } else { 44 | uniform_int_distribution dis(1, 10); 45 | n = dis(gen); 46 | m = dis(gen); 47 | } 48 | vector> B(n, deque(m)); 49 | for (size_t i = 0; i < n; ++i) { 50 | for (size_t j = 0; j < m; ++j) { 51 | uniform_int_distribution dis(0, 9); 52 | int x = dis(gen); 53 | B[i][j] = ((x < 2) ? 1 : 0); 54 | } 55 | } 56 | for (size_t i = 0; i < n; ++i) { 57 | for (size_t j = 0; j < m; ++j) { 58 | cout << B[i][j] << ' '; 59 | } 60 | cout << endl; 61 | } 62 | cout << number_of_ways_with_obstacles(n, m, B) << endl; 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /Offline_sampling.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::default_random_engine; 11 | using std::endl; 12 | using std::random_device; 13 | using std::swap; 14 | using std::uniform_int_distribution; 15 | using std::vector; 16 | 17 | // @include 18 | vector offline_sampling(vector A, int k) { 19 | default_random_engine gen((random_device())()); // random num generator. 20 | for (int i = 0; i < k; ++i) { 21 | // Generate a random int in [i, A.size() - 1]. 22 | uniform_int_distribution dis(i, A.size() - 1); 23 | swap(A[i], A[dis(gen)]); 24 | } 25 | A.resize(k); 26 | return A; 27 | } 28 | // @exclude 29 | 30 | int main(int argc, char *argv[]) { 31 | int n, k; 32 | default_random_engine gen((random_device())()); 33 | vector A; 34 | if (argc == 2) { 35 | n = atoi(argv[1]); 36 | uniform_int_distribution dis(1, n); 37 | k = dis(gen); 38 | } else if (argc == 3) { 39 | n = atoi(argv[1]); 40 | k = atoi(argv[2]); 41 | } else { 42 | uniform_int_distribution n_dis(1, 1000000); 43 | n = n_dis(gen); 44 | uniform_int_distribution k_dis(1, n); 45 | k = k_dis(gen); 46 | } 47 | for (int i = 0; i < n; ++i) { 48 | A.emplace_back(i); 49 | } 50 | cout << n << ' ' << k << endl; 51 | vector ans = offline_sampling(A, k); 52 | assert(ans.size() == k); 53 | for (int i = 0; i < k; ++i) { 54 | cout << ans[i] << ' '; 55 | } 56 | cout << endl; 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /Overlapping_lists_no_cycle.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "./Linked_list_prototype.h" 8 | #include "./Overlapping_lists_no_cycle.h" 9 | 10 | using std::cout; 11 | using std::endl; 12 | using std::make_shared; 13 | using std::shared_ptr; 14 | 15 | int main(int argc, char* argv[]) { 16 | shared_ptr> L1, L2; 17 | // L1: 1->2->3->null 18 | L1 = make_shared>(ListNode{ 19 | 1, make_shared>(ListNode{2, make_shared>(ListNode{3, nullptr})})}); 20 | L2 = L1->next->next; 21 | assert(overlapping_no_cycle_lists(L1, L2)->data == 3); 22 | // L2: 4->5->null 23 | L2 = make_shared>(ListNode{4, make_shared>(ListNode{5, nullptr})}); 24 | assert(!overlapping_no_cycle_lists(L1, L2)); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /Overlapping_lists_no_cycle.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_OVERLAPPING_LISTS_NO_CYCLE_H_ 4 | #define SOLUTIONS_OVERLAPPING_LISTS_NO_CYCLE_H_ 5 | 6 | #include "./Linked_list_prototype.h" 7 | 8 | int count_len(shared_ptr> L); 9 | void advance_list_by_k(shared_ptr>* L, int k); 10 | 11 | // @include 12 | shared_ptr> overlapping_no_cycle_lists( 13 | shared_ptr> L1, shared_ptr> L2) { 14 | // Counts the lengths of L1 and L2. 15 | int L1_len = count_len(L1), L2_len = count_len(L2); 16 | 17 | // Advances the longer list. 18 | advance_list_by_k(L1_len > L2_len ? &L1 : &L2, abs(L1_len - L2_len)); 19 | 20 | while (L1 && L2 && L1 != L2) { 21 | L1 = L1->next, L2 = L2->next; 22 | } 23 | return L1; // nullptr means no overlap between L1 and L2. 24 | } 25 | 26 | // Counts the list length till end. 27 | int count_len(shared_ptr> L) { 28 | int len = 0; 29 | while (L) { 30 | ++len, L = L->next; 31 | } 32 | return len; 33 | } 34 | 35 | // Advances L by n steps. 36 | void advance_list_by_k(shared_ptr>* L, int k) { 37 | while (k--) { 38 | *L = (*L)->next; 39 | } 40 | } 41 | // @exclude 42 | #endif // SOLUTIONS_OVERLAPPING_LISTS_NO_CYCLE_H_ 43 | -------------------------------------------------------------------------------- /Parity.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "./Parity1.h" 9 | #include "./Parity2.h" 10 | #include "./Parity3.h" 11 | #include "./Parity4.h" 12 | 13 | using std::cout; 14 | using std::default_random_engine; 15 | using std::endl; 16 | using std::numeric_limits; 17 | using std::random_device; 18 | using std::uniform_int_distribution; 19 | 20 | int main(int argc, char* argv[]) { 21 | build_table(); 22 | if (argc == 2) { 23 | long x = atol(argv[1]); 24 | assert(parity1(x) == parity3(x)); 25 | assert(parity2(x) == parity3(x)); 26 | assert(parity3(x) == parity4(x)); 27 | cout << "x = " << x << ", parity = " << parity3(x) << endl; 28 | } else { 29 | default_random_engine gen((random_device())()); 30 | for (int times = 0; times < 1000; ++times) { 31 | uniform_int_distribution dis(0, numeric_limits::max()); 32 | long x = dis(gen); 33 | assert(parity1(x) == parity3(x)); 34 | assert(parity2(x) == parity3(x)); 35 | assert(parity4(x) == parity3(x)); 36 | cout << "x = " << x << ", parity = " << parity3(x) << endl; 37 | } 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /Parity1.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_PARITY1_H_ 4 | #define SOLUTIONS_PARITY1_H_ 5 | 6 | // @include 7 | short parity1(unsigned long x) { 8 | short result = 0; 9 | while (x) { 10 | result ^= (x & 1); 11 | x >>= 1; 12 | } 13 | return result; 14 | } 15 | // @exclude 16 | #endif // SOLUTIONS_PARITY1_H_ 17 | -------------------------------------------------------------------------------- /Parity2.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_PARITY2_H_ 4 | #define SOLUTIONS_PARITY2_H_ 5 | 6 | // @include 7 | short parity2(unsigned long x) { 8 | short result = 0; 9 | while (x) { 10 | result ^= 1; 11 | x &= (x - 1); // erases the lowest set bit of x. 12 | } 13 | return result; 14 | } 15 | // @exclude 16 | #endif // SOLUTIONS_PARITY2_H_ 17 | -------------------------------------------------------------------------------- /Parity3.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_PARITY3_H_ 4 | #define SOLUTIONS_PARITY3_H_ 5 | 6 | static bool is_initialized = false; 7 | 8 | short precomputed_parity[1 << 16]; 9 | 10 | void build_table() { 11 | if (!is_initialized) { 12 | for (int i = 0; i < (1 << 16); ++i) { 13 | precomputed_parity[i] = parity1(i); 14 | } 15 | is_initialized = true; 16 | } 17 | } 18 | 19 | // @include 20 | short parity3(unsigned long x) { 21 | return precomputed_parity[x >> 48] ^ 22 | precomputed_parity[(x >> 32) & 0b1111111111111111] ^ 23 | precomputed_parity[(x >> 16) & 0b1111111111111111] ^ 24 | precomputed_parity[x & 0b1111111111111111]; 25 | } 26 | // @exclude 27 | #endif // SOLUTIONS_PARITY3_H_ 28 | -------------------------------------------------------------------------------- /Parity4.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_PARITY4_H_ 4 | #define SOLUTIONS_PARITY4_H_ 5 | 6 | short four_bit_parity_lookup(int x); 7 | 8 | // @include 9 | short parity4(unsigned long x) { 10 | x ^= x >> 32; 11 | x ^= x >> 16; 12 | x ^= x >> 8; 13 | x ^= x >> 4; 14 | x &= 0xf; // only want the last 4 bits of x. 15 | // Return the LSB, which is the parity. 16 | return four_bit_parity_lookup(x) & 1; 17 | } 18 | 19 | // The LSB of kFourBitParityLookupTable is the parity of 0, 20 | // next bit is parity of 1, followed by the parity of 2, etc. 21 | 22 | const int kFourBitParityLookupTable = 0x6996; // = 0b0110100110010110. 23 | 24 | short four_bit_parity_lookup(int x) { 25 | return kFourBitParityLookupTable >> x; 26 | } 27 | // @exclude 28 | #endif // SOLUTIONS_PARITY4_H_ 29 | -------------------------------------------------------------------------------- /Permutation_array.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "./Permutation_array1.h" 11 | #include "./Permutation_array2.h" 12 | 13 | using std::cout; 14 | using std::default_random_engine; 15 | using std::endl; 16 | using std::ostream_iterator; 17 | using std::random_device; 18 | using std::uniform_int_distribution; 19 | using std::vector; 20 | 21 | int main(int argc, char *argv[]) { 22 | default_random_engine gen((random_device())()); 23 | int n; 24 | for (int times = 0; times < 1000; ++times) { 25 | if (argc == 2) { 26 | n = atoi(argv[1]); 27 | } else { 28 | uniform_int_distribution dis(1, 100); 29 | n = dis(gen); 30 | } 31 | vector A, perm; 32 | for (int i = 0; i < n; ++i) { 33 | A.emplace_back(i); 34 | perm.emplace_back(i); 35 | } 36 | 37 | // knuth shuffle 38 | random_shuffle(perm.begin(), perm.end()); 39 | copy(perm.begin(), perm.end(), ostream_iterator(cout, " ")); 40 | cout << endl; 41 | 42 | vector B(A); 43 | apply_permutation1(&perm, &B); 44 | copy(B.begin(), B.end(), ostream_iterator(cout, " ")); 45 | cout << endl; 46 | vector C(A); 47 | apply_permutation2(&perm, &C); 48 | copy(C.begin(), C.end(), ostream_iterator(cout, " ")); 49 | cout << endl; 50 | // check answer by comparing the two permutations 51 | assert(equal(B.begin(), B.end(), C.begin())); 52 | assert(B.size() == C.size()); 53 | } 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /Permutation_array1.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_PERMUTATION_ARRAY1_H_ 4 | #define SOLUTIONS_PERMUTATION_ARRAY1_H_ 5 | 6 | #include 7 | #include 8 | 9 | using std::vector; 10 | 11 | // @include 12 | void apply_permutation1(vector* perm, vector* A) { 13 | for (int i = 0; i < A->size(); ++i) { 14 | if ((*perm)[i] >= 0) { 15 | int a = i; 16 | int temp = (*A)[i]; 17 | do { 18 | int next_a = (*perm)[a]; 19 | int next_temp = (*A)[next_a]; 20 | (*A)[next_a] = temp; 21 | // Mark a as visited by using the sign bit. 22 | (*perm)[a] -= perm->size(); 23 | a = next_a, temp = next_temp; 24 | } while (a != i); 25 | } 26 | } 27 | 28 | // Restore perm back. 29 | for_each(perm->begin(), perm->end(), [&](int &x) { x += perm->size(); }); 30 | } 31 | // @exclude 32 | #endif // SOLUTIONS_PERMUTATION_ARRAY1_H_ 33 | -------------------------------------------------------------------------------- /Permutation_array2.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_PERMUTATION_ARRAY2_H_ 4 | #define SOLUTIONS_PERMUTATION_ARRAY2_H_ 5 | 6 | #include 7 | 8 | using std::vector; 9 | 10 | // @include 11 | void apply_permutation2(vector* perm, vector* A) { 12 | for (int i = 0; i < A->size(); ++i) { 13 | // Traverse the cycle to see if i is the min element. 14 | bool is_min = true; 15 | int j = (*perm)[i]; 16 | while (j != i) { 17 | if (j < i) { 18 | is_min = false; 19 | break; 20 | } 21 | j = (*perm)[j]; 22 | } 23 | 24 | if (is_min) { 25 | int a = i; 26 | int temp = (*A)[i]; 27 | do { 28 | int next_a = (*perm)[a]; 29 | int next_temp = (*A)[next_a]; 30 | (*A)[next_a] = temp; 31 | a = next_a, temp = next_temp; 32 | } while (a != i); 33 | } 34 | } 35 | } 36 | // @exclude 37 | #endif // SOLUTIONS_PERMUTATION_ARRAY2_H_ 38 | -------------------------------------------------------------------------------- /Phone_mnemonic.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::array; 9 | using std::cout; 10 | using std::default_random_engine; 11 | using std::endl; 12 | using std::random_device; 13 | using std::string; 14 | using std::uniform_int_distribution; 15 | 16 | void phone_mnemonic_helper(const string &num, int d, string* ans); 17 | 18 | // @include 19 | void phone_mnemonic(const string &num) { 20 | string ans(num.size(), 0); 21 | phone_mnemonic_helper(num, 0, &ans); 22 | } 23 | 24 | const int kNumTelDigits = 10; 25 | 26 | const array M = {{"0", "1", "ABC", "DEF", "GHI", 27 | "JKL", "MNO", "PQRS", "TUV", 28 | "WXYZ"}}; 29 | 30 | void phone_mnemonic_helper(const string &num, int d, string* ans) { 31 | if (d == num.size()) { // get enough characters and output answer. 32 | cout << *ans << endl; 33 | } else { 34 | for (const char &c : M[num[d] - '0']) { // try all combinations. 35 | (*ans)[d] = c; 36 | phone_mnemonic_helper(num, d + 1, ans); 37 | } 38 | } 39 | } 40 | // @exclude 41 | 42 | string rand_string(int len) { 43 | default_random_engine gen((random_device())()); 44 | string ret; 45 | while (len--) { 46 | uniform_int_distribution dis('0', '9'); 47 | ret += dis(gen); 48 | } 49 | return ret; 50 | } 51 | 52 | int main(int argc, char *argv[]) { 53 | string num; 54 | if (argc == 2) { 55 | num = argv[1]; 56 | } else { 57 | num = rand_string(10); 58 | } 59 | phone_mnemonic(num); 60 | cout << "number = " << num << endl; 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /Planning_fishing.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::default_random_engine; 10 | using std::endl; 11 | using std::max; 12 | using std::random_device; 13 | using std::uniform_int_distribution; 14 | using std::vector; 15 | 16 | // @include 17 | int maximize_fishing(vector> A) { 18 | for (int i = 0; i < A.size(); ++i) { 19 | for (int j = 0; j < A[i].size(); ++j) { 20 | A[i][j] += max(i < 1 ? 0 : A[i - 1][j], j < 1 ? 0 : A[i][j - 1]); 21 | } 22 | } 23 | return A.back().back(); 24 | } 25 | // @exclude 26 | 27 | int main(int argc, char* argv[]) { 28 | default_random_engine gen((random_device())()); 29 | int n, m; 30 | if (argc == 3) { 31 | n = atoi(argv[1]), m = atoi(argv[2]); 32 | } else { 33 | uniform_int_distribution dis(1, 100); 34 | n = dis(gen), m = dis(gen); 35 | } 36 | vector> A(n, vector(m)); 37 | for (size_t i = 0; i < n; ++i) { 38 | for (size_t j = 0; j < m; ++j) { 39 | uniform_int_distribution dis(0, 999); 40 | A[i][j] = dis(gen); 41 | } 42 | } 43 | for (size_t i = 0; i < n; ++i) { 44 | for (size_t j = 0; j < m; ++j) { 45 | cout << A[i][j] << ' '; 46 | } 47 | cout << endl; 48 | } 49 | cout << maximize_fishing(A) << endl; 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /Postings_list_prototype.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_POSTINGS_LIST_PROTOTYPE_H_ 4 | #define SOLUTIONS_POSTINGS_LIST_PROTOTYPE_H_ 5 | 6 | #include 7 | 8 | using std::shared_ptr; 9 | 10 | // @include 11 | template 12 | class ListNode { 13 | public: 14 | T data; 15 | shared_ptr> next, jump; 16 | }; 17 | // @exclude 18 | #endif // SOLUTIONS_POSTINGS_LIST_PROTOTYPE_H_ 19 | -------------------------------------------------------------------------------- /Power_set.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::default_random_engine; 10 | using std::endl; 11 | using std::random_device; 12 | using std::uniform_int_distribution; 13 | using std::vector; 14 | 15 | // @include 16 | void generate_power_set(const vector& S) { 17 | for (int i = 0; i < (1 << S.size()); ++i) { 18 | int x = i; 19 | while (x) { 20 | int tar = log2(x & ~(x - 1)); 21 | cout << S[tar]; 22 | if (x &= x - 1) { 23 | cout << ','; 24 | } 25 | } 26 | cout << endl; 27 | } 28 | } 29 | // @exclude 30 | 31 | int main(int argc, char* argv[]) { 32 | vector S; 33 | if (argc >= 2) { 34 | for (int i = 1; i < argc; ++i) { 35 | S.emplace_back(atoi(argv[i])); 36 | } 37 | } else { 38 | default_random_engine gen((random_device())()); 39 | uniform_int_distribution dis(1, 10); 40 | S.resize(dis(gen)); 41 | for (int i = 0; i < S.size(); ++i) { 42 | S[i] = i; 43 | } 44 | } 45 | generate_power_set(S); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /Power_set_alternative.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::default_random_engine; 11 | using std::endl; 12 | using std::ostream_iterator; 13 | using std::random_device; 14 | using std::uniform_int_distribution; 15 | using std::vector; 16 | 17 | void generate_power_set_helper(const vector& S, int m, vector* subset); 18 | 19 | // @include 20 | void generate_power_set(const vector& S) { 21 | vector subset; 22 | generate_power_set_helper(S, 0, &subset); 23 | } 24 | 25 | void generate_power_set_helper(const vector& S, int m, 26 | vector* subset) { 27 | if (!subset->empty()) { 28 | // Print the subset. 29 | cout << subset->front(); 30 | for (int i = 1; i < subset->size(); ++i) { 31 | cout << "," << (*subset)[i]; 32 | } 33 | } 34 | cout << endl; 35 | 36 | for (int i = m; i < S.size(); ++i) { 37 | subset->emplace_back(S[i]); 38 | generate_power_set_helper(S, i + 1, subset); 39 | subset->pop_back(); 40 | } 41 | } 42 | // @exclude 43 | 44 | int main(int argc, char* argv[]) { 45 | vector S; 46 | if (argc >= 2) { 47 | for (int i = 1; i < argc; ++i) { 48 | S.emplace_back(atoi(argv[i])); 49 | } 50 | } else { 51 | default_random_engine gen((random_device())()); 52 | uniform_int_distribution dis(1, 10); 53 | S.resize(dis(gen)); 54 | for (int i = 0; i < S.size(); ++i) { 55 | S[i] = i; 56 | } 57 | } 58 | generate_power_set(S); 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /PrintMatrixSpiral.java: -------------------------------------------------------------------------------- 1 | public class PrintMatrixSpiral { 2 | // @include 3 | static void printCycle(int A[][], int offset) { 4 | for (int j = offset; j < A.length - offset - 1; ++j) { 5 | System.out.print(A[offset][j] + ","); 6 | } 7 | for (int i = offset; i < A.length - offset - 1; ++i) { 8 | System.out.print(A[i][A.length - offset - 1] + ","); 9 | } 10 | for (int j = A.length - offset - 1; j > offset; --j) { 11 | System.out.print(A[A.length - offset - 1][j] + ","); 12 | } 13 | for (int i = A.length - offset - 1; i > offset; --i) { 14 | System.out.print(A[i][offset] + ","); 15 | } 16 | } 17 | 18 | static void printMatrix(int [][] A) { 19 | for (int l = 0; l <= A.length / 2; ++l) { 20 | printCycle(A, l); 21 | } 22 | } 23 | // @exclude 24 | 25 | public static int A1[][] = {{0}}; 26 | public static int A2[][] = {{0,1,2},{7,8,3},{6,5,4}}; 27 | public static int A3[][] = {{0,1,2},{7,8,3},{6,5,4}}; 28 | public static int A4[][] = {{0,1,2,3},{11,12,13,4},{10,15,14,5},{9,8,7,6}}; 29 | public static int A5[][] = {{0,1,2,3,4},{15,16,17,18,5},{14,23,24,19,6},{13,22,21,20,7},{12,11,10,9,8}}; 30 | public static int A6[][] = {{0,1,2,3,4,5},{19,20,21,22,23,6},{18,31,32,33,24,7},{17,30,35,34,25,8},{16,29,28,27,26,9},{15,14,13,12,11,10}}; 31 | 32 | public static void main(String [] args) { 33 | printMatrix(A1); 34 | System.out.println(); 35 | printMatrix(A2); 36 | System.out.println(); 37 | printMatrix(A3); 38 | System.out.println(); 39 | printMatrix(A4); 40 | System.out.println(); 41 | printMatrix(A5); 42 | System.out.println(); 43 | printMatrix(A6); 44 | System.out.println(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Queue_from_stacks.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::endl; 10 | using std::exception; 11 | using std::length_error; 12 | using std::stack; 13 | 14 | // @include 15 | class Queue { 16 | public: 17 | void enqueue(int x) { A_.emplace(x); } 18 | 19 | int dequeue() { 20 | if (B_.empty()) { 21 | while (!A_.empty()) { 22 | B_.emplace(A_.top()); 23 | A_.pop(); 24 | } 25 | } 26 | if (!B_.empty()) { 27 | int ret = B_.top(); 28 | B_.pop(); 29 | return ret; 30 | } 31 | throw length_error("empty queue"); 32 | } 33 | 34 | private: 35 | stack A_, B_; 36 | }; 37 | // @exclude 38 | 39 | int main(int argc, char* argv[]) { 40 | Queue Q; 41 | Q.enqueue(1); 42 | Q.enqueue(2); 43 | assert(1 == Q.dequeue()); // 1 44 | assert(2 == Q.dequeue()); // 2 45 | Q.enqueue(3); 46 | assert(3 == Q.dequeue()); // 3 47 | try { 48 | Q.dequeue(); 49 | } 50 | catch (const exception& e) { 51 | cout << e.what() << endl; // throw 52 | } 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /Queue_using_two_integers.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::endl; 11 | using std::exception; 12 | using std::length_error; 13 | using std::numeric_limits; 14 | 15 | // @include 16 | class Queue { 17 | public: 18 | void enqueue(unsigned x) { 19 | if (size_ >= max_size_) { 20 | throw length_error("queue overflow"); 21 | } 22 | val_ = val_ * 10 + x; 23 | ++size_; 24 | } 25 | 26 | unsigned dequeue() { 27 | if (!size_) { 28 | throw length_error("empty queue"); 29 | } 30 | unsigned ret = val_ / pow(10.0, --size_); 31 | val_ -= pow(10.0, size_) * ret; 32 | return ret; 33 | } 34 | 35 | private: 36 | unsigned val_ = 0; 37 | size_t size_ = 0, max_size_ = floor(log10(numeric_limits::max())); 38 | }; 39 | // @exclude 40 | 41 | int main(int argc, char* argv[]) { 42 | Queue q; 43 | q.enqueue(0); 44 | q.enqueue(5); 45 | q.enqueue(0); 46 | q.enqueue(2); 47 | assert(0 == q.dequeue()); 48 | assert(5 == q.dequeue()); 49 | q.enqueue(3); 50 | assert(0 == q.dequeue()); 51 | assert(2 == q.dequeue()); 52 | assert(3 == q.dequeue()); 53 | q.enqueue(0); 54 | q.enqueue(0); 55 | assert(0 == q.dequeue()); 56 | assert(0 == q.dequeue()); 57 | // Empty queue, it should throw. 58 | try { 59 | q.dequeue(); 60 | } 61 | catch (const exception& e) { 62 | cout << e.what() << endl; 63 | } 64 | q.enqueue(0); 65 | q.enqueue(0); 66 | q.enqueue(0); 67 | q.enqueue(0); 68 | q.enqueue(5); 69 | q.enqueue(0); 70 | q.enqueue(2); 71 | q.enqueue(5); 72 | q.enqueue(0); 73 | // Queue overflow, it should throw. 74 | try { 75 | q.enqueue(2); 76 | } 77 | catch (const exception& e) { 78 | cout << e.what() << endl; 79 | } 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /Queue_with_max.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "./Stack_with_max.h" 9 | 10 | using std::cout; 11 | using std::endl; 12 | using std::exception; 13 | using std::length_error; 14 | 15 | // @include 16 | class Queue { 17 | public: 18 | void enqueue(int x) { A_.push(x); } 19 | 20 | int dequeue() { 21 | if (B_.empty()) { 22 | while (!A_.empty()) { 23 | B_.push(A_.pop()); 24 | } 25 | } 26 | if (!B_.empty()) { 27 | return B_.pop(); 28 | } 29 | throw length_error("empty queue"); 30 | } 31 | 32 | int max() const { 33 | if (!A_.empty()) { 34 | return B_.empty() ? A_.max() : std::max(A_.max(), B_.max()); 35 | } else { // A_.empty() == true. 36 | if (!B_.empty()) { 37 | return B_.max(); 38 | } 39 | throw length_error("empty queue"); 40 | } 41 | } 42 | 43 | private: 44 | Stack A_, B_; 45 | }; 46 | // @exclude 47 | 48 | int main(int argc, char* argv[]) { 49 | Queue Q; 50 | Q.enqueue(1); 51 | Q.enqueue(2); 52 | assert(2 == Q.max()); 53 | assert(1 == Q.dequeue()); // 1 54 | assert(2 == Q.max()); 55 | assert(2 == Q.dequeue()); // 2 56 | Q.enqueue(3); 57 | assert(3 == Q.max()); 58 | assert(3 == Q.dequeue()); // 3 59 | try { 60 | Q.max(); 61 | } 62 | catch (const exception& e) { 63 | cout << e.what() << endl; // throw 64 | } 65 | try { 66 | Q.dequeue(); 67 | } 68 | catch (const exception& e) { 69 | cout << e.what() << endl; // throw 70 | } 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /Queue_with_max_using_deque.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include "./Queue_with_max_using_deque.h" 4 | 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::endl; 10 | using std::exception; 11 | 12 | // Just for testing. 13 | int main(int argc, char* argv[]) { 14 | Queue Q; 15 | Q.enqueue(1); 16 | Q.enqueue(2); 17 | assert(2 == Q.max()); 18 | assert(1 == Q.dequeue()); // 1 19 | assert(2 == Q.max()); 20 | assert(2 == Q.dequeue()); // 2 21 | Q.enqueue(3); 22 | assert(3 == Q.max()); 23 | assert(3 == Q.dequeue()); // 3 24 | try { 25 | Q.max(); 26 | } 27 | catch (const exception& e) { 28 | cout << e.what() << endl; // throw 29 | } 30 | try { 31 | Q.dequeue(); 32 | } 33 | catch (const exception& e) { 34 | cout << e.what() << endl; // throw 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /Queue_with_max_using_deque.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_QUEUE_WITH_MAX_USING_DEQUE_H_ 4 | #define SOLUTIONS_QUEUE_WITH_MAX_USING_DEQUE_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using std::deque; 12 | using std::length_error; 13 | using std::queue; 14 | 15 | // @include 16 | template 17 | class Queue { 18 | public: 19 | void enqueue(const T& x) { 20 | Q_.emplace(x); 21 | while (!D_.empty() && D_.back() < x) { 22 | D_.pop_back(); 23 | } 24 | D_.emplace_back(x); 25 | } 26 | 27 | T dequeue() { 28 | if (!Q_.empty()) { 29 | T ret = Q_.front(); 30 | if (ret == D_.front()) { 31 | D_.pop_front(); 32 | } 33 | Q_.pop(); 34 | return ret; 35 | } 36 | throw length_error("empty queue"); 37 | } 38 | 39 | const T& max() const { 40 | if (!D_.empty()) { 41 | return D_.front(); 42 | } 43 | throw length_error("empty queue"); 44 | } 45 | // @exclude 46 | T& head() { return Q_.front(); } 47 | 48 | const T& head() const { return Q_.front(); } 49 | // @include 50 | 51 | private: 52 | queue Q_; 53 | deque D_; 54 | }; 55 | // @exclude 56 | #endif // SOLUTIONS_QUEUE_WITH_MAX_USING_DEQUE_H_ 57 | -------------------------------------------------------------------------------- /RPN.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::stack; 9 | using std::string; 10 | using std::stringstream; 11 | 12 | // @include 13 | int eval(const string& s) { 14 | stack eval_stack; 15 | stringstream ss(s); 16 | string symbol; 17 | 18 | while (getline(ss, symbol, ',')) { 19 | if (symbol == "+" || symbol == "-" || symbol == "*" || symbol == "/") { 20 | int y = eval_stack.top(); 21 | eval_stack.pop(); 22 | int x = eval_stack.top(); 23 | eval_stack.pop(); 24 | switch (symbol.front()) { 25 | case '+': 26 | eval_stack.emplace(x + y); 27 | break; 28 | case '-': 29 | eval_stack.emplace(x - y); 30 | break; 31 | case '*': 32 | eval_stack.emplace(x * y); 33 | break; 34 | case '/': 35 | eval_stack.emplace(x / y); 36 | break; 37 | } 38 | } else { // number. 39 | eval_stack.emplace(stoi(symbol)); 40 | } 41 | } 42 | return eval_stack.top(); 43 | } 44 | // @exclude 45 | 46 | int main(int argc, char* argv[]) { 47 | assert(0 == eval("2,-10,/")); 48 | assert(-5 == eval("-10,2,/")); 49 | assert(5 == eval("-10,-2,/")); 50 | assert(-5 == eval("5,10,-")); 51 | assert(6 == eval("-10,-16,-")); 52 | assert(12 == eval("10,2,+")); 53 | assert(15 == eval("1,2,+,3,4,*,+")); 54 | assert(42 == eval("1,2,3,4,5,+,*,+,+,3,4,*,+")); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /Rearrange.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::default_random_engine; 11 | using std::endl; 12 | using std::random_device; 13 | using std::swap; 14 | using std::uniform_int_distribution; 15 | using std::vector; 16 | 17 | // @include 18 | void rearrange(vector* A) { 19 | vector& B = *A; 20 | for (size_t i = 1; i < B.size(); ++i) { 21 | if ((!(i & 1) && B[i - 1] < B[i]) || ((i & 1) && B[i - 1] > B[i])) { 22 | swap(B[i - 1], B[i]); 23 | } 24 | } 25 | } 26 | // @exclude 27 | 28 | void check_answer(const vector& A) { 29 | for (size_t i = 0; i < A.size(); ++i) { 30 | if (i & 1) { 31 | assert(A[i] >= A[i - 1]); 32 | if (i + 1 < A.size()) { 33 | assert(A[i] >= A[i + 1]); 34 | } 35 | } else { 36 | if (i > 0) { 37 | assert(A[i - 1] >= A[i]); 38 | } 39 | if (i + 1 < A.size()) { 40 | assert(A[i + 1] >= A[i]); 41 | } 42 | } 43 | } 44 | } 45 | 46 | int main(int argc, char* argv[]) { 47 | default_random_engine gen((random_device())()); 48 | for (int times = 0; times < 10000; ++times) { 49 | int n; 50 | if (argc == 2) { 51 | n = atoi(argv[1]); 52 | } else { 53 | uniform_int_distribution dis(1, 10000); 54 | n = dis(gen); 55 | } 56 | vector A; 57 | uniform_int_distribution dis(-n, n); 58 | for (int i = 0; i < n; ++i) { 59 | A.emplace_back(dis(gen)); 60 | } 61 | rearrange(&A); 62 | /* 63 | for (const int &a : A) { 64 | cout << a << ' '; 65 | } 66 | cout << endl; 67 | */ 68 | check_answer(A); 69 | } 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /Remove_kth_last_list.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "./Linked_list_prototype.h" 9 | 10 | using std::cout; 11 | using std::endl; 12 | using std::exception; 13 | using std::length_error; 14 | using std::make_shared; 15 | using std::shared_ptr; 16 | 17 | // @include 18 | void remove_kth_last(int k, shared_ptr>* L) { 19 | // Advances k steps first. 20 | shared_ptr> ahead = *L; 21 | int num = k; 22 | while (ahead && num) { 23 | ahead = ahead->next; 24 | --num; 25 | } 26 | 27 | if (num) { 28 | throw length_error("not enough nodes in the list"); 29 | } 30 | 31 | shared_ptr> pre = nullptr, curr = *L; 32 | // Finds the k-th last node. 33 | while (ahead) { 34 | pre = curr; 35 | curr = curr->next, ahead = ahead->next; 36 | } 37 | if (pre) { 38 | pre->next = curr->next; 39 | } else { 40 | *L = curr->next; // special case: delete L. 41 | } 42 | } 43 | // @exclude 44 | 45 | int main(int argc, char* argv[]) { 46 | shared_ptr> L; 47 | L = make_shared>(ListNode{ 48 | 1, make_shared>(ListNode{ 49 | 2, make_shared>(ListNode{3, nullptr})})}); 50 | try { 51 | remove_kth_last(4, &L); 52 | } 53 | catch (const exception& e) { 54 | cout << e.what() << endl; 55 | } 56 | remove_kth_last(2, &L); 57 | assert(L->data == 1 && L->next->data == 3); 58 | remove_kth_last(2, &L); 59 | assert(L->data == 3 && L->next == nullptr); 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /Reverse_bits.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "./swap_bits.h" 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::numeric_limits; 14 | using std::random_device; 15 | using std::uniform_int_distribution; 16 | using std::vector; 17 | 18 | vector precomputed_reverse; 19 | 20 | long reverse_x(long x, int n) { 21 | for (int i = 0, j = n; i < j; ++i, --j) { 22 | x = swap_bits(x, i, j); 23 | } 24 | return x; 25 | } 26 | 27 | void create_precomputed_table() { 28 | for (int i = 0; i < (1 << 16); ++i) { 29 | precomputed_reverse.emplace_back(reverse_x(i, 15)); 30 | } 31 | } 32 | 33 | // @include 34 | long reverse_bits(long x) { 35 | return precomputed_reverse[(x >> 48) & 0b1111111111111111] | 36 | precomputed_reverse[(x >> 32) & 0b1111111111111111] << 16 | 37 | precomputed_reverse[(x >> 16) & 0b1111111111111111] << 32 | 38 | precomputed_reverse[x & 0b1111111111111111] << 48; 39 | } 40 | // @exclude 41 | 42 | int main(int argc, char* argv[]) { 43 | create_precomputed_table(); 44 | if (argc == 2) { 45 | long x = atoi(argv[1]); 46 | cout << "sizeof(x) = " << sizeof(x) << endl; 47 | cout << "x = " << x << ", reverse x = " << reverse_bits(x) << endl; 48 | cout << reverse_x(x, 63) << endl; 49 | assert(reverse_bits(x) == reverse_x(x, 63)); 50 | } else { 51 | default_random_engine gen((random_device())()); 52 | for (int times = 0; times < 1000; ++times) { 53 | uniform_int_distribution dis(0, numeric_limits::max()); 54 | long x = dis(gen); 55 | cout << "x = " << x << ", reverse x = " << reverse_bits(x) << endl; 56 | assert(reverse_bits(x) == reverse_x(x, 63)); 57 | } 58 | } 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /Reverse_linked_list_iterative.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_REVERSE_LINKED_LIST_ITERATIVE_H_ 4 | #define SOLUTIONS_REVERSE_LINKED_LIST_ITERATIVE_H_ 5 | 6 | #include 7 | 8 | #include "./Linked_list_prototype.h" 9 | 10 | using std::shared_ptr; 11 | 12 | // @include 13 | shared_ptr> reverse_linked_list( 14 | const shared_ptr>& head) { 15 | shared_ptr> prev = nullptr, curr = head; 16 | while (curr) { 17 | shared_ptr> temp = curr->next; 18 | curr->next = prev; 19 | prev = curr; 20 | curr = temp; 21 | } 22 | return prev; 23 | } 24 | // @exclude 25 | #endif // SOLUTIONS_REVERSE_LINKED_LIST_ITERATIVE_H_ 26 | -------------------------------------------------------------------------------- /Reverse_linked_list_iterative_template.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | 6 | #include "./Linked_list_prototype_template.h" 7 | #include "./Reverse_linked_list_iterative_template.h" 8 | 9 | using std::cout; 10 | using std::endl; 11 | using std::make_shared; 12 | using std::shared_ptr; 13 | 14 | template 15 | void print(shared_ptr> head) { 16 | if (head) { 17 | cout << "(" << head->data << ")" << endl; 18 | print(head->next); 19 | } 20 | } 21 | 22 | int main(int argc, char* argv[]) { 23 | shared_ptr> L1 = make_shared>(node_t{1, nullptr}); 24 | shared_ptr> L2 = make_shared>(node_t{2, nullptr}); 25 | L1->next = L2; 26 | shared_ptr> L3 = make_shared>(node_t{3, nullptr}); 27 | L2->next = L3; 28 | 29 | cout << "before reverse" << endl; 30 | print(L1); 31 | shared_ptr> newhead = reverse_linked_list(L1); 32 | cout << endl << "after reverse" << endl; 33 | print(newhead); 34 | newhead = reverse_linked_list(newhead); 35 | cout << endl << "after another reverse" << endl; 36 | print(newhead); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /Reverse_linked_list_recursive.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "./Linked_list_prototype.h" 8 | 9 | using std::cout; 10 | using std::endl; 11 | using std::make_shared; 12 | using std::shared_ptr; 13 | 14 | // @include 15 | shared_ptr> reverse_linked_list( 16 | const shared_ptr>& head) { 17 | if (!head || !head->next) { 18 | return head; 19 | } 20 | 21 | shared_ptr> new_head = reverse_linked_list(head->next); 22 | head->next->next = head; 23 | head->next = nullptr; 24 | return new_head; 25 | } 26 | // @exclude 27 | 28 | void print(shared_ptr> head) { 29 | if (head) { 30 | cout << "(" << head->data << ")" << endl; 31 | print(head->next); 32 | } 33 | } 34 | 35 | int main(int argc, char* argv[]) { 36 | shared_ptr> L1 = 37 | make_shared>(ListNode{1, nullptr}); 38 | shared_ptr> L2 = 39 | make_shared>(ListNode{2, nullptr}); 40 | L1->next = L2; 41 | shared_ptr> L3 = 42 | make_shared>(ListNode{3, nullptr}); 43 | L2->next = L3; 44 | 45 | cout << "before reverse" << endl; 46 | print(L1); 47 | shared_ptr> newhead = reverse_linked_list(L1); 48 | assert(newhead->data == 3 && newhead->next->data == 2 && newhead->next->next->data == 1); 49 | cout << endl << "after reverse" << endl; 50 | print(newhead); 51 | newhead = reverse_linked_list(newhead); 52 | assert(newhead->data == 1 && newhead->next->data == 2 && newhead->next->next->data == 3); 53 | cout << endl << "after another reverse" << endl; 54 | print(newhead); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /Robot_battery.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::max; 14 | using std::min; 15 | using std::numeric_limits; 16 | using std::random_device; 17 | using std::uniform_int_distribution; 18 | using std::vector; 19 | 20 | // @include 21 | int find_battery_capacity(const vector& h) { 22 | int min_height = numeric_limits::max(), capacity = 0; 23 | for (const int &height : h) { 24 | capacity = max(capacity, height - min_height); 25 | min_height = min(min_height, height); 26 | } 27 | return capacity; 28 | } 29 | // @exclude 30 | 31 | // O(n^2) checking answer. 32 | int check_ans(const vector& h) { 33 | int cap = 0; 34 | for (int i = 1; i < h.size(); ++i) { 35 | for (int j = 0; j < i; ++j) { 36 | cap = max(cap, h[i] - h[j]); 37 | } 38 | } 39 | return cap; 40 | } 41 | 42 | int main(int argc, char *argv[]) { 43 | default_random_engine gen((random_device())()); 44 | for (int times = 0; times < 1000; ++times) { 45 | int n; 46 | if (argc == 2) { 47 | n = atoi(argv[1]); 48 | } else { 49 | uniform_int_distribution dis(1, 10000); 50 | n = dis(gen); 51 | } 52 | vector A; 53 | uniform_int_distribution dis(0, numeric_limits::max()); 54 | for (int i = 0; i < n; ++i) { 55 | A.emplace_back(dis(gen)); 56 | } 57 | cout << find_battery_capacity(A) << endl; 58 | assert(check_ans(A) == find_battery_capacity(A)); 59 | } 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /Rotate_array.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "./Rotate_array.h" 10 | #include "./Rotate_array_permutation.h" 11 | 12 | using std::cout; 13 | using std::default_random_engine; 14 | using std::endl; 15 | using std::random_device; 16 | using std::uniform_int_distribution; 17 | using std::vector; 18 | 19 | vector rand_vector(int len) { 20 | default_random_engine gen((random_device())()); 21 | vector ret; 22 | uniform_int_distribution dis(0, len); 23 | while (len--) { 24 | ret.emplace_back(dis(gen)); 25 | } 26 | return ret; 27 | } 28 | 29 | void check_answer(const vector &A, int i, const vector &rotated) { 30 | assert(A.size() == rotated.size()); 31 | for (size_t idx = 0; idx < A.size(); ++idx) { 32 | assert(rotated[(idx + i) % rotated.size()] == A[idx]); 33 | } 34 | } 35 | 36 | int main(int argc, char *argv[]) { 37 | default_random_engine gen((random_device())()); 38 | for (int times = 0; times < 1000; ++times) { 39 | int len; 40 | if (argc == 2) { 41 | len = atoi(argv[1]); 42 | } else { 43 | uniform_int_distribution dis(1, 10000); 44 | len = dis(gen); 45 | } 46 | vector A(rand_vector(len)); 47 | uniform_int_distribution dis(0, len - 1); 48 | int i = dis(gen); 49 | vector B(A); 50 | rotate_array1::rotate_array(i, &B); 51 | check_answer(A, i, B); 52 | vector C(A); 53 | rotate_array2::rotate_array(i, &C); 54 | check_answer(A, i, C); 55 | } 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /Rotate_array.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_ROTATE_ARRAY_H_ 4 | #define SOLUTIONS_ROTATE_ARRAY_H_ 5 | 6 | #include 7 | #include 8 | 9 | using std::vector; 10 | 11 | namespace rotate_array2 { 12 | 13 | // @include 14 | void rotate_array(int i, vector* A) { 15 | i %= A->size(); 16 | reverse(A->begin(), A->end()); 17 | reverse(A->begin(), A->begin() + i); 18 | reverse(A->begin() + i, A->end()); 19 | } 20 | // @exclude 21 | 22 | } // rotate_array2 23 | #endif // SOLUTIONS_ROTATE_ARRAY_H_ 24 | -------------------------------------------------------------------------------- /Rotate_array_permutation.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_ROTATE_ARRAY_PERMUTATION_H_ 4 | #define SOLUTIONS_ROTATE_ARRAY_PERMUTATION_H_ 5 | 6 | #include 7 | #include 8 | 9 | #include "./GCD.h" 10 | 11 | using std::swap; 12 | using std::vector; 13 | 14 | namespace rotate_array1 { 15 | 16 | // @include 17 | void rotate_array(int i, vector* A) { 18 | i %= A->size(); 19 | int cycles = GCD(A->size(), i); // number of cycles in this rotation. 20 | int hops = A->size() / cycles; // number of elements in a cycle. 21 | 22 | for (int c = 0; c < cycles; ++c) { 23 | int temp = (*A)[c]; 24 | for (int j = 1; j < hops; ++j) { 25 | swap((*A)[(c + j * i) % A->size()], temp); 26 | } 27 | (*A)[c] = temp; 28 | } 29 | } 30 | // @exclude 31 | 32 | } // rotate_array1 33 | #endif // SOLUTIONS_ROTATE_ARRAY_PERMUTATION_H_ 34 | -------------------------------------------------------------------------------- /Run_length_compression.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::endl; 12 | using std::string; 13 | using std::stringstream; 14 | 15 | // @include 16 | string decoding(const string &s) { 17 | int count = 0; 18 | string ret; 19 | for (const char &c : s) { 20 | if (isdigit(c)) { 21 | count = count * 10 + c - '0'; 22 | } else { // isalpha. 23 | ret.append(count, c); 24 | count = 0; 25 | } 26 | } 27 | return ret; 28 | } 29 | 30 | string encoding(const string &s) { 31 | int count = 1; 32 | stringstream ss; 33 | for (int i = 1; i < s.size(); ++i) { 34 | if (s[i] == s[i - 1]) { 35 | ++count; 36 | } else { 37 | ss << count << s[i - 1]; 38 | count = 1; 39 | } 40 | } 41 | ss << count << s.back(); 42 | return ss.str(); 43 | } 44 | // @exclude 45 | 46 | int main(int argc, char *argv[]) { 47 | if (argc == 3) { 48 | cout << encoding(argv[1]) << ' ' << decoding(argv[2]) << endl; 49 | } 50 | assert(string("4a1b3c2a") == encoding("aaaabcccaa")); 51 | assert(string("eeeffffee") == decoding("3e4f2e")); 52 | assert(string("aaaaaaaaaaffffee") == decoding("10a4f2e")); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /S2.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | // @include 3 | public class S2 extends SpellCheckService { 4 | static String wLast = null; 5 | static String [] closestToLastWord = null; 6 | 7 | public static void service(ServiceRequest req, ServiceResponse resp) { 8 | String w = req.extractWordToCheckFromRequest(); 9 | String [] result = null; 10 | synchronized (S2.class) { 11 | if (w.equals(wLast)) { 12 | result = Arrays.copyOf(closestToLastWord, closestToLastWord.length); 13 | } 14 | } 15 | if (result == null) { 16 | result = Spell.closestInDictionary(w); 17 | synchronized (S2.class) { 18 | wLast = w; 19 | closestToLastWord = result; 20 | } 21 | } 22 | resp.encodeIntoResponse(result); 23 | } 24 | } 25 | // @exclude 26 | -------------------------------------------------------------------------------- /Search_BST_first_larger_k.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | 5 | #include "./BST_prototype.h" 6 | 7 | using std::unique_ptr; 8 | 9 | // @include 10 | BSTNode* find_first_larger_k_with_k_exist( 11 | const unique_ptr>& T, 12 | int k) { 13 | bool found_k = false; 14 | BSTNode* curr = T.get(), *first = nullptr; 15 | 16 | while (curr) { 17 | if (curr->data == k) { 18 | found_k = true; 19 | curr = curr->right.get(); 20 | } else if (curr->data > k) { 21 | first = curr; 22 | curr = curr->left.get(); 23 | } else { // curr->data < k. 24 | curr = curr->right.get(); 25 | } 26 | } 27 | return found_k ? first : nullptr; 28 | } 29 | // @exclude 30 | 31 | int main(int argc, char* argv[]) { 32 | // 3 33 | // 2 5 34 | // 1 4 7 35 | auto root = unique_ptr>(new BSTNode{3}); 36 | root->left = unique_ptr>(new BSTNode{2}); 37 | root->left->left = unique_ptr>(new BSTNode{1}); 38 | root->right = unique_ptr>(new BSTNode{5}); 39 | root->right->left = unique_ptr>(new BSTNode{4}); 40 | root->right->right = unique_ptr>(new BSTNode{7}); 41 | assert(find_first_larger_k_with_k_exist(root, 1) == root->left.get()); 42 | assert(find_first_larger_k_with_k_exist(root, 5) == root->right->right.get()); 43 | assert(!find_first_larger_k_with_k_exist(root, 6)); 44 | assert(!find_first_larger_k_with_k_exist(root, 7)); 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /Search_BST_for_first_occurrence_iterative.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | 6 | #include "./BST_prototype.h" 7 | 8 | using std::unique_ptr; 9 | 10 | // @include 11 | BSTNode* find_first_equal_k(const unique_ptr>& T, int k) { 12 | BSTNode* first = nullptr, *curr = T.get(); 13 | while (curr) { 14 | if (curr->data < k) { 15 | curr = curr->right.get(); 16 | } else if (curr->data > k) { 17 | curr = curr->left.get(); 18 | } else { // curr->data == k. 19 | // Searches for the leftmost in the left subtree. 20 | first = curr; 21 | curr = curr->left.get(); 22 | } 23 | } 24 | return first; 25 | } 26 | // @exclude 27 | 28 | int main(int argc, char* argv[]) { 29 | // 3 30 | // 2 5 31 | // 1 4 6 32 | auto root = unique_ptr>(new BSTNode{3}); 33 | root->left = unique_ptr>(new BSTNode{2}); 34 | root->left->left = unique_ptr>(new BSTNode{1}); 35 | root->right = unique_ptr>(new BSTNode{5}); 36 | root->right->left = unique_ptr>(new BSTNode{4}); 37 | root->right->right = unique_ptr>(new BSTNode{6}); 38 | assert(!find_first_equal_k(root, 7)); 39 | assert(find_first_equal_k(root, 6)->data == 6); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /Search_BST_for_first_occurrence_recursive.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | 6 | #include "./BST_prototype.h" 7 | 8 | using std::unique_ptr; 9 | 10 | // @include 11 | BSTNode* find_first_equal_k(const unique_ptr>& T, int k) { 12 | if (!T) { 13 | return nullptr; // no match. 14 | } else if (T->data == k) { 15 | // Recursively searches the left subtree for first one == k. 16 | auto* node = find_first_equal_k(T->left, k); 17 | return node ? node : T.get(); 18 | } 19 | // Search left or right tree according to T->data and k. 20 | return find_first_equal_k(T->data < k ? T->right : T->left, k); 21 | } 22 | // @exclude 23 | 24 | int main(int argc, char* argv[]) { 25 | // 3 26 | // 2 6 27 | // 1 4 6 28 | auto root = unique_ptr>(new BSTNode{3}); 29 | root->left = unique_ptr>(new BSTNode{2}); 30 | root->left->left = 31 | unique_ptr>(new BSTNode{1}); 32 | root->right = 33 | unique_ptr>(new BSTNode{6}); 34 | root->right->left = 35 | unique_ptr>(new BSTNode{4}); 36 | root->right->right = 37 | unique_ptr>(new BSTNode{6}); 38 | assert(!find_first_equal_k(root, 7)); 39 | assert(find_first_equal_k(root, 6)->data == 6 && 40 | find_first_equal_k(root, 6)->right->data == 6); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /Search_min_first_BST.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | 6 | #include "./BST_prototype.h" 7 | 8 | using std::unique_ptr; 9 | 10 | // @include 11 | bool search_min_first_BST(const unique_ptr>& T, int k) { 12 | if (!T || T->data > k) { 13 | return false; 14 | } else if (T->data == k) { 15 | return true; 16 | } 17 | 18 | // Searches the right subtree if the smallest key in the right subtree is 19 | // greater than or equal to k. 20 | if (T->right && k >= T->right->data) { 21 | return search_min_first_BST(T->right, k); 22 | } 23 | return search_min_first_BST(T->left, k); 24 | } 25 | // @exclude 26 | 27 | int main(int argc, char* argv[]) { 28 | // A min-first BST 29 | // 1 30 | // 2 4 31 | // 3 5 7 32 | auto root = unique_ptr>(new BSTNode{1}); 33 | root->left = unique_ptr>(new BSTNode{2}); 34 | root->left->left = unique_ptr>(new BSTNode{3}); 35 | root->right = unique_ptr>(new BSTNode{4}); 36 | root->right->left = unique_ptr>(new BSTNode{5}); 37 | root->right->right = unique_ptr>(new BSTNode{7}); 38 | assert(search_min_first_BST(root, 1)); 39 | assert(search_min_first_BST(root, 3)); 40 | assert(search_min_first_BST(root, 5)); 41 | assert(!search_min_first_BST(root, 6)); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /Search_skip_list_iterative_template.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | template 8 | class node_t { 9 | public: 10 | T order; 11 | shared_ptr > next, jump; 12 | }; 13 | 14 | // @include 15 | template 16 | void search_postings_list(const shared_ptr > &L) { 17 | stack > > s; 18 | int order = 0; 19 | s.emplace(L); 20 | while (!s.empty()) { 21 | shared_ptr > curr = s.top(); 22 | s.pop(); 23 | if (curr && curr->order == -1) { 24 | curr->order = order++; 25 | s.emplace(curr->next); 26 | s.emplace(curr->jump); 27 | } 28 | } 29 | } 30 | // @exclude 31 | 32 | int main(int argc, char *argv[]) { 33 | shared_ptr > L = nullptr, curr; 34 | curr = L; 35 | // build a linked list L->1->2->3->4->5->nullptr 36 | for (size_t i = 0; i < 5; ++i) { 37 | shared_ptr > temp = shared_ptr >(new node_t{-1, nullptr, nullptr}); 38 | if (curr) { 39 | curr->next = temp; 40 | curr = temp; 41 | } else { 42 | curr = L = temp; 43 | } 44 | } 45 | L->jump = nullptr; // no jump from 1 46 | L->next->jump = L->next->next->next; // 2's jump points to 4 47 | L->next->next->jump = L; // 3's jump points to 1 48 | L->next->next->next->jump = nullptr; // no jump from 4 49 | L->next->next->next->next->jump = L->next->next->next->next; // 5's jump points to 5 50 | shared_ptr > temp = L; 51 | int order = 0; 52 | search_postings_list(L); 53 | // output the jump-first order, it should be 0, 1, 4, 2, 3 54 | assert(temp->order == 0); 55 | temp = temp->next; 56 | assert(temp->order == 1); 57 | temp = temp->next; 58 | assert(temp->order == 4); 59 | temp = temp->next; 60 | assert(temp->order == 2); 61 | temp = temp->next; 62 | assert(temp->order == 3); 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /SimpleWebServer.java: -------------------------------------------------------------------------------- 1 | // @include 2 | public class SimpleWebServer { 3 | final static int PORT = 8080; 4 | public static void main (String [] args) throws IOException { 5 | ServerSocket serversock = new ServerSocket(PORT); 6 | for (;;) { 7 | Socket sock = serversock.accept(); 8 | ProcessReq(sock); 9 | } 10 | } 11 | } 12 | // @exclude 13 | -------------------------------------------------------------------------------- /Sliding_window.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "./Queue_with_max_using_deque.h" 10 | 11 | using std::cout; 12 | using std::endl; 13 | using std::length_error; 14 | using std::queue; 15 | using std::vector; 16 | 17 | // @include 18 | struct TrafficElement { 19 | bool operator<(const TrafficElement& that) const { 20 | return volume < that.volume; 21 | } 22 | 23 | bool operator==(const TrafficElement& that) const { 24 | return time == that.time && volume == that.volume; 25 | } 26 | 27 | int time, volume; 28 | }; 29 | 30 | void calculate_traffic_volumes(const vector& A, int w) { 31 | Queue Q; 32 | for (int i = 0; i < A.size(); ++i) { 33 | Q.enqueue(A[i]); 34 | while (A[i].time - Q.head().time > w) { 35 | Q.dequeue(); 36 | } 37 | cout << "Max after inserting " << i << " is " << Q.max().volume << endl; 38 | } 39 | } 40 | // @exclude 41 | 42 | int main(int argc, char* argv[]) { 43 | int w = 3; 44 | // It should output 0, 1, 3, 3, 3, 3, 2, 2. 45 | vector A = {TrafficElement{0, 0}, TrafficElement{1, 1}, 46 | TrafficElement{2, 3}, TrafficElement{3, 1}, 47 | TrafficElement{4, 0}, TrafficElement{5, 2}, 48 | TrafficElement{6, 2}, TrafficElement{7, 2}}; 49 | calculate_traffic_volumes(A, w); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /Smallest_subarray_covering_set.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_SMALLEST_SUBARRAY_COVERING_SET_H_ 4 | #define SOLUTIONS_SMALLEST_SUBARRAY_COVERING_SET_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using std::pair; 13 | using std::string; 14 | using std::unordered_map; 15 | using std::unordered_set; 16 | using std::vector; 17 | 18 | // @include 19 | pair find_smallest_subarray_covering_subset( 20 | const vector &A, const vector &Q) { 21 | unordered_set dict(Q.cbegin(), Q.cend()); 22 | unordered_map count_Q; 23 | int l = 0, r = 0; 24 | pair res(-1, -1); 25 | while (r < static_cast(A.size())) { 26 | // Keep moving r until it reaches end or count_Q has |Q| items. 27 | while (r < static_cast(A.size()) && count_Q.size() < Q.size()) { 28 | if (dict.find(A[r]) != dict.end()) { 29 | ++count_Q[A[r]]; 30 | } 31 | ++r; 32 | } 33 | 34 | if (count_Q.size() == Q.size() && // found |Q| keywords. 35 | ((res.first == -1 && res.second == -1) || 36 | r - 1 - l < res.second - res.first)) { 37 | res = {l, r - 1}; 38 | } 39 | 40 | // Keep moving l until it reaches end or count_Q has less |Q| items. 41 | while (l < r && count_Q.size() == Q.size()) { 42 | if (dict.find(A[l]) != dict.end()) { 43 | auto it = count_Q.find(A[l]); 44 | if (--(it->second) == 0) { 45 | count_Q.erase(it); 46 | if ((res.first == -1 && res.second == -1) || 47 | r - 1 - l < res.second - res.first) { 48 | res = {l, r - 1}; 49 | } 50 | } 51 | } 52 | ++l; 53 | } 54 | } 55 | return res; 56 | } 57 | // @exclude 58 | #endif // SOLUTIONS_SMALLEST_SUBARRAY_COVERING_SET_H_ 59 | -------------------------------------------------------------------------------- /Smallest_subarray_covering_set_stream.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_SMALLEST_SUBARRAY_COVERING_SET_STREAM_H_ 4 | #define SOLUTIONS_SMALLEST_SUBARRAY_COVERING_SET_STREAM_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using std::istringstream; 14 | using std::list; 15 | using std::pair; 16 | using std::unordered_map; 17 | 18 | // @include 19 | pair find_smallest_subarray_covering_subset( 20 | istringstream* sin, const vector &Q) { 21 | list loc; // tracks the last occurrence (index) of each string in Q. 22 | unordered_map::iterator> dict; 23 | for (const string& s : Q) { 24 | dict.emplace(s, loc.end()); 25 | } 26 | 27 | pair res(-1, -1); 28 | int idx = 0; 29 | string s; 30 | while (*sin >> s) { 31 | auto it = dict.find(s); 32 | if (it != dict.end()) { // s is in Q. 33 | if (it->second != loc.end()) { 34 | loc.erase(it->second); 35 | } 36 | loc.emplace_back(idx); 37 | it->second = --loc.end(); 38 | } 39 | 40 | if (loc.size() == Q.size() && // found |Q| keywords. 41 | ((res.first == -1 && res.second == -1) || 42 | idx - loc.front() < res.second - res.first)) { 43 | res = {loc.front(), idx}; 44 | } 45 | ++idx; 46 | } 47 | return res; 48 | } 49 | // @exclude 50 | #endif // SOLUTIONS_SMALLEST_SUBARRAY_COVERING_SET_STREAM_H_ 51 | -------------------------------------------------------------------------------- /Spiral_matrix.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::array; 9 | using std::cout; 10 | using std::default_random_engine; 11 | using std::endl; 12 | using std::random_device; 13 | using std::uniform_int_distribution; 14 | using std::vector; 15 | 16 | // @include 17 | void print_matrix_in_spiral_order(vector> A) { 18 | const array, 4> shift = {{{{0, 1}}, {{1, 0}}, 19 | {{0, -1}}, {{-1, 0}}}}; 20 | int dir = 0, x = 0, y = 0; 21 | 22 | for (int i = 0; i < A.size() * A.size(); ++i) { 23 | cout << A[x][y] << ' '; 24 | A[x][y] = 0; 25 | int nx = x + shift[dir][0], ny = y + shift[dir][1]; 26 | if (nx < 0 || nx >= A.size() || ny < 0 || ny >= A.size() || 27 | A[nx][ny] == 0) { 28 | dir = (dir + 1) & 3; 29 | nx = x + shift[dir][0], ny = y + shift[dir][1]; 30 | } 31 | x = nx, y = ny; 32 | } 33 | } 34 | // @exclude 35 | 36 | int main(int argc, char *argv[]) { 37 | default_random_engine gen((random_device())()); 38 | int N; 39 | if (argc == 2) { 40 | N = atoi(argv[1]); 41 | } else { 42 | uniform_int_distribution dis(1, 50); 43 | N = dis(gen); 44 | } 45 | vector> A(N, vector(N)); 46 | int x = 1; 47 | for (size_t i = 0; i < N; ++i) { 48 | for (size_t j = 0; j < N; ++j) { 49 | A[i][j] = x++; 50 | } 51 | } 52 | print_matrix_in_spiral_order(A); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /Spiral_matrix_clockwise.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::default_random_engine; 10 | using std::endl; 11 | using std::random_device; 12 | using std::uniform_int_distribution; 13 | using std::vector; 14 | 15 | void print_matrix_clockwise(const vector> &A, int offset); 16 | 17 | // @include 18 | void print_matrix_in_spiral_order(const vector> &A) { 19 | for (int offset = 0; offset < ceil(0.5 * A.size()); ++offset) { 20 | print_matrix_clockwise(A, offset); 21 | } 22 | } 23 | 24 | void print_matrix_clockwise(const vector> &A, int offset) { 25 | if (offset == A.size() - offset - 1) { // for matrix with odd size. 26 | cout << A[offset][offset]; 27 | } 28 | 29 | for (int j = offset; j < A.size() - offset - 1; ++j) { 30 | cout << A[offset][j] << ' '; 31 | } 32 | for (int i = offset; i < A.size() - offset - 1; ++i) { 33 | cout << A[i][A.size() - offset - 1] << ' '; 34 | } 35 | for (int j = A.size() - offset - 1; j > offset; --j) { 36 | cout << A[A.size() - offset - 1][j] << ' '; 37 | } 38 | for (int i = A.size() - offset - 1; i > offset; --i) { 39 | cout << A[i][offset] << ' '; 40 | } 41 | } 42 | // @exclude 43 | 44 | int main(int argc, char *argv[]) { 45 | default_random_engine gen((random_device())()); 46 | int N; 47 | if (argc == 2) { 48 | N = atoi(argv[1]); 49 | } else { 50 | uniform_int_distribution dis(1, 50); 51 | N = dis(gen); 52 | } 53 | vector> A(N, vector(N)); 54 | int x = 1; 55 | for (size_t i = 0; i < N; ++i) { 56 | for (size_t j = 0; j < N; ++j) { 57 | A[i][j] = x++; 58 | } 59 | } 60 | print_matrix_in_spiral_order(A); 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /Spreadsheet_encoding.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::default_random_engine; 10 | using std::endl; 11 | using std::random_device; 12 | using std::string; 13 | using std::uniform_int_distribution; 14 | 15 | string rand_string(int len) { 16 | default_random_engine gen((random_device())()); 17 | string ret; 18 | uniform_int_distribution dis('A', 'Z'); 19 | while (len--) { 20 | ret.push_back(dis(gen)); 21 | } 22 | return ret; 23 | } 24 | 25 | // @include 26 | int ssDecodeColID(const string& col) { 27 | int ret = 0; 28 | for (const char& c : col) { 29 | ret = ret * 26 + c - 'A' + 1; 30 | } 31 | return ret; 32 | } 33 | // @exclude 34 | 35 | void simple_test() { 36 | assert(1 == ssDecodeColID("A")); 37 | assert(27 == ssDecodeColID("AA")); 38 | } 39 | 40 | int main(int argc, char* argv[]) { 41 | default_random_engine gen((random_device())()); 42 | if (argc == 2) { 43 | cout << argv[1] << " " << ssDecodeColID(argv[1]) << endl; 44 | } else { 45 | uniform_int_distribution len_dis(1, 5); 46 | string s(rand_string(len_dis(gen))); 47 | cout << s << " " << ssDecodeColID(s) << endl; 48 | } 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /StackSort.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | 3 | public class StackSort { 4 | 5 | // @include 6 | static Integer pop(LinkedList stack) { 7 | return stack.removeLast(); 8 | } 9 | 10 | static void push(LinkedList stack, Integer e) { 11 | stack.addLast(e); 12 | return; 13 | } 14 | 15 | static boolean isEmpty(LinkedList stack) { 16 | return (stack.isEmpty() == true); 17 | } 18 | 19 | static Integer peek(LinkedList stack) { 20 | return stack.getLast(); 21 | } 22 | 23 | static void insert(LinkedList stack, Integer e) { 24 | if (!isEmpty(stack) && peek(stack) < e) { 25 | Integer f = pop(stack); 26 | insert(stack, e); 27 | push(stack, f); 28 | } else { 29 | push(stack, e); 30 | } 31 | } 32 | 33 | static void sort(LinkedList stack) { 34 | if (!isEmpty(stack)) { 35 | Integer e = pop(stack); 36 | sort(stack); 37 | insert(stack, e); 38 | } 39 | } 40 | // @exclude 41 | 42 | static void print(LinkedList stack ) { 43 | for ( Integer e : stack ) { 44 | System.out.print("\t" + e ); 45 | } 46 | System.out.println(); 47 | } 48 | 49 | public static void main( String [] args ) { 50 | LinkedList stack = new LinkedList(); 51 | stack.addLast(1); 52 | stack.addLast(3); 53 | stack.addLast(0); 54 | stack.addLast(3); 55 | stack.addLast(1); 56 | stack.addLast(7); 57 | stack.addLast(-1); 58 | System.out.println("Before sorting:"); 59 | print(stack); 60 | System.out.println("After sorting:"); 61 | sort(stack); 62 | print(stack); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Stack_sorting.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::numeric_limits; 14 | using std::random_device; 15 | using std::stack; 16 | using std::uniform_int_distribution; 17 | using std::vector; 18 | 19 | void insert(int e, stack* S); 20 | 21 | // @include 22 | void sort(stack* S) { 23 | if (!S->empty()) { 24 | int e = S->top(); 25 | S->pop(); 26 | sort(S); 27 | insert(e, S); 28 | } 29 | } 30 | 31 | void insert(int e, stack* S) { 32 | if (S->empty() || S->top() <= e) { 33 | S->push(e); 34 | } else { 35 | int f = S->top(); 36 | S->pop(); 37 | insert(e, S); 38 | S->push(f); 39 | } 40 | } 41 | // @exclude 42 | 43 | int main(int argc, char* argv[]) { 44 | default_random_engine gen((random_device())()); 45 | for (int times = 0; times < 1000; ++times) { 46 | int n; 47 | if (argc == 2) { 48 | n = atoi(argv[1]); 49 | } else { 50 | uniform_int_distribution dis(1, 10000); 51 | n = dis(gen); 52 | } 53 | stack S; 54 | uniform_int_distribution dis(0, 999999); 55 | for (int i = 0; i < n; ++i) { 56 | S.push(dis(gen)); 57 | } 58 | sort(&S); 59 | int pre = numeric_limits::max(); 60 | while (!S.empty()) { 61 | assert(pre >= S.top()); 62 | cout << S.top() << endl; 63 | pre = S.top(); 64 | S.pop(); 65 | } 66 | } 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /Stack_with_max.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_STACK_WITH_MAX_H_ 4 | #define SOLUTIONS_STACK_WITH_MAX_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using std::length_error; 12 | using std::pair; 13 | using std::stack; 14 | 15 | // @include 16 | class Stack { 17 | public: 18 | bool empty() const { return s_.empty(); } 19 | 20 | int max() const { 21 | if (!empty()) { 22 | return s_.top().second; 23 | } 24 | throw length_error("empty stack"); 25 | } 26 | 27 | int pop() { 28 | if (empty()) { 29 | throw length_error("empty stack"); 30 | } 31 | int ret = s_.top().first; 32 | s_.pop(); 33 | return ret; 34 | } 35 | 36 | void push(int x) { 37 | s_.emplace(x, std::max(x, empty() ? x : s_.top().second)); 38 | } 39 | 40 | private: 41 | stack> s_; 42 | }; 43 | // @exclude 44 | #endif // SOLUTIONS_STACK_WITH_MAX_H_ 45 | -------------------------------------------------------------------------------- /Stack_with_max_template.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "./Stack_with_max_template.h" 8 | 9 | using std::cout; 10 | using std::endl; 11 | using std::exception; 12 | 13 | int main(int argc, char* argv[]) { 14 | Stack s; 15 | s.push(1); 16 | s.push(2); 17 | assert(s.max() == 2); 18 | cout << s.max() << endl; // 2 19 | cout << s.pop() << endl; // 2 20 | assert(s.max() == 1); 21 | cout << s.max() << endl; // 1 22 | s.push(3); 23 | s.push(2); 24 | assert(s.max() == 3); 25 | cout << s.max() << endl; // 3 26 | s.pop(); 27 | assert(s.max() == 3); 28 | cout << s.max() << endl; // 3 29 | s.pop(); 30 | assert(s.max() == 1); 31 | cout << s.max() << endl; // 1 32 | s.pop(); 33 | try { 34 | s.max(); 35 | s.pop(); 36 | s.pop(); 37 | s.pop(); 38 | s.pop(); 39 | } 40 | catch (const exception& e) { 41 | cout << e.what() << endl; 42 | } 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /StringInMatrix.java: -------------------------------------------------------------------------------- 1 | import java.util.Set; 2 | import java.util.HashSet; 3 | 4 | public class StringInMatrix { 5 | 6 | static int[][] A = { {1,2,3,4}, {4,5,6,5}, {7,8,9,10}, {10,11,12,13} }; 7 | 8 | static int[] searchString = {13,12,11,10,7,4,1}; 9 | 10 | // @include 11 | static Set cache = new HashSet(); 12 | 13 | public static boolean matchHelper(int [][] A, int [] S, int i, int j, int k) { 14 | if (S.length == k) { 15 | return true; 16 | } 17 | 18 | if (cache.contains(new Integer[] {i, j, k}) || i < 0 || j < 0 || 19 | i >= A.length || j >= A[i].length || A[i][j] != S[k]) { 20 | return false; 21 | } 22 | 23 | if (matchHelper(A, S, i - 1, j, k + 1) || matchHelper(A, S, i + 1, j, k + 1) || 24 | matchHelper(A, S, i, j - 1, k + 1) || matchHelper(A, S, i, j + 1, k + 1)) { 25 | System.out.println("A[" + i + "," + j + "] = " + A[i][j]); 26 | return true; 27 | } 28 | cache.add(new Integer[] {i, j, k}); 29 | return false; 30 | } 31 | 32 | public static boolean match(int [][] A, int [] S) { 33 | for (int i = 0; i < A.length; ++i) { 34 | for (int j = 0; j < A[i].length; ++j) { 35 | if (matchHelper(A, S, i, j, 0)) { 36 | return true; 37 | } 38 | } 39 | } 40 | return false; 41 | } 42 | // @exclude 43 | 44 | public static void main(String [] args) { 45 | boolean success = false; 46 | success = match(A, searchString); 47 | if ( !success ) { 48 | System.out.println("There is no occurrence of the target array"); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /String_matching_wildcard.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | // @include 8 | bool is_match(const string &s, const string &m) { 9 | if (m.empty()) { 10 | return s.empty(); 11 | } 12 | 13 | if (m.size() == 1) { 14 | return s.size() == 1 && (s.front() == m.front() || m.front() == '.'); 15 | } 16 | 17 | if (m[1] == '*') { 18 | for (int i = 0; i < s.size() && (s[i] == m.front() || m.front() == '.'); ++i) { 19 | if (is_match(s.substr(i + 1), m.substr(2))) { 20 | return true; 21 | } 22 | } 23 | return is_match(s, m.substr(2)); 24 | } 25 | 26 | return !s.empty() && (s.front() == m.front() || m.front() == '.') && 27 | is_match(s.substr(1), m.substr(1)); 28 | } 29 | // @exclude 30 | 31 | int main(int argc, char *argv[]) { 32 | if (argc == 3) { 33 | // Remember to put '\' before any special metacharacter you input 34 | cout << boolalpha << is_match(argv[1], argv[2]) << endl; 35 | } 36 | assert(true == is_match("c", ".")); 37 | assert(true == is_match("ac", ".c")); 38 | assert(true == is_match("c", "c")); 39 | assert(false == is_match("cc", "c")); 40 | assert(true == is_match("c", "c*")); 41 | assert(true == is_match("ac", ".*c")); 42 | assert(true == is_match("acac", ".*a.*")); 43 | assert(true == is_match("ac", ".*a.*c")); 44 | assert(true == is_match("acac", ".*a.*c")); 45 | assert(true == is_match("", ".*")); 46 | assert(true == is_match("a", ".*")); 47 | assert(true == is_match("cagt", ".*c.*a.*g.*t")); 48 | assert(true == is_match("cagt", "c*ca*ag*gt*")); 49 | assert(true == is_match("cagtt", "c*ca*ag*gt*tt")); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /Tail_coin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | 6 | using std::cout; 7 | using std::default_random_engine; 8 | using std::endl; 9 | using std::random_device; 10 | using std::uniform_int_distribution; 11 | using std::uniform_real_distribution; 12 | 13 | // @include 14 | // Return the number of failed trials. 15 | int simulate_biased_coin(int n, int trials) { 16 | default_random_engine gen((random_device())()); // random num generator. 17 | // Generate random double in [0.0, 1.0]. 18 | uniform_real_distribution dis(0.0, 1.0); 19 | const double kBias = 0.4; 20 | int fails = 0; 21 | for (int i = 0; i < trials; ++i) { 22 | int biased_num = 0; 23 | for (int j = 0; j < n; ++j) { 24 | biased_num += (dis(gen) >= kBias); 25 | } 26 | 27 | if (biased_num < (n >> 1)) { 28 | ++fails; 29 | } 30 | } 31 | return fails; 32 | } 33 | // @exclude 34 | 35 | int main(int argc, char* argv[]) { 36 | int n, trials; 37 | default_random_engine gen((random_device())()); 38 | if (argc == 3) { 39 | n = atoi(argv[1]); 40 | trials = atoi(argv[2]); 41 | } else { 42 | uniform_int_distribution dis(1, 1000); 43 | n = dis(gen); 44 | trials = dis(gen); 45 | } 46 | int fails = simulate_biased_coin(n, trials); 47 | cout << "fails = " << fails << endl; 48 | cout << "ratio = " << static_cast(fails) / trials << endl; 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /TaskExecutionWebServer.java: -------------------------------------------------------------------------------- 1 | // @exclude 2 | import java.util.concurrent.*; 3 | import java.io.*; 4 | import java.net.*; 5 | // @include 6 | class TaskExecutionWebServer { 7 | private static final int NTHREADS = 100; 8 | private static final int SERVERPORT = 8080; 9 | private static final Executor exec = Executors.newFixedThreadPool(NTHREADS); 10 | 11 | public static void main(String[] args) throws IOException { 12 | ServerSocket serversocket = new ServerSocket(SERVERPORT); 13 | while (true) { 14 | final Socket connection = serversocket.accept(); 15 | Runnable task = new Runnable() { 16 | public void run() { 17 | Worker.handleRequest(connection); 18 | } 19 | }; 20 | exec.execute(task); 21 | } 22 | } 23 | } 24 | // @exclude 25 | 26 | class Worker { 27 | static void handleRequest(Socket connection) { 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Task_assignment.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::numeric_limits; 14 | using std::pair; 15 | using std::random_device; 16 | using std::uniform_int_distribution; 17 | using std::vector; 18 | 19 | // @include 20 | vector> task_assignment(vector A) { 21 | sort(A.begin(), A.end()); 22 | vector> P; 23 | for (int i = 0, j = A.size() - 1; i < j; ++i, --j) { 24 | P.emplace_back(A[i], A[j]); 25 | } 26 | return P; 27 | } 28 | // @exclude 29 | 30 | int main(int argc, char* argv[]) { 31 | default_random_engine gen((random_device())()); 32 | int n; 33 | if (argc == 2) { 34 | n = atoi(argv[1]); 35 | } else { 36 | uniform_int_distribution dis(1, 10000); 37 | n = dis(gen); 38 | } 39 | vector A; 40 | for (size_t i = 0; i < n; ++i) { 41 | uniform_int_distribution dis(0, 999); 42 | A.emplace_back(dis(gen)); 43 | } 44 | vector> P(task_assignment(A)); 45 | int max = numeric_limits::min(); 46 | for (size_t i = 0; i < P.size(); ++i) { 47 | if (P[i].first + P[i].second > max) { 48 | max = P[i].first + P[i].second; 49 | } 50 | } 51 | cout << max << endl; 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /Team_photo_1.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using std::vector; 8 | 9 | // @include 10 | struct Player { 11 | bool operator<(const Player& that) const { return height < that.height; } 12 | 13 | int height; 14 | }; 15 | 16 | class Team { 17 | public: 18 | explicit Team(const vector& height) { 19 | for (const int& h : height) { 20 | members_.emplace_back(Player{h}); 21 | } 22 | } 23 | 24 | bool operator<(const Team& that) const { 25 | vector this_sorted(SortHeightMembers()); 26 | vector that_sorted(that.SortHeightMembers()); 27 | for (int i = 0; i < this_sorted.size() && i < that_sorted.size(); ++i) { 28 | if (!(this_sorted[i] < that_sorted[i])) { 29 | return false; 30 | } 31 | } 32 | return true; 33 | } 34 | 35 | private: 36 | vector SortHeightMembers() const { 37 | vector sorted_members(members_); 38 | sort(sorted_members.begin(), sorted_members.end()); 39 | return sorted_members; 40 | } 41 | 42 | vector members_; 43 | }; 44 | // @exclude 45 | 46 | int main(int argc, char* argv[]) { 47 | vector height(3); 48 | height[0] = 1, height[1] = 5, height[2] = 4; 49 | Team t1(height); 50 | height[0] = 2, height[2] = 3, height[2] = 4; 51 | Team t2(height); 52 | assert(!(t1 < t2) && !(t2 < t1)); 53 | height[0] = 0, height[1] = 3, height[2] = 2; 54 | Team t3(height); 55 | assert(t3 < t1 && !(t1 < t3) && t3 < t2 && !(t1 < t2)); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /ThreadPerTaskWebserver.java: -------------------------------------------------------------------------------- 1 | // @exclude 2 | import java.net.*; 3 | import java.io.*; 4 | // @include 5 | class ThreadPerTaskWebServer { 6 | private static final int SERVERPORT = 8080; 7 | public static void main(String [] args) throws IOException { 8 | final ServerSocket serversocket = new ServerSocket(SERVERPORT); 9 | while (true) { 10 | final Socket connection = serversocket.accept(); 11 | Runnable task = new Runnable() { 12 | public void run() { 13 | Worker.handleRequest(connection); 14 | } 15 | }; 16 | new Thread(task).start(); 17 | } 18 | } 19 | } 20 | // @exclude 21 | -------------------------------------------------------------------------------- /Ties_election.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::endl; 10 | using std::vector; 11 | 12 | // @include 13 | // V contains the number of votes for each state. 14 | // This function returns the total number of ways to tie. 15 | long ties_election(const vector& V) { 16 | int total_votes = accumulate(V.cbegin(), V.cend(), 0); 17 | 18 | // No way to tie if the total number of votes is odd. 19 | if (total_votes & 1) { 20 | return 0; 21 | } 22 | 23 | vector> table(V.size() + 1, vector(total_votes + 1, 0)); 24 | table[0][0] = 1; // base condition: 1 way to reach 0. 25 | for (int i = 0; i < V.size(); ++i) { 26 | for (int j = 0; j <= total_votes; ++j) { 27 | table[i + 1][j] = table[i][j] + (j >= V[i] ? table[i][j - V[i]] : 0); 28 | } 29 | } 30 | return table[V.size()][total_votes >> 1]; 31 | } 32 | // @exclude 33 | 34 | void simple_test() { 35 | vector votes = {4, 5, 2, 7}; 36 | assert(2 == ties_election(votes)); 37 | } 38 | 39 | int main(int argc, char* argv[]) { 40 | simple_test(); 41 | vector votes = {9, 3, 11, 6, 55, 9, 7, 3, 29, 16, 4, 4, 20, 42 | 11, 6, 6, 8, 8, 4, 10, 11, 16, 10, 6, 10, 3, 43 | 5, 6, 4, 14, 5, 29, 15, 3, 18, 7, 7, 20, 4, 44 | 9, 3, 11, 38, 6, 3, 13, 12, 5, 10, 3, 3}; 45 | cout << ties_election(votes) << endl; 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /Uniform_random_number_generation.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::default_random_engine; 10 | using std::endl; 11 | using std::random_device; 12 | using std::uniform_int_distribution; 13 | 14 | int zero_one_random() { 15 | default_random_engine gen((random_device())()); 16 | uniform_int_distribution dis(0, 1); 17 | return dis(gen); 18 | } 19 | 20 | // @include 21 | int uniform_random_a_b(int a, int b) { 22 | int t = b - a + 1, res; 23 | do { 24 | res = 0; 25 | for (int i = 0; (1 << i) < t; ++i) { 26 | // zero_one_random() is the system-provided random number generator. 27 | res = (res << 1) | zero_one_random(); 28 | } 29 | } while (res >= t); 30 | return res + a; 31 | } 32 | // @exclude 33 | 34 | int main(int argc, char* argv[]) { 35 | default_random_engine gen((random_device())()); 36 | for (int times = 0; times < 1000; ++times) { 37 | int a, b; 38 | if (argc == 3) { 39 | a = atoi(argv[1]), b = atoi(argv[2]); 40 | } else { 41 | uniform_int_distribution a_dis(0, 99); 42 | a = a_dis(gen); 43 | uniform_int_distribution b_dis(a + 1, a + 100); 44 | b = b_dis(gen); 45 | } 46 | int x = uniform_random_a_b(a, b); 47 | cout << "a = " << a << " b = " << b << endl; 48 | cout << "random result = " << x << endl; 49 | assert(x >= a && x <= b); 50 | } 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /add-binary.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::default_random_engine; 11 | using std::endl; 12 | using std::random_device; 13 | using std::string; 14 | using std::uniform_int_distribution; 15 | 16 | // @include 17 | string add_binary(string a, string b) { 18 | string sum; 19 | reverse(a.begin(), a.end()), reverse(b.begin(), b.end()); 20 | bool have_carry = false; 21 | for (size_t i = 0; i < a.size() || i < b.size(); ++i) { 22 | int val_a = i < a.size() ? a[i] - '0' : 0, val_b = i < b.size() ? b[i] - '0' : 0; 23 | int val = val_a + val_b + have_carry; 24 | have_carry = val >= 2; 25 | sum += (val == 1 || val == 3) ? '1' : '0'; 26 | } 27 | if (have_carry) { 28 | sum += '1'; 29 | } 30 | reverse(sum.begin(), sum.end()); 31 | return sum; 32 | } 33 | // @exclude 34 | 35 | int main(int argc, char** argv) { 36 | if (argc == 3) { 37 | cout << "a = " << argv[1] << ", b = " << argv[2] << endl; 38 | cout << add_binary(argv[1], argv[2]) << endl; 39 | } 40 | assert(!add_binary("0", "0").compare("0")); 41 | assert(!add_binary("11", "1").compare("100")); 42 | assert(!add_binary("1", "0").compare("1")); 43 | assert(!add_binary("111", "1").compare("1000")); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /array-reference-copy.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::length_error; 14 | using std::random_device; 15 | using std::swap; 16 | using std::uniform_int_distribution; 17 | using std::vector; 18 | 19 | /* 20 | void CannotModify(const vector& A) { 21 | A[0] = 1; 22 | } 23 | */ 24 | 25 | // Not recommended. 26 | void Modify(vector& A) { 27 | A[0] = 5; 28 | } 29 | 30 | // Recommended. 31 | void AnotherModify(vector* A) { 32 | auto& B = *A; 33 | B[0] = 4; 34 | } 35 | 36 | // Copy. 37 | void Copy(vector A) { 38 | A[0] = 10; 39 | } 40 | 41 | void TwoLevelModify(const vector>& B) { 42 | auto& C = B; 43 | C[0][0] = 3; 44 | } 45 | 46 | int main(void) { 47 | vector A = {1, 3, 5, 7, 10}; 48 | //CannotModify(A); 49 | Modify(A); 50 | cout << "A[0] = " << A[0] << endl; 51 | AnotherModify(&A); 52 | cout << "A[0] = " << A[0] << endl; 53 | Copy(A); 54 | cout << "A[0] = " << A[0] << endl; 55 | cout << "A[0] = " << A.at(0) << endl; 56 | cout << "A[10] = " << A[10] << endl; 57 | //cout << "A[10] = " << A.at(10) << endl; 58 | 59 | vector> B = {{2, 3}, {4, 5}}; 60 | cout << "B[0][0] = " << B[0][0] << endl; 61 | TwoLevelModify(B); 62 | cout << "B[0][0] = " << B[0][0] << endl; 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /climb-stairs.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::default_random_engine; 11 | using std::endl; 12 | using std::random_device; 13 | using std::stoi; 14 | using std::uniform_int_distribution; 15 | 16 | // @include 17 | int climb_stairs(int n) { 18 | if (n <= 1) { 19 | return 1; 20 | } 21 | 22 | int pre_2 = 1, pre_1 = 1; 23 | for (int i = 2; i <= n; ++i) { 24 | int temp = pre_2 + pre_1; 25 | pre_2 = pre_1; 26 | pre_1 = temp; 27 | } 28 | return pre_1; 29 | } 30 | // @exclude 31 | 32 | int main(int argc, char** argv) { 33 | default_random_engine gen((random_device())()); 34 | int n; 35 | if (argc == 2) { 36 | n = stoi(argv[1]); 37 | } else { 38 | uniform_int_distribution dis(1, 100); 39 | n = dis(gen); 40 | } 41 | cout << climb_stairs(n) << endl; 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /combinations.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::random_device; 14 | using std::stoi; 15 | using std::uniform_int_distribution; 16 | using std::vector; 17 | 18 | void combinations_helper(int n, int k, int start, vector* ans, 19 | vector>* res); 20 | 21 | // @include 22 | vector> combinations(int n, int k) { 23 | vector> res; 24 | vector ans; 25 | combinations_helper(n, k, 0, &ans, &res); 26 | return res; 27 | } 28 | 29 | void combinations_helper(int n, int k, int start, vector* ans, 30 | vector>* res) { 31 | if (ans->size() == k) { 32 | res->emplace_back(*ans); 33 | return; 34 | } 35 | 36 | if (k - ans->size() <= n - (start + 1)) { 37 | combinations_helper(n, k, start + 1, ans, res); 38 | } 39 | ans->emplace_back(start + 1); 40 | combinations_helper(n, k, start + 1, ans, res); 41 | ans->pop_back(); 42 | } 43 | // @exclude 44 | 45 | int main(int argc, char** argv) { 46 | default_random_engine gen((random_device())()); 47 | int n, k; 48 | if (argc == 3) { 49 | n = stoi(argv[1]), k = stoi(argv[2]); 50 | } else { 51 | uniform_int_distribution n_dis(1, 10); 52 | n = n_dis(gen); 53 | uniform_int_distribution k_dis(0, n); 54 | k = k_dis(gen); 55 | } 56 | auto res = combinations(n, k); 57 | cout << "n = " << n << ", k = " << k << endl; 58 | for (const auto& vec : res) { 59 | for (int a : vec) { 60 | cout << a << " "; 61 | } 62 | cout << endl; 63 | } 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /container-with-most-water.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::max; 14 | using std::min; 15 | using std::random_device; 16 | using std::stoul; 17 | using std::uniform_int_distribution; 18 | using std::vector; 19 | 20 | // @include 21 | int get_max_area(const vector& heights) { 22 | size_t i = 0, j = heights.size() - 1; 23 | int res = 0; 24 | while (i < j) { 25 | res = max(res, min(heights[i], heights[j]) * static_cast(j - i)); 26 | if (heights[i] > heights[j]) { 27 | --j; 28 | } else if (heights[i] < heights[j]) { 29 | ++i; 30 | } else { // heights[i] == heights[j]. 31 | ++i, --j; 32 | } 33 | } 34 | return res; 35 | } 36 | // @exclude 37 | 38 | // O(n^2) checking answer. 39 | int check_ans(const vector& heights) { 40 | int res = 0; 41 | for (size_t i = 0; i < heights.size(); ++i) { 42 | for (size_t j = i + 1; j < heights.size(); ++j) { 43 | res = max(res, min(heights[i], heights[j]) * static_cast(j - i)); 44 | } 45 | } 46 | return res; 47 | } 48 | 49 | int main(int argc, char** argv) { 50 | default_random_engine gen((random_device())()); 51 | for (int times = 0; times < 1000; ++times) { 52 | size_t n; 53 | if (argc == 2) { 54 | n = stoul(argv[1]); 55 | } else { 56 | uniform_int_distribution dis(2, 10000); 57 | n = dis(gen); 58 | } 59 | uniform_int_distribution dis_1000(1, 1000); 60 | vector heights; 61 | generate_n(back_inserter(heights), n, [&] { return dis_1000(gen); }); 62 | cout << get_max_area(heights) << endl; 63 | assert(get_max_area(heights) == check_ans(heights)); 64 | } 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /cyclic-right-shift.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "./Linked_list_prototype.h" 8 | 9 | using std::cout; 10 | using std::endl; 11 | using std::make_shared; 12 | using std::shared_ptr; 13 | 14 | // @include 15 | shared_ptr> cyclically_right_shift_list( 16 | shared_ptr> L, int k) { 17 | if (!L) { 18 | return L; 19 | } 20 | 21 | // Computes n, the length of L, and stores the tails of the list. 22 | auto tail = L; 23 | int n = 1; 24 | while (tail->next) { 25 | ++n, tail = tail->next; 26 | } 27 | // We only need to rotate right k % n nodes. 28 | k %= n; 29 | 30 | // No need to rotate if k == 0. 31 | if (!k) { 32 | return L; 33 | } 34 | 35 | tail->next = L; // makes a cycle by connecting the tail to the head. 36 | // Advances (n - k) steps. 37 | int step = n - k; 38 | shared_ptr> prev = nullptr, curr = L; 39 | while (step--) { 40 | prev = curr; 41 | curr = curr->next; 42 | } 43 | prev->next = nullptr; // prev is the new tail. 44 | return curr; 45 | } 46 | // @exclude 47 | 48 | int main(int argc, char* argv[]) { 49 | shared_ptr> L; 50 | L = make_shared>(ListNode{ 51 | 1, make_shared>(ListNode{ 52 | 2, make_shared>(ListNode{3, nullptr})})}); 53 | auto res = cyclically_right_shift_list(L, 2); 54 | assert(res->data == 2 && res->next->data == 3 && res->next->next->data == 1 && !res->next->next->next); 55 | while (res) { 56 | cout << res->data << endl; 57 | res = res->next; 58 | } 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /distinct-sorted-list.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "./Linked_list_prototype.h" 8 | 9 | using std::cout; 10 | using std::endl; 11 | using std::make_shared; 12 | using std::shared_ptr; 13 | 14 | // @include 15 | shared_ptr> distinct_list(shared_ptr>* L) { 16 | shared_ptr> pre = nullptr, now = *L; 17 | while (now) { 18 | if (now && now->next && now->data == now->next->data) { 19 | int target = now->data; 20 | while (now && now->data == target) { 21 | if (pre) { 22 | pre->next = now->next; 23 | } 24 | if (now == *L) { 25 | *L = now->next; 26 | } 27 | now = now->next; 28 | } 29 | } else { 30 | pre = now; 31 | now = now->next; 32 | } 33 | } 34 | return *L; 35 | } 36 | // @exclude 37 | 38 | int main(int argc, char** argv) { 39 | shared_ptr> L; 40 | L = make_shared>(ListNode{ 41 | 2, make_shared>(ListNode{ 42 | 2, make_shared>(ListNode{ 43 | 3, make_shared>(ListNode{ 44 | 3, make_shared>(ListNode{5, nullptr})})})})}); 45 | shared_ptr> pre = nullptr; 46 | auto res = distinct_list(&L); 47 | while (res) { 48 | if (pre) { 49 | assert(pre->data != res->data); 50 | } 51 | cout << res->data << endl; 52 | pre = res; 53 | res = res->next; 54 | } 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /execute-shell.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_EXECUTE_SHELL_H_ 4 | #define SOLUTIONS_EXECUTE_SHELL_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | using std::string; 11 | 12 | string execute_shell(const string &cmd) { 13 | FILE* pipe = popen(cmd.c_str(), "r"); 14 | if (!pipe) { 15 | return "ERROR"; 16 | } 17 | char buffer[128]; 18 | string result; 19 | while (!feof(pipe)) { 20 | if (!fgets(buffer, 128, pipe)) { 21 | result += buffer; 22 | } 23 | } 24 | pclose(pipe); 25 | return result; 26 | } 27 | #endif // SOLUTIONS_EXECUTE_SHELL_H_ 28 | -------------------------------------------------------------------------------- /insertion-sort-list.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "./Linked_list_prototype.h" 8 | 9 | using std::cout; 10 | using std::endl; 11 | using std::make_shared; 12 | using std::shared_ptr; 13 | 14 | // @include 15 | shared_ptr> insertion_sort(const shared_ptr>& L) { 16 | shared_ptr> head = nullptr; 17 | auto now = L; 18 | while (now) { 19 | auto next = now->next; 20 | now->next = nullptr; 21 | if (head) { 22 | shared_ptr> pre_head_ptr = nullptr, head_ptr = head; 23 | while (head_ptr && now->data >= head_ptr->data) { 24 | pre_head_ptr = head_ptr; 25 | head_ptr = head_ptr->next; 26 | } 27 | now->next = head_ptr; 28 | if (pre_head_ptr) { 29 | pre_head_ptr->next = now; 30 | } else { 31 | head = now; 32 | } 33 | } else { 34 | head = now; 35 | } 36 | now = next; 37 | } 38 | return head; 39 | } 40 | // @exclude 41 | 42 | int main(int argc, char** argv) { 43 | shared_ptr> L; 44 | L = make_shared>(ListNode{ 45 | 1, make_shared>(ListNode{ 46 | 4, make_shared>(ListNode{ 47 | 3, make_shared>(ListNode{ 48 | 2, make_shared>(ListNode{5, nullptr})})})})}); 49 | auto res = insertion_sort(L); 50 | shared_ptr> pre = nullptr; 51 | while (res) { 52 | assert(!pre || pre->data <= res->data); 53 | pre = res; 54 | cout << res->data << endl; 55 | res = res->next; 56 | } 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /jump-game-min-steps.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::max; 14 | using std::random_device; 15 | using std::stoul; 16 | using std::uniform_int_distribution; 17 | using std::vector; 18 | 19 | // @include 20 | int jump(const vector& A) { 21 | int step = 0, last_reach = 0, reach = 0; 22 | for (int i = 0; i < A.size(); ++i) { 23 | if (i > last_reach) { 24 | last_reach = reach, ++step; 25 | } 26 | reach = max(reach, i + A[i]); 27 | } 28 | return step; 29 | } 30 | // @exclude 31 | 32 | void small_test() { 33 | vector A1 = {2, 3, 1, 1, 4}; 34 | assert(2 == jump(A1)); 35 | vector A2 = {3, 1, 4, 1, 1, 1}; 36 | assert(2 == jump(A2)); 37 | } 38 | 39 | int main(int argc, char** argv) { 40 | small_test(); 41 | return 0; 42 | default_random_engine gen((random_device())()); 43 | size_t n; 44 | if (argc == 2) { 45 | n = stoul(argv[1]); 46 | } else { 47 | uniform_int_distribution dis(1, 1000); 48 | n = dis(gen); 49 | } 50 | uniform_int_distribution A_dis(1, 10); 51 | vector A; 52 | generate_n(back_inserter(A), n, [&] { return A_dis(gen); }); 53 | cout << jump(A) << endl; 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /jump-game.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::max; 14 | using std::random_device; 15 | using std::stoul; 16 | using std::uniform_int_distribution; 17 | using std::vector; 18 | 19 | // @include 20 | bool can_reach(const vector& A) { 21 | int last_reach = 0, farthest_reach = 0; 22 | for (int i = 0; i < A.size(); ++i) { 23 | if (i > last_reach) { 24 | if (last_reach >= farthest_reach) { 25 | return false; 26 | } 27 | last_reach = farthest_reach; 28 | } 29 | farthest_reach = max(farthest_reach, i + A[i]); 30 | } 31 | return true; 32 | } 33 | // @exclude 34 | 35 | void small_test() { 36 | vector A = {2, 3, 1, 1, 4}; 37 | assert(can_reach(A)); 38 | A = {3, 2, 1, 0, 4}; 39 | assert(!can_reach(A)); 40 | A = {3, 2, 1, -10, 4}; 41 | assert(!can_reach(A)); 42 | A = {2, 3, -1, -1, 4}; 43 | assert(can_reach(A)); 44 | A = {2, 2, -1, -1, 100}; 45 | assert(!can_reach(A)); 46 | } 47 | 48 | int main(int argc, char** argv) { 49 | small_test(); 50 | return 0; 51 | default_random_engine gen((random_device())()); 52 | size_t n; 53 | if (argc == 2) { 54 | n = stoul(argv[1]); 55 | } else { 56 | uniform_int_distribution dis(1, 1000); 57 | n = dis(gen); 58 | } 59 | uniform_int_distribution A_dis(1, 10); 60 | vector A; 61 | generate_n(back_inserter(A), n, [&] { return A_dis(gen); }); 62 | cout << std::boolalpha << can_reach(A) << endl; 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /k-largest-elements-binary-heap.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::endl; 11 | using std::pair; 12 | using std::priority_queue; 13 | using std::vector; 14 | 15 | // @include 16 | struct Compare { 17 | bool operator()(const pair &a, const pair &b) { 18 | return a.second < b.second; 19 | } 20 | }; 21 | 22 | vector k_largest_in_binary_heap(const vector& A, int k) { 23 | if (k <= 0) { 24 | return {}; 25 | } 26 | 27 | // Stores the (index, value)-pair in this max-heap. Ordered by value. 28 | priority_queue, 29 | vector>, 30 | Compare> max_heap; 31 | max_heap.emplace(0, A[0]); // the largest element stores at index 0. 32 | vector res; 33 | for (int i = 0; i < k; ++i) { 34 | size_t idx = max_heap.top().first; 35 | res.emplace_back(max_heap.top().second); 36 | max_heap.pop(); 37 | 38 | if ((idx << 1) + 1 < A.size()) { 39 | max_heap.emplace((idx << 1) + 1, A[(idx << 1) + 1]); 40 | } 41 | if ((idx << 1) + 2 < A.size()) { 42 | max_heap.emplace((idx << 1) + 2, A[(idx << 1) + 2]); 43 | } 44 | } 45 | return res; 46 | } 47 | // @exclude 48 | 49 | int main(int argc, char* argv[]) { 50 | vector max_heap = {10, 2, 9, 2, 2, 8, 8, 2, 2, 2, 2, 7, 7, 7, 7}; 51 | auto res = k_largest_in_binary_heap(max_heap, 3); 52 | vector expected_res = {10, 9, 8}; 53 | assert(res.size() == 3 && equal(res.begin(), res.end(), expected_res.begin())); 54 | res = k_largest_in_binary_heap(max_heap, 5); 55 | expected_res = {10, 9, 8, 8, 7}; 56 | assert(res.size() == 5 && equal(res.begin(), res.end(), expected_res.begin())); 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /lazy-init.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | 6 | using std::cout; 7 | using std::endl; 8 | 9 | // @include 10 | template 11 | class Array { 12 | public: 13 | bool read(size_t i, ValueType* v) const { 14 | if (isValid(i)) { 15 | *v = A_[i]; 16 | return true; 17 | } 18 | return false; 19 | } 20 | 21 | void write(size_t i, const ValueType& v) { 22 | if (!isValid(i)) { 23 | S_[t_] = i; 24 | P_[i] = t_++; 25 | } 26 | A_[i] = v; 27 | } 28 | 29 | private: 30 | bool isValid(size_t i) const { 31 | return (0 <= P_[i] && P_[i] < t_ && S_[P_[i]] == i); 32 | } 33 | 34 | ValueType A_[N]; 35 | int P_[N], S_[N], t_ = 0; 36 | }; 37 | // @exclude 38 | 39 | int main(int argc, char* argv[]) { 40 | Array A; 41 | int x; 42 | assert(A.read(0, &x) == false); 43 | assert(A.read(1, &x) == false); 44 | A.write(1, 5); 45 | assert(A.read(1, &x) == true && x == 5); 46 | assert(A.read(2, &x) == false); 47 | A.write(2, 27); 48 | assert(A.read(2, &x) == true && x == 27); 49 | assert(A.read(7, &x) == false); 50 | A.write(7, -19); 51 | assert(A.read(7, &x) == true && x == -19); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /length-of-last-word.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::default_random_engine; 11 | using std::endl; 12 | using std::random_device; 13 | using std::string; 14 | using std::uniform_int_distribution; 15 | 16 | // @include 17 | size_t length_of_last_word(const string& s) { 18 | auto last_space = s.rbegin(); 19 | bool seen_non_space = false; 20 | for (auto it = s.rbegin(); it != s.rend(); ++it) { 21 | if (*it == ' ') { 22 | if (seen_non_space) { 23 | return distance(*last_space == ' ' ? last_space + 1 : last_space, it); 24 | } 25 | last_space = it; 26 | } else { 27 | seen_non_space = true; 28 | } 29 | } 30 | return seen_non_space ? distance(*last_space == ' ' ? last_space + 1 : last_space, s.rend()) : 0; 31 | } 32 | // @exclude 33 | 34 | int main(int argc, char** argv) { 35 | string s = "Hello World"; 36 | assert(5 == length_of_last_word(s)); 37 | s = "a "; 38 | assert(1 == length_of_last_word(s)); 39 | s = " "; 40 | assert(0 == length_of_last_word(s)); 41 | s = "a"; 42 | assert(1 == length_of_last_word(s)); 43 | s = " a "; 44 | assert(1 == length_of_last_word(s)); 45 | s = " a,b,.c d "; 46 | assert(1 == length_of_last_word(s)); 47 | s = " a,bbbbbbb,.c d "; 48 | assert(1 == length_of_last_word(s)); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /longest-valid-parentheses.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::endl; 12 | using std::max; 13 | using std::stack; 14 | using std::string; 15 | using std::vector; 16 | 17 | // @include 18 | size_t longest_valid_parentheses(const string& s) { 19 | size_t max_len = 0, last_end = 0; 20 | stack left_parentheses; 21 | for (size_t i = 0; i < s.size(); ++i) { 22 | if (s[i] == '(') { 23 | left_parentheses.emplace(i); 24 | } else { 25 | if (left_parentheses.empty()) { 26 | last_end = i + 1; 27 | } else { 28 | left_parentheses.pop(); 29 | size_t start = left_parentheses.empty() ? 30 | last_end - 1 : left_parentheses.top(); 31 | max_len = max(max_len, i - start); 32 | } 33 | } 34 | } 35 | return max_len; 36 | } 37 | // @exclude 38 | 39 | void small_test() { 40 | assert(longest_valid_parentheses("((())()(()(") == 6); 41 | assert(longest_valid_parentheses("()()())") == 6); 42 | } 43 | 44 | int main(int argc, char** argv) { 45 | small_test(); 46 | string s; 47 | if (argc == 2) { 48 | s = argv[1]; 49 | } 50 | cout << "s = " << s << endl; 51 | cout << longest_valid_parentheses(s) << endl; 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /look-and-say.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::random_device; 14 | using std::stoi; 15 | using std::string; 16 | using std::stringstream; 17 | using std::to_string; 18 | using std::uniform_int_distribution; 19 | 20 | string next_sequence(const string& s); 21 | 22 | // @include 23 | string look_and_say(int n) { 24 | string s = "1"; 25 | for (int i = 1; i < n; ++i) { 26 | s = next_sequence(s); 27 | } 28 | return s; 29 | } 30 | 31 | string next_sequence(const string& s) { 32 | string ret; 33 | for (size_t i = 0; i < s.size(); ++i) { 34 | int count = 1; 35 | while (i + 1 < s.size() && s[i] == s[i + 1]) { 36 | ++i, ++count; 37 | } 38 | ret += to_string(count) + s[i]; 39 | } 40 | return ret; 41 | } 42 | // @exclude 43 | 44 | int main(int argc, char** argv) { 45 | default_random_engine gen((random_device())()); 46 | int n; 47 | if (argc == 2) { 48 | n = stoi(argv[1]); 49 | } else { 50 | uniform_int_distribution dis(1, 50); 51 | n = dis(gen); 52 | } 53 | assert(!look_and_say(1).compare("1")); 54 | assert(!look_and_say(2).compare("11")); 55 | assert(!look_and_say(3).compare("21")); 56 | assert(!look_and_say(5).compare("111221")); 57 | cout << "n = " << n << endl; 58 | cout << look_and_say(n) << endl; 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /merge-two-sorted-arrays-in-place.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::random_device; 14 | using std::stoul; 15 | using std::uniform_int_distribution; 16 | using std::vector; 17 | 18 | // @include 19 | void merge_two_sorted_arrays(int A[], int m, int B[], int n) { 20 | int a = m - 1, b = n - 1, tar = m + n - 1; 21 | while (a >= 0 && b >= 0) { 22 | A[tar--] = (A[a] > B[b]) ? A[a--] : B[b--]; 23 | } 24 | while (b >= 0) { 25 | A[tar--] = B[b--]; 26 | } 27 | } 28 | // @exclude 29 | 30 | void check_ans(const vector& A) { 31 | for (size_t i = 1; i < A.size(); ++i) { 32 | assert(A[i - 1] <= A[i]); 33 | } 34 | } 35 | 36 | int main(int argc, char** argv) { 37 | default_random_engine gen((random_device())()); 38 | for (int times = 0; times < 1000; ++times) { 39 | size_t m, n; 40 | if (argc == 3) { 41 | m = stoul(argv[1]), n = stoul(argv[2]); 42 | } else { 43 | uniform_int_distribution size_dis(0, 10000); 44 | m = size_dis(gen), n = size_dis(gen); 45 | } 46 | uniform_int_distribution dis(-(m + n), m + n); 47 | vector A(m + n), B; 48 | for (size_t i = 0; i < m; ++i) { 49 | A[i] = dis(gen); 50 | } 51 | generate_n(back_inserter(B), n, [&] { return dis(gen); }); 52 | sort(A.begin(), A.begin() + m), sort(B.begin(), B.end()); 53 | merge_two_sorted_arrays(A.data(), m, B.data(), n); 54 | check_ans(A); 55 | } 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /n-queens-count.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::random_device; 14 | using std::string; 15 | using std::stoi; 16 | using std::uniform_int_distribution; 17 | using std::vector; 18 | 19 | // @include 20 | bool is_feasible(const vector& col_placement, int row) { 21 | for (int i = 0; i < row; ++i) { 22 | int diff = abs(col_placement[i] - col_placement[row]); 23 | if (diff == 0 || diff == row - i) { 24 | return false; 25 | } 26 | } 27 | return true; 28 | } 29 | 30 | int n_queens_helper(int n, int row, vector* col_placement) { 31 | if (row == n) { 32 | return 1; 33 | } else { 34 | int sum = 0; 35 | for (int col = 0; col < n; ++col) { 36 | (*col_placement)[row] = col; 37 | if (is_feasible(*col_placement, row)) { 38 | sum += n_queens_helper(n, row + 1, col_placement); 39 | } 40 | } 41 | return sum; 42 | } 43 | } 44 | 45 | int n_queens(int n) { 46 | vector placement(n); 47 | return n_queens_helper(n, 0, &placement); 48 | } 49 | // @exclude 50 | 51 | int main(int argc, char** argv) { 52 | default_random_engine gen((random_device())()); 53 | int n; 54 | if (argc == 2) { 55 | n = stoi(argv[1]); 56 | } else { 57 | uniform_int_distribution dis(1, 15); 58 | n = dis(gen); 59 | } 60 | cout << "n = " << n << endl; 61 | cout << n_queens(n) << endl; 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /nnChomp.pseudo: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | // @include 4 | WinChomp(): 5 | You choose square (1,1); 6 | Until you win: 7 | Wait for your opponent to choose square (i,j); 8 | You choose square (j,i); 9 | // @exclude 10 | -------------------------------------------------------------------------------- /number-steps.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::random_device; 14 | using std::stoi; 15 | using std::uniform_int_distribution; 16 | using std::vector; 17 | 18 | // @include 19 | int number_steps(int n, int k) { 20 | if (n <= 1) { 21 | return 1; 22 | } 23 | 24 | vector steps(k + 1, 0); 25 | steps[0] = steps[1] = 1; 26 | for (int i = 2; i <= n; ++i) { 27 | steps[i % (k + 1)] = 0; 28 | for (int j = 1; j <= k && i - j >= 0; ++j) { 29 | steps[i % (k + 1)] += steps[(i - j) % (k + 1)]; 30 | } 31 | } 32 | return steps[n % (k + 1)]; 33 | } 34 | // @exclude 35 | 36 | int main(int argc, char** argv) { 37 | assert(5 == number_steps(4, 2)); 38 | default_random_engine gen((random_device())()); 39 | int n, k; 40 | if (argc == 3) { 41 | n = stoi(argv[1]), k = stoi(argv[2]); 42 | } else { 43 | uniform_int_distribution dis(1, 20); 44 | n = dis(gen); 45 | uniform_int_distribution k_dis(1, n); 46 | k = k_dis(gen); 47 | } 48 | cout << "n = " << n << ", k = " << k << endl; 49 | cout << number_steps(n, k) << endl; 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /palindrome-number.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::random_device; 14 | using std::stoi; 15 | using std::to_string; 16 | using std::uniform_int_distribution; 17 | using std::vector; 18 | 19 | // @include 20 | bool is_palindrome(int x) { 21 | if (x < 0) { 22 | return false; 23 | } 24 | 25 | int num_digits = static_cast(floor(log10(x))) + 1; 26 | int temp_x = x, msb_shift = static_cast(pow(10, num_digits - 1)); 27 | for (int i = 0; i < (num_digits >> 1); ++i) { 28 | if (x / msb_shift != temp_x % 10) { 29 | return false; 30 | } 31 | x %= msb_shift; 32 | msb_shift /= 10, temp_x /= 10; 33 | } 34 | return true; 35 | } 36 | // @exclude 37 | 38 | bool check_ans(int x) { 39 | auto s = to_string(x); 40 | for (size_t i = 0, j = s.size() - 1; i < j; ++i, --j) { 41 | if (s[i] != s[j]) { 42 | return false; 43 | } 44 | } 45 | return true; 46 | } 47 | 48 | int main(int argc, char** argv) { 49 | default_random_engine gen((random_device())()); 50 | int x; 51 | if (argc == 2) { 52 | x = stoi(argv[1]); 53 | cout << x << " " << std::boolalpha << is_palindrome(x) << endl; 54 | assert(check_ans(x) == is_palindrome(x)); 55 | } else { 56 | uniform_int_distribution dis(-99999, 99999); 57 | for (int times = 0; times < 1000; ++times) { 58 | x = dis(gen); 59 | assert(check_ans(x) == is_palindrome(x)); 60 | } 61 | } 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /pascal-triangle-1.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using std::cout; 12 | using std::default_random_engine; 13 | using std::endl; 14 | using std::ostream_iterator; 15 | using std::random_device; 16 | using std::stoi; 17 | using std::uniform_int_distribution; 18 | using std::vector; 19 | 20 | // @include 21 | vector> generate_pascal_triangle(int n) { 22 | if (n <= 0) { 23 | return {}; 24 | } 25 | 26 | vector> result; 27 | result.emplace_back(vector{1}); 28 | for (int i = 1; i < n; ++i) { 29 | vector curr_row; 30 | curr_row.emplace_back(1); // for the first element. 31 | for (int j = 1; j < i; ++j) { 32 | curr_row.emplace_back(result.back()[j - 1] + result.back()[j]); 33 | } 34 | curr_row.emplace_back(1); // for the last element. 35 | result.emplace_back(curr_row); 36 | } 37 | return result; 38 | } 39 | // @exclude 40 | 41 | int main(int argc, char** argv) { 42 | default_random_engine gen((random_device())()); 43 | int n; 44 | if (argc == 2) { 45 | n = stoi(argv[1]); 46 | } else { 47 | uniform_int_distribution dis(0, 10); 48 | n = dis(gen); 49 | } 50 | cout << "n = " << n << endl; 51 | auto res = generate_pascal_triangle(n); 52 | for (size_t i = 0; i < res.size(); ++i) { 53 | for (size_t j = 0; j < res[i].size(); ++j) { 54 | cout << res[i][j] << ' '; 55 | } 56 | cout << endl; 57 | } 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /permutations.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::random_device; 14 | using std::stoul; 15 | using std::uniform_int_distribution; 16 | using std::vector; 17 | 18 | // @include 19 | vector> permutations(vector A) { 20 | vector> res; 21 | sort(A.begin(), A.end()); 22 | do { 23 | res.emplace_back(A); 24 | } while (next_permutation(A.begin(), A.end())); 25 | return res; 26 | } 27 | // @exclude 28 | 29 | template 30 | bool equal_vector(const vector &A, const vector &B) { 31 | return A.size() == B.size() && equal(A.begin(), A.end(), B.begin()); 32 | } 33 | 34 | void small_test() { 35 | vector A = {1, 2, 3}; 36 | auto res = permutations(A); 37 | assert(res.size() == 6); 38 | vector> golden_res = {{1, 2, 3}, {1, 3, 2}, {2, 1, 3}, {2, 3, 1}, {3, 1, 2}, {3, 2, 1}}; 39 | for (size_t i = 0; i < 6; ++i) { 40 | assert(equal_vector(res[i], golden_res[i])); 41 | } 42 | } 43 | 44 | int main(int argc, char** argv) { 45 | small_test(); 46 | default_random_engine gen((random_device())()); 47 | size_t n; 48 | if (argc == 2) { 49 | n = stoul(argv[1]); 50 | } else { 51 | uniform_int_distribution dis(1, 10); 52 | n = dis(gen); 53 | } 54 | vector A(n); 55 | iota(A.begin(), A.end(), 0); 56 | auto res = permutations(A); 57 | cout << "n = " << n << endl; 58 | for (const auto& vec : res) { 59 | for (int a : vec) { 60 | cout << a << " "; 61 | } 62 | cout << endl; 63 | } 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /power-x-y.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using std::cout; 12 | using std::default_random_engine; 13 | using std::endl; 14 | using std::numeric_limits; 15 | using std::random_device; 16 | using std::stod; 17 | using std::stoi; 18 | using std::uniform_int_distribution; 19 | using std::uniform_real_distribution; 20 | 21 | // 0 means equal, -1 means smaller, and 1 means larger. 22 | int compare(double a, double b) { 23 | // Use normalization for precision problem. 24 | double diff = (a - b) / b; 25 | return diff < -numeric_limits::epsilon() 26 | ? -1 27 | : diff > numeric_limits::epsilon(); 28 | } 29 | 30 | // @include 31 | double pow(double x, int y) { 32 | double res = 1.0; 33 | long long power = y; 34 | if (y < 0) { 35 | power = -power, x = 1.0 / x; 36 | } 37 | while (power) { 38 | if (power & 1) { 39 | res *= x; 40 | } 41 | x *= x, power >>= 1; 42 | } 43 | return res; 44 | } 45 | // @exclude 46 | 47 | int main(int argc, char** argv) { 48 | default_random_engine gen((random_device())()); 49 | double x; 50 | int y; 51 | if (argc == 3) { 52 | x = stod(argv[1]), y = stoi(argv[2]); 53 | cout << x << "^" << y << ": " << pow(x, y) << ", " << std::pow(x, y) << endl; 54 | assert(!compare(pow(x, y), std::pow(x, y))); 55 | } else { 56 | uniform_real_distribution<> dis_x(0.0, 10.0); 57 | uniform_int_distribution<> dis_y(-128, 128); 58 | for (int times = 0; times < 10000; ++times) { 59 | x = dis_x(gen); 60 | y = dis_y(gen); 61 | cout << x << "^" << y << ": " << pow(x, y) << " " << std::pow(x, y) << endl; 62 | //assert(!compare(pow(x, y), std::pow(x, y))); 63 | } 64 | } 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /remove-duplicates-from-sorted-array.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::random_device; 14 | using std::stoul; 15 | using std::uniform_int_distribution; 16 | using std::vector; 17 | 18 | // @include 19 | size_t remove_duplicates(vector* A) { 20 | if (!A->size()) { 21 | return 0; 22 | } 23 | 24 | size_t i = 0, j = 1; 25 | while (j < A->size()) { 26 | if ((*A)[i] != (*A)[j]) { 27 | (*A)[++i] = (*A)[j]; 28 | } 29 | ++j; 30 | } 31 | return i + 1; 32 | } 33 | // @exclude 34 | 35 | void check_ans(const vector A, size_t n) { 36 | for (size_t i = 1; i < n; ++i) { 37 | assert(A[i - 1] != A[i]); 38 | } 39 | } 40 | 41 | int main(int argc, char** argv) { 42 | default_random_engine gen((random_device())()); 43 | size_t n; 44 | if (argc == 2) { 45 | n = stoul(argv[1]); 46 | } else { 47 | uniform_int_distribution dis_n(0, 10000); 48 | n = dis_n(gen); 49 | } 50 | for (int times = 0; times < 1000; ++times) { 51 | uniform_int_distribution A_dis(-1000, 1000); 52 | vector A; 53 | generate_n(back_inserter(A), n, [&] { return A_dis(gen); }); 54 | sort(A.begin(), A.end()); 55 | auto B(A); 56 | auto iter = unique(B.begin(), B.end()); 57 | auto size = remove_duplicates(&A); 58 | assert(size == distance(B.begin(), iter)); 59 | check_ans(A, size); 60 | cout << size << endl; 61 | } 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /remove-duplicates-sorted-list.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "./Linked_list_prototype.h" 8 | 9 | using std::cout; 10 | using std::endl; 11 | using std::make_shared; 12 | using std::shared_ptr; 13 | 14 | // @include 15 | shared_ptr> remove_duplicates( 16 | const shared_ptr>& L) { 17 | shared_ptr> pre = nullptr, now = L; 18 | while (now) { 19 | if (pre && pre->data == now->data) { 20 | pre->next = now->next; 21 | now = now->next; 22 | } else { 23 | pre = now; 24 | now = now->next; 25 | } 26 | } 27 | return L; 28 | } 29 | // @exclude 30 | 31 | int main(int argc, char** argv) { 32 | shared_ptr> L; 33 | L = make_shared>(ListNode{ 34 | 2, make_shared>(ListNode{ 35 | 2, make_shared>(ListNode{ 36 | 2, make_shared>(ListNode{ 37 | 2, make_shared>(ListNode{2, nullptr})})})})}); 38 | shared_ptr> pre = nullptr; 39 | auto res = remove_duplicates(L); 40 | while (res) { 41 | if (pre) { 42 | assert(pre->data != res->data); 43 | } 44 | cout << res->data << endl; 45 | pre = res; 46 | res = res->next; 47 | } 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /remove-element.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::random_device; 14 | using std::stoul; 15 | using std::uniform_int_distribution; 16 | using std::vector; 17 | 18 | // @include 19 | size_t remove_element(vector* A, int k) { 20 | size_t write_idx = 0; 21 | for (size_t i = 0; i < A->size(); ++i) { 22 | if ((*A)[i] != k) { 23 | (*A)[write_idx++] = (*A)[i]; 24 | } 25 | } 26 | return write_idx; 27 | } 28 | // @exclude 29 | 30 | void check_ans(const vector& A, size_t n, int k) { 31 | for (size_t i = 0; i < n; ++i) { 32 | assert(A[i] != k); 33 | } 34 | } 35 | 36 | int main(int argc, char** argv) { 37 | default_random_engine gen((random_device())()); 38 | size_t n; 39 | if (argc == 2) { 40 | n = stoul(argv[1]); 41 | } else { 42 | uniform_int_distribution dis_n(0, 10000); 43 | n = dis_n(gen); 44 | } 45 | for (int times = 0; times < 1000; ++times) { 46 | uniform_int_distribution A_dis(-1000, 1000); 47 | vector A; 48 | generate_n(back_inserter(A), n, [&] { return A_dis(gen); }); 49 | auto copy_A(A); 50 | int target = A_dis(gen); 51 | auto size = remove_element(&A, target); 52 | cout << "size = " << size << " k = " << target << endl; 53 | check_ans(A, size, target); 54 | auto it = remove_if(copy_A.begin(), copy_A.end(), [&target](int a) { return a == target; }); 55 | cout << distance(copy_A.begin(), it) << endl; 56 | assert(size == distance(copy_A.begin(), it)); 57 | } 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /remove-twice-duplicates-from-sorted-array.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::random_device; 14 | using std::stoul; 15 | using std::uniform_int_distribution; 16 | using std::vector; 17 | 18 | // @include 19 | size_t remove_twice_duplicates(int* A, size_t n) { 20 | if (!n) { 21 | return 0; 22 | } 23 | 24 | size_t i = 0, j = 1; 25 | while (j < n) { 26 | if (A[i] != A[j] || (A[i] == A[j] && (i == 0 || A[i - 1] != A[i]))) { 27 | ++i; 28 | A[i] = A[j]; 29 | } 30 | ++j; 31 | } 32 | return i + 1; 33 | } 34 | // @exclude 35 | 36 | void check_ans(const vector A, size_t n) { 37 | for (size_t i = 1; i < n; ++i) { 38 | assert(A[i - 1] != A[i] || (i == 1 || A[i - 2] != A[i - 1])); 39 | } 40 | } 41 | 42 | int main(int argc, char** argv) { 43 | default_random_engine gen((random_device())()); 44 | size_t n; 45 | if (argc == 2) { 46 | n = stoul(argv[1]); 47 | } else { 48 | uniform_int_distribution dis_n(0, 10000); 49 | n = dis_n(gen); 50 | } 51 | for (int times = 0; times < 1000; ++times) { 52 | uniform_int_distribution A_dis(-1000, 1000); 53 | vector A; 54 | generate_n(back_inserter(A), n, [&] { return A_dis(gen); }); 55 | sort(A.begin(), A.end()); 56 | auto size = remove_twice_duplicates(A.data(), n); 57 | check_ans(A, size); 58 | cout << size << endl; 59 | } 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /reverse-integer.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::numeric_limits; 14 | using std::random_device; 15 | using std::stoi; 16 | using std::stol; 17 | using std::string; 18 | using std::to_string; 19 | using std::uniform_int_distribution; 20 | 21 | // @include 22 | long reverse(int K) { 23 | long res = 0; 24 | while (K) { 25 | res = res * 10 + K % 10; 26 | K /= 10; 27 | } 28 | return res; 29 | } 30 | // @exclude 31 | 32 | long check_ans(int x) { 33 | string s = to_string(x); 34 | if (s.front() == '-') { 35 | reverse(s.begin() + 1, s.end()); 36 | } else { 37 | reverse(s.begin(), s.end()); 38 | } 39 | return stol(s); 40 | } 41 | 42 | int main(int argc, char** argv) { 43 | default_random_engine gen((random_device())()); 44 | int n; 45 | if (argc == 2) { 46 | n = stoi(argv[1]); 47 | cout << "n = " << n << ", reversed n = " << reverse(n) << endl; 48 | assert(check_ans(n) == reverse(n)); 49 | } else { 50 | uniform_int_distribution dis(numeric_limits::min(), numeric_limits::max()); 51 | for (int times = 0; times < 1000; ++times) { 52 | n = dis(gen); 53 | cout << "n = " << n << ", reversed n = " << reverse(n) << endl; 54 | assert(check_ans(n) == reverse(n)); 55 | } 56 | } 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /roman-to-integer.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::endl; 11 | using std::string; 12 | using std::unordered_map; 13 | 14 | // @include 15 | int roman_to_integer(const string& s) { 16 | unordered_map T = { { 'I', 1 }, 17 | { 'V', 5 }, 18 | { 'X', 10 }, 19 | { 'L', 50 }, 20 | { 'C', 100 }, 21 | { 'D', 500 }, 22 | { 'M', 1000 } }; 23 | 24 | int sum = T[s.back()]; 25 | for (int i = s.length() - 2; i >= 0; --i) { 26 | if (T[s[i]] < T[s[i + 1]]) { 27 | sum -= T[s[i]]; 28 | } else { 29 | sum += T[s[i]]; 30 | } 31 | } 32 | return sum; 33 | } 34 | // @exclude 35 | 36 | int main(int argc, char** argv) { 37 | assert(7 == roman_to_integer("VII")); 38 | assert(184 == roman_to_integer("CLXXXIV")); 39 | assert(9 == roman_to_integer("IX")); 40 | assert(40 == roman_to_integer("XL")); 41 | assert(60 == roman_to_integer("LX")); 42 | assert(1500 == roman_to_integer("MD")); 43 | assert(400 == roman_to_integer("CD")); 44 | assert(1900 == roman_to_integer("MCM")); 45 | assert(9919 == roman_to_integer("MMMMMMMMMCMXIX")); 46 | if (argc == 2) { 47 | cout << argv[1] << " equals to " << roman_to_integer(argv[1]) << endl; 48 | } 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /scramble-string.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using std::cout; 12 | using std::default_random_engine; 13 | using std::deque; 14 | using std::endl; 15 | using std::random_device; 16 | using std::string; 17 | using std::uniform_int_distribution; 18 | using std::vector; 19 | 20 | // @include 21 | bool is_scramble(const string& s1, const string& s2) { 22 | int n = s1.size(); 23 | if (n != s2.size()) { 24 | return false; 25 | } 26 | if (!s1.compare(s2)) { 27 | return true; 28 | } 29 | 30 | vector>> T(n, vector>(n, deque(n))); 31 | for (size_t i = 0; i < n; ++i) { 32 | for (size_t j = 0; j < n; ++j) { 33 | T[i][j][0] = s1[i] == s2[j]; 34 | } 35 | } 36 | 37 | for (int len = 1; len < n; ++len) { 38 | for (int i = 0; i + len < n; ++i) { 39 | for (int j = 0; j + len < n; ++j) { 40 | T[i][j][len] = false; 41 | for (int k = 0; k < len; ++k) { 42 | if ((T[i][j][k] && T[i + k + 1][j + k + 1][len - 1 - k]) || (T[i][j + len - k][k] && T[i + k + 1][j][len - 1 -k])) { 43 | T[i][j][len] = true; 44 | break; 45 | } 46 | } 47 | } 48 | } 49 | } 50 | return T[0][0][n - 1]; 51 | } 52 | // @exclude 53 | 54 | int main(int argc, char** argv) { 55 | assert(is_scramble("great", "rgtae")); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /snake-string.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::default_random_engine; 10 | using std::endl; 11 | using std::random_device; 12 | using std::stoi; 13 | using std::string; 14 | using std::uniform_int_distribution; 15 | 16 | // @include 17 | string snake_string(const string& s) { 18 | string ret; 19 | // Processes the first row. 20 | size_t idx = 1; 21 | while (idx < s.size()) { 22 | ret += s[idx]; 23 | idx += 4; 24 | } 25 | // Processes the second row. 26 | idx = 0; 27 | while (idx < s.size()) { 28 | ret += s[idx]; 29 | idx += 2; 30 | } 31 | // Processes the third row. 32 | idx = 3; 33 | while (idx < s.size()) { 34 | ret += s[idx]; 35 | idx += 4; 36 | } 37 | 38 | return ret; 39 | } 40 | // @exclude 41 | 42 | string rand_string(size_t len) { 43 | default_random_engine gen((random_device())()); 44 | uniform_int_distribution dis('A', 'Z'); 45 | string ret; 46 | while (len--) { 47 | ret += dis(gen); 48 | } 49 | return ret; 50 | } 51 | 52 | void small_test() { 53 | assert(!snake_string("Hello World!").compare("e lHloWrdlo!")); 54 | } 55 | 56 | int main(int argc, char** argv) { 57 | small_test(); 58 | default_random_engine gen((random_device())()); 59 | string s; 60 | if (argc == 2) { 61 | s = argv[1]; 62 | } else { 63 | uniform_int_distribution dis_s(1, 100); 64 | s = rand_string(dis_s(gen)); 65 | } 66 | cout << snake_string(s) << endl; 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /square-root-int.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using std::cout; 12 | using std::default_random_engine; 13 | using std::endl; 14 | using std::numeric_limits; 15 | using std::random_device; 16 | using std::stoi; 17 | using std::uniform_int_distribution; 18 | 19 | // @include 20 | int square_root(int x) { 21 | if (x <= 1) { 22 | return x; 23 | } 24 | 25 | long left = 0, right = x; 26 | while (left + 1 < right) { 27 | long mid = left + ((right - left) >> 1); 28 | long square_m = mid * mid; 29 | if (square_m == x) { 30 | return mid; 31 | } else if (square_m < x) { 32 | left = mid; 33 | } else { // square_m > x 34 | right = mid - 1; 35 | } 36 | } 37 | if (right * right <= x) { 38 | return right; 39 | } 40 | return left; 41 | } 42 | // @exclude 43 | 44 | int main(int argc, char** argv) { 45 | int x; 46 | if (argc == 2) { 47 | x = stoi(argv[1]); 48 | } else { 49 | default_random_engine gen((random_device())()); 50 | uniform_int_distribution dis(0, numeric_limits::max()); 51 | for (int times = 0; times < 100000; ++times) { 52 | x = dis(gen); 53 | int res[2]; 54 | cout << "x is " << x << endl; 55 | cout << (res[0] = square_root(x)) << ' ' << (res[1] = static_cast(sqrt(x))) << endl; 56 | assert(res[0] == res[1]); 57 | } 58 | } 59 | x = 2147395599; 60 | cout << square_root(x) << endl; 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /sum-root-to-leaf-binary-tree.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "./Binary_tree_prototype.h" 9 | 10 | using std::cout; 11 | using std::endl; 12 | using std::equal; 13 | using std::unique_ptr; 14 | 15 | int preorder_traversal(const unique_ptr>& root, int num); 16 | 17 | // @include 18 | int sum_root_to_leaf(const unique_ptr>& root) { 19 | return preorder_traversal(root, 0); 20 | } 21 | 22 | int preorder_traversal(const unique_ptr>& root, int num) { 23 | if (!root) { 24 | return 0; 25 | } 26 | 27 | num = (num << 1) + root->data; 28 | if (!root->left && !root->right) { // leaf. 29 | return num; 30 | } 31 | // non-leaf. 32 | return preorder_traversal(root->left, num) + 33 | preorder_traversal(root->right, num); 34 | } 35 | // @exclude 36 | 37 | int main(int argc, char** argv) { 38 | // 1 39 | // 1 0 40 | // 0 1 0 41 | unique_ptr> root = 42 | unique_ptr>(new BinaryTreeNode{1, nullptr, nullptr}); 43 | root->left = 44 | unique_ptr>(new BinaryTreeNode{1, nullptr, nullptr}); 45 | root->left->left = 46 | unique_ptr>(new BinaryTreeNode{0, nullptr, nullptr}); 47 | root->right = 48 | unique_ptr>(new BinaryTreeNode{0, nullptr, nullptr}); 49 | root->right->left = 50 | unique_ptr>(new BinaryTreeNode{1, nullptr, nullptr}); 51 | root->right->right = 52 | unique_ptr>(new BinaryTreeNode{0, nullptr, nullptr}); 53 | auto res = sum_root_to_leaf(root); 54 | assert(res == 15); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /swap_bits.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "./swap_bits.h" 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::numeric_limits; 14 | using std::random_device; 15 | using std::uniform_int_distribution; 16 | 17 | 18 | void simple_test() { 19 | assert(swap_bits(47, 1, 4) == 61); 20 | assert(swap_bits(28, 0, 2) == 25); 21 | } 22 | 23 | int main(int argc, char *argv[]) { 24 | simple_test(); 25 | default_random_engine gen((random_device())()); 26 | long x; 27 | int i, j; 28 | if (argc == 4) { 29 | x = atol(argv[1]), i = atoi(argv[2]), j = atoi(argv[3]); 30 | } else { 31 | uniform_int_distribution dis(0, numeric_limits::max()); 32 | x = dis(gen); 33 | uniform_int_distribution digit_dis(0, 63); 34 | i = digit_dis(gen), j = digit_dis(gen); 35 | } 36 | cout << "x = " << x << ", i = " << i << ", j = " << j << endl; 37 | cout << swap_bits(x, i, j) << endl; 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /swap_bits.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #ifndef SOLUTIONS_SWAP_BITS_H_ 4 | #define SOLUTIONS_SWAP_BITS_H_ 5 | 6 | // @include 7 | long swap_bits(long x, int i, int j) { 8 | if (((x >> i) & 1) != ((x >> j) & 1)) { 9 | x ^= (1L << i) | (1L << j); 10 | } 11 | return x; 12 | } 13 | // @exclude 14 | #endif // SOLUTIONS_SWAP_BITS_H_ 15 | -------------------------------------------------------------------------------- /tmp.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int evalRPN(const vector &tokens) { 7 | stack s; 8 | while (const auto& t : tokens) { 9 | if (isdigit(t.front()) { 10 | s.push(stoi(t)); 11 | } else { 12 | int a = s.top(); 13 | s.pop(); 14 | int b = s.top(); 15 | s.pop(); 16 | if (!t.compare(t, "+")) { 17 | s.push(a + b); 18 | } else if (!t.compare(t, "-")) { 19 | s.push(a - b); 20 | } else if (!t.compare(t, "*")) { 21 | s.push(a * b); 22 | } else { 23 | s.push(a / b); 24 | } 25 | } 26 | } 27 | return s.top(); 28 | } 29 | 30 | int main(int argc, char* argv) { 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /tower_hanoi.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::array; 9 | using std::cout; 10 | using std::default_random_engine; 11 | using std::endl; 12 | using std::random_device; 13 | using std::stack; 14 | using std::uniform_int_distribution; 15 | 16 | void transfer(int n, array, 3>& pegs, int from, int to, int use); 17 | 18 | // @include 19 | void move_tower_hanoi(int n) { 20 | array, 3> pegs; 21 | // Initialize pegs. 22 | for (int i = n; i >= 1; --i) { 23 | pegs[0].push(i); 24 | } 25 | 26 | transfer(n, pegs, 0, 1, 2); 27 | } 28 | 29 | void transfer(int n, array, 3>& pegs, int from, int to, int use) { 30 | if (n > 0) { 31 | transfer(n - 1, pegs, from, use, to); 32 | pegs[to].push(pegs[from].top()); 33 | pegs[from].pop(); 34 | cout << "Move from peg " << from << " to peg " << to << endl; 35 | transfer(n - 1, pegs, use, to, from); 36 | } 37 | } 38 | // @exclude 39 | 40 | int main(int argc, char* argv[]) { 41 | int n; 42 | if (argc == 2) { 43 | n = atoi(argv[1]); 44 | } else { 45 | default_random_engine gen((random_device())()); 46 | uniform_int_distribution dis(1, 10); 47 | n = dis(gen); 48 | } 49 | cout << "n = " << n << endl; 50 | move_tower_hanoi(n); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /triangle.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::endl; 10 | using std::min; 11 | using std::vector; 12 | 13 | // @include 14 | int find_minimum_total(const vector>& triangle) { 15 | if (triangle.empty()) { 16 | return 0; 17 | } 18 | 19 | // Stores the minimum path sum of triangle[i - 1]. 20 | vector prev_row(triangle.front()); 21 | for (size_t i = 1; i < triangle.size(); ++i) { 22 | // Stores the minimum path sum of triangle[i]. 23 | vector curr_row(triangle[i]); 24 | curr_row.front() += prev_row.front(); // for the first element. 25 | for (size_t j = 1; j < curr_row.size() - 1; ++j) { 26 | curr_row[j] += min(prev_row[j - 1], prev_row[j]); 27 | } 28 | curr_row.back() += prev_row.back(); // for the last element. 29 | 30 | prev_row.swap(curr_row); // swaps the contents of prev_row and curr_row. 31 | } 32 | return *min_element(prev_row.cbegin(), prev_row.cend()); 33 | } 34 | // @exclude 35 | 36 | int main(int argc, char** argv) { 37 | vector> A = {{2}, {3, 4}, {6, 5, 7}, {4, 1, 8, 3}}; 38 | assert(11 == find_minimum_total(A)); 39 | return 0; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /unique-binary-trees.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::default_random_engine; 12 | using std::endl; 13 | using std::random_device; 14 | using std::string; 15 | using std::stoi; 16 | using std::uniform_int_distribution; 17 | using std::vector; 18 | 19 | // @include 20 | int num_unique_binary_trees(int n) { 21 | vector num(n + 1, 0); 22 | num[0] = 1; 23 | for (int i = 1; i <= n; ++i) { 24 | for (int j = 0; j < i; ++j) { 25 | num[i] += num[j] * num[i - j - 1]; 26 | } 27 | } 28 | return num.back(); 29 | } 30 | // @exclude 31 | 32 | int main(int argc, char** argv) { 33 | assert(16796 == num_unique_binary_trees(10)); 34 | assert(4862 == num_unique_binary_trees(9)); 35 | assert(2 == num_unique_binary_trees(2)); 36 | assert(5 == num_unique_binary_trees(3)); 37 | default_random_engine gen((random_device())()); 38 | int n; 39 | if (argc == 2) { 40 | n = stoi(argv[1]); 41 | } else { 42 | uniform_int_distribution dis(1, 15); 43 | n = dis(gen); 44 | } 45 | cout << "n = " << n << endl; 46 | cout << num_unique_binary_trees(n) << endl; 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /valid-palindrome.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::cout; 9 | using std::endl; 10 | using std::string; 11 | 12 | // @include 13 | bool is_palindrome(const string& s) { 14 | int i = 0, j = s.size() - 1; 15 | while (i < j) { 16 | while (!isalnum(s[i]) && i < j) { 17 | ++i; 18 | } 19 | while (!isalnum(s[j]) && i < j) { 20 | --j; 21 | } 22 | if (tolower(s[i]) != tolower(s[j])) { 23 | return false; 24 | } 25 | ++i, --j; 26 | } 27 | return true; 28 | } 29 | // @exclude 30 | 31 | int main(int argc, char** argv) { 32 | assert(is_palindrome("A man, a plan, a canal: Panama")); 33 | assert(!is_palindrome("race a car")); 34 | assert(is_palindrome("")); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /valid-parentheses.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Elements of Programming Interviews. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::boolalpha; 9 | using std::cout; 10 | using std::endl; 11 | using std::stack; 12 | using std::string; 13 | 14 | // @include 15 | bool is_valid_parentheses(const string& s) { 16 | stack left_parens; 17 | for (size_t i = 0; i < s.size(); ++i) { 18 | if (s[i] == '(' || s[i] == '{' || s[i] == '[') { 19 | left_parens.emplace(s[i]); 20 | } else { 21 | if (left_parens.empty()) { 22 | return false; // no left paren. 23 | } 24 | if ((s[i] == ')' && left_parens.top() != '(') || 25 | (s[i] == '}' && left_parens.top() != '{') || 26 | (s[i] == ']' && left_parens.top() != '[')) { 27 | return false; // unmatched left paren. 28 | } 29 | left_parens.pop(); 30 | } 31 | } 32 | return left_parens.empty(); 33 | } 34 | // @exclude 35 | 36 | void small_test() { 37 | assert(is_valid_parentheses("()")); 38 | assert(is_valid_parentheses("()[]{}")); 39 | assert(is_valid_parentheses("[()[]]{}")); 40 | assert(is_valid_parentheses("(()[]{()[]{}{}})")); 41 | assert(!is_valid_parentheses("([)]")); 42 | assert(!is_valid_parentheses("[")); 43 | assert(!is_valid_parentheses("(()[]{()[]{})({}})")); 44 | } 45 | 46 | int main(int argc, char** argv) { 47 | small_test(); 48 | if (argc == 2) { 49 | cout << boolalpha << is_valid_parentheses(argv[1]) << endl; 50 | } 51 | return 0; 52 | } 53 | --------------------------------------------------------------------------------