From 0685fa7ce761fe292cd8ecc618f30f9e41fe0a6c Mon Sep 17 00:00:00 2001 From: Hakim Date: Sat, 12 Sep 2015 18:52:29 -0400 Subject: [PATCH 1/6] Renamed all files. Added some main methods --- ch1/Solution01.java | 76 ++++++++++++++ ch1/Solution02.java | 49 +++++++++ ch1/Solution03.java | 43 ++++++++ ch1/Solution04.java | 54 ++++++++++ ch1/Solution05.java | 58 +++++++++++ ch1/Solution06.java | 77 ++++++++++++++ ch1/Solution07.java | 88 ++++++++++++++++ ch1/Solution08.java | 150 ++++++++++++++++++++++++++++ ch1/Solution09.java | 39 ++++++++ ch2/Solution01.java | 141 ++++++++++++++++++++++++++ ch2/Solution02.java | 92 +++++++++++++++++ ch2/Solution03.java | 80 +++++++++++++++ ch2/Solution04.java | 108 ++++++++++++++++++++ ch2/Solution05.java | 237 ++++++++++++++++++++++++++++++++++++++++++++ ch2/Solution06.java | 121 ++++++++++++++++++++++ ch2/Solution07.java | 133 +++++++++++++++++++++++++ ch2/Solution08.java | 77 ++++++++++++++ 17 files changed, 1623 insertions(+) create mode 100644 ch1/Solution01.java create mode 100644 ch1/Solution02.java create mode 100644 ch1/Solution03.java create mode 100644 ch1/Solution04.java create mode 100644 ch1/Solution05.java create mode 100644 ch1/Solution06.java create mode 100644 ch1/Solution07.java create mode 100644 ch1/Solution08.java create mode 100644 ch1/Solution09.java create mode 100644 ch2/Solution01.java create mode 100644 ch2/Solution02.java create mode 100644 ch2/Solution03.java create mode 100644 ch2/Solution04.java create mode 100644 ch2/Solution05.java create mode 100644 ch2/Solution06.java create mode 100644 ch2/Solution07.java create mode 100644 ch2/Solution08.java diff --git a/ch1/Solution01.java b/ch1/Solution01.java new file mode 100644 index 0000000..c554b70 --- /dev/null +++ b/ch1/Solution01.java @@ -0,0 +1,76 @@ +import java.util.List; + +/** + * Question 1.1 + * Created by hsidahme on 9/8/15. + */ +public class Solution01 { + public static void main(String[] args){ + Solution01 solution01 = new Solution01(); + + String s1 = "asfgte"; + String s2 = "aasded"; + + System.out.println("isUnique(" + s1 + "): " + solution01.isUnique(s1)); + System.out.println("isUnique(" + s2 + "): " + solution01.isUnique(s2)); + + System.out.println("isUniqueV2(" + s1 + "): " + solution01.isUniqueV2(s1)); + System.out.println("isUniqueV2(" + s2 + "): " + solution01.isUniqueV2(s2)); + + } + + /** + * Determine if String s has all unique characters. + * @param s - Input String + * @return true if all the characters in s are unique. false otherwise + */ + public boolean isUnique(String s){ + // Assume 8-bit ascii encoding (256 possible characters) + if (s.length() > 256){ + return false; + } + + // Create an array in which each element stores the count of the corresponding character + int[] elements = new int[256]; + + for (int i=0; i 1){ + return false; + } + } + + // None of the characters is repeated, return true + return true; + } + + // Follow up: What if you cannot use additional data structures + + /** + * Second version of isUnique that does not use any extra data structure. + * @param s - Input String + * @return true if s has unique characters only. false otherwise + */ + public boolean isUniqueV2(String s){ + // O(n^2) complexity: For each character in s, check that none of the next characters is the same + + if (s == null || s.length() <= 1){ + return true; + } + + for (int i=0; i= 0){ + if (c[pointer1] == ' '){ + c[pointer2] = '0'; + c[pointer2-1] = '2'; + c[pointer2-2] = '%'; + + pointer2 -= 3; + pointer1--; + } + else{ + c[pointer2] = c[pointer1]; + pointer2--; + pointer1--; + } + } + } +} diff --git a/ch1/Solution04.java b/ch1/Solution04.java new file mode 100644 index 0000000..7e61df2 --- /dev/null +++ b/ch1/Solution04.java @@ -0,0 +1,54 @@ +/** + * Created by Hakim on 9/8/15. + */ + +/** + * Check whether a String is the permutation of a palindrome. + */ +public class Solution04 { + public static void main(String[] args){ + Solution04 pp = new Solution04(); + System.out.println(pp.isPalindromePermutation("Tact Coa")); + } + + /** + * Check whether a String is the permutation of a palindrome. + * @param s + * @return true if it is. false otherwise + */ + public boolean isPalindromePermutation(String s){ + // A String is a palindrome permutation iif + // it contains an even count for each character except at most + // one character which can be odd + if (s == null || s.length() == 0){ + return true; + } + + // Lower case the String and remove white spaces + s = s.toLowerCase(); + s = s.replaceAll(" ", ""); + + // Assume 8-bit ascii encoding + boolean[] isOdd = new boolean[256]; + + // For each character c in the input String, save whether it is + // represented an odd number of times + for (int i=0; i 1){ + return false; + } + } + return true; + } +} diff --git a/ch1/Solution05.java b/ch1/Solution05.java new file mode 100644 index 0000000..9eb8f60 --- /dev/null +++ b/ch1/Solution05.java @@ -0,0 +1,58 @@ +/** + * Created by Hakim on 9/8/15. + * Find whether two Strings are less than one edit away + */ +public class Solution05 { + public static void main(String[] args){ + Solution05 oa = new Solution05(); + System.out.println(oa.isOneAway("pale","ple")); + System.out.println(oa.isOneAway("pales","pale")); + System.out.println(oa.isOneAway("pale","bale")); + System.out.println(oa.isOneAway("pale","bake")); + System.out.println(oa.isOneAway("","")); + System.out.println(oa.isOneAway("","e")); + } + + /** + * Check whether two Strings are at most one edit away. + * Possible edits are insertion, deletion, and replacement + * @param s - First input String + * @param t - Second input String + * @return true if s and t are less than one edit away. False otherwise + */ + public boolean isOneAway(String s, String t){ + // If s and t's lengths are different by more than 1, then return false + if (Math.abs(s.length()-t.length()) > 1){ + return false; + } + // Make sure the first input String is greater or equal than the second one + if (s.length() < t.length()){ + return isOneAway(t,s); + } + + int i = 0; // Pointer for the first String + int j = 0; // Pointer for the second String + + int diff = 0; // Count the number of differences (edits) between the two Strings + while (i < s.length() && j < t.length()){ + // If two characters are different, increment count + if (s.charAt(i) != t.charAt(j)){ + diff++; + if (s.length() != t.length()){ + // If s and t have different sizes, than edit should be a deletion + i++; + continue; + } + } + i++; + j++; + } + + if (diff <= 1){ + return true; + } + else{ + return false; + } + } +} diff --git a/ch1/Solution06.java b/ch1/Solution06.java new file mode 100644 index 0000000..11bd4f9 --- /dev/null +++ b/ch1/Solution06.java @@ -0,0 +1,77 @@ +/** + * Created by Hakim on 9/9/15. + * Compress a String using the characters count + */ +public class Solution06 { + public static void main(String[] args){ + Solution06 sc = new Solution06(); + System.out.println(sc.compressString("aabcccccaaa")); + System.out.println(sc.compressString("abccd")); + } + + /** + * Perform String compression using the counts of the characters in the String. + * @param s - String to compress + * @return - Compressed String + */ + public String compressString(String s){ + // If the compressed String is not actually smaller than s, then return s + if (s.length() <= 2 || !isCompression(s)){ + return s; + } + + StringBuilder sb = new StringBuilder(); + int count = 1; + + for (int i=1; i seen = new HashSet<>(); + + Node current = head; + seen.add(head.val); + + // For each node, if its content is saved in seen, remove it + while (current.next != null){ + if (seen.contains(current.next.val)){ + current.next = current.next.next; + } + else{ + seen.add(current.next.val); + current = current.next; + } + } + return head; + } + + /** + * Remove duplicates in a linked list with no buffer allowed. + * @param head - Head of the linked list to remove duplicates from + * @return head of the linked list from which duplicates were removed + */ + public Node removeDuplicatesNoBuffer(Node head){ + if (head == null || head.next == null){ + return head; + } + + Node current = head; + + // For each node, loop through all the next nodes and remove them if they have the same value as + // the current node + while (current.next != null){ + Node n = current; + while (n.next != null){ + if (n.next.val == current.val){ + n.next = n.next.next; + } + else{ + n = n.next; + } + } + current = current.next; + } + return head; + } + + /** + * Helper function to print a linked list. + * @param head - Head of the linked list to print + */ + public void printList(Node head){ + if (head == null){ + System.out.println(""); + } + + StringBuilder sb = new StringBuilder(); + sb.append(head.val); + + while (head.next != null){ + sb.append("->"); + sb.append(head.next.val); + head = head.next; + } + + System.out.println(sb.toString()); + } +} diff --git a/ch2/Solution02.java b/ch2/Solution02.java new file mode 100644 index 0000000..0a56b0c --- /dev/null +++ b/ch2/Solution02.java @@ -0,0 +1,92 @@ +/** + * Created by Hakim on 9/10/15. + */ + +/** + * Define a LinkedListNode. + */ +class Node{ + Node next; + int val; + + public Node(int v){ + val = v; + } +} + +/** + * Find the kth to last node of a list. + */ +public class Solution02 { + public static void main(String[] args){ + Solution02 solution02 = new Solution02(); + Node a = new Node(1); + Node b = new Node(2); + Node c = new Node(3); + Node d = new Node(4); + Node e = new Node(5); + + a.next = b; + b.next = c; + c.next = d; + d.next = e; + + System.out.print("1 to last element of "); + solution02.printList(a); + System.out.println("is: " + solution02.kthToLast(a,1).val); + } + + /** + * Return kth to last element of a linked list. + * k=0 corresponds to the last element of the list + * @param head - Head of the linked list + * @param k + * @return kth to last node of the list + */ + public Node kthToLast(Node head, int k){ + Node fast = head; + Node slow = head; + + // Set the fast pointer k nodes away from the slow one + for (int i=0; i< k; i++){ + if (fast == null){ + return null; + } + else{ + fast = fast.next; + } + } + + // Move the fast and slow pointers one node at a time + // until fast points to the last node + // slow will then be pointing to the kth to last node + while (fast.next != null){ + fast = fast.next; + slow = slow.next; + } + + return slow; + } + + /** + * Helper function to print a linked list. + * @param head - Head of the linked list to print + * @return String representing the linked list + */ + public void printList(Node head){ + if (head == null){ + System.out.println(""); + } + + StringBuilder sb = new StringBuilder(); + sb.append(head.val); + + while (head.next != null){ + sb.append("->"); + sb.append(head.next.val); + head = head.next; + } + + System.out.println(sb.toString()); + } +} diff --git a/ch2/Solution03.java b/ch2/Solution03.java new file mode 100644 index 0000000..78e9049 --- /dev/null +++ b/ch2/Solution03.java @@ -0,0 +1,80 @@ +/** + * Created by Hakim on 9/10/15. + */ + +/** + * Define a LinkedListNode. + */ +class Node{ + Node next; + int val; + + public Node(int v){ + val = v; + } +} + +/** + * Delete middle node of a linked list. + */ +public class Solution03 { + public static void main(String[] args){ + Solution03 solution03 = new Solution03(); + Node a = new Node(1); + Node b = new Node(2); + Node c = new Node(3); + Node d = new Node(4); + Node e = new Node(5); + + a.next = b; + b.next = c; + c.next = d; + d.next = e; + + System.out.println("Before deleting middle node: "); + solution03.printList(a); + solution03.deleteMiddleNode(c); + System.out.println("After deleting middle node: "); + solution03.printList(a); + } + + /** + * Delete the middle node of a linked list given only this node. + * @param middle - Middle node to delete + */ + public void deleteMiddleNode(Node middle){ + if (middle == null){ + return; + } + + // For each node starting from the middle node, + // copy the value and next node of the node to come + while (middle.next != null){ + middle.val = middle.next.val; + middle.next = middle.next.next; + middle = middle.next; + } + } + + /** + * Helper function to create a String corresponding to a linked list. + * @param head - Head of the linked list to print + * @return String corresponding to that linked list + */ + public void printList(Node head){ + if (head == null){ + System.out.println(""); + } + + StringBuilder sb = new StringBuilder(); + sb.append(head.val); + + while (head.next != null){ + sb.append("->"); + sb.append(head.next.val); + head = head.next; + } + + System.out.println(sb.toString()); + } +} diff --git a/ch2/Solution04.java b/ch2/Solution04.java new file mode 100644 index 0000000..f72e3ff --- /dev/null +++ b/ch2/Solution04.java @@ -0,0 +1,108 @@ +/** + * Created by Hakim on 9/11/15. + */ + +/** + * Define a LinkedListNode. + */ +class Node{ + Node next; + int val; + + public Node(int v){ + val = v; + } +} + +/** + * Partition a linked list around a value v. + * If v is contained within the list, the values of v only need to + * be after the elements less than v. + */ +public class Solution04 { + public static void main(String[] args){ + Solution04 solution04 = new Solution04(); + Node a = new Node(3); + Node b = new Node(5); + Node c = new Node(8); + Node d = new Node(5); + Node e = new Node(10); + Node f = new Node(2); + Node g = new Node(1); + + a.next = b; + b.next = c; + c.next = d; + d.next = e; + e.next = f; + f.next = g; + + System.out.println("Original linked list: "); + solution04.printList(a); + Node partitioned = solution04.partition(a,5); + System.out.println("Partitioned linked list: "); + solution04.printList(partitioned); + + } + + /** + * Partition a linked list around a value. + * @param head - Head of the linked list + * @param v - Value to partition around + * @return head of the partitioned linked list + */ + public Node partition(Node head, int v){ + if (head == null || head.next == null){ + return head; + } + + // Elements smaller than v will be added at the new head + // Elements greater or equal than v will be appended to the new tail + Node newHead = head; + Node newTail = newHead; + + Node current = head.next; + Node next = current.next; + newHead.next = null; + current.next = null; + + while (current != null){ + if (current.val < v){ + current.next = newHead; + newHead = current; + } + else{ + newTail.next = current; + newTail = current; + } + current = next; + if (current != null){ + next = current.next; + current.next = null; + } + } + + return newHead; + } + + /** + * Helper function to print a linked list. + * @param head - Head of the linked list to print + */ + public void printList(Node head){ + if (head == null){ + System.out.println(""); + } + + StringBuilder sb = new StringBuilder(); + sb.append(head.val); + + while (head.next != null){ + sb.append("->"); + sb.append(head.next.val); + head = head.next; + } + + System.out.println(sb.toString()); + } +} diff --git a/ch2/Solution05.java b/ch2/Solution05.java new file mode 100644 index 0000000..11df40b --- /dev/null +++ b/ch2/Solution05.java @@ -0,0 +1,237 @@ +/** + * Created by Hakim on 9/11/15. + */ + +/** + * Define a Linked List Node. + */ +class Node{ + Node next; + int val; + + public Node(int v){ + val = v; + } +} + +/** + * Sum two numbers represented by linked lists. + */ +public class Solution05 { + public static void main(String[] args){ + Solution05 solution05 = new Solution05(); + Node a = new Node(7); + Node b = new Node(1); + Node c = new Node(6); + + Node d = new Node(5); + Node e = new Node(9); + Node f = new Node(2); + + a.next = b; + b.next = c; + + d.next = e; + e.next = f; + + System.out.println("Backwards: "); + solution05.printList(a); + System.out.println(" + "); + solution05.printList(d); + System.out.println(" = "); + solution05.printList(solution05.sumLists(a,d)); + + System.out.println(); + + System.out.println("Forwards: "); + solution05.printList(a); + System.out.println(" + "); + solution05.printList(d); + System.out.println(" = "); + solution05.printList(solution05.sumListsForwardOrder(a, d)); + } + + /** + * Sum two numbers represented by linked lists where the digits are stored in reverse order. + * @param a - Head of the first linked list + * @param b - Head of the second linked list + * @return Head of the linked list representing the summed number + */ + public Node sumLists(Node a, Node b){ + if (a == null){ + return b; + } + if (b == null){ + return a; + } + + // Dummy node to start the linked list + Node dummy = new Node(Integer.MIN_VALUE); + Node next = dummy; + + int carry = 0; + + // Sum each node from the lists + while (a != null || b != null){ + int aVal = (a != null) ? a.val : 0; + int bVal = (b != null) ? b.val : 0; + + int sum = aVal + bVal + carry; + int v = sum % 10; + + Node current = new Node(v); + next.next = current; + next = current; + + carry = (sum >= 10) ? 1 : 0; + + a = a.next; + b = b.next; + } + + // if remainder == 1, add extra node + if (carry == 1){ + Node current = new Node(1); + next.next = current; + } + + return dummy.next; + } + + /** + * FOLLOW UP: Sum two numbers represented by linked lists where the digits are stored in FORWARD order. + * @param a - Head of the first linked list + * @param b - Head of the second linked list + * @return Head of the linked list representing the sum + */ + public Node sumListsForwardOrder(Node a, Node b){ + // Count the number of nodes in each list + int n1 = numberNodes(a); + int n2 = numberNodes(b); + + // Complete the smallest list with zeros on its left + if (n1 < n2){ + a = completeList(a, n2-n1); + } + else if (n1 > n2){ + b = completeList(b, n1-n2); + } + + Node result = sumRecursive(a, b); + // The head returned by sumRecursive might be greater than 10 + // In that situation, create a new head set to 1 and + // set the previous head to its value minus 10 + if (result.val >= 10){ + Node head = new Node(1); + result.val -= 10; + head.next = result; + return head; + } + else { + return result; + } + } + + /** + * Recursive function used to sum a linked list forward. + * Warning: The head of the created linked list might be greater than 10 and this case + * must be handled in the caller + * @param node1 - current node of list1 being summed + * @param node2 - current node of list2 being summed + * @return Node corresponding to the sum of node1 and node2 + */ + public Node sumRecursive(Node node1, Node node2){ + // The input linked lists have same size + if (node1 == null && node2 == null){ + return null; + } + + // Compute the sum of the number formed by the digits to the right of node1 and node2 + Node next = sumRecursive(node1.next, node2.next); + + int sum = node1.val + node2.val; + if (next != null){ + int carry = 0; + if (next.val >= 10){ + // if the node on the right of the sum is greater than 10, then set carry to 1 and + // replace this node by its actual value + carry = 1; + next.val -= 10; + } + + sum += carry; + } + + Node current = new Node(sum); + current.next = next; + + return current; + } + + /** + * Helper function to complete a linked list by adding n zero nodes at its head. + * @param a - Head of the linked list to complete + * @param n - Number of zeros to add at the beginning + * @return Head of the completed linked list + */ + public Node completeList(Node a, int n){ + if (n == 0){ + return a; + } + + Node head = new Node(0); + Node node = head; + + for (int i=1; i"); + sb.append(head.next.val); + head = head.next; + } + + System.out.println(sb.toString()); + } +} diff --git a/ch2/Solution06.java b/ch2/Solution06.java new file mode 100644 index 0000000..29d480a --- /dev/null +++ b/ch2/Solution06.java @@ -0,0 +1,121 @@ +/** + * Created by Hakim on 9/11/15. + */ + +import java.util.Stack; + +/** + * Define a LinkedListNode. +*/ +class Node{ + Node next; + int val; + + public Node(int v){ + val = v; + } +} + +/** + * Check whether a linked list is a palindrome. + */ +public class Solution06 { + public static void main(String[] args){ + Solution06 solution06 = new Solution06(); + Node a = new Node(1); + Node b = new Node(2); + Node c = new Node(3); + Node d = new Node(2); + Node e = new Node(1); + + a.next = b; + b.next = c; + c.next = d; + d.next = e; + + System.out.println("isPalindrome("); + solution06.printList(a); + System.out.println("):"); + System.out.println(solution06.isPalindrome(a)); + + a = new Node(1); + b = new Node(2); + c = new Node(3); + d = new Node(2); + e = new Node(2); + + a.next = b; + b.next = c; + c.next = d; + d.next = e; + + System.out.println(); + + System.out.println("isPalindrome("); + solution06.printList(a); + System.out.println("):"); + System.out.println(solution06.isPalindrome(a)); + + + } + + /** + * Check whether a linked list is a palindrome. + * @param head - Head of the linked list + * @return - true if the linked list is a palindrome. False otherwise + */ + public boolean isPalindrome(Node head){ + if (head == null || head.next == null){ + return true; + } + + // stack will save the first half of the list + Stack stack = new Stack<>(); + + // Put the first half of the list in the stack + Node fast = head; + Node slow = head; + + while (fast != null){ + stack.push(slow.val); + if (fast.next == null){ + break; + } + + slow = slow.next; + fast = fast.next.next; + } + + // Compare the second half of the list to the elements stacked + while (slow != null){ + int elt = stack.pop(); + if (elt != slow.val){ + return false; + } + slow = slow.next; + } + + return true; + } + + /** + * Helper function to print a linked list. + * @param head - Head of the linked list to print + */ + public void printList(Node head){ + if (head == null){ + System.out.println(""); + } + + StringBuilder sb = new StringBuilder(); + sb.append(head.val); + + while (head.next != null){ + sb.append("->"); + sb.append(head.next.val); + head = head.next; + } + + System.out.println(sb.toString()); + } +} diff --git a/ch2/Solution07.java b/ch2/Solution07.java new file mode 100644 index 0000000..750006b --- /dev/null +++ b/ch2/Solution07.java @@ -0,0 +1,133 @@ +/** + * Created by Hakim on 9/11/15. + */ + +/** + * Define a LinkedListNode. + */ +class Node{ + Node next; + int val; + + public Node(int v){ + val = v; + } +} + +/** + * Find the intersection of two linked lists. + */ +public class Solution07 { + public static void main(String[] args){ + Solution07 solution07 = new Solution07(); + Node a = new Node(1); + Node b = new Node(2); + Node c = new Node(3); + Node d = new Node(4); + Node e = new Node(5); + Node f = new Node(6); + Node g = new Node(7); + Node h = new Node(8); + + a.next = b; + b.next = c; + + f.next = g; + g.next = h; + h.next = c; + + c.next = d; + d.next = e; + + + System.out.println("Intersection of "); + solution07.printList(a); + System.out.println(" and "); + solution07.printList(f); + System.out.println(": "); + System.out.println(solution07.intersection(a,f).val); + } + + /** + * Find the intersection of two linked lists. + * @param a - Head of the first linked list + * @param b - Head of the second linked list + * @return Node where the two linked lists intersect. Null if there is no such a node + */ + public Node intersection(Node a, Node b){ + int count1 = 0; + int count2 = 0; + + Node node1 = a; + Node node2 = b; + + Node fast; + Node slow; + + // Count the sizes of the two linked lists + while (node1 != null){ + node1 = node1.next; + count1++; + } + + while (node2 != null){ + node2 = node2.next; + count2++; + } + + // Set the pointer of the longest list "its size - smallest list's size" + // in advance so that, when we move this pointer at the same pace + // as the pointer in the smallest list, they will meet at the node where + // they intersect if such a node exists + if (count1 > count2){ + int diff = count1 - count2; + fast = a; + for (int i=0; i"); + sb.append(head.next.val); + head = head.next; + } + + System.out.println(sb.toString()); + } +} diff --git a/ch2/Solution08.java b/ch2/Solution08.java new file mode 100644 index 0000000..e38bcf3 --- /dev/null +++ b/ch2/Solution08.java @@ -0,0 +1,77 @@ +/** + * Created by Hakim on 9/11/15. + */ + +/** + * Define a LinkedListNode. + */ +class Node{ + Node next; + int val; + + public Node(int v){ + val = v; + } +} + +/** + * Given a circular linked list, return the node at the beginning of the loop. + */ +public class Solution08 { + public static void main(String[] args){ + Solution08 solution08 = new Solution08(); + Node a = new Node(1); + Node b = new Node(2); + Node c = new Node(3); + Node d = new Node(4); + Node e = new Node(5); + + a.next = b; + b.next = c; + c.next = d; + d.next = e; + e.next = c; + + + System.out.println("loop: " + solution08.detectLoop(a).val); + + } + + /** + * Return the Node at the beginning of a loopy linked list. + * @param head - Head of the linked list + * @return node where the loop begins. null if there is no such a node + */ + public Node detectLoop(Node head){ + if (head == null || head.next == null){ + return head; + } + + // Slow runner moves one node at a time + // Fast runner moves two nodes at a time + Node slow = head.next; + Node fast = head.next.next; + + // if we denote by len the length of the list before the loop begins, + // fast and slow will meet len mod (size of the loop) before the node where + // the loop begins + while (slow != fast){ + if (fast.next == null){ + return null; + } + + slow = slow.next; + fast = fast.next.next; + } + + // we then introduce a third node starting from head + // third and slow will meet at the node where the loop begins + Node third = head; + while (third != slow){ + third = third.next; + slow = slow.next; + } + + return third; + } +} From a35a1687953aa0e3e965173c43aa986a0de99a4e Mon Sep 17 00:00:00 2001 From: hakimsd9 Date: Thu, 17 Sep 2015 10:47:59 -0400 Subject: [PATCH 2/6] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index be4cd4f..ee8b0ec 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ # CCAssignment +Hakim Sidahmed +hsidahme From 1a73f4c1bf9b87a376af3280c8542fd76b73233b Mon Sep 17 00:00:00 2001 From: Hakim Date: Wed, 23 Sep 2015 23:11:11 -0400 Subject: [PATCH 3/6] chapters 3 and 4 --- ch3/Solution01.java | 63 +++++++++++++ ch3/Solution02.java | 82 ++++++++++++++++ ch3/Solution03.java | 158 +++++++++++++++++++++++++++++++ ch3/Solution04.java | 84 +++++++++++++++++ ch3/Solution05.java | 72 ++++++++++++++ ch3/Solution06.java | 120 ++++++++++++++++++++++++ ch4/Solution01.java | 109 +++++++++++++++++++++ ch4/Solution02.java | 61 ++++++++++++ ch4/Solution03.java | 116 +++++++++++++++++++++++ ch4/Solution04.java | 107 +++++++++++++++++++++ ch4/Solution05.java | 92 ++++++++++++++++++ ch4/Solution06.java | 118 +++++++++++++++++++++++ ch4/Solution07.java | 149 +++++++++++++++++++++++++++++ ch4/Solution08.java | 112 ++++++++++++++++++++++ ch4/Solution09.java | 89 ++++++++++++++++++ ch4/Solution10.java | 90 ++++++++++++++++++ ch4/Solution11.java | 224 ++++++++++++++++++++++++++++++++++++++++++++ ch4/Solution12.java | 90 ++++++++++++++++++ 18 files changed, 1936 insertions(+) create mode 100644 ch3/Solution01.java create mode 100644 ch3/Solution02.java create mode 100644 ch3/Solution03.java create mode 100644 ch3/Solution04.java create mode 100644 ch3/Solution05.java create mode 100644 ch3/Solution06.java create mode 100644 ch4/Solution01.java create mode 100644 ch4/Solution02.java create mode 100644 ch4/Solution03.java create mode 100644 ch4/Solution04.java create mode 100644 ch4/Solution05.java create mode 100644 ch4/Solution06.java create mode 100644 ch4/Solution07.java create mode 100644 ch4/Solution08.java create mode 100644 ch4/Solution09.java create mode 100644 ch4/Solution10.java create mode 100644 ch4/Solution11.java create mode 100644 ch4/Solution12.java diff --git a/ch3/Solution01.java b/ch3/Solution01.java new file mode 100644 index 0000000..ff08d21 --- /dev/null +++ b/ch3/Solution01.java @@ -0,0 +1,63 @@ +import java.util.ArrayList; +import java.util.EmptyStackException; +import java.util.List; + +/** + * Created by Hakim on 9/15/15. + */ +public class Solution01 { + int N = 8; + int[] array = new int[3*N]; + + int[] begin = new int[3]; + int[] end = new int[3]; + int[] top = new int[3]; + + public void initializeStacks(){ + begin[0] = 0; + begin[1] = N; + begin[2] = 2*N; + + end[0] = N; + end[1] = 2*N-1; + end[2] = 3*N-1; + + top[0] = 0; + top[1] = N; + top[2] = 2*N; + + } + + + public void push(int stackNumber, int elt){ + if (top[stackNumber] == end[stackNumber]){ + throw new StackOverflowError(); + } + else{ + top[stackNumber]++; + array[top[stackNumber]] = elt; + } + } + + public void pop(int stackNumber){ + if (isEmpty(stackNumber)){ + throw new EmptyStackException(); + } + else{ + top[stackNumber]--; + } + } + + public int peek(int stackNumber){ + if (isEmpty(stackNumber)){ + throw new EmptyStackException(); + } + else{ + return array[top[stackNumber]]; + } + } + + public boolean isEmpty(int stackNumber){ + return begin[stackNumber] == end[stackNumber]; + } +} diff --git a/ch3/Solution02.java b/ch3/Solution02.java new file mode 100644 index 0000000..4648f40 --- /dev/null +++ b/ch3/Solution02.java @@ -0,0 +1,82 @@ +import java.util.EmptyStackException; +import java.util.Stack; + +/** + * Created by Hakim on 9/16/15. + */ + +/*** + * 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 O(1). + */ +class MinStack { + Stack stack = new Stack<>(); + // Create an auxiliary stack mins which keeps track + // of the current minimum element + Stack mins = new Stack<>(); + + // Push x into stack + // if x is smaller than the current smallest element, + // then add it to mins + public void push(int x){ + stack.push(x); + if (mins.isEmpty()){ + mins.push(x); + } + int currentMin = mins.peek(); + + if (x <= currentMin){ + mins.push(x); + } + } + + // if the element popped from stack is smaller than the + // current minimum, then update mins by popping it + public void pop(){ + if (stack.isEmpty()){ + throw new EmptyStackException(); + } + + int current = stack.peek(); + stack.pop(); + + if (mins.isEmpty()){ + return; + } + if (mins.peek() >= current){ + mins.pop(); + } + } + + public int getMin(){ + return mins.peek(); + } + + public int peek(){ + return stack.peek(); + } + + public boolean isEmpty(){ + return stack.isEmpty(); + } +} + + +public class Solution02{ + public static void main(String[] args){ + Solution02 solution02 = new Solution02(); + MinStack minStack = new MinStack(); + + minStack.push(3); + minStack.push(5); + minStack.push(7); + minStack.push(2); + minStack.push(4); + + System.out.println("Minimum element in stack: " + minStack.getMin()); + minStack.pop(); + minStack.pop(); + System.out.println("New minimum element in stack: " + minStack.getMin()); + } +} + diff --git a/ch3/Solution03.java b/ch3/Solution03.java new file mode 100644 index 0000000..ed7320e --- /dev/null +++ b/ch3/Solution03.java @@ -0,0 +1,158 @@ +import java.util.*; + +/** + * Created by Hakim on 9/17/15. + */ + +/** + * Implement a set of stacks, similarly to a set of plates. + * SetOfStacks should be composed of several stacks and should + * create a new stack once the previous one exceeds capacity. + * @param + */ +class SetOfStacks { + List stacks; // stacks[0] stores the first (oldest) stack + int capacity; // Capacity of each stack + + public SetOfStacks(int N){ + stacks = new ArrayList<>(); + capacity = N; + } + + public void push(T x){ + // If there is no stack in the set or the last stack is full, + // then create a new stack and push x there + if (stacks.size() == 0 || stacks.get(stacks.size()-1).size() == capacity){ + Stack newStack = new Stack(); + newStack.push(x); + stacks.add(newStack); + } + else{ + // push x to the newest stack + stacks.get(stacks.size()-1).push(x); + } + } + + public T pop(){ + if (stacks.size() == 0){ + throw new EmptyStackException(); + } + + T p = (T) stacks.get(stacks.size()-1).pop(); + + // If the last stack gets empty after popping it + // remove it from the set + if (stacks.get(stacks.size()-1).isEmpty()){ + stacks.remove(stacks.size()-1); + } + + return p; + } + + public T peek(){ + if (stacks.size() == 0){ + throw new EmptyStackException(); + } + T p = (T) stacks.get(stacks.size()-1).peek(); + return p; + } + + public boolean isEmpty(){ + return stacks.size() == 0; + } + + /** + * Helper method to print the set of stacks. + * Top of each stack is on the right + * The newest stack is at the bottom + */ + public void printSetOfStacks(){ + for (Stack stack : stacks){ + for (T t : stack){ + System.out.print(t + " | "); + } + System.out.println(); + } + } + + // FOLLOW UP: Implement popAt(int index) which pops stack index + public T popAt(int index){ + // Choose to shift all the elements in the stacks after index + // to fill stack index + if (stacks.size() <= index){ + throw new RuntimeException("Attempting to pop an non existing stack"); + } + + T p = (T) stacks.get(index).pop(); + + // If the stack is empty, then just remove it + // (no need to shift anything) + if (stacks.get(index).isEmpty()){ + stacks.remove(index); + } + else{ + // Else, shift each stack after index + // by adding elements to the previous stack + // until it is full + for (int i=index+1; i buffer = new Stack<>(); + while (!stacks.get(i).isEmpty()){ + buffer.push((T) stacks.get(i).pop()); + } + + // While the previous stack is not full and the current not + // empty, empty the buffer to the new stack + while (!buffer.isEmpty() && stacks.get(i-1).size() < capacity){ + stacks.get(i-1).push(buffer.pop()); + } + + // Put back the remaining elements in buffer into the original stack + while (!buffer.isEmpty()){ + stacks.get(i).push(buffer.pop()); + } + } + +} + + + +public class Solution03 { + public static void main(String[] args){ + SetOfStacks setOfStacks = new SetOfStacks<>(2); + setOfStacks.push(0); + setOfStacks.push(1); + setOfStacks.push(2); + setOfStacks.push(3); + setOfStacks.push(4); + setOfStacks.push(5); + setOfStacks.push(6); + + System.out.println(" Set of stacks "); + setOfStacks.printSetOfStacks(); + System.out.print("Top element: " + setOfStacks.peek()); + setOfStacks.pop(); + System.out.println(" Set of stacks after removing top element: "); + setOfStacks.printSetOfStacks(); + setOfStacks.popAt(1); + System.out.println("Set of stacks after popping stack 1: "); + setOfStacks.printSetOfStacks(); + } + + + +} diff --git a/ch3/Solution04.java b/ch3/Solution04.java new file mode 100644 index 0000000..8faf1b3 --- /dev/null +++ b/ch3/Solution04.java @@ -0,0 +1,84 @@ +import java.util.Stack; + +/** + * Created by Hakim on 9/17/15. + */ + +/** + * Implement a Queue using two Stacks. + * @param + */ +class MyQueue { + Stack stack1 = new Stack<>(); // holds the old elements in a "FIFO" manner + Stack stack2 = new Stack<>(); // holds the new elements in a "FILO" manner + + public void add(T t){ + // Add new element to stack2 + stack2.push(t); + } + + public T remove(){ + if (this.isEmpty()){ + throw new RuntimeException("Trying to remove from an empty MyQueue"); + } + + // If stack1 is not empty, it holds the oldest elements + if (!stack1.isEmpty()){ + return stack1.pop(); + } + else{ + // otherwise, add all the newest elements from stack2 into stack1, + // reverting their order + while (!stack2.isEmpty()){ + stack1.push(stack2.pop()); + } + // the oldest element is now at stack1's top + return stack1.pop(); + } + } + + public T peek(){ + if (this.isEmpty()){ + throw new RuntimeException("Trying to peek from an empty MyQueue"); + } + + // If stack1 is not empty, it holds the oldest elements + if (!stack1.isEmpty()){ + return stack1.peek(); + } + else{ + // otherwise, add all the newest elements from stack2 into stack1, + // reverting their order + while (!stack2.isEmpty()){ + stack1.push(stack2.pop()); + } + // the oldest element is now at stack1's top + return stack1.peek(); + } + } + + public boolean isEmpty(){ + // check whether both stacks are empty + return stack1.isEmpty() && stack2.isEmpty(); + } +} + +public class Solution04 { + public static void main(String[] args){ + MyQueue queue = new MyQueue<>(); + + queue.add(1); + queue.add(2); + queue.add(3); + queue.add(4); + queue.add(5); + queue.add(6); + + System.out.println("queue.peek(): " + queue.peek()); + System.out.println("queue.pop(): " + queue.remove()); + System.out.println("queue.pop(): " + queue.remove()); + System.out.println("queue.pop(): " + queue.remove()); + System.out.println("queue.pop(): " + queue.remove()); + System.out.println("queue.pop(): " + queue.remove()); + } +} diff --git a/ch3/Solution05.java b/ch3/Solution05.java new file mode 100644 index 0000000..f9318a5 --- /dev/null +++ b/ch3/Solution05.java @@ -0,0 +1,72 @@ +import java.util.Stack; + +/** + * Created by Hakim on 9/17/15. + */ + +/** + * Sort a Stack such that the smallest items are on the top. + * May use an additional Stack, but no other data structure + */ +public class Solution05 { + public static void main(String[] args){ + Solution05 s = new Solution05(); + Stack stack = new Stack<>(); + stack.push(2); + stack.push(3); + stack.push(1); + stack.push(4); + stack.push(1); + stack.push(0); + + System.out.println("Unsorted Stack: "); + printStack(stack); + s.sortStack(stack); + System.out.println("Sorted Stack: "); + printStack(stack); + } + + + /** + * Sort a Stack such that the smallest items are on the top. + * @param stack - Stack to be sorted + */ + public void sortStack(Stack stack){ + // Additional Stack + Stack buffer = new Stack<>(); + + if (stack == null || stack.size() < 2){ + return; + } + + buffer.push(stack.pop()); + + // Use buffer to store all the elements in reverse order + while (!stack.isEmpty()){ + int top = stack.pop(); + int topBuffer = buffer.peek(); + while (!buffer.isEmpty() && topBuffer > top){ + stack.push(buffer.pop()); + topBuffer = buffer.peek(); + } + buffer.push(top); + } + + // push back the elements from buffer so stack is sorted + while (!buffer.isEmpty()){ + stack.push(buffer.pop()); + } + } + + /** + * Helper method to print the elements in a Stack. + * @param stack + */ + public static void printStack(Stack stack){ + for (int t : stack){ + System.out.print(t + " "); + } + System.out.println(); + } + +} diff --git a/ch3/Solution06.java b/ch3/Solution06.java new file mode 100644 index 0000000..dcded7c --- /dev/null +++ b/ch3/Solution06.java @@ -0,0 +1,120 @@ +import java.util.LinkedList; + +/** + * Created by Hakim on 9/23/15. + */ + +/** + * Define an Animal. + */ +class Animal{ + String name; + int adoptionTime; + + public Animal(String n){ + name = n; + } +} + +/** + * Define a Dog. + */ +class Dog extends Animal{ + public Dog(String n){ + super(n); + } +} + +/** + * Define a Cat. + */ +class Cat extends Animal{ + public Cat(String n){ + super(n); + } +} + +/** + * Data structure to keep track of the Cats and Dogs arriving at the Shelter. + * Update a time stamp to keep track of the Animal's arrival. + * Store Dogs and Cats in separate LinkedLists. + * When Enqueuing a new Animal, enqueue it in the corresponding linked list. + * If dequeuing any animal, compare the oldest of the two linked lists and return the oldest of the two. + */ +class AnimalQueue{ + LinkedList dogQueue = new LinkedList<>(); + LinkedList catQueue = new LinkedList<>(); + int adoptionTime = 0; + + public void enqueue(Animal animal){ + animal.adoptionTime = adoptionTime; + if (animal.getClass() == Dog.class){ + dogQueue.add((Dog)animal); + } + if (animal.getClass() == Cat.class){ + catQueue.add((Cat)animal); + } + adoptionTime++; + } + + public Animal dequeueAny(){ + if (dogQueue.isEmpty() && catQueue.isEmpty()){ + return null; + } + if (dogQueue.isEmpty()){ + return catQueue.remove(); + } + if (catQueue.isEmpty()){ + return dogQueue.remove(); + } + + int oldestDog = dogQueue.peek().adoptionTime; + int oldestCat = catQueue.peek().adoptionTime; + + if (oldestCat < oldestDog){ + return catQueue.remove(); + } + else{ + return dogQueue.remove(); + } + } + + public Dog dequeueDog(){ + if (dogQueue.isEmpty()){ + return null; + } + return dogQueue.remove(); + } + + public Cat dequeueCat(){ + if (catQueue.isEmpty()){ + return null; + } + return catQueue.remove(); + } +} +public class Solution06 { + public static void main(String[] args){ + AnimalQueue queue = new AnimalQueue(); + Dog dog1 = new Dog("dog1"); + Dog dog2 = new Dog("dog2"); + Dog dog3 = new Dog("dog3"); + + Cat cat1 = new Cat("cat1"); + Cat cat2 = new Cat("cat2"); + Cat cat3 = new Cat("cat3"); + + queue.enqueue(dog1); + queue.enqueue(cat1); + queue.enqueue(dog2); + queue.enqueue(cat2); + queue.enqueue(dog3); + queue.enqueue(cat3); + + System.out.println("dequeueAny should return Dog1: " + queue.dequeueAny().name); + System.out.println("dequeueDog should return Dog2: " + queue.dequeueDog().name); + System.out.println("dequeueAny should return Cat1: " + queue.dequeueAny().name); + System.out.println("dequeueCat should return Cat2: " + queue.dequeueCat().name); + System.out.println("dequeueCat should return Cat3: " + queue.dequeueCat().name); + } +} diff --git a/ch4/Solution01.java b/ch4/Solution01.java new file mode 100644 index 0000000..69a4674 --- /dev/null +++ b/ch4/Solution01.java @@ -0,0 +1,109 @@ +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Queue; +import java.util.Set; + +/** + * Created by Hakim on 9/19/15. + */ +class Graph{ + public Node[] nodes; +} + +class Node{ + public int label; + public Node[] children; + + public Node(int l){ + label = l; + } +} + +public class Solution01 { + public static void main(String[] args){ + Solution01 solution01 = new Solution01(); + + // graph1: {0,1#1,3#2,0#3,2,4#4,5#5} (cf serialization: https://leetcode.com/problems/clone-graph/) + Graph graph1 = new Graph(); + Node a1 = new Node(0); + Node b1 = new Node(1); + Node c1 = new Node(2); + Node d1 = new Node(3); + Node e1 = new Node(4); + Node f1 = new Node(5); + + Node[] a1Children = {b1}; + Node[] b1Children = {d1}; + Node[] c1Children = {a1}; + Node[] d1Children = {c1,e1}; + Node[] e1Children = {f1}; + + a1.children = a1Children; + b1.children = b1Children; + c1.children = c1Children; + d1.children = d1Children; + e1.children = e1Children; + + System.out.println("Route between a1 and f1 in graph1: " + solution01.existsRoute(graph1, a1, f1)); + + // graph2: {0,1#1,3#2,0#3,2#4,3,5#5} + Graph graph2 = new Graph(); + Node a2 = new Node(0); + Node b2 = new Node(1); + Node c2 = new Node(2); + Node d2 = new Node(3); + Node e2 = new Node(4); + Node f2 = new Node(5); + + Node[] a2Children = {b2}; + Node[] b2Children = {d2}; + Node[] c2Children = {a2}; + Node[] d2Children = {c2}; + Node[] e2Children = {d2,f2}; + + a2.children = a2Children; + b2.children = b2Children; + c2.children = c2Children; + d2.children = d2Children; + e2.children = e2Children; + + System.out.println("Route between a2 and f2 in graph2: " + solution01.existsRoute(graph2, a2, f2)); + + + } + + /** + * Find out whether there is a route from node a to node b. + * @param graph + * @param a + * @param b + * @return true if there is a route from node a to node b. False otherwise. + */ + public boolean existsRoute(Graph graph, Node a, Node b){ + // We implement BFS + if (graph == null || a == null || b == null){ + return false; + } + + // Keep track of the nodes visited to avoid getting stuck in a cycle + Set visited = new HashSet<>(); + Queue queue = new LinkedList<>(); + queue.add(a); + + while (!queue.isEmpty()){ + Node n = queue.remove(); + visited.add(n); + + for (Node child : n.children){ + if (child == b){ + return true; + } + if (!visited.contains(child)){ + queue.add(child); + } + } + } + + return false; + } +} diff --git a/ch4/Solution02.java b/ch4/Solution02.java new file mode 100644 index 0000000..e1eaac6 --- /dev/null +++ b/ch4/Solution02.java @@ -0,0 +1,61 @@ +/** + * Created by Hakim on 9/19/15. + */ + +/** + * Define a tree node. + */ +class TreeNode{ + int val; + TreeNode left; + TreeNode right; + + public TreeNode(int v){ + val = v; + } +} + +/** + * Create a BST with minimal height. + */ +public class Solution02 { + public static void main(String[] args){ + Solution02 solution02 = new Solution02(); + int[] sortedArray = {1,2,3,4,5,6,7,8}; + TreeNode root = solution02.buildMinimalTree(sortedArray, 0, sortedArray.length-1); + + System.out.println("Level 1: " + root.val); + System.out.println("Level2: " + root.left.val + " | " + root.right.val); + TreeNode b = root.left; + TreeNode c = root.right; + System.out.println("Level3: " + b.left.val + " | " + b.right.val + " | " + c.left.val + " | " + c.right.val); + TreeNode g = c.right; + System.out.println("Level4: " + g.right.val); + } + + /** + * Given a sorted array, create a BST with minimal height. + * @param sortedArray + * @param min + * @param max + * @return Root of the BST created. + */ + public TreeNode buildMinimalTree(int[] sortedArray, int min, int max){ + // To create a BST with minimal height, we try to create a + // BST as balanced as possible + if (min > max){ + return null; + } + + int middle = (min+max)/2; + // middle element as root + TreeNode root = new TreeNode(sortedArray[middle]); + + // recurse for left subtree + root.left = buildMinimalTree(sortedArray, min, middle-1); + // recurse for right subtree + root.right = buildMinimalTree(sortedArray, middle+1, max); + + return root; + } +} diff --git a/ch4/Solution03.java b/ch4/Solution03.java new file mode 100644 index 0000000..abe86bb --- /dev/null +++ b/ch4/Solution03.java @@ -0,0 +1,116 @@ +/** + * Created by Hakim on 9/19/15. + */ + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * Define a TreeNode + */ +class TreeNode{ + int val; + TreeNode left; + TreeNode right; + + public TreeNode(int v){ + val = v; + } +} + +/** + * Given a Binary Tree, create a linked list of all the nodes at each depth. + */ +public class Solution03 { + public static void main(String[] args){ + Solution03 solution03 = new Solution03(); + + // Define tree {1,2,3,null,null,4,5,null,null,6} + TreeNode a = new TreeNode(1); + TreeNode b = new TreeNode(2); + TreeNode c = new TreeNode(3); + TreeNode d = new TreeNode(4); + TreeNode e = new TreeNode(5); + TreeNode f = new TreeNode(6); + + a.left = b; + a.right = c; + c.left = d; + c.right = e; + e.left = f; + + List> result = solution03.buildListDepths(a); + for (int i=0; i> buildListDepths(TreeNode root){ + List> result = new ArrayList<>(); + if (root == null){ + return result; + } + + // We implement a variant of BFS where instead of + // using one queue, we use two and store the queues (linked lists here) + // in the result for each level + LinkedList current = new LinkedList<>(); + LinkedList next = new LinkedList<>(); + current.add(root); + result.add((LinkedList)current.clone()); + + while (!current.isEmpty()){ + // Move to the next level + for (TreeNode t:current){ + if (t.left != null){ + next.add(t.left); + } + if (t.right != null){ + next.add(t.right); + } + } + current.clear(); + if (!next.isEmpty()){ + result.add((LinkedList)next.clone()); + } + + for (TreeNode t:next){ + if (t.left != null){ + current.add(t.left); + } + if (t.right != null){ + current.add(t.right); + } + } + next.clear(); + if (!current.isEmpty()){ + result.add((LinkedList)current.clone()); + } + } + + return result; + } + + /** + * Helper method to print a linked list. + * @param l + */ + public void printLinkedList(LinkedList l){ + if (l == null){ + System.out.println(""); + return; + } + + for (int i=0;i"); + } + System.out.println(l.get(l.size() - 1).val); + } +} diff --git a/ch4/Solution04.java b/ch4/Solution04.java new file mode 100644 index 0000000..f967d79 --- /dev/null +++ b/ch4/Solution04.java @@ -0,0 +1,107 @@ +import javax.transaction.TransactionRequiredException; + +/** + * Created by Hakim on 9/20/15. + */ + +/** + * Define a tree node. + */ +class TreeNode{ + int val; + TreeNode left; + TreeNode right; + + public TreeNode(int v){ + val = v; + } +} + +/** + * Check whether a binary tree is balanced. + */ +public class Solution04 { + public static void main(String[] args){ + Solution04 solution04 = new Solution04(); + // Tree1 is not balanced: + // 1 + // / \ + // 2 3 + // / + // 4 + // \ + // 5 + TreeNode a1 = new TreeNode(1); + TreeNode b1 = new TreeNode(2); + TreeNode c1 = new TreeNode(3); + TreeNode d1 = new TreeNode(4); + TreeNode e1 = new TreeNode(5); + + a1.left = b1; + a1.right = c1; + b1.left = d1; + d1.right = e1; + + System.out.println("isBalanced(tree1): " + solution04.isBalanced(a1)); + + // Tree2 is balanced: + // 1 + // / \ + // 2 3 + // / \ + // 4 5 + TreeNode a2 = new TreeNode(1); + TreeNode b2 = new TreeNode(2); + TreeNode c2 = new TreeNode(3); + TreeNode d2 = new TreeNode(4); + TreeNode e2 = new TreeNode(5); + + a2.left = b2; + a2.right = c2; + b2.left = d2; + b2.right = e2; + + System.out.println("isBalanced(tree2): " + solution04.isBalanced(a2)); + } + + /** + * Check whether the binary tree rooted at root is balanced. + * @param root - root of the tree + * @return true if the tree is balanced. false otherwise + */ + public boolean isBalanced(TreeNode root){ + int height = computeHeight(root); + return height >= 0; + } + + /** + * Compute the height of a binary tree if it is balanced. + * @param root - Root of the binary tree + * @return Height of the tree if it is balanced. -1 if it isn't + */ + public int computeHeight(TreeNode root){ + if (root == null){ + return 0; + } + + // If the left and right subtrees' height differ by more than 1 + // or if either of these subtrees is not balanced + // then return -1 + int leftHeight = computeHeight(root.left); + if (leftHeight < 0 ){ + return -1; + } + + int rightHeight = computeHeight(root.right); + if (rightHeight < 0){ + return -1; + } + + if (Math.abs(leftHeight-rightHeight) > 1){ + return -1; + } + else{ + return Math.max(leftHeight,rightHeight)+1; + } + } +} diff --git a/ch4/Solution05.java b/ch4/Solution05.java new file mode 100644 index 0000000..ce0150b --- /dev/null +++ b/ch4/Solution05.java @@ -0,0 +1,92 @@ +/** + * Created by Hakim on 9/20/15. + */ +class TreeNode{ + int val; + TreeNode left; + TreeNode right; + + public TreeNode(int v){ + val = v; + } +} + +public class Solution05 { + public static void main(String[] args){ + Solution05 solution05 = new Solution05(); + // Tree1 is a BST + // 4 + // / \ + // 2 6 + // / \ / \ + // 1 3 5 7 + // \ + // 8 + TreeNode a1 = new TreeNode(4); + TreeNode b1 = new TreeNode(2); + TreeNode c1 = new TreeNode(6); + TreeNode d1 = new TreeNode(1); + TreeNode e1 = new TreeNode(3); + TreeNode f1 = new TreeNode(5); + TreeNode g1 = new TreeNode(7); + TreeNode h1 = new TreeNode(8); + + a1.left = b1; + a1.right = c1; + b1.left = d1; + b1.right = e1; + c1.left = f1; + c1.right = g1; + g1.right = h1; + + System.out.println("solution05.isValid(a1): " + solution05.isValid(a1)); + + // Tree2 is NOT a BST + // 5 + // / \ + // 2 6 + // / \ / \ + // 1 3 5 7 + // \ + // 8 + TreeNode a2 = new TreeNode(5); + TreeNode b2 = new TreeNode(2); + TreeNode c2 = new TreeNode(6); + TreeNode d2 = new TreeNode(1); + TreeNode e2 = new TreeNode(3); + TreeNode f2 = new TreeNode(5); + TreeNode g2 = new TreeNode(7); + TreeNode h2 = new TreeNode(8); + + a2.left = b2; + a2.right = c2; + b2.left = d2; + b2.right = e2; + c2.left = f2; + c2.right = g2; + g2.right = h2; + + System.out.println("solution05.isValid(a2): " + solution05.isValid(a2)); + } + + public boolean isValid(TreeNode root){ + // Assume left subtree nodes must be less or equal to root.val + // right subtree nodes must be greater than root.val + return isValid(root, Integer.MIN_VALUE, Integer.MAX_VALUE); + } + + public boolean isValid(TreeNode root, int min, int max){ + if (root == null){ + return true; + } + + // Check that left nodes are smaller than min and greater than max + // Check no overflow occurs on max value + if (root.val > max || root.val < min || root.val == Integer.MAX_VALUE && root.right != null){ + return false; + } + + // Check that left and right subtrees are valid + return isValid(root.left, min, root.val) && isValid(root.right, root.val+1, max); + } +} diff --git a/ch4/Solution06.java b/ch4/Solution06.java new file mode 100644 index 0000000..3639a99 --- /dev/null +++ b/ch4/Solution06.java @@ -0,0 +1,118 @@ +/** + * Created by Hakim on 9/20/15. + */ +class TreeNode{ + int val; + TreeNode parent; + TreeNode left; + TreeNode right; + + public TreeNode(int v){ + val = v; + } +} + +public class Solution06 { + public static void main(String[] args){ + Solution06 solution06 = new Solution06(); + // Tree: + // 4 + // / \ + // 2 6 + // / \ / \ + // 1 3 5 7 + // \ + // 8 + TreeNode a = new TreeNode(4); + TreeNode b = new TreeNode(2); + TreeNode c = new TreeNode(6); + TreeNode d = new TreeNode(1); + TreeNode e = new TreeNode(3); + TreeNode f = new TreeNode(5); + TreeNode g = new TreeNode(7); + TreeNode h = new TreeNode(8); + + a.left = b; + a.right = c; + b.left = d; + b.right = e; + c.left = f; + c.right = g; + g.right = h; + + b.parent = a; + c.parent = a; + d.parent = b; + e.parent = b; + f.parent = c; + g.parent = c; + h.parent = g; + + + System.out.println("successor of 1: " + solution06.successor(d).val); + System.out.println("successor of 2: " + solution06.successor(b).val); + System.out.println("successor of 3: " + solution06.successor(e).val); + System.out.println("successor of 4: " + solution06.successor(a).val); + System.out.println("successor of 5: " + solution06.successor(f).val); + System.out.println("successor of 6: " + solution06.successor(c).val); + System.out.println("successor of 7: " + solution06.successor(g).val); + System.out.println("successor of 8: " + solution06.successor(h)); + + } + + /** + * Find in-order successor of node node. + * @param node + * @return in-order successor of node + */ + public TreeNode successor(TreeNode node){ + if (node == null){ + return null; + } + + if (node.right != null){ + return leftMost(node.right); + } + else{ + return nextParent(node); + } + } + + /** + * Find the leftmost child of a node. + * @param node - node for which the leftmost child is searched + * @return leftmost child. + */ + public TreeNode leftMost(TreeNode node){ + if (node == null){ + return null; + } + TreeNode current = node; + while (current.left != null){ + current = current.left; + } + + return current; + } + + /** + * Find the next parent in succession order. + * This is the first parent for which the current node is its left child + * @param node - Node for which the next parent is searched + * @return next parent + */ + public TreeNode nextParent(TreeNode node){ + if (node.parent == null){ + return null; + } + TreeNode current = node; + + while (current.parent.left != current){ + current = current.parent; + if (current.parent == null){ + return null; + } + } + return current.parent; + } +} diff --git a/ch4/Solution07.java b/ch4/Solution07.java new file mode 100644 index 0000000..497d1f9 --- /dev/null +++ b/ch4/Solution07.java @@ -0,0 +1,149 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by Hakim on 9/20/15. + */ + +class Graph{ + GraphNode[] nodes; +} + +class GraphNode{ + String name; + List children = new ArrayList<>(); + int incomingEdges; + + public void incrementIncomingEdges(){ + incomingEdges++; + } + + public void decrementIncomingEdges(){ + incomingEdges--; + } + + + public GraphNode(String s){ + name = s; + } + +} + +/** + * Find a build order if one exists. + */ +public class Solution07 { + public static void main(String[] args){ + Solution07 solution07 = new Solution07(); + // example 1: no cycles + String[] projects = {"a","b","c","d","e","f"}; + List dependencies = new ArrayList<>(); + String[] dep1 = {"a","d"}; // d depends on a + String[] dep2 = {"f","b"}; + String[] dep3 = {"b","d"}; + String[] dep4 = {"f","a"}; + String[] dep5 = {"d","c"}; + + dependencies.add(dep1); + dependencies.add(dep2); + dependencies.add(dep3); + dependencies.add(dep4); + dependencies.add(dep5); + System.out.println("Order for graph 1 with no cycles:"); + solution07.printStringArray(solution07.buildOrder(projects, dependencies)); + + // example2: cycle + String[] projects2 = {"a","b","c","d","e","f"}; + List dependencies2 = new ArrayList<>(); + String[] dep21 = {"a","d"}; // d depends on a + String[] dep22 = {"f","b"}; + String[] dep23 = {"b","d"}; + String[] dep24 = {"f","a"}; + String[] dep25 = {"d","c"}; + String[] dep26 = {"c","a"}; + + dependencies2.add(dep21); + dependencies2.add(dep22); + dependencies2.add(dep23); + dependencies2.add(dep24); + dependencies2.add(dep25); + dependencies2.add(dep26); + System.out.println("Order for graph 2 with cycle:"); + solution07.printStringArray(solution07.buildOrder(projects2, dependencies2)); + } + + /** + * Find a build order that will allow the projects given in projects[] to be built + * so that each project is built after the projects it depends on. + * @param projects - list of the projects + * @param dependencies - dependencies: [a,b] -> b depends on a + * @return a valid build order if one exists, null otherwise + */ + public String[] buildOrder(String[] projects, List dependencies){ + String[] order = new String[projects.length]; + + Map map = new HashMap<>(); + // Build the graph + GraphNode[] nodes = new GraphNode[projects.length]; + + // Create all the nodes + for (int i=0; i> bstSequences(TreeNode root){ + List> result = new ArrayList<>(); + LinkedList prefix = new LinkedList<>(); + if (root == null){ + result.add(new LinkedList()); + return result; + } + + prefix.add(root.val); + List> leftResult = bstSequences(root.left); + List> rightResult = bstSequences(root.right); + + // merge the left and right results so that the order in each element + // in the left and right linked lists remain in relative order + mergeResults(leftResult, rightResult, result, prefix); + + return result; + } + + public void mergeResults(List> leftResult, List> rightResult, List> result, LinkedList prefix){ + for (LinkedList lResult : leftResult){ + for (LinkedList rResult : rightResult){ + weave(lResult, rResult, result, prefix); + } + } + } + + public void weave(LinkedList lResult, LinkedList rResult, List> result, LinkedList prefix){ +// System.out.println("weaving " + lResult + " and " + rResult + " with prefix " + prefix); + if (lResult.isEmpty()){ + LinkedList currentResult = (LinkedList) prefix.clone(); + currentResult.addAll(rResult); + result.add(currentResult); + return; + } + if (rResult.isEmpty()){ + LinkedList currentResult = (LinkedList) prefix.clone(); + currentResult.addAll(lResult); + result.add(currentResult); + return; + } + + int lHead = lResult.remove(); + prefix.addLast(lHead); + weave(lResult, rResult, result, prefix); + lResult.add(lHead); + prefix.removeLast(); + + int rHead = rResult.remove(); + prefix.addLast(rHead); + weave(lResult, rResult, result, prefix); + rResult.add(rHead); + prefix.removeLast(); + } +} diff --git a/ch4/Solution10.java b/ch4/Solution10.java new file mode 100644 index 0000000..600c13f --- /dev/null +++ b/ch4/Solution10.java @@ -0,0 +1,90 @@ +/** + * Created by Hakim on 9/22/15. + */ + +/** + * Define a tree node. + */ +class TreeNode{ + int val; + TreeNode left; + TreeNode right; + + public TreeNode(int v){ + val = v; + } +} + +/** + * Check whether a tree is another's subtree. + */ +public class Solution10 { + public static void main(String[] args){ + Solution10 solution10 = new Solution10(); + // tree1 + // 6 + // / \ + // 5 9 + // / \ + // 3 1 + TreeNode a = new TreeNode(6); + TreeNode b = new TreeNode(5); + TreeNode c = new TreeNode(9); + TreeNode d = new TreeNode(3); + TreeNode e = new TreeNode(1); + + a.left = b; + a.right = c; + b.left = d; + b.right = e; + + // tree2 (is subtree of t1) + // 5 + // / \ + // 3 1 + TreeNode f = new TreeNode(5); + TreeNode g = new TreeNode(3); + TreeNode h = new TreeNode(1); + + f.left = g; + f.right = h; + + // tree3 (is not subtree of t1) + // 5 + // / \ + // 3 2 + + TreeNode i = new TreeNode(5); + TreeNode j = new TreeNode(3); + TreeNode k = new TreeNode(2); + + i.left = j; + i.right = k; + + System.out.println("Is tree2 a subtree of tree1: " + solution10.isSubtree(a,f)); + System.out.println("Is tree2 a subtree of tree1: " + solution10.isSubtree(a,i)); + + } + + /** + * Check whether t2 is a subtree of t1. + * @param t1 + * @param t2 + * @return true if t2 is a subtree of t1. false otherwise + */ + public boolean isSubtree(TreeNode t1, TreeNode t2) { + if (t2 == null) { + return true; // empty tree is a subtree of any tree + } + if (t1 == null) { + // we already checked that t2 is not null + return false; + } + if (t1.val == t2.val){ + return isSubtree(t1.left, t2.left) && isSubtree(t1.right, t2.right); + } + else{ + return isSubtree(t1.left, t2) || isSubtree(t1.right, t2); + } + } +} diff --git a/ch4/Solution11.java b/ch4/Solution11.java new file mode 100644 index 0000000..fa4ceb7 --- /dev/null +++ b/ch4/Solution11.java @@ -0,0 +1,224 @@ +import java.util.Random; + +/** + * Created by Hakim on 9/23/15. + */ + +/** + * Define a Tree. + */ +class Tree { + TreeNode root; + + public void deleteNode(TreeNode node){ + if (root == null){ + return; + } + TreeNode toDelete = root.findNode(node.val); + + toDelete.deleteNode(); + } + + public void insertNode(TreeNode node){ + if (root == null){ + root = node; + } + else{ + root.insertNode(node); + } + } + + public TreeNode getRandomNode(){ + Random random = new Random(); + int index = random.nextInt(getSize(root)); + return findITh(root, index); + } + + public TreeNode findITh(TreeNode root, int index){ +// System.out.println("root.val " + root.val + " index " + index + " leftSize " + getSize(root.left)); + if (index == getSize(root.left)){ + return root; + } + else if (index < getSize(root.left)){ + return findITh(root.left, index); + } + else{ + return findITh(root.right, index-getSize(root.left)-1); + } + } + + public int getSize(TreeNode root){ + if (root == null){ + return 0; + } + else{ + return root.size; + } + } +} + +/** + * Define a TreeNode. + */ +class TreeNode { + int val; + TreeNode parent; + TreeNode left; + TreeNode right; + int size = 1; + + public TreeNode(int v){ + val = v; + } + + public void insertNode(TreeNode node){ + if (node.val <= val){ + if (left != null){ + left.insertNode(node); + } + else{ + left = new TreeNode(node.val); + left.parent = this; + } + } + else{ + if (right != null){ + right.insertNode(node); + } + else{ + right = new TreeNode(node.val); + right.parent = this; + } + } + size++; + } + + public TreeNode findNode(int v){ + if (val == v){ + return this; + } + else if (v <= val) { + if (left != null) { + return left.findNode(v); + } + else{ + return null; + } + } + else { + if (right != null) { + return right.findNode(v); + } + else{ + return null; + } + } + } + + public void deleteNode(){ + if (left == null && right == null){ + if (parent.left == this){ + parent.left = null; + } + else{ + parent.right = null; + } + } + else if (left == null && right != null){ + parent.right = right; + this.right = null; + } + else if (left != null && right == null){ + parent.left = left; + this.left = null; + } + else{ + // the current node has both a left and a right child + // randomly choose to replace it with its successor or + // its predecessor + Random random = new Random(); + int chooseLeft = random.nextInt(2); + if (chooseLeft == 0){ + // replace with the predecessor + TreeNode predecessor = this.findPredecessor(); + this.replaceNode(predecessor); + } + else{ + // replace with the successor + TreeNode successor = this.findSuccessor(); + this.replaceNode(successor); + } + } + TreeNode p = parent; + while (p != null){ + p.size --; + p = p.parent; + } + } + + public void replaceNode(TreeNode replacement){ + this.val = replacement.val; + replacement.deleteNode(); + } + + public TreeNode findPredecessor(){ + // this.left is assumed to be non null + TreeNode currentLeft = this.left; + while (currentLeft.right != null){ + currentLeft = currentLeft.right; + } + return currentLeft; + } + + public TreeNode findSuccessor(){ + // this.right is assumed to be non null + TreeNode currentRight = this.right; + while (currentRight.left != null){ + currentRight = currentRight.left; + } + return currentRight; + } + +} + +public class Solution11 { + public static void main(String[] args){ + // build tree: + // 20 + // / \ + // 10 30 + // / \ \ + // 5 15 35 + // / \ \ + // 3 7 17 + + Tree tree = new Tree(); + tree.insertNode(new TreeNode(20)); + tree.insertNode(new TreeNode(10)); + tree.insertNode(new TreeNode(30)); + tree.insertNode(new TreeNode(5)); + tree.insertNode(new TreeNode(15)); + tree.insertNode(new TreeNode(35)); + tree.insertNode(new TreeNode(3)); + tree.insertNode(new TreeNode(7)); + tree.insertNode(new TreeNode(17)); + + System.out.println("tree.root.size " + tree.root.size); + System.out.println("deleting node : " + tree.root.right.val); + tree.deleteNode(tree.root.right); + System.out.println("new node at the right of root: " + tree.root.right.val); + System.out.println("new tree size: " + tree.root.size); + System.out.println("Random node: " + tree.getRandomNode().val); + System.out.println("Random node: " + tree.getRandomNode().val); + System.out.println("Random node: " + tree.getRandomNode().val); + System.out.println("Random node: " + tree.getRandomNode().val); + System.out.println("Random node: " + tree.getRandomNode().val); + System.out.println("Random node: " + tree.getRandomNode().val); + System.out.println("Random node: " + tree.getRandomNode().val); + System.out.println("Random node: " + tree.getRandomNode().val); + System.out.println("Random node: " + tree.getRandomNode().val); + System.out.println("Random node: " + tree.getRandomNode().val); + System.out.println("Random node: " + tree.getRandomNode().val); + System.out.println("Random node: " + tree.getRandomNode().val); + } +} diff --git a/ch4/Solution12.java b/ch4/Solution12.java new file mode 100644 index 0000000..8fb352b --- /dev/null +++ b/ch4/Solution12.java @@ -0,0 +1,90 @@ +/** + * Created by Hakim on 9/22/15. + */ + +class TreeNode{ + int val; + TreeNode left; + TreeNode right; + + public TreeNode(int v){ + val = v; + } +} +public class Solution12 { + public static void main(String[] args){ + Solution12 solution12 = new Solution12(); + // tree1: + // 7 + // / \ + // 3 -1 + + TreeNode a1 = new TreeNode(7); + TreeNode b1 = new TreeNode(3); + TreeNode c1 = new TreeNode(-1); + + a1.left = b1; + a1.right = c1; + + System.out.println("number of paths in tree1 summing to 10: " + solution12.numberOfPaths(a1,10)); + System.out.println("number of paths in tree1 summing to 6: " + solution12.numberOfPaths(a1,6)); + System.out.println("number of paths in tree1 summing to 1: " + solution12.numberOfPaths(a1,1)); + + // tree2: + // 10 + // / \ + // 5 -3 + // / \ \ + // 3 2 11 + // / \ \ + // 3 -2 1 + + TreeNode a2 = new TreeNode(10); + TreeNode b2 = new TreeNode(5); + TreeNode c2 = new TreeNode(-3); + TreeNode d2 = new TreeNode(3); + TreeNode e2 = new TreeNode(2); + TreeNode f2 = new TreeNode(11); + TreeNode g2 = new TreeNode(3); + TreeNode h2 = new TreeNode(-2); + TreeNode i2 = new TreeNode(1); + + a2.left = b2; + a2.right = c2; + b2.left = d2; + b2.right = e2; + c2.right = f2; + d2.left = g2; + d2.right = h2; + e2.right = i2; + + System.out.println("\nnumber of paths in tree2 summing to 8: " + solution12.numberOfPaths(a2,8)); + + + } + + /** + * Brute force solution.... + * @param root + * @param target + * @return + */ + public int numberOfPaths(TreeNode root, int target){ + if (root.val == target){ + return 0; + } + return numberOfPathsFromNode(root, target) + numberOfPathsFromNode(root.left, target) + numberOfPathsFromNode(root.right, target); + } + + public int numberOfPathsFromNode(TreeNode root, int target){ + if (root == null){ + return 0; + } + if (target == root.val){ + return 1; + } + return numberOfPathsFromNode(root.left, target-root.val) + numberOfPathsFromNode(root.right,target-root.val); + } + + +} From a880a31188d143e1edfaff6ae0d492abbbabf02d Mon Sep 17 00:00:00 2001 From: Hakim Date: Thu, 1 Oct 2015 10:37:19 -0400 Subject: [PATCH 4/6] chapter 10 --- ch10/Solution01.java | 56 +++++++++++++++++ ch10/Solution02.java | 58 +++++++++++++++++ ch10/Solution03.java | 78 +++++++++++++++++++++++ ch10/Solution04.java | 135 +++++++++++++++++++++++++++++++++++++++ ch10/Solution05.java | 88 ++++++++++++++++++++++++++ ch10/Solution06.java | 37 +++++++++++ ch10/Solution07.java | 147 +++++++++++++++++++++++++++++++++++++++++++ ch10/Solution08.java | 72 +++++++++++++++++++++ ch10/Solution09.java | 96 ++++++++++++++++++++++++++++ ch10/Solution10.java | 117 ++++++++++++++++++++++++++++++++++ ch10/Solution11.java | 99 +++++++++++++++++++++++++++++ ch10/input1 | 7 +++ 12 files changed, 990 insertions(+) create mode 100644 ch10/Solution01.java create mode 100644 ch10/Solution02.java create mode 100644 ch10/Solution03.java create mode 100644 ch10/Solution04.java create mode 100644 ch10/Solution05.java create mode 100644 ch10/Solution06.java create mode 100644 ch10/Solution07.java create mode 100644 ch10/Solution08.java create mode 100644 ch10/Solution09.java create mode 100644 ch10/Solution10.java create mode 100644 ch10/Solution11.java create mode 100644 ch10/input1 diff --git a/ch10/Solution01.java b/ch10/Solution01.java new file mode 100644 index 0000000..79431d6 --- /dev/null +++ b/ch10/Solution01.java @@ -0,0 +1,56 @@ +/** + * Created by Hakim on 9/27/15. + */ +public class Solution01 { + public static void main(String[] args){ + Solution01 solution01 = new Solution01(); + int[] arrayA = {0,1,4,7,0,0,0}; + int numElementsA = 4; + int[] arrayB = {2,3,8}; + + solution01.mergeSort(arrayA,arrayB,numElementsA); + for (int i=0; i= 0 && pointB >= 0){ + if (arrayA[pointA] > arrayB[pointB]){ + arrayA[last] = arrayA[pointA]; + pointA--; + } + else{ + arrayA[last] = arrayB[pointB]; + pointB--; + } + last--; + } + + if (pointB < 0){ + return; + } + if (pointA < 0){ + while (pointB >= 0){ + arrayA[last] = arrayB[pointB]; + pointB--; + last--; + } + } + } +} diff --git a/ch10/Solution02.java b/ch10/Solution02.java new file mode 100644 index 0000000..acc56da --- /dev/null +++ b/ch10/Solution02.java @@ -0,0 +1,58 @@ +import java.util.*; + +/** + * Created by Hakim on 9/27/15. + */ +public class Solution02 { + public static void main(String[] args){ + Solution02 solution02 = new Solution02(); + String[] arr = {"", "abcd", "dcab", "cdab", "aer", "are", "e"}; + solution02.groupAnagrams(arr); + solution02.printArray(arr); + } + + /** + * Sort array of strings so that all the anagrams are next to each other. + * @param array + */ + public void groupAnagrams(String[] array){ + Map> anagrams = new HashMap<>(); + + for (int i=0; i> e : anagrams.entrySet()){ + List lst = e.getValue(); + for (String s : lst) { + array[i] = s; + i++; + } + } + } + + /** + * Add element to HashMap, creating a new entry if none exists already. + * @param map + * @param toAdd + */ + public void addElement(Map> map, String toAdd){ + char[] arrayToAdd = toAdd.toCharArray(); + Arrays.sort(arrayToAdd); + if (map.containsKey(arrayToAdd.toString())){ // can't use array as equal points to specific object + map.get(arrayToAdd.toString()).add(toAdd); + } + else{ + List lst = new ArrayList<>(); + lst.add(toAdd); + map.put(arrayToAdd.toString(),lst); + } + } + + public void printArray(String[] array){ + for (int i=0; i= high) { + return -1; + } + int mid = (low + high) / 2; + if (array[mid] > array[mid + 1]) { + return mid; + } + if (array[low] >= array[high]) { + return Math.max(findPivot(array, low, mid), findPivot(array, mid + 1, high)); + } + else{ + return -1; + } + } + + /** + * Do binary search in array between l and h. + * @param array + * @param l + * @param h + * @param x + * @return index of x if between l and h. -1 otherwise + */ + public int binarySearch(int[] array, int l, int h, int x){ + int low = l; + int high = h; + int mid; + + while (low <= high){ + mid = (low+high)/2; + if (array[mid] > x){ + high = mid-1; + } + else if (array[mid] < x){ + low = mid+1; + } + else{ + return mid; + } + } + return -1; + } +} diff --git a/ch10/Solution04.java b/ch10/Solution04.java new file mode 100644 index 0000000..588b375 --- /dev/null +++ b/ch10/Solution04.java @@ -0,0 +1,135 @@ +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Hakim on 9/28/15. + */ + +/** + * Define the Listy class. + */ +class Listy{ + List lst = new ArrayList<>(); + + public Listy(List l){ + lst.addAll(l); + } + + public int elementAt(int i){ + return lst.get(i); + } + +} + +/** + * Sorted seach, no size. + */ +public class Solution04 { + public static void main(String[] args){ + Solution04 solution04 = new Solution04(); + List l = new ArrayList<>(); + l.add(1); + l.add(3); + l.add(4); + l.add(5); + l.add(6); + l.add(7); + l.add(10); + l.add(-1); + l.add(-1); + + Listy listy = new Listy(l); + System.out.println("findIndex(listy,1) " + solution04.findIndex(listy,1)); + System.out.println("findIndex(listy,3) " + solution04.findIndex(listy,3)); + System.out.println("findIndex(listy,4) " + solution04.findIndex(listy,4)); + System.out.println("findIndex(listy,5) " + solution04.findIndex(listy,5)); + System.out.println("findIndex(listy,6) " + solution04.findIndex(listy,6)); + System.out.println("findIndex(listy,7) " + solution04.findIndex(listy,7)); + System.out.println("findIndex(listy,10) " + solution04.findIndex(listy,10)); + System.out.println("findIndex(listy,8) - not in list " + solution04.findIndex(listy,8)); + } + + /** + * Find index of element x (positive) in Listy. + * @param listy + * @param x + * @return index of x if present in list. -1 otherwise + */ + public int findIndex(Listy listy, int x){ + // Find the size of listy + int size = findSize(listy); + + // Do binary search on listy + return binarySearch(listy, 0, size-1, x); + } + + /** + * Find size of Listy in log time. + * @param listy + * @return size of listy + */ + public int findSize(Listy listy){ + if (listy == null || listy.elementAt(0) == -1){ + return 0; + } + + int n = 1; + while (listy.elementAt(n) > -1){ + n = 2*n; + } + int size = binarySearchMax(listy, n/2, n) + 1; + return size; + } + + /** + * Do binary search in Listy to find element x. + * @param listy + * @param low + * @param high + * @param x + * @return index of x if present. -1 otherwise + */ + public int binarySearch(Listy listy, int low, int high, int x){ + if (low > high){ + return -1; + } + + int mid = (low+high)/2; + if (listy.elementAt(mid) == x){ + return mid; + } + else if (listy.elementAt(mid) < x){ + return binarySearch(listy, mid+1, high, x); + } + else if (listy.elementAt(mid) > x){ + return binarySearch(listy, low, mid-1, x); + } + return -1; + } + + /** + * Find largest index in Listy that is not -1. + * @param listy + * @param min + * @param max + * @return largest index different from -1 if exists. -1 otherwise + */ + public int binarySearchMax(Listy listy, int min, int max){ + if (min > max){ + return -1; + } + + int mid = (min+max)/2; + if (listy.elementAt(mid) > -1 && listy.elementAt(mid+1) == -1){ + return mid; + } + else if (listy.elementAt(mid) == -1) { + return binarySearchMax(listy, min, mid-1); + } + else if (listy.elementAt(mid) > -1){ + return binarySearchMax(listy, mid+1, max); + } + return -1; + } + +} diff --git a/ch10/Solution05.java b/ch10/Solution05.java new file mode 100644 index 0000000..d7e7ce1 --- /dev/null +++ b/ch10/Solution05.java @@ -0,0 +1,88 @@ +/** + * Created by Hakim on 9/28/15. + */ + +/** + * Sparse search. + */ +public class Solution05 { + public static void main(String[] args){ + Solution05 solution05 = new Solution05(); + String[] array = {"at", "", "", "", "ball", "", "", "car", "", "", "dad", "", ""}; + System.out.println("index of ball: " + solution05.binarySearchSparse(array, "ball")); + System.out.println("index of at: " + solution05.binarySearchSparse(array, "at")); + System.out.println("index of dad: " + solution05.binarySearchSparse(array, "dad")); + System.out.println("index of da (not in array): " + solution05.binarySearchSparse(array, "da")); + } + + /** + * Find a String in an array intersperced with empty strings. + * @param array + * @param target + * @return index of the String if it exists in the array. -1 otherwise. Note that searching the + * empty string will return an index where this string occurs if one exists + */ + public int binarySearchSparse(String[] array, String target){ + return binarySearchSparse(array, 0, array.length-1, target); + } + + /** + * Recursive binary search in a sparse array. + * @param array + * @param low + * @param high + * @param target + * @return index of target in the array if it occurs there. -1 otherwise + */ + public int binarySearchSparse(String[] array, int low, int high, String target) { + if (low > high){ + return -1; + } + + int mid = (low+high)/2; + + if (array[mid].equals(target)){ + return mid; + } + else if (array[mid].length() != 0 && array[mid].compareTo(target) > 0){ + return binarySearchSparse(array, low, mid-1, target); + } + else if (array[mid].length() != 0 && array[mid].compareTo(target) < 0){ + return binarySearchSparse(array, mid+1, high, target); + } + else if (array[mid].length() == 0){ + int midL = mid; + int midR = mid; + + while (midL >= low){ + if (array[midL].length() == 0){ + midL--; + } + else if (array[midL].equals(target)){ + return midL; + } + else if ((array[low].length() == 0 | array[low].compareTo(target) <= 0) && array[midL].compareTo(target) > 0){ + return binarySearchSparse(array, low, midL-1, target); + } + else{ + break; + } + } + while (midR <= high){ + if (array[midR].length() == 0){ + midR++; + } + else if (array[midR].equals(target)){ + return midR; + } + else if ((array[high].length() == 0 | array[high].compareTo(target) >= 0) && array[midR].compareTo(target) < 0){ + return binarySearchSparse(array, midR+1, high, target); + } + else{ + break; + } + } + } + return -1; + } +} diff --git a/ch10/Solution06.java b/ch10/Solution06.java new file mode 100644 index 0000000..50ad442 --- /dev/null +++ b/ch10/Solution06.java @@ -0,0 +1,37 @@ +/** + * Created by Hakim on 9/29/15. + */ + +/** + * Sort big file. + */ +public class Solution06 { + public static void main(String[] args){ + + String solution = "We will use an external sorting procedure, namely an external merge sort" + + "Assume we have x MB of memory available.\n" + + "We divide the file in disk into chunks of size 20GB/xMB\n" + + "We load each chunk separately in memory and sort it using " + + "a standard sorting algorithm, like quick sort (or an algorithm which does not require extra space)\n" + + "Each sorted chunk is saved back to disk\n" + + "once all the chunks have been processed, we will merge them.\n" + + "To do so, we divide each chunk into subchunks of size xMB/(number of chunks + 1)." + + " We load each subchunk into memory, and allocate a buffer of size xMB/(number of chunks + 1) as well" + + "We perform an n-way merge on these chunks (n = number of subchunks loaded) and save" + + " the result in the buffer space allocated. Every time this buffer is full, we empty it to " + + "disk (with the final result). Every time a subchunk loaded into memory is empty, we fill it with" + + " the next part from it chunk in disk.\n" + + "For example, if we assume that we use 1 GB of RAM, we will divide the original file into" + + " 20 chunks of 1 GB each. Each of these chunks will be sorted in memory. When performing merge sort," + + " we will load 1GB/21 of each chunk at a time.\n" + + "\nThis merge phase of this procedure as described would not be efficient if the " + + "memory available is small. Assume, for example, that we have 0.1GB available instead of 1GB. In that " + + "case, 20GB/0.1 = 200 chunks. The size allocated for each of these chunks in memory when merging them " + + "would be 0.1GB/200 = 512KB. The cost of IO operations to refill the chunks and empty the buffer would " + + "slow down the soring process considerably. In this situation, we can choose to perform more merge sweeps." + + " For instance, we could first merge 20 chunks at a time. Each would be ~5MB. This would result in " + + "10 chunks that we could merge in a second pass."; + + System.out.println(solution); + } +} diff --git a/ch10/Solution07.java b/ch10/Solution07.java new file mode 100644 index 0000000..0b3de6f --- /dev/null +++ b/ch10/Solution07.java @@ -0,0 +1,147 @@ +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Scanner; + +/** + * Created by Hakim on 9/30/15. + */ +public class Solution07 { + public static void main(String[] args) throws Exception{ // should handle it + Solution07 solution07 = new Solution07(); + String file = "src/input1"; + System.out.println("generate missing v1: " + solution07.generateMissingInt(file)); + System.out.println("generate missing v2: " + solution07.generateMissingIntV2(file)); + } + + public int generateMissingInt(String inputFile) throws Exception{ + // create bit vector that can store all the non negative ints + // for each integer read in the inputFile, + // we mark this int with a bit 1 in the corresponding place + byte[] bitVector = new byte[Integer.MAX_VALUE/8+1]; + + // read file line by line + Scanner scanner = new Scanner(new File(inputFile)); + while (scanner.hasNextInt()){ + int current = scanner.nextInt(); + addToBitVector(bitVector, current); + } + + // read the bit vector, searching for a 0 bit + int zeroBit = -1; + for (int i=0; i -1){ + break; + } + } + + return zeroBit; + } + + public void addToBitVector(byte[] bitVector, int current){ + // find index + int index = findIndex(current); + // find offset + int offset = findOffset(current); + int mask = createMask(offset); + bitVector[index] |= mask; + } + + public int findIndex(int number){ + return number/8; + } + + public int findOffset(int number){ + return number%8; + } + + public int createMask(int offset){ + return (1<>1; + offset++; + } + } + + return 8 * index + offset; + } + + + /** + * Follow up: What if only 10MB of memory available and all the + * numbers are distinct. + * No more than 1b values. + * @return + */ + public int generateMissingIntV2(String inputFile) throws FileNotFoundException{ + int[] array = new int[(1<<20)]; // 2^(31-20) ints per index = 2^11 + byte[] bitVector = new byte[(1<<8)]; + + Scanner scanner = new Scanner(new File(inputFile)); + while (scanner.hasNextInt()){ + int n = scanner.nextInt(); + incrementArray(array, n); + } + + int missingRange = 0; + // check the number of elements in each range + for (int i=0; i>1; + offset++; + } + } + + return beginRange + 8 * index + offset; + } + + public void incrementArray(int[] array, int n){ + array[n/(1<<11)]++; + } + +} diff --git a/ch10/Solution08.java b/ch10/Solution08.java new file mode 100644 index 0000000..22cd118 --- /dev/null +++ b/ch10/Solution08.java @@ -0,0 +1,72 @@ +/** + * Created by Hakim on 9/30/15. + */ + +/** + * Find duplicates. + */ +public class Solution08 { + public static void main(String[] args){ + Solution08 solution08 = new Solution08(); + int[] array = {1,2,8,2,4,5,6,8,2,3,4,10}; // duplicates: 2,8,4 + solution08.printAllDuplicates(array); + } + + /** + * Given an array of numbers <= N <= 32000, print all the duplicate elements. + * @param array + */ + public void printAllDuplicates(int[] array){ + // The maximum value N that can be contained in the array + // is 32000 + // 32,000 bits <= 4 KB. + // We can represent the set of values in the array using + // a bit vector with 32,000 bits (of size 4KB) + // We loop through the array. If a value is seen for the first + // time, we set the corresponding bit to 1 + // otherwise we print the value + + byte[] bitVector = new byte[4000]; + for (int i=0; i result1 = solution09.findElement(array,5); + List result10 = solution09.findElement(array,10); + System.out.println("Position of 5 (expect 1,2): " + result1.get(0)+ ", " + result1.get(1)); + System.out.println("Position of 10 (expect -1,-1): " + result10.get(0)+ ", " + result10.get(1)); + } + + public List findElement(int[][] array, int x){ + return findElement(array, 0, array.length-1, 0, array[0].length-1, x); + } + + /** + * Find an element in a M x N matrix for which each row and column is sorted in ascending order. + * @param array + * @param rowLow + * @param rowHigh + * @param colLow + * @param colHigh + * @param x + * @return + */ + public List findElement(int[][] array, int rowLow, int rowHigh, int colLow, int colHigh, int x){ + //System.out.println("rowLow " + rowLow + " rowHigh " + rowHigh + " colLow " + colLow + " colHigh " + colHigh); + + if (rowLow > rowHigh || colLow > colHigh){ + return minusOnes(); + } + + int rowMiddle = (rowLow + rowHigh)/2; + int colMiddle = (colLow + colHigh)/2; + + if (array[rowMiddle][colLow] == x){ + return coordinates(rowMiddle,colLow); + } + else if (array[rowMiddle][colLow] < x){ + if (array[rowMiddle][colHigh] < x){ + rowLow = rowMiddle + 1; + } + else{ + rowLow = rowMiddle; + } + } + else { + rowHigh = rowMiddle-1; + } + + if (rowLow > rowHigh){ + return minusOnes(); + } + + if (array[rowLow][colMiddle] == x) { + return coordinates(rowLow, colMiddle); + } + else if (array[rowLow][colMiddle] < x) { + if (array[rowHigh][colMiddle] < x){ + colLow = colMiddle + 1; + } + else{ + colLow = colMiddle; + } + } + else { + colHigh = colMiddle-1; + } + + return findElement(array, rowLow, rowHigh, colLow, colHigh, x); + } + + public List minusOnes(){ + List result = new ArrayList<>(); + result.add(-1); + result.add(-1); + return result; + } + + public List coordinates(int x, int y){ + List result = new ArrayList<>(); + result.add(x); + result.add(y); + return result; + } + +} diff --git a/ch10/Solution10.java b/ch10/Solution10.java new file mode 100644 index 0000000..07fc058 --- /dev/null +++ b/ch10/Solution10.java @@ -0,0 +1,117 @@ +/** + * Created by Hakim on 9/29/15. + */ + +/** + * Define a Tree. + */ +class Tree{ + TreeNode root; + + /** + * Insert a new number into the Tree. + * @param x + */ + public void track(int x){ + if (root == null){ + root = new TreeNode(x); + } + else{ + root.track(new TreeNode(x)); + } + } + + /** + * Get rank of x in the Tree. + * @param x + * @return + */ + public int getRankOfNumber(int x){ + if (root == null){ + return -1; + } + else{ + return root.getRankOfNumber(x); + } + } +} + +/** + * Define a TreeNode. + */ +class TreeNode{ + int val; + TreeNode left; + TreeNode right; + int rank; + + public TreeNode(int v){ + val = v; + } + + public void track(TreeNode x){ + if (x.val <= val){ + if (left == null){ + left = x; + } + else{ + left.track(x); + } + rank++; + } + else{ + if (right == null){ + right = x; + } + else{ + right.track(x); + } + x.rank = rank+1; + } + } + + public int getRankOfNumber(int x){ + if (val == x){ + return rank; + } + else if (x <= val){ + if (left == null){ + return -1; + } + else{ + return left.getRankOfNumber(x); + } + } + else{ + if (right == null){ + return -1; + } + else{ + return right.getRankOfNumber(x); + } + } + } +} + +public class Solution10 { + public static void main(String[] args){ + Tree tree = new Tree(); + tree.track(5); + tree.track(1); + tree.track(4); + tree.track(4); + tree.track(5); + tree.track(9); + tree.track(7); + tree.track(13); + tree.track(3); + + System.out.println(" rank of 1: " + tree.getRankOfNumber(1)); + System.out.println(" rank of 3: " + tree.getRankOfNumber(3)); + System.out.println(" rank of 4: " + tree.getRankOfNumber(4)); + System.out.println(" rank of 44: " + tree.getRankOfNumber(44)); + } + + + +} diff --git a/ch10/Solution11.java b/ch10/Solution11.java new file mode 100644 index 0000000..0f201fa --- /dev/null +++ b/ch10/Solution11.java @@ -0,0 +1,99 @@ +/** + * Created by Hakim on 9/29/15. + */ + +/** + * Peaks and Valleys. + */ +public class Solution11 { + public static void main(String[] args){ + Solution11 solution11 = new Solution11(); + int[] array = {5,3,1,2,3}; + System.out.println("Before rearranging:"); + solution11.printArray(array); + solution11.rearrangePeaksValleys(array); + System.out.println("\nAfter rearranging:"); + solution11.printArray(array); + + int[] array2 = {1,2,6,2,3,7,7,7,55,3,1,2,3}; + System.out.println("\nBefore rearranging:"); + solution11.printArray(array2); + solution11.rearrangePeaksValleys(array2); + System.out.println("\nAfter rearranging:"); + solution11.printArray(array2); + } + + /** + * Rearrange an array into a succession of peaks and valleys. + * @param array + */ + public void rearrangePeaksValleys(int[] array){ + // Rearrange array into a sequence of peaks/valleys (starting with a peak) + int len = array.length; + if (len < 2){ + return; + } + + // Rearrange the first two elements to start with a peak + if (array[1] > array[0]){ + swap(array, 0, 1); + } + if (len == 2){ + return; + } + + // Go every two elements in the array and make it a peak + // the other elements will automatically become valleys + for (int i=2; i Date: Wed, 7 Oct 2015 22:33:22 -0400 Subject: [PATCH 5/6] Chapters 5 and 6 --- ch5/Solution01.java | 30 +++++++++ ch5/Solution02.java | 52 +++++++++++++++ ch5/Solution03.java | 51 +++++++++++++++ ch5/Solution04.java | 156 ++++++++++++++++++++++++++++++++++++++++++++ ch5/Solution05.java | 16 +++++ ch5/Solution06.java | 47 +++++++++++++ ch5/Solution07.java | 51 +++++++++++++++ ch5/Solution08.java | 118 +++++++++++++++++++++++++++++++++ ch6/Solution01.java | 67 +++++++++++++++++++ ch6/Solution02.java | 41 ++++++++++++ ch6/Solution03.java | 17 +++++ ch6/Solution04.java | 29 ++++++++ ch6/Solution05.java | 27 ++++++++ ch6/Solution06.java | 28 ++++++++ ch6/Solution07.java | 62 ++++++++++++++++++ ch6/Solution08.java | 91 ++++++++++++++++++++++++++ ch6/Solution09.java | 28 ++++++++ ch6/Solution10.java | 95 +++++++++++++++++++++++++++ 18 files changed, 1006 insertions(+) create mode 100644 ch5/Solution01.java create mode 100644 ch5/Solution02.java create mode 100644 ch5/Solution03.java create mode 100644 ch5/Solution04.java create mode 100644 ch5/Solution05.java create mode 100644 ch5/Solution06.java create mode 100644 ch5/Solution07.java create mode 100644 ch5/Solution08.java create mode 100644 ch6/Solution01.java create mode 100644 ch6/Solution02.java create mode 100644 ch6/Solution03.java create mode 100644 ch6/Solution04.java create mode 100644 ch6/Solution05.java create mode 100644 ch6/Solution06.java create mode 100644 ch6/Solution07.java create mode 100644 ch6/Solution08.java create mode 100644 ch6/Solution09.java create mode 100644 ch6/Solution10.java diff --git a/ch5/Solution01.java b/ch5/Solution01.java new file mode 100644 index 0000000..9da0dac --- /dev/null +++ b/ch5/Solution01.java @@ -0,0 +1,30 @@ +/** + * Created by Hakim on 10/2/15. + */ + +/** + * 5.1. + */ +public class Solution01 { + public static void main(String[] args){ + Solution01 solution01 = new Solution01(); + int N = (1 << 10); + int M = 19; + int inserted = solution01.insertBits(N, M, 2, 6); + System.out.println("Inserted: (expect 1100) " + inserted); + + } + + /** + * Given two 32 bits numbers and two bit positions, insert M in + * N between bits i and j. + * @param N + * @param M + * @return + */ + public int insertBits(int N, int M, int i, int j){ + // Clear bits between i and j in N + int mask = ~((~0 >>> (31-(j-i))) << i); + return (N & mask) | (M << i); + } +} diff --git a/ch5/Solution02.java b/ch5/Solution02.java new file mode 100644 index 0000000..34b3287 --- /dev/null +++ b/ch5/Solution02.java @@ -0,0 +1,52 @@ +/** + * Created by Hakim on 10/2/15. + */ + +/** + * 5.2. + */ +public class Solution02 { + public static void main(String[] args){ + Solution02 solution02 = new Solution02(); + double d1 = 0.72; + System.out.println("Representation of " + d1 + ": " + solution02.binaryToString(d1)); + double d2 = 0.5 + 0.125; + System.out.println("Representation of " + d2 + ": " + solution02.binaryToString(d2)); + } + + /** + * Return the binary representation of a real number between 0 and 1. Return ERROR if the binary representation + * would require more than 32 bits. + * @param num + * @return + */ + public String binaryToString(double num){ + if (num == 0 || num == 1){ + // no '.' + return Double.toString(num); + } + + int n = 0; // count the number of digits needed to represent num + for (int i=0; i<32; i++){ + if (num == Math.floor(num)){ + break; + } + num *= 2; + n++; + } + + // if more than 32 characters are needed (excluding '.'), then print "ERROR" + if (n == 32){ + return "ERROR"; + } + + StringBuilder sb = new StringBuilder(); + while (num >= 1){ + sb.insert(0,Integer.toString((int)num&1)); + num /= 2; + } + + sb.insert(0, "."); + return sb.toString(); + } +} diff --git a/ch5/Solution03.java b/ch5/Solution03.java new file mode 100644 index 0000000..a4a5205 --- /dev/null +++ b/ch5/Solution03.java @@ -0,0 +1,51 @@ +/** + * Created by Hakim on 10/2/15. + */ + +/** + * 5.3. + */ +public class Solution03 { + public static void main(String[] args){ + Solution03 solution03 = new Solution03(); + System.out.println("Longest possible sequence for " + Integer.toBinaryString(1775) + ": " + solution03.lengthLongestSequence(1775)); + } + + /** + * Find the length of the longest sequence of 1s you can create in the binary representation of an integer, begin + * able to flip exaclty one 0 to a 1. + * @param n + * @return + */ + public int lengthLongestSequence(int n){ + int longest = 0; + int begin = 0, end = 0; + boolean hasZero = false; + + int currentBit = 0; + while (n != 0){ + if ((n & 1) == 0){ + if (hasZero){ + longest = ((end-begin+1) > longest) ? (end-begin+1) : longest; + hasZero = false; + begin = currentBit+1; + end = currentBit+1; + } + else{ + hasZero = true; + end = currentBit; + } + } + else{ + end = currentBit; + } + + n >>= 1; + currentBit++; + } + // if MSB is 1 + longest = ((end-begin+1) > longest) ? (end-begin+1) : longest; + + return longest; + } +} diff --git a/ch5/Solution04.java b/ch5/Solution04.java new file mode 100644 index 0000000..6bc0d70 --- /dev/null +++ b/ch5/Solution04.java @@ -0,0 +1,156 @@ +/** + * Created by Hakim on 10/6/15. + */ +public class Solution04 { + public static void main(String[] argv){ + Solution04 solution04 = new Solution04(); + + System.out.println("getNext(14) = getNext(" + Integer.toBinaryString(14) + ") = " + solution04.getNext(14) + + " = " + Integer.toBinaryString(solution04.getNext(14))); + + System.out.println("getNext(15) = getNext(" + Integer.toBinaryString(15) + ") = " + solution04.getNext(15) + + " = " + Integer.toBinaryString(solution04.getNext(15))); + + System.out.println("getPrevious(14) = getPrevious(" + Integer.toBinaryString(14) + ") = " + + solution04.getPrevious(14) + " = " + Integer.toBinaryString(solution04.getPrevious(14))); + + System.out.println("getPrevious(15) = getPrevious(" + Integer.toBinaryString(15) + ") = " + + solution04.getPrevious(15) + " = " + Integer.toBinaryString(solution04.getPrevious(15))); + + + } + + /** + * Get the next number greater than n with the same number of 1 bits (return -1 if no such numbers). + * @param n + * @return + */ + public int getNext(int n){ + // flip the smallest non trailing zero + // first find the index of this bit + int idx = 0; + int m = n; + while (((m & 1) != 1) & idx < 32){ + m >>= 1; + idx++; + } + + while (((m & 1) != 0) & idx < 32){ + m >>= 1; + idx++; + } + + // if idx >= 31, then the number is now negative or no trailing zero was found, impossible (return -1) + if (idx > 30){ + return -1; + } + int mask = (1 << idx); + + // flip this bit + n |= mask; + + // Replace the bits to the right of the flipped 0 by + // the smallest number with the number of 1 bits there -1 + n = replaceOneBitsRight(n, idx); + + return n; + } + + /** + * Get largest positive number smaller than n with the same number of 1 bits (return -1 if no such number). + * @param n + * @return + */ + public int getPrevious(int n){ + // flip the smallest non trailing one + // first find the index of this bit + int idx = 0; + int m = n; + + if ((m & 1) == 1){ + return -1; // no smaller number with the same number of 1 bits + } + + while (((m & 1) != 0) & idx < 32){ + m >>= 1; + idx++; + } + + while (((m & 1) != 1) & idx < 32){ + m >>= 1; + idx++; + } + + if (idx > 30){ + // no positive number strictly smaller than n with the same number of bits + return -1; + } + + int mask = ~(1 << idx); + + // flip this bit + n &= mask; + + // Replace the bits to the right of the flipped 0 by + // the smallest number with the number of 1 bits there -1 + n = replaceZeroBitsRight(n, idx); + + return n; + } + + /** + * Count the number of 1 bits to the right (excluded) of idx bit, + * replace them by cnt-1 adjacent bits starting from zero index. + * @param n + * @param idx + * @return + */ + public int replaceOneBitsRight(int n, int idx){ + // count the number of 1 bits + int cnt = 0; + + for (int i=0; i>= 1; + } + + cnt--; // flip one 1 bit + for (int i=0; i>= 1; + } + + cnt--; // flip one 0 bit + for (int i=0; i>>= 1; + } + + return number; + + // NOTE: Alternatively, instead of shifting n repeatedly to count the number of 1 bits, repeatedly + // clear the least significant 1 bit : n & n-1 + } +} diff --git a/ch5/Solution07.java b/ch5/Solution07.java new file mode 100644 index 0000000..af92d27 --- /dev/null +++ b/ch5/Solution07.java @@ -0,0 +1,51 @@ +/** + * Created by Hakim on 10/3/15. + */ +public class Solution07 { + public static void main(String[] args){ + Solution07 solution07 = new Solution07(); + int n = 37; + System.out.println("Pairwise swap V1 of " + Integer.toBinaryString(n) + ": " + Integer.toBinaryString(solution07.swapBitsV1(n))); + System.out.println("Pairwise swap V2 of " + Integer.toBinaryString(n) + ": " + Integer.toBinaryString(solution07.swapBitsV2(n))); + } + + /** + * Swap odd and even bits of a number n. + * Solution 1: Right shift n by 1 | Left shift n by 1 | mask removing the extra one bit that could be created on the + * left + * @param n + * @return + */ + public int swapBitsV1(int n){ + int msk = maskMSOneBit(n); + return ((n<<1) | (n>>1)) & ~(msk << 1); + } + + /** + * Create a mask to set n's most significant 1 bit to 0. + * @param n + * @return + */ + public int maskMSOneBit(int n){ + int msk = 0; + while ((n & (n & (n-1))) != 0){ +// System.out.println("mask " + msk); + msk = n & (n-1); + n = n & msk; + } + return msk; + } + + /** + * Solution 2 using less operations. + * Extract even bits and odd bits using masks. Logical right shift the even bits, left shift the odd bits and 'or' + * the results + * This solution is implemented for 32-bit integers (change the masks if 64-bit integers) + * @param n + * @return + */ + public int swapBitsV2(int n){ + // logical shift for the even bits as don't want to add a 1 if msb is 1 + return ((n & 0xaaaaaaaa) >>> 1) | ((n & 0x55555555) << 1); + } +} diff --git a/ch5/Solution08.java b/ch5/Solution08.java new file mode 100644 index 0000000..fa8431b --- /dev/null +++ b/ch5/Solution08.java @@ -0,0 +1,118 @@ +/** + * Created by Hakim on 10/3/15. + */ + +/** + * 5.8. + */ +public class Solution08 { + public static void main(String[] args){ + Solution08 solution08 = new Solution08(); + System.out.println("Screen 1: "); + byte[] b = {58,58,58,58,58,58}; + solution08.printScreen(b, 16); + solution08.drawLine(b, 16, 0, 6, 2); + System.out.println(); + System.out.println(); + solution08.printScreen(b, 16); + + System.out.println("\n\nScreen 2: "); + byte[] c = {0,0,0,0,0,0}; + solution08.printScreen(c, 24); + solution08.drawLine(c, 24, 8, 9, 1); + System.out.println(); + System.out.println(); + solution08.printScreen(c, 24); + + + } + + /** + * Draw a horizontal line in screen between (x1,y) and (x2,y). + * @param screen + * @param width = 8*k; k > 0 + * @param x1 + * @param x2 + * @param y + */ + public void drawLine(byte[] screen, int width, int x1, int x2, int y){ + // compute index of the first and last bytes affected + int startByte = y*(width/8) + x1/8; + int endByte = y*(width/8) + x2/8; + + // compute offset inside byte + int startOffset = 7-x2%8; + int endOffset = 7-x1%8; + + // if startByte == endByte, set bits between startOffset and endOffset to 1 + if (startByte == endByte){ + setBitsToOne(screen, startByte, startOffset, endOffset); + } + // otherwise set first byte and last byte before setting the bytes in between to all 1s + else{ + setBitsToOne(screen, startByte, startOffset, 8); + setBitsToOne(screen, endByte, 0, endOffset); + } + + for (int i=startByte+1; i>= 1; + } + + System.out.print(sb.reverse().toString()); + } +} diff --git a/ch6/Solution01.java b/ch6/Solution01.java new file mode 100644 index 0000000..59a0bb8 --- /dev/null +++ b/ch6/Solution01.java @@ -0,0 +1,67 @@ +/** + * Created by Hakim on 10/4/15. + */ + +import java.util.ArrayList; +import java.util.List; + +/** + * 6.1. + */ +public class Solution01 { + public static void main(String[] args){ + Solution01 solution01 = new Solution01(); + + List> bottles = new ArrayList<>(); + List standard = new ArrayList<>(); + for (int i=0; i<123; i++){ + standard.add(1.0); + } + + List heavy = new ArrayList<>(); + for (int i=0; i<13; i++){ + heavy.add(1.1); + } + + for (int i=0; i<5; i++){ + bottles.add(new ArrayList(standard)); + } + + bottles.add(new ArrayList(heavy)); + + for (int i=6; i<20; i++){ + bottles.add(new ArrayList(standard)); + } + + System.out.println("Heavy bottle (expect 5): " + solution01.findHeavyPills(bottles)); + } + + /** + * Find the bottle that contains pills of 1.1 grams instead of 1 gram + * @param bottles: List of the list of pills weights in each bottle + * @return + */ + public int findHeavyPills(List> bottles){ + // Given that we are only allowed to use the scale once, we are going to take pills from + // all the bottles. + // We assume that at least one bottle has 1 pill, one has a minimum of 2 pills etc + // We take 1 pill from the first bottle + // 2 pills from the second bottle + // ... + // 20 pills from the last bottle + // If all the pills had the same weight, then the total weight would be + // 20 * 21/2 = 210 g + // If bottle n contains the pills that weight 1.1 gram, then the weight excess + // will be nE-1 grams. + // Therefore, the bottle that contains the heavy pills is bottle n such that + // weight = 210 + nE-1 => n = 10 * (weight - 210) + + double weight = 0; + int len = bottles.size(); + for (int i=0; i p^3 + 3*(1-p)*p^2 + * iff p > p^3 + 3*p^2 - 3*p^3 + * iff p > -2*p^3 + 3*p^2 + * iff 2*p^2 - 3*p + 1 > 0 or p=0 (otherwise, could not divide by p) + * iff p^2 - 3/2*p +1/2 > 0 + * iff (p-3/4)^2 - 1/16 > 0 + * iff (p-3/4-1/4)*(p-3/4+1/4) > 0 + * iff (p-1)*(p-1/2) > 0 + * iff p < 0.5 + * + * In conclusion, we should play game 1 iff p < 0.5, game 2 otherwise + * (with equal chances if winning either game if p=1, 0.5, or 0 (cf 3rd iff)) + */ + + String solution = "Please see comment"; + System.out.println(solution); + } + + +} diff --git a/ch6/Solution03.java b/ch6/Solution03.java new file mode 100644 index 0000000..bdfb869 --- /dev/null +++ b/ch6/Solution03.java @@ -0,0 +1,17 @@ +/** + * Created by Hakim on 10/4/15. + */ +public class Solution03 { + public static void main(String[] args){ + String solution = "There are originally 8x8 = 64 cases, 32 of them black and 32 white.\n" + + "Two diagonally opposed cases have the same color. Let's assume this color is black for the " + + "cases that were removed.\n" + + "There are now 30 black cases and 32 white. Each domino covers two cases: one black and one white.\n" + + "Therefore, the dominos cover as many white cases as they cover black ones.\n" + + "Since there are two more white cases than black ones, it is impossible to cover the board this way"; + + System.out.println(solution); + } + + +} diff --git a/ch6/Solution04.java b/ch6/Solution04.java new file mode 100644 index 0000000..933c9dc --- /dev/null +++ b/ch6/Solution04.java @@ -0,0 +1,29 @@ +/** + * Created by Hakim on 10/4/15. + */ + +/** + * 6.4. + */ +public class Solution04 { + public static void main(String[] args){ + String solution = "The probability that a collision occurs is 1 - Pr(all ants walk on the same direction).\n" + + "Let's consider Pr(all ants walk on the same direction):\n" + + "Pr(all ants walk on the same direction) = Pr(all ants walk in direction 1) + Pr(all ants walk in direction 2).\n" + + "Pr(all ants walk in direction 1) = Pr(ant1 walks in direction 1 and ant2 walks in direction 1) and ant3 walks in direction 1 \n" + + "By independence: Pr(all ants walk in direction 1) = Pr(ant1 walks in direction 1) * Pr(ant2 walks in direction 1) * Pr(ant3 walks in direction 1)\n" + + "Pr(all ants walk in direction 1) = (1/2)^3\n" + + "Likewise, Pr(all ants walk in direction 2) = (1/2)^3.\n" + + "Hence, Pr(all ants walk on the same direction) = (1/2)^3 * 2 = 1/4\n" + + "Finally, the probability that a collision occurs is 1 - Pr(all ants walk on the same direction) = 1 - 1/4" + + "The probability that a collision occurs is 3/4\n" + + "\n" + + "FOLLOW UP n ants on an n-vertex polygone:" + + "The probability that a collision occurs is 1 - Pr(all ants walk on the same direction).\n" + + "Pr(all ants walk on the same direction) = Pr(all ants walk in direction 1) + Pr(all ants walk in direction 2)\n" + + "Pr(all ants walk on the same direction) = 2 * (1/2)^n = (1/2)^(n-1)\n" + + "and The probability that a collision occurs is 1 - (1/2)^(n-1)"; + + System.out.println(solution); + } +} diff --git a/ch6/Solution05.java b/ch6/Solution05.java new file mode 100644 index 0000000..5205377 --- /dev/null +++ b/ch6/Solution05.java @@ -0,0 +1,27 @@ +/** + * Created by Hakim on 10/4/15. + */ + +/** + * 6.5. + */ +public class Solution05 { + public static void main(String[] args){ + String solution1 = "Solution1: If we have an extra recipient that can contain at least 9 quart:" + + "\n1- Fill this extra recipient with the 3-quart jug three times: It will contain 9-quart." + + "\n2- Empty the filled recipient in the 5-quart, so that 9-5 = 4-quart will remain.\n"; + + String solution2 = "If we only have the 5-quart and the 3-quart:\n" + + "1- Fill 5-quart\n" + + "2- Empty 5-quart in 3 quart => 2 remaining in 5-quart\n" + + "3- Empty 3-quart\n" + + "4- Empty 5-quart in 3-quart => 2 in 3-quart\n" + + "5- Fill 5-quart\n" + + "6- Empty 5-quart in 3-quart is full (1) => 4 remaining in 5-quart"; + + System.out.println(solution1); + System.out.println(solution2); + } + + +} diff --git a/ch6/Solution06.java b/ch6/Solution06.java new file mode 100644 index 0000000..819f479 --- /dev/null +++ b/ch6/Solution06.java @@ -0,0 +1,28 @@ +/** + * Created by Hakim on 10/4/15. + */ + +/** + * 6.6. + */ +public class Solution06 { + public static void main(String[] args){ + String solution = "Let's note p the number of blue eyed persons on the island.\n" + + "If p==1: The blue eyed person will see that no one else has blue eyes. In addition to that, " + + "he knows that at least one person is blue eyed. It must be him and he will leave on the first night.\n" + + "If p==2: Both blue eyed persons will see that at least one other person has blue eyes. Either that " + + "person is the only one, or they too are blue eyed. If the other person was the only one, then he " + + "would leave the first night. Both blue eyed persons will the wait for the first night. On the second " + + "day, when no one leaves, they will understand that the other person was expecting them to leave and " + + "so they are both blue eyed. Finally, they will both leave on the second night.\n" + + "Let's prove by induction that p blue eyed tourist will all leave on the pth day.\n" + + "We just proved p=1 and p=2 and let's assume this property is true for up to p-1 blue eyed tourist.\n" + + "When there are p blue eyed persons, each person will know that there are either " + + "p-1 blue eyed persons (the others he can see) or p persons (the others + himself). " + + "He will then wait at least p-1 nights, expecting all of them to leave that night. Since everyone " + + "is expecting the same thing, no one will leave. On the pth night, they will understand there are " + + "in fact p blue eyed persons and the p of them will leave.\n" + + "In conclusion, if the island contains p blue eyed persons, then it takes p nights for " + + "them to leave. (They will all leave on the pth night)"; + } +} diff --git a/ch6/Solution07.java b/ch6/Solution07.java new file mode 100644 index 0000000..289335d --- /dev/null +++ b/ch6/Solution07.java @@ -0,0 +1,62 @@ +import java.util.Random; + +/** + * Created by Hakim on 10/6/15. + */ +public class Solution07 { + public static void main(String[] args){ + Solution07 solution07 = new Solution07(); + String solution = "Each family has n boys and 1 girl.\n" + + "The probability of having 0 boys and 1 girl is 1/2\n" + + "More generally, the probability of having n boys and 1 girl is (1/2)^n (for having n boys first) * 1/2 = (1/2)^(n+1)\n" + + "Let's compute the expected gender ratio: The ratio of girls over boys is:" + + "Pr(having 1 girl given 0 boys) * (1/(0+1)) + ...+ Pr(having 1 girl given n boys) * (1/(n+1)) + ... \n" + + "This gives: sum_{n=0,n=inf}((1/n+1)*(0.5^(n+1)))\n" + + "We compute this probability for N=1000 families and find: " + solution07.prediction(1000) + "\n" + + "Why does this result make sense?\n" + + "Intuitively, the fact that each family has to have children until they have one girl " + + "will make some families have different ratios of girls and boys. At the population level, however, " + + "the probability of having a girl is still 0.5. Hence, at the populatino level, the gender ratio is " + + "still 0.5.\n" + + "We simulate this process with N=10, N=100, and N=1000 families:\n" + + "N=10: " + solution07.simulation(10) + "\n" + + "N=100: " + solution07.simulation(100) + "\n" + + "N=1000: " + solution07.simulation(1000) + "\n"; + System.out.println(solution); + } + + public double prediction(int n){ + double result = 0; + + for (int i=0; i= 100\n" + + "<=> M*(M+1)/2 >= 100\n" + + "Solving for this second order polynomial and choosing the root so that " + + "the values above are positive, \n" + + "<=> M>=13.6509...\n" + + "As M is an integer, we choose M=14.\n" + + "Hence, the solution optimizing the number of drops consists of \n" + + "1/ Drop egg1 at floor 14" + + "2/ While egg1 is not broken, drop it from a height increasing by interval - 1 at every iteration\n" + + "3/ When egg1 breaks, do a linear search with egg2.\n" + + "The worst case number of drops is then is then 14+1=15\n" + + "We can find this result using dp:"; + + System.out.println(solution); + System.out.println(solution08.maxNumberOfDrops(100,2)); + } + + /** + * Fin max number of drops needed to find 'breaking' floor in a building of numFloors using numEggs. + * @param numFloors + * @param numEggs + * @return + */ + public int maxNumberOfDrops(int numFloors, int numEggs){ + int[][] results = new int[numFloors+1][numEggs+1]; + + // if no floors, then 0 + for (int i=0; i>=1; + } + } + + /** + * Read the number that has binary representation given by the array strips. + * @param strips + * @return + */ + public int readStrips(int[] strips){ + int result = 0; + for (int i=0; i Date: Tue, 27 Oct 2015 11:23:24 -0400 Subject: [PATCH 6/6] chap 7 8 11 --- ch11/Solution01.java | 13 +++++ ch11/Solution02.java | 25 +++++++++ ch11/Solution03.java | 19 +++++++ ch11/Solution04.java | 22 ++++++++ ch11/Solution05.java | 25 +++++++++ ch11/Solution06.java | 21 ++++++++ ch7/Solution01.java | 53 +++++++++++++++++++ ch7/Solution02.java | 108 +++++++++++++++++++++++++++++++++++++++ ch7/Solution03.java | 71 ++++++++++++++++++++++++++ ch7/Solution04.java | 83 ++++++++++++++++++++++++++++++ ch7/Solution05.java | 63 +++++++++++++++++++++++ ch7/Solution06.java | 60 ++++++++++++++++++++++ ch7/Solution07.java | 77 ++++++++++++++++++++++++++++ ch7/Solution08.java | 45 ++++++++++++++++ ch7/Solution09.java | 78 ++++++++++++++++++++++++++++ ch7/Solution10.java | 69 +++++++++++++++++++++++++ ch7/Solution11.java | 91 +++++++++++++++++++++++++++++++++ ch7/Solution12.java | 119 +++++++++++++++++++++++++++++++++++++++++++ ch8/Solution01.java | 37 ++++++++++++++ ch8/Solution02.java | 108 +++++++++++++++++++++++++++++++++++++++ ch8/Solution03.java | 94 ++++++++++++++++++++++++++++++++++ ch8/Solution04.java | 55 ++++++++++++++++++++ ch8/Solution05.java | 42 +++++++++++++++ ch8/Solution06.java | 68 +++++++++++++++++++++++++ ch8/Solution07.java | 59 +++++++++++++++++++++ ch8/Solution08.java | 85 +++++++++++++++++++++++++++++++ ch8/Solution09.java | 70 +++++++++++++++++++++++++ ch8/Solution11.java | 57 +++++++++++++++++++++ ch8/Solution12.java | 112 ++++++++++++++++++++++++++++++++++++++++ ch8/Solution13.java | 98 +++++++++++++++++++++++++++++++++++ 30 files changed, 1927 insertions(+) create mode 100644 ch11/Solution01.java create mode 100644 ch11/Solution02.java create mode 100644 ch11/Solution03.java create mode 100644 ch11/Solution04.java create mode 100644 ch11/Solution05.java create mode 100644 ch11/Solution06.java create mode 100644 ch7/Solution01.java create mode 100644 ch7/Solution02.java create mode 100644 ch7/Solution03.java create mode 100644 ch7/Solution04.java create mode 100644 ch7/Solution05.java create mode 100644 ch7/Solution06.java create mode 100644 ch7/Solution07.java create mode 100644 ch7/Solution08.java create mode 100644 ch7/Solution09.java create mode 100644 ch7/Solution10.java create mode 100644 ch7/Solution11.java create mode 100644 ch7/Solution12.java create mode 100644 ch8/Solution01.java create mode 100644 ch8/Solution02.java create mode 100644 ch8/Solution03.java create mode 100644 ch8/Solution04.java create mode 100644 ch8/Solution05.java create mode 100644 ch8/Solution06.java create mode 100644 ch8/Solution07.java create mode 100644 ch8/Solution08.java create mode 100644 ch8/Solution09.java create mode 100644 ch8/Solution11.java create mode 100644 ch8/Solution12.java create mode 100644 ch8/Solution13.java diff --git a/ch11/Solution01.java b/ch11/Solution01.java new file mode 100644 index 0000000..65eaad1 --- /dev/null +++ b/ch11/Solution01.java @@ -0,0 +1,13 @@ +/** + * Created by Hakim on 10/19/15. + */ +public class Solution01 { + public static void main(String[] args){ + String solution = "i being unsigned, printf should use %u instead of %d\n" + + "The method will loop infinitely as i is unsigned and will always respect the" + + " condition i>=0.\n" + + "We can print all the numbers between 100 and 1 replacing it by for (i=100; i>0;--i)\n" + + "and can additionally print 0 if we want after the loop."; + System.out.println(solution); + } +} diff --git a/ch11/Solution02.java b/ch11/Solution02.java new file mode 100644 index 0000000..feb5d8f --- /dev/null +++ b/ch11/Solution02.java @@ -0,0 +1,25 @@ +/** + * Created by Hakim on 10/19/15. + */ +public class Solution02 { + public static void main(String[] args){ + String solution = "Programming errors that could be causing this crash:\n" + + "- Problems inside the program itself:\n" + + "\t* Random variables. Randomness can be introduced in the code using random number generators, " + + "user input, use of 'references' like current time.\n" + + "- Problems caused by the system:\n" + + "\t* Running out of resources, like memory, heap space\n" + + "- Problems caused by dependencies:\n" + + "\t* Buggy dependencies that return random false results\n" + + "\n" + + "How to test each possible source of the crash:\n" + + "- Problems inside the program itself: Look into the code and search for uninitialized variables, " + + "and sources of randomness\n" + + "- Problems caused by the system: Isolate the program by stopping any other program that " + + "is not necessary. Monitor the resources usage during the execution of the program\n" + + "- Problems caused by dependencies: Does the program have dependencies? If so, need to test the " + + "expected output of each of these dependencies"; + + System.out.println(solution); + } +} diff --git a/ch11/Solution03.java b/ch11/Solution03.java new file mode 100644 index 0000000..47c93b8 --- /dev/null +++ b/ch11/Solution03.java @@ -0,0 +1,19 @@ +/** + * Created by Hakim on 10/19/15. + */ +public class Solution03 { + public static void main(String[] args){ + String solution = "Testing the canMoveTo method:\n" + + "- For every kind of piece, test legal moves for that piece, where moving this piece " + + "would not create a check and not eat another piece; perform these tests under different " + + "conditions: unbalanced repartition of pieces, different types of pieces present\n" + + "- For every kind of piece, test legal moves for that piece, where moving this piece\n" + + " would not create a check and would eat another piece\n" + + "- Test illegal inputs: Trying to move a piece outside the board, trying to move a null piece\n" + + "- Test illegal moves: Generate situations where moving a piece would create a check situation for " + + "the person who moves that piece, " + + "try to move a piece in a way it is not allowed to\n"; + + System.out.println(solution); + } +} diff --git a/ch11/Solution04.java b/ch11/Solution04.java new file mode 100644 index 0000000..c41c679 --- /dev/null +++ b/ch11/Solution04.java @@ -0,0 +1,22 @@ +/** + * Created by Hakim on 10/19/15. + */ +public class Solution04 { + public static void main(String[] args) { + String solution = "We want to test the webpage under two circonstances:\n" + + "- High number of users trying to access it\n" + + "- Sharp changes in the number of users trying to access it\n" + + "For each of these scenarios, we might be interested in parameters like the response time " + + "or the throughput.\n" + + "We can load test the webpage by creating virtual users, each represented by " + + "a program thread. To simulate a high number of users trying to access the webpage, " + + "we can make a high number of threads try to access this webpage and measure, for " + + "each user, the scores we defined earlier.\n" + + "To test the reaction of the webpage under sharp changes in the number of users, we can" + + " increase/decrease the number of threads trying to access the webpage simultaneously and " + + "measure the same scores."; + + System.out.println(solution); + } + +} diff --git a/ch11/Solution05.java b/ch11/Solution05.java new file mode 100644 index 0000000..5da1df6 --- /dev/null +++ b/ch11/Solution05.java @@ -0,0 +1,25 @@ +/** + * Created by Hakim on 10/19/15. + */ +public class Solution05 { + public static void main(String[] args) { + String solution = "Assume the pen is intended to be used by college students, to write on paper " + + "in 'normal conditions' (no extreme temperature for instance). The writing doesn't need to be " + + "erasable and is offered in only one color and in a thin tip. The pen " + + "should not be toxic for the environment and not present any danger if it breaks.\n" + + "Let's perform the following tests:\n" + + "- Test the normal condition use cases: \n" + + "\t*Writing on paper" + + "- Test unintended use cases: \n" + + "\t* Drawing\n" + + "\t*Writing on other surfaces" + + "- Test stress conditions: \n" + + "\t* Exposure to extreme temperatures\n*" + + "\t* Exposure to high pressure, would the tip resist?" + + "- Failure conditions: \n" + + "\t* Is the ink toxic?" + + "\t* Would breaking the pen hurt the user or people around?"; + + System.out.println(solution); + } +} diff --git a/ch11/Solution06.java b/ch11/Solution06.java new file mode 100644 index 0000000..1c17bc2 --- /dev/null +++ b/ch11/Solution06.java @@ -0,0 +1,21 @@ +/** + * Created by Hakim on 10/19/15. + */ +public class Solution06 { + public static void main(String[] args) { + String solution = "Need to clarify the system under test:\n" + + "- Why? Withdraw cash, deposit cash, check balance\n" + + "- Where? In the street\n" + + "- How? Insert card, enter pin, proceed to operation\n" + + "- When? Anytime\n" + + "- Who? Customers with/without disabilities, businesses\n" + + "Define the priorities:\n" + + "- Security: Block if wrong pin entered multiple times or card reported stolen\n" + + "- Reliability: Do not give more money or less than asked for/ available in account\n" + + "- Accessibility for people with disabilities\n" + + "Failure handling: If not enough cash in the machine, signal the bank and the user\n" + + "For each of the use cases identified, create tests. Automatise when possible."; + + System.out.println(solution); + } +} diff --git a/ch7/Solution01.java b/ch7/Solution01.java new file mode 100644 index 0000000..fedf89c --- /dev/null +++ b/ch7/Solution01.java @@ -0,0 +1,53 @@ +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Hakim on 10/21/15. + */ +enum Suit{ + DIAMOND, HEART, CLUB, SPADE +} + +abstract class Card{ + int value; + Suit suit; + boolean isAvailable; + + public Card(int val, Suit st){ + value = val; + suit = st; + } + + public abstract int value(); +} + +class Hand { + List cards = new ArrayList<>(); + + public void addCard(){}; + public void removeCard(Card c){}; +} + +class Deck { + List cards = new ArrayList<>(); + public void shuffle(List cards){}; + public void distribute(List cards, List hands){}; +} + +class BlackJackCard extends Card { + public BlackJackCard(int v, Suit s){ + super(v,s); + } + public int value(){// multiple values possible for ace}; + +} + +class BlackJackHand extends Hand{ + public boolean isBlackJack(){}; + + +} + +public class Solution01 { + +} diff --git a/ch7/Solution02.java b/ch7/Solution02.java new file mode 100644 index 0000000..d61913a --- /dev/null +++ b/ch7/Solution02.java @@ -0,0 +1,108 @@ +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Queue; + +/** + * Created by Hakim on 10/21/15. + */ + +enum Rank{ + RESPONDENT, MANAGER, DIRECTOR +} +abstract class Employee{ + int id; + String name; + Rank rank; + Call currentCall; + + void processCall(Call call) { + // update isAvailable before and after + // update currentCall + } + + +} + +class Respondent extends Employee { + public Respondent() { + rank = Rank.RESPONDENT; + } +} + +class Manager extends Employee{ + public Manager() { + rank = Rank.MANAGER; + } +} + +class Director extends Employee{ + public Director() { + rank = Rank.DIRECTOR; + } +} + +class Call{ + int id; + Date received; + + public Call(int id){ + + } +} + +class CallCenter{ + Queue calls; + int numRespondents; + int numManagers; + int numDirectors; + + List respondents; + List managers; + List directors; + List> employees; + + public CallCenter(int numResp, int numMng, int numDirs) { + numRespondents = numResp; + numManagers = numMng; + numDirectors = numDirs; + + respondents = new ArrayList<>(); + managers = new ArrayList<>(); + directors = new ArrayList<>(); + + for (int r=0; r e : employees){ + for (Employee emp : e){ + if (emp.currentCall == null){ + emp.processCall(call); + } + } + } + } + } +} + + +public class Solution02 { + +} diff --git a/ch7/Solution03.java b/ch7/Solution03.java new file mode 100644 index 0000000..20e1db9 --- /dev/null +++ b/ch7/Solution03.java @@ -0,0 +1,71 @@ +import javax.print.DocFlavor; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Hakim on 10/21/15. + */ + +class JukeBox{ + private Screen screen; + private PlayList playList; + private Register register; + private Speaker speaker; + public JukeBox(){}; + +} + +class Screen{ + public Screen(){}; + public void displaySong(){}; + public void selectSong(){}; + +} + +class Coin{ + private int value; + public Coin(int v) { + value = v; + } +} + + class Speaker{ + public Speaker(){}; + } + +class Register{ + public Register(){}; + public boolean acceptCoin(){}; + public boolean returnChange(){}; +} + +class Song{ + private String title; + private String artist; + private int id; + + public Song(){}; + public void play(){}; +} + +class PlayList{ + private List songs; + private int currentSong; + + public PlayList(){}; + public void addSong(){}; + public void removeSong(){}; + public void shuffle(){}; +} + +class User{ + private String name; + private List money; + + public User(){}; + public void selectSong(){}; + +} + +public class Solution03 { +} diff --git a/ch7/Solution04.java b/ch7/Solution04.java new file mode 100644 index 0000000..85b85e9 --- /dev/null +++ b/ch7/Solution04.java @@ -0,0 +1,83 @@ +import java.util.Date; +import java.util.List; + +/** + * Created by Hakim on 10/23/15. + */ + +class ParkingLot{ + private int numberOfSpots; + private double maxVehicleLength; + private double maxVehicleWidth; + private double maxVehicleHeight; + List spots; + public ParkingLot(int nSpots, double lenLimit, double widthLimit, double heightLimit){} + public int getNumvAvailableSpots(){} + public boolean canFitCar(Car car){} +} + +class Car{ + private double length; + private double width; + private double height; + + public void park(ParkingSpot ps) {} +} + +class ParkingSpot{ + private double length; + private double width; + private boolean isAvailable; + private Car car; + public void parkCar(){} + public void removeCar(){} +} + +class Ticket{ + private Date issueDate; + private double duration; + + public Ticket(){} + +} + +class AutomaticRegister{ + + void returnChange(){} + void acceptCoins(){} + Ticket printTicket(){return new Ticket();} +} + +class TicketReader{ + private static TicketReader _instance = null; + protected TicketReader(){} + + public static TicketReader getInstance(){ + if (_instance == null){ + _instance = new TicketReader(); + } + return _instance; + } + + public boolean isValid(){} + public boolean openBarrier(){} + public void callOperator(){} +} + +class Barrier{ + private static Barrier _instance = null; + protected Barrier(){} + public static Barrier getInstance(){ + if (_instance == null){ + _instance = new Barrier(); + } + return _instance; + } + + public void lift(){} + public void putDown(){} +} + + +public class Solution04 { +} diff --git a/ch7/Solution05.java b/ch7/Solution05.java new file mode 100644 index 0000000..c5c761c --- /dev/null +++ b/ch7/Solution05.java @@ -0,0 +1,63 @@ +import java.util.List; +import java.util.Map; + +/** + * Created by Hakim on 10/23/15. + */ +class User{ + String name; + int id; + SubscriptionType subscriptionType; + Book activeBook; + +} + +enum SubscriptionType{ + BASIC, PREMIUM +} + +class Book{ + private String title; + private int id; + private LicenseType licenseType; + + public void updateLicenseType(){}; + +} + +class Library{ + private List books; + + public void addBook(){}; + public void removeBook(){}; + public boolean searchBookByTitle(String title){}; + +} + +enum LicenseType{ + // class type and maximum number of users who can access + // a book that has this license at a time + +} + +class OnlineBookReader{ + private Map> activeUsers; + private Library bookStore; + private List users; + + // manage users + public void addUser(){}; + public void removeUser(){}; + + // manage display + public void displayBook(User user, Book book){}; + public void displayPage(User user, int pageNum){}; + public void turnPageUp(User user){}; + public void turnPageDown(User user){}; + +} + + + +public class Solution05 { +} diff --git a/ch7/Solution06.java b/ch7/Solution06.java new file mode 100644 index 0000000..9982245 --- /dev/null +++ b/ch7/Solution06.java @@ -0,0 +1,60 @@ +import java.util.List; + +/** + * Created by Hakim on 10/23/15. + */ + +class Piece{ + List edges; // can be reordered so as to change the orientation + + public void reorderEdges(){}; // reoriente the edges (ie rotate the piece) + public boolean isCorner(){}; + public void makePiecesMatchAccordingToEdge(Piece other, Edge edgeToMatch){}; +} + +class Edge{ + int shape; // 0: flat + // 1: inner + // 2: outer + Piece belongsTo; + + public boolean fitsWith(Edge other){}; +} + +class Puzzle{ + List piecesToPlace; // initially all of them + Piece[][] solution; // placed pieces + int N; + int numRemainingCorners; + int numRemainingEdgePieces; // has 1 flat edge + + public void removePieceFromPiecesToPlace(Piece piece){}; + public void solve(){ + // place the next piece that can be placed in the row, or the first piece in the row below + for (int row=0; row userByName; + private Map userById; + protected UserManager(){}; + public static UserManager getInstance(){ + if (_instance == null){ + _instance = new UserManager(); + } + return _instance; + } +} + +class User{ + private int id; + private String name; + private Status status; + private Set friends; + + public void sendFriendshipRequest(User receiver){}; + public void acceptFriendshipRequest(int requestId){}; + public void rejectFriendShipRequest(int requestId){}; + public void createConversation(User other){}; + public void createConversation(Group group){}; + public void addToConversation(Conversation conversationId, User user){}; + public void signin(){}; + public void signOff(){}; + public void setStatus(){}; + public void updateFriendsList(){}; + + public User(String name){}; +} + +class FriendshipRequest{ + private int senderId; + private int receiverId; + private int requestId; + + public FriendshipRequest(User sender, User receiver){}; +} + +class Conversation{ + private List members; + private List messages; + + public Conversation(User initiator, User other){}; + public Conversation(User initiator, Group group){}; +} + +class Message{ + private String content; + private int senderId; + private int receiverId; + public Message(User sender, Conversation conversation, String content){}; +} + +class Group{ + private List members; + public Group(User admin, List users){}; +} + +public class Solution07 { +} diff --git a/ch7/Solution08.java b/ch7/Solution08.java new file mode 100644 index 0000000..4b49518 --- /dev/null +++ b/ch7/Solution08.java @@ -0,0 +1,45 @@ +import java.util.Date; +import java.util.List; + +/** + * Created by Hakim on 10/26/15. + */ + +class Player{ + private String name; + private int id; + private boolean color; // black/white false/true +} + +class GameController{ + private int numRows; + private int numCols; + private Date begin; + private Date end; + private Board board; + private List players; +} + +class Board{ + private int numRows; + private int numCols; + private boolean[][] board; // true/false white/black + private int totalWhite; + private int totalBlack; + public Board(int numRows, int numCols){} + public boolean canStillPlay(){}; + public boolean isLegalPlacement(){}; + public void updateCounts(){}; + public void placePiece(int row, int col, boolean color){}; +} + +class Piece{ + private boolean currentColor; + public void flipPiece(){}; + public void playPiece(int row, int col){} +} + + + +public class Solution08 { +} diff --git a/ch7/Solution09.java b/ch7/Solution09.java new file mode 100644 index 0000000..0b2ac29 --- /dev/null +++ b/ch7/Solution09.java @@ -0,0 +1,78 @@ +import java.util.Iterator; +import java.util.List; + +/** + * Created by Hakim on 10/26/15. + */ + +class CircularArray implements Iterable{ + private int start; + private int size; + private List arr; + + public CircularArray(int l){ + size = l; + for (int i=0; i getArr(){ + return arr; + } + public Iterator iterator(){ + return new CAIterator(this); + } +} + +class CAIterator implements Iterator{ + private List cpArray; + private int offset; + private int size; + + public CAIterator(CircularArray cArr){ + cpArray = cArr.getArr(); + size = cArr.getSize(); + } + + @Override + public boolean hasNext(){ + if (offset < size){ + return true; + } + else{ + return false; + } + } + + @Override + public T next(){ + offset++; + return cpArray.get((offset+size) % size); + } + + @Override + public void remove(){ + cpArray.remove(offset); + } +} + + +public class Solution09 { +} diff --git a/ch7/Solution10.java b/ch7/Solution10.java new file mode 100644 index 0000000..249cc81 --- /dev/null +++ b/ch7/Solution10.java @@ -0,0 +1,69 @@ +/** + * Created by Hakim on 10/27/15. + */ + +class Board{ + private int numRows; + private int numCols; + private int originalNumBombs; + private int remainingNumBombs; + private Cell[][] cells; + + public void initialize(){ + + } + + public void uncoverAll(){ + + } +} + +class Cell{ + private int row; + private int column; + private boolean isBomb; + private boolean isBlank; + private boolean isGuess; + private int num; + + public Cell(int r, int c, boolean isB, boolean isG, int num){ + + } + + public void click(){ + + } + + public void markAsGuess(int number){ + + } +} + +class Player{ + private int id; + private String name; + private Boolean hasWon; + + public Player(){ + + } + + public void playOneMove(int r, int c, boolean guess){ + + } + + public void play(){ + // while + } + + + +} + +class Result{ + private boolean hitBomb; + +} + +public class Solution10 { +} diff --git a/ch7/Solution11.java b/ch7/Solution11.java new file mode 100644 index 0000000..22a9004 --- /dev/null +++ b/ch7/Solution11.java @@ -0,0 +1,91 @@ +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Created by Hakim on 10/26/15. + */ + +class File { + private boolean isDirectory; + private int size; + private String name; + private String accessRights; + private Set fileNames; + private Set files; + private Map nameFile; + private String content; + + public File(String name, boolean isDirectory, String content){ + + } + + public void updateContent(){ + + } + + public void updateSize(){ + + } + + public void rename(String newName){ + + } + + public String pwd(){ + + } + + public String getAccessRights(){}; + public void updateAccessStrings(){}; + + public void writeContent(String con){ + content = con; + } + + public boolean mkdir(String directoryName){ + if (fileNames.contains(directoryName)){ + return false; + } + File dir = new File(directoryName,true); + fileNames.add(directoryName); + files.add(dir); + return true; + } + + public boolean touch(String fileName){ + if (fileNames.contains(fileName)){ + return false; + } + else{ + files.add(new File(fileName,false)); + fileNames.add(fileName); + return true; + } + } + + public void ls(){ + for (String fileName : fileNames){ + System.out.println(fileName); + } + } + + public boolean rm(String fileName){ + if (!fileNames.contains(fileName)){ + return false; + } + fileNames.remove(fileName); + files.remove(nameFile.get(fileName)); + return true; + } + + public int computeSize(String con){ + + } +} + + + + +public class Solution11 { +} diff --git a/ch7/Solution12.java b/ch7/Solution12.java new file mode 100644 index 0000000..a1b9ae0 --- /dev/null +++ b/ch7/Solution12.java @@ -0,0 +1,119 @@ +import java.util.LinkedList; +import java.util.List; + +/** + * Created by Hakim on 10/26/15. + */ + +class HashTable{ + private int capacity; + private List> list; + + public HashTable(int cap){ + capacity = cap; + // initialize + for (int i=0; i()); + list.get(code).add(new ESet(e)); + } + else{ + list.get(code).addFirst(new ESet(e)); + } + } + + public boolean remove(T t){ + int code = Utils.hashFunction(t.toString(), capacity); + if (list.get(code) == null){ + return false; + } + + LinkedList lst = list.get(code); + for (int i=0; i lst = list.get(code); + if (lst == null){ + return false; + } + for (int j=0; j lst = list.get(i); + if (lst == null){ + continue; + } + for (int j=0; j lst = list.get(code); + + if (lst == null){ + return null; + } + for (int j=0; j{ + T key; + V value; + public ESet(T t, V v){ + key = t; + value = v; + } + + public ESet(ESet e){ + key = (T) e.key; + value = (V) e.value; + } +} + +class Utils{ + public static int hashFunction(String s, int max){ + int result = 0; + for (int i=0; i forbidden = new ArrayList<>(); + forbidden.add(upperRight); + forbidden.add(lowerLeft); + + List path = solution02.findPath(numRows, numCols, forbidden); + for (int i=0; i findPath(int numRows, int numCols, List forbidden) { + // Create the grid + boolean[][] grid = new boolean[numRows][numCols]; + for (int i=0; i path = new ArrayList<>(); + Coordinate destination = new Coordinate(numRows-1, numCols-1); + findPath(grid, memo, destination, path); + + return path; + } + + /** + * Helper function to find a path from upper left corner to lower right one, avoiding forbidden cases. + * @param grid + * @param memo + * @param destination + * @param path + * @return + */ + public boolean findPath(boolean[][] grid, boolean[][] memo, Coordinate destination, List path) { + if (destination.row < 0 || destination.row >= grid.length || + destination.col < 0 || destination.col >= grid[0].length || + !grid[destination.row][destination.col]){ + // out of bounds or forbidden + return false; + } + if (memo[destination.row][destination.col]){ // already computed + path.add(destination); + return true; + } + + Coordinate up = new Coordinate(destination.row-1, destination.col); + Coordinate left = new Coordinate(destination.row, destination.col-1); + if (findPath(grid, memo, up, path) || findPath(grid, memo, left, path)){ + path.add(destination); + memo[destination.row][destination.col] = true; + } + + return memo[destination.row][destination.col]; + } +} diff --git a/ch8/Solution03.java b/ch8/Solution03.java new file mode 100644 index 0000000..04d8476 --- /dev/null +++ b/ch8/Solution03.java @@ -0,0 +1,94 @@ +/** + * Created by Hakim on 10/10/15. + */ +public class Solution03 { + public static void main(String[] args){ + Solution03 solution03 = new Solution03(); + int[] A1 = {1,2,3,4,5}; + int[] A2 = {-1,0,1,3,4,7,8,9}; + System.out.println("A magic index in A1: (expect -1) " + solution03.magicIndex(A1)); + System.out.println("A magic index in A2: (expect 3) " + solution03.magicIndex(A2)); + + int[] A3 = {1,3,4,5,5,6,6}; + int[] A4 = {-1,-1,0,1,2}; + System.out.println("A magic index in A3: (expect 6) " + solution03.magicIndexWithDups(A3)); + System.out.println("A magic index in A4: (expect -1) " + solution03.magicIndexWithDups(A4)); + } + + /** + * Given a sorted array of distinct integers, find a magic index, if one exists. + * @param A + * @return + */ + public int magicIndex(int[] A){ + return magicIndex(A, 0, A.length-1); + } + + /** + * Find a magic index in A between low and high. + * @param A + * @param low + * @param high + * @return + */ + public int magicIndex(int[] A, int low, int high){ + if (low > high){ + return -1; // error value + } + + int mid = (low + high)/2; + + if (A[mid] == mid){ + return mid; + } + else if (A[mid] > mid){ + // there can't be a magic index on the right side + return magicIndex(A, low, mid-1); + } + else{ + // can't be a magic index on the left side + return magicIndex(A, mid+1, high); + } + } + + + /** + * Follow up: If the values in A are not distinct. + * @param A + * @return + */ + public int magicIndexWithDups(int[] A){ + return magicIndexWithDups(A, 0, A.length-1); + } + + /** + * Find a magic index in A between low and high. + * @param A + * @param low + * @param high + * @return + */ + public int magicIndexWithDups(int[] A, int low, int high){ + if (low > high || low < 0 || high > A.length-1){ + return -1; + } + + int mid = (low + high)/2; + + if (A[mid] == mid){ + return mid; + } + else if (A[mid] < mid){ + int right = magicIndexWithDups(A, mid+1, high); + int left = magicIndexWithDups(A, low, A[mid]); + int magic = (right > -1) ? right:left; + return magic; + } + else{ + int right = magicIndexWithDups(A, A[mid], high); + int left = magicIndexWithDups(A, low, mid-1); + int magic = (right > -1) ? right:left; + return magic; + } + } +} diff --git a/ch8/Solution04.java b/ch8/Solution04.java new file mode 100644 index 0000000..72ee6ba --- /dev/null +++ b/ch8/Solution04.java @@ -0,0 +1,55 @@ +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Created by Hakim on 10/11/15. + */ + +/** + * 8.4. + */ +public class Solution04 { + public static void main(String[] args){ + Solution04 solution04 = new Solution04(); + Set set = new HashSet<>(); + set.add(1); + set.add(2); + set.add(3); + + Set> subsets = solution04.findAllSubsets(set); + for (Set s : subsets){ + System.out.println(s); + } + } + + /** + * Return all the subsets of set. + * @param set + * @return + */ + public Set> findAllSubsets(Set set){ + if (set.isEmpty()){ + return new HashSet<>(); + } + + Set> result = new HashSet<>(); + + result.add(new HashSet()); // add the empty set + + // For every element, add the sets of size at most maxSizePreviousSets+1 that + // contain this element + for (Integer i : set){ + List> tmp = new ArrayList<>(); + for (HashSet s : result){ + tmp.add((HashSet)s.clone()); + } + for (HashSet s : tmp){ + s.add(i); + result.add(s); + } + } + return result; + } +} diff --git a/ch8/Solution05.java b/ch8/Solution05.java new file mode 100644 index 0000000..c577434 --- /dev/null +++ b/ch8/Solution05.java @@ -0,0 +1,42 @@ +/** + * Created by Hakim on 10/11/15. + */ + +/** + * 8.5. + */ +public class Solution05 { + public static void main(String[] args){ + Solution05 solution05 = new Solution05(); + System.out.println("65 * 3 = " + solution05.recursiveMultiply(65, 3)); + } + + + /** + * Recursive multiply. + * Multiply m by n without using '*' + * recursively multiply min(m,n)/2 by max(m,n) + * if min == 1, return max + * if min is odd, add max to the result + * @param m + * @param n + * @return + */ + public int recursiveMultiply(int m, int n){ + int maxi = Math.max(m, n); + int mini = Math.min(m, n); + + if (m != mini){ + return recursiveMultiply(mini, maxi); + } + + if (m == 1){ + return maxi; + } + + int div = recursiveMultiply(mini/2, maxi); + int rest = (mini % 2 == 0) ? 0 : maxi; + + return div + div + rest; + } +} diff --git a/ch8/Solution06.java b/ch8/Solution06.java new file mode 100644 index 0000000..373efb1 --- /dev/null +++ b/ch8/Solution06.java @@ -0,0 +1,68 @@ +import java.util.Stack; + +/** + * Created by Hakim on 10/11/15. + */ + +/** + * 8.6. + */ +public class Solution06 { + public static void main(String[] args){ + Solution06 solution06 = new Solution06(); + Stack tower1 = new Stack<>(); + Stack tower2 = new Stack<>(); + Stack tower3 = new Stack<>(); + + for (int i=9; i>=0; i--){ + tower1.push(i); + } + + System.out.println("Tower 1 before: " + tower1); + System.out.println("Tower 2 before: " + tower2); + System.out.println("Tower 3 before: " + tower3); + + solution06.moveDisks(tower1.size(), tower1, tower2, tower3); + + System.out.println("Tower 1 after: " + tower1); + System.out.println("Tower 2 after: " + tower2); + System.out.println("Tower 3 after: " + tower3); + } + + /** + * move the disks from tower1 to tower3, using tower2 as a buffer and respecting the + * constraints defined in the Towers of Hanoi problem: + * - Only one disk can be moved at a time + * - A disk is slid off the top of one tower onto the next tower + * - A disk can only be placed on top of a larger disk. + * @param n - Number of disks to move from tower1 to tower3 + * @param tower1 + * @param tower2 + * @param tower3 + */ + public void moveDisks(int n, Stack tower1, Stack tower2, Stack tower3){ + if (tower1.size() == 0){ + return; + } + + if (n == 1){ + moveOneDisk(tower1, tower3); + return; + } + + moveDisks(n-1, tower1, tower3, tower2); + moveOneDisk(tower1, tower3); + moveDisks(n-1, tower2, tower1, tower3); + } + + /** + * Move the top disk from origin to destination. + * @param origin + * @param destination + */ + public void moveOneDisk(Stack origin, Stack destination){ + int top = origin.pop(); + destination.push(top); + return; + } +} diff --git a/ch8/Solution07.java b/ch8/Solution07.java new file mode 100644 index 0000000..11a162b --- /dev/null +++ b/ch8/Solution07.java @@ -0,0 +1,59 @@ +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Hakim on 10/12/15. + */ + +/** + * 8.7. + */ +public class Solution07 { + public static void main(String[] args){ + Solution07 solution07 = new Solution07(); + System.out.println(solution07.permutations("abc")); + } + + /** + * Return the list of all the permutations of String s which doesn't contain duplicates. + * @param s + * @return + */ + public List permutations(String s) { + if (s == null) { + return null; + } + if (s.length() <= 1) { + List result = new ArrayList<>(); + result.add(s); + return result; + } + + List result = new ArrayList<>(); + char c = s.charAt(0); + List perms = permutations(s.substring(1)); + + for (int index = 0; index <= perms.get(0).length(); index++) { + for (String st : perms) { + String t = insert(c, st, index); + result.add(t); + } + } + + return result; + } + + /** + * Insert character c into String st in position index. + * @param c + * @param st + * @param index + * @return + */ + public String insert(char c, String st, int index){ + String prefix = st.substring(0,index); + String suffix = st.substring(index,st.length()); + return prefix + c + suffix; + } + +} diff --git a/ch8/Solution08.java b/ch8/Solution08.java new file mode 100644 index 0000000..649bd3b --- /dev/null +++ b/ch8/Solution08.java @@ -0,0 +1,85 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by Hakim on 10/13/15. + */ + +/** + * 8.8. + */ +public class Solution08 { + public static void main(String[] args){ + Solution08 solution08 = new Solution08(); + System.out.println(solution08.permutations("aab")); + } + + /** + * Compute all the permutations of a string whose characters are not necessarily unique. + * The list of permutations should not have duplicates + * The previous method (8.7) combined with a set to keep + * unique elements only would work here, but would not be efficient if + * there are many duplicate characters as we would recompute the same permutations + * many times to discard them. + * The permutations can be computed by choosing the first character once for + * each unique character and then recursively computing the sub permutations + * We keep track of the counts for each character + * @param s + * @return + */ + public List permutations(String s){ + if (s == null){ + return null; + } + Map counts = new HashMap<>(); + int remainder = s.length(); // sum of the counts + for (char c : s.toCharArray()) { + if (!counts.containsKey(c)) { + counts.put(c, 1); + } + else { + counts.put(c, counts.get(c)+1); + } + } + + return permutations(counts, remainder); + } + + /** + * Helper function to permute a string of size remainder + * containing counts elements of each character. + * @param counts + * @param remainder + * @return + */ + public List permutations(Map counts, int remainder){ + if (remainder == 0){ + List result = new ArrayList<>(); + result.add(""); + return result; + } + if (remainder == 1){ + List result = new ArrayList<>(); + for (Map.Entry entry : counts.entrySet()){ + if (entry.getValue() == 1){ + result.add(entry.getKey().toString()); + } + } + return result; + } + + List result = new ArrayList<>(); + for (Character c : counts.keySet()){ + if (counts.get(c) > 0){ + counts.put(c, counts.get(c)-1); + for (String st : permutations(counts, remainder-1)){ + result.add(c.toString() + st); + } + counts.put(c, counts.get(c)+1); + } + } + return result; + } +} diff --git a/ch8/Solution09.java b/ch8/Solution09.java new file mode 100644 index 0000000..7388f9b --- /dev/null +++ b/ch8/Solution09.java @@ -0,0 +1,70 @@ +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Hakim on 10/14/15. + */ + +/** + * 8.9. + */ +public class Solution09 { + public static void main(String[] args) { + Solution09 solution09 = new Solution09(); + int numPairs = 3; + System.out.println(solution09.generateValidParens(numPairs)); + } + + /** + * Generate all valid string containing numPairs of parentheses. + * @param numPairs + * @return + */ + public List generateValidParens(int numPairs) { + List combinations = new ArrayList<>(); + generateValidParens(numPairs, numPairs, "", combinations); + return combinations; + } + + /** + * Helper function to generate all valid pairs of parenthesis. + * @param countOpenRemaining + * @param countCloseRemaining + * @param current + * @param combinations + */ + public void generateValidParens(int countOpenRemaining, + int countCloseRemaining, + String current, // would be more efficient using char array cause would + // avoid copying string over when adding one character + List combinations) { + if (countCloseRemaining < countOpenRemaining){ + return; // wrote more closed parentheses than open ones. Invalid + } + + if (countOpenRemaining == 0){ + // complete with all the closed parentheses + String end = current; + for (int i=0; i=0 && col-i>=0){ + if (columns[col-i] == row-i){ + return false; + } + i++; + } + + // Check the lower left diagonal + int j=1; + while (row+j=0){ + if (columns[col-j] == row+j){ + return false; + } + j++; + } + + return true; // all good + } + + /** + * Print the arrangement of the board defined by columns. + * @param columns + * @param N + */ + public void printBoardTranspose(Integer[] columns, int N) { + // print the transpose of the board. Fine since all combinations will be printed + // => all transposes = all originals + for (int c : columns){ + printColumnTranspose(c, N); + System.out.println(); + } + } + + /** + * Print the transpose of the column that contains a queen on row c. + * @param c + * @param N + */ + public void printColumnTranspose(int c, int N) { + for (int i=0; i(){ + @Override + public int compare(int[] box1, int[] box2){ + int width1 = box1[0]; + int width2 = box2[0]; + if (width1 == width2){ + return 0; + } + if (width1 > width2){ + return -1; + } + else{ + return +1; + } + } + }); + + // save results to avoid duplicate computations + long[] memo = new long[boxes.length]; + + long max = 0; + for (int base=0; base boxes.length-1){ + return 0; + } + + if (memo[begin] > 0){ + return memo[begin]; + } + + // Try all the boxes after begin (including begin) as bottom + // and, recursively, all the stacks that can be formed after bottom + long mx = 0; + int[] bottom = boxes[begin]; + long highest = 0; + + // find the tallest stack that can be formed on top of bottom + for (int j=begin+1; j h) ? highest : h; + } + } + highest += bottom[2]; + + mx = (highest > mx) ? highest : mx; + + if (mx > memo[begin]){ + memo[begin] = mx; + } + return mx; + } + + public static void main(String[] args) throws IOException{ + Scanner in = new Scanner(System.in); + int N = Integer.parseInt(in.nextLine().trim()); + int[][] boxes = new int[N][3]; + for (int i = 0; i < N; i++) { + String[] split = in.nextLine().split(" "); + for (int j = 0; j < split.length; j++) { + boxes[i][j] = Integer.parseInt(split[j]); + } + } + System.out.println(highestStack(boxes)); + in.close(); + } +}