├── README.md ├── coursera └── algorithms-part1 │ ├── README.md │ ├── stacks-and-queues │ ├── Generics.txt │ ├── CloneLinked.txt │ ├── StackWithMax.java │ ├── StackQueue.java │ └── LinkedListCycle.java │ ├── elementary-sorts │ ├── IntersectionSets.txt │ └── Permutation.java │ ├── analysis-of-algorithms │ ├── ThreeSum.java │ ├── EggDrop.txt │ └── BitonicArray.java │ └── union-find │ ├── SuccessorWithDelete.java │ ├── SocialNetworkConnectivity.java │ ├── WeightedQuickUnionHeight.java │ └── WeightedQuickUnionUF.java ├── .gitignore ├── leetcode ├── hindex.py ├── single_number.cpp ├── group_anagrams.py ├── permutations.py ├── unique_paths.py ├── most_water.cpp ├── reverseint.cpp ├── next_permutation.py ├── remove_array_duplicates.cpp ├── zigzag.cpp ├── UglyNumber.java ├── twosum.cpp ├── validParentheses.cpp ├── four_sum.py ├── regex.py ├── romanToInt.cpp ├── subsets.cpp ├── edit_distance.py ├── merge_intervals.py ├── restore_ips.py ├── RotateArray.java ├── permutations2.cpp ├── search_range.py ├── QueueUsingStack.java ├── reverse_words.cpp ├── dungeon.cpp ├── threesum.cpp ├── wordsearch.cpp ├── LowestCommonAncestor.java ├── largest_number.cpp ├── reverse-k-list.py ├── min_stack.cpp ├── multiply_strings.cpp └── validnumbers.cpp ├── src ├── hanoi.py ├── sort_anagrams.py ├── generate_sets.py ├── removechars.cpp ├── parenthesization.cpp ├── generate_products.py ├── stablesort.cpp ├── stringcombinations.cpp ├── printlastlines.cpp ├── reversewords.cpp ├── anagrams.cpp ├── allsubsets.cpp ├── stringpermutations.cpp ├── random_median.cpp ├── towers.cpp ├── convert.cpp ├── philosophers.cpp ├── zeromatrix.cpp ├── producerconsumer.cpp ├── libds_list.cpp └── libds_btree.cpp └── Makefile /README.md: -------------------------------------------------------------------------------- 1 | Practice Problems 2 | ======== 3 | 4 | Interview practice problems from leetcode and other sources. 5 | 6 | System Design Review 7 | ======== 8 | https://github.com/donnemartin/system-design-primer 9 | -------------------------------------------------------------------------------- /coursera/algorithms-part1/README.md: -------------------------------------------------------------------------------- 1 | ## Algorithms, Part I 2 | **Coursera - Princeton University** 3 | 4 | This repository contains answers to the job interview questions. 5 | 6 | https://www.coursera.org/course/algs4partI 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | *.class 7 | 8 | # Precompiled Headers 9 | *.gch 10 | *.pch 11 | 12 | # Compiled Dynamic libraries 13 | *.so 14 | *.dylib 15 | *.dll 16 | 17 | # Fortran module files 18 | *.mod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | 31 | # Debugging 32 | *.dSYM 33 | -------------------------------------------------------------------------------- /leetcode/hindex.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def hIndex(self, citations): 3 | """ 4 | :type citations: List[int] 5 | :rtype: int 6 | """ 7 | citations.sort() 8 | for index in range(0, len(citations)): 9 | if citations[index] >= (len(citations)-index): 10 | return citations[index] 11 | return 0 12 | 13 | s = Solution() 14 | print s.hIndex([1]) 15 | -------------------------------------------------------------------------------- /src/hanoi.py: -------------------------------------------------------------------------------- 1 | # Cracking the Coding Interview 2 | # Problem 3.4 3 | 4 | def move_disks(src, dest, tmp, n): 5 | if n == 0: 6 | return 7 | move_disks(src, tmp, dest, n-1) 8 | dest.append(src.pop()) 9 | print_current() 10 | move_disks(tmp, dest, src, n-1) 11 | 12 | def print_current(): 13 | print src, dest, tmp 14 | 15 | src = [4,3,2,1] 16 | dest = [] 17 | tmp = [] 18 | 19 | print_current() 20 | move_disks(src, dest, tmp, len(src)) 21 | -------------------------------------------------------------------------------- /src/sort_anagrams.py: -------------------------------------------------------------------------------- 1 | # Cracking The Coding Interview 2 | # Problem 11.2 3 | 4 | def sort_anagrams(strings): 5 | return sorted(strings,cmp=anasort) 6 | 7 | def anasort(a,b): 8 | al = sorted(a) 9 | bl = sorted(b) 10 | if al < bl: 11 | return -1 12 | elif al > bl: 13 | return 1 14 | else: 15 | return 0 16 | 17 | strs = ['god', 'asdf', 'dog', 'asfd', 'asdflkjf', 'more', 'fas'] 18 | strs_sorted = sort_anagrams(strs) 19 | print strs 20 | print strs_sorted -------------------------------------------------------------------------------- /src/generate_sets.py: -------------------------------------------------------------------------------- 1 | # Cracking the Coding Interview 2 | # Problem 9.4 3 | 4 | def generate_sets(s): 5 | set_list = [set()] 6 | for elem in s: 7 | new_sets = [] 8 | for cur_set in set_list: 9 | new_set = set(cur_set) 10 | new_set.add(elem) 11 | new_sets.append(new_set) 12 | set_list.extend(new_sets) 13 | return set_list 14 | 15 | 16 | base = set([1,2,3,4]) 17 | out = generate_sets(base) 18 | for o in out: 19 | print o 20 | -------------------------------------------------------------------------------- /leetcode/single_number.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class Solution { 7 | public: 8 | int singleNumber(int A[], int n) { 9 | int exclusive_sum = 0; 10 | for(int i = 0; i < n; ++i) { 11 | exclusive_sum ^= A[i]; 12 | } 13 | return exclusive_sum; 14 | } 15 | }; 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | Solution s; 20 | int A[11] = {1,3,2,3,4,6,1,2,4,6,5}; 21 | cout << s.singleNumber(A, 11) << endl; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /leetcode/group_anagrams.py: -------------------------------------------------------------------------------- 1 | # Leetcode 49 - Group Anagrams 2 | 3 | class Solution(object): 4 | def groupAnagrams(self, strs): 5 | """ 6 | :type strs: List[str] 7 | :rtype: List[List[str]] 8 | """ 9 | strs = sorted(strs) 10 | groups = {} 11 | for s in strs: 12 | key = ''.join(sorted(s)) 13 | if key in groups: 14 | groups[key].append(s) 15 | else: 16 | groups[key] = [s] 17 | output = [g for g in groups.itervalues()] 18 | return output 19 | 20 | 21 | s = Solution() 22 | print s.groupAnagrams(['']) 23 | 24 | -------------------------------------------------------------------------------- /src/removechars.cpp: -------------------------------------------------------------------------------- 1 | // Programming Interviews Exposed PG.94 2 | // Remove Specified Characters 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | string remove_chars(string str, string remove) { 11 | string output; 12 | unordered_set remove_set; 13 | for(char c : remove) { 14 | remove_set.insert(c); 15 | } 16 | for(char c : str) { 17 | if( remove_set.find(c) == remove_set.end() ) { 18 | output.append(1, c); 19 | } 20 | } 21 | 22 | return output; 23 | } 24 | 25 | int main() 26 | { 27 | string output = remove_chars(string("My Little Pony"), string("aeiou")); 28 | cout << output << endl; 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /leetcode/permutations.py: -------------------------------------------------------------------------------- 1 | # Leetcode 46 2 | # Permutations 3 | 4 | class Solution(object): 5 | def permute(self, nums): 6 | """ 7 | :type nums: List[int] 8 | :rtype: List[List[int]] 9 | """ 10 | from collections import deque 11 | res = [] 12 | nums_copy = deque(nums) 13 | self.permute_r(nums_copy, [], res) 14 | return res 15 | 16 | def permute_r(self, nums, cur, res): 17 | print nums, cur 18 | if not nums: 19 | res.append(cur) 20 | return 21 | for i in range(len(nums)): 22 | cur.append(nums.pop()) 23 | self.permute_r(nums, cur, res) 24 | nums.appendleft(cur.pop()) 25 | 26 | s = Solution() 27 | s.permute([1,2,3]) 28 | -------------------------------------------------------------------------------- /leetcode/unique_paths.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def uniquePaths(self, m, n): 3 | """ 4 | :type m: int 5 | :type n: int 6 | :rtype: int 7 | """ 8 | grid = [[0 for x in range(0, n)] for y in range(0, m)] 9 | for mi in range(0, m): 10 | for ni in range(0, n): 11 | total = 0 12 | if mi == 0 and ni == 0: 13 | total += 1 14 | if mi > 0: 15 | total += grid[mi-1][ni] 16 | if ni > 0: 17 | total += grid[mi][ni-1] 18 | grid[mi][ni] = total 19 | print mi, ni, total, grid 20 | return grid[-1][-1] 21 | 22 | s = Solution() 23 | 24 | print s.uniquePaths(3,3) 25 | -------------------------------------------------------------------------------- /coursera/algorithms-part1/stacks-and-queues/Generics.txt: -------------------------------------------------------------------------------- 1 | Coursera - Algorithms Part I 2 | 3 | Week 2 - Interview Questions - Stacks and Queues 4 | 5 | Question 3: Java generics 6 | Explain why Java prohibits generic array creation. 7 | 8 | Java generics are a compile time only type check. The type is "erased" during 9 | compilation and a result the runtime does not know what type a generic object is. 10 | Creating a generic array would mean the runtime cannot know the type of the array. 11 | This would mean the runtime cannot perform type safety checks. This is not a 12 | problem for other generic objects since they have their base type. 13 | 14 | ArrayList has the same type as ArrayList 15 | 16 | http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#FAQ104 17 | -------------------------------------------------------------------------------- /src/parenthesization.cpp: -------------------------------------------------------------------------------- 1 | // Build all possible order of operations for string (parenthesis) 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | void BuildString(const string current, int left_rem, int right_rem, vector* list) { 10 | if(left_rem == 0 && right_rem == 0) { 11 | list->push_back(current); 12 | } else { 13 | if(left_rem > 0) { 14 | BuildString(current+"(", left_rem-1, right_rem, list); 15 | } 16 | if(right_rem > left_rem) { 17 | BuildString(current+")", left_rem, right_rem-1, list); 18 | } 19 | } 20 | } 21 | 22 | int main(int argc, char *argv[]) 23 | { 24 | const int count = 4; 25 | vector tmp; 26 | BuildString("", count, count, &tmp); 27 | 28 | for(auto s : tmp) { 29 | cout << s << endl; 30 | } 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /leetcode/most_water.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class Solution { 7 | public: 8 | int maxArea(vector &height) { 9 | int max_area = 0; 10 | if(height.size() > 1) { 11 | int left = 0; 12 | int right = height.size() - 1; 13 | while(left < right) { 14 | int area = (right-left)*min(height[left], height[right]); 15 | max_area = max(area, max_area); 16 | if(height[left] < height[right]) { 17 | ++left; 18 | } else { 19 | --right; 20 | } 21 | } 22 | } 23 | return max_area; 24 | } 25 | }; 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | Solution s; 30 | vector height = {15000,1,23,4,5,5,56,6}; 31 | cout << s.maxArea(height) << endl; 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /leetcode/reverseint.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | class Solution { 8 | public: 9 | int reverse(int x) { 10 | int num_digits = 0; 11 | long tmp_x = labs(x); 12 | while(tmp_x != 0) { 13 | ++num_digits; 14 | tmp_x /= 10; 15 | } 16 | long tmp = 0; 17 | tmp_x = labs(x); 18 | for(int d = 1; d <= num_digits; ++d) { 19 | int value = tmp_x%10; 20 | tmp += value * pow(10, num_digits-d); 21 | tmp_x /= 10; 22 | } 23 | if(x < 0) { 24 | tmp = -tmp; 25 | } 26 | if(tmp > INT_MAX || tmp < INT_MIN) { 27 | return 0; 28 | } 29 | return tmp; 30 | } 31 | }; 32 | 33 | int main(int argc, char *argv[]) 34 | { 35 | Solution s; 36 | cout << s.reverse(-2147483648) << endl; 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /src/generate_products.py: -------------------------------------------------------------------------------- 1 | #def products(inputs, num, index, outputs): 2 | # if index >= len(inputs): 3 | # return 4 | # tmp = num*inputs[index] 5 | # outputs.append(tmp) 6 | # products(inputs, num, index+1, outputs) 7 | # products(inputs, tmp, index+1, outputs) 8 | # 9 | # 10 | #inputs = [3,11,2, 7,4,8] 11 | #outputs = [] 12 | # 13 | #products(inputs, 1, 0, outputs) 14 | # 15 | #print sorted(outputs) 16 | #print len(outputs) 17 | 18 | # Generate all products from a list of prime numbers 19 | 20 | def products(input, num, index, output): 21 | if index > len(input): 22 | return 23 | output.append(num) 24 | for new_index in range(index+1, len(input)): 25 | products(input, num*input[new_index], new_index, output) 26 | 27 | input = [2, 11, 3, 4, 7, 8] 28 | output = [] 29 | 30 | for index in range(len(input)): 31 | products(input, input[index], index, output) 32 | 33 | print sorted(output) 34 | print len(output) 35 | 36 | -------------------------------------------------------------------------------- /src/stablesort.cpp: -------------------------------------------------------------------------------- 1 | // stable version of selection sort 2 | 3 | #include 4 | #include 5 | 6 | void stablesort(int array[], int length) { 7 | for(int idx = 0; idx < length-1; idx++) { 8 | int target = idx; 9 | for(int tidx = idx; tidx < length; tidx++) { 10 | if( array[target] > array[tidx] ) { 11 | target = tidx; 12 | } 13 | } 14 | std::cout << target << std::endl; 15 | int val = array[target]; 16 | memmove(array+idx+1, array+idx, (target-idx)*sizeof(int)); 17 | array[idx] = val; 18 | } 19 | } 20 | 21 | int main() 22 | { 23 | int array[10] = {3,4,5,23,7,21,4,7,1,87}; 24 | for(auto a : array) { 25 | std::cout << a << " "; 26 | } 27 | std::cout << std::endl; 28 | stablesort(array, 10); 29 | for(auto a : array) { 30 | std::cout << a << " "; 31 | } 32 | std::cout << std::endl; 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /leetcode/next_permutation.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def nextPermutation(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: void Do not return anything, modify nums in-place instead. 6 | """ 7 | si = None 8 | # find last increasing num 9 | for i in range(len(nums)-1): 10 | if nums[i] < nums[i+1]: 11 | si = i 12 | # if found, swap with min in remaining elements and reverse remaining 13 | if si is not None: 14 | mi = si+1 15 | for m in range(si+1, len(nums)): 16 | if nums[m] <= nums[mi] and nums[m] > nums[si]: 17 | mi = m 18 | nums[mi], nums[si] = nums[si], nums[mi] 19 | tmp = nums[si+1:] 20 | tmp.reverse() 21 | nums[si+1:] = tmp 22 | else: 23 | nums.reverse() 24 | 25 | s = Solution() 26 | l = [1,3,2] 27 | s.nextPermutation(l) 28 | print l 29 | -------------------------------------------------------------------------------- /src/stringcombinations.cpp: -------------------------------------------------------------------------------- 1 | // Programming Interviews Exposed PG 116 2 | // Print All Combinations Of A String 3 | 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | void combinations(string source, string str, size_t target_len) { 10 | if(str.size() == target_len) { 11 | cout << str << endl; 12 | } 13 | else { 14 | string tmpsource = source; 15 | while(tmpsource.size() > 0) { 16 | string tmpstr = str; 17 | tmpstr.push_back(tmpsource.at(0)); 18 | tmpsource.erase(0, 1); 19 | combinations(tmpsource, tmpstr, target_len); 20 | } 21 | } 22 | } 23 | 24 | void print_string_combinations(string str) { 25 | for(size_t len = 1; len <= str.size(); len++) { 26 | combinations(str, "", len); 27 | } 28 | } 29 | 30 | int main() 31 | { 32 | print_string_combinations("1234"); 33 | print_string_combinations("abcdef"); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /leetcode/remove_array_duplicates.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | class Solution { 6 | public: 7 | int removeDuplicates(int A[], int n) { 8 | int length = 0; 9 | for(int i = 0; i < n; ++i) { 10 | if(length-1 >= 0 && A[length-1] == A[i]) { 11 | continue; 12 | } else { 13 | A[length++] = A[i]; 14 | } 15 | } 16 | return length; 17 | } 18 | 19 | }; 20 | 21 | 22 | int main(int argc, char *argv[]) 23 | { 24 | Solution s; 25 | 26 | int A1[] = { 1, 1 }; 27 | int A2[] = { 1, 1, 1, 3, 4, 5, 6, 6, 6, 7 }; 28 | 29 | int A1_len = s.removeDuplicates(A1, 2); 30 | for(auto i = 0; i < A1_len; ++i ) { 31 | cout << A1[i]; 32 | } 33 | cout << endl; 34 | 35 | int A2_len = s.removeDuplicates(A2, 10); 36 | for(auto i = 0; i < A2_len; ++i ) { 37 | cout << A2[i]; 38 | } 39 | cout << endl; 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /leetcode/zigzag.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class Solution { 7 | public: 8 | string convert(string s, int nrows) { 9 | string tmp; 10 | if(nrows > 0) { 11 | for(int row = 0; row < nrows; ++row) { 12 | int pos = row; 13 | while(pos < s.size()) { 14 | tmp.push_back(s[pos]); 15 | if(row != 0 && row != (nrows-1)) { 16 | int zag_index = pos+2*(nrows-1-row); 17 | if(zag_index < s.size()) { 18 | tmp.push_back(s[zag_index]); 19 | } 20 | } 21 | pos += nrows + max(0, nrows-2); 22 | } 23 | } 24 | } 25 | return tmp; 26 | } 27 | }; 28 | 29 | int main(int argc, char *argv[]) 30 | { 31 | Solution s; 32 | cout << s.convert("PAYPALISHIRING", 3) << endl; 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /src/printlastlines.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | void PrintLastLines(const string& filename, const int K) { 10 | if(K <= 0) { 11 | return; 12 | } 13 | ifstream filestream(filename); 14 | string tmp; 15 | vector offsets; 16 | offsets.push_back(0); 17 | while(getline(filestream, tmp)) { 18 | offsets.push_back(filestream.tellg()); 19 | } 20 | size_t start_line = (static_cast(K) < offsets.size()) ? (offsets.size() - static_cast(K)) : 0; 21 | filestream.clear(); 22 | filestream.seekg(offsets[start_line]); 23 | while(getline(filestream,tmp)) { 24 | cout << tmp << endl; 25 | } 26 | 27 | } 28 | 29 | int main(int argc, char *argv[]) 30 | { 31 | if(argc < 3) { 32 | cout << argv[0] << " FILE LINES" << endl; 33 | return 1; 34 | } 35 | PrintLastLines(argv[1],atoi(argv[2])); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /src/reversewords.cpp: -------------------------------------------------------------------------------- 1 | // Interviews Exposed - PG 97 2 | // Reverse Words 3 | 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | string ReverseWords(const string& str) { 10 | string rstr = str; 11 | reverse(rstr.begin(), rstr.end()); 12 | 13 | auto word_start = rstr.begin(); 14 | auto word_end = word_start; 15 | 16 | while(word_start != rstr.end() && word_end != rstr.end()) { 17 | 18 | while(word_start != rstr.end() && (*word_start) == ' ') { 19 | word_start++; 20 | } 21 | 22 | word_end = word_start; 23 | while(word_end != rstr.end() && (*word_end) != ' ') { 24 | word_end++; 25 | } 26 | 27 | reverse(word_start, word_end); 28 | 29 | word_start = word_end; 30 | } 31 | 32 | return rstr; 33 | } 34 | 35 | int main() 36 | { 37 | cout << ReverseWords("testing a sentence of some sort, do stuff!") << endl; 38 | cout << ReverseWords("wtf. why is there a mammoth in my place... word ") << endl; 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /leetcode/UglyNumber.java: -------------------------------------------------------------------------------- 1 | // Leetcode 2 | // Ugly Number 3 | 4 | public class UglyNumber { 5 | public boolean isUgly(int num) { 6 | if (num == 0) { 7 | return false; 8 | } else if (num == 1) { 9 | return true; 10 | } 11 | 12 | while (num != 2 && num != 3 && num != 5) { 13 | if (num % 2 == 0) { 14 | num = num / 2; 15 | } else if (num % 3 == 0) { 16 | num = num / 3; 17 | } else if (num % 5 == 0) { 18 | num = num / 5; 19 | } else { 20 | return false; 21 | } 22 | } 23 | return true; 24 | } 25 | 26 | public static void main(String[] args) { 27 | UglyNumber ugly = new UglyNumber(); 28 | 29 | System.out.println(ugly.isUgly(3)); 30 | System.out.println(ugly.isUgly(4)); 31 | System.out.println(ugly.isUgly(7)); 32 | System.out.println(ugly.isUgly(1000)); 33 | System.out.println(ugly.isUgly(134)); 34 | } 35 | } -------------------------------------------------------------------------------- /src/anagrams.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | void SortAnagramList(vector* list) { 10 | if(list == nullptr) { 11 | return; 12 | } 13 | unordered_map> table; 14 | for(auto s : (*list)) { 15 | string tmp(s); 16 | sort(tmp.begin(), tmp.end()); 17 | table[tmp].push_back(s); 18 | } 19 | int index = 0; 20 | for(auto anagrams : table) { 21 | for(auto astr : anagrams.second) { 22 | (*list)[index++] = astr; 23 | } 24 | } 25 | } 26 | 27 | 28 | int main(int argc, char *argv[]) 29 | { 30 | vector list; 31 | list.push_back("dog"); 32 | list.push_back("something"); 33 | list.push_back("god"); 34 | list.push_back("licker"); 35 | list.push_back("dice"); 36 | list.push_back("kicler"); 37 | list.push_back("cide"); 38 | SortAnagramList(&list); 39 | for(auto str : list) { 40 | cout << str << endl; 41 | } 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /leetcode/twosum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | class Solution { 8 | public: 9 | vector twoSum(vector &numbers, int target) { 10 | unordered_map num_map; 11 | for(int i = 0; i < numbers.size(); ++i) { 12 | num_map[numbers[i]] = i+1; 13 | } 14 | for(int i = 0; i < numbers.size(); ++i) { 15 | auto value2 = num_map.find(target - numbers[i]); 16 | if(value2 != num_map.end() && value2->second != (i+1)) { 17 | vector result = { min(i+1, value2->second), 18 | max(i+1, value2->second) }; 19 | return result; 20 | } 21 | } 22 | return vector(); 23 | } 24 | }; 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | Solution s; 29 | vector v = { 1,2,3,4,5,666,0,1,123,999,0}; 30 | vector result = s.twoSum(v, 0); 31 | if(result.size() == 2) { 32 | cout << result[0] << " " << result[1] << endl; 33 | } 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /leetcode/validParentheses.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class Solution { 9 | public: 10 | bool isValid(string s) { 11 | 12 | unordered_map close_parens; 13 | close_parens['('] = ')'; 14 | close_parens['{'] = '}'; 15 | close_parens['['] = ']'; 16 | 17 | stack parens; 18 | 19 | for(auto c : s) { 20 | if(c == '(' || c =='{' || c == '[') { 21 | parens.push(close_parens[c]); 22 | } else if(c ==')' || c == '}' || c == ']') { 23 | if(parens.size() == 0 || parens.top() != c) { 24 | return false; 25 | } 26 | parens.pop(); 27 | } 28 | } 29 | if(parens.size() == 0) { 30 | return true; 31 | } else { 32 | return false; 33 | } 34 | } 35 | }; 36 | 37 | 38 | int main(int argc, char *argv[]) 39 | { 40 | Solution s; 41 | cout << (s.isValid("()()[[{{{}}}]]") ? "TRUE" : "FALSE") << endl; 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /src/allsubsets.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | /* 8 | void GetSubsets(const set& s, vector>* out) { 9 | if(s.size() == 0 || out == nullptr) { 10 | return; 11 | } 12 | out->push_back(s); 13 | for(auto v : s) { 14 | set tmp(s); 15 | tmp.erase(v); 16 | GetSubsets(tmp, out); 17 | } 18 | } 19 | */ 20 | 21 | void GetSubsets(const set& s, vector>* out) { 22 | if(s.size() == 0 || out == nullptr) { 23 | return; 24 | } 25 | for(auto v : s) { 26 | for(auto pset : vector>{*out}) { 27 | set tmp(pset); 28 | tmp.insert(v); 29 | out->push_back(tmp); 30 | } 31 | out->push_back(set{v}); 32 | } 33 | } 34 | 35 | int main() 36 | { 37 | set s{1,2,3,4}; 38 | vector> output; 39 | 40 | GetSubsets(s, &output); 41 | 42 | for(auto o : output) { 43 | for(auto v : o) { 44 | cout << v << " "; 45 | } 46 | cout << endl; 47 | } 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /leetcode/four_sum.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def fourSum(self, nums, target): 3 | """ 4 | :type nums: List[int] 5 | :type target: int 6 | :rtype: List[List[int]] 7 | """ 8 | two_sums = {} 9 | results = set() 10 | for i in range(len(nums)): 11 | for j in range(i+1, len(nums)): 12 | remainder = -(nums[i]+nums[j]-target) 13 | if remainder in two_sums: 14 | for indexes in two_sums[remainder]: 15 | if indexes[0] != i and indexes[1] != i and indexes[0] != j and indexes[1] != j: 16 | values = [nums[indexes[0]],nums[indexes[1]],nums[i],nums[j]] 17 | values.sort() 18 | results.add(tuple(values)) 19 | two_sum = nums[i]+nums[j] 20 | if two_sum not in two_sums: 21 | two_sums[two_sum] = [] 22 | two_sums[two_sum].append((i,j)) 23 | 24 | return [s for s in results] 25 | 26 | s = Solution() 27 | #print s.fourSum([0,0,0,0], 0) 28 | print s.fourSum([2,1,0,-1], 2) 29 | -------------------------------------------------------------------------------- /coursera/algorithms-part1/elementary-sorts/IntersectionSets.txt: -------------------------------------------------------------------------------- 1 | Coursera - Algorithms Part I 2 | Week 2 - Interview Questions - Elementary Sorts 3 | 4 | Question 1: Intersection of two sets 5 | Given two arrays a[] and b[], each containing N distinct 2D points in the plane, 6 | design a subquadratic algorithm to count the number of points that are contained 7 | both in array a[] and array b[]. 8 | 9 | 10 | Solution: 11 | 12 | class Point { 13 | private int x; 14 | private int y; 15 | } 16 | 17 | Duplicate points can be detected by comparing the x and y coordinates of each 18 | points. A brute force approach would involve checking each point in a[] against 19 | each other point in b[]. This requires O(N^2) time, which does not meet the 20 | requires. 21 | 22 | A more optimal solution sorts the two arrays by their coordinates (x then y). 23 | After sorting, a linear scan over each array simultaneously will allow 24 | duplicates to be detected. The iteration requires only incrementing the position 25 | within the array with the smallest point. 26 | 27 | Alternatively, the arrays would be concatenated and sorted. Then, duplicate 28 | points will be sorted next to each other. 29 | -------------------------------------------------------------------------------- /leetcode/regex.py: -------------------------------------------------------------------------------- 1 | # Leetcode Problem 10 2 | # Regular Expression Matching 3 | 4 | class Solution(object): 5 | def isMatch(self, s, p): 6 | """ 7 | :type s: str 8 | :type p: str 9 | :rtype: bool 10 | """ 11 | tbl = [[False]*(len(p)+1) for i in range(len(s)+1)] 12 | tbl[0][0] = True 13 | for si in range(0, len(s)+1): 14 | for pi in range(1, len(p)+1): 15 | if p[pi-1] == '*': 16 | if tbl[si][pi-2]: 17 | # wildcard consumes 0 characters, pass forward previous result 18 | tbl[si][pi] = True 19 | if si > 0 and tbl[si-1][pi] and (p[pi-2] == s[si-1] or p[pi-2] == '.'): 20 | # wildcard consumes 1+ characters, check previous pattern character against string 21 | tbl[si][pi] = True 22 | elif si > 0 and (p[pi-1] == s[si-1] or p[pi-1] == '.'): 23 | # previous string/pattern is True 24 | tbl[si][pi] = tbl[si-1][pi-1] 25 | 26 | return tbl[-1][-1] 27 | 28 | s = Solution() 29 | print s.isMatch('aab', 'c*a*b') 30 | -------------------------------------------------------------------------------- /leetcode/romanToInt.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class Solution { 7 | public: 8 | int romanToInt(string s) { 9 | int value = 0; 10 | for(int i = 0; i < s.size(); ++i) { 11 | int num = getInt(s[i]); 12 | if(i+1 < s.size() && getInt(s[i+1]) > num) { 13 | value += getInt(s[i+1]) - num; 14 | ++i; 15 | } else { 16 | value += num; 17 | } 18 | } 19 | return value; 20 | } 21 | int getInt(char c) { 22 | if(c=='I') { 23 | return 1; 24 | } else if(c=='V') { 25 | return 5; 26 | } else if(c=='X') { 27 | return 10; 28 | } else if(c=='L') { 29 | return 50; 30 | } else if(c=='C') { 31 | return 100; 32 | } else if(c=='D') { 33 | return 500; 34 | } else if(c == 'M') { 35 | return 1000; 36 | } else { 37 | return 0; 38 | } 39 | } 40 | }; 41 | 42 | int main(int argc, char *argv[]) 43 | { 44 | Solution s; 45 | cout << s.romanToInt("MXXI") << endl; 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /leetcode/subsets.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | class Solution { 10 | public: 11 | vector > subsetsWithDup(vector &S) { 12 | vector> subsets = { {} }; 13 | for(auto n : S) { 14 | vector> new_subsets; 15 | for(auto prev_set : subsets) { 16 | auto new_set = prev_set; 17 | new_set.push_back(n); 18 | sort(new_set.begin(), new_set.end()); 19 | new_subsets.push_back(new_set); 20 | } 21 | move(new_subsets.begin(), new_subsets.end(), back_inserter(subsets)); 22 | } 23 | sort(subsets.begin(), subsets.end()); 24 | subsets.erase(unique(subsets.begin(), subsets.end()), subsets.end()); 25 | return subsets; 26 | } 27 | }; 28 | 29 | int main(int argc, char *argv[]) 30 | { 31 | Solution s; 32 | vector set = { 4,1,0}; 33 | auto subsets = s.subsetsWithDup(set); 34 | for(auto v : subsets) { 35 | for(auto n : v) { 36 | cout << n << " "; 37 | } 38 | cout << endl; 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Build and run practice problems 2 | 3 | PROGS= 4 | PROGS+=src/allsubsets 5 | PROGS+=src/anagrams 6 | PROGS+=src/convert 7 | PROGS+=src/libds_btree 8 | PROGS+=src/libds_list 9 | PROGS+=src/philosophers 10 | PROGS+=src/printlastlines 11 | PROGS+=src/producerconsumer 12 | PROGS+=src/reversewords 13 | PROGS+=src/stablesort 14 | PROGS+=src/stringcombinations 15 | PROGS+=src/stringpermutations 16 | PROGS+=src/zeromatrix 17 | PROGS+=src/removechars 18 | PROGS+=src/parenthesization 19 | PROGS+=src/random_median 20 | PROGS+=src/towers 21 | 22 | CXX=g++ 23 | CXXFLAGS=-Wall -Werror -std=c++11 -g -O0 24 | 25 | .PRONY: all clean check 26 | 27 | all: $(PROGS) 28 | 29 | $(PROGS): % : %.cpp 30 | @echo ">> BUILD: $@"; \ 31 | $(CXX) $(CXXFLAGS) $< -o $@; \ 32 | if [ $$? != 0 ]; then \ 33 | echo "\033[0;31mFailure\033[0m"; \ 34 | else \ 35 | echo "\033[0;32mSuccess\033[0m"; \ 36 | fi; \ 37 | 38 | check: $(PROGS) 39 | @for PROG in $(PROGS); do \ 40 | echo ">> TEST: $${PROG}"; \ 41 | $${PROG}; \ 42 | if [ $$? != 0 ]; then \ 43 | echo "\033[0;31mFailure\033[0m"; \ 44 | else \ 45 | echo "\033[0;32mSuccess\033[0m"; \ 46 | fi; \ 47 | done 48 | 49 | clean: 50 | @rm -r $(PROGS) src/*.dSYM >/dev/null 2>&1 || echo "\033[0;32mCleaned\033[0m" 51 | -------------------------------------------------------------------------------- /leetcode/edit_distance.py: -------------------------------------------------------------------------------- 1 | # Leetcode 72 - Edit Distance 2 | 3 | class Solution(object): 4 | def minDistance(self, word1, word2): 5 | """ 6 | :type word1: str 7 | :type word2: str 8 | :rtype: int 9 | """ 10 | if len(word1) == 0 or len(word2) == 0: 11 | return max(len(word1), len(word2)) 12 | if len(word2) > len(word1): 13 | word1, word2 = word2, word1 14 | 15 | dist = [[0]*(len(word1)+1) for i in range(len(word2)+1)] 16 | 17 | for r in range(len(word2)+1): 18 | for c in range(len(word1)+1): 19 | if r == 0 and c == 0: 20 | dist[r][c] = 0 21 | elif r == 0: 22 | dist[r][c] = dist[r][c-1]+1 23 | elif c == 0: 24 | dist[r][c] = dist[r-1][c]+1 25 | else: 26 | dist[r][c] = min(dist[r-1][c-1], dist[r][c-1], dist[r-1][c]) 27 | if dist[r][c] != dist[r-1][c-1] or word1[c-1] != word2[r-1]: 28 | dist[r][c] += 1 29 | 30 | for r in dist: 31 | print r 32 | return dist[-1][-1] 33 | 34 | s = Solution() 35 | 36 | print s.minDistance('zoologicoarchaeologist', 'zoogeologist') 37 | -------------------------------------------------------------------------------- /leetcode/merge_intervals.py: -------------------------------------------------------------------------------- 1 | # Leetcode #56 - Merge Intervals 2 | 3 | class Interval(object): 4 | def __init__(self, s=0, e=0): 5 | self.start = s 6 | self.end = e 7 | def __repr__(self): 8 | return str(self.start) + ' ' + str(self.end) 9 | 10 | def cmp_interval(x, y): 11 | return cmp(x.start, y.start) 12 | 13 | class Solution(object): 14 | def merge(self, intervals): 15 | """ 16 | :type intervals: List[Interval] 17 | :rtype: List[Interval] 18 | """ 19 | # sort by start of interval 20 | # scan through intervals 21 | # if current start within previous interval range 22 | # merge 23 | # otherwise add new interval 24 | print intervals 25 | intervals = sorted(intervals, cmp=cmp_interval) 26 | print intervals 27 | 28 | output = [] 29 | for i in intervals: 30 | if not output: 31 | output.append(i) 32 | else: 33 | if i.start <= output[-1].end: 34 | output[-1].end = i.end 35 | else: 36 | output.append(i) 37 | 38 | return output 39 | 40 | s = Solution() 41 | print s.merge([Interval(1,4), Interval(0,4)]) 42 | -------------------------------------------------------------------------------- /leetcode/restore_ips.py: -------------------------------------------------------------------------------- 1 | # Leetcode 93 2 | # Restore IP Addresses 3 | 4 | class Solution(object): 5 | def restoreIpAddresses(self, s): 6 | """ 7 | :type s: str 8 | :rtype: List[str] 9 | """ 10 | # three dots 11 | # consume 1-3 digits, place dot 12 | # must be 1-3 remaining digits, else invalid 13 | if len(s) > 12: 14 | return [] 15 | dots = '...' 16 | results = [] 17 | self.restore_r(s, dots, 0, 0, '', results) 18 | return results 19 | 20 | def restore_r(self, s, dots, si, di, current, results): 21 | if si >= len(s) and di >= len(dots) and current[-1] != '.': 22 | results.append(''.join(current)) 23 | return 24 | if si >= len(s) or (current and current[-1] != '.'): 25 | return 26 | 27 | num = 0 28 | for i in range(0,min(len(s)-si, 3)): 29 | num *= 10 30 | num += ord(s[si+i]) - ord('0') 31 | if num > 255: 32 | break 33 | tmp = current + str(num) 34 | if di < len(dots): 35 | tmp += dots[di] 36 | self.restore_r(s, dots, si+i+1, di+1, tmp, results) 37 | if s[si] == '0': 38 | break 39 | 40 | 41 | s = Solution() 42 | print s.restoreIpAddresses('010010') 43 | -------------------------------------------------------------------------------- /leetcode/RotateArray.java: -------------------------------------------------------------------------------- 1 | // Leetcode 2 | // Rotate Array 3 | // Only rotation to the right is supported 4 | 5 | public class RotateArray { 6 | public void rotate(int[] nums, int k) { 7 | if (k < 0) { 8 | return; 9 | } 10 | int rotate = k % nums.length; 11 | int[] tmp = new int[nums.length]; 12 | for (int i = 0; i < nums.length; ++i) { 13 | tmp[i] = nums[i]; 14 | } 15 | int pos = 0; 16 | for (int i = nums.length - rotate; i < nums.length; ++i) { 17 | nums[pos++] = tmp[i]; 18 | } 19 | for (int i = 0; i < nums.length - rotate; ++i) { 20 | nums[pos++] = tmp[i]; 21 | } 22 | } 23 | 24 | public void printArray(int[] nums) { 25 | for (int i = 0; i < nums.length; ++i) { 26 | System.out.print(nums[i]); 27 | System.out.print(' '); 28 | } 29 | System.out.println(); 30 | } 31 | 32 | public static void main(String[] args) { 33 | int[] test = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; 34 | 35 | RotateArray s = new RotateArray(); 36 | 37 | System.out.println("Original"); 38 | s.printArray(test); 39 | s.rotate(test, 1); 40 | s.printArray(test); 41 | s.rotate(test, test.length); 42 | s.printArray(test); 43 | s.rotate(test, test.length+1); 44 | s.printArray(test); 45 | s.rotate(test, 5); 46 | s.printArray(test); 47 | s.rotate(test, -1); 48 | s.printArray(test); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /coursera/algorithms-part1/analysis-of-algorithms/ThreeSum.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Coursera - Algorithms Part I 3 | * Week 1 - Interview Questions - Analysis of Algorithms 4 | * 5 | * Question 1: 3-SUM in quadratic time 6 | * 7 | * Design an algorithm for the 3-SUM problem that takes time proportional to N2 8 | * in the worst case. You may assume that you can sort the N integers in time 9 | * proportional to N2 or better. 10 | */ 11 | 12 | import java.util.Collections; 13 | import java.util.ArrayList; 14 | import java.util.Scanner; 15 | 16 | class ThreeSum { 17 | 18 | public static void main(String[] args) { 19 | 20 | // initialize array 21 | ArrayList data = new ArrayList(); 22 | Scanner scan = new Scanner(System.in); 23 | while (scan.hasNextInt()) { 24 | data.add(scan.nextInt()); 25 | } 26 | 27 | // sort array 28 | Collections.sort(data); 29 | 30 | // compute all 3-sum combinations 31 | for (int i = 0; i < data.size()-2; ++i) { 32 | int j = i+1; 33 | int k = data.size()-1; 34 | 35 | while (j < k) { 36 | int sum = data.get(i)+data.get(j)+data.get(k); 37 | if (sum == 0) { 38 | System.out.println(i+":"+data.get(i)+", "+j+":"+data.get(j)+", "+k+":"+data.get(k)); 39 | } 40 | if (sum >= 0) { 41 | --k; 42 | } else { 43 | ++j; 44 | } 45 | } 46 | } 47 | 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /leetcode/permutations2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class Solution { 9 | public: 10 | vector > permuteUnique(vector &num) { 11 | vector> permutations; 12 | permuteUniqueHelper(num, 0, &permutations); 13 | return permutations; 14 | } 15 | 16 | void permuteUniqueHelper(vector num, int index, vector>* list) { 17 | if(index >= num.size() - 1) { 18 | list->push_back(num); 19 | } else { 20 | unordered_set swaps; 21 | for(int i = index; i < num.size(); ++i) { 22 | if(swaps.find(num[i]) == swaps.end()) { 23 | vector tmp(num); 24 | int ntmp = tmp[i]; 25 | tmp[i] = tmp[index]; 26 | tmp[index] = ntmp; 27 | permuteUniqueHelper(tmp, index+1, list); 28 | swaps.insert(ntmp); 29 | } 30 | } 31 | } 32 | } 33 | }; 34 | 35 | int main(int argc, char *argv[]) 36 | { 37 | Solution s; 38 | vector num = {3,3,0,0,2,3,2}; 39 | //vector num = {1,1,2}; 40 | auto result = s.permuteUnique(num); 41 | for(auto v : result) { 42 | for(auto n : v) { 43 | cout << n << " "; 44 | } 45 | cout << endl; 46 | } 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /leetcode/search_range.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def searchRange(self, nums, target): 3 | """ 4 | :type nums: List[int] 5 | :type target: int 6 | :rtype: List[int] 7 | """ 8 | index = self.bsearch(nums, 0, len(nums)-1, target) 9 | if index[0] == -1: 10 | return [-1, -1] 11 | else: 12 | lindex = index 13 | rindex = index 14 | # search left 15 | tmp_index = self.bsearch(nums, lindex[1], lindex[0]-1, target) 16 | while tmp_index[0] != -1: 17 | lindex = tmp_index 18 | tmp_index = self.bsearch(nums, lindex[1], lindex[0]-1, target) 19 | 20 | # search right 21 | tmp_index = self.bsearch(nums, rindex[0]+1, rindex[2], target) 22 | while tmp_index[0] != -1: 23 | rindex = tmp_index 24 | tmp_index = self.bsearch(nums, rindex[0]+1, rindex[2], target) 25 | 26 | return [lindex[0], rindex[0]] 27 | 28 | def bsearch(self, nums, start, end, target): 29 | print start, end 30 | while start <= end: 31 | mid = start + (end-start)/2 32 | if nums[mid] == target: 33 | return [mid, start, end] 34 | elif nums[mid] > target: 35 | end = mid-1 36 | else: 37 | start = mid+1 38 | 39 | return [-1, start, end] 40 | 41 | s = Solution() 42 | print s.searchRange([2, 2], 2) 43 | -------------------------------------------------------------------------------- /src/stringpermutations.cpp: -------------------------------------------------------------------------------- 1 | // Programming Interviews Exposed 2 | // Print All String Permutations 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | // Option 1 11 | void perm(string str, size_t rotate) { 12 | if(str.size() <= rotate) { 13 | cout << str << endl; 14 | } 15 | else { 16 | for(size_t idx = rotate; idx < str.size(); idx++) { 17 | string rstr = str; 18 | char tmp = rstr[rotate]; 19 | rstr[rotate] = rstr[idx]; 20 | rstr[idx] = tmp; 21 | perm(rstr, rotate+1); 22 | } 23 | } 24 | } 25 | 26 | // Option 2 27 | vector GenerateStrings(string source, string target) { 28 | vector results; 29 | if(source.size() == 0) { 30 | results.push_back(target); 31 | } 32 | for(size_t i = 0; i < source.size(); ++i) { 33 | string new_source(source); 34 | string new_target(target); 35 | new_source.erase(i, 1); 36 | new_target.push_back(source.at(i)); 37 | vector tmp_results = GenerateStrings(new_source, new_target); 38 | results.insert(results.end(), tmp_results.begin(), tmp_results.end()); 39 | } 40 | return results; 41 | } 42 | 43 | int main() 44 | { 45 | perm("hat", 0); 46 | perm("tire", 0); 47 | perm("sweat", 0); 48 | 49 | vector results = GenerateStrings("abcd", ""); 50 | for(auto s : results) { 51 | cout << s << endl; 52 | } 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /coursera/algorithms-part1/elementary-sorts/Permutation.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Coursera - Algorithms Part I 3 | * Week 2 - Interview Questions - Elementary Sorts 4 | * 5 | * Question 2: Permutation 6 | * Given two integer arrays of size N, design a subquadratic algorithm to 7 | * determine whether one is a permutation of the other. That is, do they 8 | * contain exactly the same entries but, possibly, in a different order. 9 | * 10 | * Solution: 11 | * 12 | * Sort each integer array and run a linear comparison. If any integer does 13 | * not align with the other array, then they are not a permutation of each 14 | * other. 15 | */ 16 | 17 | import java.util.Arrays; 18 | 19 | class Permutation { 20 | 21 | private static boolean isPermutation(int[] a, int[] b) { 22 | int[] a1 = new int[a.length]; 23 | int[] b1 = new int[b.length]; 24 | System.arraycopy(a, 0, a1, 0, a.length); 25 | System.arraycopy(b, 0, b1, 0, b.length); 26 | 27 | Arrays.sort(a1); 28 | Arrays.sort(b1); 29 | 30 | for (int i = 0; i < a1.length; ++i) { 31 | if (a1[i] != b1[i]) { 32 | return false; 33 | } 34 | } 35 | 36 | return true; 37 | } 38 | 39 | public static void main(String[] args) { 40 | int[] a = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 41 | int[] b = { 1, 3, 4, 6 }; 42 | int[] c = { 1, 3, 5, 7, 9, 2, 4, 6, 8 }; 43 | System.out.println(isPermutation(a, b)); 44 | System.out.println(isPermutation(a, c)); 45 | System.out.println(isPermutation(a, a)); 46 | System.out.println(isPermutation(b, c)); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /leetcode/QueueUsingStack.java: -------------------------------------------------------------------------------- 1 | // Leetcode 2 | // Queue implemented using a stack 3 | 4 | import java.util.Stack; 5 | 6 | class QueueUsingStack { 7 | 8 | private Stack stack = new Stack(); 9 | 10 | // Push element x to the back of queue. 11 | public void push(int x) { 12 | Stack tmp = new Stack(); 13 | while(!stack.empty()) { 14 | tmp.push(stack.peek()); 15 | stack.pop(); 16 | } 17 | stack.push(x); 18 | while(!tmp.empty()) { 19 | stack.push(tmp.peek()); 20 | tmp.pop(); 21 | } 22 | } 23 | 24 | // Removes the element from in front of queue. 25 | public void pop() { 26 | stack.pop(); 27 | } 28 | 29 | // Get the front element. 30 | public int peek() { 31 | return stack.peek(); 32 | } 33 | 34 | // Return whether the queue is empty. 35 | public boolean empty() { 36 | return stack.empty(); 37 | } 38 | 39 | public static void main(String[] args) { 40 | QueueUsingStack queue = new QueueUsingStack(); 41 | 42 | System.out.println(queue.empty()); 43 | queue.push(1); 44 | queue.push(2); 45 | queue.push(3); 46 | queue.push(4); 47 | System.out.println(queue.empty()); 48 | System.out.println(queue.peek()); 49 | queue.pop(); 50 | System.out.println(queue.peek()); 51 | queue.pop(); 52 | System.out.println(queue.peek()); 53 | queue.pop(); 54 | System.out.println(queue.peek()); 55 | queue.pop(); 56 | System.out.println(queue.empty()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /leetcode/reverse_words.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class Solution { 7 | public: 8 | void reverseWords(string &s) { 9 | trim(s); 10 | reverse(s, 0, s.size()-1); 11 | int start = 0; 12 | int end = 0; 13 | while(start < s.size()) { 14 | while(start < s.size() && s[start] == ' ') { 15 | ++start; 16 | } 17 | end = start+1; 18 | while(end < s.size() && s[end] != ' ') { 19 | ++end; 20 | } 21 | reverse(s, start, end-1); 22 | start = end+1; 23 | } 24 | } 25 | 26 | void reverse(string& s, int start, int end) { 27 | while(start < end) { 28 | char tmp = s[start]; 29 | s[start] = s[end]; 30 | s[end] = tmp; 31 | ++start; 32 | --end; 33 | } 34 | } 35 | 36 | void trim(string& s) { 37 | s.erase(0, s.find_first_not_of(' ', 0)); 38 | s.erase(s.find_last_not_of(' ')+1); 39 | cout << "here" << endl; 40 | int pos = 0; 41 | while(pos+1 < s.size()) { 42 | if(s[pos] == ' ' && s[pos+1] == ' ') { 43 | s.erase(pos+1, 1); 44 | } else { 45 | ++pos; 46 | } 47 | } 48 | } 49 | }; 50 | 51 | int main(int argc, char *argv[]) 52 | { 53 | Solution s; 54 | string str = " the sky is blue "; 55 | //s.reverseWords(str); 56 | str = " the sky is blue "; 57 | //s.reverseWords(str); 58 | str = ""; 59 | s.reverseWords(str); 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /src/random_median.cpp: -------------------------------------------------------------------------------- 1 | // Keep track of median value given a random set of numbers 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | struct min_compare { 10 | bool operator() ( int i, int j){ 11 | return i > j; 12 | } 13 | }; 14 | 15 | priority_queue low; 16 | priority_queue, min_compare> high; 17 | 18 | double GetMedian() { 19 | if(low.size() == 0 && high.size() == 0) { 20 | return 0.0; 21 | } else if(low.size() < high.size()) { 22 | return high.top(); 23 | } else { 24 | return (static_cast(low.top()) + static_cast(high.top())) / 2; 25 | } 26 | } 27 | 28 | void AddNumber(int num) { 29 | // always store extra in high heap 30 | if(high.size() == 0) { 31 | high.push(num); 32 | return; 33 | } 34 | 35 | if(low.size() != high.size()) { 36 | if(num < high.top()) { 37 | low.push(num); 38 | } else { 39 | low.push(high.top()); 40 | high.pop(); 41 | high.push(num); 42 | } 43 | } else { 44 | if(num < low.top()) { 45 | high.push(low.top()); 46 | low.pop(); 47 | low.push(num); 48 | } else { 49 | high.push(num); 50 | } 51 | } 52 | } 53 | 54 | int main() 55 | { 56 | for(int i = 0; i < 10; i++) { 57 | int num = rand() % 30; 58 | AddNumber(num); 59 | cout << "Add: " << num << " Median: " << GetMedian() << endl; 60 | //if(i > 1) 61 | //cout << "LOW: " << low.top() << " HIGH: " << high.top() << endl; 62 | } 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /coursera/algorithms-part1/union-find/SuccessorWithDelete.java: -------------------------------------------------------------------------------- 1 | /* 2 | Coursera - Algorithms Part II 3 | 4 | Week 1 - Interview Questions 5 | 6 | Question 3: Successor with delete. 7 | 8 | Given a set of N integers S={0,1,...,N−1} and a sequence of requests of the 9 | following form: 10 | - Remove x from S 11 | - Find the successor of x: the smallest y in S such that y≥x. 12 | 13 | Design a data type so that all operations (except construction) should take 14 | logarithmic time or better. 15 | */ 16 | 17 | /* 18 | Solution: 19 | Use union find data structure to mark successor of each integer. When an 20 | integer is removed, the union find data structure connects to the next 21 | integer in the list (which may be farther up the list). Must be careful with 22 | optimizations since connected component id is the successor integer. 23 | */ 24 | 25 | import edu.princeton.cs.algs4.QuickFindUF; 26 | 27 | class SuccessorWithDelete { 28 | 29 | private QuickFindUF uf; 30 | 31 | public SuccessorWithDelete(int N) { 32 | uf = new QuickFindUF(N); 33 | } 34 | 35 | public void remove(int x) { 36 | uf.union(x, x+1); 37 | } 38 | 39 | public int successor(int x) { 40 | return uf.find(x); 41 | } 42 | 43 | public static void main(String[] args) { 44 | int N = 50; 45 | SuccessorWithDelete swd = new SuccessorWithDelete(50); 46 | System.out.println(swd.successor(10)); 47 | swd.remove(11); 48 | swd.remove(13); 49 | swd.remove(12); 50 | swd.remove(10); 51 | swd.remove(9); 52 | swd.remove(15); 53 | System.out.println(swd.successor(8)); 54 | System.out.println(swd.successor(9)); 55 | System.out.println(swd.successor(10)); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/towers.cpp: -------------------------------------------------------------------------------- 1 | // Towers of Hanoi Example 2 | 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | template 9 | class Adapter : public Container { 10 | public: 11 | typedef typename Container::container_type container_type; 12 | container_type &get_container() { return this->c; } 13 | }; 14 | 15 | typedef Adapter> MyStack; 16 | 17 | MyStack s_source, s_temp, s_dest; 18 | 19 | void PrintStacks(MyStack& source, MyStack& dest, MyStack& temp) { 20 | 21 | cout << "SRC: "; 22 | for(auto i : source.get_container()) { 23 | cout << i << " "; 24 | } 25 | cout << endl; 26 | 27 | cout << "DEST: "; 28 | for(auto i : dest.get_container()) { 29 | cout << i << " "; 30 | } 31 | cout << endl; 32 | 33 | cout << "TEMP: "; 34 | for(auto i : temp.get_container()) { 35 | cout << i << " "; 36 | } 37 | cout << endl; 38 | cout << endl; 39 | } 40 | 41 | void MoveDisc(MyStack& source, MyStack& dest, MyStack& temp, int count) { 42 | if(count == 0) { 43 | return; 44 | } 45 | if(count > 1) { 46 | MoveDisc(source, dest, temp, count-1); 47 | } 48 | 49 | MoveDisc(dest, temp, source, count-1); 50 | dest.push(source.top()); 51 | source.pop(); 52 | PrintStacks(s_source, s_dest, s_temp); 53 | MoveDisc(temp, dest, source, count-1); 54 | 55 | } 56 | 57 | int main() 58 | { 59 | 60 | const int N = 3; 61 | for(int i = N; i > 0; --i) { 62 | s_source.push(i); 63 | } 64 | 65 | PrintStacks(s_source, s_dest, s_temp); 66 | 67 | MoveDisc(s_source, s_dest, s_temp, N); 68 | 69 | PrintStacks(s_source, s_dest, s_temp); 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /coursera/algorithms-part1/analysis-of-algorithms/EggDrop.txt: -------------------------------------------------------------------------------- 1 | Coursera - Algorithms Part I 2 | Week 1 - Interview Questions - Union Find 3 | 4 | Question 3: Egg Drop 5 | 6 | Suppose that you have an N-story building (with floors 1 through N) and plenty 7 | of eggs. An egg breaks if it is dropped from floor T or higher and does not 8 | break otherwise. Your goal is to devise a strategy to determine the value of T 9 | given the following limitations on the number of eggs and tosses: 10 | 11 | Version 0: 1 egg, ≤ T tosses. 12 | Version 1: ~1lgN eggs and ~1lgN tosses. 13 | Version 2: ~lgT eggs and ~2lgT tosses. 14 | Version 3: 2 eggs and ~2sqrt(N) tosses. 15 | Version 4: 2 eggs and ≤ c*sqrt(T) tosses for some fixed constant c. 16 | 17 | 18 | Solutions: 19 | 20 | Version 0 21 | Try each floor starting from the bottom. The first floor that the egg breaks on 22 | is the value of T. 23 | 24 | Version 1 25 | Use a binary search on the floors. First, try floor T/2. If the egg breaks, T 26 | must be equal to T/2 or smaller. If the egg does not break, T must be greater 27 | than T/2. Continue testing the mid-point of the subset of floors until T is 28 | determined. 29 | 30 | Version 2 31 | Start test at floor 0 and exponentially grow (2^t) floor number until first egg 32 | breaks. The value of T must be between 2^t and 2^(t-1). This range can then 33 | be searched in ~lgT tosses using the technique from version 1. 34 | 35 | Version 3 36 | Test floors in increments of sqrt(N) starting from floor 0. When the egg breaks 37 | on floor t, return to the previous test floor t-1 and increment by each floor. 38 | The remaining sqrt(N) tests will be enough to check each floor between floor t-1 39 | and t. The floor that breaks will be the value of T. 40 | 41 | Version 4 42 | -------------------------------------------------------------------------------- /src/convert.cpp: -------------------------------------------------------------------------------- 1 | // Interviews Exposed - PG 101 2 | // Integer/String Conversions 3 | 4 | #include 5 | 6 | using namespace std; 7 | 8 | int StringToInt(const string& str) { 9 | 10 | int value = 0; 11 | size_t index = 0; 12 | bool negate_flag = false; 13 | 14 | if(str[index] == '-') { 15 | negate_flag = true; 16 | index++; 17 | } 18 | 19 | for(; index < str.size(); ++index) { 20 | value *= 10; 21 | value += str[index] - '0'; 22 | } 23 | 24 | if(negate_flag) { 25 | value = -value; 26 | } 27 | 28 | return value; 29 | } 30 | 31 | 32 | string IntToString(const int& value) { 33 | 34 | string str; 35 | int tmp = value; 36 | bool negate_flag = false; 37 | 38 | if(tmp < 0) { 39 | negate_flag = true; 40 | tmp = -tmp; 41 | } 42 | 43 | if(tmp == 0) { 44 | str.insert(0, 1, '0'); 45 | } else { 46 | while(tmp > 0) { 47 | char c = (tmp % 10) + '0'; 48 | str.insert(0, 1, c); 49 | tmp /= 10; 50 | } 51 | } 52 | 53 | if(negate_flag) { 54 | str.insert(0, 1, '-'); 55 | } 56 | 57 | return str; 58 | } 59 | 60 | 61 | int main() 62 | { 63 | cout << StringToInt("-100") << endl; 64 | cout << StringToInt("101") << endl; 65 | cout << StringToInt("3") << endl; 66 | cout << StringToInt("32340357") << endl; 67 | cout << StringToInt("0") << endl; 68 | cout << StringToInt("-1") << endl; 69 | 70 | cout << IntToString(100) << endl; 71 | cout << IntToString(-101) << endl; 72 | cout << IntToString(1287234) << endl; 73 | cout << IntToString(-19467) << endl; 74 | cout << IntToString(0) << endl; 75 | cout << IntToString(-1) << endl; 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /leetcode/dungeon.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class Solution { 7 | public: 8 | 9 | int calculateMinimumHP(vector>& dungeon) { 10 | vector> health(dungeon); 11 | int max_row = dungeon.size() - 1; 12 | for(int row = dungeon.size() - 1; row >= 0; --row) { 13 | int max_col = dungeon[row].size() - 1; 14 | for(int col = dungeon[row].size() - 1; col >= 0; --col) { 15 | int right_pos = -INT_MAX; 16 | int down_pos = -INT_MAX; 17 | if(col < max_col) { 18 | right_pos = health[row][col+1]; 19 | } 20 | if(row < max_row) { 21 | down_pos = health[row+1][col]; 22 | } 23 | 24 | if(col != max_col || row != max_row) { 25 | health[row][col] = max(right_pos, down_pos) + dungeon[row][col]; 26 | } else { 27 | health[row][col] = dungeon[row][col]; 28 | } 29 | 30 | if(health[row][col] > 0) { 31 | health[row][col] = 0; 32 | } 33 | cout << "ROW: " << row << " COL:" << col << " " << health[row][col] << endl; 34 | } 35 | } 36 | if(health[0][0] < 0) { 37 | return 1 - health[0][0]; 38 | } else { 39 | return 1; 40 | } 41 | } 42 | 43 | }; 44 | 45 | 46 | int main(int argc, char *argv[]) 47 | { 48 | vector> tmp = { {0, -3} }; 49 | //vector> tmp = { {-3, 5} }; 50 | //vector> tmp = { {1,-3,3}, {0,-2,0}, {-3,-3,-3} }; 51 | Solution s; 52 | cout << s.calculateMinimumHP(tmp) << endl; 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /src/philosophers.cpp: -------------------------------------------------------------------------------- 1 | // Philosophers Sharing Forks 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | mutex stdout_lock; 11 | 12 | class Philosopher 13 | { 14 | public: 15 | Philosopher (int number, mutex& left, mutex& right) : 16 | number_(number), 17 | left_fork_(left), 18 | right_fork_(right) 19 | {} 20 | virtual ~Philosopher () {} 21 | 22 | void eat() { 23 | int count = 0; 24 | while(count < 10) { 25 | left_fork_.lock(); 26 | right_fork_.lock(); 27 | stdout_lock.lock(); 28 | cout << "Philosopher: #" << number_ << " - Eating - " << count << endl; 29 | stdout_lock.unlock(); 30 | right_fork_.unlock(); 31 | left_fork_.unlock(); 32 | ++count; 33 | } 34 | } 35 | 36 | private: 37 | int number_; 38 | mutex& left_fork_; 39 | mutex& right_fork_; 40 | }; 41 | 42 | int main() 43 | { 44 | const int num_philosophers = 5; 45 | array forks; 46 | array, num_philosophers> philosophers; 47 | array, num_philosophers> threads; 48 | 49 | for(int i = 0; i < num_philosophers; i++) { 50 | if(i == 0) { 51 | philosophers[i] = shared_ptr(new Philosopher(i+1, forks[i], forks[(i+1)%num_philosophers])); 52 | } else { 53 | philosophers[i] = shared_ptr(new Philosopher(i+1, forks[(i+1)%num_philosophers], forks[i])); 54 | } 55 | threads[i] = shared_ptr(new thread(&Philosopher::eat, philosophers[i])); 56 | } 57 | 58 | for(auto t : threads) { 59 | t->join(); 60 | } 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /leetcode/threesum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | class Solution { 8 | public: 9 | vector > threeSum(vector &num) { 10 | vector> results; 11 | sort(num.begin(), num.end()); 12 | for(int i = 0; i < num.size(); ++i) { 13 | if(i > 0 && num[i] == num[i-1]) { 14 | continue; 15 | } 16 | int left = i+1; 17 | int right = num.size() - 1; 18 | while(left < right) { 19 | if(left > i+1 && num[left] == num[left-1]) { 20 | ++left; 21 | continue; 22 | } 23 | if(right < num.size()-1 && num[right] == num[right+1]) { 24 | --right; 25 | continue; 26 | } 27 | int sum = num[i] + num[left] + num[right]; 28 | if(sum == 0) { 29 | results.push_back(vector{num[i], num[left], num[right]}); 30 | ++left; 31 | } else if(sum < 0) { 32 | ++left; 33 | } else { 34 | --right; 35 | } 36 | } 37 | } 38 | return results; 39 | } 40 | }; 41 | 42 | int main(int argc, char *argv[]) 43 | { 44 | Solution s; 45 | vector input = {-1, 0, 1, 2, -1, -4}; 46 | vector input2; 47 | for(int i = -20; i <= 20; ++i) { 48 | input2.push_back(i); 49 | input2.push_back(i); 50 | } 51 | auto results = s.threeSum(input2); 52 | for(auto v : results) { 53 | for(auto n : v) { 54 | cout << n << " "; 55 | } 56 | cout << endl; 57 | } 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /leetcode/wordsearch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | class Solution { 8 | public: 9 | bool exist(vector>& board, string word) { 10 | for(int row = 0; row < board.size(); ++row) { 11 | for(int col = 0; col < board[row].size(); ++col) { 12 | vector> path; 13 | if(WordCheck(board, row, col, path, word, 0)) { 14 | return true; 15 | } 16 | } 17 | } 18 | return false; 19 | } 20 | 21 | bool WordCheck(vector>& board, int row, int col, vector> path, string word, int index) { 22 | if(row < 0 || row > board.size()-1 || col < 0 || col > board[row].size()-1) { 23 | return false; 24 | } else if(board[row][col] != word[index]) { 25 | return false; 26 | } else if(find(begin(path), end(path), pair(row,col)) != end(path) ) { 27 | return false; 28 | } else if(index >= word.size()-1) { 29 | return true; 30 | } else { 31 | path.push_back(pair(row,col)); 32 | if( WordCheck(board, row+1, col, path, word, index+1) || 33 | WordCheck(board, row-1, col, path, word, index+1) || 34 | WordCheck(board, row, col+1, path, word, index+1) || 35 | WordCheck(board, row, col-1, path, word, index+1) ) { 36 | return true; 37 | } 38 | } 39 | return false; 40 | } 41 | }; 42 | 43 | 44 | int main(int argc, char *argv[]) 45 | { 46 | vector> tmp = { {'A','B','C','E'}, {'S','F','C','S'}, {'A','D','E','E'}}; 47 | Solution s; 48 | 49 | cout << "Test1: " << s.exist(tmp, "ABCCED") << endl; 50 | cout << "Test2: " << s.exist(tmp, "ABCB") << endl; 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /coursera/algorithms-part1/stacks-and-queues/CloneLinked.txt: -------------------------------------------------------------------------------- 1 | Coursera - Algorithms Part I 2 | Week 2 - Interview Questions - Stacks and Queues 3 | 4 | Question 5: Clone a linked structure with two pointers per node. Suppose that 5 | you are given a reference to the first node of a linked structure where each 6 | node has two pointers: one pointer to the next node in the sequence (as in a 7 | standard singly-linked list) and one pointer to an arbitrary node. 8 | 9 | Design a linear-time algorithm to create a copy of the doubly-linked structure. 10 | You may modify the original linked structure, but you must end up with two 11 | copies of the original. 12 | 13 | private class Node { 14 | private String item; 15 | private Node next; 16 | private Node random; 17 | } 18 | 19 | 20 | Solution: 21 | 22 | The structure can be cloned in linear time by temporarily modifying the original 23 | nodes to point to the new nodes. The new nodes will also need to temporarily 24 | keep track of the original nodes next pointers, allowing the pointers to be 25 | restored as the random pointers are established in the new structure. 26 | 27 | The psuedocode for the order of operations: 28 | 29 | 30 | # initialize cloned structure with a root 31 | create clone of root as prev 32 | 33 | # create clone of each following node from original structure and cross-link 34 | for each node in original: 35 | create clone node 36 | set prev.next = clone 37 | set clone.item = orig.item 38 | set clone.random = orig.next 39 | set orig.next = clone 40 | prev = clone 41 | 42 | # make another pass through original structure resolving random pointers for cloned structure 43 | for each node in original: 44 | tmpPointer = orig.next.random # original next pointer 45 | orig.next.random = orig.random.next # following original random pointer to find clone random pointer 46 | orig.next = tmpPointer # restore original next pointer 47 | -------------------------------------------------------------------------------- /src/zeromatrix.cpp: -------------------------------------------------------------------------------- 1 | // Cracking The Coding Interview - 1.7 2 | // Zero rows and columns in an MxN matrix 3 | 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | void PropogateZeros(int* matrix[], int M, int N) { 10 | bool* zrows = new bool[M]; 11 | bool* zcols = new bool[N]; 12 | for(int row = 0; row < M; row++) { 13 | for(int col = 0; col < N; col++) { 14 | if(matrix[row][col] == 0) { 15 | zrows[row] = true; 16 | zcols[col] = true; 17 | } 18 | } 19 | } 20 | 21 | // zero rows 22 | for(int row = 0; row < M; row++) { 23 | if(zrows[row]) { 24 | for(int col = 0; col < N; col++) { 25 | matrix[row][col] = 0; 26 | } 27 | } 28 | } 29 | 30 | // zero cols 31 | for(int col = 0; col < N; col++) { 32 | if(zcols[col]) { 33 | for(int row = 0; row < M; row++) { 34 | matrix[row][col] = 0; 35 | } 36 | } 37 | } 38 | 39 | } 40 | 41 | void PrintMatrix(int* matrix[], int M, int N) { 42 | for(int row = 0; row < M; row++) { 43 | for(int col = 0; col < N; col++) { 44 | cout << setw(3) << matrix[row][col] << " "; 45 | } 46 | cout << endl; 47 | } 48 | } 49 | 50 | int main() 51 | { 52 | // allocate matrix 53 | const int ROWS = 10; 54 | const int COLS = 7; 55 | int* matrix[ROWS]; 56 | for(int r = 0; r < ROWS; r++) { 57 | matrix[r] = new int[COLS]; 58 | } 59 | 60 | // initialize matrix 61 | for(int r = 0; r < ROWS; r++) { 62 | for(int c = 0; c < COLS; c++) { 63 | matrix[r][c] = r+c; 64 | } 65 | } 66 | matrix[ROWS/2][COLS/2+2] = 0; 67 | 68 | // print and set zeros 69 | PrintMatrix(matrix, ROWS, COLS); 70 | PropogateZeros(matrix, ROWS, COLS); 71 | PrintMatrix(matrix, ROWS, COLS); 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /coursera/algorithms-part1/stacks-and-queues/StackWithMax.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Coursera - Algorithms Part I 3 | * Week 2 - Interview Questions - Stacks and Queues 4 | * 5 | * Question 2: Stack with max 6 | * 7 | * Create a data structure that efficiently supports the stack operations 8 | * (push and pop) and also a return-the-maximum operation. Assume the elements 9 | * are reals numbers so that you can compare them. 10 | */ 11 | 12 | /** 13 | * Solution: 14 | * 15 | * 1) Iterate over stack to find max element. Time: O(n), Space: O(1) 16 | * 2) Keep an additional list of items in sorted order. Max element is the 17 | * top of the sorted list. Complex to remove elements on pop. Time: O(1) for 18 | * max, O(N) for pop, Space: O(n) 19 | * 3) Keep an additional binary tree of elements. Time: O(lg N), Space: O(N) 20 | */ 21 | 22 | import java.util.Stack; 23 | import java.util.TreeSet; 24 | 25 | class StackWithMax extends Stack { 26 | 27 | private TreeSet tree = new TreeSet(); 28 | 29 | public Item max() { 30 | return tree.last(); 31 | } 32 | 33 | public Item push(Item item) { 34 | super.push(item); 35 | tree.add(item); 36 | return item; 37 | } 38 | 39 | public Item pop() { 40 | Item item = super.pop(); 41 | tree.remove(item); 42 | return item; 43 | } 44 | 45 | public static void main(String[] args) { 46 | 47 | StackWithMax stack = new StackWithMax(); 48 | int i = 1; 49 | int N = 100; 50 | 51 | System.out.println("Size: " + stack.size()); 52 | while (i <= N) { 53 | if (i % 3 == 0) { 54 | System.out.println("Max: " + stack.max()); 55 | } else { 56 | System.out.println("Push: " + i); 57 | stack.push(i); 58 | } 59 | ++i; 60 | } 61 | System.out.println("Size: " + stack.size()); 62 | while (!stack.isEmpty()) { 63 | System.out.println("Pop: " + stack.pop()); 64 | } 65 | System.out.println("Size: " + stack.size()); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /leetcode/LowestCommonAncestor.java: -------------------------------------------------------------------------------- 1 | // Leetcode 2 | // Rotate Array 3 | // Only rotation to the right is supported 4 | 5 | public class LowestCommonAncestor { 6 | 7 | public static class TreeNode { 8 | int val; 9 | TreeNode left; 10 | TreeNode right; 11 | TreeNode(int x) { val = x; } 12 | } 13 | 14 | private class Nodes { 15 | TreeNode pNode; 16 | TreeNode qNode; 17 | TreeNode aNode; 18 | 19 | public Nodes() { 20 | qNode = null; 21 | pNode = null; 22 | aNode = null; 23 | } 24 | } 25 | 26 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 27 | return lowestCommonAncestorHelper(root, p, q).aNode; 28 | } 29 | 30 | private Nodes lowestCommonAncestorHelper(TreeNode root, TreeNode p, TreeNode q) { 31 | if (root == null) { 32 | return new Nodes(); 33 | } else { 34 | Nodes l = lowestCommonAncestorHelper(root.left, p, q); 35 | Nodes r = lowestCommonAncestorHelper(root.right, p, q); 36 | 37 | Nodes local = l; 38 | if (local.pNode == null) { local.pNode = r.pNode; } 39 | if (local.pNode == null && root == p) { local.pNode = root; } 40 | if (local.qNode == null) { local.qNode = r.qNode; } 41 | if (local.qNode == null && root == q) { local.qNode = root; } 42 | if (local.aNode == null) { local.aNode = r.aNode; } 43 | if (local.aNode == null && (local.pNode != null && local.qNode != null) ) { 44 | local.aNode = root; 45 | } 46 | return local; 47 | } 48 | } 49 | 50 | public static void main(String[] args) { 51 | TreeNode root = new TreeNode(1); 52 | root.left = new TreeNode(2); 53 | root.right = new TreeNode(3); 54 | root.right.right = new TreeNode(4); 55 | 56 | LowestCommonAncestor ancestor = new LowestCommonAncestor(); 57 | 58 | System.out.println(ancestor.lowestCommonAncestor(root, root.right.right, root.left).val); 59 | System.out.println(ancestor.lowestCommonAncestor(root, root.right.right, root.right).val); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /leetcode/largest_number.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | class Solution { 11 | public: 12 | 13 | string largestNumber(vector &num) { 14 | sort(begin(num), end(num), CustomCompare); 15 | stringstream stream; 16 | for(auto i : num) { 17 | stream << i; 18 | } 19 | return stream.str(); 20 | } 21 | 22 | struct { 23 | bool operator()(const int& i1, const int& i2) { 24 | int tmp1 = i1; 25 | int tmp2 = i2; 26 | vector d1; 27 | vector d2; 28 | 29 | if(i1 == i2) { 30 | return false; 31 | } 32 | 33 | do { 34 | d1.push_back(tmp1 % 10); 35 | tmp1 = tmp1 / 10; 36 | } while(tmp1 > 0); 37 | do { 38 | d2.push_back(tmp2 % 10); 39 | tmp2 = tmp2 / 10; 40 | } while(tmp2 > 0); 41 | 42 | reverse(begin(d1), end(d1)); 43 | reverse(begin(d2), end(d2)); 44 | 45 | auto d1size = d1.size(); 46 | auto d2size = d2.size(); 47 | 48 | for(int i = 0; i < d1size; ++i) { 49 | d2.push_back(d1[i]); 50 | } 51 | for(int i = 0; i < d2size; ++i) { 52 | d1.push_back(d2[i]); 53 | } 54 | 55 | for(int i = 0; i < d1.size(); ++i) { 56 | if(d1[i] > d2[i]) { 57 | return true; 58 | } else if(d1[i] < d2[i]) { 59 | return false; 60 | } 61 | } 62 | 63 | return false; 64 | } 65 | } CustomCompare; 66 | 67 | }; 68 | 69 | int main(int argc, char *argv[]) 70 | { 71 | Solution s; 72 | //vector A = {9, 950, 930, 0, 91}; 73 | //vector A = {0,0,0,0,0}; 74 | //vector A = {128, 12}; 75 | vector A = {121, 12}; 76 | cout << s.largestNumber(A) << endl; 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /coursera/algorithms-part1/union-find/SocialNetworkConnectivity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Coursera - Algorithms Part I 3 | * Week 1 - Interview Questions - Union Find 4 | * 5 | * Question 1: Social network connectivity 6 | * 7 | * Given a social network containing N members and a log file containing M 8 | * timestamps at which times pairs of members formed friendships, design an 9 | * algorithm to determine the earliest time at which all members are connected 10 | * (i.e., every member is a friend of a friend of a friend ... of a friend). 11 | * Assume that the log file is sorted by timestamp and that friendship is an 12 | * equivalence relation. The running time of your algorithm should be MlogN or 13 | * better and use extra space proportional to N. 14 | */ 15 | 16 | /** 17 | * Solution: 18 | * 19 | * Use a union-find data structure with each site representing a social network 20 | * member. Add unions between sites in time order of friendships being formed. 21 | * After each union is added, check the number of connected components 22 | * within the union-find data structure. If only one, all members are connected. 23 | * 24 | * Must keep track of number of unique components. Decreases when a union occurs 25 | * between different components. 26 | */ 27 | 28 | /** 29 | * Determine when all members of a social network are connected. 30 | */ 31 | class SocialNetworkConnectivity { 32 | 33 | private UnionFindUF uf; 34 | private int numComponents; 35 | 36 | public SocialNetworkConnectivity(int N) { 37 | uf = new QuickFindUF(N); 38 | numComponents = N; 39 | } 40 | 41 | public void addFriendship(int p1, int p2) { 42 | if (!uf.connected(p1, p2)) { 43 | --numComponents; 44 | } 45 | uf.union(p1,p2); 46 | } 47 | 48 | public boolean fullyConnected() { 49 | return this.numComponents == 1; 50 | } 51 | 52 | public static void main(String[] args) { 53 | 54 | // initialize social network data structure with N sites 55 | 56 | while (!f.isEmpty()) { 57 | // read timestamp and relationship 58 | // union relationship 59 | // check if members fully connected 60 | } 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /leetcode/reverse-k-list.py: -------------------------------------------------------------------------------- 1 | # Leetcode 25 2 | # Reverse nodes in k-group 3 | 4 | # Not optimal solution. O(k*n) due to additional passes over list to reverse groups. 5 | # Groups should be reversed all at once instead of repositioning individual nodes. 6 | 7 | 8 | # Definition for singly-linked list. 9 | class ListNode(object): 10 | def __init__(self, x): 11 | self.val = x 12 | self.next = None 13 | 14 | class Solution(object): 15 | def reverseKGroup(self, head, k): 16 | """ 17 | :type head: ListNode 18 | :type k: int 19 | :rtype: ListNode 20 | """ 21 | current = head 22 | new_head = None 23 | prev = None 24 | while current: 25 | count = 0 26 | count_node = current 27 | while count_node and count < k: 28 | count += 1 29 | count_node = count_node.next 30 | if count == k: 31 | swap = current 32 | for sc in range(k-1, 0, -1): 33 | swap_start = swap.next 34 | swap_prev = None 35 | for i in range(sc): 36 | tmp = swap.next.next 37 | swap.next.next = swap 38 | if swap_prev: 39 | swap_prev.next = swap.next 40 | swap_prev = swap.next 41 | swap.next = tmp 42 | swap = swap_start 43 | print_list(swap) 44 | if prev: 45 | prev.next = swap 46 | if not new_head: 47 | new_head = swap 48 | prev = current 49 | current = current.next 50 | else: 51 | break 52 | return new_head or head 53 | 54 | def print_list(head): 55 | current = head 56 | while current: 57 | print current.val, 58 | print ' ', 59 | current = current.next 60 | print 61 | 62 | head = ListNode(1) 63 | current = head 64 | for i in range(2,5): 65 | current.next = ListNode(i) 66 | current = current.next 67 | 68 | s = Solution() 69 | print_list(head) 70 | new_head = s.reverseKGroup(head, 4) 71 | print_list(new_head) 72 | 73 | -------------------------------------------------------------------------------- /src/producerconsumer.cpp: -------------------------------------------------------------------------------- 1 | // Producer/consumer using C++11 threads/mutexes 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | class Buffer 11 | { 12 | public: 13 | Buffer () : 14 | index(0) 15 | {}; 16 | virtual ~Buffer () {} 17 | 18 | void add(int value) { 19 | while(true) { 20 | lock_guard lock(bmutex); 21 | if(index < (buf.size() - 1)) { 22 | cout << "Add: " << value << endl; 23 | buf[index++] = value; 24 | break; 25 | } 26 | } 27 | } 28 | 29 | int remove() { 30 | while(true) { 31 | lock_guard lock(bmutex); 32 | if(index > 0) { 33 | int value = buf[--index]; 34 | cout << "Remove: " << value << endl; 35 | return value; 36 | } 37 | } 38 | } 39 | 40 | private: 41 | array buf; 42 | size_t index; 43 | mutex bmutex; 44 | }; 45 | 46 | class Producer 47 | { 48 | public: 49 | Producer (Buffer& b, int range) : 50 | b(b), 51 | rd(), 52 | e1(rd()), 53 | uniform_dist(1, range) 54 | {}; 55 | virtual ~Producer () {} 56 | void run() { 57 | int ticks = 0; 58 | while(ticks < 100) { 59 | int value = uniform_dist(e1); 60 | b.add(value); 61 | ++ticks; 62 | } 63 | } 64 | private: 65 | Buffer& b; 66 | random_device rd; 67 | default_random_engine e1; 68 | uniform_int_distribution uniform_dist; 69 | }; 70 | 71 | class Consumer 72 | { 73 | public: 74 | Consumer (Buffer& b) : 75 | b(b) 76 | {}; 77 | void run() { 78 | int ticks = 0; 79 | while(ticks < 100) { 80 | b.remove(); 81 | ++ticks; 82 | } 83 | } 84 | virtual ~Consumer () {} 85 | private: 86 | Buffer& b; 87 | }; 88 | 89 | int main() 90 | { 91 | Buffer b; 92 | Producer p(b, 100); 93 | Consumer c(b); 94 | thread pthread(&Producer::run, &p); 95 | thread cthread(&Consumer::run, &c); 96 | pthread.join(); 97 | cthread.join(); 98 | return 0; 99 | } 100 | -------------------------------------------------------------------------------- /coursera/algorithms-part1/stacks-and-queues/StackQueue.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Coursera - Algorithms Part I 3 | * Week 2 - Interview Questions - Stacks and Queues 4 | * 5 | * Question 1: Queue with two stacks 6 | * 7 | * Implement a queue with two stacks so that each queue operations takes a 8 | * constant amortized number of stack operations. 9 | */ 10 | 11 | /** 12 | * Solution: 13 | * 14 | * Use one stack for keeping track of elements queued up and another for 15 | * tracking elements to be dequeued. When the dequeue stack if empty, the 16 | * elements from the enqueue stack are popped and pushed into the dequeue 17 | * stack. This operation reverses the order of elements so they are in FIFO. 18 | * 19 | * The dequeue stack cannot be populated until depleated, otherwise elements 20 | * would be out of order. 21 | */ 22 | 23 | import java.util.Stack; 24 | 25 | class StackQueue { 26 | 27 | private Stack input = new Stack(); 28 | private Stack output = new Stack(); 29 | 30 | public StackQueue() { 31 | 32 | } 33 | 34 | public int size() { 35 | return input.size() + output.size(); 36 | } 37 | 38 | public boolean isEmpty() { 39 | return (size() == 0); 40 | } 41 | 42 | public void enqueue(Item item) { 43 | if (item == null) { 44 | throw new java.lang.NullPointerException(); 45 | } 46 | input.push(item); 47 | } 48 | 49 | public Item dequeue() { 50 | if (isEmpty()) { 51 | throw new java.util.NoSuchElementException(); 52 | } 53 | 54 | if (output.isEmpty()) { 55 | while (!input.isEmpty()) { 56 | output.push(input.pop()); 57 | } 58 | } 59 | 60 | return output.pop(); 61 | } 62 | 63 | // unit testing 64 | public static void main(String[] args) { 65 | StackQueue squeue = new StackQueue(); 66 | int i = 0; 67 | int N = 100; 68 | 69 | System.out.println("Size: " + squeue.size()); 70 | squeue.enqueue(i); 71 | while (i <= N) { 72 | if (i % 3 == 0) { 73 | System.out.println("Dequeue: " + squeue.dequeue()); 74 | } else { 75 | squeue.enqueue(i); 76 | System.out.println("Enqueue: " + i); 77 | } 78 | ++i; 79 | } 80 | System.out.println("Size: " + squeue.size()); 81 | while (!squeue.isEmpty()) { 82 | System.out.println("Dequeue: " + squeue.dequeue()); 83 | } 84 | System.out.println("Size: " + squeue.size()); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /coursera/algorithms-part1/analysis-of-algorithms/BitonicArray.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Coursera - Algorithms Part I 3 | * Week 1 - Interview Questions - Union Find 4 | * 5 | * Question 2: Search in a bitonic array 6 | * An array is bitonic if it is comprised of an increasing sequence of integers 7 | * followed immediately by a decreasing sequence of integers. Write a program 8 | * that, given a bitonic array of N distinct integer values, determines whether 9 | * a given integer is in the array. 10 | * 11 | * Standard version: Use ~3lgN compares in the worst case. 12 | * Signing bonus: Use ~2lgN compares in the worst case (and prove that no 13 | * algorithm can guarantee to perform fewer than ~2lgN compares in the worst case). 14 | */ 15 | 16 | /** 17 | * Solution: 18 | * 19 | * Use three binary searches. 20 | * 1) Locate the point in the array where ascending switchines to descending 21 | * 2) Perform binary search on each half of the array for the target integer 22 | * 23 | */ 24 | 25 | class BitonicArray { 26 | 27 | private static boolean bitonicSearch(int[] array, int start, int end, int target, boolean desc) { 28 | int mid = (start + end) / 2; 29 | if (array[mid] == target) { 30 | return true; 31 | } 32 | if (start > end) { 33 | return false; 34 | } 35 | 36 | if ((desc && array[mid] < target) || (!desc && array[mid] > target)) { 37 | return bitonicSearch(array, start, mid-1, target, desc); 38 | } else { 39 | return bitonicSearch(array, mid+1, end, target, desc); 40 | } 41 | } 42 | 43 | private static int binarySearchPeak(int[] array, int start, int end) { 44 | int mid = (start + end) / 2; 45 | if (start == end) { 46 | return mid; 47 | } else if (array[mid] < array[mid+1]) { 48 | return binarySearchPeak(array, mid+1, end); 49 | } else { 50 | return binarySearchPeak(array, start, mid); 51 | } 52 | } 53 | 54 | private static boolean find(int[] array, int peak, int target) { 55 | return bitonicSearch(array, 0, peak, target, false) || 56 | bitonicSearch(array, peak, array.length-1, target, true); 57 | } 58 | 59 | public static void main(String[] args) { 60 | int[] array = { 1, 2, 3, 4, 5, 15, 10, 9, 8, 7, 6 }; 61 | int target = 0; 62 | 63 | int peak = binarySearchPeak(array, 0, array.length-1); 64 | System.out.println(target + ": " + find(array, peak, target)); 65 | target = 1; 66 | System.out.println(target + ": " + find(array, peak, target)); 67 | target = 8; 68 | System.out.println(target + ": " + find(array, peak, target)); 69 | target = 20; 70 | System.out.println(target + ": " + find(array, peak, target)); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/libds_list.cpp: -------------------------------------------------------------------------------- 1 | // Basic list data structure implemented in C++ 2 | 3 | #include 4 | #include 5 | 6 | class List { 7 | public: 8 | 9 | List(); 10 | ~List(); 11 | void AppendHead(const int& value); 12 | void AppendTail(const int& value); 13 | int RemoveHead(); 14 | int RemoveTail(); 15 | 16 | private: 17 | struct Node { 18 | std::unique_ptr next; 19 | int value; 20 | }; 21 | std::unique_ptr head_; 22 | Node* tail_; 23 | }; 24 | 25 | List::List() : 26 | tail_(nullptr) 27 | {} 28 | 29 | List::~List() {} 30 | 31 | void List::AppendHead(const int& value) { 32 | if(head_.get() == nullptr) { 33 | head_.reset(new List::Node()); 34 | head_.get()->value = value; 35 | tail_ = head_.get(); 36 | } else { 37 | List::Node* tmp = new List::Node(); 38 | tmp->value = value; 39 | tmp->next = std::move(head_); 40 | head_.reset(tmp); 41 | } 42 | } 43 | 44 | void List::AppendTail(const int& value) { 45 | if(head_.get() == nullptr) { 46 | head_.reset(new List::Node()); 47 | head_.get()->value = value; 48 | tail_ = head_.get(); 49 | } else { 50 | List::Node* tmp = new List::Node(); 51 | tmp->value = value; 52 | tmp->next = nullptr; 53 | tail_->next.reset(tmp); 54 | tail_ = tail_->next.get(); 55 | } 56 | } 57 | 58 | int List::RemoveHead() { 59 | if(head_.get() == nullptr) { 60 | return -1; 61 | } else { 62 | int tmp = head_.get()->value; 63 | head_ = std::move(head_.get()->next); 64 | return tmp; 65 | } 66 | } 67 | 68 | int List::RemoveTail() { 69 | if(tail_ == nullptr) { 70 | return -1; 71 | } else if(head_.get() == tail_) { 72 | int tmp = tail_->value; 73 | tail_ = nullptr; 74 | head_.release(); 75 | return tmp; 76 | } else { 77 | int tmp = tail_->value; 78 | Node* prev = nullptr; 79 | Node* current = head_.get(); 80 | while(current != nullptr && current->next.get() != nullptr) { 81 | prev = current; 82 | current = current->next.get(); 83 | } 84 | prev->next.release(); 85 | tail_ = prev; 86 | return tmp; 87 | } 88 | } 89 | 90 | int main() 91 | { 92 | List l; 93 | l.AppendTail(10); 94 | l.AppendHead(1); 95 | l.AppendHead(2); 96 | l.AppendTail(12); 97 | l.AppendHead(3); 98 | l.AppendTail(11); 99 | l.AppendHead(4); 100 | l.AppendTail(13); 101 | std::cout << l.RemoveHead() << std::endl; 102 | std::cout << l.RemoveTail() << std::endl; 103 | std::cout << l.RemoveHead() << std::endl; 104 | std::cout << l.RemoveTail() << std::endl; 105 | std::cout << l.RemoveHead() << std::endl; 106 | std::cout << l.RemoveTail() << std::endl; 107 | std::cout << l.RemoveHead() << std::endl; 108 | std::cout << l.RemoveTail() << std::endl; 109 | std::cout << l.RemoveHead() << std::endl; 110 | std::cout << l.RemoveTail() << std::endl; 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /coursera/algorithms-part1/stacks-and-queues/LinkedListCycle.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Coursera - Algorithms Part I 3 | * Week 2 - Interview Questions - Stacks and Queues 4 | * 5 | * Question 4: Detect cycle in a linked list 6 | * Detect cycle in a linked list. A singly-linked data structure is a data 7 | * structure made up of nodes where each node has a pointer to the next node 8 | * (or a pointer to null). Suppose that you have a pointer to the first node of 9 | * a singly-linked list data structure: 10 | * 11 | * -Determine whether a singly-linked data structure contains a cycle. You may 12 | * use only two pointers into the list (and no other variables). The running 13 | * time of your algorithm should be linear in the number of nodes in the data 14 | * structure. 15 | * 16 | * -If a singly-linked data structure contains a cycle, determine the first 17 | * node that participates in the cycle. you may use only a constant number 18 | * of pointers into the list (and no other variables). The running time of 19 | * your algorithm should be linear in the number of nodes in the data structure. 20 | * 21 | * You may not modify the structure of the linked list. 22 | */ 23 | 24 | class LinkedListCycle { 25 | 26 | public static class Node { 27 | public int value; 28 | public Node next; 29 | 30 | public Node(int value) { 31 | this.value = value; 32 | this.next = null; 33 | } 34 | } 35 | 36 | public static Node cycleFirstNode(Node root) { 37 | if (root == null || root.next == null) { 38 | return null; 39 | } 40 | 41 | Node p1 = root; 42 | Node p2 = root; 43 | 44 | // find cycle in loop where pointers cross 45 | // p1 increments one node per iteration 46 | // p2 increments two nodes per iteration 47 | do { 48 | if (p1 == null || p2 == null || p2.next == null) { 49 | return null; 50 | } 51 | p1 = p1.next; 52 | p2 = p2.next.next; 53 | } while (p1 != p2); 54 | 55 | // find cycle start by resetting p1 to beginning 56 | // increment pointers until they meet again 57 | p1 = root; 58 | while (p1 != p2) { 59 | p1 = p1.next; 60 | p2 = p2.next; 61 | } 62 | 63 | return p1; 64 | } 65 | 66 | public static void main(String[] args) { 67 | 68 | Node root = new Node(0); 69 | Node current = root; 70 | Node cycle = null; 71 | 72 | // generate list 73 | int total = 20; 74 | int count = 1; 75 | while (count < total) { 76 | Node newNode = new Node(count); 77 | current.next = newNode; 78 | current = newNode; 79 | ++count; 80 | if (count == 3) { 81 | cycle = current; 82 | } 83 | } 84 | 85 | // create cycle 86 | System.out.println("Cycle inserted at: " + cycle.value); 87 | current.next = cycle; 88 | 89 | // locate cycle 90 | Node found = cycleFirstNode(root); 91 | if (cycle == null) { 92 | System.out.println("No Cycle"); 93 | } else { 94 | System.out.println("Cycle located at: " + found.value); 95 | } 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /leetcode/min_stack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | class MinStack { 6 | public: 7 | MinStack() { 8 | _stack_size = 4; 9 | _index_top = -1; 10 | _index_min = -1; 11 | _stack = new int[_stack_size]; 12 | } 13 | 14 | ~MinStack() { 15 | delete[] _stack; 16 | } 17 | 18 | void push(int x) { 19 | if(_index_top == _stack_size-1) { 20 | grow(); 21 | } 22 | _stack[++_index_top] = x; 23 | if(_index_min != -1) { 24 | if(_stack[_index_top] < _stack[_index_min]) { 25 | _index_min = _index_top; 26 | } 27 | } else { 28 | _index_min = _index_top; 29 | } 30 | } 31 | 32 | void pop() { 33 | if(_index_top >= 0) { 34 | --_index_top; 35 | if(_index_top >= 0) { 36 | _index_min = 0; 37 | for(int i = 1; i <= _index_top; ++i) { 38 | if(_stack[i] < _stack[_index_min]) { 39 | _index_min = i; 40 | } 41 | } 42 | } else { 43 | _index_min = -1; 44 | } 45 | } 46 | shrink(); 47 | } 48 | 49 | int top() { 50 | if(_index_top >= 0) { 51 | return _stack[_index_top]; 52 | } 53 | return -1; 54 | } 55 | 56 | int getMin() { 57 | if(_index_min == -1) { 58 | return -1; 59 | } 60 | return _stack[_index_min]; 61 | } 62 | 63 | private: 64 | 65 | void grow() { 66 | _stack_size *= 2; 67 | resize(); 68 | } 69 | 70 | void shrink() { 71 | if(_index_top < _stack_size / 2) { 72 | _stack_size /= 2; 73 | resize(); 74 | } 75 | } 76 | 77 | void resize() { 78 | int* old_stack = _stack; 79 | _stack = new int[_stack_size]; 80 | for(int i = 0; i <= _index_top; ++i) { 81 | _stack[i] = old_stack[i]; 82 | } 83 | delete[] old_stack; 84 | } 85 | 86 | int* _stack; 87 | int _stack_size; // allocated size 88 | int _index_top; // number of elements 89 | int _index_min; // index of min element 90 | 91 | }; 92 | 93 | int main(int argc, char *argv[]) 94 | { 95 | MinStack stack; 96 | stack.push(10); 97 | stack.push(6); 98 | stack.push(10); 99 | stack.push(20); 100 | stack.push(8); 101 | stack.push(10); 102 | stack.push(10); 103 | stack.push(-110); 104 | stack.push(10); 105 | cout << stack.top() << endl; 106 | cout << stack.getMin() << endl; 107 | stack.pop(); 108 | stack.pop(); 109 | stack.pop(); 110 | stack.pop(); 111 | stack.pop(); 112 | stack.pop(); 113 | stack.pop(); 114 | stack.pop(); 115 | stack.pop(); 116 | stack.pop(); 117 | cout << stack.top() << endl; 118 | cout << stack.getMin() << endl; 119 | return 0; 120 | } 121 | -------------------------------------------------------------------------------- /leetcode/multiply_strings.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | class Solution { 8 | public: 9 | string multiply(string num1, string num2) { 10 | 11 | if(num1 == "0" || num2 == "0") { 12 | return "0"; 13 | } 14 | 15 | vector digits1 = ConvertToDigits(num1); 16 | vector digits2 = ConvertToDigits(num2); 17 | 18 | // multiply each digit of num1 19 | vector> partial_results; 20 | vector offset; 21 | for(auto d1 : digits1) { 22 | int carry = 0; 23 | vector partial(offset); 24 | for(auto d2 : digits2) { 25 | int m = (d1*d2) + carry; 26 | partial.push_back(m%10); 27 | carry = m / 10; 28 | } 29 | if(carry > 0) { 30 | partial.push_back(carry); 31 | } 32 | partial_results.push_back(partial); 33 | offset.push_back(0); 34 | } 35 | 36 | // sum all partial results 37 | vector result(partial_results[0]); 38 | partial_results.erase(begin(partial_results)); 39 | for(auto p : partial_results) { 40 | int carry = 0; 41 | int index = 0; 42 | for(index = 0; index < p.size() && index < result.size(); ++index) { 43 | result[index] += p[index] + carry; 44 | carry = result[index] / 10; 45 | result[index] = result[index] % 10; 46 | } 47 | for(; index < p.size(); ++index) { 48 | int tmp = p[index] + carry; 49 | result.push_back(tmp%10); 50 | carry = tmp/10; 51 | } 52 | if(carry > 0) { 53 | for(; index < result.size(); ++index) { 54 | int tmp = result[index] + carry; 55 | result.push_back(tmp%10); 56 | carry = tmp/10; 57 | } 58 | if(carry > 0) { 59 | result.push_back(carry); 60 | carry = 0; 61 | } 62 | } 63 | } 64 | 65 | string str = DigitsToString(result); 66 | return str; 67 | } 68 | 69 | // returns string from array of reversed digits 70 | string DigitsToString(const vector& num) { 71 | string tmp; 72 | for(int i = num.size() - 1; i >= 0; --i) { 73 | tmp.push_back('0' + num[i]); 74 | } 75 | return tmp; 76 | } 77 | 78 | // returns string as digits in reverse order 79 | vector ConvertToDigits(const string& num) { 80 | vector tmp; 81 | for(int i = num.size() - 1; i >= 0; --i) { 82 | tmp.push_back(num[i] - '0'); 83 | } 84 | return tmp; 85 | } 86 | }; 87 | 88 | int main(int argc, char *argv[]) 89 | { 90 | Solution s; 91 | cout << s.multiply("99", "22") << endl; 92 | cout << s.multiply("702", "34") << endl; 93 | cout << s.multiply("123908", "234876") << endl; 94 | cout << s.multiply("9133", "0") << endl; 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /leetcode/validnumbers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | class Solution { 8 | public: 9 | bool isNumber(const char *s) { 10 | string tmp(s); 11 | int index = 0; 12 | transform(begin(tmp), end(tmp), begin(tmp), ::tolower); 13 | SkipWhiteSpace(tmp, index); 14 | if(index == tmp.size()) { 15 | return false; 16 | } 17 | if(tmp.compare(index, 2, "0x") == 0) { 18 | index += 2; 19 | if(!ReadHex(tmp, index)) { 20 | return false; 21 | } 22 | } else { 23 | bool number = false; 24 | bool fraction = false; 25 | bool exponent = false; 26 | ReadPrefix(s, index); 27 | if(index < tmp.size() && s[index] != '.') { 28 | if(!ReadNumbers(tmp, index)) { 29 | return false; 30 | } else { 31 | number = true; 32 | } 33 | } 34 | if(index < tmp.size() && s[index] == '.') { 35 | ++index; 36 | if(!ReadNumbers(tmp, index) && !number) { 37 | return false; 38 | } else { 39 | fraction = true; 40 | } 41 | } 42 | if(index < tmp.size() && s[index] == 'e') { 43 | ++index; 44 | ReadPrefix(s, index); 45 | if(!ReadNumbers(tmp, index)) { 46 | return false; 47 | } else { 48 | exponent = true; 49 | } 50 | } 51 | } 52 | SkipWhiteSpace(tmp, index); 53 | if(index == tmp.size()) { 54 | return true; 55 | } else { 56 | return false; 57 | } 58 | } 59 | 60 | void ReadPrefix(const string& s, int& index) { 61 | if(s[index] == '-' || s[index] == '+') { 62 | ++index; 63 | } 64 | } 65 | 66 | bool ReadNumbers(const string& s, int& index) { 67 | bool valid = false; 68 | while(index < s.size()) { 69 | if( !(s[index] >= '0' && s[index] <= '9') ) { 70 | break; 71 | } 72 | ++index; 73 | valid = true; 74 | } 75 | return valid; 76 | } 77 | 78 | bool ReadHex(const string& s, int& index) { 79 | bool valid = false; 80 | while(index < s.size()) { 81 | if( !( (s[index] >= 'a' && s[index] <= 'z') || 82 | (s[index] >= '0' && s[index] <= '9') ) ) { 83 | break; 84 | } 85 | ++index; 86 | valid = true; 87 | } 88 | return valid; 89 | } 90 | 91 | void SkipWhiteSpace(const string& s, int& index) { 92 | while(isspace(s[index])) { 93 | ++index; 94 | } 95 | } 96 | }; 97 | 98 | int main(int argc, char *argv[]) 99 | { 100 | Solution s; 101 | cout << s.isNumber("2e0") << endl; 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /src/libds_btree.cpp: -------------------------------------------------------------------------------- 1 | // Basic binary tree data structure implemented in C++ 2 | 3 | #include 4 | #include 5 | 6 | class BinaryTree { 7 | public: 8 | BinaryTree(); 9 | ~BinaryTree(); 10 | void Insert(const int& value); 11 | bool Remove(const int& value); 12 | bool Find(const int& value); 13 | void Print(std::ostream& stream); 14 | 15 | private: 16 | struct Node { 17 | std::unique_ptr left; 18 | std::unique_ptr right; 19 | int value; 20 | }; 21 | typedef std::unique_ptr NodePtr; 22 | 23 | void PrintPreOrder(Node* root, std::ostream& stream); 24 | void InsertNode(NodePtr& ptr); 25 | 26 | NodePtr root_; 27 | }; 28 | 29 | BinaryTree::BinaryTree() : 30 | root_(nullptr) 31 | {} 32 | 33 | BinaryTree::~BinaryTree() {} 34 | 35 | void BinaryTree::Insert(const int& value) { 36 | if(!root_) { 37 | root_.reset(new Node()); 38 | root_->value = value; 39 | return; 40 | } 41 | Node* current = root_.get(); 42 | while(current != nullptr) { 43 | if(current->value >= value) { 44 | if(!current->left) { 45 | current->left.reset(new Node()); 46 | current->left->value = value; 47 | break; 48 | } 49 | current = current->left.get(); 50 | } else { 51 | if(!current->right) { 52 | current->right.reset(new Node()); 53 | current->right->value = value; 54 | break; 55 | } 56 | current = current->right.get(); 57 | } 58 | } 59 | } 60 | 61 | void BinaryTree::InsertNode(NodePtr& ptr) { 62 | if(!ptr) { 63 | return; 64 | } 65 | if(!root_) { 66 | root_ = std::move(ptr); 67 | return; 68 | } 69 | Node* current = root_.get(); 70 | while(current != nullptr) { 71 | if(current->value >= ptr->value) { 72 | if(!current->left) { 73 | current->left = std::move(ptr); 74 | break; 75 | } 76 | current = current->left.get(); 77 | } else { 78 | if(!current->right) { 79 | current->right = std::move(ptr); 80 | break; 81 | } 82 | current = current->right.get(); 83 | } 84 | } 85 | } 86 | 87 | bool BinaryTree::Remove(const int& value) { 88 | Node* current = root_.get(); 89 | if(current->value == value) { 90 | NodePtr right_tmp(std::move(current->right)); 91 | root_ = std::move(current->left); 92 | InsertNode(right_tmp); 93 | return true; 94 | } 95 | while(current != nullptr) { 96 | if(current->value >= value) { 97 | if(current->left && current->left->value == value) { 98 | NodePtr right_tmp(std::move(current->left->right)); 99 | current->left = std::move(current->left->left); 100 | InsertNode(right_tmp); 101 | return true; 102 | } 103 | current = current->left.get(); 104 | } else { 105 | if(current->right && current->right->value == value) { 106 | NodePtr right_tmp(std::move(current->right->right)); 107 | current->right = std::move(current->right->left); 108 | InsertNode(right_tmp); 109 | return true; 110 | } 111 | current = current->right.get(); 112 | } 113 | } 114 | return false; 115 | } 116 | 117 | bool BinaryTree::Find(const int& value) { 118 | Node* current = root_.get(); 119 | while(current != nullptr) { 120 | if(current->value == value) { 121 | return true; 122 | } 123 | else if(current->value >= value) { 124 | current = current->left.get(); 125 | } else { 126 | current = current->right.get(); 127 | } 128 | } 129 | return false; 130 | } 131 | 132 | void BinaryTree::Print(std::ostream& stream) { 133 | PrintPreOrder(root_.get(), stream); 134 | stream << std::endl; 135 | } 136 | 137 | void BinaryTree::PrintPreOrder(Node* root, std::ostream& stream) { 138 | if(root) { 139 | PrintPreOrder(root->left.get(), stream); 140 | stream << root->value << " "; 141 | PrintPreOrder(root->right.get(), stream); 142 | } 143 | } 144 | 145 | int main() 146 | { 147 | BinaryTree t; 148 | t.Insert(1); 149 | t.Insert(97); 150 | t.Insert(44); 151 | t.Insert(4); 152 | t.Insert(3); 153 | t.Insert(10); 154 | t.Insert(100); 155 | t.Insert(5); 156 | t.Insert(5); 157 | t.Print(std::cout); 158 | std::cout << "Find: " << 10 << " : " << t.Find(10) << std::endl; 159 | std::cout << "Find: " << 100 << " : " << t.Find(100) << std::endl; 160 | std::cout << "Find: " << 99 << " : " << t.Find(99) << std::endl; 161 | t.Remove(10); 162 | t.Remove(5); 163 | t.Remove(4); 164 | t.Remove(100); 165 | t.Remove(44); 166 | t.Print(std::cout); 167 | t.Remove(5); 168 | t.Remove(1); 169 | t.Remove(3); 170 | t.Remove(97); 171 | t.Print(std::cout); 172 | t.Insert(5); 173 | t.Insert(5); 174 | t.Print(std::cout); 175 | 176 | return 0; 177 | } 178 | -------------------------------------------------------------------------------- /coursera/algorithms-part1/union-find/WeightedQuickUnionHeight.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Coursera - Algorithms Part II 3 | * 4 | * Week 1 - Interview Questions 5 | * Question 4: Union-by-size 6 | * 7 | * Develop a union-find implementation that uses the same basic strategy as 8 | * weighted quick-union but keeps track of tree height and always links the 9 | * shorter tree to the taller one. Prove a lgN upper bound on the height of the 10 | * trees for N sites with your algorithm. 11 | */ 12 | 13 | import edu.princeton.cs.algs4.StdIn; 14 | import edu.princeton.cs.algs4.StdOut; 15 | 16 | /** 17 | * The WeightedQuickUnionUF class represents a union-find data structure. 18 | * It supports the union and find operations, along with 19 | * methods for determinig whether two objects are in the same component 20 | * and the total number of components. 21 | *

