├── .gitignore ├── DynamicStackBaseArray.java ├── LICENSE ├── README.md ├── StackBaseArray.java ├── c-cpp ├── .gitignore ├── .gitkeep ├── 05_array │ ├── .gitkeep │ ├── Array_gp.c │ ├── Array_gp.h │ └── array.c ├── 06_linkedlist │ ├── .gitkeep │ ├── Dlist │ │ ├── Dlist.c │ │ └── Dlist.h │ ├── LRUBasedLinkedList.cpp │ ├── list_isPalindrome │ │ ├── LinkList.cpp │ │ ├── LinkList.h │ │ └── main.cpp │ ├── palindromeList │ │ ├── LinkedList.hpp │ │ ├── ListNode.hpp │ │ └── palindromeList.cpp │ ├── single_list.c │ └── singlelist_gc │ │ ├── singleList.c │ │ └── singleList.h ├── 07_linkedlist │ ├── .gitkeep │ ├── LinkedListAlgo.c │ ├── SingleList.cpp │ ├── linked_list.h │ ├── linked_list_algo.hpp │ └── linklist_jinshaohui.c ├── 08_stack │ ├── StackBasedOnArray │ │ ├── StackBasedOnArray.cpp │ │ └── StackBasedOnArray.h │ ├── StackBasedOnLinkedList │ │ ├── StackBasedOnLinkedList.cpp │ │ └── StackBasedOnLinkedList.h │ ├── arrayStack │ │ ├── arrayStack.c │ │ └── arrayStack.h │ ├── linkList │ │ ├── linklist_stack.c │ │ └── linklist_stack.h │ ├── linked_list.h │ └── stack_based_on_linked_list.hpp ├── 09_queue │ ├── .gitkeep │ ├── array_queue.hpp │ ├── array_queue │ │ ├── array_queue.c │ │ └── array_queue.h │ ├── array_queue_test.cc │ ├── block_queue.hpp │ ├── circular_queue.hpp │ ├── circular_queue_test.cc │ ├── concurrency_queue.hpp │ ├── dynamic_array_queue.hpp │ ├── dynamic_array_queue_test.cc │ ├── linked_queue.hpp │ ├── linked_queue_test.cc │ ├── list_queue │ │ ├── list_queue.c │ │ └── list_queue.h │ ├── lock_free_queue.hpp │ └── ring_queue.c ├── 10_recursive │ ├── .gitkeep │ ├── one_two_step.c │ └── one_two_step.cc ├── 11_sorts │ ├── .gitkeep │ ├── sorts.c │ ├── sorts.cpp │ ├── sorts.hpp │ ├── sorts_jinshaohui.c │ └── sorts_test.cc ├── 12_sorts │ ├── .gitkeep │ ├── merge_sort.c │ ├── merge_sort.hpp │ ├── merge_sort_test.cc │ ├── my12_sorts │ │ ├── merge_sort.c │ │ └── quick_sort.c │ ├── quick_sort.c │ ├── quick_sort.hpp │ └── quick_sort_test.cc ├── 13_sorts │ ├── .gitkeep │ ├── bucket_sort.hpp │ ├── bucket_sort_test.cc │ ├── counting_sort.hpp │ ├── counting_sort_test.cc │ └── sort.c ├── 14_sorts │ ├── .gitkeep │ ├── analytics_of_std_sort.md │ └── counting_sort.c ├── 15_bsearch │ ├── .gitkeep │ ├── binary_search.c │ ├── bsearch.hpp │ ├── bsearch_c │ │ ├── bsearch.c │ │ └── sqrt.c │ └── bsearch_test.cc ├── 16_bsearch │ ├── .gitkeep │ ├── bsearch.c │ ├── bsearch_variant.c │ ├── bsearch_varients.hpp │ └── bsearch_varients_test.cc ├── 17_skiplist │ ├── .gitkeep │ ├── SkipList.cpp │ ├── skiplist.c │ ├── skiplist.hpp │ ├── skiplist_c │ │ ├── skiplist.c │ │ └── skiplist.h │ ├── skiplist_test.cc │ ├── skiplist_tr.hpp │ └── skiplist_tr_test.cc ├── 18_hashtable │ ├── .gitkeep │ ├── hash_map.cc │ ├── hashtable.c │ └── listhash │ │ ├── listhash.c │ │ └── listhash.h ├── 19_Dlisthash │ ├── Dlist.h │ ├── LinkedHashMap.c │ └── LinkedHashMap.h ├── 23_binarytree │ ├── binarytree.c │ └── tree │ │ ├── binarytree.c │ │ ├── list_queue.c │ │ └── list_queue.h ├── 24_binarysearchtree │ ├── binary_search_tree.cpp │ ├── binarysearchtree.c │ ├── binarysearchtree.h │ └── bst.c ├── 24_tree │ ├── Trie.c │ └── binarysearchtree.c ├── 28_heap │ └── heap.c ├── 30_Graph │ └── graph.c └── bst.c ├── csharp ├── 05-array │ ├── Array.cs │ └── algo05_array.csproj ├── 06-linkedlist │ ├── LRUWithArray.cs │ ├── LRUWithLinkedList.cs │ ├── LRU缓存实现思路.txt │ ├── SingleLinkedList.cs │ └── algo06_linked_list.csproj ├── 07-linkedlist │ └── _07_linkedlist │ │ ├── SingleLinkedListAlgo.cs │ │ └── algo07_linkedlist.csproj ├── 08-stack │ └── algo08_stack │ │ ├── ArrayStack.cs │ │ ├── LinkedStack.cs │ │ ├── LinkedStackBrowser.cs │ │ └── algo08_stack.csproj ├── Tests │ ├── _05_array_tests │ │ ├── Array.Tests.cs │ │ └── algo05_array_tests.csproj │ ├── _06_linkedlist_tests │ │ ├── BaseLinkedListTests.cs │ │ ├── LRUWithArray.Tests.cs │ │ ├── LRUWithLinkedList.Tests.cs │ │ ├── SingleLinkedList.Tests.cs │ │ └── algo06_linkedlist_tests.csproj │ ├── _07_linkedlist_tests │ │ ├── SingleLinkedListAlgo.Tests.cs │ │ └── algo07_linkedlist_tests.csproj │ └── algo08_stack_tests │ │ ├── ArrayStack.Tests.cs │ │ ├── LinkedStack.Tests.cs │ │ ├── LinkedStackBrowser.Tests.cs │ │ └── algo08_stack_tests.csproj ├── csharp.sln └── csharp.sln.DotSettings.user ├── f21 ├── go ├── .gitkeep ├── 05_array │ ├── .gitkeep │ ├── array.go │ └── array_test.go ├── 06_linkedlist │ ├── .gitkeep │ ├── palindrome-linked-list.go │ ├── palindrome.go │ ├── palindrome_test.go │ ├── singlelinkedlist.go │ └── singlelinkedlist_test.go ├── 07_linkedlist │ ├── .gitkeep │ ├── main.go │ └── main_test.go ├── 08_stack │ ├── SimpleBrowser.go │ ├── SimpleBrowser_test.go │ ├── StackBasedOnArray.go │ ├── StackBasedOnArray_test.go │ ├── StackBasedOnLinkedList.go │ ├── StackBasedOnLinkedList_test.go │ └── StatckInterface.go ├── 09_queue │ ├── CircularQueue.go │ ├── CircularQueue_test.go │ ├── QueueBasedOnArray.go │ ├── QueueBasedOnArray_test.go │ ├── QueueBasedOnLinkedList.go │ └── QueueBasedOnLinkedList_test.go ├── 10_recursion │ ├── Factorial.go │ ├── Factorial_test.go │ ├── Fibonacci.go │ ├── Fibonacci_test.go │ ├── RangAll.go │ └── RangAll_test.go ├── 11_sorts │ ├── Sort.go │ └── Sort_test.go ├── 12_sorts │ ├── MergeSort.go │ ├── MergeSort_test.go │ ├── QuickSort.go │ └── QuickSort_test.go ├── 13_sorts │ ├── BucketSort.go │ └── BucketSort_test.go ├── 14_sorts │ ├── CountingSort.go │ └── CountingSort_test.go ├── 15_binarysearch │ ├── binarysearch.go │ └── binarysearch_test.go ├── 17_skiplist │ ├── skiplist.go │ └── skiplist_test.go ├── 20_lru │ ├── lru_cache.go │ └── lru_cache_test.go ├── 23_binarytree │ ├── binarytree.go │ └── binarytree_test.go ├── 24_tree │ ├── BinarySearchTree.go │ ├── BinarySearchTree_test.go │ ├── BinaryTree.go │ ├── BinaryTree_test.go │ ├── StackBasedOnArray.go │ └── TreeNode.go ├── 28_heap │ ├── heap.go │ └── heap_sort.go ├── 29_priority_queue │ ├── heap.go │ ├── heap_test.go │ ├── priority_queue.go │ ├── priority_queue_test.go │ └── readme.md ├── 31_graph │ └── graph_search.go ├── 32_string │ ├── string_bf.go │ └── string_bm.go ├── 34_kmp │ └── kmp.go ├── 41_dynamic_programming │ ├── backtracking │ │ ├── leastcoins.go │ │ └── leastcoins_test.go │ └── dp │ │ ├── leastcoins.go │ │ └── leastcoins_test.go ├── 42_dynamic_programming │ └── longest_common_substring.go ├── 45_bitmap │ ├── bitmap.go │ └── bitmap_test.go └── binarysearch2.go ├── java ├── 05_array │ ├── .gitkeep │ ├── Array.java │ └── GenericArray.java ├── 06_linkedlist │ ├── .gitkeep │ ├── LRUBaseLinkedList.java │ ├── LRUBasedArray.java │ └── SinglyLinkedList.java ├── 07_linkedlist │ ├── .gitkeep │ └── LinkedListAlgo.java ├── 08_stack │ ├── SampleBrowser.java │ └── StackBasedOnLinkedList.java ├── 09_queue │ ├── ArrayQueue.java │ ├── CircularQueue.java │ ├── DynamicArrayQueue.java │ └── QueueBasedOnLinkedList.java ├── 11_sorts │ ├── InsertionSortAdd.java │ ├── Sorts.java │ └── SortsAddOn.java ├── 12_sorts │ ├── KthSmallest.java │ ├── MergeSort.java │ ├── QuickSort.java │ └── Sorts.java ├── 13_sorts │ ├── BucketSort.java │ ├── CountingSort.java │ └── RadixSort.java ├── 17_skiplist │ ├── SkipList.java │ └── SkipList2.java ├── 18_hashtable │ └── HashTable.java ├── 20_hashtable │ └── LRUBaseHashTable.java ├── 24_tree │ └── BinarySearchTree.java ├── 28_sorts │ └── HeapSort.java ├── 30_graph │ └── Graph.java ├── 32_BFRK └── 36_ac_automata │ └── ACAutoMata.java ├── javascript ├── .gitkeep ├── 05_array │ ├── .gitkeep │ └── Array.md ├── 06_linkedlist │ ├── .gitkeep │ └── SinglyLinkedList.js ├── 07_linkedlist │ ├── .gitkeep │ └── LinkedListAlgo.js ├── 08_stack │ ├── SampleBrowser.js │ └── StackBasedOnLinkedList.js ├── 09_queue │ ├── CircularQueueBasedOnLinkedList.js │ └── QueueBasedOnLinkedList.js ├── 11_sorts │ └── sort.js ├── 12_sorts │ ├── KthNum.js │ ├── MergeSort.js │ └── QuickSort.js ├── 13_sorts │ ├── bucketSort.js │ └── countingSort.js ├── 15_binary │ └── binaryFind.js ├── 16_binary │ └── binary-find.js ├── 17_skiplist │ └── SkipList.js ├── 18_hashmap │ └── HashTable.html ├── 19_hashTable │ └── hashtable.js ├── 23_tree │ └── binary_tree.js ├── 28_heapsort │ ├── heap-sort.js │ └── heap.js ├── 35_trie │ └── trie.js ├── 36_ac_automata │ ├── ac_automata.js │ └── ac_automata_unicode.js ├── 42_dynamic_programming │ └── levenshtein_distance.js ├── 43_topological_sorting │ └── dsf.js └── 45_bitmap │ └── bitmap.js ├── kotlin ├── 05_array │ ├── ArrayKt.kt │ └── DynamicArray.kt ├── 06_linkedlist │ └── SinglyLinkedList.kt ├── 07_linkedlist │ └── LinkedListAlgo.kt └── 08_stack │ └── StackBasedOnLinkedList.kt ├── notes ├── .gitkeep ├── 10_recursion │ └── readme.md ├── 11_sorts │ └── readme.md ├── 12_sorts │ ├── .gitkeep │ └── readme.md ├── 13_sorts │ ├── .gitkeep │ └── readme.md ├── 14_sorts │ ├── .gitkeep │ └── readme.md ├── 15_bsearch │ ├── .gitkeep │ └── readme.md ├── 16_bsearch │ ├── .gitkeep │ └── readme.md ├── 17_skiplist │ ├── .gitkeep │ └── readme.md ├── 18_hashtable │ ├── .gitkeep │ └── readme.md ├── 19_hashtable │ ├── .gitkeep │ └── readme.md └── 20_hashtable │ ├── .gitkeep │ └── readme.md ├── object-c ├── .gitkeep ├── 05_array │ ├── .gitkeep │ ├── MyArray.h │ └── MyArray.m ├── 06_linkedlist │ ├── .gitkeep │ ├── ListNode.h │ ├── ListNode.m │ ├── SinglyLinkedList.h │ ├── SinglyLinkedList.m │ └── SinglyLinkedListTests.m ├── 07_linkedlist │ └── .gitkeep ├── 08_stack │ ├── LinkedStack.h │ ├── LinkedStack.m │ ├── LinkedStackTests.m │ ├── ListNode.h │ ├── ListNode.m │ └── stack_practice │ │ ├── ArrayStack.h │ │ ├── ArrayStack.m │ │ ├── BalancedParentheses.h │ │ ├── BalancedParentheses.m │ │ ├── FourOperation.h │ │ ├── FourOperation.m │ │ └── main.m ├── 11_Sort │ ├── Sort.h │ └── Sort.m └── 33_bm_match │ ├── BM.h │ ├── BM.m │ └── main.m ├── php ├── .gitignore ├── 05_array │ ├── .gitkeep │ ├── array.php │ └── array_test.php ├── 06_linkedlist │ ├── .gitkeep │ ├── SingleLinkedList.php │ ├── SingleLinkedListNode.php │ └── main.php ├── 07_linkedlist │ ├── .gitkeep │ └── main.php ├── 08_stack │ ├── .gitkeep │ ├── Compute.php │ ├── StackOnLinkedList.php │ └── main.php ├── 09_queue │ ├── QueueOnLinkedList.php │ ├── Sequential.php │ └── main.php ├── 10_heap │ ├── Heap.php │ ├── findmiddle.php │ ├── main.php │ └── topn.php ├── 11_sort │ └── Sort.php ├── 12_sort │ ├── mergeSort.php │ └── quicksort.php ├── 13_sort │ ├── bucketSort.php │ ├── countingSort.php │ └── radixSort.php ├── 15_binary │ └── binary.php ├── 16_binary │ └── binary.php ├── 17_skiplist │ └── skipList.php ├── 24_tree │ ├── Tree.php │ ├── TreeNode.php │ ├── levelOrder.php │ └── main.php ├── 38_divide_and_conquer │ └── matrix_production.php ├── 39_backtracking │ └── queens.php ├── README.md ├── Stack │ └── Compute.php ├── buildAutoLoad.sh └── composer.json ├── python ├── .gitkeep ├── .vs │ └── slnx.sqlite ├── 05_array │ ├── .gitkeep │ └── myarray.py ├── 06_linkedlist │ ├── .gitkeep │ ├── LRUCache.py │ ├── palindrome.py │ ├── singlyLinkedList.py │ └── singly_linked_list.py ├── 07_linkedlist │ ├── .gitkeep │ └── linked_list_algo.py ├── 08_stack │ ├── linked_stack.py │ └── simple_browser.py ├── 09_queue │ ├── array_queue.py │ ├── circular_queue.py │ ├── dynamic_array_queue.py │ └── linked_queue.py ├── 11_sorts │ └── sorts.py ├── 12_sorts │ ├── merge_sort.py │ ├── quick_sort.py │ └── quicksort_twoway.py ├── 14_sorts │ └── counting_sort.py ├── 15_bsearch │ ├── bsearch.py │ └── bsearch_recursion.py ├── 16_bsearch │ └── bsearch_variants.py ├── 17_skiplist │ ├── skip_list.py │ └── skip_list_comments.py ├── 23_binarytree │ ├── binary_search_tree.py │ └── binary_tree.py ├── 24_tree │ └── binary_search_tree.py ├── 26_red_black_tree │ └── red_black_tree.py ├── 28_binary_heap │ ├── binary_heap.py │ ├── binary_heap_sort.py │ ├── heap.py │ ├── priority_queue.py │ └── top_k.py ├── 28_heap │ ├── heap.py │ └── min_heap.py ├── 31_bfs_dfs │ ├── bfs_dfs.py │ ├── graph.py │ └── graph_application.py ├── 32_bf_rk │ └── bf_rk.py ├── 33_bm │ ├── bm.py │ └── bm_.py ├── 34_kmp │ ├── kmp.py │ └── kmp_.py ├── 35_trie │ ├── trie.py │ └── trie_.py ├── 36_ac_automata │ ├── ac_automata.py │ └── ac_automata_.py ├── 38_divide_and_conquer │ └── merge_sort_counting.py ├── 39_back_track │ ├── 01_bag.py │ ├── eight_queens.py │ ├── permutations.py │ └── regex.py ├── 39_backtracking │ └── backtracking.py ├── 40_dynamic_programming │ ├── 01_bag.py │ ├── knapsack.py │ └── yh_triangle.py ├── 41_dynamic_programming │ ├── coins_problem.py │ └── min_dist.py ├── 42_dynamic_programming │ ├── longest_increasing_subsequence.py │ └── min_edit_dist.py ├── 43_topological_sorting │ └── topological_sorting.py ├── 44_shortest_path │ ├── dijkstra.py │ └── shortest_path.py ├── 45_bitmap │ └── bitmap.py └── array.py ├── rust ├── 05_array │ └── main.rs ├── 07_linkedlist │ ├── linked_list_cycle.rs │ ├── merge_two_sorted_lists.rs │ ├── middle_of_the_linked_list.rs │ ├── remove_nth_node_from_end_of_list.rs │ ├── reverse_linked_list.rs │ └── util │ │ └── linked_list.rs ├── 08_stack │ ├── simple_browser.rs │ ├── stack_based_on_array.rs │ └── stack_based_on_linked_list.rs ├── 09_queue │ ├── array_queue.rs │ ├── circle_queue.rs │ └── linked_list_queue.rs ├── 11_sorts │ ├── bubble_sort.rs │ ├── insertion_sort.rs │ └── selection_sort.rs ├── 12_sorts │ ├── kth_largest.rs │ ├── merge_sort.rs │ └── quick_sort.rs ├── 13_sorts │ ├── bucket_sort.rs │ ├── counting_sort.rs │ ├── radix_sort.rs │ └── sort_string.rs ├── 15_binary_search │ ├── binary_search.rs │ └── sqrtx.rs ├── 16_binary_search │ ├── binary_search.rs │ └── search_in_rotated_sorted_array.rs ├── 19_hash_table │ └── hash_table.rs ├── 23_binary_tree │ ├── inorder_traversal.rs │ ├── level_order_traversal.rs │ ├── postorder_traversal.rs │ ├── preorder_traversal.rs │ └── util │ │ └── tree.rs ├── 24_binary_tree │ ├── insert_in_binary_tree.rs │ ├── max_depth_in_binary_tree.rs │ ├── search_in_binary_tree.rs │ └── util │ │ └── tree.rs ├── 28_heap │ ├── build_heap.rs │ ├── heap.rs │ └── sort_heap.rs ├── 29_heap │ ├── get_median.rs │ ├── get_top_k.rs │ └── merge_sorted_array.rs ├── 31_graph │ └── graph_search.rs ├── 32_string │ └── bf_rk.rs ├── 33_string │ └── bm.rs ├── 34_string │ └── kmp.rs ├── 35_trie │ └── trie.rs ├── 38_divide_and_conquer │ └── merge_sort_count.rs ├── 39_back_tracking │ ├── bag.rs │ ├── bag_exec.rs │ ├── n_queens.rs │ └── regex.rs ├── 40_dynamic_programming │ ├── bag.rs │ ├── knapsack.rs │ └── triangle.rs ├── 41_dynamic_programming │ ├── coin_change.rs │ └── min_dis_path.rs └── 42_dynamic_programming │ ├── edit_distance.rs │ └── longest_increasing_subsequence.rs ├── scala ├── .gitignore ├── build.sbt ├── project │ └── build.properties └── src │ ├── main │ └── scala │ │ ├── ch05_array │ │ └── ArrayDemo.scala │ │ ├── ch06_linkedlist │ │ └── SinglyLinkedList.scala │ │ ├── ch07_linkedlist │ │ └── LinkedListAlgo.scala │ │ ├── ch08_stack │ │ ├── BrowserDemo.scala │ │ └── StackDemo.scala │ │ ├── ch09_queue │ │ ├── ArrayQueue.scala │ │ ├── CircularQueue.scala │ │ ├── DemoQueue.scala │ │ ├── DynamicArrayQueue.scala │ │ └── LinkedListQueue.scala │ │ ├── ch10_recursive │ │ └── RecursiveDemo.scala │ │ ├── ch11_sorts │ │ └── Sorts.scala │ │ ├── ch12_sorts │ │ ├── MergeSort.scala │ │ └── QuickSort.scala │ │ ├── ch15_bsearch │ │ ├── BSearch.scala │ │ └── BSearchRecursive.scala │ │ ├── ch16_bsearch │ │ └── BSearch.scala │ │ ├── ch17_skip_list │ │ └── SkipList.scala │ │ ├── ch20_linked_hash_map │ │ └── LRUCache.scala │ │ ├── ch23_binary_tree │ │ └── BinaryTree.scala │ │ ├── ch24_binary_search_tree │ │ └── BinarySearchTree.scala │ │ ├── ch28_heap │ │ └── Heap.scala │ │ ├── ch29_heap_solutions │ │ ├── FileMerger.scala │ │ ├── MiddleNumberKeeper.scala │ │ └── TopKItemsKeeper.scala │ │ ├── ch31_graph │ │ └── Graph.scala │ │ ├── ch32_matching │ │ ├── BruteForce.scala │ │ └── RabinKarp.scala │ │ ├── ch35_tire_tree │ │ └── TrieTree.scala │ │ ├── ch39_back_tracking │ │ ├── BagWeight.scala │ │ ├── EightQueens.scala │ │ ├── NQueens.scala │ │ └── Sudoku.scala │ │ └── ch43_topology_sort │ │ └── GraphTopology.scala │ └── test │ └── scala │ ├── ch05_array │ └── ArrayDemoSpec.scala │ ├── ch06_linkedlist │ ├── NodeTest.scala │ └── SinglyLinkedListTest.scala │ ├── ch07_linkedlist │ └── LinkedListAlgoTest.scala │ ├── ch08_stack │ ├── BrowserDemoTest.scala │ └── StackDemoTest.scala │ ├── ch09_queue │ ├── ArrayQueueTest.scala │ ├── CircularQueueTest.scala │ ├── DemoQueueTest.scala │ ├── DynamicArrayQueueTest.scala │ └── LinkedListQueueTest.scala │ ├── ch10_recursive │ └── RecursiveDemoTest.scala │ ├── ch11_sorts │ └── SortsTest.scala │ ├── ch12_sorts │ ├── MergeSortTest.scala │ └── QuickSortTest.scala │ ├── ch15_bsearch │ ├── BSearchRecursiveTest.scala │ └── BSearchTest.scala │ ├── ch16_bsearch │ └── BSearchTest.scala │ ├── ch17_skip_list │ └── SkipListTest.scala │ ├── ch20_linked_hash_map │ └── LRUCacheTest.scala │ ├── ch23_binary_tree │ └── BinaryTreeTest.scala │ ├── ch24_binary_search_tree │ └── BinarySearchTreeTest.scala │ ├── ch28_heap │ └── HeapTest.scala │ ├── ch29_heap_solutions │ ├── FileMergerTest.scala │ ├── MiddleNumberKeeperTest.scala │ └── TopKItemsKeeperTest.scala │ ├── ch31_graph │ └── GraphTest.scala │ ├── ch32_matching │ ├── BruteForceTest.scala │ └── RabinKarpTest.scala │ ├── ch35_tire_tree │ └── TrieTreeTest.scala │ ├── ch39_back_tracking │ ├── BagWeightTest.scala │ ├── EightQueensTest.scala │ ├── NQueensTest.scala │ └── SudokuTest.scala │ └── ch43_topology_sort │ └── GraphTopologyTest.scala ├── swift ├── 05_array │ └── MyArray.swift ├── 06_linkedlist │ └── SinglyLinkedList.swift ├── 07_linkedlist │ └── LinkedListAlgo.swift ├── 08_stack │ ├── Browser.swift │ ├── BrowserDemo.swift │ ├── Stack.swift │ └── StackBasedOnLinkedList.swift ├── 09_queue │ ├── ArrayQueue.swift │ ├── CircularQueue.swift │ ├── Queue.swift │ └── QueueBasedOnLinkedList.swift ├── 11_sorts │ └── Sorts.swift ├── 12_sorts │ ├── .DS_Store │ ├── QuickSort.swift │ ├── SortsTests.swift │ └── mergeSort.swift └── 14_sorts │ └── CountingSort.swift └── typescript ├── 06_linkedlist ├── LRUCache.ts ├── LinkedList.ts ├── List.ts └── SingleLinkedList.ts ├── 07_linkedlist └── LinkedListAlog.ts ├── 08_stack └── StackAndBrowser.ts ├── 09_queue ├── CircularQueue.ts ├── README.md └── SimpleQueue.ts ├── 10_recursive └── climbStairs.ts ├── 11_sorts └── simpleSort.ts ├── 12_sorts ├── KthNum.ts ├── MergeSort.ts └── quickSort.ts ├── 13_sorts ├── BucketSort.ts └── CountingSort.ts ├── 14_binarysearch └── BinarySearch.ts ├── 15_binarysearch └── BinaryFind.ts ├── 17_skiplist └── SkipList.ts └── 24_treesearch └── TreeSearch.ts /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | *.DS_Store 22 | *.exe 23 | 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | hs_err_pid* 26 | 27 | # editor files 28 | .vscode 29 | .*.swp 30 | 31 | # WebStorm 32 | .idea/ 33 | 34 | # Build results 35 | [Dd]ebug/ 36 | [Dd]ebugPublic/ 37 | [Rr]elease/ 38 | [Rr]eleases/ 39 | x64/ 40 | x86/ 41 | bld/ 42 | [Bb]in/ 43 | [Oo]bj/ 44 | [Ll]og/ 45 | 46 | # Visual Studio 2015/2017 cache/options directory 47 | .vs/ 48 | 49 | **/*.idea 50 | **/*.iml 51 | **/*out 52 | -------------------------------------------------------------------------------- /c-cpp/.gitignore: -------------------------------------------------------------------------------- 1 | # main files 2 | main.* 3 | 4 | # executives 5 | a.out 6 | 7 | # objective files 8 | *.o 9 | *.obj 10 | -------------------------------------------------------------------------------- /c-cpp/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/.gitkeep -------------------------------------------------------------------------------- /c-cpp/05_array/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/05_array/.gitkeep -------------------------------------------------------------------------------- /c-cpp/05_array/Array_gp.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/05_array/Array_gp.h -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/06_linkedlist/.gitkeep -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/Dlist/Dlist.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: Dlist.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-07 6 | > Desc: 7 | ************************************************************************/ 8 | #include 9 | 10 | typedef struct DlistNode //双向链表中每一个节点 11 | { 12 | struct DlistNode *prev; //节点前项指针 13 | struct DlistNode *next; //节点后项指针 14 | int data; //数据 15 | }stDlistNode; 16 | 17 | typedef struct Dlisthead //定义链表总体 18 | { 19 | int size; //链表长度 20 | stDlistNode *head; //头指针 21 | stDlistNode *tail; //尾部指针 22 | }stDlistHead; 23 | 24 | -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/list_isPalindrome/LinkList.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/06_linkedlist/list_isPalindrome/LinkList.cpp -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/list_isPalindrome/LinkList.h: -------------------------------------------------------------------------------- 1 | #ifndef LINKLIST_H 2 | #define LINKLIST_H 3 | 4 | #include 5 | #include 6 | typedef char ElemType; 7 | typedef struct LNode 8 | { 9 | ElemType data; 10 | struct LNode*next; 11 | }LinkList; 12 | 13 | void CreateListHead(LinkList *&L,ElemType a[],int n); 14 | void CreateListTail(LinkList *&L,ElemType a[],int n); 15 | void InitList(LinkList *&L); 16 | void DestroyList(LinkList *&L); 17 | bool ListEmpty(LinkList *L); 18 | int ListLength(LinkList *L); 19 | void ShowList(LinkList *L); 20 | bool GetListElem(LinkList *L,int i,ElemType &e); 21 | int LocateElem(LinkList*L,ElemType e); 22 | bool ListInsert(LinkList *&L,int i,ElemType e); 23 | bool ListDelete(LinkList *&L,int i,ElemType &e); 24 | #endif 25 | -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/list_isPalindrome/main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/06_linkedlist/list_isPalindrome/main.cpp -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/palindromeList/ListNode.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: TripleZ 3 | * Date: 2018-10-10 4 | * Brief: ListNode class. 5 | */ 6 | 7 | #ifndef _LISTNODE_HPP_ 8 | #define _LISTNODE_HPP_ 9 | 10 | class ListNode { 11 | public: 12 | int val; 13 | ListNode *next; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/singlelist_gc/singleList.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/06_linkedlist/singlelist_gc/singleList.c -------------------------------------------------------------------------------- /c-cpp/07_linkedlist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/07_linkedlist/.gitkeep -------------------------------------------------------------------------------- /c-cpp/07_linkedlist/SingleList.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/07_linkedlist/SingleList.cpp -------------------------------------------------------------------------------- /c-cpp/07_linkedlist/linked_list.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 单链表 3 | * 4 | * Author: Liam Huang (Liam0205) 5 | */ 6 | 7 | #ifndef LINKEDLIST_LINKED_LIST_H_ 8 | #define LINKEDLIST_LINKED_LIST_H_ 9 | 10 | #include 11 | 12 | template 13 | struct Node { 14 | using ptr_t = std::shared_ptr>; 15 | T data; 16 | ptr_t next; 17 | 18 | Node(T data_) : data(data_), next(nullptr) {} 19 | Node() : next(nullptr) {} 20 | }; 21 | 22 | #endif // LINKEDLIST_LINKED_LIST_H_ 23 | -------------------------------------------------------------------------------- /c-cpp/08_stack/StackBasedOnArray/StackBasedOnArray.h: -------------------------------------------------------------------------------- 1 | 2 | // 类模板的声明(line 3),类模板实例化后就是模板类 3 | // 类模板声明的写法 template class 类名{} 4 | template class ArrayStack 5 | { 6 | public: 7 | ArrayStack(); 8 | ArrayStack(int count); 9 | ~ArrayStack(); 10 | void push(T data); //入栈 11 | T pop(); //出栈,并删除栈顶元素 12 | T peek(); //返回栈顶元素,不删除栈顶元素,栈顶指针不变 13 | int stackSize(); 14 | int stackMaxSize(); 15 | 16 | private: 17 | int flag; //栈顶标签,指向栈顶 18 | int count ; //栈的容量 19 | T *array; //指针 20 | }; 21 | -------------------------------------------------------------------------------- /c-cpp/08_stack/StackBasedOnLinkedList/StackBasedOnLinkedList.h: -------------------------------------------------------------------------------- 1 | // 类模板的声明,关键字 class 也可以更换成 typename 2 | template class LinkedListStack 3 | { 4 | public: 5 | LinkedListStack(); 6 | ~LinkedListStack(); 7 | 8 | void push(const T & data); //入栈 9 | T peek(); //返回栈顶元素,即出栈,不删除栈顶元素 10 | T pop(); //出栈,删除栈顶元素 11 | int size() const; //返回栈的大小 12 | private: 13 | int count; //存放栈的大小,因为是单链表所以这里不规定栈的最大可承载量 14 | struct LinkedNode 15 | { 16 | T data; 17 | LinkedNode * next; 18 | }; 19 | LinkedNode * head; // 单链表的头指针,不带头节点 20 | }; 21 | -------------------------------------------------------------------------------- /c-cpp/08_stack/arrayStack/arrayStack.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: arrayStack.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-12 6 | > Desc: 7 | ************************************************************************/ 8 | 9 | #ifndef ARRAY_STACJ_H 10 | #define ARRAY_STACJ_H 11 | 12 | typedef struct _array_stack 13 | { 14 | int size;/*栈的大小*/ 15 | int pos;/*当前存储元素的个数,即栈顶元素下表*/ 16 | int *array;/*数据存储区*/ 17 | }stArrayStack; 18 | 19 | #define arrayStack_size(arrayStack) (arrayStack->size) 20 | #define arrayStack_is_empty(arrayStack) (arrayStack->pos == -1) 21 | #define arrayStack_is_full(arrayStack) (arrayStack->pos == (arrayStack->size-1)) 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /c-cpp/08_stack/linkList/linklist_stack.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: linklist_stack.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-12 6 | > Desc: 7 | ************************************************************************/ 8 | 9 | #ifndef STACK_LINK_LIST_H 10 | #define STACK_LINK_LIST_H 11 | 12 | typedef struct _linkliststack 13 | { 14 | int data; 15 | struct _linkliststack *next; 16 | }linklist_stack; 17 | 18 | 19 | #define stack_is_empty(liststack) (liststack->next == NULL) 20 | 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /c-cpp/08_stack/linked_list.h: -------------------------------------------------------------------------------- 1 | /** 2 | * C++ 版本单链表结点 3 | * 4 | * Author: Liam Huang (Liam0205) 5 | */ 6 | 7 | #ifndef STACK_LINKED_LIST_H_ 8 | #define STACK_LINKED_LIST_H_ 9 | 10 | #include 11 | 12 | template 13 | struct Node { 14 | using ptr_t = std::shared_ptr>; 15 | T data; 16 | ptr_t next; 17 | 18 | Node(T data_) : data(data_), next(nullptr) {} 19 | Node() : next(nullptr) {} 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /c-cpp/09_queue/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/09_queue/.gitkeep -------------------------------------------------------------------------------- /c-cpp/09_queue/array_queue/array_queue.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: array_queue.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-12 6 | > Desc: 7 | ************************************************************************/ 8 | #ifndef ARRAY_QUEUE_H 9 | #define ARRAY_QUEUE_H 10 | 11 | typedef struct _array_queue 12 | { 13 | int size;/*队列的大小*/ 14 | int num; /*当前存储数据的大小*/ 15 | int head;/*队列的头*/ 16 | int tail;/*队列的尾*/ 17 | int *array;/*数据存储区*/ 18 | }array_queue; 19 | 20 | #define array_queue_is_empty(array_queue) (array_queue->num == 0) 21 | #define array_queue_is_full(array_queue) ((array_queue->num) == (array_queue->size)) 22 | 23 | #endif 24 | 25 | -------------------------------------------------------------------------------- /c-cpp/09_queue/list_queue/list_queue.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: list_queue.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-13 6 | > Desc: 7 | ************************************************************************/ 8 | 9 | #ifndef LINK_LIST_QUEUE_H 10 | #define LINK_LIST_QUEUE_H 11 | 12 | typedef struct _list_queue_node 13 | { 14 | int data; 15 | struct _list_queue_node *next; 16 | }queue_node; 17 | 18 | typedef struct _list_queue 19 | { 20 | int num; 21 | queue_node *head; 22 | queue_node *tail; 23 | }list_queue; 24 | 25 | #define list_queue_is_empty(queue) ((queue->num) == 0) 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /c-cpp/10_recursive/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/10_recursive/.gitkeep -------------------------------------------------------------------------------- /c-cpp/10_recursive/one_two_step.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: one_two_step.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-19 6 | > Desc: 7 | ************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | 12 | /*爬楼梯的问题,解决重复计算,采用数据保存方法*/ 13 | 14 | int helper(int n ,int *vlaue) 15 | { 16 | 17 | if(vlaue[n] != 0) 18 | { 19 | return vlaue[n]; 20 | } 21 | 22 | vlaue[n] = helper(n - 1,vlaue) + helper(n - 2,vlaue); 23 | 24 | return vlaue[n]; 25 | } 26 | 27 | int climbStaris(int n) 28 | { 29 | int *vlaue = NULL; 30 | int res = 0; 31 | 32 | vlaue = (int *)malloc(sizeof(int)*(n+1)); 33 | if(vlaue == NULL) 34 | { 35 | return -1; 36 | } 37 | 38 | memset(vlaue,0,sizeof(int)*(n + 1)); 39 | vlaue[0] = 0; 40 | vlaue[1] = 1; 41 | vlaue[2] = 2; 42 | res = helper(n,vlaue); 43 | free(vlaue); 44 | 45 | return res; 46 | } 47 | 48 | int main() 49 | { 50 | 51 | printf("\r\nnum%d ,%d",5,climbStaris(5)); 52 | printf("\r\nnum%d ,%d",6,climbStaris(6)); 53 | printf("\r\nnum%d ,%d",7,climbStaris(7)); 54 | return 0; 55 | } 56 | 57 | 58 | -------------------------------------------------------------------------------- /c-cpp/11_sorts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/11_sorts/.gitkeep -------------------------------------------------------------------------------- /c-cpp/11_sorts/sorts.cpp: -------------------------------------------------------------------------------- 1 | // C program for implementation of selection sort 2 | #include 3 | 4 | void swap(int *xp, int *yp) 5 | { 6 | int temp = *xp; 7 | *xp = *yp; 8 | *yp = temp; 9 | } 10 | 11 | void selectionSort(int arr[], int n) 12 | { 13 | int i, j, min_idx; 14 | 15 | // One by one move boundary of unsorted subarray 16 | for (i = 0; i < n-1; i++) 17 | { 18 | // Find the minimum element in unsorted array 19 | min_idx = i; 20 | for (j = i+1; j < n; j++) 21 | if (arr[j] < arr[min_idx]) 22 | min_idx = j; 23 | 24 | // Swap the found minimum element with the first element 25 | swap(&arr[min_idx], &arr[i]); 26 | } 27 | } 28 | 29 | /* Function to print an array */ 30 | void printArray(int arr[], int size) 31 | { 32 | int i; 33 | for (i=0; i < size; i++) 34 | printf("%d ", arr[i]); 35 | printf("\n"); 36 | } 37 | 38 | // Driver program to test above functions 39 | int main() 40 | { 41 | int arr[] = {64, 25, 12, 22, 11}; 42 | int n = sizeof(arr)/sizeof(arr[0]); 43 | selectionSort(arr, n); 44 | printf("Sorted array: \n"); 45 | printArray(arr, n); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /c-cpp/11_sorts/sorts_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "sorts.hpp" 5 | 6 | int main() { 7 | const std::vector test_data{1, 2, 3, 0}; 8 | 9 | std::vector a(test_data.begin(), test_data.end()); 10 | bubble_sort(a.begin(), a.end()); 11 | for (auto i : a) { 12 | std::cout << i << ' '; 13 | } 14 | std::cout << '\n'; 15 | 16 | std::vector b(test_data.begin(), test_data.end()); 17 | insertion_sort(b.begin(), b.end()); 18 | for (auto i : b) { 19 | std::cout << i << ' '; 20 | } 21 | std::cout << '\n'; 22 | 23 | std::vector c(test_data.begin(), test_data.end()); 24 | selection_sort(c.begin(), c.end()); 25 | for (auto i : c) { 26 | std::cout << i << ' '; 27 | } 28 | std::cout << '\n'; 29 | 30 | std::vector d(test_data.begin(), test_data.end()); 31 | bubble_down_sort(d.begin(), d.end()); 32 | for (auto i : d) { 33 | std::cout << i << ' '; 34 | } 35 | std::cout << '\n'; 36 | 37 | std::vector e(test_data.begin(), test_data.end()); 38 | shell_sort(e.begin(), e.end()); 39 | for (auto i : e) { 40 | std::cout << i << ' '; 41 | } 42 | std::cout << '\n'; 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /c-cpp/12_sorts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/12_sorts/.gitkeep -------------------------------------------------------------------------------- /c-cpp/12_sorts/merge_sort_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/17. 3 | */ 4 | 5 | #include 6 | #include 7 | #include "merge_sort.hpp" 8 | 9 | int main() { 10 | const std::vector test_data{0, -1, 3, 190, -500}; 11 | 12 | std::vector a{test_data}; 13 | merge_sort(a.begin(), a.end()); 14 | for (auto i : a) { 15 | std::cout << i << ' '; 16 | } 17 | std::cout << std::endl; 18 | 19 | std::vector b{test_data}; 20 | inplace_merge_sort(b.begin(), b.end()); 21 | for (auto i : b) { 22 | std::cout << i << ' '; 23 | } 24 | std::cout << std::endl; 25 | 26 | return 0; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /c-cpp/12_sorts/quick_sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void dump(int *arr, int size) 7 | { 8 | int idx; 9 | 10 | for (idx = 0; idx < size; idx++) 11 | printf("%08d\n", arr[idx]); 12 | } 13 | 14 | void swap(int *a, int *b) 15 | { 16 | int tmp = *a; 17 | *a = *b; 18 | *b = tmp; 19 | } 20 | 21 | int partition(int *arr, int p, int r) 22 | { 23 | //int pivot = arr[r]; 24 | int i, j; 25 | 26 | i = j = p; 27 | 28 | for (; j < r; j++) { 29 | if (arr[j] < arr[r]) { 30 | if(i != j) 31 | { 32 | swap(arr + i, arr + j); 33 | 34 | } 35 | i++; 36 | } 37 | } 38 | 39 | swap(arr + i, arr + r); 40 | return i; 41 | } 42 | 43 | void __quick_sort(int *arr, int p, int r) 44 | { 45 | int q; 46 | 47 | if (p >= r) 48 | return; 49 | 50 | q = partition(arr, p, r); 51 | __quick_sort(arr, p, q-1); 52 | __quick_sort(arr, q+1, r); 53 | } 54 | 55 | void quick_sort(int *arr, int size) 56 | { 57 | __quick_sort(arr, 0, size - 1); 58 | } 59 | 60 | void quick_sort_test() 61 | { 62 | int test[10] = {5, 8, 9, 23, 67, 1, 3, 7, 31, 56}; 63 | 64 | quick_sort(test, 10); 65 | 66 | dump(test, 10); 67 | } 68 | 69 | int main() 70 | { 71 | quick_sort_test(); 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /c-cpp/12_sorts/quick_sort_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/17. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "quick_sort.hpp" 10 | 11 | void test_quick_sort(std::vector test_data) { 12 | quick_sort(test_data.begin(), test_data.end()); 13 | std::transform(test_data.begin(), test_data.end(), 14 | std::ostream_iterator(std::cout, " "), [](int i){ return i; }); 15 | std::cout << '\n'; 16 | } 17 | 18 | int main() { 19 | test_quick_sort({-3, -1, 1, -2, -3, 0, -3, 100, 1, 1, -100}); 20 | test_quick_sort({1, 1, 1}); 21 | test_quick_sort({1, 0, -1}); 22 | test_quick_sort({1}); 23 | return 0; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /c-cpp/13_sorts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/13_sorts/.gitkeep -------------------------------------------------------------------------------- /c-cpp/13_sorts/bucket_sort.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/26. 3 | */ 4 | 5 | #ifndef SORTS_BUCKET_SORT_HPP_ 6 | #define SORTS_BUCKET_SORT_HPP_ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | template ::value_type, 16 | typename Compare = std::less> 17 | void bucket_sort(IterT first, IterT last, Compare comp = Compare()) { 18 | const T min = *std::min_element(first, last), max = *std::max_element(first, last); 19 | const T range = max + 1 - min; 20 | const size_t bucket_num = (range - 1) / BucketSize + 1; 21 | 22 | std::vector> buckets(bucket_num); 23 | for (auto b : buckets) { 24 | b.reserve(2 * BucketSize); 25 | } 26 | 27 | for (IterT i = first; i != last; ++i) { 28 | size_t idx = (*i - min) / BucketSize; 29 | buckets[idx].emplace_back(*i); 30 | } 31 | 32 | IterT dest = first; 33 | for (auto b : buckets) { 34 | std::sort(b.begin(), b.end(), comp); 35 | std::copy(b.begin(), b.end(), dest); 36 | dest += b.size(); 37 | } 38 | 39 | return; 40 | } 41 | 42 | #endif // SORTS_BUCKET_SORT_HPP_ 43 | 44 | -------------------------------------------------------------------------------- /c-cpp/13_sorts/bucket_sort_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/26. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "bucket_sort.hpp" 10 | 11 | template > 15 | void test_bucket_sort(Container cont, Compare comp = Compare()) { 16 | bucket_sort(cont.begin(), cont.end(), comp); 17 | std::transform(cont.begin(), cont.end(), std::ostream_iterator(std::cout, " "), 18 | [](T i){ return i; }); 19 | std::cout << std::endl; 20 | } 21 | 22 | int main() { 23 | std::vector test{3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9}; 24 | 25 | test_bucket_sort<2>(test); // 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9 26 | test_bucket_sort<3>(test); // 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9 27 | test_bucket_sort<4>(test); // 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9 28 | test_bucket_sort<5>(test); // 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9 29 | test_bucket_sort<6>(test); // 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9 30 | 31 | return 0; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /c-cpp/13_sorts/counting_sort.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/26. 3 | */ 4 | 5 | #ifndef SORTS_COUNTING_SORT_HPP_ 6 | #define SORTS_COUNTING_SORT_HPP_ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | template ::value_type> 15 | void counting_sort(IterT first, IterT last) { 16 | const auto len = std::distance(first, last); 17 | if (len < 2) { return; } 18 | 19 | const T max = *std::max_element(first, last); 20 | if (max == 0) { return; } 21 | 22 | std::vector counter(max + 1); 23 | for (IterT i = first; i != last; ++i) { 24 | ++counter[*i]; 25 | } 26 | for (size_t i = 1; i != max + 1; ++i) { 27 | const size_t j = max - i; 28 | counter[j] += counter[j + 1]; // Liam Huang: count of numbers that is not less than j. 29 | } 30 | 31 | std::vector temp(len); 32 | for (IterT i = first; i != last; ++i) { 33 | temp[len - counter[*i]] = *i; 34 | --counter[*i]; // Liam Huang: stable for relative position. 35 | } 36 | std::copy(temp.begin(), temp.end(), first); 37 | } 38 | 39 | #endif // SORTS_COUNTING_SORT_HPP_ 40 | 41 | -------------------------------------------------------------------------------- /c-cpp/14_sorts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/14_sorts/.gitkeep -------------------------------------------------------------------------------- /c-cpp/14_sorts/analytics_of_std_sort.md: -------------------------------------------------------------------------------- 1 | # C++ STL 中的 std::sort 分析 2 | 3 | 参见 [Liam Huang 的博客](https://liam.page/)中的 3 篇文章: 4 | 5 | * [谈谈基于比较的排序算法的复杂度下界](https://liam.page/2018/08/28/lower-bound-of-comparation-based-sort-algorithm/) 6 | * [谈谈内省式排序算法](https://liam.page/2018/08/29/introspective-sort/) 7 | * [谈谈 STL 中的 std::sort](https://liam.page/2018/09/18/std-sort-in-STL/) 8 | 9 | -------------------------------------------------------------------------------- /c-cpp/15_bsearch/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/15_bsearch/.gitkeep -------------------------------------------------------------------------------- /c-cpp/15_bsearch/bsearch.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/24. 3 | */ 4 | 5 | #ifndef BSEARCH_BSEARCH_HPP_ 6 | #define BSEARCH_BSEARCH_HPP_ 7 | 8 | #include 9 | #include 10 | 11 | // Liam Huang: The algorithm works right with iterators that meet the ForwardIterator requirement, 12 | // but with a bad time complexity. For better performance, iterators should meet 13 | // the RandomAccessIterator requirement. 14 | template ::value_type, 16 | typename Compare = std::less> 17 | IterT bsearch(IterT first, 18 | IterT last, 19 | ValueT target, 20 | Compare comp = Compare()) { 21 | IterT result = last; 22 | while (std::distance(first, last) > 0) { 23 | IterT mid = first + std::distance(first, last) / 2; 24 | if (comp(*mid, target)) { 25 | first = mid + 1; 26 | } else if (comp(target, *mid)) { 27 | last = mid; 28 | } else { // equal 29 | result = mid; 30 | break; 31 | } 32 | } 33 | return result; 34 | } 35 | 36 | #endif // BSEARCH_BSEARCH_HPP_ 37 | 38 | -------------------------------------------------------------------------------- /c-cpp/15_bsearch/bsearch_c/sqrt.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: sqrt.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-31 6 | > Desc: 7 | ************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | /*求解精度设置*/ 15 | #define E 0.000001 16 | double mybsearch(double num) 17 | { 18 | double start = 1.0; 19 | double end = num; 20 | double mid = 0.0; 21 | while(1) 22 | { 23 | mid = (start + end)/2; 24 | if(((mid*mid - num) <= E) && ((mid*mid - num) >= -E)) 25 | { 26 | return mid; 27 | } 28 | 29 | if ((mid*mid - num) > E) 30 | { 31 | end = mid; 32 | } 33 | else 34 | { 35 | start = mid; 36 | } 37 | } 38 | 39 | return 0; 40 | } 41 | 42 | 43 | int main() 44 | { 45 | double num = 0.0; 46 | 47 | /*这里需要注意:double的输入方式*/ 48 | scanf("%lf",&num); 49 | printf("\r\n num %lf的平方根是%lf",num,mybsearch(num)); 50 | 51 | return 0; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /c-cpp/15_bsearch/bsearch_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/24. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #include "bsearch.hpp" 9 | 10 | template 11 | void test_bsearch(const VecT& test, T target) { 12 | auto it = bsearch(test.begin(), test.end(), target); 13 | std::cout << std::distance(test.begin(), it) << std::endl; 14 | } 15 | 16 | int main() { 17 | std::vector test{0, 0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 5, 6, 7}; // std::less() 18 | 19 | test_bsearch(test, 8); // 14 20 | test_bsearch(test, -1); // 14 21 | test_bsearch(test, 0); // 0, 1 22 | test_bsearch(test, 4); // 5, 6 23 | test_bsearch(test, 5); // 7, 8, 9, 10, 11 24 | test_bsearch(test, 7); // 13 25 | 26 | return 0; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /c-cpp/16_bsearch/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/16_bsearch/.gitkeep -------------------------------------------------------------------------------- /c-cpp/17_skiplist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/17_skiplist/.gitkeep -------------------------------------------------------------------------------- /c-cpp/17_skiplist/SkipList.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/17_skiplist/SkipList.cpp -------------------------------------------------------------------------------- /c-cpp/17_skiplist/skiplist_c/skiplist.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: skiplist.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-31 6 | > Desc: 7 | ************************************************************************/ 8 | #ifndef __SKIP_LIST_H__ 9 | #define __SKIP_LIST_H__ 10 | 11 | 12 | typedef struct _node 13 | { 14 | int key; /*key是唯一的*/ 15 | int value; /*存储的内容*/ 16 | int max_level; /*当前节点最大层数*/ 17 | struct _node *next[0];/*level层链表结构*/ 18 | }node; 19 | 20 | typedef struct _skiplist 21 | { 22 | int level; 23 | int count; 24 | node *head; 25 | }skiplist; 26 | 27 | /*根据当前结构体元素的地址,获取到结构体首地址*/ 28 | #define offsetof(TYPE,MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 29 | #define container(ptr,type,member) ({\ 30 | const typeof( ((type *)0)->member) *__mptr = (ptr);\ 31 | (type *) ( (char *)__mptr - offsetof(type,member));}) 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /c-cpp/18_hashtable/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/c-cpp/18_hashtable/.gitkeep -------------------------------------------------------------------------------- /c-cpp/23_binarytree/tree/list_queue.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: list_queue.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-13 6 | > Desc: 7 | ************************************************************************/ 8 | 9 | #ifndef LINK_LIST_QUEUE_H 10 | #define LINK_LIST_QUEUE_H 11 | 12 | typedef struct _list_queue_node 13 | { 14 | void *data; 15 | struct _list_queue_node *next; 16 | }queue_node; 17 | 18 | typedef struct _list_queue 19 | { 20 | int num; 21 | queue_node *head; 22 | queue_node *tail; 23 | }list_queue; 24 | 25 | #define list_queue_is_empty(queue) ((queue->num) == 0) 26 | list_queue *list_queue_create(); 27 | int list_queue_enqueue(list_queue *queue,void *data); 28 | int list_queue_dequeue(list_queue *queue,void **data); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /c-cpp/24_binarysearchtree/binarysearchtree.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: binarysearchtree.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-11-12 6 | > Desc: 7 | ************************************************************************/ 8 | #ifndef __BINARY_SEARCH_TREE__ 9 | #define __BINARY_SEARCH_TREE__ 10 | typedef int mytype; 11 | 12 | typedef struct _bstree_node 13 | { 14 | mytype data; 15 | struct _bstree_node *lchild; 16 | struct _bstree_node *rchild; 17 | }bstree_node; 18 | 19 | typedef struct _bstree 20 | { 21 | int size; 22 | int (*compare)(mytype key1,mytype key2); 23 | int (*destory)(mytype data); 24 | bstree_node *root; 25 | }bstree; 26 | 27 | typedef int (*compare_fuc)(mytype key1,mytype key2); 28 | typedef int (*destory_fuc)(mytype data); 29 | 30 | #define bstree_is_empty(tree) (tree->size == 0) 31 | 32 | bstree *bstree_create(compare_fuc compare,destory_fuc destory); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /csharp/05-array/algo05_array.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.2 5 | false 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /csharp/06-linkedlist/LRUWithArray.cs: -------------------------------------------------------------------------------- 1 | using algo05_array; 2 | 3 | namespace algo06_linked_list 4 | { 5 | /// 6 | /// 使用数组实现LRU缓存淘汰算法 7 | /// 8 | public class LRUWithArray 9 | { 10 | private readonly int _capacity; 11 | 12 | public LRUWithArray(int capacity) 13 | { 14 | _capacity = capacity; 15 | CachedList = new Array(capacity); 16 | } 17 | 18 | public Array CachedList { get; } 19 | 20 | public void Set(int val) 21 | { 22 | // 找出该值在缓存中的索引位置 23 | int idx = CachedList.IndexOf(val); 24 | 25 | // 存在该缓存值 26 | if (idx != -1) 27 | { 28 | CachedList.Delete(idx); 29 | CachedList.Insert(0, val); 30 | return; 31 | } 32 | 33 | // 不存在该缓存值 34 | if (CachedList.Length == _capacity) 35 | { 36 | // 缓存已满,删除最后一个元素 37 | CachedList.Delete(CachedList.Length - 1); 38 | } 39 | 40 | // 将新缓存插入到表头 41 | CachedList.Insert(0, val); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /csharp/06-linkedlist/LRU缓存实现思路.txt: -------------------------------------------------------------------------------- 1 | 实现LRU缓存淘汰算法思路: 2 | 3 | 维护一个有序单链表,越靠近链尾的数据是最早访问的。 4 | 当有一个新的数据被访问时, 5 | 1. 如果数据在缓存中,则将其从原位置删除,然后插入到表头; 6 | 2. 如果数据不在缓存中,有两种情况: 7 | 1) 链表未满,则将数据插入到表头; 8 | 2) 链表已满,则删除尾结点,将新数据插入到表头。 9 | -------------------------------------------------------------------------------- /csharp/06-linkedlist/algo06_linked_list.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.2 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /csharp/07-linkedlist/_07_linkedlist/algo07_linkedlist.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.2 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /csharp/08-stack/algo08_stack/ArrayStack.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace algo08_stack 4 | { 5 | public class ArrayStack 6 | { 7 | private readonly int _capacity; 8 | 9 | private readonly T[] _data; 10 | 11 | private int _top = -1; // 指向栈顶元素,当为-1时表示栈为空 12 | 13 | public ArrayStack(int capacity) 14 | { 15 | _capacity = capacity; 16 | 17 | _data = new T[capacity]; 18 | } 19 | 20 | public int Count => _top + 1; 21 | 22 | public void Push(T val) 23 | { 24 | if (Count == _capacity) throw new InvalidOperationException("Stack full."); 25 | 26 | _top++; 27 | 28 | _data[_top] = val; 29 | } 30 | 31 | public T Pop() 32 | { 33 | if (_top == -1) throw new InvalidOperationException("Stack empty."); 34 | 35 | T val = _data[_top]; 36 | _top--; 37 | 38 | return val; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /csharp/08-stack/algo08_stack/LinkedStack.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace algo08_stack 4 | { 5 | public class LinkedStack 6 | { 7 | private StackListNode _top; 8 | 9 | public int Count { get; private set; } 10 | 11 | public void Push(T val) 12 | { 13 | var newNode = new StackListNode(val); 14 | newNode.Next = _top; 15 | _top = newNode; 16 | 17 | Count++; 18 | } 19 | 20 | public T Pop() 21 | { 22 | if (_top == null) throw new InvalidOperationException("Stack empty"); 23 | 24 | T val = _top.Value; 25 | _top = _top.Next; 26 | 27 | Count--; 28 | 29 | return val; 30 | } 31 | 32 | public void Clear() 33 | { 34 | while (Count > 0) 35 | { 36 | Pop(); 37 | } 38 | } 39 | } 40 | 41 | public class StackListNode 42 | { 43 | public StackListNode(T nodeValue) 44 | { 45 | Value = nodeValue; 46 | } 47 | 48 | public T Value { get; set; } 49 | public StackListNode Next { get; set; } 50 | } 51 | } -------------------------------------------------------------------------------- /csharp/08-stack/algo08_stack/LinkedStackBrowser.cs: -------------------------------------------------------------------------------- 1 | namespace algo08_stack 2 | { 3 | /// 4 | /// 利用链栈实现浏览器怎么进后退 5 | /// 6 | public class LinkedStackBrowser 7 | { 8 | private readonly LinkedStack _backStack = new LinkedStack(); 9 | private readonly LinkedStack _forwardStack = new LinkedStack(); 10 | 11 | public void Open(string url) 12 | { 13 | _backStack.Push(url); 14 | 15 | _forwardStack.Clear(); 16 | } 17 | 18 | public string Backward() 19 | { 20 | if (_backStack.Count == 0) return string.Empty; 21 | 22 | string url = _backStack.Pop(); 23 | 24 | _forwardStack.Push(url); 25 | 26 | return url; 27 | } 28 | 29 | public string Forward() 30 | { 31 | if (_forwardStack.Count == 0) return string.Empty; 32 | 33 | string url = _forwardStack.Pop(); 34 | _backStack.Push(url); 35 | 36 | return url; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /csharp/08-stack/algo08_stack/algo08_stack.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.2 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /csharp/Tests/_05_array_tests/algo05_array_tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.2 5 | 6 | false 7 | 8 | 05_array_tests 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /csharp/Tests/_06_linkedlist_tests/BaseLinkedListTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using algo06_linked_list; 3 | 4 | namespace algo06_linkedlist_tests 5 | { 6 | public class BaseLinkedListTests 7 | { 8 | protected void PrintLinkedList (SingleLinkedList list) where T : IComparable 9 | { 10 | if (list == null) return; 11 | 12 | var p = list.First; 13 | while (p != null) 14 | { 15 | System.Console.WriteLine (p.Value); 16 | p = p.Next; 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /csharp/Tests/_06_linkedlist_tests/algo06_linkedlist_tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.2 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /csharp/Tests/_07_linkedlist_tests/algo07_linkedlist_tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.2 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /csharp/Tests/algo08_stack_tests/algo08_stack_tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.2 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /go/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/go/.gitkeep -------------------------------------------------------------------------------- /go/05_array/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/go/05_array/.gitkeep -------------------------------------------------------------------------------- /go/05_array/array_test.go: -------------------------------------------------------------------------------- 1 | package _5_array 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestInsert(t *testing.T) { 8 | capacity := 10 9 | arr := NewArray(uint(capacity)) 10 | for i := 0; i < capacity-2; i++ { 11 | err := arr.Insert(uint(i), i+1) 12 | if nil != err { 13 | t.Fatal(err.Error()) 14 | } 15 | } 16 | arr.Print() 17 | 18 | arr.Insert(uint(6), 999) 19 | arr.Print() 20 | 21 | arr.InsertToTail(666) 22 | arr.Print() 23 | } 24 | 25 | func TestDelete(t *testing.T) { 26 | capacity := 10 27 | arr := NewArray(uint(capacity)) 28 | for i := 0; i < capacity; i++ { 29 | err := arr.Insert(uint(i), i+1) 30 | if nil != err { 31 | t.Fatal(err.Error()) 32 | } 33 | } 34 | arr.Print() 35 | 36 | for i := 9; i >= 0; i-- { 37 | _, err := arr.Delete(uint(i)) 38 | if nil != err { 39 | t.Fatal(err) 40 | } 41 | arr.Print() 42 | } 43 | } 44 | 45 | func TestFind(t *testing.T) { 46 | capacity := 10 47 | arr := NewArray(uint(capacity)) 48 | for i := 0; i < capacity; i++ { 49 | err := arr.Insert(uint(i), i+1) 50 | if nil != err { 51 | t.Fatal(err.Error()) 52 | } 53 | } 54 | arr.Print() 55 | 56 | t.Log(arr.Find(0)) 57 | t.Log(arr.Find(9)) 58 | t.Log(arr.Find(11)) 59 | } 60 | -------------------------------------------------------------------------------- /go/06_linkedlist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/go/06_linkedlist/.gitkeep -------------------------------------------------------------------------------- /go/06_linkedlist/palindrome-linked-list.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * type ListNode struct { 4 | * Val int 5 | * Next *ListNode 6 | * } 7 | */ 8 | func isPalindrome(head *ListNode) bool { 9 | var slow *ListNode = head 10 | var fast *ListNode = head 11 | var prev *ListNode = nil 12 | var temp *ListNode = nil 13 | 14 | if (head == nil || head.Next == nil) { 15 | return true 16 | } 17 | 18 | for (fast != nil && fast.Next !=nil){ 19 | fast = fast.Next.Next 20 | temp = slow.Next 21 | slow.Next = prev 22 | prev = slow 23 | slow = temp 24 | } // 快的先跑完,同时反转了一半链表,剪短 25 | 26 | if fast != nil { 27 | slow = slow.Next // 处理余数,跨过中位数 28 | // prev 增加中 2->1->nil 29 | } 30 | 31 | var l1 *ListNode = prev 32 | var l2 *ListNode = slow 33 | 34 | for (l1 != nil && l2 !=nil && l1.Val == l2.Val){ 35 | l1 = l1.Next 36 | l2 = l2.Next 37 | } 38 | 39 | return (l1 == nil && l2 == nil) 40 | 41 | } 42 | -------------------------------------------------------------------------------- /go/06_linkedlist/palindrome_test.go: -------------------------------------------------------------------------------- 1 | package _6_linkedlist 2 | 3 | import "testing" 4 | 5 | func TestPalindrome1(t *testing.T) { 6 | strs := []string{"heooeh", "hello", "heoeh", "a", ""} 7 | for _, str1 := range strs { 8 | l := NewLinkedList() 9 | for _, c := range str1 { 10 | l.InsertToTail(string(c)) 11 | } 12 | l.Print() 13 | t.Log(isPalindrome1(l)) 14 | } 15 | } 16 | 17 | func TestPalindrome2(t *testing.T) { 18 | strs := []string{"heooeh", "hello", "heoeh", "a", ""} 19 | for _, str1 := range strs { 20 | l := NewLinkedList() 21 | for _, c := range str1 { 22 | l.InsertToTail(string(c)) 23 | } 24 | l.Print() 25 | t.Log(isPalindrome2(l)) 26 | l.Print() 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /go/06_linkedlist/singlelinkedlist_test.go: -------------------------------------------------------------------------------- 1 | package _6_linkedlist 2 | 3 | import "testing" 4 | 5 | func TestInsertToHead(t *testing.T) { 6 | l := NewLinkedList() 7 | for i := 0; i < 10; i++ { 8 | l.InsertToHead(i + 1) 9 | } 10 | l.Print() 11 | } 12 | 13 | func TestInsertToTail(t *testing.T) { 14 | l := NewLinkedList() 15 | for i := 0; i < 10; i++ { 16 | l.InsertToTail(i + 1) 17 | } 18 | l.Print() 19 | } 20 | 21 | func TestFindByIndex(t *testing.T) { 22 | l := NewLinkedList() 23 | for i := 0; i < 10; i++ { 24 | l.InsertToTail(i + 1) 25 | } 26 | t.Log(l.FindByIndex(0)) 27 | t.Log(l.FindByIndex(9)) 28 | t.Log(l.FindByIndex(5)) 29 | t.Log(l.FindByIndex(11)) 30 | } 31 | 32 | func TestDeleteNode(t *testing.T) { 33 | l := NewLinkedList() 34 | for i := 0; i < 3; i++ { 35 | l.InsertToTail(i + 1) 36 | } 37 | l.Print() 38 | 39 | t.Log(l.DeleteNode(l.head.next)) 40 | l.Print() 41 | 42 | t.Log(l.DeleteNode(l.head.next.next)) 43 | l.Print() 44 | } 45 | -------------------------------------------------------------------------------- /go/07_linkedlist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/go/07_linkedlist/.gitkeep -------------------------------------------------------------------------------- /go/08_stack/SimpleBrowser.go: -------------------------------------------------------------------------------- 1 | package _8_stack 2 | 3 | import "fmt" 4 | 5 | type Browser struct { 6 | forwardStack Stack 7 | backStack Stack 8 | } 9 | 10 | func NewBrowser() *Browser { 11 | return &Browser{ 12 | forwardStack: NewArrayStack(), 13 | backStack: NewLinkedListStack(), 14 | } 15 | } 16 | 17 | func (this *Browser) CanForward() bool { 18 | if this.forwardStack.IsEmpty() { 19 | return false 20 | } 21 | return true 22 | } 23 | 24 | func (this *Browser) CanBack() bool { 25 | if this.backStack.IsEmpty() { 26 | return false 27 | } 28 | return true 29 | } 30 | 31 | func (this *Browser) Open(addr string) { 32 | fmt.Printf("Open new addr %+v\n", addr) 33 | this.forwardStack.Flush() 34 | } 35 | 36 | func (this *Browser) PushBack(addr string) { 37 | this.backStack.Push(addr) 38 | } 39 | 40 | func (this *Browser) Forward() { 41 | if this.forwardStack.IsEmpty() { 42 | return 43 | } 44 | top := this.forwardStack.Pop() 45 | this.backStack.Push(top) 46 | fmt.Printf("forward to %+v\n", top) 47 | } 48 | 49 | func (this *Browser) Back() { 50 | if this.backStack.IsEmpty() { 51 | return 52 | } 53 | top := this.backStack.Pop() 54 | this.forwardStack.Push(top) 55 | fmt.Printf("back to %+v\n", top) 56 | } 57 | -------------------------------------------------------------------------------- /go/08_stack/SimpleBrowser_test.go: -------------------------------------------------------------------------------- 1 | package _8_stack 2 | 3 | import "testing" 4 | 5 | func TestBrowser(t *testing.T) { 6 | b := NewBrowser() 7 | b.PushBack("www.qq.com") 8 | b.PushBack("www.baidu.com") 9 | b.PushBack("www.sina.com") 10 | if b.CanBack() { 11 | b.Back() 12 | } 13 | if b.CanForward() { 14 | b.Forward() 15 | } 16 | if b.CanBack() { 17 | b.Back() 18 | } 19 | if b.CanBack() { 20 | b.Back() 21 | } 22 | if b.CanBack() { 23 | b.Back() 24 | } 25 | b.Open("www.taobao.com") 26 | if b.CanForward() { 27 | b.Forward() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /go/08_stack/StackBasedOnArray_test.go: -------------------------------------------------------------------------------- 1 | package _8_stack 2 | 3 | import "testing" 4 | 5 | func TestArrayStack_Push(t *testing.T) { 6 | s := NewArrayStack() 7 | s.Push(1) 8 | s.Push(2) 9 | t.Log(s.Pop()) 10 | s.Push(3) 11 | t.Log(s.Pop()) 12 | t.Log(s.Pop()) 13 | s.Push(4) 14 | t.Log(s.Pop()) 15 | s.Print() 16 | } 17 | 18 | func TestArrayStack_Pop(t *testing.T) { 19 | s := NewArrayStack() 20 | s.Push(1) 21 | s.Push(2) 22 | s.Push(3) 23 | s.Print() 24 | 25 | t.Log(s.Pop()) 26 | t.Log(s.Pop()) 27 | t.Log(s.Pop()) 28 | t.Log(s.Pop()) 29 | s.Print() 30 | } 31 | 32 | func TestArrayStack_Top(t *testing.T) { 33 | s := NewArrayStack() 34 | s.Push(1) 35 | s.Push(2) 36 | s.Push(3) 37 | 38 | t.Log(s.Top()) 39 | s.Pop() 40 | t.Log(s.Top()) 41 | s.Pop() 42 | t.Log(s.Top()) 43 | s.Pop() 44 | t.Log(s.Top()) 45 | s.Pop() 46 | } 47 | -------------------------------------------------------------------------------- /go/08_stack/StackBasedOnLinkedList.go: -------------------------------------------------------------------------------- 1 | package _8_stack 2 | 3 | import "fmt" 4 | 5 | /* 6 | 基于链表实现的栈 7 | */ 8 | type node struct { 9 | next *node 10 | val interface{} 11 | } 12 | 13 | type LinkedListStack struct { 14 | //栈顶节点 15 | topNode *node 16 | } 17 | 18 | func NewLinkedListStack() *LinkedListStack { 19 | return &LinkedListStack{nil} 20 | } 21 | 22 | func (this *LinkedListStack) IsEmpty() bool { 23 | return this.topNode == nil 24 | } 25 | 26 | func (this *LinkedListStack) Push(v interface{}) { 27 | this.topNode = &node{next: this.topNode, val: v} 28 | } 29 | 30 | func (this *LinkedListStack) Pop() interface{} { 31 | if this.IsEmpty() { 32 | return nil 33 | } 34 | v := this.topNode.val 35 | this.topNode = this.topNode.next 36 | return v 37 | } 38 | 39 | func (this *LinkedListStack) Top() interface{} { 40 | if this.IsEmpty() { 41 | return nil 42 | } 43 | return this.topNode.val 44 | } 45 | 46 | func (this *LinkedListStack) Flush() { 47 | this.topNode = nil 48 | } 49 | 50 | func (this *LinkedListStack) Print() { 51 | if this.IsEmpty() { 52 | fmt.Println("empty stack") 53 | } else { 54 | cur := this.topNode 55 | for nil != cur { 56 | fmt.Println(cur.val) 57 | cur = cur.next 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /go/08_stack/StackBasedOnLinkedList_test.go: -------------------------------------------------------------------------------- 1 | package _8_stack 2 | 3 | import "testing" 4 | 5 | func TestLinkedListStack_Push(t *testing.T) { 6 | s := NewLinkedListStack() 7 | s.Push(1) 8 | s.Push(2) 9 | s.Push(3) 10 | s.Print() 11 | } 12 | 13 | func TestLinkedListStack_Pop(t *testing.T) { 14 | s := NewLinkedListStack() 15 | s.Push(1) 16 | s.Push(2) 17 | s.Push(3) 18 | s.Print() 19 | 20 | t.Log(s.Pop()) 21 | t.Log(s.Pop()) 22 | t.Log(s.Pop()) 23 | t.Log(s.Pop()) 24 | s.Print() 25 | } 26 | 27 | func TestLinkedListStack_Top(t *testing.T) { 28 | s := NewLinkedListStack() 29 | s.Push(1) 30 | s.Push(2) 31 | s.Push(3) 32 | 33 | t.Log(s.Top()) 34 | s.Pop() 35 | t.Log(s.Top()) 36 | s.Pop() 37 | t.Log(s.Top()) 38 | s.Pop() 39 | t.Log(s.Top()) 40 | s.Pop() 41 | } 42 | -------------------------------------------------------------------------------- /go/08_stack/StatckInterface.go: -------------------------------------------------------------------------------- 1 | package _8_stack 2 | 3 | type Stack interface { 4 | Push(v interface{}) 5 | Pop() interface{} 6 | IsEmpty() bool 7 | Top() interface{} 8 | Flush() 9 | } 10 | -------------------------------------------------------------------------------- /go/09_queue/CircularQueue_test.go: -------------------------------------------------------------------------------- 1 | package _9_queue 2 | 3 | import "testing" 4 | 5 | func TestCircularQueue_EnQueue(t *testing.T) { 6 | q := NewCircularQueue(5) 7 | q.EnQueue(1) 8 | q.EnQueue(2) 9 | q.EnQueue(3) 10 | q.EnQueue(4) 11 | q.EnQueue(5) 12 | q.EnQueue(6) 13 | t.Log(q) 14 | } 15 | 16 | func TestCircularQueue_DeQueue(t *testing.T) { 17 | q := NewCircularQueue(5) 18 | q.EnQueue(1) 19 | q.EnQueue(2) 20 | q.EnQueue(3) 21 | q.EnQueue(4) 22 | q.EnQueue(5) 23 | q.EnQueue(6) 24 | t.Log(q) 25 | t.Log(q.DeQueue()) 26 | t.Log(q) 27 | q.EnQueue(5) 28 | t.Log(q) 29 | q.DeQueue() 30 | t.Log(q) 31 | q.DeQueue() 32 | t.Log(q) 33 | q.DeQueue() 34 | t.Log(q) 35 | q.DeQueue() 36 | t.Log(q) 37 | } 38 | -------------------------------------------------------------------------------- /go/09_queue/QueueBasedOnArray.go: -------------------------------------------------------------------------------- 1 | package _9_queue 2 | 3 | import "fmt" 4 | 5 | type ArrayQueue struct { 6 | q []interface{} 7 | capacity int 8 | head int 9 | tail int 10 | } 11 | 12 | func NewArrayQueue(n int) *ArrayQueue { 13 | return &ArrayQueue{make([]interface{}, n), n, 0, 0} 14 | } 15 | 16 | func (this *ArrayQueue) EnQueue(v interface{}) bool { 17 | if this.tail == this.capacity { 18 | return false 19 | } 20 | this.q[this.tail] = v 21 | this.tail++ 22 | return true 23 | } 24 | 25 | func (this *ArrayQueue) DeQueue() interface{} { 26 | if this.head == this.tail { 27 | return nil 28 | } 29 | v := this.q[this.head] 30 | this.head++ 31 | return v 32 | } 33 | 34 | func (this *ArrayQueue) String() string { 35 | if this.head == this.tail { 36 | return "empty queue" 37 | } 38 | result := "head" 39 | for i := this.head; i <= this.tail-1; i++ { 40 | result += fmt.Sprintf("<-%+v", this.q[i]) 41 | } 42 | result += "<-tail" 43 | return result 44 | } 45 | -------------------------------------------------------------------------------- /go/09_queue/QueueBasedOnArray_test.go: -------------------------------------------------------------------------------- 1 | package _9_queue 2 | 3 | import "testing" 4 | 5 | func TestArrayQueue_EnQueue(t *testing.T) { 6 | q := NewArrayQueue(5) 7 | q.EnQueue(1) 8 | q.EnQueue(2) 9 | q.EnQueue(3) 10 | q.EnQueue(4) 11 | q.EnQueue(5) 12 | q.EnQueue(6) 13 | t.Log(q) 14 | } 15 | 16 | func TestArrayQueue_DeQueue(t *testing.T) { 17 | q := NewArrayQueue(5) 18 | q.EnQueue(1) 19 | q.EnQueue(2) 20 | q.EnQueue(3) 21 | q.EnQueue(4) 22 | q.EnQueue(5) 23 | q.EnQueue(6) 24 | t.Log(q) 25 | q.DeQueue() 26 | t.Log(q) 27 | q.DeQueue() 28 | t.Log(q) 29 | q.DeQueue() 30 | t.Log(q) 31 | q.DeQueue() 32 | t.Log(q) 33 | q.DeQueue() 34 | t.Log(q) 35 | } 36 | -------------------------------------------------------------------------------- /go/09_queue/QueueBasedOnLinkedList.go: -------------------------------------------------------------------------------- 1 | package _9_queue 2 | 3 | import "fmt" 4 | 5 | type ListNode struct { 6 | val interface{} 7 | next *ListNode 8 | } 9 | 10 | type LinkedListQueue struct { 11 | head *ListNode 12 | tail *ListNode 13 | length int 14 | } 15 | 16 | func NewLinkedListQueue() *LinkedListQueue { 17 | return &LinkedListQueue{nil, nil, 0} 18 | } 19 | 20 | func (this *LinkedListQueue) EnQueue(v interface{}) { 21 | node := &ListNode{v, nil} 22 | if nil == this.tail { 23 | this.tail = node 24 | this.head = node 25 | } else { 26 | this.tail.next = node 27 | this.tail = node 28 | } 29 | this.length++ 30 | } 31 | 32 | func (this *LinkedListQueue) DeQueue() interface{} { 33 | if this.head == nil { 34 | return nil 35 | } 36 | v := this.head.val 37 | this.head = this.head.next 38 | this.length-- 39 | return v 40 | } 41 | 42 | func (this *LinkedListQueue) String() string { 43 | if this.head == nil { 44 | return "empty queue" 45 | } 46 | result := "head<-" 47 | for cur := this.head; cur != nil; cur = cur.next { 48 | result += fmt.Sprintf("<-%+v", cur.val) 49 | } 50 | result += "<-tail" 51 | return result 52 | } 53 | -------------------------------------------------------------------------------- /go/09_queue/QueueBasedOnLinkedList_test.go: -------------------------------------------------------------------------------- 1 | package _9_queue 2 | 3 | import "testing" 4 | 5 | func TestListQueue_EnQueue(t *testing.T) { 6 | q := NewLinkedListQueue() 7 | q.EnQueue(1) 8 | q.EnQueue(2) 9 | q.EnQueue(3) 10 | q.EnQueue(4) 11 | q.EnQueue(5) 12 | q.EnQueue(6) 13 | t.Log(q) 14 | } 15 | 16 | func TestListQueue_DeQueue(t *testing.T) { 17 | q := NewLinkedListQueue() 18 | q.EnQueue(1) 19 | q.EnQueue(2) 20 | q.EnQueue(3) 21 | q.EnQueue(4) 22 | q.EnQueue(5) 23 | q.EnQueue(6) 24 | t.Log(q) 25 | q.DeQueue() 26 | t.Log(q) 27 | q.DeQueue() 28 | t.Log(q) 29 | q.DeQueue() 30 | t.Log(q) 31 | q.DeQueue() 32 | t.Log(q) 33 | q.DeQueue() 34 | t.Log(q) 35 | } 36 | -------------------------------------------------------------------------------- /go/10_recursion/Factorial.go: -------------------------------------------------------------------------------- 1 | package Recursion 2 | 3 | // 迭代实现阶乘 4 | type Fac struct { 5 | val map[int]int 6 | } 7 | 8 | func NewFactorial(n int) *Fac { 9 | return &Fac{ 10 | make(map[int]int, n), 11 | } 12 | } 13 | 14 | func (fac *Fac) Factorial(n int) int { 15 | if fac.val[n] != 0{ 16 | return fac.val[n] 17 | } 18 | 19 | if n <= 1{ 20 | fac.val[n] = 1 21 | return 1 22 | }else { 23 | res := n * fac.Factorial(n-1) 24 | fac.val[n] =res 25 | return res 26 | } 27 | } 28 | 29 | func (fac *Fac) Print(n int ) { 30 | println(fac.val[n]) 31 | } 32 | -------------------------------------------------------------------------------- /go/10_recursion/Factorial_test.go: -------------------------------------------------------------------------------- 1 | package Recursion 2 | 3 | import "testing" 4 | 5 | func TestFac_Factorial(t *testing.T) { 6 | fac := NewFactorial(10) 7 | for i:=1; i<15; i++{ 8 | fac.Factorial(i) 9 | fac.Print(i) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /go/10_recursion/Fibonacci.go: -------------------------------------------------------------------------------- 1 | package Recursion 2 | 3 | import "fmt" 4 | 5 | // 递归实现斐波那契数列 6 | type Fibs struct { 7 | val map[int]int // 使用字典存储结果 8 | } 9 | 10 | func NewFibs(n int) *Fibs { 11 | return &Fibs{ 12 | make(map[int]int, n), 13 | } 14 | } 15 | 16 | func (fib *Fibs)Fibonacci(n int) int { 17 | if fib.val[n] != 0{ 18 | return fib.val[n] 19 | } 20 | if n <= 1 { 21 | fib.val[1] = 1 22 | return 1 23 | }else if n ==2{ 24 | fib.val[2] = 1 25 | return 1 26 | } else { 27 | res := fib.Fibonacci(n-1) + fib.Fibonacci(n-2) 28 | fib.val[n] = res 29 | return res 30 | } 31 | } 32 | 33 | func (fib *Fibs)Print(n int) { 34 | fmt.Println(fib.val[n]) 35 | } 36 | -------------------------------------------------------------------------------- /go/10_recursion/Fibonacci_test.go: -------------------------------------------------------------------------------- 1 | package Recursion 2 | 3 | import "testing" 4 | 5 | func TestFibs_Fibonacci(t *testing.T) { 6 | fib := NewFibs(10) 7 | for i:=1; i<15; i++{ 8 | fib.Fibonacci(i) 9 | fib.Print(i) 10 | } 11 | } -------------------------------------------------------------------------------- /go/10_recursion/RangAll.go: -------------------------------------------------------------------------------- 1 | package Recursion 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | // 实现一组数据集合的全排列 7 | type RangeType struct { 8 | value []interface{} 9 | } 10 | 11 | func NewRangeArray(n int) *RangeType { 12 | return &RangeType{ 13 | make([]interface{},n), 14 | } 15 | } 16 | 17 | func (slice *RangeType)RangeALL( start int) { 18 | len := len(slice.value) 19 | if start == len-1{ 20 | // 如果已经是最后位置,直接将数组数据合并输出 21 | fmt.Println(slice.value) 22 | } 23 | 24 | for i:=start; i a[j+1] { 17 | a[j], a[j+1] = a[j+1], a[j] 18 | //此次冒泡有数据交换 19 | flag = true 20 | } 21 | } 22 | // 如果没有交换数据,提前退出 23 | if !flag { 24 | break 25 | } 26 | } 27 | } 28 | 29 | // 插入排序,a表示数组,n表示数组大小 30 | func InsertionSort(a []int, n int) { 31 | if n <= 1 { 32 | return 33 | } 34 | for i := 1; i < n; i++ { 35 | value := a[i] 36 | j := i - 1 37 | //查找要插入的位置并移动数据 38 | for ; j >= 0; j-- { 39 | if a[j] > value { 40 | a[j+1] = a[j] 41 | } else { 42 | break 43 | } 44 | } 45 | a[j+1] = value 46 | } 47 | } 48 | 49 | // 选择排序,a表示数组,n表示数组大小 50 | func SelectionSort(a []int, n int) { 51 | if n <= 1 { 52 | return 53 | } 54 | for i := 0; i < n; i++ { 55 | // 查找最小值 56 | minIndex := i 57 | for j := i + 1; j < n; j++ { 58 | if a[j] < a[minIndex] { 59 | minIndex = j 60 | } 61 | } 62 | // 交换 63 | a[i], a[minIndex] = a[minIndex],a[i] 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /go/11_sorts/Sort_test.go: -------------------------------------------------------------------------------- 1 | package _1_sorts 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestBubbleSort(t *testing.T) { 9 | arr := []int{1,5,9,6,3,7,5,10} 10 | fmt.Println("排序前:",arr) 11 | BubbleSort(arr,len(arr)) 12 | fmt.Println("排序后:",arr) 13 | } 14 | 15 | func TestInsertionSort(t *testing.T) { 16 | arr := []int{1,5,9,6,3,7,5,10} 17 | fmt.Println("排序前:",arr) 18 | InsertionSort(arr,len(arr)) 19 | fmt.Println("排序后:",arr) 20 | } 21 | 22 | func TestSelectionSort(t *testing.T) { 23 | arr := []int{1,5,9,6,3,7,5,10} 24 | fmt.Println("排序前:",arr) 25 | SelectionSort(arr,len(arr)) 26 | fmt.Println("排序后:",arr) 27 | } 28 | -------------------------------------------------------------------------------- /go/12_sorts/MergeSort.go: -------------------------------------------------------------------------------- 1 | package _2_sorts 2 | 3 | func MergeSort(arr []int) { 4 | arrLen := len(arr) 5 | if arrLen <= 1 { 6 | return 7 | } 8 | 9 | mergeSort(arr, 0, arrLen-1) 10 | } 11 | 12 | func mergeSort(arr []int, start, end int) { 13 | if start >= end { 14 | return 15 | } 16 | 17 | mid := (start + end) / 2 18 | mergeSort(arr, start, mid) 19 | mergeSort(arr, mid+1, end) 20 | merge(arr, start, mid, end) 21 | } 22 | 23 | func merge(arr []int, start, mid, end int) { 24 | tmpArr := make([]int, end-start+1) 25 | 26 | i := start 27 | j := mid + 1 28 | k := 0 29 | for ; i <= mid && j <= end; k++ { 30 | if arr[i] <= arr[j] { 31 | tmpArr[k] = arr[i] 32 | i++ 33 | } else { 34 | tmpArr[k] = arr[j] 35 | j++ 36 | } 37 | } 38 | 39 | for ; i <= mid; i++ { 40 | tmpArr[k] = arr[i] 41 | k++ 42 | } 43 | for ; j <= end; j++ { 44 | tmpArr[k] = arr[j] 45 | k++ 46 | } 47 | copy(arr[start:end+1], tmpArr) 48 | } 49 | -------------------------------------------------------------------------------- /go/12_sorts/MergeSort_test.go: -------------------------------------------------------------------------------- 1 | package _2_sorts 2 | 3 | import "testing" 4 | 5 | func TestMergeSort(t *testing.T) { 6 | arr := []int{5, 4} 7 | MergeSort(arr) 8 | t.Log(arr) 9 | 10 | arr = []int{5, 4, 3, 2, 1} 11 | MergeSort(arr) 12 | t.Log(arr) 13 | } 14 | -------------------------------------------------------------------------------- /go/12_sorts/QuickSort.go: -------------------------------------------------------------------------------- 1 | package _2_sorts 2 | 3 | // QuickSort is quicksort methods for golang 4 | func QuickSort(arr []int) { 5 | separateSort(arr, 0, len(arr)-1) 6 | } 7 | 8 | func separateSort(arr []int, start, end int) { 9 | if start >= end { 10 | return 11 | } 12 | i := partition(arr, start, end) 13 | separateSort(arr, start, i-1) 14 | separateSort(arr, i+1, end) 15 | } 16 | 17 | func partition(arr []int, start, end int) int { 18 | // 选取最后一位当对比数字 19 | pivot := arr[end] 20 | 21 | var i = start 22 | for j := start; j < end; j++ { 23 | if arr[j] < pivot { 24 | if !(i == j) { 25 | // 交换位置 26 | arr[i], arr[j] = arr[j], arr[i] 27 | } 28 | i++ 29 | } 30 | } 31 | 32 | arr[i], arr[end] = arr[end], arr[i] 33 | 34 | return i 35 | } 36 | -------------------------------------------------------------------------------- /go/12_sorts/QuickSort_test.go: -------------------------------------------------------------------------------- 1 | package _2_sorts 2 | 3 | import ( 4 | "math/rand" 5 | "testing" 6 | ) 7 | 8 | func createRandomArr(length int) []int { 9 | arr := make([]int, length, length) 10 | for i := 0; i < length; i++ { 11 | arr[i] = rand.Intn(100) 12 | } 13 | return arr 14 | } 15 | 16 | func TestQuickSort(t *testing.T) { 17 | arr := []int{5, 4} 18 | QuickSort(arr) 19 | t.Log(arr) 20 | 21 | arr = createRandomArr(100) 22 | QuickSort(arr) 23 | t.Log(arr) 24 | } 25 | -------------------------------------------------------------------------------- /go/13_sorts/BucketSort_test.go: -------------------------------------------------------------------------------- 1 | package LinearSort 2 | 3 | import "testing" 4 | 5 | func TestBucketSort(t *testing.T) { 6 | a := []int{1,6,3,5,8,6,4} 7 | BucketSort(a) 8 | t.Log(a) 9 | } 10 | 11 | func TestBucketSortSimple(t *testing.T) { 12 | a := []int{1,6,3,5,8,6,4} 13 | BucketSortSimple(a) 14 | t.Log(a) 15 | } 16 | -------------------------------------------------------------------------------- /go/14_sorts/CountingSort.go: -------------------------------------------------------------------------------- 1 | package _4_sorts 2 | 3 | import "math" 4 | 5 | func CountingSort(a []int, n int) { 6 | if n <= 1 { 7 | return 8 | } 9 | 10 | var max int = math.MinInt32 11 | for i := range a { 12 | if a[i] > max { 13 | max = a[i] 14 | } 15 | } 16 | 17 | c := make([]int, max+1) 18 | for i := range a { 19 | c[a[i]]++ 20 | } 21 | for i := 1; i <= max; i++ { 22 | c[i] += c[i-1] 23 | } 24 | 25 | r := make([]int, n) 26 | for i := n - 1; i >= 0; i-- { 27 | index := c[a[i]] - 1 28 | r[index] = a[i] 29 | c[a[i]]-- 30 | } 31 | 32 | copy(a, r) 33 | } 34 | -------------------------------------------------------------------------------- /go/14_sorts/CountingSort_test.go: -------------------------------------------------------------------------------- 1 | package _4_sorts 2 | 3 | import "testing" 4 | 5 | func TestCountingSort(t *testing.T) { 6 | arr := []int{5, 4} 7 | CountingSort(arr, len(arr)) 8 | t.Log(arr) 9 | 10 | arr = []int{5, 4, 3, 2, 1} 11 | CountingSort(arr, len(arr)) 12 | t.Log(arr) 13 | } 14 | -------------------------------------------------------------------------------- /go/17_skiplist/skiplist_test.go: -------------------------------------------------------------------------------- 1 | package _7_skiplist 2 | 3 | import "testing" 4 | 5 | func TestSkipList(t *testing.T) { 6 | sl := NewSkipList() 7 | 8 | sl.Insert("leo", 95) 9 | t.Log(sl.head.forwards[0]) 10 | t.Log(sl.head.forwards[0].forwards[0]) 11 | t.Log(sl) 12 | t.Log("-----------------------------") 13 | 14 | sl.Insert("jack", 88) 15 | t.Log(sl.head.forwards[0]) 16 | t.Log(sl.head.forwards[0].forwards[0]) 17 | t.Log(sl.head.forwards[0].forwards[0].forwards[0]) 18 | t.Log(sl) 19 | t.Log("-----------------------------") 20 | 21 | sl.Insert("lily", 100) 22 | t.Log(sl.head.forwards[0]) 23 | t.Log(sl.head.forwards[0].forwards[0]) 24 | t.Log(sl.head.forwards[0].forwards[0].forwards[0]) 25 | t.Log(sl.head.forwards[0].forwards[0].forwards[0].forwards[0]) 26 | t.Log(sl) 27 | t.Log("-----------------------------") 28 | 29 | t.Log(sl.Find("jack", 88)) 30 | t.Log("-----------------------------") 31 | 32 | sl.Delete("leo", 95) 33 | t.Log(sl.head.forwards[0]) 34 | t.Log(sl.head.forwards[0].forwards[0]) 35 | t.Log(sl.head.forwards[0].forwards[0].forwards[0]) 36 | t.Log(sl) 37 | t.Log("-----------------------------") 38 | } 39 | -------------------------------------------------------------------------------- /go/24_tree/BinaryTree_test.go: -------------------------------------------------------------------------------- 1 | package _4_tree 2 | 3 | import "testing" 4 | 5 | func TestBinaryTree_InOrderTraverse(t *testing.T) { 6 | binaryTree := NewBinaryTree(1) 7 | binaryTree.root.left = NewNode(3) 8 | binaryTree.root.right = NewNode(4) 9 | binaryTree.root.right.left = NewNode(5) 10 | 11 | binaryTree.InOrderTraverse() 12 | } 13 | 14 | func TestBinaryTree_PreOrderTraverse(t *testing.T) { 15 | binaryTree := NewBinaryTree(1) 16 | binaryTree.root.left = NewNode(3) 17 | binaryTree.root.right = NewNode(4) 18 | binaryTree.root.right.left = NewNode(5) 19 | 20 | binaryTree.PreOrderTraverse() 21 | } 22 | 23 | func TestBinaryTree_PostOrderTraverse(t *testing.T) { 24 | binaryTree := NewBinaryTree(1) 25 | binaryTree.root.left = NewNode(3) 26 | binaryTree.root.right = NewNode(4) 27 | binaryTree.root.right.left = NewNode(5) 28 | 29 | binaryTree.PostOrderTraverse() 30 | } 31 | 32 | func TestBinaryTree_PostOrderTraverse2(t *testing.T) { 33 | binaryTree := NewBinaryTree(1) 34 | binaryTree.root.left = NewNode(3) 35 | binaryTree.root.right = NewNode(4) 36 | binaryTree.root.right.left = NewNode(5) 37 | 38 | binaryTree.PostOrderTraverse2() 39 | } 40 | -------------------------------------------------------------------------------- /go/24_tree/TreeNode.go: -------------------------------------------------------------------------------- 1 | package _4_tree 2 | 3 | import "fmt" 4 | 5 | type Node struct { 6 | data interface{} 7 | left *Node 8 | right *Node 9 | } 10 | 11 | func NewNode(data interface{}) *Node { 12 | return &Node{data: data} 13 | } 14 | 15 | func (this *Node) String() string { 16 | return fmt.Sprintf("v:%+v, left:%+v, right:%+v", this.data, this.left, this.right) 17 | } 18 | -------------------------------------------------------------------------------- /go/28_heap/heap_sort.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | //build a heap 4 | func buidHeap(a []int, n int) { 5 | 6 | //heapify from the last parent node 7 | for i := n / 2; i >= 1; i-- { 8 | heapifyUpToDown(a, i, n) 9 | } 10 | 11 | } 12 | 13 | //sort by ascend, a index begin from 1, has n elements 14 | func sort(a []int, n int) { 15 | buidHeap(a, n) 16 | 17 | k := n 18 | for k >= 1 { 19 | swap(a, 1, k) 20 | heapifyUpToDown(a, 1, k-1) 21 | k-- 22 | } 23 | } 24 | 25 | //heapify from up to down , node index = top 26 | func heapifyUpToDown(a []int, top int, count int) { 27 | 28 | for i := top; i <= count/2; { 29 | 30 | maxIndex := i 31 | if a[i] < a[i*2] { 32 | maxIndex = i * 2 33 | } 34 | 35 | if i*2+1 <= count && a[maxIndex] < a[i*2+1] { 36 | maxIndex = i*2 + 1 37 | } 38 | 39 | if maxIndex == i { 40 | break 41 | } 42 | 43 | swap(a, i, maxIndex) 44 | i = maxIndex 45 | } 46 | 47 | } 48 | 49 | //swap two elements 50 | func swap(a []int, i int, j int) { 51 | tmp := a[i] 52 | a[i] = a[j] 53 | a[j] = tmp 54 | } 55 | -------------------------------------------------------------------------------- /go/29_priority_queue/heap.go: -------------------------------------------------------------------------------- 1 | package pqueue 2 | 3 | func adjustHeap(src []Node, start, end int) { 4 | if start >= end { 5 | return 6 | } 7 | 8 | // 只需要保证优先级最高的节点在 src[1] 的位置即可 9 | for i := end / 2; i >= start; i-- { 10 | high := i 11 | if src[high].priority < src[2*i].priority { 12 | high = 2 * i 13 | } 14 | if 2*i+1 <= end && src[high].priority < src[2*i+1].priority { 15 | high = 2*i + 1 16 | } 17 | if high == i { 18 | continue 19 | } 20 | src[high], src[i] = src[i], src[high] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /go/29_priority_queue/heap_test.go: -------------------------------------------------------------------------------- 1 | package pqueue 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func Test_AdjustHeap(t *testing.T) { 10 | list := []Node{Node{0, 0}, Node{1, 1}, Node{2, 2}, Node{3, 3}, Node{4, 1}, Node{6, 6}} 11 | 12 | adjustHeap(list, 1, len(list)-1) 13 | assert.Equal(t, 6, list[1].value) 14 | } 15 | -------------------------------------------------------------------------------- /go/29_priority_queue/priority_queue.go: -------------------------------------------------------------------------------- 1 | package pqueue 2 | 3 | // Node 队列节点 4 | type Node struct { 5 | value int 6 | priority int 7 | } 8 | 9 | // PQueue priority queue 10 | type PQueue struct { 11 | heap []Node 12 | 13 | capacity int 14 | used int 15 | } 16 | 17 | // NewPriorityQueue new 18 | func NewPriorityQueue(capacity int) PQueue { 19 | return PQueue{ 20 | heap: make([]Node, capacity+1, capacity+1), 21 | capacity: capacity, 22 | used: 0, 23 | } 24 | } 25 | 26 | // Push 入队 27 | func (q *PQueue) Push(node Node) { 28 | 29 | if q.used > q.capacity { 30 | // 队列已满 31 | return 32 | } 33 | q.used++ 34 | q.heap[q.used] = node 35 | // 堆化可以放在 Pop 中 36 | // adjustHeap(q.heap, 1, q.used) 37 | } 38 | 39 | // Pop 出队列 40 | func (q *PQueue) Pop() Node { 41 | if q.used == 0 { 42 | return Node{-1, -1} 43 | } 44 | // 先堆化, 再取堆顶元素 45 | adjustHeap(q.heap, 1, q.used) 46 | node := q.heap[1] 47 | 48 | q.heap[1] = q.heap[q.used] 49 | q.used-- 50 | 51 | return node 52 | } 53 | 54 | // Top 获取队列顶部元素 55 | func (q *PQueue) Top() Node { 56 | if q.used == 0 { 57 | return Node{-1, -1} 58 | } 59 | 60 | adjustHeap(q.heap, 1, q.used) 61 | return q.heap[1] 62 | } 63 | -------------------------------------------------------------------------------- /go/29_priority_queue/readme.md: -------------------------------------------------------------------------------- 1 | 2 | ## TODO 3 | - 该实现方式不能保证 相同优先级的元素在出队列时 和入队列的顺序是一致的 -------------------------------------------------------------------------------- /go/32_string/string_bf.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | //BF search pattern index, return the first match subs start index 8 | func bfSearch(main string, pattern string) int { 9 | 10 | //defensive 11 | if len(main) == 0 || len(pattern) == 0 || len(main) < len(pattern) { 12 | return -1 13 | } 14 | 15 | for i := 0; i <= len(main)-len(pattern); i++ { 16 | subStr := main[i : i+len(pattern)] 17 | if subStr == pattern { 18 | return i 19 | } 20 | } 21 | 22 | return -1 23 | } 24 | 25 | func main() { 26 | 27 | main := "abcd227fac" 28 | pattern := "ac" 29 | fmt.Println(bfSearch(main, pattern)) 30 | } 31 | -------------------------------------------------------------------------------- /go/41_dynamic_programming/backtracking/leastcoins_test.go: -------------------------------------------------------------------------------- 1 | package backtracking 2 | 3 | import "testing" 4 | 5 | func TestFindLeastCoins(t *testing.T) { 6 | 7 | coinOptions := []int{1, 3, 5, 10, 50} 8 | 9 | Cnt = 0 10 | result := LeastCoins(9, coinOptions) 11 | 12 | t.Log("test 1 =====================") 13 | if result != 3 { 14 | t.Logf("least coins %d", result) 15 | t.Error("failed") 16 | } 17 | t.Logf("cnt===%d", Cnt) 18 | 19 | Cnt = 0 20 | t.Log("test 2 =====================") 21 | result = LeastCoins(36, coinOptions) 22 | 23 | if result != 5 { 24 | t.Logf("least coins %d", result) 25 | t.Error("failed") 26 | } 27 | t.Logf("cnt===%d", Cnt) 28 | 29 | } 30 | 31 | func TestFindLeastCoins2(t *testing.T) { 32 | 33 | coinOptions := []int{1, 3, 5, 10, 50} 34 | 35 | Cnt = 0 36 | result := LeastCoins2(9, coinOptions) 37 | 38 | t.Log("test 1 =====================") 39 | if result != 3 { 40 | t.Logf("least coins %d", result) 41 | t.Error("failed") 42 | } 43 | 44 | t.Logf("cnt===%d", Cnt) 45 | 46 | Cnt = 0 47 | t.Log("test 2 =====================") 48 | result = LeastCoins2(36, coinOptions) 49 | 50 | if result != 5 { 51 | t.Logf("least coins %d", result) 52 | t.Error("failed") 53 | } 54 | t.Logf("cnt===%d", Cnt) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /go/41_dynamic_programming/dp/leastcoins_test.go: -------------------------------------------------------------------------------- 1 | package dp 2 | 3 | import "testing" 4 | 5 | func TestFindLeastCoins(t *testing.T) { 6 | 7 | coinOptions := []int{1, 3, 5, 10, 50} 8 | 9 | Cnt = 0 10 | result := LeastCoins(9, coinOptions) 11 | 12 | t.Log("test 1 =====================") 13 | if result != 3 { 14 | t.Logf("least coins %d", result) 15 | t.Error("failed") 16 | } 17 | t.Logf("cnt===%d", Cnt) 18 | 19 | Cnt = 0 20 | t.Log("test 2 =====================") 21 | result = LeastCoins(36, coinOptions) 22 | 23 | if result != 5 { 24 | t.Logf("least coins %d", result) 25 | t.Error("failed") 26 | } 27 | t.Logf("cnt===%d", Cnt) 28 | 29 | } 30 | 31 | func TestFindLeastCoins2(t *testing.T) { 32 | 33 | coinOptions := []int{1, 3, 5, 10, 50} 34 | 35 | Cnt = 0 36 | result := LeastCoins2(9, coinOptions) 37 | 38 | t.Log("test 1 =====================") 39 | if result != 3 { 40 | t.Logf("least coins %d", result) 41 | t.Error("failed") 42 | } 43 | t.Logf("cnt===%d", Cnt) 44 | 45 | Cnt = 0 46 | t.Log("test 2 =====================") 47 | result = LeastCoins2(36, coinOptions) 48 | 49 | if result != 5 { 50 | t.Logf("least coins %d", result) 51 | t.Error("failed") 52 | } 53 | t.Logf("cnt===%d", Cnt) 54 | 55 | } 56 | -------------------------------------------------------------------------------- /go/42_dynamic_programming/longest_common_substring.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func lsc(s1 string, s2 string) int { 6 | m := len(s1) 7 | n := len(s2) 8 | 9 | memo := make([][]int, m + 1) 10 | for i := 0; i < m + 1; i++ { 11 | memo[i] = make([]int, n + 1) 12 | } 13 | 14 | 15 | for i := 1; i < m + 1; i++ { 16 | for j := 1; j < n + 1; j++ { 17 | if s1[i - 1] == s2[j - 1] { 18 | memo[i][j] = memo[i - 1][j - 1] + 1 19 | } 20 | } 21 | } 22 | 23 | fmt.Println(memo) 24 | longest := 0 25 | for i, _ := range memo { 26 | for j, e2 := range memo[i] { 27 | if longest < memo[i][j] { 28 | longest = e2 29 | } 30 | } 31 | } 32 | 33 | return longest 34 | } 35 | 36 | func main() { 37 | fmt.Println(lsc("blue", "clues")) //3 38 | fmt.Println(lsc("fosh", "fish")) //2 39 | fmt.Println(lsc("fosh", "fort")) //2 40 | fmt.Println(lsc("hish", "fish")) //3 41 | fmt.Println(lsc("hish", "vista")) //2 42 | } -------------------------------------------------------------------------------- /go/45_bitmap/bitmap.go: -------------------------------------------------------------------------------- 1 | package bitmap 2 | 3 | // BitMap implement bitmap 4 | type BitMap []byte 5 | 6 | // New create BitMap 7 | func New(length uint) BitMap { 8 | return make([]byte, length/8+1) 9 | } 10 | 11 | // Set set value in bitmap 12 | func (b BitMap) Set(value uint) { 13 | byteIndex := value / 8 14 | if byteIndex >= uint(len(b)) { 15 | return 16 | } 17 | bitIndex := value % 8 18 | []byte(b)[byteIndex] |= 1 << bitIndex 19 | } 20 | 21 | // Get check whether value exist or not 22 | func (b BitMap) Get(value uint) bool { 23 | byteIndex := value / 8 24 | if byteIndex >= uint(len(b)) { 25 | return false 26 | } 27 | bitIndex := value % 8 28 | return []byte(b)[byteIndex]&(1<= r) return; 16 | 17 | int q = partition(a, p, r); // 获取分区点 18 | quickSortInternally(a, p, q-1); 19 | quickSortInternally(a, q+1, r); 20 | } 21 | 22 | private static int partition(int[] a, int p, int r) { 23 | int pivot = a[r]; 24 | int i = p; 25 | for(int j = p; j < r; ++j) { 26 | if (a[j] < pivot) { 27 | if (i == j) { 28 | ++i; 29 | } else { 30 | int tmp = a[i]; 31 | a[i++] = a[j]; 32 | a[j] = tmp; 33 | } 34 | } 35 | } 36 | 37 | int tmp = a[i]; 38 | a[i] = a[r]; 39 | a[r] = tmp; 40 | 41 | System.out.println("i=" + i); 42 | return i; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /java/13_sorts/CountingSort.java: -------------------------------------------------------------------------------- 1 | package sorts; 2 | 3 | /** 4 | * 计数排序 5 | * 6 | * Author: ZHENG 7 | */ 8 | public class CountingSort { 9 | 10 | // 计数排序,a是数组,n是数组大小。假设数组中存储的都是非负整数。 11 | public static void countingSort(int[] a, int n) { 12 | if (n <= 1) return; 13 | 14 | // 查找数组中数据的范围 15 | int max = a[0]; 16 | for (int i = 1; i < n; ++i) { 17 | if (max < a[i]) { 18 | max = a[i]; 19 | } 20 | } 21 | 22 | // 申请一个计数数组c,下标大小[0,max] 23 | int[] c = new int[max + 1]; 24 | 25 | // 计算每个元素的个数,放入c中 26 | for (int i = 0; i < n; ++i) { 27 | c[a[i]]++; 28 | } 29 | 30 | // 依次累加 31 | for (int i = 1; i < max + 1; ++i) { 32 | c[i] = c[i-1] + c[i]; 33 | } 34 | 35 | // 临时数组r,存储排序之后的结果 36 | int[] r = new int[n]; 37 | // 计算排序的关键步骤了,有点难理解 38 | for (int i = n - 1; i >= 0; --i) { 39 | int index = c[a[i]]-1; 40 | r[index] = a[i]; 41 | c[a[i]]--; 42 | } 43 | 44 | // 将结果拷贝会a数组 45 | for (int i = 0; i < n; ++i) { 46 | a[i] = r[i]; 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /java/32_BFRK: -------------------------------------------------------------------------------- 1 | public static int bF(String a,String b) { 2 | int m=a.length(),n=b.length(),k; 3 | char[] a1=a.toCharArray(); 4 | char[] b1=b.toCharArray(); 5 | for(int i=0;i<=m-n;i++) { 6 | k=0; 7 | for(int j=0;j len) { 9 | return -1; 10 | } 11 | let p = partition(arr, 0, len - 1); 12 | while (p + 1 !== k) { 13 | if (p + 1 > k) { 14 | p = partition(arr, 0, p - 1); 15 | } else { 16 | p = partition(arr, p + 1, len - 1); 17 | } 18 | } 19 | return arr[p]; 20 | } 21 | 22 | function partition(arr, start, end) { 23 | let i = start; 24 | let pivot = arr[end]; 25 | for (let j = start; j < end; j++) { 26 | if (arr[j] < pivot) { 27 | swap(arr, i, j); 28 | i += 1; 29 | } 30 | } 31 | swap(arr, i, end); 32 | return i; 33 | } 34 | 35 | function swap(arr, i, j) { 36 | if (i === j) return; 37 | let tmp = arr[i]; 38 | arr[i] = arr[j]; 39 | arr[j] = tmp; 40 | } 41 | -------------------------------------------------------------------------------- /javascript/12_sorts/MergeSort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 归并排序 3 | * 4 | * Author: nameczz 5 | */ 6 | 7 | const mergeArr = (left, right) => { 8 | let temp = [] 9 | let leftIndex = 0 10 | let rightIndex = 0 11 | // 判断2个数组中元素大小,依次插入数组 12 | while (left.length > leftIndex && right.length > rightIndex) { 13 | if (left[leftIndex] <= right[rightIndex]) { 14 | temp.push(left[leftIndex]) 15 | leftIndex++ 16 | } else { 17 | temp.push(right[rightIndex]) 18 | rightIndex++ 19 | } 20 | } 21 | // 合并 多余数组 22 | return temp.concat(left.slice(leftIndex)).concat(right.slice(rightIndex)) 23 | } 24 | 25 | const mergeSort = (arr) => { 26 | // 当任意数组分解到只有一个时返回。 27 | if (arr.length <= 1) return arr 28 | const middle = Math.floor(arr.length / 2) // 找到中间值 29 | const left = arr.slice(0, middle) // 分割数组 30 | const right = arr.slice(middle) 31 | // 递归 分解 合并 32 | return mergeArr(mergeSort(left), mergeSort(right)) 33 | } 34 | 35 | const testArr = [] 36 | let i = 0 37 | while (i < 100) { 38 | testArr.push(Math.floor(Math.random() * 1000)) 39 | i++ 40 | } 41 | 42 | const res = mergeSort(testArr) 43 | console.log(res) -------------------------------------------------------------------------------- /javascript/12_sorts/QuickSort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 快速排序 3 | * 4 | * Author: nameczz 5 | */ 6 | 7 | const swap = (arr, i, j) => { 8 | const temp = arr[i] 9 | arr[i] = arr[j] 10 | arr[j] = temp 11 | } 12 | 13 | // 获取 pivot 交换完后的index 14 | const partition = (arr, pivot, left, right) => { 15 | const pivotVal = arr[pivot] 16 | let startIndex = left 17 | for (let i = left; i < right; i++) { 18 | if (arr[i] < pivotVal) { 19 | swap(arr, i, startIndex) 20 | startIndex++ 21 | } 22 | } 23 | swap(arr, startIndex, pivot) 24 | return startIndex 25 | } 26 | 27 | const quickSort = (arr, left, right) => { 28 | if (left < right) { 29 | let pivot = right 30 | let partitionIndex = partition(arr, pivot, left, right) 31 | quickSort(arr, left, partitionIndex - 1 < left ? left : partitionIndex - 1) 32 | quickSort(arr, partitionIndex + 1 > right ? right : partitionIndex + 1, right) 33 | } 34 | 35 | } 36 | 37 | 38 | const testArr = [] 39 | let i = 0 40 | while (i < 10) { 41 | testArr.push(Math.floor(Math.random() * 1000)) 42 | i++ 43 | } 44 | console.log('unsort', testArr) 45 | quickSort(testArr, 0, testArr.length - 1); 46 | console.log('sort', testArr) -------------------------------------------------------------------------------- /javascript/13_sorts/countingSort.js: -------------------------------------------------------------------------------- 1 | const countingSort = array => { 2 | if (array.length <= 1) return 3 | 4 | const max = findMaxValue(array) 5 | const counts = new Array(max + 1) 6 | 7 | // 计算每个元素的个数,放入到counts桶中 8 | // counts下标是元素,值是元素个数 9 | array.forEach(element => { 10 | if (!counts[element]) { 11 | counts[element] = 0 12 | } 13 | counts[element]++ 14 | }) 15 | 16 | // counts下标是元素,值是元素个数 17 | // 例如: array: [6, 4, 3, 1], counts: [empty, 1, empty, 1, 1, empty, 1] 18 | // i是元素, count是元素个数 19 | let sortedIndex = 0 20 | counts.forEach((count, i) => { 21 | while (count > 0) { 22 | array[sortedIndex] = i 23 | sortedIndex++ 24 | count-- 25 | } 26 | }) 27 | // return array 28 | } 29 | 30 | function findMaxValue(array) { 31 | let max = array[0] 32 | for (let i = 1; i < array.length; i++) { 33 | if (array[i] > max) { 34 | max = array[i] 35 | } 36 | } 37 | return max 38 | } 39 | -------------------------------------------------------------------------------- /javascript/15_binary/binaryFind.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 二分查找 3 | * 4 | * Author: nameczz 5 | */ 6 | // 数组必须有序 不存在重复 7 | const biaryFind = (sortedArr, target) => { 8 | if (sortedArr.length === 0) return -1 9 | let low = 0 10 | let high = sortedArr.length - 1 11 | while (low <= high) { 12 | const mid = Math.floor((low + high) / 2) 13 | if (target === sortedArr[mid]) { 14 | return mid 15 | } else if (target < sortedArr[mid]) { 16 | high = mid - 1 17 | } else { 18 | low = mid + 1 19 | } 20 | } 21 | return -1 22 | } 23 | const arr = [1, 4, 5, 6, 7, 8, 10, 11, 23, 42, 44, 54, 56, 77, 102] 24 | console.log(biaryFind(arr, 44)) 25 | console.log(biaryFind(arr, 1)) 26 | console.log(biaryFind(arr, 102)) 27 | console.log(biaryFind(arr, 1111)) -------------------------------------------------------------------------------- /javascript/45_bitmap/bitmap.js: -------------------------------------------------------------------------------- 1 | 2 | class BitMap { 3 | constructor(n) { 4 | this.nbits = n; 5 | this.blk = new Array(Math.floor(n / 16) + 1); 6 | this.blk.fill(0); 7 | } 8 | 9 | get(k) { 10 | if( k > this.nbits) return false; 11 | 12 | let byteIndex = Math.floor(k / 16); 13 | let bitIndex = k % 16; 14 | 15 | return !((this.blk[byteIndex] & (1 << bitIndex)) === 0); 16 | } 17 | 18 | set(k) { 19 | if( k > this.nbits) return; 20 | 21 | let byteIndex = Math.floor(k / 16); 22 | let bitIndex = k % 16; 23 | 24 | this.blk[byteIndex] = this.blk[byteIndex] | (1 << bitIndex); 25 | 26 | } 27 | } 28 | 29 | let aBitMap = new BitMap(20); 30 | 31 | aBitMap.set(1); 32 | aBitMap.set(3); 33 | aBitMap.set(5); 34 | aBitMap.set(7); 35 | aBitMap.set(9); 36 | aBitMap.set(11); 37 | aBitMap.set(13); 38 | aBitMap.set(15); 39 | aBitMap.set(17); 40 | aBitMap.set(19); 41 | 42 | for(let i = 0; i < 21; i++) { 43 | console.log(aBitMap.get(i)); 44 | } -------------------------------------------------------------------------------- /kotlin/08_stack/StackBasedOnLinkedList.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * 基于链表实现的栈。 3 | * 4 | * Author: Zackratos 5 | */ 6 | 7 | class StackBasedOnLinkedList { 8 | 9 | private var top: Node? = null 10 | 11 | fun push(value: Int) { 12 | val newNode = Node(value, null) 13 | // 不管 top 是不是 null,都可以这么写 14 | newNode.next = top 15 | top = newNode 16 | } 17 | 18 | fun pop(): Int { 19 | if (top == null) return -1 20 | val node = top 21 | top = top!!.next 22 | return node!!.data 23 | } 24 | 25 | fun printAll() { 26 | var p = top 27 | while (p != null) { 28 | print("${p.data} ") 29 | p = p.next 30 | } 31 | println() 32 | } 33 | 34 | class Node(var data: Int, var next: Node?) 35 | 36 | } -------------------------------------------------------------------------------- /notes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/notes/.gitkeep -------------------------------------------------------------------------------- /notes/10_recursion/readme.md: -------------------------------------------------------------------------------- 1 | # 递归 2 | 3 | ## 三个条件 4 | 5 | * 可分解为子问题 6 | * 子问题与原问题解法一致,只有规模上的不同 7 | * 有终止条件 8 | 9 | ## 写递归代码 10 | 11 | * 整理出递推公式 12 | * 确定好终止条件 13 | * 「翻译」成代码 14 | 15 | 关键: 16 | 17 | > 只要遇到递归,我们就把它抽象成一个递推公式,不用想一层层的调用关系,不要试图用人脑去分解每一个步骤。 18 | 19 | ## 警惕 20 | 21 | * 堆栈溢出 <- 递归深度过大 22 | * 重复计算 <- 递归过程中的不同分支,重复计算相同子问题 23 | * 保存子问题结果(map/dict) 24 | * 空间复杂度高 <- 递归函数调用带来的消耗 25 | 26 | ## 递归改写非递归 27 | 28 | 本质:人肉模拟函数调用堆栈。 29 | -------------------------------------------------------------------------------- /notes/12_sorts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/notes/12_sorts/.gitkeep -------------------------------------------------------------------------------- /notes/13_sorts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/notes/13_sorts/.gitkeep -------------------------------------------------------------------------------- /notes/14_sorts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/notes/14_sorts/.gitkeep -------------------------------------------------------------------------------- /notes/14_sorts/readme.md: -------------------------------------------------------------------------------- 1 | # 排序优化 2 | 3 | ## 如何取舍排序算法? 4 | 5 | * 排序规模小 —— $O(n^2)$ 的算法(通常是插排) 6 | * 排序规模大 —— $O(n\log n)$ 的算法(通常不用归并排序) 7 | 8 | ## 如何优化快速排序? 9 | 10 | 参考:[谈谈内省式排序算法](https://liam.page/2018/08/29/introspective-sort/) 11 | -------------------------------------------------------------------------------- /notes/15_bsearch/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/notes/15_bsearch/.gitkeep -------------------------------------------------------------------------------- /notes/15_bsearch/readme.md: -------------------------------------------------------------------------------- 1 | # 二分查找(上) 2 | 3 | ## 算法描述 4 | 5 | 二分查找(Binary Search)也叫折半查找,是针对有序数据集合的查找算法。其描述十分简单: 6 | 7 | * 折半取中,判断元素与目标元素的大小关系 8 | * 小于——往前继续折半 9 | * 大于——往后继续折半 10 | * 等于——返回 11 | 12 | 关于它的复杂度分析,参见[谈谈基于比较的排序算法的复杂度下界](https://liam.page/2018/08/28/lower-bound-of-comparation-based-sort-algorithm/)中的相关信息。它的复杂度是 $O(\log n)$。 13 | 14 | ## $O(\log n)$ 的惊人之处 15 | 16 | 在 42 亿个数据中用二分查找一个数据,最多需要比较 32 次。 17 | 18 | ## 适用场景 19 | 20 | * 依赖顺序表结构 21 | * 数据本身必须有序 22 | * 数据量相对比较元素的开销要足够大——不然遍历即可 23 | * 数据量相对内存空间不能太大——不然顺序表装不下 24 | -------------------------------------------------------------------------------- /notes/16_bsearch/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/notes/16_bsearch/.gitkeep -------------------------------------------------------------------------------- /notes/17_skiplist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/notes/17_skiplist/.gitkeep -------------------------------------------------------------------------------- /notes/18_hashtable/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/notes/18_hashtable/.gitkeep -------------------------------------------------------------------------------- /notes/19_hashtable/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/notes/19_hashtable/.gitkeep -------------------------------------------------------------------------------- /notes/19_hashtable/readme.md: -------------------------------------------------------------------------------- 1 | # 散列表 2 | 3 | 核心:散列表的效率并不总是 $O(1)$,仅仅是在理论上能达到 $O(1)$。实际情况中,恶意攻击者可以通过精心构造数据,使得散列表的性能急剧下降。 4 | 5 | 如何设计一个工业级的散列表? 6 | 7 | ## 散列函数 8 | 9 | * 不能过于复杂——避免散列过程耗时 10 | * 散列函数的结果要尽可能均匀——最小化散列冲突 11 | 12 | ## 装载因子过大怎么办 13 | 14 | 动态扩容。涉及到 rehash,效率可能很低。 15 | 16 | ![](https://static001.geekbang.org/resource/image/67/43/67d12e07a7d673a9c1d14354ad029443.jpg) 17 | 18 | 如何避免低效扩容? 19 | 20 | ——将 rehash 的步骤,均摊到每一次插入中去: 21 | 22 | * 申请新的空间 23 | * 不立即使用 24 | * 每次来了新的数据,往新表插入数据 25 | * 同时,取出旧表的一个数据,插入新表 26 | 27 | ![](https://static001.geekbang.org/resource/image/6d/cb/6d6736f986ec4b75dabc5472965fb9cb.jpg) 28 | 29 | ## 解决冲突 30 | 31 | 开放寻址法,优点: 32 | 33 | * 不需要额外空间 34 | * 有效利用 CPU 缓存 35 | * 方便序列化 36 | 37 | 开放寻址法,缺点: 38 | 39 | * 查找、删除数据时,涉及到 `delete` 标志,相对麻烦 40 | * 冲突的代价更高 41 | * 对装载因子敏感 42 | 43 | 链表法,优点: 44 | 45 | * 内存利用率较高——链表的优点 46 | * 对装载因子不敏感 47 | 48 | 链表法,缺点: 49 | 50 | * 需要额外的空间(保存指针) 51 | * 对 CPU 缓存不友好 52 | 53 | ——将链表改造成更高效的数据结构,例如跳表、红黑树 54 | 55 | ## 举个栗子(JAVA 中的 HashMap) 56 | 57 | * 初始大小:16 58 | * 装载因子:超过 0.75 时动态扩容 59 | * 散列冲突:优化版的链表法(当槽位冲突元素超过 8 时使用红黑树,否则使用链表) 60 | -------------------------------------------------------------------------------- /notes/20_hashtable/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/notes/20_hashtable/.gitkeep -------------------------------------------------------------------------------- /notes/20_hashtable/readme.md: -------------------------------------------------------------------------------- 1 | # 散列表 2 | 3 | 散列表和链表的组合?为什么呢? 4 | 5 | * 链表:涉及查找的操作慢,不连续存储; 6 | * 顺序表:支持随机访问,连续存储。 7 | 8 | 散列表 + 链表:结合优点、规避缺点。 9 | 10 | ## 结合散列表的 LRU 缓存淘汰算法 11 | 12 | 缓存的操作接口: 13 | 14 | * 向缓存添加数据 15 | * 从缓存删除数据 16 | * 在缓存中查找数据 17 | 18 | 然而——不管是添加还是删除,都涉及到查找数据。因此,单纯的链表效率低下。 19 | 20 | 魔改一把! 21 | 22 | ![](https://static001.geekbang.org/resource/image/ea/6e/eaefd5f4028cc7d4cfbb56b24ce8ae6e.jpg) 23 | 24 | * `prev` 和 `next`:双向链表——LRU 的链表 25 | * `hnext`:单向链表——解决散列冲突的链表 26 | 27 | 操作: 28 | 29 | * 在缓存中查找数据:利用散列表 30 | * 从缓存中删除数据:先利用散列表寻找数据,然后删除——改链表就好了,效率很高 31 | * 向缓存中添加数据:先利用散列表寻找数据,如果找到了,LRU 更新;如果没找到,直接添加在 LRU 链表尾部 32 | 33 | ## Java: LinkedHashMap 34 | 35 | 遍历时,按照访问顺序遍历。实现结构,与上述 LRU 的结构完全相同——只不过它不是缓存,不限制容量大小。 36 | -------------------------------------------------------------------------------- /object-c/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/object-c/.gitkeep -------------------------------------------------------------------------------- /object-c/05_array/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/object-c/05_array/.gitkeep -------------------------------------------------------------------------------- /object-c/05_array/MyArray.h: -------------------------------------------------------------------------------- 1 | // 2 | // MyArray.h 3 | // algo 4 | // 5 | // Created by Wenru Dong on 2018/10/3. 6 | // Copyright © 2018年 Wenru Dong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MyArray : NSObject 12 | 13 | - (instancetype)initWithCapacity:(NSUInteger)capacity; 14 | - (id)objectAtIndexedSubscript:(NSUInteger)index; 15 | - (void)removeObjectAtIndex:(NSUInteger)index; 16 | - (void)insertObject:(id)anObject atIndex:(NSUInteger)index; 17 | - (void)addObject:(id)anObject; 18 | - (void)printAll; 19 | @end 20 | -------------------------------------------------------------------------------- /object-c/06_linkedlist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/object-c/06_linkedlist/.gitkeep -------------------------------------------------------------------------------- /object-c/06_linkedlist/ListNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // ListNode.h 3 | // algo 4 | // 5 | // Created by Wenru Dong on 2018/10/6. 6 | // Copyright © 2018年 Wenru Dong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ListNode : NSObject 12 | 13 | @property int value; 14 | @property ListNode *next; 15 | 16 | - (instancetype)initWithValue:(int)value; 17 | + (instancetype)nodeWithValue:(int)value; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /object-c/06_linkedlist/ListNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // ListNode.m 3 | // algo 4 | // 5 | // Created by Wenru Dong on 2018/10/6. 6 | // Copyright © 2018年 Wenru Dong. All rights reserved. 7 | // 8 | 9 | #import "ListNode.h" 10 | 11 | @implementation ListNode 12 | 13 | - (instancetype)initWithValue:(int)value { 14 | if (self = [super init]) { 15 | _value = value; 16 | } 17 | return self; 18 | } 19 | 20 | + (instancetype)nodeWithValue:(int)value { 21 | return [[self alloc] initWithValue:value]; 22 | } 23 | 24 | - (NSString*)debugDescription { 25 | return [NSString stringWithFormat:@"%d", _value]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /object-c/06_linkedlist/SinglyLinkedList.h: -------------------------------------------------------------------------------- 1 | // 2 | // SinglyLinkedList.h 3 | // algo 4 | // 5 | // Created by Wenru Dong on 2018/10/6. 6 | // Copyright © 2018年 Wenru Dong. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ListNode.h" 11 | 12 | @interface SinglyLinkedList : NSObject 13 | 14 | @property ListNode* head; 15 | 16 | - (ListNode*)nodeWithValue:(int)value; 17 | - (ListNode*)nodeAtIndex:(NSUInteger)index; 18 | 19 | - (void)insertNodeWithValue:(int)value; 20 | - (void)insertNode:(nonnull ListNode*)node; 21 | + (void)insertNodeWithValue:(int)value afterNode:(nonnull ListNode*)node; 22 | + (void)insertNode:(nonnull ListNode*)aNode afterNode:(nonnull ListNode*)node; 23 | - (void)insertNodeWithValue:(int)value beforeNode:(nonnull ListNode*)node; 24 | - (void)insertNode:(nonnull ListNode*)aNode beforeNode:(nonnull ListNode*)node; 25 | 26 | - (void)deleteNode:(nonnull ListNode*)node; 27 | - (void)deleteNodesWithValue:(int)value; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /object-c/07_linkedlist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/object-c/07_linkedlist/.gitkeep -------------------------------------------------------------------------------- /object-c/08_stack/LinkedStack.h: -------------------------------------------------------------------------------- 1 | // 2 | // LinkedStack.h 3 | // algo 4 | // 5 | // Created by Wenru Dong on 2018/10/8. 6 | // Copyright © 2018年 Wenru Dong. All rights reserved. 7 | // 8 | // Stack based upon linked list 9 | // 基于链表实现的栈 10 | 11 | #import 12 | 13 | @interface LinkedStack : NSObject 14 | 15 | - (BOOL)isEmpty; 16 | - (void)push:(int)value; 17 | - (int)pop; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /object-c/08_stack/LinkedStack.m: -------------------------------------------------------------------------------- 1 | // 2 | // LinkedStack.m 3 | // algo 4 | // 5 | // Created by Wenru Dong on 2018/10/8. 6 | // Copyright © 2018年 Wenru Dong. All rights reserved. 7 | // 8 | 9 | #import "LinkedStack.h" 10 | #import "ListNode.h" 11 | 12 | @implementation LinkedStack 13 | { 14 | @private 15 | ListNode* _top; 16 | } 17 | 18 | - (BOOL)isEmpty { 19 | return _top == nil; 20 | } 21 | 22 | - (void)push:(int)value { 23 | ListNode *newTop = [ListNode nodeWithValue:value]; 24 | newTop.next = _top; 25 | _top = newTop; 26 | } 27 | 28 | - (int)pop { 29 | if ([self isEmpty]) { 30 | [NSException raise:NSRangeException format:@"The stack is empty."]; 31 | } 32 | int value = _top.value; 33 | _top = _top.next; 34 | return value; 35 | } 36 | 37 | - (NSString *)debugDescription { 38 | NSMutableString *info = [[NSMutableString alloc] init]; 39 | ListNode *current = _top; 40 | while (current) { 41 | [info appendString:[NSString stringWithFormat:@"%d]", current.value]]; 42 | current = current.next; 43 | } 44 | return [NSString stringWithString:info]; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /object-c/08_stack/ListNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // ListNode.h 3 | // algo 4 | // 5 | // Created by Wenru Dong on 2018/10/6. 6 | // Copyright © 2018年 Wenru Dong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ListNode : NSObject 12 | 13 | @property int value; 14 | @property ListNode *next; 15 | 16 | - (instancetype)initWithValue:(int)value; 17 | + (instancetype)nodeWithValue:(int)value; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /object-c/08_stack/ListNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // ListNode.m 3 | // algo 4 | // 5 | // Created by Wenru Dong on 2018/10/6. 6 | // Copyright © 2018年 Wenru Dong. All rights reserved. 7 | // 8 | 9 | #import "ListNode.h" 10 | 11 | @implementation ListNode 12 | 13 | - (instancetype)initWithValue:(int)value { 14 | if (self = [super init]) { 15 | _value = value; 16 | } 17 | return self; 18 | } 19 | 20 | + (instancetype)nodeWithValue:(int)value { 21 | return [[self alloc] initWithValue:value]; 22 | } 23 | 24 | - (NSString*)debugDescription { 25 | return [NSString stringWithFormat:@"%d", _value]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /object-c/08_stack/stack_practice/ArrayStack.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | 栈实现 4 | 5 | Author: Smallfly 6 | */ 7 | 8 | #import 9 | 10 | @interface Stack : NSObject 11 | 12 | - (id)initWithCapacity:(NSUInteger)count; 13 | 14 | - (BOOL)isEmpty; 15 | - (id)top; 16 | - (NSUInteger)size; 17 | 18 | - (BOOL)push:(id)obj; 19 | - (id)pop; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /object-c/08_stack/stack_practice/ArrayStack.m: -------------------------------------------------------------------------------- 1 | #import "ArrayStack.h" 2 | 3 | @implementation Stack { 4 | NSMutableArray *_arr; 5 | NSUInteger _capacity; 6 | NSUInteger _count; 7 | } 8 | 9 | - (id)initWithCapacity:(NSUInteger)capacity { 10 | self = [super init]; 11 | _capacity = capacity; 12 | _arr = [[NSMutableArray alloc] initWithCapacity:capacity]; 13 | return self; 14 | } 15 | 16 | - (BOOL)isEmpty { 17 | return _arr.count == 0; 18 | } 19 | 20 | - (BOOL)isFull { 21 | return _arr.count == _capacity; 22 | } 23 | 24 | - (id)top { 25 | if ([self isEmpty]) return nil; 26 | NSUInteger index = _arr.count - 1; 27 | return _arr[index]; 28 | } 29 | 30 | - (NSUInteger)size { 31 | return _arr.count; 32 | } 33 | 34 | - (BOOL)push:(id)obj { 35 | if (!obj) return NO; 36 | if (_arr.count == _capacity) return NO; 37 | [_arr addObject:obj]; 38 | return YES; 39 | } 40 | 41 | - (id)pop { 42 | if ([self isEmpty]) return nil; 43 | NSUInteger index = _arr.count - 1; 44 | id obj = _arr[index]; 45 | [_arr removeLastObject]; 46 | return obj; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /object-c/08_stack/stack_practice/BalancedParentheses.h: -------------------------------------------------------------------------------- 1 | /** 2 | 判断括号是否匹配 {} [] () 3 | 4 | Author: Smallfly 5 | */ 6 | #import 7 | 8 | @interface BalancedParentheses : NSObject 9 | 10 | - (BOOL)checkForParenthessBlanced:(NSString *)express; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /object-c/08_stack/stack_practice/BalancedParentheses.m: -------------------------------------------------------------------------------- 1 | 2 | #import "BalancedParentheses.h" 3 | #import "ArrayStack.h" 4 | 5 | const NSDictionary *parenthesesDict() { 6 | return @{@"(": @")", @"{": @"}", @"[": @"]"}; 7 | } 8 | 9 | @implementation BalancedParentheses { 10 | Stack *_stack; 11 | } 12 | 13 | - (instancetype)init { 14 | self = [super init]; 15 | _stack = [[Stack alloc] initWithCapacity:100]; 16 | return self; 17 | } 18 | 19 | - (BOOL)checkForParenthessBlanced:(NSString *)express { 20 | NSInteger midIndex = express.length / 2; 21 | for (int i = 0; i < express.length; ++i) { 22 | NSString *ele = [express substringWithRange:NSMakeRange(i, 1)]; 23 | if (i < midIndex) { 24 | // 前半部分把与 ele 匹配的括号加入栈 25 | [_stack push:parenthesesDict()[ele]]; 26 | } else { 27 | // 后半部分检查栈顶的元素与当前元素是否相同 28 | NSString *topEle = [_stack pop]; 29 | if (![topEle isEqualToString:ele]) { 30 | return NO; 31 | } 32 | } 33 | } 34 | return YES; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /object-c/08_stack/stack_practice/FourOperation.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | 整型四则运算 4 | 5 | Author: Smallfly 6 | */ 7 | 8 | #import 9 | 10 | @interface FourOperation : NSObject 11 | 12 | + (FourOperation *)shared; 13 | 14 | /** 15 | 整型四则运算 16 | 17 | @param expression 运算表达式,注意操作数和运算符之间要有空格 18 | @return 计算结果 19 | */ 20 | - (NSNumber *)caculateExpression:(NSString *)expression; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /object-c/08_stack/stack_practice/main.m: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | #import "FourOperation.h" 4 | #import "BalancedParentheses.h" 5 | 6 | int main(int argc, const char * argv[]) { 7 | @autoreleasepool { 8 | // 测试四则运算 9 | NSNumber *a = [[FourOperation shared] caculateExpression:@"10 - 4 / 2 * 3 + 3 - 6 / 2"]; 10 | NSNumber *b = [[FourOperation shared] caculateExpression:@"10 - 3"]; 11 | NSNumber *c = [[FourOperation shared] caculateExpression:@"2 * 3"]; 12 | NSLog(@"FourOperation: %ld\t%ld\t%ld\t", a.integerValue, b.integerValue, c.integerValue); 13 | 14 | // 测试括号匹配 15 | BalancedParentheses *balancedCheck = [BalancedParentheses new]; 16 | BOOL result = [balancedCheck checkForParenthessBlanced:@"([{{{}}}])"]; 17 | NSLog(@"BalancedParentheses: %d", result); 18 | } 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /object-c/11_Sort/Sort.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sort.h 3 | // test1231231 4 | // 5 | // Created by Scarlett Che on 2018/12/12. 6 | // Copyright © 2018 Scarlett Che. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface Sort : NSObject 14 | // 冒泡排序 15 | + (NSArray *)bubbleSortWithArray:(NSArray *)array; 16 | 17 | // 插入排序 18 | + (NSArray *)insertionSortWithArray:(NSArray *)array; 19 | 20 | // 选择排序 21 | + (NSArray *)selectionSortWithArray:(NSArray *)array; 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /object-c/33_bm_match/BM.h: -------------------------------------------------------------------------------- 1 | // 2 | // BM.h 3 | // BM-Match 4 | // 5 | // Created by Smallfly on 2018/12/9. 6 | // Copyright © 2018 Smallfly. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BM : NSObject 14 | - (instancetype)initWithA:(NSString *)a andB:(NSString *)b; 15 | - (NSInteger)startMatch; 16 | - (void)startMatchCompeletion:(void (^)(NSInteger))completion; 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /object-c/33_bm_match/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // BM-Match 4 | // 5 | // Created by Smallfly on 2018/12/9. 6 | // Copyright © 2018 Smallfly. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BM.h" 11 | 12 | int main(int argc, const char * argv[]) { 13 | @autoreleasepool { 14 | BM *bm = [[BM alloc] initWithA:@"abacadc" andB:@"adc"]; 15 | 16 | [bm startMatchCompeletion:^(NSInteger index) { 17 | NSLog(@"异步查找到下标:%ld\n", index); 18 | }]; 19 | 20 | NSLog(@"同步查找到下标:%ld\n", [bm startMatch]); 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /php/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor 3 | *my* 4 | Queue -------------------------------------------------------------------------------- /php/05_array/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/php/05_array/.gitkeep -------------------------------------------------------------------------------- /php/05_array/array_test.php: -------------------------------------------------------------------------------- 1 | insert($i, $i+1); 12 | } 13 | $myArr1->printData(); 14 | 15 | $code = $myArr1->insert(6, 999); 16 | echo "insert at 6: code:{$code}\n"; 17 | $myArr1->printData(); 18 | 19 | list($code, $value) = $myArr1->delete(6); 20 | echo "delete at 6: code:{$code}, value:{$value}\n"; 21 | $myArr1->printData(); 22 | 23 | $code = $myArr1->insert(11, 999); 24 | echo "insert at 11: code:{$code}\n"; 25 | $myArr1->printData(); 26 | 27 | list($code, $value) = $myArr1->delete(0); 28 | echo "delete at 0: code:{$code}, value:{$value}\n"; 29 | $myArr1->printData(); 30 | 31 | list($code, $value) = $myArr1->find(0); 32 | echo "find at 0: code:{$code}, value:{$value}\n"; -------------------------------------------------------------------------------- /php/06_linkedlist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/php/06_linkedlist/.gitkeep -------------------------------------------------------------------------------- /php/06_linkedlist/SingleLinkedListNode.php: -------------------------------------------------------------------------------- 1 | data = $data; 42 | $this->next = null; 43 | } 44 | } -------------------------------------------------------------------------------- /php/07_linkedlist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/php/07_linkedlist/.gitkeep -------------------------------------------------------------------------------- /php/08_stack/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/php/08_stack/.gitkeep -------------------------------------------------------------------------------- /php/08_stack/main.php: -------------------------------------------------------------------------------- 1 | pushData(1); 14 | $stack->pushData(2); 15 | $stack->pushData(3); 16 | $stack->pushData(4); 17 | var_dump($stack->getLength()); 18 | $stack->printSelf(); 19 | 20 | $topNode = $stack->top(); 21 | var_dump($topNode->data); 22 | 23 | $stack->pop(); 24 | $stack->printSelf(); 25 | $stack->pop(); 26 | $stack->printSelf(); 27 | 28 | var_dump($stack->getLength()); 29 | 30 | $stack->pop(); 31 | $stack->pop(); 32 | $stack->printSelf(); -------------------------------------------------------------------------------- /php/09_queue/main.php: -------------------------------------------------------------------------------- 1 | enqueue(1); 14 | $queue->enqueue(2); 15 | $queue->enqueue(3); 16 | $queue->enqueue(4); 17 | $queue->enqueue(5); 18 | $queue->printSelf(); 19 | var_dump($queue->getLength()); 20 | 21 | $queue->dequeue(); 22 | $queue->printSelf(); 23 | $queue->dequeue(); 24 | $queue->dequeue(); 25 | $queue->dequeue(); 26 | $queue->printSelf(); 27 | 28 | $queue->dequeue(); 29 | $queue->printSelf(); 30 | -------------------------------------------------------------------------------- /php/10_heap/main.php: -------------------------------------------------------------------------------- 1 | insert($v); 16 | } 17 | 18 | while(($r=$heap->deleteFirst())!==null){ 19 | echo $r." "; 20 | } 21 | echo PHP_EOL; 22 | 23 | $heap1=new Heap(10); 24 | 25 | foreach ($arr as $v){ 26 | $heap1->insertOnly($v); 27 | } 28 | 29 | 30 | 31 | $heap1->heapAll(); 32 | //堆化后的 33 | print_r($heap1->dataArr); 34 | //堆排序 35 | $heap1->heapSort(); 36 | print_r($heap1->dataArr); 37 | -------------------------------------------------------------------------------- /php/10_heap/topn.php: -------------------------------------------------------------------------------- 1 | ".$heap->topn($v).PHP_EOL; 29 | } 30 | -------------------------------------------------------------------------------- /php/12_sort/quicksort.php: -------------------------------------------------------------------------------- 1 | = $r) return; 13 | 14 | $q = partition($a, $l, $r); 15 | quickSortInternally($a, $l, $q-1); 16 | quickSortInternally($a, $q+1, $r); 17 | } 18 | 19 | function partition(&$a, $l, $r): int 20 | { 21 | $pivot = $a[$r]; 22 | $i = $l; 23 | 24 | for ($j = $l; $j < $r; ++$j) { 25 | if ($a[$j] < $pivot) { 26 | [$a[$j], $a[$i]] = [$a[$i], $a[$j]]; 27 | ++$i; 28 | } 29 | } 30 | 31 | [$a[$r], $a[$i]] = [$a[$i], $a[$r]]; 32 | 33 | return $i; 34 | } 35 | 36 | $a1 = [1,4,6,2,3,5,4]; 37 | $a2 = [2, 2, 2, 2]; 38 | $a3 = [4, 3, 2, 1]; 39 | $a4 = [5, -1, 9, 3, 7, 8, 3, -2, 9]; 40 | quickSort($a1); 41 | print_r($a1); 42 | quickSort($a2); 43 | print_r($a2); 44 | quickSort($a3); 45 | print_r($a3); 46 | quickSort($a4); 47 | print_r($a4); -------------------------------------------------------------------------------- /php/13_sort/countingSort.php: -------------------------------------------------------------------------------- 1 | $value) { 22 | $countScore[$value]++; 23 | } 24 | 25 | /** 26 | * 顺序求和 27 | */ 28 | for($i=1;$i<=5;$i++) { 29 | $countScore[$i] += $countScore[$i-1]; 30 | } 31 | /** 32 | * 排序 33 | */ 34 | foreach ($score as $key => $value) { 35 | $countScore[$value] --; 36 | $temp[$countScore[$value]] = $value; 37 | } 38 | //copy 39 | for($i=0;$i<$length;$i++) { 40 | $score[$i] = $temp[$i]; 41 | } 42 | return $score; 43 | } -------------------------------------------------------------------------------- /php/13_sort/radixSort.php: -------------------------------------------------------------------------------- 1 | toArray(); 35 | foreach ($numbers as $key => $value) { 36 | $index = ($value/$divisor)%10;//计算该数字在哪个桶中 37 | $buckets[$index][] = $value; 38 | } 39 | /** 40 | * 从桶中取出数字 41 | */ 42 | $k=0; 43 | for($i=0;$i<10;$i++) { 44 | while(count($buckets[$i]) > 0) { 45 | $numbers[$k++] = array_shift($buckets[$i]); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /php/24_tree/TreeNode.php: -------------------------------------------------------------------------------- 1 | data = $data; 33 | $this->left = null; 34 | $this->right = null; 35 | } 36 | } -------------------------------------------------------------------------------- /php/24_tree/levelOrder.php: -------------------------------------------------------------------------------- 1 | insert(16); 18 | $tree->insert(30); 19 | $tree->insert(12); 20 | $tree->insert(19); 21 | 22 | $tree->insert(10); 23 | $tree->insert(15); 24 | $tree->insert(18); 25 | $tree->insert(21); 26 | $tree->insert(38); 27 | 28 | 29 | $q=$tree->levelOrder([$tree->head]); 30 | 31 | foreach ($q as $n){ 32 | echo $n->data." "; 33 | } 34 | echo PHP_EOL; -------------------------------------------------------------------------------- /php/24_tree/main.php: -------------------------------------------------------------------------------- 1 | insert(20); 11 | $tree->insert(30); 12 | $tree->insert(40); 13 | $tree->insert(10); 14 | $tree->insert(21); 15 | $tree->insert(22); 16 | 17 | $tree->preOrder($tree->head); 18 | echo PHP_EOL; 19 | 20 | $tree->inOrder($tree->head); 21 | echo PHP_EOL; 22 | 23 | $tree->postOrder($tree->head); 24 | echo PHP_EOL; 25 | 26 | 27 | print_r($tree->find(30)); 28 | echo PHP_EOL; 29 | 30 | 31 | $tree->delete(30); 32 | $tree->preOrder($tree->head); 33 | echo PHP_EOL; -------------------------------------------------------------------------------- /php/README.md: -------------------------------------------------------------------------------- 1 | ## 数据结构与算法之美PHP实现 2 | 3 | ### 项目运行 4 | * 依赖composer自动加载,php目录下执行`composer dump-autoload` || `sh buildAutoLoad.sh` 5 | * 项目代码均在mac&php7环境下跑通 6 | 7 | ### 项目实现 8 | #### 06_linkedlist 9 | * 单链表php实现 10 | * 回文判断 11 | 12 | #### 07_linkedlist 13 | * reverse 单链表反转 14 | * checkCircle 链表中环的检测 15 | * mergerSortedList 两个有序的链表合并 16 | * deleteLastKth 删除链表倒数第n个结点 17 | * findMiddleNode 求链表的中间结点 18 | 19 | #### 08_stack 20 | * 链栈实现 21 | 22 | #### 09_stack 23 | * 队列链表实现 24 | #### 10_heap 25 | * main 堆的基本操作,堆排序 26 | * findmiddle 动态数据流求中位数 27 | * topn 动态数据流求top k 28 | #### 24_tree 29 | * main 二叉树的基本操作 前中后序遍历 30 | * levelOrder 二叉树的层级遍历 31 | -------------------------------------------------------------------------------- /php/buildAutoLoad.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | composer dump-autoload -------------------------------------------------------------------------------- /php/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "algo/php", 3 | "description": "数据结构与算法之美php实现", 4 | "type": "project", 5 | "require": {}, 6 | "autoload": { 7 | "psr-4": { 8 | "Algo_06\\": "06_linkedlist/", 9 | "Algo_07\\": "07_linkedlist/", 10 | "Algo_08\\": "08_stack/", 11 | "Algo_09\\": "09_queue/", 12 | "Algo_24\\": "24_tree/", 13 | "Algo_10\\": "10_heap/" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /python/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/python/.gitkeep -------------------------------------------------------------------------------- /python/.vs/slnx.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/python/.vs/slnx.sqlite -------------------------------------------------------------------------------- /python/05_array/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/python/05_array/.gitkeep -------------------------------------------------------------------------------- /python/06_linkedlist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/python/06_linkedlist/.gitkeep -------------------------------------------------------------------------------- /python/07_linkedlist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/python/07_linkedlist/.gitkeep -------------------------------------------------------------------------------- /python/08_stack/linked_stack.py: -------------------------------------------------------------------------------- 1 | """ 2 | Stack based upon linked list 3 | 基于链表实现的栈 4 | 5 | Author: Wenru 6 | """ 7 | 8 | from typing import Optional 9 | 10 | class Node: 11 | 12 | def __init__(self, data: int, next=None): 13 | self._data = data 14 | self._next = next 15 | 16 | 17 | class LinkedStack: 18 | """A stack based upon singly-linked list. 19 | """ 20 | def __init__(self): 21 | self._top: Node = None 22 | 23 | def push(self, value: int): 24 | new_top = Node(value) 25 | new_top._next = self._top 26 | self._top = new_top 27 | 28 | def pop(self) -> Optional[int]: 29 | if self._top: 30 | value = self._top._data 31 | self._top = self._top._next 32 | return value 33 | 34 | def __repr__(self) -> str: 35 | current = self._top 36 | nums = [] 37 | while current: 38 | nums.append(current._data) 39 | current = current._next 40 | return " ".join(f"{num}]" for num in nums) 41 | 42 | if __name__ == "__main__": 43 | stack = LinkedStack() 44 | for i in range(9): 45 | stack.push(i) 46 | print(stack) 47 | for _ in range(3): 48 | stack.pop() 49 | print(stack) -------------------------------------------------------------------------------- /python/09_queue/array_queue.py: -------------------------------------------------------------------------------- 1 | """ 2 | Queue based upon array 3 | 用数组实现的队列 4 | 5 | Author: Wenru 6 | """ 7 | 8 | from typing import Optional 9 | 10 | class ArrayQueue: 11 | 12 | def __init__(self, capacity: int): 13 | self._items = [] 14 | self._capacity = capacity 15 | self._head = 0 16 | self._tail = 0 17 | 18 | def enqueue(self, item: str) -> bool: 19 | if self._tail == self._capacity: 20 | if self._head == 0: 21 | return False 22 | else: 23 | for i in range(0, self._tail - self._head): 24 | self._items[i] = self._items[i + self._head] 25 | self._tail = self._tail - self._head 26 | self._head = 0 27 | 28 | self._items.insert(self._tail, item) 29 | self._tail += 1 30 | return True 31 | 32 | def dequeue(self) -> Optional[str]: 33 | if self._head != self._tail: 34 | item = self._items[self._head] 35 | self._head += 1 36 | return item 37 | else: 38 | return None 39 | 40 | def __repr__(self) -> str: 41 | return " ".join(item for item in self._items[self._head : self._tail]) 42 | 43 | -------------------------------------------------------------------------------- /python/14_sorts/counting_sort.py: -------------------------------------------------------------------------------- 1 | """ 2 | 计数排序 3 | 4 | Author: Wenru 5 | """ 6 | 7 | from typing import List 8 | import itertools 9 | 10 | def counting_sort(a: List[int]): 11 | if len(a) <= 1: return 12 | 13 | # a中有counts[i]个数不大于i 14 | counts = [0] * (max(a) + 1) 15 | for num in a: 16 | counts[num] += 1 17 | counts = list(itertools.accumulate(counts)) 18 | 19 | # 临时数组,储存排序之后的结果 20 | a_sorted = [0] * len(a) 21 | for num in reversed(a): 22 | index = counts[num] - 1 23 | a_sorted[index] = num 24 | counts[num] -= 1 25 | 26 | a[:] = a_sorted 27 | 28 | 29 | if __name__ == "__main__": 30 | a1 = [1, 2, 3, 4] 31 | counting_sort(a1) 32 | print(a1) 33 | 34 | a2 = [1, 1, 1, 1] 35 | counting_sort(a2) 36 | print(a2) 37 | 38 | a3 = [4, 5, 0, 9, 3, 3, 1, 9, 8, 7] 39 | counting_sort(a3) 40 | print(a3) 41 | -------------------------------------------------------------------------------- /python/15_bsearch/bsearch.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author: Wenru 3 | """ 4 | 5 | from typing import List 6 | 7 | def bsearch(nums: List[int], target: int) -> int: 8 | """Binary search of a target in a sorted array 9 | without duplicates. If such a target does not exist, 10 | return -1, othewise, return its index. 11 | """ 12 | low, high = 0, len(nums) - 1 13 | while low <= high: 14 | mid = low + (high - low) // 2 15 | if nums[mid] == target: 16 | return mid 17 | elif nums[mid] < target: 18 | low = mid + 1 19 | else: 20 | high = mid - 1 21 | 22 | return -1 23 | -------------------------------------------------------------------------------- /python/15_bsearch/bsearch_recursion.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author: dreamkong 3 | """ 4 | 5 | from typing import List 6 | 7 | 8 | def bsearch(nums: List[int], target: int) -> int: 9 | return bsearch_internally(nums, 0, len(nums)-1, target) 10 | 11 | 12 | def bsearch_internally(nums: List[int], low: int, high: int, target: int) -> int: 13 | if low > high: 14 | return -1 15 | 16 | mid = low+int((high-low) >> 2) 17 | if nums[mid] == target: 18 | return mid 19 | elif nums[mid] < target: 20 | return bsearch_internally(nums, mid+1, high, target) 21 | else: 22 | return bsearch_internally(nums, low, mid-1, target) 23 | -------------------------------------------------------------------------------- /python/28_binary_heap/binary_heap_sort.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | from binary_heap import BinaryHeap 5 | 6 | 7 | class BinaryHeapSort(BinaryHeap): 8 | def __init__(self): 9 | super(BinaryHeapSort, self).__init__() 10 | 11 | def sort(self, nums): 12 | """ 13 | 排序 14 | 1. 堆化,大顶堆 15 | 2. 排序,从后往前遍历,首尾元素互换,子数组堆化 16 | :param nums: 17 | :return: 18 | """ 19 | assert type(nums) is list 20 | length = len(nums) 21 | 22 | if length <= 1: 23 | return 24 | 25 | self._type_assert(nums) 26 | 27 | # heapify 28 | self._heapify(nums, length-1) 29 | 30 | # sort 31 | for i in range(length-1, 0, -1): 32 | nums[0], nums[i] = nums[i], nums[0] 33 | self._heap_down(nums, 0, i-1) 34 | 35 | return 36 | 37 | 38 | if __name__ == '__main__': 39 | bhs = BinaryHeapSort() 40 | nums = [3, 5, 2, 6, 1, 7, 6] 41 | 42 | print('--- before sort ---') 43 | print(nums) 44 | 45 | bhs.sort(nums) 46 | print('--- after sort ---') 47 | print(nums) 48 | -------------------------------------------------------------------------------- /python/28_binary_heap/top_k.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | import random 5 | from heap import MinHeap 6 | 7 | 8 | def top_k(nums, k): 9 | """ 10 | 返回数组的前k大元素 11 | :param nums: 12 | :param k: 13 | :return: 14 | """ 15 | if len(nums) <= k: 16 | return nums 17 | 18 | min_h = MinHeap(nums[:k], k) 19 | for i in range(k, len(nums)): 20 | tmp = min_h.get_top() 21 | if nums[i] > tmp: 22 | min_h.remove_top() 23 | min_h.insert(nums[i]) 24 | 25 | return min_h.get_data() 26 | 27 | 28 | if __name__ == '__main__': 29 | nums = [] 30 | k = 3 31 | 32 | for i in range(20): 33 | nums.append(random.randint(1, 100)) 34 | 35 | print('--- nums ---') 36 | print(nums) 37 | 38 | print('--- top {} ---'.format(k)) 39 | print(top_k(nums, k)) 40 | -------------------------------------------------------------------------------- /python/31_bfs_dfs/graph_application.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | 5 | from collections import deque 6 | from graph import Undigraph 7 | 8 | def find_vertex_by_degree(graph, s, degree): 9 | if len(graph) <= 1: 10 | return [] 11 | if degree == 0: 12 | return [s] 13 | d_vertices = [] 14 | queue = deque() 15 | prev = [-1] * len(graph) 16 | visited = [False] * len(graph) 17 | visited[s] = True 18 | queue.append(s) 19 | while len(queue) > 0: 20 | sz = len(queue) 21 | for i in range(sz): 22 | v = queue.popleft() 23 | for adj_v in graph[v]: 24 | if not visited[adj_v]: 25 | prev[adj_v] = v 26 | visited[adj_v] = True 27 | queue.append(adj_v) 28 | degree -= 1 29 | if degree == 0 and len(queue) != 0: 30 | return queue 31 | 32 | 33 | if __name__ == '__main__': 34 | g = Undigraph(8) 35 | g.add_edge(0, 1) 36 | g.add_edge(0, 3) 37 | g.add_edge(1, 2) 38 | g.add_edge(1, 4) 39 | g.add_edge(2, 5) 40 | g.add_edge(3, 4) 41 | g.add_edge(4, 5) 42 | g.add_edge(4, 6) 43 | g.add_edge(5, 7) 44 | g.add_edge(6, 7) 45 | print(find_vertex_by_degree(g, 0, 4)) 46 | -------------------------------------------------------------------------------- /python/35_trie/trie.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author: Wenru Dong 3 | """ 4 | 5 | class TrieNode: 6 | def __init__(self, data: str): 7 | self._data = data 8 | self._children = [None] * 26 9 | self._is_ending_char = False 10 | 11 | 12 | class Trie: 13 | def __init__(self): 14 | self._root = TrieNode("/") 15 | 16 | def insert(self, text: str) -> None: 17 | node = self._root 18 | for index, char in map(lambda x: (ord(x) - ord("a"), x), text): 19 | if not node._children[index]: 20 | node._children[index] = TrieNode(char) 21 | node = node._children[index] 22 | node._is_ending_char = True 23 | 24 | def find(self, pattern: str) -> bool: 25 | node = self._root 26 | for index in map(lambda x: ord(x) - ord("a"), pattern): 27 | if not node._children[index]: return False 28 | node = node._children[index] 29 | return node._is_ending_char 30 | 31 | 32 | if __name__ == "__main__": 33 | 34 | strs = ["how", "hi", "her", "hello", "so", "see"] 35 | trie = Trie() 36 | for s in strs: 37 | trie.insert(s) 38 | 39 | for s in strs: 40 | print(trie.find(s)) 41 | 42 | print(trie.find("swift")) -------------------------------------------------------------------------------- /python/39_back_track/permutations.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | from typing import List 5 | 6 | permutations_list = [] # 全局变量,用于记录每个输出 7 | 8 | 9 | def permutations(nums: List, n: int, pick_count: int): 10 | """ 11 | 从nums选取n个数的全排列 12 | 13 | 回溯法,用一个栈记录当前路径信息 14 | 当满足n==0时,说明栈中的数已足够,输出并终止遍历 15 | :param nums: 16 | :param n: 17 | :param pick_count: 18 | :return: 19 | """ 20 | if n == 0: 21 | print(permutations_list) 22 | else: 23 | for i in range(len(nums) - pick_count): 24 | permutations_list[pick_count] = nums[i] 25 | nums[i], nums[len(nums) - pick_count - 1] = nums[len(nums) - pick_count - 1], nums[i] 26 | permutations(nums, n-1, pick_count+1) 27 | nums[i], nums[len(nums) - pick_count - 1] = nums[len(nums) - pick_count - 1], nums[i] 28 | 29 | 30 | if __name__ == '__main__': 31 | nums = [1, 2, 3, 4] 32 | n = 3 33 | print('--- list ---') 34 | print(nums) 35 | 36 | print('\n--- pick num ---') 37 | print(n) 38 | 39 | print('\n--- permutation list ---') 40 | permutations_list = [0] * n 41 | permutations(nums, n, 0) 42 | 43 | -------------------------------------------------------------------------------- /python/39_back_track/regex.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | is_match = False 5 | 6 | 7 | def rmatch(r_idx: int, m_idx: int, regex: str, main: str): 8 | global is_match 9 | if is_match: 10 | return 11 | 12 | if r_idx >= len(regex): # 正则串全部匹配好了 13 | is_match = True 14 | return 15 | 16 | if m_idx >= len(main) and r_idx < len(regex): # 正则串没匹配完,但是主串已经没得匹配了 17 | is_match = False 18 | return 19 | 20 | if regex[r_idx] == '*': # * 匹配1个或多个任意字符,递归搜索每一种情况 21 | for i in range(m_idx, len(main)): 22 | rmatch(r_idx+1, i+1, regex, main) 23 | elif regex[r_idx] == '?': # ? 匹配0个或1个任意字符,两种情况 24 | rmatch(r_idx+1, m_idx+1, regex, main) 25 | rmatch(r_idx+1, m_idx, regex, main) 26 | else: # 非特殊字符需要精确匹配 27 | if regex[r_idx] == main[m_idx]: 28 | rmatch(r_idx+1, m_idx+1, regex, main) 29 | 30 | 31 | if __name__ == '__main__': 32 | regex = 'ab*eee?d' 33 | main = 'abcdsadfkjlekjoiwjiojieeecd' 34 | rmatch(0, 0, regex, main) 35 | print(is_match) 36 | -------------------------------------------------------------------------------- /python/39_backtracking/backtracking.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author: Wenru Dong 3 | """ 4 | 5 | from typing import List 6 | 7 | def eight_queens() -> None: 8 | solutions = [] 9 | 10 | def backtracking(queens_at_column: List[int], index_sums: List[int], index_diffs: List[int]) -> None: 11 | row = len(queens_at_column) 12 | if row == 8: 13 | solutions.append(queens_at_column) 14 | return 15 | for col in range(8): 16 | if col in queens_at_column or row + col in index_sums or row - col in index_diffs: continue 17 | backtracking(queens_at_column + [col], index_sums + [row + col], index_diffs + [row - col]) 18 | 19 | backtracking([], [], []) 20 | print(*(" " + " ".join("*" * i + "Q" + "*" * (8 - i - 1) + "\n" for i in solution) for solution in solutions), sep="\n") 21 | 22 | 23 | if __name__ == "__main__": 24 | 25 | eight_queens() 26 | -------------------------------------------------------------------------------- /python/40_dynamic_programming/knapsack.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author: Wenru Dong 3 | """ 4 | 5 | from typing import List 6 | 7 | def knapsack01(weights: List[int], values: List[int], capacity: int) -> int: 8 | # Denote the state as (i, c), where i is the stage number, 9 | # and c is the capacity available. Denote f(i, c) to be the 10 | # maximum value when the capacity available is c, and Item 0 11 | # to Item i-1 are to be packed. 12 | # The goal is to find f(n-1, W), where W is the total capacity. 13 | # Then the DP functional equation is: 14 | # f(i, c) = max(xᵢvᵢ + f(i-1, c-xᵢwᵢ)), xᵢ ∈ D, i ≥ 0, 15 | # f(-1, c) = 0, 0 ≤ c ≤ W, 16 | # where 17 | # / {0}, if wᵢ > c 18 | # D = D(i, c) = 19 | # \ {0, 1}, if wᵢ ≤ c 20 | 21 | prev = [0] * (capacity + 1) 22 | for w, v in zip(weights, values): 23 | prev = [c >= w and max(prev[c], prev[c-w] + v) for c in range(capacity + 1)] 24 | return prev[-1] 25 | 26 | 27 | if __name__ == "__main__": 28 | # To find the maximum weight that can be packed, 29 | # set values equal to the weights 30 | print(knapsack01([2, 2, 4, 6, 3], [2, 2, 4, 6, 3], 9)) 31 | -------------------------------------------------------------------------------- /python/45_bitmap/bitmap.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author: Wenru Dong 3 | """ 4 | 5 | from typing import Optional 6 | 7 | class Bitmap: 8 | def __init__(self, num_bits: int): 9 | self._num_bits = num_bits 10 | self._bytes = bytearray(num_bits // 8 + 1) 11 | 12 | def setbit(self, k: int) -> None: 13 | if k > self._num_bits or k < 1: return 14 | self._bytes[k // 8] |= (1 << k % 8) 15 | 16 | def getbit(self, k: int) -> Optional[bool]: 17 | if k > self._num_bits or k < 1: return 18 | return self._bytes[k // 8] & (1 << k % 8) != 0 19 | 20 | 21 | if __name__ == "__main__": 22 | bitmap = Bitmap(10) 23 | bitmap.setbit(1) 24 | bitmap.setbit(3) 25 | bitmap.setbit(6) 26 | bitmap.setbit(7) 27 | bitmap.setbit(8) 28 | 29 | for i in range(1, 11): 30 | print(bitmap.getbit(i)) -------------------------------------------------------------------------------- /rust/07_linkedlist/linked_list_cycle.rs: -------------------------------------------------------------------------------- 1 | use super::util::linked_list::{ListNode, to_list}; 2 | 3 | pub fn has_cycle(head: Option>) -> bool { 4 | let mut fast_p = &head; 5 | let mut slow_p = &head; 6 | 7 | while fast_p.is_some() && fast_p.as_ref().unwrap().next.is_some() { 8 | slow_p = &slow_p.as_ref().unwrap().next; 9 | fast_p = &fast_p.as_ref().unwrap().next.as_ref().unwrap().next; 10 | 11 | if slow_p == fast_p { return true; } 12 | } 13 | false 14 | } 15 | 16 | fn main() { 17 | println!("{:?}", has_cycle(to_list(vec![1, 2, 3, 4, 5]))); 18 | } 19 | -------------------------------------------------------------------------------- /rust/07_linkedlist/merge_two_sorted_lists.rs: -------------------------------------------------------------------------------- 1 | use super::util::linked_list::{ListNode, to_list}; 2 | 3 | pub fn merge_two_lists(l1: Option>, l2: Option>) -> Option> { 4 | match (l1, l2) { 5 | (Some(node1), None) => Some(node1), 6 | (None, Some(node2)) => Some(node2), 7 | (Some(mut node1), Some(mut node2)) => { 8 | if node1.val < node2.val { 9 | let n = node1.next.take(); 10 | node1.next = Solution::merge_two_lists(n, Some(node2)); 11 | Some(node1) 12 | } else { 13 | let n = node2.next.take(); 14 | node2.next = Solution::merge_two_lists(Some(node1), n); 15 | Some(node2) 16 | } 17 | }, 18 | _ => None, 19 | } 20 | } 21 | 22 | fn main() { 23 | println!("{:?}", merge_two_lists(to_list(vec![1, 3, 4]), to_list(vec![1, 2, 4]))); 24 | } 25 | -------------------------------------------------------------------------------- /rust/07_linkedlist/middle_of_the_linked_list.rs: -------------------------------------------------------------------------------- 1 | use super::util::linked_list::{ListNode, to_list}; 2 | 3 | pub fn middle_node(head: Option>) -> Option> { 4 | let mut fast_p = &head; 5 | let mut slow_p = &head; 6 | 7 | while fast_p.is_some() && fast_p.as_ref().unwrap().next.is_some() { 8 | slow_p = &slow_p.as_ref().unwrap().next; 9 | fast_p = &fast_p.as_ref().unwrap().next.as_ref().unwrap().next; 10 | } 11 | slow_p.clone() 12 | } 13 | 14 | fn main() { 15 | println!("{:?}", middle_node(to_list(vec![1, 3, 4]))); 16 | } 17 | -------------------------------------------------------------------------------- /rust/07_linkedlist/remove_nth_node_from_end_of_list.rs: -------------------------------------------------------------------------------- 1 | use super::util::linked_list::{ListNode, to_list}; 2 | 3 | pub fn remove_nth_from_end(head: Option>, n: i32) -> Option> { 4 | let mut dummy = Some(Box::new(ListNode { val: 0, next: head })); 5 | let mut cur = &mut dummy; 6 | let mut length = 0; 7 | 8 | while let Some(_node) = cur.as_mut() { 9 | cur = &mut cur.as_mut().unwrap().next; 10 | if let Some(_inner_node) = cur { length += 1; } 11 | } 12 | 13 | let mut new_cur = dummy.as_mut(); 14 | let idx = length - n; 15 | 16 | for _ in 0..idx { 17 | new_cur = new_cur.unwrap().next.as_mut(); 18 | } 19 | 20 | let next = new_cur.as_mut().unwrap().next.as_mut().unwrap().next.take(); 21 | new_cur.as_mut().unwrap().next = next; 22 | 23 | dummy.unwrap().next 24 | } 25 | 26 | fn main() { 27 | println!("{:?}", remove_nth_from_end(to_list(vec![1, 3, 4]))); 28 | } 29 | -------------------------------------------------------------------------------- /rust/07_linkedlist/reverse_linked_list.rs: -------------------------------------------------------------------------------- 1 | use super::util::linked_list::{ListNode, to_list}; 2 | 3 | pub fn reverse_list(head: Option>) -> Option> { 4 | let mut prev = None; 5 | let mut curr = head; 6 | 7 | while let Some(mut boxed_node) = curr.take() { 8 | let next = boxed_node.next.take(); 9 | boxed_node.next = prev.take(); 10 | 11 | prev = Some(boxed_node); 12 | curr = next; 13 | } 14 | 15 | prev 16 | } 17 | 18 | fn main() { 19 | println!("{:?}", reverse_list(to_list(vec![1, 2, 3, 4, 5]))); 20 | } 21 | -------------------------------------------------------------------------------- /rust/07_linkedlist/util/linked_list.rs: -------------------------------------------------------------------------------- 1 | // Definition for singly-linked list. 2 | #[derive(PartialEq, Eq, Clone, Debug)] 3 | pub struct ListNode { 4 | pub val: i32, 5 | pub next: Option> 6 | } 7 | 8 | impl ListNode { 9 | #[inline] 10 | fn new(val: i32) -> Self { 11 | ListNode { 12 | next: None, 13 | val 14 | } 15 | } 16 | } 17 | 18 | pub fn to_list(vec: Vec) -> Option> { 19 | let mut current = None; 20 | for &v in vec.iter().rev() { 21 | let mut node = ListNode::new(v); 22 | node.next = current; 23 | current = Some(Box::new(node)); 24 | } 25 | current 26 | } 27 | 28 | #[macro_export] 29 | macro_rules! linked { 30 | ($($e:expr),*) => {to_list(vec![$($e.to_owned()), *])}; 31 | ($($e:expr,)*) => {to_list(vec![$($e.to_owned()), *])}; 32 | } 33 | -------------------------------------------------------------------------------- /rust/08_stack/stack_based_on_array.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | struct ArrayStack { 3 | data: Vec, 4 | top: i32, 5 | } 6 | 7 | impl ArrayStack { 8 | fn new() -> Self { 9 | ArrayStack { data: Vec::with_capacity(32), top: -1 } 10 | } 11 | 12 | fn push(&mut self, x: i32) { 13 | self.top += 1; 14 | if self.top == self.data.capacity() as i32 { 15 | let tmp_arr = self.data.clone(); 16 | self.data = Vec::with_capacity(self.data.capacity() * 2); 17 | for d in tmp_arr.into_iter() { 18 | self.data.push(d); 19 | } 20 | } 21 | self.data.push(x); 22 | } 23 | 24 | fn pop(&mut self) { 25 | if self.is_empty() { return; } 26 | self.top -= 1; 27 | self.data.pop(); 28 | } 29 | 30 | fn top(&self) -> i32 { 31 | if self.is_empty() { return -1; } 32 | *self.data.last().unwrap() 33 | } 34 | 35 | fn is_empty(&self) -> bool { 36 | if self.top < 0 { true } else { false } 37 | } 38 | } 39 | 40 | fn main() { 41 | let mut stack = ArrayStack::new(); 42 | stack.push(-2); 43 | stack.push(0); 44 | stack.push(-3); 45 | stack.pop(); 46 | println!("{:?}", stack.top()); 47 | } 48 | -------------------------------------------------------------------------------- /rust/11_sorts/bubble_sort.rs: -------------------------------------------------------------------------------- 1 | /// 冒泡排序 2 | /// 时间复杂度:O(n2),原地排序算法, 稳定排序算法 3 | // 冒泡排序 4 | fn bubble_sort(mut nums: Vec) -> Vec { 5 | if nums.is_empty() { return vec![]; } 6 | 7 | let n = nums.len(); 8 | for i in 0..n { 9 | // 提前退出标志 10 | let mut swap = false; 11 | for j in 0..n-i-1 { 12 | if nums[j] > nums[j+1] { 13 | // 此次冒泡有数据交换 14 | swap = true; 15 | let tmp = nums[j]; 16 | nums[j] = nums[j+1]; 17 | nums[j+1] = tmp; 18 | } 19 | } 20 | // 若没有数据交换,提前退出 21 | if !swap { break; } 22 | } 23 | nums 24 | } 25 | 26 | fn main() { 27 | let nums = vec![4, 5, 6, 1, 2, 3]; 28 | println!("{:?}", bubble_sort(nums)); 29 | } 30 | -------------------------------------------------------------------------------- /rust/11_sorts/insertion_sort.rs: -------------------------------------------------------------------------------- 1 | /// 插入排序 2 | /// 时间复杂度:O(n2),原地排序算法, 稳定排序算法 3 | // 插入排序 4 | fn insertion_sort(mut nums: Vec) -> Vec { 5 | if nums.is_empty() { return vec![]; } 6 | 7 | for i in 1..nums.len() { 8 | let value = nums[i]; 9 | let mut j = (i - 1) as i32; 10 | // 查找要插入的位置并移动数据 11 | while j >= 0 { 12 | if nums[j as usize] > value { 13 | nums[(j+1) as usize] = nums[j as usize]; 14 | } else { 15 | break; 16 | } 17 | j -= 1; 18 | } 19 | nums[(j+1) as usize] = value; 20 | } 21 | nums 22 | } 23 | 24 | fn main() { 25 | let nums = vec![4, 5, 6, 1, 2, 3]; 26 | println!("{:?}", insert_on_sort(nums)); 27 | } 28 | -------------------------------------------------------------------------------- /rust/11_sorts/selection_sort.rs: -------------------------------------------------------------------------------- 1 | /// 选择排序 2 | /// 时间复杂度:O(n2),原地排序算法, 不稳定排序算法 3 | // 选择排序 4 | fn selection_sort(mut nums: Vec) -> Vec { 5 | if nums.is_empty() { return vec![]; } 6 | 7 | for i in 0..nums.len() { 8 | let mut mini_index = i; 9 | // 查找最小 index 10 | for j in i+1..nums.len() { 11 | if nums[j] < nums[mini_index] { 12 | mini_index = j; 13 | } 14 | } 15 | // 交换数据 16 | let tmp = nums[i]; 17 | nums[i] = nums[mini_index]; 18 | nums[mini_index] = tmp; 19 | } 20 | nums 21 | } 22 | 23 | fn main() { 24 | let nums = vec![4, 5, 6, 1, 2, 3]; 25 | println!("{:?}", selection_sort(nums)); 26 | } 27 | -------------------------------------------------------------------------------- /rust/12_sorts/kth_largest.rs: -------------------------------------------------------------------------------- 1 | pub fn kth_largest(mut nums: Vec, k: i32) -> Option { 2 | if nums.is_empty() || k >= nums.len() as i32 { return None; } 3 | 4 | let end = nums.len() - 1; 5 | let k = k as usize; 6 | // 分区点 7 | let mut pivot = partition(&mut nums, 0, end); 8 | while pivot + 1 != k { 9 | if k > pivot + 1 { 10 | pivot = partition(&mut nums, pivot + 1, end); 11 | } else { 12 | pivot = partition(&mut nums, 0, pivot - 1); 13 | } 14 | } 15 | 16 | Some(nums[pivot]) 17 | } 18 | 19 | fn partition(nums: &mut Vec, start: usize, end: usize) -> usize { 20 | let pivot = nums[end]; 21 | let mut i = start; 22 | for j in start..end { 23 | if nums[j] >= pivot { // if nums[j] <= pivot then swap, search kth smallest 24 | swap(nums, i, j); 25 | i += 1; 26 | } 27 | } 28 | 29 | swap(nums, i, end); 30 | i 31 | } 32 | 33 | fn swap(nums: &mut Vec, i: usize, j: usize) { 34 | if i == j { return; } 35 | 36 | let tmp = nums[i]; 37 | nums[i] = nums[j]; 38 | nums[j] = tmp; 39 | } 40 | 41 | fn main() { 42 | let nums = vec![8, 10, 2, 3, 6,1, 5]; 43 | println!("{:?}", kth_largest(nums, 3)); 44 | } 45 | -------------------------------------------------------------------------------- /rust/12_sorts/quick_sort.rs: -------------------------------------------------------------------------------- 1 | /// 快排 2 | /// 时间复杂度:O(nlogn), 空间复杂度: O(1), 不稳定排序 3 | // 快排 4 | pub fn quick_sort(mut nums: Vec) -> Vec { 5 | if nums.is_empty() { return nums; } 6 | 7 | let n = nums.len() - 1; 8 | quick_sort_internally(&mut nums, 0, n); 9 | nums 10 | } 11 | 12 | fn quick_sort_internally(nums: &mut Vec, start: usize, end: usize) { 13 | if start >= end { return; } 14 | 15 | // 分区点 16 | let pivot = partition(nums, start, end); 17 | if pivot != 0 { 18 | quick_sort_internally(nums, start, pivot-1); 19 | } 20 | quick_sort_internally(nums, pivot+1, end); 21 | } 22 | 23 | fn partition(nums: &mut Vec, start: usize, end: usize) -> usize { 24 | let pivot = nums[end]; 25 | let mut i = start; 26 | for j in start..end { 27 | if nums[j] < pivot { 28 | swap(nums, i, j); 29 | i += 1; 30 | } 31 | } 32 | 33 | swap(nums, i, end); 34 | i 35 | } 36 | 37 | fn swap(nums: &mut Vec, i: usize, j: usize) { 38 | if i == j { return; } 39 | 40 | let tmp = nums[i]; 41 | nums[i] = nums[j]; 42 | nums[j] = tmp; 43 | } 44 | 45 | fn main() { 46 | let nums = vec![8, 10, 2, 3, 6,1, 5]; 47 | println!("{:?}", quick_sort(nums)); 48 | } 49 | -------------------------------------------------------------------------------- /rust/13_sorts/sort_string.rs: -------------------------------------------------------------------------------- 1 | fn sort_string(s: String) -> Vec> { 2 | let mut bucket: Vec> = vec![vec![]; 3]; 3 | for ch in s.as_bytes() { 4 | if ch as u8 >= 48 && ch as u8 <= 57 { 5 | bucket[0].push(ch); 6 | } else if ch as u8 >= 65 && ch as u8 <= 90 { 7 | bucket[1].push(ch); 8 | } else { 9 | bucket[2].push(ch); 10 | } 11 | } 12 | 13 | bucket 14 | } 15 | fn main() { 16 | let s = "DaFBCA789".to_string(); 17 | println!("{:?}", sort_string(s)); 18 | } 19 | -------------------------------------------------------------------------------- /rust/15_binary_search/sqrtx.rs: -------------------------------------------------------------------------------- 1 | // leetcode: https://leetcode.com/problems/sqrtx/ 2 | 3 | pub fn my_sqrt(x: i32, precision: f32) -> f32 { 4 | if x == 0 || x == 1 { return x as f32; } 5 | 6 | let mut left = 0f32; 7 | let mut right = x as f32; 8 | let mut res = 0f32; 9 | 10 | while left <= right { 11 | let mid: f32 = (right - left) / 2.0 + left; 12 | 13 | if (right - left).abs() < precision { return mid; } 14 | 15 | if mid > x as f32 / mid { 16 | right = mid; 17 | } else { 18 | left = mid; 19 | } 20 | res = mid 21 | } 22 | 23 | res 24 | } 25 | 26 | fn main() { 27 | println!("{:?}", my_sqrt(8, 0.000001)); 28 | } 29 | -------------------------------------------------------------------------------- /rust/16_binary_search/search_in_rotated_sorted_array.rs: -------------------------------------------------------------------------------- 1 | // leetcode 33 Search in Rotated Sorted Array (https://leetcode.com/problems/search-in-rotated-sorted-array/) 2 | pub fn search(nums: Vec, target: i32) -> i32 { 3 | if nums.is_empty() { return -1; } 4 | 5 | let mut low = 0; 6 | let mut high = nums.len() - 1; 7 | 8 | while low <= high { 9 | let mid = low + ((high - low) >> 1); 10 | if nums[mid] == target { return mid as i32; } 11 | 12 | // left is order 13 | if nums[low] <= nums[mid] { 14 | // target is in left array 15 | if nums[low] <= target && target <= nums[mid] { 16 | high = mid - 1; 17 | } else { 18 | low = mid + 1; 19 | } 20 | } else { 21 | if nums[mid] <= target && target <= nums[high] { 22 | low = mid + 1; 23 | } else { 24 | high = mid - 1; 25 | } 26 | } 27 | } 28 | -1 29 | } 30 | 31 | fn main() { 32 | let nums = vec![4,5,6,7,0,1,2]; 33 | let n = search(nums, 0); 34 | println!("{:?}", n); 35 | } 36 | -------------------------------------------------------------------------------- /rust/23_binary_tree/level_order_traversal.rs: -------------------------------------------------------------------------------- 1 | // leetcode https://leetcode.com/problems/binary-tree-level-order-traversal/ 2 | 3 | use super::util::tree::{TreeNode, to_tree}; 4 | use std::collections::VecDeque; 5 | 6 | pub fn level_order(root: Option>>) -> Vec> { 7 | let mut result: Vec> = vec![]; 8 | if root.is_none() { return result; } 9 | 10 | let mut deque: VecDeque>>> = VecDeque::new(); 11 | deque.push_back(root); 12 | 13 | while !deque.is_empty() { 14 | let mut current_level = vec![]; 15 | let mut added = false; 16 | let level_size = deque.len(); 17 | 18 | for i in 0..level_size { 19 | let n = deque.pop_front(); 20 | if let Some(Some(node)) = n { 21 | current_level.push(node.borrow().val); 22 | added = true; 23 | if node.borrow().left.is_some() { deque.push_back(node.borrow().left.clone()); } 24 | if node.borrow().right.is_some() { deque.push_back(node.borrow().right.clone()); } 25 | } 26 | } 27 | 28 | if !added { break; } 29 | 30 | result.push(current_level); 31 | } 32 | 33 | result 34 | } 35 | -------------------------------------------------------------------------------- /rust/24_binary_tree/insert_in_binary_tree.rs: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/insert-into-a-binary-search-tree/ 2 | use super::util::tree::{TreeNode, to_tree}; 3 | 4 | pub fn insert_into_bst(root: Option>>, val: i32) -> Option>> { 5 | insert(&root, val); 6 | root 7 | } 8 | fn insert(node: &Option>>, val: i32) { 9 | if let Some(n) = node { 10 | let mut n = n.borrow_mut(); 11 | let target = if val > n.val { &mut n.right } else { &mut n.left }; 12 | 13 | if target.is_some() { 14 | return insert(target, val); 15 | } 16 | 17 | *target = Some(Rc::new(RefCell::new(TreeNode::new(val)))); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /rust/24_binary_tree/search_in_binary_tree.rs: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/search-in-a-binary-search-tree/ 2 | use super::util::tree::{TreeNode, to_tree}; 3 | 4 | // Iterating method 5 | pub fn search_bst(root: Option>>, val: i32) -> Option>> { 6 | let mut r = root.clone(); 7 | while let Some(node) = r { 8 | if node.borrow().val == val { return Some(node); } 9 | if node.borrow().val > val { 10 | r = node.borrow().left.clone(); 11 | } else { 12 | r = node.borrow().right.clone(); 13 | } 14 | } 15 | None 16 | } 17 | 18 | // Recursive Approach 19 | pub fn search_bst(root: Option>>, val: i32) -> Option>> { 20 | if let Some(n) = &root { 21 | if n.borrow().val > val { return Self::search_bst(n.borrow().left.clone(), val); } 22 | if n.borrow().val < val { return Self::search_bst(n.borrow().right.clone(), val); } 23 | } 24 | root 25 | } 26 | -------------------------------------------------------------------------------- /rust/28_heap/sort_heap.rs: -------------------------------------------------------------------------------- 1 | pub fn sort(nums: &mut Vec) { 2 | build_heap(nums); 3 | for i in (0..nums.len()).rev() { 4 | swap(nums, 0, i); 5 | heapify(nums, 0, i); 6 | } 7 | } 8 | 9 | fn build_heap(nums: &mut Vec) { 10 | let nums_len = nums.len(); 11 | for i in (0..nums_len).rev() { 12 | heapify(nums, i, nums_len); 13 | } 14 | } 15 | 16 | fn heapify(nums: &mut Vec, idx: usize, nums_len: usize) { 17 | let mut idx = idx; 18 | loop { 19 | let mut max_pos = idx; 20 | if 2 * idx + 1 < nums_len && nums[idx] < nums[2 * idx + 1] { max_pos = 2 * idx + 1; } 21 | if 2 * idx + 2 < nums_len && nums[max_pos] < nums[2 * idx + 2] { max_pos = 2 * idx + 2; } 22 | 23 | if max_pos == idx { break; } 24 | swap(nums, idx, max_pos); 25 | idx = max_pos; 26 | } 27 | } 28 | 29 | fn swap(nums: &mut Vec, idx: usize, parent_idx: usize) { 30 | let tmp = nums[parent_idx]; 31 | nums[parent_idx] = nums[idx]; 32 | nums[idx] = tmp; 33 | } 34 | 35 | fn main() { 36 | let mut nums = vec![9, 6, 3, 1, 5]; 37 | sort(&mut nums); 38 | println!("{:?}", nums); 39 | } 40 | -------------------------------------------------------------------------------- /rust/29_heap/get_top_k.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BinaryHeap; 2 | 3 | // 动态数组取 top k 元素 4 | fn get_top_k(nums: &mut Vec, k: i32, x: i32) -> Vec { 5 | let nums_len = nums.len() as i32; 6 | if nums_len <= k { return nums.clone(); } 7 | 8 | let mut heap = BinaryHeap::new(); 9 | 10 | // 先将数组的前k个数据放入堆中 11 | for _i in 0..k { 12 | heap.push(-nums[k as usize]); 13 | } 14 | 15 | // 对数组中其它数据进行迭代,若数据大于堆顶元素,将堆顶元素移除,将此数据放入堆中 16 | for i in k + 1..nums_len { 17 | if -nums[i as usize] < *heap.peek().unwrap() { 18 | heap.pop(); 19 | heap.push(-nums[i as usize]); 20 | } 21 | } 22 | 23 | // 向数组中插入新数据 24 | nums.push(x); 25 | 26 | // 新插入的数据若大于堆顶元素,将堆顶元素移除,将此数据放入堆中 27 | if -x < *heap.peek().unwrap() { 28 | heap.pop(); 29 | heap.push(-x); 30 | } 31 | 32 | // let m: Vec = heap.iter().map(|h| h * -1).collect(); 33 | // m 34 | 35 | heap.iter().map(|h| h * -1).collect::>() 36 | } 37 | 38 | fn main() { 39 | let mut nums = vec![4, 5, 7, 9, 10, 6, 11]; 40 | let m = get_top_k(&mut nums, 3, 23); 41 | println!("{:?}", m); 42 | } 43 | -------------------------------------------------------------------------------- /rust/35_trie/trie.rs: -------------------------------------------------------------------------------- 1 | // [leetcode 208](https://leetcode.com/problems/implement-trie-prefix-tree/) 2 | 3 | #[derive(Default, Debug)] 4 | struct Trie { 5 | is_ending: bool, 6 | nodes: [Option>; 26], 7 | } 8 | 9 | impl Trie { 10 | fn new() -> Self { 11 | Default::default() 12 | } 13 | 14 | fn insert(&mut self, word: &str) { 15 | let mut curr = self; 16 | for i in word.chars().map(|c| (c as usize - 'a' as usize) as usize) { 17 | curr = curr.nodes[i].get_or_insert_with(|| Box::new(Trie::new())); 18 | } 19 | curr.is_ending = true; 20 | } 21 | 22 | fn find(&self, word: &str) -> bool { 23 | let mut curr = self; 24 | for i in word.chars().map(|c| (c as usize - 'a' as usize) as usize) { 25 | match curr.nodes[i].as_ref() { 26 | Some(node) => { curr = node; }, 27 | None => { return false; }, 28 | } 29 | } 30 | curr.is_ending 31 | } 32 | } 33 | 34 | fn main() { 35 | let mut m = Trie::new(); 36 | m.insert("hello"); 37 | m.insert("she"); 38 | println!("{:?}", m); 39 | let r = m.search("hello"); 40 | println!("{}", r); // true 41 | } 42 | -------------------------------------------------------------------------------- /rust/40_dynamic_programming/knapsack.rs: -------------------------------------------------------------------------------- 1 | fn knapsack(items: Vec<(i32, i32)>, capacity: i32) -> i32 { 2 | let mut states = vec![-1; (capacity + 1) as usize]; 3 | let mut result = vec![]; 4 | states[0] = 0; 5 | if items[0].0 <= capacity { states[items[0].0 as usize] = items[0].1; } 6 | for i in 1..items.len() { 7 | for j in 0..=(capacity - items[i].0) as usize { 8 | if states[j] >= 0 { 9 | let value = states[j] + items[i].1; 10 | if value > states[j+items[i].0 as usize] { 11 | states[j+items[i].0 as usize] = value; 12 | result.push(items[i].0); 13 | } 14 | } 15 | } 16 | } 17 | 18 | let mut max_value = -1; 19 | for i in (0..=capacity as usize).rev() { 20 | if states[i] >= max_value { 21 | max_value = states[i]; 22 | } 23 | } 24 | max_value 25 | } 26 | 27 | fn main() { 28 | let items = vec![(2, 3), (2, 4), (4, 8), (6, 9), (3, 6)]; 29 | let capacity = 9; 30 | let m = knapsack(items, capacity); 31 | println!("{}", m); 32 | } 33 | -------------------------------------------------------------------------------- /rust/40_dynamic_programming/triangle.rs: -------------------------------------------------------------------------------- 1 | # leetcode [minimum_total](https://leetcode.com/problems/triangle/) 2 | 3 | pub fn minimum_total(mut triangle: Vec>) -> i32 { 4 | if triangle.len() == 0 { return 0; } 5 | 6 | for i in (0..triangle.len() - 1).rev() { 7 | for j in 0..triangle[i].len() { 8 | triangle[i][j] = triangle[i+1][j].min(triangle[i+1][j+1]) + triangle[i][j]; 9 | } 10 | } 11 | triangle[0][0] 12 | } 13 | 14 | fn main() { 15 | let triangle = vec![ 16 | vec![2], 17 | vec![3, 4], 18 | vec![6, 5, 7], 19 | vec![4, 1, 8, 3], 20 | ]; 21 | 22 | println!("{:?}", minimum_total(triangle)); 23 | } 24 | -------------------------------------------------------------------------------- /rust/41_dynamic_programming/coin_change.rs: -------------------------------------------------------------------------------- 1 | fn coin_change(coins: Vec, amount: i32) -> i32 { 2 | let mut dp = vec![amount+1; (amount+1) as usize]; 3 | dp[0] = 0; 4 | for i in 1..=amount as usize { 5 | for &coin in coins.iter() { 6 | if i as i32 >= coin { 7 | dp[i] = dp[i].min(dp[i-coin as usize] + 1); 8 | } 9 | } 10 | } 11 | 12 | let last = *dp.last().unwrap(); 13 | if last > amount { -1 } else { last } 14 | } 15 | fn main() { 16 | let coins = vec![1, 3, 5]; 17 | 18 | let m = coin_change(coins, 9); 19 | println!("{}", m); // 3 20 | } 21 | -------------------------------------------------------------------------------- /rust/41_dynamic_programming/min_dis_path.rs: -------------------------------------------------------------------------------- 1 | fn min_dis_path(matrix: Vec>) -> i32 { 2 | let m_len = matrix.len(); 3 | if m_len == 0 { return 0; } 4 | 5 | let mut states = vec![vec![0; m_len]; m_len]; 6 | let mut sum = 0; 7 | // 初始化第一行数据 8 | for j in 0..m_len { 9 | sum += matrix[0][j]; 10 | states[0][j] = sum; 11 | } 12 | 13 | sum = 0; 14 | // 初始化第一列数据 15 | for i in 0..m_len { 16 | sum += matrix[i][0]; 17 | states[i][0] = sum; 18 | } 19 | 20 | for i in 1..m_len { 21 | for j in 1..m_len { 22 | states[i][j] = matrix[i][j] + states[i-1][j].min(states[i][j-1]) 23 | } 24 | } 25 | 26 | states[m_len-1][m_len-1] 27 | } 28 | fn main() { 29 | let matrix = vec![ 30 | vec![1, 3, 5, 9], 31 | vec![2, 1, 3, 4], 32 | vec![5, 2, 6, 7], 33 | vec![6, 8, 4, 3], 34 | ]; 35 | 36 | let m = min_dis_path(matrix); 37 | println!("{}", m); 38 | } 39 | -------------------------------------------------------------------------------- /rust/42_dynamic_programming/edit_distance.rs: -------------------------------------------------------------------------------- 1 | // leetcode 72 [edit_distance](https://leetcode.com/problems/edit-distance/) 2 | fn edit_distance(word1: &str, word2: &str) -> i32 { 3 | let word1_chars: Vec = word1.chars().collect(); 4 | let word2_chars: Vec = word2.chars().collect(); 5 | let m = word1.len(); 6 | let n = word2.len(); 7 | let mut dp = vec![vec![0; m+1]; n+1]; 8 | 9 | // 初始化第一行 10 | for i in 0..=m { dp[i][0] = i; } 11 | // 初始化第一列 12 | for j in 0..=n { dp[0][j] = j; } 13 | 14 | for i in 1..=m { 15 | for j in 1..=n { 16 | let mut step = 0; 17 | if word1_chars[i-1] != word2_chars[j-1] { step = 1; } 18 | dp[i][j] = (dp[i][j-1] + 1).min(dp[i-1][j] + 1).min(dp[i-1][j-1] + step); 19 | } 20 | } 21 | 22 | dp[m][n] as i32 23 | } 24 | fn main() { 25 | let word1 = "mitcmu"; 26 | let word2 = "mtacnu"; 27 | let m = edit_distance(word1, word2); 28 | println!("{:?}", m); 29 | } 30 | -------------------------------------------------------------------------------- /rust/42_dynamic_programming/longest_increasing_subsequence.rs: -------------------------------------------------------------------------------- 1 | // leetcode 300 [longest_increasing_subsequence](https://leetcode.com/problems/longest-increasing-subsequence) 2 | fn longest_increasing_subsequence(nums: Vec) -> i32 { 3 | if nums.len() <= 1 { return nums.len() as i32; } 4 | 5 | let mut dp = vec![1; nums.len()]; 6 | let mut max_list = 1; 7 | 8 | for i in 0..nums.len() { 9 | for j in 0..i { 10 | if nums[i] > nums[j] { 11 | dp[i] = dp[i].max(dp[j]+1); 12 | } 13 | } 14 | max_list = max_list.max(dp[i]); 15 | } 16 | max_list 17 | } 18 | fn main() { 19 | let nums = vec![2, 9, 3, 6, 5, 1, 7]; 20 | let m = longest_increasing_subsequence(nums); 21 | println!("{:?}", m); 22 | } 23 | -------------------------------------------------------------------------------- /scala/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /scala/build.sbt: -------------------------------------------------------------------------------- 1 | lazy val root = (project in file(".")) 2 | .settings( 3 | name := "algo-scala", 4 | version := "1.0", 5 | scalaVersion := "2.12.8", 6 | libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.5" % "test" 7 | ) 8 | -------------------------------------------------------------------------------- /scala/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.2.1 2 | -------------------------------------------------------------------------------- /scala/src/main/scala/ch05_array/ArrayDemo.scala: -------------------------------------------------------------------------------- 1 | package ch05_array 2 | 3 | class ArrayDemo(capacity: Int) { 4 | 5 | var data: Array[Char] = new Array[Char](capacity) 6 | var length: Int = 0 7 | 8 | def find(index: Int): Char = { 9 | if (index < 0 || index > length) { 10 | return 0.toChar 11 | } 12 | data(index) 13 | } 14 | 15 | def insert(index: Int, value: Char): Boolean = { 16 | if (length == capacity) { 17 | return false 18 | } 19 | 20 | if (index < 0 || index >= capacity) { 21 | return false 22 | } 23 | 24 | for (i <- length until index by -1) { 25 | data(i) = data(i - 1) 26 | } 27 | data(index) = value 28 | length += 1 29 | 30 | true 31 | } 32 | 33 | def delete(index: Int): Char = { 34 | if (length == 0) { 35 | throw new IllegalStateException("array is empty") 36 | } 37 | if (index >= length) { 38 | throw new IllegalStateException("index out of range, current data length is " + length) 39 | } 40 | val result = data(index) 41 | for (i <- index until length-1) { 42 | data(i) = data(i + 1) 43 | } 44 | 45 | length -= 1 46 | result 47 | } 48 | 49 | def print: String = { 50 | data.subSequence(0, length).toString 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /scala/src/main/scala/ch08_stack/BrowserDemo.scala: -------------------------------------------------------------------------------- 1 | package ch08_stack 2 | 3 | class BrowserDemo(var currentPageOpt: Option[String], val backStack: StackDemo[String], 4 | val forwardStack: StackDemo[String]) { 5 | 6 | def this() = this(None, new StackDemo[String], new StackDemo[String]) 7 | 8 | def open(page: String) = { 9 | currentPageOpt.foreach(backStack.push) 10 | forwardStack.clear() 11 | currentPageOpt = Some(page) 12 | } 13 | 14 | def canGoBack(): Boolean = backStack.size > 0 15 | 16 | def goBack(): Unit = { 17 | backStack.pop().foreach(page => { 18 | forwardStack.push(currentPageOpt.get) 19 | currentPageOpt = Some(page.data) 20 | }) 21 | } 22 | 23 | def canGoForward(): Boolean = forwardStack.size > 0 24 | 25 | def goForward(): Unit = { 26 | forwardStack.pop().foreach(page => { 27 | backStack.push(currentPageOpt.get) 28 | currentPageOpt = Some(page.data) 29 | }) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /scala/src/main/scala/ch08_stack/StackDemo.scala: -------------------------------------------------------------------------------- 1 | package ch08_stack 2 | 3 | class Node[T](var data: T, var next: Option[Node[T]]) 4 | 5 | class StackDemo[T] { 6 | 7 | 8 | var headOpt: Option[Node[T]] = None 9 | var size = 0 10 | 11 | def clear(): Unit = { 12 | headOpt = None 13 | size = 0 14 | } 15 | 16 | def push(data: T) = { 17 | val newHead = new Node(data, headOpt) 18 | headOpt = Some(newHead) 19 | size += 1 20 | } 21 | 22 | def pop(): Option[Node[T]] = { 23 | headOpt match { 24 | case None => None 25 | case Some(head) => 26 | headOpt = head.next 27 | size -= 1 28 | Some(head) 29 | 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /scala/src/main/scala/ch09_queue/ArrayQueue.scala: -------------------------------------------------------------------------------- 1 | package ch09_queue 2 | 3 | import scala.reflect.ClassTag 4 | 5 | class ArrayQueue[T: ClassTag](capacity: Int) extends DemoQueue[T] { 6 | 7 | var items: Array[T] = new Array[T](capacity) 8 | var head = 0 9 | var tail = 0 10 | 11 | override def enqueue(data: T): Unit = { 12 | require(tail < capacity, "queue is full") 13 | items(tail) = data 14 | tail += 1 15 | size += 1 16 | } 17 | 18 | override def dequeue(): Option[T] = { 19 | if (head < tail) { 20 | val result = Some(items(head)) 21 | head += 1 22 | size -= 1 23 | result 24 | } else { 25 | None 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /scala/src/main/scala/ch09_queue/CircularQueue.scala: -------------------------------------------------------------------------------- 1 | package ch09_queue 2 | 3 | import scala.reflect.ClassTag 4 | 5 | class CircularQueue[T: ClassTag](capacity: Int) extends DemoQueue[T] { 6 | 7 | var items: Array[T] = new Array[T](capacity) 8 | var head = 0 9 | var tail = 0 10 | 11 | 12 | override def enqueue(data: T): Unit = { 13 | require((tail + 1) % capacity != head, "queue is full") 14 | items(tail) = data 15 | tail = (tail + 1) % capacity 16 | size += 1 17 | } 18 | 19 | override def dequeue(): Option[T] = { 20 | if (head == tail) { 21 | None 22 | } else { 23 | size -= 1 24 | val result = Some(items(head)) 25 | head = (head + 1) % capacity 26 | result 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /scala/src/main/scala/ch09_queue/DemoQueue.scala: -------------------------------------------------------------------------------- 1 | package ch09_queue 2 | 3 | trait DemoQueue[T] { 4 | 5 | var size = 0 6 | 7 | def enqueue(data: T): Unit 8 | 9 | def dequeue(): Option[T] 10 | } 11 | -------------------------------------------------------------------------------- /scala/src/main/scala/ch09_queue/DynamicArrayQueue.scala: -------------------------------------------------------------------------------- 1 | package ch09_queue 2 | 3 | import scala.reflect.ClassTag 4 | 5 | class DynamicArrayQueue[T: ClassTag](val capacity: Int) extends ArrayQueue[T](capacity) { 6 | 7 | override def enqueue(data: T): Unit = { 8 | if (tail == capacity) { 9 | //tail is the end of 10 | require(head > 0, "queue is full") 11 | for (i <- Range(head, tail)) { 12 | items(i - head) = items(head) 13 | } 14 | tail = tail - head 15 | head = 0 16 | } 17 | super.enqueue(data) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /scala/src/main/scala/ch09_queue/LinkedListQueue.scala: -------------------------------------------------------------------------------- 1 | package ch09_queue 2 | 3 | class Node[T](var data: T, var next: Option[Node[T]]) 4 | 5 | class LinkListQueue[T]() extends DemoQueue[T] { 6 | 7 | var headOpt: Option[Node[T]] = None 8 | var tailOpt: Option[Node[T]] = None 9 | 10 | override 11 | def enqueue(data: T): Unit = { 12 | val node = new Node(data, None) 13 | size += 1 14 | headOpt match { 15 | case None => headOpt = Some(node) 16 | case Some(_) => 17 | } 18 | tailOpt match { 19 | case None => tailOpt = Some(node) 20 | case Some(tail) => 21 | tail.next = Some(node) 22 | tailOpt = Some(node) 23 | } 24 | } 25 | 26 | override 27 | def dequeue(): Option[T] = { 28 | headOpt.map(head => { 29 | size -= 1 30 | headOpt = head.next 31 | if (headOpt.isEmpty) { 32 | //head is empty reach the end of the queue 33 | tailOpt = None 34 | } 35 | head.data 36 | }) 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /scala/src/main/scala/ch10_recursive/RecursiveDemo.scala: -------------------------------------------------------------------------------- 1 | package ch10_recursive 2 | 3 | import scala.collection.mutable 4 | 5 | object RecursiveDemo { 6 | 7 | def calculateStepWays(steps: Int): Int = { 8 | //use knownResults to avoid duplicated computing 9 | val knownResults = mutable.HashMap.empty[Int, Int] 10 | steps match { 11 | case 1 => 1 12 | case 2 => 2 13 | case _ => knownResults.get(steps) match { 14 | case Some(result) => result 15 | case None => { 16 | val result = calculateStepWays(steps - 1) + calculateStepWays(steps - 2) 17 | knownResults.put(steps, result) 18 | result 19 | } 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /scala/src/main/scala/ch15_bsearch/BSearchRecursive.scala: -------------------------------------------------------------------------------- 1 | package ch15_bsearch 2 | 3 | object BSearchRecursive { 4 | 5 | def search(items: Array[Int], target: Int): Int = { 6 | _search(items, target, 0, items.length - 1) 7 | } 8 | 9 | private[this] def _search(items: Array[Int], target: Int, low: Int, high: Int): Int = { 10 | if (low > high) { 11 | return -1 12 | } 13 | 14 | val mid = low + (high - low) / 2 15 | if (items(mid) == target) { 16 | mid 17 | } else if (items(mid) > target) { 18 | _search(items, target, low, mid - 1) 19 | } else { 20 | _search(items, target, mid + 1, high) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /scala/src/main/scala/ch29_heap_solutions/MiddleNumberKeeper.scala: -------------------------------------------------------------------------------- 1 | package ch29_heap_solutions 2 | 3 | import scala.collection.mutable 4 | 5 | class MiddleNumberKeeper(val percent: Double) { 6 | 7 | def this() = this(0.5) 8 | 9 | val bigTop = new mutable.PriorityQueue[Int]() 10 | val smallTop = new mutable.PriorityQueue[Int]()(scala.math.Ordering.Int.reverse) 11 | 12 | 13 | def put(num: Int): Unit = { 14 | if (smallTop.nonEmpty && num >= smallTop.head) { 15 | smallTop += num 16 | adjustHeap() 17 | return 18 | } 19 | 20 | //for any other scenario, we just put the item to bitTop then adjustHeap 21 | bigTop += num 22 | adjustHeap() 23 | } 24 | 25 | def get(): Option[Int] = { 26 | bigTop.headOption 27 | } 28 | 29 | private[this] def adjustHeap(): Unit = { 30 | val totalLength = smallTop.length + bigTop.length 31 | //deal with bigTop 32 | while (bigTop.length.doubleValue() / totalLength - percent > 0.0001) { 33 | //move item from bigTop to smallTop 34 | smallTop += bigTop.dequeue() 35 | } 36 | 37 | //deal with smallTop 38 | while (smallTop.length.doubleValue() / totalLength - (1.0D - percent) > 0.0001) { 39 | bigTop += smallTop.dequeue() 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /scala/src/main/scala/ch29_heap_solutions/TopKItemsKeeper.scala: -------------------------------------------------------------------------------- 1 | package ch29_heap_solutions 2 | 3 | import scala.collection.mutable 4 | 5 | /** 6 | * keep the top k items in the the class 7 | */ 8 | class TopKItemsKeeper(val itemsToKeepCount: Int) { 9 | 10 | 11 | //have a smallest value top heap 12 | val queue = new mutable.PriorityQueue[Int]()(scala.math.Ordering.Int.reverse) 13 | 14 | def put(item: Int): Unit = { 15 | if (queue.length < itemsToKeepCount) { 16 | queue += item 17 | return 18 | } 19 | 20 | //queue already have the k items 21 | if (item.compareTo(queue.head) > 0) { 22 | queue.dequeue() 23 | queue += item 24 | } 25 | } 26 | 27 | def get(): List[Int] = { 28 | queue.clone().dequeueAll 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /scala/src/main/scala/ch32_matching/BruteForce.scala: -------------------------------------------------------------------------------- 1 | package ch32_matching 2 | 3 | import scala.util.control.Breaks._ 4 | 5 | object BruteForce { 6 | 7 | def firstIndexOf(main: Array[Char], sub: Array[Char]): Int = { 8 | 9 | require(main != null, "main array required") 10 | require(sub != null, "sub array required") 11 | require(main.length >= sub.length, "sub array should be small than main array") 12 | var result = -1 13 | breakable { 14 | for (i <- 0 until (main.length - sub.length)) { 15 | if (main.slice(i, i + sub.length) sameElements sub) { 16 | result = i 17 | break 18 | } 19 | } 20 | } 21 | result 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /scala/src/main/scala/ch32_matching/RabinKarp.scala: -------------------------------------------------------------------------------- 1 | package ch32_matching 2 | 3 | import scala.util.control.Breaks.{break, breakable} 4 | 5 | object RabinKarp { 6 | 7 | def firstIndexOf(main: Array[Char], sub: Array[Char]): Int = { 8 | require(main != null, "main array required") 9 | require(sub != null, "sub array required") 10 | require(main.length >= sub.length, "sub array should be small than main array") 11 | val baseNums: Array[Long] = new Array[Long](sub.length) 12 | for (i <- sub.indices) { 13 | baseNums(i) = scala.math.pow(128, i).longValue() 14 | } 15 | 16 | val subHash = hash(sub, baseNums) 17 | var result = -1 18 | breakable { 19 | for (i <- 0 until (main.length - sub.length)) { 20 | if (hash(main.slice(i, i + sub.length), baseNums).equals(subHash) 21 | && main.slice(i, i + sub.length).sameElements(sub)) { 22 | result = i 23 | break 24 | } 25 | } 26 | } 27 | result 28 | 29 | } 30 | 31 | def hash(array: Array[Char], baseNums: Array[Long]): Long = { 32 | var hash = 0L 33 | for (i <- array.indices) { 34 | hash += array(i).toInt * baseNums(array.length - 1 - i) 35 | } 36 | hash 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /scala/src/main/scala/ch39_back_tracking/BagWeight.scala: -------------------------------------------------------------------------------- 1 | package ch39_back_tracking 2 | 3 | class BagWeight(maxBagItemCount: Int, maxBagWeight: Int) { 4 | 5 | def calculateMaxWeight(items: Array[Int]): Int = { 6 | var maxWeight = 0 7 | 8 | def _calcMaxWeight(itemIndex: Int, currentWeight: Int): Unit = { 9 | if (currentWeight == maxBagWeight || itemIndex == items.length) { 10 | if (currentWeight > maxWeight) { 11 | maxWeight = currentWeight 12 | } 13 | } else { 14 | //check next item 15 | _calcMaxWeight(itemIndex + 1, currentWeight) 16 | if (currentWeight + items(itemIndex) <= maxBagWeight) { 17 | _calcMaxWeight(itemIndex + 1, currentWeight + items(itemIndex)) 18 | } 19 | } 20 | } 21 | 22 | _calcMaxWeight(0, 0) 23 | maxWeight 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch06_linkedlist/NodeTest.scala: -------------------------------------------------------------------------------- 1 | package ch06_linkedlist 2 | 3 | import org.scalatest.{FlatSpec, Matchers} 4 | 5 | class NodeTest extends FlatSpec with Matchers { 6 | 7 | behavior of "NodeTest" 8 | it should "create node with constructor" in { 9 | val node1 = new Node(1, None) 10 | val node2 = new Node(2, Some(node1)) 11 | val node3 = new Node(2, Some(node2)) 12 | 13 | node1.next should be(None) 14 | node1.next = Some(node3) 15 | node1.next should equal(Some(node3)) 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch08_stack/StackDemoTest.scala: -------------------------------------------------------------------------------- 1 | package ch08_stack 2 | 3 | import org.scalatest.{FlatSpec, Matchers} 4 | 5 | class StackDemoTest extends FlatSpec with Matchers { 6 | 7 | behavior of "StackDemoTest" 8 | 9 | it should "push/pop should be FILO" in { 10 | val stack = new StackDemo[String] 11 | val num = 100 12 | for (i <- 1 to num) { 13 | stack.push(i.toString) 14 | } 15 | 16 | for (i <- num to 1 by -1) { 17 | stack.pop().get.data should equal(i.toString) 18 | } 19 | } 20 | 21 | it should "pop should also work for empty stack" in { 22 | val stack = new StackDemo[Int] 23 | val num = 100 24 | for (i <- num to 1 by -1) { 25 | assert(stack.pop().isEmpty) 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch09_queue/ArrayQueueTest.scala: -------------------------------------------------------------------------------- 1 | package ch09_queue 2 | 3 | class ArrayQueueTest extends DemoQueueTest { 4 | 5 | override def getInstance() = new ArrayQueue[Int](15) 6 | } 7 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch09_queue/CircularQueueTest.scala: -------------------------------------------------------------------------------- 1 | package ch09_queue 2 | 3 | class CircularQueueTest extends DemoQueueTest { 4 | 5 | override def getInstance(): DemoQueue[Int] = new CircularQueue[Int](15) 6 | } 7 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch09_queue/DemoQueueTest.scala: -------------------------------------------------------------------------------- 1 | package ch09_queue 2 | 3 | import org.scalatest.{FlatSpec, Matchers} 4 | 5 | abstract class DemoQueueTest extends FlatSpec with Matchers { 6 | 7 | def getInstance(): DemoQueue[Int] 8 | 9 | behavior of "test" 10 | 11 | it should "dequeue nothing for empty queue" in { 12 | val queue = getInstance() 13 | assert(queue.dequeue().isEmpty) 14 | } 15 | 16 | it should "enqueue/dequeue should be FIFO" in { 17 | val queue = getInstance() 18 | for (i <- Range(0, 10)) { 19 | queue.enqueue(i) 20 | } 21 | 22 | queue.size should equal(10) 23 | 24 | for (i <- Range(0, 10)) { 25 | queue.dequeue().get should equal(i) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch09_queue/DynamicArrayQueueTest.scala: -------------------------------------------------------------------------------- 1 | package ch09_queue 2 | 3 | class DynamicArrayQueueTest extends DemoQueueTest { 4 | 5 | override def getInstance(): DemoQueue[Int] = new DynamicArrayQueue[Int](15) 6 | 7 | it should "copy data when tail reach the end of the queue" in { 8 | val queue = getInstance() 9 | for (i <- Range(0, 15)) { 10 | queue.enqueue(i) 11 | } 12 | queue.size should equal(15) 13 | queue.dequeue().get should equal(0) 14 | 15 | //enqueue another one 16 | queue.enqueue(30) 17 | queue.size should equal(15) 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch09_queue/LinkedListQueueTest.scala: -------------------------------------------------------------------------------- 1 | package ch09_queue 2 | 3 | class LinkedListQueueTest extends DemoQueueTest { 4 | 5 | override def getInstance() = new LinkListQueue[Int] 6 | 7 | } 8 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch10_recursive/RecursiveDemoTest.scala: -------------------------------------------------------------------------------- 1 | package ch10_recursive 2 | 3 | import org.scalatest.{FlatSpec, Matchers} 4 | 5 | class RecursiveDemoTest extends FlatSpec with Matchers { 6 | 7 | behavior of "RecursiveDemoTest" 8 | 9 | it should "calculateStepWays" in { 10 | RecursiveDemo.calculateStepWays(1) should equal(1) 11 | RecursiveDemo.calculateStepWays(2) should equal(2) 12 | RecursiveDemo.calculateStepWays(3) should equal(3) 13 | RecursiveDemo.calculateStepWays(4) should equal(5) 14 | RecursiveDemo.calculateStepWays(5) should equal(8) 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch12_sorts/MergeSortTest.scala: -------------------------------------------------------------------------------- 1 | package ch12_sorts 2 | 3 | 4 | import org.scalatest.{FlatSpec, Matchers} 5 | 6 | class MergeSortTest extends FlatSpec with Matchers { 7 | behavior of "SortsTest in ch12" 8 | 9 | it should "mergeSort int arrays" in { 10 | var array = Array(4, 5, 6, 3, 2, 1) 11 | array = MergeSort.mergeSort(array) 12 | array.mkString("") should equal("123456") 13 | 14 | array = Array(4) 15 | array = MergeSort.mergeSort(array) 16 | array.mkString("") should equal("4") 17 | 18 | array = Array(4, 2) 19 | array = MergeSort.mergeSort(array) 20 | array.mkString("") should equal("24") 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch12_sorts/QuickSortTest.scala: -------------------------------------------------------------------------------- 1 | package ch12_sorts 2 | 3 | import org.scalatest.{FlatSpec, Matchers} 4 | 5 | class QuickSortTest extends FlatSpec with Matchers { 6 | 7 | behavior of "QuickSortTest" 8 | 9 | it should "quickSort" in { 10 | var array = Array(4, 5, 6, 3, 2, 1) 11 | array = QuickSort.quickSort(array) 12 | array.mkString("") should equal("123456") 13 | 14 | array = Array(4) 15 | array = QuickSort.quickSort(array) 16 | array.mkString("") should equal("4") 17 | 18 | array = Array(4, 2) 19 | array = QuickSort.quickSort(array) 20 | array.mkString("") should equal("24") 21 | } 22 | 23 | it should "find the Kth element in the array" in { 24 | val array = Array(4, 2, 5, 12, 3) 25 | 26 | QuickSort.findKthElement(array, 3) should equal(4) 27 | QuickSort.findKthElement(array, 5) should equal(12) 28 | QuickSort.findKthElement(array, 1) should equal(2) 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch15_bsearch/BSearchRecursiveTest.scala: -------------------------------------------------------------------------------- 1 | package ch15_bsearch 2 | 3 | import ch12_sorts.QuickSort 4 | import org.scalatest.{FlatSpec, Matchers} 5 | 6 | import scala.util.Random 7 | 8 | class BSearchRecursiveTest extends FlatSpec with Matchers { 9 | 10 | behavior of "BSearchRecursiveTest" 11 | 12 | it should "search with exist value" in { 13 | val length = 50000 14 | val array = new Array[Int](length) 15 | val rnd = new Random() 16 | for (i <- Range(0, length)) { 17 | array(i) = rnd.nextInt() 18 | } 19 | 20 | val target = array(2698) 21 | 22 | BSearchRecursive.search(QuickSort.quickSort(array), target) should be > -1 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch15_bsearch/BSearchTest.scala: -------------------------------------------------------------------------------- 1 | package ch15_bsearch 2 | 3 | import ch12_sorts.QuickSort 4 | import org.scalatest.{FlatSpec, Matchers} 5 | 6 | import scala.util.Random 7 | 8 | class BSearchTest extends FlatSpec with Matchers { 9 | 10 | behavior of "BSearchTest" 11 | 12 | it should "search with exist value" in { 13 | val length = 50000 14 | val array = new Array[Int](length) 15 | val rnd = new Random() 16 | for (i <- Range(0, length)) { 17 | array(i) = rnd.nextInt() 18 | } 19 | 20 | val target = array(2698) 21 | 22 | BSearch.search(QuickSort.quickSort(array), target) should be > -1 23 | } 24 | 25 | it should "calculate sqrt value -1 " in { 26 | val x = 4 27 | val precision = 0.000001 28 | BSearch.sqrt(x, precision) should equal(2.0) 29 | } 30 | 31 | it should "calculate sqrt value -2 " in { 32 | val x = 0.04 33 | val precision = 0.000001 34 | BSearch.sqrt(x, precision) should equal(0.2 +- precision) 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch16_bsearch/BSearchTest.scala: -------------------------------------------------------------------------------- 1 | package ch16_bsearch 2 | 3 | import org.scalatest.{FlatSpec, Matchers} 4 | 5 | class BSearchTest extends FlatSpec with Matchers { 6 | 7 | behavior of "BSearchTest" 8 | 9 | it should "findFirstValue" in { 10 | val items = Array(1, 3, 4, 5, 6, 8, 8, 8, 11, 18) 11 | BSearch.findFirstValue(items, 8) should equal(5) 12 | } 13 | 14 | it should "findLastValue" in { 15 | val items = Array(1, 3, 4, 5, 6, 8, 8, 8, 11, 18) 16 | BSearch.findLastValue(items, 8) should equal(7) 17 | } 18 | 19 | it should "findFirstGreaterThan" in { 20 | val items = Array(1, 3, 4, 5, 6, 8, 8, 8, 11, 18) 21 | BSearch.findFirstGreaterThan(items, 2) should equal(1) 22 | BSearch.findFirstGreaterThan(items, 8) should equal(5) 23 | } 24 | 25 | it should "findLastSmallerThan" in { 26 | val items = Array(1, 3, 4, 5, 6, 8, 8, 8, 11, 18) 27 | BSearch.findLastSmallerThan(items, 2) should equal(0) 28 | BSearch.findLastSmallerThan(items, 8) should equal(7) 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch17_skip_list/SkipListTest.scala: -------------------------------------------------------------------------------- 1 | package ch17_skip_list 2 | 3 | import org.scalatest.{FlatSpec, Matchers} 4 | 5 | import scala.util.Random 6 | 7 | class SkipListTest extends FlatSpec with Matchers { 8 | 9 | behavior of "SkipListTest" 10 | 11 | it should "insert skip list" in { 12 | val list = new SkipList() 13 | for (i <- Range(0, 10)) { 14 | list.insert(i) 15 | } 16 | 17 | list.mkString() should equal("0123456789") 18 | } 19 | 20 | it should "delete skip list" in { 21 | val list = new SkipList() 22 | for (i <- Range(0, 10)) { 23 | list.insert(i) 24 | } 25 | 26 | list.delete(5) 27 | list.mkString() should equal("012346789") 28 | } 29 | 30 | it should "find value in skip list" in { 31 | val list = new SkipList() 32 | val length = 5000 33 | val array = new Array[Int](length) 34 | val rnd = new Random() 35 | for (i <- Range(0, length)) { 36 | array(i) = rnd.nextInt(length) 37 | list.insert(array(i)) 38 | } 39 | 40 | assert(list.find(array(rnd.nextInt(length - 1))).isDefined) 41 | assert(list.find(array(rnd.nextInt(length - 1)) + length + 1).isEmpty) 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch20_linked_hash_map/LRUCacheTest.scala: -------------------------------------------------------------------------------- 1 | package ch20_linked_hash_map 2 | 3 | import org.scalatest.{FlatSpec, Matchers} 4 | 5 | class LRUCacheTest extends FlatSpec with Matchers { 6 | 7 | behavior of "LRUCacheTest" 8 | 9 | it should "put data and get back" in { 10 | val cache = new LRUCache[Int, Int](2) 11 | cache.put(1, 1) 12 | cache.put(2, 2) 13 | cache.get(1) should equal(Some(1)) // returns 1 14 | cache.put(3, 3) // evicts key 2 15 | cache.get(2) should equal(None) //should not find 16 | cache.put(4, 4) // evicts key 1 17 | cache.get(1) should equal(None) //should not find 18 | cache.get(3) should equal(Some(3)) // returns 3 19 | cache.get(4) should equal(Some(4)) // returns 4 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch28_heap/HeapTest.scala: -------------------------------------------------------------------------------- 1 | package ch28_heap 2 | 3 | import org.scalatest.{FlatSpec, Matchers} 4 | 5 | class HeapTest extends FlatSpec with Matchers { 6 | 7 | behavior of "HeapTest" 8 | 9 | it should "insert and removeMax" in { 10 | val nums = Array(33, 27, 21, 16, 13, 15, 19, 5, 6, 7, 8, 1, 2, 12) 11 | val heap = new Heap(nums.length + 1) 12 | nums.foreach(heap.insert) 13 | 14 | heap.removeMax() should equal(33) 15 | heap.removeMax() should equal(27) 16 | } 17 | 18 | it should "build heap from array - bottom up" in { 19 | val nums = Array(33, 27, 21, 16, 13, 15, 19, 5, 6, 7, 8, 1, 2, 12) 20 | val heap = new Heap(nums, true) 21 | 22 | heap.removeMax() should equal(33) 23 | heap.removeMax() should equal(27) 24 | } 25 | 26 | it should "build heap from array - top down" in { 27 | val nums = Array(33, 27, 21, 16, 13, 15, 19, 5, 6, 7, 8, 1, 2, 12) 28 | val heap = new Heap(nums, false) 29 | 30 | heap.removeMax() should equal(33) 31 | heap.removeMax() should equal(27) 32 | } 33 | 34 | it should "sort array" in { 35 | val nums = Array(33, 27, 21, 16, 13, 15, 19, 5, 6, 7, 8, 1, 2, 12) 36 | val result = Heap.heapSort(nums) 37 | 38 | result.mkString("") should equal(nums.sorted.mkString("")) 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch29_heap_solutions/MiddleNumberKeeperTest.scala: -------------------------------------------------------------------------------- 1 | package ch29_heap_solutions 2 | 3 | import org.scalatest.{FlatSpec, Matchers} 4 | 5 | class MiddleNumberKeeperTest extends FlatSpec with Matchers { 6 | 7 | behavior of "MiddleNumberKeeperTest" 8 | 9 | it should "get middle of the array" in { 10 | val numKeeper = new MiddleNumberKeeper() 11 | for (i <- Range(0, 10)) { 12 | numKeeper.put(i) 13 | } 14 | 15 | numKeeper.get().get should equal(4) 16 | } 17 | 18 | it should "get 90% position of the array" in { 19 | val numKeeper = new MiddleNumberKeeper(0.9) 20 | for (i <- Range(0, 9)) { 21 | numKeeper.put(i) 22 | } 23 | numKeeper.put(9) 24 | 25 | numKeeper.get().get should equal(8) 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch29_heap_solutions/TopKItemsKeeperTest.scala: -------------------------------------------------------------------------------- 1 | package ch29_heap_solutions 2 | 3 | import org.scalatest.{FlatSpec, Matchers} 4 | 5 | import scala.util.Random 6 | 7 | class TopKItemsKeeperTest extends FlatSpec with Matchers { 8 | 9 | behavior of "TopKItemsKeeperTest" 10 | 11 | it should "put and get top K from the keeper" in { 12 | val length = 50 13 | val k = 5 14 | val topKItemsKeeper = new TopKItemsKeeper(k) 15 | val nums = new Array[Int](length) 16 | for (i <- Range(0, length)) { 17 | nums(i) = Random.nextInt 18 | } 19 | 20 | nums.foreach(topKItemsKeeper.put) 21 | val ordering = scala.math.Ordering.Int.reverse 22 | topKItemsKeeper.get().toArray.sorted(ordering) should equal(nums.sorted(ordering).slice(0, k)) 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch32_matching/BruteForceTest.scala: -------------------------------------------------------------------------------- 1 | package ch32_matching 2 | 3 | import org.scalatest.{FlatSpec, Matchers} 4 | 5 | import scala.util.Random 6 | 7 | class BruteForceTest extends FlatSpec with Matchers { 8 | 9 | behavior of "BruteForceTest" 10 | 11 | it should "find firstIndexOf a sub string" in { 12 | val random = Random.alphanumeric 13 | val main = random.take(1000).toArray 14 | val index = Random.nextInt(950) 15 | val sub = random.take(1000).toArray.slice(index, index + 50) 16 | 17 | BruteForce.firstIndexOf(main, sub) should equal(index) 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch32_matching/RabinKarpTest.scala: -------------------------------------------------------------------------------- 1 | package ch32_matching 2 | 3 | import org.scalatest.{FlatSpec, Matchers} 4 | 5 | import scala.util.Random 6 | 7 | class RabinKarpTest extends FlatSpec with Matchers { 8 | 9 | it should "find firstIndexOf a sub string" in { 10 | val random = Random.alphanumeric 11 | val main = random.take(1000).toArray 12 | val index = Random.nextInt(950) 13 | val sub = random.take(1000).toArray.slice(index, index + 50) 14 | 15 | RabinKarp.firstIndexOf(main, sub) should equal(index) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch39_back_tracking/BagWeightTest.scala: -------------------------------------------------------------------------------- 1 | package ch39_back_tracking 2 | 3 | import org.scalatest.FlatSpec 4 | 5 | class BagWeightTest extends FlatSpec { 6 | 7 | behavior of "BagWeightTest" 8 | 9 | it should "calculateMaxWeight" in { 10 | val bagWeight = new BagWeight(5,9) 11 | val maxWeight = bagWeight.calculateMaxWeight(Array(1,2,3,5,6)) 12 | println(maxWeight) 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch39_back_tracking/EightQueensTest.scala: -------------------------------------------------------------------------------- 1 | package ch39_back_tracking 2 | 3 | import org.scalatest.FlatSpec 4 | 5 | class EightQueensTest extends FlatSpec { 6 | 7 | behavior of "EightQueensTest" 8 | 9 | it should "calc8Queues" in { 10 | val eightQueens = new EightQueens() 11 | eightQueens.calc8Queues(0) 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /scala/src/test/scala/ch39_back_tracking/NQueensTest.scala: -------------------------------------------------------------------------------- 1 | package ch39_back_tracking 2 | 3 | import org.scalatest.FlatSpec 4 | 5 | class NQueensTest extends FlatSpec { 6 | 7 | behavior of "NQueensTest" 8 | 9 | it should "calc8Queues" in { 10 | val eightQueens = new NQueens(8) 11 | eightQueens.calcNQueues(0) 12 | 13 | } 14 | 15 | it should "calc4Queues" in { 16 | val eightQueens = new NQueens(4) 17 | eightQueens.calcNQueues(0) 18 | 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /swift/08_stack/Browser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/12. 3 | // Copyright (c) 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | struct Page { 9 | /// 存储前进 url 10 | private var forwardArray = [String]() 11 | /// 存储后退 url 12 | private var backArray = [String]() 13 | 14 | var currentURL: String? { return forwardArray.last } 15 | 16 | init(url: String) { 17 | forwardArray.append(url) 18 | } 19 | /// 前进 20 | mutating func goForward(url: String) { 21 | forwardArray.append(url) 22 | } 23 | /// 后退 24 | mutating func goBack() { 25 | backArray.append(forwardArray.popLast()!) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /swift/08_stack/BrowserDemo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/12. 3 | // Copyright (c) 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | struct Page { 9 | /// 存储前进 url 10 | private var forwardArray = [String]() 11 | /// 存储后退 url 12 | private var backArray = [String]() 13 | 14 | var currentURL: String { return forwardArray.last! } 15 | 16 | init(url: String) { 17 | forwardArray.append(url) 18 | } 19 | /// 前进 20 | mutating func goForward(url: String) { 21 | forwardArray.append(url) 22 | } 23 | /// 后退 24 | mutating func goBack() { 25 | backArray.append(forwardArray.popLast()!) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /swift/08_stack/Stack.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/12. 3 | // Copyright (c) 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | protocol Stack { 9 | /// 持有的数据类型 10 | associatedtype Element 11 | /// 是否为空 12 | var isEmpty: Bool { get } 13 | /// 队列大小 14 | var size: Int { get } 15 | /// 返回队列头部元素 16 | var peek: Element? { get } 17 | /// 入栈 18 | mutating func push(newElement: Element) -> Bool 19 | /// 出栈 20 | mutating func pop() -> Element? 21 | } 22 | -------------------------------------------------------------------------------- /swift/08_stack/StackBasedOnLinkedList.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/12. 3 | // Copyright (c) 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | struct StackBasedOnLinkedList: Stack { 9 | private var head = Node() // 哨兵结点,不存储内容 10 | 11 | // MARK: Protocol: Stack 12 | 13 | var isEmpty: Bool { return head.next == nil } 14 | 15 | var size: Int { 16 | var count = 0 17 | var cur = head.next 18 | while cur != nil { 19 | count += 1 20 | cur = cur?.next 21 | } 22 | return count 23 | } 24 | 25 | var peek: Element? { return head.next?.value } 26 | 27 | func push(newElement: Element) -> Bool { 28 | let node = Node(value: newElement) 29 | node.next = head.next 30 | head.next = node 31 | return true 32 | } 33 | 34 | func pop() -> Element? { 35 | let node = head.next 36 | head.next = node?.next 37 | return node?.value 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /swift/09_queue/Queue.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/11. 3 | // Copyright (c) 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | protocol Queue { 9 | /// 持有的数据类型 10 | associatedtype Element 11 | /// 是否为空 12 | var isEmpty: Bool { get } 13 | /// 队列大小 14 | var size: Int { get } 15 | /// 返回队列头部元素 16 | var peek: Element? { get } 17 | /// 入队 18 | mutating func enqueue(newElement: Element) -> Bool 19 | /// 出队 20 | mutating func dequeue() -> Element? 21 | } 22 | -------------------------------------------------------------------------------- /swift/12_sorts/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzheng0822/algo/b2c1228ff915287ad7ebeae4355fa26854ea1557/swift/12_sorts/.DS_Store -------------------------------------------------------------------------------- /swift/12_sorts/QuickSort.swift: -------------------------------------------------------------------------------- 1 | // 2 | // QuickSort.swift 3 | // algo 4 | // 5 | // Created by Wenru Dong on 2018/10/17. 6 | // Copyright © 2018年 Wenru Dong. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public func quickSort(_ a: inout T) where T.Element: Comparable { 12 | quickSort(&a, from: a.startIndex, to: a.index(before: a.endIndex)) 13 | } 14 | 15 | fileprivate func quickSort(_ a: inout T, from low: T.Index, to high: T.Index) where T.Element: Comparable { 16 | if low >= high { return } 17 | 18 | let m = partition(&a, from: low, to: high) 19 | quickSort(&a, from: low, to: a.index(before: m)) 20 | quickSort(&a, from: a.index(after: m), to: high) 21 | } 22 | 23 | fileprivate func partition(_ a: inout T, from low: T.Index, to high: T.Index) -> T.Index where T.Element: Comparable { 24 | let pivot = a[low] 25 | var j = low 26 | var i = a.index(after: low) 27 | while i <= high { 28 | if a[i] < pivot { 29 | a.formIndex(after: &j) 30 | a.swapAt(i, j) 31 | } 32 | a.formIndex(after: &i) 33 | } 34 | a.swapAt(low, j) 35 | return j 36 | } 37 | -------------------------------------------------------------------------------- /swift/14_sorts/CountingSort.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CountingSort.swift 3 | // algo 4 | // 5 | // Created by Wenru Dong on 2018/10/18. 6 | // Copyright © 2018年 Wenru Dong. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // 假设数组中储存的都是非负整数 12 | public func countingSort(_ a: inout [Int]) { 13 | if a.count <= 1 { return } 14 | 15 | var counts = Array(repeating: 0, count: a.max()! + 1) 16 | for num in a { 17 | counts[num] += 1 18 | } 19 | for i in 1.. { 2 | insertToHead(value: T): void 3 | 4 | findByValue(value: T): any 5 | 6 | findByIndex(index: number): any 7 | 8 | insertToIndex(value: T, index: number): void 9 | 10 | remove(value: T): boolean 11 | 12 | insertToHead(value: T): void 13 | 14 | insertToTail(value: T): void 15 | 16 | toString(): string 17 | } 18 | 19 | export default List 20 | -------------------------------------------------------------------------------- /typescript/09_queue/CircularQueue.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 基于数组的循环队列 3 | * 为了方便判断队列为空的情况,这里最好引入元素个数 4 | */ 5 | class CircularQueue { 6 | private items: T[] = [] 7 | private readonly n: number = 0 8 | private head: number = 0 9 | private tail: number = 0 10 | // 队列的实际元素大小 11 | size: number = 0 12 | 13 | 14 | constructor(capacity: number) { 15 | this.n = capacity 16 | } 17 | 18 | public enqueue(item: T): boolean { 19 | // 表示队列已经满了 20 | if (this.size === this.n) return false 21 | this.items[this.tail] = item 22 | this.tail = (this.tail + 1) % this.n 23 | this.size++ 24 | return true 25 | } 26 | 27 | public dequeue(): T | null { 28 | if (!this.size) return null 29 | const item = this.items[this.head] 30 | this.head = (this.head + 1) % this.n 31 | this.size-- 32 | return item 33 | } 34 | } 35 | 36 | const circularQueue = new CircularQueue(3) 37 | circularQueue.enqueue(1) 38 | circularQueue.enqueue(2) 39 | circularQueue.enqueue(3) 40 | circularQueue.enqueue(4) 41 | 42 | const value = circularQueue.dequeue() 43 | const value1 = circularQueue.dequeue() 44 | const value2 = circularQueue.dequeue() 45 | const value3 = circularQueue.dequeue() 46 | 47 | // null 48 | console.log(value3) 49 | // 0 50 | console.log(circularQueue.size) 51 | 52 | -------------------------------------------------------------------------------- /typescript/09_queue/README.md: -------------------------------------------------------------------------------- 1 | ### 队列 2 | 3 | 由于js语言天生就可以使用array数组来实现栈和队列等结构: 4 | ```javascript 5 | // 模拟数组队列 6 | const queue = [] 7 | queue.push(1) // 向数组尾部添加数据 8 | queue.shift() //数组头部去除数据,并返回 9 | ``` 10 | 这里我们使用链表来实现队列结构 11 | 12 | 队列分为无限队列和循环队列 13 | -------------------------------------------------------------------------------- /typescript/10_recursive/climbStairs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 递归求解爬楼梯问题 3 | */ 4 | 5 | /** 6 | * 最开始版本的递归算法 7 | * @param n 8 | */ 9 | function fn(n: number): any { 10 | if (n === 1) return 1 11 | if (n === 2) return 2 12 | return fn(n - 1) + fn(n - 2) 13 | } 14 | 15 | const res1 = fn(10) 16 | // 89 17 | console.log(res1) 18 | 19 | /** 20 | * 使用depth结合js的闭包特性实现限制函数调用次数的功能 21 | * @param depth 递归的深度 22 | */ 23 | function fnWithDepth(depth: number) { 24 | return function fn(n: number): any { 25 | depth++ 26 | if (depth > 1000) throw new Error('function stack is too deep!') 27 | if (n === 1) return 1 28 | if (n === 2) return 2 29 | return fn(n - 1) + fn(n - 2) 30 | } 31 | } 32 | 33 | const res2 = fnWithDepth(3)(10) 34 | // 89 35 | console.log(res2) 36 | 37 | /** 38 | * 通过map来存储已经计算过的值,避免递归重复计算 39 | */ 40 | function fnWithMap() { 41 | const map = new Map() 42 | return function fn(n: number): any { 43 | if (n === 1) return 1 44 | if (n === 2) return 2 45 | if (map.has(n)) { 46 | return map.get(n) 47 | } 48 | const ret = fn(n - 1) + fn(n - 2) 49 | map.set(n, ret) 50 | return ret 51 | } 52 | } 53 | 54 | const res3 = fnWithMap()(10) 55 | console.log(res3) 56 | -------------------------------------------------------------------------------- /typescript/14_binarysearch/BinarySearch.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 二分查找适合于连续内存的数组查找 3 | * 并且是已经排好序的数组 4 | * 时间复杂度只有log(n) 5 | */ 6 | class BinarySearch { 7 | static bSearch(array: number[], target: number) { 8 | if (!array || array.length === 0) return -1 9 | const length = array.length 10 | let low = 0 11 | let high = length - 1 12 | while (low <= high) { 13 | // 一定是整数,这边的移位运算优先级低于+,-运算符,需要加括号 14 | const mid = low + ((high - low) >> 1) 15 | if (array[mid] === target) { 16 | return mid 17 | } else if (array[mid] > target) { 18 | high = mid - 1 19 | } else { 20 | low = mid + 1 21 | } 22 | } 23 | return -1 24 | } 25 | } 26 | 27 | const testBinarySearch = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 28 | console.log(BinarySearch.bSearch(testBinarySearch, 10)) 29 | --------------------------------------------------------------------------------