Repository: mission-peace/interview Branch: master Commit: 94be5deb0c0d Files: 646 Total size: 1.2 MB Directory structure: gitextract_ew93x48r/ ├── .gitignore ├── .idea/ │ ├── misc.xml │ └── vcs.xml ├── C++/ │ ├── Arrays/ │ │ └── Trapping the rain water.cpp │ ├── Bit Manipulation/ │ │ ├── Checking Whether K-th Bit is Set or Not.cpp │ │ ├── Clearing the K-th bit of a number.cpp │ │ ├── Setting the K-th bit of a number.cpp │ │ ├── Toggling Rightmost Set Bit of a number.cpp │ │ └── Toggling the K-th bit of a number.cpp │ ├── Dynamic Programming/ │ │ ├── Edit Distance.cpp │ │ ├── Longest Common Subsequence.cpp │ │ ├── Longest Common Substring.cpp │ │ ├── Longest Increasing Subsequence.cpp │ │ ├── Longest palindromic Subsequence.cpp │ │ └── Matrix Chain Multiplication.cpp │ ├── Graph Algorithms/ │ │ ├── All Pair Shortest Path Problem.cpp │ │ ├── Breadth First Search.cpp │ │ ├── Connected Components Algorithm DFS.cpp │ │ ├── Depth First Search.cpp │ │ ├── Kruskal's Minimum Spanning Tree Algorithm.cpp │ │ ├── Prims Minimum Spanning Tree Algorithm.cpp │ │ ├── Recursive Depth First Search.cpp │ │ ├── Single Shortest Path Bellman Ford Algorithm.cpp │ │ ├── Single Source Shortest Path Dijkstra Algorithm.cpp │ │ └── Topological Sorting.cpp │ ├── Heaps - Priority Queues/ │ │ └── K-th Largest element of the stream.cpp │ ├── Linked List/ │ │ └── Reverse a linked list recursively.cpp │ ├── Number Theory Algorithms/ │ │ ├── Divisors.cpp │ │ └── Sieve of Eratosthenes.cpp │ ├── Recursion/ │ │ ├── Partition of array on the pivot.cpp │ │ └── Permutation of a string.cpp │ ├── Segment Tree/ │ │ └── Segment Tree.cpp │ ├── Stacks - Queue/ │ │ └── CircularQueue.cpp │ ├── String Algorithms/ │ │ ├── KMP.cpp │ │ └── Trie.cpp │ └── Union Find/ │ └── Union Find.cpp ├── LICENSE ├── README.md ├── build.gradle ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── python/ │ ├── array/ │ │ ├── arrayaddition.py │ │ ├── commonthreesortedarray.py │ │ ├── countinversionofsize3.py │ │ ├── flip0smaximum1s.py │ │ ├── longestsamesumspan.py │ │ ├── maximumsumpathtwoarrays.py │ │ ├── maxproductsubarray.py │ │ ├── numberoftrianglesunsortedarray.py │ │ ├── positiveandnegativealternativelymaintainingorder.py │ │ ├── rearrangearrayperindex.py │ │ ├── reorderarraybyindex.py │ │ ├── rotationwithmaxsum.py │ │ ├── smallestintegernotrepresentedbysubsetsum.py │ │ ├── tripletsumlessthantotal.py │ │ └── zigzagarrangement.py │ ├── dynamic/ │ │ ├── bitonicsequence.py │ │ ├── boxstacking.py │ │ ├── breakword.py │ │ ├── coin_change_num_ways.py │ │ ├── coinchangingmincoins.py │ │ ├── count_num_A.py │ │ ├── count_num_binary_without_consec_1.py │ │ ├── cutting_rod.py │ │ ├── dice_throw_ways.py │ │ ├── editdistance.py │ │ ├── egg_drop.py │ │ ├── knapsack_01.py │ │ ├── kth_ugly_number.py │ │ ├── longest_common_subsequence.py │ │ ├── longest_common_substring.py │ │ ├── longest_increasing_subsequence.py │ │ ├── longest_palindromic_subsequence.py │ │ ├── matrix_chain_order.py │ │ ├── maximum_increasing_subsequence.py │ │ ├── nth_fibonacci.py │ │ ├── num_bst.py │ │ ├── num_paths_nm_matrix.py │ │ ├── num_trees_preorder.py │ │ ├── optimal_bst.py │ │ ├── stockbuysellktransactions.py │ │ ├── string_interleaving.py │ │ ├── sub_rectangular_maximum_sum.py │ │ ├── subset_sum.py │ │ ├── symbolexpressionevaluation.py │ │ └── weighted_job_scheduling_max_profit.py │ ├── geometry/ │ │ └── skylinedrawing.py │ ├── graph/ │ │ ├── cycledirectedgraph.py │ │ ├── cycleundirectedgraph.py │ │ ├── dijkstrashortestpath.py │ │ ├── disjointset.py │ │ ├── floydwarshall.py │ │ ├── fordfulkerson.py │ │ ├── graph.py │ │ ├── graphtraversal.py │ │ ├── kruskalmst.py │ │ ├── primmst.py │ │ ├── priorityqueue.py │ │ └── topologicalsort.py │ ├── recursion/ │ │ ├── setpairtogether.py │ │ └── stringpermutation.py │ ├── string/ │ │ ├── Z_Algorithm.py │ │ ├── knuthmorrispratt.py │ │ └── rabinkarp.py │ └── tree/ │ ├── binary_tree.py │ ├── construct_tree_from_inorder_preorder.py │ ├── fenwick_tree.py │ ├── largest_bst_in_binary_tree.py │ ├── max_depth_binary_tree.py │ ├── morris_traversal.py │ └── segmenttreesum.py ├── src/ │ └── com/ │ └── interview/ │ ├── array/ │ │ ├── AdditiveNumber.java │ │ ├── ArrayAddition.java │ │ ├── BestMeetingPoint.java │ │ ├── BuySellStockProfit.java │ │ ├── CheckIfArrayElementsAreConsecutive.java │ │ ├── ChunkMerge.java │ │ ├── CommonThreeSortedArray.java │ │ ├── ConvertAnArrayIntoDecreaseIncreaseFashion.java │ │ ├── CountInversionOfSize3.java │ │ ├── CountSmallerOnRight.java │ │ ├── DivideNumbersInEqualGroupWithClosestSum.java │ │ ├── DuplicateNumberDetection.java │ │ ├── DuplicateWithinkIndices.java │ │ ├── FindElementsOccurringNByKTimesTetris.java │ │ ├── FirstPositiveMissing.java │ │ ├── Flip0sMaximum1s.java │ │ ├── FourSum.java │ │ ├── GasStationCircle.java │ │ ├── GreedyTextJustification.java │ │ ├── GroupElementsInSizeM.java │ │ ├── HIndex.java │ │ ├── IncreasingSubsequnceOfLength3WithMaxProduct.java │ │ ├── IncreasingTripletSubsequence.java │ │ ├── JumpGame.java │ │ ├── KadaneWrapArray.java │ │ ├── KthElementInArray.java │ │ ├── KthLargestInTwoSortedArray.java │ │ ├── LargerElementOnRight.java │ │ ├── LargestMountain.java │ │ ├── LargestSubArrayWithEqual0sAnd1s.java │ │ ├── LeetCodeCandy.java │ │ ├── LongestConsecutiveSubsequence.java │ │ ├── LongestIncreasingSubSequenceOlogNMethod.java │ │ ├── LongestSameSumSpan.java │ │ ├── LongestSubstringWithAtMost2Char.java │ │ ├── MaxNumberFromTwoArray.java │ │ ├── MaxProductSubarray.java │ │ ├── MaxRepeatingNumber.java │ │ ├── MaximumGap.java │ │ ├── MaximumIminusJSuchThatAiGTAj.java │ │ ├── MaximumMinimumArrangement.java │ │ ├── MaximumOfSubarrayOfSizeK.java │ │ ├── MaximumSumPathTwoArrays.java │ │ ├── MaximumSumThreeNonOverlappingSubarray.java │ │ ├── MeetingRooms.java │ │ ├── MinimumDistanceBetweenTwoNumbers.java │ │ ├── MinimumNumberFromSequence.java │ │ ├── MinimumSortedWhichSortsEntireArray.java │ │ ├── MissingRanges.java │ │ ├── MoveAllZerosToEnd.java │ │ ├── MultiplyAllFieldsExceptOwnPosition.java │ │ ├── NthElementOfCountNumberSequence.java │ │ ├── NumberOfTrianglesInUnsortedArray.java │ │ ├── PositiveAndNegativeNumberAlternatively.java │ │ ├── PositiveAndNegativeNumberAlternativelyMaintainingOrder.java │ │ ├── RearrangeArrayPerIndex.java │ │ ├── RearrangeSuchThatArriBecomesArrArri.java │ │ ├── ReorderArrayByIndex.java │ │ ├── RepeatingAndMissingNumber.java │ │ ├── RotationWithMaxSum.java │ │ ├── SelfCrossing.java │ │ ├── ShortestPalindrome.java │ │ ├── SmallestIntegerNotRepresentedBySubsetSum.java │ │ ├── SmallestSubarrayWithAtleastKSum.java │ │ ├── SortedArrayTransformation.java │ │ ├── StableMarriageProblem.java │ │ ├── SubarrayWithGivenSum.java │ │ ├── SummaryRanges.java │ │ ├── ThreeSumSmallerThanTarget.java │ │ ├── TrappingWater.java │ │ ├── TripletInArray.java │ │ ├── TripletSumLessThanTotal.java │ │ ├── TugOfWar.java │ │ ├── WaterContainer.java │ │ ├── WiggleSort.java │ │ └── ZigZagArrangement.java │ ├── binarysearch/ │ │ ├── ArithmeticProgressionSearch.java │ │ ├── BinarySearch.java │ │ ├── CircularBinarySearch.java │ │ ├── CountNDistinctPairsWithDifferenceK.java │ │ ├── FirstOccurrenceOfNumberInSortedArray.java │ │ ├── FloorAndCeilingSortedArray.java │ │ ├── MedianOfTwoSortedArray.java │ │ ├── MedianOfTwoSortedArrayOfDifferentLength.java │ │ ├── MinimumInSortedRotatedArray.java │ │ ├── MissingNumberInConsecutiveNumbers.java │ │ ├── MonotonicallyIncreasingFunctionBecomesPositive.java │ │ ├── NumberOfPairWithXPowerYGreaterThanYPowerX.java │ │ ├── PeakElement.java │ │ ├── SearchForRange.java │ │ ├── SearchInsertPosition.java │ │ ├── SortedAndRotatedArraySearch.java │ │ └── SquareRootOfNumber.java │ ├── bits/ │ │ ├── AddTwoNumberInBinaryRepresentation.java │ │ ├── BitRotation.java │ │ ├── ByteAsStorage.java │ │ ├── CountBits.java │ │ ├── CountingBitsTillNum.java │ │ ├── DrawHorizontalLine.java │ │ ├── FindNumberOccurringOnceOtherNumbers3Times.java │ │ ├── GrayCode.java │ │ ├── InsertMintoNiTojBits.java │ │ ├── MaxProductWordLength.java │ │ ├── MissingNumbers.java │ │ ├── NextHigherAndNextLowerWithSameNumberBits.java │ │ ├── NextPowerOf2.java │ │ ├── NumberOccuringOddTimes.java │ │ ├── NumberOfBitsFlipToConvertNToM.java │ │ ├── RealNumberToBinary.java │ │ ├── RepeatedDnaSequence.java │ │ ├── ReverseBits.java │ │ ├── SquareOfNumber.java │ │ ├── SwapOddEvenBits.java │ │ ├── SwapTwoBits.java │ │ └── WinnerWithBeautifulNumber.java │ ├── dynamic/ │ │ ├── BitonicSequence.java │ │ ├── BoxStacking.java │ │ ├── BreakMultipleWordsWithNoSpaceIntoSpace.java │ │ ├── BurstBalloons.java │ │ ├── CoinChanging.java │ │ ├── CoinChangingMinimumCoin.java │ │ ├── CountAs.java │ │ ├── CountNumberOfBinaryWithoutConsecutive1s.java │ │ ├── CountNumberOfTreePreorder.java │ │ ├── CountNumberOfTreesInBST.java │ │ ├── CutRodToMinimizeCost.java │ │ ├── CuttingRod.java │ │ ├── DecodeWays.java │ │ ├── DiceThrowWays.java │ │ ├── DistinctSubsequence.java │ │ ├── DungeonGame.java │ │ ├── EditDistance.java │ │ ├── EggDropping.java │ │ ├── ExpressionEvaluation.java │ │ ├── FibonacciSeries.java │ │ ├── Immutable2DSumRangeQuery.java │ │ ├── Knapsack01.java │ │ ├── LongestCommonSubsequence.java │ │ ├── LongestCommonSubstring.java │ │ ├── LongestEvenLengthSubstringOfEqualHalf.java │ │ ├── LongestIncreasingPath.java │ │ ├── LongestIncreasingSubsequence.java │ │ ├── LongestPalindromicSubsequence.java │ │ ├── MatrixMultiplicationCost.java │ │ ├── MaxSumForNonAdjacentElements.java │ │ ├── MaximizeSkiGates.java │ │ ├── MaximumLengthChainPair.java │ │ ├── MaximumProductCutting.java │ │ ├── MaximumRectangularSubmatrixOf1s.java │ │ ├── MaximumSizeSubMatrix.java │ │ ├── MaximumSumSubsequence.java │ │ ├── MinCostPath.java │ │ ├── MinJumpToReachEnd.java │ │ ├── MinimumCostTrainTicket.java │ │ ├── MinimumNumberOfPerfectSquares.java │ │ ├── MinimumTriangleSum.java │ │ ├── NPotGold.java │ │ ├── NumberOfPathsInMxNMatrix.java │ │ ├── NumberOfWaysToScorePoints.java │ │ ├── OptimalTreeSearch.java │ │ ├── PaintHouse.java │ │ ├── PalindromePartition.java │ │ ├── PhoneDialNumberOfCombinationOfSizeK.java │ │ ├── RegexMatching.java │ │ ├── RemoveFromEndToMake2IntoMinGreaterThanMax.java │ │ ├── ScrambledString.java │ │ ├── StockBuySellKTransactions.java │ │ ├── SubRectangularMatrixWithMaximumSum.java │ │ ├── SubsetSum.java │ │ ├── SubsquareSurrounedByXs.java │ │ ├── SymbolExpressionEvaluation.java │ │ ├── TextJustification.java │ │ ├── TwoStringInterleavingToFormThird.java │ │ ├── UglyNumbers.java │ │ ├── WeightedJobSchedulingMaximumProfit.java │ │ └── WildCardMatching.java │ ├── geometry/ │ │ ├── ClosestPairOfPoints.java │ │ ├── GrahamScanConvexHull.java │ │ ├── JarvisMarchConvexHull.java │ │ ├── MaximumPointsOnSameLine.java │ │ └── SkylineDrawing.java │ ├── graph/ │ │ ├── AlientDictionary.java │ │ ├── AllCyclesInDirectedGraphJohnson.java │ │ ├── AllCyclesInDirectedGraphTarjan.java │ │ ├── ArticulationPoint.java │ │ ├── BellmanFordShortestPath.java │ │ ├── BinaryMaxHeap.java │ │ ├── BinaryMinHeap.java │ │ ├── BiparteGraph.java │ │ ├── Boggle.java │ │ ├── Bridge.java │ │ ├── CloneDirectedGraph.java │ │ ├── CloneGraph.java │ │ ├── ConvertOneWordToAnother.java │ │ ├── CourseSchedule.java │ │ ├── CycleInDirectedGraph.java │ │ ├── CycleUndirectedGraph.java │ │ ├── DAGShortestPathTopological.java │ │ ├── DijkstraShortestPath.java │ │ ├── DirectedGraphConnectivity.java │ │ ├── DisjointSet.java │ │ ├── EulerianPathAndCircuit.java │ │ ├── EvaluateDivison.java │ │ ├── FillOsWIthXsIfSurroundedByXs.java │ │ ├── FloodFillAlgorithm.java │ │ ├── FloydWarshallAllPairShortestPath.java │ │ ├── FordFulkerson.java │ │ ├── Graph.java │ │ ├── GraphColoring.java │ │ ├── GraphTraversal.java │ │ ├── HamiltonianCycle.java │ │ ├── KruskalMST.java │ │ ├── MaximumBiparteMatching.java │ │ ├── MinimumHeightTree.java │ │ ├── NumberOfIsland.java │ │ ├── NumberOfIslandDynamic.java │ │ ├── NumberofTriangles.java │ │ ├── PrimMST.java │ │ ├── PrintAllPathFromSourceToDestination.java │ │ ├── ShortestDistanceFromExit.java │ │ ├── StronglyConnectedComponent.java │ │ ├── TarjanStronglyConnectedComponent.java │ │ ├── TopologicalSort.java │ │ ├── TransitiveClosure.java │ │ ├── TravelingSalesmanHeldKarp.java │ │ ├── ValidTree.java │ │ ├── WallsAndGates.java │ │ └── WordLadder.java │ ├── linklist/ │ │ ├── AddNumberRepresentedByLinkList.java │ │ ├── CopyLinkListWIthArbitPointer.java │ │ ├── DeleteDuplicateNodes.java │ │ ├── DeleteNAfterMNodes.java │ │ ├── DeleteNodeWithGreaterValueOnRight.java │ │ ├── DoubleLinkList.java │ │ ├── Flatten2DList.java │ │ ├── FlattenLinkList.java │ │ ├── InsertionSortLinkList.java │ │ ├── LRUCache.java │ │ ├── LRUCacheLeetCode.java │ │ ├── LinkList.java │ │ ├── LinkListIsPalindrome.java │ │ ├── LinkListToCompleteBinaryTree.java │ │ ├── LoopInLinkList.java │ │ ├── MergeForLargestSum.java │ │ ├── MergeSortLinkList.java │ │ ├── MiddleElementOfLinkList.java │ │ ├── MultiplyTwoNumbersLinkList.java │ │ ├── QuickSortSingleLinkList.java │ │ ├── RemoveDuplicatesSortedList.java │ │ ├── RemoveMiddleElementsOfLineSegment.java │ │ ├── ReorderList.java │ │ ├── ReverseAlternateKNodes.java │ │ ├── ReverseAlternateNodeAndAppendAtEnd.java │ │ ├── ReverseKNodes.java │ │ ├── RotateList.java │ │ ├── ShuffleMerge.java │ │ ├── SortNearlySortedList.java │ │ ├── SortedCircularLinkList.java │ │ ├── SortedLLToBalancedBST.java │ │ ├── StackWithLinkListMiddleOperation.java │ │ ├── SwapTwoNodesInDoubleLL.java │ │ └── TripletToSumInLinkList.java │ ├── misc/ │ │ ├── AddingTwoSetOfIntervals.java │ │ ├── AngleBetweenHourAndMinuteHand.java │ │ ├── BulbSwitcher.java │ │ ├── CandiesProblem.java │ │ ├── ContainsNumberWithinKDistance.java │ │ ├── ConvertNumberIntoBase26.java │ │ ├── CountRanges.java │ │ ├── DayDifferenceBetweenTwoDates.java │ │ ├── DifferenceBetweenTwoTime.java │ │ ├── FindingCelebrity.java │ │ ├── FloatPointConversion.java │ │ ├── FourPointsFormSquare.java │ │ ├── GetKthPermutation.java │ │ ├── HammingDistanceBetweenPair.java │ │ ├── InsertInterval.java │ │ ├── IntegerListParser.java │ │ ├── KthLargestInRowiseColumnWiseSorted2DArray.java │ │ ├── LoadBalancers.java │ │ ├── NestedIterator.java │ │ ├── NumberToWord.java │ │ ├── PrimeNumbersBeforeN.java │ │ ├── Read4Function.java │ │ ├── RomanNumberToDecimal.java │ │ └── SparseTableRangeMinimumQuery.java │ ├── multiarray/ │ │ ├── Fill2DMatrixWith1.java │ │ ├── GameOfLife.java │ │ ├── LongestConsecutiveIntegerInUnsorted2DArray.java │ │ ├── MatrixCalculation.java │ │ ├── MatrixFindAllSubSquareRectangleMatrix.java │ │ ├── MatrixInDiagonalOrder.java │ │ ├── MatrixOf0sAnd1s.java │ │ ├── MoveCellPerCellValue.java │ │ ├── Mutable2DSumRangeQuery.java │ │ ├── RotateImage.java │ │ ├── ShortestDistanceFromAllBuildings.java │ │ ├── SmallestRectangleBlackPixel.java │ │ ├── SpiralGeneration.java │ │ ├── SpiralPrinting.java │ │ └── TilingProblem.java │ ├── multithreaded/ │ │ ├── BoundedBlockingQueue.java │ │ ├── CountingWord.java │ │ ├── DependencyTaskExecutor.java │ │ ├── FillupMatrix.java │ │ ├── MinMaxKeeper.java │ │ ├── PrintInSequence.java │ │ ├── RealTimeCounter.java │ │ ├── SingleQueueDomainTableUpdate.java │ │ ├── SpinLockMutex.java │ │ ├── ThreadPoolExample.java │ │ └── ThreadPoolImpl.java │ ├── number/ │ │ ├── AggregateNumber.java │ │ ├── AllStrobogrammaticNumber.java │ │ ├── ArithemeticProgressionExists.java │ │ ├── ArrayMultiplication.java │ │ ├── BasicCalculator.java │ │ ├── BinomialCoefficient.java │ │ ├── ConvertToBaseN.java │ │ ├── CountNoOf2s.java │ │ ├── CountNumbersNotIncluding4.java │ │ ├── DivisionWithoutDivisionOperator.java │ │ ├── EuclideanAlgoForGCD.java │ │ ├── FactorialOfLargeNumber.java │ │ ├── GenerateSignature.java │ │ ├── LargestMultipleOf3inArray.java │ │ ├── LuckyNumbers.java │ │ ├── MedianOf3Number.java │ │ ├── MthNumberInNSizeArray.java │ │ ├── NBy2PairSumToK.java │ │ ├── NextLargestPalindrome.java │ │ ├── NotIncluding4.java │ │ ├── NumberOfCombinationsForStairs.java │ │ ├── PermutationBiggerThanNumber.java │ │ ├── PermutationLargerThanGivenArray.java │ │ ├── PowerFunction.java │ │ ├── RearrangeNumberInArrayToFormLargestNumber.java │ │ ├── RussianPeasantMultiplication.java │ │ ├── SmallestNumberGreaterThanGiveNumberIncreasingSequence.java │ │ ├── SquareRoot.java │ │ ├── StrobogrammaticNumber.java │ │ ├── Trailing0sinFactorial.java │ │ └── UniquePartitionOfInteger.java │ ├── playground/ │ │ └── TestInnerClass.java │ ├── random/ │ │ ├── Rand7UsingRand5.java │ │ ├── RandomCountrySelectionByPopluation.java │ │ ├── SelectMRandomNumbersInStream.java │ │ └── ShuffleArray.java │ ├── recursion/ │ │ ├── AllAdjacentCombination.java │ │ ├── Bracketology.java │ │ ├── ChainWordsToFormCircle.java │ │ ├── Combination.java │ │ ├── CombinationOfSizeK.java │ │ ├── CombinationWithStar.java │ │ ├── DifferentWaysToAddParentheses.java │ │ ├── FancyShuffle.java │ │ ├── InterpretationOfArray.java │ │ ├── KeyPadPermutation.java │ │ ├── LongestAbsolutePath.java │ │ ├── MinimumEditForReversePolishNotation.java │ │ ├── NQueenProblem.java │ │ ├── OneEditApart.java │ │ ├── OperatorAdditionForTarget.java │ │ ├── OptimalDivision.java │ │ ├── PrintAllPathFromTopLeftToBottomRight.java │ │ ├── PrintAllSubsequence.java │ │ ├── PrintArrayInAdjacentWay.java │ │ ├── PrintArrayInCustomizedFormat.java │ │ ├── PrintSumCombination.java │ │ ├── ReconstructItinerary.java │ │ ├── RemoveInvalidParenthesis.java │ │ ├── RestoreIPAddresses.java │ │ ├── SetPairTogether.java │ │ ├── StringInterleaving.java │ │ ├── StringPermutation.java │ │ ├── StringPermutationRotation.java │ │ ├── SudokuSolver.java │ │ ├── WordCombination.java │ │ └── WordPattern.java │ ├── regex/ │ │ └── MultiSpaceReplacement.java │ ├── sort/ │ │ ├── CountingSort.java │ │ ├── HeapSort.java │ │ ├── IterativeQuickSort.java │ │ ├── MergeSort.java │ │ ├── PanCakeSorting.java │ │ ├── QuickSort.java │ │ ├── RadixSort.java │ │ ├── Sort0toN3.java │ │ └── SortArrayByFrequence.java │ ├── stackqueue/ │ │ ├── CircularQueue.java │ │ ├── MaximumHistogram.java │ │ ├── MedianFinder.java │ │ ├── RealTimeCounter.java │ │ ├── RealTimeCounterUsingCircularQueue.java │ │ ├── RemoveDuplicateMaintainingOrder.java │ │ ├── RemoveExtraBrackets.java │ │ ├── ReverseStackUsingRecursion.java │ │ ├── SimplyPath.java │ │ └── StockSpanProblem.java │ ├── string/ │ │ ├── AnagramOfFirstAsSubstring.java │ │ ├── CycleLeaderIteration.java │ │ ├── GroupAnagramsTogether.java │ │ ├── InPlaceTransformationOfString.java │ │ ├── LexicographicRankInPermutation.java │ │ ├── LongestPalindromeSubstring.java │ │ ├── LongestSubstringWithKDistinctCharacters.java │ │ ├── LongestSubstringWithoutRepetingCharacter.java │ │ ├── MultiplyStrings.java │ │ ├── NTMatch.java │ │ ├── PalindromePair.java │ │ ├── PrintAnagramTogether.java │ │ ├── RabinKarpSearch.java │ │ ├── RearrangeDuplicateCharsdDistanceAway.java │ │ ├── RemoveConsecutiveDuplicate.java │ │ ├── RunLengthEncoding.java │ │ ├── SmallestWindowContaingAllCharacters.java │ │ ├── StringEncoderDecoder.java │ │ ├── SubstringSearch.java │ │ ├── SubtringWithConcatentationOfWords.java │ │ ├── ValidPalindrome.java │ │ ├── ValidWordAbbreviation.java │ │ ├── WordAbbreviationCombination.java │ │ └── ZAlgorithm.java │ ├── suffixprefix/ │ │ ├── SuffixArray.java │ │ ├── SuffixTree.java │ │ ├── TernaryTree.java │ │ └── Trie.java │ └── tree/ │ ├── AVLTree.java │ ├── AddGreaterValueNodeToEveryNode.java │ ├── ArbitaryTreeToChildSumTree.java │ ├── BSTOneChildPreOrderTraversal.java │ ├── BSTSearch.java │ ├── BTree.java │ ├── BinaryTree.java │ ├── BinaryTreeFromParentRepresentation.java │ ├── BinaryTreeMaximumPathSum.java │ ├── BinaryTreeToCircularLinkList.java │ ├── BinaryTreeToDoubleLinkList.java │ ├── BinaryTreeToSortedLinkList.java │ ├── BoundaryTraversal.java │ ├── ClosestValueBinaryTree.java │ ├── ConnectNodesAtSameLevel.java │ ├── ConstructAllBinaryTreeFromInorderTraversal.java │ ├── ConstructBSTFromPreOrderArray.java │ ├── ConstructFullTreeFromPreOrderPostOrder.java │ ├── ConstructTreeFromInOrderPreOrder.java │ ├── ConstructTreeFromLevelOrderInOrder.java │ ├── ConstructTreeFromPreOrderTraversalWith0or2Child.java │ ├── ContructTreeFromInOrderTraversalRootGreaterThanChild.java │ ├── ContructTreeFromInorderPostOrder.java │ ├── CountNodesCompleteTree.java │ ├── CountNumberOfSmallerElementOnRight.java │ ├── CountPathSum.java │ ├── CountUnivalueTree.java │ ├── CousinNodes.java │ ├── DegenerateBinaryTreeToSortedLL.java │ ├── DiameterOfTree.java │ ├── FenwickTree.java │ ├── FlattenLinkListToBinaryTreePreorder.java │ ├── HeightBalanced.java │ ├── HuffmanEncoding.java │ ├── IdenticalTrees.java │ ├── InorderSuccessor.java │ ├── IntervalTree.java │ ├── IsBST.java │ ├── IsCompleteBinaryTree.java │ ├── IsPreOrderArrayBST.java │ ├── KClosestValueInBinaryTree.java │ ├── LargestBSTInBinaryTree.java │ ├── LargestIndependentSetInTree.java │ ├── LeavesOfBinaryTree.java │ ├── LevelOrderTraversal.java │ ├── LevelOrderTraversalInReverse.java │ ├── LongestConsecutiveSequence.java │ ├── LowestCommonAncestorInBinaryTree.java │ ├── LowestCommonAncestoryBinarySearchTree.java │ ├── MorrisTraversal.java │ ├── NextInorderSuccessorIterator.java │ ├── NextInorderSuccessorOfTwoTree.java │ ├── NodesAtDistanceK.java │ ├── NodesWithNoSibling.java │ ├── PathSum.java │ ├── PopulateInOrderSuccessor.java │ ├── PrintPostOrderFromPreOrderInOrder.java │ ├── PrintTwoBSTInSortedForm.java │ ├── RedBlackTree.java │ ├── RootToLeafToSum.java │ ├── SameTree.java │ ├── SegmentTree.java │ ├── SegmentTreeMinimumRangeQuery.java │ ├── SerializeDeserializeBinaryTree.java │ ├── SinkNegativeToBottom.java │ ├── SizeOfBinaryTree.java │ ├── SortedArrayToBST.java │ ├── SortedOrderPrintCompleteTreeArray.java │ ├── SuccinctTree.java │ ├── SumTree.java │ ├── TreeIsomorphism.java │ ├── TreeTraversalInSpiralOrder.java │ ├── TreeTraversalLevelByLevel.java │ ├── TreeTraversals.java │ ├── UpsidedownBinaryTree.java │ ├── VertexCoverBinaryTreeDP.java │ ├── VerticalOrder.java │ └── VerticalTreePrinting.java └── test/ └── com/ └── interview/ ├── TestUtil.java ├── array/ │ ├── AdditiveNumberTest.java │ ├── ArrayAdditionTest.java │ ├── MaximumMinimumArrangementTest.java │ ├── MeetingRoomsTest.java │ ├── MultiplyAllFieldsExceptOwnPositionTest.java │ ├── NumberOfTriangledInUnsortedArrayTest.java │ └── ThreeSumSmallerThanTargetTest.java ├── bits/ │ ├── CountingBitsTillNumTest.java │ └── MaxProductWordLengthTest.java ├── dynamic/ │ ├── DecodeWaysTest.java │ └── PalindromePartitionTest.java ├── graph/ │ ├── CourseScheduleTest.java │ ├── TravelingSalesmanHeldKarpTest.java │ └── WallsAndGatesTest.java ├── linklist/ │ └── DeleteDuplicateNodesTest.java ├── misc/ │ └── IntegerListParserTest.java ├── multiarray/ │ └── Mutable2DSumRangeQueryTest.java ├── number/ │ ├── AllStrobogrammaticNumberTest.java │ └── BasicCalculatorTest.java ├── recursion/ │ └── RestoreIPAddressesTest.java ├── string/ │ ├── LongestSubstringWithKDistinctCharactersTest.java │ ├── PalindromePairTest.java │ ├── StringEncoderDecoderTest.java │ ├── ValidPalindromeTest.java │ └── ValidWordAbbreviationTest.java ├── suffixprefix/ │ └── TrieTest.java └── tree/ ├── KClosestValueInBinaryTreeTest.java └── VerticalOrderTest.java ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ interview.iml interview.ipr interview.iws build/ .gradle/ .classpath .project .settings/ /bin/ /out .DS_Store python/graph/__pycache__/ python/.idea target/ ================================================ FILE: .idea/misc.xml ================================================ ================================================ FILE: .idea/vcs.xml ================================================ ================================================ FILE: C++/Arrays/Trapping the rain water.cpp ================================================ #include using namespace std; int trapped_water(int array[],int size){ int amount = 0; int left[size],right[size]; left[0] = array[0]; right[size-1] = array[size-1]; for(int i = 1; i < size; i++){ left[i] = max(left[i-1],array[i]); } for(int i = size-2; i >=0; i--){ right[i] = max(right[i+1],array[i]); } for(int i = 0 ; i < size;i++){ amount += min(left[i],right[i]) - array[i]; } return amount; } int main(){ int array[] = {1,0,3,4,5,0,5,7,7,8,9,0}; int size = sizeof(array) / sizeof(int); cout << trapped_water(array,size); return 0; } ================================================ FILE: C++/Bit Manipulation/Checking Whether K-th Bit is Set or Not.cpp ================================================ #include using namespace std; int main(){ int n,k; cout << "Enter the number and the value of K : "; cin >> n >> k; int mask = 1 << (k-1); if(n & mask){ cout << "Yes K-th bit is set" << endl; } else{ cout << "No K-th bit is not set" << endl; } return 0; } ================================================ FILE: C++/Bit Manipulation/Clearing the K-th bit of a number.cpp ================================================ #include using namespace std; int main(){ int n,k,mask; cout << "Enter the number and the value of K : "; cin >> n >> k; mask = ~(1 << (k-1)); n = n&mask; cout << "The number after clearing the K-th bit is : " << n << endl; return 0; } ================================================ FILE: C++/Bit Manipulation/Setting the K-th bit of a number.cpp ================================================ #include using namespace std; int main(){ int n,k; cout << "Enter the number and the value of K :"; cin >> n >> k; int mask = 1 << (k - 1); n = n | mask; cout << "The number after setting the K-th bit is:" << n; return 0; } ================================================ FILE: C++/Bit Manipulation/Toggling Rightmost Set Bit of a number.cpp ================================================ #include using namespace std; int main(){ int n; cout << "Enter the number : "; cin >> n ; n = n & (n-1); cout << "The number after toggling right most set bit : " << n << endl; return 0; } ================================================ FILE: C++/Bit Manipulation/Toggling the K-th bit of a number.cpp ================================================ #include using namespace std; int main(){ int n,k,mask; cout << "Enter the number and the value of K : "; cin >> n >> k; mask = 1 << (k-1); n = n ^ mask; cout << "The number after toggling the K-th bit is : " << n << endl; return 0; } ================================================ FILE: C++/Dynamic Programming/Edit Distance.cpp ================================================ int editDistance(string s1, string s2){ int m = s1.length(); int n = s2.length(); int dp[m+1][n+1]; for (int i = 0; i <= m; i++) { dp[i][0] = i; } for (int j = 0; j <= n; j++) { dp[0][j] = j; } for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (s1[i-1] == s2[j-1]) dp[i][j] = dp[i-1][j-1]; else dp[i][j] = 1 + min(min(dp[i][j-1],dp[i-1][j]),dp[i-1][j-1]); } } return dp[m][n]; } ================================================ FILE: C++/Dynamic Programming/Longest Common Subsequence.cpp ================================================ int lcs(string x,string y){ int m = x.size(),n = y.size(); int dp[m+1][n+1]; for(int i=0;i<=m;i++){ dp[i][0] = 0; } for(int j=0;j<=m;j++){ dp[0][j] = 0; } for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ if(x[i-1] == y[j-1]){ dp[i][j] = dp[i-1][j-1]+1; } else{ dp[i][j] = max(dp[i][j-1],dp[i-1][j]); } } } return dp[m][n]; } ================================================ FILE: C++/Dynamic Programming/Longest Common Substring.cpp ================================================ #include using namespace std; int longest_common_substring(string x,string y){ int m = x.size(); int n = y.size(); int lcs[m+1][n+1]; for(int i = 0 ; i < m; i++){ lcs[i][0] = 0; } for(int j = 0; j < n; j++){ lcs[0][j] = 0; } for(int i = 1; i <= m; i++){ for(int j = 1; j <=n; j++){ if(x[i-1] == y[j-1]){ lcs[i][j] = 1 + lcs[i-1][j-1]; } else{ lcs[i][j] = 0; } } } return lcs[m][n]; } int main(){ string x,y; cin >> x >> y; cout << longest_common_substring(x,y); return 0; } ================================================ FILE: C++/Dynamic Programming/Longest Increasing Subsequence.cpp ================================================ int lis(int array[],int n){ int dp[n],lis_value = -1; for(int i=0;i array[j] and dp[i] < dp[j]+1){ dp[i] = dp[j] + 1; } } } for(int i=0;i using namespace std; int longest_palindromic_subsequence(string str){ int table[str.size()][str.size()]; for(int i = 0 ; i < str.size(); i++){ table[i][i] = 1; } for(int l = 1 ; l < str.size() ; l++){ int i = 0, j = l; while(j != str.size()){ if(str[i] == str[j]){ table[i][j] = 2 + table[i+1][j-1]; } else{ table[i][j] = max(table[i+1][j],table[i][j-1]); } i++;j++; } } return table[0][str.size()-1]; } int main(){ string str; cin >> str; cout << longest_palindromic_subsequence(str); return 0; } ================================================ FILE: C++/Dynamic Programming/Matrix Chain Multiplication.cpp ================================================ int mcm(int p[], int n){ int m[n][n]; int i, j, k, L, q; for (i = 1; i < n; i++) m[i][i] = 0; for (L=2; L #include using namespace std; void floydWarshall(vector> &graph){ for (int k=0; k> graph; int v,e,src,des,weight; cin >> v >> e; graph.resize(v,vector(v,0)); while(e--){ cin >> src >> des >> weight; graph[src][des] = weight; } floydWarshall(graph); for(int i=0;i #include #include #include using namespace std; void breadth_first_search(vector> graph,int src){ vectorvisited(graph.size(),false); queueQ; Q.push(src); visited[src] = true; while(!Q.empty()){ int vertex = Q.front(); Q.pop(); cout << vertex << " "; for(list::iterator itr = graph[vertex].begin();itr!=graph[vertex].end();itr++){ if(!visited[*itr]) Q.push(*itr); visited[*itr] = true; } } } int main(){ vector> graph; int v,e,src,des; cin >> v >> e; graph.resize(v); while(e--){ cin >> src >> des; graph[src].push_back(des); graph[des].push_back(src); } cin >> src; breadth_first_search(graph,src); return 0; } ================================================ FILE: C++/Graph Algorithms/Connected Components Algorithm DFS.cpp ================================================ #include #include #include using namespace std; void connectedComponentsDFS(vector> graph,int src,vector &visited){ if(!visited[src]){ visited[src] = true; for(list::iterator itr = graph[src].begin();itr != graph[src].end();itr++){ connectedComponentsDFS(graph,*itr,visited); } } } int connectedComponents(vector> graph){ int components = 0; vector visited(graph.size(),false); for(int src = 0; src < graph.size();src++){ if(!visited[src]){ components++; connectedComponentsDFS(graph,src,visited); } } return components; } int main(){ vector> graph; int v,e,src,des; cin >> v >> e; graph.resize(v); while(e--){ cin >> src >> des; graph[src].push_back(des); } cout << connectedComponents(graph); return 0; } ================================================ FILE: C++/Graph Algorithms/Depth First Search.cpp ================================================ #include #include #include #include using namespace std; void depth_first_search(vector> graph,int src){ vectorvisited(graph.size(),false); stackS; S.push(src); visited[src] = true; while(!S.empty()){ int vertex = S.top(); S.pop(); cout << vertex << " "; for(list::iterator itr = graph[vertex].begin();itr!=graph[vertex].end();itr++){ if(!visited[*itr]) S.push(*itr); visited[*itr] = true; } } } int main(){ vector> graph; int v,e,src,des; cin >> v >> e; graph.resize(v); while(e--){ cin >> src >> des; graph[src].push_back(des); graph[des].push_back(src); } cin >> src; depth_first_search(graph,src); return 0; } ================================================ FILE: C++/Graph Algorithms/Kruskal's Minimum Spanning Tree Algorithm.cpp ================================================ #include #include #include using namespace std; struct edge{int src,des,weight;}; class UnionFind { int *parent, *ranks, _size; public: UnionFind(){ } UnionFind(int size){ parent = new int[size]; ranks = new int[size]; for(int element = 0 ; element < size ; element++){ parent[element] = element , ranks[element] = 0 ; } _size = size; } void resize(int size){ parent = new int[size]; ranks = new int[size]; for(int element = 0 ; element < size ; element++){ parent[element] = element , ranks[element] = 0 ; } _size = size; } int find(int element){ if(parent[element] == element){ return element; } else{ return parent[element] = find(parent[element]); // Path Compression algorithm } } bool connected(int x,int y){ if(find(x) == find(y)){ return true; } else{ return false; } } void merge(int x,int y){ x = find(x); y = find(y); if(x != y){ // Union by Rank algorithm if(ranks[x] > ranks[y]){ parent[y] = x; } else if(ranks[x] < ranks[y]){ parent[x] = y; } else{ parent[x] = y; ranks[y] ++ ; } _size--; } } void clear(){ delete [] parent; delete [] ranks; } int size(){ return _size; } }; bool comparator(const edge &a,const edge &b){ return a.weight < b.weight; } vector kruskalsAlgorithm(vectorgraph,int vertices){ UnionFind uf(vertices); vectorspanningTree; sort(graph.begin(),graph.end(),comparator); spanningTree.push_back(graph[0]); uf.merge(graph[0].src,graph[0].des); for(int i=1;igraph; int e,v; cin >> e >> v; graph.resize(e); for(int i=0;i> graph[i].src >> graph[i].des >> graph[i].weight; } vector spanningTree = kruskalsAlgorithm(graph,v); for(edge x : spanningTree){ cout << x.src << " " << x.des << " " << x.weight << endl; } return 0; } ================================================ FILE: C++/Graph Algorithms/Prims Minimum Spanning Tree Algorithm.cpp ================================================ #include #include #include #include #include using namespace std; const int INF = INT_MAX; class edge{ public: int src,des,weight; edge(){}edge(int s,int d,int w): src(s),des(d),weight(w){}}; class compare { public: bool operator()(const edge &a,const edge &b){ return a.weight < b.weight; }}; vector primsAlgorithm(vector>> graph,edge minEdge){ vectorspanningTree; priority_queue,compare> Q; while(spanningTree.size() == graph.size()-1){ spanningTree.push_back(minEdge); for(list>::iterator it = graph[minEdge.src].begin();it!=graph[minEdge.src].end();it++){ Q.push(edge(minEdge.src,it->first,it->second)); } for(list>::iterator it = graph[minEdge.des].begin();it!=graph[minEdge.des].end();it++){ Q.push(edge(minEdge.des,it->first,it->second)); } minEdge = Q.top(); Q.pop(); } return spanningTree; } int main(){ vector>>graph; int v,e,src,des,weight; cin >> v >> e; graph.resize(v); edge minEdge; minEdge.weight = INF; while(e--){ cin >> src >> des >> weight; graph[src].push_back(make_pair(des,weight)); graph[des].push_back(make_pair(src,weight)); if(weight < minEdge.weight){ minEdge.src = src, minEdge.des = des, minEdge.weight = weight; } } vector spanningTree = primsAlgorithm(graph,minEdge); for(edge x : spanningTree){ cout << x.src << " " << x.des << " " << x.weight << endl; } return 0; } ================================================ FILE: C++/Graph Algorithms/Recursive Depth First Search.cpp ================================================ #include #include #include using namespace std; void depth_first_search(vector> graph,int src,vector &visited){ if(!visited[src]){ cout << src << " "; visited[src] = true; for(list::iterator itr = graph[src].begin();itr != graph[src].end();itr++){ depth_first_search(graph,*itr,visited); } } } int main(){ vector> graph; vector visited; int v,e,src,des; cin >> v >> e; graph.resize(v); visited.resize(v,false); while(e--){ cin >> src >> des; graph[src].push_back(des); } cin >> src; depth_first_search(graph,src,visited); return 0; } ================================================ FILE: C++/Graph Algorithms/Single Shortest Path Bellman Ford Algorithm.cpp ================================================ #include #include #include using namespace std; struct edge {int src, des, weight;}; pair> bellmanFord(vector graph,int vertex,int source){ vector distances(vertex,INT_MAX); distances[source] = 0; for(int i=0;i distances[graph[j].src] + graph[j].weight){ distances[graph[j].des] = distances[graph[j].src] + graph[j].weight; } } } for(int j=0;j distances[graph[j].src] + graph[j].weight){ return make_pair(false,vector()); } } return make_pair(true,distances); } int main(){ int edges,source,vertex; vector graph; cin >> edges >> vertex; for(int i = 0; i < edges; i++){ cin >> graph[i].src >> graph[i].des >> graph[i].weight; } cin >> source; pair> result = bellmanFord(graph,vertex,source); if(result.first == true){ cout << "No Cycle Exist ! " << endl; for(vector::iterator itr = (result.second).begin();itr!=(result.second).end();itr++){ cout << *itr << " "; } } else{ cout << "Graph Has Negative Weight Cycle" << endl; } return 0; } ================================================ FILE: C++/Graph Algorithms/Single Source Shortest Path Dijkstra Algorithm.cpp ================================================ #include #include #include #include #include using namespace std; struct compare{ bool operator()(const pair &a,const pair &b){ return a.second > b.second; } }; vector dijkshtra(vector>> graph,int src){ priority_queue,vector>,compare> Q; vector distances(graph.size(),INT_MAX); vector visited(graph.size(),false); distances[src] = 0; Q.push(make_pair(src,0)); while(!Q.empty()){ pair current = Q.top(); Q.pop(); cout << "Currently at" << current.first << endl; if(!visited[current.first]){ visited[current.first] = true; for(list> :: iterator vertex = graph[current.first].begin();vertex != graph[current.first].end();vertex++){ if(current.second + vertex->second < distances[vertex->first]){ distances[vertex->first] = current.second + vertex->second; Q.push(make_pair(vertex->first,distances[vertex->first])); } } } } return distances; } int main(){ vector>> graph; int v,e,src,des,weight; cin >> v >> e; graph.resize(v); while(e--){ cin >> src >> des >> weight; graph[src].push_back(make_pair(des,weight)); } cin >> src; vector distances = dijkshtra(graph,src); for(vector :: iterator itr = distances.begin();itr != distances.end();itr++){ cout << *itr << " "; } return 0; } ================================================ FILE: C++/Graph Algorithms/Topological Sorting.cpp ================================================ #include #include #include using namespace std; void topologicalSortDFS(vector> graph,int src,vector &visited,list &topologicalSortedList){ if(!visited[src]){ visited[src] = true; for(list::iterator itr = graph[src].begin();itr != graph[src].end();itr++){ topologicalSortDFS(graph,*itr,visited,topologicalSortedList); } topologicalSortedList.push_front(src); } } list topologicalSort(vector> graph){ list topologicalSortedList; vector visited(graph.size(),false); for(int src = 0; src < graph.size();src++){ topologicalSortDFS(graph,src,visited,topologicalSortedList); } return topologicalSortedList; } int main(){ vector> graph; int v,e,src,des; cin >> v >> e; graph.resize(v); while(e--){ cin >> src >> des; graph[src].push_back(des); } list topologicalSortedList = topologicalSort(graph); for(list::iterator itr = topologicalSortedList.begin();itr!=topologicalSortedList.end();itr++){ cout << *itr << " "; } return 0; } ================================================ FILE: C++/Heaps - Priority Queues/K-th Largest element of the stream.cpp ================================================ #include #include using namespace std; int main(){ int n,k; priority_queue,greater>Q; cout << "Enter the the value of K : "; cin >> k; while(cin >> n){ cout << k << "-th largest element of the stream : "; if(Q.size() < k){ Q.push(n); if(Q.size() == k){ cout << Q.top() 3<< endl; } else{ cout << "NULL" << endl; } } else{ if(Q.top() < n){ Q.pop(); Q.push(n); } cout << Q.top() << endl; } cout << "Enter next element of the stream : "; } return 0; } ================================================ FILE: C++/Linked List/Reverse a linked list recursively.cpp ================================================ void reverse_list(list_node *head){ list_node * } ================================================ FILE: C++/Number Theory Algorithms/Divisors.cpp ================================================ #include #include using namespace std; set generateDivisors(long long int num){ set divisors; for(int i = 1 ; i*i <= num; i++ ){ if(num % i == 0){ divisors.insert(i); if( i != num/i ){ divisors.insert(num/i); } } } return divisors; } int main(){ set d = generateDivisors(23); for(int x : d){ cout << x << " "; } return 0; } ================================================ FILE: C++/Number Theory Algorithms/Sieve of Eratosthenes.cpp ================================================ #include #include #include using namespace std; const int MAX = 1000*1000; const int LMT = 1000; vector prime(MAX+1,true); int seiveEratosthenes(){ prime[0] = prime[1] = false; for(int i = 2; i <= LMT; i++){ if(prime[i]){ for(int j = i + i; j <= MAX ; j += i){ prime[j] = false; } } } return count_if(prime.begin(),prime.end(),[](bool p){ return p == true;}); } int main(){ cout << seiveEratosthenes(); return 0; } ================================================ FILE: C++/Recursion/Partition of array on the pivot.cpp ================================================ #include using namespace std; void partition(int array[],int low,int high){ int i = low-1, pivot = array[high-1]; for(int j = low ; j < high ; j++){ if(array[j] <= pivot){ i++; swap(array[i],array[j]); } } swap(array[i+1],array[high-1]); } int main(){ int n; cin >> n; int array[n]; partition(array,0,n); return 0; } ================================================ FILE: C++/Recursion/Permutation of a string.cpp ================================================ #include using namespace std; void permutation(char str[],int k,int n){ if(k == n){ for(int j = 0; j < n; j++){ cout << str[j]; } cout << endl; } else{ for(int i = k ; i < n; i++){ swap(str[i],str[k]); permutation(str,k+1,n); swap(str[i],str[k]); } } } int main(){ char str[] = {'A','B','C','D'}; permutation(str,0,4); return 0; } ================================================ FILE: C++/Segment Tree/Segment Tree.cpp ================================================ void buildTree (int tree[],int array[], int index, int low, int high) { if (low == high) tree[index] = array[low]; else { int mid = (low + high) >> 1; buildTree (tree,array, index*2, low, mid); buildTree (tree,array, index*2+1, mid+1, high); tree[index] = tree[index*2] + tree[index*2+1]; } } int rangeQuery (int tree[],int index, int low, int high, int l, int r) { if (l > r) return 0; if (l == low && r == high) return tree[index]; int mid = (low + high) >> 1; return rangeQuery (tree,index*2, low, mid, l, min(r,mid)) + rangeQuery (tree,index*2+1, mid+1, high, max(l,mid+1), r); } void updateQuery (int tree[],int index, int low, int high, int pos, int delta) { if (low == high) tree[index] = delta; else { int mid = (low + high) >> 1; if (pos <= mid) updateQuery (tree,index*2, low, mid, pos, delta); else updateQuery (tree,index*2+1, mid+1, high, pos, delta); tree[index] = tree[index*2] + tree[index*2+1]; } } ================================================ FILE: C++/Stacks - Queue/CircularQueue.cpp ================================================ #include using namespace std; class circular_queue { private : int *array ; int front, back ; int MAX; public : circular_queue( int maxsize = 10 ) ; void enqueue ( int item ) ; int dequeue( ) ; void display( ) ; } ; circular_queue :: circular_queue( int maxsize ) { MAX = maxsize ; array = new int [ MAX ]; front = back = -1 ; for ( int i = 0 ; i < MAX ; i++ ) array[i] = 0 ; } void circular_queue :: enqueue(int item){ if((back+1)%MAX == front){ cout << "Queue is full" << endl; return ; } back = ( back + 1 ) % MAX; array[back] = item ; if ( front == -1 ) front = 0 ; } int circular_queue :: dequeue(){ int data ; if ( front == -1 ) { cout << "\nQueue is empty" ; return NULL ; } data = array[front] ; array[front] = 0 ; if ( front == back ) { front = -1 ; back = -1 ; } else front = ( front + 1 ) % MAX; return data ; } void circular_queue :: display() { cout << endl ; for ( int i = 0 ; i < MAX ; i++ ) cout << array[i] << " " ; cout << endl ; } int main(){ circular_queue cq(10) ; cq.enqueue(14); cq.enqueue(22); cq.enqueue(13); cq.enqueue(-6); cq.enqueue(25); cout << "\nElements in the circular queue: " ; cq.display(); int i = cq.dequeue() ; cout << "Item deleted: " << i ; i = cq.dequeue(); cout << "\nItem deleted: " << i ; cout << "\nElements in the circular queue after deletion: " ; cq.display(); cq.enqueue(21); cq.enqueue(17); cq.enqueue(18); cq.enqueue(9); cq.enqueue(20); cout << "Elements in the circular queue after addition: " ; cq.display(); cq.enqueue(32); cout << "Elements in the circular queue after addition: " ; cq.display(); return 0; } ================================================ FILE: C++/String Algorithms/KMP.cpp ================================================ vector computePrefix(string pat){ int m = pat.size(); vector longestPrefix(m); for(int i = 1, k = 0; i < m; i++){ while(k > 0 && pat[k] != pat[i]){ k = longestPrefix[k - 1]; } if(pat[i] == pat[k]){ longestPrefix[i] = ++k; } else{ longestPrefix[i] = k; } } return longestPrefix; } void KMP(string str,string pat){ int n = str.size(); int m = pat.size(); vector longestPrefix = computePrefix(pat); for(int i = 0, k = 0; i < n; i++){ while(k > 0 && pat[k] != str[i]){ k = longestPrefix[k - 1]; } if(str[i] == pat[k]){ k++; } if(k == m){ cout << i - m + 1 << "\n"; k = longestPrefix[k - 1]; } } } ================================================ FILE: C++/String Algorithms/Trie.cpp ================================================ struct Trie { Trie* child[26]; bool isLeaf; Trie() { memset(child, 0, sizeof(child)); isLeaf = 0; } void pushWord(char *str) { if(*str == '\0') isLeaf = 1; else { int cur = *str - 'a'; if(child[cur] == 0 ) child[cur] = new Trie(); child[cur]->pushWord(str+1); } } bool wordExist(char* str) { if(*str == '\0') return isLeaf; int cur = *str - 'a'; if(child[cur] == 0 ) return false; return child[cur]->wordExist(str+1); } bool prefixExist(char* str) { if(*str == '\0') return true; int cur = *str - 'a'; if(child[cur] == 0 ) return false; return child[cur]->prefixExist(str+1); } }; ================================================ FILE: C++/Union Find/Union Find.cpp ================================================ #include using namespace std; class UnionFind { int *parent, *ranks, _size; public: UnionFind(){ } UnionFind(int size){ parent = new int[size]; ranks = new int[size]; for(int element = 0 ; element < size ; element++){ parent[element] = element , ranks[element] = 0 ; } _size = size; } void resize(int size){ parent = new int[size]; ranks = new int[size]; for(int element = 0 ; element < size ; element++){ parent[element] = element , ranks[element] = 0 ; } _size = size; } int find(int element){ if(parent[element] == element){ return element; } else{ return parent[element] = find(parent[element]); // Path Compression algorithm } } bool connected(int x,int y){ if(find(x) == find(y)){ return true; } else{ return false; } } void merge(int x,int y){ x = find(x); y = find(y); if(x != y){ // Union by Rank algorithm if(ranks[x] > ranks[y]){ parent[y] = x; } else if(ranks[x] < ranks[y]){ parent[x] = y; } else{ parent[x] = y; ranks[y] ++ ; } _size--; } } void clear(){ delete [] parent; delete [] ranks; } int size(){ return _size; } }; int main(){ UnionFind uf(5); cout << uf.size() << endl; // 5 disjoint sets are there uf.merge(0,1); cout << uf.size() << endl; // 4 disjoint sets are there uf.merge(0,2); cout << uf.size() << endl; // 3 disjoint sets are there uf.merge(1,2); cout << uf.size() << endl; // 3 disjoint sets are there uf.clear(); return 0; } ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================

Please visit my wiki link for full list of questions

https://github.com/mission-peace/interview/wiki

Like my facebook page for latest updates on my youtube channel

https://www.facebook.com/tusharroy25

Contribution

Please contribute to this repository to help it make better. Any change like new question, code improvement, doc improvement etc. is very welcome. Just send me a pull request and I will review the request and approve it if it looks good.

How to use this repository

Softwares to install

* Install JDK8 https://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html * Install Git https://git-scm.com/book/en/v2/Getting-Started-Installing-Git * Install either Intellij https://www.jetbrains.com/idea/download/ * If you like eclipse instead of intellij install eclipse https://eclipse.org/downloads/

Set up your desktop

* Pull the git repository. Go to command line and type git clone https://github.com/mission-peace/interview.git * Go to root directory of checked out project. * Run ./gradlew idea to generate idea related classes * Fire up intellij. Go to Open. Go to git repo folder and open interview.ipr . On file menu go to project structure. Update language level support to 8 * If you use eclipse, do ./gradlew eclipse . This will generate eclipse related files. Go to eclipse and open up folder containing this repo. * Go to any program and run that program * Go to any test and run the junit test. * Run ./gradlew build to create classes, run tests and create jar. ================================================ FILE: build.gradle ================================================ apply plugin: 'java' apply plugin: 'idea' apply plugin: 'eclipse' apply plugin: "jacoco" sourceCompatibility = '1.8' targetCompatibility = '1.8' repositories { mavenCentral() } dependencies { testCompile 'junit:junit:4.12' } sourceSets { main { java { srcDir 'src' } } test { java { srcDir 'test' } } } jacocoTestReport { reports { xml.enabled false csv.enabled false html.destination "${buildDir}/jacocoHtml" } } ================================================ FILE: gradle/wrapper/gradle-wrapper.properties ================================================ #Sat Apr 02 16:59:09 PDT 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-bin.zip ================================================ FILE: gradlew ================================================ #!/usr/bin/env bash ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS="" APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn ( ) { echo "$*" } die ( ) { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; esac # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin, switch paths to Windows format before running java if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=$((i+1)) done case $i in (0) set -- ;; (1) set -- "$args0" ;; (2) set -- "$args0" "$args1" ;; (3) set -- "$args0" "$args1" "$args2" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules function splitJvmOpts() { JVM_OPTS=("$@") } eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" ================================================ FILE: python/array/arrayaddition.py ================================================ def add(arr1, arr2): l = max(len(arr1), len(arr2)) result = [0 for j in range(l)] c = 0 i = len(arr1) - 1 j = len(arr2) - 1 r = 0 l -= 1 while i >= 0 and j >= 0: r = arr1[i] + arr2[j] + c i -= 1 j -= 1 c = r // 10 result[l] = r % 10 l -= 1 while i >= 0: r = arr1[i] + c i -= 1 c = r // 10 result[l] = r % 10 l -= 1 while j >= 0: r = arr1[j] + c j -= 1 c = r // 10 result[l] = r % 10 l -= 1 if c != 0: new_result = [0 for j in range(len(result) + 1)] t = len(new_result) - 1 while t > 0: new_result[t] = result[t - 1] t -= 1 new_result[0] = c return new_result return result arr1 = [9, 9, 9, 9, 9, 9, 9] arr2 = [1, 6, 8, 2, 6, 7] result = add(arr1, arr2) print(result) ================================================ FILE: python/array/commonthreesortedarray.py ================================================ # http://www.geeksforgeeks.org/find-common-elements-three-sorted-arrays/ def common_elements(input1, input2, input3): result = [] i = 0 j = 0 k = 0 while i < len(input1) and j < len(input2) and k < len(input3): if input1[i] == input2[j] and input2[j] == input3[k]: result.append(input1[i]) i = i + 1 j = j + 1 k = k + 1 elif input1[i] < input2[j]: i = i + 1 elif input2[j] < input3[k]: j = j + 1 else: k = k + 1 return result if __name__ == '__main__': input1 = [1, 5, 10, 20, 40, 80] input2 = [6, 7, 20, 80, 100] input3 = [3, 4, 15, 20, 30, 70, 80, 120] print(common_elements(input1, input2, input3)) ================================================ FILE: python/array/countinversionofsize3.py ================================================ # http://www.geeksforgeeks.org/count-inversions-of-size-three-in-a-give-array/ def find_inversions(input): inversion = 0 for i in range(1, len(input) - 1): larger = 0 for k in range(0, i): if input[k] > input[i]: larger = larger + 1 smaller = 0 for k in range(i+1, len(input)): if input[k] < input[i]: smaller = smaller + 1 inversion += larger*smaller return inversion if __name__ == '__main__': input = [9, 6, 4, 5, 8] print(find_inversions(input)) ================================================ FILE: python/array/flip0smaximum1s.py ================================================ # http://www.geeksforgeeks.org/find-zeroes-to-be-flipped-so-that-number-of-consecutive-1s-is-maximized/ def flip_0s_to_maximize_consecutive_1s(input, flips_allowed): window_start = 0 count_zero = 0 result = 0 for i in range(len(input)): if input[i] == 1: result = max(result, i - window_start + 1) else: if count_zero < flips_allowed: count_zero = count_zero + 1 result = max(result, i - window_start + 1) else: while True: if input[window_start] == 0: window_start = window_start + 1 break window_start = window_start + 1 return result if __name__ == '__main__': input = [0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1] print(flip_0s_to_maximize_consecutive_1s(input, 1)) ================================================ FILE: python/array/longestsamesumspan.py ================================================ # http://www.geeksforgeeks.org/longest-span-sum-two-binary-arrays/ # java code https://github.com/mission-peace/interview/blob/master/src/com/interview/array/LongestSameSumSpan.java def longest_span(input1, input2): if len(input1) != len(input2): raise ValueError; diff = {} prefix1 = 0 prefix2 = 0 max_span = 0 diff[0] = -1 for i in range(len(input1)): prefix1 += input1[i] prefix2 += input2[i] curr_diff = prefix1 - prefix2 if curr_diff in diff: max_span = max(max_span, i - diff[curr_diff]) else: diff[curr_diff] = i return max_span if __name__ == '__main__': input1 = [1, 0, 0, 1, 1, 0] input2 = [0, 1, 1, 0, 1, 1] print(longest_span(input1, input2)) ================================================ FILE: python/array/maximumsumpathtwoarrays.py ================================================ # http://www.geeksforgeeks.org/maximum-sum-path-across-two-arrays/ def max_sum(input1, input2): max_sum = 0 i = 0 j = 0 sum1 = 0 sum2 = 0 while i < len(input1) and j < len(input2): if input1[i] == input2[j]: if sum1 > sum2: max_sum += sum1 + input1[i] else: max_sum += sum2 + input2[j] i = i + 1 j = j + 1 sum1 = 0 sum2 = 0 elif input1[i] < input2[j]: sum1 += input1[i] i = i + 1 else: sum2 += input2[j] j = j + 1 while i < len(input1): sum1 += input1[i] i = i + 1 while j < len(input2): sum2 += input2[j] j = j + 1 if sum1 > sum2: max_sum += sum1 else: max_sum += sum2 return max_sum if __name__ == '__main__': input1 = [2, 3, 7, 10, 12, 15, 30, 34] input2 = [1, 5, 7, 8, 10, 15, 16, 19] print(max_sum(input1, input2)) ================================================ FILE: python/array/maxproductsubarray.py ================================================ # http://www.geeksforgeeks.org/maximum-product-subarray/ def max_product(input): max_ending = 1 min_ending = 1 max_so_far = 1 for i in input: if i > 0: max_ending = max_ending * i min_ending = min(min_ending*i, 1) elif i == 0: max_ending = 1 min_ending = 1 else: t = max_ending max_ending = max(min_ending*i, 1) min_ending = t * i if max_so_far < max_ending: max_so_far = max_ending return max_so_far if __name__ == '__main__': input = [-6,-3,8,-9,-1,-1,3,6,9,0,3,-1] print(max_product(input)) ================================================ FILE: python/array/numberoftrianglesunsortedarray.py ================================================ # http://www.geeksforgeeks.org/find-number-of-triangles-possible/ def number_of_triangles(input): input.sort() count = 0 for i in range(len(input)-2): k = i + 2 for j in range(i+1, len(input)): while k < len(input) and input[i] + input[j] > input[k]: k = k + 1 count += k - j - 1 return count if __name__ == '__main__': input = [15, 9, 8, 3, 4, 5, 6] print(number_of_triangles(input)) ================================================ FILE: python/array/positiveandnegativealternativelymaintainingorder.py ================================================ # http://www.geeksforgeeks.org/rearrange-array-alternating-positive-negative-items-o1-extra-space/ def rearrange(input): for i in range (len(input)): if i%2 == 0 and input[i] >= 0: index_of_next_negative = find_next(input, i+1, False) if index_of_next_negative == -1: return else: right_rotate(input, i, index_of_next_negative) elif i % 2 != 0 and input[i] < 0: index_of_next_positive = find_next(input, i+1, True) if index_of_next_positive == -1: return else: right_rotate(input, i, index_of_next_positive) def find_next(input, start, isPositive): for i in range(start, len(input)): if (isPositive and input[i] >= 0) or (not isPositive and input[i] < 0): return i; return -1 def right_rotate(input, start, end): t = input[end] for i in range(end, start -1, -1): input[i] = input[i-1] input[start] = t if __name__ == '__main__': input = [-5, -2, 5, 2, 4, 7, 1, 8, 0, -8]; rearrange(input) print(input) ================================================ FILE: python/array/rearrangearrayperindex.py ================================================ # http://www.geeksforgeeks.org/rearrange-array-arrj-becomes-arri-j/ def rearrange(input): for i in range(len(input)): input[i] += 1 for i in range(len(input)): if input[i] > 0: rearrange_util(input, i) for i in range(len(input)): input[i] = -input[i] - 1 def rearrange_util(input, start): i = start + 1 v = input[start] while v > 0: t = input[v-1] input[v-1] = -i i = v v = t if __name__ == '__main__': input = [1, 2, 0, 5, 3, 4]; rearrange(input) print(input) ================================================ FILE: python/array/reorderarraybyindex.py ================================================ # http://www.geeksforgeeks.org/reorder-a-array-according-to-given-indexes/ def reorder(input, index): if len(input) != len(index): raise ValueError for i in range(len(index)): while index[i] != i: s_index = index[index[i]] s_val = input[index[i]] index[index[i]] = index[i] input[index[i]] = input[i] index[i] = s_index input[i] = s_val if __name__ == '__main__': input = [50, 40, 70, 60, 90] index = [3, 0, 4, 1, 2] reorder(input, index) print(input) print(index) ================================================ FILE: python/array/rotationwithmaxsum.py ================================================ # http://www.geeksforgeeks.org/find-maximum-value-of-sum-iarri-with-only-rotations-on-given-array-allowed/ def max_sum(input): arr_sum = 0 rotation_sum = 0 for i in range(len(input)): arr_sum += input[i] rotation_sum += i*input[i] max_rotation_sum = rotation_sum for i in range(1, len(input)): rotation_sum += len(input)*input[i-1] - arr_sum max_rotation_sum = max(max_rotation_sum, rotation_sum) return max_rotation_sum if __name__ == '__main__': input = [10, 1, 2, 3, 4, 5, 6, 7, 8, 9] print(max_sum(input)) ================================================ FILE: python/array/smallestintegernotrepresentedbysubsetsum.py ================================================ # http://www.geeksforgeeks.org/find-smallest-value-represented-sum-subset-given-array/ def find_smallest_integer(input): result = 1 for i in range(len(input)): if input[i] <= result: result += input[i] else: break return result if __name__ == '__main__': input = [1, 2, 3, 8] print(find_smallest_integer(input)) ================================================ FILE: python/array/tripletsumlessthantotal.py ================================================ # http://www.geeksforgeeks.org/count-triplets-with-sum-smaller-that-a-given-value/ def find_all_triplet(input, total): input.sort() result = 0 for i in range(len(input) - 2): j = i + 1 k = len(input) - 1 while j < k: if input[i] + input[j] + input[k] >= total: k = k - 1 else: result += k - j j = j + 1 return result if __name__ == '__main__': input = [5, 1, 3, 4, 7] print(find_all_triplet(input, 12)) ================================================ FILE: python/array/zigzagarrangement.py ================================================ # http://www.geeksforgeeks.org/convert-array-into-zig-zag-fashion/ def rearrange(input): is_less = True for i in range(len(input)-1): if is_less: if input[i] > input[i+1]: swap(input, i, i+1) else: if input[i] < input[i+1]: swap(input, i, i+1) is_less = not is_less def swap(input, i, j): t = input[i] input[i] = input[j] input[j] = t if __name__ == '__main__': input = [4, 3, 2, 6, 7, 1, 9] rearrange(input) print(input) ================================================ FILE: python/dynamic/bitonicsequence.py ================================================ """ Problem Statement ================= Find the length of the longest Bitonic Sequence in a given sequence of numbers. A Bitonic sequence is a sequence of numbers which are increasing and then decreasing. Video ----- * https://youtu.be/TWHytKnOPaQ Analysis -------- * Runtime O(n) Reference --------- * http://www.geeksforgeeks.org/dynamic-programming-set-15-longest-bitonic-subsequence/ """ def longest_bitonic(sequence): length_of_input = len(sequence) increasing_sequence = [1] * length_of_input decreasing_sequence = [1] * length_of_input for i in range(1, length_of_input): for j in range(0, i): if sequence[i] > sequence[j]: increasing_sequence[i] = max(increasing_sequence[i], increasing_sequence[j] + 1) for i in range(length_of_input - 2, -1, -1): for j in range(length_of_input - 1, i, -1): if sequence[i] > sequence[j]: decreasing_sequence[i] = max(decreasing_sequence[i], decreasing_sequence[j] + 1) max_value = 0 for i in range(len(sequence)): bitonic_sequence_length = increasing_sequence[i] + decreasing_sequence[i] - 1 max_value = max(max_value, bitonic_sequence_length) return max_value if __name__ == '__main__': max_value = longest_bitonic([1, 4, 3, 7, 2, 1, 8, 11, 13, 0]) assert 7 == max_value # 1, 4, 7, 8, 11, 13, 0 ================================================ FILE: python/dynamic/boxstacking.py ================================================ """ Problem Statement ================= Given different dimensions and unlimited supply of boxes for each dimension, stack boxes on top of each other such that it has maximum height but with caveat that length and width of box on top should be strictly less than length and width of box under it. You can rotate boxes as you like. 1) Create all rotations of boxes such that length is always greater or equal to width 2) Sort boxes by base area in non increasing order (length * width). This is because box with more area will never ever go on top of box with less area. 3) Take T[] and result[] array of same size as total boxes after all rotations are done 4) Apply longest increasing subsequence type of algorithm to get max height. Analysis -------- If n number of dimensions are given total boxes after rotation will be 3n. * Space complexity is O(n) * Time complexity - O(nlogn) to sort boxes. O(n^2) to apply DP on it So really O(n^2) Video ----- * https://youtu.be/9mod_xRB-O0 References ---------- * http://www.geeksforgeeks.org/dynamic-programming-set-21-box-stacking-problem/ * http://people.cs.clemson.edu/~bcdean/dp_practice/ """ from collections import namedtuple from itertools import permutations dimension = namedtuple("Dimension", "height length width") def create_rotation(given_dimensions): """ A rotation is an order wherein length is greater than or equal to width. Having this constraint avoids the repetition of same order, but with width and length switched. For e.g (height=3, width=2, length=1) is same the same box for stacking as (height=3, width=1, length=2). :param given_dimensions: Original box dimensions :return: All the possible rotations of the boxes with the condition that length >= height. """ for current_dim in given_dimensions: for (height, length, width) in permutations((current_dim.height, current_dim.length, current_dim.width)): if length >= width: yield dimension(height, length, width) def sort_by_decreasing_area(rotations): return sorted(rotations, key=lambda dim: dim.length * dim.width, reverse=True) def can_stack(box1, box2): return box1.length < box2.length and box1.width < box2.width def box_stack_max_height(dimensions): boxes = sort_by_decreasing_area([rotation for rotation in create_rotation(dimensions)]) num_boxes = len(boxes) T = [rotation.height for rotation in boxes] R = [idx for idx in range(num_boxes)] for i in range(1, num_boxes): for j in range(0, i): if can_stack(boxes[i], boxes[j]): stacked_height = T[j] + boxes[i].height if stacked_height > T[i]: T[i] = stacked_height R[i] = j max_height = max(T) start_index = T.index(max_height) # Prints the dimensions which were stored in R list. while True: print boxes[start_index] next_index = R[start_index] if next_index == start_index: break start_index = next_index return max_height if __name__ == '__main__': d1 = dimension(3, 2, 5) d2 = dimension(1, 2, 4) assert 11 == box_stack_max_height([d1, d2]) ================================================ FILE: python/dynamic/breakword.py ================================================ """ Problem Statement ================= Given a string and a dictionary, split the string in to multiple words so that each word belongs to the dictionary. Video ----- * https://youtu.be/WepWFGxiwRs Analysis -------- * word_break_recursive: Exponential * word_break_dp : O(n^3) Solution -------- if input[i..j] belongs in a dictionary: DP[i][j] = True else: DP[i][j] = True if DP[i][k-1] and DP[k][j] for any k between i to j. Multiple different implementations are given below. """ def word_break_recursive(given_string, dictionary): """"Returns None if the given string cannot be broken into words, otherwise returns space separate words.""" given_string_length = len(given_string) if given_string_length == 0: return "" string = "" for i in range(given_string_length): string += given_string[i] if string in dictionary: r = word_break_recursive(given_string[i + 1:], dictionary) if r is not None: string += " " + r return string return None def word_break_dp(given_string, dictionary): """Returns None if the given string cannot be broken into words, otherwise returns space separated words.""" given_string_length = len(given_string) # -1 indicates the word cannot be split. DP = [[-1 for _ in range(given_string_length)] for _ in range(given_string_length)] for substring_length in range(1, given_string_length + 1): for start in range(0, given_string_length - substring_length + 1): end = start + substring_length - 1 substring = given_string[start: end + 1] if substring in dictionary: DP[start][end] = start continue for split in range(start + 1, end + 1): if DP[start][split - 1] != -1 and DP[split][end] != -1: DP[start][end] = split break if DP[0][-1] == -1: return None words = [] start_index = 0 end_index = given_string_length - 1 while start_index < given_string_length: split_index = DP[start_index][end_index] if start_index == split_index: words.append(given_string[start_index: end_index + 1]) break else: words.append(given_string[start_index: split_index]) start_index = split_index return " ".join(words) def is_word_break_possible(given_string, dictionary): """Returns if any word break is possible amongst the multiple word breaks in the sentence.""" DP = dict() max_word_length = len(max(dictionary, key=len)) return is_word_break_possible_recursive_helper(given_string, dictionary, 0, max_word_length, DP) def is_word_break_possible_recursive_helper(given_string, dictionary, start, max_word_length, DP): if start == len(given_string): return True if start in DP: return DP[start] for i in range(start, start + max_word_length): if i < len(given_string): new_word = given_string[start: i + 1] if new_word in dictionary: continue if is_word_break_possible_recursive_helper(given_string, dictionary, i + 1, max_word_length, DP): DP[start] = True return True DP[start] = False return False def all_possible_word_break_helper(given_string, dictionary, start, max_word_length, DP): """"Returns all possible word breaks in a given sentence.""" if start == len(given_string): return [""] if start in DP: return DP[start] words = [] for i in range(start, start + max_word_length): if i < len(given_string): new_word = given_string[start: i + 1] if new_word not in dictionary: continue sub_words = all_possible_word_break_helper(given_string, dictionary, i + 1, max_word_length, DP) for word in sub_words: extra_space = "" if len(word) == 0 else " " words.append(new_word + extra_space + word) DP[start] = words return words def all_possible_word_breaks(given_string, dictionary): DP = dict() max_word_length = len(max(dictionary, key=len)) return all_possible_word_break_helper(given_string, dictionary, 0, max_word_length, DP) if __name__ == '__main__': dictionary = {"joy", "likes", "to", "play"} given_string = "joylikestoplay" assert True == is_word_break_possible(given_string, dictionary) assert "joy likes to play " == word_break_recursive(given_string, dictionary) assert "joy likes to play" == word_break_dp(given_string, dictionary) dictionary = {"pea", "nut", "peanut", "butter"} given_string = "peanutbutter" assert ['pea nut butter', 'peanut butter'] == all_possible_word_breaks(given_string, dictionary) ================================================ FILE: python/dynamic/coin_change_num_ways.py ================================================ """ Problem Statement ================= Given a total and coins of certain denominations find number of ways total can be formed from coins assuming infinity supply of coins. Analysis -------- * Runtime : O(num_of_coins * total) Video ----- * https://youtu.be/_fgjrs570YE Reference --------- * http://www.geeksforgeeks.org/dynamic-programming-set-7-coin-change/ """ def coin_changing_num_ways(coins, total): cols = total + 1 # 1 for value 0 in total rows = len(coins) T = [[1 if col == 0 else 0 for col in range(cols)] for _ in range(rows)] for i in range(rows): for j in range(cols): if (i - 1) < 0: continue if j < coins[i]: T[i][j] = T[i - 1][j] else: T[i][j] = T[i - 1][j] + T[i][j - coins[i]] return T[rows - 1][cols - 1] def coin_changing_num_ways2(coins, total): cols = total + 1 num_coins = len(coins) # Using 1-D Array instead of 2-D Array. Approach is same as coin_changing_num_ways. T = [1 if col == 0 else 0 for col in range(cols)] for i in range(num_coins): for col in range(1, cols): if col >= coins[i]: T[col] += T[col - coins[i]] return T[cols - 1] def print_coin_changes_recursive(coins, total, results_stack, pos): if total == 0: for coin in results_stack: print "%d " % coin, print for idx in range(pos, len(coins)): if total >= coins[idx]: results_stack.append(coins[idx]) print_coin_changes_recursive(coins, total - coins[idx], results_stack, idx) results_stack.pop() # Remove last inserted coin from stack to use new coin with different index. def print_coin_changes(coins, total): print_coin_changes_recursive(coins, total, list(), 0) if __name__ == '__main__': coins = [1, 2, 3] total = 5 expected = 5 assert expected == coin_changing_num_ways(coins, total) assert expected == coin_changing_num_ways2(coins, total) print_coin_changes(coins, total) ================================================ FILE: python/dynamic/coinchangingmincoins.py ================================================ """ Problem Statement ================= Given coins of certain denominations with infinite supply find minimum number of coins it takes to form given total Video ----- * Topdown DP - https://youtu.be/Kf_M7RdHr1M * Bottom Up DP - https://youtu.be/Y0ZqKpToTic (Approach 1. 2D array.) * Bottom up DP - https://youtu.be/NJuKJ8sasGk (Same as Approach 1. Uses 1D array since 2D array is not required.) Analysis -------- * Time complexity - O(len(coins) * total) * Space complexity - O(len(coins) * total) """ def min_coins(coins, total): cols = total + 1 rows = len(coins) T = [[0 if col == 0 else float("inf") for col in range(cols)] for _ in range(rows)] for i in range(rows): for j in range(1, cols): if j < coins[i]: T[i][j] = T[i - 1][j] else: T[i][j] = min(T[i - 1][j], 1 + T[i][j - coins[i]]) return T[rows - 1][cols - 1] def print_coins(R, coins): start = len(R) - 1 if R[start] == -1: print "No Solution Possible." return print "Coins:", while start != 0: coin = coins[R[start]] print "%d " % coin, start = start - coin def min_coins2(coins, total): cols = total + 1 T =[0 if idx == 0 else float("inf") for idx in range(cols)] R = [-1 for _ in range(total + 1)] for j in range(len(coins)): for i in range(1, cols): coin = coins[j] if i >= coins[j]: if T[i] > 1 + T[i - coin]: T[i] = 1 + T[i - coin] R[i] = j print_coins(R, coins) return T[cols - 1] def min_coins_top_down(coins, total, memo): if total == 0: return 0 if total in memo: return memo[total] min_value = float("inf") for i in range(len(coins)): coin = coins[i] if coin > total: continue val = min_coins_top_down(coins, total - coin, memo) min_value = min(min_value, val) min_value += 1 memo[total] = min_value return min_value if __name__ == '__main__': coins = [1, 5, 6, 8] total = 11 expected = 2 assert expected == min_coins(coins, total) assert expected == min_coins2(coins, total) assert expected == min_coins_top_down(coins, total, dict()) ================================================ FILE: python/dynamic/count_num_A.py ================================================ """ Problem Statement ================= Imagine you have a special keyboard with the following keys: Key 1: Prints 'A' on screen Key 2: (Ctrl-A): Select screen Key 3: (Ctrl-C): Copy selection to buffer Key 4: (Ctrl-V): Print buffer on screen appending it after what has already been printed. If you can only press the keyboard for N times (with the above four keys), write a program to produce maximum numbers of A's. That is to say, the input parameter is N (No. of keys that you can press), the output is M (No. of As that you can produce). Complexity ---------- * Recursive Solution : Exponential > O(2^n) * Dynamic Programming: Quadratic O(n^2) Reference --------- * http://www.geeksforgeeks.org/how-to-print-maximum-number-of-a-using-given-four-keys/ """ def count_a_recursive(n_times): if n_times < 7: return n_times result = float("-inf") for sub_prob in range(n_times - 3, 0, -1): result = max(result, (n_times - sub_prob - 1) * count_a_recursive(sub_prob)) return result def count_a(n_times): if n_times < 7: return n_times T = [0 for _ in range(n_times + 1)] for num in range(7): T[num] = num for n in range(7, n_times + 1): for sub_prob in range(n - 3, 0, -1): T[n] = max(T[n], T[sub_prob] * (n - sub_prob - 1)) return T[n_times] if __name__ == '__main__': expected = 9 assert expected == count_a_recursive(7) assert expected == count_a(7) ================================================ FILE: python/dynamic/count_num_binary_without_consec_1.py ================================================ """ Problem Statement ================= Given a positive integer N, count all the numbers from 1 to 2^N, whose binary representation does not have consecutive 1s. This is a simple application of fibonacci series. Video ----- * https://www.youtube.com/watch?v=a9-NtLIs1Kk Complexity ---------- * Runtime Complexity: O(n) Reference --------- * http://www.geeksforgeeks.org/count-number-binary-strings-without-consecutive-1s/ """ def consec_one(num_n): f1 = f2 = 1 for _ in range(num_n): f1, f2 = f1 + f2, f1 return f1 if __name__ == '__main__': assert 13 == consec_one(5) ================================================ FILE: python/dynamic/cutting_rod.py ================================================ """ Problem Statement ================= Given a rod of length n inches and an array of prices that contains prices of all pieces of size smaller than n. Determine the maximum value obtainable by cutting up the rod and selling the pieces. Video ----- * https://youtu.be/IRwVmTmN6go Time Complexity --------------- 1. Recursive Solution = O(2^n) 2. Dynamic Programming Solution = O(n^2) Reference --------- http://www.geeksforgeeks.org/dynamic-programming-set-13-cutting-a-rod/ """ def max_profit_dp(prices, rod_length): rod_length_values = [0 for _ in range(rod_length + 1)] for length in range(1, rod_length + 1): max_value = float("-inf") for cut_length in range(1, length + 1): max_value = max(max_value, prices[cut_length - 1] + rod_length_values[length - cut_length]) rod_length_values[length] = max_value return rod_length_values[rod_length] def max_profit_recursive(prices, rod_length): if rod_length == 0: return 0 max_price = float('-inf') for length in range(1, rod_length + 1): max_price = max(max_price, prices[length - 1] + max_profit_recursive(prices, rod_length - length)) return max_price if __name__ == '__main__': prices = [3,5,8,9,10,20,22,25] rod_length = 8 expected_max_profit = 26 assert expected_max_profit == max_profit_recursive(prices, rod_length) assert expected_max_profit == max_profit_dp(prices, rod_length) ================================================ FILE: python/dynamic/dice_throw_ways.py ================================================ """ Problem Statement ================= Given n dice each with m faces, numbered from 1 to m, find the number of ways to get sum X. X is the summation of values on each face when all the dice are thrown. Complexity ---------- * Run time complexity: O(m * n * x) where m is number of faces, n is number of dice and x is given sum. References ---------- * http://www.geeksforgeeks.org/dice-throw-problem/ """ def num_ways(faces, dices, sumX): T = [[0 for _ in range(sumX + 1)] for _ in range(dices + 1)] # For a single dice for face_value in range(1, faces + 1): if face_value <= sumX: T[1][face_value] = 1 for dice in range(2, dices + 1): for partial_sum in range(1, sumX + 1): for face_value in range(1, faces + 1): if face_value < partial_sum: T[dice][partial_sum] += T[dice - 1][partial_sum - face_value] return T[dices][sumX] if __name__ == '__main__': assert 7 == num_ways(3, 3, 6) ================================================ FILE: python/dynamic/editdistance.py ================================================ """ Problem Statement ================= Given two strings str1 and str2, find the minimum number of edits (edit one character to another, delete char from str1 or delete char from str2) to change str1 to str2. Video ----- * https://youtu.be/We3YDTzNXEk Analysis -------- * DP Runtime : O(len(str1) * len(str2)) * Recursive Solution: Exponential (O(3^(m+n-1))) Reference --------- * https://www.clear.rice.edu/comp130/12spring/editdist/ """ def print_edits(T, str1, str2): i = len(T) - 1 j = len(T[0]) - 1 while True: if i == 0 or j == 0: break if str2[i - 1] == str1[j - 1]: i -= 1 j -= 1 elif T[i][j] == T[i - 1][j - 1] + 1: print "Edit %s in string1 to %s in string2." % (str1[j - 1], str2[i - 1]) i -= 1 j -= 1 elif T[i][j] == T[i - 1][j] + 1: print "Delete %s in string2." % str2[i - 1] i -= 1 elif T[i][j] == T[i][j - 1] + 1: print "Delete %s in string1." % str1[j - 1] j -= 1 def min_edit_distance(str1, str2): rows = len(str2) + 1 cols = len(str1) + 1 T = [[0 for _ in range(cols)] for _ in range(rows)] for j in range(cols): T[0][j] = j for i in range(rows): T[i][0] = i for i in range(1, rows): for j in range(1, cols): if str2[i - 1] == str1[j - 1]: T[i][j] = T[i - 1][j - 1] else: T[i][j] = 1 + min(T[i - 1][j - 1], T[i - 1][j], T[i][j - 1]) print_edits(T, str1, str2) return T[rows - 1][cols - 1] def min_edit_distance_recursive(str1, str2): i = len(str1) j = len(str2) if i == 0: return j if j == 0: return i return min(min_edit_distance_recursive(str1[:i - 1], str2) + 1, min_edit_distance_recursive(str1, str2[:j - 1]) + 1, min_edit_distance_recursive(str1[:i - 1], str2[:j - 1]) + (1 if str1[i - 1] != str2[j - 1] else 0)) if __name__ == '__main__': str1 = "azced" str2 = "abcdef" expected = 3 assert expected == min_edit_distance(str1, str2) assert expected == min_edit_distance(str2, str1) assert expected == min_edit_distance_recursive(str1, str2) ================================================ FILE: python/dynamic/egg_drop.py ================================================ """ Problem Statement ================= Given a certain number of eggs and a certain number of floors, determine the minimum number of attempts required to find the egg breaking floor. Analysis -------- * Dynamic Programming Time Complexity: O(eggs * num_floors^2) * Recursive Solution: Exponential Video ----- * https://youtu.be/3hcaVyX00_4 Reference --------- * http://www.geeksforgeeks.org/dynamic-programming-set-11-egg-dropping-puzzle/ """ def min_attempts_egg_drop(eggs, floors): num_eggs = eggs + 1 num_floors = floors + 1 T = [[floor if egg == 1 else 0 for floor in range(num_floors)] for egg in range(num_eggs)] for egg in range(2, num_eggs): for floor in range(1, num_floors): T[egg][floor] = min(1 + max(T[egg - 1][k - 1], T[egg][floor - k]) for k in range(1, floor + 1)) return T[num_eggs - 1][num_floors - 1] def min_attempts_egg_drop_recursive(eggs, floors): if eggs == 1 or floors == 0: return floors min_value = float("inf") for floor in range(1, floors + 1): min_value = min(min_value, 1 + max(min_attempts_egg_drop_recursive(eggs - 1, floor - 1), min_attempts_egg_drop_recursive(eggs, floors - floor))) return min_value if __name__ == '__main__': eggs = 3 floors = 100 expected_attempts = 9 assert expected_attempts == min_attempts_egg_drop(eggs, floors) eggs = 2 floors = 6 expected_attempts = 3 assert expected_attempts == min_attempts_egg_drop_recursive(eggs, floors) ================================================ FILE: python/dynamic/knapsack_01.py ================================================ """ Problem Statement ================= 0/1 Knapsack Problem - Given items of certain weights/values and maximum allowed weight how to pick items to pick items from this set to maximize sum of value of items such that sum of weights is less than or equal to maximum allowed weight. Runtime Analysis ---------------- Time complexity - O(W*total items) Video ----- * Topdown DP - https://youtu.be/149WSzQ4E1g * Bottomup DP - https://youtu.be/8LusJS5-AGo References ---------- * http://www.geeksforgeeks.org/dynamic-programming-set-10-0-1-knapsack-problem/ * https://en.wikipedia.org/wiki/Knapsack_problem """ def knapsack_01(values, weights, total): total_items = len(weights) rows = total_items + 1 cols = total + 1 T = [[0 for _ in range(cols)] for _ in range(rows)] for i in range(1, rows): for j in range(1, cols): if j < weights[i - 1]: T[i][j] = T[i - 1][j] else: T[i][j] = max(T[i - 1][j], values[i - 1] + T[i - 1][j - weights[i - 1]]) return T[rows - 1][cols -1] def knapsack_01_recursive_util(values, weights, remaining_weight, total_items, current_item, memo): if current_item >= total_items or remaining_weight <= 0: return 0 key = (total_items - current_item - 1, remaining_weight) if key in memo: return memo[key] if remaining_weight < weights[current_item]: max_value = knapsack_01_recursive_util(values, weights, remaining_weight, total_items, current_item + 1, memo) else: max_value = max(values[current_item] + knapsack_01_recursive_util(values, weights, remaining_weight - weights[current_item], total_items, current_item + 1, memo), knapsack_01_recursive_util(values, weights, remaining_weight, total_items, current_item + 1, memo)) memo[key] = max_value return max_value def knapsack_01_recursive(values, weights, total_weight): memo = dict() return knapsack_01_recursive_util(values, weights, total_weight, len(values), 0, memo) if __name__ == '__main__': total_weight = 7 weights = [1, 3, 4, 5] values = [1, 4, 5, 7] expected = 9 assert expected == knapsack_01(values, weights, total_weight) assert expected == knapsack_01_recursive(values, weights, total_weight) total_weight = 8 weights = [2, 2, 4, 5] values = [2, 4, 6, 9] expected = 13 assert expected == knapsack_01(values, weights, total_weight) assert expected == knapsack_01_recursive(values, weights, total_weight) ================================================ FILE: python/dynamic/kth_ugly_number.py ================================================ """ Problem Statement ================= Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, shows the first 11 ugly numbers. By convention, 1 is included. Write a program to find the kth ugly number. Complexity ---------- * Time Complexity O(n) * Space Complexity O(n) Reference --------- * http://www.geeksforgeeks.org/ugly-numbers/ """ def ugly_number(kth): ugly_factors = [1] # By convention 1 is included. factor_index = { 2: 0, 3: 0, 5: 0} for num in range(1, kth): minimal_factor = min(min(ugly_factors[factor_index[2]] * 2, ugly_factors[factor_index[3]] * 3), ugly_factors[factor_index[5]] * 5) ugly_factors.append(minimal_factor) for factor in [2, 3, 5]: if minimal_factor % factor == 0: factor_index[factor] += 1 return ugly_factors[kth - 1] if __name__ == '__main__': assert 5832 == ugly_number(150) ================================================ FILE: python/dynamic/longest_common_subsequence.py ================================================ """ Problem Statement ================= Given two sequences A = [A1, A2, A3,..., An] and B = [B1, B2, B3,..., Bm], find the length of the longest common subsequence. Video ----- * https://youtu.be/NnD96abizww Complexity ---------- * Recursive Solution: O(2^n) (or O(2^m) whichever of n and m is larger). * Dynamic Programming Solution: O(n * m) Reference --------- * https://en.wikipedia.org/wiki/Longest_common_subsequence_problem * http://www.geeksforgeeks.org/dynamic-programming-set-4-longest-common-subsequence/ """ def lcs_recursive_helper(sequence1, sequence2, index1, index2): if (index1 == len(sequence1)) or (index2 == len(sequence2)): return 0 if sequence1[index1] == sequence2[index2]: return 1 + lcs_recursive_helper(sequence1, sequence2, index1 + 1, index2 + 1) return max(lcs_recursive_helper(sequence1, sequence2, index1 + 1, index2), lcs_recursive_helper(sequence1, sequence2, index1, index2 + 1)) def longest_common_subsequence_recursive(sequence1, sequence2): return lcs_recursive_helper(sequence1, sequence2, 0, 0) def longest_common_subsequence(sequence1, sequence2): cols = len(sequence1) + 1 # Add 1 to represent 0 valued column for DP rows = len(sequence2) + 1 # Add 1 to represent 0 valued row for DP T = [[0 for _ in range(cols)] for _ in range(rows)] max_length = 0 for i in range(1, rows): for j in range(1, cols): if sequence2[i - 1] == sequence1[j - 1]: T[i][j] = 1 + T[i - 1][j - 1] else: T[i][j] = max(T[i - 1][j], T[i][j - 1]) max_length = max(max_length, T[i][j]) return max_length if __name__ == '__main__': sequence1 = "ABCDGHLQR" sequence2 = "AEDPHR" expected_length = 4 assert expected_length == longest_common_subsequence_recursive(sequence1, sequence2) assert expected_length == longest_common_subsequence_recursive(sequence2, sequence1) assert expected_length == longest_common_subsequence(sequence1, sequence2) assert expected_length == longest_common_subsequence(sequence2, sequence1) ================================================ FILE: python/dynamic/longest_common_substring.py ================================================ """ Problem Statement ================= Given two sequences A = [A1, A2, A3,..., An] and B = [B1, B2, B3,..., Bm], find the length of the longest common substring. Video ----- * https://youtu.be/BysNXJHzCEs Complexity ---------- * Recursive Solution: O(2^n) (or O(2^m) whichever of n and m is larger). * Dynamic Programming Solution: O(n * m) Reference --------- * http://en.wikipedia.org/wiki/Longest_common_substring_problem """ def longest_common_string_recursive_helper(str1, str2, pos1, pos2, check_equal): if pos1 == -1 or pos2 == -1: return 0 if check_equal: if str1[pos1] == str2[pos2]: return 1 + longest_common_string_recursive_helper(str1, str2, pos1 - 1, pos2 - 1, True) else: return 0 longest = 0 # start (again) to find the longest from the current positions if str1[pos1] == str2[pos2]: longest = 1 + longest_common_string_recursive_helper(str1, str2, pos1 - 1, pos2 - 1, True) return max(longest, longest_common_string_recursive_helper(str1, str2, pos1, pos2 - 1, False), longest_common_string_recursive_helper(str1, str2, pos1 - 1, pos2, False)) def longest_common_substring_recursive(str1, str2): return longest_common_string_recursive_helper(str1, str2, len(str1) - 1, len(str2) - 1, False) def longest_common_substring(str1, str2): cols = len(str1) + 1 # Add 1 to represent 0 valued col for DP rows = len(str2) + 1 # Add 1 to represent 0 valued row for DP T = [[0 for _ in range(cols)] for _ in range(rows)] max_length = 0 for i in range(1, rows): for j in range(1, cols): if str2[i - 1] == str1[j - 1]: T[i][j] = T[i - 1][j - 1] + 1 max_length = max(max_length, T[i][j]) return max_length if __name__ == '__main__': str1 = "abcdef" str2 = "zcdemf" expected = 3 assert expected == longest_common_substring(str1, str2) assert expected == longest_common_substring_recursive(str1, str2) str1 = "abcdef" str2 = "cde" expected = 3 assert expected == longest_common_substring(str1, str2) str1 = "cde" str2 = "zcdemf" expected = 3 assert expected == longest_common_substring(str1, str2) ================================================ FILE: python/dynamic/longest_increasing_subsequence.py ================================================ """ Problem Statement ================= Find a subsequence in given array in which the subsequence's elements are in sorted order, lowest to highest, and in which the subsequence is as long as possible. Video ----- * https://youtu.be/CE2b_-XfVDk Solution -------- Dynamic Programming is used to solve this question. DP equation is.:: if(arr[i] > arr[j]) { T[i] = max(T[i], T[j] + 1) } * Time complexity is O(n^2). * Space complexity is O(n) Reference --------- * http://en.wikipedia.org/wiki/Longest_increasing_subsequence * http://www.geeksforgeeks.org/dynamic-programming-set-3-longest-increasing-subsequence/ """ def longest_increasing_subsequence(sequence): sequence_length = len(sequence) T = [1 for _ in range(sequence_length)] solution_indices = [i for i in range(sequence_length)] for index_i in range(1, sequence_length): for index_j in range(0, index_i): if (sequence[index_i] > sequence[index_j]) and (T[index_i] < T[index_j] + 1): T[index_i] = T[index_j] + 1 solution_indices[index_i] = index_j # find the index of the max number in T max_value = max(T) max_index = T.index(max_value) # Print solution using linked values in solution_indices next_index = max_index while True: print sequence[next_index], old_index = next_index next_index = solution_indices[next_index] if next_index == old_index: break return T[max_index] def longest_increasing_subsequence_recursive(sequence): sequence_length = len(sequence) longest = 0 for index in range(sequence_length - 1): longest_so_far = longest_subsequence_recursive_helper(sequence, index + 1, sequence[index]) if longest_so_far > longest: longest = longest_so_far return longest + 1 def longest_subsequence_recursive_helper(sequence, next_position, current_position_value): if next_position == len(sequence): return 0 temp1 = 0 if sequence[next_position] > current_position_value: temp1 = 1 + longest_subsequence_recursive_helper(sequence, next_position + 1, sequence[next_position]) temp2 = longest_subsequence_recursive_helper(sequence, next_position + 1, current_position_value) return max(temp1, temp2) if __name__ == '__main__': sequence = [23, 10, 22, 5, 33, 8, 9, 21, 50, 41, 60, 80, 99, 22, 23, 24, 25, 26, 27] assert 10 == longest_increasing_subsequence(sequence) assert 10 == longest_increasing_subsequence_recursive(sequence) ================================================ FILE: python/dynamic/longest_palindromic_subsequence.py ================================================ """ Problem Statement ================= Given a string find longest palindromic subsequence in this string. Complexity ---------- * Dynamic Programming Time Complexity: O(n^2) * Recursive Solution Time Complexity: O(2^n) Video ----- * https://youtu.be/_nCsPn7_OgI References ---------- * http://www.geeksforgeeks.org/dynamic-programming-set-12-longest-palindromic-subsequence/ """ def longest_palindromic_subsequence(given_string): rows = cols = string_length = len(given_string) T = [[0 for _ in range(cols)] for _ in range(rows)] for row in range(rows): T[row][row] = 1 for substring_length in range(2, string_length + 1): for row in range(0, string_length - substring_length + 1): col = row + substring_length - 1 if given_string[row] == given_string[col]: if string_length == 2: T[row][col] = 2 else: T[row][col] = 2 + T[row + 1][col - 1] else: T[row][col] = max(T[row + 1][col], T[row][col - 1]) return T[0][-1] def palindromic_subsequence_recursive_helper(given_string, start_index, length): if length == 0 or length == 1: return length if given_string[start_index] == given_string[length - start_index - 1]: return 2 + palindromic_subsequence_recursive_helper(given_string, start_index + 1, length - 2) else: return max(palindromic_subsequence_recursive_helper(given_string, start_index, length - 1), palindromic_subsequence_recursive_helper(given_string, start_index + 1, length - 1)) def longest_palindromic_subsequence_recursive(given_string): return palindromic_subsequence_recursive_helper(given_string, 0, len(given_string)) if __name__ == '__main__': given_string = "agbdba" expected_result = 5 assert expected_result == longest_palindromic_subsequence(given_string) assert expected_result == longest_palindromic_subsequence_recursive(given_string) ================================================ FILE: python/dynamic/matrix_chain_order.py ================================================ """ Problem Statement ================= Given an array p[] which represents the chain of matrices such that the ith matrix Ai is of dimension p[i-1] x p[i]. We need to write a function matrix_chain_order() that should return the minimum number of multiplications needed to multiply the chain. Video ----- * https://youtu.be/vgLJZMUfnsU Note ---- In the code below we give matrices length as an array and each matrix takes 2 indices from the array. For e.g. {2, 3, 4} represents two matrices (2, 3) and (3, 4) in (row, col) format. Complexity ---------- Time Complexity: O(n^3) Reference --------- * http://www.geeksforgeeks.org/dynamic-programming-set-8-matrix-chain-multiplication/ """ def matrix_chain_order(matrices): matrices_length = len(matrices) T = [[0 for _ in range(matrices_length)] for _ in range(matrices_length)] for gap in range(2, matrices_length): for index_i in range(0, matrices_length - gap): index_j = index_i + gap T[index_i][index_j] = 10000 for index_k in range(index_i + 1, index_j): temp = T[index_i][index_k] + T[index_k][index_j] + matrices[index_i] * matrices[index_k] * matrices[index_j] if temp < T[index_i][index_j]: T[index_i][index_j] = temp return T[0][-1] if __name__ == '__main__': matrices = [4, 2, 3, 5, 3] assert 84 == matrix_chain_order(matrices) ================================================ FILE: python/dynamic/maximum_increasing_subsequence.py ================================================ """ Problem Statement ================= Given an array of n positive integers. Write a program to find the sum of maximum sum subsequence of the given array such that the integers in the subsequence are in increasing order. Complexity ---------- * Time Complexity: O(n^2) * Space Complexity: O(n) Video ----- * https://youtu.be/99ssGWhLPUE Reference --------- * http://www.geeksforgeeks.org/dynamic-programming-set-14-maximum-sum-increasing-subsequence/ """ def maximum_sum_subsequence(sequence): sequence_length = len(sequence) T = [sequence[i] for i in range(sequence_length)] for index_i in range(1, sequence_length): for index_j in range(0, index_i): if sequence[index_j] < sequence[index_i]: T[index_i] = max(T[index_i], T[index_j] + sequence[index_i]) return max(T) if __name__ == '__main__': sequence = [1, 101, 10, 2, 3, 100, 4] assert 111 == maximum_sum_subsequence(sequence) ================================================ FILE: python/dynamic/nth_fibonacci.py ================================================ """ Problem Statement ================= Given the number n, find the nth fibanacci number. The fibonacci series is 0, 1, 1, 2, 3 ... And follows the formula Fn = Fn-1 + Fn-2 Complexity ---------- * Recursive Solution: O(2^n) * Dynamic Programming: O(n) """ def fibonacci_recursive(n): if n == 0 or n == 1: return n return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2) def fibonacci(n): n1, n2 = 0, 1 if n == n1 or n == n2: return n for i in range(2, n + 1): n1, n2 = n2, n1 + n2 return n2 if __name__ == '__main__': assert 610 == fibonacci_recursive(15) assert 610 == fibonacci(15) ================================================ FILE: python/dynamic/num_bst.py ================================================ """ Problem Statement ================= Count number of binary search trees created for array of size n. The solution is the nth catalan number. Complexity ---------- * Dynamic Programming: O(n^2) * Recursive Solution: O(2^n) Video ----- * https://youtu.be/YDf982Lb84o Reference --------- * http://www.geeksforgeeks.org/program-nth-catalan-number/ """ def num_bst(num_nodes): T = [0 for _ in range(num_nodes + 1)] T[0] = 1 T[1] = 1 for node in range(2, num_nodes+1): for sub in range(0, node): T[node] += T[sub] * T[node - sub - 1] return T[num_nodes] def num_bst_recursive(num_nodes): if num_nodes == 0 or num_nodes == 1: return 1 result = 0 for root in range(1, num_nodes + 1): result += num_bst_recursive(root - 1) * num_bst_recursive(num_nodes - root) return result if __name__ == '__main__': assert 5 == num_bst(3) assert 5 == num_bst_recursive(3) ================================================ FILE: python/dynamic/num_paths_nm_matrix.py ================================================ """ Problem Statement ================= Count the number of Paths from 1,1 to N,M in an NxM matrix. Analysis -------- * Dynamic Programing Solution: O(rows * cols) * Recursive: O(2^rows) if rows > cols else O(2^cols) References ---------- * http://www.geeksforgeeks.org/count-possible-paths-top-left-bottom-right-nxm-matrix/ """ def num_paths_matrix(rows, cols): T = [[1 if row == 0 or col == 0 else 0 for row in range(cols)] for col in range(rows)] for row in range(1, rows): for col in range(1, cols): T[row][col] = T[row - 1][col] + T[row][col - 1] return T[rows - 1][cols - 1] def num_paths_matrix_recursive(rows, cols): if rows == 1 or cols == 1: return 1 return num_paths_matrix(rows-1, cols) + num_paths_matrix(rows, cols - 1) if __name__ == '__main__': rows = 3 cols = 3 expected = 6 assert expected == num_paths_matrix(rows, cols) assert expected == num_paths_matrix_recursive(rows, cols) ================================================ FILE: python/dynamic/num_trees_preorder.py ================================================ """ Problem Statement ================= Given the number of nodes N, in a pre-order sequence how many unique trees can be created? Number of tree is exactly same as number of unique BST create with array of size n. The solution is a catalan number. Complexity ---------- * Dynamic Programming: O(n^2) * Recursive Solution: O(2^n) Video ----- * https://youtu.be/RUB5ZPfKcnY """ def num_trees(num_nodes): T = [0 for _ in range(num_nodes + 1)] T[0] = 1 T[1] = 1 for n in range(2, num_nodes + 1): for j in range(0, n): T[n] += T[j] * T[n - j - 1] return T[num_nodes] def num_trees_recursive(num_nodes): if num_nodes == 0 or num_nodes == 1: return 1 result = 0 for n in range(1, num_nodes + 1): result += num_trees_recursive(n - 1) * num_trees_recursive(num_nodes - n) return result if __name__ == '__main__': assert 5 == num_trees(3) assert 14 == num_trees(4) assert 42 == num_trees(5) assert 5 == num_trees_recursive(3) assert 14 == num_trees_recursive(4) assert 42 == num_trees_recursive(5) ================================================ FILE: python/dynamic/optimal_bst.py ================================================ """ Problem Statement ================= Given a sorted array keys[0.. n-1] of search keys and an array freq[0.. n-1] of frequency counts, where freq[i] is the number of searches to keys[i]. Construct a binary search tree of all keys such that the total cost of all the searches is as small as possible. Video ----- * https://youtu.be/hgA4xxlVvfQ Analysis -------- * Recursive: Exponential O(n^n) * Dynamic Programming: O(n^3) Reference --------- * http://www.geeksforgeeks.org/dynamic-programming-set-24-optimal-binary-search-tree/ """ def min_cost_bst(input_array, freq): size = rows = cols = len(input_array) T = [[0 for _ in range(cols)] for _ in range(rows)] for idx in range(rows): T[idx][idx] = freq[idx] for sub_tree_size in range(2, size + 1): for start in range(size + 1 - sub_tree_size): end = start + sub_tree_size - 1 T[start][end] = float("inf") total = sum(freq[start:end + 1]) for k in range(start, end + 1): val = total + (0 if k - 1 < 0 else T[start][k - 1]) + (0 if k + 1 > end else T[k + 1][end]) T[start][end] = min(val, T[start][end]) return T[0][-1] def min_cost_bst_recursive_helper(input_array, freq, low_index, high_index, level): if low_index > high_index: return 0 min_value = float("inf") for index in range(low_index, high_index + 1): val = (min_cost_bst_recursive_helper(input_array, freq, low_index, index - 1, level + 1) # left tree + level * freq[index] # value at level + min_cost_bst_recursive_helper(input_array, freq, index + 1, high_index, level + 1)) # right tree min_value = min(val, min_value) return min_value def min_cost_bst_recursive(input_array, freq): return min_cost_bst_recursive_helper(input_array, freq, 0, len(input_array) - 1, 1) if __name__ == '__main__': input_array = [10, 12, 16, 21] freq = [4, 2, 6, 3] expected = 26 assert expected == min_cost_bst(input_array, freq) assert expected == min_cost_bst_recursive(input_array, freq) input_array = [10, 12, 20, 35, 46] freq = [34, 8, 50, 21, 16] expected = 232 assert expected == min_cost_bst(input_array, freq) assert expected == min_cost_bst_recursive(input_array, freq) ================================================ FILE: python/dynamic/stockbuysellktransactions.py ================================================ """" Problem Statement ================= Given certain stock values over a period of days (d days) and a number K, the number of transactions allowed, find the maximum profit that be obtained with at most K transactions. Video ----- * https://youtu.be/oDhu5uGq_ic Complexity ---------- * Space Complexity O(days * transctions) * Time Complexity: Slow Solution O (days^2 * transactions), Faster Solution O(days * transaction) """ def max_profit(prices, K): if K == 0 or prices == []: return 0 days = len(prices) num_transactions = K + 1 # 0th transaction up to and including kth transaction is considered. T = [[0 for _ in range(days)] for _ in range(num_transactions)] for transaction in range(1, num_transactions): max_diff = - prices[0] for day in range(1, days): T[transaction][day] = max(T[transaction][day - 1], # No transaction prices[day] + max_diff) # price on that day with max diff max_diff = max(max_diff, T[transaction - 1][day] - prices[day]) # update max_diff print_actual_solution(T, prices) return T[-1][-1] def max_profit_slow_solution(prices, K): if K == 0 or prices == []: return 0 days = len(prices) num_transactions = K + 1 T = [[0 for _ in range(len(prices))] for _ in range(num_transactions)] for transaction in range(1, num_transactions): for day in range(1, days): # This maximum value of either # a) No Transaction on the day. We pick the value from day - 1 # b) Max profit made by selling on the day plus the cost of the previous transaction, considered over m days T[transaction][day] = max(T[transaction][day - 1], max([(prices[day] - prices[m] + T[transaction - 1][m]) for m in range(day)])) print_actual_solution(T, prices) return T[-1][-1] def print_actual_solution(T, prices): transaction = len(T) - 1 day = len(T[0]) - 1 stack = [] while True: if transaction == 0 or day == 0: break if T[transaction][day] == T[transaction][day - 1]: # Didn't sell day -= 1 else: stack.append(day) # sold max_diff = T[transaction][day] - prices[day] for k in range(day - 1, -1, -1): if T[transaction - 1][k] - prices[k] == max_diff: stack.append(k) # bought transaction -= 1 break for entry in range(len(stack) - 1, -1, -2): print("Buy on day {day} at price {price}".format(day=stack[entry], price=prices[stack[transaction]])) print("Sell on day {day} at price {price}".format(day=stack[entry], price=prices[stack[transaction - 1]])) if __name__ == '__main__': prices = [2, 5, 7, 1, 4, 3, 1, 3] assert 10 == max_profit(prices, 3) assert 10 == max_profit_slow_solution(prices, 3) ================================================ FILE: python/dynamic/string_interleaving.py ================================================ """ Problem Statement ================= Given three strings A, B and C. Write a function that checks whether C is an interleaving of A and B. C is said to be interleaving A and B, if it contains all characters of A and B and order of all characters in individual strings is preserved. http://www.geeksforgeeks.org/check-whether-a-given-string-is-an-interleaving-of-two-other-given-strings-set-2/ Video: https://www.youtube.com/watch?v=ih2OZ9-M3OM """ def is_interleaved_recursive(str1, str2, str3, pos1, pos2, pos3): if pos1 == len(str1) and pos2 == len(str2) and pos3 == len(str3): return True if pos3 == len(str3): return False return (((pos1 < len(str1) and str1[pos1] == str3[pos3]) and is_interleaved_recursive(str1, str2, str3, pos1 + 1, pos2, pos3 + 1)) or (pos2 < len(str2) and str2[pos2] == str3[pos3]) and is_interleaved_recursive(str1, str2, str3, pos1, pos2 + 1, pos3 + 1)) def is_interleaved(str1, str2, str3): if len(str3) != (len(str1) + len(str2)): return False cols = len(str1) + 1 rows = len(str2) + 1 T = [[False for _ in range(cols)] for _ in range(rows)] for row in range(rows): for col in range(cols): index = row + col - 1 if row == 0 and col == 0: T[row][col] = True elif row == 0: if str3[index] == str1[col - 1]: T[row][col] = True and T[row][col - 1] elif col == 0: if str3[index] == str2[row - 1]: T[row][col] = True and T[row - 1][col] else: T[row][col] = ((T[row][col - 1] if str3[index] == str1[col - 1] else False) or (T[row - 1][col] if str3[index] == str2[row - 1] else False)) return T[rows - 1][cols - 1] if __name__ == '__main__': str1 = "XXYM" str2 = "XXZT" str3 = "XXXZXYTM" assert True == is_interleaved(str1, str2, str3) assert True == is_interleaved_recursive(str1, str2, str3, 0, 0, 0) ================================================ FILE: python/dynamic/sub_rectangular_maximum_sum.py ================================================ """ Problem Statement ================= Write a program to find maximum sum rectangle in give 2D matrix. Assume there is at least one positive number in the 2D matrix. Solution: -------- * Keep temp array with size as number of rows. Start left and right from 0 and keep adding values for each row and maintain them in this temp array. * Run Kadane's algorithm to find max sum subarray in temp. Now increment right by 1. * When right reaches last column reset right to 1 and left to 1. Analysis -------- * Space complexity of this algorithm is O(row) * Time complexity of this algorithm is O(row*col*col) Video ----- * https://youtu.be/yCQN096CwWM References ---------- * http://www.geeksforgeeks.org/dynamic-programming-set-27-max-sum-rectangle-in-a-2d-matrix/ """ from collections import namedtuple Result = namedtuple("Result","maxSum leftBound rightBound upBound lowBound") KadanesResult = namedtuple("KadanesResult","maxSum start end") def kadanes(temp): max = 0 maxStart = -1 maxEnd = -1 currentStart = 0 maxSoFar = 0 for i in range(0, len(temp)): maxSoFar += temp[i] if maxSoFar < 0: maxSoFar = 0 currentStart = i + 1 if maxSoFar > max: maxStart = currentStart maxEnd = i max = maxSoFar return KadanesResult(max, maxStart, maxEnd) def max_sub_sub_rectangle(rectangle): rows = len(rectangle) cols = len(rectangle[0]) result = Result(float("-inf"), -1, -1, -1, -1) for left in range(cols): temp = [0 for _ in range(rows)] for right in range(left, cols): for i in range(rows): temp[i] += rectangle[i][right] kadanes_result = kadanes(temp) if kadanes_result.maxSum > result.maxSum: result = Result(kadanes_result.maxSum, left, right, kadanes_result.start, kadanes_result.end) return result if __name__ == '__main__': rectangle = [[2, 1, -3, -4, 5], [0, 6, 3, 4, 1], [2, -2, -1, 4, -5], [-3, 3, 1, 0, 3]] result = max_sub_sub_rectangle(rectangle) assert 18 == result.maxSum print result ================================================ FILE: python/dynamic/subset_sum.py ================================================ """ Problem Statement ================= Given an array of non negative numbers and a total, is there subset of numbers in this array which adds up to given total. Another variation is given an array is it possible to split it up into 2 equal sum partitions. Partition need not be equal sized. Just equal sum. Video ----- * https://youtu.be/s6FhG--P7z0 Solution -------- * Time complexity is O(input.size * total_sum) * Space complexity is O(input.size*total_sum) Reference --------- * https://en.wikipedia.org/wiki/Subset_sum_problem """ def subset_sum(sequence, sum_value): cols = sum_value + 1 # Plus 1 for 0 valued col. rows = len(sequence) + 1 # Plus 1 for 0 valued row. T = [[False for _ in range(cols)] for _ in range(rows)] for row in range(rows): T[row][0] = True for index_i in range(1, rows): for index_j in range(1, cols): if index_j >= sequence[index_i - 1]: T[index_i][index_j] = T[index_i - 1][index_j] or T[index_i - 1][index_j - sequence[index_i - 1]] else: T[index_i][index_j] = T[index_i - 1][index_j] return T[rows - 1][cols - 1] def partition(sequence): sequence_sum = sum(sequence) if sequence_sum % 2 != 0: return False expected = sequence_sum / 2 return subset_sum(sequence, expected) if __name__ == '__main__': sequence = [2, 3, 7, 8] assert True == subset_sum(sequence, 11) sequence = [1, 3, 5, 5, 2, 1, 1, 6] assert True == partition(sequence) ================================================ FILE: python/dynamic/symbolexpressionevaluation.py ================================================ """ Problem Statement ================= Let there be a binary operation for 3 symbols a, b, c and result of these binary operation given in a table. Given an expression of these 3 symbols and a final result, tell if this expression can be parenthesize in certain way to produce the final result. Complexity ---------- * Run time Complexity: O(n^3) * SpaceL O(n^2) Where n is the length of the expression. """ def evaluate_expression(expression_map, expression, result): expression_length = len(expression) T = [[set() for _ in range(expression_length)] for _ in range(len(expression))] for idx, expr in enumerate(expression): T[idx][idx].add(expr) # We take a sub expression of length 2 until the total expression length for sub_length in range(2, expression_length + 1): for left_index in range(0, expression_length - sub_length + 1): right_index = left_index + sub_length - 1 # we split the expression at different k indices for the total sub-expression length and store the result. # at T[left_index][right_index] # Like bbc, will be treated for (b(bc) and ((bb) c) and the final result is stored in a set at T[0][2] for k in range(left_index, right_index): for expr1 in T[left_index][k]: for expr2 in T[k+1][right_index]: T[left_index][right_index].add(expression_map[(expr1, expr2)]) for expr in T[0][-1]: if result in expr: return True return False if __name__ == '__main__': expressions = ['a', 'b', 'c'] # expression table denotes the binary operation between two expression and its result. expression_table = [ ['b', 'b', 'a'], ['c', 'b', 'a'], ['a', 'a', 'c'] ] # For convenience, we can modify it to be more explicit and use the expression table expression_map = { ('a', 'a'): 'b', ('a', 'b'): 'b', ('a', 'c'): 'a', ('b', 'a'): 'c', ('b', 'b'): 'b', ('b', 'c'): 'a', ('c', 'a'): 'a', ('c', 'b'): 'a', ('c', 'c'): 'c' } assert True == evaluate_expression(expression_map, 'bbbbac', 'a') ================================================ FILE: python/dynamic/weighted_job_scheduling_max_profit.py ================================================ """ Problem Statement ================= Given set of jobs with start and end interval and profit, how to maximize profit such that jobs in subset do not overlap. Video ----- * https://youtu.be/cr6Ip0J9izc Complexity ---------- * Runtime Complexity: O(n^2) * Space Complexity: O(n) Reference Link -------------- * http://www.cs.princeton.edu/courses/archive/spr05/cos423/lectures/06dynamic-programming.pdf """ def can_sequence(job1, job2): _, job1_finish_time = job1 job2_start_time, _ = job2 return job1_finish_time <= job2_start_time def find_max_profit(jobs): sequenced_jobs = sorted(jobs.keys(), key=lambda x: x[1]) T = [jobs[job_key] for job_key in sequenced_jobs] num_jobs = len(sequenced_jobs) for j in range(1, num_jobs): for i in range(0, j): if can_sequence(sequenced_jobs[i], sequenced_jobs[j]): T[j] = max(T[j], T[i] + jobs[sequenced_jobs[j]]) return max(T) if __name__ == '__main__': jobs = { (1, 3): 5, # (start_time, end_time, total_cost) (2, 5): 6, (4, 6): 5, (6, 7): 4, (5, 8): 11, (7, 9): 2 } assert 17 == find_max_profit(jobs) ================================================ FILE: python/geometry/skylinedrawing.py ================================================ # https://leetcode.com/problems/the-skyline-problem/ class BuildingPoint(object): def __init__(self, point, is_start, height): self.point = point; self.is_start = is_start self.height = height def __lt__(self, other): if self.point != other.point: return self.point < other.point else: if self.is_start: h1 = -self.height else: h1 = self.height if other.is_start: h2 = -other.height; else: h2 = other.height return h1 < h2 def get_skyline(buildings): building_points = [] for building in buildings: building_points.append(BuildingPoint(building[0], True, building[2])) building_points.append(BuildingPoint(building[1], False, building[2])) building_points = sorted(building_points) queue = {} queue[0] = 1 prev_max_height = 0 result = [] for building_point in building_points: if building_point.is_start: if building_point.height in queue: queue[building_point.height] = queue[building_point.height] + 1 else: queue[building_point.height] = 1 else: if queue[building_point.height] == 1: del queue[building_point.height] else: queue[building_point.height] = queue[building_point.height] - 1 current_max_height = max(queue.keys()) if prev_max_height != current_max_height: result.append([building_point.point, current_max_height]) prev_max_height = current_max_height return result if __name__ == '__main__': buildings = [[1, 3, 4], [3, 4, 4], [2, 6, 2], [8, 11, 4], [7, 9, 3], [10, 11, 2]] print(get_skyline(buildings)) ================================================ FILE: python/graph/cycledirectedgraph.py ================================================ # detect cycle in directed graph # https://github.com/mission-peace/interview/blob/master/src/com/interview/graph/CycleInDirectedGraph.java from graph import * def has_cycle(graph): white = set() gray = set() black = set() for vertex in graph.all_vertex.values(): white.add(vertex) while len(white) > 0: current = next(iter(white)) if dfs(current, white, gray, black) == True: return True return False def dfs(current, white, gray, black): move_vertex(current, white, gray) for neighbor in current.adjacent_vertices: if neighbor in black: continue if neighbor in gray: return True if dfs(neighbor, white, gray, black) == True: return True move_vertex(current, gray, black) return False def move_vertex(vertex, source_set, destination_set): source_set.remove(vertex) destination_set.add(vertex) if __name__ == '__main__': graph = Graph(True) graph.add_edge(1,2) graph.add_edge(1,3) graph.add_edge(2,3) graph.add_edge(4,1) graph.add_edge(4,5) graph.add_edge(5,6) graph.add_edge(6,4) print(has_cycle(graph)); ================================================ FILE: python/graph/cycleundirectedgraph.py ================================================ # detect cycle in undirected graph # https://github.com/mission-peace/interview/blob/master/src/com/interview/graph/CycleUndirectedGraph.java from graph import * from disjointset import * def has_cycle_dfs(graph): visited = set() for vertex in graph.all_vertex.values(): if vertex in visited: continue flag = has_cycle_dfs_util(vertex, visited, None) if flag: return True return False def has_cycle_dfs_util(vertex, visited, parent): visited.add(vertex) for adjacent in vertex.adjacent_vertices: if parent is not None and adjacent == parent: continue if adjacent in visited: return True has_cycle = has_cycle_dfs_util(adjacent, visited, vertex) if has_cycle: return True return False def has_cycle_using_disjoint_set(graph): disjoint_set = DisjointSet() for vertex in graph.all_vertex.values(): disjoint_set.make_set(vertex.id) for edge in graph.all_edges: parent1 = disjoint_set.find_set(edge.vertex1.id) parent2 = disjoint_set.find_set(edge.vertex2.id) if parent1 == parent2: return True disjoint_set.union(edge.vertex1.id, edge.vertex2.id) return False if __name__ == '__main__': graph = Graph(False) graph.add_edge(0,1) graph.add_edge(1,2) graph.add_edge(0,3) graph.add_edge(3,4) graph.add_edge(4,5) graph.add_edge(5,1) has_cycle1 = has_cycle_dfs(graph) has_cycle2 = has_cycle_using_disjoint_set(graph) print(str(has_cycle1) + " " + str(has_cycle2)) ================================================ FILE: python/graph/dijkstrashortestpath.py ================================================ #dijkstra's algorithm # java code https://github.com/mission-peace/interview/blob/master/src/com/interview/graph/DijkstraShortestPath.java from priorityqueue import PriorityQueue from graph import Graph import sys def shortest_path(graph, sourceVertex): min_heap = PriorityQueue(True) distance = {} parent = {} for vertex in graph.all_vertex.values(): min_heap.add_task(sys.maxsize, vertex) min_heap.change_task_priority(0, sourceVertex) distance[sourceVertex] = 0 parent[sourceVertex] = None while min_heap.is_empty() is False: task = min_heap.peek_task() weight = min_heap.get_task_priority(task) current = min_heap.pop_task() distance[current] = weight for edge in current.edges: adjacent = get_other_vertex_for_edge(current, edge) if min_heap.contains_task(adjacent) is False: continue new_distance = distance[current] + edge.weight; if min_heap.get_task_priority(adjacent) > new_distance: min_heap.change_task_priority(new_distance, adjacent) parent[adjacent] = current return distance def get_other_vertex_for_edge(vertex, edge): if edge.vertex1.id == vertex.id: return edge.vertex2 else: return edge.vertex1 if __name__ == '__main__': graph = Graph(False) graph.add_edge(1,2,5) graph.add_edge(2,3,2) graph.add_edge(1,4,9) graph.add_edge(1,5,3) graph.add_edge(5,6,2) graph.add_edge(6,4,2) graph.add_edge(3,4,3) distance = shortest_path(graph, graph.all_vertex[1]) print(distance) ================================================ FILE: python/graph/disjointset.py ================================================ # disjoint sets # https://github.com/mission-peace/interview/blob/master/src/com/interview/graph/DisjointSet.java class Node(object): def __init__(self, data, parent = None, rank = 0): self.data = data self.parent = parent self.rank = rank def __str__(self): return str(self.data) def __repr__(self): return self.__str__() class DisjointSet(object): def __init__(self): self.map = {} def make_set(self, data): node = Node(data) node.parent = node self.map[data] = node def union(self, data1, data2): node1 = self.map[data1] node2 = self.map[data2] parent1 = self.find_set_util(node1) parent2 = self.find_set_util(node2) if parent1.data == parent2.data: return if parent1.rank >= parent2.rank: if parent1.rank == parent2.rank: parent1.rank = parent1.rank + 1 parent2.parent = parent1 else: parent1.parent = parent2 def find_set(self, data): return self.find_set_util(self.map[data]) def find_set_util(self, node): parent = node.parent if parent == node: return parent node.parent = self.find_set_util(node.parent) return node.parent if __name__ == '__main__': ds = DisjointSet() ds.make_set(1) ds.make_set(2) ds.make_set(3) ds.make_set(4) ds.make_set(5) ds.make_set(6) ds.make_set(7) ds.union(1,2) ds.union(2,3) ds.union(4,5) ds.union(6,7) ds.union(5,6) ds.union(3,7) for i in range(1,8): print(ds.find_set(i)) ================================================ FILE: python/graph/floydwarshall.py ================================================ # floyd warshall all pair shortest path # java code https://github.com/mission-peace/interview/blob/master/src/com/interview/graph/FloydWarshallAllPairShortestPath.java import sys INF = 1000000 class NegativeWeightCycleException(Exception): def __init__(self): pass def all_pair_shortest_path(distance_matrix): size = len(distance_matrix) distance = [[0 for x in range(size)] for x in range (size)] path = [[0 for x in range(size)] for x in range (size)] for i in range(size): for j in range(size): distance[i][j] = distance_matrix[i][j] if distance_matrix[i][j] != INF and i != j: path[i][j] = i else: path[i][j] = -1 for k in range(size): for i in range(size): for j in range(size): if distance[i][k] == INF or distance[k][j] == INF: continue if distance[i][j] > distance[i][k] + distance[k][j]: distance[i][j] = distance[i][k] + distance[k][j] path[i][j] = path[k][j] for i in range(size): if distance[i][i] < 0: raise NegativeWeightCycleException() print_path(path, 3, 2) return (distance, path) def print_path(path, start, end): stack = [] stack.append(end) while True: end = path[start][end] if end == -1: return stack.append(end) if end == start: break print(stack[::-1]) if __name__ == '__main__': distance_matrix = [[0, 3, 6, 15], [INF, 0, -2, INF], [INF, INF, 0, 2], [1, INF, INF, 0]] distance, path = all_pair_shortest_path(distance_matrix) print(distance) #print(path) ================================================ FILE: python/graph/fordfulkerson.py ================================================ #ford fulkerson method Edomonds Karp algorithm for finding max flow # java code https://github.com/mission-peace/interview/blob/master/src/com/interview/graph/FordFulkerson.java from queue import Queue import sys def max_flow(capacity, source, sink): residual_capacity = [x[:] for x in capacity] augmented_paths = [] max_flow = 0 while True: found_augmented_path, parent = bfs(residual_capacity, source, sink) if not found_augmented_path: break augmented_path = [] v = sink flow = sys.maxsize while not v == source: augmented_path.append(v) u = parent[v] if flow > residual_capacity[u][v]: flow = residual_capacity[u][v] v = u augmented_path.append(source) augmented_paths.append(augmented_path[::-1]) max_flow += flow v = sink while not v == source: u = parent[v] residual_capacity[u][v] -= flow residual_capacity[v][u] += flow v = u print("Augmented path") print(augmented_paths) return max_flow def bfs(residual_capacity, source, sink): visited = set() queue = Queue() parent = {} queue.put(source) visited.add(source) found_augmented_path = False while not queue.empty(): u = queue.get() for v in range(len(residual_capacity)): if v not in visited and residual_capacity[u][v] > 0: parent[v] = u visited.add(v) queue.put(v) if v == sink: found_augmented_path = True break; return found_augmented_path, parent if __name__ == '__main__': capacity = [[0, 3, 0, 3, 0, 0, 0], [0, 0, 4, 0, 0, 0, 0], [3, 0, 0, 1, 2, 0, 0], [0, 0, 0, 0, 2, 6, 0], [0, 1, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 9], [0, 0, 0, 0, 0, 0, 0]] max_val = max_flow(capacity, 0, 6) print(max_val) ================================================ FILE: python/graph/graph.py ================================================ #Graph class # Java code https://github.com/mission-peace/interview/blob/master/src/com/interview/graph/Graph.java class Graph(object): def __init__(self, is_directed): self.all_edges = [] self.all_vertex = {} self.is_directed = is_directed def add_edge(self, id1, id2, weight=0): if id1 in self.all_vertex: vertex1 = self.all_vertex[id1] else: vertex1 = Vertex(id1) self.all_vertex[id1] = vertex1 if id2 in self.all_vertex: vertex2 = self.all_vertex[id2] else: vertex2 = Vertex(id2) self.all_vertex[id2] = vertex2 edge = Edge(vertex1, vertex2, self.is_directed, weight) self.all_edges.append(edge) vertex1.add_adjacent_vertex(edge, vertex2) if self.is_directed is not True: vertex2.add_adjacent_vertex(edge,vertex1) class Edge(object): def __init__(self, vertex1, vertex2, is_directed, weight): self.vertex1 = vertex1 self.vertex2 = vertex2 self.is_directed = is_directed self.weight = weight def __eq__(self, other): return self.vertex1.id == other.vertex1.id and self.vertex2.id == other.vertex2.id def __hash(self): return hash(vertex1) + hash(vertex2) def __str__(self): return "Edge " + str(self.vertex1) + " " + str(self.vertex2) + " Weight-" + str(self.weight) def __repr__(self): return self.__str__() class Vertex(object): def __init__(self, id): self.id = id; self.edges = [] self.adjacent_vertices = [] def add_adjacent_vertex(self, edge, vertex): self.edges.append(edge) self.adjacent_vertices.append(vertex) def get_degree(self): return len(self.edges) def __eq__(self, other): return self.id == other.id def __hash__(self): return hash(self.id) def __str__(self): return str("Vertex-" + str(self.id)) def __repr__(self): return self.__str__(); def __lt__(self, other): return self.id < other.id def __gt__(self, other): return self.id > other.id if __name__ == '__main__': g = Graph(False) g.add_edge(1,2,10) g.add_edge(2,3,5) g.add_edge(1,4,6) for edge in g.all_edges: print(edge) for vertex in g.all_vertex: print("Vertex " + str(g.all_vertex[vertex])) for edge in g.all_vertex[vertex].edges: print("Edge " + str(edge)) ================================================ FILE: python/graph/graphtraversal.py ================================================ #doing BFS and DFS traversal of the graph # java code https://github.com/mission-peace/interview/blob/master/src/com/interview/graph/GraphTraversal.java from graph import * import queue def dfs_util(v, visited): if v in visited: return visited.add(v) print(v) for vertex in v.adjacent_vertices: dfs_util(vertex, visited) def dfs(graph): visited = set() for id in graph.all_vertex: dfs_util(graph.all_vertex[id], visited) def bfs(graph): q = queue.Queue() visited = set() for vertex in graph.all_vertex.values(): if vertex not in visited: q.put(vertex) visited.add(vertex) while not q.empty(): v = q.get(); print(v) for adj in v.adjacent_vertices: if adj not in visited: q.put(adj) visited.add(adj) if __name__ == '__main__': g = Graph(False) g.add_edge(1,2,10) g.add_edge(2,3,5) g.add_edge(1,4,6) dfs(g) bfs(g) ================================================ FILE: python/graph/kruskalmst.py ================================================ # kruskal minimum spanning tree # java code https://github.com/mission-peace/interview/blob/master/src/com/interview/graph/KruskalMST.java from disjointset import * from graph import * def get_key(edge): return edge.weight def minimum_spanning_tree(graph): disjoint_set = DisjointSet() sorted_edges = sorted(graph.all_edges, key = get_key) print(sorted_edges) for vertex in graph.all_vertex.values(): disjoint_set.make_set(vertex.id) result_edge = [] for edge in sorted_edges: root1 = disjoint_set.find_set(edge.vertex1.id) root2 = disjoint_set.find_set(edge.vertex2.id) if root1 == root2: continue else: result_edge.append(edge) disjoint_set.union(edge.vertex1.id, edge.vertex2.id) return result_edge if __name__ == '__main__': graph = Graph(False) graph.add_edge(1,3,1) graph.add_edge(1,2,4) graph.add_edge(2,4,2) graph.add_edge(2,5,1) graph.add_edge(2,6,3) graph.add_edge(3,4,5) graph.add_edge(3,7,8) graph.add_edge(4,7,2) graph.add_edge(6,5,2) graph.add_edge(6,4,3) result = minimum_spanning_tree(graph) for edge in result: print(edge) ================================================ FILE: python/graph/primmst.py ================================================ #Prim's MST # Java code https://github.com/mission-peace/interview/blob/master/src/com/interview/graph/PrimMST.java from graph import Graph from priorityqueue import PriorityQueue import sys def minimum_spanning_tree(graph): min_heap = PriorityQueue(True) vertex_to_edge = {} result = [] for vertex in graph.all_vertex.values(): min_heap.add_task(sys.maxsize, vertex) start_vertex = next(iter((graph.all_vertex.values()))) min_heap.change_task_priority(0, start_vertex) while min_heap.is_empty() is False: current = min_heap.pop_task() if(current in vertex_to_edge): spanning_tree_edge = vertex_to_edge[current] result.append(spanning_tree_edge) for edge in current.edges: adjacent = get_other_vertex_for_edge(current, edge) if min_heap.contains_task(adjacent) is True and min_heap.get_task_priority(adjacent) > edge.weight: min_heap.change_task_priority(edge.weight, adjacent) vertex_to_edge[adjacent] = edge return result def get_other_vertex_for_edge(vertex, edge): if edge.vertex1.id == vertex.id: return edge.vertex2 else: return edge.vertex1 if __name__ == '__main__': graph = Graph(False) graph.add_edge(1,2,3) graph.add_edge(2,3,1) graph.add_edge(3,1,1) graph.add_edge(1,4,1) graph.add_edge(2,4,3) graph.add_edge(4,5,6) graph.add_edge(5,6,2) graph.add_edge(3,5,5) graph.add_edge(3,6,4) result = minimum_spanning_tree(graph) print(result) ================================================ FILE: python/graph/priorityqueue.py ================================================ # add to heapq things like removing any item and changing key value # implementation of priority queue to support contains, change_task_priority # and remove_task in log time from heapq import * class PriorityQueue(object): def __init__(self, is_min_heap): self.pq = [] self.entry_finder = {} if(is_min_heap is True): self.mul = 1 else : self.mul = -1 def contains_task(self, task): if task in self.entry_finder: return True else: return False def get_task_priority(self, task): if task in self.entry_finder: return (self.entry_finder[task])[0] raise ValueError("task does not exist") def add_task(self, priority, task): if task in self.entry_finder: raise KeyError("Key already exists") entry = [self.mul*priority, False, task] self.entry_finder[task] = entry heappush(self.pq, entry) def change_task_priority(self, priority, task): if task not in self.entry_finder: raise KeyError("Task not found") self.remove_task(task) entry = [self.mul*priority, False, task] self.entry_finder[task] = entry heappush(self.pq, entry) def remove_task(self, task): entry = self.entry_finder.pop(task) entry[1] = True def pop_task(self): while self.pq: priority, removed, task = heappop(self.pq) if removed is False: del self.entry_finder[task] return task raise KeyError("pop from an empty priority queue") def peek_task(self): while self.pq: priority, removed, task = tuple(heappop(self.pq)) if removed is False: heappush(self.pq, [priority, False, task]) return task raise KeyError("pop from an empty priority queue") def is_empty(self): try: self.peek_task() return False except KeyError: return True def __str__(self): return str(self.entry_finder) + " " + str(self.pq) if __name__ == '__main__': task1 = "Tushar" task2 = "Roy" task3 = "is" task4 = "coder" min_pq = PriorityQueue(True) min_pq.add_task(1, task1) min_pq.add_task(3, task2) min_pq.add_task(6, task3) min_pq.add_task(7, task4) print(min_pq.contains_task(task3)) print(min_pq.get_task_priority(task3)) print(min_pq) while min_pq.is_empty() is False: print(min_pq.pop_task()) max_pq = PriorityQueue(False) max_pq.add_task(1, task1) max_pq.add_task(3, task2) max_pq.add_task(6, task3) max_pq.add_task(7, task4) while max_pq.is_empty() is False: print(max_pq.pop_task()) ================================================ FILE: python/graph/topologicalsort.py ================================================ #topological sort # java code https://github.com/mission-peace/interview/blob/master/src/com/interview/graph/TopologicalSort.java from graph import Graph def top_sort(graph): stack = [] visited = set() for vertex in graph.all_vertex.values(): if vertex in visited: continue top_sort_util(vertex, stack, visited) return stack def top_sort_util(vertex, stack, visited): visited.add(vertex) for adjacent in vertex.adjacent_vertices: if adjacent in visited: continue top_sort_util(adjacent, stack, visited) stack.append(vertex) if __name__ == '__main__': graph = Graph(True) graph.add_edge(1,3) graph.add_edge(1,2) graph.add_edge(3,4) graph.add_edge(5,6) graph.add_edge(6,3) graph.add_edge(3,8) graph.add_edge(8,11) stack = top_sort(graph) print(stack[::-1]) ================================================ FILE: python/recursion/setpairtogether.py ================================================ # http://www.geeksforgeeks.org/minimum-number-of-swaps-required-for-arranging-pairs-adjacent-to-each-other/ def find_minimum_swaps(input, pair): index = {} for i, val in enumerate(input): index[val] = i return find_minimum_swaps_util(input, pair, index, 0) def find_minimum_swaps_util(input, pair, index, current): if current == len(input): return 0 v1 = input[current] v2 = input[current + 1] pv2 = pair[v1] if pv2 == v2: return find_minimum_swaps_util(input, pair, index, current + 2) else: idx1 = index.get(v1) idx2 = index.get(v2) idx3 = index.get(pair[v1]) idx4 = index.get(pair[v2]) swap(index, input, idx2, idx3) val1 = find_minimum_swaps_util(input, pair, index, current+2) swap(index, input, idx2, idx3) swap(index, input, idx1, idx4) val2 = find_minimum_swaps_util(input, pair, index, current+2) swap(index, input, idx1, idx4) return 1 + max(val1, val2) def swap(index, input, i, j): index[input[i]] = j index[input[j]] = i t = input[i] input[i] = input[j] input[j] = t if __name__ == '__main__': input = [3, 5, 6, 4, 1, 2] pair = {} pair[1] = 3 pair[3] = 1 pair[2] = 6 pair[6] = 2 pair[4] = 5 pair[5] = 4 print(find_minimum_swaps(input, pair)) ================================================ FILE: python/recursion/stringpermutation.py ================================================ # string permutation in lexicographically order with repetition of characters in the string def permute(input): count_map = {} for ch in input: if ch in count_map.keys(): count_map[ch] = count_map[ch] + 1 else: count_map[ch] = 1 keys = sorted(count_map) str = [] count = [] for key in keys: str.append(key) count.append(count_map[key]) result = [0 for x in range(len(input))] permute_util(str, count, result, 0) def permute_util(str, count, result, level): if level == len(result): print(result) return for i in range(len(str)): if count[i] == 0: continue; result[level] = str[i] count[i] -= 1 permute_util(str, count, result, level + 1) count[i] += 1 if __name__ == '__main__': input = ['B', 'C', 'A', 'A'] permute(input) ================================================ FILE: python/string/Z_Algorithm.py ================================================ #author: Pankaj Kumar #time complexity: O(length(string) + length(pattern)) #space complexity: O(length(string) + length(pattern)) #Link to theory: http://www.geeksforgeeks.org/z-algorithm-linear-time-pattern-searching-algorithm/ def z_algo(arr): z = [0 for i in range(len(arr))] left , right = 0 , 0 for k in range(1 , len(arr)): if k > right: left = k right = k while right < len(arr) and arr[right] == arr[right-left]: right += 1 z[k] = right - left right -= 1 else: k1 = k - left if z[k1] < right - k + 1: z[k] = z[k1] else: left = k while right < len(arr) and arr[right] == arr[right-left]: right += 1 z[k] = right - left right -= 1 return z def makepattern(string , pattern): n , m = len(string) , len(pattern) str_arr = [] for i in range(m): str_arr.append(pattern[i]) str_arr.append('$') for i in range(n): str_arr.append(string[i]) z_values = z_algo(str_arr) result = [] for i in range(len(z_values)): if z_values[i] == m: result.append(i - m - 1) print result if __name__ == '__main__': string = 'abcdeabcd' pattern = 'abc' makepattern(string , pattern) ================================================ FILE: python/string/knuthmorrispratt.py ================================================ # Knuth-Morris-Pratt algorithm # Compute temporary array to maintain size of suffix which is same as prefix # Time/space complexity is O(size of pattern) def compute_temporary_array(pattern): n = len(pattern) lsp = [0 for j in range(n)] index = 0 i = 1 while i < len(pattern): if pattern[i] == pattern[index]: lsp[i] = index + 1 index += 1 i += 1 else: if index != 0: index = lsp[index - 1] else: lsp[i] = 0 i += 1 return lsp # KMP algorithm of pattern matching. def kmp(text, pattern): lsp = compute_temporary_array(pattern) i = 0 j = 0 while i < len(text) and j < len(pattern): if text[i] == pattern[j]: i += 1 j += 1 else: if j != 0: j = lsp[j - 1] else: i += 1 if j == len(pattern): return True else: return False src = 'abcxabcdabcdabcy' sub_string = 'abcdabcy' result = kmp(src, sub_string) print(result) ================================================ FILE: python/string/rabinkarp.py ================================================ #Rabin Karp algorithm # Java code https://github.com/mission-peace/interview/blob/master/src/com/interview/string/RabinKarpSearch.java prime = 101 def pattern_matching(text, pattern): m = len(pattern) n = len(text) pattern_hash = create_hash(pattern, m - 1) text_hash = create_hash(text, m - 1) for i in range(1, n - m + 2): if pattern_hash == text_hash: if check_equal(text[i-1:i+m-1], pattern[0:]) is True: return i - 1; if i < n - m + 1: text_hash = recalculate_hash(text, i-1, i+m-1, text_hash, m) return -1; def check_equal(str1, str2): if len(str1) != len(str2): return False; i = 0 j = 0 for i, j in zip(str1, str2): if i != j: return False; return True def create_hash(input, end): hash = 0 for i in range(end + 1): hash = hash + ord(input[i])*pow(prime, i) return hash def recalculate_hash(input, old_index, new_index, old_hash, pattern_len): new_hash = old_hash - ord(input[old_index]) new_hash = new_hash/prime new_hash += ord(input[new_index])*pow(prime, pattern_len - 1) return new_hash; index = pattern_matching("TusharRoy", "sharRoy") print("Index ", index) index = pattern_matching("TusharRoy", "Roy") print("Index ", index) index = pattern_matching("TusharRoy", "shar") print("Index ", index) index = pattern_matching("TusharRoy", "usha") print("Index ", index) index = pattern_matching("TusharRoy", "Tus") print("Index ", index) index = pattern_matching("TusharRoy", "Roa") print("Index ", index) ================================================ FILE: python/tree/binary_tree.py ================================================ from collections import namedtuple Color = namedtuple("Color", "RED BLACK") class Node: def __init__(self): self.color = None self.height = None self.lis = None self.data = None self.size = None self.next = None self.right = None self.left = None @staticmethod def newNode(data): n = Node() n.data = data n.lis = -1 n.height = 1 n.size = 1 n.color = Color.RED return n class BinaryTree: def __init__(self): pass @staticmethod def add_head(data, head): temp_head = head n = Node.newNode(data) if head is None: head = n return head prev = None while head is not None: prev = head if head.data < data: head = head.right else: head = head.left if prev.data < data: prev.right = n else: prev.left = n return temp_head ================================================ FILE: python/tree/construct_tree_from_inorder_preorder.py ================================================ from binary_tree import Node class ConstructTreeFromInorderPreOrder: def __init__(self): self.index = 0 def _createTree(self, inorder, preorder, start, end): if start > end: return None i = 0 for i in range(start, end + 1): if preorder[self.index] == inorder[i]: break node = Node.newNode(preorder[self.index]) self.index += 1 node.left = self._createTree(inorder, preorder, start, i - 1) node.right = self._createTree(inorder, preorder, i + 1, end) return node def createTree(self, inorder, preorder): return self._createTree(inorder, preorder, 0, len(inorder) - 1) ================================================ FILE: python/tree/fenwick_tree.py ================================================ ################################################################################################################################# #Implementation of Binary Indexed Tree OR Fenwick Tree #Time Complexities: # Construction of Tree: O (n.log (n)) # Updating an element: O (log (n)) # Prefix Query (sum of elements 0 to i) or Range Minimum Query (sum of elements x to y): O (log (n)) #Space Complexity: O (n) ################################################################################################################################# class FenTree (object): def __init__ (self, array): self.array, self.tree = [0] * len (array), [0] * (len (array) + 1); for i in range (len (array)): self.update (i, array [i]); def get_parent (self, child): return (child - (child & -child)); def get_next (self, index): return (index + (index & -index)); def update (self, index, item): current, self.array [index] = self.array [index], item; item -= current; index += 1; while (index <= len (self.array)): self.tree [index] += item; index = self.get_next (index); def prefix_sum (self, index): index += 1; total = 0; while (index > 0): total += self.tree [index]; index = self.get_parent (index); return (total); def range_sum (self, x, y): return (self.prefix_sum (max (x, y)) - self.prefix_sum (min (x, y) - 1)); def describe (self): print ('ARRAY =>\t', self.array); print ('Binary Indexed Tree =>\t', self.tree); if (__name__ == '__main__'): tree = FenTree ([3,2,-1,6,5,4]); # tree = FenTree ([int (i) for i in input ('Enter the array (space-separated integers): ').split ()]); tree.describe (); tree.update (4, 8); #replaces 5 with 8 in the list given to the fenwick tree tree.describe (); print (tree.range_sum (1, 5)); #returns 2-1+6+5+4 print (tree.prefix_sum (5)); #returns 3+2-1+6+5+4 ================================================ FILE: python/tree/largest_bst_in_binary_tree.py ================================================ """ Given a binary tree, find size of largest binary search subtree in this binary tree. Approach -------- Traverse tree in post order fashion. Left and right nodes return 4 piece of information to root which isBST, size of max BST, min and max in those subtree. If both left and right subtree are BST and this node data is greater than max of left and less than min of right then it returns to above level left size + right size + 1 and new min will be min of left side and new max will be max of right side. Video link ---------- * https://youtu.be/4fiDs7CCxkc References ---------- * http://www.geeksforgeeks.org/find-the-largest-subtree-in-a-tree-that-is-also-a-bst/ * https://leetcode.com/problems/largest-bst-subtree/ * http://www.geeksforgeeks.org/construct-tree-from-given-inorder-and-preorder-traversal/ """ from construct_tree_from_inorder_preorder import ConstructTreeFromInorderPreOrder class MinMax: def __init__(self): self.min = float("inf") self.max = float("-inf") self.isBST = True self.size = 0 class LargestBSTBinaryTree: def largestBST(self, root): m = self.largest(root) return m.size def largest(self, root): if root is None: return MinMax() leftMinMax = self.largest(root.left) rightMinMax = self.largest(root.right) m = MinMax() if ((leftMinMax.isBST == False or rightMinMax.isBST == False) or (leftMinMax.max > root.data or rightMinMax.min <= root.data)): m.isBST = False m.size = max(leftMinMax.size, rightMinMax.size) return m m.isBST = True m.size = leftMinMax.size + rightMinMax.size + 1 m.min = leftMinMax.min if root.left is not None else root.data m.max = rightMinMax.max if root.right is not None else root.data return m if __name__ == '__main__': lbi = LargestBSTBinaryTree() ctf = ConstructTreeFromInorderPreOrder() inorder = [-7, -6, -5, -4, -3, -2, 1, 2, 3, 16, 6, 10, 11, 12, 14] preorder = [3, -2, -3, -4, -5, -6, -7, 1, 2, 16, 10, 6, 12, 11, 14] root = ctf.createTree(inorder, preorder) largestBSTSize = lbi.largestBST(root) print "Size of the largest BST in the Binary Tree is ", largestBSTSize assert 8 == lbi.largestBST(root) ================================================ FILE: python/tree/max_depth_binary_tree.py ================================================ """ Problem Statement ================= Given a binary tree, write a program to find the maximum depth at any given node. For e.g, for this binary tree. 1 / \ 2 3 / \ 4 5 The height at 1 is 3, and the height at 3 is 2. """ class Node: def __init__(self, value): self.value = value self.left = None self.right = None n1 = Node(1) n2 = Node(2) n3 = Node(3) n4 = Node(4) n5 = Node(5) # construct the tree as given in the problem. n1.left = n2 n1.right = n3 n3.left = n4 n3.right = n5 def find_max_depth(n): if n is None: return 0 left_height = find_max_depth(n.left) right_height = find_max_depth(n.right) if left_height > right_height: result = left_height + 1 else: result = right_height + 1 return result if __name__ == '__main__': assert 3 == find_max_depth(n1) assert 2 == find_max_depth(n3) ================================================ FILE: python/tree/morris_traversal.py ================================================ """Morris Traversal of a Binary Tree. Video ----- * https://youtu.be/wGXB9OWhPTg Analysis -------- * Time complexity O(n) * Space complexity O(1) """ from binary_tree import BinaryTree class MorrisTraversal: def __init__(self): pass @staticmethod def find_predecessor(current): predecessor = current.left while predecessor.right != current and predecessor.right is not None: predecessor = predecessor.right return predecessor @staticmethod def inorder(root_node): current = root_node while current is not None: if current.left is None: print "{data} ".format(data=current.data), current = current.right else: predecessor = MorrisTraversal.find_predecessor(current) if predecessor.right is None: predecessor.right = current current = current.left else: predecessor.right = None print "{data} ".format(data=current.data), current = current.right @staticmethod def preorder(root_node): current = root_node while current is not None: if current.left is None: print "{data} ".format(data=current.data), current = current.right else: predecessor = MorrisTraversal.find_predecessor(current) if predecessor.right is None: print "{data} ".format(data=current.data), predecessor.right = current current = current.left else: predecessor.right = None current = current.right if __name__ == '__main__': bt = BinaryTree() root = None root = bt.add_head(10, root) root = bt.add_head(50, root) root = bt.add_head(-10, root) root = bt.add_head(7, root) root = bt.add_head(9, root) root = bt.add_head(-20, root) root = bt.add_head(30, root) mt = MorrisTraversal() mt.inorder(root) print "\n", mt.preorder(root) ================================================ FILE: python/tree/segmenttreesum.py ================================================ def create_segment_tree(input): size = next_power_of_2(len(input)); segment_tree = [0 for x in range(2*size - 1)] construct_tree(segment_tree, input, 0, len(input) - 1, 0) return segment_tree def construct_tree(segment_tree, input, low, high, pos): if low == high: segment_tree[pos] = input[low] return mid = (low + high)/2 construct_tree(segment_tree, input, low, mid, 2*pos + 1) construct_tree(segment_tree, input, mid + 1, high, 2*pos + 2) segment_tree[pos] = segment_tree[2*pos+1] + segment_tree[2*pos+2] def sum_range_query(segment_tree, q_low, q_high, len): return sum_range_query_util(segment_tree, 0, len - 1, q_low, q_high, 0) def sum_range_query_util(segment_tree, low, high, q_low, q_high, pos): if q_low <= low and q_high >= high: return segment_tree[pos] if q_high < low or q_low > high: return 0 mid = (low + high)/2 return sum_range_query_util(segment_tree, low, mid, q_low, q_high, 2*pos + 1)\ + sum_range_query_util(segment_tree, mid + 1, high, q_low, q_high, 2*pos + 2) def update_value(input, segment_tree, new_value, index): diff = new_value - input[index] input[index] = new_value update_value_util(segment_tree, 0, len(input)-1, diff, index, 0) def update_value_util(segment_tree, low, high, diff, index, pos): if low > index or high < index: return segment_tree[pos] += diff if low >= high: return mid = (low + high)/2 update_value_util(segment_tree, low, mid, diff, index, 2*pos + 1) update_value_util(segment_tree, mid + 1, high, diff, index, 2*pos + 2) def next_power_of_2(n): if n == 0: return 1 if n & (n - 1) == 0: return n while n & (n - 1) > 0: n &= (n - 1) return n << 1 if __name__ == '__main__': input = [1,3,5,7,9,11] segment_tree = create_segment_tree(input) print(segment_tree) print(sum_range_query(segment_tree, 2, 5, len(input))) print(sum_range_query(segment_tree, 1, 3, len(input))) update_value(input, segment_tree, 4, 3) print(sum_range_query(segment_tree, 2, 5, len(input))) print(sum_range_query(segment_tree, 1, 3, len(input))) ================================================ FILE: src/com/interview/array/AdditiveNumber.java ================================================ package com.interview.array; import java.math.BigInteger; /** * Date 04/24/2016 * @author Tushar Roy * * Additive number is a string whose digits can form additive sequence. * A valid additive sequence should contain at least three numbers. * Except for the first two numbers, each subsequent number in the sequence must be the sum of the preceding two. * * https://leetcode.com/problems/additive-number/ */ public class AdditiveNumber { public boolean isAdditiveNumber(String num) { if (num.length() < 3) { return false; } for (int i = 0; i <= num.length()/2; i++) { if (num.charAt(0) == '0' && i > 0) { break; } BigInteger x1 = new BigInteger(num.substring(0, i + 1)); //make sure remaining size is at least size of first and second integer. for (int j = i + 1; Math.max(i, j - (i + 1)) + 1 <= num.length() - j - 1 ; j++) { if (num.charAt(i + 1) == '0' && j > i + 1) { break; } BigInteger x2 = new BigInteger(num.substring(i + 1, j + 1)); if (isValid(num, j + 1, x1, x2)) { return true; } } } return false; } private boolean isValid(String num, int start, BigInteger x1, BigInteger x2) { if (start == num.length()) { return true; } BigInteger x3 = x1.add(x2); //if num starts with x3 from offset start means x3 is found. So look for next number. return num.startsWith(x3.toString(), start) && isValid(num, start + x3.toString().length(), x2, x3); } } ================================================ FILE: src/com/interview/array/ArrayAddition.java ================================================ package com.interview.array; public class ArrayAddition { public int[] add(int arr1[], int arr2[]){ int l = Math.max(arr1.length, arr2.length); int[] result = new int[l]; int c=0; int i = arr1.length-1; int j= arr2.length-1; int r=0; l--; while(i >=0 && j >=0){ r = arr1[i--] + arr2[j--] + c; c = r/10; result[l--] = r%10; } while(i>=0){ r = arr1[i--] + c; c = r/10; result[l--] = r%10; } while(j>=0){ r = arr2[j--] + c; c = r/10; result[l--] = r%10; } if(c != 0){ int[] newResult = new int[result.length+1]; for(int t= newResult.length-1; t> 0; t--){ newResult[t] = result[t-1]; } newResult[0] = c; return newResult; } return result; } public static void main(String args[]){ int arr1[] = {9,9,9,9,9,9,9}; int arr2[] = {1,6,8,2,6,7}; ArrayAddition aa = new ArrayAddition(); int result[] = aa.add(arr1, arr2); for(int i=0; i < result.length; i++){ System.out.print(" " + result[i]); } } } ================================================ FILE: src/com/interview/array/BestMeetingPoint.java ================================================ package com.interview.array; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Date 03/24/2016 * @author Tushar Roy * * A group of two or more people wants to meet and minimize the total travel distance. * You are given a 2D grid of values 0 or 1, where each 1 marks the home of someone in the group. * The distance is calculated using Manhattan Distance, where distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|. * Find the total distance that needs to be travelled to reach this meeting point. * * Time complexity O(m*n) * Space complexity O(m + n) * * https://leetcode.com/problems/best-meeting-point/ */ public class BestMeetingPoint { public int minTotalDistance(int[][] grid) { if (grid.length == 0 || grid[0].length == 0) { return 0; } List vertical = new ArrayList<>(); List horizontal = new ArrayList<>(); for (int i = 0; i < grid.length; i++) { for (int j = 0; j < grid[0].length; j++) { if (grid[i][j] == 1) { vertical.add(i); horizontal.add(j); } } } Collections.sort(vertical); Collections.sort(horizontal); int size = vertical.size()/2; int x = vertical.get(size); int y = horizontal.get(size); int distance = 0; for (int i = 0; i < grid.length; i++) { for (int j = 0; j < grid[0].length; j++) { if (grid[i][j] == 1) { distance += Math.abs(x - i) + Math.abs(y - j); } } } return distance; } public static void main(String args[]) { BestMeetingPoint bmp = new BestMeetingPoint(); int[][] grid = {{1, 0, 0, 0, 1}, {0, 0, 0, 0, 0},{0, 0, 1, 0, 0}}; System.out.print(bmp.minTotalDistance(grid)); } } ================================================ FILE: src/com/interview/array/BuySellStockProfit.java ================================================ package com.interview.array; /** * Date 03/04/2016 * @author Tushar Roy * * Best time to buy and sell stocks. * 1) Only 1 transaction is allowed * 2) Infinite number transactions are allowed * * Time complexity O(n) * Space complexity O(1) * * https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ * https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/ */ public class BuySellStockProfit { public int oneProfit(int arr[]){ int minPrice = arr[0]; int maxProfit = 0; for(int i=1; i < arr.length; i++){ if(arr[i] - minPrice > maxProfit){ maxProfit = arr[i] - minPrice; } if(arr[i] < minPrice){ minPrice = arr[i]; } } return maxProfit; } public int allTimeProfit(int arr[]){ int profit = 0; for(int i=1; i < arr.length;i++){ if(arr[i-1] < arr[i]){ profit += arr[i] - arr[i-1]; } } return profit; } public static void main(String args[]){ int arr[] = {7,10,15,5,11,2,7,9,3}; int arr1[] = {6,4,1,3,5,7,3,1,3,4,7,9,2,5,6,0,1,2}; BuySellStockProfit bss = new BuySellStockProfit(); System.out.println(bss.oneProfit(arr)); System.out.print(bss.allTimeProfit(arr1)); } } ================================================ FILE: src/com/interview/array/CheckIfArrayElementsAreConsecutive.java ================================================ package com.interview.array; /** * http://www.geeksforgeeks.org/check-if-array-elements-are-consecutive/ */ public class CheckIfArrayElementsAreConsecutive { public boolean areConsecutive(int input[]){ int min = Integer.MAX_VALUE; for(int i=0; i < input.length; i++){ if(input[i] < min){ min = input[i]; } } for(int i=0; i < input.length; i++){ if(Math.abs(input[i]) - min >= input.length){ return false; } if(input[Math.abs(input[i]) - min] < 0){ return false; } input[Math.abs(input[i]) - min] = -input[Math.abs(input[i]) - min]; } for(int i=0; i < input.length ; i++){ input[i] = Math.abs(input[i]); } return true; } public static void main(String args[]){ int input[] = {76,78,76,77,73,74}; CheckIfArrayElementsAreConsecutive cia = new CheckIfArrayElementsAreConsecutive(); System.out.println(cia.areConsecutive(input)); } } ================================================ FILE: src/com/interview/array/ChunkMerge.java ================================================ package com.interview.array; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.PriorityQueue; /** * Given a list of lists. Each element in the list is sorted. Sort the * entire list. * Test cases * One or more lists are empty * All elements in one list are smaller than all elements in another list */ public class ChunkMerge { class Triplet implements Comparable{ int pos; int val; int index; @Override public int compareTo(Triplet o) { if(val <= o.val){ return -1; }else{ return 1; } } } public List mergeUsingHeap(List> chunks){ List result = new ArrayList(); PriorityQueue queue = new PriorityQueue(); //add first element of every chunk into queue for(int i=0; i < chunks.size(); i++){ Triplet p = new Triplet(); p.pos = i; p.val = chunks.get(i).get(0); p.index = 1; queue.add(p); } while(!queue.isEmpty()){ Triplet p = queue.poll(); result.add(p.val); if(p.index < chunks.get(p.pos).size()){ p.val = chunks.get(p.pos).get(p.index); p.index += 1; queue.add(p); } } return result; } public List mergeChunksOfDifferentSize(List> chunks){ List result = new ArrayList(); int sum[] = new int[chunks.size()+1]; sum[0] = 0; for(int i =1; i < sum.length;i++){ sum[i] = sum[i-1] + chunks.get(i-1).size(); } for(List chunk : chunks){ for(Integer i : chunk){ result.add(i); } } mergeSort(result,0,chunks.size()-1,sum); return result; } private void mergeSort(List result,int start,int end,int sum[]){ if(start >= end){ return; } int mid = (start + end)/2; mergeSort(result,start,mid,sum); mergeSort(result,mid+1,end,sum); sortedMerge(result,start,end,sum); } private void sortedMerge(List result,int start,int end,int sum[]){ /** * If chunks are of equal size then * i = size*start to (mid+1)*size -1 * j = (mid+1)*size to size*(end+1) */ int mid = (start + end)/2; int i = sum[start]; int j = sum[mid+1]; List temp = new ArrayList(); while(i < sum[mid+1] && j < sum[end+1]){ if(result.get(i) < result.get(j)){ temp.add(result.get(i)); i++; }else{ temp.add(result.get(j)); j++; } } while(i < sum[mid+1]){ temp.add(result.get(i)); i++; } while(j < sum[end+1]){ temp.add(result.get(j)); j++; } int index = sum[start]; for(int k : temp){ result.set(index, k); index++; } } public static void main(String args[]){ Integer arr1[] = {1,5,6,9,21}; Integer arr2[] = {4,6,11,14}; Integer arr3[] = {-1,0,7}; Integer arr4[] = {-4,-2,11,14,18}; Integer arr5[] = {2,6}; Integer arr6[] = {-5,-2,1,5,7,11,14}; Integer arr7[] = {-6,-1,0,15,17,22,24}; List list1 = Arrays.asList(arr1); List list2 = Arrays.asList(arr2); List list3 = Arrays.asList(arr3); List list4 = Arrays.asList(arr4); List list5 = Arrays.asList(arr5); List list6 = Arrays.asList(arr6); List list7 = Arrays.asList(arr7); List> chunks = new ArrayList>(); chunks.add(list1); chunks.add(list2); chunks.add(list3); chunks.add(list4); chunks.add(list5); chunks.add(list6); chunks.add(list7); ChunkMerge cm = new ChunkMerge(); List result = cm.mergeChunksOfDifferentSize(chunks); System.out.println(result.size()); for(Integer r : result){ System.out.print(r + " "); } result = cm.mergeUsingHeap(chunks); System.out.println(); for(Integer r : result){ System.out.print(r + " "); } } } ================================================ FILE: src/com/interview/array/CommonThreeSortedArray.java ================================================ package com.interview.array; import java.util.ArrayList; import java.util.List; /** * Date 01/01/2016 * @author Tushar Roy * * Given 3 sorted array find common elements in these 3 sorted array. * * Time complexity is O(m + n + k) * * http://www.geeksforgeeks.org/find-common-elements-three-sorted-arrays/ */ public class CommonThreeSortedArray { public List commonElements(int input1[], int input2[], int input3[]) { int i = 0; int j = 0; int k = 0; List result = new ArrayList<>(); while (i < input1.length && j < input2.length && k < input3.length) { if (input1[i] == input2[j] && input2[j] == input3[k]) { result.add(input1[i]); i++; j++; k++; } else if (input1[i] < input2[j]) { i++; } else if (input2[j] < input3[k]) { j++; } else { k++; } } return result; } public static void main(String args[]) { int input1[] = {1, 5, 10, 20, 40, 80}; int input2[] = {6, 7, 20, 80, 100}; int input3[] = {3, 4, 15, 20, 30, 70, 80, 120}; CommonThreeSortedArray cts = new CommonThreeSortedArray(); List result = cts.commonElements(input1, input2, input3); result.forEach(i -> System.out.print(i + " ")); } } ================================================ FILE: src/com/interview/array/ConvertAnArrayIntoDecreaseIncreaseFashion.java ================================================ package com.interview.array; import java.util.Arrays; /** * Convert an unsorted array into an array such that * a < b > c < d > e < f and so on */ public class ConvertAnArrayIntoDecreaseIncreaseFashion { public void convert(int arr[]){ int k = 0; if(arr.length % 2 ==0){ k = arr.length/2 ; }else{ k = arr.length/2+1; } KthElementInArray kthElement = new KthElementInArray(); kthElement.kthElement(arr, k); int high = k; int low = 1; while(low < high && high < arr.length){ swap(arr,low,high); high++; low += 2; } } /** * Sort the array first. * Then swap every adjacent element to get final result * @param arr */ public void convert1(int arr[]){ Arrays.sort(arr); for(int i=1; i < arr.length; i+=2){ if(i+1 < arr.length){ swap(arr, i, i+1); } } } private void swap(int arr[],int low,int high){ int temp = arr[low]; arr[low] = arr[high]; arr[high] = temp; } public static void main(String args[]){ ConvertAnArrayIntoDecreaseIncreaseFashion can = new ConvertAnArrayIntoDecreaseIncreaseFashion(); int arr[] = {0,6,9,13,10,-1,8,2,4,14,-5}; can.convert(arr); for(int i=0; i < arr.length; i++){ System.out.print(arr[i] + " "); } System.out.println(); int arr1[] = {0,6,9,13,10,-1,8,2,4,14,-5}; can.convert1(arr1); for(int i=0; i < arr1.length; i++){ System.out.print(arr1[i] + " "); } } } ================================================ FILE: src/com/interview/array/CountInversionOfSize3.java ================================================ package com.interview.array; /** * Date 12/29/15 * @author Tushar Roy * * Given input array find number of inversions where i < j < k and input[i] > input[j] > input[k] * * http://www.geeksforgeeks.org/count-inversions-of-size-three-in-a-give-array/ */ public class CountInversionOfSize3 { /** * Time complexity of this method is O(n^2) * Space complexity is O(1) */ public int findInversions(int input[]) { int inversion = 0; for (int i = 1; i < input.length - 1 ; i++) { int larger = 0; for (int k = 0; k < i; k++) { if (input[k] > input[i]) { larger++; } } int smaller = 0; for (int k = i+1; k < input.length; k++) { if (input[k] < input[i]) { smaller++; } } inversion += smaller*larger; } return inversion; } public static void main(String args[]) { int input[] = {9, 6, 4, 5, 8}; CountInversionOfSize3 ci = new CountInversionOfSize3(); System.out.print(ci.findInversions(input)); } } ================================================ FILE: src/com/interview/array/CountSmallerOnRight.java ================================================ package com.interview.array; import java.util.ArrayList; import java.util.List; /** * Date 03/01/2016 * @author Tushar Roy * * Count number of smaller elements on right side of an array for every element. * * Time complexity is O(nlogn) * Space complexity is O(n) * * https://leetcode.com/problems/count-of-smaller-numbers-after-self/ */ public class CountSmallerOnRight { static class NumberIndex { int val; int index; NumberIndex(int val, int index) { this.val = val; this.index = index; } } public List countSmaller(int[] nums) { if (nums.length == 0) { return new ArrayList<>(); } NumberIndex[] input = new NumberIndex[nums.length]; for (int i = 0; i < nums.length; i++) { input[i] = new NumberIndex(nums[i], i); } int result[] = new int[nums.length]; mergeUtil(input, result, 0, input.length - 1); List r = new ArrayList<>(); for (int s : result) { r.add(s); } return r; } private void mergeUtil(NumberIndex[] nums, int[] result, int low, int high) { if (low == high) { return; } int mid = (low + high)/2; mergeUtil(nums, result, low, mid); mergeUtil(nums, result, mid + 1, high); int i = low; int j = mid + 1; NumberIndex[] t = new NumberIndex[high - low + 1]; int k = 0; int tempResult[] = new int[high - low + 1]; while (i <= mid && j <= high) { if (nums[i].val <= nums[j].val) { tempResult[nums[i].index - low] = j - mid - 1; t[k++] = nums[i++]; } else { tempResult[nums[i].index - low] = j - mid; t[k++] = nums[j++]; } } int i1= i; while (i1 <= mid) { tempResult[nums[i1].index - low] = j - mid - 1; t[k++] = nums[i1++]; } while (j <= high) { t[k++] = nums[j++]; } k = 0; for (i = low; i <= high; i++) { nums[i] = t[k]; result[i] += tempResult[k++]; } } public static void main(String args[]) { CountSmallerOnRight csr = new CountSmallerOnRight(); int nums[] = {5, 2, 6, 1, 0, 3}; List result = csr.countSmaller(nums); result.forEach(r -> System.out.print(r + " ")); } } ================================================ FILE: src/com/interview/array/DivideNumbersInEqualGroupWithClosestSum.java ================================================ package com.interview.array; /** * This solution is incorrect. It is greedy approach which will not work * e.g 1,6,6,8,9,10 - Result should be 1,9,10 and 6,6,8 but it will not give this result * since it will greedily break 9 and 10 into different sets * * INCORRECT SOLUTION.(Still keeping the code in case I can improve it) * */ import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class DivideNumbersInEqualGroupWithClosestSum { public void divide(int arr[],List list1, List list2){ Arrays.sort(arr); int len = arr.length; int sum1 = 0; int sum2 = 0; for(int i = len-1 ; i >=0; i--){ if((sum1 < sum2 && list1.size() < len/2) || (list2.size() >= len/2)){ list1.add(arr[i]); sum1 = sum1 + arr[i]; }else{ list2.add(arr[i]); sum2 = sum2 + arr[i]; } } } public static void main(String args[]){ List list1 = new ArrayList(); List list2 = new ArrayList(); int arr[] = {15,14,13,1,3,2,}; int arr1[] = {23, 45, 34, 12,11, 98, 99, 4, 189, 1,7,19,105, 201}; DivideNumbersInEqualGroupWithClosestSum dn = new DivideNumbersInEqualGroupWithClosestSum(); dn.divide(arr, list1, list2); System.out.println(list1); System.out.println(list2); list1.clear(); list2.clear(); dn.divide(arr1, list1, list2); System.out.println(list1); System.out.println(list2); } } ================================================ FILE: src/com/interview/array/DuplicateNumberDetection.java ================================================ package com.interview.array; /** * Date 03/04/2016 * @author Tushar Roy * * Given an array of size n + 1 with elements from 1 to n. One element is duplicated mulitiple times. * Find that element in O(1) space. Array cannot be changed. * * Reference * https://leetcode.com/problems/find-the-duplicate-number/ */ public class DuplicateNumberDetection { public int findDuplicate(int[] nums) { if (nums.length == 0 || nums.length == 1) { return -1; } int slow = nums[0]; int fast = nums[nums[0]]; while (slow != fast) { slow = nums[slow]; fast = nums[nums[fast]]; } fast = 0; while (slow != fast) { slow = nums[slow]; fast = nums[fast]; } return fast; } public static void main(String args[]) { int[] input = {2,1,3,4,3}; DuplicateNumberDetection dd = new DuplicateNumberDetection(); System.out.println(dd.findDuplicate(input)); } } ================================================ FILE: src/com/interview/array/DuplicateWithinkIndices.java ================================================ package com.interview.array; import java.util.HashSet; import java.util.Set; /** * Write a function that determines whether a array contains duplicate * characters within k indices of each other */ public class DuplicateWithinkIndices { public boolean duplicate(int arr[],int k){ Set visited = new HashSet(); for(int i=0; i < arr.length; i++){ if(visited.contains(arr[i])){ return true; } if(i >= k){ visited.remove(arr[i-k]); } visited.add(arr[i]); } return false; } public static void main(String args[]){ int arr[] = {1,2,3,11,2,5,6}; DuplicateWithinkIndices dk = new DuplicateWithinkIndices(); System.out.println(dk.duplicate(arr, 3)); } } ================================================ FILE: src/com/interview/array/FindElementsOccurringNByKTimesTetris.java ================================================ package com.interview.array; /** * http://www.geeksforgeeks.org/given-an-array-of-of-size-n-finds-all-the-elements-that-appear-more-than-nk-times/ * The reason this algorithm works is there can never be more than k-1 elements of size * more than n/k * * This question does not make much sense. Why not just use a map and keep count and * check if occurrence is more than n/k. This is way too much effort to find elements more than * n by k even though it saves some space. */ public class FindElementsOccurringNByKTimesTetris { public static class Pair{ public int element; public int count; } public void printElementsOccurringKTimes(int arr[],int k){ Pair[] p = new Pair[k]; for(int i=0; i < k; i++){ p[i] = new Pair(); } for(int i=0; i < arr.length; i++){ int j=0; for(j=0; j < k; j++){ if(p[j].element == arr[i]){ p[j].count++; break; } } if(j == k){ int l=0; for(l =0; l < k ; l++){ if(p[l].count == 0){ p[l].element = arr[i]; p[l].count = 1; break; } } if(l == k){ for(int t =0; t < k ; t++){ p[t].count--; } } } } for(int i=0; i < k ; i++){ if(p[i].count > 0){ int count =0; for(int j=0; j < arr.length; j++){ if(arr[j] == p[i].element){ count++; } } if(count >= arr.length/k){ System.out.println(p[i].element); } } } } public static void main(String args[]){ int arr[] = {3,2,2,1,1,2,3,3,4,5,3,1}; FindElementsOccurringNByKTimesTetris fe = new FindElementsOccurringNByKTimesTetris(); fe.printElementsOccurringKTimes(arr, 3); } } ================================================ FILE: src/com/interview/array/FirstPositiveMissing.java ================================================ package com.interview.array; /** * https://leetcode.com/problems/first-missing-positive/ */ public class FirstPositiveMissing { public int firstMissingPositive(int[] nums) { int startOfPositive = segregate(nums); for (int i = startOfPositive; i < nums.length; i++) { int index = Math.abs(nums[i]) + startOfPositive - 1; if (index < nums.length) { nums[index] = -Math.abs(nums[index]); } } for (int i = startOfPositive; i < nums.length; i++) { if (nums[i] > 0) { return i - startOfPositive + 1; } } return nums.length - startOfPositive + 1; } private int segregate(int[] nums) { int start = 0; int end = nums.length -1 ; while (start <= end) { if (nums[start] <= 0) { start++; } else if (nums[end] > 0) { end--; } else { swap(nums, start, end); } } return start; } private void swap(int[] nums, int start, int end) { int t = nums[start]; nums[start] = nums[end]; nums[end] = t; } } ================================================ FILE: src/com/interview/array/Flip0sMaximum1s.java ================================================ package com.interview.array; /** * Date 12/29/2015 * @author Tushar Roy * * Given input array of 0s and 1s and number of flips allowed from 0 to 1, what is maximum consecutive 1s we can have * in array * * Time complexity - O(n) * Space complexity - O(1) * * http://www.geeksforgeeks.org/find-zeroes-to-be-flipped-so-that-number-of-consecutive-1s-is-maximized/ */ public class Flip0sMaximum1s { public int flip0sToMaximizeConsecutive1s(int input[], int flipsAllowed) { int windowStart = 0; int countZero = 0; int result = 0; for (int i = 0 ; i < input.length; i++) { if (input[i] == 1) { result = Math.max(result, i - windowStart + 1); } else { if (countZero < flipsAllowed) { countZero++; result = Math.max(result, i - windowStart + 1); } else { while(true) { if (input[windowStart] == 0) { windowStart++; break; } windowStart++; } } } } return result; } public static void main(String args[]) { int input[] = {0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1}; Flip0sMaximum1s fm = new Flip0sMaximum1s(); System.out.print(fm.flip0sToMaximizeConsecutive1s(input, 1)); } } ================================================ FILE: src/com/interview/array/FourSum.java ================================================ package com.interview.array; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; /** * Date 07/31/2016 * @author Tushar Roy * * Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? * Find all unique quadruplets in the array which gives the sum of target. * * Time complexity O(n^3) * Space complexity O(1) * * Reference * https://leetcode.com/problems/4sum/ */ public class FourSum { public List> fourSum(int[] nums, int target) { if (nums.length < 4) { return Collections.EMPTY_LIST; } Arrays.sort(nums); List> result = new ArrayList<>(); for (int i = 0; i < nums.length - 3; i++) { if (i != 0 && nums[i] == nums[i - 1]) { continue; } if(nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target) { break; } if(nums[i] + nums[nums.length - 3] + nums[nums.length - 2] + nums[nums.length - 1] < target) { continue; } for (int j = i + 1; j < nums.length - 2; j++) { if (j != i + 1 && nums[j] == nums[j - 1]) { continue; } if (nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) { break; } if (nums[i] + nums[j] + nums[nums.length - 1] + nums[nums.length - 1] < target) { continue; } int low = j + 1; int high = nums.length - 1; while (low < high) { if (low != j + 1 && nums[low] == nums[low - 1]) { low++; continue; } if (high != nums.length - 1 && nums[high] == nums[high + 1]) { high--; continue; } int sum = nums[i] + nums[j] + nums[low] + nums[high]; if (sum == target) { List r = new ArrayList<>(); r.add(nums[i]); r.add(nums[j]); r.add(nums[low]); r.add(nums[high]); result.add(r); low++; high--; } else if (sum < target) { low++; } else { high--; } } } } return result; } public static void main(String args[]) { int[] nums = {1, 1, 4, 5, 9, 11}; int[] nums1 = {1, 0, -1, 0, -2, 2}; int target = 0; FourSum fourSum = new FourSum(); List> result = fourSum.fourSum(nums1, target); result.forEach(System.out::print); } } ================================================ FILE: src/com/interview/array/GasStationCircle.java ================================================ package com.interview.array; /** * http://www.geeksforgeeks.org/find-a-tour-that-visits-all-stations/ * You can solve this one using kadane wrap since it finds max contiguous sum * for wrapped array. That start point is a best place to start a tour. * Test cases * Check if length of both input array is same * Check that there exists a path after kadane wrap responds * Check that there is at least one positive difference before you call kadane */ public class GasStationCircle { public int startTour(int gasAvailable[],int gasRequired[]){ int start = -1; int end = 0; int currentGas = 0; boolean visitedOnce = false; while(start != end){ currentGas += gasAvailable[end] - gasRequired[end]; if(start == -1){ start = end; } if(end == gasAvailable.length-1 && visitedOnce == false){ visitedOnce = true; }else if(end == gasAvailable.length-1 && visitedOnce == true){ return -1; } if(currentGas < 0){ start = -1; currentGas = 0; } end = (end + 1)%gasAvailable.length; } return end; } /** * If it is not guaranteed that tour exists then once you get * result of kadanewrap make an actual trip to see if value is positive * @return -1 if no solution exists otherwise returns gas station at which to start. */ public int startTour1(int gasAvailable[], int gasRequired[]){ int diff[] = new int[gasAvailable.length]; for(int i=0; i < diff.length; i++){ diff[i] = gasAvailable[i] - gasRequired[i]; } boolean allNegative = true; for (int i = 0; i < diff.length; i++) { if (diff[i] >= 0) { allNegative = false; break; } } if (allNegative) { return -1; } KadaneWrapArray kwa = new KadaneWrapArray(); Triplet t = kwa.kadaneWrap(diff); //make sure this solution leads to answer int i = t.start; int netGas = 0; do { netGas += diff[i]; i = (i + 1)%diff.length; if (netGas < 0) { return -1; } } while (i != t.start); return t.start; } public static void main(String args[]){ GasStationCircle gsc = new GasStationCircle(); int[] gasAvailable = {4, 4, 6}; int[] gasRequired = {5, 6, 1}; System.out.println(gsc.startTour(gasAvailable, gasRequired)); System.out.println(gsc.startTour1(gasAvailable, gasRequired)); } } ================================================ FILE: src/com/interview/array/GreedyTextJustification.java ================================================ package com.interview.array; import java.util.ArrayList; import java.util.List; /** * Date 03/12/2016 * @author Tushar Roy * * Given an array of words and a length L, format the text such that each line has exactly L characters and is fully * (left and right) justified. * You should pack your words in a greedy approach; that is, pack as many words as you can in each line. * * Time complexity - O(n) where n is the number of words * Space complexity - O(1) * * https://leetcode.com/problems/text-justification/ */ public class GreedyTextJustification { public List fullJustify(String[] words, int maxWidth) { List result = new ArrayList<>(); for (int i = 0; i < words.length; ) { int total = words[i].length(); int j = i + 1; StringBuffer buff = new StringBuffer(); buff.append(words[i]); while(j < words.length && total + words[j].length() + 1 <= maxWidth) { total += words[j].length() + 1; j++; } int remaining = maxWidth - total; //since j is not word length means its not a last line. So pad accordingly. if (j != words.length) { int count = j - i - 1; if (count == 0) { padSpace(buff, remaining); } else { int q = remaining/count; int r = remaining % count; for (int k = i + 1; k < j; k++) { padSpace(buff, q); if (r > 0) { buff.append(" "); r--; } buff.append(" ").append(words[k]); } } } else { //if it is last line then left justify all the words. for (int k = i + 1; k < j; k++) { buff.append(" ").append(words[k]); } padSpace(buff, remaining); } result.add(buff.toString()); i = j; } return result; } private void padSpace(StringBuffer buff, int count) { for (int i = 0; i < count; i++) { buff.append(" "); } } public List fullJustify1(String[] words, int maxWidth) { int currentLength = 0; int prevIndex = 0; List result = new ArrayList<>(); for (int i = 0; i < words.length; i++) { //keep track of length for currentLine. For first word only use length while for remaining words use //lenght + 1 since there will be a space b/w them. currentLength += (words[i].length() + (i == prevIndex ? 0 : 1)); //if currentLength exceeds maxWidth it means currentWord cannot in same line. if (currentLength > maxWidth) { //subtract current word's length from currentLength currentLength -= words[i].length() + 1; StringBuffer builder = new StringBuffer(); //find number of words which will find in the line. int gaps = i - 1 - prevIndex; if (gaps > 0) {//if more than one word fits in the gap. //available number of spaces is below. Subtract gaps because that many spaces have been accounted //for in currentLength. int availableSpace = maxWidth - currentLength + gaps; //first remaining gaps get one extra space. int remaining = availableSpace % gaps; //every gap gets this much extra space. int atleast = availableSpace / gaps; for (int j = prevIndex; j <= i - 2; j++) { builder.append(words[j]); padSpace(builder, atleast); if (j - prevIndex < remaining) { padSpace(builder, 1); } } builder.append(words[i - 1]); } else { //if only one word can fit in a one line then left specify it. builder.append(words[i - 1]); padSpace(builder, maxWidth - words[i - 1].length()); } result.add(builder.toString()); prevIndex = i; currentLength = words[i].length(); } } //handle the last line. Left justify the remaining words if (prevIndex < words.length) { StringBuffer builder = new StringBuffer(); int count = 0; while (prevIndex < words.length) { builder.append(words[prevIndex]).append(" "); count += words[prevIndex].length() + 1; prevIndex++; } count--; //delete extra space added by above for looop. builder.deleteCharAt(builder.length() - 1); //whatever spae is left just put it at the end. padSpace(builder, maxWidth - count); result.add(builder.toString()); } return result; } public static void main(String args[]) { String[] input = {"What","must","be","shall","be."}; GreedyTextJustification gtj = new GreedyTextJustification(); List result = gtj.fullJustify(input, 12); System.out.print(result); } } ================================================ FILE: src/com/interview/array/GroupElementsInSizeM.java ================================================ package com.interview.array; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.PriorityQueue; /** * http://www.careercup.com/question?id=6026101998485504 * This answer two questions. * Group elements in size m such that in every group only unique elements are possible. * It also answers question where rearrange array such that same elements are exactly m * distance from each other */ class Pair{ int num; int count; Pair(int num,int count){ this.count = count; this.num = num; } } class Comparators implements Comparator{ @Override public int compare(Pair o1, Pair o2) { if(o1.count <= o2.count){ return 1; }else{ return -1; } } } public class GroupElementsInSizeM { public boolean group(int input[],int m){ Map count = new HashMap(); for(Integer i : input){ int c = 1; if(count.containsKey(i)){ c = count.get(i); c++; } count.put(i, c); } PriorityQueue maxHeap = new PriorityQueue(count.size(),new Comparators()); for(Integer s : count.keySet()){ int c = count.get(s); //if any count is greater than len/m then this arrangement is not possible if(c > Math.ceil(input.length*1.0/m)){ return false; } maxHeap.offer(new Pair(s,c)); } int current = 0; int start = current; while(maxHeap.size() > 0){ Pair p = maxHeap.poll(); int i =0; while(i < p.count){ input[start] = p.num; start = start + m; if(start >= input.length){ current++; start = current; } i++; } } return true; } public static void main(String args[]){ int input[] = {2,1,5,1,3,5,3,3,4}; int input1[] = {1,2,3,8,8,8,7,8}; GroupElementsInSizeM gps = new GroupElementsInSizeM(); boolean r = gps.group(input1, 3); System.out.println(r); for(int i=0; i < input1.length; i++){ System.out.println(input1[i]); } } } ================================================ FILE: src/com/interview/array/HIndex.java ================================================ package com.interview.array; /** * Given an array of citations (each citation is a non-negative integer) of a researcher, * write a function to compute the researcher's h-index. * https://leetcode.com/problems/h-index/ */ public class HIndex { public int hIndex(int[] citations) { int[] count = new int[citations.length + 1]; for (int c : citations) { if (c <= citations.length) { count[c]++; } else { count[citations.length]++; } } int sum = 0; int max = 0; for (int i = 0; i < count.length; i++) { sum += count[i]; //we are trying to see if i is answer. //already everything before i has less than i citations. //so only thing to check is that p >= i where p is //total number of papers with i or more citations. int p = citations.length - sum + count[i]; if (i <= p) { max = i; } } return max; } public static void main(String args[]) { HIndex hi = new HIndex(); int[] input = {0, 1, 1, 1, 1, 6, 7 ,8}; System.out.print(hi.hIndex(input)); } } //0 1 2 6 6 6 6 7 //0 1 2 3 4 5 6 7 //0 1 1 1 3 6 7 8 //0 1 2 3 4 5 6 7 //0 1 2 5 6 ================================================ FILE: src/com/interview/array/IncreasingSubsequnceOfLength3WithMaxProduct.java ================================================ package com.interview.array; /** * http://www.geeksforgeeks.org/increasing-subsequence-of-length-three-with-maximum-product/ * Keep two arrays which keeps max from current position to right side * Other array keeps max on left size which is smaller than current element * Once you have these two arrays from 2nd to 2nd last position keep multiplying * elements at 3 arrays index position to get max product * Test cases * Negative numbers * 0 in the input */ public class IncreasingSubsequnceOfLength3WithMaxProduct { public int maxProduct(int arr[]){ int RGN[] = new int[arr.length]; int LGN[] = new int[arr.length]; RGN[arr.length-1] = arr[arr.length-1]; int max = arr[arr.length-1]; for(int i=arr.length-2; i>=0; i--){ if(max < arr[i]){ max = arr[i]; } if(max > arr[i]){ RGN[i] = max; } else{ RGN[i] = 0; } } LGN[0] = 0; //This can be implemented using an AVL tree instead of this way which will //make it O(nLogn) operation insteado ofO(n2). for(int i=1; i < arr.length; i++){ getLGN(arr,i,LGN); } int maxProduct = 0; for(int i=1; i < arr.length-1; i++){ int product = arr[i]*LGN[i]*RGN[i]; if(maxProduct < product){ maxProduct = product; } } return maxProduct; } private void getLGN(int arr[],int pos,int LGN[]){ int max = 0; int i =0; while(i < pos){ if(arr[i] < arr[pos]){ if(arr[i] > max){ max = arr[i]; } } i++; } LGN[pos] = max; } public static void main(String args[]){ int arr[] = {6, 7, 8, 1, 2, 3, 9, 10}; IncreasingSubsequnceOfLength3WithMaxProduct iss = new IncreasingSubsequnceOfLength3WithMaxProduct(); System.out.println(iss.maxProduct(arr)); int arr1[] = {1, 5, 10, 8, 9}; System.out.println(iss.maxProduct(arr1)); } } ================================================ FILE: src/com/interview/array/IncreasingTripletSubsequence.java ================================================ package com.interview.array; /** * Date 03/06/2016 * @author Tushar Roy * * Find if there exists an increasing triplet subsequence. * Similar method to longest increasing subsequence in nlogn time. * * Time complexity is O(n) * Space complexity is O(1) * * https://leetcode.com/problems/increasing-triplet-subsequence/ */ public class IncreasingTripletSubsequence { public boolean increasingTriplet(int[] nums) { int T[] = new int[3]; int len = 0; for (int i = 0; i < nums.length; i++) { boolean found = false; for (int j = 0; j < len; j++) { if (T[j] >= nums[i]) { T[j] = nums[i]; found = true; break; } } if (!found) { T[len++] = nums[i]; } if (len == 3) { return true; } } return false; } public static void main(String args[]) { IncreasingTripletSubsequence tripletSubsequence = new IncreasingTripletSubsequence(); int input[] = {9, 10, -2, 12, 6, 7, -1}; System.out.print(tripletSubsequence.increasingTriplet(input)); } } ================================================ FILE: src/com/interview/array/JumpGame.java ================================================ package com.interview.array; /** * Date 07/31/2016 * @author Tushar Roy * * Given an array of non-negative integers, you are initially positioned at the first index of the array. * Each element in the array represents your maximum jump length at that position. * Determine if you are able to reach the last index. * * Time complexity O(n) * Space complexity O(1) * * https://leetcode.com/problems/jump-game/ * * Given an array of non-negative integers, you are initially positioned at the first index of the array. * Each element in the array represents your maximum jump length at that position. * Your goal is to reach the last index in the minimum number of jumps. * * Time complexity O(n) * Space complexity O(1) * * https://leetcode.com/problems/jump-game-ii/ */ public class JumpGame { public boolean canJump(int[] nums) { int jump = 0; int i; for (i = 0; i < nums.length && i <= jump; i++) { jump = Math.max(jump, i + nums[i]); } return i == nums.length; } public int jump(int[] nums) { int current = 0; int max = 0; int count = 0; for (int i = 0; i < nums.length - 1; i++) { max = Math.max(max, i + nums[i]); if (current == i) { count++; current = max; } } return count; } public static void main(String args[]) { JumpGame jumpGame = new JumpGame(); int[] nums = {3, 2, 3, 0, 2, 1}; System.out.println(jumpGame.jump(nums)); int[] nums1 = {3, 0, 2, 0, 0, 1}; System.out.println(jumpGame.canJump(nums1)); } } ================================================ FILE: src/com/interview/array/KadaneWrapArray.java ================================================ package com.interview.array; /** * http://www.geeksforgeeks.org/maximum-contiguous-circular-sum/ * Test cases * All negative * All positives * all 0s */ class Triplet{ int start; int end; int sum; @Override public String toString() { return "Triplet [start=" + start + ", end=" + end + ", sum=" + sum + "]"; } } public class KadaneWrapArray { public Triplet kadaneWrap(int arr[]){ Triplet straightKadane = kadane(arr); int sum =0; for(int i=0; i < arr.length; i++){ sum += arr[i]; arr[i] = -arr[i]; } Triplet wrappedNegKadane = kadane(arr); for(int i=0; i < arr.length; i++){ arr[i] = -arr[i]; } if(straightKadane.sum < sum + wrappedNegKadane.sum){ straightKadane.sum = wrappedNegKadane.sum + sum; straightKadane.start = wrappedNegKadane.end+1; straightKadane.end = wrappedNegKadane.start-1; } return straightKadane; } /** * This method assumes there is at least one positive number in the array. * Otherwise it will break * @param arr * @return */ public Triplet kadane(int arr[]){ int sum =0; int cStart = 0; int mStart = 0; int end = 0; int maxSum = Integer.MIN_VALUE; for(int i=0; i < arr.length; i++){ sum += arr[i]; if(sum <= 0){ sum = 0; cStart = i+1; }else{ if(sum > maxSum){ maxSum = sum; mStart = cStart; end = i; } } } Triplet p = new Triplet(); p.sum = maxSum; p.start = mStart; p.end = end; return p; } public static void main(String args[]){ KadaneWrapArray kwa = new KadaneWrapArray(); int input[] = {12, -2, -6, 5, 9, -7, 3}; int input1[] = {8, -8, 9, -9, 10, -11, 12}; System.out.println(kwa.kadaneWrap(input)); System.out.println(kwa.kadaneWrap(input1)); } } ================================================ FILE: src/com/interview/array/KthElementInArray.java ================================================ package com.interview.array; import java.util.Arrays; /** * Kth largest element in an array. * Use quickselect of quicksort to find the solution in hopefully O(nlogn) time. * Test cases * Sorted array * Reverse sorted array */ public class KthElementInArray { public int kthElement(int arr[],int k){ int low = 0; int high = arr.length-1; int pos =0; while(true){ pos = quickSelect(arr,low,high); if(pos == (k+low)){ return arr[pos]; } if(pos > k + low){ high = pos-1; }else{ k = k - (pos - low + 1); low = pos+1; } } } private int quickSelect(int arr[],int low,int high){ int pivot = low; low++; while(low <= high){ if(arr[pivot] > arr[low]){ low++; continue; } if(arr[pivot] <= arr[high]){ high--; continue; } swap(arr,low,high); } if(arr[high] < arr[pivot]){ swap(arr,pivot,high); } return high; } private void swap(int arr[],int low,int high){ int temp = arr[low]; arr[low] = arr[high]; arr[high] = temp; } public static void main(String args[]){ int arr[] = {6, 2, 1, 6, 8, 9, 6}; KthElementInArray kthElement = new KthElementInArray(); System.out.print(kthElement.kthElement(arr, arr.length/2)); System.out.print(Arrays.toString(arr)); } } ================================================ FILE: src/com/interview/array/KthLargestInTwoSortedArray.java ================================================ package com.interview.array; /** * http://stackoverflow.com/questions/4686823/given-2-sorted-arrays-of-integers-find-the-nth-largest-number-in-sublinear-time * http://articles.leetcode.com/2011/01/find-k-th-smallest-element-in-union-of.html */ public class KthLargestInTwoSortedArray { public int kthLargest1(int arr1[],int arr2[],int low1,int high1,int low2,int high2,int k){ int len1 = high1-low1 +1; int len2 = high2 - low2+1; if(len1 == 0){ return arr2[low2+k]; } if(len2 ==0){ return arr1[low1+k]; } if(k == 0){ return Math.min(arr1[low1], arr2[low2]); } int mid1 = len1*k/(len1 + len2); int mid2 = k - mid1 - 1; mid1 = low1+mid1; mid2 = low2 + mid2; if(arr1[mid1] > arr2[mid2]){ k = k - mid2 + low2 -1; high1 = mid1; low2 = mid2 + 1; }else{ k = k - mid1 + low1 -1; high2 = mid2; low1 = mid1+1; } return kthLargest(arr1, arr2, low1, high1, low2, high2, k); } public int kthLargest(int input1[],int input2[],int k){ return kthLargest(input1, input2, 0, input1.length-1, 0, input2.length-1, k); } private int kthLargest(int input1[],int input2[],int l1, int h1, int l2,int h2,int k){ if(l1 > h1){ return input2[k-1]; } if(l2 > h2){ return input1[k-1]; } if((h1 - l1 + 1) + (h2 - l2 + 1) == k){ return Math.max(input1[h1], input2[h2]); } if(k == 1){ return Math.min(input1[l1],input2[l2]); } //handle the situation where only one element is left //in either of array. //e.g k =2 and arr1 = 8 arr2 = 1,9,11 //we try to find if 8 is before 9 betweenn 1 and 9 //or before 1. In all these cases k will be either //1 8 or 9 if(l2 == h2 || l1 == h1){ if(l2 == h2){ if(input1[l1+k-1] < input2[l2]){ return input1[l1+k-1]; }else if(input1[l1+k-2] > input2[l2]){ return input1[l1+k-2]; }else{ return input2[l2]; } } if(l1 == h1){ if(input2[l2+k-1] < input1[l1]){ return input2[l2+k-1]; }else if(input2[l2+k-2] > input1[l1]){ return input2[l2+k-2]; }else{ return input1[l1]; } } } int m1 = (h1 + l1)/2; int m2 = (h2 + l2)/2; int diff1 = m1 - l1+1; int diff2 = m2 - l2+1; if(diff1 + diff2 >= k){ if(input1[m1] < input2[m2]){ return kthLargest(input1, input2, l1, h1, l2, m2, k); }else{ return kthLargest(input1, input2, l1, m1, l2, h2, k); } }else{ if(input1[m1] < input2[m2]){ return kthLargest(input1, input2,m1+1, h1, l2, h2, k - diff1); }else{ return kthLargest(input1, input2, l1, h1, m2+1, h2, k -diff2); } } } public static void main(String args[]){ KthLargestInTwoSortedArray kis = new KthLargestInTwoSortedArray(); int input1[] = {1,4,7,11,17,21}; int input2[] = {-4,-1,3,4,6,28,35,41,56,70}; for(int i = 0; i < input1.length + input2.length; i++){ System.out.println(kis.kthLargest(input1, input2, i+1)); } // System.out.println(kis.kthLargest(input1, input2, 6)); } } ================================================ FILE: src/com/interview/array/LargerElementOnRight.java ================================================ package com.interview.array; import java.util.Deque; import java.util.LinkedList; /** * http://www.geeksforgeeks.org/next-greater-element/ * Find next larger element on right side of a number in array for * all positions in array * This is different than finding largest element on right side which can * be done by keeping max while iterating from right * It is also different from find next higher number on right side which can * be found by keeping AVL tree and finding ceiling. */ public class LargerElementOnRight { public int[] larger(int input[]){ Deque stack = new LinkedList(); int result[] = new int[input.length]; for(int i=0; i < result.length; i++){ result[i] = -1; } stack.offerFirst(0); for(int i=1; i < input.length; i++){ while(stack.size() > 0){ int t = stack.peekFirst(); if(input[t] < input[i]){ result[t] = i; stack.pollFirst(); }else{ break; } } stack.offerFirst(i); } return result; } public static void main(String args[]){ LargerElementOnRight leo = new LargerElementOnRight(); int input[] = {4,2,-8,6,0,-3,-1,1,9}; int result[] = leo.larger(input); for(int i=0; i < result.length; i++){ if(result[i] != -1){ System.out.print(input[result[i]] + " "); }else{ System.out.print("NIL "); } } } } ================================================ FILE: src/com/interview/array/LargestMountain.java ================================================ package com.interview.array; /** * https://leetcode.com/problems/longest-mountain-in-array/description/ */ public class LargestMountain { public int longestMountain(int[] nums) { int start = 0; int max = 0; State state = State.STARTED; for (int i = 1; i < nums.length; i++) { if (nums[i] == nums[i - 1]) { start = i; state = State.STARTED; } else if (nums[i] > nums[i - 1]) { if (state == State.DECREASING || state == State.STARTED) { start = i - 1; state = State.INCREASING; } } else { if (state == State.INCREASING || state == State.DECREASING) { state = State.DECREASING; max = Math.max(max, i - start + 1); } else { start = i; } } } return max; } enum State { STARTED, INCREASING, DECREASING; } public static void main(String[] args) { LargestMountain lm = new LargestMountain(); int[] nums = {2, 1, 4, 7, 3, 2, 5}; System.out.println(lm.longestMountain(nums)); } } ================================================ FILE: src/com/interview/array/LargestSubArrayWithEqual0sAnd1s.java ================================================ package com.interview.array; import java.util.HashMap; import java.util.Map; /** * http://www.geeksforgeeks.org/largest-subarray-with-equal-number-of-0s-and-1s/ * Test cases * Starting with either 0 or 1 * Maximum length of 0 1 2 or more * */ public class LargestSubArrayWithEqual0sAnd1s { public int equalNumber(int arr[]){ int sum[] = new int[arr.length]; sum[0] = arr[0] == 0? -1 : 1; for(int i=1; i < sum.length; i++){ sum[i] = sum[i-1] + (arr[i] == 0? -1 : 1); } Map pos = new HashMap(); int maxLen = 0; int i = 0; for(int s : sum){ if(s == 0){ maxLen = Math.max(maxLen, i+1); } if(pos.containsKey(s)){ maxLen = Math.max(maxLen, i-pos.get(s)); }else{ pos.put(s, i); } i++; } return maxLen; } public static void main(String args[]){ int arr[] = {0,0,0,1,0,1,0,0,1,0,0,0}; LargestSubArrayWithEqual0sAnd1s mse = new LargestSubArrayWithEqual0sAnd1s(); System.out.println(mse.equalNumber(arr)); } } ================================================ FILE: src/com/interview/array/LeetCodeCandy.java ================================================ package com.interview.array; /** * References * https://leetcode.com/problems/candy/ */ public class LeetCodeCandy { public int candy(int[] ratings) { int pointOfChange = 0; int totalCandies = 1; int currentCandy = 1; boolean isIndependent = true; int maxHeight = 0; int diff = 0; for (int i = 1; i < ratings.length; i++) { diff = 0; if (ratings[i] > ratings[i-1]) { currentCandy += 1; } else if (ratings[i] == ratings[i-1]) { isIndependent = true; pointOfChange = i; currentCandy = 1; } else { if (currentCandy == 1) { if (!isIndependent) { if (i - pointOfChange == maxHeight - 1) { pointOfChange--; } } } else { maxHeight = currentCandy; currentCandy = 1; isIndependent = false; pointOfChange = i; } diff = i - pointOfChange; } totalCandies += (diff + currentCandy); } return totalCandies; } } ================================================ FILE: src/com/interview/array/LongestConsecutiveSubsequence.java ================================================ package com.interview.array; import java.util.HashMap; import java.util.Map; /** * Date 12/03/2016 * @author Tushar Roy * * Find longest consecutive subsequence in unsorted array. * * Time complexity O(n) * Space complexity O(n) * * Reference * https://leetcode.com/problems/longest-consecutive-sequence/ */ public class LongestConsecutiveSubsequence { public int longestConsecutive(int[] nums) { Map map = new HashMap(); int result = 1; for (int i : nums) { if (map.containsKey(i)) { continue; } int left = map.containsKey(i - 1) ? map.get(i - 1) : 0; int right = map.containsKey(i + 1) ? map.get(i + 1) : 0; int sum = left + right + 1; map.put(i, sum); result = Math.max(sum, result); map.put(i - left, sum); map.put(i + right, sum); } return result; } public static void main(String args[]) { LongestConsecutiveSubsequence lcs = new LongestConsecutiveSubsequence(); int[] input = {100, 4, 200, 1, 3, 2}; System.out.println(lcs.longestConsecutive(input)); } } ================================================ FILE: src/com/interview/array/LongestIncreasingSubSequenceOlogNMethod.java ================================================ package com.interview.array; import java.util.Arrays; /** * Date 08/01/2015 * @author Tushar Roy * * Given an array, find longest increasing subsequence in nlogn time complexity * * References * http://www.geeksforgeeks.org/longest-monotonically-increasing-subsequence-size-n-log-n/ * http://www.geeksforgeeks.org/construction-of-longest-monotonically-increasing-subsequence-n-log-n/ */ public class LongestIncreasingSubSequenceOlogNMethod { /** * Returns index in T for ceiling of s */ private int ceilIndex(int input[], int T[], int end, int s){ int start = 0; int middle; int len = end; while(start <= end){ middle = (start + end)/2; if(middle < len && input[T[middle]] < s && s <= input[T[middle+1]]){ return middle+1; }else if(input[T[middle]] < s){ start = middle+1; }else{ end = middle-1; } } return -1; } public int longestIncreasingSubSequence(int input[]){ int T[] = new int[input.length]; int R[] = new int[input.length]; for(int i=0; i < R.length ; i++) { R[i] = -1; } T[0] = 0; int len = 0; for(int i=1; i < input.length; i++){ if(input[T[0]] > input[i]){ //if input[i] is less than 0th value of T then replace it there. T[0] = i; }else if(input[T[len]] < input[i]){ //if input[i] is greater than last value of T then append it in T len++; T[len] = i; R[T[len]] = T[len-1]; }else{ //do a binary search to find ceiling of input[i] and put it there. int index = ceilIndex(input, T, len,input[i]); T[index] = i; R[T[index]] = T[index-1]; } } //this prints increasing subsequence in reverse order. System.out.print("Longest increasing subsequence "); int index = T[len]; while(index != -1) { System.out.print(input[index] + " "); index = R[index]; } System.out.println(); return len+1; } public static void main(String args[]){ //int input[] = {2,5,3,1,2,10,6,7,8}; int input[] = {3, 4, -1, 5, 8, 2, 3, 12, 7, 9, 10}; LongestIncreasingSubSequenceOlogNMethod lis = new LongestIncreasingSubSequenceOlogNMethod(); System.out.println("Maximum length " + lis.longestIncreasingSubSequence(input)); } } ================================================ FILE: src/com/interview/array/LongestSameSumSpan.java ================================================ package com.interview.array; import java.util.HashMap; import java.util.Map; /** * Date 12/29/2015 * @author Tushar Roy * * Give two arrays of same size consisting of 0s and 1s find span (i, j) such that * sum of input1[i..j] = sum of input2[i..j] * * Time complexity O(n) * Space complexity O(n) * * http://www.geeksforgeeks.org/longest-span-sum-two-binary-arrays/ */ public class LongestSameSumSpan { public int longestSpan(int input1[], int input2[]) { if (input1.length != input2.length) { throw new IllegalArgumentException("Not same length input"); } Map diff = new HashMap<>(); int prefix1 = 0, prefix2 = 0; int maxSpan = 0; diff.put(0, -1); for (int i = 0; i < input1.length ; i++) { prefix1 += input1[i]; prefix2 += input2[i]; int currDiff = prefix1 - prefix2; if (diff.containsKey(currDiff)) { maxSpan = Math.max(maxSpan, i - diff.get(currDiff)); } else { diff.put(currDiff, i); } } return maxSpan; } public static void main(String args[]) { int input1[] = {1, 0, 0, 1, 1, 0}; int input2[] = {0, 1, 1, 0, 1, 1}; LongestSameSumSpan lsss = new LongestSameSumSpan(); System.out.print(lsss.longestSpan(input1, input2)); } } ================================================ FILE: src/com/interview/array/LongestSubstringWithAtMost2Char.java ================================================ package com.interview.array; /** * Longest Substring with At Most Two Distinct Characters * https://leetcode.com/problems/longest-substring-with-at-most-two-distinct-characters/ */ public class LongestSubstringWithAtMost2Char { public int lengthOfLongestSubstringTwoDistinct(String s) { int count1 = 0; int count2 = 0; char c1 = 0; char c2 = 0; int start = 0; int current = 0; int max = 0; for (char ch: s.toCharArray()) { if (ch == c1 || ch == c2) { if (ch == c1) { count1++; } else { count2++; } } else { if (count1 != 0 && count2 != 0) { while (start < current) { if (s.charAt(start) == c1) { count1--; } else if (s.charAt(start) == c2) { count2--; } start++; if (count1 == 0 || count2 == 0) { break; } } } if (count1 == 0) { c1 = ch; count1 = 1; } else { c2 = ch; count2 = 1; } } max = Math.max(max, current - start + 1); current++; } return max; } public static void main(String args[]) { LongestSubstringWithAtMost2Char lc = new LongestSubstringWithAtMost2Char(); System.out.print(lc.lengthOfLongestSubstringTwoDistinct("eceba")); } } ================================================ FILE: src/com/interview/array/MaxNumberFromTwoArray.java ================================================ package com.interview.array; import java.util.Arrays; import java.util.Deque; import java.util.LinkedList; /** * Date 03/01/2016 * @author Tushar Roy * * Given two arrays of length m and n with digits 0-9 representing two numbers. * Create the maximum number of length k <= m + n from digits of the two * * e.g * nums1 = [3, 4, 6, 5] * nums2 = [9, 1, 2, 5, 8, 3] * k = 5 * return [9, 8, 6, 5, 3] * * https://leetcode.com/problems/create-maximum-number/ */ public class MaxNumberFromTwoArray { public int[] maxNumber(int[] nums1, int[] nums2, int k) { int[] max = new int[k]; for (int i = 0; i <= k; i++) { if (nums1.length < i || nums2.length < k - i) { continue; } int[] a = merge(findLargest1(nums1, i), findLargest1(nums2, k - i)); if (isGreater(a, max, 0, 0)) { max = a; } } return max; } private int[] merge(int[] a1, int[] a2) { int[] result = new int[a1.length + a2.length]; int i = 0; int j = 0; int k = 0; while (i < a1.length || j < a2.length) { if (i == a1.length) { result[k++] = a2[j++]; } else if (j == a2.length) { result[k++] = a1[i++]; } else if (a1[i] > a2[j]) { result[k++] = a1[i++]; } else if (a1[i] < a2[j]) { result[k++] = a2[j++]; } else { if (isGreater(a1, a2, i, j)) { result[k++] = a1[i++]; } else { result[k++] = a2[j++]; } } } return result; } private boolean isGreater(int[] a, int[] b, int i, int j) { while (i < a.length && j < b.length) { if (a[i] > b[j]) { return true; } else if (a[i] < b[j]) { return false; } i++; j++; } return j == b.length; } private int[] findLargest1(int[] nums, int k) { if (k == 0) { return new int[0]; } int[] result = new int[k]; int index = 0; for (int i = 0; i < nums.length; i++) { while (index > 0 && index + (nums.length - i - 1) >= k && result[index - 1] < nums[i]) { index--; } if (index < k) { result[index++] = nums[i]; } } return result; } public static void main(String args[]) { MaxNumberFromTwoArray max = new MaxNumberFromTwoArray(); int[] input1 = {9,1,2,5,8,3}; int[] input2 = {3,4,6,5}; int[] input3 = {2,5,6,4,4,0}; int[] input4 = {7,3,8,0,6,5,7,6,2}; int[] result = max.maxNumber(input3, input4, 15); System.out.print(Arrays.toString(result)); } } ================================================ FILE: src/com/interview/array/MaxProductSubarray.java ================================================ package com.interview.array; /** * Date 04/`7/2016 * @author Tushar Roy * * Find the contiguous subarray within an array (containing at least one number) which has the largest product. * * Time complexity is O(n) * Space complexity is O(1) * * http://www.geeksforgeeks.org/maximum-product-subarray/ * https://leetcode.com/problems/maximum-product-subarray/ */ public class MaxProductSubarray { public int maxProduct(int[] nums) { //neg maintains the multiplication which is negative since last 0 //pos maintains the multiplication which is positive since last 0 int neg = 1; int pos = 1; int maxProduct = nums[0]; for (int i = 0; i < nums.length; i++) { if (nums[i] == 0) { neg = 1; pos = 1; maxProduct = Math.max(maxProduct, 0); } else if (nums[i] < 0) { int temp = pos; if (neg < 0) { pos = neg * nums[i]; maxProduct = Math.max(pos, maxProduct); } else { pos = 1; } neg = temp * nums[i]; } else { if (neg < 0) { neg *= nums[i]; } pos *= nums[i]; maxProduct = Math.max(pos, maxProduct); } } return maxProduct; } public static void main(String args[]){ MaxProductSubarray mps = new MaxProductSubarray(); int input[] = {-6, -3, 8, -9, -1, -1, 3, 6, 9, 0, 3, -1}; System.out.println(mps.maxProduct(input)); } } ================================================ FILE: src/com/interview/array/MaxRepeatingNumber.java ================================================ package com.interview.array; /** * http://www.geeksforgeeks.org/find-the-maximum-repeating-number-in-ok-time/ * Given an array of size n, the array contains numbers in range from 0 to k-1 * where k is a positive integer and k <= n. * Find the maximum repeating number in this array */ public class MaxRepeatingNumber { public int maxRepeatingNumber(int arr[], int k){ int len = k; for(int i=0; i < arr.length; i++){ arr[arr[i]%len] += len; } int maxRepeating = 0; int maxRepeatingIndex =0; for(int i=0; i < len; i++){ if(maxRepeating < arr[i]){ maxRepeating = arr[i]; maxRepeatingIndex = i; } } for(int i=0; i < len; i++){ arr[i] = arr[i] % len; } return maxRepeatingIndex; } public static void main(String args[]){ MaxRepeatingNumber mrn = new MaxRepeatingNumber(); int arr[] = {2,2,1,3,1,2,0,3,0,0,0,4,5,4,4,4,4}; System.out.println(mrn.maxRepeatingNumber(arr, 6)); } } ================================================ FILE: src/com/interview/array/MaximumGap.java ================================================ package com.interview.array; /** * Date 03/12/2016 * @author Tushar Roy * * Given an unsorted array find maximum gap between consecutive element in sorted array. * * Time complexity O(n) * Space complexity O(n) * * Reference * https://leetcode.com/problems/maximum-gap/ */ public class MaximumGap { class Bucket { int low ; int high; boolean isSet = false; void update(int val) { if (!isSet) { low = val; high = val; isSet = true; } else { low = Math.min(low, val); high = Math.max(high, val); } } } public int maximumGap(int[] input) { if (input == null || input.length < 2) { return 0; } int min = Integer.MAX_VALUE; int max = Integer.MIN_VALUE; for (int i = 0; i < input.length; i++) { min = Math.min(min, input[i]); max = Math.max(max, input[i]); } int gap = (int) Math.ceil((double) (max - min) / (input.length - 1)); Bucket[] buckets = new Bucket[input.length - 1]; for (int i = 0; i < buckets.length; i++) { buckets[i] = new Bucket(); } for (int i = 0; i < input.length; i++) { if (input[i] == max || input[i] == min) { continue; } buckets[(input[i] - min) / gap].update(input[i]); } int prev = min; int maxGap = 0; for (int i = 0; i < buckets.length; i++) { if (!buckets[i].isSet) { continue; } maxGap = Math.max(maxGap, buckets[i].low - prev); prev = buckets[i].high; } return Math.max(maxGap, max - prev); } public static void main(String args[]) { int[] input = {4, 3, 13, 2, 9, 7}; MaximumGap mg = new MaximumGap(); System.out.println(mg.maximumGap(input)); } } ================================================ FILE: src/com/interview/array/MaximumIminusJSuchThatAiGTAj.java ================================================ package com.interview.array; import java.util.Iterator; import java.util.LinkedList; /** * http://www.geeksforgeeks.org/given-an-array-arr-find-the-maximum-j-i-such-that-arrj-arri/ */ public class MaximumIminusJSuchThatAiGTAj { class Node{ int index; int size; } public int maximumGeeks(int input[]){ int lhs[] = new int[input.length]; int rhs[] = new int[input.length]; lhs[0] = 0; for(int i=1; i < lhs.length; i++){ if(input[lhs[i-1]] < input[i]){ lhs[i] = lhs[i-1]; }else{ lhs[i] = i; } } rhs[input.length-1] = input.length-1; for(int i=input.length-2; i >= 0; i--){ if(input[rhs[i+1]] > input[i]){ rhs[i] = rhs[i+1]; }else{ rhs[i] = i; } } int i=0; int j=0; int max = 0; for(;j < input.length;){ if(input[lhs[i]] < input[rhs[j]]){ max = Math.max(max, j-i); j++; }else{ i++; } } return max; } public static void main(String args[]){ MaximumIminusJSuchThatAiGTAj mj = new MaximumIminusJSuchThatAiGTAj(); int input[] = {11,14,13,1,4,13,1,10}; System.out.println(mj.maximumGeeks(input)); } } ================================================ FILE: src/com/interview/array/MaximumMinimumArrangement.java ================================================ package com.interview.array; /** * Date 04/16/2016 * @author Tushar Roy * * Given a sorted array of positive integers, rearrange the array alternately i.e first element should be maximum value, * second minimum value, third second max, fourth second min and so on. * * Time complexity O(n) * Space complexity O(1) * * http://www.geeksforgeeks.org/rearrange-array-maximum-minimum-form/ */ public class MaximumMinimumArrangement { public void rearrange(int[] input) { for (int i = 0; i < input.length; i++) { int t = input[i]; if (t < 0) { continue; } int i1 = i; while (true) { int j = i1 < input.length/2 ? 2 * i1 + 1 : (input.length - 1 - i1) * 2; if (j == i1) { break; } if (input[j] < 0) { break; } int t1 = input[j]; input[j] = -t; t = t1; i1 = j; } } for (int i = 0; i < input.length; i++) { input[i] = Math.abs(input[i]); } } } ================================================ FILE: src/com/interview/array/MaximumOfSubarrayOfSizeK.java ================================================ package com.interview.array; /** * http://www.geeksforgeeks.org/maximum-of-all-subarrays-of-size-k/ * Test cases * input containg neg and pos values * val of k is neg 0 or pos * val of k is larger than size of input * val of k is same as size of input */ import java.util.Deque; import java.util.LinkedList; public class MaximumOfSubarrayOfSizeK { public int[] maxSubArray(int input[], int k) { Deque queue = new LinkedList(); int max[] = new int[input.length - k + 1]; int maxVal = Integer.MIN_VALUE; //first find max of first k values and make it 0th element of max array for (int i = 0; i < k; i++) { if(maxVal < input[i]){ maxVal = input[i]; } if (queue.isEmpty()) { queue.offerLast(i); } else { while (!queue.isEmpty() && input[queue.peekLast()] <= input[i]) { queue.pollLast(); } queue.offerLast(i); } } max[0] = maxVal; int index=1; //continue from k till end of the input array for (int i = k; i < input.length; i++) { //if index of peek is k distance from i then its no value to us. //throw it away if (i - k + 1 > queue.peekFirst()) { queue.pollFirst(); } while (!queue.isEmpty() && input[queue.peekLast()] <= input[i]) { queue.pollLast(); } queue.offerLast(i); //Only reason first element survived was because it was biggest element. //make it the max value for this k max[index] = input[queue.peekFirst()]; index++; } return max; } public static void main(String args[]){ int input[] = {8, 5, 10, 7, 9, 4, 15, 12, 90, 13}; MaximumOfSubarrayOfSizeK msa = new MaximumOfSubarrayOfSizeK(); int max[] = msa.maxSubArray(input, 4); for(int i : max){ System.out.print(i + " "); } } } ================================================ FILE: src/com/interview/array/MaximumSumPathTwoArrays.java ================================================ package com.interview.array; /** * Date 12/31/2015 * @author Tushar Roy * * Given two sorted arrays such the arrays may have some common elements. Find the sum of the maximum sum * path to reach from beginning of any array to end of any of the two arrays. We can switch from one array * to another array only at common elements. * * Time complexity is O(n + m) * Space complexity is O(1) * * http://www.geeksforgeeks.org/maximum-sum-path-across-two-arrays/ */ public class MaximumSumPathTwoArrays { public int maxSum(int input1[], int input2[]) { int maxSum = 0; int i = 0, j = 0; int sum1 = 0; int sum2 = 0; while (i < input1.length && j < input2.length) { if (input1[i] == input2[j]) { if (sum1 > sum2) { maxSum += sum1 + input1[i]; } else { maxSum += sum2 + input2[j]; } i++; j++; sum1 = 0; sum2 = 0; } else if (input1[i] < input2[j]) { sum1 += input1[i++]; } else { sum2 += input2[j++]; } } while(i < input1.length) { sum1 += input1[i++]; } while(j < input2.length) { sum2 += input2[j++]; } if (sum1 > sum2) { maxSum += sum1; } else { maxSum += sum2; } return maxSum; } public static void main(String args[]) { int input1[] = {2, 3, 7, 10, 12, 15, 30, 34}; int input2[] = {1, 5, 7, 8, 10, 15, 16, 19}; MaximumSumPathTwoArrays msp = new MaximumSumPathTwoArrays(); System.out.println(msp.maxSum(input1, input2)); } } ================================================ FILE: src/com/interview/array/MaximumSumThreeNonOverlappingSubarray.java ================================================ package com.interview.array; import java.util.Arrays; import java.util.Deque; import java.util.LinkedList; import java.util.List; /** *https://leetcode.com/problems/maximum-sum-of-3-non-overlapping-subarrays/description/ */ public class MaximumSumThreeNonOverlappingSubarray { public int[] maxSumOfThreeSubarrays(int[] nums, int k) { int sum = 0; int[] sumArray = new int[nums.length - k + 1]; for (int i = 0; i < nums.length; i++) { if (i < k) { sum += nums[i]; } else { sumArray[i - k] = sum; sum += nums[i]; sum -= nums[i - k]; } } sumArray[sumArray.length - 1] = sum; int[][] dp = new int[4][sumArray.length + 1]; for (int i = 1; i <= 3; i++) { for (int j = 1; j <= sumArray.length; j++) { if (j >= k) { if (dp[i][j - 1] >= sumArray[j - 1] + dp[i - 1][j - k]) { dp[i][j] = dp[i][j - 1]; } else { dp[i][j] = sumArray[j - 1] + dp[i - 1][j - k]; } } else { if (dp[i][j - 1] >= sumArray[j - 1]) { dp[i][j] = dp[i][j - 1]; } else { dp[i][j] = sumArray[j - 1]; } } } } int[] output = new int[3]; int j = dp[0].length - 1; for (int i = 3; i > 0;) { if (dp[i][j] == dp[i][j - 1]) { j--; } else { output[i - 1] = j - 1; i--; j = j - k; } } return output; } public static void main(String[] args) { MaximumSumThreeNonOverlappingSubarray mss = new MaximumSumThreeNonOverlappingSubarray(); int[] input = {3, 2, 2, 1, 1, 0, 5}; int[] input1 = {1, 2, 1, 2, 6, 7, 5, 1}; int[] output = mss.maxSumOfThreeSubarrays(input1, 2); for (int i : output) { System.out.println(i); } } } ================================================ FILE: src/com/interview/array/MeetingRooms.java ================================================ package com.interview.array; import java.util.Arrays; import java.util.PriorityQueue; /** * Date 05/01/2016 * @author Tushar Roy * * Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), * find the minimum number of conference rooms required. * * Both methods have time comlexity of nlogn * Method 1 has space complexity of O(1) * * https://leetcode.com/problems/meeting-rooms-ii/ */ public class MeetingRooms { public static class Interval { int start; int end; Interval() { start = 0; end = 0; } Interval(int s, int e) { start = s; end = e; } } public int minMeetingRooms1(Interval[] intervals) { int[] start = new int[intervals.length]; int[] end = new int[intervals.length]; for (int i = 0; i < intervals.length; i++) { start[i] = intervals[i].start; end[i] = intervals[i].end; } Arrays.sort(start); Arrays.sort(end); int j = 0; int rooms = 0; for (int i = 0; i < start.length; i++) { if (start[i] < end[j]) { rooms++; } else { j++; } } return rooms; } public int minMeetingRooms(Interval[] intervals) { if (intervals.length == 0) { return 0; } Arrays.sort(intervals, (a, b) -> a.start - b.start); PriorityQueue pq = new PriorityQueue<>((a, b) -> a.end - b.end); pq.offer(intervals[0]); int rooms = 1; for (int i = 1; i < intervals.length; i++) { Interval it = pq.poll(); if (it.end <= intervals[i].start) { it = new Interval(it.start, intervals[i].end); } else { rooms++; pq.offer(intervals[i]); } pq.offer(it); } return rooms; } } ================================================ FILE: src/com/interview/array/MinimumDistanceBetweenTwoNumbers.java ================================================ package com.interview.array; /** * http://www.geeksforgeeks.org/find-the-minimum-distance-between-two-numbers/ */ public class MinimumDistanceBetweenTwoNumbers { public int minDistance(int input[],int x, int y){ int prev = -1; int prevFound = -1; int min = 10000; for(int i=0; i < input.length; i++){ if(input[i] == x){ if(prevFound == -1){ prevFound = x; prev = i; }else if(prevFound == x){ prev = i; }else{ min = min > i - prev ? i -prev : min; prev = i; prevFound = x; } }else if(input[i] == y){ if(prevFound == -1){ prevFound = y; prev = i; }else if(prevFound == y){ prev =i; }else{ min = min > i - prev ? i -prev : min; prevFound = y; prev = i; } } } return min; } public static void main(String args[]){ MinimumDistanceBetweenTwoNumbers mdb = new MinimumDistanceBetweenTwoNumbers(); int input[] = {6,4,1,5,6,9,10,4,6,6}; System.out.println(mdb.minDistance(input, 5, 6)); } } ================================================ FILE: src/com/interview/array/MinimumNumberFromSequence.java ================================================ package com.interview.array; import java.util.Arrays; /** * Date 02/26/2016 * @author Tushar Roy * * Time complexity : O(n^2) * Space complexity : O(n) * * Reference * http://www.geeksforgeeks.org/form-minimum-number-from-given-sequence/ */ public class MinimumNumberFromSequence { public int[] find(char[] input) { int[] output = new int[input.length + 1]; output[0] = 1; int low = 0; int start = 0; for (int i = 0; i < input.length; i++) { if (input[i] == 'D') { output[i + 1] = output[i] - 1; if (output[i+1] == low) { for (int j = start; j <= i + 1; j++) { output[j] = output[j] + 1; } } } else { low = output[start]; output[i + 1] = low + 1; start = i + 1; } } return output; } public static void main(String args[]) { MinimumNumberFromSequence ms = new MinimumNumberFromSequence(); int output[] = ms.find("DDIDDIID".toCharArray()); System.out.println(Arrays.toString(output)); output = ms.find("IIDDD".toCharArray()); System.out.println(Arrays.toString(output)); output = ms.find("DIDI".toCharArray()); System.out.println(Arrays.toString(output)); } } ================================================ FILE: src/com/interview/array/MinimumSortedWhichSortsEntireArray.java ================================================ package com.interview.array; /** *http://www.geeksforgeeks.org/minimum-length-unsorted-subarray-sorting-which-makes-the-complete-array-sorted/ */ public class MinimumSortedWhichSortsEntireArray { public int minLength(int arr[]){ int i=0; while(i < arr.length -1 && arr[i] < arr[i+1]){ i++; } if(i == arr.length-1){ return 0; } int j = arr.length-1; while(j > 0 && arr[j] > arr[j-1]){ j--; } int max = Integer.MIN_VALUE; int min = Integer.MAX_VALUE; for(int k = i; k <= j; k++){ if(max < arr[k]){ max = arr[k]; } if(min > arr[k]){ min = arr[k]; } } int x = i-1; while(x >=0){ if(min > arr[x]){ break; } x--; } int y = j +1; while(y < arr.length){ if(max < arr[y]){ break; } y++; } return y -x -2 + 1; } public static void main(String args[]){ int arr[] = {4,5,10,21,18,23,7,8,19,34,38}; int arr1[] = {4,5,6,12,11,15}; int arr2[] = {4,5,6,10,11,15}; MinimumSortedWhichSortsEntireArray msw = new MinimumSortedWhichSortsEntireArray(); System.out.println(msw.minLength(arr1)); } } ================================================ FILE: src/com/interview/array/MissingRanges.java ================================================ package com.interview.array; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Given a sorted integer array where the range of elements are in the inclusive range [lower, upper], return its missing ranges. * For example, given [0, 1, 3, 50, 75], lower = 0 and upper = 99, return ["2", "4->49", "51->74", "76->99"]. * * Time complexity O(n) * * https://leetcode.com/problems/missing-ranges/ */ public class MissingRanges { public List findMissingRanges(int[] nums, int lower, int upper) { if (nums.length == 0) { return Collections.singletonList(makeRange(lower, upper)); } List result = new ArrayList<>(); if (lower < nums[0]) { result.add(makeRange(lower, nums[0] - 1)); } for (int i = 0; i < nums.length - 1; i++) { if (nums[i] == nums[i + 1]) { continue; } if ((nums[i] + 1) != nums[i + 1]) { result.add(makeRange(nums[i] + 1, nums[i + 1] - 1)); } } if (nums[nums.length - 1] < upper) { result.add(makeRange(nums[nums.length - 1] + 1, upper)); } return result; } private String makeRange(int a, int b) { if (a == b) { return String.valueOf(a); } else { return a + "->" + b; } } } ================================================ FILE: src/com/interview/array/MoveAllZerosToEnd.java ================================================ package com.interview.array; public class MoveAllZerosToEnd { public void moveZeros(int arr[]){ int slow =0; int fast =0; while(fast < arr.length){ if(arr[fast] == 0){ fast++; continue; } arr[slow] = arr[fast]; slow++; fast++; } while(slow < arr.length){ arr[slow++] = 0; } } public static void main(String args[]){ MoveAllZerosToEnd maz = new MoveAllZerosToEnd(); int arr[] = {0,0,1,2,0,5,6,7,0}; maz.moveZeros(arr); for(int i=0; i < arr.length; i++){ System.out.print(arr[i]); } } } ================================================ FILE: src/com/interview/array/MultiplyAllFieldsExceptOwnPosition.java ================================================ package com.interview.array; /** * https://leetcode.com/problems/product-of-array-except-self/ */ public class MultiplyAllFieldsExceptOwnPosition { public int[] multiply(int nums[]) { if (nums.length == 0) { return new int[0]; } int[] output = new int[nums.length]; output[0] = 1; for (int i = 1; i < nums.length; i++) { output[i] = output[i - 1] * nums[i - 1]; } int mult = 1; for (int i = nums.length - 1; i >= 0; i--) { output[i] *= mult; mult *= nums[i]; } return output; } } ================================================ FILE: src/com/interview/array/NthElementOfCountNumberSequence.java ================================================ package com.interview.array; import java.util.ArrayList; import java.util.List; /** * Date 07/20/2015 * @author Tushar Roy * * Given a sequence like * 1 11 21 1211 111221 312211 * Print nth element of this sequence. */ public class NthElementOfCountNumberSequence { public List nthElement(int n) { int i = 1; List current = new ArrayList<>(); current.add(1); List result = new ArrayList<>(); while(i < n) { int count = 1; int index = 0; for(int j = 1; j < current.size(); j++) { if(current.get(index) == current.get(j)) { count++; } else { result.add(count); result.add(current.get(index)); count = 1; index = j; } } result.add(count); result.add(current.get(index)); current = result; result = new ArrayList<>(); i++; } return current; } public static void main(String args[]) { NthElementOfCountNumberSequence nes = new NthElementOfCountNumberSequence(); for(int i = 1 ; i <= 10; i++) { List result = nes.nthElement(i); result.forEach(System.out::print); System.out.println(); } } } ================================================ FILE: src/com/interview/array/NumberOfTrianglesInUnsortedArray.java ================================================ package com.interview.array; import java.util.Arrays; /** * http://www.geeksforgeeks.org/find-number-of-triangles-possible/ */ public class NumberOfTrianglesInUnsortedArray { public int numberOfTriangles(int input[]){ Arrays.sort(input); int count = 0; for(int i=0; i < input.length-2; i++){ int k = i+2; for(int j=i+1; j < input.length; j++){ while(k < input.length && input[i] + input[j] > input[k]){ k++; } count += k - j -1; } } return count; } public static void main(String args[]){ int input[] = {3, 4, 5, 6, 8, 9, 15}; NumberOfTrianglesInUnsortedArray not = new NumberOfTrianglesInUnsortedArray(); System.out.println(not.numberOfTriangles(input)); } } ================================================ FILE: src/com/interview/array/PositiveAndNegativeNumberAlternatively.java ================================================ package com.interview.array; /** * http://www.geeksforgeeks.org/rearrange-positive-and-negative-numbers-publish/ */ public class PositiveAndNegativeNumberAlternatively { public void arrange(int arr[]){ int startOfPos = segregate(arr); int startOfNeg = 1; while(startOfNeg < startOfPos && startOfPos < arr.length){ swap(arr,startOfNeg,startOfPos); startOfNeg+=2; startOfPos++; } } private int segregate(int arr[]){ int low =0; int high = arr.length-1; while(low < high){ if(arr[low] < 0){ low++; }else if(arr[high] >= 0){ high--; }else{ swap(arr,low,high); } } return low; } private void swap(int arr[],int i,int j){ int t = arr[i]; arr[i] = arr[j]; arr[j] = t; } public static void main(String args[]){ int arr[] = {-1,-2,-3,-4,-5,1,2,3,4,5}; PositiveAndNegativeNumberAlternatively pan = new PositiveAndNegativeNumberAlternatively(); pan.arrange(arr); for(int i=0; i < arr.length; i++){ System.out.print(arr[i]+ " "); } } } ================================================ FILE: src/com/interview/array/PositiveAndNegativeNumberAlternativelyMaintainingOrder.java ================================================ package com.interview.array; import java.util.Arrays; /** * Date 12/31/2015 * @author Tushar Roy * * Given an array of positive and negative integers arrange them alternatively maintaining initial order. * If there are more +ve or -ve integer then push them to the end together. * * Time complexity is O(n) * Space complexity is O(1) * * http://www.geeksforgeeks.org/rearrange-array-alternating-positive-negative-items-o1-extra-space/ */ public class PositiveAndNegativeNumberAlternativelyMaintainingOrder { public void rearrange(int input[]) { for (int i = 0; i < input.length; i++) { if (i % 2 == 0 && input[i] >= 0) { int indexOfNextNegative = findNext(input, i + 1, false); if (indexOfNextNegative == -1) { return; } else { rightRotate(input, i, indexOfNextNegative); } } else if (i % 2 != 0 && input[i] < 0) { int indexOfNextPositive = findNext(input, i + 1, true); if (indexOfNextPositive == -1) { return; } else { rightRotate(input, i, indexOfNextPositive); } } } } private int findNext(int input[], int start, boolean isPositive) { for (int i = start; i < input.length; i++) { if ((isPositive && input[i] >= 0) || (!isPositive && input[i] < 0)) { return i; } } return -1; } private void rightRotate(int input[], int start, int end) { int t = input[end]; for (int i = end; i > start; i--) { input[i] = input[i - 1]; } input[start] = t; } public static void main(String args[]) { int input[] = {-5, -2, 5, 2, 4, 7, 1, 8, 0, -8}; PositiveAndNegativeNumberAlternativelyMaintainingOrder pss = new PositiveAndNegativeNumberAlternativelyMaintainingOrder(); pss.rearrange(input); Arrays.stream(input).forEach(i -> System.out.print(i + " ")); } } ================================================ FILE: src/com/interview/array/RearrangeArrayPerIndex.java ================================================ package com.interview.array; import java.util.Arrays; /** * Date 12/30/2015 * * Given an array of size n where elements are in range 0 to n-1. Rearrange elements of array * such that if arr[i] = j then arr[j] becomes i. * * Time complexity O(n) * Space complexity O(1) * * http://www.geeksforgeeks.org/rearrange-array-arrj-becomes-arri-j/ */ public class RearrangeArrayPerIndex { public void rearrange(int input[]) { for (int i = 0; i < input.length; i++) { input[i]++; } for (int i = 0; i < input.length; i++) { if (input[i] > 0) { rearrangeUtil(input, i); } } for (int i = 0; i < input.length; i++) { input[i] = -input[i] - 1; } } private void rearrangeUtil(int input[], int start) { int i = start + 1; int v = input[start]; while (v > 0) { int t = input[v - 1]; input[v - 1] = -i; i = v; v = t; } } public static void main(String args[]) { RearrangeArrayPerIndex rai = new RearrangeArrayPerIndex(); int input[] = {1, 2, 0, 5, 3, 4}; rai.rearrange(input); Arrays.stream(input).forEach(i -> System.out.print(i + " ")); } } ================================================ FILE: src/com/interview/array/RearrangeSuchThatArriBecomesArrArri.java ================================================ package com.interview.array; /** * http://www.geeksforgeeks.org/rearrange-given-array-place/ */ public class RearrangeSuchThatArriBecomesArrArri { public void rearrange(int arr[]){ for(int i=0; i < arr.length; i++){ int temp; if(arr[arr[i]] > arr.length-1){ temp = arr[arr[i]]/arr.length-1; }else{ temp = arr[arr[i]]; } arr[i] = temp + arr.length*(arr[i]+1); } for(int i=0; i < arr.length;i++){ arr[i] = arr[i] % arr.length; } } public static void main(String args[]){ int arr[] = {4,2,0,1,3}; RearrangeSuchThatArriBecomesArrArri rss = new RearrangeSuchThatArriBecomesArrArri(); rss.rearrange(arr); for(int i=0; i < arr.length; i++){ System.out.print(arr[i]); } } } ================================================ FILE: src/com/interview/array/ReorderArrayByIndex.java ================================================ package com.interview.array; import java.util.Arrays; /** * Date 12/29/2015 * @author Tushar Roy * * Given two arrays one with values and other with index where values should be positioned. Move values to correct * position * * Time complexity - O(n) * Space complexity - O(1) * * http://www.geeksforgeeks.org/reorder-a-array-according-to-given-indexes/ */ public class ReorderArrayByIndex { public void reorder(int input[], int index[]) { if(index.length != input.length) { throw new IllegalArgumentException(); } for (int i = 0 ; i < index.length; i++) { while (index[i] != i) { int sIndex = index[index[i]]; int sVal = input[index[i]]; index[index[i]] = index[i]; input[index[i]] = input[i]; index[i] = sIndex; input[i] = sVal; } } } public static void main(String args[]) { int input[] = {50, 40, 70, 60, 90}; int index[] = {3, 0, 4, 1, 2}; ReorderArrayByIndex reorderArrayByIndex = new ReorderArrayByIndex(); reorderArrayByIndex.reorder(input, index); Arrays.stream(input).forEach(i -> System.out.print(i + " ")); System.out.println(); Arrays.stream(index).forEach(i -> System.out.print(i + " ")); } } ================================================ FILE: src/com/interview/array/RepeatingAndMissingNumber.java ================================================ package com.interview.array; /** * http://www.geeksforgeeks.org/find-a-repeating-and-a-missing-number/ */ public class RepeatingAndMissingNumber { class Pair{ int repeating; int missing; public String toString(){ return repeating + " " + missing; } } public Pair findNumbers(int input[]){ Pair p = new Pair(); for(int i=0; i < input.length; i++){ if(input[Math.abs(input[i])-1] < 0){ p.repeating = Math.abs(input[i]); }else{ input[Math.abs(input[i])-1] = -input[Math.abs(input[i])-1]; } } for(int i=0; i < input.length; i++){ if(input[i] < 0){ input[i] = -input[i]; }else{ p.missing = i + 1; } } return p; } public static void main(String args[]){ RepeatingAndMissingNumber rmn = new RepeatingAndMissingNumber(); int input[] = {3,1,2,4,6,8,2,7}; System.out.println(rmn.findNumbers(input)); } } ================================================ FILE: src/com/interview/array/RotationWithMaxSum.java ================================================ package com.interview.array; /** * Date 12/30/2015 * @author Tushar Roy * * Given an input array find which rotation will give max sum of i * arr[i] * * Time complexity - O(n) * Space complexity - O(1) * * http://www.geeksforgeeks.org/find-maximum-value-of-sum-iarri-with-only-rotations-on-given-array-allowed/ */ public class RotationWithMaxSum { int maxSum(int input[]) { int arrSum = 0; int rotationSum = 0; for (int i =0; i < input.length; i++) { arrSum += input[i]; rotationSum += i*input[i]; } int maxRotationSum = rotationSum; for (int i = 1; i < input.length; i++) { rotationSum += input.length*input[i - 1] - arrSum; maxRotationSum = Math.max(maxRotationSum, rotationSum); } return maxRotationSum; } public static void main(String args[]) { int input[] = {10, 1, 2, 3, 4, 5, 6, 7, 8, 9}; RotationWithMaxSum rms = new RotationWithMaxSum(); System.out.print(rms.maxSum(input)); } } ================================================ FILE: src/com/interview/array/SelfCrossing.java ================================================ package com.interview.array; /** * Created by tushar_v_roy on 3/10/16. */ public class SelfCrossing { public boolean isSelfCrossing(int[] x) { if (x.length < 4) { return false; } int v1 = -x[0]; int v2 = -x[1]; int i = 2; while (i < x.length) { if (i % 2 == 0) { if (i % 4 == 0) { v1 -= x[i]; } else { v1 += x[i]; } } else { if ((i + 1) % 4 == 0) { v2 += x[i]; } else { v2 -= x[i]; } } if (i % 2 != 0) { if ((v1 >= 0 && v2 <= 0) || (v1 <= 0 && v2 >= 0)) { return true; } } i++; } return false; } public static void main(String args[]) { SelfCrossing sc = new SelfCrossing(); int input[] = {3, 3, 4, 2, 2}; System.out.print(sc.isSelfCrossing(input)); } } ================================================ FILE: src/com/interview/array/ShortestPalindrome.java ================================================ package com.interview.array; /** * Date 03/04/2016 * @author Tushar Roy * * How to append minimum numbers of characters in front of string to make it a palindrome. * * Idea is to create a new string which is original ttring + $ + reverse of original string * Get value of suffix which is also prefix using KMP. * This part of string is good. Rest needs to be copied in the front. * * Time complexity is O(n) * Space complexity is O(n) * * https://leetcode.com/problems/shortest-palindrome/ */ public class ShortestPalindrome { public String shortestPalindrome(String s) { char[] input = createInput(s); int val = kmp(input); StringBuffer sb = new StringBuffer(); int remaining = s.length() - val; int i = s.length() - 1; while (remaining > 0) { sb.append(s.charAt(i)); i--; remaining--; } sb.append(s); return sb.toString(); } private int kmp(char[] input) { int T[] = new int[input.length]; int j = 1; int i = 0; T[0] = 0; while (j < input.length) { if (input[i] == input[j]) { T[j] = i + 1; i++; } else { while (i != 0) { i = T[i-1]; if (input[j] == input[i]) { T[j] = i + 1; i++; break; } } } j++; } return T[input.length - 1]; } private char[] createInput(String s) { char[] input = new char[2*s.length() + 1]; int index = 0; for (char ch: s.toCharArray()) { input[index++] = ch; } input[index++] = '$'; for (int i = s.length() - 1; i >= 0; i--) { input[index++] = s.charAt(i); } return input; } public static void main(String args[]) { ShortestPalindrome sp = new ShortestPalindrome(); System.out.print(sp.shortestPalindrome("aacecaaa")); } } ================================================ FILE: src/com/interview/array/SmallestIntegerNotRepresentedBySubsetSum.java ================================================ package com.interview.array; /** * Date 12/31/2015 * @author Tushar Roy * * Given array in non decreasing order find smallest integer which cannot be represented by * subset sum of these integers. * * Time complexity is O(n) * * http://www.geeksforgeeks.org/find-smallest-value-represented-sum-subset-given-array/ */ public class SmallestIntegerNotRepresentedBySubsetSum { public int findSmallestInteger(int input[]) { int result = 1; for (int i = 0; i < input.length; i++) { if (input[i] <= result) { result += input[i]; } else { break; } } return result; } /** * Leetcode variation https://leetcode.com/problems/patching-array/ */ public int minPatches(int[] nums, int n) { int patch = 0; long t = 1; int i = 0; while(t <= n) { if (i == nums.length || t < nums[i]) { patch++; t += t; } else { t = nums[i] + t; i++; } } return patch; } public static void main(String args[]) { int input[] = {1, 2, 3, 8}; SmallestIntegerNotRepresentedBySubsetSum ss = new SmallestIntegerNotRepresentedBySubsetSum(); System.out.println(ss.findSmallestInteger(input)); int input1[] = {}; System.out.println(ss.minPatches(input1, 7)); } } ================================================ FILE: src/com/interview/array/SmallestSubarrayWithAtleastKSum.java ================================================ package com.interview.array; /** * https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/description/ */ public class SmallestSubarrayWithAtleastKSum { public int shortestSubarray(int[] A, int K) { int[] skip = new int[A.length]; int sum = 0; int start = A.length - 1; skip[A.length - 1] = 1; for (int i = A.length - 1; i > 0; i--) { skip[i - 1] = 1; sum += A[i]; if (sum <= 0) { skip[i - 1] = start - i + 1; } else { start = i; sum = 0; } } start = 0; int end = 0; sum = 0; int min = Integer.MAX_VALUE; while (end < A.length) { sum += A[end++]; while (start <= end && sum >= K) { min = Math.min(end - start, min); for (int j = start; j < start + skip[start]; j++) { sum -= A[j]; } start = start + skip[start]; } if (sum <= 0) { start = end; sum = 0; } } return min == Integer.MAX_VALUE ? -1 : min; } public static void main(String[] args) { int[] input = {1, 3, -1, -4, -2, 3, 4, -5, -1, 8}; SmallestSubarrayWithAtleastKSum ss = new SmallestSubarrayWithAtleastKSum(); ss.shortestSubarray(input, 8); } } ================================================ FILE: src/com/interview/array/SortedArrayTransformation.java ================================================ package com.interview.array; /** * Date 10/08/2016 * @author Tushar Roy * * Given a sorted array of integers nums and integer values a, b and c. * Apply a function of the form f(x) = ax2 + bx + c to each element x in the array. * * Time complexity O(n) * * https://leetcode.com/problems/sort-transformed-array/ */ public class SortedArrayTransformation { public int[] sortTransformedArray(int[] nums, int a, int b, int c) { int start = 0; int end = nums.length - 1; int[] result = new int[nums.length]; int index = (a >= 0 ? nums.length - 1 : 0); while (start <= end) { int x = apply(nums[start], a, b, c); int y = apply(nums[end], a, b, c); boolean condition = (a >= 0 ? x >= y : x <= y); if (condition) { result[index] = x; start++; } else { result[index] = y; end--; } index = index + (a >= 0 ? -1 : 1); } return result; } private int apply(int x, int a, int b, int c) { return a*x*x + b * x + c; } } ================================================ FILE: src/com/interview/array/StableMarriageProblem.java ================================================ package com.interview.array; public class StableMarriageProblem { private boolean checkIfNewIsBetter(int priority[][], int bride, int currentGroom, int suitor) { for (int groom : priority[bride]) { if (currentGroom == groom) { return false; } if (suitor == groom) { return true; } } return false; } public int[] findPair(int[][] priority) { int pair = priority[0].length; int groomToBride[] = new int[pair]; int brideToGroom[] = new int[pair]; for(int i=0; i < groomToBride.length; i++){ groomToBride[i] = -1; } for(int i=0; i < brideToGroom.length; i++){ brideToGroom[i] = -1; } int groom ; int remaingGrooms = pair; while (remaingGrooms > 0) { groom = -1; for (int hasBride : groomToBride) { if (hasBride != -1) { continue; } groom++; for (int bride : priority[groom]) { if (brideToGroom[bride-pair] == -1) { groomToBride[groom] = bride; brideToGroom[bride-pair] = groom; remaingGrooms--; break; } else { boolean flag = checkIfNewIsBetter(priority, bride, brideToGroom[bride-pair], groom); if (flag) { int currentGroom = brideToGroom[bride-pair]; brideToGroom[bride-pair] = groom; groomToBride[groom] = bride; groomToBride[currentGroom] = -1; } } } } } return groomToBride; } public static void main(String args[]){ int priority[][] = {{5,4,7,6}, {4,5,6,7}, {5,4,6,7}, {5,4,7,6}, {0,1,2,3}, {0,1,3,2}, {0,3,1,2}, {0,1,2,3}}; StableMarriageProblem smp = new StableMarriageProblem(); int[] result = smp.findPair(priority); for(int i=0; i < result.length; i++){ System.out.println(i + " " + result[i]); } } } ================================================ FILE: src/com/interview/array/SubarrayWithGivenSum.java ================================================ package com.interview.array; /** * http://www.geeksforgeeks.org/find-subarray-with-given-sum/ */ public class SubarrayWithGivenSum { class Pair{ int start; int end; public String toString(){ return start + " " + end; } } public Pair findSubArray(int input[],int sum){ int currentSum = 0; Pair p = new Pair(); p.start = 0; for(int i=0; i < input.length; i++){ currentSum += input[i]; p.end = i; if(currentSum == sum){ return p; }else if(currentSum > sum){ int s = p.start; while(currentSum > sum){ currentSum -= input[s]; s++; } p.start = s; if(currentSum == sum){ return p; } } } return null; } public static void main(String args[]){ SubarrayWithGivenSum sgs = new SubarrayWithGivenSum(); int input[] = {6,3,9,11,1,3,5}; System.out.println(sgs.findSubArray(input,15)); } } ================================================ FILE: src/com/interview/array/SummaryRanges.java ================================================ package com.interview.array; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Date 10/19/2016 * @author Tushar Roy * * Given a sorted integer array without duplicates, return the summary of its ranges. * For example, given [0,1,2,4,5,7], return ["0->2","4->5","7"]. * * Solution - * Just check if num[i] + 1 != num[i + 1]. If its not equal means you need to add previous range to result * and start a new range. * * Time complexity O(n) * * https://leetcode.com/problems/summary-ranges/ */ public class SummaryRanges { public List summaryRanges(int[] nums) { if (nums.length == 0) { return Collections.EMPTY_LIST; } if (nums.length == 1) { return Collections.singletonList(String.valueOf(nums[0])); } int start = 0; List result = new ArrayList<>(); for (int i = 0; i < nums.length - 1; i++) { if ((nums[i] + 1) != nums[i + 1]) { result.add(makeRange(nums[start], nums[i])); start = i + 1; } } if ((nums[nums.length - 2] + 1) != nums[nums.length - 1]) { start = nums.length - 1; } result.add(makeRange(nums[start], nums[nums.length - 1])); return result; } private String makeRange(int a, int b) { if (a == b) { return String.valueOf(a); } return a + "->" + b; } } ================================================ FILE: src/com/interview/array/ThreeSumSmallerThanTarget.java ================================================ package com.interview.array; import java.util.Arrays; /** * Given an array of n integers nums and a target, find the number of index triplets i, j, k * with 0 <= i < j < k < n that satisfy the condition nums[i] + nums[j] + nums[k] < target. * * https://leetcode.com/problems/3sum-smaller/ */ public class ThreeSumSmallerThanTarget { public int threeSumSmaller(int[] nums, int target) { if (nums.length < 3) { return 0; } Arrays.sort(nums); int count = 0; for (int i = 0; i < nums.length; i++) { int j = i + 1; int k = nums.length - 1; while (j < k) { if (nums[i] + nums[j] + nums[k] >= target) { k--; } else { count += k - j; j++; } } } return count; } } ================================================ FILE: src/com/interview/array/TrappingWater.java ================================================ package com.interview.array; /** * References * https://oj.leetcode.com/problems/trapping-rain-water/ * https://leetcode.com/problems/trapping-rain-water/ */ public class TrappingWater { public int trap(int[] height) { if(height == null || height.length == 0) { return 0; } int len = height.length; int left[] = new int[len]; int right[] = new int[len]; left[0] = height[0]; right[len-1] = height[len -1]; for (int i = 1; i < len; i++) { left[i] = Math.max(height[i], left[i-1]); right[len - i - 1] = Math.max(height[len- i - 1], right[len-i]); } int maxWaterTrapped = 0; for (int i = 1; i < len - 1; i++) { int min = Math.min(left[i], right[i]); if (height[i] < min) { maxWaterTrapped += min - height[i]; } } return maxWaterTrapped; } public static void main(String args[]){ int input[] = {0,1,0,2,1,0,1,3,2,1,2,1}; TrappingWater tw = new TrappingWater(); System.out.println(tw.trap(input)); } } ================================================ FILE: src/com/interview/array/TripletInArray.java ================================================ package com.interview.array; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * http://www.geeksforgeeks.org/find-a-triplet-that-sum-to-a-given-value/ */ public class TripletInArray { class Triplet { int a; int b; int c; public String toString() { return a + " " + b + " " + c; } } public Triplet findTriplet(int input[], int sum) { Arrays.sort(input); for (int i = 0; i < input.length - 2; i++) { int start = i + 1; int end = input.length - 1; int new_sum = sum - input[i]; while (start < end) { if (new_sum == input[start] + input[end]) { Triplet t = new Triplet(); t.a = input[i]; t.b = input[start]; t.c = input[end]; return t; } if (new_sum > input[start] + input[end]) { start++; } else { end--; } } } return null; } /** * https://leetcode.com/problems/3sum/ */ public List> threeSum(int[] nums) { Arrays.sort(nums); List> result = new ArrayList<>(); for (int i = 0; i < nums.length - 2; i++) { if (i != 0 && nums[i] == nums[i-1]) { continue; } int start = i + 1; int end = nums.length - 1; while (start < end) { if (nums[i] + nums[start] + nums[end] == 0) { List r = new ArrayList<>(); r.add(nums[i]); r.add(nums[start]); r.add(nums[end]); result.add(r); start++; end--; while(start < nums.length && nums[start] == nums[start - 1]) { start++; } while(end >= 0 && nums[end] == nums[end+1]) { end--; } } else if (nums[i] + nums[start] + nums[end] < 0) { start++; } else { end--; } } } return result; } public static void main(String args[]){ TripletInArray tip = new TripletInArray(); int input[] = {1,2,6,9,11,18,26,28}; int sum = 22; System.out.println(tip.findTriplet(input, sum)); } } ================================================ FILE: src/com/interview/array/TripletSumLessThanTotal.java ================================================ package com.interview.array; import java.util.Arrays; /** * Date 12/29/2015 * @author Tushar Roy * * Given array with unique numbers and a total, find all triplets whose sum is less than total * * http://www.geeksforgeeks.org/count-triplets-with-sum-smaller-that-a-given-value/ */ public class TripletSumLessThanTotal { public int findAllTriplets(int input[], int total) { Arrays.sort(input); int result = 0; for (int i = 0; i < input.length - 2; i++) { int j = i + 1; int k = input.length - 1; while (j < k) { if (input[i] + input[j] + input[k] >= total) { k--; } else { result += k - j; j++; } } } return result; } public static void main(String args[]) { int input[] = {5, 1, 3, 4, 7}; TripletSumLessThanTotal tt = new TripletSumLessThanTotal(); System.out.print(tt.findAllTriplets(input, 12)); } } ================================================ FILE: src/com/interview/array/TugOfWar.java ================================================ package com.interview.array; import java.util.ArrayList; import java.util.List; /* * http://www.geeksforgeeks.org/tug-of-war/ */ public class TugOfWar { private int minFoundSoFar = 1000000; public int findMind(int arr[]){ int total = 0; for(int i=0; i < arr.length; i++){ total += arr[i]; } List result = new ArrayList<>(); combinationUtil(arr,arr.length/2,0,0,total,0,result); return minFoundSoFar; } private void combinationUtil(int arr[],int k, int start,int sum, int total,int pos, List result){ if(pos == k){ if(Math.abs(sum - total/2) < minFoundSoFar) { minFoundSoFar = Math.abs(sum - total/2); System.out.println(result); } return; } for(int i=start; i < arr.length; i++){ sum += arr[i]; result.add(arr[i]); combinationUtil(arr,k,i+1,sum,total,pos+1,result); result.remove(result.size()-1); sum -= arr[i]; } } public static void main(String args[]){ TugOfWar tow = new TugOfWar(); int arr[] = {23, 45, 34, 12,11, 98, 99, 4, 189, 1,7,19,105, 201}; int min = tow.findMind(arr); System.out.print(min); } } ================================================ FILE: src/com/interview/array/WaterContainer.java ================================================ package com.interview.array; /** * Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). * n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, * which together with x-axis forms a container, such that the container contains the most water. * * https://leetcode.com/problems/container-with-most-water/ */ public class WaterContainer { public int maxArea(int[] height) { int i = 0; int j = height.length - 1; int maxArea = 0; while (i < j) { if (height[i] < height[j]) { maxArea = Math.max(maxArea, (height[i]) * (j - i)); i++; } else { maxArea = Math.max(maxArea, height[j] * (j - i)); j--; } } return maxArea; } } ================================================ FILE: src/com/interview/array/WiggleSort.java ================================================ package com.interview.array; import java.util.Arrays; /** * Date 03/23/2016 * @author Tushar Roy * * Convert an unsorted array into an array of form num[0] < num[1] > nums[2] < num[3].... * * Time complexity O(n) - This depends on KthElementInArray time * Space complexity O(1) * * https://leetcode.com/problems/wiggle-sort/ * https://leetcode.com/problems/wiggle-sort-ii/ */ public class WiggleSort { //looking for nums[0] < nums[1] > nums[2] < nums[3] and so on. public void wiggleSort2(int[] arr) { if (arr.length == 0) { return; } int k = arr.length/2; KthElementInArray kthElementInArray = new KthElementInArray(); kthElementInArray.kthElement(arr, k); int mid = arr[k]; int n = arr.length; int i = 0, j = 0; k = n - 1; while (j <= k) { if (arr[next(j, n)] > mid) { swap(arr, next(i++, n), next(j++, n)); } else if (arr[next(j, n)] < mid) { swap(arr, next(j, n), next(k--, n)); } else { j++; } } } //in this version we are looking for nums[0] <= nums[1] >= nums[2] <= nums[3] and so on. public void wiggleSort1(int[] nums) { boolean flag = true; for (int i = 0; i < nums.length - 1; i++) { if (flag) { if (nums[i] > nums[i + 1]) { swap(nums, i, i + 1); } } else { if (nums[i] < nums[i + 1]) { swap(nums, i, i + 1); } } flag = !flag; } } private int next(int index, int n) { return (2*index + 1) % (n | 1); } private void swap(int arr[],int low,int high){ int temp = arr[low]; arr[low] = arr[high]; arr[high] = temp; } public static void main(String args[]) { WiggleSort ws = new WiggleSort(); int input[] = {6, 2, 1, 6, 8, 9, 6}; ws.wiggleSort2(input); System.out.print(Arrays.toString(input)); } } ================================================ FILE: src/com/interview/array/ZigZagArrangement.java ================================================ package com.interview.array; import java.util.Arrays; /** * Date 12/30/2015 * @author Tushar Roy * * Given an array of unique elements rearrange the array to be a < b > c < d > e form * * Time complexity - O(n) * Space complexity - O(1) * * http://www.geeksforgeeks.org/convert-array-into-zig-zag-fashion/ */ public class ZigZagArrangement { public void rearrange(int input[]) { boolean isLess = true; for (int i = 0; i < input.length - 1; i++) { if(isLess) { if (input[i] > input[i+1]) { swap(input, i, i+1); } } else { if (input[i] < input[i+1]) { swap(input, i, i+1); } } isLess = !isLess; } } private void swap(int input[], int i, int j) { int t = input[i]; input[i] = input[j]; input[j] = t; } public static void main(String args[]) { int input[] = {4, 3, 2, 6, 7, 1, 9}; ZigZagArrangement zza = new ZigZagArrangement(); zza.rearrange(input); Arrays.stream(input).forEach(i -> System.out.print(i + " ")); } } ================================================ FILE: src/com/interview/binarysearch/ArithmeticProgressionSearch.java ================================================ package com.interview.binarysearch; /** * http://www.careercup.com/question?id=4798365246160896 */ public class ArithmeticProgressionSearch { public int search(int input[]){ int low =0; int high = input.length-1; int ap = (input[high] - input[low])/(input.length); int middle = -1; while(low <= high){ middle = (low + high)/2; if(input[middle] == input[0] + (middle)*ap){ low = middle+1; }else if((input[middle] > input[0] + (middle)*ap) && input[middle-1] == input[0] + (middle-1)*ap){ return input[0] + (middle)*ap; }else{ high = middle-1; } } return -1; } public static void main(String args[]){ int input[] = {1,7,10,13,16,19,22}; ArithmeticProgressionSearch aps = new ArithmeticProgressionSearch(); System.out.println(aps.search(input)); } } ================================================ FILE: src/com/interview/binarysearch/BinarySearch.java ================================================ package com.interview.binarysearch; /** * Regular binary search */ public class BinarySearch { public int search(final int input[], int search) { int low = 0; int high = input.length - 1; int mid; while (low <= high) { mid = low + ((high - low) / 2); if (input[mid] == search) { return mid; } else if (input[mid] < search) { low = mid + 1; } else { high = mid - 1; } } return -1; } public static void main(String args[]) { BinarySearch bSearch = new BinarySearch(); final int arr1[] = {1, 2, 4, 5, 7, 8}; System.out.println(bSearch.search(arr1, -1)); System.out.println(bSearch.search(arr1, 1)); System.out.println(bSearch.search(arr1, 8)); System.out.println(bSearch.search(arr1, 2)); } } ================================================ FILE: src/com/interview/binarysearch/CircularBinarySearch.java ================================================ package com.interview.binarysearch; /** * http://www.careercup.com/question?id=4877486110277632 * Given a circle with N defined points and a point M outside the circle, * find the point that is closest to M among the set of N. O(LogN) * Test cases * 1) smallest element at center * 2) smallest element at left/right end * 3) largest element at center * 4) smallest element at left side * 5) smallest element at right side */ public class CircularBinarySearch { //if mid is greater than both ends than result is low of two ends else move in direction //where either mid-1 or mid+1 is less public int search(int arr[]) { int low = 0; int high = arr.length - 1; int mid = 0; while (low < high) { mid = (low + high) / 2; //if middle is less than both mid-1 and mid+1 then mid is the answer if((low == mid || arr[mid] < arr[mid-1])&& arr[mid] < arr[mid+1]){ return arr[mid]; } if ((arr[mid] >= arr[low] && arr[mid] >= arr[high])){ if(arr[low] < arr[high]){ high = mid-1; }else{ low = mid+1; } }else{ if(arr[mid-1] < arr[mid+1]){ high = mid-1; }else{ low = mid+1; } } } return arr[low]; } public static void main(String args[]) { CircularBinarySearch cbs = new CircularBinarySearch(); int arr[] = { 7, 10, 8, 5, 2, 3, 5 }; System.out.print(cbs.search(arr)); int arr1[] = { 5, 8, 10, 7, 5, 3, 2 }; System.out.print(cbs.search(arr1)); int arr2[] = { 3, 5, 7, 10, 8, 5, 2 }; System.out.print(cbs.search(arr2)); int arr3[] = { 8, 5, 2, 3, 5, 7, 10 }; System.out.print(cbs.search(arr3)); int arr4[] = { 5, 3, 2, 5, 8, 10, 7 }; System.out.print(cbs.search(arr4)); int arr5[] = {100,20,10,5,2,8,11,16,19}; System.out.print(cbs.search(arr5)); int arr6[] = {200,2,10,15,20,80,110,160,190}; System.out.print(cbs.search(arr6)); int arr7[] = {5,10,20,50,200,800,1100,1600,1900,2}; System.out.print(cbs.search(arr7)); int arr8[] = {2,5,10,20,50,200,800,1100,1600,1900}; System.out.print(cbs.search(arr8)); int arr9[] = {3,1,8,5,4}; System.out.print(cbs.search(arr9)); } } ================================================ FILE: src/com/interview/binarysearch/CountNDistinctPairsWithDifferenceK.java ================================================ package com.interview.binarysearch; import java.util.Arrays; /** * http://www.geeksforgeeks.org/count-pairs-difference-equal-k/ */ public class CountNDistinctPairsWithDifferenceK { public int count(int arr[],int k){ Arrays.sort(arr); int count = 0; for(int i=0; i < arr.length; i++){ boolean result = binarySearch(arr, i+1, arr.length-1, arr[i] + k); if(result){ count++; } } return count; } private boolean binarySearch(int arr[],int start,int end,int num){ if(start > end){ return false; } int mid = (start + end)/2; if(arr[mid] == num){ return true; } else if(arr[mid] > num){ return binarySearch(arr,start,mid-1,num); }else{ return binarySearch(arr,mid+1,end,num); } } public static void main(String args[]){ CountNDistinctPairsWithDifferenceK cn = new CountNDistinctPairsWithDifferenceK(); int arr[] = {1,2,3,4,5,7,9}; System.out.print(cn.count(arr, 3)); } } ================================================ FILE: src/com/interview/binarysearch/FirstOccurrenceOfNumberInSortedArray.java ================================================ package com.interview.binarysearch; /** * http://www.geeksforgeeks.org/check-for-majority-element-in-a-sorted-array/ */ public class FirstOccurrenceOfNumberInSortedArray { public int firstOccurrence(int input[], int x){ int low = 0; int high = input.length-1; while(low <= high){ int middle = (low + high)/2; if(input[middle] == x && (middle == 0 || input[middle-1] < x)){ return middle; }else if(input[middle] < x){ low = middle+1; }else{ high = middle-1; } } return -1; } public static void main(String args[]){ FirstOccurrenceOfNumberInSortedArray fos = new FirstOccurrenceOfNumberInSortedArray(); int input[] = {1,2,2,2,2,2,5,7,7}; System.out.println(fos.firstOccurrence(input, 6)); } } ================================================ FILE: src/com/interview/binarysearch/FloorAndCeilingSortedArray.java ================================================ package com.interview.binarysearch; /** * http://www.geeksforgeeks.org/search-floor-and-ceil-in-a-sorted-array/ */ public class FloorAndCeilingSortedArray { public int floor(int input[], int x){ int low = 0; int high = input.length-1; while(low <= high){ int middle = (low + high)/2; if(input[middle] == x || (input[middle] < x && (middle == input.length-1 || input[middle+1] > x))){ return middle; }else if(input[middle] < x){ low = middle+1; }else{ high = middle-1; } } return -1; } public int ceiling(int input[], int x){ int low = 0; int high = input.length-1; while(low <= high){ int middle = (low + high)/2; if(input[middle] == x || (input[middle] > x && (middle == 0 || input[middle-1] < x))){ return middle; }else if(input[middle] < x){ low = middle+1; }else{ high = middle-1; } } return -1; } public static void main(String args[]){ int input[] = {1,2,5,6,11,15}; FloorAndCeilingSortedArray foc = new FloorAndCeilingSortedArray(); System.out.println(foc.floor(input, 15)); System.out.println(foc.ceiling(input, 2)); } } ================================================ FILE: src/com/interview/binarysearch/MedianOfTwoSortedArray.java ================================================ package com.interview.binarysearch; /** * http://www.geeksforgeeks.org/median-of-two-sorted-arrays/ */ public class MedianOfTwoSortedArray { public double median(int arr1[],int arr2[]){ int low1 = 0; int high1 = arr1.length-1; int low2 = 0; int high2 = arr2.length-1; while(true){ if(high1 == low1){ return (arr1[low1] + arr2[low2])/2; } if(high1 - low1 == 1){ return (double)(Math.max(arr1[low1], arr2[low2]) + Math.min(arr1[high1], arr2[high2]))/2; } double med1 = getMedian(arr1,low1,high1); double med2 = getMedian(arr2,low1,high2); if(med1 <= med2){ if((high1-low1 + 1) % 2 == 0){ low1 = (high1+low1)/2; high2 = (high2+low2)/2 + 1; }else{ low1 = (low1+high1)/2; high2 = (low2+high2)/2; } } else{ if((high1-low1 + 1) % 2 == 0){ low2 = (high2+low2)/2; high1 = (high1+low1)/2 + 1; }else{ low2 = (low2+high2)/2; high1 = (low1+high1)/2; } } } } private double getMedian(int arr[],int low,int high){ int len = high - low+1; if(len % 2 == 0){ return (arr[low + len/2] + arr[low+ len/2-1])/2; }else{ return arr[low+len/2]; } } public static void main(String args[]){ int arr1[] = {1,2,3,4,6}; int arr2[] = {-1,5,6,7,8}; MedianOfTwoSortedArray mts = new MedianOfTwoSortedArray(); System.out.println(mts.median(arr1, arr2)); } } ================================================ FILE: src/com/interview/binarysearch/MedianOfTwoSortedArrayOfDifferentLength.java ================================================ package com.interview.binarysearch; /** * There are two sorted arrays nums1 and nums2 of size m and n respectively. * Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)). * * Solution * Take minimum size of two array. Possible number of partitions are from 0 to m in m size array. * Try every cut in binary search way. When you cut first array at i then you cut second array at (m + n + 1)/2 - i * Now try to find the i where a[i-1] <= b[j] and b[j-1] <= a[i]. So this i is partition around which lies the median. * * Time complexity is O(log(min(x,y)) * Space complexity is O(1) * * https://leetcode.com/problems/median-of-two-sorted-arrays/ * https://discuss.leetcode.com/topic/4996/share-my-o-log-min-m-n-solution-with-explanation/4 */ public class MedianOfTwoSortedArrayOfDifferentLength { public double findMedianSortedArrays(int input1[], int input2[]) { //if input1 length is greater than switch them so that input1 is smaller than input2. if (input1.length > input2.length) { return findMedianSortedArrays(input2, input1); } int x = input1.length; int y = input2.length; int low = 0; int high = x; while (low <= high) { int partitionX = (low + high)/2; int partitionY = (x + y + 1)/2 - partitionX; //if partitionX is 0 it means nothing is there on left side. Use -INF for maxLeftX //if partitionX is length of input then there is nothing on right side. Use +INF for minRightX int maxLeftX = (partitionX == 0) ? Integer.MIN_VALUE : input1[partitionX - 1]; int minRightX = (partitionX == x) ? Integer.MAX_VALUE : input1[partitionX]; int maxLeftY = (partitionY == 0) ? Integer.MIN_VALUE : input2[partitionY - 1]; int minRightY = (partitionY == y) ? Integer.MAX_VALUE : input2[partitionY]; if (maxLeftX <= minRightY && maxLeftY <= minRightX) { //We have partitioned array at correct place // Now get max of left elements and min of right elements to get the median in case of even length combined array size // or get max of left for odd length combined array size. if ((x + y) % 2 == 0) { return ((double)Math.max(maxLeftX, maxLeftY) + Math.min(minRightX, minRightY))/2; } else { return (double)Math.max(maxLeftX, maxLeftY); } } else if (maxLeftX > minRightY) { //we are too far on right side for partitionX. Go on left side. high = partitionX - 1; } else { //we are too far on left side for partitionX. Go on right side. low = partitionX + 1; } } //Only we we can come here is if input arrays were not sorted. Throw in that scenario. throw new IllegalArgumentException(); } public static void main(String[] args) { int[] x = {1, 3, 8, 9, 15}; int[] y = {7, 11, 19, 21, 18, 25}; MedianOfTwoSortedArrayOfDifferentLength mm = new MedianOfTwoSortedArrayOfDifferentLength(); mm.findMedianSortedArrays(x, y); } } ================================================ FILE: src/com/interview/binarysearch/MinimumInSortedRotatedArray.java ================================================ package com.interview.binarysearch; /** * https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/ */ public class MinimumInSortedRotatedArray { public int findMin(int[] nums) { int low = 0; int high = nums.length - 1; while (low < high) { int middle = (low + high)/2; if ((middle == 0 && nums[middle] < nums[middle + 1]) || (middle > 0 && nums[middle] < nums[middle - 1])) { return nums[middle]; } else if (nums[middle] > nums[high]) { low = middle + 1; } else { high = middle - 1; } } return nums[low]; } } ================================================ FILE: src/com/interview/binarysearch/MissingNumberInConsecutiveNumbers.java ================================================ package com.interview.binarysearch; /** * Find missing number in consecutive numbers. */ public class MissingNumberInConsecutiveNumbers { public Integer findMissing(int arr[]){ int lowNum = arr[0]; int low = 0; int high = arr.length -1; int middle = (low + high)/2; while(low <= high){ middle = (low + high)/2; if(arr[middle] == (middle+1 + lowNum) && middle-1 >=0 && arr[middle-1] == (middle + lowNum-1)){ return middle + lowNum; } else if((middle + lowNum) == arr[middle]){ low = middle+1; }else { high = middle-1; } } return null; } public static void main(String args[]){ int arr[] = {3,4,5,6,7,8,9,10,11,12}; int arr1[] = {-5,-4,-3,-1,0,1,2,3}; MissingNumberInConsecutiveNumbers mn = new MissingNumberInConsecutiveNumbers(); System.out.println(mn.findMissing(arr1)); } } ================================================ FILE: src/com/interview/binarysearch/MonotonicallyIncreasingFunctionBecomesPositive.java ================================================ package com.interview.binarysearch; /** * http://www.geeksforgeeks.org/find-the-point-where-a-function-becomes-negative/ */ public class MonotonicallyIncreasingFunctionBecomesPositive { private int f(int x){ return x*x - 10*x - 20; } public int findPoint(){ int i=1; while(f(i) <=0 ){ i = i*2; } return binarySearch(i/2,i); } private int binarySearch(int start,int end){ int mid = (start+end)/2; while(start < end){ mid = (start+end)/2; if(f(mid) >0 && f(mid-1) <=0){ return mid; } if(f(mid) <=0 && f(mid+1)>0){ return mid+1; } if(f(mid) <= 0){ start = mid+1; }else{ end = mid-1; } } return mid; } public static void main(String args[]){ MonotonicallyIncreasingFunctionBecomesPositive mif = new MonotonicallyIncreasingFunctionBecomesPositive(); System.out.print(mif.findPoint()); } } ================================================ FILE: src/com/interview/binarysearch/NumberOfPairWithXPowerYGreaterThanYPowerX.java ================================================ package com.interview.binarysearch; import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** * http://www.geeksforgeeks.org/find-number-pairs-xy-yx/ */ public class NumberOfPairWithXPowerYGreaterThanYPowerX { public int countPairs(int X[],int Y[]){ Map hardCoded = new HashMap(); for(int i=0; i < Y.length; i++){ if(Y[i] < 4){ Integer count = hardCoded.get(Y[i]); if(count != null){ hardCoded.put(Y[i], count++); }else{ hardCoded.put(Y[i], 1); } } } Arrays.sort(Y); int countPairs = 0; for(int i=0 ; i < X.length; i++){ countPairs += count(X[i],Y,hardCoded); } return countPairs; } private int count(int x, int Y[],Map hardCount){ if(x == 0){ return 0; } if(x == 1){ return upperBound(0,Y); } int result = Y.length - upperBound(x,Y); result += (hardCount.containsKey(1) ? hardCount.get(1) : 0 ) + (hardCount.containsKey(0) ? hardCount.get(0) : 0); if(x == 2){ result -= (hardCount.containsKey(3) ? hardCount.get(3) : 0); } if(x == 3){ result += (hardCount.containsKey(2) ? hardCount.get(2) : 0); } return result; } private int upperBound(int x, int arr[]){ int low = 0; int high = arr.length-1; while(low <= high){ int mid = (low+high)/2; if(arr[mid] > x && (mid-1 < 0 || arr[mid-1] <= x)){ return mid; }else if(arr[mid] > x){ high = mid-1; }else{ low = mid+1; } } return -1; } public static void main(String args[]){ NumberOfPairWithXPowerYGreaterThanYPowerX nop = new NumberOfPairWithXPowerYGreaterThanYPowerX(); int X[] = {7,9,5,8,9,11,0,1,1,3}; int Y[] = {6,8,9,11,14,5,1,0,2,3,9}; System.out.println(nop.countPairs(X, Y)); } } ================================================ FILE: src/com/interview/binarysearch/PeakElement.java ================================================ package com.interview.binarysearch; /** * @author Tushar Roy * Date 01/17/2107 * A peak element is an element that is greater than its neighbors. Find index of peak element in the array. * * Space complexity is O(1) * Time complexity is O(n) * * https://leetcode.com/problems/find-peak-element/ */ public class PeakElement { public int findPeakElement(int[] nums) { int low = 0; int high = nums.length - 1; int middle = 0; while (low <= high) { middle = (low + high)/2; int before = Integer.MIN_VALUE; if (middle > 0) { before = nums[middle - 1]; } int after = Integer.MIN_VALUE; if (middle < nums.length - 1) { after = nums[middle + 1]; } if (nums[middle] > before && nums[middle] > after) { return middle; } else if (before > after) { high = middle - 1; } else { low = middle + 1; } } return middle; } public static void main(String args[]){ int arr[] = {10,5,15,2,23,90,67}; PeakElement pe = new PeakElement(); System.out.println(pe.findPeakElement(arr)); int arr1[] = {10,20,30,40,50}; System.out.println(pe.findPeakElement(arr1)); int arr2[] = {100,90,80,70,60}; System.out.println(pe.findPeakElement(arr2)); } } ================================================ FILE: src/com/interview/binarysearch/SearchForRange.java ================================================ package com.interview.binarysearch; /** * Date 07/31/2016 * @author Tushar Roy * * Given a sorted array of integers, find the starting and ending position of a given target value. * * Time complexity O(logn) * Space complexity O(1) * * https://leetcode.com/problems/search-for-a-range/ */ public class SearchForRange { public int[] searchRange(int[] nums, int target) { int first = firstOccurence(nums, target); if (first == -1) { return new int[]{-1, -1}; } int last = lastOccurence(nums, target); return new int[]{first, last}; } private int firstOccurence(int[] nums, int target) { int low = 0; int high = nums.length - 1; while (low <= high) { int mid = low + (high - low)/2; if (nums[mid] == target && (mid == 0 || nums[mid - 1] < target)) { return mid; } else if (nums[mid] >= target) { high = mid - 1; } else { low = mid + 1; } } return -1; } private int lastOccurence(int[] nums, int target) { int low = 0; int high = nums.length - 1; while (low <= high) { int mid = low + (high - low)/2; if (nums[mid] == target && (mid == nums.length - 1 || nums[mid + 1] > target)) { return mid; } else if (nums[mid] <= target) { low = mid + 1; } else { high = mid - 1; } } return -1; } public static void main(String args[]) { SearchForRange searchForRange = new SearchForRange(); int[] nums = {0, 1, 1, 3, 6, 9, 11}; int[] r = searchForRange.searchRange(nums, 11); System.out.println(r[0] + " " + r[1]); r = searchForRange.searchRange(nums, 0); System.out.println(r[0] + " " + r[1]); } } ================================================ FILE: src/com/interview/binarysearch/SearchInsertPosition.java ================================================ package com.interview.binarysearch; /** * https://leetcode.com/problems/search-insert-position/ */ public class SearchInsertPosition { public int searchInsert(int[] nums, int target) { int low = 0; int high = nums.length - 1; while (low <= high) { int middle = (low + high)/2; if (nums[middle] == target) { return middle; } if (nums[middle] < target && (middle == nums.length - 1 || nums[middle + 1] > target)) { return middle + 1; } if (nums[middle] < target) { low = middle + 1; } else { high = middle - 1; } } return 0; } } ================================================ FILE: src/com/interview/binarysearch/SortedAndRotatedArraySearch.java ================================================ package com.interview.binarysearch; /** * @author Tushar Roy * Date 01/22/17 * * Search in sorted and rotated array. In one version duplicate is not allowed and * in another version duplicate is allowed. * * Time complexity with no duplicate - O(logn) * Time complexity with duplicates - O(n) * * https://leetcode.com/problems/search-in-rotated-sorted-array/ * https://leetcode.com/problems/search-in-rotated-sorted-array-ii/ */ public class SortedAndRotatedArraySearch { /** * Duplicates are not allowed in arr. */ public int search(int arr[],int search){ int low =0; int high = arr.length-1; while(low <= high){ int mid = (low + high)/2; if(arr[mid] == search){ return mid; } if(arr[mid] < arr[high]){ if(arr[mid] < search && search <= arr[high]){ low = mid+1; }else{ high = mid-1; } }else{ if(search >= arr[low] && search < arr[mid]){ high = mid-1; }else{ low = mid+1; } } } return -1; } /** * Duplicates are allowed in arr. */ public boolean searchWithDuplicates(int[] arr, int search) { int low =0; int high = arr.length-1; while(low <= high){ int mid = (low + high)/2; if(arr[mid] == search) { return true; } //if low is same as mid then increment low. if (arr[mid] == arr[low]) { low++; } else if (arr[mid] == arr[high]) { //if high is same as mid then decrement high. high--; } else if (arr[mid] < arr[high]) { if(arr[mid] < search && search <= arr[high]) { low = mid + 1; } else { high = mid - 1; } } else { if(search >= arr[low] && search < arr[mid]) { high = mid - 1; } else { low = mid + 1; } } } return false; } public static void main(String args[]){ SortedAndRotatedArraySearch ras = new SortedAndRotatedArraySearch(); int arr1[] = {1,2,5,6,7,8,11,21}; System.out.print(ras.search(arr1, 1)); System.out.print(ras.search(arr1, 5)); System.out.print(ras.search(arr1, 22)); System.out.println(); int arr2[] = {18,21,1,2,5,6,7,8,10,15}; System.out.print(ras.search(arr2, 1)); System.out.print(ras.search(arr2, 5)); System.out.print(ras.search(arr2, 10)); System.out.print(ras.search(arr2, 14)); System.out.println(); int arr3[] = {7,8,15,17,18,21,1,2,5,6}; System.out.print(ras.search(arr3, 1)); System.out.print(ras.search(arr3, 5)); System.out.print(ras.search(arr3, 10)); System.out.print(ras.search(arr3, 7)); System.out.print(ras.search(arr3, 6)); System.out.print(ras.search(arr3, 16)); } } ================================================ FILE: src/com/interview/binarysearch/SquareRootOfNumber.java ================================================ package com.interview.binarysearch; /** * * https://leetcode.com/problems/sqrtx/ */ public class SquareRootOfNumber { public int mySqrt(int x) { if (x == 0) return 0; int left = 1, right = x; while (true) { int mid = left + (right - left)/2; if (mid > x/mid) { right = mid - 1; } else { if (mid + 1 > x/(mid + 1)) return mid; left = mid + 1; } } } } ================================================ FILE: src/com/interview/bits/AddTwoNumberInBinaryRepresentation.java ================================================ package com.interview.bits; /** * http://www.geeksforgeeks.org/add-two-bit-strings/ * http://www.geeksforgeeks.org/binary-representation-of-a-given-number/ * http://www.geeksforgeeks.org/add-two-numbers-without-using-arithmetic-operators/ */ public class AddTwoNumberInBinaryRepresentation { public int add(char[] num1,char[] num2){ int index1 = num1.length -1; int index2 = num2.length -1; int carry = 0; int result = 0; int index = 0; while(index1 >= 0 && index2 >= 0){ int r1 = num1[index1] - '0'; int r2 = num2[index2] - '0'; result = result | (r1^r2^carry)<= 0){ int r1 = num1[index1] - '0'; result = result | (r1^carry)<= 0){ int r2 = num1[index2] - '0'; result = result | (r2^carry)<>>1){ if((num & i) > 0){ System.out.print("1"); }else{ System.out.print("0"); } } } public static void main(String args[]){ AddTwoNumberInBinaryRepresentation anp = new AddTwoNumberInBinaryRepresentation(); char num1[] = "1010001110".toCharArray(); char num2[] = "10011".toCharArray(); int result = anp.add(num1, num2); System.out.println(anp.addTwoNumbersWithoutArithmeticOperator(296, 5662)); System.out.println(anp.addTwoNumbersWithoutArithmeticOperatorFaster(296, 5662)); anp.printResult(result); } } ================================================ FILE: src/com/interview/bits/BitRotation.java ================================================ package com.interview.bits; /* * http://www.geeksforgeeks.org/rotate-bits-of-an-integer/ */ public class BitRotation { public byte rotateLeft(byte num, int d){ return (byte)((num << d) | (num >>> (8-d))); } public static void main(String args[]){ BitRotation br = new BitRotation(); System.out.println(br.rotateLeft((byte)28, 2)); } } ================================================ FILE: src/com/interview/bits/ByteAsStorage.java ================================================ package com.interview.bits; public class ByteAsStorage { void useByteAsBoolean(boolean[] visited){ byte[] bytes = new byte[(int)(Math.ceil(visited.length*1.0/8))]; for(int i=0; i < visited.length; i++){ int row = i/8; int col = i%8; if(visited[i]){ bytes[row] = (byte)(bytes[row] | (byte)(1<= 1){ System.out.print("True"); }else{ System.out.print("False"); } } } public static void main(String args[]){ boolean visited[] = {true,false,true,true,false}; ByteAsStorage bas = new ByteAsStorage(); bas.useByteAsBoolean(visited); } } ================================================ FILE: src/com/interview/bits/CountBits.java ================================================ package com.interview.bits; /** * http://www.geeksforgeeks.org/count-set-bits-in-an-integer/ */ public class CountBits { public CountBits(){ preCalculate(); } public int countBits(int num){ int count=0; while(num > 0){ num &= num-1; count++; } return count; } private int count[] = new int[256]; void preCalculate(){ for(int i=0; i < 256; i++){ count[i] = countBits(i); } } public int countBitsFaster(int num){ //get 8 bits at a time and check count from count array int total = 0; int mask = (1<<8) - 1; for(int i=0 ; i < 4; i++){ total += count[num & mask]; num = num>>>8; } return total; } //http://bits.stephan-brumme.com/countBits.html public int countBitsEvenFaster(int x){ // count bits of each 2-bit chunk x = x - ((x >> 1) & 0x55555555); // count bits of each 4-bit chunk x = (x & 0x33333333) + ((x >> 2) & 0x33333333); // count bits of each 8-bit chunk x = x + (x >> 4); // mask out junk x &= 0xF0F0F0F; // add all four 8-bit chunks return (x * 0x01010101) >> 24; } public static void main(String args[]){ CountBits cb = new CountBits(); System.out.println(cb.countBits(3636363)); System.out.println(cb.countBitsFaster(3636363)); System.out.println(cb.countBitsEvenFaster(3636363)); } } ================================================ FILE: src/com/interview/bits/CountingBitsTillNum.java ================================================ package com.interview.bits; /** * Date 04/03/2016 * @author Tushar Roy * * Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate * the number of 1's in their binary representation and return them as an array. * * Time complexity O(n) * Space complexity O(n) * * https://leetcode.com/problems/counting-bits/ */ public class CountingBitsTillNum { public int[] countBits(int num) { if (num == 0) { return new int[1]; } int[] count = new int[num + 1]; count[0] = 0; int n = 1; int start = n; while (start <= num) { start = n; count[start++] = 1; int end = n<<1; while (start < end && start <= num) { count[start] = 1 + count[start - n]; start++; } n = n<<1; } return count; } } ================================================ FILE: src/com/interview/bits/DrawHorizontalLine.java ================================================ package com.interview.bits; /** * Exercise 5.8 150qs */ public class DrawHorizontalLine { public void draw(byte[] screen, int width, int x1, int x2,int y){ int pos1 = y*width + x1; int pos2 = y*width + x2; int start = pos1; while(start <= pos2){ int row = start/8; int col = start%8; screen[row] = (byte)(screen[row] | 1<>i; } result = result | (sum%3)< grayCode(int n) { List result = new LinkedList<>(); for (int i = 0; i < 1<>1); } return result; } public static void main(String args[]) { GrayCode gc = new GrayCode(); System.out.println(gc.grayCode(4)); } } ================================================ FILE: src/com/interview/bits/InsertMintoNiTojBits.java ================================================ package com.interview.bits; /** * Exercise 5.1 150 qs */ public class InsertMintoNiTojBits { public int insert(int M,int N, int i, int j){ int mask = 1<<(j+1) -1; mask = mask< b.length() - a.length()); int[] masks = new int[words.length]; // alphabet masks for(int i = 0; i < masks.length; i++){ for(char c: words[i].toCharArray()){ masks[i] |= 1 << (c - 'a'); } } for(int i = 0; i < masks.length; i++){ if(words[i].length() * words[i].length() <= max) { break; //prunning } for(int j = i + 1; j < masks.length; j++){ if((masks[i] & masks[j]) == 0){ max = Math.max(max, words[i].length() * words[j].length()); break; //prunning } } } return max; } } ================================================ FILE: src/com/interview/bits/MissingNumbers.java ================================================ package com.interview.bits; class Pair{ int x; int y; } /** * http://www.geeksforgeeks.org/find-the-two-repeating-elements-in-a-given-array/ * http://www.geeksforgeeks.org/find-a-repeating-and-a-missing-number/ */ public class MissingNumbers { public Pair findMissingAndRepeated(int arr[], int n){ int xor = 0; for(int i=0; i < arr.length; i++){ xor = xor ^ arr[i]; } for(int i=1; i <= n; i++){ xor = xor ^ i; } xor = xor & ~(xor-1); int set1 = 0; int set2 = 0; for(int i=0; i < arr.length; i++){ if((arr[i] & xor) > 0){ set1 ^= arr[i]; }else{ set2 ^= arr[i]; } } Pair p = new Pair(); for(int i=1; i <= n; i++){ if((i & xor) > 0){ set1 ^= i; }else{ set2 ^= i; } } p.x = set1; p.y = set2; return p; } public Pair findTwoMissingNumber(int arr[], int n){ int xor = 0; for(int i=0; i < arr.length; i++){ xor = xor ^ arr[i]; } for(int i=1; i <= n; i++){ xor = xor ^ i; } xor = xor & ~(xor-1); int set1 = 0; int set2 = 0; for(int i=0; i < arr.length; i++){ if((arr[i] & xor) > 0){ set1 ^= arr[i]; }else{ set2 ^= arr[i]; } } Pair p = new Pair(); for(int i=1; i <= n; i++){ if((i & xor) > 0){ set1 ^= i; }else{ set2 ^= i; } } p.x = set1; p.y = set2; return p; } public static void main(String args[]){ MissingNumbers mn = new MissingNumbers(); int arr[] = {1,2,3,5,5}; Pair p = mn.findMissingAndRepeated(arr, 5); System.out.println(p.x + " " + p.y); int arr1[] = {1,5,3,6}; p = mn.findMissingAndRepeated(arr1, 6); System.out.println(p.x + " " + p.y); } } ================================================ FILE: src/com/interview/bits/NextHigherAndNextLowerWithSameNumberBits.java ================================================ package com.interview.bits; /** * Exercise 5.3 150 qs */ public class NextHigherAndNextLowerWithSameNumberBits { public int nextHigher(int n){ int i = 1; int first1 = 0; //go till you find first 1 while((n & i) == 0){ i = i << 1; first1++; } //count number of 1s before first 0 int count1s = 0; while((n & i) > 0){ i = i <<1; count1s++; } count1s--; //change this first 0 after 1 to 1 n = n^i; n = n ^ (i>>1); int mask = ~(1<<(first1 + count1s) -1); n = mask & n; n = n | ((1< 0){ i = i << 1; first0++; } int count0s = 0; while((n & i) == 0){ i = i <<1; count0s++; } count0s--; //change this first 0 after 1 to 1 n = n^i; n = n ^ (i>>1); int mask = (1< 0 && (num & (num-1)) == 0){ return num; } while((num & (num-1)) > 0){ num = num & (num-1); } return num<<1; } public static void main(String args[]){ NextPowerOf2 np = new NextPowerOf2(); System.out.println(np.nextPowerOf2(4)); } } ================================================ FILE: src/com/interview/bits/NumberOccuringOddTimes.java ================================================ package com.interview.bits; /** * http://www.geeksforgeeks.org/find-the-number-occurring-odd-number-of-times/ * http://www.geeksforgeeks.org/find-two-non-repeating-elements-in-an-array-of-repeating-elements/ */ public class NumberOccuringOddTimes { public int oneNumberOccuringOddTimes(int arr[]){ int r = 0; for(int i=0; i < arr.length; i++){ r = r^arr[i]; } return r; } class Pair{ int a; int b; } public Pair twoNumbersOccuringOddTimes(int arr[]){ int r = 0; for(int i=0; i < arr.length; i++){ r = r^arr[i]; } r = r & ~(r-1); int r1 = 0; int r2 = 0; for(int i=0; i < arr.length; i++){ if((r&arr[i]) == 0){ r1 = r1^arr[i]; }else{ r2 = r2^arr[i]; } } Pair p = new Pair(); p.a = r1; p.b = r2; return p; } public static void main(String args[]){ NumberOccuringOddTimes noot = new NumberOccuringOddTimes(); int arr[] = {1,2,9,9,2,1,9,7,2,1,9,1}; Pair p = noot.twoNumbersOccuringOddTimes(arr); System.out.print(p.a + " " + p.b); } } ================================================ FILE: src/com/interview/bits/NumberOfBitsFlipToConvertNToM.java ================================================ package com.interview.bits; /** * Exercise 5.5 150 qs */ public class NumberOfBitsFlipToConvertNToM { public int number(int m, int n){ int r = n^m; int count = 0; while(r != 0){ r = r & (r-1); count++; } return count; } public static void main(String args[]){ NumberOfBitsFlipToConvertNToM nb = new NumberOfBitsFlipToConvertNToM(); System.out.println(nb.number(31, 14)); } } ================================================ FILE: src/com/interview/bits/RealNumberToBinary.java ================================================ package com.interview.bits; /** * Exercise 5.2 150 qs */ public class RealNumberToBinary { public void print(double num){ if(num > 1 || num < 0){ System.out.println("ERROR"); return; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("0."); while(num > 0){ num = num*2; int r = (int)num ; stringBuilder.append(r); num = num -r; if(stringBuilder.length() > 32){ System.out.println("ERROR"); return; } } System.out.println(stringBuilder); } public static void main(String args[]){ RealNumberToBinary rnb = new RealNumberToBinary(); rnb.print(0.8125); rnb.print(0.72); } } ================================================ FILE: src/com/interview/bits/RepeatedDnaSequence.java ================================================ package com.interview.bits; import java.util.*; /** * Date 03/08/2016 * @author Tushar Roy * * Find repeated sequence of length 10 in string consisting of A,C,G,T * * Time complexity is O(n) * Space complexity is O(n) * * https://leetcode.com/problems/repeated-dna-sequences/ */ public class RepeatedDnaSequence { private static final int mask = 0xFFFFF; private static final int mask1 = 3; public List findRepeatedDnaSequences(String s) { if (s.length() < 10) { return Collections.emptyList(); } Set set = new HashSet<>(); int val = 0; for (int i = 0; i < 10; i++) { val = add(val, s.charAt(i)); } set.add(val); List result = new ArrayList<>(); createString(val); Set repeatSet = new HashSet<>(); for (int i = 10; i < s.length(); i++) { val = add(val, s.charAt(i)); if (set.contains(val) && !repeatSet.contains(val)) { result.add(createString(val)); repeatSet.add(val); } else { set.add(val); } } return result; } private String createString(int input) { StringBuffer sb = new StringBuffer(); for (int i = 9; i >= 0; i--) { sb.append(getChar(input>>(i*2) & mask1)); } return sb.toString(); } private int add(int input, char ch) { int val = getVal(ch); input = input<<2; input = input & mask; return input | val; } private int getVal(char ch) { switch(ch) { case 'A': return 0; case 'C': return 1; case 'G': return 2; case 'T': return 3; default: throw new IllegalArgumentException(); } } private char getChar(int val) { switch (val) { case 0: return 'A'; case 1: return 'C'; case 2: return 'G'; case 3: return 'T'; default: throw new IllegalArgumentException(); } } public static void main(String args[]) { RepeatedDnaSequence rds = new RepeatedDnaSequence(); List result = rds.findRepeatedDnaSequences("AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"); System.out.print(result); } } ================================================ FILE: src/com/interview/bits/ReverseBits.java ================================================ package com.interview.bits; /** * http://www.geeksforgeeks.org/write-an-efficient-c-program-to-reverse-bits-of-a-number/ */ public class ReverseBits { public int reverse(int num){ //assuming int is 32 bits. int result = 0; int r1 = 1; for(int i=31; i >= 0; i--,r1<<=1){ if((num & 1<> and << while((k & (k-1))!= 0){ result += n; k--; } while(k > 1){ n = n<<1; k = k>>1; } return result + n; } public int fastSquare(int n){ return fastSquareRec(n, n); } /** * Start with 9,9. Then take 1 and keep left shifting 1 till you find number * less than 9 but power of 2. Then shift 9 by that many powers and repeat * the process with whatever is left between that number and 9. */ private int fastSquareRec(int n, int leftToMultiply){ if(leftToMultiply <= 0){ return 0; } int k = 1; int count=0; while(k <= leftToMultiply){ k = k<<1; count++; } k = k>>1; count--; return (n<> 1 & mask2); } public static void main(String args[]){ SwapOddEvenBits soe = new SwapOddEvenBits(); System.out.println(soe.swap(697)); } } ================================================ FILE: src/com/interview/bits/SwapTwoBits.java ================================================ package com.interview.bits; /** * http://www.careercup.com/question?id=17542662 */ public class SwapTwoBits { public int swap(int num,int i, int j){ int t1 = (num & 1<>i ^ (num & 1<>j) != 0){ num ^= 1< 1001 -> 101 -> 11 * 1010 -> 110 -> 101 -> 11 * * No matter which route you take it leads to same result so just looking at swaps you can say * which player will win * */ public class WinnerWithBeautifulNumber { public int winner(int n){ int sum = 0; int i =1; int result = 0; while( i <= n){ i = i*2; } i = i/2; while(i > 0){ if((n & i) != 0){ sum++; }else{ result += sum; } i = i/2; } if(result % 2 == 0){ return 2; }else{ return 1; } } public static void main(String args[]){ WinnerWithBeautifulNumber wwb = new WinnerWithBeautifulNumber(); System.out.println(wwb.winner(37)); System.out.println(wwb.winner(10)); } } ================================================ FILE: src/com/interview/dynamic/BitonicSequence.java ================================================ package com.interview.dynamic; /** * http://www.geeksforgeeks.org/dynamic-programming-set-15-longest-bitonic-subsequence/ */ public class BitonicSequence { public int longestSequence(int arr[]){ int lis[] = new int[arr.length]; int lds[] = new int[arr.length]; for(int i=0; i < arr.length; i++){ lis[i] = 1; lds[i] = 1; } for(int i=1 ; i < arr.length; i++){ for(int j=0; j < i ; j++){ if(arr[i] > arr[j]){ lis[i] = Math.max(lis[i], lis[j] + 1); } } } for(int i = arr.length-2; i >=0 ; i--){ for(int j = arr.length-1; j > i; j--){ if(arr[i] > arr[j]){ lds[i] = Math.max(lds[i], lds[j] + 1); } } } int max = 0; for(int i=0; i < arr.length; i++){ if(max < lis[i] + lds[i]-1){ max = lis[i] + lds[i] -1; } } return max; } public static void main(String args[]){ BitonicSequence bs = new BitonicSequence(); int[] arr = {1,4,3,7,2,1,8,11,13,0}; int r = bs.longestSequence(arr); System.out.print(r); } } ================================================ FILE: src/com/interview/dynamic/BoxStacking.java ================================================ package com.interview.dynamic; import java.util.Arrays; /** * Date 05/09/2015 * @author tusroy * * Given different dimensions and unlimited supply of boxes for each dimension, stack boxes * on top of each other such that it has maximum height but with caveat that length and width * of box on top should be strictly less than length and width of box under it. You can * rotate boxes as you like. * * 1) Create all rotations of boxes such that length is always greater or equal to width * 2) Sort boxes by base area in non increasing order (length * width). This is because box * with more area will never ever go on top of box with less area. * 3) Take T[] and result[] array of same size as total boxes after all rotations are done * 4) Apply longest increasing subsequence type of algorithm to get max height. * * If n number of dimensions are given total boxes after rotation will be 3n. * So space complexity is O(n) * Time complexity - O(nlogn) to sort boxes. O(n^2) to apply DP on it So really O(n^2) * * References * http://www.geeksforgeeks.org/dynamic-programming-set-21-box-stacking-problem/ * http://people.cs.clemson.edu/~bcdean/dp_practice/ */ public class BoxStacking { public int maxHeight(Dimension[] input) { //get all rotations of box dimension. //e.g if dimension is 1,2,3 rotations will be 2,1,3 3,2,1 3,1,2 . Here length is always greater //or equal to width and we can do that without loss of generality. Dimension[] allRotationInput = new Dimension[input.length * 3]; createAllRotation(input, allRotationInput); //sort these boxes in non increasing order by their base area.(length X width) Arrays.sort(allRotationInput); //apply longest increasing subsequence kind of algorithm on these sorted boxes. int T[] = new int[allRotationInput.length]; int result[] = new int[allRotationInput.length]; for (int i = 0; i < T.length; i++) { T[i] = allRotationInput[i].height; result[i] = i; } for (int i = 1; i < T.length; i++) { for (int j = 0; j < i; j++) { if (allRotationInput[i].length < allRotationInput[j].length && allRotationInput[i].width < allRotationInput[j].width) { if( T[j] + allRotationInput[i].height > T[i]){ T[i] = T[j] + allRotationInput[i].height; result[i] = j; } } } } //find max in T[] and that will be our max height. //Result can also be found using result[] array. int max = Integer.MIN_VALUE; for(int i=0; i < T.length; i++){ if(T[i] > max){ max = T[i]; } } return max; } //create all rotations of boxes, always keeping length greater or equal to width private void createAllRotation(Dimension[] input, Dimension[] allRotationInput) { int index = 0; for (int i = 0; i < input.length; i++) { allRotationInput[index++] = Dimension.createDimension( input[i].height, input[i].length, input[i].width); allRotationInput[index++] = Dimension.createDimension( input[i].length, input[i].height, input[i].width); allRotationInput[index++] = Dimension.createDimension( input[i].width, input[i].length, input[i].height); } } public static void main(String args[]) { BoxStacking bs = new BoxStacking(); Dimension input[] = { new Dimension(3, 2, 5), new Dimension(1, 2, 4) }; int maxHeight = bs.maxHeight(input); System.out.println("Max height is " + maxHeight); assert 11 == maxHeight; } } /** * Utility class to hold dimensions * @author tusroy * */ class Dimension implements Comparable { int height; int length; int width; Dimension(int height, int length, int width) { this.height = height; this.length = length; this.width = width; } Dimension() { } static Dimension createDimension(int height, int side1, int side2) { Dimension d = new Dimension(); d.height = height; if (side1 >= side2) { d.length = side1; d.width = side2; } else { d.length = side2; d.width = side1; } return d; } /** * Sorts by base area(length X width) */ @Override public int compareTo(Dimension d) { if (this.length * this.width >= d.length * d.width) { return -1; } else { return 1; } } @Override public String toString() { return "Dimension [height=" + height + ", length=" + length + ", width=" + width + "]"; } } ================================================ FILE: src/com/interview/dynamic/BreakMultipleWordsWithNoSpaceIntoSpace.java ================================================ package com.interview.dynamic; import java.util.*; /** * Date 08/01/2014 * @author tusroy * * Given a string and a dictionary, split this string into multiple words such that * each word belongs in dictionary. * * e.g peanutbutter -> pea nut butter * e.g Iliketoplay -> I like to play * * Solution * DP solution to this problem * if( input[i...j] belongs in dictionary) T[i][j] = i * else{ * T[i][j] = k if T[i][k-1] != -1 && T[k][j] != -1 * * Test cases * 1) Empty string * 2) String where entire string is in dictionary * 3) String which cannot be split into words which are in dictionary * 3) String which can be split into words which are in dictionary * */ public class BreakMultipleWordsWithNoSpaceIntoSpace { /** * Recursive and slow version of breaking word problem. * If no words can be formed it returns null */ public String breakWord(char[] str,int low,Set dictionary){ StringBuffer buff = new StringBuffer(); for(int i= low; i < str.length; i++){ buff.append(str[i]); if(dictionary.contains(buff.toString())){ String result = breakWord(str, i+1, dictionary); if(result != null){ return buff.toString() + " " + result; } } } if(dictionary.contains(buff.toString())){ return buff.toString(); } return null; } /** * Dynamic programming version for breaking word problem. * It returns null string if string cannot be broken into multipe words * such that each word is in dictionary. * Gives preference to longer words over splits * e.g peanutbutter with dict{pea nut butter peanut} it would result in * peanut butter instead of pea nut butter. */ public String breakWordDP(String word, Set dict){ int T[][] = new int[word.length()][word.length()]; for(int i=0; i < T.length; i++){ for(int j=0; j < T[i].length ; j++){ T[i][j] = -1; //-1 indicates string between i to j cannot be split } } //fill up the matrix in bottom up manner for(int l = 1; l <= word.length(); l++){ for(int i=0; i < word.length() -l + 1 ; i++){ int j = i + l-1; String str = word.substring(i,j+1); //if string between i to j is in dictionary T[i][j] is true if(dict.contains(str)){ T[i][j] = i; continue; } //find a k between i+1 to j such that T[i][k-1] && T[k][j] are both true for(int k=i+1; k <= j; k++){ if(T[i][k-1] != -1 && T[k][j] != -1){ T[i][j] = k; break; } } } } if(T[0][word.length()-1] == -1){ return null; } //create space separate word from string is possible StringBuffer buffer = new StringBuffer(); int i = 0; int j = word.length() -1; while(i < j){ int k = T[i][j]; if(i == k){ buffer.append(word.substring(i, j+1)); break; } buffer.append(word.substring(i,k) + " "); i = k; } return buffer.toString(); } /** * Prints all the words possible instead of just one combination. * Reference * https://leetcode.com/problems/word-break-ii/ */ public List wordBreakTopDown(String s, Set wordDict) { Map> dp = new HashMap<>(); int max = 0; for (String s1 : wordDict) { max = Math.max(max, s1.length()); } return wordBreakUtil(s, wordDict, dp, 0, max); } private List wordBreakUtil(String s, Set dict, Map> dp, int start, int max) { if (start == s.length()) { return Collections.singletonList(""); } if (dp.containsKey(start)) { return dp.get(start); } List words = new ArrayList<>(); for (int i = start; i < start + max && i < s.length(); i++) { String newWord = s.substring(start, i + 1); if (!dict.contains(newWord)) { continue; } List result = wordBreakUtil(s, dict, dp, i + 1, max); for (String word : result) { String extraSpace = word.length() == 0 ? "" : " "; words.add(newWord + extraSpace + word); } } dp.put(start, words); return words; } /** * Check if any one solution exists. * https://leetcode.com/problems/word-break/ */ public boolean wordBreakTopDownOneSolution(String s, Set wordDict) { Map dp = new HashMap<>(); int max = 0; for (String s1 : wordDict) { max = Math.max(max, s1.length()); } return wordBreakTopDownOneSolutionUtil(s, wordDict, 0, max, dp); } private boolean wordBreakTopDownOneSolutionUtil(String s, Set dict, int start, int max, Map dp) { if (start == s.length()) { return true; } if (dp.containsKey(start)) { return dp.get(start); } for (int i = start; i < start + max && i < s.length(); i++) { String newWord = s.substring(start, i + 1); if (!dict.contains(newWord)) { continue; } if (wordBreakTopDownOneSolutionUtil(s, dict, i + 1, max, dp)) { dp.put(start, true); return true; } } dp.put(start, false); return false; } public boolean wordBreakBottomUp(String s, List wordList) { boolean[] T = new boolean[s.length() + 1]; Set set = new HashSet<>(); for (String word : wordList) { set.add(word); } T[0] = true; for (int i = 1; i <= s.length(); i++) { for (int j = 0; j < i; j++) { if(T[j] && set.contains(s.substring(j, i))) { T[i] = true; break; } } } return T[s.length()]; } public static void main(String args[]){ Set dictionary = new HashSet(); dictionary.add("I"); dictionary.add("like"); dictionary.add("had"); dictionary.add("play"); dictionary.add("to"); String str = "Ihadliketoplay"; BreakMultipleWordsWithNoSpaceIntoSpace bmw = new BreakMultipleWordsWithNoSpaceIntoSpace(); String result1 = bmw.breakWordDP(str, dictionary); System.out.print(result1); } } ================================================ FILE: src/com/interview/dynamic/BurstBalloons.java ================================================ package com.interview.dynamic; /** * Date 03/02/2016 * @author Tushar Roy * * Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented * by array nums. You are asked to burst all the balloons. If the you burst balloon i you will * get nums[left] * nums[i] * nums[right] coins. Here left and right are adjacent indices of i. After the burst, * the left and right then becomes adjacent. * Find the maximum coins you can collect by bursting the balloons wisely. * * Time complexity O(n^3) * Space complexity O(n^2) * * Reference * https://leetcode.com/problems/burst-balloons/ */ public class BurstBalloons { /** * Dynamic programming solution. */ public int maxCoinsBottomUpDp(int[] nums) { int T[][] = new int[nums.length][nums.length]; for (int len = 1; len <= nums.length; len++) { for (int i = 0; i <= nums.length - len; i++) { int j = i + len - 1; for (int k = i; k <= j; k++) { //leftValue/rightValue is initially 1. If there is element on // left/right of k then left/right value will take that value. int leftValue = 1; int rightValue = 1; if (i != 0) { leftValue = nums[i-1]; } if (j != nums.length -1) { rightValue = nums[j+1]; } //before is initially 0. If k is i then before will //stay 0 otherwise it gets value T[i][k-1] //after is similarly 0 initially. if k is j then after will //stay 0 other will get value T[k+1][j] int before = 0; int after = 0; if (i != k) { before = T[i][k-1]; } if (j != k) { after = T[k+1][j]; } T[i][j] = Math.max(leftValue * nums[k] * rightValue + before + after, T[i][j]); } } } return T[0][nums.length - 1]; } /** * Recursive solution. */ public int maxCoinsRec(int nums[]) { int[] nums1 = new int[nums.length + 2]; nums1[0] = 1; nums1[nums1.length - 1] = 1; for (int i = 0; i < nums.length; i++) { nums1[i+1] = nums[i]; } return maxCoinsRecUtil(nums1); } private int maxCoinsRecUtil(int[] nums) { if (nums.length == 2) { return 0; } int max = 0; for (int i = 1; i < nums.length - 1; i++) { int val = nums[i - 1]*nums[i]*nums[i+1] + maxCoinsRecUtil(formNewArray(nums, i)); if (val > max) { max = val; } } return max; } private int[] formNewArray(int[] input, int doNotIncludeIndex) { int[] newArray = new int[input.length - 1]; int index = 0; for (int i = 0; i < input.length; i++) { if (i == doNotIncludeIndex) { continue; } newArray[index++] = input[i]; } return newArray; } public static void main(String args[]) { BurstBalloons bb = new BurstBalloons(); int input[] = {2, 4, 3, 5}; System.out.print(bb.maxCoinsBottomUpDp(input)); } } ================================================ FILE: src/com/interview/dynamic/CoinChanging.java ================================================ package com.interview.dynamic; import java.util.ArrayList; import java.util.List; /** * @Date 08/01/2014 * @author Tushar Roy * * Given a total and coins of certain denominations find number of ways total * can be formed from coins assuming infinity supply of coins * * References: * http://www.geeksforgeeks.org/dynamic-programming-set-7-coin-change/ */ public class CoinChanging { public int numberOfSolutions(int total, int coins[]){ int temp[][] = new int[coins.length+1][total+1]; for(int i=0; i <= coins.length; i++){ temp[i][0] = 1; } for(int i=1; i <= coins.length; i++){ for(int j=1; j <= total ; j++){ if(coins[i-1] > j){ temp[i][j] = temp[i-1][j]; } else{ temp[i][j] = temp[i][j-coins[i-1]] + temp[i-1][j]; } } } return temp[coins.length][total]; } /** * Space efficient DP solution */ public int numberOfSolutionsOnSpace(int total, int arr[]){ int temp[] = new int[total+1]; temp[0] = 1; for(int i=0; i < arr.length; i++){ for(int j=1; j <= total ; j++){ if(j >= arr[i]){ temp[j] += temp[j-arr[i]]; } } } return temp[total]; } /** * This method actually prints all the combination. It takes exponential time. */ public void printCoinChangingSolution(int total,int coins[]){ List result = new ArrayList<>(); printActualSolution(result, total, coins, 0); } private void printActualSolution(List result,int total,int coins[],int pos){ if(total == 0){ for(int r : result){ System.out.print(r + " "); } System.out.print("\n"); } for(int i=pos; i < coins.length; i++){ if(total >= coins[i]){ result.add(coins[i]); printActualSolution(result,total-coins[i],coins,i); result.remove(result.size()-1); } } } public static void main(String args[]){ CoinChanging cc = new CoinChanging(); int total = 15; int coins[] = {3,4,6,7,9}; System.out.println(cc.numberOfSolutions(total, coins)); System.out.println(cc.numberOfSolutionsOnSpace(total, coins)); cc.printCoinChangingSolution(total, coins); } } ================================================ FILE: src/com/interview/dynamic/CoinChangingMinimumCoin.java ================================================ package com.interview.dynamic; import java.text.Format; import java.util.HashMap; import java.util.Map; /** * Date 08/12/2013 * @author Tushar Roy * * Given a total and coins of certain denomination with infinite supply, what is the minimum number * of coins it takes to form this total. * * Time complexity - O(coins.size * total) * Space complexity - O(coins.size * total) * * Youtube video - * Topdown DP - https://youtu.be/Kf_M7RdHr1M * Bottom up DP - https://youtu.be/Y0ZqKpToTic */ public class CoinChangingMinimumCoin { /** * Top down dynamic programing. Using map to store intermediate results. * Returns Integer.MAX_VALUE if total cannot be formed with given coins */ public int minimumCoinTopDown(int total, int coins[], Map map) { //if total is 0 then there is nothing to do. return 0. if ( total == 0 ) { return 0; } //if map contains the result means we calculated it before. Lets return that value. if ( map.containsKey(total) ) { return map.get(total); } //iterate through all coins and see which one gives best result. int min = Integer.MAX_VALUE; for ( int i=0; i < coins.length; i++ ) { //if value of coin is greater than total we are looking for just continue. if( coins[i] > total ) { continue; } //recurse with total - coins[i] as new total int val = minimumCoinTopDown(total - coins[i], coins, map); //if val we get from picking coins[i] as first coin for current total is less // than value found so far make it minimum. if( val < min ) { min = val; } } //if min is MAX_VAL dont change it. Just result it as is. Otherwise add 1 to it. min = (min == Integer.MAX_VALUE ? min : min + 1); //memoize the minimum for current total. map.put(total, min); return min; } /** * Bottom up way of solving this problem. * Keep input sorted. Otherwise temp[j-arr[i]) + 1 can become Integer.Max_value + 1 which * can be very low negative number * Returns Integer.MAX_VALUE - 1 if solution is not possible. */ public int minimumCoinBottomUp(int total, int coins[]){ int T[] = new int[total + 1]; int R[] = new int[total + 1]; T[0] = 0; for(int i=1; i <= total; i++){ T[i] = Integer.MAX_VALUE-1; R[i] = -1; } for(int j=0; j < coins.length; j++){ for(int i=1; i <= total; i++){ if(i >= coins[j]){ if (T[i - coins[j]] + 1 < T[i]) { T[i] = 1 + T[i - coins[j]]; R[i] = j; } } } } printCoinCombination(R, coins); return T[total]; } private void printCoinCombination(int R[], int coins[]) { if (R[R.length - 1] == -1) { System.out.print("No solution is possible"); return; } int start = R.length - 1; System.out.print("Coins used to form total "); while ( start != 0 ) { int j = R[start]; System.out.print(coins[j] + " "); start = start - coins[j]; } System.out.print("\n"); } public static void main ( String args[] ) { int total = 13; int coins[] = {7, 3, 2, 6}; CoinChangingMinimumCoin cc = new CoinChangingMinimumCoin(); Map map = new HashMap<>(); int topDownValue = cc.minimumCoinTopDown(total, coins, map); int bottomUpValue = cc.minimumCoinBottomUp(total, coins); System.out.print(String.format("Bottom up and top down result %s %s", bottomUpValue, topDownValue)); } } ================================================ FILE: src/com/interview/dynamic/CountAs.java ================================================ package com.interview.dynamic; /** * http://www.geeksforgeeks.org/how-to-print-maximum-number-of-a-using-given-four-keys/ * Test cases * Negative number * Number less than 7 * Number greater than equal to 7 */ public class CountAs { public int countAsRec(int n){ if(n < 7){ return n; } int max = Integer.MIN_VALUE; int result = 0; for(int b=n-3; b > 0; b--){ result = (n-b-1)*countAs(b); if(max < result){ max = result; } } return max; } public int countAs(int n){ if(n < 7){ return n; } int T[] = new int[n+1]; for(int i=1; i < 7 ; i++){ T[i] = i; } for(int i=7; i <= n; i++){ for(int b = i-3; b > 0; b--){ T[i] = Math.max(T[i], T[b]*(i-b-1)); } } return T[n]; } public static void main(String args[]){ CountAs ca =new CountAs(); System.out.println(ca.countAsRec(25)); System.out.println(ca.countAs(25)); } } ================================================ FILE: src/com/interview/dynamic/CountNumberOfBinaryWithoutConsecutive1s.java ================================================ package com.interview.dynamic; /** * http://www.geeksforgeeks.org/count-number-binary-strings-without-consecutive-1s/ * It is really a straight up fibonacci series with values * 1,2,3,5,8,13.... * Look how we assign a[i] value of a[i-1] + b[i-1] and then b[i] becomes a[i] */ public class CountNumberOfBinaryWithoutConsecutive1s { public int count(int n){ int a[] = new int[n]; int b[] = new int[n]; a[0] = 1; b[0] = 1; for(int i=1; i < n; i++){ a[i] = a[i-1] + b[i-1]; b[i] = a[i-1]; } return a[n-1] + b[n-1]; } public int countSimple(int n){ int a = 1; int b = 1; for(int i=1; i < n; i++){ int tmp = a; a = a + b; b = tmp; } return a + b; } public static void main(String args[]){ CountNumberOfBinaryWithoutConsecutive1s cnb = new CountNumberOfBinaryWithoutConsecutive1s(); System.out.println(cnb.count(5)); } } ================================================ FILE: src/com/interview/dynamic/CountNumberOfTreePreorder.java ================================================ package com.interview.dynamic; /** * Given a preorder sequence how many unique trees can be created * Solution is catalan number. Number of tree is exactly same * as number of unique BST create with array of size n * * The way it works for preorder sequence is as follows * * Suppose our preorder sequence is 1 2 3 4 * So we need to compute following things * count(3)* 2 (combination of 2,3 and 4 on both side of 1) * count(1)*count(2) (combination of 2 on one side and 3, 4 on other side) * count(2)*count(1) (combinatino of 2,3 on one side and 4 on other side) * count(3)*2 can be broken into count(3)*count(0) + count(0)*count(3) * * So our final result is * count(0)*count(3) + count(1)*count(2) + count(2)*count(1) + count(3)*count(0) * which is a catalan number */ public class CountNumberOfTreePreorder { public int count(int num){ if(num == 0){ return 0; } int T[] = new int[num+1]; T[0] = 1; T[1] = 1; for(int i=2; i <= num; i++){ int sum = 0; for(int k=0; k < i; k++){ sum += T[k]*T[i-k-1]; } T[i] = sum; } return T[num]; } public int countRec(int num){ if(num == 0 || num ==1){ return 1; } int sum = 0; for(int i=1; i <= num; i++){ sum += countRec(i-1)*countRec(num-i); } return sum; } public static void main(String args[]){ CountNumberOfTreePreorder cn = new CountNumberOfTreePreorder(); System.out.println(cn.count(3)); System.out.println(cn.count(4)); System.out.println(cn.count(5)); System.out.println(cn.countRec(3)); System.out.println(cn.countRec(4)); System.out.println(cn.countRec(5)); } } ================================================ FILE: src/com/interview/dynamic/CountNumberOfTreesInBST.java ================================================ package com.interview.dynamic; /** * http://www.geeksforgeeks.org/program-nth-catalan-number/ * Count number of binary search tree created for array of size n */ public class CountNumberOfTreesInBST { int countTreesRec(int numKeys) { if (numKeys <=1) { return(1); } else { int sum = 0; int left, right, root; for (root=1; root<=numKeys; root++) { left = countTreesRec(root - 1); right = countTreesRec(numKeys - root); sum += left*right; } return(sum); } } public int countTrees(int n){ int T[] = new int[n+1]; T[0] = 1; T[1] = 1; for(int i=2; i <= n; i++){ for(int j=0; j = 0; j--){ if(end > markings[j]) { break; } } if(j == -1) { T[start][end] = 0; return 0; } if(i == j){ T[start][end] = end - start; return end - start; } int cost = end - start; int minCost = Integer.MAX_VALUE; for(int k=i; k <= j; k++) { int c1 = cutRodToMinimizeCost(markings, start, markings[k], T); int c2 = cutRodToMinimizeCost(markings, markings[k], end, T); if(c1 == Integer.MAX_VALUE || c2 == Integer.MAX_VALUE) { continue; } if(minCost > c1 + c2){ minCost = c1 + c2; } } if(minCost == Integer.MAX_VALUE) { T[start][end] = Integer.MAX_VALUE; return Integer.MAX_VALUE; } T[start][end] = cost + minCost; return cost + minCost; } public static void main(String args[]) { int markings[] = {2,3,6,7}; CutRodToMinimizeCost cr = new CutRodToMinimizeCost(); int cost = cr.cutRodToMinimizeCost(markings, 8); System.out.println(cost); } } ================================================ FILE: src/com/interview/dynamic/CuttingRod.java ================================================ package com.interview.dynamic; /** * http://www.geeksforgeeks.org/dynamic-programming-set-13-cutting-a-rod/ */ public class CuttingRod { public int maxValue(int price[]){ int max[] = new int[price.length+1]; for(int i=1; i <= price.length; i++){ for(int j=i; j <= price.length; j++){ max[j] = Math.max(max[j], max[j-i] + price[i-1]); } } return max[price.length]; } public int maxValue1(int price[]){ int max[] = new int[price.length+1]; for(int i=1; i <= price.length; i++){ max[i] = price[i-1]; } for(int i=1 ; i <= price.length; i++){ for(int j=1; j < i ; j++){ max[i] = Math.max(max[i], max[i-j] + max[j]); } } return max[price.length]; } public int recursiveMaxValue(int price[],int len){ if(len <= 0){ return 0; } int maxValue = 0; for(int i=0; i < len;i++){ int val = price[i] + recursiveMaxValue(price, len-i-1); if(maxValue < val){ maxValue = val; } } return maxValue; } public static void main(String args[]){ CuttingRod cr =new CuttingRod(); int[] price = {3,5,8,9,10,20,22,25}; long t1 = System.currentTimeMillis(); int r = cr.recursiveMaxValue(price,8); long t2 = System.currentTimeMillis(); System.out.println(r); System.out.println(t2 - t1); } } ================================================ FILE: src/com/interview/dynamic/DecodeWays.java ================================================ package com.interview.dynamic; import java.util.HashMap; import java.util.Map; /** * A message containing letters from A-Z is being encoded to numbers using the following mapping: * 1 -> A * 2 -> B * 3 -> C * 26-> Z * Given an encoded message containing digits, determine the total number of ways to decode it. * * https://leetcode.com/problems/decode-ways/ */ public class DecodeWays { public int numDecodings(String s) { if (s.length() == 0) { return 0; } Map count = new HashMap<>(); return numDecodingsUtil(s, 0, count); } public int numDecodingsUtil(String s, int start, Map count) { if (s.length() == start) { return 1; } if (count.containsKey(start)) { return count.get(start); } String s1 = s.substring(start, start + 1); if (s1.equals("0")) { count.put(start, 0); return 0; } int c1 = numDecodingsUtil(s, start + 1, count); int c2 = 0; if (start < s.length() - 1) { s1 = s.substring(start, start + 2); if (Integer.valueOf(s1) <= 26) { c2 = numDecodingsUtil(s, start + 2, count); } } count.put(start, c1 + c2); return c1 + c2; } } ================================================ FILE: src/com/interview/dynamic/DiceThrowWays.java ================================================ package com.interview.dynamic; /** * @author Tushar Roy * http://www.geeksforgeeks.org/dice-throw-problem/ * This solution assumes that 1,2,1 is different from 2,1,1 which is different from 1,1 2 * so total 3 ways are possible */ public class DiceThrowWays { public int numberOfWays(int n, int f, int k){ int T[][] = new int[n+1][k+1]; T[0][0] = 1; /* for(int i=0; i < T.length; i++){ T[0][i] = 1; }*/ for(int i=1; i <= n; i++){ for(int j =1; j <= i*f && j <= k ; j++){ if(j == i){ T[i][j] = 1; continue; } if(j < i){ continue; } for(int l =1; l <=f ;l++){ if(j >= l){ T[i][j] += T[i-1][j-l]; } } } } return T[n][k]; } public static void main(String args[]){ DiceThrowWays dtw = new DiceThrowWays(); System.out.println(dtw.numberOfWays(3, 3, 6)); } } ================================================ FILE: src/com/interview/dynamic/DistinctSubsequence.java ================================================ package com.interview.dynamic; /** * Date 03/20/2016 * @author Tushar Roy * * Given a string S and a string T, count the number of distinct subsequences of T in S. * * Time complexity O(n^2) * Space complexity O(n^2) * * https://leetcode.com/problems/distinct-subsequences/ */ public class DistinctSubsequence { public int numDistinct(String s, String t) { if (s.length() == 0 || t.length() == 0) { return 0; } int[][] T = new int[t.length() + 1][s.length() + 1]; for (int i = 0; i < T[0].length; i++) { T[0][i] = 1; } for (int i = 1; i < T.length; i++) { for (int j = 1; j < T[0].length; j++) { if (s.charAt(j - 1) == t.charAt(i - 1)) { T[i][j] = T[i-1][j-1] + T[i][j-1]; } else { T[i][j] = T[i][j-1]; } } } return T[t.length()][s.length()]; } public static void main(String args[]) { DistinctSubsequence ds = new DistinctSubsequence(); System.out.println(ds.numDistinct("abdacgblc", "abc")); } } ================================================ FILE: src/com/interview/dynamic/DungeonGame.java ================================================ package com.interview.dynamic; /** * Date 03/21/2016 * @author Tushar Roy * * Minimum life needed for knight to reach princess in 2D matrix. * * Time complexity O(n^2) * Space complexity O(n^2) * * https://leetcode.com/problems/dungeon-game/ */ public class DungeonGame { public int calculateMinimumHP(int[][] dungeon) { if (dungeon.length == 0 || dungeon[0].length == 0) { return 0; } int[][] health = new int[dungeon.length][dungeon[0].length]; int m = dungeon.length - 1; int n = dungeon[0].length - 1; health[m][n] = Math.max(1 - dungeon[m][n] , 1); for (int i = m - 1; i >= 0; i--) { health[i][n] = Math.max(health[i + 1][n] - dungeon[i][n], 1); } for (int i = n - 1; i >= 0; i--) { health[m][i] = Math.max(health[m][i+1] - dungeon[m][i], 1); } for (int i = m - 1; i >= 0; i--) { for (int j = n - 1; j >= 0; j--) { health[i][j] = Math.min(Math.max(health[i + 1][j] - dungeon[i][j], 1), Math.max(health[i][j + 1] - dungeon[i][j], 1)); } } return health[0][0]; } public static void main(String args[]) { DungeonGame dg = new DungeonGame(); int[][] dungeon = {{-2, -3, 3}, {-5, -10, 1}, {10, 30, -30}}; System.out.print(dg.calculateMinimumHP(dungeon)); } } ================================================ FILE: src/com/interview/dynamic/EditDistance.java ================================================ package com.interview.dynamic; import java.util.List; /** * Date 07/07/2014 * @author Tushar Roy * * Given two strings how many minimum edits(update, delete or add) is needed to convert one string to another * * Time complexity is O(m*n) * Space complexity is O(m*n) * * References: * http://www.geeksforgeeks.org/dynamic-programming-set-5-edit-distance/ * https://en.wikipedia.org/wiki/Edit_distance */ public class EditDistance { /** * Uses recursion to find minimum edits */ public int recEditDistance(char[] str1, char str2[], int len1,int len2){ if(len1 == str1.length){ return str2.length - len2; } if(len2 == str2.length){ return str1.length - len1; } return min(recEditDistance(str1, str2, len1 + 1, len2 + 1) + str1[len1] == str2[len2] ? 0 : 1, recEditDistance(str1, str2, len1, len2 + 1) + 1, recEditDistance(str1, str2, len1 + 1, len2) + 1); } /** * Uses bottom up DP to find the edit distance */ public int dynamicEditDistance(char[] str1, char[] str2){ int temp[][] = new int[str1.length+1][str2.length+1]; for(int i=0; i < temp[0].length; i++){ temp[0][i] = i; } for(int i=0; i < temp.length; i++){ temp[i][0] = i; } for(int i=1;i <=str1.length; i++){ for(int j=1; j <= str2.length; j++){ if(str1[i-1] == str2[j-1]){ temp[i][j] = temp[i-1][j-1]; }else{ temp[i][j] = 1 + min(temp[i-1][j-1], temp[i-1][j], temp[i][j-1]); } } } printActualEdits(temp, str1, str2); return temp[str1.length][str2.length]; } /** * Prints the actual edits which needs to be done. */ public void printActualEdits(int T[][], char[] str1, char[] str2) { int i = T.length - 1; int j = T[0].length - 1; while(true) { if (i == 0 || j == 0) { break; } if (str1[i-1] == str2[j-1]) { i = i-1; j = j-1; } else if (T[i][j] == T[i-1][j-1] + 1){ System.out.println("Edit " + str2[j-1] + " in string2 to " + str1[i-1] + " in string1"); i = i-1; j = j-1; } else if (T[i][j] == T[i-1][j] + 1) { System.out.println("Delete in string1 " + str1[i-1]); i = i-1; } else if (T[i][j] == T[i][j-1] + 1){ System.out.println("Delete in string2 " + str2[j-1]); j = j -1; } else { throw new IllegalArgumentException("Some wrong with given data"); } } } private int min(int a,int b, int c){ int l = Math.min(a, b); return Math.min(l, c); } public static void main(String args[]){ String str1 = "azced"; String str2 = "abcdef"; EditDistance editDistance = new EditDistance(); int result = editDistance.dynamicEditDistance(str1.toCharArray(), str2.toCharArray()); System.out.print(result); } } ================================================ FILE: src/com/interview/dynamic/EggDropping.java ================================================ package com.interview.dynamic; /** * http://www.geeksforgeeks.org/dynamic-programming-set-11-egg-dropping-puzzle/ */ public class EggDropping { public int calculate(int eggs, int floors){ int T[][] = new int[eggs+1][floors+1]; int c =0; for(int i=0; i <= floors; i++){ T[1][i] = i; } for(int e = 2; e <= eggs; e++){ for(int f = 1; f <=floors; f++){ T[e][f] = Integer.MAX_VALUE; for(int k = 1; k <=f ; k++){ c = 1 + Math.max(T[e-1][k-1], T[e][f-k]); if(c < T[e][f]){ T[e][f] = c; } } } } return T[eggs][floors]; } public int calculateRecursive(int eggs, int floors){ if(eggs == 1){ return floors; } if(floors == 0){ return 0; } int min = 1000; for(int i=1; i <= floors; i++){ int val = 1 + Math.max(calculateRecursive(eggs-1, i-1),calculateRecursive(eggs, floors-i)); if(val < min){ min = val; } } return min; } public static void main(String args[]){ EggDropping ed = new EggDropping(); int r = ed.calculate(3,100); System.out.println(r); } } ================================================ FILE: src/com/interview/dynamic/ExpressionEvaluation.java ================================================ package com.interview.dynamic; import java.util.HashSet; import java.util.Set; /** * Date 01/07/2016 * @author Tushar Roy * * Given an expression with +, -, * and / operators. Tell if expression can evaluate to given result with different * parenthesis combination. * e.g expresson is 2*3-1 and result is 4, function should return true since 2*(3-1) evaluate to 4. * * Time complexity is O(n^5) * Space complexity is O(n^3) */ public class ExpressionEvaluation { public boolean evaluate(char[] expression, int result) { int operands[] = new int[expression.length/2 + 1]; char operators[] = new char[expression.length/2]; int index1 = 0; int index2 = 0; operands[index1++] = expression[0] - '0'; for (int i = 1; i < expression.length; i += 2 ) { operators[index2++] = expression[i]; operands[index1++] = expression[i+1] - '0'; } Holder T[][] = new Holder[operands.length][operands.length]; for (int i = 0; i < T.length; i++) { for (int j = 0; j < T.length; j++) { T[i][j] = new Holder(); } } for (int i = 0; i < operands.length; i++) { T[i][i].add(operands[i]); } for (int l = 2; l <= T.length; l++) { for (int i = 0; i <= T.length - l; i++) { int j = i + l - 1; for (int k = i; k < j; k++) { for (int x : T[i][k].values()) { for (int y : T[k + 1][j].values()) { if (operators[k] == '/' && y == 0) { continue; } T[i][j].add(operate(operators[k], x, y)); } } } } } T[0][T.length-1].values().forEach((i -> System.out.print(i + " "))); for (int i : T[0][T.length - 1].values()) { if ( i == result) { return true; } } return false; } private int operate(char operator, int x, int y) { switch (operator) { case '+': return x + y; case '-': return x - y; case '*': return x*y; case '/': return x/y; default: throw new IllegalArgumentException(); } } static class Holder { private Set valueHolder = new HashSet<>(); void add(Integer ch) { valueHolder.add(ch); } Set values() { return valueHolder; } } public static void main(String args[]) { ExpressionEvaluation ee = new ExpressionEvaluation(); System.out.println(ee.evaluate("9*3+1/7".toCharArray(), 0)); } } ================================================ FILE: src/com/interview/dynamic/FibonacciSeries.java ================================================ package com.interview.dynamic; /** * Date 03/28/2015 * @author tusroy * * Fibonacci series * Given a number find the fibonacci series value for that number * e.g n = 3 -> 3 * n = 4 -> 5 * n = 5 -> 8 * * Solution * Recursively it can calculated very easily by f(n) = f(n-1) + f(n-2) * For Dp version we do not recalculate f(n-1) and f(n-2) but keep it in a and b * * Test cases * 1) Negative number * 2) 0 * 3) 1 * 4) Very high number * */ public class FibonacciSeries { /** * DP version where we do not recalculate values but just keep last 2 * calculate values */ public int fibonacciSeries(int n){ int n1 = 0, n2 = 1; int sum; if (n == n1 || n == n2) { return n; } for(int i=2; i <= n; i++){ sum = n1 + n2; n1 = n2; n2 = sum; } return n2; } /** * Recursive and slow version. Recalculates same value over and over again. * Chokes for n greater than 60 */ public int fibonacciSeriesRecursive(int n){ if(n == 1 || n == 0){ return n; } return fibonacciSeriesRecursive(n-1) + fibonacciSeriesRecursive(n-2); } public static void main(String args[]){ FibonacciSeries fs = new FibonacciSeries(); System.out.println(fs.fibonacciSeries(15)); System.out.println(fs.fibonacciSeriesRecursive(15)); } } ================================================ FILE: src/com/interview/dynamic/Immutable2DSumRangeQuery.java ================================================ package com.interview.dynamic; /** * Date 03/11/2016 * @author Tushar Roy * * Given a 2D array find the sum in given range defining a rectangle. * * Time complexity construction O(n*m) * Time complexity of query O(1) * Space complexity is O(n*m) * * Reference * https://leetcode.com/problems/range-sum-query-2d-immutable/ */ public class Immutable2DSumRangeQuery { private int[][] T; public Immutable2DSumRangeQuery(int[][] matrix) { int row = 0; int col = 0; if (matrix.length != 0) { row = matrix.length; col = matrix[0].length; } T = new int[row + 1][col + 1]; for (int i = 1; i < T.length; i++) { for (int j = 1; j < T[0].length; j++) { T[i][j] = T[i - 1][j] + T[i][j - 1] + matrix[i - 1][j - 1] - T[i - 1][j - 1]; } } } public int sumQuery(int row1, int col1, int row2, int col2) { row1++; col1++; row2++; col2++; return T[row2][col2] - T[row1 - 1][col2] - T[row2][col1 - 1] + T[row1 - 1][col1 - 1]; } public static void main(String args[]) { int[][] input = {{3, 0, 1, 4, 2}, {5, 6, 3, 2, 1}, {1, 2, 0, 1, 5}, {4, 1, 0, 1, 7}, {1, 0, 3, 0, 5}}; int[][] input1 = {{2,0,-3,4}, {6, 3, 2, -1}, {5, 4, 7, 3}, {2, -6, 8, 1}}; Immutable2DSumRangeQuery isr = new Immutable2DSumRangeQuery(input1); System.out.println(isr.sumQuery(1, 1, 2, 2)); } } ================================================ FILE: src/com/interview/dynamic/Knapsack01.java ================================================ package com.interview.dynamic; import java.util.HashMap; import java.util.Map; /** * Date 04/04/2014 * @author Tushar Roy * * 0/1 Knapsack Problem - Given items of certain weights/values and maximum allowed weight * how to pick items to pick items from this set to maximize sum of value of items such that * sum of weights is less than or equal to maximum allowed weight. * * Time complexity - O(W*total items) * * Youtube link * Topdown DP - https://youtu.be/149WSzQ4E1g * Bottomup DP - https://youtu.be/8LusJS5-AGo * * References - * http://www.geeksforgeeks.org/dynamic-programming-set-10-0-1-knapsack-problem/ * https://en.wikipedia.org/wiki/Knapsack_problem */ public class Knapsack01 { /** * Solves 0/1 knapsack in bottom up dynamic programming */ public int bottomUpDP(int val[], int wt[], int W){ int K[][] = new int[val.length+1][W+1]; for(int i=0; i <= val.length; i++){ for(int j=0; j <= W; j++){ if(i == 0 || j == 0){ K[i][j] = 0; continue; } if(j - wt[i-1] >= 0){ K[i][j] = Math.max(K[i-1][j], K[i-1][j-wt[i-1]] + val[i-1]); }else{ K[i][j] = K[i-1][j]; } } } return K[val.length][W]; } /** * Key for memoization */ class Index { int remainingWeight; int remainingItems; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Index index = (Index) o; if (remainingWeight != index.remainingWeight) return false; return remainingItems == index.remainingItems; } @Override public int hashCode() { int result = remainingWeight; result = 31 * result + remainingItems; return result; } } /** * Solves 0/1 knapsack in top down DP */ public int topDownRecursive(int values[], int weights[], int W) { //map of key(remainingWeight, remainingCount) to maximumValue they can get. Map map = new HashMap<>(); return topDownRecursiveUtil(values, weights, W, values.length, 0, map); } public int topDownRecursiveUtil(int values[], int weights[], int remainingWeight, int totalItems, int currentItem, Map map) { //if currentItem exceeds total item count or remainingWeight is less than 0 then //just return with 0; if(currentItem >= totalItems || remainingWeight <= 0) { return 0; } //fom a key based on remainingWeight and remainingCount Index key = new Index(); key.remainingItems = totalItems - currentItem -1; key.remainingWeight = remainingWeight; //see if key exists in map. If so then return the maximumValue for key stored in map. if(map.containsKey(key)) { return map.get(key); } int maxValue; //if weight of item is more than remainingWeight then try next item by skipping current item if(remainingWeight < weights[currentItem]) { maxValue = topDownRecursiveUtil(values, weights, remainingWeight, totalItems, currentItem + 1, map); } else { //try to get maximumValue of either by picking the currentItem or not picking currentItem maxValue = Math.max(values[currentItem] + topDownRecursiveUtil(values, weights, remainingWeight - weights[currentItem], totalItems, currentItem + 1, map), topDownRecursiveUtil(values, weights, remainingWeight, totalItems, currentItem + 1, map)); } //memoize the key with maxValue found to avoid recalculation map.put(key, maxValue); return maxValue; } public static void main(String args[]){ Knapsack01 k = new Knapsack01(); int val[] = {22, 20, 15, 30, 24, 54, 21, 32, 18, 25}; int wt[] = {4, 2, 3, 5, 5, 6, 9, 7, 8, 10}; int r = k.bottomUpDP(val, wt, 30); int r1 = k.topDownRecursive(val, wt, 30); System.out.println(r); System.out.println(r1); } } ================================================ FILE: src/com/interview/dynamic/LongestCommonSubsequence.java ================================================ package com.interview.dynamic; /** http://www.geeksforgeeks.org/dynamic-programming-set-4-longest-common-subsequence/ */ public class LongestCommonSubsequence { public int lcs(char str1[],char str2[],int len1, int len2){ if(len1 == str1.length || len2 == str2.length){ return 0; } if(str1[len1] == str2[len2]){ return 1 + lcs(str1,str2,len1+1,len2+1); } else{ return Math.max(lcs(str1,str2,len1+1,len2),lcs(str1,str2,len1,len2+1)); } } public int lcsDynamic(char str1[],char str2[]){ int temp[][] = new int[str1.length + 1][str2.length + 1]; int max = 0; for(int i=1; i < temp.length; i++){ for(int j=1; j < temp[i].length; j++){ if(str1[i-1] == str2[j-1]) { temp[i][j] = temp[i - 1][j - 1] + 1; } else { temp[i][j] = Math.max(temp[i][j-1],temp[i-1][j]); } if(temp[i][j] > max){ max = temp[i][j]; } } } return max; } public static void main(String args[]){ LongestCommonSubsequence lcs = new LongestCommonSubsequence(); String str1 = "ABCDGHLQR"; String str2 = "AEDPHR"; int result = lcs.lcsDynamic(str1.toCharArray(), str2.toCharArray()); System.out.print(result); } } ================================================ FILE: src/com/interview/dynamic/LongestCommonSubstring.java ================================================ package com.interview.dynamic; /** * http://en.wikipedia.org/wiki/Longest_common_substring_problem */ public class LongestCommonSubstring { /** * Dynamic way of calculating lcs */ public int longestCommonSubstring(char str1[], char str2[]){ int T[][] = new int[str1.length+1][str2.length+1]; int max = 0; for(int i=1; i <= str1.length; i++){ for(int j=1; j <= str2.length; j++){ if(str1[i-1] == str2[j-1]){ T[i][j] = T[i-1][j-1] +1; if(max < T[i][j]){ max = T[i][j]; } } } } return max; } /** * Recursive way of calculating lcs */ public int longestCommonSubstringRec(char str1[], char str2[], int pos1, int pos2, boolean checkEqual){ if(pos1 == -1 || pos2 == -1){ return 0; } if(checkEqual){ if(str1[pos1] == str2[pos2]){ return 1 + longestCommonSubstringRec(str1, str2, pos1-1, pos2-1, true); }else{ return 0; } } int r1 = 0; if(str1[pos1] == str2[pos2]){ r1 = 1 + longestCommonSubstringRec(str1, str2, pos1-1, pos2-1, true); } return Math.max(r1,Math.max(longestCommonSubstringRec(str1, str2, pos1-1, pos2, false), longestCommonSubstringRec(str1, str2, pos1, pos2-1,false))); } public static void main(String args[]){ LongestCommonSubstring lcs = new LongestCommonSubstring(); char str1[] = "abcdef".toCharArray(); char str2[] = "zcdemf".toCharArray(); System.out.println(lcs.longestCommonSubstring(str1, str2)); System.out.println(lcs.longestCommonSubstringRec(str1, str2,str1.length-1, str2.length-1,false)); } } ================================================ FILE: src/com/interview/dynamic/LongestEvenLengthSubstringOfEqualHalf.java ================================================ package com.interview.dynamic; /** * http://www.geeksforgeeks.org/longest-even-length-substring-sum-first-second-half/ * Test cases * Even length string * odd length string * 0 length string */ public class LongestEvenLengthSubstringOfEqualHalf { public int findMaxLength(int input[]){ assert input != null; int T[][] = new int[input.length][input.length]; for(int i=0; i < T.length; i++){ T[i][i] = input[i]; } int max = 0; for(int len = 2; len <= input.length; len++){ for(int i=0; i < input.length - len+1; i++){ int j = i + len-1; //updating sum for each lenght T[i][j] = T[i][j-1] + input[j]; if(len % 2 == 0){ int k = (i + j)/2; if(T[i][k] == T[k+1][j]){ if(max < len){ max = len; } } } } } return max; } public static void main(String args[]){ int input[] = {1,5,3,8,0,2,14,9}; LongestEvenLengthSubstringOfEqualHalf lel = new LongestEvenLengthSubstringOfEqualHalf(); System.out.println(lel.findMaxLength(input)); } } ================================================ FILE: src/com/interview/dynamic/LongestIncreasingPath.java ================================================ package com.interview.dynamic; /** * Date 03/10/2016 * @author Tushar Roy * * Given a 2D matrix find longest increasing path length in this matrix. * * Time complexity is O(n*m) * Space complexity is O(n*m) * * Reference * https://leetcode.com/problems/longest-increasing-path-in-a-matrix/ */ public class LongestIncreasingPath { public int longestIncreasingPath(int[][] matrix) { if (matrix.length == 0 || matrix[0].length == 0) { return 0; } int[][] distance = new int[matrix.length][matrix[0].length]; int max = 1; for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[0].length; j++) { int r = dfs(matrix, i, j, distance, Integer.MIN_VALUE); if (r > max) { max = r; } } } return max; } int dfs(int[][] matrix, int i, int j, int[][] distance, int prev) { if (i < 0 || i >= matrix.length || j < 0 || j >= matrix[i].length) { return 0; } if (matrix[i][j] <= prev) { return 0; } if (distance[i][j] != 0) { return distance[i][j]; } int v1 = dfs(matrix, i - 1, j, distance, matrix[i][j]); int v2 = dfs(matrix, i, j - 1, distance, matrix[i][j]); int v3 = dfs(matrix, i + 1, j, distance, matrix[i][j]); int v4 = dfs(matrix, i, j + 1, distance, matrix[i][j]); distance[i][j] = 1 + Math.max(Math.max(v1, v2), Math.max(v3, v4)); return distance[i][j]; } public static void main(String args[]) { LongestIncreasingPath lip = new LongestIncreasingPath(); int[][] input = {{9, 9, 4},{6, 6, 8},{2, 1, 1}}; int[][] input1 = {{3, 4, 5}, {3, 2, 6}, {2, 2, 1}}; System.out.println(lip.longestIncreasingPath(input)); } } ================================================ FILE: src/com/interview/dynamic/LongestIncreasingSubsequence.java ================================================ package com.interview.dynamic; /** * Date 05/02/2014 * @author tusroy * * Youtube link - https://youtu.be/CE2b_-XfVDk * * Find a subsequence in given array in which the subsequence's elements are * in sorted order, lowest to highest, and in which the subsequence is as long as possible * * Solution : * Dynamic Programming is used to solve this question. DP equation is * if(arr[i] > arr[j]) { T[i] = max(T[i], T[j] + 1 } * * Time complexity is O(n^2). * Space complexity is O(n) * * Reference * http://en.wikipedia.org/wiki/Longest_increasing_subsequence * http://www.geeksforgeeks.org/dynamic-programming-set-3-longest-increasing-subsequence/ */ public class LongestIncreasingSubsequence { /** * DP way of solving LIS */ public int longestSubsequenceWithActualSolution(int arr[]){ int T[] = new int[arr.length]; int actualSolution[] = new int[arr.length]; for(int i=0; i < arr.length; i++){ T[i] = 1; actualSolution[i] = i; } for(int i=1; i < arr.length; i++){ for(int j=0; j < i; j++){ if(arr[i] > arr[j]){ if(T[j] + 1 > T[i]){ T[i] = T[j] + 1; //set the actualSolution to point to guy before me actualSolution[i] = j; } } } } //find the index of max number in T int maxIndex = 0; for(int i=0; i < T.length; i++){ if(T[i] > T[maxIndex]){ maxIndex = i; } } //lets print the actual solution int t = maxIndex; int newT = maxIndex; do{ t = newT; System.out.print(arr[t] + " "); newT = actualSolution[t]; }while(t != newT); System.out.println(); return T[maxIndex]; } /** * Recursive way of solving LIS */ public int longestSubsequenceRecursive(int arr[]){ int maxLen = 0; for(int i=0; i < arr.length-1; i++){ int len = longestSubsequenceRecursive(arr,i+1,arr[i]); if(len > maxLen){ maxLen = len; } } return maxLen + 1; } private int longestSubsequenceRecursive(int arr[], int pos, int lastNum){ if(pos == arr.length){ return 0; } int t1 = 0; if(arr[pos] > lastNum){ t1 = 1 + longestSubsequenceRecursive(arr, pos+1, arr[pos]); } int t2 = longestSubsequenceRecursive(arr, pos+1, lastNum); return Math.max(t1, t2); } public static void main(String args[]){ LongestIncreasingSubsequence lis = new LongestIncreasingSubsequence(); int arr[] = {23,10,22,5,33,8,9,21,50,41,60,80,99, 22,23,24,25,26,27}; int result = lis.longestSubsequenceWithActualSolution(arr); int result1 = lis.longestSubsequenceRecursive(arr); System.out.println(result); System.out.println(result1); } } ================================================ FILE: src/com/interview/dynamic/LongestPalindromicSubsequence.java ================================================ package com.interview.dynamic; /** * Date 08/01/2014 * @author Tushar Roy * * Given a string find longest palindromic subsequence in this string. * * Time complexity - O(n2) * Space complexity - O(n2 * * Youtube link - https://youtu.be/_nCsPn7_OgI * * References * http://www.geeksforgeeks.org/dynamic-programming-set-12-longest-palindromic-subsequence/ */ public class LongestPalindromicSubsequence { public int calculate1(char []str){ int T[][] = new int[str.length][str.length]; for(int i=0; i < str.length; i++){ T[i][i] = 1; } for(int l = 2; l <= str.length; l++){ for(int i = 0; i < str.length-l + 1; i++){ int j = i + l - 1; if(l == 2 && str[i] == str[j]){ T[i][j] = 2; }else if(str[i] == str[j]){ T[i][j] = T[i + 1][j-1] + 2; }else{ T[i][j] = Math.max(T[i + 1][j], T[i][j - 1]); } } } return T[0][str.length-1]; } public int calculateRecursive(char str[],int start,int len){ if(len == 1){ return 1; } if(len ==0){ return 0; } if(str[start] == str[start+len-1]){ return 2 + calculateRecursive(str,start+1,len-2); }else{ return Math.max(calculateRecursive(str, start+1, len-1), calculateRecursive(str, start, len-1)); } } public static void main(String args[]){ LongestPalindromicSubsequence lps = new LongestPalindromicSubsequence(); String str = "agbdba"; int r1 = lps.calculateRecursive(str.toCharArray(), 0, str.length()); int r2 = lps.calculate1(str.toCharArray()); System.out.print(r1 + " " + r2); } } ================================================ FILE: src/com/interview/dynamic/MatrixMultiplicationCost.java ================================================ package com.interview.dynamic; /** * http://www.geeksforgeeks.org/dynamic-programming-set-8-matrix-chain-multiplication/ */ public class MatrixMultiplicationCost { public int findCost(int arr[]){ int temp[][] = new int[arr.length][arr.length]; int q = 0; for(int l=2; l < arr.length; l++){ for(int i=0; i < arr.length - l; i++){ int j = i + l; temp[i][j] = 1000000; for(int k=i+1; k < j; k++){ q = temp[i][k] + temp[k][j] + arr[i]*arr[k]*arr[j]; if(q < temp[i][j]){ temp[i][j] = q; } } } } return temp[0][arr.length-1]; } public static void main(String args[]){ MatrixMultiplicationCost mmc = new MatrixMultiplicationCost(); int arr[] = {4,2,3,5,3}; int cost = mmc.findCost(arr); System.out.print(cost); } } ================================================ FILE: src/com/interview/dynamic/MaxSumForNonAdjacentElements.java ================================================ package com.interview.dynamic; /** * Date 11/03/2016 * @author Tushar Roy * * Find maximum sum for non adjacent elements. * Variation is finding maximum sum non adjacent elements assuming its a circular array. * So first element cannot be with last element. * * Time complexity O(n) * Space complexity O(1) * * https://leetcode.com/problems/house-robber/ * https://leetcode.com/problems/house-robber-ii/ */ public class MaxSumForNonAdjacentElements { /** * Fast DP solution. */ public int maxSum(int arr[]) { int excl = 0; int incl = arr[0]; for (int i = 1; i < arr.length; i++) { int temp = incl; incl = Math.max(excl + arr[i], incl); excl = temp; } return incl; } /** * Recursive slow solution. */ public int maxSum(int arr[], int index) { if (index == 0) { return arr[0]; } else if (index == 1) { return Math.max(arr[0], arr[1]); } return Math.max(this.maxSum(arr, index - 2) + arr[index], this.maxSum(arr, index - 1)); } /** * Find maximum sum from left to right ignoring first element. * Find maximum sum from right to left ignoring last element. * Maximum of two will be the answer. It gurantees that both first and last element * will be not selected together. */ public int maxSumCircularArray(int[] nums) { if (nums.length == 0) { return 0; } if (nums.length == 1) { return nums[0]; } int with = nums[1]; int without = 0; for (int i = 2; i < nums.length; i++) { int newWith = without + nums[i]; without = with; with = Math.max(with, newWith); } int with1 = nums[nums.length - 2]; int without1 = 0; for (int i = nums.length - 3; i >= 0; i--) { int newWith1 = without1 + nums[i]; without1 = with1; with1 = Math.max(with1, newWith1); } return Math.max(with, with1); } public static void main(String args[]) { MaxSumForNonAdjacentElements msn = new MaxSumForNonAdjacentElements(); int arr[] = { 2, 10, 13, 4, 2, 15, 10 }; System.out.println(msn.maxSum(arr)); System.out.println(msn.maxSum(arr, arr.length-1)); } } ================================================ FILE: src/com/interview/dynamic/MaximizeSkiGates.java ================================================ package com.interview.dynamic; import java.util.HashMap; import java.util.Map; /** * Date 11/23/2015 * @author Tushar Roy * * Given starting line and right barrier which is perpendicular to starting line. There are * n gates at certain distinct distance from right barrier. Starting from start line how do you ski * such that you can cover maximum number of gates. Changing direction is expensive so you can * only do limited number of direction changes. * * Idea at every gate is to either select this gate or not select this gate. Another decision to make * is to either change or not change direction at every gate(provided you have remainingDirectionChanges > 0). * Do recursion and apply memoization to make it top down recursive solution. */ public class MaximizeSkiGates { class Index { int remainingChanges; int current; boolean isRight; int prevItem; Index(int remainingChanges, int current, boolean isRight, int prevItem) { this.remainingChanges = remainingChanges; this.current = current; this.isRight = isRight; this.prevItem = prevItem; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Index index = (Index) o; if (remainingChanges != index.remainingChanges) return false; if (current != index.current) return false; if (isRight != index.isRight) return false; return prevItem == index.prevItem; } @Override public int hashCode() { int result = remainingChanges; result = 31 * result + current; result = 31 * result + (isRight ? 1 : 0); result = 31 * result + prevItem; return result; } } public int solution(int gates[], int totalDirectionChanges) { Map dpMap = new HashMap<>(); return solution(gates, totalDirectionChanges, 0, false, -1, dpMap); } public int solution(int gates[], int remainingDirectionChanges, int current, boolean isRight, int prevItem, Map dpMap) { if(current >= gates.length) { return 0; } Index index = new Index(remainingDirectionChanges, current, isRight, prevItem); if(dpMap.containsKey(index)) { return dpMap.get(index); } int val1 = 0, val2 = 0; //if current gate is picked. if((isRight && gates[current] < prevItem) || (!isRight && gates[current] > prevItem)) { //if we decide to continue in same direction. val1 = 1 + solution(gates, remainingDirectionChanges, current + 1, isRight, gates[current], dpMap); if(remainingDirectionChanges > 0) { //if we flip direction. We can only do that if remainingDirectionChanges > 0 val2 = 1 + solution(gates, remainingDirectionChanges - 1, current + 1, !isRight, gates[current], dpMap); } } //if current gate is not picked int val3 = solution(gates, remainingDirectionChanges, current + 1, isRight, prevItem, dpMap); //max of all 3 possibilities int max = Math.max(Math.max(val1, val2), val3); dpMap.put(index, max); return max; } public static void main(String args[]) { int input[] = {15, 13, 5, 7, 4, 10, 12, 8, 2, 11, 6, 9 , 3}; MaximizeSkiGates sg = new MaximizeSkiGates(); System.out.println(sg.solution(input, 2)); } } ================================================ FILE: src/com/interview/dynamic/MaximumLengthChainPair.java ================================================ package com.interview.dynamic; import java.util.Arrays; /** * http://www.geeksforgeeks.org/dynamic-programming-set-20-maximum-length-chain-of-pairs/ */ public class MaximumLengthChainPair { static class Pair implements Comparable{ public Pair(int a,int b){ this.a = a; this.b = b; } int a; int b; @Override public int compareTo(Pair o) { if(this.a <= o.a){ return -1; }else{ return 1; } } } public int maxLength(Pair[] arr){ Arrays.sort(arr); int T[] = new int[arr.length+1]; for(int i=0; i < T.length; i++){ T[i] = 1; } for(int i=2; i < T.length; i++){ for(int j=1; j < i; j++){ if(arr[j-1].b < arr[i-1].a){ T[i] = Math.max(T[j] + 1, T[i]); } } } int max =0 ; for(int i=1; i maxArea){ maxArea = area; } } return maxArea; } public static void main(String args[]){ int input[][] = {{1,1,1,0}, {1,1,1,1}, {0,1,1,0}, {0,1,1,1}, {1,0,0,1}, {1,1,1,1}}; MaximumRectangularSubmatrixOf1s mrs = new MaximumRectangularSubmatrixOf1s(); int maxRectangle = mrs.maximum(input); //System.out.println("Max rectangle is of size " + maxRectangle); assert maxRectangle == 8; } } ================================================ FILE: src/com/interview/dynamic/MaximumSizeSubMatrix.java ================================================ package com.interview.dynamic; /** * http://www.geeksforgeeks.org/maximum-size-sub-matrix-with-all-1s-in-a-binary-matrix/ */ public class MaximumSizeSubMatrix { private int min(int a,int b, int c){ int l = Math.min(a, b); return Math.min(l, c); } public int maxSize(int arr[][]){ int result[][] = new int[arr.length][arr[0].length]; int max = 0; for(int i=0; i < arr.length; i++){ result[i][0] = arr[i][0]; if (result[i][0] == 1) { max = 1; } } for(int i=0; i < arr[0].length; i++){ result[0][i] = arr[0][i]; if (result[0][i] == 1) { max = 1; } } for(int i=1; i < arr.length; i++){ for(int j=1; j < arr[i].length; j++){ if(arr[i][j] == 0){ continue; } int t = min(result[i-1][j],result[i-1][j-1],result[i][j-1]); result[i][j] = t +1; if(result[i][j] > max){ max = result[i][j]; } } } return max; } public static void main(String args[]){ int arr[][] = {{0,1,1,0,1},{1,1,1,0,0},{1,1,1,1,0},{1,1,1,0,1}}; MaximumSizeSubMatrix mssm = new MaximumSizeSubMatrix(); int result = mssm.maxSize(arr); System.out.print(result); } } ================================================ FILE: src/com/interview/dynamic/MaximumSumSubsequence.java ================================================ package com.interview.dynamic; /** * Problem Statement: * * Given an array of n positive integers. Write a program to find the sum of maximum sum subsequence of the given array * such that the integers in the subsequence are in increasing order. * * * Video: https://youtu.be/99ssGWhLPUE * * Reference: * http://www.geeksforgeeks.org/dynamic-programming-set-14-maximum-sum-increasing-subsequence/ */ public class MaximumSumSubsequence { public int maxSum(int arr[]){ int T[] = new int[arr.length]; for (int i = 0; i < T.length; i++) { T[i] = arr[i]; } for(int i=1; i < T.length; i++){ for(int j = 0; j < i; j++){ if(arr[j] < arr[i]){ T[i] = Math.max(T[i], T[j] + arr[i]); } } } int max = T[0]; for (int i=1; i < T.length; i++){ if(T[i] > max){ max = T[i]; } } return max; } public static void main(String args[]){ MaximumSumSubsequence mss = new MaximumSumSubsequence(); int arr[] = {1, 101, 10, 2, 3, 100,4}; int r = mss.maxSum(arr); System.out.print(r); } } ================================================ FILE: src/com/interview/dynamic/MinCostPath.java ================================================ package com.interview.dynamic; /** * http://www.geeksforgeeks.org/dynamic-programming-set-6-min-cost-path/ */ public class MinCostPath { public int minCost(int [][]cost,int m,int n){ int temp[][] = new int[m+1][n+1]; int sum = 0; for(int i=0; i <= n; i++){ temp[0][i] = sum + cost[0][i]; sum = temp[0][i]; } sum = 0; for(int i=0; i <= m; i++){ temp[i][0] = sum + cost[i][0]; sum = temp[i][0]; } for(int i=1; i <= m; i++){ for(int j=1; j <= n; j++){ temp[i][j] = cost[i][j] + min(temp[i-1][j-1], temp[i-1][j],temp[i][j-1]); } } return temp[m][n]; } public int minCostRec(int cost[][], int m, int n){ return minCostRec(cost, m, n, 0 , 0); } public int minCostRec(int cost[][], int m, int n, int x, int y){ if(x > m || y > n){ return Integer.MAX_VALUE; } if(x == m && y == n){ return cost[m][n]; } int t1 = minCostRec(cost, m , n, x+1, y); int t2 = minCostRec(cost, m , n, x+1, y+1); int t3 = minCostRec(cost, m , n, x, y+1); return cost[x][y] + min(t1,t2,t3); } private int min(int a,int b, int c){ int l = Math.min(a, b); return Math.min(l, c); } public static void main(String args[]){ MinCostPath mcp = new MinCostPath(); int cost[][] = {{1,2,3},{4,8,2},{1,5,3},{6,2,9}}; int result = mcp.minCost(cost, 3, 2); int result1 = mcp.minCostRec(cost, 3, 2); System.out.println(result); System.out.println(result1); } } ================================================ FILE: src/com/interview/dynamic/MinJumpToReachEnd.java ================================================ package com.interview.dynamic; import java.util.Arrays; /** * Date 06/12/2014 * @author tusroy * * Given an array of non negative integers where each element represents the max * number of steps that can be made forward from that element. Write a function to * return the minimum number of jumps to reach the end of the array from first element * * Solution * Have 2 for loop. j trails i. If arr[j] + j >= i then you calculate new jump * and result. * * Space complexity O(n) to maintain result and min jumps * Time complexity O(n^2) * * Reference * http://www.geeksforgeeks.org/minimum-number-of-jumps-to-reach-end-of-a-given-array/ */ public class MinJumpToReachEnd { public int minJump(int arr[],int result[]){ int []jump = new int[arr.length]; jump[0] = 0; for(int i=1; i < arr.length ; i++){ jump[i] = Integer.MAX_VALUE-1; } for(int i=1; i < arr.length; i++){ for(int j=0; j < i; j++){ if(arr[j] + j >= i){ if(jump[i] > jump[j] + 1){ result[i] = j; jump[i] = jump[j] + 1; } } } } return jump[jump.length-1]; } /** * https://leetcode.com/problems/jump-game-ii/ */ public int jump(int[] nums) { if (nums.length == 1) { return 0; } int count = 0; int i = 0; while (i + nums[i] < nums.length - 1) { int maxVal = 0; int maxValIndex = 0; for (int j = 1; j <= nums[i]; j++) { if (nums[j + i] + j > maxVal) { maxVal = nums[j + i] + j; maxValIndex = i + j; } } i = maxValIndex; count++; } return count + 1; } public static void main(String args[]){ MinJumpToReachEnd mj = new MinJumpToReachEnd(); int arr[] = {1,3,5,3,2,2,6,1,6,8,9}; int r[] = new int[arr.length]; int result = mj.minJump(arr,r); System.out.println(result); int i = arr.length-1; Arrays.toString(r); int arr1[] = {2,3,1,1,4}; System.out.print(mj.jump(arr)); } } ================================================ FILE: src/com/interview/dynamic/MinimumCostTrainTicket.java ================================================ package com.interview.dynamic; /** * http://www.geeksforgeeks.org/find-the-minimum-cost-to-reach-a-destination-where-every-station-is-connected-in-one-direction/ */ public class MinimumCostTrainTicket { public int minCost(int ticket[][]){ assert ticket != null && ticket.length > 0 && ticket.length == ticket[0].length; int T[] = new int[ticket.length]; int T1[] = new int[ticket.length]; T1[0] = -1; for(int i=1; i < T.length; i++){ T[i] = ticket[0][i]; T1[i] = i-1; } for(int i=1; i < T.length; i++){ for(int j=i+1; j < T.length; j++){ if(T[j] > T[i] + ticket[i][j]){ T[j] = T[i] + ticket[i][j]; T1[j] = i; } } } //printing actual stations int i = ticket.length-1; while(i != -1){ System.out.print(i + " "); i = T1[i]; } System.out.println(); return T[ticket.length-1]; } public static void main(String args[]){ int input[][] = {{0, 15, 80, 90}, {-1, 0, 40, 50}, {-1, -1, 0, 70}, {-1, -1, -1, 0}}; MinimumCostTrainTicket mctt = new MinimumCostTrainTicket(); System.out.println(mctt.minCost(input)); } } ================================================ FILE: src/com/interview/dynamic/MinimumNumberOfPerfectSquares.java ================================================ package com.interview.dynamic; import java.util.*; /** * Date 10/19/2016 * @author Tushar Roy * * Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n. * For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9. * * Solution 1 - Using DP similar to coin change problem with infinite supply * Solution 2 - Using a BFS. Put all perfect squares in queue. Then considering each as a node try adding * another perfect square and see if we can get n. Keep doing this in BFS fashion till you hit the number. * * https://leetcode.com/problems/perfect-squares/ */ public class MinimumNumberOfPerfectSquares { public int numSquaresUsingDP(int n) { int count = (int)Math.ceil(Math.sqrt(n)); int[] T = new int[n + 1]; T[0] = 0; for (int i = 1; i < T.length; i++) { T[i] = Integer.MAX_VALUE; for (int j = 1; j <= count; j++) { if (i < j*j) { break; } T[i] = Math.min(T[i], T[i - j*j] + 1); } } return T[n]; } public int numSquaresUsingBFS(int n) { List perfectSquares = new ArrayList<>(); int i = 1; Queue queue = new LinkedList<>(); Set visited = new HashSet<>(); while (true) { int square = i * i; if (square == n) { return 1; } if (square > n) { break; } perfectSquares.add(square); queue.offer(square); visited.add(square); i++; } int distance = 1; while (!queue.isEmpty()) { int size = queue.size(); distance++; for (int j = 0; j < size; j++) { int node = queue.poll(); for (int square : perfectSquares) { int sum = node + square; if (sum == n) { return distance; } else if (!visited.contains(sum)) { visited.add(sum); queue.add(sum); } else if (sum > n) { break; } } } } return distance; } } ================================================ FILE: src/com/interview/dynamic/MinimumTriangleSum.java ================================================ package com.interview.dynamic; import java.util.List; /** * Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on * the row below. * https://leetcode.com/problems/triangle/ */ public class MinimumTriangleSum { public int minimumTotal(List> triangle) { int n = triangle.size(); int[] dp = new int[n]; for (int i = 0; i < triangle.get(n - 1).size(); i++) { dp[i] = triangle.get(n - 1).get(i); } for (int i = triangle.size() - 2; i >= 0; i--) { for (int j = 0; j < triangle.get(i).size(); j++) { dp[j] = triangle.get(i).get(j) + Math.min(dp[j], dp[j + 1]); } } return dp[0]; } } ================================================ FILE: src/com/interview/dynamic/NPotGold.java ================================================ package com.interview.dynamic; /** * http://www.glassdoor.com/Interview/N-pots-each-with-some-number-of-gold-coins-are-arranged-in-a-line-You-are-playing-a-game-against-another-player-You-tak-QTN_350584.htm * @author tusroy * @author Z. Berkay Celik */ public class NPotGold { static class Pair{ int first, second; int pick=0; public String toString(){ return first + " " + second + " " + pick; } } public Pair[][] findMoves(int pots[]){ Pair[][] moves = new Pair[pots.length][pots.length]; for(int i=0; i < moves.length; i++){ for(int j=0; j < moves[i].length; j++){ moves[i][j] = new Pair(); } } for(int i=0; i < pots.length; i++){ moves[i][i].first = pots[i]; //to track the sequence of moves moves[i][i].pick = i; } for(int l = 2; l <= pots.length; l++){ for(int i=0; i <= pots.length - l; i++){ int j = i + l -1; if(pots[i] + moves[i+1][j].second > moves[i][j-1].second + pots[j]){ moves[i][j].first = pots[i] + moves[i+1][j].second; moves[i][j].second = moves[i+1][j].first; moves[i][j].pick = i; }else{ moves[i][j].first = pots[j] + moves[i][j-1].second; moves[i][j].second = moves[i][j-1].first; moves[i][j].pick =j; } } } return moves; } //prints the sequence of values and indexes public void printSequence(int pots[], Pair moves[][]){ int i = 0; int j = pots.length - 1; int step; for (int k = 0; k < pots.length; k++) { step = moves[i][j].pick; //this is the value of pick and its index System.out.print("value: " + pots[step] + " " + "index: " + step + " "); if (step <= i) { i = i + 1; } else { j = j - 1; } } } public static void main(String args[]){ NPotGold npg = new NPotGold(); int pots[] = {3,1,5,6,2,9,3}; Pair[][] moves = npg.findMoves(pots); for(int i=0; i < moves.length; i++){ for(int j=0; j < moves[i].length; j++){ System.out.print(moves[i][j] + " "); } System.out.print("\n"); } System.out.println("The moves by first player and second player:"); npg.printSequence(pots, moves); } } ================================================ FILE: src/com/interview/dynamic/NumberOfPathsInMxNMatrix.java ================================================ package com.interview.dynamic; /** * http://www.geeksforgeeks.org/count-possible-paths-top-left-bottom-right-nxm-matrix/ */ public class NumberOfPathsInMxNMatrix { public int countPathsRecursive(int n, int m){ if(n == 1 || m == 1){ return 1; } return countPathsRecursive(n-1, m) + countPathsRecursive(n, m-1); } public int countPaths(int n,int m){ int T[][] = new int[n][m]; for(int i=0; i < n; i++){ T[i][0] = 1; } for(int i=0; i < m; i++){ T[0][i] = 1; } for(int i=1; i < n; i++){ for(int j=1; j < m; j++){ T[i][j] = T[i-1][j] + T[i][j-1]; } } return T[n-1][m-1]; } public static void main(String args[]){ NumberOfPathsInMxNMatrix nop = new NumberOfPathsInMxNMatrix(); System.out.print(nop.countPathsRecursive(3,3)); } } ================================================ FILE: src/com/interview/dynamic/NumberOfWaysToScorePoints.java ================================================ package com.interview.dynamic; /** * Finding the number of ways a given score could be reached for a game with 3 different ways of scoring (e.g. 3, 5 and 10 points). *test case *what happens if total can't be formed with given values *what if numbers are 0 or negative */ public class NumberOfWaysToScorePoints { //in this version to make 3 - 1,2 is same as 2,1. //This is similar to coin changing problem public int version1(int score[],int total){ int T[] = new int[total+1]; T[0] = 1; for(int i=0; i < score.length; i++){ for(int j=1; j <= total; j++){ if(score[i] <= j){ T[j] += T[j-score[i]]; } } } return T[total]; } //in this version to make 3 - 1,2 and 2,1 are counted different. //This is same as fibo series only that fibo series looks at last 2 numbers and here we look back k values public int version2(int score[],int total){ int T[] = new int[total+1]; T[0] = 1; for(int i=1; i <= total ; i++){ for(int j=0; j < score.length; j++){ if(score[j] <= i){ T[i] += T[i-score[j]]; } } } return T[total]; } public static void main(String args[]){ int score[] = {1,2,3}; NumberOfWaysToScorePoints now = new NumberOfWaysToScorePoints(); System.out.println(now.version1(score, 4)); System.out.println(now.version2(score, 4)); } } ================================================ FILE: src/com/interview/dynamic/OptimalTreeSearch.java ================================================ package com.interview.dynamic; /** * http://www.geeksforgeeks.org/dynamic-programming-set-24-optimal-binary-search-tree/ */ public class OptimalTreeSearch { public int minCostRec(int input[],int freq[]){ return minCostRec(input,freq,0,input.length-1,1); } private int minCostRec(int input[],int freq[],int low,int high,int level){ if(low > high){ return 0; } int min = Integer.MAX_VALUE; for(int i=low; i <= high; i++){ int val = minCostRec(input,freq,low,i-1,level+1) + minCostRec(input,freq,i+1,high,level+1) + level*freq[i]; if(val < min){ min = val; } } return min; } public int minCost(int input[], int freq[]){ int T[][] = new int[input.length][input.length]; for(int i=0; i < T.length; i++){ T[i][i] = freq[i]; } for(int l = 2; l <= input.length; l++){ for(int i=0; i <= input.length-l; i++){ int j = i + l -1; T[i][j] = Integer.MAX_VALUE; int sum = getSum(freq, i, j); for(int k=i; k <= j; k++){ int val = sum + (k-1 < i ? 0 : T[i][k-1]) + (k+1 > j ? 0 : T[k+1][j]) ; if(val < T[i][j]){ T[i][j] = val; } } } } return T[0][input.length-1]; } private int getSum(int freq[], int i, int j){ int sum = 0; for(int x = i; x <= j; x++){ sum += freq[x]; } return sum; } public static void main(String args[]){ int input[] = {10,12,20,35,46}; int freq[] = {34,8,50,21,16}; OptimalTreeSearch ots = new OptimalTreeSearch(); System.out.println(ots.minCost(input, freq)); System.out.println(ots.minCostRec(input, freq)); } } ================================================ FILE: src/com/interview/dynamic/PaintHouse.java ================================================ package com.interview.dynamic; /** * Paint House * https://leetcode.com/problems/paint-house/ * https://leetcode.com/problems/paint-house-ii/ */ public class PaintHouse { public int minCostTopDownPainHouse1or2(int[][] costs) { if (costs.length == 0) { return 0; } int[][] dp = new int[costs.length][3]; return minCostUtil(costs, 0, -1, 3, dp); } private int minCostUtil(int[][] costs, int house, int prevColor, int k, int[][] dp) { if (house == costs.length) { return 0; } int min = Integer.MAX_VALUE; for (int i = 0; i < k; i++) { if (i == prevColor) { continue; } int val; if (dp[house][i] != 0) { val = dp[house][i]; } else { val = costs[house][i] + minCostUtil(costs, house + 1, i, k, dp); dp[house][i] = val; } min = Math.min(min, val); } return min; } public int minCostBottomUpPaintHouse2(int[][] costs) { if (costs.length == 0 || costs[0].length == 0) { return 0; } int[][] dp = new int[costs.length][costs[0].length]; for (int i = 0; i < costs[0].length; i++) { dp[0][i] = costs[0][i]; } for (int i = 1; i < costs.length; i++) { Pair p = findMinSecondMin(dp[i - 1]); for (int j = 0; j < costs[0].length; j++) { dp[i][j] = costs[i][j]; if (j == p.minIndex) { dp[i][j] += dp[i-1][p.secondMinIndex]; } else { dp[i][j] += dp[i-1][p.minIndex]; } } } int min = Integer.MAX_VALUE; for (int i = 0; i < dp[0].length; i++) { min = Math.min(min, dp[dp.length - 1][i]); } return min; } class Pair { int minIndex; int secondMinIndex; } private Pair findMinSecondMin(int[] input) { int minIndex; int secondMinIndex; if (input[0] < input[1]) { minIndex = 0; secondMinIndex = 1; } else { minIndex = 1; secondMinIndex = 0; } for (int i = 2; i < input.length; i++) { if (input[i] < input[minIndex]) { secondMinIndex = minIndex; minIndex = i; } else if (input[i] < input[secondMinIndex]) { secondMinIndex = i; } } Pair p = new Pair(); p.minIndex = minIndex; p.secondMinIndex = secondMinIndex; return p; } public static void main(String args[]) { PaintHouse ph = new PaintHouse(); int[][] input = {{1, 2, 1}, {1, 4, 5}, {2, 6, 1}, {3, 3, 2}}; System.out.println(ph.minCostBottomUpPaintHouse2(input)); } } ================================================ FILE: src/com/interview/dynamic/PalindromePartition.java ================================================ package com.interview.dynamic; import java.util.*; /** * Date 04/03/2016 * @author Tushar Roy * * Partitioning the string into palindromes. * * https://leetcode.com/problems/palindrome-partitioning/ * https://leetcode.com/problems/palindrome-partitioning-ii/ */ public class PalindromePartition { /* * Given a string s, partition s such that every substring of the partition is a palindrome. * Return the minimum cuts needed for a palindrome partitioning of s. * https://leetcode.com/problems/palindrome-partitioning-ii/ */ public int minCut(String str){ if (str.length() == 0) { return 0; } int[] cut = new int[str.length()]; boolean isPal[][] = new boolean[str.length()][str.length()]; for (int i = 1; i < str.length(); i++) { int min = i; for (int j = 0; j <= i; j++) { if (str.charAt(i) == str.charAt(j) && (i <= j + 1 || isPal[i - 1][j + 1])) { isPal[i][j] = true; min = Math.min(min, j == 0 ? 0 : 1 + cut[j - 1]); } } cut[i] = min; } return cut[str.length() - 1]; } /** * Given a string s, partition s such that every substring of the partition is a palindrome. * https://leetcode.com/problems/palindrome-partitioning/ */ public List> partition(String s) { Map>> dp = new HashMap<>(); List> result = partitionUtil(s, dp, 0); List> r = new ArrayList<>(); for (List l : result) { r.add(l); } return r; } private List> partitionUtil(String s, Map>> dp, int start) { if (start == s.length()) { List r = new ArrayList<>(); return Collections.singletonList(r); } if (dp.containsKey(start)) { return dp.get(start); } List> words = new ArrayList<>(); for (int i = start; i < s.length(); i++) { if (!isPalindrome(s, start, i) ) { continue; } String newWord = s.substring(start, i + 1); List> result = partitionUtil(s, dp, i + 1); for (List l : result) { List l1 = new ArrayList<>(); l1.add(newWord); l1.addAll(l); words.add(l1); } } dp.put(start, words); return words; } private boolean isPalindrome(String str, int r, int t) { while(r < t) { if (str.charAt(r) != str.charAt(t)) { return false; } r++; t--; } return true; } } ================================================ FILE: src/com/interview/dynamic/PhoneDialNumberOfCombinationOfSizeK.java ================================================ package com.interview.dynamic; import java.util.HashMap; import java.util.Map; /** * Given the mobile numeric keypad. You can only press buttons that are * up,left,right or down to the current button.You are not allowed to press * bottom row corner buttons (i.e. * and # ).Given a N find out the number of * numbers possible of given length. * * The idea is that to calculate for i all you have to do is add up i-1 values of all the neighbors. * e.g for i =2 and at 0 you need find i=1s of all neighbors including 0 and add them up. */ public class PhoneDialNumberOfCombinationOfSizeK { /** * -1 in the input means don't use that position * * @param k * @param input * @return */ public int numberOfCombination(int k, int input[][]) { if (input == null || input.length == 0) { throw new IllegalArgumentException(); } Map t = new HashMap(); Map t1 = new HashMap(); for (int i = 0; i < input.length; i++) { for (int j = 0; j < input[i].length; j++) { if (input[i][j] < 0) { continue; } t1.put(input[i][j], 1); } } for (int x = 1; x < k; x++) { for (int i = 0; i < input.length; i++) { for (int j = 0; j < input[i].length; j++) { if (input[i][j] < 0) { continue; } findNeighborsAndPopulateMap(i, j, input, t, t1); } } copyMap(t, t1); t.clear(); } int count = 0; for (int i : t1.keySet()) { count += t1.get(i); } return count; } private void copyMap(Map t, Map t1) { for (Integer i : t.keySet()) { int c = t.get(i); t1.put(i, c); } } private void findNeighborsAndPopulateMap(int x, int y, int input[][], Map t, Map t1) { updateMap(input, x, y, x - 1, y, t, t1); updateMap(input, x, y, x, y - 1, t, t1); updateMap(input, x, y, x, y, t, t1); updateMap(input, x, y, x, y + 1, t, t1); updateMap(input, x, y, x + 1, y, t, t1); } private void updateMap(int input[][], int x, int y, int i, int j, Map t, Map t1) { if (i < 0 || i >= input.length || j < 0 || j >= input[x].length || input[i][j] < 0) { return; } Integer c = t.get(input[x][y]); if (c == null) { c = 0; } c += t1.get(input[i][j]); t.put(input[x][y], c); } public static void main(String args[]) { int input[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { -1, 0, -1 } }; PhoneDialNumberOfCombinationOfSizeK pdn = new PhoneDialNumberOfCombinationOfSizeK(); System.out.println(pdn.numberOfCombination(3, input)); } } ================================================ FILE: src/com/interview/dynamic/RegexMatching.java ================================================ package com.interview.dynamic; /** * Date 06/24/2015 * @author Tushar Roy * * Write a program to perform regex matching with * an . * * References : http://leetcode.com/2011/09/regular-expression-matching.html */ public class RegexMatching { public boolean matchRegexRecursive(char[] str, char[] pattern){ return matchRegexRecursive(str,pattern,0,0); } private boolean matchRegexRecursive(char text[], char pattern[], int pos1, int pos2){ //if pos2 has reached end of pattern means pos2 should also reach end of text for match //to happen if(pos2 == pattern.length) { return pos1 == text.length; } //if next character is not * means either current value at pattern and text should be same //or current value at pattern should be . in which case you can skip one character of text if(pos2 == pattern.length - 1 || pattern[pos2+1] != '*') { return (pos1 < text.length && (text[pos1] == pattern[pos2] || pattern[pos2] == '.')) && matchRegexRecursive(text, pattern, pos1+1, pos2+1); } //if we have case like abc and ad*bc so here we totally skip d* if(matchRegexRecursive(text, pattern, pos1, pos2+2)){ return true; } //For case like abbc and ab*c match first b with b* and then next b to c. If that does not work out //then try next b with b* and then c with c and so on. //if pattern current val is . then skip one character at time from text till we either reach end of text //or a match is found while(pos1 < text.length && (text[pos1] == pattern[pos2] || pattern[pos2] == '.')){ if( matchRegexRecursive(text, pattern, pos1+1, pos2+2)){ return true; } pos1++; } return false; } /** * Dynamic programming technique for regex matching. */ public boolean matchRegex(char[] text, char[] pattern) { boolean T[][] = new boolean[text.length + 1][pattern.length + 1]; T[0][0] = true; //Deals with patterns like a* or a*b* or a*b*c* for (int i = 1; i < T[0].length; i++) { if (pattern[i-1] == '*') { T[0][i] = T[0][i - 2]; } } for (int i = 1; i < T.length; i++) { for (int j = 1; j < T[0].length; j++) { if (pattern[j - 1] == '.' || pattern[j - 1] == text[i - 1]) { T[i][j] = T[i-1][j-1]; } else if (pattern[j - 1] == '*') { T[i][j] = T[i][j - 2]; if (pattern[j-2] == '.' || pattern[j - 2] == text[i - 1]) { T[i][j] = T[i][j] | T[i - 1][j]; } } else { T[i][j] = false; } } } return T[text.length][pattern.length]; } public static void main(String args[]){ RegexMatching rm = new RegexMatching(); System.out.println(rm.matchRegexRecursive("Tushar".toCharArray(),"Tushar".toCharArray())); System.out.println(rm.matchRegexRecursive("Tusha".toCharArray(),"Tushar*a*b*".toCharArray())); System.out.println(rm.matchRegexRecursive("".toCharArray(),"a*b*".toCharArray())); System.out.println(rm.matchRegexRecursive("abbbbccc".toCharArray(),"a*ab*bbbbc*".toCharArray())); System.out.println(rm.matchRegexRecursive("abbbbccc".toCharArray(),"aa*bbb*bbbc*".toCharArray())); System.out.println(rm.matchRegexRecursive("abbbbccc".toCharArray(),".*bcc".toCharArray())); System.out.println(rm.matchRegexRecursive("abbbbccc".toCharArray(),".*bcc*".toCharArray())); System.out.println(rm.matchRegexRecursive("abbbbccc".toCharArray(),".*bcc*".toCharArray())); System.out.println(rm.matchRegexRecursive("aaa".toCharArray(),"ab*a*c*a".toCharArray())); System.out.println(rm.matchRegex("aa".toCharArray(), "a*".toCharArray())); } } ================================================ FILE: src/com/interview/dynamic/RemoveFromEndToMake2IntoMinGreaterThanMax.java ================================================ package com.interview.dynamic; /** * http://www.geeksforgeeks.org/remove-minimum-elements-either-side-2min-max/ */ public class RemoveFromEndToMake2IntoMinGreaterThanMax { public int removeFromEnd(int input[]){ return removeFromEnd(input,0,input.length-1); } private int removeFromEnd(int input[],int low,int high){ if(low > high){ return input.length; } int min = min(input,low,high); int max = max(input,low,high); if(2*min > max){ return 0; } return Math.min(removeFromEnd(input,low,high-1), removeFromEnd(input,low+1,high)) +1; } private int min(int input[],int low,int high){ int min = Integer.MAX_VALUE; for(int i=low; i <=high; i++){ if(min > input[i]){ min = input[i]; } } return min; } private int max(int input[],int low,int high){ int max = Integer.MIN_VALUE; for(int i=low; i <=high; i++){ if(max < input[i]){ max = input[i]; } } return max; } public int removeFromEndDynamic(int input[]){ int T[][] = new int[input.length][input.length]; for(int l=1; l <= input.length; l++){ for(int i=0, j = i + l-1; i < input.length-l+1; i++,j++){ int min = min(input,i,j); int max = max(input,i,j); if(2*min > max){ T[i][j] = 0; }else{ T[i][j] = Math.min(T[i+1][j] , T[i][j-1]) +1; } } } return T[0][input.length-1]; } public static void main(String args[]){ int input[] = {5,1,3,1,3,8,3}; RemoveFromEndToMake2IntoMinGreaterThanMax rme = new RemoveFromEndToMake2IntoMinGreaterThanMax(); System.out.println(rme.removeFromEnd(input)); System.out.println(rme.removeFromEndDynamic(input)); } } ================================================ FILE: src/com/interview/dynamic/ScrambledString.java ================================================ package com.interview.dynamic; import java.util.HashMap; import java.util.Map; /** * Read question at https://leetcode.com/problems/scramble-string/ */ public class ScrambledString { /** * Index for memoization. */ private static class Index { int start1; int end1; int start2; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Index index = (Index) o; if (start1 != index.start1) return false; if (end1 != index.end1) return false; if (start2 != index.start2) return false; return end2 == index.end2; } @Override public int hashCode() { int result = start1; result = 31 * result + end1; result = 31 * result + start2; result = 31 * result + end2; return result; } int end2; } boolean isScrambled(char input1[], char input2[], int start1, int end1, int start2, int end2, Map memMap) { //return false conditions if(start1 > end1 || start2 > end2) { return false; } if(end1 - start1 != end2 - start2) { return false; } Index index = new Index(); index.start1 = start1; index.end1 = end1; index.start2 = start2; index.end2 = end2; //if we have already calculated value for index then lets use it instead of recalculating again. if(memMap.containsKey(index)) { return memMap.get(index); } //if both input from their respective start to end are same then return true. boolean isSame = true; for(int i= start1, j = start2; i <= end1 && j <= end2; i++, j++) { if(input1[i] != input2[j]) { isSame = false; break; } } if(isSame) { memMap.put(index, true); return true; } //check if both input from their respective start to end have same characters. If not then return false. Map countMap = new HashMap<>(); for(int i= start1; i <= end1; i++) { countMap.compute(input1[i], (ch, val) -> { if(val == null) { return 1; } else { return val + 1; } }); } for(int i= start2; i <= end2; i++) { countMap.compute(input2[i], (ch, val) -> { if(val == null) { return -1; } else { return val - 1; } }); } //all values in map should have value 0 otherwise there is character mismatch. Return false in that case. long nonZeroCount = countMap.values().stream().filter(val -> val !=0 ).count(); if(nonZeroCount > 0) { memMap.put(index, false); return false; } //for values from input range try splitting into 2 and check recursively if they match or not. for(int len = 0; len < end1 - start1; len++) { //e.g great gtear so match g ,g and reat, tear if(isScrambled(input1, input2, start1, start1 + len, start2, start2 + len, memMap) && isScrambled(input1, input2, start1 + len +1, end1, start2 + len + 1, end2, memMap)) { memMap.put(index, true); return true; } //e.g great reatg so match g,g and reat,reat if(isScrambled(input1, input2, start1, start1 + len, end2 - len, end2, memMap) && isScrambled(input1, input2, start1 + len +1, end1, start2, end2 - len -1, memMap)) { memMap.put(index, true); return true; } } memMap.put(index, false); return false; } public static void main(String args[]) { ScrambledString ss = new ScrambledString(); String str1 = "great"; String str2 = "rgtae"; Map memMap = new HashMap<>(); boolean result = ss.isScrambled(str1.toCharArray(), str2.toCharArray(), 0, str1.length() - 1, 0, str2.length() -1, memMap); System.out.println(result); } } ================================================ FILE: src/com/interview/dynamic/StockBuySellKTransactions.java ================================================ package com.interview.dynamic; import java.util.Deque; import java.util.LinkedList; /** * Date 12/22/2015 * @author Tushar Roy * * Given stockc prices for certain days and at most k transactions how to buy and sell * to maximize profit. * * Time complexity - O(number of transactions * number of days) * Space complexity - O(number of transcations * number of days) * * https://leetcode.com/discuss/15153/a-clean-dp-solution-which-generalizes-to-k-transactions */ public class StockBuySellKTransactions { /** * Below solution is accepted by leetcode and runs in space proportional to prices length. */ public int maxProfitLinearSpace(int k, int[] prices) { if (k == 0 || prices.length == 0) { return 0; } if (k >= prices.length) { return allTimeProfit(prices); } int[] T = new int[prices.length]; int[] prev = new int[prices.length]; for (int i = 1; i <= k; i++) { int maxDiff = -prices[0]; for (int j = 1; j < prices.length; j++) { T[j] = Math.max(T[j - 1], maxDiff + prices[j]); maxDiff = Math.max(maxDiff, prev[j] - prices[j]); } for (int j = 1; j < prices.length; j++) { prev[j] = T[j]; } } return T[T.length - 1]; } public int allTimeProfit(int arr[]){ int profit = 0; int localMin = arr[0]; for(int i=1; i < arr.length;i++){ if(arr[i-1] >= arr[i]){ localMin = arr[i]; }else{ profit += arr[i] - localMin; localMin = arr[i]; } } return profit; } /** * This is faster method which does optimization on slower method * Time complexity here is O(K * number of days) * * Formula is * T[i][j] = max(T[i][j-1], prices[j] + maxDiff) * maxDiff = max(maxDiff, T[i-1][j] - prices[j]) */ public int maxProfit(int prices[], int K) { if (K == 0 || prices.length == 0) { return 0; } int T[][] = new int[K+1][prices.length]; for (int i = 1; i < T.length; i++) { int maxDiff = -prices[0]; for (int j = 1; j < T[0].length; j++) { T[i][j] = Math.max(T[i][j-1], prices[j] + maxDiff); maxDiff = Math.max(maxDiff, T[i-1][j] - prices[j]); } } printActualSolution(T, prices); return T[K][prices.length-1]; } /** * This is slow method but easier to understand. * Time complexity is O(k * number of days ^ 2) * T[i][j] = max(T[i][j-1], max(prices[j] - prices[m] + T[i-1][m])) where m is 0...j-1 */ public int maxProfitSlowSolution(int prices[], int K) { if (K == 0 || prices.length == 0) { return 0; } int T[][] = new int[K+1][prices.length]; for (int i = 1; i < T.length; i++) { for (int j = 1; j < T[0].length; j++) { int maxVal = 0; for (int m = 0; m < j; m++) { maxVal = Math.max(maxVal, prices[j] - prices[m] + T[i-1][m]); } T[i][j] = Math.max(T[i][j-1], maxVal); } } printActualSolution(T, prices); return T[K][prices.length - 1]; } public void printActualSolution(int T[][], int prices[]) { int i = T.length - 1; int j = T[0].length - 1; Deque stack = new LinkedList<>(); while(true) { if(i == 0 || j == 0) { break; } if (T[i][j] == T[i][j-1]) { j = j - 1; } else { stack.addFirst(j); int maxDiff = T[i][j] - prices[j]; for (int k = j-1; k >= 0; k--) { if (T[i-1][k] - prices[k] == maxDiff) { i = i - 1; j = k; stack.addFirst(j); break; } } } } while(!stack.isEmpty()) { System.out.println("Buy at price " + prices[stack.pollFirst()]); System.out.println("Sell at price " + prices[stack.pollFirst()]); } } public static void main(String args[]) { StockBuySellKTransactions sbt = new StockBuySellKTransactions(); int prices[] = {2, 5, 7, 1, 4, 3, 1, 3}; System.out.println("Max profit fast solution " + sbt.maxProfit(prices, 3)); System.out.println("Max profit slow solution " + sbt.maxProfitSlowSolution(prices, 3)); } } ================================================ FILE: src/com/interview/dynamic/SubRectangularMatrixWithMaximumSum.java ================================================ package com.interview.dynamic; /** * Date 07/31/2014 * @author tusroy * * Write a program to find maximum sum rectangle in give 2D matrix. * Assume there is at least one positive number in the 2D matrix. * * Solution: * Keep temp array with size as number of rows. Start left and right from 0 * and keep adding values for each row and maintain them in this temp array. * Run Kadane's algorithm to find max sum subarray in temp. Now increment right by * 1. When right reaches last column reset right to 1 and left to 1. * * Space complexity of this algorithm is O(row) * Time complexity of this algorithm is O(row*col*col) * * References * http://www.geeksforgeeks.org/dynamic-programming-set-27-max-sum-rectangle-in-a-2d-matrix/ */ public class SubRectangularMatrixWithMaximumSum { class Result{ int maxSum; int leftBound; int rightBound; int upBound; int lowBound; @Override public String toString() { return "Result [maxSum=" + maxSum + ", leftBound=" + leftBound + ", rightBound=" + rightBound + ", upBound=" + upBound + ", lowBound=" + lowBound + "]"; } } public Result maxSum(int input[][]){ int rows = input.length; int cols = input[0].length; int temp[] = new int[rows]; Result result = new Result(); for(int left = 0; left < cols ; left++){ for(int i=0; i < rows; i++){ temp[i] = 0; } for(int right = left; right < cols; right++){ for(int i=0; i < rows; i++){ temp[i] += input[i][right]; } KadaneResult kadaneResult = kadane(temp); if(kadaneResult.maxSum > result.maxSum){ result.maxSum = kadaneResult.maxSum; result.leftBound = left; result.rightBound = right; result.upBound = kadaneResult.start; result.lowBound = kadaneResult.end; } } } return result; } class KadaneResult{ int maxSum; int start; int end; public KadaneResult(int maxSum, int start, int end) { this.maxSum = maxSum; this.start = start; this.end = end; } } private KadaneResult kadane(int arr[]){ int max = 0; int maxStart = -1; int maxEnd = -1; int currentStart = 0; int maxSoFar = 0; for(int i=0; i < arr.length; i++){ maxSoFar += arr[i]; if(maxSoFar < 0){ maxSoFar = 0; currentStart = i+1; } if(max < maxSoFar){ maxStart = currentStart; maxEnd = i; max = maxSoFar; } } return new KadaneResult(max, maxStart, maxEnd); } public static void main(String args[]){ int input[][] = {{ 2, 1, -3, -4, 5}, { 0, 6, 3, 4, 1}, { 2, -2, -1, 4, -5}, {-3, 3, 1, 0, 3}}; SubRectangularMatrixWithMaximumSum saw = new SubRectangularMatrixWithMaximumSum(); System.out.println(saw.maxSum(input)); } } ================================================ FILE: src/com/interview/dynamic/SubsetSum.java ================================================ package com.interview.dynamic; /* * Date 09/23/2014 * @author Tushar Roy * * Given an array of non negative numbers and a total, is there subset of numbers in this array which adds up * to given total. Another variation is given an array is it possible to split it up into 2 equal * sum partitions. Partition need not be equal sized. Just equal sum. * * Time complexity - O(input.size * total_sum) * Space complexity - O(input.size*total_sum) * * Youtube video - https://youtu.be/s6FhG--P7z0 */ public class SubsetSum { public boolean subsetSum(int input[], int total) { boolean T[][] = new boolean[input.length + 1][total + 1]; for (int i = 0; i <= input.length; i++) { T[i][0] = true; } for (int i = 1; i <= input.length; i++) { for (int j = 1; j <= total; j++) { if (j - input[i - 1] >= 0) { T[i][j] = T[i - 1][j] || T[i - 1][j - input[i - 1]]; } else { T[i][j] = T[i-1][j]; } } } return T[input.length][total]; } public boolean partition(int arr[]) { int sum = 0; for (int i = 0; i < arr.length; i++) { sum += arr[i]; } if (sum % 2 != 0) { return false; } sum = sum / 2; boolean[][] T = new boolean[arr.length + 1][sum + 1]; for (int i = 0; i <= arr.length; i++) { T[i][0] = true; } for (int i = 1; i <= arr.length; i++) { for (int j = 1; j <= sum; j++) { if (j - arr[i - 1] >= 0) { T[i][j] = T[i - 1][j - arr[i - 1]] || T[i - 1][j]; } else { T[i][j] = T[i-1][j]; } } } return T[arr.length][sum]; } public static void main(String args[]) { SubsetSum ss = new SubsetSum(); int arr[] = {1, 3, 5, 5, 2, 1, 1, 6}; System.out.println(ss.partition(arr)); int arr1[] = {2, 3, 7, 8}; System.out.print(ss.subsetSum(arr1, 11)); } } ================================================ FILE: src/com/interview/dynamic/SubsquareSurrounedByXs.java ================================================ package com.interview.dynamic; /** * Date 09/15/2014 * @author tusroy * * Find maximum subsquare in a matrix made up of Xs and Os such that all four sides of subsquare are Xs. It does not matter what is inside * the subsquare. All 4 sides should be made up entirely of Xs * * e.g * 0 0 0 0 0 X 0,0 0,0 0,0 0,0 0,0 1,1 * 0 X 0 X X X 0,0 1,1 0,0 1,1 1,2 2,3 * 0 X 0 X 0 X 0,0 2,1 0,0 2,1 0,0 3,1 * 0 X X X X X 0,0 3,1 1,2 3,3 1,4 4,5 * 0 0 0 0 0 0 0,0 0,0 0,0 0,0 0,0 0,0 * * Output of above program should be 3 * * Solution * Have another matrix which is capable of holding 2 values hori and ver. * Ver stores how far vertically you can see Xs. Hori stores how far horizontally you can see Xs. * Once this matrix is build look for biggest subsquare by getting min of hori and ver at each point and checking * if subsquare can be formed from value min to 1. * * Test cases: * Matrix entirely made up of Xs * Matrix entirely made up of Os * Matrix with Xs and Os but maximum subsquare is length 1 */ public class SubsquareSurrounedByXs { class Cell{ int ver; int hori; } public int findSubSquare(char input[][]){ Cell T[][] = new Cell[input.length][input[0].length]; for(int i=0; i < T.length; i++){ for(int j=0; j < T[0].length; j++){ T[i][j] = new Cell(); } } for(int i=0; i < input.length; i++){ for(int j=0; j < input[0].length; j++){ if(input[i][j] == 'X'){ if(i == 0 && j == 0){ T[i][j].hori = 1; T[i][j].ver = 1; } else if(i == 0){ T[i][j].hori = T[i][j-1].hori + 1; T[i][j].ver = 1; }else if(j == 0){ T[i][j].ver = T[i-1][j].ver +1; T[i][j].hori = 1; }else{ T[i][j].hori = T[i][j-1].hori +1; T[i][j].ver = T[i-1][j].ver + 1; } } } } for(int i=0; i < T.length; i++){ for(int j=0; j < T[0].length; j++){ System.out.print(T[i][j].ver + "," + T[i][j].hori+ " "); } System.out.println(); } //start iterating from bottom right corner and find min of hori or ver at every cell. //If this is greater than 1 then see if you can find a number between this min and 1 //such that on left's ver and top's hori is greater greater than or equal to k. int max = 1; for(int i=T.length -1; i >=0 ; i--){ for(int j= T[0].length-1 ; j >=0; j--){ if(T[i][j].ver == 0 || T[i][j].ver == 1 || T[i][j].hori ==1 ){ continue; } int min = Math.min(T[i][j].ver, T[i][j].hori); int k = 0; for(k=min; k > 1; k--){ if(T[i][j-k+1].ver >= k && T[i-k+1][j].hori >= k){ break; } } if(max < k){ max = k; } } } return max; } public static void main(String args[]){ char[][] input = {{'X','O','O','O','O','O'}, {'O','O','O','O','O','O'}, {'X','X','X','X','O','O'}, {'X','X','X','X','X','O'}, {'X','O','O','X','X','O'}, {'X','O','X','X','X','O'}}; char [][] input1 = {{'O', 'O', 'O', 'O', 'O', 'X'}, {'O', 'X', 'O', 'X', 'X', 'X'}, {'O', 'X', 'O', 'X', 'O', 'X'}, {'O', 'X', 'X', 'X', 'X', 'X'}, {'O', 'O', 'O', 'O', 'O', 'O'}, }; char [][] input2 = {{'O', 'O', 'X', 'O', 'X'}, {'O', 'X', 'X', 'O', 'X'}, {'O', 'X', 'O', 'X', 'X'}, {'X', 'X', 'X', 'X', 'X'}, {'O', 'X', 'X', 'X', 'O'}, }; SubsquareSurrounedByXs ss = new SubsquareSurrounedByXs(); System.out.println(ss.findSubSquare(input)); System.out.println(ss.findSubSquare(input1)); System.out.println(ss.findSubSquare(input2)); } } ================================================ FILE: src/com/interview/dynamic/SymbolExpressionEvaluation.java ================================================ package com.interview.dynamic; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * Date 01/06/2016 * @author Tushar Roy * Let there be a binary operation for 3 symbols a, b, c and result of these binary operation given in a table. * Given an expression of these 3 symbols and a final result, tell if this expression can be parenthesize in certain * way to produce the final result. * * Time complexity is O(n^4) * Space complexity is O(n^3) */ public class SymbolExpressionEvaluation { public boolean evaluateExpression(char input[][], Map index, char[] expression, char result) { Holder[][] T = new Holder[expression.length][expression.length]; for (int i = 0; i < T.length; i++) { for (int j = 0; j < T.length; j++) { T[i][j] = new Holder(); } } for (int i = 0; i < expression.length; i++) { T[i][i].add(expression[i]); } for (int l = 2; l <= T.length; l++) { for (int i = 0; i <= T.length - l; i++) { int j = i + l - 1; for (int k = i; k < j; k++) { for (char ch : T[i][k].values()) { for (char ch1: T[k+1][j].values()) { T[i][j].add(input[index.get(ch)][index.get(ch1)]); } } } } } for (char ch : T[0][T.length-1].values()) { if ( result == ch) { return true; } } return false; } public static void main(String args[]) { Map index = new HashMap<>(); index.put('a', 0); index.put('b', 1); index.put('c', 2); char input[][] = {{'b', 'b', 'a'}, {'c', 'b', 'a'}, {'a', 'c', 'c'}}; SymbolExpressionEvaluation sbe = new SymbolExpressionEvaluation(); System.out.println(sbe.evaluateExpression(input, index, "bbbbac".toCharArray(), 'a')); } } class Holder { private Set valueHolder = new HashSet<>(); void add(Character ch) { valueHolder.add(ch); } Set values() { return valueHolder; } } ================================================ FILE: src/com/interview/dynamic/TextJustification.java ================================================ package com.interview.dynamic; /** * Date 05/07/2015 * @author tusroy * * Video link - https://youtu.be/RORuwHiblPc * * Given a sequence of words, and a limit on the number of characters that can be put * in one line (line width). Put line breaks in the given sequence such that the * lines are printed neatly * * Solution: * Badness - We define badness has square of empty spaces in every line. So 2 empty space * on one line gets penalized as 4 (2^2) while 1 each empty space on 2 lines gets * penalized as 2(1 + 1). So we prefer 1 empty space on different lines over 2 empty space on * one line. * * For every range i,j(words from i to j) find the cost of putting them on one line. If words * from i to j cannot fit in one line cost will be infinite. Cost is calculated as square of * empty space left in line after fitting words from i to j. * * Then apply this formula to get places where words need to be going on new line. * minCost[i] = minCost[j] + cost[i][j-1] * Above formula will try every value of j from i to len and see which one gives minimum * cost to split words from i to len. * * Space complexity is O(n^2) * Time complexity is O(n^2) * * References: * http://www.geeksforgeeks.org/dynamic-programming-set-18-word-wrap/ */ public class TextJustification { public String justify(String words[], int width) { int cost[][] = new int[words.length][words.length]; //next 2 for loop is used to calculate cost of putting words from //i to j in one line. If words don't fit in one line then we put //Integer.MAX_VALUE there. for(int i=0 ; i < words.length; i++){ cost[i][i] = width - words[i].length(); for(int j=i+1; j < words.length; j++){ cost[i][j] = cost[i][j-1] - words[j].length() - 1; } } for(int i=0; i < words.length; i++){ for(int j=i; j < words.length; j++){ if(cost[i][j] < 0){ cost[i][j] = Integer.MAX_VALUE; }else{ cost[i][j] = (int)Math.pow(cost[i][j], 2); } } } //minCost from i to len is found by trying //j between i to len and checking which //one has min value int minCost[] = new int[words.length]; int result[] = new int[words.length]; for(int i = words.length-1; i >= 0 ; i--){ minCost[i] = cost[i][words.length-1]; result[i] = words.length; for(int j=words.length-1; j > i; j--){ if(cost[i][j-1] == Integer.MAX_VALUE){ continue; } if(minCost[i] > minCost[j] + cost[i][j-1]){ minCost[i] = minCost[j] + cost[i][j-1]; result[i] = j; } } } int i = 0; int j; System.out.println("Minimum cost is " + minCost[0]); System.out.println("\n"); //finally put all words with new line added in //string buffer and print it. StringBuilder builder = new StringBuilder(); do{ j = result[i]; for(int k=i; k < j; k++){ builder.append(words[k] + " "); } builder.append("\n"); i = j; }while(j < words.length); return builder.toString(); } public static void main(String args[]){ String words1[] = {"Tushar","likes","to","write","code","at", "free", "time"}; TextJustification awl = new TextJustification(); System.out.println(awl.justify(words1, 12)); } } ================================================ FILE: src/com/interview/dynamic/TwoStringInterleavingToFormThird.java ================================================ package com.interview.dynamic; /** * * http://www.geeksforgeeks.org/check-whether-a-given-string-is-an-interleaving-of-two-other-given-strings-set-2/ */ public class TwoStringInterleavingToFormThird { public boolean isInterleavedRecursive(char str1[], char str2[], char str3[],int pos1, int pos2, int pos3){ if(pos1 == str1.length && pos2 == str2.length && pos3 == str3.length){ return true; } if(pos3 == str3.length){ return false; } return (pos1 < str1.length && str1[pos1] == str3[pos3] && isInterleavedRecursive(str1, str2, str3, pos1+1, pos2, pos3+1)) || (pos2 < str2.length && str2[pos2] == str3[pos3] && isInterleavedRecursive(str1, str2, str3, pos1, pos2+1, pos3+1)); } public boolean isInterleaved(char str1[], char str2[], char str3[]){ boolean T[][] = new boolean[str1.length +1][str2.length +1]; if(str1.length + str2.length != str3.length){ return false; } for(int i=0; i < T.length; i++){ for(int j=0; j < T[i].length; j++){ int l = i + j -1; if(i == 0 && j == 0){ T[i][j] = true; } else if(i == 0){ if(str3[l] == str2[j-1]){ T[i][j] = T[i][j-1]; } } else if(j == 0){ if(str1[i-1] == str3[l]){ T[i][j] = T[i-1][j]; } } else{ T[i][j] = (str1[i-1] == str3[l] ? T[i-1][j] : false) || (str2[j-1] == str3[l] ? T[i][j-1] : false); } } } return T[str1.length][str2.length]; } public static void main(String args[]){ String str1 = "XXYM"; String str2 = "XXZT"; String str3 = "XXXZXYTM"; TwoStringInterleavingToFormThird sti = new TwoStringInterleavingToFormThird(); System.out.println(sti.isInterleaved(str1.toCharArray(), str2.toCharArray(), str3.toCharArray())); } } ================================================ FILE: src/com/interview/dynamic/UglyNumbers.java ================================================ package com.interview.dynamic; import java.util.PriorityQueue; /** * Date 03/08/2016 * @author Tushar Roy * * Find nth ugly number. * * https://leetcode.com/problems/ugly-number-ii/ * https://leetcode.com/problems/super-ugly-number/ * http://www.geeksforgeeks.org/ugly-numbers/ */ public class UglyNumbers { static class Node implements Comparable { int inputIndex; int index; int val; Node (int inputIndex, int index, int val) { this.index = index; this.val = val; this.inputIndex = inputIndex; } @Override public int compareTo(Node other) { return this.val - other.val; } } public int nthSuperUglyNumber1(int n, int[] primes) { PriorityQueue pq = new PriorityQueue<>(); for (int i = 0; i < primes.length; i++) { pq.offer(new Node(i, 0, primes[i])); } int[] val = new int[n]; val[0] = 1; for (int i = 1; i < n; ) { Node node = pq.poll(); if (val[i-1] != node.val) { val[i] = node.val; i++; } node.index = node.index + 1; node.val = primes[node.inputIndex]*val[node.index]; pq.offer(node); } return val[n - 1]; } int ugly(int n){ int arr[] = new int[n]; int count = 1; arr[0] = 1; int i2 = 0; int i3 = 0; int i5 = 0; while(count < n){ int minNumber = min(arr[i2] * 2, arr[i3] * 3, arr[i5] * 5); if(minNumber == arr[i2]*2){ i2++; } if(minNumber == arr[i3]*3){ i3++; } if(minNumber == arr[i5]*5){ i5++; } arr[count++] = minNumber; } return arr[n-1]; } private int min(int a,int b, int c){ int l = Math.min(a, b); return Math.min(l, c); } public static void main(String args[]) { UglyNumbers ugly = new UglyNumbers(); int result = ugly.ugly(150); System.out.println(result); int[] primes = {2, 3, 7, 11}; System.out.print(ugly.nthSuperUglyNumber1(17, primes)); } } ================================================ FILE: src/com/interview/dynamic/WeightedJobSchedulingMaximumProfit.java ================================================ package com.interview.dynamic; import java.util.Arrays; import java.util.Comparator; class Job{ int start; int end; int profit; Job(int start,int end,int profit){ this.start= start; this.end = end; this.profit= profit; } } class FinishTimeComparator implements Comparator{ @Override public int compare(Job arg0, Job arg1) { if(arg0.end <= arg1.end){ return -1; }else{ return 1; } } } /** * http://www.cs.princeton.edu/courses/archive/spr05/cos423/lectures/06dynamic-programming.pdf * Given set of jobs with start and end interval and profit, how to maximize profit such that * jobs in subset do not overlap. */ public class WeightedJobSchedulingMaximumProfit { /** * Sort the jobs by finish time. * For every job find the first job which does not overlap with this job * and see if this job profit plus profit till last non overlapping job is greater * than profit till last job. * @param jobs * @return */ public int maximum(Job[] jobs){ int T[] = new int[jobs.length]; FinishTimeComparator comparator = new FinishTimeComparator(); Arrays.sort(jobs, comparator); T[0] = jobs[0].profit; for(int i=1; i < jobs.length; i++){ T[i] = Math.max(jobs[i].profit, T[i-1]); for(int j=i-1; j >=0; j--){ if(jobs[j].end <= jobs[i].start){ T[i] = Math.max(T[i], jobs[i].profit + T[j]); break; } } } int maxVal = Integer.MIN_VALUE; for (int val : T) { if (maxVal < val) { maxVal = val; } } return maxVal; } public static void main(String args[]){ Job jobs[] = new Job[6]; jobs[0] = new Job(1,3,5); jobs[1] = new Job(2,5,6); jobs[2] = new Job(4,6,5); jobs[3] = new Job(6,7,4); jobs[4] = new Job(5,8,11); jobs[5] = new Job(7,9,2); WeightedJobSchedulingMaximumProfit mp = new WeightedJobSchedulingMaximumProfit(); System.out.println(mp.maximum(jobs)); } } ================================================ FILE: src/com/interview/dynamic/WildCardMatching.java ================================================ package com.interview.dynamic; /** * Date 02/11/2016 * @author Tushar Roy * * Wild car matching with ? and * * * Reference * https://leetcode.com/problems/wildcard-matching/ */ public class WildCardMatching { public boolean isMatch(String s, String p) { char[] str = s.toCharArray(); char[] pattern = p.toCharArray(); //replace multiple * with one * //e.g a**b***c --> a*b*c int writeIndex = 0; boolean isFirst = true; for ( int i = 0 ; i < pattern.length; i++) { if (pattern[i] == '*') { if (isFirst) { pattern[writeIndex++] = pattern[i]; isFirst = false; } } else { pattern[writeIndex++] = pattern[i]; isFirst = true; } } boolean T[][] = new boolean[str.length + 1][writeIndex + 1]; if (writeIndex > 0 && pattern[0] == '*') { T[0][1] = true; } T[0][0] = true; for (int i = 1; i < T.length; i++) { for (int j = 1; j < T[0].length; j++) { if (pattern[j-1] == '?' || str[i-1] == pattern[j-1]) { T[i][j] = T[i-1][j-1]; } else if (pattern[j-1] == '*'){ T[i][j] = T[i-1][j] || T[i][j-1]; } } } return T[str.length][writeIndex]; } /** * Recursive and slow version of wild card matching. */ public boolean isMatchRecursive(String s, String p) { return isMatchRecursiveUtil(s.toCharArray(), p.toCharArray(), 0, 0); } private boolean isMatchRecursiveUtil(char[] text, char[] pattern, int pos1, int pos2) { if (pos2 == pattern.length) { return text.length == pos1; } if (pattern[pos2] != '*') { if (pos1 < text.length && (text[pos1] == pattern[pos2]) || pattern[pos2] == '?') { return isMatchRecursiveUtil(text, pattern, pos1 + 1, pos2 + 1); } else { return false; } } else { //if we have a***b then skip to the last * while (pos2 < pattern.length - 1 && pattern[pos2 + 1] == '*') { pos2++; } pos1--; while (pos1 < text.length) { if (isMatchRecursiveUtil(text, pattern, pos1 + 1, pos2 + 1)) { return true; } pos1++; } return false; } } public static void main(String args[]) { WildCardMatching wcm = new WildCardMatching(); System.out.println(wcm.isMatch("xbylmz", "x?y*z")); } } ================================================ FILE: src/com/interview/geometry/ClosestPairOfPoints.java ================================================ package com.interview.geometry; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; /** * http://www.geeksforgeeks.org/closest-pair-of-points-onlogn-implementation/ * https://www.youtube.com/watch?v=_pSl90jq-m0 another good explanation * Given coordinates of points find closest pair points distance. * * Test cases: * Number of points should be more than 1 * Test along positive and negative axis * * The way it works is * 1) Sort by x coordinate * 2) Recursively divide into two halves. * 3) Find min distance between points in each half. Say this distance is d. * 4) Find points which are in either half and closer than d. To find this point sort by y * axis and find distance to next 6 points. Magic about 6 points is we can create a rectangular * area and only 6 points can fit in that rectangular area. So we need to check only 7 points * for each point in rectangular area. * @author tusroy */ class Point{ int x; int y; Point(int x, int y){ this.x = x; this.y = y; } } class XCoordinatorSorter implements Comparator{ @Override public int compare(Point o1, Point o2) { if(o1.x < o2.x){ return -1; }else{ return 1; } } } class YCoordinatorSorter implements Comparator{ @Override public int compare(Point o1, Point o2) { if(o1.y < o2.y){ return -1; }else{ return 1; } } } public class ClosestPairOfPoints { private static final int SIZE = 7; public double closestPairOfPoints(Point[] points){ if(points.length < 2){ throw new IllegalArgumentException(); } Point[] px = new Point[points.length]; Point[] py = new Point[points.length]; int i=0; for(Point point : points){ px[i++] = point; } i=0; for(Point point : points){ py[i++] = point; } XCoordinatorSorter xSorter = new XCoordinatorSorter(); YCoordinatorSorter ySorter = new YCoordinatorSorter(); Arrays.sort(px, xSorter); Arrays.sort(py, ySorter); int minDistance = closestPairOfPoints(px, py, 0, points.length-1); return Math.sqrt(minDistance); } private int closestPairOfPoints(Point[] px, Point[] py,int start, int end){ if(end - start < 3){ return computeMinDistance(px, start, end); } int mid = (start + end)/2; Point[] pyLeft = new Point[mid-start+1]; Point[] pyRight = new Point[end-mid]; int i=0, j=0; for(Point p : px){ if(p.x <= px[mid].x){ pyLeft[i++] = p; }else{ pyRight[j++] = p; } } int d1 = closestPairOfPoints(px,pyLeft,start,mid); int d2 = closestPairOfPoints(px, pyRight, mid+1, end); int d = Math.min(d1, d2); List deltaPoints = new ArrayList(); for(Point p : px){ if(Math.sqrt(distance(p,px[mid])) < Math.sqrt(d)){ deltaPoints.add(p); } } int d3 = closest(deltaPoints); return Math.min(d3, d); } private int closest(List deltaPoints){ int minDistance = Integer.MAX_VALUE; for(int i=0; i < deltaPoints.size(); i++){ for(int j=i+1; j <= i + SIZE && j < deltaPoints.size() ; j++){ int distance = distance(deltaPoints.get(i), deltaPoints.get(j)); if(minDistance < distance){ minDistance = distance; } } } return minDistance; } private int distance(Point p1, Point p2){ return (p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y); } private int computeMinDistance(Point[] points, int start, int end){ if(end - start == 1){ Point p1 = points[start]; Point p2 = points[end]; return (p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y); }else if(end - start == 2){ Point p1 = points[start]; Point p2 = points[end-1]; Point p3 = points[end]; return Math.min(Math.min((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y), (p1.x - p3.x)*(p1.x - p3.x) + (p1.y - p3.y)*(p1.y - p3.y)), (p2.x - p3.x)*(p2.x - p3.x) + (p2.y - p3.y)*(p2.y - p3.y)); }else{ throw new IllegalArgumentException(); } } public static void main(String args[]){ ClosestPairOfPoints cpp = new ClosestPairOfPoints(); Point[] points = {new Point(6,2),new Point(4,6),new Point(5,4),new Point(-8,2),new Point(0,2)}; double minDistance = cpp.closestPairOfPoints(points); System.out.println(minDistance); } } ================================================ FILE: src/com/interview/geometry/GrahamScanConvexHull.java ================================================ package com.interview.geometry; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Stack; /** * @author Tushar Roy * Date 10/11/2107 * * Convex hull or convex envelope of a set X of points in the Euclidean plane or in a Euclidean space * (or, more generally, in an affine space over the reals) is the smallest convex set that contains X. * * Graham scan finds all vertices of the convex hull ordered along its boundary. * * Time complexity O(nlogn) * Space complexity O(n) * * References * https://leetcode.com/problems/erect-the-fence/description/ * https://en.wikipedia.org/wiki/Convex_hull * https://en.wikipedia.org/wiki/Graham_scan * https://discuss.leetcode.com/topic/89336/java-graham-scan-with-adapted-sorting-to-deal-with-collinear-points */ public class GrahamScanConvexHull { static class Point{ int x; int y; Point(int x, int y){ this.x = x; this.y = y; } } public List findConvexHull(Point[] points) { if (points.length < 2) { return Arrays.asList(points); } //find the lowest point in the plane. If there are multiple lowest points //then pick the leftmost one. Point start = points[0]; for (int i = 1; i < points.length; i++) { if (start.y > points[i].y) { start = points[i]; } else if (start.y == points[i].y && start.x > points[i].x) { start = points[i]; } } sortToHandleCollinear(points, start); Stack stack = new Stack<>(); stack.push(points[0]); stack.push(points[1]); for (int i = 2; i < points.length; i++) { Point top = stack.pop(); //second point will always be in answer so this will never cause empty stack exception. //as long as points[i] is on right of vector stack.peek() -> top keep getting rid of top of stack. while (crossProduct(stack.peek(), top, points[i]) < 0) { top = stack.pop(); } stack.push(top); stack.push(points[i]); } return new ArrayList<>(stack); } private void sortToHandleCollinear(Point[] points, Point start) { Arrays.sort(points, (p1, p2) -> { if (p1 == start) { return -1; } if (p2 == start) { return 1; } int cp = crossProduct(start, p1, p2); if (cp == 0) { return distance(start, p1, p2); } else { return -cp; } }); //make sure last collinear points are in reverse order of distance. Point p = points[0], q = points[points.length - 1]; int i = points.length - 2; while (i >= 0 && crossProduct(p, q, points[i]) == 0) { i--; } // reverse sort order of collinear points in the end positions for (int l = i + 1, h = points.length - 1; l < h; l++, h--) { Point tmp = points[l]; points[l] = points[h]; points[h] = tmp; } } /** * Returns < 0 if 'b' is closer to 'a' compared to 'c', == 0 if 'b' and 'c' are same distance from 'a' * or > 0 if 'c' is closer to 'a' compared to 'b'. */ private int distance(Point a, Point b, Point c) { int y1 = a.y - b.y; int y2 = a.y - c.y; int x1 = a.x - b.x; int x2 = a.x - c.x; return Integer.compare(y1 * y1 + x1 * x1, y2 * y2 + x2 * x2); } /** * Cross product to find where c belongs in reference to vector ab. * If result > 0 it means 'c' is on left of ab * result == 0 it means 'a','b' and 'c' are collinear * result < 0 it means 'c' is on right of ab */ private int crossProduct(Point a, Point b, Point c) { int y1 = a.y - b.y; int y2 = a.y - c.y; int x1 = a.x - b.x; int x2 = a.x - c.x; return y2 * x1 - y1 * x2; } public static void main(String[] args) { GrahamScanConvexHull grahamScanConvexHull = new GrahamScanConvexHull(); //int[][] input = new int[][]{{0,0},{0,1},{0,2},{1,2},{2,2},{3,2},{3,1},{3,0},{2,0},{1,0},{1,1},{4,3}}; int[][] input = new int[][] {{1,1},{2,2},{2,0},{2,4},{3,3},{4,2}}; Point[] points = new Point[input.length]; int index = 0; for (int[] i : input) { points[index++] = new Point(i[0], i[1]); } System.out.println(grahamScanConvexHull.findConvexHull(points)); } } ================================================ FILE: src/com/interview/geometry/JarvisMarchConvexHull.java ================================================ package com.interview.geometry; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; /** * @author Tushar Roy * Date 10/11/2107 * * Convex hull or convex envelope of a set X of points in the Euclidean plane or in a Euclidean space * (or, more generally, in an affine space over the reals) is the smallest convex set that contains X. * * Jarvis March is finding convex or gift wrapping algorithm. * * Time complexity O(nh) * n - number of points * h - number of points on the boundary. * Worst case O(n^2) * * Space complexity O(n^2) * * Reference * https://leetcode.com/problems/erect-the-fence/description/ * https://en.wikipedia.org/wiki/Convex_hull * https://en.wikipedia.org/wiki/Gift_wrapping_algorithm */ public class JarvisMarchConvexHull { class Point{ int x; int y; Point(int x, int y){ this.x = x; this.y = y; } } public List findConvexHull(Point[] points) { //first find leftmost point to start the march. Point start = points[0]; for (int i = 1; i < points.length; i++) { if (points[i].x < start.x) { start = points[i]; } } Point current = start; //use set because this algorithm might try to insert duplicate point. Set result = new HashSet<>(); result.add(start); List collinearPoints = new ArrayList<>(); while (true) { Point nextTarget = points[0]; for (int i = 1; i < points.length; i++) { if (points[i] == current) { continue; } int val = crossProduct(current, nextTarget, points[i]); //if val > 0 it means points[i] is on left of current -> nextTarget. Make him the nextTarget. if (val > 0) { nextTarget = points[i]; //reset collinear points because we now have a new nextTarget. collinearPoints = new ArrayList<>(); } else if (val == 0) { //if val is 0 then collinear current, nextTarget and points[i] are collinear. //if its collinear point then pick the further one but add closer one to list of collinear points. if (distance(current, nextTarget, points[i]) < 0) { collinearPoints.add(nextTarget); nextTarget = points[i]; } else { //just add points[i] to collinearPoints list. If nextTarget indeed is the next point on //convex then all points in collinear points will be also on boundary. collinearPoints.add(points[i]); } } //else if val < 0 then nothing to do since points[i] is on right side of current -> nextTarget. } //add all points in collinearPoints to result. for (Point p : collinearPoints) { result.add(p); } //if nextTarget is same as start it means we have formed an envelope and its done. if (nextTarget == start) { break; } //add nextTarget to result and set current to nextTarget. result.add(nextTarget); current = nextTarget; } return new ArrayList<>(result); } /** * Returns < 0 if 'b' is closer to 'a' compared to 'c', == 0 if 'b' and 'c' are same distance from 'a' * or > 0 if 'c' is closer to 'a' compared to 'b'. */ private int distance(Point a, Point b, Point c) { int y1 = a.y - b.y; int y2 = a.y - c.y; int x1 = a.x - b.x; int x2 = a.x - c.x; return Integer.compare(y1 * y1 + x1 * x1, y2 * y2 + x2 * x2); } /** * Cross product to find where c belongs in reference to vector ab. * If result > 0 it means 'c' is on left of ab * result == 0 it means 'a','b' and 'c' are collinear * result < 0 it means 'c' is on right of ab */ private int crossProduct(Point a, Point b, Point c) { int y1 = a.y - b.y; int y2 = a.y - c.y; int x1 = a.x - b.x; int x2 = a.x - c.x; return y2 * x1 - y1 * x2; } } ================================================ FILE: src/com/interview/geometry/MaximumPointsOnSameLine.java ================================================ package com.interview.geometry; import java.util.HashMap; import java.util.Map; /** * Date 03/21/2016 * @author Tushar Roy * * Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. * * Time complexity O(n^2) * Space complexity O(n) * * https://leetcode.com/problems/max-points-on-a-line/ */ public class MaximumPointsOnSameLine { static class Point { int x; int y; Point() { x = 0; y = 0; } Point(int a, int b) { x = a; y = b; } } class Pair { int a; int b; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Pair pair = (Pair) o; if (a != pair.a) return false; return b == pair.b; } @Override public int hashCode() { int result = a; result = 31 * result + b; return result; } } public int maxPoints(Point[] points) { int result = 0; for (int i = 0; i < points.length; i++) { Map map = new HashMap<>(); int verticalLine = 1; int onePointMax = 1; int samePoint = 0; for (int j = i + 1; j < points.length; j++) { //same point repeated again. Just increment samePoint count if (points[i].x == points[j].x && points[i].y == points[j].y) { samePoint++; } else if (points[i].x == points[j].x) { //vertical line verticalLine++; onePointMax = Math.max(onePointMax, verticalLine); } else { int gcd = gcd(points[i].y - points[j].y, points[i].x - points[j].x); Pair p = new Pair(); p.a = (points[i].y - points[j].y)/gcd; p.b = (points[i].x - points[j].x)/gcd; int count = 2; if (map.containsKey(p)) { count = map.get(p); count++; map.put(p, count); } else { map.put(p, count); } onePointMax = Math.max(onePointMax, count); } } result = Math.max(result, onePointMax + samePoint); } return result; } int gcd(int a, int b) { if(b==0) return a; else return gcd(b, a % b); } } ================================================ FILE: src/com/interview/geometry/SkylineDrawing.java ================================================ package com.interview.geometry; import java.util.*; /** * Date 01/07/2016 * @author Tushar Roy * * Given skyline of a city merge the buildings * * Time complexity is O(nlogn) * Space complexity is O(n) * * References * https://leetcode.com/problems/the-skyline-problem/ * https://leetcode.com/discuss/67091/once-for-all-explanation-with-clean-java-code-nlog-time-space */ public class SkylineDrawing { /** * Represents either start or end of building */ static class BuildingPoint implements Comparable { int x; boolean isStart; int height; @Override public int compareTo(BuildingPoint o) { //first compare by x. //If they are same then use this logic //if two starts are compared then higher height building should be picked first //if two ends are compared then lower height building should be picked first //if one start and end is compared then start should appear before end if (this.x != o.x) { return this.x - o.x; } else { return (this.isStart ? -this.height : this.height) - (o.isStart ? -o.height : o.height); } } } public List getSkyline(int[][] buildings) { //for all start and end of building put them into List of BuildingPoint BuildingPoint[] buildingPoints = new BuildingPoint[buildings.length*2]; int index = 0; for(int building[] : buildings) { buildingPoints[index] = new BuildingPoint(); buildingPoints[index].x = building[0]; buildingPoints[index].isStart = true; buildingPoints[index].height = building[2]; buildingPoints[index + 1] = new BuildingPoint(); buildingPoints[index + 1].x = building[1]; buildingPoints[index + 1].isStart = false; buildingPoints[index + 1].height = building[2]; index += 2; } Arrays.sort(buildingPoints); //using TreeMap because it gives log time performance. //PriorityQueue in java does not support remove(object) operation in log time. TreeMap queue = new TreeMap<>(); //PriorityQueue queue1 = new PriorityQueue<>(Collections.reverseOrder()); queue.put(0, 1); //queue1.add(0); int prevMaxHeight = 0; List result = new ArrayList<>(); for(BuildingPoint buildingPoint : buildingPoints) { //if it is start of building then add the height to map. If height already exists then increment //the value if (buildingPoint.isStart) { queue.compute(buildingPoint.height, (key, value) -> { if (value != null) { return value + 1; } return 1; }); // queue1.add(cp.height); } else { //if it is end of building then decrement or remove the height from map. queue.compute(buildingPoint.height, (key, value) -> { if (value == 1) { return null; } return value - 1; }); // queue1.remove(cp.height); } //peek the current height after addition or removal of building x. int currentMaxHeight = queue.lastKey(); //int currentMaxHeight = queue1.peek(); //if height changes from previous height then this building x becomes critcal x. // So add it to the result. if (prevMaxHeight != currentMaxHeight) { result.add(new int[]{buildingPoint.x, currentMaxHeight}); prevMaxHeight = currentMaxHeight; } } return result; } public static void main(String args[]) { int [][] buildings = {{1,3,4},{3,4,4},{2,6,2},{8,11,4}, {7,9,3},{10,11,2}}; SkylineDrawing sd = new SkylineDrawing(); List criticalPoints = sd.getSkyline(buildings); criticalPoints.forEach(cp -> System.out.println(cp[0] + " " + cp[1])); } } ================================================ FILE: src/com/interview/graph/AlientDictionary.java ================================================ package com.interview.graph; import java.util.*; /** * There is a new alien language which uses the latin alphabet. However, the order among letters * are unknown to you. You receive a list of words from the dictionary, where words are sorted * lexicographically by the rules of this new language. Derive the order of letters in this language. * * https://leetcode.com/problems/alien-dictionary/ */ public class AlientDictionary { public String alienOrder(String[] words) { Set allCharacters = new HashSet<>(); Map> graph = buildGraph(words, new HashMap<>(), allCharacters); Deque stack = new LinkedList<>(); Set visited = new HashSet<>(); Set dfs = new HashSet<>(); for (char ch : allCharacters) { if (topSortUtil(ch, stack, visited, dfs, graph)) { return ""; } } StringBuffer buff = new StringBuffer(); while (!stack.isEmpty()) { buff.append(stack.pollFirst()); } return buff.toString(); } private boolean topSortUtil(char vertex, Deque stack, Set visited, Set dfs, Map> graph) { if (visited.contains(vertex)) { return false; } visited.add(vertex); dfs.add(vertex); Set set = graph.get(vertex); if (set != null) { for (char neighbor : set) { if (dfs.contains(neighbor)) { return true; } if (topSortUtil(neighbor, stack, visited, dfs, graph)) { return true; } } } dfs.remove(vertex); stack.offerFirst(vertex); return false; } /** * degree is only used for BFS. Not for DFS. */ private Map> buildGraph(String words[], Map degree, Set allCharacters) { getAllChars(words, degree, allCharacters); Set all = new HashSet<>(allCharacters); Map> graph = new HashMap<>(); for (int i = 0; i < words.length - 1; i++) { String nextWord = words[i + 1]; for (int k = 0; k < Math.min(words[i].length(), nextWord.length()); k++) { if (words[i].charAt(k) != nextWord.charAt((k))) { all.remove(words[i].charAt(k)); Set set = graph.get(words[i].charAt(k)); if (set == null) { set = new HashSet<>(); graph.put(words[i].charAt(k), set); } set.add(nextWord.charAt(k)); degree.compute(nextWord.charAt(k), (key, count) -> count + 1); break; } } } for (char ch : all) { graph.put(ch, null); } return graph; } private void getAllChars(String words[], Map degree, Set allCharacters) { for (String word : words) { for (char ch : word.toCharArray()) { allCharacters.add(ch); degree.computeIfAbsent(ch, key -> 0); } } } public String alienOrder1(String words[]) { Map degree = new HashMap<>(); Map> graph = buildGraph(words, degree, new HashSet<>()); Queue zeroDegreeNodes = new LinkedList<>(); for (Map.Entry entry : degree.entrySet()) { if (entry.getValue() == 0) { zeroDegreeNodes.offer(entry.getKey()); } } StringBuilder result = new StringBuilder(); while (!zeroDegreeNodes.isEmpty()) { char vertex = zeroDegreeNodes.poll(); result.append(vertex); Set neighbors = graph.get(vertex); if (neighbors != null) { for (char neighbor : graph.get(vertex)) { int count = degree.get(neighbor); count--; if (count == 0) { zeroDegreeNodes.offer(neighbor); } else { degree.put(neighbor, count); } } } graph.remove(vertex); } return graph.size() > 0 ? "" : result.toString(); } public static void main(String args[]) { AlientDictionary ad = new AlientDictionary(); String[] words1 = {"zy","zx"}; String[] words = {"wrt", "wrf", "er", "ett", "rftt"}; String[] words2 = {"wrtkj","wrt"}; String result = ad.alienOrder1(words2); System.out.print(result); //w -> e // e -> r //t -> f //r -> t // } } ================================================ FILE: src/com/interview/graph/AllCyclesInDirectedGraphJohnson.java ================================================ package com.interview.graph; import java.util.*; /** * Date 11/16/2015 * @author Tushar Roy * * Find all cycles in directed graph using Johnson's algorithm * * Time complexity - O(E + V).(c+1) where c is number of cycles found * Space complexity - O(E + V + s) where s is sum of length of all cycles. * * Link to youtube video - https://youtu.be/johyrWospv0 * * References * https://github.com/jgrapht/jgrapht/blob/master/jgrapht-core/src/main/java/org/jgrapht/alg/cycle/JohnsonSimpleCycles.java */ public class AllCyclesInDirectedGraphJohnson { Set> blockedSet; Map, Set>> blockedMap; Deque> stack; List>> allCycles; /** * Main function to find all cycles */ public List>> simpleCyles(Graph graph) { blockedSet = new HashSet<>(); blockedMap = new HashMap<>(); stack = new LinkedList<>(); allCycles = new ArrayList<>(); long startIndex = 1; TarjanStronglyConnectedComponent tarjan = new TarjanStronglyConnectedComponent(); while(startIndex <= graph.getAllVertex().size()) { Graph subGraph = createSubGraph(startIndex, graph); List>> sccs = tarjan.scc(subGraph); //this creates graph consisting of strongly connected components only and then returns the //least indexed vertex among all the strongly connected component graph. //it also ignore one vertex graph since it wont have any cycle. Optional> maybeLeastVertex = leastIndexSCC(sccs, subGraph); if(maybeLeastVertex.isPresent()) { Vertex leastVertex = maybeLeastVertex.get(); blockedSet.clear(); blockedMap.clear(); findCyclesInSCG(leastVertex, leastVertex); startIndex = leastVertex.getId() + 1; } else { break; } } return allCycles; } private Optional> leastIndexSCC(List>> sccs, Graph subGraph) { long min = Integer.MAX_VALUE; Vertex minVertex = null; Set> minScc = null; for(Set> scc : sccs) { if(scc.size() == 1) { continue; } for(Vertex vertex : scc) { if(vertex.getId() < min) { min = vertex.getId(); minVertex = vertex; minScc = scc; } } } if(minVertex == null) { return Optional.empty(); } Graph graphScc = new Graph<>(true); for(Edge edge : subGraph.getAllEdges()) { if(minScc.contains(edge.getVertex1()) && minScc.contains(edge.getVertex2())) { graphScc.addEdge(edge.getVertex1().getId(), edge.getVertex2().getId()); } } return Optional.of(graphScc.getVertex(minVertex.getId())); } private void unblock(Vertex u) { blockedSet.remove(u); if(blockedMap.get(u) != null) { blockedMap.get(u).forEach( v -> { if(blockedSet.contains(v)) { unblock(v); } }); blockedMap.remove(u); } } private boolean findCyclesInSCG( Vertex startVertex, Vertex currentVertex) { boolean foundCycle = false; stack.push(currentVertex); blockedSet.add(currentVertex); for (Edge e : currentVertex.getEdges()) { Vertex neighbor = e.getVertex2(); //if neighbor is same as start vertex means cycle is found. //Store contents of stack in final result. if (neighbor == startVertex) { List> cycle = new ArrayList<>(); stack.push(startVertex); cycle.addAll(stack); Collections.reverse(cycle); stack.pop(); allCycles.add(cycle); foundCycle = true; } //explore this neighbor only if it is not in blockedSet. else if (!blockedSet.contains(neighbor)) { boolean gotCycle = findCyclesInSCG(startVertex, neighbor); foundCycle = foundCycle || gotCycle; } } //if cycle is found with current vertex then recursively unblock vertex and all vertices which are dependent on this vertex. if (foundCycle) { //remove from blockedSet and then remove all the other vertices dependent on this vertex from blockedSet unblock(currentVertex); } else { //if no cycle is found with current vertex then don't unblock it. But find all its neighbors and add this //vertex to their blockedMap. If any of those neighbors ever get unblocked then unblock current vertex as well. for (Edge e : currentVertex.getEdges()) { Vertex w = e.getVertex2(); Set> bSet = getBSet(w); bSet.add(currentVertex); } } //remove vertex from the stack. stack.pop(); return foundCycle; } private Set> getBSet(Vertex v) { return blockedMap.computeIfAbsent(v, (key) -> new HashSet<>() ); } private Graph createSubGraph(long startVertex, Graph graph) { Graph subGraph = new Graph<>(true); for(Edge edge : graph.getAllEdges()) { if(edge.getVertex1().getId() >= startVertex && edge.getVertex2().getId() >= startVertex) { subGraph.addEdge(edge.getVertex1().getId(), edge.getVertex2().getId()); } } return subGraph; } public static void main(String args[]) { AllCyclesInDirectedGraphJohnson johnson = new AllCyclesInDirectedGraphJohnson(); Graph graph = new Graph<>(true); graph.addEdge(1, 2); graph.addEdge(1, 8); graph.addEdge(1, 5); graph.addEdge(2, 9); graph.addEdge(2, 7); graph.addEdge(2, 3); graph.addEdge(3, 1); graph.addEdge(3, 2); graph.addEdge(3, 6); graph.addEdge(3, 4); graph.addEdge(6, 4); graph.addEdge(4, 5); graph.addEdge(5, 2); graph.addEdge(8, 9); graph.addEdge(9, 8); List>> allCycles = johnson.simpleCyles(graph); allCycles.forEach(cycle -> { StringJoiner joiner = new StringJoiner("->"); cycle.forEach(vertex -> joiner.add(String.valueOf(vertex.getId()))); System.out.println(joiner); }); } } ================================================ FILE: src/com/interview/graph/AllCyclesInDirectedGraphTarjan.java ================================================ package com.interview.graph; import java.util.*; /** * Find all simple cycles in a directed graph using Tarjan's algorithm. * * Space complexity - O(E + V + S) where S is length of all cycles * Time complexity - O(E*V(C+1) where C is total number of cycles * * Reference - https://ecommons.cornell.edu/handle/1813/5941 * https://github.com/jgrapht/jgrapht/tree/master/jgrapht-core/src/main/java/org/jgrapht/alg/cycle */ public class AllCyclesInDirectedGraphTarjan { private Set> visited; private Deque> pointStack; private Deque> markedStack; private Set> markedSet; public AllCyclesInDirectedGraphTarjan() { reset(); } private void reset() { visited = new HashSet<>(); pointStack = new LinkedList<>(); markedStack = new LinkedList<>(); markedSet = new HashSet<>(); } public List>> findAllSimpleCycles(Graph graph) { reset(); List>> result = new ArrayList<>(); for(Vertex vertex : graph.getAllVertex()) { findAllSimpleCycles(vertex, vertex, result); visited.add(vertex); while(!markedStack.isEmpty()) { markedSet.remove(markedStack.pollFirst()); } } return result; } private boolean findAllSimpleCycles(Vertex start, Vertex current,List>> result) { boolean hasCycle = false; pointStack.offerFirst(current); markedSet.add(current); markedStack.offerFirst(current); for (Vertex w : current.getAdjacentVertexes()) { if (visited.contains(w)) { continue; } else if (w.equals(start)) { hasCycle = true; pointStack.offerFirst(w); List> cycle = new ArrayList<>(); Iterator> itr = pointStack.descendingIterator(); while(itr.hasNext()) { cycle.add(itr.next()); } pointStack.pollFirst(); result.add(cycle); } else if (!markedSet.contains(w)) { hasCycle = findAllSimpleCycles(start, w, result) || hasCycle; } } if (hasCycle) { while(!markedStack.peekFirst().equals(current)) { markedSet.remove(markedStack.pollFirst()); } markedSet.remove(markedStack.pollFirst()); } pointStack.pollFirst(); return hasCycle; } public static void main(String args[]) { Graph graph = new Graph<>(true); graph.addEdge(0, 1); graph.addEdge(1, 4); graph.addEdge(1, 7); graph.addEdge(1, 6); graph.addEdge(4, 2); graph.addEdge(4, 3); graph.addEdge(2, 4); graph.addEdge(2, 7); graph.addEdge(2, 6); graph.addEdge(7, 8); graph.addEdge(7, 5); graph.addEdge(5, 2); graph.addEdge(5, 3); graph.addEdge(3, 7); graph.addEdge(3, 6); graph.addEdge(3, 4); graph.addEdge(6, 5); graph.addEdge(6, 8); AllCyclesInDirectedGraphTarjan tarjan = new AllCyclesInDirectedGraphTarjan(); List>> result = tarjan.findAllSimpleCycles(graph); result.forEach(cycle -> { cycle.forEach(v -> System.out.print(v.getId() + " ")); System.out.println(); }); } } ================================================ FILE: src/com/interview/graph/ArticulationPoint.java ================================================ package com.interview.graph; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * Date 08/22/2015 * @author Tushar Roy * * Find articulation points in connected undirected graph. * Articulation points are vertices such that removing any one of them disconnects the graph. * * We need to do DFS of this graph and keep visitedTime and lowTime for each vertex. * lowTime is keeps track of back edges. * * If any one of following condition meets then vertex is articulation point. * * 1) If vertex is root of DFS and has atlesat 2 independent children.(By independent it means they are * not connected to each other except via this vertex). This condition is needed because if we * started from corner vertex it will meet condition 2 but still is not an articulation point. To filter * out those vertices we need this condition. * * 2) It is not root of DFS and if visitedTime of vertex <= lowTime of any adjacent vertex then its articulation point. * * Time complexity is O(E + V) * Space complexity is O(V) * * References: * https://en.wikipedia.org/wiki/Biconnected_component * http://www.geeksforgeeks.org/articulation-points-or-cut-vertices-in-a-graph/ */ public class ArticulationPoint { private int time; public Set> findarticulationPoints(Graph graph) { time = 0; Set> visited = new HashSet<>(); Set> articulationPoints = new HashSet<>(); Vertex startVertex = graph.getAllVertex().iterator().next(); Map, Integer> visitedTime = new HashMap<>(); Map, Integer> lowTime = new HashMap<>(); Map, Vertex> parent = new HashMap<>(); DFS(visited,articulationPoints,startVertex, visitedTime, lowTime, parent); return articulationPoints; } private void DFS(Set> visited, Set> articulationPoints, Vertex vertex, Map, Integer> visitedTime, Map, Integer> lowTime, Map, Vertex> parent) { visited.add(vertex); visitedTime.put(vertex, time); lowTime.put(vertex, time); time++; int childCount =0; boolean isArticulationPoint = false; for(Vertex adj : vertex.getAdjacentVertexes()){ //if adj is same as parent then just ignore this vertex. if(adj.equals(parent.get(vertex))) { continue; } //if adj has not been visited then visit it. if(!visited.contains(adj)) { parent.put(adj, vertex); childCount++; DFS(visited, articulationPoints, adj, visitedTime, lowTime, parent); if(visitedTime.get(vertex) <= lowTime.get(adj)) { isArticulationPoint = true; } else { //below operation basically does lowTime[vertex] = min(lowTime[vertex], lowTime[adj]); lowTime.compute(vertex, (currentVertex, time) -> Math.min(time, lowTime.get(adj)) ); } } else { //if adj is already visited see if you can get better low time. //below operation basically does lowTime[vertex] = min(lowTime[vertex], visitedTime[adj]); lowTime.compute(vertex, (currentVertex, time) -> Math.min(time, visitedTime.get(adj)) ); } } //checks if either condition 1 or condition 2 meets). If yes then it is articulation point. if((parent.get(vertex) == null && childCount >= 2) || parent.get(vertex) != null && isArticulationPoint ) { articulationPoints.add(vertex); } } public static void main(String args[]){ Graph graph = new Graph<>(false); graph.addEdge(1, 2); graph.addEdge(2, 3); graph.addEdge(1, 3); graph.addEdge(1, 4); graph.addEdge(4, 5); graph.addEdge(5, 6); graph.addEdge(6, 7); graph.addEdge(7, 5); graph.addEdge(6, 8); //bigger example /* graph.addEdge(0, 1); graph.addEdge(0, 2); graph.addEdge(0, 3); graph.addEdge(0, 4); graph.addEdge(4, 2); graph.addEdge(3, 5); graph.addEdge(4, 6); graph.addEdge(6, 3); graph.addEdge(6, 7); graph.addEdge(6, 8); graph.addEdge(7, 9); graph.addEdge(9, 10); graph.addEdge(8, 10);*/ ArticulationPoint ap = new ArticulationPoint(); Set> aPoints = ap.findarticulationPoints(graph); aPoints.forEach(point -> System.out.println(point)); } } ================================================ FILE: src/com/interview/graph/BellmanFordShortestPath.java ================================================ package com.interview.graph; import java.util.HashMap; import java.util.Map; /** * Date 11/05/2015 * @author Tushar Roy * * Write program for Bellman Ford algorithm to find single source shortest path in directed graph. * Bellman ford works with negative edges as well unlike Dijksra's algorithm. If there is negative * weight cycle it detects it. * * Time complexity - O(EV) * Space complexity - O(V) * * References * https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm * http://www.geeksforgeeks.org/dynamic-programming-set-23-bellman-ford-algorithm/ */ public class BellmanFordShortestPath { //some random big number is treated as infinity. I m not taking INTEGER_MAX as infinity because //doing any addition on that causes integer overflow private static int INFINITY = 10000000; class NegativeWeightCycleException extends RuntimeException { } public Map, Integer> getShortestPath(Graph graph, Vertex sourceVertex) { Map, Integer> distance = new HashMap<>(); Map, Vertex> parent = new HashMap<>(); //set distance of every vertex to be infinity initially for(Vertex v : graph.getAllVertex()) { distance.put(v, INFINITY); parent.put(v, null); } //set distance of source vertex to be 0 distance.put(sourceVertex, 0); int V = graph.getAllVertex().size(); //relax edges repeatedly V - 1 times for (int i = 0; i < V - 1 ; i++) { for (Edge edge : graph.getAllEdges()) { Vertex u = edge.getVertex1(); Vertex v = edge.getVertex2(); //relax the edge //if we get better distance to v via u then use this distance //and set u as parent of v. if (distance.get(u) + edge.getWeight() < distance.get(v)) { distance.put(v, distance.get(u) + edge.getWeight()); parent.put(v, u); } } } //relax all edges again. If we still get lesser distance it means //there is negative weight cycle in the graph. Throw exception in that //case for (Edge edge : graph.getAllEdges()) { Vertex u = edge.getVertex1(); Vertex v = edge.getVertex2(); if (distance.get(u) + edge.getWeight() < distance.get(v)) { throw new NegativeWeightCycleException(); } } return distance; } public static void main(String args[]){ Graph graph = new Graph<>(false); graph.addEdge(0, 3, 8); graph.addEdge(0, 1, 4); graph.addEdge(0, 2, 5); graph.addEdge(1, 2, -3); graph.addEdge(2, 4, 4); graph.addEdge(3, 4, 2); graph.addEdge(4, 3, 1); BellmanFordShortestPath shortestPath = new BellmanFordShortestPath(); Vertex startVertex = graph.getAllVertex().iterator().next(); Map,Integer> distance = shortestPath.getShortestPath(graph, startVertex); System.out.println(distance); } } ================================================ FILE: src/com/interview/graph/BinaryMaxHeap.java ================================================ package com.interview.graph; import java.util.ArrayList; import java.util.List; public class BinaryMaxHeap { private List allNodes = new ArrayList(); class Node { int weight; T data; } public void add(int weight,T data) { Node node = new Node(); node.weight = weight; node.data = data; allNodes.add(node); int size = allNodes.size(); int current = size - 1; int parentIndex = (current - 1) / 2; while (parentIndex >= 0) { Node parentNode = allNodes.get(parentIndex); Node currentNode = allNodes.get(current); if (parentNode.weight < currentNode.weight) { swap(parentNode,currentNode); current = parentIndex; parentIndex = (parentIndex - 1) / 2; } else { break; } } } private void swap(Node node1,Node node2){ int weight = node1.weight; T data = node1.data; node1.data = node2.data; node1.weight = node2.weight; node2.data = data; node2.weight = weight; } public T max(){ return allNodes.get(0).data; } public boolean empty(){ return allNodes.size() == 0; } public T extractMap(){ int size = allNodes.size() -1; T max = allNodes.get(0).data; int lastNodeWeight = allNodes.get(size).weight; allNodes.get(0).weight = lastNodeWeight; allNodes.get(0).data = allNodes.get(size).data; allNodes.remove(size); int currentIndex = 0; size--; while(true){ int left = 2*currentIndex + 1; int right = 2*currentIndex + 2; if(left > size){ break; } if(right > size){ right = left; } int largerIndex = allNodes.get(left).weight >= allNodes.get(right).weight ? left : right; if(allNodes.get(currentIndex).weight < allNodes.get(largerIndex).weight){ swap(allNodes.get(currentIndex),allNodes.get(largerIndex)); currentIndex = largerIndex; }else{ break; } } return max; } public void printHeap(){ for(Node n : allNodes){ System.out.println(n.weight + " " + n.data); } } public static void main(String args[]){ BinaryMaxHeap heap = new BinaryMaxHeap(); heap.add(3, "Tushar"); heap.add(4, "Ani"); heap.add(8, "Vijay"); heap.add(10, "Pramila"); heap.add(5, "Roy"); heap.add(6, "NTF"); heap.printHeap(); } } ================================================ FILE: src/com/interview/graph/BinaryMinHeap.java ================================================ package com.interview.graph; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Date 04/06/2013 * @author Tushar Roy * * Data structure to support following operations * extracMin - O(logn) * addToHeap - O(logn) * containsKey - O(1) * decreaseKey - O(logn) * getKeyWeight - O(1) * * It is a combination of binary heap and hash map * */ public class BinaryMinHeap { private List allNodes = new ArrayList<>(); private Map nodePosition = new HashMap<>(); public class Node { int weight; T key; } /** * Checks where the key exists in heap or not */ public boolean containsData(T key){ return nodePosition.containsKey(key); } /** * Add key and its weight to they heap */ public void add(int weight,T key) { Node node = new Node(); node.weight = weight; node.key = key; allNodes.add(node); int size = allNodes.size(); int current = size - 1; int parentIndex = (current - 1) / 2; nodePosition.put(node.key, current); while (parentIndex >= 0) { Node parentNode = allNodes.get(parentIndex); Node currentNode = allNodes.get(current); if (parentNode.weight > currentNode.weight) { swap(parentNode,currentNode); updatePositionMap(parentNode.key,currentNode.key,parentIndex,current); current = parentIndex; parentIndex = (parentIndex - 1) / 2; } else { break; } } } /** * Get the heap min without extracting the key */ public T min(){ return allNodes.get(0).key; } /** * Checks with heap is empty or not */ public boolean empty(){ return allNodes.size() == 0; } /** * Decreases the weight of given key to newWeight */ public void decrease(T data, int newWeight){ Integer position = nodePosition.get(data); allNodes.get(position).weight = newWeight; int parent = (position -1 )/2; while(parent >= 0){ if(allNodes.get(parent).weight > allNodes.get(position).weight){ swap(allNodes.get(parent), allNodes.get(position)); updatePositionMap(allNodes.get(parent).key,allNodes.get(position).key,parent,position); position = parent; parent = (parent-1)/2; }else{ break; } } } /** * Get the weight of given key */ public Integer getWeight(T key) { Integer position = nodePosition.get(key); if( position == null ) { return null; } else { return allNodes.get(position).weight; } } /** * Returns the min node of the heap */ public Node extractMinNode() { int size = allNodes.size() -1; Node minNode = new Node(); minNode.key = allNodes.get(0).key; minNode.weight = allNodes.get(0).weight; int lastNodeWeight = allNodes.get(size).weight; allNodes.get(0).weight = lastNodeWeight; allNodes.get(0).key = allNodes.get(size).key; nodePosition.remove(minNode.key); nodePosition.remove(allNodes.get(0)); nodePosition.put(allNodes.get(0).key, 0); allNodes.remove(size); int currentIndex = 0; size--; while(true){ int left = 2*currentIndex + 1; int right = 2*currentIndex + 2; if(left > size){ break; } if(right > size){ right = left; } int smallerIndex = allNodes.get(left).weight <= allNodes.get(right).weight ? left : right; if(allNodes.get(currentIndex).weight > allNodes.get(smallerIndex).weight){ swap(allNodes.get(currentIndex), allNodes.get(smallerIndex)); updatePositionMap(allNodes.get(currentIndex).key,allNodes.get(smallerIndex).key,currentIndex,smallerIndex); currentIndex = smallerIndex; }else{ break; } } return minNode; } /** * Extract min value key from the heap */ public T extractMin(){ Node node = extractMinNode(); return node.key; } private void printPositionMap(){ System.out.println(nodePosition); } private void swap(Node node1,Node node2){ int weight = node1.weight; T data = node1.key; node1.key = node2.key; node1.weight = node2.weight; node2.key = data; node2.weight = weight; } private void updatePositionMap(T data1, T data2, int pos1, int pos2){ nodePosition.remove(data1); nodePosition.remove(data2); nodePosition.put(data1, pos1); nodePosition.put(data2, pos2); } public void printHeap(){ for(Node n : allNodes){ System.out.println(n.weight + " " + n.key); } } public static void main(String args[]){ BinaryMinHeap heap = new BinaryMinHeap(); heap.add(3, "Tushar"); heap.add(4, "Ani"); heap.add(8, "Vijay"); heap.add(10, "Pramila"); heap.add(5, "Roy"); heap.add(6, "NTF"); heap.add(2,"AFR"); heap.decrease("Pramila", 1); heap.printHeap(); heap.printPositionMap(); } } ================================================ FILE: src/com/interview/graph/BiparteGraph.java ================================================ package com.interview.graph; import java.util.HashSet; import java.util.LinkedList; import java.util.Queue; import java.util.Set; /** http://www.geeksforgeeks.org/bipartite-graph/ Includes both DFS and BFS method */ public class BiparteGraph { public boolean isBiparte(Graph graph){ Set> redSet = new HashSet>(); Set> blueSet = new HashSet>(); Queue> queue = new LinkedList>(); for(Vertex vertex : graph.getAllVertex()){ if(!redSet.contains(vertex) && !blueSet.contains(vertex)){ queue.add(vertex); redSet.add(vertex); while(!queue.isEmpty()){ vertex = queue.poll(); for(Vertex v : vertex.getAdjacentVertexes()){ if(redSet.contains(vertex)){ if(redSet.contains(v)){ return false; }if(blueSet.contains(v)){ continue; } blueSet.add(v); } else if(blueSet.contains(vertex)){ if(blueSet.contains(v)){ return false; }if(redSet.contains(v)){ continue; } redSet.add(v); } queue.add(v); } } } } System.out.println(redSet); System.out.println(blueSet); return true; } public boolean isBiparteDFS(Graph graph){ Set> redSet = new HashSet>(); Set> blueSet = new HashSet>(); for(Vertex vertex : graph.getAllVertex()){ if(redSet.contains(vertex) || blueSet.contains(vertex)){ continue; } boolean flag = isBiparteDFS(vertex, redSet, blueSet, true); if(!flag){ return false; } } return true; } private boolean isBiparteDFS(Vertex vertex, Set> redSet, Set> blueSet,boolean wasRed){ if(wasRed){ if(redSet.contains(vertex)){ return false; } else if(blueSet.contains(vertex)){ return true; } blueSet.add(vertex); } else if(!wasRed){ if(blueSet.contains(vertex)){ return false; } if(redSet.contains(vertex)){ return true; } redSet.add(vertex); } for(Vertex adj : vertex.getAdjacentVertexes()){ boolean flag = isBiparteDFS(adj, redSet, blueSet, !wasRed); if(!flag){ return false; } } return true; } public static void main(String argsp[]){ Graph graph = new Graph(false); graph.addEdge(1, 2); graph.addEdge(2, 5); graph.addEdge(1, 3); graph.addEdge(3, 4); graph.addEdge(4, 6); graph.addEdge(5, 6); graph.addEdge(7, 9); graph.addEdge(7, 8); BiparteGraph bi = new BiparteGraph(); boolean result = bi.isBiparteDFS(graph); System.out.print(result); } } ================================================ FILE: src/com/interview/graph/Boggle.java ================================================ package com.interview.graph; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Date 03/04/2016 * @author Tushar Roy * * Search for dictionary words in the board. * Idea is to use trie for the dictionary which keeps search * very efficient. * * https://leetcode.com/problems/word-search-ii/ */ public class Boggle { public List findWords(char[][] board, String[] words) { Trie t = new Trie(); for (String word : words) { t.insert(word); } StringBuffer buff = new StringBuffer(); Set result = new HashSet<>(); Set visited = new HashSet<>(); for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[i].length; j++) { findWordsUtil(board, t, i, j, buff, visited, result, board[0].length); } } return new ArrayList<>(result); } private void findWordsUtil(char[][] board, Trie t , int i, int j, StringBuffer buff, Set visited, Set result, int col ) { if (i < 0 || j < 0 || i >= board.length || j >= board[i].length) { return; } int val = i*col + j; if (visited.contains(val)) { return; } buff.append(board[i][j]); String str = buff.toString(); if(!t.startsWith(str)) { buff.deleteCharAt(buff.length() - 1); return; } visited.add(val); if(t.search(str)) { result.add(buff.toString()); } findWordsUtil(board, t, i + 1, j, buff, visited, result, col); findWordsUtil(board, t, i, j + 1, buff, visited, result, col); findWordsUtil(board, t, i, j - 1, buff, visited, result, col); findWordsUtil(board, t, i - 1, j, buff, visited, result, col); buff.deleteCharAt(buff.length() - 1); visited.remove(val); } class TrieNode { TrieNode[] child = new TrieNode[26]; boolean isWord; public TrieNode() { } } class Trie { private TrieNode root; public Trie() { root = new TrieNode(); } // Inserts a word into the trie. public void insert(String word) { TrieNode current = root; for (int i = 0; i < word.length(); i++) { char ch = (char)(word.charAt(i) - 'a'); if (current.child[ch] == null) { current.child[ch] = new TrieNode(); } current = current.child[ch]; } current.isWord = true; } // Returns if the word is in the trie. public boolean search(String word) { TrieNode current = root; for (int i = 0; i < word.length(); i++) { char ch = (char)(word.charAt(i) - 'a'); if (current.child[ch] == null) { return false; } current = current.child[ch]; } return current.isWord; } // Returns if there is any word in the trie // that starts with the given prefix. public boolean startsWith(String prefix) { TrieNode current = root; for (int i = 0; i < prefix.length(); i++) { char ch = (char)(prefix.charAt(i) - 'a'); if (current.child[ch] == null) { return false; } current = current.child[ch]; } return true; } public void printTrie() { printTrieUtil(root); } private void printTrieUtil(TrieNode root) { if (root == null) { return; } for (int i = 0; i < root.child.length; i++) { if (root.child[i] != null) { System.out.println((char)(i + 'a')); printTrieUtil(root.child[i]); } } } } public static void main(String args[]) { char[][] board = {{'o','a','a','n'},{'e','t','a','e'},{'i','h','k','r'},{'i','f','l','v'}}; String[] words = {"oath","pea","eat","rain"}; Boggle boggle = new Boggle(); List result = boggle.findWords(board, words); result.stream().forEach(s -> System.out.println(s)); } } ================================================ FILE: src/com/interview/graph/Bridge.java ================================================ package com.interview.graph; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** http://www.geeksforgeeks.org/bridge-in-a-graph/ */ public class Bridge { private int time; public Set> getBridge(Graph graph){ Set> result = new HashSet>(); Map,Integer> discovery = new HashMap,Integer>(); Map,Integer> low = new HashMap,Integer>(); Map,Vertex> parent = new HashMap,Vertex>(); Map,Boolean> visited = new HashMap,Boolean>(); for(Vertex vertex : graph.getAllVertex()){ if(!visited.containsKey(vertex)){ BridgeUtil(vertex,result,discovery,low,parent,visited); } } return result; } private void BridgeUtil(Vertex vertex, Set> result,Map,Integer> discovery, Map,Integer> low,Map,Vertex> parent,Map,Boolean> visited){ visited.put(vertex, true); discovery.put(vertex, time); low.put(vertex, time); time++; for(Vertex child : vertex.getAdjacentVertexes()){ if(!visited.containsKey(child)){ parent.put(child, vertex); BridgeUtil(child,result,discovery,low,parent,visited); if(discovery.get(vertex) < low.get(child) ){ result.add(new Edge(vertex,child)); } low.put(vertex, Math.min(discovery.get(vertex), low.get(child))); }else{ if(!child.equals(parent.get(vertex))){ low.put(vertex,Math.min(discovery.get(vertex), low.get(child))); } } } } public static void main(String args[]){ Graph graph = new Graph(false); graph.addEdge(2, 1); graph.addEdge(3, 1); graph.addEdge(1, 4); graph.addEdge(4, 5); graph.addEdge(5, 1); Bridge ap = new Bridge(); Set> result = ap.getBridge(graph); System.out.print(result); } } ================================================ FILE: src/com/interview/graph/CloneDirectedGraph.java ================================================ package com.interview.graph; import java.util.HashMap; import java.util.Map; /** * Given a directed graph clone it in O(n) time where n is total number of edges * Test cases * Graph is directed/non directed * Graph has 0 edges * Graph has cycle * Graph is linear * Graph is dense * Graph is sparse */ public class CloneDirectedGraph { public Graph clone(Graph graph){ if(graph == null){ return null; } if(!graph.isDirected){ throw new IllegalArgumentException("Cloning non directed graph"); } if(graph.getAllVertex().size() == 0){ throw new IllegalArgumentException("No vertex in the graph"); } Map,Vertex> cloneMap = new HashMap,Vertex>(); for(Vertex vertex : graph.getAllVertex()){ clone(vertex,cloneMap); } Graph clonedGraph = new Graph<>(true); for(Vertex vertex : cloneMap.values()){ clonedGraph.addVertex(vertex); } return clonedGraph; } private void clone(Vertex origVertex,Map,Vertex> cloneMap){ Vertex cloneVertex = null; if(cloneMap.containsKey(origVertex)){ cloneVertex = cloneMap.get(origVertex); }else{ cloneVertex = new Vertex(origVertex.getId()*10); cloneMap.put(origVertex, cloneVertex); } for(Edge edge : origVertex.getEdges()){ if(edge.getVertex1().equals(origVertex)){ Vertex adjVertex = edge.getVertex2(); updateMap(cloneMap,cloneVertex,adjVertex,edge); }else{ Vertex adjVertex = edge.getVertex1(); updateMap(cloneMap,cloneVertex,adjVertex,edge); } } } private void updateMap(Map,Vertex> cloneMap, Vertex cloneVertex, Vertex adjVertex, Edge edge){ if(cloneMap.containsKey(adjVertex)){ Vertex adjVertexClone = cloneMap.get(adjVertex); Edge newEdge = new Edge(cloneVertex, adjVertexClone, edge.isDirected(), edge.getWeight()); cloneVertex.addAdjacentVertex(newEdge, adjVertexClone); }else{ Vertex adjVertexClone = new Vertex(adjVertex.getId()); cloneMap.put(adjVertex, adjVertexClone); Edge newEdge = new Edge(cloneVertex, adjVertexClone, edge.isDirected(), edge.getWeight()); cloneVertex.addAdjacentVertex(newEdge, adjVertexClone); } } public static void main(String args[]){ Graph graph = new Graph(true); graph.addEdge(0, 3); graph.addEdge(0, 2); graph.addEdge(0, 4); graph.addEdge(3, 2); graph.addEdge(2, 0); graph.addEdge(4, 3); graph.addEdge(4, 1); graph.addEdge(1, 2); CloneDirectedGraph cg = new CloneDirectedGraph<>(); Graph clonedGraph = cg.clone(graph); System.out.println(clonedGraph); } } ================================================ FILE: src/com/interview/graph/CloneGraph.java ================================================ package com.interview.graph; import java.util.*; /** * Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. * https://leetcode.com/problems/clone-graph/ */ public class CloneGraph { class UndirectedGraphNode { int label; List neighbors; UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList(); } }; public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { if (node == null) { return null; } UndirectedGraphNode clone = new UndirectedGraphNode(node.label); Set visited = new HashSet<>(); Map map = new HashMap<>(); map.put(clone.label, clone); dfs(node, clone, map, visited); return clone; } private void dfs(UndirectedGraphNode current, UndirectedGraphNode clone, Map map, Set visited) { if (visited.contains(current.label)) { return; } visited.add(current.label); for (UndirectedGraphNode adj : current.neighbors) { if (adj.label != current.label) { UndirectedGraphNode adjClone = map.get(adj.label); if (adjClone == null) { adjClone = new UndirectedGraphNode(adj.label); map.put(adjClone.label, adjClone); } clone.neighbors.add(adjClone); dfs(adj, adjClone, map, visited); } else { clone.neighbors.add(clone); } } } } ================================================ FILE: src/com/interview/graph/ConvertOneWordToAnother.java ================================================ package com.interview.graph; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.Map; import java.util.Queue; import java.util.Set; /** * 150s qs 18.10 * Given two words of equal length in dictionary convert one word to another one letter at a time * in such a way that all intermediate words are int the dictionary */ public class ConvertOneWordToAnother { public void convert(String word1, String word2, Set dict) { Set visited = new HashSet(); Queue queue = new LinkedList(); Map parentMap = new HashMap(); queue.add(word1); visited.add(word1); while (queue.size() != 0) { String word = queue.poll(); if (word.equals(word2)) { break; } for (int i = 0; i < word.length(); i++) { for (int ch = 'a'; ch <= 'z'; ch++) { String newWord = replace(word, i, (char) ch); if (dict.contains(newWord)){ if (!visited.contains(newWord)) { parentMap.put(newWord, word); queue.add(newWord); visited.add(newWord); } } } } } String word = word2; while(word != null){ System.out.println(word); word = parentMap.get(word); } } public String replace(String newWord, int pos, char ch) { StringBuffer buffer = new StringBuffer(); buffer.append(newWord.substring(0, pos)); buffer.append(ch); buffer.append(newWord.substring(pos+1,newWord.length())); return buffer.toString(); } public static void main(String args[]){ Set dictionary = new HashSet(); dictionary.add("cat"); dictionary.add("pat"); dictionary.add("pit"); dictionary.add("pid"); dictionary.add("did"); ConvertOneWordToAnother cow = new ConvertOneWordToAnother(); cow.convert("cat", "did", dictionary); } } ================================================ FILE: src/com/interview/graph/CourseSchedule.java ================================================ package com.interview.graph; import java.util.ArrayList; import java.util.Deque; import java.util.LinkedList; import java.util.List; /** * Date 03/01/2016 * @author Tushar Roy * * There are a total of n courses you have to take, labeled from 0 to n - 1. * Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1] * Given the total number of courses and a list of prerequisite pairs, return the ordering of courses you should take to finish all courses. * There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array. * * Time complexity O(n) * Space complexity O(n) * * https://leetcode.com/problems/course-schedule-ii/ */ public class CourseSchedule { public int[] findOrder(int numCourses, int[][] prerequisites) { boolean[] used = new boolean[numCourses]; Neighbors[] graph = new Neighbors[numCourses]; for (int i = 0; i < graph.length; i++) { graph[i] = new Neighbors(); } for (int[] tuple : prerequisites) { graph[tuple[1]].neighbor.add(tuple[0]); } Deque stack = new LinkedList<>(); boolean[] dfs = new boolean[numCourses]; for (int i = 0; i < numCourses; i++) { if (topSort(i, graph, used, stack, dfs)) { return new int[0]; } } int[] output = new int[numCourses]; int index = 0; while (!stack.isEmpty()) { output[index++] = stack.pollFirst(); } return output; } class Neighbors { List neighbor = new ArrayList<>(); } private boolean topSort(int course, Neighbors[] graph, boolean[] used, Deque stack, boolean[] dfs) { if (used[course]) { return false; } if (dfs[course]) { return true; } dfs[course] = true; for (int adj : graph[course].neighbor) { if (topSort(adj, graph, used, stack, dfs)) { return true; } } dfs[course] = false; used[course] = true; stack.offerFirst(course); return false; } } ================================================ FILE: src/com/interview/graph/CycleInDirectedGraph.java ================================================ package com.interview.graph; import java.util.HashSet; import java.util.Set; /** * http://www.geeksforgeeks.org/detect-cycle-in-a-graph/ */ public class CycleInDirectedGraph { public boolean hasCycle(Graph graph) { Set> whiteSet = new HashSet<>(); Set> graySet = new HashSet<>(); Set> blackSet = new HashSet<>(); for (Vertex vertex : graph.getAllVertex()) { whiteSet.add(vertex); } while (whiteSet.size() > 0) { Vertex current = whiteSet.iterator().next(); if(dfs(current, whiteSet, graySet, blackSet)) { return true; } } return false; } private boolean dfs(Vertex current, Set> whiteSet, Set> graySet, Set> blackSet ) { //move current to gray set from white set and then explore it. moveVertex(current, whiteSet, graySet); for(Vertex neighbor : current.getAdjacentVertexes()) { //if in black set means already explored so continue. if (blackSet.contains(neighbor)) { continue; } //if in gray set then cycle found. if (graySet.contains(neighbor)) { return true; } if(dfs(neighbor, whiteSet, graySet, blackSet)) { return true; } } //move vertex from gray set to black set when done exploring. moveVertex(current, graySet, blackSet); return false; } private void moveVertex(Vertex vertex, Set> sourceSet, Set> destinationSet) { sourceSet.remove(vertex); destinationSet.add(vertex); } public static void main(String args[]){ Graph graph = new Graph<>(true); graph.addEdge(1, 2); graph.addEdge(1, 3); graph.addEdge(2, 3); graph.addEdge(4, 1); graph.addEdge(4, 5); graph.addEdge(5, 6); graph.addEdge(6, 4); CycleInDirectedGraph cdg = new CycleInDirectedGraph(); System.out.println(cdg.hasCycle(graph)); } } ================================================ FILE: src/com/interview/graph/CycleUndirectedGraph.java ================================================ package com.interview.graph; import java.util.HashSet; import java.util.Set; /** * Date 10/11/2014 * @author Tushar Roy * * Given an undirected graph find cycle in this graph. * * Solution * This can be solved in many ways. * Below is the code to solve it using disjoint sets and DFS. * * Runtime and space complexity for both the techniques is O(v) * where v is total number of vertices in the graph. */ public class CycleUndirectedGraph { public boolean hasCycleUsingDisjointSets(Graph graph){ DisjointSet disjointSet = new DisjointSet(); for(Vertex vertex : graph.getAllVertex()){ disjointSet.makeSet(vertex.getId()); } for(Edge edge : graph.getAllEdges()){ long parent1 = disjointSet.findSet(edge.getVertex1().getId()); long parent2 = disjointSet.findSet(edge.getVertex2().getId()); if(parent1 == parent2){ return true; } disjointSet.union(edge.getVertex1().getId(), edge.getVertex2().getId()); } return false; } public boolean hasCycleDFS(Graph graph){ Set> visited = new HashSet>(); for(Vertex vertex : graph.getAllVertex()){ if(visited.contains(vertex)){ continue; } boolean flag = hasCycleDFSUtil(vertex, visited, null); if(flag){ return true; } } return false; } public boolean hasCycleDFSUtil(Vertex vertex, Set> visited,Vertex parent){ visited.add(vertex); for(Vertex adj : vertex.getAdjacentVertexes()){ if(adj.equals(parent)){ continue; } if(visited.contains(adj)){ return true; } boolean hasCycle = hasCycleDFSUtil(adj,visited,vertex); if(hasCycle){ return true; } } return false; } public static void main(String args[]){ CycleUndirectedGraph cycle = new CycleUndirectedGraph(); Graph graph = new Graph(false); graph.addEdge(0, 1); graph.addEdge(1, 2); graph.addEdge(0, 3); graph.addEdge(3, 4); graph.addEdge(4, 5); graph.addEdge(5, 1); boolean isCycle = cycle.hasCycleDFS(graph); System.out.println(isCycle); isCycle = cycle.hasCycleUsingDisjointSets(graph); System.out.print(isCycle); } } ================================================ FILE: src/com/interview/graph/DAGShortestPathTopological.java ================================================ package com.interview.graph; import java.util.Deque; import java.util.HashMap; import java.util.Map; /** http://www.geeksforgeeks.org/shortest-path-for-directed-acyclic-graphs/ */ public class DAGShortestPathTopological { public Map,Integer> shortestPath(Graph graph,Vertex startVertex){ Map,Integer> distance = new HashMap,Integer>(); TopologicalSort sort = new TopologicalSort(); Deque> deque = sort.topSort(graph); distance.put(startVertex, 0); while(!deque.isEmpty()){ Vertex vertex = deque.poll(); for(Edge edge : vertex.getEdges()){ if(getDistance(edge.getVertex2(),distance) > getDistance(edge.getVertex1(),distance) + edge.getWeight()){ distance.put(edge.getVertex2(), getDistance(edge.getVertex1(),distance) + edge.getWeight()); } } } return distance; } private int getDistance( Vertex vertex,Map,Integer> distance){ return distance.containsKey(vertex) ? distance.get(vertex) : 1000; } public static void main(String args[]){ Graph graph = new Graph(true); graph.addEdge(1, 2,4); graph.addEdge(2, 3,3); graph.addEdge(2, 4,2); graph.addEdge(1, 3,2); graph.addEdge(3, 5,1); graph.addEdge(4, 5,5); graph.addEdge(5, 6,2); graph.addEdge(4, 7,3); DAGShortestPathTopological shortestPath = new DAGShortestPathTopological(); Map,Integer> distance = shortestPath.shortestPath(graph, graph.getAllVertex().iterator().next()); System.out.print(distance); } } ================================================ FILE: src/com/interview/graph/DijkstraShortestPath.java ================================================ package com.interview.graph; import java.util.HashMap; import java.util.Map; /** * Date 10/11/2014 * @author Tushar Roy * * Find single source shortest path using Dijkstra's algorithm * * Space complexity - O(E + V) * Time complexity - O(ElogV) * * References * https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm * CLRS book*/ public class DijkstraShortestPath { public Map,Integer> shortestPath(Graph graph, Vertex sourceVertex){ //heap + map data structure BinaryMinHeap> minHeap = new BinaryMinHeap<>(); //stores shortest distance from root to every vertex Map,Integer> distance = new HashMap<>(); //stores parent of every vertex in shortest distance Map, Vertex> parent = new HashMap<>(); //initialize all vertex with infinite distance from source vertex for(Vertex vertex : graph.getAllVertex()){ minHeap.add(Integer.MAX_VALUE, vertex); } //set distance of source vertex to 0 minHeap.decrease(sourceVertex, 0); //put it in map distance.put(sourceVertex, 0); //source vertex parent is null parent.put(sourceVertex, null); //iterate till heap is not empty while(!minHeap.empty()){ //get the min value from heap node which has vertex and distance of that vertex from source vertex. BinaryMinHeap>.Node heapNode = minHeap.extractMinNode(); Vertex current = heapNode.key; //update shortest distance of current vertex from source vertex distance.put(current, heapNode.weight); //iterate through all edges of current vertex for(Edge edge : current.getEdges()){ //get the adjacent vertex Vertex adjacent = getVertexForEdge(current, edge); //if heap does not contain adjacent vertex means adjacent vertex already has shortest distance from source vertex if(!minHeap.containsData(adjacent)){ continue; } //add distance of current vertex to edge weight to get distance of adjacent vertex from source vertex //when it goes through current vertex int newDistance = distance.get(current) + edge.getWeight(); //see if this above calculated distance is less than current distance stored for adjacent vertex from source vertex if(minHeap.getWeight(adjacent) > newDistance) { minHeap.decrease(adjacent, newDistance); parent.put(adjacent, current); } } } return distance; } private Vertex getVertexForEdge(Vertex v, Edge e){ return e.getVertex1().equals(v) ? e.getVertex2() : e.getVertex1(); } public static void main(String args[]){ Graph graph = new Graph<>(false); /*graph.addEdge(0, 1, 4); graph.addEdge(1, 2, 8); graph.addEdge(2, 3, 7); graph.addEdge(3, 4, 9); graph.addEdge(4, 5, 10); graph.addEdge(2, 5, 4); graph.addEdge(1, 7, 11); graph.addEdge(0, 7, 8); graph.addEdge(2, 8, 2); graph.addEdge(3, 5, 14); graph.addEdge(5, 6, 2); graph.addEdge(6, 8, 6); graph.addEdge(6, 7, 1); graph.addEdge(7, 8, 7);*/ graph.addEdge(1, 2, 5); graph.addEdge(2, 3, 2); graph.addEdge(1, 4, 9); graph.addEdge(1, 5, 3); graph.addEdge(5, 6, 2); graph.addEdge(6, 4, 2); graph.addEdge(3, 4, 3); DijkstraShortestPath dsp = new DijkstraShortestPath(); Vertex sourceVertex = graph.getVertex(1); Map,Integer> distance = dsp.shortestPath(graph, sourceVertex); System.out.print(distance); } } ================================================ FILE: src/com/interview/graph/DirectedGraphConnectivity.java ================================================ package com.interview.graph; import java.util.ArrayDeque; import java.util.Deque; import java.util.HashMap; import java.util.Map; public class DirectedGraphConnectivity { public boolean scc(Graph graph) { Deque> stack = new ArrayDeque>(); Map, Boolean> visited = new HashMap, Boolean>(); for (Vertex vertex : graph.getAllVertex()) { if (visited.containsKey(vertex)) { continue; } DFSUtil(vertex, visited, stack); } System.out.println(stack); Graph reverseGraph = new Graph(true); Map> vertexMap = new HashMap>(); for (Edge edge : graph.getAllEdges()) { reverseGraph.addEdge(edge.getVertex2().getId(), edge.getVertex1() .getId(), edge.getWeight()); } for (Vertex vertex : reverseGraph.getAllVertex()) { vertexMap.put(vertex.getId(), vertex); } visited.clear(); Vertex vertex = vertexMap.get(stack.poll().getId()); DFSUtil1(vertex, visited); for(Vertex testVertex : reverseGraph.getAllVertex()){ if(!visited.containsKey(testVertex)){ return false; } } return true; } private void DFSUtil(Vertex vertex, Map, Boolean> visited, Deque> stack) { visited.put(vertex, true); for (Vertex v : vertex.getAdjacentVertexes()) { if (visited.containsKey(v)) { continue; } DFSUtil(v, visited, stack); } stack.offerFirst(vertex); } private void DFSUtil1(Vertex vertex, Map, Boolean> visited) { visited.put(vertex, true); for (Vertex v : vertex.getAdjacentVertexes()) { if (visited.containsKey(v)) { continue; } DFSUtil1(v, visited); } } public static void main(String args[]){ Graph graph = new Graph(true); graph.addEdge(1, 0); graph.addEdge(2,1); graph.addEdge(0,2); graph.addEdge(0, 3); graph.addEdge(3, 4); graph.addEdge(4, 2); DirectedGraphConnectivity scc = new DirectedGraphConnectivity(); boolean result = scc.scc(graph); System.out.println(result); } } ================================================ FILE: src/com/interview/graph/DisjointSet.java ================================================ package com.interview.graph; import java.util.HashMap; import java.util.Map; /** * @author tusroy * Date 06/20/2015 * * Video link - https://youtu.be/ID00PMy0-vE * * Disjoint sets using path compression and union by rank * Supports 3 operations * 1) makeSet * 2) union * 3) findSet * * For m operations and total n elements time complexity is O(m*f(n)) where f(n) is * very slowly growing function. For most cases f(n) <= 4 so effectively * total time will be O(m). Proof in Coreman book. */ public class DisjointSet { private Map map = new HashMap<>(); class Node { long data; Node parent; int rank; } /** * Create a set with only one element. */ public void makeSet(long data) { Node node = new Node(); node.data = data; node.parent = node; node.rank = 0; map.put(data, node); } /** * Combines two sets together to one. * Does union by rank * * @return true if data1 and data2 are in different set before union else false. */ public boolean union(long data1, long data2) { Node node1 = map.get(data1); Node node2 = map.get(data2); Node parent1 = findSet(node1); Node parent2 = findSet(node2); //if they are part of same set do nothing if (parent1.data == parent2.data) { return false; } //else whoever's rank is higher becomes parent of other if (parent1.rank >= parent2.rank) { //increment rank only if both sets have same rank parent1.rank = (parent1.rank == parent2.rank) ? parent1.rank + 1 : parent1.rank; parent2.parent = parent1; } else { parent1.parent = parent2; } return true; } /** * Finds the representative of this set */ public long findSet(long data) { return findSet(map.get(data)).data; } /** * Find the representative recursively and does path * compression as well. */ private Node findSet(Node node) { Node parent = node.parent; if (parent == node) { return parent; } node.parent = findSet(node.parent); return node.parent; } public static void main(String args[]) { DisjointSet ds = new DisjointSet(); ds.makeSet(1); ds.makeSet(2); ds.makeSet(3); ds.makeSet(4); ds.makeSet(5); ds.makeSet(6); ds.makeSet(7); ds.union(1, 2); ds.union(2, 3); ds.union(4, 5); ds.union(6, 7); ds.union(5, 6); ds.union(3, 7); System.out.println(ds.findSet(1)); System.out.println(ds.findSet(2)); System.out.println(ds.findSet(3)); System.out.println(ds.findSet(4)); System.out.println(ds.findSet(5)); System.out.println(ds.findSet(6)); System.out.println(ds.findSet(7)); } } ================================================ FILE: src/com/interview/graph/EulerianPathAndCircuit.java ================================================ package com.interview.graph; import java.util.HashMap; import java.util.Map; public class EulerianPathAndCircuit { public enum Eulerian{ NOT_EULERIAN, EULERIAN, SEMIEULERIAN } private boolean isConnected(Graph graph){ Vertex startVertex = null; for(Vertex vertex : graph.getAllVertex()){ if(vertex.getDegree() != 0){ startVertex = vertex; break; } } if(startVertex == null){ return true; } Map,Boolean> visited = new HashMap, Boolean>(); DFS(startVertex,visited); for(Vertex testVertex : graph.getAllVertex()){ if(testVertex.getDegree()!= 0 && !visited.containsKey(testVertex)){ return false; } } return true; } private void DFS(Vertex startVertex, Map, Boolean> visited){ visited.put(startVertex, true); for(Vertex child : startVertex.getAdjacentVertexes()){ if(!visited.containsKey(child)){ DFS(child,visited); } } } public Eulerian isEulerian(Graph graph){ if(!isConnected(graph)){ return Eulerian.NOT_EULERIAN; } int odd = 0; for(Vertex vertex : graph.getAllVertex()){ if(vertex.getDegree()!=0 && vertex.getDegree() % 2 != 0){ odd++; } } if(odd > 2){ return Eulerian.NOT_EULERIAN; } return odd == 0 ? Eulerian.EULERIAN : Eulerian.SEMIEULERIAN; } public static void main(String args[]){ Graph graph = new Graph(false); graph.addSingleVertex(1); graph.addSingleVertex(2); graph.addSingleVertex(3); graph.addEdge(4, 5); graph.addEdge(6, 4); graph.addEdge(5,6); EulerianPathAndCircuit eulerian = new EulerianPathAndCircuit(); Eulerian result = eulerian.isEulerian(graph); System.out.print(result); } } ================================================ FILE: src/com/interview/graph/EvaluateDivison.java ================================================ package com.interview.graph; import java.util.HashMap; import java.util.Map; /** * Date 10/31/2016 * @author Tushar Roy * * Equations are given in the format A / B = k, where A and B are variables represented as strings, and k is a real number (floating point number). * Given some queries, return the answers. If the answer does not exist, return -1.0. * * Solution * Do Flyod warshall algorithm initialized as values between equations. Do Flyod Warshall to create * all possible paths b/w two strings. * * Time complexity O(n * n * n) + O(m) * where n is total number of strings in equations and m is total number of queries * * Reference * https://leetcode.com/problems/evaluate-division/ */ public class EvaluateDivison { public double[] calcEquation(String[][] equations, double[] values, String[][] queries) { if (equations.length == 0) { return new double[0]; } Map index = new HashMap<>(); int count = 0; for (int i = 0; i < equations.length; i++) { String first = equations[i][0]; String second = equations[i][1]; if (!index.containsKey(first)) { index.put(first, count++); } if (!index.containsKey(second)) { index.put(second, count++); } } double graph[][] = new double[count][count]; for (int i = 0; i < graph.length; i++) { for (int j = 0; j < graph[i].length; j++) { graph[i][j] = -1; } } for (int i = 0; i < equations.length; i++) { String first = equations[i][0]; String second = equations[i][1]; int i1 = index.get(first); int i2 = index.get(second); graph[i1][i1] = graph[i2][i2] = 1.0; graph[i1][i2] = values[i]; graph[i2][i1] = 1/values[i]; } for (int i = 0 ; i < graph.length; i++) { for (int j = 0; j < graph.length; j++) { if (graph[i][j] != -1) { continue; } for (int k = 0; k < graph.length; k++) { if (graph[i][k] == -1 || graph[k][j] == -1) { continue; } graph[i][j] = graph[i][k] * graph[k][j]; } } } double[] result = new double[queries.length]; for (int i = 0; i < queries.length; i++) { String first = queries[i][0]; String second = queries[i][1]; if (!index.containsKey(first) || !index.containsKey(second)) { result[i] = -1; } else { int i1 = index.get(first); int i2 = index.get(second); result[i] = graph[i1][i2]; } } return result; } } ================================================ FILE: src/com/interview/graph/FillOsWIthXsIfSurroundedByXs.java ================================================ package com.interview.graph; /** * Date 04/17/2016 * @author Tushar Roy * * Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. * A region is captured by flipping all 'O's into 'X's in that surrounded region. * * Reference * https://leetcode.com/problems/surrounded-regions/ */ public class FillOsWIthXsIfSurroundedByXs { public void solve(char[][] board) { if (board.length == 0 || board[0].length == 0) { return; } for (int i = 0; i < board.length; i++) { dfs(board, i, 0); dfs(board, i, board[0].length - 1); } for (int i = 0; i < board[0].length; i++) { dfs(board, 0, i); dfs(board, board.length - 1, i); } for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { if (board[i][j] == 'O') { board[i][j] = 'X'; } else if (board[i][j] == '1') { board[i][j] = 'O'; } } } } private void dfs(char[][] board, int i, int j) { if (i < 0 || i >= board.length || j < 0 || j >= board[0].length) { return; } if (board[i][j] != 'O') { return; } board[i][j] = '1'; if (i < board.length - 2) { dfs(board, i + 1, j); } if (i > 1) { dfs(board, i - 1, j); } if (j < board[0].length - 2) { dfs(board, i, j + 1); } if (j > 1) { dfs(board, i, j - 1); } } public static void main(String args[]){ FillOsWIthXsIfSurroundedByXs fo = new FillOsWIthXsIfSurroundedByXs(); char board[][] = {{'X','X','X','X'}, {'X','X','O','X'}, {'X','O','X','X'}, {'X','X','O','X'}}; fo.solve(board); } } ================================================ FILE: src/com/interview/graph/FloodFillAlgorithm.java ================================================ package com.interview.graph; /** * http://en.wikipedia.org/wiki/Flood_fill * */ public class FloodFillAlgorithm { public void fillDFS(int screen[][], int oldColor, int newColor,int startx,int starty){ fillUtil(screen,startx,starty,oldColor,newColor); } public void fillUtil(int screen[][], int currentx,int currenty, int oldColor, int newColor){ if(currentx < 0 || currentx >= screen.length || currenty < 0 || currenty >= screen[currentx].length){ return; } if(screen[currentx][currenty] != oldColor){ return; } screen[currentx][currenty] = newColor; fillUtil(screen,currentx+1,currenty,oldColor,newColor); fillUtil(screen,currentx-1,currenty,oldColor,newColor); fillUtil(screen,currentx,currenty+1,oldColor,newColor); fillUtil(screen,currentx,currenty-1,oldColor,newColor); } public static void main(String args[]){ int screen[][] = {{1,1,1,1,1,1}, {1,1,1,1,1,1}, {1,0,0,1,1,0}, {1,1,1,0,0,0}, {1,1,1,0,1,0}, {1,1,1,1,1,1}}; FloodFillAlgorithm ff = new FloodFillAlgorithm(); ff.fillDFS(screen, 0, 2, 3, 3); for(int i=0; i < screen.length; i++){ for(int j=0; j < screen[i].length; j++){ System.out.print(screen[i][j] + " "); } System.out.println(); } } } ================================================ FILE: src/com/interview/graph/FloydWarshallAllPairShortestPath.java ================================================ package com.interview.graph; import java.util.Deque; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; /** * Date 11/02/2015 * @author Tushar Roy * * Floyd-Warshall Algorithm for finding all pair shortest path. * * Time complexity - O(V^3) * Space complexity - O(V^2) * * References * https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm */ public class FloydWarshallAllPairShortestPath { class NegativeWeightCycleException extends RuntimeException { } private static final int INF = 1000000; public int[][] allPairShortestPath(int[][] distanceMatrix) { int distance[][] = new int[distanceMatrix.length][distanceMatrix.length]; int path[][] = new int[distanceMatrix.length][distanceMatrix.length]; for (int i=0; i < distanceMatrix.length; i++) { for (int j=0; j< distanceMatrix[i].length; j++){ distance[i][j] = distanceMatrix[i][j]; if (distanceMatrix[i][j] != INF && i != j) { path[i][j] = i; } else { path[i][j] = -1; } } } for(int k=0; k < distanceMatrix.length; k++){ for(int i=0; i < distanceMatrix.length; i++){ for(int j=0; j < distanceMatrix.length; j++){ if(distance[i][k] == INF || distance[k][j] == INF) { continue; } if(distance[i][j] > distance[i][k] + distance[k][j]){ distance[i][j] = distance[i][k] + distance[k][j]; path[i][j] = path[k][j]; } } } } //look for negative weight cycle in the graph //if values on diagonal of distance matrix is negative //then there is negative weight cycle in the graph. for(int i = 0; i < distance.length; i++) { if(distance[i][i] < 0) { throw new NegativeWeightCycleException(); } } printPath(path, 3, 2); return distance; } public void printPath(int[][] path, int start, int end) { if(start < 0 || end < 0 || start >= path.length || end >= path.length) { throw new IllegalArgumentException(); } System.out.println("Actual path - between " + start + " " + end); Deque stack = new LinkedList<>(); stack.addFirst(end); while (true) { end = path[start][end]; if(end == -1) { return; } stack.addFirst(end); if(end == start) { break; } } while (!stack.isEmpty()) { System.out.print(stack.pollFirst() + " "); } System.out.println(); } public static void main(String args[]){ int[][] graph = { {0, 3, 6, 15}, {INF, 0, -2, INF}, {INF, INF, 0, 2}, {1, INF, INF, 0} }; FloydWarshallAllPairShortestPath shortestPath = new FloydWarshallAllPairShortestPath(); int[][] distance = shortestPath.allPairShortestPath(graph); System.out.println("Minimum Distance matrix"); for(int i=0; i < distance.length; i++){ for(int j=0; j < distance.length; j++){ System.out.print(distance[i][j] + " "); } System.out.println(""); } } } ================================================ FILE: src/com/interview/graph/FordFulkerson.java ================================================ package com.interview.graph; import java.util.*; /** * Date 04/14/2014 * @author Tushar Roy * * Ford fulkerson method Edmonds Karp algorithm for finding max flow * * Capacity - Capacity of an edge to carry units from source to destination vertex * Flow - Actual flow of units from source to destination vertex of an edge * Residual capacity - Remaining capacity on this edge i.e capacity - flow * AugmentedPath - Path from source to sink which has residual capacity greater than 0 * * Time complexity is O(VE^2) * * References: * http://www.geeksforgeeks.org/ford-fulkerson-algorithm-for-maximum-flow-problem/ * https://en.wikipedia.org/wiki/Edmonds%E2%80%93Karp_algorithm */ public class FordFulkerson { public int maxFlow(int capacity[][], int source, int sink){ //declare and initialize residual capacity as total avaiable capacity initially. int residualCapacity[][] = new int[capacity.length][capacity[0].length]; for (int i = 0; i < capacity.length; i++) { for (int j = 0; j < capacity[0].length; j++) { residualCapacity[i][j] = capacity[i][j]; } } //this is parent map for storing BFS parent Map parent = new HashMap<>(); //stores all the augmented paths List> augmentedPaths = new ArrayList<>(); //max flow we can get in this network int maxFlow = 0; //see if augmented path can be found from source to sink. while(BFS(residualCapacity, parent, source, sink)){ List augmentedPath = new ArrayList<>(); int flow = Integer.MAX_VALUE; //find minimum residual capacity in augmented path //also add vertices to augmented path list int v = sink; while(v != source){ augmentedPath.add(v); int u = parent.get(v); if (flow > residualCapacity[u][v]) { flow = residualCapacity[u][v]; } v = u; } augmentedPath.add(source); Collections.reverse(augmentedPath); augmentedPaths.add(augmentedPath); //add min capacity to max flow maxFlow += flow; //decrease residual capacity by min capacity from u to v in augmented path // and increase residual capacity by min capacity from v to u v = sink; while(v != source){ int u = parent.get(v); residualCapacity[u][v] -= flow; residualCapacity[v][u] += flow; v = u; } } printAugmentedPaths(augmentedPaths); return maxFlow; } /** * Prints all the augmented path which contribute to max flow */ private void printAugmentedPaths(List> augmentedPaths) { System.out.println("Augmented paths"); augmentedPaths.forEach(path -> { path.forEach(i -> System.out.print(i + " ")); System.out.println(); }); } /** * Breadth first search to find augmented path */ private boolean BFS(int[][] residualCapacity, Map parent, int source, int sink){ Set visited = new HashSet<>(); Queue queue = new LinkedList<>(); queue.add(source); visited.add(source); boolean foundAugmentedPath = false; //see if we can find augmented path from source to sink while(!queue.isEmpty()){ int u = queue.poll(); for(int v = 0; v < residualCapacity.length; v++){ //explore the vertex only if it is not visited and its residual capacity is //greater than 0 if(!visited.contains(v) && residualCapacity[u][v] > 0){ //add in parent map saying v got explored by u parent.put(v, u); //add v to visited visited.add(v); //add v to queue for BFS queue.add(v); //if sink is found then augmented path is found if ( v == sink) { foundAugmentedPath = true; break; } } } } //returns if augmented path is found from source to sink or not return foundAugmentedPath; } public static void main(String args[]){ FordFulkerson ff = new FordFulkerson(); int[][] capacity = {{0, 3, 0, 3, 0, 0, 0}, {0, 0, 4, 0, 0, 0, 0}, {3, 0, 0, 1, 2, 0, 0}, {0, 0, 0, 0, 2, 6, 0}, {0, 1, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 9}, {0, 0, 0, 0, 0, 0, 0}}; System.out.println("\nMaximum capacity " + ff.maxFlow(capacity, 0, 6)); } } ================================================ FILE: src/com/interview/graph/Graph.java ================================================ package com.interview.graph; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; public class Graph{ private List> allEdges; private Map> allVertex; boolean isDirected = false; public Graph(boolean isDirected){ allEdges = new ArrayList>(); allVertex = new HashMap>(); this.isDirected = isDirected; } public void addEdge(long id1, long id2){ addEdge(id1,id2,0); } //This works only for directed graph because for undirected graph we can end up //adding edges two times to allEdges public void addVertex(Vertex vertex){ if(allVertex.containsKey(vertex.getId())){ return; } allVertex.put(vertex.getId(), vertex); for(Edge edge : vertex.getEdges()){ allEdges.add(edge); } } public Vertex addSingleVertex(long id){ if(allVertex.containsKey(id)){ return allVertex.get(id); } Vertex v = new Vertex(id); allVertex.put(id, v); return v; } public Vertex getVertex(long id){ return allVertex.get(id); } public void addEdge(long id1,long id2, int weight){ Vertex vertex1 = null; if(allVertex.containsKey(id1)){ vertex1 = allVertex.get(id1); }else{ vertex1 = new Vertex(id1); allVertex.put(id1, vertex1); } Vertex vertex2 = null; if(allVertex.containsKey(id2)){ vertex2 = allVertex.get(id2); }else{ vertex2 = new Vertex(id2); allVertex.put(id2, vertex2); } Edge edge = new Edge(vertex1,vertex2,isDirected,weight); allEdges.add(edge); vertex1.addAdjacentVertex(edge, vertex2); if(!isDirected){ vertex2.addAdjacentVertex(edge, vertex1); } } public List> getAllEdges(){ return allEdges; } public Collection> getAllVertex(){ return allVertex.values(); } public void setDataForVertex(long id, T data){ if(allVertex.containsKey(id)){ Vertex vertex = allVertex.get(id); vertex.setData(data); } } @Override public String toString(){ StringBuffer buffer = new StringBuffer(); for(Edge edge : getAllEdges()){ buffer.append(edge.getVertex1() + " " + edge.getVertex2() + " " + edge.getWeight()); buffer.append("\n"); } return buffer.toString(); } } class Vertex { long id; private T data; private List> edges = new ArrayList<>(); private List> adjacentVertex = new ArrayList<>(); Vertex(long id){ this.id = id; } public long getId(){ return id; } public void setData(T data){ this.data = data; } public T getData(){ return data; } public void addAdjacentVertex(Edge e, Vertex v){ edges.add(e); adjacentVertex.add(v); } public String toString(){ return String.valueOf(id); } public List> getAdjacentVertexes(){ return adjacentVertex; } public List> getEdges(){ return edges; } public int getDegree(){ return edges.size(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (int) (id ^ (id >>> 32)); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Vertex other = (Vertex) obj; if (id != other.id) return false; return true; } } class Edge{ private boolean isDirected = false; private Vertex vertex1; private Vertex vertex2; private int weight; Edge(Vertex vertex1, Vertex vertex2){ this.vertex1 = vertex1; this.vertex2 = vertex2; } Edge(Vertex vertex1, Vertex vertex2,boolean isDirected,int weight){ this.vertex1 = vertex1; this.vertex2 = vertex2; this.weight = weight; this.isDirected = isDirected; } Edge(Vertex vertex1, Vertex vertex2,boolean isDirected){ this.vertex1 = vertex1; this.vertex2 = vertex2; this.isDirected = isDirected; } Vertex getVertex1(){ return vertex1; } Vertex getVertex2(){ return vertex2; } int getWeight(){ return weight; } public boolean isDirected(){ return isDirected; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((vertex1 == null) ? 0 : vertex1.hashCode()); result = prime * result + ((vertex2 == null) ? 0 : vertex2.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Edge other = (Edge) obj; if (vertex1 == null) { if (other.vertex1 != null) return false; } else if (!vertex1.equals(other.vertex1)) return false; if (vertex2 == null) { if (other.vertex2 != null) return false; } else if (!vertex2.equals(other.vertex2)) return false; return true; } @Override public String toString() { return "Edge [isDirected=" + isDirected + ", vertex1=" + vertex1 + ", vertex2=" + vertex2 + ", weight=" + weight + "]"; } } ================================================ FILE: src/com/interview/graph/GraphColoring.java ================================================ package com.interview.graph; import java.util.Collection; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; /** http://www.geeksforgeeks.org/graph-coloring-set-2-greedy-algorithm/ */ public class GraphColoring { public void WelshPowell(){ Graph graph = new Graph(false); graph.addEdge(1, 2); graph.addEdge(2, 3); graph.addEdge(1, 4); graph.addEdge(4, 6); graph.addEdge(1, 7); graph.addEdge(1, 8); graph.addEdge(2, 9); graph.addEdge(1, 3); graph.addEdge(3, 4); graph.addEdge(2,4); graph.addEdge(3, 7); graph.addEdge(2, 7); ComparatorVertex c = new ComparatorVertex(); Set> sortedSet = new TreeSet>(c); for(Vertex v : graph.getAllVertex()){ sortedSet.add(v); } Map assignedColor = new HashMap(); Map finalAssignedColor = new HashMap(); Map colorsUsed = new TreeMap(); colorsUsed.put("Green", false); colorsUsed.put("Blue", false); colorsUsed.put("Red", false); colorsUsed.put("Yellow", false); colorsUsed.put("Orange",false); Set> removeSet = new HashSet>(); while(sortedSet.size() != removeSet.size()){ String color = null ; for(Vertex v : sortedSet){ if(removeSet.contains(v)){ continue; } boolean allUncolored = allAdjacentUnColored(v.getAdjacentVertexes(),assignedColor); if(allUncolored){ color = getUnusedColor(colorsUsed); assignedColor.put(v.getId(), color); removeSet.add(v); finalAssignedColor.put(v.getId(), color); } } colorsUsed.remove(color); assignedColor.clear(); } System.out.println(finalAssignedColor); } public void colorGraph(){ Graph graph = new Graph(false); graph.addEdge(1, 2); graph.addEdge(2, 3); graph.addEdge(1, 4); graph.addEdge(4, 6); graph.addEdge(1, 7); graph.addEdge(1, 8); graph.addEdge(2, 9); graph.addEdge(1, 3); graph.addEdge(3, 4); graph.addEdge(2,4); graph.addEdge(3,7); Map colorsUsed = new HashMap(); colorsUsed.put("Green", false); colorsUsed.put("Blue", false); colorsUsed.put("Red", false); colorsUsed.put("Yellow", false); Map colorsAssigned = new HashMap(); Collection> allVertex = graph.getAllVertex(); for(Vertex v : allVertex){ List> adjacentVertexes = v.getAdjacentVertexes(); for(Vertex adjacentVertex : adjacentVertexes){ String color = colorsAssigned.get(adjacentVertex.getId()); if(color != null){ assignColor(color,colorsUsed); } } String color = getUnusedColor(colorsUsed); colorsAssigned.put(v.getId(), color); resetColor(colorsUsed); } System.out.println(colorsAssigned); } private String getUnusedColor(Map colorsUsed){ for(String color : colorsUsed.keySet()){ if(colorsUsed.get(color).equals(false)){ return color; } } throw new RuntimeException(); } private void resetColor(Map colorsUsed){ Set colors = new HashSet(); for(String color : colorsUsed.keySet()){ colors.add(color); } for(String color : colors){ colorsUsed.remove(color); colorsUsed.put(color, false); } } private void assignColor(String color, Map colorsUsed){ colorsUsed.remove(color); colorsUsed.put(color, true); } private boolean allAdjacentUnColored(Collection> vertexes, Map colorsAssigned){ for(Vertex vertex : vertexes){ if(colorsAssigned.containsKey(vertex.getId())){ return false; } } return true; } public static void main(String args[]){ GraphColoring graphColoring = new GraphColoring(); graphColoring.WelshPowell(); } } class ComparatorVertex implements Comparator>{ @Override public int compare(Vertex o1, Vertex o2) { if(o1.getDegree() <= o2.getDegree()){ return 1; }else{ return -1; } } } ================================================ FILE: src/com/interview/graph/GraphTraversal.java ================================================ package com.interview.graph; import java.util.HashSet; import java.util.LinkedList; import java.util.Queue; import java.util.Set; /** * http://www.geeksforgeeks.org/breadth-first-traversal-for-a-graph/ * http://www.geeksforgeeks.org/depth-first-traversal-for-a-graph/ */ public class GraphTraversal { public void DFS(Graph graph){ Set visited = new HashSet(); for(Vertex vertex : graph.getAllVertex()){ if(!visited.contains(vertex.getId())){ DFSUtil(vertex,visited); } } } private void DFSUtil(Vertex v,Set visited){ visited.add(v.getId()); System.out.print(v.getId() + " "); for(Vertex vertex : v.getAdjacentVertexes()){ if(!visited.contains(vertex.getId())) DFSUtil(vertex,visited); } } public void BFS(Graph graph){ Set visited = new HashSet(); Queue> q = new LinkedList>(); for(Vertex vertex: graph.getAllVertex()){ if(!visited.contains(vertex.getId())){ q.add(vertex); visited.add(vertex.getId()); while(q.size() != 0){ Vertex vq = q.poll(); System.out.print(vq.getId()+ " "); for(Vertex v : vq.getAdjacentVertexes()){ if(!visited.contains(v.getId())){ q.add(v); visited.add(v.getId()); } } } } } } public static void main(String args[]){ Graph graph = new Graph(true); graph.addEdge(1, 2); graph.addEdge(1, 3); graph.addEdge(2, 4); graph.addEdge(3, 4); graph.addEdge(4, 6); graph.addEdge(6, 5); // graph.addEdge(5, 1); graph.addEdge(5,3); GraphTraversal g = new GraphTraversal(); g.BFS(graph); } } ================================================ FILE: src/com/interview/graph/HamiltonianCycle.java ================================================ package com.interview.graph; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; public class HamiltonianCycle { public boolean getHamiltonianCycle(Graph graph,List> result){ Vertex startVertex = graph.getAllVertex().iterator().next(); Set> visited = new HashSet>(); return hamiltonianUtil(startVertex,startVertex,result,visited,graph.getAllVertex().size()); } private boolean hamiltonianUtil(Vertex startVertex, Vertex currentVertex , List> result, Set> visited, int totalVertex){ visited.add(currentVertex); result.add(currentVertex); for(Vertex child : currentVertex.getAdjacentVertexes()){ if(startVertex.equals(child) && totalVertex == result.size()){ result.add(startVertex); return true; } if(!visited.contains(child)){ boolean isHamil = hamiltonianUtil(startVertex,child,result,visited,totalVertex); if(isHamil){ return true; } } } result.remove(result.size()-1); visited.remove(currentVertex); return false; } public static void main(String args[]){ Graph graph = new Graph(false); graph.addEdge(1, 2); graph.addEdge(2, 3); graph.addEdge(3, 5); graph.addEdge(5, 2); graph.addEdge(2, 4); graph.addEdge(4, 1); graph.addEdge(4, 5); HamiltonianCycle hamil = new HamiltonianCycle(); List> result = new ArrayList>(); boolean isHamiltonian = hamil.getHamiltonianCycle(graph, result); System.out.println(isHamiltonian); if(isHamiltonian){ System.out.print(result); } } } ================================================ FILE: src/com/interview/graph/KruskalMST.java ================================================ package com.interview.graph; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * Date 09/25/2014 * * @author Tushar Roy *

* Find minimum spanning tree usinig Kruskals algorithm *

* Time complexity - O(ElogE) * Space complexity - O(E + V) *

* References * https://en.wikipedia.org/wiki/Kruskal%27s_algorithm */ public class KruskalMST { /** * Comparator to sort edges by weight in non decreasing order */ public class EdgeComparator implements Comparator> { @Override public int compare(Edge edge1, Edge edge2) { if (edge1.getWeight() <= edge2.getWeight()) { return -1; } else { return 1; } } } public List> getMST(Graph graph) { List> allEdges = graph.getAllEdges(); EdgeComparator edgeComparator = new EdgeComparator(); //sort all edges in non decreasing order Collections.sort(allEdges, edgeComparator); DisjointSet disjointSet = new DisjointSet(); //create as many disjoint sets as the total vertices for (Vertex vertex : graph.getAllVertex()) { disjointSet.makeSet(vertex.getId()); } List> resultEdge = new ArrayList>(); for (Edge edge : allEdges) { //get the sets of two vertices of the edge long root1 = disjointSet.findSet(edge.getVertex1().getId()); long root2 = disjointSet.findSet(edge.getVertex2().getId()); //check if the vertices are in same set or different set //if verties are in same set then ignore the edge if (root1 == root2) { continue; } else { //if vertices are in different set then add the edge to result and union these two sets into one resultEdge.add(edge); disjointSet.union(edge.getVertex1().getId(), edge.getVertex2().getId()); } } return resultEdge; } public static void main(String args[]) { Graph graph = new Graph(false); graph.addEdge(1, 2, 4); graph.addEdge(1, 3, 1); graph.addEdge(2, 5, 1); graph.addEdge(2, 6, 3); graph.addEdge(2, 4, 2); graph.addEdge(6, 5, 2); graph.addEdge(6, 4, 3); graph.addEdge(4, 7, 2); graph.addEdge(3, 4, 5); graph.addEdge(3, 7, 8); KruskalMST mst = new KruskalMST(); List> result = mst.getMST(graph); for (Edge edge : result) { System.out.println(edge.getVertex1() + " " + edge.getVertex2()); } } } ================================================ FILE: src/com/interview/graph/MaximumBiparteMatching.java ================================================ package com.interview.graph; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * http://www.geeksforgeeks.org/maximum-bipartite-matching/ */ public class MaximumBiparteMatching { public int findMaxMatching(Map> jobApplications, List allJobs){ Map match = new HashMap(); int maxMatch = 0; for(Integer candidate : jobApplications.keySet()){ Set jobsSeen = new HashSet(); maxMatch += matchJobs(candidate, jobApplications, match, jobsSeen) ==true ? 1 : 0; } return maxMatch; } private boolean matchJobs(Integer candidate, Map> jobApplications,Map match,Set jobsSeen){ for(int job : jobApplications.get(candidate)){ if(jobsSeen.contains(job)){ continue; } jobsSeen.add(job); if(match.get(job) == null){ match.put(job, candidate); return true; } boolean flag = matchJobs(match.get(job),jobApplications,match,jobsSeen); if(flag){ match.put(job, candidate); return true; } } return false; } public static void main(String args[]){ List app0 = new ArrayList(); app0.add(10); app0.add(11); app0.add(13); List app1 = new ArrayList(); app1.add(10); List app2 = new ArrayList(); app2.add(12); List app3 = new ArrayList(); app3.add(12); app3.add(10); app3.add(11); Map> jobApplications = new HashMap>(); jobApplications.put(0, app0); jobApplications.put(1, app1); jobApplications.put(2, app2); jobApplications.put(3, app3); MaximumBiparteMatching mbm = new MaximumBiparteMatching(); List allJobs = new ArrayList(); allJobs.add(10); allJobs.add(11); allJobs.add(12); allJobs.add(13); System.out.print(mbm.findMaxMatching(jobApplications, allJobs)); } } ================================================ FILE: src/com/interview/graph/MinimumHeightTree.java ================================================ package com.interview.graph; import java.util.*; /** * Date 03/08/2016 * @author Tushar Roy * * Given a graph representing a tree. Find all minimum height trees. * * Time complexity O(n) * Space complexity O(n) * * https://leetcode.com/problems/minimum-height-trees/ */ public class MinimumHeightTree { public List findMinHeightTrees(int n, int[][] edges) { if (n == 1) { return Collections.singletonList(0); } List> adj = new ArrayList<>(); for (int i = 0; i < n; i++) { adj.add(new HashSet<>()); } for (int[] edge: edges) { adj.get(edge[0]).add(edge[1]); adj.get(edge[1]).add(edge[0]); } List leaves = new ArrayList<>(); for (int i = 0; i < n; i++) { if (adj.get(i).size() == 1) { leaves.add(i); } } while (n > 2) { n -= leaves.size(); List newLeaves = new ArrayList<>(); for (int leaf : leaves) { int node = adj.get(leaf).iterator().next(); adj.get(node).remove(leaf); if (adj.get(node).size() == 1) { newLeaves.add(node); } } leaves = newLeaves; } return leaves; } public static void main(String args[]) { MinimumHeightTree mht = new MinimumHeightTree(); int input[][] = {{1,0},{1,2},{1,3}}; List result = mht.findMinHeightTrees(4, input); result.forEach(r -> System.out.print(r + " ")); } } ================================================ FILE: src/com/interview/graph/NumberOfIsland.java ================================================ package com.interview.graph; /** http://www.geeksforgeeks.org/find-number-of-islands/ */ public class NumberOfIsland { public int numberOfIsland(int[][] graph){ boolean[][] visited = new boolean[graph.length][graph.length]; int count = 0; for(int i=0; i < graph.length ; i ++){ for(int j =0 ; j < graph[i].length ; j++){ if(visited[i][j] == false && graph[i][j] == 1) { count++; DFS(graph,visited,i,j); } } } return count; } private void DFS(int[][] graph, boolean[][] visited,int i,int j){ if(i <0 || j < 0 || i == graph.length || j == graph[i].length) { return; } visited[i][j] = true; if(graph[i][j] == 0){ return; } DFS(graph,visited,i,j+1); DFS(graph,visited,i+1,j); DFS(graph,visited,i+1,j+1); DFS(graph,visited,i-1, j+1); } public static void main(String args[]){ int matrix[][] = {{1,1,0,1,0}, {1,0,0,1,1}, {0,0,0,0,0}, {1,0,1,0,1}, {1,0,0,0,0} }; NumberOfIsland island = new NumberOfIsland(); int count = island.numberOfIsland(matrix); System.out.println(count); } } ================================================ FILE: src/com/interview/graph/NumberOfIslandDynamic.java ================================================ package com.interview.graph; import java.util.*; /** * A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand operation * which turns the water at position (row, col) into a land. Given a list of positions to operate, * count the number of islands after each addLand operation. An island is surrounded by water and is formed by * connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all * surrounded by water. * https://leetcode.com/problems/number-of-islands-ii/ */ public class NumberOfIslandDynamic { public List numIslands2(int n, int m, int[][] positions) { if (positions.length == 0 || positions[0].length == 0) { return Collections.emptyList(); } int count = 0; DisjointSet ds = new DisjointSet(); Set land = new HashSet<>(); List result = new ArrayList<>(); for (int[] position : positions) { int index = position[0]*m + position[1]; land.add(index); ds.makeSet(index); count++; //find the four neighbors; int n1 = (position[0] - 1)*m + position[1]; int n2 = (position[0] + 1)*m + position[1]; int n3 = (position[0])*m + position[1] + 1; int n4 = (position[0])*m + position[1] - 1; if (position[0] - 1 >= 0 && land.contains(n1)) { if (ds.union(index, n1)) { count--; } } if (position[0] + 1 < n && land.contains(n2)) { if (ds.union(index, n2)) { count--; } } if (position[1] + 1 < m && land.contains(n3)) { if (ds.union(index, n3)) { count--; } } if (position[1] - 1 >= 0 && land.contains(n4)) { if (ds.union(index, n4)) { count--; } } result.add(count); } return result; } public static void main(String args[]) { NumberOfIslandDynamic nd = new NumberOfIslandDynamic(); int[][] input = {{0, 1}, {1, 2}, {2, 1}, {1, 0}, {0, 2}, {0, 0}, {1, 1}}; System.out.print(nd.numIslands2(3, 3, input)); } } ================================================ FILE: src/com/interview/graph/NumberofTriangles.java ================================================ package com.interview.graph; import java.util.HashMap; import java.util.Map; /** * http://www.careercup.com/question?id=5988741646647296 * Given an undirected graph find number of triangles in this graph * Find cycle of length 3. Pass parent in DFS search. * If there is a cycle check if my parent is neighbor of the the node * which caused it to be a cycle. */ public class NumberofTriangles { public int countTriangles(Graph graph){ Map,Boolean> visited = new HashMap,Boolean>(); int count =0; for(Vertex vertex : graph.getAllVertex()){ count += DFS(vertex,visited,null); } return count; } public int DFS(Vertex vertex, Map,Boolean> visited,Vertex parent){ if(visited.containsKey(vertex)){ return 0; } visited.put(vertex, true); int count = 0; for(Vertex child : vertex.getAdjacentVertexes()){ if(child.equals(parent)){ continue; } if(visited.containsKey(child)){ count += isNeighbor(child, parent) ? 1: 0; }else{ count += DFS(child, visited, vertex); } } return count; } private boolean isNeighbor(Vertex vertex, Vertex destVertex){ for(Vertex child : vertex.getAdjacentVertexes()){ if(child.equals(destVertex)){ return true; } } return false; } public static void main(String args[]){ Graph graph = new Graph(false); graph.addEdge(0, 1); graph.addEdge(0, 2); graph.addEdge(1, 2); graph.addEdge(2, 3); graph.addEdge(1, 3); graph.addEdge(3, 4); graph.addEdge(0, 4); graph.addEdge(0,3); NumberofTriangles not = new NumberofTriangles(); System.out.println(not.countTriangles(graph)); } } ================================================ FILE: src/com/interview/graph/PrimMST.java ================================================ package com.interview.graph; import java.util.*; /** * Date 10/11/2014 * @author Tushar Roy * * Find minimum spanning tree using Prim's algorithm * * Space complexity - O(E + V) * Time complexity - O(ElogV) * * References * https://en.wikipedia.org/wiki/Prim%27s_algorithm * CLRS book */ public class PrimMST { /** * Main method of Prim's algorithm. */ public List> primMST(Graph graph){ //binary heap + map data structure BinaryMinHeap> minHeap = new BinaryMinHeap<>(); //map of vertex to edge which gave minimum weight to this vertex. Map,Edge> vertexToEdge = new HashMap<>(); //stores final result List> result = new ArrayList<>(); //insert all vertices with infinite value initially. for(Vertex v : graph.getAllVertex()){ minHeap.add(Integer.MAX_VALUE, v); } //start from any random vertex Vertex startVertex = graph.getAllVertex().iterator().next(); //for the start vertex decrease the value in heap + map to 0 minHeap.decrease(startVertex, 0); //iterate till heap + map has elements in it while(!minHeap.empty()){ //extract min value vertex from heap + map Vertex current = minHeap.extractMin(); //get the corresponding edge for this vertex if present and add it to final result. //This edge wont be present for first vertex. Edge spanningTreeEdge = vertexToEdge.get(current); if(spanningTreeEdge != null) { result.add(spanningTreeEdge); } //iterate through all the adjacent vertices for(Edge edge : current.getEdges()){ Vertex adjacent = getVertexForEdge(current, edge); //check if adjacent vertex exist in heap + map and weight attached with this vertex is greater than this edge weight if(minHeap.containsData(adjacent) && minHeap.getWeight(adjacent) > edge.getWeight()){ //decrease the value of adjacent vertex to this edge weight. minHeap.decrease(adjacent, edge.getWeight()); //add vertex->edge mapping in the graph. vertexToEdge.put(adjacent, edge); } } } return result; } private Vertex getVertexForEdge(Vertex v, Edge e){ return e.getVertex1().equals(v) ? e.getVertex2() : e.getVertex1(); } public static void main(String args[]){ Graph graph = new Graph<>(false); /* graph.addEdge(0, 1, 4); graph.addEdge(1, 2, 8); graph.addEdge(2, 3, 7); graph.addEdge(3, 4, 9); graph.addEdge(4, 5, 10); graph.addEdge(2, 5, 4); graph.addEdge(1, 7, 11); graph.addEdge(0, 7, 8); graph.addEdge(2, 8, 2); graph.addEdge(3, 5, 14); graph.addEdge(5, 6, 2); graph.addEdge(6, 8, 6); graph.addEdge(6, 7, 1); graph.addEdge(7, 8, 7);*/ graph.addEdge(1, 2, 3); graph.addEdge(2, 3, 1); graph.addEdge(3, 1, 1); graph.addEdge(1, 4, 1); graph.addEdge(2, 4, 3); graph.addEdge(4, 5, 6); graph.addEdge(5, 6, 2); graph.addEdge(3, 5, 5); graph.addEdge(3, 6, 4); PrimMST prims = new PrimMST(); Collection> edges = prims.primMST(graph); for(Edge edge : edges){ System.out.println(edge); } } } ================================================ FILE: src/com/interview/graph/PrintAllPathFromSourceToDestination.java ================================================ package com.interview.graph; import java.util.LinkedHashSet; import java.util.Set; /** * http://www.careercup.com/question?id=5922416572235776 * Test case * Source or destination vertex does not exist in the graph * There is no path between src to dest vertex */ public class PrintAllPathFromSourceToDestination { public void printPath(Graph graph,Vertex start, Vertex destination){ Set> visited = new LinkedHashSet>(); printPath(visited,destination,start); } private void printPath(Set> visited,Vertex destination,Vertex current){ if(visited.contains(current)){ return; } if(destination.equals(current)){ for(Vertex v : visited){ System.out.print(v.id + " "); } System.out.println(destination.id); return; } visited.add(current); for(Vertex child : current.getAdjacentVertexes()){ printPath(visited,destination,child); } visited.remove(current); } public static void main(String args[]){ Graph graph = new Graph(false); graph.addEdge(1, 2); graph.addEdge(1, 3); graph.addEdge(2, 4); graph.addEdge(2, 5); graph.addEdge(3, 6); graph.addEdge(5, 6); graph.addEdge(5, 7); graph.addEdge(6, 7); graph.addEdge(4, 7); graph.addEdge(1, 8); graph.addEdge(8, 9); graph.addEdge(9, 1); Vertex start = graph.getVertex(1); Vertex dest = graph.getVertex(7); PrintAllPathFromSourceToDestination pap = new PrintAllPathFromSourceToDestination(); pap.printPath(graph, start, dest); } } ================================================ FILE: src/com/interview/graph/ShortestDistanceFromExit.java ================================================ package com.interview.graph; import java.util.LinkedList; import java.util.Queue; enum Cell{ SPACE, BLOCK, GUARD } class Point{ int x; int y; Point(int x, int y){ this.x = x; this.y = y; } } /** * @Date 07/05/2015 * @author Tushar Roy * * Given a 2 D floor plan with empty space, block and multiple exits. Find distance of every empty space * from nearest exits in case of fire emergency. * * Idea is to start from every exit position and do BFS search in all 4 directions and maintain the distance of every * space from exit. If another exit in future iterator is closer than already calculated exit then update * the distance. * * Space complexity is O(n*m) * Time complexity is O(number of exit * m * n); * */ public class ShortestDistanceFromExit { public int[][] findShortest(Cell input[][]){ int distance[][] = new int[input.length][input[0].length]; for(int i=0; i < input.length; i++){ for(int j=0; j < input[0].length; j++){ distance[i][j] = Integer.MAX_VALUE; } } for(int i=0; i < input.length; i++){ for(int j =0; j < input[i].length; j++){ //for every exit location do a BFS starting with this exit as the origin if(input[i][j] == Cell.GUARD){ distance[i][j] = 0; setDistance(input, i, j, distance); } } } return distance; } private void setDistance(Cell input[][], int x, int y, int distance[][]){ boolean visited[][] = new boolean[input.length][input[0].length]; Queue q = new LinkedList<>(); q.offer(new Point(x,y)); //Do a BFS at keep updating distance. while(!q.isEmpty()){ Point p = q.poll(); setDistanceUtil(q, input, p, getNeighbor(input, p.x+1, p.y), distance, visited); setDistanceUtil(q, input, p, getNeighbor(input, p.x, p.y+1), distance, visited); setDistanceUtil(q, input, p, getNeighbor(input, p.x-1, p.y), distance, visited); setDistanceUtil(q, input, p, getNeighbor(input, p.x, p.y-1), distance, visited); } } private void setDistanceUtil(Queue q, Cell input[][], Point p, Point newPoint, int distance[][], boolean visited[][]){ if(newPoint != null && !visited[newPoint.x][newPoint.y]){ if(input[newPoint.x][newPoint.y] != Cell.GUARD && input[newPoint.x][newPoint.y] != Cell.BLOCK){ distance[newPoint.x][newPoint.y] = Math.min(distance[newPoint.x][newPoint.y], 1 + distance[p.x][p.y]); visited[newPoint.x][newPoint.y] = true; q.offer(newPoint); } } } private Point getNeighbor(Cell input[][], int x, int y){ if(x < 0 || x >= input.length || y < 0 || y >= input[0].length ) { return null; } return new Point(x,y); } public static void main(String args[]){ ShortestDistanceFromExit sdg = new ShortestDistanceFromExit(); Cell input[][] = {{Cell.SPACE, Cell.SPACE, Cell.BLOCK, Cell.BLOCK}, {Cell.SPACE, Cell.SPACE, Cell.GUARD, Cell.SPACE}, {Cell.SPACE, Cell.SPACE, Cell.BLOCK, Cell.SPACE}, {Cell.SPACE, Cell.GUARD, Cell.BLOCK, Cell.SPACE} }; int result[][] = sdg.findShortest(input); for(int i=0; i < result.length; i++) { for(int j=0; j < result[0].length; j++){ System.out.print(result[i][j] + " "); } System.out.println(); } } } ================================================ FILE: src/com/interview/graph/StronglyConnectedComponent.java ================================================ package com.interview.graph; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Date 10/01/2014 * @author Tushar Roy * * Given a directed graph, find all strongly connected components in this graph. * We are going to use Kosaraju's algorithm to find strongly connected component. * * Algorithm * Create a order of vertices by finish time in decreasing order. * Reverse the graph * Do a DFS on reverse graph by finish time of vertex and created strongly connected * components. * * Runtime complexity - O(V + E) * Space complexity - O(V) * * References * https://en.wikipedia.org/wiki/Strongly_connected_component * http://www.geeksforgeeks.org/strongly-connected-components/ */ public class StronglyConnectedComponent { public List>> scc(Graph graph) { //it holds vertices by finish time in reverse order. Deque> stack = new ArrayDeque<>(); //holds visited vertices for DFS. Set> visited = new HashSet<>(); //populate stack with vertices with vertex finishing last at the top. for (Vertex vertex : graph.getAllVertex()) { if (visited.contains(vertex)) { continue; } DFSUtil(vertex, visited, stack); } //reverse the graph. Graph reverseGraph = reverseGraph(graph); //Do a DFS based off vertex finish time in decreasing order on reverse graph.. visited.clear(); List>> result = new ArrayList<>(); while (!stack.isEmpty()) { Vertex vertex = reverseGraph.getVertex(stack.poll().getId()); if(visited.contains(vertex)){ continue; } Set> set = new HashSet<>(); DFSUtilForReverseGraph(vertex, visited, set); result.add(set); } return result; } private Graph reverseGraph(Graph graph) { Graph reverseGraph = new Graph<>(true); for (Edge edge : graph.getAllEdges()) { reverseGraph.addEdge(edge.getVertex2().getId(), edge.getVertex1() .getId(), edge.getWeight()); } return reverseGraph; } private void DFSUtil(Vertex vertex, Set> visited, Deque> stack) { visited.add(vertex); for (Vertex v : vertex.getAdjacentVertexes()) { if (visited.contains(v)) { continue; } DFSUtil(v, visited, stack); } stack.offerFirst(vertex); } private void DFSUtilForReverseGraph(Vertex vertex, Set> visited, Set> set) { visited.add(vertex); set.add(vertex); for (Vertex v : vertex.getAdjacentVertexes()) { if (visited.contains(v)) { continue; } DFSUtilForReverseGraph(v, visited, set); } } public static void main(String args[]){ Graph graph = new Graph<>(true); graph.addEdge(0, 1); graph.addEdge(1, 2); graph.addEdge(2, 0); graph.addEdge(1, 3); graph.addEdge(3, 4); graph.addEdge(4, 5); graph.addEdge(5, 3); graph.addEdge(5, 6); StronglyConnectedComponent scc = new StronglyConnectedComponent(); List>> result = scc.scc(graph); //print the result result.forEach(set -> { set.forEach(v -> System.out.print(v.getId() + " ")); System.out.println(); }); } } ================================================ FILE: src/com/interview/graph/TarjanStronglyConnectedComponent.java ================================================ package com.interview.graph; import java.util.*; /** * Date 08/16/2015 * @author Tushar Roy * * Find strongly connected components of directed graph. * * Time complexity is O(E + V) * Space complexity is O(V) * * Reference - https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm */ public class TarjanStronglyConnectedComponent { private Map, Integer> visitedTime; private Map, Integer> lowTime; private Set> onStack; private Deque> stack; private Set> visited; private List>> result; private int time; public List>> scc(Graph graph) { //keeps the time when every vertex is visited time = 0; //keeps map of vertex to time it was visited visitedTime = new HashMap<>(); //keeps map of vertex and time of first vertex visited in current DFS lowTime = new HashMap<>(); //tells if a vertex is in stack or not onStack = new HashSet<>(); //stack of visited vertices stack = new LinkedList<>(); //tells if vertex has ever been visited or not. This is for DFS purpose. visited = new HashSet<>(); //stores the strongly connected components result; result = new ArrayList<>(); //start from any vertex in the graph. for (Vertex vertex : graph.getAllVertex()) { if(visited.contains(vertex)) { continue; } sccUtil(vertex); } return result; } private void sccUtil(Vertex vertex) { visited.add(vertex); visitedTime.put(vertex, time); lowTime.put(vertex, time); time++; stack.addFirst(vertex); onStack.add(vertex); for (Vertex child : vertex.getAdjacentVertexes()) { //if child is not visited then visit it and see if it has link back to vertex's ancestor. In that case update //low time to ancestor's visit time if (!visited.contains(child)) { sccUtil(child); //sets lowTime[vertex] = min(lowTime[vertex], lowTime[child]); lowTime.compute(vertex, (v, low) -> Math.min(low, lowTime.get(child)) ); } //if child is on stack then see if it was visited before vertex's low time. If yes then update vertex's low time to that. else if (onStack.contains(child)) { //sets lowTime[vertex] = min(lowTime[vertex], visitedTime[child]); lowTime.compute(vertex, (v, low) -> Math.min(low, visitedTime.get(child)) ); } } //if vertex low time is same as visited time then this is start vertex for strongly connected component. //keep popping vertices out of stack still you find current vertex. They are all part of one strongly //connected component. if (visitedTime.get(vertex) == lowTime.get(vertex)) { Set> stronglyConnectedComponenet = new HashSet<>(); Vertex v; do { v = stack.pollFirst(); onStack.remove(v); stronglyConnectedComponenet.add(v); } while (!vertex.equals(v)); result.add(stronglyConnectedComponenet); } } public static void main(String args[]) { Graph graph = new Graph<>(true); graph.addEdge(1,2); graph.addEdge(2,3); graph.addEdge(3,1); graph.addEdge(3,4); graph.addEdge(4,5); graph.addEdge(5,6); graph.addEdge(6,4); graph.addEdge(7,6); graph.addEdge(7,8); graph.addEdge(8,7); TarjanStronglyConnectedComponent tarjanStronglyConnectedComponent = new TarjanStronglyConnectedComponent(); List>> result = tarjanStronglyConnectedComponent.scc(graph); result.forEach(scc -> { scc.forEach(vertex -> System.out.print(vertex + " ")); System.out.println(); }); } } ================================================ FILE: src/com/interview/graph/TopologicalSort.java ================================================ package com.interview.graph; import java.util.Set; import java.util.HashSet; import java.util.Deque; import java.util.ArrayDeque; /** * Date 08/20/2014 * @author Tushar Roy * * Given a directed acyclic graph, do a topological sort on this graph. * * Do DFS by keeping visited. Put the vertex which are completely explored into a stack. * Pop from stack to get sorted order. * * Space and time complexity is O(n). */ public class TopologicalSort { /** * Main method to be invoked to do topological sorting. */ public Deque> topSort(Graph graph) { Deque> stack = new ArrayDeque<>(); Set> visited = new HashSet<>(); for (Vertex vertex : graph.getAllVertex()) { if (visited.contains(vertex)) { continue; } topSortUtil(vertex,stack,visited); } return stack; } private void topSortUtil(Vertex vertex, Deque> stack, Set> visited) { visited.add(vertex); for(Vertex childVertex : vertex.getAdjacentVertexes()){ if(visited.contains(childVertex)){ continue; } topSortUtil(childVertex,stack,visited); } stack.offerFirst(vertex); } public static void main(String args[]){ Graph graph = new Graph<>(true); graph.addEdge(1, 3); graph.addEdge(1, 2); graph.addEdge(3, 4); graph.addEdge(5, 6); graph.addEdge(6, 3); graph.addEdge(3, 8); graph.addEdge(8, 11); TopologicalSort sort = new TopologicalSort(); Deque> result = sort.topSort(graph); while(!result.isEmpty()){ System.out.println(result.poll()); } } } ================================================ FILE: src/com/interview/graph/TransitiveClosure.java ================================================ package com.interview.graph; /** * http://www.geeksforgeeks.org/transitive-closure-of-a-graph/ */ public class TransitiveClosure { public boolean[][] getTransitiveClosure(int [][]graph){ int rows = graph.length; int cols = graph[0].length; boolean[][] result = new boolean[rows][cols]; for(int i = 0; i < graph.length; i++){ for(int j=0; j < graph.length; j++){ if(graph[i][j] != 100){ result[i][j] = true; } } } for(int i=0; i < rows; i++){ for(int j=0 ; j < rows; j++){ for(int k=0; k < rows; k++){ result[i][j] = result[i][j] || (result[i][k] && result[k][j]); } } } return result; } public static void main(String args[]){ TransitiveClosure closure = new TransitiveClosure(); int[][] graph = {{0,2,2,4,100},{100,0,100,1,100},{100,100,0,3,100},{100,100,3,0,2},{100,3,100,100,0}}; boolean result[][] = closure.getTransitiveClosure(graph); for(int i=0; i < result.length; i++){ for(int j=0; j < result.length; j++){ System.out.print(result[i][j] + " "); } System.out.println(); } } } ================================================ FILE: src/com/interview/graph/TravelingSalesmanHeldKarp.java ================================================ package com.interview.graph; import java.util.*; /** * Date 11/17/2015 * @author Tushar Roy * * Help Karp method of finding tour of traveling salesman. * * Time complexity - O(2^n * n^2) * Space complexity - O(2^n) * * https://en.wikipedia.org/wiki/Held%E2%80%93Karp_algorithm */ public class TravelingSalesmanHeldKarp { private static int INFINITY = 100000000; private static class Index { int currentVertex; Set vertexSet; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Index index = (Index) o; if (currentVertex != index.currentVertex) return false; return !(vertexSet != null ? !vertexSet.equals(index.vertexSet) : index.vertexSet != null); } @Override public int hashCode() { int result = currentVertex; result = 31 * result + (vertexSet != null ? vertexSet.hashCode() : 0); return result; } private static Index createIndex(int vertex, Set vertexSet) { Index i = new Index(); i.currentVertex = vertex; i.vertexSet = vertexSet; return i; } } private static class SetSizeComparator implements Comparator>{ @Override public int compare(Set o1, Set o2) { return o1.size() - o2.size(); } } public int minCost(int[][] distance) { //stores intermediate values in map Map minCostDP = new HashMap<>(); Map parent = new HashMap<>(); List> allSets = generateCombination(distance.length - 1); for(Set set : allSets) { for(int currentVertex = 1; currentVertex < distance.length; currentVertex++) { if(set.contains(currentVertex)) { continue; } Index index = Index.createIndex(currentVertex, set); int minCost = INFINITY; int minPrevVertex = 0; //to avoid ConcurrentModificationException copy set into another set while iterating Set copySet = new HashSet<>(set); for(int prevVertex : set) { int cost = distance[prevVertex][currentVertex] + getCost(copySet, prevVertex, minCostDP); if(cost < minCost) { minCost = cost; minPrevVertex = prevVertex; } } //this happens for empty subset if(set.size() == 0) { minCost = distance[0][currentVertex]; } minCostDP.put(index, minCost); parent.put(index, minPrevVertex); } } Set set = new HashSet<>(); for(int i=1; i < distance.length; i++) { set.add(i); } int min = Integer.MAX_VALUE; int prevVertex = -1; //to avoid ConcurrentModificationException copy set into another set while iterating Set copySet = new HashSet<>(set); for(int k : set) { int cost = distance[k][0] + getCost(copySet, k, minCostDP); if(cost < min) { min = cost; prevVertex = k; } } parent.put(Index.createIndex(0, set), prevVertex); printTour(parent, distance.length); return min; } private void printTour(Map parent, int totalVertices) { Set set = new HashSet<>(); for(int i=0; i < totalVertices; i++) { set.add(i); } Integer start = 0; Deque stack = new LinkedList<>(); while(true) { stack.push(start); set.remove(start); start = parent.get(Index.createIndex(start, set)); if(start == null) { break; } } StringJoiner joiner = new StringJoiner("->"); stack.forEach(v -> joiner.add(String.valueOf(v))); System.out.println("\nTSP tour"); System.out.println(joiner.toString()); } private int getCost(Set set, int prevVertex, Map minCostDP) { set.remove(prevVertex); Index index = Index.createIndex(prevVertex, set); int cost = minCostDP.get(index); set.add(prevVertex); return cost; } private List> generateCombination(int n) { int input[] = new int[n]; for(int i = 0; i < input.length; i++) { input[i] = i+1; } List> allSets = new ArrayList<>(); int result[] = new int[input.length]; generateCombination(input, 0, 0, allSets, result); Collections.sort(allSets, new SetSizeComparator()); return allSets; } private void generateCombination(int input[], int start, int pos, List> allSets, int result[]) { if(pos == input.length) { return; } Set set = createSet(result, pos); allSets.add(set); for(int i=start; i < input.length; i++) { result[pos] = input[i]; generateCombination(input, i+1, pos+1, allSets, result); } } private static Set createSet(int input[], int pos) { if(pos == 0) { return new HashSet<>(); } Set set = new HashSet<>(); for(int i = 0; i < pos; i++) { set.add(input[i]); } return set; } } ================================================ FILE: src/com/interview/graph/ValidTree.java ================================================ package com.interview.graph; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), * write a function to check whether these edges make up a valid tree. * https://leetcode.com/problems/graph-valid-tree/ */ public class ValidTree { public boolean validTree(int n, int[][] edges) { if (n <= 1) { return true; } Map> graph = new HashMap<>(); for (int[] edge : edges) { List neighbors = graph.get(edge[0]); if (neighbors == null) { neighbors = new ArrayList<>(); graph.put(edge[0], neighbors); } neighbors.add(edge[1]); neighbors = graph.get(edge[1]); if (neighbors == null) { neighbors = new ArrayList<>(); graph.put(edge[1], neighbors); } neighbors.add(edge[0]); } boolean[] visited = new boolean[n]; boolean hasCycle = isCycle(0, graph, -1, visited); if (hasCycle) { return false; } for (int i = 0; i < visited.length; i++) { if (!visited[i]) { return false; } } return true; } boolean isCycle(int vertex, Map> graph, int parent, boolean[] visited) { if (visited[vertex]) { return true; } visited[vertex] = true; if (graph.get(vertex) == null) { return false; } for (int i : graph.get(vertex)) { if (i == parent) { continue; } if (isCycle(i, graph, vertex, visited)) { return true; } } return false; } } ================================================ FILE: src/com/interview/graph/WallsAndGates.java ================================================ package com.interview.graph; import java.util.Deque; import java.util.LinkedList; /** * You are given a m x n 2D grid initialized with these three possible values. * -1 - A wall or an obstacle. * 0 - A gate. * INF - Infinity means an empty room. We use the value 231 - 1 = 2147483647 to represent INF as * you may assume that the distance to a gate is less than 2147483647. * * Fill each empty room with the distance to its nearest gate. If it is impossible to reach a gate, it should be filled with INF * * Time complexity O(n*m) * Space complexity O(n*m) * * https://leetcode.com/problems/walls-and-gates/ */ public class WallsAndGates { private static final int d[][] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; private static final int INF = Integer.MAX_VALUE; public void wallsAndGates(int[][] rooms) { Deque queue = new LinkedList<>(); gates(rooms, queue); while (!queue.isEmpty()) { Cell cell = queue.pollLast(); addNeighbors(rooms, cell.row, cell.col, queue); } } private void addNeighbors(int[][] rooms, int row, int col, Deque queue) { for (int[] d1 : d) { int r1 = row + d1[0]; int c1 = col + d1[1]; if (r1 < 0 || c1 < 0 || r1 >= rooms.length || c1 >= rooms[0].length || rooms[r1][c1] != INF) { continue; } rooms[r1][c1] = 1 + rooms[row][col]; queue.offerFirst(new Cell(r1, c1)); } } private void gates(int[][] rooms, Deque queue) { for (int i = 0; i < rooms.length; i++) { for (int j = 0; j < rooms[0].length; j++) { if (rooms[i][j] == 0) { queue.offerFirst(new Cell(i, j)); } } } } class Cell { int row; int col; Cell(int row, int col) { this.row = row; this.col = col; } } } ================================================ FILE: src/com/interview/graph/WordLadder.java ================================================ package com.interview.graph; import java.util.*; /** * Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that: * Only one letter can be changed at a time * Each intermediate word must exist in the word list * * Solution - * Since we have to find all paths we need care about below extra stuff on top of regular BFS * 1) Maintain parent of every word to recreate the path * 2) Maintain 2 visited. First is for level and once the entire level is done then move it to visited. * 3) Also since we are looking result from beginWord to endWord switch them initially and go from endWord towards beginWord. * * https://leetcode.com/problems/word-ladder-ii/ */ public class WordLadder { public List> findLadders(String beginWord, String endWord, Set wordList) { if (wordList == null || wordList.size() == 0) { return Collections.EMPTY_LIST; } String temp = endWord; endWord = beginWord; beginWord = temp; Map> parent = new HashMap<>(); Queue queue1 = new LinkedList<>(); Set visited = new HashSet<>(); Set levelVisited = new HashSet<>(); List> result = new ArrayList<>(); parent.put(beginWord, null); queue1.offer(beginWord); visited.add(beginWord); boolean foundDestination = false; while (!queue1.isEmpty()) { while (!queue1.isEmpty()) { String word = queue1.poll(); for (int i = 0; i < word.length(); i++) { char wordArray[] = word.toCharArray(); for (char ch = 'a'; ch <= 'z'; ch++) { wordArray[i] = ch; String newWord = new String(wordArray); if (!endWord.equals(newWord) && (!wordList.contains(newWord) || visited.contains(newWord))) { continue; } List parents = parent.get(newWord); if (parents == null) { parents = new ArrayList<>(); parent.put(newWord, parents); } parents.add(word); levelVisited.add(newWord); if (endWord.equals(newWord)) { foundDestination = true; break; } } } } if (foundDestination) { break; } for (String word : levelVisited) { queue1.offer(word); visited.add(word); } levelVisited.clear(); } if (!foundDestination) { return Collections.EMPTY_LIST; } else { setParent(parent, beginWord, new ArrayList<>(), endWord, result); } return result; } private void setParent(Map> parent, String startWord, List path, String currentWord, List> result) { path.add(currentWord); if (startWord.equals(currentWord)) { result.add(new ArrayList<>(path)); path.remove(path.size() - 1); return; } for (String p : parent.get(currentWord)) { setParent(parent, startWord, path, p, result); } path.remove(path.size() - 1); } public static void main(String args[]) { String[] wordList = {"hot","dot","dog","lot","log"}; Set wordSet = new HashSet<>(); wordSet.addAll(Arrays.asList(wordList)); WordLadder wl = new WordLadder(); List> result = wl.findLadders("hit", "cog", wordSet); System.out.print(result); } } ================================================ FILE: src/com/interview/linklist/AddNumberRepresentedByLinkList.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/sum-of-two-linked-lists/ * Test case * Either of list is null * Size of list1 is greater, equal or smaller than list2 * Add with carry in main * Add with carry in remaining */ public class AddNumberRepresentedByLinkList { private int carry = 0; private Node addWithCarry(Node head1, Node head2){ if(head1 == null){ return null; } Node result = Node.newNode(0); result.next = addWithCarry(head1.next, head2.next); int r = head1.data + head2.data + carry; result.data = r % 10; carry = r / 10; return result; } private Node addRemaining(Node start, Node stop){ if(start != stop){ Node result = Node.newNode(0); result.next = addRemaining(start.next , stop); result.data = (start.data + carry)%10; carry = (start.data + carry)/10; return result; }else{ return null; } } public Node add(Node head1, Node head2){ if(head1 == null || head2 == null){ throw new IllegalArgumentException(); } LinkList ll = new LinkList(); int size1 = ll.size(head1); int size2 = ll.size(head2); Node larger = null; Node smaller = null; if(size1 >= size2){ larger = head1; smaller = head2; }else{ larger = head2; smaller = head1; } int diff = Math.abs(size1 - size2); Node largerStart = larger; while(diff > 0){ largerStart = largerStart.next; diff--; } Node result = addWithCarry(largerStart,smaller); Node result1 = addRemaining(larger,largerStart); if(carry != 0){ Node top = Node.newNode(carry); result1 = ll.addAtFront(top, result1); } if(result1 != null){ Node tail = result1; while(tail.next != null){ tail = tail.next; } tail.next = result; return result1; } return result; } public static void main(String args[]){ LinkList ll = new LinkList(); Node head = null; head = ll.addNode(9, head); head = ll.addNode(4, head); Node head1 = null; head1 = ll.addNode(3, head1); head1 = ll.addNode(1, head1); head1 = ll.addNode(2, head1); AddNumberRepresentedByLinkList anr = new AddNumberRepresentedByLinkList(); Node result = anr.add(head,head1); ll.printList(result); } } ================================================ FILE: src/com/interview/linklist/CopyLinkListWIthArbitPointer.java ================================================ package com.interview.linklist; /** * Date 03/24/2016 * @author Tushar Roy * * A linked list is given such that each node contains an additional random pointer which could point * to any node in the list or null. Return a deep copy of the list. * * Time complexity is O(n) * Space complexity is O(1) * * https://leetcode.com/problems/copy-list-with-random-pointer/ */ public class CopyLinkListWIthArbitPointer { static class RandomListNode { int label; RandomListNode next, random; RandomListNode(int x) { this.label = x; } } public RandomListNode copyRandomList(RandomListNode head) { if (head == null) { return null; } RandomListNode current = head; while (current != null) { RandomListNode newNode = new RandomListNode(current.label); newNode.next = current.next; newNode.random = current.random; current.next = newNode; current = newNode.next; } current = head; while (current != null) { RandomListNode next = current.next; if (next.random != null) { next.random = next.random.next; } current = current.next.next; } current = head; RandomListNode dummy = new RandomListNode(0); RandomListNode newCurrent = dummy; while (current != null) { newCurrent.next = current.next; newCurrent = newCurrent.next; current.next = current.next.next; current = current.next; } return dummy.next; } public static void main(String args[]){ CopyLinkListWIthArbitPointer cll = new CopyLinkListWIthArbitPointer(); RandomListNode randomListNode = new RandomListNode(-1); RandomListNode randomListNode1 = new RandomListNode(4); RandomListNode randomListNode2 = new RandomListNode(8); RandomListNode randomListNode3 = new RandomListNode(-3); RandomListNode randomListNode4 = new RandomListNode(7); randomListNode.next = randomListNode1; randomListNode1.next = randomListNode2; randomListNode2.next = randomListNode3; randomListNode3.next = randomListNode4; randomListNode.random = randomListNode1; randomListNode2.random = randomListNode3; randomListNode1.random = randomListNode; cll.copyRandomList(randomListNode); } } ================================================ FILE: src/com/interview/linklist/DeleteDuplicateNodes.java ================================================ package com.interview.linklist; /** * Date 04/17/2016 * @author Tushar Roy * * Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct * numbers from the original list. * * For example, * Given 1->2->3->3->4->4->5, return 1->2->5. * Given 1->1->1->2->3, return 2->3. * * https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/ */ public class DeleteDuplicateNodes { public Node deleteDuplicates(Node head) { Node dummyNode = new Node(); dummyNode.next = head; Node current = head; Node prev = dummyNode; while (current != null) { while(current.next != null && current.data == current.next.data) { current = current.next; } if (prev.next == current) { prev = current; } else { prev.next = current.next; } current = current.next; } return dummyNode.next; } } ================================================ FILE: src/com/interview/linklist/DeleteNAfterMNodes.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/delete-n-nodes-after-m-nodes-of-a-linked-list/ * Test cases: * neg value of m and/or n - not allowed * 0 value of n and/or m - not allowed * even n and m * odd n and m * odd size of the list * even size of the list */ public class DeleteNAfterMNodes { public void deleteNAfterMNodes(Node head,int m, int n){ if(head == null){ return; } while(head != null){ int i = 0; while(head != null && i < m-1){ head = head.next; i++; } if(head == null){ break; } Node temp = head.next; i=0; while(temp != null && i < n){ temp = temp.next; i++; } head.next = temp; head = temp; } } public static void main(String args[]){ DeleteNAfterMNodes daf = new DeleteNAfterMNodes(); LinkList ll = new LinkList(); Node head = null; head = ll.addNode(1, head); head = ll.addNode(2, head); head = ll.addNode(3, head); head = ll.addNode(4, head); head = ll.addNode(5, head); head = ll.addNode(6, head); daf.deleteNAfterMNodes(head, 3, 2); ll.printList(head); } } ================================================ FILE: src/com/interview/linklist/DeleteNodeWithGreaterValueOnRight.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/delete-nodes-which-have-a-greater-value-on-right-side/ * Test cases * Sorted list * reverse sorted list * 0 1 or more nodes in the list */ public class DeleteNodeWithGreaterValueOnRight { private int maxFound = Integer.MIN_VALUE; public Node deleteNodes(Node head){ if(head == null){ return null; } Node nextNode = deleteNodes(head.next); if(head.data > maxFound){ maxFound = head.data; } if(maxFound > head.data){ return nextNode; } head.next = nextNode; return head; } public static void main(String args[]){ DeleteNodeWithGreaterValueOnRight dng = new DeleteNodeWithGreaterValueOnRight(); LinkList ll = new LinkList(); Node head = null; head = ll.addNode(12, head); head = ll.addNode(15, head); head = ll.addNode(10, head); head = ll.addNode(11, head); head = ll.addNode(5, head); head = ll.addNode(6, head); head = ll.addNode(2, head); head = ll.addNode(3, head); head = dng.deleteNodes(head); ll.printList(head); } } ================================================ FILE: src/com/interview/linklist/DoubleLinkList.java ================================================ package com.interview.linklist; public class DoubleLinkList { public Node addNode(Node head,int data){ if(head == null){ head = Node.newNode(data); return head; } Node newNode = Node.newNode(data); Node current = head; while(current.next != null){ current = current.next; } current.next = newNode; newNode.before = current; return head; } public Node addAtFront(Node head, int data){ Node newNode = Node.newNode(data); if(head == null){ return newNode; } newNode.next = head; head.before = newNode; return newNode; } public void print(Node head){ while(head != null){ System.out.print(head.data + " "); head = head.next; } } public void printFrontBack(Node head){ Node prev = null; while(head != null){ System.out.print(head.data + " "); prev = head; head = head.next; } System.out.println(); while(prev != null){ System.out.print(prev.data + " "); prev = prev.before; } } public Node find(Node head, int data){ while(head != null){ if(head.data == data){ return head; } head = head.next; } return null; } public static void main(String args[]){ DoubleLinkList dll = new DoubleLinkList(); Node head = null; head = dll.addNode(head,1); head = dll.addNode(head,2); head = dll.addNode(head,3); head = dll.addNode(head,4); head = dll.addNode(head,5); dll.print(head); } } ================================================ FILE: src/com/interview/linklist/Flatten2DList.java ================================================ package com.interview.linklist; import java.util.Iterator; import java.util.List; /** * Date 10/10/2016 * @author Tushar Roy * * Implement an iterator to flatten a 2d vector. * * https://leetcode.com/problems/flatten-2d-vector/ * */ public class Flatten2DList implements Iterator { private List> vector; private int currentList = 0; private int currentPos = 0; public Flatten2DList(List> vec2d) { vector = vec2d; } @Override public Integer next() { if (!hasNext()) { throw new IllegalArgumentException(); } int data = vector.get(currentList).get(currentPos); currentPos++; if (currentPos == vector.get(currentList).size()) { currentPos = 0; currentList++; } return data; } @Override public boolean hasNext() { while (currentList < vector.size() && vector.get(currentList).size() == 0) { currentList++; } return currentList < vector.size(); } } ================================================ FILE: src/com/interview/linklist/FlattenLinkList.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/flatten-a-linked-list-with-next-and-child-pointers/ * Test case * 0 node in the list * 1 node in the list * All nodes with child * No nodes with child */ public class FlattenLinkList { public void flatten(Node head) { Node tail = getTail(head); while (head != null) { if (head.child != null) { tail.next = head.child; tail = getTail(tail.next); head.child = null; } head = head.next; } } private Node getTail(Node head) { if (head == null) { return null; } while (head.next != null) { head = head.next; } return head; } public static void main(String args[]) { LinkList ll = new LinkList(); Node head = null; head = ll.addNode(10, head); head = ll.addNode(5, head); head = ll.addNode(12, head); head = ll.addNode(7, head); head = ll.addNode(11, head); Node head1 = null; head1 = ll.addNode(4, head1); head1 = ll.addNode(20, head1); head1 = ll.addNode(13, head1); Node head2 = null; head2 = ll.addNode(2, head2); head2 = ll.addNode(8, head2); Node head4 = null; head4 = ll.addNode(17, head4); head4 = ll.addNode(6, head4); Node head5 = null; head5 = ll.addNode(9, head5); head5 = ll.addNode(8, head5); head5 = ll.addNode(15, head5); Node f1 = ll.find(head, 10); f1.child = head1; f1 = ll.find(head, 7); f1.child = head4; f1 = ll.find(head4, 17); f1.child = head5; f1 = ll.find(head1, 20); f1.child = head2; FlattenLinkList fll = new FlattenLinkList(); fll.flatten(head); ll.printList(head); } } ================================================ FILE: src/com/interview/linklist/InsertionSortLinkList.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/given-a-linked-list-which-is-sorted-how-will-you-insert-in-sorted-way/ * Test cases: * 0 nodes * 1 nodes * 2 or more nodes * already sorted * reverse sorted * negative positive numbers */ public class InsertionSortLinkList { private Node insert(Node head,Node curr){ if(head == null){ return curr; } Node prev = null; Node start = head; while(start != null && curr.data >= start.data){ prev = start; start = start.next; } if(prev == null){ curr.next = head; head = curr; }else{ prev.next = curr; curr.next = start; } return head; } public Node sort(Node head){ Node result = null; Node curr = head; Node prevCurr = null; while(curr != null){ prevCurr = curr; curr = curr.next; prevCurr.next = null; result = insert(result,prevCurr); } return result; } public static void main(String args[]){ LinkList ll = new LinkList(); Node head = null; head = ll.addNode(11, head); head = ll.addNode(12, head); head = ll.addNode(-3, head); head = ll.addNode(45, head); head = ll.addNode(5, head); head = ll.addNode(101, head); InsertionSortLinkList isll = new InsertionSortLinkList(); head = isll.sort(head); ll.printList(head); } } ================================================ FILE: src/com/interview/linklist/LRUCache.java ================================================ package com.interview.linklist; import java.util.HashMap; import java.util.Map; /** * http://www.geeksforgeeks.org/implement-lru-cache/ * Test cases: * MAX_SIZE greater than 1 * Delete when empty * Delete when full * Enter data more than max * Delete till cache is empty */ public class LRUCache { private Node head; private Node tail; private Map map = new HashMap(); private int MAX_SIZE = 5; private int size = 0; public LRUCache(int size){ MAX_SIZE = size; } public void used(int data){ if(containsInCache(data)){ Node node = map.get(data); if(node != head){ deleteFromCache(data); node.next = head; head.before = node; head = node; map.put(data, node); } }else{ addIntoCache(data); } } public void addIntoCache(int data){ size++; if(head == null){ head = Node.newNode(data); tail = head; return; } if(size > MAX_SIZE){ tail = tail.before; Node next = tail.next; tail.next = null; next.before = null; map.remove(next.data); } Node newNode = Node.newNode(data); newNode.next = head; if(head != null){ head.before = newNode; } head = newNode; map.put(data, newNode); return; } public void printCache(){ Node temp = head; while(temp != null){ System.out.print(temp.data + " "); temp = temp.next; } System.out.println(); } public boolean containsInCache(int data) { return map.containsKey(data); } public void deleteFromCache(int data){ Node node = map.get(data); if(node == null){ return; } map.remove(data); if(size == 1){ head = null; tail = null; } else if(node == head){ head = head.next; if(head != null){ head.before = null; } node.next = null; }else if(node == tail){ tail = tail.before; tail.next = null; }else{ Node before = node.before; Node next = node.next; before.next = next; next.before = before; } } public static void main(String args[]){ LRUCache lruCache = new LRUCache(5); lruCache.used(4); lruCache.used(5); lruCache.printCache(); lruCache.used(6); lruCache.printCache(); lruCache.used(5); lruCache.printCache(); lruCache.used(9); lruCache.printCache(); lruCache.used(10); lruCache.printCache(); lruCache.used(11); lruCache.printCache(); lruCache.used(16); lruCache.printCache(); lruCache.used(10); lruCache.printCache(); lruCache.deleteFromCache(10); lruCache.printCache(); lruCache.deleteFromCache(9); lruCache.printCache(); } } ================================================ FILE: src/com/interview/linklist/LRUCacheLeetCode.java ================================================ package com.interview.linklist; import java.util.LinkedHashMap; import java.util.Map; /** * Date 02/11/2016 * @author Tushar Roy * * Reference * https://leetcode.com/problems/lru-cache/ */ public class LRUCacheLeetCode { private LinkedHashMap map; private int capacity; public LRUCacheLeetCode(int capacity) { this.capacity = capacity; this.map = new MyMap(capacity); } public int get(int key) { Integer val = map.get(key); return val == null ? -1 : val; } public void set(int key, int value) { map.put(key, value); } class MyMap extends LinkedHashMap { int capacity; MyMap(int capacity) { super(capacity, 0.75f, true); this.capacity = capacity; } @Override protected boolean removeEldestEntry(Map.Entry entry) { return size() > capacity; } } } ================================================ FILE: src/com/interview/linklist/LinkList.java ================================================ package com.interview.linklist; class NodeRef{ Node node; public void next(){ node = node.next; } } class Node{ int data; Node next; Node before; Node child; Object obj; public static Node newNode(int data, Object... obj){ Node n = new Node(); n.data = data; n.next = null; n.before = null; if(obj.length > 0) { n.obj = obj[0]; } return n; } } public class LinkList { public Node addNode(int data, Node head, Object... obj){ Node temp = head; Node n = null; if(obj.length > 0){ n = Node.newNode(data, obj[0]); }else{ n = Node.newNode(data); } if(head == null){ return n; } while(head.next != null){ head = head.next; } head.next = n; return temp; } public Node addAtFront(Node node, Node head){ if(head == null){ return node; } node.next = head; return node; } public Node reverse(Node head){ Node front = null; Node middle = head; Node end = null; while(middle != null){ end = middle.next; middle.next = front; front = middle; middle = end; } return front; } public Node reverseRecursiveEasy(Node head){ if(head == null || head.next == null){ return head; } Node reversedList = reverseRecursiveEasy(head.next); head.next.next = head; head.next = null; return reversedList; } public void reverseRecursive(NodeRef headRef){ if(headRef.node == null){ return; } Node first = headRef.node; Node last = headRef.node.next; if(last == null){ return; } NodeRef lastHeadRef = new NodeRef(); lastHeadRef.node = last; reverseRecursive(lastHeadRef); first.next.next = first; first.next = null; headRef.node = lastHeadRef.node; } public Node addAtFront(int data, Node head){ Node node = Node.newNode(data); return addAtFront(node,head); } public void printList(Node head){ while(head != null){ System.out.println(head.data); head = head.next; } } public Node find(Node head, int data){ while(head != null){ if(head.data == data){ return head; } head = head.next; } return null; } public int size(Node head){ int size =0; while(head != null){ size++; head = head.next; } return size; } public static void main(String args[]){ LinkList ll = new LinkList(); Node head = null; head = ll.addNode(1, head); head = ll.addNode(2, head); head = ll.addNode(3, head); head = ll.addNode(4, head); head = ll.addNode(5, head); head = ll.addNode(6, head); ll.printList(head); // NodeRef headRef = new NodeRef(); // headRef.node = head; // ll.reverseRecursive(headRef); // head = headRef.node; // ll.printList(head); System.out.println(); head = ll.reverseRecursiveEasy(head); ll.printList(head); } } ================================================ FILE: src/com/interview/linklist/LinkListIsPalindrome.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/function-to-check-if-a-singly-linked-list-is-palindrome/ * Test cases: * odd number of nodes * even number of nodes * 0 1 or more nodes * palindrome list * non palindrom list */ public class LinkListIsPalindrome { public boolean isPalindrome(NodeRef head,Node end){ if(end == null){ return true; } boolean r = isPalindrome(head,end.next); r = r && head.node.data == end.data; head.next(); return r; } public static void main(String args[]){ LinkList ll = new LinkList(); Node head = null; head = ll.addNode(1, head); head = ll.addNode(2, head); head = ll.addNode(3, head); head = ll.addNode(4, head); head = ll.addNode(3, head); head = ll.addNode(2, head); head = ll.addNode(1, head); NodeRef nodeRef = new NodeRef(); nodeRef.node = head; LinkListIsPalindrome llp = new LinkListIsPalindrome(); System.out.println(llp.isPalindrome(nodeRef, head)); } } ================================================ FILE: src/com/interview/linklist/LinkListToCompleteBinaryTree.java ================================================ package com.interview.linklist; import java.util.LinkedList; import java.util.Queue; /** * http://www.geeksforgeeks.org/given-linked-list-representation-of-complete-tree-convert-it-to-linked-representation/ * Test cases * Zero, One or more nodes in link list */ public class LinkListToCompleteBinaryTree { public void convert(Node head){ if(head == null){ return; } Queue queue = new LinkedList<>(); queue.add(head); head = head.next; while(head != null){ Node top = queue.poll(); top.before = head; head = head.next; if(head != null){ top.next = head; head = head.next; //null the next of child before putting them into queue top.before.next = null; top.next.next = null; queue.add(top.before); queue.add(top.next); }else{ break; } } } public void inorder(Node head){ if(head == null){ return; } inorder(head.before); System.out.print(head.data + " "); inorder(head.next); } public static void main(String args[]){ LinkList ll = new LinkList(); Node head = null; head = ll.addNode(10, head); head = ll.addNode(12, head); head = ll.addNode(15, head); head = ll.addNode(25, head); head = ll.addNode(30, head); head = ll.addNode(36, head); head = ll.addNode(40, head); head = ll.addNode(45, head); LinkListToCompleteBinaryTree llct = new LinkListToCompleteBinaryTree(); llct.convert(head); llct.inorder(head); } } ================================================ FILE: src/com/interview/linklist/LoopInLinkList.java ================================================ package com.interview.linklist; /** * Date 04/17/2016 * @author tusroy * * Given a linked list, determine if it has a cycle in it. * * Time complexity O(n) * Space complexity O(1) * * https://leetcode.com/problems/linked-list-cycle/ */ public class LoopInLinkList { public boolean hasCycle(Node head){ if (head == null) { return false; } Node slow = head; Node fast = head.next; while (fast != null) { if (slow == fast || fast.next == slow) { return true; } slow = slow.next; if (fast.next != null) { fast = fast.next.next; } else { break; } } return false; } public static void main(String args[]){ LinkList ll = new LinkList(); Node head = null; head = ll.addNode(1, head); head = ll.addNode(2, head); head = ll.addNode(3, head); head = ll.addNode(4, head); head = ll.addNode(5, head); head = ll.addNode(6, head); head = ll.addNode(7, head); head = ll.addNode(8, head); Node node1 = ll.find(head, 8); Node node2 = ll.find(head, 4); node1.next = node2; LoopInLinkList lll = new LoopInLinkList(); System.out.println(lll.hasCycle(head)); node2.next = null; System.out.println(lll.hasCycle(head)); node1 = ll.find(head, 3); node2.next = node1; System.out.println(lll.hasCycle(head)); } } ================================================ FILE: src/com/interview/linklist/MergeForLargestSum.java ================================================ package com.interview.linklist; /* * http://www.geeksforgeeks.org/maximum-sum-linked-list-two-sorted-linked-lists-common-nodes/ * Test cases * Test that chains never meet * Test that chain meets only once * Test that chain meets multipe times * Test that one chain ends where it meets chain 2 */ public class MergeForLargestSum { Node maxChain(Node head1, Node head2){ if(head1 == null){ return head2; } if(head2 == null){ return head1; } Node curr1 = head1; Node curr2 = head2; int sum1 = 0; int sum2 = 0; Node result = null; Node prev = null; while(curr1!= null && curr2 != null){ if(curr1.data == curr2.data){ sum1 += curr1.data; sum2 += curr2.data; if(sum1 <= sum2){ if(result == null){ result = head2; prev = curr2; }else{ prev.next = head2.next; prev = curr2; } }else{ if(result == null){ result = head1; prev = curr1; }else{ prev.next = head1.next; prev = curr1; } } head1 = curr1; head2 = curr2; sum1 = 0; sum2 = 0; curr1 = curr1.next; curr2 = curr2.next; } else if(curr1.data < curr2.data){ sum1 += curr1.data; curr1 = curr1.next; } else{ sum2 += curr2.data; curr2 = curr2.next; } } while(curr1 != null){ sum1+= curr1.data; curr1 = curr1.next; } while(curr2 != null){ sum2 += curr2.data; curr2 = curr2.next; } if(result != null){ if(sum1 <= sum2){ prev.next = head2.next; }else{ prev.next = head1.next; } }else{ if(sum1 <= sum2){ result = head2; }else{ result = head1; } } return result; } public static void main(String args[]){ LinkList ll = new LinkList(); Node head1 = null; head1 = ll.addNode(1, head1); head1 = ll.addNode(3, head1); head1 = ll.addNode(30, head1); head1 = ll.addNode(90, head1); head1 = ll.addNode(120, head1); head1 = ll.addNode(240, head1); head1 = ll.addNode(243, head1); head1 = ll.addNode(251, head1); head1 = ll.addNode(511, head1); Node head2 = null; head2 = ll.addNode(0, head2); head2 = ll.addNode(3, head2); head2 = ll.addNode(12, head2); head2 = ll.addNode(32, head2); head2 = ll.addNode(90, head2); head2 = ll.addNode(125, head2); head2 = ll.addNode(240, head2); head2 = ll.addNode(249, head2); head2 = ll.addNode(251, head2); head2 = ll.addNode(260, head2); MergeForLargestSum mls = new MergeForLargestSum(); Node result = mls.maxChain(head1, head2); ll.printList(result); } } ================================================ FILE: src/com/interview/linklist/MergeSortLinkList.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/merge-sort-for-linked-list/ * Test cases * 0 nodes * 1 nodes * 2 nodes * 3 nodes * fully sorted * reverse sorted */ public class MergeSortLinkList { public Node sort(Node head, boolean isAscending){ if(head == null || head.next == null){ return head; } Node head1 = frontBackSplit(head); head = sort(head,isAscending); head1 = sort(head1,isAscending); return sortedMerge(head, head1, isAscending); } private Node sortedMerge(Node head1, Node head2, boolean isAscending){ if(head1 == null){ return head2; } if(head2 == null){ return head1; } if(isAscending){ if(head1.data <= head2.data){ head1.next = sortedMerge(head1.next, head2, isAscending); return head1; }else{ head2.next = sortedMerge(head1,head2.next, isAscending); return head2; } }else{ if(head1.data >= head2.data){ head1.next = sortedMerge(head1.next, head2, isAscending); return head1; }else{ head2.next = sortedMerge(head1,head2.next, isAscending); return head2; } } } private Node frontBackSplit(Node head){ if(head == null){ return null; } Node slow = head; Node fast = head.next; while(fast != null && fast.next != null){ slow = slow.next; fast = fast.next.next; } Node newHead = slow.next; slow.next = null; return newHead; } public static void main(String args[]){ MergeSortLinkList msll = new MergeSortLinkList(); LinkList ll = new LinkList(); Node head = null; head = ll.addNode(11, head); head = ll.addNode(12, head); head = ll.addNode(-3, head); head = ll.addNode(45, head); head = ll.addNode(5, head); head = msll.sort(head, false); ll.printList(head); } } ================================================ FILE: src/com/interview/linklist/MiddleElementOfLinkList.java ================================================ package com.interview.linklist; /** * Find middle element in linklist. * Use two pointer approach. * Test cases * 0,1,2,3,4 and so on nodes * @author tusroy * */ public class MiddleElementOfLinkList { public int middle(Node head){ if(head == null || head.next == null){ return head.data; } Node slow = head; Node fast = head.next; while(fast != null && fast.next != null){ slow = slow.next; fast = fast.next.next; } return slow.data; } public static void main(String args[]){ MiddleElementOfLinkList mle = new MiddleElementOfLinkList(); LinkList ll = new LinkList(); Node head = null; head = ll.addNode(1, head); System.out.println(mle.middle(head)); head = ll.addNode(2, head); System.out.println(mle.middle(head)); head = ll.addNode(3, head); System.out.println(mle.middle(head)); head = ll.addNode(4, head); System.out.println(mle.middle(head)); head = ll.addNode(5, head); System.out.println(mle.middle(head)); } } ================================================ FILE: src/com/interview/linklist/MultiplyTwoNumbersLinkList.java ================================================ package com.interview.linklist; /** * Multiply two numbers in form of link list * Idea is to multiply one number from head2 with all numbers from head1. * This result is stored in currentResult. Pass this currentResult and any previous result from multiplication * and add them */ public class MultiplyTwoNumbersLinkList { public Node multiply(Node head1, Node head2){ LinkList ll = new LinkList(); head1 = ll.reverse(head1); head2 = ll.reverse(head2); DoubleLinkList dll = new DoubleLinkList(); Node result = null; Node resultStart = null; Node currentResult = null; Node currentTail = null; while(head2 != null){ Node current = head1; int carry = 0; while(current != null){ int r = current.data * head2.data; r += carry; carry = r/10; r = r%10; if(currentResult == null){ currentResult = dll.addAtFront(currentResult, r); currentTail = currentResult; }else{ currentResult = dll.addAtFront(currentResult, r); } current = current.next; } if(carry != 0){ currentResult = dll.addAtFront(currentResult, carry); } currentResult = null; if(result == null){ result = add(resultStart,currentTail); resultStart = result; }else{ result = add(resultStart,currentTail); resultStart = resultStart.before; } head2 = head2.next; } while(result.before != null){ result = result.before; } head1 = ll.reverse(head1); head2 = ll.reverse(head2); return result; } private Node add(Node result, Node currentResult){ if(currentResult == null){ return result; } if(result == null){ return currentResult; } Node r1 = result.before; Node addResult = null; int carry = 0; while(r1 != null && currentResult != null){ int r = r1.data + currentResult.data + carry; Node newNode = Node.newNode(r%10); if(addResult == null){ addResult = newNode; }else{ addResult.before = newNode; newNode.next = addResult; addResult = addResult.before; } carry = r/10; r1 = r1.before; currentResult = currentResult.before; } while(r1 != null){ int r = r1.data + carry; Node newNode = Node.newNode(r%10); if(addResult == null){ addResult = newNode; }else{ addResult.before = newNode; newNode.next = addResult; addResult = addResult.before; } carry = r/10; r1 = r1.before; } while(currentResult != null){ int r = currentResult.data + carry; Node newNode = Node.newNode(r%10); if(addResult == null){ addResult = newNode; }else{ addResult.before = newNode; newNode.next = addResult; addResult = addResult.before; } carry = r/10; currentResult = currentResult.before; } if(carry != 0){ Node newNode = Node.newNode(carry); addResult.before = newNode; newNode.next = addResult; addResult = addResult.before; } while(addResult.next != null){ addResult = addResult.next; } addResult.next = result; result.before = addResult; return result; } public static void main(String args[]){ MultiplyTwoNumbersLinkList mtn = new MultiplyTwoNumbersLinkList(); LinkList ll = new LinkList(); Node head1 = null; head1 = ll.addNode(2, head1); head1 = ll.addNode(3, head1); head1 = ll.addNode(5, head1); head1 = ll.addNode(0, head1); head1 = ll.addNode(1, head1); Node head2 = null; head2 = ll.addNode(5, head2); head2 = ll.addNode(7, head2); head2 = ll.addNode(8, head2); Node result = mtn.multiply(head1, head2); ll.printList(result); } } ================================================ FILE: src/com/interview/linklist/QuickSortSingleLinkList.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/quicksort-on-singly-linked-list/ * Test cases * 0 1 or more nodes * sorted reverse sorted nodes */ //keep head and tail of each result since caller function needs it to //set complete linklist. If we do not keep tail in each recursion we will //have to traverse to tail of left side which can be costly operation class HeadTail{ Node head; Node tail; } public class QuickSortSingleLinkList { public Node quickSort(Node head){ if(head == null || head.next == null){ return head; } Node smaller = null; Node larger = null; Node pivot = head; Node temp = head.next; pivot.next = null; LinkList ll = new LinkList(); while(temp != null){ Node next = temp.next; temp.next = null; if(temp.data < pivot.data){ smaller = ll.addAtFront(temp, smaller); }else{ larger = ll.addAtFront(temp, larger); } temp = next; } smaller = quickSort(smaller); larger = quickSort(larger); Node tail1 = smaller; //this is costly operation which can be prevented by keeping tail. while(tail1 != null && tail1.next != null){ tail1 = tail1.next; } if(smaller != null){ tail1.next = pivot; pivot.next = larger; return smaller; }else{ pivot.next = larger; return pivot; } } public Node quickSortFaster(Node head){ HeadTail result = quickSortUtil(head); return result.head; } /** * This version keeps tail of each recursion which helps us avoid going to tail in each recursion. * @param head * @return */ private HeadTail quickSortUtil(Node head){ if(head == null || head.next == null){ HeadTail headTail = new HeadTail(); headTail.head = head; headTail.tail = head; return headTail; } LinkList ll = new LinkList(); Node leftHead = null; Node rightHead = null; Node curr = head.next; head.next = null; Node next = null; while(curr != null){ next = curr.next; curr.next = null; if(curr.data < head.data){ leftHead = ll.addAtFront(curr, leftHead); }else{ rightHead = ll.addAtFront(curr, rightHead); } curr = next; } HeadTail leftSide = quickSortUtil(leftHead); HeadTail rightSide = quickSortUtil(rightHead); head.next= rightSide.head; HeadTail result = new HeadTail(); result.head = head; result.tail = head; if(leftSide.tail != null){ leftSide.tail.next = head; result.head = leftSide.head; } if(rightSide.head != null){ head.next = rightSide.head; result.tail = rightSide.tail; } return result; } public static void main(String args[]){ QuickSortSingleLinkList qss = new QuickSortSingleLinkList(); LinkList ll = new LinkList(); Node head = null; head = ll.addNode(11, head); head = ll.addNode(2, head); head = ll.addNode(-1, head); head = ll.addNode(50, head); head = ll.addNode(13, head); head = ll.addNode(-5, head); head = ll.addNode(10, head); head = ll.addNode(8, head); head = qss.quickSortFaster(head); ll.printList(head); } } ================================================ FILE: src/com/interview/linklist/RemoveDuplicatesSortedList.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/remove-duplicates-from-a-sorted-linked-list/ * Test cases * All duplicates * No duplicates * Duplicates only in starting * Duplicates only at the end * 0 1 or more nodes in the list */ public class RemoveDuplicatesSortedList { public void removeDuplicates(Node head){ if(head == null){ return; } Node current = head; while(current != null && current.next != null){ if(current.data == current.next.data){ current.next = current.next.next; }else{ current = current.next; } } } public static void main(String args[]){ LinkList ll = new LinkList(); Node head = null; head = ll.addNode(1, head); head = ll.addNode(1, head); head = ll.addNode(1, head); head = ll.addNode(4, head); head = ll.addNode(4, head); head = ll.addNode(5, head); head = ll.addNode(6, head); head = ll.addNode(6, head); head = ll.addNode(6, head); RemoveDuplicatesSortedList rds = new RemoveDuplicatesSortedList(); rds.removeDuplicates(head); ll.printList(head); } } ================================================ FILE: src/com/interview/linklist/RemoveMiddleElementsOfLineSegment.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/given-linked-list-line-segments-remove-middle-points/ * @author tusroy * Test cases: * 0 or more nodes * All points are edge of line segments so nothing gets removed * One long line so all points in between get removed * */ class Point{ int x; int y; Point(int x, int y){ this.x = x; this.y = y; } } public class RemoveMiddleElementsOfLineSegment { public void remove(Node head){ if(head == null || head.next == null){ return; } Node curr = head; Node next = head.next; Node nextNext = head.next.next; while(nextNext != null){ Point pcurr = (Point)curr.obj; Point pnext = (Point)nextNext.obj; if(pcurr.x == pnext.x || pcurr.y == pnext.y){ curr.next = nextNext; next = nextNext; nextNext = nextNext.next; }else{ curr = curr.next; next = next.next; nextNext = nextNext.next; } } } public static void main(String args[]){ Node head1 = null; LinkList ll = new LinkList(); head1 = ll.addNode(1, head1, new Point(0,10)); head1 = ll.addNode(2, head1, new Point(1,10)); head1 = ll.addNode(3, head1, new Point(5,10)); head1 = ll.addNode(4, head1, new Point(7,10)); head1 = ll.addNode(5, head1, new Point(7,5)); head1 = ll.addNode(6, head1, new Point(20,5)); head1 = ll.addNode(7, head1, new Point(40,5)); head1 = ll.addNode(8, head1, new Point(40,8)); RemoveMiddleElementsOfLineSegment rme = new RemoveMiddleElementsOfLineSegment(); rme.remove(head1); ll.printList(head1); } } ================================================ FILE: src/com/interview/linklist/ReorderList.java ================================================ package com.interview.linklist; /** * Given a singly linked list L: L0→L1→…→Ln-1→Ln, * reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… * * https://leetcode.com/problems/reorder-list/ */ public class ReorderList { public void reorderList(Node head) { Node back = frontBackSplit(head); back = reverse(back); alternateMerge(head, back); } private Node alternateMerge(Node head1, Node head2) { Node dummyHead = new Node(); Node current = dummyHead; while (head1 != null && head2 != null) { current.next= head1; head1 = head1.next; current = current.next; current.next = head2; head2 = head2.next; current = current.next; } current.next = head1; return dummyHead.next; } private Node reverse(Node head) { if (head == null) { return null; } Node front = null; Node mid = head; Node next = null; while (mid != null) { next = mid.next; mid.next = front; front = mid; mid = next; } return front; } private Node frontBackSplit(Node head) { if (head == null) { return null; } Node slow = head; head = head.next; while (head != null && head.next != null) { slow = slow.next; head = head.next.next; } Node next = slow.next; slow.next = null; return next; } } ================================================ FILE: src/com/interview/linklist/ReverseAlternateKNodes.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/reverse-alternate-k-nodes-in-a-singly-linked-list/ * Test case * k is even odd * number of nodes are even odd * k is less than or equal to 1. */ public class ReverseAlternateKNodes { public Node reverse(Node head,int k,boolean reverse){ if(k <= 1){ return head; } if(head == null){ return null; } if(reverse){ int i =0; Node front = null; Node middle = head; Node end = null; while(middle != null && i < k){ end = middle.next; middle.next = front; front = middle; middle = end; i++; } head.next = reverse(middle,k, !reverse); head = front; }else{ int i=0; Node temp = head; while(i < k-1 && head != null){ head = head.next; i++; } if(head != null){ head.next = reverse(head.next,k, !reverse); } head = temp; } return head; } public static void main(String args[]){ LinkList ll = new LinkList(); Node head = null; head = ll.addNode(1, head); head = ll.addNode(2, head); head = ll.addNode(3, head); head = ll.addNode(4, head); head = ll.addNode(5, head); head = ll.addNode(6, head); head = ll.addNode(7, head); head = ll.addNode(8, head); ReverseAlternateKNodes ra = new ReverseAlternateKNodes(); head = ra.reverse(head, 3, false); ll.printList(head); } } ================================================ FILE: src/com/interview/linklist/ReverseAlternateNodeAndAppendAtEnd.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/given-linked-list-reverse-alternate-nodes-append-end/ * Test case * Even and odd number of nodes */ public class ReverseAlternateNodeAndAppendAtEnd { public void act(Node head){ Node result = null; LinkList ll = new LinkList(); while(head != null && head.next != null){ Node temp = head.next; head.next = head.next.next; temp.next = null; result = ll.addAtFront(temp,result); if(head.next == null){ break; } head = head.next; } head.next = result; } public static void main(String args[]){ LinkList ll = new LinkList(); Node head = null; head = ll.addNode(1, head); head = ll.addNode(2, head); head = ll.addNode(3, head); head = ll.addNode(4, head); head = ll.addNode(5, head); head = ll.addNode(6, head); ReverseAlternateNodeAndAppendAtEnd ran = new ReverseAlternateNodeAndAppendAtEnd(); ran.act(head); ll.printList(head); } } ================================================ FILE: src/com/interview/linklist/ReverseKNodes.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/pairwise-swap-elements-of-a-given-linked-list/ * Test case * odd or even number of k * odd or even number of nodes in the list */ public class ReverseKNodes { public Node reverse(Node head,int k){ if(head == null){ return null; } Node front = null; Node middle = head; Node end = null; int i=0; while(middle != null && i < k){ end = middle.next; middle.next = front; front = middle; middle = end; i++; } head.next = reverse(middle,k); return front; } public static void main(String args[]){ LinkList ll = new LinkList(); Node head = null; head = ll.addNode(1, head); head = ll.addNode(2, head); head = ll.addNode(3, head); head = ll.addNode(4, head); head = ll.addNode(5, head); head = ll.addNode(6, head); head = ll.addNode(7, head); head = ll.addNode(8, head); ReverseKNodes rn = new ReverseKNodes(); head = rn.reverse(head, 3); ll.printList(head); } } ================================================ FILE: src/com/interview/linklist/RotateList.java ================================================ package com.interview.linklist; /** * Date 10/10/2016 * @author Tushar Roy * Given a list, rotate the list to the right by k places, where k is non-negative. * * Time complexity O(min(n, k)) * * https://leetcode.com/problems/rotate-list/ */ public class RotateList { public Node rotateRight(Node head, int k) { if (head == null || k == 0) { return head; } Node slow = head; Node fast = head; int i = 0; while (i < k && fast != null) { fast = fast.next; i++; } if (fast == null) { return rotateRight(head, k % i); } while (fast.next != null) { fast = fast.next; slow = slow.next; } Node next = slow.next; slow.next = null; fast.next = head; return next; } } ================================================ FILE: src/com/interview/linklist/ShuffleMerge.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/merge-a-linked-list-into-another-linked-list-at-alternate-positions/ * Given two linklist shuffle merge them. * e.g head1 = {1->3->5} * head2 = {2->4} * result = {1->2->3->4->5} * Test cases * head1 is null and head2 is not * head2 is null and head1 is not * both are null * more nodes in head1 than head2 * more nodes in head2 than head1 * @author tusroy * */ public class ShuffleMerge { public Node shuffleMergeRecursive(Node head1, Node head2){ if(head1 == null){ return head2; } if(head2 == null){ return head1; } Node recur = null; recur = shuffleMergeRecursive(head1.next, head2.next); head1.next = head2; head2.next = recur; return head1; } /** Size of list 1 is smaller, equal and larger than list 2 */ public Node shuffleMerge(Node head1, Node head2){ if(head1 == null || head2 == null){ return head2; } Node tempHead = head1; Node prev = null; while(head1 != null && head2 != null){ Node temp = head1.next; Node temp1 = head2.next; head1.next = head2; head2.next = temp; prev = head2; head2 = temp1; head1 = temp; } if(head2 != null){ prev.next = head2; } return tempHead; } public static void main(String args[]){ LinkList ll = new LinkList(); Node head1 = null; Node head2 = null; head1 = ll.addNode(1, head1); head1 = ll.addNode(3, head1); head1 = ll.addNode(5, head1); head1 = ll.addNode(7, head1); head1 = ll.addNode(9, head1); head2 = ll.addNode(2, head2); head2 = ll.addNode(4, head2); head2 = ll.addNode(6, head2); head2 = ll.addNode(8, head2); head2 = ll.addNode(10, head2); head2 = ll.addNode(12, head2); head2 = ll.addNode(14, head2); ShuffleMerge sm = new ShuffleMerge(); Node result = sm.shuffleMerge(head1, head2); ll.printList(result); } } ================================================ FILE: src/com/interview/linklist/SortNearlySortedList.java ================================================ package com.interview.linklist; /** * Given a linklist which has individual sorted componenets sort the entire linst * e.g 1-3-6-8-4-5-10-7-9 * Here 1,2,6,8 are sorted, 4,5,10 are sorted and 7,9 are sorted * Test case * null node * 1 node * 2 sorted nodes * 2 reverse sorted nodes * 3 reverse sorted nodes * 4 nodes 2 each sorted among themselves */ public class SortNearlySortedList { public Node sort(Node head){ Node result = null; Node start = head; while(head != null && head.next != null){ if(head.data < head.next.data){ head = head.next; }else{ Node temp = head.next; head.next = null; result = mergeSort(result,start); head = temp; start = temp; } } result = mergeSort(result,start); return result; } private Node mergeSort(Node head1,Node head2){ if(head1 == null){ return head2; } if(head2 == null){ return head1; } if(head1.data <= head2.data){ head1.next = mergeSort(head1.next,head2); return head1; }else{ head2.next = mergeSort(head1,head2.next); return head2; } } public static void main(String args[]){ LinkList ll = new LinkList(); Node head = null; head = ll.addNode(1, head); head = ll.addNode(2, head); head = ll.addNode(3, head); head = ll.addNode(7, head); head = ll.addNode(5, head); head = ll.addNode(6, head); head = ll.addNode(13, head); head = ll.addNode(11, head); head = ll.addNode(12, head); SortNearlySortedList sns = new SortNearlySortedList(); head = sns.sort(head); ll.printList(head); } } ================================================ FILE: src/com/interview/linklist/SortedCircularLinkList.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/sorted-insert-for-circular-linked-list/ * Test cases * Insert 2nd element smaller than head * Insert 2nd element larger than head * Insert element larger than tail * Insert element just before tail * Insert element somewhere between head and tail */ public class SortedCircularLinkList { public Node add(Node head,int data){ if(head == null){ head = Node.newNode(data); head.next = head; return head; } Node node = Node.newNode(data); Node tail = getTail(head); if(node.data < head.data){ node.next = head; tail.next = node; return node; } Node current = head; Node pre = null; while(current != tail && node.data >= current.data){ pre = current; current = current.next; } if(node.data < current.data){ node.next = current; pre.next = node; } else{ node.next = tail.next; tail.next = node; } return head; } private Node getTail(Node head){ Node temp = head; while(temp.next != head){ temp = temp.next; } return temp; } public void printList(Node head){ if(head == null){ return; } Node current = head.next; System.out.println(head.data); while(current != head){ System.out.println(current.data); current = current.next; } } public static void main(String args[]){ SortedCircularLinkList scll = new SortedCircularLinkList(); Node head = null; head = scll.add(head, 10); head = scll.add(head, 12); head = scll.add(head, -1); head = scll.add(head, -5); head = scll.add(head, 11); head = scll.add(head, 7); scll.printList(head); } } ================================================ FILE: src/com/interview/linklist/SortedLLToBalancedBST.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/sorted-linked-list-to-balanced-bst/ * Test cases * empty list * 0 1 or more node lists */ public class SortedLLToBalancedBST { public Node toBalancedBST(Node head){ LinkList ll = new LinkList(); int size = ll.size(head); NodeRef headRef = new NodeRef(); headRef.node = head; return toBalancedBST(headRef, size); } private Node toBalancedBST(NodeRef headRef, int size){ if(size <= 0){ return null; } Node left = toBalancedBST(headRef,size/2); Node head = headRef.node; headRef.next(); Node right = toBalancedBST(headRef,size - size/2 -1); head.before = left; head.next = right; return head; } public void printTreeInOrder(Node head){ if(head == null){ return; } printTreeInOrder(head.before); System.out.println(head.data); printTreeInOrder(head.next); } public void printTreePreOrder(Node head){ if(head == null){ return; } System.out.println(head.data); printTreePreOrder(head.before); printTreePreOrder(head.next); } public static void main(String args[]){ LinkList ll = new LinkList(); Node head = null; head = ll.addNode(1, head); head = ll.addNode(2, head); head = ll.addNode(3, head); head = ll.addNode(4, head); head = ll.addNode(5, head); head = ll.addNode(6, head); head = ll.addNode(7, head); SortedLLToBalancedBST sll = new SortedLLToBalancedBST(); head = sll.toBalancedBST(head); sll.printTreeInOrder(head); sll.printTreePreOrder(head); } } ================================================ FILE: src/com/interview/linklist/StackWithLinkListMiddleOperation.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/design-a-stack-with-find-middle-operation/ * Test cases: * Delete middle with 1,2,3 element * Pop with 1,2,3 elements * Delete or pop when empty stack */ public class StackWithLinkListMiddleOperation { private Node head = null; private Node middle = null; private int size = 0; public void push(int data){ if(head == null){ head = Node.newNode(data); middle = head; size++; return; } size++; Node node = Node.newNode(data); node.next = head; head.before = node; head = node; if(size % 2 ==0){ middle = middle.before; } } public boolean hasMore(){ if(size > 0 ){ return true; }else{ return false; } } public int size(){ return size; } public int pop(){ if(size == 0){ throw new IllegalArgumentException(); } size--; if(size % 2 != 0 || size == 0){ middle = middle.next; } int data = head.data; head = head.next; head.before = null; return data; } public int top(){ if(size == 0){ throw new IllegalArgumentException(); } return head.data; } public int middle(){ if(size == 0){ throw new IllegalArgumentException(); } return middle.data; } public int deleteMiddle(){ if(size == 0){ throw new IllegalArgumentException(); } size--; if(middle == head){ int data = middle.data; middle = middle.next; head = head.next; if(head != null){ head.before = null; } return data; } if(size % 2 == 0){ int data = middle.data; Node next = middle.next; middle = middle.before; middle.next = next; if(next != null){ next.before = middle; } return data; } else{ int data = middle.data; Node before = middle.before; middle = middle.next; middle.before = before; if(before != null){ before.next = middle; } return data; } } public static void main(String args[]){ StackWithLinkListMiddleOperation swl = new StackWithLinkListMiddleOperation(); swl.push(1); System.out.println(swl.top() + " " + swl.middle()); swl.push(2); System.out.println(swl.top() + " " + swl.middle()); swl.push(3); System.out.println(swl.top() + " " + swl.middle()); swl.push(4); System.out.println(swl.top() + " " + swl.middle()); swl.push(5); System.out.println(swl.top() + " " + swl.middle()); swl.push(6); System.out.println(swl.top() + " " + swl.middle()); System.out.println("\n\n"); swl.pop(); System.out.println(swl.top() + " " + swl.middle()); swl.deleteMiddle(); System.out.println(swl.top() + " " + swl.middle()); swl.pop(); System.out.println(swl.top() + " " + swl.middle()); swl.deleteMiddle(); System.out.println(swl.top() + " " + swl.middle()); swl.pop(); System.out.println(swl.top() + " " + swl.middle()); swl.deleteMiddle(); } } ================================================ FILE: src/com/interview/linklist/SwapTwoNodesInDoubleLL.java ================================================ package com.interview.linklist; /** * Swap two nodes in double link list. If it swaps first node its callers responsibility to fix the head * Test cases * A right neighbor of B * B right neighbor of A * A and B not neighbors of each other * A or B are start or end nodes */ public class SwapTwoNodesInDoubleLL { public void swap(Node nodeA, Node nodeB){ if(nodeA == null || nodeB == null){ throw new IllegalArgumentException(); } //if B is right neighbor of A if(nodeA.next == nodeB){ if(nodeA.before != null){ nodeA.before.next = nodeB; nodeB.before = nodeA.before; }else{ nodeB.before = null; } if(nodeB.next != null){ nodeB.next.before = nodeA; nodeA.next = nodeB.next; }else{ nodeA.next = null; } nodeB.next = nodeA; nodeA.before = nodeB; }//else if A is right neighbor of B else if(nodeB.next == nodeA){ if(nodeB.before != null){ nodeB.before.next = nodeA; nodeA.before = nodeB.before; }else{ nodeA.before = null; } if(nodeA.next != null){ nodeA.next.before = nodeB; nodeB.next = nodeA.next; }else{ nodeB.next = null; } nodeA.next = nodeB; nodeB.before = nodeA; }//if A and B are not neighbors of each other else{ if(nodeA.before != null){ nodeA.before.next = nodeB; } if(nodeA.next != null){ nodeA.next.before = nodeB; } Node next = nodeB.next; Node before = nodeB.before; nodeB.before = nodeA.before; nodeB.next = nodeA.next; if(next != null){ next.before = nodeA; } if(before != null){ before.next = nodeA; } nodeA.before = before; nodeA.next = next; } } public static void main(String args[]){ DoubleLinkList dll = new DoubleLinkList(); Node head = null; head = dll.addNode(head,1); head = dll.addNode(head,2); head = dll.addNode(head,3); head = dll.addNode(head,4); head = dll.addNode(head,5); SwapTwoNodesInDoubleLL snt = new SwapTwoNodesInDoubleLL(); Node nodeA = dll.find(head, 3); Node nodeB = dll.find(head, 5); snt.swap(nodeA, nodeB); dll.printFrontBack(head); } } ================================================ FILE: src/com/interview/linklist/TripletToSumInLinkList.java ================================================ package com.interview.linklist; /** * http://www.geeksforgeeks.org/find-a-triplet-from-three-linked-lists-with-sum-equal-to-a-given-number/ * Test case * empty list * list with 0 1 or more nodes * negative sum * 0 sum * positive sum */ public class TripletToSumInLinkList { public void printTriplet(Node head1, Node head2, Node head3,int sum){ if(head1 == null || head2 == null || head3 == null){ return; } MergeSortLinkList msll = new MergeSortLinkList(); head2 = msll.sort(head2, true); head3 = msll.sort(head3, false); while(head1 != null){ int newSum = sum - head1.data; Node tempHead2 = head2; Node tempHead3 = head3; while(tempHead2 != null && tempHead3 != null){ if(tempHead2.data + tempHead3.data == newSum){ System.out.println(head1.data + " " + tempHead2.data + " " + tempHead3.data); break; } else if(tempHead2.data + tempHead3.data < newSum){ tempHead2 = tempHead2.next; }else{ tempHead3 = tempHead3.next; } } head1 = head1.next; } } public static void main(String args[]){ LinkList ll = new LinkList(); Node head = null; head = ll.addNode(1, head); head = ll.addNode(8, head); head = ll.addNode(-3, head); head = ll.addNode(14, head); Node head1 = null; head1 = ll.addNode(-1, head1); head1 = ll.addNode(22, head1); head1 = ll.addNode(31, head1); head1 = ll.addNode(11, head1); Node head2 = null; head2 = ll.addNode(5, head2); head2 = ll.addNode(7, head2); head2 = ll.addNode(3, head2); head2 = ll.addNode(1, head2); TripletToSumInLinkList tts = new TripletToSumInLinkList(); tts.printTriplet(head, head1, head2, 20); } } ================================================ FILE: src/com/interview/misc/AddingTwoSetOfIntervals.java ================================================ package com.interview.misc; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class AddingTwoSetOfIntervals { public static class Pair implements Comparable{ int low; int high; Pair(int low,int high){ this.low = low; this.high = high; } @Override public int compareTo(Pair o) { if(this.low <= o.low){ return -1; }else{ return 1; } } public String toString(){ return low + " " + high; } } public List combineInterval(Pair[] arr1, Pair[] arr2){ Arrays.sort(arr1); Arrays.sort(arr2); List result = new ArrayList(); int i=0; int j=0; Pair current = new Pair(Integer.MIN_VALUE,Integer.MIN_VALUE+1); while(i < arr1.length && j < arr2.length){ if(arr1[i].low <= arr2[j].low){ if(arr1[i].low <= current.high){ current.high = Math.max(arr1[i].high,current.high); }else{ current = arr1[i]; result.add(current); } i++; } else{ if(arr2[j].low <= current.high){ current.high = Math.max(arr2[j].high,current.high); }else{ current = arr2[j]; result.add(current); } j++; } } while(i < arr1.length){ if(arr1[i].low <= current.high){ current.high = Math.max(current.high,arr1[i].high); }else{ current = arr1[i]; result.add(current); } i++; } while(j < arr2.length){ if(arr2[j].low <= current.high){ current.high = Math.max(current.high, arr2[j].high); }else{ current = arr2[j]; result.add(current); } j++; } return result; } public static void main(String args[]){ Pair p1 = new Pair(1,3); Pair p2 = new Pair(4,6); Pair p3 = new Pair(9,15); Pair p4 = new Pair(14,18); Pair[] arr1 = {p1,p2,p3,p4}; Pair r1 = new Pair(2,4); Pair r2 = new Pair(7,8); Pair r3 = new Pair(11,13); Pair[] arr2 = {r1,r2,r3}; AddingTwoSetOfIntervals ats = new AddingTwoSetOfIntervals(); List rs = ats.combineInterval(arr1, arr2); System.out.print(rs); } } ================================================ FILE: src/com/interview/misc/AngleBetweenHourAndMinuteHand.java ================================================ package com.interview.misc; /** * Find small angle between hour and minute hand in analog clock */ public class AngleBetweenHourAndMinuteHand { public double angle(int hour, int min){ double hourAngle = (hour%12)*360/12 + ((double)min/60)*(360/12); double minAngle = min*360/60; double angleDiff = Math.abs(hourAngle - minAngle); return angleDiff < 360 - angleDiff ? angleDiff : 360 - angleDiff; } public static void main(String args[]){ AngleBetweenHourAndMinuteHand abm = new AngleBetweenHourAndMinuteHand(); System.out.println(abm.angle(10, 15)); } } ================================================ FILE: src/com/interview/misc/BulbSwitcher.java ================================================ package com.interview.misc; /** * There are n bulbs that are initially off. You first turn on all the bulbs. * Then, you turn off every second bulb. On the third round, you toggle every third bulb (turning on if it's * off or turning off if it's on). For the ith round, you toggle every i bulb. For the nth round, you only * toggle the last bulb. Find how many bulbs are on after n rounds. * * https://leetcode.com/problems/bulb-switcher/ */ public class BulbSwitcher { public int bulbSwitch(int n) { int count = 0; while (count*count <= n) { count++; } return count - 1; } } ================================================ FILE: src/com/interview/misc/CandiesProblem.java ================================================ package com.interview.misc; /** * Date 2/7/16 * @author Tushar Roy * * * There are N children standing in a line. Each child is assigned a rating value. * You are giving candies to these children subjected to the following requirements: * Each child must have at least one candy. * Children with a higher rating get more candies than their neighbors. * What is the minimum candies you must give? * * * Time complexity - O(n) * Space complexity - O(1) * * Reference * https://leetcode.com/problems/candy/ * * */ public class CandiesProblem { public int minCandies(int ratings[]) { int pointOfChange = 0; int totalCandies = 1; int currentCandy = 1; boolean isIndependent = true; int maxHeight = 0; int diff = 0; for (int i = 1; i < ratings.length; i++) { diff = 0; //if the rating of ith guy is greater than rating of i-1 guy //then give ith guy one more candy than i-1 guy. if (ratings[i] > ratings[i-1]) { currentCandy += 1; } //if rating of ith guy is same as i-1 guy then give ith guy only 1 candy //because in same rating ith guy can get less candy. //But also mark that if need we can keep increasing candy given to ith //guy without affecting i-1 guy's candy since it can also go more than //i-1th guy candy as they have same rating. else if (ratings[i] == ratings[i-1]) { isIndependent = true; pointOfChange = i; currentCandy = 1; } //if rating of ith guy is less than i-1th guy then //give ith guy one candy. If i-1th guy has only one candy //then all the guys till point of change needs to be given one more candy //which is what diff takes care off. //if point of change guy is independent then we are cool otherwise //point of change needs to point to one less number if we reach its height. else { if (currentCandy == 1) { if (!isIndependent) { if (i - pointOfChange == maxHeight - 1) { pointOfChange--; } } } else { maxHeight = currentCandy; currentCandy = 1; isIndependent = false; pointOfChange = i; } diff = i - pointOfChange; } totalCandies += (diff + currentCandy); } return totalCandies; } public static void main(String args[]) { int input[] = {1,3,4,3,2,1}; CandiesProblem cp = new CandiesProblem(); System.out.println(cp.minCandies(input)); } } ================================================ FILE: src/com/interview/misc/ContainsNumberWithinKDistance.java ================================================ package com.interview.misc; import java.util.Map; import java.util.TreeMap; /** * Date 10/26/2016 * @author Tushar Roy * * Given an array of integers, * find out whether there are two distinct indices i and j in the array such that the difference * between nums[i] and nums[j] is at most t and the difference between i and j is at most k. * * Solution * Keep a tree map of num and its count. For every new number check if any number exists in map between * num - t and num + t. If yes than return true. If no then add this number to the tree map. Also if tree map * becomes of size k then drop the num[i - k] number from the tree map. * * Time complexity O(nlogk) * * https://leetcode.com/problems/contains-duplicate-iii/ */ public class ContainsNumberWithinKDistance { public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { if (nums.length == 0 || k == 0) { return false; } TreeMap map = new TreeMap<>(); for (int i = 0; i < nums.length; i++) { int lowerEntry = nums[i] - t - 1; int higherEntry = nums[i] + t + 1; Map.Entry higher = map.lowerEntry(higherEntry); if (higher != null && higher.getKey() >= nums[i]) { return true; } Map.Entry lower = map.higherEntry(lowerEntry); if (lower != null && lower.getKey() <= nums[i]) { return true; } if (map.size() == k) { map.compute(nums[i - k], (key, val) -> { if (val == 1) { return null; } else { return val - 1; } }); } map.compute(nums[i], (key, val) -> { if (val == null) { return 1; } else { return val + 1; } }); } return false; } } ================================================ FILE: src/com/interview/misc/ConvertNumberIntoBase26.java ================================================ package com.interview.misc; /** * Given a positive integer, return its corresponding column title as appear in an Excel sheet. * https://leetcode.com/problems/excel-sheet-column-title/ */ public class ConvertNumberIntoBase26 { public String numberToBase26(int n) { StringBuffer buff = new StringBuffer(); while (n > 0) { n--; buff.append((char)(n % 26 + 'A')); n = n / 26; } return buff.reverse().toString(); } public int base26ToNumber(String str) { int result = 0; int pow = 1; for(int i = str.length() - 1; i>=0; i--) { char s = str.charAt(i); s = (char)(s - 'A'+1); result += s*pow; pow *= 26; } return result; } public static void main(String args[]) { ConvertNumberIntoBase26 cni = new ConvertNumberIntoBase26(); System.out.println(cni.numberToBase26(704)); System.out.println(cni.base26ToNumber("AAB")); System.out.println(cni.numberToBase26(52)); System.out.println(cni.base26ToNumber("AZ")); System.out.println(cni.numberToBase26(13)); System.out.println(cni.base26ToNumber("M")); System.out.println(cni.numberToBase26(126)); System.out.println(cni.base26ToNumber("DV")); } } ================================================ FILE: src/com/interview/misc/CountRanges.java ================================================ package com.interview.misc; import java.util.HashMap; import java.util.Map; import java.util.NavigableMap; import java.util.TreeMap; /** * Date 03/03/2016 * @author Tushar Roy * * Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive. * * Time complexity O(nlogn) * Space complexity O(n) * * Performance can be improved by using self balancing BST which keeps the count of key and size of substree under it * * https://leetcode.com/problems/count-of-range-sum/ */ public class CountRanges { public int countRangeSum(int[] nums, int lower, int upper) { TreeMap map = new TreeMap<>(); Map countMap = new HashMap<>(); long prefixSum[] = new long[nums.length + 1]; map.put(0l, 1); countMap.put(0l, 1); int count = 0; for (int i = 0; i < nums.length; i++) { prefixSum[i+1] = prefixSum[i] + nums[i]; NavigableMap rangeMap = map.subMap(prefixSum[i+1] - upper, true, prefixSum[i+1] - lower, true); if (rangeMap.size() > 0) { for (int c : rangeMap.values()) { count += c; } } if (countMap.containsKey(prefixSum[i+1])) { countMap.put(prefixSum[i+1], countMap.get(prefixSum[i+1]) + 1); } else { countMap.put(prefixSum[i+1], 1); } map.put(prefixSum[i+1], countMap.get(prefixSum[i+1])); } return count; } public static void main(String args[]) { CountRanges cr = new CountRanges(); int[] input = {0, 0}; System.out.print(cr.countRangeSum(input, 0, 0)); } } ================================================ FILE: src/com/interview/misc/DayDifferenceBetweenTwoDates.java ================================================ package com.interview.misc; /** * Number of days between two valid dates * The idea is to get number of days from 00/00/0000 for both the dates and find the * difference between them. */ public class DayDifferenceBetweenTwoDates { private static final int days[] = {31,28,31,30,31,30,31,31,30,31,30,31}; public int diff(int year1,int month1, int day1,int year2, int month2,int day2){ int days1 = year1*365 + day1; int days2 = year2*365 + day2; for(int i=0; i < month1-1; i++){ days1 = days1 + days[i]; } for(int i=0; i < month2-1; i++){ days2 = days2 + days[i]; } days1 = days1 + (year1-1)/4 - (year1 -1)/100 + (year1 -1 )/400; days2 = days2 + (year2-1)/4 - (year2 -1)/100 + (year2 -1 )/400; if(isLeapYear(year1) && month1 > 2){ days1++; } if(isLeapYear(year2) && month2 > 2){ days2++; } return days2 - days1; } public static void main(String args[]){ DayDifferenceBetweenTwoDates dd = new DayDifferenceBetweenTwoDates(); System.out.println(dd.diff(1945, 3, 7, 2009, 8, 31)); } public boolean isLeapYear(int year){ if(year % 400 == 0){ return true; } if(year % 4 == 0 && year % 100 != 0){ return true; } return false; } } ================================================ FILE: src/com/interview/misc/DifferenceBetweenTwoTime.java ================================================ package com.interview.misc; /** * Given two times in four digits number e.g 10:10 is 1010 find difference between them * Test cases * Time 1 better be less than equal to time 2 * First 2 digits better be between 0 and 23 * Last 2 digits of number better be between 0 to 59 */ public class DifferenceBetweenTwoTime { public int diff(int time1, int time2){ if(time2 < time1){ throw new IllegalArgumentException(); } int hourDiff = time2/100 - time1/100 -1; int minDiff = time2%100 + (60 - time1%100); if(minDiff >= 60){ hourDiff++; minDiff = minDiff - 60; } return hourDiff*100 + minDiff; } public static void main(String args[]){ DifferenceBetweenTwoTime dbtt = new DifferenceBetweenTwoTime(); int time = dbtt.diff(1400, 1645); System.out.println(time); time = dbtt.diff(1223, 1246); System.out.println(time); time = dbtt.diff(1500, 1620); System.out.println(time); time = dbtt.diff(344, 936); System.out.println(time); time = dbtt.diff(1000, 1234); System.out.println(time); } } ================================================ FILE: src/com/interview/misc/FindingCelebrity.java ================================================ package com.interview.misc; /** * Find the Celebrity * https://leetcode.com/problems/find-the-celebrity/ */ class Relation { boolean knows(int a, int b) { return false; } } public class FindingCelebrity extends Relation { public int findCelebrity(int n) { int celebrity = 0; for (int i = 1; i < n; i++) { if (knows(celebrity, i)) { celebrity = i; } } for (int i = 0; i < n; i++) { if (i == celebrity) { continue; } if (knows(celebrity, i) || !knows(i, celebrity)) { return -1; } } return celebrity; } } ================================================ FILE: src/com/interview/misc/FloatPointConversion.java ================================================ package com.interview.misc; import java.util.StringTokenizer; /** * http://www.careercup.com/question?id=4901629824335872 * e.g * -99.01E-2 -> -.9901 * 845.67E2 -> 84567.0 */ public class FloatPointConversion { public double convert(String input){ boolean isNeg = false; if(input.startsWith("-")){ isNeg = true; input = input.substring(1); } StringTokenizer strtk = new StringTokenizer(input,"E"); String number = strtk.nextToken(); String power = strtk.nextToken(); double dNumber = toDouble(number); double dPower = toDouble(power); double pow = Math.pow(10, dPower); double result = dNumber * pow; return isNeg ? result * -1 : result; } private double toDouble(String number){ boolean isNeg = false; if(number.startsWith("-")){ isNeg = true; number = number.substring(1); } int result = 0; int pow = 1; boolean foundDot = false; for(char ch : number.toCharArray()){ if(ch == '.'){ foundDot = true; continue; } if(foundDot){ pow = pow*10; } result *= 10; result += (ch - '0'); } double doubleResult = (result*1.0)/pow; return isNeg ? doubleResult*-1 : doubleResult; } public static void main(String args[]){ FloatPointConversion fpc = new FloatPointConversion(); System.out.println(fpc.convert("-99.01E-2")); System.out.println(fpc.convert("845.67E2")); System.out.println(fpc.convert("99.01E-1")); } } ================================================ FILE: src/com/interview/misc/FourPointsFormSquare.java ================================================ package com.interview.misc; class Cordinate{ int x; int y; } /** * Given four points in any order determine if they form a square * Test cases * Less than or more than 4 points in input * Points could be in any quadrants e.it neg and pos allowed */ public class FourPointsFormSquare { public boolean isSquare(Cordinate[] cordinates){ Cordinate startPoint = cordinates[0]; int a1 = distanceSquare(startPoint, cordinates[1]); int a2 = distanceSquare(startPoint, cordinates[2]); int a3 = distanceSquare(startPoint, cordinates[3]); if(a1 == a2){ //then 0,3 is diagonal return compare(cordinates[3],cordinates[1],cordinates[2],a1,a3); }else if(a1 == a3){ return compare(cordinates[2],cordinates[1],cordinates[3],a1,a2); }else if(a2 == a3){ return compare(cordinates[1],cordinates[2],cordinates[3],a2,a1); }else{ return false; } } private boolean compare(Cordinate startPoint, Cordinate point1, Cordinate point2,int len, int diag){ if(2*len != diag){ return false; } int a1 = distanceSquare(startPoint,point1); int a2 = distanceSquare(startPoint,point2); if(a1 != len || a2 != len){ return false; } return true; } private int distanceSquare(Cordinate c1, Cordinate c2){ return (int)(Math.pow(Math.abs(c1.x - c2.x) ,2) + Math.pow(Math.abs(c1.y-c2.y), 2)); } public static void main(String args[]){ FourPointsFormSquare fpf = new FourPointsFormSquare(); Cordinate c1 = new Cordinate(); c1.x = 2; c1.y = 2; Cordinate c2 = new Cordinate(); c2.x = 6; c2.y = 2; Cordinate c3 = new Cordinate(); c3.x = 2; c3.y = -2; Cordinate c4 = new Cordinate(); c4.x = 6; c4.y = -2; Cordinate[] c = new Cordinate[4]; c[0] = c1; c[1] = c2; c[2] = c3; c[3] = c4; System.out.println(fpf.isSquare(c)); } } ================================================ FILE: src/com/interview/misc/GetKthPermutation.java ================================================ package com.interview.misc; import java.util.ArrayList; import java.util.List; /** * https://leetcode.com/problems/permutation-sequence/ */ public class GetKthPermutation { public String getPermutation(int n, int k) { List unused = new ArrayList<>(); for (int i = 1; i <= n; i++) { unused.add(i); } StringBuffer result = new StringBuffer(); int fac = factorial(n); int d = n; while (n > 1) { fac = fac/d; d--; int index = (int)Math.ceil((double)k/fac); result.append(unused.get(index - 1)); unused.remove(index - 1); n--; k = k - fac*(index - 1); } if (n == 0) { for (int i = unused.size() - 1; i >= 0; i--) { result.append(unused.get(i)); } } if (n == 1) { for (int i = 0; i < unused.size(); i++) { result.append(unused.get(i)); } } return result.toString(); } private int factorial(int n) { int result = 1; for (int i = 1; i <= n; i++) { result *= i; } return result; } public static void main(String args[]) { GetKthPermutation gp = new GetKthPermutation(); System.out.println(gp.getPermutation(6, 343)); } } ================================================ FILE: src/com/interview/misc/HammingDistanceBetweenPair.java ================================================ package com.interview.misc; /** * http://www.glassdoor.com/Interview/-a-first-write-a-function-to-calculate-the-hamming-distance-between-two-binary-numbers-b-write-a-function-that-takes-QTN_450885.htm * Test cases * Not equal length strings * String containing anything other than 0 and 1 */ public class HammingDistanceBetweenPair { public int hammingDistance(String input[]){ int size = input[0].length(); int total = 0; for(int i=0; i < size; i++){ int count0s = 0; int count1s = 0; for(String str : input){ if(str.charAt(i) == '0'){ count0s++; }else{ count1s++; } } total += count0s * count1s; } return total; } public static void main(String args[]){ String input[] = {"10011","00011","11101","01010"}; HammingDistanceBetweenPair hdb = new HammingDistanceBetweenPair(); System.out.println(hdb.hammingDistance(input)); } } ================================================ FILE: src/com/interview/misc/InsertInterval.java ================================================ package com.interview.misc; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; /** * Date 03/21/2016 * @author Tushar Roy * * Insert internal into sorted intervals and merge them. * * Time complexity O(n) * * https://leetcode.com/problems/insert-interval/ */ public class InsertInterval { public static class Interval { int start; int end; @Override public String toString() { return "Interval{" + "start=" + start + ", end=" + end + '}'; } Interval(int s, int e) { start = s; end = e; } } public List insert(List intervals, Interval newInterval) { List result = new ArrayList<>(); boolean alreadyAdded = false; for (int i = 0; i < intervals.size(); i++) { if ((intervals.get(i).end < newInterval.start)) { result.add(intervals.get(i)); } else if (intervals.get(i).start > newInterval.end) { if (!alreadyAdded) { result.add(newInterval); alreadyAdded = true; } result.add(intervals.get(i)); } else { newInterval.start = Math.min(newInterval.start, intervals.get(i).start); newInterval.end = Math.max(newInterval.end, intervals.get(i).end); if (!alreadyAdded) { result.add(newInterval); alreadyAdded = true; } } } if (!alreadyAdded) { result.add(newInterval); } return result; } public static void main(String args[]) { Interval i1 = new Interval(1,3); Interval i2 = new Interval(6,7); Interval i3 = new Interval(9,10); Interval i4 = new Interval(11,12); List input = new ArrayList<>(); input.add(i1); input.add(i2); input.add(i3); input.add(i4); InsertInterval ii = new InsertInterval(); System.out.println(ii.insert(input, new Interval(13, 15))); } } ================================================ FILE: src/com/interview/misc/IntegerListParser.java ================================================ package com.interview.misc; import java.util.ArrayList; import java.util.List; import java.util.Stack; /** * Date 10/10/2016 * @author Tushar Roy * * Given a nested list of integers represented as a string, implement a parser to deserialize it. * Each element is either an integer, or a list -- whose elements may also be integers or other lists. * * https://leetcode.com/problems/mini-parser/ */ public class IntegerListParser { public NestedInteger deserialize(String s) { Stack stack = new Stack(); NestedInteger current = null; StringBuffer subInteger = new StringBuffer(); for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '[') { if (current != null) { stack.push(current); } current = new NestedInteger(); subInteger = new StringBuffer(); } else if (s.charAt(i) == ']') { if (subInteger.length() > 0) { current.add(new NestedInteger(Integer.parseInt(subInteger.toString()))); subInteger = new StringBuffer(); } if (!stack.isEmpty()) { NestedInteger top = stack.pop(); top.add(current); current = top; } } else if (s.charAt(i) == ',') { if (subInteger.length() > 0) { current.add(new NestedInteger(Integer.parseInt(subInteger.toString()))); } subInteger = new StringBuffer(); } else { subInteger.append(s.charAt(i)); } } if (subInteger.length() > 0) { return new NestedInteger(Integer.parseInt(subInteger.toString())); } return current; } public String serialize(NestedInteger nestedInteger) { StringBuffer result = new StringBuffer(); serialize(nestedInteger, result); return result.toString(); } private void serialize(NestedInteger nestedInteger, StringBuffer result) { if (nestedInteger.isInteger()) { result.append(nestedInteger.getInteger()); return; } boolean isFirst = true; result.append("["); for (NestedInteger ni : nestedInteger.getList()) { if (!isFirst) { result.append(","); } isFirst = false; if (ni.isInteger()) { result.append(ni.getInteger()); } else { serialize(ni, result); } } result.append("]"); } public static void main(String args[]) { IntegerListParser integerListParser = new IntegerListParser(); NestedInteger nestedInteger = integerListParser.deserialize("123"); String result = integerListParser.serialize(nestedInteger); System.out.println(result); nestedInteger = integerListParser.deserialize("[]"); result = integerListParser.serialize(nestedInteger); System.out.println(result); nestedInteger = integerListParser.deserialize("[123]"); result = integerListParser.serialize(nestedInteger); System.out.println(result); nestedInteger = integerListParser.deserialize("[123,41]"); result = integerListParser.serialize(nestedInteger); System.out.println(result); nestedInteger = integerListParser.deserialize("[123,41,[1]]"); result = integerListParser.serialize(nestedInteger); System.out.println(result); nestedInteger = integerListParser.deserialize("[123,41,[[[]]]]"); result = integerListParser.serialize(nestedInteger); System.out.println(result); nestedInteger = integerListParser.deserialize("[123,41,[[[],[]]]],[],[]"); result = integerListParser.serialize(nestedInteger); System.out.println(result); nestedInteger = integerListParser.deserialize("[123,41,[[[121,41,[1]],[2]]]],[2],[4]"); result = integerListParser.serialize(nestedInteger); System.out.println(result); nestedInteger = integerListParser.deserialize("[123,41,[[1,2,[],[]]]],[],[],[[1],[3]]"); result = integerListParser.serialize(nestedInteger); System.out.println(result); } class NestedInteger { private List nestedInteger = new ArrayList<>(); private Integer val; public NestedInteger() { } public NestedInteger(int value) { this.val = value; } public boolean isInteger() { return val != null; } public Integer getInteger() { return val; } public void setInteger(int value) { this.val = value; } public void add(NestedInteger ni) { this.nestedInteger.add(ni); } public List getList() { return val != null ? null : nestedInteger; } } } ================================================ FILE: src/com/interview/misc/KthLargestInRowiseColumnWiseSorted2DArray.java ================================================ package com.interview.misc; import com.interview.graph.BinaryMinHeap; /** * Kth largest in rowwise and column wise sorted array * http://www.geeksforgeeks.org/kth-smallest-element-in-a-row-wise-and-column-wise-sorted-2d-array-set-1/ */ public class KthLargestInRowiseColumnWiseSorted2DArray { public int kthLargest(int input[][],int k){ BinaryMinHeap minHeap = new BinaryMinHeap(); int c = input[0].length; int total = input.length * c; minHeap.add(input[0][0], 0); for(int i=1; i < k; i++){ int minIndex = minHeap.extractMin(); int minRow = minIndex/c; int minCol = minIndex%c; int downNeighbor = (minRow+1)*c + minCol; int rightNeighbor; if(minCol== (c-1)){ rightNeighbor = total; }else{ rightNeighbor = minRow*c + (minCol + 1); } if(downNeighbor < total && !minHeap.containsData(downNeighbor)){ minHeap.add(input[minRow+1][minCol], downNeighbor); } if(rightNeighbor < total && !minHeap.containsData(rightNeighbor)){ minHeap.add(input[minRow][minCol+1], rightNeighbor); } } int minIndex = minHeap.extractMin(); return input[minIndex/c][minIndex%c]; } public static void main(String args[]){ int input[][] ={{1,5,11,21}, {6,8,12,22}, {7,9,15,26}, {11,13,18,28}}; KthLargestInRowiseColumnWiseSorted2DArray kl = new KthLargestInRowiseColumnWiseSorted2DArray(); System.out.println(kl.kthLargest(input, 10)); } } ================================================ FILE: src/com/interview/misc/LoadBalancers.java ================================================ package com.interview.misc; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class LoadBalancers { private List servers = new ArrayList(); Map index = new HashMap(); public void addServer(String name){ servers.add(name); index.put(name, servers.size()-1); } public void removeServer(String name){ Integer pos = index.get(name); if(pos == null){ throw new IllegalArgumentException(); } servers.set(pos, servers.get(servers.size()-1)); servers.remove(servers.size()-1); } public String getRandom(){ int r = (int)(Math.random()*1000); return servers.get(r%servers.size()); } public static void main(String args[]){ LoadBalancers lb = new LoadBalancers(); lb.addServer("1"); lb.addServer("2"); lb.addServer("3"); lb.addServer("4"); lb.addServer("5"); System.out.print(lb.getRandom()); System.out.print(lb.getRandom()); System.out.print(lb.getRandom()); System.out.print(lb.getRandom()); lb.removeServer("3"); lb.removeServer("1"); System.out.print(lb.getRandom()); System.out.print(lb.getRandom()); System.out.print(lb.getRandom()); System.out.print(lb.getRandom()); } } ================================================ FILE: src/com/interview/misc/NestedIterator.java ================================================ package com.interview.misc; import java.util.Deque; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Stack; /** * Date 04/17/2017 * @author Tushar Roy * * Given a nested list of integers, implement an iterator to flatten it. * Each element is either an integer, or a list -- whose elements may also be integers or other lists. * Example 1: * Given the list [[1,1],2,[1,1]], * By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,1,2,1,1]. * * https://leetcode.com/problems/flatten-nested-list-iterator/ */ public class NestedIterator implements Iterator { Stack> stack = new Stack<>(); Integer nextVal = null; public NestedIterator(List nestedList) { stack.push(nestedList.iterator()); } @Override public Integer next() { if (!hasNext()) { throw new IllegalArgumentException(); } Integer val = nextVal; nextVal = null; return val; } @Override public boolean hasNext() { if (nextVal != null) { return true; } while (!stack.isEmpty()) { boolean pushedIntoStack = false; Iterator itr = stack.peek(); if (itr.hasNext()) { NestedInteger ni = itr.next(); if (ni.isInteger()) { nextVal = ni.getInteger(); return true; } else { pushedIntoStack = true; stack.push(ni.getList().iterator()); } } if (!pushedIntoStack) { stack.pop(); } } return false; } } interface NestedInteger { boolean isInteger(); Integer getInteger(); List getList(); } ================================================ FILE: src/com/interview/misc/NumberToWord.java ================================================ package com.interview.misc; /** * Convert a number into words * * Reference * https://leetcode.com/problems/integer-to-english-words/ */ public class NumberToWord { private static int BILLION = 1000000000; private static int MILLION = 1000000; private static int THOUSAND = 1000; public String numberToWords(int number){ StringBuffer buffer = new StringBuffer(); if(number ==0){ return toString(number).trim(); } if(number < 0){ buffer.append("Minus"); number = number *-1; } if (number >= BILLION) { int first = number / BILLION; number = number % BILLION; buffer.append(hundredsPart(first)).append(toString(BILLION)); } if(number >= MILLION){ int first = number /MILLION; number = number % MILLION; buffer.append(hundredsPart(first)).append(toString(MILLION)); } if(number >= THOUSAND){ int first = number /THOUSAND; number = number % THOUSAND; buffer.append(hundredsPart(first)).append(toString(THOUSAND)); } buffer.append(hundredsPart(number)); return buffer.toString().trim(); } private String hundredsPart(int number){ StringBuffer buffer = new StringBuffer(); if(number != 0){ if(number <= 99){ buffer.append(tenthPart(number)); }else{ int first = (number /100); int second = number % 100; buffer.append(toString(first) + toString(100)); if (second != 0){ buffer.append(tenthPart(second)); } } return buffer.toString(); }else{ return ""; } } private String tenthPart(int number){ StringBuffer buffer = new StringBuffer(); if(number != 0){ if(number <= 19){ buffer.append(toString(number)); }else{ int first = (number/10)*10; int second = number%10; buffer.append(toString(first)); if (second != 0){ buffer.append(toString(second)); } } return buffer.toString(); }else{ return ""; } } private String toString(int number){ switch(number){ case 0: return " Zero"; case 1: return " One"; case 2: return " Two"; case 3: return " Three"; case 4: return " Four"; case 5: return " Five"; case 6: return " Six"; case 7: return " Seven"; case 8: return " Eight"; case 9: return " Nine"; case 10: return " Ten"; case 11: return " Eleven"; case 12: return " Twelve"; case 13: return " Thrirteen"; case 14: return " Fourteen"; case 15: return " Fifteen"; case 16: return " Sixteen"; case 17: return " Seventeen"; case 18: return " Eighteen"; case 19: return " Nineteen"; case 20: return " Twenty"; case 30: return " Thirty"; case 40: return " Forty"; case 50: return " Fifty"; case 60: return " Sixty"; case 70: return " Seventy"; case 80: return " Eighty"; case 90: return " Ninety"; case 100: return " Hundred"; case 1000: return " Thousand"; case 1000000: return " Million"; case 1000000000: return " Billion"; default: throw new IllegalArgumentException(); } } public static void main(String args[]){ NumberToWord ntw = new NumberToWord(); System.out.println(ntw.numberToWords(8000)); System.out.println(ntw.numberToWords(8192)); System.out.println(ntw.numberToWords(8112)); System.out.println(ntw.numberToWords(504)); System.out.println(ntw.numberToWords(565100)); System.out.println(ntw.numberToWords(6721157)); System.out.println(ntw.numberToWords(-106721157)); System.out.println(ntw.numberToWords(106070571)); System.out.println(ntw.numberToWords(-92)); System.out.println(ntw.numberToWords(0)); System.out.println(ntw.numberToWords(1212121451)); } } ================================================ FILE: src/com/interview/misc/PrimeNumbersBeforeN.java ================================================ package com.interview.misc; import java.util.ArrayList; import java.util.List; /** * All prime numbers before n */ public class PrimeNumbersBeforeN { public List primeNumbers(int n){ List result = new ArrayList(); result.add(2); boolean flag = false; for(int i=3; i < n; i+=2){ for(int r : result){ if(2*r > i){ break; } if(i % r == 0){ flag = true; break; } } if(!flag){ result.add(i); } flag = false; } return result; } public static void main(String args[]){ PrimeNumbersBeforeN pnb = new PrimeNumbersBeforeN(); List result = pnb.primeNumbers(150); result.forEach(i -> System.out.print(i + " ")); } } ================================================ FILE: src/com/interview/misc/Read4Function.java ================================================ package com.interview.misc; import java.util.Arrays; /** * Date 03/26/2016 * @author Tushar Roy * * Given a reader which only reads 4 bytes implement a Reader which can read bytes of give size. * * Reference * Read N Characters Given Read4 II * https://leetcode.com/problems/read-n-characters-given-read4-ii-call-multiple-times/ */ class Read4 { int read4(char[] buff) { buff[0] = 'a'; buff[1] = 'b'; buff[2] = 'c'; buff[3] = 'd'; return 4; } } public class Read4Function extends Read4{ class Queue { int start; int end; int count; char[] data; int size; Queue(int size) { data = new char[size]; this.size = size; } boolean isEmpty() { return count == 0; } void offer(char b) { data[start] = b; start = (start + 1)%size; count++; } char poll() { char d = data[end]; end = (end + 1)%size; count--; return d; } } private final Queue queue; public Read4Function() { queue = new Queue(4); } public int read(char[] buf, int n) { int r = 0; while (!queue.isEmpty() && r < n) { buf[r++] = queue.poll(); } if (r == n) { return r; } int index = 0; int readSize = 0; char[] input = null; do { input = new char[4]; readSize = read4(input); index = 0; while(r < n && index < readSize) { buf[r++] = input[index++]; } } while (readSize == 4 && r < n); while (index < readSize) { queue.offer(input[index++]); } return r; } public static void main(String args[]) { Read4Function rf = new Read4Function(); char[] buff = new char[10]; int size = rf.read(buff, 2); System.out.print(size); System.out.println(Arrays.toString(buff)); size = rf.read(buff, 1); System.out.print(size); System.out.println(Arrays.toString(buff)); size = rf.read(buff, 1); System.out.print(size); System.out.println(Arrays.toString(buff)); } } ================================================ FILE: src/com/interview/misc/RomanNumberToDecimal.java ================================================ package com.interview.misc; /** * Convert a roman number to decimal number * Test cases: smaller number appearing before bigger number unless it is representing one less. * VL is incorrect since XL should be used to represent 90 * chars not used in roman representation is used * http://www.onlineconversion.com/roman_numerals_advanced.htm * */ public class RomanNumberToDecimal { public String converToRoman(int decimal){ StringBuffer buffer = new StringBuffer(); while(decimal > 0){ decimal = literal(decimal,buffer); } return buffer.toString(); } public int convertToDecimal(char[] roman){ int decimal = 0; for(int i=0; i < roman.length; ){ if(i < roman.length-1 && literal(roman[i]) < literal(roman[i+1])){ decimal += literal(roman[i+1]) - literal(roman[i]); i += 2; }else{ decimal += literal(roman[i]); i++; } } return decimal; } private int literal(int decimal,StringBuffer buffer){ if(decimal >= 1000){ buffer.append("M"); decimal -= 1000; return decimal; } else if(decimal >= 900){ buffer.append("CM"); decimal -= 900; return decimal; } else if(decimal >= 500){ buffer.append("D"); decimal -= 500; return decimal; } else if(decimal >= 400){ buffer.append("CD"); decimal -= 400; return decimal; } else if(decimal >= 100){ buffer.append("C"); decimal -= 100; return decimal; } else if(decimal >= 90){ buffer.append("XC"); decimal -= 90; return decimal; } else if(decimal >= 50){ buffer.append("L"); decimal -= 50; return decimal; } else if(decimal >= 40){ buffer.append("XL"); decimal -= 40; return decimal; } else if(decimal >= 10){ buffer.append("X"); decimal -= 10; return decimal; }else if(decimal >= 9){ buffer.append("IX"); decimal -= 9; return decimal; } else if(decimal >=5){ buffer.append("V"); decimal -= 5; return decimal; }else if(decimal >= 4){ buffer.append("IV"); decimal -= 4; return decimal; }else { buffer.append("I"); decimal -= 1; return decimal; } } private int literal(char ch){ switch(ch){ case 'I' : return 1; case 'V' : return 5; case 'X' : return 10; case 'L' : return 50; case 'C' : return 100; case 'D' : return 500; case 'M' : return 1000; default : throw new IllegalArgumentException(); } } public static void main(String args[]){ RomanNumberToDecimal rnd = new RomanNumberToDecimal(); System.out.println(rnd.convertToDecimal("XX".toCharArray())); System.out.println(rnd.convertToDecimal("XCIX".toCharArray())); System.out.println(rnd.convertToDecimal("MLXIX".toCharArray())); System.out.println(rnd.convertToDecimal("MMDXLIII".toCharArray())); System.out.println(rnd.converToRoman(20)); System.out.println(rnd.converToRoman(99)); System.out.println(rnd.converToRoman(1069)); System.out.println(rnd.converToRoman(2543)); } } ================================================ FILE: src/com/interview/misc/SparseTableRangeMinimumQuery.java ================================================ package com.interview.misc; /** * Date 04/28/2016 * @author Tushar Roy * * Find range minimum query using sparse table. * * Preprocessing Time complexity O(nlogn) * Query Time complexity O(1) * Space complexity O(nlogn) * * Reference - * https://www.topcoder.com/community/data-science/data-science-tutorials/range-minimum-query-and-lowest-common-ancestor/ */ public class SparseTableRangeMinimumQuery { private final int[][] sparse; private final int n; private final int[] input; public SparseTableRangeMinimumQuery(int[] input) { this.input = input; this.n = input.length; this.sparse = preprocess(input, this.n); } private int[][] preprocess(int[] input, int n) { int[][] sparse = new int[n][log2(n) + 1]; for (int i = 0; i < input.length; i++) { sparse[i][0] = i; } for (int j = 1; 1 << j <= n; j++) { for (int i = 0; i + (1 << j) - 1 < n; i++) { if (input[sparse[i][j - 1]] < input[sparse[i + (1 << (j - 1))][j - 1]]) { sparse[i][j] = sparse[i][j - 1]; } else { sparse[i][j] = sparse[i + (1 << (j - 1))][j - 1]; } } } return sparse; } public int rangeMinimumQuery(int low, int high) { int l = high - low + 1; int k = log2(l); if (input[sparse[low][k]] <= input[sparse[low + l - (1<= board.length) { break; } if (j < 0 || j >= board[0].length) { continue; } count += board[i][j]; } } if (board[x][y] == 1) { return count == 2 || count == 3; } else { return count == 3; } } } ================================================ FILE: src/com/interview/multiarray/LongestConsecutiveIntegerInUnsorted2DArray.java ================================================ package com.interview.multiarray; /** * Find the length of the longest chain of consecutive integers in an unsorted 2D square array (non-diagonal) */ public class LongestConsecutiveIntegerInUnsorted2DArray { public int longestConsecutiveInteger(int input[][]){ boolean visited[][] = new boolean[input.length][input[0].length]; int max = 1; for(int i=0; i < input.length; i++){ for(int j=0; j < input[i].length; j++){ int r = DFS(input,i,j,visited,-10000); if(r > max){ max = r; } } } return max; } private int DFS(int input[][],int i,int j,boolean visited[][],int lastNum){ if(i >= input.length || i < 0 || j < 0 || j >= input[0].length){ return 0; } if(visited[i][j]){ return 0; } if(lastNum != -10000 && input[i][j] + 1 != lastNum){ return 0; } visited[i][j] = true; int r1 = DFS(input,i+1,j,visited,input[i][j]); int r2 = DFS(input,i-1,j,visited,input[i][j]); int r3 = DFS(input,i,j+1,visited,input[i][j]); int r4 = DFS(input,i,j-1,visited,input[i][j]); visited[i][j] = false; return Math.max(Math.max(r1, r2), Math.max(r3,r4)) + 1; } public static void main(String args[]){ LongestConsecutiveIntegerInUnsorted2DArray lci = new LongestConsecutiveIntegerInUnsorted2DArray(); int input[][] = {{3,2,5}, {4,1,4}, {5,6,5}}; System.out.println(lci.longestConsecutiveInteger(input)); } } ================================================ FILE: src/com/interview/multiarray/MatrixCalculation.java ================================================ package com.interview.multiarray; public class MatrixCalculation { private int r = 0; public String[][] crossMultiply(String[][] str){ int cols = 1; for(int i=1; i < str.length; i++){ cols = cols*str[i].length; } String[][] result = new String[str[0].length][cols]; for(int i=0; i < str[0].length ; i++){ StringBuffer buffer = new StringBuffer(); r=0; buffer.append(str[0][i]); recur(buffer,result,str,1,i); } return result; } private void recur(StringBuffer buffer,String[][] result,String[][] str,int currentRow,int mainCol){ if(currentRow == str.length){ result[mainCol][r++] = buffer.toString(); return; } for(int i=0; i < str[currentRow].length; i++){ StringBuffer tempBuffer = new StringBuffer(buffer); buffer.append(str[currentRow][i]); recur(buffer,result,str,currentRow+1,mainCol); buffer = tempBuffer; } } public static void main(String args[]){ MatrixCalculation mc = new MatrixCalculation(); String[][] str = {{"abc","def","gh"},{"l","m"},{"p","q","r"},{"x","y"}}; String[][] result = mc.crossMultiply(str); for(int i=0; i < result.length; i++){ for(int j=0; j < result[i].length; j++){ System.out.print(result[i][j] + " "); } System.out.println(); } } } ================================================ FILE: src/com/interview/multiarray/MatrixFindAllSubSquareRectangleMatrix.java ================================================ package com.interview.multiarray; /** * Iterate through matrix and get all subsquare and subrectangle matrix and print their sum */ public class MatrixFindAllSubSquareRectangleMatrix { public void printSumOfAllSquareMatrix(int input[][]){ for(int len = 1; len <= input.length; len++){ for(int i=0; i < input.length - len + 1; i++){ for(int j=0; j < input[i].length - len + 1; j++){ int sum = 0; for(int k=i;k < i+len; k++){ for(int m = j; m < j+len; m++){ sum += input[k][m]; } } System.out.println("Start " + i + " " + j + " End " + len + " sum " + sum); } } } } public void printSumOfAllRectangleMatrix(int input[][]){ for(int rlen = 1 ; rlen <= input.length; rlen++){ for(int clen = 1; clen <= input[0].length; clen++){ for(int i=0; i < input.length - rlen + 1; i++){ for(int j=0; j < input[i].length - clen + 1; j++){ int sum = 0; for(int k=i;k < i+rlen; k++){ for(int m = j; m < j+clen; m++){ sum += input[k][m]; } } System.out.println("Start " + i + " " + j + " End " + (i + rlen-1) + " " + (j + clen-1) + " sum " + sum); } } } } } public static void main(String args[]){ int input[][] = {{1,2,3}, {4,5,6}, {7,8,9}}; MatrixFindAllSubSquareRectangleMatrix mal = new MatrixFindAllSubSquareRectangleMatrix(); mal.printSumOfAllRectangleMatrix(input); } } ================================================ FILE: src/com/interview/multiarray/MatrixInDiagonalOrder.java ================================================ package com.interview.multiarray; /** * http://www.geeksforgeeks.org/print-matrix-diagonally/ */ public class MatrixInDiagonalOrder { public void printMatrix(int [][]matrix){ for(int i=0; i < matrix.length; i++){ int start =i; int end =0; while(start >= 0 && end < matrix[0].length){ System.out.print(matrix[start][end] + " "); start--; end++; } System.out.print("\n"); } for(int i=1; i < matrix[0].length; i++){ int start = matrix.length-1; int end =i; while(start >= 0 && end < matrix[0].length){ System.out.print(matrix[start][end] + " "); start--; end++; } System.out.print("\n"); } } public static void main(String args[]){ int arr[][] = {{1,2,3,4},{1,2,3,4},{1,2,3,4},{1,2,3,4},{1,2,3,4}}; MatrixInDiagonalOrder mdo = new MatrixInDiagonalOrder(); mdo.printMatrix(arr); } } ================================================ FILE: src/com/interview/multiarray/MatrixOf0sAnd1s.java ================================================ package com.interview.multiarray; /** * http://www.geeksforgeeks.org/create-a-matrix-with-alternating-rectangles-of-0-and-x/ * Test case : negative or 0 for n or m */ public class MatrixOf0sAnd1s { public char[][] create(int n,int m){ char[][] matrix = new char[n][m]; int r = 0; char ch = 'X'; int high = Math.min(n, m); //high is min of n and m. If high is odd then high is ceiling of high/2 //else high is high/2. e.g high is 5 then high becomes 3 if high is 4 //high becomes 2 high = (int)Math.ceil(high*1.0/2); while(r < high){ for(int i=r; i < m-r ; i++){ matrix[r][i] = ch; } for(int i = r; i < n-r; i++ ){ matrix[i][m-r-1] = ch; } for(int i = m-r-1; i >= r; i-- ){ matrix[n-r-1][i] = ch; } for(int i = n-r-1; i >= r; i-- ){ matrix[i][r] = ch; } if(ch =='X'){ ch = 'O'; }else{ ch = 'X'; } r++; } return matrix; } public static void main(String args[]){ MatrixOf0sAnd1s mos = new MatrixOf0sAnd1s(); char matrix[][] = mos.create(4, 7); for(int i=0; i < matrix.length; i++){ for(int j=0; j < matrix[i].length; j++){ System.out.print(matrix[i][j] + " "); } System.out.println(); } } } ================================================ FILE: src/com/interview/multiarray/MoveCellPerCellValue.java ================================================ package com.interview.multiarray; /** * http://www.careercup.com/question?id=6685828805820416 * Test Edge cases * Values in cell should be in range of 2D array. */ class Cell{ int x; int y; Cell(int x,int y){ this.x = x; this.y = y; } } public class MoveCellPerCellValue { public boolean isAllCellTraversed(Cell grid[][]){ boolean[][] visited = new boolean[grid.length][grid[0].length]; int total = grid.length * grid[0].length; int startx = grid[0][0].x; int starty = grid[0][0].y; for(int i=0; i < total-2; i++){ if(grid[startx][starty] == null){ return false; } if(visited[startx][starty] == true){ return false; } visited[startx][starty] = true; int x = grid[startx][starty].x; int y = grid[startx][starty].y; startx = x; starty = y; } if(grid[startx][starty] == null){ return true; } return false; } public static void main(String args[]){ Cell cell[][] = new Cell[3][2]; cell[0][0] = new Cell(0,1); cell[0][1] = new Cell(2,0); cell[1][0] = null; cell[1][1] = new Cell(1,0); cell[2][0] = new Cell(2,1); cell[2][1] = new Cell(1,1); MoveCellPerCellValue mcp = new MoveCellPerCellValue(); System.out.println(mcp.isAllCellTraversed(cell)); } } ================================================ FILE: src/com/interview/multiarray/Mutable2DSumRangeQuery.java ================================================ package com.interview.multiarray; /** * * Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner * (row1, col1) and lower right corner (row2, col2). * * https://leetcode.com/problems/range-sum-query-2d-mutable/ */ public class Mutable2DSumRangeQuery { private int[][] prefixSum; private int rows; private int cols; private int[][] matrix; public Mutable2DSumRangeQuery(int[][] matrix) { if (matrix.length == 0) { return; } prefixSum = new int[matrix.length][matrix[0].length + 1]; this.matrix = matrix; rows = matrix.length; cols = matrix[0].length; for (int i = 0; i < rows; i++) { for (int j = 1; j <= cols; j++) { prefixSum[i][j] = prefixSum[i][j - 1] + matrix[i][j - 1]; } } } public void update(int row, int col, int val) { int delta = val - matrix[row][col]; matrix[row][col] = val; for (int i = col + 1; i <= cols; i++) { prefixSum[row][i] += delta; } } public int sumRegion(int row1, int col1, int row2, int col2) { int sum = 0; for (int i = row1; i <= row2; i++) { sum += prefixSum[i][col2 + 1] - prefixSum[i][col1]; } return sum; } } ================================================ FILE: src/com/interview/multiarray/RotateImage.java ================================================ package com.interview.multiarray; /** * Date 07/31/2016 * @author Tushar Roy * * You are given an n x n 2D matrix representing an image. * Rotate the image by 90 degrees (clockwise). * * https://leetcode.com/problems/rotate-image/ */ public class RotateImage { public void rotate(int[][] matrix) { int length = matrix.length-1; int j=0; while(j < matrix.length/2){ for(int i=j; i < length-j; i++){ int temp = matrix[j][i]; matrix[j][i] = matrix[length-i][j]; matrix[length-i][j] = matrix[length-j][length-i]; matrix[length-j][length-i] = matrix[i][length-j]; matrix[i][length-j] = temp; } j++; } } private void print(int arr[][]){ for(int i=0; i < arr.length; i++){ for(int j=0; j < arr.length; j++){ System.out.print(arr[i][j] + " "); } System.out.print("\n"); } } public static void main(String args[]){ int matrix[][] = {{1,2,3,4,20},{5,6,7,8,30},{9,10,11,12,40},{13,14,15,16,50},{21,22,23,24,25}}; RotateImage ti = new RotateImage(); ti.rotate(matrix); ti.print(matrix); } } ================================================ FILE: src/com/interview/multiarray/ShortestDistanceFromAllBuildings.java ================================================ package com.interview.multiarray; import java.util.ArrayList; import java.util.Deque; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.Set; /** * Date 03/25/2016 * @author Tushar Roy * * Shortest Distance from All Buildings * https://leetcode.com/problems/shortest-distance-from-all-buildings/ */ public class ShortestDistanceFromAllBuildings { private class Point { int x, y, dist = 0; Point(int row, int col, int dist) { x = row; y = col; this.dist = dist; } } public int shortestDistance(int[][] grid) { int totalBuild = 0; int[][] reach = new int[grid.length][grid[0].length]; int[][] distance = new int[grid.length][grid[0].length]; for(int i = 0; i < grid.length; i++) { for(int j = 0; j < grid[0].length; j++) { if(grid[i][j] == 1) { Queue queue = new LinkedList<>(); queue.offer(new Point(i, j, 0)); totalBuild++; boolean[][] visited = new boolean[grid.length][grid[0].length]; while (!queue.isEmpty()) { List neighbors = getNeighbors(queue.poll(), grid, visited, grid.length, grid[0].length); for (Point neigh : neighbors) { visited[neigh.x][neigh.y] = true; reach[neigh.x][neigh.y]++; distance[neigh.x][neigh.y] += neigh.dist; queue.offer(neigh); } } } } } int min = Integer.MAX_VALUE; for (int i = 0; i < reach.length; i++) { for (int j = 0; j < reach[0].length; j++) { if (reach[i][j] == totalBuild) { min = Math.min(min, distance[i][j]); } } } return min == Integer.MAX_VALUE ? -1 : min; } private List getNeighbors(Point p, int[][] grid, boolean[][] visited, int n, int m) { List resultList = new ArrayList<>(); if(p.x > 0 && grid[p.x -1][p.y] == 0 && !visited[p.x - 1][p.y]) resultList.add(new Point(p.x -1, p.y, p.dist + 1)); if(p.x < n - 1 && grid[p.x + 1][p.y] == 0 && !visited[p.x + 1][p.y]) resultList.add(new Point(p.x + 1, p.y, p.dist + 1)); if(p.y > 0 && grid[p.x][p.y - 1] == 0 && !visited[p.x][p.y - 1]) resultList.add(new Point(p.x, p.y - 1, p.dist + 1)); if(p.y < m - 1 && grid[p.x][p.y + 1] == 0 && !visited[p.x][p.y + 1]) resultList.add(new Point(p.x, p.y + 1, p.dist + 1)); return resultList; } public static void main(String args[]) { int[][] grid = {{1,1,1,1,1,0},{0,0,0,0,0,1},{0,1,1,0,0,1},{1,0,0,1,0,1},{1,0,1,0,0,1},{1,0,0,0,0,1},{0,1,1,1,1,0}}; int[][] grid1 = {{1,1},{0,1}}; ShortestDistanceFromAllBuildings shortestDistanceFromAllBuildings = new ShortestDistanceFromAllBuildings(); System.out.println(shortestDistanceFromAllBuildings.shortestDistance(grid)); } } ================================================ FILE: src/com/interview/multiarray/SmallestRectangleBlackPixel.java ================================================ package com.interview.multiarray; /** * An image is represented by a binary matrix with 0 as a white pixel and 1 as a black pixel. * The black pixels are connected, i.e., there is only one black region. Pixels are connected horizontally * and vertically. Given the location (x, y) of one of the black pixels, return the area of the smallest * (axis-aligned) rectangle that encloses all black pixels. * https://leetcode.com/problems/smallest-rectangle-enclosing-black-pixels/ */ public class SmallestRectangleBlackPixel { public int minArea(char[][] image, int x, int y) { int m = image.length; int n = image[0].length; int left = searchColumns(image, 0, y, 0, m - 1, true); int right = searchColumns(image, y, n - 1, 0, m - 1, false); int top = searchRows(image, 0, x, left, right, true); int bottom = searchRows(image, x, m - 1, left, right, false); return (right - left + 1)*(bottom - top + 1); } private int searchColumns(char[][] image, int i, int j, int top, int bottom, boolean opt) { int result = 0; while (i <= j) { int k = top; int mid = (i + j)/2; while (k <= bottom && image[k][mid] == '0') { k++; } if (k != bottom + 1) { result = mid; } if ((k == bottom + 1) == opt) { i = mid + 1; } else { j = mid - 1; } } return result; } private int searchRows(char[][] image, int i, int j, int left, int right, boolean opt) { int result = 0; while (i <= j) { int k = left; int mid = (i + j)/2; while (k <= right && image[mid][k] == '0') { k++; } if (k != right + 1) { result = mid; } if ((k == right + 1) == opt) { i = mid + 1; } else { j = mid - 1; } } return result; } public static void main(String args[]) { char[][] image1 = {{'1'},{'1'}}; char[][] image = {{'0', '0', '1', '0'}, {'0', '1', '1', '0'}, {'0', '1', '0', '0'}}; SmallestRectangleBlackPixel sbp = new SmallestRectangleBlackPixel(); System.out.print(sbp.minArea(image, 0, 2)); } } ================================================ FILE: src/com/interview/multiarray/SpiralGeneration.java ================================================ package com.interview.multiarray; /** * Date 07/31/2016 * @author Tushar Roy * * Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order. * * https://leetcode.com/problems/spiral-matrix-ii/ */ public class SpiralGeneration { public int[][] generateMatrix(int n) { int[][] result = new int[n][n]; int up = 0; int down = n - 1; int left = 0; int right = n - 1; int index = 1; while (up <= down && left <= right) { for (int i = left; i <= right; i++) { result[up][i] = index++; } up++; for (int i = up; i <= down; i++) { result[i][right] = index++; } right--; for (int i = right; i >= left; i--) { result[down][i] = index++; } down--; for (int i = down; i >= up; i--) { result[i][left] = index++; } left++; } return result; } public static void main(String args[]) { SpiralGeneration sg = new SpiralGeneration(); int[][] r = sg.generateMatrix(4); for (int i = 0; i < r.length; i++) { for (int j = 0; j < r[i].length; j++) { System.out.print(r[i][j] + " "); } System.out.println(); } } } ================================================ FILE: src/com/interview/multiarray/SpiralPrinting.java ================================================ package com.interview.multiarray; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Date 03/15/2015 * @author Tushar Roy * * Given a 2D matrix(square or rectangular) print it in spiral way. * e.g 1 2 3 * 4 5 6 * 7 8 9 * Printing should be 1 2 3 6 9 8 7 4 5 * * Solution: * Keep 4 pointers which are bounds for this matrix, up, down, left, right. Print each * row or column and keep incrementing and decrementing the bounds. As soon as up meets down * or left meets right we are done. * * Reference * https://leetcode.com/problems/spiral-matrix/ * http://stackoverflow.com/questions/726756/print-two-dimensional-array-in-spiral-order * http://www.geeksforgeeks.org/print-a-given-matrix-in-spiral-form/ */ public class SpiralPrinting { public List spiralOrder(int[][] matrix) { if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { return Collections.EMPTY_LIST; } List result = new ArrayList<>(); int left = 0; int right = matrix[0].length - 1; int up = 0; int down = matrix.length - 1; while (left <= right && up <= down) { for (int i = left; i <= right; i++) { result.add(matrix[up][i]); } up++; for (int i = up; i <= down; i++) { result.add(matrix[i][right]); } right--; if (up <= down) { for (int i = right; i >= left; i--) { result.add(matrix[down][i]); } } down--; if (left <= right) { for (int i = down; i >= up; i--) { result.add(matrix[i][left]); } } left++; } return result; } public static void main(String args[]){ SpiralPrinting sp = new SpiralPrinting(); int[][] matrix = {{1, 2, 3}, {4, 5, 6}}; List result = sp.spiralOrder(matrix); System.out.print(result); } } ================================================ FILE: src/com/interview/multiarray/TilingProblem.java ================================================ package com.interview.multiarray; /** * http://www.geeksforgeeks.org/divide-and-conquer-set-6-tiling-problem/ * Test cases * Size of matrix is at least 2 and power of 2 always * Missing point could be on edges * Missing point could be in any of 4 quadrants */ class Position{ int x; int y; Position(int x, int y){ this.x = x; this.y = y; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + x; result = prime * result + y; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Position other = (Position) obj; if (x != other.x) return false; if (y != other.y) return false; return true; } } public class TilingProblem { char tileCount = 'a'; public char[][] fit(int size, Position missingPosition){ char matrix[][] = new char[size][size]; matrix[missingPosition.x][missingPosition.y] = 'X'; fit(matrix, new Position(0,0), matrix.length, missingPosition); return matrix; } private void fit(char matrix[][], Position topLeft, int size, Position missingPosition){ if(size == 2){ updateMatrix(matrix, topLeft, missingPosition); return; } Position alreadyFilledQuadrantPosition = determineQuadrant(topLeft, size, missingPosition); updateMatrix(matrix, new Position(topLeft.x + size/2-1, topLeft.y + size/2-1), alreadyFilledQuadrantPosition); for(int i=0 ; i < 2; i++){ for(int j=0; j < 2; j++){ Position newMissingPosition = new Position(topLeft.x + size/2 -1+i, topLeft.y + size/2 -1 + j); if(newMissingPosition.equals(alreadyFilledQuadrantPosition)){ fit(matrix, new Position(topLeft.x + i*size/2, topLeft.y + j*size/2) , size/2, missingPosition); }else{ fit(matrix, new Position(topLeft.x + i*size/2, topLeft.y + j*size/2) , size/2, newMissingPosition); } } } } private Position determineQuadrant(Position topLeft, int size, Position missingPosition){ for(int i = 0; i < 2; i++){ for(int j = 0; j < 2; j++){ if(missingPosition.x >= topLeft.x + i*size/2 && missingPosition.x <= topLeft.x + i*size/2 + size/2-1 && missingPosition.y >= topLeft.y + j*size/2 && missingPosition.y <= topLeft.y + j*size/2 + size/2 -1){ return new Position(topLeft.x+size/2 -1 +i, topLeft.y + size/2 - 1 + j); } } } throw new IllegalArgumentException("Something went wrong in determining quadrant"); } private void updateMatrix(char matrix[][], Position topLeft, Position missingPosition){ for(int i=topLeft.x; i < topLeft.x + 2; i++){ for(int j=topLeft.y; j < topLeft.y + 2; j++){ if(i == missingPosition.x && j == missingPosition.y){ continue; } matrix[i][j] = tileCount; } } tileCount++; } public static void main(String args[]){ TilingProblem tp = new TilingProblem(); Position p = new Position(5,6); char matrix[][] = tp.fit(8, p); for(int i=0; i < matrix.length; i++){ for(int j=0; j < matrix[0].length ; j++){ System.out.print(matrix[i][j] + " "); } System.out.println(); } } } ================================================ FILE: src/com/interview/multithreaded/BoundedBlockingQueue.java ================================================ package com.interview.multithreaded; import java.util.Optional; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; /** * Date 06/25/2015 * @author tusroy * * Write a program to implement bounded blocking queue. This is similar to consumer producer problem * Properties of queue * 1) If queue is empty poll will wait with timeout till item is available * 2) If queue is full offer will wait with timeout till space is available */ public class BoundedBlockingQueue { private final Object[] items; private int takeIndex; private int putIndex; private int count; private final ReentrantLock lock; private final Condition notEmpty; private final Condition notFull; /** * @param size - Define the size of bounded blocking queue. */ public BoundedBlockingQueue(int size){ items = new Object[size]; lock = new ReentrantLock(); notEmpty = lock.newCondition(); notFull = lock.newCondition(); } /** * Poll an item from queue. If queue is empty wait with timeout till item is available * @return Optional depending on if item was polled or queue was empty */ public Optional poll(long timeout, TimeUnit timeUnit) throws InterruptedException{ long left = timeUnit.toNanos(timeout); //acquire the lock on the lock object lock.lockInterruptibly(); T t; try{ //if count is 0 means there is no item to poll. Keep trying to poll //till either item is available or left gets 0 or less which means its //time to time out. while(count == 0){ if(left <= 0){ return Optional.empty(); } //if queue is empty wait fir signal from notEmpty condition left = notEmpty.awaitNanos(timeUnit.toNanos(left)); } //dequeu the item. t = dequeue(); //signal notFull since queue is not full anymore notFull.signal(); } finally { //unlock the lock object lock.unlock(); } return Optional.of(t); } /** * Offer item to queue. If queue is full wait with timeout till space is available. * @param t - item to offer * @param timeout - time out time * @param timeUnit - time out unit * @return - returns true if item was offered in queue successfully else false. * @throws InterruptedException */ public boolean offer(T t, long timeout, TimeUnit timeUnit) throws InterruptedException{ if(t == null) { throw new IllegalArgumentException(); } long left = timeUnit.toNanos(timeout); //acquire lock on lock object lock.lockInterruptibly(); try{ //keep trying if you do not have space available in queue or time out is reached. while(count == items.length){ if(left <= 0){ return false; } left = notFull.awaitNanos(timeUnit.toNanos(left)); } //enqueue the item into the queue enqueue(t); //signal notEmpty condition since queue is not empty anymore notEmpty.signal(); } finally { //release the lock. lock.unlock(); } return true; } private void enqueue(T t){ items[putIndex] = t; if(++putIndex == items.length) { putIndex = 0; } count++; } @SuppressWarnings("unchecked") private T dequeue() { T t = (T)items[takeIndex]; items[takeIndex] = null; if(++takeIndex == items.length) { takeIndex = 0; } count--; return t; } public static void main(String args[]) throws Exception{ verifyQueueWorks(); } public static void verifyQueueWorks() throws Exception{ BoundedBlockingQueue queue = new BoundedBlockingQueue<>(30); ExecutorService writeExecutors = Executors.newFixedThreadPool(10); int TOTAL = 10000; AtomicInteger result[] = new AtomicInteger[TOTAL]; AtomicInteger test = new AtomicInteger(0); for(int i = 0; i < TOTAL; i++) { writeExecutors.execute(() -> { try { int val = test.getAndIncrement(); result[val] = new AtomicInteger(1); while(true){ if(queue.offer(val, (long)(Math.random()*100 + 1), TimeUnit.MILLISECONDS)){ break; } } } catch (InterruptedException e) { System.out.println("Shutting down read thread"); } }); } ExecutorService readExecutors = Executors.newFixedThreadPool(10); for(int i = 0; i < TOTAL; i++) { readExecutors.execute(() -> { try { while(true){ Optional r = queue.poll((long)(Math.random()*1000 + 1), TimeUnit.MILLISECONDS); if(r.isPresent()) { result[r.get()].incrementAndGet(); } } } catch (InterruptedException e) { System.out.println("Shutting down read thread"); } }); } //you can replace this with countdown latch. But I do not feel like writing all that code. Thread.sleep(10000); System.out.println("Validating result after reasonable wait"); //if queue worked as expected all integers in result array should have value 2. for(int i=0; i < result.length; i++){ if(result[i].get() != 2){ throw new RuntimeException(String.valueOf(i)); } } System.out.println("Shutting down executors"); //force shutdown on read/write executor readExecutors.shutdownNow(); writeExecutors.shutdownNow(); } } ================================================ FILE: src/com/interview/multithreaded/CountingWord.java ================================================ package com.interview.multithreaded; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; /** * Date 03/05/2015 * @author tusroy * * Write a program to count words. This program should be threadsafe. * Implement two apis * 1) void addWord(String word) -> increment count of this word * 2) long getCount(String word) -> get count of this word * * Solution * Keep a concurrent map. Key to this map should be word while value should be AtomicLong to update it * in threadsafe way * * Test cases * One word updated by many threads * Many words updated by many threads * *@Threadsafe */ public class CountingWord { private ConcurrentMap map = new ConcurrentHashMap<>(); public void addWord(String word){ AtomicLong l = map.get(word); if(l == null){ l = new AtomicLong(1); l = map.putIfAbsent(word, l); if(l != null){ l.incrementAndGet(); } }else{ l.incrementAndGet(); } } public long getCount(String word){ AtomicLong l = map.get(word); if(l != null){ return l.longValue(); } return 0; } public static void main(String args[]) throws InterruptedException{ ExecutorService executor1 = Executors.newFixedThreadPool(20); ExecutorService executor2 = Executors.newFixedThreadPool(20); ExecutorService executor3 = Executors.newFixedThreadPool(20); int total = 100000; CountDownLatch countDownLatch = new CountDownLatch(3*total); CountingWord cw = new CountingWord(); for(int i= 0; i < total; i++){ executor1.execute(() -> cw.addWord("word1")); countDownLatch.countDown(); } for(int i= 0; i < total; i++){ executor2.execute(() -> cw.addWord("word2")); countDownLatch.countDown(); } for(int i= 0; i < total; i++){ executor3.execute(() -> cw.addWord("word3")); countDownLatch.countDown(); } try { countDownLatch.await(); } catch (InterruptedException e) { throw e; } executor1.shutdownNow(); executor2.shutdownNow(); executor3.shutdownNow(); long count1 = cw.getCount("word1"); long count2 = cw.getCount("word2"); long count3 = cw.getCount("word3"); assert count1 == total; assert count2 == total; assert count3 == total; } } ================================================ FILE: src/com/interview/multithreaded/DependencyTaskExecutor.java ================================================ package com.interview.multithreaded; import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.RunnableFuture; /** * Given a Task with list of its dependencies and execute method. Run the task such that dependencies are executed first. * You are given x number of threads. Increase parallelism as much as possible. */ public class DependencyTaskExecutor { Map> taskTracker = new HashMap<>(); void scheduleTask(List tasks, int threads) { ExecutorService executor = Executors.newFixedThreadPool(threads); CompletableFuture future = CompletableFuture.completedFuture(null); for (Task task : tasks) { future = future.thenAcceptBothAsync(scheduleTaskUtil(task, executor), (a, b) -> {}, executor); } future.thenRunAsync(() -> {System.out.println("All tasks done. Closing executor"); executor.shutdown();}); } CompletableFuture scheduleTaskUtil(Task task, Executor executor) { CompletableFuture f = taskTracker.get(task.name()); if (f != null) { return f; } if (task.dependencies().isEmpty()) { CompletableFuture future = CompletableFuture.runAsync(() -> task.execute(), executor); taskTracker.put(task.name(), future); return future; } CompletableFuture future = CompletableFuture.completedFuture(null);; for (Task upstreamTask : task.dependencies()) { future = future.thenAcceptBothAsync(scheduleTaskUtil(upstreamTask, executor), (a, b) -> {}, executor); } future = future.thenRunAsync(() -> task.execute(), executor); taskTracker.put(task.name(), future); return future; } public static void main(String args[]) { DependencyTaskExecutor taskExecutor = new DependencyTaskExecutor(); SimpleSleepTask a = new SimpleSleepTask("a", 2000); SimpleSleepTask b = new SimpleSleepTask("b", 4000); SimpleSleepTask c = new SimpleSleepTask("c", 6000); SimpleSleepTask d = new SimpleSleepTask("d", 3000); SimpleSleepTask x = new SimpleSleepTask("x", 4000); SimpleSleepTask y = new SimpleSleepTask("y", 6000); SimpleSleepTask z = new SimpleSleepTask("z", 3000); d.addDependency(b); d.addDependency(c); c.addDependency(a); b.addDependency(a); x.addDependency(y); x.addDependency(z); y.addDependency(a); taskExecutor.scheduleTask(Lists.newArrayList(a, b, c, d, x, y, z), 4); } } interface Task { String name(); List dependencies(); void execute(); } class SimpleSleepTask implements Task { String name; int sleepTimeInMillis; List dependencies = new ArrayList<>(); SimpleSleepTask(String name, int sleepTimeInMillis) { this.name = name; this.sleepTimeInMillis = sleepTimeInMillis; } void addDependency(Task task) { dependencies.add(task); } @Override public String name() { return name; } @Override public List dependencies() { return dependencies; } @Override public void execute() { try { System.out.println("Starting sleep for task " + name); Thread.sleep(sleepTimeInMillis); System.out.println("Ending sleep for task " + name); } catch (InterruptedException e) { e.printStackTrace(); } } } class FutureTask implements Runnable { Task task; List chainedTasks = new ArrayList<>(); Executor executor; FutureTask(Task task, Executor executor) { this.task = task; this.executor = executor; } @Override public void run() { task.execute(); for (FutureTask t : chainedTasks) { supplyAsync(t, executor); } } void supplyAsync(FutureTask task, Executor executor) { executor.execute(task); } void addChain(FutureTask task) { task.addChain(this); } } ================================================ FILE: src/com/interview/multithreaded/FillupMatrix.java ================================================ package com.interview.multithreaded; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; /** * Date 03/05/2015 * @author tusroy * * Write a program which fills up boolean matrix from top left to bottom right with true. * This program should support two apis * 1) void updateMatrix() which updates last position of matrix with true * 2) boolean getVal(int x,int y) return boolean val at matrix[x][y] * * This program should be threadsafe. * * Solution * Use AtomicLong to increment the value and return old value. * * Test cases * 1) Try with single thread * 2) Try with multiple threads and big matrix size. * */ public class FillupMatrix { private boolean matrix[][]; private int size; private AtomicLong pos; public FillupMatrix(int size){ matrix = new boolean[size][size]; this.size = size; pos = new AtomicLong(-1); } public void updateMatrix(){ long pos = next(); updateMatrix(pos); } private void updateMatrix(long pos){ if(pos >= size*size){ throw new IllegalArgumentException("Out of memory"); } matrix[(int)(pos/size)][(int)(pos%size)] = true; } private long next(){ long val = pos.incrementAndGet(); return val; } public boolean getVal(int x, int y){ return matrix[x][y]; } public static void main(String args[]) throws InterruptedException{ int size = 5000; FillupMatrix fum = new FillupMatrix(size); ExecutorService executor = Executors.newFixedThreadPool(10); for(int i=0; i < size*size ; i++){ executor.execute(() -> fum.updateMatrix()); } executor.shutdown(); executor.awaitTermination(10, TimeUnit.SECONDS); for(int i=0; i < size ; i++){ for(int j=0; j < size; j++){ assert fum.getVal(i, j); } } } } ================================================ FILE: src/com/interview/multithreaded/MinMaxKeeper.java ================================================ package com.interview.multithreaded; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; /** * Date 03/05/2015 * @author tusroy * * Write a program which keeps min and max value in threadsafe way * Support 2 apis * void updateMaxMin(int val) * int getMin() * int getMax() * * Solution * Use compareAndSet method of AtomicInteger to update min and max * * @ThreadSafe */ public class MinMaxKeeper { private AtomicInteger min = new AtomicInteger(Integer.MAX_VALUE); private AtomicInteger max = new AtomicInteger(Integer.MIN_VALUE); /** * Threadsafe way of updating min and max * @param value */ public void updateMinMax(int value){ //update min while(true){ //if value is greater than whatever is in min just break right away int minVal = min.get(); if(value >= minVal){ break; } //try to update value only if minVal is in min boolean isSetSuccesful = min.compareAndSet(minVal, value); //if set was successful break from while loop else keep looping if(isSetSuccesful){ break; } } //update max while(true){ int maxVal = max.get(); if(value <= maxVal){ break; } boolean isSetSuccesful = max.compareAndSet(maxVal, value); if(isSetSuccesful){ break; } } } public int getMin(){ return min.get(); } public int getMax(){ return max.get(); } public static void main(String args[]) throws InterruptedException{ ExecutorService executors = Executors.newFixedThreadPool(100); MinMaxKeeper mmKeeper = new MinMaxKeeper(); for(int i=0 ; i < 100000; i++){ GenerateRand rand = new GenerateRand(mmKeeper, i); executors.execute(rand); } executors.shutdown(); executors.awaitTermination(10, TimeUnit.SECONDS); assert mmKeeper.getMin() == -1; assert mmKeeper.getMax() == 1000001; } static class GenerateRand implements Runnable{ int index = 0; MinMaxKeeper mmKeeper; public GenerateRand(MinMaxKeeper mmKeeper, int index) { this.index = index; this.mmKeeper = mmKeeper; } @Override public void run() { int rand = ThreadLocalRandom.current().nextInt(1000000); if(index == 999){ rand = -1; } if(index == 1001){ rand = 1000001; } mmKeeper.updateMinMax(rand); } } } ================================================ FILE: src/com/interview/multithreaded/PrintInSequence.java ================================================ package com.interview.multithreaded; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * A class that has 5 threads - two to increment the myVar variable, two to decrement the myVar variable and one to print the value of myVar. * Implement increment(), decrement() and printVar() methods such that the following series is printed: * 0 1 2 3 4 5 4 3 2 1 0 1 2 3 4 5 4 3 2 1 ... (repeating) */ public class PrintInSequence { private volatile int val = 0; private volatile boolean shouldPrint = true; private volatile boolean isIncreasing = true; private ReentrantReadWriteLock.WriteLock lock = new ReentrantReadWriteLock().writeLock(); public void increment() { lock.lock(); if (!shouldPrint && isIncreasing) { val = val + 1; if (val == 5) { isIncreasing = false; } shouldPrint = true; } lock.unlock(); } public void decrement() { lock.lock(); if (!shouldPrint && !isIncreasing) { val = val - 1; if (val == 0) { isIncreasing = true; } shouldPrint = true; } lock.unlock(); } //only one thread is calling print. So no contention in updating shouldPrint flag. public void printVar() { if (shouldPrint) { System.out.println(val); shouldPrint = false; } } public static void main(String args[]) { PrintInSequence printInSequence = new PrintInSequence(); Thread t1 = new Thread(printInSequence::runIncrement); t1.start(); Thread t2 = new Thread(printInSequence::runIncrement); t2.start(); Thread t3 = new Thread(printInSequence::runPrint); t3.start(); Thread t4 = new Thread(printInSequence::runDecrement); t4.start(); Thread t5 = new Thread(printInSequence::runDecrement); t5.start(); } private void runIncrement() { while(true) { this.increment(); } } private void runPrint() { while (true) { this.printVar(); } } private void runDecrement() { while (true) { this.decrement(); } } } ================================================ FILE: src/com/interview/multithreaded/RealTimeCounter.java ================================================ package com.interview.multithreaded; import java.util.Random; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLongArray; /** * Date 03/03/2015 * @author tusroy * * Develop a software to count number of events in last 5 mins. You have to support two apis * 1) addEvent() -> It means increment event by 1 * 2) getTotalEvents() -> Return total number of events in last 5 mins * * Program should support millions of events every minute and should also provide multi-threading support * * This class might not have 100% accuracy as far as events in last 5 mins are concerned. * Since we are using circular queue last second information may not be very accurate. * * Solution: * Keep atomiclong of 300 in array. PositionUpdater updates position every second. * @Threadsafe */ public class RealTimeCounter { private final static int GRANULARITY = 300; private AtomicLongArray counter = new AtomicLongArray(GRANULARITY); private volatile int pos = 0; private RealTimeCounter(){ PositionUpdater positionUpdater = new PositionUpdater(this); positionUpdater.start(); } private static volatile RealTimeCounter INSTANCE; public static RealTimeCounter getInstance(){ if(INSTANCE == null){ synchronized (RealTimeCounter.class) { if(INSTANCE == null){ INSTANCE = new RealTimeCounter(); } } } return INSTANCE; } public long getTotalEvents(){ int total = 0; for(int i=0; i < GRANULARITY; i++){ total += counter.get(i); } return total; } public void addEvent(){ counter.getAndIncrement(pos); } void incrementPosition(){ //first reset the value to 0 at next counter location. counter.set((pos + 1)%GRANULARITY, 0); pos = (pos + 1)%GRANULARITY; } public static void main(String args[]){ ExecutorService executor = Executors.newFixedThreadPool(10); RealTimeCounter realTimeCounter = new RealTimeCounter(); final Random random = new Random(); final int TOTAL_EVENTS = 10000; CountDownLatch countDownLatch = new CountDownLatch(TOTAL_EVENTS); for(int i=0; i < TOTAL_EVENTS; i++){ executor.execute(() -> { realTimeCounter.addEvent(); try { Thread.sleep(random.nextInt(10)); } catch (Exception e) { e.printStackTrace(); } countDownLatch.countDown(); } ); } try{ countDownLatch.await(); }catch(Exception e){ } System.out.println(realTimeCounter.getTotalEvents()); executor.shutdownNow(); } } class PositionUpdater extends TimerTask{ private final RealTimeCounter realTimeCounter; private final Timer timer = new Timer(true); private static final int DELAY = 1000; PositionUpdater(RealTimeCounter realTimeCounter) { this.realTimeCounter = realTimeCounter; } public void start(){ timer.schedule(this, DELAY); } @Override public void run() { realTimeCounter.incrementPosition(); } } ================================================ FILE: src/com/interview/multithreaded/SingleQueueDomainTableUpdate.java ================================================ package com.interview.multithreaded; import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * Given a queue which gets millions of messages. Message is of form . * You have 10000 domain tables. Also you have 50 worker threads. You can only get * data from front of the queue. Threads get data from the front and then update the * domain table. If work is being done on domain table you cannot apply another update. * Update should also be applied sequentially. So an update coming later on should not * be applied before an update coming sooner. */ class Data{ private String domain; private String update; public String getUpdate() { return update; } public String getDomain() { return domain; } } interface DomainLock{ boolean acquireLock(String domain); boolean releaseLock(String domain); boolean isLocked(String domain); } class ThreadPoolManager{ private ConcurrentMap> domainQueueMap = new ConcurrentHashMap<>(); public ThreadPoolManager(int numOfThreads){ //initialize numOfThreads of type ThreadWorker; } } interface DatabaseLayer{ public void applyUpdates(String domain,String update); } class ThreadWorker implements Runnable{ private QueueManager mgr; private ConcurrentMap> domainQueueMap; private DomainLock domainLock; private DatabaseLayer databaseLayer; public ThreadWorker(QueueManager mgr){ this.mgr = mgr; } @Override public void run() { while(true){ Pair p = mgr.getDataFromFrontOfQueue(domainLock); if(p.yourLock){ Queue queue = domainQueueMap.get(p.data.getDomain()); if(queue != null){ while(queue.size() > 0){ Data data = queue.poll(); databaseLayer.applyUpdates(data.getDomain(), data.getUpdate()); } } databaseLayer.applyUpdates(p.data.getDomain(), p.data.getUpdate()); queue = domainQueueMap.get(p.data.getDomain()); if(queue != null){ while(queue.size() > 0){ Data data = queue.poll(); databaseLayer.applyUpdates(data.getDomain(), data.getUpdate()); } } domainLock.releaseLock(p.data.getDomain()); //check if queue is not empty //if queue is not empty try to acquire lock again }else{ if(domainQueueMap.containsKey(p.data.getDomain())){ Queue queue = domainQueueMap.get(p.data.getDomain()); queue.offer(p.data); } } } } } interface QueueHandle{ //this is a blocking call. If there is no data in the queue it just waits for data to be available public Data getNextData(); } class Pair{ Data data; boolean yourLock; } class QueueManager{ private QueueHandle queueHandle; public QueueManager(QueueHandle queueHandle){ this.queueHandle = queueHandle; } public synchronized Pair getDataFromFrontOfQueue(DomainLock domainLock){ Data data = queueHandle.getNextData(); boolean yourLock = false; //if lock for table does not exists or if it is false lock the table if(!domainLock.isLocked(data.getDomain())){ domainLock.acquireLock(data.getDomain()); yourLock = true; } Pair p = new Pair(); p.data = data; p.yourLock = yourLock; return p; } } public class SingleQueueDomainTableUpdate { } ================================================ FILE: src/com/interview/multithreaded/SpinLockMutex.java ================================================ package com.interview.multithreaded; /** * Design a mutex using 2 variable method assuming operation ice happens atomically */ class Mutex { int val = 0; /** * Val is stored somewhere. If oldVal is same as val * then you change val to newVal and return oldVal * Otherwise you do nothing but return val * @param oldValue * @param newValue * @return */ private synchronized int ice(int oldValue, int newValue) { if (oldValue == val) { val = newValue; return oldValue; } else { return val; } } void acquireLock() { while (ice(0, 1) != 0); } void releaseLock() { ice(1, 0); } } public class SpinLockMutex { StringBuffer buff = new StringBuffer(); // some method needs mutex protection public void changeBuffer(String str) { buff.append(str); } public String getBuffer() { return buff.toString(); } public static void main(String args[]) throws Exception{ SpinLockMutex slm = new SpinLockMutex(); Mutex m = new Mutex(); Thread t1 = new Thread(() -> { for (int i = 0; i < 10; i++) { m.acquireLock(); slm.changeBuffer("a" + i); m.releaseLock(); } }); Thread t2 = new Thread(() -> { for (int i = 0; i < 10; i++) { m.acquireLock(); slm.changeBuffer("b" + i); m.releaseLock(); } }); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { throw e; } System.out.println(slm.getBuffer()); } } ================================================ FILE: src/com/interview/multithreaded/ThreadPoolExample.java ================================================ package com.interview.multithreaded; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.CompletionService; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class ThreadPoolExample { private static BlockingQueue queue = new ArrayBlockingQueue(10); public static ExecutorService threadPool = Executors.newFixedThreadPool(5); public void doWork() throws Exception{ CompletionService completionService = new ExecutorCompletionService(threadPool); List> futureList = new ArrayList>(); for(int i=0; i < 20; i++){ futureList.add(completionService.submit(new Count10(i))); } for(int i=0; i < 20; i++){ Future future = completionService.take(); System.out.println(future.get()); } } public static void main(String args[]) throws Exception{ ThreadPoolExample tpe = new ThreadPoolExample(); tpe.doWork(); } } class Count10 implements Callable{ private int index = 0; Count10(int i){ index = i; } @Override public String call() throws Exception { // for(int i=0; i < 10; i++){ int sleepTime = 5000 + 1; try { System.out.println("Before sleep " + index); Thread.sleep(sleepTime); System.out.println("After sleep " + index); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } // } return "Done" + index; } } ================================================ FILE: src/com/interview/multithreaded/ThreadPoolImpl.java ================================================ package com.interview.multithreaded; import java.util.LinkedList; import java.util.Queue; class ThreadPool { public Thread run(Runnable runnable) { Thread t = new Thread(runnable); t.start(); return t; } } /** * Facebook interview question * Implement a non block run which takes as many runnables as given but only * runs a specified number of threads. * You can also update maxSize in between which will change number of threads executing * http://tutorials.jenkov.com/java-concurrency/thread-pools.html */ public class ThreadPoolImpl { private int maxSize = 0; ThreadPool threadPool; public ThreadPoolImpl(int size, ThreadPool threadPool) { maxSize = size; this.threadPool = threadPool; } public void setMax(int size){ System.out.print("Setting max size " + size); if(maxSize == 0){ maxSize = size; execute(); }else{ maxSize = size; } } private int currentSize = 0; private Queue waitingThreads = new LinkedList(); private boolean isExecuting = false; private Object monitor = new Object(); public void run(Runnable thread) { synchronized (monitor) { waitingThreads.offer(thread); execute(); } } private void execute() { if (!isExecuting) { isExecuting = true; ExecutingRunnable runnable = new ExecutingRunnable(); threadPool.run(runnable); } } class ExecutingRunnable implements Runnable { @Override public void run() { while (true) { synchronized(monitor){ if(maxSize ==0){ isExecuting = false; break; } } while (waitingThreads.size() > 0) { synchronized(monitor){ if(maxSize ==0){ isExecuting = false; break; } } if (currentSize < maxSize) { currentSize++; Runnable run = waitingThreads.poll(); RunnableThreads r = new RunnableThreads(run); threadPool.run(r); } } synchronized (monitor) { if (waitingThreads.size() == 0) { isExecuting = false; break; } } // System.out.println("Looping"); } } } class RunnableThreads implements Runnable { private Runnable r; RunnableThreads(Runnable r) { this.r = r; } @Override public void run() { r.run(); currentSize--; } } public static void main(String args[]) throws InterruptedException{ ThreadPool threadPool = new ThreadPool(); ThreadPoolImpl impl = new ThreadPoolImpl(4, threadPool); int i; for(i=0; i < 10; i++){ MyRunnable runnable = new MyRunnable(i); impl.run(runnable); } Thread.sleep(5000); impl.setMax(0); Thread.sleep(10000); impl.setMax(6); for(;i < 15;i++){ MyRunnable runnable = new MyRunnable(i); impl.run(runnable); } } } class MyRunnable implements Runnable{ int index = 0; MyRunnable(int index){ this.index =index; } @Override public void run() { System.out.println("Start of index " + index); try { Thread.sleep(3000); } catch (InterruptedException e) { System.out.println("Exception " + index + " " + e); } System.out.println("End of index " + index); } } ================================================ FILE: src/com/interview/number/AggregateNumber.java ================================================ package com.interview.number; /** * Number such that 11 + 11 = 22, 11 +22 = 33, 22 +33 = 55 * so 1111223355 is aggregate number */ public class AggregateNumber { //assumption is that numbers in array are single digit non-negative number(0..9) public boolean isAggregate(int[] number){ if(number.length < 3){ return false; } int prev = 0; for(int i=1; i <= number.length/2; i++){ for(int j=0; j right) { String r = new String(result); if ((r.length() == low.length() && low.compareTo(r) > 0) || (high.length() == result.length && high.compareTo(r) < 0)) { return 0; } return 1; } int count = 0; for (char[] pair : pairs) { result[left] = pair[0]; result[right] = pair[1]; //number should not start with 0 if its length is greater than 0 if (result.length != 1 && result[0] == '0') { continue; } //if left == right then we got to make sure we dont pick pair 6, 9 or 9, 6 if ((left < right) || (left == right && pair[0] == pair[1])) { count += strobogrammaticInRangeUtil(low, high, left + 1, right - 1, result); } } return count; } } ================================================ FILE: src/com/interview/number/ArithemeticProgressionExists.java ================================================ package com.interview.number; /** * http://www.geeksforgeeks.org/length-of-the-longest-arithmatic-progression-in-a-sorted-array/ */ public class ArithemeticProgressionExists { public boolean exists(int input[]){ for(int i=1; i < input.length-1; i++){ int j = i-1; int k = i+1; while(j >=0 && k <= input.length-1){ if(input[i]*2 == input[j] + input[k]){ return true; }else if(input[i]*2 > input[j] + input[k]){ k++; }else{ j--; } } } return false; } public static void main(String args[]){ int input[] = {1,3,6,7,10,11,15}; ArithemeticProgressionExists ape = new ArithemeticProgressionExists(); System.out.println(ape.exists(input)); } } ================================================ FILE: src/com/interview/number/ArrayMultiplication.java ================================================ package com.interview.number; import com.interview.array.ArrayAddition; public class ArrayMultiplication { public int[] multiplyDivideAndConquer(int arr1[],int arr2[],int low1,int high1,int low2,int high2){ if(low1 == high1 || low2 == high2){ return simpleMultiplication(arr1, arr2, low1, high1, low2, high2); } int mid1 = (low1 + high1)/2; int mid2 = (low2 + high2)/2; int r1[] = multiplyDivideAndConquer(arr1,arr2,low1,mid1,low2,mid2); int shiftBy = high1-mid1 + high2-mid2; r1 = shift(r1,shiftBy); int r2[] = multiplyDivideAndConquer(arr1,arr2,mid1+1,high1,mid2+1,high2); int r3[] = multiplyDivideAndConquer(arr1,arr2,low1,mid1,mid2+1,high2); shiftBy = high1 - mid1; r3 = shift(r3,shiftBy); int r4[] = multiplyDivideAndConquer(arr1,arr2,mid1+1,high1,low2,mid2); shiftBy = high2 - mid2; r4 = shift(r4,shiftBy); ArrayAddition aa = new ArrayAddition(); r1 = aa.add(r1, r2); r1 = aa.add(r1, r3); r1 = aa.add(r1, r4); return r1; } private int[] shift(int arr[],int n){ int[] result = new int[arr.length + n]; int i=0; for(i=0; i < arr.length; i++){ result[i] = arr[i]; } return result; } public int[] simpleMultiplication(int arr1[],int arr2[],int low1,int high1,int low2,int high2){ int[] result = new int[high1-low1 + high2 -low2 + 2]; int m=0; int c=0; int n =0; int index = result.length-1; int temp[] = new int[Math.max(high1-low1+1, high2-low2+1)+1]; for(int i= high1; i >=low1; i--){ int l = temp.length-1; for(int j=high2; j>=low2; j--){ m = arr1[i]*arr2[j] + c; n = m%10; temp[l--] = n; c = m/10; } temp[l] = c; addToResult(result,temp,index); index--; c=0; for(int t=0; t < temp.length; t++){ temp[t] = 0; } } return result; } private void addToResult(int[] result,int temp[],int start){ int c=0; for(int i=temp.length-1; i>=0 ; i--){ if(start == -1){ break; } int m = result[start] + temp[i] + c; result[start--] = m%10; c = m/10; } } public int multiplicationImproved(int x, int y, int len){ if(len == 1){ return x*y; } len = len/2; int div = power(len); int result1 = multiplicationImproved(x/div,y/div,len); int result2 = multiplicationImproved(x%div, y % div, len); int result3 = multiplicationImproved(x/div + x%div,y/div + y % div,len); return result1*div*(div -1) + result3*div - result2*(div -1 ); } private int power(int n){ return (int)Math.pow(10, n); } public static void main(String args[]){ int arr2[] = {9,9,7,4,7,9}; int arr1[] = {9,9,5,7,4,2,1}; ArrayMultiplication am = new ArrayMultiplication(); int result[] = am.multiplyDivideAndConquer(arr1, arr2, 0, arr1.length-1, 0, arr2.length-1); for(int i=0; i < result.length; i++){ System.out.print(" " + result[i]); } System.out.print("\n" + am.multiplicationImproved(999, 168, 2)); } } ================================================ FILE: src/com/interview/number/BasicCalculator.java ================================================ package com.interview.number; import java.util.Stack; /** * Date 10/11/2016 * @author Tushar Roy * * Implement a basic calculator to evaluate a simple expression string. * The expression string contains only non-negative integers, +, -, *, / operators and empty spaces. * The integer division should truncate toward zero. * * Time complexity O(n) * Space complexity (n) * * https://leetcode.com/problems/basic-calculator-ii/ */ public class BasicCalculator { public int calculate(String s) { Stack operand = new Stack<>(); int current = 0; char prevOperator = '+'; for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if (Character.isDigit(ch)) { current = current * 10 + ch - '0'; } //if its not a digit or space then go in this block. //also if it is last character then go in this block and finish up last operation. if (i == s.length() - 1 || (ch != ' ' && !Character.isDigit(ch))) { if (prevOperator == '+') { operand.push(current); } else if (prevOperator == '-') { operand.push(-current); } else if (prevOperator == '/') { operand.push(operand.pop() / current); } else { operand.push(operand.pop() * current); } prevOperator = ch; current = 0; } } int result = 0; while (!operand.isEmpty()) { result += operand.pop(); } return result; } } ================================================ FILE: src/com/interview/number/BinomialCoefficient.java ================================================ package com.interview.number; /** * http://www.geeksforgeeks.org/space-and-time-efficient-binomial-coefficient/ * Test cases * k is 0 * k or n are negative * k greater than n */ public class BinomialCoefficient { public int calculate(int n, int k){ if(k > n-k){ k = n-k; } int result = 1; for(int i=0; i < k; i++){ result *= (n-i); result /= (i+1); } return result; } public static void main(String args[]){ BinomialCoefficient bc = new BinomialCoefficient(); System.out.print(bc.calculate(8, 3)); } } ================================================ FILE: src/com/interview/number/ConvertToBaseN.java ================================================ package com.interview.number; public class ConvertToBaseN { int baseN(int num,int base){ if(base > 10){ throw new IllegalArgumentException(); } int result =0; int pow = 1; while(num > 0){ result += pow*(num%base); pow = pow*10; num /= base; } return result; } public static void main(String args[]){ ConvertToBaseN ctb = new ConvertToBaseN(); System.out.println(ctb.baseN(13, 9)); } } ================================================ FILE: src/com/interview/number/CountNoOf2s.java ================================================ package com.interview.number; /** * 150 qs 18.4 */ public class CountNoOf2s { public int count2s(int n){ if(n < 2){ return 0; }else if(n <= 9){ return 1; } int pow = 1; while(pow <= n){ pow *= 10; } pow = pow/10; if(n/pow == 2){ //e.g 2105 becomes 1 + 105 + count2s(105) + count2s(1999) return 1 + n%pow + count2s(n%pow) + count2s((n/pow)*pow -1); }else{ //e.g 3856 becomes 1000*count2s(3) + count2s(856) + 3*counts(999) return pow*count2s(n/pow) + count2s(n%pow) + (n/pow)*count2s(pow-1); } } public static void main(String args[]){ CountNoOf2s cn2 = new CountNoOf2s(); System.out.println(cn2.count2s(255)); } } ================================================ FILE: src/com/interview/number/CountNumbersNotIncluding4.java ================================================ package com.interview.number; /** * http://www.geeksforgeeks.org/count-numbers-that-dont-contain-3/ */ public class CountNumbersNotIncluding4 { public int count(int n){ if(n < 4){ return n; } if( n >=4 && n <=10){ return n-1; } int pow = 1; while(n/pow > 9){ pow = pow*10; } int msd = n/pow; if(msd == 4){ return count(msd*pow -1); }else{ //suppose number is 276. So this becomes count(2)*count(99) + //count(2) + count(76) //reason we split this way rather than count(2)*count(100) is because //count(100) can go into infinite loop return count(msd)*count(pow-1) + count(msd) + count(n%pow); } } public static void main(String args[]){ CountNumbersNotIncluding4 cn = new CountNumbersNotIncluding4(); int c = cn.count(44); System.out.print(c); } } ================================================ FILE: src/com/interview/number/DivisionWithoutDivisionOperator.java ================================================ package com.interview.number; public class DivisionWithoutDivisionOperator { public static class Pair { int remainder; int quotient; } public Pair divide(int number, int divisor) { int divident = 0; while (number >= divisor) { number -= divisor; divident++; } Pair p = new Pair(); p.quotient = divident; p.remainder = number; return p; } public int divideRec(int number, int divisor){ if(number < divisor){ return 0; } return divideRec(number-divisor, divisor) + 1; } public Pair efficientDivide(int divident, int divisor) { int quotient = 1; int currentDivisor = divisor; int currentDivident = divident; int q = 0; while (divisor < divident) { currentDivisor = divisor; currentDivident = divident; quotient = 1; while (currentDivisor <= currentDivident) { currentDivisor *= 2; quotient *= 2; } currentDivisor = currentDivisor >> 1; quotient = quotient >> 1; divident = divident - currentDivisor; q += quotient; } Pair p = new Pair(); p.quotient = q; p.remainder = divident; return p; } public int efficientDivideRec(int divident, int divisor){ if(divisor > divident){ return 0; } int tempDivisor = divisor; int quotient = 1; while(divisor <= divident){ divisor = divisor*2; quotient *= 2; } divisor = divisor >> 1; quotient = quotient >> 1; return quotient + efficientDivideRec(divident - divisor, tempDivisor); } public static void main(String args[]) { DivisionWithoutDivisionOperator dd = new DivisionWithoutDivisionOperator(); Pair p = dd.efficientDivide(95,4); System.out.println(p.quotient + " " + p.remainder); System.out.print(dd.efficientDivideRec(135,12)); } } ================================================ FILE: src/com/interview/number/EuclideanAlgoForGCD.java ================================================ package com.interview.number; /** * GCD greatest common divisor * Co prime numbers if GCD of both the numbers is 1 */ public class EuclideanAlgoForGCD { public int gcd(int num1, int num2){ if(num1 > num2){ int temp = num1; num1 = num2; num2 = temp; } while(num1 != 0){ int temp = num1; num1 = num2 % num1; num2 = temp; } return num2; } /** * assumption that num1 is less than num2 as initial parameter */ public int gcdRec(int num1, int num2){ if(num1 == 0){ return num2; } return gcdRec(num2%num1, num1); } public static void main(String args[]){ EuclideanAlgoForGCD ea = new EuclideanAlgoForGCD(); int gcd = ea.gcd(956,1044); if(gcd == 1){ System.out.println("Co prime numbers"); }else{ System.out.println("No coprime numbers " + gcd); } } } ================================================ FILE: src/com/interview/number/FactorialOfLargeNumber.java ================================================ package com.interview.number; /** * Date 03/14/2015 * @author tusroy * Find factorial of very large number like 100. * * Solution * Since result will be very large it cannot fit in long. We need to store result in array * and do regular multiplication of result in array with next number of factorial. * Result is randomly initialized with size 500. Better would be to use list which grows * dynamically. * * Test cases: * Negative number - should throw exception for negative number * 0 * large number * * Reference * http://www.geeksforgeeks.org/factorial-large-number/ */ public class FactorialOfLargeNumber { public int calculate(int result[], int n){ assert n >= 0; result[0] = 1; int size = 1; for(int i=2; i <= n; i++){ size = multiply(result, i, size); } return size; } private int multiply(int result[], int x, int size){ int carry = 0; int prod = 0; int i=0; for(; i < size; i++){ prod = result[i]*x + carry; result[i] = prod%10; carry = prod/10; } while(carry != 0){ result[i] = carry%10; carry = carry/10; i++; } return i; } public static void main(String args[]){ FactorialOfLargeNumber fol = new FactorialOfLargeNumber(); int result[] = new int[500]; int size = fol.calculate(result, 126); for(int i=size-1; i >=0; i--){ System.out.print(result[i]); } } } ================================================ FILE: src/com/interview/number/GenerateSignature.java ================================================ package com.interview.number; /** * You are given an array of n elements [1,2,....n]. For example {3,2,1,6,7,4,5}. Now we create a signature of this * array by comparing every consecutive pir of elements. If they increase, write I else write D. * For example for the above array, the signature would be "DDIIDI". The signature thus has a length of N-1. * Now the question is given a signature, compute the lexicographically smallest permutation of [1,2,....n]. * * Time complexity O(n) * Space complexity O(1) * * Reference https://learn.hackerearth.com/forum/182/lexicographically-smallest-permutation-given-a-signature/ */ public class GenerateSignature { public int[] generate(char[] input) { int n = input.length+1; int[] result = new int[n]; int i; for (i = 0; i < n; i++) { result[i] = i+1; } i = 0; while(i < n-1) { int start = -1, end = -1; while(i < n-1 && input[i] == 'D') { if(start == -1) { start = i; } end = i; i++; } if(start != -1) { reverse(result, start, end+1); } i++; } return result; } private void reverse(int[] result, int start, int end) { while(start < end) { int tmp = result[start]; result[start] = result[end]; result[end] = tmp; start++; end--; } } public static void main(String args[]){ String input = "IIIDIIDDDDIIDDD"; GenerateSignature gs = new GenerateSignature(); int result[] = gs.generate(input.toCharArray()); for(int i=0; i < result.length; i++){ System.out.print(result[i] + " "); } } } ================================================ FILE: src/com/interview/number/LargestMultipleOf3inArray.java ================================================ package com.interview.number; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; /** * http://www.geeksforgeeks.org/find-the-largest-number-multiple-of-3/ */ public class LargestMultipleOf3inArray { public void swap(int input[],int i, int j){ int temp = input[i]; input[i] = input[j]; input[j] = temp; } private void reverse(int input[]){ for(int i=0; i < input.length/2; i++){ swap(input,i, input.length-1-i); } } public int[] largestMultiple(int input[]){ Arrays.sort(input); int output[]; Queue q0 = new LinkedList(); Queue q1 = new LinkedList(); Queue q2 = new LinkedList(); int sum = 0; for(int i=0; i < input.length; i++){ if(input[i] % 3 == 0){ q0.add(input[i]); } if(input[i] % 3 == 1){ q1.add(input[i]); } if(input[i] % 3 == 2){ q2.add(input[i]); } sum += input[i]; } if(sum % 3 == 0){ output = new int[input.length]; for(int i=0; i < input.length; i++){ output[input.length-1-i] = input[i]; } return output; } else if(sum % 3 == 1){ int len = input.length; if(q1.size() > 0){ q1.poll(); len--; }else if (q2.size() > 1){ q2.poll(); q2.poll(); len -= 2; }else{ return null; } output = new int[len]; int i=0; while(q0.size() > 0){ output[i] = q0.poll(); i++; } while(q1.size() > 0){ output[i] = q1.poll(); i++; } while(q2.size() > 0){ output[i] = q2.poll(); i++; } Arrays.sort(output); reverse(output); }else{ int len = input.length; if(q2.size() > 0){ q2.poll(); len--; }else if(q1.size() > 1){ q1.poll(); q1.poll(); len -= 2; }else{ return null; } output = new int[len]; int i=0; while(q0.size() > 0){ output[i] = q0.poll(); i++; } while(q1.size() > 0){ output[i] = q1.poll(); i++; } while(q2.size() > 0){ output[i] = q2.poll(); i++; } Arrays.sort(output); reverse(output); } return output; } public static void main(String args[]){ int input[] = {8,9,0,2,2,2}; LargestMultipleOf3inArray lma = new LargestMultipleOf3inArray(); int output[] = lma.largestMultiple(input); for(int a : output){ System.out.print(a + " "); } } } ================================================ FILE: src/com/interview/number/LuckyNumbers.java ================================================ package com.interview.number; /** * http://www.geeksforgeeks.org/lucky-numbers/ */ public class LuckyNumbers { public boolean isLuck(int n,int counter){ if(n < counter){ return true; } if(n % counter == 0){ return false; } return isLuck( n - n/counter,counter+1); } public static void main(String args[]){ LuckyNumbers ln = new LuckyNumbers(); System.out.println(ln.isLuck(19, 2)); } } ================================================ FILE: src/com/interview/number/MedianOf3Number.java ================================================ package com.interview.number; public class MedianOf3Number { public int median(int arr[]){ int l = 0; int h = 2; int m =1; if(arr[m] >= arr[l]){ if(arr[m] <= arr[h]){ return arr[m]; }else if(arr[l] >= arr[h]){ return arr[l]; } }else{ if(arr[l] <= arr[h]){ return arr[l]; }else if(arr[m] >= arr[h]){ return arr[m]; } } return arr[h]; } public int median2Comparison(int arr[]){ int l = 0; int h = 2; int m =1; if((arr[l] - arr[m])*(arr[h] - arr[l]) >= 0){ return arr[l]; }else if((arr[m] - arr[l])*(arr[h] - arr[m]) >= 0){ return arr[m]; }else{ return arr[h]; } } public int medianXORMethod(int arr[]){ int a = arr[0] <= arr[1] ? arr[0] : arr[1]; int b = arr[1] <= arr[2] ? arr[1] : arr[2]; int c = arr[0] <= arr[2] ? arr[0] : arr[2]; return a^b^c; } public static void main(String args[]){ MedianOf3Number mn = new MedianOf3Number(); int arr[] = {2,0,1}; System.out.println(mn.medianXORMethod(arr)); } } ================================================ FILE: src/com/interview/number/MthNumberInNSizeArray.java ================================================ package com.interview.number; import java.util.Arrays; /** * @author Tushar Roy * Date 01/21/2016 * * Given a number n, find mth value in permutation of array consisting of [1..n] values. * mth is defined by lexicographical order. */ public class MthNumberInNSizeArray { public int[] find(int n, int m) { boolean used[] = new boolean[n]; int result[] = new int[n]; find(result, used, 0, n, m); return result; } private void find(int result[], boolean used[], int start, int n, int m) { if(1 == m) { fillupRemaining(result, used, start); return; } int index = binarySearch(m, start + 1, n, factorial(n - start - 1)); int i = nthUnused(used, index); used[i] = true; result[start] = i + 1; find(result, used, start + 1, n, m - (index-1)*factorial(n - start - 1)); } private int binarySearch(int m, int start, int end, int factorial) { int i = 1; int j = end - start + 1; while (i <= j) { int middle = (i + j)/2; if (factorial*(middle) >= m && factorial*(middle - 1) < m) { return middle; } else if (factorial*middle < m){ i = middle + 1; } else { j = middle - 1; } } throw new IllegalArgumentException(); } private void fillupRemaining(int result[], boolean used[], int index) { int j = 0; for(int i = index; i < result.length; i++) { while (true) { if (!used[j]) { result[i] = j + 1; used[j] = true; break; } j++; } } } private int nthUnused(boolean used[], int n) { int unused = 0; for ( int i = 0; i < used.length; i++) { if (!used[i]) { unused++; if (unused == n) { return i; } } } throw new IllegalArgumentException(); } private int factorial(int n) { int result = 1; for ( int i = 1; i <= n; i++) { result = result*i; } return result; } public static void main(String args[]) { MthNumberInNSizeArray mn = new MthNumberInNSizeArray(); int n = 5; int m = 120; for ( int i = 1; i <= m; i++) { int result[] = mn.find(n, i); Arrays.stream(result).forEach(r -> System.out.print(r + " ")); System.out.print("\n"); } } } ================================================ FILE: src/com/interview/number/NBy2PairSumToK.java ================================================ package com.interview.number; /** * Write a program to determine whether n/2 distinctive pairs can be formed * from given n integers where n is even and each pair's sum is divisible by given k. * Numbers cannot be repeated in the pairs, that means only you can form total n/2 pairs. */ public class NBy2PairSumToK { //assuming input is from 1 to n. If input can contain 0 special logic will be needed //to handle that. public boolean pair(int input[],int k){ int count[] = new int[k]; for(int i=0; i < input.length; i++){ count[input[i]%k]++; } if(count[0]%2 != 0){ return false; } if(k%2==0){ if(count[k/2]%2 != 0){ return false; } } for(int i=1; i <= k/2; i++){ if(count[i] != count[k-i]){ return false; } } return true; } public static void main(String args[]){ int input[] = {5,7,6,8,2,6,10,4}; NBy2PairSumToK nb = new NBy2PairSumToK(); System.out.println(nb.pair(input, 6)); } } ================================================ FILE: src/com/interview/number/NextLargestPalindrome.java ================================================ package com.interview.number; /** http://www.geeksforgeeks.org/given-a-number-find-next-smallest-palindrome-larger-than-this-number/ */ public class NextLargestPalindrome { public void nextPalindrome(int num[]){ int mid = num.length/2; int i = mid-1; int j = num.length % 2 == 0 ? mid : mid+1; while(i >= 0 && j <= num.length-1 && num[i] == num[j]){ i--; j++; } boolean leftSmaller = false; if(i < 0 || num[i] < num[j]){ leftSmaller = true; } if(!leftSmaller){ while(i >= 0){ num[j] = num[i]; i--; j++; } }else{ int carry =0; if(num.length % 2 != 0){ num[mid] = num[mid] + 1; carry = num[mid]/10; num[mid] = num[mid]%10; j = mid+1; }else{ j = mid; carry = 1; } i = mid-1; while(i >= 0){ num[i] = carry + num[i]; carry = num[i]/10; num[i] = num[i]%10; num[j] = num[i]; i--; j++; } } } public void printArray(int num[]){ for(int i=0; i < num.length; i++){ System.out.print(num[i] + " "); } } public static void main(String args[]){ NextLargestPalindrome nextLargestPalindrom = new NextLargestPalindrome(); int num[] = {6,5,4,4,5,6}; //handle case of 999 separately nextLargestPalindrom.nextPalindrome(num); nextLargestPalindrom.printArray(num); } } ================================================ FILE: src/com/interview/number/NotIncluding4.java ================================================ package com.interview.number; /** * http://saikatd.wordpress.com/author/saikatd/page/4/ * In a number system where 4 is not there, how do you convert such a number system to decimal * Here basically we have base 9 and convert it to base 10. Just be careful when you convert * anything from 5 to 9 because they are basically 4 to 8 in base 9 system. So subtract them * by 1 when doing multiplications. */ public class NotIncluding4 { public int number(int chinaNumber){ int result = 0; int mul = 1; while(chinaNumber > 0){ int r = chinaNumber % 10; chinaNumber /= 10; if(r == 4){ throw new IllegalArgumentException(); } if(r >=5){ r--; } result += r*mul; mul = mul*9; } return result; } public static void main(String args[]){ NotIncluding4 ni = new NotIncluding4(); System.out.print(ni.number(16)); } } ================================================ FILE: src/com/interview/number/NumberOfCombinationsForStairs.java ================================================ package com.interview.number; import java.util.Iterator; import java.util.LinkedList; /** * A man is walking up a set of stairs. He can either take 1 or 2 steps at a time. * Given n number of steps, * find out how many combinations of steps he can take to reach the top of the stairs. * Its like building a fibonaaci series but instead of looking back 2 you have to * look back k elements */ public class NumberOfCombinationsForStairs { /** * Assumption is k is always greater than or equal to 2 */ public int numberOfWays(int n,int k){ if(k < 2){ throw new IllegalArgumentException(); } LinkedList queue = new LinkedList(); queue.add(1); queue.add(2); int count=0; for(int i=2; i < k ; i++){ Iterator itr = queue.iterator(); count = 0; while(itr.hasNext()){ count += itr.next(); } queue.offerLast(count); } for(int i = k; i < n ; i++){ Iterator itr = queue.iterator(); count = 0; while(itr.hasNext()){ count += itr.next(); } queue.pollFirst(); queue.offerLast(count); } return queue.pollLast(); } public static void main(String args[]){ NumberOfCombinationsForStairs noc = new NumberOfCombinationsForStairs(); System.out.println(noc.numberOfWays(7, 4)); } } ================================================ FILE: src/com/interview/number/PermutationBiggerThanNumber.java ================================================ package com.interview.number; import com.interview.sort.QuickSort; /** * Date 02/17/2016 * @author Tushar Roy * Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers. * If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order). * * Time complexity is O(n) * Space complexity is O(1) * * https://leetcode.com/problems/next-permutation/ * e.g 1 7 9 8 4 will transform to 1 8 4 7 9 * or 4 2 6 4 3 will transform to 4 3 2 4 6 */ public class PermutationBiggerThanNumber { public void nextPermutation(int[] nums) { int i; for (i = nums.length - 2; i >= 0 ; i--) { if (nums[i] < nums[i + 1]) { break; } } if (i != -1) { int pos = ceiling(nums[i], i + 1, nums.length - 1, nums); int t = nums[pos]; nums[pos] = nums[i]; nums[i] = t; } reverse(nums, i + 1, nums.length - 1); } private void reverse(int nums[], int start, int end) { while (start <= end) { int t = nums[start]; nums[start] = nums[end]; nums[end] = t; start++; end--; } } private int ceiling(int val, int start, int end, int[] nums) { while (start <= end) { int middle = (start + end)/2; if (nums[middle] > val && (middle + 1 == nums.length || nums[middle+1] <= val)) { return middle; } else if (nums[middle] > val) { start = middle + 1; } else { end = middle - 1; } } throw new IllegalArgumentException(); } public static void main(String args[]){ PermutationBiggerThanNumber pb = new PermutationBiggerThanNumber(); int arr[] = {1,7,9,8,4}; pb.nextPermutation(arr); for(int i=0; i < arr.length; i++){ System.out.print(arr[i] + " "); } } } ================================================ FILE: src/com/interview/number/PermutationLargerThanGivenArray.java ================================================ package com.interview.number; import java.util.Arrays; /** * e.g if src array is {1,2,5,7,8} and dest is {5,8,1,9,8} * permute src in such a way that it is greater than dest but diff is minimal * so here we will have {5,8,2,1,7} * */ public class PermutationLargerThanGivenArray { public int[] findBiggerNumber(int src[],int dest[]){ int result[] = new int[src.length]; boolean[] used = new boolean[src.length]; boolean r = findNumber(src, dest, result, 0, used); if(!r){ return null; } return result; } private void sortRemaining(int src[],int result[],boolean used[],int pos){ int pos1 = pos; for(int i=0; i < src.length; i++){ if(!used[i]){ result[pos1] = src[i]; pos1++; } } Arrays.sort(result,pos,result.length); } private boolean findNumber(int src[],int dest[],int result[],int pos,boolean used[]){ if(pos == result.length){ return false; } boolean hasEqual = false; int nextGreaterIndex = -1; int equalIndex = -1; int nextGreaterDiff = Integer.MAX_VALUE; for(int i=0; i < src.length; i++){ if(used[i]){ continue; } if(dest[pos] == src[i]){ hasEqual = true; equalIndex = i; continue; } if(src[i] > dest[pos]){ if(src[i] - dest[pos] < nextGreaterDiff){ nextGreaterIndex = i; nextGreaterDiff = src[i] - dest[pos]; } } } //first try with equal item and see next numbers in array might find larger one. //if it fail try next larger number if(hasEqual){ used[equalIndex] = true; result[pos] = src[equalIndex]; if(findNumber(src,dest,result,pos+1,used)){ return true; } used[equalIndex] = false; } if(nextGreaterIndex != -1){ used[nextGreaterIndex] = true; result[pos] = src[nextGreaterIndex]; sortRemaining(src, result, used, pos+1); return true; } return false; } public static void main(String args[]){ int src[] = {1,2,5,7,8}; int dest[] = {5,8,1,9,8}; PermutationLargerThanGivenArray nld = new PermutationLargerThanGivenArray(); int result[] = nld.findBiggerNumber(src, dest); if(result != null){ for(int i=0; i < result.length; i++){ System.out.print(result[i] + " "); } }else{ System.out.println("Cant find bigger permutation"); } } } ================================================ FILE: src/com/interview/number/PowerFunction.java ================================================ package com.interview.number; /** * Date 03/13/2016 * @author Tushar Roy * * Find power of 2 numbers. * * Time complexity O(logn) * Space complexity O(1) * * https://leetcode.com/problems/powx-n/ * http://www.geeksforgeeks.org/write-a-c-program-to-calculate-powxn/ */ public class PowerFunction { public int power(int n, int m){ if(m == 0){ return 1; } int pow = power(n,m/2); if(m % 2 ==0){ return pow*pow; }else{ return n*pow*pow; } } public double powerUsingBit(double x, int n) { if (n == 0) { return 1; } long r = n; if (r < 0) { x = 1/x; r = -r; } double power = x; double result = x; double result1 = 1; while (r > 1) { result *= result; if ((r & 1) != 0) { result1 = result1 * power; } r = r >> 1; power = power * power; } return result * result1; } public static void main(String args[]){ PowerFunction pf = new PowerFunction(); long pow = pf.power(3, 5); System.out.print(pow); } } ================================================ FILE: src/com/interview/number/RearrangeNumberInArrayToFormLargestNumber.java ================================================ package com.interview.number; import java.util.Arrays; import java.util.Comparator; /** * Given a list of non negative integers, arrange them such that they form the largest number. * For example, given [3, 30, 34, 5, 9], the largest formed number is 9534330. * * https://leetcode.com/problems/largest-number/ */ public class RearrangeNumberInArrayToFormLargestNumber { public String largestNumber(int[] nums) { Integer[] nums1 = new Integer[nums.length]; int i = 0; for (int n : nums) { nums1[i++] = n; } IntegerComparator comparator = new IntegerComparator(); Arrays.sort(nums1, comparator); StringBuffer buff = new StringBuffer(); //handle 0s in the front by removing them. for (i = 0; i < nums1.length; i++) { if (nums1[i] != 0) { break; } } //if no element is left means return one 0 if (i == nums1.length) { return "0"; } for (;i < nums1.length; i++) { buff.append(nums1[i]); } return buff.toString(); } public static void main(String args[]){ RearrangeNumberInArrayToFormLargestNumber rni = new RearrangeNumberInArrayToFormLargestNumber(); int[] input = {999999998, 999999997, 999999999}; int[] input1 = {0, 9, 8}; int[] input2 = {0, 0}; String result = rni.largestNumber(input2); System.out.print(result); } class IntegerComparator implements Comparator { @Override public int compare(Integer o1, Integer o2) { int pow1 = 10; while(pow1 <= o1){ pow1 *= 10; } int pow2 = 10; while(pow2 <= o2){ pow2 *= 10; } int r1 = o1*pow2 + o2; int r2 = o2*pow1 + o1; return r2 - r1; } } } ================================================ FILE: src/com/interview/number/RussianPeasantMultiplication.java ================================================ package com.interview.number; /** * http://www.geeksforgeeks.org/fast-multiplication-method-without-using-multiplication-operator-russian-peasants-algorithm/ * Test cases * Division by 0 * Negative numbers */ public class RussianPeasantMultiplication { public int multiply(int a,int b){ int res = 0; while(b > 0){ if(b % 2 != 0){ res += a; } a = a<<1; b = b>>1; } return res; } public static void main(String args[]){ RussianPeasantMultiplication rpm = new RussianPeasantMultiplication(); System.out.println(rpm.multiply(7, 13)); } } ================================================ FILE: src/com/interview/number/SmallestNumberGreaterThanGiveNumberIncreasingSequence.java ================================================ package com.interview.number; /** * http://www.careercup.com/question?id=4857362737266688 * Test cases : * 6 2 3 -> 6 7 8 * 1 2 3 -> 1 2 4 * 1,7,9 -> 1,8,9 * 1,8,9 -> 2,3,4 * 9,8,7 -> 1,2,3,4 * 2,6 -> 2,7 */ public class SmallestNumberGreaterThanGiveNumberIncreasingSequence { public int[] getNextInt(int []input){ int result[] = new int[input.length]; boolean flag = getNextInt(input,result,0); if(flag){ return result; }else{ result = new int[input.length+1]; fillRestOfArray(result, 0, (input[0] +1)%9); return result; } } private boolean getNextInt(int input[], int result[], int pos){ if(pos == input.length-1){ int higher = getHigherNumber(input[pos]+1,pos,input.length); if(higher == -1){ return false; }else{ result[pos] = input[pos]+1; return true; } } if(pos != 0 && input[pos] <= input[pos-1]){ int higher = getHigherNumber(input[pos-1] +1,pos,input.length); if(higher == -1){ return false; }else{ fillRestOfArray(result, pos, input[pos-1]+1); return true; } } if(input[pos] + (input.length - 1 -pos) <=9){ result[pos] = input[pos]; boolean flag = getNextInt(input,result,pos+1); if(flag){ return true; } int higher = getHigherNumber(input[pos]+1,pos,input.length); if(higher == -1){ return false; }else{ fillRestOfArray(result,pos,input[pos]+1); return true; } }else{ return false; } } private void fillRestOfArray(int result[],int pos,int val){ for(int i=pos; i < result.length ; i++){ result[i] = val; val++; } } private int getHigherNumber(int input, int i, int len){ if(input + len - i-1 <=9){ return input; } return -1; } public static void main(String args[]){ int arr[] = {2,6}; SmallestNumberGreaterThanGiveNumberIncreasingSequence sm = new SmallestNumberGreaterThanGiveNumberIncreasingSequence(); int result[] = sm.getNextInt(arr); for(int i : result){ System.out.print(i); } } } ================================================ FILE: src/com/interview/number/SquareRoot.java ================================================ package com.interview.number; /** * Babylonian method for calculating square root */ public class SquareRoot { double findRoot(int num){ double start =0; double end = num; while(Math.abs(start - end) > 0.01){ end = (start + end)/2; start = num/end; } return end; } public static void main(String args[]){ SquareRoot sr = new SquareRoot(); System.out.println(sr.findRoot(144)); } } ================================================ FILE: src/com/interview/number/StrobogrammaticNumber.java ================================================ package com.interview.number; /** * A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down). * https://leetcode.com/problems/strobogrammatic-number/ */ public class StrobogrammaticNumber { public boolean isStrobogrammatic(String num) { for (int i = 0; i <= num.length()/2; i++) { char ch1 = num.charAt(i); char ch2 = num.charAt(num.length() - i - 1); if (ch1 != ch2) { if ((ch1 != '9' || ch2 != '6') && (ch1 != '6' || ch2 != '9')) { return false; } } else { if (ch1 != '0' && ch1 != '1' && ch1 != '8') { return false; } } } return true; } } ================================================ FILE: src/com/interview/number/Trailing0sinFactorial.java ================================================ package com.interview.number; /** * 150qs hard section * lets consider 625. First we divide 625 by 5 and that takes care of one 5 * till 625. Then we divide 625 with 25 and that takes care of numbers with 2 * 5s. We keep doing this till divisor becomes greater than number. */ public class Trailing0sinFactorial { public int trailing0s(int num){ int pow = 5; int count = 0; while(pow <= num){ count += num/pow; pow *= 5; } return count; } public static void main(String args[]){ Trailing0sinFactorial t0 = new Trailing0sinFactorial(); System.out.println(t0.trailing0s(625)); System.out.println(t0.trailing0s(146)); System.out.println(t0.trailing0s(1046)); System.out.println(t0.trailing0s(4617)); } } ================================================ FILE: src/com/interview/number/UniquePartitionOfInteger.java ================================================ package com.interview.number; import java.util.ArrayList; import java.util.List; /** * http://www.geeksforgeeks.org/generate-unique-partitions-of-an-integer/ * Test cases: * 0 or negative number */ public class UniquePartitionOfInteger { public void partition(int n){ List result = new ArrayList(); partition(n,n,result); } private void partition(int n, int max,List result){ if(n < 0){ return ; } if(n == 0){ result.forEach(i -> System.out.print(i + " ")); System.out.println(); return; } for(int i=Math.min(n, max); i > 0 && i <= max; i--){ result.add(i); partition(n-i,i, result); result.remove(result.size()-1); } } public static void main(String args[]){ UniquePartitionOfInteger upi = new UniquePartitionOfInteger(); upi.partition(12); } } ================================================ FILE: src/com/interview/playground/TestInnerClass.java ================================================ package com.interview.playground; import java.util.Random; /** * Created by tushar_v_roy on 5/18/16. */ public class TestInnerClass { int t = 20; Random random; public Okay test() { final int r = 10; return random::nextInt; } public void test1() { random = new Random(); Okay o1 = test(); System.out.print(o1.next()); Okay o2 = test(); random = null; System.out.print(o2.next()); } public static void main(String args[]) { TestInnerClass testInnerClass = new TestInnerClass(); testInnerClass.test1(); } } interface Okay { int next(); } ================================================ FILE: src/com/interview/random/Rand7UsingRand5.java ================================================ package com.interview.random; public class Rand7UsingRand5 { public int rand7(){ int r = (rand5()-1)*5 + rand5(); while(r > 21){ // I just need to ignore [22, 25] r = (rand5()-1)*5 + rand5(); } return (r%7) + 1; } private int rand5(){ return (int)(Math.ceil(Math.random()*5)); } public static void main(String args[]){ Rand7UsingRand5 rr = new Rand7UsingRand5(); for(int i=0; i < 10; i++){ System.out.print(rr.rand7()); } } } ================================================ FILE: src/com/interview/random/RandomCountrySelectionByPopluation.java ================================================ package com.interview.random; public class RandomCountrySelectionByPopluation { public int getRandom(int []arr){ int sum[] = new int[arr.length]; sum[0] = arr[0]; int n = arr[0]; for(int i=1; i < sum.length; i++){ sum[i] = sum[i-1] + arr[i]; n += arr[i]; } int ran = (int)(Math.random()*n + 1); int low = 0; int high = arr.length-1; int mid = (high + low)/2; while(true){ if(sum[mid] >= ran && (mid-1 == -1 || sum[mid-1] < ran)){ break; } if(sum[mid] > ran){ high = mid-1; }else{ low = mid+1; } mid = (high + low)/2; } return mid; } public static void main(String args[]){ RandomCountrySelectionByPopluation rcsp = new RandomCountrySelectionByPopluation(); int arr[] = {5,5,2,3,7,1}; for(int i=0; i < 10; i++){ System.out.print(rcsp.getRandom(arr)); } } } ================================================ FILE: src/com/interview/random/SelectMRandomNumbersInStream.java ================================================ package com.interview.random; /** * Reservoir Sampling * 150qs 18.3 */ public class SelectMRandomNumbersInStream { public int[] selectRandom(int arr[],int m){ int result[] = new int[m]; for(int i=0; i < m ;i++){ result[i] = arr[i]; } for(int i=m ; i < arr.length; i++){ int random = (int)(Math.random()*i) + 1; if(random <= m){ result[random-1] = arr[i]; } } return result; } public static void main(String args[]){ SelectMRandomNumbersInStream srn = new SelectMRandomNumbersInStream(); int arr[] = {1,2,3,4,5,6,7,8,9,10,11,12,13}; int result[] = srn.selectRandom(arr, 5); for(int i=0; i < result.length; i++){ System.out.print(result[i] + " "); } } } ================================================ FILE: src/com/interview/random/ShuffleArray.java ================================================ package com.interview.random; /** * Shuffle deck of cards * 150 qs 18.2 */ public class ShuffleArray { public void shuffle(int arr[]){ for(int i=arr.length-1; i>=0; i--){ int random = (int)(Math.random()*(i+1)) ; System.out.print(random + " "); swap(arr,random,i); } } private void swap(int arr[],int a,int b){ int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } public static void main(String args[]){ int arr[] = {1,2,3,4,5,6,7,8}; ShuffleArray sa = new ShuffleArray(); sa.shuffle(arr); System.out.println(); for(int i=0; i < arr.length; i++){ System.out.print(arr[i] + " "); } for(int i=0; i < arr.length; i++){ System.out.println((int)(Math.random()*10) + 1); } } } ================================================ FILE: src/com/interview/recursion/AllAdjacentCombination.java ================================================ package com.interview.recursion; /** * Generate all combination of size k and less of adjacent numbers * e.g 1,2,3,4 k = 2 * 1 2 3 4 * 12 3 4 * 1 23 4 * 1 2 3 34 * 12 34 * @author tusroy * */ public class AllAdjacentCombination { public void combination(int input[],int result[],int k,int pos,int r){ if(pos == input.length){ for(int i=0; i < r ; i++){ System.out.print(result[i] + " "); } System.out.println(); return; } for(int i=pos; i < pos + k && i < input.length; i++ ){ result[r] = formNumber(input,pos,i); combination(input,result,k,i+1,r+1); } } private int formNumber(int input[], int start, int end){ int num = 0; for(int i=start; i <=end; i++){ num = num*10 + input[i]; } return num; } public static void main(String args[]){ AllAdjacentCombination adc = new AllAdjacentCombination(); int input[] = {1,2,3,4,5}; int result[] = new int[input.length]; adc.combination(input,result,3,0,0); } } ================================================ FILE: src/com/interview/recursion/Bracketology.java ================================================ package com.interview.recursion; import java.util.Deque; import java.util.LinkedList; public class Bracketology { public boolean matchBracket(char str[],int openCount,int pos){ if(str.length == pos){ if(openCount == 0){ return true; } return false; } if(str[pos] == '('){ openCount++; }else{ openCount--; } if(openCount < 0){ return false; } return matchBracket(str,openCount,pos+1); } private void printArray(char result[]){ for(int i=0; i < result.length; i++){ System.out.print(result[i]); } System.out.println(); } public void bracketPermutation(char result[],int n, int pos,int openCount,int closeCount){ if(pos == 2*n){ printArray(result); return; } if(openCount < n){ result[pos] = '('; bracketPermutation(result, n, pos+1,openCount+1,closeCount); } if(closeCount < openCount){ result[pos] = ')'; bracketPermutation(result, n, pos+1, openCount, closeCount+1); } } public boolean matchBracket(char []brackets){ Deque stack = new LinkedList(); for(Character ch : brackets){ char checkChar = getOpeningCharacter(ch); if(checkChar == 0){ stack.addFirst(ch); }else{ if(stack.size() == 0 || stack.peek() != checkChar){ return false; }else{ stack.pop(); } } } if(stack.size() > 0){ return false; } return true; } private Character getOpeningCharacter(char ch){ switch(ch){ case ')' : return '('; case ']' : return '['; case '}' : return '{'; default : return 0; } } public static void main(String args[]){ Bracketology matcher = new Bracketology(); //System.out.print(matcher.matchBracket("(())())".toCharArray(), 0, 0)); int n=4; char result[] = new char[n*2]; // matcher.bracketPermutation(result, n, 0, 0, 0); System.out.println(matcher.matchBracket("[({()}{}[])]".toCharArray())); } } ================================================ FILE: src/com/interview/recursion/ChainWordsToFormCircle.java ================================================ package com.interview.recursion; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * http://www.geeksforgeeks.org/given-array-strings-find-strings-can-chained-form-circle/ * Test cases: * Empty input * 1 element in input * no chain formed * chain formed */ public class ChainWordsToFormCircle { public List formCircle(String input[]){ List result = new ArrayList(); //since chain is a circle any point can be the start point of the chain. //We make input[0] as start point result.add(input[0]); boolean used[] = new boolean[input.length]; boolean r = formCircle(input,result,used,input[0].charAt(0)); if(!r){ return Collections.emptyList(); } return result; } //we keep track of first char of the chain and the end compare that with last char of last element of the chain private boolean formCircle(String input[], List result,boolean used[],char firstChar){ if(input.length == result.size()){ String str = result.get(result.size()-1); if(firstChar == str.charAt(str.length()-1)){ return true; } return false; } String str = result.get(result.size()-1); char lastChar = str.charAt(str.length()-1); for(int i=1; i < input.length; i++){ if(used[i]){ continue; } if(lastChar == input[i].charAt(0)){ used[i] = true; result.add(input[i]); boolean r = formCircle(input,result,used,firstChar); if(r){ return true; } used[i] = false; result.remove(result.size()-1); } } return false; } public static void main(String args[]){ String notChaininput[] = {"geeks","king", "seeks", "sing","gik","kin"}; String chainInput[] = {"king","gik","geeks", "seeks", "sing"}; ChainWordsToFormCircle cwt = new ChainWordsToFormCircle(); List result = cwt.formCircle(chainInput); if(result.size() == 0){ System.out.println("Not able to form a chain"); }else{ for(String chainNode : result){ System.out.print(chainNode + " "); } } } } ================================================ FILE: src/com/interview/recursion/Combination.java ================================================ package com.interview.recursion; import java.util.*; public class Combination { public void combination(char input[]){ Map countMap = new TreeMap<>(); for (char ch : input) { countMap.compute(ch, (key, val) -> { if (val == null) { return 1; } else { return val + 1; } }); } char str[] = new char[countMap.size()]; int count[] = new int[countMap.size()]; int index = 0; for (Map.Entry entry : countMap.entrySet()) { str[index] = entry.getKey(); count[index] = entry.getValue(); index++; } char[] output = new char[input.length]; combination(str, count, 0, output, 0); } private void combination(char input[],int count[],int pos, char output[],int len){ print(output, len); for(int i=pos; i < input.length; i++){ if (count[i] == 0) { continue; } output[len] = input[i]; count[i]--; combination(input, count, i, output, len + 1); count[i]++; } } private void print(char result[],int pos){ for(int i=0; i < pos; i++){ System.out.print(result[i] + " "); } System.out.println(); } public void combinationEasy(char[] input) { List r = new ArrayList<>(); Arrays.sort(input); combinationEasy(input, 0, r); } private void combinationEasy(char[] input, int pos, List r) { r.forEach(r1 -> System.out.print(r1 + " ")); System.out.println(); for (int i = pos; i < input.length; i++) { if (i != pos && input[i] == input[i-1]) { continue; } r.add(input[i]); combinationEasy(input, i + 1, r); r.remove(r.size() - 1); } } public static void main(String args[]){ Combination c = new Combination(); c.combination("aabbc".toCharArray()); c.combinationEasy("aabbc".toCharArray()); } } ================================================ FILE: src/com/interview/recursion/CombinationOfSizeK.java ================================================ package com.interview.recursion; /** * http://www.geeksforgeeks.org/print-all-possible-combinations-of-r-elements-in-a-given-array-of-size-n/ */ public class CombinationOfSizeK { public void combination(int arr[],int k){ int result[] = new int[k]; combinationUtil(arr,k,0,result,0); } private void combinationUtil(int arr[],int k, int pos,int result[],int start){ if(pos == k){ for(int i=0; i < k; i++){ System.out.print(result[i] + " "); } System.out.print("\n"); return; } for(int i=start; i < arr.length; i++){ result[pos] = arr[i]; combinationUtil(arr,k,pos+1,result,i+1); } } public static void main(String args[]){ CombinationOfSizeK kk = new CombinationOfSizeK(); int arr[] = {1,2,3,4}; kk.combination(arr, 2); } } ================================================ FILE: src/com/interview/recursion/CombinationWithStar.java ================================================ package com.interview.recursion; /** * e.g a, b c * * * * * a * * * a b * * a b c * * b * * * b c * * * c * * Idea is to store the index of values in used[] array. So just * like regular combination if used is set print it else print * */ public class CombinationWithStar { public void combine(char input[], int pos, boolean used[]){ printArray(input, used); for(int i= pos; i < input.length; i++){ used[i] = true; combine(input, i+1, used); used[i] = false; } } private void printArray(char result[], boolean used[]){ for(int i=0; i < used.length; i++){ if(used[i]){ System.out.print(result[i] + " "); }else{ System.out.print("* "); } } System.out.println(); } public static void main(String args[]){ char input[] = {'a','b','c','d'}; CombinationWithStar cws = new CombinationWithStar(); boolean used[] = new boolean[input.length]; cws.combine(input, 0, used); } } ================================================ FILE: src/com/interview/recursion/DifferentWaysToAddParentheses.java ================================================ package com.interview.recursion; import java.util.*; /** https://leetcode.com/problems/different-ways-to-add-parentheses/ */ public class DifferentWaysToAddParentheses { public List diffWaysToCompute(String str) { List operands = new ArrayList<>(); List operators = new ArrayList<>(); int prev = -1; for (int i = 0; i < str.length(); i++) { if (str.charAt(i) == '+' || str.charAt(i) == '-' || str.charAt(i) == '*') { operands.add(Integer.parseInt(str.substring(prev + 1, i))); operators.add(str.charAt(i)); prev = i; } } operands.add(Integer.parseInt(str.substring(prev + 1, str.length()))); return diffWaysToComputeUtil(operands, operators, 0, operators.size() - 1); } private List diffWaysToComputeUtil(List operands, List operators, int start, int end) { if (start > end) { if (start >= 0) { return Collections.singletonList(operands.get(start)); } else { return Collections.singletonList(operands.get(end)); } } List result = new ArrayList<>(); for (int i = start; i <= end; i++) { List leftResult = diffWaysToComputeUtil(operands, operators, start, i - 1); List rightResult = diffWaysToComputeUtil(operands, operators, i + 1, end); for (int left : leftResult) { for (int right : rightResult) { result.add((int)operate(left, right, operators.get(i))); } } } return result; } private long operate(int val1, int val2, char op) { switch (op) { case '+': return val1 + val2; case '-': return val1 - val2; case '*': return val1 * val2; } throw new IllegalArgumentException(); } public static void main(String args[]) { DifferentWaysToAddParentheses df = new DifferentWaysToAddParentheses(); List result = df.diffWaysToCompute("2*3-4*5"); result.forEach(s -> System.out.println(s)); } } ================================================ FILE: src/com/interview/recursion/FancyShuffle.java ================================================ package com.interview.recursion; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; /** * Date 07/05/2015 * @author Tushar Roy * * Given an input with duplicate characters generate a shuffle which does not have * two duplicate characters together * * Do regular permutation with repetition with additional constraint of keeping * duplicates away from each other. * */ public class FancyShuffle { public char[] shuffle(char input[]){ char result[] = new char[input.length]; //create a map of character to its frequency. Map map = new HashMap(); for(int i=0; i < input.length; i++){ Integer count = map.putIfAbsent(input[i], 1); if(count != null) { count++; map.put(input[i], count); } } char newInput[] = new char[map.size()]; int freq[] = new int[map.size()]; //create a new char array and freq array from map. int index = 0; for(Entry entry : map.entrySet()){ newInput[index] = entry.getKey(); freq[index] = entry.getValue(); index++; } //assuming char with ASCII value 0 does not exists in the input shuffleUtil(newInput,freq, result, 0, (char)0); return result; } //regular permutation code. If we do find a permutation which satisfies the //constraint then return true and stop the process. private boolean shuffleUtil(char input[], int freq[], char result[], int pos, char lastVal) { if(pos == result.length){ return true; } for(int i=0; i < input.length; i++){ if(lastVal == input[i]) { continue; } if(freq[i] == 0) { continue; } freq[i]--; result[pos] = input[i]; if(shuffleUtil(input, freq, result, pos+1, input[i])){ return true; } freq[i]++; } return false; } public static void main(String args[]) { FancyShuffle fs = new FancyShuffle(); char result[] = fs.shuffle("bbcdaaaaa".toCharArray()); for(char ch : result) { System.out.print(ch); } } } ================================================ FILE: src/com/interview/recursion/InterpretationOfArray.java ================================================ package com.interview.recursion; import java.util.ArrayList; import java.util.List; /** * http://www.geeksforgeeks.org/find-all-possible-interpretations/ */ public class InterpretationOfArray { public void interpret(int arr[]){ char t[][] = new char[arr.length][2]; for(int i=0; i < arr.length; i++){ for(int j=0; j < 2; j++){ t[i][j] = '0'; } } for(int l=1; l <=2; l++){ for(int i=0; i <= arr.length -l ; i++){ int j = i + l-1; t[i][l-1] = getRepresentation(i == j ? arr[i] : arr[i]*10 +arr[j]); } } List result = new ArrayList(); interpret(arr.length,0,result,t); } private void interpret(int len,int pos,List result,char[][] t){ if(pos== len){ print(result); return; } if(t[pos][0] != '0'){ result.add(t[pos][0]); interpret(len,pos+1,result,t); result.remove(result.size()-1); } if(pos+1 < len && t[pos][1] != '0'){ result.add(t[pos][1]); interpret(len, pos+2, result, t); result.remove(result.size()-1); } } private void print(List result){ for(int i=0; i < result.size(); i++){ System.out.print(result.get(i) + " "); } System.out.println(); } private char getRepresentation(int number){ if(number > 26 || number <= 0){ return '0'; } return (char)('a' + number -1); } public static void main(String args[]){ int arr[] = {1,2,6,1,7}; InterpretationOfArray ioa = new InterpretationOfArray(); ioa.interpret(arr); } } ================================================ FILE: src/com/interview/recursion/KeyPadPermutation.java ================================================ package com.interview.recursion; /** * http://stackoverflow.com/questions/2344496/how-can-i-print-out-all-possible-letter-combinations-a-given-phone-number-can-re */ public class KeyPadPermutation { public void permute(int input[]) { char result[] = new char[input.length]; permute(input,0,result); } private void permute(int input[], int pos, char result[]) { if (pos == input.length) { for (int i = 0; i < result.length; i++) { System.out.print(result[i]); } System.out.println(); return; } char[] str = getCharSetForNumber(input[pos]); for (char ch : str) { result[pos] = ch; permute(input, pos+1, result); } } private char[] getCharSetForNumber(int num) { switch(num){ case 1 : return "abc".toCharArray(); case 2 : return "def".toCharArray(); case 3: return "ghi".toCharArray(); case 4: return "jkl".toCharArray(); case 5: return "mno".toCharArray(); case 6: return "pqrs".toCharArray(); case 8: return "tuv".toCharArray(); case 9: return "wxyz".toCharArray(); } throw new IllegalArgumentException(); } public static void main(String args[]){ int input[] = {2,3,1,5}; KeyPadPermutation kpp = new KeyPadPermutation(); kpp.permute(input); } } ================================================ FILE: src/com/interview/recursion/LongestAbsolutePath.java ================================================ package com.interview.recursion; import java.util.LinkedList; import java.util.Queue; import java.util.Stack; import java.util.StringTokenizer; /** * Find longest absolute path in file system indicated by \n and \t. * * Solution 1: * Create queue of file and its level. Then recurse from root towards file. Use level * to decide if next word in queue is in same level (so no more recursion) or next level so * going deep in recursion. * * Solution 2(iterative): * Keep pushing elements into stack till you either reach a file with . or a file whose number of tabs is less than * top of stack. If you reach file with extension then update the max. Otherwise keep popping from stack till number of tabs * at top of stack becomes less than current file. Maintain current length during push and pop. * * Time complexity O(n) * Space complexity O(n) * * https://leetcode.com/problems/longest-absolute-file-path/ */ public class LongestAbsolutePath { public int lengthLongestPath(String input) { if (input.length() == 0) { return 0; } StringTokenizer tokenizer = new StringTokenizer(input, "\n"); Queue queue = new LinkedList<>(); while (tokenizer.hasMoreTokens()) { queue.offer(new Node(tokenizer.nextToken())); } Node root = new Node("", -1); return lengthLongestPath(queue, root, 0); } public int lengthLongestPath(Queue queue, Node root, int currentLength) { if (root.isFile) { return currentLength + root.level; } if (queue.isEmpty()) { return 0; } int max = 0; while (!queue.isEmpty()) { Node n = queue.peek(); if (root.level < n.level) { queue.poll(); max = Math.max(max, lengthLongestPath(queue, n, n.file.length() + currentLength)); } else { break; } } return max; } class Node { String file; int level; boolean isFile; Node(String file, int level) { this.file = file; this.level = level; } Node(String file) { int numberOfTabs = 0; int i; for (i = 0; i < file.length(); i++) { if (file.charAt(i) == '\t') { numberOfTabs++; } else { break; } } this.file = file.substring(i); this.level = numberOfTabs; this.isFile = file.contains("."); } } public int lengthLongestPathIterative(String input) { if (input.length() == 0) { return 0; } String[] tokens = input.split("\n"); Stack stack = new Stack<>(); Stack stack1 = new Stack<>(); int len = 0; int max = 0; for (String token : tokens) { int level = 0; int i; for (i = 0; i < token.length(); i++) { if (token.charAt(i) == '\t') { level++; } else { break; } } token = token.substring(i); while (!stack1.isEmpty() && level <= stack1.peek()) { stack1.pop(); String data = stack.pop(); len -= data.length() + 1; //+1 to account for '\' between folders files } if (token.contains(".")) { max = Math.max(max, len + token.length()); } else { stack1.push(level); stack.push(token); len += token.length() + 1; //+1 to accoutn for '\' between folders files } } return max; } } ================================================ FILE: src/com/interview/recursion/MinimumEditForReversePolishNotation.java ================================================ package com.interview.recursion; /** *http://www.careercup.com/question?id=5762415492857856 */ public class MinimumEditForReversePolishNotation { public int minimum(char input[]){ return minimum(input,0,0); } private int minimum(char input[],int pos,int countXs){ if(pos == input.length){ //we should be always be left with 1 x otherwise notation is incomplete if(countXs > 1){ return Integer.MAX_VALUE; } return 0; } //if input is x we can have x as it is or delete it or convert it to *. //So basically we try all those options below //If input is * we can take 2 xs and conver it to one x. If we dont have //2xs then we can either delete this * or convert it to x. //Remember adding anything does not make any sense since deleting things //can achieve same things unless cost of adding is different from deleting if(input[pos] == 'x'){ int v1 = minimum(input,pos+1,countXs+1); int v2 = Integer.MAX_VALUE; if(countXs > 1){ v2 = minimum(input,pos+1,countXs-1); v2 =( v2 != Integer.MAX_VALUE ? v2 + 1 : Integer.MAX_VALUE); } int v3 = minimum(input,pos+1,countXs); v3 =( v3 != Integer.MAX_VALUE ? v3 + 1 : Integer.MAX_VALUE); return Math.min(Math.min(v1,v2),v3); }else{ if(countXs >= 2){ return minimum(input,pos+1,countXs-1); }else{ int v1 = minimum(input,pos+1,countXs); v1 = (v1 != Integer.MAX_VALUE ? v1 + 1 : Integer.MAX_VALUE); int v2 = minimum(input,pos+1,countXs+1); v2 =( v2 != Integer.MAX_VALUE ? v2 + 1 : Integer.MAX_VALUE); return Math.min(v1, v2); } } } public static void main(String args[]){ MinimumEditForReversePolishNotation mef = new MinimumEditForReversePolishNotation(); System.out.println(mef.minimum("xxxx*x*x*".toCharArray())); } } ================================================ FILE: src/com/interview/recursion/NQueenProblem.java ================================================ package com.interview.recursion; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; /** * Date 02/20/2016 * @author Tushar Roy * * Given nxn board place n queen on this board so that they dont attack each other. One solution is to find * any placement of queens which do not attack each other. Other solution is to find all placements of queen * on the board. * * Time complexity O(n*n) * Space complexity O(n*n) */ public class NQueenProblem { class Position { int row, col; Position(int row, int col) { this.row = row; this.col = col; } } public Position[] solveNQueenOneSolution(int n) { Position[] positions = new Position[n]; boolean hasSolution = solveNQueenOneSolutionUtil(n, 0, positions); if (hasSolution) { return positions; } else { return new Position[0]; } } private boolean solveNQueenOneSolutionUtil(int n, int row, Position[] positions) { if (n == row) { return true; } int col; for (col = 0; col < n; col++) { boolean foundSafe = true; //check if this row and col is not under attack from any previous queen. for (int queen = 0; queen < row; queen++) { if (positions[queen].col == col || positions[queen].row - positions[queen].col == row - col || positions[queen].row + positions[queen].col == row + col) { foundSafe = false; break; } } if (foundSafe) { positions[row] = new Position(row, col); if (solveNQueenOneSolutionUtil(n, row + 1, positions)) { return true; } } } return false; } /* *Solution for https://leetcode.com/problems/n-queens/ */ public List> solveNQueens(int n) { List> result = new ArrayList<>(); Position[] positions = new Position[n]; solve(0, positions, result, n); return result; } public void solve(int current, Position[] positions, List> result, int n) { if (n == current) { StringBuffer buff = new StringBuffer(); List oneResult = new ArrayList<>(); for (Position p : positions) { for (int i = 0; i < n; i++) { if (p.col == i) { buff.append("Q"); } else { buff.append("."); } } oneResult.add(buff.toString()); buff = new StringBuffer(); } result.add(oneResult); return; } for (int i = 0; i < n; i++) { boolean foundSafe = true; for (int j = 0; j < current; j++) { if (positions[j].col == i || positions[j].col - positions[j].row == i - current || positions[j].row + positions[j].col == i + current) { foundSafe = false; break; } } if (foundSafe) { positions[current] = new Position(current, i); solve(current + 1, positions, result, n); } } } public static void main(String args[]) { NQueenProblem s = new NQueenProblem(); Position[] positions = s.solveNQueenOneSolution(6); Arrays.stream(positions).forEach(position -> System.out.println(position.row + " " + position.col)); } } ================================================ FILE: src/com/interview/recursion/OneEditApart.java ================================================ package com.interview.recursion; /** * Date 03/26/2016 * @author Tushar Roy * Given two strings S and T, determine if they are both one edit distance apart. * * Time complexity O(n) * Space complexity O(1) * * Reference * https://leetcode.com/problems/one-edit-distance/ */ public class OneEditApart { public boolean isOneEditDistance(String s, String t) { String larger, smaller; if (s.length() < t.length()) { larger = t; smaller = s; } else { larger = s; smaller = t; } if (Math.abs(larger.length() - smaller.length()) > 1) { return false; } boolean diffFound = false; int j = 0; for (int i = 0; i < smaller.length();) { if (smaller.charAt(i) == larger.charAt(j)) { i++; j++; } else { if (diffFound) { return false; } else { diffFound = true; if (smaller.length() == larger.length()) { i++; j++; } else { j++; } } } } return diffFound || j < larger.length(); } public static void main(String args[]){ OneEditApart oea = new OneEditApart(); System.out.println(oea.isOneEditDistance("cat", "dog")); System.out.println(oea.isOneEditDistance("cat", "cats")); System.out.println(oea.isOneEditDistance("cat", "cut")); System.out.println(oea.isOneEditDistance("cats", "casts")); System.out.println(oea.isOneEditDistance("catsts", "casts")); } } ================================================ FILE: src/com/interview/recursion/OperatorAdditionForTarget.java ================================================ package com.interview.recursion; import java.util.ArrayList; import java.util.List; /** * Date 02/23/2016 * @author Tushar Roy * * Given a string eg. 123 and target e.g 6. Put operators *, +, - between 123 so that it evaluates to 6 * * https://leetcode.com/problems/expression-add-operators/ */ public class OperatorAdditionForTarget { public List addOperators(String num, int target) { if (num.length() == 0) { return new ArrayList<>(); } List result = new ArrayList<>(); StringBuffer buff = new StringBuffer(); dfs(num, 0, target, 0, 0, result, buff); return result; } private void dfs(String nums, int pos, int target, long runningTotal, long multiplicationVal, List result, StringBuffer buff) { if (pos == nums.length()) { if (runningTotal == target) { result.add(buff.toString()); } return; } for (int i = pos; i < nums.length(); i++) { if (i != pos && nums.charAt(pos) == '0') { break; } String subStr = nums.substring(pos, i + 1); long num = Long.parseLong(subStr); if (pos == 0) { dfs(nums, i + 1, target, num, num, result, buff.append(num)); buff.delete(buff.length() - subStr.length(), buff.length()); continue; } dfs(nums, i + 1, target, runningTotal + num, num, result, buff.append("+").append(subStr)); buff.delete(buff.length() - subStr.length() - 1, buff.length()); dfs(nums, i + 1, target, runningTotal - num, -num, result, buff.append("-").append(subStr)); buff.delete(buff.length() - subStr.length() - 1, buff.length()); dfs(nums, i + 1, target, runningTotal + num * multiplicationVal - multiplicationVal, num * multiplicationVal, result, buff.append("*").append(subStr)); buff.delete(buff.length() - subStr.length() - 1, buff.length()); } } public static void main(String args[]) { OperatorAdditionForTarget p = new OperatorAdditionForTarget(); List result = p.addOperators("1234", -1); result.stream().forEach(s -> System.out.println(s)); } } ================================================ FILE: src/com/interview/recursion/OptimalDivision.java ================================================ package com.interview.recursion; /** * Date 05/09/2017 * @author Tushar Roy * * https://leetcode.com/problems/optimal-division/#/description */ public class OptimalDivision { public String optimalDivision(int[] nums) { Result r = optimalDivison(nums, 0, nums.length - 1, true); System.out.println(r.val); return r.str; } private Result optimalDivison(int[] nums, int start, int end, boolean maximize) { if (start == end) { return new Result(nums[start], String.valueOf(nums[start])); } double maxResult = 0; double minResult = Double.MAX_VALUE; String result = ""; int cutI = start; String part1 = ""; String part2 = ""; for (int i = start; i < end; i++) { Result d1 = optimalDivison(nums, start, i, maximize); Result d2 = optimalDivison(nums, i + 1, end, !maximize); double val = d1.val / d2.val; if (maximize) { if (maxResult < val) { maxResult = val; part1 = d1.str; part2 = d2.str; cutI = i; } } else { if (minResult > val) { minResult = val; part1 = d1.str; part2 = d2.str; cutI = i; } } } if (cutI < end - 1) { result = part1 + "/(" + part2 + ")"; } else { result = part1 + "/" + part2; } return maximize ? new Result(maxResult, result) : new Result(minResult, result); } class Result { double val; String str; Result(double val, String str) { this.val = val; this.str = str; } } public static void main(String args[]) { // int[] nums = {1000, 100, 10, 2}; int[] nums = {6,2,3,4,5}; OptimalDivision od = new OptimalDivision(); System.out.println(od.optimalDivision(nums)); } } ================================================ FILE: src/com/interview/recursion/PrintAllPathFromTopLeftToBottomRight.java ================================================ package com.interview.recursion; import java.util.Arrays; /** http://www.geeksforgeeks.org/print-all-possible-paths-from-top-left-to-bottom-right-of-a-mxn-matrix/ */ public class PrintAllPathFromTopLeftToBottomRight { public void print(int arr[][],int row, int col,int result[],int pos){ if(row == arr.length-1 && col == arr[0].length-1){ result[pos] = arr[row][col]; System.out.println(Arrays.toString(result)); return; } if(row >= arr.length || col >= arr[0].length){ return; } result[pos] = arr[row][col]; print(arr,row,col+1,result,pos+1); print(arr,row+1,col,result,pos+1); } public static void main(String args[]){ PrintAllPathFromTopLeftToBottomRight pam = new PrintAllPathFromTopLeftToBottomRight(); int arr[][] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; int result[] = new int[arr.length + arr[0].length-1]; pam.print(arr, 0, 0, result,0); } } ================================================ FILE: src/com/interview/recursion/PrintAllSubsequence.java ================================================ package com.interview.recursion; /** * Date 02/25/2016 * @author Tushar Roy * * Print all subsequence of a given array. * * Time complexity is exponential * Space complexity is O(n) */ public class PrintAllSubsequence { public void print(int[] input) { int[] output = new int[input.length]; for (int i = 0; i < input.length; i++) { output[0] = input[i]; print(input, output, 1, i + 1, true); } } private void print(int[] input, int[] output, int len, int current, boolean print) { if (print) { for (int i = 0; i < len; i++) { System.out.print(output[i] + " "); } System.out.println(); } if (current == input.length) { return; } output[len] = input[current]; print(input, output, len + 1, current + 1, true); print(input, output, len, current + 1, false); } public static void main(String args[]) { PrintAllSubsequence ps = new PrintAllSubsequence(); int[] input = {1, 2, 3, 4}; ps.print(input); } } ================================================ FILE: src/com/interview/recursion/PrintArrayInAdjacentWay.java ================================================ package com.interview.recursion; import java.util.ArrayList; import java.util.List; /** * http://www.geeksforgeeks.org/find-all-possible-interpretations/ * This is class fibonacci series example. * e.g {1,1,1,1} -> when n = 4 total number of ways possible are * f(3) + f(2). * Suppose we solved for n =3 . When we add another 1 we know that total number * of combinations without this 1 doing anything will be f(3). Not if we involve this new 1 * and exclude f(3) we get total of f(2) because think of as if we combined last 2 ones and * then see how many ways first 2 ones can combine * example * {1,1,1, new1} * f(3) is all combinations without including new1 * Now lets combine {1,1,newnew1} . This gives total of f(2) * Test cases * negative number * 0 * null array */ public class PrintArrayInAdjacentWay { public void printArray(int len,int k){ List result = new ArrayList(); printArray(len,0,result,k); } private void printArray(int len, int pos,List result,int k){ if(pos > len){ return; } if(pos == len){ for(int i:result){ System.out.print(i + " "); } System.out.println(); return ; } for(int i=0; i < k ; i++){ result.add(i+1); printArray(len,pos+i+1,result,k); result.remove(result.size()-1); } } public int numberOfWaysPossible(int input[],int pos){ if(pos > input.length){ return 0; } if(pos == input.length){ return 1; } int count = numberOfWaysPossible(input,pos+1); if(pos + 1 < input.length){ int num = input[pos]*10 + input[pos+1]; if(num < 27){ count += numberOfWaysPossible(input, pos+2); } } return count; } /** * Since we know this is same as fibonacci series all we have to do is either use sum of last two numbers if * total is less than equal to 26 or use just last number if total is greater than 26 * total is calculated by creating a number from current number and previous number * @param input * @return */ public int numberOfWaysPossibleFaster(int input[]){ int a0 = 1; int a1 = 1; int c = 0; for(int i=1; i < input.length; i++){ if(input[i] + input[i-1]*10 <=26){ c = a1 + a0; }else{ c = a1; } a0 = a1; a1 = c; } return c; } public static void main(String args[]){ PrintArrayInAdjacentWay paw = new PrintArrayInAdjacentWay(); // paw.printArray(5, 2); int input[] = {1,3,7,7,1,7,2,3,2}; System.out.println(paw.numberOfWaysPossible(input, 0)); System.out.println(paw.numberOfWaysPossibleFaster(input)); } } ================================================ FILE: src/com/interview/recursion/PrintArrayInCustomizedFormat.java ================================================ package com.interview.recursion; import java.util.HashMap; import java.util.Map; /** * http://www.geeksforgeeks.org/custom-tree-problem/ */ public class PrintArrayInCustomizedFormat { void print(char str[][]){ Map visited = new HashMap(); Map alreadyPrinted = new HashMap(); for(int i=0 ; i < str.length; i++){ if(!visited.containsKey(str[i][0]) || !visited.get(str[i][0])){ if(!alreadyPrinted.containsKey(str[i][0]) || !alreadyPrinted.get(str[i][0])){ System.out.println(str[i][0]); alreadyPrinted.put(str[i][0],true); } DFS(str,i,5,visited); } } } private void DFS(char str[][],int pos,int distance,Map visited){ for(int i=0; i < distance; i++){ System.out.print(" "); } System.out.println(str[pos][1]); char ch = str[pos][1]; visited.put(ch, true); int i = pos+1; for(; i < str.length; i++){ if(ch == str[i][0]){ if(i != str.length){ DFS(str,i,distance + 5,visited); } } } } public static void main(String args[]){ char str[][] = {{'a','b'},{'a','c'},{'b','d'},{'c','f'},{'b','e'},{'x','y'},{'y','z'}}; PrintArrayInCustomizedFormat pac = new PrintArrayInCustomizedFormat(); pac.print(str); } } ================================================ FILE: src/com/interview/recursion/PrintSumCombination.java ================================================ package com.interview.recursion; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Date 07/10/2015 * @author Tushar Roy * * Given an input and total print all combinations with repetitions in this input * which sums to given total. * e.g * input - {2,3,5} * total - 10 * * Output * [2,2,2,2,2], * [2,2,3,3], * [2,3,5], * [5,5]] * Reference * https://leetcode.com/problems/combination-sum/ */ public class PrintSumCombination { public List> combinationSum(int[] candidates, int target) { if (candidates.length == 0) { return new ArrayList<>(); } List> rr = new ArrayList<>(); List r = new ArrayList<>(); Arrays.sort(candidates); combinationSumUtil(candidates, target, r, rr, 0); return rr; } private void combinationSumUtil(int[] candidates, int target, List r, List> rr, int pos) { if (target == 0) { List r1 = new ArrayList<>(); r1.addAll(r); rr.add(r1); return; } if (target < 0) { return; } if (pos == candidates.length) { return; } r.add(candidates[pos]); combinationSumUtil(candidates, target - candidates[pos], r, rr, pos); r.remove(r.size() - 1); combinationSumUtil(candidates, target, r, rr, pos + 1); } public static void main(String args[]) { int input[] = {2,3,5}; PrintSumCombination psc = new PrintSumCombination(); List> result = psc.combinationSum(input, 10); result.forEach(r -> { r.forEach(r1 -> System.out.print(r1 + " ")); System.out.println(); }); } } ================================================ FILE: src/com/interview/recursion/ReconstructItinerary.java ================================================ package com.interview.recursion; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Date 03/08/2016 * @author Tushar Roy * * Reconstruct itinerary based on ticket. * * https://leetcode.com/problems/reconstruct-itinerary/ */ public class ReconstructItinerary { public List findItinerary(String[][] tickets) { List input = new ArrayList<>(); for (String[] ticket : tickets) { input.add(new Itinerary(ticket[0], ticket[1])); } Collections.sort(input); List output = new ArrayList<>(); boolean[] used = new boolean[input.size()]; findItineraryUtil(input, used, "JFK", output, 0); return output; } boolean findItineraryUtil(List input, boolean[] used, String end, List output, int count) { if (count == used.length) { output.add(end); return true; } for (int i = 0; i < input.size(); i++) { if (used[i]) { continue; } Itinerary itr = input.get(i); if (itr.start.equals(end)) { output.add(itr.start); used[i] = true; if (findItineraryUtil(input, used, itr.dest, output, count + 1)) { return true; } used[i] = false; output.remove(output.size() - 1); } } return false; } class Itinerary implements Comparable { String start; String dest; Itinerary(String start, String dest) { this.start = start; this.dest = dest; } @Override public int compareTo(Itinerary other) { if (this.start.equals(other.start)) { return this.dest.compareTo(other.dest); } else { return this.start.compareTo(other.start); } } } public static void main(String args[]) { String input[][] = {{"MUC","LHR"},{"JFK","MUC"},{"SFO","SJC"},{"LHR","SFO"}}; ReconstructItinerary ri = new ReconstructItinerary(); List output = ri.findItinerary(input); output.forEach(r -> System.out.print(r + " ")); } } ================================================ FILE: src/com/interview/recursion/RemoveInvalidParenthesis.java ================================================ package com.interview.recursion; import java.util.*; /** * Date 03/03/2016 * @author Tushar Roy * * Remove the minimum number of invalid parentheses in order to make the input string valid. * Return all possible results * * Reference * https://leetcode.com/problems/remove-invalid-parentheses/ */ public class RemoveInvalidParenthesis { public List removeInvalidParentheses(String s) { Set res = new HashSet<>(); int rmL = 0, rmR = 0; for(int i = 0; i < s.length(); i++) { if(s.charAt(i) == '(') rmL++; if(s.charAt(i) == ')') { if(rmL != 0) rmL--; else rmR++; } } DFS(res, s, 0, rmL, rmR, 0, new StringBuilder()); return new ArrayList(res); } public void DFS(Set res, String s, int i, int rmL, int rmR, int open, StringBuilder sb) { if(i == s.length() && rmL == 0 && rmR == 0 && open == 0) { res.add(sb.toString()); return; } if(i == s.length() || rmL < 0 || rmR < 0 || open < 0) return; char c = s.charAt(i); int len = sb.length(); if(c == '(') { DFS(res, s, i + 1, rmL - 1, rmR, open, sb); DFS(res, s, i + 1, rmL, rmR, open + 1, sb.append(c)); } else if(c == ')') { DFS(res, s, i + 1, rmL, rmR - 1, open, sb); DFS(res, s, i + 1, rmL, rmR, open - 1, sb.append(c)); } else { DFS(res, s, i + 1, rmL, rmR, open, sb.append(c)); } sb.setLength(len); } public static void main(String args[]) { String s = "(r(()()("; RemoveInvalidParenthesis rmp = new RemoveInvalidParenthesis(); List result = rmp.removeInvalidParentheses(s); result.forEach(s1 -> System.out.println(s1)); } } ================================================ FILE: src/com/interview/recursion/RestoreIPAddresses.java ================================================ package com.interview.recursion; import java.util.*; /** * Date 04/04/2016 * @author Tushar Roy * * Given a string containing only digits, restore it by returning all possible valid IP address combinations. * * Reference * https://leetcode.com/problems/restore-ip-addresses/ */ public class RestoreIPAddresses { public List restoreIpAddresses(String s) { List result = new ArrayList<>(); List current = new ArrayList<>(); restoreIpAddressesUtil(s, 0, 0, result, current); return result; } private void restoreIpAddressesUtil(String s, int start, int count, List result, List current) { if (start == s.length() && count == 4) { StringBuffer stringBuffer = new StringBuffer(current.get(0)); for (int i = 1; i < current.size(); i++) { stringBuffer.append(".").append(current.get(i)); } result.add(stringBuffer.toString()); return; } else if (start == s.length() || count == 4) { return; } for (int i = start; i < s.length() && i < start + 3; i++) { if (i != start && s.charAt(start) == '0') { break; } String ip = s.substring(start, i + 1); if (Integer.valueOf(ip) > 255) { continue; } current.add(ip); restoreIpAddressesUtil(s, i + 1, count + 1, result, current); current.remove(current.size() - 1); } } } ================================================ FILE: src/com/interview/recursion/SetPairTogether.java ================================================ package com.interview.recursion; import java.util.HashMap; import java.util.Map; /** * Date 12/30/2015 * @author Tushar Roy * * Given input array with every element in array having its pair element. How many minimum swaps needs to be * done so that all pair elements are adjacent to each other. * * Time complexity is O(2^n) * * http://www.geeksforgeeks.org/minimum-number-of-swaps-required-for-arranging-pairs-adjacent-to-each-other/ */ public class SetPairTogether { public int findMinimumSwaps(int input[], Map pair) { Map index = new HashMap<>(); for (int i = 0; i < input.length; i++) { index.put(input[i], i); } return findMinimumSwapsUtil(input, pair, index, 0); } public int findMinimumSwapsUtil(int input[], Map pair, Map index, int current) { if (current == input.length) { return 0; } int v1 = input[current]; int v2 = input[current + 1]; int pv2 = pair.get(v1); if(pv2 == v2) { return findMinimumSwapsUtil(input, pair, index, current + 2); } else { int idx1 = index.get(v1); int idx2 = index.get(v2); int idx3 = index.get(pair.get(v1)); int idx4 = index.get(pair.get(v2)); swap(index, input, idx2, idx3); int val1 = findMinimumSwapsUtil(input, pair, index, current + 2); swap(index, input, idx2, idx3); swap(index, input, idx1, idx4); int val2 = findMinimumSwapsUtil(input, pair, index, current + 2); swap(index, input, idx1, idx4); return 1 + Math.min(val1, val2); } } private void swap(Map index, int input[], int i, int j) { index.compute(input[i], (k, v) -> j); index.compute(input[j], (k, v) -> i); int t = input[i]; input[i] = input[j]; input[j] = t; } public static void main(String args[]) { SetPairTogether spt = new SetPairTogether(); int input[] = {3, 5, 6, 4, 1, 2}; Map pair = new HashMap<>(); pair.put(1, 3); pair.put(3, 1); pair.put(2, 6); pair.put(6, 2); pair.put(4, 5); pair.put(5 ,4); System.out.println(spt.findMinimumSwaps(input, pair)); } } ================================================ FILE: src/com/interview/recursion/StringInterleaving.java ================================================ package com.interview.recursion; public class StringInterleaving { private void printArray(char[] str){ for(int i=0; i < str.length; i++){ System.out.print(str[i]); } System.out.println(); } public void interleaving(char[] str1,char[] str2,int len1,int len2,int current, char []result){ if(current == result.length){ printArray(result); return; } if(len1 < str1.length){ result[current] = str1[len1]; interleaving(str1, str2, len1+1, len2, current+1, result); } if(len2 < str2.length){ result[current] = str2[len2]; interleaving(str1,str2,len1,len2+1,current+1,result); } } public static void main(String args[]){ StringInterleaving si = new StringInterleaving(); String str1 ="AB"; String str2 = "CDE"; char[] result = new char[str1.length() + str2.length()]; si.interleaving(str1.toCharArray(), str2.toCharArray(), 0, 0, 0, result); } } ================================================ FILE: src/com/interview/recursion/StringPermutation.java ================================================ package com.interview.recursion; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TreeMap; /** * Date 01/29/2016 * @author Tushar Roy * * Generate all permutations of string in lexicographically sorted order where repetitions of * character is possible in string. */ public class StringPermutation { public List permute(char input[]) { Map countMap = new TreeMap<>(); for (char ch : input) { countMap.compute(ch, (key, val) -> { if (val == null) { return 1; } else { return val + 1; } }); } char str[] = new char[countMap.size()]; int count[] = new int[countMap.size()]; int index = 0; for (Map.Entry entry : countMap.entrySet()) { str[index] = entry.getKey(); count[index] = entry.getValue(); index++; } List resultList = new ArrayList<>(); char result[] = new char[input.length]; permuteUtil(str, count, result, 0, resultList); return resultList; } public void permuteUtil(char str[], int count[], char result[], int level, List resultList) { if (level == result.length) { resultList.add(new String(result)); return; } for(int i = 0; i < str.length; i++) { if(count[i] == 0) { continue; } result[level] = str[i]; count[i]--; permuteUtil(str, count, result, level + 1, resultList); count[i]++; } } private void printArray(char input[]) { for(char ch : input) { System.out.print(ch); } System.out.println(); } public static void main(String args[]) { StringPermutation sp = new StringPermutation(); sp.permute("AABC".toCharArray()).forEach(s -> System.out.println(s)); } } ================================================ FILE: src/com/interview/recursion/StringPermutationRotation.java ================================================ package com.interview.recursion; public class StringPermutationRotation { private void swap(char arr[],int i, int j){ char temp = arr[i]; arr[i] = arr[j]; arr[j] =temp; } private void printArray(char str[]){ for(int i=0; i< str.length; i++){ System.out.print(str[i]); } System.out.print("\n"); } public void permute(char[] str,int pos){ if(pos == str.length){ printArray(str); return; } for(int i=pos; i < str.length; i++){ swap(str,pos,i); permute(str,pos+1); swap(str,pos,i); } } public static void main(String args[]){ String str = "ABC"; StringPermutationRotation sp = new StringPermutationRotation(); sp.permute(str.toCharArray(),0); } } ================================================ FILE: src/com/interview/recursion/SudokuSolver.java ================================================ package com.interview.recursion; import java.util.Arrays; /** * Date 03/24/2016 * @author Tushar Roy * * Write a program to solve a Sudoku puzzle by filling the empty cells. * * https://leetcode.com/problems/sudoku-solver/ */ public class SudokuSolver { public void solveSudoku(char[][] input) { boolean[][] horizontal = new boolean[9][9]; boolean[][] vertical = new boolean[9][9]; boolean[][] box = new boolean[9][9]; for (int i = 0; i < input.length; i++) { for (int j = 0; j < input[0].length; j++) { if (input[i][j] == '.') { continue; } horizontal[i][input[i][j] - '1'] = true; vertical[j][input[i][j] - '1'] = true; int index = 3*(i/3) + j/3; box[index][input[i][j] - '1'] = true; } } solveSudokuUtil(input, horizontal, vertical, box, 0, 0); } private boolean solveSudokuUtil(char[][] input, boolean[][] horizontal, boolean[][] vertical, boolean[][] box, int row, int col) { if (col == 9) { row = row + 1; col = 0; } if (row == 9) { return true; } if (input[row][col] != '.') { return solveSudokuUtil(input, horizontal, vertical, box, row, col + 1); } for (int val = 1; val <= 9; val++) { int index = 3*(row/3) + col/3; if (horizontal[row][val - 1] == false && vertical[col][val - 1] == false && box[index][val - 1] == false) { horizontal[row][val - 1] = true; vertical[col][val - 1] = true; box[index][val - 1] = true; input[row][col] = (char)(val + '0'); if (solveSudokuUtil(input, horizontal, vertical, box, row, col + 1)) { return true; } input[row][col] = '.'; horizontal[row][val - 1] = false; vertical[col][val - 1] = false; box[index][val - 1] = false; } } return false; } public static void main(String args[]) { SudokuSolver ss = new SudokuSolver(); char[][] input = new char[9][9]; for (int i = 0; i < input.length; i++) { for (int j = 0; j < input.length; j++) { input[i][j] = '.'; } } input[0] = "..9748...".toCharArray(); input[1] = "7........".toCharArray(); input[2] = ".2.1.9...".toCharArray(); input[3] = "..7...24.".toCharArray(); input[4] = ".64.1.59.".toCharArray(); input[5] = ".98...3..".toCharArray(); input[6] = "...8.3.2.".toCharArray(); input[7] = "........6".toCharArray(); input[8] = "...2759..".toCharArray(); ss.solveSudoku(input); for (int i = 0; i < input.length; i++) { for (int j = 0; j < input.length; j++) { System.out.print(input[i][j] + " "); } System.out.println(); } } } ================================================ FILE: src/com/interview/recursion/WordCombination.java ================================================ package com.interview.recursion; import java.util.ArrayList; import java.util.List; /** * Date 07/20/2015 * @author Tushar Roy * * Given a list of list of Strings. Print cartesian product of lists. * input -> {"Hello", "World"} , {"Game"}, {"Go","Home"} * output -> * Hello Game Go * Hellow Game Home * World Game Go * World Game Home */ public class WordCombination { public void printCombinations(List> input) { int[] result = new int[input.size()]; print(input,result, 0); } private void print(List> input, int[] result, int pos) { if(pos == result.length){ for (int i = 0; i < input.size(); i++) { System.out.print(input.get(i).get(result[i]) + " "); } System.out.println(); return; } for(int i=0; i < input.get(pos).size(); i++){ result[pos] = i; print(input,result, pos+1); } } public static void main(String args[]){ List l1 = new ArrayList<>(); l1.add("quick"); l1.add("slow"); List l2 = new ArrayList<>(); l2.add("brown"); l2.add("red"); List l3 = new ArrayList<>(); l3.add("fox"); l3.add("dog"); List> input = new ArrayList<>(); input.add(l1); input.add(l2); input.add(l3); WordCombination wc = new WordCombination(); wc.printCombinations(input); } } ================================================ FILE: src/com/interview/recursion/WordPattern.java ================================================ package com.interview.recursion; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * Given a pattern and a string str, find if str follows the same pattern. Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty substring in str. * https://leetcode.com/problems/word-pattern-ii/ */ public class WordPattern { public boolean wordPatternMatch(String pattern, String str) { Map map = new HashMap<>(); Set set = new HashSet<>(); return wordPatternMatch(pattern, str, 0, 0, map, set); } public boolean wordPatternMatch(String pattern, String str, int pos1, int pos2, Map map, Set set) { if (pos1 == pattern.length()) { return pos2 == str.length(); } char ch = pattern.charAt(pos1); String val = map.get(ch); if (val != null) { return pos2 + val.length() <= str.length() && val.equals(str.substring(pos2, pos2 + val.length())) && wordPatternMatch(pattern, str, pos1 + 1, pos2 + val.length(), map, set); } else { for (int i = pos2; i < str.length() - (pattern.length() - pos1 - 1); i++) { String newStr = str.substring(pos2, i + 1); if (set.contains(newStr)) { continue; } set.add(newStr); map.put(ch, newStr); if (wordPatternMatch(pattern, str, pos1 + 1, i + 1, map, set)) { return true; } set.remove(newStr); } map.remove(ch); } return false; } public static void main(String args[]) { String pattern = "abcbc"; String str = "bcdgflgfl"; WordPattern wp = new WordPattern(); System.out.println(wp.wordPatternMatch(pattern, str)); } } ================================================ FILE: src/com/interview/regex/MultiSpaceReplacement.java ================================================ package com.interview.regex; import java.util.regex.Matcher; import java.util.regex.Pattern; public class MultiSpaceReplacement { public void replace(String str){ Pattern pattern = Pattern.compile("^ +| +| +$"); Matcher matcher = pattern.matcher(str); System.out.println(matcher.replaceAll("")); } public static void main(String args[]){ String str = " This is Tushar Roy "; MultiSpaceReplacement mrs = new MultiSpaceReplacement(); mrs.replace(str); } } ================================================ FILE: src/com/interview/sort/CountingSort.java ================================================ package com.interview.sort; public class CountingSort { private static int TOTAL = 10; public void sort(int arr[]) { int count[] = new int[TOTAL]; for (int i = 0; i < arr.length; i++) { count[arr[i]]++; } int c = 0; for (int i = 0; i < TOTAL; i++) { while (count[i] > 0) { arr[c++] = i; count[i]--; } } } public void sort1(int arr[]) { int count[] = new int[TOTAL]; int output[] = new int[arr.length]; for (int i = 0; i < arr.length; i++) { count[arr[i]]++; } for(int i=1; i < TOTAL; i++){ count[i] += count[i-1]; } for(int i=0; i 0 ; i--){ swap(arr, 0, i); heapify(arr, i-1); } } private void heapify(int arr[], int end){ int i = 0; int leftIndex; int rightIndex; while(i <= end){ leftIndex = 2*i + 1; if(leftIndex > end){ break; } rightIndex = 2*i + 2; if(rightIndex > end){ rightIndex = leftIndex; } if(arr[i] >= Math.max(arr[leftIndex], arr[rightIndex])){ break; } if(arr[leftIndex] >= arr[rightIndex]){ swap(arr, i, leftIndex); i = leftIndex; }else{ swap(arr, i, rightIndex); i = rightIndex; } } } private void swap(int arr[], int x, int y){ int temp = arr[x]; arr[x] = arr[y]; arr[y] = temp; } private void heapAdd(int arr[], int end){ int i = end; while(i > 0){ if(arr[i] > arr[(i-1)/2]){ swap(arr, i, (i-1)/2); i = (i - 1)/2; }else{ break; } } } public static void main(String args[]){ HeapSort hs = new HeapSort(); int arr[] = {-1,5,8,2,-6,-8,11,5}; hs.sort(arr); for(int a : arr){ System.out.println(a); } } } ================================================ FILE: src/com/interview/sort/IterativeQuickSort.java ================================================ package com.interview.sort; import java.util.Deque; import java.util.LinkedList; /** * http://www.geeksforgeeks.org/iterative-quick-sort/ * Test case * 0,1 or more elements in the array */ public class IterativeQuickSort { public void sort(int arr[]){ Deque stack = new LinkedList(); int l = 0; int h = arr.length-1; stack.offerFirst(l); stack.offerFirst(h); while(!stack.isEmpty()){ h = stack.pollFirst(); l = stack.pollFirst(); int p = partition(arr,l,h); if(l < p-1 && h > p+1){ stack.offerFirst(l); stack.offerFirst(p-1); stack.offerFirst(p+1); stack.offerFirst(h); } else if(l < p-1){ stack.offerFirst(l); stack.offerFirst(p-1); }else if(h > p+1){ stack.offerFirst(p+1); stack.offerFirst(h); } } } private int partition(int arr[], int low,int high){ int pivot = arr[low]; int i = low+1; int j = low+1; while(j <= high){ if(arr[j] < pivot){ swap(arr,i,j); i++; } j++; } swap(arr,i-1,low); return i-1; } private void swap(int arr[],int a,int b){ int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } public static void main(String args[]){ int arr[] = {3,2,8,0,11,-1,-5,4,32,-60,44}; IterativeQuickSort iqs = new IterativeQuickSort(); iqs.sort(arr); for(int i=0; i < arr.length; i++){ System.out.print(arr[i] + " "); } } } ================================================ FILE: src/com/interview/sort/MergeSort.java ================================================ package com.interview.sort; /** * http://en.wikipedia.org/wiki/Merge_sort * Test cases * 1 element * 2 element * negative numbers * already sorted * reverse sorted */ public class MergeSort { public void sort(int input[]){ sort(input, 0, input.length-1); } private void sort(int input[], int low, int high){ if(low >= high){ return; } int middle = (low + high)/2; sort(input, low, middle); sort(input, middle+1, high); sortedMerge(input,low,high); } private void sortedMerge(int input[], int low, int high){ int middle = (low+high)/2; int temp[] = new int[high-low+1]; int i = low; int j = middle+1; int r = 0; while(i <= middle && j <= high){ if(input[i] <= input[j]){ temp[r++] = input[i++]; }else{ temp[r++] = input[j++]; } } while(i <= middle){ temp[r++] = input[i++]; } while(j <= high){ temp[r++] = input[j++]; } i = low; for(int k=0; k < temp.length;){ input[i++] = temp[k++]; } } public void printArray(int input[]){ for(int i : input){ System.out.print(i + " "); } System.out.println(); } public static void main(String args[]){ int input1[] = {1}; int input2[] = {4,2}; int input3[] = {6,2,9}; int input4[] = {6,-1,10,4,11,14,19,12,18}; MergeSort ms = new MergeSort(); ms.sort(input1); ms.sort(input2); ms.sort(input3); ms.sort(input4); ms.printArray(input1); ms.printArray(input2); ms.printArray(input3); ms.printArray(input4); } } ================================================ FILE: src/com/interview/sort/PanCakeSorting.java ================================================ package com.interview.sort; /** * http://www.geeksforgeeks.org/pancake-sorting/ * Two ways to do it * 1) Start i from arr.length-1 towards 0, find max from 0 to i, move this max to top * by one flip and then move this max to ith position by another flip * * 2) Start i from 0 towards arr.length-1, find floor of input[i] from 0 to i-1 lets call * f , flip 0 to f, then flip 0 to i-1 then flip 0 to i, then flip 0 to i-1. * e.g 1 2 3 5 4. Here i is 4 and f is 2 * 1 2 3 5 4 flip(0,f) -> 3 2 1 5 4 * 3 2 1 5 4 flip(0,i-1) -> 5 1 2 3 4 * 5 1 2 3 4 flip(0,i) -> 4 3 2 1 5 * 4 3 2 1 5 flip(0,i-1) -> 1 2 3 4 5 */ public class PanCakeSorting { public void sort(int arr[]){ for(int i=arr.length-1; i >= 0 ; i--){ int pos = findMax(arr,i); flip(arr,pos); flip(arr,i); } } private int findMax(int arr[],int pos){ int max = pos; for(int i= pos-1 ;i >= 0 ;i--){ if(arr[i] > arr[max]){ max = i; } } return max; } private void flip(int arr[],int pos){ for(int i=0; i <= pos/2; i++){ swap(arr,i,pos-i); } } private void swap(int arr[],int i,int j){ int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } public static void main(String args[]){ int arr[] = {9,2,7,11,3,6,1,10,8}; PanCakeSorting pcs = new PanCakeSorting(); pcs.sort(arr); for(int i=0; i < arr.length; i++){ System.out.print(arr[i] + " "); } } } ================================================ FILE: src/com/interview/sort/QuickSort.java ================================================ package com.interview.sort; public class QuickSort { private void swap(int A[],int i,int j) { int temp = A[i]; A[i] = A[j]; A[j] = temp; } private int split(int A[],int low,int high) { int pivot = low; int i = low +1; int j = high; while(i=A[i]) { i++; } while(j>=i && A[pivot]A[j]) { swap(A,i++,j--); } } if(A[pivot] > A[j]){ swap(A,j,pivot); } return j; } private int split1(int A[],int low,int high){ int pivot = low; int i = low+1; int j = high; while(i <= j){ if(A[i] <= A[pivot]){ i++; continue; } if(A[j] > A[pivot]){ j--; continue; } swap(A,i++,j--); } if(A[pivot] > A[j]){ swap(A,pivot,j); return j; } return pivot; } public void sort(int A[],int low,int high) { if(low>=high) { return; } int pos = split1(A,low,high); sort(A,low,pos-1); sort(A,pos+1,high); } private void printArray(int arr[]){ for(int a : arr){ System.out.println(a); } } public static void main(String args[]){ QuickSort qs = new QuickSort(); int A[] = {11,19,0,-1,5,6,16,-3,6,0,14,18,7,21,18,-6,-8}; // int A[] = {11,9,0,4,6,-1,13}; qs.sort(A, 0, A.length-1); qs.printArray(A); } } ================================================ FILE: src/com/interview/sort/RadixSort.java ================================================ package com.interview.sort; public class RadixSort { private void countSort(int arr[],int exp){ int[] count = new int[10]; int[] output = new int[arr.length]; for(int i=0; i < arr.length; i++){ count[(arr[i]/exp)%10]++; } for(int i=1; i < count.length; i++){ count[i] += count[i-1]; } for(int i=arr.length-1; i >= 0; i--){ output[count[(arr[i]/exp)%10]-1] = arr[i]; count[(arr[i]/exp)%10]--; } for(int i=0; i < arr.length; i++){ arr[i] = output[i]; } } private int max(int arr[]){ int max = arr[0]; for(int i=1; i < arr.length; i++){ if(max < arr[i]){ max = arr[i]; } } return max; } public void radixSort(int arr[]){ int max = max(arr); for(int exp = 1; exp <= max; exp *= 10){ countSort(arr,exp); } } public static void main(String args[]){ int arr[] = {101,10,11,66,94,26,125}; RadixSort rs = new RadixSort(); rs.radixSort(arr); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } } ================================================ FILE: src/com/interview/sort/Sort0toN3.java ================================================ package com.interview.sort; /** * http://www.geeksforgeeks.org/sort-n-numbers-range-0-n2-1-linear-time/ */ public class Sort0toN3 { public void sort(int arr[],int n){ sort(arr,n,1); sort(arr,n,n); sort(arr,n,n*n); } private void sort(int arr[],int n, int exp){ int count[] = new int[n]; for(int i=0; i < arr.length;i++){ count[(arr[i]/exp)%n]++; } for(int i=1; i < arr.length; i++){ count[i] += count[i-1]; } int output[] = new int[n]; for(int i=arr.length-1;i>=0; i--){ output[count[(arr[i]/exp)%n]-1] = arr[i]; count[(arr[i]/exp)%n]--; } for(int i=0; i < arr.length; i++){ arr[i] = output[i]; } } public static void main(String args[]){ int arr[] = {100,2,124,18,36}; Sort0toN3 sn = new Sort0toN3(); sn.sort(arr,arr.length); for(int i=0; i < arr.length; i++){ System.out.print(arr[i] + " "); } } } ================================================ FILE: src/com/interview/sort/SortArrayByFrequence.java ================================================ package com.interview.sort; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.Map; /** * http://www.geeksforgeeks.org/sort-elements-by-frequency/ */ public class SortArrayByFrequence { class SortNode{ int count; int firstIndex; } class FrequenceComparator implements Comparator{ private Map countMap = null; FrequenceComparator(Map countMap){ this.countMap = countMap; } @Override public int compare(Integer i1, Integer i2) { SortNode n1 = countMap.get(i1); SortNode n2 = countMap.get(i2); if(n1.count > n2.count){ return -1; }else if(n1.count < n2.count){ return 1; }else{ return n1.firstIndex < n2.firstIndex ? -1 : 1; } } } public void sortByFrequence(Integer arr[]){ Map countMap = new HashMap(); int index = 0; for(int a : arr){ if(countMap.containsKey(a)){ SortNode s = countMap.get(a); s.count++; }else{ SortNode s = new SortNode(); s.count = 1; s.firstIndex = index; countMap.put(a, s); } index++; } FrequenceComparator freqComparator = new FrequenceComparator(countMap); Arrays.sort(arr,freqComparator); } public static void main(String args[]){ Integer input[] = {5,2,8,9,9,9,2}; SortArrayByFrequence saf = new SortArrayByFrequence(); saf.sortByFrequence(input); for(int i : input){ System.out.println(i + " "); } } } ================================================ FILE: src/com/interview/stackqueue/CircularQueue.java ================================================ package com.interview.stackqueue; public class CircularQueue { private int QUEUE_LENGTH; private T data[] = null; public CircularQueue(int size){ this.QUEUE_LENGTH = size; data = (T [])new Object[QUEUE_LENGTH]; } private int top=-1; private int end = -1; public void offer(T t){ if(top == -1){ data[0] = t; top =0; end = 0; }else if(top == (end + 1) % QUEUE_LENGTH){ throw new IllegalArgumentException(); }else{ end = (end + 1) % QUEUE_LENGTH; data[end] = t; } } public T top(){ if(top == -1){ throw new IllegalArgumentException(); }else{ return data[top]; } } public T poll(){ if(top == -1){ throw new IllegalArgumentException(); }else if(top == end){ T t = data[top]; top = -1; end = -1; return t; } else{ T t = data[top]; top = (top +1)% QUEUE_LENGTH; return t; } } public boolean isEmpty(){ if(top == -1){ return true; } return false; } public boolean isFull(){ if(top == (end + 1)% QUEUE_LENGTH){ return true; } return false; } public static void main(String args[]){ CircularQueue circularQueue = new CircularQueue(5); circularQueue.offer(1); circularQueue.offer(2); circularQueue.offer(3); System.out.println(circularQueue.poll()); circularQueue.offer(4); circularQueue.offer(5); System.out.print(circularQueue.isFull()); circularQueue.offer(6); System.out.print(circularQueue.isFull()); while(!circularQueue.isEmpty()){ System.out.println(circularQueue.poll()); } } } ================================================ FILE: src/com/interview/stackqueue/MaximumHistogram.java ================================================ package com.interview.stackqueue; import java.util.Deque; import java.util.LinkedList; /** * 12/23/2014 * @author tusroy * * Video link https://youtu.be/ZmnqCZp9bBs * * Given an array representing height of bar in bar graph, find max histogram * area in the bar graph. Max histogram will be max rectangular area in the * graph. * * Maintain a stack * * If stack is empty or value at index of stack is less than or equal to value at current * index, push this into stack. * Otherwise keep removing values from stack till value at index at top of stack is * less than value at current index. * While removing value from stack calculate area * if stack is empty * it means that till this point value just removed has to be smallest element * so area = input[top] * i * if stack is not empty then this value at index top is less than or equal to * everything from stack top + 1 till i. So area will * area = input[top] * (i - stack.peek() - 1); * Finally maxArea is area if area is greater than maxArea. * * * Time complexity is O(n) * Space complexity is O(n) * * References: * http://www.geeksforgeeks.org/largest-rectangle-under-histogram/ */ public class MaximumHistogram { public int maxHistogram(int input[]){ Deque stack = new LinkedList(); int maxArea = 0; int area = 0; int i; for(i=0; i < input.length;){ if(stack.isEmpty() || input[stack.peekFirst()] <= input[i]){ stack.offerFirst(i++); }else{ int top = stack.pollFirst(); //if stack is empty means everything till i has to be //greater or equal to input[top] so get area by //input[top] * i; if(stack.isEmpty()){ area = input[top] * i; } //if stack is not empty then everythin from i-1 to input.peek() + 1 //has to be greater or equal to input[top] //so area = input[top]*(i - stack.peek() - 1); else{ area = input[top] * (i - stack.peekFirst() - 1); } if(area > maxArea){ maxArea = area; } } } while(!stack.isEmpty()){ int top = stack.pollFirst(); //if stack is empty means everything till i has to be //greater or equal to input[top] so get area by //input[top] * i; if(stack.isEmpty()){ area = input[top] * i; } //if stack is not empty then everything from i-1 to input.peek() + 1 //has to be greater or equal to input[top] //so area = input[top]*(i - stack.peek() - 1); else{ area = input[top] * (i - stack.peekFirst() - 1); } if(area > maxArea){ maxArea = area; } } return maxArea; } public static void main(String args[]){ MaximumHistogram mh = new MaximumHistogram(); int input[] = {2,2,2,6,1,5,4,2,2,2,2}; int maxArea = mh.maxHistogram(input); //System.out.println(maxArea); assert maxArea == 12; } } ================================================ FILE: src/com/interview/stackqueue/MedianFinder.java ================================================ package com.interview.stackqueue; import java.util.Collections; import java.util.PriorityQueue; /** * Date 03/03/2016 * @author Tushar Roy * * Find median in stream of numbers * * https://leetcode.com/problems/find-median-from-data-stream/ */ public class MedianFinder { PriorityQueue minPq = new PriorityQueue<>(); PriorityQueue maxPq = new PriorityQueue<>(); public MedianFinder() { minPq = new PriorityQueue<>(); maxPq = new PriorityQueue<>(20, Collections.reverseOrder()); } // Adds a number into the data structure. public void addNum(int num) { if (maxPq.size() == 0) { maxPq.add(num); return; } if (maxPq.size() == minPq.size()) { if (minPq.peek() < num) { maxPq.offer(minPq.poll()); minPq.offer(num); } else { maxPq.offer(num); } } else { int toBeOffered = 0; if (num >= maxPq.peek()) { toBeOffered = num; } else { toBeOffered = maxPq.poll(); maxPq.offer(num); } minPq.offer(toBeOffered); } } // Returns the median of current data stream public double findMedian() { if (minPq.size() == maxPq.size()) { return ((double)minPq.peek() + (double)maxPq.peek())/2; } else { return maxPq.peek(); } } public static void main(String args[]) { MedianFinder mf = new MedianFinder(); mf.addNum(4); System.out.println(mf.findMedian()); mf.addNum(8); System.out.println(mf.findMedian()); mf.addNum(2); System.out.println(mf.findMedian()); mf.addNum(11); System.out.println(mf.findMedian()); mf.addNum(13); System.out.println(mf.findMedian()); mf.addNum(14); System.out.println(mf.findMedian()); mf.addNum(-1); System.out.println(mf.findMedian()); } } ================================================ FILE: src/com/interview/stackqueue/RealTimeCounter.java ================================================ package com.interview.stackqueue; import java.util.LinkedList; import java.util.Queue; public class RealTimeCounter { private Queue secQueue = new LinkedList(); private long secCount; public void add(long currentTimeInMills){ while(secQueue.size() > 0 && currentTimeInMills - 1000 > secQueue.peek()){ secCount--; secQueue.poll(); } secCount++; secQueue.offer(currentTimeInMills); } public long getCallsInLastSec(long currentTimeInMills){ while(secQueue.size() > 0 && currentTimeInMills - 1000 > secQueue.peek()){ secCount--; secQueue.poll(); } return secCount; } public static void main(String args[]){ RealTimeCounter rtc = new RealTimeCounter(); rtc.add(100); rtc.add(300); rtc.add(550); System.out.println(rtc.getCallsInLastSec(780)); System.out.println(rtc.getCallsInLastSec(1280)); rtc.add(1540); System.out.println(rtc.getCallsInLastSec(1551)); rtc.add(1570); System.out.println(rtc.getCallsInLastSec(2651)); } } ================================================ FILE: src/com/interview/stackqueue/RealTimeCounterUsingCircularQueue.java ================================================ package com.interview.stackqueue; import java.util.Deque; import java.util.LinkedList; public class RealTimeCounterUsingCircularQueue { class Node { long time; int count; } private static int MAX_SIZE = 0; private static int BOUND = 100; private static int MAX_BOUND = 1000; int count = 0; private int currentSize = 0; Deque queue = new LinkedList(); public void add(long time) { Node last = queue.peekLast(); if(last != null){ if (time - last.time < BOUND) { last.count++; count++; return; } else if (time - last.time > MAX_BOUND) { queue.clear(); Node n = new Node(); n.time = time/BOUND * BOUND; n.count = 1; queue.add(n); count++; return; } } while(queue.size() > 0){ Node t1 = queue.peekFirst(); if(time - t1.time > MAX_BOUND){ count = count - t1.count; queue.pollFirst(); }else{ break; } } Node n = new Node(); n.time = time/BOUND * BOUND; n.count = 1; queue.add(n); count++; } public int getCount(int time){ while(queue.size() > 0){ Node t1 = queue.peekFirst(); if(time - t1.time > MAX_BOUND){ count = count - t1.count; queue.pollFirst(); }else{ break; } } return count; } public static void main(String args[]){ RealTimeCounterUsingCircularQueue src = new RealTimeCounterUsingCircularQueue(); src.add(10); src.add(70); src.add(80); src.add(120); src.add(150); src.add(450); src.add(750); src.add(799); src.add(1001); src.add(1010); src.add(1210); System.out.print(src.getCount(1515)); } } ================================================ FILE: src/com/interview/stackqueue/RemoveDuplicateMaintainingOrder.java ================================================ package com.interview.stackqueue; import java.util.*; /** * Date 02/29/2016 * @author Tushar Roy * * Given a string remove duplicates from the string maintaining order * and getting lexicographically smallest string. * * Reference: * https://leetcode.com/problems/remove-duplicate-letters/ */ public class RemoveDuplicateMaintainingOrder { public String removeDuplicateLetters(String s) { Deque stack = new LinkedList<>(); Map count = new HashMap<>(); for (int i = 0; i < s.length(); i++) { count.compute(s.charAt(i), (key, val) -> { if (val == null) { return 1; } else { return val + 1; } }); } Set visited = new HashSet<>(); for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); count.put(ch, count.get(ch) - 1); if (visited.contains(ch)) { continue; } while (!stack.isEmpty() && stack.peekFirst() > ch && count.get(stack.peekFirst()) > 0) { visited.remove(stack.peekFirst()); stack.pollFirst(); } stack.offerFirst(ch); visited.add(ch); } StringBuffer buff = new StringBuffer(); while (!stack.isEmpty()) { buff.append(stack.pollLast()); } return buff.toString(); } public static void main(String args[]) { RemoveDuplicateMaintainingOrder rm = new RemoveDuplicateMaintainingOrder(); System.out.println(rm.removeDuplicateLetters("cbacdcbc")); } } ================================================ FILE: src/com/interview/stackqueue/RemoveExtraBrackets.java ================================================ package com.interview.stackqueue; import java.util.Deque; import java.util.LinkedList; /** * Date 03/17/2015 * @author tusroy * * Given a string with unbalanced brackets how do you remove minimum number * of extra brackets so that you are left with balanced brackets in the string * * e.g )( -> empty string * (a) -> (a) * ((mnq)abc))) -> ((mna)abc) * (abc)(( -> (abc) * * Solution 1 * Keep a stack. When non bracket character shows up just skip it. * When an opening bracket shows up just add it. * When closing bracket shows up, see if top of stack is opening bracket. If yes * then just remove that from stack else add closing bracket into the stack. * * Solution 2 * This can be done without stack as well. Keep count of open and close brackets. * Any time closeBracket gets more than openBracket do not put it in result. * After we are done iterating input again if openBracket is more than closeBracket * get rid of last (openBracket-closeBracket) open brackets. * * Test cases: * empty string * String with )( * String with all opening brackets * String with all closing brackets * String with mix of open close brackets and characters between them * String with already balanced parenthesis * */ public class RemoveExtraBrackets { public int remove(char input[]){ if(input == null){ return 0; } Deque dq = new LinkedList(); for(int i=0; i < input.length; i++){ //skip non bracket characters if(input[i] != '(' && input[i] != ')'){ continue; } //add opening brackets if(input[i] == '('){ dq.addFirst(i); } else if(input[i] == ')'){ //if top is opening bracket just remove from stack else add closing bracket if(!dq.isEmpty() && input[dq.peekFirst()] == '('){ dq.pollFirst(); }else{ dq.addFirst(i); } } } int index = 0; //iterate through list again and don't add leftover //characters from stack in final result for(int i=0; i < input.length; i++){ if(!dq.isEmpty() && i == dq.peekLast()) { dq.pollLast(); }else { input[index++] = input[i]; } } return index; } /** * This method does not uses stack and does inplace conversion */ public int removeWithoutExtraSpace(char input[]){ int openBrackets = 0; int closeBrackets = 0; int index = 0; for(int i=0; i < input.length; i++){ if(input[i] != '(' && input[i] != ')'){ input[index++] = input[i]; continue; } if(input[i] == '('){ openBrackets++; input[index++] = input[i]; }else { //add close bracket to input only if it is //less than open bracket count. if(closeBrackets < openBrackets){ input[index++] = input[i]; closeBrackets++; } } } //iterate through result get rid of extra open brackets if any towards //the end if(openBrackets > closeBrackets){ int newIndex = 0; int seenOpenBracket = 0; for(int i=0; i < index; i++){ if(input[i] == '('){ seenOpenBracket++; } if(input[i] != '(' || seenOpenBracket <= closeBrackets){ input[newIndex++] = input[i]; } } index = newIndex; } return index; } public static void printArray(char input[], int size) { for(int i=0; i < size; i++){ System.out.print(input[i] + " "); } System.out.println(); } public static void main(String args[]){ RemoveExtraBrackets reb = new RemoveExtraBrackets(); char input1[] = ")(".toCharArray(); int pos = reb.remove(input1); printArray(input1, pos); char input1_1[] = ")(".toCharArray(); pos = reb.removeWithoutExtraSpace(input1_1); printArray(input1_1, pos); char input2[] = "(((abc)(lm)(()".toCharArray(); pos = reb.remove(input2); printArray(input2, pos); char input2_1[] = "(((abc)(lm)(()".toCharArray(); pos = reb.removeWithoutExtraSpace(input2_1); printArray(input2_1, pos); char input3[] = "(((c)(l))))(()))".toCharArray(); pos = reb.remove(input3); printArray(input3, pos); char input3_1[] = "(((c)(l))))(()))".toCharArray(); pos = reb.removeWithoutExtraSpace(input3_1); printArray(input3_1, pos); char input4[] = "((((".toCharArray(); pos = reb.remove(input4); printArray(input4, pos); char input4_1[] = "((((".toCharArray(); pos = reb.removeWithoutExtraSpace(input4_1); printArray(input4_1, pos); char input5[] = "))))".toCharArray(); pos = reb.remove(input5); printArray(input5, pos); char input5_1[] = "))))".toCharArray(); pos = reb.removeWithoutExtraSpace(input5_1); printArray(input5_1, pos); char input6[] = "((Test))(Great)".toCharArray(); pos = reb.remove(input6); printArray(input6, pos); char input6_1[] = "((Test))(Great)".toCharArray(); pos = reb.removeWithoutExtraSpace(input6_1); printArray(input6_1, pos); } } ================================================ FILE: src/com/interview/stackqueue/ReverseStackUsingRecursion.java ================================================ package com.interview.stackqueue; import java.util.Deque; import java.util.Iterator; import java.util.LinkedList; /** * http://www.geeksforgeeks.org/reverse-a-stack-using-recursion/ */ public class ReverseStackUsingRecursion { public void reverse(Deque stack){ if(stack.size() == 0){ return; } int temp = stack.pollFirst(); reverse(stack); pushAtBottom(stack,temp); } private void pushAtBottom(Deque stack,int data){ if(stack.size() == 0){ stack.offerFirst(data); return; } int temp = stack.pollFirst(); pushAtBottom(stack, data); stack.offerFirst(temp); } public static void main(String args[]){ Deque stack = new LinkedList(); stack.push(1); stack.push(2); stack.push(3); stack.push(4); stack.push(5); stack.push(6); Iterator itr = stack.iterator(); while(itr.hasNext()){ System.out.println(itr.next()); } ReverseStackUsingRecursion rsu = new ReverseStackUsingRecursion(); rsu.reverse(stack); itr = stack.iterator(); while(itr.hasNext()){ System.out.println(itr.next()); } } } ================================================ FILE: src/com/interview/stackqueue/SimplyPath.java ================================================ package com.interview.stackqueue; import java.util.Deque; import java.util.LinkedList; import java.util.StringTokenizer; /** * Date 04/18/2016 * @author Tushar Roy * * Given an absolute path for a file (Unix-style), simplify it. * For example, * path = "/home/", => "/home" * path = "/a/./b/../../c/", => "/c" * * Space complexity O(n) * Time complexity O(n) * * https://leetcode.com/problems/simplify-path/ */ public class SimplyPath { public String simplifyPath(String path) { Deque stack = new LinkedList<>(); StringTokenizer token = new StringTokenizer(path, "/"); while (token.hasMoreTokens()) { String tok = token.nextToken(); if (tok.equals(".")) { continue; } else if (tok.equals("..")) { stack.pollFirst(); } else { stack.offerFirst(tok); } } StringBuffer buff = new StringBuffer(); if (stack.isEmpty()) { buff.append("/"); } while(!stack.isEmpty()) { buff.append("/").append(stack.pollLast()); } return buff.toString(); } public static void main(String args[]){ String absCurrentFolder = "/home/tusroy"; SimplyPath mfc = new SimplyPath(); System.out.println(mfc.simplifyPath(absCurrentFolder)); } } ================================================ FILE: src/com/interview/stackqueue/StockSpanProblem.java ================================================ package com.interview.stackqueue; import java.util.ArrayDeque; import java.util.Arrays; import java.util.Deque; /** * Created by saitejatokala on 21/11/15. * http://www.geeksforgeeks.org/the-stock-span-problem/ * Question: * The stock span problem is a financial problem where we have a series of n daily price quotes for a stock and we need to calculate span of stock’s price for all n days. * The span Si of the stock’s price on a given day i is defined as the maximum number of consecutive days just before the given day, for which the price of the stock on the current day is less than or equal to its price on the given day. * For example, if an array of 7 days prices is given as {100, 80, 60, 70, 60, 75, 85}, then the span values for corresponding 7 days are {1, 1, 1, 2, 1, 4, 6} * * Solution 1: * We see that S[i] on day i can be easily computed if we know the closest day preceding i, such that the price is greater than on that day than the price on day i. If such a day exists, let’s call it h(i), otherwise, we define h(i) = -1. * The span is now computed as S[i] = i – h(i). See the following diagram. */ public class StockSpanProblem { public static int[] stockSpan(int[] prices){ Deque stack = new ArrayDeque<>(); int[] stockSpan = new int[prices.length]; stockSpan[0] = 1; stack.offerFirst(0); for (int i = 1; i < prices.length ; i++) { while (!stack.isEmpty() && prices[stack.peekFirst()] < prices[i]) { stack.pollFirst(); } if (stack.isEmpty()) { stockSpan[i] = i + 1; } else { stockSpan[i] = i - stack.peekFirst(); } stack.offerFirst(i); } return stockSpan; } public static void main(String[] args) { int[] prices = {100, 80, 60, 70, 60, 75, 85}; int[] result = stockSpan(prices); System.out.print(Arrays.toString(result)); } } ================================================ FILE: src/com/interview/string/AnagramOfFirstAsSubstring.java ================================================ package com.interview.string; import java.util.HashMap; import java.util.Map; /** * http://www.careercup.com/question?id=5389078581215232 * Given two strings tells if anagram of first is substring of another * Keep map of characters in array1 and keep checking if array2 has these characters. * main string : a b a c a b b and looking for a a b b c when 3rd a is encountered * we move index to second a and start from there. * * Another idea is to keep a sorted linklist of string in comparison. Whenever a new character * is to be added remove last character from linklist and add this new one. */ public class AnagramOfFirstAsSubstring { public boolean isSubString(char str1[], char str2[]) { int index = 0; int curLen = 0; Map count = new HashMap(); for (int i = 0; i < str1.length; i++) { incrementCount(str1[i], count); } Map currentCount = new HashMap(); Map pos = new HashMap(); while (index < str2.length) { if (containsAndUpdate(currentCount, count, str2[index], pos, index)) { index++; curLen++; } else { Integer p = pos.get(str2[index]); if (p != null) { curLen = index - p; index = p; } else { index++; } currentCount.clear(); pos.clear(); } if (curLen == str1.length) { return true; } } return false; } private boolean containsAndUpdate(Map currentCount, Map count, Character ch, Map pos, int index) { if (count.containsKey(ch)) { if(currentCount.containsKey(ch)) { if (currentCount.get(ch) < count.get(ch)) { if (currentCount.get(ch) == 1) { pos.put(ch, index); } currentCount.put(ch, currentCount.get(ch) + 1); return true; } }else{ currentCount.put(ch, 1); pos.put(ch,index); return true; } } return false; } private void incrementCount(Character ch, Map count) { if (count.containsKey(ch)) { int c = count.get(ch); count.put(ch, c + 1); } else { count.put(ch, 1); } } public static void main(String args[]){ char str1[] = "aaabccde".toCharArray(); char str2[] = "tbcdaacaaecbd".toCharArray(); AnagramOfFirstAsSubstring ana = new AnagramOfFirstAsSubstring(); System.out.println(ana.isSubString(str1, str2)); } } ================================================ FILE: src/com/interview/string/CycleLeaderIteration.java ================================================ package com.interview.string; public class CycleLeaderIteration { //assumption that size is going to be 3^k +1 from start to end public void iterate(char str[],int start,int end){ int len = end - start +1; int power = 1; while(power < len){ int index = power; int newIndex = -1; char temp = str[start+index]; char temp1; while(newIndex != power){ if(index % 2 ==0){ newIndex = index/2; }else{ newIndex = len/2 + index/2; } temp1 = str[start + newIndex]; str[start+newIndex] = temp; temp = temp1; index = newIndex; } power = power*3; } } public static void main(String args[]){ String str = "1a2b3c4d5e6f7g8h9iAjBkClDmEn"; char[] str1 = str.toCharArray(); CycleLeaderIteration cli = new CycleLeaderIteration(); cli.iterate(str1, 0, str1.length); for(char ch: str1){ System.out.print(ch + " "); } } } ================================================ FILE: src/com/interview/string/GroupAnagramsTogether.java ================================================ package com.interview.string; import java.util.*; /** * https://leetcode.com/problems/anagrams/ */ public class GroupAnagramsTogether { public List> groupAnagrams(String[] strs) { if (strs == null || strs.length == 0) return new ArrayList>(); int listIndex = 0; List> result = new ArrayList<>(); Map anagramGroup = new HashMap<>(); for (String str : strs) { char[] chars = str.toCharArray(); Arrays.sort(chars); String sorted = new String(chars); if (anagramGroup.containsKey(sorted)) { int index = anagramGroup.get(sorted); List listResult = result.get(index); listResult.add(str); } else { List resultList = new ArrayList<>(); resultList.add(str); result.add(listIndex, resultList); anagramGroup.put(sorted, listIndex); listIndex++; } } return result; } } ================================================ FILE: src/com/interview/string/InPlaceTransformationOfString.java ================================================ package com.interview.string; /** * http://www.geeksforgeeks.org/an-in-place-algorithm-for-string-transformation/ */ public class InPlaceTransformationOfString { private void reverse(char []str, int low, int high){ while(low 0){ int end = get3PowerK1(size); size = size-end; CycleLeaderIteration cli = new CycleLeaderIteration(); cli.iterate(str, low, end + low-1); low = low+end; } size = str.length; low =0; int end = get3PowerK1(size); while(end < str.length){ int nextEnd = get3PowerK1(str.length-end); reverse(str,end/2,end-1); reverse(str,end/2,end+nextEnd/2-1); reverse(str,end/2,end/2+nextEnd/2-1); // size = str.length - (end + nextEnd); end = end + nextEnd; } } private int get3PowerK1(int size){ int power = 1; while((power*3 +1)<= size){ power = power*3; } return power+1; } public static void main(String args[]){ char str[] = {'a','1','b','2','c','3','d','4','e','5','f','6','g','7','h','8','i','9','j','A','k','B','l','C','m','D'}; InPlaceTransformationOfString ip = new InPlaceTransformationOfString(); ip.inPlaceTransformationImproved(str); for(int i=0; i < str.length; i++){ System.out.print(str[i]); } } } ================================================ FILE: src/com/interview/string/LexicographicRankInPermutation.java ================================================ package com.interview.string; public class LexicographicRankInPermutation { //you can create a AVL tree to efficiently find total //number of smaller characters. //You can keep size of subtree at root and keep moving left or right //depending on the character you looking for private int findNumberOfSmallerCharactersOnRight(int index,char []str){ int count=0; for(int i=index+1; i < str.length; i++){ if(str[i] < str[index]){ count++; } } return count; } private int factorial(int n){ int fact = 1; for(int i =1; i <=n; i++){ fact = i*fact; } return fact; } public int rank(char []str){ int rank =0; for(int i=0; i < str.length;i++){ int num = findNumberOfSmallerCharactersOnRight(i, str); rank += factorial(str.length -i-1)*num; } return rank+1; } public static void main(String args[]){ LexicographicRankInPermutation lrp = new LexicographicRankInPermutation(); int rank = lrp.rank("STRING".toCharArray()); System.out.println(rank); } } ================================================ FILE: src/com/interview/string/LongestPalindromeSubstring.java ================================================ package com.interview.string; /** * Date 07/29/2015 * @author Tushar Roy * * Given a string find longest palindromic substring in this string. * * References * http://www.geeksforgeeks.org/longest-palindrome-substring-set-1/ * http://www.geeksforgeeks.org/longest-palindromic-substring-set-2/ * http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html * http://www.akalin.cx/longest-palindrome-linear-time * http://tarokuriyama.com/projects/palindrome2.php */ public class LongestPalindromeSubstring { public int longestPalindromeSubstringEasy(char arr[]) { int longest_substring = 1; for (int i = 0; i < arr.length; i++) { int x, y; int palindrome; x = i; y = i + 1; palindrome = 0; while (x >= 0 && y < arr.length && arr[x] == arr[y]) { x--; y++; palindrome += 2; } longest_substring = Math.max(longest_substring, palindrome); x = i - 1; y = i + 1; palindrome = 1; while (x >= 0 && y < arr.length && arr[x] == arr[y]) { x--; y++; palindrome += 2; } longest_substring = Math.max(longest_substring, palindrome); } return longest_substring; } /** * Linear time Manacher's algorithm to find longest palindromic substring. * There are 4 cases to handle * Case 1 : Right side palindrome is totally contained under current palindrome. In this case do not consider this as center. * Case 2 : Current palindrome is proper suffix of input. Terminate the loop in this case. No better palindrom will be found on right. * Case 3 : Right side palindrome is proper suffix and its corresponding left side palindrome is proper prefix of current palindrome. Make largest such point as * next center. * Case 4 : Right side palindrome is proper suffix but its left corresponding palindrome is be beyond current palindrome. Do not consider this * as center because it will not extend at all. * * To handle even size palindromes replace input string with one containing $ between every input character and in start and end. */ public int longestPalindromicSubstringLinear(char input[]) { int index = 0; //preprocess the input to convert it into type abc -> $a$b$c$ to handle even length case. //Total size will be 2*n + 1 of this new array. char newInput[] = new char[2*input.length + 1]; for(int i=0; i < newInput.length; i++) { if(i % 2 != 0) { newInput[i] = input[index++]; } else { newInput[i] = '$'; } } //create temporary array for holding largest palindrome at every point. There are 2*n + 1 such points. int T[] = new int[newInput.length]; int start = 0; int end = 0; //here i is the center. for(int i=0; i < newInput.length; ) { //expand around i. See how far we can go. while(start >0 && end < newInput.length-1 && newInput[start-1] == newInput[end+1]) { start--; end++; } //set the longest value of palindrome around center i at T[i] T[i] = end - start + 1; //this is case 2. Current palindrome is proper suffix of input. No need to proceed. Just break out of loop. if(end == T.length -1) { break; } //Mark newCenter to be either end or end + 1 depending on if we dealing with even or old number input. int newCenter = end + (i%2 ==0 ? 1 : 0); for(int j = i + 1; j <= end; j++) { //i - (j - i) is left mirror. Its possible left mirror might go beyond current center palindrome. So take minimum //of either left side palindrome or distance of j to end. T[j] = Math.min(T[i - (j - i)], 2 * (end - j) + 1); //Only proceed if we get case 3. This check is to make sure we do not pick j as new center for case 1 or case 4 //As soon as we find a center lets break out of this inner while loop. if(j + T[i - (j - i)]/2 == end) { newCenter = j; break; } } //make i as newCenter. Set right and left to atleast the value we already know should be matching based of left side palindrome. i = newCenter; end = i + T[i]/2; start = i - T[i]/2; } //find the max palindrome in T and return it. int max = Integer.MIN_VALUE; for(int i = 0; i < T.length; i++) { int val; /* if(i%2 == 0) { val = (T[i] -1)/2; } else { val = T[i]/2; }*/ val = T[i]/2; if(max < val) { max = val; } } return max; } public int longestPalindromeDynamic(char []str){ boolean T[][] = new boolean[str.length][str.length]; for(int i=0; i < T.length; i++){ T[i][i] = true; } int max = 1; for(int l = 2; l <= str.length; l++){ int len = 0; for(int i=0; i < str.length-l+1; i++){ int j = i + l-1; len = 0; if(l == 2){ if(str[i] == str[j]){ T[i][j] = true; len = 2; } }else{ if(str[i] == str[j] && T[i+1][j-1]){ T[i][j] = true; len = j -i + 1; } } if(len > max){ max = len; } } } return max; } public static void main(String args[]) { LongestPalindromeSubstring lps = new LongestPalindromeSubstring(); System.out.println(lps.longestPalindromicSubstringLinear("abba".toCharArray())); System.out.println(lps.longestPalindromicSubstringLinear("abbababba".toCharArray())); System.out.println(lps.longestPalindromicSubstringLinear("babcbaabcbaccba".toCharArray())); System.out.println(lps.longestPalindromicSubstringLinear("cdbabcbabdab".toCharArray())); } } ================================================ FILE: src/com/interview/string/LongestSubstringWithKDistinctCharacters.java ================================================ package com.interview.string; import java.util.HashMap; import java.util.Map; /** * Date 04/03/2016 * @author Tushar Roy * * Given a string, find the length of the longest substring T that contains at most k distinct characters. * For example, Given s = “eceba” and k = 2, * T is "ece" which its length is 3. * * Time complexity O(n) * Space complexity O(n) * * https://leetcode.com/problems/longest-substring-with-at-most-k-distinct-characters/ */ public class LongestSubstringWithKDistinctCharacters { public int lengthOfLongestSubstringKDistinct(String s, int k) { if (k == 0 || s.length() == 0) { return 0; } int[] ascii = new int[256]; int count = 0; int start = 0; int max = 0; for (int i = 0; i < s.length(); i++) { int ch = s.charAt(i); if (count < k) { if (ascii[ch] == 0) { count++; } } else if (ascii[ch] == 0){ while (start < i) { char ch1 = s.charAt(start++); ascii[ch1]--; if (ascii[ch1] == 0) { break; } } } ascii[ch]++; max = Math.max(max, i - start + 1); } return max; } public int lengthOfLongestSubstringKDistinctUsingMap(String s, int k) { if (k == 0 || s.length() == 0) { return 0; } Map countMap = new HashMap<>(); int max = 0; int start = 0; for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if (!countMap.containsKey(ch) && countMap.size() >= k) { while (start < i) { countMap.compute(s.charAt(start), (key, val) -> { if (val == 1) { return null; } else { return val - 1; } }); start++; if (countMap.size() < k) { break; } } } countMap.compute(ch, (key, val) -> { if (val == null) { return 1; } else { return val + 1; } }); max = Math.max(max, i - start + 1); } return max; } } ================================================ FILE: src/com/interview/string/LongestSubstringWithoutRepetingCharacter.java ================================================ package com.interview.string; import java.util.HashSet; import java.util.Set; /** * References * http://www.geeksforgeeks.org/length-of-the-longest-substring-without-repeating-characters/ * https://leetcode.com/problems/longest-substring-without-repeating-characters/ */ public class LongestSubstringWithoutRepetingCharacter { public int lengthOfLongestSubstring(String s) { Set uniqueSet = new HashSet<>(); int maxSize = 0; int start = 0; for(int i = 0; i < s.length(); i++) { if(!uniqueSet.contains(s.charAt(i))) { uniqueSet.add(s.charAt(i)); if(uniqueSet.size() > maxSize) { maxSize = uniqueSet.size(); } } else { while (s.charAt(start) != s.charAt(i)) { uniqueSet.remove(s.charAt(start)); start++; } start++; } } return maxSize; } public static void main(String args[]){ LongestSubstringWithoutRepetingCharacter lsw = new LongestSubstringWithoutRepetingCharacter(); System.out.println(lsw.lengthOfLongestSubstring("ABCDECAMNCZB")); } } ================================================ FILE: src/com/interview/string/MultiplyStrings.java ================================================ package com.interview.string; /** * https://leetcode.com/discuss/questions/oj/multiply-strings */ public class MultiplyStrings { public String multiply(String num1, String num2) { String output = multiply(num1, num2, 0, num1.length() - 1, 0, num2.length() - 1); return output; } private String multiply(String num1, String num2, int start1, int end1, int start2, int end2) { if (end1 - start1 == 0 || end2 - start2 == 0) { return simpleMultiply(num1.substring(start1, end1 + 1), num2.substring(start2, end2 + 1)); } int mid1 = (start1 + end1)/2; int mid2 = (start2 + end2)/2; int count1 = end1 - mid1; int count2 = end2 - mid2; String v1 = multiply(num1, num2, start1, mid1, start2, mid2); String v2 = multiply(num1, num2, start1, mid1, mid2 + 1, end2); String v3 = multiply(num1, num2, mid1 + 1, end1, start2, mid2); String v4 = multiply(num1, num2, mid1 + 1, end1, mid2 + 1, end2); v1 = append0s(v1, count1 + count2); v2 = append0s(v2, count1); v3 = append0s(v3, count2); v1 = add(v1.toCharArray(), v2.toCharArray()); v3 = add(v3.toCharArray(), v4.toCharArray()); return add(v1.toCharArray(), v3.toCharArray()); } private String simpleMultiply(String num1, String num2) { String smaller; String larger; if (num1.length() == 1) { smaller = num1; larger = num2; } else { smaller = num2; larger = num1; } int r2 = smaller.charAt(0) - '0'; if (r2 == 0) { return "0"; } int carry = 0; StringBuffer stringBuffer = new StringBuffer(); for (int i = larger.length() - 1; i >= 0; i--) { int r1 = larger.charAt(i) - '0'; int r = r1 * r2 + carry; stringBuffer.append(r%10); carry = r / 10; } if (carry != 0) { stringBuffer.append(carry); } return stringBuffer.reverse().toString(); } private String append0s(String v1, int count ) { StringBuffer buff = new StringBuffer(v1); for (int i = 0; i < count; i++) { buff.append("0"); } return buff.toString(); } public String add(char[] num1,char[] num2){ int index1 = num1.length -1; int index2 = num2.length -1; int carry = 0; StringBuffer buffer = new StringBuffer(); while(index1 >= 0 && index2 >= 0){ int r1 = num1[index1] - '0'; int r2 = num2[index2] - '0'; int r = r1 + r2 + carry; buffer.append(r%10); carry = r/10; index1--; index2--; } while(index1 >= 0){ int r1 = num1[index1] - '0'; int r = r1 + carry; buffer.append(r%10); carry = r/10; index1--; } while(index2 >= 0){ int r2 = num2[index2] - '0'; int r = r2 + carry; buffer.append(r%10); carry = r/10; index2--; } if (carry != 0) { buffer.append(carry); } return buffer.reverse().toString(); } public static void main(String args[]) { MultiplyStrings ms = new MultiplyStrings(); System.out.print(ms.multiply("6752716719037375654442652725945722915786612669126862029212","2840271321219335147")); } } ================================================ FILE: src/com/interview/string/NTMatch.java ================================================ package com.interview.string; /** .Given an input string S write a function which returns true if it satisfies S = nT. Basically you have to find if a given string can be represented from a substring by iterating it �n� times. n >= 2 An example would suffice Function should return true if 1) S = abab 2) S = abcdabcd 3) S = abcabcabc 4) S = zzxzzxzzx Function should return false if 1) S = abac 2) S = abcdabbd 3) S = abcabcefg 4) S = zzxzzyzzx */ public class NTMatch { public boolean match(char str[]){ int kmp[] = buildKMP(str); int index = kmp[str.length-1]; //reason end is this rather than index+1 because //if our string was ababab for KMP we would have index as 4 at str.length-1 and we //want end to be 1 rather than 5 int end = str.length - index-1; if(end >= str.length/2){ return false; } int j = end+1; int i = 0; while(j < str.length){ if(str[i] != str[j]){ return false; } i = (i+1)%(end+1); j++; } if(i == 0){ return true; } return false; } private int[] buildKMP(char str[]){ int result[] = new int[str.length]; int i =1; result[0] = 0; int len =0; while(i < str.length){ if(str[i] == str[len]){ len++; result[i] = len; i++; }else{ if(len != 0){ len = result[len-1]; }else{ len =0; result[i] = 0; i++; } } } return result; } public static void main(String args[]){ NTMatch ntMatch = new NTMatch(); System.out.println(ntMatch.match("bababababa".toCharArray())); } } ================================================ FILE: src/com/interview/string/PalindromePair.java ================================================ package com.interview.string; import java.util.*; /** * Given a list of unique words. Find all pairs of distinct indices (i, j) in the given list, * so that the concatenation of the two words, i.e. words[i] + words[j] is a palindrome. * * Solution - * First keep mapping of word and its index. * Then iterate through every word and split it into every possible 2 substring. Then if first substring is palindrome * and reverse of second substring is in map means you can form a palindrome by combing this word with the word * in the map. * * Time complexity is O(n*k*k) * * Reference * https://leetcode.com/problems/palindrome-pairs/ */ public class PalindromePair { public List> palindromePairs(String[] words) { if (words == null || words.length < 2) { return Collections.EMPTY_LIST; } Map wordMap = new HashMap<>(); List> result = new ArrayList<>(); for (int i = 0; i < words.length; i++) { wordMap.put(words[i], i); } for (int i = 0; i < words.length; i++) { for (int j = 0; j < words[i].length(); j++) { String str1 = words[i].substring(0, j + 1); String str2 = words[i].substring(j + 1, words[i].length()); if (isPalindrome(str2)) { String revStr1 = new StringBuilder(str1).reverse().toString(); Integer index = wordMap.get(revStr1); if (index != null) { createList(i, wordMap.get(revStr1), result); } } if (isPalindrome(str1)) { String revStr2 = new StringBuilder(str2).reverse().toString(); Integer index = wordMap.get(revStr2); if (index != null) { createList(wordMap.get(revStr2), i, result); if (revStr2.equals("")) { createList(i, wordMap.get(revStr2), result); } } } } } return result; } private boolean isPalindrome(String word) { int start = 0; int end = word.length() - 1; while (start < end) { if (word.charAt(start) != word.charAt(end)) { return false; } start++; end--; } return true; } private void createList(int i1, int i2, List> result) { if (i1 == i2) { return; } List r = new ArrayList<>(); r.add(i1); r.add(i2); result.add(r); } public static void main(String args[]) { PalindromePair palindromePair = new PalindromePair(); String[] words = {"bat", "tab"}; List> result = palindromePair.palindromePairs(words); System.out.println(result); String[] words1 = {"abcd", "dcba", "lls", "s", "sssll"}; result = palindromePair.palindromePairs(words1); System.out.println(result); String[] words2 = {"", "abcd", "abba"}; result = palindromePair.palindromePairs(words2); System.out.println(result); String[] words3 = {"a","abc","aba",""}; result = palindromePair.palindromePairs(words3); System.out.println(result); String[] words4 = {"abcd","dcba","lls","s","sssll"}; result = palindromePair.palindromePairs(words4); System.out.println(result); } } ================================================ FILE: src/com/interview/string/PrintAnagramTogether.java ================================================ package com.interview.string; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; public class PrintAnagramTogether { public void print(String[] string){ Map> invertedIndex = new HashMap>(); int index = 0; for(String str : string){ char [] charArray = str.toCharArray(); Arrays.sort(charArray); String newString = new String(charArray); if(invertedIndex.containsKey(newString)){ List pos = invertedIndex.get(newString); pos.add(index); }else{ List pos = new ArrayList(); pos.add(index); invertedIndex.put(newString, pos); } index++; } for(List result : invertedIndex.values()){ for(Integer i : result){ System.out.println(string[i]); } } } public static void main(String args[]){ String str[] = {"cat","dog","tac","god","act"}; PrintAnagramTogether pat = new PrintAnagramTogether(); pat.print(str); } } ================================================ FILE: src/com/interview/string/RabinKarpSearch.java ================================================ package com.interview.string; /** * Date 09/25/2014 * @author Tushar Roy * * Rabin Karp algorith for substring matching. * * Time complexity in worst case O(n^2)(depends on hash function) * Space complexity O(1) * * References * https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm */ public class RabinKarpSearch { private int prime = 101; public int patternSearch(char[] text, char[] pattern){ int m = pattern.length; int n = text.length; long patternHash = createHash(pattern, m - 1); long textHash = createHash(text, m - 1); for (int i = 1; i <= n - m + 1; i++) { if(patternHash == textHash && checkEqual(text, i - 1, i + m - 2, pattern, 0, m - 1)) { return i - 1; } if(i < n - m + 1) { textHash = recalculateHash(text, i - 1, i + m - 1, textHash, m); } } return -1; } private long recalculateHash(char[] str,int oldIndex, int newIndex,long oldHash, int patternLen) { long newHash = oldHash - str[oldIndex]; newHash = newHash/prime; newHash += str[newIndex]*Math.pow(prime, patternLen - 1); return newHash; } private long createHash(char[] str, int end){ long hash = 0; for (int i = 0 ; i <= end; i++) { hash += str[i]*Math.pow(prime,i); } return hash; } private boolean checkEqual(char str1[],int start1,int end1, char str2[],int start2,int end2){ if(end1 - start1 != end2 - start2) { return false; } while(start1 <= end1 && start2 <= end2){ if(str1[start1] != str2[start2]){ return false; } start1++; start2++; } return true; } public static void main(String args[]){ RabinKarpSearch rks = new RabinKarpSearch(); System.out.println(rks.patternSearch("TusharRoy".toCharArray(), "sharRoy".toCharArray())); System.out.println(rks.patternSearch("TusharRoy".toCharArray(), "Roy".toCharArray())); System.out.println(rks.patternSearch("TusharRoy".toCharArray(), "shas".toCharArray())); System.out.println(rks.patternSearch("TusharRoy".toCharArray(), "usha".toCharArray())); System.out.println(rks.patternSearch("TusharRoy".toCharArray(), "Tus".toCharArray())); } } ================================================ FILE: src/com/interview/string/RearrangeDuplicateCharsdDistanceAway.java ================================================ package com.interview.string; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.PriorityQueue; import java.util.Set; /** * http://www.geeksforgeeks.org/rearrange-a-string-so-that-all-same-characters-become-at-least-d-distance-away/ * */ public class RearrangeDuplicateCharsdDistanceAway { class CharCount implements Comparable{ char ch; int count; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + getOuterType().hashCode(); result = prime * result + ch; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; CharCount other = (CharCount) obj; if (!getOuterType().equals(other.getOuterType())) return false; if (ch != other.ch) return false; return true; } private RearrangeDuplicateCharsdDistanceAway getOuterType() { return RearrangeDuplicateCharsdDistanceAway.this; } @Override public String toString() { return "CharCount [ch=" + ch + ", count=" + count + "]"; } @Override public int compareTo(CharCount cc) { if(this.count >= cc.count){ return -1; }else{ return 1; } } } public boolean rearrangeExactKDistanceAway(char input[],int d){ PriorityQueue heap = new PriorityQueue(); Map map = new HashMap(); for(int i=0; i < input.length; i++){ int count = 1; if(map.containsKey(input[i])){ count = map.get(input[i]); count++; } map.put(input[i], count); input[i] = 0; } for(Character ch : map.keySet()){ CharCount cc = new CharCount(); cc.ch = ch; cc.count = map.get(ch); heap.add(cc); } while(heap.size() > 0){ CharCount cc = heap.poll(); int i; for(i=0; i < input.length && input[i] != 0; i++); if(i == input.length){ return false; } while(cc.count > 0 && i < input.length){ input[i] = cc.ch; i = i + d; cc.count--; } if(cc.count > 0){ return false; } } return true; } private void getAllFeasibleCharacters(char output[], int k,int pos,Set allChars){ for(int i = pos-1; i > pos -k && i >=0; i--){ allChars.remove(output[i]); } } public boolean rearrangeAtleastkDistanceAway(char input[],int k){ Map map = new HashMap(); for(int i=0; i < input.length; i++){ int count = 1; if(map.containsKey(input[i])){ count = map.get(input[i]); count++; } map.put(input[i], count); input[i] = 0; } return rearrangeAtleastkDistanceAway(map, input, 0, k); } public boolean rearrangeAtleastkDistanceAway(Map charCount,char output[],int pos,int k){ if(pos == output.length && charCount.size() == 0){ return true; } Set allChars = new HashSet(); for(char ch : charCount.keySet()){ allChars.add(ch); } getAllFeasibleCharacters(output,k,pos,allChars); for(char ch : allChars){ output[pos] = ch; int c = charCount.get(ch); if(c -1 == 0){ charCount.remove(ch); }else{ charCount.put(ch, c-1); } boolean r = rearrangeAtleastkDistanceAway(charCount, output, pos+1, k); if(r){ return true; } charCount.put(ch, c); } return false; } public static void main(String args[]){ String str = "ABBACCCCDD"; char input[] = str.toCharArray(); RearrangeDuplicateCharsdDistanceAway rdc =new RearrangeDuplicateCharsdDistanceAway(); boolean r =rdc.rearrangeAtleastkDistanceAway(input, 3); if(r){ for(char ch : input){ System.out.print(ch + " "); } }else{ System.out.println("Not possible"); } } } ================================================ FILE: src/com/interview/string/RemoveConsecutiveDuplicate.java ================================================ package com.interview.string; /** * Remove consecutive duplicate characters * e.g * AABBCDDAAB -> ABCDAB * ABBBCCD -> ABCD * Test cases * Empty string * all unique * all duplicates * duplicates at certain different places */ public class RemoveConsecutiveDuplicate { public int removeDuplicates(char input[]){ int slow = 0; int fast = 0; int index = 0; while(fast < input.length){ while(fast < input.length && input[slow] == input[fast]){ fast++; } input[index++] = input[slow]; slow = fast; } return index; } public static void main(String args[]){ String str = "AAABBCCDDDEFGH"; char input[] = str.toCharArray(); RemoveConsecutiveDuplicate rcd = new RemoveConsecutiveDuplicate(); int len = rcd.removeDuplicates(input); for(int i=0; i < len; i++){ System.out.print(input[i] + " "); } } } ================================================ FILE: src/com/interview/string/RunLengthEncoding.java ================================================ package com.interview.string; public class RunLengthEncoding { private int updateCounter(char[] result, int current, int counter){ int tempCounter = counter; int len = 1; while(tempCounter > 0){ len = len*10; tempCounter /= 10; } len = len/10; while(counter > 0){ result[current++] = (char)((counter/len) + '0'); counter = counter%len; len /= 10; } return current; } public int encoding(char[] str,char[] result){ char pickedChar = str[0]; int current =0; int counter =1; for(int i=1; i < str.length; i++){ if(str[i] == pickedChar){ counter++; } else{ result[current++] = pickedChar; current = updateCounter(result, current, counter); pickedChar = str[i]; counter =1; } } result[current++] = pickedChar; current = updateCounter(result, current, counter); return current; } public static void main(String args[]){ String str = "AAAAAAAAAAAAABBCDDEEEEE"; char result[] = new char[str.length()*2]; RunLengthEncoding rle = new RunLengthEncoding(); int current = rle.encoding(str.toCharArray(),result); for(int i=0; i < current; i++){ System.out.print(result[i]); } } } ================================================ FILE: src/com/interview/string/SmallestWindowContaingAllCharacters.java ================================================ package com.interview.string; /** * References * https://leetcode.com/problems/minimum-window-substring/ * http://www.geeksforgeeks.org/find-the-smallest-window-in-a-string-containing-all-characters-of-another-string/ */ import java.util.HashMap; import java.util.Map; public class SmallestWindowContaingAllCharacters { public String minWindow(String s, String t) { Map countMap = new HashMap<>(); for (char ch : t.toCharArray()) { Integer val = countMap.get(ch); if (val == null) { val = 0; } countMap.put(ch, val + 1); } int start = 0; int currLen = t.length(); int minWindow = Integer.MAX_VALUE; int minStart = 0; int i = 0; while (i < s.length()) { Integer val = countMap.get(s.charAt(i)); if (val == null) { i++; continue; } if (val > 0) { currLen--; } val--; countMap.put(s.charAt(i), val); while (currLen == 0) { if (minWindow > i - start + 1) { minWindow = i - start + 1; minStart = start; } Integer val1 = countMap.get(s.charAt(start)); if (val1 != null) { if (val1 == 0) { break; } else { val1++; countMap.put(s.charAt(start), val1); } } start++; } i++; } return minWindow != Integer.MAX_VALUE ? s.substring(minStart, minStart + minWindow) : ""; } public static void main(String args[]) { String str = "Tsuaosyogrlmnsluuorjkoruost"; String subString = "soor"; SmallestWindowContaingAllCharacters swcac = new SmallestWindowContaingAllCharacters(); String result = swcac.minWindow(str, subString); System.out.println(result); } } ================================================ FILE: src/com/interview/string/StringEncoderDecoder.java ================================================ package com.interview.string; import java.util.ArrayList; import java.util.List; /** * Date 04/06/2016 * @author Tushar Roy * * Design an algorithm to encode a list of strings to a string. The encoded string is then sent over the network * and is decoded back to the original list of strings. * * Reference * https://leetcode.com/problems/encode-and-decode-strings/ */ public class StringEncoderDecoder { // Encodes a list of strings to a single string. public String encode(List strs) { StringBuffer buff = new StringBuffer(); for (String str : strs) { String size = toFixedLength(str.length()); buff.append(size); buff.append(str); } return buff.toString(); } private String toFixedLength(int len) { StringBuffer buff = new StringBuffer(); for (int i = 0; i < 4; i++) { char b1 = (char) len; buff.append(b1); len = len >> 8; } return buff.toString(); } private int toSize(String str) { int val = 0; for (int i = str.length() - 1; i > 0; i--) { val += str.charAt(i); val = val << 8; } val += str.charAt(0); return val; } // Decodes a single string to a list of strings. public List decode(String s) { List result = new ArrayList<>(); while (s.length() != 0) { int size = toSize(s.substring(0, 4)); result.add(s.substring(4, size + 4)); s = s.substring(size + 4); } return result; } } ================================================ FILE: src/com/interview/string/SubstringSearch.java ================================================ package com.interview.string; /** * Date 09/22/2014 * @author tusroy * * Do pattern matching using KMP algorithm * * Runtime complexity - O(m + n) where m is length of text and n is length of pattern * Space complexity - O(n) */ public class SubstringSearch { /** * Slow method of pattern matching */ public boolean hasSubstring(char[] text, char[] pattern){ int i=0; int j=0; int k = 0; while(i < text.length && j < pattern.length){ if(text[i] == pattern[j]){ i++; j++; }else{ j=0; k++; i = k; } } if(j == pattern.length){ return true; } return false; } /** * Compute temporary array to maintain size of suffix which is same as prefix * Time/space complexity is O(size of pattern) */ private int[] computeTemporaryArray(char pattern[]){ int [] lps = new int[pattern.length]; int index =0; for(int i=1; i < pattern.length;){ if(pattern[i] == pattern[index]){ lps[i] = index + 1; index++; i++; }else{ if(index != 0){ index = lps[index-1]; }else{ lps[i] =0; i++; } } } return lps; } /** * KMP algorithm of pattern matching. */ public boolean KMP(char []text, char []pattern){ int lps[] = computeTemporaryArray(pattern); int i=0; int j=0; while(i < text.length && j < pattern.length){ if(text[i] == pattern[j]){ i++; j++; }else{ if(j!=0){ j = lps[j-1]; }else{ i++; } } } if(j == pattern.length){ return true; } return false; } public static void main(String args[]){ String str = "abcxabcdabcdabcy"; String subString = "abcdabcy"; SubstringSearch ss = new SubstringSearch(); boolean result = ss.KMP(str.toCharArray(), subString.toCharArray()); System.out.print(result); } } ================================================ FILE: src/com/interview/string/SubtringWithConcatentationOfWords.java ================================================ package com.interview.string; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * References * https://leetcode.com/problems/substring-with-concatenation-of-all-words/ */ public class SubtringWithConcatentationOfWords { public List findSubstring(String s, String[] words) { Map actual = new HashMap<>(); Map used = new HashMap<>(); set(actual, words); List output = new ArrayList<>(); int len = words[0].length(); int count = words.length; int k = words.length * len; for (int i = 0; i <= s.length() - k; i++) { int j = i; int currentCount = 0; while (true) { if(j + len > s.length()) { break; } String sub = s.substring(j, j + len); Integer actualCount = actual.get(sub); if (actualCount != null) { Integer usedCount = used.get(sub); if ( usedCount == null) { usedCount = 0; } if ( actualCount > usedCount) { j = j + len; currentCount++; used.put(sub, usedCount + 1); } else { break; } } else { break; } if ( currentCount == count) { break; } } used.clear(); if (currentCount == count) { output.add(i); } } return output; } private void set(Map actual, String[] words) { for (String word : words) { if (actual.containsKey(word)) { actual.put(word, actual.get(word) + 1); } else { actual.put(word, 1); } } } } ================================================ FILE: src/com/interview/string/ValidPalindrome.java ================================================ package com.interview.string; /** * Date 04/09/2016 * @author Tushar Roy * * Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. * For example, * "A man, a plan, a canal: Panama" is a palindrome. * "race a car" is not a palindrome. * * https://leetcode.com/problems/valid-palindrome/ */ public class ValidPalindrome { public boolean isPalindrome(String s) { int start = 0; int end = s.length() - 1; while (start < end) { if (!isAlphaNum(s.charAt(start))) { start++; } else if (!isAlphaNum(s.charAt(end))) { end--; } else { if (Character.toLowerCase(s.charAt(start++)) != Character.toLowerCase(s.charAt(end--))) { return false; } } } return true; } private boolean isAlphaNum(char ch) { if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) { return true; } return false; } } ================================================ FILE: src/com/interview/string/ValidWordAbbreviation.java ================================================ package com.interview.string; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * Date 04/15/2016 * @author Tushar Roy * * Given a dictionary of words and a word tell if there is unique abbrreviation of this word in the dictionary. */ public class ValidWordAbbreviation { private final Map> map = new HashMap<>(); public ValidWordAbbreviation(String[] dictionary) { for (String str : dictionary) { String key = ""; int len = 0; if (str.length() > 0) { key = str.charAt(0) + "" + str.charAt(str.length() - 1); len = str.length() - 2; } Map innerMap = map.get(key); if (innerMap == null) { innerMap = new HashMap<>(); map.put(key, innerMap); } Integer count = innerMap.get(len); if (count == null) { count = 0; } innerMap.put(len, count + 1); } } public boolean isUnique(String word) { if (word.length() == 0 || word.length() == 1) { return true; } String key = ""; int len = 0; if (word.length() > 0) { key = word.charAt(0) + "" + word.charAt(word.length() - 1); len = word.length() - 2; } Map set = map.get(key); if (set == null) { return true; } Integer count = set.get(len); return count == null || count == 1; } } ================================================ FILE: src/com/interview/string/WordAbbreviationCombination.java ================================================ package com.interview.string; import java.util.*; /** * Date 04/17/2106 * @author Tushar Roy * * Write a function to generate the generalized abbreviations of a word. * Example: * Given word = "word", return the following list (order does not matter): * ["word", "1ord", "w1rd", "wo1d", "wor1", "2rd", "w2d", "wo2", "1o1d", "1or1", "w1r1", "1o2", "2r1", "3d", "w3", "4"] * * https://leetcode.com/problems/generalized-abbreviation/ */ public class WordAbbreviationCombination { public List generateAbbreviations(String word) { List result = new ArrayList<>(); generateAbbreviationsUtil(word, result, "", 0, 0); return result; } public void generateAbbreviationsUtil(String input, List result, String current, int pos, int count) { if (input.length() == pos) { if (count > 0) { result.add(current + count); } else { result.add(current); } return; } generateAbbreviationsUtil(input, result, current, pos + 1, count + 1); generateAbbreviationsUtil(input, result, current + (count > 0 ? count : "") + input.charAt(pos), pos + 1, 0); } public static void main(String args[]) { WordAbbreviationCombination ssc = new WordAbbreviationCombination(); List result = ssc.generateAbbreviations("word"); result.forEach(r -> System.out.println(r)); } } ================================================ FILE: src/com/interview/string/ZAlgorithm.java ================================================ package com.interview.string; import java.util.ArrayList; import java.util.List; /** * Date 10/31/2015 * @author Tushar Roy * * Z algorithm to pattern matching * * Time complexity - O(n + m) * Space complexity - O(n + m) * * http://www.geeksforgeeks.org/z-algorithm-linear-time-pattern-searching-algorithm/ * http://www.utdallas.edu/~besp/demo/John2010/z-algorithm.htm */ public class ZAlgorithm { private int[] calculateZ(char input[]) { int Z[] = new int[input.length]; int left = 0; int right = 0; for(int k = 1; k < input.length; k++) { if(k > right) { left = right = k; while(right < input.length && input[right] == input[right - left]) { right++; } Z[k] = right - left; right--; } else { //we are operating inside box int k1 = k - left; //if value does not stretches till right bound then just copy it. if(Z[k1] < right - k + 1) { Z[k] = Z[k1]; } else { //otherwise try to see if there are more matches. left = k; while(right < input.length && input[right] == input[right - left]) { right++; } Z[k] = right - left; right--; } } } return Z; } /** * Returns list of all indices where pattern is found in text. */ public List matchPattern(char text[], char pattern[]) { char newString[] = new char[text.length + pattern.length + 1]; int i = 0; for(char ch : pattern) { newString[i] = ch; i++; } newString[i] = '$'; i++; for(char ch : text) { newString[i] = ch; i++; } List result = new ArrayList<>(); int Z[] = calculateZ(newString); for(i = 0; i < Z.length ; i++) { if(Z[i] == pattern.length) { result.add(i - pattern.length - 1); } } return result; } public static void main(String args[]) { String text = "aaabcxyzaaaabczaaczabbaaaaaabc"; String pattern = "aaabc"; ZAlgorithm zAlgorithm = new ZAlgorithm(); List result = zAlgorithm.matchPattern(text.toCharArray(), pattern.toCharArray()); result.forEach(System.out::println); } } ================================================ FILE: src/com/interview/suffixprefix/SuffixArray.java ================================================ package com.interview.suffixprefix; import java.util.Arrays; import java.util.Comparator; /** http://www.geeksforgeeks.org/suffix-array-set-1-introduction/ */ public class SuffixArray { public static class SuffixSort implements Comparator{ private char str[] = null; public SuffixSort(char str[]){ this.str = str; } @Override public int compare(Integer i1, Integer i2) { while(i1 < str.length && i2 < str.length && str[i1] == str[i2]){ i1++; i2++; } if(i2 == str.length && i1 == str.length){ return 0; } else if(i1 == str.length){ return -1; }else if(i2 == str.length){ return 1; }else return str[i1] < str[i2] ? -1 : 1; } } public Integer[] createSuffixArray(char str[]){ SuffixSort sort = new SuffixSort(str); Integer suffix[] = new Integer[str.length]; for(int i=0; i < suffix.length; i++){ suffix[i] = i; } Arrays.sort(suffix,sort); return suffix; } private int stringCompare(char str[],char subString[],int pos){ int i=0; while(pos < str.length && i < subString.length && str[pos] == subString[i]){ pos++; i++; } if(i == subString.length){ return 0; } if(pos == str.length){ return -1; } return str[pos] < subString[i] ? -1 : 1; } public int subStringSearch(char str[],char subString[], Integer suffix[]){ int low =0; int high = suffix.length-1; while(low <= high){ int mid = (low + high)/2; int result = stringCompare(str, subString, suffix[mid]); if(result == 0){ return suffix[mid]; } if(result > 0){ high = mid-1; }else{ low = mid+1; } } return -1; } public static void main(String args[]){ SuffixArray suffix = new SuffixArray(); String str = "missisippi"; Integer result[] = suffix.createSuffixArray(str.toCharArray()); System.out.print(suffix.subStringSearch(str.toCharArray(), "sippi".toCharArray(), result)); } } ================================================ FILE: src/com/interview/suffixprefix/SuffixTree.java ================================================ package com.interview.suffixprefix; import java.util.ArrayList; import java.util.List; /** * Date 06/01/2015 * @author tusroy * * Construct suffix tree using Ukkonen's algorithm * * Solution * Rule 1: For phase i+1 if S[j..i] ends at last character of leaf edge then add S[i+1] at * the end. * Rule 2: For phase i+1 if S[j..i] ends somewhere in middle of edge and next character is * not S[i+1] then a new leaf edge with label S[i+1] should be created * Rule 3: For phase i+1 if S[j..i] ends somewhere in middle of edge and next character is * S[i+1] then do nothing(resulting in implicit tree) * * Suffix Link: * For every node with label x@ where x is a single character and @ is possibly empty substring * there is another node with label x. This node is suffix link of first node. If @ is * empty then suffix link is root. * * Trick1 * Skip/Count trick * While traveling down if number of characters on edge is less than number of characters * to traverse then skip directly to the end of the edge. If number of characters on label * is more than number of characters to traverse then go directly to that character * we care about. * * Edge-label compression * Instead of storing actual characters on the path store start and end indices on the * path. * * Trick2 - Stop process as soon as you hit rule 3. Rule 3 is show stopper * * Trick3 - Keep a global end on leaf to do rule 1 extension. * * Active point - It is the point from which traversal starts for next extension or next phase. * Active point always starts from root. Other extension will get active point set up * correctly by last extension. * * Active node - Node from which active point will start * Active Edge - It is used to choose the edge from active node. It has index of character. * Active Length - How far to go on active edge. * * Active point rules * 1) If rule 3 extension is applied then active length will increment by 1 if active length is not greater then length of path on edge. * 2) If rule 3 extension is applied and if active length gets greater than length path of edge then change active node, active edge and active length * 3) If active length is 0 then always start looking for the character from root. * 4) If rule 2 extension is applied and if active node is root then active edge is active edge + 1 and active length is active lenght -1 * 5) If rule 2 extension is applied and if active node is not root then follow suffix link and make active node as suffix link and do no change * anything. * * Test cases * adeacdade * abcabxabcd * abcdefabxybcdmnabcdex * abcadak * dedododeodo * abcabxabcd * mississippi * banana * ooooooooo * * References * http://web.stanford.edu/~mjkay/gusfield.pdf * http://www.geeksforgeeks.org/ukkonens-suffix-tree-construction-part-6/ * https://www.cs.helsinki.fi/u/ukkonen/SuffixT1withFigs.pdf * https://gist.github.com/axefrog/2373868 */ public class SuffixTree { public static void main(String args[]){ SuffixTree st = new SuffixTree("mississippi".toCharArray()); st.build(); st.dfsTraversal(); System.out.println(st.validate()); } private SuffixNode root; private Active active; private int remainingSuffixCount; private End end; private char input[]; private static char UNIQUE_CHAR = '$'; public SuffixTree(char input[]){ this.input = new char[input.length+1]; for(int i=0; i < input.length; i++){ this.input[i] = input[i]; } this.input[input.length] = UNIQUE_CHAR; } public void build(){ root = SuffixNode.createNode(1, new End(0)); root.index = -1; active = new Active(root); this.end = new End(-1); //loop through string to start new phase for(int i=0; i < input.length; i++){ startPhase(i); } if (remainingSuffixCount != 0) { System.out.print("Something wrong happened"); } //finally walk the tree again and set up the index. setIndexUsingDfs(root, 0, input.length); } private void startPhase(int i){ //set lastCreatedInternalNode to null before start of every phase. SuffixNode lastCreatedInternalNode = null; //global end for leaf. Does rule 1 extension as per trick 3 by incrementing end. end.end++; //these many suffixes need to be created. remainingSuffixCount++; while(remainingSuffixCount > 0){ //if active length is 0 then look for current character from root. if(active.activeLength == 0){ //if current character from root is not null then increase active length by 1 //and break out of while loop. This is rule 3 extension and trick 2 (show stopper) if(selectNode(i) != null){ active.activeEdge = selectNode(i).start; active.activeLength++; break; } //create a new leaf node with current character from leaf. This is rule 2 extension. else { root.child[input[i]] = SuffixNode.createNode(i, end); remainingSuffixCount--; } } else{ //if active length is not 0 means we are traversing somewhere in middle. So check if next character is same as //current character. try { char ch = nextChar(i); //if next character is same as current character then do a walk down. This is again a rule 3 extension and //trick 2 (show stopper). if(ch == input[i]){ //if lastCreatedInternalNode is not null means rule 2 extension happened before this. Point suffix link of that node //to selected node using active point. //TODO - Could be wrong here. Do we only do this if when walk down goes past a node or we do it every time. if(lastCreatedInternalNode != null){ lastCreatedInternalNode.suffixLink = selectNode(); } //walk down and update active node if required as per rules of active node update for rule 3 extension. walkDown(i); break; } else { //next character is not same as current character so create a new internal node as per //rule 2 extension. SuffixNode node = selectNode(); int oldStart = node.start; node.start = node.start + active.activeLength; //create new internal node SuffixNode newInternalNode = SuffixNode.createNode(oldStart, new End(oldStart + active.activeLength - 1)); //create new leaf node SuffixNode newLeafNode = SuffixNode.createNode(i, this.end); //set internal nodes child as old node and new leaf node. newInternalNode.child[input[newInternalNode.start + active.activeLength]] = node; newInternalNode.child[input[i]] = newLeafNode; newInternalNode.index = -1; active.activeNode.child[input[newInternalNode.start]] = newInternalNode; //if another internal node was created in last extension of this phase then suffix link of that //node will be this node. if (lastCreatedInternalNode != null) { lastCreatedInternalNode.suffixLink = newInternalNode; } //set this guy as lastCreatedInternalNode and if new internalNode is created in next extension of this phase //then point suffix of this node to that node. Meanwhile set suffix of this node to root. lastCreatedInternalNode = newInternalNode; newInternalNode.suffixLink = root; //if active node is not root then follow suffix link if(active.activeNode != root){ active.activeNode = active.activeNode.suffixLink; } //if active node is root then increase active index by one and decrease active length by 1 else{ active.activeEdge = active.activeEdge + 1; active.activeLength--; } remainingSuffixCount--; } } catch (EndOfPathException e) { //this happens when we are looking for new character from end of current path edge. Here we already have internal node so //we don't have to create new internal node. Just create a leaf node from here and move to suffix new link. SuffixNode node = selectNode(); node.child[input[i]] = SuffixNode.createNode(i, end); if (lastCreatedInternalNode != null) { lastCreatedInternalNode.suffixLink = node; } lastCreatedInternalNode = node; //if active node is not root then follow suffix link if(active.activeNode != root){ active.activeNode = active.activeNode.suffixLink; } //if active node is root then increase active index by one and decrease active length by 1 else{ active.activeEdge = active.activeEdge + 1; active.activeLength--; } remainingSuffixCount--; } } } } private void walkDown(int index){ SuffixNode node = selectNode(); //active length is greater than path edge length. //walk past current node so change active point. //This is as per rules of walk down for rule 3 extension. if(diff(node) < active.activeLength){ active.activeNode = node; active.activeLength = active.activeLength - diff(node); active.activeEdge = node.child[input[index]].start; }else{ active.activeLength++; } } //find next character to be compared to current phase character. private char nextChar(int i) throws EndOfPathException{ SuffixNode node = selectNode(); if(diff(node) >= active.activeLength){ return input[active.activeNode.child[input[active.activeEdge]].start + active.activeLength]; } if(diff(node) + 1 == active.activeLength ){ if(node.child[input[i]] != null){ return input[i]; } } else{ active.activeNode = node; active.activeLength = active.activeLength - diff(node) -1; active.activeEdge = active.activeEdge + diff(node) +1; return nextChar(i); } throw new EndOfPathException(); } private static class EndOfPathException extends Exception{ } private SuffixNode selectNode(){ return active.activeNode.child[input[active.activeEdge]]; } private SuffixNode selectNode(int index){ return active.activeNode.child[input[index]]; } private int diff(SuffixNode node){ return node.end.end - node.start; } private void setIndexUsingDfs(SuffixNode root,int val, int size){ if(root == null){ return; } val += root.end.end - root.start + 1; if(root.index != -1){ root.index = size - val; return; } for(SuffixNode node : root.child){ setIndexUsingDfs(node, val, size); } } /** * Do a DFS traversal of the tree. */ public void dfsTraversal(){ List result = new ArrayList<>(); for(SuffixNode node : root.child){ dfsTraversal(node, result); } } private void dfsTraversal(SuffixNode root, List result){ if(root == null){ return; } if(root.index != -1){ for(int i=root.start; i <= root.end.end; i++){ result.add(input[i]); } result.stream().forEach(System.out::print); System.out.println(" " + root.index); for(int i=root.start; i <= root.end.end; i++){ result.remove(result.size()-1); } return; } for(int i=root.start; i <= root.end.end; i++){ result.add(input[i]); } for(SuffixNode node : root.child){ dfsTraversal(node, result); } for(int i=root.start; i <= root.end.end; i++){ result.remove(result.size()-1); } } /** * Do validation of the tree by comparing all suffixes and their index at leaf node. */ private boolean validate(SuffixNode root, char[] input, int index, int curr){ if(root == null){ System.out.println("Failed at " + curr + " for index " + index); return false; } if(root.index != -1){ if(root.index != index){ System.out.println("Index not same. Failed at " + curr + " for index " + index); return false; }else{ return true; } } if(curr >= input.length){ System.out.println("Index not same. Failed at " + curr + " for index " + index); return false; } SuffixNode node = root.child[input[curr]]; if(node == null){ System.out.println("Failed at " + curr + " for index " + index); return false; } int j = 0; for(int i=node.start ; i <= node.end.end; i++){ if(input[curr+j] != input[i] ){ System.out.println("Mismatch found " + input[curr+j] + " " + input[i]); return false; } j++; } curr += node.end.end - node.start + 1; return validate(node, input, index, curr); } public boolean validate(){ for(int i=0; i < this.input.length; i++){ if(!validate(this.root, this.input, i, i)){ System.out.println("Failed validation"); return false; } } return true; } } class SuffixNode{ private SuffixNode(){ } private static final int TOTAL = 256; SuffixNode[] child = new SuffixNode[TOTAL]; int start; End end; int index; SuffixNode suffixLink; public static SuffixNode createNode(int start, End end){ SuffixNode node = new SuffixNode(); node.start = start; node.end = end; return node; } @Override public String toString() { StringBuffer buffer = new StringBuffer(); int i=0; for(SuffixNode node : child){ if(node != null){ buffer.append((char)i + " "); } i++; } return "SuffixNode [start=" + start + "]" + " " + buffer.toString(); } } class End{ public End(int end){ this.end = end; } int end; } class Active{ Active(SuffixNode node){ activeLength = 0; activeNode = node; activeEdge = -1; } @Override public String toString() { return "Active [activeNode=" + activeNode + ", activeIndex=" + activeEdge + ", activeLength=" + activeLength + "]"; } SuffixNode activeNode; int activeEdge; int activeLength; } ================================================ FILE: src/com/interview/suffixprefix/TernaryTree.java ================================================ package com.interview.suffixprefix; /** * http://www.geeksforgeeks.org/ternary-search-tree/ */ public class TernaryTree { private Node root = null; class Node{ char data; boolean isLeaf; Node left, right, eq; } public void insert(String data){ Node root = insert(this.root,data,0); this.root = root; } public boolean search(String data){ return search(root,data,0); } private boolean search(Node root,String data,int pos){ if(pos == data.length()){ return true; } if(root == null){ return false; } if(root.data == data.charAt(pos)){ boolean result = search(root.eq,data,pos+1); if(pos == data.length() -1){ return result && root.isLeaf; } return result; }else if(root.data < data.charAt(pos)){ return search(root.right,data,pos); }else{ return search(root.left,data,pos); } } private Node insert(Node root,String data,int pos){ if(pos == data.length()){ return root; } if(root == null){ root = new Node(); root.data = data.charAt(pos); root.eq = insert(root.eq,data,pos+1); if(pos == (data.length()-1)){ root.isLeaf = true; } }else{ if(root.data == data.charAt(pos)){ root.eq = insert(root.eq,data,pos+1); if(pos == (data.length()-1)){ root.isLeaf = true; } } else if(root.data < data.charAt(pos)){ root.right = insert(root.right,data,pos); }else{ root.left = insert(root.left,data,pos); } } return root; } public static void main(String args[]){ TernaryTree tt = new TernaryTree(); tt.insert("cute"); tt.insert("as"); tt.insert("at"); tt.insert("cut"); tt.insert("cup"); tt.insert("time"); tt.insert("tax"); tt.insert("bat"); System.out.println(tt.search("cute")); System.out.println(tt.search("cut")); System.out.println(tt.search("tax")); System.out.println(tt.search("as")); System.out.println(tt.search("abat")); } } ================================================ FILE: src/com/interview/suffixprefix/Trie.java ================================================ package com.interview.suffixprefix; import java.util.HashMap; import java.util.Map; /** * Date 04/25/2016 * @author Tushar Roy * * Insert/delete/search into trie data structure * * Reference * https://en.wikipedia.org/wiki/Trie */ public class Trie { private class TrieNode { Map children; boolean endOfWord; public TrieNode() { children = new HashMap<>(); endOfWord = false; } } private final TrieNode root; public Trie() { root = new TrieNode(); } /** * Iterative implementation of insert into trie */ public void insert(String word) { TrieNode current = root; for (int i = 0; i < word.length(); i++) { char ch = word.charAt(i); TrieNode node = current.children.get(ch); if (node == null) { node = new TrieNode(); current.children.put(ch, node); } current = node; } //mark the current nodes endOfWord as true current.endOfWord = true; } /** * Recursive implementation of insert into trie */ public void insertRecursive(String word) { insertRecursive(root, word, 0); } private void insertRecursive(TrieNode current, String word, int index) { if (index == word.length()) { //if end of word is reached then mark endOfWord as true on current node current.endOfWord = true; return; } char ch = word.charAt(index); TrieNode node = current.children.get(ch); //if node does not exists in map then create one and put it into map if (node == null) { node = new TrieNode(); current.children.put(ch, node); } insertRecursive(node, word, index + 1); } /** * Iterative implementation of search into trie. */ public boolean search(String word) { TrieNode current = root; for (int i = 0; i < word.length(); i++) { char ch = word.charAt(i); TrieNode node = current.children.get(ch); //if node does not exist for given char then return false if (node == null) { return false; } current = node; } //return true of current's endOfWord is true else return false. return current.endOfWord; } /** * Recursive implementation of search into trie. */ public boolean searchRecursive(String word) { return searchRecursive(root, word, 0); } private boolean searchRecursive(TrieNode current, String word, int index) { if (index == word.length()) { //return true of current's endOfWord is true else return false. return current.endOfWord; } char ch = word.charAt(index); TrieNode node = current.children.get(ch); //if node does not exist for given char then return false if (node == null) { return false; } return searchRecursive(node, word, index + 1); } /** * Delete word from trie. */ public void delete(String word) { delete(root, word, 0); } /** * Returns true if parent should delete the mapping */ private boolean delete(TrieNode current, String word, int index) { if (index == word.length()) { //when end of word is reached only delete if currrent.endOfWord is true. if (!current.endOfWord) { return false; } current.endOfWord = false; //if current has no other mapping then return true return current.children.size() == 0; } char ch = word.charAt(index); TrieNode node = current.children.get(ch); if (node == null) { return false; } boolean shouldDeleteCurrentNode = delete(node, word, index + 1); //if true is returned then delete the mapping of character and trienode reference from map. if (shouldDeleteCurrentNode) { current.children.remove(ch); //return true if no mappings are left in the map. return current.children.size() == 0; } return false; } } ================================================ FILE: src/com/interview/tree/AVLTree.java ================================================ package com.interview.tree; /** * Date 07/04/2014 * @author tusroy * * Video link - https://youtu.be/rbg7Qf8GkQ4 * * Write a program to insert into an AVL tree. * * AVL tree is self balancing binary tree. Difference of height of left or right subtree * cannot be greater than one. * * There are four different use cases to insert into AVL tree * left left - needs ones right rotation * left right - needs one left and one right rotation * right left - needs one right and one left rotation * right right - needs one left rotation * * Follow rotation rules to keep tree balanced. * * At every node we will also keep height of the tree so that we don't * have to recalculate values again. * * Runtime complexity to insert into AVL tree is O(logn). * * References * http://en.wikipedia.org/wiki/AVL_tree * http://www.geeksforgeeks.org/avl-tree-set-1-insertion/ * */ public class AVLTree { private Node leftRotate(Node root){ Node newRoot = root.right; root.right = root.right.left; newRoot.left = root; root.height = setHeight(root); root.size = setSize(root); newRoot.height = setHeight(newRoot); newRoot.size = setSize(newRoot); return newRoot; } private Node rightRotate(Node root){ Node newRoot = root.left; root.left = root.left.right; newRoot.right = root; root.height = setHeight(root); root.size = setSize(root); newRoot.height = setHeight(newRoot); newRoot.size = setSize(newRoot); return newRoot; } private int setHeight(Node root){ if(root == null){ return 0; } return 1 + Math.max((root.left != null ? root.left.height : 0), (root.right != null ? root.right.height : 0)); } private int height(Node root){ if(root == null){ return 0; }else { return root.height; } } private int setSize(Node root){ if(root == null){ return 0; } return 1 + Math.max((root.left != null ? root.left.size : 0), (root.right != null ? root.right.size : 0)); } public Node insert(Node root, int data){ if(root == null){ return Node.newNode(data); } if(root.data <= data){ root.right = insert(root.right,data); } else{ root.left = insert(root.left,data); } int balance = balance(root.left, root.right); if(balance > 1){ if(height(root.left.left) >= height(root.left.right)){ root = rightRotate(root); }else{ root.left = leftRotate(root.left); root = rightRotate(root); } }else if(balance < -1){ if(height(root.right.right) >= height(root.right.left)){ root = leftRotate(root); }else{ root.right = rightRotate(root.right); root = leftRotate(root); } } else{ root.height = setHeight(root); root.size = setSize(root); } return root; } private int balance(Node rootLeft, Node rootRight){ return height(rootLeft) - height(rootRight); } public static void main(String args[]){ AVLTree avlTree = new AVLTree(); Node root = null; root = avlTree.insert(root, -10); root = avlTree.insert(root, 2); root = avlTree.insert(root, 13); root = avlTree.insert(root, -13); root = avlTree.insert(root, -15); root = avlTree.insert(root, 15); root = avlTree.insert(root, 17); root = avlTree.insert(root, 20); TreeTraversals tt = new TreeTraversals(); tt.inOrder(root); System.out.println(); tt.preOrder(root); } } ================================================ FILE: src/com/interview/tree/AddGreaterValueNodeToEveryNode.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/add-greater-values-every-node-given-bst/ * Test cases: * Empty tree * One node tree * Two node tree */ class IntegerRef{ int val; } public class AddGreaterValueNodeToEveryNode { public void add(Node root,IntegerRef ref){ if(root == null){ return ; } add(root.right,ref); root.data += ref.val; ref.val = root.data; add(root.left,ref); } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node root = null; root = bt.addNode(10, root); root = bt.addNode(5, root); root = bt.addNode(20, root); root = bt.addNode(15, root); root = bt.addNode(25, root); AddGreaterValueNodeToEveryNode agv = new AddGreaterValueNodeToEveryNode(); IntegerRef ir = new IntegerRef(); ir.val = 0; agv.add(root, ir); TreeTraversals tt = new TreeTraversals(); tt.inOrder(root); } } ================================================ FILE: src/com/interview/tree/ArbitaryTreeToChildSumTree.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/convert-an-arbitrary-binary-tree-to-a-tree-that-holds-children-sum-property/ * Only operation you can do is increase data on the node. No decrement of data * Test case * Root greater than children * Root less than children * Root equal to children */ public class ArbitaryTreeToChildSumTree { public void childSumTree(Node root){ toChildSumTree(root); } private void incrementChild(Node root,int increment){ if(root == null || (root.left ==null && root.right == null)){ return; } if(root.left != null){ root.left.data = root.left.data + increment; incrementChild(root.left,increment); }else{ root.right.data = root.right.data + increment; incrementChild(root.right,increment); } } private int toChildSumTree(Node root){ if(root == null){ return 0; } if(root.left == null && root.right == null){ return root.data; } int sum1 = toChildSumTree(root.left); int sum2 = toChildSumTree(root.right); if(root.data < sum1 + sum2){ root.data = sum1 + sum2; }else if(root.data > sum1 + sum2){ incrementChild(root,root.data - sum1 - sum2); } return root.data; } public static void main(String args[]){ ArbitaryTreeToChildSumTree att = new ArbitaryTreeToChildSumTree(); BinaryTree bt = new BinaryTree(); Node head = null; head = bt.addNode(10, head); head = bt.addNode(15, head); head = bt.addNode(5, head); head = bt.addNode(7, head); head = bt.addNode(19, head); head = bt.addNode(20, head); head = bt.addNode(-1, head); att.childSumTree(head); TreeTraversals tt = new TreeTraversals(); tt.inOrder(head); } } ================================================ FILE: src/com/interview/tree/BSTOneChildPreOrderTraversal.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/check-if-each-internal-node-of-a-bst-has-exactly-one-child/ */ public class BSTOneChildPreOrderTraversal { public boolean isBST(int input[]){ int max = Integer.MAX_VALUE; int min = Integer.MIN_VALUE; for(int i = 0; i < input.length-1; i++){ if(input[i] > min && input[i] < max){ if(input[i+1] < input[i]){ max = input[i]; }else{ min = input[i]; } }else{ return false; } } if(input[input.length-1] < max && input[input.length-1] > min){ return true; }else{ return false; } } public static void main(String args[]){ int input[] = {20,10,14,15,17}; BSTOneChildPreOrderTraversal boc = new BSTOneChildPreOrderTraversal(); System.out.println(boc.isBST(input)); } } ================================================ FILE: src/com/interview/tree/BSTSearch.java ================================================ package com.interview.tree; /** * Date 04/11/2015 * @author tusroy * * Youtube link - https://youtu.be/zm83jPHZ-jA * * Given a binary search tree and a key, return node which has data as this key or return * null if no node has data as key. * * Solution * Since its BST for every node check if root.data is key and if not go either left or * right depending on if root.data is greater or less than key * * Time complexity is O(n) for non balanced BST * Time complexity is O(logn) for balanced BST * * Test cases: * 1) null tree * 2) Tree with one node and key is that node * 3) Tree with many nodes and key does not exist * 4) Tree with many nodes and key exists */ public class BSTSearch { public Node search(Node root, int key){ if(root == null){ return null; } if(root.data == key){ return root; }else if(root.data < key){ return search(root.right, key); }else{ return search(root.left, key); } } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node root = null; root = bt.addNode(10, root); root = bt.addNode(20, root); root = bt.addNode(-10, root); root = bt.addNode(15, root); root = bt.addNode(0, root); root = bt.addNode(21, root); root = bt.addNode(-1, root); BSTSearch bstSearch = new BSTSearch(); Node result = bstSearch.search(root, 21); assert result.data == 21; result = bstSearch.search(root, -1); assert result.data == 21; result = bstSearch.search(root, 11); assert result == null; } } ================================================ FILE: src/com/interview/tree/BTree.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/b-tree-set-1-insert-2/ * http://www.geeksforgeeks.org/b-tree-set-1-introduction-2/ */ public class BTree { private BTreeNode root = null; private static int T = 2; public void insert(int data){ if(root == null){ root = BTreeNode.newNode(data); return; } SplitResult sr = insert(root,data); if(sr != null){ BTreeNode newRoot = BTreeNode.newNode(); newRoot.n = 1; newRoot.isLeaf = false; newRoot.keys[0] = sr.c; newRoot.child[0] = sr.r1; newRoot.child[1] = sr.r2; root = newRoot; } } public boolean search(int data){ return search(root,data); } public boolean search(BTreeNode root, int data){ int i =0; while(i < root.n && root.keys[i] < data){ i++; } if(i < root.n && root.keys[i] == data){ return true; } if(root.isLeaf){ return false; } return search(root.child[i],data); } private SplitResult insert(BTreeNode root,int data){ if(root.isLeaf){ if(!root.isFull()){ root.insertKey(data, null, null); return null; }else{ SplitResult sr = splitNode(root,data,null,null); return sr; } }else{ int i=0; for(; i < root.n; i++){ if(data <= root.keys[i]){ SplitResult sr = insert(root.child[i],data); if(sr == null){ return null; }else{ if(!root.isFull()){ root.insertKey(sr.c, sr.r1, sr.r2); return null; }else{ SplitResult sr1 = splitNode(root,sr.c,sr.r1,sr.r2); return sr1; } } } } if(i == root.n){ SplitResult sr = insert(root.child[i],data); if(sr == null){ return null; }else{ if(!root.isFull()){ root.insertKey(sr.c, sr.r1, sr.r2); return null; }else{ SplitResult sr1 = splitNode(root,sr.c,sr.r1,sr.r2); return sr1; } } } } return null; } private SplitResult splitNode(BTreeNode node,int data, BTreeNode nr1, BTreeNode nr2){ int c = node.keys[node.n/2]; BTreeNode r1 = BTreeNode.newNode(); BTreeNode r2 = BTreeNode.newNode(); r1.n = node.n/2; r2.n = node.n - node.n/2-1; if(!node.isLeaf){ r1.isLeaf = false; r2.isLeaf = false; } int i=0; for(; i < node.n/2; i++){ r1.keys[i] = node.keys[i]; r1.child[i] = node.child[i]; } r1.child[i] = node.child[i]; i = node.n/2 + 1; int j=0; for(;i < node.n; i++,j++){ r2.keys[j] = node.keys[i]; r2.child[j] = node.child[i]; } r2.child[j] = node.child[i]; if(data < c){ r1.insertKey(data, nr1, nr2); }else{ r2.insertKey(data, nr1, nr2); } SplitResult sr = new SplitResult(); sr.c = c; sr.r1 = r1; sr.r2 = r2; return sr; } class SplitResult{ BTreeNode r1; BTreeNode r2; int c; } public void traverse(){ traverse(root); } private void traverse(BTreeNode root){ for(int i=0; i < root.n; i++){ if(!root.isLeaf){ traverse(root.child[i]); } System.out.print(root.keys[i] + " "); } if(!root.isLeaf){ traverse(root.child[root.n]); } } static class BTreeNode{ int n ; BTreeNode[] child = new BTreeNode[2*T]; int keys[] = new int[2*T-1]; boolean isLeaf; public void insertKey(int data,BTreeNode r1,BTreeNode r2){ int i = n-1; while(i >=0 && data < keys[i]){ keys[i+1] = keys[i]; i--; } keys[i+1] = data; int j = n; while(j > i+1){ child[j+1] = child[j]; j--; } child[j] = r1; child[j+1] = r2; n++; } public static BTreeNode newNode(int data){ BTreeNode node = new BTreeNode(); node.keys[0] = data; node.isLeaf = true; node.n = 1; return node; } public static BTreeNode newNode(){ BTreeNode node = new BTreeNode(); node.isLeaf = true; node.n = 0; return node; } public boolean isFull(){ return 2*T - 1 == n; } } public static void main(String args[]){ BTree bTree = new BTree(); bTree.insert(5); bTree.insert(4); bTree.insert(3); bTree.insert(2); bTree.insert(1); bTree.insert(6); bTree.insert(11); bTree.insert(13); bTree.insert(8); bTree.insert(7); bTree.insert(10); bTree.insert(9); bTree.insert(28); bTree.insert(22); bTree.insert(12); bTree.insert(18); bTree.insert(16); bTree.traverse(); System.out.print(bTree.search(28)); System.out.print(bTree.search(11)); System.out.print(bTree.search(5)); System.out.print(bTree.search(21)); System.out.print(bTree.search(3)); System.out.print(bTree.search(4)); System.out.print(bTree.search(14)); } } ================================================ FILE: src/com/interview/tree/BinaryTree.java ================================================ package com.interview.tree; /** * Date 07/07/2014 * @author tusroy * * Youtube link - https://youtu.be/bmaeYtlO2OE * Youtube link - https://youtu.be/_SiwrPXG9-g * Youtube link - https://youtu.be/NA8B84DZYSA * */ class NodeRef{ Node node; } enum Color{ RED, BLACK } class Node{ Node left; Node right; Node next; int data; int lis; int height; int size; Color color; public static Node newNode(int data){ Node n = new Node(); n.left = null; n.right = null; n.data = data; n.lis = -1; n.height = 1; n.size = 1; n.color = Color.RED; return n; } } public class BinaryTree { public Node addNode(int data, Node head){ Node tempHead = head; Node n = Node.newNode(data); if(head == null){ head = n; return head; } Node prev = null; while(head != null){ prev = head; if(head.data < data){ head = head.right; }else{ head = head.left; } } if(prev.data < data){ prev.right = n; }else{ prev.left = n; } return tempHead; } class IntegerRef{ int height; } public int height(Node root){ if(root == null){ return 0; } int leftHeight = height(root.left); int rightHeight = height(root.right); return Math.max(leftHeight, rightHeight) + 1; } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node head = null; head = bt.addNode(10, head); head = bt.addNode(15, head); head = bt.addNode(5, head); head = bt.addNode(7, head); head = bt.addNode(19, head); head = bt.addNode(20, head); head = bt.addNode(-1, head); head = bt.addNode(21, head); System.out.println(bt.height(head)); } } ================================================ FILE: src/com/interview/tree/BinaryTreeFromParentRepresentation.java ================================================ package com.interview.tree; /** * Date 11/01/2015 * @author Tushar Roy * * Given an array reprsentation of binary tree where index is data while value at index is * parent create the binary tree. Value of -1 indicates root node. * * References: * http://www.geeksforgeeks.org/construct-a-binary-tree-from-parent-array-representation/ */ public class BinaryTreeFromParentRepresentation { public Node create(int input[]) { Node t[] = new Node[input.length]; for(int i = 0; i < input.length; i++) { t[i] = new Node(); t[i].data = i; } Node root = null; for(int i = 0; i < input.length; i++) { int parentIndex = input[i]; if(parentIndex == -1) { root = t[i]; continue; } Node parent = t[parentIndex]; if(parent.left == null) { parent.left = t[i]; } else { parent.right = t[i]; } } return root; } public static void main(String args[]) { BinaryTreeFromParentRepresentation btpp = new BinaryTreeFromParentRepresentation(); int input[] = {1, 5, 5, 2, 2, -1, 3}; Node root = btpp.create(input); TreeTraversals tt = new TreeTraversals(); tt.inOrder(root); System.out.println(); tt.preOrder(root); } } ================================================ FILE: src/com/interview/tree/BinaryTreeMaximumPathSum.java ================================================ package com.interview.tree; /** * Date 03/22/2016 * @author Tushar Roy * * Given a binary tree, find the maximum path sum. For this problem, a path is defined as any sequence of nodes * from some starting node to any node in the tree along the parent-child connections. * * Time complexity O(n) * Space complexity depends on depth of tree. * * https://leetcode.com/problems/binary-tree-maximum-path-sum/ */ public class BinaryTreeMaximumPathSum { int max = 0; public int maxPathSum(Node root) { max = Integer.MIN_VALUE; maxPathSumUtil(root); return max; } private int maxPathSumUtil(Node root) { if (root == null) { return 0; } int left = maxPathSumUtil(root.left); int right = maxPathSumUtil(root.right); if (left < 0) { left = 0; } if (right < 0) { right = 0; } max = Math.max(max, root.data + left + right); return root.data + Math.max(left, right); } } ================================================ FILE: src/com/interview/tree/BinaryTreeToCircularLinkList.java ================================================ package com.interview.tree; /** * http://cslibrary.stanford.edu/109/TreeListRecursion.html * Test cases * Null tree * */ public class BinaryTreeToCircularLinkList { public Node convert(Node root){ if(root == null){ return null; } if(root.left == null && root.right == null){ root.left = root; root.right = root; return root; } Node left = convert(root.left); Node right = convert(root.right); root.left = root; root.right = root; left = join(left,root); left = join(left,right); return left; } private Node join(Node r1, Node r2){ if(r1 == null){ return r2; } if(r2 == null){ return r1; } Node t1 = r2.left; r1.left.right = r2; r2.left = r1.left; r1.left = t1; t1.right = r1; return r1; } private void print(Node root){ Node temp = root; do{ System.out.println(temp.data); temp = temp.right; }while(temp != root); System.out.println(); do{ System.out.println(temp.data); temp = temp.left; }while(temp != root); } public static void main(String args[]){ BinaryTreeToCircularLinkList btc = new BinaryTreeToCircularLinkList(); BinaryTree bt = new BinaryTree(); Node root = null; root = bt.addNode(10, root); root = bt.addNode(3, root); root = bt.addNode(-1, root); root = bt.addNode(8, root); root = bt.addNode(-6, root); root = bt.addNode(13, root); root = btc.convert(root); btc.print(root); } } ================================================ FILE: src/com/interview/tree/BinaryTreeToDoubleLinkList.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/convert-given-binary-tree-doubly-linked-list-set-3/ */ public class BinaryTreeToDoubleLinkList { public void toDoubleLL(Node root){ NodeRef prev = new NodeRef(); toDoubleLL(root,prev); } private void toDoubleLL(Node root, NodeRef prev){ if(root == null){ return; } toDoubleLL(root.left,prev); if(prev.node != null){ prev.node.right = root; root.left = prev.node; prev.node = root; }else{ prev.node = root; } toDoubleLL(root.right,prev); } public void print(Node root){ Node curr = null; while(root != null){ curr = root; System.out.print(root.data + " "); root = root.right; } System.out.println(); root = curr; while(root != null){ System.out.print(root.data + " "); root = root.left; } } public static void main(String args[]){ BinaryTreeToDoubleLinkList btd = new BinaryTreeToDoubleLinkList(); BinaryTree bt = new BinaryTree(); Node head = null; head = bt.addNode(100, head); head = bt.addNode(90, head); head = bt.addNode(10, head); head = bt.addNode(15, head); head = bt.addNode(25, head); head = bt.addNode(5, head); head = bt.addNode(7, head); head = bt.addNode(-7, head); btd.toDoubleLL(head); btd.print(head); } } ================================================ FILE: src/com/interview/tree/BinaryTreeToSortedLinkList.java ================================================ package com.interview.tree; /** * http://www.careercup.com/question?id=6241652616200192 * Test cases: * 0,1 or more nodes in the tree */ public class BinaryTreeToSortedLinkList { public Node toSortedLinkList(Node root){ if(root == null){ return null; } Node left = toSortedLinkList(root.left); Node right = toSortedLinkList(root.right); root.left = null; root.right = null; root = merge(left,root); return merge(root,right); } private Node merge(Node head1,Node head2){ if(head1 == null){ return head2; } if(head2 == null){ return head1; } if(head1.data <= head2.data){ head1.next = merge(head1.next, head2); return head1; }else{ head2.next = merge(head1,head2.next); return head2; } } private void print(Node root){ while(root != null){ System.out.print(root.data + " "); root = root.next; } } public static void main(String args[]){ int in[] = {-6,0,15,10,3,25,2}; int pre[] = {10,15,-6,0,25,3,2}; ConstructTreeFromInOrderPreOrder ct = new ConstructTreeFromInOrderPreOrder(); Node root = ct.createTree(in, pre); BinaryTreeToSortedLinkList bt = new BinaryTreeToSortedLinkList(); root = bt.toSortedLinkList(root); bt.print(root); } } ================================================ FILE: src/com/interview/tree/BoundaryTraversal.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/boundary-traversal-of-binary-tree/ * Test cases * All left children * All right children * Full tree * Complete tree */ public class BoundaryTraversal { public void traversal(Node root){ //find starting point for right side Node current = root; while(current != null){ if(current.right != null && current.left != null){ current = current.right; break; } current = current.left != null ? current.left : current.right; } printRightSide(current); printLeaves(root); printLeftSide(root); } private void printRightSide(Node root){ if(root == null || (root.left == null && root.right == null)){ return; } System.out.println(root.data); if(root.right != null){ printRightSide(root.right); }else{ printRightSide(root.left); } } private void printLeftSide(Node root){ if(root == null || (root.left == null && root.right == null)){ return; } if(root.left != null){ printLeftSide(root.left); }else{ printRightSide(root.right); } System.out.println(root.data); } private void printLeaves(Node root){ if(root == null){ return; } if(root.left == null && root.right == null){ System.out.println(root.data); } printLeaves(root.right); printLeaves(root.left); } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node head = null; head = bt.addNode(100, head); head = bt.addNode(90, head); head = bt.addNode(10, head); head = bt.addNode(15, head); head = bt.addNode(25, head); head = bt.addNode(5, head); head = bt.addNode(7, head); head = bt.addNode(-7, head); BoundaryTraversal bd = new BoundaryTraversal(); bd.traversal(head); } } ================================================ FILE: src/com/interview/tree/ClosestValueBinaryTree.java ================================================ package com.interview.tree; /** * Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target. * https://leetcode.com/problems/closest-binary-search-tree-value/ */ public class ClosestValueBinaryTree { public int closestValue(Node root, double target) { int r = target > 0 ? Integer.MIN_VALUE : Integer.MAX_VALUE; return closestValueUtil(root, target, r); } private int closestValueUtil(Node root, double target, int result) { if (root == null) { return (int)result; } if (target == root.data) { return root.data; } if (Math.abs(root.data - target) < Math.abs(result - target)) { result = root.data; } if (target < root.data) { return closestValueUtil(root.left, target, result); } else { return closestValueUtil(root.right, target, result); } } } ================================================ FILE: src/com/interview/tree/ConnectNodesAtSameLevel.java ================================================ package com.interview.tree; /** * Date 03/24/2016 * @author Tushar Roy * * Populate next pointer for each node of binary tree. * * Time complexity O(n) * Space complexity O(1) * * https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/ */ public class ConnectNodesAtSameLevel { public void connect(Node root) { if (root == null) { return; } Node firstNode = root; Node prevNode = null; while (firstNode != null) { root = firstNode; firstNode = null; prevNode = null; while (root != null) { if (root.left != null) { if (firstNode == null) { firstNode = root.left; } if (prevNode != null) { prevNode.next = root.left; } prevNode = root.left; } if (root.right != null) { if (firstNode == null) { firstNode = root.right; } if (prevNode != null) { prevNode.next = root.right; } prevNode = root.right; } root = root.next; } } } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node root = null; root = bt.addNode(10, root); root = bt.addNode(15, root); root = bt.addNode(5, root); root = bt.addNode(7, root); root = bt.addNode(19, root); root = bt.addNode(20, root); root = bt.addNode(-1, root); root = bt.addNode(21, root); ConnectNodesAtSameLevel cns = new ConnectNodesAtSameLevel(); cns.connect(root); } } ================================================ FILE: src/com/interview/tree/ConstructAllBinaryTreeFromInorderTraversal.java ================================================ package com.interview.tree; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Date 11/07/2015 * @author Tushar Roy * * Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. * Total number of binary search tree possible is Catalan number. * * https://leetcode.com/problems/unique-binary-search-trees-ii/ */ public class ConstructAllBinaryTreeFromInorderTraversal { public List generateTrees(int n) { if (n == 0) { return Collections.emptyList(); } return construct(1, n); } private List construct(int start, int end) { if (start > end) { return Collections.singletonList(null); } List allTrees = new ArrayList<>(); for (int root = start; root <= end; root++) { //get all subtrees from left and right side. List allLeftSubstrees = construct(start, root - 1); List allRightSubstrees = construct(root + 1, end); //iterate through them in all combination and them connect them to root //and add to allTrees. for (Node left : allLeftSubstrees) { for (Node right : allRightSubstrees) { Node node = Node.newNode(root); node.left = left; node.right = right; allTrees.add(node); } } } return allTrees; } public void printAllTrees(List allTrees) { TreeTraversals tt = new TreeTraversals(); System.out.println("Total number of trees " + allTrees.size()); for(Node node : allTrees) { tt.inOrder(node); System.out.println(); tt.preOrder(node); System.out.print("\n\n"); } } public static void main(String args[]) { ConstructAllBinaryTreeFromInorderTraversal ct = new ConstructAllBinaryTreeFromInorderTraversal(); List allTrees = ct.generateTrees(3); ct.printAllTrees(allTrees); } } ================================================ FILE: src/com/interview/tree/ConstructBSTFromPreOrderArray.java ================================================ package com.interview.tree; class Index{ int index; } /** * http://www.geeksforgeeks.org/construct-bst-from-given-preorder-traversa/ * Test case * empty array * 1,2 or more elements in the array */ public class ConstructBSTFromPreOrderArray { public Node toBST(int preorder[]){ Index index = new Index(); return toBST(preorder,Integer.MIN_VALUE,Integer.MAX_VALUE,index); } //stack based version public Node toBSTIterative(int preorder[]){ return null; } private Node toBST(int preorder[],int min, int max,Index index){ if(index.index >= preorder.length){ return null; } if(preorder[index.index] < min || preorder[index.index] >= max){ return null; } Node node = new Node(); node.data = preorder[index.index]; index.index++; node.left = toBST(preorder,min,node.data, index); node.right = toBST(preorder,node.data,max,index); return node; } public static void main(String args[]){ int preorder[] = {10,5,1,7,40,50}; ConstructBSTFromPreOrderArray poa = new ConstructBSTFromPreOrderArray(); Node root = poa.toBST(preorder); TreeTraversals tt = new TreeTraversals(); tt.preOrder(root); System.out.println(); tt.inOrder(root); } } ================================================ FILE: src/com/interview/tree/ConstructFullTreeFromPreOrderPostOrder.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/full-and-complete-binary-tree-from-given-preorder-and-postorder-traversals/ * Full tree is a tree with all nodes with either 0 or 2 child. Never has 1 child. * Test cases * Empty tree * Tree with big on left side * Tree with big on right side */ public class ConstructFullTreeFromPreOrderPostOrder { public Node constructTree(int preorder[],int postorder[]){ return constructTree(preorder, postorder, 0, postorder.length-2, 0); } private Node constructTree(int preorder[],int postorder[],int low,int high,int index){ if(low > high || index >= preorder.length-1){ Node node = new Node(); node.data = preorder[index]; return node; } Node node = new Node(); node.data = preorder[index]; int i=0; for(i=low; i <= high; i++){ if(preorder[index+1] == postorder[i]){ break; } } node.left = constructTree(preorder, postorder, low, i-1, index+1); node.right = constructTree(preorder, postorder, i+1, high-1, index + i-low+2); return node; } public static void main(String args[]){ ConstructFullTreeFromPreOrderPostOrder cft = new ConstructFullTreeFromPreOrderPostOrder(); int preorder[] = {1,2,3,6,7,8,9}; int postorder[] = {2,6,8,9,7,3,1}; Node root = cft.constructTree(preorder, postorder); TreeTraversals tt = new TreeTraversals(); tt.inOrder(root); tt.preOrder(root); tt.postOrder(root); } } ================================================ FILE: src/com/interview/tree/ConstructTreeFromInOrderPreOrder.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/construct-tree-from-given-inorder-and-preorder-traversal/ * Test cases: * Empty tree * One node tree * All left side tree * All right side tree * Mixed tree * Full tree * complete tree */ public class ConstructTreeFromInOrderPreOrder { private int index = 0; public Node createTree(int inorder[],int preorder[]){ Node result = createTree(inorder,preorder,0,inorder.length-1); index = 0; return result; } private Node createTree(int inorder[],int preorder[], int start, int end){ if(start > end){ return null; } int i; for(i=start; i <= end; i++){ if(preorder[index] == inorder[i]){ break; } } Node node = Node.newNode(preorder[index]); index++; node.left = createTree(inorder,preorder,start,i-1); node.right = createTree(inorder,preorder,i+1,end); return node; } } ================================================ FILE: src/com/interview/tree/ConstructTreeFromLevelOrderInOrder.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/construct-tree-inorder-level-order-traversals/ * Test cases * same length of inorder and level order array * all elements should be same in them * what to do if repetition happens. This logic only works for non repeated values * if inorder and levelorder were represented by string how would you handle multi digits * e.g 1234 we don't know if it is 12 34 or 1 2 3 4 or what. Maybe use brackets * (12)(3)(4) to differentiate between them. */ public class ConstructTreeFromLevelOrderInOrder { public Node constructTree(int inOrder[], int levelOrder[]){ return constructTree(inOrder, levelOrder,0,inOrder.length-1); } private int[] extractArray(int inOrder[], int levelOrder[],int low, int high){ int result[] = new int[high - low + 1]; int p=0; for(int i=1; i < levelOrder.length; i++){ int index = search(inOrder,levelOrder[i],low,high); if(index != -1){ result[p++] = inOrder[index]; } } return result; } private Node constructTree(int inOrder[], int levelOrder[], int low, int high){ if(low > high){ return null; } int lowElement = levelOrder[0]; Node n = Node.newNode(lowElement); int index = search(inOrder,lowElement,low,high); int left[] = extractArray(inOrder,levelOrder,low,index-1); int right[] = extractArray(inOrder,levelOrder,index+1,high); n.left = constructTree(inOrder, left, low, index-1); n.right = constructTree(inOrder, right, index+1, high); return n; } private int search(int input[],int key, int low, int high){ if(low > high){ return -1; } int middle = (low + high)/2; if(input[middle] == key){ return middle; }else if(input[middle] > key){ return search(input,key,low,middle-1); }else{ return search(input,key,middle+1,high); } } public static void main(String args[]){ int inOrder[] = {4,8,10,12,14,20,22}; int levelOrder[] = {20,8,22,4,12,10,14}; ConstructTreeFromLevelOrderInOrder ctf = new ConstructTreeFromLevelOrderInOrder(); Node root = ctf.constructTree(inOrder, levelOrder); LevelOrderTraversal lot = new LevelOrderTraversal(); TreeTraversals tt = new TreeTraversals(); tt.inOrder(root); lot.levelOrder(root); } } ================================================ FILE: src/com/interview/tree/ConstructTreeFromPreOrderTraversalWith0or2Child.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/construct-a-special-tree-from-given-preorder-traversal/ * Test cases: * Length of pre and val is not same * val contains values other than N or L */ class PreIndex{ int index; } public class ConstructTreeFromPreOrderTraversalWith0or2Child { public Node createTree(int pre[],char val[]){ PreIndex pi = new PreIndex(); pi.index = 0; return createTree(pre, val,pi); } private Node createTree(int pre[],char val[], PreIndex ind){ if(ind.index >= pre.length){ return null; } Node root = Node.newNode(pre[ind.index]); if(val[ind.index] == 'L'){ ind.index++; }else{ ind.index++; root.left = createTree(pre,val,ind); root.right = createTree(pre,val,ind); } return root; } public static void main(String args[]){ int pre[] = {10,20,30,40,50,60,70,80,90}; char val[] = {'N','N','N','L','L','L','N','L','L'}; ConstructTreeFromPreOrderTraversalWith0or2Child tfp = new ConstructTreeFromPreOrderTraversalWith0or2Child(); Node root = tfp.createTree(pre, val); TreeTraversals tt = new TreeTraversals(); tt.preOrder(root); System.out.println(); tt.inOrder(root); } } ================================================ FILE: src/com/interview/tree/ContructTreeFromInOrderTraversalRootGreaterThanChild.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/construct-binary-tree-from-inorder-traversal/ * Given inorder traversal of binary tree where every node is greater than * its left and right child. * Test cases: * One two or more nodes in the tree */ public class ContructTreeFromInOrderTraversalRootGreaterThanChild { public Node createTree(int inorder[]){ return createTree(inorder,0,inorder.length-1); } private Node createTree(int inorder[],int low,int high) { if(low > high){ return null; } int i; int maxIndex = low; for(i=low ; i <= high; i++){ if(inorder[maxIndex] > inorder[i]){ maxIndex = i; } } Node root = Node.newNode(inorder[maxIndex]); root.left = createTree(inorder,low,maxIndex-1); root.right = createTree(inorder,maxIndex+1,high); return root; } public static void main(String args[]){ int inorder[] = {9,15,25,6,18,-1,3,-3}; ContructTreeFromInOrderTraversalRootGreaterThanChild tf = new ContructTreeFromInOrderTraversalRootGreaterThanChild(); Node root = tf.createTree(inorder); TreeTraversals tt = new TreeTraversals(); tt.inOrder(root); } } ================================================ FILE: src/com/interview/tree/ContructTreeFromInorderPostOrder.java ================================================ package com.interview.tree; /** * Given inorder and postorder traversal of a tree, construct the binary tree. * * https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/ */ public class ContructTreeFromInorderPostOrder { public Node buildTree(int[] inorder, int[] postorder) { return buildTree(inorder, postorder, 0, inorder.length - 1, postorder.length - 1); } public Node buildTree(int[] inorder, int[] postorder, int start, int end, int index) { if (start > end) { return null; } int i; for (i = start; i <= end; i++) { if (postorder[index] == inorder[i]) { break; } } Node tn = Node.newNode(postorder[index]); tn.left = buildTree(inorder, postorder, start, i - 1, index - (end - i + 1)); tn.right = buildTree(inorder, postorder, i + 1, end, index - 1); return tn; } } ================================================ FILE: src/com/interview/tree/CountNodesCompleteTree.java ================================================ package com.interview.tree; /** * Date 10/06/2016 * @author Tushar Roy * * Given a complete binary tree, count the number of nodes. * * Time complexity O(log(n) ^ 2) * * Reference * https://leetcode.com/problems/count-complete-tree-nodes/ */ public class CountNodesCompleteTree { public int countNodes(Node root) { if (root == null) { return 0; } int lh = leftHeight(root.left); int rh1 = rightHeight(root.left); int rh = rightHeight(root.right); if (lh == rh) { return (1< 1){ if(height(root.left.left) >= height(root.left.right)){ root = rightRotate(root); }else{ root.left = leftRotate(root.left); root = rightRotate(root); } }else if(height(root.right) - height(root.left) > 1){ if(height(root.right.right) >= height(root.right.left)){ root = leftRotate(root); }else{ root.right = rightRotate(root.right); root = leftRotate(root); } } else{ root.height = setHeight(root); root.size = setSize(root); } return root; } public int[] count(int input[]){ int count[] = new int[input.length]; Node root = null; for(int i=input.length-1; i >= 0; i--){ root = insert(root,input[i],count,i,0); } return count; } public static void main(String args[]){ int input[] = {12, 1, 2, 3, 0, 11, 4}; CountNumberOfSmallerElementOnRight cns = new CountNumberOfSmallerElementOnRight(); int count[] = cns.count(input); for(int c : count){ System.out.print(c + " "); } System.out.println(); int input1[] = {5, 4, 3, 2, 1}; int count1[] = cns.count(input1); for(int c : count1){ System.out.print(c + " "); } System.out.println(); int input2[] = {1,2,3,4,5}; int count2[] = cns.count(input2); for(int c : count2){ System.out.print(c + " "); } } } ================================================ FILE: src/com/interview/tree/CountPathSum.java ================================================ package com.interview.tree; import java.util.HashMap; import java.util.Map; /** * https://leetcode.com/problems/path-sum-iii/description/ */ public class CountPathSum { public int pathSum(Node root, int sum) { Map map = new HashMap<>(); map.put(0, 1); return countPathSum(root, sum, map, 0); } private int countPathSum(Node root, int sum, Map map, int prefixSum) { if (root == null) { return 0; } prefixSum += root.data; int count = map.getOrDefault(prefixSum - sum,0); map.put(prefixSum, map.getOrDefault(prefixSum, 0) + 1); count += countPathSum(root.left, sum, map, prefixSum) + countPathSum(root.right, sum, map, prefixSum); map.put(prefixSum, map.getOrDefault(prefixSum, 1) - 1); return count; } } ================================================ FILE: src/com/interview/tree/CountUnivalueTree.java ================================================ package com.interview.tree; /** * Date 10/07/2016 * @author Tushar Roy * * Given a binary tree, count the number of uni-value subtrees. * A Uni-value subtree means all nodes of the subtree have the same value. * * https://leetcode.com/problems/count-univalue-subtrees/ */ public class CountUnivalueTree { private int count = 0; public int countUnivalSubtrees(Node root) { countUnivalSubtreesUtil(root, 0); return count; } private int countUnivalSubtreesUtil(Node root, int val) { if (root == null) { return val; } int left = countUnivalSubtreesUtil(root.left, root.data); int right = countUnivalSubtreesUtil(root.right, root.data); if (left == right && left == root.data) { count++; return root.data; } else { return Integer.MAX_VALUE; } } } ================================================ FILE: src/com/interview/tree/CousinNodes.java ================================================ package com.interview.tree; import java.util.Deque; import java.util.LinkedList; import java.util.Queue; /** * http://www.geeksforgeeks.org/check-two-nodes-cousins-binary-tree/ Assumption * that both a and b are unique in tree. Test cases: Empty tree Tree with only * root Tree and input with a and b as cousin node Tree and input with a and b * not cousin node Tree with input a and b being siblings(not cousin) */ public class CousinNodes { /** * Little more efficient than other method since this guy does not need * another look up to see if parent is same for found nodes. */ public boolean areCousins1(Node root, int data1, int data2) { Queue queue = new LinkedList<>(); queue.add(root); int tempLevel = 1; int level = 0; boolean found1 = false; boolean found2 = false; Node parent1 = null; Node parent2 = null; while (!queue.isEmpty()) { while (tempLevel > 0) { root = queue.poll(); if (root.left != null) { if (root.left.data == data1) { found1 = true; parent1 = root; } else if (root.left.data == data2) { found2 = true; parent2 = root; } else { queue.add(root.left); level++; } } if (root.right != null) { if (root.right.data == data1) { found1 = true; parent1 = root; } else if (root.right.data == data2) { found2 = true; parent2 = root; } else { queue.add(root.right); level++; } } tempLevel--; } if (found1 && found2 && parent1 != parent2) { return true; } else if (found1 || found2) { return false; } tempLevel = level; level = 0; } return false; } public boolean areCousins(Node root, int a, int b) { Deque queue = new LinkedList(); queue.offerFirst(root); int levelSize = 1; int tempLevelSize = 1; boolean foundFirst = false; while (!queue.isEmpty()) { levelSize = 0; while (tempLevelSize > 0) { Node node = queue.pollLast(); // this is to make sure a and b are not siblings of each other // if they are return false since they cant be cousins if (checkSameParent(node, a, b)) { return false; } if (node.data == a || node.data == b) { if (foundFirst) { return true; } foundFirst = true; } if (node.left != null) { queue.offerFirst(node.left); levelSize++; } if (node.right != null) { queue.offerFirst(node.right); levelSize++; } tempLevelSize--; } if (foundFirst) { return false; } tempLevelSize = levelSize; } return false; } private boolean checkSameParent(Node root, int a, int b) { if (root.left != null && root.right != null) { if ((root.left.data == a || root.left.data == b) && (root.right.data == a || root.right.data == b)) { return true; } } return false; } public static void main(String args[]) { BinaryTree bt = new BinaryTree(); Node head = null; head = bt.addNode(10, head); head = bt.addNode(15, head); head = bt.addNode(5, head); head = bt.addNode(7, head); head = bt.addNode(19, head); head = bt.addNode(20, head); head = bt.addNode(-1, head); head = bt.addNode(21, head); head = bt.addNode(-6, head); CousinNodes cn = new CousinNodes(); System.out.println(cn.areCousins(head, 10, 19)); System.out.println(cn.areCousins(head, 19, 7)); System.out.println(cn.areCousins(head, 19, -1)); System.out.println(cn.areCousins(head, 19, -6)); System.out.println(cn.areCousins(head, -1, 7)); System.out.println(cn.areCousins(head, 7, -1)); } } ================================================ FILE: src/com/interview/tree/DegenerateBinaryTreeToSortedLL.java ================================================ package com.interview.tree; /** * Date 03/16/2015 * @author tusroy * * Given a binary tree(not BST) convert it into sorted linklist. * e.g 10 * 11 15 * 8 9 16 13 * 7 * * should become 7->8->9->10->11->13->15->16 * * Solution * Idea is that at every root, get the sorted linklist from left and right and merge them * along with root and return left most element in this merged linklist to upper level call. * * Test cases * 1) Null root * 2) One node root * 3) BST * 4) Reverse BST * 5) All on left side of root * * Reference * http://www.careercup.com/question?id=6241652616200192 * */ public class DegenerateBinaryTreeToSortedLL { public Node degenerate(Node root){ if(root == null){ return null; } Node left = root.left; Node right = root.right; root.left = null; root.right = null; left = degenerate(left); right = degenerate(right); left = merge(left, root); return merge(left, right); } private Node merge(Node root1, Node root2){ if(root1 == null){ return root2; } if(root2 == null){ return root1; } if(root1.data <= root2.data){ root1.right = merge(root1.right, root2); return root1; }else{ root2.right = merge(root1, root2.right); return root2; } } private void printList(Node root){ while(root != null){ System.out.print(root.data + " "); root = root.right; } } public static void main(String args[]){ ConstructTreeFromInOrderPreOrder ctf = new ConstructTreeFromInOrderPreOrder(); int inorder[] = {8, 11, 9, 10, 16, 15, 13, 7}; int preorder[] = {10, 11, 8, 9, 15, 16, 13, 7}; Node root = ctf.createTree(inorder, preorder); DegenerateBinaryTreeToSortedLL dbt = new DegenerateBinaryTreeToSortedLL(); root = dbt.degenerate(root); dbt.printList(root); } } ================================================ FILE: src/com/interview/tree/DiameterOfTree.java ================================================ package com.interview.tree; class Height{ int height; } /** * http://www.geeksforgeeks.org/diameter-of-a-binary-tree/ * Test cases * All left nodes * All right nodes */ public class DiameterOfTree { public int diameter(Node root){ Height height = new Height(); return diameter(root,height); } private int diameter(Node root, Height height){ if(root == null){ return 0; } Height leftHeight = new Height(); Height rightHeight = new Height(); int dial = diameter(root.left,leftHeight); int diar = diameter(root.right,rightHeight); height.height = Math.max(leftHeight.height, rightHeight.height) + 1; return Math.max(Math.max(dial, diar),(1 + leftHeight.height + rightHeight.height)); } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node head = null; head = bt.addNode(10, head); head = bt.addNode(15, head); head = bt.addNode(5, head); head = bt.addNode(7, head); head = bt.addNode(19, head); head = bt.addNode(20, head); head = bt.addNode(-1, head); head = bt.addNode(21, head); head = bt.addNode(11, head); head = bt.addNode(12, head); head = bt.addNode(13, head); head = bt.addNode(14, head); DiameterOfTree dt = new DiameterOfTree(); System.out.println(dt.diameter(head)); } } ================================================ FILE: src/com/interview/tree/FenwickTree.java ================================================ package com.interview.tree; /** * Date 04/27/2015 * @author tusroy * * Write a program to implement fenwick or binary indexed tree * * A Fenwick tree or binary indexed tree is a data structure providing efficient methods * for calculation and manipulation of the prefix sums of a table of values. * * Space complexity for fenwick tree is O(n) * Time complexity to create fenwick tree is O(nlogn) * Time complexity to update value is O(logn) * Time complexity to get prefix sum is O(logn) * * References * http://www.geeksforgeeks.org/binary-indexed-tree-or-fenwick-tree-2/ * https://www.topcoder.com/community/data-science/data-science-tutorials/binary-indexed-trees/ * http://en.wikipedia.org/wiki/Fenwick_tree */ public class FenwickTree { /** * Start from index+1 if you updating index in original array. Keep adding this value * for next node till you reach outside range of tree */ public void updateBinaryIndexedTree(int binaryIndexedTree[], int val, int index){ while(index < binaryIndexedTree.length){ binaryIndexedTree[index] += val; index = getNext(index); } } /** * Start from index+1 if you want prefix sum 0 to index. Keep adding value * till you reach 0 */ public int getSum(int binaryIndexedTree[], int index){ index = index + 1; int sum = 0; while(index > 0){ sum += binaryIndexedTree[index]; index = getParent(index); } return sum; } /** * Creating tree is like updating Fenwick tree for every value in array */ public int[] createTree(int input[]){ int binaryIndexedTree[] = new int[input.length+1]; for(int i=1; i <= input.length; i++){ updateBinaryIndexedTree(binaryIndexedTree, input[i-1], i); } return binaryIndexedTree; } /** * To get parent * 1) 2's complement to get minus of index * 2) AND this with index * 3) Subtract that from index */ private int getParent(int index){ return index - (index & -index); } /** * To get next * 1) 2's complement of get minus of index * 2) AND this with index * 3) Add it to index */ private int getNext(int index){ return index + (index & -index); } public static void main(String args[]){ int input[] = {1,2,3,4,5,6,7}; FenwickTree ft = new FenwickTree(); int binaryIndexedTree[] = ft.createTree(input); assert 1 == ft.getSum(binaryIndexedTree, 0); assert 3 == ft.getSum(binaryIndexedTree, 1); assert 6 == ft.getSum(binaryIndexedTree, 2); assert 10 == ft.getSum(binaryIndexedTree, 3); assert 15 == ft.getSum(binaryIndexedTree, 4); assert 21 == ft.getSum(binaryIndexedTree, 5); assert 28 == ft.getSum(binaryIndexedTree, 6); } } ================================================ FILE: src/com/interview/tree/FlattenLinkListToBinaryTreePreorder.java ================================================ package com.interview.tree; import java.util.Stack; /** * Date 10/06/2016 * @author Tushar Roy * * Given a binary tree, flatten it to a linked list in-place in preorder traversal. * * Time complexity O(n) * * https://leetcode.com/problems/flatten-binary-tree-to-linked-list/ */ public class FlattenLinkListToBinaryTreePreorder { public void flatten(Node root) { if (root == null) { return; } Stack stack = new Stack<>(); stack.push(root); Node prev = null; while (!stack.isEmpty()) { Node node = stack.pop(); if (prev != null) { prev.right = node; } prev = node; if (node.right != null) { stack.push(node.right); } if (node.left != null) { stack.push(node.left); } node.left = null; node.right = null; } } public void flatten1(Node root) { if(root==null) return; flatten(root.left); flatten(root.right); Node left = root.left; Node right = root.right; root.left = null; root.right = left; while(root.right!=null) root = root.right; root.right = right; } } ================================================ FILE: src/com/interview/tree/HeightBalanced.java ================================================ package com.interview.tree; /** * Date 10/06/2016 * @author Tushar Roy * * Given a binary tree, determine if it is height-balanced. * * Time complexity O(logn) * * Reference * https://leetcode.com/problems/balanced-binary-tree/ */ public class HeightBalanced { public boolean isBalanced(Node root) { return isBalancedUtil(root) >= 0; } private int isBalancedUtil(Node root) { if (root == null) { return 0; } int left = isBalancedUtil(root.left); if (left < 0) { return -1; } int right = isBalancedUtil(root.right); if (right < 0) { return -1; } int diff = Math.abs(left - right); return diff <= 1 ? (Math.max(left, right) + 1) : -1; } } ================================================ FILE: src/com/interview/tree/HuffmanEncoding.java ================================================ package com.interview.tree; import java.util.HashMap; import java.util.Map; import java.util.PriorityQueue; import java.util.Comparator; /** * http://www.geeksforgeeks.org/greedy-algorithms-set-3-huffman-coding/ * http://www.geeksforgeeks.org/greedy-algorithms-set-3-huffman-coding-set-2/ */ class HuffmanNode{ int freq; char input; HuffmanNode left; HuffmanNode right; } class HuffmanNodeComparator implements Comparator{ @Override public int compare(HuffmanNode o1, HuffmanNode o2) { if(o1.freq < o2.freq){ return -1; }else{ return 1; } } } public class HuffmanEncoding { public Map huffman(char[] input, int freq[]){ HuffmanNodeComparator comparator = new HuffmanNodeComparator(); PriorityQueue heap = new PriorityQueue(input.length,comparator); for(int i=0; i < input.length; i++){ HuffmanNode node = new HuffmanNode(); node.freq = freq[i]; node.input = input[i]; heap.offer(node); } while(heap.size() > 1){ HuffmanNode node1 = heap.poll(); HuffmanNode node2 = heap.poll(); HuffmanNode node = new HuffmanNode(); node.left = node1; node.right = node2; node.freq = node1.freq + node2.freq; heap.offer(node); } Map map = new HashMap(); StringBuffer buff = new StringBuffer(); createCode(heap.poll(),map,buff); return map; } public void createCode(HuffmanNode node,Map map,StringBuffer buff){ if(node == null){ return; } if(node.left == null && node.right == null){ map.put(node.input,buff.toString()); return; } buff.append("0"); createCode(node.left,map,buff); buff.deleteCharAt(buff.length()-1); buff.append("1"); createCode(node.right,map,buff); buff.deleteCharAt(buff.length()-1); } public static void main(String args[]){ HuffmanEncoding he = new HuffmanEncoding(); char input[] = {'a','b','c','d','e','f'}; int freq[] = {5,9,12,13,16,45}; Map code = he.huffman(input, freq); System.out.println(code); } } ================================================ FILE: src/com/interview/tree/IdenticalTrees.java ================================================ package com.interview.tree; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; /** * http://www.geeksforgeeks.org/check-for-identical-bsts-without-building-the-trees/ * Test cases * Both array should be same size and have exact same elements and first element should be same */ public class IdenticalTrees { private class BigSmall{ int big; int small; } public boolean sameBST(int tree1[], int tree2[]){ return sameBST(tree1,tree2,Integer.MIN_VALUE,Integer.MAX_VALUE,0); } private boolean sameBST(int tree1[],int tree2[],int min,int max,int index){ if(index ==tree1.length){ return true; } int i=0; for(i=0; i < tree2.length; i++){ if(tree2[i] == tree1[index]){ break; } } BigSmall bs1 = nextBigSmall(tree1,index,min,max); BigSmall bs2 = nextBigSmall(tree2,i,min,max); boolean r1= tree1[bs1.big] == tree2[bs2.big] && tree1[bs1.small] == tree2[bs2.small] ; if(r1 == false){ return false; } boolean r2 = true,r3 =true; if(bs1.small != 0){ r2 = sameBST(tree1,tree2,min,tree1[index],bs1.small); } if(bs1.big != 0){ r3 = sameBST(tree1,tree2,tree1[index],max,bs1.big); } return r2 && r3; } private BigSmall nextBigSmall(int[] tree,int index,int min,int max){ BigSmall bs = new BigSmall(); boolean seenBig = false, seenSmall = false; for(int i=index+1; i < tree.length && (!seenBig || !seenSmall); i++){ if(tree[i] > max || tree[i] < min){ continue; } if(!seenBig && tree[i] > tree[index]){ bs.big = i; seenBig = true; } if(!seenSmall && tree[i] < tree[index]){ bs.small = i; seenSmall = true; } } return bs; } /** * Little simpler version of above implementation. Uses more space but atleast its easy to understand. * All it does is makes 2 list one of larger and one of smaller element than root and then passes * them into left and right sides * @param arr1 * @param arr2 * @return */ public boolean sameBST1(int arr1[], int arr2[]){ List list1 = new ArrayList<>(); for(int i : arr1){ list1.add(i); } List list2 = new ArrayList<>(); for(int i : arr2){ list2.add(i); } return sameBST1(list1, list2); } /** * It might not work for duplicate elements in array. For that you have to store * both index and actual value to differentiate somehow. */ private boolean sameBST1(List arr1, List arr2){ if(arr1.size() == 0 && arr2.size() == 0){ return true; } if(arr1.size() == 0 || arr2.size() == 0){ return false; } if(arr1.get(0) != arr2.get(0)){ return false; } List smaller1 = new ArrayList(); List larger1= new ArrayList(); boolean first = true; for(Integer i : arr1){ if(first){ first = false; continue; } if(i <= arr1.get(0)){ smaller1.add(i); }else{ larger1.add(i); } } first = true; List smaller2 = new ArrayList(); List larger2= new ArrayList(); for(Integer i : arr2){ if(first){ first = false; continue; } if(i <= arr2.get(0)){ smaller2.add(i); }else{ larger2.add(i); } } boolean r = compare(smaller1, smaller2) && compare(larger1, larger2); if(!r){ return false; } return sameBST1(smaller1, smaller2) && sameBST1(larger1, larger2); } private boolean compare(List l1, List l2){ Set s = new HashSet(); for(Integer i : l1){ s.add(i); } for(Integer i : l2){ if(!s.contains(i)){ return false; } } return true; } public static void main(String args[]){ int tree1[] = {3,-6,-2,11,9,-10,-1,15,10}; int tree2[] = {3,11,9,15,-6,10,-2,-1,-10}; IdenticalTrees it = new IdenticalTrees(); System.out.println(it.sameBST(tree1, tree2)); System.out.println(it.sameBST1(tree1, tree2)); } } ================================================ FILE: src/com/interview/tree/InorderSuccessor.java ================================================ package com.interview.tree; /** * Date 03/27/2016 * @author Tushar Roy * * Given a binary search tree and a node in it, find the in-order successor of that node in the BST. * * Time complexity O(h) * Space complexity O(h) * * https://leetcode.com/problems/inorder-successor-in-bst/ */ public class InorderSuccessor { public Node inorderSuccessor(Node root, Node p) { if (p.right != null) { p = p.right; while (p.left != null) { p = p.left; } return p; } else { return succ(root, p.data); } } private Node succ(Node root, int data) { if (root.data == data) { return null; } if (root.data < data) { return succ(root.right, data); } else { Node s = succ(root.left, data); return s == null ? root : s; } } } ================================================ FILE: src/com/interview/tree/IntervalTree.java ================================================ package com.interview.tree; /** * Date 11/07/2015 * @author Tushar Roy * * Write class for interval tree * Keep a max at every node which is max of that subtree. * This max is used to decide which direction to move when checking * for overlap. When an interval's high is less than max of left side go * in that direciton otherwise go in other direction. */ class InternalNode { int low; int high; int max; InternalNode left; InternalNode right; @Override public String toString() { return "InternalNode{" + "max=" + max + ", low=" + low + ", high=" + high + '}'; } } public class IntervalTree { public InternalNode insert(InternalNode root, int low, int high) { if(root == null) { InternalNode node = new InternalNode(); node.low = low; node.high = high; node.max = high; return node; } if(low < root.low) { root.left = insert(root.left, low, high); } else { root.right = insert(root.right, low, high); } root.max = Math.max(root.high, high); return root; } public InternalNode isOverlap(InternalNode root, int low, int high) { if(root == null) { return null; } if(root.high >= low && root.low <= high) { return root; } if(root.left != null && root.left.max > low) { return isOverlap(root.left, low, high); } else { return isOverlap(root.right, low, high); } } public static void main(String args[]) { IntervalTree it = new IntervalTree(); InternalNode root = null; root = it.insert(root, 10, 15); root = it.insert(root, 11, 13); root = it.insert(root, 18, 21); root = it.insert(root, 20, 25); root = it.insert(root, 0, 7); System.out.println(it.isOverlap(root, 8, 9)); System.out.println(it.isOverlap(root, 17, 17)); System.out.println(it.isOverlap(root, 21, 22)); System.out.println(it.isOverlap(root, 21, 22)); System.out.println(it.isOverlap(root, 12, 18)); System.out.println(it.isOverlap(root, 24, 26)); } } ================================================ FILE: src/com/interview/tree/IsBST.java ================================================ package com.interview.tree; import java.util.Deque; import java.util.LinkedList; /** * Date 04/11/2015 * @author tusroy * * Youtube link - https://youtu.be/MILxfAbIhrE * * Given a binary tree, return true if it is binary search tree else return false. * * Solution * Keep min, max for every recursion. Initial min and max is very small and very larger * number. Check if root.data is in this range. When you go left pass min and root.data and * for right pass root.data and max. * * Time complexity is O(n) since we are looking at all nodes. * * Test cases: * Null tree * 1 or 2 nodes tree * Binary tree which is actually BST * Binary tree which is not a BST */ public class IsBST { public boolean isBST(Node root){ return isBST(root, Integer.MIN_VALUE, Integer.MAX_VALUE); } private boolean isBST(Node root, int min, int max){ if(root == null){ return true; } if(root.data <= min || root.data > max){ return false; } return isBST(root.left, min, root.data) && isBST(root.right, root.data, max); } public boolean isBSTIterative(Node root) { if (root == null) { return true; } Deque stack = new LinkedList<>(); Node node = root; int prev = Integer.MIN_VALUE; int current; while ( true ) { if (node != null) { stack.addFirst(node); node = node.left; } else { if (stack.isEmpty()) { break; } node = stack.pollFirst(); current = node.data; if (current < prev) { return false; } prev = current; node = node.right; } } return true; } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node root = null; root = bt.addNode(10, root); root = bt.addNode(15, root); root = bt.addNode(-10, root); root = bt.addNode(17, root); root = bt.addNode(20, root); root = bt.addNode(0, root); IsBST isBST = new IsBST(); assert isBST.isBST(root); assert isBST.isBSTIterative(root); } } ================================================ FILE: src/com/interview/tree/IsCompleteBinaryTree.java ================================================ package com.interview.tree; import java.util.LinkedList; import java.util.Queue; /** * http://www.geeksforgeeks.org/check-if-a-given-binary-tree-is-complete-tree-or-not/ * Test cases: * A node with only right child * A node with only left child * A node with both left and right child */ public class IsCompleteBinaryTree { public boolean isComplete(Node root){ Queue queue = new LinkedList(); queue.offer(root); boolean foundFirstNonFull = false; while(!queue.isEmpty()){ root = queue.poll(); if(foundFirstNonFull){ if(root.left != null || root.right != null){ return false; } continue; } if(root.left != null && root.right != null){ queue.offer(root.left); queue.offer(root.right); }else if(root.left != null){ queue.offer(root.left); foundFirstNonFull = true; }else if(root.right != null){ return false; }else{ foundFirstNonFull = true; } } return true; } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node head = null; head = bt.addNode(3, head); head = bt.addNode(-6, head); head = bt.addNode(7, head); head = bt.addNode(-10, head); head = bt.addNode(-15, head); head = bt.addNode(-4, head); head = bt.addNode(4, head); head = bt.addNode(11, head); head = bt.addNode(-9, head); IsCompleteBinaryTree icbt = new IsCompleteBinaryTree(); System.out.println(icbt.isComplete(head)); } } ================================================ FILE: src/com/interview/tree/IsPreOrderArrayBST.java ================================================ package com.interview.tree; import java.util.Deque; import java.util.LinkedList; /** * Check if given pre array sequence will create a binary search tree or not. * * Idea is to keep minimal acceptable value. Any element in pre array should never be less * than minimal acceptable value. Values are popped from stack till they are less than pre[i] * Last popped value becomes new minimally acceptable vaue. * * It does not work for duplicates * * Time complexity - O(n) * https://leetcode.com/problems/verify-preorder-sequence-in-binary-search-tree/ * Reference - http://www.geeksforgeeks.org/check-if-a-given-array-can-represent-preorder-traversal-of-binary-search-tree/ */ public class IsPreOrderArrayBST { public boolean verifyPreorder(int pre[]) { Deque deque = new LinkedList<>(); int minAcceptable = Integer.MIN_VALUE; deque.addFirst(pre[0]); for(int i = 1; i < pre.length; i++) { if(pre[i] < minAcceptable) { return false; } while(!deque.isEmpty() && deque.peekFirst() < pre[i]) { minAcceptable = deque.pollFirst(); } deque.addFirst(pre[i]); } return true; } public boolean verifyPreorderConstantSpace(int[] preorder) { int start = 0; int min = Integer.MIN_VALUE; for (int i = 1; i < preorder.length; i++) { if (preorder[i] < min) { return false; } if (preorder[i] > preorder[i - 1]) { int index = binarySearch(preorder, start, i - 1, preorder[i]); min = preorder[index]; start = i; } } return true; } int binarySearch(int[] preorder, int start, int end, int val) { int s = start; int e = end; while (s <= e) { int middle = (s + e)/2; if (preorder[middle] < val && (start == middle || preorder[middle - 1] > val)) { return middle; } else if (preorder[middle] < val) { e = middle - 1; } else { s = middle + 1; } } return -1; } public static void main(String args[]) { IsPreOrderArrayBST isb = new IsPreOrderArrayBST(); int[] input = {10, 3, -1, 4, 13, 11, 12, 10}; System.out.println(isb.verifyPreorder(input)); System.out.println(isb.verifyPreorderConstantSpace(input)); } } ================================================ FILE: src/com/interview/tree/KClosestValueInBinaryTree.java ================================================ package com.interview.tree; import java.util.ArrayList; import java.util.List; import java.util.Stack; /** * Date 10/08/2016 * @author Tushar Roy * * Given a non-empty binary search tree and a target value, find k values in the BST that are closest to the target. * * Time complexity O(log(n) + k) * * https://leetcode.com/problems/closest-binary-search-tree-value-ii/ */ public class KClosestValueInBinaryTree { public List closestKValues(Node root, double target, int k) { if (root == null || k == 0) { return new ArrayList<>(); } Stack predecessor = new Stack(); Stack successor = new Stack(); double closestDiff = Double.MAX_VALUE; Node closestDiffNode = null; while (root != null) { predecessor.push(root); successor.push(root); if (Math.abs(target - root.data) < closestDiff) { closestDiff = Math.abs(target - root.data); closestDiffNode = root; } if (root.data == target) { break; } else if (target > root.data) { root = root.right; } else { root = root.left; } } while (predecessor.peek() != closestDiffNode) { predecessor.pop(); successor.pop(); } predecessor.pop(); successor.pop(); List result = new ArrayList<>(); result.add(closestDiffNode.data); Node prec = closestDiffNode; Node succ = closestDiffNode; k--; prec = predecessor(predecessor, prec); succ = successor(successor, succ); while (k > 0) { if (succ == null || (prec != null && Math.abs(target - prec.data) < Math.abs(target - succ.data))) { result.add(prec.data); prec = predecessor(predecessor, prec); } else { result.add(succ.data); succ = successor(successor, succ); } k--; } return result; } private Node predecessor(Stack stack, Node current) { if (current == null) { return null; } if (current.left != null) { stack.push(current); current = current.left; while (current.right != null) { stack.push(current); current = current.right; } return current; } else { while (!stack.isEmpty() && stack.peek().left == current) { current = stack.pop(); } if (stack.isEmpty()) { return null; } else { return stack.pop(); } } } private Node successor(Stack stack, Node current) { if (current == null) { return null; } if (current.right != null) { stack.push(current); current = current.right; while (current.left != null) { stack.push(current); current = current.left; } return current; } else { while (!stack.isEmpty() && stack.peek().right == current) { current = stack.pop(); } if (stack.isEmpty()) { return null; } else { return stack.pop(); } } } } ================================================ FILE: src/com/interview/tree/LargestBSTInBinaryTree.java ================================================ package com.interview.tree; /** * Date 07/20/2014 * @author tusroy * * Video link - https://youtu.be/4fiDs7CCxkc * * Given a binary tree, find size of largest binary search subtree in this * binary tree. * * Traverse tree in post order fashion. Left and right nodes return 4 piece * of information to root which isBST, size of max BST, min and max in those * subtree. * If both left and right subtree are BST and this node data is greater than max * of left and less than min of right then it returns to above level left size + * right size + 1 and new min will be min of left side and new max will be max of * right side. * * References: * http://www.geeksforgeeks.org/find-the-largest-subtree-in-a-tree-that-is-also-a-bst/ * https://leetcode.com/problems/largest-bst-subtree/ */ public class LargestBSTInBinaryTree { public int largestBST(Node root){ MinMax m = largest(root); return m.size; } private MinMax largest(Node root){ //if root is null return min as Integer.MAX and max as Integer.MIN if(root == null){ return new MinMax(); } //postorder traversal of tree. First visit left and right then //use information of left and right to calculate largest BST. MinMax leftMinMax = largest(root.left); MinMax rightMinMax =largest(root.right); MinMax m = new MinMax(); //if either of left or right subtree says its not BST or the data //of this node is not greater/equal than max of left and less than min of right //then subtree with this node as root will not be BST. //Return false and max size of left and right subtree to parent if(leftMinMax.isBST == false || rightMinMax.isBST == false || (leftMinMax.max > root.data || rightMinMax.min <= root.data)){ m.isBST = false; m.size = Math.max(leftMinMax.size, rightMinMax.size); return m; } //if we reach this point means subtree with this node as root is BST. //Set isBST as true. Then set size as size of left + size of right + 1. //Set min and max to be returned to parent. m.isBST = true; m.size = leftMinMax.size + rightMinMax.size + 1; //if root.left is null then set root.data as min else //take min of left side as min m.min = root.left != null ? leftMinMax.min : root.data; //if root.right is null then set root.data as max else //take max of right side as max. m.max = root.right != null ? rightMinMax.max : root.data; return m; } public static void main(String args[]){ LargestBSTInBinaryTree lbi = new LargestBSTInBinaryTree(); ConstructTreeFromInOrderPreOrder ctf = new ConstructTreeFromInOrderPreOrder(); //this is just to create a binary tree. int inorder[] = {-7,-6,-5,-4,-3,-2,1,2,3,16,6,10,11,12,14}; int preorder[] = {3,-2,-3,-4,-5,-6,-7,1,2,16,10,6,12,11,14}; Node root = ctf.createTree(inorder, preorder); int largestBSTSize = lbi.largestBST(root); System.out.println("Size of largest BST is " + largestBSTSize); assert largestBSTSize == 8; } } /** * Object of this class holds information which child passes back * to parent node. */ class MinMax{ int min; int max; boolean isBST; int size ; MinMax(){ min = Integer.MAX_VALUE; max = Integer.MIN_VALUE; isBST = true; size = 0; } } ================================================ FILE: src/com/interview/tree/LargestIndependentSetInTree.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/largest-independent-set-problem/ */ public class LargestIndependentSetInTree { public int largestSet(Node root){ if(root == null){ return 0; } if(root.lis != -1){ return root.lis; } int excl = 0; int left_excl = 0; if(root.left != null){ left_excl = largestSet(root.left.left) + largestSet(root.left.right); excl += largestSet(root.left); } int right_excl = 0; if(root.right != null){ right_excl = largestSet(root.right.left) + largestSet(root.right.right); excl += largestSet(root.right); } int incl = left_excl + right_excl + root.data; root.lis = incl; return incl > excl ? incl : excl; } public static void main(String args[]){ int inorder[] = {4,13,1,7,6,3,19}; int preorder[] = {13,4,6,7,1,3,19}; ConstructTreeFromInOrderPreOrder ctf = new ConstructTreeFromInOrderPreOrder(); Node root = ctf.createTree(inorder, preorder); LargestIndependentSetInTree lis = new LargestIndependentSetInTree(); System.out.println(lis.largestSet(root)); } } ================================================ FILE: src/com/interview/tree/LeavesOfBinaryTree.java ================================================ package com.interview.tree; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Date 10/08/2016 * @author Tushar Roy * * Given a binary tree, collect a tree's nodes as if you were doing this: Collect and remove all leaves, repeat until the tree is empty. * * Time complexity O(n^2) for unbalanced tree. * * https://leetcode.com/problems/find-leaves-of-binary-tree/ */ public class LeavesOfBinaryTree { public List> findLeaves(Node root) { if (root == null) { return Collections.EMPTY_LIST; } List> result = new ArrayList<>(); List leaves = new ArrayList<>(); while (stripLeaves(root, leaves) != null) { result.add(leaves); leaves = new ArrayList<>(); } result.add(leaves); return result; } Node stripLeaves(Node root, List leaves) { if (root == null) { return null; } if (root.left == null && root.right == null) { leaves.add(root.data); return null; } root.left = stripLeaves(root.left, leaves); root.right = stripLeaves(root.right, leaves); return root; } } ================================================ FILE: src/com/interview/tree/LevelOrderTraversal.java ================================================ package com.interview.tree; import java.util.LinkedList; import java.util.Queue; /** * Youtube link - https://youtu.be/9PHkM0Jri_4 * * http://www.geeksforgeeks.org/level-order-tree-traversal/ * Test cases * Empty tree * Tree with only left side * Tree with only right side * Mixed size tree * Full tree * complete tree */ public class LevelOrderTraversal { public void levelOrder(Node root){ if(root == null){ System.out.println("Please enter a valid tree!"); return; } Queue queue = new LinkedList(); queue.offer(root); System.out.println(); while(queue.size() > 0){ root = queue.poll(); System.out.print(root.data + " "); if(root.left != null){ queue.add(root.left); } if(root.right != null){ queue.add(root.right); } } } public static void main(String args[]){ LevelOrderTraversal loi = new LevelOrderTraversal(); BinaryTree bt = new BinaryTree(); Node head = null; head = bt.addNode(10, head); head = bt.addNode(15, head); head = bt.addNode(5, head); head = bt.addNode(7, head); head = bt.addNode(19, head); head = bt.addNode(20, head); head = bt.addNode(-1, head); loi.levelOrder(head); } } ================================================ FILE: src/com/interview/tree/LevelOrderTraversalInReverse.java ================================================ package com.interview.tree; import java.util.LinkedList; import java.util.Queue; import java.util.Stack; /** * Date 04/20/2015 * @author tusroy * * Video link - https://youtu.be/D2bIbWGgvzI * * Given a binary tree print its level order traversal in reverse * e.g 1 * 2 3 * 4 5 6 7 * * Output should be 4 5 6 7 2 3 1 * * Solution * Maintain a stack and queue. Do regular level order traversal but * put right first in the queue. Instead of printing put the result * in stack. Finally print contents of the stack. * * Time and space complexity is O(n) * * References : http://www.geeksforgeeks.org/reverse-level-order-traversal/ */ public class LevelOrderTraversalInReverse { public void reverseLevelOrderTraversal(Node root){ if(root == null){ return; } Queue q = new LinkedList<>(); Stack s = new Stack<>(); q.offer(root); while(!q.isEmpty()){ root = q.poll(); if(root.right != null){ q.offer(root.right); } if(root.left != null){ q.offer(root.left); } s.push(root); } while(!s.isEmpty()){ System.out.print(s.pop().data + " "); } } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node root = null; root = bt.addNode(10, root); root = bt.addNode(30, root); root = bt.addNode(25, root); root = bt.addNode(35, root); root = bt.addNode(-10, root); root = bt.addNode(0, root); root = bt.addNode(-20, root); root = bt.addNode(-15, root); root = bt.addNode(45, root); LevelOrderTraversalInReverse rlo = new LevelOrderTraversalInReverse(); rlo.reverseLevelOrderTraversal(root); } } ================================================ FILE: src/com/interview/tree/LongestConsecutiveSequence.java ================================================ package com.interview.tree; /** * Created by tushar_v_roy on 4/1/16. */ public class LongestConsecutiveSequence { int max = 0; public int longestConsecutive(Node root) { if (root == null) { return 0; } max = 0; longestConsecutiveUtil(root, root.data - 1, 0); return max; } public void longestConsecutiveUtil(Node root, int prevData, int current) { if (root == null) { return; } if (root.data == prevData + 1) { current = current + 1; } else { current = 1; } max = Math.max(current, max); longestConsecutiveUtil(root.left, root.data, current); longestConsecutiveUtil(root.right, root.data, current); } } ================================================ FILE: src/com/interview/tree/LowestCommonAncestorInBinaryTree.java ================================================ package com.interview.tree; /** * Date 04/27/2016 * @author Tushar Roy * * Find lowest common ancestor in binary tree. * * Time complexity O(n) * Space complexity O(h) */ public class LowestCommonAncestorInBinaryTree { public Node lca(Node root, Node n1, Node n2){ if(root == null){ return null; } if(root == n1 || root == n2){ return root; } Node left = lca(root.left, n1, n2); Node right = lca(root.right, n1, n2); if(left != null && right != null){ return root; } return left != null ? left : right; } } ================================================ FILE: src/com/interview/tree/LowestCommonAncestoryBinarySearchTree.java ================================================ package com.interview.tree; /** * Date 05/04/2016 * @author Tushar Roy * * Lowest common ancestor in binary search tree. * * Time complexity O(height of tree) * Space complexity O(height of tree) * * https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/ */ public class LowestCommonAncestoryBinarySearchTree { public Node lowestCommonAncestor(Node root, int p, int q) { if (root.data > Math.max(p, q)) { return lowestCommonAncestor(root.left, p, q); } else if (root.data < Math.min(p, q)) { return lowestCommonAncestor(root.right, p, q); } else { return root; } } } ================================================ FILE: src/com/interview/tree/MorrisTraversal.java ================================================ package com.interview.tree; /** * Date 03/08/2016 * @author Tushar Roy * * Morris inorder/preorder traversals * * Time complexity O(n) * Space complexity O(1) */ public class MorrisTraversal { public void inorder(Node root) { Node current = root; while(current != null) { //left is null then print the node and go to right if (current.left == null) { System.out.print(current.data + " "); current = current.right; } else { //find the predecessor. Node predecessor = current.left; //To find predecessor keep going right till right node is not null or right node is not current. while(predecessor.right != current && predecessor.right != null){ predecessor = predecessor.right; } //if right node is null then go left after establishing link from predecessor to current. if(predecessor.right == null){ predecessor.right = current; current = current.left; }else{ //left is already visit. Go rigth after visiting current. predecessor.right = null; System.out.print(current.data + " "); current = current.right; } } } } public void preorder(Node root) { Node current = root; while (current != null) { if(current.left == null) { System.out.print(current.data + " "); current = current.right; } else { Node predecessor = current.left; while(predecessor.right != current && predecessor.right != null) { predecessor = predecessor.right; } if(predecessor.right == null){ predecessor.right = current; System.out.print(current.data + " "); current = current.left; }else{ predecessor.right = null; current = current.right; } } } } public static void main(String args[]) { BinaryTree bt = new BinaryTree(); Node root = null; root = bt.addNode(10, root); root = bt.addNode(50, root); root = bt.addNode(-10, root); root = bt.addNode(7, root); root = bt.addNode(9, root); root = bt.addNode(-20, root); root = bt.addNode(30, root); MorrisTraversal mt = new MorrisTraversal(); mt.inorder(root); System.out.println(); mt.preorder(root); } } ================================================ FILE: src/com/interview/tree/NextInorderSuccessorIterator.java ================================================ package com.interview.tree; import java.util.HashSet; import java.util.Set; import java.util.Stack; /** * http://www.glassdoor.com/Interview/Create-an-iterator-to-traverse-a-binary-tree-When-the-next-function-is-called-on-the-binary-tree-return-the-value-at-the-QTN_674695.htm * null tree. */ public class NextInorderSuccessorIterator { private Node root = null; Stack stack = new Stack(); Set visited = new HashSet(); NextInorderSuccessorIterator(Node root){ this.root = root; } public int next(){ Node node = null; while(root != null){ stack.push(root); root = root.left; } root = stack.pop(); node = root; root = root.right; return node.data; } public boolean hasNext(){ if(root != null || stack.size() > 0){ return true; } return false; } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node node = null; node = bt.addNode(10, node); node = bt.addNode(-5, node); node = bt.addNode(7, node); node = bt.addNode(20, node); node = bt.addNode(3, node); node = bt.addNode(14, node); NextInorderSuccessorIterator nis = new NextInorderSuccessorIterator(node); while(nis.hasNext()){ System.out.println(nis.next()); } } } ================================================ FILE: src/com/interview/tree/NextInorderSuccessorOfTwoTree.java ================================================ package com.interview.tree; import java.util.HashSet; import java.util.Set; import java.util.Stack; /** * Next inorder iterator of two trees. * Merging tree to print one result */ public class NextInorderSuccessorOfTwoTree { private Node root1 = null; private Node root2 = null; Stack stack1 = new Stack(); Stack stack2 = new Stack(); Set visited = new HashSet(); NextInorderSuccessorOfTwoTree(Node root1, Node root2) { this.root1 = root1; this.root2 = root2; } public boolean hasNext() { if (root1 != null || stack1.size() > 0 || root2 != null || stack2.size() > 0) { return true; } return false; } public Node next() { Node node = null; while (root1 != null) { stack1.push(root1); root1 = root1.left; } while (root2 != null) { stack2.push(root2); root2 = root2.left; } if (!stack1.isEmpty() && !stack2.isEmpty()) { if (stack1.peek().data <= stack2.peek().data) { node = stack1.pop(); root1 = node.right; } else { node = stack2.pop(); root2 = node.right; } } else if (stack1.isEmpty()) { node = stack2.pop(); root2 = node.right; } else { node = stack1.pop(); root1 = node.right; } return node; } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node node = null; node = bt.addNode(10, node); node = bt.addNode(-5, node); node = bt.addNode(7, node); node = bt.addNode(20, node); node = bt.addNode(3, node); node = bt.addNode(14, node); Node node1 = null; node1 = bt.addNode(8, node1); node1 = bt.addNode(-10, node1); node1 = bt.addNode(18, node1); node1 = bt.addNode(2, node1); node1 = bt.addNode(11, node1); NextInorderSuccessorOfTwoTree nis = new NextInorderSuccessorOfTwoTree(node, node1); while(nis.hasNext()){ System.out.println(nis.next().data); } } } ================================================ FILE: src/com/interview/tree/NodesAtDistanceK.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/print-nodes-distance-k-given-node-binary-tree/ * Test case * k should not be negative * k could be very big number which means nothing was found * dest might/might not exists in the tree * root could be null */ public class NodesAtDistanceK { private void findInChild(Node root, int k){ if(root == null){ return; } if(k == 0){ System.out.println(root.data); } findInChild(root.left, k-1); findInChild(root.right, k-1); } public int printNodes(Node root,int dest, int k){ if(root == null){ return -1; } if(root.data == dest){ findInChild(root, k); return k-1; } int found = printNodes(root.left,dest,k); if(found != -1){ if(found == 0){ System.out.println(root.data); }else{ findInChild(root.right, found-1); } return found -1; } found = printNodes(root.right,dest,k); if(found != -1){ if(found == 0){ System.out.println(root.data); }else{ findInChild(root.left, found-1); } return found-1; } return -1; } public static void main(String args[]){ NodesAtDistanceK nad = new NodesAtDistanceK(); Node root = null; BinaryTree bt = new BinaryTree(); root = bt.addNode(10, root); root = bt.addNode(3, root); root = bt.addNode(-1, root); root = bt.addNode(8, root); root = bt.addNode(-6, root); root = bt.addNode(-11, root); root = bt.addNode(18, root); root = bt.addNode(11, root); root = bt.addNode(13, root); root = bt.addNode(26, root); root = bt.addNode(27, root); nad.printNodes(root, 11, 2); } } ================================================ FILE: src/com/interview/tree/NodesWithNoSibling.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/print-nodes-dont-sibling-binary-tree/ * This does not print root node even though it has no sibling * Test cases: * Null tree * Only one node tree * All left side tree * All right side tree * Regular mix tree */ public class NodesWithNoSibling { public void printNodes(Node root){ if(root == null){ return; } if(root.left == null || root.right == null){ if(root.left != null){ System.out.print(root.left.data + " "); } if(root.right != null){ System.out.print(root.right.data + " "); } } printNodes(root.left); printNodes(root.right); } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node root = null; root = bt.addNode(10, root); root = bt.addNode(5, root); root = bt.addNode(-1, root); root = bt.addNode(-5, root); root = bt.addNode(20, root); root = bt.addNode(25, root); NodesWithNoSibling nws = new NodesWithNoSibling(); nws.printNodes(root); } } ================================================ FILE: src/com/interview/tree/PathSum.java ================================================ package com.interview.tree; import java.util.ArrayList; import java.util.List; /** * Date 10/06/2016 * @author Tushar Roy * * Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum. * * Time complexity O(n) * * https://leetcode.com/problems/path-sum/ * https://leetcode.com/problems/path-sum-ii/ */ public class PathSum { public List> pathSum(Node root, int sum) { List> result = new ArrayList<>(); List current = new ArrayList<>(); pathSumUtil(root, sum, result, current); return result; } private void pathSumUtil(Node root, int sum, List> result, List currentPath) { if (root == null) { return; } if (root.left == null && root.right == null) { if (root.data == sum) { currentPath.add(root.data); result.add(new ArrayList<>(currentPath)); currentPath.remove(currentPath.size() - 1); } return; } currentPath.add(root.data); pathSumUtil(root.left, sum - root.data, result, currentPath); pathSumUtil(root.right, sum - root.data, result, currentPath); currentPath.remove(currentPath.size() - 1); } public boolean hasPathSum(Node root, int sum) { if (root == null) { return false; } if (root.left == null && root.right == null) { return root.data == sum; } return hasPathSum(root.left, sum - root.data) || hasPathSum(root.right, sum - root.data); } } ================================================ FILE: src/com/interview/tree/PopulateInOrderSuccessor.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/populate-inorder-successor-for-all-nodes/ */ public class PopulateInOrderSuccessor { private void populate(Node root, NodeRef nodeRef){ if(root == null){ return; } populate(root.right,nodeRef); root.next = nodeRef.node; nodeRef.node = root; populate(root.left,nodeRef); } public void populate(Node root){ NodeRef nodeRef = new NodeRef(); populate(root,nodeRef); } public void print(Node root){ if(root == null){ return; } System.out.println(root.data); print(root.next); } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node head = null; head = bt.addNode(10, head); head = bt.addNode(15, head); head = bt.addNode(5, head); head = bt.addNode(7, head); head = bt.addNode(19, head); head = bt.addNode(20, head); head = bt.addNode(-1, head); head = bt.addNode(21, head); PopulateInOrderSuccessor pio = new PopulateInOrderSuccessor(); pio.populate(head); while(head.left != null){ head = head.left; } pio.print(head); } } ================================================ FILE: src/com/interview/tree/PrintPostOrderFromPreOrderInOrder.java ================================================ package com.interview.tree; /** * Date 11/02/2015 * @author Tushar Roy * * Given a preorder/inorder traversal of binary tree create postorder traversal of binary tree * without creating the tree * * Time complexity - O(n) * * References * http://www.geeksforgeeks.org/print-postorder-from-given-inorder-and-preorder-traversals/ */ import java.util.concurrent.atomic.AtomicInteger; public class PrintPostOrderFromPreOrderInOrder { public int[] postOrder(int[] preorder, int[] inorder) { int[] post = new int[inorder.length]; AtomicInteger postIndex = new AtomicInteger(post.length - 1); postOrder(preorder, inorder, post, 0, inorder.length -1, 0, postIndex); return post; } private void postOrder(int[] preorder, int[] inorder, int post[], int low, int high, int preIndex, AtomicInteger postIndex) { if(low > high) { return; } post[postIndex.getAndDecrement()] = preorder[preIndex]; int i; for(i=0; i < inorder.length; i++) { if(preorder[preIndex] == inorder[i]) { break; } } postOrder(preorder, inorder, post, i+1, high, preIndex + (i - low) + 1, postIndex); postOrder(preorder, inorder, post, low, i-1, preIndex + 1, postIndex); } public static void main(String args[]) { int preorder[] = {10, 5, 3, 21, 20, 18, 9 , 16}; int inorder[] = {3, 5, 21, 10, 18, 9, 20, 16}; PrintPostOrderFromPreOrderInOrder ppp = new PrintPostOrderFromPreOrderInOrder(); int postorder[] = ppp.postOrder(preorder, inorder); for(int i : postorder) { System.out.print(i + " "); } } } ================================================ FILE: src/com/interview/tree/PrintTwoBSTInSortedForm.java ================================================ package com.interview.tree; import java.util.Deque; import java.util.LinkedList; /** * http://www.geeksforgeeks.org/merge-two-bsts-with-limited-extra-space/ * Test cases * Both tree are null * One of the tree is null * All elements of one tree occur before other tree * All elements of one tree occur after other tree * Elements are mixed * All same elements */ public class PrintTwoBSTInSortedForm { public void print(Node root1, Node root2){ Deque s1 = new LinkedList(); Deque s2 = new LinkedList(); while(true){ if(root1 != null){ s1.addFirst(root1); root1 = root1.left; continue; } if(root2 != null){ s2.addFirst(root2); root2 = root2.left; continue; } if(!s1.isEmpty()){ root1 = s1.peekFirst(); } if(!s2.isEmpty()){ root2 = s2.peekFirst(); } if(root1 != null && root2 != null){ if(root1.data <= root2.data){ System.out.println(root1.data); root1 = s1.pollFirst(); root1 = root1.right; root2 = null; }else{ System.out.println(root2.data); root2 = s2.pollFirst(); root2 = root2.right; root1 = null; } } else if(root1 != null){ System.out.println(root1.data); root1 = s1.pollFirst(); root1 = root1.right; }else if(root2 != null){ System.out.println(root2.data); root2 = s2.pollFirst(); root2 = root2.right; } if(root1 == null && root2 == null && s1.isEmpty() && s2.isEmpty()){ break; } } } public static void main(String args[]){ PrintTwoBSTInSortedForm ptb = new PrintTwoBSTInSortedForm(); BinaryTree bt = new BinaryTree(); Node head = null; head = bt.addNode(10, head); head = bt.addNode(15, head); head = bt.addNode(5, head); head = bt.addNode(7, head); head = bt.addNode(19, head); head = bt.addNode(20, head); head = bt.addNode(-1, head); Node head1 = null; head1 = bt.addNode(-4, head1); head1 = bt.addNode(-3, head1); head1 = bt.addNode(6, head1); head1 = bt.addNode(11, head1); head1 = bt.addNode(22, head1); head1 = bt.addNode(26, head1); ptb.print(head, head1); } } ================================================ FILE: src/com/interview/tree/RedBlackTree.java ================================================ package com.interview.tree; import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; /** * Date 10/29/2015 * @author Tushar Roy * * Red Black Tree * * Time complexity * Insert - O(logn) * Delete - O(logn) * Search - O(logn) * * Does not work for duplicates. * * References * http://pages.cs.wisc.edu/~skrentny/cs367-common/readings/Red-Black-Trees/ * https://en.wikipedia.org/wiki/Red%E2%80%93black_tree */ public class RedBlackTree { public enum Color { RED, BLACK } public static class Node { int data; Color color; Node left; Node right; Node parent; boolean isNullLeaf; } private static Node createBlackNode(int data) { Node node = new Node(); node.data = data; node.color = Color.BLACK; node.left = createNullLeafNode(node); node.right = createNullLeafNode(node); return node; } private static Node createNullLeafNode(Node parent) { Node leaf = new Node(); leaf.color = Color.BLACK; leaf.isNullLeaf = true; leaf.parent = parent; return leaf; } private static Node createRedNode(Node parent, int data) { Node node = new Node(); node.data = data; node.color = Color.RED; node.parent = parent; node.left = createNullLeafNode(node); node.right = createNullLeafNode(node); return node; } /** * Main insert method of red black tree. */ public Node insert(Node root, int data) { return insert(null, root, data); } /** * Main delete method of red black tree. */ public Node delete(Node root, int data) { AtomicReference rootReference = new AtomicReference<>(); delete(root, data, rootReference); if(rootReference.get() == null) { return root; } else { return rootReference.get(); } } /** * Main print method of red black tree. */ public void printRedBlackTree(Node root) { printRedBlackTree(root, 0); } /** * Main validate method of red black tree. */ public boolean validateRedBlackTree(Node root) { if(root == null) { return true; } //check if root is black if(root.color != Color.BLACK) { System.out.print("Root is not black"); return false; } //Use of AtomicInteger solely because java does not provide any other mutable int wrapper. AtomicInteger blackCount = new AtomicInteger(0); //make sure black count is same on all path and there is no red red relationship return checkBlackNodesCount(root, blackCount, 0) && noRedRedParentChild(root, Color.BLACK); } private void rightRotate(Node root, boolean changeColor) { Node parent = root.parent; root.parent = parent.parent; if(parent.parent != null) { if(parent.parent.right == parent) { parent.parent.right = root; } else { parent.parent.left = root; } } Node right = root.right; root.right = parent; parent.parent = root; parent.left = right; if(right != null) { right.parent = parent; } if(changeColor) { root.color = Color.BLACK; parent.color = Color.RED; } } private void leftRotate(Node root, boolean changeColor) { Node parent = root.parent; root.parent = parent.parent; if(parent.parent != null) { if(parent.parent.right == parent) { parent.parent.right = root; } else { parent.parent.left = root; } } Node left = root.left; root.left = parent; parent.parent = root; parent.right = left; if(left != null) { left.parent = parent; } if(changeColor) { root.color = Color.BLACK; parent.color = Color.RED; } } private Optional findSiblingNode(Node root) { Node parent = root.parent; if(isLeftChild(root)) { return Optional.ofNullable(parent.right.isNullLeaf ? null : parent.right); } else { return Optional.ofNullable(parent.left.isNullLeaf ? null : parent.left); } } private boolean isLeftChild(Node root) { Node parent = root.parent; if(parent.left == root) { return true; } else { return false; } } private Node insert(Node parent, Node root, int data) { if(root == null || root.isNullLeaf) { //if parent is not null means tree is not empty //so create a red leaf node if(parent != null) { return createRedNode(parent, data); } else { //otherwise create a black root node if tree is empty return createBlackNode(data); } } //duplicate insertion is not allowed for this tree. if(root.data == data) { throw new IllegalArgumentException("Duplicate date " + data); } //if we go on left side then isLeft will be true //if we go on right side then isLeft will be false. boolean isLeft; if(root.data > data) { Node left = insert(root, root.left, data); //if left becomes root parent means rotation //happened at lower level. So just return left //so that nodes at upper level can set their //child correctly if(left == root.parent) { return left; } //set the left child returned to be left of root node root.left = left; //set isLeft to be true isLeft = true; } else { Node right = insert(root, root.right, data); //if right becomes root parent means rotation //happened at lower level. So just return right //so that nodes at upper level can set their //child correctly if(right == root.parent) { return right; } //set the right child returned to be right of root node root.right = right; //set isRight to be true isLeft = false; } if(isLeft) { //if we went to left side check to see Red-Red conflict //between root and its left child if(root.color == Color.RED && root.left.color == Color.RED) { //get the sibling of root. It is returning optional means //sibling could be empty Optional sibling = findSiblingNode(root); //if sibling is empty or of BLACK color if(!sibling.isPresent() || sibling.get().color == Color.BLACK) { //check if root is left child of its parent if(isLeftChild(root)) { //this creates left left situation. So do one right rotate rightRotate(root, true); } else { //this creates left-right situation so do one right rotate followed //by left rotate //do right rotation without change in color. So sending false. //when right rotation is done root becomes right child of its left //child. So make root = root.parent because its left child before rotation //is new root of this subtree. rightRotate(root.left, false); //after rotation root should be root's parent root = root.parent; //then do left rotate with change of color leftRotate(root, true); } } else { //we have sibling color as RED. So change color of root //and its sibling to Black. And then change color of their //parent to red if their parent is not a root. root.color = Color.BLACK; sibling.get().color = Color.BLACK; //if parent's parent is not null means parent is not root. //so change its color to RED. if(root.parent.parent != null) { root.parent.color = Color.RED; } } } } else { //this is mirror case of above. So same comments as above. if(root.color == Color.RED && root.right.color == Color.RED) { Optional sibling = findSiblingNode(root); if(!sibling.isPresent() || sibling.get().color == Color.BLACK) { if(!isLeftChild(root)) { leftRotate(root, true); } else { leftRotate(root.right, false); root = root.parent; rightRotate(root, true); } } else { root.color = Color.BLACK; sibling.get().color = Color.BLACK; if(root.parent.parent != null) { root.parent.color = Color.RED; } } } } return root; } /** * Using atomicreference because java does not provide mutable wrapper. Its like * double pointer in C. */ private void delete(Node root, int data, AtomicReference rootReference) { if(root == null || root.isNullLeaf) { return; } if(root.data == data) { //if node to be deleted has 0 or 1 null children then we have //deleteOneChild use case as discussed in video. if(root.right.isNullLeaf || root.left.isNullLeaf) { deleteOneChild(root, rootReference); } else { //otherwise look for the inorder successor in right subtree. //replace inorder successor data at root data. //then delete inorder successor which should have 0 or 1 not null child. Node inorderSuccessor = findSmallest(root.right); root.data = inorderSuccessor.data; delete(root.right, inorderSuccessor.data, rootReference); } } //search for the node to be deleted. if(root.data < data) { delete(root.right, data, rootReference); } else { delete(root.left, data, rootReference); } } private Node findSmallest(Node root) { Node prev = null; while(root != null && !root.isNullLeaf) { prev = root; root = root.left; } return prev != null ? prev : root; } /** * Assumption that node to be deleted has either 0 or 1 non leaf child */ private void deleteOneChild(Node nodeToBeDelete, AtomicReference rootReference) { Node child = nodeToBeDelete.right.isNullLeaf ? nodeToBeDelete.left : nodeToBeDelete.right; //replace node with either one not null child if it exists or null child. replaceNode(nodeToBeDelete, child, rootReference); //if the node to be deleted is BLACK. See if it has one red child. if(nodeToBeDelete.color == Color.BLACK) { //if it has one red child then change color of that child to be Black. if(child.color == Color.RED) { child.color = Color.BLACK; } else { //otherwise we have double black situation. deleteCase1(child, rootReference); } } } /** * If double black node becomes root then we are done. Turning it into * single black node just reduces one black in every path. */ private void deleteCase1(Node doubleBlackNode, AtomicReference rootReference) { if(doubleBlackNode.parent == null) { rootReference.set(doubleBlackNode); return; } deleteCase2(doubleBlackNode, rootReference); } /** * If sibling is red and parent and sibling's children are black then rotate it * so that sibling becomes black. Double black node is still double black so we need * further processing. */ private void deleteCase2(Node doubleBlackNode, AtomicReference rootReference) { Node siblingNode = findSiblingNode(doubleBlackNode).get(); if(siblingNode.color == Color.RED) { if(isLeftChild(siblingNode)) { rightRotate(siblingNode, true); } else { leftRotate(siblingNode, true); } if(siblingNode.parent == null) { rootReference.set(siblingNode); } } deleteCase3(doubleBlackNode, rootReference); } /** * If sibling, sibling's children and parent are all black then turn sibling into red. * This reduces black node for both the paths from parent. Now parent is new double black * node which needs further processing by going back to case1. */ private void deleteCase3(Node doubleBlackNode, AtomicReference rootReference) { Node siblingNode = findSiblingNode(doubleBlackNode).get(); if(doubleBlackNode.parent.color == Color.BLACK && siblingNode.color == Color.BLACK && siblingNode.left.color == Color.BLACK && siblingNode.right.color == Color.BLACK) { siblingNode.color = Color.RED; deleteCase1(doubleBlackNode.parent, rootReference); } else { deleteCase4(doubleBlackNode, rootReference); } } /** * If sibling color is black, parent color is red and sibling's children color is black then swap color b/w sibling * and parent. This increases one black node on double black node path but does not affect black node count on * sibling path. We are done if we hit this situation. */ private void deleteCase4(Node doubleBlackNode, AtomicReference rootReference) { Node siblingNode = findSiblingNode(doubleBlackNode).get(); if(doubleBlackNode.parent.color == Color.RED && siblingNode.color == Color.BLACK && siblingNode.left.color == Color.BLACK && siblingNode.right.color == Color.BLACK) { siblingNode.color = Color.RED; doubleBlackNode.parent.color = Color.BLACK; return; } else { deleteCase5(doubleBlackNode, rootReference); } } /** * If sibling is black, double black node is left child of its parent, siblings right child is black * and sibling's left child is red then do a right rotation at siblings left child and swap colors. * This converts it to delete case6. It will also have a mirror case. */ private void deleteCase5(Node doubleBlackNode, AtomicReference rootReference) { Node siblingNode = findSiblingNode(doubleBlackNode).get(); if(siblingNode.color == Color.BLACK) { if (isLeftChild(doubleBlackNode) && siblingNode.right.color == Color.BLACK && siblingNode.left.color == Color.RED) { rightRotate(siblingNode.left, true); } else if (!isLeftChild(doubleBlackNode) && siblingNode.left.color == Color.BLACK && siblingNode.right.color == Color.RED) { leftRotate(siblingNode.right, true); } } deleteCase6(doubleBlackNode, rootReference); } /** * If sibling is black, double black node is left child of its parent, sibling left child is black and sibling's right child is * red, sibling takes its parent color, parent color becomes black, sibling's right child becomes black and then do * left rotation at sibling without any further change in color. This removes double black and we are done. This * also has a mirror condition. */ private void deleteCase6(Node doubleBlackNode, AtomicReference rootReference) { Node siblingNode = findSiblingNode(doubleBlackNode).get(); siblingNode.color = siblingNode.parent.color; siblingNode.parent.color = Color.BLACK; if(isLeftChild(doubleBlackNode)) { siblingNode.right.color = Color.BLACK; leftRotate(siblingNode, false); } else { siblingNode.left.color = Color.BLACK; rightRotate(siblingNode, false); } if(siblingNode.parent == null) { rootReference.set(siblingNode); } } private void replaceNode(Node root, Node child, AtomicReference rootReference) { child.parent = root.parent; if(root.parent == null) { rootReference.set(child); } else { if(isLeftChild(root)) { root.parent.left = child; } else { root.parent.right = child; } } } private void printRedBlackTree(Node root, int space) { if(root == null || root.isNullLeaf) { return; } printRedBlackTree(root.right, space + 5); for(int i=0; i < space; i++) { System.out.print(" "); } System.out.println(root.data + " " + (root.color == Color.BLACK ? "B" : "R")); printRedBlackTree(root.left, space + 5); } private boolean noRedRedParentChild(Node root, Color parentColor) { if(root == null) { return true; } if(root.color == Color.RED && parentColor == Color.RED) { return false; } return noRedRedParentChild(root.left, root.color) && noRedRedParentChild(root.right, root.color); } private boolean checkBlackNodesCount(Node root, AtomicInteger blackCount, int currentCount) { if(root.color == Color.BLACK) { currentCount++; } if(root.left == null && root.right == null) { if(blackCount.get() == 0) { blackCount.set(currentCount); return true; } else { return currentCount == blackCount.get(); } } return checkBlackNodesCount(root.left, blackCount, currentCount) && checkBlackNodesCount(root.right, blackCount, currentCount); } public static void main(String args[]) { Node root = null; RedBlackTree redBlackTree = new RedBlackTree(); root = redBlackTree.insert(root, 10); root = redBlackTree.insert(root, 15); root = redBlackTree.insert(root, -10); root = redBlackTree.insert(root, 20); root = redBlackTree.insert(root, 30); root = redBlackTree.insert(root, 40); root = redBlackTree.insert(root, 50); root = redBlackTree.insert(root, -15); root = redBlackTree.insert(root, 25); root = redBlackTree.insert(root, 17); root = redBlackTree.insert(root, 21); root = redBlackTree.insert(root, 24); root = redBlackTree.insert(root, 28); root = redBlackTree.insert(root, 34); root = redBlackTree.insert(root, 32); root = redBlackTree.insert(root, 26); root = redBlackTree.insert(root, 35); root = redBlackTree.insert(root, 19); redBlackTree.printRedBlackTree(root); root = redBlackTree.delete(root, 50); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 40); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, -10); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 15); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 17); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 24); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 21); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 32); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 26); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 19); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 25); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 17); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, -15); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 20); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 35); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 34); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 30); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 28); System.out.println(redBlackTree.validateRedBlackTree(root)); root = redBlackTree.delete(root, 10); System.out.println(redBlackTree.validateRedBlackTree(root)); } } ================================================ FILE: src/com/interview/tree/RootToLeafToSum.java ================================================ package com.interview.tree; import java.util.ArrayList; import java.util.List; /** * Date 04/11/2015 * @author tusroy * * Youtube link - https://youtu.be/Jg4E4KZstFE * * Given a binary tree and a sum, find if there is a path from root to leaf * which sums to this sum. * * Solution * Keep going left and right and keep subtracting node value from sum. * If leaf node is reached check if whatever sum is remaining same as leaf node data. * * Time complexity is O(n) since all nodes are visited. * * Test cases: * Negative number, 0 and positive number * Tree with 0, 1 or more nodes * * Reference http://www.geeksforgeeks.org/root-to-leaf-path-sum-equal-to-a-given-number/ */ public class RootToLeafToSum { public boolean printPath(Node root, int sum, List path){ if(root == null){ return false; } if(root.left == null && root.right == null){ if(root.data == sum){ path.add(root); return true; }else{ return false; } } if(printPath(root.left, sum-root.data, path) || printPath(root.right, sum - root.data, path)){ path.add(root); return true; } return false; } public static void main(String args[]){ RootToLeafToSum rtl = new RootToLeafToSum(); BinaryTree bt = new BinaryTree(); Node head = null; head = bt.addNode(10, head); head = bt.addNode(15, head); head = bt.addNode(5, head); head = bt.addNode(7, head); head = bt.addNode(19, head); head = bt.addNode(20, head); head = bt.addNode(4, head); head = bt.addNode(3, head); List result = new ArrayList<>(); boolean r = rtl.printPath(head, 22, result); if(r){ result.forEach(node -> System.out.print(node.data + " ")); }else{ System.out.println("No path for sum " + 22); } } } ================================================ FILE: src/com/interview/tree/SameTree.java ================================================ package com.interview.tree; /** * Date 04/11/2015 * @author tusroy * * Youtube link - https://youtu.be/ySDDslG8wws * * Given roots of two tree, return true if they have same data and same structure * or return false. * * Solution * Keep comparing root of both data and then recursively check left and right. * * Time complexity is O(n) */ public class SameTree { public boolean sameTree(Node root1, Node root2){ if(root1 == null && root2 == null){ return true; } if(root1 == null || root2 == null){ return false; } return root1.data == root2.data && sameTree(root1.left, root2.left) && sameTree(root1.right, root2.right); } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node root1 = null; root1 = bt.addNode(10, root1); root1 = bt.addNode(20, root1); root1 = bt.addNode(15, root1); root1 = bt.addNode(2, root1); Node root2 = null; root2 = bt.addNode(10, root2); root2 = bt.addNode(20, root2); root2 = bt.addNode(15, root2); root2 = bt.addNode(2, root2); SameTree st = new SameTree(); assert st.sameTree(root1, root2); } } ================================================ FILE: src/com/interview/tree/SegmentTree.java ================================================ package com.interview.tree; /** * Date 08/21/2014 * @author tusroy * * Video link - https://youtu.be/ZBHKZF5w4YU * * A segment tree is a tree data structure for storing intervals, or segments. It allows * for faster querying (e.g sum or min) in these intervals. * Write a program to support these operations for sum * createSegmentTree(int arr[]) - create segment tree * query(int segment[], int startRange, int endRange) - query in this range * * Similar segment trees can be created for min or max. * * Time complexity to create segment tree is O(nlogn) * Space complexity to create segment tree is O(nlogn) * Time complexity to search in segment tree is O(logn) * References * http://www.geeksforgeeks.org/segment-tree-set-1-sum-of-given-range/ * http://www.geeksforgeeks.org/segment-tree-set-1-range-minimum-query/ */ public class SegmentTree { public int[] createTree(int input[], Operation operation){ int height = (int)Math.ceil(Math.log(input.length)/Math.log(2)); int segmentTree[] = new int[(int)(Math.pow(2, height+1)-1)]; constructTree(segmentTree,input,0,input.length-1,0, operation); return segmentTree; } private void constructTree(int segmentTree[], int input[], int low, int high,int pos, Operation operation){ if(low == high){ segmentTree[pos] = input[low]; return; } int mid = (low + high)/2; constructTree(segmentTree,input,low,mid,2*pos+1, operation); constructTree(segmentTree,input,mid+1,high,2*pos+2, operation); segmentTree[pos] = operation.perform(segmentTree[2*pos+1], segmentTree[2*pos+2]); } public int rangeQuery(int []segmentTree,int qlow,int qhigh,int len, Operation operation){ return rangeQuery(segmentTree,0,len-1,qlow,qhigh,0, operation); } private int rangeQuery(int segmentTree[],int low,int high,int qlow,int qhigh,int pos, Operation operation){ if(qlow <= low && qhigh >= high){ return segmentTree[pos]; } if(qlow > high || qhigh < low){ return 0; } int mid = (low+high)/2; return operation.perform(rangeQuery(segmentTree,low,mid,qlow,qhigh,2*pos+1, operation), rangeQuery(segmentTree,mid+1,high,qlow,qhigh,2*pos+2, operation)); } public void updateValueForSumOperation(int input[],int segmentTree[],int newVal,int index){ int diff = newVal - input[index]; input[index] = newVal; updateVal(segmentTree,0,input.length-1,diff,index,0); } private void updateVal(int segmentTree[],int low,int high,int diff,int index, int pos){ if(index < low || index > high){ return; } segmentTree[pos] += diff; if(low >= high){ return; } int mid = (low + high)/2; updateVal(segmentTree,low,mid,diff,index,2*pos+1); updateVal(segmentTree,mid+1,high,diff,index,2*pos+2); } public static void main(String args[]){ int input[] = {1,3,5,7,9,11}; SegmentTree st = new SegmentTree(); Operation sumOp = new SumOperation(); Operation minOp = new MinOperation(); int result [] = st.createTree(input, sumOp); for(int i=0; i < result.length; i++){ System.out.print(result[i] + " "); } int input1[] = {3,4,2,1,6,-1}; int result1[] = st.createTree(input1, minOp); for(int i=0; i < result1.length; i++){ System.out.print(result1[i] + " "); } st.updateValueForSumOperation(input, result,0 , 0); System.out.println(); for(int i=0; i < result.length; i++){ System.out.print(result[i] + " "); } } } /** * Provides interface to perform operations on range queue like sum or min */ interface Operation{ int perform(int a, int b); } class SumOperation implements Operation{ @Override public int perform(int a, int b) { return a+b; } } class MinOperation implements Operation{ @Override public int perform(int a, int b){ return Math.min(a,b); } } ================================================ FILE: src/com/interview/tree/SegmentTreeMinimumRangeQuery.java ================================================ package com.interview.tree; import com.interview.bits.NextPowerOf2; /** * Date 08/22/2015 * @author Tushar Roy * * A segment tree is a tree data structure for storing intervals, or segments. It allows * for faster querying (e.g sum or min) in these intervals. Lazy propagation is useful * when there are high number of updates in the input array. * Write a program to support mininmum range query * createSegmentTree(int arr[]) - create segment tree * query(int segment[], int startRange, int endRange) - returns minimum between startRange and endRange * update(int input[], int segment[], int indexToBeUpdated, int newVal) - updates input and segmentTree with newVal at index indexToBeUpdated; * updateRange(int input[], int segment[], int lowRange, int highRange, int delta) - updates all the values in given range by * adding delta to them * queryLazy(int segment[], int startRange, int endRange) - query based off lazy propagation * * Time complexity to create segment tree is O(n) since new array will be at max 4n size * Space complexity to create segment tree is O(n) since new array will be at max 4n size * Time complexity to search in segment tree is O(logn) since you would at max travel 4 depths * Time complexity to update in segment tree is O(logn) * Time complexity to update range in segment tree is O(range) * * References * http://www.geeksforgeeks.org/segment-tree-set-1-sum-of-given-range/ * http://www.geeksforgeeks.org/segment-tree-set-1-range-minimum-query/ * https://www.topcoder.com/community/data-science/data-science-tutorials/range-minimum-query-and-lowest-common-ancestor/ */ public class SegmentTreeMinimumRangeQuery { /** * Creates a new segment tree based off input array. */ public int[] createSegmentTree(int input[]){ NextPowerOf2 np2 = new NextPowerOf2(); //if input len is pow of 2 then size of //segment tree is 2*len - 1, otherwise //size of segment tree is next (pow of 2 for len)*2 - 1. int nextPowOfTwo = np2.nextPowerOf2(input.length); int segmentTree[] = new int[nextPowOfTwo*2 -1]; for(int i=0; i < segmentTree.length; i++){ segmentTree[i] = Integer.MAX_VALUE; } constructMinSegmentTree(segmentTree, input, 0, input.length - 1, 0); return segmentTree; } /** * Updates segment tree for certain index by given delta */ public void updateSegmentTree(int input[], int segmentTree[], int index, int delta){ input[index] += delta; updateSegmentTree(segmentTree, index, delta, 0, input.length - 1, 0); } /** * Updates segment tree for given range by given delta */ public void updateSegmentTreeRange(int input[], int segmentTree[], int startRange, int endRange, int delta) { for(int i = startRange; i <= endRange; i++) { input[i] += delta; } updateSegmentTreeRange(segmentTree, startRange, endRange, delta, 0, input.length - 1, 0); } /** * Queries given range for minimum value. */ public int rangeMinimumQuery(int []segmentTree,int qlow,int qhigh,int len){ return rangeMinimumQuery(segmentTree,0,len-1,qlow,qhigh,0); } /** * Updates given range by given delta lazily */ public void updateSegmentTreeRangeLazy(int input[], int segmentTree[], int lazy[], int startRange, int endRange, int delta) { updateSegmentTreeRangeLazy(segmentTree, lazy, startRange, endRange, delta, 0, input.length - 1, 0); } /** * Queries given range lazily */ public int rangeMinimumQueryLazy(int segmentTree[], int lazy[], int qlow, int qhigh, int len) { return rangeMinimumQueryLazy(segmentTree, lazy, qlow, qhigh, 0, len - 1, 0); } private void constructMinSegmentTree(int segmentTree[], int input[], int low, int high,int pos){ if(low == high){ segmentTree[pos] = input[low]; return; } int mid = (low + high)/2; constructMinSegmentTree(segmentTree, input, low, mid, 2 * pos + 1); constructMinSegmentTree(segmentTree, input, mid + 1, high, 2 * pos + 2); segmentTree[pos] = Math.min(segmentTree[2*pos+1], segmentTree[2*pos+2]); } private void updateSegmentTree(int segmentTree[], int index, int delta, int low, int high, int pos){ //if index to be updated is less than low or higher than high just return. if(index < low || index > high){ return; } //if low and high become equal, then index will be also equal to them and update //that value in segment tree at pos if(low == high){ segmentTree[pos] += delta; return; } //otherwise keep going left and right to find index to be updated //and then update current tree position if min of left or right has //changed. int mid = (low + high)/2; updateSegmentTree(segmentTree, index, delta, low, mid, 2 * pos + 1); updateSegmentTree(segmentTree, index, delta, mid + 1, high, 2 * pos + 2); segmentTree[pos] = Math.min(segmentTree[2*pos+1], segmentTree[2*pos + 2]); } private void updateSegmentTreeRange(int segmentTree[], int startRange, int endRange, int delta, int low, int high, int pos) { if(low > high || startRange > high || endRange < low ) { return; } if(low == high) { segmentTree[pos] += delta; return; } int middle = (low + high)/2; updateSegmentTreeRange(segmentTree, startRange, endRange, delta, low, middle, 2 * pos + 1); updateSegmentTreeRange(segmentTree, startRange, endRange, delta, middle + 1, high, 2 * pos + 2); segmentTree[pos] = Math.min(segmentTree[2*pos+1], segmentTree[2*pos+2]); } private int rangeMinimumQuery(int segmentTree[],int low,int high,int qlow,int qhigh,int pos){ if(qlow <= low && qhigh >= high){ return segmentTree[pos]; } if(qlow > high || qhigh < low){ return Integer.MAX_VALUE; } int mid = (low+high)/2; return Math.min(rangeMinimumQuery(segmentTree, low, mid, qlow, qhigh, 2 * pos + 1), rangeMinimumQuery(segmentTree, mid + 1, high, qlow, qhigh, 2 * pos + 2)); } private void updateSegmentTreeRangeLazy(int segmentTree[], int lazy[], int startRange, int endRange, int delta, int low, int high, int pos) { if(low > high) { return; } //make sure all propagation is done at pos. If not update tree //at pos and mark its children for lazy propagation. if (lazy[pos] != 0) { segmentTree[pos] += lazy[pos]; if (low != high) { //not a leaf node lazy[2 * pos + 1] += lazy[pos]; lazy[2 * pos + 2] += lazy[pos]; } lazy[pos] = 0; } //no overlap condition if(startRange > high || endRange < low) { return; } //total overlap condition if(startRange <= low && endRange >= high) { segmentTree[pos] += delta; if(low != high) { lazy[2*pos + 1] += delta; lazy[2*pos + 2] += delta; } return; } //otherwise partial overlap so look both left and right. int mid = (low + high)/2; updateSegmentTreeRangeLazy(segmentTree, lazy, startRange, endRange, delta, low, mid, 2*pos+1); updateSegmentTreeRangeLazy(segmentTree, lazy, startRange, endRange, delta, mid+1, high, 2*pos+2); segmentTree[pos] = Math.min(segmentTree[2*pos + 1], segmentTree[2*pos + 2]); } private int rangeMinimumQueryLazy(int segmentTree[], int lazy[], int qlow, int qhigh, int low, int high, int pos) { if(low > high) { return Integer.MAX_VALUE; } //make sure all propagation is done at pos. If not update tree //at pos and mark its children for lazy propagation. if (lazy[pos] != 0) { segmentTree[pos] += lazy[pos]; if (low != high) { //not a leaf node lazy[2 * pos + 1] += lazy[pos]; lazy[2 * pos + 2] += lazy[pos]; } lazy[pos] = 0; } //no overlap if(qlow > high || qhigh < low){ return Integer.MAX_VALUE; } //total overlap if(qlow <= low && qhigh >= high){ return segmentTree[pos]; } //partial overlap int mid = (low+high)/2; return Math.min(rangeMinimumQueryLazy(segmentTree, lazy, qlow, qhigh, low, mid, 2 * pos + 1), rangeMinimumQueryLazy(segmentTree, lazy, qlow, qhigh, mid + 1, high, 2 * pos + 2)); } public static void main(String args[]){ SegmentTreeMinimumRangeQuery st = new SegmentTreeMinimumRangeQuery(); int input[] = {0,3,4,2,1,6,-1}; int segTree[] = st.createSegmentTree(input); //non lazy propagation example assert 0 == st.rangeMinimumQuery(segTree, 0, 3, input.length); assert 1 == st.rangeMinimumQuery(segTree, 1, 5, input.length); assert -1 == st.rangeMinimumQuery(segTree, 1, 6, input.length); st.updateSegmentTree(input, segTree, 2, 1); assert 2 == st.rangeMinimumQuery(segTree, 1, 3, input.length); st.updateSegmentTreeRange(input, segTree, 3, 5, -2); assert -1 == st.rangeMinimumQuery(segTree, 5, 6, input.length); assert 0 == st.rangeMinimumQuery(segTree, 0, 3, input.length); //lazy propagation example int input1[] = {-1,2,4,1,7,1,3,2}; int segTree1[] = st.createSegmentTree(input1); int lazy1[] = new int[segTree.length]; st.updateSegmentTreeRangeLazy(input1, segTree1, lazy1, 0, 3, 1); st.updateSegmentTreeRangeLazy(input1, segTree1, lazy1, 0, 0, 2); assert 1 == st.rangeMinimumQueryLazy(segTree1, lazy1, 3, 5, input1.length); } } ================================================ FILE: src/com/interview/tree/SerializeDeserializeBinaryTree.java ================================================ package com.interview.tree; import javax.swing.tree.TreeNode; import java.util.Deque; import java.util.LinkedList; /** * Date 03/12/2016 * @author Tushar Roy * * Serialize/Deserialize a binary tree whose data is a number. * * Time complexity O(n) * Space complexity O(n) * * Reference * https://leetcode.com/problems/serialize-and-deserialize-binary-tree/ */ public class SerializeDeserializeBinaryTree { /** * Serialize Tree using preorder DFS * @param root * @return */ public String serialize(Node root) { StringBuffer buff = new StringBuffer(); serializeUtil(root, buff); return buff.toString(); } private void serializeUtil(Node root, StringBuffer buff) { if (root == null) { buff.append("%,"); return; } buff.append(root.data).append(","); if (root.left != null || root.right != null) { buff.append("$,"); serializeUtil(root.left, buff); serializeUtil(root.right, buff); } else { return; } } int index = 0; /** * Deserialize Tree using preorder DFS * @param data * @return */ public Node deserialize(String data) { String[] input = data.split(","); index = 0; return deserializeUtil(input); } private Node deserializeUtil(String input[]) { if (index == input.length) { return null; } if (input[index].equals("%")) { index++; return null; } Node n = new Node(); n.data = Integer.parseInt(input[index]); if (index < input.length - 1) { if (input[index + 1].equals("$")) { index += 2; n.left = deserializeUtil(input); n.right = deserializeUtil(input); } else { index++; } } return n; } /** * Serialize tree using level order traversal. */ public String serializeLevelOrder(Node root) { if (root == null) { return ""; } Deque queue = new LinkedList<>(); queue.offerFirst(root); StringBuffer buff = new StringBuffer(); while (!queue.isEmpty()) { root = queue.pollFirst(); if (root == null) { buff.append("%,"); } else { buff.append(root.data).append(","); queue.offer(root.left); queue.offer(root.right); } } for (int i = buff.length() - 1; i >= 0; i--) { if (buff.charAt(i) == '%' || buff.charAt(i) == ',') { buff.deleteCharAt(i); } else { break; } } return buff.toString(); } /** * Deserialize Tree using level order traversal. */ public Node deserializeLevelOrder(String data) { if (data == null || data.length() == 0) { return null; } String[] input = data.split(","); Deque queue = new LinkedList<>(); int index = 0; queue.offerFirst(Node.newNode(Integer.parseInt(input[index]))); Node root = queue.peekFirst(); index++; while (!queue.isEmpty()) { Node current = queue.pollFirst(); if (index < input.length && !input[index].equals("%")) { current.left = Node.newNode(Integer.parseInt(input[index])); queue.offerLast(current.left); } index++; if (index < input.length && !input[index].equals("%")) { current.right = Node.newNode(Integer.parseInt(input[index])); queue.offerLast(current.right); } index++; } return root; } public static void main(String args[]) { SerializeDeserializeBinaryTree sd = new SerializeDeserializeBinaryTree(); Node node = sd.deserialize("10,$,30,15,$,%,20,$,21,16,$,%,18"); TreeTraversals tt = new TreeTraversals(); tt.inOrder(node); String serializedTree= sd.serializeLevelOrder(node); Node root = sd.deserializeLevelOrder("1,2"); tt.inOrder(root); } } ================================================ FILE: src/com/interview/tree/SinkNegativeToBottom.java ================================================ package com.interview.tree; /** * http://www.careercup.com/question?id=5344154741637120 */ public class SinkNegativeToBottom { public void sinkZero(Node root) { if (root == null) { return; } sinkZero(root.left); sinkZero(root.right); if (root.data < 0) { pushDown(root); } } private void pushDown(Node root) { if(root == null){ return; } // find a child with non zero node value if (root.left == null && root.right == null) { // already leaf node. nothing to do. just return return; } //if root left is not null and root left data is not 0 pick it to swap if (root.left != null && root.left.data >= 0) { int temp = root.data; root.data = root.left.data; root.left.data = temp; pushDown(root.left); } else if(root.right != null && root.right.data >= 0){ int temp = root.data; root.data = root.right.data; root.right.data = temp; pushDown(root.right); } } public static void main(String args[]){ int preorder[] = {-1,1,6,-2,11,3,2,-3,31,22,17}; int inorder[] = {-2,6,11,1,3,-1,31,-3,22,2,17}; ConstructTreeFromInOrderPreOrder ctf = new ConstructTreeFromInOrderPreOrder(); Node root = ctf.createTree(inorder, preorder); SinkNegativeToBottom szb = new SinkNegativeToBottom(); szb.sinkZero(root); LevelOrderTraversal lot = new LevelOrderTraversal(); TreeTraversals tt = new TreeTraversals(); tt.inOrder(root); lot.levelOrder(root); } } ================================================ FILE: src/com/interview/tree/SizeOfBinaryTree.java ================================================ package com.interview.tree; /** * Date 03/05/2015 * @author tusroy * * Given a root of binary tree, return size of binar tree * * Solution: * Recursively find size of left side, right side and add one to them and return that to calling function. * * Time complexity - O(n) * Space complexity(because of recursion stack) - height of binary tree. Worst case O(n) * * Test cases: * Null tree * 1 node tree * multi node tree */ public class SizeOfBinaryTree { public int size(Node root){ if(root == null){ return 0; } return size(root.left) + size(root.right) + 1; } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node head = null; head = bt.addNode(10, head); head = bt.addNode(15, head); head = bt.addNode(5, head); head = bt.addNode(7, head); head = bt.addNode(19, head); head = bt.addNode(20, head); head = bt.addNode(-1, head); SizeOfBinaryTree sbt = new SizeOfBinaryTree(); System.out.println(sbt.size(head)); } } ================================================ FILE: src/com/interview/tree/SortedArrayToBST.java ================================================ package com.interview.tree; /** * Date 10/06/2016 * @author Tushar Roy * * Given an array where elements are sorted in ascending order, convert it to a height balanced BST. * * Time complexity O(n) * * Reference * https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/ */ public class SortedArrayToBST { public Node sortedArrayToBST(int[] nums) { return toBST(nums, 0, nums.length - 1); } private Node toBST(int[] nums, int low, int high) { if (low > high) { return null; } int mid = (low + high)/2; Node n = Node.newNode(nums[mid]); n.left = toBST(nums, low, mid - 1); n.right = toBST(nums, mid + 1, high); return n; } } ================================================ FILE: src/com/interview/tree/SortedOrderPrintCompleteTreeArray.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/sorted-order-printing-of-an-array-that-represents-a-bst/ * Test case * empty array * 1 element array * multi element array */ public class SortedOrderPrintCompleteTreeArray { private void print(int arr[],int current){ if(current >= arr.length){ return; } print(arr,2*current+1); System.out.println(arr[current]); print(arr,2*current+2); } public void print(int arr[]){ print(arr,0); } public static void main(String args[]){ int arr[] = {4, 2, 5, 1, 3}; SortedOrderPrintCompleteTreeArray sop = new SortedOrderPrintCompleteTreeArray(); sop.print(arr); } } ================================================ FILE: src/com/interview/tree/SuccinctTree.java ================================================ package com.interview.tree; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; /** * Date 11/01/2015 * @author Tushar * * Encode and decode binary tree using succinct encoding technique * * References - http://www.geeksforgeeks.org/succinct-encoding-of-binary-tree/ * https://en.wikipedia.org/wiki/Binary_tree#Succinct_encodings */ public class SuccinctTree { public static class Result { List binaryRep = new ArrayList<>(); List actualData = new ArrayList<>(); } public Result encode(Node root) { Result r = new Result(); encode(root, r); return r; } private void encode(Node root, Result r) { if(root == null) { r.binaryRep.add(0); return; } r.actualData.add(root.data); r.binaryRep.add(1); encode(root.left, r); encode(root.right, r); } public Node decode(Result r) { AtomicInteger x = new AtomicInteger(0); AtomicInteger y = new AtomicInteger(0); return decode(r, x, y); } private Node decode(Result r, AtomicInteger x, AtomicInteger y) { if(r.binaryRep.get(x.get()) == 0) { x.getAndIncrement(); return null; } Node root = new Node(); root.data = r.actualData.get(y.getAndIncrement()); x.getAndIncrement(); root.left = decode(r, x, y); root.right = decode(r, x, y); return root; } public static void main(String args[]) { Node root = null; BinaryTree bt = new BinaryTree(); root = bt.addNode(10, root); root = bt.addNode(-10, root); root = bt.addNode(20, root); root = bt.addNode(15, root); root = bt.addNode(-7, root); root = bt.addNode(22, root); root = bt.addNode(-4, root); root = bt.addNode(12, root); System.out.println("Before decoding"); TreeTraversals tt = new TreeTraversals(); tt.inOrder(root); System.out.println(); tt.preOrder(root); System.out.println(); SuccinctTree st = new SuccinctTree(); Result r = st.encode(root); root = st.decode(r); System.out.println("After decoding"); tt.inOrder(root); System.out.println(); tt.preOrder(root); } } ================================================ FILE: src/com/interview/tree/SumTree.java ================================================ package com.interview.tree; class Count{ int size; } /** * http://www.geeksforgeeks.org/check-if-a-given-binary-tree-is-sumtree/ * A SumTree is a Binary Tree where the value of a node is equal to sum of the nodes present * in its left subtree and right subtree */ public class SumTree { public boolean isSumTree(Node root){ Count count = new Count(); return isSumTree(root,count); } private boolean isSumTree(Node root,Count count){ if(root == null){ return true; } if(root.left == null && root.right == null){ count.size = root.data; return true; } Count leftCount = new Count(); Count rightCount = new Count(); boolean isLeft = isSumTree(root.left,leftCount); boolean isRight = isSumTree(root.right,rightCount); count.size = root.data + leftCount.size + rightCount.size; return isLeft && isRight && root.data == (leftCount.size + rightCount.size); } public static void main(String args[]){ ConstructTreeFromInOrderPreOrder ctf = new ConstructTreeFromInOrderPreOrder(); int inorder[] = {4,10,6,46,11,13,2}; int preorder[] = {46,10,4,6,13,11,2}; Node root = ctf.createTree(inorder, preorder); SumTree st = new SumTree(); System.out.println(st.isSumTree(root)); } } ================================================ FILE: src/com/interview/tree/TreeIsomorphism.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/tree-isomorphism-problem/ * Test cases: * Same tree * Exact mirror * Some nodes flipped */ public class TreeIsomorphism { public boolean areIsomorphicTrees(Node root1, Node root2) { if (root1 == null && root2 == null) { return true; } if(root1 == null || root2 == null){ return false; } return root1.data == root2.data && ((areIsomorphicTrees(root1.left, root2.left) && areIsomorphicTrees( root1.right, root2.right)) || (areIsomorphicTrees( root1.left, root2.right) && areIsomorphicTrees( root1.right, root2.left))); } public static void main(String args[]){ int in1[] = {8,5,6,10,11,9,12}; int pre1[] = {10,5,8,6,9,11,12}; int in2[] = {11,9,12,10,6,5,15}; int pre2[] = {10,9,11,12,5,6,15}; ConstructTreeFromInOrderPreOrder ct = new ConstructTreeFromInOrderPreOrder(); Node root1 = ct.createTree(in1, pre1); Node root2 = ct.createTree(in2, pre2); TreeIsomorphism ti = new TreeIsomorphism(); System.out.println(ti.areIsomorphicTrees(root1, root2)); } } ================================================ FILE: src/com/interview/tree/TreeTraversalInSpiralOrder.java ================================================ package com.interview.tree; import java.util.Deque; import java.util.LinkedList; import java.util.Stack; /** * Date 04/16/2015 * @author tusroy * * Video link - https://youtu.be/vjt5Y6-1KsQ * * Given a root of binary tree, print in spiral order. * e.g 1 * 2 3 * 4 5 6 7 * 8 9 10 11 * should print 1 3 2 4 5 6 7 8 9 10 11 * * Solution 1 : Use two stack. Put root in stack1. While stack1 is not * empty take items from stack1 and put its child left,right in stack2. * Then once stack1 is empty pop from stack2 and put its child right, * left into stack1. * * Solution 2 : Use one dequeue. Technique is like above but instead of * using two stack use dequeue. Also keep count till which point you read * in the dequeue. * * Solution 3: Use one dequeue. Use a delimiter to separate between one * stack growing from top and another one growing from bottom. * * Time complexity is O(n) * Space complexity is O(n) * * Reference * https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/ */ public class TreeTraversalInSpiralOrder { /** * Two stack to print in spiral way */ public void spiralWithTwoStack(Node root) { if (root == null) { return; } Stack s1 = new Stack<>(); Stack s2 = new Stack<>(); s1.push(root); while (!s1.isEmpty() || !s2.isEmpty()) { while (!s1.isEmpty()) { root = s1.pop(); System.out.print(root.data + " "); if (root.left != null) { s2.push(root.left); } if (root.right != null) { s2.push(root.right); } } while (!s2.isEmpty()) { root = s2.pop(); System.out.print(root.data + " "); if (root.right != null) { s1.push(root.right); } if (root.left != null) { s1.push(root.left); } } } } /** * One deque with count method to print tree in spiral order */ public void spiralWithOneDeque(Node root) { if (root == null) { return; } Deque deque = new LinkedList(); deque.offerFirst(root); int count = 1; boolean flip = true; while (!deque.isEmpty()) { int currentCount = 0; while (count > 0) { if (flip) { root = deque.pollFirst(); System.out.print(root.data + " "); if (root.left != null) { deque.offerLast(root.left); currentCount++; } if (root.right != null) { deque.offerLast(root.right); currentCount++; } } else { root = deque.pollLast(); System.out.print(root.data + " "); if (root.right != null) { deque.offerFirst(root.right); currentCount++; } if (root.left != null) { deque.offerFirst(root.left); currentCount++; } } count--; } flip = !flip; count = currentCount; } } /** * One deque with delimiter to print tree in spiral order */ public void spiralWithOneDequeDelimiter(Node root) { if(root == null){ return; } Deque q = new LinkedList<>(); q.offer(null); q.offerFirst(root); //if only delimiter(in this case null) is left in queue then break while(q.size() > 1){ root = q.peekFirst(); while(root != null){ root = q.pollFirst(); System.out.print(root.data + " "); if(root.left != null){ q.offerLast(root.left); } if(root.right != null){ q.offerLast(root.right); } root = q.peekFirst(); } root = q.peekLast(); while(root != null){ System.out.print(root.data + " "); root = q.pollLast(); if(root.right != null){ q.offerFirst(root.right); } if(root.left != null){ q.offerFirst(root.left); } root = q.peekLast(); } } } public static void main(String args[]) { BinaryTree bt = new BinaryTree(); Node root = null; root = bt.addNode(10, root); root = bt.addNode(30, root); root = bt.addNode(25, root); root = bt.addNode(35, root); root = bt.addNode(-10, root); root = bt.addNode(0, root); root = bt.addNode(-20, root); root = bt.addNode(-15, root); root = bt.addNode(45, root); TreeTraversalInSpiralOrder tt = new TreeTraversalInSpiralOrder(); System.out.println("Two stack method"); tt.spiralWithTwoStack(root); System.out.println("\nOne deque with count"); tt.spiralWithOneDeque(root); System.out.println("\nOne deque with delimiter"); tt.spiralWithOneDequeDelimiter(root); } } ================================================ FILE: src/com/interview/tree/TreeTraversalLevelByLevel.java ================================================ package com.interview.tree; import java.util.LinkedList; import java.util.Queue; /** * Date 04/18/2015 * @author tusroy * * Video link - https://youtu.be/7uG0gLDbhsI * * Given a binary tree print each level on new line. * * e.g 10 * 5 15 * 0 -1 2 6 * Output : 10 * 5 15 * 0 -1 2 6 * * Solution * Technique 1: * Use 2 queue. Keep polling from q1 and offer to q2 till q1 is empty. * After that print a new line. Keep polling from q2 and offer to q1 * till q2 is empty. Keep doing this still both q1 and q2 are empty. * * Technique 2 * Use one queue with delimiter. Add a delimiter null after every level. * As soon as you encounter a null print a new line and add null at end of queue * * Technique 3 * Use one queue with count. Keep count of nodes at every level. As soon as this * count is 0 print a new line. * * Time space complexity for all above algorithm is O(n). */ public class TreeTraversalLevelByLevel { /** * Use two queue to print level by level */ public void levelByLevelTwoQueue(Node root) { if (root == null) { return; } Queue q1 = new LinkedList<>(); Queue q2 = new LinkedList<>(); q1.add(root); while (!q1.isEmpty() || !q2.isEmpty()) { while (!q1.isEmpty()) { root = q1.poll(); System.out.print(root.data + " "); if (root.left != null) { q2.offer(root.left); } if (root.right != null) { q2.offer(root.right); } } System.out.println(); while (!q2.isEmpty()) { root = q2.poll(); System.out.print(root.data + " "); if (root.left != null) { q1.offer(root.left); } if (root.right != null) { q1.offer(root.right); } } System.out.println(); } } /** * Use one queue and delimiter to print level by level */ public void levelByLevelOneQueueUsingDelimiter(Node root) { if (root == null) { return; } Queue q = new LinkedList(); q.offer(root); q.offer(null); while (!q.isEmpty()) { root = q.poll(); if (root != null) { System.out.print(root.data + " "); if (root.left != null) { q.offer(root.left); } if (root.right != null) { q.offer(root.right); } } else { if (!q.isEmpty()) { System.out.println(); q.offer(null); } } } } /** * Use one queue and count to print level by level */ public void levelByLevelOneQueueUsingCount(Node root) { if (root == null) { return; } Queue q = new LinkedList(); int levelCount = 1; int currentCount = 0; q.offer(root); while (!q.isEmpty()) { while (levelCount > 0) { root = q.poll(); System.out.print(root.data + " "); if (root.left != null) { currentCount++; q.offer(root.left); } if (root.right != null) { currentCount++; q.offer(root.right); } levelCount--; } System.out.println(); levelCount = currentCount; currentCount = 0; } } public static void main(String args[]) { TreeTraversalLevelByLevel tt = new TreeTraversalLevelByLevel(); BinaryTree bt = new BinaryTree(); Node root = null; root = bt.addNode(10, root); root = bt.addNode(20, root); root = bt.addNode(30, root); root = bt.addNode(15, root); root = bt.addNode(-10, root); root = bt.addNode(0, root); root = bt.addNode(5, root); root = bt.addNode(-5, root); root = bt.addNode(-15, root); root = bt.addNode(27, root); root = bt.addNode(35, root); System.out.println("1. Two queue technique"); tt.levelByLevelTwoQueue(root); System.out.println("\n2. One queue and delimiter"); tt.levelByLevelOneQueueUsingDelimiter(root); System.out.println("\n\n3. One queue and count"); tt.levelByLevelOneQueueUsingCount(root); } } ================================================ FILE: src/com/interview/tree/TreeTraversals.java ================================================ package com.interview.tree; import java.util.Deque; import java.util.LinkedList; /** * Youtube link - https://youtu.be/nzmtCFNae9k * Youtube link - https://youtu.be/elQcrJrfObg * Youtube link - https://youtu.be/qT65HltK2uE * Youtube link - https://youtu.be/ZM-sV9zQPEs * * http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion/ * http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/ * http://www.geeksforgeeks.org/iterative-preorder-traversal/ */ public class TreeTraversals { public void inOrder(Node root){ if(root == null){ return; } inOrder(root.left); System.out.print(root.data + " "); inOrder(root.right); } public void preOrder(Node root){ if(root == null){ return; } System.out.print(root.data + " "); preOrder(root.left); preOrder(root.right); } public void postOrder(Node root){ if(root == null){ return; } postOrder(root.left); postOrder(root.right); System.out.print(root.data + " "); } public void inorderItr(Node root){ Deque stack = new LinkedList(); Node node = root; while(true){ if(node != null){ stack.addFirst(node); node = node.left; } else{ if(stack.isEmpty()){ break; } node = stack.pollFirst(); System.out.println(node.data); node = node.right; } } } public void preOrderItr(Node root){ Deque stack = new LinkedList(); stack.addFirst(root); while(!stack.isEmpty()){ root = stack.pollFirst(); System.out.print(root.data + " "); if(root.right != null){ stack.addFirst(root.right); } if(root.left!= null){ stack.addFirst(root.left); } } } public void postOrderItr(Node root){ Deque stack1 = new LinkedList(); Deque stack2 = new LinkedList(); stack1.addFirst(root); while(!stack1.isEmpty()){ root = stack1.pollFirst(); if(root.left != null){ stack1.addFirst(root.left); } if(root.right != null){ stack1.addFirst(root.right); } stack2.addFirst(root); } while(!stack2.isEmpty()){ System.out.print(stack2.pollFirst().data + " "); } } public void postOrderItrOneStack(Node root){ Node current = root; Deque stack = new LinkedList<>(); while(current != null || !stack.isEmpty()){ if(current != null){ stack.addFirst(current); current = current.left; }else{ Node temp = stack.peek().right; if (temp == null) { temp = stack.poll(); System.out.print(temp.data + " "); while (!stack.isEmpty() && temp == stack.peek().right) { temp = stack.poll(); System.out.print(temp.data + " "); } } else { current = temp; } } } } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node head = null; head = bt.addNode(10, head); head = bt.addNode(15, head); head = bt.addNode(19, head); head = bt.addNode(17, head); head = bt.addNode(11, head); head = bt.addNode(-11, head); TreeTraversals tt = new TreeTraversals(); tt.postOrder(head); System.out.println(); tt.postOrderItr(head); System.out.println(); tt.postOrderItrOneStack(head); } } ================================================ FILE: src/com/interview/tree/UpsidedownBinaryTree.java ================================================ package com.interview.tree; /** * Given a binary tree where all the right nodes are either leaf nodes with a sibling (a left node that * shares the same parent node) or empty, flip it upside down and turn it into a tree where the original * right nodes turned into left leaf nodes. Return the new root. * * https://leetcode.com/problems/binary-tree-upside-down/ */ public class UpsidedownBinaryTree { public Node upsideDownBinaryTree(Node root) { if (root == null) { return null; } return upsideDownBinaryTree(root, null, null); } public Node upsideDownBinaryTree(Node root, Node parent, Node rightChild) { if (root == null) { return parent; } Node left = root.left; Node right = root.right; root.right = parent; root.left = rightChild; return upsideDownBinaryTree(left, root, right); } } ================================================ FILE: src/com/interview/tree/VertexCoverBinaryTreeDP.java ================================================ package com.interview.tree; /** * http://www.geeksforgeeks.org/vertex-cover-problem-set-2-dynamic-programming-solution-tree/ * http://en.wikipedia.org/wiki/Vertex_cover * Using lis to store the cover data * Test cases: * null root * Only left child * Only right child * Tree with only one child at every node */ public class VertexCoverBinaryTreeDP { public int cover(Node root){ if(root == null){ return 0; } //no need to include leaf node ever if(root.left == null && root.right == null){ return 0; } //store result if(root.lis != -1){ return root.lis; } //if root is included int inclRoot = 1 + cover(root.left) + cover(root.right); int exclRoot = 0; //if root is not included if(root.left!=null){ exclRoot += (1 + cover(root.left.left) + cover(root.left.right)); } if(root.right!=null){ exclRoot += (1 + cover(root.right.left) + cover(root.right.right)); } root.lis = Math.min(inclRoot, exclRoot); return root.lis; } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node root = null; root = bt.addNode(10, root); root = bt.addNode(0, root); root = bt.addNode(-5, root); root = bt.addNode(5, root); root = bt.addNode(7, root); root = bt.addNode(3, root); root = bt.addNode(30, root); root = bt.addNode(40, root); root = bt.addNode(25, root); root = bt.addNode(46, root); root = bt.addNode(-8, root); root = bt.addNode(-2, root); root = bt.addNode(-1, root); root = bt.addNode(28, root); VertexCoverBinaryTreeDP vc = new VertexCoverBinaryTreeDP(); System.out.println(vc.cover(root)); } } ================================================ FILE: src/com/interview/tree/VerticalOrder.java ================================================ package com.interview.tree; import java.util.*; /** * Given a binary tree, return the vertical order traversal of its nodes' values. (ie, from top to bottom, column by column). * If two nodes are in the same row and column, the order should be from left to right. * * https://leetcode.com/problems/binary-tree-vertical-order-traversal/ */ public class VerticalOrder { public List> verticalOrder(Node root) { if (root == null) { return new ArrayList<>(); } int minVal = 0; int maxVal = 0; Map> map = new HashMap<>(); Deque queue = new LinkedList<>(); Deque verticalQueue = new LinkedList<>(); queue.offerFirst(root); verticalQueue.offerFirst(0); int vertical; while (!queue.isEmpty()) { root = queue.pollFirst(); vertical = verticalQueue.pollFirst(); minVal = Math.min(minVal, vertical); maxVal = Math.max(maxVal, vertical); List r = map.get(vertical); if (r == null) { r = new ArrayList<>(); map.put(vertical, r); } r.add(root.data); if (root.left != null) { queue.offerLast(root.left); verticalQueue.offerLast(vertical - 1); } if (root.right != null) { queue.offerLast(root.right); verticalQueue.offerLast(vertical + 1); } } List> result = new ArrayList<>(); for (int i = minVal; i <= maxVal; i++) { List r = map.get(i); result.add(r); } return result; } } ================================================ FILE: src/com/interview/tree/VerticalTreePrinting.java ================================================ package com.interview.tree; import java.util.ArrayList; import java.util.Map; import java.util.List; import java.util.TreeMap; /** * http://www.geeksforgeeks.org/print-binary-tree-vertical-order-set-2/ */ public class VerticalTreePrinting { public void printVertical(Node root){ Map> map = new TreeMap>(); populateMap(root,map,0); printLevel(map); } private void printLevel(Map> map){ for(Integer key : map.keySet()){ List listNodes = map.get(key); for(Node n : listNodes){ System.out.print(n.data + " "); } System.out.println(); } } private void populateMap(Node root, Map> map,int level){ if(root == null){ return; } List listNodes = null; if(map.containsKey(level)){ listNodes = map.get(level); }else{ listNodes = new ArrayList(); map.put(level, listNodes); } listNodes.add(root); populateMap(root.left,map,level-1); populateMap(root.right,map,level+1); } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node head = null; head = bt.addNode(3, head); head = bt.addNode(-6, head); head = bt.addNode(-7, head); head = bt.addNode(2, head); head = bt.addNode(9, head); head = bt.addNode(6, head); head = bt.addNode(11, head); head = bt.addNode(13, head); head = bt.addNode(12, head); VerticalTreePrinting vtp = new VerticalTreePrinting(); vtp.printVertical(head); } } ================================================ FILE: test/com/interview/TestUtil.java ================================================ package com.interview; import org.junit.Assert; import java.util.List; public class TestUtil { public void compareList(List expected, List actual) { int i = 0; for (T str : expected) { Assert.assertEquals("Failed at index " + i, str, actual.get(i++)); } } public void compareListOfList(List> expected, List> actual) { Assert.assertEquals(expected.size(), actual.size()); for (int i = 0; i < expected.size(); i++) { List a1 = expected.get(i); List a2 = expected.get(i); compareList(a1, a2); } } } ================================================ FILE: test/com/interview/array/AdditiveNumberTest.java ================================================ package com.interview.array; import org.junit.Assert; public class AdditiveNumberTest { public static void main(String args[]) { AdditiveNumber additiveNumber = new AdditiveNumber(); Assert.assertTrue(additiveNumber.isAdditiveNumber("12351174")); Assert.assertFalse(additiveNumber.isAdditiveNumber("1023")); Assert.assertTrue(additiveNumber.isAdditiveNumber("198019823962")); } } ================================================ FILE: test/com/interview/array/ArrayAdditionTest.java ================================================ package com.interview.array; import org.junit.Assert; import org.junit.Test; public class ArrayAdditionTest { @Test public void testAddSimple() { ArrayAddition arrayAddition = new ArrayAddition(); int arr1[] = {9,9,9,9,9,9,9}; int arr2[] = {1,6,8,2,6,7}; int[] result = arrayAddition.add(arr1, arr2); int[] expected = {1, 0, 1, 6, 8, 2, 6, 6}; Assert.assertArrayEquals(expected, result); } } ================================================ FILE: test/com/interview/array/MaximumMinimumArrangementTest.java ================================================ package com.interview.array; import org.junit.Assert; import org.junit.Test; public class MaximumMinimumArrangementTest { @Test public void differentCases() { MaximumMinimumArrangement maximumMinimumArrangement = new MaximumMinimumArrangement(); int[] input1 = {1, 2, 3, 4, 5, 6, 7}; maximumMinimumArrangement.rearrange(input1); int[] expected1 = {7, 1, 6, 2, 5, 3, 4}; Assert.assertArrayEquals(expected1, input1); int[] input2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; maximumMinimumArrangement.rearrange(input2); int[] expected2 = {10, 1, 9, 2, 8, 3, 7, 4, 6, 5}; Assert.assertArrayEquals(expected2, input2); } } ================================================ FILE: test/com/interview/array/MeetingRoomsTest.java ================================================ package com.interview.array; import org.junit.Assert; import org.junit.Test; import java.util.Arrays; public class MeetingRoomsTest { @Test public void testDifferentCases() { MeetingRooms meetingRooms = new MeetingRooms(); MeetingRooms.Interval[] interval = new MeetingRooms.Interval[4]; interval[0] = new MeetingRooms.Interval(0,3); interval[1] = new MeetingRooms.Interval(2,5); interval[2] = new MeetingRooms.Interval(6,8); interval[3] = new MeetingRooms.Interval(8,10); Assert.assertEquals(2, meetingRooms.minMeetingRooms(interval)); Assert.assertEquals(2, meetingRooms.minMeetingRooms1(interval)); } } ================================================ FILE: test/com/interview/array/MultiplyAllFieldsExceptOwnPositionTest.java ================================================ package com.interview.array; import org.junit.Assert; import org.junit.Test; public class MultiplyAllFieldsExceptOwnPositionTest { @Test public void testDifferentCases() { MultiplyAllFieldsExceptOwnPosition mop = new MultiplyAllFieldsExceptOwnPosition(); int[] input1 = {0, 9, -2}; int[] output1 = {-18, 0, 0}; Assert.assertArrayEquals(output1, mop.multiply(input1)); int[] input2 = {1, 1}; int[] output2 = {1, 1}; Assert.assertArrayEquals(output2, mop.multiply(input2)); int[] input3 = {3, 1, -3, 6}; int[] output3 = {-18, -54, 18, -9}; Assert.assertArrayEquals(output3, mop.multiply(input3)); } } ================================================ FILE: test/com/interview/array/NumberOfTriangledInUnsortedArrayTest.java ================================================ package com.interview.array; import org.junit.Assert; import org.junit.Test; public class NumberOfTriangledInUnsortedArrayTest { @Test public void testSimpleCase() { NumberOfTrianglesInUnsortedArray numberOfTrianglesInUnsortedArray = new NumberOfTrianglesInUnsortedArray(); int[] input = {3, 4, 5, 6, 8, 9, 15}; int result = numberOfTrianglesInUnsortedArray.numberOfTriangles(input); Assert.assertEquals(15, result); } } ================================================ FILE: test/com/interview/array/ThreeSumSmallerThanTargetTest.java ================================================ package com.interview.array; import junit.framework.Assert; import org.junit.Test; public class ThreeSumSmallerThanTargetTest { @Test public void testDifferentCases() { ThreeSumSmallerThanTarget threeSumSmallerThanTarget = new ThreeSumSmallerThanTarget(); int[] input = {-2, 0, 1, 3}; Assert.assertEquals(2, threeSumSmallerThanTarget.threeSumSmaller(input, 2)); } } ================================================ FILE: test/com/interview/bits/CountingBitsTillNumTest.java ================================================ package com.interview.bits; import org.junit.Assert; import org.junit.Test; /** * Created by tushar_v_roy on 4/3/16. */ public class CountingBitsTillNumTest { @Test public void testDifferentCases() { CountingBitsTillNum countingBitsTillNum = new CountingBitsTillNum(); int[] expected1 = {0, 1, 1}; int[] expected2 = {0, 1, 1, 2, 1, 2}; int[] expected3 = {0, 1, 1, 2, 1, 2, 2, 3, 1}; int[] expected4 = {0, 1, 1, 2, 1, 2, 2, 3 ,1, 2, 2, 3}; Assert.assertArrayEquals(expected1, countingBitsTillNum.countBits(2)); Assert.assertArrayEquals(expected2, countingBitsTillNum.countBits(5)); Assert.assertArrayEquals(expected3, countingBitsTillNum.countBits(8)); Assert.assertArrayEquals(expected4, countingBitsTillNum.countBits(11)); } } ================================================ FILE: test/com/interview/bits/MaxProductWordLengthTest.java ================================================ package com.interview.bits; import org.junit.Assert; import org.junit.Test; public class MaxProductWordLengthTest { @Test public void testDifferentCases() { MaxProductWordLength maxProductWordLength = new MaxProductWordLength(); String[] words1 = {"abcw", "baz", "foo", "bar", "xtfn", "abcdef"}; Assert.assertEquals(16, maxProductWordLength.maxProduct(words1)); String[] words2 = {"a", "ab", "abc", "d", "cd", "bcd", "abcd"}; Assert.assertEquals(4, maxProductWordLength.maxProduct(words2)); } } ================================================ FILE: test/com/interview/dynamic/DecodeWaysTest.java ================================================ package com.interview.dynamic; import org.junit.Test; public class DecodeWaysTest { @Test public void testDifferentCases() { DecodeWays decodeWays = new DecodeWays(); System.out.println(decodeWays.numDecodings("20320")); } } ================================================ FILE: test/com/interview/dynamic/PalindromePartitionTest.java ================================================ package com.interview.dynamic; import org.junit.Assert; import org.junit.Test; import java.util.ArrayList; import java.util.List; public class PalindromePartitionTest { @Test public void testAllPartitions() { PalindromePartition palindromePartition = new PalindromePartition(); List> result = palindromePartition.partition("aab"); List> expected = new ArrayList<>(); List r1 = new ArrayList<>(); r1.add("a"); r1.add("a"); r1.add("b"); expected.add(r1); r1 = new ArrayList<>(); r1.add("aa"); r1.add("b"); expected.add(r1); int index = 0; for (List r : result) { Assert.assertEquals(expected.get(index++), r); } } @Test public void palindromePartitionMinCuts() { PalindromePartition palindromePartition = new PalindromePartition(); Assert.assertEquals(3, palindromePartition.minCut("ABCCDCCLMLCCD")); Assert.assertEquals(0, palindromePartition.minCut("bb")); Assert.assertEquals(0, palindromePartition.minCut("b")); } } ================================================ FILE: test/com/interview/graph/CourseScheduleTest.java ================================================ package com.interview.graph; import org.junit.Assert; import org.junit.Test; public class CourseScheduleTest { @Test public void testDifferentCases() { CourseSchedule cs = new CourseSchedule(); int[][] courses = {{1,0},{2,0},{3,1},{3,2}}; int[] output = cs.findOrder(4, courses); int[] expected = {0, 2, 1, 3}; Assert.assertArrayEquals(expected, output); int[][] courses1 = {{1,0},{2,0},{3,1},{3,2}, {0, 3}}; int[] output1 = cs.findOrder(4, courses1); int[] expected1 = {}; Assert.assertArrayEquals(expected1, output1); } } ================================================ FILE: test/com/interview/graph/TravelingSalesmanHeldKarpTest.java ================================================ package com.interview.graph; import org.junit.Assert; import org.junit.Test; public class TravelingSalesmanHeldKarpTest { @Test public void testDifferentCases() { TravelingSalesmanHeldKarp tsp = new TravelingSalesmanHeldKarp(); int[][] distance = {{0, 12, 3, 9, 6, 1, 2}, {12, 0, 6, 1, 8, 2, 10}, {3, 6, 0, 6, 7, 11, 7}, {9, 1, 6, 0, 9, 10, 3}, {6, 8, 7, 9, 0, 1, 11}, {1, 2, 11, 10, 1, 0, 12}, {2, 10, 7, 3, 11, 12, 0}}; int cost = tsp.minCost(distance); Assert.assertEquals(19, cost); int[][] distance1 = {{0, 1, 15, 6}, {2, 0, 7, 3}, {9, 6, 0, 12}, {10, 4, 8, 0}, }; cost = tsp.minCost(distance1); Assert.assertEquals(21, cost); } } ================================================ FILE: test/com/interview/graph/WallsAndGatesTest.java ================================================ package com.interview.graph; import org.junit.Assert; import org.junit.Test; public class WallsAndGatesTest { @Test public void testDifferentScenarios() { WallsAndGates wallsAndGates = new WallsAndGates(); int INF = Integer.MAX_VALUE; int[][] rooms = {{INF, -1, 0, INF}, {INF, INF, INF, -1}, {INF, -1, INF, -1}, {0, -1, INF, INF}}; int[][] output = {{3, -1, 0, 1}, {2, 2, 1, -1}, {1, -1, 2, -1}, {0, -1, 3, 4}}; wallsAndGates.wallsAndGates(rooms); int i = 0; for (int[] o : output) { Assert.assertArrayEquals(o, rooms[i++]); } } } ================================================ FILE: test/com/interview/linklist/DeleteDuplicateNodesTest.java ================================================ package com.interview.linklist; import org.junit.Test; public class DeleteDuplicateNodesTest { @Test public void testDifferentCases() { DeleteDuplicateNodes deleteDuplicateNodes = new DeleteDuplicateNodes(); LinkList linkList = new LinkList(); Node node = null; node = linkList.addNode(1, node); node = linkList.addNode(2, node); node = linkList.addNode(2, node); deleteDuplicateNodes.deleteDuplicates(node); } } ================================================ FILE: test/com/interview/misc/IntegerListParserTest.java ================================================ package com.interview.misc; import org.junit.Assert; import org.junit.Test; public class IntegerListParserTest { @Test public void testDifferentCases() { IntegerListParser integerListParser = new IntegerListParser(); IntegerListParser.NestedInteger nestedInteger = integerListParser.deserialize("123"); String result = integerListParser.serialize(nestedInteger); Assert.assertEquals("123", result); nestedInteger = integerListParser.deserialize("[]"); result = integerListParser.serialize(nestedInteger); Assert.assertEquals("[]", result); nestedInteger = integerListParser.deserialize("[123]"); result = integerListParser.serialize(nestedInteger); Assert.assertEquals("[123]", result); nestedInteger = integerListParser.deserialize("[123,41]"); result = integerListParser.serialize(nestedInteger); Assert.assertEquals("[123,41]", result); nestedInteger = integerListParser.deserialize("[123,41,[1]]"); result = integerListParser.serialize(nestedInteger); Assert.assertEquals("[123,41,[1]]", result); nestedInteger = integerListParser.deserialize("[123,41,[[[]]]]"); result = integerListParser.serialize(nestedInteger); Assert.assertEquals("[123,41,[[[]]]]", result); nestedInteger = integerListParser.deserialize("[123,41,[[[],[]]],[],[]]"); result = integerListParser.serialize(nestedInteger); Assert.assertEquals("[123,41,[[[],[]]],[],[]]", result); nestedInteger = integerListParser.deserialize("[123,41,[[[121,41,[1]],[2]]],[2],[4]]"); result = integerListParser.serialize(nestedInteger); Assert.assertEquals("[123,41,[[[121,41,[1]],[2]]],[2],[4]]", result); nestedInteger = integerListParser.deserialize("[123,41,[[1,2,[],[]]],[],[],[[1],[3]]]"); result = integerListParser.serialize(nestedInteger); Assert.assertEquals("[123,41,[[1,2,[],[]]],[],[],[[1],[3]]]", result); } } ================================================ FILE: test/com/interview/multiarray/Mutable2DSumRangeQueryTest.java ================================================ package com.interview.multiarray; import org.junit.Assert; import org.junit.Test; public class Mutable2DSumRangeQueryTest { @Test public void testDifferentCases() { int[][] input = {{2, 3, 6}, {-1, 2, 4}, {-3, 2, 5}}; Mutable2DSumRangeQuery mutable2DSumRangeQuery = new Mutable2DSumRangeQuery(input); int total = mutable2DSumRangeQuery.sumRegion(1, 1, 2, 2); Assert.assertEquals(13, total); total = mutable2DSumRangeQuery.sumRegion(0, 1, 2, 1); Assert.assertEquals(7, total); mutable2DSumRangeQuery.update(1, 1, 4); total = mutable2DSumRangeQuery.sumRegion(1, 1, 2, 2); Assert.assertEquals(15, total); total = mutable2DSumRangeQuery.sumRegion(0, 1, 2, 1); Assert.assertEquals(9, total); } } ================================================ FILE: test/com/interview/number/AllStrobogrammaticNumberTest.java ================================================ package com.interview.number; import org.junit.Assert; import org.junit.Test; public class AllStrobogrammaticNumberTest { @Test public void testDifferentCases() { AllStrobogrammaticNumber allStrobogrammaticNumber = new AllStrobogrammaticNumber(); Assert.assertEquals(19, allStrobogrammaticNumber.strobogrammaticInRange("0", "1000")); Assert.assertEquals(34171, allStrobogrammaticNumber.strobogrammaticInRange("1011010", "2210101121121")); } } ================================================ FILE: test/com/interview/number/BasicCalculatorTest.java ================================================ package com.interview.number; import org.junit.Assert; import org.junit.Test; public class BasicCalculatorTest { @Test public void testDifferentCases() { BasicCalculator basicCalculator = new BasicCalculator(); Assert.assertEquals(0, basicCalculator.calculate("0")); Assert.assertEquals(9, basicCalculator.calculate("0 + 9")); Assert.assertEquals(19, basicCalculator.calculate("1 + 9 * 2")); Assert.assertEquals(15, basicCalculator.calculate("3 + 9/2 * 3")); Assert.assertEquals(6, basicCalculator.calculate("8 -2 + 3/ 5 ")); } } ================================================ FILE: test/com/interview/recursion/RestoreIPAddressesTest.java ================================================ package com.interview.recursion; import com.interview.TestUtil; import org.junit.Test; import java.util.ArrayList; import java.util.List; public class RestoreIPAddressesTest { @Test public void testDifferenceCases() { RestoreIPAddresses restoreIPAddresses = new RestoreIPAddresses(); List result = restoreIPAddresses.restoreIpAddresses("25525511135"); List expected = new ArrayList<>(); expected.add("255.255.11.135"); expected.add("255.255.111.35"); TestUtil t = new TestUtil<>(); t.compareList(expected, result); List result1 = restoreIPAddresses.restoreIpAddresses("0000"); expected = new ArrayList<>(); expected.add("0.0.0.0"); t.compareList(expected, result1); } } ================================================ FILE: test/com/interview/string/LongestSubstringWithKDistinctCharactersTest.java ================================================ package com.interview.string; import org.junit.Assert; import org.junit.Test; public class LongestSubstringWithKDistinctCharactersTest { @Test public void testDifferenceCases() { LongestSubstringWithKDistinctCharacters longestSubstringWithKDistinctCharacters = new LongestSubstringWithKDistinctCharacters(); Assert.assertEquals(3, longestSubstringWithKDistinctCharacters.lengthOfLongestSubstringKDistinct("eceba", 2)); Assert.assertEquals(1, longestSubstringWithKDistinctCharacters.lengthOfLongestSubstringKDistinct("aba", 1)); Assert.assertEquals(5, longestSubstringWithKDistinctCharacters.lengthOfLongestSubstringKDistinct("caebegcle", 4)); Assert.assertEquals(0, longestSubstringWithKDistinctCharacters.lengthOfLongestSubstringKDistinct("eceba", 0)); Assert.assertEquals(3, longestSubstringWithKDistinctCharacters.lengthOfLongestSubstringKDistinctUsingMap("eceba", 2)); Assert.assertEquals(1, longestSubstringWithKDistinctCharacters.lengthOfLongestSubstringKDistinctUsingMap("aba", 1)); Assert.assertEquals(5, longestSubstringWithKDistinctCharacters.lengthOfLongestSubstringKDistinctUsingMap("caebegcle", 4)); Assert.assertEquals(0, longestSubstringWithKDistinctCharacters.lengthOfLongestSubstringKDistinctUsingMap("eceba", 0)); } } ================================================ FILE: test/com/interview/string/PalindromePairTest.java ================================================ package com.interview.string; import com.interview.TestUtil; import org.junit.Test; import java.util.ArrayList; import java.util.List; public class PalindromePairTest { @Test public void testDifferentCases() { PalindromePair palindromePair = new PalindromePair(); TestUtil testUtil = new TestUtil(); String[] words = {"bat", "tab"}; List> result = palindromePair.palindromePairs(words); testUtil.compareListOfList(createList(0, 1, 1, 0), result); String[] words1 = {"abcd", "dcba", "lls", "s", "sssll"}; result = palindromePair.palindromePairs(words1); testUtil.compareListOfList(createList(0, 1, 1, 0, 3, 2, 2, 4), result); String[] words2 = {"", "abcd", "abba"}; result = palindromePair.palindromePairs(words2); testUtil.compareListOfList(createList(0, 2, 2, 0), result); String[] words3 = {"a","abc","aba",""}; result = palindromePair.palindromePairs(words3); testUtil.compareListOfList(createList(3, 0, 0, 3, 3, 2, 2, 3), result); String[] words4 = {"abcd","dcba","lls","s","sssll"}; result = palindromePair.palindromePairs(words4); testUtil.compareListOfList(createList(0, 1, 1, 0, 3, 2, 2, 4), result); } private List> createList(int... index) { List> result = new ArrayList<>(); for (int i = 0; i < index.length; i += 2) { List r = new ArrayList<>(); r.add(index[i]); r.add((index[i + 1])); result.add(r); } return result; } } ================================================ FILE: test/com/interview/string/StringEncoderDecoderTest.java ================================================ package com.interview.string; import com.interview.TestUtil; import org.junit.Test; import java.util.ArrayList; import java.util.List; public class StringEncoderDecoderTest { @Test public void testDifferentCases() { StringEncoderDecoder stringEncoderDecoder = new StringEncoderDecoder(); List input = new ArrayList<>(); input.add("Tushar"); input.add("Roy"); input.add(""); String encoded = stringEncoderDecoder.encode(input); List result = stringEncoderDecoder.decode(encoded); TestUtil testUtil = new TestUtil(); testUtil.compareList(input, result); } } ================================================ FILE: test/com/interview/string/ValidPalindromeTest.java ================================================ package com.interview.string; import org.junit.Assert; import org.junit.Test; public class ValidPalindromeTest { @Test public void testDifferentCases() { ValidPalindrome validPalindrome = new ValidPalindrome(); Assert.assertTrue(validPalindrome.isPalindrome("A man, a plan, a canal: Panama")); Assert.assertFalse(validPalindrome.isPalindrome("race a car")); } } ================================================ FILE: test/com/interview/string/ValidWordAbbreviationTest.java ================================================ package com.interview.string; import org.junit.Assert; import org.junit.Test; public class ValidWordAbbreviationTest { @Test public void testDifferentCases() { String[] dict = {"eersynoiyqkqubhdd","ylz","yldongowlrnsafafcgmz","rxcjc","dvgdtnknareecongydc","ixiwz","erjfyctsla","xovvrnbbvivbsuhb","bpslbpzbwphhwvhtcr","wptflnqkvekpkt","hwoiniqvfe","dgidjd","ecgsghxuesvqmhxe","kfgppbbvwfyp","qntzitqjuazrqwz","yjbycoyngfrreiyibdsk","nguqbtdistlgicmjfrs","yjqrqibgp","avulamdverhdpkpqjtae","cbwvtowh","yhgvjnvo","rihywmuspvzvp","rbkpetmovkwj","jtsehilffmfkicusup","ficdolmdtvk","qwldknj","hseogl","pdyxrfdxekk","xnrliooqnsqfzwgd","utnumabyrkasiizsjx","urygh","odj","nttcedxgpkjqzwfb","gxs","rkizfdlfmm","pjlz","fvjm","edkozzeuhxp","pbjcmakwqkdm","ppuhqdpaokitaowrzkfh","yimgbxllumgkbqadjjqf","sqsytssfjbaldz","llkw","aliw","hagvoxjnuuhsafkmxww","hahndehh","fqmrjyuogqpxyv","gnzbcrikf","auopjpwsepqwmend","xfgsbfafytrrkyevtz","acrtfozvjdvg","hspkwabiheogyk","uvlcpqien","eaamufqeal","wsvuyeysox","oywhf","kasdlmnj","fjpryefc","ftdqq","ftfqzqqig","dloh","tleszaz","yajyoyaxmmos","zbobgedfdpacbkzmxt","lmcj","dtjonkbwsg","xeiqjxvsfjdfddclnso","gpeutivfqwzfyrtax","wjoo","pptzwdcynnfpnirfkfo","wsudzgwuouof","ykjmbtoafrjjsehckh","oqhamskusmqofrsgkqfv","yifmkodzvk","vmufzdavpwjagmlcv","dtamuegujvtzdxui","nxdyotptdjdhst","rsthatscf","kdpwhmjtnkunabzaxv","ggzytma","sdypdz","xncvkmcddpkhkoalh","qnjndoizypqqqxewgla","czc","ojhzmxxceltwzg","hmwvynbzpuebokl","weuuontazzovia","ohwqtugyirw","lrtftghr","fngstcishaseslmb","athpsapnlyx","tcdnqc","fjfyvg","fneurgd","xddiwjfbshgfbbejmpe","ynscraxwlwsqhsioe","eaderhxrlwrjpp","wpnlrfxgnbfpuuiggsvo","ogqmzw","xai","fdtbvhaosybjczyfcsdx","abbcbqhcuoiaggs","qtdwhsqqjt","dqdvabloavvjhunafwhw","gcpqevfuos","hipvttjbniv","acheeyf","seqrnvez","hszzzvbvmhjg","kkwpshwuvsrbjqm","jqxo","sukagbkkrvbquzkfsj","axbrmcroycbyykkdhl","zrtshq","cgwssttvz","nbwccbisxtkccgmkmped","ivplojduvs","wmblfkhtnj","jeoodscttkmjrszzjgh","qmadddn","ssdauwepilwi","wghuntzaltedkacttafj","rxojnfrleq","qzkuejnvhncjzc","cromyllbcleqipqaitzd","yjdzifptqtcmrfyjrfj","svinvs","uftn"}; ValidWordAbbreviation validWordAbbreviation = new ValidWordAbbreviation(dict); Assert.assertTrue(validWordAbbreviation.isUnique("hello")); } } ================================================ FILE: test/com/interview/suffixprefix/TrieTest.java ================================================ package com.interview.suffixprefix; import org.junit.Assert; import org.junit.Test; public class TrieTest { @Test public void testDifferentCases() { Trie trie = new Trie(); trie.insert("abcd"); trie.insert("abgl"); trie.insertRecursive("lmn"); trie.insertRecursive("lmnpq"); trie.insert("cdeg"); trie.insert("ghijk"); Assert.assertFalse(trie.search("ab")); Assert.assertFalse(trie.search("abc")); Assert.assertTrue(trie.search("abcd")); Assert.assertFalse(trie.search("abg")); Assert.assertTrue(trie.search("abgl")); Assert.assertFalse(trie.search("lm")); Assert.assertTrue(trie.search("lmn")); Assert.assertFalse(trie.search("lmnp")); Assert.assertTrue(trie.search("lmnpq")); trie.delete("abcd"); Assert.assertTrue(trie.search("abgl")); Assert.assertFalse(trie.search("abcd")); trie.delete("lmn"); Assert.assertFalse(trie.search("lmn")); Assert.assertTrue(trie.search("lmnpq")); trie.delete("lmnpq"); Assert.assertFalse(trie.search("lmnpq")); } } ================================================ FILE: test/com/interview/tree/KClosestValueInBinaryTreeTest.java ================================================ package com.interview.tree; import com.interview.TestUtil; import org.junit.Test; import java.util.Arrays; import java.util.List; public class KClosestValueInBinaryTreeTest { @Test public void testDifferentCases() { Node root = null; BinaryTree bt = new BinaryTree(); root = bt.addNode(10, root); root = bt.addNode(20, root); root = bt.addNode(30, root); root = bt.addNode(0, root); root = bt.addNode(6, root); root = bt.addNode(-6, root); root = bt.addNode(16, root); root = bt.addNode(19, root); KClosestValueInBinaryTree kClosestValueInBinaryTree = new KClosestValueInBinaryTree(); List result = kClosestValueInBinaryTree.closestKValues(root, 18, 2); TestUtil testUtil = new TestUtil(); testUtil.compareList(Arrays.asList(19, 20), result); result = kClosestValueInBinaryTree.closestKValues(root, 18, 4); testUtil.compareList(Arrays.asList(19, 20, 16, 10), result); } } ================================================ FILE: test/com/interview/tree/VerticalOrderTest.java ================================================ package com.interview.tree; import com.interview.TestUtil; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class VerticalOrderTest { @Test public void testDifferentCases() { SerializeDeserializeBinaryTree serializeDeserializeBinaryTree = new SerializeDeserializeBinaryTree(); Node root = serializeDeserializeBinaryTree.deserializeLevelOrder("5,1,6,%,3,%,%,2,4"); VerticalOrder verticalOrder = new VerticalOrder(); List> result = verticalOrder.verticalOrder(root); List> expected = new ArrayList<>(); expected.add(Arrays.asList(1, 2)); expected.add(Arrays.asList(5, 3)); expected.add(Arrays.asList(6, 4)); int index = 0; TestUtil t = new TestUtil<>(); for (List r : result) { t.compareList(expected.get(index++), r); } expected = new ArrayList<>(); expected.add(Arrays.asList(9)); expected.add(Arrays.asList(3, 15)); expected.add(Arrays.asList(20)); expected.add(Arrays.asList(7)); root = serializeDeserializeBinaryTree.deserializeLevelOrder("3,9,20,%,%,15,7"); result = verticalOrder.verticalOrder(root); index = 0; for (List r : result) { t.compareList(expected.get(index++), r); } } }