├── .gitignore ├── .idea ├── .name ├── encodings.xml ├── misc.xml ├── modules.xml ├── scopes │ └── scope_settings.xml ├── syringe.iml ├── vcs.xml └── workspace.xml ├── DISCLAIMER ├── LICENSE ├── README.md ├── java ├── .classpath ├── .project ├── .settings │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.jdt.ui.prefs ├── lib │ └── junit-4.11.jar ├── src │ ├── arrays │ │ ├── Answer0toKRangeQuery.java │ │ ├── BoundedQueue.java │ │ ├── CountInversions.java │ │ ├── FindCommonElements.java │ │ ├── FindNumHops.java │ │ ├── RearrangeInputToTarget.java │ │ ├── SearchBitonicArray.java │ │ └── SimplePhoneNumberAllotter.java │ ├── binarytrees │ │ ├── BstClosestNode.java │ │ ├── BstCountTrees.java │ │ ├── BstDoubleTree.java │ │ ├── BstFindMode.java │ │ ├── BstInsert.java │ │ ├── BstIsBst.java │ │ ├── BstLookup.java │ │ ├── BstMinValue.java │ │ ├── TreeConvertToSinglyLinkedList.java │ │ ├── TreeDepth.java │ │ ├── TreeHasPathSum.java │ │ ├── TreeMirror.java │ │ ├── TreeNode.java │ │ ├── TreeNonRecursiveTraversals.java │ │ ├── TreePrintPaths.java │ │ ├── TreeReconstruct.java │ │ ├── TreeRecursiveTraversals.java │ │ ├── TreeSameTree.java │ │ └── TreeSize.java │ ├── bitsandbytes │ │ └── NumSetBits.java │ ├── cache │ │ ├── Cache.java │ │ └── LRUCache.java │ ├── collections │ │ ├── DeepIterator.java │ │ ├── FilteringIterator.java │ │ ├── HoppingIterator.java │ │ ├── InorderIterator.java │ │ ├── LevelOrderIterator.java │ │ ├── MaxIterator.java │ │ ├── MultiIterator.java │ │ ├── PeekIterator.java │ │ ├── PreorderIterator.java │ │ └── RotatingIterator.java │ ├── common │ │ ├── ArrayUtils.java │ │ ├── BitUtils.java │ │ ├── ListUtils.java │ │ ├── NumberUtils.java │ │ └── Pair.java │ ├── concurrency │ │ ├── BoundedBlockingQueue.java │ │ ├── FirstReadWriteLock.java │ │ ├── ReadWriteLock.java │ │ ├── SchedulingExecutor.java │ │ ├── SecondReadWriteLock.java │ │ ├── Semaphore.java │ │ └── SimpleSchedulingExecutor.java │ ├── dp │ │ ├── CountBinarySubsequences.java │ │ ├── EditDistance.java │ │ ├── LongestCommonSubsequence.java │ │ ├── PrintNeatly.java │ │ ├── RatInAMaze.java │ │ ├── RetrieveSentenceWithShuffledWords.java │ │ └── RobotMove.java │ ├── exceptions │ │ └── EmptyHeapException.java │ ├── general │ │ ├── BinaryGap.java │ │ ├── DigitSerializedArray.java │ │ ├── EnglishKeyboard.java │ │ ├── FindNumCombinations.java │ │ ├── KnightsTour.java │ │ ├── LexicographicalRanking.java │ │ ├── MatrixRegionSum.java │ │ ├── MaximalSum.java │ │ ├── Maze.java │ │ ├── MeetingRoom.java │ │ ├── MergeIntervals.java │ │ ├── MinimumMeetingRooms.java │ │ ├── NQueens.java │ │ ├── NextLexciographicalPermutation.java │ │ ├── NextPalindromeNumber.java │ │ ├── NumEvenSumPairs.java │ │ ├── NumberOfZerosInFactorial.java │ │ ├── PalindromeNumber.java │ │ ├── PascalsTriangle.java │ │ ├── PermutationsCombinations.java │ │ ├── PowerFunctions.java │ │ ├── PrimeFactors.java │ │ ├── RainWater.java │ │ ├── RatInAMaze.java │ │ ├── RomanNumerals.java │ │ ├── Schedule.java │ │ ├── Shuffle.java │ │ ├── SkylineOfACity.java │ │ ├── SubsetSum.java │ │ ├── ThreeSum.java │ │ ├── Time.java │ │ ├── TwoDifference.java │ │ ├── TwoSum.java │ │ └── YoungsTableau.java │ ├── graphs │ │ ├── BloodRelatives.java │ │ ├── GraphNode.java │ │ ├── SearchingTechniques.java │ │ ├── SocialNetworkConnectivity.java │ │ └── SpellChecker.java │ ├── linkedlists │ │ ├── List.java │ │ └── SinglyLinkedList.java │ ├── sorting │ │ ├── FindMinLengthUnsortedSubArray.java │ │ ├── Heap.java │ │ ├── HeapSort.java │ │ ├── InsertionSort.java │ │ ├── KwayMerge.java │ │ ├── MergeSort.java │ │ ├── MergeWithSpaceForOtherArray.java │ │ ├── QuickSort.java │ │ ├── SimpleHeapImpl.java │ │ ├── Sort012.java │ │ └── StupidSort.java │ ├── strings │ │ ├── CheckInterleavedStrings.java │ │ ├── LongestPalindromicSubstring.java │ │ ├── LongestSubstringWithNoRepetition.java │ │ ├── NaivePatternMatching.java │ │ ├── RegexMatching.java │ │ ├── SentenceReverse.java │ │ └── StringSerialization.java │ └── trees │ │ ├── NaryTreeNode.java │ │ ├── NaryTreeSerialization.java │ │ └── SumTree.java └── tests │ ├── AllTests.java │ ├── arrays │ ├── RearrangeInputToTargetTest.java │ └── SimplePhoneNumberAllotterTest.java │ ├── binarytree │ ├── BstClosestNodeTest.java │ └── BstFindModeTest.java │ ├── bitsandbytes │ └── NumSetBitsTest.java │ ├── cache │ └── LRUCacheTest.java │ ├── collections │ ├── DeepIteratorTest.java │ └── PeekIteratorTest.java │ ├── common │ └── NumberUtilsTest.java │ ├── general │ └── RainWaterTest.java │ ├── lists │ └── SinglyLinkedListTest.java │ └── sorting │ ├── HeapSortTest.java │ ├── InsertionSortTest.java │ ├── MergeSortTest.java │ ├── QuickSortTest.java │ ├── SimpleHeapImplTest.java │ └── StupidSortTest.java └── ruby ├── .idea ├── .name ├── encodings.xml ├── misc.xml ├── modules.xml ├── ruby.iml ├── scopes │ └── scope_settings.xml ├── vcs.xml └── workspace.xml ├── spec ├── .gitkeep ├── arrays │ ├── sort_012_spec.rb │ └── sub_array_with_max_sum_spec.rb ├── binary_trees │ └── tree_to_circular_list_spec.rb ├── lists │ └── singly_linked_list_spec.rb ├── sorting │ ├── heap_sort_spec.rb │ ├── merge_sort_spec.rb │ ├── quick_sort_spec.rb │ └── stupid_sort_spec.rb └── spec_helper.rb └── src ├── arrays ├── sort_012.rb └── sub_array_with_max_sum.rb ├── binary_trees ├── tree_node.rb └── tree_to_circular_list.rb ├── common └── array_utils.rb ├── general ├── longest_palindromic_substring.rb └── num_hops.rb ├── lists └── singly_linked_list.rb └── sorting ├── heap_sort.rb ├── merge_sort.rb ├── quick_sort.rb └── stupid_sort.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *~* 3 | *#* 4 | .metadata/ 5 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | syringe -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/syringe.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DISCLAIMER: -------------------------------------------------------------------------------- 1 | Hi all, 2 | 3 | I am providing the code in this repository to you under the MIT license for open source projects. 4 | Because this is my personal repository, the license you receive to my code is from me and not from 5 | my employer (Facebook). 6 | 7 | 8 | Cheers, 9 | Kowshik Prakasam 10 | (kowshik@gmail.com) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Kowshik Prakasam 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Big O 2 | ===== 3 | 4 | A big collection of data structures and algorithms puzzles. 5 | As on May 2013, the repository has roughly 130 problems with solutions. 6 | 7 | Solutions are primarily in Java (under [java/](https://github.com/kowshik/big-o/tree/master/java)). Some solutions are in Ruby (under [ruby/](https://github.com/kowshik/big-o/tree/master/ruby)). 8 | 9 | Problem statements are specified as Javadoc at the top of every solution. I have tried to be as descriptive as I can, but if something is not clear then please do let me know! 10 | Problems are broadly classified into the following categories which are self explanatory. 11 | 12 | Please feel free to contribute! 13 | 14 | * [arrays/](https://github.com/kowshik/big-o/tree/master/java/src/arrays) 15 | * [binarytrees/](https://github.com/kowshik/big-o/tree/master/java/src/binarytrees) 16 | * [bitsandbytes/](https://github.com/kowshik/big-o/tree/master/java/src/bitsandbytes) 17 | * [cache/](https://github.com/kowshik/big-o/tree/master/java/src/cache) 18 | * [collections/](https://github.com/kowshik/big-o/tree/master/java/src/collections) 19 | * [concurrency/](https://github.com/kowshik/big-o/tree/master/java/src/concurrency) 20 | * [dp/](https://github.com/kowshik/big-o/tree/master/java/src/dp) 21 | * [general/](https://github.com/kowshik/big-o/tree/master/java/src/general) 22 | * [graphs/](https://github.com/kowshik/big-o/tree/master/java/src/graphs) 23 | * [linkedlists/](https://github.com/kowshik/big-o/tree/master/java/src/linkedlists) 24 | * [sorting/](https://github.com/kowshik/big-o/tree/master/java/src/sorting) 25 | * [strings/](https://github.com/kowshik/big-o/tree/master/java/src/strings) 26 | * [trees/](https://github.com/kowshik/big-o/tree/master/java/src/trees) 27 | 28 | 29 | -------------------------------------------------------------------------------- /java/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /java/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | big-o-java 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /java/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.6 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.6 12 | -------------------------------------------------------------------------------- /java/.settings/org.eclipse.jdt.ui.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true 3 | sp_cleanup.add_default_serial_version_id=true 4 | sp_cleanup.add_generated_serial_version_id=false 5 | sp_cleanup.add_missing_annotations=true 6 | sp_cleanup.add_missing_deprecated_annotations=true 7 | sp_cleanup.add_missing_methods=false 8 | sp_cleanup.add_missing_nls_tags=false 9 | sp_cleanup.add_missing_override_annotations=true 10 | sp_cleanup.add_missing_override_annotations_interface_methods=true 11 | sp_cleanup.add_serial_version_id=false 12 | sp_cleanup.always_use_blocks=true 13 | sp_cleanup.always_use_parentheses_in_expressions=false 14 | sp_cleanup.always_use_this_for_non_static_field_access=false 15 | sp_cleanup.always_use_this_for_non_static_method_access=false 16 | sp_cleanup.convert_to_enhanced_for_loop=false 17 | sp_cleanup.correct_indentation=true 18 | sp_cleanup.format_source_code=true 19 | sp_cleanup.format_source_code_changes_only=false 20 | sp_cleanup.make_local_variable_final=false 21 | sp_cleanup.make_parameters_final=false 22 | sp_cleanup.make_private_fields_final=true 23 | sp_cleanup.make_type_abstract_if_missing_method=false 24 | sp_cleanup.make_variable_declarations_final=true 25 | sp_cleanup.never_use_blocks=false 26 | sp_cleanup.never_use_parentheses_in_expressions=true 27 | sp_cleanup.on_save_use_additional_actions=true 28 | sp_cleanup.organize_imports=true 29 | sp_cleanup.qualify_static_field_accesses_with_declaring_class=false 30 | sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true 31 | sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true 32 | sp_cleanup.qualify_static_member_accesses_with_declaring_class=false 33 | sp_cleanup.qualify_static_method_accesses_with_declaring_class=false 34 | sp_cleanup.remove_private_constructors=true 35 | sp_cleanup.remove_trailing_whitespaces=true 36 | sp_cleanup.remove_trailing_whitespaces_all=true 37 | sp_cleanup.remove_trailing_whitespaces_ignore_empty=false 38 | sp_cleanup.remove_unnecessary_casts=true 39 | sp_cleanup.remove_unnecessary_nls_tags=false 40 | sp_cleanup.remove_unused_imports=false 41 | sp_cleanup.remove_unused_local_variables=false 42 | sp_cleanup.remove_unused_private_fields=true 43 | sp_cleanup.remove_unused_private_members=false 44 | sp_cleanup.remove_unused_private_methods=true 45 | sp_cleanup.remove_unused_private_types=true 46 | sp_cleanup.sort_members=false 47 | sp_cleanup.sort_members_all=false 48 | sp_cleanup.use_blocks=false 49 | sp_cleanup.use_blocks_only_for_return_and_throw=false 50 | sp_cleanup.use_parentheses_in_expressions=false 51 | sp_cleanup.use_this_for_non_static_field_access=false 52 | sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true 53 | sp_cleanup.use_this_for_non_static_method_access=false 54 | sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true 55 | -------------------------------------------------------------------------------- /java/lib/junit-4.11.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kowshik/big-o/a5c5e5fad3049b8898b64b0952c9d7ac9fef9d1c/java/lib/junit-4.11.jar -------------------------------------------------------------------------------- /java/src/arrays/Answer0toKRangeQuery.java: -------------------------------------------------------------------------------- 1 | package arrays; 2 | 3 | /** 4 | * Write a class that given an array of N integers with values in the range 0 to 5 | * K, pre-processes its input and then answers any query about how many of the N 6 | * integers fall into a range [A,B] in O(1) time (note: the range includes A and 7 | * B). Your algorithm can use no more than O(N + K) pre-preocessing time. 8 | * 9 | * Your class: Answer0toKRangeQuery should implement a constructor with the 10 | * following signature. The constructor should take as input the array to be 11 | * processed, and the value K which determines the range 0 to K. 12 | * 13 | * Answer0toKRangeQuery(int[] array, int k) {...} 14 | * 15 | * Your class should also implement the method: 16 | * 17 | * int countNumIntegers(int rangeStart, int rangeEnd) {...} 18 | * 19 | * The above method answers the required queries in O(1) time. 20 | */ 21 | public class Answer0toKRangeQuery { 22 | private final int[] counter; 23 | private final int k; 24 | 25 | public Answer0toKRangeQuery(int[] array, int k) { 26 | if (k < 0) { 27 | throw new IllegalArgumentException(String.format( 28 | "Value of 'K' can't be negative. You passed: %d:", k)); 29 | } 30 | 31 | this.k = k; 32 | counter = new int[k + 1]; 33 | for (int number : array) { 34 | counter[number]++; 35 | } 36 | 37 | for (int i = 1; i <= k; i++) { 38 | counter[i] += counter[i - 1]; 39 | } 40 | } 41 | 42 | public int countNumIntegers(int rangeStart, int rangeEnd) { 43 | if (rangeStart < 0) { 44 | throw new IllegalArgumentException(String.format( 45 | "rangeStart can't be negative. You passed: %d", rangeStart)); 46 | } 47 | 48 | if (rangeEnd > k) { 49 | throw new IllegalArgumentException(String.format( 50 | "rangeStart can't be negative. You passed: %d", rangeEnd)); 51 | } 52 | 53 | return counter[rangeEnd] 54 | - (rangeStart == 0 ? 0 : counter[rangeStart - 1]); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /java/src/arrays/CountInversions.java: -------------------------------------------------------------------------------- 1 | package arrays; 2 | 3 | /** 4 | * Count number of inversions in an array of integers. 5 | * 6 | * An inversion is a pair of indices: (i,j) such that i < j and array[i] > 7 | * array[j]. 8 | * 9 | * Signature of expected method: 10 | * 11 | * public static long countInversions(int[] array) {...} 12 | */ 13 | public class CountInversions { 14 | public static long countInversions(int[] array) { 15 | return countInversions(array, 0, array.length - 1, 16 | new int[array.length]); 17 | } 18 | 19 | // Recursively counts the inversions. 20 | private static long countInversions(int[] array, int start, int end, 21 | int[] merged) { 22 | if (start == end) { 23 | merged[0] = array[start]; 24 | return 0L; 25 | } 26 | 27 | int middle = (start + end) / 2; 28 | 29 | int[] left = new int[middle - start + 1]; 30 | long leftInversions = countInversions(array, start, middle, left); 31 | int[] right = new int[end - middle]; 32 | long rightInversions = countInversions(array, middle + 1, end, right); 33 | 34 | return leftInversions + rightInversions 35 | + mergeAndCountInversions(left, right, merged); 36 | } 37 | 38 | // This method is very similar to merge sort's merge method. Study the 39 | // merge method first if you don't immediately understand the below. 40 | private static long mergeAndCountInversions(int[] foo, int[] bar, 41 | int[] merged) { 42 | if (foo == null || bar == null || merged == null) { 43 | throw new NullPointerException( 44 | "One or more of foo/bar/merged is null."); 45 | } 46 | 47 | long numInversions = 0L; 48 | int fooIndex = 0, barIndex = 0; 49 | int sortedIndex = 0; 50 | while (fooIndex < foo.length && barIndex < bar.length) { 51 | if (foo[fooIndex] <= bar[barIndex]) { 52 | merged[sortedIndex] = foo[fooIndex]; 53 | fooIndex++; 54 | } else { 55 | numInversions += foo.length - fooIndex; 56 | merged[sortedIndex] = bar[barIndex]; 57 | barIndex++; 58 | } 59 | 60 | sortedIndex++; 61 | } 62 | 63 | while (fooIndex < foo.length) { 64 | merged[sortedIndex] = foo[fooIndex]; 65 | fooIndex++; 66 | sortedIndex++; 67 | } 68 | 69 | while (barIndex < bar.length) { 70 | merged[sortedIndex] = bar[barIndex]; 71 | barIndex++; 72 | sortedIndex++; 73 | } 74 | 75 | return numInversions; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /java/src/arrays/FindCommonElements.java: -------------------------------------------------------------------------------- 1 | package arrays; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * Find common elements between two sorted integer arrays. 8 | * 9 | * Signature of expected method: 10 | * 11 | * public static List findCommonElements(int[] a, int[] b) {...} 12 | */ 13 | public class FindCommonElements { 14 | public static List findCommonElements(int[] a, int[] b) { 15 | if (a == null || b == null) { 16 | return null; 17 | } 18 | 19 | List common = new ArrayList(); 20 | for (int aIndex = 0, bIndex = 0; aIndex < a.length && bIndex < b.length;) { 21 | if (a[aIndex] < b[bIndex]) { 22 | aIndex++; 23 | } else if (b[bIndex] < a[aIndex]) { 24 | bIndex++; 25 | } else { 26 | common.add(a[aIndex]); 27 | aIndex++; 28 | bIndex++; 29 | } 30 | } 31 | 32 | return common; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /java/src/arrays/FindNumHops.java: -------------------------------------------------------------------------------- 1 | package arrays; 2 | 3 | import java.util.HashSet; 4 | import java.util.Iterator; 5 | import java.util.Set; 6 | 7 | /** 8 | * You are given an array of size N containing *only* non-negative integers 9 | * (i.e. >= 0). From any index in the array, a hop can be either of the 10 | * following: 11 | * 12 | * [1] Jump array[index] positions 13 | * [2] Jump 1 position 14 | * 15 | * The target of this question is to find the number of hops required to reach 16 | * the last element in the array from the first element. 17 | * 18 | * Signature of expected method: 19 | * 20 | * public static int findNumHops(int[] array) {...} 21 | */ 22 | public class FindNumHops { 23 | public static int findNumHops(int[] array) { 24 | if (array == null) { 25 | throw new NullPointerException("array can't be null."); 26 | } 27 | 28 | if (array.length == 0) { 29 | return 0; 30 | } 31 | 32 | Set steps = new HashSet(); 33 | int lastSeenStep = array.length - 1; 34 | steps.add(lastSeenStep); 35 | 36 | for (int index = array.length - 2; index >= 0; index--) { 37 | int hopSize = array[index]; 38 | int reachableStep = hopSize + index; 39 | 40 | if (steps.contains(reachableStep)) { 41 | for (Iterator iter = steps.iterator(); iter.hasNext();) { 42 | int step = iter.next(); 43 | if (step < reachableStep) { 44 | iter.remove(); 45 | } 46 | } 47 | 48 | steps.add(index); 49 | lastSeenStep = index; 50 | } 51 | } 52 | 53 | return steps.size() - 1 + lastSeenStep; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /java/src/arrays/RearrangeInputToTarget.java: -------------------------------------------------------------------------------- 1 | package arrays; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * You are given two integer arrays: input and target. These arrays contain the 8 | * same unique integers, and always the value zero in each of them. Also, the 9 | * target array is some permutation of the input array and both arrays are of 10 | * the same size. 11 | * 12 | * You are supposed to write a method to convert the input array to the target 13 | * array. The restriction is that you can modify the input array by repeating 14 | * only the following operation any number of times: Take any value in the input 15 | * array and swap its location with that of the value zero in the same array. 16 | * 17 | * Signature of expected method: 18 | * 19 | * public static void rearrange(int[] input, int[] target) {...} 20 | */ 21 | public class RearrangeInputToTarget { 22 | 23 | public static void rearrange(int[] input, int[] target) { 24 | assert (input.length == target.length); 25 | 26 | Map map = new HashMap(); 27 | buildIndex(input, map); 28 | int zeroIndex = common.ArrayUtils.findIndex(input, 0); 29 | int numMoves = 0; 30 | 31 | while (numMoves < input.length) { 32 | // zero has reached its final location. So we displace it 33 | // temporarily so that we can continue putting other elements in 34 | // their final locations. 35 | if (target[zeroIndex] == 0) { 36 | int outOfOrderIndex = findFirstOutOfOrderIndex(input, target); 37 | if (outOfOrderIndex == -1) { 38 | // All elements including '0' are in their final locations. 39 | return; 40 | } 41 | 42 | map.put(input[outOfOrderIndex], zeroIndex); 43 | // We need to update the index because we are going to modify 44 | // the original location of the value in input[outOfOrderIndex]. 45 | common.ArrayUtils.swap(input, zeroIndex, outOfOrderIndex); 46 | zeroIndex = outOfOrderIndex; 47 | 48 | } else { 49 | // Swap zero with what should actually be in zero's location 50 | // in the target array. 51 | int nextZeroIndex = map.get(target[zeroIndex]); 52 | common.ArrayUtils.swap(input, zeroIndex, nextZeroIndex); 53 | zeroIndex = nextZeroIndex; 54 | numMoves++; 55 | } 56 | } 57 | 58 | } 59 | 60 | private static void buildIndex(int[] input, Map index) { 61 | for (int location = 0; location < input.length; location++) { 62 | index.put(input[location], location); 63 | } 64 | } 65 | 66 | private static int findFirstOutOfOrderIndex(int[] input, int[] target) { 67 | assert (input.length == target.length); 68 | 69 | for (int index = 0; index < input.length; index++) { 70 | if (input[index] != target[index]) { 71 | return index; 72 | } 73 | } 74 | 75 | return -1; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /java/src/binarytrees/BstClosestNode.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | /** 4 | * Given the root of a binary search tree and a node from the same tree, find 5 | * the node closest to the given node. 6 | * 7 | * Signature of expected method: 8 | * 9 | * public static TreeNode findClosestNode(TreeNode bstRootNode, 10 | * TreeNode node); 11 | */ 12 | public class BstClosestNode { 13 | public static TreeNode findClosestNode( 14 | TreeNode bstRootNode, TreeNode node) { 15 | TreeNode inorderPredecessor = getInorderPredecessor( 16 | bstRootNode, node); 17 | TreeNode inorderSuccessor = getInorderSuccessor(bstRootNode, 18 | node); 19 | 20 | if (inorderPredecessor == null) { 21 | return inorderSuccessor; 22 | } 23 | 24 | if (inorderSuccessor == null) { 25 | return inorderPredecessor; 26 | } 27 | 28 | if ((node.getValue() - inorderPredecessor.getValue()) < (inorderSuccessor 29 | .getValue() - node.getValue())) { 30 | return inorderPredecessor; 31 | } 32 | 33 | return inorderSuccessor; 34 | } 35 | 36 | public static TreeNode getInorderSuccessor( 37 | TreeNode bstRootNode, TreeNode node) { 38 | if (bstRootNode == null || node == null) { 39 | return null; 40 | } 41 | 42 | TreeNode successorNode = getMinValueNode(node.getRight()); 43 | if (successorNode != null) { 44 | return successorNode; 45 | } 46 | 47 | while (bstRootNode != null) { 48 | if (node.getValue() < bstRootNode.getValue()) { 49 | successorNode = bstRootNode; 50 | bstRootNode = bstRootNode.getLeft(); 51 | } else { 52 | bstRootNode = bstRootNode.getRight(); 53 | } 54 | } 55 | 56 | return successorNode; 57 | } 58 | 59 | public static TreeNode getInorderPredecessor( 60 | TreeNode bstRootNode, TreeNode node) { 61 | if (bstRootNode == null || node == null) { 62 | return null; 63 | } 64 | 65 | TreeNode predecessorNode = getMaxValueNode(node.getLeft()); 66 | if (predecessorNode != null) { 67 | return predecessorNode; 68 | } 69 | 70 | while (bstRootNode != null) { 71 | if (node.getValue() > bstRootNode.getValue()) { 72 | predecessorNode = bstRootNode; 73 | bstRootNode = bstRootNode.getRight(); 74 | } else { 75 | bstRootNode = bstRootNode.getLeft(); 76 | } 77 | } 78 | 79 | return predecessorNode; 80 | } 81 | 82 | private static TreeNode getMinValueNode(TreeNode node) { 83 | if (node == null) { 84 | return null; 85 | } 86 | 87 | while (node.hasLeft()) { 88 | node = node.getLeft(); 89 | } 90 | 91 | return node; 92 | } 93 | 94 | private static TreeNode getMaxValueNode(TreeNode node) { 95 | if (node == null) { 96 | return null; 97 | } 98 | 99 | while (node.hasRight()) { 100 | node = node.getRight(); 101 | } 102 | 103 | return node; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /java/src/binarytrees/BstCountTrees.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | /** 4 | * Suppose you are building an N node binary search tree with the values 1..N. 5 | * How many structurally different binary search trees are there that store 6 | * those values? Write a recursive function that, given the number of distinct 7 | * values, computes the number of structurally unique binary search trees that 8 | * store those values. 9 | * 10 | * Signature of expected method: 11 | * 12 | * public static long countTrees(int numKeys); 13 | * 14 | * For example, countTrees(4) should return 14, since there 15 | * are 14 structurally unique binary search trees that store 1, 2, 3, and 4. 16 | */ 17 | public class BstCountTrees { 18 | 19 | public static long countTrees(int numKeys) { 20 | if (numKeys <= 0) { 21 | return 0; 22 | } 23 | 24 | long sum = 0L; 25 | for (int root = 1; root <= numKeys; root++) { 26 | sum += countTrees(root - 1) * countTrees(numKeys - root); 27 | } 28 | 29 | return sum; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /java/src/binarytrees/BstDoubleTree.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | /** 4 | * For each node in a binary search tree, create a new duplicate node, and 5 | * insert the duplicate as the left child of the original node. The resulting 6 | * tree should still be a binary search tree. 7 | * 8 | * Signature of expected method: 9 | * 10 | * public static void doubleTree(TreeNode root) {...} 11 | */ 12 | public class BstDoubleTree { 13 | public static void doubleTree(TreeNode root) { 14 | if (root == null) { 15 | return; 16 | } 17 | 18 | doubleTree(root.getLeft()); 19 | doubleTree(root.getRight()); 20 | 21 | TreeNode duplicate = new TreeNode(root.getValue()); 22 | duplicate.setLeft(root.getLeft()); 23 | root.setLeft(duplicate); 24 | 25 | return; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /java/src/binarytrees/BstFindMode.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | import common.Pair; 4 | 5 | /** 6 | * Given a BST, find the mode i.e. the value that occurs maximum number of 7 | * times. 8 | * 9 | * Signature of expected method: 10 | * 11 | * public static T findMode(TreeNode root) {...} 12 | */ 13 | public class BstFindMode { 14 | public static T findMode(TreeNode root) { 15 | Pair mode = new Pair(); 16 | mode.setSecond(0); 17 | 18 | findMode(root, mode); 19 | 20 | return mode.getFirst(); 21 | } 22 | 23 | private static void findMode(TreeNode root, Pair mode) { 24 | Pair current = new Pair(); 25 | current.setSecond(0); 26 | 27 | findMode(root, mode, current); 28 | if (current.getFirst() != null 29 | && (mode.getFirst() == null || current.getSecond() > mode 30 | .getSecond())) { 31 | mode.setFirst(current.getFirst()); 32 | mode.setSecond(current.getSecond()); 33 | } 34 | } 35 | 36 | private static void findMode(TreeNode root, Pair mode, 37 | Pair current) { 38 | if (root == null) { 39 | return; 40 | } 41 | 42 | findMode(root.getLeft(), mode, current); 43 | 44 | if (current.getFirst() == null) { 45 | current.setFirst(root.getValue()); 46 | current.setSecond(1); 47 | } else { 48 | if (current.getFirst().equals(root.getValue())) { 49 | current.setSecond(current.getSecond() + 1); 50 | } else { 51 | if (mode.getFirst() == null 52 | || current.getSecond() > mode.getSecond()) { 53 | mode.setFirst(current.getFirst()); 54 | mode.setSecond(current.getSecond()); 55 | } 56 | 57 | current.setFirst(root.getValue()); 58 | current.setSecond(1); 59 | } 60 | } 61 | 62 | findMode(root.getRight(), mode, current); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /java/src/binarytrees/BstInsert.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | import java.util.Comparator; 4 | 5 | /** 6 | * Insert a value into a binary search tree. 7 | * 8 | * Signature of expected method: 9 | * 10 | * public static void insert(TreeNode root, T value, 11 | Comparator comparator) {...} 12 | * 13 | */ 14 | public class BstInsert { 15 | public static void insert(TreeNode root, T value, 16 | Comparator comparator) { 17 | if (root == null || value == null || comparator == null) { 18 | return; 19 | } 20 | 21 | doInsert(root, value, comparator); 22 | } 23 | 24 | private static TreeNode doInsert(TreeNode root, T value, 25 | Comparator comparator) { 26 | if (root == null) { 27 | return new TreeNode(value); 28 | } 29 | 30 | if (comparator.compare(root.getValue(), value) <= 0) { 31 | root.setLeft(doInsert(root.getLeft(), value, comparator)); 32 | } 33 | 34 | root.setRight(doInsert(root.getRight(), value, comparator)); 35 | return root; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /java/src/binarytrees/BstIsBst.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | /** 4 | * Check if a binary tree is a binary search tree. To keep things simple, assume 5 | * that the binary tree contains only integers. 6 | * 7 | * Signature of expected method: 8 | * 9 | * public static boolean isBst(TreeNode rootNode) {...} 10 | */ 11 | public class BstIsBst { 12 | public static boolean isBst(TreeNode rootNode) { 13 | return isBst(rootNode, Integer.MIN_VALUE, Integer.MAX_VALUE); 14 | } 15 | 16 | private static boolean isBst(TreeNode rootNode, int minValue, 17 | int maxValue) { 18 | if (rootNode == null) { 19 | return true; 20 | } 21 | 22 | boolean check = minValue <= rootNode.getValue() 23 | && rootNode.getValue() < maxValue; 24 | if (check) { 25 | check = isBst(rootNode.getLeft(), minValue, rootNode.getValue()); 26 | if (check) { 27 | check = isBst(rootNode.getRight(), rootNode.getValue() + 1, 28 | maxValue); 29 | } 30 | } 31 | 32 | return check; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /java/src/binarytrees/BstLookup.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | import java.util.Comparator; 4 | 5 | /** 6 | * Check if a given node exists in the binary search tree. 7 | * 8 | * Signature of expected method: 9 | * 10 | * public static boolean lookup(TreeNode rootNode, 11 | TreeNode searchedNode, Comparator comparator) {...} 12 | */ 13 | public class BstLookup { 14 | public static boolean lookup(TreeNode rootNode, 15 | TreeNode searchedNode, Comparator comparator) { 16 | if (rootNode == null) { 17 | return false; 18 | } 19 | 20 | int compared = comparator.compare(rootNode.getValue(), 21 | searchedNode.getValue()); 22 | if (compared < 0) { 23 | return lookup(rootNode.getLeft(), searchedNode, comparator); 24 | } else if (compared == 0) { 25 | return true; 26 | } 27 | 28 | return lookup(rootNode.getRight(), searchedNode, comparator); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /java/src/binarytrees/BstMinValue.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | /** 4 | * Find the smallest value in a binary search tree. 5 | * 6 | * Signature of expected method: 7 | * 8 | * public static T minValue(TreeNode root) {...} 9 | */ 10 | public class BstMinValue { 11 | public static T minValue(TreeNode root) { 12 | if (root == null) { 13 | return null; 14 | } 15 | 16 | while (root.getLeft() != null) { 17 | root = root.getLeft(); 18 | } 19 | 20 | return root.getValue(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /java/src/binarytrees/TreeConvertToSinglyLinkedList.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | import common.Pair; 4 | 5 | /** 6 | * Given a binary tree, convert it into a singly linked list. The "next" pointer 7 | * in each node of the list is defined using the "right" pointer in the binary 8 | * tree. The order of nodes in the linked list is the same order that occurs in 9 | * the inorder representation of the binary tree. Also the solution must set all 10 | * "left" pointers in each node to null. 11 | * 12 | * Signature of expected method: 13 | * 14 | * public static TreeNode convertToSinglyLinkedList( 15 | TreeNode root) {...} 16 | */ 17 | public class TreeConvertToSinglyLinkedList { 18 | public static TreeNode convertToSinglyLinkedList( 19 | TreeNode root) { 20 | return doConnectInorder(root).getFirst(); 21 | } 22 | 23 | private static Pair, TreeNode> doConnectInorder( 24 | TreeNode root) { 25 | if (root == null) { 26 | return null; 27 | } 28 | 29 | Pair, TreeNode> toReturn = new Pair, TreeNode>(); 30 | Pair, TreeNode> leftPair = doConnectInorder(root 31 | .getLeft()); 32 | if (leftPair != null) { 33 | leftPair.getSecond().setRight(root); 34 | toReturn.setFirst(leftPair.getFirst()); 35 | } else { 36 | toReturn.setFirst(root); 37 | } 38 | 39 | Pair, TreeNode> rightPair = doConnectInorder(root 40 | .getRight()); 41 | if (rightPair != null) { 42 | root.setRight(rightPair.getFirst()); 43 | toReturn.setSecond(rightPair.getSecond()); 44 | } else { 45 | toReturn.setSecond(root); 46 | } 47 | 48 | root.setLeft(null); 49 | 50 | return toReturn; 51 | } 52 | 53 | public static void main(String[] args) { 54 | TreeNode rootLeftLeft = new TreeNode(3); 55 | TreeNode rootLeftRight = new TreeNode(5); 56 | 57 | TreeNode rootLeft = new TreeNode(4); 58 | rootLeft.setLeft(rootLeftLeft); 59 | rootLeft.setRight(rootLeftRight); 60 | 61 | TreeNode rootRightLeft = new TreeNode(7); 62 | TreeNode rootRightRight = new TreeNode(9); 63 | 64 | TreeNode rootRight = new TreeNode(8); 65 | rootRight.setLeft(rootRightLeft); 66 | rootRight.setRight(rootRightRight); 67 | 68 | TreeNode root = new TreeNode(6); 69 | root.setLeft(rootLeft); 70 | root.setRight(rootRight); 71 | 72 | root = convertToSinglyLinkedList(root); 73 | 74 | while (root != null) { 75 | System.out.println(root); 76 | System.out.println(root.getLeft()); 77 | root = root.getRight(); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /java/src/binarytrees/TreeDepth.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | /** 4 | * Given a binary tree, find its depth. 5 | * 6 | * Signature of expected method: 7 | * 8 | * public static int maxDepth(TreeNode root) {...} 9 | */ 10 | public class TreeDepth { 11 | public static int maxDepth(TreeNode root) { 12 | if (root == null) { 13 | return 0; 14 | } 15 | 16 | return Math.max(maxDepth(root.getLeft()), maxDepth(root.getRight())) + 1; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /java/src/binarytrees/TreeHasPathSum.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | /** 4 | * Given a binary tree and a sum, return true if the tree has a root-to-leaf 5 | * path such that adding up all the values along the path equals the given sum. 6 | * Return false if no such path can be found. 7 | * 8 | * Signature of expected method: 9 | * 10 | * public static boolean hasPathSum(TreeNode root, int sum) {...} 11 | */ 12 | public class TreeHasPathSum { 13 | public static boolean hasPathSum(TreeNode root, int sum) { 14 | if (root == null) { 15 | return false; 16 | } 17 | 18 | Integer value = root.getValue(); 19 | if (value == null) { 20 | throw new NullPointerException("You are an insane programmer."); 21 | } 22 | return hasPathSum(root.getLeft(), sum - value) 23 | || hasPathSum(root.getRight(), sum - value) 24 | || (sum - value == 0 && !root.hasLeft() && !root.hasRight()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /java/src/binarytrees/TreeMirror.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | /** 4 | * Given a binary tree, convert it into its mirror. 5 | * 6 | * Signature of expected method: 7 | * 8 | * public static void mirror(TreeNode root) { 9 | */ 10 | public class TreeMirror { 11 | public static void mirror(TreeNode root) { 12 | if (root == null) { 13 | return; 14 | } 15 | 16 | mirror(root.getLeft()); 17 | mirror(root.getRight()); 18 | 19 | TreeNode temp = root.getLeft(); 20 | root.setLeft(root.getRight()); 21 | root.setRight(temp); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /java/src/binarytrees/TreeNode.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | public class TreeNode { 4 | private TreeNode left; 5 | private TreeNode right; 6 | private T value; 7 | 8 | public TreeNode(T value) { 9 | setValue(value); 10 | } 11 | 12 | public TreeNode getLeft() { 13 | return left; 14 | } 15 | 16 | public void setLeft(TreeNode left) { 17 | this.left = left; 18 | } 19 | 20 | public TreeNode getRight() { 21 | return right; 22 | } 23 | 24 | public boolean hasLeft() { 25 | return getLeft() != null; 26 | } 27 | 28 | public void setRight(TreeNode right) { 29 | this.right = right; 30 | } 31 | 32 | public boolean hasRight() { 33 | return getRight() != null; 34 | } 35 | 36 | public T getValue() { 37 | return value; 38 | } 39 | 40 | public void setValue(T value) { 41 | this.value = value; 42 | } 43 | 44 | public boolean hasValue() { 45 | return getValue() != null; 46 | } 47 | 48 | @Override 49 | public String toString() { 50 | if (getValue() != null) { 51 | return getValue().toString(); 52 | } 53 | 54 | return ""; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /java/src/binarytrees/TreePrintPaths.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | import java.util.LinkedList; 4 | 5 | /** 6 | * Given the root of a binary tree, print all different paths from root to 7 | * leaves to standard out. 8 | * 9 | * Signature of expected method: 10 | * 11 | * public static void printPaths(TreeNode root) {...} 12 | */ 13 | public class TreePrintPaths { 14 | public static void printPaths(TreeNode root) { 15 | @SuppressWarnings("rawtypes") 16 | LinkedList list = new LinkedList(); 17 | printPaths(root, list); 18 | } 19 | 20 | @SuppressWarnings("unchecked") 21 | private static void printPaths(TreeNode root, 22 | @SuppressWarnings("rawtypes") LinkedList path) { 23 | if (root == null) { 24 | return; 25 | } 26 | 27 | Object value = root.getValue(); 28 | path.addLast(value); 29 | printPaths(root.getLeft(), path); 30 | printPaths(root.getRight(), path); 31 | 32 | if (root.getLeft() == null && root.getRight() == null) { 33 | System.out.println(path); 34 | } 35 | 36 | path.removeLast(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /java/src/binarytrees/TreeReconstruct.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | import java.util.Comparator; 4 | 5 | /** 6 | * Reconstruct a binary tree from its inorder and preorder traversals. 7 | * 8 | * Signature of expected method: 9 | * 10 | * public static TreeNode reconstruct(T[] inorder, T[] preorder, 11 | * Comparator comparator) {...} 12 | */ 13 | 14 | public class TreeReconstruct { 15 | 16 | public static TreeNode reconstruct(T[] inorder, T[] preorder, 17 | Comparator comparator) { 18 | return reconstruct(inorder, 0, inorder.length - 1, preorder, 0, 19 | preorder.length - 1, comparator); 20 | } 21 | 22 | private static TreeNode reconstruct(T[] inorder, int inorderStart, 23 | int inorderEnd, T[] preorder, int preorderStart, int preorderEnd, 24 | Comparator comparator) { 25 | if (inorderStart > inorderEnd || preorderStart > preorderEnd) { 26 | return null; 27 | } 28 | 29 | int rootNodeIndex = findNode(inorder, inorderStart, inorderEnd, 30 | preorder[preorderStart], comparator); 31 | if (rootNodeIndex == -1) { 32 | throw new RuntimeException("Bad input."); 33 | } 34 | 35 | TreeNode rootNode = new TreeNode(inorder[rootNodeIndex]); 36 | 37 | int leftSubTreeSize = rootNodeIndex - inorderStart; 38 | TreeNode leftNode = reconstruct(inorder, inorderStart, 39 | rootNodeIndex - 1, preorder, preorderStart + 1, preorderStart 40 | + leftSubTreeSize, comparator); 41 | 42 | TreeNode rightNode = reconstruct(inorder, rootNodeIndex + 1, 43 | inorderEnd, preorder, preorderStart + leftSubTreeSize + 1, 44 | preorderEnd, comparator); 45 | 46 | rootNode.setLeft(leftNode); 47 | rootNode.setRight(rightNode); 48 | return rootNode; 49 | } 50 | 51 | private static int findNode(T[] array, int startIndex, int endIndex, 52 | T value, Comparator comparator) { 53 | for (int index = startIndex; index <= endIndex; index++) { 54 | if (comparator.compare(array[index], value) == 0) { 55 | return index; 56 | } 57 | } 58 | 59 | return -1; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /java/src/binarytrees/TreeRecursiveTraversals.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | /** 4 | * Given the root of a binary tree recursively print the (in/pre/post)-order 5 | * traversals to standard out. 6 | * 7 | * Signature of expected methods: 8 | * 9 | * public static void inorderTraversal(TreeNode root) {...} 10 | * public static void preorderTraversal(TreeNode root) {...} 11 | * public static void postorderTraversal(TreeNode root) {...} 12 | */ 13 | public class TreeRecursiveTraversals { 14 | 15 | public static void inorderTraversal(TreeNode root) { 16 | if (root == null) { 17 | return; 18 | } 19 | 20 | inorderTraversal(root.getLeft()); 21 | System.out.printf("%s ", root.getValue()); 22 | inorderTraversal(root.getRight()); 23 | } 24 | 25 | public static void preorderTraversal(TreeNode root) { 26 | if (root == null) { 27 | return; 28 | } 29 | 30 | System.out.printf("%s ", root.getValue()); 31 | preorderTraversal(root.getLeft()); 32 | preorderTraversal(root.getRight()); 33 | } 34 | 35 | public static void postorderTraversal(TreeNode root) { 36 | if (root == null) { 37 | return; 38 | } 39 | 40 | postorderTraversal(root.getLeft()); 41 | postorderTraversal(root.getRight()); 42 | System.out.printf("%s ", root.getValue()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /java/src/binarytrees/TreeSameTree.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | import java.util.Comparator; 4 | 5 | /** 6 | * Determine if two binary trees are structurally identical. 7 | * 8 | * Signature of expected method: 9 | * 10 | * public static boolean isSameTree(TreeNode rootFoo, 11 | TreeNode rootBar, 12 | Comparator comparator) {...} 13 | */ 14 | public class TreeSameTree { 15 | public static boolean isSameTree(TreeNode rootFoo, 16 | TreeNode rootBar, Comparator comparator) { 17 | if (rootFoo == null && rootBar == null) { 18 | return true; 19 | } 20 | 21 | if (rootFoo != null && rootBar != null) { 22 | return isSameTree(rootFoo.getLeft(), rootBar.getLeft(), comparator) 23 | && isSameTree(rootFoo.getRight(), rootBar.getRight(), 24 | comparator) 25 | && comparator.compare(rootFoo.getValue(), 26 | rootBar.getValue()) == 0; 27 | } 28 | 29 | return false; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /java/src/binarytrees/TreeSize.java: -------------------------------------------------------------------------------- 1 | package binarytrees; 2 | 3 | /** 4 | * Find the size of a binary tree. 5 | * 6 | * Signature of expected method: 7 | * 8 | * public static int size(TreeNode root) {...} 9 | */ 10 | public class TreeSize { 11 | public static int size(TreeNode root) { 12 | if (root == null) { 13 | return 0; 14 | } 15 | 16 | return size(root.getLeft()) + 1 + size(root.getRight()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /java/src/bitsandbytes/NumSetBits.java: -------------------------------------------------------------------------------- 1 | package bitsandbytes; 2 | 3 | /** 4 | * You have a series of LEDs whose state is represented as a series of bits -- 1 5 | * represents ON and 0 represents off. You are also given an offset and a 6 | * length. You need to find the number of LED bulbs present in ON state, 7 | * starting at the specified offset in the series of bits, until the specified 8 | * length from the offset. Write the method signature and code in any language. 9 | * 10 | * Signature of expected method: 11 | * 12 | * public static long getNumSetBits(byte[] leds, long offset, long length) {...} 13 | * 14 | */ 15 | public class NumSetBits { 16 | public static long getNumSetBits(byte[] leds, long offset, long length) { 17 | // s/offset/firstBitIndex/ for readability. 18 | long firstBitIndex = offset; 19 | long lastBitIndex = firstBitIndex + length - 1; 20 | byte firstByteIndex = (byte) (firstBitIndex / 8); 21 | byte lastByteIndex = (byte) ((firstBitIndex + length - 1) / 8); 22 | 23 | long totalSetBits = 0L; 24 | if (firstByteIndex != lastByteIndex) { 25 | totalSetBits += getNumSetBitsBetweenWholeBytes(leds, 26 | firstByteIndex + 1, lastByteIndex - 1); 27 | totalSetBits += getNumSetBits(leds[firstByteIndex], 28 | (int) (firstBitIndex % 8), 7); 29 | totalSetBits += getNumSetBits(leds[lastByteIndex], 0, 30 | (int) (lastBitIndex % 8)); 31 | } else { 32 | totalSetBits += getNumSetBits(leds[firstByteIndex], 33 | (int) (firstBitIndex % 8), (int) (lastBitIndex % 8)); 34 | } 35 | 36 | return totalSetBits; 37 | } 38 | 39 | public static int getNumSetBits(byte b, int startOffset, int endOffset) { 40 | if ((startOffset < 0 || startOffset > 7) 41 | || (endOffset < 0 || endOffset > 7) || endOffset < startOffset) { 42 | throw new IllegalArgumentException(String.format( 43 | "Either startOffset: %d or endOffset: %d is incorrect", 44 | startOffset, endOffset)); 45 | } 46 | 47 | int totalBits = 0; 48 | for (int bitIndex = startOffset; bitIndex <= endOffset; bitIndex++) { 49 | totalBits += (byte) (b & (1 << (8 - bitIndex - 1))) != 0 ? 1 : 0; 50 | } 51 | 52 | return totalBits; 53 | } 54 | 55 | public static long getNumSetBitsBetweenWholeBytes(byte[] array, 56 | int firstByte, int lastByte) { 57 | long totalBits = 0; 58 | for (int index = firstByte; index <= lastByte; index++) { 59 | totalBits += getNumSetBits(array[index], 0, 7); 60 | } 61 | 62 | return totalBits; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /java/src/cache/Cache.java: -------------------------------------------------------------------------------- 1 | package cache; 2 | 3 | /** 4 | * A simple cache interface. 5 | * 6 | * @param 7 | * Type of cache key 8 | * @param 9 | * Type of cache value 10 | */ 11 | public interface Cache { 12 | CacheValueType get(CacheKeyType key); 13 | 14 | void put(CacheKeyType key, CacheValueType value); 15 | 16 | int getSize(); 17 | } 18 | -------------------------------------------------------------------------------- /java/src/collections/FilteringIterator.java: -------------------------------------------------------------------------------- 1 | package collections; 2 | 3 | import java.util.Iterator; 4 | import java.util.NoSuchElementException; 5 | 6 | /** 7 | * Implement an iterator that filters elements from the underlying iterator 8 | * based on the given predicate. 9 | * 10 | * Methods expected to be implemented: 11 | * 12 | * public class FilteringIterator implements Iterator { 13 | * public FilteringIterator(Iterator iterator, 14 | * Predicate predicate) {...} 15 | * public boolean hasNext() {...} 16 | * public T next() {...} 17 | * } 18 | */ 19 | 20 | interface Predicate { 21 | boolean apply(T object); 22 | } 23 | 24 | public class FilteringIterator implements Iterator { 25 | 26 | private final Iterator iterator; 27 | private final Predicate predicate; 28 | private T nextItem; 29 | 30 | public FilteringIterator(Iterator iterator, Predicate predicate) { 31 | this.iterator = iterator; 32 | this.predicate = predicate; 33 | nextItem = null; 34 | } 35 | 36 | @Override 37 | public boolean hasNext() { 38 | if (nextItem != null) { 39 | return true; 40 | } 41 | 42 | while (iterator.hasNext()) { 43 | T item = iterator.next(); 44 | if (predicate.apply(item)) { 45 | nextItem = item; 46 | break; 47 | } 48 | } 49 | 50 | return nextItem != null; 51 | } 52 | 53 | @Override 54 | public T next() { 55 | if (!hasNext()) { 56 | throw new NoSuchElementException(); 57 | } 58 | 59 | T toReturn = nextItem; 60 | nextItem = null; 61 | return toReturn; 62 | } 63 | 64 | @Override 65 | public void remove() { 66 | throw new UnsupportedOperationException(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /java/src/collections/HoppingIterator.java: -------------------------------------------------------------------------------- 1 | package collections; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | import java.util.NoSuchElementException; 7 | 8 | /** 9 | * Implement an iterator that hops specified number of times and then returns the next 10 | * element after the hop. Note: the iterator always returns the first element as 11 | * it is, and starts hopping only after the first element. 12 | * 13 | * Examples: 14 | * 15 | * If the original iterator returns: [1, 2, 3, 4, 5] in order, then the hopping 16 | * iterator will return [1, 3, 5] in order when the hop value is 1. 17 | * 18 | * If the original iterator returns: [1, 2, 3, 4, 5] in order, then the hopping 19 | * iterator will return [1, 4] in order when the hop value is 2. 20 | * 21 | * If the original iterator returns: [1, 2, 3, 4, 5] in order, then the hopping 22 | * iterator will return [1, 5] in order when the hop value is 3. 23 | * 24 | * Methods expected to be implemented: 25 | * 26 | * public class HoppingIterator implements Iterator { 27 | * public HoppingIterator(Iterator iterator, int numHops) {...} 28 | * public boolean hasNext() {...} 29 | * public T next() {...} 30 | * } 31 | */ 32 | public class HoppingIterator implements Iterator { 33 | 34 | private final Iterator iterator; 35 | private T nextItem; 36 | private final int numHops; 37 | private boolean first; 38 | 39 | public HoppingIterator(Iterator iterator, int numHops) { 40 | if (numHops < 0) { 41 | throw new IllegalArgumentException(String.format( 42 | "numHops needs to be >= 0. You passed: %d", numHops)); 43 | } 44 | 45 | this.numHops = numHops; 46 | this.iterator = iterator; 47 | nextItem = null; 48 | first = true; 49 | } 50 | 51 | @Override 52 | public boolean hasNext() { 53 | if (nextItem != null) { 54 | return true; 55 | } 56 | 57 | if (!first) { 58 | for (int hop = 0; hop < numHops && iterator.hasNext(); hop++) { 59 | iterator.next(); 60 | } 61 | } 62 | 63 | if (iterator.hasNext()) { 64 | nextItem = iterator.next(); 65 | first = false; 66 | } 67 | 68 | return nextItem != null; 69 | } 70 | 71 | @Override 72 | public T next() { 73 | if (!hasNext()) { 74 | throw new NoSuchElementException(); 75 | } 76 | 77 | T toReturn = nextItem; 78 | nextItem = null; 79 | return toReturn; 80 | } 81 | 82 | @Override 83 | public void remove() { 84 | throw new UnsupportedOperationException(); 85 | } 86 | 87 | public static void main(String[] args) { 88 | List list = new ArrayList(); 89 | list.add(1); 90 | list.add(2); 91 | list.add(3); 92 | list.add(4); 93 | list.add(5); 94 | 95 | HoppingIterator hi = new HoppingIterator( 96 | list.iterator(), 2); 97 | System.out.println(hi.next()); 98 | System.out.println(hi.next()); 99 | System.out.println(hi.hasNext()); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /java/src/collections/InorderIterator.java: -------------------------------------------------------------------------------- 1 | package collections; 2 | 3 | import java.util.Iterator; 4 | import java.util.NoSuchElementException; 5 | import java.util.Stack; 6 | 7 | import binarytrees.TreeNode; 8 | 9 | /** 10 | * Implement an iterator that iterates through a binary tree in inorder. 11 | * 12 | * Methods expected to be implemented: 13 | * 14 | * public class InorderIterator implements Iterator { 15 | * public InorderIterator(TreeNode rootNode) {...} 16 | * public boolean hasNext() {...} 17 | * public T next() {...} 18 | * } 19 | */ 20 | public class InorderIterator implements Iterator { 21 | private T nextItem; 22 | private final Stack> stack; 23 | private boolean unwind; 24 | 25 | public InorderIterator(TreeNode rootNode) { 26 | this.nextItem = null; 27 | this.stack = new Stack>(); 28 | stack.push(rootNode); 29 | } 30 | 31 | @Override 32 | public boolean hasNext() { 33 | if (nextItem != null) { 34 | return true; 35 | } 36 | 37 | if (stack.empty()) { 38 | return false; 39 | } 40 | 41 | TreeNode node; 42 | if (!unwind) { 43 | while ((node = stack.peek()).hasLeft()) { 44 | stack.push(node.getLeft()); 45 | } 46 | } 47 | 48 | node = stack.pop(); 49 | nextItem = node.getValue(); 50 | 51 | if (node.hasRight()) { 52 | unwind = false; 53 | stack.push(node.getRight()); 54 | } else { 55 | unwind = true; 56 | } 57 | 58 | return true; 59 | } 60 | 61 | @Override 62 | public T next() { 63 | if (!hasNext()) { 64 | throw new NoSuchElementException(); 65 | } 66 | 67 | T toReturn = nextItem; 68 | nextItem = null; 69 | return toReturn; 70 | } 71 | 72 | @Override 73 | public void remove() { 74 | throw new UnsupportedOperationException(); 75 | } 76 | 77 | // Some quick testing below. 78 | public static void main(String[] args) { 79 | TreeNode ll = new TreeNode(1); 80 | TreeNode l = new TreeNode(2); 81 | 82 | TreeNode r = new TreeNode(5); 83 | TreeNode rl = new TreeNode(4); 84 | TreeNode rr = new TreeNode(6); 85 | 86 | l.setLeft(ll); 87 | 88 | r.setLeft(rl); 89 | r.setRight(rr); 90 | 91 | TreeNode rootNode = new TreeNode(3); 92 | rootNode.setLeft(l); 93 | rootNode.setRight(r); 94 | 95 | InorderIterator ii = new InorderIterator(rootNode); 96 | 97 | System.out.println(ii.next()); 98 | System.out.println(ii.hasNext()); 99 | System.out.println(ii.next()); 100 | System.out.println(ii.hasNext()); 101 | System.out.println(ii.next()); 102 | System.out.println(ii.hasNext()); 103 | System.out.println(ii.next()); 104 | System.out.println(ii.hasNext()); 105 | System.out.println(ii.next()); 106 | System.out.println(ii.hasNext()); 107 | System.out.println(ii.next()); 108 | System.out.println(ii.hasNext()); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /java/src/collections/LevelOrderIterator.java: -------------------------------------------------------------------------------- 1 | package collections; 2 | 3 | import java.util.Iterator; 4 | import java.util.LinkedList; 5 | import java.util.NoSuchElementException; 6 | import java.util.Queue; 7 | 8 | import binarytrees.TreeNode; 9 | 10 | /** 11 | * Implement an iterator that iterates through a binary tree in level order. 12 | * 13 | * Methods expected to be implemented: 14 | * 15 | * public class LevelOrderIterator implements Iterator { 16 | * public LevelOrderIterator(TreeNode rootNode) {..} 17 | * public boolean hasNext() {...} 18 | * public T next() {...} 19 | * } 20 | */ 21 | public class LevelOrderIterator implements Iterator { 22 | 23 | private T nextItem; 24 | private final Queue> queue; 25 | 26 | public LevelOrderIterator(TreeNode rootNode) { 27 | queue = new LinkedList>(); 28 | queue.add(rootNode); 29 | } 30 | 31 | @Override 32 | public boolean hasNext() { 33 | if (nextItem != null) { 34 | return true; 35 | } 36 | 37 | if (queue.isEmpty()) { 38 | return false; 39 | } 40 | 41 | TreeNode node = queue.remove(); 42 | if (node.hasLeft()) { 43 | queue.add(node.getLeft()); 44 | } 45 | 46 | if (node.hasRight()) { 47 | queue.add(node.getRight()); 48 | } 49 | 50 | nextItem = node.getValue(); 51 | return true; 52 | } 53 | 54 | @Override 55 | public T next() { 56 | if (!hasNext()) { 57 | throw new NoSuchElementException(); 58 | } 59 | 60 | T toReturn = nextItem; 61 | nextItem = null; 62 | return toReturn; 63 | } 64 | 65 | @Override 66 | public void remove() { 67 | throw new UnsupportedOperationException(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /java/src/collections/MaxIterator.java: -------------------------------------------------------------------------------- 1 | package collections; 2 | 3 | import java.util.Comparator; 4 | import java.util.Iterator; 5 | import java.util.NoSuchElementException; 6 | import java.util.Vector; 7 | 8 | /** 9 | * Implement a max iterator i.e. it always returns the next item in the list 10 | * bigger than the last item returned. 11 | * 12 | * Methods expected to be implemented: 13 | * 14 | * public class MaxIterator implements Iterator { 15 | * public MaxIterator(Iterator iterator, Comparator comparator) {..} 16 | * public boolean hasNext() {...} 17 | * public T next() {...} 18 | * } 19 | */ 20 | public class MaxIterator implements Iterator { 21 | 22 | private final Iterator iterator; 23 | private T nextItem; 24 | private T lastItem; 25 | private final Comparator comparator; 26 | 27 | public MaxIterator(Iterator iterator, Comparator comparator) { 28 | this.iterator = iterator; 29 | this.comparator = comparator; 30 | } 31 | 32 | @Override 33 | public boolean hasNext() { 34 | if (nextItem != null) { 35 | return true; 36 | } 37 | 38 | while (nextItem == null && iterator.hasNext()) { 39 | T item = iterator.next(); 40 | if (lastItem == null || comparator.compare(item, lastItem) > 0) { 41 | nextItem = item; 42 | } 43 | } 44 | 45 | return nextItem != null; 46 | } 47 | 48 | @Override 49 | public T next() { 50 | if (!hasNext()) { 51 | throw new NoSuchElementException(); 52 | } 53 | 54 | lastItem = nextItem; 55 | nextItem = null; 56 | return lastItem; 57 | } 58 | 59 | @Override 60 | public void remove() { 61 | throw new UnsupportedOperationException(); 62 | } 63 | 64 | public static void main(String[] args) { 65 | Vector vec = new Vector(); 66 | vec.add(3); 67 | vec.add(2); 68 | vec.add(9); 69 | vec.add(8); 70 | vec.add(11); 71 | 72 | MaxIterator mi = new MaxIterator(vec.iterator(), 73 | new Comparator() { 74 | @Override 75 | public int compare(Integer a, Integer b) { 76 | return a - b; 77 | } 78 | }); 79 | 80 | System.out.println(mi.next()); 81 | System.out.println(mi.next()); 82 | System.out.println(mi.next()); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /java/src/collections/PeekIterator.java: -------------------------------------------------------------------------------- 1 | package collections; 2 | 3 | import java.util.Iterator; 4 | import java.util.NoSuchElementException; 5 | 6 | /** 7 | * Implement a peeking iterator. This can be used to peek at values 8 | * in the underlying iterator before iterating over them. 9 | * 10 | * Methods expected to be implemented: 11 | * 12 | * public class PeekIterator implements Iterator { 13 | * public PeekIterator(Iterator iterator) {...} 14 | * public boolean hasNext() {...} 15 | * public T next() {...} 16 | * } 17 | */ 18 | public class PeekIterator implements Iterator { 19 | 20 | private final Iterator iterator; 21 | private T nextitem; 22 | 23 | public PeekIterator(Iterator iterator) { 24 | this.iterator = iterator; 25 | } 26 | 27 | @Override 28 | public boolean hasNext() { 29 | if (nextitem != null) { 30 | return true; 31 | } 32 | 33 | if (iterator.hasNext()) { 34 | nextitem = iterator.next(); 35 | } 36 | 37 | return nextitem != null; 38 | } 39 | 40 | @Override 41 | public T next() { 42 | if (!hasNext()) { 43 | throw (new NoSuchElementException("Iterator has no elements left.")); 44 | } 45 | 46 | T toReturn = nextitem; 47 | nextitem = null; 48 | return toReturn; 49 | } 50 | 51 | public T peek() { 52 | if (!hasNext()) { 53 | throw (new NoSuchElementException("Iterator has no elements left.")); 54 | } 55 | 56 | return nextitem; 57 | } 58 | 59 | @Override 60 | public void remove() { 61 | throw new UnsupportedOperationException(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /java/src/collections/PreorderIterator.java: -------------------------------------------------------------------------------- 1 | package collections; 2 | 3 | import java.util.Iterator; 4 | import java.util.NoSuchElementException; 5 | import java.util.Stack; 6 | 7 | import binarytrees.TreeNode; 8 | 9 | /** 10 | * Implement an iterator that iterates through a binary tree in preorder. 11 | * 12 | * Methods expected to be implemented: 13 | * 14 | * public class PreorderIterator implements Iterator { 15 | * public PreorderIterator(TreeNode rootNode) {...} 16 | * public boolean hasNext() {...} 17 | * public T next() {...} 18 | * } 19 | */ 20 | public class PreorderIterator implements Iterator { 21 | private T nextItem; 22 | private final Stack> stack; 23 | 24 | public PreorderIterator(TreeNode rootNode) { 25 | this.nextItem = null; 26 | this.stack = new Stack>(); 27 | stack.push(rootNode); 28 | } 29 | 30 | @Override 31 | public boolean hasNext() { 32 | if (nextItem != null) { 33 | return true; 34 | } 35 | 36 | if (stack.empty()) { 37 | return false; 38 | } 39 | 40 | TreeNode node = stack.peek(); 41 | nextItem = node.getValue(); 42 | if (node.hasLeft()) { 43 | stack.push(node.getLeft()); 44 | } else { 45 | while (!stack.empty()) { 46 | TreeNode current = stack.pop(); 47 | if (current.hasRight()) { 48 | stack.push(current.getRight()); 49 | break; 50 | } 51 | } 52 | } 53 | 54 | return true; 55 | } 56 | 57 | @Override 58 | public T next() { 59 | if (!hasNext()) { 60 | throw new NoSuchElementException(); 61 | } 62 | 63 | T toReturn = nextItem; 64 | nextItem = null; 65 | return toReturn; 66 | } 67 | 68 | @Override 69 | public void remove() { 70 | throw new UnsupportedOperationException(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /java/src/collections/RotatingIterator.java: -------------------------------------------------------------------------------- 1 | package collections; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Iterator; 5 | import java.util.NoSuchElementException; 6 | 7 | /** 8 | * Implement a rotating iterator. The iterator accepts an array list of 9 | * iterators, and iterates over them column-wise. 10 | * 11 | * i.e If the following iterators are passed: 12 | * 13 | * iterator_1 => [1] iterator_2 => [2, 3] iterator_3 => [4, 5] 14 | * 15 | * Then the rotating iterator returns the following elements in sequential 16 | * order: 17 | * 18 | * 1, 2, 4, 3, 5. 19 | * 20 | * Methods expected to be implemented: 21 | * 22 | * public class RotatingIterator implements Iterator { 23 | * public RotatingIterator(ArrayList> iterators) {...} 24 | * public boolean hasNext() {...} 25 | * public T next() {...} 26 | * } 27 | */ 28 | public class RotatingIterator implements Iterator { 29 | 30 | private final ArrayList> iterators; 31 | private int rotatingIndex; 32 | private T nextItem; 33 | 34 | public RotatingIterator(ArrayList> iterators) { 35 | this.iterators = iterators; 36 | this.rotatingIndex = 0; 37 | } 38 | 39 | @Override 40 | public boolean hasNext() { 41 | if (nextItem != null) { 42 | return true; 43 | } 44 | 45 | int count = 0; 46 | boolean itemFound = false; 47 | while (!itemFound && count < iterators.size()) { 48 | Iterator iterator = iterators.get(rotatingIndex); 49 | if (iterator != null && iterator.hasNext()) { 50 | nextItem = iterator.next(); 51 | // we need this because nextItem can possibly be null. 52 | itemFound = true; 53 | } 54 | 55 | rotatingIndex++; 56 | rotatingIndex %= iterators.size(); 57 | count++; 58 | } 59 | 60 | return count != iterators.size(); 61 | } 62 | 63 | @Override 64 | public T next() { 65 | if (!hasNext()) { 66 | throw new NoSuchElementException(); 67 | } 68 | 69 | T toReturn = nextItem; 70 | nextItem = null; 71 | return toReturn; 72 | } 73 | 74 | @Override 75 | public void remove() { 76 | throw new UnsupportedOperationException(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /java/src/common/ArrayUtils.java: -------------------------------------------------------------------------------- 1 | package common; 2 | 3 | import java.util.Comparator; 4 | 5 | /** 6 | * Common methods required for manipulating arrays. 7 | */ 8 | public class ArrayUtils { 9 | // Converts an integer array into Integer array. 10 | public static Integer[] autoBox(int[] array) { 11 | if (array == null) { 12 | return null; 13 | } 14 | 15 | Integer[] converted = new Integer[array.length]; 16 | for (int index = 0; index < array.length; index++) { 17 | converted[index] = array[index]; 18 | } 19 | 20 | return converted; 21 | } 22 | 23 | // Converts a character array into Character array. 24 | public static Character[] autoBox(char[] array) { 25 | if (array == null) { 26 | return null; 27 | } 28 | 29 | Character[] converted = new Character[array.length]; 30 | for (int index = 0; index < array.length; index++) { 31 | converted[index] = array[index]; 32 | } 33 | 34 | return converted; 35 | } 36 | 37 | // Swaps elements of a character array. 38 | public static void swap(char[] array, int fooIndex, int barIndex) { 39 | char temp = array[fooIndex]; 40 | array[fooIndex] = array[barIndex]; 41 | array[barIndex] = temp; 42 | } 43 | 44 | // Swaps elements of an integer array. 45 | public static void swap(int[] array, int fooIndex, int barIndex) { 46 | int temp = array[fooIndex]; 47 | array[fooIndex] = array[barIndex]; 48 | array[barIndex] = temp; 49 | } 50 | 51 | // Swaps elements of a long array. 52 | public static void swap(long[] array, int fooIndex, int barIndex) { 53 | long temp = array[fooIndex]; 54 | array[fooIndex] = array[barIndex]; 55 | array[barIndex] = temp; 56 | } 57 | 58 | // Swaps elements of an array. 59 | public static void swap(T[] array, int fooIndex, int barIndex) { 60 | T temp = array[fooIndex]; 61 | array[fooIndex] = array[barIndex]; 62 | array[barIndex] = temp; 63 | } 64 | 65 | // Searches the given integer array for the occurrence of the value. 66 | // If the value exists in the array, returns first index of occurrence of 67 | // the value. Otherwise, returns -1. 68 | public static int findIndex(int[] array, int value) { 69 | for (int index = 0; index < array.length; index++) { 70 | if (array[index] == value) { 71 | return index; 72 | } 73 | } 74 | 75 | return -1; 76 | } 77 | 78 | // Searches the given array for the occurrence of the value using the 79 | // comparator passed. If the value exists in the array, returns first index 80 | // of occurrence of the value. Otherwise, returns -1. 81 | public static int findIndex(T[] array, T value, Comparator comparator) { 82 | for (int index = 0; index < array.length; index++) { 83 | if (comparator.compare(array[index], value) == 0) { 84 | return index; 85 | } 86 | } 87 | 88 | return -1; 89 | } 90 | 91 | // Swaps the value in table[a][b] with the value in table[c][d]. 92 | public static void swap(Integer[][] table, int a, int b, int c, int d) { 93 | Integer temp = table[a][b]; 94 | table[a][b] = table[c][d]; 95 | table[c][d] = temp; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /java/src/common/BitUtils.java: -------------------------------------------------------------------------------- 1 | package common; 2 | 3 | /** 4 | * Common methods used for manipulating bits. 5 | */ 6 | public class BitUtils { 7 | // Serializes an integer into a byte array. 8 | public static byte[] serialize(int number) { 9 | byte[] serialized = new byte[4]; 10 | 11 | for (int count = 0; count < 4; count++) { 12 | serialized[count] = (byte) (number & 0xff); 13 | number >>>= 8; 14 | } 15 | 16 | return serialized; 17 | } 18 | 19 | // Deserializes an integer from a byte array generated using 20 | // the method above. 21 | public static int deserialize(byte[] serialized) { 22 | int number = 0; 23 | for (int count = 0; count < 4; count++) { 24 | number |= ((serialized[count] & 0xff) << (count * 8)); 25 | } 26 | 27 | return number; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /java/src/common/ListUtils.java: -------------------------------------------------------------------------------- 1 | package common; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Common methods required for manipulating lists. 7 | */ 8 | public class ListUtils { 9 | 10 | // Swaps elements of a list. 11 | public static void swap(List list, int fooIndex, int barIndex) { 12 | T tmp = list.get(fooIndex); 13 | list.set(fooIndex, list.get(barIndex)); 14 | list.set(barIndex, tmp); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /java/src/common/Pair.java: -------------------------------------------------------------------------------- 1 | package common; 2 | 3 | /** 4 | * An object of this class can be used to store a pair of objects. 5 | */ 6 | public class Pair { 7 | private Foo first; 8 | 9 | public Foo getFirst() { 10 | return first; 11 | } 12 | 13 | public void setFirst(Foo foo) { 14 | this.first = foo; 15 | } 16 | 17 | private Bar second; 18 | 19 | public Bar getSecond() { 20 | return second; 21 | } 22 | 23 | public void setSecond(Bar bar) { 24 | this.second = bar; 25 | } 26 | 27 | public Pair(Foo first, Bar second) { 28 | setFirst(first); 29 | setSecond(second); 30 | } 31 | 32 | public Pair() { 33 | } 34 | 35 | @Override 36 | public int hashCode() { 37 | final int prime = 31; 38 | int result = 1; 39 | result = prime * result + ((first == null) ? 0 : first.hashCode()); 40 | result = prime * result + ((second == null) ? 0 : second.hashCode()); 41 | return result; 42 | } 43 | 44 | @Override 45 | public boolean equals(Object obj) { 46 | if (this == obj) 47 | return true; 48 | if (obj == null) 49 | return false; 50 | if (getClass() != obj.getClass()) 51 | return false; 52 | @SuppressWarnings("rawtypes") 53 | Pair other = (Pair) obj; 54 | if (first == null) { 55 | if (other.first != null) 56 | return false; 57 | } else if (!first.equals(other.first)) 58 | return false; 59 | if (second == null) { 60 | if (other.second != null) 61 | return false; 62 | } else if (!second.equals(other.second)) 63 | return false; 64 | return true; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | StringBuffer buffer = new StringBuffer(); 70 | 71 | buffer.append("("); 72 | buffer.append(first == null ? "null" : first.toString()); 73 | buffer.append(","); 74 | buffer.append(second == null ? "null" : second.toString()); 75 | buffer.append(")"); 76 | 77 | return buffer.toString(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /java/src/concurrency/BoundedBlockingQueue.java: -------------------------------------------------------------------------------- 1 | package concurrency; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | /** 7 | * Implement add() and remove() methods for the queue data structure. 8 | * 9 | * The queue should be a bounded queue i.e. at any point of time, it can only 10 | * hold a specified number of elements. 11 | * 12 | * The queue should be blocking i.e. if a thread is trying to read from the 13 | * queue, and does not find any elements left to read, then it should wait until 14 | * an element becomes available. Similarly, if a thread is trying to write to 15 | * the queue, and finds the queue to be full, then it should wait until an 16 | * element is removed from the queue. 17 | * 18 | * The queue should be fair i.e. if there are 10 readers waiting to read from 19 | * the queue, and if a queue element becomes available for reading, then the 20 | * reader thread that arrived earliest in time should be allowed access to read 21 | * the element, and other reader threads should continue to remain blocked. 22 | * Similarly, if there are 10 writers waiting to write to the queue, and if 23 | * slots become available in the queue for writing, then the writer thread that 24 | * arrived earliest in time should be allowed access to write to the free slot, 25 | * and the other writer threads should continue to remain blocked. 26 | */ 27 | public class BoundedBlockingQueue { 28 | private final Queue elementQueue; 29 | private final Queue readerQueue; 30 | private final Queue writerQueue; 31 | private final int capacity; 32 | 33 | public BoundedBlockingQueue(int capacity) { 34 | if (capacity < 0) { 35 | throw new IllegalArgumentException(String.format( 36 | "Queue size cannot be negative. You passed: %d", capacity)); 37 | } 38 | 39 | this.capacity = capacity; 40 | this.elementQueue = new LinkedList(); 41 | this.readerQueue = new LinkedList(); 42 | this.writerQueue = new LinkedList(); 43 | } 44 | 45 | public synchronized void add(T element) throws InterruptedException { 46 | long threadId = Thread.currentThread().getId(); 47 | writerQueue.add(threadId); 48 | 49 | while (elementQueue.size() == capacity 50 | || writerQueue.peek() != threadId) { 51 | wait(); 52 | } 53 | 54 | writerQueue.remove(); 55 | elementQueue.add(element); 56 | notifyAll(); // notify all waiting readers as well as writers. 57 | } 58 | 59 | public synchronized T remove() throws InterruptedException { 60 | long threadId = Thread.currentThread().getId(); 61 | readerQueue.add(threadId); 62 | 63 | while (elementQueue.isEmpty() || readerQueue.peek() != threadId) { 64 | wait(); 65 | } 66 | 67 | readerQueue.remove(); 68 | T toReturn = elementQueue.remove(); 69 | notifyAll(); // notify all waiting readers as well as writers. 70 | 71 | return toReturn; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /java/src/concurrency/FirstReadWriteLock.java: -------------------------------------------------------------------------------- 1 | package concurrency; 2 | 3 | import java.util.Collections; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | 7 | /** 8 | * Solves the first reader writer problem: 9 | * 10 | * 1. If no write lock has been acquired, then any number of read locks are 11 | * allowed to be acquired. 12 | * 13 | * 2. If a write lock has been acquired, then read locks are not allowed to be 14 | * acquired until the write lock has been released. 15 | * 16 | * 3. If one or more read locks have been acquired, then a write lock is not 17 | * allowed to be acquired until all read locks have been released. 18 | * 19 | * 4. Only threads that previously held a read or write lock are allowed to 20 | * release them. 21 | * 22 | * 5. The implementation is not re-entrant. 23 | * 24 | * Note: Writers can potentially starve if there are many more readers when 25 | * compared to writers, but we don't address this in the solution. 26 | */ 27 | public class FirstReadWriteLock implements ReadWriteLock { 28 | private final Semaphore readMutex = new Semaphore(1); 29 | private final Semaphore writeMutex = new Semaphore(1); 30 | private final Set readerIds = Collections 31 | .synchronizedSet(new HashSet()); 32 | private volatile Long writerId; 33 | 34 | @Override 35 | public void readLock() { 36 | try { 37 | readMutex.acquire(); 38 | readerIds.add(Thread.currentThread().getId()); 39 | if (readerIds.size() == 1) { 40 | writeMutex.acquire(); 41 | } 42 | } finally { 43 | readMutex.release(); 44 | } 45 | } 46 | 47 | @Override 48 | public void readUnlock() { 49 | try { 50 | readMutex.acquire(); 51 | long threadId = Thread.currentThread().getId(); 52 | if (!readerIds.contains(threadId)) { 53 | throw new IllegalStateException( 54 | String.format( 55 | "The current thread with id: %d never acquired a read lock before.", 56 | threadId)); 57 | } 58 | readerIds.remove(threadId); 59 | if (readerIds.size() == 0) { 60 | writeMutex.release(); 61 | } 62 | } finally { 63 | readMutex.release(); 64 | } 65 | 66 | } 67 | 68 | @Override 69 | public void writeLock() { 70 | writeMutex.acquire(); 71 | writerId = Thread.currentThread().getId(); 72 | } 73 | 74 | @Override 75 | public void writeUnlock() { 76 | Long threadId = Thread.currentThread().getId(); 77 | if (writerId == null || !writerId.equals(threadId)) { 78 | throw new IllegalStateException( 79 | String.format( 80 | "The current thread with id: %d never acquired a write lock before.", 81 | threadId)); 82 | } 83 | 84 | writeMutex.release(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /java/src/concurrency/ReadWriteLock.java: -------------------------------------------------------------------------------- 1 | package concurrency; 2 | 3 | /** 4 | * Defines a common interface for different types of read writer locks. 5 | */ 6 | public interface ReadWriteLock { 7 | void readLock(); 8 | 9 | void readUnlock(); 10 | 11 | void writeLock(); 12 | 13 | void writeUnlock(); 14 | } 15 | -------------------------------------------------------------------------------- /java/src/concurrency/SchedulingExecutor.java: -------------------------------------------------------------------------------- 1 | package concurrency; 2 | 3 | /** 4 | * Defines an executor that schedules threads to run at specified time. 5 | */ 6 | public interface SchedulingExecutor { 7 | /** 8 | * Schedule the given Runnable to start execution at the specified 9 | * epochTime. 10 | */ 11 | void schedule(Runnable task, long epochTime); 12 | 13 | /** 14 | * Delete a previously scheduled Runnable. 15 | */ 16 | void delete(Runnable task); 17 | 18 | /** 19 | * Shutdown the executor, and disallow all future schedule/delete calls. 20 | */ 21 | void shutdown(); 22 | } 23 | -------------------------------------------------------------------------------- /java/src/concurrency/Semaphore.java: -------------------------------------------------------------------------------- 1 | package concurrency; 2 | 3 | /** 4 | * Implements a counting semaphore implementation. This can be used as a mutex 5 | * by initializing the count to one. 6 | */ 7 | public class Semaphore { 8 | private int count; 9 | private int waitCount = 0; 10 | 11 | public Semaphore(int count) { 12 | if (count <= 0) { 13 | throw new IllegalArgumentException( 14 | String.format( 15 | "Semaphore count should be greater than zero. You passed: %d.", 16 | count)); 17 | } 18 | 19 | this.count = count; 20 | } 21 | 22 | public synchronized void acquire() { 23 | waitCount++; 24 | while (count == 0) { 25 | try { 26 | wait(); 27 | } catch (InterruptedException e) { 28 | throw new RuntimeException(e); 29 | } 30 | } 31 | 32 | waitCount--; 33 | count--; 34 | } 35 | 36 | public synchronized void release() { 37 | if (count == 0) { 38 | notify(); 39 | } 40 | 41 | count++; 42 | } 43 | 44 | public synchronized int numWaitingThreads() { 45 | return waitCount; 46 | } 47 | 48 | // Simple tests for the above class. 49 | public static void main(String[] args) { 50 | final Semaphore semaphore = new Semaphore(2); 51 | new Thread(new Runnable() { 52 | @Override 53 | public void run() { 54 | semaphore.acquire(); 55 | try { 56 | System.out.println("Acquired semaphore.. sleeping!"); 57 | Thread.sleep(3000); 58 | } catch (InterruptedException e) { 59 | e.printStackTrace(); 60 | } 61 | semaphore.release(); 62 | } 63 | }).start(); 64 | 65 | new Thread(new Runnable() { 66 | @Override 67 | public void run() { 68 | semaphore.acquire(); 69 | try { 70 | System.out.println("Acquired semaphore.. sleeping!"); 71 | Thread.sleep(3000); 72 | } catch (InterruptedException e) { 73 | e.printStackTrace(); 74 | } 75 | semaphore.release(); 76 | } 77 | }).start(); 78 | 79 | new Thread(new Runnable() { 80 | @Override 81 | public void run() { 82 | semaphore.acquire(); 83 | try { 84 | System.out.println("Acquired semaphore.. sleeping!"); 85 | Thread.sleep(3000); 86 | } catch (InterruptedException e) { 87 | e.printStackTrace(); 88 | } 89 | semaphore.release(); 90 | } 91 | }).start(); 92 | 93 | new Thread(new Runnable() { 94 | @Override 95 | public void run() { 96 | semaphore.acquire(); 97 | try { 98 | System.out.println("Acquired semaphore.. sleeping!"); 99 | Thread.sleep(3000); 100 | } catch (InterruptedException e) { 101 | e.printStackTrace(); 102 | } 103 | semaphore.release(); 104 | } 105 | }).start(); 106 | 107 | new Thread(new Runnable() { 108 | @Override 109 | public void run() { 110 | semaphore.acquire(); 111 | try { 112 | System.out.println("Acquired semaphore.. sleeping!"); 113 | Thread.sleep(3000); 114 | } catch (InterruptedException e) { 115 | e.printStackTrace(); 116 | } 117 | semaphore.release(); 118 | } 119 | }).start(); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /java/src/dp/EditDistance.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | /** 4 | * Given two text strings A of length n and B of length m, you want to transform 5 | * A into B with a minimum number of operations of the following types: delete a 6 | * character from A, insert a character into A, or change some character in A 7 | * into a new character. The minimal number of such operations required to 8 | * transform A into B is called the edit distance between A and B. 9 | * 10 | * Write a function to compute the edit distance between two given strings. 11 | */ 12 | public class EditDistance { 13 | private static final int COST_OF_DELETION = 1; 14 | private static final int COST_OF_INSERTION = 1; 15 | private static final int COST_OF_REPLACEMENT = 1; 16 | 17 | private static int min(int a, int b, int c) { 18 | return Math.min(Math.min(a, b), c); 19 | } 20 | 21 | public static int findEditDistance(String foo, String bar) { 22 | if (foo == null) { 23 | throw new NullPointerException("foo can't be null."); 24 | } 25 | 26 | if (bar == null) { 27 | throw new NullPointerException("bar can't be null."); 28 | } 29 | 30 | int[][] dpTable = new int[foo.length() + 1][bar.length() + 1]; 31 | dpTable[0][0] = 0; 32 | 33 | // fill first row with cost of transforming an empty string 34 | // to bar[0..0], bar[0..1], bar[0..2], ... , bar[0..bar.length - 1]. 35 | for (int colIndex = 1; colIndex < dpTable[0].length; colIndex++) { 36 | dpTable[0][colIndex] = dpTable[0][colIndex - 1] + 1; 37 | } 38 | 39 | // fill first col with cost of transforming an empty string 40 | // to foo[0..0], foo[0..1], foo[0..2], ... , foo[0..bar.length - 1]. 41 | for (int rowIndex = 1; rowIndex < dpTable.length; rowIndex++) { 42 | dpTable[rowIndex][0] = dpTable[rowIndex - 1][0] + 1; 43 | } 44 | 45 | for (int fooIndex = 1; fooIndex <= foo.length(); fooIndex++) { 46 | for (int barIndex = 1; barIndex <= bar.length(); barIndex++) { 47 | int deleteAndTransform = dpTable[fooIndex - 1][barIndex] 48 | + COST_OF_DELETION; 49 | int insertAndTransform = dpTable[fooIndex][barIndex - 1] 50 | + COST_OF_INSERTION; 51 | int replaceAndTransform = dpTable[fooIndex - 1][barIndex - 1]; 52 | if (foo.charAt(fooIndex - 1) != bar.charAt(barIndex - 1)) { 53 | replaceAndTransform += COST_OF_REPLACEMENT; 54 | } 55 | 56 | dpTable[fooIndex][barIndex] = min(deleteAndTransform, 57 | insertAndTransform, replaceAndTransform); 58 | } 59 | } 60 | 61 | return dpTable[foo.length()][bar.length()]; 62 | } 63 | 64 | public static void main(String[] args) { 65 | System.out.println(findEditDistance("c", "abmd")); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /java/src/dp/LongestCommonSubsequence.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | /** 4 | * Find the longest common subsequence between two strings. 5 | */ 6 | public class LongestCommonSubsequence { 7 | public static String lcs(String x, String y) { 8 | if (x == null || y == null) { 9 | return null; 10 | } 11 | 12 | int[][] dpTable = new int[x.length() + 1][y.length() + 1]; 13 | for (int row = 1; row <= x.length(); row++) { 14 | for (int col = 1; col <= y.length(); col++) { 15 | if (x.charAt(row - 1) == y.charAt(col - 1)) { 16 | dpTable[row][col] = dpTable[row - 1][col - 1] + 1; 17 | } else { 18 | if (dpTable[row - 1][col] >= dpTable[row][col - 1]) { 19 | dpTable[row][col] = dpTable[row - 1][col]; 20 | } else { 21 | dpTable[row][col] = dpTable[row][col - 1]; 22 | } 23 | } 24 | } 25 | } 26 | 27 | return generateSolution(x, y, dpTable).toString(); 28 | } 29 | 30 | private static String generateSolution(String x, String y, int[][] dpTable) { 31 | StringBuffer solution = new StringBuffer(); 32 | generateSolution(x, y, x.length(), y.length(), dpTable, solution); 33 | 34 | return solution.toString(); 35 | } 36 | 37 | private static void generateSolution(String x, String y, int xIndex, 38 | int yIndex, int[][] dpTable, StringBuffer solution) { 39 | if (xIndex <= 0 || yIndex <= 0) { 40 | return; 41 | } 42 | 43 | if (x.charAt(xIndex - 1) == y.charAt(yIndex - 1)) { 44 | generateSolution(x, y, xIndex - 1, yIndex - 1, dpTable, solution); 45 | solution.append(x.charAt(xIndex - 1)); 46 | } else { 47 | if (dpTable[xIndex - 1][yIndex] >= dpTable[xIndex][yIndex - 1]) { 48 | generateSolution(x, y, xIndex - 1, yIndex, dpTable, solution); 49 | } else { 50 | generateSolution(x, y, xIndex, yIndex - 1, dpTable, solution); 51 | } 52 | } 53 | } 54 | 55 | public static void main(String[] args) { 56 | System.out.println(lcs("ABCDBB", "AEFBABB")); 57 | System.out.println(lcs("ABCDBB", "EAGBFAAB")); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /java/src/dp/RatInAMaze.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * A maze is represented as an M x N matrix of 0s and 1s. A rat is stuck in 7 | * location (0,0), and needs to find its way through the maze to location (M-1, 8 | * N-1). 9 | * 10 | * The rat can move either right, or down. 11 | * 12 | * If maze[x][y] == 0, it means that the rat cannot visit this location. If 13 | * maze[x][y] == 1, the rat is allowed to pass through the location. 14 | * 15 | * Write a function to check if a path exists for the rate from (0, 0) to (M-1, 16 | * N-1) in the maze. 17 | */ 18 | public class RatInAMaze { 19 | public static boolean doesPathExist(int[][] maze) { 20 | if (maze == null) { 21 | return false; 22 | } 23 | 24 | int[][] solved = new int[maze.length][maze[0].length]; 25 | for (int[] array : solved) { 26 | Arrays.fill(array, 2); 27 | } 28 | 29 | return doesPathExist(maze, solved, 0, 0); 30 | } 31 | 32 | private static boolean doesPathExist(int[][] maze, int[][] solved, int x, 33 | int y) { 34 | if (x >= maze.length || y >= maze[0].length) { 35 | return false; 36 | } 37 | 38 | if (solved[x][y] != 2) { 39 | return solved[x][y] == 1; 40 | } 41 | 42 | if (maze[x][y] == 0) { 43 | solved[x][y] = 0; 44 | return false; 45 | } 46 | 47 | if (x == maze.length - 1 && y == maze[0].length - 1) { 48 | solved[x][y] = 1; 49 | return true; 50 | } 51 | 52 | solved[x][y] = (doesPathExist(maze, solved, x, y + 1) || doesPathExist( 53 | maze, solved, x + 1, y)) ? 1 : 0; 54 | return solved[x][y] == 1; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /java/src/dp/RobotMove.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | /* 4 | * We are given a nxn square matrix with 0s and 1s. 5 | * 0 means blocked cell and 1 means open cell where a 6 | * robot can walk. If your robot is at (0,0) initially, 7 | * what are the number of ways to reach (n-1,n-1)? 8 | * Your robot can go only right or down. 9 | */ 10 | public class RobotMove { 11 | public static long countMoves(int[][] board) { 12 | if (board == null || board[board.length - 1][board[0].length - 1] == 1) { 13 | return 0; 14 | } 15 | 16 | int numRows = board.length; 17 | int numCols = board[0].length; 18 | long[][] dp = new long[numRows][numCols]; 19 | dp[numRows - 1][numCols - 1] = 1; // base case. 20 | 21 | for (int col = numCols - 2; col >= 0; col--) { 22 | if (board[numRows - 1][col] == 0) { 23 | dp[numRows - 1][col] = dp[numRows - 1][col + 1]; 24 | } else { 25 | dp[numRows - 1][col] = 0; 26 | } 27 | } 28 | 29 | for (int row = numRows - 2; row >= 0; row--) { 30 | if (board[row][numCols - 1] == 0) { 31 | dp[row][numCols - 1] = dp[row + 1][numCols - 1]; 32 | } else { 33 | dp[row][numCols - 1] = 0; 34 | } 35 | } 36 | 37 | for (int row = numRows - 2; row >= 0; row--) { 38 | for (int col = numCols - 2; col >= 0; col--) { 39 | if (board[row][col] == 1) { 40 | dp[row][col] = 0; 41 | } else { 42 | dp[row][col] = dp[row][col + 1] + dp[row + 1][col]; 43 | } 44 | 45 | } 46 | } 47 | 48 | return dp[0][0]; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /java/src/exceptions/EmptyHeapException.java: -------------------------------------------------------------------------------- 1 | package exceptions; 2 | 3 | public class EmptyHeapException extends Exception { 4 | private static final long serialVersionUID = 7369489192365377416L; 5 | } 6 | -------------------------------------------------------------------------------- /java/src/general/BinaryGap.java: -------------------------------------------------------------------------------- 1 | package general; 2 | 3 | /** 4 | * A binary gap within a positive integer N is any maximal sequence of 5 | * consecutive zeros that is surrounded by ones at both ends in the binary 6 | * representation of N. 7 | * 8 | * For example, number 9 has binary representation 1001 and contains a binary 9 | * gap of length 2. The number 529 has binary representation 1000010001 and 10 | * contains two binary gaps: one of length 4 and one of length 3. The number 20 11 | * has binary representation 10100 and contains one binary gap of length 1. The 12 | * number 15 has binary representation 1111 and has no binary gaps. 13 | * 14 | * Write a function that, given a positive integer N, returns the length of its 15 | * longest binary gap. The function should return 0 if N doesn't contain a 16 | * binary gap. For example, given N = 1041 the function should return 5, because 17 | * N has binary representation 10000010001 and so its longest binary gap is of 18 | * length 5. Assume that: N is an integer within the range [1..2,147,483,647]. 19 | */ 20 | public class BinaryGap { 21 | public int binaryGap(int number) { 22 | while (number != 0 && (number & 1) == 0) { 23 | number >>>= 1; 24 | } 25 | 26 | if (number == 0) { 27 | return 0; 28 | } 29 | 30 | int count = 0; 31 | int max = Integer.MIN_VALUE; 32 | while (number != 0) { 33 | if ((number & 1) == 0) { 34 | count++; 35 | } else { 36 | if (count > max) { 37 | max = count; 38 | } 39 | count = 0; 40 | } 41 | 42 | number >>>= 1; 43 | } 44 | 45 | return count; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /java/src/general/DigitSerializedArray.java: -------------------------------------------------------------------------------- 1 | package general; 2 | 3 | /** 4 | * Imagine the sequence: 0123456789101112131415... etc. This is a sequence 5 | * starting from '0', but with no separation between the digits of subsequent 6 | * numbers. 7 | * 8 | * Here, the digits at indices 10 and 11 are '1' and '0' respectively, and they 9 | * together represent the number '10'. Similarly, the digits at indices 190, 10 | * 191, 192 are '1', '0' and '0' respectively, and they together represent the 11 | * number '100'. 12 | * 13 | * Write a function that given only such an index into this sequence, returns 14 | * the digit at the given index. 15 | * 16 | * Other examples: 17 | * 18 | * index = 100 => result = 5 19 | * index = 30 => result = 2 20 | * index = 31 => result = 0 21 | * index = 1000 => result = 3 22 | */ 23 | public class DigitSerializedArray { 24 | public static int getDigit(int index) { 25 | if (index < 0) { 26 | throw new IllegalArgumentException(String.format( 27 | "index should be >= 0. You passed: %d", index)); 28 | } 29 | 30 | int slabStartValue = 0; 31 | int slabLevelCap = 10; 32 | int numDigitsAtThisLevel = 1; 33 | int slabOfNumbers = (slabLevelCap - slabStartValue) 34 | * numDigitsAtThisLevel; 35 | 36 | while (index - slabOfNumbers >= 0) { 37 | index -= slabOfNumbers; 38 | slabStartValue = slabLevelCap; 39 | slabLevelCap *= 10; 40 | numDigitsAtThisLevel++; 41 | slabOfNumbers = (slabLevelCap - slabStartValue) 42 | * numDigitsAtThisLevel; 43 | } 44 | 45 | int corneredNumber = index / numDigitsAtThisLevel + slabStartValue; 46 | int digitFindingIndex = index % numDigitsAtThisLevel + 1; 47 | while (digitFindingIndex < numDigitsAtThisLevel) { 48 | digitFindingIndex++; 49 | corneredNumber /= 10; 50 | } 51 | 52 | return corneredNumber % 10; 53 | } 54 | 55 | public static void main(String[] args) { 56 | String sequence = generateSequence(100000); 57 | for (int index = 0; index < sequence.length(); index++) { 58 | int expected = sequence.charAt(index) - '0'; 59 | int got = getDigit(index); 60 | System.out.printf("Expected: %d, Got: %d\n", expected, got); 61 | if (expected != got) { 62 | throw new AssertionError(); 63 | } 64 | } 65 | } 66 | 67 | private static String generateSequence(int limit) { 68 | StringBuffer buffer = new StringBuffer(); 69 | for (int number = 0; number <= limit; number++) { 70 | buffer.append(number); 71 | } 72 | 73 | return buffer.toString(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /java/src/general/EnglishKeyboard.java: -------------------------------------------------------------------------------- 1 | package general; 2 | 3 | /** 4 | * You are given an imaginary onscreen keyboard containing the English 5 | * alphabets, 'a' through 'z' (lowercase), with the letters laid out in a 6 | * specified number of columns. 7 | * 8 | * For example, if number of cols = 6, then the onscreen keyboard will be: 9 | * 10 | * a b c d e f 11 | * g h i j k l 12 | * m n o p q r 13 | * s t u v w x 14 | * y z 15 | * 16 | * You are using a remote control - (up - 'u', down 'd', left 'l', right 'r' and 17 | * enter '!') to navigate the keyboard, and you start at position (0, 0). 18 | * 19 | * Write a function that given a word will produce the sequence 20 | * of key presses required to type out the word on the onscreen keyboard. 21 | * The function should return the sequence string. 22 | * 23 | * For example: 24 | * 25 | * getSequence(6, "google") should return "d!drr!!ull!rrrrr!ul!" 26 | * getSequence(1, "google") should return "dddddd!dddddddd!!uuuuuuuu!ddddd!uuuuuuu!" 27 | */ 28 | public class EnglishKeyboard { 29 | public static String getSequence(int cols, String word) { 30 | if (cols <= 0) { 31 | throw new IllegalArgumentException(String.format( 32 | "cols should be > 0. You passed: %d", cols)); 33 | } 34 | 35 | if (word == null) { 36 | throw new NullPointerException("word cannot be null"); 37 | } 38 | 39 | StringBuffer buffer = new StringBuffer(); 40 | int prevRow = 0; 41 | int prevCol = 0; 42 | for (int index = 0; index < word.length(); index++) { 43 | int row = findRow(word.charAt(index), cols); 44 | int col = findCol(word.charAt(index), cols); 45 | 46 | move(prevRow, row, buffer, 'd'); 47 | move(row, prevRow, buffer, 'u'); 48 | move(prevCol, col, buffer, 'r'); 49 | move(col, prevCol, buffer, 'l'); 50 | 51 | buffer.append("!"); 52 | 53 | prevRow = row; 54 | prevCol = col; 55 | } 56 | 57 | return buffer.toString(); 58 | } 59 | 60 | private static void move(int start, int end, StringBuffer buffer, 61 | char appendChar) { 62 | while (start < end) { 63 | buffer.append(appendChar); 64 | start++; 65 | } 66 | } 67 | 68 | private static int findRow(char ch, int cols) { 69 | return (ch - 'a') / cols; 70 | } 71 | 72 | private static int findCol(char ch, int cols) { 73 | return (ch - 'a') % cols; 74 | } 75 | 76 | public static void main(String[] args) { 77 | System.out.println(getSequence(6, "google")); 78 | System.out.println(getSequence(1, "google")); 79 | System.out.println(getSequence(2, "google")); 80 | System.out.println(getSequence(10, "google")); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /java/src/general/FindNumCombinations.java: -------------------------------------------------------------------------------- 1 | package general; 2 | 3 | /** 4 | * Find n C r. n C r = n! / r! x (n - r)! 5 | */ 6 | public class FindNumCombinations { 7 | // n C r = n! / r! x (n - r)! 8 | public static long findNumCombinations(int n, int r) { 9 | if (n <= 0 || r < 0) { 10 | throw new IllegalArgumentException( 11 | String.format( 12 | "Values for n should be > 0 and r should be >= 0. You passed n: %d and r: %d.", 13 | n, r)); 14 | } 15 | 16 | if (r > n - r) { 17 | r = n - r; 18 | } 19 | 20 | long result = 1; 21 | for (int i = 0; i < r; i++) { 22 | result *= (n - i); 23 | result /= (i + 1); 24 | } 25 | 26 | return result; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /java/src/general/KnightsTour.java: -------------------------------------------------------------------------------- 1 | package general; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import common.Pair; 7 | 8 | public class KnightsTour { 9 | public static void printKnightsTour(int boardLength) { 10 | if (boardLength <= 0) { 11 | throw new IllegalArgumentException(String.format( 12 | "Board lengths should be > 0. You passed: %d", boardLength)); 13 | } 14 | 15 | boolean[][] visited = new boolean[boardLength][boardLength]; 16 | printKnightsTour(boardLength, 0, 0, visited); 17 | } 18 | 19 | private static void printKnightsTour(int boardLength, int x, int y, 20 | boolean[][] visited) { 21 | if (x >= boardLength || y >= boardLength) { 22 | return; 23 | } 24 | 25 | if (visited[x][y]) { 26 | return; 27 | } 28 | 29 | visited[x][y] = true; 30 | System.out.printf("Knight is visiting: (%d, %d)\n", x, y); 31 | 32 | for (Pair p : getKnightMoves(boardLength, x, y)) { 33 | printKnightsTour(boardLength, p.getFirst(), p.getSecond(), visited); 34 | } 35 | } 36 | 37 | private static List> getKnightMoves(int boardLength, 38 | int row, int col) { 39 | ArrayList> validMoves = new ArrayList>(); 40 | 41 | int x = row - 2; 42 | int y = col - 1; 43 | if (validPosition(boardLength, x, y)) { 44 | validMoves.add(new Pair(x, y)); 45 | } 46 | 47 | y = col + 1; 48 | if (validPosition(boardLength, x, y)) { 49 | validMoves.add(new Pair(x, y)); 50 | } 51 | 52 | x = row + 2; 53 | y = col - 1; 54 | if (validPosition(boardLength, x, y)) { 55 | validMoves.add(new Pair(x, y)); 56 | } 57 | 58 | y = col + 1; 59 | if (validPosition(boardLength, x, y)) { 60 | validMoves.add(new Pair(x, y)); 61 | } 62 | 63 | // 64 | 65 | x = row - 1; 66 | y = col + 2; 67 | if (validPosition(boardLength, x, y)) { 68 | validMoves.add(new Pair(x, y)); 69 | } 70 | 71 | y = col - 2; 72 | if (validPosition(boardLength, x, y)) { 73 | validMoves.add(new Pair(x, y)); 74 | } 75 | 76 | x = row + 1; 77 | y = col + 2; 78 | if (validPosition(boardLength, x, y)) { 79 | validMoves.add(new Pair(x, y)); 80 | } 81 | 82 | y = col - 2; 83 | if (validPosition(boardLength, x, y)) { 84 | validMoves.add(new Pair(x, y)); 85 | } 86 | 87 | return validMoves; 88 | } 89 | 90 | private static boolean validPosition(int boardLength, int x, int y) { 91 | return x >= 0 && x < boardLength && y >= 0 && y < boardLength; 92 | } 93 | 94 | public static void main(String[] args) { 95 | // When board length = 3, the Knight's tour should print all positions 96 | // on the board except (1,1) which can never be visited by the Knight. 97 | printKnightsTour(3); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /java/src/general/LexicographicalRanking.java: -------------------------------------------------------------------------------- 1 | package general; 2 | 3 | /** 4 | * Given a string s, find its lexicographical ranking. 5 | */ 6 | public class LexicographicalRanking { 7 | public static int findLexicographicalRank(String s) { 8 | if (s == null) { 9 | throw new NullPointerException("Can't find rank for null string."); 10 | } 11 | 12 | if (s.length() == 0) { 13 | throw new IllegalArgumentException( 14 | "Can't find rank for empty string."); 15 | } 16 | 17 | int rank = 0; 18 | int exponent = s.length() - 1; 19 | for (int index = 0; index < s.length(); index++) { 20 | rank += new Double(Math.pow(26, exponent)).intValue() 21 | * (getRank(s.charAt(index))); 22 | exponent--; 23 | } 24 | 25 | return rank; 26 | } 27 | 28 | private static int getRank(char c) { 29 | if (c < 'a' || c > 'z') { 30 | throw new IllegalArgumentException(String.format( 31 | "Character is not in range: %c to %c", 'a', 'z')); 32 | } 33 | 34 | return c - 'a' + 1; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /java/src/general/MatrixRegionSum.java: -------------------------------------------------------------------------------- 1 | package general; 2 | 3 | /** 4 | * Given a matrix of integers and coordinates of a rectangular region within the 5 | * matrix, find the sum of numbers falling inside the rectangle. The program 6 | * will be called multiple times with different rectangular regions from the 7 | * same matrix. 8 | */ 9 | public class MatrixRegionSum { 10 | private final int[][] matrix; 11 | private final long[][] sumMatrix; 12 | 13 | public MatrixRegionSum(int[][] matrix) { 14 | if (matrix == null) { 15 | throw new NullPointerException("null matrix is not allowed."); 16 | } 17 | 18 | this.matrix = matrix; 19 | this.sumMatrix = new long[matrix.length][matrix[0].length]; 20 | preComputeSums(); 21 | } 22 | 23 | private void preComputeSums() { 24 | for (int col = 0; col < matrix[0].length; col++) { 25 | sumMatrix[0][col] += matrix[0][col]; 26 | } 27 | 28 | for (int row = 1; row < matrix.length; row++) { 29 | for (int col = 0; col < matrix[0].length; col++) { 30 | sumMatrix[row][col] = sumMatrix[row - 1][col] 31 | + matrix[row][col]; 32 | } 33 | } 34 | 35 | for (int row = matrix.length - 1; row >= 0; row--) { 36 | for (int col = 1; col < matrix[0].length; col++) { 37 | sumMatrix[row][col] += sumMatrix[row][col - 1]; 38 | } 39 | } 40 | } 41 | 42 | // (lx, ly) is the top left co-ordinate of the rectangle. 43 | // (rx, ry) is the bottom right co-ordinate of the rectangle. 44 | public long findSum(int lx, int ly, int rx, int ry) { 45 | if (!valid(lx, ly) || !valid(rx, ry)) { 46 | throw new IllegalArgumentException( 47 | String.format( 48 | "The co-ordinates: (%d, %d), (%d, %d) are not valid co-ordinates.", 49 | lx, ly, rx, ry)); 50 | } 51 | 52 | long sum = sumMatrix[rx][ry]; 53 | sum -= (ly == 0 ? 0 : sumMatrix[rx][ly - 1]); 54 | sum -= (lx == 0 ? 0 : sumMatrix[lx - 1][ry]); 55 | sum += (lx == 0 || ly == 0 ? 0 : sumMatrix[lx - 1][ly - 1]); 56 | 57 | return sum; 58 | } 59 | 60 | public boolean valid(int x, int y) { 61 | return x >= 0 && x < matrix.length && y >= 0 && y < matrix[0].length; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /java/src/general/MaximalSum.java: -------------------------------------------------------------------------------- 1 | package general; 2 | 3 | /** 4 | * Find sum of values in the sub array that has the maximal sum. 5 | */ 6 | public class MaximalSum { 7 | public static long findMaximalSum(int[] array) { 8 | long currentSum = 0L; 9 | long maxSum = 0L; 10 | int biggestNonPositive = Integer.MIN_VALUE; 11 | boolean seenPositive = false; 12 | 13 | for (int number : array) { 14 | currentSum += number; 15 | if (number > 0) { 16 | seenPositive = true; 17 | } 18 | 19 | if (currentSum > maxSum) { 20 | maxSum = currentSum; 21 | } else { 22 | currentSum = 0L; 23 | if (!seenPositive) { 24 | if (number > biggestNonPositive) { 25 | biggestNonPositive = number; 26 | } 27 | } 28 | } 29 | } 30 | 31 | if (!seenPositive) { 32 | return biggestNonPositive; 33 | } 34 | 35 | return maxSum; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /java/src/general/Maze.java: -------------------------------------------------------------------------------- 1 | package general; 2 | 3 | /** 4 | * You are given a maze (2D boolean matrix) where true = free way, false = 5 | * obstacle. Write a function to find out how many ways exist to reach [N][M] 6 | * from [0][0]. 7 | */ 8 | public class Maze { 9 | public static long findNumWays(boolean[][] maze) { 10 | if (maze == null) { 11 | return 0; 12 | } 13 | 14 | boolean[][] visited = new boolean[maze.length][maze[0].length]; 15 | return findNumWays(maze, 0, 0, visited); 16 | } 17 | 18 | private static long findNumWays(boolean[][] maze, int row, int col, 19 | boolean[][] visited) { 20 | if (!isValid(maze, row, col) || visited[row][col] || !maze[row][col]) { 21 | return 0L; 22 | } 23 | 24 | if (endOfMaze(maze, row, col)) { 25 | return 1L; 26 | } 27 | 28 | visited[row][col] = true; 29 | 30 | long numWays = 0L; 31 | numWays += findNumWays(maze, row - 1, col, visited); 32 | numWays += findNumWays(maze, row + 1, col, visited); 33 | numWays += findNumWays(maze, row, col + 1, visited); 34 | numWays += findNumWays(maze, row, col - 1, visited); 35 | 36 | visited[row][col] = false; 37 | return numWays; 38 | } 39 | 40 | private static boolean endOfMaze(boolean[][] maze, int row, int col) { 41 | return maze != null && row == maze.length - 1 42 | && col == maze[0].length - 1; 43 | } 44 | 45 | private static boolean isValid(boolean[][] maze, int row, int col) { 46 | return maze != null && row >= 0 && row < maze.length && col >= 0 47 | && col < maze[0].length; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /java/src/general/MeetingRoom.java: -------------------------------------------------------------------------------- 1 | package general; 2 | 3 | public class MeetingRoom { 4 | private Time earliestStartTime; 5 | 6 | public Time getEarliestStartTime() { 7 | return earliestStartTime; 8 | } 9 | 10 | public void setEarliestStartTime(Time earliestStartTime) { 11 | this.earliestStartTime = earliestStartTime; 12 | } 13 | 14 | public MeetingRoom(Time earliestStartTime) { 15 | setEarliestStartTime(earliestStartTime); 16 | } 17 | 18 | public MeetingRoom() { 19 | setEarliestStartTime(Time.EPOCH); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /java/src/general/MinimumMeetingRooms.java: -------------------------------------------------------------------------------- 1 | package general; 2 | 3 | import java.util.Collections; 4 | import java.util.Comparator; 5 | import java.util.List; 6 | 7 | import sorting.Heap; 8 | import sorting.SimpleHeapImpl; 9 | import exceptions.EmptyHeapException; 10 | 11 | public class MinimumMeetingRooms { 12 | public static int findMinimumMeetingRooms(List schedules, 13 | final Comparator