├── dp └── py3 │ ├── __init__.py │ ├── TestRNASecondaryStructure.py │ ├── TestLongestCommonSubsequence.py │ ├── segmented_least_squares.py │ ├── TestSequenceAlignment.py │ ├── subset_sum.py │ ├── longest_common_subsequence.py │ ├── sequence_alignment.py │ ├── TestSubsetSum.py │ ├── TestWeightedIntervalScheduling.py │ └── TestKnapsack.py ├── bst ├── py3 │ └── __init__.py └── cxx │ └── BinarySearchTree.h ├── graph └── py3 │ ├── __init__.py │ ├── is_tree.py │ ├── bipartiteness.py │ ├── TestConnectedComponent.py │ └── TestBipartiteness.py ├── hashset ├── py3 │ ├── __init__.py │ └── TestHashSet.py └── cxx │ ├── HashSet.h │ └── TestHashSet.cxx ├── heap ├── py3 │ ├── __init__.py │ └── TestHeap.py ├── cxx │ ├── TestHeap.cxx │ └── heap.cxx ├── c │ ├── test_heap.c │ └── heap.c └── java │ ├── TestHeap.java │ └── Heap.java ├── math ├── py3 │ ├── __init__.py │ └── TestMymath.py ├── c │ ├── mymath.c │ └── test_math.c ├── java │ ├── MyMath.java │ └── TestMyMath.java └── cxx │ ├── mymath.cxx │ └── test_math.cxx ├── mst └── py3 │ ├── __init__.py │ ├── prim.py │ ├── TestMST.py │ └── kruskal.py ├── shuffle ├── py3 │ ├── __init__.py │ ├── TestFisherYates.py │ └── fisher_yates.py ├── c │ ├── fisher_yates.h │ ├── fisher_yates.c │ └── test_fisher_yates.c ├── cxx │ ├── fisher_yates.h │ ├── test_fisher_yates.cxx │ └── fisher_yates.cxx └── java │ ├── TestFisherYates.java │ └── FisherYates.java ├── sorting ├── py3 │ ├── __init__.py │ ├── selection_sort.py │ ├── bubble_sort.py │ ├── k_way_merge_sort.py │ ├── insertion_sort.py │ ├── TestKWayMergeSort.py │ ├── heap_sort.py │ ├── quick_sort_lomuto.py │ ├── TestSortImpl.py │ └── quick_sort.py ├── c │ ├── swap.h │ ├── swap.c │ ├── makefile │ ├── insertion_sort.c │ ├── selection_sort.c │ ├── bubble_sort.c │ ├── heap_sort.c │ ├── merge_sort.c │ ├── test_sort_algo.c │ └── quick_sort.c ├── java │ ├── SortAlgorithm.java │ ├── InsertionSort.java │ ├── BubbleSort.java │ ├── HeapSort.java │ ├── MergeSort.java │ ├── TestSortImpl.java │ └── QuickSort.java ├── cxx │ ├── selection_sort.cxx │ ├── bubble_sort.cxx │ ├── insertion_sort.cxx │ ├── heap_sort.cxx │ ├── straight_radix_sort.cxx │ ├── merge_sort.cxx │ └── radix_exchange_sort.cxx └── go │ └── quicksort.go ├── stack └── py3 │ ├── __init__.py │ ├── next_greater.py │ └── TestNextGreater.py ├── string ├── py3 │ ├── __init__.py │ ├── naive_matcher.py │ ├── kmp_matcher.py │ └── TestStringMatcher.py ├── c │ ├── kmp_matcher.h │ ├── kmp_matcher.c │ └── test_str_matcher.c ├── KMP.png ├── cxx │ ├── kmp_matcher.h │ ├── test_str_matcher.cxx │ └── kmp_matcher.cxx ├── java │ ├── StringMatcher.java │ ├── NaiveMatcher.java │ ├── KMPMatcher.java │ └── TestStringMatcher.java └── perl │ ├── test_str_matcher.pl │ └── kmp_matcher.pm ├── trie ├── py3 │ └── __init__.py ├── trie.md ├── cxx │ ├── Trie.h │ ├── Trie.cxx │ └── TestTrie.cxx ├── c │ ├── trie.h │ └── test_trie.c ├── go │ └── trie.go └── java │ └── Trie.java ├── disjoint_set ├── py3 │ ├── __init__.py │ └── TestDisjointSet.py ├── cxx │ ├── DisjointSet.h │ ├── TestDisjoinSet.cxx │ └── DisjointSet.cxx ├── c │ ├── disjoint_set.h │ ├── test_disjoint_set.c │ └── disjoint_set.c ├── java │ ├── TestDisjointSet.java │ └── DisjointSet.java ├── go │ └── disjointset.go ├── scala │ └── DisjointSet.scala └── DisjointSet.md ├── linked_list ├── py3 │ ├── __init__.py │ ├── reverse_linked_list.py │ ├── find_middle.py │ ├── LinkedList.py │ ├── cycle_detection.py │ ├── list_merge_sort.py │ └── list_quick_sort.py ├── c │ ├── find_middle.h │ ├── reverse_linked_list.h │ ├── cycle_detection.h │ ├── list_merge_sort.h │ ├── find_middle.c │ ├── reverse_linked_list.c │ ├── linked_list.h │ ├── cycle_detection.c │ ├── linked_list.c │ └── list_merge_sort.c ├── cxx │ ├── find_middle.h │ ├── list_merge_sort.h │ ├── reverse_linked_list.h │ ├── cycle_detection.h │ ├── find_middle.cxx │ ├── reverse_linked_list.cxx │ ├── LinkedList.h │ ├── cycle_detection.cxx │ ├── LinkedList.cxx │ └── list_merge_sort.cxx └── java │ ├── ListSortAlgorithm.java │ ├── LinkedListAlgorithms.java │ ├── CycleDetection.java │ ├── ListNode.java │ └── ListMergeSort.java ├── recursion └── py3 │ ├── __init__.py │ ├── partitions.py │ └── combinations.py ├── sampling ├── py3 │ ├── __init__.py │ ├── weighted_random_sample.py │ ├── TestSampling.py │ └── simple_random_sample.py └── cxx │ ├── simple_random_sample.cxx │ └── test_sampling.cxx ├── segment_tree ├── py3 │ └── __init__.py ├── cxx │ ├── RMQSegmentTree.h │ └── TestSegmentTree.cxx ├── c │ ├── rsq_segment_tree.h │ └── test_segment_tree.c └── java │ └── TestRMQSegmentTree.java ├── selection ├── py3 │ ├── __init__.py │ └── TestSelect.py ├── java │ ├── SelectionAlgorithm.java │ └── QuickSelect.java ├── c │ ├── quick_select_lomuto.c │ ├── test_selection.c │ └── quick_select.c └── go │ └── quickselect.go ├── topo_sort └── py3 │ ├── __init__.py │ └── random_dag.py ├── binary_search ├── py3 │ ├── __init__.py │ ├── TestMybisect.py │ └── mybisect.py ├── perl │ ├── binary_search.pm │ └── test_binary_search.pl ├── c │ └── binary_search.c ├── java │ ├── BinarySearch.java │ └── TestBinarySearch.java └── cxx │ └── binary_search.cxx ├── majority_vote ├── py3 │ ├── __init__.py │ └── TestMajorityVote.py └── cxx │ └── majority_vote.cxx ├── shortest_path ├── py3 │ ├── __init__.py │ ├── bellman_ford.py │ ├── shortest_path_faster.py │ ├── floyd_warshall.py │ ├── bidirectional.py │ ├── johnson.py │ ├── dijkstra.py │ ├── TestSearch.py │ ├── iterative_deepening.py │ └── bfs.py └── cxx │ └── bfs.cxx ├── traverse_tree ├── py3 │ ├── __init__.py │ ├── RecursiveTraversal.py │ └── TreeNode.py ├── java │ ├── TreeNode.java │ ├── TraversalMethods.java │ └── RecursiveTraversal.java ├── c │ ├── TreeNode.h │ ├── makefile │ ├── morris_traversal.c │ ├── test_traversal.c │ └── recursive_traversal.c └── cxx │ ├── TreeNode.h │ └── TraversalMethods.h ├── binary_indexed_tree ├── py3 │ ├── __init__.py │ └── TestBinaryIndexedTree.py ├── BITimg.gif ├── cxx │ ├── BinaryIndexedTree.h │ ├── BinaryIndexedTree.cxx │ └── TestBinaryIndexedTree.cxx ├── c │ ├── binary_indexed_tree.h │ ├── binary_indexed_tree.c │ └── test_binary_indexed_tree.c ├── java │ └── BinaryIndexedTree.java └── Binary Indexed Tree.md ├── dutch_national_flag ├── py3 │ ├── __init__.py │ ├── TestThreeWayPartition.py │ └── three_way_partition.py ├── c │ ├── swap.h │ ├── swap.c │ ├── three_way_partition.h │ ├── three_way_partition.c │ └── test_three_way_partition.c ├── cxx │ ├── three_way_partition.h │ ├── three_way_partition.cxx │ └── test_three_way_partition.cxx └── java │ ├── ThreeWayPartition.java │ └── TestThreeWayPartition.java ├── .gitignore ├── vector ├── myvector.h └── test_myvector.c └── InterviewEssentials.md /dp/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bst/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /graph/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hashset/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /heap/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /math/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mst/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /shuffle/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sorting/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /stack/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /string/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /trie/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /disjoint_set/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /linked_list/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /recursion/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sampling/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /segment_tree/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /selection/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /topo_sort/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /binary_search/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /majority_vote/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /shortest_path/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /traverse_tree/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /binary_indexed_tree/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dutch_national_flag/py3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sorting/c/swap.h: -------------------------------------------------------------------------------- 1 | void swap(int* a, int* b); 2 | -------------------------------------------------------------------------------- /dutch_national_flag/c/swap.h: -------------------------------------------------------------------------------- 1 | void swap(int* a, int* b); 2 | -------------------------------------------------------------------------------- /string/c/kmp_matcher.h: -------------------------------------------------------------------------------- 1 | 2 | int kmp_matcher(const char* text, const char* pattern); 3 | -------------------------------------------------------------------------------- /string/KMP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidxk/Algorithm-Implementations/HEAD/string/KMP.png -------------------------------------------------------------------------------- /string/cxx/kmp_matcher.h: -------------------------------------------------------------------------------- 1 | 2 | int kmp_matcher(const std::string& text, const std::string& pattern); 3 | -------------------------------------------------------------------------------- /linked_list/c/find_middle.h: -------------------------------------------------------------------------------- 1 | #include "linked_list.h" 2 | 3 | ListNode* find_middle(ListNode* head); 4 | -------------------------------------------------------------------------------- /linked_list/cxx/find_middle.h: -------------------------------------------------------------------------------- 1 | #include "LinkedList.h" 2 | 3 | ListNode* find_middle(ListNode* head); 4 | -------------------------------------------------------------------------------- /sorting/c/swap.c: -------------------------------------------------------------------------------- 1 | void swap(int* a, int* b) 2 | { 3 | int tmp = *a; 4 | *a = *b; 5 | *b = tmp; 6 | } 7 | -------------------------------------------------------------------------------- /linked_list/cxx/list_merge_sort.h: -------------------------------------------------------------------------------- 1 | #include "LinkedList.h" 2 | 3 | ListNode* list_merge_sort(ListNode* head); 4 | -------------------------------------------------------------------------------- /dutch_national_flag/c/swap.c: -------------------------------------------------------------------------------- 1 | void swap(int* a, int* b) 2 | { 3 | int tmp = *a; 4 | *a = *b; 5 | *b = tmp; 6 | } 7 | -------------------------------------------------------------------------------- /sorting/java/SortAlgorithm.java: -------------------------------------------------------------------------------- 1 | public interface SortAlgorithm 2 | { 3 | public void sort(int[] array); 4 | } 5 | -------------------------------------------------------------------------------- /linked_list/c/reverse_linked_list.h: -------------------------------------------------------------------------------- 1 | #include "linked_list.h" 2 | 3 | ListNode* reverse_linked_list(ListNode* head); 4 | -------------------------------------------------------------------------------- /linked_list/cxx/reverse_linked_list.h: -------------------------------------------------------------------------------- 1 | #include "LinkedList.h" 2 | 3 | ListNode* reverse_linked_list(ListNode* head); 4 | -------------------------------------------------------------------------------- /shuffle/c/fisher_yates.h: -------------------------------------------------------------------------------- 1 | 2 | void fisher_yates(int* array, int n); 3 | void fisher_yates_front(int* array, int n); 4 | -------------------------------------------------------------------------------- /binary_indexed_tree/BITimg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidxk/Algorithm-Implementations/HEAD/binary_indexed_tree/BITimg.gif -------------------------------------------------------------------------------- /linked_list/java/ListSortAlgorithm.java: -------------------------------------------------------------------------------- 1 | 2 | public interface ListSortAlgorithm 3 | { 4 | public ListNode sort(ListNode head); 5 | } 6 | -------------------------------------------------------------------------------- /string/java/StringMatcher.java: -------------------------------------------------------------------------------- 1 | 2 | public interface StringMatcher 3 | { 4 | public int match(String text, String pattern); 5 | } 6 | -------------------------------------------------------------------------------- /selection/java/SelectionAlgorithm.java: -------------------------------------------------------------------------------- 1 | 2 | public interface SelectionAlgorithm 3 | { 4 | public int select(int[] array, int rank); 5 | } 6 | -------------------------------------------------------------------------------- /math/c/mymath.c: -------------------------------------------------------------------------------- 1 | 2 | int gcd(int large, int small) 3 | { 4 | if(small == 0) 5 | return large; 6 | return gcd(small, large % small); 7 | } 8 | -------------------------------------------------------------------------------- /linked_list/cxx/cycle_detection.h: -------------------------------------------------------------------------------- 1 | #include "LinkedList.h" 2 | 3 | bool cycle_detection(ListNode* head); 4 | ListNode* cycle_finding(ListNode* head); 5 | -------------------------------------------------------------------------------- /shuffle/cxx/fisher_yates.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void fisher_yates(std::vector& array); 4 | void fisher_yates_front(std::vector& array); 5 | -------------------------------------------------------------------------------- /traverse_tree/java/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | TreeNode(int x) { val = x; } 6 | } 7 | -------------------------------------------------------------------------------- /sorting/c/makefile: -------------------------------------------------------------------------------- 1 | a.out: test_sort_algo.c swap.o merge_sort.c quick_sort_hoare.c heap_sort.c bubble_sort.c insertion_sort.c selection_sort.c 2 | gcc swap.o test_sort_algo.c 3 | -------------------------------------------------------------------------------- /linked_list/c/cycle_detection.h: -------------------------------------------------------------------------------- 1 | #ifndef CYCLE_DETECTION_H_ 2 | #define CYCLE_DETECTION_H_ 3 | 4 | int cycle_detection(ListNode* head); 5 | ListNode* cycle_finding(ListNode* head); 6 | #endif -------------------------------------------------------------------------------- /math/java/MyMath.java: -------------------------------------------------------------------------------- 1 | 2 | class MyMath 3 | { 4 | public int gcd(int large, int small) 5 | { 6 | if(small == 0) 7 | return large; 8 | return gcd(small, large % small); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /linked_list/c/list_merge_sort.h: -------------------------------------------------------------------------------- 1 | #include "linked_list.h" 2 | 3 | ListNode* list_merge_sort(ListNode* head); 4 | ListNode* list_m_sort(ListNode* head); 5 | ListNode* list_merge(ListNode* l1, ListNode* l2); 6 | -------------------------------------------------------------------------------- /math/cxx/mymath.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int gcd(int large, int small) 4 | { 5 | while(small) 6 | { 7 | std::swap(large, small); 8 | small %= large; 9 | } 10 | return large; 11 | } 12 | -------------------------------------------------------------------------------- /traverse_tree/c/TreeNode.h: -------------------------------------------------------------------------------- 1 | #ifndef _TREE_NODE_H_ 2 | #define _TREE_NODE_H_ 3 | 4 | struct TreeNode { 5 | int val; 6 | struct TreeNode *left; 7 | struct TreeNode *right; 8 | }; 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /dutch_national_flag/c/three_way_partition.h: -------------------------------------------------------------------------------- 1 | 2 | int default_is_head(int elem); 3 | int default_is_tail(int elem); 4 | void three_way_partition(int* array, int n, int (*is_head)(int), 5 | int (*is_tail)(int)); 6 | -------------------------------------------------------------------------------- /math/c/test_math.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "mymath.c" 3 | 4 | void test_gcd() 5 | { 6 | assert(gcd(40, 16) == 8); 7 | assert(gcd(100, 16) == 4); 8 | } 9 | 10 | int main() 11 | { 12 | test_gcd(); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /math/cxx/test_math.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include "mymath.cxx" 3 | 4 | void test_gcd() 5 | { 6 | assert(gcd(16, 40) == 8); 7 | assert(gcd(100, 40) == 20); 8 | } 9 | 10 | int main() 11 | { 12 | test_gcd(); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /dutch_national_flag/cxx/three_way_partition.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | bool default_is_head(int elem); 4 | bool default_is_tail(int elem); 5 | void three_way_partition(std::vector& array, 6 | bool (*is_head)(int) = default_is_head, 7 | bool (*is_tail)(int) = default_is_tail); 8 | -------------------------------------------------------------------------------- /linked_list/c/find_middle.c: -------------------------------------------------------------------------------- 1 | #include "linked_list.h" 2 | 3 | ListNode* find_middle(ListNode* head) 4 | { 5 | ListNode *slow = head, *fast = head; 6 | while(fast && fast->next) 7 | { 8 | slow = slow->next; 9 | fast = fast->next->next; 10 | } 11 | return slow; 12 | } 13 | -------------------------------------------------------------------------------- /linked_list/cxx/find_middle.cxx: -------------------------------------------------------------------------------- 1 | #include "LinkedList.h" 2 | 3 | ListNode* find_middle(ListNode* head) 4 | { 5 | ListNode *slow = head, *fast = head; 6 | while(fast and fast->next) 7 | { 8 | slow = slow->next; 9 | fast = fast->next->next; 10 | } 11 | return slow; 12 | } 13 | -------------------------------------------------------------------------------- /traverse_tree/cxx/TreeNode.h: -------------------------------------------------------------------------------- 1 | #ifndef __TREE_NODE__ 2 | #define __TREE_NODE__ 3 | 4 | #include 5 | 6 | struct TreeNode 7 | { 8 | int val; 9 | TreeNode *left; 10 | TreeNode *right; 11 | TreeNode(int x) : val(x), left(NULL), right(NULL) {} 12 | }; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /binary_indexed_tree/cxx/BinaryIndexedTree.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class BinaryIndexedTree 4 | { 5 | public: 6 | BinaryIndexedTree(std::vector array); 7 | int getSum(int i); 8 | void update(int i, int delta); 9 | int getRange(int i, int j); 10 | private: 11 | std::vector tree; 12 | }; 13 | -------------------------------------------------------------------------------- /linked_list/c/reverse_linked_list.c: -------------------------------------------------------------------------------- 1 | #include "linked_list.h" 2 | 3 | ListNode* reverse_linked_list(ListNode* head) 4 | { 5 | ListNode *prev = 0, *curr = head, *next = 0; 6 | while(curr) 7 | { 8 | next = curr->next; 9 | curr->next = prev; 10 | prev = curr; 11 | curr = next; 12 | } 13 | return prev; 14 | } 15 | -------------------------------------------------------------------------------- /traverse_tree/java/TraversalMethods.java: -------------------------------------------------------------------------------- 1 | import java.lang.Integer; 2 | import java.util.List; 3 | 4 | public interface TraversalMethods 5 | { 6 | public List preorderTraversal(TreeNode root); 7 | public List inorderTraversal(TreeNode root); 8 | public List postorderTraversal(TreeNode root); 9 | } 10 | -------------------------------------------------------------------------------- /string/py3/naive_matcher.py: -------------------------------------------------------------------------------- 1 | # Time: O(nk) 2 | # Space: O(1) 3 | 4 | def naive_matcher(pattern, text): 5 | for i in range(len(text) - len(pattern) + 1): 6 | for j in range(len(pattern)): 7 | if text[i + j] != pattern[j]: 8 | break 9 | else: 10 | return i 11 | return -1 12 | -------------------------------------------------------------------------------- /linked_list/cxx/reverse_linked_list.cxx: -------------------------------------------------------------------------------- 1 | #include "LinkedList.h" 2 | 3 | ListNode* reverse_linked_list(ListNode* head) 4 | { 5 | ListNode *prev = NULL, *curr = head, *next = NULL; 6 | while(curr != NULL) 7 | { 8 | next = curr->next; 9 | curr->next = prev; 10 | prev = curr; 11 | curr = next; 12 | } 13 | return prev; 14 | } 15 | -------------------------------------------------------------------------------- /sorting/py3/selection_sort.py: -------------------------------------------------------------------------------- 1 | # Time: O(n^2) 2 | # Space: O(1) 3 | 4 | def selection_sort(array): 5 | for i in range(len(array)): 6 | minIdx = i 7 | for j in range(i + 1, len(array)): 8 | if array[j] < array[minIdx]: 9 | minIdx = j 10 | array[i], array[minIdx] = array[minIdx], array[i] 11 | -------------------------------------------------------------------------------- /traverse_tree/c/makefile: -------------------------------------------------------------------------------- 1 | a.out: TreeNode.h ../../vector/myvector.* stack_traversal.c recursive_traversal.c test_traversal.c 2 | gcc test_traversal.c ../../vector/myvector.o 3 | ../../vector/myvector.o: ../../vector/myvector.h ../../vector/myvector.c 4 | pushd ../../vector; gcc -c myvector.c; popd 5 | 6 | .PHONY: clean 7 | clean: 8 | rm -f *.o a.out 9 | -------------------------------------------------------------------------------- /trie/trie.md: -------------------------------------------------------------------------------- 1 | ## Compare to Hash Set 2 | 3 | | Data Structure | find | startsWith | Space complexity | 4 | |----------------|------|------------|------------------| 5 | Hash Set | \\(O(k)\\) key evaluation | Don't support | \\(O(nk)\\) 6 | Trie | \\(O(k)\\) | \\(O(k)\\) | worst-case \\(O(nk)\\) 7 | 8 | * \\(n\\) number of words 9 | * \\(k\\) average length of words 10 | -------------------------------------------------------------------------------- /disjoint_set/cxx/DisjointSet.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class DisjointSet 4 | { 5 | public: 6 | DisjointSet() { } 7 | void makeSet(int elem); 8 | int findSet(int elem); 9 | void unionSet(int elem1, int elem2); 10 | protected: 11 | void linkSet(int elem1, int elem2); 12 | std::unordered_map height; 13 | std::unordered_map parent; 14 | }; 15 | -------------------------------------------------------------------------------- /linked_list/c/linked_list.h: -------------------------------------------------------------------------------- 1 | #ifndef _LINKED_LIST_H_ 2 | #define _LINKED_LIST_H_ 3 | 4 | typedef struct list_node { 5 | int val; 6 | struct list_node *next; 7 | } ListNode; 8 | 9 | ListNode* get_list_node(int value); 10 | ListNode* get_linked_list(int* array, int n); 11 | int* get_array(ListNode* head); 12 | void destroy_linked_list(ListNode* head); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /sorting/c/insertion_sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void insertion_sort(int *array, const int n) 5 | { 6 | int i, j; 7 | int x; 8 | for(i = 1; i < n; i++) 9 | { 10 | x = array[i]; 11 | for(j = i - 1; j >= 0; j--) 12 | if(array[j] > x) 13 | array[j + 1] = array[j]; 14 | else 15 | break; 16 | array[j + 1] = x; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /sorting/cxx/selection_sort.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void selection_sort(std::vector& array) 5 | { 6 | int minIdx; 7 | for(int i = 0; i < array.size(); i++) 8 | { 9 | minIdx = i; 10 | for(int j = i + 1; j < array.size(); j++) 11 | if(array[j] < array[minIdx]) 12 | minIdx = j; 13 | std::swap(array[i], array[minIdx]); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /sorting/py3/bubble_sort.py: -------------------------------------------------------------------------------- 1 | # Time: O(n^2) 2 | # Space: O(1) 3 | 4 | def bubble_sort(array): 5 | while True: 6 | swapped = False 7 | for i in range(len(array) - 1): 8 | if array[i] > array[i + 1]: 9 | array[i], array[i + 1] = array[i + 1], array[i] 10 | swapped = True 11 | if not swapped: 12 | break 13 | -------------------------------------------------------------------------------- /sorting/c/selection_sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void selection_sort(int* a, const int n) 5 | { 6 | int i, j, minIdx; 7 | int tmp; 8 | for(i = 0; i < n; i++) 9 | { 10 | minIdx = i; 11 | for(j = i + 1; j < n; j ++) 12 | if(a[j] < a[minIdx]) 13 | minIdx = j; 14 | 15 | tmp = a[i]; 16 | a[i] = a[minIdx]; 17 | a[minIdx] = tmp; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /sorting/cxx/bubble_sort.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void bubble_sort(std::vector& array) 5 | { 6 | bool swapped = false; 7 | do 8 | { 9 | swapped = false; 10 | for(int i = 1; i < array.size(); i++) 11 | if(array[i - 1] > array[i]) 12 | { 13 | std::swap(array[i - 1], array[i]); 14 | swapped = true; 15 | } 16 | } while(swapped); 17 | } 18 | -------------------------------------------------------------------------------- /linked_list/cxx/LinkedList.h: -------------------------------------------------------------------------------- 1 | #ifndef __LINKED_LIST__ 2 | #define __LINKED_LIST__ 3 | 4 | #include 5 | 6 | struct ListNode 7 | { 8 | int val; 9 | ListNode* next; 10 | ListNode(int x) : val(x), next(NULL) {} 11 | }; 12 | 13 | ListNode* getLinkedList(std::vector array); 14 | std::vector getArray(ListNode* head); 15 | void destroyLinkedList(ListNode* head); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /sorting/java/InsertionSort.java: -------------------------------------------------------------------------------- 1 | 2 | public class InsertionSort implements SortAlgorithm 3 | { 4 | public void sort(int[] array) 5 | { 6 | int j; 7 | for(int i = 1; i < array.length; i++) 8 | { 9 | int x = array[i]; 10 | for(j = i - 1; j >= 0; j--) 11 | if(array[j] > x) 12 | array[j + 1] = array[j]; 13 | else 14 | break; 15 | array[j + 1] = x; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /linked_list/py3/reverse_linked_list.py: -------------------------------------------------------------------------------- 1 | # O -> O -> O -> $ 2 | # prev curr nxt 3 | # O -> $ 4 | # prev curr 5 | # Time: O(n) 6 | # Space: O(1) 7 | 8 | def reverse_linked_list(head): 9 | prev = None 10 | curr = head 11 | while curr: 12 | nxt = curr.next 13 | curr.next = prev 14 | prev = curr 15 | curr = nxt 16 | return prev 17 | -------------------------------------------------------------------------------- /sorting/cxx/insertion_sort.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void insertion_sort(std::vector& array) 6 | { 7 | int j; 8 | for(int i = 0; i < array.size(); i++) 9 | { 10 | int x = array[i]; 11 | for(j = i - 1; j >= 0; j--) 12 | if(array[j] > x) 13 | array[j + 1] = array[j]; 14 | else 15 | break; 16 | array[j + 1] = x; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /sorting/c/bubble_sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void bubble_sort(int* array, const int n) 5 | { 6 | int i, swapped; 7 | do 8 | { 9 | swapped = 0; 10 | for(i = 0; i < n - 1; i++) 11 | if(array[i] > array[i + 1]) 12 | { 13 | int tmp = array[i]; 14 | array[i] = array[i + 1]; 15 | array[i + 1] = tmp; 16 | 17 | swapped = 1; 18 | } 19 | } while( swapped ); 20 | } 21 | -------------------------------------------------------------------------------- /traverse_tree/cxx/TraversalMethods.h: -------------------------------------------------------------------------------- 1 | #ifndef __TRAVERSAL_METHODS__ 2 | #define __TRAVERSAL_METHODS__ 3 | 4 | #include "TreeNode.h" 5 | #include 6 | 7 | class TraversalMethods 8 | { 9 | public: 10 | virtual std::vector preorderTraversal(TreeNode* root) = 0; 11 | virtual std::vector inorderTraversal(TreeNode* root) = 0; 12 | virtual std::vector postorderTraversal(TreeNode* root) = 0; 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /string/java/NaiveMatcher.java: -------------------------------------------------------------------------------- 1 | 2 | public class NaiveMatcher implements StringMatcher 3 | { 4 | public int match(String text, String pattern) 5 | { 6 | int j; 7 | for(int i = 0; i < text.length() - pattern.length(); i++) 8 | { 9 | for(j = 0; j < pattern.length(); j++) 10 | if(text.charAt(i + j) != pattern.charAt(j)) 11 | break; 12 | if(j == pattern.length()) 13 | return i; 14 | } 15 | return -1; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /sorting/java/BubbleSort.java: -------------------------------------------------------------------------------- 1 | 2 | public class BubbleSort implements SortAlgorithm 3 | { 4 | public void sort(int[] array) 5 | { 6 | boolean swapped = false; 7 | do 8 | { 9 | swapped = false; 10 | for(int i = 1; i < array.length; i++) 11 | if(array[i - 1] > array[i]) 12 | { 13 | int tmp = array[i - 1]; 14 | array[i - 1] = array[i]; 15 | array[i] = tmp; 16 | swapped = true; 17 | } 18 | } while(swapped); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /graph/py3/is_tree.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | def is_tree(n, edges): 3 | indegree = Counter() 4 | for u, v in edges: 5 | indegree[v] += 1 6 | hasRoot = False 7 | for node in range(n): 8 | if indegree[node] > 1: 9 | return False 10 | elif indegree[node] == 0: 11 | if not hasRoot: 12 | hasRoot = True 13 | else: 14 | return False 15 | return hasRoot 16 | -------------------------------------------------------------------------------- /shuffle/py3/TestFisherYates.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from fisher_yates import fisher_yates 3 | from fisher_yates import fisher_yates_front 4 | 5 | class TestFisherYates(unittest.TestCase): 6 | def testFisherYates(self): 7 | array = list(range(100)) 8 | fisher_yates(array) 9 | 10 | def testFisherYatesFront(self): 11 | array = list(range(100)) 12 | fisher_yates_front(array) 13 | 14 | if __name__ == "__main__": 15 | unittest.main() 16 | -------------------------------------------------------------------------------- /disjoint_set/cxx/TestDisjoinSet.cxx: -------------------------------------------------------------------------------- 1 | #include "DisjointSet.h" 2 | 3 | #include 4 | 5 | void testDisjointSet() 6 | { 7 | DisjointSet ds; 8 | for(int i = 0; i < 100; i++) 9 | ds.makeSet(i); 10 | for(int i = 0; i < 100; i++) 11 | ds.unionSet(i, i % 5); 12 | for(int i = 0; i < 100; i++) 13 | for(int j = i; j < 100; j++) 14 | assert((ds.findSet(i) == ds.findSet(j)) == ((i % 5) == (j % 5))); 15 | } 16 | 17 | int main() 18 | { 19 | testDisjointSet(); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /sorting/py3/k_way_merge_sort.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | 3 | def k_way_merge_sort(arrays): 4 | arrays = [array for array in arrays if array] 5 | heap = [(array[0], k, 0) for k, array in enumerate(arrays)] 6 | heapq.heapify(heap) 7 | result = [] 8 | while heap: 9 | num, k, idx = heapq.heappop(heap) 10 | result.append(num) 11 | idx += 1 12 | if idx < len(arrays[k]): 13 | heapq.heappush(heap, (arrays[k][idx], k, idx)) 14 | return result 15 | -------------------------------------------------------------------------------- /disjoint_set/c/disjoint_set.h: -------------------------------------------------------------------------------- 1 | typedef struct disjoint_set 2 | { 3 | int* height; 4 | int* parent; 5 | 6 | int (*findSet)(struct disjoint_set*, int); 7 | void (*unionSet)(struct disjoint_set*, int, int); 8 | void (*destroy)(struct disjoint_set*); 9 | } DisjointSet; 10 | 11 | void disjoint_set_init(DisjointSet* ds, int n); 12 | int disjoint_set_find(DisjointSet* ds, int elem); 13 | void disjoint_set_union(DisjointSet* ds, int elem1, int elem2); 14 | void disjoint_set_destroy(DisjointSet* ds); 15 | -------------------------------------------------------------------------------- /disjoint_set/c/test_disjoint_set.c: -------------------------------------------------------------------------------- 1 | #include "disjoint_set.h" 2 | 3 | #include 4 | 5 | void testDisjointSet() 6 | { 7 | DisjointSet ds; 8 | disjoint_set_init(&ds, 100); 9 | int i; 10 | for(int i = 0; i < 100; i++) 11 | ds.unionSet(&ds, i, i % 5); 12 | for(int i = 0; i < 100; i++) 13 | for(int j = i; j < 100; j++) 14 | assert((ds.findSet(&ds, i) == ds.findSet(&ds, j)) == ((i % 5) == (j % 5))); 15 | ds.destroy(&ds); 16 | } 17 | 18 | int main() 19 | { 20 | testDisjointSet(); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /linked_list/py3/find_middle.py: -------------------------------------------------------------------------------- 1 | # For even length 2 | # O O $ 3 | #sf 4 | # ^ s f 5 | # 6 | # For odd length 7 | # O O O $ 8 | #sf 9 | # ^ s f 10 | # ^ s f 11 | # Time: O(n) 12 | # Space: O(1) 13 | 14 | # For even length 15 | # O O $ 16 | # s f 17 | # 18 | # For odd length 19 | # O O O $ 20 | # s f 21 | # s f 22 | # Time: O(n) 23 | # Space: O(1) 24 | 25 | def find_middle(head): 26 | fast = slow = head 27 | while fast and fast.next: 28 | slow = slow.next 29 | fast = fast.next.next 30 | return slow 31 | -------------------------------------------------------------------------------- /segment_tree/cxx/RMQSegmentTree.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class RMQSegmentTree 4 | { 5 | public: 6 | RMQSegmentTree(const std::vector& array); 7 | void build(int index, const std::vector& array, int left, int right); 8 | int query(int qLeft, int qRight); 9 | void update(int index, int delta); 10 | protected: 11 | int queryUtil(int index, int qLeft, int qRight, int left, int right); 12 | void updateUtil(int index, int delta, int i, int left, int right); 13 | private: 14 | std::vector tree; 15 | int length; 16 | }; 17 | -------------------------------------------------------------------------------- /shuffle/cxx/test_fisher_yates.cxx: -------------------------------------------------------------------------------- 1 | #include "fisher_yates.h" 2 | 3 | #include 4 | 5 | void test_fisher_yates() 6 | { 7 | std::vector array(100); 8 | for(int i = 0; i < 100; i++) 9 | array[i] = i; 10 | fisher_yates(array); 11 | } 12 | 13 | void test_fisher_yates_front() 14 | { 15 | std::vector array(100); 16 | for(int i = 0; i < 100; i++) 17 | array[i] = i; 18 | fisher_yates_front(array); 19 | } 20 | 21 | int main() 22 | { 23 | test_fisher_yates(); 24 | test_fisher_yates_front(); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /shuffle/c/fisher_yates.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void swap(int* left, int* right) 4 | { 5 | int tmp = *left; 6 | *left = *right; 7 | *right = tmp; 8 | } 9 | 10 | void fisher_yates(int* array, int n) 11 | { 12 | int i, j; 13 | for(i = n - 1; i > 1; i--) 14 | { 15 | j = rand() % (i + 1); 16 | swap(&array[i], &array[j]); 17 | } 18 | } 19 | 20 | void fisher_yates_front(int* array, int n) 21 | { 22 | int i, j; 23 | for(i = 0; i < n; i++) 24 | { 25 | j = i + rand() % (n - i); 26 | swap(&array[i], &array[j]); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /binary_search/perl/binary_search.pm: -------------------------------------------------------------------------------- 1 | package binary_search; 2 | use Exporter; 3 | @ISA = ('Exporter'); 4 | @EXPORT = ('binary_search'); 5 | 6 | sub binary_search { 7 | my ($array, $target) = @_; 8 | my ($left, $right) = (0, $#{$array}); 9 | while($left <= $right) { 10 | my $center = int(($left + $right) / 2); 11 | if($$array[$center] == $target) { 12 | return $center; 13 | } elsif($$array[$center] < $target) { 14 | $left = $center + 1; 15 | } else { 16 | $right = $center - 1; 17 | } 18 | } 19 | return -1; 20 | } 21 | 22 | 1; 23 | -------------------------------------------------------------------------------- /disjoint_set/java/TestDisjointSet.java: -------------------------------------------------------------------------------- 1 | 2 | public class TestDisjointSet 3 | { 4 | public static void testUnionFind() 5 | { 6 | DisjointSet ds = new DisjointSet(); 7 | for(int i = 0; i < 100; i++) 8 | { 9 | ds.makeSet(i); 10 | ds.union(i, i % 5); 11 | } 12 | for(int i = 0; i < 100; i++) 13 | for(int j = 0; j < 100; j++) 14 | if((i % 5 == j % 5) != (ds.findSet(i) == ds.findSet(j))) 15 | System.out.println("Error in Union-Find"); 16 | } 17 | public static void main(String[] args) 18 | { 19 | testUnionFind(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /binary_search/perl/test_binary_search.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use binary_search; 6 | 7 | sub test_binary_search { 8 | my $size = 10_000; 9 | my @array = (0 .. $size); 10 | for(0 .. 100) { 11 | my $pick = int(rand($size)); 12 | my $retval = binary_search(\@array, $pick); 13 | my ($expect) = grep{ $array[$_] == $pick } @array; 14 | return 0 if $retval != $expect; 15 | } 16 | return 1; 17 | } 18 | 19 | sub main { 20 | if(not test_binary_search()){ 21 | print "WA: binary_search" 22 | } 23 | } 24 | 25 | main() 26 | -------------------------------------------------------------------------------- /segment_tree/c/rsq_segment_tree.h: -------------------------------------------------------------------------------- 1 | typedef struct rsq_segment_tree 2 | { 3 | int* tree; 4 | int length; 5 | int (*query)(struct rsq_segment_tree*, int, int); 6 | void (*update)(struct rsq_segment_tree*, int, int); 7 | void (*destroy)(struct rsq_segment_tree*); 8 | } RSQSegmentTree; 9 | 10 | RSQSegmentTree* rsq_segment_tree_init(int* array, int n); 11 | int rsq_segment_tree_query(RSQSegmentTree* st, int q_left, int q_right); 12 | void rsq_segment_tree_update(RSQSegmentTree* st, int index, int delta); 13 | void rsq_segment_tree_destroy(RSQSegmentTree* st); 14 | -------------------------------------------------------------------------------- /trie/cxx/Trie.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class TrieNode 5 | { 6 | public: 7 | TrieNode(char x): character(x) { } 8 | std::unordered_map children; 9 | char character; 10 | bool isLeaf; 11 | }; 12 | 13 | class Trie 14 | { 15 | public: 16 | Trie() { root = new TrieNode('!'); } 17 | void insert(const std::string& word); 18 | bool search(const std::string& word); 19 | bool startWith(const std::string& prefix); 20 | ~Trie(); 21 | private: 22 | TrieNode* root; 23 | void deleteSubtree(TrieNode* root); 24 | }; 25 | -------------------------------------------------------------------------------- /shuffle/c/test_fisher_yates.c: -------------------------------------------------------------------------------- 1 | #include "fisher_yates.h" 2 | 3 | void test_fisher_yates() 4 | { 5 | const int size = size; 6 | int array[size]; 7 | int i; 8 | for(i = 0; i < size; i++) 9 | array[i] = i; 10 | fisher_yates(array, size); 11 | } 12 | 13 | void test_fisher_yates_front() 14 | { 15 | const int size = size; 16 | int array[size]; 17 | int i; 18 | for(i = 0; i < size; i++) 19 | array[i] = i; 20 | fisher_yates_front(array, size); 21 | } 22 | 23 | int main() 24 | { 25 | test_fisher_yates(); 26 | test_fisher_yates_front(); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /linked_list/py3/LinkedList.py: -------------------------------------------------------------------------------- 1 | class ListNode(object): 2 | def __init__(self, x): 3 | self.val = x 4 | self.next = None 5 | 6 | def getLinkedList(array): 7 | if not array: 8 | return None 9 | curr = head = ListNode(array[0]) 10 | for i in range(1, len(array)): 11 | curr.next = ListNode(array[i]) 12 | curr = curr.next 13 | return head 14 | 15 | def getArray(head): 16 | curr = head 17 | array = [] 18 | while curr: 19 | array.append(curr.val) 20 | curr = curr.next 21 | return array 22 | -------------------------------------------------------------------------------- /hashset/cxx/HashSet.h: -------------------------------------------------------------------------------- 1 | #ifndef __HASH_TABLE__ 2 | #define __HASH_TABLE__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class HashSet 9 | { 10 | public: 11 | explicit HashSet(); 12 | bool contains(const int& x) const; 13 | void clear(); 14 | bool insert(const int& x); 15 | bool erase(const int& x); 16 | int size() { return _size; }; 17 | private: 18 | static int primes[32]; 19 | std::vector > table; 20 | int _size; 21 | int primeIdx; 22 | void rehash(); 23 | int myhash(const int& x) const; 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /shuffle/java/TestFisherYates.java: -------------------------------------------------------------------------------- 1 | 2 | public class TestFisherYates 3 | { 4 | public static void main(String[] args) 5 | { 6 | int[] array = new int[100]; 7 | for(int i = 0; i < 100; i++) 8 | array[i] = i; 9 | FisherYates.shuffle(array); 10 | for(int i = 0; i < 100; i++) 11 | System.out.print(array[i] + " "); 12 | System.out.println(); 13 | 14 | for(int i = 0; i < 100; i++) 15 | array[i] = i; 16 | FisherYates.shuffle_front(array); 17 | for(int i = 0; i < 100; i++) 18 | System.out.print(array[i] + " "); 19 | System.out.println(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /shuffle/cxx/fisher_yates.cxx: -------------------------------------------------------------------------------- 1 | #include "fisher_yates.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | void fisher_yates(std::vector& array) 9 | { 10 | int j; 11 | for(int i = array.size() - 1; i >= 0; i--) 12 | { 13 | j = rand() % (i + 1); 14 | std::swap(array[i], array[j]); 15 | } 16 | } 17 | 18 | void fisher_yates_front(std::vector& array) 19 | { 20 | int j; 21 | for(int i = 0; i < array.size(); i++) 22 | { 23 | j = i + rand() % (array.size() - i); 24 | std::swap(array[i], array[j]); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /recursion/py3/partitions.py: -------------------------------------------------------------------------------- 1 | from copy import deepcopy 2 | def partitions(nums): 3 | """ Semba, 1984 """ 4 | if len(nums) == 0: 5 | return [] 6 | front = [[[nums[0]]]] 7 | for num in nums[1:]: 8 | nextLayer = [] 9 | for partition in front: 10 | children = [deepcopy(partition) for _ in range(len(partition) + 1)] 11 | children[-1].append([]) 12 | for i in range(len(partition) + 1): 13 | children[i][i].append(num) 14 | nextLayer += children 15 | front = nextLayer 16 | return front 17 | -------------------------------------------------------------------------------- /sorting/py3/insertion_sort.py: -------------------------------------------------------------------------------- 1 | # 2 3 5 7->9 9 2 | # x = 4 j j+1 i 3 | # For everyone before me, if you are taller, walk one step back 4 | # that is your index goes up by one 5 | # For the first guy no taller than me, I will stand right behind you 6 | # Time: O(n^2) 7 | # Space: O(1) 8 | 9 | def insertion_sort(array): 10 | for i in range(len(array)): 11 | x = array[i] 12 | j = i - 1 13 | while j >= 0 and array[j] > x: 14 | array[j + 1] = array[j] 15 | j -= 1 16 | array[j + 1] = x 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.o 6 | 7 | # Compiled Dynamic libraries 8 | *.so 9 | *.dylib 10 | *.dll 11 | 12 | # Compiled Static libraries 13 | *.a 14 | *.lib 15 | 16 | # Executables 17 | *.exe 18 | *.out 19 | *.app 20 | .gdb_history 21 | *.dSYM 22 | 23 | 24 | # Byte-compiled / optimized / DLL files 25 | __pycache__/ 26 | *.py[cod] 27 | *$py.class 28 | 29 | 30 | # Distribution / packaging 31 | *.egg-info/ 32 | 33 | 34 | # C extensions 35 | *.so 36 | 37 | 38 | # Compiled class file 39 | *.class 40 | 41 | 42 | # Mac 43 | .DS_Store 44 | .*.*swp 45 | -------------------------------------------------------------------------------- /math/java/TestMyMath.java: -------------------------------------------------------------------------------- 1 | import java.math.*; 2 | import java.util.Random; 3 | 4 | class TestMyMath 5 | { 6 | public static MyMath mymath = new MyMath(); 7 | public static Random myrand = new Random(); 8 | public static void testGCD() 9 | { 10 | for(int i = 0; i < 100; i++) 11 | { 12 | BigInteger a = new BigInteger(20, myrand); 13 | BigInteger b = new BigInteger(20, myrand); 14 | if(mymath.gcd(a.intValue(), b.intValue()) != a.gcd(b).intValue()) 15 | System.out.println("GCD Error!"); 16 | } 17 | } 18 | public static void main(String[] argv) 19 | { 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /linked_list/java/LinkedListAlgorithms.java: -------------------------------------------------------------------------------- 1 | 2 | public class LinkedListAlgorithms 3 | { 4 | public static ListNode findMiddle(ListNode head) 5 | { 6 | ListNode slow = head, fast = head; 7 | while(fast != null && fast.next != null) 8 | { 9 | slow = slow.next; 10 | fast = fast.next.next; 11 | } 12 | return slow; 13 | } 14 | public static ListNode reverse(ListNode head) 15 | { 16 | ListNode prev = null, curr = head, next; 17 | while(curr != null) 18 | { 19 | next = curr.next; 20 | curr.next = prev; 21 | prev = curr; 22 | curr = next; 23 | } 24 | return prev; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /dutch_national_flag/java/ThreeWayPartition.java: -------------------------------------------------------------------------------- 1 | // Remember the swap(a, b) in java is a = b ^ a ^ (b = a) 2 | 3 | public class ThreeWayPartition 4 | { 5 | static public void partition(int[] array) 6 | { 7 | int head = 0, tail = array.length - 1; 8 | int i = 0; 9 | while(i <= tail) 10 | { 11 | if(array[i] == 0) 12 | { 13 | array[i] = array[head] ^ array[i] ^ (array[head] = array[i]); 14 | i++; head++; 15 | } 16 | else if(array[i] == 2) 17 | { 18 | array[i] = array[tail] ^ array[i] ^ (array[tail] = array[i]); 19 | tail--; 20 | } 21 | else 22 | i++; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /dutch_national_flag/c/three_way_partition.c: -------------------------------------------------------------------------------- 1 | #include "three_way_partition.h" 2 | #include "swap.h" 3 | 4 | int default_is_head(int elem) 5 | { 6 | return elem == 0; 7 | } 8 | 9 | int default_is_tail(int elem) 10 | { 11 | return elem == 2; 12 | } 13 | 14 | void three_way_partition(int* array, int n, int (*is_head)(int), 15 | int (*is_tail)(int)) 16 | { 17 | int head = 0, tail = n - 1; 18 | int i = 0; 19 | while(i <= tail) 20 | { 21 | if(is_head(array[i])) 22 | swap(&array[i++], &array[head++]); 23 | else if(is_tail(array[i])) 24 | swap(&array[i], &array[tail--]); 25 | else 26 | i++; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /dp/py3/TestRNASecondaryStructure.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import random 3 | from rna_secondary_structure import * 4 | 5 | class TestRNASecondaryStructure(unittest.TestCase): 6 | def __gen_case__(self): 7 | bases = "AUCG" 8 | return str().join(random.choice(bases) for i in range(50)) 9 | 10 | def testTableFilling(self): 11 | for i in range(100): 12 | case = self.__gen_case__() 13 | max1 = rna_secondary_structure(case) 14 | max2 = rna_secondary_structure_memo(case) 15 | self.assertEqual(max1, max2) 16 | 17 | if __name__ == "__main__": 18 | unittest.main() 19 | -------------------------------------------------------------------------------- /mst/py3/prim.py: -------------------------------------------------------------------------------- 1 | # Time: O(E log(V)) 2 | 3 | from collections import defaultdict 4 | import heapq 5 | def prim(adjList): 6 | source = 0 7 | dist = {source: 0} 8 | front = [(0, source, source)] 9 | parent = {} 10 | while len(parent) < len(adjList): 11 | _, daddy, node = heapq.heappop(front) 12 | if node in parent: 13 | continue 14 | parent[node] = daddy 15 | for child, weight in adjList[node]: 16 | if child not in dist or weight < dist[child]: 17 | dist[child] = weight 18 | heapq.heappush(front, (dist[child], node, child)) 19 | return parent 20 | -------------------------------------------------------------------------------- /binary_indexed_tree/c/binary_indexed_tree.h: -------------------------------------------------------------------------------- 1 | 2 | typedef struct binary_indexed_tree 3 | { 4 | int* tree; 5 | int treesz; 6 | int (*get_sum)(struct binary_indexed_tree*, int); 7 | void (*update)(struct binary_indexed_tree*, int, int); 8 | int (*get_range)(struct binary_indexed_tree*, int, int); 9 | void (*destroy)(struct binary_indexed_tree*); 10 | } BinaryIndexedTree; 11 | 12 | BinaryIndexedTree* bit_init(int* array, int n); 13 | int bit_get_sum(BinaryIndexedTree* bit, int i); 14 | void bit_update(BinaryIndexedTree* bit, int i, int delta); 15 | int bit_get_range(BinaryIndexedTree* bit, int i, int j); 16 | void bit_destroy(BinaryIndexedTree* bit); 17 | -------------------------------------------------------------------------------- /bst/cxx/BinarySearchTree.h: -------------------------------------------------------------------------------- 1 | struct TreeNode 2 | { 3 | int val; 4 | TreeNode *left; 5 | TreeNode *right; 6 | TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 7 | }; 8 | 9 | // All methods that returns an iterator in std returns the corresponding value 10 | class BinarySearchTree 11 | { 12 | public: 13 | BinarySearchTree(): root(nullptr) { } 14 | ~BinarySearchTree(); 15 | int front(); 16 | int back(); 17 | bool empty() { return root == nullptr; } 18 | bool insert(int value); 19 | bool erase(int value); 20 | bool find(int value); 21 | int lower_bound(int value); 22 | int upper_bound(int value); 23 | protected: 24 | TreeNode* root; 25 | }; 26 | -------------------------------------------------------------------------------- /shortest_path/cxx/bfs.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // UNTESTED 6 | 7 | // Nodes are 0 .. n-1 by default 8 | void bfs(std::vector > adjList) 9 | { 10 | std::deque front(1, 0); 11 | std::unordered_set visited; 12 | while(!front.empty()) 13 | { 14 | int frontLen = front.size(); 15 | for(int i = 0; i < frontLen; i++) 16 | { 17 | int node = front.front(); 18 | front.pop_front(); 19 | for(const int& child: adjList[node]) 20 | if(visited.find(child) == visited.end()) 21 | { 22 | front.push_back(child); 23 | visited.insert(child); 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sampling/py3/weighted_random_sample.py: -------------------------------------------------------------------------------- 1 | import random 2 | from bisect import bisect 3 | 4 | # 1 2 3 4 5 | # 1 3 6 10 6 | # 0 1~2 3~5 6~9 7 | # Find upper bound use bisect 8 | 9 | # Input [weight]; output sampled index 10 | # Compute prefix sum once and sample with replacement O(log n) every time after 11 | # Time: O(n) + O(log n) 12 | # Space: O(n) 13 | def weighted_random_sample(weights): 14 | if not weights: 15 | raise IndexError("Cannot choose from an empty sequence") 16 | sums = list(weights) 17 | for i in range(1, len(weights)): 18 | sums[i] += sums[i - 1] 19 | rand = random.randrange(sums[-1]) 20 | return bisect(sums, rand) 21 | -------------------------------------------------------------------------------- /dutch_national_flag/cxx/three_way_partition.cxx: -------------------------------------------------------------------------------- 1 | #include "three_way_partition.h" 2 | 3 | #include 4 | #include 5 | 6 | bool default_is_head(int elem) 7 | { 8 | return elem == 0; 9 | } 10 | 11 | bool default_is_tail(int elem) 12 | { 13 | return elem == 2; 14 | } 15 | 16 | void three_way_partition(std::vector& array, bool (*is_head)(int), 17 | bool (*is_tail)(int)) 18 | { 19 | int head = 0, tail = array.size() - 1; 20 | int i = 0; 21 | while(i <= tail) 22 | { 23 | if(is_head(array[i])) 24 | std::swap(array[i++], array[head++]); 25 | else if(is_tail(array[i])) 26 | std::swap(array[i], array[tail--]); 27 | else 28 | i++; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /shortest_path/py3/bellman_ford.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | # Tested 4 | def bellman_ford(nodes, edges, source): 5 | #dist = [float("inf")] * len(nodes) 6 | #prev = [None] * len(nodes) 7 | dist = defaultdict(lambda: float("inf")) 8 | prev = {source: None} 9 | dist[source] = 0 10 | 11 | for i in range(1, len(nodes)): 12 | for edge in edges: 13 | u, v, w = edge 14 | if dist[u] + w < dist[v]: 15 | dist[v] = dist[u] + w 16 | prev[v] = u 17 | 18 | for u, v, w in edges: 19 | if dist[u] + w < dist[v]: 20 | return None, "Negative Cycle" 21 | 22 | return dist, prev 23 | -------------------------------------------------------------------------------- /dutch_national_flag/py3/TestThreeWayPartition.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import random 3 | from collections import Counter 4 | from three_way_partition import three_way_partition 5 | 6 | class TestThreeWayPartition(unittest.TestCase): 7 | def testThreeWayPartition(self): 8 | size = 1000 9 | case = [random.randrange(3) for i in range(size)] 10 | cnt = Counter(case) 11 | three_way_partition(case) 12 | for i, num in enumerate(case): 13 | if i > 0: 14 | self.assertTrue(case[i - 1] <= case[i]) 15 | cnt[num] -= 1 16 | self.assertEqual(sum(cnt.values()), 0) 17 | 18 | if __name__ == "__main__": 19 | unittest.main() 20 | -------------------------------------------------------------------------------- /trie/c/trie.h: -------------------------------------------------------------------------------- 1 | typedef struct trie_node 2 | { 3 | char character; 4 | int isLeaf; 5 | struct trie_node* children[26]; 6 | } TrieNode; 7 | 8 | typedef struct trie 9 | { 10 | TrieNode* root; 11 | void (*insert)(struct trie* trie, const char* word); 12 | int (*search)(struct trie* trie, const char* word); 13 | int (*startWith)(struct trie* trie, const char* word); 14 | void (*destroy)(struct trie* trie); 15 | } Trie; 16 | 17 | void trie_node_init(TrieNode* node, char x); 18 | void trie_init(Trie* trie); 19 | void trie_insert(Trie* trie, const char* word); 20 | int trie_search(Trie* trie, const char* word); 21 | int trie_start_with(Trie* trie, const char* prefix); 22 | void trie_destroy(Trie* trie); 23 | -------------------------------------------------------------------------------- /shuffle/py3/fisher_yates.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | # 1 2 3 4 5 6 7 4 | # ^ ^ ^ ^ ^ ^ ^ 5 | # ^ ^ ^ ^ ^ ^ 6 | # ^ ^ ^ ^ ^ 7 | # Every time decrease the range of swapping by 1 from the back 8 | # Time: O(n) 9 | # Space: O(1) 10 | def fisher_yates(array): 11 | for i in range(len(array) - 1, -1, -1): 12 | j = random.randrange(i + 1) 13 | array[i], array[j] = array[j], array[i] 14 | 15 | # 1 2 3 4 5 6 7 16 | # ^ ^ ^ ^ ^ ^ ^ 17 | # ^ ^ ^ ^ ^ ^ 18 | # ^ ^ ^ ^ ^ 19 | # ... or do so from the front. Makes no difference 20 | def fisher_yates_front(array): 21 | for i in range(len(array)): 22 | j = random.randrange(i, len(array)) 23 | array[i], array[j] = array[j], array[i] 24 | -------------------------------------------------------------------------------- /sorting/cxx/heap_sort.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void perc_down(std::vector& array, int i, int size) 5 | { 6 | int child, x; 7 | for(x = array[i]; 2*i+1 < size; i = child) 8 | { 9 | child = 2 * i + 1; 10 | if(child + 1 < size and array[child + 1] > array[child]) 11 | child++; 12 | if(array[child] > x) 13 | array[i] = array[child]; 14 | else 15 | break; 16 | } 17 | array[i] = x; 18 | } 19 | 20 | void heap_sort(std::vector& array) 21 | { 22 | for(int i = array.size()/2; i >= 0; i--) 23 | perc_down(array, i, array.size()); 24 | for(int i = array.size() - 1; i > 0; i--) 25 | { 26 | std::swap(array[0], array[i]); 27 | perc_down(array, 0, i); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /linked_list/py3/cycle_detection.py: -------------------------------------------------------------------------------- 1 | # Floyd's tortoise and hare algorithm 2 | # Time: O(n) 3 | # Space: O(1) 4 | 5 | def cycle_detection(head): 6 | fast = slow = head 7 | while fast and fast.next: 8 | slow = slow.next 9 | fast = fast.next.next 10 | if fast == slow: 11 | return True 12 | return False 13 | 14 | def cycle_finding(head): 15 | fast = slow = head 16 | while fast and fast.next: 17 | slow = slow.next 18 | fast = fast.next.next 19 | if fast == slow: 20 | slow = head 21 | while fast != slow: 22 | slow = slow.next 23 | fast = fast.next 24 | return fast 25 | return None 26 | -------------------------------------------------------------------------------- /string/perl/test_str_matcher.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use kmp_matcher; 6 | 7 | sub gen_str { 8 | my $size = shift; 9 | my (@chars, $str); 10 | my @ATCG = qw(A T C G); 11 | for(0 .. $size) { 12 | push @chars, $ATCG[int(rand(4))]; 13 | } 14 | $str = join '', @chars; 15 | return $str; 16 | } 17 | 18 | sub test_str_matcher { 19 | my $text; 20 | my $pattern; 21 | for(1 .. 1000) { 22 | $text = gen_str(2000); 23 | $pattern = gen_str(5); 24 | if(kmp_matcher($text, $pattern) != index($text, $pattern)) { 25 | return 0; 26 | } 27 | } 28 | return 1; 29 | } 30 | 31 | sub main { 32 | if(not test_str_matcher()) { 33 | print "WA: kmp_matcher\n"; 34 | } 35 | } 36 | 37 | main() 38 | -------------------------------------------------------------------------------- /shortest_path/py3/shortest_path_faster.py: -------------------------------------------------------------------------------- 1 | from collections import deque, defaultdict 2 | 3 | def shortest_path_faster(adjList, source): 4 | dist = defaultdict(lambda: float("inf")) 5 | dist[source] = 0 6 | prev = {source: None} 7 | front = deque([source]) 8 | queue = {source} 9 | while front: 10 | node = front.popleft() 11 | queue.remove(node) 12 | for child, weight in adjList[node]: 13 | if dist[node] + weight < dist[child]: 14 | dist[child] = dist[node] + weight 15 | prev[child] = node 16 | if child not in queue: 17 | front.append(child) 18 | queue.add(child) 19 | return dist, prev 20 | -------------------------------------------------------------------------------- /linked_list/cxx/cycle_detection.cxx: -------------------------------------------------------------------------------- 1 | #include "LinkedList.h" 2 | 3 | bool cycle_detection(ListNode* head) 4 | { 5 | ListNode *slow = head, *fast = head; 6 | while(fast and fast->next) 7 | { 8 | slow = slow->next; 9 | fast = fast->next->next; 10 | if(slow == fast) 11 | return true; 12 | } 13 | return false; 14 | } 15 | 16 | ListNode* cycle_finding(ListNode* head) 17 | { 18 | ListNode *slow = head, *fast = head; 19 | while(fast and fast->next) 20 | { 21 | slow = slow->next; 22 | fast = fast->next->next; 23 | if(slow == fast) 24 | { 25 | slow = head; 26 | while(slow != fast) 27 | { 28 | slow = slow->next; 29 | fast = fast->next; 30 | } 31 | return fast; 32 | } 33 | } 34 | return NULL; 35 | } 36 | -------------------------------------------------------------------------------- /sorting/c/heap_sort.c: -------------------------------------------------------------------------------- 1 | #include "swap.h" 2 | 3 | void heap_sort(int* array, const int n); 4 | void perc_down(int* array, int i, int size); 5 | 6 | void perc_down(int* array, int i, int size) 7 | { 8 | int x, child; 9 | for(x = array[i]; 2*i+1 < size; i = child) 10 | { 11 | child = 2*i+1; 12 | if(child + 1 < size && array[child + 1] > array[child]) 13 | child++; 14 | if(array[child] > x) 15 | array[i] = array[child]; 16 | else 17 | break; 18 | } 19 | array[i] = x; 20 | } 21 | 22 | void heap_sort(int* array, const int n) 23 | { 24 | int i; 25 | for(i = n/2; i >= 0; i--) 26 | perc_down(array, i, n); 27 | 28 | for(i = n - 1; i > 0; i--) 29 | { 30 | swap(&array[0], &array[i]); 31 | perc_down(array, 0, i); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /linked_list/c/cycle_detection.c: -------------------------------------------------------------------------------- 1 | #include "linked_list.h" 2 | #include 3 | 4 | int cycle_detection(ListNode* head) 5 | { 6 | ListNode *slow = head, *fast = head; 7 | while(fast && fast->next) 8 | { 9 | slow = slow->next; 10 | fast = fast->next->next; 11 | if(slow == fast) 12 | return 1; 13 | } 14 | return 0; 15 | } 16 | 17 | ListNode* cycle_finding(ListNode* head) 18 | { 19 | ListNode *slow = head, *fast = head; 20 | while(fast && fast->next) 21 | { 22 | slow = slow->next; 23 | fast = fast->next->next; 24 | if(slow == fast) 25 | { 26 | slow = head; 27 | while(slow != fast) 28 | { 29 | slow = slow->next; 30 | fast = fast->next; 31 | } 32 | return fast; 33 | } 34 | } 35 | return NULL; 36 | } 37 | -------------------------------------------------------------------------------- /shuffle/java/FisherYates.java: -------------------------------------------------------------------------------- 1 | import java.util.Random; 2 | 3 | public class FisherYates 4 | { 5 | public static Random myrand = new Random(); 6 | public static void shuffle(int[] array) 7 | { 8 | int j; 9 | for(int i = array.length - 1; i >= 1; i--) 10 | { 11 | j = myrand.nextInt(i); 12 | array[i] = array[j] ^ array[i] ^ (array[j] = array[i]); 13 | } 14 | } 15 | public static void shuffle_front(int[] array) 16 | { 17 | int j; 18 | for(int i = 0; i < array.length; i++) 19 | { 20 | j = i + myrand.nextInt(array.length - i); 21 | swap(array, i, j); 22 | } 23 | } 24 | private static void swap(int[] array, int i, int j) 25 | { 26 | int temp = array[i]; 27 | array[i] = array[j]; 28 | array[j] = temp; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /linked_list/cxx/LinkedList.cxx: -------------------------------------------------------------------------------- 1 | #include "LinkedList.h" 2 | 3 | ListNode* getLinkedList(std::vector array) 4 | { 5 | if(array.empty()) 6 | return NULL; 7 | 8 | ListNode* head = new ListNode(array[0]); 9 | ListNode* curr = head; 10 | for(int i = 1; i < array.size(); i++) 11 | { 12 | curr->next = new ListNode(array[i]); 13 | curr = curr->next; 14 | } 15 | return head; 16 | } 17 | 18 | std::vector getArray(ListNode* head) 19 | { 20 | std::vector array; 21 | ListNode* curr = head; 22 | while(curr) 23 | { 24 | array.push_back(curr->val); 25 | curr = curr->next; 26 | } 27 | return array; 28 | } 29 | 30 | void destroyLinkedList(ListNode* head) 31 | { 32 | while(head != NULL) 33 | { 34 | delete head; 35 | head = head->next; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /shortest_path/py3/floyd_warshall.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | # Tested 4 | def floyd_warshall(nodes, edges): 5 | dist = {node: defaultdict(lambda: float("inf")) for node in nodes} 6 | #dist = [[float("inf")] * len(nodes) for i in range(len(nodes))] 7 | then = [[None] * len(nodes) for i in range(len(nodes))] 8 | for v in nodes: 9 | dist[v][v] = 0 10 | for edge in edges: 11 | u, v, w = edge 12 | dist[u][v] = w 13 | then[u][v] = v 14 | for k in nodes: 15 | for i in nodes: 16 | for j in nodes: 17 | if dist[i][j] > dist[i][k] + dist[k][j]: 18 | dist[i][j] = dist[i][k] + dist[k][j] 19 | then[i][j] = then[i][k] 20 | return dist, then 21 | -------------------------------------------------------------------------------- /sorting/java/HeapSort.java: -------------------------------------------------------------------------------- 1 | 2 | public class HeapSort implements SortAlgorithm 3 | { 4 | private void percDown(int[] array, int i, int size) 5 | { 6 | int x, child; 7 | for(x = array[i]; i*2+1 < size; i = child) 8 | { 9 | child = i*2+1; 10 | if(child + 1 < size && array[child + 1] > array[child]) 11 | child++; 12 | if(array[child] > x) 13 | array[i] = array[child]; 14 | else 15 | break; 16 | } 17 | array[i] = x; 18 | } 19 | public void sort(int[] array) 20 | { 21 | for(int i = array.length/2; i >= 0; i--) 22 | percDown(array, i, array.length); 23 | for(int i = array.length - 1; i > 0; i--) 24 | { 25 | int tmp = array[i]; 26 | array[i] = array[0]; 27 | array[0] = tmp; 28 | percDown(array, 0, i); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /dp/py3/TestLongestCommonSubsequence.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import random 3 | import string 4 | from longest_common_subsequence import * 5 | 6 | class TestLongestCommonSubsequence(unittest.TestCase): 7 | def __gen_case__(self): 8 | str1 = str().join(random.choice(string.ascii_lowercase) for _ in range(50)) 9 | str2 = str().join(random.choice(string.ascii_lowercase) for _ in range(50)) 10 | return str1, str2 11 | 12 | def testTableFilling(self): 13 | for i in range(50): 14 | str1, str2 = self.__gen_case__() 15 | max1 = longest_common_subsequence_memo(str1, str2) 16 | max2 = longest_common_subsequence(str1, str2) 17 | self.assertEqual(max1, max2) 18 | 19 | if __name__ == "__main__": 20 | unittest.main() 21 | -------------------------------------------------------------------------------- /sorting/py3/TestKWayMergeSort.py: -------------------------------------------------------------------------------- 1 | import operator 2 | import unittest 3 | from random import randrange 4 | from k_way_merge_sort import k_way_merge_sort 5 | from functools import reduce 6 | 7 | class TestKWayMergeSort(unittest.TestCase): 8 | def testKWayMergeSort(self): 9 | for i in range(50): 10 | k = randrange(2, 20) 11 | arrays = [[randrange(9999) for _ in range(1000)] for _ in range(k)] 12 | for array in arrays: 13 | array.sort() 14 | expect = list(reduce(operator.add, arrays)) 15 | expect.sort() 16 | result = k_way_merge_sort(arrays) 17 | self.assertEqual(result, expect) 18 | 19 | if __name__ == '__main__': 20 | print("This could take up to 2 seconds. ") 21 | unittest.main() 22 | -------------------------------------------------------------------------------- /graph/py3/bipartiteness.py: -------------------------------------------------------------------------------- 1 | # Time: O(V + E) 2 | # Space: O(b^d) 3 | # Has to test every connected component 4 | def is_bipartite(adjList): 5 | color = {} 6 | for node in range(len(adjList)): 7 | if node not in color: 8 | if not dfs_alternate_test(adjList, node, color): 9 | return False 10 | return True 11 | 12 | def dfs_alternate_test(adjList, source, color): 13 | front = [source] 14 | color[source] = 0 15 | while front: 16 | node = front.pop() 17 | for child in adjList[node]: 18 | if child in color and color[child] == color[node]: 19 | return False 20 | elif child not in color: 21 | front.append(child) 22 | color[child] = not color[node] 23 | return True 24 | -------------------------------------------------------------------------------- /linked_list/java/CycleDetection.java: -------------------------------------------------------------------------------- 1 | 2 | class CycleDetection 3 | { 4 | static public boolean detectCycle(ListNode head) 5 | { 6 | ListNode fast = head, slow = head; 7 | while(fast != null && fast.next != null) 8 | { 9 | slow = slow.next; 10 | fast = fast.next.next; 11 | if(slow == fast) 12 | return true; 13 | } 14 | return false; 15 | } 16 | static public ListNode findCycle(ListNode head) 17 | { 18 | ListNode fast = head, slow = head; 19 | while(fast != null && fast.next != null) 20 | { 21 | slow = slow.next; 22 | fast = fast.next; 23 | if(slow == fast) 24 | { 25 | slow = head; 26 | while(slow != fast) 27 | { 28 | slow = slow.next; 29 | fast = fast.next; 30 | } 31 | return fast; 32 | } 33 | } 34 | return null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /dutch_national_flag/c/test_three_way_partition.c: -------------------------------------------------------------------------------- 1 | #include "three_way_partition.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | void test_three_way_partition() 8 | { 9 | const int size = 1000; 10 | int array[size]; 11 | int cnt[3] = { 0, 0, 0 }; 12 | int num = 0; 13 | for(int i = 0; i < size; i++) 14 | { 15 | num = rand() % 3; 16 | array[i] = num; 17 | cnt[num] += 1; 18 | } 19 | three_way_partition(array, size, default_is_head, default_is_tail); 20 | for(int i = 0; i < size; i++) 21 | { 22 | assert(i == 0 || array[i - 1] <= array[i]); 23 | cnt[array[i]]--; 24 | } 25 | assert(array[0] == array[1] && array[1] == array[2] && array[2] == 0); 26 | } 27 | 28 | int main() 29 | { 30 | srand(time(0)); 31 | test_three_way_partition(); 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /dutch_national_flag/cxx/test_three_way_partition.cxx: -------------------------------------------------------------------------------- 1 | #include "three_way_partition.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | void test_three_way_partition() 9 | { 10 | const int size = 1000; 11 | std::vector array(size); 12 | int cnt[3] = { 0, 0, 0 }; 13 | int num = 0; 14 | for(int i = 0; i < size; i++) 15 | { 16 | num = rand() % 3; 17 | array[i] = num; 18 | cnt[num] += 1; 19 | } 20 | three_way_partition(array); 21 | for(int i = 0; i < size; i++) 22 | { 23 | assert(i == 0 or array[i - 1] <= array[i]); 24 | cnt[array[i]]--; 25 | } 26 | assert(array[0] == array[1] and array[1] == array[2] and array[2] == 0); 27 | } 28 | 29 | int main() 30 | { 31 | srand(time(NULL)); 32 | test_three_way_partition(); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /binary_search/py3/TestMybisect.py: -------------------------------------------------------------------------------- 1 | import bisect 2 | import mybisect 3 | import random 4 | import unittest 5 | 6 | class TestMybisect(unittest.TestCase): 7 | def setUp(self): 8 | self.array = [random.randrange(1000) for i in range(100)] 9 | self.array.sort() 10 | self.cases = [random.randrange(-1100, 1100) for i in range(100)] 11 | 12 | def testBisect(self): 13 | for case in self.cases: 14 | self.assertEqual(mybisect.bisect(self.array, case), \ 15 | bisect.bisect(self.array, case)) 16 | 17 | def testBisectLeft(self): 18 | for case in self.cases: 19 | self.assertEqual(mybisect.bisect_left(self.array, case), \ 20 | bisect.bisect_left(self.array, case)) 21 | 22 | if __name__ == "__main__": 23 | unittest.main() 24 | -------------------------------------------------------------------------------- /topo_sort/py3/random_dag.py: -------------------------------------------------------------------------------- 1 | import itertools 2 | import random 3 | 4 | def random_dag(size = 500, isWeighted = True): 5 | root = int(size ** 0.5) 6 | ranks = random.randrange(root // 2, root * 3 // 2) 7 | width = size // ranks 8 | lvlMin, lvlMax = width // 2, width * 3 // 2 9 | base = 0 10 | elders = [] 11 | edges = [] 12 | for rank in range(ranks): 13 | count = random.randrange(lvlMin, lvlMax) 14 | level = range(base, base + count) 15 | for u, v in itertools.product(elders, level): 16 | if random.random() < 0.1: 17 | if isWeighted: 18 | edges.append((u, v, random.randrange(100))) 19 | else: 20 | edges.append((u, v)) 21 | elders += level 22 | base += count 23 | return edges 24 | -------------------------------------------------------------------------------- /disjoint_set/cxx/DisjointSet.cxx: -------------------------------------------------------------------------------- 1 | #include "DisjointSet.h" 2 | 3 | void DisjointSet::makeSet(int elem) 4 | { 5 | height.emplace(elem, 0); 6 | parent.emplace(elem, elem); 7 | } 8 | 9 | int DisjointSet::findSet(int elem) 10 | { 11 | if(parent[elem] != elem) 12 | parent[elem] = findSet(parent[elem]); 13 | return parent[elem]; 14 | } 15 | 16 | void DisjointSet::unionSet(int elem1, int elem2) 17 | { 18 | int root1 = findSet(elem1), root2 = findSet(elem2); 19 | if(root1 != root2) 20 | linkSet(root1, root2); 21 | } 22 | 23 | void DisjointSet::linkSet(int root1, int root2) 24 | { 25 | if(height[root1] > height[root2]) 26 | { 27 | height.erase(root2); 28 | parent[root2] = root1; 29 | } 30 | else 31 | { 32 | if(height[root1] == height[root2]) 33 | height[root2]++; 34 | height.erase(root1); 35 | parent[root1] = root2; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /traverse_tree/c/morris_traversal.c: -------------------------------------------------------------------------------- 1 | #include "TreeNode.h" 2 | #include "../../vector/myvector.h" 3 | #include 4 | 5 | int* morris_preorder(struct TreeNode* root, int* returnSize) 6 | { 7 | int* result = (int*) malloc(sizeof(int) * (*returnSize)); 8 | int cnt = 0; 9 | struct TreeNode *curr = root, *node; 10 | while(curr) 11 | { 12 | if(curr->left == NULL) 13 | { 14 | result[cnt++] = curr->val; 15 | curr = curr->right; 16 | } 17 | else 18 | { 19 | node = curr->left; 20 | while(node->right && node->right != curr) 21 | node = node->right; 22 | 23 | if(node->right == NULL) 24 | { 25 | result[cnt++] = curr->val; 26 | node->right = curr; 27 | curr = curr->left; 28 | } 29 | else 30 | { 31 | node->right = NULL; 32 | curr = curr->right; 33 | } 34 | } 35 | } 36 | return result; 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /disjoint_set/py3/TestDisjointSet.py: -------------------------------------------------------------------------------- 1 | import unittest; 2 | from DisjointSet import DisjointSet 3 | from DisjointSet import DisjointSetLinkBySize 4 | 5 | class TestDisjointSet(unittest.TestCase): 6 | def testUnionFind(self): 7 | ds = DisjointSet(range(100)) 8 | for i in range(100): 9 | ds.union(i, i % 5) 10 | for i in range(100): 11 | for j in range(i, 100): 12 | self.assertEqual(ds.find_set(i) == ds.find_set(j), i%5 ==j%5) 13 | 14 | def testDisjointSetLinkBySize(self): 15 | ds = DisjointSetLinkBySize(range(100)) 16 | for i in range(100): 17 | ds.union(i, i % 5) 18 | for i in range(100): 19 | for j in range(i, 100): 20 | self.assertEqual(ds.find_set(i) == ds.find_set(j), i%5 ==j%5) 21 | 22 | if __name__ == '__main__': 23 | unittest.main() 24 | -------------------------------------------------------------------------------- /linked_list/java/ListNode.java: -------------------------------------------------------------------------------- 1 | 2 | public class ListNode 3 | { 4 | public int val; 5 | public ListNode next; 6 | public ListNode(int x) { val = x; next = null; } 7 | public static ListNode getLinkedList(int[] array) 8 | { 9 | if(array.length == 0) 10 | return null; 11 | ListNode head = new ListNode(array[0]); 12 | ListNode curr = head; 13 | for(int i = 1; i < array.length; i++) 14 | { 15 | curr.next = new ListNode(array[i]); 16 | curr = curr.next; 17 | } 18 | return head; 19 | } 20 | public static int[] getArray(ListNode head) 21 | { 22 | ListNode curr = head; 23 | int cnt = 0; 24 | while(curr != null) 25 | { 26 | curr = curr.next; 27 | cnt++; 28 | } 29 | int[] array = new int[cnt]; 30 | for(int i = 0; i < cnt; i++) 31 | { 32 | array[i] = curr.val; 33 | curr = curr.next; 34 | } 35 | return array; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /sorting/py3/heap_sort.py: -------------------------------------------------------------------------------- 1 | # Time: O(n log n) 2 | # Space: O(1) 3 | 4 | def perc_down(array, i, size): 5 | x = array[i] 6 | child = None 7 | while i*2+1 < size: 8 | child = i * 2 + 1 9 | # Heap sort uses a max heap 10 | if child + 1 < size and array[child + 1] > array[child]: 11 | child += 1 12 | # Larger elements goes up 13 | if array[child] > x: 14 | array[i] = array[child] 15 | i = child 16 | else: 17 | break 18 | 19 | array[i] = x 20 | 21 | def heap_sort(array): 22 | # Heapify 23 | for i in range(len(array) // 2, -1, -1): 24 | perc_down(array, i, len(array)) 25 | # Pop from the top and place at the back 26 | for i in range(len(array) - 1, 0, -1): 27 | array[0], array[i] = array[i], array[0] 28 | perc_down(array, 0, i) 29 | -------------------------------------------------------------------------------- /string/cxx/test_str_matcher.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "kmp_matcher.h" 4 | 5 | void gen_str(std::string& str) 6 | { 7 | for(int i = 0; i < str.size(); i++) 8 | switch(rand() % 4) 9 | { 10 | case 0: str[i] = 'A'; break; 11 | case 1: str[i] = 'T'; break; 12 | case 2: str[i] = 'C'; break; 13 | case 3: str[i] = 'G'; break; 14 | } 15 | } 16 | 17 | bool test_str_matcher(int (*matcher)(const std::string&, const std::string&)) 18 | { 19 | std::string text(2000, 'A'), pattern(5, 'T'); 20 | for(int i = 0; i < 1000; i++) 21 | { 22 | gen_str(text); 23 | gen_str(pattern); 24 | 25 | if(text.find(pattern) != matcher(text, pattern)) 26 | return false; 27 | } 28 | return true; 29 | } 30 | 31 | int main() 32 | { 33 | if(!test_str_matcher(kmp_matcher)) 34 | std::cout<<"WA: kmp_matcher"< 0) 23 | { 24 | sum += tree[i]; 25 | i -= i &(-i); 26 | } 27 | return sum; 28 | } 29 | public void update(int i, int delta) 30 | { 31 | i += 1; 32 | while(i < tree.length) 33 | { 34 | tree[i] += delta; 35 | i += i &(-i); 36 | } 37 | } 38 | public int getRange(int i, int j) 39 | { 40 | return getSum(j) - getSum(i - 1); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /vector/myvector.h: -------------------------------------------------------------------------------- 1 | 2 | struct myvector 3 | { 4 | void** data; 5 | int _size; 6 | int _capacity; 7 | void (*init)(struct myvector*); 8 | void (*copy)(struct myvector*, const struct myvector*); 9 | int (*empty)(struct myvector*); 10 | int (*size)(const struct myvector*); 11 | void (*push_back)(struct myvector*, void*); 12 | void (*pop_back)(struct myvector*); 13 | void* (*front)(const struct myvector*); 14 | void* (*back)(const struct myvector*); 15 | void (*destroy)(struct myvector*); 16 | }; 17 | 18 | void init(struct myvector* vec); 19 | void copy(struct myvector* vec, const struct myvector* other); 20 | int empty(struct myvector* vec); 21 | int size(const struct myvector* vec); 22 | void push_back(struct myvector* vec, void* elem); 23 | void pop_back(struct myvector* vec); 24 | void* front(const struct myvector* vec); 25 | void* back(const struct myvector* vec); 26 | void destroy(struct myvector* vec); 27 | -------------------------------------------------------------------------------- /string/cxx/kmp_matcher.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void compute_prefix_function(const std::string& pattern, std::vector& pi) 5 | { 6 | int matched = 0; 7 | for(int i = 1; i < pattern.size(); i++) 8 | { 9 | while(matched > 0 and pattern[i] != pattern[matched]) 10 | matched = pi[matched - 1]; 11 | 12 | if(pattern[i] == pattern[matched]) 13 | matched++; 14 | pi[i] = matched; 15 | } 16 | } 17 | 18 | int kmp_matcher(const std::string& text, const std::string& pattern) 19 | { 20 | std::vector pi(pattern.size(), 0); 21 | compute_prefix_function(pattern, pi); 22 | int matched = 0; 23 | for(int i = 0; i < text.size(); i++) 24 | { 25 | while(matched > 0 and text[i] != pattern[matched]) 26 | matched = pi[matched - 1]; 27 | 28 | if(text[i] == pattern[matched]) 29 | matched++; 30 | if(matched == pattern.size()) 31 | return i - matched + 1; 32 | } 33 | return -1; 34 | } 35 | -------------------------------------------------------------------------------- /binary_indexed_tree/cxx/BinaryIndexedTree.cxx: -------------------------------------------------------------------------------- 1 | #include "BinaryIndexedTree.h" 2 | #include 3 | 4 | BinaryIndexedTree::BinaryIndexedTree(std::vector array) 5 | { 6 | this->tree.push_back(0); 7 | for(int elem: array) 8 | this->tree.push_back(elem); 9 | int j; 10 | for(int i = 0; i < this->tree.size(); i++) 11 | { 12 | j = i + (i & (-i)); 13 | if(j < this->tree.size()) 14 | this->tree[j] += this->tree[i]; 15 | } 16 | } 17 | 18 | int BinaryIndexedTree::getSum(int i) 19 | { 20 | i += 1; 21 | int sum = 0; 22 | while(i > 0) 23 | { 24 | sum += this->tree[i]; 25 | i -= i & (-i); 26 | } 27 | return sum; 28 | } 29 | 30 | void BinaryIndexedTree::update(int i, int delta) 31 | { 32 | i += 1; 33 | while(i <= this->tree.size()) 34 | { 35 | this->tree[i] += delta; 36 | i += i & (-i); 37 | } 38 | } 39 | 40 | int BinaryIndexedTree::getRange(int i, int j) 41 | { 42 | return getSum(j) - getSum(i - 1); 43 | } 44 | -------------------------------------------------------------------------------- /dutch_national_flag/java/TestThreeWayPartition.java: -------------------------------------------------------------------------------- 1 | import java.util.Random; 2 | 3 | public class TestThreeWayPartition 4 | { 5 | public static void testPartition() 6 | { 7 | Random myrand = new Random(); 8 | final int size = 100; 9 | int[] array = new int[size]; 10 | int[] cnt = { 0, 0, 0 }; 11 | int num = 0; 12 | for(int i = 0; i < size; i++) 13 | { 14 | num = myrand.nextInt(3); 15 | array[i] = num; 16 | cnt[num] += 1; 17 | } 18 | ThreeWayPartition.partition(array); 19 | for(int i = 0; i < size; i++) 20 | { 21 | if(array[i] != 0 && array[i - 1] > array[i]) 22 | System.out.println("Partition Error: order"); 23 | cnt[array[i]]--; 24 | } 25 | if(!(array[0] == array[1] && array[1] == array[2] && array[2] == 0)) 26 | System.out.println("Partition Error: swap"); 27 | } 28 | public static void main(String[] args) 29 | { 30 | for(int i = 0; i < 100; i++) 31 | testPartition(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /heap/cxx/TestHeap.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "heap.cxx" 7 | 8 | void testHeapify() 9 | { 10 | std::vector heap; 11 | const int N = 1000; 12 | for(int i = 0; i < N; i++) 13 | heap.push_back(rand() % N); 14 | auto copy = std::vector(heap); 15 | std::sort(copy.begin(), copy.end()); 16 | heapify(heap); 17 | for(int i = 0; i< N; i++) 18 | assert(copy[i] == heappop(heap)); 19 | } 20 | 21 | void testHeappush() 22 | { 23 | std::vector heap, array; 24 | const int N = 1000; 25 | for(int i = 0; i < N; i++) 26 | array.push_back(rand() % N); 27 | for(int i = 0; i < N; i++) 28 | heappush(heap, array[i]); 29 | std::sort(array.begin(), array.end()); 30 | for(int i = 0; i< N; i++) 31 | assert(array[i] == heappop(heap)); 32 | } 33 | 34 | int main() 35 | { 36 | srand(time(nullptr)); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /selection/py3/TestSelect.py: -------------------------------------------------------------------------------- 1 | import random 2 | import time 3 | import unittest 4 | from quick_select import quick_select 5 | from bfprt_select import bfprt_select 6 | 7 | class TestSelect(unittest.TestCase): 8 | def __test_select__(self, select): 9 | size = random.randrange(4000, 5000) 10 | array = [random.randrange(int(size * 1.2)) for i in range(size)] 11 | copy = sorted(array) 12 | time1 = time.time() 13 | for i in range(100): 14 | random.shuffle(array) 15 | rank = random.randrange(1, size + 1) 16 | retval = select(array, rank) 17 | self.assertEqual(retval, copy[rank - 1]) 18 | time2 = time.time() 19 | print(time2 - time1, select) 20 | 21 | def testQuickSelect(self): 22 | self.__test_select__(quick_select) 23 | 24 | def testBFPRTSelect(self): 25 | self.__test_select__(bfprt_select) 26 | 27 | if __name__ == '__main__': 28 | unittest.main() 29 | -------------------------------------------------------------------------------- /string/c/kmp_matcher.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void compute_prefix_function(const char* pattern, int* pi) 5 | { 6 | pi[0] = 0; 7 | int matched = 0, i; 8 | for(i = 1; i < strlen(pattern); i++) 9 | { 10 | while(matched > 0 && pattern[i] != pattern[matched]) 11 | matched = pi[matched - 1]; 12 | if(pattern[i] == pattern[matched]) 13 | matched++; 14 | pi[i] = matched; 15 | } 16 | } 17 | 18 | int kmp_matcher(const char* text, const char* pattern) 19 | { 20 | int* pi = (int*) malloc(sizeof(int) * strlen(pattern)); 21 | compute_prefix_function(pattern, pi); 22 | 23 | int matched = 0, i; 24 | for(i = 0; i < strlen(text); i++) 25 | { 26 | while(matched > 0 && text[i] != pattern[matched]) 27 | matched = pi[matched - 1]; 28 | 29 | if(text[i] == pattern[matched]) 30 | matched++; 31 | if(matched == strlen(pattern)) 32 | { 33 | free(pi); 34 | return i - matched + 1; 35 | } 36 | } 37 | free(pi); 38 | return -1; 39 | } 40 | -------------------------------------------------------------------------------- /sorting/java/MergeSort.java: -------------------------------------------------------------------------------- 1 | 2 | class MergeSort implements SortAlgorithm 3 | { 4 | public void sort(int[] array) 5 | { 6 | int[] tmp = new int[array.length]; 7 | m_sort(array, tmp, 0, array.length); 8 | } 9 | private void m_sort(int[] array, int[] tmp, int start, int end) 10 | { 11 | if(end - start > 1) 12 | { 13 | int middle = (start + end) / 2; 14 | m_sort(array, tmp, start, middle); 15 | m_sort(array, tmp, middle, end); 16 | merge(array, tmp, start, middle, end); 17 | } 18 | } 19 | private void merge(int[] array, int[] tmp, int start, int middle, int end) 20 | { 21 | int i = start, j = middle, k = 0; 22 | while(i < middle && j < end) 23 | { 24 | if(array[i] < array[j]) 25 | tmp[ k++ ] = array[ i++ ]; 26 | else 27 | tmp[ k++ ] = array[ j++ ]; 28 | } 29 | while(i < middle) 30 | tmp[ k++ ] = array[ i++ ]; 31 | while(j < end) 32 | tmp[ k++ ] = array[ j++ ]; 33 | for(i = 0; i < k; i++) 34 | array[start + i] = tmp[i]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /string/java/KMPMatcher.java: -------------------------------------------------------------------------------- 1 | 2 | class KMPMatcher implements StringMatcher 3 | { 4 | public int match(String text, String pattern) 5 | { 6 | int[] pi = computePrefixFunction(pattern); 7 | int matched = 0; 8 | for(int i = 0; i < text.length(); i++) 9 | { 10 | while(matched > 0 && text.charAt(i) != pattern.charAt(matched)) 11 | matched = pi[matched - 1]; 12 | 13 | if(text.charAt(i) == pattern.charAt(matched)) 14 | matched++; 15 | if(matched == pattern.length()) 16 | return i - matched + 1; 17 | } 18 | return -1; 19 | } 20 | public int[] computePrefixFunction(String pattern) 21 | { 22 | int[] pi = new int[ pattern.length() ]; 23 | int matched = 0; 24 | for(int i = 1; i < pattern.length(); i++) 25 | { 26 | while(matched > 0 && pattern.charAt(i) != pattern.charAt(matched)) 27 | matched = pi[matched - 1]; 28 | 29 | if(pattern.charAt(i) == pattern.charAt(matched)) 30 | matched++; 31 | pi[i] = matched; 32 | } 33 | return pi; 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /linked_list/py3/list_merge_sort.py: -------------------------------------------------------------------------------- 1 | from LinkedList import ListNode 2 | 3 | def findMiddle(head): 4 | fast = slow = head 5 | while fast.next and fast.next.next: 6 | slow = slow.next 7 | fast = fast.next.next 8 | return slow 9 | 10 | def list_merge_sort(head): 11 | return list_m_sort(head) if head else None 12 | 13 | def list_m_sort(head): 14 | if head.next is None: 15 | return head 16 | 17 | slow = findMiddle(head) 18 | midd, slow.next = slow.next, None 19 | 20 | head = list_m_sort( head ) 21 | midd = list_m_sort( midd ) 22 | head = list_merge(head, midd) 23 | return head 24 | 25 | def list_merge(l1, l2): 26 | curr = head = ListNode(float("-inf")) 27 | while l1 and l2: 28 | if l1.val < l2.val: 29 | curr.next = l1 30 | l1 = l1.next 31 | else: 32 | curr.next = l2 33 | l2 = l2.next 34 | curr = curr.next 35 | 36 | curr.next = l1 or l2 37 | return head.next 38 | -------------------------------------------------------------------------------- /recursion/py3/combinations.py: -------------------------------------------------------------------------------- 1 | # Combination C(i, n) 2 | """ 3 | Same algorithm with subsets. Only different on stop conditions 4 | """ 5 | def combinations(nums, k): 6 | def helper(k, start, buf, result): 7 | if len(buf) == k: 8 | result.append(list(buf)) 9 | return result 10 | for i in range(start, len(nums) - (k - len(buf)) + 1): 11 | buf.append(nums[i]) 12 | helper(k, i + 1, buf, result) 13 | buf.pop() 14 | return result 15 | return helper(k, 0, [], []) 16 | 17 | def combinationsWithDup(nums, k): 18 | def helper(k, start, buf, result): 19 | if len(buf) == k: 20 | result.append(list(buf)) 21 | return result 22 | for i in range(start, len(nums) - (k - len(buf)) + 1): 23 | if i == start or nums[i] != nums[i - 1]: 24 | buf.append(nums[i]) 25 | helper(k, i + 1, buf, result) 26 | buf.pop() 27 | return result 28 | return helper(k, 0, [], []) 29 | -------------------------------------------------------------------------------- /shortest_path/py3/bidirectional.py: -------------------------------------------------------------------------------- 1 | # Tested 2 | # Verified 3 | def bidirectional(adjList, source, target): 4 | fronts = [[source], [target]] 5 | visited = [set([source]), set([target])] 6 | cnt = [0, 0] 7 | prev = [{source: None}, {target: None}] 8 | border = [] 9 | if source == target: 10 | border.append(source) 11 | while all(fronts) and not border: 12 | smaller = 0 if len(fronts[0]) < len(fronts[1]) else 1 13 | children = [] 14 | cnt[smaller] += 1 15 | for node in fronts[smaller]: 16 | for child in adjList[node]: 17 | if child in visited[not smaller]: 18 | border.append(child) 19 | if child not in visited[smaller]: 20 | visited[smaller].add(child) 21 | children.append(child) 22 | prev[smaller][child] = node 23 | fronts[smaller] = children 24 | for node, parent in prev[1].items(): 25 | prev[0][parent] = node 26 | return sum(cnt), prev[0] 27 | -------------------------------------------------------------------------------- /hashset/cxx/TestHashSet.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "HashSet.h" 4 | 5 | void testInsert(HashSet& dict, int size) 6 | { 7 | for(int i = 0; i < 1000; i++) 8 | { 9 | assert(dict.size() == i); 10 | dict.insert(i); 11 | assert(dict.contains(i)); 12 | assert(not dict.contains(i + 1)); 13 | assert(dict.contains(rand() % (i + 1))); 14 | } 15 | assert(dict.size() == size); 16 | } 17 | 18 | void testErase(HashSet& dict, int size) 19 | { 20 | for(int i = 0; i < 1000; i++) 21 | { 22 | assert(dict.size() == size - i); 23 | assert(dict.contains(i)); 24 | dict.erase(i); 25 | assert(dict.size() == size - i - 1); 26 | assert(not dict.contains(i)); 27 | } 28 | } 29 | 30 | int main() 31 | { 32 | const int size = 1000; 33 | HashSet dict; 34 | testInsert(dict, size); 35 | testErase(dict, size); 36 | testInsert(dict, size); 37 | testErase(dict, size); 38 | testInsert(dict, size); 39 | dict.clear(); 40 | for(int i = 0; i < 1000; i++) 41 | assert(not dict.contains(i)); 42 | assert(dict.size() == 0); 43 | } 44 | -------------------------------------------------------------------------------- /dp/py3/segmented_least_squares.py: -------------------------------------------------------------------------------- 1 | def precompute_errors(points, error): 2 | errors = [[float("inf")] * (len(points) + 1) for _ in points] 3 | for i in range(len(points)): 4 | for j in range(i + 1, len(points) + 1): 5 | errors[i][j] = error(points[i: j]) 6 | return errors 7 | 8 | # Find a partition: variable steps, for each element j that could be a segment 9 | # end find a preceding point i so that segment [i, j) minimizes the overall cost 10 | # OPT[j]: min cost for segmenting points[:j] 11 | # OPT[j] = min(e(i, j) + C + OPT[i]), 0 <= i < j 12 | # OPT[0] = 0 13 | # return OPT[n] 14 | # Time: O(n^2) 15 | # Space: O(n^2) 16 | def segmented_least_squares(points, error, penalty): 17 | errors = precompute_errors(points, error) 18 | n = len(points) 19 | OPT = [float("inf")] * (n + 1) 20 | OPT[0] = 0 21 | for j in range(1, n + 1): 22 | for i in range(j): 23 | candidate = errors[i][j] + penalty + OPT[i] 24 | if candidate < OPT[j]: 25 | OPT[j] = candidate 26 | return OPT[n] 27 | -------------------------------------------------------------------------------- /sorting/java/TestSortImpl.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Random; 3 | 4 | public class TestSortImpl 5 | { 6 | private static int N = 5000; 7 | private static boolean checkMonotonic(int[] array) 8 | { 9 | for(int i = 1; i < array.length; i++) 10 | if(array[i - 1] > array[i]) 11 | return false; 12 | return true; 13 | } 14 | private static boolean checkSortImpl(SortAlgorithm func) 15 | { 16 | Random rand = new Random(); 17 | int[] a = new int[ N ]; 18 | for(int i = 0; i < a.length; i++) 19 | a[i] = rand.nextInt(N); 20 | 21 | func.sort(a); 22 | return checkMonotonic(a); 23 | } 24 | public static void main(String[] argv) 25 | { 26 | ArrayList funcs = new ArrayList(); 27 | funcs.add( new BubbleSort() ); 28 | funcs.add( new InsertionSort() ); 29 | funcs.add( new MergeSort() ); 30 | funcs.add( new QuickSort() ); 31 | funcs.add( new HeapSort() ); 32 | for(SortAlgorithm func: funcs) 33 | if(!checkSortImpl(func)) 34 | System.out.println("WA: " + func.toString()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /graph/py3/TestConnectedComponent.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import random 3 | from connected_component import cnt_connected_component, cnt_connected_component_dj 4 | 5 | class TestConnectedComponent(unittest.TestCase): 6 | def randomGnmGraph(self, n, M): 7 | adjList = { node: set() for node in range(n) } 8 | if M > n * (n - 1) / 2: 9 | raise ValueError("Impossible number of edges") 10 | cntEdge = 0 11 | while cntEdge < M: 12 | u, v = random.randrange(n), random.randrange(n) 13 | if v not in adjList[u] and u != v: 14 | adjList[u].add(v) 15 | adjList[v].add(u) 16 | cntEdge += 1 17 | return adjList 18 | 19 | def testConnectedComponent(self): 20 | for _ in range(100): 21 | adjList = self.randomGnmGraph(50, 70) 22 | cnt1 = cnt_connected_component(adjList) 23 | cnt2 = cnt_connected_component_dj(adjList) 24 | self.assertEqual(cnt1, cnt2) 25 | 26 | if __name__ == "__main__": 27 | unittest.main() 28 | -------------------------------------------------------------------------------- /sorting/cxx/straight_radix_sort.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void straight_radix_sort(std::vector& array); 6 | void counting_sort(std::vector& array, int mask); 7 | 8 | void straight_radix_sort(std::vector& array) 9 | { 10 | int signMask = 1 << (sizeof(int) * CHAR_BIT - 1); 11 | for(int& num: array) 12 | num ^= signMask; 13 | 14 | for(int i = 0; i < sizeof(int) * CHAR_BIT; i++) 15 | counting_sort(array, i); 16 | 17 | for(int& num: array) 18 | num ^= signMask; 19 | } 20 | 21 | void counting_sort(std::vector& array, int bitNo) 22 | { 23 | const int bits = 2; 24 | std::vector count(2, 0); 25 | for(const int& num: array) 26 | count[num >> bitNo & 1]++; 27 | for(int i = 1; i < bits; i++) 28 | count[i] += count[i - 1]; 29 | 30 | std::vector temp(array.size()); 31 | for(int i = array.size() - 1; i >= 0; i--) 32 | { 33 | temp[count[array[i] >> bitNo & 1] - 1] = array[i]; 34 | count[array[i] >> bitNo & 1] -= 1; 35 | } 36 | std::copy(temp.begin(), temp.end(), array.begin()); 37 | } 38 | -------------------------------------------------------------------------------- /string/c/test_str_matcher.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "kmp_matcher.h" 5 | 6 | void gen_str(char* str, int size) 7 | { 8 | int i; 9 | for(i = 0; i < size; i++) 10 | switch(rand() % 4) 11 | { 12 | case 0: str[i] = 'A'; break; 13 | case 1: str[i] = 'T'; break; 14 | case 2: str[i] = 'C'; break; 15 | case 3: str[i] = 'G'; break; 16 | } 17 | str[size - 1] = '\0'; 18 | } 19 | 20 | int test_str_matcher(int (*matcher)(const char*, const char*)) 21 | { 22 | int i; 23 | char text[2001], pattern[6]; 24 | 25 | char* ans = NULL; 26 | int retval = -1; 27 | for(i = 0; i < 1000; i++) 28 | { 29 | gen_str(text, 2001); 30 | gen_str(pattern, 6); 31 | 32 | ans = strstr(text, pattern); 33 | retval = matcher(text, pattern); 34 | 35 | if(ans == NULL && retval != -1) 36 | return 0; 37 | else if(ans != NULL && ans - text != retval) 38 | return 0; 39 | } 40 | return 1; 41 | } 42 | 43 | int main() 44 | { 45 | if(!test_str_matcher(kmp_matcher)) 46 | printf("WA: kmp_matcher\n"); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /mst/py3/TestMST.py: -------------------------------------------------------------------------------- 1 | import random 2 | import unittest 3 | from collections import defaultdict 4 | from prim import prim 5 | from kruskal import kruskal 6 | 7 | class TestMST(unittest.TestCase): 8 | def testMST(self): 9 | size = 50 10 | for _ in range(100): 11 | adjList = defaultdict(list) 12 | edges = [] 13 | cnt = 0 14 | weights = list(range(size * (size - 1) // 2)) 15 | random.shuffle(weights) 16 | for i in range(size): 17 | for j in range(i + 1, size): 18 | adjList[i].append((j, weights[cnt])) 19 | adjList[j].append((i, weights[cnt])) 20 | edges.append((i, j, weights[cnt])) 21 | cnt += 1 22 | parent = prim(adjList) 23 | edges = kruskal(size, edges) 24 | self.assertEqual(len(edges) + 1, len(parent)) 25 | for u, v in edges: 26 | self.assertTrue(parent[u] == v or parent[v] == u) 27 | 28 | if __name__ == "__main__": 29 | unittest.main() 30 | -------------------------------------------------------------------------------- /shortest_path/py3/johnson.py: -------------------------------------------------------------------------------- 1 | # Intuition: Make each edge positive while preserve s-t path length ordering 2 | # Observation: w + Pu - Pv -> L + Ps - Pt does not change path length ordering 3 | # Claim: Use shortest path distance as P will make weights positive 4 | 5 | from bellman_ford import bellman_ford 6 | from dijkstra import dijkstra 7 | 8 | def johnson(nodes, edges): 9 | sentinel = -1 10 | for node in nodes: 11 | edges.append((sentinel, node, 0)) 12 | nodes.append(sentinel) 13 | 14 | weights, prev = bellman_ford(nodes, edges, sentinel) 15 | if weights is None: 16 | return None, "Negative Cycle" 17 | nodes.pop() 18 | del edges[-len(nodes):] 19 | 20 | adjList = { node: [] for node in nodes } 21 | for u, v, w in edges: 22 | adjList[u].append((v, w + weights[u] - weights[v])) 23 | dist, prev = {}, {} 24 | for src in nodes: 25 | dist[src], prev[src] = dijkstra(adjList, src) 26 | for dest in dist[src]: 27 | dist[src][dest] -= (weights[src] - weights[dest]) 28 | return dist, prev 29 | -------------------------------------------------------------------------------- /vector/test_myvector.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "myvector.c" 4 | 5 | int test_myvector() 6 | { 7 | long i, j; 8 | struct myvector vec; 9 | init(&vec); 10 | for(i = 0; i < 9999; i++) 11 | { 12 | vec.push_back(&vec, (void*)i); 13 | if(vec.size(&vec) != i + 1 || vec._capacity < vec.size(&vec) || 14 | vec.front(&vec) != (void*) 0 || vec.back(&vec) != (void*) i) 15 | { 16 | vec.destroy(&vec); 17 | return 0; 18 | } 19 | if(i < 512) 20 | continue; 21 | for(j = 0; j < i + 1; j++) 22 | if((long)vec.data[j] != j) 23 | { 24 | vec.destroy(&vec); 25 | return 0; 26 | } 27 | } 28 | struct myvector vec2; 29 | copy(&vec2, &vec); 30 | for(i = 0; i < 9999; i++) 31 | if(vec2.data[i] != (void*) i || vec.data[i] != (void*) i|| &vec2.data[i] == &vec.data[i]) 32 | { 33 | vec.destroy(&vec); 34 | vec2.destroy(&vec2); 35 | return 0; 36 | } 37 | vec.destroy(&vec); 38 | vec2.destroy(&vec2); 39 | return 1; 40 | } 41 | 42 | int main() 43 | { 44 | if(!test_myvector()) 45 | printf("WA: myvector"); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /shortest_path/py3/dijkstra.py: -------------------------------------------------------------------------------- 1 | from heapq import * 2 | 3 | # Tested 4 | def dijkstra(adjList, source): 5 | front = [(0, source)] 6 | dist = {source: 0} 7 | prev = {source: None} 8 | 9 | while front: 10 | d, node = heappop(front) 11 | for child, weight in adjList[node]: 12 | if child not in dist or d + weight < dist[child]: 13 | dist[child] = d + weight 14 | heappush(front, (dist[child], child)) 15 | prev[child] = node 16 | 17 | return dist, prev 18 | 19 | # Verified 20 | def dijkstra_template(adjList, source): 21 | front = [(0, source)] 22 | dist = {source: 0} 23 | while front: 24 | d, node = heappop(front) 25 | for child, weight in adjList[node]: 26 | if child not in dist or d + weight < dist[child]: 27 | dist[child] = d + weight 28 | heappush(front, (dist[child], child)) 29 | return dist 30 | 31 | def dijkstra_decrese_key(adjList, source): 32 | pass 33 | 34 | def uniform_cost_search(adjList, source, dest): 35 | pass 36 | -------------------------------------------------------------------------------- /linked_list/c/linked_list.c: -------------------------------------------------------------------------------- 1 | #include "linked_list.h" 2 | 3 | #include 4 | 5 | ListNode* get_list_node(int value) 6 | { 7 | ListNode* node = (ListNode*) malloc(sizeof(ListNode)); 8 | node->val = value; 9 | node->next = NULL; 10 | return node; 11 | } 12 | 13 | ListNode* get_linked_list(int* array, int n) 14 | { 15 | if(n == 0) 16 | return 0; 17 | 18 | int i; 19 | ListNode* head = get_list_node(array[0]); 20 | ListNode* curr = head; 21 | 22 | for(i = 1; i < n; i++) 23 | { 24 | curr->next = get_list_node(array[i]); 25 | curr = curr->next; 26 | } 27 | return head; 28 | } 29 | 30 | int* get_array(ListNode* head) 31 | { 32 | ListNode* curr = head; 33 | int cnt = 0; 34 | while(curr) 35 | { 36 | cnt++; 37 | curr = curr->next; 38 | } 39 | 40 | int* array = (int*) malloc(sizeof(int) * cnt); 41 | curr = head; 42 | int i; 43 | for(i = 0; i < cnt; i++) 44 | { 45 | array[i] = curr->val; 46 | curr = curr->next; 47 | } 48 | return array; 49 | } 50 | 51 | void destroy_linked_list(ListNode* head) 52 | { 53 | while(head) 54 | { 55 | free(head); 56 | head = head->next; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /heap/c/test_heap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "heap.c" 5 | 6 | int compare(const void* a, const void* b) 7 | { 8 | if ( *(int*)a < *(int*)b ) return -1; 9 | if ( *(int*)a > *(int*)b ) return 1; 10 | return 0; 11 | } 12 | 13 | void testHeapify() 14 | { 15 | const int N = 1000; 16 | int array[N]; 17 | struct myvector vec; 18 | struct myvector* heap = &vec; 19 | for(int i = 0; i < N; i++) 20 | { 21 | array[i] = rand() % N; 22 | heap->push_back(heap, array[i]); 23 | } 24 | qsort(heap, N, sizeof(int), compare); 25 | heapify(heap); 26 | for(int i = 0; i< N; i++) 27 | assert(array[i] == heappop(heap)); 28 | } 29 | 30 | void testHeappush() 31 | { 32 | const int N = 1000; 33 | int array[N]; 34 | struct myvector vec; 35 | struct myvector* heap = &vec; 36 | for(int i = 0; i < N; i++) 37 | array[i] = rand() % N; 38 | for(int i = 0; i < N; i++) 39 | heappush(heap, array[i]); 40 | qsort(heap, N, sizeof(int), compare); 41 | for(int i = 0; i< N; i++) 42 | assert(array[i] == heappop(heap)); 43 | } 44 | 45 | int main() 46 | { 47 | srand(time(0)); 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /binary_search/c/binary_search.c: -------------------------------------------------------------------------------- 1 | int binary_search(int* array, int n, int target) 2 | { 3 | int left = 0, right = n - 1, center; 4 | while(left <= right) 5 | { 6 | center = left + (right - left) / 2; 7 | if(array[center] == target) 8 | return center; 9 | else if(array[center] < target) 10 | left = center + 1; 11 | else 12 | right = center - 1; 13 | } 14 | return -1; 15 | } 16 | 17 | int lower(int* array, int n, int target) 18 | { 19 | int left = 0, right = n - 1, center; 20 | while(left <= right) 21 | { 22 | center = left + (right - left) / 2; 23 | if(array[center] == target) 24 | right = center - 1; 25 | else if(array[center] < target) 26 | left = center + 1; 27 | else 28 | right = center - 1; 29 | } 30 | return left - 1; 31 | } 32 | 33 | int higher(int* array, int n, int target) 34 | { 35 | int left = 0, right = n - 1, center; 36 | while(left <= right) 37 | { 38 | center = left + (right - left) / 2; 39 | if(array[center] == target) 40 | left = center + 1; 41 | else if(array[center] < target) 42 | left = center + 1; 43 | else 44 | right = center - 1; 45 | } 46 | return left; 47 | } 48 | -------------------------------------------------------------------------------- /sorting/c/merge_sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void merge_sort(int* array, const int n); 4 | void m_sort(int* array, int* temp, int start, int stop); 5 | void merge(int* array, int* temp, int start, int middle, int stop); 6 | 7 | void merge_sort(int* array, const int n) 8 | { 9 | int* temp = malloc(sizeof(int) * n); 10 | m_sort(array, temp, 0, n); 11 | free( temp ); 12 | } 13 | 14 | void m_sort(int* array, int* temp, int start, int stop) 15 | { 16 | if(stop - start > 1) 17 | { 18 | int middle = start + (stop - start) / 2; 19 | m_sort(array, temp, start, middle); 20 | m_sort(array, temp, middle, stop); 21 | merge(array, temp, start, middle, stop); 22 | } 23 | } 24 | 25 | void merge(int* array, int* temp, int start, int middle, int stop) 26 | { 27 | int i = start, j = middle, k = 0; 28 | while(i < middle && j < stop) 29 | if(array[i] < array[j]) 30 | temp[ k++ ] = array[ i++ ]; 31 | else 32 | temp[ k++ ] = array[ j++ ]; 33 | 34 | while(i < middle) 35 | temp[ k++ ] = array[ i++ ]; 36 | 37 | while(j < stop) 38 | temp[ k++ ] = array[ j++ ]; 39 | 40 | for(i = 0; i < k; i++) 41 | array[start + i] = temp[i]; 42 | } 43 | -------------------------------------------------------------------------------- /selection/c/quick_select_lomuto.c: -------------------------------------------------------------------------------- 1 | int partition(int* array, int left, int right); 2 | int q_select(int* array, int left, int right, int rank); 3 | int quick_select(int* array, const int n, int rank); 4 | 5 | int quick_select(int* array, int n, int rank) 6 | { 7 | return q_select(array, 0, n - 1, rank); 8 | } 9 | 10 | int q_select(int* array, int left, int right, int rank) 11 | { 12 | if(left == right) 13 | return array[right]; 14 | int center = partition(array, left, right); 15 | int pivot_rank = center - left + 1; 16 | if(rank == pivot_rank) 17 | return array[center]; 18 | else if(rank < pivot_rank) 19 | return q_select(array, left, center - 1, rank); 20 | else 21 | return q_select(array, center + 1, right, rank - pivot_rank); 22 | } 23 | 24 | void swap(int* a, int* b) 25 | { 26 | int tmp = *a; 27 | *a = *b; 28 | *b = tmp; 29 | } 30 | 31 | int partition(int* array, int left, int right) 32 | { 33 | int pivot = array[right]; 34 | int i = left; 35 | for(int j = left; j < right; j++) 36 | if(array[j] < pivot) 37 | { 38 | swap(&array[i], &array[j]); 39 | i++; 40 | } 41 | swap(&array[i], &array[right]); 42 | return i; 43 | } 44 | -------------------------------------------------------------------------------- /disjoint_set/java/DisjointSet.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | 3 | public class DisjointSet 4 | { 5 | private HashMap parent; 6 | private HashMap height; 7 | public DisjointSet() 8 | { 9 | parent = new HashMap(); 10 | height = new HashMap(); 11 | } 12 | public void makeSet(int elem) 13 | { 14 | parent.put(elem, elem); 15 | height.put(elem, 0); 16 | } 17 | public int findSet(int elem) 18 | { 19 | if(parent.get(elem) != elem) 20 | parent.put(elem, findSet(parent.get(elem))); 21 | return parent.get(elem); 22 | } 23 | public void union(int elem1, int elem2) 24 | { 25 | int root1 = findSet(elem1), root2 = findSet(elem2); 26 | if(root1 != root2) 27 | link(root1, root2); 28 | } 29 | private void link(int root1, int root2) 30 | { 31 | if(height.get(root1) > height.get(root2)) 32 | { 33 | parent.put(root2, root1); 34 | height.remove(root2); 35 | } 36 | else 37 | { 38 | if(height.get(root1) == height.get(root2)) 39 | height.put(root2, height.get(root2) + 1); 40 | parent.put(root1, root2); 41 | height.remove(root1); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /heap/java/TestHeap.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Arrays; 3 | import java.util.Random; 4 | 5 | class TestHeap 6 | { 7 | public static Random myrand = new Random(); 8 | public static void testHeapify() 9 | { 10 | final int N = 1000; 11 | int[] array = new int[N]; 12 | ArrayList heap = new ArrayList(); 13 | for(int i = 0; i < N; i++) 14 | { 15 | array[i] = myrand.nextInt(N); 16 | heap.add(array[i]); 17 | } 18 | Arrays.sort(array); 19 | Heap.heapify(heap); 20 | for(int i = 0; i < N; i++) 21 | if(array[i] != Heap.heappop(heap)) 22 | System.out.println("Heapify Error!"); 23 | } 24 | public static void testHeappush() 25 | { 26 | final int N = 1000; 27 | int[] array = new int[N]; 28 | ArrayList heap = new ArrayList(); 29 | for(int i = 0; i < N; i++) 30 | { 31 | array[i] = myrand.nextInt(N); 32 | Heap.heappush(heap, array[i]); 33 | } 34 | Arrays.sort(array); 35 | for(int i = 0; i < N; i++) 36 | if(array[i] != Heap.heappop(heap)) 37 | System.out.println("Heapify Error!"); 38 | } 39 | public static void main(String[] argv) 40 | { 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /binary_search/py3/mybisect.py: -------------------------------------------------------------------------------- 1 | """0, 0, 0, 1, 1, 1, 2, 2, 2""" 2 | """ ^ """ 3 | # Equivalent to ceiling(array, target), target <= ceiling 4 | # Insert 1 or 0.5 in above example 5 | # Thus, lower = ceiling - 1 6 | def bisect_left(array, target): 7 | left, right = 0, len(array) - 1 8 | while left <= right: 9 | center = (left + right) // 2 10 | if array[center] == target: 11 | right = center - 1 12 | elif array[center] < target: 13 | left = center + 1 14 | else: 15 | right = center - 1 16 | return left 17 | 18 | """0, 0, 0, 1, 1, 1, 2, 2, 2""" 19 | """ $ """ 20 | # Equivalent to higher(array, target), target < higher 21 | # Insert 1 or 1.5 in above example 22 | # Thus, floor = higher - 1 23 | def bisect(array, target): 24 | left, right = 0, len(array) - 1 25 | while left <= right: 26 | center = (left + right) // 2 27 | if array[center] == target: 28 | left = center + 1 29 | elif array[center] < target: 30 | left = center + 1 31 | else: 32 | right = center - 1 33 | return left 34 | -------------------------------------------------------------------------------- /dp/py3/TestSequenceAlignment.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import random 3 | import collections 4 | from sequence_alignment import * 5 | 6 | class TestSequenceAlignment(unittest.TestCase): 7 | def __gen_case__(self): 8 | bases = "ATCG" 9 | X = str().join(random.choice(bases) for i in range(50)) 10 | Y = str().join(random.choice(bases) for i in range(50)) 11 | gap_penalty = 2 12 | mmat = [[0, 1, 2, 3], 13 | [1, 0, 3, 2], 14 | [2, 3, 0, 1], 15 | [3, 2, 1, 0]] 16 | mismatch_penalty = collections.defaultdict(dict) 17 | for i in range(len(bases)): 18 | for j in range(len(bases)): 19 | mismatch_penalty[bases[i]][bases[j]] = mmat[i][j] 20 | return X, Y, gap_penalty, mismatch_penalty 21 | 22 | def testTableFilling(self): 23 | for i in range(10): 24 | X, Y, gap_penalty, mismatch_penalty = self.__gen_case__() 25 | min1 = sequence_alignment_memo(X, Y, gap_penalty, mismatch_penalty) 26 | min2 = sequence_alignment(X, Y, gap_penalty, mismatch_penalty) 27 | 28 | if __name__ == "__main__": 29 | unittest.main() 30 | -------------------------------------------------------------------------------- /binary_indexed_tree/Binary Indexed Tree.md: -------------------------------------------------------------------------------- 1 | # Binary Indexed Tree 2 | With the number system, human can represent the number a hundred with three digits. 3 | 4 | ``` 5 | 100 = count([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) 6 | ``` 7 | 8 | This reduce the space complexity of number representation to $\log(n)$ 9 | 10 | $$\log(100) = 3$$ 11 | 12 | Binary Indexed Tree takes this notion of taking $\log$, and arrives at a data structure that achieves `update()` and `getSum()` operation both at $\log(n)$ complexity. 13 | 14 | For $\forall n$, `getSum(n)` is decomposed as the sum of powers-of-two. 15 | 16 | $$\begin{align} 17 | 13 &= 8 + 4 + 1 \\ 18 | 1101 &= 1000 + 0100 + 0001 19 | \end{align}$$ 20 | 21 | Each corresponding sum is stored 22 | 23 | ```python 24 | sum(array[0: 13]) = sum(array[0: 8]) + sum(array[8: 12]) + sum(array[12: 13]) 25 | sum([0000: 1101]) = sum([0000: 1000]) + sum([1000: 1100]) + sum([1100: 1101]) 26 | ``` 27 | -------------------------------------------------------------------------------- /stack/py3/next_greater.py: -------------------------------------------------------------------------------- 1 | def next_greater(nums): 2 | stack = [] 3 | greater = [float("inf")] * len(nums) 4 | for i in range(len(nums)): 5 | while stack and nums[stack[-1]] < nums[i]: 6 | greater[stack.pop()] = nums[i] 7 | stack.append(i) 8 | return greater 9 | 10 | def next_greater_reverse(nums): 11 | stack = [] 12 | greater = [float("inf")] * len(nums) 13 | for i in range(len(nums) - 1, -1, -1): 14 | while stack and stack[-1] <= nums[i]: 15 | stack.pop() 16 | if stack: 17 | greater[i] = stack[-1] 18 | stack.append(nums[i]) 19 | return greater 20 | 21 | # Find next element greater than curr and the last element greater than or equal 22 | # to curr for each element in the array 23 | def next_gt_last_ge(nums): 24 | stack = [] 25 | nGt = [float("inf")] * len(nums) 26 | lGe = [float("inf")] * len(nums) 27 | for i, num in enumerate(nums): 28 | while stack and nums[stack[-1]] < num: 29 | left = stack.pop() 30 | nGt[left] = num 31 | if stack: 32 | lGe[i] = nums[stack[-1]] 33 | stack.append(i) 34 | return nGt, lGe 35 | -------------------------------------------------------------------------------- /string/java/TestStringMatcher.java: -------------------------------------------------------------------------------- 1 | 2 | import java.util.Random; 3 | 4 | public class TestStringMatcher 5 | { 6 | private static Random myrand = new Random(); 7 | private static String genRandomString(char[] str) 8 | { 9 | for(int i = 0; i < str.length; i++) 10 | switch(myrand.nextInt(4)) 11 | { 12 | case 0: str[i] = 'A'; break; 13 | case 1: str[i] = 'T'; break; 14 | case 2: str[i] = 'C'; break; 15 | case 3: str[i] = 'G'; break; 16 | } 17 | return new String(str); 18 | } 19 | private static boolean testStringMatcher(StringMatcher matcher) 20 | { 21 | char[] text = new char[2000]; 22 | char[] pattern = new char[5]; 23 | 24 | for(int i = 0; i < 1000; i++) 25 | { 26 | String txt = genRandomString(text); 27 | String pat = genRandomString(pattern); 28 | 29 | if(matcher.match(txt, pat) != txt.indexOf(pat)) 30 | return false; 31 | } 32 | return true; 33 | } 34 | public static void main(String[] argv) 35 | { 36 | StringMatcher[] matchers = { 37 | new NaiveMatcher(), new KMPMatcher() 38 | }; 39 | for(StringMatcher matcher: matchers) 40 | if(!testStringMatcher(matcher)) 41 | System.out.println("WA: " + matcher); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /trie/go/trie.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // UNTESTED 4 | 5 | // TrieNode is a node in a Trie 6 | type TrieNode struct { 7 | Children map[rune]*TrieNode 8 | IsLeaf bool 9 | } 10 | 11 | // Trie is a prefix tree 12 | type Trie struct { 13 | Root *TrieNode 14 | } 15 | 16 | // Insert adds a word in the Trie 17 | func (t *Trie) Insert(word string) { 18 | curr := t.Root 19 | for _, char := range word { 20 | if _, ok := curr.Children[char]; !ok { 21 | curr.Children[char] = &TrieNode{} 22 | } 23 | curr = curr.Children[char] 24 | } 25 | curr.IsLeaf = true 26 | } 27 | 28 | // Search finds if a word in the Trie 29 | func (t *Trie) Search(word string) bool { 30 | curr := t.Root 31 | for _, char := range word { 32 | if _, ok := curr.Children[char]; !ok { 33 | return false 34 | } 35 | curr = curr.Children[char] 36 | } 37 | return curr.IsLeaf 38 | } 39 | 40 | // StartWith returns if there are words in the Trie that starts with the prefix 41 | func (t *Trie) StartWith(prefix string) bool { 42 | curr := t.Root 43 | for _, char := range prefix { 44 | if _, ok := curr.Children[char]; !ok { 45 | return false 46 | } 47 | curr = curr.Children[char] 48 | } 49 | return true 50 | } 51 | -------------------------------------------------------------------------------- /dp/py3/subset_sum.py: -------------------------------------------------------------------------------- 1 | # Find a subset: n steps, for each element decide to include it or not 2 | # OPT[i][k]: maximum subset sum of a[:i] that is less than or equal to k 3 | # OPT[i][k] = max(OPT[i - 1][k], OPT[i - 1][k - a[i - 1]] + a[i - 1]) 4 | # OPT[0][k] = 0 5 | # OPT[i][0] = 0 6 | # return OPT[n][K] 7 | # Time: O(nK) 8 | # Space: O(nK) 9 | def subset_sum(nums, K): 10 | OPT = [[0] * (K + 1) for _ in range(len(nums) + 1)] 11 | for i in range(1, len(nums) + 1): 12 | for k in range(1, K + 1): 13 | num = nums[i - 1] 14 | if k - num < 0: 15 | OPT[i][k] = OPT[i - 1][k] 16 | else: 17 | OPT[i][k] = max(OPT[i - 1][k], OPT[i - 1][k - num] + num) 18 | return OPT[-1][-1] 19 | 20 | def subset_sum_memoization(nums, K): 21 | def helper(start, K): 22 | if (start, K) in cache: 23 | return cache[(start, K)] 24 | maximum = 0 25 | for i in range(start, len(nums)): 26 | if nums[i] <= K: 27 | maximum = max(nums[i] + helper(i + 1, K - nums[i]), maximum) 28 | cache[(start, K)] = maximum 29 | return cache[(start, K)] 30 | cache = {} 31 | return helper(0, K) 32 | -------------------------------------------------------------------------------- /sorting/py3/quick_sort_lomuto.py: -------------------------------------------------------------------------------- 1 | def insertion_sort(array, left, right): 2 | for i in range(left + 1, right + 1): 3 | x = array[i] 4 | j = i - 1 5 | while j >= left and x < array[j]: 6 | array[j + 1] = array[j] 7 | j -= 1 8 | array[j + 1] = x 9 | 10 | def median3(array, left, right): 11 | center = (left + right) // 2 12 | a, b, c = sorted([array[left], array[center], array[right]]) 13 | array[left], array[center], array[right] = a, c, b 14 | return b 15 | 16 | def partition(array, left, right): 17 | pivot = median3(array, left, right) 18 | i = left 19 | for j in range(left, right): 20 | if array[j] < pivot: 21 | array[i], array[j] = array[j], array[i] 22 | i += 1 23 | array[i], array[right] = array[right], array[i] 24 | return i 25 | 26 | def q_sort(array, left, right): 27 | if right - left > 10: 28 | center = partition(array, left, right) 29 | q_sort(array, left, center - 1) 30 | q_sort(array, center + 1, right) 31 | else: 32 | insertion_sort(array, left, right) 33 | 34 | def quick_sort_lomuto(array): 35 | q_sort(array, 0, len(array) - 1) 36 | -------------------------------------------------------------------------------- /traverse_tree/py3/RecursiveTraversal.py: -------------------------------------------------------------------------------- 1 | class RecursiveTraversal: 2 | @staticmethod 3 | def preorderTraversal(root): 4 | result = [] 5 | 6 | def helper(root, result): 7 | if not root: 8 | return 9 | result.append(root.val) 10 | helper(root.left, result) 11 | helper(root.right, result) 12 | 13 | helper(root, result) 14 | return result 15 | 16 | @staticmethod 17 | def inorderTraversal(root): 18 | result = [] 19 | 20 | def helper(root, result): 21 | if not root: 22 | return 23 | helper(root.left, result) 24 | result.append(root.val) 25 | helper(root.right, result) 26 | 27 | helper(root, result) 28 | return result 29 | 30 | @staticmethod 31 | def postorderTraversal(root, result = []): 32 | result = [] 33 | 34 | def helper(root, result): 35 | if not root: 36 | return 37 | helper(root.left, result) 38 | helper(root.right, result) 39 | result.append(root.val) 40 | 41 | helper(root, result) 42 | return result 43 | -------------------------------------------------------------------------------- /linked_list/java/ListMergeSort.java: -------------------------------------------------------------------------------- 1 | 2 | public class ListMergeSort implements ListSortAlgorithm 3 | { 4 | public ListNode sort(ListNode head) 5 | { 6 | if(head == null) 7 | return head; 8 | return m_sort(head); 9 | } 10 | private ListNode m_sort(ListNode head) 11 | { 12 | if(head.next == null) 13 | return head; 14 | ListNode slow = findMiddle(head); 15 | ListNode midd = slow.next; 16 | slow.next = null; 17 | 18 | head = m_sort(head); 19 | midd = m_sort(midd); 20 | return merge(head, midd); 21 | } 22 | private ListNode findMiddle(ListNode head) 23 | { 24 | ListNode slow = head, fast = head; 25 | while(fast.next != null && fast.next.next != null) 26 | { 27 | slow = slow.next; 28 | fast = fast.next.next; 29 | } 30 | return slow; 31 | } 32 | private ListNode merge(ListNode l1, ListNode l2) 33 | { 34 | ListNode dummy = new ListNode(-1); 35 | ListNode curr = dummy; 36 | while(l1 != null && l2 != null) 37 | { 38 | if(l1.val < l2.val) 39 | { 40 | curr.next = l1; 41 | l1 = l1.next; 42 | } 43 | else 44 | { 45 | curr.next = l2; 46 | l2 = l2.next; 47 | } 48 | curr = curr.next; 49 | } 50 | curr.next = (l1 != null ? l1 : l2); 51 | return dummy.next; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /string/py3/kmp_matcher.py: -------------------------------------------------------------------------------- 1 | # Time: O(n) text 2 | # Space: O(k) pattern 3 | 4 | def kmp_matcher(pattern, text): 5 | pi = compute_prefix_function(pattern) 6 | matched = 0 7 | for i in range(len(text)): 8 | while matched > 0 and pattern[matched] != text[i]: 9 | matched = pi[matched - 1] 10 | if pattern[matched] == text[i]: 11 | matched += 1 12 | if matched == len(pattern): 13 | return i + 1 - len(pattern) 14 | return -1 15 | 16 | # pi is a jump table indicating which index in pattern you should match next 17 | # pi[i] = how many you have matched given you have matched pattern[0 .. i] 18 | # In other words, where to jump when you are at character pattern[i] 19 | # Since we know pattern[0 .. i] won't work because pattern[i + 1] doesn't match 20 | # We never jump at index 0 because there is no more character behind it 21 | def compute_prefix_function(pattern): 22 | pi = [0] * len(pattern) 23 | matched = 0 24 | for i in range(1, len(pattern)): 25 | while matched > 0 and pattern[i] != pattern[matched]: 26 | matched = pi[matched - 1] 27 | if pattern[i] == pattern[matched]: 28 | matched += 1 29 | pi[i] = matched 30 | return pi 31 | -------------------------------------------------------------------------------- /traverse_tree/c/test_traversal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "morris_traversal.c" 4 | #include "TreeNode.h" 5 | 6 | void shuffle(int* array, int size) 7 | { 8 | int i, j, tmp; 9 | for(i = 0; i < size; i++) 10 | { 11 | j = rand() % size; 12 | 13 | tmp = array[i]; 14 | array[i] = array[j]; 15 | array[j] = tmp; 16 | } 17 | } 18 | 19 | struct TreeNode* generate_random_tree(int size) 20 | { 21 | int* pool = (int*) malloc(sizeof(int) * size); 22 | int i; 23 | for(i = 0; i < size; i++) 24 | pool[i] = i; 25 | i = 0; 26 | struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode)); 27 | root->val = pool[i++]; 28 | // I need a deque 29 | for(i = 0; i < size; i++) 30 | { 31 | 32 | } 33 | free(pool); 34 | return root; 35 | } 36 | 37 | int test_traversal_methods(int* (*func)(struct TreeNode*, int*), int size) 38 | { 39 | struct TreeNode* root = generate_random_tree(size); 40 | root = 0; 41 | return 1; 42 | } 43 | 44 | int main() 45 | { 46 | typedef int* (*traversal)(struct TreeNode*, int*); 47 | traversal funcs[] = { morris_preorder }; 48 | int i; 49 | for(i = 0; i < 1; i++) 50 | if(!test_traversal_methods(funcs[i], 0)) 51 | printf("WA: func at funcs[%d]", i); 52 | } 53 | -------------------------------------------------------------------------------- /heap/cxx/heap.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | static void perc_down(std::vector& array, int i, int size) 6 | { 7 | T x = array[i]; 8 | int child; 9 | while(2 * i + 1 < size) 10 | { 11 | child = 2 * i + 1; 12 | if(child < size - 1 and array[child + 1] < array[child]) 13 | child++; 14 | if(array[child] < x) 15 | { 16 | array[i] = array[child]; 17 | i = child; 18 | } 19 | else 20 | break; 21 | array[i] = x; 22 | } 23 | } 24 | 25 | template 26 | void heapify(std::vector& array) 27 | { 28 | for(int i = array.size() / 2; i >= 0; i--) 29 | perc_down(array, i, array.size()); 30 | } 31 | 32 | template 33 | void heappush(std::vector array, T elem) 34 | { 35 | array.push_back(elem); 36 | int i = array.size() - 1; 37 | int parent; 38 | while(i > 0) 39 | { 40 | parent = (i - 1) / 2; 41 | if(array[i] < array[parent]) 42 | { 43 | std::swap(array[i], array[parent]); 44 | i = parent; 45 | } 46 | else 47 | break; 48 | } 49 | } 50 | 51 | template 52 | T heappop(std::vector array) 53 | { 54 | T retval = array[0]; 55 | array[0] = array.back(); 56 | array.pop_back(); 57 | perc_down(array, 0, array.size()); 58 | return retval; 59 | } 60 | -------------------------------------------------------------------------------- /sorting/c/test_sort_algo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "insertion_sort.c" 5 | #include "selection_sort.c" 6 | #include "bubble_sort.c" 7 | #include "merge_sort.c" 8 | #include "quick_sort.c" 9 | #include "heap_sort.c" 10 | 11 | int compare(const void * a, const void * b) { return (*(int*)a - *(int*)b); } 12 | 13 | int check_sort_impl(void (*func)(int*, const int)) 14 | { 15 | const int times = 100; 16 | int array[2000], original[2000]; 17 | for(int j = 0; j < times; j++) 18 | { 19 | int size = rand() % 1000 + 1000; 20 | for(int i = 0; i < size; i++) 21 | array[i] = rand() % size; 22 | memcpy(original, array, sizeof(int) * size); 23 | func(array, size); 24 | qsort(original, size, sizeof(int), compare); 25 | for(int i = 0; i < size; i++) 26 | if(array[i] != original[i]) 27 | return 0; 28 | } 29 | return 1; 30 | } 31 | 32 | int main() 33 | { 34 | const int NFUNC = 6; 35 | typedef void (*sort_func)(int*, const int); 36 | sort_func funcs[] = { insertion_sort, selection_sort, bubble_sort, 37 | merge_sort, quick_sort, heap_sort 38 | }; 39 | int i; 40 | for(i = 0; i < NFUNC; i++) 41 | if( !check_sort_impl(funcs[i]) ) 42 | printf("Error at funcs[%d]", i); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /sorting/cxx/merge_sort.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void merge_sort(std::vector& array); 4 | void m_sort(std::vector& array, std::vector& temp, int start, int stop); 5 | void merge(std::vector& array, std::vector& temp, int start, int middle, int stop); 6 | 7 | void merge_sort(std::vector& array) 8 | { 9 | std::vector temp(array.size()); 10 | m_sort(array, temp, 0, array.size()); 11 | } 12 | 13 | void m_sort(std::vector& array, std::vector& temp, int start, int stop) 14 | { 15 | if(stop - start > 1) 16 | { 17 | int middle = start + (stop - start) / 2; 18 | m_sort(array, temp, start, middle); 19 | m_sort(array, temp, middle, stop); 20 | merge(array, temp, start, middle, stop); 21 | } 22 | } 23 | 24 | void merge(std::vector& array, std::vector& temp, int start, int middle, int stop) 25 | { 26 | int i = start, j = middle, k = 0; 27 | while(i < middle && j < stop) 28 | { 29 | if(array[i] < array[j]) 30 | temp[ k++ ] = array[ i++ ]; 31 | else 32 | temp[ k++ ] = array[ j++ ]; 33 | } 34 | 35 | while(i < middle) 36 | temp[ k++ ] = array[ i++ ]; 37 | 38 | while(j < stop) 39 | temp[ k++ ] = array[ j++ ]; 40 | 41 | for(int k = 0; k < stop - start; k++) 42 | array[start + k] = temp[k]; 43 | } 44 | -------------------------------------------------------------------------------- /binary_search/java/BinarySearch.java: -------------------------------------------------------------------------------- 1 | 2 | public class BinarySearch 3 | { 4 | public static int search(int[] array, int target) 5 | { 6 | int left = 0, right = array.length - 1, center = 0; 7 | while(left <= right) 8 | { 9 | center = left + (right - left) / 2; 10 | if(array[center] == target) 11 | return center; 12 | else if(array[center] < target) 13 | left = center + 1; 14 | else 15 | right = center - 1; 16 | } 17 | return -1; 18 | } 19 | public static int lower(int[] array, int target) 20 | { 21 | int left = 0, right = array.length - 1, center = 0; 22 | while(left <= right) 23 | { 24 | center = left + (right - left) / 2; 25 | if(array[center] == target) 26 | right = center - 1; 27 | else if(array[center] < target) 28 | left = center + 1; 29 | else 30 | right = center - 1; 31 | } 32 | return right; 33 | } 34 | public static int higher(int[] array, int target) 35 | { 36 | int left = 0, right = array.length - 1, center = 0; 37 | while(left <= right) 38 | { 39 | center = left + (right - left) / 2; 40 | if(array[center] == target) 41 | left = center + 1; 42 | if(array[center] < target) 43 | left = center + 1; 44 | else 45 | right = center - 1; 46 | } 47 | return left; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /trie/cxx/Trie.cxx: -------------------------------------------------------------------------------- 1 | #include "Trie.h" 2 | #include 3 | 4 | void Trie::insert(const std::string& word) 5 | { 6 | TrieNode* curr = root; 7 | for(int i = 0; i < word.length(); i++) 8 | { 9 | if(curr->children.find(word.at(i)) == curr->children.end()) 10 | curr->children.emplace(word.at(i), new TrieNode(word.at(i))); 11 | curr = curr->children[word.at(i)]; 12 | } 13 | curr->isLeaf = true; 14 | } 15 | 16 | bool Trie::search(const std::string& word) 17 | { 18 | TrieNode* curr = root; 19 | for(int i = 0; i < word.size(); i++) 20 | { 21 | if(curr->children.find(word[i]) == curr->children.end()) 22 | return false; 23 | curr = curr->children[word[i]]; 24 | } 25 | return curr->isLeaf == true; 26 | } 27 | 28 | bool Trie::startWith(const std::string& prefix) 29 | { 30 | TrieNode* curr = root; 31 | for(int i = 0; i < prefix.size(); i++) 32 | { 33 | if(curr->children.find(prefix[i]) == curr->children.end()) 34 | return false; 35 | curr = curr->children[prefix[i]]; 36 | } 37 | return true; 38 | } 39 | 40 | void Trie::deleteSubtree(TrieNode* root) 41 | { 42 | for(auto it = root->children.begin(); it != root->children.end(); it++) 43 | deleteSubtree(it->second); 44 | delete root; 45 | } 46 | 47 | Trie::~Trie() 48 | { 49 | deleteSubtree(this->root); 50 | } 51 | -------------------------------------------------------------------------------- /string/py3/TestStringMatcher.py: -------------------------------------------------------------------------------- 1 | from kmp_matcher import kmp_matcher 2 | from naive_matcher import naive_matcher 3 | import unittest 4 | import random 5 | from time import time 6 | 7 | class TestStringMathcer(unittest.TestCase): 8 | def __gen_str__(self, size): 9 | text = [] 10 | for i in range(size): 11 | rand_base = random.random() 12 | if rand_base < 0.25: 13 | text.append('A') 14 | elif rand_base < 0.50: 15 | text.append('T') 16 | elif rand_base < 0.75: 17 | text.append('C') 18 | else: 19 | text.append('G') 20 | return str().join(text) 21 | 22 | def __check_matcher__(self, matcher): 23 | time0 = time() 24 | for i in range(100): 25 | text = self.__gen_str__(10000) 26 | patt = self.__gen_str__(random.randrange(10, 50)) 27 | self.assertEqual(matcher(patt, text), text.find(patt)) 28 | time1 = time() 29 | print(time1 - time0, matcher) 30 | 31 | def testNaiveMatcher(self): 32 | self.__check_matcher__(naive_matcher) 33 | 34 | def testKMPMatcher(self): 35 | self.__check_matcher__(kmp_matcher) 36 | 37 | if __name__ == "__main__": 38 | unittest.main() 39 | -------------------------------------------------------------------------------- /string/perl/kmp_matcher.pm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | package kmp_matcher; 4 | 5 | use strict; 6 | use warnings; 7 | use Exporter; 8 | our @ISA = qw(Exporter); 9 | our @EXPORT = qw(kmp_matcher); 10 | 11 | sub get_char_at { 12 | my ($string, $index) = @_; 13 | return substr $string, $index, 1; 14 | } 15 | 16 | sub kmp_matcher { 17 | my ($text, $pattern) = @_; 18 | my @pi = compute_prefix_function($pattern); 19 | my $matched = 0; 20 | for(my $i = 0; $i < length($text); $i++) { 21 | while($matched > 0 and 22 | get_char_at($text, $i) ne get_char_at($pattern, $matched)) { 23 | $matched = $pi[$matched - 1]; 24 | } 25 | if(get_char_at($text, $i) eq get_char_at($pattern, $matched)) { 26 | $matched++; 27 | } 28 | if($matched == length($pattern)) { 29 | return $i - $matched + 1; 30 | } 31 | } 32 | return -1; 33 | } 34 | 35 | sub compute_prefix_function { 36 | my $pattern = shift; 37 | my @pi = (0); 38 | my $matched = 0; 39 | for(my $i = 1; $i < length($pattern); $i++) { 40 | while($matched > 0 and 41 | get_char_at($pattern, $i) ne get_char_at($pattern, $matched)) { 42 | $matched = $pi[$matched - 1]; 43 | } 44 | if(get_char_at($pattern, $i) eq get_char_at($pattern, $matched)) { 45 | $matched++; 46 | } 47 | $pi[$i] = $matched; 48 | } 49 | return @pi; 50 | } 51 | 52 | 1; 53 | -------------------------------------------------------------------------------- /binary_search/cxx/binary_search.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int binary_search(std::vector array, int target) 4 | { 5 | int left = 0, right = array.size() - 1, center; 6 | while(left <= right) 7 | { 8 | center = left + (right - left) / 2; 9 | if(array[center] == target) 10 | return center; 11 | else if(array[center] < target) 12 | left = center + 1; 13 | else 14 | right = center - 1; 15 | } 16 | return -1; 17 | } 18 | 19 | // Equivalent to "ceiling" or "bisect_left" 20 | int lower_bound(std::vector array, int target) 21 | { 22 | int left = 0, right = array.size() - 1, center; 23 | while(left <= right) 24 | { 25 | center = left + (right - left) / 2; 26 | if(array[center] == target) 27 | right = center - 1; 28 | else if(array[center] < target) 29 | left = center + 1; 30 | else 31 | right = center - 1; 32 | } 33 | return left; 34 | } 35 | 36 | // Equivalent to "higher" or "bisect" 37 | int upper_bound(std::vector array, int target) 38 | { 39 | int left = 0, right = array.size() - 1, center; 40 | while(left <= right) 41 | { 42 | center = left + (right - left) / 2; 43 | if(array[center] == target) 44 | left = center + 1; 45 | else if(array[center] < target) 46 | left = center + 1; 47 | else 48 | right = center - 1; 49 | } 50 | return left; 51 | } 52 | -------------------------------------------------------------------------------- /shortest_path/py3/TestSearch.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import random 3 | from random_graph import RandomGraph 4 | from bfs import bfs 5 | from bidirectional import bidirectional 6 | from iterative_deepening import iterative_deepening 7 | 8 | class TestSearch(unittest.TestCase): 9 | def setUp(self): 10 | self.randG = RandomGraph() 11 | 12 | def testBidirectional(self): 13 | for i in range(50): 14 | adjList = self.randG.randomGnmGraph(n=50, M=1000, isWeighted=False, isDirected=False) 15 | src = random.choice(list(adjList.keys())) 16 | dest = random.choice(list(adjList.keys())) 17 | dist1, prev1 = bfs(adjList, src) 18 | dist2, prev2 = bidirectional(adjList, src, dest) 19 | self.assertEqual(dist1[dest], dist2) 20 | 21 | def testIterativeDeepening(self): 22 | for i in range(50): 23 | adjList = self.randG.randomGnmGraph(n=50, M=1000, isWeighted=False, isDirected=False) 24 | src = random.choice(list(adjList.keys())) 25 | dest = random.choice(list(adjList.keys())) 26 | dist1, prev1 = bfs(adjList, src) 27 | dist2, prev2 = iterative_deepening(adjList, src, dest) 28 | self.assertEqual(dist1[dest], dist2[dest]) 29 | 30 | if __name__ == "__main__": 31 | unittest.main() 32 | -------------------------------------------------------------------------------- /disjoint_set/c/disjoint_set.c: -------------------------------------------------------------------------------- 1 | #include "disjoint_set.h" 2 | #include 3 | 4 | void disjoint_set_init(DisjointSet* ds, int n) 5 | { 6 | ds->height = (int*) malloc(sizeof(int) * n); 7 | ds->parent = (int*) malloc(sizeof(int) * n); 8 | int i; 9 | for(i = 0; i < n; i++) 10 | { 11 | ds->height[i] = 0; 12 | ds->parent[i] = i; 13 | } 14 | 15 | ds->findSet = disjoint_set_find; 16 | ds->unionSet = disjoint_set_union; 17 | ds->destroy = disjoint_set_destroy; 18 | } 19 | 20 | int disjoint_set_find(DisjointSet* ds, int elem) 21 | { 22 | if(ds->parent[elem] != elem) 23 | ds->parent[elem] = disjoint_set_find(ds, ds->parent[elem]); 24 | return ds->parent[elem]; 25 | } 26 | 27 | void disjoint_set_link(DisjointSet* ds, int root1, int root2) 28 | { 29 | if(ds->height[root1] > ds->height[root2]) 30 | ds->parent[root2] = root1; 31 | else 32 | { 33 | if(ds->height[root1] == ds->height[root2]) 34 | ds->height[root2]++; 35 | ds->parent[root1] = root2; 36 | } 37 | } 38 | 39 | void disjoint_set_union(DisjointSet* ds, int elem1, int elem2) 40 | { 41 | int root1 = disjoint_set_find(ds, elem1); 42 | int root2 = disjoint_set_find(ds, elem2); 43 | if(root1 != root2) 44 | disjoint_set_link(ds, root1, root2); 45 | } 46 | 47 | void disjoint_set_destroy(DisjointSet* ds) 48 | { 49 | free(ds->height); 50 | free(ds->parent); 51 | } 52 | -------------------------------------------------------------------------------- /graph/py3/TestBipartiteness.py: -------------------------------------------------------------------------------- 1 | import random 2 | import unittest 3 | from bipartiteness import is_bipartite 4 | 5 | class RandomGraph: 6 | def randomGnmGraph(self, n, M, isBipartite): 7 | adjList = { node: set() for node in range(n) } 8 | left = set(range(0, random.randrange(1, n))) 9 | if isBipartite and M > len(left) * (n - len(left)): 10 | raise ValueError("M > max edges in bipartite graph") 11 | cntEdge = 0 12 | while cntEdge < M: 13 | u, v = random.randrange(n), random.randrange(n) 14 | if v not in adjList[u] and u != v: 15 | if isBipartite and (u in left) == (v in left): 16 | continue 17 | adjList[u].add(v) 18 | adjList[v].add(u) 19 | cntEdge += 1 20 | return adjList 21 | 22 | class TestBipartiteness(unittest.TestCase): 23 | def testIsBipartite(self): 24 | gnm = RandomGraph() 25 | for _ in range(100): 26 | adjList = gnm.randomGnmGraph(50, 49, True) 27 | self.assertEqual(is_bipartite(adjList), True) 28 | 29 | for _ in range(100): 30 | adjList = gnm.randomGnmGraph(50, 1000, False) 31 | self.assertEqual(is_bipartite(adjList), False) 32 | 33 | if __name__ == "__main__": 34 | unittest.main() 35 | -------------------------------------------------------------------------------- /linked_list/c/list_merge_sort.c: -------------------------------------------------------------------------------- 1 | #include "list_merge_sort.h" 2 | #include "linked_list.h" 3 | #include 4 | 5 | static ListNode* find_middle(ListNode* head); 6 | 7 | ListNode* list_merge_sort(ListNode* head) 8 | { 9 | if(head == 0) 10 | return head; 11 | return list_m_sort(head); 12 | } 13 | 14 | ListNode* find_middle(ListNode* head) 15 | { 16 | ListNode *slow = head, *fast = head; 17 | while(fast->next && fast->next->next) 18 | { 19 | slow = slow->next; 20 | fast = fast->next->next; 21 | } 22 | return slow; 23 | } 24 | 25 | ListNode* list_m_sort(ListNode* head) 26 | { 27 | if(head->next == 0) 28 | return head; 29 | ListNode* slow = find_middle(head); 30 | ListNode* midd = slow->next; 31 | slow->next = 0; 32 | 33 | head = list_m_sort(head); 34 | midd = list_m_sort(midd); 35 | 36 | return list_merge(head, midd); 37 | } 38 | 39 | ListNode* list_merge(ListNode* l1, ListNode* l2) 40 | { 41 | ListNode* dummy = (ListNode*) malloc(sizeof(ListNode)); 42 | ListNode* curr = dummy; 43 | while(l1 && l2) 44 | { 45 | if(l1->val < l2->val) 46 | { 47 | curr->next = l1; 48 | l1 = l1->next; 49 | } 50 | else 51 | { 52 | curr->next = l2; 53 | l2 = l2->next; 54 | } 55 | curr = curr->next; 56 | } 57 | curr->next = l1 ? l1 : l2; 58 | curr = dummy->next; 59 | free(dummy); 60 | return curr; 61 | } 62 | -------------------------------------------------------------------------------- /heap/c/heap.c: -------------------------------------------------------------------------------- 1 | #include "../../vector/myvector.h" 2 | 3 | void perc_down(struct myvector* array, int i, int size) 4 | { 5 | int x = array->data[i]; 6 | int child; 7 | while(2 * i + 1 < size) 8 | { 9 | child = 2 * i + 1; 10 | if(child < size - 1 && array->data[child + 1] < array->data[child]) 11 | child++; 12 | if(array->data[child] < x) 13 | { 14 | array->data[i] = array->data[child]; 15 | i = child; 16 | } 17 | else 18 | break; 19 | } 20 | array->data[i] = x; 21 | } 22 | 23 | void heapify(struct myvector* array) 24 | { 25 | int i; 26 | for(i = array->size(array)/2; i >= 0; i--) 27 | perc_down(array, i, array->size(array)); 28 | } 29 | 30 | void heappush(struct myvector* array, int elem) 31 | { 32 | array->push_back(array, elem); 33 | int i = array->size(array) - 1; 34 | int parent, tmp; 35 | while(i > 0) 36 | { 37 | parent = (i - 1) / 2; 38 | if(array->data[i] < array->data[parent]) 39 | { 40 | tmp = array->data[i]; 41 | array->data[i] = array->data[parent]; 42 | array->data[parent] = array->data[i]; 43 | i = parent; 44 | } 45 | else 46 | break; 47 | } 48 | } 49 | 50 | int heappop(struct myvector* array) 51 | { 52 | int retval = array->data[0]; 53 | array->data[0] = array->back(array); 54 | array->pop_back(array); 55 | perc_down(array, 0, array->size(array)); 56 | return retval; 57 | } 58 | -------------------------------------------------------------------------------- /InterviewEssentials.md: -------------------------------------------------------------------------------- 1 | # Interview Essentials 2 | ## Data Structures 3 | * Binary Search Tree 4 | * Disjoint Set (Union-Find) 5 | * Trie 6 | 7 | ## Algorithms 8 | | Category | Algorithms | 9 | | ---------- | ------------ | 10 | | search | binary search | 11 | | sorting | merge sort, quick sort, k-way merge sort | 12 | | selection | quick select | 13 | | linked list | find middle, reverse linked list, cycle detection, merge sort | 14 | | tree | stack traversal | 15 | | shortest path | bfs, Bellman–Ford | 16 | | graph search | bidirectional | 17 | | topological sort | Kahn's, DFS-based, Viterbi shortest path | 18 | | recursion | permutations, combinations, subsets | 19 | | math | gcd | 20 | | majority | Boyer–Moore majority vote | 21 | | sampling | selection-rejection, reservoir sampling, weighted sampling | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /disjoint_set/go/disjointset.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // UNTESTED 4 | 5 | // DisjointSet is a ADT implemented with union-find algorithm 6 | type DisjointSet struct { 7 | parent map[int]int 8 | height map[int]int 9 | } 10 | 11 | // NewDisjointSet returns a initialized DisjointSet 12 | func NewDisjointSet() *DisjointSet { 13 | return &DisjointSet{ 14 | parent: make(map[int]int), 15 | height: make(map[int]int), 16 | } 17 | } 18 | 19 | // MakeSet adds elem as a set 20 | func (ds *DisjointSet) MakeSet(elem int) { 21 | ds.parent[elem] = elem 22 | ds.height[elem] = 1 23 | } 24 | 25 | // FindSet finds the set that elem belongs to 26 | func (ds *DisjointSet) FindSet(elem int) int { 27 | if ds.parent[elem] != elem { 28 | ds.parent[elem] = ds.FindSet(elem) 29 | } 30 | return ds.parent[elem] 31 | } 32 | 33 | // UnionSet joins two sets into one 34 | func (ds *DisjointSet) UnionSet(elem1, elem2 int) { 35 | root1, root2 := ds.FindSet(elem1), ds.FindSet(elem2) 36 | if root1 != root2 { 37 | ds.linkSet(root1, root2) 38 | } 39 | } 40 | 41 | func (ds *DisjointSet) linkSet(root1, root2 int) { 42 | if ds.height[root1] > ds.height[root2] { 43 | delete(ds.height, root2) 44 | ds.parent[root2] = root1 45 | } else { 46 | if ds.height[root1] == ds.height[root2] { 47 | ds.height[root2]++ 48 | } 49 | delete(ds.height, root1) 50 | ds.parent[root1] = root2 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /sampling/cxx/simple_random_sample.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | template 6 | std::vector draw_by_draw(std::vector& array, int k) 7 | { 8 | int index; 9 | for(int i = 0; i < k; i++) 10 | { 11 | index = rand() % (array.size() - i); 12 | std::swap(array[index], array[array.size() - 1 - i]); 13 | } 14 | return std::vector(array.begin() + array.size() - k, array.end()); 15 | } 16 | 17 | template 18 | std::vector selection_rejection(const std::vector& array, int k) 19 | { 20 | std::vector sample(k, 0); 21 | int cnt = 0, n = array.size(); 22 | for(const auto& elem: array) 23 | { 24 | if((float)rand() / RAND_MAX < (float)k / n) 25 | { 26 | sample[cnt++] = elem; 27 | k--; 28 | } 29 | n--; 30 | } 31 | return sample; 32 | } 33 | 34 | template 35 | std::vector reservoir_sampling(const std::vector& array, int k) 36 | { 37 | std::vector sample(k, 0); 38 | auto it = array.begin(); 39 | for(int i = 0; i < k; i++) 40 | { 41 | sample[i] = *it++; 42 | if(it == array.end()) 43 | return sample; 44 | } 45 | int n = k; 46 | int idx; 47 | while(it != array.end()) 48 | { 49 | n += 1; 50 | if((float)rand() / RAND_MAX < (float)k / n) 51 | { 52 | idx = rand() % k; 53 | sample[idx] = *it; 54 | } 55 | it++; 56 | } 57 | return sample; 58 | } 59 | -------------------------------------------------------------------------------- /segment_tree/c/test_segment_tree.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "rsq_segment_tree.h" 6 | 7 | void test_query() 8 | { 9 | const int size = 100; 10 | int array[size]; 11 | int i, j, left, right; 12 | int sum; 13 | for(i = 0; i < size; i++) 14 | array[i] = rand() % size; 15 | RSQSegmentTree* st = rsq_segment_tree_init(array, size); 16 | for(i = 0; i < size; i++) 17 | { 18 | left = rand() % (size / 2); 19 | right = rand() % size; 20 | sum = 0; 21 | for(j = left; j <= right; j++) 22 | sum += array[j]; 23 | assert(st->query(st, left, right) == sum); 24 | } 25 | st->destroy(st); 26 | } 27 | 28 | void test_update() 29 | { 30 | const int size = 100; 31 | int array[size]; 32 | int i, j, left, right; 33 | int sum; 34 | for(i = 0; i < size; i++) 35 | array[i] = rand() % size; 36 | RSQSegmentTree* st = rsq_segment_tree_init(array, size); 37 | 38 | int index = rand() % size, delta = -rand() % 50; 39 | array[index] += delta; 40 | st->update(st, index, delta); 41 | for(i = 0; i < size; i++) 42 | { 43 | left = rand() % (size / 2); 44 | right = rand() % size; 45 | sum = 0; 46 | for(j = left; j <= right; j++) 47 | sum += array[j]; 48 | assert(st->query(st, left, right) == sum); 49 | } 50 | st->destroy(st); 51 | } 52 | 53 | int main() 54 | { 55 | test_query(); 56 | test_update(); 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /selection/c/test_selection.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "quick_select.c" 5 | 6 | void perc_down(int* array, int i, int size) 7 | { 8 | int x, child; 9 | for(x = array[i]; 2*i+1 < size; i = child) 10 | { 11 | child = 2*i+1; 12 | if(child + 1 < size && array[child + 1] > array[child]) 13 | child++; 14 | if(array[child] > x) 15 | array[i] = array[child]; 16 | else 17 | break; 18 | } 19 | array[i] = x; 20 | } 21 | 22 | void heap_sort(int* array, const int n) 23 | { 24 | int i; 25 | for(i = n/2; i >= 0; i--) 26 | perc_down(array, i, n); 27 | 28 | for(i = n - 1; i > 0; i--) 29 | { 30 | swap(&array[0], &array[i]); 31 | perc_down(array, 0, i); 32 | } 33 | } 34 | 35 | int check_selection(int* array, int n, int rank, int retval) 36 | { 37 | heap_sort(array, n); 38 | return array[rank - 1] == retval; 39 | } 40 | 41 | int test_selection() 42 | { 43 | const int n = 5000; 44 | int array[n]; 45 | int i, j, rank, retval; 46 | for(i = 0; i < 1000; i++) 47 | { 48 | for(j = 0; j < n; j++) 49 | array[j] = rand() % (n * 2); 50 | rank = rand() % n + 1; 51 | retval = quick_select(array, n, rank); 52 | if(!check_selection(array, n, rank, retval)) 53 | return 0; 54 | } 55 | return 1; 56 | } 57 | 58 | int main() 59 | { 60 | srand(time(0)); 61 | if(!test_selection()) 62 | printf("WA: rand_select\n"); 63 | } 64 | -------------------------------------------------------------------------------- /binary_indexed_tree/c/binary_indexed_tree.c: -------------------------------------------------------------------------------- 1 | #include "binary_indexed_tree.h" 2 | #include 3 | #include 4 | 5 | BinaryIndexedTree* bit_init(int* array, int n) 6 | { 7 | BinaryIndexedTree*bit=(BinaryIndexedTree*)malloc(sizeof(BinaryIndexedTree)); 8 | bit->get_sum = bit_get_sum; 9 | bit->update = bit_update; 10 | bit->get_range = bit_get_range; 11 | bit->destroy = bit_destroy; 12 | 13 | bit->tree = (int*)malloc(sizeof(int) * (n + 1)); 14 | bit->treesz = n + 1; 15 | bit->tree[0] = 0; 16 | memcpy(bit->tree + 1, array, sizeof(int) * n); 17 | int i, j; 18 | for(i = 1; i < n + 1; i++) 19 | { 20 | j = i + (i & (-i)); 21 | if(j < bit->treesz) 22 | bit->tree[j] += bit->tree[i]; 23 | } 24 | return bit; 25 | } 26 | 27 | int bit_get_sum(BinaryIndexedTree* bit, int i) 28 | { 29 | i += 1; 30 | int sum = 0; 31 | while(i > 0) 32 | { 33 | sum += bit->tree[i]; 34 | i -= i & (-i); 35 | } 36 | return sum; 37 | } 38 | 39 | void bit_update(BinaryIndexedTree* bit, int i, int delta) 40 | { 41 | i += 1; 42 | while(i < bit->treesz) 43 | { 44 | bit->tree[i] += delta; 45 | i += i & (-i); 46 | } 47 | } 48 | 49 | int bit_get_range(BinaryIndexedTree* bit, int i, int j) 50 | { 51 | return bit_get_sum(bit, j) - bit_get_sum(bit, i - 1); 52 | } 53 | 54 | void bit_destroy(BinaryIndexedTree* bit) 55 | { 56 | free(bit->tree); 57 | bit->treesz = 0; 58 | free(bit); 59 | } 60 | -------------------------------------------------------------------------------- /traverse_tree/c/recursive_traversal.c: -------------------------------------------------------------------------------- 1 | #include "TreeNode.h" 2 | #include 3 | 4 | static int cnt = 0; 5 | static void preorder(struct TreeNode* root, int* result) 6 | { 7 | if(root) 8 | { 9 | result[cnt++] = root->val; 10 | preorder(root->left, result); 11 | preorder(root->right, result); 12 | } 13 | } 14 | 15 | int* recursive_preorder(struct TreeNode* root, int* returnSize) 16 | { 17 | int* result = (int*) malloc(sizeof(int) * (*returnSize)); 18 | cnt = 0; 19 | preorder(root, result); 20 | return result; 21 | } 22 | 23 | static void inorder(struct TreeNode* root, int* result) 24 | { 25 | if(root != NULL) 26 | { 27 | inorder(root->left, result++); 28 | result[cnt++] = root->val; 29 | inorder(root->right, result++); 30 | } 31 | } 32 | 33 | int* recursive_inorder(struct TreeNode* root, int* returnSize) 34 | { 35 | int* result = (int*) malloc(sizeof(int) * (*returnSize)); 36 | cnt = 0; 37 | inorder(root, result); 38 | return result; 39 | } 40 | 41 | static void postorder(struct TreeNode* root, int* result) 42 | { 43 | if(root) 44 | { 45 | postorder(root->left, result); 46 | postorder(root->right, result); 47 | result[cnt++] = root->val; 48 | } 49 | } 50 | 51 | int* postorderTravesal(struct TreeNode* root, int* returnSize) 52 | { 53 | int* result = (int*) malloc(sizeof(int) * (*returnSize)); 54 | cnt = 0; 55 | postorder(root, result); 56 | return result; 57 | } 58 | -------------------------------------------------------------------------------- /segment_tree/cxx/TestSegmentTree.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "RMQSegmentTree.h" 7 | 8 | void testQuery() 9 | { 10 | const int size = 100; 11 | std::vector array(size); 12 | int i, j, left, right; 13 | int minimum; 14 | for(i = 0; i < size; i++) 15 | array[i] = rand() % size; 16 | RMQSegmentTree rmq(array); 17 | for(i = 0; i < size; i++) 18 | { 19 | left = rand() % (size / 2); 20 | right = rand() % size; 21 | minimum = INT_MAX; 22 | for(j = left; j <= right; j++) 23 | if(array[j] < minimum) 24 | minimum = array[j]; 25 | assert(rmq.query(left, right) == minimum); 26 | } 27 | } 28 | 29 | void testUpdate() 30 | { 31 | const int size = 100; 32 | std::vector array(size); 33 | int i, j, left, right; 34 | int minimum; 35 | for(i = 0; i < size; i++) 36 | array[i] = rand() % size; 37 | RMQSegmentTree rmq(array); 38 | 39 | int index = rand() % size, delta = -rand() % 50; 40 | array[index] += delta; 41 | rmq.update(index, delta); 42 | for(i = 0; i < size; i++) 43 | { 44 | left = rand() % (size / 2); 45 | right = rand() % size; 46 | minimum = INT_MAX; 47 | for(j = left; j <= right; j++) 48 | if(array[j] < minimum) 49 | minimum = array[j]; 50 | assert(rmq.query(left, right) == minimum); 51 | } 52 | } 53 | 54 | int main() 55 | { 56 | testQuery(); 57 | testUpdate(); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /linked_list/cxx/list_merge_sort.cxx: -------------------------------------------------------------------------------- 1 | #include "list_merge_sort.h" 2 | #include "LinkedList.h" 3 | 4 | static ListNode* find_middle(ListNode* head); 5 | static ListNode* list_m_sort(ListNode* head); 6 | static ListNode* list_merge(ListNode* l1, ListNode* l2); 7 | 8 | ListNode* list_merge_sort(ListNode* head) 9 | { 10 | if(head == NULL) 11 | return head; 12 | return list_m_sort(head); 13 | } 14 | 15 | ListNode* find_middle(ListNode* head) 16 | { 17 | ListNode *slow = head, *fast = head; 18 | while(fast->next and fast->next->next) 19 | { 20 | slow = slow->next; 21 | fast = fast->next->next; 22 | } 23 | return slow; 24 | } 25 | 26 | ListNode* list_m_sort(ListNode* head) 27 | { 28 | if(head->next == NULL) 29 | return head; 30 | 31 | ListNode* slow = find_middle(head); 32 | ListNode* midd = slow->next; 33 | slow->next = NULL; 34 | 35 | head = list_m_sort(head); 36 | midd = list_m_sort(midd); 37 | return list_merge(head, midd); 38 | } 39 | 40 | ListNode* list_merge(ListNode* l1, ListNode* l2) 41 | { 42 | ListNode* dummy = new ListNode(-1); 43 | ListNode* curr = dummy; 44 | while(l1 and l2) 45 | { 46 | if(l1->val < l2->val) 47 | { 48 | curr->next = l1; 49 | l1 = l1->next; 50 | } 51 | else 52 | { 53 | curr->next = l2; 54 | l2 = l2->next; 55 | } 56 | curr = curr->next; 57 | } 58 | curr->next = l1 ? l1 : l2; 59 | curr = dummy->next; 60 | delete dummy; 61 | return curr; 62 | } 63 | -------------------------------------------------------------------------------- /sorting/go/quicksort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // TESTED on LeetCode 4 | 5 | // QuickSort sorts the array 6 | func QuickSort(nums []int) { 7 | qSort(nums, 0, len(nums)-1) 8 | } 9 | 10 | func qSort(nums []int, left, right int) { 11 | if right-left > 10 { 12 | center := partition(nums, left, right) 13 | qSort(nums, left, center-1) 14 | qSort(nums, center+1, right) 15 | } else { 16 | insertionSort(nums, left, right) 17 | } 18 | } 19 | 20 | func insertionSort(nums []int, left, right int) { 21 | var j, x int 22 | for i := left + 1; i < right+1; i++ { 23 | x = nums[i] 24 | for j = i - 1; j >= left && nums[j] > x; j-- { 25 | nums[j+1] = nums[j] 26 | } 27 | nums[j+1] = x 28 | } 29 | } 30 | 31 | func median3(nums []int, left, right int) int { 32 | center := left + (right-left)/2 33 | tmp := []int{nums[left], nums[center], nums[right]} 34 | insertionSort(tmp, 0, 2) 35 | nums[left], nums[center], nums[right] = tmp[0], tmp[2], tmp[1] 36 | return nums[right] 37 | } 38 | 39 | func partition(nums []int, left, right int) int { 40 | pivot := median3(nums, left, right) 41 | i, j := left+1, right-1 42 | for { 43 | for nums[i] < pivot { 44 | i++ 45 | } 46 | for pivot < nums[j] { 47 | j-- 48 | } 49 | // INVARIANT: nums[i] > pivot 50 | if i >= j { 51 | nums[i], nums[right] = nums[right], nums[i] 52 | return i 53 | } 54 | nums[i], nums[j] = nums[j], nums[i] 55 | i++ 56 | j-- 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /hashset/py3/TestHashSet.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import random 3 | from HashSet import HashSet 4 | 5 | class TestHashSet(unittest.TestCase): 6 | def setUp(self): 7 | self.size = 1000 8 | self.array = {random.randrange(self.size) for i in range(self.size)} 9 | self.set = HashSet() 10 | for elem in self.array: 11 | self.set.add(elem) 12 | 13 | def testAdd(self): 14 | self.array = range(self.size) 15 | self.set = HashSet() 16 | for i, elem in enumerate(self.array): 17 | self.assertEqual(len(self.set), i) 18 | self.set.add(elem) 19 | self.assertEqual(len(self.set), len(self.array)) 20 | 21 | def testContains(self): 22 | for elem in self.array: 23 | self.assertTrue(elem in self.set) 24 | 25 | def testRemove(self): 26 | for i, elem in enumerate(self.array): 27 | self.assertTrue(elem in self.set) 28 | self.assertEqual(len(self.array) - i, len(self.set)) 29 | self.set.remove(elem) 30 | self.assertEqual(len(self.array) - i - 1, len(self.set)) 31 | self.assertFalse(elem in self.set) 32 | 33 | def testClear(self): 34 | self.set.clear() 35 | for elem in self.array: 36 | self.assertFalse(elem in self.set) 37 | self.assertEqual(len(self.set), 0) 38 | 39 | if __name__ == '__main__': 40 | unittest.main() 41 | -------------------------------------------------------------------------------- /trie/java/Trie.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | 3 | public class Trie 4 | { 5 | public class TrieNode 6 | { 7 | public char character; 8 | public HashMap children; 9 | public boolean isLeaf; 10 | public TrieNode(char x) 11 | { 12 | character = x; 13 | children = new HashMap(); 14 | isLeaf = false; 15 | } 16 | } 17 | 18 | public TrieNode root; 19 | public Trie() 20 | { 21 | this.root = new TrieNode('!'); 22 | } 23 | public void insert(String word) 24 | { 25 | TrieNode root = this.root; 26 | for(int i = 0; i < word.length(); i++) 27 | { 28 | if(!root.children.containsKey(word.charAt(i))) 29 | root.children.put(word.charAt(i), new TrieNode(word.charAt(i))); 30 | root = root.children.get(word.charAt(i)); 31 | } 32 | root.isLeaf = true; 33 | } 34 | public boolean search(String word) 35 | { 36 | TrieNode root = this.root; 37 | for(int i = 0; i < word.length(); i++) 38 | { 39 | if(!root.children.containsKey(word.charAt(i))) 40 | return false; 41 | root = root.children.get(word.charAt(i)); 42 | } 43 | return root.isLeaf; 44 | } 45 | public boolean startWith(String prefix) 46 | { 47 | TrieNode root = this.root; 48 | for(int i = 0; i < prefix.length(); i++) 49 | { 50 | if(!root.children.containsKey(prefix.charAt(i))) 51 | return false; 52 | root = root.children.get(prefix.charAt(i)); 53 | } 54 | return true; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /shortest_path/py3/iterative_deepening.py: -------------------------------------------------------------------------------- 1 | def iterative_deepening(adjList, source, target, max_depth = 10000): 2 | for limit in range(1, max_depth + 1): 3 | result = depth_limited(adjList, source, target, limit) 4 | if result: 5 | return result 6 | 7 | def depth_limited(adjList, source, target, limit): 8 | stack = [(source, 0)] 9 | dist = {source: 0} 10 | prev = {source: None} 11 | while stack: 12 | node, level = stack.pop() 13 | if node is target: 14 | return dist, prev 15 | if level >= limit: 16 | continue 17 | for child in adjList[node]: 18 | stack.append((child, level + 1)) 19 | dist[child] = level + 1 20 | prev[child] = node 21 | return None 22 | 23 | # Verified 24 | def depth_limited_recursive(adjList, source, target, limit): 25 | def helper(source, target, limit, path, result): 26 | if source is target: 27 | result.append(list(path)) 28 | return result 29 | elif limit <= 0 or source in visited: 30 | return result 31 | visited.add(source) 32 | 33 | for child in adjList[source]: 34 | path.append(child) 35 | if helper(child, target, limit - 1, path, result): 36 | return result 37 | path.pop() 38 | return result 39 | visited = set() 40 | return helper(source, target, limit, [source], []) 41 | -------------------------------------------------------------------------------- /dp/py3/longest_common_subsequence.py: -------------------------------------------------------------------------------- 1 | # ** A sequence alignment problem ** 2 | # Find an alignment (non-crossing matching): n (or m) steps, for each character 3 | # find a matching character from the other string or skip it 4 | # OPT[i][j]: longest common subsequence in str1[:i] and str2[:j] 5 | # OPT[i][j] = max(OPT[i - 1][j - 1] + (s1[i - 1] == s2[j - 1]), OPT[i - 1][j], 6 | # OPT[i][j - 1]) 7 | # OPT[0][j] = 0 8 | # OPT[i][0] = 0 9 | # return OPT[n][m] 10 | # Time: O(mn) 11 | # Space: O(mn) 12 | def longest_common_subsequence(str1, str2): 13 | OPT = [[0] * (len(str2) + 1) for _ in range(len(str1) + 1)] 14 | for i in range(1, len(str1) + 1): 15 | for j in range(1, len(str2) + 1): 16 | OPT[i][j] = max(OPT[i - 1][j], OPT[i][j - 1], \ 17 | OPT[i - 1][j - 1] + (str1[i - 1] == str2[j - 1])) 18 | return OPT[-1][-1] 19 | 20 | def longest_common_subsequence_memo(str1, str2): 21 | def helper(end1, end2): 22 | if end1 == 0 or end2 == 0: 23 | return 0 24 | elif (end1, end2) in cache: 25 | return cache[(end1, end2)] 26 | cache[(end1, end2)] = max( 27 | helper(end1 - 1, end2 - 1) + (str1[end1 - 1] == str2[end2 - 1]), 28 | helper(end1 - 1, end2), 29 | helper(end1, end2 - 1)) 30 | return cache[(end1, end2)] 31 | cache = {} 32 | return helper(len(str1), len(str2)) 33 | -------------------------------------------------------------------------------- /traverse_tree/java/RecursiveTraversal.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.lang.Integer; 3 | import java.util.List; 4 | 5 | public class RecursiveTraversal implements TraversalMethods 6 | { 7 | public List preorderTraversal(TreeNode root) 8 | { 9 | List result = new ArrayList(); 10 | preorderHelper(root, result); 11 | return result; 12 | } 13 | private void preorderHelper(TreeNode root, List result) 14 | { 15 | if(root != null) 16 | { 17 | result.add(root.val); 18 | preorderHelper(root.left, result); 19 | preorderHelper(root.right, result); 20 | } 21 | } 22 | public List inorderTraversal(TreeNode root) 23 | { 24 | List result = new ArrayList(); 25 | inorderHelper(root, result); 26 | return result; 27 | } 28 | private void inorderHelper(TreeNode root, List result) 29 | { 30 | if(root != null) 31 | { 32 | inorderHelper(root.left, result); 33 | result.add(root.val); 34 | inorderHelper(root.right, result); 35 | } 36 | } 37 | public List postorderTraversal(TreeNode root) 38 | { 39 | List result = new ArrayList(); 40 | postorderHelper(root, result); 41 | return result; 42 | } 43 | private void postorderHelper(TreeNode root, List result) 44 | { 45 | if(root != null) 46 | { 47 | postorderHelper(root.left, result); 48 | postorderHelper(root.right, result); 49 | result.add(root.val); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /binary_indexed_tree/py3/TestBinaryIndexedTree.py: -------------------------------------------------------------------------------- 1 | from BinaryIndexedTree import BinaryIndexedTree 2 | from random import randrange 3 | import unittest 4 | 5 | class TestBinaryIndexedTree(unittest.TestCase): 6 | def testGetSum(self): 7 | array = [randrange(100) for i in range(100)] 8 | bit = BinaryIndexedTree(array) 9 | for cnt in range(100): 10 | i = randrange(100) 11 | self.assertEqual(sum(array[:i + 1]), bit.getSum(i)) 12 | 13 | def testUpdate(self): 14 | array = [randrange(100) for i in range(100)] 15 | bit = BinaryIndexedTree(array) 16 | for cnt in range(100): 17 | index, delta = randrange(100), randrange(-50, 50) 18 | array[index] += delta 19 | bit.update(index, delta) 20 | i = randrange(100) 21 | self.assertEqual(sum(array[:i + 1]), bit.getSum(i)) 22 | 23 | def testGetRange(self): 24 | array = [randrange(100) for i in range(100)] 25 | bit = BinaryIndexedTree(array) 26 | for cnt in range(100): 27 | i, j = randrange(50), randrange(50, 100) 28 | self.assertEqual(sum(array[i: j + 1]), bit.getRange(i, j)) 29 | 30 | def testBasic(self): 31 | array = [2, 1, 1, 3, 2, 3, 4, 5, 6, 7, 8, 9] 32 | bit = BinaryIndexedTree(array) 33 | expected = [0, 2, 3, 1, 7, 2, 5, 4, 21, 6, 13, 8, 30] 34 | self.assertEqual(bit.tree, expected) 35 | 36 | if __name__ == '__main__': 37 | unittest.main() 38 | -------------------------------------------------------------------------------- /sorting/cxx/radix_exchange_sort.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void radix_exchange_sort(std::vector& array); 6 | 7 | # define RADIX_EXCHANGE_BEGIN namespace radix_exchange { 8 | # define RADIX_EXCHANGE_END }; 9 | 10 | RADIX_EXCHANGE_BEGIN 11 | 12 | void r_sort(std::vector& array, int left, int right, int bitNo); 13 | int partition(std::vector& array, int left, int right, int mask); 14 | 15 | 16 | void r_sort(std::vector& array, int left, int right, int bitNo) 17 | { 18 | if(right > left and bitNo >= 0) 19 | { 20 | int center = partition(array, left, right, 1 << bitNo); 21 | r_sort(array, left, center - 1, bitNo - 1); 22 | r_sort(array, center, right, bitNo - 1); 23 | } 24 | } 25 | 26 | int partition(std::vector& array, int left, int right, int mask) 27 | { 28 | int i = left, j = right; 29 | while(true) 30 | { 31 | while((array[i] & mask) == 0 && i < j) i++; 32 | while((array[j] & mask) != 0 && i < j) j--; 33 | if(i >= j) 34 | { 35 | if((array[i] & mask) == 0) 36 | i++; 37 | return i; 38 | } 39 | std::swap(array[i++], array[j--]); 40 | } 41 | } 42 | 43 | RADIX_EXCHANGE_END 44 | 45 | void radix_exchange_sort(std::vector& array) 46 | { 47 | int signMask = 1 << (sizeof(int) * CHAR_BIT - 1); 48 | for(int& num: array) 49 | num ^= signMask; 50 | 51 | radix_exchange::r_sort(array, 0, array.size() - 1, sizeof(int) * CHAR_BIT - 1); 52 | 53 | for(int& num: array) 54 | num ^= signMask; 55 | } 56 | -------------------------------------------------------------------------------- /sampling/py3/TestSampling.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from collections import Counter 3 | from simple_random_sample import * 4 | from weightd_random_sample import weighted_random_sample 5 | 6 | class TestSampling(unittest.TestCase): 7 | def __test_srs__(self, algo, isIter): 8 | size = 10 9 | array = list(range(size)) 10 | cnt = Counter() 11 | times = 1000 12 | for i in range(times): 13 | if isIter: 14 | sample = algo(iter(array), size // 2) 15 | else: 16 | sample = algo(array, size // 2) 17 | self.assertEqual(len(sample), size // 2) 18 | for num in sample: 19 | cnt[num] += 1 20 | for num in array: 21 | self.assertGreater(cnt[num], 0.4 * times) 22 | self.assertLess(cnt[num], 0.6 * times) 23 | 24 | def testWeightedSampling(self): 25 | size = 1000 26 | for i in range(100): 27 | result = sum(weighted_random_sample([1, 2]) for i in range(size)) 28 | self.assertLessEqual(result, size * 0.72) 29 | self.assertGreaterEqual(result, size * 0.62) 30 | 31 | def testDrawByDraw(self): 32 | self.__test_srs__(draw_by_draw, False) 33 | 34 | def testSelectionRejection(self): 35 | self.__test_srs__(selection_rejection, False) 36 | 37 | def testReservoirSampling(self): 38 | self.__test_srs__(reservoir_sampling, True) 39 | 40 | if __name__ == "__main__": 41 | unittest.main() 42 | -------------------------------------------------------------------------------- /heap/java/Heap.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Collections; 3 | 4 | // Java PriorityQueue does not support heapify 5 | class Heap 6 | { 7 | public static > void percDown(ArrayList array, int i, int size) 8 | { 9 | T x = array.get(i); 10 | int child; 11 | while(2 * i + 1 < size) 12 | { 13 | child = 2 * i + 1; 14 | if(child + 1 < size && array.get(child + 1).compareTo(array.get(child)) < 0) 15 | child++; 16 | if(x.compareTo(array.get(child)) > 0) 17 | { 18 | array.set(i, array.get(child)); 19 | i = child; 20 | } 21 | else 22 | break; 23 | } 24 | array.set(i, x); 25 | } 26 | public static > void heapify(ArrayList array) 27 | { 28 | for(int i = array.size() / 2; i >= 0; i--) 29 | percDown(array, i, array.size()); 30 | } 31 | public static > void heappush(ArrayList array, T elem) 32 | { 33 | array.add(elem); 34 | int i = array.size() - 1; 35 | int parent; 36 | while(i > 0) 37 | { 38 | parent = (i - 1) / 2; 39 | if(array.get(i).compareTo(array.get(parent)) < 0) 40 | { 41 | Collections.swap(array, i, parent); 42 | i = parent; 43 | } 44 | else 45 | break; 46 | } 47 | } 48 | public static > T heappop(ArrayList array) 49 | { 50 | T retval = array.get(0); 51 | array.set(0, array.get(array.size() - 1)); 52 | array.remove(array.size() - 1); 53 | percDown(array, 0, array.size()); 54 | return retval; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /sampling/cxx/test_sampling.cxx: -------------------------------------------------------------------------------- 1 | #include "simple_random_sample.cxx" 2 | #include 3 | #include 4 | #include 5 | 6 | typedef std::vector (*SamplingFuncConst)(const std::vector&, int); 7 | typedef std::vector (*SamplingFunc)(std::vector&, int); 8 | 9 | void test_srs(SamplingFunc func) 10 | { 11 | const int SIZE = 10; 12 | std::vector array(SIZE, 0); 13 | for(int i = 0; i < array.size(); i++) 14 | array[i] = i; 15 | std::vector count(SIZE, 0); 16 | const int TIMES = 1000; 17 | for(int i = 0; i < TIMES; i++) 18 | { 19 | std::vector sample = func(array, SIZE / 2); 20 | for(const auto& num: sample) 21 | count[num] += 1; 22 | } 23 | for(int i = 0; i < SIZE; i++) 24 | { 25 | assert(0.4 * TIMES < count[i]); 26 | assert(count[i] < 0.6 * TIMES); 27 | } 28 | } 29 | 30 | void test_srs(SamplingFuncConst func) 31 | { 32 | const int SIZE = 10; 33 | std::vector array(SIZE, 0); 34 | for(int i = 0; i < array.size(); i++) 35 | array[i] = i; 36 | std::vector count(SIZE, 0); 37 | const int TIMES = 1000; 38 | for(int i = 0; i < TIMES; i++) 39 | { 40 | std::vector sample = func(array, SIZE / 2); 41 | for(const auto& num: sample) 42 | count[num] += 1; 43 | } 44 | for(int i = 0; i < SIZE; i++) 45 | { 46 | assert(0.4 * TIMES < count[i]); 47 | assert(count[i] < 0.6 * TIMES); 48 | } 49 | } 50 | 51 | int main() 52 | { 53 | test_srs(draw_by_draw); 54 | test_srs(selection_rejection); 55 | test_srs(reservoir_sampling); 56 | return 0 ; 57 | } 58 | -------------------------------------------------------------------------------- /majority_vote/cxx/majority_vote.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int majority_vote(const std::vector& nums) 6 | { 7 | int candy, count = 0; 8 | for(const auto& num: nums) 9 | { 10 | if(count == 0) 11 | { 12 | candy = num; 13 | count = 1; 14 | } 15 | else if(num == candy) 16 | count += 1; 17 | else 18 | count -= 1; 19 | } 20 | if(std::count(nums.begin(), nums.end(), candy) > nums.size() / 2) 21 | return candy; 22 | return -1; 23 | } 24 | 25 | std::vector majority_vote_general(const std::vector& nums, int k) 26 | { 27 | if(nums.size() < k) 28 | { 29 | std::vector result(nums); 30 | std::sort(result.begin(), result.end()); 31 | auto it = std::unique(result.begin(), result.end()); 32 | result.resize(std::distance(result.begin(), it)); 33 | return result; 34 | } 35 | std::unordered_map count; 36 | for(const auto& num: nums) 37 | { 38 | if(count.find(num) != count.end() or count.size() < k - 1) 39 | count[num]++; 40 | else 41 | { 42 | auto it = count.begin(); 43 | for(; it != count.end(); it++) 44 | if(it->second == 0) 45 | { 46 | count.erase(it); 47 | count[num] = 1; 48 | break; 49 | } 50 | if(it == count.end()) 51 | for(auto& item: count) 52 | item.second--; 53 | } 54 | } 55 | std::vector result; 56 | for(const auto& item: count) 57 | if(std::count(nums.begin(), nums.end(), item.first) > nums.size() / k) 58 | result.push_back(item.first); 59 | return result; 60 | } 61 | -------------------------------------------------------------------------------- /linked_list/py3/list_quick_sort.py: -------------------------------------------------------------------------------- 1 | from LinkedList import ListNode 2 | 3 | def median3(head): 4 | if head.next and head.next.next: 5 | return sorted([head.val, head.next.val, head.next.next.val])[1] 6 | return head.val 7 | 8 | def list_partition(head): 9 | pivot = median3(head) 10 | s_head = s_ptr = ListNode(float("-inf")) 11 | l_head = l_ptr = ListNode(float("-inf")) 12 | p_head = p_ptr = ListNode(float("-inf")) 13 | while head: 14 | if head.val < pivot: 15 | s_ptr.next = head 16 | s_ptr = s_ptr.next 17 | elif head.val > pivot: 18 | l_ptr.next = head 19 | l_ptr = l_ptr.next 20 | else: 21 | p_ptr.next = head 22 | p_ptr = p_ptr.next 23 | head = head.next 24 | s_ptr.next, l_ptr.next, p_ptr.next = None, None, None 25 | return s_head.next, l_head.next, p_head.next, p_ptr 26 | 27 | 28 | def list_q_sort(head): 29 | if head and head.next: 30 | left, center, pivot_start, pivot_end = list_partition(head) 31 | head, tail = pivot_start, pivot_end 32 | if left: 33 | small_start, small_end = list_q_sort(left) 34 | head = small_start 35 | small_end.next = pivot_start 36 | if center: 37 | large_start, large_end = list_q_sort(center) 38 | tail = large_end 39 | pivot_end.next = large_start 40 | return head, tail 41 | 42 | return head, head 43 | 44 | def list_quick_sort(head): 45 | return list_q_sort(head)[0] 46 | -------------------------------------------------------------------------------- /selection/go/quickselect.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // TESTED on LeetCode 4 | 5 | // QuickSelect returns the k'th largest number in the array 6 | func QuickSelect(nums []int, rank int) int { 7 | qSelect(nums, 0, len(nums)-1, rank-1) 8 | return nums[rank-1] 9 | } 10 | 11 | func qSelect(nums []int, left, right, rank int) { 12 | if right-left < 10 { 13 | insertionSort(nums, left, right) 14 | return 15 | } 16 | center := partition(nums, left, right) 17 | if rank < center { 18 | qSelect(nums, left, center-1, rank) 19 | } else if rank > center { 20 | qSelect(nums, center+1, right, rank) 21 | } 22 | } 23 | 24 | func insertionSort(nums []int, left, right int) { 25 | var j, x int 26 | for i := left + 1; i < right+1; i++ { 27 | x = nums[i] 28 | for j = i - 1; j >= left && nums[j] > x; j-- { 29 | nums[j+1] = nums[j] 30 | } 31 | nums[j+1] = x 32 | } 33 | } 34 | 35 | func median3(nums []int, left, right int) int { 36 | center := left + (right-left)/2 37 | tmp := []int{nums[left], nums[center], nums[right]} 38 | insertionSort(tmp, 0, 2) 39 | nums[left], nums[center], nums[right] = tmp[0], tmp[2], tmp[1] 40 | return nums[right] 41 | } 42 | 43 | func partition(nums []int, left, right int) int { 44 | pivot := median3(nums, left, right) 45 | var i, j int = left + 1, right - 1 46 | for { 47 | for nums[i] < pivot { 48 | i++ 49 | } 50 | for pivot < nums[j] { 51 | j-- 52 | } 53 | if i >= j { 54 | nums[i], nums[right] = nums[right], nums[i] 55 | return i 56 | } 57 | nums[i], nums[j] = nums[j], nums[i] 58 | i++ 59 | j-- 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /dp/py3/sequence_alignment.py: -------------------------------------------------------------------------------- 1 | # Find an alignment (non-crossing matching): n (or m) steps, for each character 2 | # choose a character from the other string to match or take the gap penalty 3 | # OPT[i][j]: minimum cost alignment between X[:i] and Y[:j] 4 | # OPT[i][j] = min(alpha[X[i]][Y[j]] + OPT[i - 1][j - 1], delta + OPT[i - 1][j], 5 | # delta + OPT[i][j - 1]) 6 | # OPT[i][0] = 0 7 | # OPT[0][j] = 0 8 | # return OPT[m][n] 9 | # Time: O(mn) 10 | # Space: O(mn) 11 | def sequence_alignment(X, Y, delta, alpha): 12 | OPT = [[0] * (len(Y) + 1) for _ in range(len(X) + 1)] 13 | for i in range(1, len(X) + 1): 14 | OPT[i][0] = i * delta 15 | for j in range(1, len(Y) + 1): 16 | OPT[0][j] = j * delta 17 | for i in range(1, len(X) + 1): 18 | for j in range(1, len(Y) + 1): 19 | OPT[i][j] = min(alpha[X[i - 1]][Y[j - 1]] + OPT[i - 1][j - 1], \ 20 | delta + OPT[i - 1][j], \ 21 | delta + OPT[i][j - 1]) 22 | return OPT[len(X)][len(Y)] 23 | 24 | def sequence_alignment_memo(X, Y, delta, alpha): 25 | def helper(i, j): 26 | if (i, j) in cache: 27 | return cache[(i, j)] 28 | elif i == 0 or j == 0: 29 | return (i or j) * delta 30 | cost = min(alpha[X[i - 1]][Y[j - 1]] + helper(i - 1, j - 1), \ 31 | delta + helper(i - 1, j), \ 32 | delta + helper(i, j - 1)) 33 | cache[(i, j)] = cost 34 | return cache[(i, j)] 35 | cache = {} 36 | return helper(len(X), len(Y)) 37 | -------------------------------------------------------------------------------- /dp/py3/TestSubsetSum.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import random 3 | from subset_sum import * 4 | 5 | def subsetsSums(nums): 6 | def helper(start, summ, result): 7 | result.append(summ) 8 | for i in range(start, len(nums)): 9 | helper(i + 1, summ + nums[i], result) 10 | return result 11 | return helper(0, 0, []) 12 | 13 | def subsetSumHaomo(nums, capacity): 14 | middle = len(nums) // 2 15 | left, right = nums[:middle], nums[middle:] 16 | sumsLeft, sumsRight = subsetsSums(left), subsetsSums(right) 17 | sumsRight.sort() 18 | import bisect 19 | maximum = 0 20 | for sumLeft in sumsLeft: 21 | higher = bisect.bisect(sumsRight, capacity - sumLeft) 22 | if higher == 0: 23 | continue 24 | floor = higher - 1 25 | if sumLeft + sumsRight[floor] > maximum: 26 | maximum = sumLeft + sumsRight[floor] 27 | return maximum 28 | 29 | class TestSubsetSum(unittest.TestCase): 30 | def __gen_cases__(self): 31 | nums = [random.randrange(100) for i in range(25)] 32 | capacity = random.randrange(sum(nums)) 33 | return nums, capacity 34 | 35 | def testSubsetSum(self): 36 | for i in range(30): 37 | nums, capacity = self.__gen_cases__() 38 | max0 = subsetSumHaomo(nums, capacity) 39 | max1 = subset_sum(nums, capacity) 40 | max2 = subset_sum_memoization(nums, capacity) 41 | self.assertEqual(max0, max1) 42 | self.assertEqual(max0, max2) 43 | 44 | if __name__ == "__main__": 45 | unittest.main() 46 | -------------------------------------------------------------------------------- /heap/py3/TestHeap.py: -------------------------------------------------------------------------------- 1 | from heap import heapify, heappush, heappop, heappushpop 2 | import unittest 3 | import random 4 | 5 | class TestHeap(unittest.TestCase): 6 | def checkHeapProperty(self, heap): 7 | for i in range(1, len(heap)): 8 | parent = (i - 1) // 2 9 | self.assertGreaterEqual(heap[i], heap[parent]) 10 | 11 | def testHeapify(self): 12 | size = 100 13 | array = [random.randrange(size) for i in range(size)] 14 | copy = sorted(array) 15 | heapify(array) 16 | self.checkHeapProperty(array) 17 | for elem in copy: 18 | self.assertEqual(heappop(array), elem) 19 | 20 | def testHeappush(self): 21 | size = 100 22 | array = [random.randrange(size) for i in range(size)] 23 | copy = sorted(array) 24 | heap = [] 25 | for elem in array: 26 | heappush(heap, elem) 27 | self.checkHeapProperty(heap) 28 | for elem in copy: 29 | self.assertEqual(heappop(heap), elem) 30 | 31 | def testHeappushpop(self): 32 | size = 100 33 | array = [random.randrange(size) for i in range(size)] 34 | copy = sorted(array) 35 | heapify(array) 36 | self.checkHeapProperty(array) 37 | for i in range(100): 38 | elem = random.randrange(size) 39 | minimum = min(array + [elem]) 40 | self.assertEqual(heappushpop(array, elem), minimum) 41 | self.assertEqual(len(array), size) 42 | self.checkHeapProperty(array) 43 | 44 | if __name__ == "__main__": 45 | unittest.main() 46 | -------------------------------------------------------------------------------- /segment_tree/java/TestRMQSegmentTree.java: -------------------------------------------------------------------------------- 1 | import java.util.Random; 2 | 3 | public class TestRMQSegmentTree 4 | { 5 | private static Random myrand = new Random(); 6 | public static void testQuery() 7 | { 8 | final int size = 100; 9 | int[] array = new int[size]; 10 | int left, right; 11 | int minimum; 12 | for(int i = 0; i < size; i++) 13 | array[i] = myrand.nextInt(size); 14 | RMQSegmentTree rmq = new RMQSegmentTree(array); 15 | for(int i = 0; i < size; i++) 16 | { 17 | left = myrand.nextInt(size / 2); 18 | right = myrand.nextInt(size); 19 | minimum = Integer.MAX_VALUE; 20 | for(int j = left; j <= right; j++) 21 | if(array[j] < minimum) 22 | minimum = array[j]; 23 | assert rmq.query(left, right) == minimum; 24 | } 25 | } 26 | public static void testUpdate() 27 | { 28 | final int size = 100; 29 | int[] array = new int[size]; 30 | int left, right; 31 | int minimum; 32 | for(int i = 0; i < size; i++) 33 | array[i] = myrand.nextInt(size); 34 | RMQSegmentTree rmq = new RMQSegmentTree(array); 35 | 36 | int index = myrand.nextInt(size), delta = -myrand.nextInt(50); 37 | array[index] += delta; 38 | rmq.update(index, delta); 39 | for(int i = 0; i < size; i++) 40 | { 41 | left = myrand.nextInt(size / 2); 42 | right = myrand.nextInt(size); 43 | minimum = Integer.MAX_VALUE; 44 | for(int j = left; j <= right; j++) 45 | if(array[j] < minimum) 46 | minimum = array[j]; 47 | assert rmq.query(left, right) == minimum; 48 | } 49 | } 50 | public static void main(String[] args) 51 | { 52 | testQuery(); 53 | testUpdate(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /mst/py3/kruskal.py: -------------------------------------------------------------------------------- 1 | # Time: O(E + V log(E)) 2 | import heapq 3 | 4 | def kruskal(n, edges): 5 | dset = DisjointSet(range(n)) 6 | edges = [(w, u, v) for u, v, w in edges] 7 | heapq.heapify(edges) 8 | result = [] 9 | while len(dset) > 1: 10 | w, u, v = heapq.heappop(edges) 11 | if dset.find_set(u) != dset.find_set(v): 12 | result.append((u, v)) 13 | dset.union(u, v) 14 | return result 15 | 16 | class DisjointSet: 17 | def __init__(self, elems = []): 18 | self.parent = { elem: elem for elem in elems } 19 | self.height = { elem: 1 for elem in elems } 20 | 21 | def make_set(self, elem): 22 | self.parent[elem] = elem 23 | self.height[elem] = 1 24 | 25 | def find_set(self, elem): 26 | if self.parent[elem] != elem: 27 | self.parent[elem] = self.find_set(self.parent[elem]) 28 | return self.parent[elem] 29 | 30 | def union(self, elem1, elem2): 31 | root1, root2 = self.find_set(elem1), self.find_set(elem2) 32 | if root1 != root2: 33 | self.link(root1, root2) 34 | 35 | def link(self, root1, root2): 36 | if self.height[root1] > self.height[root2]: 37 | self.parent[root2] = root1 38 | self.height.pop(root2) 39 | else: 40 | # When same height, link root1 to root2 41 | if self.height[root1] == self.height[root2]: 42 | self.height[root2] += 1 43 | self.parent[root1] = root2 44 | self.height.pop(root1) 45 | 46 | def __len__(self): 47 | return len(self.height) 48 | -------------------------------------------------------------------------------- /sorting/java/QuickSort.java: -------------------------------------------------------------------------------- 1 | 2 | public class QuickSort implements SortAlgorithm 3 | { 4 | public void insertionSort(int[] array, int left, int right) 5 | { 6 | int j; 7 | for(int i = left + 1; i < right + 1; i++) 8 | { 9 | int x = array[i]; 10 | for(j = i - 1; j >= left; j--) 11 | if(array[j] > x) 12 | array[j + 1] = array[j]; 13 | else 14 | break; 15 | array[j + 1] = x; 16 | } 17 | } 18 | public void sort(int[] array) 19 | { 20 | q_sort(array, 0, array.length - 1); 21 | } 22 | private void q_sort(int[] array, int left, int right) 23 | { 24 | if(right - left > 10) 25 | { 26 | int center = partition(array, left, right); 27 | q_sort(array, left, center - 1); 28 | q_sort(array, center + 1, right); 29 | } 30 | else 31 | insertionSort(array, left, right); 32 | } 33 | private int partition(int[] array, int left, int right) 34 | { 35 | int pivot = median3(array, left, right); 36 | int i = left + 1, j = right - 1; 37 | while(true) 38 | { 39 | while(array[i] < pivot) i++; 40 | while(pivot < array[j]) j--; 41 | if(i >= j) 42 | { 43 | array[i] = array[right] ^ array[i] ^ (array[right] = array[i]); 44 | return i; 45 | } 46 | array[i] = array[j] ^ array[i] ^ (array[j] = array[i]); 47 | i++; j--; 48 | } 49 | } 50 | private int median3(int[] array, int left, int right) 51 | { 52 | int center = (left + right) / 2; 53 | int[] tmp = { array[left], array[center], array[right] }; 54 | insertionSort(tmp, 0, 2); 55 | array[left] = tmp[0]; 56 | array[center] = tmp[2]; 57 | array[right] = tmp[1]; 58 | return array[right]; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /sorting/py3/TestSortImpl.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | from random import randrange 3 | import time 4 | import random 5 | import unittest 6 | 7 | from bubble_sort import bubble_sort 8 | from insertion_sort import insertion_sort 9 | from selection_sort import selection_sort 10 | from merge_sort import merge_sort 11 | from heap_sort import heap_sort 12 | from quick_sort_lomuto import quick_sort_lomuto 13 | from quick_sort import quick_sort 14 | 15 | class TestSortImpl(unittest.TestCase): 16 | def __check_sort_impl__(self, sort_algo): 17 | time1 = time.time() 18 | for i in range(10): 19 | size = random.randrange(1000, 2000) 20 | array = [random.randrange(size) for i in range(size)] 21 | copy = list(array) 22 | copy.sort() 23 | sort_algo(array) 24 | self.assertEqual(array, copy) 25 | time2 = time.time() 26 | print(sort_algo, time2 - time1) 27 | 28 | def testBubbleSort(self): 29 | self.__check_sort_impl__(bubble_sort) 30 | 31 | def testInsertionSort(self): 32 | self.__check_sort_impl__(insertion_sort) 33 | 34 | def testSelectionSort(self): 35 | self.__check_sort_impl__(selection_sort) 36 | 37 | def testMergeSort(self): 38 | self.__check_sort_impl__(merge_sort) 39 | 40 | def testHeapSort(self): 41 | self.__check_sort_impl__(heap_sort) 42 | 43 | def testQuickSortLomuto(self): 44 | self.__check_sort_impl__(quick_sort_lomuto) 45 | 46 | def testQuickSort(self): 47 | self.__check_sort_impl__(quick_sort) 48 | 49 | if __name__ == '__main__': 50 | unittest.main() 51 | -------------------------------------------------------------------------------- /stack/py3/TestNextGreater.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import random 3 | from next_greater import * 4 | 5 | class TestNextGreater(unittest.TestCase): 6 | def __gen_case__(self): 7 | return [random.randrange(70) for i in range(100)] 8 | 9 | def naiveNextGreater(self, nums): 10 | greater = [float("inf")] * len(nums) 11 | for i, num in enumerate(nums): 12 | for j in range(i + 1, len(nums)): 13 | if nums[j] > nums[i]: 14 | greater[i] = nums[j] 15 | break 16 | return greater 17 | 18 | def naiveNextGtLastGe(self, nums): 19 | nGt = self.naiveNextGreater(nums) 20 | lGe = [float("inf")] * len(nums) 21 | for i, num in enumerate(nums): 22 | for j in range(i - 1, -1, -1): 23 | if nums[j] >= nums[i]: 24 | lGe[i] = nums[j] 25 | break 26 | return nGt, lGe 27 | 28 | def testNextGreater(self): 29 | for _ in range(100): 30 | nums = self.__gen_case__() 31 | g1 = self.naiveNextGreater(nums) 32 | g2 = next_greater(nums) 33 | g3 = next_greater_reverse(nums) 34 | self.assertEqual(g1, g2) 35 | self.assertEqual(g1, g3) 36 | 37 | def testCombined(self): 38 | for _ in range(100): 39 | nums = self.__gen_case__() 40 | nGt1, lGe1 = self.naiveNextGtLastGe(nums) 41 | nGt2, lGe2 = next_gt_last_ge(nums) 42 | self.assertEqual(nGt1, nGt2) 43 | self.assertEqual(lGe1, lGe2) 44 | 45 | if __name__ == "__main__": 46 | unittest.main() 47 | -------------------------------------------------------------------------------- /trie/cxx/TestTrie.cxx: -------------------------------------------------------------------------------- 1 | #include "Trie.h" 2 | 3 | #include 4 | #include 5 | 6 | void test_insert_search() 7 | { 8 | string setA[] = { "A", "a", "aa", "aal", "aalii", "aam", "Aani", 9 | "aardvark", "aardwolf", "Aaron", "Aaronic", "Aaronical", "Aaronite", 10 | "Aaronitic", "Aaru", "Ab", "aba", "Ababdeh", "Ababua", "abac", "abaca", 11 | "abacate", "abacay", "abacinate" 12 | }; 13 | string setB[] = { "B", "b", "ba", "baa", "baahling", "Baal", "baal", 14 | "Baalath", "Baalish", "Baalism", "Baalist", "Baalite", "Baalitical", 15 | "Baalize", "Baalshem", "baar", "Bab", "baba", "babacoote", "babai", 16 | "babasco", "babassu", "babaylan", "Babbie" 17 | }; 18 | Trie trie; 19 | for(const string& word: setA) 20 | trie.insert(word); 21 | for(const string& word: setA) 22 | assert(trie.search(word)); 23 | for(const string& word: setB) 24 | assert(not trie.search(word)); 25 | } 26 | 27 | void test_start_with() 28 | { 29 | std::string words[] = { "aalii", "aam", "Aani", "aardvark", "aardwolf", 30 | "Aaronic", "Aaronite", "Aaronitic", "Aaru", "Ababdeh", "Ababua", 31 | "abacay", "abacinate" 32 | }; 33 | std::string prefixes[] = {"A","a","aa","aal","Aaron","Ab","aba","abac"}; 34 | std::string others[] = { 35 | "abaciscus","abacist","aback","abactinal","Abe","abaction" 36 | }; 37 | Trie trie; 38 | for(const string& word: words) 39 | trie.insert(word); 40 | for(const string& prefix: prefixes) 41 | assert(trie.startWith(prefix)); 42 | for(const string& word: others) 43 | assert(not trie.startWith(word)); 44 | } 45 | 46 | int main() 47 | { 48 | test_insert_search(); 49 | test_start_with(); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /traverse_tree/py3/TreeNode.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | # Definition for a binary tree node. 4 | class TreeNode(object): 5 | def __init__(self, x): 6 | self.val = x 7 | self.left = None 8 | self.right = None 9 | 10 | class Codec: 11 | def serialize(self, root): 12 | """Encodes a tree to a single string. 13 | 14 | :type root: TreeNode 15 | :rtype: str 16 | """ 17 | ret = [] 18 | queue = deque([root]) 19 | while any(queue): 20 | node = queue.popleft() 21 | if node is None: 22 | ret.append("null") 23 | continue 24 | ret.append(str(node.val)) 25 | queue.append(node.left) 26 | queue.append(node.right) 27 | return ",".join(ret) 28 | 29 | def deserialize(self, data): 30 | """Decodes your encoded data to tree. 31 | 32 | :type data: str 33 | :rtype: TreeNode 34 | """ 35 | if not data: 36 | return None 37 | data = data.split(',') 38 | root = TreeNode(data[0]) 39 | queue = deque([(root, 0)]) 40 | while queue: 41 | node, index = queue.popleft() 42 | ileft, iright = index * 2 + 1, index * 2 + 2 43 | if ileft < len(data) and data != "null": 44 | node.left = TreeNode(data[ileft]) 45 | queue.append((node.left, ileft)) 46 | if iright < len(data) and data != "null": 47 | node.right = TreeNode(data[iright]) 48 | queue.append((node.right, iright)) 49 | return root 50 | -------------------------------------------------------------------------------- /dutch_national_flag/py3/three_way_partition.py: -------------------------------------------------------------------------------- 1 | # Dijkstra three way partition 2 | # Time : O(n) 3 | # Space: O(1) 4 | # 5 | # 0 0 0 1 1 0 2 0 1 2 2 6 | # ^ i $ 7 | # Invariant: array[:head] all 0, array[head: i] all 1, array[tail + 1:] all 2 8 | 9 | def isHead(elem): 10 | return elem == 0 11 | 12 | def isTail(elem): 13 | return elem == 2 14 | 15 | def three_way_partition(array, is_head = isHead, is_tail = isTail): 16 | """ Dijkstra, 1976 """ 17 | head, tail = 0, len(array) - 1 18 | i = 0 19 | while i <= tail: 20 | if is_head(array[i]): 21 | array[i], array[head] = array[head], array[i] 22 | head += 1 23 | i += 1 24 | elif is_tail(array[i]): 25 | array[i], array[tail] = array[tail], array[i] 26 | tail -= 1 27 | else: 28 | i += 1 29 | 30 | # Compared to lumoto quick sort two way partition 31 | # def three_way_partition(array): def two_way_partition(array): 32 | # head, tail = 0, len(array) - 1 head = 0 33 | # i = 0 i = 0 34 | # while i <= tail: while i <= len(array) - 1: 35 | # if array[i] == 0: if array[i] == 0: 36 | # array[i], array[head] = array[head], array[i] array[head], array[i] = array[i], array[head] 37 | # head += 1 head += 1 38 | # i += 1 39 | # elif array[i] == 2: 40 | # array[i], array[tail] = array[tail], array[i] 41 | # tail -= 1 42 | # else: 43 | # i += 1 44 | -------------------------------------------------------------------------------- /dp/py3/TestWeightedIntervalScheduling.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import random 3 | from weighted_interval_scheduling import * 4 | 5 | class TestWeightedIntervalScheduling(unittest.TestCase): 6 | def __gen_cases__(self, n): 7 | cases = [] 8 | for i in range(n): 9 | intervals = [] 10 | for i in range(1000): 11 | startTime = random.randrange(1000) 12 | endTime = random.randrange(startTime + 1, startTime + 21) 13 | value = random.randrange(30) 14 | interval = (startTime, endTime, value) 15 | intervals.append(interval) 16 | intervals.sort(key=lambda interval: interval[1]) 17 | case = zip(*intervals) 18 | cases.append(case) 19 | return cases 20 | 21 | def testComputeOPT(self): 22 | cases = self.__gen_cases__(100) 23 | for case in cases: 24 | startTimes, endTimes, values = case 25 | max1 = weighted_interval_scheduling(startTimes, endTimes, values) 26 | max2 = weighted_interval_scheduling_memo(startTimes, endTimes, values) 27 | self.assertEqual(max1, max2) 28 | 29 | def testFindSolution(self): 30 | cases = self.__gen_cases__(100) 31 | for case in cases: 32 | startTimes, endTimes, values = case 33 | sol1, max1 = weighted_interval_scheduling_sol(startTimes, endTimes, values) 34 | sol2, max2 = weighted_interval_scheduling_memo_sol(startTimes, endTimes, values) 35 | self.assertEqual(max1, max2) 36 | self.assertEqual(set(sol1), set(sol2)) 37 | 38 | if __name__ == "__main__": 39 | unittest.main() 40 | -------------------------------------------------------------------------------- /disjoint_set/scala/DisjointSet.scala: -------------------------------------------------------------------------------- 1 | import collection.mutable 2 | import collection.immutable 3 | 4 | class DisjointSet[T](elems: Iterable[T]) { 5 | val height = new mutable.HashMap[T, Int]() 6 | val parent = new mutable.HashMap[T, T]() 7 | for(elem <- elems) { 8 | parent(elem) = elem; 9 | height(elem) = 1 10 | } 11 | 12 | def makeSet(elem: T) { 13 | parent(elem) = elem; 14 | height(elem) = 1 15 | } 16 | def findSet(elem: T): T = { 17 | if(parent(elem) != elem) 18 | parent(elem) = findSet(parent(elem)) 19 | return parent(elem) 20 | } 21 | def union(elemA: T, elemB: T) { 22 | val rootA: T = parent(elemA) 23 | val rootB: T = parent(elemB) 24 | if(rootA != rootB) 25 | link(rootA, rootB) 26 | } 27 | def link(rootA: T, rootB: T) { 28 | if(height(rootA) > height(rootB)) { 29 | parent(rootB) = rootA 30 | height.remove(rootB) 31 | } else { 32 | if(height(rootA) == height(rootB)) 33 | height(rootB) += 1 34 | height.remove(rootA) 35 | parent(rootA) = rootB 36 | } 37 | } 38 | def count(): Int = { 39 | return height.size 40 | } 41 | def clear() { 42 | height.clear() 43 | parent.clear() 44 | } 45 | def partition(): immutable.Iterable[Seq[T]] = { 46 | val mapping = mutable.HashMap[T, mutable.ArrayBuffer[T]]().empty 47 | for((elem, daddy) <- parent) { 48 | val repr = findSet(elem) 49 | if(!mapping.contains(repr)) 50 | mapping(repr) = new mutable.ArrayBuffer[T]() 51 | mapping(repr) += elem 52 | } 53 | val parts = immutable.Iterable[Seq[T]]() ++ mapping 54 | .values 55 | .map(_.toSeq) 56 | return parts 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /dp/py3/TestKnapsack.py: -------------------------------------------------------------------------------- 1 | import random 2 | import time 3 | import unittest 4 | from knapsack import * 5 | 6 | class TestKnapsack(unittest.TestCase): 7 | def setUp(self): 8 | self.cases = [] 9 | for i in range(50): 10 | nItems = random.randrange(40, 61) 11 | capacity = random.randrange(100, 301) 12 | weights = [random.randint(1, 11) for _ in range(nItems)] 13 | values = [random.randint(10, 101) for _ in range(nItems)] 14 | self.cases.append([weights, values, capacity]) 15 | 16 | def testKnapsackResult(self): 17 | for weights, values, capacity in self.cases: 18 | max1 = knapsack(weights, values, capacity) 19 | max2 = knapsack_two_rows(weights, values, capacity) 20 | max3 = knapsack_one_row(weights, values, capacity) 21 | max4 = knapsack_memo(weights, values, capacity) 22 | self.assertEqual(max1, max2) 23 | self.assertEqual(max1, max3) 24 | self.assertEqual(max1, max4) 25 | 26 | def __speed_test__(self, algo): 27 | time1 = time.time() 28 | for i in range(20): 29 | weights, values, capacity = self.cases[i] 30 | algo(weights, values, capacity) 31 | time2 = time.time() 32 | print("%-45s\t%f" % (algo, time2 - time1)) 33 | 34 | def testRunningTime(self): 35 | print() 36 | self.__speed_test__(knapsack) 37 | self.__speed_test__(knapsack_two_rows) 38 | self.__speed_test__(knapsack_one_row) 39 | self.__speed_test__(knapsack_memo) 40 | 41 | if __name__ == "__main__": 42 | print("This could take up to 10 seconds") 43 | unittest.main() 44 | -------------------------------------------------------------------------------- /selection/c/quick_select.c: -------------------------------------------------------------------------------- 1 | // Rank == count( _ <= the element ) in sorted array 2 | 3 | #include 4 | 5 | void swap(int *a, int *b) 6 | { 7 | int tmp = *a; 8 | *a = *b; 9 | *b = tmp; 10 | } 11 | 12 | void _insertion_sort(int *array, int left, int right) 13 | { 14 | int i, j, x; 15 | for(i = left + 1; i < right + 1; i++) 16 | { 17 | x = array[i]; 18 | for(j = i - 1; j >= left && array[j] > x; j--) 19 | array[j + 1] = array[j]; 20 | array[j + 1] = x; 21 | } 22 | } 23 | 24 | int median3(int* array, int left, int right) 25 | { 26 | int center = (left + right) / 2; 27 | int tmp[] = { array[left], array[center], array[right] }; 28 | _insertion_sort(tmp, 0, 2); 29 | array[left] = tmp[0]; 30 | array[center] = tmp[2]; 31 | array[right] = tmp[1]; 32 | return array[right]; 33 | } 34 | 35 | int partition(int* array, int left, int right) 36 | { 37 | int pivot = median3(array, left, right); 38 | int i = left + 1, j = right - 1; 39 | while(1) 40 | { 41 | while(array[i] < pivot) i++; 42 | while(pivot < array[j]) j--; 43 | if(i >= j) 44 | { 45 | swap(&array[i], &array[right]); 46 | return i; 47 | } 48 | swap(&array[i++], &array[j--]); 49 | } 50 | } 51 | 52 | void q_select(int* array, int left, int right, int rank) 53 | { 54 | if(right - left < 10) 55 | { 56 | _insertion_sort(array, left, right); 57 | return; 58 | } 59 | int center = partition(array, left, right); 60 | if(rank < center) 61 | q_select(array, left, center - 1, rank); 62 | else if(rank > center) 63 | q_select(array, center + 1, right, rank); 64 | } 65 | 66 | int quick_select(int* array, const int n, int rank) 67 | { 68 | q_select(array, 0, n - 1, rank - 1); 69 | return array[rank - 1]; 70 | } 71 | -------------------------------------------------------------------------------- /sorting/c/quick_sort.c: -------------------------------------------------------------------------------- 1 | #include "swap.h" 2 | 3 | void quick_sort(int* array, const int n); 4 | void q_sort(int* array, int left, int right); 5 | int partition(int* array, int left, int right); 6 | int median3(int *array, int left, int right); 7 | void _insertion_sort(int* array, int left, int right); 8 | 9 | void _insertion_sort(int* array, int left, int right) 10 | { 11 | int i, j, x; 12 | for(i = left + 1; i < right + 1; i++) 13 | { 14 | x = array[i]; 15 | for(j = i - 1; j >= left; j--) 16 | if(array[j] > x) 17 | array[j + 1] = array[j]; 18 | else 19 | break; 20 | array[j + 1] = x; 21 | } 22 | } 23 | 24 | void quick_sort(int* array, const int n) 25 | { 26 | q_sort(array, 0, n - 1); 27 | } 28 | 29 | void q_sort(int* array, int left, int right) 30 | { 31 | if(right - left > 10) 32 | { 33 | int center = partition(array, left, right); 34 | q_sort(array, left, center - 1); 35 | q_sort(array, center + 1, right); 36 | } 37 | else 38 | _insertion_sort(array, left, right); 39 | } 40 | 41 | int median3(int* array, int left, int right) 42 | { 43 | int center = (left + right) / 2; 44 | int tmp[] = { array[left], array[center], array[right] }; 45 | _insertion_sort(tmp, 0, 2); 46 | array[left] = tmp[0]; 47 | array[center] = tmp[2]; 48 | array[right] = tmp[1]; 49 | return array[right]; 50 | } 51 | 52 | int partition(int* array, int left, int right) 53 | { 54 | int pivot = median3(array, left, right); 55 | int i = left + 1, j = right - 1; 56 | while(1) 57 | { 58 | while(array[i] < pivot) i++; 59 | while(pivot < array[j]) j--; 60 | if(i >= j) 61 | { 62 | swap(&array[i], &array[right]); 63 | return i; 64 | } 65 | swap(&array[ i++ ], &array[ j-- ]); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /binary_search/java/TestBinarySearch.java: -------------------------------------------------------------------------------- 1 | import java.util.Random; 2 | import java.util.Arrays; 3 | 4 | public class TestBinarySearch 5 | { 6 | public static final int size = 1000; 7 | public static Random myrand = new Random(); 8 | public static int[] setUp(int size) 9 | { 10 | int[] array = new int[size]; 11 | int i, target; 12 | for(i = 0; i < size; i++) 13 | array[i] = myrand.nextInt(); 14 | return array; 15 | } 16 | public static void testBinarySearch() 17 | { 18 | int[] array = new int[size]; 19 | for(int i = 0; i < size; i++) 20 | array[i] = i; 21 | for(int i = 0; i < 100; i++) 22 | { 23 | int target = myrand.nextInt() % (size * 2); 24 | if(target >= size) 25 | assert BinarySearch.search(array, target) == -1; 26 | else 27 | assert BinarySearch.search(array, target) == target; 28 | } 29 | } 30 | public static void testLower() 31 | { 32 | int[] array = setUp(size); 33 | Arrays.sort(array); 34 | int lower = 0; 35 | for(int i = 0; i < 100; i++) 36 | { 37 | int target = myrand.nextInt(); 38 | for(int j = 0; j < size; j++) 39 | if(array[j] >= target) 40 | { 41 | lower = j - 1; 42 | break; 43 | } 44 | assert BinarySearch.lower(array, target) == lower; 45 | } 46 | } 47 | public static void testHigher() 48 | { 49 | int[] array = setUp(size); 50 | Arrays.sort(array); 51 | int upper = 0; 52 | for(int i = 0; i < 100; i++) 53 | { 54 | int target = myrand.nextInt(); 55 | for(int j = size - 1; j >= 0; j--) 56 | if(array[j] <= target) 57 | { 58 | upper = j + 1; 59 | break; 60 | } 61 | assert BinarySearch.higher(array, target) == upper; 62 | } 63 | } 64 | public static void main(String[] args) 65 | { 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /trie/c/test_trie.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "trie.h" 4 | 5 | void test_insert_search() 6 | { 7 | char* setA[24] = { "a", "a", "aa", "aal", "aalii", "aam", "aani", 8 | "aardvark", "aardwolf", "aaron", "aaronic", "aaronical", "aaronite", 9 | "aaronitic", "aaru", "ab", "aba", "ababdeh", "ababua", "abac", "abaca", 10 | "abacate", "abacay", "abacinate" 11 | }; 12 | char* setB[24] = { "b", "b", "ba", "baa", "baahling", "baal", "baal", 13 | "baalath", "baalish", "baalism", "baalist", "baalite", "baalitical", 14 | "baalize", "baalshem", "baar", "bab", "baba", "babacoote", "babai", 15 | "babasco", "babassu", "babaylan", "babbie" 16 | }; 17 | Trie trie; 18 | trie_init(&trie); 19 | int i; 20 | for(i = 0; i < 24; i++) 21 | trie.insert(&trie, setA[i]); 22 | for(i = 0; i < 24; i++) 23 | assert(trie.search(&trie, setA[i])); 24 | for(i = 0; i < 24; i++) 25 | assert(!trie.search(&trie, setB[i])); 26 | trie.destroy(&trie); 27 | } 28 | 29 | void test_start_with() 30 | { 31 | char* words[13] = { "aalii", "aam", "aani", "aardvark", "aardwolf", 32 | "aaronic", "aaronite", "aaronitic", "aaru", "ababdeh", "ababua", 33 | "abacay", "abacinate" 34 | }; 35 | char* prefixes[8] = {"a","a","aa","aal","aaron","ab","aba","abac"}; 36 | char* others[6] = { 37 | "abaciscus","abacist","aback","abactinal","Abe","abaction" 38 | }; 39 | Trie trie; 40 | trie_init(&trie); 41 | int i; 42 | for(i = 0; i < 13; i++) 43 | trie.insert(&trie, words[i]); 44 | for(i = 0; i < 8; i++) 45 | assert(trie.startWith(&trie, prefixes[i])); 46 | for(i = 0; i < 6; i++) 47 | assert(!trie.startWith(&trie, others[i])); 48 | trie.destroy(&trie); 49 | } 50 | 51 | int main() 52 | { 53 | test_insert_search(); 54 | test_start_with(); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /math/py3/TestMymath.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import math 3 | import random 4 | import mymath 5 | 6 | class TestMymath(unittest.TestCase): 7 | def testGCD(self): 8 | for i in range(100): 9 | a, b = random.randrange(100000), random.randrange(100000) 10 | self.assertEqual(mymath.gcd(a, b), math.gcd(a, b)) 11 | 12 | def testExtendedEuclidean(self): 13 | for i in range(100): 14 | a, b = random.randrange(100000), random.randrange(100000) 15 | r, s, t = mymath.egcd(a, b) 16 | self.assertEqual(r, math.gcd(a, b)) 17 | self.assertEqual(a * s + b * t, r) 18 | 19 | def testModInv(self): 20 | primes = [2, 3, 5, 7, 11, 13, 17, 19] 21 | for prime in primes: 22 | for num in range(1, prime): 23 | self.assertEqual(num * mymath.mod_inv(num, prime) % prime, 1) 24 | 25 | def testChineseRemainderTheorem(self): 26 | moduli, remainders = [3, 5, 7], [2, 3, 2] 27 | self.assertEqual(mymath.chinese_remainder_theorem(moduli, remainders), 23) 28 | 29 | def testFracCeiling(self): 30 | for i in range(100): 31 | a, b = random.randrange(100000), random.randrange(100000) 32 | big, small = max(a, b), min(a, b) 33 | expected = big // small 34 | if big % small != 0: 35 | expected += 1 36 | self.assertEqual(mymath.frac_ceiling(big, small), expected) 37 | 38 | def testPrime(self): 39 | maximum = 100 * 1000 40 | primes = set(mymath.sieve_of_eratosthenes(maximum)) 41 | for num in range(maximum): 42 | self.assertEqual(mymath.is_prime(num), num in primes, num) 43 | 44 | if __name__ == "__main__": 45 | unittest.main() 46 | -------------------------------------------------------------------------------- /binary_indexed_tree/cxx/TestBinaryIndexedTree.cxx: -------------------------------------------------------------------------------- 1 | #include "BinaryIndexedTree.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | void testGetSum() 8 | { 9 | const int LENGTH = 100; 10 | std::vector array(100); 11 | for(int i = 0; i < LENGTH; i++) 12 | array[i] = rand() % 100; 13 | BinaryIndexedTree bit(array); 14 | int right, sum; 15 | for(int cnt = 0; cnt < 100; cnt++) 16 | { 17 | right = rand() % LENGTH; 18 | sum = 0; 19 | for(int i = 0; i <= right; i++) 20 | sum += array[i]; 21 | assert(bit.getSum(right) == sum); 22 | } 23 | } 24 | 25 | void testUpdate() 26 | { 27 | const int LENGTH = 100; 28 | std::vector array(100); 29 | for(int i = 0; i < LENGTH; i++) 30 | array[i] = rand() % 100; 31 | BinaryIndexedTree bit(array); 32 | int right, sum; 33 | int index, delta; 34 | for(int cnt = 0; cnt < 100; cnt++) 35 | { 36 | index = rand() % LENGTH; 37 | delta = rand() % 100; 38 | array[index] += delta; 39 | bit.update(index, delta); 40 | right = rand() % LENGTH; 41 | sum = 0; 42 | for(int i = 0; i <= right; i++) 43 | sum += array[i]; 44 | assert(bit.getSum(right) == sum); 45 | } 46 | } 47 | 48 | void testGetRange() 49 | { 50 | const int LENGTH = 100; 51 | std::vector array(100); 52 | for(int i = 0; i < LENGTH; i++) 53 | array[i] = rand() % 100; 54 | BinaryIndexedTree bit(array); 55 | int left, right, sum; 56 | for(int cnt = 0; cnt < 100; cnt++) 57 | { 58 | left = rand() % LENGTH/2; 59 | right = left + rand() % LENGTH/2; 60 | sum = 0; 61 | for(int i = left; i <= right; i++) 62 | sum += array[i]; 63 | assert(bit.getRange(left, right) == sum); 64 | } 65 | } 66 | 67 | int main() 68 | { 69 | srand(time(NULL)); 70 | testGetSum(); 71 | testUpdate(); 72 | testGetRange(); 73 | } 74 | -------------------------------------------------------------------------------- /shortest_path/py3/bfs.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | # Tested 4 | def bfs(adjList, source): 5 | front = deque([source]) 6 | dist = {source: 0} 7 | prev = {source: None} 8 | while front: 9 | node = front.popleft() 10 | for child in adjList[node]: 11 | if child not in dist: 12 | front.append(child) 13 | dist[child] = dist[node] + 1 14 | prev[child] = node 15 | return dist, prev 16 | 17 | def bfs_template_1(adjList, source): 18 | front = deque([source]) 19 | visited = {source} 20 | while front: 21 | node = front.popleft() 22 | # Do something here 23 | for child in adjList[node]: 24 | if child not in visited: 25 | front.append(child) 26 | visited.add(child) 27 | return None 28 | 29 | # Verified 30 | def bfs_template_2(adjList, source): 31 | front = [source] 32 | visited = {source} 33 | while front: 34 | children = [] 35 | for node in front: 36 | # Do something here 37 | for child in adjList[node]: 38 | if child not in visited: 39 | children.append(child) 40 | visited.add(child) 41 | front = children 42 | return None 43 | 44 | def bfs_template_3(adjList, source): 45 | front = deque([source]) 46 | visited = {source} 47 | while front: 48 | frontLen = len(front) 49 | for _ in range(frontLen): 50 | node = front.popleft() 51 | # Do something here 52 | for child in adjList[node]: 53 | if child not in visited: 54 | front.append(child) 55 | visited.add(child) 56 | return None 57 | -------------------------------------------------------------------------------- /sorting/py3/quick_sort.py: -------------------------------------------------------------------------------- 1 | # 99% of the time faster than lomuto, 30% faster on average 2 | # 99% of the time faster than pure quick sort, 15% faster on average 3 | # Time: O(n log n) 4 | 5 | def insertion_sort(array, left, right): 6 | for i in range(left + 1, right + 1): 7 | x = array[i] 8 | j = i - 1 9 | while j >= left and array[j] > x: 10 | array[j + 1] = array[j] 11 | j -= 1 12 | array[j + 1] = x 13 | 14 | def median3(array, left, right): 15 | center = (left + right) // 2 16 | temp = [array[left], array[center], array[right]] 17 | insertion_sort(temp, 0, 2) 18 | array[left], array[right], array[center] = temp 19 | return array[right] 20 | 21 | def partition(array, left, right): 22 | pivot = median3(array, left, right) 23 | # Invariant: array[left] <= pivot && array[right] == pivot 24 | i, j = left + 1, right - 1 25 | while True: 26 | # Invariant: array[i] >= pivot 27 | while array[i] < pivot: 28 | i += 1 29 | # Invariant: array[j] <= pivot 30 | while pivot < array[j]: 31 | j -= 1 32 | # If i == j there is no need to swap 33 | if i >= j: 34 | # Because array[i] >= pivot, array[i] should be put on the right 35 | array[i], array[right] = array[right], array[i] 36 | return i 37 | array[i], array[j] = array[j], array[i] 38 | i, j = i + 1, j - 1 39 | 40 | def q_sort(array, left, right): 41 | if right - left > 10: 42 | center = partition(array, left, right) 43 | q_sort(array, left, center - 1) 44 | q_sort(array, center + 1, right) 45 | else: 46 | insertion_sort(array, left, right) 47 | 48 | def quick_sort(array): 49 | q_sort(array, 0, len(array) - 1) 50 | -------------------------------------------------------------------------------- /sampling/py3/simple_random_sample.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | # Simple Random Sample: get a sample of size k from input of size n 4 | 5 | # Simple Random Sample algorithm for fixed-length, randomly-accessible input 6 | # Useful when the sampling has to be done in a draw-by-draw fashion 7 | # Time: O(k) 8 | # Space: O(k) 9 | def draw_by_draw(array, k): 10 | for i in range(k): 11 | index = random.randrange(len(array) - i) 12 | array[index], array[-1 - i] = array[-1 - i], array[index] 13 | return array[len(array) - k:] 14 | 15 | # Simple Random Sample algorithm for fixed-length input 16 | # Intuition: randomly taking 3 balls out of the box at once is equivalent to 17 | # randomly taking 1 ball from the box without replacement 3 times 18 | # Time: O(n) 19 | # Space: O(k) 20 | def selection_rejection(array, k): 21 | """ Fan et al., 1962 """ 22 | sample = [] 23 | n = len(array) 24 | for elem in array: 25 | if random.random() * n < k: 26 | sample.append(elem) 27 | k -= 1 28 | n -= 1 29 | return sample 30 | 31 | # Simple Random Sample algorithm for stream input 32 | # Every incoming element has a k/n chance of being sampled 33 | # Time: O(n) 34 | # Space: O(k) 35 | def reservoir_sampling(iterator, k): 36 | """ Vitter, 1985 """ 37 | sample = [] 38 | for i in range(k): 39 | try: 40 | sample.append(next(iterator)) 41 | except StopIteration: 42 | return sample 43 | 44 | n = k 45 | while True: 46 | n += 1 47 | try: 48 | elem = next(iterator) 49 | if random.random() * n < k: 50 | idx = random.randrange(k) 51 | sample[idx] = elem 52 | except StopIteration: 53 | break 54 | return sample 55 | -------------------------------------------------------------------------------- /selection/java/QuickSelect.java: -------------------------------------------------------------------------------- 1 | import java.util.Random; 2 | 3 | public class QuickSelect implements SelectionAlgorithm 4 | { 5 | private Random rand = new Random(); 6 | private void insertion_sort(int[] array, int left, int right) 7 | { 8 | int j, x; 9 | for(int i = left + 1; i < right + 1; i++) 10 | { 11 | x = array[i]; 12 | j = i - 1; 13 | for(j = i - 1; j >= left && array[j] > x; j--) 14 | array[j + 1] = array[j]; 15 | array[j + 1] = x; 16 | } 17 | } 18 | private int median3(int[] array, int left, int right) 19 | { 20 | int center = (left + right) / 2; 21 | int tmp[] = { array[left], array[center], array[right] }; 22 | insertion_sort(tmp, 0, 2); 23 | array[left] = tmp[0]; 24 | array[center] = tmp[2]; 25 | array[right] = tmp[1]; 26 | return array[right]; 27 | } 28 | private int partition(int[] array, int left, int right) 29 | { 30 | int pivot = median3(array, left, right); 31 | int i = left, j = right - 1; 32 | while(true) 33 | { 34 | while(array[i] < pivot) i++; 35 | while(pivot < array[j]) j--; 36 | if(i >= j) 37 | { 38 | array[i] = array[right] ^ array[i] ^ (array[right] = array[i]); 39 | return i; 40 | } 41 | array[i] = array[j] ^ array[i] ^ (array[j] = array[i]); 42 | i++; j--; 43 | } 44 | } 45 | private void q_select(int[] array, int left, int right, int rank) 46 | { 47 | if(right - left < 10) 48 | { 49 | insertion_sort(array, left, right); 50 | return; 51 | } 52 | int center = partition(array, left, right); 53 | if(rank < center) 54 | q_select(array, left, center - 1, rank); 55 | else if(rank > center) 56 | q_select(array, center + 1, right, rank); 57 | } 58 | public int select(int[] array, int rank) 59 | { 60 | q_select(array, 0, array.length - 1, rank - 1); 61 | return array[rank - 1]; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /majority_vote/py3/TestMajorityVote.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import random 3 | from majority_vote import majority_vote, majority_vote_general 4 | 5 | class TestMajorityVote(unittest.TestCase): 6 | def testMajorityVote(self): 7 | size = random.randrange(100, 500) 8 | for count in range(size): 9 | array = [0] * count 10 | array += [random.randrange(1, 3) for _ in range(size - count)] 11 | elect = None 12 | for num in set(array): 13 | if array.count(num) > len(array) / 2: 14 | elect = num 15 | random.shuffle(array) 16 | self.assertEqual(majority_vote(array), elect) 17 | 18 | def testMajorityVoteGeneral(self): 19 | size = random.randrange(100, 500) 20 | for i in range(100): 21 | k = random.randrange(2, 10) 22 | value = random.randrange(1, 10) 23 | array = [random.randrange(value) for _ in range(size)] 24 | elect = [] 25 | for num in set(array): 26 | if array.count(num) > len(array) / k: 27 | elect.append(num) 28 | self.assertEqual(set(elect), set(majority_vote_general(array, k))) 29 | 30 | def testMajorityVoteEdgeCase(self): 31 | size = random.randrange(100, 500) 32 | for i in range(100): 33 | k = random.randrange(1, int(size * 1.5)) 34 | value = random.randrange(1, 10) 35 | array = [random.randrange(value) for _ in range(size)] 36 | elect = [] 37 | for num in set(array): 38 | if array.count(num) > len(array) / k: 39 | elect.append(num) 40 | self.assertEqual(set(elect), set(majority_vote_general(array, k))) 41 | 42 | if __name__ == "__main__": 43 | unittest.main() 44 | -------------------------------------------------------------------------------- /disjoint_set/DisjointSet.md: -------------------------------------------------------------------------------- 1 | ## Equivalence Relation 2 | An equivalence relation is a relation \\(\text{R}\\) that satisfies three properties: 3 | 4 | | Property | Mathematically | 5 | |----------|----------------| 6 | Reflexive | For \\(\forall a \in S\\), \\(a \text{ R } a\\). 7 | Symmetric | \\(a \text{ R } b \Longleftrightarrow b \text{ R } a\\). 8 | Transitive | \\(a \text{ R } b \text{ and } b \text{ R } c \Longrightarrow a \text{ R } c\\). 9 | 10 | ## Partition of A Set 11 | A family of sets \\(P\\) is a *partition* of \\(X\\) iff all of the following conditions hold: 12 | 13 | | Property | Mathematically | 14 | |----------|----------------| 15 | \\(P\\) does not contain the empty set | \\(\varnothing \not\in P\\) 16 | Union of all sets in \\(P\\) is \\(X\\) | \\(\bigcup _ {A \in P} A = X\\) 17 | All pairs of sets in \\(P\\) are disjoint | \\(\forall A, B \in P, A \neq B \Longrightarrow A \cap B = \varnothing)\\) 18 | 19 | * An equivalence relation \\(\sim\\) on a set \\(X\\) partitions \\(X\\). 20 | * Conversely, corresponding to any partition of \\(X\\), there exists an equivalence relation \\(\sim\\) on \\(X\\). 21 | 22 | ## LeetCode 23 | Disjoint Set is typically used to solve "Connected Components in Undirected Graph" problem. Nodes in connected components naturally form a family of disjoint sets. With Union Find data structure, we can find if two nodes are in the same component or join two components when an edge between them is found in inverse Ackermann function time. 24 | 25 | Connected Component related problems are usually solvable via DFS or BFS, which could be easier to implement when implementation of Disjoint Set is not present. However, Disjoint Set does have an advantage over DFS and BFS in dealing with streaming input, where Disjoint Set can make it possible to save the equivalence relations obtained as the input goes along. 26 | -------------------------------------------------------------------------------- /binary_indexed_tree/c/test_binary_indexed_tree.c: -------------------------------------------------------------------------------- 1 | #include "binary_indexed_tree.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | BinaryIndexedTree* bit; 9 | const int LENGTH = 100; 10 | int array[LENGTH]; 11 | 12 | void set_up() 13 | { 14 | for(int i = 0; i < LENGTH; i++) 15 | array[i] = rand() % 100; 16 | bit = bit_init(array, LENGTH); 17 | } 18 | 19 | void break_down() 20 | { 21 | bit->destroy(bit); 22 | free(bit); 23 | } 24 | 25 | void test_get_sum() 26 | { 27 | set_up(); 28 | int right, sum; 29 | for(int cnt = 0; cnt < 100; cnt++) 30 | { 31 | right = rand() % LENGTH; 32 | sum = 0; 33 | for(int i = 0; i <= right; i++) 34 | sum += array[i]; 35 | if(bit->get_sum(bit, right) != sum) 36 | printf("Error in test_get_sum: expect %d, got %d", 37 | sum, bit->get_sum(bit, right)); 38 | } 39 | break_down(); 40 | } 41 | 42 | void test_update() 43 | { 44 | set_up(); 45 | int right, sum; 46 | int index, delta; 47 | for(int cnt = 0; cnt < 100; cnt++) 48 | { 49 | index = rand() % LENGTH; 50 | delta = rand() % 100; 51 | array[index] += delta; 52 | bit->update(bit, index, delta); 53 | right = rand() % LENGTH; 54 | sum = 0; 55 | for(int i = 0; i <= right; i++) 56 | sum += array[i]; 57 | assert(bit->get_sum(bit, right) == sum); 58 | } 59 | break_down(); 60 | } 61 | 62 | void test_get_range() 63 | { 64 | set_up(); 65 | int left, right, sum; 66 | for(int cnt = 0; cnt < 100; cnt++) 67 | { 68 | left = rand() % LENGTH/2; 69 | right = left + rand() % LENGTH/2; 70 | sum = 0; 71 | for(int i = left; i <= right; i++) 72 | sum += array[i]; 73 | assert(bit->get_range(bit, left, right) == sum); 74 | } 75 | break_down(); 76 | } 77 | 78 | int main() 79 | { 80 | srand(time(NULL)); 81 | test_get_sum(); 82 | test_update(); 83 | test_get_range(); 84 | 85 | } 86 | --------------------------------------------------------------------------------