22 | * This implementation uses weighted quick union by size (without path compression). 23 | * Initializing a data structure with N objects takes linear time. 24 | * Afterwards, union, find, and connected take 25 | * logarithmic time (in the worst case) and count takes constant 26 | * time. 27 | *

28 | * For additional documentation, see Section 1.5 of 29 | * Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne. 30 | * 31 | * @author Robert Sedgewick 32 | * @author Kevin Wayne 33 | */ 34 | public class WeightedQuickUnionHeight { 35 | private int[] parent; // parent[i] = parent of i 36 | private int[] height; // height[i] = height of subtree rooted at i 37 | private int count; // number of components 38 | 39 | /** 40 | * Initializes an empty union-find data structure with N isolated components 0 through N-1. 41 | * @param N the number of objects 42 | * @throws java.lang.IllegalArgumentException if N < 0 43 | */ 44 | public WeightedQuickUnionHeight(int N) { 45 | count = N; 46 | parent = new int[N]; 47 | height = new int[N]; 48 | for (int i = 0; i < N; i++) { 49 | parent[i] = i; 50 | height[i] = 1; 51 | } 52 | } 53 | 54 | /** 55 | * Returns the number of components. 56 | * @return the number of components (between 1 and N) 57 | */ 58 | public int count() { 59 | return count; 60 | } 61 | 62 | /** 63 | * Returns the component identifier for the component containing site p. 64 | * @param p the integer representing one site 65 | * @return the component identifier for the component containing site p 66 | * @throws java.lang.IndexOutOfBoundsException unless 0 <= p < N 67 | */ 68 | public int find(int p) { 69 | validate(p); 70 | while (p != parent[p]) 71 | p = parent[p]; 72 | return p; 73 | } 74 | 75 | // validate that p is a valid index 76 | private void validate(int p) { 77 | int N = parent.length; 78 | if (p < 0 || p >= N) { 79 | throw new IndexOutOfBoundsException("index " + p + " is not between 0 and " + (N-1)); 80 | } 81 | } 82 | 83 | /** 84 | * Are the two sites p and q in the same component? 85 | * @param p the integer representing one site 86 | * @param q the integer representing the other site 87 | * @return true if the two sites p and q 88 | * are in the same component, and false otherwise 89 | * @throws java.lang.IndexOutOfBoundsException unless both 0 <= p < N and 0 <= q < N 90 | */ 91 | public boolean connected(int p, int q) { 92 | return find(p) == find(q); 93 | } 94 | 95 | 96 | /** 97 | * Merges the component containing sitep with the component 98 | * containing site q. 99 | * @param p the integer representing one site 100 | * @param q the integer representing the other site 101 | * @throws java.lang.IndexOutOfBoundsException unless both 0 <= p < N and 0 <= q < N 102 | */ 103 | public void union(int p, int q) { 104 | int rootP = find(p); 105 | int rootQ = find(q); 106 | if (rootP == rootQ) return; 107 | 108 | // make shorter tree point to larger one 109 | if (height[rootP] < height[rootQ]) { 110 | parent[rootP] = rootQ; 111 | height[rootQ] = Math.max(height[rootP]+1, height[rootQ]); 112 | } 113 | else { 114 | parent[rootQ] = rootP; 115 | height[rootP] = Math.max(height[rootQ]+1, height[rootP]); 116 | } 117 | count--; 118 | } 119 | 120 | 121 | /** 122 | * Reads in a sequence of pairs of integers (between 0 and N-1) from standard input, 123 | * where each integer represents some object; 124 | * if the objects are in different components, merge the two components 125 | * and print the pair to standard output. 126 | */ 127 | public static void main(String[] args) { 128 | int N = StdIn.readInt(); 129 | WeightedQuickUnionUF uf = new WeightedQuickUnionUF(N); 130 | while (!StdIn.isEmpty()) { 131 | int p = StdIn.readInt(); 132 | int q = StdIn.readInt(); 133 | if (uf.connected(p, q)) continue; 134 | uf.union(p, q); 135 | StdOut.println(p + " " + q); 136 | } 137 | StdOut.println(uf.count() + " components"); 138 | } 139 | 140 | } 141 | 142 | 143 | /****************************************************************************** 144 | * Copyright 2002-2015, Robert Sedgewick and Kevin Wayne. 145 | * 146 | * This file is part of algs4.jar, which accompanies the textbook 147 | * 148 | * Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne, 149 | * Addison-Wesley Professional, 2011, ISBN 0-321-57351-X. 150 | * http://algs4.cs.princeton.edu 151 | * 152 | * 153 | * algs4.jar is free software: you can redistribute it and/or modify 154 | * it under the terms of the GNU General Public License as published by 155 | * the Free Software Foundation, either version 3 of the License, or 156 | * (at your option) any later version. 157 | * 158 | * algs4.jar is distributed in the hope that it will be useful, 159 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 160 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 161 | * GNU General Public License for more details. 162 | * 163 | * You should have received a copy of the GNU General Public License 164 | * along with algs4.jar. If not, see http://www.gnu.org/licenses. 165 | ******************************************************************************/ 166 | -------------------------------------------------------------------------------- /coursera/algorithms-part1/union-find/WeightedQuickUnionUF.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Coursera - Algorithms Part II 3 | * 4 | * Week 1 - Interview Questions 5 | * 6 | * Union-find with specific canonical element. Add a method find() to the 7 | * union-find data type so that find(i) returns the largest element in the 8 | * connected component containing i. The operations, union(), connected(), and 9 | * find() should all take logarithmic time or better. 10 | * 11 | * For example, if one of the connected components is {1,2,6,9}, then the find() 12 | * method should return 9 for each of the four elements in the connected 13 | * components because 9 is larger 1, 2, and 6. 14 | ******************************************************************************/ 15 | 16 | 17 | /****************************************************************************** 18 | * Compilation: javac WeightedQuickUnionUF.java 19 | * Execution: java WeightedQuickUnionUF < input.txt 20 | * Dependencies: StdIn.java StdOut.java 21 | * 22 | * Weighted quick-union (without path compression). 23 | * 24 | ******************************************************************************/ 25 | 26 | import edu.princeton.cs.algs4.StdIn; 27 | import edu.princeton.cs.algs4.StdOut; 28 | 29 | /** 30 | * The WeightedQuickUnionUF class represents a union-find data structure. 31 | * It supports the union and find operations, along with 32 | * methods for determinig whether two objects are in the same component 33 | * and the total number of components. 34 | *

35 | * This implementation uses weighted quick union by size (without path compression). 36 | * Initializing a data structure with N objects takes linear time. 37 | * Afterwards, union, find, and connected take 38 | * logarithmic time (in the worst case) and count takes constant 39 | * time. 40 | *

41 | * For additional documentation, see Section 1.5 of 42 | * Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne. 43 | * 44 | * @author Robert Sedgewick 45 | * @author Kevin Wayne 46 | */ 47 | public class WeightedQuickUnionUF { 48 | private int[] parent; // parent[i] = parent of i 49 | private int[] size; // size[i] = number of objects in subtree rooted at i 50 | private int[] max; // max[i] = largest element in subtree rooted at i 51 | private int count; // number of components 52 | 53 | /** 54 | * Initializes an empty union-find data structure with N isolated components 0 through N-1. 55 | * @param N the number of objects 56 | * @throws java.lang.IllegalArgumentException if N < 0 57 | */ 58 | public WeightedQuickUnionUF(int N) { 59 | count = N; 60 | parent = new int[N]; 61 | size = new int[N]; 62 | max = new int[N]; 63 | for (int i = 0; i < N; i++) { 64 | parent[i] = i; 65 | size[i] = 1; 66 | max[i] = i; 67 | } 68 | } 69 | 70 | /** 71 | * Returns the number of components. 72 | * @return the number of components (between 1 and N) 73 | */ 74 | public int count() { 75 | return count; 76 | } 77 | 78 | /** 79 | * Returns the component identifier for the component containing site p. 80 | * @param p the integer representing one site 81 | * @return the component identifier for the component containing site p 82 | * @throws java.lang.IndexOutOfBoundsException unless 0 <= p < N 83 | */ 84 | public int find(int p) { 85 | validate(p); 86 | while (p != parent[p]) 87 | p = parent[p]; 88 | return p; 89 | } 90 | 91 | public int findMax(int p) { 92 | int rootP = find(p); 93 | return max[rootP]; 94 | } 95 | 96 | // validate that p is a valid index 97 | private void validate(int p) { 98 | int N = parent.length; 99 | if (p < 0 || p >= N) { 100 | throw new IndexOutOfBoundsException("index " + p + " is not between 0 and " + N); 101 | } 102 | } 103 | 104 | /** 105 | * Are the two sites p and q in the same component? 106 | * @param p the integer representing one site 107 | * @param q the integer representing the other site 108 | * @return true if the two sites p and q 109 | * are in the same component, and false otherwise 110 | * @throws java.lang.IndexOutOfBoundsException unless both 0 <= p < N and 0 <= q < N 111 | */ 112 | public boolean connected(int p, int q) { 113 | return find(p) == find(q); 114 | } 115 | 116 | 117 | /** 118 | * Merges the component containing sitep with the component 119 | * containing site q. 120 | * @param p the integer representing one site 121 | * @param q the integer representing the other site 122 | * @throws java.lang.IndexOutOfBoundsException unless both 0 <= p < N and 0 <= q < N 123 | */ 124 | public void union(int p, int q) { 125 | int rootP = find(p); 126 | int rootQ = find(q); 127 | if (rootP == rootQ) return; 128 | 129 | // make smaller root point to larger one 130 | if (size[rootP] < size[rootQ]) { 131 | parent[rootP] = rootQ; 132 | size[rootQ] += size[rootP]; 133 | max[rootQ] = Math.max(max[rootP], max[rootQ]); 134 | } 135 | else { 136 | parent[rootQ] = rootP; 137 | size[rootP] += size[rootQ]; 138 | max[rootP] = Math.max(max[rootP], max[rootQ]); 139 | } 140 | count--; 141 | } 142 | 143 | 144 | /** 145 | * Reads in a sequence of pairs of integers (between 0 and N-1) from standard input, 146 | * where each integer represents some object; 147 | * if the objects are in different components, merge the two components 148 | * and print the pair to standard output. 149 | */ 150 | public static void main(String[] args) { 151 | int N = StdIn.readInt(); 152 | WeightedQuickUnionUF uf = new WeightedQuickUnionUF(N); 153 | while (!StdIn.isEmpty()) { 154 | int p = StdIn.readInt(); 155 | int q = StdIn.readInt(); 156 | if (uf.connected(p, q)) continue; 157 | uf.union(p, q); 158 | StdOut.println(p + " " + q); 159 | } 160 | StdOut.println(uf.count() + " components"); 161 | 162 | for(int i = 0; i < N; ++i) { 163 | StdOut.println("Max: " + i + " = " + uf.findMax(i)); 164 | } 165 | } 166 | 167 | } 168 | 169 | 170 | /****************************************************************************** 171 | * Copyright 2002-2015, Robert Sedgewick and Kevin Wayne. 172 | * 173 | * This file is part of algs4.jar, which accompanies the textbook 174 | * 175 | * Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne, 176 | * Addison-Wesley Professional, 2011, ISBN 0-321-57351-X. 177 | * http://algs4.cs.princeton.edu 178 | * 179 | * 180 | * algs4.jar is free software: you can redistribute it and/or modify 181 | * it under the terms of the GNU General Public License as published by 182 | * the Free Software Foundation, either version 3 of the License, or 183 | * (at your option) any later version. 184 | * 185 | * algs4.jar is distributed in the hope that it will be useful, 186 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 187 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 188 | * GNU General Public License for more details. 189 | * 190 | * You should have received a copy of the GNU General Public License 191 | * along with algs4.jar. If not, see http://www.gnu.org/licenses. 192 | ******************************************************************************/ --------------------------------------------------------------------------------