cols) {
+ for (int row : rows) {
+ // make entire row zero
+ for (int c = 0; c < matrix[0].length; c++) {
+ matrix[row][c] = 0;
+ }
+ }
+ for (int col : cols) {
+ // make entire column zero
+ for (int r = 0; r < matrix.length; r++) {
+ matrix[r][col] = 0;
+ }
+ }
+ }
+
+ private static void printMatrix(int[][] matrix) {
+ for (int i = 0; i < matrix.length; i++) {
+ for (int j = 0; j < matrix[0].length; j++) {
+ System.out.print(matrix[i][j]);
+ if (j + 1 >= matrix[0].length) {
+ System.out.println();
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ int[][] m = new int[][]{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
+ printMatrix(m);
+ zeroMatrix(m);
+ System.out.println("---");
+ printMatrix(m);
+ System.out.println("---");
+ m = new int[][]{{1, 0, 2}, {3, 4, 5}, {6, 7, 8}};
+ printMatrix(m);
+ zeroMatrix(m);
+ System.out.println("---");
+ printMatrix(m);
+ System.out.println("---");
+ m = new int[][]{{1, 2, 0}, {3, 4, 5}, {6, 7, 8}};
+ printMatrix(m);
+ zeroMatrix(m);
+ System.out.println("---");
+ printMatrix(m);
+ System.out.println("---");
+ }
+}
diff --git a/src/main/java/com/ctci/bitmanipulation/BinaryToString.java b/src/main/java/com/ctci/bitmanipulation/BinaryToString.java
new file mode 100644
index 00000000..895c354a
--- /dev/null
+++ b/src/main/java/com/ctci/bitmanipulation/BinaryToString.java
@@ -0,0 +1,48 @@
+package com.ctci.bitmanipulation;
+
+/**
+ * @author rampatra
+ * @since 2019-03-16
+ */
+public class BinaryToString {
+
+ /**
+ * Given a real number between 0 and 1 (e.g., 0.72) that is passed in as a double, print the binary representation.
+ * If the number cannot be represented accurately in binary with at most 32 characters, print "ERROR."
+ *
+ * @param realNum a real number between 0 and 1 (for ex. 0.75)
+ * @return binary string of the real number
+ * @see how to convert decimal fraction to binary
+ */
+ private static String decimalFractionToBinaryString(double realNum) {
+ if (realNum <= 0 || realNum >= 1) {
+ return "ERROR";
+ }
+
+ int binaryBit;
+ StringBuilder sb = new StringBuilder();
+ sb.append("0.");
+
+ while (realNum > 0) {
+ if (sb.length() == 32) {
+ return "ERROR";
+ }
+ realNum = realNum * 2;
+ // the binary bit is the whole number part (left to the decimal)
+ binaryBit = (int) realNum;
+ // we only have to take the part after the decimal (right to the decimal) for the next iteration
+ if (binaryBit == 1) {
+ realNum -= 1;
+ }
+ sb.append(binaryBit);
+ }
+ return sb.toString();
+ }
+
+ public static void main(String[] args) {
+ System.out.println(decimalFractionToBinaryString(0.625));
+ System.out.println(decimalFractionToBinaryString(0.75));
+ System.out.println(decimalFractionToBinaryString(0.72));
+ System.out.println(decimalFractionToBinaryString(0.10));
+ }
+}
diff --git a/src/main/java/com/ctci/bitmanipulation/Conversion.java b/src/main/java/com/ctci/bitmanipulation/Conversion.java
new file mode 100644
index 00000000..5a4c7575
--- /dev/null
+++ b/src/main/java/com/ctci/bitmanipulation/Conversion.java
@@ -0,0 +1,63 @@
+package com.ctci.bitmanipulation;
+
+/**
+ * @author rampatra
+ * @since 2019-03-17
+ */
+public class Conversion {
+
+ /**
+ * Write a function to determine the number of bits you would need to flip to convert
+ * integer A to integer B.
+ * Example:
+ * Input: 29 (or: 11101), 15 (or: 01111)
+ * Output: 2
+ *
+ * @param a
+ * @param b
+ * @return the number of bits to flip
+ */
+ private static int getNoOfBitsToFlipToConvertAToB(int a, int b) {
+ return countSetBits(a ^ b);
+ }
+
+ private static int countSetBits(int n) {
+ int count = 0;
+ while (n > 0) {
+ if ((n & 1) == 1) {
+ count++;
+ }
+ n >>>= 1;
+ }
+ return count;
+ }
+
+ /**
+ * In this approach, we first take the xor of both the integers (which sets the bits at positions where the bits
+ * in a and b are different). We then unset the least significant bit in each iteration (c & (c - 1)) and count the
+ * number of iterations to find the bits to flip.
+ *
+ * @param a
+ * @param b
+ * @return the number of bits to flip
+ */
+ private static int getNoOfBitsToFlipToConvertAToBWithoutRightShift(int a, int b) {
+ int count = 0;
+ for (int c = a ^ b; c != 0; c = c & (c - 1)) {
+ count++;
+ }
+ return count;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(getNoOfBitsToFlipToConvertAToB(5, 7));
+ System.out.println(getNoOfBitsToFlipToConvertAToB(5, 5));
+ System.out.println(getNoOfBitsToFlipToConvertAToB(29, 15));
+
+ System.out.println("---");
+
+ System.out.println(getNoOfBitsToFlipToConvertAToBWithoutRightShift(5, 7));
+ System.out.println(getNoOfBitsToFlipToConvertAToBWithoutRightShift(5, 5));
+ System.out.println(getNoOfBitsToFlipToConvertAToBWithoutRightShift(29, 15));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/bitmanipulation/Debugger.java b/src/main/java/com/ctci/bitmanipulation/Debugger.java
new file mode 100644
index 00000000..6782036b
--- /dev/null
+++ b/src/main/java/com/ctci/bitmanipulation/Debugger.java
@@ -0,0 +1,30 @@
+package com.ctci.bitmanipulation;
+
+/**
+ * @author rampatra
+ * @since 2019-03-17
+ */
+public class Debugger {
+
+ /**
+ * If after un-setting the least significant bit in n, it becomes 0 then it implies that it has only set bit. This
+ * can also imply that n is a power of 2.
+ *
+ * @param n input integer
+ * @return {@code true} if n has only set bit, {@code false} otherwise.
+ */
+ private static boolean hasOneSetBit(int n) {
+ // edge case
+ if (n == 0) {
+ return false;
+ }
+ return (n & (n - 1)) == 0; // (n & (n - 1)) un-sets the least significant bit
+ }
+
+ public static void main(String[] args) {
+ System.out.println(hasOneSetBit(0));
+ System.out.println(hasOneSetBit(2));
+ System.out.println(hasOneSetBit(16));
+ System.out.println(hasOneSetBit(10));
+ }
+}
diff --git a/src/main/java/com/ctci/bitmanipulation/DrawLine.java b/src/main/java/com/ctci/bitmanipulation/DrawLine.java
new file mode 100644
index 00000000..3eb2be0c
--- /dev/null
+++ b/src/main/java/com/ctci/bitmanipulation/DrawLine.java
@@ -0,0 +1,109 @@
+package com.ctci.bitmanipulation;
+
+import java.util.Arrays;
+
+/**
+ * @author rampatra
+ * @since 2019-03-21
+ */
+public class DrawLine {
+
+ /**
+ * A monochrome screen is stored as a single array of bytes, allowing eight consecutive pixels to be stored
+ * in one byte. The screen has width w, where w is divisible by 8 (that is, no byte will be split across rows).
+ * The height of the screen, of course, can be derived from the length of the array and the width. Implement a
+ * function that draws a horizontal line from (xl, y) to ( x2, y).
+ *
+ * The method signature should look something like:
+ * {@code drawline(byte[] screen, int width, int xl, int x2, int y)}
+ *
+ * Approach:
+ * First, find the numbers in which all bits has to be set. Next, find the starting number and apply the mask
+ * created from the starting offset. Do the same with the ending number.
+ *
+ * @param screen
+ * @param width
+ * @param x1
+ * @param x2
+ * @param y
+ */
+ private static void drawLine(byte[] screen, int width, int x1, int x2, int y) {
+ int startOffset = x1 % 8;
+ int startFullByte = x1 / 8;
+ if (startOffset != 0) {
+ startFullByte++;
+ }
+ int endOffset = x2 % 8;
+ int endFullByte = x2 / 8;
+ if (endOffset != 7) {
+ endFullByte--;
+ }
+
+ // all bits have to be set in in-between numbers
+ for (int i = startFullByte; i <= endFullByte; i++) {
+ screen[width / 8 * y + i] |= (byte) 0xff;
+ }
+
+ /* 0xff is an integer literal which is like 000...11111111 (32 bits) but when we
+ cast it to a byte, we get rid of the initial 24 bits */
+ byte startByteMask = (byte) (0xff >> startOffset);
+ byte endByteMask = (byte) ~(0xff >> endOffset + 1);
+
+ if (x1 / 8 == x2 / 8) { // if starting and ending both lie in the same byte
+ screen[width / 8 * y + (x1 / 8)] |= (startByteMask & endByteMask);
+ } else {
+ screen[width / 8 * y + (startFullByte - 1)] |= startByteMask; // only specific bits set in the starting number
+ screen[width / 8 * y + (endFullByte + 1)] |= endByteMask; // only specific bits set in the ending number
+ }
+ }
+
+ public static void main(String[] args) {
+ /*
+ Consider the below screen with width 32 as an example:
+
+ byte[] screen = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+
+ This screen has a width of 32 so you can assume the screen would be looking like:
+
+ 9 10 11 12
+ 5 6 7 8
+ 1 2 3 4
+
+ x-axis is 5-20 (5th position to 20th position)
+ y-axis is 1
+
+ which means our line would lie in numbers 5, 6, and 7
+
+ so if you visualize these numbers in bits, it would be like:
+
+ 00000101 00000110 00000111
+ ^ ^
+ and after drawing the line, the bits would become:
+
+ 00000111 11111111 11111111
+
+ and in the output we would see:
+
+ 7, -1, -1 instead of 5, 6, 7
+ */
+ byte[] screen = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+ System.out.println("Input: " + Arrays.toString(screen));
+ drawLine(screen, 32, 5, 20, 1);
+ System.out.println("Output: " + Arrays.toString(screen));
+ System.out.println("---");
+ screen = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+ System.out.println("Input: " + Arrays.toString(screen));
+ drawLine(screen, 32, 0, 5, 1);
+ System.out.println("Output: " + Arrays.toString(screen));
+ System.out.println("---");
+ screen = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+ System.out.println("Input: " + Arrays.toString(screen));
+ drawLine(screen, 32, 3, 7, 1);
+ System.out.println("Output: " + Arrays.toString(screen));
+ System.out.println("---");
+ screen = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+ System.out.println("Input: " + Arrays.toString(screen));
+ drawLine(screen, 16, 0, 7, 0);
+ System.out.println("Output: " + Arrays.toString(screen));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/bitmanipulation/FlipBitToWin.java b/src/main/java/com/ctci/bitmanipulation/FlipBitToWin.java
new file mode 100644
index 00000000..4424f7ab
--- /dev/null
+++ b/src/main/java/com/ctci/bitmanipulation/FlipBitToWin.java
@@ -0,0 +1,53 @@
+package com.ctci.bitmanipulation;
+
+/**
+ * @author rampatra
+ * @since 2019-03-16
+ */
+public class FlipBitToWin {
+
+ /**
+ * You have an integer and you can flip exactly one bit from a O to a 1. Write code to find the length of the
+ * longest sequence of 1s you could create.
+ * Example:
+ * Input: 1775 (or: 11011101111)
+ * Output: 8
+ *
+ * Approach:
+ * We just walk through the integer tracking the current 1s sequence length and the previous 1s sequence length.
+ * When we see a zero, update previous length as follows:
+ * - If the next bit is a 1, previous Length should be set to current Length.
+ * - If the next bit is a 0, then we can't merge these sequences together. So, set previous Length to 0.
+ *
+ * @param n an integer
+ * @return the longest sequence of set bits in {@code n} by flipping only one zero bit
+ */
+ private static int findLongestSequence(int n) {
+ // if all bits are set, return the total number of bits in an integer
+ if (n == ~0) {
+ return Integer.BYTES * 8;
+ }
+
+ int prevOnesLen = 0;
+ int currOnesLen = 0;
+ int maxOnesLen = 0;
+
+ while (n > 0) {
+ // if the current bit is 0, reset the currOnesLen
+ if ((n & 1) == 0) {
+ prevOnesLen = (n & 2) == 0 ? 0 : currOnesLen; // if the next bit is also 0, set prevOnesLen to 0
+ currOnesLen = 0;
+ } else {
+ currOnesLen++;
+ }
+ n >>>= 1;
+ maxOnesLen = Math.max(maxOnesLen, prevOnesLen + 1 + currOnesLen);
+ }
+ return maxOnesLen;
+ }
+
+ public static void main(String[] args) {
+ System.out.println("Longest seq in " + Integer.toBinaryString(125) + " is " + findLongestSequence(125));
+ System.out.println("Longest seq in " + Integer.toBinaryString(1275) + " is " + findLongestSequence(1275));
+ }
+}
diff --git a/src/main/java/com/ctci/bitmanipulation/Insertion.java b/src/main/java/com/ctci/bitmanipulation/Insertion.java
new file mode 100644
index 00000000..3230d86f
--- /dev/null
+++ b/src/main/java/com/ctci/bitmanipulation/Insertion.java
@@ -0,0 +1,49 @@
+package com.ctci.bitmanipulation;
+
+/**
+ * @author rampatra
+ * @since 2019-03-14
+ */
+public class Insertion {
+
+ /**
+ * You are given two 32-bit numbers, N and M, and two bit positions, startIndex and endIndex. Write a method to
+ * insert M into N such that M starts at bit startIndex and ends at bit endIndex. You can assume that the bits
+ * startIndex through endIndex have enough space to fit all of M. That is, if M = 10011, you can assume that there
+ * are at least 5 bits between j and i. You would not, for example, have startIndex = 3 and endIndex = 2, because
+ * M could not fully fit between bit 3 and bit 2.
+ *
+ * EXAMPLE
+ * Input: N = 10000000000, M = 10011, startIndex = 6, endIndex = 2
+ * Output: 10001001100
+ *
+ * @param n
+ * @param m
+ * @param startIndex
+ * @param endIndex
+ * @return
+ */
+ private static int insertMIntoN(int n, int m, int startIndex, int endIndex) {
+ // create a mask with only one bit set
+ int mask = 1;
+ // shift the set bit so that it starts with endIndex
+ mask <<= endIndex;
+
+ // unset the bits in 'n' from endIndex to startIndex
+ for (int i = endIndex; i <= startIndex; i++) {
+ n = n & ~mask; // ~mask will make the bit at ith index 0 but the rest of the bits will be 1
+ mask <<= 1;
+ }
+
+ // shift 'm' so that it lines up with bits from startIndex to endIndex
+ m <<= endIndex;
+
+ // finally, return the xor of both as we know that 0 ^ a = a
+ return n ^ m;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(Integer.toBinaryString(insertMIntoN(Integer.parseInt("10000000000", 2), Integer.parseInt("10011", 2), 6, 2)));
+ System.out.println(Integer.toBinaryString(insertMIntoN(Integer.parseInt("10110110111", 2), Integer.parseInt("11101", 2), 7, 3)));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/bitmanipulation/NextNumber.java b/src/main/java/com/ctci/bitmanipulation/NextNumber.java
new file mode 100644
index 00000000..ec817c13
--- /dev/null
+++ b/src/main/java/com/ctci/bitmanipulation/NextNumber.java
@@ -0,0 +1,124 @@
+package com.ctci.bitmanipulation;
+
+/**
+ * @author rampatra
+ * @since 2019-03-17
+ */
+public class NextNumber {
+
+ private static class NextLargerAndSmallerNumber {
+ int nextLarger;
+ int nextSmaller;
+ }
+
+ /**
+ * Given a positive integer, print the next smallest and the next largest number that have the same number of
+ * 1 bits in their binary representation.
+ *
+ * @param n a positive integer.
+ * @return an object containing the next larger and next smaller number containing the identical set bits.
+ */
+ private static NextLargerAndSmallerNumber getNextLargerAndSmallerNumber(int n) {
+ NextLargerAndSmallerNumber result = new NextLargerAndSmallerNumber();
+ result.nextLarger = getNextLarger(n);
+ result.nextSmaller = getNextSmaller(n);
+ return result;
+ }
+
+ private static int getNextLarger(int n) {
+ int rightmostNonTrailingZero = 0;
+ int noOfZeros = 0;
+ int noOfOnes = 0;
+ int temp = n;
+
+ /* Count the number of zeros and ones until the rightmost non-trailing zero
+ For example, see below:
+
+ n = 10110110011110
+ ^
+ */
+ while ((temp & 1) == 0 && temp != 0) {
+ noOfZeros++;
+ temp >>>= 1;
+ }
+
+ while ((temp & 1) == 1 && temp != 0) {
+ noOfOnes++;
+ temp >>>= 1;
+ }
+
+ if (noOfZeros + noOfOnes == 31 || noOfZeros + noOfOnes == 0) {
+ return -1;
+ }
+
+ /* Flip the bit and then shift all the 1s to the right end and then fill with 0s until the bit pattern '01.
+ For example, consider the above number:
+ n = 10110110011110 (original)
+ ^
+ n = 10110110111110 (after flip bit)
+ ^
+ next larger = 10110110100111 (the 1s are shifted to the right end and 0s to the left but before the rightmostNonTrailingZero)
+ ^
+ */
+ rightmostNonTrailingZero = noOfOnes + noOfZeros;
+ n |= 1 << rightmostNonTrailingZero; // set the rightmost non-trailing zero
+ n &= ~((1 << rightmostNonTrailingZero) - 1); // unset all bits until rightmost non-trailing zero
+ n |= (1 << noOfOnes - 1) - 1; // set (noOfOnes - 1) bits from the right
+
+ return n;
+ }
+
+ private static int getNextSmaller(int n) {
+ int rightmostNonTrailingOne = 0;
+ int noOfZeros = 0;
+ int noOfOnes = 0;
+ int temp = n;
+
+ while ((temp & 1) == 1 && temp != 0) {
+ noOfOnes++;
+ temp >>>= 1;
+ }
+
+ if (temp == 0) {
+ return -1;
+ }
+
+ while ((temp & 1) == 0 && temp != 0) {
+ noOfZeros++;
+ temp >>>= 1;
+ }
+
+ rightmostNonTrailingOne = noOfZeros + noOfOnes;
+ n &= ~(1 << rightmostNonTrailingOne); // unset the rightmost non-trailing one
+ n |= (1 << rightmostNonTrailingOne - 1); // set all the bits until rightmost non-trailing one
+ n &= ~((1 << noOfZeros - 1) - 1); // unset (noOfZeros - 1) bits from the right
+
+ return n;
+ }
+
+ public static void main(String[] args) {
+ NextLargerAndSmallerNumber of0 = getNextLargerAndSmallerNumber(0);
+ System.out.println("Next larger of 0: " + of0.nextLarger);
+ System.out.println("Next smaller of 0: " + of0.nextSmaller);
+
+ NextLargerAndSmallerNumber of2 = getNextLargerAndSmallerNumber(2);
+ System.out.println("Next larger of 2: " + of2.nextLarger);
+ System.out.println("Next smaller of 2: " + of2.nextSmaller);
+
+ NextLargerAndSmallerNumber of5 = getNextLargerAndSmallerNumber(5);
+ System.out.println("Next larger of 5: " + of5.nextLarger);
+ System.out.println("Next smaller of 5: " + of5.nextSmaller);
+
+ NextLargerAndSmallerNumber of7 = getNextLargerAndSmallerNumber(7);
+ System.out.println("Next larger of 7: " + of7.nextLarger);
+ System.out.println("Next smaller of 7: " + of7.nextSmaller);
+
+ NextLargerAndSmallerNumber of8 = getNextLargerAndSmallerNumber(8);
+ System.out.println("Next larger of 8: " + of8.nextLarger);
+ System.out.println("Next smaller of 8: " + of8.nextSmaller);
+
+ NextLargerAndSmallerNumber of15 = getNextLargerAndSmallerNumber(15);
+ System.out.println("Next larger of 15: " + of15.nextLarger);
+ System.out.println("Next smaller of 15: " + of15.nextSmaller);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/bitmanipulation/PairwiseSwap.java b/src/main/java/com/ctci/bitmanipulation/PairwiseSwap.java
new file mode 100644
index 00000000..a1219d47
--- /dev/null
+++ b/src/main/java/com/ctci/bitmanipulation/PairwiseSwap.java
@@ -0,0 +1,40 @@
+package com.ctci.bitmanipulation;
+
+/**
+ * @author rampatra
+ * @since 2019-03-18
+ */
+public class PairwiseSwap {
+
+ /**
+ * Write a program to swap odd and even bits in an integer with as few instructions as
+ * possible (e.g., bit O and bit 1 are swapped, bit 2 and bit 3 are swapped, and so on).
+ *
+ * Approach:
+ * Shift the odd bits to the left, shift the even bits to the right, and finally, OR both the results.
+ * Note: You can operate on only odd bits or only even bits by using the appropriate masks, for e.g.,
+ * 0x55555555 for odd bits and 0xaaaaaaaa for even bits.
+ *
+ * @param n an input integer.
+ * @return an integer with even and odd bits swapped.
+ */
+ private static int swapBits(int n) {
+ return ((n & 0x55555555) << 1) | ((n & 0xaaaaaaaa) >>> 1);
+ }
+
+ public static void main(String[] args) {
+ System.out.println("Input: " + Integer.toBinaryString(1569) +
+ "\nOutput: " + Integer.toBinaryString(swapBits(1569)));
+
+ assert Integer.toBinaryString(swapBits(1569)).equals("100100010010");
+
+ System.out.println("Input: " + Integer.toBinaryString(2680) +
+ "\nOutput: " + Integer.toBinaryString(swapBits(2680)));
+
+ assert Integer.toBinaryString(swapBits(2680)).equals("10110110100");
+
+ // fyi
+ System.out.println(Integer.toBinaryString(0x55555555));
+ System.out.println(Integer.toBinaryString(0xaaaaaaaa));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/linkedlists/DeleteMiddleNode.java b/src/main/java/com/ctci/linkedlists/DeleteMiddleNode.java
new file mode 100644
index 00000000..c4b4052e
--- /dev/null
+++ b/src/main/java/com/ctci/linkedlists/DeleteMiddleNode.java
@@ -0,0 +1,65 @@
+package com.ctci.linkedlists;
+
+/**
+ * @author rampatra
+ * @since 2019-01-27
+ */
+public class DeleteMiddleNode {
+
+ /**
+ * Implement an algorithm to delete a node in the middle (i.e., any node but the first and last node, not
+ * necessarily the exact middle) of a singly linked list, given only access to that node.
+ *
+ * EXAMPLE
+ * Input: the node c from the linked list a->b->c->d->e->f
+ * Result: nothing is returned, but the new linked list looks like a->b->d->e->f
+ *
+ * @param middle the node to be deleted
+ */
+ private static void deleteMiddleNode(Node middle) {
+ if (middle == null || middle.next == null) {
+ return;
+ }
+ // copy the data from the next node over to the middle node, and then to delete the next node
+ Node next = middle.next;
+ middle.val = next.val;
+ middle.next = next.next;
+ }
+
+ public static void main(String[] args) {
+ Node l1 = new Node(1);
+ l1.next = new Node(2);
+ l1.next.next = new Node(3);
+ l1.next.next.next = new Node(4);
+ l1.next.next.next.next = new Node(5);
+ l1.next.next.next.next.next = new Node(6);
+ l1.print();
+ deleteMiddleNode(l1.next.next);
+ l1.print();
+
+ System.out.println("----");
+
+ l1 = new Node(1);
+ l1.next = new Node(2);
+ l1.next.next = new Node(3);
+ l1.print();
+ deleteMiddleNode(l1.next);
+ l1.print();
+
+ System.out.println("----");
+
+ l1 = new Node(1);
+ l1.next = new Node(3);
+ l1.print();
+ deleteMiddleNode(l1);
+ l1.print();
+
+ System.out.println("----");
+
+ l1 = new Node(1);
+ l1.next = new Node(3);
+ l1.print();
+ deleteMiddleNode(l1.next);
+ l1.print();
+ }
+}
diff --git a/src/main/java/com/ctci/linkedlists/Intersection.java b/src/main/java/com/ctci/linkedlists/Intersection.java
new file mode 100644
index 00000000..4665fe43
--- /dev/null
+++ b/src/main/java/com/ctci/linkedlists/Intersection.java
@@ -0,0 +1,104 @@
+package com.ctci.linkedlists;
+
+/**
+ * @author rampatra
+ * @since 2019-02-02
+ */
+public class Intersection {
+
+ /**
+ * Given two (singly) linked lists, determine if the two lists intersect. Return the intersecting node. Note that
+ * the intersection is defined based on reference, not value. That is, if the kth node of the first linked list is
+ * the exact same node (by reference) as the jth node of the second linked list, then they are intersecting.
+ *
+ * @param n1
+ * @param n2
+ * @return the intersecting node, {@code null} otherwise.
+ */
+ private static Node findIntersectingNode(Node n1, Node n2) {
+ Node curr1 = n1;
+ Node curr2 = n2;
+ int len1 = 1;
+ int len2 = 1;
+
+ /* Calculate the length of both linked lists */
+ while (curr1 != null && curr1.next != null) {
+ len1++;
+ curr1 = curr1.next;
+ }
+ while (curr2 != null && curr2.next != null) {
+ len2++;
+ curr2 = curr2.next;
+ }
+
+ // if different tail nodes, they don't intersect
+ if (curr1 != curr2) {
+ return null;
+ }
+
+ curr1 = n1;
+ curr2 = n2;
+
+ /* Get rid of the extra nodes from the longer list */
+ if (len1 > len2) {
+ for (int i = 0; i < len1 - len2; i++) {
+ curr1 = curr1.next;
+ }
+ }
+ if (len2 > len1) {
+ for (int i = 0; i < len2 - len1; i++) {
+ curr2 = curr2.next;
+ }
+ }
+
+ // move both pointers until you have a collision
+ while (curr1 != curr2) {
+ curr1 = curr1.next;
+ curr2 = curr2.next;
+ }
+
+ // return either
+ return curr1;
+ }
+
+ public static void main(String[] args) {
+ Node l1 = new Node(1);
+ l1.next = new Node(2);
+ l1.next.next = new Node(3);
+ l1.next.next.next = new Node(4);
+ l1.next.next.next.next = new Node(5);
+ l1.next.next.next.next.next = new Node(5);
+ Node l2 = new Node(1);
+ l2.next = new Node(4);
+ l2.next.next = new Node(2);
+ l2.next.next.next = new Node(3);
+ l2.next.next.next.next = l1.next.next.next;
+ l1.print();
+ l2.print();
+ System.out.println(findIntersectingNode(l1, l2).val); // may throw NPE, not handling for the sake of simplicity
+
+ System.out.println("----");
+
+ l1 = new Node(1);
+ l2 = l1;
+ l1.print();
+ l2.print();
+ System.out.println(findIntersectingNode(l1, l2).val); // may throw NPE, not handling for the sake of simplicity
+
+ System.out.println("----");
+
+ l1 = new Node(1);
+ l1.next = new Node(2);
+ l1.next.next = new Node(3);
+ l1.next.next.next = new Node(4);
+ l1.next.next.next.next = new Node(5);
+ l1.next.next.next.next.next = new Node(5);
+ l2 = new Node(1);
+ l2.next = new Node(4);
+ l2.next.next = new Node(2);
+ l2.next.next.next = new Node(3);
+ l1.print();
+ l2.print();
+ System.out.println(findIntersectingNode(l1, l2));
+ }
+}
diff --git a/src/main/java/com/ctci/linkedlists/KthToLastElement.java b/src/main/java/com/ctci/linkedlists/KthToLastElement.java
index 01f56298..8fff3f9d 100644
--- a/src/main/java/com/ctci/linkedlists/KthToLastElement.java
+++ b/src/main/java/com/ctci/linkedlists/KthToLastElement.java
@@ -1,7 +1,5 @@
package com.ctci.linkedlists;
-import static com.ctci.linkedlists.Node.printList;
-
/**
* @author rampatra
* @since 21/11/2018
@@ -34,6 +32,25 @@ private static Node getKthToLastElement(Node head, int k) {
return slow;
}
+ /**
+ * This approach is recursive and it just prints the kth to last node instead
+ * of returning the node.
+ *
+ * @param head starting node of the linklist
+ * @param k kth to last node to print
+ * @return the index of the kth to last node
+ */
+ private static int printKthToLastElement(Node head, int k) {
+ if (head == null) {
+ return 0;
+ }
+ int index = printKthToLastElement(head.next, k) + 1;
+ if (index == k) {
+ System.out.println(head.val);
+ }
+ return index;
+ }
+
public static void main(String[] args) {
Node l1 = new Node(1);
l1.next = new Node(6);
@@ -41,8 +58,10 @@ public static void main(String[] args) {
l1.next.next.next = new Node(4);
l1.next.next.next.next = new Node(5);
l1.next.next.next.next.next = new Node(7);
- printList(l1);
+ l1.print();
System.out.println("k=2: " + getKthToLastElement(l1, 2).val); // NPE check is omitted intentionally to keep it simple
+ System.out.print("k=2: ");
+ printKthToLastElement(l1, 2);
Node l2 = new Node(1);
l2.next = new Node(6);
@@ -50,8 +69,10 @@ public static void main(String[] args) {
l2.next.next.next = new Node(3);
l2.next.next.next.next = new Node(4);
l2.next.next.next.next.next = new Node(7);
- printList(l2);
+ l2.print();
System.out.println("k=1: " + getKthToLastElement(l2, 1).val);
+ System.out.print("k=1: ");
+ printKthToLastElement(l2, 1);
Node l3 = new Node(1);
l3.next = new Node(6);
@@ -59,7 +80,9 @@ public static void main(String[] args) {
l3.next.next.next = new Node(3);
l3.next.next.next.next = new Node(4);
l3.next.next.next.next.next = new Node(7);
- printList(l3);
+ l3.print();
System.out.println("k=6: " + getKthToLastElement(l3, 6).val);
+ System.out.print("k=6: ");
+ printKthToLastElement(l3, 6);
}
}
diff --git a/src/main/java/com/ctci/linkedlists/LoopDetection.java b/src/main/java/com/ctci/linkedlists/LoopDetection.java
new file mode 100644
index 00000000..d0a9a110
--- /dev/null
+++ b/src/main/java/com/ctci/linkedlists/LoopDetection.java
@@ -0,0 +1,67 @@
+package com.ctci.linkedlists;
+
+/**
+ * @author rampatra
+ * @since 2019-02-03
+ */
+public class LoopDetection {
+
+ /**
+ * Given a circular linked list, implement an algorithm that returns the node at the beginning of the loop.
+ * DEFINITION
+ * Circular linked list: A (corrupt) linked list in which a node's next pointer points to an earlier node, so
+ * as to make a loop in the linked list.
+ * EXAMPLE
+ * Input: A -> B -> C -> D -> E -> C [the same C as earlier]
+ * Output: C
+ *
+ * See {@link com.rampatra.linkedlists.DetectAndRemoveLoop} for a slightly more complex problem.
+ *
+ * @param head the starting node of the linked list
+ * @return the {@code Node} where the loop starts, {@code null} otherwise.
+ */
+ private static Node findLoopStartNode(Node head) {
+ Node slow = head;
+ Node fast = head;
+
+ while (fast != null && fast.next != null) {
+ slow = slow.next;
+ fast = fast.next.next;
+ if (slow == fast) {
+ break;
+ }
+ }
+
+ /* Error check - no meeting point, and therefore no loop */
+ if (fast == null || fast.next == null) {
+ return null;
+ }
+
+ /* Move slow to Head. Keep fast at Meeting Point. Each are k steps from the
+ * Loop Start. If they move at the same pace, they must meet at Loop Start. */
+ slow = head;
+ while (slow != fast) {
+ slow = slow.next;
+ fast = fast.next;
+ }
+
+ /* You can return either as now both point to the start of the loop */
+ return fast;
+ }
+
+ public static void main(String[] args) {
+ /*
+ * 1 -> 2 -> 3 -> 4 -> 5 -> 6
+ * ^ |
+ * |_________|
+ */
+ Node l1 = new Node(1);
+ l1.next = new Node(2);
+ l1.next.next = new Node(3);
+ l1.next.next.next = new Node(4);
+ l1.next.next.next.next = new Node(5);
+ l1.next.next.next.next.next = new Node(6);
+ l1.next.next.next.next.next.next = l1.next.next.next;
+ System.out.println(findLoopStartNode(l1).val);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/linkedlists/Node.java b/src/main/java/com/ctci/linkedlists/Node.java
index a0f68cb1..5c0d1ec3 100644
--- a/src/main/java/com/ctci/linkedlists/Node.java
+++ b/src/main/java/com/ctci/linkedlists/Node.java
@@ -12,10 +12,8 @@ class Node {
this.val = val;
}
- public static void printList(Node head) {
- if (head == null) return;
-
- Node curr = head;
+ public void print() {
+ Node curr = this;
while (curr.next != null) {
System.out.print(curr.val + "->");
curr = curr.next;
diff --git a/src/main/java/com/ctci/linkedlists/Palindrome.java b/src/main/java/com/ctci/linkedlists/Palindrome.java
new file mode 100644
index 00000000..57bb184d
--- /dev/null
+++ b/src/main/java/com/ctci/linkedlists/Palindrome.java
@@ -0,0 +1,107 @@
+package com.ctci.linkedlists;
+
+import java.util.Stack;
+
+/**
+ * @author rampatra
+ * @since 2019-02-02
+ */
+public class Palindrome {
+
+ /**
+ * Checks whether a Linked List is palindrome by using a stack.
+ *
+ * @param head starting node of the linked list.
+ * @return {@code true} if linked list palindrome, {@code false} otherwise.
+ */
+ private static boolean isPalindrome(Node head) {
+ Node curr = head;
+ Stack stack = new Stack<>();
+ // pop all elements into stack
+ while (curr != null) {
+ stack.push(curr.val);
+ curr = curr.next;
+ }
+ curr = head;
+ // as stack contains the elements in reverse order, pop and compare with the list one by one
+ while (curr != null) {
+ if (curr.val != stack.pop()) {
+ return false;
+ }
+ curr = curr.next;
+ }
+ return true;
+ }
+
+ /**
+ * This is a similar approach like above but a bit faster as we are not iterating the entire list twice.
+ *
+ * @param head starting node of the linked list.
+ * @return {@code true} if linked list palindrome, {@code false} otherwise.
+ */
+ private static boolean isPalindromeOptimized(Node head) {
+ Node slow = head;
+ Node fast = head;
+ Stack stack = new Stack<>();
+
+ // push half of the elements into the stack
+ while (fast != null && fast.next != null) {
+ stack.push(slow.val);
+ slow = slow.next;
+ fast = fast.next.next;
+ }
+
+ // linked list has odd number of elements, so forward the slow reference by one
+ if (fast != null) {
+ slow = slow.next;
+ }
+
+ while (slow != null) {
+ if (slow.val != stack.pop()) {
+ return false;
+ }
+ slow = slow.next;
+ }
+ return true;
+ }
+
+ public static void main(String[] args) {
+
+ Node l1 = new Node(1);
+ l1.next = new Node(2);
+ l1.next.next = new Node(3);
+ l1.next.next.next = new Node(3);
+ l1.next.next.next.next = new Node(2);
+ l1.next.next.next.next.next = new Node(1);
+ l1.print();
+ System.out.println(isPalindrome(l1));
+ System.out.println(isPalindromeOptimized(l1));
+ System.out.println("------");
+
+ l1 = new Node(1);
+ l1.next = new Node(2);
+ l1.next.next = new Node(3);
+ l1.next.next.next = new Node(2);
+ l1.next.next.next.next = new Node(1);
+ l1.print();
+ System.out.println(isPalindrome(l1));
+ System.out.println(isPalindromeOptimized(l1));
+ System.out.println("------");
+
+ l1 = new Node(0);
+ l1.next = new Node(2);
+ l1.next.next = new Node(3);
+ l1.next.next.next = new Node(3);
+ l1.next.next.next.next = new Node(0);
+ l1.print();
+ System.out.println(isPalindrome(l1));
+ System.out.println(isPalindromeOptimized(l1));
+ System.out.println("------");
+
+ l1 = new Node(1);
+ l1.print();
+ System.out.println(isPalindrome(l1));
+ System.out.println(isPalindromeOptimized(l1));
+
+ }
+}
diff --git a/src/main/java/com/ctci/linkedlists/Partition.java b/src/main/java/com/ctci/linkedlists/Partition.java
new file mode 100644
index 00000000..8876a424
--- /dev/null
+++ b/src/main/java/com/ctci/linkedlists/Partition.java
@@ -0,0 +1,93 @@
+package com.ctci.linkedlists;
+
+/**
+ * Write code to partition a linked list around a value x, such that all nodes less than x come before all
+ * nodes greater than or equal to x. If x is contained within the list, the values of x only need to be
+ * after the elements less than x (see below). The partition element x can appear anywhere in the "right
+ * partition"; it does not need to appear between the left and right partitions.
+ *
+ * EXAMPLE:
+ * Input: 3 -> 5 -> 8 -> 5 -> 10 -> 2 -> 1 [partition=5]
+ * Output: 3 -> 1 -> 2 -> 10 -> 5 -> 5 -> 8
+ *
+ * @author rampatra
+ * @since 2019-01-28
+ */
+public class Partition {
+
+ private static Node partition(Node head, int x) {
+ Node leftPartitionHead = null;
+ Node leftPartitionCurr = null;
+ Node rightPartitionHead = null;
+ Node rightPartitionCurr = null;
+ Node curr = head;
+
+ while (curr != null) {
+ if (curr.val < x) {
+ if (leftPartitionHead == null) {
+ leftPartitionHead = curr;
+ leftPartitionCurr = curr;
+ } else {
+ leftPartitionCurr.next = curr;
+ leftPartitionCurr = leftPartitionCurr.next;
+ }
+ } else {
+ if (rightPartitionHead == null) {
+ rightPartitionHead = curr;
+ rightPartitionCurr = curr;
+ } else {
+ rightPartitionCurr.next = curr;
+ rightPartitionCurr = rightPartitionCurr.next;
+ }
+ }
+ curr = curr.next;
+ }
+
+ if (leftPartitionCurr != null) leftPartitionCurr.next = rightPartitionHead;
+ if (rightPartitionCurr != null) rightPartitionCurr.next = null;
+
+ return leftPartitionHead;
+ }
+
+ public static void main(String[] args) {
+ Node l1 = new Node(3);
+ l1.next = new Node(5);
+ l1.next.next = new Node(8);
+ l1.next.next.next = new Node(5);
+ l1.next.next.next.next = new Node(10);
+ l1.next.next.next.next.next = new Node(2);
+ l1.next.next.next.next.next.next = new Node(1);
+ l1.print();
+ l1.print();
+
+ System.out.println("----");
+
+ l1 = new Node(1);
+ l1.next = new Node(2);
+ l1.next.next = new Node(3);
+ l1.print();
+ l1.print();
+
+ System.out.println("----");
+
+ l1 = new Node(3);
+ l1.next = new Node(2);
+ l1.next.next = new Node(1);
+ l1.print();
+ l1.print();
+
+ System.out.println("----");
+
+ l1 = new Node(1);
+ l1.print();
+ l1.print();
+
+ System.out.println("----");
+
+ l1 = null;
+ l1.print();
+ l1.print();
+
+ System.out.println("----");
+ }
+}
diff --git a/src/main/java/com/ctci/linkedlists/RemoveDuplicates.java b/src/main/java/com/ctci/linkedlists/RemoveDuplicates.java
index fc7244c1..31029188 100644
--- a/src/main/java/com/ctci/linkedlists/RemoveDuplicates.java
+++ b/src/main/java/com/ctci/linkedlists/RemoveDuplicates.java
@@ -3,8 +3,6 @@
import java.util.HashSet;
import java.util.Set;
-import static com.ctci.linkedlists.Node.printList;
-
/**
* @author rampatra
* @since 21/11/2018
@@ -44,10 +42,10 @@ public static void main(String[] args) {
l1.next.next.next.next = new Node(5);
l1.next.next.next.next.next = new Node(5);
System.out.print("With dups: ");
- printList(l1);
+ l1.print();
removeDuplicatesFromUnsortedList(l1);
System.out.print("Without dups: ");
- printList(l1);
+ l1.print();
Node l2 = new Node(1);
l2.next = new Node(1);
@@ -56,10 +54,10 @@ public static void main(String[] args) {
l2.next.next.next.next = new Node(4);
l2.next.next.next.next.next = new Node(5);
System.out.print("\nWith dups: ");
- printList(l2);
+ l2.print();
removeDuplicatesFromUnsortedList(l2);
System.out.print("Without dups: ");
- printList(l2);
+ l2.print();
Node l3 = new Node(1);
l3.next = new Node(2);
@@ -68,9 +66,23 @@ public static void main(String[] args) {
l3.next.next.next.next = new Node(4);
l3.next.next.next.next.next = new Node(5);
System.out.print("\nWith dups: ");
- printList(l3);
+ l3.print();
removeDuplicatesFromUnsortedList(l3);
System.out.print("Without dups: ");
- printList(l3);
+ l3.print();
+
+ Node l4 = new Node(1);
+ System.out.print("\nWith dups: ");
+ l4.print();
+ removeDuplicatesFromUnsortedList(l4);
+ System.out.print("Without dups: ");
+ l4.print();
+
+ Node l5 = null;
+ System.out.print("\nWith dups: ");
+ l5.print();
+ removeDuplicatesFromUnsortedList(l5);
+ System.out.print("Without dups: ");
+ l5.print();
}
}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/linkedlists/SumLists.java b/src/main/java/com/ctci/linkedlists/SumLists.java
new file mode 100644
index 00000000..befdfc3e
--- /dev/null
+++ b/src/main/java/com/ctci/linkedlists/SumLists.java
@@ -0,0 +1,86 @@
+package com.ctci.linkedlists;
+
+/**
+ * @author rampatra
+ * @since 2019-01-31
+ */
+public class SumLists {
+
+ /**
+ * You have two numbers represented by a linked list, where each node contains a single digit. The digits are
+ * stored in reverse order, such that the 1's digit is at the head of the list (or in other words, the least
+ * significant digit is stored at the head of the list). Write a function that adds the two numbers and returns
+ * the sum as a linked list.
+ *
+ * EXAMPLE
+ * Input: (7-> 1 -> 6) + (5 -> 9 -> 2).That is, 617 + 295.
+ * Output: 2 -> 1 -> 9. That is, 912.
+ *
+ * @param num1
+ * @param num2
+ * @return
+ */
+ private static Node sumLists(Node num1, Node num2) {
+ int carry = 0;
+ int sum;
+ Node sumList = null, curr = null;
+ while (num1 != null || num2 != null) {
+ sum = ((num1 == null) ? 0 : num1.val) + ((num2 == null) ? 0 : num2.val) + carry;
+ carry = sum / 10;
+ if (sumList == null) {
+ sumList = new Node(sum % 10);
+ curr = sumList;
+ } else {
+ curr.next = new Node(sum % 10);
+ curr = curr.next;
+ }
+ if (num1 != null) num1 = num1.next;
+ if (num2 != null) num2 = num2.next;
+ }
+ if (carry != 0) {
+ curr.next = new Node(carry);
+ }
+ return sumList;
+ }
+
+ // TODO: After doing reverseListRecursive
+ private static Node sumListsWithMostSignificantDigitAtHead(Node n1, Node n2) {
+ return null;
+ }
+
+ public static void main(String[] args) {
+ Node l1 = new Node(9);
+ l1.next = new Node(9);
+ l1.next.next = new Node(9);
+
+ Node l2 = new Node(9);
+ l2.next = new Node(9);
+ l2.next.next = new Node(9);
+
+ l1.print();
+ l2.print();
+ sumLists(l1, l2).print();
+ System.out.println("-----------");
+
+ l1 = new Node(9);
+ l1.next = new Node(9);
+
+ l2 = new Node(9);
+ l2.next = new Node(9);
+ l2.next.next = new Node(9);
+
+ l1.print();
+ l2.print();
+ sumLists(l1, l2).print();
+ System.out.println("-----------");
+
+ l1 = null;
+ l2 = new Node(9);
+ l2.next = new Node(9);
+ l2.next.next = new Node(8);
+
+ l1.print();
+ l2.print();
+ sumLists(l1, l2).print();
+ }
+}
diff --git a/src/main/java/com/ctci/recursionanddp/FibonacciNumber.java b/src/main/java/com/ctci/recursionanddp/FibonacciNumber.java
new file mode 100644
index 00000000..caa4d095
--- /dev/null
+++ b/src/main/java/com/ctci/recursionanddp/FibonacciNumber.java
@@ -0,0 +1,64 @@
+package com.ctci.recursionanddp;
+
+/**
+ * The fabled fibonacci numbers problem with three different solutions.
+ * The {@link FibonacciNumber#fibonacciBottomUpOptimized(int)} version is the most optimized among all w.r.t space
+ * and time. See {@link com.rampatra.dynamicprogramming.FibonacciNumbers} for Fibonacci series.
+ *
+ * @author rampatra
+ * @since 2019-02-26
+ */
+public class FibonacciNumber {
+
+ private static int fibonacciTopDown(int n, int[] memo) {
+ if (n == 0 || n == 1) return n;
+
+ if (memo[n] != 0) {
+ return memo[n];
+ } else {
+ memo[n] = fibonacciTopDown(n - 1, memo) + fibonacciTopDown(n - 2, memo);
+ return memo[n];
+ }
+ }
+
+ private static int fibonacciBottomUp(int n) {
+ if (n == 0 || n == 1) return n;
+
+ int[] memo = new int[n + 1];
+ memo[1] = 1;
+ for (int i = 2; i <= n; i++) {
+ memo[i] = memo[i - 1] + memo[i - 2];
+ }
+ return memo[n];
+ }
+
+ private static int fibonacciBottomUpOptimized(int n) {
+ if (n == 0 || n == 1) return n;
+
+ int a = 0;
+ int b = 1;
+ int res = a + b;
+
+ for (int i = 2; i <= n; i++) {
+ res = a + b;
+ a = b;
+ b = res;
+ }
+
+ return res;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(fibonacciTopDown(4, new int[5]));
+ System.out.println(fibonacciBottomUp(4));
+ System.out.println(fibonacciBottomUpOptimized(4));
+ System.out.println("---");
+ System.out.println(fibonacciTopDown(5, new int[6]));
+ System.out.println(fibonacciBottomUp(5));
+ System.out.println(fibonacciBottomUpOptimized(5));
+ System.out.println("---");
+ System.out.println(fibonacciTopDown(10, new int[11]));
+ System.out.println(fibonacciBottomUp(10));
+ System.out.println(fibonacciBottomUpOptimized(10));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/stacksandqueues/QueueViaStacks.java b/src/main/java/com/ctci/stacksandqueues/QueueViaStacks.java
new file mode 100644
index 00000000..271fd8e4
--- /dev/null
+++ b/src/main/java/com/ctci/stacksandqueues/QueueViaStacks.java
@@ -0,0 +1,61 @@
+package com.ctci.stacksandqueues;
+
+import java.util.NoSuchElementException;
+import java.util.Stack;
+
+/**
+ * Implement a queue using two stacks. No other data structures to be used.
+ *
+ * @author rampatra
+ * @since 2019-02-06
+ */
+public class QueueViaStacks {
+
+ private Stack stackFront = new Stack<>();
+ private Stack stackRear = new Stack<>();
+
+ private T add(T item) {
+ return stackRear.push(item);
+ }
+
+ private T remove() {
+ if (stackFront.empty() && stackRear.empty()) {
+ throw new NoSuchElementException();
+ } else if (!stackFront.empty()) {
+ return stackFront.pop();
+ } else {
+ while (!stackRear.empty()) {
+ stackFront.push(stackRear.pop());
+ }
+ return stackFront.pop();
+ }
+ }
+
+ private void print() {
+ Stack tempStack = new Stack<>();
+ while (!stackFront.empty()) {
+ tempStack.push(stackFront.pop());
+ }
+ System.out.print("[");
+ tempStack.forEach(item -> System.out.print(item + ","));
+ stackRear.forEach(item -> System.out.print(item + ","));
+ System.out.println("]");
+ while (!tempStack.empty()) {
+ stackFront.push(tempStack.pop());
+ }
+ }
+
+ public static void main(String[] args) {
+ QueueViaStacks queue = new QueueViaStacks<>();
+ queue.add(1);
+ queue.add(2);
+ queue.add(3);
+ queue.print();
+ queue.remove();
+ queue.print();
+ queue.remove();
+ queue.print();
+ queue.remove();
+ queue.print();
+ }
+}
diff --git a/src/main/java/com/ctci/stacksandqueues/SortStack.java b/src/main/java/com/ctci/stacksandqueues/SortStack.java
new file mode 100644
index 00000000..b94c68fb
--- /dev/null
+++ b/src/main/java/com/ctci/stacksandqueues/SortStack.java
@@ -0,0 +1,48 @@
+package com.ctci.stacksandqueues;
+
+import java.util.Arrays;
+import java.util.Stack;
+
+/**
+ * Write a program to sort a stack such that the smallest items are on the top. You can use an additional temporary
+ * stack, but you may not copy the elements into any other data structure (such as an array). The stack supports the
+ * following operations: push, pop, peek, and isEmpty.
+ *
+ * @author rampatra
+ * @since 2019-02-08
+ */
+public class SortStack {
+
+ private static void sortStack(Stack stack) {
+ Stack tempStack = new Stack<>();
+ while (!stack.empty()) {
+ tempStack.push(stack.pop());
+ }
+ while (!tempStack.empty()) {
+ Integer item = tempStack.pop();
+ if (stack.empty()) {
+ stack.push(item);
+ } else {
+ while (!stack.empty() && item > stack.peek()) {
+ tempStack.push(stack.pop());
+ }
+ stack.push(item);
+ }
+ }
+ }
+
+ private static void printStack(Stack stack) {
+ System.out.println(Arrays.toString(stack.toArray()));
+ }
+
+ public static void main(String[] args) {
+ Stack unsortedStack = new Stack<>();
+ unsortedStack.push(2);
+ unsortedStack.push(5);
+ unsortedStack.push(1);
+ unsortedStack.push(3);
+ printStack(unsortedStack);
+ sortStack(unsortedStack);
+ printStack(unsortedStack);
+ }
+}
diff --git a/src/main/java/com/ctci/stacksandqueues/StackMin.java b/src/main/java/com/ctci/stacksandqueues/StackMin.java
new file mode 100644
index 00000000..0a5d2d59
--- /dev/null
+++ b/src/main/java/com/ctci/stacksandqueues/StackMin.java
@@ -0,0 +1,62 @@
+package com.ctci.stacksandqueues;
+
+import com.sun.tools.javac.util.Assert;
+
+import java.util.Stack;
+
+/**
+ * How would you design a stack which, in addition to push and pop, has a function min
+ * which returns the minimum element? Push, pop and min should all operate in 0(1) time.
+ *
+ * @author rampatra
+ * @since 2019-02-04
+ */
+public class StackMin {
+
+ // the main stack to do push, pop, and min operations
+ private static Stack stack = new Stack<>();
+ // another stack to store the mins (needed to make min() call O(1))
+ private static Stack minStack = new Stack<>();
+
+ private static int push(int item) {
+ minPush(item);
+ return stack.push(item);
+ }
+
+ private static int pop() {
+ minPop(stack.peek());
+ return stack.pop();
+ }
+
+ private static int min() {
+ return minStack.peek();
+ }
+
+ private static void minPush(int item) {
+ if (minStack.empty() || item <= minStack.peek()) {
+ minStack.push(item);
+ }
+ }
+
+ private static void minPop(int item) {
+ if (item == minStack.peek()) {
+ minStack.pop();
+ }
+ }
+
+ public static void main(String[] args) {
+ push(2);
+ push(5);
+ push(1);
+ push(1);
+ push(6);
+ push(8);
+ Assert.check(min() == 1);
+ pop();
+ pop();
+ pop();
+ Assert.check(min() == 1);
+ pop();
+ Assert.check(min() == 2);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/stacksandqueues/StackOfPlates.java b/src/main/java/com/ctci/stacksandqueues/StackOfPlates.java
new file mode 100644
index 00000000..f001c4e4
--- /dev/null
+++ b/src/main/java/com/ctci/stacksandqueues/StackOfPlates.java
@@ -0,0 +1,80 @@
+package com.ctci.stacksandqueues;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EmptyStackException;
+import java.util.List;
+import java.util.Stack;
+
+/**
+ * Imagine a (literal) stack of plates. If the stack gets too high, it might topple. Therefore, in real life, we
+ * would likely start a new stack when the previous stack exceeds some threshold. Implement a data structure
+ * SetOfStacks that mimics this. SetOfStacks should be composed of several stacks and should create a new stack once
+ * the previous one exceeds capacity. SetOfStacks.push() and SetOfStacks. pop() should behave identically to a single
+ * stack (that is, pop() should return the same values as it would if there were just a single stack).
+ *
+ * @author rampatra
+ * @since 2019-02-08
+ */
+public class StackOfPlates {
+
+ private static final int capacity = 3;
+ private static List> stackList = new ArrayList<>();
+
+ private static int push(int item) {
+ return getLastStack().push(item);
+ }
+
+ private static int pop() {
+ Stack lastStack = stackList.get(stackList.size() - 1);
+ if (lastStack == null || (stackList.size() == 1 && lastStack.empty())) {
+ throw new EmptyStackException();
+ } else if (lastStack.empty()) {
+ stackList.remove(stackList.size() - 1);
+ return pop();
+ } else {
+ return lastStack.pop();
+ }
+ }
+
+ private static Stack getLastStack() {
+ if (stackList.size() == 0 || isFull(stackList.get(stackList.size() - 1))) {
+ stackList.add(new Stack<>());
+ }
+ return stackList.get(stackList.size() - 1);
+ }
+
+ private static boolean isFull(Stack stack) {
+ return stack.size() >= capacity;
+ }
+
+ private static void print() {
+ System.out.print("[");
+ stackList.stream().flatMap(Collection::stream).forEach(System.out::print);
+ System.out.println("]");
+ }
+
+ public static void main(String[] args) {
+ push(1);
+ push(2);
+ print();
+ push(3);
+ print();
+ push(4);
+ push(5);
+ print();
+ push(6);
+ push(7);
+ print();
+ pop();
+ print();
+ pop();
+ pop();
+ pop();
+ print();
+ pop();
+ pop();
+ pop();
+ print();
+ }
+}
diff --git a/src/main/java/com/ctci/treesandgraphs/BuildOrder.java b/src/main/java/com/ctci/treesandgraphs/BuildOrder.java
new file mode 100644
index 00000000..6d64e48a
--- /dev/null
+++ b/src/main/java/com/ctci/treesandgraphs/BuildOrder.java
@@ -0,0 +1,144 @@
+package com.ctci.treesandgraphs;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
+
+/**
+ * You are given a list of projects and a list of dependencies (which is a list of pairs of projects, where the second
+ * project is dependent on the first project). All of a project's dependencies must be built before the project is. Find
+ * a build order that will allow the projects to be built. If there is no valid build order, return an error.
+ * EXAMPLE
+ * Input: projects: a, b, c, d, e, f and dependencies: (a, d), (f, b), (b, d), (f, a), (d, c)
+ * Output: f, e, a, b, d, c
+ *
+ * @author rampatra
+ * @since 2019-02-21
+ */
+public class BuildOrder {
+
+ private class Project {
+ String name;
+ Set dependencies = new HashSet<>();
+
+ Project(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+
+ private final Map projects = new HashMap<>();
+
+ private void addProjects(Stream projectNames) {
+ projectNames.forEach(name -> projects.put(name, new Project(name)));
+ }
+
+ /**
+ * Adds a directed edge from {@code projectName2} to {@code ProjectName1}. This means {@code projectName2} is
+ * dependent on {@code projectName1}, i.e, {@code projectName1} has to be built before {@code projectName2}.
+ *
+ * @param projectName1 name of project 1
+ * @param projectName2 name of project 2
+ */
+ private void addDependency(String projectName1, String projectName2) {
+ Project p1 = projects.get(projectName1);
+ Project p2 = projects.get(projectName2);
+
+ if (p1 == null) {
+ p1 = new Project(projectName1);
+ projects.put(projectName1, p1);
+ }
+ if (p2 == null) {
+ p2 = new Project(projectName2);
+ projects.put(projectName2, p2);
+ }
+
+ p2.dependencies.add(p1);
+ }
+
+ /**
+ * Determines the order in which the projects need to be built.
+ * Time complexity: TODO
+ *
+ * @return a list of projects in the order they should be built, the first project should be built first and so on.
+ */
+ private List getBuildOrder() {
+ Map projectsBuilt = new LinkedHashMap<>(); // linked hashmap is needed to maintain the insertion order
+
+ while (projectsBuilt.size() != projects.size()) {
+ // find the projects which are not dependent on any project
+ Set nextProjectsToBuild = getProjectsWithNoDependencies(projectsBuilt);
+
+ // if there are no further independent projects to build, then we can't proceed further
+ if (nextProjectsToBuild.size() == 0) {
+ throw new IllegalStateException("Error: Projects can't be built.");
+ }
+ nextProjectsToBuild.forEach(p -> projectsBuilt.put(p.name, p));
+
+ // once a project is built, remove the dependencies from all other projects dependent on this
+ removeDependency(nextProjectsToBuild);
+ }
+
+ return new ArrayList<>(projectsBuilt.values());
+ }
+
+ private Set getProjectsWithNoDependencies(Map alreadyBuildProjects) {
+ Set unBuiltProjectsWithZeroDependencies = new HashSet<>();
+
+ for (Map.Entry entry : projects.entrySet()) {
+ if (entry.getValue().dependencies.size() == 0 && alreadyBuildProjects.get(entry.getKey()) == null) {
+ unBuiltProjectsWithZeroDependencies.add(entry.getValue());
+ }
+ }
+
+ return unBuiltProjectsWithZeroDependencies;
+ }
+
+ private void removeDependency(Set newlyBuiltProjects) {
+ projects.forEach((n, p) -> p.dependencies.removeAll(newlyBuiltProjects));
+ }
+
+
+ public static void main(String[] args) {
+ /* test case 1
+
+ ––––––––––– b
+ | ↑
+ ↓ |
+ f <–– a <–– d <–– c
+
+ Note: Project "a" is dependent on "f", and project "d" is dependent on "a", and so on.
+
+ */
+ BuildOrder buildOrder = new BuildOrder();
+ buildOrder.addProjects(Stream.of("a", "b", "c", "d", "e", "f"));
+ buildOrder.addDependency("a", "d");
+ buildOrder.addDependency("f", "b");
+ buildOrder.addDependency("b", "d");
+ buildOrder.addDependency("f", "a");
+ buildOrder.addDependency("d", "c");
+ System.out.println(buildOrder.getBuildOrder());
+
+ // test case 2
+ buildOrder = new BuildOrder();
+ buildOrder.addProjects(Stream.of("a", "b", "c", "d", "e", "f", "g"));
+ buildOrder.addDependency("d", "g");
+ buildOrder.addDependency("f", "b");
+ buildOrder.addDependency("f", "c");
+ buildOrder.addDependency("f", "a");
+ buildOrder.addDependency("c", "a");
+ buildOrder.addDependency("b", "a");
+ buildOrder.addDependency("b", "e");
+ buildOrder.addDependency("a", "e");
+ System.out.println(buildOrder.getBuildOrder());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/treesandgraphs/CheckBalanced.java b/src/main/java/com/ctci/treesandgraphs/CheckBalanced.java
new file mode 100644
index 00000000..d7658cd8
--- /dev/null
+++ b/src/main/java/com/ctci/treesandgraphs/CheckBalanced.java
@@ -0,0 +1,81 @@
+package com.ctci.treesandgraphs;
+
+/**
+ * Implement a function to check if a binary tree is balanced. For the purposes of this question, a balanced
+ * tree is defined to be a tree such that the heights of the two subtrees of any node never differ by more than one.
+ *
+ * @author rampatra
+ * @since 2019-02-16
+ */
+public class CheckBalanced {
+
+ /**
+ * Checks whether its left and right child are balanced, if yes then continues down the
+ * tree or else stops and returns {@code false}. Time complexity: O(n log n) since each
+ * node is touched once per node above it. Space complexity: O(h) where, h is the height
+ * of the tree.
+ *
+ * @param node reference to the node for which the balanced property needs to be checked
+ * @return {@code true} if balanced, {@code false} otherwise
+ */
+ private static boolean isBalanced(TreeNode node) {
+ if (node == null) return true;
+
+ boolean isBalanced = (height(node.left) - height(node.right)) <= 1;
+
+ /* Note: isBalanced is first checked below as there is no point is checking the left and right child
+ if the current node itself is not balanced. And, as '&&' is a short circuit operator, it won't evaluate
+ the rest of the conditions if the first condition is false. */
+ return isBalanced && isBalanced(node.left) && isBalanced(node.right);
+ }
+
+ private static int height(TreeNode node) {
+ if (node == null) return -1;
+
+ return Math.max(height(node.left), height(node.right)) + 1;
+ }
+
+ /**
+ * This approach is a slight modification to the above {@link CheckBalanced#height(TreeNode)} method where
+ * while calculating the height we also check whether the difference between the left and right child heights
+ * is more than 1. If yes, we return an error code, which in this case, is {@code Integer.MIN_VALUE}.
+ * Time complexity: O(n). Space complexity: O(h) where, h is the height of the tree.
+ *
+ * @param node reference to the node for which the balanced property needs to be checked
+ * @return the height of the tree if it's balance, {@code Integer.MIN_VALUE} otherwise
+ */
+ private static int checkHeightAndBalance(TreeNode node) {
+ if (node == null) return -1;
+
+ int leftHeight = checkHeightAndBalance(node.left);
+ int rightHeight = checkHeightAndBalance(node.right);
+
+ if (leftHeight == Integer.MIN_VALUE || rightHeight == Integer.MIN_VALUE || !(leftHeight - rightHeight <= 1)) {
+ return Integer.MIN_VALUE;
+ }
+
+ return Math.max(leftHeight, rightHeight) + 1;
+ }
+
+ public static boolean isBalancedOptimized(TreeNode node) {
+ return checkHeightAndBalance(node) != Integer.MIN_VALUE;
+ }
+
+ public static void main(String[] args) {
+ TreeNode treeRoot = new TreeNode(1);
+ treeRoot.left = new TreeNode(2);
+ treeRoot.right = new TreeNode(3);
+ System.out.println("Height: " + height(treeRoot));
+ System.out.println("Is Balance: " + isBalanced(treeRoot));
+ System.out.println("Is Balance Optimized: " + isBalancedOptimized(treeRoot));
+
+ treeRoot = new TreeNode(1);
+ treeRoot.left = new TreeNode(2);
+ treeRoot.right = new TreeNode(3);
+ treeRoot.left.left = new TreeNode(4);
+ treeRoot.left.left.left = new TreeNode(5);
+ System.out.println("Height: " + height(treeRoot));
+ System.out.println("Is Balance: " + isBalanced(treeRoot));
+ System.out.println("Is Balance Optimized: " + isBalancedOptimized(treeRoot));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/treesandgraphs/CheckSubtree.java b/src/main/java/com/ctci/treesandgraphs/CheckSubtree.java
new file mode 100644
index 00000000..a49f1b74
--- /dev/null
+++ b/src/main/java/com/ctci/treesandgraphs/CheckSubtree.java
@@ -0,0 +1,96 @@
+package com.ctci.treesandgraphs;
+
+/**
+ * @author rampatra
+ * @since 2019-02-24
+ */
+public class CheckSubtree {
+
+ private static boolean isT2SubtreeOfT1(TreeNode t1, TreeNode t2) {
+ if (t1 == null) {
+ return false;
+ } else if (t2 == null) {
+ return true;
+ }
+
+ if (t1.val == t2.val) {
+ if (matchTree(t1, t2)) {
+ return true;
+ }
+ }
+ return isT2SubtreeOfT1(t1.left, t2) || isT2SubtreeOfT1(t1.right, t2);
+ }
+
+ private static boolean matchTree(TreeNode a, TreeNode b) {
+ if (a == null && b == null) {
+ return true;
+ } else if (a == null) {
+ return false;
+ } else if (b == null) {
+ return true;
+ } else if (a.val != b.val) {
+ return false;
+ } else {
+ return matchTree(a.left, b.left) && matchTree(a.right, b.right);
+ }
+ }
+
+ public static void main(String[] args) {
+ /*
+ The BST looks like:
+
+ 4
+ / \
+ 2 8
+ / \ / \
+ 1 3 6 9
+ /
+ 0
+
+ */
+ TreeNode treeRoot = new TreeNode(4);
+ treeRoot.left = new TreeNode(2);
+ treeRoot.right = new TreeNode(8);
+ treeRoot.left.left = new TreeNode(1);
+ treeRoot.left.right = new TreeNode(3);
+ treeRoot.left.left.left = new TreeNode(0);
+ treeRoot.right.left = new TreeNode(6);
+ treeRoot.right.right = new TreeNode(9);
+ System.out.println(isT2SubtreeOfT1(treeRoot, treeRoot));
+ System.out.println(isT2SubtreeOfT1(treeRoot, treeRoot.left));
+ System.out.println(isT2SubtreeOfT1(treeRoot, treeRoot.right));
+
+ /*
+ The sub-tree:
+
+ 8
+ /
+ 6
+ */
+ TreeNode treeRoot2 = new TreeNode(8);
+ treeRoot2.left = new TreeNode(6);
+ System.out.println(isT2SubtreeOfT1(treeRoot, treeRoot2));
+
+ /*
+ The sub-tree:
+
+ 2
+ /
+ 1
+ */
+ TreeNode treeRoot3 = new TreeNode(2);
+ treeRoot3.left = new TreeNode(1);
+ System.out.println(isT2SubtreeOfT1(treeRoot, treeRoot3));
+
+ /*
+ The sub-tree:
+
+ 8
+ /
+ 9
+ */
+ TreeNode treeRoot4 = new TreeNode(8);
+ treeRoot4.left = new TreeNode(9);
+ System.out.println(isT2SubtreeOfT1(treeRoot, treeRoot4));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/treesandgraphs/FirstCommonAncestor.java b/src/main/java/com/ctci/treesandgraphs/FirstCommonAncestor.java
new file mode 100644
index 00000000..38977be3
--- /dev/null
+++ b/src/main/java/com/ctci/treesandgraphs/FirstCommonAncestor.java
@@ -0,0 +1,103 @@
+package com.ctci.treesandgraphs;
+
+/**
+ * Design an algorithm and write code to find the first common ancestor of two nodes in a binary
+ * tree. Avoid storing additional nodes in a data structure. Also, for this question, the tree node
+ * does NOT have access to its parent node. NOTE: This is not necessarily a binary search tree.
+ *
+ * First Common Ancestor or the Least/Lowest Common Ancestor of two nodes is a node which is the
+ * closest to both of the nodes.
+ *
+ * @author rampatra
+ * @since 2019-02-24
+ */
+public class FirstCommonAncestor {
+
+ /**
+ * We recurse through the entire tree with a function called findFCA(TreeNode root, TreeNode TreeNode a, TreeNode b).
+ * This function returns values as follows:
+ * - Returns p, if root's subtree includes p (and not q).
+ * - Returns q, if root's subtree includes q (and not p).
+ * - Returns null, if neither p nor q are in root's subtree.
+ * - Else, returns the common ancestor of p and q.
+ *
+ * See {@link com.rampatra.trees.LeastCommonAncestorInBT} for a better answer.
+ *
+ * @param root
+ * @param a
+ * @param b
+ * @return the least common ancestor node
+ */
+ private static TreeNode findFCA(TreeNode root, TreeNode a, TreeNode b) {
+ if (root == null) { // validation
+ return null;
+ }
+ if (root == a && root == b) { // optimization
+ return root;
+ }
+
+ TreeNode left = findFCA(root.left, a, b);
+ if (left != null && left != a && left != b) {
+ return left;
+ }
+
+ TreeNode right = findFCA(root.right, a, b);
+ if (right != null && right != a && right != b) {
+ return right;
+ }
+
+ /* One node is found on the left subtree and other on the
+ right one. This means current node is the ancestor. */
+ if (left != null && right != null) {
+ return root;
+ } else if (root == a || root == b) {
+ return root;
+ } else {
+ return left == null ? right : left;
+ }
+ }
+
+ private static class TreeNode {
+ int val;
+ TreeNode left;
+ TreeNode right;
+
+ TreeNode(int val) {
+ this.val = val;
+ }
+ }
+
+ public static void main(String[] args) {
+ /*
+ The binary tree looks like:
+
+ 4
+ / \
+ 5 8
+ / \ / \
+ 1 3 2 9
+ / \
+ 0 7
+
+ */
+ TreeNode treeRoot = new TreeNode(4);
+ treeRoot.left = new TreeNode(5);
+ treeRoot.right = new TreeNode(8);
+ treeRoot.left.left = new TreeNode(1);
+ treeRoot.left.right = new TreeNode(3);
+ treeRoot.left.left.left = new TreeNode(0);
+ treeRoot.right.left = new TreeNode(2);
+ treeRoot.right.right = new TreeNode(9);
+ treeRoot.right.left.right = new TreeNode(7);
+
+ System.out.println("FCA of 0 and 7 is: " + findFCA(treeRoot, treeRoot.left.left.left, treeRoot.right.left.right).val);
+ System.out.println("FCA of 0 and 9 is: " + findFCA(treeRoot, treeRoot.left.left.left, treeRoot.right.right).val);
+ System.out.println("FCA of 0 and 1 is: " + findFCA(treeRoot, treeRoot.left.left.left, treeRoot.left.left).val);
+ System.out.println("FCA of 1 and 2 is: " + findFCA(treeRoot, treeRoot.left.left, treeRoot.right.left).val);
+ System.out.println("FCA of 1 and 7 is: " + findFCA(treeRoot, treeRoot.left.left, treeRoot.right.left.right).val);
+ System.out.println("FCA of 4 and 7 is: " + findFCA(treeRoot, treeRoot, treeRoot.right.left.right).val);
+ System.out.println("FCA of 5 and 2 is: " + findFCA(treeRoot, treeRoot.left, treeRoot.right.left).val);
+ System.out.println("FCA of 7 and 9 is: " + findFCA(treeRoot, treeRoot.right.left.right, treeRoot.right.right).val);
+ System.out.println("FCA of 7 and 10 is: " + findFCA(treeRoot, treeRoot.right.left.right, new TreeNode(10)).val); // this use case does not work with the above algorithm
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/treesandgraphs/FirstCommonAncestorWithParentAccess.java b/src/main/java/com/ctci/treesandgraphs/FirstCommonAncestorWithParentAccess.java
new file mode 100644
index 00000000..5aa453cf
--- /dev/null
+++ b/src/main/java/com/ctci/treesandgraphs/FirstCommonAncestorWithParentAccess.java
@@ -0,0 +1,115 @@
+package com.ctci.treesandgraphs;
+
+/**
+ * Design an algorithm and write code to find the first common ancestor of two nodes in a binary
+ * tree. Avoid storing additional nodes in a data structure. Also, for this question, the tree node
+ * has access to its parent node. NOTE: This is not necessarily a binary search tree.
+ *
+ * @author rampatra
+ * @since 2019-02-23
+ */
+public class FirstCommonAncestorWithParentAccess {
+
+ /**
+ * This is a simple approach where we start with two references, one pointing to {@code node a} and another
+ * pointing to {@code node b}. We move the reference pointing to the deeper node upwards, if required, so that
+ * both the references are at the same depth from root. After both the references are at same depth, we simply
+ * move both the references upwards until they merge. The node at which they merge is our LCA.
+ *
+ * @param a
+ * @param b
+ * @return the least common ancestor node
+ */
+ private static TreeNode findLCA(TreeNode a, TreeNode b) {
+ if (a == null || b == null) {
+ return null;
+ }
+
+ int depthA = depth(a);
+ int depthB = depth(b);
+ /* be little careful when both nodes are at same depth, have the checks such that
+ shallow and deeper references point to different nodes */
+ TreeNode shallowNode = depthA < depthB ? a : b;
+ TreeNode deeperNode = depthB > depthA ? b : a;
+
+ // move deeper node reference upwards so that both the references are at same depth
+ deeperNode = goUpBy(deeperNode, Math.abs(depthA - depthB));
+
+ while (shallowNode != deeperNode && shallowNode != null && deeperNode != null) {
+ shallowNode = shallowNode.parent;
+ deeperNode = deeperNode.parent;
+ }
+
+ return shallowNode;
+ }
+
+ private static int depth(TreeNode node) {
+ int d = 0;
+ while (node != null && node.parent != null) {
+ d++;
+ node = node.parent;
+ }
+ return d;
+ }
+
+ private static TreeNode goUpBy(TreeNode node, int levelsUp) {
+ int c = 0;
+ while (node != null && c < levelsUp) {
+ node = node.parent;
+ c++;
+ }
+ return node;
+ }
+
+ private static class TreeNode {
+ int val;
+ TreeNode parent;
+ TreeNode left;
+ TreeNode right;
+
+ TreeNode(int val) {
+ this.val = val;
+ }
+ }
+
+ public static void main(String[] args) {
+ /*
+ The binary tree looks like:
+
+ 4
+ / \
+ 5 8
+ / \ / \
+ 1 3 2 9
+ / \
+ 0 7
+
+ */
+ TreeNode treeRoot = new TreeNode(4);
+ treeRoot.left = new TreeNode(5);
+ treeRoot.left.parent = treeRoot;
+ treeRoot.right = new TreeNode(8);
+ treeRoot.right.parent = treeRoot;
+ treeRoot.left.left = new TreeNode(1);
+ treeRoot.left.left.parent = treeRoot.left;
+ treeRoot.left.right = new TreeNode(3);
+ treeRoot.left.right.parent = treeRoot.left;
+ treeRoot.left.left.left = new TreeNode(0);
+ treeRoot.left.left.left.parent = treeRoot.left.left;
+ treeRoot.right.left = new TreeNode(2);
+ treeRoot.right.left.parent = treeRoot.right;
+ treeRoot.right.right = new TreeNode(9);
+ treeRoot.right.right.parent = treeRoot.right;
+ treeRoot.right.left.right = new TreeNode(7);
+ treeRoot.right.left.right.parent = treeRoot.right.left;
+
+ System.out.println("FCA of 0 and 7 is: " + findLCA(treeRoot.left.left.left, treeRoot.right.left.right).val);
+ System.out.println("FCA of 0 and 9 is: " + findLCA(treeRoot.left.left.left, treeRoot.right.right).val);
+ System.out.println("FCA of 0 and 1 is: " + findLCA(treeRoot.left.left.left, treeRoot.left.left).val);
+ System.out.println("FCA of 1 and 2 is: " + findLCA(treeRoot.left.left, treeRoot.right.left).val);
+ System.out.println("FCA of 1 and 7 is: " + findLCA(treeRoot.left.left, treeRoot.right.left.right).val);
+ System.out.println("FCA of 4 and 7 is: " + findLCA(treeRoot, treeRoot.right.left.right).val);
+ System.out.println("FCA of 5 and 2 is: " + findLCA(treeRoot.left, treeRoot.right.left).val);
+ System.out.println("FCA of 7 and 9 is: " + findLCA(treeRoot.right.left.right, treeRoot.right.right).val);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/treesandgraphs/GraphNode.java b/src/main/java/com/ctci/treesandgraphs/GraphNode.java
new file mode 100644
index 00000000..573cccf3
--- /dev/null
+++ b/src/main/java/com/ctci/treesandgraphs/GraphNode.java
@@ -0,0 +1,17 @@
+package com.ctci.treesandgraphs;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author rampatra
+ * @since 2019-03-21
+ */
+public class GraphNode {
+ int value;
+ Set adjacent = new HashSet<>();
+
+ GraphNode(int value) {
+ this.value = value;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/treesandgraphs/ListOfDepths.java b/src/main/java/com/ctci/treesandgraphs/ListOfDepths.java
new file mode 100644
index 00000000..fd5287dc
--- /dev/null
+++ b/src/main/java/com/ctci/treesandgraphs/ListOfDepths.java
@@ -0,0 +1,99 @@
+package com.ctci.treesandgraphs;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Given a binary tree, design an algorithm which creates a linked list of all the nodes
+ * at each depth (e.g., if you have a tree with depth D, you'll have D linked lists).
+ *
+ * @author rampatra
+ * @since 2019-02-16
+ */
+public class ListOfDepths {
+
+ /**
+ * This approach visits the root node, adds all its children to a list, then iterates
+ * that list, and repeats the same process until all nodes are visited.
+ *
+ * @param root the root node of the tree
+ * @return list of nodes at each depth, where depth starts from 0
+ */
+ private static List> listOfDepths(TreeNode root) {
+ List> listOfDepths = new ArrayList<>();
+ List listOfNodesAtCurrentDepth = new ArrayList<>();
+
+ if (root != null) {
+ listOfNodesAtCurrentDepth.add(root);
+ }
+
+ while (listOfNodesAtCurrentDepth.size() > 0) {
+ listOfDepths.add(listOfNodesAtCurrentDepth); // add current depth
+ List listOfNodesAtPreviousDepth = listOfNodesAtCurrentDepth; // make current depth as previous
+ /* make current depth as the new depth to be processed considering
+ the nodes from the previous depth as parents */
+ listOfNodesAtCurrentDepth = new ArrayList<>();
+
+ for (TreeNode node : listOfNodesAtPreviousDepth) {
+ if (node.left != null) {
+ listOfNodesAtCurrentDepth.add(node.left);
+ }
+ if (node.right != null) {
+ listOfNodesAtCurrentDepth.add(node.right);
+ }
+ }
+ }
+
+ return listOfDepths;
+ }
+
+ /**
+ * This is a recursive approach where we pass the depth of each node in the call. We use a
+ * list {@code listOfDepths} to keep track of all the depths.
+ *
+ * @param node
+ * @param depth
+ * @param listOfDepths
+ * @return list of nodes at each depth, where depth starts from 0
+ */
+ private static List> listOfDepths(TreeNode node, int depth, List> listOfDepths) {
+ if (node == null) return null;
+
+ List listOfNodesAtDepth;
+ if (depth == listOfDepths.size()) {
+ listOfNodesAtDepth = new ArrayList<>();
+ listOfDepths.add(listOfNodesAtDepth);
+ } else {
+ listOfNodesAtDepth = listOfDepths.get(depth);
+ }
+
+ listOfNodesAtDepth.add(node);
+
+ listOfDepths(node.left, depth + 1, listOfDepths);
+ listOfDepths(node.right, depth + 1, listOfDepths);
+
+ return listOfDepths;
+ }
+
+ private static void printAllDepths(List> listOfDepths) {
+ for (int i = 0; i < listOfDepths.size(); i++) {
+ System.out.print("Depth " + i + ": ");
+ listOfDepths.get(i).forEach(node -> System.out.print("->" + node.val));
+ System.out.println();
+ }
+ }
+
+ public static void main(String[] args) {
+ TreeNode treeRoot = new TreeNode(1);
+ treeRoot.left = new TreeNode(2);
+ treeRoot.right = new TreeNode(3);
+ treeRoot.left.left = new TreeNode(4);
+ treeRoot.left.right = new TreeNode(5);
+ treeRoot.right.left = new TreeNode(6);
+ treeRoot.right.right = new TreeNode(7);
+
+ printAllDepths(listOfDepths(treeRoot));
+ System.out.println("-----");
+ printAllDepths(listOfDepths(treeRoot, 0, new ArrayList<>()));
+ }
+}
diff --git a/src/main/java/com/ctci/treesandgraphs/MinimalTree.java b/src/main/java/com/ctci/treesandgraphs/MinimalTree.java
new file mode 100644
index 00000000..4d18faf7
--- /dev/null
+++ b/src/main/java/com/ctci/treesandgraphs/MinimalTree.java
@@ -0,0 +1,43 @@
+package com.ctci.treesandgraphs;
+
+/**
+ * Given a sorted (increasing order) array with unique integer elements, write
+ * an algorithm to create a binary search tree with minimal height.
+ *
+ * @author rampatra
+ * @since 2019-02-15
+ */
+public class MinimalTree {
+
+ private static TreeNode constructBSTWithMinimalHeight(int[] arr, int start, int end) {
+ if (start > end) return null;
+
+ int mid = (start + end) / 2;
+ TreeNode root = new TreeNode(arr[mid]);
+ root.left = constructBSTWithMinimalHeight(arr, start, mid - 1);
+ root.right = constructBSTWithMinimalHeight(arr, mid + 1, end);
+ return root;
+ }
+
+ private static void inOrderTraversal(TreeNode node) {
+ if (node == null) return;
+
+ inOrderTraversal(node.left);
+ System.out.print("->" + node.val);
+ inOrderTraversal(node.right);
+ }
+
+ public static void main(String[] args) {
+ TreeNode root = constructBSTWithMinimalHeight(new int[]{1, 2, 3, 4, 5, 6, 7}, 0, 6);
+ inOrderTraversal(root);
+ System.out.println();
+ root = constructBSTWithMinimalHeight(new int[]{1, 2, 3, 4, 5, 6, 7, 8}, 0, 7);
+ inOrderTraversal(root);
+ System.out.println();
+ root = constructBSTWithMinimalHeight(new int[]{1, 2}, 0, 1);
+ inOrderTraversal(root);
+ System.out.println();
+ root = constructBSTWithMinimalHeight(new int[]{1}, 0, 0);
+ inOrderTraversal(root);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/treesandgraphs/RouteBetweenNodes.java b/src/main/java/com/ctci/treesandgraphs/RouteBetweenNodes.java
new file mode 100644
index 00000000..b849b8c8
--- /dev/null
+++ b/src/main/java/com/ctci/treesandgraphs/RouteBetweenNodes.java
@@ -0,0 +1,94 @@
+package com.ctci.treesandgraphs;
+
+import java.util.ArrayDeque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+/**
+ * @author rampatra
+ * @since 2019-03-21
+ */
+public class RouteBetweenNodes {
+
+ class Graph {
+
+ private final Map nodes = new HashMap<>();
+
+ /**
+ * Adds an edge from a node with value {@code v1} to another node with value {@code v2}.
+ * Note: This code doesn't work for nodes having duplicate values.
+ *
+ * @param v1
+ * @param v2
+ */
+ void addEdge(int v1, int v2) {
+ GraphNode n1 = nodes.get(v1);
+ GraphNode n2 = nodes.get(v2);
+
+ if (n1 == null) {
+ n1 = new GraphNode(v1);
+ nodes.put(v1, n1);
+ }
+ if (n2 == null) {
+ n2 = new GraphNode(v2);
+ nodes.put(v2, n2);
+ }
+
+ n1.adjacent.add(n2); // as it is a directed graph
+ }
+
+ /**
+ * Checks for a path from a node with value {@code v1} to another node with value {@code v2} in a breadth-first
+ * manner. Note: This code doesn't work for nodes having duplicate values.
+ *
+ * @param v1 the value of the first node or starting node.
+ * @param v2 the value of the ending node.
+ * @return {@code true} if path exists, {@code false} otherwise.
+ */
+ boolean isRoutePresent(int v1, int v2) {
+ Queue queue = new ArrayDeque<>();
+ Set visited = new HashSet<>();
+
+ GraphNode n1 = nodes.get(v1);
+ GraphNode n2 = nodes.get(v2);
+
+ if (n1 == null || n2 == null) {
+ return false;
+ }
+
+ queue.add(n1);
+
+ while (!queue.isEmpty()) {
+ GraphNode n = queue.poll();
+
+ if (visited.contains(n)) {
+ continue;
+ }
+ if (n.adjacent.contains(n2)) {
+ return true;
+ }
+ queue.addAll(n.adjacent);
+ visited.add(n);
+ }
+
+ return false;
+ }
+ }
+
+ public static void main(String[] args) {
+ Graph g = new RouteBetweenNodes().new Graph();
+ g.addEdge(1, 2);
+ g.addEdge(2, 3);
+ g.addEdge(4, 5);
+ g.addEdge(5, 6);
+ System.out.println("Route exists from 1 to 2: " + g.isRoutePresent(1, 2));
+ System.out.println("Route exists from 2 to 5: " + g.isRoutePresent(2, 5));
+ System.out.println("Route exists from 1 to 3: " + g.isRoutePresent(1, 3));
+ System.out.println("Route exists from 4 to 6: " + g.isRoutePresent(4, 6));
+ System.out.println("Route exists from 6 to 4: " + g.isRoutePresent(6, 4));
+ System.out.println("Route exists from 6 to 5: " + g.isRoutePresent(6, 5));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/treesandgraphs/Successor.java b/src/main/java/com/ctci/treesandgraphs/Successor.java
new file mode 100644
index 00000000..d37488bd
--- /dev/null
+++ b/src/main/java/com/ctci/treesandgraphs/Successor.java
@@ -0,0 +1,98 @@
+package com.ctci.treesandgraphs;
+
+/**
+ * Write an algorithm to find the "next" node (i.e., in-order successor) of a given node
+ * in a binary search tree. You may assume that each node has a link to its parent.
+ *
+ * @author rampatra
+ * @since 2019-02-17
+ */
+public class Successor {
+
+ /**
+ * To get the inorder successor what this method does is that it checks if the right child of the input node
+ * is null and if not, gets the leftmost child of the right child. And, if the right child of the input
+ * node is null, it checks all the parents until it finds the next successor.
+ *
+ * @param node
+ * @return
+ */
+ private static TreeNode getInOrderSuccessor(TreeNode node) {
+ if (node == null) return null;
+
+ if (node.right != null) {
+ return getLeftmostNode(node.right);
+ } else {
+ TreeNode curr = node;
+
+ while (curr != null) {
+ if (curr.parent != null && curr.parent.left == curr) {
+ return curr.parent;
+ }
+ curr = curr.parent;
+ }
+ }
+ return null;
+ }
+
+ private static TreeNode getLeftmostNode(TreeNode node) {
+ TreeNode curr = node;
+ while (curr != null && curr.left != null) {
+ curr = curr.left;
+ }
+ return curr;
+ }
+
+ private static class TreeNode {
+ int val;
+ TreeNode parent;
+ TreeNode left;
+ TreeNode right;
+
+ TreeNode(int val) {
+ this.val = val;
+ }
+ }
+
+ public static void main(String[] args) {
+ /*
+ The binary search tree looks like:
+
+ 4
+ / \
+ 2 8
+ / \ / \
+ 1 3 6 9
+ / \
+ 0 7
+
+ */
+ TreeNode treeRoot = new TreeNode(4);
+ treeRoot.left = new TreeNode(2);
+ treeRoot.left.parent = treeRoot;
+ treeRoot.right = new TreeNode(8);
+ treeRoot.right.parent = treeRoot;
+ treeRoot.left.left = new TreeNode(1);
+ treeRoot.left.left.parent = treeRoot.left;
+ treeRoot.left.right = new TreeNode(3);
+ treeRoot.left.right.parent = treeRoot.left;
+ treeRoot.left.left.left = new TreeNode(0);
+ treeRoot.left.left.left.parent = treeRoot.left.left;
+ treeRoot.right.left = new TreeNode(6);
+ treeRoot.right.left.parent = treeRoot.right;
+ treeRoot.right.right = new TreeNode(9);
+ treeRoot.right.right.parent = treeRoot.right;
+ treeRoot.right.left.right = new TreeNode(7);
+ treeRoot.right.left.right.parent = treeRoot.right.left;
+
+ System.out.println("InOrder successor of 0 is: " + getInOrderSuccessor(treeRoot.left.left.left).val);
+ System.out.println("InOrder successor of 1 is: " + getInOrderSuccessor(treeRoot.left.left).val);
+ System.out.println("InOrder successor of 2 is: " + getInOrderSuccessor(treeRoot.left).val);
+ System.out.println("InOrder successor of 3 is: " + getInOrderSuccessor(treeRoot.left.right).val);
+ System.out.println("InOrder successor of 4 is: " + getInOrderSuccessor(treeRoot).val);
+ System.out.println("InOrder successor of 6 is: " + getInOrderSuccessor(treeRoot.right.left).val);
+ System.out.println("InOrder successor of 7 is: " + getInOrderSuccessor(treeRoot.right.left.right).val);
+ System.out.println("InOrder successor of 8 is: " + getInOrderSuccessor(treeRoot.right).val);
+ System.out.println("InOrder successor of 9 is: " + getInOrderSuccessor(treeRoot.right.right));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ctci/treesandgraphs/TreeNode.java b/src/main/java/com/ctci/treesandgraphs/TreeNode.java
new file mode 100644
index 00000000..3fe24210
--- /dev/null
+++ b/src/main/java/com/ctci/treesandgraphs/TreeNode.java
@@ -0,0 +1,15 @@
+package com.ctci.treesandgraphs;
+
+/**
+ * @author rampatra
+ * @since 2019-02-15
+ */
+public class TreeNode {
+ public int val;
+ public TreeNode left;
+ public TreeNode right;
+
+ public TreeNode(int val) {
+ this.val = val;
+ }
+}
diff --git a/src/main/java/com/ctci/treesandgraphs/ValidateBST.java b/src/main/java/com/ctci/treesandgraphs/ValidateBST.java
new file mode 100644
index 00000000..0170cdfe
--- /dev/null
+++ b/src/main/java/com/ctci/treesandgraphs/ValidateBST.java
@@ -0,0 +1,101 @@
+package com.ctci.treesandgraphs;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implement a function to check if a binary tree is a binary search tree.
+ *
+ * @author rampatra
+ * @since 2019-02-17
+ */
+public class ValidateBST {
+
+ private static boolean isBST(TreeNode node) {
+ return isBST(node, new ArrayList<>());
+ }
+
+ /**
+ * This method exploits the fact that the inorder traversal of a binary search tree
+ * results in the values being sorted in ascending order. Here, we have used a list
+ * but if you see closely we use this list to only compare with the previous element.
+ * Ergo, we can use an instance/class variable to store just the last element. This
+ * will be a good optimization for space.
+ *
+ * Time Complexity: O(n) as we touch all the nodes in the tree.
+ * Space Complexity: O(n) as we use a list to store all the elements in the tree. If we
+ * had used just a instance/class variable, the space complexity would have been O(log n)
+ * as there can be up to O(log n) recursive calls as we may recurse up to the depth of
+ * the tree. Note, the tree has to balanced though.
+ *
+ * @param node
+ * @param values
+ * @return
+ */
+ private static boolean isBST(TreeNode node, List values) {
+ if (node == null) return true;
+
+ isBST(node.left, values);
+ if (values.isEmpty() || node.val > values.get(values.size() - 1)) {
+ values.add(node.val);
+ } else {
+ return false;
+ }
+ isBST(node.right, values);
+
+ return true;
+ }
+
+ private static boolean isBSTApproach2(TreeNode node) {
+ return isBSTApproach2(node, Integer.MIN_VALUE, Integer.MAX_VALUE);
+ }
+
+ /**
+ * This approach exploits the condition that all left nodes must be less than or equal to
+ * the current node, which must be less than all the right nodes.
+ *
+ * Time Complexity: O(n) as we touch all the nodes in the tree.
+ * Space Complexity: O(log n) as there are up to O(log n) recursive calls on the stack
+ * as we may recurse up to the depth fo the tree. Note, the tree has to be balanced though.
+ *
+ * @param node
+ * @param min
+ * @param max
+ * @return
+ */
+ private static boolean isBSTApproach2(TreeNode node, int min, int max) {
+ if (node == null) return true;
+
+ if (node.val < min || node.val > max) {
+ return false;
+ }
+
+ return isBSTApproach2(node.left, min, node.val) && isBSTApproach2(node.right, node.val + 1, max);
+ }
+
+ public static void main(String[] args) {
+ TreeNode treeRoot = new TreeNode(1);
+ treeRoot.left = new TreeNode(2);
+ treeRoot.right = new TreeNode(3);
+ System.out.println("Is BST Approach 1: " + isBST(treeRoot));
+ System.out.println("Is BST Approach 2: " + isBSTApproach2(treeRoot));
+
+ treeRoot = new TreeNode(2);
+ treeRoot.left = new TreeNode(1);
+ treeRoot.right = new TreeNode(3);
+ System.out.println("Is BST Approach 1: " + isBST(treeRoot));
+ System.out.println("Is BST Approach 2: " + isBSTApproach2(treeRoot));
+
+ treeRoot = new TreeNode(4);
+ treeRoot.left = new TreeNode(2);
+ treeRoot.right = new TreeNode(8);
+ treeRoot.left.left = new TreeNode(1);
+ treeRoot.left.right = new TreeNode(3);
+ treeRoot.left.left.left = new TreeNode(0);
+ treeRoot.right.left = new TreeNode(6);
+ treeRoot.right.right = new TreeNode(9);
+ treeRoot.right.left.right = new TreeNode(7);
+ System.out.println("Is BST Approach 1: " + isBST(treeRoot));
+ System.out.println("Is BST Approach 2: " + isBSTApproach2(treeRoot));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/hackerrank/algorithms/arraysandsorting/InsertionSort1.java b/src/main/java/com/hackerrank/algorithms/arraysandsorting/InsertionSort1.java
index 7dadb554..6fd03542 100644
--- a/src/main/java/com/hackerrank/algorithms/arraysandsorting/InsertionSort1.java
+++ b/src/main/java/com/hackerrank/algorithms/arraysandsorting/InsertionSort1.java
@@ -4,7 +4,7 @@
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 3/1/15
* Time: 8:58 PM
* To change this template go to Preferences | IDE Settings | File and Code Templates
diff --git a/src/main/java/com/hackerrank/algorithms/arraysandsorting/InsertionSort2.java b/src/main/java/com/hackerrank/algorithms/arraysandsorting/InsertionSort2.java
index 93ee48a3..cd710eb9 100644
--- a/src/main/java/com/hackerrank/algorithms/arraysandsorting/InsertionSort2.java
+++ b/src/main/java/com/hackerrank/algorithms/arraysandsorting/InsertionSort2.java
@@ -4,7 +4,7 @@
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 3/1/15
* Time: 9:42 PM
* To change this template go to Preferences | IDE Settings | File and Code Templates
diff --git a/src/main/java/com/hackerrank/algorithms/arraysandsorting/IntroTutorial.java b/src/main/java/com/hackerrank/algorithms/arraysandsorting/IntroTutorial.java
index aac8e479..aeb8ea5f 100644
--- a/src/main/java/com/hackerrank/algorithms/arraysandsorting/IntroTutorial.java
+++ b/src/main/java/com/hackerrank/algorithms/arraysandsorting/IntroTutorial.java
@@ -5,7 +5,7 @@
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 3/1/15
* Time: 3:38 PM
* To change this template go to Preferences | IDE Settings | File and Code Templates
@@ -15,7 +15,7 @@ static int search(int searchVal, int[] arr) {
return Arrays.binarySearch(arr, searchVal);
}
- public static void main(String[] a) {
+ public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int searchVal = in.nextInt();
diff --git a/src/main/java/com/hackerrank/algorithms/arraysandsorting/LoopInvariant.java b/src/main/java/com/hackerrank/algorithms/arraysandsorting/LoopInvariant.java
index 2b8613e9..dd12ee7e 100644
--- a/src/main/java/com/hackerrank/algorithms/arraysandsorting/LoopInvariant.java
+++ b/src/main/java/com/hackerrank/algorithms/arraysandsorting/LoopInvariant.java
@@ -4,7 +4,7 @@
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 3/2/15
* Time: 3:26 PM
* To change this template go to Preferences | IDE Settings | File and Code Templates
diff --git a/src/main/java/com/hackerrank/algorithms/arraysandsorting/QuickSort1.java b/src/main/java/com/hackerrank/algorithms/arraysandsorting/QuickSort1.java
index 7e14ca9b..0753f812 100644
--- a/src/main/java/com/hackerrank/algorithms/arraysandsorting/QuickSort1.java
+++ b/src/main/java/com/hackerrank/algorithms/arraysandsorting/QuickSort1.java
@@ -4,7 +4,7 @@
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 3/2/15
* Time: 5:13 PM
* To change this template go to Preferences | IDE Settings | File and Code Templates
diff --git a/src/main/java/com/hackerrank/algorithms/arraysandsorting/QuickSort2.java b/src/main/java/com/hackerrank/algorithms/arraysandsorting/QuickSort2.java
index a366da37..b9b1dcba 100644
--- a/src/main/java/com/hackerrank/algorithms/arraysandsorting/QuickSort2.java
+++ b/src/main/java/com/hackerrank/algorithms/arraysandsorting/QuickSort2.java
@@ -4,7 +4,7 @@
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 3/3/15
* Time: 1:05 PM
* To change this template go to Preferences | IDE Settings | File and Code Templates
diff --git a/src/main/java/com/hackerrank/algorithms/arraysandsorting/RunningTime.java b/src/main/java/com/hackerrank/algorithms/arraysandsorting/RunningTime.java
index 36a55877..27a0bd77 100644
--- a/src/main/java/com/hackerrank/algorithms/arraysandsorting/RunningTime.java
+++ b/src/main/java/com/hackerrank/algorithms/arraysandsorting/RunningTime.java
@@ -4,7 +4,7 @@
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 3/2/15
* Time: 5:02 PM
* To change this template go to Preferences | IDE Settings | File and Code Templates
diff --git a/src/main/java/com/hackerrank/algorithms/implementation/CavityMap.java b/src/main/java/com/hackerrank/algorithms/implementation/CavityMap.java
index 8ead43c8..0bc4a052 100644
--- a/src/main/java/com/hackerrank/algorithms/implementation/CavityMap.java
+++ b/src/main/java/com/hackerrank/algorithms/implementation/CavityMap.java
@@ -3,7 +3,7 @@
import java.util.Scanner;
/**
- * Created by ramswaroop on 08/05/2016.
+ * Created by rampatra on 08/05/2016.
*/
public class CavityMap {
public static void main(String[] args) {
diff --git a/src/main/java/com/hackerrank/algorithms/implementation/ExtraLongFactorials.java b/src/main/java/com/hackerrank/algorithms/implementation/ExtraLongFactorials.java
index d4e340b7..230a18aa 100644
--- a/src/main/java/com/hackerrank/algorithms/implementation/ExtraLongFactorials.java
+++ b/src/main/java/com/hackerrank/algorithms/implementation/ExtraLongFactorials.java
@@ -4,7 +4,7 @@
import java.util.Scanner;
/**
- * Created by ramswaroop on 29/05/2016.
+ * Created by rampatra on 29/05/2016.
*/
public class ExtraLongFactorials {
public static void main(String[] args) {
diff --git a/src/main/java/com/hackerrank/algorithms/implementation/GridSearch.java b/src/main/java/com/hackerrank/algorithms/implementation/GridSearch.java
index 6fb2251d..a317913c 100644
--- a/src/main/java/com/hackerrank/algorithms/implementation/GridSearch.java
+++ b/src/main/java/com/hackerrank/algorithms/implementation/GridSearch.java
@@ -3,7 +3,7 @@
import java.util.Scanner;
/**
- * Created by ramswaroop on 02/05/2016.
+ * Created by rampatra on 02/05/2016.
*/
public class GridSearch {
diff --git a/src/main/java/com/hackerrank/algorithms/implementation/TheTimeInWords.java b/src/main/java/com/hackerrank/algorithms/implementation/TheTimeInWords.java
index 0b747ce5..4915014b 100644
--- a/src/main/java/com/hackerrank/algorithms/implementation/TheTimeInWords.java
+++ b/src/main/java/com/hackerrank/algorithms/implementation/TheTimeInWords.java
@@ -3,7 +3,7 @@
import java.util.Scanner;
/**
- * Created by ramswaroop on 29/05/2016.
+ * Created by rampatra on 29/05/2016.
*/
public class TheTimeInWords {
public static void main(String[] args) {
diff --git a/src/main/java/com/hackerrank/algorithms/strings/AlternatingCharacters.java b/src/main/java/com/hackerrank/algorithms/strings/AlternatingCharacters.java
index 823f1e61..c81f5c22 100644
--- a/src/main/java/com/hackerrank/algorithms/strings/AlternatingCharacters.java
+++ b/src/main/java/com/hackerrank/algorithms/strings/AlternatingCharacters.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 10/22/15
+ * @author rampatra
+ * @since 10/22/15
* @time: 9:24 AM
*/
public class AlternatingCharacters {
diff --git a/src/main/java/com/hackerrank/algorithms/strings/MakingAnagrams.java b/src/main/java/com/hackerrank/algorithms/strings/MakingAnagrams.java
index fd0f847e..b218c04e 100644
--- a/src/main/java/com/hackerrank/algorithms/strings/MakingAnagrams.java
+++ b/src/main/java/com/hackerrank/algorithms/strings/MakingAnagrams.java
@@ -3,7 +3,7 @@
import java.util.Arrays;
/**
- * @author ramswaroop
+ * @author rampatra
* @version 28/09/2016
*/
public class MakingAnagrams {
@@ -47,7 +47,7 @@ public static int makeAnagrams(String a, String b) {
return c;
}
- public static void main(String[] a) {
+ public static void main(String[] args) {
System.out.println(makeAnagrams("abc", "cde"));
}
}
diff --git a/src/main/java/com/hackerrank/algorithms/strings/PalindromeIndex.java b/src/main/java/com/hackerrank/algorithms/strings/PalindromeIndex.java
index b9d76784..294c4dd2 100644
--- a/src/main/java/com/hackerrank/algorithms/strings/PalindromeIndex.java
+++ b/src/main/java/com/hackerrank/algorithms/strings/PalindromeIndex.java
@@ -4,7 +4,7 @@
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 3/18/15
* Time: 12:27 PM
* To change this template go to Preferences | IDE Settings | File and Code Templates
@@ -37,7 +37,7 @@ static boolean isPalindrome(String s) {
return true;
}
- public static void main(String[] a) {
+ public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
diff --git a/src/main/java/com/hackerrank/algorithms/strings/Pangram.java b/src/main/java/com/hackerrank/algorithms/strings/Pangram.java
index 27fffa88..fa98b4fd 100644
--- a/src/main/java/com/hackerrank/algorithms/strings/Pangram.java
+++ b/src/main/java/com/hackerrank/algorithms/strings/Pangram.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 10/22/15
+ * @author rampatra
+ * @since 10/22/15
* @time: 8:47 AM
*/
public class Pangram {
diff --git a/src/main/java/com/hackerrank/algorithms/strings/TwoStrings.java b/src/main/java/com/hackerrank/algorithms/strings/TwoStrings.java
index f2b0ea1f..779a148b 100644
--- a/src/main/java/com/hackerrank/algorithms/strings/TwoStrings.java
+++ b/src/main/java/com/hackerrank/algorithms/strings/TwoStrings.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 10/22/15
+ * @author rampatra
+ * @since 10/22/15
* @time: 10:08 AM
*/
public class TwoStrings {
@@ -22,7 +22,7 @@ public static String isSubstringInBoth(String[] a) {
return "NO";
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = Integer.parseInt(in.nextLine());
diff --git a/src/main/java/com/hackerrank/algorithms/warmup/FlippingBits.java b/src/main/java/com/hackerrank/algorithms/warmup/FlippingBits.java
index 7f593e9a..e335efe1 100644
--- a/src/main/java/com/hackerrank/algorithms/warmup/FlippingBits.java
+++ b/src/main/java/com/hackerrank/algorithms/warmup/FlippingBits.java
@@ -4,7 +4,7 @@
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 2/28/15
* Time: 12:41 PM
* To change this template go to Preferences | IDE Settings | File and Code Templates
diff --git a/src/main/java/com/hackerrank/algorithms/warmup/LonelyInteger.java b/src/main/java/com/hackerrank/algorithms/warmup/LonelyInteger.java
index f2a3a7fd..666b3fa0 100644
--- a/src/main/java/com/hackerrank/algorithms/warmup/LonelyInteger.java
+++ b/src/main/java/com/hackerrank/algorithms/warmup/LonelyInteger.java
@@ -6,7 +6,7 @@
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 2/28/15
* Time: 12:16 PM
* To change this template go to Preferences | IDE Settings | File and Code Templates
diff --git a/src/main/java/com/hackerrank/algorithms/warmup/LoveLetterMystery.java b/src/main/java/com/hackerrank/algorithms/warmup/LoveLetterMystery.java
index 88e27080..8855498c 100644
--- a/src/main/java/com/hackerrank/algorithms/warmup/LoveLetterMystery.java
+++ b/src/main/java/com/hackerrank/algorithms/warmup/LoveLetterMystery.java
@@ -4,7 +4,7 @@
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 3/17/15
* Time: 3:22 PM
* To change this template go to Preferences | IDE Settings | File and Code Templates
@@ -20,7 +20,7 @@ static int calcPalindromeSteps(String s) {
return steps;
}
- public static void main(String[] a) {
+ public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
diff --git a/src/main/java/com/hackerrank/algorithms/warmup/MaximizingXor.java b/src/main/java/com/hackerrank/algorithms/warmup/MaximizingXor.java
index 115e2ac1..2b0cc0ab 100644
--- a/src/main/java/com/hackerrank/algorithms/warmup/MaximizingXor.java
+++ b/src/main/java/com/hackerrank/algorithms/warmup/MaximizingXor.java
@@ -5,7 +5,7 @@
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 3/7/15
* Time: 11:07 AM
* To change this template go to Preferences | IDE Settings | File and Code Templates
diff --git a/src/main/java/com/hackerrank/algorithms/warmup/UtopianTree.java b/src/main/java/com/hackerrank/algorithms/warmup/UtopianTree.java
index 65e23887..43e455c2 100644
--- a/src/main/java/com/hackerrank/algorithms/warmup/UtopianTree.java
+++ b/src/main/java/com/hackerrank/algorithms/warmup/UtopianTree.java
@@ -4,7 +4,7 @@
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 3/1/15
* Time: 3:07 PM
* To change this template go to Preferences | IDE Settings | File and Code Templates
@@ -23,7 +23,7 @@ static int calcHeight(int growthCycles) {
return h;
}
- public static void main(String[] a) {
+ public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
diff --git a/src/main/java/com/hackerrank/bitmanipulation/CounterGame.java b/src/main/java/com/hackerrank/bitmanipulation/CounterGame.java
index c319fc38..b2a03e21 100644
--- a/src/main/java/com/hackerrank/bitmanipulation/CounterGame.java
+++ b/src/main/java/com/hackerrank/bitmanipulation/CounterGame.java
@@ -6,8 +6,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/24/15
+ * @author rampatra
+ * @since 6/24/15
* @time: 12:03 PM
*/
public class CounterGame {
@@ -37,7 +37,7 @@ public static String computeWinner(BigInteger n) {
return (louiseTurn) ? "Richard" : "Louise";
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = Integer.parseInt(in.nextLine());
diff --git a/src/main/java/com/hackerrank/bitmanipulation/Solution.java b/src/main/java/com/hackerrank/bitmanipulation/Solution.java
index 618b9120..d07b9f37 100644
--- a/src/main/java/com/hackerrank/bitmanipulation/Solution.java
+++ b/src/main/java/com/hackerrank/bitmanipulation/Solution.java
@@ -7,8 +7,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/24/15
+ * @author rampatra
+ * @since 6/24/15
* @time: 10:25 PM
*/
public class Solution {
diff --git a/src/main/java/com/hackerrank/bitmanipulation/TwosCompliment.java b/src/main/java/com/hackerrank/bitmanipulation/TwosCompliment.java
index 37fb21ae..0bfdc29f 100644
--- a/src/main/java/com/hackerrank/bitmanipulation/TwosCompliment.java
+++ b/src/main/java/com/hackerrank/bitmanipulation/TwosCompliment.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/24/15
+ * @author rampatra
+ * @since 6/24/15
* @time: 10:25 PM
*/
public class TwosCompliment {
@@ -19,7 +19,7 @@ public static long countSetBitsInRange(int start, int end) {
return count;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = Integer.parseInt(in.nextLine());
diff --git a/src/main/java/com/hackerrank/java/advanced/JavaVisitorPattern.java b/src/main/java/com/hackerrank/java/advanced/JavaVisitorPattern.java
new file mode 100644
index 00000000..5f91e9b5
--- /dev/null
+++ b/src/main/java/com/hackerrank/java/advanced/JavaVisitorPattern.java
@@ -0,0 +1,226 @@
+package com.hackerrank.java.advanced;
+
+import java.util.*;
+
+/**
+ * Level: Medium
+ * Problem Link: https://www.hackerrank.com/challenges/java-vistor-pattern/
+ *
+ * @author rampatra
+ * @since 2019-06-22
+ */
+enum Color {
+ RED, GREEN
+}
+
+abstract class Tree {
+
+ private int value;
+ private Color color;
+ private int depth;
+
+ public Tree(int value, Color color, int depth) {
+ this.value = value;
+ this.color = color;
+ this.depth = depth;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public Color getColor() {
+ return color;
+ }
+
+ public int getDepth() {
+ return depth;
+ }
+
+ public abstract void accept(TreeVis visitor);
+
+
+}
+
+class TreeNode extends Tree {
+
+ private ArrayList children = new ArrayList<>();
+
+ public TreeNode(int value, Color color, int depth) {
+ super(value, color, depth);
+ }
+
+ public void accept(TreeVis visitor) {
+ visitor.visitNode(this);
+
+ for (Tree child : children) {
+ child.accept(visitor);
+ }
+ }
+
+ public void addChild(Tree child) {
+ children.add(child);
+ }
+}
+
+class TreeLeaf extends Tree {
+
+ public TreeLeaf(int value, Color color, int depth) {
+ super(value, color, depth);
+ }
+
+ public void accept(TreeVis visitor) {
+ visitor.visitLeaf(this);
+ }
+}
+
+abstract class TreeVis {
+ public abstract int getResult();
+
+ public abstract void visitNode(TreeNode node);
+
+ public abstract void visitLeaf(TreeLeaf leaf);
+
+}
+
+class SumInLeavesVisitor extends TreeVis {
+ int nodeSum = 0;
+ int leafSum = 0;
+
+ public int getResult() {
+ //implement this
+ return leafSum;
+ }
+
+ public void visitNode(TreeNode node) {
+ //implement this
+ //nodeSum += node.getValue();
+ }
+
+ public void visitLeaf(TreeLeaf leaf) {
+ //implement this
+ leafSum += leaf.getValue();
+ }
+}
+
+class ProductOfRedNodesVisitor extends TreeVis {
+ int prodOfRedNodesAndLeaves = 1;
+ private final int M = 1000000007;
+
+ public int getResult() {
+ //implement this
+ return prodOfRedNodesAndLeaves;
+ }
+
+ public void visitNode(TreeNode node) {
+ //implement this
+ if (node.getColor() == Color.RED) {
+ prodOfRedNodesAndLeaves *= (node.getValue() % M);
+ }
+ }
+
+ public void visitLeaf(TreeLeaf leaf) {
+ //implement this
+ if (leaf.getColor() == Color.RED) {
+ prodOfRedNodesAndLeaves *= (leaf.getValue() % M);
+ }
+ }
+}
+
+class FancyVisitor extends TreeVis {
+ int sumOfNodesAtEvenDepth = 0;
+ int sumOfGreenLeaves = 0;
+
+ public int getResult() {
+ //implement this
+ return Math.abs(sumOfNodesAtEvenDepth - sumOfGreenLeaves);
+ }
+
+ public void visitNode(TreeNode node) {
+ //implement this
+ if (node.getDepth() % 2 == 0) {
+ sumOfNodesAtEvenDepth += node.getValue();
+ }
+ }
+
+ public void visitLeaf(TreeLeaf leaf) {
+ //implement this
+ if (leaf.getColor() == Color.GREEN) {
+ sumOfGreenLeaves += leaf.getValue();
+ }
+ }
+}
+
+public class JavaVisitorPattern {
+
+ public static Tree solve() {
+ //read the tree from STDIN and return its root as a return value of this function
+ Scanner s = new Scanner(System.in);
+
+ int numOfNodes = s.nextInt();
+ int[] nodeValues = new int[numOfNodes];
+ int[] nodeColors = new int[numOfNodes];
+ Map> parentToChildMap = new HashMap<>();
+ Map childToParentMap = new HashMap<>();
+
+ for (int i = 0; i < numOfNodes; i++) {
+ nodeValues[i] = s.nextInt();
+ }
+ for (int i = 0; i < numOfNodes; i++) {
+ nodeColors[i] = s.nextInt();
+ }
+ for (int i = 0; i < numOfNodes - 1; i++) {
+ int parentIndex = s.nextInt();
+ int childIndex = s.nextInt();
+
+ Set children = parentToChildMap.get(parentIndex - 1) != null ? parentToChildMap.get(parentIndex - 1) : new HashSet<>();
+ children.add(childIndex - 1);
+ parentToChildMap.put(parentIndex - 1, children);
+ childToParentMap.put(childIndex - 1, parentIndex - 1);
+ }
+
+ List nodes = new ArrayList<>(numOfNodes);
+ for (int i = 0; i < numOfNodes; i++) {
+
+ int depth = childToParentMap.get(i) == null ? -1 : nodes.get(childToParentMap.get(i)).getDepth();
+
+ if (parentToChildMap.get(i) != null) {
+ nodes.add(new TreeNode(nodeValues[i], nodeColors[i] == 0 ? Color.RED : Color.GREEN, depth + 1));
+ } else {
+ nodes.add(new TreeLeaf(nodeValues[i], nodeColors[i] == 0 ? Color.RED : Color.GREEN, depth + 1));
+ }
+ }
+
+
+ for (Map.Entry> entry : parentToChildMap.entrySet()) {
+
+ TreeNode parent = (TreeNode) nodes.get(entry.getKey());
+
+ for (Integer childIndex : entry.getValue()) {
+ parent.addChild(nodes.get(childIndex));
+ }
+ }
+
+ return nodes.get(0);
+ }
+
+
+ public static void main(String[] args) {
+ Tree root = solve();
+ SumInLeavesVisitor vis1 = new SumInLeavesVisitor();
+ ProductOfRedNodesVisitor vis2 = new ProductOfRedNodesVisitor();
+ FancyVisitor vis3 = new FancyVisitor();
+
+ root.accept(vis1);
+ root.accept(vis2);
+ root.accept(vis3);
+
+ int res1 = vis1.getResult();
+ int res2 = vis2.getResult();
+ int res3 = vis3.getResult();
+
+ System.out.println(res1);
+ System.out.println(res2);
+ System.out.println(res3);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/hackerrank/java/bignumber/BigDecimal.java b/src/main/java/com/hackerrank/java/bignumber/BigDecimal.java
new file mode 100644
index 00000000..7e1b804e
--- /dev/null
+++ b/src/main/java/com/hackerrank/java/bignumber/BigDecimal.java
@@ -0,0 +1,40 @@
+package com.hackerrank.java.bignumber;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Scanner;
+
+/**
+ * Problem Link: https://www.hackerrank.com/challenges/java-bigdecimal/
+ *
+ * @author rampatra
+ * @since 2019-06-22
+ */
+class BigDecimal {
+ public static void main(String[] args) {
+ //Input
+ Scanner sc = new Scanner(System.in);
+ int n = sc.nextInt();
+ String[] s = new String[n + 2];
+ for (int i = 0; i < n; i++) {
+ s[i] = sc.next();
+ }
+ sc.close();
+
+ //Write your code here
+ s = Arrays.copyOfRange(s, 0, s.length - 2);
+ List input = Arrays.asList(s);
+ Arrays.sort(s, (s1, s2) -> {
+ int compare = new java.math.BigDecimal(s2).compareTo(new java.math.BigDecimal(s1));
+ if (compare == 0) {
+ return Integer.compare(input.indexOf(s1), input.indexOf(s2));
+ }
+ return compare;
+ });
+
+ //Output
+ for (int i = 0; i < n; i++) {
+ System.out.println(s[i]);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/hackerrank/java/oops/JavaInheritance.java b/src/main/java/com/hackerrank/java/oops/JavaInheritance.java
index 4a1a90e2..b8d0d9e4 100644
--- a/src/main/java/com/hackerrank/java/oops/JavaInheritance.java
+++ b/src/main/java/com/hackerrank/java/oops/JavaInheritance.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/19/15
+ * @author rampatra
+ * @since 7/19/15
* @time: 3:36 PM
*/
public class JavaInheritance {
@@ -13,7 +13,7 @@ public void JavaInheritance() {
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
}
}
diff --git a/src/main/java/com/hackerrank/projecteuler/MultiplesOf3and5.java b/src/main/java/com/hackerrank/projecteuler/MultiplesOf3and5.java
index f90772b9..f56da78e 100644
--- a/src/main/java/com/hackerrank/projecteuler/MultiplesOf3and5.java
+++ b/src/main/java/com/hackerrank/projecteuler/MultiplesOf3and5.java
@@ -5,13 +5,13 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 1/1/16
+ * @author rampatra
+ * @since 1/1/16
* @time: 8:48 AM
*/
public class MultiplesOf3and5 {
- public static void main(String a[]) {
+ public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = Integer.parseInt(in.nextLine());
diff --git a/src/main/java/com/hackerrank/tutorials/ctci/QueuesWithTwoStacks.java b/src/main/java/com/hackerrank/tutorials/ctci/QueuesWithTwoStacks.java
index 6d4e3ae9..333ecd1d 100644
--- a/src/main/java/com/hackerrank/tutorials/ctci/QueuesWithTwoStacks.java
+++ b/src/main/java/com/hackerrank/tutorials/ctci/QueuesWithTwoStacks.java
@@ -7,7 +7,7 @@
* Question: https://www.hackerrank.com/challenges/ctci-queue-using-two-stacks
* Level: Medium
*
- * @author ramswaroop
+ * @author rampatra
* @version 07/10/2016
*/
public class QueuesWithTwoStacks {
diff --git a/src/main/java/com/hackerrank/tutorials/ctci/RansomNote.java b/src/main/java/com/hackerrank/tutorials/ctci/RansomNote.java
index eb8414ee..b0d45c75 100644
--- a/src/main/java/com/hackerrank/tutorials/ctci/RansomNote.java
+++ b/src/main/java/com/hackerrank/tutorials/ctci/RansomNote.java
@@ -8,7 +8,7 @@
* Question: https://www.hackerrank.com/challenges/ctci-ransom-note
* Level: Easy
*
- * @author ramswaroop
+ * @author rampatra
* @version 30/09/2016
*/
public class RansomNote {
diff --git a/src/main/java/com/leetcode/arrays/BuySellStocks.java b/src/main/java/com/leetcode/arrays/BuySellStocks.java
new file mode 100644
index 00000000..4d4ba02b
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/BuySellStocks.java
@@ -0,0 +1,67 @@
+package com.leetcode.arrays;
+
+/**
+ * Level: Easy
+ * Link: https://leetcode.com/problems/best-time-to-buy-and-sell-stock/
+ * Description:
+ * Say you have an array for which the ith element is the price of a given stock on day i.
+ *
+ * If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock),
+ * design an algorithm to find the maximum profit.
+ *
+ * Note that you cannot sell a stock before you buy one.
+ *
+ * Example 1:
+ *
+ * Input: [7,1,5,3,6,4]
+ * Output: 5
+ * Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
+ * Not 7-1 = 6, as selling price needs to be larger than buying price.
+ *
+ * Example 2:
+ *
+ * Input: [7,6,4,3,1]
+ * Output: 0
+ * Explanation: In this case, no transaction is done, i.e. max profit = 0.
+ *
+ * @author rampatra
+ * @since 2019-04-23
+ */
+public class BuySellStocks {
+
+ /**
+ * Time complexity: O(n)
+ * where,
+ * n = no. of stock prices
+ *
+ * Runtime: 0 ms.
+ *
+ * @param prices
+ * @return
+ */
+ public static int maxProfit(int[] prices) {
+ int profit = 0;
+ int buyPrice = Integer.MAX_VALUE;
+
+ for (int i = 0; i < prices.length; i++) {
+ if (prices[i] < buyPrice) {
+ buyPrice = prices[i];
+ } else if (prices[i] - buyPrice > profit) {
+ profit = prices[i] - buyPrice;
+ }
+ }
+
+ return profit;
+ }
+
+ public static void main(String[] args) {
+
+ System.out.println(maxProfit(new int[]{7, 1, 5, 3, 6, 4}));
+ System.out.println(maxProfit(new int[]{7, 1, 5, 0, 6, 4}));
+ System.out.println(maxProfit(new int[]{4, 3, 2, 1}));
+
+ // edge cases
+ System.out.println(maxProfit(new int[]{}));
+ System.out.println(maxProfit(new int[]{1}));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/arrays/BuySellStocksII.java b/src/main/java/com/leetcode/arrays/BuySellStocksII.java
new file mode 100644
index 00000000..d215246e
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/BuySellStocksII.java
@@ -0,0 +1,94 @@
+package com.leetcode.arrays;
+
+/**
+ * Level: Easy
+ * Link: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/
+ * Description:
+ * Say you have an array for which the ith element is the price of a given stock on day i.
+ *
+ * Design an algorithm to find the maximum profit. You may complete as many transactions as you
+ * like (i.e., buy one and sell one share of the stock multiple times).
+ *
+ * Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock
+ * before you buy again).
+ *
+ * @author rampatra
+ * @since 2019-04-23
+ */
+public class BuySellStocksII {
+
+ /**
+ * The key point is we need to consider every peak immediately following a valley to maximize the profit. In case
+ * we skip one of the peaks (trying to obtain more profit), we will end up losing the profit over one of the
+ * transactions leading to an overall lesser profit.
+ * Read this to learn more.
+ *
+ * Time complexity: O(n)
+ * where,
+ * n = no. of stock prices
+ *
+ * Runtime: 0 ms.
+ *
+ * @param prices
+ * @return
+ */
+ public static int maxProfit(int[] prices) {
+ int valley;
+ int peak;
+ int maxProfit = 0;
+
+ for (int i = 0; i < prices.length; i++) {
+ while (i < prices.length - 1 && prices[i] > prices[i + 1]) {
+ i++;
+ }
+ valley = i;
+
+ while (i < prices.length - 1 && prices[i] < prices[i + 1]) {
+ i++;
+ }
+ peak = i;
+
+ maxProfit += prices[peak] - prices[valley];
+ }
+
+ return maxProfit;
+ }
+
+ /**
+ * This solution follows the logic used in the above approach {@link #maxProfit(int[])}, but with only a slight
+ * variation. In this case, instead of looking for every peak following a valley, we can simply go on crawling over
+ * the slope and keep on adding the profit obtained from every consecutive transaction.
+ * In the end, we will be using the peaks and valleys effectively, but we need not track the costs corresponding to
+ * the peaks and valleys along with the maximum profit, but we can directly keep on adding the difference between the
+ * consecutive numbers of the array if the second number is larger than the first one, and at the total sum we obtain
+ * will be the maximum profit. This approach will simplify the solution.
+ *
+ * Time complexity: O(n)
+ * where,
+ * n = no. of stock prices
+ *
+ * @param prices
+ * @return
+ */
+ public static int maxProfitSimplified(int[] prices) {
+ int maxProfit = 0;
+ for (int i = 1; i < prices.length; i++) {
+ if (prices[i] > prices[i - 1]) {
+ maxProfit += prices[i] - prices[i - 1];
+ }
+ }
+ return maxProfit;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(maxProfit(new int[]{7, 1, 5, 3, 6, 4}));
+ System.out.println(maxProfit(new int[]{1, 2, 3, 4, 5}));
+ System.out.println(maxProfit(new int[]{7, 6, 4, 3, 1}));
+
+ System.out.println("----");
+
+ System.out.println(maxProfitSimplified(new int[]{7, 1, 5, 3, 6, 4}));
+ System.out.println(maxProfitSimplified(new int[]{1, 2, 3, 4, 5}));
+ System.out.println(maxProfitSimplified(new int[]{7, 6, 4, 3, 1}));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/arrays/CanPlaceFlowers.java b/src/main/java/com/leetcode/arrays/CanPlaceFlowers.java
new file mode 100644
index 00000000..916499ac
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/CanPlaceFlowers.java
@@ -0,0 +1,68 @@
+package com.leetcode.arrays;
+
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/can-place-flowers/
+ * Problem Description:
+ * Suppose you have a long flowerBed in which some of the plots are planted and some are not. However, flowers cannot
+ * be planted in adjacent plots - they would compete for water and both would die.
+ *
+ * Given a flowerBed (represented as an array containing 0 and 1, where 0 means empty and 1 means not empty), and a
+ * number n, return if n new flowers can be planted in it without violating the no-adjacent-flowers rule.
+ *
+ * Example 1:
+ * Input: flowerBed = [1,0,0,0,1], n = 1
+ * Output: True
+ *
+ * Example 2:
+ * Input: flowerBed = [1,0,0,0,1], n = 2
+ * Output: False
+ *
+ * Note:
+ * The input array won't violate no-adjacent-flowers rule.
+ * The input array size is in the range of [1, 20000].
+ * n is a non-negative integer which won't exceed the input array size.
+ *
+ * @author rampatra
+ * @since 2019-07-24
+ */
+public class CanPlaceFlowers {
+
+ /**
+ * Time Complexity: O(n)
+ * Space Complexity: O(1)
+ * Runtime: 1 ms.
+ *
+ * @param flowerBed
+ * @param n
+ * @return
+ */
+ public static boolean canPlaceFlowers(int[] flowerBed, int n) {
+ int i = 0, count = 0;
+ while (i < flowerBed.length) {
+ if (flowerBed[i] == 0 && (i == 0 || flowerBed[i - 1] == 0) && (i == flowerBed.length - 1 || flowerBed[i + 1] == 0)) {
+ flowerBed[i++] = 1;
+ count++;
+ }
+ if (count >= n)
+ return true;
+ i++;
+ }
+ return false;
+ }
+
+ public static void main(String[] args) {
+ assertTrue(canPlaceFlowers(new int[]{0}, 0));
+ assertTrue(canPlaceFlowers(new int[]{0}, 1));
+ assertTrue(canPlaceFlowers(new int[]{1}, 0));
+ assertFalse(canPlaceFlowers(new int[]{1}, 1));
+ assertTrue(canPlaceFlowers(new int[]{1, 0, 0, 0, 1}, 1));
+ assertFalse(canPlaceFlowers(new int[]{1, 0, 0, 0, 1}, 2));
+ assertFalse(canPlaceFlowers(new int[]{1, 0, 0, 0, 0, 1}, 2));
+ assertTrue(canPlaceFlowers(new int[]{1, 0, 0, 0, 1, 0, 0}, 2));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/arrays/FindTheCelebrity.java b/src/main/java/com/leetcode/arrays/FindTheCelebrity.java
new file mode 100644
index 00000000..1b15d996
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/FindTheCelebrity.java
@@ -0,0 +1,105 @@
+package com.leetcode.arrays;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Problem Link: https://leetcode.com/problems/find-the-celebrity/
+ * Problem Description:
+ * Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist one celebrity.
+ * The definition of a celebrity is that all the other n - 1 people know him/her but he/she does not know any of them.
+ *
+ * Now you want to find out who the celebrity is or verify that there is not one. The only thing you are allowed to do
+ * is to ask questions like: "Hi, A. Do you know B?" to get information of whether A knows B. You need to find out the
+ * celebrity (or verify there is not one) by asking as few questions as possible (in the asymptotic sense).
+ *
+ * You are given a helper function bool knows(a, b) which tells you whether A knows B. Implement a
+ * function int findCelebrity(n). There will be exactly one celebrity if he/she is in the party. Return the celebrity's
+ * label if there is a celebrity in the party. If there is no celebrity, return -1.
+ *
+ * Example 1:
+ *
+ * Input: graph = [
+ * [1,1,0],
+ * [0,1,0],
+ * [1,1,1]
+ * ]
+ * Output: 1
+ * Explanation: There are three persons labeled with 0, 1 and 2. graph[i][j] = 1 means person i knows person j, otherwise
+ * graph[i][j] = 0 means person i does not know person j. The celebrity is the person labeled as 1 because both 0 and 2
+ * know him but 1 does not know anybody.
+ *
+ *
+ * Example 2:
+ *
+ * Input: graph = [
+ * [1,0,1],
+ * [1,1,0],
+ * [0,1,1]
+ * ]
+ * Output: -1
+ * Explanation: There is no celebrity.
+ *
+ *
+ * Note: The directed graph is represented as an adjacency matrix, which is an n x n matrix where a[i][j] = 1 means
+ * person i knows person j while a[i][j] = 0 means the contrary. Remember that you won't have direct access to the
+ * adjacency matrix.
+ *
+ * @author rampatra
+ * @since 2019-08-04
+ */
+public class FindTheCelebrity {
+
+ private int[][] knowsMatrix;
+
+ FindTheCelebrity(int[][] knowsMatrix) {
+ this.knowsMatrix = knowsMatrix;
+ }
+
+ public boolean knows(int a, int b) {
+ return knowsMatrix[a][b] == 1;
+ }
+
+ /**
+ * Time Complexity: O(n)
+ * Space Complexity: O(1)
+ * Runtime: 6 ms.
+ *
+ * @param n
+ * @return
+ */
+ public int findCelebrity(int n) {
+ int celebrityIndex = 0;
+
+ for (int i = 1; i < n; i++) {
+ // if a person doesn't know another person then he maybe a celebrity
+ if (!knows(i, celebrityIndex)) {
+ celebrityIndex = i;
+ }
+ }
+
+ for (int i = 0; i < n; i++) {
+ // verify whether the celebrity only knows himself and all other people know the celebrity
+ if ((knows(celebrityIndex, i) && i != celebrityIndex) || !knows(i, celebrityIndex)) {
+ return -1;
+ }
+ }
+
+ return celebrityIndex;
+ }
+
+ public static void main(String[] args) {
+ FindTheCelebrity findTheCelebrity = new FindTheCelebrity(new int[][]{
+ {1, 1, 0},
+ {0, 1, 0},
+ {1, 1, 1}});
+
+ assertEquals(1, findTheCelebrity.findCelebrity(3));
+
+ findTheCelebrity = new FindTheCelebrity(new int[][]{
+ {1, 0},
+ {0, 1}});
+
+ assertEquals(-1, findTheCelebrity.findCelebrity(2));
+ }
+}
diff --git a/src/main/java/com/leetcode/arrays/InsertInterval.java b/src/main/java/com/leetcode/arrays/InsertInterval.java
new file mode 100644
index 00000000..52155f19
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/InsertInterval.java
@@ -0,0 +1,78 @@
+package com.leetcode.arrays;
+
+import java.util.Arrays;
+
+/**
+ * Level: Hard
+ * Problem Link: https://leetcode.com/problems/insert-interval/
+ * Problem Description:
+ * Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).
+ *
+ * You may assume that the intervals were initially sorted according to their start times.
+ *
+ * Example 1:
+ * Input: intervals = [[1,3],[6,9]], newInterval = [2,5]
+ * Output: [[1,5],[6,9]]
+ *
+ * Example 2:
+ * Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
+ * Output: [[1,2],[3,10],[12,16]]
+ * Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10].
+ *
+ * Companies: LinkedIn.
+ * Related: {@link MergeIntervals}.
+ *
+ * @author rampatra
+ * @since 2019-07-23
+ */
+public class InsertInterval {
+
+ /**
+ * Time Complexity: O(n)
+ * Space Complexity: O(n)
+ * Runtime: 2 ms.
+ *
+ * @param intervals
+ * @param newInterval
+ * @return
+ */
+ public static int[][] insert(int[][] intervals, int[] newInterval) {
+ if (intervals.length == 0 && newInterval.length == 0) {
+ return new int[][]{};
+ } else if (intervals.length == 0) {
+ return new int[][]{newInterval};
+ }
+
+ int[][] mergedIntervals = new int[intervals.length + 1][2];
+ int j = 0;
+
+ for (int i = 0; i < intervals.length; i++) {
+ if (newInterval == null || newInterval[0] > intervals[i][1]) { // newInterval is after the ith interval
+ mergedIntervals[j++] = intervals[i];
+ } else if (newInterval[1] < intervals[i][0]) { // newInterval is before the ith interval
+ mergedIntervals[j++] = newInterval;
+ mergedIntervals[j++] = intervals[i];
+ newInterval = null;
+ } else { // if overlapping
+ newInterval[0] = Math.min(newInterval[0], intervals[i][0]);
+ newInterval[1] = Math.max(newInterval[1], intervals[i][1]);
+ }
+ }
+
+ if (newInterval != null) {
+ mergedIntervals[j++] = newInterval;
+ }
+
+ return Arrays.copyOfRange(mergedIntervals, 0, j);
+ }
+
+ public static void main(String[] args) {
+ System.out.println(Arrays.deepToString(insert(new int[][]{}, new int[]{})));
+ System.out.println(Arrays.deepToString(insert(new int[][]{}, new int[]{5, 7})));
+ System.out.println(Arrays.deepToString(insert(new int[][]{{1, 5}}, new int[]{0, 0})));
+ System.out.println(Arrays.deepToString(insert(new int[][]{{1, 5}}, new int[]{2, 3})));
+ System.out.println(Arrays.deepToString(insert(new int[][]{{2, 5}, {6, 7}, {8, 9}}, new int[]{0, 1})));
+ System.out.println(Arrays.deepToString(insert(new int[][]{{1, 3}, {6, 9}}, new int[]{2, 5})));
+ System.out.println(Arrays.deepToString(insert(new int[][]{{1, 2}, {3, 5}, {6, 7}, {8, 10}, {12, 16}}, new int[]{4, 8})));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/arrays/MajorityElement.java b/src/main/java/com/leetcode/arrays/MajorityElement.java
new file mode 100644
index 00000000..2ccdd116
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/MajorityElement.java
@@ -0,0 +1,47 @@
+package com.leetcode.arrays;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/majority-element/
+ * Problem Description:
+ * Given an array of size n, find the majority element. The majority element is the element
+ * that appears more than ⌊ n/2 ⌋ times. You may assume that the array is non-empty and the
+ * majority element always exist in the array.
+ *
+ * @author rampatra
+ * @since 2019-04-27
+ */
+public class MajorityElement {
+
+ /**
+ * Time complexity: O(n)
+ * Runtime: 1 ms.
+ *
+ * @param nums
+ * @return
+ */
+ public static int majorityElement(int[] nums) {
+ int count = 1;
+ int majElem = nums[0];
+
+ for (int i = 1; i < nums.length; i++) {
+ if (count <= 0) {
+ majElem = nums[i];
+ count = 0;
+ }
+ if (majElem == nums[i]) {
+ count++;
+ } else {
+ count--;
+ }
+ }
+
+ return majElem;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(majorityElement(new int[]{10, 9, 9, 9, 10}));
+ System.out.println(majorityElement(new int[]{2, 3, 2, 2, 3, 2}));
+ System.out.println(majorityElement(new int[]{2, 3, 2, 2, 2, 3}));
+ }
+}
diff --git a/src/main/java/com/leetcode/arrays/MergeIntervals.java b/src/main/java/com/leetcode/arrays/MergeIntervals.java
new file mode 100644
index 00000000..58f56ebc
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/MergeIntervals.java
@@ -0,0 +1,78 @@
+package com.leetcode.arrays;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * Level: Medium
+ * Problem Link: https://leetcode.com/problems/merge-intervals/
+ * Problem Description:
+ *
+ * Given a collection of intervals, merge all overlapping intervals.
+ *
+ * Example 1:
+ * Input: [[1,3],[2,6],[8,10],[15,18]]
+ * Output: [[1,6],[8,10],[15,18]]
+ * Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].
+ *
+ * Example 2:
+ * Input: [[1,4],[4,5]]
+ * Output: [[1,5]]
+ * Explanation: Intervals [1,4] and [4,5] are considered overlapping.
+ *
+ * Companies: LinkedIn
+ * Related: {@link InsertInterval}.
+ *
+ * @author rampatra
+ * @since 2019-07-22
+ */
+public class MergeIntervals {
+
+ /**
+ * Time complexity: O(n log n)
+ * Space complexity: O(n)
+ * Runtime: 6 ms
+ *
+ * @param intervals a list of intervals, may not be sorted
+ * @return a list of intervals, with overlapping intervals merged
+ */
+ public static int[][] merge(int[][] intervals) {
+ // some validations
+ if (intervals.length == 0) return new int[0][2];
+
+ // we first sort the intervals based on their start times
+ Arrays.sort(intervals, new IntervalComparator());
+
+ int[][] mergedIntervals = new int[intervals.length][2];
+ int lastMergedIndex = 0;
+ mergedIntervals[lastMergedIndex] = intervals[0];
+
+ for (int i = 1; i < intervals.length; i++) {
+ if (isOverlap(mergedIntervals[lastMergedIndex], intervals[i])) {
+ // if two intervals overlap, then merge the two
+ mergedIntervals[lastMergedIndex] = new int[]{Math.min(mergedIntervals[lastMergedIndex][0], intervals[i][0]),
+ Math.max(mergedIntervals[lastMergedIndex][1], intervals[i][1])};
+ } else {
+ mergedIntervals[++lastMergedIndex] = intervals[i];
+ }
+ }
+
+ return Arrays.copyOfRange(mergedIntervals, 0, lastMergedIndex + 1);
+ }
+
+ private static boolean isOverlap(int[] interval1, int[] interval2) {
+ return interval1[0] <= interval2[0] && interval1[1] >= interval2[0];
+ }
+
+ private static class IntervalComparator implements Comparator {
+ @Override
+ public int compare(int[] interval1, int[] interval2) {
+ return interval1[0] - interval2[0];
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println(Arrays.deepToString(merge(new int[][]{{1, 3}, {2, 6}, {8, 10}, {15, 18}})));
+ System.out.println(Arrays.deepToString(merge(new int[][]{{1, 4}, {4, 5}})));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/arrays/MergeSortedArray.java b/src/main/java/com/leetcode/arrays/MergeSortedArray.java
new file mode 100644
index 00000000..975db8ec
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/MergeSortedArray.java
@@ -0,0 +1,86 @@
+package com.leetcode.arrays;
+
+import java.util.Arrays;
+
+/**
+ * Level: Easy
+ * Link: https://leetcode.com/problems/merge-sorted-array/
+ * Description:
+ * Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.
+ *
+ * Note:
+ * The number of elements initialized in nums1 and nums2 are m and n respectively.
+ * You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold
+ * additional elements from nums2.
+ *
+ * Example:
+ * Input:
+ * nums1 = [1,2,3,0,0,0], m = 3
+ * nums2 = [2,5,6], n = 3
+ * Output: [1,2,2,3,5,6]
+ *
+ * @author rampatra
+ * @since 2019-04-26
+ */
+public class MergeSortedArray {
+
+ /**
+ * Time complexity: O(m*n)
+ * Runtime: 1 ms.
+ *
+ * @param nums1
+ * @param m
+ * @param nums2
+ * @param n
+ */
+ public static void mergeSimple(int[] nums1, int m, int[] nums2, int n) {
+ int i = 0;
+
+ for (int j = 0; j < n; j++) {
+ // find the index where the element from nums2 need to be inserted
+ while (i < m + j && nums1[i] < nums2[j]) {
+ i++;
+ }
+ // copy elements from i+1th position to one position right
+ for (int k = m + j; k > i; k--) { // note: replacing this with System.arraycopy() gives a 0 ms runtime
+ nums1[k] = nums1[k - 1];
+ }
+ nums1[i] = nums2[j];
+ }
+ }
+
+ /**
+ * Time complexity: O(m+n)
+ * Runtime: 0 ms.
+ *
+ * @param nums1
+ * @param m
+ * @param nums2
+ * @param n
+ */
+ public static void merge(int[] nums1, int m, int[] nums2, int n) {
+ for (int i = m + n - 1; i >= 0; i--) {
+ if (m == 0) {
+ nums1[i] = nums2[--n];
+ } else if (n == 0) { // we ran out of nums2 elements so there is nothing left to merge
+ return;
+ } else if (nums1[m - 1] > nums2[n - 1]) {
+ nums1[i] = nums1[--m];
+ } else {
+ nums1[i] = nums2[--n];
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ int[] nums1 = {1, 2, 3, 0, 0, 0};
+ int[] nums2 = {4, 5, 6};
+ merge(nums1, 3, nums2, 3);
+ System.out.println(Arrays.toString(nums1));
+
+ nums1 = new int[]{4, 5, 6, 0, 0, 0};
+ nums2 = new int[]{1, 2, 3};
+ merge(nums1, 3, nums2, 3);
+ System.out.println(Arrays.toString(nums1));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/arrays/NumberOfIslands.java b/src/main/java/com/leetcode/arrays/NumberOfIslands.java
new file mode 100644
index 00000000..04ac6831
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/NumberOfIslands.java
@@ -0,0 +1,107 @@
+package com.leetcode.arrays;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Link: https://leetcode.com/problems/number-of-islands/
+ * Description:
+ * Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. 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.
+ *
+ * Example 1:
+ * Input:
+ * 11110
+ * 11010
+ * 11000
+ * 00000
+ * Output: 1
+ *
+ * Example 2:
+ * Input:
+ * 11000
+ * 11000
+ * 00100
+ * 00011
+ * Output: 3
+ *
+ * @author rampatra
+ * @since 2019-08-07
+ */
+public class NumberOfIslands {
+
+ /**
+ * The idea is simple and straightforward. Once we encounter land ('1' in grid) we drown the island or change the
+ * neighboring '1's to '0's. Therefore, the number of '1's we encounter, we can say that we have that many islands.
+ *
+ * Time Complexity: O(n)
+ * Space Complexity: O(n)
+ * Runtime: 1 ms.
+ *
+ * @param grid
+ * @return
+ */
+ public static int numIslands(char[][] grid) {
+ int count = 0;
+
+ for (int i = 0; i < grid.length; i++) {
+ for (int j = 0; j < grid[0].length; j++) {
+ if (grid[i][j] == '1') {
+ drownTheIsland(grid, i, j);
+ count++;
+ }
+ }
+ }
+
+ return count;
+ }
+
+ private static void drownTheIsland(char[][] grid, int i, int j) {
+ if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] == '0') {
+ return;
+ }
+
+ grid[i][j] = '0';
+
+ drownTheIsland(grid, i, j + 1);
+ drownTheIsland(grid, i, j - 1);
+ drownTheIsland(grid, i + 1, j);
+ drownTheIsland(grid, i - 1, j);
+ }
+
+ public static void main(String[] args) {
+ assertEquals(1, numIslands(new char[][]{
+ {'1', '1', '1', '1', '0'},
+ {'1', '1', '0', '1', '0'},
+ {'1', '1', '0', '0', '0'},
+ {'0', '0', '0', '0', '0'}
+ }));
+
+ assertEquals(2, numIslands(new char[][]{
+ {'1', '1', '1', '1', '0'},
+ {'1', '1', '0', '1', '0'},
+ {'1', '1', '0', '0', '0'},
+ {'0', '0', '0', '1', '0'}
+ }));
+
+ assertEquals(1, numIslands(new char[][]{
+ {'1', '1', '1', '1', '1'},
+ {'1', '1', '1', '1', '1'},
+ {'1', '1', '1', '1', '1'},
+ {'1', '1', '1', '1', '1'}
+ }));
+
+ assertEquals(1, numIslands(new char[][]{
+ {'1'}
+ }));
+
+ assertEquals(0, numIslands(new char[][]{
+ {'0'}
+ }));
+
+ assertEquals(0, numIslands(new char[][]{
+ {}
+ }));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/arrays/PascalsTriangle.java b/src/main/java/com/leetcode/arrays/PascalsTriangle.java
new file mode 100644
index 00000000..5f32d69f
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/PascalsTriangle.java
@@ -0,0 +1,53 @@
+package com.leetcode.arrays;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Level: Easy
+ * Problem: https://leetcode.com/problems/pascals-triangle/
+ *
+ * @author rampatra
+ * @since 2019-04-20
+ */
+public class PascalsTriangle {
+
+ /**
+ * Time complexity: O(numRows^2)
+ * Space complexity: O(numRows^2)
+ *
+ * Runtime: 0 ms.
+ *
+ * @param numRows
+ * @return
+ */
+ public static List> generatePascalsTriangle(int numRows) {
+ List> pascalsTriangle = new ArrayList<>();
+
+ if (numRows == 0) return pascalsTriangle;
+
+ List firstRow = new ArrayList<>();
+ firstRow.add(1);
+ pascalsTriangle.add(firstRow);
+
+ List prevRow;
+ for (int i = 1; i < numRows; i++) {
+ prevRow = pascalsTriangle.get(i - 1);
+
+ List currRow = new ArrayList<>();
+ currRow.add(1);
+ for (int j = 0; j < prevRow.size() - 1; j++) {
+ currRow.add(prevRow.get(j) + prevRow.get(j + 1));
+ }
+ currRow.add(1);
+
+ pascalsTriangle.add(currRow);
+ }
+
+ return pascalsTriangle;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(generatePascalsTriangle(5));
+ }
+}
diff --git a/src/main/java/com/leetcode/arrays/RemoveDuplicates.java b/src/main/java/com/leetcode/arrays/RemoveDuplicates.java
new file mode 100644
index 00000000..57eba5ad
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/RemoveDuplicates.java
@@ -0,0 +1,62 @@
+package com.leetcode.arrays;
+
+import java.util.Arrays;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/remove-duplicates-from-sorted-array/
+ * Problem Description:
+ * Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length.
+ *
+ * Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
+ * Example 1:
+ *
+ * Given nums = [1,1,2]
+ *
+ * Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.
+ *
+ * NOTE: It doesn't matter what you leave beyond the returned length.
+ *
+ * @author rampatra
+ * @since 2019-04-24
+ */
+public class RemoveDuplicates {
+
+ /**
+ * This removes the duplicates from the array in-place.
+ *
+ * Time complexity: O(n)
+ * where,
+ * n = no. of elements in the array
+ *
+ * Runtime: 1 ms.
+ *
+ * @param nums
+ * @return
+ */
+ public static int removeDuplicatesInSortedArray(int[] nums) {
+ int insertIndex = 0;
+
+ for (int i = 1; i < nums.length; i++) {
+ if (nums[i] != nums[i - 1]) {
+ nums[++insertIndex] = nums[i];
+ }
+ }
+
+ return insertIndex + 1;
+ }
+
+ public static void main(String[] args) {
+ int[] arr = new int[]{1, 1, 2};
+ System.out.println(removeDuplicatesInSortedArray(arr));
+ System.out.println(Arrays.toString(arr));
+
+ arr = new int[]{0, 0, 1, 1, 1, 2, 2, 3, 3, 4};
+ System.out.println(removeDuplicatesInSortedArray(arr));
+ System.out.println(Arrays.toString(arr));
+
+ arr = new int[]{0, 1, 2, 3, 4, 5};
+ System.out.println(removeDuplicatesInSortedArray(arr));
+ System.out.println(Arrays.toString(arr));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/arrays/RotateArray.java b/src/main/java/com/leetcode/arrays/RotateArray.java
new file mode 100644
index 00000000..91475160
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/RotateArray.java
@@ -0,0 +1,93 @@
+package com.leetcode.arrays;
+
+import java.util.Arrays;
+
+/**
+ * Level: Easy
+ * Link: https://leetcode.com/problems/rotate-array/
+ * Description:
+ * Given an array, rotate the array to the right by k steps, where k is non-negative.
+ *
+ * Example 1:
+ * Input: [1,2,3,4,5,6,7] and k = 3
+ * Output: [5,6,7,1,2,3,4]
+ * Explanation:
+ * rotate 1 steps to the right: [7,1,2,3,4,5,6]
+ * rotate 2 steps to the right: [6,7,1,2,3,4,5]
+ * rotate 3 steps to the right: [5,6,7,1,2,3,4]
+ *
+ * Example 2:
+ * Input: [-1,-100,3,99] and k = 2
+ * Output: [3,99,-1,-100]
+ * Explanation:
+ * rotate 1 steps to the right: [99,-1,-100,3]
+ * rotate 2 steps to the right: [3,99,-1,-100]
+ *
+ * Note:
+ * Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
+ * Could you do it in-place with O(1) extra space?
+ *
+ * @author rampatra
+ * @since 2019-04-20
+ */
+public class RotateArray {
+
+ /**
+ * Time complexity: O(n)
+ * where,
+ * n = no. of elements in the array
+ *
+ * Runtime: 0 ms.
+ *
+ * @param nums
+ * @param k
+ */
+ public static void rotate(int[] nums, int k) {
+
+ if (k > nums.length) {
+ k = k % nums.length;
+ }
+
+ reverse(nums, 0, nums.length);
+ reverse(nums, 0, k);
+ reverse(nums, k, nums.length);
+ }
+
+ private static void reverse(int[] nums, int start, int end) {
+ int temp;
+ for (int i = start, j = end - 1; i < j; i++, j--) {
+ temp = nums[i];
+ nums[i] = nums[j];
+ nums[j] = temp;
+ }
+ }
+
+ public static void main(String[] args) {
+ // normal case
+ int[] arr = {1, 2, 3, 4, 5, 6, 7};
+ System.out.println(Arrays.toString(arr));
+ rotate(arr, 3);
+ System.out.println(Arrays.toString(arr));
+
+ // edge cases
+ arr = new int[]{1, 2};
+ System.out.println(Arrays.toString(arr));
+ rotate(arr, 2);
+ System.out.println(Arrays.toString(arr)); // should be [1, 2]
+
+ arr = new int[]{1, 2};
+ System.out.println(Arrays.toString(arr));
+ rotate(arr, 3);
+ System.out.println(Arrays.toString(arr)); // should be [2, 1]
+
+ arr = new int[]{1, 2, 3};
+ System.out.println(Arrays.toString(arr));
+ rotate(arr, 4);
+ System.out.println(Arrays.toString(arr)); // should be [3, 1, 2]
+
+ arr = new int[]{1};
+ System.out.println(Arrays.toString(arr));
+ rotate(arr, 2);
+ System.out.println(Arrays.toString(arr));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/arrays/ShortestWordDistance.java b/src/main/java/com/leetcode/arrays/ShortestWordDistance.java
new file mode 100644
index 00000000..5cd0c821
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/ShortestWordDistance.java
@@ -0,0 +1,71 @@
+package com.leetcode.arrays;
+
+import com.leetcode.hashtables.ShortestWordDistanceII;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/shortest-word-distance/
+ * Problem Description:
+ * Given a list of words and two words word1 and word2, return the shortest distance between these two words in the
+ * list of words.
+ *
+ * Example 1:
+ * Assume that words = ["practice", "makes", "perfect", "coding", "makes"].
+ * Given word1 = "coding", word2 = "practice", return 3.
+ * Given word1 = "makes", word2 = "coding", return 1.
+ *
+ * Note: You may assume that word1 does not equal to word2, and word1 and word2 are both in the list.
+ *
+ * Lastly, for a more complex variant, see {@link ShortestWordDistanceII}.
+ *
+ * @author rampatra
+ * @since 2019-07-31
+ */
+public class ShortestWordDistance {
+
+ /**
+ * Time Complexity:
+ * Space Complexity:
+ * Runtime: 1 ms.
+ *
+ * @param words
+ * @param word1
+ * @param word2
+ * @return
+ */
+ public static int findShortestDistance(String[] words, String word1, String word2) {
+ int indexWord1 = -1;
+ int indexWord2 = -1;
+ int minDistance = Integer.MAX_VALUE;
+
+ for (int i = 0; i < words.length; i++) {
+ if (words[i].equals(word1)) {
+ indexWord1 = i;
+ } else if (words[i].equals(word2)) {
+ indexWord2 = i;
+ }
+ if (indexWord1 != -1 && indexWord2 != -1) {
+ minDistance = Math.min(minDistance, Math.abs(indexWord1 - indexWord2));
+ }
+ }
+
+ return minDistance;
+ }
+
+ public static void main(String[] args) {
+ assertEquals(3, findShortestDistance(new String[]{"practice", "makes", "perfect", "coding", "makes"},
+ "practice", "coding"));
+ assertEquals(3, findShortestDistance(new String[]{"practice", "makes", "perfect", "coding", "makes"},
+ "coding", "practice"));
+ assertEquals(1, findShortestDistance(new String[]{"practice", "makes", "perfect", "coding", "makes"},
+ "makes", "coding"));
+ assertEquals(1, findShortestDistance(new String[]{"practice", "makes", "perfect", "coding", "makes"},
+ "makes", "perfect"));
+ assertEquals(0, findShortestDistance(new String[]{"practice", "makes", "perfect", "coding", "makes"},
+ "perfect", "perfect"));
+ assertEquals(0, findShortestDistance(new String[]{"practice", "makes", "perfect", "coding", "makes"},
+ "makes", "makes"));
+ }
+}
diff --git a/src/main/java/com/leetcode/arrays/ShortestWordDistanceIII.java b/src/main/java/com/leetcode/arrays/ShortestWordDistanceIII.java
new file mode 100644
index 00000000..0d404633
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/ShortestWordDistanceIII.java
@@ -0,0 +1,80 @@
+package com.leetcode.arrays;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/shortest-word-distance-iii/
+ * Problem Description:
+ * This is a follow-up problem of {@link ShortestWordDistance}. The only difference is that now word1 could be the
+ * same as word2.
+ *
+ * Given a list of words and two words word1 and word2, return the shortest distance between these two words in the list.
+ * word1 and word2 may be the same and they represent two individual words in the list.
+ *
+ * For example,
+ * Assume that words = ["practice", "makes", "perfect", "coding", "makes"].
+ * Given word1 = “makes”, word2 = “coding”, return 1.
+ * Given word1 = "makes", word2 = "makes", return 3.
+ *
+ * Note: You may assume word1 and word2 are both in the list. If they are same then it's guaranteed that there are
+ * two occurrences of the same.
+ *
+ * @author rampatra
+ * @since 2019-07-31
+ */
+public class ShortestWordDistanceIII {
+
+ /**
+ * Time Complexity:
+ * Space Complexity:
+ * TODO
+ *
+ * @param words
+ * @param word1
+ * @param word2
+ * @return
+ */
+ public static int findShortestDistance(String[] words, String word1, String word2) {
+ int indexWord1 = -1;
+ int indexWord2 = -1;
+ int minDistance = Integer.MAX_VALUE;
+
+ for (int i = 0; i < words.length; i++) {
+ if (words[i].equals(word1)) {
+ // if both words are same and the first index is already set then do nothing
+ if (word1.equals(word2) && indexWord1 != -1) {
+
+ } else {
+ indexWord1 = i;
+ }
+ }
+ if (words[i].equals(word2)) {
+ // if both words are same and i is same as first index then it implies its the
+ // first occurrence, skip and continue look for the second occurrence
+ if (word1.equals(word2) && i == indexWord1) {
+ continue;
+ }
+ indexWord2 = i;
+ }
+ if (indexWord1 != -1 && indexWord2 != -1) {
+ minDistance = Math.min(minDistance, Math.abs(indexWord1 - indexWord2));
+ }
+ }
+
+ return minDistance;
+ }
+
+ public static void main(String[] args) {
+ assertEquals(3, findShortestDistance(new String[]{"practice", "makes", "perfect", "coding", "makes"},
+ "makes", "makes"));
+ assertEquals(3, findShortestDistance(new String[]{"practice", "makes", "perfect", "coding", "makes"},
+ "coding", "practice"));
+ assertEquals(3, findShortestDistance(new String[]{"practice", "makes", "perfect", "coding", "makes"},
+ "practice", "coding"));
+ assertEquals(1, findShortestDistance(new String[]{"practice", "makes", "perfect", "coding", "makes"},
+ "makes", "coding"));
+ assertEquals(1, findShortestDistance(new String[]{"practice", "makes", "perfect", "coding", "makes"},
+ "makes", "perfect"));
+ }
+}
diff --git a/src/main/java/com/leetcode/arrays/SparseMatrixMultiplication.java b/src/main/java/com/leetcode/arrays/SparseMatrixMultiplication.java
new file mode 100644
index 00000000..78c884e4
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/SparseMatrixMultiplication.java
@@ -0,0 +1,87 @@
+package com.leetcode.arrays;
+
+import java.util.Arrays;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Link: https://leetcode.com/problems/sparse-matrix-multiplication/
+ * Description:
+ * Given two sparse matrices A and B, return the result of AB.
+ *
+ * You may assume that A's column number is equal to B's row number.
+ *
+ * Example:
+ *
+ * Input:
+ *
+ * A = [
+ * [ 1, 0, 0],
+ * [-1, 0, 3]
+ * ]
+ *
+ * B = [
+ * [ 7, 0, 0 ],
+ * [ 0, 0, 0 ],
+ * [ 0, 0, 1 ]
+ * ]
+ *
+ * Output:
+ *
+ * | 1 0 0 | | 7 0 0 | | 7 0 0 |
+ * AB = | -1 0 3 | x | 0 0 0 | = | -7 0 3 |
+ * | 0 0 1 |
+ *
+ * @author rampatra
+ * @since 2019-08-09
+ */
+public class SparseMatrixMultiplication {
+
+ /**
+ * Time Complexity: O(Arow * Acol * Bcol)
+ * Space Complexity: O(Arow * Bcol)
+ *
+ * @param A
+ * @param B
+ * @return
+ */
+ public static int[][] multiply(int[][] A, int[][] B) {
+ int[][] AB = new int[A.length][B[0].length];
+
+ for (int Bcol = 0; Bcol < B[0].length; Bcol++) {
+ for (int Arow = 0; Arow < A.length; Arow++) {
+ int sum = 0;
+ for (int Acol = 0; Acol < A[0].length; Acol++) {
+ sum += A[Arow][Acol] * B[Acol][Bcol];
+ }
+ AB[Arow][Bcol] = sum;
+ }
+ }
+
+ return AB;
+ }
+
+ public static void main(String[] args) {
+ assertEquals(Arrays.deepToString(new int[][]{
+ {7, 0, 0},
+ {-7, 0, 3}
+ }), Arrays.deepToString(multiply(new int[][]{
+ {1, 0, 0},
+ {-1, 0, 3}
+ }, new int[][]{
+ {7, 0, 0},
+ {0, 0, 0},
+ {0, 0, 1}
+ })));
+
+ assertEquals(Arrays.deepToString(new int[][]{
+ {0}
+ }), Arrays.deepToString(multiply(new int[][]{
+ {0, 1}
+ }, new int[][]{
+ {1},
+ {0}
+ })));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/arrays/ValidTriangleNumber.java b/src/main/java/com/leetcode/arrays/ValidTriangleNumber.java
new file mode 100644
index 00000000..cdbfb0c5
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/ValidTriangleNumber.java
@@ -0,0 +1,117 @@
+package com.leetcode.arrays;
+
+import java.util.Arrays;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Problem Link: https://leetcode.com/problems/valid-triangle-number/
+ * Problem Description:
+ * Given an array consists of non-negative integers, your task is to count the number of triplets chosen from the array
+ * that can make triangles if we take them as side lengths of a triangle.
+ *
+ * Example 1:
+ * Input: [2,2,3,4]
+ * Output: 3
+ * Explanation:
+ * Valid combinations are:
+ * 2,3,4 (using the first 2)
+ * 2,3,4 (using the second 2)
+ * 2,2,3
+ *
+ * Note:
+ * - The length of the given array won't exceed 1000.
+ * - The integers in the given array are in the range of [0, 1000].
+ * - Triangle Property: Sum of any 2 sides must be greater than the 3rd side.
+ *
+ * @author rampatra
+ * @since 2019-08-07
+ */
+public class ValidTriangleNumber {
+
+ /**
+ * Time complexity : O(n^2 log n). In worst case, the inner loop will take n log n (binary search applied n times).
+ * Space complexity : O(log n). Sorting takes O(log n) space.
+ * Runtime: 13 ms.
+ *
+ * @param nums
+ * @return
+ */
+ public static int triangleNumberUsingBinarySearch(int[] nums) {
+ int noOfTriangles = 0;
+
+ Arrays.sort(nums);
+
+ for (int i = 0; i < nums.length - 2; i++) {
+ int k = i + 2;
+ for (int j = i + 1; j < nums.length - 1; j++) {
+ k = binarySearch(nums, k, nums.length - 1, nums[i] + nums[j]);
+ if (k - j - 1 > 0) {
+ noOfTriangles += k - j - 1;
+ }
+ }
+ }
+
+ return noOfTriangles;
+ }
+
+ private static int binarySearch(int[] nums, int low, int high, int num) {
+ while (low <= high) {
+ int mid = (low + high) / 2;
+ if (nums[mid] < num) {
+ low = mid + 1;
+ } else {
+ high = mid - 1;
+ }
+ }
+
+ return low;
+ }
+
+ /**
+ * The concept is simple. For each pair (i,j), find the value of k such that nums[i] + nums[j] > nums[k] (as per
+ * triangle property). Once we find k then we can form k- j - 1 triangles.
+ *
+ * Time Complexity: O(n^2) Loop of k and j will be executed O(n^2) times in total, because, we do
+ * not reinitialize the value of k for a new value of j chosen(for the same i). Thus, the complexity
+ * will be O(n^2 + n^2) = O(n^2).
+ * Space Complexity: O(log n). Sorting takes O(log n) space.
+ * Runtime: 5 ms.
+ *
+ * @param nums
+ * @return
+ */
+ public static int triangleNumber(int[] nums) {
+ int noOfTriangles = 0;
+ Arrays.sort(nums);
+
+ for (int i = 0; i < nums.length - 2; i++) {
+ int k = i + 2;
+ for (int j = i + 1; j < nums.length - 1; j++) {
+ while (k < nums.length && nums[i] + nums[j] > nums[k]) {
+ k++;
+ }
+ if (k - j - 1 > 0) {
+ noOfTriangles += k - j - 1;
+ }
+ }
+ }
+
+ return noOfTriangles;
+ }
+
+ public static void main(String[] args) {
+ assertEquals(0, triangleNumberUsingBinarySearch(new int[]{}));
+ assertEquals(0, triangleNumberUsingBinarySearch(new int[]{1}));
+ assertEquals(3, triangleNumberUsingBinarySearch(new int[]{2, 2, 3, 4}));
+ assertEquals(0, triangleNumberUsingBinarySearch(new int[]{0, 1, 0, 1}));
+ assertEquals(7, triangleNumberUsingBinarySearch(new int[]{1, 2, 3, 4, 5, 6}));
+
+ assertEquals(0, triangleNumber(new int[]{}));
+ assertEquals(0, triangleNumber(new int[]{1}));
+ assertEquals(3, triangleNumber(new int[]{2, 2, 3, 4}));
+ assertEquals(0, triangleNumber(new int[]{0, 1, 0, 1}));
+ assertEquals(7, triangleNumber(new int[]{1, 2, 3, 4, 5, 6}));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/arrays/binarysearch/PowXN.java b/src/main/java/com/leetcode/arrays/binarysearch/PowXN.java
new file mode 100644
index 00000000..3591c50e
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/binarysearch/PowXN.java
@@ -0,0 +1,85 @@
+package com.leetcode.arrays.binarysearch;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Link: https://leetcode.com/problems/powx-n/
+ * Description:
+ * Implement pow(x, n), which calculates x raised to the power n (x^n).
+ *
+ * Example 1:
+ * Input: 2.00000, 10
+ * Output: 1024.00000
+ *
+ * Example 2:
+ * Input: 2.10000, 3
+ * Output: 9.26100
+ *
+ * Example 3:
+ * Input: 2.00000, -2
+ * Output: 0.25000
+ * Explanation: 2^-2 = 1/22 = 1/4 = 0.25
+ *
+ * Note:
+ * -100.0 < x < 100.0
+ * n is a 32-bit signed integer, within the range [−231, 231 − 1]
+ *
+ * @author rampatra
+ * @since 2019-08-19
+ */
+public class PowXN {
+
+ /**
+ * In this approach we iterate n times and keep multiplying x with x.
+ * Runtime: Time limit exceeded.
+ *
+ * @param x
+ * @param n
+ * @return
+ */
+ public static double myPowNaive(double x, int n) {
+ if (n == 0) {
+ return 1;
+ }
+ double res = x;
+ int absN = Math.abs(n);
+ for (int i = 1; i < absN; i++) {
+ res *= x;
+ }
+ return n < 0 ? 1 / res : res;
+ }
+
+
+ /**
+ * In this approach, we iterate log n times. We omit half of n each time. When n is odd, we store whatever product
+ * we have calculated so far in the final result.
+ *
+ * Runtime: 1 ms.
+ *
+ * @param x
+ * @param n
+ * @return
+ */
+ public static double myPow(double x, int n) {
+ double res = 1;
+ long absN = Math.abs((long) n); // used a long so that `absN / 2` doesn't overflow
+
+ while (absN > 0) {
+ if (absN % 2 == 1) res *= x; // store whatever we have calculated so far in the final result
+ x *= x;
+ absN /= 2;
+ }
+ return n < 0 ? 1 / res : res;
+ }
+
+ public static void main(String[] args) {
+ assertEquals(1024.0, myPowNaive(2.0, 10));
+ assertEquals(0.25, myPowNaive(2.0, -2));
+ assertEquals(0.0, myPowNaive(0.00001, 2147483647));
+
+ assertEquals(1024.0, myPow(2.0, 10));
+ assertEquals(0.25, myPow(2.0, -2));
+ assertEquals(0.0, myPow(0.00001, 2147483647));
+ }
+}
diff --git a/src/main/java/com/leetcode/arrays/binarysearch/SearchInsertPosition.java b/src/main/java/com/leetcode/arrays/binarysearch/SearchInsertPosition.java
new file mode 100644
index 00000000..2f13214a
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/binarysearch/SearchInsertPosition.java
@@ -0,0 +1,64 @@
+package com.leetcode.arrays.binarysearch;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Easy
+ * Link: https://leetcode.com/problems/search-insert-position/
+ * Description:
+ * Given a sorted array and a target value, return the index if the target is found. If not, return the index where it
+ * would be if it were inserted in order.
+ *
+ * You may assume no duplicates in the array.
+ *
+ * Example 1:
+ * Input: [1,3,5,6], 5
+ * Output: 2
+ *
+ * Example 2:
+ * Input: [1,3,5,6], 2
+ * Output: 1
+ *
+ * Example 3:
+ * Input: [1,3,5,6], 7
+ * Output: 4
+ *
+ * Example 4:
+ * Input: [1,3,5,6], 0
+ * Output: 0
+ *
+ * Similar question: {@link SmallestLetterGreaterThanTarget}.
+ *
+ * @author rampatra
+ * @since 2019-08-19
+ */
+public class SearchInsertPosition {
+
+ /**
+ * Runtime: 0 ms.
+ *
+ * @param nums
+ * @param target
+ * @return
+ */
+ public static int searchInsert(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) {
+ return mid;
+ } else if (nums[mid] < target) {
+ low = mid + 1;
+ } else {
+ high = mid - 1;
+ }
+ }
+ return low;
+ }
+
+ public static void main(String[] args) {
+ assertEquals(2, searchInsert(new int[]{1, 2}, 3));
+ assertEquals(1, searchInsert(new int[]{1, 3, 5, 6}, 2));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/arrays/binarysearch/SmallestLetterGreaterThanTarget.java b/src/main/java/com/leetcode/arrays/binarysearch/SmallestLetterGreaterThanTarget.java
new file mode 100644
index 00000000..e44dc339
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/binarysearch/SmallestLetterGreaterThanTarget.java
@@ -0,0 +1,87 @@
+package com.leetcode.arrays.binarysearch;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Easy
+ * Link: https://leetcode.com/problems/find-smallest-letter-greater-than-target/
+ * Description:
+ * Given a list of sorted characters letters containing only lowercase letters, and given a target letter target, find
+ * the smallest element in the list that is larger than the given target.
+ *
+ * Letters also wrap around. For example, if the target is target = 'z' and letters = ['a', 'b'], the answer is 'a'.
+ *
+ * Examples:
+ *
+ * Input:
+ * letters = ["c", "f", "j"]
+ * target = "a"
+ * Output: "c"
+ *
+ * Input:
+ * letters = ["c", "f", "j"]
+ * target = "c"
+ * Output: "f"
+ *
+ * Input:
+ * letters = ["c", "f", "j"]
+ * target = "d"
+ * Output: "f"
+ *
+ * Input:
+ * letters = ["c", "f", "j"]
+ * target = "g"
+ * Output: "j"
+ *
+ * Input:
+ * letters = ["c", "f", "j"]
+ * target = "j"
+ * Output: "c"
+ *
+ * Input:
+ * letters = ["c", "f", "j"]
+ * target = "k"
+ * Output: "c"
+ *
+ * Note:
+ * - letters has a length in range [2, 10000].
+ * - letters consists of lowercase letters, and contains at least 2 unique letters.
+ * - target is a lowercase letter.
+ *
+ * @author rampatra
+ * @since 2019-08-19
+ */
+public class SmallestLetterGreaterThanTarget {
+
+ /**
+ * Runtime: 0 ms.
+ *
+ * @param letters
+ * @param target
+ * @return
+ */
+ public static char nextGreatestLetter(char[] letters, char target) {
+ int low = 0, hi = letters.length - 1;
+ while (low <= hi) {
+ int mid = low + (hi - low) / 2;
+ if (letters[mid] <= target) {
+ low = mid + 1;
+ } else {
+ hi = mid - 1;
+ }
+ }
+ return letters[low % letters.length];
+ }
+
+ public static void main(String[] args) {
+ assertEquals('a', nextGreatestLetter(new char[]{'a'}, 'z'));
+ assertEquals('b', nextGreatestLetter(new char[]{'a', 'b'}, 'a'));
+ assertEquals('b', nextGreatestLetter(new char[]{'a', 'b', 'c'}, 'a'));
+ assertEquals('a', nextGreatestLetter(new char[]{'a', 'b', 'c'}, 'z'));
+ assertEquals('c', nextGreatestLetter(new char[]{'c', 'f', 'j'}, 'a'));
+ assertEquals('f', nextGreatestLetter(new char[]{'c', 'f', 'j'}, 'c'));
+ assertEquals('f', nextGreatestLetter(new char[]{'c', 'f', 'j'}, 'd'));
+ assertEquals('b', nextGreatestLetter(new char[]{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'l',
+ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}, 'a'));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/arrays/binarysearch/SqrtX.java b/src/main/java/com/leetcode/arrays/binarysearch/SqrtX.java
new file mode 100644
index 00000000..0dde1308
--- /dev/null
+++ b/src/main/java/com/leetcode/arrays/binarysearch/SqrtX.java
@@ -0,0 +1,62 @@
+package com.leetcode.arrays.binarysearch;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Easy
+ * Link: https://leetcode.com/problems/sqrtx/
+ * Description:
+ * Implement int sqrt(int x).
+ *
+ * Compute and return the square root of x, where x is guaranteed to be a non-negative integer.
+ *
+ * Since the return type is an integer, the decimal digits are truncated and only the integer part
+ * of the result is returned.
+ *
+ * Example 1:
+ * Input: 4
+ * Output: 2
+ *
+ * Example 2:
+ * Input: 8
+ * Output: 2
+ * Explanation: The square root of 8 is 2.82842..., and since
+ * the decimal part is truncated, 2 is returned.
+ *
+ * @author rampatra
+ * @since 2019-08-19
+ */
+public class SqrtX {
+
+ /**
+ * Runtime: 1 ms.
+ *
+ * @param x
+ * @return
+ */
+ public static int mySqrt(int x) {
+ if (x == 0 || x == 1) {
+ return x;
+ }
+ long low = 1;
+ long high = x / 2;
+
+ while (low <= high) {
+ long mid = low + (high - low) / 2;
+ if (mid * mid == x) {
+ return (int) mid;
+ } else if (mid * mid < x) {
+ low = mid + 1;
+ } else {
+ high = mid - 1;
+ }
+ }
+ return (int) high;
+ }
+
+ public static void main(String[] args) {
+ assertEquals(2, mySqrt(8));
+ assertEquals(3, mySqrt(9));
+ assertEquals(46339, mySqrt(2147395599));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/design/AllOne.java b/src/main/java/com/leetcode/design/AllOne.java
new file mode 100644
index 00000000..51f771d7
--- /dev/null
+++ b/src/main/java/com/leetcode/design/AllOne.java
@@ -0,0 +1,125 @@
+package com.leetcode.design;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Hard
+ * Link: https://leetcode.com/problems/all-oone-data-structure/
+ * Description:
+ * Implement a data structure supporting the following operations:
+ * Inc(Key) - Inserts a new key with value 1. Or increments an existing key by 1. Key is guaranteed to be a non-empty
+ * string.
+ * Dec(Key) - If Key's value is 1, remove it from the data structure. Otherwise decrements an existing key by 1. If
+ * the key does not exist, this function does nothing. Key is guaranteed to be a non-empty string.
+ * GetMaxKey() - Returns one of the keys with maximal value. If no element exists, return an empty string "".
+ * GetMinKey() - Returns one of the keys with minimal value. If no element exists, return an empty string "".
+ *
+ * Challenge: Perform all these in O(1) time complexity.
+ *
+ * @author rampatra
+ * @since 2019-08-11
+ */
+public class AllOne {
+
+
+
+ Map keyToValMap;
+ Map> valToKeyMap;
+
+ /**
+ * Initialize your data structure here.
+ */
+ public AllOne() {
+ keyToValMap = new HashMap<>();
+ valToKeyMap = new HashMap<>();
+ }
+
+ /**
+ * Inserts a new key with value 1. Or increments an existing key by 1.
+ */
+ public void inc(String key) {
+
+ }
+
+ /**
+ * Decrements an existing key by 1. If Key's value is 1, remove it from the data structure.
+ */
+ public void dec(String key) {
+
+ }
+
+ /**
+ * Returns one of the keys with maximal value.
+ */
+ public String getMaxKey() {
+ return null;
+ }
+
+ /**
+ * Returns one of the keys with Minimal value.
+ */
+ public String getMinKey() {
+ return null;
+ }
+
+ public static void main(String[] args) {
+ AllOne allOne = new AllOne();
+ allOne.inc("r");
+ allOne.inc("r");
+ allOne.dec("r");
+ allOne.inc("a");
+ allOne.inc("b");
+ allOne.inc("b");
+ assertEquals("b", allOne.getMaxKey());
+ assertEquals("a", allOne.getMinKey());
+
+ allOne = new AllOne();
+ allOne.dec("hello");
+ assertEquals("", allOne.getMaxKey());
+
+ allOne = new AllOne();
+ allOne.inc("a");
+ allOne.inc("b");
+ allOne.inc("b");
+ allOne.inc("b");
+ allOne.inc("b");
+ allOne.dec("b");
+ allOne.dec("b");
+ assertEquals("b", allOne.getMaxKey());
+ assertEquals("a", allOne.getMinKey());
+
+ allOne = new AllOne();
+ allOne.inc("hello");
+ allOne.inc("hello");
+ assertEquals("hello", allOne.getMaxKey());
+ assertEquals("hello", allOne.getMinKey());
+ allOne.inc("leet");
+ assertEquals("hello", allOne.getMaxKey());
+ assertEquals("leet", allOne.getMinKey());
+
+ allOne = new AllOne();
+ allOne.inc("a");
+ allOne.inc("b");
+ allOne.inc("b");
+ allOne.inc("c");
+ allOne.inc("c");
+ allOne.inc("c");
+ allOne.dec("b");
+ allOne.dec("b");
+ assertEquals("a", allOne.getMinKey());
+ allOne.dec("a");
+ assertEquals("c", allOne.getMaxKey());
+ //assertEquals("c", allOne.getMinKey());
+
+ allOne = new AllOne();
+ allOne.inc("hello");
+ allOne.dec("hello");
+ assertEquals("", allOne.getMaxKey());
+ assertEquals("", allOne.getMinKey());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/design/DesignHitCounter.java b/src/main/java/com/leetcode/design/DesignHitCounter.java
new file mode 100644
index 00000000..62133196
--- /dev/null
+++ b/src/main/java/com/leetcode/design/DesignHitCounter.java
@@ -0,0 +1,117 @@
+package com.leetcode.design;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Problem Link: https://leetcode.com/problems/design-hit-counter/
+ * Problem Description:
+ * Design a hit counter which counts the number of hits received in the past 5 minutes.
+ *
+ * Each function accepts a timestamp parameter (in seconds granularity) and you may assume that calls are being made
+ * to the system in chronological order (ie, the timestamp is monotonically increasing). You may assume that the
+ * earliest timestamp starts at 1.
+ *
+ * It is possible that several hits arrive roughly at the same time.
+ *
+ * Example:
+ *
+ * HitCounter counter = new HitCounter();
+ *
+ * // hit at timestamp 1.
+ * counter.hit(1);
+ *
+ * // hit at timestamp 2.
+ * counter.hit(2);
+ *
+ * // hit at timestamp 3.
+ * counter.hit(3);
+ *
+ * // get hits at timestamp 4, should return 3.
+ * counter.getHits(4);
+ *
+ * // hit at timestamp 300.
+ * counter.hit(300);
+ *
+ * // get hits at timestamp 300, should return 4.
+ * counter.getHits(300);
+ *
+ * // get hits at timestamp 301, should return 3.
+ * counter.getHits(301);
+ *
+ * Follow up:
+ * What if the number of hits per second could be very large? Does your design scale?
+ *
+ * Runtime: 42 ms (better than ~98%).
+ *
+ * @author rampatra
+ * @since 2019-08-04
+ */
+public class DesignHitCounter {
+
+ private int[] timestamps;
+ private int[] hits;
+
+ /**
+ * Initialize your data structure here.
+ */
+ public DesignHitCounter() {
+ this.timestamps = new int[300];
+ this.hits = new int[300];
+ }
+
+ /**
+ * Record a hit.
+ *
+ * @param timestamp - The current timestamp (in seconds granularity).
+ */
+ public void hit(int timestamp) {
+ int bucket = timestamp % 300;
+ if (timestamps[bucket] == timestamp) {
+ hits[bucket]++;
+ } else {
+ timestamps[bucket] = timestamp;
+ hits[bucket] = 1;
+ }
+ }
+
+ /**
+ * Return the number of hits in the past 5 minutes.
+ *
+ * @param timestamp - The current timestamp (in seconds granularity).
+ */
+ public int getHits(int timestamp) {
+ int totalHits = 0;
+ for (int i = 0; i < 300; i++) {
+ if (timestamp - 300 < timestamps[i]) {
+ totalHits += hits[i];
+ }
+ }
+ return totalHits;
+ }
+
+ public static void main(String[] args) {
+ DesignHitCounter counter = new DesignHitCounter();
+
+ // hit at timestamp 1.
+ counter.hit(1);
+
+ // hit at timestamp 2.
+ counter.hit(2);
+
+ // hit at timestamp 3.
+ counter.hit(3);
+
+ // get hits at timestamp 4, should return 3.
+ assertEquals(3, counter.getHits(4));
+
+ // hit at timestamp 300.
+ counter.hit(300);
+
+ // get hits at timestamp 300, should return 4.
+ assertEquals(4, counter.getHits(300));
+
+ // get hits at timestamp 301, should return 3.
+ assertEquals(3, counter.getHits(301));
+ }
+}
diff --git a/src/main/java/com/leetcode/design/InsertDeleteGetRandom.java b/src/main/java/com/leetcode/design/InsertDeleteGetRandom.java
new file mode 100644
index 00000000..a6c2f376
--- /dev/null
+++ b/src/main/java/com/leetcode/design/InsertDeleteGetRandom.java
@@ -0,0 +1,106 @@
+package com.leetcode.design;
+
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Level: Medium
+ * Link: https://leetcode.com/problems/insert-delete-getrandom-o1/
+ * Description:
+ * Design a data structure that supports all following operations in average O(1) time.
+ *
+ * insert(val): Inserts an item val to the set if not already present.
+ * remove(val): Removes an item val from the set if present.
+ * getRandom: Returns a random element from current set of elements. Each element must have the same probability of
+ * being returned.
+ *
+ * Example:
+ *
+ * // Init an empty set.
+ * RandomizedSet randomSet = new RandomizedSet();
+ *
+ * // Inserts 1 to the set. Returns true as 1 was inserted successfully.
+ * randomSet.insert(1);
+ *
+ * // Returns false as 2 does not exist in the set.
+ * randomSet.remove(2);
+ *
+ * // Inserts 2 to the set, returns true. Set now contains [1,2].
+ * randomSet.insert(2);
+ *
+ * // getRandom should return either 1 or 2 randomly.
+ * randomSet.getRandom();
+ *
+ * // Removes 1 from the set, returns true. Set now contains [2].
+ * randomSet.remove(1);
+ *
+ * // 2 was already in the set, so return false.
+ * randomSet.insert(2);
+ *
+ * // Since 2 is the only number in the set, getRandom always return 2.
+ * randomSet.getRandom();
+ *
+ * Runtime: 54 ms.
+ *
+ * @author rampatra
+ * @since 2019-08-20
+ */
+public class LRUCache {
+
+ private LinkedHashMap cache;
+
+ public LRUCache(int capacity) {
+ this.cache = new LinkedHashMap(capacity, 0.75f, true) {
+ @Override
+ protected boolean removeEldestEntry(Map.Entry eldest) {
+ return size() > capacity;
+ }
+ };
+ }
+
+ public int get(int key) {
+ Integer val = cache.get(key);
+ return val == null ? -1 : val;
+ }
+
+ public void put(int key, int value) {
+ cache.put(key, value);
+ }
+
+ public static void main(String[] args) {
+ LRUCache cache = new LRUCache(2);
+ cache.put(1,1);
+ cache.put(2,2);
+ cache.put(1,1);
+ cache.put(3,3);
+ assertEquals(1, cache.get(1));
+ assertEquals(-1, cache.get(2));
+ assertEquals(3, cache.get(3));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/dynamicprogramming/MaximumProductSubArray.java b/src/main/java/com/leetcode/dynamicprogramming/MaximumProductSubArray.java
new file mode 100644
index 00000000..781cad13
--- /dev/null
+++ b/src/main/java/com/leetcode/dynamicprogramming/MaximumProductSubArray.java
@@ -0,0 +1,62 @@
+package com.leetcode.dynamicprogramming;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Link: https://leetcode.com/problems/maximum-product-subarray/
+ * Description:
+ * Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which
+ * has the largest product.
+ *
+ * Example 1:
+ * Input: [2,3,-2,4]
+ * Output: 6
+ * Explanation: [2,3] has the largest product 6.
+ *
+ * Example 2:
+ * Input: [-2,0,-1]
+ * Output: 0
+ * Explanation: The result cannot be 2, because [-2,-1] is not a subarray.
+ *
+ * @author rampatra
+ * @since 2019-08-18
+ */
+public class MaximumProductSubArray {
+
+ /**
+ * The approach is similar to {@link MaximumSubArray} where we update maxUntilIndex only if multiplying the current
+ * number to the product of of all numbers until index produces a larger product and if not make maxUntilIndex the
+ * current number. The only twist here is that we keep two such variables, one for max and one for min, and that's
+ * because the product of two negatives gives us a positive number.
+ *
+ * Runtime: 1 ms.
+ *
+ * @param nums
+ * @return
+ */
+ public static int maxProduct(int[] nums) {
+ int maxProd = nums[0];
+ int maxUntilIndex = nums[0];
+ int minUntilIndex = nums[0];
+
+ for (int i = 1; i < nums.length; i++) {
+ if (nums[i] >= 0) {
+ maxUntilIndex = Math.max(nums[i], maxUntilIndex * nums[i]);
+ minUntilIndex = Math.min(nums[i], minUntilIndex * nums[i]);
+ } else {
+ int prevMaxUntilIndex = maxUntilIndex;
+ maxUntilIndex = Math.max(nums[i], minUntilIndex * nums[i]); // when current number is -ve then multiply with minUntilIndex to get the max as product of two negatives is a positive
+ minUntilIndex = Math.min(nums[i], prevMaxUntilIndex * nums[i]);
+ }
+
+ maxProd = Math.max(maxProd, maxUntilIndex);
+ }
+
+ return maxProd;
+ }
+
+ public static void main(String[] args) {
+ assertEquals(24, maxProduct(new int[]{-2, 3, -4}));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/dynamicprogramming/MaximumSubArray.java b/src/main/java/com/leetcode/dynamicprogramming/MaximumSubArray.java
new file mode 100644
index 00000000..90a28c93
--- /dev/null
+++ b/src/main/java/com/leetcode/dynamicprogramming/MaximumSubArray.java
@@ -0,0 +1,104 @@
+package com.leetcode.dynamicprogramming;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/maximum-subarray
+ *
+ * @author rampatra
+ * @since 2019-04-26
+ */
+public class MaximumSubArray {
+
+ /**
+ * Time complexity: O(n)
+ * Runtime: 0 ms.
+ *
+ * @param nums
+ * @return
+ */
+ public static int maxSubArray(int[] nums) {
+ if (nums.length == 0) {
+ return 0;
+ }
+
+ int consecutiveSum = nums[0];
+ int maxSum = nums[0];
+
+ for (int i = 1; i < nums.length; i++) {
+ consecutiveSum += nums[i];
+
+ /* if the current number is larger than the summation of all the
+ previous numbers then start from current number */
+ if (nums[i] > consecutiveSum) {
+ consecutiveSum = nums[i];
+ }
+
+ if (consecutiveSum > maxSum) {
+ maxSum = consecutiveSum;
+ }
+ }
+
+ return maxSum;
+ }
+
+
+ /**
+ * Divide and Conquer approach.
+ * Time complexity: O(n log n). See Master's Theorem to understand how.
+ * Runtime: 1 ms.
+ *
+ * @param nums
+ * @return
+ */
+ public static int maxSubArrayDivideAndConquer(int[] nums) {
+ return maxSubArrayDivideAndConquer(nums, 0, nums.length - 1);
+ }
+
+ public static int maxSubArrayDivideAndConquer(int[] nums, int start, int end) {
+ if (start == end) {
+ return nums[start];
+ }
+
+ int mid = start + (end - start) / 2;
+ int leftSASum = maxSubArrayDivideAndConquer(nums, start, mid);
+ int rightSASum = maxSubArrayDivideAndConquer(nums, mid + 1, end);
+
+ int leftSum = Integer.MIN_VALUE;
+ int rightSum = Integer.MIN_VALUE;
+
+ // compute consecutive sum from mid towards start
+ int sum = 0;
+ for (int i = mid; i >= start; i--) {
+ sum += nums[i];
+ if (sum > leftSum) {
+ leftSum = sum;
+ }
+ }
+
+ // compute consecutive sum from mid towards end
+ sum = 0;
+ for (int i = mid + 1; i <= end; i++) {
+ sum += nums[i];
+ if (sum > rightSum) {
+ rightSum = sum;
+ }
+ }
+
+ // return the max of left sub-array, right sub-array, and the consecutive sum between start and end via mid
+ return Math.max(Math.max(leftSASum, rightSASum), leftSum + rightSum);
+ }
+
+ public static void main(String[] args) {
+ System.out.println(maxSubArray(new int[]{3}));
+ System.out.println(maxSubArray(new int[]{-3}));
+ System.out.println(maxSubArray(new int[]{-2, 1, -3, 4, -1, 2, 1, -5, 4}));
+ System.out.println(maxSubArray(new int[]{4, -5, 1, 2, -1, 4, -3, 1, -2}));
+
+ System.out.println("----");
+
+ System.out.println(maxSubArrayDivideAndConquer(new int[]{3}));
+ System.out.println(maxSubArrayDivideAndConquer(new int[]{-3}));
+ System.out.println(maxSubArrayDivideAndConquer(new int[]{-2, 1, -3, 4, -1, 2, 1, -5, 4}));
+ System.out.println(maxSubArrayDivideAndConquer(new int[]{4, -5, 1, 2, -1, 4, -3, 1, -2}));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/dynamicprogramming/PaintHouse.java b/src/main/java/com/leetcode/dynamicprogramming/PaintHouse.java
new file mode 100644
index 00000000..5692b0d8
--- /dev/null
+++ b/src/main/java/com/leetcode/dynamicprogramming/PaintHouse.java
@@ -0,0 +1,52 @@
+package com.leetcode.dynamicprogramming;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/paint-house/
+ * Problem Description:
+ * There are a row of n houses, each house can be painted with one of the three colors: red, blue or green. The cost
+ * of painting each house with a certain color is different. You have to paint all the houses such that no two adjacent
+ * houses have the same color. The cost of painting each house with a certain color is represented by a n x 3 cost matrix.
+ *
+ * For example, costs[0][0] is the cost of painting house 0 with color red; costs[1][2] is the cost of painting
+ * house 1 with color green, and so on... Find the minimum cost to paint all houses.
+ *
+ * Companies: LinkedIn.
+ * Related: {@link PaintHouseII}.
+ *
+ * @author rampatra
+ * @since 2019-07-23
+ */
+public class PaintHouse {
+
+ /**
+ * Runtime: 1 ms.
+ *
+ * @param costs of coloring the houses with red, blue, and green respectively. 1st row represents house 1, 2nd row
+ * house 2 and so on
+ * @return the minimum cost to paint all houses such that no two adjacent houses are of same color
+ */
+ public static int minCost(int[][] costs) {
+ if (costs == null || costs.length == 0) return 0;
+
+ for (int i = 1; i < costs.length; i++) {
+ costs[i][0] += Math.min(costs[i - 1][1], costs[i - 1][2]);
+ costs[i][1] += Math.min(costs[i - 1][0], costs[i - 1][2]);
+ costs[i][2] += Math.min(costs[i - 1][0], costs[i - 1][1]);
+ }
+
+ int lastRow = costs.length - 1;
+ return Math.min(Math.min(costs[lastRow][0], costs[lastRow][1]), costs[lastRow][2]);
+ }
+
+ public static void main(String[] args) {
+ System.out.println(minCost(new int[][]{
+ }));
+
+ System.out.println(minCost(new int[][]{
+ {2, 3, 4},
+ {5, 7, 6},
+ {8, 7, 2}
+ }));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/dynamicprogramming/PaintHouseII.java b/src/main/java/com/leetcode/dynamicprogramming/PaintHouseII.java
new file mode 100644
index 00000000..431ce612
--- /dev/null
+++ b/src/main/java/com/leetcode/dynamicprogramming/PaintHouseII.java
@@ -0,0 +1,120 @@
+package com.leetcode.dynamicprogramming;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Hard
+ * Problem Link: https://leetcode.com/problems/paint-house-ii/
+ * Problem Description:
+ * There are a row of n houses, each house can be painted with one of the m colors.
+ * The cost of painting each house with a certain color is different.
+ * You have to paint all the houses such that no two adjacent houses have the same color.
+ *
+ * The cost of painting each house with a certain color is represented by a n x m cost matrix.
+ *
+ * For example, costs[0][0] is the cost of painting house 0 with color 0;
+ * costs[1][2] is the cost of painting house 1 with color 2, and so on...
+ * Find the minimum cost to paint all houses.
+ *
+ * Note: All costs are positive integers.
+ *
+ * Follow up: Could you solve it in O(n * m) runtime? // TODO
+ *
+ * Companies: LinkedIn.
+ * Related: {@link PaintHouse}.
+ *
+ * @author rampatra
+ * @since 2019-07-24
+ */
+public class PaintHouseII {
+
+ /**
+ * The approach is similar to {@link PaintHouse} but slightly complex as the number of colors are arbitrary
+ * instead of the 3 fixed colors. So, we use two additional for loops to cycle through all the colors.
+ * Time Complexity: O(n * m * m)
+ * Space Complexity: O(1)
+ *
+ * @param costs the costs of coloring the house, each row represents the cost of coloring a particular
+ * house with different colors
+ * @return the minimum cost to paint all houses such that no two adjacent houses are of same color
+ */
+ public static int minCost(int[][] costs) {
+ if (costs == null || costs.length == 0) return 0;
+
+ for (int i = 1; i < costs.length; i++) {
+ for (int j = 0; j < costs[0].length; j++) {
+ int min = Integer.MAX_VALUE;
+ // loop through all colors for the previous house except the color of the current house
+ for (int k = 0; k < costs[0].length; k++) {
+ if (k != j) {
+ min = Math.min(costs[i - 1][k], min);
+ }
+ }
+ costs[i][j] += min;
+ }
+ }
+
+ int minCost = Integer.MAX_VALUE;
+ for (int i = 0; i < costs[0].length; i++) {
+ minCost = Math.min(costs[costs.length - 1][i], minCost);
+ }
+
+ return minCost;
+ }
+
+ public static void main(String[] args) {
+ assertEquals(0, minCost(new int[][]{}));
+
+ assertEquals(10, minCost(new int[][]{
+ {2, 3, 4},
+ {5, 7, 6},
+ {8, 7, 2}
+ }));
+
+ assertEquals(10, minCost(new int[][]{{10, 30, 20}}));
+
+ assertEquals(3, minCost(new int[][]{{1, 1, 1},
+ {1, 1, 1},
+ {1, 1, 1}}));
+
+ assertEquals(5, minCost(new int[][]{{1, 2, 3},
+ {3, 2, 1},
+ {2, 2, 2},
+ {3, 1, 2}}));
+
+ assertEquals(10, minCost(new int[][]{{17, 2, 17},
+ {16, 16, 5},
+ {14, 3, 19}}));
+
+ assertEquals(5, minCost(new int[][]{{1, 5, 3},
+ {2, 9, 4}}));
+
+ assertEquals(8, minCost(new int[][]{{8}}));
+
+ assertEquals(143, minCost(new int[][]{{12, 1, 19},
+ {15, 1, 10},
+ {3, 11, 10},
+ {9, 3, 10},
+ {4, 8, 7},
+ {4, 18, 2},
+ {16, 6, 6},
+ {3, 3, 6},
+ {10, 18, 16},
+ {5, 4, 8},
+ {5, 3, 16},
+ {11, 8, 19},
+ {18, 15, 18},
+ {16, 4, 15},
+ {10, 7, 13},
+ {11, 10, 14},
+ {3, 9, 8},
+ {5, 2, 2},
+ {3, 2, 5},
+ {2, 19, 14},
+ {17, 3, 6},
+ {6, 4, 17},
+ {5, 15, 19},
+ {2, 14, 14},
+ {19, 4, 16}}));
+ }
+}
diff --git a/src/main/java/com/leetcode/graphs/GraphValidTree.java b/src/main/java/com/leetcode/graphs/GraphValidTree.java
new file mode 100644
index 00000000..15950143
--- /dev/null
+++ b/src/main/java/com/leetcode/graphs/GraphValidTree.java
@@ -0,0 +1,131 @@
+package com.leetcode.graphs;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Level: Medium
+ * Problem Link: https://leetcode.com/problems/graph-valid-tree/
+ * Problem Description:
+ * 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.
+ *
+ * Example 1:
+ * Input: n = 5, and edges = [[0,1], [0,2], [0,3], [1,4]]
+ * Output: true
+ *
+ * Example 2:
+ * Input: n = 5, and edges = [[0,1], [1,2], [2,3], [1,3], [1,4]]
+ * Output: false
+ *
+ * Note: you can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0,1] is the
+ * same as [1,0] and thus will not appear together in edges.
+ *
+ * @author rampatra
+ * @since 2019-08-05
+ */
+public class GraphValidTree {
+
+ /**
+ *
+ * @param n
+ * @param edges
+ * @return
+ */
+ public static boolean isValidTree(int n, int[][] edges) {
+ List> adjacencyList = new ArrayList<>(n);
+
+ for (int i = 0; i < n; i++) {
+ adjacencyList.add(new ArrayList<>());
+ }
+
+ for (int i = 0; i < edges.length; i++) {
+ adjacencyList.get(edges[i][0]).add(edges[i][1]);
+ }
+
+ boolean[] visited = new boolean[n];
+
+ if (hasCycle(adjacencyList, 0, -1, visited)) {
+ return false;
+ }
+
+ for (int i = 0; i < n; i++) {
+ if (!visited[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static boolean hasCycle(List> adjacencyList, int node1, int exclude, boolean[] visited) {
+ visited[node1] = true;
+
+ for (int i = 0; i < adjacencyList.get(node1).size(); i++) {
+ int node2 = adjacencyList.get(node1).get(i);
+
+ if ((visited[node2] && exclude != node2) || (!visited[node2] && hasCycle(adjacencyList, node2, node1, visited))) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Union-find algorithm: We keep all connected nodes in one set in the union operation and in find operation we
+ * check whether two nodes belong to the same set. If yes then there's a cycle and if not then no cycle.
+ *
+ * Good articles on union-find:
+ * - https://www.hackerearth.com/practice/notes/disjoint-set-union-union-find/
+ * - https://www.youtube.com/watch?v=wU6udHRIkcc
+ *
+ * @param n
+ * @param edges
+ * @return
+ */
+ public static boolean isValidTreeUsingUnionFind(int n, int[][] edges) {
+ int[] roots = new int[n];
+
+ for (int i = 0; i < n; i++) {
+ roots[i] = i;
+ }
+
+ for (int i = 0; i < edges.length; i++) {
+ // find operation
+ if (roots[edges[i][0]] == roots[edges[i][1]]) {
+ return false;
+ }
+ // union operation
+ roots[edges[i][1]] = findRoot(roots, roots[edges[i][0]]); // note: we can optimize this even further by
+ // considering size of each side and then join the side with smaller size to the one with a larger size (weighted union).
+ // We can use another array called size to keep count of the size or we can use the same root array with
+ // negative values, i.e, negative resembles that the node is pointing to itself and the number will represent
+ // the size. For example, roots = [-2, -1, -1, 0] means that node 3 is pointing to node 0 and node 0 is pointing
+ // to itself and is has 2 nodes under it including itself.
+ }
+
+ return edges.length == n - 1;
+ }
+
+ private static int findRoot(int[] roots, int node) {
+ while (roots[node] != node) {
+ node = roots[node];
+ }
+ return node;
+ }
+
+ public static void main(String[] args) {
+ assertTrue(isValidTree(5, new int[][]{{0, 1}, {0, 2}, {0, 3}, {1, 4}}));
+ assertFalse(isValidTree(5, new int[][]{{0, 1}, {1, 2}, {2, 3}, {1, 3}, {1, 4}}));
+ assertFalse(isValidTree(3, new int[][]{{0, 1}, {1, 2}, {2, 0}}));
+
+ assertTrue(isValidTreeUsingUnionFind(5, new int[][]{{0, 1}, {0, 2}, {0, 3}, {1, 4}}));
+ assertFalse(isValidTreeUsingUnionFind(5, new int[][]{{0, 1}, {1, 2}, {2, 3}, {1, 3}, {1, 4}}));
+ assertFalse(isValidTreeUsingUnionFind(3, new int[][]{{0, 1}, {1, 2}, {2, 0}}));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/graphs/WordLadder.java b/src/main/java/com/leetcode/graphs/WordLadder.java
new file mode 100644
index 00000000..61e706ce
--- /dev/null
+++ b/src/main/java/com/leetcode/graphs/WordLadder.java
@@ -0,0 +1,121 @@
+package com.leetcode.graphs;
+
+
+import javafx.util.Pair;
+
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Link: https://leetcode.com/problems/word-ladder/
+ * Description:
+ * Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation
+ * sequence from beginWord to endWord, such that:
+ *
+ * Only one letter can be changed at a time. Each transformed word must exist in the word list. Note that beginWord
+ * is not a transformed word.
+ *
+ * Note:
+ * - Return 0 if there is no such transformation sequence.
+ * - All words have the same length.
+ * - All words contain only lowercase alphabetic characters.
+ * - You may assume no duplicates in the word list.
+ * - You may assume beginWord and endWord are non-empty and are not the same.
+ *
+ * Example 1:
+ * Input:
+ * beginWord = "hit",
+ * endWord = "cog",
+ * wordList = ["hot","dot","dog","lot","log","cog"]
+ *
+ * Output: 5
+ *
+ * Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
+ * return its length 5.
+ *
+ * Example 2:
+ * Input:
+ * beginWord = "hit"
+ * endWord = "cog"
+ * wordList = ["hot","dot","dog","lot","log"]
+ *
+ * Output: 0
+ *
+ * Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
+ *
+ * @author rampatra
+ * @since 2019-08-15
+ */
+public class WordLadder {
+
+ /**
+ * Runtime: 79 ms.
+ *
+ * @param beginWord
+ * @param endWord
+ * @param wordList
+ * @return
+ */
+ public static int ladderLength(String beginWord, String endWord, List wordList) {
+ int L = beginWord.length();
+ Map> transformedToOriginalWordMap = new HashMap<>();
+ Queue> queue = new LinkedList<>();
+
+ wordList.forEach(word -> {
+ String transformedWord;
+ for (int i = 0; i < L; i++) {
+ transformedWord = word.substring(0, i) + "*" + word.substring(i + 1, L);
+ transformedToOriginalWordMap.putIfAbsent(transformedWord, new HashSet<>());
+ transformedToOriginalWordMap.get(transformedWord).add(word);
+ }
+ }
+ );
+
+ Set visited = new HashSet<>();
+ queue.add(new Pair<>(beginWord, 1));
+ visited.add(beginWord);
+
+ while (!queue.isEmpty()) {
+ Pair currPair = queue.poll();
+ String word = currPair.getKey();
+ Integer level = currPair.getValue();
+
+ if (word.equals(endWord)) {
+ return level;
+ }
+
+ String transformedWord;
+ for (int i = 0; i < L; i++) {
+ transformedWord = word.substring(0, i) + "*" + word.substring(i + 1, L);
+
+ for (String originalWord : transformedToOriginalWordMap.getOrDefault(transformedWord, Collections.emptySet())) {
+ if (!visited.contains(originalWord)) {
+ queue.add(new Pair<>(originalWord, level + 1));
+ visited.add(originalWord);
+ }
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * TODO: Optimized both end BFS solution
+ *
+ * @param beginWord
+ * @param endWord
+ * @param wordList
+ * @return
+ */
+ public static int ladderLengthOptimized(String beginWord, String endWord, List wordList) {
+ return -1;
+ }
+
+ public static void main(String[] args) {
+ assertEquals(5, ladderLength("hit", "cog", Arrays.asList("hot", "dot", "dog", "lot", "log", "cog")));
+ assertEquals(0, ladderLength("hit", "cog", Arrays.asList("hot", "dot", "dog", "lot", "log")));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/graphs/WordLadderII.java b/src/main/java/com/leetcode/graphs/WordLadderII.java
new file mode 100644
index 00000000..8265c259
--- /dev/null
+++ b/src/main/java/com/leetcode/graphs/WordLadderII.java
@@ -0,0 +1,152 @@
+package com.leetcode.graphs;
+
+import javafx.util.Pair;
+
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Hard
+ * Link: https://leetcode.com/problems/word-ladder-ii/
+ * Description:
+ * 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 transformed word must exist in the word list. Note that beginWord is not a transformed word.
+ *
+ * Note:
+ * - Return an empty list if there is no such transformation sequence.
+ * - All words have the same length.
+ * - All words contain only lowercase alphabetic characters.
+ * - You may assume no duplicates in the word list.
+ * - You may assume beginWord and endWord are non-empty and are not the same.
+ *
+ * Example 1:
+ * Input:
+ * beginWord = "hit",
+ * endWord = "cog",
+ * wordList = ["hot","dot","dog","lot","log","cog"]
+ *
+ * Output:
+ * [
+ * ["hit","hot","dot","dog","cog"],
+ * ["hit","hot","lot","log","cog"]
+ * ]
+ *
+ *
+ * Example 2:
+ * Input:
+ * beginWord = "hit"
+ * endWord = "cog"
+ * wordList = ["hot","dot","dog","lot","log"]
+ *
+ * Output: []
+ * Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
+ *
+ * @author rampatra
+ * @since 2019-08-15
+ */
+public class WordLadderII {
+
+ /**
+ * The approach is same as {@link WordLadder}. We calculate the {@code minDistance} from start to end word and also
+ * keep a map of words and its adjacent words (i.e, with only character difference). After we are done calculating
+ * the {@code mindistance}, we perform a dfs on the map upto depth {@code minDistance} and if the last word at this
+ * depth is equal to the end word then we add all words to the result.
+ *
+ * @param beginWord
+ * @param endWord
+ * @param wordList
+ * @return
+ */
+ public static List> findLadders(String beginWord, String endWord, List wordList) {
+ int L = beginWord.length();
+ List> ladders = new LinkedList<>();
+ Map> transformedToOriginalWordMap = new HashMap<>();
+ Queue> queue = new LinkedList<>();
+
+ wordList.forEach(word -> {
+ String transformedWord;
+ for (int i = 0; i < L; i++) {
+ transformedWord = word.substring(0, i) + "*" + word.substring(i + 1, L);
+ transformedToOriginalWordMap.putIfAbsent(transformedWord, new HashSet<>());
+ transformedToOriginalWordMap.get(transformedWord).add(word);
+ }
+ }
+ );
+
+ int minDistance = -1;
+ Set visited = new HashSet<>();
+ queue.add(new Pair<>(beginWord, 1));
+ visited.add(beginWord);
+
+ HashMap> connectedNodes = new HashMap<>();
+
+ while (!queue.isEmpty()) {
+ Pair currPair = queue.poll();
+ String word = currPair.getKey();
+ Integer level = currPair.getValue();
+
+ if (word.equals(endWord) && minDistance == -1) {
+ minDistance = level - 1;
+ }
+
+ String transformedWord;
+ for (int i = 0; i < L; i++) {
+ transformedWord = word.substring(0, i) + "*" + word.substring(i + 1, L);
+
+ for (String originalWord : transformedToOriginalWordMap.getOrDefault(transformedWord, Collections.emptySet())) {
+ if (!visited.contains(originalWord)) {
+ queue.add(new Pair<>(originalWord, level + 1));
+ visited.add(originalWord);
+ }
+
+ if (!word.equals(originalWord)) {
+ connectedNodes.putIfAbsent(word, new HashSet<>());
+ connectedNodes.get(word).add(originalWord);
+ }
+ }
+ }
+ }
+
+ dfs(ladders, new LinkedHashSet<>(), connectedNodes, beginWord, endWord, 0, minDistance);
+
+ return ladders;
+ }
+
+ /**
+ * Perform dfs on the map which contains words and its adjacent words.
+ *
+ * @param ladders
+ * @param ladder
+ * @param connectedNodes
+ * @param startNode
+ * @param endNode
+ * @param distance
+ * @param minDistance
+ */
+ private static void dfs(List> ladders, Set ladder, Map> connectedNodes,
+ String startNode, String endNode, int distance, int minDistance) {
+ if (distance == minDistance && startNode.equals(endNode)) {
+ ladder.add(endNode);
+ ladders.add(new ArrayList<>(ladder));
+ return;
+ } else if (distance > minDistance) {
+ return;
+ }
+
+ ladder.add(startNode);
+ for (String nextNode : connectedNodes.getOrDefault(startNode, new HashSet<>())) {
+ if (!ladder.contains(nextNode)) {
+ dfs(ladders, new LinkedHashSet<>(ladder), connectedNodes, nextNode, endNode, distance + 1, minDistance);
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ assertEquals("[[hit, hot, lot, log, cog], [hit, hot, dot, dog, cog]]", findLadders("hit", "cog", Arrays.asList("hot", "dot", "dog", "lot", "log", "cog")).toString());
+ // TODO Fix this test case System.out.println(findLadders("cet", "ism", Arrays.asList("kid", "tag", "pup", "ail", "tun", "woo", "erg", "luz", "brr", "gay", "sip", "kay", "per", "val", "mes", "ohs", "now", "boa", "cet", "pal", "bar", "die", "war", "hay", "eco", "pub", "lob", "rue", "fry", "lit", "rex", "jan", "cot", "bid", "ali", "pay", "col", "gum", "ger", "row", "won", "dan", "rum", "fad", "tut", "sag", "yip", "sui", "ark", "has", "zip", "fez", "own", "ump", "dis", "ads", "max", "jaw", "out", "btu", "ana", "gap", "cry", "led", "abe", "box", "ore", "pig", "fie", "toy", "fat", "cal", "lie", "noh", "sew", "ono", "tam", "flu", "mgm", "ply", "awe", "pry", "tit", "tie", "yet", "too", "tax", "jim", "san", "pan", "map", "ski", "ova", "wed", "non", "wac", "nut", "why", "bye", "lye", "oct", "old", "fin", "feb", "chi", "sap", "owl", "log", "tod", "dot", "bow", "fob", "for", "joe", "ivy", "fan", "age", "fax", "hip", "jib", "mel", "hus", "sob", "ifs", "tab", "ara", "dab", "jag", "jar", "arm", "lot", "tom", "sax", "tex", "yum", "pei", "wen", "wry", "ire", "irk", "far", "mew", "wit", "doe", "gas", "rte", "ian", "pot", "ask", "wag", "hag", "amy", "nag", "ron", "soy", "gin", "don", "tug", "fay", "vic", "boo", "nam", "ave", "buy", "sop", "but", "orb", "fen", "paw", "his", "sub", "bob", "yea", "oft", "inn", "rod", "yam", "pew", "web", "hod", "hun", "gyp", "wei", "wis", "rob", "gad", "pie", "mon", "dog", "bib", "rub", "ere", "dig", "era", "cat", "fox", "bee", "mod", "day", "apr", "vie", "nev", "jam", "pam", "new", "aye", "ani", "and", "ibm", "yap", "can", "pyx", "tar", "kin", "fog", "hum", "pip", "cup", "dye", "lyx", "jog", "nun", "par", "wan", "fey", "bus", "oak", "bad", "ats", "set", "qom", "vat", "eat", "pus", "rev", "axe", "ion", "six", "ila", "lao", "mom", "mas", "pro", "few", "opt", "poe", "art", "ash", "oar", "cap", "lop", "may", "shy", "rid", "bat", "sum", "rim", "fee", "bmw", "sky", "maj", "hue", "thy", "ava", "rap", "den", "fla", "auk", "cox", "ibo", "hey", "saw", "vim", "sec", "ltd", "you", "its", "tat", "dew", "eva", "tog", "ram", "let", "see", "zit", "maw", "nix", "ate", "gig", "rep", "owe", "ind", "hog", "eve", "sam", "zoo", "any", "dow", "cod", "bed", "vet", "ham", "sis", "hex", "via", "fir", "nod", "mao", "aug", "mum", "hoe", "bah", "hal", "keg", "hew", "zed", "tow", "gog", "ass", "dem", "who", "bet", "gos", "son", "ear", "spy", "kit", "boy", "due", "sen", "oaf", "mix", "hep", "fur", "ada", "bin", "nil", "mia", "ewe", "hit", "fix", "sad", "rib", "eye", "hop", "haw", "wax", "mid", "tad", "ken", "wad", "rye", "pap", "bog", "gut", "ito", "woe", "our", "ado", "sin", "mad", "ray", "hon", "roy", "dip", "hen", "iva", "lug", "asp", "hui", "yak", "bay", "poi", "yep", "bun", "try", "lad", "elm", "nat", "wyo", "gym", "dug", "toe", "dee", "wig", "sly", "rip", "geo", "cog", "pas", "zen", "odd", "nan", "lay", "pod", "fit", "hem", "joy", "bum", "rio", "yon", "dec", "leg", "put", "sue", "dim", "pet", "yaw", "nub", "bit", "bur", "sid", "sun", "oil", "red", "doc", "moe", "caw", "eel", "dix", "cub", "end", "gem", "off", "yew", "hug", "pop", "tub", "sgt", "lid", "pun", "ton", "sol", "din", "yup", "jab", "pea", "bug", "gag", "mil", "jig", "hub", "low", "did", "tin", "get", "gte", "sox", "lei", "mig", "fig", "lon", "use", "ban", "flo", "nov", "jut", "bag", "mir", "sty", "lap", "two", "ins", "con", "ant", "net", "tux", "ode", "stu", "mug", "cad", "nap", "gun", "fop", "tot", "sow", "sal", "sic", "ted", "wot", "del", "imp", "cob", "way", "ann", "tan", "mci", "job", "wet", "ism", "err", "him", "all", "pad", "hah", "hie", "aim", "ike", "jed", "ego", "mac", "baa", "min", "com", "ill", "was", "cab", "ago", "ina", "big", "ilk", "gal", "tap", "duh", "ola", "ran", "lab", "top", "gob", "hot", "ora", "tia", "kip", "han", "met", "hut", "she", "sac", "fed", "goo", "tee", "ell", "not", "act", "gil", "rut", "ala", "ape", "rig", "cid", "god", "duo", "lin", "aid", "gel", "awl", "lag", "elf", "liz", "ref", "aha", "fib", "oho", "tho", "her", "nor", "ace", "adz", "fun", "ned", "coo", "win", "tao", "coy", "van", "man", "pit", "guy", "foe", "hid", "mai", "sup", "jay", "hob", "mow", "jot", "are", "pol", "arc", "lax", "aft", "alb", "len", "air", "pug", "pox", "vow", "got", "meg", "zoe", "amp", "ale", "bud", "gee", "pin", "dun", "pat", "ten", "mob")));
+ }
+}
diff --git a/src/main/java/com/leetcode/hashtables/ContainsDuplicates.java b/src/main/java/com/leetcode/hashtables/ContainsDuplicates.java
new file mode 100644
index 00000000..7b12311b
--- /dev/null
+++ b/src/main/java/com/leetcode/hashtables/ContainsDuplicates.java
@@ -0,0 +1,49 @@
+package com.leetcode.hashtables;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/contains-duplicate/
+ *
+ * @author rampatra
+ * @since 2019-04-24
+ */
+public class ContainsDuplicates {
+
+ public static boolean containsDuplicates(int[] nums) {
+ Set numSet = new HashSet<>();
+ for (int num : nums) {
+ if (!numSet.add(num)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Runtime: 5 ms.
+ *
+ * @param nums
+ * @return
+ */
+ public static boolean containsDuplicatesWithoutSet(int[] nums) {
+ Arrays.sort(nums);
+ for (int i = 0; i < nums.length - 1; i++) {
+ if (nums[i] == nums[i + 1]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(containsDuplicates(new int[]{1, 2, 3, 1}));
+ System.out.println(containsDuplicates(new int[]{1, 2, 3, 4}));
+
+ System.out.println(containsDuplicatesWithoutSet(new int[]{1, 2, 3, 1}));
+ System.out.println(containsDuplicatesWithoutSet(new int[]{1, 2, 3, 4}));
+ }
+}
diff --git a/src/main/java/com/leetcode/hashtables/IsomorphicStrings.java b/src/main/java/com/leetcode/hashtables/IsomorphicStrings.java
new file mode 100644
index 00000000..f9a7f4eb
--- /dev/null
+++ b/src/main/java/com/leetcode/hashtables/IsomorphicStrings.java
@@ -0,0 +1,104 @@
+package com.leetcode.hashtables;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Level: Easy
+ * Link: https://leetcode.com/problems/isomorphic-strings/
+ * Description:
+ * Given two strings s and t, determine if they are isomorphic.
+ *
+ * Two strings are isomorphic if the characters in s can be replaced to get t.
+ *
+ * All occurrences of a character must be replaced with another character while preserving the order of characters. No
+ * two characters may map to the same character but a character may map to itself.
+ *
+ * Example 1:
+ * Input: s = "egg", t = "add"
+ * Output: true
+ *
+ * Example 2:
+ * Input: s = "foo", t = "bar"
+ * Output: false
+ *
+ * Example 3:
+ * Input: s = "paper", t = "title"
+ * Output: true
+ *
+ * Note:
+ * You may assume both s and t have the same length.
+ *
+ * @author rampatra
+ * @since 2019-08-11
+ */
+public class IsomorphicStrings {
+
+ /**
+ * Time Complexity:
+ * Space Complexity:
+ * Runtime: 8 ms.
+ *
+ * @param s
+ * @param t
+ * @return
+ */
+ public static boolean isIsomorphic(String s, String t) {
+
+ Map sToTCharMap = new HashMap<>();
+ Map tToSCharMap = new HashMap<>();
+
+ for (int i = 0; i < s.length(); i++) {
+ char chFromS = s.charAt(i);
+ char chFromT = t.charAt(i);
+ if (sToTCharMap.get(chFromS) == null && tToSCharMap.get(chFromT) == null) {
+ sToTCharMap.put(chFromS, chFromT);
+ tToSCharMap.put(chFromT, chFromS);
+ }
+ Character mappedChFromSToT = sToTCharMap.get(chFromS);
+ if (mappedChFromSToT == null || mappedChFromSToT != chFromT) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Time Complexity:
+ * Space Complexity:
+ * Runtime: 3 ms.
+ *
+ * @param s
+ * @param t
+ * @return
+ */
+ public static boolean isIsomorphicWithoutMaps(String s, String t) {
+ int[] charMap = new int[512];
+ for (int i = 0; i < s.length(); i++) {
+ char chFromS = s.charAt(i);
+ char chFromT = t.charAt(i);
+ if (charMap[chFromS] != charMap[chFromT + 256]) {
+ return false;
+ }
+ charMap[chFromS] = charMap[chFromT + 256] = i + 1;
+ }
+
+ return true;
+ }
+
+ public static void main(String[] args) {
+ assertTrue(isIsomorphic("egg", "add"));
+ assertFalse(isIsomorphic("foo", "bar"));
+ assertTrue(isIsomorphic("paper", "title"));
+ assertFalse(isIsomorphic("ab", "aa"));
+
+ assertTrue(isIsomorphicWithoutMaps("egg", "add"));
+ assertFalse(isIsomorphicWithoutMaps("foo", "bar"));
+ assertTrue(isIsomorphicWithoutMaps("paper", "title"));
+ assertFalse(isIsomorphicWithoutMaps("ab", "aa"));
+ }
+}
diff --git a/src/main/java/com/leetcode/hashtables/MyHashMap.java b/src/main/java/com/leetcode/hashtables/MyHashMap.java
new file mode 100644
index 00000000..cf13c344
--- /dev/null
+++ b/src/main/java/com/leetcode/hashtables/MyHashMap.java
@@ -0,0 +1,105 @@
+package com.leetcode.hashtables;
+
+/**
+ * Level: Learning cards
+ * Problem Link: https://leetcode.com/explore/learn/card/hash-table/182/practical-applications/1140/
+ * Runtime: https://leetcode.com/submissions/detail/224928756/
+ *
+ * @author rampatra
+ * @since 2019-04-25
+ */
+public class MyHashMap {
+
+ class Entry {
+ int key;
+ int value;
+ Entry next;
+
+ Entry(int key, int value) {
+ this.key = key;
+ this.value = value;
+ }
+ }
+
+ private final int SIZE = 10000;
+ private final Entry[] entries;
+
+ /**
+ * Initialize your data structure here.
+ */
+ public MyHashMap() {
+ entries = new Entry[SIZE];
+ }
+
+ /**
+ * value will always be non-negative.
+ */
+ public void put(int key, int value) {
+ int bucket = key % SIZE;
+ Entry entry = entries[bucket];
+
+ if (entry == null) {
+ entries[bucket] = new Entry(key, value);
+ } else {
+ while (entry.next != null && entry.key != key) {
+ entry = entry.next;
+ }
+
+ if (entry.key == key) {
+ entry.value = value;
+ } else {
+ entry.next = new Entry(key, value);
+ }
+ }
+ }
+
+ /**
+ * Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key
+ */
+ public int get(int key) {
+ int bucket = key % SIZE;
+ Entry entry = entries[bucket];
+ while (entry != null) {
+ if (entry.key == key) {
+ return entry.value;
+ }
+ entry = entry.next;
+ }
+ return -1;
+ }
+
+ /**
+ * Removes the mapping of the specified value key if this map contains a mapping for the key
+ */
+ public void remove(int key) {
+ int bucket = key % SIZE;
+ Entry entry = entries[bucket];
+
+ if (entry != null && entry.key == key) {
+ entries[bucket] = entry.next;
+ return;
+ }
+
+ Entry curr = new Entry(0, 0);
+ curr.next = entry;
+
+ while (curr.next != null && curr.next.key != key) {
+ curr = curr.next;
+ }
+
+ if (curr.next != null) {
+ curr.next = curr.next.next;
+ }
+ }
+
+ public static void main(String[] args) {
+ MyHashMap map = new MyHashMap();
+ map.put(1, 2);
+ System.out.println("1 -> " + map.get(1));
+ map.put(1, 4);
+ System.out.println("1 -> " + map.get(1));
+ map.remove(1);
+ System.out.println("1 -> " + map.get(1));
+ System.out.println("5 -> " + map.get(5));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/hashtables/MyHashSet.java b/src/main/java/com/leetcode/hashtables/MyHashSet.java
new file mode 100644
index 00000000..3c13d488
--- /dev/null
+++ b/src/main/java/com/leetcode/hashtables/MyHashSet.java
@@ -0,0 +1,93 @@
+package com.leetcode.hashtables;
+
+/**
+ * Level: Learning Cards
+ * Problem Link: https://leetcode.com/explore/learn/card/hash-table/182/practical-applications/1139/
+ * Runtime: https://leetcode.com/submissions/detail/224872991/
+ *
+ * @author rampatra
+ * @since 2019-04-24
+ */
+public class MyHashSet {
+
+ private final int SIZE = 10000;
+ private final Entry[] entries;
+
+ class Entry {
+ int key;
+ Entry next;
+
+ Entry(int key) {
+ this.key = key;
+ }
+ }
+
+ /**
+ * Initialize your data structure here.
+ */
+ public MyHashSet() {
+ entries = new Entry[SIZE];
+ }
+
+ public void add(int key) {
+ if (contains(key)) return;
+
+ Entry newEntry = new Entry(key);
+ int bucket = key % SIZE;
+
+ newEntry.next = entries[bucket];
+ entries[bucket] = newEntry;
+ }
+
+ public void remove(int key) {
+ int bucket = key % SIZE;
+ Entry entry = entries[bucket];
+
+ if (entry != null && entry.key == key) {
+ entries[bucket] = entry.next;
+ return;
+ }
+
+ Entry curr = new Entry(0);
+ curr.next = entry;
+
+ while (curr.next != null && curr.next.key != key) {
+ curr = curr.next;
+ }
+
+ if (curr.next != null) {
+ curr.next = curr.next.next;
+ }
+ }
+
+ /**
+ * Returns true if this set contains the specified element
+ */
+ public boolean contains(int key) {
+ int bucket = key % SIZE;
+ Entry entry = entries[bucket];
+
+ while (entry != null) {
+ if (entry.key == key) {
+ return true;
+ }
+ entry = entry.next;
+ }
+
+ return false;
+ }
+
+ public static void main(String[] args) {
+ MyHashSet set = new MyHashSet();
+ set.add(1);
+ set.add(2);
+ set.add(3);
+ System.out.println(set.contains(1));
+ System.out.println(set.contains(2));
+ set.remove(2);
+ System.out.println(set.contains(2));
+ System.out.println(set.contains(3));
+ set.remove(3);
+ System.out.println(set.contains(3));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/hashtables/RepeatedDnaSequence.java b/src/main/java/com/leetcode/hashtables/RepeatedDnaSequence.java
new file mode 100644
index 00000000..7674273d
--- /dev/null
+++ b/src/main/java/com/leetcode/hashtables/RepeatedDnaSequence.java
@@ -0,0 +1,89 @@
+package com.leetcode.hashtables;
+
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Problem Link: https://leetcode.com/problems/repeated-dna-sequences/submissions/
+ * Problem Description:
+ * All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACGAATTCCG". When
+ * studying DNA, it is sometimes useful to identify repeated sequences within the DNA.
+ *
+ * Write a function to find all the 10-letter-long sequences (substrings) that occur more than once in a DNA molecule.
+ *
+ * Example:
+ * Input: s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
+ * Output: ["AAAAACCCCC", "CCCCCAAAAA"]
+ *
+ * TODO: Figure another method which would have a better runtime.
+ *
+ * @author rampatra
+ * @since 2019-07-29
+ */
+public class RepeatedDnaSequence {
+
+ /**
+ * Rabin-Karp Algorithm: https://brilliant.org/wiki/rabin-karp-algorithm/
+ * Following Rabin-Karp's approach let's you avoid spurious hits (worst case scenario) but once the hash matches,
+ * you will have to compare and check the string you're searching. I tried to just rely on the hash and few test
+ * cases failed for me (https://leetcode.com/submissions/detail/247342702/).
+ *
+ * Time Complexity:
+ * Space Complexity:
+ * Runtime: 38 ms.
+ *
+ * @param s
+ * @return
+ */
+ public static List findRepeatedDnaSequences(String s) {
+ if (s.length() < 10) return new ArrayList<>();
+
+ Set repeatedSequences = new HashSet<>();
+ Map> hashToStringMap = new HashMap<>();
+ long hashOfSequence = computeHash(s);
+ hashToStringMap.put(hashOfSequence, new HashSet() {{
+ add(s.substring(0, 10));
+ }});
+
+ long pow = (long) Math.pow(4, 9);
+
+ for (int i = 10; i < s.length(); i++) {
+ hashOfSequence = (hashOfSequence - (pow * (s.charAt(i - 10) - 'A'))) * 4 + (s.charAt(i) - 'A');
+ String subString = s.substring(i - 10 + 1, i + 1);
+
+ if (hashToStringMap.get(hashOfSequence) != null && hashToStringMap.get(hashOfSequence).contains(subString)) {
+ repeatedSequences.add(subString);
+ continue;
+ }
+
+ hashToStringMap.putIfAbsent(hashOfSequence, new HashSet<>());
+ hashToStringMap.get(hashOfSequence).add(subString);
+ }
+
+ return new ArrayList<>(repeatedSequences);
+ }
+
+ private static long computeHash(String s) {
+ long hash = 0;
+ for (int i = 0; i < 10; i++) {
+ hash += (Math.pow(4, i) * (s.charAt(9 - i) - 'A'));
+ }
+ return hash;
+ }
+
+ public static void main(String[] args) {
+ assertEquals(new ArrayList<>(),
+ findRepeatedDnaSequences("AAAAACCC"));
+
+ assertEquals(Arrays.asList("AAAAACCCCC", "CCCCCAAAAA"),
+ findRepeatedDnaSequences("AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"));
+
+ assertEquals(Collections.singletonList("AAAAAAAAAA"),
+ findRepeatedDnaSequences("AAAAAAAAAAAA"));
+
+ assertEquals(Collections.singletonList("BBBBBBBBBB"),
+ findRepeatedDnaSequences("BBBBBBBBBBBB"));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/hashtables/ShortestWordDistanceII.java b/src/main/java/com/leetcode/hashtables/ShortestWordDistanceII.java
new file mode 100644
index 00000000..3932cebf
--- /dev/null
+++ b/src/main/java/com/leetcode/hashtables/ShortestWordDistanceII.java
@@ -0,0 +1,89 @@
+package com.leetcode.hashtables;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Problem Link: https://leetcode.com/problems/shortest-word-distance-ii/
+ * Problem Description:
+ * Design a class which receives a list of words in the constructor, and implements a method that takes two words
+ * word1 and word2 and return the shortest distance between these two words in the list. Your method will be called
+ * repeatedly many times with different parameters. For a simpler variant, see {@link com.leetcode.arrays.ShortestWordDistance}.
+ *
+ * Examples:
+ * Assume that words = ["practice", "makes", "perfect", "coding", "makes"].
+ *
+ * Input1: word1 = “coding”, word2 = “practice”
+ * Output1: 3
+ *
+ * Input2: word1 = "makes", word2 = "coding"
+ * Output2: 1
+ *
+ * Note: You may assume that word1 does not equal to word2, and word1 and word2 are both in the list.
+ *
+ * @author rampatra
+ * @since 2019-07-31
+ */
+public class ShortestWordDistanceII {
+
+ private String[] words;
+ private Map> wordsToIndexesMap;
+
+ ShortestWordDistanceII(String[] words) {
+ this.words = words;
+ this.wordsToIndexesMap = getWordsToIndexesMap();
+ }
+
+ /**
+ * Runtime: 65 ms.
+ *
+ * @param word1
+ * @param word2
+ * @return
+ */
+ public int findShortestDistance(String word1, String word2) {
+ return findShortestDistance(wordsToIndexesMap.get(word1), wordsToIndexesMap.get(word2));
+ }
+
+ private int findShortestDistance(List indexes1, List indexes2) {
+ int minDistance = Integer.MAX_VALUE;
+
+ for (int i = 0, j = 0; i < indexes1.size() && j < indexes2.size(); ) {
+ if (indexes1.get(i) <= indexes2.get(j)) {
+ minDistance = Math.min(minDistance, Math.abs(indexes1.get(i) - indexes2.get(j)));
+ i++;
+ } else if (indexes1.get(i) > indexes2.get(j)) {
+ minDistance = Math.min(minDistance, Math.abs(indexes1.get(i) - indexes2.get(j)));
+ j++;
+ }
+ }
+
+ return minDistance;
+ }
+
+ private Map> getWordsToIndexesMap() {
+ Map> wordsToIndexesMap = new HashMap<>();
+
+ for (int i = 0; i < words.length; i++) {
+ wordsToIndexesMap.putIfAbsent(words[i], new ArrayList<>());
+ wordsToIndexesMap.get(words[i]).add(i);
+ }
+ return wordsToIndexesMap;
+ }
+
+ public static void main(String[] args) {
+ ShortestWordDistanceII shortestWordDist = new ShortestWordDistanceII(new String[]{"practice", "makes", "perfect", "coding", "makes"});
+ assertEquals(1, shortestWordDist.findShortestDistance("coding", "makes"));
+ assertEquals(1, shortestWordDist.findShortestDistance("perfect", "makes"));
+ assertEquals(1, shortestWordDist.findShortestDistance("practice", "makes"));
+ assertEquals(1, shortestWordDist.findShortestDistance("makes", "practice"));
+ assertEquals(3, shortestWordDist.findShortestDistance("coding", "practice"));
+ assertEquals(0, shortestWordDist.findShortestDistance("coding", "coding"));
+ assertEquals(0, shortestWordDist.findShortestDistance("makes", "makes"));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/hashtables/TwoSumIII.java b/src/main/java/com/leetcode/hashtables/TwoSumIII.java
new file mode 100644
index 00000000..88916db0
--- /dev/null
+++ b/src/main/java/com/leetcode/hashtables/TwoSumIII.java
@@ -0,0 +1,78 @@
+package com.leetcode.hashtables;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/two-sum-iii-data-structure-design/
+ * Problem Description:
+ * Design and implement a TwoSum class. It should support the following operations: add and find.
+ *
+ * add - Add the number to an internal data structure.
+ * find - Find if there exists any pair of numbers which sum is equal to the value.
+ *
+ * Example 1:
+ * add(1); add(3); add(5);
+ * find(4) -> true
+ * find(7) -> false
+ *
+ * Example 2:
+ * add(3); add(1); add(2);
+ * find(3) -> true
+ * find(6) -> false
+ *
+ * @author rampatra
+ * @since 2019-08-03
+ */
+public class TwoSumIII {
+
+ Map numCount;
+
+ /**
+ * Initialize your data structure here.
+ */
+ public TwoSumIII() {
+ this.numCount = new HashMap<>();
+ }
+
+ /**
+ * Add the number to an internal data structure..
+ */
+ public void add(int number) {
+ if (numCount.containsKey(number)) {
+ numCount.put(number, 2);
+ } else {
+ numCount.put(number, 1);
+ }
+ }
+
+ /**
+ * Find if there exists any pair of numbers which sum is equal to the value.
+ */
+ public boolean find(int value) {
+ for (Map.Entry entry : numCount.entrySet()) {
+ int num1 = entry.getKey();
+ int num2 = value - num1;
+ if ((num2 == num1 && entry.getValue() == 2) || (num1 != num2 && numCount.containsKey(num2))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Runtime: 115 ms.
+ *
+ * @param args
+ */
+ public static void main(String[] args) {
+ TwoSumIII twoSumIII = new TwoSumIII();
+ twoSumIII.add(0);
+ twoSumIII.add(-1);
+ twoSumIII.add(1);
+ assertTrue(twoSumIII.find(0));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithKDistinctCharacters.java b/src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithKDistinctCharacters.java
new file mode 100644
index 00000000..4b209b6e
--- /dev/null
+++ b/src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithKDistinctCharacters.java
@@ -0,0 +1,83 @@
+package com.leetcode.hashtables.slidingwindow;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Hard
+ * Link: https://leetcode.com/problems/longest-substring-with-at-most-k-distinct-characters/
+ * Description:
+ * Given a string, find the length of the longest substring T that contains at most k distinct characters.
+ *
+ * Example 1:
+ * Input: s = "eceba", k = 2
+ * Output: 3
+ * Explanation: T is "ece" which its length is 3.
+ *
+ * Example 2:
+ * Input: s = "aa", k = 1
+ * Output: 2
+ * Explanation: T is "aa" which its length is 2.
+ *
+ * @author rampatra
+ * @since 2019-08-09
+ */
+public class LongestSubstringWithKDistinctCharacters {
+
+ /**
+ * Time Complexity: O(n)
+ * Space Complexity: O(k), as we keep at most k characters in the hash table
+ *
+ * @param str
+ * @param k
+ * @return
+ */
+ public static int lengthOfLongestSubstringKDistinct(String str, int k) {
+ int length = 0;
+ Map letterCountInWindow = new HashMap<>();
+
+ int left = 0; // start of window
+ int right = 0; // end of window
+
+ while (right < str.length()) {
+ char ch = str.charAt(right);
+
+ letterCountInWindow.put(ch, letterCountInWindow.getOrDefault(ch, 0) + 1);
+
+ // when number of distinct characters in the window exceeds k:
+ // - update length
+ // - remove the first character in the window or reduce its count if the window has more than one of this character
+ // - lastly, move the window forward
+ if (letterCountInWindow.keySet().size() > k) {
+ char firstChar = str.charAt(left);
+ int firstCharCount = letterCountInWindow.get(firstChar);
+ if (firstCharCount > 1) {
+ letterCountInWindow.put(firstChar, firstCharCount - 1);
+ } else {
+ letterCountInWindow.remove(firstChar);
+ }
+ length = Math.max(length, right - left);
+ left++;
+ }
+ right++;
+ }
+
+ return Math.max(length, right - left);
+ }
+
+ public static void main(String[] args) {
+ assertEquals(3, lengthOfLongestSubstringKDistinct("eceba", 2));
+ assertEquals(7, lengthOfLongestSubstringKDistinct("eceeeeeba", 2));
+ assertEquals(12, lengthOfLongestSubstringKDistinct("bbbeeeeebaaaaaaaaaaa", 2));
+ assertEquals(2, lengthOfLongestSubstringKDistinct("abcdef", 2));
+ assertEquals(1, lengthOfLongestSubstringKDistinct("a", 1));
+ assertEquals(0, lengthOfLongestSubstringKDistinct("aa", 0));
+ assertEquals(2, lengthOfLongestSubstringKDistinct("aa", 1));
+ assertEquals(3, lengthOfLongestSubstringKDistinct("aaa", 1));
+ assertEquals(3, lengthOfLongestSubstringKDistinct("aab", 2));
+ assertEquals(8, lengthOfLongestSubstringKDistinct("abcabcbb", 3));
+ assertEquals(5, lengthOfLongestSubstringKDistinct("pwwkew", 3));
+ }
+}
diff --git a/src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithoutRepeatingCharacters.java b/src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithoutRepeatingCharacters.java
new file mode 100644
index 00000000..93a940e4
--- /dev/null
+++ b/src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithoutRepeatingCharacters.java
@@ -0,0 +1,128 @@
+package com.leetcode.hashtables.slidingwindow;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Link: https://leetcode.com/problems/longest-substring-without-repeating-characters/
+ * Description:
+ * Given a string, find the length of the longest substring without repeating characters.
+ *
+ * Example 1:
+ * Input: "abcabcbb"
+ * Output: 3
+ * Explanation: The answer is "abc", with the length of 3.
+ *
+ * Example 2:
+ * Input: "bbbbb"
+ * Output: 1
+ * Explanation: The answer is "b", with the length of 1.
+ *
+ * Example 3:
+ * Input: "pwwkew"
+ * Output: 3
+ * Explanation: The answer is "wke", with the length of 3.
+ * Note that the answer must be a substring, "pwke" is a subsequence and not a substring.
+ *
+ * @author rampatra
+ * @since 2019-08-15
+ */
+public class LongestSubstringWithoutRepeatingCharacters {
+
+ /**
+ * Sliding Window Approach (using map).
+ *
+ * Note:
+ * If we know that the charset is rather small, we can replace the Map with an integer array as direct access table.
+ *
+ * Commonly used tables are:
+ *
+ * int[26] for Letters 'a' - 'z' or 'A' - 'Z'
+ * int[128] for ASCII
+ * int[256] for Extended ASCII
+ *
+ * Runtime: 8 ms.
+ *
+ * @param s
+ * @return
+ */
+ public static int lengthOfLongestSubstring(String s) {
+ int left = 0;
+ int right = 0;
+ int longestSubstringLen = 0;
+ Set charsInWindow = new HashSet<>();
+
+
+ while (right < s.length()) {
+
+ if (charsInWindow.contains(s.charAt(right))) {
+ while (s.charAt(left) != s.charAt(right)) {
+ longestSubstringLen = Math.max(longestSubstringLen, right - left);
+ charsInWindow.remove(s.charAt(left));
+ left++;
+ }
+ left++;
+ }
+
+ charsInWindow.add(s.charAt(right));
+ right++;
+ }
+
+ return Math.max(longestSubstringLen, right - left);
+ }
+
+ /**
+ * Sliding Window Approach using int array.
+ *
+ * Runtime: 2 ms.
+ *
+ * @param s
+ * @return
+ */
+ public static int lengthOfLongestSubstringNoMap(String s) {
+ int left = 0;
+ int right = 0;
+ int longestSubstringLen = 0;
+ int[] charsInWindow = new int[128];
+
+ // keep moving forward the right pointer and adding characters to the window
+ while (right < s.length()) {
+
+ // once we encounter repeated characters, move the left pointer until the repeated character is removed
+ if (charsInWindow[s.charAt(right)] == 1) {
+ while (s.charAt(left) != s.charAt(right)) {
+ longestSubstringLen = Math.max(longestSubstringLen, right - left);
+ charsInWindow[s.charAt(left)] = 0;
+ left++;
+ }
+ left++;
+ }
+
+ charsInWindow[s.charAt(right)] = 1;
+ right++;
+ }
+
+ return Math.max(longestSubstringLen, right - left);
+ }
+
+ public static void main(String[] args) {
+ assertEquals(0, lengthOfLongestSubstring(""));
+ assertEquals(1, lengthOfLongestSubstring(" "));
+ assertEquals(1, lengthOfLongestSubstring("a"));
+ assertEquals(2, lengthOfLongestSubstring("aab"));
+ assertEquals(3, lengthOfLongestSubstring("abcabcbb"));
+ assertEquals(1, lengthOfLongestSubstring("bbbbb"));
+ assertEquals(3, lengthOfLongestSubstring("pwwkew"));
+
+ assertEquals(0, lengthOfLongestSubstringNoMap(""));
+ assertEquals(1, lengthOfLongestSubstringNoMap(" "));
+ assertEquals(1, lengthOfLongestSubstringNoMap("a"));
+ assertEquals(2, lengthOfLongestSubstringNoMap("aab"));
+ assertEquals(3, lengthOfLongestSubstringNoMap("abcabcbb"));
+ assertEquals(1, lengthOfLongestSubstringNoMap("bbbbb"));
+ assertEquals(3, lengthOfLongestSubstringNoMap("pwwkew"));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/hashtables/slidingwindow/MinimumWindowSubstring.java b/src/main/java/com/leetcode/hashtables/slidingwindow/MinimumWindowSubstring.java
new file mode 100644
index 00000000..5414cdc1
--- /dev/null
+++ b/src/main/java/com/leetcode/hashtables/slidingwindow/MinimumWindowSubstring.java
@@ -0,0 +1,104 @@
+package com.leetcode.hashtables.slidingwindow;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Hard
+ * Link: https://leetcode.com/problems/minimum-window-substring/
+ * Description:
+ * Given a string S and a string T, find the minimum window in S which will contain all the characters in T in
+ * complexity O(n).
+ *
+ * Example:
+ *
+ * Input: S = "ADOBECODEBANC", T = "ABC"
+ * Output: "BANC"
+ *
+ * Note:
+ * - If there is no such window in S that covers all characters in T, return the empty string "".
+ * - If there is such window, you are guaranteed that there will always be only one unique minimum window in S.
+ *
+ * @author rampatra
+ * @since 2019-08-13
+ */
+public class MinimumWindowSubstring {
+
+ /**
+ * Sliding Window Approach (using map).
+ *
+ * Note:
+ * If we know that the charset is rather small, we can replace the Map with an integer array as direct access table.
+ *
+ * Commonly used tables are:
+ *
+ * int[26] for Letters 'a' - 'z' or 'A' - 'Z'
+ * int[128] for ASCII
+ * int[256] for Extended ASCII
+ *
+ * Runtime: 22 ms.
+ *
+ * @param s
+ * @param t
+ * @return
+ */
+ public static String minWindow(String s, String t) {
+
+ int left = 0; // start of window
+ int right = 0; // end of window
+ int begin = 0;
+ int windowSize = Integer.MAX_VALUE;
+ int charsInWindow = 0; // to check whether the window has all the characters in t with the required frequency
+
+ // characters and their counts in t
+ Map dictT = new HashMap<>();
+ for (int i = 0; i < t.length(); i++) {
+ char ch = t.charAt(i);
+ dictT.put(ch, dictT.getOrDefault(ch, 0) + 1);
+ }
+
+ // characters and their counts in the window
+ Map dictWindow = new HashMap<>();
+
+ while (right < s.length()) {
+ char rightChar = s.charAt(right);
+ int rightCharCount;
+ dictWindow.put(rightChar, (rightCharCount = dictWindow.getOrDefault(rightChar, 0) + 1));
+
+ // once the window has a character in t with the required frequency, increment charsInWindow
+ if (dictT.get(rightChar) != null && dictT.get(rightChar).equals(rightCharCount)) {
+ charsInWindow++;
+ }
+
+ // once the window has all characters in t with required frequency then shorten the window by moving the
+ // left window forward until the window no longer has all characters of t
+ while (left <= right && charsInWindow == dictT.size()) {
+ if (right - left < windowSize) {
+ windowSize = right - left + 1;
+ begin = left;
+ }
+
+ char leftChar = s.charAt(left);
+ Integer leftCharCount = dictWindow.get(leftChar);
+ dictWindow.put(leftChar, leftCharCount - 1);
+
+ if (dictT.get(leftChar) != null && leftCharCount - 1 < dictT.get(leftChar)) {
+ charsInWindow--;
+ }
+ left++;
+ }
+ right++;
+ }
+
+ return windowSize == Integer.MAX_VALUE ? "" : s.substring(begin, begin + windowSize);
+ }
+
+ public static void main(String[] args) {
+ assertEquals("BANC", minWindow("ADOBECODEBANC", "ABC"));
+ assertEquals("BAC", minWindow("ADOBECODEBAC", "ABC"));
+ assertEquals("ba", minWindow("bba", "ab"));
+ assertEquals("baca", minWindow("acbbaca", "aba"));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/heaps/KthLargestElementInArray.java b/src/main/java/com/leetcode/heaps/KthLargestElementInArray.java
new file mode 100644
index 00000000..2422de08
--- /dev/null
+++ b/src/main/java/com/leetcode/heaps/KthLargestElementInArray.java
@@ -0,0 +1,143 @@
+package com.leetcode.heaps;
+
+import com.rampatra.base.MaxHeap;
+
+import java.util.PriorityQueue;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Link: https://leetcode.com/problems/kth-largest-element-in-an-array/
+ * Description:
+ * Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not
+ * the kth distinct element.
+ *
+ * Example 1:
+ * Input: [3,2,1,5,6,4] and k = 2
+ * Output: 5
+ *
+ * Example 2:
+ * Input: [3,2,3,1,2,4,5,5,6] and k = 4
+ * Output: 4
+ *
+ * Note:
+ * You may assume k is always valid, 1 ≤ k ≤ array's length.
+ *
+ * @author rampatra
+ * @since 2019-08-19
+ */
+public class KthLargestElementInArray {
+
+ /**
+ * Runtime: 1 ms.
+ *
+ * @param nums
+ * @param k
+ * @return
+ */
+ public static int findKthLargest(int[] nums, int k) {
+ return heapSortUntilK(nums, k);
+ }
+
+ /**
+ * In heapsort, after each iteration we have the max element at the end of the array. Ergo, if we run the algorithm
+ * k times then we would have our kth largest element.
+ *
+ * @param a
+ * @param k
+ * @return
+ */
+ public static int heapSortUntilK(int[] a, int k) {
+ buildMaxHeap(a);
+ int count = 0;
+
+ for (int i = a.length - 1; i > 0; i--) {
+ if (count++ == k) {
+ break;
+ }
+ swap(a, 0, i);
+ maxHeapify(a, 0, i);
+ }
+
+ return a[a.length - k];
+ }
+
+ /**
+ * Makes the array {@param a} satisfy the max heap property starting from
+ * {@param index} till {@param end} position in array.
+ *
+ * See this {@link MaxHeap#maxHeapify} for a basic version of maxHeapify.
+ *
+ * Time complexity: O(log n).
+ *
+ * @param a
+ * @param index
+ * @param end
+ */
+ public static void maxHeapify(int[] a, int index, int end) {
+ int largest = index;
+ int leftIndex = 2 * index + 1;
+ int rightIndex = 2 * index + 2;
+
+ if (leftIndex < end && a[index] < a[leftIndex]) {
+ largest = leftIndex;
+ }
+ if (rightIndex < end && a[largest] < a[rightIndex]) {
+ largest = rightIndex;
+ }
+
+ if (largest != index) {
+ swap(a, index, largest);
+ maxHeapify(a, largest, end);
+ }
+ }
+
+ /**
+ * Converts array {@param a} in to a max heap.
+ *
+ * Time complexity: O(n) and is not O(n log n).
+ */
+ private static void buildMaxHeap(int[] a) {
+ for (int i = a.length / 2 - 1; i >= 0; i--) {
+ maxHeapify(a, i, a.length);
+ }
+ }
+
+
+ /**
+ * When you poll() on a PriorityQueue the smallest number in the queue is removed. Based on this property, we can
+ * iterate over the entire array and in the end we would be left with the k largest element in the queue.
+ *
+ * @param nums
+ * @param k
+ * @return
+ */
+ public static int findKthLargestUsingPriorityQueue(int[] nums, int k) {
+ PriorityQueue priorityQueue = new PriorityQueue<>();
+
+ for (int num : nums) {
+ priorityQueue.add(num);
+
+ if (priorityQueue.size() > k) {
+ priorityQueue.poll();
+ }
+ }
+
+ return priorityQueue.isEmpty() ? -1 : priorityQueue.peek();
+ }
+
+ private static void swap(int[] a, int firstIndex, int secondIndex) {
+ a[firstIndex] = a[firstIndex] + a[secondIndex];
+ a[secondIndex] = a[firstIndex] - a[secondIndex];
+ a[firstIndex] = a[firstIndex] - a[secondIndex];
+ }
+
+ public static void main(String[] args) {
+ assertEquals(5, findKthLargest(new int[]{3, 2, 1, 5, 6, 4}, 2));
+ assertEquals(3, findKthLargest(new int[]{3, 2, 1, 5, 6, 4}, 4));
+
+ assertEquals(5, findKthLargestUsingPriorityQueue(new int[]{3, 2, 1, 5, 6, 4}, 2));
+ assertEquals(3, findKthLargestUsingPriorityQueue(new int[]{3, 2, 1, 5, 6, 4}, 4));
+ }
+}
diff --git a/src/main/java/com/leetcode/heaps/TopKFrequentElements.java b/src/main/java/com/leetcode/heaps/TopKFrequentElements.java
new file mode 100644
index 00000000..5a684325
--- /dev/null
+++ b/src/main/java/com/leetcode/heaps/TopKFrequentElements.java
@@ -0,0 +1,68 @@
+package com.leetcode.heaps;
+
+import javafx.util.Pair;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Link: https://leetcode.com/problems/top-k-frequent-elements/
+ * Description:
+ * Given a non-empty array of integers, return the k most frequent elements.
+ *
+ * Example 1:
+ * Input: nums = [1,1,1,2,2,3], k = 2
+ * Output: [1,2]
+ *
+ * Example 2:
+ * Input: nums = [1], k = 1
+ * Output: [1]
+ *
+ * Note:
+ * - You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
+ * - Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
+ *
+ * @author rampatra
+ * @since 2019-08-19
+ */
+public class TopKFrequentElements {
+
+ /**
+ * TODO: A faster approach without using Pair.
+ *
+ * Runtime: 51 ms.
+ *
+ * @param nums
+ * @param k
+ * @return
+ */
+ public static List topKFrequent(int[] nums, int k) {
+ Map numCount = new HashMap<>();
+ PriorityQueue> pq = new PriorityQueue<>(Comparator.comparing(Pair::getValue));
+
+ for (int num : nums) {
+ numCount.put(num, numCount.getOrDefault(num, 0) + 1);
+ }
+
+ for (Map.Entry entry : numCount.entrySet()) {
+ pq.add(new Pair<>(entry.getKey(), entry.getValue()));
+
+ if (pq.size() > k) {
+ pq.poll();
+ }
+ }
+
+ return pq.stream().map(Pair::getKey).collect(Collectors.toList());
+ }
+
+ public static void main(String[] args) {
+ assertEquals("[2, 1]", topKFrequent(new int[]{1, 1, 1, 2, 2, 3}, 2).toString());
+ assertEquals("[0]", topKFrequent(new int[]{3, 0, 1, 0}, 1).toString());
+ assertEquals("[1]", topKFrequent(new int[]{1}, 1).toString());
+ assertEquals("[1, 2]", topKFrequent(new int[]{1, 2}, 2).toString());
+ assertEquals("[2, -1]", topKFrequent(new int[]{4, 1, -1, 2, -1, 2, 3}, 2).toString());
+ }
+}
diff --git a/src/main/java/com/leetcode/linkedlists/AddOneToNumberInList.java b/src/main/java/com/leetcode/linkedlists/AddOneToNumberInList.java
new file mode 100644
index 00000000..9f0a029c
--- /dev/null
+++ b/src/main/java/com/leetcode/linkedlists/AddOneToNumberInList.java
@@ -0,0 +1,91 @@
+package com.leetcode.linkedlists;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/plus-one-linked-list/
+ * Problem Description: Given a non-empty single linked list representing a number where the head is the
+ * most significant bit, add one to the number and return a new linked list.
+ *
+ * @author rampatra
+ * @since 2019-06-19
+ */
+public class AddOneToNumberInList {
+
+
+ /**
+ * Add {@code one} to the number represented by linked list {@code head}.
+ *
+ * @param head the starting node of the linked list
+ * @return the head of the linked list after adding {@code one}
+ */
+ private static Node addOne(Node head) {
+ Node currOrig = reverse(head);
+ Node currRes = null;
+ Node res = null;
+
+ int sum = 1;
+ int carry = 0;
+ int rem;
+
+ while (currOrig != null) {
+ sum += carry + currOrig.val;
+ rem = sum % 10;
+ carry = sum / 10;
+
+ if (res == null) {
+ res = currRes = new Node(rem);
+ } else {
+ currRes.next = new Node(rem);
+ currRes = currRes.next;
+ }
+
+ sum = 0;
+ currOrig = currOrig.next;
+ }
+
+ if (carry != 0) {
+ currRes.next = new Node(carry);
+ }
+
+ return reverse(res);
+ }
+
+ private static Node reverse(Node head) {
+ Node prev = null;
+ Node curr = head;
+ Node next;
+
+ while (curr != null) {
+ next = curr.next;
+ curr.next = prev;
+
+ prev = curr;
+ curr = next;
+ }
+
+ return prev;
+ }
+
+
+ public static void main(String[] args) {
+ Node node = new Node(9);
+ node.next = new Node(9);
+ node.next.next = new Node(9);
+ node.print();
+ addOne(node).print();
+
+ System.out.println("---------");
+
+ node = new Node(1);
+ node.next = new Node(9);
+ node.next.next = new Node(9);
+ node.print();
+ addOne(node).print();
+
+ System.out.println("---------");
+
+ node = new Node(0);
+ node.print();
+ addOne(node).print();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/linkedlists/LinkedListCycleII.java b/src/main/java/com/leetcode/linkedlists/LinkedListCycleII.java
new file mode 100644
index 00000000..d5fe0e50
--- /dev/null
+++ b/src/main/java/com/leetcode/linkedlists/LinkedListCycleII.java
@@ -0,0 +1,73 @@
+package com.leetcode.linkedlists;
+
+/**
+ * Level: Medium
+ * Link: https://leetcode.com/problems/linked-list-cycle-ii/
+ * Description:
+ * Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
+ *
+ * To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in
+ * the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
+ *
+ * Note: Do not modify the linked list.
+ *
+ * Example 1:
+ *
+ * Input: head = [3,2,0,-4], pos = 1
+ * Output: tail connects to node index 1
+ * Explanation: There is a cycle in the linked list, where tail connects to the second node.
+ *
+ *
+ * Example 2:
+ *
+ * Input: head = [1,2], pos = 0
+ * Output: tail connects to node index 0
+ * Explanation: There is a cycle in the linked list, where tail connects to the first node.
+ *
+ *
+ * Example 3:
+ *
+ * Input: head = [1], pos = -1
+ * Output: no cycle
+ * Explanation: There is no cycle in the linked list.
+ *
+ * Follow-up:
+ * Can you solve it without using extra space?
+ *
+ * @author rampatra
+ * @since 2019-08-18
+ */
+public class LinkedListCycleII {
+
+ /**
+ * Runtime: 0 ms.
+ *
+ * @param head
+ * @return
+ */
+ public Node detectCycle(Node head) {
+ Node slow = head;
+ Node fast = head;
+
+ while (fast != null && fast.next != null) {
+ slow = slow.next;
+ fast = fast.next.next;
+ if (slow == fast) {
+ break;
+ }
+ }
+
+ if (fast == null || fast.next == null) {
+ return null;
+ } else {
+ slow = head;
+
+ while (slow != fast) {
+ slow = slow.next;
+ fast = fast.next;
+ }
+
+ return slow;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/linkedlists/Node.java b/src/main/java/com/leetcode/linkedlists/Node.java
new file mode 100644
index 00000000..3276413f
--- /dev/null
+++ b/src/main/java/com/leetcode/linkedlists/Node.java
@@ -0,0 +1,23 @@
+package com.leetcode.linkedlists;
+
+/**
+ * @author rampatra
+ * @since 21/11/2018
+ */
+class Node {
+ int val;
+ Node next;
+
+ Node(int val) {
+ this.val = val;
+ }
+
+ public void print() {
+ Node curr = this;
+ while (curr.next != null) {
+ System.out.print(curr.val + "->");
+ curr = curr.next;
+ }
+ System.out.println(curr.val);
+ }
+}
diff --git a/src/main/java/com/leetcode/math/BestMeetingPoint.java b/src/main/java/com/leetcode/math/BestMeetingPoint.java
new file mode 100644
index 00000000..84d96fe9
--- /dev/null
+++ b/src/main/java/com/leetcode/math/BestMeetingPoint.java
@@ -0,0 +1,141 @@
+package com.leetcode.math;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Hard
+ * Link: https://leetcode.com/problems/best-meeting-point/
+ * Description:
+ * 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|.
+ *
+ * Example:
+ *
+ * Input:
+ *
+ * 1 - 0 - 0 - 0 - 1
+ * | | | | |
+ * 0 - 0 - 0 - 0 - 0
+ * | | | | |
+ * 0 - 0 - 1 - 0 - 0
+ *
+ * Output: 6
+ *
+ * Explanation: Given three people living at (0,0), (0,4), and (2,2):
+ * The point (0,2) is an ideal meeting point, as the total travel distance
+ * of 2+2+2=6 is minimal. So, return 6.
+ *
+ * @author rampatra
+ * @since 2019-08-07
+ */
+public class BestMeetingPoint {
+
+ /**
+ * Time Complexity: O(k * i * j)
+ * Space Complexity: O(1)
+ * where,
+ * k = no of homes
+ * i = rows in grid
+ * j = columns in grid
+ *
+ * So, if i = j = k then you can see that it has a O(n^3) time complexity.
+ *
+ * @param grid
+ * @return
+ */
+ public static int minTotalDistanceBrutForce(int[][] grid) {
+ int minDistance = Integer.MAX_VALUE;
+ List> homeCoordinates = new ArrayList<>();
+
+ for (int i = 0; i < grid.length; i++) {
+ for (int j = 0; j < grid[0].length; j++) {
+ if (grid[i][j] == 1) {
+ homeCoordinates.add(Arrays.asList(i, j));
+ }
+ }
+ }
+
+ for (int i = 0; i < grid.length; i++) {
+ for (int j = 0; j < grid[0].length; j++) {
+ int distance = 0;
+ for (int k = 0; k < homeCoordinates.size(); k++) {
+ distance += Math.abs(homeCoordinates.get(k).get(0) - i) + Math.abs(homeCoordinates.get(k).get(1) - j);
+ }
+ minDistance = Math.min(minDistance, distance);
+ }
+ }
+
+ return minDistance;
+ }
+
+ public static int minTotalDistance(int[][] grid) {
+ return -1; // todo
+ }
+
+ public static void main(String[] args) {
+ assertEquals(6, minTotalDistanceBrutForce(new int[][]{
+ {1,0,0,0,1},
+ {0,0,0,0,0},
+ {0,0,1,0,0}
+ }));
+
+ assertEquals(4, minTotalDistanceBrutForce(new int[][]{
+ {1,0,0,0,1},
+ {0,0,0,0,0},
+ {0,0,0,0,0}
+ }));
+
+ assertEquals(1, minTotalDistanceBrutForce(new int[][]{
+ {1,1,0,0,0},
+ {0,0,0,0,0},
+ {0,0,0,0,0}
+ }));
+
+ assertEquals(0, minTotalDistanceBrutForce(new int[][]{
+ {1,0,0,0,0},
+ {0,0,0,0,0},
+ {0,0,0,0,0}
+ }));
+
+ assertEquals(0, minTotalDistanceBrutForce(new int[][]{
+ {0,0,0,0,0},
+ {0,0,0,0,0},
+ {0,0,0,0,0}
+ }));
+
+ assertEquals(6, minTotalDistance(new int[][]{
+ {1,0,0,0,1},
+ {0,0,0,0,0},
+ {0,0,1,0,0}
+ }));
+
+ assertEquals(4, minTotalDistance(new int[][]{
+ {1,0,0,0,1},
+ {0,0,0,0,0},
+ {0,0,0,0,0}
+ }));
+
+ assertEquals(1, minTotalDistance(new int[][]{
+ {1,1,0,0,0},
+ {0,0,0,0,0},
+ {0,0,0,0,0}
+ }));
+
+ assertEquals(0, minTotalDistance(new int[][]{
+ {1,0,0,0,0},
+ {0,0,0,0,0},
+ {0,0,0,0,0}
+ }));
+
+ assertEquals(0, minTotalDistance(new int[][]{
+ {0,0,0,0,0},
+ {0,0,0,0,0},
+ {0,0,0,0,0}
+ }));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/math/ExcelSheetColumnNumber.java b/src/main/java/com/leetcode/math/ExcelSheetColumnNumber.java
new file mode 100644
index 00000000..29e1dded
--- /dev/null
+++ b/src/main/java/com/leetcode/math/ExcelSheetColumnNumber.java
@@ -0,0 +1,44 @@
+package com.leetcode.math;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/excel-sheet-column-number/
+ * Problem Description:
+ * Given a column title as appear in an Excel sheet, return its corresponding column number.
+ *
+ * For example:
+ *
+ * A -> 1
+ * B -> 2
+ * C -> 3
+ * ...
+ * Z -> 26
+ * AA -> 27
+ * AB -> 28
+ * ...
+ *
+ * Example 1:
+ * Input: "A"
+ * Output: 1
+ *
+ * Example 2:
+ * Input: "AB"
+ * Output: 28
+ *
+ * Example 3:
+ * Input: "ZY"
+ * Output: 701
+ *
+ * @author rampatra
+ * @since 2019-05-31
+ */
+public class ExcelSheetColumnNumber {
+
+ private static int titleToNumber(String title) {
+ return 0;
+ }
+
+ public static void main(String[] args) {
+
+ }
+}
diff --git a/src/main/java/com/leetcode/math/ReverseInteger.java b/src/main/java/com/leetcode/math/ReverseInteger.java
new file mode 100644
index 00000000..7e540778
--- /dev/null
+++ b/src/main/java/com/leetcode/math/ReverseInteger.java
@@ -0,0 +1,62 @@
+package com.leetcode.math;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/reverse-integer/
+ * Problem Description:
+ * Given a 32-bit signed integer, reverse digits of an integer.
+ *
+ * Example 1:
+ * Input: 123
+ * Output: 321
+ *
+ * Example 2:
+ * Input: -123
+ * Output: -321
+ *
+ * Example 3:
+ * Input: 120
+ * Output: 21
+ *
+ * Note: Assume we are dealing with an environment which could only store integers within the 32-bit signed
+ * integer range: [−2^31, 2^31 − 1]. For the purpose of this problem, assume that your function returns 0 when
+ * the reversed integer overflows.
+ *
+ * @author rampatra
+ * @since 2019-05-31
+ */
+public class ReverseInteger {
+
+ /**
+ * Reverses the input integer.
+ * Time complexity: O(d)
+ * where,
+ * d = number of digits in num
+ *
+ * Runtime: 1 ms.
+ *
+ * @param num an integer.
+ * @return the reverse of {@code num}.
+ */
+ private static int reverse(int num) {
+ long reverse = 0;
+ int pop;
+
+ while (num != 0) {
+ pop = num % 10;
+ num = num / 10;
+ reverse = reverse * 10 + pop;
+ }
+
+ return reverse < Integer.MIN_VALUE || reverse > Integer.MAX_VALUE ? 0 : (int) reverse;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(reverse(0));
+ System.out.println(reverse(-0));
+ System.out.println(reverse(123));
+ System.out.println(reverse(-123));
+ System.out.println(reverse(Integer.MAX_VALUE));
+ System.out.println(reverse(Integer.MIN_VALUE));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/recursion/FlattenNestListIterator.java b/src/main/java/com/leetcode/recursion/FlattenNestListIterator.java
new file mode 100644
index 00000000..b443e954
--- /dev/null
+++ b/src/main/java/com/leetcode/recursion/FlattenNestListIterator.java
@@ -0,0 +1,69 @@
+package com.leetcode.recursion;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Level: Medium
+ * Link: https://leetcode.com/problems/flatten-nested-list-iterator/
+ * Description:
+ * 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:
+ * Input: [[1,1],2,[1,1]]
+ * Output: [1,1,2,1,1]
+ * Explanation: By calling next repeatedly until hasNext returns false,
+ * the order of elements returned by next should be: [1,1,2,1,1].
+ *
+ * Example 2:
+ * Input: [1,[4,[6]]]
+ * Output: [1,4,6]
+ * Explanation: By calling next repeatedly until hasNext returns false,
+ * the order of elements returned by next should be: [1,4,6].
+ *
+ * Runtime: 2 ms.
+ *
+ * @author rampatra
+ * @since 2019-08-12
+ */
+public class FlattenNestListIterator implements Iterator {
+
+ private int index;
+ private List flattenedList;
+
+ public FlattenNestListIterator(List nestedList) {
+ index = 0;
+ flattenedList = getFlattenedList(nestedList);
+ }
+
+ private List getFlattenedList(List nestedList) {
+ List flattenedList = new ArrayList<>();
+
+ for (NestedInteger nestedInteger : nestedList) {
+ if (nestedInteger.isInteger()) {
+ flattenedList.add(nestedInteger.getInteger());
+ } else {
+ flattenedList.addAll(getFlattenedList(nestedInteger.getList()));
+ }
+ }
+
+ return flattenedList;
+ }
+
+ @Override
+ public Integer next() {
+ return flattenedList.get(index++);
+ }
+
+ @Override
+ public boolean hasNext() {
+ return index < flattenedList.size();
+ }
+
+ public static void main(String[] args) {
+ // TODO add some test cases
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/recursion/NestedInteger.java b/src/main/java/com/leetcode/recursion/NestedInteger.java
new file mode 100644
index 00000000..1bba817e
--- /dev/null
+++ b/src/main/java/com/leetcode/recursion/NestedInteger.java
@@ -0,0 +1,46 @@
+package com.leetcode.recursion;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class needed for various problems like {@link NestedListWeightSumII}, {@link FlattenNestListIterator}, etc.
+ *
+ * @author rampatra
+ * @since 2019-08-12
+ */
+public class NestedInteger {
+
+ private Integer integer;
+ private List list;
+
+ public NestedInteger() {
+ this.list = new ArrayList<>();
+ }
+
+ public NestedInteger(int integer) {
+ this.integer = integer;
+ this.list = new ArrayList<>();
+ }
+
+ public boolean isInteger() {
+ return this.integer != null;
+ }
+
+ public Integer getInteger() {
+ return integer;
+ }
+
+ public void setInteger(Integer integer) {
+ this.integer = integer;
+ }
+
+ public List getList() {
+ return list;
+ }
+
+ public NestedInteger add(NestedInteger nestedInteger) {
+ this.list.add(nestedInteger);
+ return this;
+ }
+}
diff --git a/src/main/java/com/leetcode/recursion/NestedListWeightSum.java b/src/main/java/com/leetcode/recursion/NestedListWeightSum.java
new file mode 100644
index 00000000..1079b29f
--- /dev/null
+++ b/src/main/java/com/leetcode/recursion/NestedListWeightSum.java
@@ -0,0 +1,57 @@
+package com.leetcode.recursion;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/nested-list-weight-sum/
+ * Problem Description:
+ * Given a nested list of integers, return the sum of all integers in the list weighted by their depth. 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]], return 10. (four 1’s at depth 2, one 2 at depth 1)
+ *
+ * Example 2:
+ * Given the list [1,[4,[6]]], return 27. (one 1 at depth 1, one 4 at depth 2, and one 6 at depth 3; 1 + 42 + 63 = 27)
+ *
+ * Note: For a more complex variant, see {@link NestedListWeightSumII}.
+ *
+ * @author rampatra
+ * @since 2019-07-27
+ */
+public class NestedListWeightSum {
+
+ /**
+ * Time Complexity: The algorithm takes O(N) time, where N is the total number of nested elements in the input
+ * list. For example, the list [ [[[[1]]]], 2 ] contains 4 nested lists and 2 nested integers (11 and 22), so N=6.
+ * Space Complexity: In terms of space, at most O(D) recursive calls are placed on the stack, where D is the
+ * maximum level of nesting in the input. For example, D=2 for the input [[1,1],2,[1,1]], and D=3 for the
+ * input [1,[4,[6]]].
+ *
+ * @param nestedList
+ * @return
+ */
+ public static long nestedSum(Object[] nestedList) {
+ return nestedSum(nestedList, 1);
+ }
+
+ private static long nestedSum(Object[] nestedList, int depth) {
+ long sum = 0;
+ for (int i = 0; i < nestedList.length; i++) {
+ if (nestedList[i] instanceof Integer) {
+ sum += ((int) nestedList[i] * depth);
+ } else {
+ sum += nestedSum((Object[]) nestedList[i], depth + 1);
+ }
+ }
+ return sum;
+ }
+
+ public static void main(String[] args) {
+ assertEquals(0, nestedSum(new Object[]{}));
+ assertEquals(0, nestedSum(new Object[]{new Object[]{}}));
+ assertEquals(10, nestedSum(new Object[]{new Object[]{1, 1}, 2, new Object[]{1, 1}}));
+ assertEquals(27, nestedSum(new Object[]{1, new Object[]{4, new Object[]{6}}}));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/recursion/NestedListWeightSumII.java b/src/main/java/com/leetcode/recursion/NestedListWeightSumII.java
new file mode 100644
index 00000000..eadd121b
--- /dev/null
+++ b/src/main/java/com/leetcode/recursion/NestedListWeightSumII.java
@@ -0,0 +1,80 @@
+package com.leetcode.recursion;
+
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Problem Link: https://leetcode.com/problems/nested-list-weight-sum-ii/
+ * Problem Description:
+ * Given a nested list of integers, return the sum of all integers in the list weighted by their depth. Each element
+ * is either an integer, or a list – whose elements may also be integers or other lists.
+ *
+ * Different from {@link NestedListWeightSum} where weight is increasing from root to leaf, now the weight is defined
+ * from bottom up, i.e., the leaf level integers have weight 1, and the root level integers have the largest weight.
+ *
+ * Example 1:
+ * Given the list [[1,1],2,[1,1]], return 8. (four 1’s at depth 1, one 2 at depth 2)
+ *
+ * Example 2:
+ * Given the list [1,[4,[6]]], return 17. (one 1 at depth 3, one 4 at depth 2, and one 6 at depth 1; 13 + 42 + 6*1 = 17)
+ *
+ * Note: For a simpler variant, see {@link NestedListWeightSum}.
+ *
+ * @author rampatra
+ * @since 2019-07-27
+ */
+public class NestedListWeightSumII {
+
+ /**
+ * Time Complexity:
+ * Space Complexity:
+ * Runtime: 1 ms.
+ *
+ * @param nestedList
+ * @return
+ */
+ public static int nestedSum(List nestedList) {
+ int weightedSum = 0;
+ int unweightedSum = 0;
+
+ while (!nestedList.isEmpty()) {
+ List nextLevel = new ArrayList<>();
+
+ for (NestedInteger ni : nestedList) {
+ if (ni.isInteger()) {
+ unweightedSum += ni.getInteger();
+ } else {
+ nextLevel.addAll(ni.getList());
+ }
+ }
+
+ unweightedSum += unweightedSum; // multiplication by repetitive addition
+ weightedSum = unweightedSum;
+ nestedList = nextLevel;
+ }
+
+ return weightedSum;
+ }
+
+ public static void main(String[] args) {
+ assertEquals(0, nestedSum(Collections.singletonList(new NestedInteger())));
+
+ assertEquals(0, nestedSum(Collections.singletonList(new NestedInteger().add(new NestedInteger()))));
+
+ // TODO: fix the test cases
+ // {2, {1,1}, {1,1}}
+ NestedInteger ni = new NestedInteger(2);
+ ni.add(new NestedInteger().add(new NestedInteger(1)).add(new NestedInteger(1)));
+ ni.add(new NestedInteger().add(new NestedInteger(1)).add(new NestedInteger(1)));
+
+ assertEquals(6, nestedSum(Collections.singletonList(ni)));
+
+ // {1, {4, {6}}}
+ ni = new NestedInteger(1);
+ ni.add(new NestedInteger(4).add(new NestedInteger(6)));
+
+ assertEquals(17, nestedSum(Collections.singletonList(ni)));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/stacks/ExclusiveTimeOfFunctions.java b/src/main/java/com/leetcode/stacks/ExclusiveTimeOfFunctions.java
new file mode 100644
index 00000000..63c61dc2
--- /dev/null
+++ b/src/main/java/com/leetcode/stacks/ExclusiveTimeOfFunctions.java
@@ -0,0 +1,89 @@
+package com.leetcode.stacks;
+
+import javafx.util.Pair;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Stack;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Link: https://leetcode.com/problems/exclusive-time-of-functions/
+ * Description:
+ * On a single threaded CPU, we execute some functions. Each function has a unique id between 0 and N-1.
+ *
+ * We store logs in timestamp order that describe when a function is entered or exited.
+ *
+ * Each log is a string with this format: "{function_id}:{"start" | "end"}:{timestamp}". For example, "0:start:3"
+ * means the function with id 0 started at the beginning of timestamp 3. "1:end:2" means the function with id 1 ended
+ * at the end of timestamp 2.
+ *
+ * A function's exclusive time is the number of units of time spent in this function. Note that this does not include
+ * any recursive calls to child functions.
+ *
+ * The CPU is single threaded which means that only one function is being executed at a given time unit.
+ *
+ * Return the exclusive time of each function, sorted by their function id.
+ *
+ * Input:
+ * n = 2
+ * logs = ["0:start:0","1:start:2","1:end:5","0:end:6"]
+ * Output: [3, 4]
+ * Explanation:
+ * Function 0 starts at the beginning of time 0, then it executes 2 units of time and reaches the end of time 1.
+ * Now function 1 starts at the beginning of time 2, executes 4 units of time and ends at time 5.
+ * Function 0 is running again at the beginning of time 6, and also ends at the end of time 6, thus executing for 1 unit of time.
+ * So function 0 spends 2 + 1 = 3 units of total time executing, and function 1 spends 4 units of total time executing.
+ *
+ *
+ * Note:
+ * -> 1 <= n <= 100
+ * -> Two functions won't start or end at the same time.
+ * -> Functions will always log when they exit.
+ *
+ * @author rampatra
+ * @since 2019-08-17
+ */
+public class ExclusiveTimeOfFunctions {
+
+ /**
+ * Runtime: 18 ms.
+ *
+ * @param n
+ * @param logs
+ * @return
+ */
+ public static int[] exclusiveTime(int n, List logs) {
+ int[] times = new int[n];
+ Stack> stack = new Stack<>();
+
+ for (String log : logs) {
+ String[] l = log.split(":");
+ int id = Integer.parseInt(l[0]);
+ String operation = l[1];
+ int timestamp = Integer.parseInt(l[2]);
+
+ if (operation.equals("start")) {
+ if (!stack.empty()) { // if there are other processes started before, calculate their time until now
+ times[stack.peek().getKey()] += (timestamp - stack.peek().getValue() - 1);
+ }
+ stack.push(new Pair<>(id, timestamp));
+ } else {
+ times[id] += timestamp - stack.pop().getValue() + 1;
+ if (!stack.isEmpty()) { // if there are other processes, make their start time to now
+ stack.push(new Pair<>(stack.pop().getKey(), timestamp));
+ }
+ }
+ }
+
+ return times;
+ }
+
+ public static void main(String[] args) {
+ assertEquals("[4]", Arrays.toString(exclusiveTime(1, Arrays.asList("0:start:0", "0:start:1", "0:end:2", "0:end:3"))));
+ assertEquals("[6]", Arrays.toString(exclusiveTime(1, Arrays.asList("0:start:0", "0:start:1", "0:start:2", "0:end:3", "0:end:4", "0:end:5"))));
+ assertEquals("[3, 4]", Arrays.toString(exclusiveTime(2, Arrays.asList("0:start:0", "1:start:2", "1:end:5", "0:end:6"))));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/stacks/ReversePolishNotation.java b/src/main/java/com/leetcode/stacks/ReversePolishNotation.java
new file mode 100644
index 00000000..f917099a
--- /dev/null
+++ b/src/main/java/com/leetcode/stacks/ReversePolishNotation.java
@@ -0,0 +1,93 @@
+package com.leetcode.stacks;
+
+import java.util.Stack;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Problem Link: https://leetcode.com/problems/evaluate-reverse-polish-notation
+ * Problem Description:
+ * Evaluate the value of an arithmetic expression in Reverse Polish Notation.
+ *
+ * Valid operators are +, -, *, /. Each operand may be an integer or another expression.
+ *
+ * Note:
+ * Division between two integers should truncate toward zero.
+ * The given RPN expression is always valid. That means the expression would always evaluate to a result and there
+ * won't be any divide by zero operation.
+ *
+ * Example 1:
+ * Input: ["2", "1", "+", "3", "*"]
+ * Output: 9
+ * Explanation: ((2 + 1) * 3) = 9
+ *
+ * Example 2:
+ * Input: ["4", "13", "5", "/", "+"]
+ * Output: 6
+ * Explanation: (4 + (13 / 5)) = 6
+ *
+ * Example 3:
+ * Input: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]
+ * Output: 22
+ * Explanation:
+ * ((10 * (6 / ((9 + 3) * -11))) + 17) + 5
+ * = ((10 * (6 / (12 * -11))) + 17) + 5
+ * = ((10 * (6 / -132)) + 17) + 5
+ * = ((10 * 0) + 17) + 5
+ * = (0 + 17) + 5
+ * = 17 + 5
+ * = 22
+ *
+ * @author rampatra
+ * @since 2019-07-27
+ */
+public class ReversePolishNotation {
+
+ /**
+ * Time Complexity:
+ * Space Complexity:
+ * Runtime: 5 ms.
+ *
+ * @param tokens
+ * @return
+ */
+ public static int evalRPN(String[] tokens) {
+ int operand1;
+ int operand2;
+
+ Stack stack = new Stack<>();
+
+ for (String s : tokens) {
+ switch (s) {
+ case "+":
+ stack.push(stack.pop() + stack.pop());
+ break;
+ case "-":
+ operand1 = stack.pop();
+ operand2 = stack.pop();
+ stack.push(operand2 - operand1);
+ break;
+ case "*":
+ stack.push(stack.pop() * stack.pop());
+ break;
+ case "/":
+ operand1 = stack.pop();
+ operand2 = stack.pop();
+ stack.push(operand2 / operand1);
+ break;
+ default:
+ stack.push(Integer.parseInt(s));
+ }
+ }
+
+ return stack.pop();
+ }
+
+ public static void main(String[] args) {
+ assertEquals(18, evalRPN(new String[]{"18"}));
+ assertEquals(9, evalRPN(new String[]{"2", "1", "+", "3", "*"}));
+ assertEquals(6, evalRPN(new String[]{"4", "13", "5", "/", "+"}));
+ assertEquals(22, evalRPN(new String[]{"10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"}));
+ }
+}
diff --git a/src/main/java/com/leetcode/strings/AnagramsInString.java b/src/main/java/com/leetcode/strings/AnagramsInString.java
new file mode 100644
index 00000000..12e7d766
--- /dev/null
+++ b/src/main/java/com/leetcode/strings/AnagramsInString.java
@@ -0,0 +1,143 @@
+package com.leetcode.strings;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Level: Medium
+ * Problem: https://leetcode.com/problems/find-all-anagrams-in-a-string/
+ * Description:
+ * Given a string s and a non-empty string p, find all the start indices of p's anagrams in s.
+ *
+ * Strings consists of lowercase English letters only and the length of both strings s and p will not be larger
+ * than 20,100.
+ *
+ * The order of output does not matter.
+ *
+ * Example 1:
+ *
+ * Input:
+ * s: "cbaebabacd" p: "abc"
+ *
+ * Output:
+ * [0, 6]
+ *
+ * Explanation:
+ * The substring with start index = 0 is "cba", which is an anagram of "abc".
+ * The substring with start index = 6 is "bac", which is an anagram of "abc".
+ *
+ * Example 2:
+ *
+ * Input:
+ * s: "abab" p: "ab"
+ *
+ * Output:
+ * [0, 1, 2]
+ *
+ * Explanation:
+ * The substring with start index = 0 is "ab", which is an anagram of "ab".
+ * The substring with start index = 1 is "ba", which is an anagram of "ab".
+ * The substring with start index = 2 is "ab", which is an anagram of "ab".
+ *
+ * @author rampatra
+ * @since 2019-04-13
+ */
+public class AnagramsInString {
+
+ /**
+ * Time complexity: O((n-m) * m log m)
+ * where,
+ * n = text length
+ * m = pattern length
+ *
+ * @param text
+ * @param pattern
+ * @return
+ */
+ private static List findAllAnagramsInTextNaive(String text, String pattern) {
+ List indexes = new ArrayList<>();
+
+ int textLen = text.length();
+ int patternLen = pattern.length();
+
+ char[] patternChars = pattern.toCharArray();
+ Arrays.sort(patternChars); // takes O(m log m) time
+ String patternSorted = String.valueOf(patternChars);
+
+ String subText;
+ char[] subTextChars;
+ String subTextSorted;
+
+ for (int i = 0; i <= textLen - patternLen; i++) { // loops n-m number of times
+ subText = text.substring(i, i + patternLen);
+ subTextChars = subText.toCharArray();
+ Arrays.sort(subTextChars); // sorts m number of characters, takes O(m log m)
+ subTextSorted = String.valueOf(subTextChars);
+
+ if (subTextSorted.equals(patternSorted)) { // compare m characters takes m time
+ indexes.add(i);
+ }
+ }
+ return indexes;
+ }
+
+ /**
+ * Time complexity: O(n)
+ * where,
+ * n = length of text or number of characters in text
+ *
+ * Runtime: 6 ms.
+ *
+ * @param text
+ * @param pattern
+ * @return
+ */
+ private static List findAllAnagramsInText(String text, String pattern) {
+ List indices = new ArrayList<>();
+
+ int textLen = text.length();
+ int patternLen = pattern.length();
+
+ int[] textCharCountInWindow = new int[26];
+ int[] patternCharCount = new int[26];
+
+ for (int i = 0; i < patternLen; i++) {
+ patternCharCount[pattern.charAt(i) - 'a']++;
+ }
+
+ for (int i = 0; i < textLen; i++) {
+ textCharCountInWindow[text.charAt(i) - 'a']++;
+ if (i >= patternLen) {
+ textCharCountInWindow[text.charAt(i - patternLen) - 'a']--;
+ }
+ if (Arrays.equals(textCharCountInWindow, patternCharCount)) { // loops 26 times no matter the text/pattern length
+ indices.add(i - patternLen + 1);
+ }
+ }
+
+ return indices;
+ }
+
+ public static void main(String[] args) {
+ // basic use cases
+ System.out.println(findAllAnagramsInTextNaive("cbaebabacd", "abc"));
+ System.out.println(findAllAnagramsInTextNaive("abab", "ab"));
+ System.out.println(findAllAnagramsInTextNaive("af", "af"));
+ System.out.println(findAllAnagramsInTextNaive("af", "be"));
+
+ // corner case
+ System.out.println(findAllAnagramsInTextNaive("", "ab"));
+
+ System.out.println("-----");
+
+ // basic use cases
+ System.out.println(findAllAnagramsInText("cbaebabacd", "abc"));
+ System.out.println(findAllAnagramsInText("abab", "ab"));
+ System.out.println(findAllAnagramsInText("af", "af"));
+ System.out.println(findAllAnagramsInText("af", "be"));
+
+ // corner case
+ System.out.println(findAllAnagramsInText("", "ab"));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/strings/CountAndSay.java b/src/main/java/com/leetcode/strings/CountAndSay.java
new file mode 100644
index 00000000..24f41a3e
--- /dev/null
+++ b/src/main/java/com/leetcode/strings/CountAndSay.java
@@ -0,0 +1,48 @@
+package com.leetcode.strings;
+
+/**
+ * Level: Easy
+ * Problem: https://leetcode.com/problems/count-and-say/
+ *
+ * @author rampatra
+ * @since 2019-04-20
+ */
+public class CountAndSay {
+
+ /**
+ * Time complexity:
+ * Runtime: 1 ms.
+ *
+ * @param n
+ * @return
+ */
+ public static String countAndSay(int n) {
+ if (n == 1) return "1";
+
+ String s = countAndSay(n - 1);
+ StringBuilder sb = new StringBuilder();
+ int count = 0;
+
+ for (int i = 0; i < s.length(); i++) {
+ count++;
+
+ if (i + 1 >= s.length() || s.charAt(i) != s.charAt(i + 1)) {
+ sb.append(count);
+ sb.append(s.charAt(i));
+ count = 0;
+ }
+ }
+
+ return sb.toString();
+ }
+
+ public static void main(String[] args) {
+ System.out.println(countAndSay(1));
+ System.out.println(countAndSay(2));
+ System.out.println(countAndSay(3));
+ System.out.println(countAndSay(4));
+ System.out.println(countAndSay(5));
+ System.out.println(countAndSay(6));
+ System.out.println(countAndSay(10));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/strings/LongestCommonPrefix.java b/src/main/java/com/leetcode/strings/LongestCommonPrefix.java
new file mode 100644
index 00000000..07bd6392
--- /dev/null
+++ b/src/main/java/com/leetcode/strings/LongestCommonPrefix.java
@@ -0,0 +1,48 @@
+package com.leetcode.strings;
+
+/**
+ * Level: Easy
+ * Problem: https://leetcode.com/problems/longest-common-prefix/
+ *
+ * @author rampatra
+ * @since 2019-04-20
+ */
+public class LongestCommonPrefix {
+
+ /**
+ * Time complexity: O(r * c)
+ * where,
+ * r = no. of strings
+ * c = max. no. of characters in a particular string
+ *
+ * Runtime: 1 ms.
+ *
+ * @param strs
+ * @return
+ */
+ public static String longestCommonPrefix(String[] strs) {
+ if (strs == null || strs.length == 0) return "";
+
+ int row;
+ for (int col = 0; col < strs[0].length(); col++) {
+ for (row = 0; row < strs.length - 1; row++) {
+ // once we find a different character under one column, return the characters read so far
+ if (col == strs[row].length()
+ || col == strs[row + 1].length()
+ || strs[row].charAt(col) != strs[row + 1].charAt(col)) {
+ return strs[row].substring(0, col);
+ }
+ }
+ }
+
+ return strs[0];
+ }
+
+ public static void main(String[] args) {
+ System.out.println(longestCommonPrefix(new String[]{}));
+ System.out.println(longestCommonPrefix(new String[]{""}));
+ System.out.println(longestCommonPrefix(new String[]{"a"}));
+ System.out.println(longestCommonPrefix(new String[]{"flower", "flow", "flight"}));
+ System.out.println(longestCommonPrefix(new String[]{"dog", "racecar", "car"}));
+ }
+}
diff --git a/src/main/java/com/leetcode/strings/RansomNote.java b/src/main/java/com/leetcode/strings/RansomNote.java
new file mode 100644
index 00000000..c6b66fb0
--- /dev/null
+++ b/src/main/java/com/leetcode/strings/RansomNote.java
@@ -0,0 +1,40 @@
+package com.leetcode.strings;
+
+/**
+ * Level: Easy
+ * Problem: https://leetcode.com/problems/ransom-note/
+ *
+ * @author rampatra
+ * @since 2019-04-19
+ */
+public class RansomNote {
+
+ /**
+ * Runtime: 4 ms/a>.
+ *
+ * @param ransomNote
+ * @param magazine
+ * @return
+ */
+ public static boolean canConstruct(String ransomNote, String magazine) {
+ char[] charCount = new char[26];
+
+ for (int i = 0; i < magazine.length(); i++) {
+ charCount[magazine.charAt(i) - 'a']++;
+ }
+
+ for (int i = 0; i < ransomNote.length(); i++) {
+ if (charCount[ransomNote.charAt(i) - 'a']-- == 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(canConstruct("", ""));
+ System.out.println(canConstruct("a", "a"));
+ System.out.println(canConstruct("ab", "ab"));
+ System.out.println(canConstruct("aab", "ab"));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/strings/ReverseStringII.java b/src/main/java/com/leetcode/strings/ReverseStringII.java
new file mode 100644
index 00000000..4a5aabd4
--- /dev/null
+++ b/src/main/java/com/leetcode/strings/ReverseStringII.java
@@ -0,0 +1,46 @@
+package com.leetcode.strings;
+
+/**
+ * Level: Easy
+ * Problem: https://leetcode.com/problems/reverse-string-ii/
+ *
+ * @author rampatra
+ * @since 2019-04-20
+ */
+public class ReverseStringII {
+
+ /**
+ * Time complexity: O(n)
+ * where,
+ * n = no. of characters in string
+ *
+ * Runtime: 0 ms.
+ *
+ * @param str
+ * @param k
+ * @return
+ */
+ public static String reverseStr(String str, int k) {
+ char[] chars = str.toCharArray();
+ int len = str.length();
+ for (int i = 0; i < len; i += 2 * k) {
+ reverse(chars, i, Math.min(len, i + k));
+ }
+ return new String(chars);
+ }
+
+ private static void reverse(char[] chars, int start, int end) {
+ char temp;
+ for (int i = start, j = end - 1; i < j; i++, j--) {
+ temp = chars[i];
+ chars[i] = chars[j];
+ chars[j] = temp;
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println(reverseStr("abcdefg", 2));
+ System.out.println(reverseStr("abcdef", 2));
+ System.out.println(reverseStr("abcde", 2));
+ }
+}
diff --git a/src/main/java/com/leetcode/strings/ReverseVowels.java b/src/main/java/com/leetcode/strings/ReverseVowels.java
new file mode 100644
index 00000000..25518cac
--- /dev/null
+++ b/src/main/java/com/leetcode/strings/ReverseVowels.java
@@ -0,0 +1,66 @@
+package com.leetcode.strings;
+
+/**
+ * Level: Easy
+ * Problem: https://leetcode.com/problems/reverse-vowels-of-a-string/
+ *
+ * @author rampatra
+ * @since 2019-04-19
+ */
+public class ReverseVowels {
+
+ /**
+ * Reverse only the vowels in the string {@code str}.
+ *
+ * Time Complexity: O(n)
+ * where,
+ * n = no. of characters in the string
+ *
+ * Runtime: 2 ms on leetcode.
+ *
+ * @param str
+ * @return
+ */
+ private static String reverseVowels(String str) {
+
+ char[] chars = str.toCharArray();
+ char temp;
+ int left = 0;
+ int right = str.length() - 1;
+
+ while (left < right) {
+ // find the vowel from left
+ while (!isVowel(chars[left]) && left < right) {
+ left++;
+ }
+ // find the vowel from right
+ while (!isVowel(chars[right]) && left < right) {
+ right--;
+ }
+
+ if (!isVowel(chars[left]) || !isVowel(chars[right])) {
+ break;
+ }
+
+ // swap the characters
+ temp = chars[left];
+ chars[left] = chars[right];
+ chars[right] = temp;
+
+ left++;
+ right--;
+ }
+ return new String(chars);
+ }
+
+ private static boolean isVowel(char c) {
+ return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' ||
+ c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U';
+ }
+
+ public static void main(String[] args) {
+ System.out.println(reverseVowels("hello"));
+ System.out.println(reverseVowels("a"));
+ System.out.println(reverseVowels(""));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/strings/StrStr.java b/src/main/java/com/leetcode/strings/StrStr.java
new file mode 100644
index 00000000..aa3bc896
--- /dev/null
+++ b/src/main/java/com/leetcode/strings/StrStr.java
@@ -0,0 +1,59 @@
+package com.leetcode.strings;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/implement-strstr/
+ * Problem Description:
+ * Implement strStr(). Return the index of the first occurrence of needle in haystack, or -1 if needle
+ * is not part of haystack.
+ *
+ * Example 1:
+ *
+ * Input: haystack = "hello", needle = "ll"
+ * Output: 2
+ * Example 2:
+ *
+ * Input: haystack = "aaaaa", needle = "bba"
+ * Output: -1
+ *
+ * @author rampatra
+ * @since 2019-04-28
+ */
+public class StrStr {
+
+ /**
+ * Time complexity: O(m*n)
+ * where,
+ * m = length of haystack
+ * n = length of needle
+ *
+ * Runtime: 3 ms.
+ *
+ * @param haystack
+ * @param needle
+ * @return
+ */
+ public static int strStr(String haystack, String needle) {
+ for (int i = 0; ; i++) {
+ for (int j = 0; ; j++) {
+ if (j == needle.length()) return i;
+ if (i + j == haystack.length()) return -1;
+ if (needle.charAt(j) != haystack.charAt(i + j)) break;
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println(strStr("hello", "ll"));
+ System.out.println(strStr("leet", "e"));
+ System.out.println(strStr("mississippi", "issip"));
+ System.out.println(strStr("mississippi", "pi"));
+ System.out.println(strStr("aaaa", "bba"));
+
+ // edge cases
+ System.out.println(strStr("aaa", "aaaa"));
+ System.out.println(strStr("aaaa", ""));
+ System.out.println(strStr("", "abc"));
+ System.out.println(strStr("", ""));
+ }
+}
diff --git a/src/main/java/com/leetcode/strings/StringCompression.java b/src/main/java/com/leetcode/strings/StringCompression.java
new file mode 100644
index 00000000..7697f591
--- /dev/null
+++ b/src/main/java/com/leetcode/strings/StringCompression.java
@@ -0,0 +1,15 @@
+package com.leetcode.strings;
+
+/**
+ * @author rampatra
+ * @since 2019-04-16
+ */
+public class StringCompression {
+
+ private static int compress(char[] chars) {
+ return -1;
+ }
+
+ public static void main(String[] args) {
+ }
+}
diff --git a/src/main/java/com/leetcode/strings/UniqueCharacterInString.java b/src/main/java/com/leetcode/strings/UniqueCharacterInString.java
new file mode 100644
index 00000000..da155710
--- /dev/null
+++ b/src/main/java/com/leetcode/strings/UniqueCharacterInString.java
@@ -0,0 +1,38 @@
+package com.leetcode.strings;
+
+/**
+ * Level: Easy
+ * Problem: https://leetcode.com/problems/first-unique-character-in-a-string/
+ *
+ * @author rampatra
+ * @since 2019-04-16
+ */
+public class UniqueCharacterInString {
+
+ /**
+ * Time complexity: O(n)
+ * Runtime: 7 ms on leetcode.
+ *
+ * @param str the input string
+ * @return the index of the first non-repeating character in {@code str}, {@code -1} otherwise.
+ */
+ private static int findFirstUniqueCharacterInString(String str) {
+ int[] charCount = new int[26];
+
+ for (int i = 0; i < str.length(); i++) {
+ charCount[str.charAt(i) - 'a']++;
+ }
+
+ for (int i = 0; i < str.length(); i++) {
+ if (charCount[str.charAt(i) - 'a'] == 1) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(findFirstUniqueCharacterInString("leetcode"));
+ System.out.println(findFirstUniqueCharacterInString("loveleetcode"));
+ }
+}
diff --git a/src/main/java/com/leetcode/strings/ValidPalindrome.java b/src/main/java/com/leetcode/strings/ValidPalindrome.java
new file mode 100644
index 00000000..451849b6
--- /dev/null
+++ b/src/main/java/com/leetcode/strings/ValidPalindrome.java
@@ -0,0 +1,59 @@
+package com.leetcode.strings;
+
+/**
+ * Level: Easy
+ * Problem: https://leetcode.com/problems/valid-palindrome/
+ *
+ * @author rampatra
+ * @since 2019-04-19
+ */
+public class ValidPalindrome {
+
+ /**
+ * Time complexity: O(n)
+ * where,
+ * n = no. of characters in the string
+ *
+ * Runtime: 2 ms on leetcode.
+ *
+ * @param str
+ * @return
+ */
+ private static boolean isPalindrome(String str) {
+ char[] chars = str.toCharArray();
+ int left = 0;
+ int right = chars.length - 1;
+
+ while (left < right) {
+ // if it's not alphanumeric then move the left pointer forward
+ while (!isAlphaNumeric(chars[left]) && left < right) {
+ left++;
+ }
+ // if it's not alphanumeric then move the right pointer backward
+ while (!isAlphaNumeric(chars[right]) && left < right) {
+ right--;
+ }
+
+ // case insensitive comparison
+ if (Character.toLowerCase(chars[left]) != Character.toLowerCase(chars[right])) {
+ return false;
+ }
+
+ left++;
+ right--;
+ }
+
+ return true;
+ }
+
+ private static boolean isAlphaNumeric(char c) {
+ int i = (int) c;
+ return (i >= 48 && i <= 57) || (i >= 65 && i <= 90) || (i >= 97 && i <= 122);
+ }
+
+ public static void main(String[] args) {
+ System.out.println(isPalindrome("A man, a plan, a canal: Panama"));
+ System.out.println(isPalindrome("race a car"));
+ System.out.println(isPalindrome("0P"));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/trees/BinaryTreeUpsideDown.java b/src/main/java/com/leetcode/trees/BinaryTreeUpsideDown.java
new file mode 100644
index 00000000..aa43bf50
--- /dev/null
+++ b/src/main/java/com/leetcode/trees/BinaryTreeUpsideDown.java
@@ -0,0 +1,207 @@
+package com.leetcode.trees;
+
+import java.util.Stack;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+/**
+ * Level: Medium
+ * Problem Link: https://leetcode.com/problems/binary-tree-upside-down/
+ * Problem Description:
+ * 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.
+ *
+ * Example:
+ * Input: [1,2,3,4,5]
+ *
+ * 1
+ * / \
+ * 2 3
+ * / \
+ * 4 5
+ *
+ * Output: return the root of the binary tree [4,5,2,#,#,3,1]
+ *
+ * 4
+ * / \
+ * 5 2
+ * / \
+ * 3 1
+ *
+ * Clarification:
+ * Confused what [4,5,2,#,#,3,1] means? Read more below on how binary tree is serialized on OJ. The serialization of
+ * a binary tree follows a level order traversal, where '#' signifies a path terminator where no node exists below.
+ *
+ * Here's an example:
+ *
+ * 1
+ * / \
+ * 2 3
+ * /
+ * 4
+ * \
+ * 5
+ *
+ * The above binary tree is serialized as [1,2,3,#,#,4,#,#,5].
+ *
+ * @author rampatra
+ * @since 2019-08-04
+ */
+public class BinaryTreeUpsideDown {
+
+ /**
+ * The solution is simple, every node (except the root) on the left of the tree would have its parent's right child
+ * as it's left child and parent as its right child. That's all you have to do to flip the tree upside down.
+ *
+ * Time Complexity: O(h)
+ * Space Complexity: O(h)
+ * where,
+ * h = height of the tree
+ *
+ * Runtime: 1 ms.
+ *
+ * @param root
+ * @return
+ */
+ public static TreeNode upsideDownBinaryTreeUsingStack(TreeNode root) {
+ if (root == null) return null;
+
+ TreeNode curr = root;
+ TreeNode currParent;
+ TreeNode newRoot = null;
+
+ // using stack to keep track of the parent node
+ Stack stack = new Stack<>();
+
+ while (curr != null) {
+ stack.add(curr);
+ curr = curr.left;
+ }
+
+ while (!stack.empty()) {
+ curr = stack.pop();
+ currParent = stack.empty() ? null : stack.peek();
+
+ if (newRoot == null) newRoot = curr;
+
+ if (currParent != null) {
+ curr.left = currParent.right;
+ curr.right = currParent;
+ } else {
+ curr.left = null;
+ curr.right = null;
+ }
+ }
+
+ return newRoot;
+ }
+
+ /**
+ * The solution is simple, every node (except the root) on the left of the tree would have its parent's right child
+ * as it's left child and parent as its right child. That's all you have to do to flip the tree upside down.
+ *
+ * Time Complexity: O(h)
+ * Space Complexity: O(h)
+ * where,
+ * h = height of the tree
+ *
+ * Runtime: 0 ms.
+ *
+ * @param node
+ * @return
+ */
+ public static TreeNode upsideDownBinaryTree(TreeNode node) {
+ if (node == null || node.left == null) return node;
+
+ // go to the last node on the extreme left branch
+ TreeNode newRoot = upsideDownBinaryTree(node.left);
+
+ // do the node changes as you backtrack
+ node.left.left = node.right;
+ node.left.right = node;
+
+ // clean up
+ node.left = null;
+ node.right = null;
+
+ return newRoot;
+ }
+
+ public static void main(String[] args) {
+ /*
+ Binary Tree
+
+ 1
+ / \
+ 2 3
+ / \
+ 4 5
+ */
+ TreeNode tree = new TreeNode(1);
+ tree.left = new TreeNode(2);
+ tree.right = new TreeNode(3);
+ tree.left.left = new TreeNode(4);
+ tree.left.right = new TreeNode(5);
+
+ /*
+ Upside Down Binary Tree
+
+ 4
+ / \
+ 5 2
+ / \
+ 3 1
+ */
+ TreeNode upsideDownTree = upsideDownBinaryTreeUsingStack(tree);
+ assertEquals(4, upsideDownTree.val);
+ assertEquals(5, upsideDownTree.left.val);
+ assertEquals(2, upsideDownTree.right.val);
+ assertEquals(1, upsideDownTree.right.right.val);
+ assertEquals(3, upsideDownTree.right.left.val);
+ assertNull(upsideDownTree.right.right.left);
+ assertNull(upsideDownTree.right.right.right);
+
+
+
+ /******************************
+ *
+ * Test for the recursive method
+ *
+ ******************************/
+
+ /*
+ Binary Tree
+
+ 1
+ / \
+ 2 3
+ / \
+ 4 5
+ */
+ tree = new TreeNode(1);
+ tree.left = new TreeNode(2);
+ tree.right = new TreeNode(3);
+ tree.left.left = new TreeNode(4);
+ tree.left.right = new TreeNode(5);
+
+ /*
+ Upside Down Binary Tree
+
+ 4
+ / \
+ 5 2
+ / \
+ 3 1
+ */
+ upsideDownTree = upsideDownBinaryTree(tree);
+ assertEquals(4, upsideDownTree.val);
+ assertEquals(5, upsideDownTree.left.val);
+ assertEquals(2, upsideDownTree.right.val);
+ assertEquals(1, upsideDownTree.right.right.val);
+ assertEquals(3, upsideDownTree.right.left.val);
+ assertNull(upsideDownTree.right.right.right);
+ assertNull(upsideDownTree.right.right.left);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/trees/BinaryTreeZigZagLevelOrderTraversal.java b/src/main/java/com/leetcode/trees/BinaryTreeZigZagLevelOrderTraversal.java
new file mode 100644
index 00000000..1a54d952
--- /dev/null
+++ b/src/main/java/com/leetcode/trees/BinaryTreeZigZagLevelOrderTraversal.java
@@ -0,0 +1,100 @@
+package com.leetcode.trees;
+
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Link: https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/
+ * Description:
+ * Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then
+ * right to left for the next level and alternate between).
+ *
+ * For example:
+ * Given binary tree [3,9,20,null,null,15,7],
+ * 3
+ * / \
+ * 9 20
+ * / \
+ * 15 7
+ * return its zigzag level order traversal as:
+ * [
+ * [3],
+ * [20,9],
+ * [15,7]
+ * ]
+ *
+ * @author rampatra
+ * @since 2019-08-11
+ */
+public class BinaryTreeZigZagLevelOrderTraversal {
+
+ /**
+ * Time Complexity:
+ * Space Complexity:
+ * Runtime: 1 ms.
+ *
+ * @param root
+ * @return
+ */
+ public static List> zigzagLevelOrder(TreeNode root) {
+
+ int levelNo = 0;
+ LinkedList currLevel = new LinkedList<>();
+ List> levelOrderTraversal = new LinkedList<>();
+
+ if (root == null) {
+ return levelOrderTraversal;
+ }
+
+ Queue queue = new LinkedList<>();
+ queue.add(root);
+ queue.add(null);
+
+ while (!queue.isEmpty()) {
+
+ TreeNode treeNode = queue.poll();
+
+ if (treeNode == null) {
+ levelOrderTraversal.add(currLevel);
+ currLevel = new LinkedList<>();
+ levelNo++;
+
+ if (queue.size() > 0) {
+ queue.add(null);
+ }
+ } else {
+ if (levelNo % 2 == 0) {
+ currLevel.add(treeNode.val);
+ } else {
+ currLevel.add(0, treeNode.val);
+ }
+ if (treeNode.left != null) queue.add(treeNode.left);
+ if (treeNode.right != null) queue.add(treeNode.right);
+ }
+ }
+
+ return levelOrderTraversal;
+ }
+
+ public static void main(String[] args) {
+ /*
+ Binary Tree
+
+ 1
+ / \
+ 2 3
+ / \
+ 4 5
+ */
+ TreeNode tree = new TreeNode(1);
+ tree.left = new TreeNode(2);
+ tree.right = new TreeNode(3);
+ tree.left.left = new TreeNode(4);
+ tree.left.right = new TreeNode(5);
+
+ assertEquals("[[1], [3, 2], [4, 5]]", zigzagLevelOrder(tree).toString());
+ assertEquals("[]", zigzagLevelOrder(null).toString());
+ }
+}
diff --git a/src/main/java/com/leetcode/trees/ClosestBinarySearchTreeValue.java b/src/main/java/com/leetcode/trees/ClosestBinarySearchTreeValue.java
new file mode 100644
index 00000000..ca6d94b7
--- /dev/null
+++ b/src/main/java/com/leetcode/trees/ClosestBinarySearchTreeValue.java
@@ -0,0 +1,110 @@
+package com.leetcode.trees;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/closest-binary-search-tree-value/
+ * Problem Description:
+ * Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target.
+ *
+ * Note:
+ * - Given target value is a floating point.
+ * - You are guaranteed to have only one unique value in the BST that is closest to the target.
+ *
+ * @author rampatra
+ * @since 2019-07-31
+ */
+public class ClosestBinarySearchTreeValue {
+
+ /**
+ * Runtime: 0 ms.
+ *
+ * @param root
+ * @param target
+ * @return
+ */
+ public static int closestValue(TreeNode root, double target) {
+ if (root == null) return -1;
+
+ return closestValue(root, root, target);
+ }
+
+ private static int closestValue(TreeNode node, TreeNode closestNode, double val) {
+ if (node == null) return closestNode.val;
+
+ if (Math.abs(node.val - val) < Math.abs(closestNode.val - val)) {
+ closestNode = node;
+ }
+
+ if (node.val > val) {
+ return closestValue(node.left, closestNode, val);
+ } else {
+ return closestValue(node.right, closestNode, val);
+ }
+ }
+
+ public static void main(String[] args) {
+
+ /*
+ BST looks like:
+
+ 9
+ / \
+ 7 13
+ / \ \
+ 5 8 20
+ / \
+ 2 6
+ */
+ TreeNode root = new TreeNode(9);
+ root.left = new TreeNode(7);
+ root.right = new TreeNode(13);
+ root.left.left = new TreeNode(5);
+ root.left.right = new TreeNode(8);
+ root.left.left.right = new TreeNode(6);
+ root.left.left.left = new TreeNode(2);
+ root.right.right = new TreeNode(20);
+
+ assertEquals(13, closestValue(root, 15));
+ assertEquals(13, closestValue(root, 13));
+ assertEquals(9, closestValue(root, 9));
+ assertEquals(2, closestValue(root, 2));
+ assertEquals(2, closestValue(root, 1));
+ assertEquals(6, closestValue(root, 6));
+ assertEquals(13, closestValue(root, 11)); // tie b/w 9 and 13
+
+ /*
+ BST looks like:
+
+ 9
+ / \
+ 7 13
+ / \ / \
+ 5 8 13 20
+ */
+ root = new TreeNode(9);
+ root.left = new TreeNode(7);
+ root.right = new TreeNode(13);
+ root.left.left = new TreeNode(5);
+ root.left.right = new TreeNode(8);
+ root.right.left = new TreeNode(13);
+ root.right.right = new TreeNode(20);
+
+ assertEquals(13, closestValue(root, 15));
+
+ /*
+ BST looks like:
+
+ 1500000000
+ /
+ /
+ /
+ 1400000000
+ */
+ root = new TreeNode(1500000000);
+ root.left = new TreeNode(1400000000);
+
+ assertEquals(1400000000, closestValue(root, -1500000000.0));
+ }
+}
diff --git a/src/main/java/com/leetcode/trees/ClosestBinarySearchTreeValueII.java b/src/main/java/com/leetcode/trees/ClosestBinarySearchTreeValueII.java
new file mode 100644
index 00000000..e583723a
--- /dev/null
+++ b/src/main/java/com/leetcode/trees/ClosestBinarySearchTreeValueII.java
@@ -0,0 +1,166 @@
+package com.leetcode.trees;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Stack;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Hard
+ * Problem Link: https://leetcode.com/problems/closest-binary-search-tree-value-ii/
+ * Problem Description:
+ * Given a non-empty binary search tree and a target value, find k values in the BST that are closest to the target.
+ *
+ * Note:
+ * - Given target value is a floating point.
+ * - You may assume k is always valid, that is: k ≤ total nodes.
+ * - You are guaranteed to have only one unique set of k values in the BST that are closest to the target.
+ *
+ * Example:
+ * Input: root = [4,2,5,1,3], target = 3.714286, and k = 2
+ *
+ * 4
+ * / \
+ * 2 5
+ * / \
+ * 1 3
+ *
+ * Output: [4,3]
+ *
+ * Follow up:
+ * Assume that the BST is balanced, could you solve it in less than O(n) runtime (where n = total nodes)?
+ *
+ * @author rampatra
+ * @since 2019-07-31
+ */
+public class ClosestBinarySearchTreeValueII {
+
+
+ /**
+ * The idea is simple. We do the inorder traversal and keep the values less than or equal to target in a stack and
+ * the values greater than target in a queue. And finally, we compare values from both stack and queue and take
+ * whichever is the closest to target value each time.
+ *
+ * Note: We can optimize it even further in terms of space. We can get rid of the stack and queue and just fill up
+ * the result list in the recursive inOrder call. Once the result list is of size k, we can compare and remove the
+ * farthest value and insert the closer value. See {@link ClosestBinarySearchTreeValueII#closestKValuesOptimized(TreeNode, double, int)}.
+ *
+ * @param root
+ * @param target
+ * @param k
+ * @return
+ */
+ public static List closestKValues(TreeNode root, double target, int k) {
+ int count = 0;
+ List closestKValues = new LinkedList<>();
+
+ Stack predecessors = new Stack<>();
+ Queue successors = new LinkedList<>();
+ inOrder(root, predecessors, successors, target, k);
+
+ while (count < k) {
+ if (predecessors.empty()) {
+ closestKValues.add(successors.poll());
+ } else if (successors.isEmpty()) {
+ closestKValues.add(predecessors.pop());
+ } else if (Math.abs(target - predecessors.peek()) < Math.abs(target - successors.peek())) {
+ closestKValues.add(predecessors.pop());
+ } else {
+ closestKValues.add(successors.poll());
+ }
+ count++;
+ }
+
+ return closestKValues;
+ }
+
+ private static void inOrder(TreeNode root, Stack predecessors, Queue successors, double target, int k) {
+ if (root == null || successors.size() == k) return;
+ inOrder(root.left, predecessors, successors, target, k);
+ if (root.val <= target) {
+ predecessors.add(root.val);
+ } else {
+ successors.add(root.val);
+ }
+ inOrder(root.right, predecessors, successors, target, k);
+ }
+
+
+ /**
+ * This approach is similar to the above one but it doesn't use stack or queue.
+ *
+ * @param root
+ * @param target
+ * @param k
+ * @return
+ */
+ public static List closestKValuesOptimized(TreeNode root, double target, int k) {
+ LinkedList closestKValues = new LinkedList<>();
+ inOrder(root, target, k, closestKValues);
+ return closestKValues;
+ }
+
+ private static void inOrder(TreeNode root, double target, int k, LinkedList closestKValues) {
+ if (root == null) return;
+
+ inOrder(root.left, target, k, closestKValues);
+ if (closestKValues.size() == k) {
+ //if size k, add current and remove head if it's closer to target, otherwise return
+ if (Math.abs(target - root.val) < Math.abs(target - closestKValues.peekFirst()))
+ closestKValues.removeFirst();
+ else {
+ return;
+ }
+ }
+ closestKValues.add(root.val);
+ inOrder(root.right, target, k, closestKValues);
+ }
+
+ public static void main(String[] args) {
+
+ /*
+ BST looks like:
+
+ 9
+ / \
+ 7 13
+ / \ \
+ 5 8 20
+ / \
+ 2 6
+ */
+ TreeNode root = new TreeNode(9);
+ root.left = new TreeNode(7);
+ root.right = new TreeNode(13);
+ root.left.left = new TreeNode(5);
+ root.left.right = new TreeNode(8);
+ root.left.left.left = new TreeNode(2);
+ root.left.left.right = new TreeNode(6);
+ root.right.right = new TreeNode(20);
+
+ assertEquals("[9, 8, 7, 6, 5]", closestKValues(root, 8.5, 5).toString());
+ assertEquals("[5, 6, 7, 8, 9]", closestKValuesOptimized(root, 8.5, 5).toString());
+
+ /*
+ BST looks like:
+
+ 9
+ / \
+ 7 13
+ / \ / \
+ 5 8 13 20
+ */
+ root = new TreeNode(9);
+ root.left = new TreeNode(7);
+ root.right = new TreeNode(13);
+ root.left.left = new TreeNode(5);
+ root.right.left = new TreeNode(13);
+ root.left.right = new TreeNode(8);
+ root.right.right = new TreeNode(20);
+
+ assertEquals("[13, 13, 9, 20, 8]", closestKValues(root, 14, 5).toString());
+ assertEquals("[8, 9, 13, 13, 20]", closestKValuesOptimized(root, 14, 5).toString());
+ }
+}
diff --git a/src/main/java/com/leetcode/trees/LeavesOfBinaryTree.java b/src/main/java/com/leetcode/trees/LeavesOfBinaryTree.java
new file mode 100644
index 00000000..6ca15e22
--- /dev/null
+++ b/src/main/java/com/leetcode/trees/LeavesOfBinaryTree.java
@@ -0,0 +1,97 @@
+package com.leetcode.trees;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Level: Medium
+ * Problem Link: https://leetcode.com/problems/find-leaves-of-binary-tree/
+ * Problem Description:
+ * 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.
+ *
+ * Example:
+ * Input: [1,2,3,4,5]
+ *
+ * 1
+ * / \
+ * 2 3
+ * / \
+ * 4 5
+ *
+ * Output: [[4,5,3],[2],[1]]
+ *
+ * Explanation:
+ * 1. Removing the leaves [4,5,3] would result in this tree:
+ * 1
+ * /
+ * 2
+ *
+ * 2. Now removing the leaf [2] would result in this tree:
+ * 1
+ *
+ * 3. Now removing the leaf [1] would result in the empty tree:
+ * []
+ *
+ * @author rampatra
+ * @since 2019-08-01
+ */
+public class LeavesOfBinaryTree {
+
+ /**
+ * THe idea is to perform a DFS and backtrack. While backtracking, check the height of the node and insert
+ * the node into the list indexed by their heights.
+ * Time Complexity:
+ * Space Complexity:
+ * Runtime: 1 ms.
+ *
+ * @param root
+ * @return
+ */
+ public static List> findLeavesOfBinaryTree(TreeNode root) {
+ List> levels = new ArrayList<>();
+ findLeavesOfBinaryTree(root, levels);
+ return levels;
+ }
+
+ private static int findLeavesOfBinaryTree(TreeNode root, List> levels) {
+ if (root == null) return -1;
+
+ int leftHeight = findLeavesOfBinaryTree(root.left, levels);
+ int rightHeight = findLeavesOfBinaryTree(root.right, levels);
+ int height = Math.max(leftHeight, rightHeight) + 1;
+
+ if (height >= levels.size()) {
+ levels.add(height, new ArrayList<>());
+ }
+ levels.get(height).add(root.val);
+
+ return height;
+ }
+
+ public static void main(String[] args) {
+ /*
+ BST looks like:
+
+ 4
+ / \
+ 1 7
+ / \ \
+ 3 8 20
+ / \
+ 2 6
+ */
+ TreeNode root = new TreeNode(4);
+ root.left = new TreeNode(1);
+ root.right = new TreeNode(7);
+ root.left.left = new TreeNode(3);
+ root.left.right = new TreeNode(8);
+ root.left.left.left = new TreeNode(2);
+ root.left.left.right = new TreeNode(6);
+ root.right.right = new TreeNode(20);
+
+ assertEquals("[[2, 6, 8, 20], [3, 7], [1], [4]]", findLeavesOfBinaryTree(root).toString());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/trees/SecondMinNodeInBinaryTree.java b/src/main/java/com/leetcode/trees/SecondMinNodeInBinaryTree.java
new file mode 100644
index 00000000..a8cddf74
--- /dev/null
+++ b/src/main/java/com/leetcode/trees/SecondMinNodeInBinaryTree.java
@@ -0,0 +1,108 @@
+package com.leetcode.trees;
+
+import java.util.Stack;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/second-minimum-node-in-a-binary-tree/
+ * Problem Description:
+ * Given a non-empty special binary tree consisting of nodes with the non-negative value, where each node in this
+ * tree has exactly two or zero sub-node. If the node has two sub-nodes, then this node's value is the smaller value
+ * among its two sub-nodes. More formally, the property root.val = min(root.left.val, root.right.val) always holds.
+ *
+ * Given such a binary tree, you need to output the second minimum value in the set made of all the nodes' value in
+ * the whole tree.
+ *
+ * If no such second minimum value exists, output -1 instead.
+ *
+ * Example 1:
+ * Input:
+ * 2
+ * / \
+ * 2 5
+ * / \
+ * 5 7
+ *
+ * Output: 5
+ * Explanation: The smallest value is 2, the second smallest value is 5.
+ *
+ *
+ * Example 2:
+ * Input:
+ * 2
+ * / \
+ * 2 2
+ *
+ * Output: -1
+ * Explanation: The smallest value is 2, but there isn't any second smallest value.
+ *
+ * @author rampatra
+ * @since 2019-08-03
+ */
+public class SecondMinNodeInBinaryTree {
+
+ /**
+ * Time Complexity: O(n)
+ * Space Complexity: O(n)
+ * Runtime: 1 ms.
+ * @param root
+ * @return
+ */
+ public static int findSecondMinimumValueIterative(TreeNode root) {
+ if (root == null || (root.left == null && root.right == null)) return -1;
+
+ int min = root.val;
+ long secondMin = Long.MAX_VALUE;
+
+ Stack stack = new Stack<>();
+ stack.push(root);
+
+ while (!stack.empty()) {
+ TreeNode node = stack.pop();
+ if (node == null) continue;
+
+ if (node.val > min && node.val < secondMin) {
+ secondMin = node.val;
+ }
+ stack.push(node.left);
+ stack.push(node.right);
+ }
+
+ return secondMin == Long.MAX_VALUE ? -1 : (int) secondMin;
+ }
+
+
+ /**
+ * Time Complexity:
+ * Space Complexity:
+ * Runtime: 0 ms.
+ *
+ * @param root
+ * @return
+ */
+ public static int findSecondMinimumValue(TreeNode root) {
+ // passing a long as secondMin because TreeNode can have Integer.MAX_VALUE as its value
+ long ans = findSecondMinimumValue(root, root.val, Long.MAX_VALUE);
+ return ans == Long.MAX_VALUE ? -1 : (int) ans;
+ }
+
+ private static long findSecondMinimumValue(TreeNode root, int min, long secondMin) {
+ if (root == null) return Long.MAX_VALUE;
+
+ if (root.val > min && root.val < secondMin) {
+ return root.val;
+ } else {
+ return Math.min(findSecondMinimumValue(root.left, min, secondMin),
+ findSecondMinimumValue(root.right, min, secondMin));
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println((int) 2147483647L);
+ System.out.println(Integer.MAX_VALUE);
+ // TODO: A function called buildTree which would take an array like [1,1,3,1,1,3,4,3,1,1,1,3,8,4,8,3,3,1,6,2,1]
+ // and return a Binary Tree
+ //assertEquals(2, findSecondMinimumValue(buildTree(new int[]{1,1,3,1,1,3,4,3,1,1,1,3,8,4,8,3,3,1,6,2,1})));
+ //assertEquals(2147483647, findSecondMinimumValue(buildTree(new int[]{2,2,2147483647})));
+ }
+}
diff --git a/src/main/java/com/leetcode/trees/SerializeDeserializeBinaryTree.java b/src/main/java/com/leetcode/trees/SerializeDeserializeBinaryTree.java
new file mode 100644
index 00000000..690de39d
--- /dev/null
+++ b/src/main/java/com/leetcode/trees/SerializeDeserializeBinaryTree.java
@@ -0,0 +1,179 @@
+package com.leetcode.trees;
+
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+/**
+ * Level: Hard
+ * Link: https://leetcode.com/problems/serialize-and-deserialize-binary-tree/
+ * Description:
+ * Serialization is the process of converting a data structure or object into a sequence of bits so that it can be
+ * stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in
+ * the same or another computer environment.
+ *
+ * Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your
+ * serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized
+ * to a string and this string can be deserialized to the original tree structure.
+ *
+ * Example:
+ *
+ * You may serialize the following tree:
+ *
+ * 1
+ * / \
+ * 2 3
+ * / \
+ * 4 5
+ *
+ * as "[1,2,3,null,null,4,5]"
+ *
+ * Clarification: The above format is the same as how LeetCode serializes a binary tree. You do not necessarily need
+ * to follow this format, so please be creative and come up with different approaches yourself.
+ *
+ * Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms
+ * should be stateless.
+ *
+ * @author rampatra
+ * @since 2019-08-17
+ */
+public class SerializeDeserializeBinaryTree {
+
+ /**
+ * Runtime: 31 ms.
+ *
+ * @param root
+ * @return
+ */
+ public static String serialize(TreeNode root) {
+ if (root == null) {
+ return "[]";
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("[");
+
+ Queue queue = new LinkedList<>();
+ queue.add(root);
+
+ while (!queue.isEmpty()) {
+ TreeNode node = queue.poll();
+
+ if (sb.length() > 1) {
+ sb.append(", ");
+ }
+ if (node == null) {
+ sb.append("null");
+ continue;
+ }
+
+ sb.append(node.val);
+
+ queue.add(node.left);
+ queue.add(node.right);
+ }
+
+ sb.append("]");
+ return removeExtraNulls(sb.toString());
+ }
+
+ private static String removeExtraNulls(String data) {
+ int i = data.length() - 1;
+ while (!(data.charAt(i) >= 48 && data.charAt(i) <= 57)) {
+ i--;
+ }
+ return data.substring(0, i + 1) + "]";
+ }
+
+ /**
+ *
+ * @param data
+ * @return
+ */
+ public static TreeNode deserialize(String data) {
+ data = data.substring(1, data.length() - 1);
+
+ if (data.length() == 0) {
+ return null;
+ }
+
+ String[] values = data.split(", ");
+
+ TreeNode root = new TreeNode(Integer.parseInt(values[0]));
+
+ Queue queue = new LinkedList<>();
+ queue.add(root);
+
+ for (int i = 0; i < values.length && !queue.isEmpty(); i += 2) {
+ TreeNode currNode = queue.poll();
+
+ if (i + 1 < values.length && !values[i + 1].equals("null")) {
+ TreeNode leftNode = new TreeNode(Integer.parseInt(values[i + 1]));
+ currNode.left = leftNode;
+ queue.add(leftNode);
+ }
+
+ if (i + 2 < values.length && !values[i + 2].equals("null")) {
+ TreeNode rightNode = new TreeNode(Integer.parseInt(values[i + 2]));
+ currNode.right = rightNode;
+ queue.add(rightNode);
+ }
+ }
+
+ return root;
+ }
+
+ public static void main(String[] args) {
+ // TODO Convert the print statements to asserts
+
+ System.out.println(serialize(new TreeNode(1)));
+
+ /*
+ Binary Tree
+
+ 1
+ / \
+ 2 3
+ / \
+ 4 5
+ */
+ TreeNode tree = new TreeNode(1);
+ tree.left = new TreeNode(2);
+ tree.right = new TreeNode(3);
+ tree.left.left = new TreeNode(4);
+ tree.left.right = new TreeNode(5);
+
+ System.out.println(serialize(tree));
+
+ System.out.println(serialize(deserialize(serialize(tree))));
+
+ System.out.println(serialize(deserialize(serialize(null))));
+
+ TreeNode tree2 = new TreeNode(1);
+ tree2.right = new TreeNode(2);
+ tree2.right.right = new TreeNode(3);
+ tree2.right.right.right = new TreeNode(4);
+ tree2.right.right.right.right = new TreeNode(5);
+ tree2.right.right.right.right.right = new TreeNode(6);
+ tree2.right.right.right.right.right.right = new TreeNode(7);
+ tree2.right.right.right.right.right.right.right = new TreeNode(8);
+
+ System.out.println(serialize(tree2));
+ System.out.println(serialize(deserialize(serialize(tree2))));
+
+ System.out.println("---");
+
+ System.out.println(serialize(deserialize("[1, 2]")));
+ System.out.println(serialize(deserialize("[1, 2, 3]")));
+ System.out.println(serialize(deserialize("[3, 2, 4, 1]")));
+ System.out.println(serialize(deserialize("[3, 2, 4, 1, 5, 6]")));
+ System.out.println(serialize(deserialize("[1, 2, 3, null, null, 4, 5]")));
+ System.out.println(serialize(deserialize("[5, 2, 3, null, null, 2, 4, 3, 1]")));
+
+ System.out.println(serialize(deserialize("[1, null, 2, null, 3, null, 4, null, 5]")));
+ System.out.println(serialize(deserialize("[1, null, 2, null, 3, null, 4, null, 5, null, 6]")));
+ System.out.println(serialize(deserialize("[1, null, 2, null, 3, null, 4, null, 5, null, 6, null, 7]")));
+ System.out.println(serialize(deserialize("[1, null, 2, null, 3, null, 4, null, 5, null, 6, null, 7, null, 8]")));
+ System.out.println(serialize(deserialize("[1, null, 2, null, 3, null, 4, null, 5, null, 6, null, 7, null, 8, null, 9]")));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/trees/SymmetricTree.java b/src/main/java/com/leetcode/trees/SymmetricTree.java
new file mode 100644
index 00000000..093d9a6f
--- /dev/null
+++ b/src/main/java/com/leetcode/trees/SymmetricTree.java
@@ -0,0 +1,117 @@
+package com.leetcode.trees;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Level: Easy
+ * Problem Link: https://leetcode.com/problems/symmetric-tree/
+ * Problem Description:
+ * Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
+ *
+ * For example, this binary tree [1,2,2,3,4,4,3] is symmetric:
+ *
+ * 1
+ * / \
+ * 2 2
+ * / \ / \
+ * 3 4 4 3
+ *
+ *
+ * But the following [1,2,2,null,3,null,3] is not:
+ *
+ * 1
+ * / \
+ * 2 2
+ * \ \
+ * 3 3
+ *
+ *
+ * Note:
+ * Bonus points if you could solve it both recursively and iteratively.
+ *
+ * @author rampatra
+ * @since 2019-07-25
+ */
+public class SymmetricTree {
+
+ /**
+ * Time Complexity: O(n) Because we traverse the entire input tree once, the total run time is O(n), where n is
+ * the total number of nodes in the tree.
+ * Space Complexity: O(n) The number of recursive calls is bound by the height of the tree. In the worst case, the
+ * tree is linear and the height is in O(n). Therefore, space complexity due to recursive calls on the stack is
+ * O(n) in the worst case.
+ * Runtime: 0 ms.
+ *
+ * @param root
+ * @return
+ */
+ public static boolean isSymmetric(TreeNode root) {
+ if (root == null) {
+ return true;
+ }
+
+ return isSymmetric(root.left, root.right);
+ }
+
+ private static boolean isSymmetric(TreeNode leftRoot, TreeNode rightRoot) {
+ if (leftRoot == null && rightRoot == null) {
+ return true;
+ } else if (leftRoot == null || rightRoot == null) {
+ return false;
+ }
+
+ return isSymmetric(leftRoot.left, rightRoot.right) && isSymmetric(leftRoot.right, rightRoot.left) && leftRoot.val == rightRoot.val;
+ }
+
+ /**
+ * Time Complexity: O(n) Because we traverse the entire input tree once, the total run time is O(n), where n is the
+ * total number of nodes in the tree.
+ * Space Complexity: There is additional space required for the search queue. In the worst case, we have to
+ * insert O(n) nodes in the queue. Therefore, space complexity is O(n).
+ * Runtime: 1 ms.
+ *
+ * @param root
+ * @return
+ */
+ public static boolean isSymmetricIterative(TreeNode root) {
+ if (root == null || (root.left == null && root.right == null)) return true;
+ if (root.left == null || root.right == null) return false;
+
+ Queue queue = new LinkedList<>();
+ queue.add(root.left);
+ queue.add(root.right);
+
+ while (!queue.isEmpty()) {
+ TreeNode t1 = queue.poll();
+ TreeNode t2 = queue.poll();
+
+ if (t1 == null && t2 == null) continue;
+ if (t1 == null || t2 == null) return false;
+ if (t1.val != t2.val) return false;
+
+ // enqueue left and then right child of t1 but do the opposite for t2
+ queue.add(t1.left);
+ queue.add(t2.right);
+ queue.add(t1.right);
+ queue.add(t2.left);
+ }
+
+ return true;
+ }
+
+ public static void main(String[] args) {
+ TreeNode root = new TreeNode(1);
+ root.left = new TreeNode(2);
+ root.right = new TreeNode(2);
+ root.left.left = new TreeNode(4);
+ root.left.right = new TreeNode(3);
+ root.right.left = new TreeNode(3);
+ root.right.right = new TreeNode(4);
+
+ assertTrue(isSymmetric(root));
+ assertTrue(isSymmetricIterative(root));
+ }
+}
diff --git a/src/main/java/com/leetcode/trees/TreeNode.java b/src/main/java/com/leetcode/trees/TreeNode.java
new file mode 100644
index 00000000..4c4c2569
--- /dev/null
+++ b/src/main/java/com/leetcode/trees/TreeNode.java
@@ -0,0 +1,21 @@
+package com.leetcode.trees;
+
+/**
+ * @author rampatra
+ * @since 2019-07-25
+ */
+public class TreeNode {
+
+ int val;
+ TreeNode left;
+ TreeNode right;
+
+ public TreeNode(int val) {
+ this.val = val;
+ }
+
+ @Override
+ public String toString() {
+ return val + "";
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/leetcode/trie/LongestWord.java b/src/main/java/com/leetcode/trie/LongestWord.java
new file mode 100644
index 00000000..155ea295
--- /dev/null
+++ b/src/main/java/com/leetcode/trie/LongestWord.java
@@ -0,0 +1,78 @@
+package com.leetcode.trie;
+
+import java.util.HashMap;
+import java.util.Stack;
+
+/**
+ * Level: Easy
+ * Problem: https://leetcode.com/problems/longest-word-in-dictionary/
+ *
+ * @author rampatra
+ * @since 2019-04-10
+ */
+public class LongestWord {
+
+ private class TrieNode {
+ char ch;
+ HashMap children = new HashMap<>();
+ String completeWord; // to mark a complete word in the trie data structure
+
+ TrieNode(char ch) {
+ this.ch = ch;
+ }
+ }
+
+ private TrieNode root = new TrieNode('0');
+
+ /**
+ * Inserts {@code data} in trie.
+ *
+ * @param str
+ */
+ public void insert(String str) {
+ char c;
+ TrieNode curr = root;
+
+ for (int i = 0; i < str.length(); i++) {
+ c = str.charAt(i);
+ curr.children.putIfAbsent(c, new TrieNode(c));
+ curr = curr.children.get(c);
+ }
+
+ curr.completeWord = str;
+ }
+
+ public String longestWord(String[] words) {
+ for (int i = 0; i < words.length; i++) {
+ insert(words[i]);
+ }
+
+ return longestWord();
+ }
+
+ private String longestWord() {
+ String longestWord = "";
+ TrieNode curr;
+ Stack stack = new Stack<>();
+ stack.addAll(root.children.values());
+
+ while (!stack.empty()) {
+ curr = stack.pop();
+ if (curr.completeWord != null) {
+ if (curr.completeWord.length() > longestWord.length() ||
+ (curr.completeWord.length() == longestWord.length() &&
+ curr.completeWord.compareTo(longestWord) < 0)) {
+ longestWord = curr.completeWord;
+ }
+ stack.addAll(curr.children.values());
+ }
+ }
+ return longestWord;
+ }
+
+ public static void main(String[] args) {
+ LongestWord longestWord = new LongestWord();
+ System.out.println(longestWord.longestWord(new String[]{"w", "wo", "wor", "worl", "world"}));
+ System.out.println(longestWord.longestWord(new String[]{"a", "banana", "app", "appl", "ap", "apply", "apple"}));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/rampatra/Main.java b/src/main/java/com/rampatra/Main.java
index 8702669f..9306b1a2 100644
--- a/src/main/java/com/rampatra/Main.java
+++ b/src/main/java/com/rampatra/Main.java
@@ -1,13 +1,13 @@
package com.rampatra;
-import com.rampatra.common.CircularSingleLinkedList;
-import com.rampatra.common.DoubleLinkedList;
-import com.rampatra.common.LinkedList;
-import com.rampatra.common.LinkedQueue;
-import com.rampatra.common.LinkedStack;
-import com.rampatra.common.Queue;
-import com.rampatra.common.SingleLinkedList;
-import com.rampatra.common.Stack;
+import com.rampatra.base.CircularSingleLinkedList;
+import com.rampatra.base.DoubleLinkedList;
+import com.rampatra.base.LinkedList;
+import com.rampatra.base.LinkedQueue;
+import com.rampatra.base.LinkedStack;
+import com.rampatra.base.Queue;
+import com.rampatra.base.SingleLinkedList;
+import com.rampatra.base.Stack;
import java.util.Scanner;
diff --git a/src/main/java/com/rampatra/arrays/ArrangeNosToFormBiggestNo.java b/src/main/java/com/rampatra/arrays/ArrangeNosToFormBiggestNo.java
index be64b7e7..ce069e34 100644
--- a/src/main/java/com/rampatra/arrays/ArrangeNosToFormBiggestNo.java
+++ b/src/main/java/com/rampatra/arrays/ArrangeNosToFormBiggestNo.java
@@ -1,47 +1,50 @@
package com.rampatra.arrays;
import java.util.Arrays;
-import java.util.Comparator;
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 11/1/15
- * @time: 8:53 PM
+ * @author rampatra
+ * @since 11/1/15
*/
public class ArrangeNosToFormBiggestNo {
/**
- * Sorts no.s in array {@param a} such that if you form a number {@code n}
+ * Sorts {@code numbers} such that if you form a number {@code n}
* by concatenating digits in order a[0]....a[size], it results being the
* largest number possible.
*
* For example,
* I/P: {54, 546, 548, 60}
- * O/P: {60, 548, 546, 54} i.e, 6054854654
+ * O/P: {60, 548, 546, 54}, i.e, 6054854654
*
* I/P: {1, 34, 3, 98, 9, 76, 45, 4}
- * O/P: {9, 98, 76, 45, 4, 34, 3, 1} i.e, 998764543431
+ * O/P: {9, 98, 76, 45, 4, 34, 3, 1}, i.e, 998764543431
*
- * @param a
- * @return
+ * @param numbers input integer array
+ * @return integer array where if you concatenate all its elements, you will get the largest number
*/
- public static Integer[] arrangeArrayOfNosToFormBiggestNo(Integer[] a) {
+ private static Integer[] arrangeArrayOfNosToFormBiggestNo(Integer[] numbers) {
- Arrays.sort(a, new Comparator() {
- @Override
- public int compare(Integer o1, Integer o2) {
- return Integer.parseInt(o1 + "" + o2) > Integer.parseInt(o2 + "" + o1) ? -1 : 1;
- }
- });
+ Arrays.sort(numbers, (o1, o2) -> Integer.parseInt(o1 + "" + o2) >= Integer.parseInt(o2 + "" + o1) ? -1 : 1);
- return a;
+ /*
+ Use the below version (without lambda) if you use JDK < 8
+
+ Arrays.sort(numbers, new Comparator() {
+ @Override
+ public int compare(Integer o1, Integer o2) {
+ return Integer.parseInt(o1 + "" + o2) >= Integer.parseInt(o2 + "" + o1) ? -1 : 1;
+ }
+ });
+ */
+ return numbers;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(arrangeArrayOfNosToFormBiggestNo(new Integer[]{45, 567, 12, 1})));
System.out.println(Arrays.toString(arrangeArrayOfNosToFormBiggestNo(new Integer[]{54, 546, 548, 60})));
System.out.println(Arrays.toString(arrangeArrayOfNosToFormBiggestNo(new Integer[]{1, 34, 3, 98, 9, 76, 45, 4})));
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/rampatra/arrays/BooleanMatrix.java b/src/main/java/com/rampatra/arrays/BooleanMatrix.java
index 58aa36ac..04ee2d88 100644
--- a/src/main/java/com/rampatra/arrays/BooleanMatrix.java
+++ b/src/main/java/com/rampatra/arrays/BooleanMatrix.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 9/11/15
+ * @author rampatra
+ * @since 9/11/15
* @time: 3:28 PM
* @see: http://www.geeksforgeeks.org/a-boolean-matrix-question/
*/
@@ -67,7 +67,7 @@ private static void print2DMatrix(int[][] a) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
int[][] ar = new int[][]{{1, 0, 0, 1}, {0, 0, 1, 0}, {0, 0, 0, 0}};
print2DMatrix(ar);
modifyBooleanMatrix(ar);
diff --git a/src/main/java/com/rampatra/arrays/CelebrityProblem.java b/src/main/java/com/rampatra/arrays/CelebrityProblem.java
index 44c03c1f..8b7278ea 100644
--- a/src/main/java/com/rampatra/arrays/CelebrityProblem.java
+++ b/src/main/java/com/rampatra/arrays/CelebrityProblem.java
@@ -1,13 +1,13 @@
package com.rampatra.arrays;
-import com.rampatra.common.LinkedStack;
-import com.rampatra.common.Stack;
+import com.rampatra.base.LinkedStack;
+import com.rampatra.base.Stack;
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 10/2/15
+ * @author rampatra
+ * @since 10/2/15
* @time: 10:48 PM
*
* In a party of N people, only one person is known to everyone. Such a person may be present in the party, if yes,
@@ -78,7 +78,7 @@ public static int findCelebrity(int[][] peoples) {
return firstPerson;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(findCelebrity(new int[][]{{0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 0, 0}, {0, 0, 1, 0}}));
System.out.println(findCelebrity(new int[][]{{0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}}));
}
diff --git a/src/main/java/com/rampatra/arrays/ConsecutiveElements.java b/src/main/java/com/rampatra/arrays/ConsecutiveElements.java
index aa96e014..f8dc151e 100644
--- a/src/main/java/com/rampatra/arrays/ConsecutiveElements.java
+++ b/src/main/java/com/rampatra/arrays/ConsecutiveElements.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/28/15
+ * @author rampatra
+ * @since 8/28/15
* @time: 10:32 AM
*/
public class ConsecutiveElements {
@@ -99,7 +99,7 @@ public static boolean areConsecutiveElementsInO1Space(int[] a) {
return true;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(areConsecutiveElements(new int[]{5, 4, 3, 2, 1}));
System.out.println(areConsecutiveElements(new int[]{67, 68, 69, 72, 70, 71}));
System.out.println(areConsecutiveElements(new int[]{67, 68, 69, 72, 70, 71, 70}));
diff --git a/src/main/java/com/rampatra/arrays/CountDivisors.java b/src/main/java/com/rampatra/arrays/CountDivisors.java
index b9344abd..3023dc3c 100644
--- a/src/main/java/com/rampatra/arrays/CountDivisors.java
+++ b/src/main/java/com/rampatra/arrays/CountDivisors.java
@@ -1,20 +1,21 @@
package com.rampatra.arrays;
/**
- * Created by ramswaroop on 31/05/2016.
+ * @author rampatra
+ * @since 31/05/2016
*/
public class CountDivisors {
/**
- * Counts the number of integers in the range {@param begin} and
- * {@param end} that are divisible by {@param n}.
+ * Counts the number of integers in the range {@code begin}
+ * and {@code end} that are divisible by {@code n}.
*
* @param begin
* @param end
* @param n
* @return
*/
- public static int countDivisorsInRange(int begin, int end, int n) {
+ private static int countDivisorsInRange(int begin, int end, int n) {
int b = end / n + 1; // From 0 to end the integers divisible by n
int a = begin / n + 1; // From 0 to begin the integers divisible by n
@@ -24,7 +25,11 @@ public static int countDivisorsInRange(int begin, int end, int n) {
return b - a; // return integers in range
}
- public static void main(String[] a) {
- countDivisorsInRange(0, 2000000000, 5);
+ public static void main(String[] args) {
+ System.out.println(countDivisorsInRange(0, 0, 5));
+ System.out.println(countDivisorsInRange(1, 1, 5));
+ System.out.println(countDivisorsInRange(0, 1, 5));
+ System.out.println(countDivisorsInRange(0, 10, 5));
+ System.out.println(countDivisorsInRange(0, 2000000000, 5));
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/rampatra/arrays/CountSmallerElementsOnRHS.java b/src/main/java/com/rampatra/arrays/CountSmallerElementsOnRHS.java
index edec6f4c..413234ec 100644
--- a/src/main/java/com/rampatra/arrays/CountSmallerElementsOnRHS.java
+++ b/src/main/java/com/rampatra/arrays/CountSmallerElementsOnRHS.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 9/19/15
+ * @author rampatra
+ * @since 9/19/15
* @time: 11:33 PM
*/
public class CountSmallerElementsOnRHS {
@@ -16,7 +16,7 @@ public static int[] getSmallerElementsCountOnRHSNaive(int[] a) {
return null;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(getSmallerElementsCountOnRHSNaive(new int[]{12, 1, 2, 3, 0, 11, 4})));
System.out.println(Arrays.toString(getSmallerElementsCountOnRHSNaive(new int[]{5, 4, 3, 2, 1})));
System.out.println(Arrays.toString(getSmallerElementsCountOnRHSNaive(new int[]{1, 2, 3, 4, 5})));
diff --git a/src/main/java/com/rampatra/arrays/DistinctPairs.java b/src/main/java/com/rampatra/arrays/DistinctPairs.java
new file mode 100644
index 00000000..3ba861ab
--- /dev/null
+++ b/src/main/java/com/rampatra/arrays/DistinctPairs.java
@@ -0,0 +1,50 @@
+package com.rampatra.arrays;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Level: Easy
+ * Problem Description:
+ * Given an array and a target sum, return the number of distinct pairs whose sum is equal to the target sum.
+ *
+ * For Example, given an array [1, 2, 3, 6, 7, 8, 9, 1] and a target sum of 10,
+ * the 7 pairs, i.e, (1, 9), (2, 8), (3, 7), (8, 2), (9, 1), (9, 1), and (1, 9) all sum to 10 but there are only
+ * three distinct pairs, i.e, (1, 9), (2, 8), and (3, 7) so the answer would be 3.
+ *
+ * @author rampatra
+ * @since 2019-06-03
+ */
+public class DistinctPairs {
+
+ /**
+ * Time complexity: O(n), n = size of the array
+ * Space complexity: O(n)
+ *
+ * @param arr
+ * @param targetSum
+ * @return
+ */
+ private static int numberOfDistinctPairs(int[] arr, int targetSum) {
+ Set numSet = new HashSet<>();
+ Set> pairSet = new HashSet<>();
+
+ for (int i = 0; i < arr.length; i++) {
+ if (numSet.contains(targetSum - arr[i])) {
+ Set pair = new HashSet<>();
+ pair.add(arr[i]);
+ pair.add(targetSum - arr[i]);
+ pairSet.add(pair);
+ }
+ numSet.add(arr[i]);
+ }
+
+ return pairSet.size();
+ }
+
+ public static void main(String[] args) {
+ System.out.println(numberOfDistinctPairs(new int[]{1, 2, 3, 6, 7, 8, 9, 1}, 1));
+ System.out.println(numberOfDistinctPairs(new int[]{1, 2, 3, 6, 7, 8, 9, 1}, 2));
+ System.out.println(numberOfDistinctPairs(new int[]{1, 2, 3, 6, 7, 8, 9, 1}, 10));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/rampatra/arrays/DuplicatesInArray.java b/src/main/java/com/rampatra/arrays/DuplicatesInArray.java
index 44655739..5cb9cbe8 100644
--- a/src/main/java/com/rampatra/arrays/DuplicatesInArray.java
+++ b/src/main/java/com/rampatra/arrays/DuplicatesInArray.java
@@ -5,16 +5,15 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/21/15
- * @time: 9:41 AM
+ * @author rampatra
+ * @since 8/21/15
*/
public class DuplicatesInArray {
/**
* Given an array of n elements which contains elements from 0 to n-1, with any of
* these numbers appearing any number of times. Find these repeating numbers in O(n)
- * and using only constant memory space.
+ * time complexity.
*
* For example, let n be 7 and array be {1, 2, 3, 1, 3, 6, 6}, the answer should be
* 1, 3 and 6.
@@ -43,7 +42,7 @@ public static int[] findDuplicatesInArray(int[] a) {
return duplicates;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(findDuplicatesInArray(new int[]{1, 1, 2, 3, 1, 3, 6, 6})));
// doesn't work if 0 is present in array (as -0 makes no sense but we can modify the algorithm to handle 0)
System.out.println(Arrays.toString(findDuplicatesInArray(new int[]{1, 0, 1, 2, 3, 1, 3, 6, 6})));
diff --git a/src/main/java/com/rampatra/arrays/DuplicatesInArrayWithinKDistance.java b/src/main/java/com/rampatra/arrays/DuplicatesInArrayWithinKDistance.java
index 792aeafc..2117d712 100644
--- a/src/main/java/com/rampatra/arrays/DuplicatesInArrayWithinKDistance.java
+++ b/src/main/java/com/rampatra/arrays/DuplicatesInArrayWithinKDistance.java
@@ -6,14 +6,13 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 10/18/15
- * @time: 8:40 PM
+ * @author rampatra
+ * @since 10/18/15
*/
public class DuplicatesInArrayWithinKDistance {
/**
- * Finds duplicates in an unsorted array {@param a} which are
+ * Finds duplicates in an unsorted array {@code a} which are
* only k distance apart from each other.
*
* @param a
@@ -41,7 +40,7 @@ public static int[] findDuplicatesInArrayWithinKDistance(int[] a, int k) {
return Arrays.copyOf(duplicates, index);
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(findDuplicatesInArrayWithinKDistance(new int[]{1, 2, 8, 1, 3, 4, 5, 6, 6, 7}, 3)));
}
}
diff --git a/src/main/java/com/rampatra/arrays/EqualProbabilityRandomNoGenerator.java b/src/main/java/com/rampatra/arrays/EqualProbabilityRandomNoGenerator.java
index 77d3ddb4..c26d8694 100644
--- a/src/main/java/com/rampatra/arrays/EqualProbabilityRandomNoGenerator.java
+++ b/src/main/java/com/rampatra/arrays/EqualProbabilityRandomNoGenerator.java
@@ -9,8 +9,8 @@
* which uses f(n) to generate non repeating random numbers from
* {@code 0} (inclusive) to {@code n} (exclusive)?
*
- * @author: ramswaroop
- * @date: 8/13/15
+ * @author rampatra
+ * @since 8/13/15
* @time: 1:41 PM
*/
public class EqualProbabilityRandomNoGenerator {
@@ -35,7 +35,7 @@ public static int f(int n) {
return new Random().nextInt(n);
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("How many random numbers you would like to generate?");
diff --git a/src/main/java/com/rampatra/arrays/EquilibriumIndex.java b/src/main/java/com/rampatra/arrays/EquilibriumIndex.java
index 0e27bf19..c943c603 100644
--- a/src/main/java/com/rampatra/arrays/EquilibriumIndex.java
+++ b/src/main/java/com/rampatra/arrays/EquilibriumIndex.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/22/15
+ * @author rampatra
+ * @since 8/22/15
* @time: 11:56 AM
*/
public class EquilibriumIndex {
@@ -44,7 +44,7 @@ public static int getEquilibriumIndex(int[] a) {
return -1;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getEquilibriumIndex(new int[]{-7, 1, 5, 2, -4, 3, 0}));
System.out.println(getEquilibriumIndex(new int[]{-7, 1, 5, 0, 0, 0, 0, 1, 2, -4, 1, 3, 0}));
System.out.println(getEquilibriumIndex(new int[]{4, 5, 2, 1, 6, 7, 8, 0, 1}));
diff --git a/src/main/java/com/rampatra/arrays/FixedPoint.java b/src/main/java/com/rampatra/arrays/FixedPoint.java
index 8407ded1..99e8a333 100644
--- a/src/main/java/com/rampatra/arrays/FixedPoint.java
+++ b/src/main/java/com/rampatra/arrays/FixedPoint.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 9/8/15
+ * @author rampatra
+ * @since 9/8/15
* @time: 11:34 PM
*/
public class FixedPoint {
@@ -33,7 +33,7 @@ public static int findFixedPoint(int[] a) {
return -1;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(findFixedPoint(new int[]{-10, -5, 0, 3, 7}));
System.out.println(findFixedPoint(new int[]{0, 2, 5, 8, 17}));
System.out.println(findFixedPoint(new int[]{-10, -5, 3, 4, 7, 9}));
diff --git a/src/main/java/com/rampatra/arrays/FlattenArray.java b/src/main/java/com/rampatra/arrays/FlattenArray.java
new file mode 100644
index 00000000..e68c250b
--- /dev/null
+++ b/src/main/java/com/rampatra/arrays/FlattenArray.java
@@ -0,0 +1,39 @@
+package com.rampatra.arrays;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FlattenArray {
+
+ /**
+ * Given a nested array like [[1, 2], 3, [4]], return an array like [1, 2, 3, 4, 5].
+ *
+ * @param nestedArray an Object array
+ * @return a list of all elements in the nestedArray but all at the same level
+ */
+ private static List flattenArray(Object[] nestedArray) {
+ if (nestedArray == null || nestedArray.length == 0) return new ArrayList<>();
+
+ List flattenedArray = new ArrayList<>();
+
+ for (Object obj : nestedArray) {
+ if (obj instanceof Object[]) {
+ flattenedArray.addAll(flattenArray((Object[]) obj));
+ } else if (obj instanceof Integer) {
+ flattenedArray.add((Integer) obj);
+ }
+ }
+
+ return flattenedArray;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(flattenArray(null));
+ System.out.println(flattenArray(new Object[]{null}));
+ System.out.println(flattenArray(new Object[]{new Object[]{}}));
+ System.out.println(flattenArray(new Object[]{new Object[]{1, 2}}));
+ System.out.println(flattenArray(new Object[]{1, 2, new Object[]{4, 5}, 6}));
+ System.out.println(flattenArray(new Object[]{new Object[]{4, 5}, 1, 2, 6}));
+ System.out.println(flattenArray(new Object[]{1, 2, 6, new Object[]{4, 5}}));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/rampatra/arrays/IntersectionAndUnionOf2SortedArrays.java b/src/main/java/com/rampatra/arrays/IntersectionAndUnionOf2SortedArrays.java
index a87a2e01..595e85a5 100644
--- a/src/main/java/com/rampatra/arrays/IntersectionAndUnionOf2SortedArrays.java
+++ b/src/main/java/com/rampatra/arrays/IntersectionAndUnionOf2SortedArrays.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/13/15
+ * @author rampatra
+ * @since 8/13/15
* @time: 3:56 PM
*/
public class IntersectionAndUnionOf2SortedArrays {
@@ -50,7 +50,7 @@ public static int[][] getIntersectionAndUnionOf2SortedArrays(int[] a, int[] b) {
return new int[][]{intersection, union};
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
int[] a1 = new int[]{2, 3, 4, 5, 6, 7, 8};
int[] a2 = new int[]{6, 7, 8, 10, 12, 14, 16};
int[][] result = getIntersectionAndUnionOf2SortedArrays(a1, a2);
diff --git a/src/main/java/com/rampatra/arrays/InversionsInArray.java b/src/main/java/com/rampatra/arrays/InversionsInArray.java
index 6aafe9e4..1677764d 100644
--- a/src/main/java/com/rampatra/arrays/InversionsInArray.java
+++ b/src/main/java/com/rampatra/arrays/InversionsInArray.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/29/15
+ * @author rampatra
+ * @since 7/29/15
* @time: 8:37 PM
*/
public class InversionsInArray {
@@ -95,7 +95,7 @@ public static int[] merge(int[] a, int[] b) {
return sortedArray;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getInversionCountNaiveApproach(new int[]{2, 4, 1, 3, 5}));
System.out.println(getInversionCount(new int[]{2, 4, 1, 3, 5}));
}
diff --git a/src/main/java/com/rampatra/arrays/KLargestElements.java b/src/main/java/com/rampatra/arrays/KLargestElements.java
index c50894d0..87546e7d 100644
--- a/src/main/java/com/rampatra/arrays/KLargestElements.java
+++ b/src/main/java/com/rampatra/arrays/KLargestElements.java
@@ -1,14 +1,14 @@
package com.rampatra.arrays;
-import com.rampatra.common.MinHeap;
+import com.rampatra.base.MinHeap;
import java.util.Arrays;
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/3/15
+ * @author rampatra
+ * @since 8/3/15
* @time: 3:47 PM
*/
public class KLargestElements {
@@ -49,7 +49,7 @@ public static int[] getKLargestElements(int[] a, int k) {
return minHeap.getHeap();
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(getKLargestElements(new int[]{2, 3, 4, 1, 5, 7, 9}, 3)));
}
}
diff --git a/src/main/java/com/rampatra/arrays/KthLargestElement.java b/src/main/java/com/rampatra/arrays/KthLargestElement.java
index b22f32ed..65ca77c7 100644
--- a/src/main/java/com/rampatra/arrays/KthLargestElement.java
+++ b/src/main/java/com/rampatra/arrays/KthLargestElement.java
@@ -1,15 +1,15 @@
package com.rampatra.arrays;
import com.rampatra.sorting.MergeSort;
-import com.rampatra.common.MaxHeap;
+import com.rampatra.base.MaxHeap;
import java.util.Arrays;
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/1/15
+ * @author rampatra
+ * @since 8/1/15
* @time: 11:26 PM
*/
public class KthLargestElement {
@@ -52,7 +52,7 @@ public static int getKthLargestElement(int[] a, int k) {
return maxHeap.findMax();
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
int[] ar = new int[]{2, 4, 5, 7, 1, 8, 9};
System.out.println(Arrays.toString(ar));
System.out.println(getKthLargestElementNaive(ar, 3));
diff --git a/src/main/java/com/rampatra/arrays/LargestProductContiguousSubArray.java b/src/main/java/com/rampatra/arrays/LargestProductContiguousSubArray.java
index a6b2cc4e..c7afb19b 100644
--- a/src/main/java/com/rampatra/arrays/LargestProductContiguousSubArray.java
+++ b/src/main/java/com/rampatra/arrays/LargestProductContiguousSubArray.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 5/28/15
+ * @author rampatra
+ * @since 5/28/15
* @time: 12:44 PM
*/
public class LargestProductContiguousSubArray {
@@ -17,7 +17,7 @@ public static int getLargestProductContiguousSubArray(int[] a) {
return 0;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getLargestProductContiguousSubArray(new int[]{-2, 1, -3, 4, 5, -1, 4}));
System.out.println(getLargestProductContiguousSubArray(new int[]{6, -3, -10, 0, 2}));
}
diff --git a/src/main/java/com/rampatra/arrays/LargestSumContiguousSubArray.java b/src/main/java/com/rampatra/arrays/LargestSumContiguousSubArray.java
index 0b61d16b..8b34d9ef 100644
--- a/src/main/java/com/rampatra/arrays/LargestSumContiguousSubArray.java
+++ b/src/main/java/com/rampatra/arrays/LargestSumContiguousSubArray.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 5/28/15
+ * @author rampatra
+ * @since 5/28/15
* @time: 12:44 PM
*/
public class LargestSumContiguousSubArray {
@@ -47,7 +47,7 @@ public static int getLargestSumOfContiguousSubArrayWhenAllNosNegative(int[] a) {
return maxSum;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getLargestSumOfContiguousSubArray(new int[]{-2, 1, -3, 4, 5, -1, 4}));
System.out.println(getLargestSumOfContiguousSubArray(new int[]{2, -1, -3, 4, -5, 1, 4}));
// kadane's algorithm doesn't work if all no.s are -ve
diff --git a/src/main/java/com/rampatra/arrays/LeadersInArray.java b/src/main/java/com/rampatra/arrays/LeadersInArray.java
index 00f9066f..c2075751 100644
--- a/src/main/java/com/rampatra/arrays/LeadersInArray.java
+++ b/src/main/java/com/rampatra/arrays/LeadersInArray.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/29/15
+ * @author rampatra
+ * @since 7/29/15
* @time: 12:06 PM
*/
public class LeadersInArray {
@@ -37,7 +37,7 @@ public static int[] getAllLeaders(int[] a) {
return Arrays.copyOfRange(leaders, 0, j + 1);
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(getAllLeaders(new int[]{16, 17, 4, 3, 5, 2})));
System.out.println(Arrays.toString(getAllLeaders(new int[]{16, 1, 4, 3, 5, 12})));
System.out.println(Arrays.toString(getAllLeaders(new int[]{16, 15, 14, 13, 12, 10})));
diff --git a/src/main/java/com/rampatra/arrays/LongestBitonicSubArray.java b/src/main/java/com/rampatra/arrays/LongestBitonicSubArray.java
index 393d25d8..dc3caafb 100644
--- a/src/main/java/com/rampatra/arrays/LongestBitonicSubArray.java
+++ b/src/main/java/com/rampatra/arrays/LongestBitonicSubArray.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 9/18/15
+ * @author rampatra
+ * @since 9/18/15
* @time: 5:10 PM
*/
public class LongestBitonicSubArray {
@@ -54,7 +54,7 @@ public static int getLongestBitonicSubArrayLength(int[] a) {
return bitonicLength;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getLongestBitonicSubArrayLength(new int[]{1, 2, 5, 4, 3}));
System.out.println(getLongestBitonicSubArrayLength(new int[]{12, 4, 78, 90, 45, 23}));
System.out.println(getLongestBitonicSubArrayLength(new int[]{10, 20, 30, 40}));
diff --git a/src/main/java/com/rampatra/arrays/LongestConsecutiveSubsequence.java b/src/main/java/com/rampatra/arrays/LongestConsecutiveSubsequence.java
index a8f41c87..8e6a99f8 100644
--- a/src/main/java/com/rampatra/arrays/LongestConsecutiveSubsequence.java
+++ b/src/main/java/com/rampatra/arrays/LongestConsecutiveSubsequence.java
@@ -10,9 +10,8 @@
public class LongestConsecutiveSubsequence {
/**
- * Given an array of integers, find the length of the longest sub-sequence such that
- * elements in the subsequence are consecutive integers, the consecutive numbers can
- * be in any order.
+ * Given an array of distinct integers, find the length of the longest sub-sequence such that
+ * elements in the subsequence are consecutive integers, the consecutive numbers can be in any order.
*
* Examples:
* Input: arr[] = {1, 9, 3, 10, 4, 20, 2};
@@ -24,14 +23,14 @@ public class LongestConsecutiveSubsequence {
* Output: 5
* The subsequence {36, 35, 33, 34, 32} is the longest subsequence
* of consecutive elements.
- *
+ *
* NOTE: You can also sort this array and check for consecutive elements. You can take this approach if interviewer
* asks to solve with no additional space but do bear in mind that some sorting algorithms do require extra space.
*
- * @param arr unsorted array of integers
+ * @param arr unsorted array of non-repeating integers
* @return the length of the longest consecutive subsequence
*/
- private static int findLongestConsecutiveSubsequence(int[] arr) {
+ private static int findLengthOfLongestConsecutiveSubsequence(int[] arr) {
int longestSubseqCount = 0;
int subseqCount;
int currElem;
@@ -67,11 +66,15 @@ private static int findLongestConsecutiveSubsequence(int[] arr) {
}
public static void main(String[] args) {
- System.out.println("{1, 9, 3, 10, 4, 20, 2}: " + findLongestConsecutiveSubsequence(new int[]{1, 9, 3, 10, 4, 20, 2}));
+
+ System.out.println("{1, 9, 3, 10, 4, 20, 2}: " +
+ findLengthOfLongestConsecutiveSubsequence(new int[]{1, 9, 3, 10, 4, 20, 2}));
System.out.println("{36, 41, 56, 35, 44, 33, 34, 92, 43, 32, 42}: " +
- findLongestConsecutiveSubsequence(new int[]{36, 41, 56, 35, 44, 33, 34, 92, 43, 32, 42}));
- System.out.println("{1}: " + findLongestConsecutiveSubsequence(new int[]{1}));
- System.out.println("{}: " + findLongestConsecutiveSubsequence(new int[]{}));
- System.out.println("{1,5,8,3}: " + findLongestConsecutiveSubsequence(new int[]{1, 5, 8, 3}));
+ findLengthOfLongestConsecutiveSubsequence(new int[]{36, 41, 56, 35, 44, 33, 34, 92, 43, 32, 42}));
+ System.out.println("{1,5,8,3}: " + findLengthOfLongestConsecutiveSubsequence(new int[]{1, 5, 8, 3}));
+
+ // corner cases
+ System.out.println("{1}: " + findLengthOfLongestConsecutiveSubsequence(new int[]{1}));
+ System.out.println("{}: " + findLengthOfLongestConsecutiveSubsequence(new int[]{}));
}
}
diff --git a/src/main/java/com/rampatra/arrays/MajorityElement.java b/src/main/java/com/rampatra/arrays/MajorityElement.java
index a9dc7386..51e5d11f 100644
--- a/src/main/java/com/rampatra/arrays/MajorityElement.java
+++ b/src/main/java/com/rampatra/arrays/MajorityElement.java
@@ -1,24 +1,18 @@
package com.rampatra.arrays;
-/**
- * Created by IntelliJ IDEA.
- *
- * @author: ramswaroop
- * @date: 5/20/15
- * @time: 2:36 PM
- */
-
-
/**
* The algorithm for finding a possible candidate
* works in O(n) which is known as Moore’s Voting Algorithm.
* Basic idea of the algorithm is if we cancel out each
* occurrence of an element e with all the other elements
- * that are different from e then e will exist till end
+ * that are different from e then e will exist until end
* if it is a majority element.
*
* Time Complexity: O(n)
* Auxiliary Space : O(1)
+ *
+ * @author rampatra
+ * @since 5/20/15
*/
public class MajorityElement {
@@ -29,7 +23,7 @@ public class MajorityElement {
* @param a
* @return
*/
- public static int findCandidate(int a[]) {
+ public static int findCandidate(int[] a) {
int candidate = a[0], count = 1;
for (int i = 1; i < a.length; i++) {
if (candidate == a[i]) {
@@ -45,7 +39,7 @@ public static int findCandidate(int a[]) {
return candidate;
}
- public static void majorityElement(int a[]) {
+ public static void majorityElement(int[] a) {
int candidate = findCandidate(a),
count = 0;
@@ -62,7 +56,7 @@ public static void majorityElement(int a[]) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
majorityElement(new int[]{1, 6, 2, 2, 2, 1, 2, 2, 7, 2});
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/rampatra/arrays/MajorityElementInSortedArray.java b/src/main/java/com/rampatra/arrays/MajorityElementInSortedArray.java
index 8d20221e..ded2db27 100644
--- a/src/main/java/com/rampatra/arrays/MajorityElementInSortedArray.java
+++ b/src/main/java/com/rampatra/arrays/MajorityElementInSortedArray.java
@@ -3,30 +3,29 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/31/15
- * @time: 10:02 AM
+ * @author rampatra
+ * @since 7/31/15
*/
public class MajorityElementInSortedArray {
/**
- * Checks if {@param n} is a majority element in array {@param a}
+ * Checks if {@code n} is a majority element in array {@code arr}
* by performing a binary search.
*
* Time complexity: O(log n)
*
- * @param a
+ * @param arr
* @param n
* @return
*/
- public static boolean isMajorityElement(int[] a, int n) {
- int l = a.length;
- int startIndex = getFirstIndexOf(a, n, 0, l - 1);
+ public static boolean isMajorityElement(int[] arr, int n) {
+ int l = arr.length;
+ int startIndex = getFirstIndexOf(arr, n, 0, l - 1);
// element not found
if (startIndex == -1) return false;
- if (startIndex + l / 2 < l && a[startIndex + l / 2] == n) {
+ if (startIndex + l / 2 < l && arr[startIndex + l / 2] == n) {
return true;
} else {
return false;
@@ -35,15 +34,15 @@ public static boolean isMajorityElement(int[] a, int n) {
}
/**
- * Returns the index of first occurrence of {@param n} in array {@param a}.
+ * Returns the index of first occurrence of {@code n} in array {@code arr}.
*
- * @param a
+ * @param arr
* @param low
* @param high
* @param n
* @return
*/
- public static int getFirstIndexOf(int[] a, int n, int low, int high) {
+ public static int getFirstIndexOf(int[] arr, int n, int low, int high) {
if (low <= high) {
int mid = (low + high) / 2;
/**
@@ -53,18 +52,18 @@ public static int getFirstIndexOf(int[] a, int n, int low, int high) {
* (i) mid == 0 and a[mid] == n
* (ii) n > a[mid-1] and a[mid] == n
*/
- if (a[mid] == n && (mid == 0 || n > a[mid - 1])) {
+ if (arr[mid] == n && (mid == 0 || n > arr[mid - 1])) {
return mid;
- } else if (n <= a[mid]) {
- return getFirstIndexOf(a, n, low, mid - 1);
+ } else if (n <= arr[mid]) {
+ return getFirstIndexOf(arr, n, low, mid - 1);
} else {
- return getFirstIndexOf(a, n, mid + 1, high);
+ return getFirstIndexOf(arr, n, mid + 1, high);
}
}
return -1;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(isMajorityElement(new int[]{2, 2}, 2));
System.out.println(isMajorityElement(new int[]{1, 2}, 2));
System.out.println(isMajorityElement(new int[]{1, 2, 2, 2, 2, 2, 3, 3}, 2));
diff --git a/src/main/java/com/rampatra/arrays/MatrixInSpiral.java b/src/main/java/com/rampatra/arrays/MatrixInSpiral.java
index a5853121..a498f39a 100644
--- a/src/main/java/com/rampatra/arrays/MatrixInSpiral.java
+++ b/src/main/java/com/rampatra/arrays/MatrixInSpiral.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 9/9/15
+ * @author rampatra
+ * @since 9/9/15
* @time: 2:55 PM
*/
public class MatrixInSpiral {
@@ -43,7 +43,7 @@ public static void printMatrixInSpiral(int[][] a) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
printMatrixInSpiral(new int[][]{{1}, {2}});
out.println();
printMatrixInSpiral(new int[][]{{1, 2}, {3, 4}});
diff --git a/src/main/java/com/rampatra/arrays/MaxDiffWithLargerElementAfterSmallerElement.java b/src/main/java/com/rampatra/arrays/MaxDiffWithLargerElementAfterSmallerElement.java
index 815e71ed..04d7a9f8 100644
--- a/src/main/java/com/rampatra/arrays/MaxDiffWithLargerElementAfterSmallerElement.java
+++ b/src/main/java/com/rampatra/arrays/MaxDiffWithLargerElementAfterSmallerElement.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/12/15
+ * @author rampatra
+ * @since 8/12/15
* @time: 5:40 PM
*/
public class MaxDiffWithLargerElementAfterSmallerElement {
@@ -35,7 +35,7 @@ public static int getMaxDiffWithLargerElementAfterSmallerElement(int[] a) {
return maxDiff;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getMaxDiffWithLargerElementAfterSmallerElement(new int[]{2, 1, 4, 5, 10, 0}));
System.out.println(getMaxDiffWithLargerElementAfterSmallerElement(new int[]{2, -6, 4, 5, 10, 1}));
System.out.println(getMaxDiffWithLargerElementAfterSmallerElement(new int[]{-2, -6, -4, -5, -10, -1}));
diff --git a/src/main/java/com/rampatra/arrays/MaxInAllSubArrays.java b/src/main/java/com/rampatra/arrays/MaxInAllSubArrays.java
index bae67d64..8061d44d 100644
--- a/src/main/java/com/rampatra/arrays/MaxInAllSubArrays.java
+++ b/src/main/java/com/rampatra/arrays/MaxInAllSubArrays.java
@@ -1,6 +1,6 @@
package com.rampatra.arrays;
-import com.rampatra.common.MaxHeap;
+import com.rampatra.base.MaxHeap;
import java.util.ArrayDeque;
import java.util.Arrays;
@@ -8,8 +8,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 9/3/15
+ * @author rampatra
+ * @since 9/3/15
* @time: 9:21 PM
*/
public class MaxInAllSubArrays {
@@ -93,7 +93,7 @@ public static int[] maxInAllSubArraysOfSizeK(int[] a, int k) {
return result;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(maxInAllSubArraysOfSizeKNaive(new int[]{1, 2, 3, 1, 4, 5, 2, 3, 6}, 3)));
System.out.println(Arrays.toString(maxInAllSubArraysOfSizeKNaive(new int[]{8, 5, 10, 7, 9, 4, 15, 12, 90, 13}, 4)));
System.out.println(Arrays.toString(maxInAllSubArraysOfSizeK(new int[]{1, 2, 3, 1, 4, 5, 2, 3, 6}, 3)));
diff --git a/src/main/java/com/rampatra/arrays/MaxIndexDiff.java b/src/main/java/com/rampatra/arrays/MaxIndexDiff.java
index da5cd359..9eb982c4 100644
--- a/src/main/java/com/rampatra/arrays/MaxIndexDiff.java
+++ b/src/main/java/com/rampatra/arrays/MaxIndexDiff.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 9/1/15
+ * @author rampatra
+ * @since 9/1/15
* @time: 10:21 PM
*/
public class MaxIndexDiff {
@@ -49,7 +49,7 @@ public static int maxDiff(int[] a) {
return maxDiff;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(maxDiff(new int[]{34, 8, 10, 3, 2, 80, 30, 33, 1}));
System.out.println(maxDiff(new int[]{9, 2, 3, 4, 5, 6, 7, 8, 18, 0}));
System.out.println(maxDiff(new int[]{1, 2, 3, 4, 5, 6}));
diff --git a/src/main/java/com/rampatra/arrays/MaxMinWithMinComparisons.java b/src/main/java/com/rampatra/arrays/MaxMinWithMinComparisons.java
index a68d9165..23e3e99d 100644
--- a/src/main/java/com/rampatra/arrays/MaxMinWithMinComparisons.java
+++ b/src/main/java/com/rampatra/arrays/MaxMinWithMinComparisons.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/31/15
+ * @author rampatra
+ * @since 7/31/15
* @time: 3:16 PM
*/
public class MaxMinWithMinComparisons {
@@ -53,7 +53,7 @@ public static int[] getMaxMinWithMinComparisons(int[] a) {
return new int[]{min, max};
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(getMaxMinWithMinComparisons(new int[]{2, 5, 1, 6, 7, 9, 0, 8, 10})));
}
}
diff --git a/src/main/java/com/rampatra/arrays/MaxSpan.java b/src/main/java/com/rampatra/arrays/MaxSpan.java
new file mode 100644
index 00000000..7db17c18
--- /dev/null
+++ b/src/main/java/com/rampatra/arrays/MaxSpan.java
@@ -0,0 +1,45 @@
+package com.rampatra.arrays;
+
+import com.sun.tools.javac.util.Assert;
+
+/**
+ * Consider the leftmost and rightmost appearances of some value in an array. We'll say that the "span" is the
+ * number of elements between the two inclusive. A single value has a span of 1. Returns the largest span found
+ * in the given array.
+ *
+ * Examples:
+ * maxSpan([1, 2, 1, 1, 3]) → 4
+ * maxSpan([1, 4, 2, 1, 4, 1, 4]) → 6
+ * maxSpan([1, 4, 2, 1, 4, 4, 4]) → 6
+ *
+ * Level: Easy
+ *
+ * @author rampatra
+ * @link https://codingbat.com/prob/p189576
+ * @since 2019-01-23
+ */
+public class MaxSpan {
+
+ public static int maxSpan(int[] nums) {
+ if (nums.length == 0) return 0;
+ int largestSpan = 1;
+ for (int i = 0; i < nums.length; i++) {
+ for (int j = nums.length - 1; j > i; j--) {
+ if (nums[i] == nums[j]) {
+ if (j - i + 1 > largestSpan) {
+ largestSpan = j - i + 1;
+ }
+ }
+ }
+ }
+ return largestSpan;
+ }
+
+ public static void main(String[] args) {
+ Assert.check(maxSpan(new int[]{1, 2, 1, 1, 3}) == 4);
+ Assert.check(maxSpan(new int[]{1, 4, 2, 1, 4, 1, 4}) == 6);
+ Assert.check(maxSpan(new int[]{1, 4, 2, 1, 4, 4, 4}) == 6);
+ Assert.check(maxSpan(new int[]{1}) == 1);
+ Assert.check(maxSpan(new int[]{}) == 0);
+ }
+}
diff --git a/src/main/java/com/rampatra/arrays/MaximumSizeSquareSubMatrix.java b/src/main/java/com/rampatra/arrays/MaximumSizeSquareSubMatrix.java
index e7974d18..0c9c4419 100644
--- a/src/main/java/com/rampatra/arrays/MaximumSizeSquareSubMatrix.java
+++ b/src/main/java/com/rampatra/arrays/MaximumSizeSquareSubMatrix.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/4/15
+ * @author rampatra
+ * @since 8/4/15
* @time: 11:48 PM
*/
public class MaximumSizeSquareSubMatrix {
@@ -64,7 +64,7 @@ public static void printMaximumSizeSquareSubMatrix(int[][] a) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
int[][] ar = new int[][]{{0, 1, 1, 1},
{1, 1, 0, 1},
{1, 0, 0, 1},
diff --git a/src/main/java/com/rampatra/arrays/MaximumSumNonAdjacentSubSequence.java b/src/main/java/com/rampatra/arrays/MaximumSumNonAdjacentSubSequence.java
index be9ce541..9734aa29 100644
--- a/src/main/java/com/rampatra/arrays/MaximumSumNonAdjacentSubSequence.java
+++ b/src/main/java/com/rampatra/arrays/MaximumSumNonAdjacentSubSequence.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/29/15
+ * @author rampatra
+ * @since 7/29/15
* @time: 9:18 AM
*/
public class MaximumSumNonAdjacentSubSequence {
@@ -35,7 +35,7 @@ public static int maximumSumNonAdjacentSubSequence(int[] a) {
return Math.max(incl, excl);
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(maximumSumNonAdjacentSubSequence(new int[]{3, 2, 7, 10}));
System.out.println(maximumSumNonAdjacentSubSequence(new int[]{3, 2, 5, 10, 7}));
}
diff --git a/src/main/java/com/rampatra/arrays/MedianOfStream.java b/src/main/java/com/rampatra/arrays/MedianOfStream.java
index 4c340d3c..47781bc0 100644
--- a/src/main/java/com/rampatra/arrays/MedianOfStream.java
+++ b/src/main/java/com/rampatra/arrays/MedianOfStream.java
@@ -1,13 +1,13 @@
package com.rampatra.arrays;
-import com.rampatra.common.MaxHeap;
-import com.rampatra.common.MinHeap;
+import com.rampatra.base.MaxHeap;
+import com.rampatra.base.MinHeap;
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 9/12/15
+ * @author rampatra
+ * @since 9/12/15
* @time: 11:19 PM
*/
public class MedianOfStream {
@@ -73,7 +73,7 @@ static int compare(int a, int b) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
printMedianOfStream(new int[]{5, 15, 1, 3, 2, 8, 7, 9, 10, 6, 11, 4});
printMedianOfStream(new int[]{5, 15, 1});
printMedianOfStream(new int[]{5, 15, 10, 20});
diff --git a/src/main/java/com/rampatra/arrays/MedianOfTwoSortedArrays.java b/src/main/java/com/rampatra/arrays/MedianOfTwoSortedArrays.java
index 946a83f9..d64ec757 100644
--- a/src/main/java/com/rampatra/arrays/MedianOfTwoSortedArrays.java
+++ b/src/main/java/com/rampatra/arrays/MedianOfTwoSortedArrays.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/27/15
+ * @author rampatra
+ * @since 7/27/15
* @time: 5:50 PM
*/
public class MedianOfTwoSortedArrays {
@@ -94,7 +94,7 @@ public static int median(int[] a1, int[] a2) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
// test cases
System.out.println(median(new int[]{1, 2, 3, 6}, new int[]{4, 6, 8, 9}));
System.out.println(median(new int[]{4, 6, 8, 9}, new int[]{1, 2, 3, 6}));
diff --git a/src/main/java/com/rampatra/arrays/MergeArrayOfNIntoArrayOfMPlusN.java b/src/main/java/com/rampatra/arrays/MergeArrayOfNIntoArrayOfMPlusN.java
index 11f14fe3..e95c653a 100644
--- a/src/main/java/com/rampatra/arrays/MergeArrayOfNIntoArrayOfMPlusN.java
+++ b/src/main/java/com/rampatra/arrays/MergeArrayOfNIntoArrayOfMPlusN.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/27/15
+ * @author rampatra
+ * @since 7/27/15
* @time: 12:15 PM
*/
public class MergeArrayOfNIntoArrayOfMPlusN {
@@ -57,7 +57,7 @@ public static void merge(int[] mPlusN, int[] n) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
int[] mPlusN = {2, NA, 12, NA, NA, 14, NA};
int[] n = {5, 7, 8, 10};
merge(mPlusN, n);
diff --git a/src/main/java/com/rampatra/arrays/MinimumDistanceBetweenTwoNos.java b/src/main/java/com/rampatra/arrays/MinimumDistanceBetweenTwoNos.java
index ee9b2a2b..48edc1a9 100644
--- a/src/main/java/com/rampatra/arrays/MinimumDistanceBetweenTwoNos.java
+++ b/src/main/java/com/rampatra/arrays/MinimumDistanceBetweenTwoNos.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 9/6/15
+ * @author rampatra
+ * @since 9/6/15
* @time: 10:53 PM
*/
public class MinimumDistanceBetweenTwoNos {
@@ -45,7 +45,7 @@ public static int getMinimumDistanceBetweenTwoNos(int[] a, int x, int y) {
return minDiff;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getMinimumDistanceBetweenTwoNos(new int[]{1, 2}, 1, 2));
System.out.println(getMinimumDistanceBetweenTwoNos(new int[]{3, 4, 5}, 3, 5));
System.out.println(getMinimumDistanceBetweenTwoNos(new int[]{3, 5, 4, 2, 6, 5, 6, 6, 5, 4, 8, 3}, 3, 6));
diff --git a/src/main/java/com/rampatra/arrays/MissingAndRepeatingElements.java b/src/main/java/com/rampatra/arrays/MissingAndRepeatingElements.java
index b2218284..5fe08bf2 100644
--- a/src/main/java/com/rampatra/arrays/MissingAndRepeatingElements.java
+++ b/src/main/java/com/rampatra/arrays/MissingAndRepeatingElements.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 9/7/15
+ * @author rampatra
+ * @since 9/7/15
* @time: 10:54 AM
*/
public class MissingAndRepeatingElements {
@@ -38,7 +38,7 @@ public static int[] findMissingAndRepeatingElements(int[] a) {
return result;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(findMissingAndRepeatingElements(new int[]{3, 1, 3})));
System.out.println(Arrays.toString(findMissingAndRepeatingElements(new int[]{4, 3, 6, 2, 1, 1})));
System.out.println(Arrays.toString(findMissingAndRepeatingElements(new int[]{4, 4, 6, 2, 5, 1})));
diff --git a/src/main/java/com/rampatra/arrays/MissingNumber.java b/src/main/java/com/rampatra/arrays/MissingNumber.java
index d9abc3b6..6691f6db 100644
--- a/src/main/java/com/rampatra/arrays/MissingNumber.java
+++ b/src/main/java/com/rampatra/arrays/MissingNumber.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 5/28/15
+ * @author rampatra
+ * @since 5/28/15
* @time: 4:34 PM
*/
@@ -48,7 +48,7 @@ public static int missingNumberUsingXOR(int a[], int n) {
return nXOR ^ arrayXOR;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println("Missing No: " + missingNumber(new int[]{2, 3, 1, 4, 6, 7, 8}, 8));
System.out.println("Missing No using XOR: " + missingNumberUsingXOR(new int[]{2, 3, 1, 4, 6, 7, 8}, 8));
}
diff --git a/src/main/java/com/rampatra/arrays/NextGreaterElement.java b/src/main/java/com/rampatra/arrays/NextGreaterElement.java
index 311d3d57..96c568f1 100644
--- a/src/main/java/com/rampatra/arrays/NextGreaterElement.java
+++ b/src/main/java/com/rampatra/arrays/NextGreaterElement.java
@@ -1,13 +1,13 @@
package com.rampatra.arrays;
-import com.rampatra.common.LinkedStack;
-import com.rampatra.common.Stack;
+import com.rampatra.base.LinkedStack;
+import com.rampatra.base.Stack;
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/26/15
+ * @author rampatra
+ * @since 8/26/15
* @time: 12:35 PM
*/
public class NextGreaterElement {
@@ -47,7 +47,7 @@ public static void nextGreaterElements(int[] a) {
System.out.println(a[i] + "->" + -1);
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
int[] ar = new int[]{4, 5, 2, 25};
nextGreaterElements(ar);
System.out.println("=========");
diff --git a/src/main/java/com/rampatra/arrays/NextLargerNumber.java b/src/main/java/com/rampatra/arrays/NextLargerNumber.java
index 18a77d74..00e00b78 100644
--- a/src/main/java/com/rampatra/arrays/NextLargerNumber.java
+++ b/src/main/java/com/rampatra/arrays/NextLargerNumber.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 10/30/15
+ * @author rampatra
+ * @since 10/30/15
* @time: 11:01 AM
* @see: http://www.geeksforgeeks.org/find-next-greater-number-set-digits/
*/
@@ -84,7 +84,7 @@ private static void swap(int[] a, int index1, int index2) {
a[index2] = temp;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(findNextLargerNumber(56));
System.out.println(findNextLargerNumber(65));
System.out.println(findNextLargerNumber(3451));
diff --git a/src/main/java/com/rampatra/arrays/NthSmallestNumber.java b/src/main/java/com/rampatra/arrays/NthSmallestNumber.java
new file mode 100644
index 00000000..8f7fbaf1
--- /dev/null
+++ b/src/main/java/com/rampatra/arrays/NthSmallestNumber.java
@@ -0,0 +1,61 @@
+package com.rampatra.arrays;
+
+/**
+ * A Google Interview Question. For a simpler version of this question see {@link SmallestAndSecondSmallest}.
+ *
+ * @author rampatra
+ * @since 2019-02-01
+ */
+public class NthSmallestNumber {
+
+ /**
+ * Given an unsorted array of integers, find the nth smallest integer in the array in most optimized way possible.
+ *
+ * Approach: Similar to Quick Sort where in every iteration, we choose a pivot element and shift all lesser integers
+ * to left and higher integers to the right. After doing this we compare the pivot index with n and recursively call
+ * the method accordingly. See {@link com.rampatra.sorting.QuickSort}.
+ *
+ * @param arr the input unsorted array of integers
+ * @param n nth smallest integer to find
+ * @param start the start index in the array to search (inclusive)
+ * @param end the last index in the array to search (inclusive)
+ * @return the nth smallest integer, {@code -1} if invalid input
+ */
+ private static int findNthSmallestNumber(int[] arr, int n, int start, int end) {
+ if (arr.length == 0 || arr.length < n) {
+ return -1;
+ }
+ int temp;
+ int lastBigger = start;
+ for (int i = start; i < end; i++) {
+ if (arr[i] < arr[end]) {
+ temp = arr[i];
+ arr[i] = arr[lastBigger];
+ arr[lastBigger] = temp;
+ lastBigger++;
+ }
+ }
+ temp = arr[lastBigger];
+ arr[lastBigger] = arr[end];
+ arr[end] = temp;
+
+ if (lastBigger + 1 < n) {
+ return findNthSmallestNumber(arr, n, lastBigger + 1, end);
+ } else if (lastBigger + 1 > n) {
+ return findNthSmallestNumber(arr, n, start, lastBigger - 1);
+ } else {
+ return arr[lastBigger];
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println(findNthSmallestNumber(new int[]{}, 3, 0, 5));
+ System.out.println(findNthSmallestNumber(new int[]{0, 1}, 3, 0, 1));
+ System.out.println(findNthSmallestNumber(new int[]{0, 1}, 2, 0, 1));
+ System.out.println(findNthSmallestNumber(new int[]{1, 0}, 2, 0, 1));
+ System.out.println(findNthSmallestNumber(new int[]{2, 3, 5, 10, 9, 4}, 3, 0, 5));
+ System.out.println(findNthSmallestNumber(new int[]{2, 3, 4, 10, 9, 4}, 3, 0, 5));
+ System.out.println(findNthSmallestNumber(new int[]{4, 4, 4, 4, 4, 4}, 3, 0, 5));
+ System.out.println(findNthSmallestNumber(new int[]{4, 8, 1, 9, 10, 2, 7, 3, 2, 6}, 3, 0, 9)); // TODO: doesn't work with duplicates currently
+ }
+}
diff --git a/src/main/java/com/rampatra/arrays/NumberOccurringOddTimes.java b/src/main/java/com/rampatra/arrays/NumberOccurringOddTimes.java
index dba56398..81656dd1 100644
--- a/src/main/java/com/rampatra/arrays/NumberOccurringOddTimes.java
+++ b/src/main/java/com/rampatra/arrays/NumberOccurringOddTimes.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 5/20/15
+ * @author rampatra
+ * @since 5/20/15
* @time: 11:09 PM
*/
@@ -28,7 +28,7 @@ public static int numberOccurringOddTimes(int a[]) {
return res;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.print(numberOccurringOddTimes(new int[]{2, 3, 3, 3, 1, 2, 1}));
}
}
diff --git a/src/main/java/com/rampatra/arrays/OccurrencesInSortedArray.java b/src/main/java/com/rampatra/arrays/OccurrencesInSortedArray.java
index 2f031951..fea37847 100644
--- a/src/main/java/com/rampatra/arrays/OccurrencesInSortedArray.java
+++ b/src/main/java/com/rampatra/arrays/OccurrencesInSortedArray.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/31/15
+ * @author rampatra
+ * @since 8/31/15
* @time: 2:52 PM
*/
public class OccurrencesInSortedArray {
@@ -74,7 +74,7 @@ public static int getLastIndexOf(int[] a, int n, int low, int high) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getOccurrencesInSortedArray(new int[]{1, 1, 2, 2, 2, 2, 3}, 1));
System.out.println(getOccurrencesInSortedArray(new int[]{1, 1, 1, 2, 2, 2, 2, 3}, 1));
System.out.println(getOccurrencesInSortedArray(new int[]{1, 1, 2, 2, 2, 2, 3}, 2));
diff --git a/src/main/java/com/rampatra/arrays/PairDiff.java b/src/main/java/com/rampatra/arrays/PairDiff.java
index 929d9ef3..8fce2367 100644
--- a/src/main/java/com/rampatra/arrays/PairDiff.java
+++ b/src/main/java/com/rampatra/arrays/PairDiff.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 5/18/15
+ * @author rampatra
+ * @since 5/18/15
* @time: 10:24 PM
*/
@@ -63,7 +63,7 @@ static boolean pairDiff(int ar[], int x, Map map) {
return false;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(pairDiff(new int[]{-3, 4, -6, 1, 1}, -4));
System.out.println(pairDiff(new int[]{3, 1}, 2));
System.out.println(pairDiff(new int[]{-3, 4, -6, 1, 1}, -4, new HashMap()));
diff --git a/src/main/java/com/rampatra/arrays/PairSum.java b/src/main/java/com/rampatra/arrays/PairSum.java
index 17c518f4..75ce7d63 100644
--- a/src/main/java/com/rampatra/arrays/PairSum.java
+++ b/src/main/java/com/rampatra/arrays/PairSum.java
@@ -58,7 +58,7 @@ static boolean pairSum(int[] ar, int sum, Set numSet) {
return false;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(pairSum(new int[]{-3, 4, -6, 1, 1}, -2));
System.out.println(pairSum(new int[]{-3, 4, -6, 1, 1}, 5));
System.out.println(pairSum(new int[]{-3, 4, -6, 1, 1}, 0));
diff --git a/src/main/java/com/rampatra/arrays/PivotedBinarySearch.java b/src/main/java/com/rampatra/arrays/PivotedBinarySearch.java
index c9155aa0..2f104e6f 100644
--- a/src/main/java/com/rampatra/arrays/PivotedBinarySearch.java
+++ b/src/main/java/com/rampatra/arrays/PivotedBinarySearch.java
@@ -5,64 +5,70 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 5/31/15
- * @time: 10:44 PM
+ * @author rampatra
+ * @since 5/31/15
*/
public class PivotedBinarySearch {
/**
- * Search an element in a sorted pivoted array {@param a}.
+ * Search an element in a sorted pivoted array {@code arr}.
*
* Example,
* 1) For array [3,4,5,1,2] pivot is 5
* 2) For array [6,7,8,5,4] pivot is 8
*
- * @param a
+ * @param arr
* @param n
* @return
*/
- public static int pivotedBinarySearch(int a[], int n) {
- int pivot = findPivot(a, 0, a.length - 1);
+ public static int pivotedBinarySearch(int[] arr, int n) {
+ int pivot = findPivotIndex(arr, 0, arr.length - 1);
- if (pivot == -1 || a[pivot] == n) {
+ if (pivot == -1 || arr[pivot] == n) {
return pivot;
- } else if (n <= a[0]) {
- return BinarySearch.binarySearch(a, n, pivot + 1, a.length - 1);
+ } else if (n < arr[0]) {
+ return BinarySearch.binarySearch(arr, n, pivot + 1, arr.length - 1);
} else {
- return BinarySearch.binarySearch(a, n, 0, pivot - 1);
+ return BinarySearch.binarySearch(arr, n, 0, pivot - 1);
}
}
/**
- * Finds the pivot element in array {@param a}. Pivot element is the only
+ * Finds the pivot element in array {@code arr}. Pivot element is the only
* element for which next element to it is smaller than it.
*
- * @param a
+ * @param arr
* @param low
* @param high
- * @return
+ * @return the index of the pivot element in the {@code arr}.
*/
- public static int findPivot(int a[], int low, int high) {
+ public static int findPivotIndex(int[] arr, int low, int high) {
if (low > high) return -1;
- if (low == high) return low;
int mid = (low + high) / 2;
- if (a[mid] > a[mid + 1] && a[mid] > a[mid - 1]) {
+ if (mid == 0 || mid == arr.length - 1) return -1;
+
+ if (arr[mid] > arr[mid + 1] && arr[mid] > arr[mid - 1]) {
return mid;
- } else if (a[mid] > a[mid - 1] && a[mid] < a[mid + 1]) {
- return findPivot(a, mid + 1, a.length - 1);
+ } else if (arr[mid] > arr[mid - 1] && arr[mid] < arr[mid + 1]) {
+ return findPivotIndex(arr, mid + 1, arr.length - 1);
} else {
- return findPivot(a, 0, mid - 1);
+ return findPivotIndex(arr, 0, mid - 1);
}
}
- public static void main(String a[]) {
- System.out.println("Pivot: " + findPivot(new int[]{1, 2, 3, 4, 5}, 0, 3));
+ public static void main(String[] args) {
+ System.out.println("Pivot: " + findPivotIndex(new int[]{3, 4, 5, 1, 2}, 0, 4));
+ System.out.println("Index: " + pivotedBinarySearch(new int[]{3, 4, 5, 1, 2}, 5));
+
+ System.out.println("Pivot: " + findPivotIndex(new int[]{1, 2, 3, 4, 5}, 0, 4));
System.out.println("Index: " + pivotedBinarySearch(new int[]{1, 2, 3, 4, 5}, 4));
- System.out.println("Pivot: " + findPivot(new int[]{5}, 0, 0));
- System.out.println("Index: " + pivotedBinarySearch(new int[]{5}, 5));
+ System.out.println("Pivot: " + findPivotIndex(new int[]{5, 4, 3, 2, 1}, 0, 4));
+ System.out.println("Index: " + pivotedBinarySearch(new int[]{5, 4, 3, 2, 1}, 4));
+
+ System.out.println("Pivot: " + findPivotIndex(new int[]{5}, 0, -1));
+ System.out.println("Index: " + pivotedBinarySearch(new int[]{5}, -1));
}
}
diff --git a/src/main/java/com/rampatra/arrays/ProductArrayPuzzle.java b/src/main/java/com/rampatra/arrays/ProductArrayPuzzle.java
index 50500dc3..23de1acc 100644
--- a/src/main/java/com/rampatra/arrays/ProductArrayPuzzle.java
+++ b/src/main/java/com/rampatra/arrays/ProductArrayPuzzle.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/15/15
+ * @author rampatra
+ * @since 8/15/15
* @time: 9:17 PM
*/
public class ProductArrayPuzzle {
@@ -63,7 +63,7 @@ public static int[] getProductArray(int[] a) {
return prod;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(getProductArray(new int[]{10, 3, 5, 6, 2})));
System.out.println(Arrays.toString(getProductArray(new int[]{0, 0})));
System.out.println(Arrays.toString(getProductArray(new int[]{1})));
diff --git a/src/main/java/com/rampatra/arrays/ReservoirSampling.java b/src/main/java/com/rampatra/arrays/ReservoirSampling.java
index 7def1ad9..050fb17f 100644
--- a/src/main/java/com/rampatra/arrays/ReservoirSampling.java
+++ b/src/main/java/com/rampatra/arrays/ReservoirSampling.java
@@ -6,8 +6,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/21/15
+ * @author rampatra
+ * @since 7/21/15
* @time: 2:52 PM
*/
public class ReservoirSampling {
@@ -58,7 +58,7 @@ public static int[] getKRandomNumbers(int[] stream, int k) {
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
int[] stream = {1, 2, 3, 4, 5, 6, 7, 8, 9};
System.out.println(Arrays.toString(getKRandomNumbers(stream, 4)));
}
diff --git a/src/main/java/com/rampatra/arrays/ReverseArray.java b/src/main/java/com/rampatra/arrays/ReverseArray.java
index a7b57ee2..64550c58 100644
--- a/src/main/java/com/rampatra/arrays/ReverseArray.java
+++ b/src/main/java/com/rampatra/arrays/ReverseArray.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/27/15
+ * @author rampatra
+ * @since 7/27/15
* @time: 8:40 PM
*/
public class ReverseArray {
@@ -43,7 +43,7 @@ public static void reverseRecursive(int[] a, int i, int j) {
reverseRecursive(a, ++i, --j);
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
int[] ar = new int[]{1, 2, 3, 4, 5};
System.out.println(Arrays.toString(ar));
reverse(ar);
diff --git a/src/main/java/com/rampatra/arrays/RotateArray.java b/src/main/java/com/rampatra/arrays/RotateArray.java
index b625210d..f720dcf6 100644
--- a/src/main/java/com/rampatra/arrays/RotateArray.java
+++ b/src/main/java/com/rampatra/arrays/RotateArray.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/28/15
+ * @author rampatra
+ * @since 7/28/15
* @time: 10:53 AM
*/
public class RotateArray {
@@ -91,7 +91,7 @@ public static int gcd(int a, int b) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
int[] ar = {1, 2, 3, 4, 5, 6, 7};
System.out.println(Arrays.toString(ar));
rotateNaiveApproach(ar, 2);
diff --git a/src/main/java/com/rampatra/arrays/RotateMatrixBy90Degrees.java b/src/main/java/com/rampatra/arrays/RotateMatrixBy90Degrees.java
index b7292629..ccff75ca 100644
--- a/src/main/java/com/rampatra/arrays/RotateMatrixBy90Degrees.java
+++ b/src/main/java/com/rampatra/arrays/RotateMatrixBy90Degrees.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/22/15
+ * @author rampatra
+ * @since 8/22/15
* @time: 4:03 PM
*/
public class RotateMatrixBy90Degrees {
@@ -42,7 +42,7 @@ private static void print2DMatrix(int[][] a) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
int[][] ar = new int[][]{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
print2DMatrix(ar);
System.out.println("--------");
diff --git a/src/main/java/com/rampatra/arrays/RotatedIndex.java b/src/main/java/com/rampatra/arrays/RotatedIndex.java
new file mode 100644
index 00000000..4478e5e3
--- /dev/null
+++ b/src/main/java/com/rampatra/arrays/RotatedIndex.java
@@ -0,0 +1,55 @@
+package com.rampatra.arrays;
+
+/**
+ * @author rampatra
+ * @since 2019-04-04
+ */
+public class RotatedIndex {
+
+ private static int findIndexOfRotationPoint(String[] words) {
+ return findIndexOfRotationPoint(words, 0, words.length - 1);
+ }
+
+ private static int findIndexOfRotationPoint(String[] words, int start, int end) {
+ if (start > end) return -1;
+
+ int mid = (start + end) / 2;
+
+ if (mid == 0 || mid == words.length - 1) return -1;
+
+ if (words[mid].compareTo(words[mid - 1]) < 0 && words[mid].compareTo(words[mid + 1]) < 0) {
+ return mid;
+ } else if (words[mid].compareTo(words[mid - 1]) > 0 && words[mid].compareTo(words[mid + 1]) < 0) {
+ return findIndexOfRotationPoint(words, start, mid - 1);
+ } else {
+ return findIndexOfRotationPoint(words, mid + 1, end);
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println(findIndexOfRotationPoint(new String[]{
+ "ptolemaic",
+ "retrograde",
+ "supplant",
+ "undulate",
+ "xenoepist",
+ "asymptote", // <-- rotates here!
+ "babka",
+ "banoffee",
+ "engender",
+ "karpatka",
+ "othellolagkage",
+ }));
+
+ System.out.println(findIndexOfRotationPoint(new String[]{}));
+
+ System.out.println(findIndexOfRotationPoint(new String[]{
+ "asymptote",
+ "babka",
+ "banoffee",
+ "engender",
+ "karpatka",
+ "othellolagkage",
+ }));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/rampatra/arrays/SearchInSorted2DArray.java b/src/main/java/com/rampatra/arrays/SearchInSorted2DArray.java
index 7d03aa8b..8ab14269 100644
--- a/src/main/java/com/rampatra/arrays/SearchInSorted2DArray.java
+++ b/src/main/java/com/rampatra/arrays/SearchInSorted2DArray.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/23/15
+ * @author rampatra
+ * @since 8/23/15
* @time: 10:31 PM
*/
public class SearchInSorted2DArray {
@@ -86,7 +86,7 @@ private static void print2DMatrix(int[][] a) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
int[][] ar = new int[][]{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
print2DMatrix(ar);
System.out.println(Arrays.toString(linearSearchNaive(ar, 0, 0, 1)));
diff --git a/src/main/java/com/rampatra/arrays/Segregate0s1sAnd2s.java b/src/main/java/com/rampatra/arrays/Segregate0s1sAnd2s.java
index 799d3a12..e64929f8 100644
--- a/src/main/java/com/rampatra/arrays/Segregate0s1sAnd2s.java
+++ b/src/main/java/com/rampatra/arrays/Segregate0s1sAnd2s.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/18/15
+ * @author rampatra
+ * @since 8/18/15
* @time: 8:38 PM
*/
public class Segregate0s1sAnd2s {
@@ -45,7 +45,7 @@ private static void swap(int[] a, int index1, int index2) {
a[index2] = temp;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
int[] ar = new int[]{0, 1, 2, 0, 1, 2};
segregate0s1sAnd2s(ar);
System.out.println(Arrays.toString(ar));
diff --git a/src/main/java/com/rampatra/arrays/Segregate0sAnd1s.java b/src/main/java/com/rampatra/arrays/Segregate0sAnd1s.java
index e9c0fbea..e5f9634a 100644
--- a/src/main/java/com/rampatra/arrays/Segregate0sAnd1s.java
+++ b/src/main/java/com/rampatra/arrays/Segregate0sAnd1s.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/31/15
+ * @author rampatra
+ * @since 7/31/15
* @time: 5:13 PM
*/
public class Segregate0sAnd1s {
@@ -27,7 +27,7 @@ public static void segregate0sAnd1s(int[] a) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
int[] ar = new int[]{0, 1, 1, 1, 0, 0, 1};
segregate0sAnd1s(ar);
System.out.println(Arrays.toString(ar));
diff --git a/src/main/java/com/rampatra/arrays/SegregateEvenAndOddNos.java b/src/main/java/com/rampatra/arrays/SegregateEvenAndOddNos.java
index 3487e810..8cdaf6b6 100644
--- a/src/main/java/com/rampatra/arrays/SegregateEvenAndOddNos.java
+++ b/src/main/java/com/rampatra/arrays/SegregateEvenAndOddNos.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/31/15
+ * @author rampatra
+ * @since 7/31/15
* @time: 5:13 PM
*/
public class SegregateEvenAndOddNos {
@@ -39,7 +39,7 @@ public static void segregateEvenAndOddNos(int[] a) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
int[] ar = new int[]{12, 34, 45, 9, 8, 90, 3};
segregateEvenAndOddNos(ar);
System.out.println(Arrays.toString(ar));
diff --git a/src/main/java/com/rampatra/arrays/SmallestAndSecondSmallest.java b/src/main/java/com/rampatra/arrays/SmallestAndSecondSmallest.java
index b628a033..9e683caf 100644
--- a/src/main/java/com/rampatra/arrays/SmallestAndSecondSmallest.java
+++ b/src/main/java/com/rampatra/arrays/SmallestAndSecondSmallest.java
@@ -5,13 +5,12 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/30/15
- * @time: 11:13 PM
+ * @author rampatra
+ * @since 7/30/15
*/
public class SmallestAndSecondSmallest {
- public static int[] getSmallestAndSecondSmallest(int[] a) {
+ private static int[] getSmallestAndSecondSmallest(int[] a) {
int smallest = Integer.MAX_VALUE, secondSmallest = Integer.MAX_VALUE;
for (int i = 0; i < a.length; i++) {
@@ -26,7 +25,7 @@ public static int[] getSmallestAndSecondSmallest(int[] a) {
return new int[]{smallest, secondSmallest};
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(getSmallestAndSecondSmallest(new int[]{100, 1, 60, -10, -80, 85, 70, -80})));
System.out.println(Arrays.toString(getSmallestAndSecondSmallest(new int[]{100, 1, 60, 10, 80, 85, 70, 0})));
}
diff --git a/src/main/java/com/rampatra/arrays/SmallestMissingNumber.java b/src/main/java/com/rampatra/arrays/SmallestMissingNumber.java
index 8a2281fb..7b63a415 100644
--- a/src/main/java/com/rampatra/arrays/SmallestMissingNumber.java
+++ b/src/main/java/com/rampatra/arrays/SmallestMissingNumber.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/29/15
+ * @author rampatra
+ * @since 8/29/15
* @time: 12:51 PM
*/
public class SmallestMissingNumber {
@@ -45,7 +45,7 @@ public static int smallestMissingNumber(int[] a, int low, int high) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(smallestMissingNumber(new int[]{0, 1}, 0, 1));
System.out.println(smallestMissingNumber(new int[]{0, 1, 2, 6, 9}, 0, 4));
System.out.println(smallestMissingNumber(new int[]{4, 5, 10, 11}, 0, 3));
diff --git a/src/main/java/com/rampatra/arrays/SortedSubSequence.java b/src/main/java/com/rampatra/arrays/SortedSubSequence.java
index e6e836ed..b6cd1b5c 100644
--- a/src/main/java/com/rampatra/arrays/SortedSubSequence.java
+++ b/src/main/java/com/rampatra/arrays/SortedSubSequence.java
@@ -3,9 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 10/12/15
- * @time: 8:32 PM
+ * @author rampatra
+ * @since 10/12/15
*/
public class SortedSubSequence {
@@ -19,18 +18,18 @@ public class SortedSubSequence {
* 2) Create another auxiliary array greater[0..n-1]. greater[i] should store the index of a number which is greater than arr[i] and is on right side of arr[i]. greater[i] should contain -1 if there is no such element.
* 3) Finally traverse both smaller[] and greater[] and find the index i for which both smaller[i] and greater[i] are not -1.
*
- * @param a
+ * @param arr
*/
- public static void printSortedSubSequenceOfSize3(int[] a) {
- int len = a.length, min = a[0], max = a[len - 1];
+ public static void printSortedSubSequenceOfSize3(int[] arr) {
+ int len = arr.length, min = arr[0], max = arr[len - 1];
int[] smaller = new int[len], larger = new int[len];
smaller[0] = -1;
for (int i = 1; i < len; i++) {
- if (a[i] < min) {
+ if (arr[i] < min) {
smaller[i] = -1;
- min = a[i];
+ min = arr[i];
} else {
smaller[i] = min;
}
@@ -38,9 +37,9 @@ public static void printSortedSubSequenceOfSize3(int[] a) {
larger[len - 1] = -1;
for (int i = len - 2; i >= 0; i--) {
- if (a[i] > max) {
+ if (arr[i] > max) {
larger[i] = -1;
- max = a[i];
+ max = arr[i];
} else {
larger[i] = max;
}
@@ -48,14 +47,14 @@ public static void printSortedSubSequenceOfSize3(int[] a) {
for (int i = 0; i < len; i++) {
if (smaller[i] != -1 && larger[i] != -1) {
- System.out.println(smaller[i] + "," + a[i] + "," + larger[i]);
+ System.out.println(smaller[i] + "," + arr[i] + "," + larger[i]);
break;
}
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
printSortedSubSequenceOfSize3(new int[]{12, 11, 10, 5, 6, 2, 30});
printSortedSubSequenceOfSize3(new int[]{1, 2, 3, 4});
printSortedSubSequenceOfSize3(new int[]{4, 3, 2, 1});
diff --git a/src/main/java/com/rampatra/arrays/SubArrayOfSum.java b/src/main/java/com/rampatra/arrays/SubArrayOfSum.java
index 6eae43bc..4e4f5c2e 100644
--- a/src/main/java/com/rampatra/arrays/SubArrayOfSum.java
+++ b/src/main/java/com/rampatra/arrays/SubArrayOfSum.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 9/27/15
+ * @author rampatra
+ * @since 9/27/15
* @time: 7:32 PM
*/
public class SubArrayOfSum {
@@ -37,7 +37,7 @@ public static void printSubArrayOfSum(int[] a, int sum) {
System.out.println("Sub-array with sum " + sum + " not found!");
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
printSubArrayOfSum(new int[]{1, 4, 20, 3, 10, 5}, 33);
printSubArrayOfSum(new int[]{1, 4, 20, 3, 10, 5}, 38);
printSubArrayOfSum(new int[]{1, 4, 20, 3, 10, 5}, 13);
diff --git a/src/main/java/com/rampatra/arrays/SubsetOfArray.java b/src/main/java/com/rampatra/arrays/SubsetOfArray.java
index 8f28f84c..21d5ff2c 100644
--- a/src/main/java/com/rampatra/arrays/SubsetOfArray.java
+++ b/src/main/java/com/rampatra/arrays/SubsetOfArray.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 9/4/15
+ * @author rampatra
+ * @since 9/4/15
* @time: 11:28 PM
*/
public class SubsetOfArray {
@@ -48,7 +48,7 @@ public static boolean isSubsetOfArray(int[] a, int[] b) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(isSubsetOfArray(new int[]{11, 1, 13, 21, 3, 7}, new int[]{11, 3, 7, 1}));
System.out.println(isSubsetOfArray(new int[]{1, 2, 2, 3, 4, 5, 6}, new int[]{1, 2, 4}));
System.out.println(isSubsetOfArray(new int[]{1, 2, 2, 3, 4, 5, 6}, new int[]{1, 2, 2, 4}));
diff --git a/src/main/java/com/rampatra/arrays/SymmetricDifference.java b/src/main/java/com/rampatra/arrays/SymmetricDifference.java
index 5be49681..9ae00478 100644
--- a/src/main/java/com/rampatra/arrays/SymmetricDifference.java
+++ b/src/main/java/com/rampatra/arrays/SymmetricDifference.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 10/20/15
+ * @author rampatra
+ * @since 10/20/15
* @time: 11:34 PM
*/
public class SymmetricDifference {
@@ -51,7 +51,7 @@ public static int[] getSymmetricDifference(int[] a1, int[] a2) {
return Arrays.copyOf(res, index);
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(getSymmetricDifference(new int[]{1, 2, 3, 4}, new int[]{2, 4, 5})));
System.out.println(Arrays.toString(getSymmetricDifference(new int[]{1, 2, 3, 4}, new int[]{5, 6, 7})));
System.out.println(Arrays.toString(getSymmetricDifference(new int[]{1, 2, 3, 4}, new int[]{5, 6, 7, 8})));
diff --git a/src/main/java/com/rampatra/arrays/TripletOfSum.java b/src/main/java/com/rampatra/arrays/TripletOfSum.java
index c3548ca3..91d47649 100644
--- a/src/main/java/com/rampatra/arrays/TripletOfSum.java
+++ b/src/main/java/com/rampatra/arrays/TripletOfSum.java
@@ -7,8 +7,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 9/28/15
+ * @author rampatra
+ * @since 9/28/15
* @time: 10:39 PM
*/
public class TripletOfSum {
@@ -42,7 +42,7 @@ public static int[] getTripletOfSum(int[] a, int sum) {
return new int[]{-1};
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(getTripletOfSum(new int[]{12, 3, 4, 5, 1, 6, 9}, 24)));
System.out.println(Arrays.toString(getTripletOfSum(new int[]{12, 3, 4, 5, 1, 6, 9}, 19)));
System.out.println(Arrays.toString(getTripletOfSum(new int[]{1, 2, 3}, 6)));
diff --git a/src/main/java/com/rampatra/arrays/TwoElementsSumClosestToZero.java b/src/main/java/com/rampatra/arrays/TwoElementsSumClosestToZero.java
index 1407828a..e41a0f92 100644
--- a/src/main/java/com/rampatra/arrays/TwoElementsSumClosestToZero.java
+++ b/src/main/java/com/rampatra/arrays/TwoElementsSumClosestToZero.java
@@ -7,8 +7,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/30/15
+ * @author rampatra
+ * @since 7/30/15
* @time: 5:44 PM
*/
public class TwoElementsSumClosestToZero {
@@ -39,7 +39,7 @@ public static int[] getTwoElementsWhoseSumIsClosestToZero(int[] a) {
return new int[]{n1, n2};
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(getTwoElementsWhoseSumIsClosestToZero(new int[]{1, 60, -10, -80, 85, 70})));
System.out.println(Arrays.toString(getTwoElementsWhoseSumIsClosestToZero(new int[]{-3, -100, -10, -80, 85, 70})));
}
diff --git a/src/main/java/com/rampatra/arrays/TwoRepeatingElements.java b/src/main/java/com/rampatra/arrays/TwoRepeatingElements.java
index db311d25..a943a532 100644
--- a/src/main/java/com/rampatra/arrays/TwoRepeatingElements.java
+++ b/src/main/java/com/rampatra/arrays/TwoRepeatingElements.java
@@ -7,8 +7,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/17/15
+ * @author rampatra
+ * @since 8/17/15
* @time: 7:23 PM
*/
public class TwoRepeatingElements {
@@ -88,7 +88,7 @@ public static int[] findTwoRepeatingElements(int[] a) {
return repeatingElements;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(getTwoRepeatingElements(new int[]{4, 2, 4, 5, 2, 3, 1})));
System.out.println(Arrays.toString(getTwoRepeatingElements(new int[]{2, 4, 5, 2, 3, 1, 6, 7, 7})));
System.out.println(Arrays.toString(getTwoRepeatingElements(new int[]{1, 2, 1, 2})));
diff --git a/src/main/java/com/rampatra/arrays/TwoStacksInOneArray.java b/src/main/java/com/rampatra/arrays/TwoStacksInOneArray.java
index fa2f3132..b4e83806 100644
--- a/src/main/java/com/rampatra/arrays/TwoStacksInOneArray.java
+++ b/src/main/java/com/rampatra/arrays/TwoStacksInOneArray.java
@@ -11,8 +11,8 @@
* So we stored stack1's elements at one end of the array and stack2's elements at
* the other end.
*
- * @author: ramswaroop
- * @date: 9/21/15
+ * @author rampatra
+ * @since 9/21/15
* @time: 6:18 PM
*/
public class TwoStacksInOneArray {
@@ -70,7 +70,7 @@ void printStack(int stack) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
TwoStacksInOneArray twoStack = new TwoStacksInOneArray(5);
twoStack.push(1, 3);
twoStack.push(1, 4);
diff --git a/src/main/java/com/rampatra/arrays/UnsortedSubArray.java b/src/main/java/com/rampatra/arrays/UnsortedSubArray.java
index f23aceb3..36aa4e12 100644
--- a/src/main/java/com/rampatra/arrays/UnsortedSubArray.java
+++ b/src/main/java/com/rampatra/arrays/UnsortedSubArray.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 8/20/15
+ * @author rampatra
+ * @since 8/20/15
* @time: 10:31 AM
*/
public class UnsortedSubArray {
@@ -89,7 +89,7 @@ public static int[] getUnsortedSubArray(int[] a) {
return unsortedArray;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(getUnsortedSubArray(new int[]{10, 12, 20, 30, 25, 40, 32, 31, 35, 50, 60})));
System.out.println(Arrays.toString(getUnsortedSubArray(new int[]{0, 1, 15, 25, 6, 7, 30, 40, 50})));
System.out.println(Arrays.toString(getUnsortedSubArray(new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8}))); // fully sorted already
diff --git a/src/main/java/com/rampatra/backtracking/KnightTour.java b/src/main/java/com/rampatra/backtracking/KnightTour.java
index 8608133c..64b58918 100644
--- a/src/main/java/com/rampatra/backtracking/KnightTour.java
+++ b/src/main/java/com/rampatra/backtracking/KnightTour.java
@@ -7,8 +7,8 @@
* once. If the knight ends on a square that is one knight's move from the beginning square (so that it could tour the
* board again immediately, following the same path), the tour is closed, otherwise it is open.
*
- * @author: ramswaroop
- * @date: 10/15/15
+ * @author rampatra
+ * @since 10/15/15
* @time: 11:56 PM
* @see: https://en.wikipedia.org/wiki/Knight%27s_tour
* @see: RatInAMaze for a simpler version of this problem
@@ -105,7 +105,7 @@ public static void print2DMatrix(int[][] array) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
printKnightTour(0, 0, new int[]{8, 8});
}
}
diff --git a/src/main/java/com/rampatra/backtracking/RatInAMaze.java b/src/main/java/com/rampatra/backtracking/RatInAMaze.java
index c7a49573..bb8ea749 100644
--- a/src/main/java/com/rampatra/backtracking/RatInAMaze.java
+++ b/src/main/java/com/rampatra/backtracking/RatInAMaze.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 10/18/15
+ * @author rampatra
+ * @since 10/18/15
* @time: 10:39 AM
*/
public class RatInAMaze {
@@ -86,7 +86,7 @@ public static void print2DMatrix(int[][] array) {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
printMazePath(0, 0, new int[][]{{1, 1, 1, 1}, {0, 0, 1, 1}});
}
}
diff --git a/src/main/java/com/rampatra/common/AVLTree.java b/src/main/java/com/rampatra/base/AVLTree.java
similarity index 64%
rename from src/main/java/com/rampatra/common/AVLTree.java
rename to src/main/java/com/rampatra/base/AVLTree.java
index beb3f22b..61999cd0 100644
--- a/src/main/java/com/rampatra/common/AVLTree.java
+++ b/src/main/java/com/rampatra/base/AVLTree.java
@@ -1,10 +1,10 @@
-package com.rampatra.common;
+package com.rampatra.base;
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 4/25/15
+ * @author rampatra
+ * @since 4/25/15
* @time: 10:25 AM
*/
public class AVLTree> extends Tree {
diff --git a/src/main/java/com/rampatra/common/BinaryNode.java b/src/main/java/com/rampatra/base/BinaryNode.java
similarity index 92%
rename from src/main/java/com/rampatra/common/BinaryNode.java
rename to src/main/java/com/rampatra/base/BinaryNode.java
index e6560820..6e57530e 100644
--- a/src/main/java/com/rampatra/common/BinaryNode.java
+++ b/src/main/java/com/rampatra/base/BinaryNode.java
@@ -1,8 +1,8 @@
-package com.rampatra.common;
+package com.rampatra.base;
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 4/11/15
* Time: 7:11 PM
* To change this template go to Preferences | IDE Settings | File and Code Templates
diff --git a/src/main/java/com/rampatra/common/BinarySearchTree.java b/src/main/java/com/rampatra/base/BinarySearchTree.java
similarity index 75%
rename from src/main/java/com/rampatra/common/BinarySearchTree.java
rename to src/main/java/com/rampatra/base/BinarySearchTree.java
index d35a3155..644f1e7d 100644
--- a/src/main/java/com/rampatra/common/BinarySearchTree.java
+++ b/src/main/java/com/rampatra/base/BinarySearchTree.java
@@ -1,15 +1,20 @@
-package com.rampatra.common;
+package com.rampatra.base;
import java.util.NoSuchElementException;
import static java.lang.System.out;
/**
- * Created by IntelliJ IDEA.
- * User: ramswaroop
- * Date: 4/19/15
- * Time: 6:36 PM
- * To change this template go to Preferences | IDE Settings | File and Code Templates
+ * A binary search tree is a binary tree in which every node fits a specific ordering property: all left
+ * descendents <= n < all right descendents. This must be true for each node n.
+ *
+ * Note: The definition of a binary search tree can vary slightly with respect to equality. Under some definitions, the
+ * tree cannot have duplicate values. In others, the duplicate values will be on the right or can be on either side. All
+ * are valid definitions, but you should clarify this with your interviewer
+ *
+ * @author rampatra
+ * @since 4/19/15
+ * @param
*/
public class BinarySearchTree> extends BinaryTree {
diff --git a/src/main/java/com/rampatra/common/BinaryTree.java b/src/main/java/com/rampatra/base/BinaryTree.java
similarity index 96%
rename from src/main/java/com/rampatra/common/BinaryTree.java
rename to src/main/java/com/rampatra/base/BinaryTree.java
index d25c866c..e420d7c0 100644
--- a/src/main/java/com/rampatra/common/BinaryTree.java
+++ b/src/main/java/com/rampatra/base/BinaryTree.java
@@ -1,4 +1,4 @@
-package com.rampatra.common;
+package com.rampatra.base;
import com.rampatra.trees.BFSUsingQueue;
@@ -74,7 +74,7 @@ public void preOrder(BinaryNode node) {
if (node == null) {
return;
}
- out.print(node.value);
+ out.print("->" + node.value);
preOrder(node.left);
preOrder(node.right);
}
@@ -92,7 +92,7 @@ public void inOrder(BinaryNode node) {
return;
}
inOrder(node.left);
- out.print(node.value);
+ out.print("->" + node.value);
inOrder(node.right);
}
@@ -110,7 +110,7 @@ public void postOrder(BinaryNode node) {
}
postOrder(node.left);
postOrder(node.right);
- out.print(node.value);
+ out.print("->" + node.value);
}
@@ -119,9 +119,9 @@ public void postOrder(BinaryNode node) {
*
* DEF: Breadth-first search (BFS) is an algorithm for traversing or searching tree
* or graph data structures. It starts at the tree root (or some arbitrary node of a
- * graph, sometimes referred to as a `search key'[1]) and explores the neighbor nodes
- * first, before moving to the next level neighbors. See {@link BFSUsingQueue}
- * for a O(n) solution.
+ * graph, sometimes referred to as a `search key'[1]) and explores the neighboring nodes
+ * first, before moving to the next level neighbors. See {@link BFSUsingQueue} for a O(n)
+ * solution.
*
* Time complexity: O(h^2) where, h is the height of the tree
*/
@@ -272,7 +272,7 @@ public void printValue(BinaryNode node) {
}
// test cases
- public static void main(String[] a) {
+ public static void main(String[] args) {
BinaryTree bt = new BinaryTree<>();
bt.put(1);
bt.put(2);
diff --git a/src/main/java/com/rampatra/common/CircularSingleLinkedList.java b/src/main/java/com/rampatra/base/CircularSingleLinkedList.java
similarity index 99%
rename from src/main/java/com/rampatra/common/CircularSingleLinkedList.java
rename to src/main/java/com/rampatra/base/CircularSingleLinkedList.java
index a0dc7329..cdf37470 100644
--- a/src/main/java/com/rampatra/common/CircularSingleLinkedList.java
+++ b/src/main/java/com/rampatra/base/CircularSingleLinkedList.java
@@ -1,4 +1,4 @@
-package com.rampatra.common;
+package com.rampatra.base;
import java.util.NoSuchElementException;
@@ -7,8 +7,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/16/15
+ * @author rampatra
+ * @since 6/16/15
* @time: 1:00 PM
*/
public class CircularSingleLinkedList> implements LinkedList {
diff --git a/src/main/java/com/rampatra/common/DoubleLinkedList.java b/src/main/java/com/rampatra/base/DoubleLinkedList.java
similarity index 99%
rename from src/main/java/com/rampatra/common/DoubleLinkedList.java
rename to src/main/java/com/rampatra/base/DoubleLinkedList.java
index 76208250..e905725c 100644
--- a/src/main/java/com/rampatra/common/DoubleLinkedList.java
+++ b/src/main/java/com/rampatra/base/DoubleLinkedList.java
@@ -1,4 +1,4 @@
-package com.rampatra.common;
+package com.rampatra.base;
import java.util.NoSuchElementException;
@@ -7,8 +7,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/16/15
+ * @author rampatra
+ * @since 6/16/15
* @time: 1:00 PM
*/
public class DoubleLinkedList> implements LinkedList {
diff --git a/src/main/java/com/rampatra/common/DoubleLinkedNode.java b/src/main/java/com/rampatra/base/DoubleLinkedNode.java
similarity index 86%
rename from src/main/java/com/rampatra/common/DoubleLinkedNode.java
rename to src/main/java/com/rampatra/base/DoubleLinkedNode.java
index 91666f37..7da01c20 100644
--- a/src/main/java/com/rampatra/common/DoubleLinkedNode.java
+++ b/src/main/java/com/rampatra/base/DoubleLinkedNode.java
@@ -1,10 +1,10 @@
-package com.rampatra.common;
+package com.rampatra.base;
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/18/15
+ * @author rampatra
+ * @since 6/18/15
* @time: 2:42 PM
*/
public class DoubleLinkedNode> {
diff --git a/src/main/java/com/rampatra/base/Graph.java b/src/main/java/com/rampatra/base/Graph.java
new file mode 100644
index 00000000..0de77ba1
--- /dev/null
+++ b/src/main/java/com/rampatra/base/Graph.java
@@ -0,0 +1,10 @@
+package com.rampatra.base;
+
+/**
+ * A rudimentary Graph having all the basic methods.
+ *
+ * @author rampatra
+ * @since 2019-02-10
+ */
+public class Graph> {
+}
diff --git a/src/main/java/com/rampatra/base/GraphNode.java b/src/main/java/com/rampatra/base/GraphNode.java
new file mode 100644
index 00000000..90f98478
--- /dev/null
+++ b/src/main/java/com/rampatra/base/GraphNode.java
@@ -0,0 +1,37 @@
+package com.rampatra.base;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * The class for a node in a graph. Ideally, you should make member variable {@code private} and have
+ * getters, setters, etc. but to keep it simple, I have omitted all those boilerplate code.
+ *
+ * @author rampatra
+ * @since 2019-02-10
+ */
+public class GraphNode> {
+ public E value;
+ public Set> adjacentNodes = new HashSet<>();
+
+ public GraphNode(E value) {
+ this(value, null);
+ }
+
+ public GraphNode(E value, Set> adjacentNodes) {
+ this.value = value;
+ if (adjacentNodes != null) {
+ this.adjacentNodes = adjacentNodes;
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ GraphNode> graphNode = (GraphNode>) o;
+
+ return value.equals(graphNode.value);
+ }
+}
diff --git a/src/main/java/com/rampatra/common/LinkedList.java b/src/main/java/com/rampatra/base/LinkedList.java
similarity index 95%
rename from src/main/java/com/rampatra/common/LinkedList.java
rename to src/main/java/com/rampatra/base/LinkedList.java
index 1b15bcb4..cd45a2d5 100644
--- a/src/main/java/com/rampatra/common/LinkedList.java
+++ b/src/main/java/com/rampatra/base/LinkedList.java
@@ -1,11 +1,10 @@
-package com.rampatra.common;
+package com.rampatra.base;
/**
- * Created by IntelliJ IDEA.
+ * A generic interface for LinkedList.
*
- * @author: ramswaroop
- * @date: 6/16/15
- * @time: 12:53 PM
+ * @author rampatra
+ * @since 6/16/15
*/
public interface LinkedList> {
diff --git a/src/main/java/com/rampatra/common/LinkedQueue.java b/src/main/java/com/rampatra/base/LinkedQueue.java
similarity index 81%
rename from src/main/java/com/rampatra/common/LinkedQueue.java
rename to src/main/java/com/rampatra/base/LinkedQueue.java
index fd7fb92c..3e4c472d 100644
--- a/src/main/java/com/rampatra/common/LinkedQueue.java
+++ b/src/main/java/com/rampatra/base/LinkedQueue.java
@@ -1,13 +1,12 @@
-package com.rampatra.common;
+package com.rampatra.base;
import java.util.NoSuchElementException;
/**
- * Created by IntelliJ IDEA.
- * User: ramswaroop
- * Date: 4/12/15
- * Time: 11:07 AM
- * To change this template go to Preferences | IDE Settings | File and Code Templates
+ * Queue implementation using a singly linked list with two pointers.
+ *
+ * @author rampatra
+ * @since 4/12/15
*/
public class LinkedQueue implements Queue {
@@ -32,7 +31,7 @@ public E add(E item) {
@Override
public E remove() {
- if (rear.next == front) {
+ if (front == null) {
throw new NoSuchElementException();
}
E item = element();
@@ -51,7 +50,7 @@ public E element() {
@Override
public int size() {
int count = 0;
- if (rear.next == front) return count;
+ if (front == null) return count;
for (Node node = front; node != rear; node = node.next) {
count++;
}
@@ -60,14 +59,14 @@ public int size() {
@Override
public boolean isEmpty() {
- return rear.next == front;
+ return front == null;
}
@Override
public void print() {
Node node;
System.out.print("[");
- if (rear.next == front) {
+ if (front == null) {
System.out.println("]");
return;
}
diff --git a/src/main/java/com/rampatra/common/LinkedStack.java b/src/main/java/com/rampatra/base/LinkedStack.java
similarity index 87%
rename from src/main/java/com/rampatra/common/LinkedStack.java
rename to src/main/java/com/rampatra/base/LinkedStack.java
index 98a72f28..d41c8945 100644
--- a/src/main/java/com/rampatra/common/LinkedStack.java
+++ b/src/main/java/com/rampatra/base/LinkedStack.java
@@ -1,21 +1,13 @@
-package com.rampatra.common;
-
+package com.rampatra.base;
import java.util.EmptyStackException;
/**
- * Created by IntelliJ IDEA.
- * User: ramswaroop
- * Date: 3/24/15
- * Time: 3:02 PM
- * To change this template go to Preferences | IDE Settings | File and Code Templates
- */
-
-/**
- * Stack implementation using
- * a singly linked list.
+ * Stack implementation using a singly linked list.
*
- * @param
+ * @param the data type to be stored in the stack
+ * @author rampatra
+ * @since 3/24/15
*/
public class LinkedStack implements Stack {
diff --git a/src/main/java/com/rampatra/common/MaxHeap.java b/src/main/java/com/rampatra/base/MaxHeap.java
similarity index 95%
rename from src/main/java/com/rampatra/common/MaxHeap.java
rename to src/main/java/com/rampatra/base/MaxHeap.java
index ba7b4a2b..22b36cfa 100644
--- a/src/main/java/com/rampatra/common/MaxHeap.java
+++ b/src/main/java/com/rampatra/base/MaxHeap.java
@@ -1,12 +1,10 @@
-package com.rampatra.common;
+package com.rampatra.base;
import com.rampatra.sorting.HeapSort;
import java.util.Arrays;
/**
- * Created by IntelliJ IDEA.
- *
* A HEAP is a specialized tree-based ABSTRACT DATA TYPE that satisfies the heap property:
* min-heap: All non-leaf elements are either smaller than or equal to their left and right child.
* max-heap: All non-leaf elements are either greater than or equal to their left and right child.
@@ -19,11 +17,10 @@
* Therefore, buildMaxHeap() would take O(n log n) time BUT IF OBSERVED CAREFULLY IT TAKES 0(N) TIME.
*
* Used in the HeapSort algorithm. Also can be used to implement a PriorityQueue.
+ * Learn more
*
- * @author: ramswaroop
- * @date: 8/2/15
- * @time: 11:57 AM
- * @see: http://staff.ustc.edu.cn/~csli/graduate/algorithms/book6/chap07.htm
+ * @author rampatra
+ * @since 8/2/15
*/
public class MaxHeap {
diff --git a/src/main/java/com/rampatra/common/MinHeap.java b/src/main/java/com/rampatra/base/MinHeap.java
similarity index 87%
rename from src/main/java/com/rampatra/common/MinHeap.java
rename to src/main/java/com/rampatra/base/MinHeap.java
index b9e69ca3..6e7b7df1 100644
--- a/src/main/java/com/rampatra/common/MinHeap.java
+++ b/src/main/java/com/rampatra/base/MinHeap.java
@@ -1,10 +1,8 @@
-package com.rampatra.common;
+package com.rampatra.base;
import java.util.Arrays;
/**
- * Created by IntelliJ IDEA.
- *
* A HEAP is a specialized tree-based ABSTRACT DATA TYPE that satisfies the heap property:
* min-heap: All non-leaf elements are either smaller than or equal to their left and right child.
* max-heap: All non-leaf elements are either greater than or equal to their left and right child.
@@ -17,16 +15,15 @@
* Therefore, buildMinHeap() would take O(n log n) time BUT IF OBSERVED CAREFULLY IT TAKES 0(N) TIME.
*
* Used in the HeapSort algorithm. Also can be used to implement a PriorityQueue.
+ * Learn more
*
- * @author: ramswaroop
- * @date: 8/2/15
- * @time: 11:57 AM
- * @see: http://staff.ustc.edu.cn/~csli/graduate/algorithms/book6/chap07.htm
+ * @author rampatra
+ * @since 8/2/15
*/
public class MinHeap {
- int[] heap;
- int size;
+ private int[] heap;
+ private int size;
public MinHeap(int[] heap) {
this.size = heap.length;
@@ -42,20 +39,20 @@ public MinHeap(int[] heap) {
* @param index
*/
public void minHeapify(int index) {
- int smallest = index;
+ int minIndex = index;
int leftIndex = 2 * index + 1;
int rightIndex = 2 * index + 2;
if (leftIndex < size && heap[index] > heap[leftIndex]) {
- smallest = leftIndex;
+ minIndex = leftIndex;
}
- if (rightIndex < size && heap[smallest] > heap[rightIndex]) {
- smallest = rightIndex;
+ if (rightIndex < size && heap[minIndex] > heap[rightIndex]) {
+ minIndex = rightIndex;
}
- if (smallest != index) {
- swap(index, smallest);
- minHeapify(smallest);
+ if (minIndex != index) {
+ swap(index, minIndex);
+ minHeapify(minIndex);
}
}
@@ -143,4 +140,4 @@ public static void main(String[] args) {
minHeap.insert(0);
minHeap.printHeap();
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/rampatra/common/Queue.java b/src/main/java/com/rampatra/base/Queue.java
similarity index 81%
rename from src/main/java/com/rampatra/common/Queue.java
rename to src/main/java/com/rampatra/base/Queue.java
index 822d7df7..660fcb90 100644
--- a/src/main/java/com/rampatra/common/Queue.java
+++ b/src/main/java/com/rampatra/base/Queue.java
@@ -1,11 +1,10 @@
-package com.rampatra.common;
+package com.rampatra.base;
/**
- * Created by IntelliJ IDEA.
- * User: ramswaroop
- * Date: 4/12/15
- * Time: 10:39 AM
- * To change this template go to Preferences | IDE Settings | File and Code Templates
+ * A generic interface for a queue.
+ *
+ * @author rampatra
+ * @since 4/12/15
*/
public interface Queue {
diff --git a/src/main/java/com/rampatra/common/SingleLinkedList.java b/src/main/java/com/rampatra/base/SingleLinkedList.java
similarity index 99%
rename from src/main/java/com/rampatra/common/SingleLinkedList.java
rename to src/main/java/com/rampatra/base/SingleLinkedList.java
index 56d62a08..d52484cb 100644
--- a/src/main/java/com/rampatra/common/SingleLinkedList.java
+++ b/src/main/java/com/rampatra/base/SingleLinkedList.java
@@ -1,4 +1,4 @@
-package com.rampatra.common;
+package com.rampatra.base;
import java.util.NoSuchElementException;
@@ -7,8 +7,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/16/15
+ * @author rampatra
+ * @since 6/16/15
* @time: 1:00 PM
*/
public class SingleLinkedList> implements LinkedList {
diff --git a/src/main/java/com/rampatra/common/SingleLinkedNode.java b/src/main/java/com/rampatra/base/SingleLinkedNode.java
similarity index 84%
rename from src/main/java/com/rampatra/common/SingleLinkedNode.java
rename to src/main/java/com/rampatra/base/SingleLinkedNode.java
index 9e0f73ae..97cd9a05 100644
--- a/src/main/java/com/rampatra/common/SingleLinkedNode.java
+++ b/src/main/java/com/rampatra/base/SingleLinkedNode.java
@@ -1,10 +1,10 @@
-package com.rampatra.common;
+package com.rampatra.base;
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/18/15
+ * @author rampatra
+ * @since 6/18/15
* @time: 2:37 PM
*/
public class SingleLinkedNode> {
diff --git a/src/main/java/com/rampatra/common/Stack.java b/src/main/java/com/rampatra/base/Stack.java
similarity index 81%
rename from src/main/java/com/rampatra/common/Stack.java
rename to src/main/java/com/rampatra/base/Stack.java
index 199aed7d..3761052a 100644
--- a/src/main/java/com/rampatra/common/Stack.java
+++ b/src/main/java/com/rampatra/base/Stack.java
@@ -1,11 +1,10 @@
-package com.rampatra.common;
+package com.rampatra.base;
/**
- * Created by IntelliJ IDEA.
- * User: ramswaroop
- * Date: 4/3/15
- * Time: 9:47 AM
- * To change this template go to Preferences | IDE Settings | File and Code Templates
+ * A generic interface for a stack.
+ *
+ * @author rampatra
+ * @since 4/3/15
*/
public interface Stack {
/**
diff --git a/src/main/java/com/rampatra/common/Tree.java b/src/main/java/com/rampatra/base/Tree.java
similarity index 80%
rename from src/main/java/com/rampatra/common/Tree.java
rename to src/main/java/com/rampatra/base/Tree.java
index 6dc0aecf..56c8b338 100644
--- a/src/main/java/com/rampatra/common/Tree.java
+++ b/src/main/java/com/rampatra/base/Tree.java
@@ -1,8 +1,8 @@
-package com.rampatra.common;
+package com.rampatra.base;
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 4/19/15
* Time: 6:30 PM
* To change this template go to Preferences | IDE Settings | File and Code Templates
diff --git a/src/main/java/com/rampatra/base/Trie.java b/src/main/java/com/rampatra/base/Trie.java
new file mode 100644
index 00000000..65cb7cbb
--- /dev/null
+++ b/src/main/java/com/rampatra/base/Trie.java
@@ -0,0 +1,91 @@
+package com.rampatra.base;
+
+import java.util.HashMap;
+
+/**
+ * Trie also called digital tree and sometimes radix tree or prefix tree (as they can be
+ * searched by prefixes), is an ordered tree data structure that is used to store a dynamic
+ * set or associative array where the keys are usually strings.
+ *
+ * You can think it as HashMap of HashMap of HashMap and so on. Each key in the HashMap is a
+ * single digit/letter of the data you want to store and {@code data} is the final full word
+ * you want to save in trie.
+ *
+ * Some resources:
+ * Trie Data Structure
+ * More about Tries
+ * Video explanation from Gayle McDowell
+ *
+ * @author rampatra
+ * @since 9/22/15
+ */
+public class Trie {
+
+ private class TrieNode {
+ char ch;
+ HashMap> children = new HashMap<>();
+ boolean isCompleteWord; // to mark a complete word in the tri data structure
+
+ TrieNode(char ch) {
+ this.ch = ch;
+ }
+ }
+
+ private TrieNode root;
+
+ Trie() {
+ root = new TrieNode<>('0');
+ }
+
+ /**
+ * Inserts {@code data} in trie.
+ *
+ * @param str
+ */
+ public void insert(String str) {
+ char c;
+ TrieNode curr = root;
+
+ for (int i = 0; i < str.length(); i++) {
+ c = str.charAt(i);
+ curr.children.putIfAbsent(c, new TrieNode<>(c));
+ curr = curr.children.get(c);
+ }
+
+ curr.isCompleteWord = true;
+ }
+
+ /**
+ * Searches {@code data} in trie.
+ *
+ * @param str the value to search.
+ * @return {@code true} if {@code str} is present, {@code false} otherwise.
+ */
+ public boolean search(String str) {
+
+ TrieNode curr = root;
+
+ for (int i = 0; i < str.length(); i++) {
+ if (curr.children.get(str.charAt(i)) == null) {
+ return false;
+ }
+ curr = curr.children.get(str.charAt(i));
+ }
+
+ return curr.isCompleteWord;
+ }
+
+ // unit testing
+ public static void main(String[] args) {
+ Trie trie = new Trie();
+ trie.insert("ram");
+ trie.insert("r");
+ trie.insert("rama");
+ trie.insert("rampatra");
+ System.out.println(trie.search("ram"));
+ System.out.println(trie.search("r"));
+ System.out.println(trie.search("ra"));
+ System.out.println(trie.search("raz"));
+ System.out.println(trie.search("rampatra"));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/rampatra/base/UndirectedGraph.java b/src/main/java/com/rampatra/base/UndirectedGraph.java
new file mode 100644
index 00000000..661fa45a
--- /dev/null
+++ b/src/main/java/com/rampatra/base/UndirectedGraph.java
@@ -0,0 +1,166 @@
+package com.rampatra.base;
+
+import java.util.ArrayDeque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * @author rampatra
+ * @since 2019-02-14
+ */
+public class UndirectedGraph> extends Graph {
+ // map for a fast lookup
+ private Map> nodes = new HashMap<>();
+
+ /**
+ * Adds an edge between a node with value {@code value} and another node with value {@code adjacentValue}. As the
+ * graph is undirected, the edges are added in both the nodes. If nodes with respective values are not present in
+ * the graph then this method creates the nodes.
+ *
+ * @param value refers to the value for first node
+ * @param adjacentValue refers to the value for the second node
+ * @return the node with value {@code value}, or the first node
+ */
+ public GraphNode addEdge(E value, E adjacentValue) {
+ GraphNode node = nodes.get(value);
+ GraphNode adjNode = nodes.get(adjacentValue);
+ if (node == null && value != null) {
+ node = new GraphNode<>(value);
+ nodes.put(value, node);
+ }
+ if (adjNode == null && adjacentValue != null) {
+ adjNode = new GraphNode<>(adjacentValue);
+ nodes.put(adjacentValue, adjNode);
+ }
+ if (node != null && adjNode != null) {
+ node.adjacentNodes.add(adjNode);
+ adjNode.adjacentNodes.add(node); // as this is an undirected graph
+ }
+ return node;
+ }
+
+ /**
+ * Method to check whether {@code src} and {@code dest} nodes are connected by depth first search (DFS).
+ *
+ * @param src source node in graph
+ * @param dest destination node in graph
+ * @return {@code true} if there is a path from {@code src} to {@code dest}, {@code false} otherwise
+ */
+ public boolean hasPathDFS(E src, E dest) {
+ GraphNode s = nodes.get(src);
+ GraphNode d = nodes.get(dest);
+ Set> visited = new HashSet<>(); // to save all visited nodes so that we do not visit them again
+ return hasPathDFS(s, d, visited);
+ }
+
+ private boolean hasPathDFS(GraphNode src, GraphNode dest, Set> visited) {
+ if (src == null || dest == null) {
+ return false;
+ }
+ if (src.value.compareTo(dest.value) == 0) {
+ return true;
+ } else if (!visited.contains(src)) {
+ visited.add(src);
+ for (GraphNode node : src.adjacentNodes) {
+ if (hasPathDFS(node, dest, visited)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Method to check whether {@code src} and {@code dest} nodes are connected by breadth first search (BFS).
+ *
+ * @param src source node in graph
+ * @param dest destination node in graph
+ * @return {@code true} if there is a path from {@code src} to {@code dest}, {@code false} otherwise
+ */
+ public boolean hasPathBFS(E src, E dest) {
+ GraphNode s = nodes.get(src);
+ GraphNode d = nodes.get(dest);
+ if (s == null || d == null) {
+ return false;
+ }
+ Set> visited = new HashSet<>();
+ Queue> toVisit = new ArrayDeque<>();
+ toVisit.add(s);
+ return hasPathBFS(d, visited, toVisit);
+ }
+
+ private boolean hasPathBFS(GraphNode dest, Set> visited, Queue> toVisit) {
+ while (!toVisit.isEmpty()) {
+ GraphNode node = toVisit.poll();
+ if (visited.contains(node)) {
+ continue;
+ } else {
+ visited.add(node);
+ }
+ toVisit.addAll(node.adjacentNodes.stream().filter(n -> !visited.contains(n)).collect(Collectors.toList()));
+ if (node.value.compareTo(dest.value) == 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Prints the node values in the graph.
+ */
+ public void print() {
+ Set visited = new HashSet<>();
+ System.out.print("[");
+ Iterator iterator = nodes.keySet().iterator();
+ while (iterator.hasNext()) {
+ E node = iterator.next();
+ if (!visited.contains(node)) {
+ visited.add(node);
+ System.out.print(node);
+ if (iterator.hasNext()) {
+ System.out.print(", ");
+ }
+ }
+ }
+ System.out.println("]");
+ }
+
+ public static void main(String[] args) {
+ UndirectedGraph graph = new UndirectedGraph<>();
+ graph.addEdge(1, 4);
+ graph.addEdge(4, 5);
+ graph.addEdge(4, 6);
+ graph.addEdge(4, 7);
+ graph.addEdge(5, 1);
+ graph.addEdge(5, 6);
+ graph.addEdge(8, null);
+ graph.addEdge(null, 9);
+ graph.print();
+
+ System.out.println("----");
+
+ // has path DFS
+ System.out.println(graph.hasPathDFS(1, 5));
+ System.out.println(graph.hasPathDFS(1, 6));
+ System.out.println(graph.hasPathDFS(1, 8));
+ System.out.println(graph.hasPathDFS(4, 8));
+ System.out.println(graph.hasPathDFS(4, 9));
+ System.out.println(graph.hasPathDFS(4, 100));
+
+ System.out.println("----");
+
+ // has path BFS
+ System.out.println(graph.hasPathBFS(1, 5));
+ System.out.println(graph.hasPathBFS(1, 6));
+ System.out.println(graph.hasPathBFS(1, 8));
+ System.out.println(graph.hasPathBFS(4, 8));
+ System.out.println(graph.hasPathBFS(4, 9));
+ System.out.println(graph.hasPathBFS(4, 100));
+ }
+}
diff --git a/src/main/java/com/rampatra/bits/AbsWithoutBranching.java b/src/main/java/com/rampatra/bits/AbsWithoutBranching.java
index 4d7e61eb..53973b6a 100644
--- a/src/main/java/com/rampatra/bits/AbsWithoutBranching.java
+++ b/src/main/java/com/rampatra/bits/AbsWithoutBranching.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/9/15
+ * @author rampatra
+ * @since 6/9/15
* @time: 12:26 PM
*/
public class AbsWithoutBranching {
@@ -28,7 +28,7 @@ public static int abs(int n) {
return (mask + n) ^ mask;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(abs(-5));
System.out.println(abs(5));
System.out.println(abs(0));
diff --git a/src/main/java/com/rampatra/bits/Addition.java b/src/main/java/com/rampatra/bits/Addition.java
index 475e1bc3..c120ecaa 100644
--- a/src/main/java/com/rampatra/bits/Addition.java
+++ b/src/main/java/com/rampatra/bits/Addition.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/10/15
+ * @author rampatra
+ * @since 6/10/15
* @time: 12:55 PM
*/
public class Addition {
@@ -95,7 +95,7 @@ public static int addByFlip(int n) {
return n ^ mask;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(add(0, 0)); //0
System.out.println(add(12, 12)); //24
System.out.println(add(12, 5)); //17
diff --git a/src/main/java/com/rampatra/bits/BinaryGap.java b/src/main/java/com/rampatra/bits/BinaryGap.java
index 9bb95f9d..a89c1a29 100644
--- a/src/main/java/com/rampatra/bits/BinaryGap.java
+++ b/src/main/java/com/rampatra/bits/BinaryGap.java
@@ -1,7 +1,7 @@
package com.rampatra.bits;
/**
- * Created by ramswaroop on 30/05/2016.
+ * Created by rampatra on 30/05/2016.
*/
public class BinaryGap {
diff --git a/src/main/java/com/rampatra/bits/BinaryString.java b/src/main/java/com/rampatra/bits/BinaryString.java
new file mode 100644
index 00000000..ad0ffb84
--- /dev/null
+++ b/src/main/java/com/rampatra/bits/BinaryString.java
@@ -0,0 +1,28 @@
+package com.rampatra.bits;
+
+/**
+ * @author rampatra
+ * @since 2019-03-21
+ */
+public class BinaryString {
+
+ /**
+ * Returns the binary representation of a {@code byte}.
+ *
+ * @param b a byte.
+ * @return the binary representation of the input byte.
+ */
+ private static String toBinaryString(byte b) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < Byte.SIZE; i++) {
+ sb.append(b & (byte) 1);
+ b >>= 1;
+ }
+ return sb.reverse().toString();
+ }
+
+ public static void main(String[] args) {
+ System.out.println(toBinaryString((byte) 0xff));
+ System.out.println(toBinaryString((byte) (0xff >> 3)));
+ }
+}
diff --git a/src/main/java/com/rampatra/bits/BooleanArrayPuzzle.java b/src/main/java/com/rampatra/bits/BooleanArrayPuzzle.java
index e1117af8..d3d87feb 100644
--- a/src/main/java/com/rampatra/bits/BooleanArrayPuzzle.java
+++ b/src/main/java/com/rampatra/bits/BooleanArrayPuzzle.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/12/15
+ * @author rampatra
+ * @since 6/12/15
* @time: 3:31 PM
*/
public class BooleanArrayPuzzle {
@@ -23,7 +23,7 @@ public static int[] change1To0InArray(int a[]) {
return a;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(change1To0InArray(new int[]{0, 0})));
System.out.println(Arrays.toString(change1To0InArray(new int[]{0, 1})));
System.out.println(Arrays.toString(change1To0InArray(new int[]{1, 0})));
diff --git a/src/main/java/com/rampatra/bits/ConvertAToB.java b/src/main/java/com/rampatra/bits/ConvertAToB.java
index b9844bd6..07c162b8 100644
--- a/src/main/java/com/rampatra/bits/ConvertAToB.java
+++ b/src/main/java/com/rampatra/bits/ConvertAToB.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/7/15
+ * @author rampatra
+ * @since 6/7/15
* @time: 1:53 PM
*/
public class ConvertAToB {
@@ -21,7 +21,7 @@ public static int getBitsToConvertAToB(int a, int b) {
return CountSetBits.countSetBits(a ^ b);
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getBitsToConvertAToB(3, 4));
System.out.println(getBitsToConvertAToB(3, 5));
System.out.println(getBitsToConvertAToB(5, 3));
diff --git a/src/main/java/com/rampatra/bits/CountSetBits.java b/src/main/java/com/rampatra/bits/CountSetBits.java
index dda9bbcf..a2296e6e 100644
--- a/src/main/java/com/rampatra/bits/CountSetBits.java
+++ b/src/main/java/com/rampatra/bits/CountSetBits.java
@@ -4,7 +4,7 @@
/**
* Created by IntelliJ IDEA.
- * User: ramswaroop
+ * User: rampatra
* Date: 4/4/15
* Time: 8:52 PM
* To change this template go to Preferences | IDE Settings | File and Code Templates
@@ -48,7 +48,7 @@ static int countSetBits(long n) {
return count;
}
- public static void main(String[] a) {
+ public static void main(String[] args) {
Scanner in = new Scanner(System.in);
long n = Long.parseLong(in.nextLine());
diff --git a/src/main/java/com/rampatra/bits/CountSetBitsFromMinusNtoN.java b/src/main/java/com/rampatra/bits/CountSetBitsFromMinusNtoN.java
index 5b5143e0..a0aeb5e0 100644
--- a/src/main/java/com/rampatra/bits/CountSetBitsFromMinusNtoN.java
+++ b/src/main/java/com/rampatra/bits/CountSetBitsFromMinusNtoN.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 7/22/15
+ * @author rampatra
+ * @since 7/22/15
* @time: 12:42 PM
*/
public class CountSetBitsFromMinusNtoN {
@@ -30,7 +30,7 @@ public static int countSetBitsFromMinusNtoN(int n) {
return n * 32 + CountSetBits.countSetBits((long) n); // 32 because int is of 32 bits in java
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(countSetBitsFromMinusNtoN(3));
System.out.println(countSetBitsFromMinusNtoN(0));
System.out.println(countSetBitsFromMinusNtoN(9));
diff --git a/src/main/java/com/rampatra/bits/ElementOccurringOnce.java b/src/main/java/com/rampatra/bits/ElementOccurringOnce.java
index 27fe37d9..4621209c 100644
--- a/src/main/java/com/rampatra/bits/ElementOccurringOnce.java
+++ b/src/main/java/com/rampatra/bits/ElementOccurringOnce.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/14/15
+ * @author rampatra
+ * @since 6/14/15
* @time: 12:37 AM
*/
public class ElementOccurringOnce {
@@ -30,7 +30,7 @@ public static int getElementOccurringOnceInElementsRepeatedThreeTimes(int a[]) {
return result;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getElementOccurringOnceInElementsRepeatedThreeTimes(new int[]{12, 12, 6, 6, 2, 12, 6}));
System.out.println(getElementOccurringOnceInElementsRepeatedThreeTimes(new int[]{5, 5, 45, 45, 456, 5, 45}));
System.out.println(getElementOccurringOnceInElementsRepeatedThreeTimes(new int[]{12, 12, 34, 34, 6, 12, 34}));
diff --git a/src/main/java/com/rampatra/bits/FlippingBits.java b/src/main/java/com/rampatra/bits/FlippingBits.java
index 22491e5d..48c891ad 100644
--- a/src/main/java/com/rampatra/bits/FlippingBits.java
+++ b/src/main/java/com/rampatra/bits/FlippingBits.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/5/15
+ * @author rampatra
+ * @since 6/5/15
* @time: 3:50 PM
*/
public class FlippingBits {
@@ -31,7 +31,7 @@ public static int getNumberByFlippingBits_V1(int n) {
return ~n;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getNumberByFlippingBits(5));
System.out.println(getNumberByFlippingBits_V1(5));
}
diff --git a/src/main/java/com/rampatra/bits/IntegerOverflow.java b/src/main/java/com/rampatra/bits/IntegerOverflow.java
index 27e5fb16..6d214ac8 100644
--- a/src/main/java/com/rampatra/bits/IntegerOverflow.java
+++ b/src/main/java/com/rampatra/bits/IntegerOverflow.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/4/15
+ * @author rampatra
+ * @since 6/4/15
* @time: 4:28 PM
*/
public class IntegerOverflow {
@@ -43,7 +43,7 @@ public static int add_V1(int a, int b) throws Exception {
}
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
try {
System.out.println(add(2, 3));
System.out.println(add(2147483647, 999999999));
diff --git a/src/main/java/com/rampatra/bits/LittleAndBigEndian.java b/src/main/java/com/rampatra/bits/LittleAndBigEndian.java
index 6fbed3aa..86ca46e9 100644
--- a/src/main/java/com/rampatra/bits/LittleAndBigEndian.java
+++ b/src/main/java/com/rampatra/bits/LittleAndBigEndian.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/5/15
+ * @author rampatra
+ * @since 6/5/15
* @time: 3:10 PM
* @link http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html
*/
@@ -16,7 +16,7 @@ public static boolean isLittleEndian() {
return ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN);
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(isLittleEndian());
}
}
diff --git a/src/main/java/com/rampatra/bits/MaxWithoutBranching.java b/src/main/java/com/rampatra/bits/MaxWithoutBranching.java
index 2e657705..f2669829 100644
--- a/src/main/java/com/rampatra/bits/MaxWithoutBranching.java
+++ b/src/main/java/com/rampatra/bits/MaxWithoutBranching.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/8/15
+ * @author rampatra
+ * @since 6/8/15
* @time: 5:41 PM
* @link: http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
*/
@@ -18,7 +18,7 @@ public static int getMaxWithoutBranching(int a, int b) {
return a ^ ((a ^ b) & -((a < b) ? 1 : 0));
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getMinWithoutBranching(5, 6));
System.out.println(getMinWithoutBranching(-5, -6));
System.out.println(getMinWithoutBranching(-5, 6));
diff --git a/src/main/java/com/rampatra/bits/Modulo.java b/src/main/java/com/rampatra/bits/Modulo.java
index 949e08e0..d220f3a8 100644
--- a/src/main/java/com/rampatra/bits/Modulo.java
+++ b/src/main/java/com/rampatra/bits/Modulo.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/8/15
+ * @author rampatra
+ * @since 6/8/15
* @time: 11:28 PM
*/
public class Modulo {
@@ -21,7 +21,7 @@ public static int getNmoduloD(int n, int d) {
return n & (d - 1);
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getNmoduloD(18, 8));
System.out.println(getNmoduloD(18, 4));
System.out.println(getNmoduloD(13, 4));
diff --git a/src/main/java/com/rampatra/bits/MultipleOf3.java b/src/main/java/com/rampatra/bits/MultipleOf3.java
index 4215f9b6..87af5c1d 100644
--- a/src/main/java/com/rampatra/bits/MultipleOf3.java
+++ b/src/main/java/com/rampatra/bits/MultipleOf3.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/3/15
+ * @author rampatra
+ * @since 6/3/15
* @time: 1:18 PM
*/
public class MultipleOf3 {
@@ -39,7 +39,7 @@ public static boolean isMultipleOf3(long n) {
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(isMultipleOf3(0));
System.out.println(isMultipleOf3(1));
System.out.println(isMultipleOf3(2));
diff --git a/src/main/java/com/rampatra/bits/Multiply.java b/src/main/java/com/rampatra/bits/Multiply.java
index 8750d138..edc2e421 100644
--- a/src/main/java/com/rampatra/bits/Multiply.java
+++ b/src/main/java/com/rampatra/bits/Multiply.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/3/15
+ * @author rampatra
+ * @since 6/3/15
* @time: 11:35 PM
*/
@@ -60,7 +60,7 @@ public static long multiplyWith8(long n) {
return (n << 3);
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(multiplyWith3point5(3));
System.out.println(multiplyWith3point5(4));
System.out.println(multiplyWith3point5(6));
diff --git a/src/main/java/com/rampatra/bits/NextHigherNumber.java b/src/main/java/com/rampatra/bits/NextHigherNumber.java
index 98d0fecb..444dcf99 100644
--- a/src/main/java/com/rampatra/bits/NextHigherNumber.java
+++ b/src/main/java/com/rampatra/bits/NextHigherNumber.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/10/15
+ * @author rampatra
+ * @since 6/10/15
* @time: 6:08 PM
*/
public class NextHigherNumber {
@@ -47,7 +47,7 @@ public static int getNextHigherNumberWithSameSetBits(int n) {
return (n << count) | (leftPattern << count) | (rightPattern >> 1);
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getNextHigherNumberWithSameSetBits(0));//doesn't work for 0
System.out.println(getNextHigherNumberWithSameSetBits(4));//8
System.out.println(getNextHigherNumberWithSameSetBits(5));//6
diff --git a/src/main/java/com/rampatra/bits/NextPowerOf2.java b/src/main/java/com/rampatra/bits/NextPowerOf2.java
index f3092064..44c04491 100644
--- a/src/main/java/com/rampatra/bits/NextPowerOf2.java
+++ b/src/main/java/com/rampatra/bits/NextPowerOf2.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/2/15
+ * @author rampatra
+ * @since 6/2/15
* @time: 5:08 PM
*/
public class NextPowerOf2 {
@@ -100,7 +100,7 @@ public static long nextLowerPowerOf2(long n) {
return (n > 1) ? p >> 1 : n; // check for n = 0 or 1;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(nextHigherPowerOf2(2));
System.out.println(nextHigherPowerOf2(3));
diff --git a/src/main/java/com/rampatra/bits/OppositeSign.java b/src/main/java/com/rampatra/bits/OppositeSign.java
index b017d90e..919d2137 100644
--- a/src/main/java/com/rampatra/bits/OppositeSign.java
+++ b/src/main/java/com/rampatra/bits/OppositeSign.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/14/15
+ * @author rampatra
+ * @since 6/14/15
* @time: 12:24 AM
*/
public class OppositeSign {
@@ -13,7 +13,7 @@ public static int isOppositeSign(int a, int b) {
return (a ^ b) >>> 31;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(isOppositeSign(-5, -3));
System.out.println(isOppositeSign(-5, 3));
System.out.println(isOppositeSign(5, -3));
diff --git a/src/main/java/com/rampatra/bits/Parity.java b/src/main/java/com/rampatra/bits/Parity.java
index 61cd27e9..673ba5b3 100644
--- a/src/main/java/com/rampatra/bits/Parity.java
+++ b/src/main/java/com/rampatra/bits/Parity.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/3/15
+ * @author rampatra
+ * @since 6/3/15
* @time: 3:50 PM
*/
@@ -54,7 +54,7 @@ public static boolean isEvenParityByCountingSetBits(long n) {
return setBitsCount % 2 == 0;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(isEvenParity(0));
System.out.println(isEvenParity(1));
System.out.println(isEvenParity(5));
diff --git a/src/main/java/com/rampatra/bits/PowerOf2.java b/src/main/java/com/rampatra/bits/PowerOf2.java
index 372e0212..04a1d9dd 100644
--- a/src/main/java/com/rampatra/bits/PowerOf2.java
+++ b/src/main/java/com/rampatra/bits/PowerOf2.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/2/15
+ * @author rampatra
+ * @since 6/2/15
* @time: 12:18 PM
*/
public class PowerOf2 {
@@ -40,7 +40,7 @@ public static boolean isPowerOf2FromRandomClass(long n) {
return n != 0 && (n & -n) == n;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(isPowerOf2(18));
System.out.println(isPowerOf2UsingANDoperator(18));
System.out.println(isPowerOf2FromRandomClass(18));
diff --git a/src/main/java/com/rampatra/bits/PowerOf4.java b/src/main/java/com/rampatra/bits/PowerOf4.java
index 11eb62b9..5b75c4a2 100644
--- a/src/main/java/com/rampatra/bits/PowerOf4.java
+++ b/src/main/java/com/rampatra/bits/PowerOf4.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/9/15
+ * @author rampatra
+ * @since 6/9/15
* @time: 12:56 PM
*/
public class PowerOf4 {
@@ -31,7 +31,7 @@ public static boolean isPowerOf4(int n) {
return false;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(isPowerOf4(0));
System.out.println(isPowerOf4(1));
System.out.println(isPowerOf4(4));
diff --git a/src/main/java/com/rampatra/bits/README.md b/src/main/java/com/rampatra/bits/README.md
new file mode 100644
index 00000000..30119f20
--- /dev/null
+++ b/src/main/java/com/rampatra/bits/README.md
@@ -0,0 +1,122 @@
+# Bits
+
+## Basic Operators
+
+#### AND:
+
+| x | y | x `&` y |
+----|---|:-------:|
+| 0 | 0 | 0 |
+| 0 | 1 | 0 |
+| 1 | 0 | 0 |
+| 1 | 1 | 1 |
+
+#### OR:
+
+| x | y | x `\|` y |
+|---|---|:--------:|
+| 0 | 0 | 0 |
+| 0 | 1 | 1 |
+| 1 | 0 | 1 |
+| 1 | 1 | 1 |
+
+#### XOR:
+
+| x | y | x `^` y |
+|---|---|:-------:|
+| 0 | 0 | 0 |
+| 0 | 1 | 1 |
+| 1 | 0 | 1 |
+| 1 | 1 | 0 |
+
+
+## Shifts
+
+_Disclaimer: We are taking `byte` (8 bits) as our datatype to explain the
+ concepts instead of the usual integer._
+
+#### 1. Left Shift (<<):
+
+1 << 3 = 8
+
+> 00000001 << 3 = 00001000
+
+#### 2. Right Shift:
+
+**Two types:**
+
+**a. Signed Right Shift (>>):**
+
+64 >> 2 = 16
+
+> 001000000 >> 2 = 00010000
+
+-64 >> 2 = -16
+
+> 111000000 >> 2 = 11110000
+
+**b. Unsigned Right Shift (>>>):**
+
+64 >>> 2 = 16
+
+> 001000000 >>> 2 = 00010000
+
+-64 >>> 2 = 56
+
+> 111000000 >>> 2 = 00111000
+
+## Helpful Masks
+
+#### 1. Set the 4th bit from right:
+
+```java
+byte mask = 1 << 3;
+```
+
+Explanation,
+
+```
+00000001 << 3 = 00001000
+```
+
+#### 2. Set the first 3 bits from right:
+
+```java
+byte mask = (1 << 3) - 1;
+```
+
+Explanation,
+
+```
+00000001 << 3 = 00001000
+
+00001000 - 00000001 = 00000111
+```
+
+#### 3. Mask with alternating 1010...10
+
+```java
+byte mask = 0x55;
+```
+
+#### 4. Mask with alternating 0101...01
+
+```java
+byte mask = 0xaa;
+```
+
+#### 5. Unset the 4th bit
+
+```java
+byte mask = 1 << 3;
+
+byte num = num & ~mask;
+```
+
+Explanation,
+
+```
+00000001 << 3 = 00001000
+
+~(00001000) = 11110111
+```
\ No newline at end of file
diff --git a/src/main/java/com/rampatra/bits/ReverseBits.java b/src/main/java/com/rampatra/bits/ReverseBits.java
index 700bd8a0..04f8cc3b 100644
--- a/src/main/java/com/rampatra/bits/ReverseBits.java
+++ b/src/main/java/com/rampatra/bits/ReverseBits.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/5/15
+ * @author rampatra
+ * @since 6/5/15
* @time: 4:26 PM
* @link: http://stackoverflow.com/questions/746171/best-algorithm-for-bit-reversal-from-msb-lsb-to-lsb-msb-in-c
* @link: http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious
@@ -82,7 +82,7 @@ public static int getNumberByReversingBitsV2(int n) {
return reverse;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getNumberByReversingBits(79876));
System.out.println(getNumberByReversingBitsV1(79876));
System.out.println(getNumberByReversingBitsV2(79876));
diff --git a/src/main/java/com/rampatra/bits/RightShiftOperator.java b/src/main/java/com/rampatra/bits/RightShiftOperator.java
index 74774e1b..3eafd7b6 100644
--- a/src/main/java/com/rampatra/bits/RightShiftOperator.java
+++ b/src/main/java/com/rampatra/bits/RightShiftOperator.java
@@ -11,7 +11,7 @@
*/
public class RightShiftOperator {
- public static void main(String a[]) {
+ public static void main(String[] args) {
int n = -4;
System.out.printf("n: %32d\n", n);
System.out.printf("n: %32s\n", Integer.toBinaryString(n));
@@ -44,4 +44,4 @@ public static void main(String a[]) {
System.out.printf("n>>2: %32s\n", Integer.toBinaryString(n >> 2));
System.out.printf("n>>>2: %32s\n", Integer.toBinaryString(n >>> 2));
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/rampatra/bits/RightmostSetBit.java b/src/main/java/com/rampatra/bits/RightmostSetBit.java
index e3b5923c..1916ed64 100644
--- a/src/main/java/com/rampatra/bits/RightmostSetBit.java
+++ b/src/main/java/com/rampatra/bits/RightmostSetBit.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/3/15
+ * @author rampatra
+ * @since 6/3/15
* @time: 11:56 PM
*/
public class RightmostSetBit {
@@ -34,7 +34,7 @@ public static long unsetRightmostSetBit(long n) {
return n & (n - 1); // brian kerningham's algorithm
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getRightmostSetBitPosition(0));
System.out.println(getRightmostSetBitPosition(1));
System.out.println(getRightmostSetBitPosition(2));
diff --git a/src/main/java/com/rampatra/bits/RotateBits.java b/src/main/java/com/rampatra/bits/RotateBits.java
index 9e7dc9ee..9712b028 100644
--- a/src/main/java/com/rampatra/bits/RotateBits.java
+++ b/src/main/java/com/rampatra/bits/RotateBits.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/8/15
+ * @author rampatra
+ * @since 6/8/15
* @time: 5:12 PM
*
* A ROTATION (OR CIRCULAR SHIFT) is an operation similar to
@@ -25,7 +25,7 @@ public static int rightRotateBits(int n, int times) {
return n >>> times | n << (32 - times);
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(leftRotateBits(5, 3));
System.out.println(leftRotateBits(234324, 3));
System.out.println(rightRotateBits(5, 3));
diff --git a/src/main/java/com/rampatra/bits/SmallestOf3Integers.java b/src/main/java/com/rampatra/bits/SmallestOf3Integers.java
index 45c23f78..63e542a9 100644
--- a/src/main/java/com/rampatra/bits/SmallestOf3Integers.java
+++ b/src/main/java/com/rampatra/bits/SmallestOf3Integers.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/12/15
+ * @author rampatra
+ * @since 6/12/15
* @time: 6:18 PM
*/
public class SmallestOf3Integers {
@@ -50,7 +50,7 @@ public static int getSmallest_V1(int a[]) {
return c;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getSmallest(new int[]{4, 5, 6}));
System.out.println(getSmallest_V1(new int[]{4, 5, 6}));
}
diff --git a/src/main/java/com/rampatra/bits/StrCmp.java b/src/main/java/com/rampatra/bits/StrCmp.java
index 00d1f933..4b1be36f 100644
--- a/src/main/java/com/rampatra/bits/StrCmp.java
+++ b/src/main/java/com/rampatra/bits/StrCmp.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/15/15
+ * @author rampatra
+ * @since 6/15/15
* @time: 10:38 AM
*/
public class StrCmp {
@@ -48,7 +48,7 @@ public static int compareStringIgnoreCase(String s1, String s2) {
return n1 - n2;
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(compareStringIgnoreCase("ram", "ram"));
System.out.println(compareStringIgnoreCase("ram", "Ram"));
System.out.println(compareStringIgnoreCase("", ""));
diff --git a/src/main/java/com/rampatra/bits/SubBit.java b/src/main/java/com/rampatra/bits/SubBit.java
index cce40d76..f91a4dd8 100644
--- a/src/main/java/com/rampatra/bits/SubBit.java
+++ b/src/main/java/com/rampatra/bits/SubBit.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/4/15
+ * @author rampatra
+ * @since 6/4/15
* @time: 10:54 PM
*/
public class SubBit {
@@ -22,7 +22,7 @@ public static int getNumberFromSubBits(int num, int start, int end) {
return num << (32 - end) >>> (start - end + 31); // more intuitive (start - 1 + 32 - end)
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(getNumberFromSubBits(5, 1, 2));
}
}
diff --git a/src/main/java/com/rampatra/bits/SwapBits.java b/src/main/java/com/rampatra/bits/SwapBits.java
index 85b4c3b2..40fbb613 100644
--- a/src/main/java/com/rampatra/bits/SwapBits.java
+++ b/src/main/java/com/rampatra/bits/SwapBits.java
@@ -3,8 +3,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/13/15
+ * @author rampatra
+ * @since 6/13/15
* @time: 4:45 PM
*/
public class SwapBits {
@@ -71,7 +71,7 @@ public static int swapBitRangeInNumber(int n, int pos1, int pos2, int length) {
// (this logic is similar to swapping bits using XOR)
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(swapEvenOddBits(23));
System.out.println(swapEvenOddBits(0));
System.out.println(swapEvenOddBits(5));
diff --git a/src/main/java/com/rampatra/bits/TwoNonRepeatingElements.java b/src/main/java/com/rampatra/bits/TwoNonRepeatingElements.java
index 19b6fff1..a3b47f08 100644
--- a/src/main/java/com/rampatra/bits/TwoNonRepeatingElements.java
+++ b/src/main/java/com/rampatra/bits/TwoNonRepeatingElements.java
@@ -5,8 +5,8 @@
/**
* Created by IntelliJ IDEA.
*
- * @author: ramswaroop
- * @date: 6/7/15
+ * @author rampatra
+ * @since 6/7/15
* @time: 2:46 PM
* @link: http://www.geeksforgeeks.org/find-two-non-repeating-elements-in-an-array-of-repeating-elements/
*/
@@ -36,7 +36,7 @@ public static int[] getTwoNonRepeatingElementsInArray(int a[]) {
return new int[]{x, y};
}
- public static void main(String a[]) {
+ public static void main(String[] args) {
System.out.println(Arrays.toString(getTwoNonRepeatingElementsInArray(new int[]{2, 3, 4, 2, 3, 4, 5, 6})));
}
}
diff --git a/src/main/java/com/rampatra/blockchain/Block.java b/src/main/java/com/rampatra/blockchain/Block.java
new file mode 100644
index 00000000..8ba8eab5
--- /dev/null
+++ b/src/main/java/com/rampatra/blockchain/Block.java
@@ -0,0 +1,87 @@
+package com.rampatra.blockchain;
+
+import java.io.Serializable;
+
+/**
+ * @author rampatra
+ * @since 2019-03-05
+ */
+public class Block implements Serializable {
+
+ private int index;
+ private String previousHash;
+ private long timestamp;
+ private String data;
+ private String hash;
+ private int nonce;
+
+ public Block(int index, String previousHash, long timestamp, String data, String hash, int nonce) {
+ this.index = index;
+ this.previousHash = previousHash;
+ this.timestamp = timestamp;
+ this.data = data;
+ this.hash = hash;
+ this.nonce = nonce;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ }
+
+ public String getPreviousHash() {
+ return previousHash;
+ }
+
+ public void setPreviousHash(String previousHash) {
+ this.previousHash = previousHash;
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getHash() {
+ return hash;
+ }
+
+ public void setHash(String hash) {
+ this.hash = hash;
+ }
+
+ public int getNonce() {
+ return nonce;
+ }
+
+ public void setNonce(int nonce) {
+ this.nonce = nonce;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("Block{");
+ sb.append("index=").append(index);
+ sb.append(", previousHash='").append(previousHash).append('\'');
+ sb.append(", timestamp=").append(timestamp);
+ sb.append(", data='").append(data).append('\'');
+ sb.append(", hash='").append(hash).append('\'');
+ sb.append(", nonce=").append(nonce);
+ sb.append('}');
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/rampatra/blockchain/Blockchain.java b/src/main/java/com/rampatra/blockchain/Blockchain.java
new file mode 100644
index 00000000..58fe7813
--- /dev/null
+++ b/src/main/java/com/rampatra/blockchain/Blockchain.java
@@ -0,0 +1,182 @@
+package com.rampatra.blockchain;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Date;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ * @author rampatra
+ * @since 2019-03-05
+ */
+public class Blockchain {
+
+ private List blocks;
+ private int difficulty;
+
+ public Blockchain(List blocks, int difficulty) {
+ this.blocks = blocks;
+ this.difficulty = difficulty;
+ this.blocks.add(getGenesisBlock());
+ }
+
+ public List getBlocks() {
+ return blocks;
+ }
+
+ public int getSize() {
+ return blocks.size();
+ }
+
+ public Block getLatestBlock() {
+ if (blocks.isEmpty()) return null;
+
+ return blocks.get(blocks.size() - 1);
+ }
+
+ public void addBlock(Block block) {
+ blocks.add(block);
+ }
+
+ /**
+ * Mine, create a new block with the {@code data}, and finally, add it to the blockchain.
+ *