From bd11ddfa054f5a2468b487d7c03437e152c4d14c Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 23 Sep 2014 16:14:26 -0700 Subject: [PATCH 001/319] KthSort --- KthSort.java | 43 +++ ListNodeDemo.java | 676 ---------------------------------------------- PostOrder.java | 3 - 3 files changed, 43 insertions(+), 679 deletions(-) create mode 100644 KthSort.java delete mode 100644 ListNodeDemo.java diff --git a/KthSort.java b/KthSort.java new file mode 100644 index 0000000..bb97cf1 --- /dev/null +++ b/KthSort.java @@ -0,0 +1,43 @@ +package Algorithms; + +import java.util.HashMap; + +public class KthSort { + public static class Graph { + String name; + HashMap subs; + public Graph(String name) { + this.name = name; + } + } + + public static void main(String[] strs) { +// int[] input = new int[]{1,2,4,3,9,11,0}; +// sort(input); +// for(int n: input) { +// System.out.print(n + " "); +// } + Graph c1 = new Graph("c1"); + + //for() + } + + public static void sort(int[] input) { + if (input == null) { + return; + } + + int len = input.length; + for (int i = 1; i < len; i++) { + int cur = input[i]; + int j = i - 1; + while (j >= 0 && input[j] > cur) { + input[j + 1] = input[j]; + j--; + } + + input[j + 1] = cur; + } + } + +} diff --git a/ListNodeDemo.java b/ListNodeDemo.java deleted file mode 100644 index 48bdae6..0000000 --- a/ListNodeDemo.java +++ /dev/null @@ -1,676 +0,0 @@ -package Algorithms; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Stack; - -/** - * REFS: - * http://blog.csdn.net/fightforyourdream/article/details/16353519 - * http://blog.csdn.net/luckyxiaoqiang/article/details/7393134 轻松搞定面试中的链表题目 - * http://www.cnblogs.com/jax/archive/2009/12/11/1621504.html 算法大全(1)单链表 - * - * 目录: - * 1. 求单链表中结点的个数: getListLength - * 2. 将单链表反转: reverseList(遍历),reverseListRec(递归) - * 3. 查找单链表中的倒数第K个节点(k > 0): reGetKthNode - * 4. 查找单链表的中间结点: getMiddleNode - * 5. 从尾到头打印单链表: reversePrintListStack,reversePrintListRec(递归) - * 6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList, mergeSortedListRec - * 7. 判断一个单链表中是否有环: hasCycle - * 8. 判断两个单链表是否相交: isIntersect - * 9. 求两个单链表相交的第一个节点: getFirstCommonNode - * 10. 已知一个单链表中存在环,求进入环中的第一个节点: detectCycle, getFirstNodeInCycleHashMap - * 11. 给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted: delete - * - */ - -public class ListNodeDemo { - - // create the link Node class. - // why use static: - // http://duqiangcise.iteye.com/blog/697476 - private static class ListNode { - int val; - ListNode next; - public ListNode(int val) { - this.val = val; - this.next = null; - } - - } - - public static void main(String[] args) { - ListNode n1 = new ListNode(1); - ListNode n2 = new ListNode(2); - ListNode n3 = new ListNode(3); - ListNode n4 = new ListNode(4); - ListNode n5 = new ListNode(5); - ListNode n6 = new ListNode(6); - - ListNode m1 = new ListNode(5); - ListNode m2 = new ListNode(8); - ListNode m3 = new ListNode(9); - m1.next = m2; - m2.next = m3; - - ListNode c1 = new ListNode(1); - ListNode c2 = new ListNode(12); - c1.next = c2; - c2.next = n1; - - //ListNode mergeNode = mergeSortedListRec(m1, c1); - //ListNode mergeNode = mergeSortedList(m1, c1); - //printList(mergeNode); - - n1.next = n2; - n2.next = n3; - n3.next = n4; - n4.next = n5; - - printList(n1); - - Delete(n1, n5); - - printList(n1); - - // create a cycle - //n5.next = n3; - //n5.next = n6; - //n6.next = n4; - -// System.out.println(hasCycle(n1)); -// System.out.println(getListLength(n1)); -// printList(n1); -// -// //n1 = reverseList(n1); -// n1 = reverseListRec(n1); -// printList(n1); - -// ListNode ret = reGetKthNode(n1, 7); -// if (ret != null) { -// System.out.println(ret.val); -// } else { -// System.out.println("null"); -// } - - //reGetKthNodeRec(n1, 1); -// reGetKthNodeRec2(n1, 3); -// ListNode ret = getMiddleNode(n1); -// -// if (ret != null) { -// System.out.println(ret.val); -// } -// -// reversePrintListStackRec(n1); -// reversePrintListStack(n1); -// reversePrintListRev(n1); - - //printList(n1); - - System.out.println(isIntersect(n1, c1)); - - ListNode cross = getFirstCommonNode(n1, c1); - if (cross == null) { - System.out.println("null"); - } else { - System.out.println(cross.val); - } - - ListNode cross2 = getFirstNodeInCycleHashMap(c1); - if (cross2 == null) { - System.out.println("null"); - } else { - System.out.println(cross2.val); - } - } - - public static void printList(ListNode head) { - while (head != null) { - System.out.print(head.val + " "); - head = head.next; - } - - System.out.println(); - } - - // 获得ListNode 的长度 - public static int getListLength(ListNode head) { - if (head == null) { - return 0; - } - - int len = 0; - while (head != null) { - len++; - head = head.next; - } - - return len; - } - - /* - * 反转链表 - * 此算法亮点是:一次只需要处理把下一个节点指向curr, - * 不断循环,即可完成任务 - * */ - public static ListNode reverseList(ListNode head) { - if (head == null) { - return null; - } - - ListNode next = head.next; - ListNode curr = head; - - // 先把头节点的下一个指定. - curr.next = null; - - // 每次只需要将curr的next指向curr即可, - // 终止条件是:next是null 表示我们将所有的节点进行了翻转 - while (next != null) { - ListNode tmp = next.next; - next.next = curr; - curr = next; - next = tmp; - } - - return curr; - } - - // 翻转递归(递归) - // 递归的精髓在于你就默认reverseListRec已经成功帮你解决了子问题了!但别去想如何解决的 - // 现在只要处理当前node和子问题之间的关系。最后就能圆满解决整个问题。 - /* - head - 1 -> 2 -> 3 -> 4 - - head - 1-------------- - | - 4 -> 3 -> 2 // Node reHead = reverseListRec(head.next); - reHead head.next - - 4 -> 3 -> 2 -> 1 // head.next.next = head; - reHead - - 4 -> 3 -> 2 -> 1 -> null // head.next = null; - reHead - */ - public static ListNode reverseListRec(ListNode head) { - // if there is no node, or only one node, just return; - if (head == null || head.next == null) { - return head; - } - - ListNode reHead = reverseListRec(head.next); // 先求解子问题。 - head.next.next = head; // 将head 与被解决的子串的尾部相连。 - head.next = null; // head的下一个必须指向 null,因为head 是新的尾部. - - return reHead; - } - - /** - * 查找单链表中的倒数第K个结点(k > 0) - * 最普遍的方法是,先统计单链表中结点的个数,然后再找到第(n-k)个结点。注意链表为空,k为0,k为1,k大于链表中节点个数时的情况 - * 。时间复杂度为O(n)。代码略。 这里主要讲一下另一个思路,这种思路在其他题目中也会有应用。 - * 主要思路就是使用两个指针,先让前面的指针走到正向第k个结点 - * ,这样前后两个指针的距离差是k,之后前后两个指针一起向前走,前面的指针走到空时,后面指针所指结点就是倒数第k个结点 - * when k = 1, it should be the last node. - */ - public static ListNode reGetKthNode(ListNode head, int k) { - if (head == null) { - return null; - } - - ListNode fast = head; - - // 使fast and slow之间差 k - while (k > 0) { - if (fast == null) { - // 发生这种情况,说明k > sizeOfList. - return null; - } - fast = fast.next; - k--; - } - - while (fast != null) { - fast = fast.next; - head = head.next; - } - - return head; - } - - /* - * 递归打印出倒数第k个节点。 - * */ - static int level = 0; - public static void reGetKthNodeRec(ListNode head, int k) { - if (head == null) { - return; - } - - reGetKthNodeRec(head.next, k); - level++; - if (level == k) { - System.out.println(head.val); - } - } - - /* - * 递归打印出倒数第k个节点。 - * return: the length of the link. - * 此为改进的递归算法,使用此算法,不需要加入辅助变量。 - * */ - public static int reGetKthNodeRec2(ListNode head, int k) { - if (head == null) { - return 0; - } - - int len = reGetKthNodeRec2(head.next, k); - if (len == k - 1) { - System.out.println(head.val); - } - - return len + 1; - } - - /** - * 判断一个单链表中是否有环 - * 这里也是用到两个指针。如果一个链表中有环,也就是说用一个指针去遍历,是永远走不到头的。因此,我们可以用两个指针去遍历,一个指针一次走两步 - * ,一个指针一次走一步,如果有环,两个指针肯定会在环中相遇。时间复杂度为O(n) - */ - public static boolean hasCycle(ListNode head) { - ListNode slow = head; // 快指针每次前进两步 - ListNode fast = head; // 慢指针每次前进一步 - - // 如果fast没有到达尾部,那么slow也不会。所以不需要判定slow是不是null - while (fast != null && fast.next != null) { - fast = fast.next.next; - slow = slow.next; - if (slow == fast) { // 相遇,存在环 - return true; - } - } - - return false; - - } - - /* - * 4. 查找单链表的中间结点: getMiddleNode - * 这里只处理n个数为 奇数的情况 - * 我们可以设置2个 指针,一个快,一个慢 - * 1-2-3-null - * 当fast前进2n时,它到达3,链表长度是2n + 1 - * 中间节点应为(2n+1)/2 + 1 = n + 1; - * 所以,slow节点前进n恰好可以到达中间。 - * - * 边界: - * n = 1时,一开始就可以退出,仍然可以满足 - * 此算法特点: - * 1->2->3->4 - * 返回2 - */ - public static ListNode getMiddleNode(ListNode head) { - if (head == null) { - return null; - } - - ListNode fast = head; - ListNode slow = head; - - while (fast != null && fast.next != null && fast.next.next != null) { - fast = fast.next.next; - slow = slow.next; - } - - return slow; - } - - /** - * 5. 从尾到头打印单链表: reversePrintListStack,reversePrintListRec(递归) - * @param head - * @return - */ - public static void reversePrintListStackRec(ListNode head) { - if (head == null) { - return; - } - - // print the next first. - reversePrintListStackRec(head.next); - System.out.print(head.val + " "); - } - - /** - * 从尾到头打印单链表 - * 对于这种颠倒顺序的问题,我们应该就会想到栈,后进先出。所以,这一题要么自己使用栈,要么让系统使用栈,也就是递归。注意链表为空的情况 - * 。时间复杂度为O(n) - * - * 还有一种做法,是可以把链表反转,我们也可以从头到尾打印。 - */ - public static void reversePrintListStack(ListNode head) { - if (head == null) { - return; - } - - System.out.println(); - - Stack s = new Stack(); - while (head != null) { - s.push(head.val); - head = head.next; - } - - // print the next first. - while (!s.isEmpty()) { - System.out.print(s.pop() + " "); - } - } - - /** - * 从尾到头打印单链表 - * 是可以把链表反转,我们也可以从头到尾打印。 为了不影响原有的链表,可以再反转回来 - */ - public static void reversePrintListRev(ListNode head) { - if (head == null) { - return; - } - - ListNode rev = reverseList(head); - - System.out.println(); - - // print the next first. - ListNode curr = rev; - while (curr != null) { - System.out.print(rev.val + " "); - curr = curr.next; - } - - System.out.println(); - - //printList(rev); - reverseList(rev); - } - - /* - * 6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList, mergeSortedListRec - * - * 与merge sort思想类似. - * */ - public static ListNode mergeSortedList(ListNode head1, ListNode head2) { - if (head1 == null) { - return head2; - } else if (head2 == null) { - return head1; - } - - // 作为头节点的前一个节点 - ListNode dummyNode = new ListNode(0); - ListNode curr = dummyNode; - while (head1 != null && head2 != null) { - if (head1.val < head2.val) { - curr.next = head1; - head1 = head1.next; - } else { - curr.next = head2; - head2 = head2.next; - } - - curr = curr.next; - } - - // 把没有取完的链直接接在结果上即可。 - if (head1 != null) { - curr.next = head1; - } else { - curr.next = head2; - } - - return dummyNode.next; - } - - /* - * 先完成的算法,应该会简单一点儿。 - * 简直是优雅的算法啊!太棒了!只不过 为什么自己很难想出这么棒的算法呢? - * 虽然递归的原理每个人都懂,但是写出漂亮的递归真的是考验功底呢。 - * - * 精髓就是: 在每一次的Merge的处理时,只需要考虑merge一个元素,也就是提取出一个元素,而下一步的merge,交给下一步的recursion - * 来处理。 - */ - public static ListNode mergeSortedListRec(ListNode head1, ListNode head2) { - if (head1 == null) { - return head2; - } - - if (head2 == null) { - return head1; - } - - ListNode headMerge = null; - if (head1.val < head2.val) { - headMerge = head1; - head1.next = mergeSortedListRec(head1.next, head2); - } else { - headMerge = head2; - head2.next = mergeSortedListRec(head1, head2.next); - } - - return headMerge; - } - - - // http://fisherlei.blogspot.com/2013/11/leetcode-linked-list-cycle-ii-solution.html - // 更进一步,寻找环的起点,实际上,2点相遇后,我们再将某点放回起点,让它再走X的距离(X为起点到环的交点的距离), - // 即可让2个点相交在环的点处。 - public static ListNode detectCycle(ListNode head) { - ListNode slow = head; - ListNode fast = head; - - while (fast != null && fast.next != null) { - fast = fast.next.next; - slow = slow.next; - if (slow == fast) { - ListNode n1 = head; - while (true) { - if (n1 == slow) { // 注意,要选判断,再移动, - return n1; // because 环的起点有可能就在开始的地方。 - } - n1 = n1.next; - slow = slow.next; - } - } - } - - return null; - } - - /* - * * 8. 判断两个单链表是否相交: isIntersect - * http://blog.csdn.net/yunzhongguwu005/article/details/11527675 - * 求两个单链表是否相交分三种情况讨论: - * 1,如果两个链表一个有环,一个无环则一定不相交 - * 2.如果都没有环,则判断两个链表的最后节点是否相同,如果相同则相交,不相同则不相交。 - * 3.如果都有环,则判断一个链表环里的节点是否是另一个链表环里的节点。如果是则相交,如果不是则不相交。 - * - * 步骤如下: - * 1. 先判断2个链表有没有环。 - * 2. 如果都没有环,查最后节点是否相同 - * 3. 如果都有环,则将b链的环节点跑一圈,如果遇到A链中的节点,则返回true - */ - public static boolean isIntersect(ListNode head1, ListNode head2) { - if (head1 == null || head2 == null) { - return false; - } - - ListNode head1C = hasCycleRetNode(head1); - ListNode head2C = hasCycleRetNode(head2); - - // 两个链表都是有环的。 - if (head1C != null && head2C != null) { - ListNode tmp = head1C; - do { - // 放在前面判断,因为有可能当前节点就是要求的结果 - if (head1C == head2C) { - return true; - } - - // 跑一圈来找是不是同一个圈。 - head1C = head1C.next; - } while (tmp != head1C); - - return false; - // 两个链表都是没有环的 - } else if (head1C == null && head2C == null){ - while (head1.next != null) { - head1 = head1.next; - } - - while (head2.next != null) { - head2 = head2.next; - } - - // 无环的话,应该具有相同的尾节点. - return head1 == head2; - } else { - return false; - } - } - - /** - * 如果有环,返回在环内的某节点。否则返回null - */ - public static ListNode hasCycleRetNode(ListNode head) { - if (head == null) { - return head; - } - - ListNode s = head; - ListNode f = head; - - while (f != null && f.next != null) { - f = f.next.next; - s = s.next; - if (f == s) { - return f; - } - } - - return null; - } - - /* - * * 9. 求两个单链表相交的第一个节点: getFirstCommonNode - * 分为2种情况: - * - * 1. 没有环的情况. - * 求两个单链表相交的第一个节点 对第一个链表遍历,计算长度len1,同时保存最后一个节点的地址。 - * 对第二个链表遍历,计算长度len2,同时检查最后一个节点是否和第一个链表的最后一个节点相同,若不相同,不相交,结束。 - * 两个链表均从头节点开始,假设len1大于len2 - * ,那么将第一个链表先遍历len1-len2个节点,此时两个链表当前节点到第一个相交节点的距离就相等了,然后一起向后遍历,直到两个节点的地址相同。 - * 时间复杂度,O(len1+len2) - * - * ---- len2 - * |__________ - * | - * --------- len1 - * |---|<- len1-len2 - * - * 2. 有环的情况 - * (1). 交点在环上 - * 这样子的话,实际上我们可以求出2个交点。我们只要判断2个交点是不是相等。不相等,把2个交点返回任何一个。 - * (2). 交点不在环上,则计算出环的交点,然后len1 = 起点至环的交点,len2 = 起点至环的交点,然后如方法1相同的做法。 - */ - public static ListNode getFirstCommonNode(ListNode head1, ListNode head2) { - if (head1 == null || head2 == null) { - return null; - } - - ListNode cross1 = detectCycle(head1); - ListNode cross2 = detectCycle(head2); - - // There is no CIRCLE - if (cross1 == null && cross2 == null) { - int len1 = getListLength(head1); - int len2 = getListLength(head2); - - //将长的链截短 - if (len1 > len2) { - while (len1 > len2) { - head1 = head1.next; - len1--; - } - } else { - while (len2 > len1) { - head2 = head2.next; - len2--; - } - } - - while (head1 != null) { - if (head1.next == head2.next) { - return head1.next; - } - } - - return null; - } else if (cross1 != null && cross2 != null) { - return cross1; - } - - return null; - } - - /** - * 求进入环中的第一个节点 用HashSet做 一个无环的链表,它每个结点的地址都是不一样的。 - * 但如果有环,指针沿着链表移动,那这个指针最终会指向一个已经出现过的地址 以地址为哈希表的键值,每出现一个地址, - 只要出现重复的元素,就找到了环的交点. - */ - public static ListNode getFirstNodeInCycleHashMap(ListNode head) { - if (head == null) { - return null; - } - - HashSet h = new HashSet(); - while (head != null) { - if (h.contains(head)) { - return head; - } else { - h.add(head); - } - head = head.next; - } - - return null; - } - - /* - * 对于删除节点,我们普通的思路就是让该节点的前一个节点指向该节点的下一个节点,这种情况需要遍历找到该节点的前一个节点, - * 时间复杂度为O(n)。对于链表,链表中的每个节点结构都是一样的,所以我们可以把该节点的下一个节点的数据复制到该节点, - * 然后删除下一个节点即可。要注意最后一个节点的情况,这个时候只能用常见的方法来操作,先找到前一个节点, - * 但总体的平均时间复杂度还是O(1)。参考代码如下: - * */ - public static void Delete(ListNode head, ListNode toBeDeleted) { - if (head == null) { - return; - } - - if (toBeDeleted.next != null) { - toBeDeleted.val = toBeDeleted.next.val; - toBeDeleted.next = toBeDeleted.next.next; - } else { - while (head != null) { - if (head.next == toBeDeleted) { - head.next = toBeDeleted.next; - return; - } - head = head.next; - } - } - - return; - } -} diff --git a/PostOrder.java b/PostOrder.java index 491b9b9..22ccb70 100644 --- a/PostOrder.java +++ b/PostOrder.java @@ -14,9 +14,6 @@ public class PostOrder { * TreeNode(int x) { val = x; } * } */ - - - public ArrayList postorderTraversal(TreeNode root) { ArrayList result = new ArrayList(); From 841e1670609c3bb25349b5f7e13cc939b7cdff84 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 23 Sep 2014 16:17:36 -0700 Subject: [PATCH 002/319] add the demos --- GraphDemo.java | 103 +++++++ ListNodeDemo.java | 716 ++++++++++++++++++++++++++++++++++++++++++++++ TreeDemo.java | 571 ++++++++++++++++++++++++++++++++++++ 3 files changed, 1390 insertions(+) create mode 100644 GraphDemo.java create mode 100644 ListNodeDemo.java create mode 100644 TreeDemo.java diff --git a/GraphDemo.java b/GraphDemo.java new file mode 100644 index 0000000..241d5ca --- /dev/null +++ b/GraphDemo.java @@ -0,0 +1,103 @@ +package Algorithms; + +import java.util.ArrayList; + +public class GraphDemo { + private static int M = Integer.MAX_VALUE; // 表示此路不可通 + + // http://www.geeksforgeeks.org/greedy-algorithms-set-6-dijkstras-shortest-path-algorithm/ + // 以上为不能再优美的C语言实现。 + public static void main(String[] args) { + int[][] w = { // 用邻接表矩阵表示的无向图 + {0, 3, 2000, 7, M}, + {3, 0, 4, 2, M}, + {M, 4, 0, 5, 4}, + {7, 2, 5, 0, 6}, + {M, M , 4, 6, 0} + }; + + int[][] w2 = { // 用邻接表矩阵表示的无向图 + {0, 10, M, 30, 100}, + {M, 0, 50, M, M}, + {M, M, 0, M, 10}, + {M, M, 20, 0, 60}, + {M, M, M, M, 0} + }; + + int start = 0; + + int[] shortPath = dijkstra(w2, start); + + for (int i = 0; i < shortPath.length; i++) { + System.out.println("The shortest path length from start to " + i + " is:" + shortPath[i]); + } + } + + public static int[] dijkstra(int[][] graph, int src) { + if (graph == null || graph.length == 0 || graph[0].length == 0) { + return null; + } + + // get to know the number of the vertexs. + int v = graph.length; + + // We need a indicator to know if we have visited the vertex. + boolean visit[] = new boolean[v]; + + // record the length result. + int[] pathLen = new int[v]; + + // record the path. + ArrayList> path = new ArrayList>(); + for (int i = 0; i < v; i++) { + path.add(new ArrayList()); + path.get(i).add(0); + path.get(i).add(i); + } + + // setup the source vertex; + visit[0] = true; + pathLen[0] = 0; + + // stop when all the vertices has been added into the result set. + for (int i = 0; i < v - 1; i++) { + + int minLen = M; + int minIndex = -1; + for (int j = 0; j < v; j++) { + // sometimes there is no route, so just let equal also return. + // so we use graph[src][j] <= minLen + if (!visit[j] && graph[src][j] <= minLen) { + minLen = graph[src][j]; + minIndex = j; + } + } + + // get the new shortest path, add it into the solution set. + visit[minIndex] = true; + pathLen[minIndex] = graph[src][minIndex]; + + // update all the neighbors of the new vertex. + for (int k = 0; k < v; k++) { + // if the path which pass the minIndex is shorter than the former path, + // just update it. + if (!visit[k] + && graph[src][minIndex] != M + && graph[minIndex][k] != M + && graph[src][minIndex] + graph[minIndex][k] < graph[src][k]) { + graph[src][k] = graph[src][minIndex] + graph[minIndex][k]; + + path.set(k, new ArrayList(path.get(minIndex))); + path.get(k).add(k); + } + } + } + + for (ArrayList array: path) { + System.out.println(array.toString()); + } + + return pathLen; + } + +} diff --git a/ListNodeDemo.java b/ListNodeDemo.java new file mode 100644 index 0000000..f23327d --- /dev/null +++ b/ListNodeDemo.java @@ -0,0 +1,716 @@ +package Algorithms; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Stack; + +/** + * REFS: + * http://blog.csdn.net/fightforyourdream/article/details/16353519 + * http://blog.csdn.net/luckyxiaoqiang/article/details/7393134 轻松搞定面试中的链表题目 + * http://www.cnblogs.com/jax/archive/2009/12/11/1621504.html 算法大全(1)单链表 + * + * 目录: + * 1. 求单链表中结点的个数: getListLength + * 2. 将单链表反转: reverseList(遍历),reverseListRec(递归) + * 3. 查找单链表中的倒数第K个节点(k > 0): reGetKthNode + * 4. 查找单链表的中间结点: getMiddleNode + * 5. 从尾到头打印单链表: reversePrintListStack,reversePrintListRec(递归) + * 6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList, mergeSortedListRec + * 7. 判断一个单链表中是否有环: hasCycle + * 8. 判断两个单链表是否相交: isIntersect + * 9. 求两个单链表相交的第一个节点: getFirstCommonNode + * 10. 已知一个单链表中存在环,求进入环中的第一个节点: detectCycle, getFirstNodeInCycleHashMap + * 11. 给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted: delete + * + */ + +public class ListNodeDemo { + + // create the link Node class. + // why use static: + // http://duqiangcise.iteye.com/blog/697476 + private static class ListNode { + int val; + ListNode next; + public ListNode(int val) { + this.val = val; + this.next = null; + } + + } + + public static void main(String[] args) { + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(2); + ListNode n3 = new ListNode(3); + ListNode n4 = new ListNode(4); + ListNode n5 = new ListNode(5); + ListNode n6 = new ListNode(6); + + ListNode m1 = new ListNode(5); + ListNode m2 = new ListNode(8); + ListNode m3 = new ListNode(9); + m1.next = m2; + m2.next = m3; + + ListNode c1 = new ListNode(1); + ListNode c2 = new ListNode(12); + c1.next = c2; + //c2.next = n1; + + ListNode mergeNode = mergeLink(m1, c1); + //ListNode mergeNode2 = mergeLink(m1, c1); + //ListNode mergeNode = mergeSortedList(m1, c1); + printList(mergeNode); + //printList(mergeNode2); + + System.out.println(); + + n1.next = n2; + n2.next = n3; + n3.next = n4; + n4.next = n5; + + printList(n1); + + Delete(n1, n5); + + printList(n1); + + // create a cycle + //n5.next = n3; + //n5.next = n6; + //n6.next = n4; + +// System.out.println(hasCycle(n1)); +// System.out.println(getListLength(n1)); +// printList(n1); +// +// //n1 = reverseList(n1); +// n1 = reverseListRec(n1); +// printList(n1); + +// ListNode ret = reGetKthNode(n1, 7); +// if (ret != null) { +// System.out.println(ret.val); +// } else { +// System.out.println("null"); +// } + + //reGetKthNodeRec(n1, 1); +// reGetKthNodeRec2(n1, 3); +// ListNode ret = getMiddleNode(n1); +// +// if (ret != null) { +// System.out.println(ret.val); +// } +// +// reversePrintListStackRec(n1); +// reversePrintListStack(n1); +// reversePrintListRev(n1); + + //printList(n1); + + System.out.println(isIntersect(n1, c1)); + + ListNode cross = getFirstCommonNode(n1, c1); + if (cross == null) { + System.out.println("null"); + } else { + System.out.println(cross.val); + } + + ListNode cross2 = getFirstNodeInCycleHashMap(c1); + if (cross2 == null) { + System.out.println("null"); + } else { + System.out.println(cross2.val); + } + } + + public static void printList(ListNode head) { + while (head != null) { + System.out.print(head.val + " "); + head = head.next; + } + + System.out.println(); + } + + // 获得ListNode 的长度 + public static int getListLength(ListNode head) { + if (head == null) { + return 0; + } + + int len = 0; + while (head != null) { + len++; + head = head.next; + } + + return len; + } + + /* + * 反转链表 + * 此算法亮点是:一次只需要处理把下一个节点指向curr, + * 不断循环,即可完成任务 + * */ + public static ListNode reverseList(ListNode head) { + if (head == null) { + return null; + } + + ListNode next = head.next; + ListNode curr = head; + + // 先把头节点的下一个指定. + curr.next = null; + + // 每次只需要将curr的next指向curr即可, + // 终止条件是:next是null 表示我们将所有的节点进行了翻转 + while (next != null) { + ListNode tmp = next.next; + next.next = curr; + curr = next; + next = tmp; + } + + return curr; + } + + // 翻转递归(递归) + // 递归的精髓在于你就默认reverseListRec已经成功帮你解决了子问题了!但别去想如何解决的 + // 现在只要处理当前node和子问题之间的关系。最后就能圆满解决整个问题。 + /* + head + 1 -> 2 -> 3 -> 4 + + head + 1-------------- + | + 4 -> 3 -> 2 // Node reHead = reverseListRec(head.next); + reHead head.next + + 4 -> 3 -> 2 -> 1 // head.next.next = head; + reHead + + 4 -> 3 -> 2 -> 1 -> null // head.next = null; + reHead + */ + public static ListNode reverseListRec(ListNode head) { + // if there is no node, or only one node, just return; + if (head == null || head.next == null) { + return head; + } + + ListNode reHead = reverseListRec(head.next); // 先求解子问题。 + head.next.next = head; // 将head 与被解决的子串的尾部相连。 + head.next = null; // head的下一个必须指向 null,因为head 是新的尾部. + + return reHead; + } + + /** + * 查找单链表中的倒数第K个结点(k > 0) + * 最普遍的方法是,先统计单链表中结点的个数,然后再找到第(n-k)个结点。注意链表为空,k为0,k为1,k大于链表中节点个数时的情况 + * 。时间复杂度为O(n)。代码略。 这里主要讲一下另一个思路,这种思路在其他题目中也会有应用。 + * 主要思路就是使用两个指针,先让前面的指针走到正向第k个结点 + * ,这样前后两个指针的距离差是k,之后前后两个指针一起向前走,前面的指针走到空时,后面指针所指结点就是倒数第k个结点 + * when k = 1, it should be the last node. + */ + public static ListNode reGetKthNode(ListNode head, int k) { + if (head == null) { + return null; + } + + ListNode fast = head; + + // 使fast and slow之间差 k + while (k > 0) { + if (fast == null) { + // 发生这种情况,说明k > sizeOfList. + return null; + } + fast = fast.next; + k--; + } + + while (fast != null) { + fast = fast.next; + head = head.next; + } + + return head; + } + + /* + * 递归打印出倒数第k个节点。 + * */ + static int level = 0; + public static void reGetKthNodeRec(ListNode head, int k) { + if (head == null) { + return; + } + + reGetKthNodeRec(head.next, k); + level++; + if (level == k) { + System.out.println(head.val); + } + } + + /* + * 递归打印出倒数第k个节点。 + * return: the length of the link. + * 此为改进的递归算法,使用此算法,不需要加入辅助变量。 + * */ + public static int reGetKthNodeRec2(ListNode head, int k) { + if (head == null) { + return 0; + } + + int len = reGetKthNodeRec2(head.next, k); + if (len == k - 1) { + System.out.println(head.val); + } + + return len + 1; + } + + /** + * 判断一个单链表中是否有环 + * 这里也是用到两个指针。如果一个链表中有环,也就是说用一个指针去遍历,是永远走不到头的。因此,我们可以用两个指针去遍历,一个指针一次走两步 + * ,一个指针一次走一步,如果有环,两个指针肯定会在环中相遇。时间复杂度为O(n) + */ + public static boolean hasCycle(ListNode head) { + ListNode slow = head; // 快指针每次前进两步 + ListNode fast = head; // 慢指针每次前进一步 + + // 如果fast没有到达尾部,那么slow也不会。所以不需要判定slow是不是null + while (fast != null && fast.next != null) { + fast = fast.next.next; + slow = slow.next; + if (slow == fast) { // 相遇,存在环 + return true; + } + } + + return false; + + } + + /* + * 4. 查找单链表的中间结点: getMiddleNode + * 这里只处理n个数为 奇数的情况 + * 我们可以设置2个 指针,一个快,一个慢 + * 1-2-3-null + * 当fast前进2n时,它到达3,链表长度是2n + 1 + * 中间节点应为(2n+1)/2 + 1 = n + 1; + * 所以,slow节点前进n恰好可以到达中间。 + * + * 边界: + * n = 1时,一开始就可以退出,仍然可以满足 + * 此算法特点: + * 1->2->3->4 + * 返回2 + */ + public static ListNode getMiddleNode(ListNode head) { + if (head == null) { + return null; + } + + ListNode fast = head; + ListNode slow = head; + + while (fast != null && fast.next != null && fast.next.next != null) { + fast = fast.next.next; + slow = slow.next; + } + + return slow; + } + + /** + * 5. 从尾到头打印单链表: reversePrintListStack,reversePrintListRec(递归) + * @param head + * @return + */ + public static void reversePrintListStackRec(ListNode head) { + if (head == null) { + return; + } + + // print the next first. + reversePrintListStackRec(head.next); + System.out.print(head.val + " "); + } + + /** + * 从尾到头打印单链表 + * 对于这种颠倒顺序的问题,我们应该就会想到栈,后进先出。所以,这一题要么自己使用栈,要么让系统使用栈,也就是递归。注意链表为空的情况 + * 。时间复杂度为O(n) + * + * 还有一种做法,是可以把链表反转,我们也可以从头到尾打印。 + */ + public static void reversePrintListStack(ListNode head) { + if (head == null) { + return; + } + + System.out.println(); + + Stack s = new Stack(); + while (head != null) { + s.push(head.val); + head = head.next; + } + + // print the next first. + while (!s.isEmpty()) { + System.out.print(s.pop() + " "); + } + } + + /** + * 从尾到头打印单链表 + * 是可以把链表反转,我们也可以从头到尾打印。 为了不影响原有的链表,可以再反转回来 + */ + public static void reversePrintListRev(ListNode head) { + if (head == null) { + return; + } + + ListNode rev = reverseList(head); + + System.out.println(); + + // print the next first. + ListNode curr = rev; + while (curr != null) { + System.out.print(rev.val + " "); + curr = curr.next; + } + + System.out.println(); + + //printList(rev); + reverseList(rev); + } + + /* + * 6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList, mergeSortedListRec + * + * 与merge sort思想类似. + * */ + public static ListNode mergeSortedList(ListNode head1, ListNode head2) { + if (head1 == null) { + return head2; + } else if (head2 == null) { + return head1; + } + + // 作为头节点的前一个节点 + ListNode dummyNode = new ListNode(0); + ListNode curr = dummyNode; + while (head1 != null && head2 != null) { + if (head1.val < head2.val) { + curr.next = head1; + head1 = head1.next; + } else { + curr.next = head2; + head2 = head2.next; + } + + curr = curr.next; + } + + // 把没有取完的链直接接在结果上即可。 + if (head1 != null) { + curr.next = head1; + } else { + curr.next = head2; + } + + return dummyNode.next; + } + + static class Node { + Node next; + int val; + Node (int val) { + this.val = val; + } + } + + public static ListNode mergeLink (ListNode aLink, ListNode bLink) { + ListNode dummy = new ListNode(0); + + ListNode root = dummy; + + while (aLink != null && bLink != null) { + if (aLink.val < bLink.val) { + dummy.next = aLink; + dummy = aLink; + aLink = aLink.next; + + } else { + dummy.next = bLink; + dummy = bLink; + bLink = bLink.next; + + } + } + + if (aLink != null) { + dummy.next = aLink; + } else { + dummy.next = bLink; + } + + return root.next; + } + + /* + * 先完成的算法,应该会简单一点儿。 + * 简直是优雅的算法啊!太棒了!只不过 为什么自己很难想出这么棒的算法呢? + * 虽然递归的原理每个人都懂,但是写出漂亮的递归真的是考验功底呢。 + * + * 精髓就是: 在每一次的Merge的处理时,只需要考虑merge一个元素,也就是提取出一个元素,而下一步的merge,交给下一步的recursion + * 来处理。 + */ + public static ListNode mergeSortedListRec(ListNode head1, ListNode head2) { + if (head1 == null) { + return head2; + } + + if (head2 == null) { + return head1; + } + + ListNode headMerge = null; + if (head1.val < head2.val) { + headMerge = head1; + head1.next = mergeSortedListRec(head1.next, head2); + } else { + headMerge = head2; + head2.next = mergeSortedListRec(head1, head2.next); + } + + return headMerge; + } + + + // http://fisherlei.blogspot.com/2013/11/leetcode-linked-list-cycle-ii-solution.html + // 更进一步,寻找环的起点,实际上,2点相遇后,我们再将某点放回起点,让它再走X的距离(X为起点到环的交点的距离), + // 即可让2个点相交在环的点处。 + public static ListNode detectCycle(ListNode head) { + ListNode slow = head; + ListNode fast = head; + + while (fast != null && fast.next != null) { + fast = fast.next.next; + slow = slow.next; + if (slow == fast) { + ListNode n1 = head; + while (true) { + if (n1 == slow) { // 注意,要选判断,再移动, + return n1; // because 环的起点有可能就在开始的地方。 + } + n1 = n1.next; + slow = slow.next; + } + } + } + + return null; + } + + /* + * * 8. 判断两个单链表是否相交: isIntersect + * http://blog.csdn.net/yunzhongguwu005/article/details/11527675 + * 求两个单链表是否相交分三种情况讨论: + * 1,如果两个链表一个有环,一个无环则一定不相交 + * 2.如果都没有环,则判断两个链表的最后节点是否相同,如果相同则相交,不相同则不相交。 + * 3.如果都有环,则判断一个链表环里的节点是否是另一个链表环里的节点。如果是则相交,如果不是则不相交。 + * + * 步骤如下: + * 1. 先判断2个链表有没有环。 + * 2. 如果都没有环,查最后节点是否相同 + * 3. 如果都有环,则将b链的环节点跑一圈,如果遇到A链中的节点,则返回true + */ + public static boolean isIntersect(ListNode head1, ListNode head2) { + if (head1 == null || head2 == null) { + return false; + } + + ListNode head1C = hasCycleRetNode(head1); + ListNode head2C = hasCycleRetNode(head2); + + // 两个链表都是有环的。 + if (head1C != null && head2C != null) { + ListNode tmp = head1C; + do { + // 放在前面判断,因为有可能当前节点就是要求的结果 + if (head1C == head2C) { + return true; + } + + // 跑一圈来找是不是同一个圈。 + head1C = head1C.next; + } while (tmp != head1C); + + return false; + // 两个链表都是没有环的 + } else if (head1C == null && head2C == null){ + while (head1.next != null) { + head1 = head1.next; + } + + while (head2.next != null) { + head2 = head2.next; + } + + // 无环的话,应该具有相同的尾节点. + return head1 == head2; + } else { + return false; + } + } + + /** + * 如果有环,返回在环内的某节点。否则返回null + */ + public static ListNode hasCycleRetNode(ListNode head) { + if (head == null) { + return head; + } + + ListNode s = head; + ListNode f = head; + + while (f != null && f.next != null) { + f = f.next.next; + s = s.next; + if (f == s) { + return f; + } + } + + return null; + } + + /* + * * 9. 求两个单链表相交的第一个节点: getFirstCommonNode + * 分为2种情况: + * + * 1. 没有环的情况. + * 求两个单链表相交的第一个节点 对第一个链表遍历,计算长度len1,同时保存最后一个节点的地址。 + * 对第二个链表遍历,计算长度len2,同时检查最后一个节点是否和第一个链表的最后一个节点相同,若不相同,不相交,结束。 + * 两个链表均从头节点开始,假设len1大于len2 + * ,那么将第一个链表先遍历len1-len2个节点,此时两个链表当前节点到第一个相交节点的距离就相等了,然后一起向后遍历,直到两个节点的地址相同。 + * 时间复杂度,O(len1+len2) + * + * ---- len2 + * |__________ + * | + * --------- len1 + * |---|<- len1-len2 + * + * 2. 有环的情况 + * (1). 交点在环上 + * 这样子的话,实际上我们可以求出2个交点。我们只要判断2个交点是不是相等。不相等,把2个交点返回任何一个。 + * (2). 交点不在环上,则计算出环的交点,然后len1 = 起点至环的交点,len2 = 起点至环的交点,然后如方法1相同的做法。 + */ + public static ListNode getFirstCommonNode(ListNode head1, ListNode head2) { + if (head1 == null || head2 == null) { + return null; + } + + ListNode cross1 = detectCycle(head1); + ListNode cross2 = detectCycle(head2); + + // There is no CIRCLE + if (cross1 == null && cross2 == null) { + int len1 = getListLength(head1); + int len2 = getListLength(head2); + + //将长的链截短 + if (len1 > len2) { + while (len1 > len2) { + head1 = head1.next; + len1--; + } + } else { + while (len2 > len1) { + head2 = head2.next; + len2--; + } + } + + while (head1 != null) { + if (head1.next == head2.next) { + return head1.next; + } + } + + return null; + } else if (cross1 != null && cross2 != null) { + return cross1; + } + + return null; + } + + /** + * 求进入环中的第一个节点 用HashSet做 一个无环的链表,它每个结点的地址都是不一样的。 + * 但如果有环,指针沿着链表移动,那这个指针最终会指向一个已经出现过的地址 以地址为哈希表的键值,每出现一个地址, + 只要出现重复的元素,就找到了环的交点. + */ + public static ListNode getFirstNodeInCycleHashMap(ListNode head) { + if (head == null) { + return null; + } + + HashSet h = new HashSet(); + while (head != null) { + if (h.contains(head)) { + return head; + } else { + h.add(head); + } + head = head.next; + } + + return null; + } + + /* + * 对于删除节点,我们普通的思路就是让该节点的前一个节点指向该节点的下一个节点,这种情况需要遍历找到该节点的前一个节点, + * 时间复杂度为O(n)。对于链表,链表中的每个节点结构都是一样的,所以我们可以把该节点的下一个节点的数据复制到该节点, + * 然后删除下一个节点即可。要注意最后一个节点的情况,这个时候只能用常见的方法来操作,先找到前一个节点, + * 但总体的平均时间复杂度还是O(1)。参考代码如下: + * */ + public static void Delete(ListNode head, ListNode toBeDeleted) { + if (head == null) { + return; + } + + if (toBeDeleted.next != null) { + toBeDeleted.val = toBeDeleted.next.val; + toBeDeleted.next = toBeDeleted.next.next; + } else { + while (head != null) { + if (head.next == toBeDeleted) { + head.next = toBeDeleted.next; + return; + } + head = head.next; + } + } + + return; + } +} diff --git a/TreeDemo.java b/TreeDemo.java new file mode 100644 index 0000000..4982693 --- /dev/null +++ b/TreeDemo.java @@ -0,0 +1,571 @@ +package Algorithms; + + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Queue; +import java.util.Stack; + + +public class TreeDemo { + /* + 1 + / \ + 2 3 + / \ \ + 4 5 6 + */ + public static void main(String[] args) { +// TreeNode r1 = new TreeNode(1); +// TreeNode r2 = new TreeNode(2); +// TreeNode r3 = new TreeNode(3); +// TreeNode r4 = new TreeNode(4); +// TreeNode r5 = new TreeNode(5); +// TreeNode r6 = new TreeNode(6); + +/* + 10 + / \ + 6 14 + / \ \ + 4 8 16 +*/ + TreeNode r1 = new TreeNode(10); + TreeNode r2 = new TreeNode(6); + TreeNode r3 = new TreeNode(14); + TreeNode r4 = new TreeNode(4); + TreeNode r5 = new TreeNode(8); + TreeNode r6 = new TreeNode(16); + + TreeNode r7 = new TreeNode(0); + + r1.left = r2; + r1.right = r3; + r2.left = r4; + r2.right = r5; + r3.right = r6; + + r4.left = r7; + +// System.out.println(getNodeNumRec(null)); +// System.out.println(getNodeNum(r1)); +// System.out.println(getDepthRec(r1)); +// System.out.println(getDepth(r1)); +// +// preorderTraversalRec(r1); +// System.out.println(); +// preorderTraversal(r1); +// System.out.println(); +// inorderTraversalRec(r1); +// +// System.out.println(); + inorderTraversal(r1); +// postorderTraversalRec(r1); +// System.out.println(); +// postorderTraversal(r1); +// System.out.println(); +// levelTraversal(r1); +// +// System.out.println(); +// levelTraversalRec(r1); + +// TreeNode ret = convertBST2DLLRec(r1); +// while (ret != null) { +// System.out.print(ret.val + " "); +// ret = ret.right; +// } + +// TreeNode ret2 = convertBST2DLL(r1); +// while (ret2.right != null) { +// ret2 = ret2.right; +// } +// +// while (ret2 != null) { +// System.out.print(ret2.val + " "); +// ret2 = ret2.left; +// } +// +// TreeNode ret = convertBST2DLL(r1); +// while (ret != null) { +// System.out.print(ret.val + " "); +// ret = ret.right; +// } + + System.out.println(); + System.out.println(findLongest(r1)); + System.out.println(); + System.out.println(findLongest2(r1)); + + } + + private static class TreeNode{ + int val; + TreeNode left; + TreeNode right; + public TreeNode(int val){ + this.val = val; + left = null; + right = null; + } + } + + /* + * null返回0,然后把左右子树的size加上即可。 + * */ + public static int getNodeNumRec(TreeNode root) { + if (root == null) { + return 0; + } + + return getNodeNumRec(root.left) + getNodeNumRec(root.right) + 1; + } + + /** + * 求二叉树中的节点个数迭代解法O(n):基本思想同LevelOrderTraversal, + * 即用一个Queue,在Java里面可以用LinkedList来模拟 + */ + public static int getNodeNum(TreeNode root) { + if (root == null) { + return 0; + } + + Queue q = new LinkedList(); + q.offer(root); + + int cnt = 0; + while (!q.isEmpty()) { + TreeNode node = q.poll(); + if (node.left != null) { + q.offer(node.left); + } + + if (node.right != null) { + q.offer(node.right); + } + + cnt++; + } + + return cnt; + } + + public static int getDepthRec(TreeNode root) { + if (root == null) { + return 0; + } + + return Math.max(getDepthRec(root.left), getDepthRec(root.right)) + 1; + } + + /* + * 可以用 level LevelOrderTraversal 来实现,我们用一个dummyNode来分隔不同的层,这样即可计算出实际的depth. + * 1 + / \ + 2 3 + / \ \ + 4 5 6 + * + * 在队列中如此排列: 1, dummy, 2, 3, dummy, 4, 5, 5, dummy + * + */ + public static int getDepth(TreeNode root) { + if (root == null) { + return 0; + } + + TreeNode dummy = new TreeNode(0); + Queue q = new LinkedList(); + q.offer(root); + q.offer(dummy); + + int depth = 0; + while (!q.isEmpty()) { + TreeNode curr = q.poll(); + if (curr == dummy) { + depth++; + if (!q.isEmpty()) { // 使用DummyNode来区分不同的层, 如果下一层不是为空,则应该在尾部加DummyNode. + q.offer(dummy); + } + } + + if (curr.left != null) { + q.offer(curr.left); + } + if (curr.right != null) { + q.offer(curr.right); + } + } + + return depth; + } + + /* + * 3. 前序遍历,中序遍历,后序遍历: preorderTraversalRec, preorderTraversal, inorderTraversalRec, postorderTraversalRec + * (https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2) + * */ + public static void preorderTraversalRec(TreeNode root) { + if (root == null) { + return; + } + + System.out.print(root.val + " "); + preorderTraversalRec(root.left); + preorderTraversalRec(root.right); + } + + /* + * 前序遍历,Iteration 算法. 把根节点存在stack中。 + * */ + public static void preorderTraversal(TreeNode root) { + if (root == null) { + return; + } + + Stack s = new Stack(); + s.push(root); + + while (!s.isEmpty()) { + TreeNode node = s.pop(); + System.out.print(node.val + " "); + if (node.right != null) { // + s.push(node.right); + } + + // 我们需要先压入右节点,再压入左节点,这样就可以先弹出左节点。 + if (node.left != null) { + s.push(node.left); + } + } + } + + /* + * 中序遍历 + * */ + public static void inorderTraversalRec(TreeNode root) { + if (root == null) { + return; + } + + inorderTraversalRec(root.left); + System.out.print(root.val + " "); + inorderTraversalRec(root.right); + } + + /** + * 中序遍历迭代解法 ,用栈先把根节点的所有左孩子都添加到栈内, + * 然后输出栈顶元素,再处理栈顶元素的右子树 + * http://www.youtube.com/watch?v=50v1sJkjxoc + * + * 还有一种方法能不用递归和栈,基于线索二叉树的方法,较麻烦以后补上 + * http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/ + */ + public static void inorderTraversal(TreeNode root) { + if (root == null) { + return; + } + + Stack s = new Stack(); + + TreeNode cur = root; + + while(true) { + // 把当前节点的左节点都push到栈中. + while (cur != null) { + s.push(cur); + cur = cur.left; + } + + if (s.isEmpty()) { + break; + } + + // 因为此时已经没有左孩子了,所以输出栈顶元素 + cur = s.pop(); + System.out.print(cur.val + " "); + + // 准备处理右子树 + cur = cur.right; + } + } + + // 后序遍历 + /* + * 1 + / \ + 2 3 + / \ \ + 4 5 6 + + if put into the stack directly, then it should be: + 1, 2, 4, 5, 3, 6 in the stack. + when pop, it should be: 6, 3, 5, 4, 2, 1 + + if I + * */ + + public static void postorderTraversalRec(TreeNode root) { + if (root == null) { + return; + } + + postorderTraversalRec(root.left); + postorderTraversalRec(root.right); + System.out.print(root.val + " "); + } + + /** + * 后序遍历迭代解法 + * http://www.youtube.com/watch?v=hv-mJUs5mvU + * http://blog.csdn.net/tang_jin2015/article/details/8545457 + * 从左到右的后序 与从右到左的前序的逆序是一样的,所以就简单喽! 哈哈 + * 用另外一个栈进行翻转即可喽 + */ + public static void postorderTraversal(TreeNode root) { + if (root == null) { + return; + } + + Stack s = new Stack(); + Stack out = new Stack(); + + s.push(root); + while(!s.isEmpty()) { + TreeNode cur = s.pop(); + out.push(cur); + + if (cur.left != null) { + s.push(cur.left); + } + if (cur.right != null) { + s.push(cur.right); + } + } + + while(!out.isEmpty()) { + System.out.print(out.pop().val + " "); + } + } + + /* + * 分层遍历二叉树(按层次从上往下,从左往右)迭代 + * 其实就是广度优先搜索,使用队列实现。队列初始化,将根节点压入队列。当队列不为空,进行如下操作:弹出一个节点 + * ,访问,若左子节点或右子节点不为空,将其压入队列 + * */ + public static void levelTraversal(TreeNode root) { + if (root == null) { + return; + } + + Queue q = new LinkedList(); + q.offer(root); + + while (!q.isEmpty()) { + TreeNode cur = q.poll(); + + System.out.print(cur.val + " "); + if (cur.left != null) { + q.offer(cur.left); + } + if (cur.right != null) { + q.offer(cur.right); + } + } + } + + public static void levelTraversalRec(TreeNode root) { + ArrayList> ret = new ArrayList>(); + levelTraversalVisit(root, 0, ret); + System.out.println(ret); + } + + /** + * 分层遍历二叉树(递归) + * 很少有人会用递归去做level traversal + * 基本思想是用一个大的ArrayList,里面包含了每一层的ArrayList。 + * 大的ArrayList的size和level有关系 + * + * http://discuss.leetcode.com/questions/49/binary-tree-level-order-traversal#answer-container-2543 + */ + public static void levelTraversalVisit(TreeNode root, int level, ArrayList> ret) { + if (root == null) { + return; + } + + // 如果ArrayList的层数不够用, 则新添加一层 + // when size = 3, level: 0, 1, 2 + if (level >= ret.size()) { + ret.add(new ArrayList()); + } + + // visit 当前节点 + ret.get(level).add(root.val); + + // 将左子树, 右子树添加到对应的层。 + levelTraversalVisit(root.left, level + 1, ret); + levelTraversalVisit(root.right, level + 1, ret); + } + + /* + * 题目要求:将二叉查找树转换成排序的双向链表,不能创建新节点,只调整指针。 + 查找树的结点定义如下: + 既然是树,其定义本身就是递归的,自然用递归算法处理就很容易。将根结点的左子树和右子树转换为有序的双向链表, + 然后根节点的left指针指向左子树结果的最后一个结点,同时左子树最后一个结点的right指针指向根节点; + 根节点的right指针指向右子树结果的第一个结点, + 同时右子树第一个结点的left指针指向根节点。 + * */ + public static TreeNode convertBST2DLLRec(TreeNode root) { + return convertBST2DLLRecHelp(root)[0]; + } + + /* + * ret[0] 代表左指针 + * ret[1] 代表右指针 + * */ + public static TreeNode[] convertBST2DLLRecHelp(TreeNode root) { + TreeNode[] ret = new TreeNode[2]; + ret[0] = null; + ret[1] = null; + + if (root == null) { + return ret; + } + + if (root.left != null) { + TreeNode left[] = convertBST2DLLRecHelp(root.left); + left[1].right = root; // 将左子树的尾节点连接到根 + root.left = left[1]; + + ret[0] = left[0]; + } else { + ret[0] = root; // 左节点返回root. + } + + if (root.right != null) { + TreeNode right[] = convertBST2DLLRecHelp(root.right); + right[0].left = root; // 将右子树的头节点连接到根 + root.right = right[0]; + + ret[1] = right[1]; + } else { + ret[1] = root; // 右节点返回root. + } + + return ret; + } + + /** + * 将二叉查找树变为有序的双向链表 迭代解法 + * 类似inOrder traversal的做法 + */ + public static TreeNode convertBST2DLL(TreeNode root) { + while (root == null) { + return null; + } + + TreeNode pre = null; + Stack s = new Stack(); + TreeNode cur = root; + TreeNode head = null; // 链表头 + + while (true) { + while (cur != null) { + s.push(cur); + cur = cur.left; + } + + // if stack is empty, just break; + if (s.isEmpty()) { + break; + } + + cur = s.pop(); + if (head == null) { + head = cur; + } + + // link pre and cur. + cur.left = pre; + if (pre != null) { + pre.right = cur; + } + + // 左节点已经处理完了,处理右节点 + cur = cur.right; + pre = cur; + } + + return root; + } + + /* + * 第一种解法: + * 返回左边最长,右边最长,及左子树最长,右子树最长。 + * */ + public static int findLongest(TreeNode root) { + if (root == null) { + return -1; + } + + TreeNode l = root; + int cntL = 0; + while (l.left != null) { + cntL++; + l = l.left; + } + + TreeNode r = root; + int cntR = 0; + while (r.right != null) { + cntR++; + r = r.right; + } + + int lmax = findLongest(root.left); + int rmax = findLongest(root.right); + + int max = Math.max(lmax, rmax); + max = Math.max(max, cntR); + max = Math.max(max, cntL); + + return max; + } + + /* 1 + * 2 3 + * 3 4 + * 6 1 + * 7 + * 9 + * 11 + * 2 + * 14 + * */ + public static int findLongest2(TreeNode root) { + int [] maxVal = new int[1]; + maxVal[0] = -1; + findLongest2Help(root, maxVal); + return maxVal[0]; + } + + // ret: + // 0: the left side longest, + // 1: the right side longest. + static int maxLen = -1; + static int[] findLongest2Help(TreeNode root, int[] maxVal) { + int[] ret = new int[2]; + if (root == null) { + ret[0] = -1; + ret[1] = -1; + return ret; + } + + ret[0] = findLongest2Help(root.left, maxVal)[0] + 1; + ret[1] = findLongest2Help(root.right, maxVal)[1] + 1; + //maxLen = Math.max(maxLen, ret[0]); + //maxLen = Math.max(maxLen, ret[1]); + maxVal[0] = Math.max(maxVal[0], ret[0]); + maxVal[0] = Math.max(maxVal[0], ret[1]); + + return ret; + } +} \ No newline at end of file From dabfdb726c78860b3472e8713c9c88dc94dd0acd Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 24 Sep 2014 20:39:58 -0700 Subject: [PATCH 003/319] min cut --- MinCut.java | 35 +++++++++++++ TreeDemo.java | 135 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 163 insertions(+), 7 deletions(-) create mode 100644 MinCut.java diff --git a/MinCut.java b/MinCut.java new file mode 100644 index 0000000..97c8e3c --- /dev/null +++ b/MinCut.java @@ -0,0 +1,35 @@ +package Algorithms; + +public class MinCut { + public int minCut(String s) { + if (s == null || s.length() == 0) { + return 0; + } + + int len = s.length(); + int[] D = new int[len]; + + boolean[][] isPalid = new boolean[len][len]; + + for (int i = len - 1; i >= 0; i--) { + // the worst case is divide the word one by one. + D[i] = len - 1 -i; + for (int j = i; j <= len - 1; j++) { + // init it to be false; + isPalid[i][j] = false; + + if (s.charAt(i) == s.charAt(j) && (j - i <= 1 || isPalid[i + 1][j - 1])) { + isPalid[i][j] = true; + if (j == len - 1) { + D[i] = 0; + } else { + // 如果前半部分是回文,那么我们可以分解为第一个回文 + 后半部分的最小分割数 + D[i] = Math.min(D[i], D[j + 1] + 1); + } + } + } + } + + return D[0]; + } +} diff --git a/TreeDemo.java b/TreeDemo.java index 4982693..8d50afb 100644 --- a/TreeDemo.java +++ b/TreeDemo.java @@ -1,11 +1,36 @@ package Algorithms; - import java.util.ArrayList; import java.util.LinkedList; import java.util.Queue; import java.util.Stack; +/** + * REF: http://blog.csdn.net/fightforyourdream/article/details/16843303 + * + * http://blog.csdn.net/luckyxiaoqiang/article/details/7518888 轻松搞定面试中的二叉树题目 + * http://www.cnblogs.com/Jax/archive/2009/12/28/1633691.html 算法大全(3) 二叉树 + * + * 1. 求二叉树中的节点个数: getNodeNumRec(递归),getNodeNum(迭代) + * 2. 求二叉树的深度: getDepthRec(递归),getDepth + * 3. 前序遍历,中序遍历,后序遍历: preorderTraversalRec, preorderTraversal, inorderTraversalRec, postorderTraversalRec + * (https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2) + * 4.分层遍历二叉树(按层次从上往下,从左往右): levelTraversal, levelTraversalRec(递归解法!) + * 5. 将二叉查找树变为有序的双向链表: convertBST2DLLRec, convertBST2DLL + * 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel + * + * 7. 求二叉树中叶子节点的个数:getNodeNumLeafRec, getNodeNumLeaf + * 8. 判断两棵二叉树是否相同的树:isSameRec, isSame + * 9. 判断二叉树是不是平衡二叉树:isAVLRec + * 10. 求二叉树的镜像(破坏和不破坏原来的树两种情况):mirrorRec, mirrorCopyRec + * 10.1 判断两个树是否互相镜像:isMirrorRec + * 11. 求二叉树中两个节点的最低公共祖先节点:getLastCommonParent, getLastCommonParentRec, getLastCommonParentRec2 + * 12. 求二叉树中节点的最大距离:getMaxDistanceRec + * 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec + * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec + * 15. 找出二叉树中最长连续子串(即全部往左的连续节点,或是全部往右的连续节点) + * + */ public class TreeDemo { /* @@ -28,7 +53,9 @@ public static void main(String[] args) { / \ 6 14 / \ \ - 4 8 16 + 4 8 16 + / + 0 */ TreeNode r1 = new TreeNode(10); TreeNode r2 = new TreeNode(6); @@ -47,6 +74,8 @@ public static void main(String[] args) { r4.left = r7; + System.out.println(getNodeNumKthLevelRec(r1, 5)); + // System.out.println(getNodeNumRec(null)); // System.out.println(getNodeNum(r1)); // System.out.println(getDepthRec(r1)); @@ -59,7 +88,7 @@ public static void main(String[] args) { // inorderTraversalRec(r1); // // System.out.println(); - inorderTraversal(r1); +// inorderTraversal(r1); // postorderTraversalRec(r1); // System.out.println(); // postorderTraversal(r1); @@ -91,10 +120,10 @@ public static void main(String[] args) { // ret = ret.right; // } - System.out.println(); - System.out.println(findLongest(r1)); - System.out.println(); - System.out.println(findLongest2(r1)); +// System.out.println(); +// System.out.println(findLongest(r1)); +// System.out.println(); +// System.out.println(findLongest2(r1)); } @@ -496,6 +525,98 @@ public static TreeNode convertBST2DLL(TreeNode root) { return root; } + +/* + * * 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel + * */ + public static int getNodeNumKthLevel(TreeNode root, int k) { + if (root == null || k <= 0) { + return 0; + } + + int level = 0; + + Queue q = new LinkedList(); + q.offer(root); + + TreeNode dummy = new TreeNode(0); + int cnt = 0; // record the size of the level. + + q.offer(dummy); + while (!q.isEmpty()) { + TreeNode node = q.poll(); + + if (node == dummy) { + level++; + if (level == k) { + return cnt; + } + cnt = 0; // reset the cnt; + if (q.isEmpty()) { + break; + } + q.offer(dummy); + continue; + } + + cnt++; + if (node.left != null) { + q.offer(node.left); + } + + if (node.right != null) { + q.offer(node.right); + } + } + + return 0; + } + + /* + * * 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel + * */ + public static int getNodeNumKthLevelRec(TreeNode root, int k) { + if (root == null || k <= 0) { + return 0; + } + + if (k == 1) { + return 1; + } + + // 将左子树及右子树在K层的节点个数相加. + return getNodeNumKthLevelRec(root.left, k - 1) + getNodeNumKthLevelRec(root.right, k - 1); + } + + /* + * 把左子树和右子树的叶子节点加在一起即可 + * */ + public static int getNodeNumLeafRec(TreeNode root) { + if (root == null) { + return 0; + } + + if (root.left == null && root.right == null) { + return 1; + } + + return getNodeNumLeafRec(root.left) + getNodeNumLeafRec(root.right); + } + + /* + * 把左子树和右子树的叶子节点加在一起即可 + * */ + public static int getNodeNumLeaf(TreeNode root) { + if (root == null) { + return 0; + } + + if (root.left == null && root.right == null) { + return 1; + } + + return getNodeNumLeafRec(root.left) + getNodeNumLeafRec(root.right); + } /* * 第一种解法: From 762dcade3a72bcb8d99c5dd8b1b9015ef98356d5 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 25 Sep 2014 15:26:09 -0700 Subject: [PATCH 004/319] Create README.md --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..b75b1ec --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +LeetCode_algorithm +================== + +About the Tree: +full binary tree: A binary tree in which each node has exactly zero or two children. +Perfect binary tree: A binary tree with all leaf nodes at the same depth. All internal nodes have degree 2 [1] + +The difference between Full Binary Tree & Complete Binary Tree: +(1). a binary tree T is full if each node is either a leaf or possesses exactly two child nodes. +(2). a binary tree T with n levels is complete if all levels except possibly the last are completely full, and the last level has all its +nodes to the left side. [2] + +AVL Trees: AVL trees are self-balancing binary search trees. These trees are named after their two +inventors G.M. Adel’son-Vel’skii and E.M. Landis. [3] + +The height/depth of a tree: +The height of a node is the length of the longest downward path to a leaf from that node. +The height of the root is the height of the tree. The depth of a node is the length of the path to its root (i.e., its root path). +This is commonly needed in the manipulation of the various self-balancing trees, +AVL Trees in particular. The root node has depth zero, leaf nodes have height zero, +and a tree with only a single node (hence both a root and leaf) has depth and height zero. +Conventionally, an empty tree (tree with no nodes, if such are allowed) has depth and height −1. + + +REF: +[1] http://xlinux.nist.gov/dads//HTML/perfectBinaryTree.html +[2] http://courses.cs.vt.edu/~cs3114/Fall09/wmcquain/Notes/T03a.BinaryTreeTheorems. +[3] http://courses.csail.mit.edu/6.006/fall09/lecture_notes/lecture04.pdf From ce3384ea27c30ba7de5d2bc93be4c07b098f89bf Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 25 Sep 2014 15:46:28 -0700 Subject: [PATCH 005/319] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b75b1ec..65aebd8 100644 --- a/README.md +++ b/README.md @@ -19,10 +19,11 @@ The height of the root is the height of the tree. The depth of a node is the len This is commonly needed in the manipulation of the various self-balancing trees, AVL Trees in particular. The root node has depth zero, leaf nodes have height zero, and a tree with only a single node (hence both a root and leaf) has depth and height zero. -Conventionally, an empty tree (tree with no nodes, if such are allowed) has depth and height −1. +Conventionally, an empty tree (tree with no nodes, if such are allowed) has depth and height −1.[4] REF: [1] http://xlinux.nist.gov/dads//HTML/perfectBinaryTree.html [2] http://courses.cs.vt.edu/~cs3114/Fall09/wmcquain/Notes/T03a.BinaryTreeTheorems. [3] http://courses.csail.mit.edu/6.006/fall09/lecture_notes/lecture04.pdf +[4] http://www.cs.cmu.edu/~adamchik/15-121/lectures/Trees/trees.html From 078baa78466003dfde1deff503afd639e29b9334 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 25 Sep 2014 21:08:51 -0700 Subject: [PATCH 006/319] modify the directors --- TreeDemo.java | 455 +++++++++++++++++- .../ReverseLinkedList2.java | 4 +- LCA.java => tree/LCA.java | 4 +- Level_Order.java => tree/Level_Order.java | 4 +- 4 files changed, 442 insertions(+), 25 deletions(-) rename ReverseLinkedList2.java => list/ReverseLinkedList2.java (96%) rename LCA.java => tree/LCA.java (98%) rename Level_Order.java => tree/Level_Order.java (97%) diff --git a/TreeDemo.java b/TreeDemo.java index 8d50afb..02db229 100644 --- a/TreeDemo.java +++ b/TreeDemo.java @@ -5,30 +5,32 @@ import java.util.Queue; import java.util.Stack; -/** - * REF: http://blog.csdn.net/fightforyourdream/article/details/16843303 - * - * http://blog.csdn.net/luckyxiaoqiang/article/details/7518888 轻松搞定面试中的二叉树题目 - * http://www.cnblogs.com/Jax/archive/2009/12/28/1633691.html 算法大全(3) 二叉树 +/** + * REFS: + * http://blog.csdn.net/fightforyourdream/article/details/16843303 面试大总结之二:Java搞定面试中的二叉树题目 + * http://blog.csdn.net/luckyxiaoqiang/article/details/7518888 轻松搞定面试中的二叉树题目 + * http://www.cnblogs.com/Jax/archive/2009/12/28/1633691.html 算法大全(3) 二叉树 * * 1. 求二叉树中的节点个数: getNodeNumRec(递归),getNodeNum(迭代) * 2. 求二叉树的深度: getDepthRec(递归),getDepth * 3. 前序遍历,中序遍历,后序遍历: preorderTraversalRec, preorderTraversal, inorderTraversalRec, postorderTraversalRec * (https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2) - * 4.分层遍历二叉树(按层次从上往下,从左往右): levelTraversal, levelTraversalRec(递归解法!) + * 4.分层遍历二叉树(按层次从上往下,从左往右): levelTraversal, levelTraversalRec(递归解法) * 5. 将二叉查找树变为有序的双向链表: convertBST2DLLRec, convertBST2DLL * 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel - * * 7. 求二叉树中叶子节点的个数:getNodeNumLeafRec, getNodeNumLeaf - * 8. 判断两棵二叉树是否相同的树:isSameRec, isSame + * 8. 判断两棵二叉树是否相同的树:isSameRec, isSame * 9. 判断二叉树是不是平衡二叉树:isAVLRec - * 10. 求二叉树的镜像(破坏和不破坏原来的树两种情况):mirrorRec, mirrorCopyRec - * 10.1 判断两个树是否互相镜像:isMirrorRec + * 10. 求二叉树的镜像(破坏和不破坏原来的树两种情况): + * mirrorRec, mirrorCopyRec + * mirror, mirrorCopy + * 10.1 判断两个树是否互相镜像:isMirrorRec isMirror + * * 11. 求二叉树中两个节点的最低公共祖先节点:getLastCommonParent, getLastCommonParentRec, getLastCommonParentRec2 * 12. 求二叉树中节点的最大距离:getMaxDistanceRec * 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec - * 15. 找出二叉树中最长连续子串(即全部往左的连续节点,或是全部往右的连续节点) + * 15. 找出二叉树中最长连续子串(即全部往左的连续节点,或是全部往右的连续节点)findLongest * */ @@ -70,15 +72,53 @@ public static void main(String[] args) { r1.right = r3; r2.left = r4; r2.right = r5; - r3.right = r6; + //r3.right = r6; r4.left = r7; - System.out.println(getNodeNumKthLevelRec(r1, 5)); + TreeNode t1 = new TreeNode(10); + TreeNode t2 = new TreeNode(6); + TreeNode t3 = new TreeNode(14); + TreeNode t4 = new TreeNode(4); + TreeNode t5 = new TreeNode(8); + TreeNode t6 = new TreeNode(16); + + TreeNode t7 = new TreeNode(0); + + t1.left = t2; + t1.right = t3; + t2.left = t4; + t2.right = t5; + t3.right = t6; + + t4.left = t7; + + //System.out.println(isSame(r1, t1)); + + System.out.println(isAVLRec(r1)); + + preorderTraversalRec(r1); + //mirrorRec(r1); + //TreeNode r1Mirror = mirror(r1); + + TreeNode r1MirrorCopy = mirrorCopy(r1); + System.out.println(); + //preorderTraversalRec(r1Mirror); + preorderTraversalRec(r1MirrorCopy); + + System.out.println(); + + System.out.println(isMirrorRec(r1, r1MirrorCopy)); + System.out.println(isMirror(r1, r1MirrorCopy)); + + + //System.out.println(getNodeNumKthLevelRec(r1, 5)); + + //System.out.println(getNodeNumLeaf(r1)); // System.out.println(getNodeNumRec(null)); // System.out.println(getNodeNum(r1)); -// System.out.println(getDepthRec(r1)); + //System.out.println(getDepthRec(null)); // System.out.println(getDepth(r1)); // // preorderTraversalRec(r1); @@ -125,6 +165,7 @@ public static void main(String[] args) { // System.out.println(); // System.out.println(findLongest2(r1)); + } private static class TreeNode{ @@ -180,7 +221,7 @@ public static int getNodeNum(TreeNode root) { public static int getDepthRec(TreeNode root) { if (root == null) { - return 0; + return -1; } return Math.max(getDepthRec(root.left), getDepthRec(root.right)) + 1; @@ -207,7 +248,7 @@ public static int getDepth(TreeNode root) { q.offer(root); q.offer(dummy); - int depth = 0; + int depth = -1; while (!q.isEmpty()) { TreeNode curr = q.poll(); if (curr == dummy) { @@ -589,7 +630,7 @@ public static int getNodeNumKthLevelRec(TreeNode root, int k) { } /* - * 把左子树和右子树的叶子节点加在一起即可 + * 7. getNodeNumLeafRec 把左子树和右子树的叶子节点加在一起即可 * */ public static int getNodeNumLeafRec(TreeNode root) { if (root == null) { @@ -603,22 +644,392 @@ public static int getNodeNumLeafRec(TreeNode root) { return getNodeNumLeafRec(root.left) + getNodeNumLeafRec(root.right); } - /* - * 把左子树和右子树的叶子节点加在一起即可 + /* 7. getNodeNumLeaf + * 随便使用一种遍历方法都可以,比如,中序遍历。 + * inorderTraversal,判断是不是叶子节点。 * */ public static int getNodeNumLeaf(TreeNode root) { if (root == null) { return 0; } - if (root.left == null && root.right == null) { - return 1; + int cnt = 0; + + // we can use inorderTraversal travesal to do it. + Stack s = new Stack(); + TreeNode cur = root; + + while (true) { + while (cur != null) { + s.push(cur); + cur = cur.left; + } + + if (s.isEmpty()) { + break; + } + + // all the left child has been put into the stack, let's deal with the + // current node. + cur = s.pop(); + if (cur.left == null && cur.right == null) { + cnt++; + } + cur = cur.right; } - return getNodeNumLeafRec(root.left) + getNodeNumLeafRec(root.right); + return cnt; + } + + /* + * 8. 判断两棵二叉树是否相同的树。 + * 递归解法: + * (1)如果两棵二叉树都为空,返回真 + * (2)如果两棵二叉树一棵为空,另一棵不为空,返回假 + * (3)如果两棵二叉树都不为空,如果对应的左子树和右子树都同构返回真,其他返回假 + * */ + public static boolean isSameRec(TreeNode r1, TreeNode r2) { + // both are null. + if (r1 == null && r2 == null) { + return true; + } + + // one is null. + if (r1 == null || r2 == null) { + return false; + } + + // 1. the value of the root should be the same; + // 2. the left tree should be the same. + // 3. the right tree should be the same. + return r1.val == r2.val && + isSameRec(r1.left, r2.left) && isSameRec(r1.right, r2.right); + } + + /* + * 8. 判断两棵二叉树是否相同的树。 + * 迭代解法 + * 我们直接用中序遍历来比较就好啦 + * */ + public static boolean isSame(TreeNode r1, TreeNode r2) { + // both are null. + if (r1 == null && r2 == null) { + return true; + } + + // one is null. + if (r1 == null || r2 == null) { + return false; + } + + Stack s1 = new Stack(); + Stack s2 = new Stack(); + + TreeNode cur1 = r1; + TreeNode cur2 = r2; + + while (true) { + while (cur1 != null && cur2 != null) { + s1.push(cur1); + s2.push(cur2); + cur1 = cur1.left; + cur2 = cur2.left; + } + + if (cur1 != null || cur2 != null) { + return false; + } + + if (s1.isEmpty() && s2.isEmpty()) { + break; + } + + cur1 = s1.pop(); + cur2 = s2.pop(); + if (cur1.val != cur2.val) { + return false; + } + + cur1 = cur1.right; + cur2 = cur2.right; + } + + return true; + } + +/* + * + * 9. 判断二叉树是不是平衡二叉树:isAVLRec + * 1. 左子树,右子树的高度差不能超过1 + * 2. 左子树,右子树都是平衡二叉树。 + * + */ + public static boolean isAVLRec(TreeNode root) { + if (root == null) { + return true; + } + + // 左子树,右子树都必须是平衡二叉树。 + if (!isAVLRec(root.left) || !isAVLRec(root.right)) { + return false; + } + + int dif = Math.abs(getDepthRec(root.left) - getDepthRec(root.right)); + if (dif > 1) { + return false; + } + + return true; + } + + /** + * 10. 求二叉树的镜像 递归解法: + * + * (1) 破坏原来的树 + * + * 1 1 + * / \ + * 2 -----> 2 + * \ / + * 3 3 + * */ + public static TreeNode mirrorRec(TreeNode root) { + if (root == null) { + return null; + } + + // 先把左右子树分别镜像,并且交换它们 + TreeNode tmp = root.right; + root.right = mirrorRec(root.left); + root.left = mirrorRec(tmp); + + return root; + } + + /** + * 10. 求二叉树的镜像 Iterator解法: + * + * (1) 破坏原来的树 + * + * 1 1 + * / \ + * 2 -----> 2 + * \ / + * 3 3 + * + * 应该可以使用任何一种Traversal 方法。 + * 我们现在可以试看看使用最简单的前序遍历。 + * */ + public static TreeNode mirror(TreeNode root) { + if (root == null) { + return null; + } + + Stack s = new Stack(); + s.push(root); + + while (!s.isEmpty()) { + TreeNode cur = s.pop(); + + // 交换当前节点的左右节点 + TreeNode tmp = cur.left; + cur.left = cur.right; + cur.right = tmp; + + // traversal 左节点,右节点。 + if (cur.right != null) { + s.push(cur.right); + } + + if (cur.left != null) { + s.push(cur.left); + } + } + + return root; + } + + /** + * 10. 求二叉树的镜像 Iterator解法: + * + * (2) 创建一个新的树 + * + * 1 1 + * / \ + * 2 -----> 2 + * \ / + * 3 3 + * + * 应该可以使用任何一种Traversal 方法。 + * 我们现在可以试看看使用最简单的前序遍历。 + * 前序遍历我们可以立刻把新建好的左右节点创建出来,比较方便 + * */ + public static TreeNode mirrorCopy(TreeNode root) { + if (root == null) { + return null; + } + + Stack s = new Stack(); + Stack sCopy = new Stack(); + s.push(root); + + TreeNode rootCopy = new TreeNode(root.val); + sCopy.push(rootCopy); + + while (!s.isEmpty()) { + TreeNode cur = s.pop(); + TreeNode curCopy = sCopy.pop(); + + // traversal 左节点,右节点。 + if (cur.right != null) { + + // copy 在这里做比较好,因为我们可以容易地找到它的父节点 + TreeNode leftCopy = new TreeNode(cur.right.val); + curCopy.left = leftCopy; + s.push(cur.right); + sCopy.push(curCopy.left); + } + + if (cur.left != null) { + // copy 在这里做比较好,因为我们可以容易地找到它的父节点 + TreeNode rightCopy = new TreeNode(cur.left.val); + curCopy.right = rightCopy; + s.push(cur.left); + sCopy.push(curCopy.right); + } + } + + return rootCopy; + } + + /** + * 10. 求二叉树的镜像 递归解法: + * + * (1) 不破坏原来的树,新建一个树 + * + * 1 1 + * / \ + * 2 -----> 2 + * \ / + * 3 3 + * */ + public static TreeNode mirrorCopyRec(TreeNode root) { + if (root == null) { + return null; + } + + // 先把左右子树分别镜像,并且把它们连接到新建的root节点。 + TreeNode rootCopy = new TreeNode(root.val); + rootCopy.left = mirrorCopyRec(root.right); + rootCopy.right = mirrorCopyRec(root.left); + + return rootCopy; + } + + /* + * 10.1. 判断两个树是否互相镜像 + * (1) 根必须同时为空,或是同时不为空 + * + * 如果根不为空: + * (1).根的值一样 + * (2).r1的左树是r2的右树的镜像 + * (3).r1的右树是r2的左树的镜像 + * */ + public static boolean isMirrorRec(TreeNode r1, TreeNode r2){ + // 如果2个树都是空树 + if (r1 == null && r2 == null) { + return true; + } + + // 如果其中一个为空,则返回false. + if (r1 == null || r2 == null) { + return false; + } + + // If both are not null, they should be: + // 1. have same value for root. + // 2. R1's left tree is the mirror of R2's right tree; + // 3. R2's right tree is the mirror of R1's left tree; + return r1.val == r2.val + && isMirrorRec(r1.left, r2.right) + && isMirrorRec(r1.right, r2.left); } /* + * 10.1. 判断两个树是否互相镜像 Iterator 做法 + * (1) 根必须同时为空,或是同时不为空 + * + * 如果根不为空: + * traversal 整个树,判断它们是不是镜像,每次都按照反向来traversal + * (1). 当前节点的值相等 + * (2). 当前节点的左右节点要镜像, + * 无论是左节点,还是右节点,对应另外一棵树的镜像位置,可以同时为空,或是同时不为空,但是不可以一个为空,一个不为空。 + * */ + public static boolean isMirror(TreeNode r1, TreeNode r2){ + // 如果2个树都是空树 + if (r1 == null && r2 == null) { + return true; + } + + // 如果其中一个为空,则返回false. + if (r1 == null || r2 == null) { + return false; + } + + Stack s1 = new Stack(); + Stack s2 = new Stack(); + + s1.push(r1); + s2.push(r2); + + while (!s1.isEmpty() && !s2.isEmpty()) { + TreeNode cur1 = s1.pop(); + TreeNode cur2 = s2.pop(); + + // 弹出的节点的值必须相等 + if (cur1.val != cur2.val) { + return false; + } + + // tree1的左节点,tree2的右节点,可以同时不为空,也可以同时为空,否则返回false. + TreeNode left1 = cur1.left; + TreeNode right1 = cur1.right; + TreeNode left2 = cur2.left; + TreeNode right2 = cur2.right; + + if (left1 != null && right2 != null) { + s1.push(left1); + s2.push(right2); + } else if (!(left1 == null && right2 == null)) { + return false; + } + + // tree1的左节点,tree2的右节点,可以同时不为空,也可以同时为空,否则返回false. + if (right1 != null && left2 != null) { + s1.push(right1); + s2.push(left2); + } else if (!(right1 == null && left2 == null)) { + return false; + } + } + + return true; + } + + /* + * 11. 求二叉树中两个节点的最低公共祖先节点: + * getLastCommonParent, + * getLastCommonParentRec, + * getLastCommonParentRec2 + * */ + public static TreeNode getLastCommonParentRec(TreeNode root, TreeNode node1, TreeNode node2) { + + + return root; + } + + /* + * 15. findLongest * 第一种解法: * 返回左边最长,右边最长,及左子树最长,右子树最长。 * */ diff --git a/ReverseLinkedList2.java b/list/ReverseLinkedList2.java similarity index 96% rename from ReverseLinkedList2.java rename to list/ReverseLinkedList2.java index 8246c8b..1441333 100644 --- a/ReverseLinkedList2.java +++ b/list/ReverseLinkedList2.java @@ -1,4 +1,6 @@ -package Algorithms; +package Algorithms.list; + +import Algorithms.ListNode; public class ReverseLinkedList2 { public static void main(String[] args) { diff --git a/LCA.java b/tree/LCA.java similarity index 98% rename from LCA.java rename to tree/LCA.java index 199a7eb..3efdc52 100644 --- a/LCA.java +++ b/tree/LCA.java @@ -1,4 +1,6 @@ -package Algorithms; +package Algorithms.tree; + +import Algorithms.TreeNode; /** diff --git a/Level_Order.java b/tree/Level_Order.java similarity index 97% rename from Level_Order.java rename to tree/Level_Order.java index 1ea79b4..04956bf 100644 --- a/Level_Order.java +++ b/tree/Level_Order.java @@ -1,8 +1,10 @@ -package Algorithms; +package Algorithms.tree; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Queue; +import Algorithms.TreeNode; + public class Level_Order { From ab453fcdbfba11cfdb53c7cc65b299ec9b72150a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 26 Sep 2014 00:53:09 -0700 Subject: [PATCH 007/319] move the folder. --- ThreeSum.java => array/ThreeSum.java | 2 +- ThreeSumN2.java => array/ThreeSumN2.java | 2 +- TwoSum.java => array/TwoSum.java | 2 +- NQueens2.java => dp/NQueens2.java | 2 +- MinCut.java => string/MinCut.java | 2 +- tree/LCA.java | 1 - PostOrder.java => tree/PostOrder.java | 4 +++- 7 files changed, 8 insertions(+), 7 deletions(-) rename ThreeSum.java => array/ThreeSum.java (99%) rename ThreeSumN2.java => array/ThreeSumN2.java (99%) rename TwoSum.java => array/TwoSum.java (95%) rename NQueens2.java => dp/NQueens2.java (98%) rename MinCut.java => string/MinCut.java (97%) rename PostOrder.java => tree/PostOrder.java (97%) diff --git a/ThreeSum.java b/array/ThreeSum.java similarity index 99% rename from ThreeSum.java rename to array/ThreeSum.java index ac4fa2c..d83ed9c 100644 --- a/ThreeSum.java +++ b/array/ThreeSum.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.array; import java.util.ArrayList; import java.util.Arrays; diff --git a/ThreeSumN2.java b/array/ThreeSumN2.java similarity index 99% rename from ThreeSumN2.java rename to array/ThreeSumN2.java index 82c3140..7ecf08e 100644 --- a/ThreeSumN2.java +++ b/array/ThreeSumN2.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.array; import java.util.ArrayList; import java.util.Arrays; diff --git a/TwoSum.java b/array/TwoSum.java similarity index 95% rename from TwoSum.java rename to array/TwoSum.java index 0b5b043..f4afa17 100644 --- a/TwoSum.java +++ b/array/TwoSum.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.array; import java.util.HashMap; diff --git a/NQueens2.java b/dp/NQueens2.java similarity index 98% rename from NQueens2.java rename to dp/NQueens2.java index cb72b58..da4d6d6 100644 --- a/NQueens2.java +++ b/dp/NQueens2.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.dp; import java.util.ArrayList; diff --git a/MinCut.java b/string/MinCut.java similarity index 97% rename from MinCut.java rename to string/MinCut.java index 97c8e3c..3a0910b 100644 --- a/MinCut.java +++ b/string/MinCut.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.string; public class MinCut { public int minCut(String s) { diff --git a/tree/LCA.java b/tree/LCA.java index 3efdc52..ae3d4b0 100644 --- a/tree/LCA.java +++ b/tree/LCA.java @@ -89,7 +89,6 @@ public static void main(String[] strs) { System.out.println(cnt); } - public TreeNode getLCA(TreeNode root, TreeNode node1, TreeNode node2) { cnt++; if (root == null || node1 == root || root == node2) { diff --git a/PostOrder.java b/tree/PostOrder.java similarity index 97% rename from PostOrder.java rename to tree/PostOrder.java index 22ccb70..572956b 100644 --- a/PostOrder.java +++ b/tree/PostOrder.java @@ -1,8 +1,10 @@ -package Algorithms; +package Algorithms.tree; import java.util.ArrayList; import java.util.LinkedList; import java.util.Stack; +import Algorithms.TreeNode; + public class PostOrder { /** From af5edeb6b963360460b97a5297d943b585f049cf Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 26 Sep 2014 01:32:58 -0700 Subject: [PATCH 008/319] modify the tree Demo --- TreeDemo.java | 132 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 100 insertions(+), 32 deletions(-) diff --git a/TreeDemo.java b/TreeDemo.java index 02db229..4726d98 100644 --- a/TreeDemo.java +++ b/TreeDemo.java @@ -43,12 +43,12 @@ public class TreeDemo { 4 5 6 */ public static void main(String[] args) { -// TreeNode r1 = new TreeNode(1); -// TreeNode r2 = new TreeNode(2); -// TreeNode r3 = new TreeNode(3); -// TreeNode r4 = new TreeNode(4); -// TreeNode r5 = new TreeNode(5); -// TreeNode r6 = new TreeNode(6); + TreeNode r1 = new TreeNode(1); + TreeNode r2 = new TreeNode(2); + TreeNode r3 = new TreeNode(3); + TreeNode r4 = new TreeNode(4); + TreeNode r5 = new TreeNode(5); + TreeNode r6 = new TreeNode(6); /* 10 @@ -59,12 +59,12 @@ public static void main(String[] args) { / 0 */ - TreeNode r1 = new TreeNode(10); - TreeNode r2 = new TreeNode(6); - TreeNode r3 = new TreeNode(14); - TreeNode r4 = new TreeNode(4); - TreeNode r5 = new TreeNode(8); - TreeNode r6 = new TreeNode(16); +// TreeNode r1 = new TreeNode(10); +// TreeNode r2 = new TreeNode(6); +// TreeNode r3 = new TreeNode(14); +// TreeNode r4 = new TreeNode(4); +// TreeNode r5 = new TreeNode(8); +// TreeNode r6 = new TreeNode(16); TreeNode r7 = new TreeNode(0); @@ -72,9 +72,21 @@ public static void main(String[] args) { r1.right = r3; r2.left = r4; r2.right = r5; - //r3.right = r6; + r3.right = r6; r4.left = r7; + /* + 1 + / \ + 2 3 + / \ \ + 4 5 6 +*/ + System.out.println(LACRec(r1, r2, r4).val); + System.out.println(LACRec(r1, r2, r6).val); + System.out.println(LACRec(r1, r4, r6).val); + System.out.println(LACRec(r1, r4, r4).val); + System.out.println(LACRec(r1, r3, r6).val); TreeNode t1 = new TreeNode(10); TreeNode t2 = new TreeNode(6); @@ -95,21 +107,21 @@ public static void main(String[] args) { //System.out.println(isSame(r1, t1)); - System.out.println(isAVLRec(r1)); - - preorderTraversalRec(r1); - //mirrorRec(r1); - //TreeNode r1Mirror = mirror(r1); - - TreeNode r1MirrorCopy = mirrorCopy(r1); - System.out.println(); - //preorderTraversalRec(r1Mirror); - preorderTraversalRec(r1MirrorCopy); - - System.out.println(); - - System.out.println(isMirrorRec(r1, r1MirrorCopy)); - System.out.println(isMirror(r1, r1MirrorCopy)); +// System.out.println(isAVLRec(r1)); +// +// preorderTraversalRec(r1); +// //mirrorRec(r1); +// //TreeNode r1Mirror = mirror(r1); +// +// TreeNode r1MirrorCopy = mirrorCopy(r1); +// System.out.println(); +// //preorderTraversalRec(r1Mirror); +// preorderTraversalRec(r1MirrorCopy); +// +// System.out.println(); +// +// System.out.println(isMirrorRec(r1, r1MirrorCopy)); +// System.out.println(isMirror(r1, r1MirrorCopy)); //System.out.println(getNodeNumKthLevelRec(r1, 5)); @@ -1018,13 +1030,69 @@ public static boolean isMirror(TreeNode r1, TreeNode r2){ /* * 11. 求二叉树中两个节点的最低公共祖先节点: - * getLastCommonParent, - * getLastCommonParentRec, - * getLastCommonParentRec2 + * Recursion Version: + * LACRec + * 1. If found in the left tree, return the Ancestor. + * 2. If found in the right tree, return the Ancestor. + * 3. If Didn't find any of the node, return null. + * 4. If found both in the left and the right tree, return the root. + * */ + public static TreeNode LACRec(TreeNode root, TreeNode node1, TreeNode node2) { + if (root == null || node1 == null || node2 == null) { + return null; + } + + // If any of the node is the root, just return the root. + if (root == node1 || root == node2) { + return root; + } + + // if no node is in the node, just recursively find it in LEFT and RIGHT tree. + TreeNode left = LACRec(root.left, node1, node2); + TreeNode right = LACRec(root.right, node1, node2); + + if (left == null) { // If didn't found in the left tree, then just return it from right. + return right; + } else if (right == null) { // Or if didn't found in the right tree, then just return it from the left side. + return left; + } + + // if both right and right found a node, just return the root as the Common Ancestor. + return root; + } + + /* + * 11. 求BST中两个节点的最低公共祖先节点: + * Recursive version: + * LCABst + * + * 1. If found in the left tree, return the Ancestor. + * 2. If found in the right tree, return the Ancestor. + * 3. If Didn't find any of the node, return null. + * 4. If found both in the left and the right tree, return the root. * */ - public static TreeNode getLastCommonParentRec(TreeNode root, TreeNode node1, TreeNode node2) { + public static TreeNode LCABstRec(TreeNode root, TreeNode node1, TreeNode node2) { + if (root == null || node1 == null || node2 == null) { + return null; + } + // If any of the node is the root, just return the root. + if (root == node1 || root == node2) { + return root; + } + + int min = Math.min(node1.val, node2.val); + int max = Math.max(node1.val, node2.val); + + // if the values are smaller than the root value, just search them in the left tree. + if (root.val > max) { + return LCABstRec(root.left, node1, node2); + } else if (root.val < min) { + // if the values are larger than the root value, just search them in the right tree. + return LCABstRec(root.right, node1, node2); + } + // if root is in the middle, just return the root. return root; } From 52407ba8ae344733fff285139f7c361f0c93a195 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 26 Sep 2014 04:00:34 -0700 Subject: [PATCH 009/319] The LCA problem. --- TreeDemo.java | 121 +++++++++++++++++++++++++++----- tree/LCA_Demo.java | 167 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 272 insertions(+), 16 deletions(-) create mode 100644 tree/LCA_Demo.java diff --git a/TreeDemo.java b/TreeDemo.java index 4726d98..96f7789 100644 --- a/TreeDemo.java +++ b/TreeDemo.java @@ -1,10 +1,12 @@ package Algorithms; import java.util.ArrayList; +import java.util.Iterator; import java.util.LinkedList; import java.util.Queue; import java.util.Stack; + /** * REFS: * http://blog.csdn.net/fightforyourdream/article/details/16843303 面试大总结之二:Java搞定面试中的二叉树题目 @@ -25,8 +27,11 @@ * mirrorRec, mirrorCopyRec * mirror, mirrorCopy * 10.1 判断两个树是否互相镜像:isMirrorRec isMirror - * - * 11. 求二叉树中两个节点的最低公共祖先节点:getLastCommonParent, getLastCommonParentRec, getLastCommonParentRec2 + * 11. 求二叉树中两个节点的最低公共祖先节点: + * LAC 求解最小公共祖先, 使用list来存储path. + * LCABstRec 递归求解BST树. + * LCARec 递归算法 . + * * 12. 求二叉树中节点的最大距离:getMaxDistanceRec * 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec @@ -50,7 +55,7 @@ public static void main(String[] args) { TreeNode r5 = new TreeNode(5); TreeNode r6 = new TreeNode(6); -/* +/* 10 / \ 6 14 @@ -59,6 +64,13 @@ public static void main(String[] args) { / 0 */ + /* + 1 + / \ + 2 3 + / \ \ + 4 5 6 +*/ // TreeNode r1 = new TreeNode(10); // TreeNode r2 = new TreeNode(6); // TreeNode r3 = new TreeNode(14); @@ -75,19 +87,7 @@ public static void main(String[] args) { r3.right = r6; r4.left = r7; - /* - 1 - / \ - 2 3 - / \ \ - 4 5 6 -*/ - System.out.println(LACRec(r1, r2, r4).val); - System.out.println(LACRec(r1, r2, r6).val); - System.out.println(LACRec(r1, r4, r6).val); - System.out.println(LACRec(r1, r4, r4).val); - System.out.println(LACRec(r1, r3, r6).val); - + TreeNode t1 = new TreeNode(10); TreeNode t2 = new TreeNode(6); TreeNode t3 = new TreeNode(14); @@ -105,6 +105,28 @@ public static void main(String[] args) { t4.left = t7; + /* + 10 + / \ + 6 14 + / \ \ + 4 8 16 + / + 0 + */ + System.out.println(LCABstRec(t1, t2, t4).val); + System.out.println(LCABstRec(t1, t2, t6).val); + System.out.println(LCABstRec(t1, t4, t6).val); + System.out.println(LCABstRec(t1, t4, t7).val); + System.out.println(LCABstRec(t1, t3, t6).val); + + System.out.println(LCA(t1, t2, t4).val); + System.out.println(LCA(t1, t2, t6).val); + System.out.println(LCA(t1, t4, t6).val); + System.out.println(LCA(t1, t4, t7).val); + System.out.println(LCA(t1, t3, t6).val); + System.out.println(LCA(t1, t6, t6).val); + //System.out.println(isSame(r1, t1)); // System.out.println(isAVLRec(r1)); @@ -1095,6 +1117,73 @@ public static TreeNode LCABstRec(TreeNode root, TreeNode node1, TreeNode node2) // if root is in the middle, just return the root. return root; } + + /* + * 解法1. 记录下path,并且比较之: + * LAC + * http://www.geeksforgeeks.org/lowest-common-ancestor-binary-tree-set-1/ + * */ + public static TreeNode LCA(TreeNode root, TreeNode r1, TreeNode r2) { + // If the nodes have one in the root, just return the root. + if (root == null || r1 == null || r2 == null) { + return null; + } + + ArrayList list1 = new ArrayList(); + ArrayList list2 = new ArrayList(); + + boolean find1 = LCAPath(root, r1, list1); + boolean find2 = LCAPath(root, r2, list2); + + // If didn't find any of the node, just return a null. + if (!find1 || !find2) { + return null; + } + + // 注意: 使用Iterator 对于linkedlist可以提高性能。 + // 所以 统一使用Iterator 来进行操作。 + Iterator iter1 = list1.iterator(); + Iterator iter2 = list2.iterator(); + + TreeNode last = null; + while (iter1.hasNext() && iter2.hasNext()) { + TreeNode tmp1 = iter1.next(); + TreeNode tmp2 = iter2.next(); + + if (tmp1 != tmp2) { + return last; + } + + last = tmp1; + } + + // If never find any node which is different, means Node 1 and Node 2 are the same one. + // so just return the last one. + return last; + } + + public static boolean LCAPath(TreeNode root, TreeNode node, ArrayList path) { + // if didn't find, we should return a empty path. + if (root == null || node == null) { + return false; + } + + // First add the root node. + path.add(root); + + // if the node is in the left side. + if (root != node + && !LCAPath(root.left, node, path) + && !LCAPath(root.right, node, path) + ) { + // Didn't find the node. should remove the node added before. + path.remove(root); + return false; + } + + // found + return true; + } /* * 15. findLongest diff --git a/tree/LCA_Demo.java b/tree/LCA_Demo.java new file mode 100644 index 0000000..e088e0c --- /dev/null +++ b/tree/LCA_Demo.java @@ -0,0 +1,167 @@ +package Algorithms.tree; + + +import java.util.ArrayList; +import java.util.Iterator; + +/** + * REFS: + * http://blog.csdn.net/fightforyourdream/article/details/16843303 面试大总结之二:Java搞定面试中的二叉树题目 + * http://blog.csdn.net/luckyxiaoqiang/article/details/7518888 轻松搞定面试中的二叉树题目 + * http://www.cnblogs.com/Jax/archive/2009/12/28/1633691.html 算法大全(3) 二叉树 + + * 1. 求二叉树中两个节点的最低公共祖先节点: + * LAC 求解最小公共祖先, 使用list来存储path. + * 算法复杂度是:O(n), 这里遍历2次,加一次对最高为H的list的遍历. 并且有O(h)的空间复杂度。 + * LCABstRec 递归求解BST树. + * 算法复杂度: O(logN). + * LCARec 递归算法 . + * 算法复杂度是:O(n) + */ + +public class LCA_Demo { + private static class TreeNode{ + int val; + TreeNode left; + TreeNode right; + public TreeNode(int val){ + this.val = val; + left = null; + right = null; + } + } + /* + * 1. 求二叉树中两个节点的最低公共祖先节点: + * Recursion Version: + * LACRec + * 1. If found in the left tree, return the Ancestor. + * 2. If found in the right tree, return the Ancestor. + * 3. If Didn't find any of the node, return null. + * 4. If found both in the left and the right tree, return the root. + * */ + public static TreeNode LACRec(TreeNode root, TreeNode node1, TreeNode node2) { + if (root == null || node1 == null || node2 == null) { + return null; + } + + // If any of the node is the root, just return the root. + if (root == node1 || root == node2) { + return root; + } + + // if no node is in the node, just recursively find it in LEFT and RIGHT tree. + TreeNode left = LACRec(root.left, node1, node2); + TreeNode right = LACRec(root.right, node1, node2); + + if (left == null) { // If didn't found in the left tree, then just return it from right. + return right; + } else if (right == null) { // Or if didn't found in the right tree, then just return it from the left side. + return left; + } + + // if both right and right found a node, just return the root as the Common Ancestor. + return root; + } + + /* + * 11. 求BST中两个节点的最低公共祖先节点: + * Recursive version: + * LCABst + * + * 1. If found in the left tree, return the Ancestor. + * 2. If found in the right tree, return the Ancestor. + * 3. If Didn't find any of the node, return null. + * 4. If found both in the left and the right tree, return the root. + * */ + public static TreeNode LCABstRec(TreeNode root, TreeNode node1, TreeNode node2) { + if (root == null || node1 == null || node2 == null) { + return null; + } + + // If any of the node is the root, just return the root. + if (root == node1 || root == node2) { + return root; + } + + int min = Math.min(node1.val, node2.val); + int max = Math.max(node1.val, node2.val); + + // if the values are smaller than the root value, just search them in the left tree. + if (root.val > max) { + return LCABstRec(root.left, node1, node2); + } else if (root.val < min) { + // if the values are larger than the root value, just search them in the right tree. + return LCABstRec(root.right, node1, node2); + } + + // if root is in the middle, just return the root. + return root; + } + + /* + * 解法1. 记录下path,并且比较之: + * LAC + * http://www.geeksforgeeks.org/lowest-common-ancestor-binary-tree-set-1/ + * */ + public static TreeNode LCA(TreeNode root, TreeNode r1, TreeNode r2) { + // If the nodes have one in the root, just return the root. + if (root == null || r1 == null || r2 == null) { + return null; + } + + ArrayList list1 = new ArrayList(); + ArrayList list2 = new ArrayList(); + + boolean find1 = LCAPath(root, r1, list1); + boolean find2 = LCAPath(root, r2, list2); + + // If didn't find any of the node, just return a null. + if (!find1 || !find2) { + return null; + } + + // 注意: 使用Iterator 对于linkedlist可以提高性能。 + // 所以 统一使用Iterator 来进行操作。 + Iterator iter1 = list1.iterator(); + Iterator iter2 = list2.iterator(); + + TreeNode last = null; + while (iter1.hasNext() && iter2.hasNext()) { + TreeNode tmp1 = iter1.next(); + TreeNode tmp2 = iter2.next(); + + if (tmp1 != tmp2) { + return last; + } + + last = tmp1; + } + + // If never find any node which is different, means Node 1 and Node 2 are the same one. + // so just return the last one. + return last; + } + + public static boolean LCAPath(TreeNode root, TreeNode node, ArrayList path) { + // if didn't find, we should return a empty path. + if (root == null || node == null) { + return false; + } + + // First add the root node. + path.add(root); + + // if the node is in the left side. + if (root != node + && !LCAPath(root.left, node, path) + && !LCAPath(root.right, node, path) + ) { + // Didn't find the node. should remove the node added before. + path.remove(root); + return false; + } + + // found + return true; + } +} \ No newline at end of file From 7c9819f71d7d77198f8261f5c9b076632420eef8 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 26 Sep 2014 04:04:16 -0700 Subject: [PATCH 010/319] add some comments. --- tree/LCA_Demo.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tree/LCA_Demo.java b/tree/LCA_Demo.java index e088e0c..cb802e8 100644 --- a/tree/LCA_Demo.java +++ b/tree/LCA_Demo.java @@ -7,16 +7,16 @@ /** * REFS: * http://blog.csdn.net/fightforyourdream/article/details/16843303 面试大总结之二:Java搞定面试中的二叉树题目 - * http://blog.csdn.net/luckyxiaoqiang/article/details/7518888 轻松搞定面试中的二叉树题目 - * http://www.cnblogs.com/Jax/archive/2009/12/28/1633691.html 算法大全(3) 二叉树 + * http://blog.csdn.net/luckyxiaoqiang/article/details/7518888 轻松搞定面试中的二叉树题目 + * http://www.cnblogs.com/Jax/archive/2009/12/28/1633691.html 算法大全(3) 二叉树 * 1. 求二叉树中两个节点的最低公共祖先节点: - * LAC 求解最小公共祖先, 使用list来存储path. + * (1) LAC 求解最小公共祖先, 使用list来存储path. * 算法复杂度是:O(n), 这里遍历2次,加一次对最高为H的list的遍历. 并且有O(h)的空间复杂度。 - * LCABstRec 递归求解BST树. - * 算法复杂度: O(logN). - * LCARec 递归算法 . + * (2) LCARec 递归算法 . * 算法复杂度是:O(n) + * (3) LCABstRec 递归求解BST树. + * 算法复杂度: O(logN). */ public class LCA_Demo { From bb3eb2b16829659e4b49bbd17b4f0cc6b82a4691 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 27 Sep 2014 13:21:31 -0700 Subject: [PATCH 011/319] Arrange the code. --- Flatten.java | 2 + InOrderTraversal.java | 2 + IsSymmetric.java | 2 + Max_path_BinaryTree.java | 2 + Populate2.java | 3 + Recover.java | 2 + ZigzagLevelOrder.java | 2 + {string => dp}/MinCut.java | 2 +- sort/QuickSort.java | 149 ++++++++++++++++++++ tree/LCA.java | 1 - tree/Level_Order.java | 2 - tree/PostOrder.java | 93 ------------ TreeDemo.java => tree/TreeDemo.java | 5 +- TreeLinkNode.java => tree/TreeLinkNode.java | 2 +- TreeNode.java => tree/TreeNode.java | 2 +- 15 files changed, 170 insertions(+), 101 deletions(-) rename {string => dp}/MinCut.java (97%) create mode 100644 sort/QuickSort.java delete mode 100644 tree/PostOrder.java rename TreeDemo.java => tree/TreeDemo.java (99%) rename TreeLinkNode.java => tree/TreeLinkNode.java (82%) rename TreeNode.java => tree/TreeNode.java (90%) diff --git a/Flatten.java b/Flatten.java index 06fc2d4..4f4bcf4 100644 --- a/Flatten.java +++ b/Flatten.java @@ -1,6 +1,8 @@ package Algorithms; import java.util.Stack; +import Algorithms.tree.TreeNode; + public class Flatten { diff --git a/InOrderTraversal.java b/InOrderTraversal.java index b365588..6de42e4 100644 --- a/InOrderTraversal.java +++ b/InOrderTraversal.java @@ -2,6 +2,8 @@ import java.util.ArrayList; import java.util.Stack; +import Algorithms.tree.TreeNode; + public class InOrderTraversal { public ArrayList inorderTraversal(TreeNode root) { diff --git a/IsSymmetric.java b/IsSymmetric.java index eb8509f..eee9d5a 100644 --- a/IsSymmetric.java +++ b/IsSymmetric.java @@ -2,6 +2,8 @@ import java.util.ArrayDeque; +import Algorithms.tree.TreeNode; + public class IsSymmetric { public boolean isSymmetric(TreeNode root) { if (root == null) { diff --git a/Max_path_BinaryTree.java b/Max_path_BinaryTree.java index de91cc8..9422213 100644 --- a/Max_path_BinaryTree.java +++ b/Max_path_BinaryTree.java @@ -1,6 +1,8 @@ package Algorithms; import java.util.ArrayList; +import Algorithms.tree.TreeNode; + public class Max_path_BinaryTree { public static void main(String args[]){ diff --git a/Populate2.java b/Populate2.java index de55770..8cf79a9 100644 --- a/Populate2.java +++ b/Populate2.java @@ -1,4 +1,7 @@ package Algorithms; + +import Algorithms.tree.TreeLinkNode; + public class Populate2 { public static void main(String[] args) { TreeLinkNode root = new TreeLinkNode(2); diff --git a/Recover.java b/Recover.java index c185ce5..989ff5a 100644 --- a/Recover.java +++ b/Recover.java @@ -1,5 +1,7 @@ package Algorithms; +import Algorithms.tree.TreeNode; + public class Recover { private TreeNode big = null; private TreeNode small = null; diff --git a/ZigzagLevelOrder.java b/ZigzagLevelOrder.java index 3eca3df..07686f8 100644 --- a/ZigzagLevelOrder.java +++ b/ZigzagLevelOrder.java @@ -4,6 +4,8 @@ import java.util.Queue; import java.util.Stack; +import Algorithms.tree.TreeNode; + public class ZigzagLevelOrder { public ArrayList> zigzagLevelOrder(TreeNode root) { diff --git a/string/MinCut.java b/dp/MinCut.java similarity index 97% rename from string/MinCut.java rename to dp/MinCut.java index 3a0910b..9aaa616 100644 --- a/string/MinCut.java +++ b/dp/MinCut.java @@ -1,4 +1,4 @@ -package Algorithms.string; +package Algorithms.dp; public class MinCut { public int minCut(String s) { diff --git a/sort/QuickSort.java b/sort/QuickSort.java new file mode 100644 index 0000000..7090a41 --- /dev/null +++ b/sort/QuickSort.java @@ -0,0 +1,149 @@ +package Algorithms.sort; + +/********************************************************* + * + * 08-722 Data Structures for Application Programmers + * Lab 5 Comparing MergeSort with QuickSort + * + * A simple QuickSort implementation + * + *********************************************************/ + +import java.util.*; + +public class QuickSort { + //private static final int SIZE = 100000; + private static final int SIZE = 100000; + private static Random rand = new Random(); + + public static void main(String args[]) { + int[] array = new int[SIZE]; + + for (int i = 0; i < SIZE; i++) + array[i] = rand.nextInt(); + + // reversely ordered + /* + for(int i=0;i= right) { + return; + } + + // we just set the right node to be pivot. + int pivPosition = partition(arr, left, right, arr[right]); + + recQuickSort(arr, left, pivPosition - 1); + recQuickSort(arr, pivPosition + 1, right); + } + + // partition the array and return the new pivot position. + private static int partition(int[] arr, int left, int right, int pivot) { + int len = arr.length; + + // set the pivot. + int l = left ; + int r = right - 1; + + /* + example: + let 4 to be the pivot. + + (1) At the beginning: + 2 8 7 1 3 5 6 4 + i j + + + (2) After the first while loop: + 2 8 7 1 3 5 6 4 + i j + + (3) swap them, then continue to move i and j: + 2 3 7 1 8 5 6 4 + i j + + (3) swap them, then continue to move i and j: + 2 3 1 7 8 5 6 4 + j i pivo + + (4) swap the left and the pivo. + 2 3 1 7 8 5 6 4 + j i pivo + + */ + + while (true) { + // Find the first element which does not fullfill the rule + // When l move to the pivot, it will not move again because arr[l] == pivot. + while (arr[l] < pivot) { + l++; + } + + // Find the first element which does not fullfill the rule + while (r > 0 && arr[r] > pivot) { + r--; + } + + // If r <= l, means that all the elements is in the right place. + if (r <= l) { + break; + } + + // Swap the first two elements that does not fit the rule. + swap(arr, r, l); + } + + // The l pointer point to the first element which is bigger than the pvio. + // So we can put the pvio just here. Because put a big one in the last will not change the rule that: + // all the smaller one is in the left and the right one is in the right. + swap(arr, l, right); + + return l; + } + + // private helper method to swap two values in an array + private static void swap(int[] arr, int dex1, int dex2) { + int tmp = arr[dex1]; + arr[dex1] = arr[dex2]; + arr[dex2] = tmp; + } + + /********************************************************** + * Check if array is sorted. A simple debugging tool + **********************************************************/ + private static boolean isSorted(int[] array) { + return isSorted(array, 0, array.length - 1); + } + + private static boolean isSorted(int[] array, int lo, int hi) { + for (int i = lo + 1; i <= hi; i++) + if (array[i] < array[i - 1]) + return false; + return true; + } + +} diff --git a/tree/LCA.java b/tree/LCA.java index ae3d4b0..9119361 100644 --- a/tree/LCA.java +++ b/tree/LCA.java @@ -1,6 +1,5 @@ package Algorithms.tree; -import Algorithms.TreeNode; /** diff --git a/tree/Level_Order.java b/tree/Level_Order.java index 04956bf..b73e3e9 100644 --- a/tree/Level_Order.java +++ b/tree/Level_Order.java @@ -3,8 +3,6 @@ import java.util.ArrayList; import java.util.Queue; -import Algorithms.TreeNode; - public class Level_Order { diff --git a/tree/PostOrder.java b/tree/PostOrder.java deleted file mode 100644 index 572956b..0000000 --- a/tree/PostOrder.java +++ /dev/null @@ -1,93 +0,0 @@ -package Algorithms.tree; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.Stack; - -import Algorithms.TreeNode; - - -public class PostOrder { - /** - * Definition for binary tree - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ - public ArrayList postorderTraversal(TreeNode root) { - ArrayList result = new ArrayList(); - - if (root == null) { - return result; - } - - Stack s = new Stack(); - Stack s2 = new Stack(); - - int currval = 0; - //s.push(root); - //s2.push(root.val); - - TreeNode curr = root; - - while (true) { - // store all the right node and the root node. then shift to the left node. - while (curr != null) { - if (curr.right != null) { - // s.push(curr.right); - } - s.push(curr); - s2.push(curr.val); - curr = curr.left; - } - - if (s.isEmpty()) { - return result; - } - - curr = s.pop(); - currval = s2.pop(); - if (curr.right != null && (s.isEmpty() || s.peek() != null)) { - // this is to indicate that this node has been visited, - // when come back from the right branch, we can know that we don't need - // to search right branch again. - s.push(null); - s.push(curr); - s2.push(0); - s2.push(curr.val); - curr = curr.right; - } else { - result.add(curr.val); - if (!s.isEmpty() && s.peek() == null) { - s.pop(); // give up the "null" node. - s2.pop(); - } - - curr = null; - } - } - } - - public static void main(String[] args) { - PostOrder p = new PostOrder(); - - TreeNode root = new TreeNode(1); - - root.left = new TreeNode(2); - root.right = new TreeNode(3); - root.right.right = new TreeNode(6); - - root.left.left = new TreeNode(4); - root.left.right = new TreeNode(5); - - root.left.left.left = new TreeNode(7); - - ArrayList rst = p.postorderTraversal(root); - - System.out.printf(rst.toString()); - - - } -} diff --git a/TreeDemo.java b/tree/TreeDemo.java similarity index 99% rename from TreeDemo.java rename to tree/TreeDemo.java index 96f7789..75cb957 100644 --- a/TreeDemo.java +++ b/tree/TreeDemo.java @@ -1,4 +1,5 @@ -package Algorithms; +@@ -1,1260 +0,0 @@ +package Algorithms.tree; import java.util.ArrayList; import java.util.Iterator; @@ -1257,4 +1258,4 @@ static int[] findLongest2Help(TreeNode root, int[] maxVal) { return ret; } -} \ No newline at end of file +} \ No newline at end of file diff --git a/TreeLinkNode.java b/tree/TreeLinkNode.java similarity index 82% rename from TreeLinkNode.java rename to tree/TreeLinkNode.java index 822615e..d81489c 100644 --- a/TreeLinkNode.java +++ b/tree/TreeLinkNode.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.tree; public class TreeLinkNode { int val; TreeLinkNode left, right, next; diff --git a/TreeNode.java b/tree/TreeNode.java similarity index 90% rename from TreeNode.java rename to tree/TreeNode.java index a7b8af7..9323d13 100644 --- a/TreeNode.java +++ b/tree/TreeNode.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.tree; public class TreeNode { public int val; From fa314c254194aaaca7124d0e31022d2296eb454d Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 28 Sep 2014 13:28:12 -0700 Subject: [PATCH 012/319] merge Sort --- sort/MergeSort.java | 123 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 sort/MergeSort.java diff --git a/sort/MergeSort.java b/sort/MergeSort.java new file mode 100644 index 0000000..e994925 --- /dev/null +++ b/sort/MergeSort.java @@ -0,0 +1,123 @@ +package Algorithms.sort; + +/******************************************************** + * + * 08-722 Data Structures for Application Programmers + * Lecture 14 Advanced Sorting + * + * Naive version of Merge Sort + * + *********************************************************/ +import java.util.Arrays; + +public class MergeSort { + + private static final int SIZE = 10000; + + public static int[] mergeSort(int[] data) { + // parameter valid judge. + if (data == null) { + return null; + } + + // the base case. + int len = data.length; + if (len <= 1) { + return data; + } + + // divide into two arrays. + // create left half and right half. + int left[] = new int[len/2]; + int right[] = new int[len - len/2]; + + System.arraycopy(data, 0, left, 0, len/2); + System.arraycopy(data, len/2, right, 0, len - len/2); + + // call itself to sort left half + left = mergeSort(left); + right = mergeSort(right); + + return merge(left, right); + } + + // Precondition: two input arrays are sorted and they are not null. + private static int[] merge(int[] left, int[] right) { + int len = left.length + right.length; + + int[] ret = new int[len]; + + int leftPoint = 0; + int rightPoint = 0; + + int cur = 0; + while (leftPoint < left.length && rightPoint < right.length) { + if (left[leftPoint] < right[rightPoint]) { + ret[cur++] = left[leftPoint++]; + } else { + ret[cur++] = right[rightPoint++]; + } + } + + if (leftPoint >= left.length) { + while (rightPoint < right.length) { + ret[cur++] = right[rightPoint++]; + } + } else { + while (leftPoint < left.length) { + ret[cur++] = left[leftPoint++]; + } + } + + return ret; + } + + public static void mergeSort2(int[] data) { + // parameter valid judge. + if (data == null) { + return null; + } + + // the base case. + int len = data.length; + if (len <= 1) { + return data; + } + + // divide into two arrays. + // create left half and right half. + int left[] = new int[len/2]; + int right[] = new int[len - len/2]; + + System.arraycopy(data, 0, left, 0, len/2); + System.arraycopy(data, len/2, right, 0, len - len/2); + + // call itself to sort left half + left = mergeSort(left); + right = mergeSort(right); + + return merge(left, right); + } + + public static void main(String[] args) { + int[] a = new int[SIZE]; + for (int i = 0; i < SIZE; i++) + a[i] = (int) (Math.random() * SIZE); + + //mergeSort(a); + + int[] test = { 42, 12, 89, 27, 94, 63, 3, 78 }; + System.out.println(Arrays.toString(mergeSort(test))); + + // test merge method + int[] left = { 12, 42, 63, 89 }; + int[] right = { 3, 27, 78, 94 }; + System.out.println(Arrays.toString(merge(left, right))); + + // test merge method + int[] left2 = {}; + int[] right2 = { 3, 27, 78, 94 }; + System.out.println(Arrays.toString(merge(left2, right2))); + } + +} \ No newline at end of file From 37c41057a5ac94e8d00848675d6174190f7b6982 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 2 Oct 2014 01:23:58 -0700 Subject: [PATCH 013/319] merge --- sort/MergeSort.java | 27 ---------- tree/TreeDemo.java | 126 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 112 insertions(+), 41 deletions(-) diff --git a/sort/MergeSort.java b/sort/MergeSort.java index e994925..053da1e 100644 --- a/sort/MergeSort.java +++ b/sort/MergeSort.java @@ -72,33 +72,6 @@ private static int[] merge(int[] left, int[] right) { return ret; } - public static void mergeSort2(int[] data) { - // parameter valid judge. - if (data == null) { - return null; - } - - // the base case. - int len = data.length; - if (len <= 1) { - return data; - } - - // divide into two arrays. - // create left half and right half. - int left[] = new int[len/2]; - int right[] = new int[len - len/2]; - - System.arraycopy(data, 0, left, 0, len/2); - System.arraycopy(data, len/2, right, 0, len - len/2); - - // call itself to sort left half - left = mergeSort(left); - right = mergeSort(right); - - return merge(left, right); - } - public static void main(String[] args) { int[] a = new int[SIZE]; for (int i = 0; i < SIZE; i++) diff --git a/tree/TreeDemo.java b/tree/TreeDemo.java index 75cb957..dcaf513 100644 --- a/tree/TreeDemo.java +++ b/tree/TreeDemo.java @@ -1,9 +1,9 @@ -@@ -1,1260 +0,0 @@ package Algorithms.tree; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; +import java.util.List; import java.util.Queue; import java.util.Stack; @@ -32,8 +32,8 @@ * LAC 求解最小公共祖先, 使用list来存储path. * LCABstRec 递归求解BST树. * LCARec 递归算法 . - * * 12. 求二叉树中节点的最大距离:getMaxDistanceRec + * * 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec * 15. 找出二叉树中最长连续子串(即全部往左的连续节点,或是全部往右的连续节点)findLongest @@ -98,6 +98,12 @@ public static void main(String[] args) { TreeNode t7 = new TreeNode(0); + TreeNode t8 = new TreeNode(0); + TreeNode t9 = new TreeNode(0); + TreeNode t10 = new TreeNode(0); + TreeNode t11 = new TreeNode(0); + + t1.left = t2; t1.right = t3; t2.left = t4; @@ -106,6 +112,12 @@ public static void main(String[] args) { t4.left = t7; + // test distance + t5.right = t8; + t8.right = t9; + t9.right = t10; + t10.right = t11; + /* 10 / \ @@ -115,18 +127,20 @@ public static void main(String[] args) { / 0 */ - System.out.println(LCABstRec(t1, t2, t4).val); - System.out.println(LCABstRec(t1, t2, t6).val); - System.out.println(LCABstRec(t1, t4, t6).val); - System.out.println(LCABstRec(t1, t4, t7).val); - System.out.println(LCABstRec(t1, t3, t6).val); - - System.out.println(LCA(t1, t2, t4).val); - System.out.println(LCA(t1, t2, t6).val); - System.out.println(LCA(t1, t4, t6).val); - System.out.println(LCA(t1, t4, t7).val); - System.out.println(LCA(t1, t3, t6).val); - System.out.println(LCA(t1, t6, t6).val); +// System.out.println(LCABstRec(t1, t2, t4).val); +// System.out.println(LCABstRec(t1, t2, t6).val); +// System.out.println(LCABstRec(t1, t4, t6).val); +// System.out.println(LCABstRec(t1, t4, t7).val); +// System.out.println(LCABstRec(t1, t3, t6).val); +// +// System.out.println(LCA(t1, t2, t4).val); +// System.out.println(LCA(t1, t2, t6).val); +// System.out.println(LCA(t1, t4, t6).val); +// System.out.println(LCA(t1, t4, t7).val); +// System.out.println(LCA(t1, t3, t6).val); +// System.out.println(LCA(t1, t6, t6).val); + + System.out.println(getMaxDistanceRec(t1)); //System.out.println(isSame(r1, t1)); @@ -1185,6 +1199,90 @@ public static boolean LCAPath(TreeNode root, TreeNode node, ArrayList // found return true; } + + /* + * * 12. 求二叉树中节点的最大距离:getMaxDistanceRec + * + * 首先我们来定义这个距离: + * 距离定义为:两个节点间边的数目. + * 如: + * 1 + * / \ + * 2 3 + * \ + * 4 + * 这里最大距离定义为2,4的距离,为3. + * 求二叉树中节点的最大距离 即二叉树中相距最远的两个节点之间的距离。 (distance / diameter) + * 递归解法: + * 返回值设计: + * 返回1. 深度, 2. 当前树的最长距离 + * (1) 计算左子树的深度,右子树深度,左子树独立的链条长度,右子树独立的链条长度 + * (2) 最大长度为三者之最: + * a. 通过根节点的链,为左右深度+2 + * b. 左子树独立链 + * c. 右子树独立链。 + * + * (3)递归初始条件: + * 当root == null, depth = -1.maxDistance = -1; + * + */ + public static int getMaxDistanceRec(TreeNode root) { + return getMaxDistanceRecHelp(root).maxDistance; + } + + public static Result getMaxDistanceRecHelp(TreeNode root) { + Result ret = new Result(-1, -1); + + if (root == null) { + return ret; + } + + Result left = getMaxDistanceRecHelp(root.left); + Result right = getMaxDistanceRecHelp(root.right); + + // 深度应加1, the depth from the subtree to the root. + ret.depth = Math.max(left.depth, right.depth) + 1; + + // 左子树,右子树与根的距离都要加1,所以通过根节点的路径为两边深度+2 + int crossLen = left.depth + right.depth + 2; + + // 求出cross根的路径,及左右子树的独立路径,这三者路径的最大值。 + ret.maxDistance = Math.max(left.maxDistance, right.maxDistance); + ret.maxDistance = Math.max(ret.maxDistance, crossLen); + + return ret; + } + + + private static class Result { + int depth; + int maxDistance; + public Result(int depth, int maxDistance) { + this.depth = depth; + this.maxDistance = maxDistance; + } + } + + /* + * 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec + * */ + public static TreeNode rebuildBinaryTreeRec(List preOrder, List inOrder) { + if (preOrder == null || inOrder == null) { + return null; + } + + // If the traversal is empty, just return a NULL. + if (preOrder.size() == 0 || inOrder.size() == 0) { + return null; + } + + // we can get the root from the preOrder. Because the first one is the + // root. + TreeNode root = preOrder.get(0); + + return null; + + } /* * 15. findLongest From b0e4e32cf5128522a9907c991fcf373d3ef0a76a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 2 Oct 2014 01:58:32 -0700 Subject: [PATCH 014/319] Five Chessman --- dfs/FiveChessman.java | 143 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 dfs/FiveChessman.java diff --git a/dfs/FiveChessman.java b/dfs/FiveChessman.java new file mode 100644 index 0000000..35a0355 --- /dev/null +++ b/dfs/FiveChessman.java @@ -0,0 +1,143 @@ +package Algorithms.dfs; + +/* + * 输入一个19*19的矩阵,只包含数字0、1、2,表示两人下五子棋的棋牌状态,1、2分别表示两人的棋子,0表示空格。 + * 要求判断当前状态下是否有人获胜(横向、竖向或者斜线方向连成5个同色棋子)。题目说明输入样例保证每条线上至多 + * 只有连续5个同色棋子,并且保证至多只有1人获胜。如果有人获胜,输出获胜者(1或2)加一个冒号, + * 接着输出获胜的五连珠的第一个棋子的坐标,从上到下从左到右序号最小的为第一个,序号从1开始编号。如果无人获胜,输出no。 + * */ +public class FiveChessman { + private static class Coordinate { + int col; + int row; + + public Coordinate (int col, int row) { + this.col = col; + this.row = row; + } + } + + public static class Visit { + boolean right; + boolean down; + boolean rightDown; + boolean leftDown; + + public Visit (boolean right, boolean down, boolean rightDown, boolean leftDown) { + this.right = right; + this.down = down; + this.rightDown = rightDown; + this.leftDown = leftDown; + } + } + + public static void main(String[] args) { + int[][] input = { + {1, 0, 0, 0, 1, 0}, + {0, 1, 0, 1, 0, 2}, + {0, 0, 1, 0, 2, 0}, + {0, 1, 0, 2, 0, 0}, + {0, 0, 2, 0, 1, 0}, + {0, 2, 0, 0, 0, 0} + }; + + Coordinate result = findWin(input); + if (result != null) { + System.out.println("" + result.row + " " + result.col); + } + + } + + // in 代表棋盘 + public static Coordinate findWin(int[][] in) { + if (in == null || in.length == 0) { + return null; + } + + int row = in.length; + int col = in[0].length; + + Visit[][] visit = new Visit[row][col]; + + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + // try to get the result from 4 directions. + for (int k = 0; k < 4; k++) { + visit[i][j] = new Visit(false, false, false, false); + Coordinate ret = findWinHelp(in, j, i, in[i][j], k, visit, 0); + if (ret != null) { + return ret; + } + } + } + } + + return null; + } + + // row, col 代表我们现在正在扫描的点的坐标 + public static Coordinate findWinHelp(int[][] in, int col, int row, int side, int direction, Visit[][] visit, int num) { + // 扫描不可以超过范围 + if (col >= in.length || row >= in.length || row < 0 || col < 0) { + return null; + } + + // if it is 0, just return. + if (in[row][col] == 0) { + return null; + } + + if (side != in[row][col]) { + return null; + } + + // we get the result. + if (num == 4) { + return new Coordinate(col, row); + } + + if (visit[row][col] == null) { + visit[row][col] = new Visit(false, false, false, false); + } + + if (direction == 0) { + if (visit[row][col].right) { + return null; + } + visit[row][col].right = true; + + // right + return findWinHelp(in, col + 1, row, side, direction, visit, num + 1); + } else if (direction == 1) { + if (visit[row][col].down) { + return null; + } + + visit[row][col].down = true; + + // down + return findWinHelp(in, col, row + 1, side, direction, visit, num + 1); + } else if (direction == 2) { + if (visit[row][col].rightDown) { + return null; + } + + + visit[row][col].rightDown = true; + + // right down + return findWinHelp(in, col + 1, row + 1, side, direction, visit, num + 1); + } else if (direction == 3) { + if (visit[row][col].leftDown) { + return null; + } + + visit[row][col].leftDown = true; + + // left down + return findWinHelp(in, col - 1, row + 1, side, direction, visit, num + 1); + } + + return null; + } +} From 441dba7dce3a0455c7e1d35654edf916773ab449 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 2 Oct 2014 02:12:28 -0700 Subject: [PATCH 015/319] FiveChessman --- dfs/FiveChessman.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dfs/FiveChessman.java b/dfs/FiveChessman.java index 35a0355..d4f8ad2 100644 --- a/dfs/FiveChessman.java +++ b/dfs/FiveChessman.java @@ -122,7 +122,6 @@ public static Coordinate findWinHelp(int[][] in, int col, int row, int side, int return null; } - visit[row][col].rightDown = true; // right down From 2eec8247b274f9d2cc973197ab0158c45490e8f7 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 2 Oct 2014 02:35:23 -0700 Subject: [PATCH 016/319] notes --- dfs/FiveChessman.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dfs/FiveChessman.java b/dfs/FiveChessman.java index d4f8ad2..9e0c33f 100644 --- a/dfs/FiveChessman.java +++ b/dfs/FiveChessman.java @@ -76,6 +76,9 @@ public static Coordinate findWin(int[][] in) { } // row, col 代表我们现在正在扫描的点的坐标 + // side 记录目前是哪一方的棋子 + // direction 记录扫描方向,有四个方向扫描:右,右下,左下,下。 + // num: 代表扫描到第几个棋子了。 public static Coordinate findWinHelp(int[][] in, int col, int row, int side, int direction, Visit[][] visit, int num) { // 扫描不可以超过范围 if (col >= in.length || row >= in.length || row < 0 || col < 0) { @@ -87,6 +90,7 @@ public static Coordinate findWinHelp(int[][] in, int col, int row, int side, int return null; } + // 必须是同边的棋子。例如,都是1,或都是2. if (side != in[row][col]) { return null; } @@ -96,10 +100,12 @@ public static Coordinate findWinHelp(int[][] in, int col, int row, int side, int return new Coordinate(col, row); } + // 如果未设置标记,新建标记。 if (visit[row][col] == null) { visit[row][col] = new Visit(false, false, false, false); } + // 对各个方向进行不同的搜索方向。 if (direction == 0) { if (visit[row][col].right) { return null; From 1551e7f95a26328bb8be765803b2b818767e613f Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 2 Oct 2014 13:44:09 -0700 Subject: [PATCH 017/319] the largest Common subtree --- tree/LargestCommonSubtrees.java | 177 ++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 tree/LargestCommonSubtrees.java diff --git a/tree/LargestCommonSubtrees.java b/tree/LargestCommonSubtrees.java new file mode 100644 index 0000000..d366db8 --- /dev/null +++ b/tree/LargestCommonSubtrees.java @@ -0,0 +1,177 @@ +package Algorithms.tree; + +import java.util.*; + + +public class LargestCommonSubtrees { + /* + * Function: Find all the common subtrees root that have most number + */ + private static class TreeNode { + int val; + ArrayList subNodes; + public TreeNode(int val, ArrayList subNodes) { + this.val = val; + this.subNodes = subNodes; + } + } + + public static void main(String[] args) { + /* + * 1 + * + * / \ \ + * 2 3 4 + * / \ / \ + * 5 6 8 9 + * \ \ + * 7 10 + * */ + TreeNode r1 = new TreeNode(1, new ArrayList()); + TreeNode r2 = new TreeNode(2, new ArrayList()); + TreeNode r3 = new TreeNode(3, new ArrayList()); + TreeNode r4 = new TreeNode(4, new ArrayList()); + TreeNode r5 = new TreeNode(5, new ArrayList()); + TreeNode r6 = new TreeNode(6, new ArrayList()); + TreeNode r7 = new TreeNode(7, new ArrayList()); + TreeNode r8 = new TreeNode(8, new ArrayList()); + TreeNode r9 = new TreeNode(9, new ArrayList()); + TreeNode r10 = new TreeNode(10, new ArrayList()); + + r1.subNodes.add(r2); + r1.subNodes.add(r3); + r1.subNodes.add(r4); + + r2.subNodes.add(r5); + r2.subNodes.add(r6); + + r6.subNodes.add(r7); + + r4.subNodes.add(r8); + r4.subNodes.add(r9); + + r9.subNodes.add(r10); + + ArrayList> ret = largestCommonSubtrees(r1); + for (ArrayList arrayl: ret) { + for (TreeNode t: arrayl) { + System.out.println(t.val); + } + } + + } + + public static ArrayList> largestCommonSubtrees(TreeNode root) { + if (root == null) { + return null; + } + + ArrayList> ret = new ArrayList>(); + + // store all the tree nodes to a arrayList. + ArrayList nodes = new ArrayList(); + traversalTree(root, nodes); + + int maxNum = 0; + + HashMap hash = new HashMap(); + + TreeNode r1 = null; + TreeNode r2 = null; + + + // compare all the nodes. + int size = nodes.size(); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + if (i == j) { + continue; + } + int num = compareTree(nodes.get(i), nodes.get(j), hash); + if (num > maxNum) { + ArrayList iden = new ArrayList(); + iden.add(nodes.get(i)); + iden.add(nodes.get(j)); + + ret.add(iden); + r1 = nodes.get(i); + r2 = nodes.get(j); + } + } + } + + ArrayList> retNew = new ArrayList>(); + retNew.add(new ArrayList()); + retNew.get(0).add(r1); + retNew.get(0).add(r2); + return retNew; + } + + + // compare two tree, if same, return the number of leafs. if no, return -1; + public static int compareTree(TreeNode r1, TreeNode r2, HashMap hash) { + if (r1 == null && r2 == null) { + return 0; + } + + if (r1 == null || r2 == null) { + return -1; + } + + // the number of subtrees should be same. + if (r1.subNodes.size() != r2.subNodes.size()) { + return -1; + } + + int num = 1; // the root itself. + + for (int i = 0; i < r1.subNodes.size(); i++) { + // get the subNode of r1. + TreeNode subNode1 = r1.subNodes.get(i); + TreeNode subNode2 = r2.subNodes.get(i); + + int HashCode = hashCode(subNode1, subNode2); + + Integer numNode = hash.get(HashCode); + if (numNode == null) { + numNode = compareTree(subNode1, subNode2, hash); + } + + if (numNode == -1) { + // not the same, should return; + num = -1; + break; + } else { + num += numNode; + continue; + } + } + + int hashCodeRoot = hashCode(r1, r2); + hash.put(hashCodeRoot, num); + + return num; + } + + public static int hashCode(TreeNode r1, TreeNode r2) { + int hash = r1.hashCode() * 31 + r2.hashCode(); + return hash; + } + + public static void traversalTree(TreeNode root, ArrayList ret) { + if (root == null) { + return; + } + + ret.add(root); + + // add all the sub nodes. + if (root.subNodes != null) { + for(TreeNode t: root.subNodes) { + traversalTree(t, ret); + } + } + } + + +} \ No newline at end of file From 61e79b2770d90e1b18a5585101d9109f71a584a9 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 2 Oct 2014 13:47:46 -0700 Subject: [PATCH 018/319] the largest common --- tree/LargestCommonSubtrees.java | 1 + 1 file changed, 1 insertion(+) diff --git a/tree/LargestCommonSubtrees.java b/tree/LargestCommonSubtrees.java index d366db8..6376a55 100644 --- a/tree/LargestCommonSubtrees.java +++ b/tree/LargestCommonSubtrees.java @@ -89,6 +89,7 @@ public static ArrayList> largestCommonSubtrees(TreeNode root } int num = compareTree(nodes.get(i), nodes.get(j), hash); if (num > maxNum) { + maxNum = num; ArrayList iden = new ArrayList(); iden.add(nodes.get(i)); iden.add(nodes.get(j)); From ff798aeb1a6152c8ba16958d64c5651bee7907bc Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 2 Oct 2014 13:51:46 -0700 Subject: [PATCH 019/319] largestCommon --- tree/LargestCommonSubtrees.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tree/LargestCommonSubtrees.java b/tree/LargestCommonSubtrees.java index 6376a55..2011e94 100644 --- a/tree/LargestCommonSubtrees.java +++ b/tree/LargestCommonSubtrees.java @@ -66,8 +66,6 @@ public static ArrayList> largestCommonSubtrees(TreeNode root return null; } - ArrayList> ret = new ArrayList>(); - // store all the tree nodes to a arrayList. ArrayList nodes = new ArrayList(); traversalTree(root, nodes); @@ -90,11 +88,6 @@ public static ArrayList> largestCommonSubtrees(TreeNode root int num = compareTree(nodes.get(i), nodes.get(j), hash); if (num > maxNum) { maxNum = num; - ArrayList iden = new ArrayList(); - iden.add(nodes.get(i)); - iden.add(nodes.get(j)); - - ret.add(iden); r1 = nodes.get(i); r2 = nodes.get(j); } From 718698dc9e5462d91c0399fed355dedac70d4751 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 4 Oct 2014 20:32:43 -0700 Subject: [PATCH 020/319] TestPermutation --- permutation/Permutation.java | 92 +++++++++++++++++++ permutation/Stopwatch.java | 22 +++++ tree/TreeDemo.java | 166 +++++++++++++++++++++++++++++++++-- 3 files changed, 271 insertions(+), 9 deletions(-) create mode 100644 permutation/Permutation.java create mode 100644 permutation/Stopwatch.java diff --git a/permutation/Permutation.java b/permutation/Permutation.java new file mode 100644 index 0000000..dfbd401 --- /dev/null +++ b/permutation/Permutation.java @@ -0,0 +1,92 @@ +package Algorithms.permutation; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; + +public class Permutation { + public static void main(String[] strs) { + int[] num = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + System.out.printf("Test size:%d \n", num.length); + + Stopwatch timer1 = new Stopwatch(); + + permute(num); + System.out + .println("Computing time with ArrayDeque used as Queue/Deque: " + + timer1.elapsedTime() + " millisec."); + + System.out.printf("Test size:%d \n", num.length); + + Stopwatch timer2 = new Stopwatch(); + + permute2(num); + System.out + .println("Computing time with ArrayDeque used as Queue/Deque: " + + timer2.elapsedTime() + " millisec."); + } + + public static ArrayList> permute(int[] num) { + ArrayList> ret = new ArrayList>(); + if (num == null) { + return ret; + } + + permuteHelp(num, ret, new LinkedHashMap()); + return ret; + } + + public static void permuteHelp(int[] num, ArrayList> ret, LinkedHashMap set) { + if (set.size() == num.length) { + + ArrayList list = new ArrayList(); + for (Integer i: set.keySet()){ + list.add(i); + } + ret.add(list); + return; + } + + int len = num.length; + for (int i = 0; i < len; i++) { + if (set.containsKey(num[i])) { + continue; + } + + //path.add(num[i]); + set.put(num[i], 0); + permuteHelp(num, ret, set); + //path.remove(path.size() - 1); + set.remove(num[i]); + } + } + + public static ArrayList> permute2(int[] num) { + ArrayList> ret = new ArrayList>(); + if (num == null) { + return ret; + } + + ArrayList path = new ArrayList(); + permuteHelp2(num, path, ret); + return ret; + } + + public static void permuteHelp2(int[] num, ArrayList path, ArrayList> ret) { + if (path.size() == num.length) { + ret.add(new ArrayList(path)); + return; + } + + int len = num.length; + for (int i = 0; i < len; i++) { + if (path.contains(num[i])) { + continue; + } + + path.add(num[i]); + permuteHelp2(num, path, ret); + path.remove(path.size() - 1); + } + } +} diff --git a/permutation/Stopwatch.java b/permutation/Stopwatch.java new file mode 100644 index 0000000..3d95f47 --- /dev/null +++ b/permutation/Stopwatch.java @@ -0,0 +1,22 @@ +package Algorithms.permutation; + +/***************************************** + * Stopwatch class to be used as a timer + *****************************************/ + +public class Stopwatch { + + + private final long start; + + public Stopwatch() { + start = System.currentTimeMillis(); + } + + // return time (in milliseconds) since this object was created + public double elapsedTime() { + long now = System.currentTimeMillis(); + return now - start; + } + +} \ No newline at end of file diff --git a/tree/TreeDemo.java b/tree/TreeDemo.java index dcaf513..8d019e0 100644 --- a/tree/TreeDemo.java +++ b/tree/TreeDemo.java @@ -33,9 +33,9 @@ * LCABstRec 递归求解BST树. * LCARec 递归算法 . * 12. 求二叉树中节点的最大距离:getMaxDistanceRec - * - * 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec - * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec + * 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec + * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec + * * 15. 找出二叉树中最长连续子串(即全部往左的连续节点,或是全部往右的连续节点)findLongest * */ @@ -214,7 +214,35 @@ public static void main(String[] args) { // System.out.println(); // System.out.println(findLongest2(r1)); - + // test the rebuildBinaryTreeRec. + test_rebuildBinaryTreeRec(); + } + + public static void test_rebuildBinaryTreeRec() { + ArrayList list1 = new ArrayList(); + list1.add(1); + list1.add(2); + list1.add(4); + list1.add(5); + list1.add(3); + list1.add(6); + list1.add(7); + list1.add(8); + + ArrayList list2 = new ArrayList(); + list2.add(4); + list2.add(2); + list2.add(5); + list2.add(1); + list2.add(3); + list2.add(7); + list2.add(6); + list2.add(8); + + TreeNode root = rebuildBinaryTreeRec(list1, list2); + preorderTraversalRec(root); + System.out.println(); + postorderTraversalRec(root); } private static class TreeNode{ @@ -1265,7 +1293,21 @@ public Result(int depth, int maxDistance) { /* * 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec - * */ + * We assume that there is no duplicate in the trees. + * For example: + * 1 + * / \ + * 2 3 + * /\ \ + * 4 5 6 + * /\ + * 7 8 + * + * PreOrder should be: 1 2 4 5 3 6 7 8 + * 根 左子树 右子树 + * InOrder should be: 4 2 5 1 3 7 6 8 + * 左子树 根 右子树 + * */ public static TreeNode rebuildBinaryTreeRec(List preOrder, List inOrder) { if (preOrder == null || inOrder == null) { return null; @@ -1276,12 +1318,118 @@ public static TreeNode rebuildBinaryTreeRec(List preOrder, List preOrderLeft; + List preOrderRight; + List inOrderLeft; + List inOrderRight; + // 获得在 inOrder中,根的位置 + int rootInIndex = inOrder.indexOf(preOrder.get(0)); + preOrderLeft = preOrder.subList(1, rootInIndex + 1); + preOrderRight = preOrder.subList(rootInIndex + 1, preOrder.size()); + + // 得到inOrder左边的左子树 + inOrderLeft = inOrder.subList(0, rootInIndex); + inOrderRight = inOrder.subList(rootInIndex + 1, inOrder.size()); + + // 通过 Rec 来调用生成左右子树。 + root.left = rebuildBinaryTreeRec(preOrderLeft, inOrderLeft); + root.right = rebuildBinaryTreeRec(preOrderRight, inOrderRight); + + return root; + } + + /* + * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec + * + * */ + + public static boolean isCompleteBinaryTree(TreeNode root) { + return false; + } + + /* + * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTreeRec + * + * + * 我们可以分解为: + * CompleteBinary Tree 的条件是: + * 1. 左右子树均为Perfect binary tree, 并且两者Height相同 + * 2. 左子树为CompleteBinaryTree, 右子树为Perfect binary tree,并且两者Height差1 + * 3. 左子树为Perfect Binary Tree,右子树为CompleteBinaryTree, 并且Height 相同 + * + * Base 条件: + * (1) root = null: 为perfect & complete BinaryTree, Height -1; + * + * 而 Perfect Binary Tree的条件: + * 左右子树均为Perfect Binary Tree,并且Height 相同。 + * */ + + public static boolean isCompleteBinaryTreeRec(TreeNode root) { + return isCompleteBinaryTreeRecHelp(root).isCompleteBT; + } + + private static class ReturnBinaryTree { + boolean isCompleteBT; + boolean isPerfectBT; + int height; + + ReturnBinaryTree(boolean isCompleteBT, boolean isPerfectBT, int height) { + this.isCompleteBT = isCompleteBT; + this.isPerfectBT = isPerfectBT; + this.height = height; + } + } + + /* + * 我们可以分解为: + * CompleteBinary Tree 的条件是: + * 1. 左右子树均为Perfect binary tree, 并且两者Height相同 + * 2. 左子树为CompleteBinaryTree, 右子树为Perfect binary tree,并且两者Height差1 + * 3. 左子树为Perfect Binary Tree,右子树为CompleteBinaryTree, 并且Height 相同 + * + * Base 条件: + * (1) root = null: 为perfect & complete BinaryTree, Height -1; + * + * 而 Perfect Binary Tree的条件: + * 左右子树均为Perfect Binary Tree,并且Height 相同。 + * */ + public static ReturnBinaryTree isCompleteBinaryTreeRecHelp(TreeNode root) { + ReturnBinaryTree ret = new ReturnBinaryTree(true, true, -1); + + if (root == null) { + return ret; + } + + ReturnBinaryTree left = isCompleteBinaryTreeRecHelp(root.left); + ReturnBinaryTree right = isCompleteBinaryTreeRecHelp(root.right); + + // 树的高度为左树高度,右树高度的最大值+1 + ret.height = 1 + Math.max(left.height, right.height); + + // set the isPerfectBT + ret.isPerfectBT = false; + if (left.isPerfectBT && right.isPerfectBT && left.height == right.height) { + ret.isPerfectBT = true; + } + + // set the isCompleteBT. + /* + * CompleteBinary Tree 的条件是: + * 1. 左右子树均为Perfect binary tree, 并且两者Height相同(其实就是本树是perfect tree) + * 2. 左子树为CompleteBinaryTree, 右子树为Perfect binary tree,并且两者Height差1 + * 3. 左子树为Perfect Binary Tree,右子树为CompleteBinaryTree, 并且Height 相同 + * */ + ret.isCompleteBT = ret.isPerfectBT + || (left.isCompleteBT && right.isPerfectBT && left.height == right.height + 1) + || (left.isPerfectBT && right.isCompleteBT && left.height == right.height); + + return ret; } /* From 7d60ff42f618c4a69179164045e69454163ea97b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 4 Oct 2014 22:20:09 -0700 Subject: [PATCH 021/319] isCompleteBinaryTree --- tree/TreeDemo.java | 75 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/tree/TreeDemo.java b/tree/TreeDemo.java index 8d019e0..882b477 100644 --- a/tree/TreeDemo.java +++ b/tree/TreeDemo.java @@ -108,15 +108,19 @@ public static void main(String[] args) { t1.right = t3; t2.left = t4; t2.right = t5; - t3.right = t6; + t3.left = t6; + t3.right = t7; + + t4.left = t8; + //t4.right = t9; + t5.right = t9; - t4.left = t7; // test distance - t5.right = t8; - t8.right = t9; - t9.right = t10; - t10.right = t11; +// t5.right = t8; +// t8.right = t9; +// t9.right = t10; +// t10.right = t11; /* 10 @@ -140,7 +144,7 @@ public static void main(String[] args) { // System.out.println(LCA(t1, t3, t6).val); // System.out.println(LCA(t1, t6, t6).val); - System.out.println(getMaxDistanceRec(t1)); + //System.out.println(getMaxDistanceRec(t1)); //System.out.println(isSame(r1, t1)); @@ -215,7 +219,10 @@ public static void main(String[] args) { // System.out.println(findLongest2(r1)); // test the rebuildBinaryTreeRec. - test_rebuildBinaryTreeRec(); + //test_rebuildBinaryTreeRec(); + + System.out.println(isCompleteBinaryTreeRec(t1)); + System.out.println(isCompleteBinaryTree(t1)); } public static void test_rebuildBinaryTreeRec() { @@ -1346,11 +1353,59 @@ public static TreeNode rebuildBinaryTreeRec(List preOrder, List q = new LinkedList(); + + q.offer(root); + q.offer(dummyNode); + + // if this is true, no node should have any child. + boolean noChild = false; + + while (!q.isEmpty()) { + TreeNode cur = q.poll(); + if (cur == dummyNode) { + if (!q.isEmpty()) { + q.offer(dummyNode); + } + // Dummy node不需要处理。 + continue; + } + + if (cur.left != null) { + // 如果标记被设置,则Queue中任何元素不应再有子元素。 + if (noChild) { + return false; + } + q.offer(cur.left); + } else { + // 一旦某元素没有左节点或是右节点,则之后所有的元素都不应有子元素。 + // 并且该元素不可以有右节点. + noChild = true; + } + + if (cur.right != null) { + // 如果标记被设置,则Queue中任何元素不应再有子元素。 + if (noChild) { + return false; + } + q.offer(cur.right); + } else { + // 一旦某元素没有左节点或是右节点,则之后所有的元素都不应有子元素。 + noChild = true; + } + } + + return true; } /* From c73a8a77b50c85d6fb5bbc64b02b139550db3216 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 5 Oct 2014 03:19:24 -0700 Subject: [PATCH 022/319] NextPermutation --- permutation/NextPermutation.java | 55 ++++++++++++++++++++++++++++++++ tree/TreeDemo.java | 2 -- 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 permutation/NextPermutation.java diff --git a/permutation/NextPermutation.java b/permutation/NextPermutation.java new file mode 100644 index 0000000..e8acbed --- /dev/null +++ b/permutation/NextPermutation.java @@ -0,0 +1,55 @@ +package Algorithms.permutation; + +public class NextPermutation { + public void nextPermutation(int[] num) { + // There should be at least 2 digitals. + if (num == null || num.length <= 1) { + return; + } + + int len = num.length; + + // From the tail to find the first digital which drop + // example: 1 2 4321 + // i + int i = len - 2; + for (; i >= 0; i--) { + if (num[i] < num[i + 1]) { + break; + } + } + + // example: 1 2 4321 + // i j + // then swap i and j. + // Find the first digital which is bigger than the digital just found. + // swap: 1 3 4221 + // if i == -1, it means that it should be like: 432, 从尾部往前,没有下降的情况 + if (i != -1) { + for (int j = len - 1; j > i; j--) { + if (num[j] > num[i]) { + swap(num, i, j); + break; + } + } + } + + + // than just make the 4221 to reverse. + // result: 1 3 1224 + int left = i + 1; + int right = len - 1; + while (left < right) { + swap(num, left, right); + left++; + right--; + } + } + + // swap the i, j element in the array. + public void swap(int[] num, int i, int j) { + int tmp = num[i]; + num[i] = num[j]; + num[j] = tmp; + } +} diff --git a/tree/TreeDemo.java b/tree/TreeDemo.java index 882b477..8931467 100644 --- a/tree/TreeDemo.java +++ b/tree/TreeDemo.java @@ -35,9 +35,7 @@ * 12. 求二叉树中节点的最大距离:getMaxDistanceRec * 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec - * * 15. 找出二叉树中最长连续子串(即全部往左的连续节点,或是全部往右的连续节点)findLongest - * */ public class TreeDemo { From 8c9f0e8c6eb486448d889228af1936c2f3528e2d Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 5 Oct 2014 04:21:02 -0700 Subject: [PATCH 023/319] permutation sequence --- permutation/PermutationSequence.java | 69 ++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 permutation/PermutationSequence.java diff --git a/permutation/PermutationSequence.java b/permutation/PermutationSequence.java new file mode 100644 index 0000000..22d5833 --- /dev/null +++ b/permutation/PermutationSequence.java @@ -0,0 +1,69 @@ +package Algorithms.permutation; + +/* + The set [1,2,3,…,n] contains a total of n! unique permutations. + +By listing and labeling all of the permutations in order, +We get the following sequence (ie, for n = 3): + + "123" + "132" + "213" + "231" + "312" + "321" + +Given n and k, return the kth permutation sequence. + +Note: Given n will be between 1 and 9 inclusive. + * */ +public class PermutationSequence { + public static String getPermutation(int n, int k) { + if (n == 0) { + return ""; + } + + // 先计算出(n)! + int num = 1; + for (int i = 1; i <= n; i++) { + num *= i; + } + + boolean[] use = new boolean[n]; + for (int i = 0; i < n; i++) { + use[i] = false; + } + + // 因为index是从0开始计算 + k--; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < n; i++) { + // 计算完第一个数字前,num要除以(n) + num = num / (n - i); + + int index = k / num; + k = k % num; + + for (int j = 0; j < n; j++) { + if (!use[j]) { + if (index == 0) { + // 记录下本次的结果. + sb.append((j + 1) + ""); + use[j] = true; + break; + } + + // 遇到未使用过的数字,记录index + index--; + } + } + } + + return sb.toString(); + } + + public static void main(String[] args) { + System.out.println(getPermutation(3, 5)); + } + +} From b8c8f5fbfd241cf949e7b346947e5b87e22cf138 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 5 Oct 2014 16:46:07 -0700 Subject: [PATCH 024/319] Fibonacci --- dp/Fibonacci.java | 69 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 dp/Fibonacci.java diff --git a/dp/Fibonacci.java b/dp/Fibonacci.java new file mode 100644 index 0000000..1c00e40 --- /dev/null +++ b/dp/Fibonacci.java @@ -0,0 +1,69 @@ +package Algorithms.dp; + +import java.util.ArrayList; + +/************************************************************************* + * Compilation: javac Fibonacci.java + * Execution: java Fibonacci N + * + * Computes and prints the first N Fibonacci numbers. + * + * WARNING: this program is spectacularly inefficient and is meant + * to illustrate a performance bug, e.g., set N = 45. + * + * + * % java Fibonacci 7 + * 1: 1 + * 2: 1 + * 3: 2 + * 4: 3 + * 5: 5 + * 6: 8 + * 7: 13 + * + * Remarks + * ------- + * - The 93rd Fibonacci number would overflow a long, but this + * will take so long to compute with this function that we + * don't bother to check for overflow. + * + *************************************************************************/ +public class Fibonacci { + public static long fib(int n) { + //System.out.println("Enter rec once."); + + if (n <= 2) { + return 1; + } + + return fib(n - 1) + fib(n - 2); + } + + public static ArrayList fibDp(int n) { + ArrayList ret = new ArrayList(); + + // We use the arrayList to store the result to avoid multiply count. + for (int i = 0; i < n; i++) { + if (i <= 1) { + ret.add(1); + } else { + ret.add(ret.get(i - 1) + ret.get(i - 2)); + } + } + + return ret; + } + + public static void main(String[] args) { + int N = 5; + + System.out.print(fib(5) + " "); +// for (int i = 1; i <= N; i++) { +// System.out.print(fib(i) + " "); +// } + + ArrayList list = fibDp(500); + System.out.println(list.toString()); + } + +} From 92f4168c0ae2fade27ce21caed29b03a6d5a05c8 Mon Sep 17 00:00:00 2001 From: piggy Date: Tue, 7 Oct 2014 01:22:12 -0700 Subject: [PATCH 025/319] add new file --- tree/sortedListToBST.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tree/sortedListToBST.java diff --git a/tree/sortedListToBST.java b/tree/sortedListToBST.java new file mode 100644 index 0000000..e69de29 From f928b91b615a05af515f4028a4d7359ae8811b72 Mon Sep 17 00:00:00 2001 From: piggy Date: Tue, 7 Oct 2014 01:46:30 -0700 Subject: [PATCH 026/319] add code. --- tree/sortedListToBST.java | 102 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/tree/sortedListToBST.java b/tree/sortedListToBST.java index e69de29..eaac151 100644 --- a/tree/sortedListToBST.java +++ b/tree/sortedListToBST.java @@ -0,0 +1,102 @@ +/** + * Definition for singly-linked list. + * public class ListNode {h + * int val; + * ListNode next; + * ListNode(int x) { val = x; next = null; } + * } + */ +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class Solution { + public TreeNode sortedListToBST1(ListNode head) { + ListNode fast = head; + ListNode slow = head; + + ListNode pre = head; + + if (head == null) { + return null; + } + + TreeNode root = null; + if (head.next == null) { + root = new TreeNode(head.val); + root.left = null; + root.right = null; + return root; + } + + // get the middle node. + while (fast != null && fast.next != null) { + fast = fast.next.next; + + // record the node before the SLOW. + pre = slow; + slow = slow.next; + } + + // cut the list to two parts. + pre.next = null; + TreeNode left = sortedListToBST1(head); + TreeNode right = sortedListToBST1(slow.next); + + root = new TreeNode(slow.val); + root.left = left; + root.right = right; + + return root; + } + + public TreeNode sortedListToBST(ListNode head) { + if (head == null) { + return null; + } + + int size = 0; + ListNode cur = head; + while (cur != null) { + size++; + cur = cur.next; + } + + CurrNode curNode = new CurrNode(head); + return sortedListToBSTHelp(curNode, size); + } + + public class CurrNode { + ListNode node; + + CurrNode(ListNode node) { + this.node = node; + } + } + + // when the recursion is done, the curr node should point to the node + // which is the next of the block. + public TreeNode sortedListToBSTHelp(CurrNode curr, int size) { + if (size <= 0) { + return null; + } + + TreeNode left = sortedListToBSTHelp(curr, size/2); + + // because we want to deal with the right block. + TreeNode root = new TreeNode(curr.node.val); + curr.node = curr.node.next; + + TreeNode right = sortedListToBSTHelp(curr, size - 1 - size/2); + + root.left = left; + root.right = right; + + return root; + } +} From b6817a69218e9897dbdd4342243b03408ebdde90 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 7 Oct 2014 19:38:05 -0700 Subject: [PATCH 027/319] Recover Binary Search Tree --- tree/IsSymmetric_LeetCode.java | 112 +++++++++++++++++++++++++++++++++ tree/RecoverTree.java | 70 +++++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 tree/IsSymmetric_LeetCode.java create mode 100644 tree/RecoverTree.java diff --git a/tree/IsSymmetric_LeetCode.java b/tree/IsSymmetric_LeetCode.java new file mode 100644 index 0000000..d52a3db --- /dev/null +++ b/tree/IsSymmetric_LeetCode.java @@ -0,0 +1,112 @@ +package Algorithms.tree; + +import java.util.Stack; + +public class IsSymmetric_LeetCode { + /* + * Given a binary tree, check whether it is a mirror of itself (ie, + * symmetric around its center). + * + * For example, this binary tree is symmetric: + * + * 1 / \ 2 2 / \ / \ 3 4 4 3 + * + * But the following is not: + * + * 1 / \ 2 2 \ \ 3 3 + * + * Note: Bonus points if you could solve it both recursively and + * iteratively. + * + * confused what "{1,#,2,3}" means? > read more on how binary tree is + * serialized on OJ. + * + * OJ's Binary Tree Serialization: + * + * The serialization of a binary tree follows a level order traversal, where + * '#' signifies a path terminator where no node exists below. + * + * Here's an example: + * + * 1 / \ 2 3 / 4 \ 5 + * + * The above binary tree is serialized as "{1,2,3,#,#,4,#,#,5}". + */ + // + public boolean isSymmetric(TreeNode root) { + if (root == null) { + return true; + } + + return isMirrorRec(root.left, root.right); + } + + /* + * 判断两个树是否互相镜像 + * (1) 根必须同时为空,或是同时不为空 + * + * 如果根不为空: + * (1).根的值一样 + * (2).r1的左树是r2的右树的镜像 + * (3).r1的右树是r2的左树的镜像 + */ + public boolean isMirrorRec(TreeNode r1, TreeNode r2) { + if (r1 == null && r2 == null) { + return true; + } + + if (r1 == null || r2 == null) { + return false; + } + + // should compare the value of the root. remember this. + return r1.val == r2.val + && isMirrorRec(r1.left, r2.right) + && isMirrorRec(r1.right, r2.left); + } + + public boolean isMirror(TreeNode r1, TreeNode r2) { + if (r1 == null && r2 == null) { + return true; + } + + if (r1 == null || r2 == null) { + return false; + } + + // We can do preOrder traverse to judge if the trees are mirror. + Stack s1 = new Stack(); + Stack s2 = new Stack(); + s1.push(r1); + s2.push(r2); + + while (!s1.isEmpty() && !s2.isEmpty()) { + // pop the current node out. + TreeNode cur1 = s1.pop(); + TreeNode cur2 = s2.pop(); + + // Judge if the value of the node is equal. + if (cur1.val != cur2.val) { + return false; + } + + // tree1的左节点,tree2的右节点,可以同时不为空,也可以同时为空,否则返回false. + if (cur1.left != null && cur2.right != null) { + s1.push(cur1.left); + s2.push(cur2.right); + } else if (!(cur1.left == null && cur2.right == null)) { + return false; + } + + // tree1的右节点,tree2的左节点,可以同时不为空,也可以同时为空,否则返回false. + if (cur1.right != null && cur2.left != null) { + s1.push(cur1.right); + s2.push(cur2.left); + } else if (!(cur1.right == null && cur2.left == null)) { + return false; + } + } + + return true; + } +} diff --git a/tree/RecoverTree.java b/tree/RecoverTree.java new file mode 100644 index 0000000..87348ee --- /dev/null +++ b/tree/RecoverTree.java @@ -0,0 +1,70 @@ +package Algorithms.tree; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class RecoverTree { + TreeNode pre = null; + TreeNode first = null; + TreeNode second = null; + + + public void recoverTree(TreeNode root) { + inOrder(root); + + // swap the value of first and second node. + int tmp = first.val; + first.val = second.val; + second.val = tmp; + } + + public void inOrder(TreeNode root) { + if (root == null) { + return; + } + + // inorder traverse. + inOrder(root.left); + + /* + Find the place which the order is wrong. + For example: 1 3 4 6 7 8 10 13 14 + Wrong order: 1 3 8 6 7 4 10 13 14 + FIND: ___ + Then we find: ___ + 8, 6 是错误的序列, 但是,7,4也是错误的序列。 + 因为8,6前面的序列是正确的,所以8,6一定是后面的序列交换来的。 + 而后面的是比较大的数字,也就是说8一定是被交换过来的。而7,4 + 中也应该是小的数字4是前面交换过来的。 + + 用反证法来证明: + 假设:6是后面交换过来的 + 推论: 那么8比6还大,那么8应该也是后面交换来的, + 这样起码有3个错误的数字了 + 而题目是2个错误的数字,得证,只应该是8是交换过来的。 + */ + + // 判断 pre 是否已经设置 + if (pre != null && pre.val > root.val) { + if (first == null) { + // 首次找到反序. + first = pre; + second = root; + } else { + // 第二次找到反序,更新Second. + second = root; + } + } + + pre = root; + + // inorder traverse. + inOrder(root.right); + } +} From a758230b044d1924d4159962bb8897826befe07e Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 7 Oct 2014 20:16:16 -0700 Subject: [PATCH 028/319] isValidBST --- tree/IsValidBST.java | 59 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 tree/IsValidBST.java diff --git a/tree/IsValidBST.java b/tree/IsValidBST.java new file mode 100644 index 0000000..7d47f60 --- /dev/null +++ b/tree/IsValidBST.java @@ -0,0 +1,59 @@ +package Algorithms.tree; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class IsValidBST { + public boolean isValidBST(TreeNode root) { + return isValidBSTHelp(root).isValidBST; + } + + public ReturnType isValidBSTHelp(TreeNode root) { + ReturnType ret = new ReturnType(Integer.MAX_VALUE, Integer.MIN_VALUE, true); + if (root == null) { + return ret; + } + + ReturnType left = isValidBSTHelp(root.left); + ReturnType right = isValidBSTHelp(root.right); + + /* the left tree and the right tree should both be Valid BST. + And the value of the root should be in the middle. + */ + + if (!left.isValidBST + || !right.isValidBST + || left.max >= root.val + || right.min <= root.val + ) { + ret.isValidBST = false; + return ret; + } + + // get the min value of the tree; + ret.min = Math.min(left.min, root.val); + + // get the max value of the tree, consider the right node may be null; + ret.max = Math.max(right.max, root.val); + + return ret; + } + + public class ReturnType { + int min; + int max; + boolean isValidBST; + + ReturnType(int min, int max, boolean isValidBST) { + this.min = min; + this.max = max; + this.isValidBST = isValidBST; + } + } +} \ No newline at end of file From c04d0094c36499bacaf63964d972f89bd3ac9abd Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 7 Oct 2014 21:04:44 -0700 Subject: [PATCH 029/319] in order --- tree/InorderTraversal.java | 76 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 tree/InorderTraversal.java diff --git a/tree/InorderTraversal.java b/tree/InorderTraversal.java new file mode 100644 index 0000000..9774325 --- /dev/null +++ b/tree/InorderTraversal.java @@ -0,0 +1,76 @@ +package Algorithms.tree; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + + +public class InorderTraversal { + public static List inorderTraversal(TreeNode root) { + ArrayList ret = new ArrayList(); + inorderTraversal(root, ret); + return ret; + } + + public static void inorderTraversalRec(TreeNode root, ArrayList ret) { + if (root == null) { + return; + } + + inorderTraversalRec(root.left, ret); + + ret.add(root.val); + + inorderTraversalRec(root.right, ret); + } + + public static void inorderTraversal(TreeNode root, ArrayList ret) { + if (root == null) { + return; + } + + TreeNode cur = root; + Stack s = new Stack(); + + while (true) { + // 因为是inorder,所以要一直先处理左节点,所以我们必须找到最最左边这一个节点, + // 否则是不处理的,也就是一直压栈。 + while (cur != null) { + s.push(cur); + cur = cur.left; + } + + // 如果栈空,表明没有任何需要处理的元素了. + if (s.isEmpty()) { + break; + } + + /* + * 1 + * / \ + * 2 6 + * / \ + * 3 5 + * / + * 4 + * + * 例如:1, 2, 3, 4会入栈。 + * 4,3,2陆续弹出 + * + * 然后会转向2的右节点,5. 5处理完后,会继续弹栈,也就是1. + * 最后处理6. + * + * */ + + // 因为所有的左节点全部已经加入栈中了,开始处理栈顶的元素, + // 或者是右子树是空的,那么弹出一个之前的节点来处理 + cur = s.pop(); + + // 处理当前节点(左节点与根节点 ) + ret.add(cur.val); + + // 处理了左节点与根节点,再处理右子树。 + cur = cur.right; + } + } +} From 32923195d6590ebf18d3871f61a425f57ab61d66 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 7 Oct 2014 22:10:02 -0700 Subject: [PATCH 030/319] tree --- tree/NumTrees.java | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tree/NumTrees.java diff --git a/tree/NumTrees.java b/tree/NumTrees.java new file mode 100644 index 0000000..5f9e245 --- /dev/null +++ b/tree/NumTrees.java @@ -0,0 +1,29 @@ +package Algorithms.tree; + +public class NumTrees { + public int numTrees(int n) { + // cnt[n] = cnt[0]cnt[n - 1] + cnt[1]cnt[n - 2] ... cnt[n - 1]cnt[0] + // cnt[n-1] = cnt[0]cnt[n - 2] + cnt[1]cnt[n - 3] ... cnt[n - 2]cnt[0] + // For example: + // when N = 3, + // cnt[3] = cnt[0]cnt[2] + cnt[1]cnt[1] + cnt[2]cnt[1]; + // so the Formula is : + + // F[n] = ∑ Cnt[j] * cnt[n-j-1] 0<=j<=n-1 + + // base case: + // when n = 0, cnt[0] = 1; + + int[] cnt = new int[n + 1]; + cnt[0] = 1; + + for (int i = 1 ; i <= n; i++) { + cnt[i] = 0; + for (int j = 0; j <= i - 1; j++) { + cnt[i] += cnt[j] * cnt[i - j - 1]; + } + } + + return cnt[n]; + } +} From 8f28a485082dba8fb3b03c079160bac7f973765b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 7 Oct 2014 22:10:46 -0700 Subject: [PATCH 031/319] tree --- tree/NumTrees.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/tree/NumTrees.java b/tree/NumTrees.java index 5f9e245..4f45028 100644 --- a/tree/NumTrees.java +++ b/tree/NumTrees.java @@ -1,7 +1,7 @@ package Algorithms.tree; public class NumTrees { - public int numTrees(int n) { + public int numTrees1(int n) { // cnt[n] = cnt[0]cnt[n - 1] + cnt[1]cnt[n - 2] ... cnt[n - 1]cnt[0] // cnt[n-1] = cnt[0]cnt[n - 2] + cnt[1]cnt[n - 3] ... cnt[n - 2]cnt[0] // For example: @@ -26,4 +26,19 @@ public int numTrees(int n) { return cnt[n]; } -} + + public int numTrees(int n) { + if (n == 0) { + return 1; + } + + // Get the results of all the trees which + // has the root from 1 to n; + int num = 0; + for (int i = 0; i <= n - 1; i++) { + num += numTrees(i) * numTrees(n - 1 - i); + } + + return num; + } +} \ No newline at end of file From 2d0cf85ad815e84a91d919a6c644261c66be1e10 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 8 Oct 2014 00:44:24 -0700 Subject: [PATCH 032/319] minDepth --- tree/MinDepth.java | 108 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 tree/MinDepth.java diff --git a/tree/MinDepth.java b/tree/MinDepth.java new file mode 100644 index 0000000..dc1aeb7 --- /dev/null +++ b/tree/MinDepth.java @@ -0,0 +1,108 @@ +package Algorithms.tree; + +import java.util.LinkedList; +import java.util.Queue; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class MinDepth { + public int minDepth(TreeNode root) { + if (root == null) { + return 0; + } + + return minDepthHelp(root); + } + + /* + * The Recursion Version1: + * */ + public int minDepthRec(TreeNode root) { + if (root == null) { + return 0; + } + + //if there is not left tree, just consider the right tree. + if (root.left == null) { + return minDepthRec(root.right) + 1; + + //if there is not right tree, just consider the left tree. + } else if (root.right == null) { + return minDepthRec(root.left) + 1; + } + + return Math.min(minDepthRec(root.right), minDepthRec(root.left)) + 1; + } + + /* + * The Recursion Version2: + * 这种递归解法更简单。因为在本层递归中不需要考虑左右子树是否为NULL的情况。因为我们直接 + 把 null 设置为返回一个最大值,这样的话,如果出现空子树,它不会影响最小值。但是如果左 + 右均为空,则应返回1(即是仅仅为根节点) + * */ + public int minDepthHelp(TreeNode root) { + if (root == null) { + return Integer.MAX_VALUE; + } + + int min = Math.min(minDepthHelp(root.left), minDepthHelp(root.right)); + if (min == Integer.MAX_VALUE) { + return 1; + } + return min + 1; + } + + /* + * The Iteration Version: + * */ + public int minDepthHelpIterator(TreeNode root) { + if (root == null) { + return 0; + } + + TreeNode dummy = new TreeNode(0); + Queue q = new LinkedList(); + + q.offer(root); + q.offer(dummy); + + //如果一开始就退出,则起码是有根节点。 + int depth = 1; + + while (!q.isEmpty()) { + TreeNode cur = q.poll(); + if (cur == dummy) { + //if queue is not empty, just add a new dummy to the end to sign a new line. + if (!q.isEmpty()) { + q.offer(dummy); + } + //don't deal with the dummynode. + depth++; + continue; + } + + if (cur.left != null) { + q.offer(cur.left); + } + + if (cur.right != null) { + q.offer(cur.right); + } + + //this is a leaf node. + if (cur.left == null && cur.right == null) { + return depth; + } + } + + return 0; + } + +} \ No newline at end of file From dc15508d7673a47fb8583e4b780445825368a392 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 8 Oct 2014 10:52:01 -0700 Subject: [PATCH 033/319] min --- tree/MinDepth.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tree/MinDepth.java b/tree/MinDepth.java index dc1aeb7..b929e2e 100644 --- a/tree/MinDepth.java +++ b/tree/MinDepth.java @@ -46,17 +46,21 @@ public int minDepthRec(TreeNode root) { * 这种递归解法更简单。因为在本层递归中不需要考虑左右子树是否为NULL的情况。因为我们直接 把 null 设置为返回一个最大值,这样的话,如果出现空子树,它不会影响最小值。但是如果左 右均为空,则应返回1(即是仅仅为根节点) + + 而且这种做法更加合理。 因为如果是空树,应该是无法到达才是。这时就应该将值设置为最大。 * */ public int minDepthHelp(TreeNode root) { if (root == null) { return Integer.MAX_VALUE; } - int min = Math.min(minDepthHelp(root.left), minDepthHelp(root.right)); - if (min == Integer.MAX_VALUE) { + // 如果root是叶子节点,直接就可以退出咯。 + if (root.left == null && root.right == null) { return 1; } - return min + 1; + + // root不是叶子节点,输出左右子树的最小值,再加上root本身 + return 1 + Math.min(minDepthHelp(root.left), minDepthHelp(root.right)); } /* From de48d998f6e210e340fdf6d7eecca41cd2ac5e9d Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 8 Oct 2014 14:58:12 -0700 Subject: [PATCH 034/319] facebook --- facebook/SortWeight.java | 115 +++++++++++++++++++++++++++++++++++++++ tree/MinDepth.java | 2 +- 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 facebook/SortWeight.java diff --git a/facebook/SortWeight.java b/facebook/SortWeight.java new file mode 100644 index 0000000..779f466 --- /dev/null +++ b/facebook/SortWeight.java @@ -0,0 +1,115 @@ +package Algorithms.facebook; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; + +public class SortWeight { + public static void main(String[] args) { + String input1 = "crab hotdog 9.0 chicken 9.2 pig 9.2"; + String input2 = "pizza 1 hotdog 2.0"; + String input3 = "pizza 500 hotdog 2.0"; + String input4 = "pizza 500 2.0"; + + LinkedList list1 = sortWeight(input1); + LinkedList list2 = sortWeight(input2); + LinkedList list3 = sortWeight(input3); + LinkedList list4 = sortWeight(input4); + + System.out.println(list1.toString()); + System.out.println(list2.toString()); + System.out.println(list3.toString()); + System.out.println(list4.toString()); + } + + public static LinkedList sortWeight(String input) { + LinkedList ret = new LinkedList(); + if (input == null) { + return ret; + } + + String[] strs = input.split(" "); + + float defautWeight = 5; + + // 当weight = -1,表示这一组食物-重量链还未完成 + String food = null; + float weight = 0; + + // 记录某重量下所有的食物 + HashMap> map = new HashMap>(); + + // Go through the string. + for (String s: strs) { + // 上一次的food-weight对已经结束 + if (weight != -1) { + food = s; + weight = -1; + } else { + float tmp = stringToNumber(s); + // This is a float, so just add a food to the list. + if (tmp != -1) { + weight = tmp; + addFoodToMap(map, food, weight); + } else { + // This is not a float, means that there should be + // a new food. + addFoodToMap(map, food, defautWeight); + + // 开始新一轮的食物-重量链 + food = s; + weight = -1; + } + } + } + + //System.out.println(map.toString()); + + if (weight == -1) { + addFoodToMap(map, food, defautWeight); + } + + ArrayList array = new ArrayList(map.keySet()); + Collections.sort(array); + + for (Float w: array) { + ArrayList foods = map.get(w); + for (String element: foods) { + ret.addFirst(element); + } + } + + return ret; + } + + public static void addFoodToMap(HashMap> map, String food, + float weight) { + // 把上一次的食物-重量终结 + ArrayList list = map.get(weight); + if (list != null) { + // 在相应的重量下添加食物 + list.add(food); + } else { + // 新建一个重量链 + ArrayList listNew = new ArrayList(); + listNew.add(food); + map.put(weight, listNew); + } + } + + // when it is not a float, return -1; + public static float stringToNumber(String cur) { + float result = -1; + + try { + result = Float.parseFloat(cur); + } catch (NumberFormatException e) { + result = -1; + } + + return result; + } +} diff --git a/tree/MinDepth.java b/tree/MinDepth.java index b929e2e..ad0afbc 100644 --- a/tree/MinDepth.java +++ b/tree/MinDepth.java @@ -47,7 +47,7 @@ public int minDepthRec(TreeNode root) { 把 null 设置为返回一个最大值,这样的话,如果出现空子树,它不会影响最小值。但是如果左 右均为空,则应返回1(即是仅仅为根节点) - 而且这种做法更加合理。 因为如果是空树,应该是无法到达才是。这时就应该将值设置为最大。 + 而且这种做法更加合理。 因为如果是空树,应该是无法到达才是。这时就应该将值设置为最大。 * */ public int minDepthHelp(TreeNode root) { if (root == null) { From 72f914daab2fd9e2eb8a63e4643297d78d4fadaa Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 8 Oct 2014 20:29:37 -0700 Subject: [PATCH 035/319] Unique BSTs --- tree/GenerateTree2.java | 70 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 tree/GenerateTree2.java diff --git a/tree/GenerateTree2.java b/tree/GenerateTree2.java new file mode 100644 index 0000000..16eb9ed --- /dev/null +++ b/tree/GenerateTree2.java @@ -0,0 +1,70 @@ +package Algorithms.tree; + +import java.util.ArrayList; +import java.util.List; +/* + * Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. + +For example, +Given n = 3, your program should return all 5 unique BST's shown below. + + 1 3 3 2 1 + \ / / / \ \ + 3 2 1 1 3 2 + / / \ \ + 2 1 2 3 +confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ. + * */ + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; left = null; right = null; } + * } + */ +public class GenerateTree2 { + public List generateTrees(int n) { + return generateTreesHelp(1, n); + } + + /* + 使用递归来完成,我们可以分解为2个步骤: + 完成左子树,完成右子树。 + + 如果说左子树有n种组合,右子树有m种组合,那最终的组合数就是n*m. 把这所有的组合组装起来即可 + */ + public List generateTreesHelp(int start, int end) { + ArrayList ret = new ArrayList(); + + // null也是一种解,也需要把它加上去。这样在组装左右子树的时候,不会出现左边没有解的情况,或 + // 是右边没有解的情况 + if (start > end) { + ret.add(null); + return ret; + } + + for (int i = start; i <= end; i++) { + // 求出左右子树的所有的可能。 + List left = generateTreesHelp(start, i - 1); + List right = generateTreesHelp(i + 1, end); + + // 将左右子树的所有的可能性全部组装起来 + for (TreeNode l: left) { + for(TreeNode r: right) { + // 先创建根节点 + TreeNode root = new TreeNode(i); + root.left = l; + root.right = r; + + // 将组合出来的树加到结果集合中。 + ret.add(root); + } + } + } + + return ret; + } +} From d92fcd1c5ba2eaabd7129351d76347ede50df5e2 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 8 Oct 2014 21:29:54 -0700 Subject: [PATCH 036/319] tree2 --- facebook/SortWeight.java | 89 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 84 insertions(+), 5 deletions(-) diff --git a/facebook/SortWeight.java b/facebook/SortWeight.java index 779f466..7172043 100644 --- a/facebook/SortWeight.java +++ b/facebook/SortWeight.java @@ -3,7 +3,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; @@ -14,10 +13,10 @@ public static void main(String[] args) { String input3 = "pizza 500 hotdog 2.0"; String input4 = "pizza 500 2.0"; - LinkedList list1 = sortWeight(input1); - LinkedList list2 = sortWeight(input2); - LinkedList list3 = sortWeight(input3); - LinkedList list4 = sortWeight(input4); + LinkedList list1 = sortWeight2(input1); + LinkedList list2 = sortWeight2(input2); + LinkedList list3 = sortWeight2(input3); + LinkedList list4 = sortWeight2(input4); System.out.println(list1.toString()); System.out.println(list2.toString()); @@ -85,6 +84,86 @@ public static LinkedList sortWeight(String input) { return ret; } + public static class Pair implements Comparable { + String food; + float weight; + + Pair (String food, float weight) { + this.food = food; + this.weight = weight; + } + + // 注意,我们用o来减当前的重量,就能得到降序的排列 + public int compareTo(Pair o) { + if (o.weight - this.weight < 0) { + return -1; + } + + return 1; + } + } + + /* + * 使用自定义结构体 Pair而不是hashmap来记录食物-重量对。可以简化算法。 + * 但这时就需要自定义一个compareTo方法 + * */ + public static LinkedList sortWeight2(String input) { + LinkedList ret = new LinkedList(); + if (input == null) { + return ret; + } + + String[] strs = input.split(" "); + + float defautWeight = 5; + + // 当weight = -1,表示这一组食物-重量链还未完成 + String food = null; + float weight = 0; + + // 使用ArrayList来记录食物-重量对 + ArrayList list = new ArrayList(); + + // Go through the string. + for (String s: strs) { + // 上一次的food-weight对已经结束 + if (weight != -1) { + food = s; + weight = -1; + } else { + float tmp = stringToNumber(s); + // This is a float, so just add a food to the list. + if (tmp != -1) { + weight = tmp; + list.add(new Pair(food, weight)); + } else { + // This is not a float, means that there should be + // a new food. + list.add(new Pair(food, defautWeight)); + + // 开始新一轮的食物-重量链 + food = s; + weight = -1; + } + } + } + + //System.out.println(map.toString()); + + if (weight == -1) { + list.add(new Pair(food, defautWeight)); + } + + Collections.sort(list); + Iterator iter = list.iterator(); + while (iter.hasNext()) { + ret.add(iter.next().food); + } + + return ret; + } + + public static void addFoodToMap(HashMap> map, String food, float weight) { // 把上一次的食物-重量终结 From 632666f85c761a93efac2608a1a3b82287929e15 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 8 Oct 2014 22:36:20 -0700 Subject: [PATCH 037/319] merge Sort --- sort/MergeSort_LinkedList.java | 99 ++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 sort/MergeSort_LinkedList.java diff --git a/sort/MergeSort_LinkedList.java b/sort/MergeSort_LinkedList.java new file mode 100644 index 0000000..9fde42d --- /dev/null +++ b/sort/MergeSort_LinkedList.java @@ -0,0 +1,99 @@ +package Algorithms.sort; + +import java.util.LinkedList; + +import Algorithms.ListNode; + +public class MergeSort_LinkedList { + public static void main(String[] args) { + ListNode node1 = new ListNode(0); + ListNode node2 = new ListNode(15); + ListNode node3 = new ListNode(6); + ListNode node4 = new ListNode(9); + ListNode node5 = new ListNode(4); + + node1.next = node2; + node2.next = node3; + node3.next = node4; + node4.next = node5; + + System.out.println(node1.toString()); + sort(node1); + System.out.println(node1.toString()); + } + + public static ListNode sort(ListNode head) { + if (head == null) { + return null; + } + + // 注意一定要加这一行,否则会不断对1个元素无限分下去 + if (head.next == null) { + return head; + } + + ListNode mid = findMidPre(head); + + // 将list切为2个list. + ListNode right = mid.next; + mid.next = null; + + //调用将2边分别排序 + ListNode left = sort(head); + right = sort(right); + + // 将2个已经排序的List Merge在一起 + return merge(left, right); + } + + public static ListNode merge(ListNode head1, ListNode head2) { + ListNode dummy = new ListNode(0); + + // cur 表示新链的尾部. + ListNode cur = dummy; + + while (head1 != null && head2 != null) { + // 将2个链中较小的一个接到新链的尾部 + if (head1.val < head2.val) { + cur.next = head1; + head1 = head1.next; + } else { + cur.next = head2; + head2 = head2.next; + } + + // 将扫描指针移动到新链的尾部0 + cur = cur.next; + } + + // 把未扫描完毕的链接在新链的结尾即可 + if (head1 != null) { + cur.next = head1; + } else { + cur.next = head2; + } + + // 返回新链的头部 + return dummy.next; + } + + // 这个函数是寻找Mid的前一个节点, + // 技巧就是:一开始就将Fast放在head的前一个节点,这样当只有2个节点的时候: + // 1->2->null + // slow 会停在1处 ,这样就可以处理只有2个节点的情况. + public static ListNode findMidPre(ListNode head) { + if (head == null) { + return null; + } + + ListNode fast = head.next; + ListNode slow = head; + + if (fast != null && fast.next != null) { + fast = fast.next.next; + slow = slow.next; + } + + return slow; + } +} From d1c27bdba5d7b17574b3e26d35e6dfd6591dbf05 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 9 Oct 2014 00:40:30 -0700 Subject: [PATCH 038/319] merge --- array/MaxProduct.java | 33 +++++++++++++++++++++++++++++++++ array/MergeSortedArray.java | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 array/MaxProduct.java create mode 100644 array/MergeSortedArray.java diff --git a/array/MaxProduct.java b/array/MaxProduct.java new file mode 100644 index 0000000..65f10d3 --- /dev/null +++ b/array/MaxProduct.java @@ -0,0 +1,33 @@ +package Algorithms.array; + +public class MaxProduct { + public static int maxProduct(int[] A) { + int max = 0; + + int left = 0; + int right = 0; + + int len = A.length; + + int product = 1; + + for (int i = 0; i < len; i++) { + if (A[i] <= 0) { + max = Math.max(max, product); + product = 1; + } + product *= A[i]; + } + + return 0; + } + + /* + * 作法是找到连续的正数,不断相乘即可。 + * */ + public static void main(String[] strs) { + int[] A = {2, 3, -2, 4}; + + System.out.println(maxProduct(A)); + } +} diff --git a/array/MergeSortedArray.java b/array/MergeSortedArray.java new file mode 100644 index 0000000..aea7ae7 --- /dev/null +++ b/array/MergeSortedArray.java @@ -0,0 +1,33 @@ +package Algorithms.array; + +public class MergeSortedArray { + public void merge(int A[], int m, int B[], int n) { + int cur = m + n - 1; + + // 指向A的尾部 + int pA = m - 1; + + // 指向B的尾部 + int pB = n - 1; + + while (cur >= 0) { + if (pA < 0 || pB < 0) { + break; + } + + // 从尾部往前比较 + if (A[pA] > B[pB]) { + A[cur] = A[pA--]; + } else { + A[cur] = B[pB--]; + } + + cur--; + } + + // copy the left over elements in B to A. + System.arraycopy(B, 0, A, 0, pB + 1); + + return; + } +} From ec77e43960719d2659c7236799df1b44385389ba Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 9 Oct 2014 00:56:10 -0700 Subject: [PATCH 039/319] remove duplicate --- array/MaxProduct.java | 9 ++++----- array/RemoveDuplicates.java | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 array/RemoveDuplicates.java diff --git a/array/MaxProduct.java b/array/MaxProduct.java index 65f10d3..fc6401f 100644 --- a/array/MaxProduct.java +++ b/array/MaxProduct.java @@ -3,10 +3,7 @@ public class MaxProduct { public static int maxProduct(int[] A) { int max = 0; - - int left = 0; - int right = 0; - + int len = A.length; int product = 1; @@ -15,11 +12,13 @@ public static int maxProduct(int[] A) { if (A[i] <= 0) { max = Math.max(max, product); product = 1; + continue; } + product *= A[i]; } - return 0; + return max; } /* diff --git a/array/RemoveDuplicates.java b/array/RemoveDuplicates.java new file mode 100644 index 0000000..60e54c4 --- /dev/null +++ b/array/RemoveDuplicates.java @@ -0,0 +1,20 @@ +package Algorithms.array; + +public class RemoveDuplicates { + public int removeDuplicates(int[] A) { + if (A == null || A.length == 0) { + return 0; + } + + // A里至少有1个元素 + int len = 1; + + for (int i = 1; i < A.length; i++) { + if (A[i] != A[i - 1]) { + A[len++] = A[i]; + } + } + + return len; + } +} From 127db30ac10a7be7573979fd50b6e9e2bcdd3ba6 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 9 Oct 2014 01:21:32 -0700 Subject: [PATCH 040/319] remove duplicates2 --- array/RemoveDuplicates2.java | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 array/RemoveDuplicates2.java diff --git a/array/RemoveDuplicates2.java b/array/RemoveDuplicates2.java new file mode 100644 index 0000000..2bbb24f --- /dev/null +++ b/array/RemoveDuplicates2.java @@ -0,0 +1,42 @@ +package Algorithms.array; + +public class RemoveDuplicates2 { + public static int removeDuplicates(int[] A) { + if (A == null) { + return 0; + } + + if (A.length <= 1) { + return A.length; + } + + int len = 1; + + // 拷贝2次后就不再拷贝 + boolean canCopy = true; + + for (int i = 1; i < A.length; i++) { + if (A[i] == A[i - 1]) { + if (!canCopy) { + continue; + } + canCopy = false; + } else { + canCopy = true; + } + + A[len++] = A[i]; + } + + return len; + } + + public static void main(String[] strs) { + int[] A = {1,1,1,2,2,3}; + removeDuplicates(A); + + for (int i: A) { + System.out.print(i + " "); + } + } +} From 63dd8d0efa034cadabd5ade0c86984c80c25e372 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 9 Oct 2014 02:28:46 -0700 Subject: [PATCH 041/319] array --- array/SearchInRotatedSortedArray.java | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 array/SearchInRotatedSortedArray.java diff --git a/array/SearchInRotatedSortedArray.java b/array/SearchInRotatedSortedArray.java new file mode 100644 index 0000000..530e50e --- /dev/null +++ b/array/SearchInRotatedSortedArray.java @@ -0,0 +1,40 @@ +package Algorithms.array; + +public class SearchInRotatedSortedArray { + public int search(int[] A, int target) { + if (A == null || A.length == 0) { + return -1; + } + + int left = 0; + int right = A.length - 1; + + while (left <= right) { + int mid = left + (right - left) / 2; + if (A[mid] == target) { + return mid; + } + + // the left side is sorted. + if (A[mid] >= A[left]) { + if (target <= A[mid] && target >= A[left]) { + // target is in the left side. + right = mid - 1; + } else { + // target is in the right side. + left = mid + 1; + } + } else { // the right side is sorted. + if (target >= A[mid] && target <= A[right]) { + // target is in the right side. + left = mid + 1; + } else { + // target is in the right side. + right = mid - 1; + } + } + } + + return -1; + } +} From 23f07e334f71188d03b52362791784d4411e8af9 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 9 Oct 2014 10:58:30 -0700 Subject: [PATCH 042/319] search --- array/SearchInRotatedSortedArray2.java | 60 ++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 array/SearchInRotatedSortedArray2.java diff --git a/array/SearchInRotatedSortedArray2.java b/array/SearchInRotatedSortedArray2.java new file mode 100644 index 0000000..4cb650e --- /dev/null +++ b/array/SearchInRotatedSortedArray2.java @@ -0,0 +1,60 @@ +package Algorithms.array; + +/* + * https://oj.leetcode.com/problems/search-in-rotated-sorted-array-ii/ + * + * Search in Rotated Sorted Array II Total Accepted: 18427 Total Submissions: 59728 My Submissions +Follow up for "Search in Rotated Sorted Array": +What if duplicates are allowed? + +Would this affect the run-time complexity? How and why? + +Write a function to determine if a given target is in the array. + * */ +public class SearchInRotatedSortedArray2 { + /* + In this function, the complex may go to O(n). It depents on how many duplicates exit in the array. + if there are M duplicates, the complexity may be O(logN + M). + */ + public boolean search(int[] A, int target) { + if (A == null || A.length == 0) { + return false; + } + + // setup two point to the left and right of the array. + int l = 0, r = A.length - 1; + while (l <= r) { + // get the mid point. + int mid = l + (r - l)/2; + if (target == A[mid]) { + return true; + } + + if (A[mid] > A[l]) { + // the left side is sorted. + if (target <= A[mid] && target >= A[l]) { + // target is in the left side. + r = mid - 1; + } else { + l = mid + 1; + } + } else if (A[mid] < A[l]) { + // the right side is sorted. + if (target <= A[r] && target >= A[mid]) { + // target is in the right side. + l = mid + 1; + } else { + r = mid - 1; + } + } else { + // when A[mid] == A[l], we can't determin, just move the + // left point one + l++; + } + } + + return false; + } + + +} From bd027087d5a4ee7a93fdc37bc03020af6ae6aabc Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 9 Oct 2014 11:57:47 -0700 Subject: [PATCH 043/319] maxSubArray --- array/MaxSubArray.java | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 array/MaxSubArray.java diff --git a/array/MaxSubArray.java b/array/MaxSubArray.java new file mode 100644 index 0000000..ea36db6 --- /dev/null +++ b/array/MaxSubArray.java @@ -0,0 +1,26 @@ +package Algorithms.array; + +public class MaxSubArray { + public int maxSubArray(int[] A) { + if (A == null || A.length == 0) { + return 0; + } + + int len = A.length; + int sum = 0; + + // 记录下最大值 + int max = Integer.MIN_VALUE; + for (int i = 0; i < len; i++) { + // 加上当前值 + sum += A[i]; + max = Math.max(max, sum); + + // 如果和小于0,则可以丢弃之,下一个值重新计算即可。 + // 因为对于每一个值来说,有2处选择:加上前面的一些数,或是不加。如果是负数,可以不加。 + sum = Math.max(0, sum); + } + + return max; + } +} From 88a4d501eeb901b667e18ad7b48cadc812d12b9b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 9 Oct 2014 12:16:21 -0700 Subject: [PATCH 044/319] the merge --- list/MergeTwoLists.java | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 list/MergeTwoLists.java diff --git a/list/MergeTwoLists.java b/list/MergeTwoLists.java new file mode 100644 index 0000000..7eac1e1 --- /dev/null +++ b/list/MergeTwoLists.java @@ -0,0 +1,33 @@ +package Algorithms.list; + +import Algorithms.ListNode; + +public class MergeTwoLists { + public ListNode mergeTwoLists(ListNode l1, ListNode l2) { + if (l1 == null && l2 == null) { + return null; + } + + ListNode dummy = new ListNode(0); + ListNode cur = dummy; + while (l1 != null && l2 != null) { + if (l1.val < l2.val) { + cur.next = l1; + l1 = l1.next; + } else { + cur.next = l2; + l2 = l2.next; + } + + cur = cur.next; + } + + if (l1 != null) { + cur.next = l1; + } else { + cur.next = l2; + } + + return dummy.next; + } +} From 0ccff33fd4f4fdc32a1b879f0977b2cd8f246867 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 9 Oct 2014 21:30:45 -0700 Subject: [PATCH 045/319] strstr --- string/StrStr.java | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 string/StrStr.java diff --git a/string/StrStr.java b/string/StrStr.java new file mode 100644 index 0000000..cd04196 --- /dev/null +++ b/string/StrStr.java @@ -0,0 +1,33 @@ +package Algorithms.string; + +public class StrStr { + public String strStr(String haystack, String needle) { + if (haystack == null || needle == null) { + return null; + } + + int len1 = haystack.length(); + int len2 = needle.length(); + + // Pay attention. if find "pl" in "apple", then len1 = 5, len2 = 2, the + // i should <= 3. + // so it should be i <= len1 - len2; + for (int i = 0; i <= len1 - len2; i++) { + int j = 0; + for (; j < len2; j++) { + if (haystack.charAt(i + j) != needle.charAt(j)) { + break; + } + } + + // j goes to the end, it means that the loop never break. That means + // found the needle. + if (j == len2) { + return haystack.substring(i); + } + } + + // didn't find the needle. + return null; + } +} \ No newline at end of file From 096b7439eb9d191975c45b55e514be99b9956a9a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 9 Oct 2014 22:23:40 -0700 Subject: [PATCH 046/319] list --- list/DeleteDuplicates.java | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 list/DeleteDuplicates.java diff --git a/list/DeleteDuplicates.java b/list/DeleteDuplicates.java new file mode 100644 index 0000000..6ddc921 --- /dev/null +++ b/list/DeleteDuplicates.java @@ -0,0 +1,40 @@ +package Algorithms.list; + +import Algorithms.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class DeleteDuplicates { + public ListNode deleteDuplicates(ListNode head) { + if (head == null) { + return null; + } + + ListNode dummy = new ListNode(0); + dummy.next = head; + + ListNode cur = dummy; + + while (cur != null) { + if (cur.next != null + && cur.next.next != null + && cur.next.val == cur.next.next.val) { + // remove cur.next; + cur.next = cur.next.next; + } else { + cur = cur.next; + } + } + + return dummy.next; + } +} \ No newline at end of file From d955d59d7c907dfa98fc8db5d6851e41f652ad86 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 9 Oct 2014 23:04:30 -0700 Subject: [PATCH 047/319] divide --- Divide2/Pow.java | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 Divide2/Pow.java diff --git a/Divide2/Pow.java b/Divide2/Pow.java new file mode 100644 index 0000000..d9eebb5 --- /dev/null +++ b/Divide2/Pow.java @@ -0,0 +1,34 @@ +package Algorithms.Divide2; + +public class Pow { + public double pow(double x, int n) { + if (x == 0) { + return 0; + } + + if (n == 0) { + return 1; + } + + // should consider the case when n is below zero. + boolean minus = false; + if (n < 0) { + minus = true; + n = -n; + } + + int m = n%2; + + // count + double ret = pow(x, n/2); + ret *= ret; + if (m == 1) { + ret *= x; + } + + if (minus) { + return 1/ret; + } + return ret; + } +} \ No newline at end of file From 218d63f6bd55431a219d1c3603df522e8e94b1d4 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 9 Oct 2014 23:34:11 -0700 Subject: [PATCH 048/319] pow --- Divide2/Pow.java | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Divide2/Pow.java b/Divide2/Pow.java index d9eebb5..eaebb53 100644 --- a/Divide2/Pow.java +++ b/Divide2/Pow.java @@ -6,11 +6,28 @@ public double pow(double x, int n) { return 0; } - if (n == 0) { + if (x == 1 || n == 0) { return 1; } - // should consider the case when n is below zero. + if (x == -1) { + int left = Math.abs(n)%2; + if (left == 1) { + return -1; + } else { + return 1; + } + } + + // 注意 这样写是不行的,因为-n在n到最小值会出错, + // int的最小值(负数)取-n仍然是n 这样就错了。 + + // if (n < 0) { + // double ret1 = pow(x, -n); + // return 1/(double)ret1; + // } + + //should consider the case when n is below zero. boolean minus = false; if (n < 0) { minus = true; From 4f99b2df5e9c54d7b80ba7e22fa8b8c8e815f8f2 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 9 Oct 2014 23:49:30 -0700 Subject: [PATCH 049/319] pow --- Divide2/Pow.java | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/Divide2/Pow.java b/Divide2/Pow.java index eaebb53..3105b69 100644 --- a/Divide2/Pow.java +++ b/Divide2/Pow.java @@ -1,7 +1,12 @@ package Algorithms.Divide2; public class Pow { - public double pow(double x, int n) { + public static void main(String[] strs) { + System.out.println(pow(-3, -2147483648)); + + } + + public static double pow(double x, int n) { if (x == 0) { return 0; } @@ -10,28 +15,13 @@ public double pow(double x, int n) { return 1; } - if (x == -1) { - int left = Math.abs(n)%2; - if (left == 1) { - return -1; - } else { - return 1; - } - } - + // Because when we deal with -2147483648, we can't get right -n + // cause -n == n when it is -2147483648. // 注意 这样写是不行的,因为-n在n到最小值会出错, // int的最小值(负数)取-n仍然是n 这样就错了。 - - // if (n < 0) { - // double ret1 = pow(x, -n); - // return 1/(double)ret1; - // } - - //should consider the case when n is below zero. - boolean minus = false; if (n < 0) { - minus = true; - n = -n; + double ret1 = x * pow(x, -(1 + n)); + return 1/(double)ret1; } int m = n%2; @@ -43,9 +33,6 @@ public double pow(double x, int n) { ret *= x; } - if (minus) { - return 1/ret; - } return ret; } } \ No newline at end of file From 7564463efb17523a23ea8d816a44cdac10a4c505 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 10 Oct 2014 00:39:59 -0700 Subject: [PATCH 050/319] list --- sort/SortList_leetCode.java | 79 +++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 sort/SortList_leetCode.java diff --git a/sort/SortList_leetCode.java b/sort/SortList_leetCode.java new file mode 100644 index 0000000..f4f31d3 --- /dev/null +++ b/sort/SortList_leetCode.java @@ -0,0 +1,79 @@ +package Algorithms.sort; + +import Algorithms.ListNode; + +/** + * Definition for singly-linked list. + * class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class SortList_leetCode { + public ListNode sortList(ListNode head) { + if (head == null) { + return null; + } + + // !! Remember to add this line! Because this may cause infinit loop. + if (head.next == null) { + return head; + } + + ListNode midPre = findmidPre(head); + + ListNode right = sortList(midPre.next); + midPre.next = null; + + ListNode left = sortList(head); + + return merge(left, right); + } + + // get the node before mid. + public ListNode findmidPre(ListNode head) { + if (head == null) { + return null; + } + + ListNode slow = head; + ListNode fast = head.next; + + while (fast != null && fast.next != null) { + fast = fast.next.next; + slow = slow.next; + } + + return slow; + } + + // get the node before mid. + public ListNode merge(ListNode h1, ListNode h2) { + ListNode dummy = new ListNode(0); + + ListNode cur = dummy; + while (h1 != null && h2 != null) { + if (h1.val < h2.val) { + cur.next = h1; + h1 = h1.next; + } else { + cur.next = h2; + h2 = h2.next; + } + + cur = cur.next; + } + + if (h1 != null) { + cur.next = h1; + } else { + cur.next = h2; + } + + return dummy.next; + } +} \ No newline at end of file From 1ddacc55917a7b77ca6a12a03cea0d7b12b72143 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 10 Oct 2014 01:26:55 -0700 Subject: [PATCH 051/319] sort --- sort/InsertionSortList.java | 51 +++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 sort/InsertionSortList.java diff --git a/sort/InsertionSortList.java b/sort/InsertionSortList.java new file mode 100644 index 0000000..fe368bd --- /dev/null +++ b/sort/InsertionSortList.java @@ -0,0 +1,51 @@ +package Algorithms.sort; + +import Algorithms.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class InsertionSortList { + public ListNode insertionSortList(ListNode head) { + // 使用dummynode来记录新的头节点,每次把旧链找合适的位置来插入即可 + if (head == null) { + return null; + } + + ListNode dummy = new ListNode(0); + + // 记录下插入位置的前趋节点. + ListNode pre = dummy; + + while (head != null) { + // every time we should reset the pre to the BEGIN OF THE LIST. + pre = dummy; + + // 这样可以找到pre.next为第一个比head大的节点 + // if we use <= here we can keep the Algorithm stable. + while (pre.next != null && pre.next.val <= head.val) { + pre = pre.next; + } + + // backup the next node of head; + ListNode tmp = head.next; + + // Insert the head between PRE and PRE.next. + head.next = pre.next; + pre.next = head; + + // set head to the next node. + head = tmp; + } + + return dummy.next; + } +} \ No newline at end of file From d5573fc6b1d3c364929c12257463c95367bcf899 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 10 Oct 2014 01:59:45 -0700 Subject: [PATCH 052/319] reorder list --- list/ReorderList.java | 109 ++++++++++++++++++++++++++++++++++++ sort/InsertionSortList.java | 2 +- 2 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 list/ReorderList.java diff --git a/list/ReorderList.java b/list/ReorderList.java new file mode 100644 index 0000000..6ec1e93 --- /dev/null +++ b/list/ReorderList.java @@ -0,0 +1,109 @@ +package Algorithms.list; + +import Algorithms.ListNode; + +/** + * Definition for singly-linked list. + * class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class ReorderList { + public void reorderList(ListNode head) { + // 4 STEP: + // 1. find the mid. + // 2. cut the list to two list. + // 3. REVERSE the right side. + // 4. MERGE the two list. + if (head == null) { + return; + } else if (head.next == null) { + return; + } + + ListNode pre = findMidPre(head); + + // cut the two list. + ListNode right = pre.next; + pre.next = null; + + // reverse the right link. + right = reverse(right); + + merge(head, right); + } + + // 找到mid的前一个节点 + // EXAMPLE: 1-> 4-> 2-> null + // 我们要找的是1. + // 这样可以把它断开为2个链:1->null and 4->2->null + // 这样做的是因为比如1->4->null + // 我们只能找1,如果你找到的是4,你是不能断开为2个的。 + // 对于这个题目可能无所谓,但是对于merge sort你不能分开2个节点就不能工作. + public ListNode findMidPre(ListNode head) { + if (head == null) { + return null; + } + + ListNode slow = head; + ListNode fast = head.next; + + while (fast != null && fast.next != null) { + fast = fast.next.next; + slow = slow.next; + } + + return slow; + } + + // reverse the linked list. + public ListNode reverse(ListNode head) { + if (head == null) { + return null; + } + + ListNode dummy = new ListNode(0); + while (head != null) { + // store the next node. + ListNode tmp = head.next; + + // insert the head into the head! + head.next = dummy.next; + dummy.next = head; + + head = tmp; + } + + return dummy.next; + } + + // merge head1 and head 2 one by one. + public void merge(ListNode head1, ListNode head2) { + ListNode dummy = new ListNode(0); + + ListNode cur = dummy; + + while (head1 != null && head2 != null) { + // 注意这里容易出错。head1要先指向它的下一个,再处理head2,否则cur.next=head2这里会改掉 + // head1的指向. + cur.next = head1; + cur = cur.next; + head1 = head1.next; + + cur.next = head2; + cur = cur.next; + head2 = head2.next; + } + + if (head1 != null) { + cur.next = head1; + } else { + cur.next = head2; + } + } +} \ No newline at end of file diff --git a/sort/InsertionSortList.java b/sort/InsertionSortList.java index fe368bd..7a36b62 100644 --- a/sort/InsertionSortList.java +++ b/sort/InsertionSortList.java @@ -15,7 +15,7 @@ */ public class InsertionSortList { public ListNode insertionSortList(ListNode head) { - // 使用dummynode来记录新的头节点,每次把旧链找合适的位置来插入即可 + // 使用dummy node来记录新的头节点,每次把旧链找合适的位置来插入即可 if (head == null) { return null; } From c144ac6620000dd673b8570fe793f581a5485078 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 10 Oct 2014 02:50:18 -0700 Subject: [PATCH 053/319] random --- list/CopyRandomList.java | 69 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 list/CopyRandomList.java diff --git a/list/CopyRandomList.java b/list/CopyRandomList.java new file mode 100644 index 0000000..499bd84 --- /dev/null +++ b/list/CopyRandomList.java @@ -0,0 +1,69 @@ +package Algorithms.list; + +/** + * Definition for singly-linked list with a random pointer. + * class RandomListNode { + * int label; + * RandomListNode next, random; + * RandomListNode(int x) { this.label = x; } + * }; + */ +public class CopyRandomList { + public static class RandomListNode { + int label; + RandomListNode next, random; + + RandomListNode(int x) { + this.label = x; + } + } + + public static void main(String[] strs) { + RandomListNode node = new RandomListNode(-1); + RandomListNode copy = copyRandomList(node); + } + + public static RandomListNode copyRandomList(RandomListNode head) { + if (head == null) { + return null; + } + + // copy the list; + RandomListNode cur = head; + while (cur != null) { + RandomListNode nodeCopy = new RandomListNode(cur.label); + + // insert the node between the old link. + nodeCopy.next = cur.next; + cur.next = nodeCopy; + + cur = cur.next.next; + } + + // copy the radom list. + cur = head; + while (cur != null) { + cur.next.random = cur.random; + cur = cur.next.next; + } + + // divide the two list. + RandomListNode headCopy = head.next; + cur = head; + + // track the new list. + RandomListNode curNew = headCopy; + while (cur != null) { + cur.next = cur.next.next; + cur = cur.next; + + if (curNew.next != null) { + curNew.next = curNew.next.next; + curNew = curNew.next; + } + + } + + return curNew; + } +} From 2a37fec11cac6630347afc9304a65470b3fcadf6 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 10 Oct 2014 03:37:28 -0700 Subject: [PATCH 054/319] reverse2 --- list/ReverseBetween.java | 49 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 list/ReverseBetween.java diff --git a/list/ReverseBetween.java b/list/ReverseBetween.java new file mode 100644 index 0000000..790c197 --- /dev/null +++ b/list/ReverseBetween.java @@ -0,0 +1,49 @@ +package Algorithms.list; + +import Algorithms.ListNode; + +public class ReverseBetween { + public ListNode reverseBetween(ListNode head, int m, int n) { + if (head == null || head.next == null) { + return head; + } + + if (m >= n) { + return head; + } + + ListNode dummy = new ListNode(0); + dummy.next = head; + + ListNode pre = dummy; + + //1. get the pre node before m. + for (int i = m; i > 1; i--) { + pre = pre.next; + } + + // record the tail of the reversed link. + ListNode reverseTail = pre.next; + pre.next = null; + + // reverse the link. + ListNode cur = reverseTail; + + for (int i = n - m + 1; i > 0; i--) { + if (i == 1) { + // 这里是翻转段后的第一个元素 . + reverseTail.next = cur.next; + } + + ListNode tmp = cur.next; + + cur.next = pre.next; + pre.next = cur; + + cur = tmp; + } + + return dummy.next; + } + +} From 150f920da0cd4ae6ec8f8f888db294466815f23a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 10 Oct 2014 04:05:18 -0700 Subject: [PATCH 055/319] tree --- tree/hasPathSum.java | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tree/hasPathSum.java diff --git a/tree/hasPathSum.java b/tree/hasPathSum.java new file mode 100644 index 0000000..d61d9b3 --- /dev/null +++ b/tree/hasPathSum.java @@ -0,0 +1,20 @@ +package Algorithms.tree; + +public class hasPathSum { + /** + * Definition for binary tree public class TreeNode { int val; TreeNode + * left; TreeNode right; TreeNode(int x) { val = x; } } + */ + public boolean hasPathSum(TreeNode root, int sum) { + if (root == null) { + return false; + } + + if (root.left == null && root.right == null && sum == root.val) { + return true; + } + + return hasPathSum(root.left, sum - root.val) + || hasPathSum(root.right, sum - root.val); + } +} From 82143ad9acbf6c02964b7a77cb0879f81cec6d0a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 10 Oct 2014 04:06:29 -0700 Subject: [PATCH 056/319] name --- tree/hasPathSum.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tree/hasPathSum.java b/tree/hasPathSum.java index d61d9b3..d4c42ba 100644 --- a/tree/hasPathSum.java +++ b/tree/hasPathSum.java @@ -1,6 +1,6 @@ package Algorithms.tree; -public class hasPathSum { +public class HasPathSum { /** * Definition for binary tree public class TreeNode { int val; TreeNode * left; TreeNode right; TreeNode(int x) { val = x; } } From f08140a11ccdd41ec0be88453af9c963a6e7d8a5 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 10 Oct 2014 23:20:53 -0700 Subject: [PATCH 057/319] lett --- dfs/LetterCombinations.java | 86 ++++++++++++++++++++++++++++++++++++ dfs/LetterCombinations2.java | 53 ++++++++++++++++++++++ dp/Fibonacci.java | 23 ++++++++-- 3 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 dfs/LetterCombinations.java create mode 100644 dfs/LetterCombinations2.java diff --git a/dfs/LetterCombinations.java b/dfs/LetterCombinations.java new file mode 100644 index 0000000..f70414c --- /dev/null +++ b/dfs/LetterCombinations.java @@ -0,0 +1,86 @@ +package Algorithms.dfs; + +import java.util.ArrayList; +import java.util.List; + +public class LetterCombinations { + public List letterCombinations(String digits) { + List ret = new ArrayList(); + ArrayList path = new ArrayList(); + + letterCombinationsHelp(digits, path, ret, 0); + + return ret; + } + + /* + 表示从digit的index处开始直到结尾的数字对应的字符的组合数 + */ + public void letterCombinationsHelp(String digits, ArrayList path, List ret, int index) { + if (digits == null) { + return; + } + + int len = digits.length(); + if (path.size() == len) { + StringBuilder sb = new StringBuilder(); + for (char c: path) { + sb.append(c); + } + ret.add(sb.toString()); + return; + } + + List chars = getChar(digits.charAt(index)); + + for (int i = 0; i < chars.size(); i++) { + path.add(chars.get(i)); + letterCombinationsHelp(digits, path, ret, index + 1); + path.remove(path.size() - 1); + } + } + + public List getChar(char c) { + ArrayList list = new ArrayList(); + + if (c == '1') { + return list; + } else if (c == '2') { + list.add('a'); + list.add('b'); + list.add('c'); + } else if (c == '3') { + list.add('d'); + list.add('e'); + list.add('f'); + } else if (c == '4') { + list.add('g'); + list.add('h'); + list.add('i'); + } else if (c == '5') { + list.add('j'); + list.add('k'); + list.add('l'); + } else if (c == '6') { + list.add('m'); + list.add('n'); + list.add('o'); + } else if (c == '7') { + list.add('p'); + list.add('q'); + list.add('r'); + list.add('s'); + } else if (c == '8') { + list.add('t'); + list.add('u'); + list.add('v'); + } else if (c == '9') { + list.add('w'); + list.add('x'); + list.add('y'); + list.add('z'); + } + + return list; + } +} diff --git a/dfs/LetterCombinations2.java b/dfs/LetterCombinations2.java new file mode 100644 index 0000000..5d7dccb --- /dev/null +++ b/dfs/LetterCombinations2.java @@ -0,0 +1,53 @@ +package Algorithms.dfs; + +import java.util.ArrayList; +import java.util.List; + +public class LetterCombinations2 { + public class Solution { + // We create a map to map the digit to the characters. + String[] map = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; + + public List letterCombinations(String digits) { + List ret = new ArrayList(); + ArrayList path = new ArrayList(); + + letterCombinationsHelp(digits, path, ret, 0); + + return ret; + } + + /* + 表示从digit的index处开始直到结尾的数字对应的字符的组合数 + */ + public void letterCombinationsHelp(String digits, ArrayList path, List ret, int index) { + if (digits == null) { + return; + } + + int len = digits.length(); + if (path.size() == len) { + StringBuilder sb = new StringBuilder(); + for (char c: path) { + sb.append(c); + } + ret.add(sb.toString()); + return; + } + + // get the possiable characters. + // for example, get abc from '2' + String combs = getChar(digits.charAt(index)); + + for (int i = 0; i < combs.length(); i++) { + path.add(combs.charAt(i)); + letterCombinationsHelp(digits, path, ret, index + 1); + path.remove(path.size() - 1); + } + } + + public String getChar(char c) { + return map[c - '0']; + } + } +} \ No newline at end of file diff --git a/dp/Fibonacci.java b/dp/Fibonacci.java index 1c00e40..e376d9e 100644 --- a/dp/Fibonacci.java +++ b/dp/Fibonacci.java @@ -1,6 +1,7 @@ package Algorithms.dp; import java.util.ArrayList; +import java.util.HashMap; /************************************************************************* * Compilation: javac Fibonacci.java @@ -29,14 +30,28 @@ * *************************************************************************/ public class Fibonacci { - public static long fib(int n) { + public static long fib(int n, HashMap map) { //System.out.println("Enter rec once."); if (n <= 2) { return 1; } + + long first; + if (map.get(n - 2) != null) { + first = map.get(n - 2); + } else { + first = fib(n - 2, map); + } + + long second; + if (map.get(n - 1) != null) { + second = map.get(n - 1); + } else { + second = fib(n - 1, map); + } - return fib(n - 1) + fib(n - 2); + return second + first; } public static ArrayList fibDp(int n) { @@ -57,12 +72,12 @@ public static ArrayList fibDp(int n) { public static void main(String[] args) { int N = 5; - System.out.print(fib(5) + " "); + System.out.print(fib(10, new HashMap()) + " "); // for (int i = 1; i <= N; i++) { // System.out.print(fib(i) + " "); // } - ArrayList list = fibDp(500); + ArrayList list = fibDp(10); System.out.println(list.toString()); } From 42796c9f28d2672598df14710af30052fb3c4d8e Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 10 Oct 2014 23:53:39 -0700 Subject: [PATCH 058/319] list --- list/DeleteDuplicates2.java | 60 +++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 list/DeleteDuplicates2.java diff --git a/list/DeleteDuplicates2.java b/list/DeleteDuplicates2.java new file mode 100644 index 0000000..4b3e3ec --- /dev/null +++ b/list/DeleteDuplicates2.java @@ -0,0 +1,60 @@ +package Algorithms.list; + +import Algorithms.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + * + * Remove Duplicates from Sorted List II Total Accepted: 21701 Total Submissions: 87380 My Submissions + Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. + + For example, + Given 1->2->3->3->4->4->5, return 1->2->5. + Given 1->1->1->2->3, return 2->3. + */ +public class DeleteDuplicates2 { + public ListNode deleteDuplicates(ListNode head) { + if (head == null) { + return null; + } + + // record the head. + ListNode dummy = new ListNode(0); + dummy.next = head; + + ListNode cur = dummy; + + // to delete the last node in the list of duplications. + boolean del = false; + + while (cur != null) { + if (cur.next != null + && cur.next.next != null + && cur.next.val == cur.next.next.val) { + cur.next = cur.next.next; + del = true; + } else { + // delete the last node in a duplicaions list. + if (del) { + cur.next = cur.next.next; + + // set back the flag to be false. + del = false; + } else { + // move forward. + cur = cur.next; + } + } + } + + return dummy.next; + } +} \ No newline at end of file From d6d13088fa5cd683251a6aa30fef90d012082239 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 00:20:27 -0700 Subject: [PATCH 059/319] list --- list/PartitionList.java | 51 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 list/PartitionList.java diff --git a/list/PartitionList.java b/list/PartitionList.java new file mode 100644 index 0000000..683e17d --- /dev/null +++ b/list/PartitionList.java @@ -0,0 +1,51 @@ +package Algorithms.list; + +import Algorithms.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class PartitionList { + public ListNode partition(ListNode head, int x) { + // the list which is greater than or equal to x + ListNode dummyGE = new ListNode(0); + + // the list which is less than x + ListNode dummyLess = new ListNode(0); + + // link the dummy to the head; + dummyGE.next = head; + + ListNode pre = dummyGE; + + ListNode tailLess = dummyLess; + + // go through the list and remove the small node to a new list. + while (pre.next != null) { + if (pre.next.val < x) { + // Add this to the less list. + tailLess.next = pre.next; + tailLess = tailLess.next; + + // remove the node from the current list. + pre.next = pre.next.next; + } else { + // move the pre node forward. + pre = pre.next; + } + } + + // link the LESS list and the Large list. + tailLess.next = dummyGE.next; + + return dummyLess.next; + } +} From 0060c07292309dc2309a7923c63b2b5b4899740b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 00:44:38 -0700 Subject: [PATCH 060/319] rotate --- list/RotateList.java | 63 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 list/RotateList.java diff --git a/list/RotateList.java b/list/RotateList.java new file mode 100644 index 0000000..f45f708 --- /dev/null +++ b/list/RotateList.java @@ -0,0 +1,63 @@ +package Algorithms.list; + +import Algorithms.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class RotateList { + public ListNode rotateRight(ListNode head, int n) { + if (head == null) { + return null; + } + + // when the list rotate n, it will go back. + n = n % getlen(head); + + ListNode dummy = new ListNode(0); + dummy.next = head; + + // get the pre node before the node which is the new head; + // for example: Given 1->2->3->4->5->NULL and k = 2, + // we should find 3 + // return 4->5->1->2->3->NULL. + ListNode tail = dummy; + while (n > 0) { + tail = tail.next; + n--; + } + + ListNode pre = dummy; + while (tail != null && tail.next != null) { + tail = tail.next; + pre = pre.next; + } + + // cut the two list and connect the head to the tail. + tail.next = dummy.next; + + ListNode headNew = pre.next; + pre.next = null; + + return headNew; + } + + // get the list lenght. + public int getlen(ListNode head) { + int len = 0; + while (head != null) { + len++; + head = head.next; + } + + return len; + } +} From 72e5ddfefe06db57fc26bc7644c62aa34581a13b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 01:06:34 -0700 Subject: [PATCH 061/319] list --- list/RemoveNthFromEnd.java | 45 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 list/RemoveNthFromEnd.java diff --git a/list/RemoveNthFromEnd.java b/list/RemoveNthFromEnd.java new file mode 100644 index 0000000..72296f9 --- /dev/null +++ b/list/RemoveNthFromEnd.java @@ -0,0 +1,45 @@ +package Algorithms.list; + +import Algorithms.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class RemoveNthFromEnd { + public ListNode removeNthFromEnd(ListNode head, int n) { + if (head == null) { + return null; + } + + ListNode dummy = new ListNode(0); + dummy.next = head; + + // move tail N nodes faster than pre. + ListNode tail = dummy; + // 注意,这里用for比较好一点,用while时,经常不记得将参量-- + for (int i = n; i > 0; i--) { + tail = tail.next; + } + + ListNode pre = dummy; + + // get the node before the node we want to delete. + while (tail != null && tail.next != null) { + tail = tail.next; + pre = pre.next; + } + + // DELTE. + pre.next = pre.next.next; + + return dummy.next; + } +} \ No newline at end of file From cfdbfe8ccf01d33b482da435cb245fd8a471c285 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 01:18:46 -0700 Subject: [PATCH 062/319] remove --- list/RemoveNthFromEnd.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/list/RemoveNthFromEnd.java b/list/RemoveNthFromEnd.java index 72296f9..cdf728c 100644 --- a/list/RemoveNthFromEnd.java +++ b/list/RemoveNthFromEnd.java @@ -38,7 +38,9 @@ public ListNode removeNthFromEnd(ListNode head, int n) { } // DELTE. - pre.next = pre.next.next; + if (pre.next != null) { + pre.next = pre.next.next; + } return dummy.next; } From 732d38a89b46c85f4a0b2a59780889d1bea3d75c Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 01:48:46 -0700 Subject: [PATCH 063/319] list --- list/MergeKLists.java | 63 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 list/MergeKLists.java diff --git a/list/MergeKLists.java b/list/MergeKLists.java new file mode 100644 index 0000000..fc90fa1 --- /dev/null +++ b/list/MergeKLists.java @@ -0,0 +1,63 @@ +package Algorithms.list; + +import java.util.Comparator; +import java.util.List; +import java.util.PriorityQueue; + +import Algorithms.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class MergeKLists { + public ListNode mergeKLists(List lists) { + // 注意:lists.size() == 0 一定要处理,否则建立queue时 不能输入初始size为0 + if (lists == null || lists.size() == 0) { + return null; + } + + Comparator comparator = new Comparator() { + public int compare(ListNode o1, ListNode o2) { + return o1.val - o2.val; + } + }; + + // create a priority Queue. + PriorityQueue q = new PriorityQueue(lists.size(), comparator); + + // add all the first nodes to the QUEUE. + for (ListNode node: lists) { + if (node != null) { + // don't add EMPTY lists. + q.offer(node); + } + } + + ListNode dummy = new ListNode(0); + ListNode tail = dummy; + + while (!q.isEmpty()) { + // get a list node from the queue. + ListNode node = q.poll(); + + // add the node to the result link. + tail.next = node; + tail = tail.next; + + // add a new node from the lists to the priority queue. + if (node.next != null) { + q.offer(node.next); + } + } + + return dummy.next; + } +} From 53f429f69d4c2fba0207b53e2c7bb13310ea1fc5 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 03:08:12 -0700 Subject: [PATCH 064/319] tree --- tree/PathSum2.java | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tree/PathSum2.java diff --git a/tree/PathSum2.java b/tree/PathSum2.java new file mode 100644 index 0000000..6618f6f --- /dev/null +++ b/tree/PathSum2.java @@ -0,0 +1,47 @@ +package Algorithms.tree; + +import java.util.ArrayList; +import java.util.List; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class PathSum2 { + public List> pathSum(TreeNode root, int sum) { + List> ret = new ArrayList>(); + + ArrayList path = new ArrayList(); + + pathSumHelp(root, sum, path, ret); + + return ret; + } + + public void pathSumHelp(TreeNode root, int sum, ArrayList path, List> ret) { + if (root == null) { + return; + } + + path.add(root.val); + + if (root.left == null + && root.right == null + && root.val == sum) { + ret.add(new ArrayList(path)); + } else { + // 继续递归 + pathSumHelp(root.left, sum - root.val, path, ret); + pathSumHelp(root.right, sum - root.val, path, ret); + } + + // 注意,递归和回溯的特点就是 递归不可以改变path的值。也就是说,你返回时,这个path不能被改变 + // 所以在这里要执行remove操作。 + path.remove(path.size() - 1); + } +} \ No newline at end of file From 1693ac260b6cc6ce56c6bf7cb82b847fdfa631b7 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 03:52:24 -0700 Subject: [PATCH 065/319] candy --- dp/Candy.java | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 dp/Candy.java diff --git a/dp/Candy.java b/dp/Candy.java new file mode 100644 index 0000000..0f0a40d --- /dev/null +++ b/dp/Candy.java @@ -0,0 +1,36 @@ +package Algorithms.dp; + +public class Candy { + public int candy(int[] ratings) { + if (ratings == null || ratings.length == 0) { + return 0; + } + + int len = ratings.length; + int[] candys = new int[len]; + + // go from the left side to the right side and give them candys. + candys[0] = 1; + for (int i = 1; i < len; i++) { + if (ratings[i] > ratings[i - 1]) { + candys[i] = candys[i - 1] + 1; + } else { + candys[i] = 1; + } + } + + for (int i = len - 2; i >= 0; i--) { + if (ratings[i] > ratings[i + 1]) { + int num = candys[i + 1] + 1; + candys[i] = Math.max(candys[i], num); + } + } + + int sum = 0; + for (int i: candys) { + sum += i; + } + + return sum; + } +} From 7a80b4624546070af1d87069f6fa3805dda7bb58 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 14:22:03 -0700 Subject: [PATCH 066/319] combine --- combination/Combinations.java | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 combination/Combinations.java diff --git a/combination/Combinations.java b/combination/Combinations.java new file mode 100644 index 0000000..54a7b7d --- /dev/null +++ b/combination/Combinations.java @@ -0,0 +1,41 @@ +package Algorithms.combination; + +import java.util.ArrayList; +import java.util.List; + +public class Combinations { + public List> combine(int n, int k) { + List> ret = new ArrayList>(); + + if (n == 0 || k == 0) { + return ret; + } + + List path = new ArrayList(); + + combine(n, k, path, ret, 1); + + return ret; + } + + // index means the position which I can choose from. + // for example: when n = 4, + // 1, 2, 3, 4, and index = 1, means now I can choose a number from 1 - 4 + // + public void combine(int n, int k, List path, List> ret, int index) { + if (0 == k) { + ret.add(new ArrayList(path)); + return; + } + + // 注意这里的终止条件. + // For example: N = 4的时候,K = 2的时候, + // 这里还有2个可以取值,那么 1, 2, 3, 4中index最多可以从3取值,也就是4-2+1. + // 就是 n - k + 1 + for (int i = index; i <= n - k + 1; i++) { + path.add(i); + combine(n, k - 1, path, ret, i + 1); + path.remove(path.size() - 1); + } + } +} \ No newline at end of file From e78f71dfe1622114e45eb4bc50f990763309daf6 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 17:51:53 -0700 Subject: [PATCH 067/319] recursion --- recursion/Factorial.java | 41 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 recursion/Factorial.java diff --git a/recursion/Factorial.java b/recursion/Factorial.java new file mode 100644 index 0000000..39603ef --- /dev/null +++ b/recursion/Factorial.java @@ -0,0 +1,41 @@ +package Algorithms.recursion; + +import java.util.Stack; + +public class Factorial { + public static void main(String[] strs) { + System.out.println(factorial(10)); + System.out.println(factorialIterator(10)); + } + + public static int factorialIterator(Integer n) { + int ret = 1; + for (int i = n; i >= 1; i--) { + ret *= i; + } + + return ret; + } + + + public static int factorial(Integer n) { + Stack s = new Stack(); + + s.push(n); + + int ret = 1; + + while (!s.isEmpty()) { + int cur = s.pop(); + + if (cur == 1) { + break; + } + + ret *= cur; + s.push(cur - 1); + } + + return ret; + } +} From 686f5ebb4292b60b7c8792609e7d7008ed41d9b9 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 21:01:19 -0700 Subject: [PATCH 068/319] combination --- combination/CombinationSum2.java | 82 ++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 combination/CombinationSum2.java diff --git a/combination/CombinationSum2.java b/combination/CombinationSum2.java new file mode 100644 index 0000000..d269c04 --- /dev/null +++ b/combination/CombinationSum2.java @@ -0,0 +1,82 @@ +package Algorithms.combination; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CombinationSum2 { + public List> combinationSum2(int[] num, int target) { + List> ret = new ArrayList>(); + List path = new ArrayList(); + + if (num == null || num.length == 0) { + return ret; + } + + // before solve it, we just need to sort it. + Arrays.sort(num); + + // boolean[] isSelect = new boolean[num.length]; + // for (int i = 0; i < num.length; i++) { + // isSelect[i] = false; + // } + + //combinationSum2Help(num, isSelect, target, path, ret, 0); + + combinationSum2HelpMethod2(num, target, path, ret, 0); + + return ret; + } + + // Solution 1; + public void combinationSum2Help(int[] num, boolean[] isSelect, int target, + List path, List> ret, int index) { + if (target < 0) { + return; + } + + if (target == 0) { + // add a new solution. + ret.add(new ArrayList(path)); + } + + for (int i = index; i < num.length; i++) { + if (i > 0 && num[i] == num[i - 1] && !isSelect[i - 1]) { + continue; + } + path.add(num[i]); + isSelect[i] = true; + combinationSum2Help(num, isSelect, target - num[i], path, ret, i + 1); + path.remove(path.size() - 1); + isSelect[i] = false; + } + } + + // Solution 2; + public void combinationSum2HelpMethod2(int[] num, int target, + List path, List> ret, int index) { + if (target < 0) { + return; + } + + if (target == 0) { + // add a new solution. + ret.add(new ArrayList(path)); + } + + int pre = -1; + for (int i = index; i < num.length; i++) { + // 我们每次都只取第一个,因为我们不能取重复的元素。在所有元素里任何挑一个就行了。 + if (num[i] == pre) { + continue; + } + + pre = num[i]; + + path.add(num[i]); + combinationSum2HelpMethod2(num, target - num[i], path, ret, i + 1); + // 回溯 + path.remove(path.size() - 1); + } + } +} From b8c591355b6009de2c01597397935a361a1abc73 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 22:01:13 -0700 Subject: [PATCH 069/319] DP --- dp/MinPathSum.java | 79 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 dp/MinPathSum.java diff --git a/dp/MinPathSum.java b/dp/MinPathSum.java new file mode 100644 index 0000000..185342c --- /dev/null +++ b/dp/MinPathSum.java @@ -0,0 +1,79 @@ +package Algorithms.dp; + +public class MinPathSum { + public int minPathSum2(int[][] grid) { + if (grid == null || grid.length == 0 || grid[0].length == 0) { + return 0; + } + + // This is a simple DP. + // 表达式: D[i][j]: 从左下到本点的最小值 + // 递推公式: D[i][j] = Math.mn(D[i - 1][j], D[i][j - 1]) + grid[i][j] + // 初始化: D[i][j] = grid[i][j]. + + int rows = grid.length; + int cols = grid[0].length; + int[][] D = new int[rows][cols]; + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + D[i][j] = grid[i][j]; + if (i == 0 && j == 0) { + continue; + } else if (i == 0) { + D[i][j] += D[i][j - 1]; + } else if (j == 0) { + D[i][j] += D[i - 1][j]; + } else { + D[i][j] += Math.min(D[i][j - 1], D[i - 1][j]); + } + } + } + + return D[rows - 1][cols - 1]; + } + + public int minPathSum(int[][] grid) { + if (grid == null || grid.length == 0 || grid[0].length == 0) { + return 0; + } + + int rows = grid.length; + int cols = grid[0].length; + int[][] visit = new int[rows][cols]; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + visit[i][j] = -1; + } + } + + return dfs(grid, 0, 0, visit); + } + + public int dfs(int[][] grid, int i, int j, int[][] visit) { + int row = grid.length; + int col = grid[0].length; + + // 符合递归的终止条件,因为我已经到达了终点 + if (i == row - 1 && j == col - 1) { + return grid[i][j]; + } + + if (i >= row || j >= col || i < 0 || j < 0) { + // 表示不可达 + return Integer.MAX_VALUE; + } + + // 已经搜索过的点不需要重复搜索 + if (visit[i][j] != -1) { + return visit[i][j]; + } + + // 开始dfs 可能的路径,目前我们只有2种可能 + int right = dfs(grid, i, j + 1, visit); + int down = dfs(grid, i + 1, j, visit); + + visit[i][j] = Math.min(down, right) + grid[i][j]; + return visit[i][j]; + } +} \ No newline at end of file From 04bbddebfbd9cad44ebcac3fa0692d8cb485b96a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 22:44:32 -0700 Subject: [PATCH 070/319] reorder --- list/DeleteDuplicates.java | 2 +- list/DeleteDuplicates2.java | 2 +- list/MergeKLists.java | 2 +- list/MergeTwoLists.java | 2 +- list/PartitionList.java | 2 +- list/RemoveNthFromEnd.java | 2 +- list/ReorderList.java | 2 +- list/ReverseBetween.java | 2 +- list/ReverseLinkedList2.java | 2 +- list/RotateList.java | 2 +- AddBinary.java => others/AddBinary.java | 2 +- Ag.java => others/Ag.java | 2 +- Anagrams.java => others/Anagrams.java | 2 +- BinarySearch.java => others/BinarySearch.java | 2 +- Combination2.java => others/Combination2.java | 2 +- CombinationSum.java => others/CombinationSum.java | 2 +- DivideTwoIntegers.java => others/DivideTwoIntegers.java | 2 +- FindKthNumber.java => others/FindKthNumber.java | 2 +- FindSame.java => others/FindSame.java | 2 +- Flatten.java => others/Flatten.java | 2 +- GenerateParentheses.java => others/GenerateParentheses.java | 2 +- GraphDemo.java => others/GraphDemo.java | 2 +- InOrderTraversal.java => others/InOrderTraversal.java | 2 +- Insertion_Link.java => others/Insertion_Link.java | 2 +- Interleaving.java => others/Interleaving.java | 2 +- .../IntersectionOfThreeSets.java | 2 +- IsMach.java => others/IsMach.java | 2 +- IsSymmetric.java => others/IsSymmetric.java | 2 +- JavaAppWithoutMain.java => others/JavaAppWithoutMain.java | 2 +- KthLargestElement.java => others/KthLargestElement.java | 2 +- KthSort.java => others/KthSort.java | 2 +- LRUCache.java => others/LRUCache.java | 2 +- LargestRectangleArea.java => others/LargestRectangleArea.java | 2 +- Line.java => others/Line.java | 2 +- ListNode.java => others/ListNode.java | 2 +- ListNodeDemo.java => others/ListNodeDemo.java | 2 +- LongestPare.java => others/LongestPare.java | 2 +- Max_path_BinaryTree.java => others/Max_path_BinaryTree.java | 2 +- MiniStack.java => others/MiniStack.java | 2 +- .../MinimumWindowSubString.java | 2 +- MortgageCalculator.java => others/MortgageCalculator.java | 2 +- MutiplyString.java => others/MutiplyString.java | 2 +- NumDecodings.java => others/NumDecodings.java | 2 +- NumTree.java => others/NumTree.java | 2 +- PartitionArray.java => others/PartitionArray.java | 2 +- Permute.java => others/Permute.java | 2 +- PlusOne.java => others/PlusOne.java | 2 +- Point.java => others/Point.java | 2 +- Populate2.java => others/Populate2.java | 2 +- Premute.java => others/Premute.java | 2 +- Recover.java => others/Recover.java | 2 +- Rectangle.java => others/Rectangle.java | 2 +- ReverseString.java => others/ReverseString.java | 2 +- SearchInRotatedArray.java => others/SearchInRotatedArray.java | 2 +- SingleNumber2.java => others/SingleNumber2.java | 2 +- SortColors.java => others/SortColors.java | 2 +- SortList.java => others/SortList.java | 2 +- SpiralMatrix.java => others/SpiralMatrix.java | 2 +- SpiralOrder.java => others/SpiralOrder.java | 2 +- Sqrt.java => others/Sqrt.java | 2 +- SubSet2.java => others/SubSet2.java | 2 +- Subset.java => others/Subset.java | 2 +- SurroundRegions.java => others/SurroundRegions.java | 2 +- TestArrayChange.java => others/TestArrayChange.java | 2 +- TreeSumCloset.java => others/TreeSumCloset.java | 2 +- WordBreak2.java => others/WordBreak2.java | 2 +- ZigzagLevelOrder.java => others/ZigzagLevelOrder.java | 2 +- letterCombinations.java => others/letterCombinations.java | 2 +- sort/InsertionSortList.java | 2 +- sort/MergeSort_LinkedList.java | 2 +- sort/SortList_leetCode.java | 2 +- 71 files changed, 71 insertions(+), 71 deletions(-) rename AddBinary.java => others/AddBinary.java (98%) rename Ag.java => others/Ag.java (55%) rename Anagrams.java => others/Anagrams.java (98%) rename BinarySearch.java => others/BinarySearch.java (98%) rename Combination2.java => others/Combination2.java (98%) rename CombinationSum.java => others/CombinationSum.java (98%) rename DivideTwoIntegers.java => others/DivideTwoIntegers.java (95%) rename FindKthNumber.java => others/FindKthNumber.java (98%) rename FindSame.java => others/FindSame.java (97%) rename Flatten.java => others/Flatten.java (96%) rename GenerateParentheses.java => others/GenerateParentheses.java (98%) rename GraphDemo.java => others/GraphDemo.java (99%) rename InOrderTraversal.java => others/InOrderTraversal.java (96%) rename Insertion_Link.java => others/Insertion_Link.java (98%) rename Interleaving.java => others/Interleaving.java (98%) rename IntersectionOfThreeSets.java => others/IntersectionOfThreeSets.java (97%) rename IsMach.java => others/IsMach.java (98%) rename IsSymmetric.java => others/IsSymmetric.java (97%) rename JavaAppWithoutMain.java => others/JavaAppWithoutMain.java (80%) rename KthLargestElement.java => others/KthLargestElement.java (98%) rename KthSort.java => others/KthSort.java (97%) rename LRUCache.java => others/LRUCache.java (98%) rename LargestRectangleArea.java => others/LargestRectangleArea.java (96%) rename Line.java => others/Line.java (99%) rename ListNode.java => others/ListNode.java (94%) rename ListNodeDemo.java => others/ListNodeDemo.java (99%) rename LongestPare.java => others/LongestPare.java (98%) rename Max_path_BinaryTree.java => others/Max_path_BinaryTree.java (98%) rename MiniStack.java => others/MiniStack.java (98%) rename MinimumWindowSubString.java => others/MinimumWindowSubString.java (98%) rename MortgageCalculator.java => others/MortgageCalculator.java (99%) rename MutiplyString.java => others/MutiplyString.java (98%) rename NumDecodings.java => others/NumDecodings.java (98%) rename NumTree.java => others/NumTree.java (96%) rename PartitionArray.java => others/PartitionArray.java (97%) rename Permute.java => others/Permute.java (97%) rename PlusOne.java => others/PlusOne.java (96%) rename Point.java => others/Point.java (84%) rename Populate2.java => others/Populate2.java (98%) rename Premute.java => others/Premute.java (99%) rename Recover.java => others/Recover.java (97%) rename Rectangle.java => others/Rectangle.java (98%) rename ReverseString.java => others/ReverseString.java (55%) rename SearchInRotatedArray.java => others/SearchInRotatedArray.java (98%) rename SingleNumber2.java => others/SingleNumber2.java (55%) rename SortColors.java => others/SortColors.java (97%) rename SortList.java => others/SortList.java (98%) rename SpiralMatrix.java => others/SpiralMatrix.java (97%) rename SpiralOrder.java => others/SpiralOrder.java (98%) rename Sqrt.java => others/Sqrt.java (97%) rename SubSet2.java => others/SubSet2.java (97%) rename Subset.java => others/Subset.java (98%) rename SurroundRegions.java => others/SurroundRegions.java (98%) rename TestArrayChange.java => others/TestArrayChange.java (94%) rename TreeSumCloset.java => others/TreeSumCloset.java (98%) rename WordBreak2.java => others/WordBreak2.java (98%) rename ZigzagLevelOrder.java => others/ZigzagLevelOrder.java (99%) rename letterCombinations.java => others/letterCombinations.java (98%) diff --git a/list/DeleteDuplicates.java b/list/DeleteDuplicates.java index 6ddc921..2dc83ed 100644 --- a/list/DeleteDuplicates.java +++ b/list/DeleteDuplicates.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.ListNode; +import Algorithms.others.ListNode; /** * Definition for singly-linked list. diff --git a/list/DeleteDuplicates2.java b/list/DeleteDuplicates2.java index 4b3e3ec..ecaab8e 100644 --- a/list/DeleteDuplicates2.java +++ b/list/DeleteDuplicates2.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.ListNode; +import Algorithms.others.ListNode; /** * Definition for singly-linked list. diff --git a/list/MergeKLists.java b/list/MergeKLists.java index fc90fa1..42d8c30 100644 --- a/list/MergeKLists.java +++ b/list/MergeKLists.java @@ -4,7 +4,7 @@ import java.util.List; import java.util.PriorityQueue; -import Algorithms.ListNode; +import Algorithms.others.ListNode; /** * Definition for singly-linked list. diff --git a/list/MergeTwoLists.java b/list/MergeTwoLists.java index 7eac1e1..d1644d4 100644 --- a/list/MergeTwoLists.java +++ b/list/MergeTwoLists.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.ListNode; +import Algorithms.others.ListNode; public class MergeTwoLists { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { diff --git a/list/PartitionList.java b/list/PartitionList.java index 683e17d..c1aa6df 100644 --- a/list/PartitionList.java +++ b/list/PartitionList.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.ListNode; +import Algorithms.others.ListNode; /** * Definition for singly-linked list. diff --git a/list/RemoveNthFromEnd.java b/list/RemoveNthFromEnd.java index cdf728c..de618a1 100644 --- a/list/RemoveNthFromEnd.java +++ b/list/RemoveNthFromEnd.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.ListNode; +import Algorithms.others.ListNode; /** * Definition for singly-linked list. diff --git a/list/ReorderList.java b/list/ReorderList.java index 6ec1e93..701d43c 100644 --- a/list/ReorderList.java +++ b/list/ReorderList.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.ListNode; +import Algorithms.others.ListNode; /** * Definition for singly-linked list. diff --git a/list/ReverseBetween.java b/list/ReverseBetween.java index 790c197..6a653a0 100644 --- a/list/ReverseBetween.java +++ b/list/ReverseBetween.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.ListNode; +import Algorithms.others.ListNode; public class ReverseBetween { public ListNode reverseBetween(ListNode head, int m, int n) { diff --git a/list/ReverseLinkedList2.java b/list/ReverseLinkedList2.java index 1441333..6d1c568 100644 --- a/list/ReverseLinkedList2.java +++ b/list/ReverseLinkedList2.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.ListNode; +import Algorithms.others.ListNode; public class ReverseLinkedList2 { public static void main(String[] args) { diff --git a/list/RotateList.java b/list/RotateList.java index f45f708..47a677f 100644 --- a/list/RotateList.java +++ b/list/RotateList.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.ListNode; +import Algorithms.others.ListNode; /** * Definition for singly-linked list. diff --git a/AddBinary.java b/others/AddBinary.java similarity index 98% rename from AddBinary.java rename to others/AddBinary.java index c19b562..2463fcf 100644 --- a/AddBinary.java +++ b/others/AddBinary.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class AddBinary { public static void main(String[] args) { diff --git a/Ag.java b/others/Ag.java similarity index 55% rename from Ag.java rename to others/Ag.java index b9746d6..0a89bfa 100644 --- a/Ag.java +++ b/others/Ag.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; diff --git a/Anagrams.java b/others/Anagrams.java similarity index 98% rename from Anagrams.java rename to others/Anagrams.java index 74ddb55..e27fda6 100644 --- a/Anagrams.java +++ b/others/Anagrams.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; import java.util.HashMap; diff --git a/BinarySearch.java b/others/BinarySearch.java similarity index 98% rename from BinarySearch.java rename to others/BinarySearch.java index b8ad95e..8ccfa1a 100644 --- a/BinarySearch.java +++ b/others/BinarySearch.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class BinarySearch { public static void main(String[] strs) { diff --git a/Combination2.java b/others/Combination2.java similarity index 98% rename from Combination2.java rename to others/Combination2.java index 9a8b8e9..ecb6f11 100644 --- a/Combination2.java +++ b/others/Combination2.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; import java.util.Arrays; diff --git a/CombinationSum.java b/others/CombinationSum.java similarity index 98% rename from CombinationSum.java rename to others/CombinationSum.java index 2a2b7d3..80b7a5a 100644 --- a/CombinationSum.java +++ b/others/CombinationSum.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; import java.util.Arrays; diff --git a/DivideTwoIntegers.java b/others/DivideTwoIntegers.java similarity index 95% rename from DivideTwoIntegers.java rename to others/DivideTwoIntegers.java index d0c6e72..17ff86f 100644 --- a/DivideTwoIntegers.java +++ b/others/DivideTwoIntegers.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class DivideTwoIntegers { public static void main(String[] args) { diff --git a/FindKthNumber.java b/others/FindKthNumber.java similarity index 98% rename from FindKthNumber.java rename to others/FindKthNumber.java index 20c1f3e..a15542a 100644 --- a/FindKthNumber.java +++ b/others/FindKthNumber.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class FindKthNumber { diff --git a/FindSame.java b/others/FindSame.java similarity index 97% rename from FindSame.java rename to others/FindSame.java index d4d3c59..b608637 100644 --- a/FindSame.java +++ b/others/FindSame.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.LinkedList; diff --git a/Flatten.java b/others/Flatten.java similarity index 96% rename from Flatten.java rename to others/Flatten.java index 4f4bcf4..31ffeda 100644 --- a/Flatten.java +++ b/others/Flatten.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.Stack; import Algorithms.tree.TreeNode; diff --git a/GenerateParentheses.java b/others/GenerateParentheses.java similarity index 98% rename from GenerateParentheses.java rename to others/GenerateParentheses.java index ba26c66..5b5e593 100644 --- a/GenerateParentheses.java +++ b/others/GenerateParentheses.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; import java.util.Stack; diff --git a/GraphDemo.java b/others/GraphDemo.java similarity index 99% rename from GraphDemo.java rename to others/GraphDemo.java index 241d5ca..b7f954a 100644 --- a/GraphDemo.java +++ b/others/GraphDemo.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; diff --git a/InOrderTraversal.java b/others/InOrderTraversal.java similarity index 96% rename from InOrderTraversal.java rename to others/InOrderTraversal.java index 6de42e4..28fe5a0 100644 --- a/InOrderTraversal.java +++ b/others/InOrderTraversal.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; import java.util.Stack; diff --git a/Insertion_Link.java b/others/Insertion_Link.java similarity index 98% rename from Insertion_Link.java rename to others/Insertion_Link.java index b5ea424..ab99a8d 100644 --- a/Insertion_Link.java +++ b/others/Insertion_Link.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class Insertion_Link { public static void main(String[] str) { diff --git a/Interleaving.java b/others/Interleaving.java similarity index 98% rename from Interleaving.java rename to others/Interleaving.java index 7c24db8..a2ec047 100644 --- a/Interleaving.java +++ b/others/Interleaving.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class Interleaving { public static void main(String[] strs) { System.out.println(isInterleave("a", "b", "ab")); diff --git a/IntersectionOfThreeSets.java b/others/IntersectionOfThreeSets.java similarity index 97% rename from IntersectionOfThreeSets.java rename to others/IntersectionOfThreeSets.java index 6d3f2cb..729d731 100644 --- a/IntersectionOfThreeSets.java +++ b/others/IntersectionOfThreeSets.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.HashMap; import java.util.LinkedList; diff --git a/IsMach.java b/others/IsMach.java similarity index 98% rename from IsMach.java rename to others/IsMach.java index 709e35d..b528be7 100644 --- a/IsMach.java +++ b/others/IsMach.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class IsMach { public static void main(String[] str) { diff --git a/IsSymmetric.java b/others/IsSymmetric.java similarity index 97% rename from IsSymmetric.java rename to others/IsSymmetric.java index eee9d5a..2dcd423 100644 --- a/IsSymmetric.java +++ b/others/IsSymmetric.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayDeque; diff --git a/JavaAppWithoutMain.java b/others/JavaAppWithoutMain.java similarity index 80% rename from JavaAppWithoutMain.java rename to others/JavaAppWithoutMain.java index 5ebab11..0e099e4 100644 --- a/JavaAppWithoutMain.java +++ b/others/JavaAppWithoutMain.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class JavaAppWithoutMain { static diff --git a/KthLargestElement.java b/others/KthLargestElement.java similarity index 98% rename from KthLargestElement.java rename to others/KthLargestElement.java index 6bd6c34..89647ae 100644 --- a/KthLargestElement.java +++ b/others/KthLargestElement.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; import java.util.Collections; diff --git a/KthSort.java b/others/KthSort.java similarity index 97% rename from KthSort.java rename to others/KthSort.java index bb97cf1..58603fc 100644 --- a/KthSort.java +++ b/others/KthSort.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.HashMap; diff --git a/LRUCache.java b/others/LRUCache.java similarity index 98% rename from LRUCache.java rename to others/LRUCache.java index f367fdc..6c04280 100644 --- a/LRUCache.java +++ b/others/LRUCache.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.HashMap; diff --git a/LargestRectangleArea.java b/others/LargestRectangleArea.java similarity index 96% rename from LargestRectangleArea.java rename to others/LargestRectangleArea.java index 9709f21..0824825 100644 --- a/LargestRectangleArea.java +++ b/others/LargestRectangleArea.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.Stack; diff --git a/Line.java b/others/Line.java similarity index 99% rename from Line.java rename to others/Line.java index 3ce7a15..9621f2a 100644 --- a/Line.java +++ b/others/Line.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.Comparator; import java.util.HashMap; diff --git a/ListNode.java b/others/ListNode.java similarity index 94% rename from ListNode.java rename to others/ListNode.java index 431ec40..edee146 100644 --- a/ListNode.java +++ b/others/ListNode.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class ListNode { public int val; diff --git a/ListNodeDemo.java b/others/ListNodeDemo.java similarity index 99% rename from ListNodeDemo.java rename to others/ListNodeDemo.java index f23327d..3e0e717 100644 --- a/ListNodeDemo.java +++ b/others/ListNodeDemo.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.HashMap; import java.util.HashSet; diff --git a/LongestPare.java b/others/LongestPare.java similarity index 98% rename from LongestPare.java rename to others/LongestPare.java index 68be7dd..1f9ab1f 100644 --- a/LongestPare.java +++ b/others/LongestPare.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.Stack; diff --git a/Max_path_BinaryTree.java b/others/Max_path_BinaryTree.java similarity index 98% rename from Max_path_BinaryTree.java rename to others/Max_path_BinaryTree.java index 9422213..16cfca6 100644 --- a/Max_path_BinaryTree.java +++ b/others/Max_path_BinaryTree.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; import Algorithms.tree.TreeNode; diff --git a/MiniStack.java b/others/MiniStack.java similarity index 98% rename from MiniStack.java rename to others/MiniStack.java index e391595..ba53553 100644 --- a/MiniStack.java +++ b/others/MiniStack.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.Stack; diff --git a/MinimumWindowSubString.java b/others/MinimumWindowSubString.java similarity index 98% rename from MinimumWindowSubString.java rename to others/MinimumWindowSubString.java index ef34ed2..0eb0a52 100644 --- a/MinimumWindowSubString.java +++ b/others/MinimumWindowSubString.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.HashMap; public class MinimumWindowSubString { diff --git a/MortgageCalculator.java b/others/MortgageCalculator.java similarity index 99% rename from MortgageCalculator.java rename to others/MortgageCalculator.java index b128438..32d25e1 100644 --- a/MortgageCalculator.java +++ b/others/MortgageCalculator.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.text.NumberFormat; diff --git a/MutiplyString.java b/others/MutiplyString.java similarity index 98% rename from MutiplyString.java rename to others/MutiplyString.java index 18da410..3d009a1 100644 --- a/MutiplyString.java +++ b/others/MutiplyString.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class MutiplyString { public static void main(String[] args) { MutiplyString ms = new MutiplyString(); diff --git a/NumDecodings.java b/others/NumDecodings.java similarity index 98% rename from NumDecodings.java rename to others/NumDecodings.java index 88dc103..c455c25 100644 --- a/NumDecodings.java +++ b/others/NumDecodings.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class NumDecodings { public static void main(String[] strs) { diff --git a/NumTree.java b/others/NumTree.java similarity index 96% rename from NumTree.java rename to others/NumTree.java index 9f8ee1f..3518ac0 100644 --- a/NumTree.java +++ b/others/NumTree.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class NumTree { public static void main(String[] strs) { diff --git a/PartitionArray.java b/others/PartitionArray.java similarity index 97% rename from PartitionArray.java rename to others/PartitionArray.java index 43d6344..135d945 100644 --- a/PartitionArray.java +++ b/others/PartitionArray.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class PartitionArray { public static void main(String[] strs) { diff --git a/Permute.java b/others/Permute.java similarity index 97% rename from Permute.java rename to others/Permute.java index 6e810bd..3f9527c 100644 --- a/Permute.java +++ b/others/Permute.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; import java.util.Arrays; diff --git a/PlusOne.java b/others/PlusOne.java similarity index 96% rename from PlusOne.java rename to others/PlusOne.java index 5f69f72..05dc69a 100644 --- a/PlusOne.java +++ b/others/PlusOne.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class PlusOne { public static void main(String[] args) { diff --git a/Point.java b/others/Point.java similarity index 84% rename from Point.java rename to others/Point.java index 4fc5f18..8b360cf 100644 --- a/Point.java +++ b/others/Point.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; class Point { int x; diff --git a/Populate2.java b/others/Populate2.java similarity index 98% rename from Populate2.java rename to others/Populate2.java index 8cf79a9..9894844 100644 --- a/Populate2.java +++ b/others/Populate2.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import Algorithms.tree.TreeLinkNode; diff --git a/Premute.java b/others/Premute.java similarity index 99% rename from Premute.java rename to others/Premute.java index dc5e852..f98d1c9 100644 --- a/Premute.java +++ b/others/Premute.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; import java.util.Arrays; diff --git a/Recover.java b/others/Recover.java similarity index 97% rename from Recover.java rename to others/Recover.java index 989ff5a..74aad22 100644 --- a/Recover.java +++ b/others/Recover.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import Algorithms.tree.TreeNode; diff --git a/Rectangle.java b/others/Rectangle.java similarity index 98% rename from Rectangle.java rename to others/Rectangle.java index 0dd9f4b..a309fbf 100644 --- a/Rectangle.java +++ b/others/Rectangle.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.Stack; diff --git a/ReverseString.java b/others/ReverseString.java similarity index 55% rename from ReverseString.java rename to others/ReverseString.java index 2e4c41d..3d1a05b 100644 --- a/ReverseString.java +++ b/others/ReverseString.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class ReverseString { diff --git a/SearchInRotatedArray.java b/others/SearchInRotatedArray.java similarity index 98% rename from SearchInRotatedArray.java rename to others/SearchInRotatedArray.java index 11e3521..3718297 100644 --- a/SearchInRotatedArray.java +++ b/others/SearchInRotatedArray.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class SearchInRotatedArray { public static void main(String[] args) { diff --git a/SingleNumber2.java b/others/SingleNumber2.java similarity index 55% rename from SingleNumber2.java rename to others/SingleNumber2.java index b34c5af..23ce80a 100644 --- a/SingleNumber2.java +++ b/others/SingleNumber2.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class SingleNumber2 { diff --git a/SortColors.java b/others/SortColors.java similarity index 97% rename from SortColors.java rename to others/SortColors.java index 67444f6..0126079 100644 --- a/SortColors.java +++ b/others/SortColors.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.Collection; import java.util.LinkedList; diff --git a/SortList.java b/others/SortList.java similarity index 98% rename from SortList.java rename to others/SortList.java index 40c9531..8f0801a 100644 --- a/SortList.java +++ b/others/SortList.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class SortList { public static void main(String[] str) { SortList sl = new SortList(); diff --git a/SpiralMatrix.java b/others/SpiralMatrix.java similarity index 97% rename from SpiralMatrix.java rename to others/SpiralMatrix.java index e14d76f..35e886d 100644 --- a/SpiralMatrix.java +++ b/others/SpiralMatrix.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class SpiralMatrix { public int[][] generateMatrix(int n) { int[][] rst = new int[n][n]; diff --git a/SpiralOrder.java b/others/SpiralOrder.java similarity index 98% rename from SpiralOrder.java rename to others/SpiralOrder.java index 2b6eb74..19a1089 100644 --- a/SpiralOrder.java +++ b/others/SpiralOrder.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; diff --git a/Sqrt.java b/others/Sqrt.java similarity index 97% rename from Sqrt.java rename to others/Sqrt.java index 06a9a67..71b12de 100644 --- a/Sqrt.java +++ b/others/Sqrt.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class Sqrt { public static int sqrt(int x) { diff --git a/SubSet2.java b/others/SubSet2.java similarity index 97% rename from SubSet2.java rename to others/SubSet2.java index 7f94174..24620e3 100644 --- a/SubSet2.java +++ b/others/SubSet2.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; import java.util.Arrays; diff --git a/Subset.java b/others/Subset.java similarity index 98% rename from Subset.java rename to others/Subset.java index a70eb11..e36e0e4 100644 --- a/Subset.java +++ b/others/Subset.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; import java.util.Arrays; diff --git a/SurroundRegions.java b/others/SurroundRegions.java similarity index 98% rename from SurroundRegions.java rename to others/SurroundRegions.java index 3ed4c16..05bb342 100644 --- a/SurroundRegions.java +++ b/others/SurroundRegions.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.LinkedList; import java.util.Queue; diff --git a/TestArrayChange.java b/others/TestArrayChange.java similarity index 94% rename from TestArrayChange.java rename to others/TestArrayChange.java index 924eaba..5d8c7fa 100644 --- a/TestArrayChange.java +++ b/others/TestArrayChange.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; public class TestArrayChange { public static void main(String[] args) { diff --git a/TreeSumCloset.java b/others/TreeSumCloset.java similarity index 98% rename from TreeSumCloset.java rename to others/TreeSumCloset.java index a9ad817..0fb3360 100644 --- a/TreeSumCloset.java +++ b/others/TreeSumCloset.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.Arrays; diff --git a/WordBreak2.java b/others/WordBreak2.java similarity index 98% rename from WordBreak2.java rename to others/WordBreak2.java index 562b197..d1ef70c 100644 --- a/WordBreak2.java +++ b/others/WordBreak2.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; diff --git a/ZigzagLevelOrder.java b/others/ZigzagLevelOrder.java similarity index 99% rename from ZigzagLevelOrder.java rename to others/ZigzagLevelOrder.java index 07686f8..7ccfb6e 100644 --- a/ZigzagLevelOrder.java +++ b/others/ZigzagLevelOrder.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; import java.util.LinkedList; import java.util.Queue; diff --git a/letterCombinations.java b/others/letterCombinations.java similarity index 98% rename from letterCombinations.java rename to others/letterCombinations.java index 53cf31a..595d915 100644 --- a/letterCombinations.java +++ b/others/letterCombinations.java @@ -1,4 +1,4 @@ -package Algorithms; +package Algorithms.others; import java.util.ArrayList; diff --git a/sort/InsertionSortList.java b/sort/InsertionSortList.java index 7a36b62..db8fd4b 100644 --- a/sort/InsertionSortList.java +++ b/sort/InsertionSortList.java @@ -1,6 +1,6 @@ package Algorithms.sort; -import Algorithms.ListNode; +import Algorithms.others.ListNode; /** * Definition for singly-linked list. diff --git a/sort/MergeSort_LinkedList.java b/sort/MergeSort_LinkedList.java index 9fde42d..ac84dae 100644 --- a/sort/MergeSort_LinkedList.java +++ b/sort/MergeSort_LinkedList.java @@ -2,7 +2,7 @@ import java.util.LinkedList; -import Algorithms.ListNode; +import Algorithms.others.ListNode; public class MergeSort_LinkedList { public static void main(String[] args) { diff --git a/sort/SortList_leetCode.java b/sort/SortList_leetCode.java index f4f31d3..05da6f9 100644 --- a/sort/SortList_leetCode.java +++ b/sort/SortList_leetCode.java @@ -1,6 +1,6 @@ package Algorithms.sort; -import Algorithms.ListNode; +import Algorithms.others.ListNode; /** * Definition for singly-linked list. From 4c6007ae521459716af984d17324c3af2016a7cf Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 22:49:16 -0700 Subject: [PATCH 071/319] list demo --- {others => list}/ListNodeDemo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename {others => list}/ListNodeDemo.java (99%) diff --git a/others/ListNodeDemo.java b/list/ListNodeDemo.java similarity index 99% rename from others/ListNodeDemo.java rename to list/ListNodeDemo.java index 3e0e717..fa03323 100644 --- a/others/ListNodeDemo.java +++ b/list/ListNodeDemo.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.list; import java.util.HashMap; import java.util.HashSet; From bc72e0739c83752cd68c33e86d2b0b14dfda8c76 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 22:50:36 -0700 Subject: [PATCH 072/319] demo --- list/ListNodeDemo.java => ListNodeDemo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename list/ListNodeDemo.java => ListNodeDemo.java (99%) diff --git a/list/ListNodeDemo.java b/ListNodeDemo.java similarity index 99% rename from list/ListNodeDemo.java rename to ListNodeDemo.java index fa03323..f23327d 100644 --- a/list/ListNodeDemo.java +++ b/ListNodeDemo.java @@ -1,4 +1,4 @@ -package Algorithms.list; +package Algorithms; import java.util.HashMap; import java.util.HashSet; From 68a548cdde951c7ce7928876c67cce3e55004b3b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 22:52:50 -0700 Subject: [PATCH 073/319] demo --- list/ListNodeDemo.java | 716 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 716 insertions(+) create mode 100644 list/ListNodeDemo.java diff --git a/list/ListNodeDemo.java b/list/ListNodeDemo.java new file mode 100644 index 0000000..fa03323 --- /dev/null +++ b/list/ListNodeDemo.java @@ -0,0 +1,716 @@ +package Algorithms.list; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Stack; + +/** + * REFS: + * http://blog.csdn.net/fightforyourdream/article/details/16353519 + * http://blog.csdn.net/luckyxiaoqiang/article/details/7393134 轻松搞定面试中的链表题目 + * http://www.cnblogs.com/jax/archive/2009/12/11/1621504.html 算法大全(1)单链表 + * + * 目录: + * 1. 求单链表中结点的个数: getListLength + * 2. 将单链表反转: reverseList(遍历),reverseListRec(递归) + * 3. 查找单链表中的倒数第K个节点(k > 0): reGetKthNode + * 4. 查找单链表的中间结点: getMiddleNode + * 5. 从尾到头打印单链表: reversePrintListStack,reversePrintListRec(递归) + * 6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList, mergeSortedListRec + * 7. 判断一个单链表中是否有环: hasCycle + * 8. 判断两个单链表是否相交: isIntersect + * 9. 求两个单链表相交的第一个节点: getFirstCommonNode + * 10. 已知一个单链表中存在环,求进入环中的第一个节点: detectCycle, getFirstNodeInCycleHashMap + * 11. 给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted: delete + * + */ + +public class ListNodeDemo { + + // create the link Node class. + // why use static: + // http://duqiangcise.iteye.com/blog/697476 + private static class ListNode { + int val; + ListNode next; + public ListNode(int val) { + this.val = val; + this.next = null; + } + + } + + public static void main(String[] args) { + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(2); + ListNode n3 = new ListNode(3); + ListNode n4 = new ListNode(4); + ListNode n5 = new ListNode(5); + ListNode n6 = new ListNode(6); + + ListNode m1 = new ListNode(5); + ListNode m2 = new ListNode(8); + ListNode m3 = new ListNode(9); + m1.next = m2; + m2.next = m3; + + ListNode c1 = new ListNode(1); + ListNode c2 = new ListNode(12); + c1.next = c2; + //c2.next = n1; + + ListNode mergeNode = mergeLink(m1, c1); + //ListNode mergeNode2 = mergeLink(m1, c1); + //ListNode mergeNode = mergeSortedList(m1, c1); + printList(mergeNode); + //printList(mergeNode2); + + System.out.println(); + + n1.next = n2; + n2.next = n3; + n3.next = n4; + n4.next = n5; + + printList(n1); + + Delete(n1, n5); + + printList(n1); + + // create a cycle + //n5.next = n3; + //n5.next = n6; + //n6.next = n4; + +// System.out.println(hasCycle(n1)); +// System.out.println(getListLength(n1)); +// printList(n1); +// +// //n1 = reverseList(n1); +// n1 = reverseListRec(n1); +// printList(n1); + +// ListNode ret = reGetKthNode(n1, 7); +// if (ret != null) { +// System.out.println(ret.val); +// } else { +// System.out.println("null"); +// } + + //reGetKthNodeRec(n1, 1); +// reGetKthNodeRec2(n1, 3); +// ListNode ret = getMiddleNode(n1); +// +// if (ret != null) { +// System.out.println(ret.val); +// } +// +// reversePrintListStackRec(n1); +// reversePrintListStack(n1); +// reversePrintListRev(n1); + + //printList(n1); + + System.out.println(isIntersect(n1, c1)); + + ListNode cross = getFirstCommonNode(n1, c1); + if (cross == null) { + System.out.println("null"); + } else { + System.out.println(cross.val); + } + + ListNode cross2 = getFirstNodeInCycleHashMap(c1); + if (cross2 == null) { + System.out.println("null"); + } else { + System.out.println(cross2.val); + } + } + + public static void printList(ListNode head) { + while (head != null) { + System.out.print(head.val + " "); + head = head.next; + } + + System.out.println(); + } + + // 获得ListNode 的长度 + public static int getListLength(ListNode head) { + if (head == null) { + return 0; + } + + int len = 0; + while (head != null) { + len++; + head = head.next; + } + + return len; + } + + /* + * 反转链表 + * 此算法亮点是:一次只需要处理把下一个节点指向curr, + * 不断循环,即可完成任务 + * */ + public static ListNode reverseList(ListNode head) { + if (head == null) { + return null; + } + + ListNode next = head.next; + ListNode curr = head; + + // 先把头节点的下一个指定. + curr.next = null; + + // 每次只需要将curr的next指向curr即可, + // 终止条件是:next是null 表示我们将所有的节点进行了翻转 + while (next != null) { + ListNode tmp = next.next; + next.next = curr; + curr = next; + next = tmp; + } + + return curr; + } + + // 翻转递归(递归) + // 递归的精髓在于你就默认reverseListRec已经成功帮你解决了子问题了!但别去想如何解决的 + // 现在只要处理当前node和子问题之间的关系。最后就能圆满解决整个问题。 + /* + head + 1 -> 2 -> 3 -> 4 + + head + 1-------------- + | + 4 -> 3 -> 2 // Node reHead = reverseListRec(head.next); + reHead head.next + + 4 -> 3 -> 2 -> 1 // head.next.next = head; + reHead + + 4 -> 3 -> 2 -> 1 -> null // head.next = null; + reHead + */ + public static ListNode reverseListRec(ListNode head) { + // if there is no node, or only one node, just return; + if (head == null || head.next == null) { + return head; + } + + ListNode reHead = reverseListRec(head.next); // 先求解子问题。 + head.next.next = head; // 将head 与被解决的子串的尾部相连。 + head.next = null; // head的下一个必须指向 null,因为head 是新的尾部. + + return reHead; + } + + /** + * 查找单链表中的倒数第K个结点(k > 0) + * 最普遍的方法是,先统计单链表中结点的个数,然后再找到第(n-k)个结点。注意链表为空,k为0,k为1,k大于链表中节点个数时的情况 + * 。时间复杂度为O(n)。代码略。 这里主要讲一下另一个思路,这种思路在其他题目中也会有应用。 + * 主要思路就是使用两个指针,先让前面的指针走到正向第k个结点 + * ,这样前后两个指针的距离差是k,之后前后两个指针一起向前走,前面的指针走到空时,后面指针所指结点就是倒数第k个结点 + * when k = 1, it should be the last node. + */ + public static ListNode reGetKthNode(ListNode head, int k) { + if (head == null) { + return null; + } + + ListNode fast = head; + + // 使fast and slow之间差 k + while (k > 0) { + if (fast == null) { + // 发生这种情况,说明k > sizeOfList. + return null; + } + fast = fast.next; + k--; + } + + while (fast != null) { + fast = fast.next; + head = head.next; + } + + return head; + } + + /* + * 递归打印出倒数第k个节点。 + * */ + static int level = 0; + public static void reGetKthNodeRec(ListNode head, int k) { + if (head == null) { + return; + } + + reGetKthNodeRec(head.next, k); + level++; + if (level == k) { + System.out.println(head.val); + } + } + + /* + * 递归打印出倒数第k个节点。 + * return: the length of the link. + * 此为改进的递归算法,使用此算法,不需要加入辅助变量。 + * */ + public static int reGetKthNodeRec2(ListNode head, int k) { + if (head == null) { + return 0; + } + + int len = reGetKthNodeRec2(head.next, k); + if (len == k - 1) { + System.out.println(head.val); + } + + return len + 1; + } + + /** + * 判断一个单链表中是否有环 + * 这里也是用到两个指针。如果一个链表中有环,也就是说用一个指针去遍历,是永远走不到头的。因此,我们可以用两个指针去遍历,一个指针一次走两步 + * ,一个指针一次走一步,如果有环,两个指针肯定会在环中相遇。时间复杂度为O(n) + */ + public static boolean hasCycle(ListNode head) { + ListNode slow = head; // 快指针每次前进两步 + ListNode fast = head; // 慢指针每次前进一步 + + // 如果fast没有到达尾部,那么slow也不会。所以不需要判定slow是不是null + while (fast != null && fast.next != null) { + fast = fast.next.next; + slow = slow.next; + if (slow == fast) { // 相遇,存在环 + return true; + } + } + + return false; + + } + + /* + * 4. 查找单链表的中间结点: getMiddleNode + * 这里只处理n个数为 奇数的情况 + * 我们可以设置2个 指针,一个快,一个慢 + * 1-2-3-null + * 当fast前进2n时,它到达3,链表长度是2n + 1 + * 中间节点应为(2n+1)/2 + 1 = n + 1; + * 所以,slow节点前进n恰好可以到达中间。 + * + * 边界: + * n = 1时,一开始就可以退出,仍然可以满足 + * 此算法特点: + * 1->2->3->4 + * 返回2 + */ + public static ListNode getMiddleNode(ListNode head) { + if (head == null) { + return null; + } + + ListNode fast = head; + ListNode slow = head; + + while (fast != null && fast.next != null && fast.next.next != null) { + fast = fast.next.next; + slow = slow.next; + } + + return slow; + } + + /** + * 5. 从尾到头打印单链表: reversePrintListStack,reversePrintListRec(递归) + * @param head + * @return + */ + public static void reversePrintListStackRec(ListNode head) { + if (head == null) { + return; + } + + // print the next first. + reversePrintListStackRec(head.next); + System.out.print(head.val + " "); + } + + /** + * 从尾到头打印单链表 + * 对于这种颠倒顺序的问题,我们应该就会想到栈,后进先出。所以,这一题要么自己使用栈,要么让系统使用栈,也就是递归。注意链表为空的情况 + * 。时间复杂度为O(n) + * + * 还有一种做法,是可以把链表反转,我们也可以从头到尾打印。 + */ + public static void reversePrintListStack(ListNode head) { + if (head == null) { + return; + } + + System.out.println(); + + Stack s = new Stack(); + while (head != null) { + s.push(head.val); + head = head.next; + } + + // print the next first. + while (!s.isEmpty()) { + System.out.print(s.pop() + " "); + } + } + + /** + * 从尾到头打印单链表 + * 是可以把链表反转,我们也可以从头到尾打印。 为了不影响原有的链表,可以再反转回来 + */ + public static void reversePrintListRev(ListNode head) { + if (head == null) { + return; + } + + ListNode rev = reverseList(head); + + System.out.println(); + + // print the next first. + ListNode curr = rev; + while (curr != null) { + System.out.print(rev.val + " "); + curr = curr.next; + } + + System.out.println(); + + //printList(rev); + reverseList(rev); + } + + /* + * 6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList, mergeSortedListRec + * + * 与merge sort思想类似. + * */ + public static ListNode mergeSortedList(ListNode head1, ListNode head2) { + if (head1 == null) { + return head2; + } else if (head2 == null) { + return head1; + } + + // 作为头节点的前一个节点 + ListNode dummyNode = new ListNode(0); + ListNode curr = dummyNode; + while (head1 != null && head2 != null) { + if (head1.val < head2.val) { + curr.next = head1; + head1 = head1.next; + } else { + curr.next = head2; + head2 = head2.next; + } + + curr = curr.next; + } + + // 把没有取完的链直接接在结果上即可。 + if (head1 != null) { + curr.next = head1; + } else { + curr.next = head2; + } + + return dummyNode.next; + } + + static class Node { + Node next; + int val; + Node (int val) { + this.val = val; + } + } + + public static ListNode mergeLink (ListNode aLink, ListNode bLink) { + ListNode dummy = new ListNode(0); + + ListNode root = dummy; + + while (aLink != null && bLink != null) { + if (aLink.val < bLink.val) { + dummy.next = aLink; + dummy = aLink; + aLink = aLink.next; + + } else { + dummy.next = bLink; + dummy = bLink; + bLink = bLink.next; + + } + } + + if (aLink != null) { + dummy.next = aLink; + } else { + dummy.next = bLink; + } + + return root.next; + } + + /* + * 先完成的算法,应该会简单一点儿。 + * 简直是优雅的算法啊!太棒了!只不过 为什么自己很难想出这么棒的算法呢? + * 虽然递归的原理每个人都懂,但是写出漂亮的递归真的是考验功底呢。 + * + * 精髓就是: 在每一次的Merge的处理时,只需要考虑merge一个元素,也就是提取出一个元素,而下一步的merge,交给下一步的recursion + * 来处理。 + */ + public static ListNode mergeSortedListRec(ListNode head1, ListNode head2) { + if (head1 == null) { + return head2; + } + + if (head2 == null) { + return head1; + } + + ListNode headMerge = null; + if (head1.val < head2.val) { + headMerge = head1; + head1.next = mergeSortedListRec(head1.next, head2); + } else { + headMerge = head2; + head2.next = mergeSortedListRec(head1, head2.next); + } + + return headMerge; + } + + + // http://fisherlei.blogspot.com/2013/11/leetcode-linked-list-cycle-ii-solution.html + // 更进一步,寻找环的起点,实际上,2点相遇后,我们再将某点放回起点,让它再走X的距离(X为起点到环的交点的距离), + // 即可让2个点相交在环的点处。 + public static ListNode detectCycle(ListNode head) { + ListNode slow = head; + ListNode fast = head; + + while (fast != null && fast.next != null) { + fast = fast.next.next; + slow = slow.next; + if (slow == fast) { + ListNode n1 = head; + while (true) { + if (n1 == slow) { // 注意,要选判断,再移动, + return n1; // because 环的起点有可能就在开始的地方。 + } + n1 = n1.next; + slow = slow.next; + } + } + } + + return null; + } + + /* + * * 8. 判断两个单链表是否相交: isIntersect + * http://blog.csdn.net/yunzhongguwu005/article/details/11527675 + * 求两个单链表是否相交分三种情况讨论: + * 1,如果两个链表一个有环,一个无环则一定不相交 + * 2.如果都没有环,则判断两个链表的最后节点是否相同,如果相同则相交,不相同则不相交。 + * 3.如果都有环,则判断一个链表环里的节点是否是另一个链表环里的节点。如果是则相交,如果不是则不相交。 + * + * 步骤如下: + * 1. 先判断2个链表有没有环。 + * 2. 如果都没有环,查最后节点是否相同 + * 3. 如果都有环,则将b链的环节点跑一圈,如果遇到A链中的节点,则返回true + */ + public static boolean isIntersect(ListNode head1, ListNode head2) { + if (head1 == null || head2 == null) { + return false; + } + + ListNode head1C = hasCycleRetNode(head1); + ListNode head2C = hasCycleRetNode(head2); + + // 两个链表都是有环的。 + if (head1C != null && head2C != null) { + ListNode tmp = head1C; + do { + // 放在前面判断,因为有可能当前节点就是要求的结果 + if (head1C == head2C) { + return true; + } + + // 跑一圈来找是不是同一个圈。 + head1C = head1C.next; + } while (tmp != head1C); + + return false; + // 两个链表都是没有环的 + } else if (head1C == null && head2C == null){ + while (head1.next != null) { + head1 = head1.next; + } + + while (head2.next != null) { + head2 = head2.next; + } + + // 无环的话,应该具有相同的尾节点. + return head1 == head2; + } else { + return false; + } + } + + /** + * 如果有环,返回在环内的某节点。否则返回null + */ + public static ListNode hasCycleRetNode(ListNode head) { + if (head == null) { + return head; + } + + ListNode s = head; + ListNode f = head; + + while (f != null && f.next != null) { + f = f.next.next; + s = s.next; + if (f == s) { + return f; + } + } + + return null; + } + + /* + * * 9. 求两个单链表相交的第一个节点: getFirstCommonNode + * 分为2种情况: + * + * 1. 没有环的情况. + * 求两个单链表相交的第一个节点 对第一个链表遍历,计算长度len1,同时保存最后一个节点的地址。 + * 对第二个链表遍历,计算长度len2,同时检查最后一个节点是否和第一个链表的最后一个节点相同,若不相同,不相交,结束。 + * 两个链表均从头节点开始,假设len1大于len2 + * ,那么将第一个链表先遍历len1-len2个节点,此时两个链表当前节点到第一个相交节点的距离就相等了,然后一起向后遍历,直到两个节点的地址相同。 + * 时间复杂度,O(len1+len2) + * + * ---- len2 + * |__________ + * | + * --------- len1 + * |---|<- len1-len2 + * + * 2. 有环的情况 + * (1). 交点在环上 + * 这样子的话,实际上我们可以求出2个交点。我们只要判断2个交点是不是相等。不相等,把2个交点返回任何一个。 + * (2). 交点不在环上,则计算出环的交点,然后len1 = 起点至环的交点,len2 = 起点至环的交点,然后如方法1相同的做法。 + */ + public static ListNode getFirstCommonNode(ListNode head1, ListNode head2) { + if (head1 == null || head2 == null) { + return null; + } + + ListNode cross1 = detectCycle(head1); + ListNode cross2 = detectCycle(head2); + + // There is no CIRCLE + if (cross1 == null && cross2 == null) { + int len1 = getListLength(head1); + int len2 = getListLength(head2); + + //将长的链截短 + if (len1 > len2) { + while (len1 > len2) { + head1 = head1.next; + len1--; + } + } else { + while (len2 > len1) { + head2 = head2.next; + len2--; + } + } + + while (head1 != null) { + if (head1.next == head2.next) { + return head1.next; + } + } + + return null; + } else if (cross1 != null && cross2 != null) { + return cross1; + } + + return null; + } + + /** + * 求进入环中的第一个节点 用HashSet做 一个无环的链表,它每个结点的地址都是不一样的。 + * 但如果有环,指针沿着链表移动,那这个指针最终会指向一个已经出现过的地址 以地址为哈希表的键值,每出现一个地址, + 只要出现重复的元素,就找到了环的交点. + */ + public static ListNode getFirstNodeInCycleHashMap(ListNode head) { + if (head == null) { + return null; + } + + HashSet h = new HashSet(); + while (head != null) { + if (h.contains(head)) { + return head; + } else { + h.add(head); + } + head = head.next; + } + + return null; + } + + /* + * 对于删除节点,我们普通的思路就是让该节点的前一个节点指向该节点的下一个节点,这种情况需要遍历找到该节点的前一个节点, + * 时间复杂度为O(n)。对于链表,链表中的每个节点结构都是一样的,所以我们可以把该节点的下一个节点的数据复制到该节点, + * 然后删除下一个节点即可。要注意最后一个节点的情况,这个时候只能用常见的方法来操作,先找到前一个节点, + * 但总体的平均时间复杂度还是O(1)。参考代码如下: + * */ + public static void Delete(ListNode head, ListNode toBeDeleted) { + if (head == null) { + return; + } + + if (toBeDeleted.next != null) { + toBeDeleted.val = toBeDeleted.next.val; + toBeDeleted.next = toBeDeleted.next.next; + } else { + while (head != null) { + if (head.next == toBeDeleted) { + head.next = toBeDeleted.next; + return; + } + head = head.next; + } + } + + return; + } +} From 20c17727576f74f62a28400c1b2196b3ebe80536 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 11 Oct 2014 23:54:55 -0700 Subject: [PATCH 074/319] DP --- dp/UniquePaths.java | 67 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 dp/UniquePaths.java diff --git a/dp/UniquePaths.java b/dp/UniquePaths.java new file mode 100644 index 0000000..3d596be --- /dev/null +++ b/dp/UniquePaths.java @@ -0,0 +1,67 @@ +package Algorithms.dp; + +public class UniquePaths { + public int uniquePaths(int m, int n) { + if (m == 0 || n == 0) { + return 0; + } + + // 经典DP题 + // 1. 状态表达式: D[i][j]: 代表从起点到这一点的所有的路径数目 + // 2. 递推公式: D[i][j] = D[i - 1][j] + D[i][j - 1] + // 3. 初始化: D[0][0] = 1 原点只有一种方法到达 + + int[][] D = new int[m][n]; + + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (i == 0 && j == 0) { + D[i][j] = 1; + } else if (i == 0) { + D[i][j] = D[i][j - 1]; + } else if (j == 0) { + D[i][j] = D[i - 1][j]; + } else { + D[i][j] = D[i - 1][j] + D[i][j - 1]; + } + } + } + + return D[m - 1][n - 1]; + } + + public int uniquePaths2(int m, int n) { + if (m == 0 || n == 0) { + return 0; + } + + // 经典DP题 + // 1. 状态表达式: D[i][j]: 代表从起点到这一点的所有的路径数目 + // 2. 递推公式: D[i][j] = D[i - 1][j] + D[i][j - 1] + // 3. 初始化: D[0][0] = 1 原点只有一种方法到达 + + int[][] D = new int[m][n]; + + // initiate. + D[0][0] = 1; + + // initiate the first line + for (int j = 1; j < n; j++) { + D[0][j] = D[0][j - 1]; + } + + // initiate the first column + for (int i = 1; i < m; i++) { + D[i][0] = D[i - 1][0]; + } + + // get the result. + for (int i = 1; i < m; i++) { + for (int j = 1; j < n; j++) { + D[i][j] = D[i - 1][j] + D[i][j - 1]; + } + } + + return D[m - 1][n - 1]; + } +} \ No newline at end of file From 8509dc2d1bcc918c4d1cfddbd94377aec69c611d Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 00:50:19 -0700 Subject: [PATCH 075/319] DP --- dp/UniquePathsWithObstacles.java | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 dp/UniquePathsWithObstacles.java diff --git a/dp/UniquePathsWithObstacles.java b/dp/UniquePathsWithObstacles.java new file mode 100644 index 0000000..3e14967 --- /dev/null +++ b/dp/UniquePathsWithObstacles.java @@ -0,0 +1,36 @@ +package Algorithms.dp; + +public class UniquePathsWithObstacles { + public int uniquePathsWithObstacles(int[][] obstacleGrid) { + if (obstacleGrid == null || obstacleGrid.length == 0 + || obstacleGrid[0].length == 0) { + return 0; + } + + int rows = obstacleGrid.length; + int cols = obstacleGrid[0].length; + + int[][] D = new int[rows][cols]; + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (obstacleGrid[i][j] == 1) { + D[i][j] = 0; + continue; + } + + if (i == 0 && j == 0) { + D[i][j] = 1; + } else if (i == 0) { + D[i][j] = D[i][j - 1]; + } else if (j == 0) { + D[i][j] = D[i - 1][j]; + } else { + D[i][j] = D[i - 1][j] + D[i][j - 1]; + } + } + } + + return D[rows - 1][cols - 1]; + } +} \ No newline at end of file From 2aa4f6dd3c29becbd1a48eaff4af105f750cf446 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 01:56:31 -0700 Subject: [PATCH 076/319] simplifypath --- string/SimplifyPath.java | 52 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 string/SimplifyPath.java diff --git a/string/SimplifyPath.java b/string/SimplifyPath.java new file mode 100644 index 0000000..3a75aa5 --- /dev/null +++ b/string/SimplifyPath.java @@ -0,0 +1,52 @@ +package Algorithms.string; + +import java.util.Stack; + +public class SimplifyPath { + public static void main(String[] strs) { + System.out.println(simplifyPath("//home")); + } + + public static String simplifyPath(String path) { + if (path == null || path.length() == 0) { + return null; + } + + /* + path = "/home/", => "/home" --> Split to : home + path = "/a/./b/../../c/", => "/c" --> splite to: a . b .. .. c + */ + // 注意 split的输入是一个字符串 /+ 可以匹配1个或多个/ + String[] strs = path.split("/+"); + + + + Stack s = new Stack(); + + for (String str: strs) { + //System.out.println("Print:" + str); + + if (str.equals("..")) { + // we should pop out a element. + if (!s.isEmpty()) { + s.pop(); + } + } else if (!str.equals(".") && !str.equals("")) { + s.push(str); + } + } + + StringBuilder sb = new StringBuilder(); + while (!s.isEmpty()) { + sb.insert(0, s.pop()); + sb.insert(0, '/'); + } + + // if we get a empty string, should return / + if (sb.length() ==0) { + sb.append('/'); + } + + return sb.toString(); + } +} From 5ec6b6fe3f1a808610fffd7916a822090ec63db1 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 02:33:32 -0700 Subject: [PATCH 077/319] array --- array/RemoveElement.java | 21 +++++++++++++++++++++ string/SimplifyPath.java | 13 +++++-------- 2 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 array/RemoveElement.java diff --git a/array/RemoveElement.java b/array/RemoveElement.java new file mode 100644 index 0000000..5972e26 --- /dev/null +++ b/array/RemoveElement.java @@ -0,0 +1,21 @@ +package Algorithms.array; + +public class RemoveElement { + public int removeElement(int[] A, int elem) { + if (A == null || A.length == 0) { + return 0; + } + + int cur = 0; + int len = 0; + while (cur < A.length) { + if (A[cur] != elem) { + A[len++] = A[cur++]; + } else { + cur++; + } + } + + return len; + } +} diff --git a/string/SimplifyPath.java b/string/SimplifyPath.java index 3a75aa5..61e5862 100644 --- a/string/SimplifyPath.java +++ b/string/SimplifyPath.java @@ -13,24 +13,21 @@ public static String simplifyPath(String path) { } /* - path = "/home/", => "/home" --> Split to : home - path = "/a/./b/../../c/", => "/c" --> splite to: a . b .. .. c + path = "/home/", => "/home" --> Split to : 空格 home + path = "/a/./b/../../c/", => "/c" --> splite to: 空格 a . b .. .. c */ - // 注意 split的输入是一个字符串 /+ 可以匹配1个或多个/ - String[] strs = path.split("/+"); - - + // 注意 split的输入是一个字符串 + String[] strs = path.split("/"); Stack s = new Stack(); for (String str: strs) { - //System.out.println("Print:" + str); - if (str.equals("..")) { // we should pop out a element. if (!s.isEmpty()) { s.pop(); } + // should skip the space and the '.' } else if (!str.equals(".") && !str.equals("")) { s.push(str); } From 6de077be9973c37661944d5a8c81ef175bbb2966 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 14:15:43 -0700 Subject: [PATCH 078/319] algorithm --- dfs/SolveNQueens.java | 93 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 dfs/SolveNQueens.java diff --git a/dfs/SolveNQueens.java b/dfs/SolveNQueens.java new file mode 100644 index 0000000..3bd4ca0 --- /dev/null +++ b/dfs/SolveNQueens.java @@ -0,0 +1,93 @@ +package Algorithms.dfs; + +import java.util.ArrayList; +import java.util.List; + +public class SolveNQueens { + public static void main(String[] strs) { + List list = solveNQueens(9); + + for (String[] strss: list) { + for (String s: strss) { + System.out.println(s); + } + + } + + //System.out.println(solveNQueens(4).toString()); + } + + public static List solveNQueens(int n) { + List ret = new ArrayList(); + if (n == 0) { + return ret; + } + + StringBuilder[] path = new StringBuilder[n]; + for (int i = 0; i < n; i++) { + path[i] = new StringBuilder(); + for (int j = 0; j < n; j++) { + path[i].append('.'); + } + } + dfs(n, path, ret, 0); + + return ret; + } + + // 递归定义为:棋盘上已经有一些棋子,还需要放n个皇后,求所有的可能的解. + // 那么 我们可以先放1个,这里有多种可能,然后再用递归继续求解即可。 + public static void dfs(int n, StringBuilder[] path, List ret, int index) { + int rows = path.length; + + if (n == 0) { + String[] strs = new String[rows]; + for (int i = 0; i < rows; i++) { + strs[i] = path[i].toString(); + } + ret.add(strs); + return; + } + + // index out of bound; + if (index >= rows * rows) { + return; + } + + // 找到一个地方先放一个棋子 + for (int i = index; i < rows*rows; i++) { + int row = i / rows; + int col = i % rows; + + if (!canPut(path, row, col)) { + // 这个位置必须是可放置的 + continue; + } + path[row].setCharAt(col, 'Q'); + + // 向下一级递归 + dfs(n - 1, path, ret, i + 1); + + //回溯 + path[row].setCharAt(col, '.'); + + } + + return; + } + + // put a chessman, and disable some positions in the chessboard. + public static boolean canPut(StringBuilder[] path, int row, int col) { + for (int i = 0; i < path.length; i++) { + for (int j = 0; j < path.length; j++) { + if (path[i].charAt(j) == 'Q' && + (i == row || j == col || Math.abs(i - row) == Math.abs(j - col)) + ) { + return false; + } + } + } + + return true; + } +} From d7576ec93a01f71f81fe2c22d3f562658bb1c20d Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 14:21:25 -0700 Subject: [PATCH 079/319] reorder --- {facebook => algorithm/interview/facebook}/SortWeight.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename {facebook => algorithm/interview/facebook}/SortWeight.java (99%) diff --git a/facebook/SortWeight.java b/algorithm/interview/facebook/SortWeight.java similarity index 99% rename from facebook/SortWeight.java rename to algorithm/interview/facebook/SortWeight.java index 7172043..c69bb9d 100644 --- a/facebook/SortWeight.java +++ b/algorithm/interview/facebook/SortWeight.java @@ -1,4 +1,4 @@ -package Algorithms.facebook; +package Algorithms.algorithm.interview.facebook; import java.util.ArrayList; import java.util.Collections; From 095d620cafef648f4f150a5952cd1dcd031e8123 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 14:22:13 -0700 Subject: [PATCH 080/319] dp --- algorithm/dp/MinPath_Block.java | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 algorithm/dp/MinPath_Block.java diff --git a/algorithm/dp/MinPath_Block.java b/algorithm/dp/MinPath_Block.java new file mode 100644 index 0000000..17078b0 --- /dev/null +++ b/algorithm/dp/MinPath_Block.java @@ -0,0 +1,5 @@ +package Algorithms.algorithm.dp; + +public class MinPath_Block { + +} From 3d9829432396ada8fd2b15071f56c0c1e77f3f39 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 14:27:01 -0700 Subject: [PATCH 081/319] reorder --- .../facebook/SortWeight.java | 30 +++++++++---------- tree/TreeLinkNode.java | 6 ++-- tree/sortedListToBST.java | 6 +++- 3 files changed, 24 insertions(+), 18 deletions(-) rename algorithm/{interview => interviews}/facebook/SortWeight.java (85%) diff --git a/algorithm/interview/facebook/SortWeight.java b/algorithm/interviews/facebook/SortWeight.java similarity index 85% rename from algorithm/interview/facebook/SortWeight.java rename to algorithm/interviews/facebook/SortWeight.java index c69bb9d..4e8b072 100644 --- a/algorithm/interview/facebook/SortWeight.java +++ b/algorithm/interviews/facebook/SortWeight.java @@ -1,4 +1,4 @@ -package Algorithms.algorithm.interview.facebook; +package Algorithms.algorithm.interviews.facebook; import java.util.ArrayList; import java.util.Collections; @@ -34,16 +34,16 @@ public static LinkedList sortWeight(String input) { float defautWeight = 5; - // 当weight = -1,表示这一组食物-重量链还未完成 + // ???weight = -1????????????????????????-????????????????????? String food = null; float weight = 0; - // 记录某重量下所有的食物 + // ????????????????????????????????? HashMap> map = new HashMap>(); // Go through the string. for (String s: strs) { - // 上一次的food-weight对已经结束 + // ????????????food-weight??????????????? if (weight != -1) { food = s; weight = -1; @@ -58,7 +58,7 @@ public static LinkedList sortWeight(String input) { // a new food. addFoodToMap(map, food, defautWeight); - // 开始新一轮的食物-重量链 + // ????????????????????????-????????? food = s; weight = -1; } @@ -93,7 +93,7 @@ public static class Pair implements Comparable { this.weight = weight; } - // 注意,我们用o来减当前的重量,就能得到降序的排列 + // ??????????????????o??????????????????????????????????????????????????? public int compareTo(Pair o) { if (o.weight - this.weight < 0) { return -1; @@ -104,8 +104,8 @@ public int compareTo(Pair o) { } /* - * 使用自定义结构体 Pair而不是hashmap来记录食物-重量对。可以简化算法。 - * 但这时就需要自定义一个compareTo方法 + * ???????????????????????? Pair?????????hashmap???????????????-????????????????????????????????? + * ?????????????????????????????????compareTo?????? * */ public static LinkedList sortWeight2(String input) { LinkedList ret = new LinkedList(); @@ -117,16 +117,16 @@ public static LinkedList sortWeight2(String input) { float defautWeight = 5; - // 当weight = -1,表示这一组食物-重量链还未完成 + // ???weight = -1????????????????????????-????????????????????? String food = null; float weight = 0; - // 使用ArrayList来记录食物-重量对 + // ??????ArrayList???????????????-????????? ArrayList list = new ArrayList(); // Go through the string. for (String s: strs) { - // 上一次的food-weight对已经结束 + // ????????????food-weight??????????????? if (weight != -1) { food = s; weight = -1; @@ -141,7 +141,7 @@ public static LinkedList sortWeight2(String input) { // a new food. list.add(new Pair(food, defautWeight)); - // 开始新一轮的食物-重量链 + // ????????????????????????-????????? food = s; weight = -1; } @@ -166,13 +166,13 @@ public static LinkedList sortWeight2(String input) { public static void addFoodToMap(HashMap> map, String food, float weight) { - // 把上一次的食物-重量终结 + // ?????????????????????-???????????? ArrayList list = map.get(weight); if (list != null) { - // 在相应的重量下添加食物 + // ????????????????????????????????? list.add(food); } else { - // 新建一个重量链 + // ????????????????????? ArrayList listNew = new ArrayList(); listNew.add(food); map.put(weight, listNew); diff --git a/tree/TreeLinkNode.java b/tree/TreeLinkNode.java index d81489c..dd3a909 100644 --- a/tree/TreeLinkNode.java +++ b/tree/TreeLinkNode.java @@ -1,6 +1,8 @@ package Algorithms.tree; public class TreeLinkNode { int val; - TreeLinkNode left, right, next; - TreeLinkNode(int x) { val = x; } + public TreeLinkNode left; + public TreeLinkNode right; + TreeLinkNode next; + public TreeLinkNode(int x) { val = x; } } \ No newline at end of file diff --git a/tree/sortedListToBST.java b/tree/sortedListToBST.java index eaac151..574f251 100644 --- a/tree/sortedListToBST.java +++ b/tree/sortedListToBST.java @@ -1,3 +1,7 @@ +package Algorithms.tree; + +import Algorithms.others.ListNode; + /** * Definition for singly-linked list. * public class ListNode {h @@ -15,7 +19,7 @@ * TreeNode(int x) { val = x; } * } */ -public class Solution { +public class sortedListToBST { public TreeNode sortedListToBST1(ListNode head) { ListNode fast = head; ListNode slow = head; From f9795194d0a8f55fb09a0c86eeaf45537a8c7608 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 14:30:20 -0700 Subject: [PATCH 082/319] reorder --- {others => algorithm/others}/AddBinary.java | 2 +- algorithm/others/Ag.java | 7 ++++++ {others => algorithm/others}/Anagrams.java | 2 +- .../others}/BinarySearch.java | 2 +- .../others}/Combination2.java | 2 +- .../others}/CombinationSum.java | 2 +- .../others}/DivideTwoIntegers.java | 2 +- .../others}/FindKthNumber.java | 2 +- {others => algorithm/others}/FindSame.java | 2 +- {others => algorithm/others}/Flatten.java | 2 +- .../others}/GenerateParentheses.java | 2 +- {others => algorithm/others}/GraphDemo.java | 10 ++++---- .../others}/InOrderTraversal.java | 2 +- .../others}/Insertion_Link.java | 2 +- .../others}/Interleaving.java | 2 +- .../others}/IntersectionOfThreeSets.java | 2 +- {others => algorithm/others}/IsMach.java | 24 +++++++++---------- {others => algorithm/others}/IsSymmetric.java | 2 +- .../others}/JavaAppWithoutMain.java | 2 +- .../others}/KthLargestElement.java | 2 +- {others => algorithm/others}/KthSort.java | 2 +- {others => algorithm/others}/LRUCache.java | 2 +- .../others}/LargestRectangleArea.java | 2 +- {others => algorithm/others}/Line.java | 2 +- {others => algorithm/others}/ListNode.java | 2 +- {others => algorithm/others}/LongestPare.java | 2 +- .../others}/Max_path_BinaryTree.java | 2 +- {others => algorithm/others}/MiniStack.java | 2 +- .../others}/MinimumWindowSubString.java | 2 +- .../others}/MortgageCalculator.java | 2 +- .../others}/MutiplyString.java | 2 +- .../others}/NumDecodings.java | 2 +- {others => algorithm/others}/NumTree.java | 2 +- .../others}/PartitionArray.java | 2 +- {others => algorithm/others}/Permute.java | 2 +- {others => algorithm/others}/PlusOne.java | 2 +- {others => algorithm/others}/Point.java | 2 +- {others => algorithm/others}/Populate2.java | 2 +- {others => algorithm/others}/Premute.java | 2 +- {others => algorithm/others}/Recover.java | 2 +- {others => algorithm/others}/Rectangle.java | 2 +- algorithm/others/ReverseString.java | 5 ++++ .../others}/SearchInRotatedArray.java | 2 +- algorithm/others/SingleNumber2.java | 5 ++++ {others => algorithm/others}/SortColors.java | 2 +- {others => algorithm/others}/SortList.java | 2 +- .../others}/SpiralMatrix.java | 2 +- {others => algorithm/others}/SpiralOrder.java | 2 +- {others => algorithm/others}/Sqrt.java | 2 +- {others => algorithm/others}/SubSet2.java | 2 +- {others => algorithm/others}/Subset.java | 2 +- .../others}/SurroundRegions.java | 4 ++-- .../others}/TestArrayChange.java | 2 +- .../others}/TreeSumCloset.java | 2 +- {others => algorithm/others}/WordBreak2.java | 2 +- .../others}/ZigzagLevelOrder.java | 2 +- .../others}/letterCombinations.java | 2 +- list/DeleteDuplicates.java | 2 +- list/DeleteDuplicates2.java | 2 +- list/MergeKLists.java | 2 +- list/MergeTwoLists.java | 2 +- list/PartitionList.java | 2 +- list/RemoveNthFromEnd.java | 2 +- list/ReorderList.java | 2 +- list/ReverseBetween.java | 2 +- list/ReverseLinkedList2.java | 2 +- list/RotateList.java | 2 +- others/Ag.java | 7 ------ others/ReverseString.java | 5 ---- others/SingleNumber2.java | 5 ---- sort/InsertionSortList.java | 2 +- sort/MergeSort_LinkedList.java | 2 +- sort/SortList_leetCode.java | 2 +- tree/sortedListToBST.java | 2 +- 74 files changed, 101 insertions(+), 101 deletions(-) rename {others => algorithm/others}/AddBinary.java (97%) create mode 100644 algorithm/others/Ag.java rename {others => algorithm/others}/Anagrams.java (97%) rename {others => algorithm/others}/BinarySearch.java (97%) rename {others => algorithm/others}/Combination2.java (97%) rename {others => algorithm/others}/CombinationSum.java (98%) rename {others => algorithm/others}/DivideTwoIntegers.java (94%) rename {others => algorithm/others}/FindKthNumber.java (97%) rename {others => algorithm/others}/FindSame.java (96%) rename {others => algorithm/others}/Flatten.java (95%) rename {others => algorithm/others}/GenerateParentheses.java (98%) rename {others => algorithm/others}/GraphDemo.java (91%) rename {others => algorithm/others}/InOrderTraversal.java (95%) rename {others => algorithm/others}/Insertion_Link.java (97%) rename {others => algorithm/others}/Interleaving.java (98%) rename {others => algorithm/others}/IntersectionOfThreeSets.java (96%) rename {others => algorithm/others}/IsMach.java (67%) rename {others => algorithm/others}/IsSymmetric.java (97%) rename {others => algorithm/others}/JavaAppWithoutMain.java (75%) rename {others => algorithm/others}/KthLargestElement.java (98%) rename {others => algorithm/others}/KthSort.java (96%) rename {others => algorithm/others}/LRUCache.java (98%) rename {others => algorithm/others}/LargestRectangleArea.java (94%) rename {others => algorithm/others}/Line.java (98%) rename {others => algorithm/others}/ListNode.java (92%) rename {others => algorithm/others}/LongestPare.java (98%) rename {others => algorithm/others}/Max_path_BinaryTree.java (98%) rename {others => algorithm/others}/MiniStack.java (98%) rename {others => algorithm/others}/MinimumWindowSubString.java (98%) rename {others => algorithm/others}/MortgageCalculator.java (99%) rename {others => algorithm/others}/MutiplyString.java (97%) rename {others => algorithm/others}/NumDecodings.java (97%) rename {others => algorithm/others}/NumTree.java (95%) rename {others => algorithm/others}/PartitionArray.java (96%) rename {others => algorithm/others}/Permute.java (96%) rename {others => algorithm/others}/PlusOne.java (95%) rename {others => algorithm/others}/Point.java (79%) rename {others => algorithm/others}/Populate2.java (98%) rename {others => algorithm/others}/Premute.java (98%) rename {others => algorithm/others}/Recover.java (96%) rename {others => algorithm/others}/Rectangle.java (97%) create mode 100644 algorithm/others/ReverseString.java rename {others => algorithm/others}/SearchInRotatedArray.java (98%) create mode 100644 algorithm/others/SingleNumber2.java rename {others => algorithm/others}/SortColors.java (97%) rename {others => algorithm/others}/SortList.java (97%) rename {others => algorithm/others}/SpiralMatrix.java (96%) rename {others => algorithm/others}/SpiralOrder.java (97%) rename {others => algorithm/others}/Sqrt.java (96%) rename {others => algorithm/others}/SubSet2.java (97%) rename {others => algorithm/others}/Subset.java (98%) rename {others => algorithm/others}/SurroundRegions.java (95%) rename {others => algorithm/others}/TestArrayChange.java (93%) rename {others => algorithm/others}/TreeSumCloset.java (98%) rename {others => algorithm/others}/WordBreak2.java (98%) rename {others => algorithm/others}/ZigzagLevelOrder.java (99%) rename {others => algorithm/others}/letterCombinations.java (98%) delete mode 100644 others/Ag.java delete mode 100644 others/ReverseString.java delete mode 100644 others/SingleNumber2.java diff --git a/others/AddBinary.java b/algorithm/others/AddBinary.java similarity index 97% rename from others/AddBinary.java rename to algorithm/others/AddBinary.java index 2463fcf..bc19c4f 100644 --- a/others/AddBinary.java +++ b/algorithm/others/AddBinary.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class AddBinary { public static void main(String[] args) { diff --git a/algorithm/others/Ag.java b/algorithm/others/Ag.java new file mode 100644 index 0000000..9e5b187 --- /dev/null +++ b/algorithm/others/Ag.java @@ -0,0 +1,7 @@ +package Algorithms.algorithm.others; + + + +abstract public class Ag { + +} diff --git a/others/Anagrams.java b/algorithm/others/Anagrams.java similarity index 97% rename from others/Anagrams.java rename to algorithm/others/Anagrams.java index e27fda6..1d79f88 100644 --- a/others/Anagrams.java +++ b/algorithm/others/Anagrams.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; import java.util.HashMap; diff --git a/others/BinarySearch.java b/algorithm/others/BinarySearch.java similarity index 97% rename from others/BinarySearch.java rename to algorithm/others/BinarySearch.java index 8ccfa1a..b842c45 100644 --- a/others/BinarySearch.java +++ b/algorithm/others/BinarySearch.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class BinarySearch { public static void main(String[] strs) { diff --git a/others/Combination2.java b/algorithm/others/Combination2.java similarity index 97% rename from others/Combination2.java rename to algorithm/others/Combination2.java index ecb6f11..fb87aed 100644 --- a/others/Combination2.java +++ b/algorithm/others/Combination2.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; import java.util.Arrays; diff --git a/others/CombinationSum.java b/algorithm/others/CombinationSum.java similarity index 98% rename from others/CombinationSum.java rename to algorithm/others/CombinationSum.java index 80b7a5a..4c7f2d4 100644 --- a/others/CombinationSum.java +++ b/algorithm/others/CombinationSum.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; import java.util.Arrays; diff --git a/others/DivideTwoIntegers.java b/algorithm/others/DivideTwoIntegers.java similarity index 94% rename from others/DivideTwoIntegers.java rename to algorithm/others/DivideTwoIntegers.java index 17ff86f..e2ad42d 100644 --- a/others/DivideTwoIntegers.java +++ b/algorithm/others/DivideTwoIntegers.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class DivideTwoIntegers { public static void main(String[] args) { diff --git a/others/FindKthNumber.java b/algorithm/others/FindKthNumber.java similarity index 97% rename from others/FindKthNumber.java rename to algorithm/others/FindKthNumber.java index a15542a..53c05f3 100644 --- a/others/FindKthNumber.java +++ b/algorithm/others/FindKthNumber.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class FindKthNumber { diff --git a/others/FindSame.java b/algorithm/others/FindSame.java similarity index 96% rename from others/FindSame.java rename to algorithm/others/FindSame.java index b608637..13ef64e 100644 --- a/others/FindSame.java +++ b/algorithm/others/FindSame.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.LinkedList; diff --git a/others/Flatten.java b/algorithm/others/Flatten.java similarity index 95% rename from others/Flatten.java rename to algorithm/others/Flatten.java index 31ffeda..0e226c3 100644 --- a/others/Flatten.java +++ b/algorithm/others/Flatten.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.Stack; import Algorithms.tree.TreeNode; diff --git a/others/GenerateParentheses.java b/algorithm/others/GenerateParentheses.java similarity index 98% rename from others/GenerateParentheses.java rename to algorithm/others/GenerateParentheses.java index 5b5e593..beae96a 100644 --- a/others/GenerateParentheses.java +++ b/algorithm/others/GenerateParentheses.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; import java.util.Stack; diff --git a/others/GraphDemo.java b/algorithm/others/GraphDemo.java similarity index 91% rename from others/GraphDemo.java rename to algorithm/others/GraphDemo.java index b7f954a..2f34649 100644 --- a/others/GraphDemo.java +++ b/algorithm/others/GraphDemo.java @@ -1,14 +1,14 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; public class GraphDemo { - private static int M = Integer.MAX_VALUE; // 表示此路不可通 + private static int M = Integer.MAX_VALUE; // ????????????????????? // http://www.geeksforgeeks.org/greedy-algorithms-set-6-dijkstras-shortest-path-algorithm/ - // 以上为不能再优美的C语言实现。 + // ???????????????????????????C??????????????? public static void main(String[] args) { - int[][] w = { // 用邻接表矩阵表示的无向图 + int[][] w = { // ???????????????????????????????????? {0, 3, 2000, 7, M}, {3, 0, 4, 2, M}, {M, 4, 0, 5, 4}, @@ -16,7 +16,7 @@ public static void main(String[] args) { {M, M , 4, 6, 0} }; - int[][] w2 = { // 用邻接表矩阵表示的无向图 + int[][] w2 = { // ???????????????????????????????????? {0, 10, M, 30, 100}, {M, 0, 50, M, M}, {M, M, 0, M, 10}, diff --git a/others/InOrderTraversal.java b/algorithm/others/InOrderTraversal.java similarity index 95% rename from others/InOrderTraversal.java rename to algorithm/others/InOrderTraversal.java index 28fe5a0..d802883 100644 --- a/others/InOrderTraversal.java +++ b/algorithm/others/InOrderTraversal.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; import java.util.Stack; diff --git a/others/Insertion_Link.java b/algorithm/others/Insertion_Link.java similarity index 97% rename from others/Insertion_Link.java rename to algorithm/others/Insertion_Link.java index ab99a8d..babef0c 100644 --- a/others/Insertion_Link.java +++ b/algorithm/others/Insertion_Link.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class Insertion_Link { public static void main(String[] str) { diff --git a/others/Interleaving.java b/algorithm/others/Interleaving.java similarity index 98% rename from others/Interleaving.java rename to algorithm/others/Interleaving.java index a2ec047..e74ef19 100644 --- a/others/Interleaving.java +++ b/algorithm/others/Interleaving.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class Interleaving { public static void main(String[] strs) { System.out.println(isInterleave("a", "b", "ab")); diff --git a/others/IntersectionOfThreeSets.java b/algorithm/others/IntersectionOfThreeSets.java similarity index 96% rename from others/IntersectionOfThreeSets.java rename to algorithm/others/IntersectionOfThreeSets.java index 729d731..8b41852 100644 --- a/others/IntersectionOfThreeSets.java +++ b/algorithm/others/IntersectionOfThreeSets.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.HashMap; import java.util.LinkedList; diff --git a/others/IsMach.java b/algorithm/others/IsMach.java similarity index 67% rename from others/IsMach.java rename to algorithm/others/IsMach.java index b528be7..32c5930 100644 --- a/others/IsMach.java +++ b/algorithm/others/IsMach.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class IsMach { public static void main(String[] str) { @@ -18,37 +18,37 @@ public static boolean help(String s, String p, int indexS, int indexP) { int pLen = p.length(); int sLen = s.length(); - // 1. P结束了,这时 S也应该要结束 + // 1. P?????????????????? S?????????????????? if (indexP == pLen) { return indexS == sLen; } - // 2. P 只有最后一个没有匹配 + // 2. P ?????????????????????????????? if (indexP == pLen - 1) { - // 必须相等,或者是p为'.'. - // S必须只有一个字符 + // ????????????????????????p???'.'. + // S???????????????????????? return indexS == sLen - 1 && matchChar(s, p, indexS, indexP); } - // 以下P 至少还有2个字符. + // ??????P ????????????2?????????. - // 2. 单独匹配的情况, 如 aa, a. 类似这样 + // 2. ?????????????????????, ??? aa, a. ???????????? if (p.charAt(indexP + 1) != '*') { if (indexS < sLen && matchChar(s, p, indexS, indexP)) { - return help(s, p, indexS + 1, indexP + 1); // p可以前进一格 + return help(s, p, indexS + 1, indexP + 1); // p?????????????????? } else { return false; } } - // 3. 多重匹配的情况, 如 .* or a* ,这时需要进行递归 + // 3. ?????????????????????, ??? .* or a* ,???????????????????????? - // 先直接跳过此2个正则,因为我们可以匹配空。 + // ??????????????????2?????????????????????????????????????????? if (help(s, p, indexS, indexP + 2)) { return true; } - // 匹配非空的情况,这里不可以跳过p,必须 匹配1个或是多个 + // ?????????????????????,?????????????????????p????????? ??????1??????????????? for (int i = indexS; i < sLen; i++) { if (!matchChar(s, p, i, indexP)) { return false; @@ -59,7 +59,7 @@ public static boolean help(String s, String p, int indexS, int indexP) { } } - // 多重匹配之后,余下的字串仍然不可以匹配,则返回失败。 + // ?????????????????????????????????????????????????????????????????????????????? return false; } diff --git a/others/IsSymmetric.java b/algorithm/others/IsSymmetric.java similarity index 97% rename from others/IsSymmetric.java rename to algorithm/others/IsSymmetric.java index 2dcd423..a3f864a 100644 --- a/others/IsSymmetric.java +++ b/algorithm/others/IsSymmetric.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayDeque; diff --git a/others/JavaAppWithoutMain.java b/algorithm/others/JavaAppWithoutMain.java similarity index 75% rename from others/JavaAppWithoutMain.java rename to algorithm/others/JavaAppWithoutMain.java index 0e099e4..ab020d2 100644 --- a/others/JavaAppWithoutMain.java +++ b/algorithm/others/JavaAppWithoutMain.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class JavaAppWithoutMain { static diff --git a/others/KthLargestElement.java b/algorithm/others/KthLargestElement.java similarity index 98% rename from others/KthLargestElement.java rename to algorithm/others/KthLargestElement.java index 89647ae..9d0fe33 100644 --- a/others/KthLargestElement.java +++ b/algorithm/others/KthLargestElement.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; import java.util.Collections; diff --git a/others/KthSort.java b/algorithm/others/KthSort.java similarity index 96% rename from others/KthSort.java rename to algorithm/others/KthSort.java index 58603fc..20c3200 100644 --- a/others/KthSort.java +++ b/algorithm/others/KthSort.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.HashMap; diff --git a/others/LRUCache.java b/algorithm/others/LRUCache.java similarity index 98% rename from others/LRUCache.java rename to algorithm/others/LRUCache.java index 6c04280..2dfcc92 100644 --- a/others/LRUCache.java +++ b/algorithm/others/LRUCache.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.HashMap; diff --git a/others/LargestRectangleArea.java b/algorithm/others/LargestRectangleArea.java similarity index 94% rename from others/LargestRectangleArea.java rename to algorithm/others/LargestRectangleArea.java index 0824825..d374156 100644 --- a/others/LargestRectangleArea.java +++ b/algorithm/others/LargestRectangleArea.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.Stack; diff --git a/others/Line.java b/algorithm/others/Line.java similarity index 98% rename from others/Line.java rename to algorithm/others/Line.java index 9621f2a..d5f56e2 100644 --- a/others/Line.java +++ b/algorithm/others/Line.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.Comparator; import java.util.HashMap; diff --git a/others/ListNode.java b/algorithm/others/ListNode.java similarity index 92% rename from others/ListNode.java rename to algorithm/others/ListNode.java index edee146..6ff9fba 100644 --- a/others/ListNode.java +++ b/algorithm/others/ListNode.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class ListNode { public int val; diff --git a/others/LongestPare.java b/algorithm/others/LongestPare.java similarity index 98% rename from others/LongestPare.java rename to algorithm/others/LongestPare.java index 1f9ab1f..34c046d 100644 --- a/others/LongestPare.java +++ b/algorithm/others/LongestPare.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.Stack; diff --git a/others/Max_path_BinaryTree.java b/algorithm/others/Max_path_BinaryTree.java similarity index 98% rename from others/Max_path_BinaryTree.java rename to algorithm/others/Max_path_BinaryTree.java index 16cfca6..be76468 100644 --- a/others/Max_path_BinaryTree.java +++ b/algorithm/others/Max_path_BinaryTree.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; import Algorithms.tree.TreeNode; diff --git a/others/MiniStack.java b/algorithm/others/MiniStack.java similarity index 98% rename from others/MiniStack.java rename to algorithm/others/MiniStack.java index ba53553..cc70e69 100644 --- a/others/MiniStack.java +++ b/algorithm/others/MiniStack.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.Stack; diff --git a/others/MinimumWindowSubString.java b/algorithm/others/MinimumWindowSubString.java similarity index 98% rename from others/MinimumWindowSubString.java rename to algorithm/others/MinimumWindowSubString.java index 0eb0a52..913ce3d 100644 --- a/others/MinimumWindowSubString.java +++ b/algorithm/others/MinimumWindowSubString.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.HashMap; public class MinimumWindowSubString { diff --git a/others/MortgageCalculator.java b/algorithm/others/MortgageCalculator.java similarity index 99% rename from others/MortgageCalculator.java rename to algorithm/others/MortgageCalculator.java index 32d25e1..b46bfac 100644 --- a/others/MortgageCalculator.java +++ b/algorithm/others/MortgageCalculator.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.text.NumberFormat; diff --git a/others/MutiplyString.java b/algorithm/others/MutiplyString.java similarity index 97% rename from others/MutiplyString.java rename to algorithm/others/MutiplyString.java index 3d009a1..8517f78 100644 --- a/others/MutiplyString.java +++ b/algorithm/others/MutiplyString.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class MutiplyString { public static void main(String[] args) { MutiplyString ms = new MutiplyString(); diff --git a/others/NumDecodings.java b/algorithm/others/NumDecodings.java similarity index 97% rename from others/NumDecodings.java rename to algorithm/others/NumDecodings.java index c455c25..2e1d0f8 100644 --- a/others/NumDecodings.java +++ b/algorithm/others/NumDecodings.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class NumDecodings { public static void main(String[] strs) { diff --git a/others/NumTree.java b/algorithm/others/NumTree.java similarity index 95% rename from others/NumTree.java rename to algorithm/others/NumTree.java index 3518ac0..6a807a6 100644 --- a/others/NumTree.java +++ b/algorithm/others/NumTree.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class NumTree { public static void main(String[] strs) { diff --git a/others/PartitionArray.java b/algorithm/others/PartitionArray.java similarity index 96% rename from others/PartitionArray.java rename to algorithm/others/PartitionArray.java index 135d945..c4a1e47 100644 --- a/others/PartitionArray.java +++ b/algorithm/others/PartitionArray.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class PartitionArray { public static void main(String[] strs) { diff --git a/others/Permute.java b/algorithm/others/Permute.java similarity index 96% rename from others/Permute.java rename to algorithm/others/Permute.java index 3f9527c..290f3b2 100644 --- a/others/Permute.java +++ b/algorithm/others/Permute.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; import java.util.Arrays; diff --git a/others/PlusOne.java b/algorithm/others/PlusOne.java similarity index 95% rename from others/PlusOne.java rename to algorithm/others/PlusOne.java index 05dc69a..ec0dacd 100644 --- a/others/PlusOne.java +++ b/algorithm/others/PlusOne.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class PlusOne { public static void main(String[] args) { diff --git a/others/Point.java b/algorithm/others/Point.java similarity index 79% rename from others/Point.java rename to algorithm/others/Point.java index 8b360cf..615d2b3 100644 --- a/others/Point.java +++ b/algorithm/others/Point.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; class Point { int x; diff --git a/others/Populate2.java b/algorithm/others/Populate2.java similarity index 98% rename from others/Populate2.java rename to algorithm/others/Populate2.java index 9894844..a4097dd 100644 --- a/others/Populate2.java +++ b/algorithm/others/Populate2.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import Algorithms.tree.TreeLinkNode; diff --git a/others/Premute.java b/algorithm/others/Premute.java similarity index 98% rename from others/Premute.java rename to algorithm/others/Premute.java index f98d1c9..7487874 100644 --- a/others/Premute.java +++ b/algorithm/others/Premute.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; import java.util.Arrays; diff --git a/others/Recover.java b/algorithm/others/Recover.java similarity index 96% rename from others/Recover.java rename to algorithm/others/Recover.java index 74aad22..7cde9de 100644 --- a/others/Recover.java +++ b/algorithm/others/Recover.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import Algorithms.tree.TreeNode; diff --git a/others/Rectangle.java b/algorithm/others/Rectangle.java similarity index 97% rename from others/Rectangle.java rename to algorithm/others/Rectangle.java index a309fbf..8e1438d 100644 --- a/others/Rectangle.java +++ b/algorithm/others/Rectangle.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.Stack; diff --git a/algorithm/others/ReverseString.java b/algorithm/others/ReverseString.java new file mode 100644 index 0000000..6d81434 --- /dev/null +++ b/algorithm/others/ReverseString.java @@ -0,0 +1,5 @@ +package Algorithms.algorithm.others; + +public class ReverseString { + +} diff --git a/others/SearchInRotatedArray.java b/algorithm/others/SearchInRotatedArray.java similarity index 98% rename from others/SearchInRotatedArray.java rename to algorithm/others/SearchInRotatedArray.java index 3718297..4908cac 100644 --- a/others/SearchInRotatedArray.java +++ b/algorithm/others/SearchInRotatedArray.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class SearchInRotatedArray { public static void main(String[] args) { diff --git a/algorithm/others/SingleNumber2.java b/algorithm/others/SingleNumber2.java new file mode 100644 index 0000000..9b549ee --- /dev/null +++ b/algorithm/others/SingleNumber2.java @@ -0,0 +1,5 @@ +package Algorithms.algorithm.others; + +public class SingleNumber2 { + +} diff --git a/others/SortColors.java b/algorithm/others/SortColors.java similarity index 97% rename from others/SortColors.java rename to algorithm/others/SortColors.java index 0126079..b35e432 100644 --- a/others/SortColors.java +++ b/algorithm/others/SortColors.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.Collection; import java.util.LinkedList; diff --git a/others/SortList.java b/algorithm/others/SortList.java similarity index 97% rename from others/SortList.java rename to algorithm/others/SortList.java index 8f0801a..6ed1099 100644 --- a/others/SortList.java +++ b/algorithm/others/SortList.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class SortList { public static void main(String[] str) { SortList sl = new SortList(); diff --git a/others/SpiralMatrix.java b/algorithm/others/SpiralMatrix.java similarity index 96% rename from others/SpiralMatrix.java rename to algorithm/others/SpiralMatrix.java index 35e886d..dd518b6 100644 --- a/others/SpiralMatrix.java +++ b/algorithm/others/SpiralMatrix.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class SpiralMatrix { public int[][] generateMatrix(int n) { int[][] rst = new int[n][n]; diff --git a/others/SpiralOrder.java b/algorithm/others/SpiralOrder.java similarity index 97% rename from others/SpiralOrder.java rename to algorithm/others/SpiralOrder.java index 19a1089..1fd66c0 100644 --- a/others/SpiralOrder.java +++ b/algorithm/others/SpiralOrder.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; diff --git a/others/Sqrt.java b/algorithm/others/Sqrt.java similarity index 96% rename from others/Sqrt.java rename to algorithm/others/Sqrt.java index 71b12de..db3e855 100644 --- a/others/Sqrt.java +++ b/algorithm/others/Sqrt.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class Sqrt { public static int sqrt(int x) { diff --git a/others/SubSet2.java b/algorithm/others/SubSet2.java similarity index 97% rename from others/SubSet2.java rename to algorithm/others/SubSet2.java index 24620e3..ea1a14a 100644 --- a/others/SubSet2.java +++ b/algorithm/others/SubSet2.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; import java.util.Arrays; diff --git a/others/Subset.java b/algorithm/others/Subset.java similarity index 98% rename from others/Subset.java rename to algorithm/others/Subset.java index e36e0e4..49ae1ff 100644 --- a/others/Subset.java +++ b/algorithm/others/Subset.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; import java.util.Arrays; diff --git a/others/SurroundRegions.java b/algorithm/others/SurroundRegions.java similarity index 95% rename from others/SurroundRegions.java rename to algorithm/others/SurroundRegions.java index 05bb342..4fb2474 100644 --- a/others/SurroundRegions.java +++ b/algorithm/others/SurroundRegions.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.LinkedList; import java.util.Queue; @@ -56,7 +56,7 @@ public static void solve(char[][] board) { public static void bfs(char[][] board, int x, int y) { Queue q = new LinkedList(); - // 把x, y放入queue代表准备要访问它的邻接点 + // ???x, y??????queue???????????????????????????????????? visit(board, x, y, q); while (!q.isEmpty()) { int num = q.poll(); diff --git a/others/TestArrayChange.java b/algorithm/others/TestArrayChange.java similarity index 93% rename from others/TestArrayChange.java rename to algorithm/others/TestArrayChange.java index 5d8c7fa..919524a 100644 --- a/others/TestArrayChange.java +++ b/algorithm/others/TestArrayChange.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; public class TestArrayChange { public static void main(String[] args) { diff --git a/others/TreeSumCloset.java b/algorithm/others/TreeSumCloset.java similarity index 98% rename from others/TreeSumCloset.java rename to algorithm/others/TreeSumCloset.java index 0fb3360..5a6b808 100644 --- a/others/TreeSumCloset.java +++ b/algorithm/others/TreeSumCloset.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.Arrays; diff --git a/others/WordBreak2.java b/algorithm/others/WordBreak2.java similarity index 98% rename from others/WordBreak2.java rename to algorithm/others/WordBreak2.java index d1ef70c..b9c7570 100644 --- a/others/WordBreak2.java +++ b/algorithm/others/WordBreak2.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; diff --git a/others/ZigzagLevelOrder.java b/algorithm/others/ZigzagLevelOrder.java similarity index 99% rename from others/ZigzagLevelOrder.java rename to algorithm/others/ZigzagLevelOrder.java index 7ccfb6e..3ec2fc7 100644 --- a/others/ZigzagLevelOrder.java +++ b/algorithm/others/ZigzagLevelOrder.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; import java.util.LinkedList; import java.util.Queue; diff --git a/others/letterCombinations.java b/algorithm/others/letterCombinations.java similarity index 98% rename from others/letterCombinations.java rename to algorithm/others/letterCombinations.java index 595d915..ecc2f85 100644 --- a/others/letterCombinations.java +++ b/algorithm/others/letterCombinations.java @@ -1,4 +1,4 @@ -package Algorithms.others; +package Algorithms.algorithm.others; import java.util.ArrayList; diff --git a/list/DeleteDuplicates.java b/list/DeleteDuplicates.java index 2dc83ed..aa978a5 100644 --- a/list/DeleteDuplicates.java +++ b/list/DeleteDuplicates.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.others.ListNode; +import Algorithms.algorithm.others.ListNode; /** * Definition for singly-linked list. diff --git a/list/DeleteDuplicates2.java b/list/DeleteDuplicates2.java index ecaab8e..9fbe983 100644 --- a/list/DeleteDuplicates2.java +++ b/list/DeleteDuplicates2.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.others.ListNode; +import Algorithms.algorithm.others.ListNode; /** * Definition for singly-linked list. diff --git a/list/MergeKLists.java b/list/MergeKLists.java index 42d8c30..6e3cf16 100644 --- a/list/MergeKLists.java +++ b/list/MergeKLists.java @@ -4,7 +4,7 @@ import java.util.List; import java.util.PriorityQueue; -import Algorithms.others.ListNode; +import Algorithms.algorithm.others.ListNode; /** * Definition for singly-linked list. diff --git a/list/MergeTwoLists.java b/list/MergeTwoLists.java index d1644d4..a1fd02f 100644 --- a/list/MergeTwoLists.java +++ b/list/MergeTwoLists.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.others.ListNode; +import Algorithms.algorithm.others.ListNode; public class MergeTwoLists { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { diff --git a/list/PartitionList.java b/list/PartitionList.java index c1aa6df..94e2763 100644 --- a/list/PartitionList.java +++ b/list/PartitionList.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.others.ListNode; +import Algorithms.algorithm.others.ListNode; /** * Definition for singly-linked list. diff --git a/list/RemoveNthFromEnd.java b/list/RemoveNthFromEnd.java index de618a1..8b256fd 100644 --- a/list/RemoveNthFromEnd.java +++ b/list/RemoveNthFromEnd.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.others.ListNode; +import Algorithms.algorithm.others.ListNode; /** * Definition for singly-linked list. diff --git a/list/ReorderList.java b/list/ReorderList.java index 701d43c..3e0b780 100644 --- a/list/ReorderList.java +++ b/list/ReorderList.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.others.ListNode; +import Algorithms.algorithm.others.ListNode; /** * Definition for singly-linked list. diff --git a/list/ReverseBetween.java b/list/ReverseBetween.java index 6a653a0..4708320 100644 --- a/list/ReverseBetween.java +++ b/list/ReverseBetween.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.others.ListNode; +import Algorithms.algorithm.others.ListNode; public class ReverseBetween { public ListNode reverseBetween(ListNode head, int m, int n) { diff --git a/list/ReverseLinkedList2.java b/list/ReverseLinkedList2.java index 6d1c568..e28e162 100644 --- a/list/ReverseLinkedList2.java +++ b/list/ReverseLinkedList2.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.others.ListNode; +import Algorithms.algorithm.others.ListNode; public class ReverseLinkedList2 { public static void main(String[] args) { diff --git a/list/RotateList.java b/list/RotateList.java index 47a677f..3178d50 100644 --- a/list/RotateList.java +++ b/list/RotateList.java @@ -1,6 +1,6 @@ package Algorithms.list; -import Algorithms.others.ListNode; +import Algorithms.algorithm.others.ListNode; /** * Definition for singly-linked list. diff --git a/others/Ag.java b/others/Ag.java deleted file mode 100644 index 0a89bfa..0000000 --- a/others/Ag.java +++ /dev/null @@ -1,7 +0,0 @@ -package Algorithms.others; - - - -abstract public class Ag { - -} diff --git a/others/ReverseString.java b/others/ReverseString.java deleted file mode 100644 index 3d1a05b..0000000 --- a/others/ReverseString.java +++ /dev/null @@ -1,5 +0,0 @@ -package Algorithms.others; - -public class ReverseString { - -} diff --git a/others/SingleNumber2.java b/others/SingleNumber2.java deleted file mode 100644 index 23ce80a..0000000 --- a/others/SingleNumber2.java +++ /dev/null @@ -1,5 +0,0 @@ -package Algorithms.others; - -public class SingleNumber2 { - -} diff --git a/sort/InsertionSortList.java b/sort/InsertionSortList.java index db8fd4b..ddb8346 100644 --- a/sort/InsertionSortList.java +++ b/sort/InsertionSortList.java @@ -1,6 +1,6 @@ package Algorithms.sort; -import Algorithms.others.ListNode; +import Algorithms.algorithm.others.ListNode; /** * Definition for singly-linked list. diff --git a/sort/MergeSort_LinkedList.java b/sort/MergeSort_LinkedList.java index ac84dae..401a734 100644 --- a/sort/MergeSort_LinkedList.java +++ b/sort/MergeSort_LinkedList.java @@ -2,7 +2,7 @@ import java.util.LinkedList; -import Algorithms.others.ListNode; +import Algorithms.algorithm.others.ListNode; public class MergeSort_LinkedList { public static void main(String[] args) { diff --git a/sort/SortList_leetCode.java b/sort/SortList_leetCode.java index 05da6f9..d4eeeda 100644 --- a/sort/SortList_leetCode.java +++ b/sort/SortList_leetCode.java @@ -1,6 +1,6 @@ package Algorithms.sort; -import Algorithms.others.ListNode; +import Algorithms.algorithm.others.ListNode; /** * Definition for singly-linked list. diff --git a/tree/sortedListToBST.java b/tree/sortedListToBST.java index 574f251..35eea52 100644 --- a/tree/sortedListToBST.java +++ b/tree/sortedListToBST.java @@ -1,6 +1,6 @@ package Algorithms.tree; -import Algorithms.others.ListNode; +import Algorithms.algorithm.others.ListNode; /** * Definition for singly-linked list. From 86cefe807835cc6b9c9afc3152e05992c846f0a7 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 14:42:03 -0700 Subject: [PATCH 083/319] comments --- algorithm/interviews/facebook/SortWeight.java | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/algorithm/interviews/facebook/SortWeight.java b/algorithm/interviews/facebook/SortWeight.java index 4e8b072..bd15e74 100644 --- a/algorithm/interviews/facebook/SortWeight.java +++ b/algorithm/interviews/facebook/SortWeight.java @@ -34,16 +34,16 @@ public static LinkedList sortWeight(String input) { float defautWeight = 5; - // ???weight = -1????????????????????????-????????????????????? + String food = null; float weight = 0; - // ????????????????????????????????? + // 使用hashmap来记录food-weight 对 HashMap> map = new HashMap>(); // Go through the string. for (String s: strs) { - // ????????????food-weight??????????????? + // 这是第一对食物-重量对 if (weight != -1) { food = s; weight = -1; @@ -58,7 +58,7 @@ public static LinkedList sortWeight(String input) { // a new food. addFoodToMap(map, food, defautWeight); - // ????????????????????????-????????? + // 重新开始计算新一轮的食物对 food = s; weight = -1; } @@ -93,7 +93,7 @@ public static class Pair implements Comparable { this.weight = weight; } - // ??????????????????o??????????????????????????????????????????????????? + // 这样子写会达成反序的效果 public int compareTo(Pair o) { if (o.weight - this.weight < 0) { return -1; @@ -104,8 +104,7 @@ public int compareTo(Pair o) { } /* - * ???????????????????????? Pair?????????hashmap???????????????-????????????????????????????????? - * ?????????????????????????????????compareTo?????? + * 实现方法2:自定义一个Pair数据类型,并且用compare来自动排序 * */ public static LinkedList sortWeight2(String input) { LinkedList ret = new LinkedList(); @@ -117,16 +116,16 @@ public static LinkedList sortWeight2(String input) { float defautWeight = 5; - // ???weight = -1????????????????????????-????????????????????? + String food = null; float weight = 0; - // ??????ArrayList???????????????-????????? + // 创建一个空的食物-weight 链 ArrayList list = new ArrayList(); // Go through the string. for (String s: strs) { - // ????????????food-weight??????????????? + // 首个食物-weight对 if (weight != -1) { food = s; weight = -1; @@ -141,7 +140,7 @@ public static LinkedList sortWeight2(String input) { // a new food. list.add(new Pair(food, defautWeight)); - // ????????????????????????-????????? + // 开始新一轮的食物-weight链 food = s; weight = -1; } @@ -166,13 +165,13 @@ public static LinkedList sortWeight2(String input) { public static void addFoodToMap(HashMap> map, String food, float weight) { - // ?????????????????????-???????????? + // 检查 在map中是否存在 ArrayList list = map.get(weight); if (list != null) { - // ????????????????????????????????? + // 添加一个新的重量 list.add(food); } else { - // ????????????????????? + // 把食物放在重量后面对应的链上 ArrayList listNew = new ArrayList(); listNew.add(food); map.put(weight, listNew); From 4c44200e753b37e447dbe3a4003bc5e8b51fb7b1 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 14:46:05 -0700 Subject: [PATCH 084/319] reorder --- tree/readme.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tree/readme.md diff --git a/tree/readme.md b/tree/readme.md new file mode 100644 index 0000000..65aebd8 --- /dev/null +++ b/tree/readme.md @@ -0,0 +1,29 @@ +LeetCode_algorithm +================== + +About the Tree: +full binary tree: A binary tree in which each node has exactly zero or two children. +Perfect binary tree: A binary tree with all leaf nodes at the same depth. All internal nodes have degree 2 [1] + +The difference between Full Binary Tree & Complete Binary Tree: +(1). a binary tree T is full if each node is either a leaf or possesses exactly two child nodes. +(2). a binary tree T with n levels is complete if all levels except possibly the last are completely full, and the last level has all its +nodes to the left side. [2] + +AVL Trees: AVL trees are self-balancing binary search trees. These trees are named after their two +inventors G.M. Adel’son-Vel’skii and E.M. Landis. [3] + +The height/depth of a tree: +The height of a node is the length of the longest downward path to a leaf from that node. +The height of the root is the height of the tree. The depth of a node is the length of the path to its root (i.e., its root path). +This is commonly needed in the manipulation of the various self-balancing trees, +AVL Trees in particular. The root node has depth zero, leaf nodes have height zero, +and a tree with only a single node (hence both a root and leaf) has depth and height zero. +Conventionally, an empty tree (tree with no nodes, if such are allowed) has depth and height −1.[4] + + +REF: +[1] http://xlinux.nist.gov/dads//HTML/perfectBinaryTree.html +[2] http://courses.cs.vt.edu/~cs3114/Fall09/wmcquain/Notes/T03a.BinaryTreeTheorems. +[3] http://courses.csail.mit.edu/6.006/fall09/lecture_notes/lecture04.pdf +[4] http://www.cs.cmu.edu/~adamchik/15-121/lectures/Trees/trees.html From 809b004b8e053b6e8993ca49b74fe7343acc5752 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 14:49:53 -0700 Subject: [PATCH 085/319] reorder --- README.md | 30 +++++++----------------------- tree/readme.md | 2 +- 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 65aebd8..0295650 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,13 @@ LeetCode_algorithm ================== -About the Tree: -full binary tree: A binary tree in which each node has exactly zero or two children. -Perfect binary tree: A binary tree with all leaf nodes at the same depth. All internal nodes have degree 2 [1] +包括LeetCode的解答(目前还不完整,大概有一半左右) -The difference between Full Binary Tree & Complete Binary Tree: -(1). a binary tree T is full if each node is either a leaf or possesses exactly two child nodes. -(2). a binary tree T with n levels is complete if all levels except possibly the last are completely full, and the last level has all its -nodes to the left side. [2] +目录划分: -AVL Trees: AVL trees are self-balancing binary search trees. These trees are named after their two -inventors G.M. Adel’son-Vel’skii and E.M. Landis. [3] +algorithm-- 包含除LeetCode以外的其它算法,如面经等 + --interviews 面经 + -- facebook 各公司的面经 -The height/depth of a tree: -The height of a node is the length of the longest downward path to a leaf from that node. -The height of the root is the height of the tree. The depth of a node is the length of the path to its root (i.e., its root path). -This is commonly needed in the manipulation of the various self-balancing trees, -AVL Trees in particular. The root node has depth zero, leaf nodes have height zero, -and a tree with only a single node (hence both a root and leaf) has depth and height zero. -Conventionally, an empty tree (tree with no nodes, if such are allowed) has depth and height −1.[4] - - -REF: -[1] http://xlinux.nist.gov/dads//HTML/perfectBinaryTree.html -[2] http://courses.cs.vt.edu/~cs3114/Fall09/wmcquain/Notes/T03a.BinaryTreeTheorems. -[3] http://courses.csail.mit.edu/6.006/fall09/lecture_notes/lecture04.pdf -[4] http://www.cs.cmu.edu/~adamchik/15-121/lectures/Trees/trees.html +array -- leetcode array 相关 +combination -- leetcode 组合相关 \ No newline at end of file diff --git a/tree/readme.md b/tree/readme.md index 65aebd8..b9bbb9f 100644 --- a/tree/readme.md +++ b/tree/readme.md @@ -1,4 +1,4 @@ -LeetCode_algorithm +Tree ================== About the Tree: From 1a03aa7c9285bec3a7d50c57dcd1782d5b136c5a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 14:52:05 -0700 Subject: [PATCH 086/319] readme --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0295650..679fcac 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ LeetCode_algorithm ================== -包括LeetCode的解答(目前还不完整,大概有一半左右) +包括LeetCode的解答(目前还不完整,大概有一半左右)
目录划分: -algorithm-- 包含除LeetCode以外的其它算法,如面经等 - --interviews 面经 - -- facebook 各公司的面经 +algorithm-- 包含除LeetCode以外的其它算法,如面经等
+ --interviews 面经
+ -- facebook 各公司的面经
-array -- leetcode array 相关 -combination -- leetcode 组合相关 \ No newline at end of file +array -- leetcode array 相关
+combination -- leetcode 组合相关
\ No newline at end of file From b47e369fa74f5d124bb3ea00371fe034cc02f3ae Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 14:52:42 -0700 Subject: [PATCH 087/319] read --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 679fcac..6b3cde9 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ LeetCode_algorithm ================== -包括LeetCode的解答(目前还不完整,大概有一半左右)
+包括LeetCode的解答(目前还不完整,大概有一半左右)
目录划分: -algorithm-- 包含除LeetCode以外的其它算法,如面经等
- --interviews 面经
- -- facebook 各公司的面经
+algorithm-- 包含除LeetCode以外的其它算法,如面经等
+ --interviews 面经
+ -- facebook 各公司的面经
-array -- leetcode array 相关
-combination -- leetcode 组合相关
\ No newline at end of file +array -- leetcode array 相关
+combination -- leetcode 组合相关
\ No newline at end of file From 2a1e9fca631a8497426771bc3b432ad0bb42ca0e Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 14:54:22 -0700 Subject: [PATCH 088/319] formate --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6b3cde9..eea0199 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,10 @@ LeetCode_algorithm 目录划分: -algorithm-- 包含除LeetCode以外的其它算法,如面经等
- --interviews 面经
- -- facebook 各公司的面经
+algorithm--包含除LeetCode以外的其它算法,如面经等
+  --interviews 面经
+  --facebook 各公司的面经
-array -- leetcode array 相关
-combination -- leetcode 组合相关
\ No newline at end of file +array--leetcode array 相关
+combination--leetcode 组合相关
+... etc \ No newline at end of file From 03d921fd6b8901728bf782615742e1600bd07ddf Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 14:56:09 -0700 Subject: [PATCH 089/319] formate --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index eea0199..cce0f2f 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,10 @@ LeetCode_algorithm 目录划分: -algorithm--包含除LeetCode以外的其它算法,如面经等
-  --interviews 面经
-  --facebook 各公司的面经
+algorithm--包含除LeetCode以外的其它算法,如面经等 + --interviews 面经 + --facebook 各公司的面经 -array--leetcode array 相关
-combination--leetcode 组合相关
-... etc \ No newline at end of file +array--leetcode array 相关 +combination--leetcode 组合相关 +... etc From 868ace0a10da4c129bc846f22aa154a4dda5dbe2 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 14:57:14 -0700 Subject: [PATCH 090/319] formate --- README.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index eea0199..895580f 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,15 @@ LeetCode_algorithm 目录划分: -algorithm--包含除LeetCode以外的其它算法,如面经等
-  --interviews 面经
-  --facebook 各公司的面经
+algorithm--包含除LeetCode以外的其它算法,如面经等 +
+  --interviews 面经 +
+  --facebook 各公司的面经 +
-array--leetcode array 相关
-combination--leetcode 组合相关
+array--leetcode array 相关 +
+combination--leetcode 组合相关 +
... etc \ No newline at end of file From 2911efddf1f173343c8e7b18fe5a3dd3737813a4 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 15:02:00 -0700 Subject: [PATCH 091/319] formate --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a9cbeda..0689844 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,13 @@ algorithm--包含除LeetCode以外的其它算法,如面经等
  --interviews 面经 +
  --facebook 各公司的面经
array--leetcode array 相关 +
combination--leetcode 组合相关
From 4eb43d28d89a6e5695086adfe7f4d3e1930b254a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 15:02:54 -0700 Subject: [PATCH 092/319] formate --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0689844..9f2b6a8 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ LeetCode_algorithm 目录划分: -algorithm--包含除LeetCode以外的其它算法,如面经等 +algorithm -- 包含除LeetCode以外的其它算法,如面经等。除了这个目录以外都是LeetCode
  --interviews 面经 From bcd230d715f8f905f75de28b1ab440ab3672e5e8 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 15:04:34 -0700 Subject: [PATCH 093/319] formate --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 9f2b6a8..cad43e9 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,7 @@ LeetCode_algorithm algorithm -- 包含除LeetCode以外的其它算法,如面经等。除了这个目录以外都是LeetCode
-  --interviews 面经 - -
+  --interviews 面经   --facebook 各公司的面经
From e1668221bfa18b3bf3c76192cbd76426c2f0ec8c Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 15:05:28 -0700 Subject: [PATCH 094/319] comment --- README.md | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index cad43e9..9a3f0a8 100644 --- a/README.md +++ b/README.md @@ -5,16 +5,10 @@ LeetCode_algorithm 目录划分: -algorithm -- 包含除LeetCode以外的其它算法,如面经等。除了这个目录以外都是LeetCode - -
+algorithm -- 包含除LeetCode以外的其它算法,如面经等。除了这个目录以外都是LeetCode   --interviews 面经 -  --facebook 各公司的面经 -
- -array--leetcode array 相关 +  --facebook 各公司的面经 -
-combination--leetcode 组合相关 -
+array--leetcode array 相关 +combination--leetcode 组合相关 ... etc From 7d08c356be8f95bfdf6c6451f71b54610b598e4e Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 15:06:31 -0700 Subject: [PATCH 095/319] formate --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9a3f0a8..d70d7af 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,10 @@ LeetCode_algorithm 目录划分: -algorithm -- 包含除LeetCode以外的其它算法,如面经等。除了这个目录以外都是LeetCode -  --interviews 面经 -  --facebook 各公司的面经 +algorithm ---- 包含除LeetCode以外的其它算法,如面经等。除了这个目录以外都是LeetCode +  -- interviews 面经 +  -- facebook 各公司的面经 -array--leetcode array 相关 -combination--leetcode 组合相关 +array -------- leetcode array 相关 +combination -- leetcode 组合相关 ... etc From 694f606f304f43a96e3f34e0ee771d8d11dc78ca Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 15:07:59 -0700 Subject: [PATCH 096/319] formate --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d70d7af..7e98c30 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,6 @@ algorithm ---- 包含除LeetCode以外的其它算法,如面经等。除了这   -- interviews 面经   -- facebook 各公司的面经 -array -------- leetcode array 相关 +array ---------- leetcode array 相关 combination -- leetcode 组合相关 ... etc From 20b77e3cbd8a305465678ed9bff8901f6da4d97c Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 15:09:57 -0700 Subject: [PATCH 097/319] reorder --- algorithm/NChapter/FindKthNumber.java | 71 +++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 algorithm/NChapter/FindKthNumber.java diff --git a/algorithm/NChapter/FindKthNumber.java b/algorithm/NChapter/FindKthNumber.java new file mode 100644 index 0000000..97ed041 --- /dev/null +++ b/algorithm/NChapter/FindKthNumber.java @@ -0,0 +1,71 @@ +package Algorithms.algorithm.NChapter; + +import java.util.Arrays; + +public class FindKthNumber { + public static void main(String[] strs) { + int[] A1 = new int[]{1,6,9,2,3,5}; + FindKthNumber find = new FindKthNumber(); + int rst = find.findKthNumber(A1, 5); + System.out.println(rst); + + System.out.println("after find"); + for (int i = 0; i < A1.length; i++) { + System.out.print(A1[i]); + System.out.print(" "); + } + + System.out.println(); + + Arrays.sort(A1); + System.out.println("After sort"); + for (int i = 0; i < A1.length; i++) { + System.out.print(A1[i]); + System.out.print(" "); + } + } + + public int findKthNumber(int A[], int k) { + + return findKthNumberHelp(A, A.length + 1 - k, 0, A.length - 1); + } + + public int findKthNumberHelp(int A[], int k, int start, int end) { + int left = start; + int right = end; + int pivot = left; + + while (left <= right) { + while (left <= right && A[left] <= A[pivot]) { + left++; + } + + while (left <= right && A[right] >= A[pivot]) { + right--; + } + + if (left < right) { + swap(A, left, right); + } + } + + swap(A, pivot, right); + + if (right + 1 == k) { + return A[right]; + } + + if (right + 1 > k) { + // find in the left side. + return findKthNumberHelp(A, k, start, right - 1); + } else { + return findKthNumberHelp(A, k, right + 1, end); + } + } + + private void swap(int A[], int one, int two) { + int tmp = A[one]; + A[one] = A[two]; + A[two] = tmp; + } +} From b1b9b998aa745a3bb4c840691cdd4721859fdfca Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 15:10:32 -0700 Subject: [PATCH 098/319] reorder --- Divide2/Pow.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Divide2/Pow.java b/Divide2/Pow.java index 3105b69..ed4913a 100644 --- a/Divide2/Pow.java +++ b/Divide2/Pow.java @@ -1,4 +1,4 @@ -package Algorithms.Divide2; +package Algorithms.divide2; public class Pow { public static void main(String[] strs) { @@ -17,8 +17,8 @@ public static double pow(double x, int n) { // Because when we deal with -2147483648, we can't get right -n // cause -n == n when it is -2147483648. - // 注意 这样写是不行的,因为-n在n到最小值会出错, - // int的最小值(负数)取-n仍然是n 这样就错了。 + // ?????? ??????????????????????????????-n???n???????????????????????? + // int???????????????????????????-n?????????n ?????????????????? if (n < 0) { double ret1 = x * pow(x, -(1 + n)); return 1/(double)ret1; From 3d4a08b7b490915f483079f6ee93a3c5b3a3722c Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 15:13:23 -0700 Subject: [PATCH 099/319] reorder --- {Divide2 => divide}/Pow.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename {Divide2 => divide}/Pow.java (97%) diff --git a/Divide2/Pow.java b/divide/Pow.java similarity index 97% rename from Divide2/Pow.java rename to divide/Pow.java index ed4913a..fb5b108 100644 --- a/Divide2/Pow.java +++ b/divide/Pow.java @@ -1,4 +1,4 @@ -package Algorithms.divide2; +package Algorithms.divide; public class Pow { public static void main(String[] strs) { From 63b0507bf9250422cf5faac6e4af448d20f19069 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 15:13:50 -0700 Subject: [PATCH 100/319] re --- {divide => divide2}/Pow.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename {divide => divide2}/Pow.java (97%) diff --git a/divide/Pow.java b/divide2/Pow.java similarity index 97% rename from divide/Pow.java rename to divide2/Pow.java index fb5b108..ed4913a 100644 --- a/divide/Pow.java +++ b/divide2/Pow.java @@ -1,4 +1,4 @@ -package Algorithms.divide; +package Algorithms.divide2; public class Pow { public static void main(String[] strs) { From 5c136377b98d8e0b0fdb53ad20a3d1396480577b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 15:23:13 -0700 Subject: [PATCH 101/319] NQueens --- dfs/SolveNQueens_v2.java | 104 +++++++++++++++++++++++++++++++++++++++ divide2/Pow.java | 2 - 2 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 dfs/SolveNQueens_v2.java diff --git a/dfs/SolveNQueens_v2.java b/dfs/SolveNQueens_v2.java new file mode 100644 index 0000000..d2af945 --- /dev/null +++ b/dfs/SolveNQueens_v2.java @@ -0,0 +1,104 @@ +package Algorithms.dfs; + +import java.util.ArrayList; +import java.util.List; + +/* + * N-Queens Total Accepted: 16418 Total Submissions: 63309 My Submissions +The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other. + + + +Given an integer n, return all distinct solutions to the n-queens puzzle. + +Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively. + +For example, +There exist two distinct solutions to the 4-queens puzzle: + +[ + [".Q..", // Solution 1 + "...Q", + "Q...", + "..Q."], + + ["..Q.", // Solution 2 + "Q...", + "...Q", + ".Q.."] +] + * */ +public class SolveNQueens_v2 { + public static List solveNQueens(int n) { + List ret = new ArrayList(); + if (n == 0) { + return ret; + } + + ArrayList cols = new ArrayList(); + + solveNQueensHelp(n, cols, ret); + + return ret; + } + + // 根据列值把解集合算出来 + public static String[] createSol(int n, ArrayList cols) { + String[] ret = new String[n]; + + for (int i = 0; i < n; i++) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < n; j++) { + sb.append('.'); + } + sb.setCharAt(cols.get(i), 'Q'); + ret[i] = sb.toString(); + } + + return ret; + } + + public static boolean isValid(ArrayList cols, int c) { + for (int i = 0; i < cols.size(); i++) { + // 与某皇后在同一列 + if (c == cols.get(i)) { + return false; + } + + // 在交叉2个方向 + // cols.size() 是新插入的皇后的行数 + if (cols.size() - i == Math.abs(c - cols.get(i))) { + return false; + } + } + + return true; + } + + /* + * n: 表示需要放多少个皇后 + * cols: 存放每一行皇后的列值。 我们在每一行放一个皇后,所以只需要算出第一行皇后的列值即可 + * ret: 返回值 + * */ + public static void solveNQueensHelp(int n, ArrayList cols, List ret) { + // 每一行的皇后的坐标都确定了。 + if (cols.size() == n) { + String[] sol = createSol(n, cols); + ret.add(sol); + return; + } + + // DFS 某一行中所有的位置,看是否可以放置一个皇后. + // 如果这一行根本没有找到解,会直接返回 + for (int i = 0; i < n; i++) { + // 判断这个位置是否与已经放好的皇后冲突 + if (!isValid(cols, i)) { + continue; + } + + cols.add(i); + solveNQueensHelp(n, cols, ret); + cols.remove(cols.size() - 1); + } + } +} \ No newline at end of file diff --git a/divide2/Pow.java b/divide2/Pow.java index ed4913a..3f01170 100644 --- a/divide2/Pow.java +++ b/divide2/Pow.java @@ -17,8 +17,6 @@ public static double pow(double x, int n) { // Because when we deal with -2147483648, we can't get right -n // cause -n == n when it is -2147483648. - // ?????? ??????????????????????????????-n???n???????????????????????? - // int???????????????????????????-n?????????n ?????????????????? if (n < 0) { double ret1 = x * pow(x, -(1 + n)); return 1/(double)ret1; From 4f36155910d13397fb06bcc1b4401ba1b6a87d31 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 16:27:08 -0700 Subject: [PATCH 102/319] Reverse --- sequence/Reverse.java | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 sequence/Reverse.java diff --git a/sequence/Reverse.java b/sequence/Reverse.java new file mode 100644 index 0000000..d802d09 --- /dev/null +++ b/sequence/Reverse.java @@ -0,0 +1,26 @@ +package Algorithms.sequence; +public class Reverse { + public int reverse(int x) { + long n = x; + + boolean neg = false; + if (n < 0) { + neg = true; + n = -n; + } + + long ret = 0; + while (n > 0) { + long left = n % 10; + ret *= 10; + ret += left; + n /= 10; + } + + if (neg) { + ret = -ret; + } + + return (int)ret; + } +} \ No newline at end of file From 2682dc4e3337e69a4451c4fd074561b6488b32c6 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 16:36:55 -0700 Subject: [PATCH 103/319] reverse --- sequence/Reverse.java | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/sequence/Reverse.java b/sequence/Reverse.java index d802d09..7892811 100644 --- a/sequence/Reverse.java +++ b/sequence/Reverse.java @@ -1,26 +1,21 @@ package Algorithms.sequence; public class Reverse { - public int reverse(int x) { + public static void main(String[] args) { + System.out.println(reverse(-1234)); + System.out.println(reverse(100)); + } + + public static int reverse(int x) { long n = x; - boolean neg = false; - if (n < 0) { - neg = true; - n = -n; - } - long ret = 0; - while (n > 0) { + while (n != 0) { long left = n % 10; ret *= 10; ret += left; n /= 10; } - if (neg) { - ret = -ret; - } - return (int)ret; } } \ No newline at end of file From 4728a4d33eb50b2e4c9e3999552de6cea4e8ca5c Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 17:05:33 -0700 Subject: [PATCH 104/319] nqueens2 --- dfs/TotalNQueens.java | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 dfs/TotalNQueens.java diff --git a/dfs/TotalNQueens.java b/dfs/TotalNQueens.java new file mode 100644 index 0000000..47d9ec5 --- /dev/null +++ b/dfs/TotalNQueens.java @@ -0,0 +1,55 @@ +package Algorithms.dfs; + +import java.util.ArrayList; + +public class TotalNQueens { + public int totalNQueens(int n) { + if (n == 0) { + return 0; + } + + ArrayList cols = new ArrayList(); + + return dfs(n, cols, 0); + } + + public int dfs(int n, ArrayList cols, int row) { + // 如果row 超过范围,返回1 + // base case 已经完成任务,应该是1种解法 因为前面已经固定,现在也不能再放了 + if (row == n) { + return 1; + } + + int sum = 0; + + // 在当前行,尝试放置棋子 + for (int i = 0; i < n; i++) { + // 不能放的位置 跳过 + if (!isValid(cols, i)) { + continue; + } + + cols.add(i); + sum += dfs(n, cols, row + 1); + cols.remove(cols.size() - 1); + } + + return sum; + } + + public boolean isValid(ArrayList cols, int col) { + for (int i = 0; i < cols.size(); i++) { + if (col == cols.get(i)) { + // same column. + return false; + } + + // diagonal. From the left up to the right down. + if (cols.size() - i == Math.abs(col - cols.get(i))) { + return false; + } + } + + return true; + } +} \ No newline at end of file From c6c60a301bc481f8ed38be46b34c6d4cfdc7f01a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 12 Oct 2014 17:39:40 -0700 Subject: [PATCH 105/319] sumNumbers sumNumbers --- tree/SumNumbers.java | 67 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 tree/SumNumbers.java diff --git a/tree/SumNumbers.java b/tree/SumNumbers.java new file mode 100644 index 0000000..66b20de --- /dev/null +++ b/tree/SumNumbers.java @@ -0,0 +1,67 @@ +package Algorithms.tree; + +import java.util.ArrayList; + +/* + * + * Sum Root to Leaf Numbers Total Accepted: 23940 Total Submissions: 80436 My Submissions +Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. + +An example is the root-to-leaf path 1->2->3 which represents the number 123. + +Find the total sum of all root-to-leaf numbers. + +For example, + + 1 + / \ + 2 3 +The root-to-leaf path 1->2 represents the number 12. +The root-to-leaf path 1->3 represents the number 13. + +Return the sum = 12 + 13 = 25. + * */ + +public class SumNumbers { + public int sumNumbers(TreeNode root) { + if (root == null) { + return 0; + } + + ArrayList ret = new ArrayList(); + + // 存储从根节点到当前节点的路径上的数字 + ArrayList path = new ArrayList(); + + dfs(root, path, ret); + int sum = 0; + for (int n: ret) { + sum += n; + } + + return sum; + } + + public void dfs(TreeNode root, ArrayList path, ArrayList ret) { + if (root == null) { + return; + } + + path.add(root.val); + + if (root.left == null && root.right == null) { + int num = 0; + for (int n: path) { + num = num * 10 + n; + } + ret.add(num); + } else { + // 向左右子树递归 + dfs(root.left, path, ret); + dfs(root.right, path, ret); + } + + // 一定要记得回溯,也就是说递归不能修改Path本身,否则以上向左右子树分别递归时 path就会被改。 + path.remove(path.size() - 1); + } +} From 8e7a6db3c4778b18fdce399455a601ef23d19901 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 13 Oct 2014 02:59:51 -0700 Subject: [PATCH 106/319] dp --- dp/MinDistance.java | 55 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 dp/MinDistance.java diff --git a/dp/MinDistance.java b/dp/MinDistance.java new file mode 100644 index 0000000..3049f58 --- /dev/null +++ b/dp/MinDistance.java @@ -0,0 +1,55 @@ +package Algorithms.dp; + +public class MinDistance { + public int minDistance(String word1, String word2) { + // THE DP FORMULA + // D[i][j]: The min operations to change from s1 to s2. + // s1: i characters in word1, s2: j characters in word2. + // + // D[i][j] = + + if (word1 == null || word2 == null) { + return -1; + } + + int len1 = word1.length(); + int len2 = word2.length(); + + // create a DP array. + // 注意:一定要多分配1个。 + // 取0表示从string中一个都不取 + int[][] D = new int[len1 + 1][len2 + 1]; + + for (int i = 0; i <= len1; i++) { + for (int j = 0; j <= len2; j++) { + if (i == 0 && j == 0) { + D[i][j] = 0; + } else if (i == 0) { + // Need to add a new element to do it. + D[i][j] = D[i][j - 1] + 1; + } else if (j == 0) { + // Need to delete a element to get the string 2. + D[i][j] = D[i - 1][j] + 1; + } else { + // we can come from 3 options: + // 1. D[i][j - 1] + // 2. D[i - 1][j] + // 3. D[i - 1][j - 1] + D[i][j] = Math.min(D[i][j - 1] + 1, D[i - 1][j] + 1); + + // 注意这里的Index是 i - 1 跟 j - 1. + // 因为i的意思是从string1取出i个字符,所以最后一个字符的索引是i - 1 + if (word1.charAt(i - 1) == word2.charAt(j - 1)) { + // 最后一个字符相等,不需要变化 + D[i][j] = Math.min(D[i][j], D[i - 1][j - 1]); + } else { + // 最后一个字符不等,需要replace. + D[i][j] = Math.min(D[i][j], D[i - 1][j - 1] + 1); + } + } + } + } + + return D[len1][len2]; + } +} From e640b43006cc311492d338c85924abc595f3417a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 13 Oct 2014 22:16:42 -0700 Subject: [PATCH 107/319] link --- ListNodeDemo.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ListNodeDemo.java b/ListNodeDemo.java index f23327d..3a1f700 100644 --- a/ListNodeDemo.java +++ b/ListNodeDemo.java @@ -57,7 +57,8 @@ public static void main(String[] args) { ListNode c1 = new ListNode(1); ListNode c2 = new ListNode(12); c1.next = c2; - //c2.next = n1; + c2.next = n1; + //c2.next = c1; ListNode mergeNode = mergeLink(m1, c1); //ListNode mergeNode2 = mergeLink(m1, c1); @@ -114,6 +115,7 @@ public static void main(String[] args) { System.out.println(isIntersect(n1, c1)); + System.out.println("TEST the getFirstCommonNode:"); ListNode cross = getFirstCommonNode(n1, c1); if (cross == null) { System.out.println("null"); @@ -650,10 +652,12 @@ public static ListNode getFirstCommonNode(ListNode head1, ListNode head2) { } } - while (head1 != null) { - if (head1.next == head2.next) { - return head1.next; + while (head1 != null && head2 != null) { + if (head1 == head2) { + return head1; } + head1 = head1.next; + head2 = head2.next; } return null; From 8e5c0c9a0ca96556c3f1fcc2d194241bdc6117f1 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 13 Oct 2014 22:23:21 -0700 Subject: [PATCH 108/319] link --- ListNodeDemo.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ListNodeDemo.java b/ListNodeDemo.java index 3a1f700..c2b9626 100644 --- a/ListNodeDemo.java +++ b/ListNodeDemo.java @@ -624,7 +624,9 @@ public static ListNode hasCycleRetNode(ListNode head) { * 2. 有环的情况 * (1). 交点在环上 * 这样子的话,实际上我们可以求出2个交点。我们只要判断2个交点是不是相等。不相等,把2个交点返回任何一个。 - * (2). 交点不在环上,则计算出环的交点,然后len1 = 起点至环的交点,len2 = 起点至环的交点,然后如方法1相同的做法。 + * 相等也是返回任何一个。 + * (2). 交点不在环上,则计算出环的交点,然后len1 = 起点至环的交点,len2 = 起点至环的交点,然后如方法1相同的做法。 + * 这段代码没写咯 */ public static ListNode getFirstCommonNode(ListNode head1, ListNode head2) { if (head1 == null || head2 == null) { From f01ecb2f6368028a13cab48ebe94aa970d581b4b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 13 Oct 2014 22:23:57 -0700 Subject: [PATCH 109/319] link --- ListNodeDemo.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ListNodeDemo.java b/ListNodeDemo.java index c2b9626..75bd1bb 100644 --- a/ListNodeDemo.java +++ b/ListNodeDemo.java @@ -664,6 +664,7 @@ public static ListNode getFirstCommonNode(ListNode head1, ListNode head2) { return null; } else if (cross1 != null && cross2 != null) { + // 这一段没怎么写咯 return cross1; } From 00385682e41a7f7e84f13e81ff7a0105250faf92 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 14 Oct 2014 00:22:13 -0700 Subject: [PATCH 110/319] wave sort --- algorithm/sort/WaveSort.java | 57 ++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 algorithm/sort/WaveSort.java diff --git a/algorithm/sort/WaveSort.java b/algorithm/sort/WaveSort.java new file mode 100644 index 0000000..c088c3e --- /dev/null +++ b/algorithm/sort/WaveSort.java @@ -0,0 +1,57 @@ +package Algorithms.algorithm.sort; + +import java.util.Arrays; + +/* + * 给定一个未排序的数组,请给出波浪状排序: + * Example: + * input: 1 2 5 4 3 9 + * output: 1 4 3 2 5 9 + * + * input: 1 2 2 5 3 9 + * output: 1 5 2 3 2 9 + * */ +public class WaveSort { + public static void main(String[] str) { + int[] in = {1,2,5,4,3,9, 12}; + + for (int i: in) { + System.out.print(i + " "); + } + System.out.println(); + + waveSort(in); + for (int i: in) { + System.out.print(i + " "); + } + } + + public static void waveSort(int[] in) { + if (in == null) { + return; + } + + // there should be at least 3 numbers. + if (in.length <= 2) { + return; + } + + int len = in.length; + + Arrays.sort(in); + + for (int i = 0; i < len; i++) { + if (i % 2 == 0) { + if (i + 1 < len) { + int tmp = in[i]; + in[i] = in[i + 1]; + in[i + 1] = tmp; + } + } + } + } + + public static void findKthNumber(int[] in, int k) { + + } +} From 3af42c9e044253af89fb8d5c30fac246fcb81385 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 14 Oct 2014 05:16:01 -0700 Subject: [PATCH 111/319] palindrome --- algorithm/dp/LongestPalindrome.java | 46 +++++++++++++++++++++++++ algorithm/dp/LongestPalindrome_dp1.java | 46 +++++++++++++++++++++++++ algorithm/sort/WaveSort.java | 20 +++++++---- 3 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 algorithm/dp/LongestPalindrome.java create mode 100644 algorithm/dp/LongestPalindrome_dp1.java diff --git a/algorithm/dp/LongestPalindrome.java b/algorithm/dp/LongestPalindrome.java new file mode 100644 index 0000000..d5d8554 --- /dev/null +++ b/algorithm/dp/LongestPalindrome.java @@ -0,0 +1,46 @@ +package Algorithms.algorithm.dp; + +public class LongestPalindrome { + public static void main(String[] args) { + String s = "cadfasdfsadfabaabaed"; + System.out.println(longestPalindrome(s)); + } + + // Solution 1: Brute Force + public static String longestPalindrome(String s) { + if (s == null) { + return null; + } + + int len = s.length(); + + int max = 0; + int begin = 0; + int end = 0; + for (int i = 0; i < len; i++) { + for (int j = i; j < len; j++) { + if (dfs(s, i, j)) { + if (j - i + 1 > max) { + max = j - i + 1; + begin = i; + end = j; + } + } + } + } + + return s.substring(begin, end + 1); + } + + public static boolean dfs(String s, int i, int j) { + if (i >= j) { + return true; + } + + if (s.charAt(i) == s.charAt(j)) { + return dfs(s, i + 1, j - 1); + } + + return false; + } +} diff --git a/algorithm/dp/LongestPalindrome_dp1.java b/algorithm/dp/LongestPalindrome_dp1.java new file mode 100644 index 0000000..29a7bca --- /dev/null +++ b/algorithm/dp/LongestPalindrome_dp1.java @@ -0,0 +1,46 @@ +package Algorithms.algorithm.dp; + +public class LongestPalindrome_dp1 { + public static void main(String[] args) { + String s = "cabaabad"; + System.out.println(longestPalindrome(s)); + } + + // Solution 1: + public static String longestPalindrome(String s) { + if (s == null) { + return null; + } + + int len = s.length(); + + // Record i-j is a palindrome. + boolean[][] D = new boolean[len][len]; + + int max = 0; + int retB = 0; + int retE = 0; + // 这样写的目的是,从前往后扫描时,被记录的DP值可以被复用 + // 因为D[i][j] 要用到i + 1, j - 1,所以每一次计算j时,把j对应的i全部计算完,这样 + // 下一次计算i,j的时候,可以有i+1, j-1可以用。 + for (int j = 0; j < len; j++) { + for (int i = 0; i <= j; i++) { + if (s.charAt(i) == s.charAt(j) + && (j - i <= 2 || D[i + 1][j - 1]) + ) { + D[i][j] = true; + + if (j - i + 1 > max) { + retB = i; + retE = j; + max = j - i + 1; + } + } else { + D[i][j] = false; + } + } + } + + return s.substring(retB, retE + 1); + } +} diff --git a/algorithm/sort/WaveSort.java b/algorithm/sort/WaveSort.java index c088c3e..962f285 100644 --- a/algorithm/sort/WaveSort.java +++ b/algorithm/sort/WaveSort.java @@ -6,14 +6,14 @@ * 给定一个未排序的数组,请给出波浪状排序: * Example: * input: 1 2 5 4 3 9 - * output: 1 4 3 2 5 9 + * output: 1 4 3 5 2 9 * * input: 1 2 2 5 3 9 * output: 1 5 2 3 2 9 * */ public class WaveSort { public static void main(String[] str) { - int[] in = {1,2,5,4,3,9, 12}; + int[] in = {1,2,5,4,3,9,9,9, 12}; for (int i: in) { System.out.print(i + " "); @@ -40,12 +40,20 @@ public static void waveSort(int[] in) { Arrays.sort(in); + for (int i: in) { + System.out.print(i + " "); + } + System.out.println(); + for (int i = 0; i < len; i++) { if (i % 2 == 0) { - if (i + 1 < len) { - int tmp = in[i]; - in[i] = in[i + 1]; - in[i + 1] = tmp; + for (int j = i + 1; j < len; j++) { + if (in[j] != in[i]) { + int tmp = in[i]; + in[i] = in[j]; + in[j] = tmp; + break; + } } } } From e9c90c8ec6d711668d25bcbd4da9eb39257dc240 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 14 Oct 2014 05:18:59 -0700 Subject: [PATCH 112/319] order --- {algorithm/dp => dp}/LongestPalindrome.java | 2 +- {algorithm/dp => dp}/LongestPalindrome_dp1.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename {algorithm/dp => dp}/LongestPalindrome.java (96%) rename {algorithm/dp => dp}/LongestPalindrome_dp1.java (97%) diff --git a/algorithm/dp/LongestPalindrome.java b/dp/LongestPalindrome.java similarity index 96% rename from algorithm/dp/LongestPalindrome.java rename to dp/LongestPalindrome.java index d5d8554..9dc9bf7 100644 --- a/algorithm/dp/LongestPalindrome.java +++ b/dp/LongestPalindrome.java @@ -1,4 +1,4 @@ -package Algorithms.algorithm.dp; +package Algorithms.dp; public class LongestPalindrome { public static void main(String[] args) { diff --git a/algorithm/dp/LongestPalindrome_dp1.java b/dp/LongestPalindrome_dp1.java similarity index 97% rename from algorithm/dp/LongestPalindrome_dp1.java rename to dp/LongestPalindrome_dp1.java index 29a7bca..125395e 100644 --- a/algorithm/dp/LongestPalindrome_dp1.java +++ b/dp/LongestPalindrome_dp1.java @@ -1,4 +1,4 @@ -package Algorithms.algorithm.dp; +package Algorithms.dp; public class LongestPalindrome_dp1 { public static void main(String[] args) { From 1982bc29c6ec81ae061b42671d6a7bff9f46da80 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 14 Oct 2014 05:45:14 -0700 Subject: [PATCH 113/319] formate --- dp/LongestPalindrome.java | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/dp/LongestPalindrome.java b/dp/LongestPalindrome.java index 9dc9bf7..81a622f 100644 --- a/dp/LongestPalindrome.java +++ b/dp/LongestPalindrome.java @@ -5,30 +5,30 @@ public static void main(String[] args) { String s = "cadfasdfsadfabaabaed"; System.out.println(longestPalindrome(s)); } - + // Solution 1: Brute Force public static String longestPalindrome(String s) { if (s == null) { return null; } - + int len = s.length(); int max = 0; int begin = 0; int end = 0; for (int i = 0; i < len; i++) { - for (int j = i; j < len; j++) { - if (dfs(s, i, j)) { - if (j - i + 1 > max) { - max = j - i + 1; - begin = i; - end = j; - } - } - } + for (int j = i; j < len; j++) { + if (dfs(s, i, j)) { + if (j - i + 1 > max) { + max = j - i + 1; + begin = i; + end = j; + } + } + } } - + return s.substring(begin, end + 1); } @@ -36,11 +36,11 @@ public static boolean dfs(String s, int i, int j) { if (i >= j) { return true; } - - if (s.charAt(i) == s.charAt(j)) { - return dfs(s, i + 1, j - 1); - } - - return false; + + if (s.charAt(i) == s.charAt(j)) { + return dfs(s, i + 1, j - 1); + } + + return false; } } From 7ae4ef0ca60745992e1a309d0c0b9c84d24042d7 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 14 Oct 2014 06:19:53 -0700 Subject: [PATCH 114/319] Palindrome --- dp/LongestPalindrome.java | 5 ++++- string/IsPalindrome.java | 41 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 string/IsPalindrome.java diff --git a/dp/LongestPalindrome.java b/dp/LongestPalindrome.java index 81a622f..321d83f 100644 --- a/dp/LongestPalindrome.java +++ b/dp/LongestPalindrome.java @@ -2,8 +2,11 @@ public class LongestPalindrome { public static void main(String[] args) { - String s = "cadfasdfsadfabaabaed"; + String s = "9cadfasdfsadfabaabaed"; System.out.println(longestPalindrome(s)); + + System.out.println(Character.toLowerCase('9')); + } // Solution 1: Brute Force diff --git a/string/IsPalindrome.java b/string/IsPalindrome.java new file mode 100644 index 0000000..7ac6cc6 --- /dev/null +++ b/string/IsPalindrome.java @@ -0,0 +1,41 @@ +package Algorithms.string; + +public class IsPalindrome { + public boolean isPalindrome(String s) { + // http://blog.csdn.net/fightforyourdream/article/details/12860445 + if (s == null) { + return false; + } + + int len = s.length(); + + s = s.toLowerCase(); + + int l = 0; + int r = len - 1; + while (l < r) { + if (!isValid(s.charAt(l))) { + l++; + } else if (!isValid(s.charAt(r))) { + r--; + } else if (s.charAt(l) != s.charAt(r)) { + return false; + } else { + l++; + r--; + } + } + + return true; + } + + public boolean isValid(char c) { + return Character.isLetterOrDigit(c); + // if (c <= 'z' && c >= 'a' || c <= 'Z' && c >= 'A' + // || c <= '9' && c >= '0') { + // return true; + // } + + // return false; + } +} From e7e021d80f8efeffa3ef701cbc54d2d97da4d3ec Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 14 Oct 2014 17:17:52 -0700 Subject: [PATCH 115/319] =?UTF-8?q?=E4=B8=AD=E5=BF=83=E5=B1=95=E5=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- algorithm/dp/LongestPalindrome_dp1.java | 100 ++++++++++++++++++++++++ dp/LongestPalindrome_dp1.java | 55 ++++++++++++- 2 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 algorithm/dp/LongestPalindrome_dp1.java diff --git a/algorithm/dp/LongestPalindrome_dp1.java b/algorithm/dp/LongestPalindrome_dp1.java new file mode 100644 index 0000000..98d9784 --- /dev/null +++ b/algorithm/dp/LongestPalindrome_dp1.java @@ -0,0 +1,100 @@ +package Algorithms.algorithm.dp; + +public class LongestPalindrome_dp1 { + public static void main(String[] args) { + String s = "cabaabad"; + System.out.println(longestPalindrome(s)); + } + + // Solution 1: + public static String longestPalindrome1(String s) { + if (s == null) { + return null; + } + + int len = s.length(); + + // Record i-j is a palindrome. + boolean[][] D = new int[len][len]; + for (int i = 0; i < len; i++) { + for (int j = 0; j < len; j++) { + D[i][j] = false; + } + } + + int max = 0; + int retB = 0; + int retE = 0; + // 这样写的目的是,从前往后扫描时,被记录的DP值可以被复用 + // 因为D[i][j] 要用到i + 1, j - 1,所以每一次计算j时,把j对应的i全部计算完,这样 + // 下一次计算i,j的时候,可以有i+1, j-1可以用。 + for (int j = 0; j < len; j++) { + for (int i = 0; i <= j; i++) { + if (s.charAt(i) == s.charAt(j) + && (j - i <= 3 || D[i + 1][j - 1]) + ) { + D[i][j] = true; + + if (j - i + 1 > max) { + retB = i; + retE = j; + } + } else { + D[i][j] = false; + } + } + } + + return s.substring(retB, retE + 1); + } + + // solution 2: 中心展开法。从头扫到尾部,每一个字符以它为中心向两边扩展,找最长回文。 + // 复杂度为N^2 并且是inplace,空间复杂度O(1) + public static String longestPalindrome(String s) { + if (s == null) { + return null; + } + + int len = s.length(); + + if (len <= 0) { + return ""; + } + + int max = 0; + String ret = ""; + + for (int i = 0; i < len; i++) { + // 考虑奇数字符串 + String s1 = expandAround(s, i, i); + if (s1.length() > max) { + ret = s1; + max = s1.length(); + } + + String s2 = expandAround(s, i, i); + if (s2.length() > max) { + ret = s2; + max = s2.length(); + } + } + + return ret; + } + + public static String expandAround(String s, int c1, int c2) { + int len = s.length(); + + while (c1 >= 0 && c2 <= len - 1) { + if (s.charAt(c1) != s.charAt(c2)) { + break; + } + + c1++; + c2--; + } + + // 注意,根据 substring的定义,c2不要减1 + return s.substring(c1 + 1, c2); + } +} diff --git a/dp/LongestPalindrome_dp1.java b/dp/LongestPalindrome_dp1.java index 125395e..2b5811b 100644 --- a/dp/LongestPalindrome_dp1.java +++ b/dp/LongestPalindrome_dp1.java @@ -6,8 +6,8 @@ public static void main(String[] args) { System.out.println(longestPalindrome(s)); } - // Solution 1: - public static String longestPalindrome(String s) { + // solution 1: DP. + public static String longestPalindrome1(String s) { if (s == null) { return null; } @@ -43,4 +43,55 @@ public static String longestPalindrome(String s) { return s.substring(retB, retE + 1); } + + // solution 2: 中心展开法。从头扫到尾部,每一个字符以它为中心向两边扩展,找最长回文。 + // 复杂度为N^2 并且是inplace,空间复杂度O(1) + public static String longestPalindrome(String s) { + if (s == null) { + return null; + } + + int len = s.length(); + + if (len <= 0) { + return ""; + } + + int max = 0; + String ret = ""; + + for (int i = 0; i < len; i++) { + // 考虑奇数字符串 + String s1 = expandAround(s, i, i); + if (s1.length() > max) { + ret = s1; + max = s1.length(); + } + + // 考虑偶数长度的字符串 + String s2 = expandAround(s, i, i + 1); + if (s2.length() > max) { + ret = s2; + max = s2.length(); + } + } + + return ret; + } + + public static String expandAround(String s, int c1, int c2) { + int len = s.length(); + + while (c1 >= 0 && c2 <= len - 1) { + if (s.charAt(c1) != s.charAt(c2)) { + break; + } + + c1--; + c2++; + } + + // 注意,根据 substring的定义,c2不要减1 + return s.substring(c1 + 1, c2); + } } From 258920d4d0e3c6275e272ebc7d633acd10b0843d Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 14 Oct 2014 21:38:49 -0700 Subject: [PATCH 116/319] list --- dp/Generate.java | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 dp/Generate.java diff --git a/dp/Generate.java b/dp/Generate.java new file mode 100644 index 0000000..03483a4 --- /dev/null +++ b/dp/Generate.java @@ -0,0 +1,31 @@ +package Algorithms.dp; + +import java.util.ArrayList; +import java.util.List; + +public class Generate { + public List> generate(int numRows) { + List> ret = new ArrayList>(); + + if (numRows <= 0) { + return ret; + } + + for (int i = 0; i < numRows; i++) { + ArrayList list = new ArrayList(); + for (int j = 0; j < i + 1; j++) { + if (j == 0 || j == i) { + // 两边的数字就是1. + list.add(1); + } else { + // 中间的数字等于上一行的j + j -1的值 + int num = ret.get(i - 1).get(j) + ret.get(i - 1).get(j - 1); + list.add(num); + } + } + ret.add(list); + } + + return ret; + } +} \ No newline at end of file From 746a14e8b6588841436035d39b63c47f01a6d5ac Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 14 Oct 2014 21:56:04 -0700 Subject: [PATCH 117/319] getrow --- dp/GetRow.java | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 dp/GetRow.java diff --git a/dp/GetRow.java b/dp/GetRow.java new file mode 100644 index 0000000..0e81ede --- /dev/null +++ b/dp/GetRow.java @@ -0,0 +1,32 @@ +package Algorithms.dp; + +import java.util.ArrayList; +import java.util.List; + +public class GetRow { + public List getRow(int rowIndex) { + List pre = new ArrayList(); + List cur = new ArrayList(); + + if (rowIndex < 0) { + return cur; + } + + // 注意这里的rowIndex跟上一题的意义不一样!这个是索引,orz... + // 所以我们要用<= + for (int i = 0; i <= rowIndex; i++) { + // 第i行有i + 1个元素 + cur = new ArrayList(); + for (int j = 0; j < i + 1; j++) { + if (j == 0 || j == i) { + cur.add(1); + } else { + cur.add(pre.get(j) + pre.get(j - 1)); + } + } + pre = cur; + } + + return cur; + } +} \ No newline at end of file From 31915c864f0e9797980099750b94bf9c838a6136 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 14 Oct 2014 22:18:51 -0700 Subject: [PATCH 118/319] the subset --- dfs/Subsets.java | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 dfs/Subsets.java diff --git a/dfs/Subsets.java b/dfs/Subsets.java new file mode 100644 index 0000000..c45a9c7 --- /dev/null +++ b/dfs/Subsets.java @@ -0,0 +1,40 @@ +package Algorithms.dfs; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Subsets { + public List> subsets(int[] S) { + List> ret = new ArrayList>(); + List path = new ArrayList(); + + if (S == null) { + return ret; + } + + Arrays.sort(S); + + subsets(S, path, ret, 0); + + return ret; + } + + public void subsets(int[] S, List path, List> ret, int index) { + int len = S.length; + + // 把当前的结果可以添加到结果集中. 空集也算是一种集合 + ret.add(new ArrayList(path)); + + if (index >= len) { + return; + } + + for (int i = index; i < len; i++) { + path.add(S[i]); + + // 注意!这里的index要填写i + 1,而不是index,开始老是会犯错。 + subsets(S, path, ret, i + 1); + path.remove(path.size() - 1); + } + } +} From c7a264794ce573993ad9189e20b96b0633141a38 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 14 Oct 2014 22:34:43 -0700 Subject: [PATCH 119/319] subset --- dfs/Subsets.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/dfs/Subsets.java b/dfs/Subsets.java index c45a9c7..2247361 100644 --- a/dfs/Subsets.java +++ b/dfs/Subsets.java @@ -20,16 +20,10 @@ public List> subsets(int[] S) { } public void subsets(int[] S, List path, List> ret, int index) { - int len = S.length; - // 把当前的结果可以添加到结果集中. 空集也算是一种集合 ret.add(new ArrayList(path)); - if (index >= len) { - return; - } - - for (int i = index; i < len; i++) { + for (int i = index; i < S.length; i++) { path.add(S[i]); // 注意!这里的index要填写i + 1,而不是index,开始老是会犯错。 From 0984ef6988c1d3180df70c2099d54604a09837dd Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 15 Oct 2014 01:27:08 -0700 Subject: [PATCH 120/319] hasmap --- sequence/TwoSum.java | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 sequence/TwoSum.java diff --git a/sequence/TwoSum.java b/sequence/TwoSum.java new file mode 100644 index 0000000..a4481a2 --- /dev/null +++ b/sequence/TwoSum.java @@ -0,0 +1,35 @@ +package Algorithms.sequence; + +import java.util.HashMap; + +/* + * Two Sum Total Accepted: 36938 Total Submissions: 200732 My Submissions Question Solution +Given an array of integers, find two numbers such that they add up to a specific target number. + +The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based. + +You may assume that each input would have exactly one solution. + +Input: numbers={2, 7, 11, 15}, target=9 +Output: index1=1, index2=2 + * */ + +public class TwoSum { + public int[] twoSum(int[] numbers, int target) { + HashMap map = new HashMap(); + int[] ret = new int[2]; + + for (int i = 0; i < numbers.length; i++) { + if (map.containsKey(target - numbers[i])) { + + // As the index is not ZERO based, we should add one to the result. + ret[0] = map.get(target - numbers[i]) + 1; + ret[1] = i + 1; + return ret; + } + map.put(numbers[i], i); + } + + return ret; + } +} From 47c8cef3d34babacb7cf6e907dd567dac98a777d Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 15 Oct 2014 01:54:44 -0700 Subject: [PATCH 121/319] comment --- algorithm/dp/LongestPalindrome_dp1.java | 1 + sequence/ThreeSum.java | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 sequence/ThreeSum.java diff --git a/algorithm/dp/LongestPalindrome_dp1.java b/algorithm/dp/LongestPalindrome_dp1.java index 98d9784..b1800ef 100644 --- a/algorithm/dp/LongestPalindrome_dp1.java +++ b/algorithm/dp/LongestPalindrome_dp1.java @@ -72,6 +72,7 @@ public static String longestPalindrome(String s) { max = s1.length(); } + // 考虑偶数长度的字符串 String s2 = expandAround(s, i, i); if (s2.length() > max) { ret = s2; diff --git a/sequence/ThreeSum.java b/sequence/ThreeSum.java new file mode 100644 index 0000000..3db242f --- /dev/null +++ b/sequence/ThreeSum.java @@ -0,0 +1,9 @@ +package Algorithms.sequence; + +import java.util.List; + +public class ThreeSum { + public List> threeSum(int[] num) { + + } +} \ No newline at end of file From 61c81279ced066192cd247248bda09aed62e9557 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 15 Oct 2014 03:24:31 -0700 Subject: [PATCH 122/319] three sum --- sequence/ThreeSum.java | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/sequence/ThreeSum.java b/sequence/ThreeSum.java index 3db242f..7d316c0 100644 --- a/sequence/ThreeSum.java +++ b/sequence/ThreeSum.java @@ -1,9 +1,53 @@ package Algorithms.sequence; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class ThreeSum { public List> threeSum(int[] num) { + List> ret = new ArrayList>(); + if (num == null) { + return ret; + } + Arrays.sort(num); + + int len = num.length; + for (int i = 0; i < len; i++) { + // 跳过重复的元素,首个数字不需要选择重复的. + if (i > 0 && num[i] == num[i - 1]) { + continue; + } + + // 创建二个指针,分别从2头查找,查目标值,它们2个加起来要等于0-num1 + int l = i + 1; + int r = len - 1; + while (l < r) { + int sum = num[i] + num[l] + num[r]; + if (sum == 0) { + ArrayList list = new ArrayList(); + list.add(num[i]); + list.add(num[l]); + list.add(num[r]); + ret.add(list); + + // 跳过重复元素 + do { + l++; + } while (l < r && num[l] == num[l - 1]); + + do { + r--; + } while (l < r && num[r] == num[r + 1]); + } else if (sum < 0) { + l++; + } else { + r--; + } + } + } + + return ret; } } \ No newline at end of file From 6ec14fc939993289b8750797821260b18375b159 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 15 Oct 2014 03:57:16 -0700 Subject: [PATCH 123/319] sum --- sequence/ThreeSumClosest.java | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 sequence/ThreeSumClosest.java diff --git a/sequence/ThreeSumClosest.java b/sequence/ThreeSumClosest.java new file mode 100644 index 0000000..960f24c --- /dev/null +++ b/sequence/ThreeSumClosest.java @@ -0,0 +1,42 @@ +package Algorithms.sequence; + +public class ThreeSumClosest { + public int threeSumClosest(int[] num, int target) { + if (num == null) { + return 0; + } + + int len = num.length; + + int diffMin = Integer.MAX_VALUE; + + int ret = 0; + for (int i = 0; i < len; i++) { + + int l = i + 1; + int r = len - 1; + + while (l < r) { + int diff = target - (num[i] + num[l] + num[r]); + + if (Math.abs(diff) < diffMin) { + diffMin = Math.abs(diff); + ret = num[i] + num[l] + num[r]; + } + + if (diff > 0) { + // move right; + l++; + } else if (diff < 0) { + // move left; + r--; + } else { + // We get the 0 now. There is no way that it would be less than 0. + return ret; + } + } + } + + return ret; + } +} \ No newline at end of file From 23c51b1d91cb2048746641b07c25b3c0c502a91d Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 15 Oct 2014 04:25:39 -0700 Subject: [PATCH 124/319] four --- sequence/FourSum.java | 61 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 sequence/FourSum.java diff --git a/sequence/FourSum.java b/sequence/FourSum.java new file mode 100644 index 0000000..e937910 --- /dev/null +++ b/sequence/FourSum.java @@ -0,0 +1,61 @@ +package Algorithms.sequence; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FourSum { + public List> fourSum(int[] num, int target) { + List> ret = new ArrayList>(); + if (num == null) { + return ret; + } + + Arrays.sort(num); + + int len = num.length; + for (int i = 0; i < len; i++) { + if (i > 0 && num[i] == num[i - 1]) { + // skip duplicate. + continue; + } + + for (int j = i + 1; j < len; j++) { + if (j > i + 1 && num[j] == num[j - 1]) { + // skip duplicate. + continue; + } + + int l = j + 1; + int r = len - 1; + + while (l < r) { + int sum = num[i] + num[j] + num[l] + num[r]; + if (sum == target) { + ArrayList list = new ArrayList(); + list.add(num[i]); + list.add(num[j]); + list.add(num[l]); + list.add(num[r]); + + ret.add(list); + + do { + l++; + } while (l < r && num[l] == num[l - 1]); + + do { + r--; + } while (l < r && num[r] == num[r + 1]); + } else if (sum < target) { + l++; + } else { + r--; + } + } + } + } + + return ret; + } +} From fe96f42c986ff6b8e18e2b7e3da75810bbd3b43c Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 15 Oct 2014 04:49:41 -0700 Subject: [PATCH 125/319] plus --- array/PlusOne.java | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 array/PlusOne.java diff --git a/array/PlusOne.java b/array/PlusOne.java new file mode 100644 index 0000000..2fdc38b --- /dev/null +++ b/array/PlusOne.java @@ -0,0 +1,41 @@ +package Algorithms.array; + +public class PlusOne { + public int[] plusOne(int[] digits) { + if (digits == null) { + return null; + } + + int overFlow = 0; + + int len = digits.length; + int[] ret = new int[len]; + + for (int i = len - 1; i >= 0; i--) { + int sum = digits[i] + overFlow; + if (i == len - 1) { + // 只有最后一位需要加1 + sum++; + } + + // 溢出的话,置溢出位。 + if (sum > 9) { + overFlow = 1; + } else { + overFlow = 0; + } + + // 把高位去掉,因为我们要0-9 + ret[i] = sum % 10; + } + + if (overFlow == 1) { + int[] retOver = new int[len + 1]; + System.arraycopy(retOver, 1, ret, 0, len); + retOver[0] = 1; + return retOver; + } + + return ret; + } +} From c938e17c65a4ef81923b456cdb652bb0e600ff04 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 15 Oct 2014 05:06:37 -0700 Subject: [PATCH 126/319] subset --- dfs/SubsetsWithDup.java | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 dfs/SubsetsWithDup.java diff --git a/dfs/SubsetsWithDup.java b/dfs/SubsetsWithDup.java new file mode 100644 index 0000000..5fa39b2 --- /dev/null +++ b/dfs/SubsetsWithDup.java @@ -0,0 +1,38 @@ +package Algorithms.dfs; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class SubsetsWithDup { + public List> subsetsWithDup(int[] num) { + List> ret = new ArrayList>(); + + if (num == null) { + return ret; + } + + Arrays.sort(num); + + dfs(num, new ArrayList(), ret, 0); + + return ret; + } + + public void dfs(int[] num, List path, List> ret, int index) { + ret.add(new ArrayList(path)); + + for (int i = index; i < num.length; i++) { + // skip the duplicate. + if (i > index && num[i] == num[i - 1]) { + continue; + } + + path.add(num[i]); + // 注意:这里是i + 1不是index + 1!!! + dfs(num, path, ret, i + 1); + path.remove(path.size() - 1); + } + + } +} From 02c9fc0729ac7f7f9d80cc8e4c27d95a5ae20805 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 15 Oct 2014 15:55:31 -0700 Subject: [PATCH 127/319] word ladder --- bfs/LadderLength.java | 57 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 bfs/LadderLength.java diff --git a/bfs/LadderLength.java b/bfs/LadderLength.java new file mode 100644 index 0000000..7ac5773 --- /dev/null +++ b/bfs/LadderLength.java @@ -0,0 +1,57 @@ +package Algorithms.bfs; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Queue; +import java.util.Set; + +public class LadderLength { + public int ladderLength(String start, String end, Set dict) { + if (start == null || end == null) { + return 0; + } + + // we use BFS to solve the problem. use a QUEUE to store all the solutions in one level. + Queue q = new LinkedList(); + + int level = 0; + + q.offer(start); + + // 避免计算到重复的字符串 + HashSet set = new HashSet(); + set.add(start); + + while (!q.isEmpty()) { + int size = q.size(); + + level++; + for (int i = 0; i < size; i++) { + String s = q.poll(); + + int len = s.length(); + for (int j = 0; j < len; j++) { + StringBuilder sb = new StringBuilder(s); + // 注意,这时是char + for (char c = 'a'; c <= 'z'; c++) { + sb.setCharAt(j, c); + + String tmp = sb.toString(); + + if (tmp.equals(end)) { + return level + 1; + } + + if (!set.contains(tmp) && dict.contains(tmp)) { + set.add(tmp); + q.offer(tmp); + } + } + } + + } + } + + return 0; + } +} From b4ede815ed7a61c10bbeb80b3c1580c18447b9ca Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 15 Oct 2014 20:04:25 -0700 Subject: [PATCH 128/319] combine --- combination/CombinationSum.java | 42 +++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 combination/CombinationSum.java diff --git a/combination/CombinationSum.java b/combination/CombinationSum.java new file mode 100644 index 0000000..5c845e3 --- /dev/null +++ b/combination/CombinationSum.java @@ -0,0 +1,42 @@ +package Algorithms.combination; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CombinationSum { + public List> combinationSum(int[] candidates, int target) { + List> ret = new ArrayList>(); + if (candidates == null || candidates.length == 0) { + return ret; + } + + List path = new ArrayList(); + + // we should sort the candidates than do it. in this case we can get a non-descending order. + Arrays.sort(candidates); + + combinationSum(candidates, target, path, ret, 0); + return ret; + } + + public void combinationSum(int[] candidates, int target, List path, List> ret, int index) { + if (target == 0) { + // add the current set into the result. + ret.add(new ArrayList(path)); + return; + } + + if (target < 0) { + return; + } + + int len = candidates.length; + for (int i = index; i < len; i++) { + int num = candidates[i]; + path.add(num); + combinationSum(candidates, target - num, path, ret, i); + path.remove(path.size() - 1); + } + } +} From 46caf6c4e052405e1c42eb7ef0431f8fbda7bedc Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 16 Oct 2014 15:12:00 -0700 Subject: [PATCH 129/319] rec --- dp/MinDistance.java | 54 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/dp/MinDistance.java b/dp/MinDistance.java index 3049f58..92ef788 100644 --- a/dp/MinDistance.java +++ b/dp/MinDistance.java @@ -1,7 +1,59 @@ package Algorithms.dp; public class MinDistance { - public int minDistance(String word1, String word2) { + public static void main(String[] strs) { + String str1 = "abcdafasdfsaf", str2 = "acadsadsfsfqweiruiijadsfsadfsadfdwqfjljfaffiuweqro"; + + System.out.println(minDistance(str1, str2)); + + int[][] record = new int[str1.length() + 1][str2.length() + 1]; + for (int i = 0; i < str1.length() + 1; i++) { + for (int j = 0; j < str2.length() + 1; j++) { + record[i][j] = -1; + } + } + + System.out.println(dfs(str1, str1.length(), str2, str2.length(), record)); + } + + /* + * 递归解法,效果跟动规是一样的。而且想起来还可能要简单一点儿。 + * */ + public static int dfs(String word1, int len1, String word2, int len2, int[][] record) { + if (len1 <= 0) { + return len2; + } + + if (len2 <= 0) { + return len1; + } + + if (record[len1][len2] != -1) { + return record[len1][len2]; + } + + int ret = 0; + + int index1 = word1.length() - len1; + int index2 = word2.length() - len2; + if (word1.charAt(index1) == word2.charAt(index2)) { + // 相等的时候,只需要直接下一步Rec + ret = dfs(word1, len1 - 1, word2, len2 - 1, record); + } else { + // 不相同的时候,有删除,添加,替换三种操作,分别求解并且求一个最小值 + int del = dfs(word1, len1 - 1, word2, len2, record) + 1; + int add = dfs(word1, len1, word2, len2 - 1, record) + 1; + int replace = dfs(word1, len1 - 1, word2, len2 - 1, record) + 1; + + ret = Math.min(del, add); + ret = Math.min(ret, replace); + } + + record[len1][len2] = ret; + return ret; + } + + public static int minDistance(String word1, String word2) { // THE DP FORMULA // D[i][j]: The min operations to change from s1 to s2. // s1: i characters in word1, s2: j characters in word2. From 5f82c25adb3b0fb197e8797af6717a3267951457 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 16 Oct 2014 17:27:13 -0700 Subject: [PATCH 130/319] the min dis --- dp/MinDistance.java | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/dp/MinDistance.java b/dp/MinDistance.java index 92ef788..6acb52b 100644 --- a/dp/MinDistance.java +++ b/dp/MinDistance.java @@ -14,6 +14,12 @@ public static void main(String[] strs) { } System.out.println(dfs(str1, str1.length(), str2, str2.length(), record)); + +// String str3 = "abc"; +// String str4 = "abcd"; + String str3 = "abc"; + String str4 = "aabc"; + System.out.println(disLessThenTwo(str3, str4)); } /* @@ -53,6 +59,37 @@ public static int dfs(String word1, int len1, String word2, int len2, int[][] re return ret; } + /* + * 递归解法,判断edit次数是不是小于2. + * */ + public static boolean disLessThenTwo(String word1, String word2) { + if (word1 == null || word2 == null) { + return false; + } + + int len1 = word1.length(); + int len2 = word2.length(); + + int dis = 1; + + for (int p1 = 0, p2 = 0; p1 < len1 && p2 < len2; p1++, p2++) { + if (word1.charAt(p1) != word2.charAt(p2)) { + dis--; + if (dis < 0) { + return false; + } else { + if (len1 < len2) { + p1--; + } else if (len1 > len2) { + p2--; + } + } + } + } + + return dis >= 0; + } + public static int minDistance(String word1, String word2) { // THE DP FORMULA // D[i][j]: The min operations to change from s1 to s2. From 01d6b77d2b524429289dad3cffe441ad8d7ec7ff Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 16 Oct 2014 21:00:06 -0700 Subject: [PATCH 131/319] comment --- dp/MinDistance.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/dp/MinDistance.java b/dp/MinDistance.java index 6acb52b..d66902e 100644 --- a/dp/MinDistance.java +++ b/dp/MinDistance.java @@ -17,8 +17,8 @@ public static void main(String[] strs) { // String str3 = "abc"; // String str4 = "abcd"; - String str3 = "abc"; - String str4 = "aabc"; + String str3 = "febc"; + String str4 = "afebc"; System.out.println(disLessThenTwo(str3, str4)); } @@ -61,6 +61,7 @@ public static int dfs(String word1, int len1, String word2, int len2, int[][] re /* * 递归解法,判断edit次数是不是小于2. + 也就是说,edit只能为1,或是为0 * */ public static boolean disLessThenTwo(String word1, String word2) { if (word1 == null || word2 == null) { @@ -72,14 +73,23 @@ public static boolean disLessThenTwo(String word1, String word2) { int dis = 1; + // 解法原理:如果2个字符串只差最多1的话,有2种情况: + // 1. 两个字符串相同长度,那肯定是存在replace 1一个字符。所以如果遇到不同的字符串, + // 两个指针都向前移动,一旦遇到不同的,就认为错误退出即可。 + // 2. 两个字符串长度不等。那肯定是用了add/ delete操作才能使2个字符串相同。所以, + // 一旦遇到不同的字符,可以将长度长的字符串向后移动,如果后面出现不等的,也是错误退出。 + for (int p1 = 0, p2 = 0; p1 < len1 && p2 < len2; p1++, p2++) { if (word1.charAt(p1) != word2.charAt(p2)) { dis--; + // 如果不同的字母超过1了,退出 if (dis < 0) { return false; } else { + // If str1 < str2, just move forward the point of STR2 if (len1 < len2) { p1--; + // If str1 > str2, just move forward the point of STR1 } else if (len1 > len2) { p2--; } From e3b7a95f33f040d3694c5a52212cff8e2b76d06b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 16 Oct 2014 21:01:12 -0700 Subject: [PATCH 132/319] comment --- dp/MinDistance.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dp/MinDistance.java b/dp/MinDistance.java index d66902e..55bcc01 100644 --- a/dp/MinDistance.java +++ b/dp/MinDistance.java @@ -74,10 +74,11 @@ public static boolean disLessThenTwo(String word1, String word2) { int dis = 1; // 解法原理:如果2个字符串只差最多1的话,有2种情况: - // 1. 两个字符串相同长度,那肯定是存在replace 1一个字符。所以如果遇到不同的字符串, + // 1. 两个字符串相同长度,那肯定是存在replace 一个字符。所以如果遇到不同的字符串, // 两个指针都向前移动,一旦遇到不同的,就认为错误退出即可。 - // 2. 两个字符串长度不等。那肯定是用了add/ delete操作才能使2个字符串相同。所以, - // 一旦遇到不同的字符,可以将长度长的字符串向后移动,如果后面出现不等的,也是错误退出。 + // 2. 两个字符串长度不等。那肯定是用了add/delete操作才能使2个字符串相同。所以, + // 一旦遇到不同的字符,它肯定是插入进去的。 + // 可以将长度长的字符串向后移动,如果后面出现不等的,也是错误退出。 for (int p1 = 0, p2 = 0; p1 < len1 && p2 < len2; p1++, p2++) { if (word1.charAt(p1) != word2.charAt(p2)) { From d6c6336252cbb62098730d2c816b32ae6cdadd4b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 16 Oct 2014 23:59:56 -0700 Subject: [PATCH 133/319] surrounded regions --- bfs/Solve_SurroundedRegions.java | 99 ++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 bfs/Solve_SurroundedRegions.java diff --git a/bfs/Solve_SurroundedRegions.java b/bfs/Solve_SurroundedRegions.java new file mode 100644 index 0000000..73e1944 --- /dev/null +++ b/bfs/Solve_SurroundedRegions.java @@ -0,0 +1,99 @@ +package Algorithms.bfs; + +import java.util.LinkedList; +import java.util.Queue; + +public class Solve_SurroundedRegions { + public void solve(char[][] board) { + if (board == null || board.length == 0 || board[0].length == 0) { + return; + } + + int rows = board.length; + int cols = board[0].length; + + // bfs the left and right side. + for (int i = 0; i < rows; i++) { + bfs(board, i, 0); + bfs(board, i, cols - 1); + } + + // bfs the first and the last line. + for (int i = 0; i < cols; i++) { + bfs(board, 0, i); + bfs(board, rows - 1, i); + } + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (board[i][j] == 'B') { + board[i][j] = 'O'; + } else if (board[i][j] == 'O') { + board[i][j] = 'X'; + } + } + } + + return; + } + + public void bfs(char[][] board, int i, int j) { + Queue q = new LinkedList(); + int cols = board[0].length; + + q.offer(i * cols + j); + + while(!q.isEmpty()) { + int index = q.poll(); + visit(board, index, q); + } + + } + + public void visit(char[][] board, int index, Queue q) { + int rows = board.length; + int cols = board[0].length; + + int i = index/cols; + int j = index%cols; + + // out of bound or visited. + if (i < 0 || i >= rows || j < 0 || j >= cols) { + return; + } + + if (board[i][j] != 'O') { + return; + } + + board[i][j] = 'B'; + + // 注意index的计算 + q.offer(index - 1); + q.offer(index + 1); + q.offer(index - cols); + q.offer(index + cols); + } + + public void dfs(char[][] board, int i, int j) { + int rows = board.length; + int cols = board[0].length; + + // out of bound or visited. + if (i < 0 || i >= rows || j < 0 || j >= cols) { + return; + } + + if (board[i][j] != 'O') { + return; + } + + board[i][j] = 'B'; + + // dfs the sorrounded regions. + dfs(board, i + 1, j); + dfs(board, i - 1, j); + dfs(board, i, j + 1); + dfs(board, i, j - 1); + } +} From 6da269566f8443a233735d2a9864db6a015b85c0 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 17 Oct 2014 01:39:02 -0700 Subject: [PATCH 134/319] isInterleave --- dp/IsInterleave.java | 132 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 dp/IsInterleave.java diff --git a/dp/IsInterleave.java b/dp/IsInterleave.java new file mode 100644 index 0000000..1915f6d --- /dev/null +++ b/dp/IsInterleave.java @@ -0,0 +1,132 @@ +package Algorithms.dp; + +public class IsInterleave { + public static void main(String[] strs) { + // String s1 = "aabcc"; + // String s2 = "dbbca"; + String s1 = "a"; + String s2 = ""; + String s3 = "a"; + + // String s3 = "aadbbcbcac"; + // String s31 = "aadbbbaccc"; + // + + System.out.println(isInterleave(s1, s2, s3)); + } + + // Solution1: Recursion with memory + public static boolean isInterleave1(String s1, String s2, String s3) { + if (s1 == null || s2 == null || s3 == null) { + return false; + } + + int len1 = s1.length(); + int len2 = s2.length(); + int len3 = s3.length(); + + // The length is not equal, just return false. + if (len1 + len2 != len3) { + return false; + } + + int[][][] memory = new int[len1 + 1][len2 + 1][len3 + 1]; + for (int i = 0; i <= len1; i++) { + for (int j = 0; j <= len2; j++) { + for (int k = 0; k <= len3; k++) { + memory[i][j][k] = -1; + } + } + } + + return recMemory(s1, 0, s2, 0, s3, 0, memory); + } + + public static boolean recMemory(String s1, int index1, String s2, + int index2, String s3, int index3, int[][][] memory) { + int len1 = s1.length(); + int len2 = s2.length(); + int len3 = s3.length(); + + if (index3 == len3 && index1 == len1 && index2 == len2) { + return true; + } + + if (memory[index1][index2][index3] != -1) { + return memory[index1][index2][index3] == 1; + } + + // 第一个字符,有2种可能:来自s1, 或是来自s2 + boolean ret = false; + if (index1 < len1 && s1.charAt(index1) == s3.charAt(index3)) { + ret = recMemory(s1, index1 + 1, s2, index2, s3, index3 + 1, memory); + } + + // 如果不成功(首字母不来自于s1),尝试另一种可能 + if (!ret && index2 < len2 && s2.charAt(index2) == s3.charAt(index3)) { + ret = recMemory(s1, index1, s2, index2 + 1, s3, index3 + 1, memory); + } + + memory[index1][index2][index3] = ret ? 1 : 0; + return ret; + } + + // Solution2: Recursion with memory + // 思考了一下看了一下过去的代码,发现其实我们用不到三维数组,因为len1 + len2 = len3, + // 所以第三维根本可以省略嘛 + public static boolean isInterleave(String s1, String s2, String s3) { + if (s1 == null || s2 == null || s3 == null) { + return false; + } + + int len1 = s1.length(); + int len2 = s2.length(); + int len3 = s3.length(); + + // The length is not equal, just return false. + if (len1 + len2 != len3) { + return false; + } + + int[][] memory = new int[len1 + 1][len2 + 1]; + for (int i = 0; i <= len1; i++) { + for (int j = 0; j <= len2; j++) { + memory[i][j] = -1; + } + } + + return recMemory2(s1, 0, s2, 0, s3, 0, memory); + } + + public static boolean recMemory2(String s1, int index1, String s2, + int index2, String s3, int index3, int[][] memory) { + int len1 = s1.length(); + int len2 = s2.length(); + int len3 = s3.length(); + + // index3 走到最后了,其实意思即是这个字符串为空,因为len1+len2+len3相等,说明其它两个也是空,必然返回true + if (index3 == len3) { + return true; + } + + if (memory[index1][index2] != -1) { + return memory[index1][index2] == 1; + } + + // 第一个字符,有2种可能:来自s1, 或是来自s2 + boolean ret = false; + // 注意,一定要判定index1 是否越界,否则会出问题 + if (index1 < len1 && s1.charAt(index1) == s3.charAt(index3)) { + ret = recMemory2(s1, index1 + 1, s2, index2, s3, index3 + 1, memory); + } + + // 如果不成功(首字母不来自于s1),尝试另一种可能,即有可能是来自s2的 + // 注意,一定要判定index2 是否越界,否则会出问题 + if (!ret && index2 < len2 && s2.charAt(index2) == s3.charAt(index3)) { + ret = recMemory2(s1, index1, s2, index2 + 1, s3, index3 + 1, memory); + } + + memory[index1][index2] = ret ? 1 : 0; + return ret; + } +} From 5a07fde01002ab726f3103f69b1fc6ff574145ff Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 17 Oct 2014 02:16:55 -0700 Subject: [PATCH 135/319] DP --- dp/IsInterleave.java | 51 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/dp/IsInterleave.java b/dp/IsInterleave.java index 1915f6d..395fc29 100644 --- a/dp/IsInterleave.java +++ b/dp/IsInterleave.java @@ -74,7 +74,7 @@ public static boolean recMemory(String s1, int index1, String s2, // Solution2: Recursion with memory // 思考了一下看了一下过去的代码,发现其实我们用不到三维数组,因为len1 + len2 = len3, // 所以第三维根本可以省略嘛 - public static boolean isInterleave(String s1, String s2, String s3) { + public static boolean isInterleave2(String s1, String s2, String s3) { if (s1 == null || s2 == null || s3 == null) { return false; } @@ -122,6 +122,7 @@ public static boolean recMemory2(String s1, int index1, String s2, // 如果不成功(首字母不来自于s1),尝试另一种可能,即有可能是来自s2的 // 注意,一定要判定index2 是否越界,否则会出问题 + // 另外,我们判断!ret 的目的是省去重复计算,如果前一个判断已经是TRUE了,这里就不必再算了。 if (!ret && index2 < len2 && s2.charAt(index2) == s3.charAt(index3)) { ret = recMemory2(s1, index1, s2, index2 + 1, s3, index3 + 1, memory); } @@ -129,4 +130,52 @@ public static boolean recMemory2(String s1, int index1, String s2, memory[index1][index2] = ret ? 1 : 0; return ret; } + + // Solution3: + // DP解法 + // D[i][j]: 定义为s1 (前i个字符) s2(前j个字符) s3(i+j) 是不是交叉字符 + // (s1.i == s3.(i+j) && D[i-1][j]) || (s2.j == s3.(i+j) && D[i][j - 1]) + public static boolean isInterleave(String s1, String s2, String s3) { + if (s1 == null || s2 == null || s3 == null) { + return false; + } + + int len1 = s1.length(); + int len2 = s2.length(); + int len3 = s3.length(); + + // The length is not equal, just return false. + if (len1 + len2 != len3) { + return false; + } + + // 注意,这里要用len1 + 1,因为我们要从0算到len1 (0表示s1取空) + // D[0][0] = true + boolean[][] D = new boolean[len1 + 1][len2 + 1]; + for (int i = 0; i <= len1; i++) { + for (int j = 0; j <= len2; j++) { + if (i == 0 && j == 0) { + D[i][j] = true; + } else { + boolean b1 = false; + // the index in s3. + int index = i + j - 2; + if (i > 0 && s1.charAt(i - 1) == s2.charAt(index) + && D[i - 1][j]) { + b1 = true; + } + + boolean b2 = false; + if (j > 0 && s2.charAt(j - 1) == s2.charAt(index) + && D[i][j - 1]) { + b2 = true; + } + + D[i][j] = b1 | b2; + } + } + } + + return D[len1][len2]; + } } From c5231a1ec33748234788f2a50755198e7cdb795a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 17 Oct 2014 03:30:42 -0700 Subject: [PATCH 136/319] swap pairs --- list/SwapPairs.java | 75 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 list/SwapPairs.java diff --git a/list/SwapPairs.java b/list/SwapPairs.java new file mode 100644 index 0000000..e46cc8b --- /dev/null +++ b/list/SwapPairs.java @@ -0,0 +1,75 @@ +package Algorithms.list; + +import Algorithms.algorithm.others.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ + +public class SwapPairs { + // Solution 1: recursion. + public ListNode swapPairs1(ListNode head) { + return rec(head); + } + + public ListNode rec(ListNode head) { + // nodes less than 2, do nothing. + if (head == null || head.next == null) { + return head; + } + + // reverse the next part. + ListNode next = rec(head.next.next); + + // store the new head; + ListNode headNew = head.next; + + // reverse the two nodes. + headNew.next = head; + head.next = next; + + return headNew; + } + + public ListNode swapPairs(ListNode head) { + if (head == null || head.next == null) { + return head; + } + + ListNode dummy = new ListNode(0); + dummy.next = head; + + // the node before the area which want to reverse + ListNode pre = dummy; + + while (pre.next != null && pre.next.next != null) { + // the node after the area which want to reverse + ListNode next = pre.next.next.next; + + // reserve the new tail. + ListNode tmp = pre.next; + + // link pre to the new head; + pre.next = pre.next.next; + + // link the next node. + pre.next.next = tmp; + + // linke the area to the next area. + tmp.next = next; + + // move forward the pre node. + pre = tmp; + } + + return dummy.next; + } +} From 18911c2b0fb542c38bff2ea4cec71455ca2dd15b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 17 Oct 2014 04:28:50 -0700 Subject: [PATCH 137/319] longest Substrting --- string/LengthOfLongestSubstring.java | 36 ++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 string/LengthOfLongestSubstring.java diff --git a/string/LengthOfLongestSubstring.java b/string/LengthOfLongestSubstring.java new file mode 100644 index 0000000..1b7a7ba --- /dev/null +++ b/string/LengthOfLongestSubstring.java @@ -0,0 +1,36 @@ +package Algorithms.string; + +import java.util.HashMap; + +public class LengthOfLongestSubstring { + public int lengthOfLongestSubstring(String s) { + if (s == null) { + return 0; + } + + int len = s.length(); + + // The start of the window. + int start = 0; + int max = 0; + + HashMap map = new HashMap(); + + for (int end = 0; end < len; end++) { + char c = s.charAt(end); + if (map.containsKey(c)) { + if (map.get(c) >= start) { + start = map.get(c) + 1; + } + } + + //更新map里的char 的位置 + map.put(c, end); + + int subLen = end - start + 1; + max = Math.max(max, subLen); + } + + return max; + } +} \ No newline at end of file From ac38eb79a0a7242603fe9fbaa571041d89b67dbb Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 17 Oct 2014 04:57:12 -0700 Subject: [PATCH 138/319] profit --- dp/MaxProfit.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 dp/MaxProfit.java diff --git a/dp/MaxProfit.java b/dp/MaxProfit.java new file mode 100644 index 0000000..db26a1f --- /dev/null +++ b/dp/MaxProfit.java @@ -0,0 +1,19 @@ +package Algorithms.dp; + +public class MaxProfit { + public int maxProfit(int[] prices) { + if (prices == null) { + return 0; + } + + int len = prices.length; + int maxProfit = 0; + int minPrice = Integer.MAX_VALUE; + for (int i = 0; i < len; i++) { + minPrice = Math.min(minPrice, prices[i]); + maxProfit = Math.max(maxProfit, prices[i] - minPrice); + } + + return maxProfit; + } +} \ No newline at end of file From 89911c81efecf902d1ad87c6614082eed0935f37 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 17 Oct 2014 05:19:54 -0700 Subject: [PATCH 139/319] max profit --- dp/MaxProfit2.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 dp/MaxProfit2.java diff --git a/dp/MaxProfit2.java b/dp/MaxProfit2.java new file mode 100644 index 0000000..4b7f576 --- /dev/null +++ b/dp/MaxProfit2.java @@ -0,0 +1,18 @@ +package Algorithms.dp; + +public class MaxProfit2 { + public int maxProfit(int[] prices) { + if (prices == null) { + return 0; + } + + int profit = 0; + for (int i = 1; i < prices.length; i++) { + if (prices[i] - prices[i - 1] > 0) { + profit += prices[i] - prices[i - 1]; + } + } + + return profit; + } +} \ No newline at end of file From adfc2ea4015776c22a559184bd479ec59bd9ac3b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 17 Oct 2014 05:53:36 -0700 Subject: [PATCH 140/319] stock3 --- dp/MaxProfit3.java | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 dp/MaxProfit3.java diff --git a/dp/MaxProfit3.java b/dp/MaxProfit3.java new file mode 100644 index 0000000..d92cdbd --- /dev/null +++ b/dp/MaxProfit3.java @@ -0,0 +1,37 @@ +package Algorithms.dp; + +public class MaxProfit3 { + public int maxProfit(int[] prices) { + if (prices == null || prices.length == 0) { + return 0; + } + + int len = prices.length; + int[] left = new int[len]; + int[] right = new int[len]; + + // 计算i左边的最大利润 + int min = prices[0]; + left[0] = 0; + for (int i = 1; i < len; i++) { + min = Math.min(min, prices[i]); + left[i] = Math.max(left[i - 1], prices[i] - min); + } + + // 计算i右边的最大利润 + int max = prices[len - 1]; + right[len - 1] = 0; + for (int i = len - 2; i >= 0; i--) { + max = Math.max(max, prices[i]); + right[i] = Math.max(right[i + 1], max - prices[i]); + } + + // 把2边的利润相加 + int rst = 0; + for (int i = 0; i < len; i++) { + rst = Math.max(rst, left[i] + right[i]); + } + + return rst; + } +} \ No newline at end of file From 703db658c556afa9ecdac8858a0dac90a431891e Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 17 Oct 2014 22:32:56 -0700 Subject: [PATCH 141/319] word --- dp/WordBreak.java | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 dp/WordBreak.java diff --git a/dp/WordBreak.java b/dp/WordBreak.java new file mode 100644 index 0000000..f9f54e5 --- /dev/null +++ b/dp/WordBreak.java @@ -0,0 +1,39 @@ +package Algorithms.dp; + +import java.util.Set; + +public class WordBreak { + public boolean wordBreak(String s, Set dict) { + if (s == null) { + return false; + } + + int len = s.length(); + if (len == 0) { + return true; + } + + boolean[] D = new boolean[len + 1]; + + // initiate the DP. 注意,这里设置为true是不得已,因为当我们划分字串为左边为0,右边为n的时候, + // 而右边的n是一个字典string,那么左边必然要设置为true,才能使结果为true。所以空字符串我们需要 + // 认为true + D[0] = true; + + // D[i] 表示i长度的字符串能否被word break. + for (int i = 1; i <= len; i++) { + // 把子串划分为2部分,分别讨论 + D[i] = false; + for (int j = 0; j <= i; j++) { + if (D[j] && dict.contains(s.substring(j, i))) { + // 只要找到任意一个符合条件,我们就可以BREAK; 表示我们检查的 + // 这一个子串符合题意 + D[i] = true; + break; + } + } + } + + return D[len]; + } +} \ No newline at end of file From f085d2db13598cae183ddf0096b4c589c66d9e7b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 18 Oct 2014 00:12:50 -0700 Subject: [PATCH 142/319] word2 --- dp/WordBreak.java | 5 +-- dp/WordBreak2.java | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 dp/WordBreak2.java diff --git a/dp/WordBreak.java b/dp/WordBreak.java index f9f54e5..33338bf 100644 --- a/dp/WordBreak.java +++ b/dp/WordBreak.java @@ -22,9 +22,10 @@ public boolean wordBreak(String s, Set dict) { // D[i] 表示i长度的字符串能否被word break. for (int i = 1; i <= len; i++) { - // 把子串划分为2部分,分别讨论 + // 把子串划分为2部分,分别讨论, j 表示左边的字符串的长度 + // 成立的条件是:左边可以break, 而右边是一个字典单词 D[i] = false; - for (int j = 0; j <= i; j++) { + for (int j = 0; j < i; j++) { if (D[j] && dict.contains(s.substring(j, i))) { // 只要找到任意一个符合条件,我们就可以BREAK; 表示我们检查的 // 这一个子串符合题意 diff --git a/dp/WordBreak2.java b/dp/WordBreak2.java new file mode 100644 index 0000000..73b1429 --- /dev/null +++ b/dp/WordBreak2.java @@ -0,0 +1,77 @@ +package Algorithms.dp; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class WordBreak2 { + public static void main(String[] strs) { + Set dict = new HashSet(); + + dict.add("apple"); + dict.add("yuzhang"); + + System.out.println(wordBreak("appleyuzhang", dict).toString()); + } + + // 我们用DFS来解决这个问题吧 + public static List wordBreak(String s, Set dict) { + HashMap> map = new HashMap>(); + if (s == null || s.length() == 0 || dict == null) { + return null; + } + + return dfs(s, dict, map); + } + + // 我们用DFS来解决这个问题吧 + public static List dfs(String s, Set dict, HashMap> map) { + if (map.containsKey(s)) { + return map.get(s); + } + + List list = new ArrayList(); + int len = s.length(); + + if (len == 0) { + list.add(""); + } else { + // i 表示左边字符串的长度 + // 注意:i千万不要从0开始计算,否则会产生死循环。递归的要点是:你要把问题分解成更小的子问题。 + // 如果i = 0,代表左字符串为空,我们又回到求解s本身的word break,那就是一个死循环! + for (int i = 1; i <= len; i++) { + String sub = s.substring(0, i); + + // 左边的子串可以为空,或是在字典内 + if (!dict.contains(sub)) { + continue; + } + + // 字符串划分为2边,计算右边的word break. + List listRight = dfs(s.substring(i, len), dict, map); + + // 右边不能break的时候,我们跳过. + if (listRight.size() == 0) { + continue; + } + + // 把左字符串加到右字符串中,形成新的解. + for (String r: listRight) { + StringBuilder sb = new StringBuilder(); + sb.append(sub); + if (i != 0 && i != len) { + // 如果左边为空,或是右边为空,不需要贴空格 + sb.append(" "); + } + sb.append(r); + list.add(sb.toString()); + } + } + } + + map.put(s, list); + return list; + } +} From 838f9f203d7d7e5782ea9c72d599e05d759cae32 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 18 Oct 2014 01:59:44 -0700 Subject: [PATCH 143/319] bst --- binarySearch/FindMin.java | 41 ++++++++++++++ dp/WordBreak2.java | 110 ++++++++++++++++++++++++++++++++------ 2 files changed, 136 insertions(+), 15 deletions(-) create mode 100644 binarySearch/FindMin.java diff --git a/binarySearch/FindMin.java b/binarySearch/FindMin.java new file mode 100644 index 0000000..1da2520 --- /dev/null +++ b/binarySearch/FindMin.java @@ -0,0 +1,41 @@ +package Algorithms.binarySearch; +public class FindMin { + public int findMin(int[] num) { + if (num == null || num.length == 0) { + return 0; + } + + if (num.length == 1) { + return num[0]; + } + + + // 至少有2个元素,才有讨论的价值 + int l = 0; + int r = num.length - 1; + + while (l < r) { + int mid = l + (r - l)/2; + // Means that there is no rotate. + if (num[mid] >= num[l] && num[mid] <= num[r]) { + return num[0]; + } + + // rotate > 0的情况 + if (l == r - 1) { + // 当只余下2个元素的时候,这里是断点,右边的是小值 + return num[r]; + } + + if (num[mid] >= num[l]) { + // The left side is sorted. Discard left. + l = mid; + } else { + // The right side is sorted. + r = mid; + } + } + + return 0; + } +} \ No newline at end of file diff --git a/dp/WordBreak2.java b/dp/WordBreak2.java index 73b1429..67f4a74 100644 --- a/dp/WordBreak2.java +++ b/dp/WordBreak2.java @@ -2,22 +2,12 @@ import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Set; public class WordBreak2 { - public static void main(String[] strs) { - Set dict = new HashSet(); - - dict.add("apple"); - dict.add("yuzhang"); - - System.out.println(wordBreak("appleyuzhang", dict).toString()); - } - // 我们用DFS来解决这个问题吧 - public static List wordBreak(String s, Set dict) { + public static List wordBreak1(String s, Set dict) { HashMap> map = new HashMap>(); if (s == null || s.length() == 0 || dict == null) { return null; @@ -26,7 +16,7 @@ public static List wordBreak(String s, Set dict) { return dfs(s, dict, map); } - // 我们用DFS来解决这个问题吧 + // 解法1:我们用DFS来解决这个问题吧 public static List dfs(String s, Set dict, HashMap> map) { if (map.containsKey(s)) { return map.get(s); @@ -39,8 +29,6 @@ public static List dfs(String s, Set dict, HashMap dfs(String s, Set dict, HashMap wordBreak(String s, Set dict) { + HashMap> map = new HashMap>(); + if (s == null || s.length() == 0 || dict == null) { + return null; + } + + List ret = new ArrayList(); + + // 记录切割过程中生成的字母 + List path = new ArrayList(); + + dfs2(s, dict, path, ret, 0); + + return ret; + } + + // 我们用DFS模板来解决这个问题吧 + public static void dfs2(String s, Set dict, List path, List ret, int index) { + int len = s.length(); + if (index == len) { + // 结束了。index到了末尾 + StringBuilder sb = new StringBuilder(); + for (String str: path) { + sb.append(str); + sb.append(" "); + } + // remove the last " " + sb.deleteCharAt(sb.length() - 1); + ret.add(sb.toString()); + return; + } + + // 如果不加上这一行会超时。就是说不能break的时候,可以直接返回 + // 但这也许只是一个treak, 其实这种方法还是不大好。 + if (!iswordBreak(s.substring(index), dict)) { + return; + } + + for (int i = index; i < len; i++) { + // 注意这些索引的取值。左字符串的长度从0到len + String left = s.substring(index, i + 1); + if (!dict.contains(left)) { + // 如果左字符串不在字典中,不需要继续递归 + continue; + } + + path.add(left); + dfs2(s, dict, path, ret, i + 1); + path.remove(path.size() - 1); + } + } + + public static boolean iswordBreak(String s, Set dict) { + if (s == null) { + return false; + } + + int len = s.length(); + if (len == 0) { + return true; + } + + boolean[] D = new boolean[len + 1]; + + // initiate the DP. 注意,这里设置为true是不得已,因为当我们划分字串为左边为0,右边为n的时候, + // 而右边的n是一个字典string,那么左边必然要设置为true,才能使结果为true。所以空字符串我们需要 + // 认为true + D[0] = true; + + // D[i] 表示i长度的字符串能否被word break. + for (int i = 1; i <= len; i++) { + // 把子串划分为2部分,分别讨论, j 表示左边的字符串的长度 + // 成立的条件是:左边可以break, 而右边是一个字典单词 + D[i] = false; + for (int j = 0; j < i; j++) { + if (D[j] && dict.contains(s.substring(j, i))) { + // 只要找到任意一个符合条件,我们就可以BREAK; 表示我们检查的 + // 这一个子串符合题意 + D[i] = true; + break; + } + } + } + + return D[len]; + } +} \ No newline at end of file From 4a588886e08d3cf4fbb4539fec2c40c799cd5441 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 18 Oct 2014 04:50:31 -0700 Subject: [PATCH 144/319] string len --- string/LengthOfLastWord.java | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 string/LengthOfLastWord.java diff --git a/string/LengthOfLastWord.java b/string/LengthOfLastWord.java new file mode 100644 index 0000000..43bc650 --- /dev/null +++ b/string/LengthOfLastWord.java @@ -0,0 +1,51 @@ +package Algorithms.string; + +public class LengthOfLastWord { + public static void main(String[] strs) { + String s = " the book "; + System.out.println(lengthOfLastWord1(s)); + } + + // solution 1 + public static int lengthOfLastWord1(String s) { + if (s == null || s.length() == 0) { + return 0; + } + + /* + 这里有个规则,它乍看之下很古怪,但很少造成问题:Split会保留开头处的空字段,却舍去结尾处的空字段。例如: + + my @fields = split /:/, “:::a:b:c:::”; #得到(“”,“”,“”,“a”,“b”,“c”) + */ + String[] strs = s.split("\\s+"); + + int size = strs.length; + if (size == 0) { + return 0; + } + int len = strs[size - 1].length(); + return len; + } + + // solution 2 + public int lengthOfLastWord(String s) { + if (s == null || s.length() == 0) { + return 0; + } + + // remove the spaces at the end. + String strs = s.trim(); + + int len = strs.length(); + + int ret = 0; + for (int i = len - 1; i >= 0; i--) { + if (strs.charAt(i) == ' ') { + return ret; + } + ret++; + } + + return len; + } +} From 346c1506a014e5ad05a4a8693f22e36556ea66b9 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 18 Oct 2014 15:05:40 -0700 Subject: [PATCH 145/319] window --- string/MinWindow.java | 75 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 string/MinWindow.java diff --git a/string/MinWindow.java b/string/MinWindow.java new file mode 100644 index 0000000..6d187ce --- /dev/null +++ b/string/MinWindow.java @@ -0,0 +1,75 @@ +package Algorithms.string; + +import java.util.HashMap; + +public class MinWindow { + public static void main(String[] strs) { + System.out.println(minWindow("aa", "aa")); + } + + public static String minWindow(String S, String T) { + if (S == null || T == null) { + return null; + } + + // Create a map to record the characters exit time. + HashMap map = new HashMap(); + + int lenS = S.length(); + int lenT = T.length(); + for (int i = 0; i < lenT; i++) { + Integer times = map.get(T.charAt(i)); + if (times == null) { + map.put(T.charAt(i), 1); + } else { + map.put(T.charAt(i), times + 1); + } + } + + int left = 0; + int right = 0; + + int size = 0; + + String ret = ""; + + int minLen = Integer.MAX_VALUE; + + // 注意:这里right 要++ + for (right = 0 ; right < lenS; right++) { + char cRight = S.charAt(right); + if (map.containsKey(cRight)) { + map.put(cRight, map.get(cRight) - 1); + if (map.get(cRight) == 0) { + // 表示某一个字符全部出现了. + size++; + } + } + + // shift the left point to right, until all the dupilcate characters gone. + while (left < lenS) { + char c = S.charAt(left); + // 如果这字符出现的次数刚好,或是不够,是不可以移动Left的 + if (map.get(c) != null && map.get(c) >= 0) { + break; + } + + // 可以删除无关的字符,以及重复的字符 + if (map.get(c) != null) { + map.put(c, map.get(c) + 1); + } + + left++; + } + + int len = right - left + 1; + // 字符都出现了 + if (size == map.size() && len < minLen) { + ret = S.substring(left, right + 1); + minLen = len; + } + } + + return ret; + } +} \ No newline at end of file From 95d1b7aa5b9e7f122de44776b15af731e1f926c8 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 18 Oct 2014 18:00:39 -0700 Subject: [PATCH 146/319] window --- string/MinWindow.java | 77 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/string/MinWindow.java b/string/MinWindow.java index 6d187ce..2a5c4c8 100644 --- a/string/MinWindow.java +++ b/string/MinWindow.java @@ -4,10 +4,16 @@ public class MinWindow { public static void main(String[] strs) { - System.out.println(minWindow("aa", "aa")); + System.out.println(minWindow("aa", "aab")); + System.out.println(minWindow1("aa", "aab")); + + int a [] = new int [5] ; + System.out.println("" + a[0]) ; } - - public static String minWindow(String S, String T) { + /* + * Use Hashmap to do it. + * */ + public static String minWindow1(String S, String T) { if (S == null || T == null) { return null; } @@ -72,4 +78,69 @@ public static String minWindow(String S, String T) { return ret; } + + /* + * Try to do it with Arrays. + * */ + public static String minWindow(String S, String T) { + if (S == null || T == null) { + return null; + } + + // 隐式初始化后,它们默认是0 + // http://developer.51cto.com/art/200906/128274.htm + int[] cntS = new int[256]; + int[] cntT = new int[256]; + + int lenS = S.length(); + int lenT = T.length(); + + // count all the characters in T. + int cntCharT = 0; + for (int i = 0; i < lenT; i++) { + cntT[T.charAt(i)]++; + if (cntT[T.charAt(i)] == 1) { + // 计算T中不同字母的个数 + cntCharT++; + } + } + + // 从左至右扫描 S + int left = 0; // LEFT set to the left and move right. + int cnt = 0; + int minLen = Integer.MAX_VALUE; + + String ret = ""; + for (int i = 0; i < lenS; i++) { + char c = S.charAt(i); + if (cntT[c] != 0) { + cntS[c]++; + //c字母全部出现了 + if (cntS[c] == cntT[c]) { + cnt++; + } + } + + while (cnt == cntCharT) { + // 更新最小长度 + if (i - left + 1 < minLen) { + minLen = i - left + 1; + ret = S.substring(left, i + 1); + } + + // 从左边移除一个字符 + if (cntT[c] != 0) { + cntS[c]--; + } + + // 如果某个字符被减到小于预定值,cnt要减少。 + if (cntS[c] < cntT[c]) { + cnt--; + } + left++; + } + } + + return ret; + } } \ No newline at end of file From d009e4402f224310cd1a79d89aa6c6b17e9c08e8 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 18 Oct 2014 18:04:07 -0700 Subject: [PATCH 147/319] size to 128 --- string/MinWindow.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/string/MinWindow.java b/string/MinWindow.java index 2a5c4c8..f7741a9 100644 --- a/string/MinWindow.java +++ b/string/MinWindow.java @@ -89,8 +89,8 @@ public static String minWindow(String S, String T) { // 隐式初始化后,它们默认是0 // http://developer.51cto.com/art/200906/128274.htm - int[] cntS = new int[256]; - int[] cntT = new int[256]; + int[] cntS = new int[128]; + int[] cntT = new int[128]; int lenS = S.length(); int lenT = T.length(); From 9241a5148ba94d79c7dfcb3dbbbd3ad5474bdcf1 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 19 Oct 2014 02:32:53 -0700 Subject: [PATCH 148/319] isScamble --- dp/IsScramble.java | 211 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 dp/IsScramble.java diff --git a/dp/IsScramble.java b/dp/IsScramble.java new file mode 100644 index 0000000..4c28f03 --- /dev/null +++ b/dp/IsScramble.java @@ -0,0 +1,211 @@ +package Algorithms.dp; + +import java.util.Arrays; + +public class IsScramble { + public static void main(String[] strs) { + System.out.println(isScramble("a", "a")); + + } + + public static boolean isScramble1(String s1, String s2) { + if (s1 == null || s2 == null) { + return false; + } + + int len1 = s1.length(); + int len2 = s2.length(); + + // the two strings should be the same length. + if (len1 != len2) { + return false; + } + + return rec(s1, s2); + } + + // Solution 1: The recursion version. + public static boolean rec1(String s1, String s2) { + int len = s1.length(); + + // the base case. + if (len == 1) { + return s1.equals(s2); + } + + // 划分2个字符串 + for (int i = 1; i < len; i++) { + // we have two situation; + // the left-left right-right & left-right right-left + if (rec1(s1.substring(0, i), s2.substring(0, i)) + && rec1(s1.substring(i, len), s2.substring(i, len))) { + return true; + } + + if (rec1(s1.substring(0, i), s2.substring(len - i, len)) + && rec1(s1.substring(i, len), s2.substring(0, len - i))) { + return true; + } + } + + return false; + } + + // Solution 2: The recursion version with sorting. + // 排序之后的剪枝可以通过LeetCode的检查 + public static boolean rec(String s1, String s2) { + int len = s1.length(); + + // the base case. + if (len == 1) { + return s1.equals(s2); + } + + // sort to speed up. + char[] s1ch = s1.toCharArray(); + Arrays.sort(s1ch); + String s1Sort = new String(s1ch); + + char[] s2ch = s2.toCharArray(); + Arrays.sort(s2ch); + String s2Sort = new String(s2ch); + + if (!s1Sort.equals(s2Sort)) { + return false; + } + + // 划分2个字符串 + for (int i = 1; i < len; i++) { + // we have two situation; + // the left-left right-right & left-right right-left + if (rec(s1.substring(0, i), s2.substring(0, i)) + && rec(s1.substring(i, len), s2.substring(i, len))) { + return true; + } + + if (rec(s1.substring(0, i), s2.substring(len - i, len)) + && rec(s1.substring(i, len), s2.substring(0, len - i))) { + return true; + } + } + + return false; + } + + // Solution 3: The recursion version with memory. + // 通过记忆矩阵来减少计算量 + public static boolean isScramble3(String s1, String s2) { + if (s1 == null || s2 == null) { + return false; + } + + int len1 = s1.length(); + int len2 = s2.length(); + + // the two strings should be the same length. + if (len1 != len2) { + return false; + } + + int[][][] mem = new int[len1][len1][len1]; + for (int i = 0; i < len1; i++) { + for (int j = 0; j < len1; j++) { + for (int k = 0; k < len1; k++) { + // -1 means unseted. + mem[i][j][k] = -1; + } + } + } + + return recMem(s1, 0, s2, 0, len1, mem); + } + + // Solution 3: The recursion version with memory. + // 通过记忆矩阵来减少计算量 + public static boolean recMem(String s1, int index1, String s2, int index2, + int len, int[][][] mem) { + // the base case. + if (len == 1) { + return s1.charAt(index1) == s2.charAt(index2); + } + + // LEN: 1 - totalLen-1 + int ret = mem[index1][index2][len - 1]; + if (ret != -1) { + return ret == 1 ? true : false; + } + + // 初始化为false + ret = 0; + + // 划分2个字符串. i means the length of the left side in S1 + for (int i = 1; i < len; i++) { + // we have two situation; + // the left-left right-right & left-right right-left + if (recMem(s1, index1, s2, index2, i, mem) + && recMem(s1, index1 + i, s2, index2 + i, len - i, mem)) { + ret = 1; + break; + } + + if (recMem(s1, index1, s2, index2 + len - i, i, mem) + && recMem(s1, index1 + i, s2, index2, len - i, mem)) { + ret = 1; + break; + } + } + + mem[index1][index2][len - 1] = ret; + return ret == 1 ? true : false; + } + + /* + * Solution 4: The DP Version. + */ + public static boolean isScramble(String s1, String s2) { + if (s1 == null || s2 == null) { + return false; + } + + int len1 = s1.length(); + int len2 = s2.length(); + + // the two strings should be the same length. + if (len1 != len2) { + return false; + } + + /* + * i: The index of string 1. j: The index of string 2. k: The length of + * the two string. 1 ~ len1 + * + * D[i][j][k] = + */ + boolean[][][] D = new boolean[len1][len1][len1 + 1]; + for (int subLen = 1; subLen <= len1; subLen++) { + // 注意这里的边界选取。 如果选的不对,就会发生越界的情况.. orz.. + // 另外,这里要取 i1 <= + for (int i1 = 0; i1 <= len1 - subLen; i1++) { + for (int i2 = 0; i2 <= len1 - subLen; i2++) { + if (subLen == 1) { + D[i1][i2][subLen] = s1.charAt(i1) == s2.charAt(i2); + continue; + } + + D[i1][i2][subLen] = false; + for (int l = 1; l < subLen; l++) { + if (D[i1][i2][l] && D[i1 + l][i2 + l][subLen - l] + || D[i1][i2 + subLen - l][l] && D[i1 + l][i2][subLen - l] + ) { + D[i1][i2][subLen] = true; + break; + } + } + } + } + } + + return D[0][0][len1]; + } + +} From 6f471ddae9578a7230c5ef19ebdea338514f5ac9 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 19 Oct 2014 16:49:24 -0700 Subject: [PATCH 149/319] search --- binarySearch/searchInsert.java | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 binarySearch/searchInsert.java diff --git a/binarySearch/searchInsert.java b/binarySearch/searchInsert.java new file mode 100644 index 0000000..370d2ad --- /dev/null +++ b/binarySearch/searchInsert.java @@ -0,0 +1,29 @@ +package Algorithms.binarySearch; + +public class searchInsert { + public static void main(String[] args) { + int[] A = {1,3,5,6}; + int target = 0; + + System.out.println(searchInsert(A, target)); + } + + public static int searchInsert(int[] A, int target) { + int low = 0, high = A.length-1; + int mid = low + (high-low)/2; + + while(low <= high){ + mid = low + (high-low)/2; + if(A[mid] == target){ + return mid; + }else if(target > A[mid]){ + low = mid+1; + }else{ + high = mid-1; + } + } + + // 返回下限值,此时刚好为适合插入的位置 + return low; + } +} From b4483a397c3b75474266ecb442676754fb509c59 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 19 Oct 2014 18:15:14 -0700 Subject: [PATCH 150/319] reverse --- list/ReverseKGroup.java | 73 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 list/ReverseKGroup.java diff --git a/list/ReverseKGroup.java b/list/ReverseKGroup.java new file mode 100644 index 0000000..0683116 --- /dev/null +++ b/list/ReverseKGroup.java @@ -0,0 +1,73 @@ +package Algorithms.list; + +import Algorithms.algorithm.others.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class ReverseKGroup { + // Solution 1: + // recursion. + public ListNode reverseKGroup1(ListNode head, int k) { + if (head == null) { + return null; + } + + return rec(head, k); + } + + public class ReturnType{ + ListNode head; + ListNode tail; + + ReturnType(ListNode head, ListNode tail) { + this.head = head; + this.tail = tail; + } + } + + public ListNode rec(ListNode head, int k) { + ListNode dummy = new ListNode(0); + + dummy.next = head; + + int len = 0; + ListNode cur = head; + while (cur != null) { + ListNode tmp = cur.next; + cur.next = dummy.next; + dummy.next = cur; + cur = tmp; + len++; + + // reverse all the k nodes. + if (len == k) { + // link the tail to the next node in the list. + head.next = rec(tmp, k); + break; + } + } + + if (len != k) { + ListNode node = dummy.next; + dummy.next = null; + + while (node != null) { + ListNode next = node.next; + node.next = dummy.next; + dummy.next = node; + node = next; + } + } + + return dummy.next; + } +} From c0746d153ce206b11a49d94b2f9b548580acd7f9 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 19 Oct 2014 19:18:04 -0700 Subject: [PATCH 151/319] reverse --- list/ReverseKGroup.java | 73 +++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/list/ReverseKGroup.java b/list/ReverseKGroup.java index 0683116..919e6f9 100644 --- a/list/ReverseKGroup.java +++ b/list/ReverseKGroup.java @@ -16,6 +16,7 @@ public class ReverseKGroup { // Solution 1: // recursion. + // 思路是先反转,如果发现长度不够K,再翻回来 public ListNode reverseKGroup1(ListNode head, int k) { if (head == null) { return null; @@ -24,16 +25,6 @@ public ListNode reverseKGroup1(ListNode head, int k) { return rec(head, k); } - public class ReturnType{ - ListNode head; - ListNode tail; - - ReturnType(ListNode head, ListNode tail) { - this.head = head; - this.tail = tail; - } - } - public ListNode rec(ListNode head, int k) { ListNode dummy = new ListNode(0); @@ -70,4 +61,66 @@ public ListNode rec(ListNode head, int k) { return dummy.next; } + + /* + * Solution 2: + * 使用区间反转的办法, iteration. + * */ + public ListNode reverseKGroup(ListNode head, int k) { + if (head == null) { + return null; + } + + ListNode dummy = new ListNode(0); + dummy.next = head; + + ListNode cur = head; + ListNode pre = dummy; + + int cnt = 0; + + while (cur != null) { + cnt++; + if (cnt == k) { + cnt = 0; + pre = reverse(pre, cur.next); + } + cur = cur.next; + } + + return dummy.next; + } + + /** + * Reverse a link list between pre and next exclusively + * an example: + * a linked list: + * 0->1->2->3->4->5->6 + * | | + * pre next + * after call pre = reverse(pre, next) + * + * 0->3->2->1->4->5->6 + * | | + * pre next + * @param pre + * @param next + * @return the reversed list's last node, which is the precedence of parameter next + */ + private static ListNode reverse(ListNode pre, ListNode next){ + ListNode cur = pre.next; + + // record the new tail. + ListNode last = cur; + while (cur != next) { + ListNode tmp = cur.next; + cur.next = pre.next; + pre.next = cur; + cur = tmp; + } + + last.next = next; + return last; + } + } From 53d3782b00832255abee6d10430974e43e55cb0c Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 19 Oct 2014 21:43:50 -0700 Subject: [PATCH 152/319] patition --- dfs/Partition.java | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 dfs/Partition.java diff --git a/dfs/Partition.java b/dfs/Partition.java new file mode 100644 index 0000000..ef270ab --- /dev/null +++ b/dfs/Partition.java @@ -0,0 +1,76 @@ +package Algorithms.dfs; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class Partition { + public List> partition(String s) { + List> ret = new ArrayList>(); + List path = new ArrayList(); + + if (s == null) { + return ret; + } + + HashMap map = new HashMap(); + + dfs(s, path, ret, 0, map); + + return ret; + } + + public boolean isPalindrom(String s) { + int len = s.length(); + if (len <= 1) { + return true; + } + + int left = 0; + int right = len - 1; + for (; left < right; left++, right--) { + if (s.charAt(right) != s.charAt(left)) { + return false; + } + } + + return true; + } + + /* + we use a map to store the solutions to reduce the times of computing. + */ + public void dfs(String s, List path, List> ret, int index, HashMap map) { + if (index == s.length()) { + ret.add(new ArrayList(path)); + return; + } + + for (int i = index; i < s.length(); i++) { + String sub = s.substring(index, i + 1); + + Boolean flag = map.get(sub); + if (flag == null) { + flag = isPalindrom(sub); + map.put(sub, flag); + } + + if (!flag) { + continue; + } + + path.add(sub); + dfs(s, path, ret, i + 1, map); + path.remove(path.size() - 1); + } + } + + /* + * Solution 2: Use DP to reduce the duplicate count. + * */ + boolean[][] isPalindromDP(String s) { + int len = s.length(); + boolean[][] ret = new boolean[len][len]; + } + +} From 5f4d6e31bcfbe46929294eff3968df4badad165d Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 19 Oct 2014 22:04:02 -0700 Subject: [PATCH 153/319] dp --- dfs/Partition.java | 58 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/dfs/Partition.java b/dfs/Partition.java index ef270ab..f9a1e77 100644 --- a/dfs/Partition.java +++ b/dfs/Partition.java @@ -5,7 +5,7 @@ import java.util.List; public class Partition { - public List> partition(String s) { + public List> partition1(String s) { List> ret = new ArrayList>(); List path = new ArrayList(); @@ -64,13 +64,63 @@ public void dfs(String s, List path, List> ret, int index, path.remove(path.size() - 1); } } + + public List> partition(String s) { + List> ret = new ArrayList>(); + List path = new ArrayList(); + + if (s == null) { + return ret; + } + + boolean[][] isPalindrom = buildPalindromDP(s); + + dfs2(s, path, ret, 0, isPalindrom); + + return ret; + } /* * Solution 2: Use DP to reduce the duplicate count. * */ - boolean[][] isPalindromDP(String s) { + boolean[][] buildPalindromDP(String s) { int len = s.length(); - boolean[][] ret = new boolean[len][len]; + boolean[][] D = new boolean[len][len]; + + for (int j = 0; j < len; j++) { + for (int i = 0; i <= j; i++) { + if (j == 0) { + D[i][j] = true; + continue; + } + + // 注意,这里要加上j - i <= 2否则会越界 + D[i][j] = s.charAt(i) == s.charAt(j) + && (j - i <= 2 || D[i + 1][j - 1]); + } + } + + return D; + } + + /* + we use a map to store the solutions to reduce the times of computing. + */ + public void dfs2(String s, List path, List> ret, int index, boolean[][] isPalindromDP) { + if (index == s.length()) { + ret.add(new ArrayList(path)); + return; + } + + for (int i = index; i < s.length(); i++) { + String sub = s.substring(index, i + 1); + if (!isPalindromDP[index][i]) { + continue; + } + + path.add(sub); + dfs2(s, path, ret, i + 1, isPalindromDP); + path.remove(path.size() - 1); + } } - } From a1ffa1f953a0b5c080f33864561c396c1c4e208a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 19 Oct 2014 23:41:46 -0700 Subject: [PATCH 154/319] word --- dp/WordBreak2.java | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/dp/WordBreak2.java b/dp/WordBreak2.java index 67f4a74..b48a2a0 100644 --- a/dp/WordBreak2.java +++ b/dp/WordBreak2.java @@ -1,11 +1,53 @@ package Algorithms.dp; + import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Set; public class WordBreak2 { + public static void main(String[] strs) { + String s = "aaaaaaaaaaaaaaaaaaaaaaa"; + Set dict = new HashSet(); + dict.add("bin"); + dict.add("apple"); + dict.add("app"); + dict.add("le"); + dict.add("aaaaaa"); + dict.add("aaaaa"); + dict.add("aaaa"); + dict.add("aaa"); + dict.add("aa"); + dict.add("a"); + dict.add("aaaaaaa"); + dict.add("aaaaaaaa"); + dict.add("aaaaaaaaa"); + + System.out.println("Test"); + + Algorithms.permutation.Stopwatch timer1 = new Algorithms.permutation.Stopwatch(); + + // 递归模板,加剪枝 + List list = wordBreak(s, dict); + + System.out + .println("Computing time with dfs and cut branch used as Queue/Deque: " + + timer1.elapsedTime() + " millisec."); + + Algorithms.permutation.Stopwatch timer2 = new Algorithms.permutation.Stopwatch(); + + // HASH保存记忆 + List list2 = wordBreak1(s, dict); + + System.out + .println("Computing time with ArrayDeque used as Queue/Deque: " + + timer2.elapsedTime() + " millisec."); + + //System.out.println(list.toString()); + } + // 我们用DFS来解决这个问题吧 public static List wordBreak1(String s, Set dict) { HashMap> map = new HashMap>(); @@ -69,7 +111,6 @@ public static List dfs(String s, Set dict, HashMap wordBreak(String s, Set dict) { - HashMap> map = new HashMap>(); if (s == null || s.length() == 0 || dict == null) { return null; } From 2c5df57bc000a8922bb7d7052d46d499851e4b2b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 20 Oct 2014 00:01:52 -0700 Subject: [PATCH 155/319] word break --- dfs/Partition.java | 19 +++++------ dp/WordBreak2.java | 84 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 91 insertions(+), 12 deletions(-) diff --git a/dfs/Partition.java b/dfs/Partition.java index f9a1e77..72b4fa1 100644 --- a/dfs/Partition.java +++ b/dfs/Partition.java @@ -88,16 +88,15 @@ boolean[][] buildPalindromDP(String s) { boolean[][] D = new boolean[len][len]; for (int j = 0; j < len; j++) { - for (int i = 0; i <= j; i++) { - if (j == 0) { - D[i][j] = true; - continue; - } - - // 注意,这里要加上j - i <= 2否则会越界 - D[i][j] = s.charAt(i) == s.charAt(j) - && (j - i <= 2 || D[i + 1][j - 1]); - } + for (int i = 0; i <= j; i++) { + if (j == 0) { + D[i][j] = true; + continue; + } + + D[i][j] = s.charAt(i) == s.charAt(j) + && (j - i <= 2 || D[i + 1][j - 1]); + } } return D; diff --git a/dp/WordBreak2.java b/dp/WordBreak2.java index b48a2a0..986b1c9 100644 --- a/dp/WordBreak2.java +++ b/dp/WordBreak2.java @@ -39,11 +39,21 @@ public static void main(String[] strs) { Algorithms.permutation.Stopwatch timer2 = new Algorithms.permutation.Stopwatch(); // HASH保存记忆 - List list2 = wordBreak1(s, dict); + wordBreak1(s, dict); System.out .println("Computing time with ArrayDeque used as Queue/Deque: " + timer2.elapsedTime() + " millisec."); + + Algorithms.permutation.Stopwatch timer3 = new Algorithms.permutation.Stopwatch(); + + // DFS+ 剪枝 3: 设置Flag 变量 + //http://fisherlei.blogspot.com/2013/11/leetcode-wordbreak-ii-solution.html + wordBreak3(s, dict); + + System.out + .println("Computing time with ArrayDeque used as Queue/Deque: " + + timer3.elapsedTime() + " millisec."); //System.out.println(list.toString()); } @@ -126,7 +136,8 @@ public static List wordBreak(String s, Set dict) { } // 我们用DFS模板来解决这个问题吧 - public static void dfs2(String s, Set dict, List path, List ret, int index) { + public static void dfs2(String s, Set dict, + List path, List ret, int index) { int len = s.length(); if (index == len) { // 结束了。index到了末尾 @@ -195,4 +206,73 @@ public static boolean iswordBreak(String s, Set dict) { return D[len]; } + + /* + // 解法3:重新剪枝。 + */ + + // 我们用DFS来解决这个问题吧 + public static List wordBreak3(String s, Set dict) { + if (s == null || s.length() == 0 || dict == null) { + return null; + } + + List ret = new ArrayList(); + + // 记录切割过程中生成的字母 + List path = new ArrayList(); + + int len = s.length(); + boolean canBreak[] = new boolean[len]; + for (int i = 0; i < len; i++) { + canBreak[i] = true; + } + + dfs3(s, dict, path, ret, 0, canBreak); + + return ret; + } + + // 我们用DFS模板来解决这个问题吧 + public static void dfs3(String s, Set dict, + List path, List ret, int index, + boolean canBreak[]) { + int len = s.length(); + if (index == len) { + // 结束了。index到了末尾 + StringBuilder sb = new StringBuilder(); + for (String str: path) { + sb.append(str); + sb.append(" "); + } + // remove the last " " + sb.deleteCharAt(sb.length() - 1); + ret.add(sb.toString()); + return; + } + + // if can't break, we exit directly. + if (!canBreak[index]) { + return; + } + + boolean flag = false; + for (int i = index; i < len; i++) { + // 注意这些索引的取值。左字符串的长度从0到len + String left = s.substring(index, i + 1); + if (!dict.contains(left)) { + // 如果左字符串不在字典中,不需要继续递归 + continue; + } + + // if can't find any solution, return false, other set it + // to be true; + flag = true; + path.add(left); + dfs3(s, dict, path, ret, i + 1, canBreak); + path.remove(path.size() - 1); + } + + canBreak[index] = flag; + } } \ No newline at end of file From 68c02a34ad0efb6de646ca7fc7a99b9bfb65c3a5 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 20 Oct 2014 01:27:57 -0700 Subject: [PATCH 156/319] dp --- dp/WordBreak2.java | 60 ++++++++++++++-------------------------------- 1 file changed, 18 insertions(+), 42 deletions(-) diff --git a/dp/WordBreak2.java b/dp/WordBreak2.java index 986b1c9..af58868 100644 --- a/dp/WordBreak2.java +++ b/dp/WordBreak2.java @@ -27,24 +27,24 @@ public static void main(String[] strs) { System.out.println("Test"); - Algorithms.permutation.Stopwatch timer1 = new Algorithms.permutation.Stopwatch(); - - // 递归模板,加剪枝 - List list = wordBreak(s, dict); - - System.out - .println("Computing time with dfs and cut branch used as Queue/Deque: " - + timer1.elapsedTime() + " millisec."); - Algorithms.permutation.Stopwatch timer2 = new Algorithms.permutation.Stopwatch(); // HASH保存记忆 wordBreak1(s, dict); System.out - .println("Computing time with ArrayDeque used as Queue/Deque: " + .println("Computing time with DFS1: " + timer2.elapsedTime() + " millisec."); + Algorithms.permutation.Stopwatch timer1 = new Algorithms.permutation.Stopwatch(); + + // 递归模板,加剪枝 + wordBreak(s, dict); + + System.out + .println("Computing time with DFS2: " + + timer1.elapsedTime() + " millisec."); + Algorithms.permutation.Stopwatch timer3 = new Algorithms.permutation.Stopwatch(); // DFS+ 剪枝 3: 设置Flag 变量 @@ -52,7 +52,7 @@ public static void main(String[] strs) { wordBreak3(s, dict); System.out - .println("Computing time with ArrayDeque used as Queue/Deque: " + .println("Computing time with DFS3: " + timer3.elapsedTime() + " millisec."); //System.out.println(list.toString()); @@ -207,32 +207,6 @@ public static boolean iswordBreak(String s, Set dict) { return D[len]; } - /* - // 解法3:重新剪枝。 - */ - - // 我们用DFS来解决这个问题吧 - public static List wordBreak3(String s, Set dict) { - if (s == null || s.length() == 0 || dict == null) { - return null; - } - - List ret = new ArrayList(); - - // 记录切割过程中生成的字母 - List path = new ArrayList(); - - int len = s.length(); - boolean canBreak[] = new boolean[len]; - for (int i = 0; i < len; i++) { - canBreak[i] = true; - } - - dfs3(s, dict, path, ret, 0, canBreak); - - return ret; - } - // 我们用DFS模板来解决这个问题吧 public static void dfs3(String s, Set dict, List path, List ret, int index, @@ -256,23 +230,25 @@ public static void dfs3(String s, Set dict, return; } - boolean flag = false; for (int i = index; i < len; i++) { // 注意这些索引的取值。左字符串的长度从0到len String left = s.substring(index, i + 1); - if (!dict.contains(left)) { + if (!dict.contains(left) || !canBreak[i + 1]) { // 如果左字符串不在字典中,不需要继续递归 continue; } // if can't find any solution, return false, other set it // to be true; - flag = true; path.add(left); + + int beforeChange = ret.size(); dfs3(s, dict, path, ret, i + 1, canBreak); + // 注意这些剪枝的代码. 关键在于此以减少复杂度 + if (ret.size() == beforeChange) { + canBreak[i + 1] = false; + } path.remove(path.size() - 1); } - - canBreak[index] = flag; } } \ No newline at end of file From 664a91c71f8696124ab3d199168f1cf2f5945373 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 20 Oct 2014 02:45:40 -0700 Subject: [PATCH 157/319] add two number --- dp/WordBreak2.java | 27 +++++++++++++++ list/AddTwoNumbers.java | 75 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 list/AddTwoNumbers.java diff --git a/dp/WordBreak2.java b/dp/WordBreak2.java index af58868..3f42018 100644 --- a/dp/WordBreak2.java +++ b/dp/WordBreak2.java @@ -207,6 +207,33 @@ public static boolean iswordBreak(String s, Set dict) { return D[len]; } + /* + // 解法3:重新剪枝。 + */ + // 我们用DFS来解决这个问题吧 + public static List wordBreak3(String s, Set dict) { + if (s == null || s.length() == 0 || dict == null) { + return null; + } + + List ret = new ArrayList(); + + // 记录切割过程中生成的字母 + List path = new ArrayList(); + + int len = s.length(); + + // 注意:一定要分配 Len+1 否则会爆哦. + boolean canBreak[] = new boolean[len + 1]; + for (int i = 0; i < len + 1; i++) { + canBreak[i] = true; + } + + dfs3(s, dict, path, ret, 0, canBreak); + + return ret; + } + // 我们用DFS模板来解决这个问题吧 public static void dfs3(String s, Set dict, List path, List ret, int index, diff --git a/list/AddTwoNumbers.java b/list/AddTwoNumbers.java new file mode 100644 index 0000000..a46119a --- /dev/null +++ b/list/AddTwoNumbers.java @@ -0,0 +1,75 @@ +package Algorithms.list; + +import Algorithms.algorithm.others.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class AddTwoNumbers { + public static void main(String[] str) { + ListNode n1 = new ListNode(9); + + ListNode l1 = new ListNode(1); + ListNode l2 = new ListNode(9); + ListNode l3 = new ListNode(9); + ListNode l4 = new ListNode(9); + ListNode l5 = new ListNode(9); + ListNode l6 = new ListNode(9); + ListNode l7 = new ListNode(9); + ListNode l8 = new ListNode(9); + ListNode l9 = new ListNode(9); + ListNode l10 = new ListNode(9); + + l1.next = l2; + l2.next = l3; + l3.next = l4; + l4.next = l5; + l5.next = l6; + l6.next = l7; + l7.next = l8; + l8.next = l9; + l9.next = l10; + + System.out.println(addTwoNumbers(n1, l1).toString()); + } + + public static ListNode addTwoNumbers(ListNode l1, ListNode l2) { + if (l1 == null || l2 == null) { + return null; + } + + ListNode dummy = new ListNode(0); + ListNode tail = dummy; + int carry = 0; + + while (l1 != null || l2 != null || carry == 1) { + int sum = carry; + if (l1 != null) { + sum += l1.val; + l1 = l1.next; + } + + if (l2 != null) { + sum += l2.val; + l2 = l2.next; + } + + carry = sum / 10; + + // create a new node and add it to the tail. + ListNode cur = new ListNode(sum % 10); + tail.next = cur; + tail = tail.next; + } + + return dummy.next; + } +} \ No newline at end of file From 5fadf43f9cfb9f5f884837e91e89ade2c4ff3f8e Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 20 Oct 2014 03:42:03 -0700 Subject: [PATCH 158/319] first --- array/FirstMissingPositive.java | 39 +++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 array/FirstMissingPositive.java diff --git a/array/FirstMissingPositive.java b/array/FirstMissingPositive.java new file mode 100644 index 0000000..97c7978 --- /dev/null +++ b/array/FirstMissingPositive.java @@ -0,0 +1,39 @@ +package Algorithms.array; + +public class FirstMissingPositive { + public static void main(String[] strs) { + int[] in = {1,2,0}; + //int[] in = {3,4,-1,1}; + System.out.println(firstMissingPositive(in)); + } + + public static int firstMissingPositive(int[] A) { + if (A == null) { + return 0; + } + + int len = A.length; + for (int i = 0; i < len; i++) { + // 1. The number should be in the range. + // 2. The number should be positive. + // 注意:和将要交换的值不可以相同,否则会死循环 + while (A[i] <= len && A[i] > 0 && A[A[i] - 1] != A[i]) { + swap(A, i, A[i] - 1); + } + } + + for (int i = 0; i < len; i++) { + if (A[i] != i + 1) { + return i + 1; + } + } + + return len + 1; + } + + public static void swap(int[] A, int i, int j) { + int tmp = A[i]; + A[i] = A[j]; + A[j] = tmp; + } +} \ No newline at end of file From f50700c8819e2b264d696889183fac83153eabc4 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 20 Oct 2014 03:50:03 -0700 Subject: [PATCH 159/319] find --- array/FirstMissingPositive.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/array/FirstMissingPositive.java b/array/FirstMissingPositive.java index 97c7978..35bc8be 100644 --- a/array/FirstMissingPositive.java +++ b/array/FirstMissingPositive.java @@ -12,6 +12,11 @@ public static int firstMissingPositive(int[] A) { return 0; } + /* + 使用桶排序,将数字放置在正确的位置,如果最后发现在某个位置不存在正确的数字,说明这个数字是缺失的。 + 在排序过程中,因为要不断交换直到不能再交换为止,所以遇到目标位置已经有正确数字时,不要再交换,以 + 免发生死循环。 + */ int len = A.length; for (int i = 0; i < len; i++) { // 1. The number should be in the range. From 64f46bdd5b61094f4767e89775bd0525165ca54d Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 20 Oct 2014 20:06:42 -0700 Subject: [PATCH 160/319] jump --- dp/CanJump.java | 82 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 dp/CanJump.java diff --git a/dp/CanJump.java b/dp/CanJump.java new file mode 100644 index 0000000..7efe4e9 --- /dev/null +++ b/dp/CanJump.java @@ -0,0 +1,82 @@ +package Algorithms.dp; + +public class CanJump { + public static void main(String[] strs) { + //int[] A = { 2, 2, 3, 4, 5 }; + } + + // DP1. + public boolean canJump1(int[] A) { + if (A == null || A.length == 0) { + return false; + } + + int len = A.length; + boolean[] can = new boolean[len]; + can[0] = true; + + for (int i = 1; i < len; i++) { + can[i] = false; + for (int j = 0; j < i; j++) { + // j can arrive and can jump to i. + if (can[j] && A[j] >= i - j) { + can[i] = true; + break; + } + } + } + + return can[len - 1]; + } + + // DP2. + public boolean canJump2(int[] A) { + if (A == null || A.length == 0) { + return false; + } + + int len = A.length; + + for (int i = 1; i < len; i++) { + boolean can = false; + for (int j = 0; j < i; j++) { + // j can arrive and can jump to i. + if (A[j] >= i - j) { + // 说明i是可达的,置标记位 + can = true; + break; + } + } + + // 优化:如果某一步已经到不了了,后面的也不必再计算了. + if (!can) { + return false; + } + } + + return true; + } + + // 3. DFS. + public static boolean canJump3(int[] A) { + if (A == null || A.length == 0) { + return false; + } + + return canJump(A, A.length - 1); + } + + public static boolean canJump(int[] A, int index) { + if (index == 0) { + return true; + } + + for (int i = 0; i <= index - 1; i++) { + if (A[i] >= index - i) { + return canJump(A, i); + } + } + + return false; + } +} From 46bf0215de738f552dabfb9794a64fce93b0f2d5 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 20 Oct 2014 20:30:58 -0700 Subject: [PATCH 161/319] atoi --- string/Atoi.java | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 string/Atoi.java diff --git a/string/Atoi.java b/string/Atoi.java new file mode 100644 index 0000000..db503d1 --- /dev/null +++ b/string/Atoi.java @@ -0,0 +1,45 @@ +package Algorithms.string; + +public class Atoi { + public int atoi(String str) { + if (str == null) { + return 0; + } + + // remove the spaces in the beginning and the end. + String s = str.trim(); + + boolean minus = false; + long num = 0; + for (int i = 0; i < s.length(); i++) { + /* + takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value. + */ + if (i == 0 && s.charAt(i) == '+') { + continue; + } else if (i == 0 && s.charAt(i) == '-'){ + // get the + minus = true; + continue; + } + + int c = s.charAt(i) - '0'; + if (c > 9 || c < 0) { + // invalid character. + break; + } + + num = num * 10 + c; + } + + // If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is // returned. + if (minus) { + num = -num; + num = Math.max(num, Integer.MIN_VALUE); + } else { + num = Math.min(num, Integer.MAX_VALUE); + } + + return (int)num; + } +} \ No newline at end of file From a1a7a65bba037f61e5bdd36d712570fd63bf0ca4 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 20 Oct 2014 23:45:34 -0700 Subject: [PATCH 162/319] exist --- dfs/Exist.java | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 dfs/Exist.java diff --git a/dfs/Exist.java b/dfs/Exist.java new file mode 100644 index 0000000..f9ffce7 --- /dev/null +++ b/dfs/Exist.java @@ -0,0 +1,79 @@ +package Algorithms.dfs; + +public class Exist { + public boolean exist(char[][] board, String word) { + if (board == null || word == null + || board.length == 0 || board[0].length == 0) { + return false; + } + + int rows = board.length; + int cols = board[0].length; + + boolean[][] visit = new boolean[rows][cols]; + + // i means the index. + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + // dfs all the characters in the matrix + if (dfs(board, i, j, word, 0, visit)) { + return true; + } + } + } + + return false; + } + + public boolean dfs(char[][] board, int i, int j, String word, int wordIndex, boolean[][] visit) { + int rows = board.length; + int cols = board[0].length; + + int len = word.length(); + if (wordIndex >= len) { + return true; + } + + // the index is out of bound. + if (i < 0 || i >= rows || j < 0 || j >= cols) { + return false; + } + + // the character is wrong. + if (word.charAt(wordIndex) != board[i][j]) { + return false; + } + + // 不要访问访问过的节点 + if (visit[i][j] == true) { + return false; + } + + visit[i][j] = true; + + // 递归 + // move down + if (dfs(board, i + 1, j, word, wordIndex + 1, visit)) { + return true; + } + + // move up + if (dfs(board, i - 1, j, word, wordIndex + 1, visit)) { + return true; + } + + // move right + if (dfs(board, i, j + 1, word, wordIndex + 1, visit)) { + return true; + } + + // move left + if (dfs(board, i, j - 1, word, wordIndex + 1, visit)) { + return true; + } + + // 回溯 + visit[i][j] = false; + return false; + } +} \ No newline at end of file From e02af9c2c2d17f7a44ac9ef5a4dc2452796d56b6 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 21 Oct 2014 03:15:18 -0700 Subject: [PATCH 163/319] dp --- dfs/Exist.java | 87 +++++++++++++++++++++++++++++++++++--- dp/WordBreak2.java | 103 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 171 insertions(+), 19 deletions(-) diff --git a/dfs/Exist.java b/dfs/Exist.java index f9ffce7..3d53964 100644 --- a/dfs/Exist.java +++ b/dfs/Exist.java @@ -1,7 +1,7 @@ package Algorithms.dfs; public class Exist { - public boolean exist(char[][] board, String word) { + public boolean exist1(char[][] board, String word) { if (board == null || word == null || board.length == 0 || board[0].length == 0) { return false; @@ -16,7 +16,7 @@ public boolean exist(char[][] board, String word) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { // dfs all the characters in the matrix - if (dfs(board, i, j, word, 0, visit)) { + if (dfs1(board, i, j, word, 0, visit)) { return true; } } @@ -25,7 +25,7 @@ public boolean exist(char[][] board, String word) { return false; } - public boolean dfs(char[][] board, int i, int j, String word, int wordIndex, boolean[][] visit) { + public boolean dfs1(char[][] board, int i, int j, String word, int wordIndex, boolean[][] visit) { int rows = board.length; int cols = board[0].length; @@ -53,22 +53,22 @@ public boolean dfs(char[][] board, int i, int j, String word, int wordIndex, boo // 递归 // move down - if (dfs(board, i + 1, j, word, wordIndex + 1, visit)) { + if (dfs1(board, i + 1, j, word, wordIndex + 1, visit)) { return true; } // move up - if (dfs(board, i - 1, j, word, wordIndex + 1, visit)) { + if (dfs1(board, i - 1, j, word, wordIndex + 1, visit)) { return true; } // move right - if (dfs(board, i, j + 1, word, wordIndex + 1, visit)) { + if (dfs1(board, i, j + 1, word, wordIndex + 1, visit)) { return true; } // move left - if (dfs(board, i, j - 1, word, wordIndex + 1, visit)) { + if (dfs1(board, i, j - 1, word, wordIndex + 1, visit)) { return true; } @@ -76,4 +76,77 @@ public boolean dfs(char[][] board, int i, int j, String word, int wordIndex, boo visit[i][j] = false; return false; } + + /* + * Solution 2: 可以省掉一个visit的数组 + * */ + public boolean exist(char[][] board, String word) { + if (board == null || word == null + || board.length == 0 || board[0].length == 0) { + return false; + } + + int rows = board.length; + int cols = board[0].length; + + // i means the index. + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + // dfs all the characters in the matrix + if (dfs(board, i, j, word, 0)) { + return true; + } + } + } + + return false; + } + + public boolean dfs(char[][] board, int i, int j, String word, int wordIndex) { + int rows = board.length; + int cols = board[0].length; + + int len = word.length(); + if (wordIndex >= len) { + return true; + } + + // the index is out of bound. + if (i < 0 || i >= rows || j < 0 || j >= cols) { + return false; + } + + // the character is wrong. + if (word.charAt(wordIndex) != board[i][j]) { + return false; + } + + // mark it to be '#', so we will not revisit this. + board[i][j] = '#'; + + // 递归 + // move down + if (dfs(board, i + 1, j, word, wordIndex + 1)) { + return true; + } + + // move up + if (dfs(board, i - 1, j, word, wordIndex + 1)) { + return true; + } + + // move right + if (dfs(board, i, j + 1, word, wordIndex + 1)) { + return true; + } + + // move left + if (dfs(board, i, j - 1, word, wordIndex + 1)) { + return true; + } + + // 回溯 + board[i][j] = word.charAt(wordIndex); + return false; + } } \ No newline at end of file diff --git a/dp/WordBreak2.java b/dp/WordBreak2.java index 3f42018..9113c44 100644 --- a/dp/WordBreak2.java +++ b/dp/WordBreak2.java @@ -39,7 +39,7 @@ public static void main(String[] strs) { Algorithms.permutation.Stopwatch timer1 = new Algorithms.permutation.Stopwatch(); // 递归模板,加剪枝 - wordBreak(s, dict); + wordBreak2(s, dict); System.out .println("Computing time with DFS2: " @@ -55,6 +55,13 @@ public static void main(String[] strs) { .println("Computing time with DFS3: " + timer3.elapsedTime() + " millisec."); + // DP + DFS + wordBreak4(s, dict); + + System.out + .println("Computing time with DFS4: " + + timer3.elapsedTime() + " millisec."); + //System.out.println(list.toString()); } @@ -92,10 +99,6 @@ public static List dfs(String s, Set dict, HashMap listRight = dfs(s.substring(i, len), dict, map); - // 右边不能break的时候,我们跳过. - if (listRight.size() == 0) { - continue; - } // 把左字符串加到右字符串中,形成新的解. for (String r: listRight) { @@ -120,7 +123,7 @@ public static List dfs(String s, Set dict, HashMap wordBreak(String s, Set dict) { + public static List wordBreak2(String s, Set dict) { if (s == null || s.length() == 0 || dict == null) { return null; } @@ -257,10 +260,12 @@ public static void dfs3(String s, Set dict, return; } + // cut branch. + int beforeChange = ret.size(); for (int i = index; i < len; i++) { // 注意这些索引的取值。左字符串的长度从0到len String left = s.substring(index, i + 1); - if (!dict.contains(left) || !canBreak[i + 1]) { + if (!dict.contains(left)) { // 如果左字符串不在字典中,不需要继续递归 continue; } @@ -268,14 +273,88 @@ public static void dfs3(String s, Set dict, // if can't find any solution, return false, other set it // to be true; path.add(left); - - int beforeChange = ret.size(); dfs3(s, dict, path, ret, i + 1, canBreak); - // 注意这些剪枝的代码. 关键在于此以减少复杂度 - if (ret.size() == beforeChange) { - canBreak[i + 1] = false; + + path.remove(path.size() - 1); + } + + // 注意这些剪枝的代码. 关键在于此以减少复杂度 + if (ret.size() == beforeChange) { + canBreak[index] = false; + } + } + + /* + // 解法4:先用DP来求解,然后再做 + */ + // 我们用DFS来解决这个问题吧 + public static List wordBreak4(String s, Set dict) { + if (s == null || s.length() == 0 || dict == null) { + return null; + } + + List ret = new ArrayList(); + + List path = new ArrayList(); + + int len = s.length(); + + // i: 表示从i索引开始的字串可以word break. + boolean[] D = new boolean[len + 1]; + D[len] = true; + for (int i = len - 1; i >= 0; i--) { + for (int j = i; j <= len - 1; j++) { + // 左边从i 到 j + D[i] = false; + if (D[j + 1] && dict.contains(s.substring(i, j + 1))) { + D[i] = true; + break; + } } + } + + dfs4(s, dict, path, ret, 0, D); + + return ret; + } + + // 我们用DFS模板来解决这个问题吧 + public static void dfs4(String s, Set dict, + List path, List ret, int index, + boolean canBreak[]) { + int len = s.length(); + if (index == len) { + // 结束了。index到了末尾 + StringBuilder sb = new StringBuilder(); + for (String str: path) { + sb.append(str); + sb.append(" "); + } + // remove the last " " + sb.deleteCharAt(sb.length() - 1); + ret.add(sb.toString()); + return; + } + + // if can't break, we exit directly. + if (!canBreak[index]) { + return; + } + + for (int i = index; i < len; i++) { + // 注意这些索引的取值。左字符串的长度从0到len + String left = s.substring(index, i + 1); + if (!dict.contains(left)) { + // 如果左字符串不在字典中,不需要继续递归 + continue; + } + + // if can't find any solution, return false, other set it + // to be true; + path.add(left); + dfs4(s, dict, path, ret, i + 1, canBreak); path.remove(path.size() - 1); } + } } \ No newline at end of file From 2aba62d7642a5530e257c9cd8924ce39695b4d99 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 21 Oct 2014 03:16:51 -0700 Subject: [PATCH 164/319] dp --- dp/WordBreak2.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dp/WordBreak2.java b/dp/WordBreak2.java index 9113c44..7827857 100644 --- a/dp/WordBreak2.java +++ b/dp/WordBreak2.java @@ -54,13 +54,15 @@ public static void main(String[] strs) { System.out .println("Computing time with DFS3: " + timer3.elapsedTime() + " millisec."); + + Algorithms.permutation.Stopwatch timer4 = new Algorithms.permutation.Stopwatch(); // DP + DFS wordBreak4(s, dict); System.out .println("Computing time with DFS4: " - + timer3.elapsedTime() + " millisec."); + + timer4.elapsedTime() + " millisec."); //System.out.println(list.toString()); } From f855c8128e58aa75a0dc86af770fdb3c3bd7db40 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 21 Oct 2014 03:18:03 -0700 Subject: [PATCH 165/319] dp --- dp/WordBreak2.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dp/WordBreak2.java b/dp/WordBreak2.java index 7827857..93e2ca8 100644 --- a/dp/WordBreak2.java +++ b/dp/WordBreak2.java @@ -287,7 +287,7 @@ public static void dfs3(String s, Set dict, } /* - // 解法4:先用DP来求解,然后再做 + // 解法4:先用DP来求解某些字段是否能word break,然后再做 */ // 我们用DFS来解决这个问题吧 public static List wordBreak4(String s, Set dict) { @@ -320,7 +320,6 @@ public static List wordBreak4(String s, Set dict) { return ret; } - // 我们用DFS模板来解决这个问题吧 public static void dfs4(String s, Set dict, List path, List ret, int index, boolean canBreak[]) { From 399814b7fe42e82ddb37ef659c51de4eaaaf343f Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 21 Oct 2014 03:59:20 -0700 Subject: [PATCH 166/319] linkedlist --- dp/WordBreak2.java | 1 - tree/Connect.java | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 tree/Connect.java diff --git a/dp/WordBreak2.java b/dp/WordBreak2.java index 93e2ca8..0bfa79a 100644 --- a/dp/WordBreak2.java +++ b/dp/WordBreak2.java @@ -289,7 +289,6 @@ public static void dfs3(String s, Set dict, /* // 解法4:先用DP来求解某些字段是否能word break,然后再做 */ - // 我们用DFS来解决这个问题吧 public static List wordBreak4(String s, Set dict) { if (s == null || s.length() == 0 || dict == null) { return null; diff --git a/tree/Connect.java b/tree/Connect.java new file mode 100644 index 0000000..11442b5 --- /dev/null +++ b/tree/Connect.java @@ -0,0 +1,49 @@ +package Algorithms.tree; + +import java.util.LinkedList; +import java.util.Queue; + +/** + * Definition for binary tree with next pointer. + * public class TreeLinkNode { + * int val; + * TreeLinkNode left, right, next; + * TreeLinkNode(int x) { val = x; } + * } + */ +public class Connect { + public void connect(TreeLinkNode root) { + if (root == null) { + return; + } + + TreeLinkNode dummy = new TreeLinkNode(0); + Queue q = new LinkedList(); + q.offer(root); + q.offer(dummy); + + while (!q.isEmpty()) { + TreeLinkNode cur = q.poll(); + if (cur == dummy) { + if (!q.isEmpty()) { + q.offer(dummy); + } + continue; + } + + if (q.peek() == dummy) { + cur.next = null; + } else { + cur.next = q.peek(); + } + + if (cur.left != null) { + q.offer(cur.left); + } + + if (cur.right != null) { + q.offer(cur.right); + } + } + } +} From c4b1aecbc6b185a5fcce4b477f4ab248279a2fae Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 21 Oct 2014 04:13:05 -0700 Subject: [PATCH 167/319] connect --- tree/Connect.java | 31 ++++++++++++++++++++++++++++++- tree/Connect2.java | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 tree/Connect2.java diff --git a/tree/Connect.java b/tree/Connect.java index 11442b5..be1b8b5 100644 --- a/tree/Connect.java +++ b/tree/Connect.java @@ -12,7 +12,10 @@ * } */ public class Connect { - public void connect(TreeLinkNode root) { + /* + * 使用level traversal来做。 + * */ + public void connect1(TreeLinkNode root) { if (root == null) { return; } @@ -46,4 +49,30 @@ public void connect(TreeLinkNode root) { } } } + + /* 试一下 recursion */ + public void connect(TreeLinkNode root) { + if (root == null) { + return; + } + + rec(root); + } + + public void rec(TreeLinkNode root) { + if (root == null) { + return; + } + + if (root.left != null) { + root.left.next = root.right; + } + + if (root.right != null) { + root.right.next = root.next.left; + } + + rec(root.left); + rec(root.right); + } } diff --git a/tree/Connect2.java b/tree/Connect2.java new file mode 100644 index 0000000..6326038 --- /dev/null +++ b/tree/Connect2.java @@ -0,0 +1,43 @@ +package Algorithms.tree; + +import java.util.LinkedList; +import java.util.Queue; + +public class Connect2 { + public void connect(TreeLinkNode root) { + if (root == null) { + return; + } + + TreeLinkNode dummy = new TreeLinkNode(0); + Queue q = new LinkedList(); + + q.offer(root); + q.offer(dummy); + + while(!q.isEmpty()) { + TreeLinkNode cur = q.poll(); + if (cur == dummy) { + if (!q.isEmpty()) { + q.offer(dummy); + } + continue; + } + + if (q.peek() == dummy) { + cur.next = null; + } else { + cur.next = q.peek(); + } + + if (cur.left != null) { + q.offer(cur.left); + } + + if (cur.right != null) { + q.offer(cur.right); + } + } + + } +} From 6ea2b17c1db9a16570256718b83a24da3506201f Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 22 Oct 2014 01:49:42 -0700 Subject: [PATCH 168/319] connect --- tree/Connect2.java | 108 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/tree/Connect2.java b/tree/Connect2.java index 6326038..fbc4f93 100644 --- a/tree/Connect2.java +++ b/tree/Connect2.java @@ -3,8 +3,19 @@ import java.util.LinkedList; import java.util.Queue; +/** + * Definition for binary tree with next pointer. + * public class TreeLinkNode { + * int val; + * TreeLinkNode left, right, next; + * TreeLinkNode(int x) { val = x; } + * } + */ public class Connect2 { - public void connect(TreeLinkNode root) { + /* + Solution 1: space: O(N), the nodes of the last level. + */ + public void connect1(TreeLinkNode root) { if (root == null) { return; } @@ -38,6 +49,101 @@ public void connect(TreeLinkNode root) { q.offer(cur.right); } } + } + + /* + Solution 2: recursion with O(h) space. H: the height of the tree. + */ + public void connect2(TreeLinkNode root) { + if (root == null) { + return; + } + TreeLinkNode cur = root.next; + TreeLinkNode next = null; + // this is very important. should exit after found the next. + while (cur != null && next == null) { + if (cur.left != null) { + next = cur.left; + } else if (cur.right != null) { + next = cur.right; + } else { + cur = cur.next; + } + } + + if (root.right != null) { + root.right.next = next; + next = root.right; + } + + if (root.left != null) { + root.left.next = next; + } + + // The order is very important. We should deal with right first! + connect2(root.right); + connect2(root.left); + } + + /* + Solution 3: iterator with O(1) space. + */ + public void connect(TreeLinkNode root) { + if (root == null) { + return; + } + + connIterator(root); + } + + /* + This is a iterator version. + */ + public void connIterator(TreeLinkNode root) { + TreeLinkNode leftEnd = root; + while (leftEnd != null) { + TreeLinkNode p = leftEnd; + + // Connect all the nodes in the next level together. + while (p != null) { + + // find the + TreeLinkNode next = findLeftEnd(p.next); + + if (p.right != null) { + p.right.next = next; + next = p.right; + } + + if (p.left != null) { + p.left.next = next; + } + + // continue to deal with the next point. + p = p.next; + } + + // Find the left end of the NEXT LEVEL. + leftEnd = findLeftEnd(leftEnd); + } + + } + + // Find out the left end of the next level of Root TreeNode. + public TreeLinkNode findLeftEnd(TreeLinkNode root) { + while (root != null) { + if (root.left != null) { + return root.left; + } + + if (root.right != null) { + return root.right; + } + + root = root.next; + } + + return null; } } From 87c647d3f51e07d51a88867251b518f8f2c87c97 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 22 Oct 2014 05:47:04 -0700 Subject: [PATCH 169/319] graph --- array/MaxProduct.java | 33 ++++++++++++++-------- bfs/CloneGraph.java | 65 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 bfs/CloneGraph.java diff --git a/array/MaxProduct.java b/array/MaxProduct.java index fc6401f..55bf0e4 100644 --- a/array/MaxProduct.java +++ b/array/MaxProduct.java @@ -2,20 +2,29 @@ public class MaxProduct { public static int maxProduct(int[] A) { - int max = 0; - - int len = A.length; + if (A == null || A.length == 0) { + return 0; + } + + // record the max value in the last node. + int DMax = A[0]; + + // record the min value in the last node. + int DMin = A[0]; - int product = 1; + // This is very important, should recode the A[0] as the initial value. + int max = A[0]; - for (int i = 0; i < len; i++) { - if (A[i] <= 0) { - max = Math.max(max, product); - product = 1; - continue; - } - - product *= A[i]; + for (int i = 1; i < A.length; i++) { + int n1 = DMax * A[i]; + int n2 = DMin * A[i]; + + // we can select the former nodes, or just discade them. + DMax = Math.max(A[i], Math.max(n1, n2)); + max = Math.max(max, DMax); + + // we can select the former nodes, or just discade them. + DMin = Math.min(A[i], Math.min(n1, n2)); } return max; diff --git a/bfs/CloneGraph.java b/bfs/CloneGraph.java new file mode 100644 index 0000000..abd6d17 --- /dev/null +++ b/bfs/CloneGraph.java @@ -0,0 +1,65 @@ +package Algorithms.bfs; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +public class CloneGraph { + class UndirectedGraphNode { + int label; + List neighbors; + + UndirectedGraphNode(int x) { + label = x; + neighbors = new ArrayList(); + } + }; + + public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { + if (node == null) { + return null; + } + + HashMap map = + new HashMap(); + + Queue q = new LinkedList(); + Queue qCopy = new LinkedList(); + + q.offer(node); + UndirectedGraphNode rootCopy = new UndirectedGraphNode(node.label); + qCopy.offer(rootCopy); + + // BFS the graph. + while (!q.isEmpty()) { + UndirectedGraphNode cur = q.poll(); + UndirectedGraphNode curCopy = qCopy.poll(); + + // bfs all the childern node. + for (UndirectedGraphNode child : cur.neighbors) { + // the node has already been copied. Just connect it and don't + // need to copy. + if (map.containsKey(child)) { + curCopy.neighbors.add(map.get(child)); + continue; + } + + // put all the children into the queue. + q.offer(child); + + // create a new child and add it to the parent. + UndirectedGraphNode childCopy = new UndirectedGraphNode( + child.label); + + curCopy.neighbors.add(childCopy); + qCopy.offer(childCopy); + + map.put(child, childCopy); + } + } + + return rootCopy; + } +} From 3e0ebca32c6cbf5a0adafbfc9de9b2948c9a5c5e Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 23 Oct 2014 03:36:33 -0700 Subject: [PATCH 170/319] spiral --- algorithm/dp/FindLargeCommonLine.java | 70 ++++++++++ array/SpiralOrder.java | 184 ++++++++++++++++++++++++++ 2 files changed, 254 insertions(+) create mode 100644 algorithm/dp/FindLargeCommonLine.java create mode 100644 array/SpiralOrder.java diff --git a/algorithm/dp/FindLargeCommonLine.java b/algorithm/dp/FindLargeCommonLine.java new file mode 100644 index 0000000..32b0474 --- /dev/null +++ b/algorithm/dp/FindLargeCommonLine.java @@ -0,0 +1,70 @@ +package Algorithms.algorithm.dp; + +import java.util.ArrayList; + +public class FindLargeCommonLine { + public static void main(String[] str) { + int[][] input = { + {0, 1}, + {1, 0} + }; + + System.out.println(find(input)); + } + + public static class DpType { + ArrayList set0; + ArrayList set1; + int max0; + int max1; + + public DpType(int max0, int max1) { + super(); + this.set0 = new ArrayList(); + this.set1 = new ArrayList(); + this.max0 = max0; + this.max1 = max1; + } + } + + public static int find(int[][] input) { + if (input == null || input.length == 0 || input[0].length == 0) { + return 0; + } + + int rows = input.length; + int cols = input[0].length; + + // create a DP + int[] max1 = new int[cols]; + int[] max0 = new int[cols]; + + // initate to be one, means the first line. + int maxLine1 = 1; + int maxLine0 = 1; + + for (int i = 0; i < cols; i++) { + if (input[0][i] == 0) { + // no change. + max0[i] = 0; + + // should reverse. + max1[i] = 1; + } else { + max0[i] = 1; + max1[i] = 0; + } + } + + // Dp from the 2nd line to the last. + for (int i = 1; i < rows; i++) { + boolean is0 = true; + for (int j = 0; j < cols; j++) { + //if (input[]) + } + } + + return 0; + } + +} diff --git a/array/SpiralOrder.java b/array/SpiralOrder.java new file mode 100644 index 0000000..7ac977a --- /dev/null +++ b/array/SpiralOrder.java @@ -0,0 +1,184 @@ +package Algorithms.array; + +import java.util.ArrayList; +import java.util.List; + +public class SpiralOrder { + public static void main(String[] strs) { + int[][] matrix = { + {1, 2}, + {3, 4} + }; + spiralOrder(matrix); + } + + public List spiralOrder1(int[][] matrix) { + List ret = new ArrayList(); + if (matrix == null || matrix.length == 0 + || matrix[0].length == 0) { + return ret; + } + + rec(matrix, 0, 0, matrix.length, matrix[0].length, ret); + + return ret; + } + + public static void rec(int[][] matrix, int x, int y, int rows, int cols, List ret) { + if (rows <= 0 || cols <= 0) { + return; + } + + // first line + for (int i = 0; i < cols; i++) { + ret.add(matrix[x][y + i]); + } + + // right column + for (int i = 1; i < rows - 1; i++) { + ret.add(matrix[x + i][y + cols - 1]); + } + + // down row + if (rows > 1) { + for (int i = cols - 1; i >= 0; i--) { + ret.add(matrix[x + rows - 1][y + i]); + } + } + + // left column. GO UP. + if (cols > 1) { + for (int i = rows - 2; i > 0; i--) { + ret.add(matrix[x + i][y]); + } + } + + rec (matrix, x + 1, y + 1, rows - 2, cols - 2, ret); + } + + /* + Solution 2: + REF: http://blog.csdn.net/fightforyourdream/article/details/16876107?reload + 此算法比较不容易算错 + */ + public List spiralOrder2(int[][] matrix) { + List ret = new ArrayList(); + if (matrix == null || matrix.length == 0 + || matrix[0].length == 0) { + return ret; + } + + int x1 = 0; + int y1 = 0; + + int rows = matrix.length; + int cols = matrix[0].length; + + while (rows >= 1 && cols >= 1) { + // Record the right down corner of the matrix. + int x2 = x1 + rows - 1; + int y2 = y1 + cols - 1; + + // go through the WHOLE first line. + for (int i = y1; i <= y2; i++) { + ret.add(matrix[x1][i]); + } + + // go through the right column. + for (int i = x1 + 1; i < x2; i++) { + ret.add(matrix[i][y2]); + } + + // go through the WHOLE last row. + if (rows > 1) { + for (int i = y2; i >= y1; i--) { + ret.add(matrix[x2][i]); + } + } + + // the left column. + if (cols > 1) { + for (int i = x2 - 1; i > x1; i--) { + ret.add(matrix[i][y1]); + } + } + + // in one loop we deal with 2 rows and 2 cols. + rows -= 2; + cols -= 2; + x1++; + y1++; + } + + return ret; + } + + /* + Solution 3: + 使用方向矩阵来求解 + */ + public static List spiralOrder(int[][] matrix) { + List ret = new ArrayList(); + if (matrix == null || matrix.length == 0 + || matrix[0].length == 0) { + return ret; + } + + int rows = matrix.length; + int cols = matrix[0].length; + + int visitedRows = 0; + int visitedCols = 0; + + // indicate the direction of x + + // 1: means we are visiting the row by the right direction. + // -1: means we are visiting the row by the left direction. + int[] x = {1, 0, -1, 0}; + + // 1: means we are visiting the colum by the down direction. + // -1: means we are visiting the colum by the up direction. + int[] y = {0, 1, 0, -1}; + + // 0: right, 1: down, 2: left, 3: up. + int direct = 0; + + int startx = 0; + int starty = 0; + + int candidateNum = 0; + int step = 0; + while (true) { + if (x[direct] == 0) { + // visit Y axis. + candidateNum = rows - visitedRows; + } else { + // visit X axis + candidateNum = cols - visitedCols; + } + + if (candidateNum <= 0) { + break; + } + + ret.add(matrix[startx][starty]); + step++; + + if (step == candidateNum) { + step = 0; + visitedRows += x[direct] == 0 ? 0: 1; + visitedCols += y[direct] == 0 ? 0: 1; + + // move forward the direction. + direct ++; + direct = direct%4; + } + + // 根据方向来移动横坐标和纵坐标。 + startx += y[direct]; + starty += x[direct]; + } + + return ret; + } +} From 926f8dc30a265fa3c91c8f044fe5c0912e3030f5 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 23 Oct 2014 18:42:20 -0700 Subject: [PATCH 171/319] SetZeroes --- array/SetZeroes.java | 80 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 array/SetZeroes.java diff --git a/array/SetZeroes.java b/array/SetZeroes.java new file mode 100644 index 0000000..61fb9f8 --- /dev/null +++ b/array/SetZeroes.java @@ -0,0 +1,80 @@ +package Algorithms.array; + +public class SetZeroes { + public static void main(String[] strs) { + int[][] matrix = { + {0,0,0,5},{4,3,1,4},{0,1,1,4},{1,2,1,3},{0,0,1,1} + }; + + setZeroes(matrix); + } + + public static void setZeroes(int[][] matrix) { + if (matrix == null || matrix.length == 0 + || matrix[0].length == 0) { + return; + } + + boolean row1Zero = false; + boolean col1Zero = false; + + int rows = matrix.length; + int cols = matrix[0].length; + + // Determine if the first column should be Zero. + for (int i = 0; i < rows; i++) { + if (matrix[i][0] == 0) { + col1Zero = true; + break; + } + } + + // Determine if the first row should be Zero. + for (int i = 0; i < cols; i++) { + if (matrix[0][i] == 0) { + row1Zero = true; + break; + } + } + + // we use the first row and the first col as the flag to record the + // cells whether or not set to 0. + for (int i = 1; i < rows; i++) { + for (int j = 1; j < cols; j++) { + // 注意了,这个矩阵是0和非0,并不是0和1. + if (matrix[i][j] == 0) { + // set the flag in the first line and the first column + matrix[i][0] = 0; + matrix[0][j] = 0; + } + } + } + + // set the inner cells. + // Be careful: i, j start from 1. + for (int i = 1; i < rows; i++) { + for (int j = 1; j < cols; j++) { + if (matrix[i][0] == 0 + || matrix[0][j] == 0) { + matrix[i][j] = 0; + } + } + } + + // set the first row. + if (row1Zero) { + for (int i = 0; i < cols; i++) { + matrix[0][i] = 0; + } + } + + // set the first col. + if (col1Zero) { + for (int i = 0; i < rows; i++) { + matrix[i][0] = 0; + } + } + + return; + } +} From d64af4e0b9bdf55a8d12e1f1c0fc50d10daaf384 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 23 Oct 2014 20:05:02 -0700 Subject: [PATCH 172/319] GenerateMatrix1 --- array/GenerateMatrix1.java | 166 +++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 array/GenerateMatrix1.java diff --git a/array/GenerateMatrix1.java b/array/GenerateMatrix1.java new file mode 100644 index 0000000..7f0fc78 --- /dev/null +++ b/array/GenerateMatrix1.java @@ -0,0 +1,166 @@ +package Algorithms.array; + +public class GenerateMatrix1 { + public int[][] generateMatrix1(int n) { + int[][] ret = new int[n][n]; + + if (n == 0) { + // return a [] not a NULL. + return ret; + } + + int number = 0; + int rows = n; + + int x1 = 0; + int y1 = 0; + + while (rows > 0) { + int x2 = x1 + rows - 1; + int y2 = y1 + rows - 1; + + // the Whole first row. + for (int i = y1; i <= y2; i++) { + number++; + ret[x1][i] = number; + } + + // the right column except the first and last line. + for (int i = x1 + 1; i < x2; i++) { + number++; + ret[i][y2] = number; + } + + // This line is very important. + if (rows <= 1) { + break; + } + + // the WHOLE last row. + for (int i = y2; i >= y1; i--) { + number++; + ret[x2][i] = number; + } + + // the left column. column keep stable + // x: x2-1 --> x1 + 1 + for (int i = x2 - 1; i > x1; i--) { + number++; + ret[i][y1] = number; + } + + // remember this. + rows -= 2; + x1++; + y1++; + } + + return ret; + } + + /* + Solution 2: use direction. + */ + public int[][] generateMatrix2(int n) { + int[][] ret = new int[n][n]; + if (n == 0) { + return ret; + } + + int[] x = {1, 0, -1, 0}; + int[] y = {0, 1, 0, -1}; + + int num = 0; + + int step = 0; + int candElements = 0; + + int visitedRows = 0; + int visitedCols = 0; + + // 0: right, 1: down, 2: left, 3: up. + int direct = 0; + + int startx = 0; + int starty = 0; + + while (true) { + if (x[direct] == 0) { + // visit the Y axis + candElements = n - visitedRows; + } else { + // visit the X axis + candElements = n - visitedCols; + } + + if (candElements <= 0) { + break; + } + + // set the cell. + ret[startx][starty] = ++num; + step++; + + // change the direction. + if (step == candElements) { + step = 0; + visitedRows += x[direct] == 0 ? 0: 1; + visitedCols += y[direct] == 0 ? 0: 1; + + // change the direction. + direct = (direct + 1) % 4; + } + + startx += y[direct]; + starty += x[direct]; + } + + return ret; + } + + /* + Solution 3: 使用四条bound来限制的方法. + */ + public int[][] generateMatrix(int n) { + int[][] ret = new int[n][n]; + if (n == 0) { + return ret; + } + + int top = 0, bottom = n - 1, left = 0, right = n - 1; + int num = 1; + while (top <= bottom) { + if (top == bottom) { + ret[top][top] = num++; + break; + } + + // first line. + for (int i = left; i < right; i++) { + ret[top][i] = num++; + } + + // right line; + for (int i = top; i < bottom; i++) { + ret[i][right] = num++; + } + + // bottom line; + for (int i = right; i > left; i--) { + ret[bottom][i] = num++; + } + + // left line; + for (int i = bottom; i > top; i--) { + ret[i][left] = num++; + } + + top++; + bottom--; + left++; + right--; + } + + return ret; + } +} \ No newline at end of file From 6486347b965279f1d65ba1da247f3cff494664e1 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 24 Oct 2014 00:11:39 -0700 Subject: [PATCH 173/319] bs --- binarySearch/SearchRange.java | 71 +++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 binarySearch/SearchRange.java diff --git a/binarySearch/SearchRange.java b/binarySearch/SearchRange.java new file mode 100644 index 0000000..84770f6 --- /dev/null +++ b/binarySearch/SearchRange.java @@ -0,0 +1,71 @@ +package Algorithms.binarySearch; + +public class SearchRange { + public static void main(String[] strs) { + int[] A = {1}; + + System.out.println(searchRange(A, 0)[0] + " " + searchRange(A, 0)[1]); + } + + public static int[] searchRange(int[] A, int target) { + int[] ret = {-1, -1}; + + if (A == null || A.length == 0) { + return ret; + } + + int len = A.length; + int left = 0; + int right = len - 1; + + // so when loop end, there will be 2 elements in the array. + // search the left bound. + while (left < right - 1) { + int mid = left + (right - left) / 2; + if (target == A[mid]) { + // 如果相等,继续往左寻找边界 + right = mid; + } else if (target > A[mid]) { + // move right; + left = mid; + } else { + right = mid; + } + } + + if (A[left] == target) { + ret[0] = left; + } else if (A[right] == target) { + ret[0] = right; + } else { + return ret; + } + + left = 0; + right = len - 1; + // so when loop end, there will be 2 elements in the array. + // search the right bound. + while (left < right - 1) { + int mid = left + (right - left) / 2; + if (target == A[mid]) { + // 如果相等,继续往右寻找右边界 + left = mid; + } else if (target > A[mid]) { + // move right; + left = mid; + } else { + right = mid; + } + } + + if (A[right] == target) { + ret[1] = right; + } else if (A[left] == target) { + ret[1] = left; + } else { + return ret; + } + + return ret; + } +} From eeaf7d092e38f9794a7ba2b13b06d2389216c09c Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 24 Oct 2014 01:37:40 -0700 Subject: [PATCH 174/319] sort --- sort/SortColors.java | 69 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 sort/SortColors.java diff --git a/sort/SortColors.java b/sort/SortColors.java new file mode 100644 index 0000000..572c352 --- /dev/null +++ b/sort/SortColors.java @@ -0,0 +1,69 @@ +package Algorithms.sort; + +public class SortColors { + public void sortColors(int[] A) { + if (A == null || A.length == 0) { + return; + } + + int len = A.length; + + int red = 0; + int white = 0; + + for (int i = 0; i < len; i++) { + if (A[i] == 0) { + red++; + } else if (A[i] == 1) { + white++; + } + } + + for (int i = 0; i < len; i++) { + if (red > 0) { + A[i] = 0; + red--; + } else if (white > 0) { + A[i] = 1; + white--; + } else { + A[i] = 2; + } + } + } + + public void sortColors2(int[] A) { + if (A == null || A.length == 0) { + return; + } + + int len = A.length - 1; + int left = 0; + int right = len; + + int cur = 0; + while (cur <= right) { + if (A[cur] == 2) { + // 换到右边,换过来的有可能是0,也有可能是1,所以cur要停留 + + swap(A, cur, right); + right--; + } else if (A[cur] == 0) { + // 从左边换过来的只可能是1,所以可以直接cur++ + // 因为所有的2全部换到右边去了。 + + swap(A, cur, left); + left++; + cur++; + } else { + cur++; + } + } + } + + public void swap(int[] A, int n1, int n2) { + int tmp = A[n1]; + A[n1] = A[n2]; + A[n2] = tmp; + } +} \ No newline at end of file From 2198d4ef43f86cf8a17295ccd674f3a69df294f6 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 24 Oct 2014 03:06:54 -0700 Subject: [PATCH 175/319] candy --- dp/Candy.java | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/dp/Candy.java b/dp/Candy.java index 0f0a40d..cd5b98b 100644 --- a/dp/Candy.java +++ b/dp/Candy.java @@ -6,29 +6,26 @@ public int candy(int[] ratings) { return 0; } + int len = ratings.length; - int[] candys = new int[len]; + int[] num = new int[len]; - // go from the left side to the right side and give them candys. - candys[0] = 1; - for (int i = 1; i < len; i++) { - if (ratings[i] > ratings[i - 1]) { - candys[i] = candys[i - 1] + 1; + // go from left to right; + for (int i = 0; i < len; i++) { + if (i > 0 && ratings[i] > ratings[i - 1]) { + num[i] = num[i - 1] + 1; } else { - candys[i] = 1; - } - } - - for (int i = len - 2; i >= 0; i--) { - if (ratings[i] > ratings[i + 1]) { - int num = candys[i + 1] + 1; - candys[i] = Math.max(candys[i], num); + num[i] = 1; } } + // go from right to left; int sum = 0; - for (int i: candys) { - sum += i; + for (int i = len - 1; i >= 0; i--) { + if (i < len - 1 && ratings[i] > ratings[i + 1]) { + num[i] = Math.max(num[i], num[i + 1] + 1); + } + sum += num[i]; } return sum; From 22cbf1a20d147cda2dbcd26f77b7c450ece41042 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 24 Oct 2014 04:33:12 -0700 Subject: [PATCH 176/319] find --- binarySearch/FindMin.java | 39 ++++++++++++++++++++++++++- binarySearch/FindMin2.java | 55 ++++++++++++++++++++++++++++++++++++++ dp/Candy.java | 1 + 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 binarySearch/FindMin2.java diff --git a/binarySearch/FindMin.java b/binarySearch/FindMin.java index 1da2520..8855696 100644 --- a/binarySearch/FindMin.java +++ b/binarySearch/FindMin.java @@ -1,6 +1,8 @@ package Algorithms.binarySearch; + public class FindMin { - public int findMin(int[] num) { + // Solution 1: + public int findMin1(int[] num) { if (num == null || num.length == 0) { return 0; } @@ -38,4 +40,39 @@ public int findMin(int[] num) { return 0; } + + // solution 2: + public int findMin(int[] A) { + if (A == null || A.length == 0) { + return 0; + } + + if (A.length == 1) { + return A[0]; + } else if (A.length == 2) { + return Math.min(A[0], A[1]); + } + + // 至少有3个元素,才有讨论的价值 + int l = 0; + int r = A.length - 1; + + while (l < r - 1) { + int m = l + (r - l) / 2; + + // means that there is no rotate. + if (A[r] > A[l]) { + return A[0]; + } + + // left side is sorted. + if (A[m] > A[l]) { + l = m; + } else { + r = m; + } + } + + return A[r]; + } } \ No newline at end of file diff --git a/binarySearch/FindMin2.java b/binarySearch/FindMin2.java new file mode 100644 index 0000000..d521f00 --- /dev/null +++ b/binarySearch/FindMin2.java @@ -0,0 +1,55 @@ +package Algorithms.binarySearch; + + +/* + * Find Minimum in Rotated Sorted Array II Total Accepted: 2541 Total Submissions: 9558 My Submissions Question Solution +Follow up for "Find Minimum in Rotated Sorted Array": +What if duplicates are allowed? + +Would this affect the run-time complexity? How and why? +Suppose a sorted array is rotated at some pivot unknown to you beforehand. + +(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). + +Find the minimum element. + +The array may contain duplicates. + * */ +public class FindMin2 { + public int findMin(int[] num) { + if (num == null || num.length == 0) { + return 0; + } + + int len = num.length; + if (len == 1) { + return num[0]; + } else if (len == 2) { + return Math.min(num[0], num[1]); + } + + int left = 0; + int right = len - 1; + + while (left < right - 1) { + int mid = left + (right - left) / 2; + // In this case, the array is sorted. + // 这一句很重要,因为我们移除一些元素后,可能会使整个数组变得有序... + if (num[left] < num[right]) { + return num[left]; + } + + // left side is sorted. CUT the left side. + if (num[mid] > num[left]) { + left = mid; + // left side is unsorted, right side is sorted. CUT the right side. + } else if (num[mid] < num[left]) { + right = mid; + } else { + left++; + } + } + + return Math.min(num[left], num[right]); + } +} diff --git a/dp/Candy.java b/dp/Candy.java index cd5b98b..443423f 100644 --- a/dp/Candy.java +++ b/dp/Candy.java @@ -31,3 +31,4 @@ public int candy(int[] ratings) { return sum; } } + From c874e3ef8b63cf127f84cbe302f47c0e8521ec05 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 24 Oct 2014 05:11:57 -0700 Subject: [PATCH 177/319] divide --- binarySearch/Divide.java | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 binarySearch/Divide.java diff --git a/binarySearch/Divide.java b/binarySearch/Divide.java new file mode 100644 index 0000000..4b9bd33 --- /dev/null +++ b/binarySearch/Divide.java @@ -0,0 +1,24 @@ +package Algorithms.binarySearch; + +public class Divide { + public int divide(int dividend, int divisor) { + long a = Math.abs((long)dividend); + + // ref : http://blog.csdn.net/kenden23/article/details/16986763 + // Note: 在这里必须先取long再abs,否则int的最小值abs后也是原值 + long b = Math.abs((long)divisor); + + int ret = 0; + // 这里必须是= 因为相等时也可以减 + while (a >= b) { + // 判断条件是 >= + for (long deduce = b, cnt = 1; a >= deduce; deduce <<= 1, cnt <<= 1) { + a -= deduce; + ret += cnt; + } + } + + // 获取符号位。根据除数跟被除数的关系来定 + return (dividend > 0) ^ (divisor > 0) ? -ret: ret; + } +} \ No newline at end of file From 46ee550ebd0a528b3dfb122dfff0c6b244af5565 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 25 Oct 2014 06:05:13 -0700 Subject: [PATCH 178/319] rotate --- array/Rotate.java | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 array/Rotate.java diff --git a/array/Rotate.java b/array/Rotate.java new file mode 100644 index 0000000..1df4899 --- /dev/null +++ b/array/Rotate.java @@ -0,0 +1,38 @@ +package Algorithms.array; + +public class Rotate { + public void rotate(int[][] matrix) { + if (matrix == null || matrix.length == 0 + || matrix[0].length == 0) { + return; + } + + int n = matrix.length; + int top = 0, down = n - 1, left = 0, right = n - 1; + + while (n > 1) { + for (int i = 0; i < n - 1; i++) { + int tmp = matrix[top][left + i]; + // 另上边等于左边 + matrix[top][left + i] = matrix[down - i][left]; + + // 另左边等于下边 + matrix[down - i][left] = matrix[down][right - i]; + + // 另下边等于右边 + matrix[down][right - i] = matrix[top + i][right]; + + // 另右边等于上边 + matrix[top + i][right] = tmp; + } + top++; + right--; + left++; + down--; + + n -= 2; + } + + return; + } +} \ No newline at end of file From f9435b5223496502bbd8c76b052ecee4ccdacf21 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 25 Oct 2014 20:13:44 -0700 Subject: [PATCH 179/319] long --- hash/LongestConsecutive.java | 57 ++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 hash/LongestConsecutive.java diff --git a/hash/LongestConsecutive.java b/hash/LongestConsecutive.java new file mode 100644 index 0000000..fae1679 --- /dev/null +++ b/hash/LongestConsecutive.java @@ -0,0 +1,57 @@ +package Algorithms.hash; + +import java.util.HashMap; + +public class LongestConsecutive { + public int longestConsecutive(int[] num) { + if (num == null) { + return 0; + } + + HashMap map = new HashMap(); + + int max = 0; + + int len = num.length; + for (int i = 0; i < len ; i++) { + // 寻找以num[i] 起头或是结尾的,如果找到,则可以跳过,因为我们 + // 不需要重复的数字 + if (map.get(num[i]) != null) { + continue; + } + + int left = num[i]; + int right = num[i]; + + // 寻找左边界 + Integer board = map.get(num[i] - 1); + if (board != null && board < left) { + // 更新左边界 + left = board; + + // 删除左边2个集合 + map.remove(left); + map.remove(num[i] - 1); + } + + // 寻找右边界 + board = map.get(num[i] + 1); + if (board != null && board > right) { + // 更新右边界 + right = board; + + // 删除右边2个集合 + map.remove(right); + map.remove(num[i] + 1); + } + + // 创建新的合并之后的集合 + map.put(left, right); + map.put(right, left); + + max = Math.max(max, right - left + 1); + } + + return max; + } +} From 45b9d4d53b6ad6f10547893717fce5d637fc7b8f Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 26 Oct 2014 05:36:37 -0700 Subject: [PATCH 180/319] merge --- array/Interval.java | 16 ++++++++++ array/Merge.java | 57 ++++++++++++++++++++++++++++++++++++ hash/LongestConsecutive.java | 40 ++++++++++++++++++++++++- 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 array/Interval.java create mode 100644 array/Merge.java diff --git a/array/Interval.java b/array/Interval.java new file mode 100644 index 0000000..f288682 --- /dev/null +++ b/array/Interval.java @@ -0,0 +1,16 @@ +package Algorithms.array; + +public class Interval { + int start; + int end; + + Interval() { + start = 0; + end = 0; + } + + Interval(int s, int e) { + start = s; + end = e; + } +} diff --git a/array/Merge.java b/array/Merge.java new file mode 100644 index 0000000..3720883 --- /dev/null +++ b/array/Merge.java @@ -0,0 +1,57 @@ +package Algorithms.array; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +/** + * Definition for an interval. + * public class Interval { + * int start; + * int end; + * Interval() { start = 0; end = 0; } + * Interval(int s, int e) { start = s; end = e; } + * } + */ +public class Merge { + public List merge(List intervals) { + List ret = new ArrayList(); + if (intervals == null || intervals.size() == 0) { + return ret; + } + + Collections.sort(intervals, new Comparator() { + public int compare(Interval o1, Interval o2) { + // sort the intervals by the start. + return o1.start - o2.start; + } + }); + + // 作为最后一个插入的区间 + Interval last = intervals.get(0); + + // 这里要考虑性能。使用iterator的话,对linkedlist会更快. + Iterator itor = intervals.iterator(); + while (itor.hasNext()) { + Interval cur = itor.next(); + // cur 在last的右边 + if (cur.start > last.end) { + // 将cur作为新的last. + ret.add(last); + last = cur; + // cur与last有重合的部分,合并之 + } else { + int s = last.start; + int e = Math.max(last.end, cur.end); + last = new Interval(s, e); + } + } + + // 把最后一个区间加上 + ret.add(last); + + return ret; + } +} \ No newline at end of file diff --git a/hash/LongestConsecutive.java b/hash/LongestConsecutive.java index fae1679..b624144 100644 --- a/hash/LongestConsecutive.java +++ b/hash/LongestConsecutive.java @@ -1,9 +1,11 @@ package Algorithms.hash; import java.util.HashMap; +import java.util.HashSet; public class LongestConsecutive { - public int longestConsecutive(int[] num) { + // Solution 1: use hashmap. + public int longestConsecutive1(int[] num) { if (num == null) { return 0; } @@ -54,4 +56,40 @@ public int longestConsecutive(int[] num) { return max; } + + // solution 2: use Hashset. + public int longestConsecutive(int[] num) { + if (num == null) { + return 0; + } + + HashSet set = new HashSet(); + for (int i: num) { + set.add(i); + } + + int max = 0; + for (int i: num) { + int cnt = 1; + set.remove(i); + + int tmp = i - 1; + while (set.contains(tmp)) { + set.remove(tmp); + cnt++; + tmp--; + } + + tmp = i + 1; + while (set.contains(tmp)) { + set.remove(tmp); + cnt++; + tmp++; + } + + max = Math.max(max, cnt); + } + + return max; + } } From 7fe6d0deffaf47e901cc6a37bd3ec2b0270bbf30 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 26 Oct 2014 06:33:01 -0700 Subject: [PATCH 181/319] valid --- string/IsValid.java | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 string/IsValid.java diff --git a/string/IsValid.java b/string/IsValid.java new file mode 100644 index 0000000..ec00205 --- /dev/null +++ b/string/IsValid.java @@ -0,0 +1,41 @@ +package Algorithms.string; + +import java.util.Stack; + +public class IsValid { + public boolean isValid(String s) { + if (s == null || s.length() == 0) { + return true; + } + + Stack stack = new Stack(); + int len = s.length(); + for (int i = 0; i < len; i++) { + char c = s.charAt(i); + if (stack.isEmpty()) { + // 栈为空的时候,不能放右括号 + if (c == ']' || c == ')' || c == '}') { + return false; + } + stack.push(c); + continue; + } + + // 栈不为空时,必须 要对应弹出相对应的括号 + if (c == ')' && stack.peek() == '(' + || c == ']' && stack.peek() == '[' + || c == '}' && stack.peek() == '{' + ) { + stack.pop(); + // 或者继续压入左括号 + } else if (c == '(' || c == '[' || c == '{') { + stack.push(c); + // 否则错误退出 + } else { + return false; + } + } + + return stack.isEmpty(); + } +} \ No newline at end of file From 96ee98df1ebfe778166acf8d87bcb10438fb371a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 26 Oct 2014 06:51:44 -0700 Subject: [PATCH 182/319] add --- string/AddBinary.java | 51 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 string/AddBinary.java diff --git a/string/AddBinary.java b/string/AddBinary.java new file mode 100644 index 0000000..692e7d5 --- /dev/null +++ b/string/AddBinary.java @@ -0,0 +1,51 @@ +package Algorithms.string; + +public class AddBinary { + public String addBinary(String a, String b) { + if (a == null || b == null) { + return null; + } + + if (a.length() == 0) { + return b; + } + + if (b.length() == 0) { + return a; + } + + StringBuilder sb = new StringBuilder(); + + int p1 = a.length() - 1; + int p2 = b.length() - 1; + + int carry = 0; + while (p1 >= 0 || p2 >= 0) { + int sum = carry; + if (p1 >= 0) { + sum += (a.charAt(p1) - '0'); + } + + if (p2 >= 0) { + sum += (b.charAt(p2) - '0'); + } + + char c = sum % 2 == 1 ? '1': '0'; + sb.insert(0, c); + carry = sum / 2; + + p1--; + p2--; + } + + if (carry == 1) { + sb.insert(0, '1'); + } + + return sb.toString(); + } +} + + + + \ No newline at end of file From 6ae97c9de021545373636d30d880884c670a3bca Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 28 Oct 2014 01:44:39 -0700 Subject: [PATCH 183/319] area --- twoPoints/MaxArea.java | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 twoPoints/MaxArea.java diff --git a/twoPoints/MaxArea.java b/twoPoints/MaxArea.java new file mode 100644 index 0000000..96d9a27 --- /dev/null +++ b/twoPoints/MaxArea.java @@ -0,0 +1,29 @@ +package Algorithms.twoPoints; + +public class MaxArea { + public int maxArea(int[] height) { + if (height == null) { + return 0; + } + + int left = 0; + int right = height.length - 1; + int maxArea = 0; + + while (left < right) { + int h = Math.min(height[left], height[right]); + int area = h * (right - left); + maxArea = Math.max(maxArea, area); + + if (height[left] < height[right]) { + // 如果左边界比较低,尝试向右寻找更高的边界 + left++; + } else { + // 如果右边界比较低,尝试向左寻找更高的边界 + right--; + } + } + + return maxArea; + } +} \ No newline at end of file From 9ec2375d57c0133c95753af542790a53bb2e7c5f Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 28 Oct 2014 02:25:24 -0700 Subject: [PATCH 184/319] trap --- array/Trap.java | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 array/Trap.java diff --git a/array/Trap.java b/array/Trap.java new file mode 100644 index 0000000..8ef3fb0 --- /dev/null +++ b/array/Trap.java @@ -0,0 +1,35 @@ +package Algorithms.array; + +public class Trap { + public int trap(int[] A) { + if (A == null) { + return 0; + } + + int max = 0; + + int len = A.length; + int[] left = new int[len]; + int[] right = new int[len]; + + // count the highest bar from the left to the current. + for (int i = 0; i < len; i++) { + left[i] = i == 0 ? A[i]: Math.max(left[i - 1], A[i]); + } + + // count the highest bar from right to current. + for (int i = len - 1; i >= 0; i--) { + right[i] = i == len - 1 ? A[i]: Math.max(right[i + 1], A[i]); + } + + // count the largest water which can contain. + for (int i = 0; i < len; i++) { + int height = Math.min(right[i], left[i]); + if (height > A[i]) { + max += height - A[i]; + } + } + + return max; + } +} \ No newline at end of file From 18c5b18aa35cd449f52413cf466c06748bbb61b3 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 29 Oct 2014 04:28:11 -0700 Subject: [PATCH 185/319] is number --- string/IsNumber.java | 54 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 string/IsNumber.java diff --git a/string/IsNumber.java b/string/IsNumber.java new file mode 100644 index 0000000..b8c1989 --- /dev/null +++ b/string/IsNumber.java @@ -0,0 +1,54 @@ +package Algorithms.string; + +public class IsNumber { + public boolean isNumber(String s) { + if (s == null) { + return false; + } + + // cut the leading spaces and tail spaces. + String sCut = s.trim(); + + /* + Some examples: + "0" => true + " 0.1 " => true + "abc" => false + "1 a" => false + "2e10" => true + */ + + int len = sCut.length(); + + boolean num = false; + boolean exp = false; + boolean dot = false; + + for (int i = 0; i < len; i++) { + char c = sCut.charAt(i); + if (c == 'e') { + if (!num || exp) { + return false; + } + exp = true; + num = false; // Should be: 2e2 , so there should be number follow "e" + } else if (c <= '9' && c >= '0') { + num = true; + } else if (c == '.') { + if (exp || dot) { // can't be: e0.2 can't be: .. + return false; + } + dot = true; + } else if (c == '+' || c == '-') { + if (i != 0 && sCut.charAt(i - 1) != 'e') { // filter : " 005047e+6", this is true. + return false; + } + } else { + // invalid character. + return false; + } + } + + return num; + } +} \ No newline at end of file From 78d523d5db1033a2dcee6bcdc54bc31c2784bbe1 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 1 Nov 2014 02:34:16 -0700 Subject: [PATCH 186/319] Anagrams --- hash/Anagrams.java | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 hash/Anagrams.java diff --git a/hash/Anagrams.java b/hash/Anagrams.java new file mode 100644 index 0000000..13b92d6 --- /dev/null +++ b/hash/Anagrams.java @@ -0,0 +1,52 @@ +package Algorithms.hash; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Anagrams { + public List anagrams(String[] strs) { + List ret = new ArrayList(); + + if (strs == null) { + return ret; + } + + HashMap> map = new HashMap>(); + + int len = strs.length; + for (int i = 0; i < len; i++) { + String s = strs[i]; + + // Sort the string. + char[] chars = s.toCharArray(); + Arrays.sort(chars); + String strSort = new String(chars); + + // Create a ArrayList for the sorted string. + if (!map.containsKey(strSort)) { + map.put(strSort, new ArrayList()); + } + + // Add a new string to the list of the hashmap. + map.get(strSort).add(s); + } + + // go through the map and add all the strings into the result. + for (Map.Entry> entry: map.entrySet()) { + List list = entry.getValue(); + + // skip the entries which only have one string. + if (list.size() == 1) { + continue; + } + + // add the strings into the list. + ret.addAll(list); + } + + return ret; + } +} \ No newline at end of file From f5bc05bb8f74e42de13402ef3d5d53ce05efc950 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 1 Nov 2014 04:14:15 -0700 Subject: [PATCH 187/319] valid --- hash/IsValidSudoku.java | 74 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 hash/IsValidSudoku.java diff --git a/hash/IsValidSudoku.java b/hash/IsValidSudoku.java new file mode 100644 index 0000000..0ae9fcd --- /dev/null +++ b/hash/IsValidSudoku.java @@ -0,0 +1,74 @@ +package Algorithms.hash; + +import java.util.HashSet; + +public class IsValidSudoku { + public static void main(String[] strs) { + + } + + public static boolean isValidSudoku(char[][] board) { + if (board == null || board.length != 9 || + board[0].length != 9) { + return false; + } + + HashSet set = new HashSet(); + + // check the rows. + for (int i = 0; i < 9; i++) { + // clear the set at every row. + set.clear(); + for (int j = 0; j < 9; j++) { + if (!isValidChar(board[i][j], set)) { + return false; + } + } + } + + // check the columns. + for (int i = 0; i < 9; i++) { + // clear the set at every column. + set.clear(); + for (int j = 0; j < 9; j++) { + if (!isValidChar(board[j][i], set)) { + return false; + } + } + } + + // check the blocks. + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + // clear the set at every block. + set.clear(); + for (int k = 0; k < 9; k++) { + if (!isValidChar(board[i + k / 3][j + k % 3], set)) { + return false; + } + } + } + } + + return true; + } + + public static boolean isValidChar(char c, HashSet set) { + if (c == '.') { + return true; + } + + if (c < '0' || c > '9') { + return false; + } + + // Check if the character exit in the hashset. + if (set.contains(c)) { + return false; + } + + set.add(c); + + return true; + } +} \ No newline at end of file From 2d279dcfb6d9cce74c644d711d51f06e07ecc3cc Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 1 Nov 2014 05:46:21 -0700 Subject: [PATCH 188/319] sudoku --- hash/SolveSudoku.java | 71 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 hash/SolveSudoku.java diff --git a/hash/SolveSudoku.java b/hash/SolveSudoku.java new file mode 100644 index 0000000..129bb83 --- /dev/null +++ b/hash/SolveSudoku.java @@ -0,0 +1,71 @@ +package Algorithms.hash; + +public class SolveSudoku { + public void solveSudoku(char[][] board) { + dfs(board, 0, 0); + } + + public boolean dfs(char[][] board, int x, int y) { + // go to next row. + if (y == 9) { + y = 0; + x++; + } + + // done + if (x >= 9) { + return true; + } + + // Skip the solved point. + if (board[x][y] != '.') { + return dfs(board, x, y + 1); + } + + // Go throught all the possibilities. + for (int k = 0; k < 9; k++) { + board[x][y] = (char)('1' + k); + // SHOULD RETURN HERE IF INVALID. + if (isValid(board, x, y) && dfs(board, x, y + 1)) { + return true; + } + board[x][y] = '.'; + } + + // because all the possibility is impossiable. + return false; + } + + public boolean isValid(char[][] board, int x, int y) { + // Judge the column. + for (int i = 0; i < 9; i++) { + if (i != x && board[i][y] == board[x][y]) { + return false; + } + } + + // Judge the row. + for (int i = 0; i < 9; i++) { + if (i != y && board[x][i] == board[x][y]) { + return false; + } + } + + // Judge the block. + int i = x / 3 * 3; + int j = y / 3 * 3; + for (int k = 0; k < 9; k++) { + int xIndex = i + k / 3; + int yIndex = j + k % 3; + if (xIndex == x && yIndex == y) { + continue; + } + + if (board[xIndex][yIndex] == board[x][y]) { + return false; + } + } + + return true; + } +} From d4688889fb5fd3e6108a7c486900abe70c7e9a93 Mon Sep 17 00:00:00 2001 From: Dante Fan Date: Mon, 3 Nov 2014 10:36:07 -0800 Subject: [PATCH 189/319] found a bug when I test it at line 46, if you do not times 3, some positions would never be checked while some positions were checked many times. --- hash/IsValidSudoku.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hash/IsValidSudoku.java b/hash/IsValidSudoku.java index 0ae9fcd..b296596 100644 --- a/hash/IsValidSudoku.java +++ b/hash/IsValidSudoku.java @@ -43,7 +43,7 @@ public static boolean isValidSudoku(char[][] board) { // clear the set at every block. set.clear(); for (int k = 0; k < 9; k++) { - if (!isValidChar(board[i + k / 3][j + k % 3], set)) { + if (!isValidChar(board[i*3 + k / 3][j*3 + k % 3], set)) { // here is a bug return false; } } @@ -71,4 +71,4 @@ public static boolean isValidChar(char c, HashSet set) { return true; } -} \ No newline at end of file +} From b6f4e0871705d54c97b8c7a3a85b49fb780ca7bc Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 17 Nov 2014 21:29:11 -0800 Subject: [PATCH 190/319] ismatch --- string/isMatch.java | 68 ++ tree/TreeDemo2.java | 1560 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1628 insertions(+) create mode 100644 string/isMatch.java create mode 100644 tree/TreeDemo2.java diff --git a/string/isMatch.java b/string/isMatch.java new file mode 100644 index 0000000..8d9799c --- /dev/null +++ b/string/isMatch.java @@ -0,0 +1,68 @@ +package Algorithms.string; + +public class isMatch { + public boolean isMatch(String s, String p) { + if (s == null || p == null) { + return false; + } + + return isMatchRec(s, p, 0, 0); + } + + public boolean isMatchRec(String s, String p, int indexS, int indexP) { + int lenS = s.length(); + int lenP = p.length(); + + // we get to the end of the string. + if (indexP == lenP) { + return indexS == lenS; + } + + // only 1 match character left. + if (indexP == lenP - 1) { + // String should also have 1 character left. + return indexS == lenS - 1 && isMatchChar(s.charAt(indexS), p.charAt(indexP)); + } + + // At lease 2 match character left + if (p.charAt(indexP + 1) == '*') { + // match 0; + if (isMatchRec(s, p, indexS, indexP + 2)) { + return true; + } + + // we can match 0 or more. + for (int i = indexS; i < lenS; i++) { + // match once or more. + if (!isMatchChar(s.charAt(i), p.charAt(indexP))) { + return false; + } + + if (isMatchRec(s, p, i + 1, indexP + 2)) { + return true; + } + } + + // if any of them does not match, just return false. + return false; + } + + // match current character and the left string. + return indexS < lenS + && isMatchChar(s.charAt(indexS), p.charAt(indexP)) + && isMatchRec(s, p, indexS + 1, indexP + 1); + } + + public boolean isMatchChar(char s, char p) { + if (p == '*') { + return false; + } + + if (s == p || p == '.') { + return true; + } + + return false; + } + +} \ No newline at end of file diff --git a/tree/TreeDemo2.java b/tree/TreeDemo2.java new file mode 100644 index 0000000..954bdaa --- /dev/null +++ b/tree/TreeDemo2.java @@ -0,0 +1,1560 @@ +package Algorithms.tree; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.Stack; + + +/** + * REFS: + * http://blog.csdn.net/fightforyourdream/article/details/16843303 面试大总结之二:Java搞定面试中的二叉树题目 + * http://blog.csdn.net/luckyxiaoqiang/article/details/7518888 轻松搞定面试中的二叉树题目 + * http://www.cnblogs.com/Jax/archive/2009/12/28/1633691.html 算法大全(3) 二叉树 + * + * 1. 求二叉树中的节点个数: getNodeNumRec(递归),getNodeNum(迭代) + * 2. 求二叉树的深度: getDepthRec(递归),getDepth + * 3. 前序遍历,中序遍历,后序遍历: preorderTraversalRec, preorderTraversal, inorderTraversalRec, postorderTraversalRec + * (https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2) + * 4.分层遍历二叉树(按层次从上往下,从左往右): levelTraversal, levelTraversalRec(递归解法) + * 5. 将二叉查找树变为有序的双向链表: convertBST2DLLRec, convertBST2DLL + * 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel + * 7. 求二叉树中叶子节点的个数:getNodeNumLeafRec, getNodeNumLeaf + * 8. 判断两棵二叉树是否相同的树:isSameRec, isSame + * 9. 判断二叉树是不是平衡二叉树:isAVLRec + * 10. 求二叉树的镜像(破坏和不破坏原来的树两种情况): + * mirrorRec, mirrorCopyRec + * mirror, mirrorCopy + * 10.1 判断两个树是否互相镜像:isMirrorRec isMirror + * 11. 求二叉树中两个节点的最低公共祖先节点: + * LAC 求解最小公共祖先, 使用list来存储path. + * LCABstRec 递归求解BST树. + * LCARec 递归算法 . + * 12. 求二叉树中节点的最大距离:getMaxDistanceRec + * 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec + * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec + * 15. 找出二叉树中最长连续子串(即全部往左的连续节点,或是全部往右的连续节点)findLongest + */ + +public class TreeDemo2 { + /* + 1 + / \ + 2 3 + / \ \ + 4 5 6 + */ + public static void main(String[] args) { + TreeNode r1 = new TreeNode(1); + TreeNode r2 = new TreeNode(2); + TreeNode r3 = new TreeNode(3); + TreeNode r4 = new TreeNode(4); + TreeNode r5 = new TreeNode(5); + TreeNode r6 = new TreeNode(6); + +/* + 10 + / \ + 6 14 + / \ \ + 4 8 16 + / + 0 +*/ + /* + 1 + / \ + 2 3 + / \ \ + 4 5 6 +*/ +// TreeNode r1 = new TreeNode(10); +// TreeNode r2 = new TreeNode(6); +// TreeNode r3 = new TreeNode(14); +// TreeNode r4 = new TreeNode(4); +// TreeNode r5 = new TreeNode(8); +// TreeNode r6 = new TreeNode(16); + + TreeNode r7 = new TreeNode(0); + + r1.left = r2; + r1.right = r3; + r2.left = r4; + r2.right = r5; + r3.right = r6; + + r4.left = r7; + + TreeNode t1 = new TreeNode(10); + TreeNode t2 = new TreeNode(6); + TreeNode t3 = new TreeNode(14); + TreeNode t4 = new TreeNode(4); + TreeNode t5 = new TreeNode(8); + TreeNode t6 = new TreeNode(16); + + TreeNode t7 = new TreeNode(0); + + TreeNode t8 = new TreeNode(0); + TreeNode t9 = new TreeNode(0); + TreeNode t10 = new TreeNode(0); + TreeNode t11 = new TreeNode(0); + + + t1.left = t2; + t1.right = t3; + t2.left = t4; + t2.right = t5; + t3.left = t6; + t3.right = t7; + + t4.left = t8; + //t4.right = t9; + t5.right = t9; + + + // test distance +// t5.right = t8; +// t8.right = t9; +// t9.right = t10; +// t10.right = t11; + + /* + 10 + / \ + 6 14 + / \ \ + 4 8 16 + / + 0 + */ +// System.out.println(LCABstRec(t1, t2, t4).val); +// System.out.println(LCABstRec(t1, t2, t6).val); +// System.out.println(LCABstRec(t1, t4, t6).val); +// System.out.println(LCABstRec(t1, t4, t7).val); +// System.out.println(LCABstRec(t1, t3, t6).val); +// +// System.out.println(LCA(t1, t2, t4).val); +// System.out.println(LCA(t1, t2, t6).val); +// System.out.println(LCA(t1, t4, t6).val); +// System.out.println(LCA(t1, t4, t7).val); +// System.out.println(LCA(t1, t3, t6).val); +// System.out.println(LCA(t1, t6, t6).val); + + //System.out.println(getMaxDistanceRec(t1)); + + //System.out.println(isSame(r1, t1)); + +// System.out.println(isAVLRec(r1)); +// +// preorderTraversalRec(r1); +// //mirrorRec(r1); +// //TreeNode r1Mirror = mirror(r1); +// +// TreeNode r1MirrorCopy = mirrorCopy(r1); +// System.out.println(); +// //preorderTraversalRec(r1Mirror); +// preorderTraversalRec(r1MirrorCopy); +// +// System.out.println(); +// +// System.out.println(isMirrorRec(r1, r1MirrorCopy)); +// System.out.println(isMirror(r1, r1MirrorCopy)); + + + //System.out.println(getNodeNumKthLevelRec(r1, 5)); + + //System.out.println(getNodeNumLeaf(r1)); + +// System.out.println(getNodeNumRec(null)); +// System.out.println(getNodeNum(r1)); + //System.out.println(getDepthRec(null)); +// System.out.println(getDepth(r1)); +// +// preorderTraversalRec(r1); +// System.out.println(); +// preorderTraversal(r1); +// System.out.println(); +// inorderTraversalRec(r1); +// +// System.out.println(); +// inorderTraversal(r1); +// postorderTraversalRec(r1); +// System.out.println(); +// postorderTraversal(r1); +// System.out.println(); +// levelTraversal(r1); +// +// System.out.println(); +// levelTraversalRec(r1); + +// TreeNode ret = convertBST2DLLRec(r1); +// while (ret != null) { +// System.out.print(ret.val + " "); +// ret = ret.right; +// } + +// TreeNode ret2 = convertBST2DLL(r1); +// while (ret2.right != null) { +// ret2 = ret2.right; +// } +// +// while (ret2 != null) { +// System.out.print(ret2.val + " "); +// ret2 = ret2.left; +// } +// +// TreeNode ret = convertBST2DLL(r1); +// while (ret != null) { +// System.out.print(ret.val + " "); +// ret = ret.right; +// } + +// System.out.println(); +// System.out.println(findLongest(r1)); +// System.out.println(); +// System.out.println(findLongest2(r1)); + + // test the rebuildBinaryTreeRec. + //test_rebuildBinaryTreeRec(); + + System.out.println(isCompleteBinaryTreeRec(t1)); + System.out.println(isCompleteBinaryTree(t1)); + } + + public static void test_rebuildBinaryTreeRec() { + ArrayList list1 = new ArrayList(); + list1.add(1); + list1.add(2); + list1.add(4); + list1.add(5); + list1.add(3); + list1.add(6); + list1.add(7); + list1.add(8); + + ArrayList list2 = new ArrayList(); + list2.add(4); + list2.add(2); + list2.add(5); + list2.add(1); + list2.add(3); + list2.add(7); + list2.add(6); + list2.add(8); + + TreeNode root = rebuildBinaryTreeRec(list1, list2); + preorderTraversalRec(root); + System.out.println(); + postorderTraversalRec(root); + } + + private static class TreeNode{ + int val; + TreeNode left; + TreeNode right; + public TreeNode(int val){ + this.val = val; + left = null; + right = null; + } + } + + /* + * null返回0,然后把左右子树的size加上即可。 + * */ + public static int getNodeNumRec(TreeNode root) { + if (root == null) { + return 0; + } + + return getNodeNumRec(root.left) + getNodeNumRec(root.right) + 1; + } + + /** + * 求二叉树中的节点个数迭代解法O(n):基本思想同LevelOrderTraversal, + * 即用一个Queue,在Java里面可以用LinkedList来模拟 + */ + public static int getNodeNum(TreeNode root) { + if (root == null) { + return 0; + } + + Queue q = new LinkedList(); + q.offer(root); + + int cnt = 0; + while (!q.isEmpty()) { + TreeNode node = q.poll(); + if (node.left != null) { + q.offer(node.left); + } + + if (node.right != null) { + q.offer(node.right); + } + + cnt++; + } + + return cnt; + } + + public static int getDepthRec(TreeNode root) { + if (root == null) { + return -1; + } + + return Math.max(getDepthRec(root.left), getDepthRec(root.right)) + 1; + } + + /* + * 可以用 level LevelOrderTraversal 来实现,我们用一个dummyNode来分隔不同的层,这样即可计算出实际的depth. + * 1 + / \ + 2 3 + / \ \ + 4 5 6 + * + * 在队列中如此排列: 1, dummy, 2, 3, dummy, 4, 5, 5, dummy + * + */ + public static int getDepth(TreeNode root) { + if (root == null) { + return 0; + } + + TreeNode dummy = new TreeNode(0); + Queue q = new LinkedList(); + q.offer(root); + q.offer(dummy); + + int depth = -1; + while (!q.isEmpty()) { + TreeNode curr = q.poll(); + if (curr == dummy) { + depth++; + if (!q.isEmpty()) { // 使用DummyNode来区分不同的层, 如果下一层不是为空,则应该在尾部加DummyNode. + q.offer(dummy); + } + } + + if (curr.left != null) { + q.offer(curr.left); + } + if (curr.right != null) { + q.offer(curr.right); + } + } + + return depth; + } + + /* + * 3. 前序遍历,中序遍历,后序遍历: preorderTraversalRec, preorderTraversal, inorderTraversalRec, postorderTraversalRec + * (https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2) + * */ + public static void preorderTraversalRec(TreeNode root) { + if (root == null) { + return; + } + + System.out.print(root.val + " "); + preorderTraversalRec(root.left); + preorderTraversalRec(root.right); + } + + /* + * 前序遍历,Iteration 算法. 把根节点存在stack中。 + * */ + public static void preorderTraversal(TreeNode root) { + if (root == null) { + return; + } + + Stack s = new Stack(); + s.push(root); + + while (!s.isEmpty()) { + TreeNode node = s.pop(); + System.out.print(node.val + " "); + if (node.right != null) { // + s.push(node.right); + } + + // 我们需要先压入右节点,再压入左节点,这样就可以先弹出左节点。 + if (node.left != null) { + s.push(node.left); + } + } + } + + /* + * 中序遍历 + * */ + public static void inorderTraversalRec(TreeNode root) { + if (root == null) { + return; + } + + inorderTraversalRec(root.left); + System.out.print(root.val + " "); + inorderTraversalRec(root.right); + } + + /** + * 中序遍历迭代解法 ,用栈先把根节点的所有左孩子都添加到栈内, + * 然后输出栈顶元素,再处理栈顶元素的右子树 + * http://www.youtube.com/watch?v=50v1sJkjxoc + * + * 还有一种方法能不用递归和栈,基于线索二叉树的方法,较麻烦以后补上 + * http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/ + */ + public static void inorderTraversal(TreeNode root) { + if (root == null) { + return; + } + + Stack s = new Stack(); + + TreeNode cur = root; + + while(true) { + // 把当前节点的左节点都push到栈中. + while (cur != null) { + s.push(cur); + cur = cur.left; + } + + if (s.isEmpty()) { + break; + } + + // 因为此时已经没有左孩子了,所以输出栈顶元素 + cur = s.pop(); + System.out.print(cur.val + " "); + + // 准备处理右子树 + cur = cur.right; + } + } + + // 后序遍历 + /* + * 1 + / \ + 2 3 + / \ \ + 4 5 6 + + if put into the stack directly, then it should be: + 1, 2, 4, 5, 3, 6 in the stack. + when pop, it should be: 6, 3, 5, 4, 2, 1 + + if I + * */ + + public static void postorderTraversalRec(TreeNode root) { + if (root == null) { + return; + } + + postorderTraversalRec(root.left); + postorderTraversalRec(root.right); + System.out.print(root.val + " "); + } + + /** + * 后序遍历迭代解法 + * http://www.youtube.com/watch?v=hv-mJUs5mvU + * http://blog.csdn.net/tang_jin2015/article/details/8545457 + * 从左到右的后序 与从右到左的前序的逆序是一样的,所以就简单喽! 哈哈 + * 用另外一个栈进行翻转即可喽 + */ + public static void postorderTraversal(TreeNode root) { + if (root == null) { + return; + } + + Stack s = new Stack(); + Stack out = new Stack(); + + s.push(root); + while(!s.isEmpty()) { + TreeNode cur = s.pop(); + out.push(cur); + + if (cur.left != null) { + s.push(cur.left); + } + if (cur.right != null) { + s.push(cur.right); + } + } + + while(!out.isEmpty()) { + System.out.print(out.pop().val + " "); + } + } + + /* + * 分层遍历二叉树(按层次从上往下,从左往右)迭代 + * 其实就是广度优先搜索,使用队列实现。队列初始化,将根节点压入队列。当队列不为空,进行如下操作:弹出一个节点 + * ,访问,若左子节点或右子节点不为空,将其压入队列 + * */ + public static void levelTraversal(TreeNode root) { + if (root == null) { + return; + } + + Queue q = new LinkedList(); + q.offer(root); + + while (!q.isEmpty()) { + TreeNode cur = q.poll(); + + System.out.print(cur.val + " "); + if (cur.left != null) { + q.offer(cur.left); + } + if (cur.right != null) { + q.offer(cur.right); + } + } + } + + public static void levelTraversalRec(TreeNode root) { + ArrayList> ret = new ArrayList>(); + levelTraversalVisit(root, 0, ret); + System.out.println(ret); + } + + /** + * 分层遍历二叉树(递归) + * 很少有人会用递归去做level traversal + * 基本思想是用一个大的ArrayList,里面包含了每一层的ArrayList。 + * 大的ArrayList的size和level有关系 + * + * http://discuss.leetcode.com/questions/49/binary-tree-level-order-traversal#answer-container-2543 + */ + public static void levelTraversalVisit(TreeNode root, int level, ArrayList> ret) { + if (root == null) { + return; + } + + // 如果ArrayList的层数不够用, 则新添加一层 + // when size = 3, level: 0, 1, 2 + if (level >= ret.size()) { + ret.add(new ArrayList()); + } + + // visit 当前节点 + ret.get(level).add(root.val); + + // 将左子树, 右子树添加到对应的层。 + levelTraversalVisit(root.left, level + 1, ret); + levelTraversalVisit(root.right, level + 1, ret); + } + + /* + * 题目要求:将二叉查找树转换成排序的双向链表,不能创建新节点,只调整指针。 + 查找树的结点定义如下: + 既然是树,其定义本身就是递归的,自然用递归算法处理就很容易。将根结点的左子树和右子树转换为有序的双向链表, + 然后根节点的left指针指向左子树结果的最后一个结点,同时左子树最后一个结点的right指针指向根节点; + 根节点的right指针指向右子树结果的第一个结点, + 同时右子树第一个结点的left指针指向根节点。 + * */ + public static TreeNode convertBST2DLLRec(TreeNode root) { + return convertBST2DLLRecHelp(root)[0]; + } + + /* + * ret[0] 代表左指针 + * ret[1] 代表右指针 + * */ + public static TreeNode[] convertBST2DLLRecHelp(TreeNode root) { + TreeNode[] ret = new TreeNode[2]; + ret[0] = null; + ret[1] = null; + + if (root == null) { + return ret; + } + + if (root.left != null) { + TreeNode left[] = convertBST2DLLRecHelp(root.left); + left[1].right = root; // 将左子树的尾节点连接到根 + root.left = left[1]; + + ret[0] = left[0]; + } else { + ret[0] = root; // 左节点返回root. + } + + if (root.right != null) { + TreeNode right[] = convertBST2DLLRecHelp(root.right); + right[0].left = root; // 将右子树的头节点连接到根 + root.right = right[0]; + + ret[1] = right[1]; + } else { + ret[1] = root; // 右节点返回root. + } + + return ret; + } + + /** + * 将二叉查找树变为有序的双向链表 迭代解法 + * 类似inOrder traversal的做法 + */ + public static TreeNode convertBST2DLL(TreeNode root) { + while (root == null) { + return null; + } + + TreeNode pre = null; + Stack s = new Stack(); + TreeNode cur = root; + TreeNode head = null; // 链表头 + + while (true) { + while (cur != null) { + s.push(cur); + cur = cur.left; + } + + // if stack is empty, just break; + if (s.isEmpty()) { + break; + } + + cur = s.pop(); + if (head == null) { + head = cur; + } + + // link pre and cur. + cur.left = pre; + if (pre != null) { + pre.right = cur; + } + + // 左节点已经处理完了,处理右节点 + cur = cur.right; + pre = cur; + } + + return root; + } + +/* + * * 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel + * */ + public static int getNodeNumKthLevel(TreeNode root, int k) { + if (root == null || k <= 0) { + return 0; + } + + int level = 0; + + Queue q = new LinkedList(); + q.offer(root); + + TreeNode dummy = new TreeNode(0); + int cnt = 0; // record the size of the level. + + q.offer(dummy); + while (!q.isEmpty()) { + TreeNode node = q.poll(); + + if (node == dummy) { + level++; + if (level == k) { + return cnt; + } + cnt = 0; // reset the cnt; + if (q.isEmpty()) { + break; + } + q.offer(dummy); + continue; + } + + cnt++; + if (node.left != null) { + q.offer(node.left); + } + + if (node.right != null) { + q.offer(node.right); + } + } + + return 0; + } + + /* + * * 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel + * */ + public static int getNodeNumKthLevelRec(TreeNode root, int k) { + if (root == null || k <= 0) { + return 0; + } + + if (k == 1) { + return 1; + } + + // 将左子树及右子树在K层的节点个数相加. + return getNodeNumKthLevelRec(root.left, k - 1) + getNodeNumKthLevelRec(root.right, k - 1); + } + + /* + * 7. getNodeNumLeafRec 把左子树和右子树的叶子节点加在一起即可 + * */ + public static int getNodeNumLeafRec(TreeNode root) { + if (root == null) { + return 0; + } + + if (root.left == null && root.right == null) { + return 1; + } + + return getNodeNumLeafRec(root.left) + getNodeNumLeafRec(root.right); + } + + /* 7. getNodeNumLeaf + * 随便使用一种遍历方法都可以,比如,中序遍历。 + * inorderTraversal,判断是不是叶子节点。 + * */ + public static int getNodeNumLeaf(TreeNode root) { + if (root == null) { + return 0; + } + + int cnt = 0; + + // we can use inorderTraversal travesal to do it. + Stack s = new Stack(); + TreeNode cur = root; + + while (true) { + while (cur != null) { + s.push(cur); + cur = cur.left; + } + + if (s.isEmpty()) { + break; + } + + // all the left child has been put into the stack, let's deal with the + // current node. + cur = s.pop(); + if (cur.left == null && cur.right == null) { + cnt++; + } + cur = cur.right; + } + + return cnt; + } + + /* + * 8. 判断两棵二叉树是否相同的树。 + * 递归解法: + * (1)如果两棵二叉树都为空,返回真 + * (2)如果两棵二叉树一棵为空,另一棵不为空,返回假 + * (3)如果两棵二叉树都不为空,如果对应的左子树和右子树都同构返回真,其他返回假 + * */ + public static boolean isSameRec(TreeNode r1, TreeNode r2) { + // both are null. + if (r1 == null && r2 == null) { + return true; + } + + // one is null. + if (r1 == null || r2 == null) { + return false; + } + + // 1. the value of the root should be the same; + // 2. the left tree should be the same. + // 3. the right tree should be the same. + return r1.val == r2.val && + isSameRec(r1.left, r2.left) && isSameRec(r1.right, r2.right); + } + + /* + * 8. 判断两棵二叉树是否相同的树。 + * 迭代解法 + * 我们直接用中序遍历来比较就好啦 + * */ + public static boolean isSame(TreeNode r1, TreeNode r2) { + // both are null. + if (r1 == null && r2 == null) { + return true; + } + + // one is null. + if (r1 == null || r2 == null) { + return false; + } + + Stack s1 = new Stack(); + Stack s2 = new Stack(); + + TreeNode cur1 = r1; + TreeNode cur2 = r2; + + while (true) { + while (cur1 != null && cur2 != null) { + s1.push(cur1); + s2.push(cur2); + cur1 = cur1.left; + cur2 = cur2.left; + } + + if (cur1 != null || cur2 != null) { + return false; + } + + if (s1.isEmpty() && s2.isEmpty()) { + break; + } + + cur1 = s1.pop(); + cur2 = s2.pop(); + if (cur1.val != cur2.val) { + return false; + } + + cur1 = cur1.right; + cur2 = cur2.right; + } + + return true; + } + +/* + * + * 9. 判断二叉树是不是平衡二叉树:isAVLRec + * 1. 左子树,右子树的高度差不能超过1 + * 2. 左子树,右子树都是平衡二叉树。 + * + */ + public static boolean isAVLRec(TreeNode root) { + if (root == null) { + return true; + } + + // 左子树,右子树都必须是平衡二叉树。 + if (!isAVLRec(root.left) || !isAVLRec(root.right)) { + return false; + } + + int dif = Math.abs(getDepthRec(root.left) - getDepthRec(root.right)); + if (dif > 1) { + return false; + } + + return true; + } + + /** + * 10. 求二叉树的镜像 递归解法: + * + * (1) 破坏原来的树 + * + * 1 1 + * / \ + * 2 -----> 2 + * \ / + * 3 3 + * */ + public static TreeNode mirrorRec(TreeNode root) { + if (root == null) { + return null; + } + + // 先把左右子树分别镜像,并且交换它们 + TreeNode tmp = root.right; + root.right = mirrorRec(root.left); + root.left = mirrorRec(tmp); + + return root; + } + + /** + * 10. 求二叉树的镜像 Iterator解法: + * + * (1) 破坏原来的树 + * + * 1 1 + * / \ + * 2 -----> 2 + * \ / + * 3 3 + * + * 应该可以使用任何一种Traversal 方法。 + * 我们现在可以试看看使用最简单的前序遍历。 + * */ + public static TreeNode mirror(TreeNode root) { + if (root == null) { + return null; + } + + Stack s = new Stack(); + s.push(root); + + while (!s.isEmpty()) { + TreeNode cur = s.pop(); + + // 交换当前节点的左右节点 + TreeNode tmp = cur.left; + cur.left = cur.right; + cur.right = tmp; + + // traversal 左节点,右节点。 + if (cur.right != null) { + s.push(cur.right); + } + + if (cur.left != null) { + s.push(cur.left); + } + } + + return root; + } + + /** + * 10. 求二叉树的镜像 Iterator解法: + * + * (2) 创建一个新的树 + * + * 1 1 + * / \ + * 2 -----> 2 + * \ / + * 3 3 + * + * 应该可以使用任何一种Traversal 方法。 + * 我们现在可以试看看使用最简单的前序遍历。 + * 前序遍历我们可以立刻把新建好的左右节点创建出来,比较方便 + * */ + public static TreeNode mirrorCopy(TreeNode root) { + if (root == null) { + return null; + } + + Stack s = new Stack(); + Stack sCopy = new Stack(); + s.push(root); + + TreeNode rootCopy = new TreeNode(root.val); + sCopy.push(rootCopy); + + while (!s.isEmpty()) { + TreeNode cur = s.pop(); + TreeNode curCopy = sCopy.pop(); + + // traversal 左节点,右节点。 + if (cur.right != null) { + + // copy 在这里做比较好,因为我们可以容易地找到它的父节点 + TreeNode leftCopy = new TreeNode(cur.right.val); + curCopy.left = leftCopy; + s.push(cur.right); + sCopy.push(curCopy.left); + } + + if (cur.left != null) { + // copy 在这里做比较好,因为我们可以容易地找到它的父节点 + TreeNode rightCopy = new TreeNode(cur.left.val); + curCopy.right = rightCopy; + s.push(cur.left); + sCopy.push(curCopy.right); + } + } + + return rootCopy; + } + + /** + * 10. 求二叉树的镜像 递归解法: + * + * (1) 不破坏原来的树,新建一个树 + * + * 1 1 + * / \ + * 2 -----> 2 + * \ / + * 3 3 + * */ + public static TreeNode mirrorCopyRec(TreeNode root) { + if (root == null) { + return null; + } + + // 先把左右子树分别镜像,并且把它们连接到新建的root节点。 + TreeNode rootCopy = new TreeNode(root.val); + rootCopy.left = mirrorCopyRec(root.right); + rootCopy.right = mirrorCopyRec(root.left); + + return rootCopy; + } + + /* + * 10.1. 判断两个树是否互相镜像 + * (1) 根必须同时为空,或是同时不为空 + * + * 如果根不为空: + * (1).根的值一样 + * (2).r1的左树是r2的右树的镜像 + * (3).r1的右树是r2的左树的镜像 + * */ + public static boolean isMirrorRec(TreeNode r1, TreeNode r2){ + // 如果2个树都是空树 + if (r1 == null && r2 == null) { + return true; + } + + // 如果其中一个为空,则返回false. + if (r1 == null || r2 == null) { + return false; + } + + // If both are not null, they should be: + // 1. have same value for root. + // 2. R1's left tree is the mirror of R2's right tree; + // 3. R2's right tree is the mirror of R1's left tree; + return r1.val == r2.val + && isMirrorRec(r1.left, r2.right) + && isMirrorRec(r1.right, r2.left); + } + + /* + * 10.1. 判断两个树是否互相镜像 Iterator 做法 + * (1) 根必须同时为空,或是同时不为空 + * + * 如果根不为空: + * traversal 整个树,判断它们是不是镜像,每次都按照反向来traversal + * (1). 当前节点的值相等 + * (2). 当前节点的左右节点要镜像, + * 无论是左节点,还是右节点,对应另外一棵树的镜像位置,可以同时为空,或是同时不为空,但是不可以一个为空,一个不为空。 + * */ + public static boolean isMirror(TreeNode r1, TreeNode r2){ + // 如果2个树都是空树 + if (r1 == null && r2 == null) { + return true; + } + + // 如果其中一个为空,则返回false. + if (r1 == null || r2 == null) { + return false; + } + + Stack s1 = new Stack(); + Stack s2 = new Stack(); + + s1.push(r1); + s2.push(r2); + + while (!s1.isEmpty() && !s2.isEmpty()) { + TreeNode cur1 = s1.pop(); + TreeNode cur2 = s2.pop(); + + // 弹出的节点的值必须相等 + if (cur1.val != cur2.val) { + return false; + } + + // tree1的左节点,tree2的右节点,可以同时不为空,也可以同时为空,否则返回false. + TreeNode left1 = cur1.left; + TreeNode right1 = cur1.right; + TreeNode left2 = cur2.left; + TreeNode right2 = cur2.right; + + if (left1 != null && right2 != null) { + s1.push(left1); + s2.push(right2); + } else if (!(left1 == null && right2 == null)) { + return false; + } + + // tree1的左节点,tree2的右节点,可以同时不为空,也可以同时为空,否则返回false. + if (right1 != null && left2 != null) { + s1.push(right1); + s2.push(left2); + } else if (!(right1 == null && left2 == null)) { + return false; + } + } + + return true; + } + + /* + * 11. 求二叉树中两个节点的最低公共祖先节点: + * Recursion Version: + * LACRec + * 1. If found in the left tree, return the Ancestor. + * 2. If found in the right tree, return the Ancestor. + * 3. If Didn't find any of the node, return null. + * 4. If found both in the left and the right tree, return the root. + * */ + public static TreeNode LACRec(TreeNode root, TreeNode node1, TreeNode node2) { + if (root == null || node1 == null || node2 == null) { + return null; + } + + // If any of the node is the root, just return the root. + if (root == node1 || root == node2) { + return root; + } + + // if no node is in the node, just recursively find it in LEFT and RIGHT tree. + TreeNode left = LACRec(root.left, node1, node2); + TreeNode right = LACRec(root.right, node1, node2); + + if (left == null) { // If didn't found in the left tree, then just return it from right. + return right; + } else if (right == null) { // Or if didn't found in the right tree, then just return it from the left side. + return left; + } + + // if both right and right found a node, just return the root as the Common Ancestor. + return root; + } + + /* + * 11. 求BST中两个节点的最低公共祖先节点: + * Recursive version: + * LCABst + * + * 1. If found in the left tree, return the Ancestor. + * 2. If found in the right tree, return the Ancestor. + * 3. If Didn't find any of the node, return null. + * 4. If found both in the left and the right tree, return the root. + * */ + public static TreeNode LCABstRec(TreeNode root, TreeNode node1, TreeNode node2) { + if (root == null || node1 == null || node2 == null) { + return null; + } + + // If any of the node is the root, just return the root. + if (root == node1 || root == node2) { + return root; + } + + int min = Math.min(node1.val, node2.val); + int max = Math.max(node1.val, node2.val); + + // if the values are smaller than the root value, just search them in the left tree. + if (root.val > max) { + return LCABstRec(root.left, node1, node2); + } else if (root.val < min) { + // if the values are larger than the root value, just search them in the right tree. + return LCABstRec(root.right, node1, node2); + } + + // if root is in the middle, just return the root. + return root; + } + + /* + * 解法1. 记录下path,并且比较之: + * LAC + * http://www.geeksforgeeks.org/lowest-common-ancestor-binary-tree-set-1/ + * */ + public static TreeNode LCA(TreeNode root, TreeNode r1, TreeNode r2) { + // If the nodes have one in the root, just return the root. + if (root == null || r1 == null || r2 == null) { + return null; + } + + ArrayList list1 = new ArrayList(); + ArrayList list2 = new ArrayList(); + + boolean find1 = LCAPath(root, r1, list1); + boolean find2 = LCAPath(root, r2, list2); + + // If didn't find any of the node, just return a null. + if (!find1 || !find2) { + return null; + } + + // 注意: 使用Iterator 对于linkedlist可以提高性能。 + // 所以 统一使用Iterator 来进行操作。 + Iterator iter1 = list1.iterator(); + Iterator iter2 = list2.iterator(); + + TreeNode last = null; + while (iter1.hasNext() && iter2.hasNext()) { + TreeNode tmp1 = iter1.next(); + TreeNode tmp2 = iter2.next(); + + if (tmp1 != tmp2) { + return last; + } + + last = tmp1; + } + + // If never find any node which is different, means Node 1 and Node 2 are the same one. + // so just return the last one. + return last; + } + + public static boolean LCAPath(TreeNode root, TreeNode node, ArrayList path) { + // if didn't find, we should return a empty path. + if (root == null || node == null) { + return false; + } + + // First add the root node. + path.add(root); + + // if the node is in the left side. + if (root != node + && !LCAPath(root.left, node, path) + && !LCAPath(root.right, node, path) + ) { + // Didn't find the node. should remove the node added before. + path.remove(root); + return false; + } + + // found + return true; + } + + /* + * * 12. 求二叉树中节点的最大距离:getMaxDistanceRec + * + * 首先我们来定义这个距离: + * 距离定义为:两个节点间边的数目. + * 如: + * 1 + * / \ + * 2 3 + * \ + * 4 + * 这里最大距离定义为2,4的距离,为3. + * 求二叉树中节点的最大距离 即二叉树中相距最远的两个节点之间的距离。 (distance / diameter) + * 递归解法: + * 返回值设计: + * 返回1. 深度, 2. 当前树的最长距离 + * (1) 计算左子树的深度,右子树深度,左子树独立的链条长度,右子树独立的链条长度 + * (2) 最大长度为三者之最: + * a. 通过根节点的链,为左右深度+2 + * b. 左子树独立链 + * c. 右子树独立链。 + * + * (3)递归初始条件: + * 当root == null, depth = -1.maxDistance = -1; + * + */ + public static int getMaxDistanceRec(TreeNode root) { + return getMaxDistanceRecHelp(root).maxDistance; + } + + public static Result getMaxDistanceRecHelp(TreeNode root) { + Result ret = new Result(-1, -1); + + if (root == null) { + return ret; + } + + Result left = getMaxDistanceRecHelp(root.left); + Result right = getMaxDistanceRecHelp(root.right); + + // 深度应加1, the depth from the subtree to the root. + ret.depth = Math.max(left.depth, right.depth) + 1; + + // 左子树,右子树与根的距离都要加1,所以通过根节点的路径为两边深度+2 + int crossLen = left.depth + right.depth + 2; + + // 求出cross根的路径,及左右子树的独立路径,这三者路径的最大值。 + ret.maxDistance = Math.max(left.maxDistance, right.maxDistance); + ret.maxDistance = Math.max(ret.maxDistance, crossLen); + + return ret; + } + + + private static class Result { + int depth; + int maxDistance; + public Result(int depth, int maxDistance) { + this.depth = depth; + this.maxDistance = maxDistance; + } + } + + /* + * 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec + * We assume that there is no duplicate in the trees. + * For example: + * 1 + * / \ + * 2 3 + * /\ \ + * 4 5 6 + * /\ + * 7 8 + * + * PreOrder should be: 1 2 4 5 3 6 7 8 + * 根 左子树 右子树 + * InOrder should be: 4 2 5 1 3 7 6 8 + * 左子树 根 右子树 + * */ + public static TreeNode rebuildBinaryTreeRec(List preOrder, List inOrder) { + if (preOrder == null || inOrder == null) { + return null; + } + + // If the traversal is empty, just return a NULL. + if (preOrder.size() == 0 || inOrder.size() == 0) { + return null; + } + + // we can get the root from the preOrder. + // Because the first one is the root. + // So we just create the root node here. + TreeNode root = new TreeNode(preOrder.get(0)); + + List preOrderLeft; + List preOrderRight; + List inOrderLeft; + List inOrderRight; + + // 获得在 inOrder中,根的位置 + int rootInIndex = inOrder.indexOf(preOrder.get(0)); + preOrderLeft = preOrder.subList(1, rootInIndex + 1); + preOrderRight = preOrder.subList(rootInIndex + 1, preOrder.size()); + + // 得到inOrder左边的左子树 + inOrderLeft = inOrder.subList(0, rootInIndex); + inOrderRight = inOrder.subList(rootInIndex + 1, inOrder.size()); + + // 通过 Rec 来调用生成左右子树。 + root.left = rebuildBinaryTreeRec(preOrderLeft, inOrderLeft); + root.right = rebuildBinaryTreeRec(preOrderRight, inOrderRight); + + return root; + } + + /* + * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec + * 进行level traversal, 一旦遇到一个节点的左节点为空,后面的节点的子节点都必须为空。而且不应该有下一行,其实就是队列中所有的 + * 元素都不应该再有子元素。 + * */ + + public static boolean isCompleteBinaryTree(TreeNode root) { + if (root == null) { + return false; + } + + TreeNode dummyNode = new TreeNode(0); + Queue q = new LinkedList(); + + q.offer(root); + q.offer(dummyNode); + + // if this is true, no node should have any child. + boolean noChild = false; + + while (!q.isEmpty()) { + TreeNode cur = q.poll(); + if (cur == dummyNode) { + if (!q.isEmpty()) { + q.offer(dummyNode); + } + // Dummy node不需要处理。 + continue; + } + + if (cur.left != null) { + // 如果标记被设置,则Queue中任何元素不应再有子元素。 + if (noChild) { + return false; + } + q.offer(cur.left); + } else { + // 一旦某元素没有左节点或是右节点,则之后所有的元素都不应有子元素。 + // 并且该元素不可以有右节点. + noChild = true; + } + + if (cur.right != null) { + // 如果标记被设置,则Queue中任何元素不应再有子元素。 + if (noChild) { + return false; + } + q.offer(cur.right); + } else { + // 一旦某元素没有左节点或是右节点,则之后所有的元素都不应有子元素。 + noChild = true; + } + } + + return true; + } + + /* + * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTreeRec + * + * + * 我们可以分解为: + * CompleteBinary Tree 的条件是: + * 1. 左右子树均为Perfect binary tree, 并且两者Height相同 + * 2. 左子树为CompleteBinaryTree, 右子树为Perfect binary tree,并且两者Height差1 + * 3. 左子树为Perfect Binary Tree,右子树为CompleteBinaryTree, 并且Height 相同 + * + * Base 条件: + * (1) root = null: 为perfect & complete BinaryTree, Height -1; + * + * 而 Perfect Binary Tree的条件: + * 左右子树均为Perfect Binary Tree,并且Height 相同。 + * */ + + public static boolean isCompleteBinaryTreeRec(TreeNode root) { + return isCompleteBinaryTreeRecHelp(root).isCompleteBT; + } + + private static class ReturnBinaryTree { + boolean isCompleteBT; + boolean isPerfectBT; + int height; + + ReturnBinaryTree(boolean isCompleteBT, boolean isPerfectBT, int height) { + this.isCompleteBT = isCompleteBT; + this.isPerfectBT = isPerfectBT; + this.height = height; + } + } + + /* + * 我们可以分解为: + * CompleteBinary Tree 的条件是: + * 1. 左右子树均为Perfect binary tree, 并且两者Height相同 + * 2. 左子树为CompleteBinaryTree, 右子树为Perfect binary tree,并且两者Height差1 + * 3. 左子树为Perfect Binary Tree,右子树为CompleteBinaryTree, 并且Height 相同 + * + * Base 条件: + * (1) root = null: 为perfect & complete BinaryTree, Height -1; + * + * 而 Perfect Binary Tree的条件: + * 左右子树均为Perfect Binary Tree,并且Height 相同。 + * */ + public static ReturnBinaryTree isCompleteBinaryTreeRecHelp(TreeNode root) { + ReturnBinaryTree ret = new ReturnBinaryTree(true, true, -1); + + if (root == null) { + return ret; + } + + ReturnBinaryTree left = isCompleteBinaryTreeRecHelp(root.left); + ReturnBinaryTree right = isCompleteBinaryTreeRecHelp(root.right); + + // 树的高度为左树高度,右树高度的最大值+1 + ret.height = 1 + Math.max(left.height, right.height); + + // set the isPerfectBT + ret.isPerfectBT = false; + if (left.isPerfectBT && right.isPerfectBT && left.height == right.height) { + ret.isPerfectBT = true; + } + + // set the isCompleteBT. + /* + * CompleteBinary Tree 的条件是: + * 1. 左右子树均为Perfect binary tree, 并且两者Height相同(其实就是本树是perfect tree) + * 2. 左子树为CompleteBinaryTree, 右子树为Perfect binary tree,并且两者Height差1 + * 3. 左子树为Perfect Binary Tree,右子树为CompleteBinaryTree, 并且Height 相同 + * */ + ret.isCompleteBT = ret.isPerfectBT + || (left.isCompleteBT && right.isPerfectBT && left.height == right.height + 1) + || (left.isPerfectBT && right.isCompleteBT && left.height == right.height); + + return ret; + } + + /* + * 15. findLongest + * 第一种解法: + * 返回左边最长,右边最长,及左子树最长,右子树最长。 + * */ + public static int findLongest(TreeNode root) { + if (root == null) { + return -1; + } + + TreeNode l = root; + int cntL = 0; + while (l.left != null) { + cntL++; + l = l.left; + } + + TreeNode r = root; + int cntR = 0; + while (r.right != null) { + cntR++; + r = r.right; + } + + int lmax = findLongest(root.left); + int rmax = findLongest(root.right); + + int max = Math.max(lmax, rmax); + max = Math.max(max, cntR); + max = Math.max(max, cntL); + + return max; + } + + /* 1 + * 2 3 + * 3 4 + * 6 1 + * 7 + * 9 + * 11 + * 2 + * 14 + * */ + public static int findLongest2(TreeNode root) { + int [] maxVal = new int[1]; + maxVal[0] = -1; + findLongest2Help(root, maxVal); + return maxVal[0]; + } + + // ret: + // 0: the left side longest, + // 1: the right side longest. + static int maxLen = -1; + static int[] findLongest2Help(TreeNode root, int[] maxVal) { + int[] ret = new int[2]; + if (root == null) { + ret[0] = -1; + ret[1] = -1; + return ret; + } + + ret[0] = findLongest2Help(root.left, maxVal)[0] + 1; + ret[1] = findLongest2Help(root.right, maxVal)[1] + 1; + //maxLen = Math.max(maxLen, ret[0]); + //maxLen = Math.max(maxLen, ret[1]); + maxVal[0] = Math.max(maxVal[0], ret[0]); + maxVal[0] = Math.max(maxVal[0], ret[1]); + + return ret; + } +} \ No newline at end of file From e9160dfb2acc26a2583f3d52dd35d88cbb902783 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 18 Nov 2014 03:45:45 -0800 Subject: [PATCH 191/319] longest --- string/LongestCommonPrefix.java | 31 +++++++++++++++++++++++++++++++ string/isMatch.java | 10 +++------- 2 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 string/LongestCommonPrefix.java diff --git a/string/LongestCommonPrefix.java b/string/LongestCommonPrefix.java new file mode 100644 index 0000000..73e0ba1 --- /dev/null +++ b/string/LongestCommonPrefix.java @@ -0,0 +1,31 @@ +package Algorithms.string; + +public class LongestCommonPrefix { + //http://blog.csdn.net/fightforyourdream/article/details/14642079 + public String longestCommonPrefix(String[] strs) { + if (strs == null) { + return null; + } + + if (strs.length == 0) { + return ""; + } + + String s = strs[0]; + int len = s.length(); + + for (int i = 0; i < len; i++) { + char c = s.charAt(i); + + for (int j = 1; j < strs.length; j++) { + if (strs[j].length() <= i || c != strs[j].charAt(i)) { + // The char i is invalid. 因为读到i时退出,所以不应包含i本身。 + return s.substring(0, i); + } + } + } + + // Didn't break, the whole String is valid. + return s; + } +} diff --git a/string/isMatch.java b/string/isMatch.java index 8d9799c..2e02ab2 100644 --- a/string/isMatch.java +++ b/string/isMatch.java @@ -18,14 +18,8 @@ public boolean isMatchRec(String s, String p, int indexS, int indexP) { return indexS == lenS; } - // only 1 match character left. - if (indexP == lenP - 1) { - // String should also have 1 character left. - return indexS == lenS - 1 && isMatchChar(s.charAt(indexS), p.charAt(indexP)); - } - // At lease 2 match character left - if (p.charAt(indexP + 1) == '*') { + if (indexP < lenP - 1 && p.charAt(indexP + 1) == '*') { // match 0; if (isMatchRec(s, p, indexS, indexP + 2)) { return true; @@ -65,4 +59,6 @@ public boolean isMatchChar(char s, char p) { return false; } +} + } \ No newline at end of file From 0e5ae7d549159fdbaa7cc9b1d899e046fa26a4d2 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 18 Nov 2014 04:29:20 -0800 Subject: [PATCH 192/319] restore --- string/RestoreIpAddresses.java | 54 ++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 string/RestoreIpAddresses.java diff --git a/string/RestoreIpAddresses.java b/string/RestoreIpAddresses.java new file mode 100644 index 0000000..56a74e0 --- /dev/null +++ b/string/RestoreIpAddresses.java @@ -0,0 +1,54 @@ +package Algorithms.string; + +import java.util.ArrayList; +import java.util.List; + +public class RestoreIpAddresses { + public List restoreIpAddresses(String s) { + if (s == null) { + return null; + } + + ArrayList ret = new ArrayList(); + ArrayList path = new ArrayList(); + + dfs(s, 0, path, ret); + + return ret; + } + + public void dfs(String s, int index, ArrayList path, ArrayList ret) { + if (path.size() == 4) { + if (index == s.length() && path.size() == 4) { + StringBuilder sb = new StringBuilder(); + for (String str: path) { + sb.append(str); + sb.append('.'); + } + + sb.deleteCharAt(sb.length() - 1); + ret.add(sb.toString()); + } + + return; + } + + int len = s.length(); + for (int i = index; i < index + 3 && i < len; i++) { + if (s.charAt(index) == '0' && i > index) { + break; + } + + String pre = s.substring(index, i + 1); + // 过滤Number > 255的情况。 + int num = Integer.parseInt(pre); + if (num > 255) { + continue; + } + + path.add(pre); + dfs(s, i + 1, path, ret); + path.remove(path.size() - 1); + } + } +} \ No newline at end of file From 1aceb60dc6919a2924b8d94b4f69305e52f6f6b4 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 18 Nov 2014 04:42:07 -0800 Subject: [PATCH 193/319] Ip ADDRESS --- string/RestoreIpAddresses.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/string/RestoreIpAddresses.java b/string/RestoreIpAddresses.java index 56a74e0..a7a7a27 100644 --- a/string/RestoreIpAddresses.java +++ b/string/RestoreIpAddresses.java @@ -19,7 +19,7 @@ public List restoreIpAddresses(String s) { public void dfs(String s, int index, ArrayList path, ArrayList ret) { if (path.size() == 4) { - if (index == s.length() && path.size() == 4) { + if (index == s.length()) { StringBuilder sb = new StringBuilder(); for (String str: path) { sb.append(str); @@ -35,12 +35,13 @@ public void dfs(String s, int index, ArrayList path, ArrayList r int len = s.length(); for (int i = index; i < index + 3 && i < len; i++) { + // 不可以有005这样子的IP地址。 if (s.charAt(index) == '0' && i > index) { break; } String pre = s.substring(index, i + 1); - // 过滤Number > 255的情况。 + // 过滤num > 255的情况。 int num = Integer.parseInt(pre); if (num > 255) { continue; From 926c79ef7457474eb1e721a831d643aa3303cbca Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 18 Nov 2014 05:23:10 -0800 Subject: [PATCH 194/319] minstack --- stack/MinStack.java | 51 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 stack/MinStack.java diff --git a/stack/MinStack.java b/stack/MinStack.java new file mode 100644 index 0000000..ceb9077 --- /dev/null +++ b/stack/MinStack.java @@ -0,0 +1,51 @@ +package Algorithms.stack; + +import java.util.Stack; + +class MinStack { + public static void main(String[] strs) { + MinStack sta = new MinStack(); + + //push(512),push(-1024),push(-1024),push(512),pop,getminStack,pop,getminStack,pop,getminStack + sta.push(512); + sta.push(-1024); + sta.push(-1024); + sta.push(512); + + sta.pop(); + sta.getminStack(); + sta.pop(); + sta.getminStack(); + sta.pop(); + sta.getminStack(); + } + + Stack elements = new Stack(); + Stack minStack = new Stack(); + + public void push(int x) { + elements.push(x); + if (minStack.isEmpty() || x <= minStack.peek()) { + minStack.push(x); + } + } + + public void pop() { + if (elements.isEmpty()) { + return; + } + + if (elements.peek().equals(minStack.peek())) { + minStack.pop(); + } + elements.pop(); + } + + public int top() { + return elements.peek(); + } + + public int getminStack() { + return minStack.peek(); + } +} From 166eb8905aae54e7b2fe126216f0c42ad6124956 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 18 Nov 2014 16:30:59 -0800 Subject: [PATCH 195/319] mac rectang --- array/MaximalRectangle.java | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 array/MaximalRectangle.java diff --git a/array/MaximalRectangle.java b/array/MaximalRectangle.java new file mode 100644 index 0000000..dc6700f --- /dev/null +++ b/array/MaximalRectangle.java @@ -0,0 +1,57 @@ +package Algorithms.array; + +import java.util.Stack; + +public class MaximalRectangle { + public int maximalRectangle(char[][] matrix) { + if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { + return 0; + } + + int rows = matrix.length; + int cols = matrix[0].length; + + int[][] h = new int[rows][cols]; + + int max = 0; + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + + h[i][j] = matrix[i][j] == '1' ? 1: 0; + + if (i != 0 && h[i][j] != 0) { + h[i][j] = h[i - 1][j] + 1; + } + + if (j == cols - 1) { + max = Math.max(max, maxArea(h[i])); + } + } + } + + return max; + } + + public int maxArea(int[] h) { + Stack s = new Stack(); + + int max = 0; + int i = 0; + + // 注意,这里使用<= 因为当i到达最后,需要计算一次。 + while (i <= h.length) { + // + if (s.isEmpty() || i < h.length && h[i] >= h[s.peek()]) { + s.push(i); + i++; + } else { + int height = h[s.pop()]; + int width = s.isEmpty() ? i: i - s.peek() - 1; + max = Math.max(max, height * width); + } + } + + return max; + } +} \ No newline at end of file From 43f86b6c615cf8f69faaab20511e38960b1a27e9 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 21 Nov 2014 01:38:32 -0800 Subject: [PATCH 196/319] LRU --- hash/LRUCache.java | 90 +++++++++++++++++++++++++++++++++++++++++++++ hash/LRUCache2.java | 51 +++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 hash/LRUCache.java create mode 100644 hash/LRUCache2.java diff --git a/hash/LRUCache.java b/hash/LRUCache.java new file mode 100644 index 0000000..82b2bc2 --- /dev/null +++ b/hash/LRUCache.java @@ -0,0 +1,90 @@ +package Algorithms.hash; + +import java.util.HashMap; + +public class LRUCache { + private class DLink { + DLink pre; + DLink next; + int val; + int key; + DLink(int key, int val) { + this.val = val; + this.key = key; + pre = null; + next = null; + } + } + + HashMap map; + + DLink head; + DLink tail; + + int capacity; + + public void removeFist() { + removeNode(head.next); + } + + public void removeNode(DLink node) { + node.pre.next = node.next; + node.next.pre = node.pre; + } + + // add a node to the tail. + public void addToTail(DLink node) { + tail.pre.next = node; + + node.pre = tail.pre; + node.next = tail; + + tail.pre = node; + } + + public LRUCache(int capacity) { + map = new HashMap(); + + // two dummy nodes. In that case, we can deal with them more conviencely. + head = new DLink(-1, -1); + tail = new DLink(-1, -1); + head.next = tail; + tail.pre = head; + + this.capacity = capacity; + } + + public int get(int key) { + if (map.get(key) == null) { + return -1; + } + + // update the node. + DLink node = map.get(key); + removeNode(node); + addToTail(node); + + return node.val; + } + + public void set(int key, int value) { + DLink node = map.get(key); + if (node == null) { + // create a node and add the key-node pair into the map. + node = new DLink(key, value); + map.put(key, node); + } else { + // update the value of the node. + node.val = value; + removeNode(node); + } + + addToTail(node); + + // if the LRU is full, just remove a node. + if (map.size() > capacity) { + map.remove(head.next.key); + removeFist(); + } + } +} \ No newline at end of file diff --git a/hash/LRUCache2.java b/hash/LRUCache2.java new file mode 100644 index 0000000..8458990 --- /dev/null +++ b/hash/LRUCache2.java @@ -0,0 +1,51 @@ +package Algorithms.hash; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class LRUCache2 { + public static void main(String[] strs) { + LRUCache2 lrc2 = new LRUCache2(2); + lrc2.set(1,3); + lrc2.set(2,2); + lrc2.set(1,4); + lrc2.set(4,2); + + System.out.println(lrc2.get(1)); + } + + LinkedHashMap map; + int capacity; + + public LRUCache2(final int capacity) { + // create a map. + map = new LinkedHashMap(capacity) { + /** + * + */ + private static final long serialVersionUID = 1L; + + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > capacity; + } + }; + this.capacity = capacity; + } + + public int get(int key) { + Integer ret = map.get(key); + if (ret == null) { + return -1; + } else { + map.remove(key); + map.put(key, ret); + } + + return ret; + } + + public void set(int key, int value) { + map.remove(key); + map.put(key, value); + } +} From a8093ee65c3c8ec0c0b0f55bca44fbca040c20fe Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 21 Nov 2014 02:26:40 -0800 Subject: [PATCH 197/319] generate Parenthesis ge --- string/GenerateParenthesis.java | 38 +++++++++++++++++++++++++++++++++ string/isMatch.java | 2 -- 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 string/GenerateParenthesis.java diff --git a/string/GenerateParenthesis.java b/string/GenerateParenthesis.java new file mode 100644 index 0000000..260a28d --- /dev/null +++ b/string/GenerateParenthesis.java @@ -0,0 +1,38 @@ +package Algorithms.string; + +import java.util.ArrayList; +import java.util.List; + +public class GenerateParenthesis { + public List generateParenthesis(int n) { + List ret = new ArrayList(); + + if (n == 0) { + return ret; + } + + dfs(n, n, new StringBuilder(), ret); + + return ret; + } + + // left : the left Parentheses + // right : the right Parentheses + public void dfs(int left, int right, StringBuilder sb, List ret) { + if (left == 0 && right == 0) { + ret.add(sb.toString()); + return; + } + + // left < right means that we have more ( then we can add ). + if (left < 0 || right < 0 || left > right) { + return; + } + + dfs(left - 1, right, sb.append('('), ret); + sb.deleteCharAt(sb.length() - 1); + + dfs(left, right - 1, sb.append(')'), ret); + sb.deleteCharAt(sb.length() - 1); + } +} \ No newline at end of file diff --git a/string/isMatch.java b/string/isMatch.java index 2e02ab2..0da97fe 100644 --- a/string/isMatch.java +++ b/string/isMatch.java @@ -59,6 +59,4 @@ public boolean isMatchChar(char s, char p) { return false; } -} - } \ No newline at end of file From 04d3b4034a7735ea63310794a42116bec62fddc8 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 21 Nov 2014 04:01:44 -0800 Subject: [PATCH 198/319] parentheses --- string/LongestValidParentheses.java | 55 +++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 string/LongestValidParentheses.java diff --git a/string/LongestValidParentheses.java b/string/LongestValidParentheses.java new file mode 100644 index 0000000..c41b7b6 --- /dev/null +++ b/string/LongestValidParentheses.java @@ -0,0 +1,55 @@ +package Algorithms.string; + +import java.util.Stack; + +public class LongestValidParentheses { + public static void main(String[] strs) { + System.out.println(longestValidParentheses("(()()())")); + } + + public int longestValidParentheses(String s) { + if (s == null) { + return 0; + } + + Stack stk = new Stack(); + int sum = 0; + int tmp = 0; + + int max = 0; + + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + + if (c == '(') { + stk.push(i); + } else { + if (stk.isEmpty()) { + // 栈中没有'(',出现')', 则必须重置计算 + sum = 0; + continue; + } + + // count the temporary lenght: + // like: (()()() + // tmp = 2. + tmp = i - stk.pop() + 1; + if (stk.isEmpty()) { + // 有一套完整的括号集,可以加到前面的一整套括号集上 + // () (()()) + // 1 2 第二套括号集可以加过来 + sum += tmp; + max = Math.max(sum, max); + } else { + // 也可能是一个未完成的括号集,比如: + // () (()() 在这里 ()() 是一个未完成的括号集,可以独立出来计算,作为 + // 阶段性的结果 + tmp = i - stk.peek(); + max = Math.max(tmp, max); + } + } + } + + return max; + } +} \ No newline at end of file From d7fbfefde1b94840529028290a80f84455ef3c69 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 21 Nov 2014 15:27:29 -0800 Subject: [PATCH 199/319] find string --- string/FindSubstring.java | 79 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 string/FindSubstring.java diff --git a/string/FindSubstring.java b/string/FindSubstring.java new file mode 100644 index 0000000..c8f80aa --- /dev/null +++ b/string/FindSubstring.java @@ -0,0 +1,79 @@ +package Algorithms.string; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class FindSubstring { + public static void main(String[] strs) { + String[] L = {"fooo","barr","wing","ding","wing"}; + + System.out.println(findSubstring("lingmindraboofooowingdingbarrwingmonkeypoundcake", L)); + } + + public static List findSubstring(String S, String[] L) { + HashMap map = new HashMap(); + HashMap found = new HashMap(); + List ret = new ArrayList(); + + if (S == null || L == null || L.length == 0) { + return ret; + } + + int cntL = 0; + + // put all the strings into the map. + for (String s: L) { + if (map.containsKey(s)) { + map.put(s, map.get(s) + 1); + } else { + map.put(s, 1); + cntL++; + } + } + + int lenL = L[0].length(); + + int cntFound = 0; + + // 注意这里的条件:i < S.length() - lenL * L.length + // 这里很关键,如果长度不够了,不需要再继续查找 + for (int i = 0; i <= S.length() - lenL * L.length; i++) { + // clear the found hashmap. + found.clear(); + cntFound = 0; + + // 一次前进一个L的length. + // 注意j <= S.length() - lenL; 防止越界 + for (int j = i; j <= S.length() - lenL; j += lenL) { + String sub = S.substring(j, j + lenL); + if (map.containsKey(sub)) { + if (found.containsKey(sub)) { + if (found.get(sub) == map.get(sub)) { + // 超过了限制数目 + break; + } + + found.put(sub, found.get(sub) + 1); + } else { + found.put(sub, 1); + } + + if (found.get(sub) == map.get(sub)) { + cntFound++; + } + + // L中所有的字符串都已经找到了。 + if (cntFound == cntL) { + ret.add(i); + } + } else { + // 不符合条件,可以break,i前进到下一个匹配位置 + break; + } + } + } + + return ret; + } +} \ No newline at end of file From efd6874e9ffe6103c7767ec1bcef46ac1378014e Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 21 Nov 2014 15:31:11 -0800 Subject: [PATCH 200/319] str --- string/FindSubstring.java | 56 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/string/FindSubstring.java b/string/FindSubstring.java index c8f80aa..40641af 100644 --- a/string/FindSubstring.java +++ b/string/FindSubstring.java @@ -11,7 +11,7 @@ public static void main(String[] strs) { System.out.println(findSubstring("lingmindraboofooowingdingbarrwingmonkeypoundcake", L)); } - public static List findSubstring(String S, String[] L) { + public static List findSubstring1(String S, String[] L) { HashMap map = new HashMap(); HashMap found = new HashMap(); List ret = new ArrayList(); @@ -76,4 +76,58 @@ public static List findSubstring(String S, String[] L) { return ret; } + + // SOLUTION 2: + public static List findSubstring(String S, String[] L) { + HashMap map = new HashMap(); + HashMap found; + List ret = new ArrayList(); + + if (S == null || L == null || L.length == 0) { + return ret; + } + + // put all the strings into the map. + for (String s: L) { + if (map.containsKey(s)) { + map.put(s, map.get(s) + 1); + } else { + map.put(s, 1); + } + } + + int lenL = L[0].length(); + + // 注意这里的条件:i < S.length() - lenL * L.length + // 这里很关键,如果长度不够了,不需要再继续查找 + for (int i = 0; i <= S.length() - lenL * L.length; i++) { + // 每一次,都复制之前的hashMap. + found = new HashMap(map); + + // 一次前进一个L的length. + // 注意j <= S.length() - lenL; 防止越界 + for (int j = i; j <= S.length() - lenL; j += lenL) { + String sub = S.substring(j, j + lenL); + if (found.containsKey(sub)) { + // 将找到字符串的计数器减1. + found.put(sub, found.get(sub) - 1); + + // 减到0即可将其移出。否则会产生重复运算,以及我们用MAP为空来判断是否找到所有的单词。 + if (found.get(sub) == 0) { + found.remove(sub); + } + } else { + // 不符合条件,可以break,i前进到下一个匹配位置 + break; + } + + // L中所有的字符串都已经找到了。 + if (found.isEmpty()) { + ret.add(i); + } + } + } + + return ret; + } } \ No newline at end of file From 589ac081987f470a8d8cdb9535f8288848764bfa Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 22 Nov 2014 02:29:07 -0800 Subject: [PATCH 201/319] decode. --- dp/NumDecodings.java | 48 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 dp/NumDecodings.java diff --git a/dp/NumDecodings.java b/dp/NumDecodings.java new file mode 100644 index 0000000..91ed522 --- /dev/null +++ b/dp/NumDecodings.java @@ -0,0 +1,48 @@ +package Algorithms.dp; + +public class NumDecodings { + public int numDecodings(String s) { + if (s == null || s.length() == 0) { + return 0; + } + + int len = s.length(); + + // D[i] 表示含有i个字符的子串的DECODE WAYS. + int[] D = new int[len + 1]; + + D[0] = 1; + + for (int i = 1; i <= len; i++) { + D[i] = 0; + + // 现在正在考察的字符的索引. + int index = i - 1; + // 最后一个字符独立解码 + if (isValidSingle(s.charAt(index))) { + D[i] += D[i - 1]; + } + + // 最后一个字符与上一个字符一起解码 + if (i > 1 && isValidTwo(s.substring(index - 1, index + 1))) { + D[i] += D[i - 2]; + } + } + + return D[len]; + } + + public boolean isValidSingle(char c) { + if (c >= '1' && c <= '9') { + return true; + } + + return false; + } + + public boolean isValidTwo(String s) { + int num = Integer.parseInt(s); + + return (num >= 10 && num <= 26); + } +} From fc1528b844893fc8cddb82cfdf643bbf41bbc52a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 22 Nov 2014 17:18:28 -0800 Subject: [PATCH 202/319] isMatch --- dp/IsMatch.java | 123 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 dp/IsMatch.java diff --git a/dp/IsMatch.java b/dp/IsMatch.java new file mode 100644 index 0000000..903376c --- /dev/null +++ b/dp/IsMatch.java @@ -0,0 +1,123 @@ +package Algorithms.dp; + +public class IsMatch { + public static void main(String[] strs) { +// System.out.println(isMatch("aa","a")); +// System.out.println(isMatch("aa","aa**")); +// System.out.println(isMatch("aaa","aa")); + System.out.println(isMatch("hi", "*?")); +// System.out.println(isMatch("aa","a*")); +// System.out.println(isMatch("ab","?*")); +// System.out.println(isMatch("aab", "c*a*b")); + } + + public static boolean isMatch1(String s, String p) { + if (s == null || p == null) { + return false; + } + + int lens = s.length(); + int lenp = p.length(); + + // 创建一个Dp二维数组 + boolean[][] D = new boolean[lens + 1][lenp + 1]; + + boolean flag = false; + + for (int i = 0; i <= lens; i++) { + flag = false; + for (int j = 0; j <= lenp; j++) { + // both is empty. + if (i == 0 && j == 0) { + D[i][j] = true; + flag = true; + continue; + } + + // if P is empty, s is not empty, it is false. + if (j == 0) { + D[i][j] = false; + continue; + } + + // if S is empty, P is not empty + if (i == 0) { + D[i][j] = D[i][j - 1] && p.charAt(j - 1) == '*'; + } else { + D[i][j] = (matchChar(s.charAt(i - 1), p.charAt(j - 1)) && D[i - 1][j - 1]) + || (p.charAt(j - 1) == '*' && (D[i][j - 1] || D[i - 1][j])); + } + + if (D[i][j]) { + flag = true; + } + + // Greedy. 在此即可以退出,因为* 可以匹配余下的所有的字符串。 + if (D[i][j] && p.charAt(j - 1) == '*' && j == lenp) { + return true; + } + } + + if (!flag) { + return false; + } + } + + return D[lens][lenp]; + } + + public static boolean matchChar(char c, char p) { + return (p == '?' || p == c); + } + + public static boolean isMatch(String s, String p) { + if (s == null || p == null) { + return false; + } + + int indexS = 0; + int indexP = 0; + + int lenS = s.length(); + int lenP = p.length(); + + int preS = 0; + int preP = 0; + + boolean back = false; + + while (indexS < lenS) { + if (indexP < lenP && matchChar(s.charAt(indexS), p.charAt(indexP))) { + indexS++; + indexP++; + } else if (indexP < lenP && p.charAt(indexP) == '*') { + while (indexP < lenP && p.charAt(indexP) == '*') { + indexP++; + } + + //P的最后一个是 *,表示可以匹配任何字符串 + if (indexP == lenP) { + return true; + } + + // 记录下这个匹配位置。 + back = true; + preS = indexS; + preP = indexP; + } else { + if (back) { + indexS = ++preS; + indexP = preP; + } else { + return false; + } + } + } + + if (indexS == lenS && indexP == lenP) { + return true; + } + + return false; + } +} From dc964fdb34d1497905ed0c9b8f43fd718e4023ac Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 22 Nov 2014 18:27:22 -0800 Subject: [PATCH 203/319] math --- dp/IsMatch.java | 5 +++++ string/Multiply.java | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 string/Multiply.java diff --git a/dp/IsMatch.java b/dp/IsMatch.java index 903376c..e6363ce 100644 --- a/dp/IsMatch.java +++ b/dp/IsMatch.java @@ -114,6 +114,11 @@ public static boolean isMatch(String s, String p) { } } + // 跳过末尾的所有的*. + while (indexP < lenP && p.charAt(indexP) == '*') { + indexP++; + } + if (indexS == lenS && indexP == lenP) { return true; } diff --git a/string/Multiply.java b/string/Multiply.java new file mode 100644 index 0000000..f973607 --- /dev/null +++ b/string/Multiply.java @@ -0,0 +1,41 @@ +package Algorithms.string; + +public class Multiply { + public static void main(String[] strs) { + multiply("9", "9"); + } + + public static String multiply(String num1, String num2) { + if (num1 == null || num2 == null) { + return null; + } + + int len1 = num1.length(); + int len2 = num2.length(); + + int[] product = new int[len1 + len2]; + + // 计算相应位置的product. + for (int i = 0; i < len1; i++) { + for (int j = 0; j < len2; j++) { + product[i + j] = (num1.charAt(len1 - 1 - i) - '0') * (num2.charAt(len2 - 1 - j) - '0'); + } + } + + StringBuilder ret = new StringBuilder(); + + int carry = 0; + for (int i = 0; i < len1 + len2; i++) { + product[i] = product[i] + carry; + int digit = product[i] % 10; + carry = digit / 10; + ret.insert(0, digit); + } + + while (ret.length() > 1 && ret.charAt(0) == '0') { + ret.deleteCharAt(0); + } + + return ret.toString(); + } +} From 267a8b2d14b0be78f3a884ce04db7eb71d6e7806 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 22 Nov 2014 23:56:12 -0800 Subject: [PATCH 204/319] convert --- string/Convert.java | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 string/Convert.java diff --git a/string/Convert.java b/string/Convert.java new file mode 100644 index 0000000..13e9bdf --- /dev/null +++ b/string/Convert.java @@ -0,0 +1,40 @@ +package Algorithms.string; + +public class Convert { + public static void main(String[] strs) { + System.out.println(convert("A", 1)); + } + + public static String convert(String s, int nRows) { + if (s == null) { + return null; + } + + // 第一个小部分的大小 + int size = 2 * nRows - 2; + + // 当行数为1的时候,不需要折叠。 + if (nRows <= 1) { + return s; + } + + StringBuilder ret = new StringBuilder(); + + int len = s.length(); + for (int i = 0; i < nRows; i++) { + // j代表第几个BLOCK + for (int j = i; j < len; j += size) { + ret.append(s.charAt(j)); + + // 即不是第一行,也不是最后一行,还需要加上中间的节点 + int mid = j + size - i * 2; + if (i != 0 && i != nRows - 1 && mid < len) { + char c = s.charAt(mid); + ret.append(c); + } + } + } + + return ret.toString(); + } +} From 49156f916f0be33511acd75e6d28503df5f78e03 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 23 Nov 2014 00:52:35 -0800 Subject: [PATCH 205/319] intToRoman --- string/IntToRoman.java | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 string/IntToRoman.java diff --git a/string/IntToRoman.java b/string/IntToRoman.java new file mode 100644 index 0000000..9a9859a --- /dev/null +++ b/string/IntToRoman.java @@ -0,0 +1,23 @@ +package Algorithms.string; + +public class IntToRoman { + public String intToRoman(int num) { + int nums[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; + String[] romans = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; + + StringBuilder sb = new StringBuilder(); + + int i = 0; + // 使用贪心法。尽量拆分数字 + while (i < nums.length) { + if (num >= nums[i]) { + sb.append(romans[i]); + num -= nums[i]; + } else { + i++; + } + } + + return sb.toString(); + } +} From c2f771610e17f882b363e21d9bf2c95fb448f1ce Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 23 Nov 2014 00:57:33 -0800 Subject: [PATCH 206/319] int --- string/IntToRoman.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/string/IntToRoman.java b/string/IntToRoman.java index 9a9859a..f950ac5 100644 --- a/string/IntToRoman.java +++ b/string/IntToRoman.java @@ -20,4 +20,4 @@ public String intToRoman(int num) { return sb.toString(); } -} +} \ No newline at end of file From 7d8a69d966153c29ff971349b104974cfe8e9001 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 23 Nov 2014 02:26:56 -0800 Subject: [PATCH 207/319] roman --- string/RomanToInt.java | 64 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 string/RomanToInt.java diff --git a/string/RomanToInt.java b/string/RomanToInt.java new file mode 100644 index 0000000..b9190d4 --- /dev/null +++ b/string/RomanToInt.java @@ -0,0 +1,64 @@ +package Algorithms.string; + +public class RomanToInt { + public int romanToInt(String s) { + if (s == null) { + return 0; + } + + int len = s.length(); + int sum = 0; + int pre = 0; + + for (int i = len - 1; i >= 0; i--) { + int cur = romanTable(s.charAt(i)); + + if (i == len - 1) { + // 如果是在尾部,直接加上当前值 + sum += cur; + } else { + // 判定当前值是不是比前一个值要小,如果小,则需要减去它 + if (cur < pre) { + sum -= cur; + } else { + sum += cur; + } + } + pre = cur; + } + + return sum; + } + + public int romanTable(char c) { + int num = 0; + switch(c) { + case 'I': + num = 1; + break; + case 'V': + num = 5; + break; + case 'X': + num = 10; + break; + case 'L': + num = 50; + break; + case 'C': + num = 100; + break; + case 'D': + num = 500; + break; + case 'M': + num = 1000; + break; + default: + num = 0; + break; + } + + return num; + } +} \ No newline at end of file From c4eafc1059efc8c0a9dfa23091a7ca8f276b4435 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 23 Nov 2014 18:32:11 -0800 Subject: [PATCH 208/319] count --- string/CountAndSay.java | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 string/CountAndSay.java diff --git a/string/CountAndSay.java b/string/CountAndSay.java new file mode 100644 index 0000000..9e567ad --- /dev/null +++ b/string/CountAndSay.java @@ -0,0 +1,30 @@ +package Algorithms.string; + +public class CountAndSay { + public String countAndSay(int n) { + if (n == 0) { + return null; + } + + if (n == 1) { + return "1"; + } + + String s = countAndSay(n - 1); + StringBuilder sb = new StringBuilder(); + + int len = s.length(); + int cnt = 0; + for (int i = 0; i < len; i++) { + cnt++; + + if (i == len - 1 || (i < len - 1 && s.charAt(i) != s.charAt(i + 1))) { + sb.append(cnt); + sb.append(s.charAt(i)); + cnt = 0; + } + } + + return sb.toString(); + } +} \ No newline at end of file From 62077341db286c7a6bbb6ff78b1b7ce79d04a404 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 24 Nov 2014 02:40:27 -0800 Subject: [PATCH 209/319] Wordladder 2 --- string/FindLadders.java | 111 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 string/FindLadders.java diff --git a/string/FindLadders.java b/string/FindLadders.java new file mode 100644 index 0000000..c35c946 --- /dev/null +++ b/string/FindLadders.java @@ -0,0 +1,111 @@ +package Algorithms.string; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.Set; + +public class FindLadders { + public static void main(String[] strs) { + Set dict = new HashSet(); + dict.add("hot"); + dict.add("dot"); + dict.add("dog"); + dict.add("lot"); + dict.add("log"); + dict.add("cog"); + + System.out.println(findLadders("hit", "cob", dict)); + } + + public static List> findLadders(String start, String end, Set dict) { + if (start == null || end == null) { + return null; + } + + Queue q = new LinkedList(); + + // 存储每一个单词对应的路径 + HashMap>> map = new HashMap>>(); + + // 标记在某一层找到解 + boolean find = false; + + // store the length of the start string. + int lenStr = start.length(); + + List> list = new ArrayList>(); + + // 唯一的路径 + List path = new ArrayList(); + path.add(start); + list.add(path); + + // 将头节点放入 + map.put(start, list); + q.offer(start); + + while (!q.isEmpty()) { + int size = q.size(); + + HashMap>> mapTmp = new HashMap>>(); + for (int i = 0; i < size; i++) { + // get the current word. + String str = q.poll(); + for (int j = 0; j < lenStr; j++) { + StringBuilder sb = new StringBuilder(str); + for (char c = 'a'; c <= 'z'; c++) { + sb.setCharAt(j, c); + String tmp = sb.toString(); + + // 1. 重复的单词,不需要计算。因为之前一层出现过,再出现只会更长 + // 2. 必须要在字典中出现 + if (map.containsKey(tmp) || (!dict.contains(tmp) && !tmp.equals(end))) { + continue; + } + + // 将前节点的路径提取出来 + List> pre = map.get(str); + + // 从mapTmp中取出节点,或者是新建一个节点 + List> curList = mapTmp.get(tmp); + if (curList == null) { + // Create a new list and add to the end word. + curList = new ArrayList>(); + mapTmp.put(tmp, curList); + + // 将生成的单词放入队列,以便下一次继续变换 + // 放在这里可以避免Q重复加入 + q.offer(tmp); + } + + // 将PRE的path 取出,加上当前节点,并放入curList中 + for(List pathPre: pre) { + List pathNew = new ArrayList(pathPre); + pathNew.add(tmp); + curList.add(pathNew); + } + + if (tmp.equals(end)) { + find = true; + } + } + } + } + + if (find) { + return mapTmp.get(end); + } + + // 把当前层找到的解放在MAP中。 + // 使用2个map的原因是:在当前层中,我们需要把同一个单词的所有的解全部找出来. + map.putAll(mapTmp); + } + + // 返回一个空的结果 + return new ArrayList>(); + } +} \ No newline at end of file From 4e341c7119b53cb94cc6c65ff2105f4062ab5d61 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 25 Nov 2014 03:49:22 -0800 Subject: [PATCH 210/319] gray --- algorithm/others/Reverse_binary.java | 20 ++++++++++++++++++++ recursion/GrayCode.java | 24 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 algorithm/others/Reverse_binary.java create mode 100644 recursion/GrayCode.java diff --git a/algorithm/others/Reverse_binary.java b/algorithm/others/Reverse_binary.java new file mode 100644 index 0000000..8ddecc4 --- /dev/null +++ b/algorithm/others/Reverse_binary.java @@ -0,0 +1,20 @@ +package Algorithms.algorithm.others; + +public class Reverse_binary { + public static void main(String[] strs) { + System.out.println(reverse(20034556)); + } + + public static int reverse(int in) { + int ret = 0; + + for (int i = 0; i < 4; i++) { + int tmp = (in & 0xFF); + ret <<= 8; + ret += tmp; + in >>= 8; + } + + return ret; + } +} diff --git a/recursion/GrayCode.java b/recursion/GrayCode.java new file mode 100644 index 0000000..d766135 --- /dev/null +++ b/recursion/GrayCode.java @@ -0,0 +1,24 @@ +package Algorithms.recursion; + +import java.util.ArrayList; +import java.util.List; + +public class GrayCode { + public List grayCode(int n) { + List ret = new ArrayList(); + if (n == 0) { + ret.add(0); + return ret; + } + + ret = grayCode(n - 1); + + for (int i = ret.size() - 1; i >= 0; i--) { + int num = ret.get(i); + num += 1 << (n - 1); + ret.add(num); + } + + return ret; + } +} \ No newline at end of file From ee98c392fea32a104ba702085417f32679a4d852 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 26 Nov 2014 03:35:25 -0800 Subject: [PATCH 211/319] maxpoint --- hash/MaxPoints.java | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 hash/MaxPoints.java diff --git a/hash/MaxPoints.java b/hash/MaxPoints.java new file mode 100644 index 0000000..37495bc --- /dev/null +++ b/hash/MaxPoints.java @@ -0,0 +1,50 @@ +package Algorithms.hash; + +import java.awt.Point; +import java.util.HashMap; + +public class MaxPoints { + public int maxPoints(Point[] points) { + int max = 0; + + if (points == null) { + return 0; + } + + int len = points.length; + + for (int i = 0; i < len; i++) { + // Create a map to recode all the numbers of elements of every K. + HashMap map = new HashMap(); + + // ItSelf. + int dup = 0; + + for (int j = i; j < len; j++) { + // the same point. + if (points[i].x == points[j].x && points[i].y == points[j].y) { + dup++; + continue; + } + + double k = Double.MAX_VALUE; + if (points[i].x != points[j].x) { + k = 0 + (double)(points[i].y - points[j].y)/(double)(points[i].x - points[j].x); + } + + if (map.containsKey(k)) { + map.put(k, map.get(k) + 1); + } else { + map.put(k, 1); + } + } + + max = Math.max(max, dup); + for (int n: map.values()) { + max = Math.max(max, n + dup); + } + } + + return max; + } +} \ No newline at end of file From 66b47328310c0982a71c4de18f834b105c0b46f3 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 26 Nov 2014 04:32:50 -0800 Subject: [PATCH 212/319] prn --- stack/EvalRPN.java | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 stack/EvalRPN.java diff --git a/stack/EvalRPN.java b/stack/EvalRPN.java new file mode 100644 index 0000000..099f961 --- /dev/null +++ b/stack/EvalRPN.java @@ -0,0 +1,40 @@ +package Algorithms.stack; + +import java.util.Stack; + +public class EvalRPN { + public int evalRPN(String[] tokens) { + if (tokens == null) { + return 0; + } + + int len = tokens.length; + Stack s = new Stack(); + + for (int i = 0; i < len; i++) { + String str = tokens[i]; + if (str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/")) { + // get out the two operation number. + int n2 = s.pop(); + int n1 = s.pop(); + if (str.equals("+")) { + s.push(n1 + n2); + } else if (str.equals("-")) { + s.push(n1 - n2); + } else if (str.equals("*")) { + s.push(n1 * n2); + } else if (str.equals("/")) { + s.push(n1 / n2); + } + } else { + s.push(Integer.parseInt(str)); + } + } + + if (s.isEmpty()) { + return 0; + } + + return s.pop(); + } +} \ No newline at end of file From 405c1a869d9e26688b5481316e2f3e09e92ea462 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 27 Nov 2014 05:54:08 -0800 Subject: [PATCH 213/319] text justify --- string/FullJustify.java | 111 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 string/FullJustify.java diff --git a/string/FullJustify.java b/string/FullJustify.java new file mode 100644 index 0000000..40493bf --- /dev/null +++ b/string/FullJustify.java @@ -0,0 +1,111 @@ +package Algorithms.string; + +import java.util.ArrayList; +import java.util.List; + +public class FullJustify { + public static void main(String[] strs) { + String[] words = {"Listen","to","many,","speak","to","a","few."}; + int L = 6; + fullJustify(words, L); + } + + // SOLUTION 1: recursion. + public List fullJustify1(String[] words, int L) { + List ret = new ArrayList(); + + if (words == null) { + return ret; + } + + rec(words, L, 0, ret); + return ret; + } + + public static void rec(String[] words, int L, int index, List list) { + int len = words.length; + if (index >= len) { + return; + } + + int LenTmp = L; + + int end = index; + for (int i = index; i < len && words[i].length() <= L; i++) { + L -= words[i].length(); + + // the space follow the word. + L--; + end = i; + } + + // 最后一个空格收回 + L++; + + // Count how many words do we have. + int num = end - index + 1; + + int extraSpace = 0; + int firstExtra = 0; + + // 单词数大于1,才需要分配,否则所有的空格加到最后即可 + if (num > 1) { + extraSpace = L / (num - 1); + // 首单词后多跟的空格 + firstExtra = L % (num - 1); + } + + StringBuilder sb = new StringBuilder(); + for (int i = index; i <= end; i++) { + sb.append(words[i]); + + // The space following every word. + if (i != end) { + sb.append(' '); + } + + // 不是最后一行 + if (end != len - 1) { + // The first words. + if (firstExtra > 0) { + sb.append(' '); + firstExtra--; + } + + // 最后一个单词后面不需要再加空格 + if (i == end) { + break; + } + + // 每个单词后的额外空格 + int cnt = extraSpace; + while (cnt > 0) { + sb.append(' '); + cnt--; + } + } + } + + // 最后一行的尾部的空格 + int tailLen = LenTmp - sb.length(); + while (tailLen > 0) { + sb.append(' '); + tailLen--; + } + + list.add(sb.toString()); + rec(words, LenTmp, end + 1, list); + } + + // SOLUTION 2: iteration. + public List fullJustify(String[] words, int L) { + List ret = new ArrayList(); + + if (words == null) { + return ret; + } + + rec(words, L, 0, ret); + return ret; + } +} \ No newline at end of file From 08ca0675bb911a6d4b41a3c51e3dd9f239cef07a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 28 Nov 2014 00:02:30 -0800 Subject: [PATCH 214/319] GetIntersectionNode1 --- list/GetIntersectionNode1.java | 98 ++++++++++++++++++++ string/FullJustify.java | 159 ++++++++++++++++++++++++++++++++- 2 files changed, 254 insertions(+), 3 deletions(-) create mode 100644 list/GetIntersectionNode1.java diff --git a/list/GetIntersectionNode1.java b/list/GetIntersectionNode1.java new file mode 100644 index 0000000..13c5e29 --- /dev/null +++ b/list/GetIntersectionNode1.java @@ -0,0 +1,98 @@ +package Algorithms.list; + +import Algorithms.algorithm.others.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class GetIntersectionNode1 { + public ListNode getIntersectionNode1(ListNode headA, ListNode headB) { + if (headA == null || headB == null) { + return null; + } + + int lenA = getLen(headA); + int lenB = getLen(headB); + + if (lenA > lenB) { + while (lenA > lenB) { + headA = headA.next; + lenA--; + } + } else { + while (lenA < lenB) { + headB = headB.next; + lenB--; + } + } + + while (headA != null) { + if (headA == headB) { + return headA; + } + headA = headA.next; + headB = headB.next; + } + + return null; + } + + public int getLen(ListNode node) { + int len = 0; + while (node != null) { + len++; + node = node.next; + } + return len; + } + + public ListNode getIntersectionNode(ListNode headA, ListNode headB) { + if (headA == null || headB == null) { + return null; + } + + ListNode pA = headA; + ListNode pB = headB; + + ListNode tailA = null; + ListNode tailB = null; + + while (true) { + if (pA == null) { + pA = headB; + } + + if (pB == null) { + pB = headA; + } + + if (pA.next == null) { + tailA = pA; + } + + if (pB.next == null) { + tailB = pB; + } + + //The two links have different tails. So just return null; + if (tailA != null && tailB != null && tailA != tailB) { + return null; + } + + if (pA == pB) { + return pA; + } + + pA = pA.next; + pB = pB.next; + } + } +} \ No newline at end of file diff --git a/string/FullJustify.java b/string/FullJustify.java index 40493bf..56d8aa5 100644 --- a/string/FullJustify.java +++ b/string/FullJustify.java @@ -10,7 +10,7 @@ public static void main(String[] strs) { fullJustify(words, L); } - // SOLUTION 1: recursion. + // SOLUTION 1: recursion. public List fullJustify1(String[] words, int L) { List ret = new ArrayList(); @@ -98,14 +98,167 @@ public static void rec(String[] words, int L, int index, List list) { } // SOLUTION 2: iteration. - public List fullJustify(String[] words, int L) { + public List fullJustify2(String[] words, int L) { List ret = new ArrayList(); + if (words == null) { + return ret; + } + + int len = words.length; + int index = 0; + + while (index < len) { + int LenTmp = L; + int end = index; + for (int i = index; i < len && words[i].length() <= LenTmp; i++) { + LenTmp -= words[i].length(); + + // the space follow the word. + LenTmp--; + end = i; + } + + // 最后一个空格收回 + LenTmp++; + + // Count how many words do we have. + int num = end - index + 1; + + int extraSpace = 0; + int firstExtra = 0; + + // 单词数大于1,才需要分配,否则所有的空格加到最后即可 + if (num > 1) { + extraSpace = LenTmp / (num - 1); + // 首单词后多跟的空格 + firstExtra = LenTmp % (num - 1); + } + + StringBuilder sb = new StringBuilder(); + for (int i = index; i <= end; i++) { + sb.append(words[i]); + + // The space following every word. + if (i != end) { + sb.append(' '); + } + + // 不是最后一行 + if (end != len - 1) { + // The first words. + if (firstExtra > 0) { + sb.append(' '); + firstExtra--; + } + + // 最后一个单词后面不需要再加空格 + if (i == end) { + break; + } + + // 每个单词后的额外空格 + int cnt = extraSpace; + while (cnt > 0) { + sb.append(' '); + cnt--; + } + } + } + + // 最后一行的尾部的空格 + int tailLen = L - sb.length(); + while (tailLen > 0) { + sb.append(' '); + tailLen--; + } + + ret.add(sb.toString()); + index = end + 1; + } + + return ret; + } + + // SOLUTION 3: iteration2 + public static List fullJustify(String[] words, int L) { + List ret = new ArrayList(); if (words == null) { return ret; } - rec(words, L, 0, ret); + int len = words.length; + int index = 0; + + while (index < len) { + int LenTmp = L; + + int end = index; + for (int i = index; i < len && words[i].length() <= LenTmp; i++) { + LenTmp -= words[i].length(); + + // the space follow the word. + LenTmp--; + end = i; + } + + // 最后一个空格收回 + LenTmp++; + + // Count how many words do we have. + int num = end - index + 1; + + int extraSpace = 0; + int firstExtra = 0; + + // 单词数大于1,才需要分配,否则所有的空格加到最后即可 + if (num > 1) { + extraSpace = LenTmp / (num - 1); + // 首单词后多跟的空格 + firstExtra = LenTmp % (num - 1); + } + + StringBuilder sb = new StringBuilder(); + for (int i = index; i <= end; i++) { + sb.append(words[i]); + + int cnt = 0; + + if (i == end) { + break; + } + + // 不是最后一行 + if (end != len - 1) { + // The first words. + if (firstExtra > 0) { + cnt++; + firstExtra--; + } + + // 最后一个单词后面不需要再加空格 + // 每个单词后的额外空格 + cnt += extraSpace; + } + + // 1: 每个单词后本来要加的空格 + appendSpace(sb, cnt + 1); + } + + // 最后一行的尾部的空格,或者是只有一个单词的情况 + appendSpace(sb, L - sb.length()); + + ret.add(sb.toString()); + index = end + 1; + } + return ret; } + + public static void appendSpace(StringBuilder sb, int cnt) { + while (cnt > 0) { + sb.append(' '); + cnt--; + } + } } \ No newline at end of file From fa4cbba0cc06dc11f9e3806ef7804767ec51b08e Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 29 Nov 2014 04:21:51 -0800 Subject: [PATCH 215/319] list --- list/SwapPairs3.java | 105 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 list/SwapPairs3.java diff --git a/list/SwapPairs3.java b/list/SwapPairs3.java new file mode 100644 index 0000000..7dd2eb9 --- /dev/null +++ b/list/SwapPairs3.java @@ -0,0 +1,105 @@ +package Algorithms.list; + +import Algorithms.algorithm.others.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class SwapPairs3 { + // Solution 1: the recursion version. + public ListNode swapPairs1(ListNode head) { + if (head == null) { + return null; + } + + return rec(head); + } + + public ListNode rec(ListNode head) { + if (head == null || head.next == null) { + return head; + } + + ListNode next = head.next.next; + + // 翻转后面的链表 + next = rec(next); + + // store the new head. + ListNode tmp = head.next; + + // reverse the two nodes. + head.next = next; + tmp.next = head; + + return tmp; + } + + // Solution 2: the iteration version. + public ListNode swapPairs(ListNode head) { + // 如果小于2个元素,不需要任何操作 + if (head == null || head.next == null) { + return head; + } + + ListNode dummy = new ListNode(0); + dummy.next = head; + + // The node before the reverse area; + ListNode pre = dummy; + + while (pre.next != null && pre.next.next != null) { + // The last node of the reverse area; + ListNode tail = pre.next.next; + + ListNode tmp = pre.next; + pre.next = tail; + + ListNode next = tail.next; + tail.next = tmp; + tmp.next = next; + + // move forward the pre node. + pre = tmp; + } + + return dummy.next; + } + + // Solution 3: the iteration version. + public ListNode swapPairs3(ListNode head) { + // 如果小于2个元素,不需要任何操作 + if (head == null || head.next == null) { + return head; + } + + ListNode dummy = new ListNode(0); + dummy.next = head; + + // The node before the reverse area; + ListNode pre = dummy; + + while (pre.next != null && pre.next.next != null) { + ListNode next = pre.next.next.next; + + ListNode tmp = pre.next; + pre.next = pre.next.next; + pre.next.next = tmp; + + tmp.next = next; + + // move forward the pre node. + pre = tmp; + } + + return dummy.next; + } +} \ No newline at end of file From 248e31fb9d2fe071557d86dcbeb15c29efe4ce7c Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 29 Nov 2014 04:53:42 -0800 Subject: [PATCH 216/319] sort --- list/SortList.java | 90 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 list/SortList.java diff --git a/list/SortList.java b/list/SortList.java new file mode 100644 index 0000000..8a7311b --- /dev/null +++ b/list/SortList.java @@ -0,0 +1,90 @@ +package Algorithms.list; + +import Algorithms.algorithm.others.ListNode; + +/** + * Definition for singly-linked list. + * class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class SortList { + public ListNode sortList(ListNode head) { + // Nodes should be more than 2. + if (head == null || head.next == null) { + return head; + } + + // get the mid node. + ListNode midPre = getMidPre(head); + + // Cut the two list. + ListNode right = midPre.next; + midPre.next = null; + + // Sort the left side and the right side. + ListNode left = sortList(head); + right = sortList(right); + + // Merge the two sides together. + return merge(left, right); + } + + // get the pre node before mid. + public ListNode getMidPre1(ListNode head) { + ListNode slow = head; + ListNode fast = head; + + while (fast != null && fast.next != null && fast.next.next != null) { + slow = slow.next; + fast = fast.next.next; + } + + return slow; + } + + // get the pre node before mid. + public ListNode getMidPre(ListNode head) { + ListNode slow = head; + + // fast提前一点儿。这样就可以得到前一个节点喽。 + ListNode fast = head.next; + + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + + return slow; + } + + public ListNode merge(ListNode head1, ListNode head2) { + ListNode dummy = new ListNode(0); + ListNode cur = dummy; + + while (head1 != null && head2 != null) { + if (head1.val < head2.val) { + cur.next = head1; + head1 = head1.next; + } else { + cur.next = head2; + head2 = head2.next; + } + + cur = cur.next; + } + + if (head1 != null) { + cur.next = head1; + } else { + cur.next = head2; + } + + return dummy.next; + } +} \ No newline at end of file From 5c5e0acdef3d4c5d4a3a56a3ba93291c812e4f08 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 29 Nov 2014 06:04:16 -0800 Subject: [PATCH 217/319] bfs --- bfs/Solve.java | 118 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 bfs/Solve.java diff --git a/bfs/Solve.java b/bfs/Solve.java new file mode 100644 index 0000000..1b8ee48 --- /dev/null +++ b/bfs/Solve.java @@ -0,0 +1,118 @@ +package Algorithms.bfs; + +import java.util.LinkedList; +import java.util.Queue; + +//https://oj.leetcode.com/problems/surrounded-regions/ +public class Solve { + public static void main(String[] strs) { + char[][] board = { + {'X','O','X','O','X','O'}, + {'O','X','O','X','O','X'}, + {'X','O','X','O','X','O'}, + {'O','X','O','X','O','X'} + }; + + //solve(board); + } + + public void solve(char[][] board) { + if (board == null || board.length == 0 || board[0].length == 0) { + return; + } + + int rows = board.length; + int cols = board[0].length; + + // the first line and the last line. + for (int j = 0; j < cols; j++) { + bfs(board, 0, j); + bfs(board, rows - 1, j); + } + + // the left and right column + for (int i = 0; i < rows; i++) { + bfs(board, i, 0); + bfs(board, i, cols - 1); + } + + // capture all the nodes. + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (board[i][j] == 'O') { + board[i][j] = 'X'; + } else if (board[i][j] == 'B') { + board[i][j] = 'O'; + } + } + } + + return; + } + + public void bfs1(char[][] board, int i, int j) { + int rows = board.length; + int cols = board[0].length; + + Queue q = new LinkedList(); + q.offer(i * cols + j); + + while (!q.isEmpty()) { + int index = q.poll(); + + // Index is out of bound. + if (index < 0 || index >= rows * cols) { + continue; + } + + int x = index / cols; + int y = index % cols; + + if (board[x][y] != 'O') { + continue; + } + + board[x][y] = 'B'; + q.offer(index + 1); + q.offer(index - 1); + q.offer(index + cols); + q.offer(index - cols); + } + } + + public void bfs(char[][] board, int i, int j) { + int rows = board.length; + int cols = board[0].length; + + Queue q = new LinkedList(); + q.offer(i * cols + j); + + while (!q.isEmpty()) { + int index = q.poll(); + + int x = index / cols; + int y = index % cols; + + if (board[x][y] != 'O') { + continue; + } + + board[x][y] = 'B'; + if (y < cols - 1) { + q.offer(index + 1); + } + + if (y > 0) { + q.offer(index - 1); + } + + if (x > 0) { + q.offer(index - cols); + } + + if (x < rows - 1) { + q.offer(index + cols); + } + } + } +} \ No newline at end of file From d62acf04d24f6638bfa86d11560f2c572b4437b5 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 29 Nov 2014 17:59:57 -0800 Subject: [PATCH 218/319] hascycle --- list/HasCycle.java | 35 ++++++++++++++++ list/RotateList.java | 10 ++++- list/RotateRight.java | 92 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 list/HasCycle.java create mode 100644 list/RotateRight.java diff --git a/list/HasCycle.java b/list/HasCycle.java new file mode 100644 index 0000000..44ca454 --- /dev/null +++ b/list/HasCycle.java @@ -0,0 +1,35 @@ +package Algorithms.list; + +import Algorithms.algorithm.others.ListNode; + +/** + * Definition for singly-linked list. + * class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class HasCycle { + public boolean hasCycle(ListNode head) { + if (head == null) { + return false; + } + + ListNode slow = head; + ListNode fast = head; + + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + if (slow == fast) { + return true; + } + } + + return false; + } +} \ No newline at end of file diff --git a/list/RotateList.java b/list/RotateList.java index 3178d50..c674ef1 100644 --- a/list/RotateList.java +++ b/list/RotateList.java @@ -14,7 +14,13 @@ * } */ public class RotateList { - public ListNode rotateRight(ListNode head, int n) { + public static void main(String[] strs) { + ListNode node1 = new ListNode(1); + ListNode ret = rotateRight(node1, 0); + System.out.println(ret.toString()); + } + + public static ListNode rotateRight(ListNode head, int n) { if (head == null) { return null; } @@ -51,7 +57,7 @@ public ListNode rotateRight(ListNode head, int n) { } // get the list lenght. - public int getlen(ListNode head) { + public static int getlen(ListNode head) { int len = 0; while (head != null) { len++; diff --git a/list/RotateRight.java b/list/RotateRight.java new file mode 100644 index 0000000..14c996a --- /dev/null +++ b/list/RotateRight.java @@ -0,0 +1,92 @@ +package Algorithms.list; + +import Algorithms.algorithm.others.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class RotateRight { + // Solution 1: + public ListNode rotateRight1(ListNode head, int n) { + if (head == null) { + return head; + } + + int len = getLen(head); + + // 不需要重复地rotate. + n = n % len; + + if (n == 0) { + return head; + } + + ListNode end = head; + while (n > 0) { + end = end.next; + n--; + } + + ListNode pre = head; + while (end.next != null) { + pre = pre.next; + end = end.next; + } + + ListNode headNew = pre.next; + end.next = head; + pre.next = null; + + return headNew; + } + + public int getLen(ListNode head) { + int len = 0; + while (head != null) { + len++; + head = head.next; + } + return len; + } + + // Solution 2: 使用dummynode. + public ListNode rotateRight(ListNode head, int n) { + if (head == null) { + return head; + } + + int len = getLen(head); + + // 不需要重复地rotate. + n = n % len; + + ListNode dummy = new ListNode(0); + dummy.next = head; + + ListNode end = dummy; + while (n > 0) { + end = end.next; + n--; + } + + ListNode pre = dummy; + while (end.next != null) { + pre = pre.next; + end = end.next; + } + + end.next = dummy.next; + ListNode headNew = pre.next; + pre.next = null; + + return headNew; + } +} \ No newline at end of file From 562bc6283ab794976d05822e082822f7b21b3ff2 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 2 Dec 2014 02:27:25 -0800 Subject: [PATCH 219/319] sort --- array/FindMedianSortedArrays.java | 62 +++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 array/FindMedianSortedArrays.java diff --git a/array/FindMedianSortedArrays.java b/array/FindMedianSortedArrays.java new file mode 100644 index 0000000..3d13baa --- /dev/null +++ b/array/FindMedianSortedArrays.java @@ -0,0 +1,62 @@ +package Algorithms.array; + +public class FindMedianSortedArrays { + public static void main(String[] strs) { + int A[] = {100000}; + int B[] = {100001}; + + System.out.println(findMedianSortedArrays(A, B)); + } + + public static double findMedianSortedArrays(int A[], int B[]) { + if (A == null || B == null) { + return 0; + } + + int len = A.length + B.length; + + double ret = 0; + // 偶数个元素 + if (len % 2 == 0) { + ret = (findKth(A, B, 0, 0, len / 2) + findKth(A, B, 0, 0, len / 2 + 1)) / (double)2.0; + } else { + // 奇数个元素 + ret = findKth(A, B, 0, 0, len / 2 + 1); + } + + return ret; + } + + // Find the Kth large number. + public static int findKth(int A[], int B[], int indexA, int indexB, int k) { + int lenA = A.length; + int lenB = B.length; + + if (indexA >= lenA) { + return B[indexB + k - 1]; + } else if (indexB >= lenB) { + return A[indexA + k - 1]; + } + + // Base Case, pay attention. 在这里必须要退出。因为k = 1的时候,不可能再分了。 + if (k == 1) { + return Math.min(A[indexA], B[indexB]); + } + + // -1是因为索引本身是从0开始的。而前k大元素含有k个元素。 + int mid = k / 2 - 1; + + // 注意,越界条件是 >= lenA. 怎么老是犯这个错误。。 + int keyA = indexA + mid >= lenA ? Integer.MAX_VALUE: A[indexA + mid]; + int keyB = indexB + mid >= lenB ? Integer.MAX_VALUE: B[indexB + mid]; + + // 因为丢弃了k / 2个元素 + int kNew = k - k / 2; + + if (keyA < keyB) { + return findKth(A, B, indexA + k / 2, indexB, kNew); + } else { + return findKth(A, B, indexA, indexB + k / 2, kNew); + } + } +} From 4d24b2e86f6906fdad469b4ce9b07bd823bb1463 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 3 Dec 2014 01:05:01 -0800 Subject: [PATCH 220/319] reverse word --- array/SpiralOrder_1201.java | 53 +++++++++++++++++++++++++++++++++++++ string/ReverseWords.java | 38 ++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 array/SpiralOrder_1201.java create mode 100644 string/ReverseWords.java diff --git a/array/SpiralOrder_1201.java b/array/SpiralOrder_1201.java new file mode 100644 index 0000000..422da10 --- /dev/null +++ b/array/SpiralOrder_1201.java @@ -0,0 +1,53 @@ +package Algorithms.array; + +import java.util.ArrayList; +import java.util.List; + +public class SpiralOrder_1201 { + public List spiralOrder(int[][] matrix) { + List ret = new ArrayList(); + if (matrix == null ||matrix.length == 0) { + // 注意在非法的时候,应该返回空解,而不是一个NULL值 + return ret; + } + + // Record how many rows and cols we still have. + int rows = matrix.length; + int cols = matrix[0].length; + + // The four coners. + int top = 0; + int left = 0; + int bottom = rows - 1; + int right = cols - 1; + + // every time we go through two rows and two cols. + for (; rows > 0 && cols > 0; rows -= 2, cols -= 2, top++, left++, bottom--, right--) { + // the first line. + for (int i = left; i <= right; i++) { + ret.add(matrix[top][i]); + } + + // the right column. + for (int i = top + 1; i < bottom; i++) { + ret.add(matrix[i][right]); + } + + // the down line; + if (rows > 1) { + for (int j = right; j >= left; j--) { + ret.add(matrix[bottom][j]); + } + } + + // the left column. + if (cols > 1) { + for (int i = bottom - 1; i > top; i --) { + ret.add(matrix[i][left]); + } + } + } + + return ret; + } +} \ No newline at end of file diff --git a/string/ReverseWords.java b/string/ReverseWords.java new file mode 100644 index 0000000..67e558f --- /dev/null +++ b/string/ReverseWords.java @@ -0,0 +1,38 @@ +package Algorithms.string; + +public class ReverseWords { + public static void main(String[] strs) { + reverseWords(" I love cmu "); + } + + /** + * @param s : A string + * @return : A string + */ + public static String reverseWords(String s) { + // write your code + if (s == null) { + return null; + } + + StringBuilder sb = new StringBuilder(); + + // remove the leading and the tail space. + //String sTrim = s.trim(); + String[] strs = s.split("\\s+"); + for (int i = strs.length - 1; i >= 0; i--) { + System.out.println("word:" + strs[i]); + if (strs[i].equals("")) { + continue; + } + + sb.append(strs[i]); + if (i != 0) { + sb.append(" "); + } + } + + return sb.toString(); + } +} + From e61df9c33325f9961c75ca34a87fd0a30be421b1 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 3 Dec 2014 01:07:03 -0800 Subject: [PATCH 221/319] 2nd sol --- string/ReverseWords.java | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/string/ReverseWords.java b/string/ReverseWords.java index 67e558f..dbbfe6e 100644 --- a/string/ReverseWords.java +++ b/string/ReverseWords.java @@ -34,5 +34,30 @@ public static String reverseWords(String s) { return sb.toString(); } + + /** + * @param s : A string + * @return : A string + */ + public String reverseWords1(String s) { + // write your code + if (s == null) { + return null; + } + + StringBuilder sb = new StringBuilder(); + + // remove the leading and the tail space. + String sTrim = s.trim(); + String strs[] = sTrim.split("\\s+"); + for (int i = strs.length - 1; i >= 0; i--) { + sb.append(strs[i]); + if (i != 0) { + sb.append(" "); + } + } + + return sb.toString(); + } } From 150fab43b3a663bc839b30e90652afd87587d69a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 3 Dec 2014 02:43:13 -0800 Subject: [PATCH 222/319] combination --- combination/Combine_1203.java | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 combination/Combine_1203.java diff --git a/combination/Combine_1203.java b/combination/Combine_1203.java new file mode 100644 index 0000000..eeda5b6 --- /dev/null +++ b/combination/Combine_1203.java @@ -0,0 +1,55 @@ +package Algorithms.combination; +import java.util.ArrayList; +import java.util.List; + +public class Combine_1203 { + public List> combine(int n, int k) { + List> ret = new ArrayList>(); + if (k == 0) { + ret.add(new ArrayList()); + return ret; + } + + // 注意:start应该从1开始。因为我们的数字是1 + dfs(n, k, new ArrayList(), ret, 1); + return ret; + } + + // SOLUTION 1: + // 注意,因为求的是组合,所以我们要考虑一下顺序问题,只需要考虑升序。这样的话就不会有重复的 + // 的组合。 + public void dfs1(int n, int k, List path, List> ret, int start) { + if (path.size() == k) { + ret.add(new ArrayList(path)); + return; + } + + // 注意这里的条件i <= n 取n也是合法的! + // Example: + for (int i = start; i <= n; i++) { + path.add(i); + + // 注意,最后一个参数是i + 1,不是start + 1!! + dfs(n, k, path, ret, i + 1); + path.remove(path.size() - 1); + } + } + + // SOLUTION 2: + public void dfs(int n, int k, List path, List> ret, int start) { + if (0 == k) { + ret.add(new ArrayList(path)); + return; + } + + // 注意这里的条件i <= n 取n也是合法的! + // Example: + for (int i = start; i <= (n - k + 1); i++) { + path.add(i); + + // 注意,最后一个参数是i + 1,不是start + 1!! + dfs(n, k - 1, path, ret, i + 1); + path.remove(path.size() - 1); + } + } +} \ No newline at end of file From a8282f906bed8ec8f1649e6de231d674a4baf133 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 3 Dec 2014 02:59:02 -0800 Subject: [PATCH 223/319] per --- dfs/Permute.java | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 dfs/Permute.java diff --git a/dfs/Permute.java b/dfs/Permute.java new file mode 100644 index 0000000..9fd4254 --- /dev/null +++ b/dfs/Permute.java @@ -0,0 +1,34 @@ +package Algorithms.dfs; + +import java.util.ArrayList; +import java.util.List; + +public class Permute { + public List> permute(int[] num) { + List> ret = new ArrayList>(); + if (num == null || num.length == 0) { + return ret; + } + + dfs(num, new ArrayList(), ret); + return ret; + } + + public void dfs(int[] num, List path, List> ret) { + int len = num.length; + if (path.size() == len) { + ret.add(new ArrayList(path)); + return; + } + + for (int i = 0; i < len; i++) { + if (path.contains(num[i])) { + continue; + } + + path.add(num[i]); + dfs(num, path, ret); + path.remove(path.size() - 1); + } + } +} \ No newline at end of file From 8bf2e2a0e5673869e979814235a91b633f87efea Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 3 Dec 2014 03:55:19 -0800 Subject: [PATCH 224/319] permutation 2 --- permutation/Permutation.java | 4 +-- permutation/PermuteUnique.java | 45 ++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 permutation/PermuteUnique.java diff --git a/permutation/Permutation.java b/permutation/Permutation.java index dfbd401..be7cc87 100644 --- a/permutation/Permutation.java +++ b/permutation/Permutation.java @@ -13,7 +13,7 @@ public static void main(String[] strs) { permute(num); System.out - .println("Computing time with ArrayDeque used as Queue/Deque: " + .println("Computing time with HASHMAP: " + timer1.elapsedTime() + " millisec."); System.out.printf("Test size:%d \n", num.length); @@ -22,7 +22,7 @@ public static void main(String[] strs) { permute2(num); System.out - .println("Computing time with ArrayDeque used as Queue/Deque: " + .println("Computing time with list: " + timer2.elapsedTime() + " millisec."); } diff --git a/permutation/PermuteUnique.java b/permutation/PermuteUnique.java new file mode 100644 index 0000000..59b68ea --- /dev/null +++ b/permutation/PermuteUnique.java @@ -0,0 +1,45 @@ +package Algorithms.permutation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class PermuteUnique { + public List> permuteUnique(int[] num) { + List> ret = new ArrayList>(); + if (num == null || num.length == 0) { + return ret; + } + + // For deal with the duplicate solution, we should sort it. + Arrays.sort(num); + boolean[] visit = new boolean[num.length]; + + dfs(num, new ArrayList(), ret, visit); + + return ret; + } + + public void dfs(int[] num, ArrayList path, List> ret, boolean[] visit) { + int len = num.length; + if (path.size() == len) { + ret.add(new ArrayList(path)); + return; + } + + for (int i = 0; i < len; i++) { + // 只能连续地选,这样就可以避免生成重复的solution. + // 例子:1 2 3 4 4 4 5 6 7 8 + // 444这个的选法只能:4, 44, 444连续这三种选法 + if (visit[i] || (i != 0 && visit[i - 1] && num[i] == num[i - 1])) { + continue; + } + + // 递归以及回溯 + visit[i] = true; + path.add(num[i]); + dfs(num, path, ret, visit); + path.remove(path.size() - 1); + visit[i] = false; + } + } +} \ No newline at end of file From 60db8b5c3a5958680c2d328c89237b6e42ee9dc4 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 3 Dec 2014 04:08:31 -0800 Subject: [PATCH 225/319] phone phone --- combination/LetterCombinations.java | 35 +++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 combination/LetterCombinations.java diff --git a/combination/LetterCombinations.java b/combination/LetterCombinations.java new file mode 100644 index 0000000..95ea2bc --- /dev/null +++ b/combination/LetterCombinations.java @@ -0,0 +1,35 @@ +package Algorithms.combination; + +import java.util.ArrayList; +import java.util.List; + +public class LetterCombinations { + String[] map = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; + + public List letterCombinations(String digits) { + List ret = new ArrayList(); + if (digits == null) { + return ret; + } + + dfs(digits, new StringBuilder(), ret, 0); + return ret; + } + + public void dfs(String digits, StringBuilder sb, List ret, int index) { + int len = digits.length(); + if (index == len) { + ret.add(sb.toString()); + return; + } + + // get the possiable selections. + String s = map[digits.charAt(index) - '0']; + for (int i = 0; i < s.length(); i++) { + sb.append(s.charAt(i)); + dfs(digits, sb, ret, index + 1); + sb.deleteCharAt(sb.length() - 1); + } + } + +} \ No newline at end of file From 290e600147d73e7aca538f4e0ed4959b4ad25442 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 3 Dec 2014 04:32:46 -0800 Subject: [PATCH 226/319] com --- combination/CombinationSum_1203.java | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 combination/CombinationSum_1203.java diff --git a/combination/CombinationSum_1203.java b/combination/CombinationSum_1203.java new file mode 100644 index 0000000..91d469f --- /dev/null +++ b/combination/CombinationSum_1203.java @@ -0,0 +1,43 @@ +package Algorithms.combination; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CombinationSum_1203 { + public List> combinationSum(int[] candidates, int target) { + List> ret = new ArrayList>(); + if (candidates == null || candidates.length == 0) { + return ret; + } + + // Sort to avoid duplicate solutions. + Arrays.sort(candidates); + + dfs(candidates, target, new ArrayList(), ret, 0); + return ret; + } + + public void dfs(int[] candidates, int target, List path, List> ret, int index) { + if (target < 0) { + return; + } + + if (target == 0) { + ret.add(new ArrayList(path)); + return; + } + + // i 的起始值是跟排列的最主要区别。因为与顺序无关,所以我们必须只能是升序,也就是说下一个取值只能是i本身 + // 或是i的下一个。 + // 但是排列的话,可以再取前同的。1, 2 与2 1是不同的排列,但是同一个组合 + for (int i = index; i < candidates.length; i++) { + int num = candidates[i]; + path.add(num); + + // 注意,最后的参数是i,不是index!! + dfs(candidates, target - num, path, ret, i); + path.remove(path.size() - 1); + } + } +} \ No newline at end of file From 8682fc7fcf75af16285643f9706fdf6a179b3515 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 3 Dec 2014 05:28:35 -0800 Subject: [PATCH 227/319] com sum2 --- combination/CombinationSum2_1203.java | 68 +++++++++++++++++++++++++++ dfs/SolveNQueens.java | 8 +++- permutation/PermuteUnique.java | 29 +++++++++++- 3 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 combination/CombinationSum2_1203.java diff --git a/combination/CombinationSum2_1203.java b/combination/CombinationSum2_1203.java new file mode 100644 index 0000000..cb4c4cc --- /dev/null +++ b/combination/CombinationSum2_1203.java @@ -0,0 +1,68 @@ +package Algorithms.combination; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CombinationSum2_1203 { + public List> combinationSum2(int[] num, int target) { + List> ret = new ArrayList>(); + if (num == null || num.length == 0) { + return ret; + } + + Arrays.sort(num); + + dfs(num, target, new ArrayList(), ret, 0); + return ret; + } + + public void dfs1(int[] num, int target, ArrayList path, List> ret, int index) { + if (target == 0) { + ret.add(new ArrayList(path)); + return; + } + + if (target < 0) { + return; + } + + // 注意,这里从 i = index开始 + // 每次只取第一个,例如 123334,到了333这里,我们第一次只取第1个3,因为我们选任何一个3是对组合来说是一个解。所以只 + // 第一次取就好了。 + int pre = -1; + for (int i = index; i < num.length; i++) { + int n = num[i]; + if (n == pre) { + continue; + } + pre = n; + path.add(n); + dfs(num, target - n, path, ret, i + 1); + path.remove(path.size() - 1); + } + } + + public void dfs(int[] num, int target, ArrayList path, List> ret, int index) { + if (target == 0) { + ret.add(new ArrayList(path)); + return; + } + + if (target < 0) { + return; + } + + // 注意,这里从 i = index开始 + // 每次只取第一个,例如 123334,到了333这里,我们第一次只取第1个3,因为我们选任何一个3是对组合来说是一个解。所以只 + // 第一次取就好了。 + for (int i = index; i < num.length; i++) { + int n = num[i]; + if (i != index && n == num[i - 1]) { + continue; + } + path.add(n); + dfs(num, target - n, path, ret, i + 1); + path.remove(path.size() - 1); + } + } +} \ No newline at end of file diff --git a/dfs/SolveNQueens.java b/dfs/SolveNQueens.java index 3bd4ca0..dc6d6f6 100644 --- a/dfs/SolveNQueens.java +++ b/dfs/SolveNQueens.java @@ -9,11 +9,17 @@ public static void main(String[] strs) { for (String[] strss: list) { for (String s: strss) { - System.out.println(s); + //System.out.println(s); } } + Long ret = Long.MAX_VALUE; + int a = Integer.MAX_VALUE; + if (ret == a) { + System.out.println(true); + } + //System.out.println(solveNQueens(4).toString()); } diff --git a/permutation/PermuteUnique.java b/permutation/PermuteUnique.java index 59b68ea..50a0100 100644 --- a/permutation/PermuteUnique.java +++ b/permutation/PermuteUnique.java @@ -19,7 +19,7 @@ public List> permuteUnique(int[] num) { return ret; } - public void dfs(int[] num, ArrayList path, List> ret, boolean[] visit) { + public void dfs1(int[] num, ArrayList path, List> ret, boolean[] visit) { int len = num.length; if (path.size() == len) { ret.add(new ArrayList(path)); @@ -42,4 +42,31 @@ public void dfs(int[] num, ArrayList path, List> ret, boo visit[i] = false; } } + + // SOLUTION 2: + // 使用一个pre来记录。只取第一个可以取的位置 + public void dfs(int[] num, ArrayList path, List> ret, boolean[] visit) { + int len = num.length; + if (path.size() == len) { + ret.add(new ArrayList(path)); + return; + } + + long pre = Long.MIN_VALUE; + for (int i = 0; i < len; i++) { + int n = num[i]; + // 只取第一个可取的位置,因为别的位置取到的也没有区别 + if (visit[i] || pre == n) { + continue; + } + pre = n; + + // 递归以及回溯 + visit[i] = true; + path.add(n); + dfs(num, path, ret, visit); + path.remove(path.size() - 1); + visit[i] = false; + } + } } \ No newline at end of file From 24648a0423fc279bd46f0c4e85efa43bbd28e9ab Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 3 Dec 2014 05:49:26 -0800 Subject: [PATCH 228/319] tree --- tree/IsSameTree1.java | 74 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 tree/IsSameTree1.java diff --git a/tree/IsSameTree1.java b/tree/IsSameTree1.java new file mode 100644 index 0000000..7aad317 --- /dev/null +++ b/tree/IsSameTree1.java @@ -0,0 +1,74 @@ +package Algorithms.tree; + +import java.util.Stack; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class IsSameTree1 { + // solution 1: + public boolean isSameTree1(TreeNode p, TreeNode q) { + if (p == null && q == null) { + return true; + } + + if (p == null || q == null) { + return false; + } + + return p.val == q.val && + isSameTree(p.left, q.left) && + isSameTree(p.right, q.right); + } + + // Solution 2: + public boolean isSameTree(TreeNode p, TreeNode q) { + if (p == null && q == null) { + return true; + } + + if (p == null || q == null) { + return false; + } + + Stack s1 = new Stack(); + Stack s2 = new Stack(); + + s1.push(p); + s2.push(q); + + while (!s1.isEmpty() && !s2.isEmpty()) { + TreeNode cur1 = s1.pop(); + TreeNode cur2 = s2.pop(); + + // 弹出的节点的值必须相等 + if (cur1.val != cur2.val) { + return false; + } + + // tree1的right节点,tree2的right节点,可以同时不为空,也可以同时为空,否则返回false. + if (cur1.left != null && cur2.left != null) { + s1.push(cur1.left); + s2.push(cur2.left); + } else if (!(cur1.left == null && cur2.left == null)) { + return false; + } + + // tree1的左节点,tree2的left节点,可以同时不为空,也可以同时为空,否则返回false. + if (cur1.right != null && cur2.right != null) { + s1.push(cur1.right); + s2.push(cur2.right); + } else if (!(cur1.right == null && cur2.right == null)) { + return false; + } + } + + return true; + } +} \ No newline at end of file From 5ac27116c310dc1b7fc4202555b7699c313169c1 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 3 Dec 2014 06:11:26 -0800 Subject: [PATCH 229/319] tree --- tree/IsSymmetric.java | 80 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 tree/IsSymmetric.java diff --git a/tree/IsSymmetric.java b/tree/IsSymmetric.java new file mode 100644 index 0000000..c9413dc --- /dev/null +++ b/tree/IsSymmetric.java @@ -0,0 +1,80 @@ +package Algorithms.tree; + +import java.util.Stack; + +public class IsSymmetric { + /** + * Definition for binary tree public class TreeNode { int val; TreeNode + * left; TreeNode right; TreeNode(int x) { val = x; } } + */ + // solution 1: + public boolean isSymmetric(TreeNode root) { + if (root == null) { + return true; + } + + return isSymmetricTree(root.left, root.right); + } + + /* + * 判断两个树是否互相镜像 (1) 根必须同时为空,或是同时不为空 + * + * 如果根不为空: (1).根的值一样 (2).r1的左树是r2的右树的镜像 (3).r1的右树是r2的左树的镜像 + */ + public boolean isSymmetricTree1(TreeNode root1, TreeNode root2) { + if (root1 == null && root2 == null) { + return true; + } + + if (root1 == null || root2 == null) { + return false; + } + + return root1.val == root2.val + && isSymmetricTree(root1.left, root2.right) + && isSymmetricTree(root1.right, root2.left); + } + + // solution 2: + public boolean isSymmetricTree(TreeNode root1, TreeNode root2) { + if (root1 == null && root2 == null) { + return true; + } + + if (root1 == null || root2 == null) { + return false; + } + + Stack s1 = new Stack(); + Stack s2 = new Stack(); + + // 一定记得初始化 + s1.push(root1); + s2.push(root2); + + while (!s1.isEmpty() && !s2.isEmpty()) { + TreeNode cur1 = s1.pop(); + TreeNode cur2 = s2.pop(); + + if (cur1.val != cur2.val) { + return false; + } + + if (cur1.left != null && cur2.right != null) { + s1.push(cur1.left); + s2.push(cur2.right); + } else if (!(cur1.left == null && cur2.right == null)) { + return false; + } + + if (cur1.right != null && cur2.left != null) { + s1.push(cur1.right); + s2.push(cur2.left); + } else if (!(cur1.right == null && cur2.left == null)) { + return false; + } + } + + return true; + } +} \ No newline at end of file From 6e751b5dc220dc5ed6a4617c58978730d78964b6 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 3 Dec 2014 06:29:27 -0800 Subject: [PATCH 230/319] tree --- tree/PreorderTraversal.java | 60 +++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 tree/PreorderTraversal.java diff --git a/tree/PreorderTraversal.java b/tree/PreorderTraversal.java new file mode 100644 index 0000000..9dabc72 --- /dev/null +++ b/tree/PreorderTraversal.java @@ -0,0 +1,60 @@ +package Algorithms.tree; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class PreorderTraversal { + // sol1: + public List preorderTraversal1(TreeNode root) { + List ret = new ArrayList(); + + rec(root, ret); + return ret; + } + + public void rec(TreeNode root, List ret) { + if (root == null) { + return; + } + + ret.add(root.val); + rec(root.left, ret); + rec(root.right, ret); + } + + public List preorderTraversal(TreeNode root) { + List ret = new ArrayList(); + + if (root == null) { + return ret; + } + + Stack s = new Stack(); + s.push(root); + + while (!s.isEmpty()) { + TreeNode cur = s.pop(); + ret.add(cur.val); + + if (cur.right != null) { + s.push(cur.right); + } + + if (cur.left != null) { + s.push(cur.left); + } + } + + return ret; + } +} \ No newline at end of file From d84764f5272e019bcb31e8f5500aacae78e8ce65 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 4 Dec 2014 03:04:26 -0800 Subject: [PATCH 231/319] list --- list/Partition.java | 57 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 list/Partition.java diff --git a/list/Partition.java b/list/Partition.java new file mode 100644 index 0000000..b7a65c3 --- /dev/null +++ b/list/Partition.java @@ -0,0 +1,57 @@ +package Algorithms.list; + +import Algorithms.algorithm.others.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class Partition { + public ListNode partition(ListNode head, int x) { + if (head == null) { + return null; + } + + ListNode dummy = new ListNode(0); + dummy.next = head; + + ListNode pre = dummy; + ListNode cur = head; + + // Record the big list. + ListNode bigDummy = new ListNode(0); + ListNode bigTail = bigDummy; + + while (cur != null) { + if (cur.val >= x) { + // Unlink the cur; + pre.next = cur.next; + + // Add the cur to the tail of the new link. + bigTail.next = cur; + cur.next = null; + + // Refresh the bigTail. + bigTail = cur; + + // 移除了一个元素的时候,pre不需要修改,因为cur已经移动到下一个位置了。 + } else { + pre = pre.next; + } + + cur = pre.next; + } + + // Link the Big linklist to the smaller one. + pre.next = bigDummy.next; + + return dummy.next; + } +} \ No newline at end of file From 9649dc8ba90ccccb369917912e8534788c38cd79 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 4 Dec 2014 05:06:04 -0800 Subject: [PATCH 232/319] sort --- sort/SortList.java | 255 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 sort/SortList.java diff --git a/sort/SortList.java b/sort/SortList.java new file mode 100644 index 0000000..89619ea --- /dev/null +++ b/sort/SortList.java @@ -0,0 +1,255 @@ +package Algorithms.sort; + +import Algorithms.algorithm.others.ListNode; + +/** + * Definition for singly-linked list. + * class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class SortList { + public static void main(String[] strs) { + ListNode n1 = new ListNode(2); + ListNode n2 = new ListNode(18); + ListNode n3 = new ListNode(3); + ListNode n4 = new ListNode(54); + ListNode n5 = new ListNode(6); + ListNode n6 = new ListNode(90); + ListNode n7 = new ListNode(2); + ListNode n8 = new ListNode(1); + ListNode n9 = new ListNode(19); + ListNode n10 = new ListNode(30); + + + n1.next = n2; + n2.next = n3; + n3.next = n4; + n4.next = n5; + n5.next = n6; + n6.next = n7; + n7.next = n8; + n8.next = n9; + n9.next = n10; + n10.next = null; + + ListNode ret = sortList(n1); + System.out.println(ret.toString()); + } + + public static ListNode sortList1(ListNode head) { + // Nodes should be more than 2. + if (head == null || head.next == null) { + return head; + } + + // get the mid node. + ListNode midPre = getMidPre(head); + + // Cut the two list. + ListNode right = midPre.next; + midPre.next = null; + + // Sort the left side and the right side. + ListNode left = sortList(head); + right = sortList(right); + + // Merge the two sides together. + return merge(left, right); + } + + // get the pre node before mid. + public static ListNode getMidPre1(ListNode head) { + ListNode slow = head; + ListNode fast = head; + + while (fast != null && fast.next != null && fast.next.next != null) { + slow = slow.next; + fast = fast.next.next; + } + + return slow; + } + + // get the pre node before mid. + public static ListNode getMidPre(ListNode head) { + ListNode slow = head; + + // fast提前一点儿。这样就可以得到前一个节点喽。 + ListNode fast = head.next; + + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + + return slow; + } + + public static ListNode merge(ListNode head1, ListNode head2) { + ListNode dummy = new ListNode(0); + ListNode cur = dummy; + + while (head1 != null && head2 != null) { + if (head1.val < head2.val) { + cur.next = head1; + head1 = head1.next; + } else { + cur.next = head2; + head2 = head2.next; + } + + cur = cur.next; + } + + if (head1 != null) { + cur.next = head1; + } else { + cur.next = head2; + } + + return dummy.next; + } + + /* + The Solution 2: + Quick Sort. + */ + public static ListNode sortList(ListNode head) { + if (head == null) { + return null; + } + + // Sort the list from 0 to len - 1 + return quickSort(head); + } + + // The quick sort algorithm + + // All the elements are the same! + public static boolean isDuplicate(ListNode head) { + while (head != null) { + if (head.next != null && head.next.val != head.val) { + return false; + } + + head = head.next; + } + + return true; + } + + public static ListNode quickSort(ListNode head) { + if (head == null) { + return null; + } + + // 如果整个链是重复的,直接跳过。 + if (isDuplicate(head)) { + return head; + } + + // Use the head node to be the pivot. + ListNode headNew = partition(head, head.val); + + // Find the pre position of the pivoit. + ListNode cur = headNew; + + ListNode dummy = new ListNode(0); + dummy.next = headNew; + + ListNode pre = dummy; + + // Find the pre node and the position of the piviot. + while (cur != null) { + if (cur.val == head.val) { + break; + } + + // move forward. + cur = cur.next; + pre = pre.next; + } + + // Cut the link to be three parts. + pre.next = null; + + // Get the left link; + ListNode left = dummy.next; + + // Get the right link. + ListNode right = cur.next; + cur.next = null; + + // Recurtion to call quick sort to sort left and right link. + left = quickSort(left); + right = quickSort(right); + + // Link the three part together. + + // Link the first part and the 2nd part. + if (left != null) { + dummy.next = left; + + // Find the tail of the left link. + while (left.next != null) { + left = left.next; + } + left.next = cur; + } else { + dummy.next = cur; + } + + cur.next = right; + + // The new head; + return dummy.next; + } + + // Return the new head; + public ListNode partition(ListNode head, int x) { + if (head == null) { + return null; + } + + ListNode dummy = new ListNode(0); + dummy.next = head; + + ListNode pre = dummy; + ListNode cur = head; + + // Record the big list. + ListNode bigDummy = new ListNode(0); + ListNode bigTail = bigDummy; + + while (cur != null) { + if (cur.val >= x) { + // Unlink the cur; + pre.next = cur.next; + + // Add the cur to the tail of the new link. + bigTail.next = cur; + cur.next = null; + + // Refresh the bigTail. + bigTail = cur; + + // 移除了一个元素的时候,pre不需要修改,因为cur已经移动到下一个位置了。 + } else { + pre = pre.next; + } + + cur = pre.next; + } + + // Link the Big linklist to the smaller one. + pre.next = bigDummy.next; + + return dummy.next; + } +} \ No newline at end of file From 672133c029d64a31cbbc27cacb677db03cc088fb Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 4 Dec 2014 18:30:54 -0800 Subject: [PATCH 233/319] list --- list/MergeKLists_1204.java | 122 +++++++++++++++++++++++++++++++++++++ list/SortList.java | 90 --------------------------- 2 files changed, 122 insertions(+), 90 deletions(-) create mode 100644 list/MergeKLists_1204.java delete mode 100644 list/SortList.java diff --git a/list/MergeKLists_1204.java b/list/MergeKLists_1204.java new file mode 100644 index 0000000..c1da6d4 --- /dev/null +++ b/list/MergeKLists_1204.java @@ -0,0 +1,122 @@ +package Algorithms.list; +import java.util.Comparator; +import java.util.List; +import java.util.PriorityQueue; + +import Algorithms.algorithm.others.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class MergeKLists_1204 { + /* + SOL 1: + 使用merge sort和分治法完成 + */ + public ListNode mergeKLists1(List lists) { + // 记得加上这个合法性判断。 + if (lists == null || lists.size() == 0) { + return null; + } + + return helper(lists, 0, lists.size() - 1); + } + + /* + l, r表示list的左右边界 + */ + public ListNode helper(List lists, int l, int r) { + if (l < r) { + int mid = l + (r - l) / 2; + + /* + 分治法。把问题分为2个更小的子问题:左边list的merge,和右边list的merge. + 再把2个生成的解合并在一起。 + */ + return merge(helper(lists, l, mid), helper(lists, mid + 1, r)); + } + + return lists.get(l); + } + + public ListNode merge(ListNode n1, ListNode n2) { + ListNode dummy = new ListNode(0); + ListNode cur = dummy; + + while (n1 != null && n2 != null) { + if (n1.val < n2.val) { + cur.next = n1; + n1 = n1.next; + } else { + cur.next = n2; + n2 = n2.next; + } + + cur = cur.next; + } + + if (n1 != null) { + cur.next = n1; + } else { + cur.next = n2; + } + + return dummy.next; + } + + /* + SOL 2: + 使用 priority Queue. + */ + public ListNode mergeKLists(List lists) { + // 记得加上这个合法性判断。 + if (lists == null || lists.size() == 0) { + return null; + } + + int size = lists.size(); + + PriorityQueue q = new PriorityQueue(size, + new Comparator() { + // 注意,此处参数用ListNode + public int compare(ListNode o1, ListNode o2) { + return o1.val - o2.val; + } + } + ); + + // Add all the head node to the priority queue. + for (ListNode node: lists) { + if (node != null) { + // Should skip the null node.s + q.offer(node); + } + } + + ListNode dummy = new ListNode(0); + ListNode tail = dummy; + + while (!q.isEmpty()) { + // get the smallest node from the queue. + ListNode cur = q.poll(); + + tail.next = cur; + tail = tail.next; + + // 将下一个节点补充进来。 + if (cur.next != null) { + q.offer(cur.next); + } + } + + return dummy.next; + } +} \ No newline at end of file diff --git a/list/SortList.java b/list/SortList.java deleted file mode 100644 index 8a7311b..0000000 --- a/list/SortList.java +++ /dev/null @@ -1,90 +0,0 @@ -package Algorithms.list; - -import Algorithms.algorithm.others.ListNode; - -/** - * Definition for singly-linked list. - * class ListNode { - * int val; - * ListNode next; - * ListNode(int x) { - * val = x; - * next = null; - * } - * } - */ -public class SortList { - public ListNode sortList(ListNode head) { - // Nodes should be more than 2. - if (head == null || head.next == null) { - return head; - } - - // get the mid node. - ListNode midPre = getMidPre(head); - - // Cut the two list. - ListNode right = midPre.next; - midPre.next = null; - - // Sort the left side and the right side. - ListNode left = sortList(head); - right = sortList(right); - - // Merge the two sides together. - return merge(left, right); - } - - // get the pre node before mid. - public ListNode getMidPre1(ListNode head) { - ListNode slow = head; - ListNode fast = head; - - while (fast != null && fast.next != null && fast.next.next != null) { - slow = slow.next; - fast = fast.next.next; - } - - return slow; - } - - // get the pre node before mid. - public ListNode getMidPre(ListNode head) { - ListNode slow = head; - - // fast提前一点儿。这样就可以得到前一个节点喽。 - ListNode fast = head.next; - - while (fast != null && fast.next != null) { - slow = slow.next; - fast = fast.next.next; - } - - return slow; - } - - public ListNode merge(ListNode head1, ListNode head2) { - ListNode dummy = new ListNode(0); - ListNode cur = dummy; - - while (head1 != null && head2 != null) { - if (head1.val < head2.val) { - cur.next = head1; - head1 = head1.next; - } else { - cur.next = head2; - head2 = head2.next; - } - - cur = cur.next; - } - - if (head1 != null) { - cur.next = head1; - } else { - cur.next = head2; - } - - return dummy.next; - } -} \ No newline at end of file From 06fd26db2ac6f33281fd398de391ff5dda66eec0 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 5 Dec 2014 11:10:20 -0800 Subject: [PATCH 234/319] memory --- dp/MinimumTotal.java | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 dp/MinimumTotal.java diff --git a/dp/MinimumTotal.java b/dp/MinimumTotal.java new file mode 100644 index 0000000..902a0eb --- /dev/null +++ b/dp/MinimumTotal.java @@ -0,0 +1,37 @@ +package Algorithms.dp; + +import java.util.List; + +public class MinimumTotal { + public int minimumTotal(List> triangle) { + if (triangle == null || triangle.size() == 0) { + return 0; + } + + int rows = triangle.size(); + int[][] mem = new int[rows][rows]; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < rows; j++) { + mem[i][j] = Integer.MAX_VALUE; + } + } + + return dfs(triangle, 0, 0, mem); + } + + public int dfs(List> triangle, int row, int col, int[][] mem) { + if (mem[row][col] != Integer.MAX_VALUE) { + return mem[row][col]; + } + + if (row == triangle.size() - 1) { + mem[row][col] = triangle.get(row).get(col); + } else { + int left = dfs(triangle, row + 1, col, mem); + int right = dfs(triangle, row + 1, col + 1, mem); + mem[row][col] = triangle.get(row).get(col) + Math.min(left, right); + } + + return mem[row][col]; + } +} \ No newline at end of file From c4d9337b461edc0b27e5790171e485444b0368ba Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 5 Dec 2014 11:52:03 -0800 Subject: [PATCH 235/319] dp --- dp/MinimumTotal.java | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/dp/MinimumTotal.java b/dp/MinimumTotal.java index 902a0eb..4399262 100644 --- a/dp/MinimumTotal.java +++ b/dp/MinimumTotal.java @@ -3,7 +3,10 @@ import java.util.List; public class MinimumTotal { - public int minimumTotal(List> triangle) { + /* + REC, SOL 1: + */ + public int minimumTotal1(List> triangle) { if (triangle == null || triangle.size() == 0) { return 0; } @@ -34,4 +37,29 @@ public int dfs(List> triangle, int row, int col, int[][] mem) { return mem[row][col]; } + + /* + DP, SOL 2: + */ + public int minimumTotal(List> triangle) { + if (triangle == null || triangle.size() == 0) { + return 0; + } + + int rows = triangle.size(); + int[] D = new int[rows]; + + for (int i = rows - 1; i >= 0; i--) { + // 注意:边界条件是 j <= i + for (int j = 0; j <= i; j++) { + if (i == rows - 1) { + D[j] = triangle.get(i).get(j); + } else { + D[j] = triangle.get(i).get(j) + Math.min(D[j], D[j + 1]); + } + } + } + + return D[0]; + } } \ No newline at end of file From 3c7c7315f070e1760d521adc396a9a48961b682e Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 6 Dec 2014 04:50:51 -0800 Subject: [PATCH 236/319] min --- dp/MinCut_1206.java | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 dp/MinCut_1206.java diff --git a/dp/MinCut_1206.java b/dp/MinCut_1206.java new file mode 100644 index 0000000..a30e33c --- /dev/null +++ b/dp/MinCut_1206.java @@ -0,0 +1,5 @@ +package Algorithms.dp; + +public class MinCut_1206 { + +} From a78311164e279a5f512694b211a2c6c93deef9b2 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 6 Dec 2014 05:48:13 -0800 Subject: [PATCH 237/319] greedy --- algorithm/dp/LongestPalindrome_dp1.java | 15 ++++++-------- greedy/Jump.java | 26 +++++++++++++++++++++++++ sort/SortList.java | 2 +- string/LongestValidParentheses.java | 2 +- tree/TreeLinkNode.java | 2 +- 5 files changed, 35 insertions(+), 12 deletions(-) create mode 100644 greedy/Jump.java diff --git a/algorithm/dp/LongestPalindrome_dp1.java b/algorithm/dp/LongestPalindrome_dp1.java index b1800ef..239606f 100644 --- a/algorithm/dp/LongestPalindrome_dp1.java +++ b/algorithm/dp/LongestPalindrome_dp1.java @@ -15,7 +15,7 @@ public static String longestPalindrome1(String s) { int len = s.length(); // Record i-j is a palindrome. - boolean[][] D = new int[len][len]; + boolean[][] D = new boolean[len][len]; for (int i = 0; i < len; i++) { for (int j = 0; j < len; j++) { D[i][j] = false; @@ -25,9 +25,6 @@ public static String longestPalindrome1(String s) { int max = 0; int retB = 0; int retE = 0; - // 这样写的目的是,从前往后扫描时,被记录的DP值可以被复用 - // 因为D[i][j] 要用到i + 1, j - 1,所以每一次计算j时,把j对应的i全部计算完,这样 - // 下一次计算i,j的时候,可以有i+1, j-1可以用。 for (int j = 0; j < len; j++) { for (int i = 0; i <= j; i++) { if (s.charAt(i) == s.charAt(j) @@ -48,8 +45,8 @@ public static String longestPalindrome1(String s) { return s.substring(retB, retE + 1); } - // solution 2: 中心展开法。从头扫到尾部,每一个字符以它为中心向两边扩展,找最长回文。 - // 复杂度为N^2 并且是inplace,空间复杂度O(1) + // solution 2: ��������������������������������������������������������������������������������������������������������� + // ������������N^2 ���������inplace������������������O(1) public static String longestPalindrome(String s) { if (s == null) { return null; @@ -65,14 +62,14 @@ public static String longestPalindrome(String s) { String ret = ""; for (int i = 0; i < len; i++) { - // 考虑奇数字符串 + // ��������������������� String s1 = expandAround(s, i, i); if (s1.length() > max) { ret = s1; max = s1.length(); } - // 考虑偶数长度的字符串 + // ������������������������������ String s2 = expandAround(s, i, i); if (s2.length() > max) { ret = s2; @@ -95,7 +92,7 @@ public static String expandAround(String s, int c1, int c2) { c2--; } - // 注意,根据 substring的定义,c2不要减1 + // ��������������� substring������������c2���������1 return s.substring(c1 + 1, c2); } } diff --git a/greedy/Jump.java b/greedy/Jump.java new file mode 100644 index 0000000..ac7440a --- /dev/null +++ b/greedy/Jump.java @@ -0,0 +1,26 @@ +package Algorithms.greedy; + +public class Jump { + public int jump(int[] A) { + if (A == null || A.length == 0) { + return 0; + } + + int len = A.length; + + int sum = 0; + + int des = len - 1; + while (des > 0) { // destination index + for (int i = 0; i < des; i++) { // 不断向前移动dest + if (A[i] + i >= des) { // 说明从i位置能1步到达dest的位置 + sum++; + des = i; // 更新dest位置,下一步就是计算要几步能调到当前i的位置 + break; // 没必要再继续找,因为越早找到的i肯定越靠前,说明这一跳的距离越远 + } + } + } + + return sum; + } +} \ No newline at end of file diff --git a/sort/SortList.java b/sort/SortList.java index 89619ea..4243acd 100644 --- a/sort/SortList.java +++ b/sort/SortList.java @@ -212,7 +212,7 @@ public static ListNode quickSort(ListNode head) { } // Return the new head; - public ListNode partition(ListNode head, int x) { + public static ListNode partition(ListNode head, int x) { if (head == null) { return null; } diff --git a/string/LongestValidParentheses.java b/string/LongestValidParentheses.java index c41b7b6..d113a02 100644 --- a/string/LongestValidParentheses.java +++ b/string/LongestValidParentheses.java @@ -7,7 +7,7 @@ public static void main(String[] strs) { System.out.println(longestValidParentheses("(()()())")); } - public int longestValidParentheses(String s) { + public static int longestValidParentheses(String s) { if (s == null) { return 0; } diff --git a/tree/TreeLinkNode.java b/tree/TreeLinkNode.java index dd3a909..ab63f36 100644 --- a/tree/TreeLinkNode.java +++ b/tree/TreeLinkNode.java @@ -3,6 +3,6 @@ public class TreeLinkNode { int val; public TreeLinkNode left; public TreeLinkNode right; - TreeLinkNode next; + public TreeLinkNode next; public TreeLinkNode(int x) { val = x; } } \ No newline at end of file From 17bfdcf3c60a95c00e7916cd8bc208fea1bcb498 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 6 Dec 2014 05:56:12 -0800 Subject: [PATCH 238/319] jump --- greedy/Jump.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/greedy/Jump.java b/greedy/Jump.java index ac7440a..b17abb4 100644 --- a/greedy/Jump.java +++ b/greedy/Jump.java @@ -1,7 +1,12 @@ package Algorithms.greedy; public class Jump { - public int jump(int[] A) { + public static void main(String[] strs) { + int[] A = {2, 3, 1, 1, 4}; + System.out.println(jump(A)); + } + + public static int jump(int[] A) { if (A == null || A.length == 0) { return 0; } @@ -16,7 +21,9 @@ public int jump(int[] A) { if (A[i] + i >= des) { // 说明从i位置能1步到达dest的位置 sum++; des = i; // 更新dest位置,下一步就是计算要几步能调到当前i的位置 - break; // 没必要再继续找,因为越早找到的i肯定越靠前,说明这一跳的距离越远 + //break; // 没必要再继续找,因为越早找到的i肯定越靠前,说明这一跳的距离越远 + System.out.println("sum:" + sum); + System.out.println("des:" + des); } } } From a338cf325d9260efba14ce9b002e1911032e198e Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 6 Dec 2014 05:57:24 -0800 Subject: [PATCH 239/319] greddy --- greedy/Jump.java | 1 + 1 file changed, 1 insertion(+) diff --git a/greedy/Jump.java b/greedy/Jump.java index b17abb4..2e94b92 100644 --- a/greedy/Jump.java +++ b/greedy/Jump.java @@ -22,6 +22,7 @@ public static int jump(int[] A) { sum++; des = i; // 更新dest位置,下一步就是计算要几步能调到当前i的位置 //break; // 没必要再继续找,因为越早找到的i肯定越靠前,说明这一跳的距离越远 + // 这一行可以去掉, des = i,不符合for的条件,会自动break. System.out.println("sum:" + sum); System.out.println("des:" + des); } From 5b410c9d1adb15af7320d9ff8fe70eb03deac36b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 6 Dec 2014 17:28:00 -0800 Subject: [PATCH 240/319] min cut. --- dp/MinCut.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dp/MinCut.java b/dp/MinCut.java index 9aaa616..c8b4ffb 100644 --- a/dp/MinCut.java +++ b/dp/MinCut.java @@ -7,6 +7,8 @@ public int minCut(String s) { } int len = s.length(); + + // D[i] 的定义: 第i个字符到len - 1个字符的最小切割数。 int[] D = new int[len]; boolean[][] isPalid = new boolean[len][len]; @@ -21,6 +23,8 @@ public int minCut(String s) { if (s.charAt(i) == s.charAt(j) && (j - i <= 1 || isPalid[i + 1][j - 1])) { isPalid[i][j] = true; if (j == len - 1) { + // 这里就是特殊处理的地方了。当整个字符串都是回文的时候,因为没有D[Len],所以这里直接 + // 将D[i]置为0,意思就是这时不需要任何的划分。 D[i] = 0; } else { // 如果前半部分是回文,那么我们可以分解为第一个回文 + 后半部分的最小分割数 From c62555b54085b805766d7132b653ac500b6182de Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 6 Dec 2014 22:42:56 -0800 Subject: [PATCH 241/319] sort --- list/MergeTwoLists_1206.java | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 list/MergeTwoLists_1206.java diff --git a/list/MergeTwoLists_1206.java b/list/MergeTwoLists_1206.java new file mode 100644 index 0000000..d5dd9a6 --- /dev/null +++ b/list/MergeTwoLists_1206.java @@ -0,0 +1,40 @@ +package Algorithms.list; + +import Algorithms.algorithm.others.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class MergeTwoLists_1206 { + public ListNode mergeTwoLists(ListNode l1, ListNode l2) { + ListNode dummy = new ListNode(0); + ListNode cur = dummy; + + while (l1 != null && l2 != null) { + if (l1.val < l2.val) { + cur.next = l1; + l1 = l1.next; + } else { + cur.next = l2; + l2 = l2.next; + } + cur = cur.next; + } + + if (l1 != null) { + cur.next = l1; + } else { + cur.next = l2; + } + + return dummy.next; + } +} \ No newline at end of file From c14d476bd04bdf9e69422e08987f4ab99cde2a78 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 9 Dec 2014 00:12:35 -0800 Subject: [PATCH 242/319] dp --- algorithm/dp/MinAdjustmentCost_Class.java | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 algorithm/dp/MinAdjustmentCost_Class.java diff --git a/algorithm/dp/MinAdjustmentCost_Class.java b/algorithm/dp/MinAdjustmentCost_Class.java new file mode 100644 index 0000000..5015668 --- /dev/null +++ b/algorithm/dp/MinAdjustmentCost_Class.java @@ -0,0 +1,58 @@ +package Algorithms.algorithm.dp; + +import java.util.ArrayList; + +public class MinAdjustmentCost_Class { + public static void main(String[] strs) { + ArrayList A = new ArrayList(); + A.add(1); + A.add(4); + A.add(2); + A.add(3); + + System.out.println(MinAdjustmentCost(A, 1)); + } + + /** + * @param A: An integer array. + * @param target: An integer. + */ + public static int MinAdjustmentCost(ArrayList A, int target) { + // write your code here + if (A == null) { + return 0; + } + + return rec(A, new ArrayList(A), target, 0); + } + + public static int rec(ArrayList A, ArrayList B, int target, int index) { + int len = A.size(); + if (index >= len) { + // The index is out of range. + return 0; + } + + int dif = 0; + + int min = Integer.MAX_VALUE; + + // If this is the first element, it can be from 1 to 100; + for (int i = 0; i <= 100; i++) { + if (index != 0 && Math.abs(i - B.get(index - 1)) > target) { + continue; + } + + B.set(index, i); + dif = Math.abs(i - A.get(index)); + dif += rec(A, B, target, index + 1); + min = Math.min(min, dif); + + // 回溯 + B.set(index, A.get(index)); + } + + return min; + } + +} From 41a5c0454b3cf2e564e7e515a6f675676806027f Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 9 Dec 2014 00:45:29 -0800 Subject: [PATCH 243/319] min cost --- algorithm/dp/MinAdjustmentCost_Class.java | 69 ++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/algorithm/dp/MinAdjustmentCost_Class.java b/algorithm/dp/MinAdjustmentCost_Class.java index 5015668..d68a232 100644 --- a/algorithm/dp/MinAdjustmentCost_Class.java +++ b/algorithm/dp/MinAdjustmentCost_Class.java @@ -17,7 +17,7 @@ public static void main(String[] strs) { * @param A: An integer array. * @param target: An integer. */ - public static int MinAdjustmentCost(ArrayList A, int target) { + public static int MinAdjustmentCost1(ArrayList A, int target) { // write your code here if (A == null) { return 0; @@ -26,6 +26,10 @@ public static int MinAdjustmentCost(ArrayList A, int target) { return rec(A, new ArrayList(A), target, 0); } + /* + * SOL 1: + * 最普通的递归方法。 + * */ public static int rec(ArrayList A, ArrayList B, int target, int index) { int len = A.size(); if (index >= len) { @@ -54,5 +58,68 @@ public static int rec(ArrayList A, ArrayList B, int target, in return min; } + + /* + * 递归2: + * Rec + memory. + * */ + /** + * @param A: An integer array. + * @param target: An integer. + */ + public static int MinAdjustmentCost(ArrayList A, int target) { + // write your code here + if (A == null || A.size() == 0) { + return 0; + } + + int[][] M = new int[A.size()][100]; + for (int i = 0; i < A.size(); i++) { + for (int j = 0; j < 100; j++) { + M[i][j] = Integer.MAX_VALUE; + } + } + + return rec2(A, new ArrayList(A), target, 0, M); + } + + public static int rec2(ArrayList A, ArrayList B, int target, int index, + int[][] M) { + int len = A.size(); + if (index >= len) { + // The index is out of range. + return 0; + } + + int dif = 0; + int min = Integer.MAX_VALUE; + + // If this is the first element, it can be from 1 to 100; + for (int i = 1; i <= 100; i++) { + if (index != 0 && Math.abs(i - B.get(index - 1)) > target) { + continue; + } + + if (M[index][i - 1] != Integer.MAX_VALUE) { + dif = M[index][i - 1]; + min = Math.min(min, dif); + continue; + } + + B.set(index, i); + dif = Math.abs(i - A.get(index)); + dif += rec2(A, B, target, index + 1, M); + + min = Math.min(min, dif); + + // Record the result. + M[index][i - 1] = dif; + + // 回溯 + B.set(index, A.get(index)); + } + + return min; + } } From 499a0885a3af2e2cb0b1b96ae0fa38febd4574bc Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 9 Dec 2014 02:00:14 -0800 Subject: [PATCH 244/319] dp --- algorithm/dp/MinAdjustmentCost_Class.java | 115 +++++++++++++++++++++- 1 file changed, 114 insertions(+), 1 deletion(-) diff --git a/algorithm/dp/MinAdjustmentCost_Class.java b/algorithm/dp/MinAdjustmentCost_Class.java index d68a232..fa1b90b 100644 --- a/algorithm/dp/MinAdjustmentCost_Class.java +++ b/algorithm/dp/MinAdjustmentCost_Class.java @@ -67,7 +67,7 @@ public static int rec(ArrayList A, ArrayList B, int target, in * @param A: An integer array. * @param target: An integer. */ - public static int MinAdjustmentCost(ArrayList A, int target) { + public static int MinAdjustmentCost2(ArrayList A, int target) { // write your code here if (A == null || A.size() == 0) { return 0; @@ -121,5 +121,118 @@ public static int rec2(ArrayList A, ArrayList B, int target, i return min; } + + /* + * SOLUTION 3 递归2: + * Rec + memory. + * 改进的递归版本 + * */ + /** + * @param A: An integer array. + * @param target: An integer. + */ + public static int MinAdjustmentCost3(ArrayList A, int target) { + // write your code here + if (A == null || A.size() == 0) { + return 0; + } + + int[][] M = new int[A.size()][100]; + for (int i = 0; i < A.size(); i++) { + for (int j = 0; j < 100; j++) { + M[i][j] = Integer.MAX_VALUE; + } + } + + // 首个数字可以取1-100 + int min = Integer.MAX_VALUE; + for (int i = 1; i <= 100; i++) { + min = Math.min(min, rec3(A, target, 0, i, M)); + } + + return min; + } + + /* + * 将当前值设置为x能求得的最小解 + * */ + public static int rec3(ArrayList A, int target, int index, int x, + int[][] M) { + int len = A.size(); + if (index >= len) { + // The index is out of range. + return 0; + } + + if (M[index][x - 1] != Integer.MAX_VALUE) { + return M[index][x - 1]; + } + + int bas = Math.abs(x - A.get(index)); + int min = Integer.MAX_VALUE; + + // 对下一个值尝试取1-100 + for (int i = 1; i <= 100; i++) { + // 下一个值的取值不可以超过abs + if (index != len - 1 && Math.abs(i - x) > target) { + continue; + } + + // 计算dif + int dif = bas + rec3(A, target, index + 1, i, M); + min = Math.min(min, dif); + } + + // Record the result. + M[index][x - 1] = min; + return min; + } + + /* + * SOLUTION 4: + * DP + * */ + /** + * @param A: An integer array. + * @param target: An integer. + */ + public static int MinAdjustmentCost(ArrayList A, int target) { + // write your code here + if (A == null || A.size() == 0) { + return 0; + } + + // D[i][v]: 把index = i的值修改为v,所需要的最小花费 + int[][] D = new int[A.size()][101]; + + int size = A.size(); + + for (int i = 0; i < size; i++) { + for (int j = 1; j <= 100; j++) { + D[i][j] = Integer.MAX_VALUE; + if (i == 0) { + // The first element. + D[i][j] = Math.abs(j - A.get(i)); + } else { + for (int k = 1; k <= 100; k++) { + // 不符合条件 + if (Math.abs(j - k) > target) { + continue; + } + + int dif = Math.abs(j - A.get(i)) + D[i - 1][k]; + D[i][j] = Math.min(D[i][j], dif); + } + } + } + } + + int ret = Integer.MAX_VALUE; + for (int i = 1; i <= 100; i++) { + ret = Math.min(ret, D[size - 1][i]); + } + + return ret; + } } From 7bc5a3504e5e8ac5e1fe9392af8dfd0efb73f050 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 9 Dec 2014 23:18:04 -0800 Subject: [PATCH 245/319] sort --- list/InsertionSortList.java | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 list/InsertionSortList.java diff --git a/list/InsertionSortList.java b/list/InsertionSortList.java new file mode 100644 index 0000000..88d5bb6 --- /dev/null +++ b/list/InsertionSortList.java @@ -0,0 +1,39 @@ +package Algorithms.list; + +import Algorithms.algorithm.others.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class InsertionSortList { + public ListNode insertionSortList(ListNode head) { + ListNode dummy = new ListNode(0); + + while (head != null) { + ListNode pre = dummy; + + // 注意,这里要用<= 来保证算法的稳定性 + // 因为假如有2个数相同,后面的数后找到,也要插入到后面才可以。也就是说当=的时候,是继续往下走 + while (pre.next != null && pre.next.val <= head.val) { + pre = pre.next; + } + + // unlink the node from the original link. And record the next position. + ListNode headNext = head.next; + head.next = pre.next; + + pre.next = head; + head = headNext; + } + + return dummy.next; + } +} \ No newline at end of file From f710a076e047b757e1a2cfde02230d67830db753 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 9 Dec 2014 23:56:47 -0800 Subject: [PATCH 246/319] detect --- list/DetectCycle.java | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 list/DetectCycle.java diff --git a/list/DetectCycle.java b/list/DetectCycle.java new file mode 100644 index 0000000..1314732 --- /dev/null +++ b/list/DetectCycle.java @@ -0,0 +1,55 @@ +package Algorithms.list; + +import Algorithms.algorithm.others.ListNode; + +/** + * Definition for singly-linked list. + * class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class DetectCycle { + public ListNode detectCycle(ListNode head) { + if (head == null) { + return null; + } + + ListNode s = head; + ListNode f = head; + + ListNode cross = null; + + while (f != null && f.next != null) { + s = s.next; + f = f.next.next; + + if (s == f) { + cross = s; + + // remember to break here, or you will get a loop. + break; + } + } + + // don't detect any cycle. + if (cross == null) { + return null; + } + + // place the slow to the start again. + s = head; + while (true) { + if (s == f) { + return s; + } + + s = s.next; + f = f.next; + } + } +} \ No newline at end of file From 435e66263f1433e798fc5cb77c1ace27ae78f65d Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 12 Dec 2014 07:56:37 -0800 Subject: [PATCH 247/319] find frequency --- algorithm/dp/MinAdjustmentCost_Class.java | 11 +- .../pocketGem/FindKthFrequency.java | 107 ++++++++++++++++++ string/StrStr.java | 31 +++++ 3 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 algorithm/interviews/pocketGem/FindKthFrequency.java diff --git a/algorithm/dp/MinAdjustmentCost_Class.java b/algorithm/dp/MinAdjustmentCost_Class.java index fa1b90b..4fd11e7 100644 --- a/algorithm/dp/MinAdjustmentCost_Class.java +++ b/algorithm/dp/MinAdjustmentCost_Class.java @@ -10,7 +10,7 @@ public static void main(String[] strs) { A.add(2); A.add(3); - System.out.println(MinAdjustmentCost(A, 1)); + System.out.println(MinAdjustmentCost1(A, 1)); } /** @@ -23,7 +23,12 @@ public static int MinAdjustmentCost1(ArrayList A, int target) { return 0; } - return rec(A, new ArrayList(A), target, 0); + ArrayList B = new ArrayList(); + for (int i = 0; i < A.size(); i++) { + B.add(0); + } + + return rec(A, B, target, 0); } /* @@ -53,7 +58,7 @@ public static int rec(ArrayList A, ArrayList B, int target, in min = Math.min(min, dif); // 回溯 - B.set(index, A.get(index)); + //B.set(index, A.get(index)); } return min; diff --git a/algorithm/interviews/pocketGem/FindKthFrequency.java b/algorithm/interviews/pocketGem/FindKthFrequency.java new file mode 100644 index 0000000..3585cda --- /dev/null +++ b/algorithm/interviews/pocketGem/FindKthFrequency.java @@ -0,0 +1,107 @@ +package Algorithms.algorithm.interviews.pocketGem; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; +import java.util.PriorityQueue; +import java.util.Set; + +/* + * Input: int[] A = {1, 1, 2, 3, 4, 5, 2}; k = 3 + * return the highest frequency numbers. + * return: [1, 2, 3] or [1, 2, 4] or [1, 2, 5] + * */ + +public class FindKthFrequency { + public static void main(String[] strs) { + int[] A = {1, 1, 2, 3, 3, 3, 4, 4, 4, 4, 4, 5, 7, 2}; + System.out.println(findKthFrenquency(A, 3).toString()); + } + + /* + * Solution 1: + * 对HashMap Sort. + * Complexity: O(NLogN) + * */ + public static Set findKthFrenquency1(int[] input, int k) { + HashSet set = new HashSet(); + HashMap map = new HashMap(); + for (int num: input) { + if (map.containsKey(num)) { + map.put(num, map.get(num) + 1); + } else { + map.put(num, 1); + } + } + + ArrayList> list = new ArrayList>(map.entrySet()); + + Collections.sort(list, new Comparator>() { + public int compare(Entry o1, Entry o2) { + return o2.getValue() - o1.getValue(); + } + }); + + for (int i = 0; i < k; i++) { + set.add(list.get(i).getKey()); + } + + return set; + } + + /* + * Solution 2: + * Use TreeMap. + * */ + public static Set findKthFrenquency2(int[] input, int k) { + HashSet set = new HashSet(); + + return set; + } + + /* + * Solution 3: + * Use The priority queue. + * */ + public static List findKthFrenquency(int[] input, int k) { + LinkedList list = new LinkedList(); + + HashMap map = new HashMap(); + for (int num: input) { + if (map.containsKey(num)) { + map.put(num, map.get(num) + 1); + } else { + map.put(num, 1); + } + } + + PriorityQueue> q = new PriorityQueue>(k + 1, new Comparator>(){ + public int compare(Entry o1, Entry o2) { + return o1.getValue() - o2.getValue(); + } + }); + + for (Entry entry: map.entrySet()) { + if (q.size() == k + 1) { + // Delete the smallest element from the queue. + q.poll(); + } + q.offer(entry); + } + + // delete one small element + q.poll(); + + while (!q.isEmpty()) { + Entry entry = q.poll(); + list.addFirst(entry.getKey()); + } + + return list; + } +} diff --git a/string/StrStr.java b/string/StrStr.java index cd04196..a7c8232 100644 --- a/string/StrStr.java +++ b/string/StrStr.java @@ -1,6 +1,10 @@ package Algorithms.string; public class StrStr { + public static void main(String[] strs) { + System.out.println(findPattern("ppa","pp")); + } + public String strStr(String haystack, String needle) { if (haystack == null || needle == null) { return null; @@ -30,4 +34,31 @@ public String strStr(String haystack, String needle) { // didn't find the needle. return null; } + + public static int findPattern(String base, String pattern) { + if (base == null || pattern == null) { + return -1; + } + + int len1 = base.length(); + int len2 = pattern.length(); + + for (int i = 0; i <= len1 - len2; i++) { + int j = 0; + for (; j < len2; j++) { + if (base.charAt(i + j) != pattern.charAt(j)) { + break; + } + + + if (j == len2 - 1) { + return i; + } + } + + } + + // did not find pattern. + return -1; + } } \ No newline at end of file From 11a207c471adcc4f63dce01845ed616f83fa6e04 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 13 Dec 2014 16:19:58 -0800 Subject: [PATCH 248/319] reverse --- math/Reverse.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 math/Reverse.java diff --git a/math/Reverse.java b/math/Reverse.java new file mode 100644 index 0000000..221dbac --- /dev/null +++ b/math/Reverse.java @@ -0,0 +1,18 @@ +package Algorithms.math; + +public class Reverse { + public int reverse(int x) { + long ret = 0; + + while (x != 0) { + ret = ret * 10 + x % 10; + x /= 10; + } + + if (ret > Integer.MAX_VALUE || ret < Integer.MIN_VALUE) { + return 0; + } + + return (int)ret; + } +} \ No newline at end of file From dce0192fe4e3d551c72c7753e2da74df74987c27 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 14 Dec 2014 22:07:05 -0800 Subject: [PATCH 249/319] kthLargestElement --- algorithm/NChapter/KthLargestElement.java | 66 +++++++++++++++++++++++ sort/QuickSort.java | 2 - 2 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 algorithm/NChapter/KthLargestElement.java diff --git a/algorithm/NChapter/KthLargestElement.java b/algorithm/NChapter/KthLargestElement.java new file mode 100644 index 0000000..93516a0 --- /dev/null +++ b/algorithm/NChapter/KthLargestElement.java @@ -0,0 +1,66 @@ +package Algorithms.algorithm.NChapter; + +import java.util.ArrayList; + +// The link: +// http://www.lintcode.com/en/problem/kth-largest-element/ + +class Solution { + //param k : description of k + //param numbers : array of numbers + //return: description of return + public int kthLargestElement(int k, ArrayList numbers) { + // write your code here + if (k < 1 || numbers == null) { + return 0; + } + + return getKth(numbers.size() - k + 1, numbers, 0, numbers.size() - 1); + } + + public int getKth(int k, ArrayList numbers, int start, int end) { + // Choose the last one as the pivot + int pivot = numbers.get(end); + + int left = start; + int right = end; + + while (true) { + while (numbers.get(left) < pivot && left < right) { + left++; + } + + while (numbers.get(right) >= pivot && right > left) { + right--; + } + + if (left == right) { + break; + } + + swap(numbers, left, right); + } + + // left: the first one which is bigger than pivot. + swap(numbers, left, end); + + if (k == left + 1) { + return pivot; + // Try to find the element from the left side. + } else if (k < left + 1) { + return getKth(k, numbers, start, left - 1); + } else { + // Try to find the element from the right side. + return getKth(k, numbers, left + 1, end); + } + } + + /* + Swap the two nodes. + */ + public void swap(ArrayList numbers, int n1, int n2) { + int tmp = numbers.get(n1); + numbers.set(n1, numbers.get(n2)); + numbers.set(n2, tmp); + } +}; diff --git a/sort/QuickSort.java b/sort/QuickSort.java index 7090a41..934345c 100644 --- a/sort/QuickSort.java +++ b/sort/QuickSort.java @@ -63,8 +63,6 @@ private static void recQuickSort(int[] arr, int left, int right) { // partition the array and return the new pivot position. private static int partition(int[] arr, int left, int right, int pivot) { - int len = arr.length; - // set the pivot. int l = left ; int r = right - 1; From 57dc58ff230bb9fe3f562697d23aea96fb992983 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 14 Dec 2014 22:18:02 -0800 Subject: [PATCH 250/319] find kth --- .../NChapter/{ => findKthNumber}/FindKthNumber.java | 6 +++++- .../findKthNumber/FindMedianSortedArrays.java} | 11 ++++------- .../findKthNumber}/KthLargestElement.java | 8 +++++--- .../KthLargestElement_lintCode.java} | 5 +++-- 4 files changed, 17 insertions(+), 13 deletions(-) rename algorithm/NChapter/{ => findKthNumber}/FindKthNumber.java (94%) rename algorithm/{others/FindKthNumber.java => NChapter/findKthNumber/FindMedianSortedArrays.java} (82%) rename algorithm/{others => NChapter/findKthNumber}/KthLargestElement.java (93%) rename algorithm/NChapter/{KthLargestElement.java => findKthNumber/KthLargestElement_lintCode.java} (95%) diff --git a/algorithm/NChapter/FindKthNumber.java b/algorithm/NChapter/findKthNumber/FindKthNumber.java similarity index 94% rename from algorithm/NChapter/FindKthNumber.java rename to algorithm/NChapter/findKthNumber/FindKthNumber.java index 97ed041..3e01052 100644 --- a/algorithm/NChapter/FindKthNumber.java +++ b/algorithm/NChapter/findKthNumber/FindKthNumber.java @@ -1,7 +1,11 @@ -package Algorithms.algorithm.NChapter; +package Algorithms.algorithm.NChapter.findKthNumber; import java.util.Arrays; +/* + * Version 1: The pivot is in the left. + * */ + public class FindKthNumber { public static void main(String[] strs) { int[] A1 = new int[]{1,6,9,2,3,5}; diff --git a/algorithm/others/FindKthNumber.java b/algorithm/NChapter/findKthNumber/FindMedianSortedArrays.java similarity index 82% rename from algorithm/others/FindKthNumber.java rename to algorithm/NChapter/findKthNumber/FindMedianSortedArrays.java index 53c05f3..743df47 100644 --- a/algorithm/others/FindKthNumber.java +++ b/algorithm/NChapter/findKthNumber/FindMedianSortedArrays.java @@ -1,18 +1,15 @@ -package Algorithms.algorithm.others; +package Algorithms.algorithm.NChapter.findKthNumber; -public class FindKthNumber { +public class FindMedianSortedArrays { public static void main(String[] str) { int A[] = {1,2,3,3}; int B[] = {3,3,7,8}; - FindKthNumber fn = new FindKthNumber(); - double ret = fn.findMedianSortedArrays(A, B); + double ret = findMedianSortedArrays(A, B); System.out.println(ret); } - public double findMedianSortedArrays(int A[], int B[]) { - int len = A.length + B.length; - + public static double findMedianSortedArrays(int A[], int B[]) { double ret = findKth(A, 0, B, 0, 6); return ret; diff --git a/algorithm/others/KthLargestElement.java b/algorithm/NChapter/findKthNumber/KthLargestElement.java similarity index 93% rename from algorithm/others/KthLargestElement.java rename to algorithm/NChapter/findKthNumber/KthLargestElement.java index 9d0fe33..b7737c1 100644 --- a/algorithm/others/KthLargestElement.java +++ b/algorithm/NChapter/findKthNumber/KthLargestElement.java @@ -1,6 +1,9 @@ -package Algorithms.algorithm.others; +package Algorithms.algorithm.NChapter.findKthNumber; import java.util.ArrayList; -import java.util.Collections; + +/* + * LintCode Version 1: Use arrays to solve it. + * */ class KthLargestElement { //param k : description of k @@ -23,7 +26,6 @@ public int kthLargestElement(int k, ArrayList numbers) { // write your code here Integer[] num = new Integer[numbers.size()]; numbers.toArray(num); - //Integer[] num = numbers.toArray(new Integer[0]); return findKthNumberHelp(num, num.length + 1 - k, 0, num.length - 1); } diff --git a/algorithm/NChapter/KthLargestElement.java b/algorithm/NChapter/findKthNumber/KthLargestElement_lintCode.java similarity index 95% rename from algorithm/NChapter/KthLargestElement.java rename to algorithm/NChapter/findKthNumber/KthLargestElement_lintCode.java index 93516a0..0d056c3 100644 --- a/algorithm/NChapter/KthLargestElement.java +++ b/algorithm/NChapter/findKthNumber/KthLargestElement_lintCode.java @@ -1,11 +1,12 @@ -package Algorithms.algorithm.NChapter; +package Algorithms.algorithm.NChapter.findKthNumber; import java.util.ArrayList; // The link: + // http://www.lintcode.com/en/problem/kth-largest-element/ -class Solution { +class KthLargestElement_lintCode { //param k : description of k //param numbers : array of numbers //return: description of return From 48840a0c2977e8958170edf7482a79a3f82f31d1 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 14 Dec 2014 22:19:12 -0800 Subject: [PATCH 251/319] v1 --- ...LargestElement.java => KthLargestElement_lintCode_v1.java} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename algorithm/NChapter/findKthNumber/{KthLargestElement.java => KthLargestElement_lintCode_v1.java} (93%) diff --git a/algorithm/NChapter/findKthNumber/KthLargestElement.java b/algorithm/NChapter/findKthNumber/KthLargestElement_lintCode_v1.java similarity index 93% rename from algorithm/NChapter/findKthNumber/KthLargestElement.java rename to algorithm/NChapter/findKthNumber/KthLargestElement_lintCode_v1.java index b7737c1..6246913 100644 --- a/algorithm/NChapter/findKthNumber/KthLargestElement.java +++ b/algorithm/NChapter/findKthNumber/KthLargestElement_lintCode_v1.java @@ -5,12 +5,12 @@ * LintCode Version 1: Use arrays to solve it. * */ -class KthLargestElement { +class KthLargestElement_lintCode_v1 { //param k : description of k //param numbers : array of numbers //return: description of return public static void main(String[] strs) { - KthLargestElement Kth = new KthLargestElement(); + KthLargestElement_lintCode_v1 Kth = new KthLargestElement_lintCode_v1(); ArrayList numbers = new ArrayList(); numbers.add(9); numbers.add(3); From 60214d4c50827b290c12ddaccfb197e5d3961356 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 18 Dec 2014 02:11:32 -0800 Subject: [PATCH 252/319] queen --- dfs/totalNQueens_1218_2014.java | 55 +++++++++++++++++++++++++++++++++ string/StrStr.java | 41 ++++++++++++++++++++++-- 2 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 dfs/totalNQueens_1218_2014.java diff --git a/dfs/totalNQueens_1218_2014.java b/dfs/totalNQueens_1218_2014.java new file mode 100644 index 0000000..61b37d8 --- /dev/null +++ b/dfs/totalNQueens_1218_2014.java @@ -0,0 +1,55 @@ +package Algorithms.dfs; + +import java.util.ArrayList; + +public class totalNQueens_1218_2014 { + public int totalNQueens(int n) { + if (n == 0) { + return 0; + } + + // Bug 1: forget to modify the parameters of the function. + return dfs(n, 0, new ArrayList()); + } + + public int dfs(int n, int row, ArrayList path) { + if (row == n) { + // The base case: 当最后一行,皇后只有1种放法(就是不放) + return 1; + } + + int num = 0; + + // The queen can select any of the slot. + for (int i = 0; i < n; i++) { + if (!isValid(path, i)) { + continue; + } + path.add(i); + + // All the solutions is all the possibilities are add up. + num += dfs(n, row + 1, path); + path.remove(path.size() - 1); + } + + return num; + } + + public boolean isValid(ArrayList path, int col) { + int size = path.size(); + for (int i = 0; i < size; i++) { + // The same column with any of the current queen. + if (col == path.get(i)) { + return false; + } + + // diagonally lines. + // Bug 2: forget to add a ')' + if (size - i == Math.abs(col - path.get(i))) { + return false; + } + } + + return true; + } +} \ No newline at end of file diff --git a/string/StrStr.java b/string/StrStr.java index a7c8232..51accac 100644 --- a/string/StrStr.java +++ b/string/StrStr.java @@ -1,11 +1,47 @@ package Algorithms.string; +import java.util.ArrayList; + public class StrStr { public static void main(String[] strs) { - System.out.println(findPattern("ppa","pp")); + System.out.println(strStr("ppa","pa")); + System.out.println(findPattern("ppa","pax")); + + System.out.println(findAllStrings("xxisxhis")); + } - public String strStr(String haystack, String needle) { + public static boolean isAWord(String s) { + if (s.equals("is")) { + return true; + } else if (s.equals("his")){ + return true; + } + return false; + } + + public static ArrayList findAllStrings(String s) { + ArrayList ret = new ArrayList(); + + if (s == null || s.length() == 0) { + return ret; + } + + int len = s.length(); + + for (int i = 0; i < len; i++) { + for (int j = i; j < len; j++) { + String sub = s.substring(i, j + 1); + if (isAWord(sub)) { + ret.add(sub); + } + } + } + + return ret; + } + + public static String strStr(String haystack, String needle) { if (haystack == null || needle == null) { return null; } @@ -50,7 +86,6 @@ public static int findPattern(String base, String pattern) { break; } - if (j == len2 - 1) { return i; } From 16ac757dbd5b413158de99c439d9c61d67fd5ace Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 18 Dec 2014 02:16:00 -0800 Subject: [PATCH 253/319] file --- dfs/totalNQueens_1218_2014.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dfs/totalNQueens_1218_2014.java b/dfs/totalNQueens_1218_2014.java index 61b37d8..b3d63b0 100644 --- a/dfs/totalNQueens_1218_2014.java +++ b/dfs/totalNQueens_1218_2014.java @@ -2,7 +2,7 @@ import java.util.ArrayList; -public class totalNQueens_1218_2014 { +public class TotalNQueens_1218_2014 { public int totalNQueens(int n) { if (n == 0) { return 0; From c4f019453c3eb49c06ef239cd383ea5ce674129f Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 18 Dec 2014 02:17:38 -0800 Subject: [PATCH 254/319] add --- dfs/totalNQueens_1218_2014.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dfs/totalNQueens_1218_2014.java b/dfs/totalNQueens_1218_2014.java index b3d63b0..5c7e7ce 100644 --- a/dfs/totalNQueens_1218_2014.java +++ b/dfs/totalNQueens_1218_2014.java @@ -44,7 +44,7 @@ public boolean isValid(ArrayList path, int col) { } // diagonally lines. - // Bug 2: forget to add a ')' + // Bug 2: forget to add a ')' if (size - i == Math.abs(col - path.get(i))) { return false; } From b3d6563407aef98b859a488f95b5bdba426839ff Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 18 Dec 2014 02:57:47 -0800 Subject: [PATCH 255/319] ladder --- bfs/LadderLength_1218_2014.java | 73 +++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 bfs/LadderLength_1218_2014.java diff --git a/bfs/LadderLength_1218_2014.java b/bfs/LadderLength_1218_2014.java new file mode 100644 index 0000000..99800ad --- /dev/null +++ b/bfs/LadderLength_1218_2014.java @@ -0,0 +1,73 @@ +package Algorithms.bfs; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Queue; +import java.util.Set; + +public class LadderLength_1218_2014 { + public static void main(String[] strs) { + HashSet set = new HashSet(); + set.add("hot"); + set.add("dot"); + set.add("dog"); + set.add("lot"); + set.add("log"); + set.add("cog"); + System.out.println(ladderLength("hit", "cog", set)); + } + + public static int ladderLength(String start, String end, Set dict) { + if (start == null || end == null || dict == null) { + return 0; + } + + // Bug 1: quese is a interface not a class + Queue q = new LinkedList(); + q.offer(start); + + HashSet set = new HashSet(); + set.add(start); + + // Bug 3: lever start from 1; + int level = 1; + + while (!q.isEmpty()) { + int size = q.size(); + + level++; + + for (int i = 0; i < size; i++) { + String s = q.poll(); + + int len = s.length(); + + for (int j = 0; j < len; j++) { + StringBuilder sb = new StringBuilder(s); + for (char c = 'a'; c <= 'z'; c++) { + // Bug 2: setCharAt + sb.setCharAt(j, c); + String tmp = sb.toString(); + + // Should be in the dict and not in the hashset. + if (set.contains(tmp) || !dict.contains(tmp)) { + continue; + } + + if (tmp.equals(end)) { + return level; + } + + set.add(tmp); + q.offer(tmp); + } + } + + } + } + + // When not found, return 0; + // "hot", "dog", ["hot","dog"] + return 0; + } +} \ No newline at end of file From 16d864fb5fab17442e11abbb07ed98ec5a7eb4cc Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 18 Dec 2014 03:59:52 -0800 Subject: [PATCH 256/319] findLadder --- string/FindLadders_1218_2014.java | 95 +++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 string/FindLadders_1218_2014.java diff --git a/string/FindLadders_1218_2014.java b/string/FindLadders_1218_2014.java new file mode 100644 index 0000000..3d968b0 --- /dev/null +++ b/string/FindLadders_1218_2014.java @@ -0,0 +1,95 @@ +package Algorithms.string; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.Set; + +public class FindLadders_1218_2014 { + public static List> findLadders(String start, String end, Set dict) { + List> ret = new ArrayList>(); + if (start == null || end == null || dict == null) { + return ret; + } + + HashMap>> map = new HashMap>>(); + + // Store the map of the current level. + HashMap>> mapTmp = new HashMap>>(); + + Queue q = new LinkedList(); + q.offer(start); + + List> listStart = new ArrayList>(); + + // 唯一的路径 + List path = new ArrayList(); + path.add(start); + listStart.add(path); + + // 将头节点放入 + map.put(start, listStart); + + while (!q.isEmpty()) { + int size = q.size(); + + for (int i = 0; i < size; i++) { + String s = q.poll(); + + int len = s.length(); + for (int j = 0; j < len; j++) { + StringBuilder sb = new StringBuilder(s); + for (char c = 'a'; c <= 'z'; c++) { + // Bug 2: should seperate the setCharAt(j, c) function and the sb.toString() function. + sb.setCharAt(j, c); + String tmp = sb.toString(); + + // 1. 不在字典中,并且不是end. + // 2. 前面的map中已经出现过 + + // Bug 1: map should use containsKey; + if ((!dict.contains(tmp) && !tmp.equals(end)) || map.containsKey(tmp)) { + continue; + } + + // Try to get the pre list. + List> pre = map.get(s); + + // 从mapTmp中取出节点,或者是新建一个节点 + List> curList = mapTmp.get(tmp); + if (curList == null) { + curList = new ArrayList>(); + + // Only offer new string to the queue. + // 将生成的单词放入队列,以便下一次继续变换 + // 放在这里可以避免Q重复加入 + q.offer(tmp); + + // create a new map. + mapTmp.put(tmp, curList); + } + + // 将PRE的path 取出,加上当前节点,并放入curList中 + for (List strList: pre) { + // Should create a new list. + List strListNew = new ArrayList(strList); + strListNew.add(tmp); + curList.add(strListNew); + } + } + } + } + + if (mapTmp.containsKey(end)) { + return mapTmp.get(end); + } + + // add the tmp map into the map. + map.putAll(mapTmp); + } + + return ret; + } +} \ No newline at end of file From 16385cd82302e265d4e2087012e8bb065e53d770 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 18 Dec 2014 04:53:12 -0800 Subject: [PATCH 257/319] tree --- tree/IsBalanced.java | 66 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 tree/IsBalanced.java diff --git a/tree/IsBalanced.java b/tree/IsBalanced.java new file mode 100644 index 0000000..8fe4ec5 --- /dev/null +++ b/tree/IsBalanced.java @@ -0,0 +1,66 @@ +package Algorithms.tree; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class IsBalanced { + // Solution 1: + public boolean isBalanced1(TreeNode root) { + return dfs(root).isBalanced; + } + + // bug 1: inner class is like: "public class ReturnType {", no () + public class ReturnType { + boolean isBalanced; + int depth; + + ReturnType(int depth, boolean isBalanced) { + this.depth = depth; + this.isBalanced = isBalanced; + } + } + + public ReturnType dfs(TreeNode root) { + ReturnType ret = new ReturnType(0, true); + + if (root == null) { + return ret; + } + + ReturnType left = dfs(root.left); + ReturnType right = dfs(root.right); + + ret.isBalanced = left.isBalanced + && right.isBalanced + && Math.abs(left.depth - right.depth) <= 1; + + // bug 2: remember to add 1( the root depth ) + ret.depth = Math.max(left.depth, right.depth) + 1; + + return ret; + } + + // Solution 2: + public boolean isBalanced(TreeNode root) { + if (root == null) { + return true; + } + + return isBalanced(root.left) && isBalanced(root.right) + && Math.abs(getDepth(root.left) - getDepth(root.right)) <= 1; + } + + public int getDepth(TreeNode root) { + if (root == null) { + return 0; + } + + return Math.max(getDepth(root.left), getDepth(root.right)) + 1; + } +} \ No newline at end of file From 035aa6085a7ba062ab733176f6567faed084b2e0 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 18 Dec 2014 05:26:31 -0800 Subject: [PATCH 258/319] tree --- tree/SumNumbers_1208_2014.java | 29 +++++++++++++++++++++++++++++ tree/hasPathSum.java | 15 +++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 tree/SumNumbers_1208_2014.java diff --git a/tree/SumNumbers_1208_2014.java b/tree/SumNumbers_1208_2014.java new file mode 100644 index 0000000..08a1038 --- /dev/null +++ b/tree/SumNumbers_1208_2014.java @@ -0,0 +1,29 @@ +package Algorithms.tree; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class SumNumbers_1208_2014 { + public int sumNumbers(TreeNode root) { + return dfs(root, 0); + } + + public int dfs(TreeNode root, int pre) { + if (root == null) { + return 0; + } + + int cur = pre * 10 + root.val; + if (root.left == null && root.right == null) { + return cur; + } + + return dfs(root.left, cur) + dfs(root.right, cur); + } +} \ No newline at end of file diff --git a/tree/hasPathSum.java b/tree/hasPathSum.java index d4c42ba..b722c4a 100644 --- a/tree/hasPathSum.java +++ b/tree/hasPathSum.java @@ -17,4 +17,19 @@ public boolean hasPathSum(TreeNode root, int sum) { return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val); } + + // Solution 2 + public boolean hasPathSum2(TreeNode root, int sum) { + if (root == null) { + return false; + } + + if (root.left == null && root.right == null && root.val == sum) { + return true; + } + + sum -= root.val; + + return hasPathSum2(root.left, sum) || hasPathSum2(root.right, sum); + } } From efb7d3d931738ede9c4b684dc1f0d489e58192ff Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 18 Dec 2014 05:48:39 -0800 Subject: [PATCH 259/319] PostorderTraversal --- tree/PostorderTraversal.java | 65 ++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 tree/PostorderTraversal.java diff --git a/tree/PostorderTraversal.java b/tree/PostorderTraversal.java new file mode 100644 index 0000000..f1a9d09 --- /dev/null +++ b/tree/PostorderTraversal.java @@ -0,0 +1,65 @@ +package Algorithms.tree; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class PostorderTraversal { + public List postorderTraversal1(TreeNode root) { + List ret = new ArrayList(); + dfs(root, ret); + return ret; + } + + // Solution 1: rec + public void dfs(TreeNode root, List ret) { + if (root == null) { + return; + } + + dfs(root.left, ret); + dfs(root.right, ret); + ret.add(root.val); + } + + // Solution 2: iterator + public List postorderTraversal(TreeNode root) { + List ret = new ArrayList(); + if (root == null) { + return ret; + } + + Stack s = new Stack(); + Stack out = new Stack(); + + s.push(root); + + while (!s.isEmpty()) { + TreeNode cur = s.pop(); + out.push(cur.val); + + if (cur.left != null) { + s.push(cur.left); + } + + if (cur.right != null) { + s.push(cur.right); + } + } + + while (!out.isEmpty()) { + ret.add(out.pop()); + } + + return ret; + } +} \ No newline at end of file From c93e92ae5c332dad81cd322e28f488113bebafcd Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 18 Dec 2014 06:30:31 -0800 Subject: [PATCH 260/319] sum --- tree/MaxPathSum.java | 61 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 tree/MaxPathSum.java diff --git a/tree/MaxPathSum.java b/tree/MaxPathSum.java new file mode 100644 index 0000000..a9711ee --- /dev/null +++ b/tree/MaxPathSum.java @@ -0,0 +1,61 @@ +package Algorithms.tree; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class MaxPathSum { + public static void main(String[] strs) { + TreeNode root = new TreeNode(2); + TreeNode left = new TreeNode(-1); + + root.left = left; + + System.out.println(maxPathSum(root)); + } + + public static class ReturnType { + int maxSingle; + int max; + ReturnType (int maxSingle, int max) { + this.max = max; + this.maxSingle = maxSingle; + } + } + + public static int maxPathSum(TreeNode root) { + return dfs(root).max; + } + + public static ReturnType dfs(TreeNode root) { + ReturnType ret = new ReturnType(Integer.MIN_VALUE, Integer.MIN_VALUE); + if (root == null) { + return ret; + } + + ReturnType left = dfs(root.left); + ReturnType right = dfs(root.right); + + int cross = root.val; + + // if any of the path of left and right is below 0, don't add it. + cross += Math.max(0, left.maxSingle); + cross += Math.max(0, right.maxSingle); + + int maxSingle = root.val + Math.max(left.maxSingle, right.maxSingle); + + // may left.maxSingle and right.maxSingle are below 0 + maxSingle = Math.max(maxSingle, root.val); + + ret.maxSingle = maxSingle; + ret.max = Math.max(right.max, left.max); + ret.max = Math.max(ret.max, cross); + + return ret; + } +} \ No newline at end of file From cc9682d036f30965ec3e6ad72114ff1f7dc27dbf Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 18 Dec 2014 06:57:26 -0800 Subject: [PATCH 261/319] tree --- tree/MinDepth_1218_2014.java | 88 ++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 tree/MinDepth_1218_2014.java diff --git a/tree/MinDepth_1218_2014.java b/tree/MinDepth_1218_2014.java new file mode 100644 index 0000000..7ab0cfa --- /dev/null +++ b/tree/MinDepth_1218_2014.java @@ -0,0 +1,88 @@ +package Algorithms.tree; + +import java.util.LinkedList; +import java.util.Queue; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class MinDepth_1218_2014 { + // SOLUTION 1: + public int minDepth1(TreeNode root) { + /* + 主页君认为,在这应该是属于未定义行为,这里我们定义为MAX会比较好,因为 + null就是取不到任何节点,没有path,不应该将最小值定为0. + */ + if (root == null) { + return 0; + } + + return dfs(root); + } + + /* + * The Recursion Version: + * 这种递归解法更简单。因为在本层递归中不需要考虑左右子树是否为NULL的情况。因为我们直接 + 把 null 设置为返回一个最大值,这样的话,如果出现空子树,它不会影响最小值。但是如果左 + 右均为空,则应返回1(即是仅仅为根节点) + + 而且这种做法更加合理。 因为如果是空树,应该是无法到达才是。这时就应该将值设置为最大。 + * */ + public int dfs(TreeNode root) { + if (root == null) { + return Integer.MAX_VALUE; + } + + // The base case: the root is a leaf. + if (root.left == null && root.right == null) { + return 1; + } + + return Math.min(dfs(root.left), dfs(root.right)) + 1; + } + + // SOLUTION 2: + // Level Traversal: + public int minDepth(TreeNode root) { + /* + 主页君认为,在这应该是属于未定义行为,这里我们定义为MAX会比较好,因为 + null就是取不到任何节点,没有path,不应该将最小值定为0. + */ + if (root == null) { + return 0; + } + + int level = 0; + + Queue q = new LinkedList(); + q.offer(root); + + while (!q.isEmpty()) { + int size = q.size(); + level++; + for (int i = 0; i < size; i++) { + TreeNode cur = q.poll(); + + if (cur.left == null && cur.right == null) { + return level; + } + + if (cur.left != null) { + q.offer(cur.left); + } + + if (cur.right != null) { + q.offer(cur.right); + } + } + } + + return 0; + } +} \ No newline at end of file From 049d5d015cf88fd0c2fa24bb753a78f3fc52b999 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 19 Dec 2014 02:00:12 -0800 Subject: [PATCH 262/319] lintcode array --- lintcode/array/SubarraySum.java | 44 +++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 lintcode/array/SubarraySum.java diff --git a/lintcode/array/SubarraySum.java b/lintcode/array/SubarraySum.java new file mode 100644 index 0000000..eb15717 --- /dev/null +++ b/lintcode/array/SubarraySum.java @@ -0,0 +1,44 @@ +package Algorithms.lintcode.array; + +import java.util.ArrayList; +import java.util.HashMap; + + +public class SubarraySum { + /** + * @param nums: A list of integers + * @return: A list of integers includes the index of the first number + * and the index of the last number + */ + public ArrayList subarraySum(int[] nums) { + // write your code here + int len = nums.length; + + ArrayList ret = new ArrayList(); + + HashMap map = new HashMap(); + + // We set the index -1 sum to be 0 to let us more convient to count. + map.put(0, -1); + + int sum = 0; + for (int i = 0; i < len; i++) { + sum += nums[i]; + + if (map.containsKey(sum)) { + // For example: + // -3 1 2 -3 4 + // SUM: 0 -3 -2 0 -3 1 + // then we got the solution is : 0 - 2 + ret.add(map.get(sum) + 1); + ret.add(i); + return ret; + } + + // Store the key:value of sum:index. + map.put(sum, i); + } + + return ret; + } +} From b626ac4e0f9914ae51fd5e4e4c865943c020ac06 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 19 Dec 2014 02:23:46 -0800 Subject: [PATCH 263/319] array --- lintcode/array/MinSubArray.java | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 lintcode/array/MinSubArray.java diff --git a/lintcode/array/MinSubArray.java b/lintcode/array/MinSubArray.java new file mode 100644 index 0000000..843387e --- /dev/null +++ b/lintcode/array/MinSubArray.java @@ -0,0 +1,30 @@ +package Algorithms.lintcode.array; + +import java.util.ArrayList; + +public class MinSubArray { + /** + * @param nums: a list of integers + * @return: A integer indicate the sum of minimum subarray + */ + public int minSubArray(ArrayList nums) { + // write your code + + int len = nums.size(); + + int max = Integer.MIN_VALUE; + int sum = 0; + for (int i = 0; i < len; i++) { + if (sum < 0) { + sum = -nums.get(i); + } else { + sum += -nums.get(i); + } + + max = Math.max(max, sum); + } + + return -max; + } +} + From 379d27d9fbf28403b8a6601c66679ec2315c1afa Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 19 Dec 2014 04:25:40 -0800 Subject: [PATCH 264/319] pow --- divide2/Pow_1219_2014.java | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 divide2/Pow_1219_2014.java diff --git a/divide2/Pow_1219_2014.java b/divide2/Pow_1219_2014.java new file mode 100644 index 0000000..c7b5044 --- /dev/null +++ b/divide2/Pow_1219_2014.java @@ -0,0 +1,36 @@ +package Algorithms.divide2; + +public class Pow_1219_2014 { + public double pow(double x, int n) { + if (x == 0) { + return 0; + } + + // base case: when n = 0, the result is 1; + if (n == 0) { + return 1; + } + + /* + 递归的主体部分 + */ + + // X^(-n) = X^(n + 1) * X + // X^n = 1/(x^(-n)) + if (n < 0) { + double ret = x * pow(x, -(n + 1)); + return (double)1/ret; + } + + // 将求pow对半分。再将结果相乘 + double ret = pow(x, n / 2); + ret = ret * ret; + + //如果有余数,再乘以x本身。 + if (n % 2 != 0) { + ret = ret * x; + } + + return ret; + } +} \ No newline at end of file From 3d51a1f27873fde8f1db3f093a9887b262178a2e Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 19 Dec 2014 06:03:55 -0800 Subject: [PATCH 265/319] pow --- math/FastPower.java | 91 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 math/FastPower.java diff --git a/math/FastPower.java b/math/FastPower.java new file mode 100644 index 0000000..8b95b16 --- /dev/null +++ b/math/FastPower.java @@ -0,0 +1,91 @@ +package Algorithms.math; + +class FastPower { + public static void main(String[] strs) { + System.out.println(fastPower(2147483647, 2147483645, 214748364)); + + //System.out.println(Math.pow(2, 2147483647)); + + //System.out.println(-9 % 2); + } + + /* + * @param a, b, n: 32bit integers + * @return: An integer + */ + /* + * @param a, b, n: 32bit integers + * @return: An integer + */ + public static int fastPower(int a, int b, int n) { + // write your code here + long ret = pow(a, b, n); + + return (int) ret; + } + + // suppose n > 0 + public static long pow1(int a, int b, int n) { + if (a == 0) { + return 0; + } + + // The base case. + if (n == 0) { + return 1 % b; + } + + if (n == 1) { + return a % b; + } + + long ret = 0; + + // (a * b) % p = (a % p * b % p) % p (3) + ret = pow(a, b, n / 2); + ret *= ret; + + // 这一步是为了防止溢出 + ret %= b; + + if (n % 2 == 1) { + ret *= pow(a, b, 1); + } + + // 执行取余操作 + ret = ret % b; + + return ret; + } + + // SOLUTION 2: + // suppose n > 0 + public static long pow(int a, int b, int n) { + if (a == 0) { + return 0; + } + + // The base case. + if (n == 0) { + return 1 % b; + } + + long ret = 0; + + // (a * b) % p = (a % p * b % p) % p (3) + ret = pow(a, b, n / 2); + ret *= ret; + + // 这一步是为了防止溢出 + ret %= b; + + if (n % 2 == 1) { + ret *= (a % b); + } + + // 执行取余操作 + ret = ret % b; + + return ret; + } +}; From 93d7e1d792cb5897f99d602aad934e212bccfd3f Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 19 Dec 2014 06:05:05 -0800 Subject: [PATCH 266/319] pow --- {math => lintcode/math}/FastPower.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename {math => lintcode/math}/FastPower.java (98%) diff --git a/math/FastPower.java b/lintcode/math/FastPower.java similarity index 98% rename from math/FastPower.java rename to lintcode/math/FastPower.java index 8b95b16..49cd286 100644 --- a/math/FastPower.java +++ b/lintcode/math/FastPower.java @@ -1,4 +1,4 @@ -package Algorithms.math; +package Algorithms.lintcode.math; class FastPower { public static void main(String[] strs) { From 0e278f11fdde9fa8935cf62406cfc0019a56a578 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 19 Dec 2014 15:41:24 -0800 Subject: [PATCH 267/319] majory --- lintcode/math/FastPower.java | 2 +- lintcode/math/MajorityNumber.java | 49 +++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 lintcode/math/MajorityNumber.java diff --git a/lintcode/math/FastPower.java b/lintcode/math/FastPower.java index 49cd286..561af55 100644 --- a/lintcode/math/FastPower.java +++ b/lintcode/math/FastPower.java @@ -6,7 +6,7 @@ public static void main(String[] strs) { //System.out.println(Math.pow(2, 2147483647)); - //System.out.println(-9 % 2); + System.out.println(9 % (-2)); } /* diff --git a/lintcode/math/MajorityNumber.java b/lintcode/math/MajorityNumber.java new file mode 100644 index 0000000..edab444 --- /dev/null +++ b/lintcode/math/MajorityNumber.java @@ -0,0 +1,49 @@ +package Algorithms.lintcode.math; + +import java.util.ArrayList; + +public class MajorityNumber { + /** + * @param nums: a list of integers + * @return: find a majority number + */ + public int majorityNumber(ArrayList nums) { + // write your code + if (nums == null || nums.size() == 0) { + // No majority number. + return -1; + } + + int candidate = nums.get(0); + + // The phase 1: Voting. + int cnt = 1; + for (int i = 1; i < nums.size(); i++) { + if (nums.get(i) == candidate) { + cnt++; + } else { + cnt--; + if (cnt == 0) { + candidate = nums.get(i); + cnt = 1; + } + } + } + + // The phase 2: Examing. + cnt = 0; + for (int i = 0; i < nums.size(); i++) { + if (nums.get(i) == candidate) { + cnt++; + } + } + + // No majory number. + if (cnt <= nums.size() / 2) { + return -1; + } + + return candidate; + } +} + From ae835022c3e49efe0bd1ba7a3dcfba1722c7c448 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 19 Dec 2014 22:49:28 -0800 Subject: [PATCH 268/319] Rerange --- lintcode/array/Rerange.java | 97 +++++++++++++++++++++++++++++++++++++ sort/QuickSort.java | 60 ++++++++++++----------- 2 files changed, 128 insertions(+), 29 deletions(-) create mode 100644 lintcode/array/Rerange.java diff --git a/lintcode/array/Rerange.java b/lintcode/array/Rerange.java new file mode 100644 index 0000000..9eb57eb --- /dev/null +++ b/lintcode/array/Rerange.java @@ -0,0 +1,97 @@ +package Algorithms.lintcode.array; + +class Rerange { + public static void main(String[] strs) { + int A[] = {1,2,3,4,-1, 2, 5, 5, 5, 6, -7,-8,843,-23,1}; + rerange(A); + + for (int i = 0; i < A.length; i++) { + System.out.print(A[i] + " "); + } + } + + /** + * @param A: An integer array. + * @return an integer array + */ + // SOLUTION 2: 判断正数多还是负数多。 + public static int[] rerange(int[] A) { + // write your code here + + // Check the input parameter. + if (A == null || A.length == 0) { + return A; + } + + int len = A.length; + + int left = -1; + int right = A.length; + + // divide the negative and positive integers. + while (true) { + while (left < A.length - 1 && A[++left] < 0); + + while (left < right && A[--right] > 0); + + if (left >= right) { + break; + } + + swap(A, left, right); + } + + // LEFT: point to the first positive number. + int negNum = left; + int posNum = len - left; + + int les = Math.min(negNum, posNum); + int dif = Math.abs(negNum - posNum); + + // 如果负数比较多,把多的负数扔到后面去 + if (negNum > posNum) { + int cnt = dif; + int l = les; + int r = len - 1; + while (cnt > 0) { + swap(A, l, r); + l++; + r--; + cnt--; + } + + // 负数多的时候,负数在前,反之,正数在前 + left = -1; + // 跳过右边不需要交换的值 + right = A.length - dif; + } else { + // 正数在前 + left = -2; + // 跳过右边不需要交换的值 + right = A.length - dif + 1; + } + + /* + -1 -2 -5 -6 3 4 les = 2; + 4 -2 -5 -6 3 -1 + */ + // swap the negative and the positive + while (true) { + left += 2; + right -= 2; + + if (left >= les) { + break; + } + swap(A, left, right); + } + + return A; + } + + public static void swap(int[] A, int n1, int n2) { + int tmp = A[n1]; + A[n1] = A[n2]; + A[n2] = tmp; + } +} diff --git a/sort/QuickSort.java b/sort/QuickSort.java index 934345c..dcf224c 100644 --- a/sort/QuickSort.java +++ b/sort/QuickSort.java @@ -13,14 +13,17 @@ public class QuickSort { //private static final int SIZE = 100000; - private static final int SIZE = 100000; + private static final int SIZE = 10000; private static Random rand = new Random(); public static void main(String args[]) { int[] array = new int[SIZE]; for (int i = 0; i < SIZE; i++) - array[i] = rand.nextInt(); + //array[i] = rand.nextInt(); + array[i] = i; + + //int[] array = {3, 4, 6, 1, 7, 8, 6}; // reversely ordered /* @@ -60,51 +63,50 @@ private static void recQuickSort(int[] arr, int left, int right) { recQuickSort(arr, left, pivPosition - 1); recQuickSort(arr, pivPosition + 1, right); } - + // partition the array and return the new pivot position. private static int partition(int[] arr, int left, int right, int pivot) { // set the pivot. - int l = left ; - int r = right - 1; + int l = left - 1 ; + int r = right; /* example: - let 4 to be the pivot. + let 6 to be the pivot. (1) At the beginning: - 2 8 7 1 3 5 6 4 - i j + 3 4 6 1 7 8 6 + l r (2) After the first while loop: - 2 8 7 1 3 5 6 4 - i j + 3 4 6 1 7 8 6 + l r (3) swap them, then continue to move i and j: - 2 3 7 1 8 5 6 4 - i j + 3 4 1 6 7 8 6 + l r (3) swap them, then continue to move i and j: - 2 3 1 7 8 5 6 4 - j i pivo - - (4) swap the left and the pivo. - 2 3 1 7 8 5 6 4 - j i pivo + 3 4 1 6 7 8 6 + l pivot + r + (4) swap the left and the pivot. + 3 4 1 6 7 8 6 + l pivot */ while (true) { - // Find the first element which does not fullfill the rule - // When l move to the pivot, it will not move again because arr[l] == pivot. - while (arr[l] < pivot) { - l++; - } + // Find the first element which does not fulfill the rule + // It will not move out of range because the right node is pivot. + // 使用< 很重要,这样可以避免l跑到pivot的位置,就是right的位置 + //while (l < r && arr[++l] <= pivot); + while (arr[++l] < pivot); - // Find the first element which does not fullfill the rule - while (r > 0 && arr[r] > pivot) { - r--; - } + // Find the first element which does not fulfill the rule + // Don't need to move r to be left of LEFT. + while (r > l && arr[--r] > pivot); // If r <= l, means that all the elements is in the right place. if (r <= l) { @@ -115,8 +117,8 @@ private static int partition(int[] arr, int left, int right, int pivot) { swap(arr, r, l); } - // The l pointer point to the first element which is bigger than the pvio. - // So we can put the pvio just here. Because put a big one in the last will not change the rule that: + // The l pointer point to the first element which is bigger than the pivot. + // So we can put the pivot just here. Because put a big or equal one in the last will not change the rule that: // all the smaller one is in the left and the right one is in the right. swap(arr, l, right); From 11a86c5bb34bdeab417cdc4803938366f862abc2 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 19 Dec 2014 23:34:09 -0800 Subject: [PATCH 269/319] queue --- lintcode/stack/StackQueue.java | 43 ++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 lintcode/stack/StackQueue.java diff --git a/lintcode/stack/StackQueue.java b/lintcode/stack/StackQueue.java new file mode 100644 index 0000000..2886fb7 --- /dev/null +++ b/lintcode/stack/StackQueue.java @@ -0,0 +1,43 @@ +package Algorithms.lintcode.stack; + +import java.util.Stack; + +public class StackQueue { + private Stack stack1; + private Stack stack2; + + public StackQueue() { + // do initialization if necessary + stack1 = new Stack(); + stack2 = new Stack(); + } + + public void push(int element) { + // write your code here + stack1.push(element); + } + + public int pop() { + // write your code here + if (stack2.isEmpty()) { + while (!stack1.isEmpty()) { + stack2.push(stack1.pop()); + } + } + + return stack2.pop(); + } + + public int top() { + // write your code here + // write your code here + if (stack2.isEmpty()) { + while (!stack1.isEmpty()) { + stack2.push(stack1.pop()); + } + } + + return stack2.peek(); + } +} + From f8e0a050f9c6b7f38f5321c744dc2b10ac131891 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 20 Dec 2014 03:11:54 -0800 Subject: [PATCH 270/319] majority2 --- lintcode/array/MajorityNumber.java | 61 ++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 lintcode/array/MajorityNumber.java diff --git a/lintcode/array/MajorityNumber.java b/lintcode/array/MajorityNumber.java new file mode 100644 index 0000000..24d0121 --- /dev/null +++ b/lintcode/array/MajorityNumber.java @@ -0,0 +1,61 @@ +package Algorithms.lintcode.array; + +import java.util.ArrayList; + +public class MajorityNumber { + /** + * @param nums: A list of integers + * @return: The majority number that occurs more than 1/3 + */ + public int majorityNumber(ArrayList nums) { + // write your code + // When there are only 1 or 2 elements in the array, + // there is no solution. + if (nums == null || nums.size() <= 2) { + return -1; + } + + int n1 = 0; + int n2 = 0; + + int cnt1 = 0; + int cnt2 = 0; + + int size = nums.size(); + for (int i = 0; i < size; i++) { + int num = nums.get(i); + if (cnt1 != 0 && num == n1) { + cnt1++; + } else if (cnt2 != 0 && num == n2) { + cnt2++; + } else if (cnt1 == 0) { + cnt1 = 1; + n1 = num; + } else if (cnt2 == 0) { + cnt2 = 1; + n2 = num; + } else { + cnt1--; + cnt2--; + } + } + + // count the two candiates. + cnt1 = 0; + cnt2 = 0; + for (int num: nums) { + if (num == n1) { + cnt1++; + } else { + cnt2++; + } + } + + if (cnt1 < cnt2) { + return n2; + } + + return n1; + } +} + From 5a206dff1a852a07bf4165bb412f7aba3f61654e Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 20 Dec 2014 03:12:59 -0800 Subject: [PATCH 271/319] MajorityNumber --- lintcode/array/MajorityNumber.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lintcode/array/MajorityNumber.java b/lintcode/array/MajorityNumber.java index 24d0121..66dae2e 100644 --- a/lintcode/array/MajorityNumber.java +++ b/lintcode/array/MajorityNumber.java @@ -46,7 +46,7 @@ public int majorityNumber(ArrayList nums) { for (int num: nums) { if (num == n1) { cnt1++; - } else { + } else if (num == n2) { cnt2++; } } @@ -59,3 +59,5 @@ public int majorityNumber(ArrayList nums) { } } + + From d24ca2ecf1f240ca8435f7adc8322c6c2c97504c Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 20 Dec 2014 03:39:23 -0800 Subject: [PATCH 272/319] number --- .../{array/MajorityNumber.java => math/MajorityNumber2.java} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename lintcode/{array/MajorityNumber.java => math/MajorityNumber2.java} (95%) diff --git a/lintcode/array/MajorityNumber.java b/lintcode/math/MajorityNumber2.java similarity index 95% rename from lintcode/array/MajorityNumber.java rename to lintcode/math/MajorityNumber2.java index 66dae2e..0dfe87a 100644 --- a/lintcode/array/MajorityNumber.java +++ b/lintcode/math/MajorityNumber2.java @@ -1,8 +1,8 @@ -package Algorithms.lintcode.array; +package Algorithms.lintcode.math; import java.util.ArrayList; -public class MajorityNumber { +public class MajorityNumber2 { /** * @param nums: A list of integers * @return: The majority number that occurs more than 1/3 From d8168b82f37c636c2003e2bf33a610ea16b88e3a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 20 Dec 2014 04:24:11 -0800 Subject: [PATCH 273/319] array --- array/MaxSubArray_1220_2014.java | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 array/MaxSubArray_1220_2014.java diff --git a/array/MaxSubArray_1220_2014.java b/array/MaxSubArray_1220_2014.java new file mode 100644 index 0000000..175e79e --- /dev/null +++ b/array/MaxSubArray_1220_2014.java @@ -0,0 +1,24 @@ +package Algorithms.array; + +public class MaxSubArray_1220_2014 { + public int maxSubArray(int[] A) { + if (A == null || A.length == 0) { + return 0; + } + + int max = Integer.MIN_VALUE; + int sum = 0; + + int len = A.length; + for (int i = 0; i < len; i++) { + if (sum < 0) { + sum = 0; + } + + sum += A[i]; + max = Math.max(max, sum); + } + + return max; + } +} \ No newline at end of file From 40560c09b75ea8df610714f71cf03e918475a1b9 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 20 Dec 2014 15:16:01 -0800 Subject: [PATCH 274/319] product --- array/MaxProduct.java | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/array/MaxProduct.java b/array/MaxProduct.java index 55bf0e4..1cf4054 100644 --- a/array/MaxProduct.java +++ b/array/MaxProduct.java @@ -30,6 +30,31 @@ public static int maxProduct(int[] A) { return max; } + /* + * 2014.12.20 Redo + * */ + public int maxProduct2(int[] A) { + if (A == null || A.length == 0) { + return 0; + } + + int max = 1; + int min = 1; + + int ret = Integer.MIN_VALUE; + for (int i = 0; i < A.length; i++) { + int n1 = max * A[i]; + int n2 = min * A[i]; + + max = Math.max(A[i], Math.max(n1, n2)); + min = Math.min(A[i], Math.min(n1, n2)); + + ret = Math.max(max, ret); + } + + return ret; + } + /* * 作法是找到连续的正数,不断相乘即可。 * */ From c7703fe1f1d8698fb1a8a1484ae09f8e225f46b2 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 21 Dec 2014 03:12:57 -0800 Subject: [PATCH 275/319] string --- string/LongestCommonPrefix_1221_2014.java | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 string/LongestCommonPrefix_1221_2014.java diff --git a/string/LongestCommonPrefix_1221_2014.java b/string/LongestCommonPrefix_1221_2014.java new file mode 100644 index 0000000..859b62d --- /dev/null +++ b/string/LongestCommonPrefix_1221_2014.java @@ -0,0 +1,5 @@ +package Algorithms.string; + +public class LongestCommonPrefix_1221_2014 { + +} From 9fbdf7ee37dccf2807318f6c05500af4e77abe54 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 21 Dec 2014 04:51:43 -0800 Subject: [PATCH 276/319] bst --- string/LongestCommonPrefix_1221_2014.java | 34 ++++- tree/IsValidBST_1221_2014.java | 178 ++++++++++++++++++++++ 2 files changed, 210 insertions(+), 2 deletions(-) create mode 100644 tree/IsValidBST_1221_2014.java diff --git a/string/LongestCommonPrefix_1221_2014.java b/string/LongestCommonPrefix_1221_2014.java index 859b62d..d59c344 100644 --- a/string/LongestCommonPrefix_1221_2014.java +++ b/string/LongestCommonPrefix_1221_2014.java @@ -1,5 +1,35 @@ package Algorithms.string; public class LongestCommonPrefix_1221_2014 { - -} + //http://blog.csdn.net/fightforyourdream/article/details/14642079 + public String longestCommonPrefix(String[] strs) { + if (strs == null || strs.length == 0) { + // bug 2: should not return null. + return ""; + } + + // Find out the shortest length. + String s0 = strs[0]; + int len = s0.length(); + for (String s: strs) { + len = Math.min(len, s.length()); + } + + // The index of the character which is examing. + // Bug 3: 当不会break的时候,结果是错的 + // Bug 4: forget to add int i = 0; + for (int i = 0; i < len; i++) { + // Bug 1: forget to write charAt(i); + char c = s0.charAt(i); + for (int j = 0; j < strs.length; j++) { + if (strs[j].charAt(i) != c) { + // Bug 5: write substring to substring + return s0.substring(0, i); + } + } + } + + // Never break, means strs[0].0-len is the solution. + return s0.substring(0, len); + } +} \ No newline at end of file diff --git a/tree/IsValidBST_1221_2014.java b/tree/IsValidBST_1221_2014.java new file mode 100644 index 0000000..b9678d7 --- /dev/null +++ b/tree/IsValidBST_1221_2014.java @@ -0,0 +1,178 @@ +package Algorithms.tree; + +import java.util.Stack; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class IsValidBST_1221_2014 { + public boolean isValidBST1(TreeNode root) { + // Just use the inOrder traversal to solve the problem. + if (root == null) { + return true; + } + + Stack s = new Stack(); + TreeNode cur = root; + + TreeNode pre = null; + + while(true) { + // Push all the left node into the stack. + while (cur != null) { + s.push(cur); + cur = cur.left; + } + + if (s.isEmpty()) { + break; + } + + // No left node, just deal with the current node. + cur = s.pop(); + + if (pre != null && pre.val >= cur.val) { + return false; + } + + pre = cur; + + // Go to the right node. + cur = cur.right; + } + + return true; + } + + /* + SOLUTION 2: Use the recursive version. + REF: http://blog.csdn.net/fightforyourdream/article/details/14444883 + */ + public boolean isValidBST2(TreeNode root) { + // Just use the inOrder traversal to solve the problem. + if (root == null) { + return true; + } + + return dfs(root, Long.MIN_VALUE, Long.MAX_VALUE); + } + + public boolean dfs(TreeNode root, long low, long up) { + if (root == null) { + return true; + } + + if (root.val >= up || root.val <= low) { + return false; + } + + return dfs(root.left, low, root.val) + && dfs(root.right, root.val, up); + } + + /* + SOLUTION 3: Use the recursive version2. + */ + public boolean isValidBST3(TreeNode root) { + // Just use the inOrder traversal to solve the problem. + if (root == null) { + return true; + } + + return dfs(root, Long.MIN_VALUE, Long.MAX_VALUE); + } + + public class ReturnType { + int min; + int max; + boolean isBST; + public ReturnType (int min, int max, boolean isBST) { + this.min = min; + this.max = max; + this.isBST = isBST; + } + } + + // BST: + // 1. Left tree is BST; + // 2. Right tree is BST; + // 3. root value is bigger than the max value of left tree and + // smaller than the min value of the right tree. + public ReturnType dfs(TreeNode root) { + ReturnType ret = new ReturnType(Integer.MAX_VALUE, Integer.MIN_VALUE, true); + if (root == null) { + return ret; + } + + ReturnType left = dfs(root.left); + ReturnType right = dfs(root.right); + + // determine the left tree and the right tree; + if (!left.isBST || !right.isBST) { + ret.isBST = false; + return ret; + } + + // 判断Root.left != null是有必要的,如果root.val是MAX 或是MIN value,判断会失误 + if (root.left != null && root.val <= left.max) { + ret.isBST = false; + return ret; + } + + if (root.right != null && root.val >= right.min) { + ret.isBST = false; + return ret; + } + + return new ReturnType(Math.min(root.val, left.min), Math.max(root.val, right.max), true); + } + + /* + SOLUTION 4: Use the recursive version3. + */ + TreeNode pre = null; + + public boolean isValidBST(TreeNode root) { + // Just use the inOrder traversal to solve the problem. + return dfs4(root); + } + + public boolean dfs4(TreeNode root) { + if (root == null) { + return true; + } + + // Judge the left tree. + if (!dfs4(root.left)) { + return false; + } + + // judge the sequence. + if (pre != null && root.val <= pre.val) { + return false; + } + pre = root; + + // Judge the right tree. + if (!dfs4(root.right)) { + return false; + } + + return true; + } +} \ No newline at end of file From c1284038caa1a1f37a91eb8f21f747c873cdb92b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 21 Dec 2014 07:51:34 -0800 Subject: [PATCH 277/319] sort --- lintcode/array/SortKColors.java | 115 ++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 lintcode/array/SortKColors.java diff --git a/lintcode/array/SortKColors.java b/lintcode/array/SortKColors.java new file mode 100644 index 0000000..440c48d --- /dev/null +++ b/lintcode/array/SortKColors.java @@ -0,0 +1,115 @@ +package Algorithms.lintcode.array; + +class SortKColors { + public static void main(String[] strs) { + int A[] = {2,2,3,1,1,1,2,3,2,2}; + sortKColors(A, 3); + + for (int i = 0; i < A.length; i++) { + System.out.print(" " + A[i]); + } + } + + + /** + * @param colors: A list of integer + * @param k: An integer + * @return: nothing + */ + /* + Solution 1: Using the quick sort. + */ + public static void sortKColors1(int[] colors, int k) { + // write your code here + if (colors == null) { + return; + } + + quickSort(colors, 0, colors.length - 1); + } + + public static void quickSort(int[] colors, int left, int right) { + if (left >= right) { + return; + } + + int pivot = colors[right]; + + int pos = partition(colors, left, right, pivot); + + quickSort(colors, left, pos - 1); + quickSort(colors, pos + 1, right); + } + + public static int partition(int[] colors, int left, int right, int pivot) { + int leftPoint = left - 1; + int rightPoint = right; + + while (true) { + while (colors[++leftPoint] < pivot); + + while (leftPoint < rightPoint && colors[--rightPoint] > pivot); + + if (leftPoint >= rightPoint) { + break; + } + + swap(colors, leftPoint, rightPoint); + } + + swap(colors, leftPoint, right); + return leftPoint; + } + + public static void swap(int[] colors, int left, int right) { + int tmp = colors[left]; + colors[left] = colors[right]; + colors[right] = tmp; + } + + // Solution 2: inplace, O(n) + public static void sortKColors(int[] colors, int k) { + // write your code here + if (colors == null) { + return; + } + + int len = colors.length; + for (int i = 0; i < len; i++) { + // Means need to deal with A[i] + while (colors[i] > 0) { + int num = colors[i]; + if (colors[num - 1] > 0) { + // 1. There is a number in the bucket, + // Store the number in the bucket in position i; + colors[i] = colors[num - 1]; + colors[num - 1] = -1; + } else if (colors[num - 1] < 0) { + // 2. Bucket is using. + colors[num - 1]--; + // delete the A[i]; + colors[i] = 0; + } else if (colors[num - 1] == 0) { + // 3. The bucket is empty. + colors[num - 1] = -1; + } + } + } + + int index = len - 1; + for (int i = k - 1; i >= 0; i--) { + int cnt = -colors[i]; + + // Empty number. + if (cnt == 0) { + continue; + } + + while (cnt > 0) { + colors[index--] = i + 1; + cnt--; + } + } + } +} + From 9e718d3d155a64dd757eeafa5410a2c88779c991 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 22 Dec 2014 04:00:55 -0800 Subject: [PATCH 278/319] dp --- algorithm/dp/MinPathSum.java | 81 +++++++++++++++++++++++++++++++++ lintcode/array/SortKColors.java | 2 + sort/SortColors.java | 42 +++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 algorithm/dp/MinPathSum.java diff --git a/algorithm/dp/MinPathSum.java b/algorithm/dp/MinPathSum.java new file mode 100644 index 0000000..35bfd95 --- /dev/null +++ b/algorithm/dp/MinPathSum.java @@ -0,0 +1,81 @@ +package Algorithms.algorithm.dp; + +public class MinPathSum { + // Solution 1: DP + public int minPathSum1(int[][] grid) { + if (grid == null || grid.length == 0 || grid[0].length == 0) { + return 0; + } + + int rows = grid.length; + int cols = grid[0].length; + int[][] D = new int[rows][cols]; + + // This is a simple DP. + // 表达式: D[i][j]: 从左下到本点的最小值 + // 递推公式: D[i][j] = Math.mn(D[i - 1][j], D[i][j - 1]) + grid[i][j] + // 初始化: D[i][j] = grid[i][j]. + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + D[i][j] = grid[i][j]; + + if (i == 0 && j != 0) { + D[i][j] += D[i][j - 1]; + } else if (j == 0 && i != 0) { + D[i][j] += D[i - 1][j]; + } else if (i != 0 && j != 0) { + D[i][j] += Math.min(D[i][j - 1], D[i - 1][j]); + } + } + } + + return D[rows - 1][cols - 1]; + } + + // Solution 2: DFS + memory. + public int minPathSum(int[][] grid) { + if (grid == null || grid.length == 0 || grid[0].length == 0) { + return 0; + } + + int[][] memory = new int[grid.length][grid[0].length]; + + // Bug 1: forget to initilize + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + memory[i][j] = -1; + } + } + + return dfs(grid, 0, 0, memory); + } + + public int dfs (int[][] grid, int i, int j, int[][] memory) { + int rows = grid.length; + int cols = grid[0].length; + + if (i >= rows || j >= cols) { + // 表示不可达 + return Integer.MAX_VALUE; + } + + // The base case: arrive the destination. + if (i == rows - 1 && j == cols - 1) { + return grid[i][j]; + } + + // 已经搜索过的点不需要重复搜索 + if (memory[i][j] != -1) { + return memory[i][j]; + } + + int sum = grid[i][j]; + + // 开始dfs 可能的路径,目前我们只有2种可能 + sum += Math.min(dfs(grid, i + 1, j, memory), dfs(grid, i, j + 1, memory)); + + // Record the memory + memory[i][j] = sum; + return sum; + } +} \ No newline at end of file diff --git a/lintcode/array/SortKColors.java b/lintcode/array/SortKColors.java index 440c48d..e9f0509 100644 --- a/lintcode/array/SortKColors.java +++ b/lintcode/array/SortKColors.java @@ -92,6 +92,8 @@ public static void sortKColors(int[] colors, int k) { } else if (colors[num - 1] == 0) { // 3. The bucket is empty. colors[num - 1] = -1; + // delete the A[i]; + colors[i] = 0; } } } diff --git a/sort/SortColors.java b/sort/SortColors.java index 572c352..265b052 100644 --- a/sort/SortColors.java +++ b/sort/SortColors.java @@ -61,9 +61,51 @@ public void sortColors2(int[] A) { } } + // Solution 3: use switch + public void sortColors3(int[] A) { + if (A == null || A.length == 0) { + return; + } + + int left = 0; + + // Bug 1: right is wrong. + int right = A.length - 1; + + int cur = 0; + + // left: the first one which is not 0 + // right: the first one which is not 2 + // So we should use <= because right may be not dealed with. + while (cur <= right) { + switch (A[cur]) { + case 0: + // Bug 0: Forget to add A. + swap(A, left, cur); + left++; + cur++; + break; + case 1: + cur++; + break; + case 2: + swap(A, cur, right); + right--; + // 这里不cur++的原因是,有可能从右边换过来有0,1还要继续处理 + break; + + default: + cur++; + break; + } + } + } + public void swap(int[] A, int n1, int n2) { int tmp = A[n1]; A[n1] = A[n2]; A[n2] = tmp; } + + } \ No newline at end of file From c80395ee3ae7e786b092ef993822b92d2877f1f9 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 22 Dec 2014 04:02:55 -0800 Subject: [PATCH 279/319] d --- algorithm/dp/MinPathSum.java => dp/MinPathSum_1222_2014.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename algorithm/dp/MinPathSum.java => dp/MinPathSum_1222_2014.java (97%) diff --git a/algorithm/dp/MinPathSum.java b/dp/MinPathSum_1222_2014.java similarity index 97% rename from algorithm/dp/MinPathSum.java rename to dp/MinPathSum_1222_2014.java index 35bfd95..8b61c5e 100644 --- a/algorithm/dp/MinPathSum.java +++ b/dp/MinPathSum_1222_2014.java @@ -1,6 +1,6 @@ -package Algorithms.algorithm.dp; +package Algorithms.dp; -public class MinPathSum { +public class MinPathSum_1222_2014 { // Solution 1: DP public int minPathSum1(int[][] grid) { if (grid == null || grid.length == 0 || grid[0].length == 0) { From 89a317e04d6b3011525fbfb907d17625d7ffa39d Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 22 Dec 2014 04:16:13 -0800 Subject: [PATCH 280/319] tree --- tree/LevelOrder.java | 48 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 tree/LevelOrder.java diff --git a/tree/LevelOrder.java b/tree/LevelOrder.java new file mode 100644 index 0000000..cd17a8a --- /dev/null +++ b/tree/LevelOrder.java @@ -0,0 +1,48 @@ +package Algorithms.tree; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class LevelOrder { + public List> levelOrder(TreeNode root) { + List> ret = new ArrayList>(); + if (root == null) { + return ret; + } + + Queue q = new LinkedList(); + q.offer(root); + + while (!q.isEmpty()) { + int size = q.size(); + List list = new ArrayList(); + for (int i = 0; i < size; i++) { + TreeNode cur = q.poll(); + list.add(cur.val); + + if (cur.left != null) { + q.offer(cur.left); + } + + if (cur.right != null) { + q.offer(cur.right); + } + } + + ret.add(list); + } + + return ret; + } +} \ No newline at end of file From 0dc8ca2bbb365885e36cb03c8400c18f61dcec81 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 22 Dec 2014 07:17:06 -0800 Subject: [PATCH 281/319] greedy --- greedy/CanCompleteCircuit.java | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 greedy/CanCompleteCircuit.java diff --git a/greedy/CanCompleteCircuit.java b/greedy/CanCompleteCircuit.java new file mode 100644 index 0000000..4160dea --- /dev/null +++ b/greedy/CanCompleteCircuit.java @@ -0,0 +1,35 @@ +package Algorithms.greedy; + +public class CanCompleteCircuit { + public int canCompleteCircuit(int[] gas, int[] cost) { + if (gas == null || cost == null || gas.length == 0 || cost.length == 0) { + // Bug 0: should not return false; + return -1; + } + + int total = 0; + int sum = 0; + + int startIndex = 0; + + int len = gas.length; + for (int i = 0; i < len; i++) { + int dif = gas[i] - cost[i]; + sum += dif; + + if (sum < 0) { + // Means that from 0 to this gas station, none of them can be the solution. + startIndex = i + 1; // Begin from the next station. + sum = 0; // reset the sum. + } + + total += dif; + } + + if (total < 0) { + return -1; + } + + return startIndex; + } +} \ No newline at end of file From 37080a6da80807bac91c92463e097de091b8f378 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 22 Dec 2014 20:29:27 -0800 Subject: [PATCH 282/319] tree --- tree/SortedArrayToBST.java | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tree/SortedArrayToBST.java diff --git a/tree/SortedArrayToBST.java b/tree/SortedArrayToBST.java new file mode 100644 index 0000000..4f1c1de --- /dev/null +++ b/tree/SortedArrayToBST.java @@ -0,0 +1,38 @@ +package Algorithms.tree; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class SortedArrayToBST { + public TreeNode sortedArrayToBST(int[] num) { + if (num == null || num.length == 0) { + return null; + } + + return sortedArrayToBST(num, 0, num.length - 1); + } + + public TreeNode sortedArrayToBST(int[] num, int left, int right) { + // The base case: + if (left > right) { + return null; + } + + int mid = left + (right - left) / 2; + TreeNode root = new TreeNode(num[mid]); + + TreeNode leftNode = sortedArrayToBST(num, left, mid - 1); + TreeNode rightNode = sortedArrayToBST(num, mid + 1, right); + + root.left = leftNode; + root.right = rightNode; + + return root; + } +} \ No newline at end of file From 7c9bebbaaa0ceb1f2884cb94f1f05bf558f02a0a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 23 Dec 2014 03:10:46 -0800 Subject: [PATCH 283/319] rerange --- lintcode/array/Rerange.java | 105 ++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 3 deletions(-) diff --git a/lintcode/array/Rerange.java b/lintcode/array/Rerange.java index 9eb57eb..6d3030a 100644 --- a/lintcode/array/Rerange.java +++ b/lintcode/array/Rerange.java @@ -2,7 +2,8 @@ class Rerange { public static void main(String[] strs) { - int A[] = {1,2,3,4,-1, 2, 5, 5, 5, 6, -7,-8,843,-23,1}; + //int A[] = {1,2,3,4,-1, 2, 5, 5, -5, 6, -7,-8,843,6,1}; + int A[] = {1,2,-3,-4,-1, -2, -5, -5, -5, 6, -7,-8,843,6,1}; rerange(A); for (int i = 0; i < A.length; i++) { @@ -14,8 +15,8 @@ public static void main(String[] strs) { * @param A: An integer array. * @return an integer array */ - // SOLUTION 2: 判断正数多还是负数多。 - public static int[] rerange(int[] A) { + // SOLUTION 1: 判断正数多还是负数多。 + public static int[] rerange1(int[] A) { // write your code here // Check the input parameter. @@ -94,4 +95,102 @@ public static void swap(int[] A, int n1, int n2) { A[n1] = A[n2]; A[n2] = tmp; } + + /* + Solution 2: + */ + public static int[] rerange(int[] A) { + // write your code here + + // Check the input parameter. + if (A == null || A.length <= 2) { + return A; + } + + int len = A.length; + + int cntPositive = 0; + + for (int num: A) { + if (num > 0) { + cntPositive++; + } + } + + // If positive numbers are more than negative numbers, + // Put the positive numbers at first. + int posPointer = 1; + int negPointer = 0; + + // means + boolean pos = false; + + if (cntPositive > A.length / 2) { + // Have more Positive numbers; + posPointer = 0; + negPointer = 1; + + pos = true; + } + + int i = 1; + int j = len - 2; + + if (pos) { + while (true) { + // Put the positive numbers at the end. + if (i < len && A[i] < 0) { + i += 2; + } + + if (j > i && A[j] > 0) { + j -= 2; + } + + if (i >= j) { + break; + } + + swap(A, i, j); + } + } else { + while (true) { + // Put the negative numbers at the end. + if (i < len && A[i] > 0) { + i += 2; + } + + if (j > i && A[j] < 0) { + j -= 2; + } + + if (i >= j) { + break; + } + + swap(A, i, j); + } + } + + // Reorder the negative and the positive numbers. + while (true) { + // Should move if it is in the range. + while (posPointer < len && A[posPointer] > 0) { + posPointer += 2; + } + + // Should move if it is in the range. + while (negPointer < len && A[negPointer] < 0) { + negPointer += 2; + } + + if (posPointer >= len || negPointer >= len) { + break; + } + + swap(A, posPointer, negPointer); + } + + return A; + } } From a6037c68c74eda074d4ef235a6a75523bb41362b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 23 Dec 2014 03:52:04 -0800 Subject: [PATCH 284/319] rerange --- lintcode/array/Rerange.java | 77 +++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/lintcode/array/Rerange.java b/lintcode/array/Rerange.java index 6d3030a..d02346e 100644 --- a/lintcode/array/Rerange.java +++ b/lintcode/array/Rerange.java @@ -2,8 +2,8 @@ class Rerange { public static void main(String[] strs) { - //int A[] = {1,2,3,4,-1, 2, 5, 5, -5, 6, -7,-8,843,6,1}; - int A[] = {1,2,-3,-4,-1, -2, -5, -5, -5, 6, -7,-8,843,6,1}; + int A[] = {1,2,3,4,-1, 2, 5, 5, -5, 6, -7,-8,843,6,1}; + //int A[] = {1,2,-3,-4,-1, -2, -5, -5, -5, 6, -7,-8,843,6,1}; rerange(A); for (int i = 0; i < A.length; i++) { @@ -99,7 +99,7 @@ public static void swap(int[] A, int n1, int n2) { /* Solution 2: */ - public static int[] rerange(int[] A) { + public static int[] rerange2(int[] A) { // write your code here // Check the input parameter. @@ -193,4 +193,75 @@ public static int[] rerange(int[] A) { return A; } + + /* + Solution 3: + */ + public static int[] rerange(int[] A) { + // write your code here + + // Check the input parameter. + if (A == null || A.length <= 2) { + return A; + } + + int len = A.length; + + int cntPositive = 0; + + // store the positive numbers index. + int i1 = 0; + + for (int i2 = 0; i2 < len; i2++) { + if (A[i2] > 0) { + cntPositive++; + + // Put all the positive numbers at in the left part. + swap(A, i1++, i2); + } + } + + // If positive numbers are more than negative numbers, + // Put the positive numbers at first. + int posPointer = 1; + int negPointer = 0; + + if (cntPositive > A.length / 2) { + // Have more Positive numbers; + posPointer = 0; + negPointer = 1; + + // Reverse the array. + int left = 0; + int right = len -1; + while (left < right) { + int tmp = A[left]; + A[left] = A[right]; + A[right] = tmp; + left++; + right--; + } + } + + // Reorder the negative and the positive numbers. + while (true) { + // Should move if it is in the range. + while (posPointer < len && A[posPointer] > 0) { + posPointer += 2; + } + + // Should move if it is in the range. + while (negPointer < len && A[negPointer] < 0) { + negPointer += 2; + } + + if (posPointer >= len || negPointer >= len) { + break; + } + + swap(A, posPointer, negPointer); + } + + return A; + } } From e3660042f0c254fed06f802ddcb0b4f53a56c4a3 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 23 Dec 2014 04:03:03 -0800 Subject: [PATCH 285/319] rerange --- lintcode/array/Rerange.java | 81 ++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/lintcode/array/Rerange.java b/lintcode/array/Rerange.java index d02346e..15d37c8 100644 --- a/lintcode/array/Rerange.java +++ b/lintcode/array/Rerange.java @@ -3,12 +3,19 @@ class Rerange { public static void main(String[] strs) { int A[] = {1,2,3,4,-1, 2, 5, 5, -5, 6, -7,-8,843,6,1}; - //int A[] = {1,2,-3,-4,-1, -2, -5, -5, -5, 6, -7,-8,843,6,1}; + int B[] = {1,2,-3,-4,-1, -2, -5, -5, -5, 6, -7,-8,843,6,1}; rerange(A); for (int i = 0; i < A.length; i++) { System.out.print(A[i] + " "); } + + rerange(B); + System.out.println(); + + for (int i = 0; i < B.length; i++) { + System.out.print(B[i] + " "); + } } /** @@ -197,7 +204,7 @@ public static int[] rerange2(int[] A) { /* Solution 3: */ - public static int[] rerange(int[] A) { + public static int[] rerange3(int[] A) { // write your code here // Check the input parameter. @@ -264,4 +271,74 @@ public static int[] rerange(int[] A) { return A; } + + /* + Solution 4: + 把reverse的步骤简化了一下 + */ + public static int[] rerange(int[] A) { + // write your code here + + // Check the input parameter. + if (A == null || A.length <= 2) { + return A; + } + + int len = A.length; + + int cntPositive = 0; + + // store the positive numbers index. + int i1 = 0; + + for (int i2 = 0; i2 < len; i2++) { + if (A[i2] > 0) { + cntPositive++; + + // Put all the positive numbers at in the left part. + swap(A, i1++, i2); + } + } + + // If positive numbers are more than negative numbers, + // Put the positive numbers at first. + int posPointer = 1; + int negPointer = 0; + + if (cntPositive > A.length / 2) { + // Have more Positive numbers; + posPointer = 0; + negPointer = 1; + + // Reverse the array. + int left = 0; + int right = len -1; + while (right >= cntPositive) { + swap(A, left, right); + left++; + right--; + } + } + + // Reorder the negative and the positive numbers. + while (true) { + // Should move if it is in the range. + while (posPointer < len && A[posPointer] > 0) { + posPointer += 2; + } + + // Should move if it is in the range. + while (negPointer < len && A[negPointer] < 0) { + negPointer += 2; + } + + if (posPointer >= len || negPointer >= len) { + break; + } + + swap(A, posPointer, negPointer); + } + + return A; + } } From dc16d4acbf31c04c675e389b8e6dcced6d369c34 Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Sat, 27 Dec 2014 02:37:20 -0800 Subject: [PATCH 286/319] lengOf string --- new/FindSubstring.java | 71 ++++++++++++ new/IsPalindrome.java | 25 ++++ new/LRUCache.java | 97 ++++++++++++++++ new/LengthOfLastWord.java | 26 +++++ new/MinWindow.java | 163 +++++++++++++++++++++++++++ new/ThreeSum.java | 61 ++++++++++ string/LengthOfLongestSubstring.java | 61 +++++++++- 7 files changed, 503 insertions(+), 1 deletion(-) create mode 100644 new/FindSubstring.java create mode 100644 new/IsPalindrome.java create mode 100644 new/LRUCache.java create mode 100644 new/LengthOfLastWord.java create mode 100644 new/MinWindow.java create mode 100644 new/ThreeSum.java diff --git a/new/FindSubstring.java b/new/FindSubstring.java new file mode 100644 index 0000000..696a7c2 --- /dev/null +++ b/new/FindSubstring.java @@ -0,0 +1,71 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + + +public class FindSubstring { + public static void main(String[] strs) { + String S = "barfoothefoobarman"; + String[] L = {"foo","bar"}; + + System.out.print(findSubstring(S, L)); + } + + public static List findSubstring(String S, String[] L) { + ArrayList ret = new ArrayList(); + if (S == null || L == null || L.length == 0) { + return ret; + } + + HashMap map = new HashMap(); + HashMap des = new HashMap(); + + for (String s: L) { + if (map.containsKey(s)) { + map.put(s, map.get(s) + 1); + } else { + // bug 1: should be , not . + map.put(s, 1); + } + } + + int wordLen = L[0].length(); + + int size = L.length; + int cnt = 0; + + int len = S.length(); + for (int i = 0; i < len; i++) { + map.clear(); + cnt = 0; + + // pay attention: should use j <= len. + for (int j = i; j <= len - wordLen; j += wordLen) { + String sub = S.substring(j, j + wordLen); + + if (!map.containsKey(sub)) { + break; + } + + if (des.containsKey(sub)) { + des.put(sub, 1 + des.get(sub)); + } else { + des.put(sub, 1); + } + + if (des.get(sub) > map.get(sub)) { + break; + } + + cnt++; + + if (cnt == size) { + ret.add(i); + break; + } + } + } + + return ret; + } +} \ No newline at end of file diff --git a/new/IsPalindrome.java b/new/IsPalindrome.java new file mode 100644 index 0000000..82108e4 --- /dev/null +++ b/new/IsPalindrome.java @@ -0,0 +1,25 @@ + +public class IsPalindrome { + public static void main(String[] strs) { + System.out.print(isPalindrome(12344321)); + } + + public static boolean isPalindrome(int x) { + long y = 0; + + if (x < 0) { + return false; + } + + int tmp = x; + while (tmp > 0) { + int a = tmp % 10; + tmp /= 10; + + y *= 10; + y += a; + } + + return y == x; + } +} \ No newline at end of file diff --git a/new/LRUCache.java b/new/LRUCache.java new file mode 100644 index 0000000..e61f344 --- /dev/null +++ b/new/LRUCache.java @@ -0,0 +1,97 @@ +import java.util.HashMap; + + +public class LRUCache { + public static void main(String[] strs) { + LRUCache cache = new LRUCache(1); + + cache.set(2, 1); + cache.get(2); + cache.set(3, 2); + cache.get(2); + + } + + HashMap map; + int capacity; + + ListNode head; + ListNode tail; + + public class ListNode { + int key; + int val; + ListNode pre; + ListNode next; + + public ListNode (int key, int val) { + this.key = key; + this.val = val; + this.pre = null; + this.next = null; + } + } + + public LRUCache(int capacity) { + this.capacity = capacity; + map = new HashMap(); + + head = new ListNode(-1, -1); + tail = new ListNode(-1, -1); + + head.next = tail; + tail.pre = head; + } + + public void moveToTail(ListNode node) { + // connect the node into the list. + node.pre = tail.pre; + node.next = tail; + + tail.pre.next = node; + tail.pre = node; + } + + public void removeNode(ListNode node) { + node.pre.next = node.next; + node.next.pre = node.pre; + } + + public int get(int key) { + if (map.get(key) == null) { + return -1; + } else { + // move the node to the tail. + ListNode node = map.get(key); + removeNode(node); + moveToTail(node); + + return node.val; + } + } + + public void set(int key, int value) { + ListNode node = map.get(key); + if (node == null) { + node = new ListNode(key, value); + + // but 2: forget to add the node into the map. + map.put(key, node); + } else { + // set the value. + node.val = value; + + removeNode(node); + } + + moveToTail(node); + + // the map is full, remove the head node. + // bug 1: use map.size() instead of map.size. + if (map.size() > capacity) { + map.remove(head.next.key); + + removeNode(head.next); + } + } +} \ No newline at end of file diff --git a/new/LengthOfLastWord.java b/new/LengthOfLastWord.java new file mode 100644 index 0000000..4b6ea01 --- /dev/null +++ b/new/LengthOfLastWord.java @@ -0,0 +1,26 @@ + +public class LengthOfLastWord { + public static void main(String[] strs) { + System.out.println(lengthOfLastWord(" a")); + } + + public static int lengthOfLastWord(String s) { + if (s == null || s.length() == 0) { + return 0; + } + + String strNew = s.trim(); + + int len = strNew.length(); + + int start = 0; + for (int i = len - 1; i >= 0; i--) { + if (s.charAt(i) == ' ') { + start = i + 1; + break; + } + } + + return (len - start); + } +} \ No newline at end of file diff --git a/new/MinWindow.java b/new/MinWindow.java new file mode 100644 index 0000000..2a19ed8 --- /dev/null +++ b/new/MinWindow.java @@ -0,0 +1,163 @@ +import java.util.HashMap; + + +public class MinWindow { + + public static void main(String[] args) { + // TODO Auto-generated method stub + System.out.println(minWindow("ab", "b")); + } + + public static String minWindow1(String S, String T) { + int lenS = S.length(); + int lenT = T.length(); + + if (lenT > lenS) { + // No such window + return ""; + } + + HashMap map = new HashMap(); + for (int i = 0; i < lenT; i++) { + char c = T.charAt(i); + if (map.containsKey(c)) { + map.put(c, map.get(c) + 1); + } else { + map.put(c, 1); + } + } + + int cnt = 0; + int size = map.size(); + + int left = -1; + + String sub = ""; + int minLen = Integer.MAX_VALUE; + + // bug 1: should use ';' instead of ',' + for (int right = 0; right < lenS; right++) { + // bug 2: write i instead of right. + char c = S.charAt(right); + + // bug 5: should add this statement to skip the invalid characters. + if (!map.containsKey(c)) { + continue; + } + + map.put(c, map.get(c) - 1); + + if (map.get(c) == 0) { + cnt++; + } + + //compress the left side. + if (cnt == size) { + while (left < lenS - 1) { + left++; + + char cLeft = S.charAt(left); + if (!map.containsKey(cLeft)) { + // bug 6. + // skip the invalid characters. + continue; + } + + map.put(cLeft, map.get(cLeft) + 1); + + // bug: should use > 0, because it means that the characters is not enought + // if the number of characters reduce to below level, we should break; + if (map.get(cLeft) > 0) { + cnt--; + // Bug 7: + if (minLen > right - left + 1) { + minLen = right - left + 1; + sub = S.substring(left, right + 1); + } + + break; + } + + + + } + } + } + + return sub; + } + + public static String minWindow(String S, String T) { + int lenS = S.length(); + int lenT = T.length(); + + String sub = ""; + + if (lenT > lenS) { + // No such window + return sub; + } + + // ʽʼĬ0 + // http://developer.51cto.com/art/200906/128274.htm + + // store the number of the characters. + int[] src = new int[128]; + int[] des = new int[128]; + + int size = 0, cnt = 0; + + for (int i = 0; i < lenT; i++) { + int num = T.charAt(i); + src[num]++; + + if (src[num] == 1) { + size++; + } + } + + int minLen = Integer.MAX_VALUE; + + int left = -1; + + for (int right = 0; right < lenS; right++) { + char c = S.charAt(right); + if (src[c] != 0) { + des[c]++; + + // bug 1: the statement should be in the 'src[c] != 0' + if (des[c] == src[c]) { + cnt++; + } + } + + if (cnt == size) { + while (left < lenS - 1) { + left++; + + char cLeft = S.charAt(left); + + // skip the invalid character. + if (src[cLeft] == 0) { + continue; + } + + des[cLeft]--; + if (src[cLeft] > des[cLeft]) { + cnt--; // the count reduce to the lower bound. + + // put the statement here. + int len = right - left + 1; + if (len < minLen) { + minLen = len; + sub = S.substring(left, right + 1); + } + break; + } + } + } + } + + return sub; + } +} diff --git a/new/ThreeSum.java b/new/ThreeSum.java new file mode 100644 index 0000000..995d245 --- /dev/null +++ b/new/ThreeSum.java @@ -0,0 +1,61 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + + +public class ThreeSum { + public static void main(String[] str) { + int[] num = {0,0,0,0}; + System.out.println(threeSum(num)); + } + + public static List> threeSum(int[] num) { + ArrayList> ret = new ArrayList>(); + if (num == null || num.length == 0) { + return ret; + } + + int len = num.length; + + // sort the array to get unique solutions. + Arrays.sort(num); + for (int i = 0; i < len - 2; i++) { + // skip the duplicate numbers. + while (i != 0 && num[i] == num[i - 1]) { + continue; + } + + int n2 = i + 1; + int n3 = len - 1; + + while (n2 < n3) { + int sum = num[i] + num[n2] + num[n3]; + if (sum == 0) { + ArrayList list = new ArrayList(); + list.add(i); + list.add(n2); + list.add(n3); + ret.add(list); + + n2++; + n3--; + + // skip the duplication. + while (n2 < len - 1 && num[n2] == num[n2 - 1]) { + n2++; + } + + while (n3 > i && num[n3] == num[n3 + 1]) { + n3--; + } + } else if (sum > 0) { + n3--; + } else { + n2++; + } + } + } + + return ret; + } +} \ No newline at end of file diff --git a/string/LengthOfLongestSubstring.java b/string/LengthOfLongestSubstring.java index 1b7a7ba..ae8f44f 100644 --- a/string/LengthOfLongestSubstring.java +++ b/string/LengthOfLongestSubstring.java @@ -24,7 +24,6 @@ public int lengthOfLongestSubstring(String s) { } } - //更新map里的char 的位置 map.put(c, end); int subLen = end - start + 1; @@ -33,4 +32,64 @@ public int lengthOfLongestSubstring(String s) { return max; } + + public int lengthOfLongestSubstring1(String s) { + if (s == null) { + return 0; + } + + int max = 0; + HashMap map = new HashMap(); + + int len = s.length(); + int l = 0; + for (int r = 0; r < len; r++) { + char c = s.charAt(r); + + if (map.containsKey(c) && map.get(c) >= l) { + l = map.get(c) + 1; + } + + // replace the last index of the character c. + map.put(c, r); + + // replace the max value. + max = Math.max(max, r - l + 1); + } + + return max; + } + + // SOLUTION 2: use the array. + public int lengthOfLongestSubstring2(String s) { + if (s == null) { + return 0; + } + + int max = 0; + + // suppose there are only ASCII code. + int[] lastIndex = new int[128]; + for (int i = 0; i < 128; i++) { + lastIndex[i] = -1; + } + + int len = s.length(); + int l = 0; + for (int r = 0; r < len; r++) { + char c = s.charAt(r); + + if (lastIndex[c] >= l) { + l = lastIndex[c] + 1; + } + + // replace the last index of the character c. + lastIndex[c] = r; + + // replace the max value. + max = Math.max(max, r - l + 1); + } + + return max; + } } \ No newline at end of file From 2dcb1ce629cf9ef74a0c1160fb3c6b2ca2cd7f2b Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Sat, 27 Dec 2014 21:48:32 -0800 Subject: [PATCH 287/319] new code list code. --- dp/IsScramble.java | 60 +++++++-- dp/LongestPalindrome_dp1.java | 83 ++++++++++-- list/ReverseKGroup.java | 4 +- list/ReverseKGroup_1227_2014.java | 201 ++++++++++++++++++++++++++++++ new/LengthOfLastWord.java | 1 - 5 files changed, 327 insertions(+), 22 deletions(-) create mode 100644 list/ReverseKGroup_1227_2014.java diff --git a/dp/IsScramble.java b/dp/IsScramble.java index 4c28f03..115c774 100644 --- a/dp/IsScramble.java +++ b/dp/IsScramble.java @@ -33,7 +33,7 @@ public static boolean rec1(String s1, String s2) { return s1.equals(s2); } - // 划分2个字符串 + // 鍒掑垎2涓瓧绗︿覆 for (int i = 1; i < len; i++) { // we have two situation; // the left-left right-right & left-right right-left @@ -52,7 +52,7 @@ && rec1(s1.substring(i, len), s2.substring(0, len - i))) { } // Solution 2: The recursion version with sorting. - // 排序之后的剪枝可以通过LeetCode的检查 + // 鎺掑簭涔嬪悗鐨勫壀鏋濆彲浠ラ�杩嘗eetCode鐨勬鏌� public static boolean rec(String s1, String s2) { int len = s1.length(); @@ -74,7 +74,7 @@ public static boolean rec(String s1, String s2) { return false; } - // 划分2个字符串 + // 鍒掑垎2涓瓧绗︿覆 for (int i = 1; i < len; i++) { // we have two situation; // the left-left right-right & left-right right-left @@ -93,7 +93,7 @@ && rec(s1.substring(i, len), s2.substring(0, len - i))) { } // Solution 3: The recursion version with memory. - // 通过记忆矩阵来减少计算量 + // 閫氳繃璁板繂鐭╅樀鏉ュ噺灏戣绠楅噺 public static boolean isScramble3(String s1, String s2) { if (s1 == null || s2 == null) { return false; @@ -121,7 +121,7 @@ public static boolean isScramble3(String s1, String s2) { } // Solution 3: The recursion version with memory. - // 通过记忆矩阵来减少计算量 + // 閫氳繃璁板繂鐭╅樀鏉ュ噺灏戣绠楅噺 public static boolean recMem(String s1, int index1, String s2, int index2, int len, int[][][] mem) { // the base case. @@ -135,10 +135,10 @@ public static boolean recMem(String s1, int index1, String s2, int index2, return ret == 1 ? true : false; } - // 初始化为false + // 鍒濆鍖栦负false ret = 0; - // 划分2个字符串. i means the length of the left side in S1 + // 鍒掑垎2涓瓧绗︿覆. i means the length of the left side in S1 for (int i = 1; i < len; i++) { // we have two situation; // the left-left right-right & left-right right-left @@ -162,7 +162,7 @@ && recMem(s1, index1 + i, s2, index2, len - i, mem)) { /* * Solution 4: The DP Version. */ - public static boolean isScramble(String s1, String s2) { + public static boolean isScramble4(String s1, String s2) { if (s1 == null || s2 == null) { return false; } @@ -183,8 +183,6 @@ public static boolean isScramble(String s1, String s2) { */ boolean[][][] D = new boolean[len1][len1][len1 + 1]; for (int subLen = 1; subLen <= len1; subLen++) { - // 注意这里的边界选取。 如果选的不对,就会发生越界的情况.. orz.. - // 另外,这里要取 i1 <= for (int i1 = 0; i1 <= len1 - subLen; i1++) { for (int i2 = 0; i2 <= len1 - subLen; i2++) { if (subLen == 1) { @@ -207,5 +205,47 @@ public static boolean isScramble(String s1, String s2) { return D[0][0][len1]; } + + /* + * Solution 4: The DP Version. REDO + */ + public static boolean isScramble(String s1, String s2) { + if (s1 == null || s2 == null) { + return false; + } + + int len = s1.length(); + + if (s2.length() != len) { + return false; + } + + boolean[][][] D = new boolean[len][len][len + 1]; + + // D[i][j][k] = D[i][] + for (int k = 1; k <= len; k++) { + // 注意这里的边界选取。 如果选的不对,就会发生越界的情况.. orz.. + // attention: should use "<=" + for (int i = 0; i <= len - k; i++) { + for (int j = 0; j <= len - k; j++) { + if (k == 1) { + D[i][j][k] = s1.charAt(i) == s2.charAt(j); + continue; + } + + D[i][j][k] = false; + for (int l = 1; l <= k - 1; l++) { + if (D[i][j][l] && D[i + l][j + l][k - l] + || D[i][j + k - l][l] && D[i + l][j][k - l] ) { + D[i][j][k] = true; + break; + } + } + } + } + } + + return D[0][0][len]; + } } diff --git a/dp/LongestPalindrome_dp1.java b/dp/LongestPalindrome_dp1.java index 2b5811b..745fb1c 100644 --- a/dp/LongestPalindrome_dp1.java +++ b/dp/LongestPalindrome_dp1.java @@ -20,9 +20,6 @@ public static String longestPalindrome1(String s) { int max = 0; int retB = 0; int retE = 0; - // 这样写的目的是,从前往后扫描时,被记录的DP值可以被复用 - // 因为D[i][j] 要用到i + 1, j - 1,所以每一次计算j时,把j对应的i全部计算完,这样 - // 下一次计算i,j的时候,可以有i+1, j-1可以用。 for (int j = 0; j < len; j++) { for (int i = 0; i <= j; i++) { if (s.charAt(i) == s.charAt(j) @@ -44,8 +41,35 @@ public static String longestPalindrome1(String s) { return s.substring(retB, retE + 1); } - // solution 2: 中心展开法。从头扫到尾部,每一个字符以它为中心向两边扩展,找最长回文。 - // 复杂度为N^2 并且是inplace,空间复杂度O(1) + // SOLUTION 1: Re do 2014.12.26 + public String longestPalindrome4(String s) { + if (s == null) { + return null; + } + + String ret = null; + + int len = s.length(); + int max = 0; + + boolean[][] D = new boolean[len][len]; + + for (int j = 0; j < len; j++) { + for (int i = 0; i <= j; i++) { + D[i][j] = s.charAt(i) == s.charAt(j) && (j - i <= 2 || D[i + 1][j - 1]); + if (D[i][j]) { + if (j - i + 1 > max) { + max = j - i + 1; + ret = s.substring(i, j + 1); + } + } + } + } + + return ret; + } + + // solution 2: 中心展开法 空间复杂度O(1) public static String longestPalindrome(String s) { if (s == null) { return null; @@ -61,14 +85,14 @@ public static String longestPalindrome(String s) { String ret = ""; for (int i = 0; i < len; i++) { - // 考虑奇数字符串 + // 鑰冭檻濂囨暟瀛楃涓� String s1 = expandAround(s, i, i); if (s1.length() > max) { ret = s1; max = s1.length(); } - // 考虑偶数长度的字符串 + // 鑰冭檻鍋舵暟闀垮害鐨勫瓧绗︿覆 String s2 = expandAround(s, i, i + 1); if (s2.length() > max) { ret = s2; @@ -91,7 +115,50 @@ public static String expandAround(String s, int c1, int c2) { c2++; } - // 注意,根据 substring的定义,c2不要减1 + // 娉ㄦ剰锛屾牴鎹�substring鐨勫畾涔夛紝c2涓嶈鍑� return s.substring(c1 + 1, c2); } + + // SOLUTION 2: Redo 2014.12.26 + public String longestPalindrome3(String s) { + if (s == null) { + return null; + } + + String ret = null; + + int len = s.length(); + int max = 0; + for (int i = 0; i < len; i++) { + String s1 = getLongest(s, i, i); + String s2 = getLongest(s, i, i + 1); + + if (s1.length() > max) { + max = Math.max(max, s1.length()); + ret = s1; + } + + if (s2.length() > max) { + max = Math.max(max, s2.length()); + ret = s2; + } + } + + return ret; + } + + public String getLongest(String s, int left, int right) { + int len = s.length(); + while (left >= 0 && right < len) { + // when i is in the center. + if (s.charAt(left) != s.charAt(right)) { + break; + } + + left--; + right++; + } + + return s.substring(left + 1, right); + } } diff --git a/list/ReverseKGroup.java b/list/ReverseKGroup.java index 919e6f9..105581f 100644 --- a/list/ReverseKGroup.java +++ b/list/ReverseKGroup.java @@ -16,7 +16,6 @@ public class ReverseKGroup { // Solution 1: // recursion. - // 思路是先反转,如果发现长度不够K,再翻回来 public ListNode reverseKGroup1(ListNode head, int k) { if (head == null) { return null; @@ -63,8 +62,7 @@ public ListNode rec(ListNode head, int k) { } /* - * Solution 2: - * 使用区间反转的办法, iteration. + * Solution 2: iteration. * */ public ListNode reverseKGroup(ListNode head, int k) { if (head == null) { diff --git a/list/ReverseKGroup_1227_2014.java b/list/ReverseKGroup_1227_2014.java new file mode 100644 index 0000000..6323c2c --- /dev/null +++ b/list/ReverseKGroup_1227_2014.java @@ -0,0 +1,201 @@ +package Algorithms.list; + +import Algorithms.algorithm.others.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class ReverseKGroup_1227_2014 { + public static void main(String[] strs) { + ListNode node1 = new ListNode(1); + ListNode node2 = new ListNode(2); + + node1.next = node2; + + System.out.println(reverseKGroup(node1, 1)); + + } + + public ListNode reverseKGroup1(ListNode head, int k) { + if (head == null) { + return null; + } + + return rec(head, k); + } + + // Solution 1: Recursion. + public ListNode rec(ListNode head, int k) { + // Reverse k and link to the next section. + ListNode dummy = new ListNode(0); + dummy.next = head; + + // find the tail node of the section. If not find, just return. + int cnt = k; + ListNode tail = dummy; + while (cnt > 0 && tail != null) { + cnt--; + tail = tail.next; + } + + // We don't have k nodes to revers. + // bug 1: we should judge that if tail == null to avoid the overflow. + if (tail == null) { + return head; + } + + // cut the 2 list. + ListNode next = tail.next; + tail.next = null; + + // reverse the first list. + ListNode newHead = reverse(head); + + // reverse the next section. + next = rec(next, k); + + // link the 2 sections. + head.next = next; + + return newHead; + } + + public ListNode reverse(ListNode head) { + ListNode dummy = new ListNode(0); + while (head != null) { + ListNode tmp = head.next; + head.next = dummy.next; + dummy.next = head; + + head = tmp; + } + + return dummy.next; + } + + /* + SOLUTION 2: A better rec version. + */ + public ListNode reverseKGroup2(ListNode head, int k) { + if (head == null) { + return null; + } + + return rec2(head, k); + } + + public ListNode rec2(ListNode head, int k) { + if (head == null) { + return null; + } + + ListNode dummy = new ListNode(0); + + ListNode cur = head; + int cnt = 0; + while (cur != null) { + ListNode tmp = cur.next; + cur.next = dummy.next; + dummy.next = cur; + + cur = tmp; + + cnt++; + + // reverse a k group. + if (cnt == k) { + // BUG 1: + head.next = rec2(tmp, k); + return dummy.next; + } + } + + // we don't have k nodes. + if (cnt != k) { + cur = dummy.next; + dummy.next = null; + + // reverse again. + while (cur != null) { + ListNode tmp = cur.next; + cur.next = dummy.next; + dummy.next = cur; + + cur = tmp; + } + } + + return dummy.next; + } + + /* + SOLUTION 3: A Iteration version. + */ + public static ListNode reverseKGroup(ListNode head, int k) { + if (head == null) { + return null; + } + + ListNode dummy = new ListNode(0); + dummy.next = head; + + ListNode pre = dummy; + ListNode cur = pre.next; + + int cnt = 0; + while (cur != null) { + cnt++; + cur = cur.next; + + if (cnt == k) { + cnt = 0; + pre = reverseSection(pre, cur); + cur = pre.next; + } + } + + return dummy.next; + } + + + /** + * Reverse a link list between pre and next exclusively + * an example: + * a linked list: + * 0->1->2->3->4->5->6 + * | | + * pre next + * after call pre = reverse(pre, next) + * + * 0->3->2->1->4->5->6 + * | | + * pre next + * @param pre + * @param next + * @return the reversed list's last node, which is the precedence of parameter next + */ + private static ListNode reverseSection(ListNode pre, ListNode next){ + ListNode cur = pre.next; + + // record the new tail. + ListNode tail = cur; + + while (cur != next) { + ListNode tmp = cur.next; + cur.next = pre.next; + pre.next = cur; + cur = tmp; + } + + tail.next = next; + return tail; + } +} \ No newline at end of file diff --git a/new/LengthOfLastWord.java b/new/LengthOfLastWord.java index 4b6ea01..0ea8ae4 100644 --- a/new/LengthOfLastWord.java +++ b/new/LengthOfLastWord.java @@ -1,4 +1,3 @@ - public class LengthOfLastWord { public static void main(String[] strs) { System.out.println(lengthOfLastWord(" a")); From 3e56cf6cd7256695489681193098c4e91cbff2aa Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Sun, 28 Dec 2014 06:11:40 -0800 Subject: [PATCH 288/319] isMatch --- dp/IsMatch.java | 5 - dp/MinDistance.java | 56 +++++++---- string/isMatch_2014_1228.java | 182 ++++++++++++++++++++++++++++++++++ 3 files changed, 217 insertions(+), 26 deletions(-) create mode 100644 string/isMatch_2014_1228.java diff --git a/dp/IsMatch.java b/dp/IsMatch.java index e6363ce..f5dd65c 100644 --- a/dp/IsMatch.java +++ b/dp/IsMatch.java @@ -19,7 +19,6 @@ public static boolean isMatch1(String s, String p) { int lens = s.length(); int lenp = p.length(); - // 创建一个Dp二维数组 boolean[][] D = new boolean[lens + 1][lenp + 1]; boolean flag = false; @@ -52,7 +51,6 @@ public static boolean isMatch1(String s, String p) { flag = true; } - // Greedy. 在此即可以退出,因为* 可以匹配余下的所有的字符串。 if (D[i][j] && p.charAt(j - 1) == '*' && j == lenp) { return true; } @@ -95,12 +93,10 @@ public static boolean isMatch(String s, String p) { indexP++; } - //P的最后一个是 *,表示可以匹配任何字符串 if (indexP == lenP) { return true; } - // 记录下这个匹配位置。 back = true; preS = indexS; preP = indexP; @@ -114,7 +110,6 @@ public static boolean isMatch(String s, String p) { } } - // 跳过末尾的所有的*. while (indexP < lenP && p.charAt(indexP) == '*') { indexP++; } diff --git a/dp/MinDistance.java b/dp/MinDistance.java index 55bcc01..51ba723 100644 --- a/dp/MinDistance.java +++ b/dp/MinDistance.java @@ -22,9 +22,6 @@ public static void main(String[] strs) { System.out.println(disLessThenTwo(str3, str4)); } - /* - * 递归解法,效果跟动规是一样的。而且想起来还可能要简单一点儿。 - * */ public static int dfs(String word1, int len1, String word2, int len2, int[][] record) { if (len1 <= 0) { return len2; @@ -43,10 +40,8 @@ public static int dfs(String word1, int len1, String word2, int len2, int[][] re int index1 = word1.length() - len1; int index2 = word2.length() - len2; if (word1.charAt(index1) == word2.charAt(index2)) { - // 相等的时候,只需要直接下一步Rec ret = dfs(word1, len1 - 1, word2, len2 - 1, record); } else { - // 不相同的时候,有删除,添加,替换三种操作,分别求解并且求一个最小值 int del = dfs(word1, len1 - 1, word2, len2, record) + 1; int add = dfs(word1, len1, word2, len2 - 1, record) + 1; int replace = dfs(word1, len1 - 1, word2, len2 - 1, record) + 1; @@ -59,10 +54,6 @@ public static int dfs(String word1, int len1, String word2, int len2, int[][] re return ret; } - /* - * 递归解法,判断edit次数是不是小于2. - 也就是说,edit只能为1,或是为0 - * */ public static boolean disLessThenTwo(String word1, String word2) { if (word1 == null || word2 == null) { return false; @@ -73,17 +64,9 @@ public static boolean disLessThenTwo(String word1, String word2) { int dis = 1; - // 解法原理:如果2个字符串只差最多1的话,有2种情况: - // 1. 两个字符串相同长度,那肯定是存在replace 一个字符。所以如果遇到不同的字符串, - // 两个指针都向前移动,一旦遇到不同的,就认为错误退出即可。 - // 2. 两个字符串长度不等。那肯定是用了add/delete操作才能使2个字符串相同。所以, - // 一旦遇到不同的字符,它肯定是插入进去的。 - // 可以将长度长的字符串向后移动,如果后面出现不等的,也是错误退出。 - for (int p1 = 0, p2 = 0; p1 < len1 && p2 < len2; p1++, p2++) { if (word1.charAt(p1) != word2.charAt(p2)) { dis--; - // 如果不同的字母超过1了,退出 if (dis < 0) { return false; } else { @@ -104,8 +87,7 @@ public static boolean disLessThenTwo(String word1, String word2) { public static int minDistance(String word1, String word2) { // THE DP FORMULA // D[i][j]: The min operations to change from s1 to s2. - // s1: i characters in word1, s2: j characters in word2. - // + // s1: 0-i in word1, s2: 0-j in word2. // D[i][j] = if (word1 == null || word2 == null) { @@ -137,8 +119,6 @@ public static int minDistance(String word1, String word2) { // 3. D[i - 1][j - 1] D[i][j] = Math.min(D[i][j - 1] + 1, D[i - 1][j] + 1); - // 注意这里的Index是 i - 1 跟 j - 1. - // 因为i的意思是从string1取出i个字符,所以最后一个字符的索引是i - 1 if (word1.charAt(i - 1) == word2.charAt(j - 1)) { // 最后一个字符相等,不需要变化 D[i][j] = Math.min(D[i][j], D[i - 1][j - 1]); @@ -152,4 +132,38 @@ public static int minDistance(String word1, String word2) { return D[len1][len2]; } + + /* + * DP: 2014.12.28 Redo. + * */ + public int minDistance2(String word1, String word2) { + if (word1 == null || word2 == null) { + return 0; + } + + int len1 = word1.length(); + int len2 = word2.length(); + + int[][] D = new int[len1 + 1][len2 + 1]; + + for (int i = 0; i <= len1; i++) { + for (int j = 0; j <= len2; j++) { + if (i == 0) { + D[i][j] = j; + } else if (j == 0) { + D[i][j] = i; + } else { + if (word1.charAt(i - 1) == word2.charAt(j - 1)) { + D[i][j] = D[i - 1][j - 1]; + } else { + D[i][j] = Math.min(D[i - 1][j - 1], D[i][j - 1]); + D[i][j] = Math.min(D[i][j], D[i - 1][j]); + D[i][j]++; + } + } + } + } + + return D[len1][len2]; + } } diff --git a/string/isMatch_2014_1228.java b/string/isMatch_2014_1228.java new file mode 100644 index 0000000..098d6ae --- /dev/null +++ b/string/isMatch_2014_1228.java @@ -0,0 +1,182 @@ +package Algorithms.string; + +public class isMatch_2014_1228 { + public boolean isMatch1(String s, String p) { + if (s == null || p == null) { + return false; + } + + return dfs(s, p, 0, 0); + } + + public boolean dfs(String s, String p, int indexS, int indexP) { + int lenS = s.length(); + int lenP = p.length(); + + // THE BASE CASE: + if (indexP >= lenP) { + // indexP is out of range. Then the s should also be empty. + return indexS >= lenS; + } + + // The first Case: next node is * + if (indexP != lenP - 1 && p.charAt(indexP + 1) == '*') { + // p can skip 2 node, and the S can skip 0 or more characters. + if (dfs(s, p, indexS, indexP + 2)) { + return true; + } + + for (int i = indexS; i < lenS; i++) { + // the char is not equal. + // bug 2: Line 31: java.lang.StringIndexOutOfBoundsException: String index out of range: -1 + if (!isSame(s.charAt(i), p.charAt(indexP))) { + return false; + } + + if (dfs(s, p, i + 1, indexP + 2)) { + return true; + } + } + + // Not any of them can match. + return false; + } else { + // S should have at least one character left. + if (indexS >= lenS) { + return false; + } + + if (!isSame(s.charAt(indexS), p.charAt(indexP))) { + return false; + } + + // bug 1: forget ';' + return dfs(s, p, indexS + 1, indexP + 1); + } + } + + public boolean isSame(char c, char p) { + return p == '.' || c == p; + } + + // solution2: dfs + memory + public boolean isMatch2(String s, String p) { + if (s == null || p == null) { + return false; + } + + int[][] mem = new int[s.length() + 1][p.length() + 1]; + + // BUG 1: forget to init the memory array. + // BUG 2: the corner is <= + for (int i = 0; i <= s.length(); i++) { + for (int j = 0; j <= p.length(); j++) { + mem[i][j] = -1; + } + } + + return dfsMem(s, p, 0, 0, mem); + } + + public boolean dfsMem(String s, String p, int indexS, int indexP, int[][] mem) { + int lenS = s.length(); + int lenP = p.length(); + + if (mem[indexS][indexP] != -1) { + return mem[indexS][indexP] == 1; + } + + // THE BASE CASE: + if (indexP >= lenP) { + // indexP is out of range. Then the s should also be empty. + mem[indexS][indexP] = indexS >= lenS ? 1: 0; + return indexS >= lenS; + } + + // The first Case: next node is * + if (indexP != lenP - 1 && p.charAt(indexP + 1) == '*') { + // p can skip 2 node, and the S can skip 0 or more characters. + if (dfsMem(s, p, indexS, indexP + 2, mem)) { + mem[indexS][indexP] = 1; + return true; + } + + for (int i = indexS; i < lenS; i++) { + // the char is not equal. + // bug 2: Line 31: java.lang.StringIndexOutOfBoundsException: String index out of range: -1 + if (!isSame(s.charAt(i), p.charAt(indexP))) { + mem[indexS][indexP] = 0; + return false; + } + + if (dfsMem(s, p, i + 1, indexP + 2, mem)) { + mem[indexS][indexP] = 1; + return true; + } + } + + // Not any of them can match. + mem[indexS][indexP] = 0; + return false; + } else { + // S should have at least one character left. + boolean ret = indexS < lenS + && isSame(s.charAt(indexS), p.charAt(indexP)) + && dfsMem(s, p, indexS + 1, indexP + 1, mem); + + mem[indexS][indexP] = ret ? 1: 0; + return ret; + } + } + + // solution4: DP + public boolean isMatch(String s, String p) { + if (s == null || p == null) { + return false; + } + + // bug 2: should use boolean instead of int. + boolean[][] D = new boolean[s.length() + 1][p.length() + 1]; + + // D[i][j]: i, j, the length of String s and String p. + for (int i = 0; i <= s.length(); i++) { + for (int j = 0; j <= p.length(); j++) { + if (j == 0) { + // when p is empth, the s should be empty. + D[i][j] = i == 0; + } else if (p.charAt(j - 1) == '*') { + /* + P has at least one node. + */ + + // The last node in p is '*' + if (j < 2) { + // a error: there should be a character before *. + //return false; + } + + // we can match 0 characters or match more characters. + for (int k = 0; k <= i; k++) { + // BUG 3: severe! Forget to deal with the empty string!! + if (k != 0 && !isSame(s.charAt(i - k), p.charAt(j - 2))) { + D[i][j] = false; + break; + } + + if (D[i - k][j - 2]) { + D[i][j] = true; + break; + } + } + } else { + D[i][j] = i >= 1 + && isSame(s.charAt(i - 1), p.charAt(j - 1)) + && D[i - 1][j - 1]; + } + } + } + + return D[s.length()][p.length()]; + } + +} \ No newline at end of file From 21faae49beced959aa96656d20df8166844922d8 Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Mon, 29 Dec 2014 00:03:35 -0800 Subject: [PATCH 289/319] largest --- array/LargestRectangleArea.java | 44 +++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 array/LargestRectangleArea.java diff --git a/array/LargestRectangleArea.java b/array/LargestRectangleArea.java new file mode 100644 index 0000000..2fcb80c --- /dev/null +++ b/array/LargestRectangleArea.java @@ -0,0 +1,44 @@ +package Algorithms.array; + +import java.util.Stack; + +public class LargestRectangleArea { + public static void main(String[] strs) { + int[] height = {0}; + System.out.println(largestRectangleArea(height)); + } + + public static int largestRectangleArea(int[] height) { + if (height == null || height.length == 0) { + return 0; + } + + Stack s = new Stack(); + + int max = 0; + + int len = height.length; + int i = 0; + + while (i <= len) { + // BUG 1: should use height[s.peek()] instead of s.peek(). + // BUG 2: should put i < length after the s.isEmpty. + // The last step: Length is also put into the stack and will break at last. + if (s.isEmpty() || (i < len && height[i] >= height[s.peek()])) { + s.push(i); + i++; + // Keep a Ascending sequence in the stack. + } else { + // Stack is not empty, and the current node is smaller than the one in the stack. + // When we come to the end of the array, we will also should count all the solutions. + // BUG 3: should use height[s.pop] instead of s.pop + // iĩβʱҲ¼һ. + int h = height[s.pop()]; + int width = s.isEmpty() ? i: i - s.peek() - 1; + max = Math.max(max, h * width); + } + } + + return max; + } +} \ No newline at end of file From 909c2ffdbbea2a1393afadeb06a6c2b720c2db20 Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Mon, 29 Dec 2014 00:06:15 -0800 Subject: [PATCH 290/319] comment --- array/LargestRectangleArea.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/array/LargestRectangleArea.java b/array/LargestRectangleArea.java index 2fcb80c..86a94e2 100644 --- a/array/LargestRectangleArea.java +++ b/array/LargestRectangleArea.java @@ -32,7 +32,7 @@ public static int largestRectangleArea(int[] height) { // Stack is not empty, and the current node is smaller than the one in the stack. // When we come to the end of the array, we will also should count all the solutions. // BUG 3: should use height[s.pop] instead of s.pop - // iĩβʱҲ¼һ. + // When the i come to the end, the rectangle will be counted again. int h = height[s.pop()]; int width = s.isEmpty() ? i: i - s.peek() - 1; max = Math.max(max, h * width); From 48c4f0e2d2e37955e2608708870b47a5520d1c7d Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Tue, 30 Dec 2014 03:34:13 -0800 Subject: [PATCH 291/319] partition --- dfs/Partition_2014_1229.java | 149 +++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 dfs/Partition_2014_1229.java diff --git a/dfs/Partition_2014_1229.java b/dfs/Partition_2014_1229.java new file mode 100644 index 0000000..46cbe91 --- /dev/null +++ b/dfs/Partition_2014_1229.java @@ -0,0 +1,149 @@ +package Algorithms.dfs; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class Partition_2014_1229 { + // Solution 1: The DFS version. + public List> partition1(String s) { + List> ret = new ArrayList>(); + if (s == null) { + return ret; + } + + dfs(s, 0, new ArrayList(), ret); + return ret; + } + + public static void dfs(String s, int index, List path, List> ret) { + int len = s.length(); + if (index == len) { + ret.add(new ArrayList(path)); + return; + } + + for (int i = index; i < len; i++) { + String sub = s.substring(index, i + 1); + if (!isPalindrome(sub)) { + continue; + } + + path.add(sub); + dfs(s, i + 1, path, ret); + path.remove(path.size() - 1); + } + } + + public static boolean isPalindrome(String s) { + int len = s.length(); + int left = 0; + int right = len - 1; + + while (left < right) { + if (s.charAt(left) != s.charAt(right)) { + return false; + } + left++; + right--; + } + + return true; + } + + // Solution 2: The DFS version with memory. + public List> partition2(String s) { + List> ret = new ArrayList>(); + if (s == null) { + return ret; + } + + // bug: new map error. + dfs2(s, 0, new ArrayList(), ret, new HashMap()); + return ret; + } + + public static void dfs2(String s, int index, List path, List> ret, HashMap map) { + int len = s.length(); + if (index == len) { + ret.add(new ArrayList(path)); + return; + } + + for (int i = index; i < len; i++) { + String sub = s.substring(index, i + 1); + if (!isPalindromeHash(sub, map)) { + continue; + } + + path.add(sub); + dfs2(s, i + 1, path, ret, map); + path.remove(path.size() - 1); + } + } + + // BUG 3: use boolean instead of Boolean. + public static boolean isPalindromeHash(String s, HashMap map) { + int len = s.length(); + int left = 0; + int right = len - 1; + + if (map.get(s) != null) { + return map.get(s); + } + + map.put(s, true); + while (left < right) { + if (s.charAt(left) != s.charAt(right)) { + map.put(s, false); + return false; + } + left++; + right--; + } + + return true; + } + + // Solution 3: Use DP to determine the palindrome first. + public List> partition(String s) { + List> ret = new ArrayList>(); + if (s == null) { + return ret; + } + + int len = s.length(); + + // D[i][j]: if this a palindrom for s.substring(i, j + 1). + boolean[][] D = new boolean[len][len]; + + for (int j = 0; j < len; j++) { + for (int i = 0; i <= j; i++) { + D[i][j] = s.charAt(i) == s.charAt(j) && (j - i <= 2 || D[i + 1][j - 1]); + } + } + + // bug: new map error. + dfs3(s, 0, new ArrayList(), ret, D); + return ret; + } + + public static void dfs3(String s, int index, List path, List> ret, boolean[][] D) { + int len = s.length(); + if (index == len) { + ret.add(new ArrayList(path)); + return; + } + + for (int i = index; i < len; i++) { + String sub = s.substring(index, i + 1); + if (!D[index][i]) { + continue; + } + + path.add(sub); + dfs3(s, i + 1, path, ret, D); + path.remove(path.size() - 1); + } + } +} \ No newline at end of file From 725cfca16c9fb95a2574d723e0f66901958d3cff Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Tue, 30 Dec 2014 04:12:39 -0800 Subject: [PATCH 292/319] ispalindrome --- string/IsPalindrome_2014_1229.java | 80 ++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 string/IsPalindrome_2014_1229.java diff --git a/string/IsPalindrome_2014_1229.java b/string/IsPalindrome_2014_1229.java new file mode 100644 index 0000000..6222930 --- /dev/null +++ b/string/IsPalindrome_2014_1229.java @@ -0,0 +1,80 @@ +package Algorithms.string; + +public class IsPalindrome_2014_1229 { + /* + SOLUTION 1: Iterator. + */ + public boolean isPalindrome1(String s) { + if (s == null) { + return false; + } + + int len = s.length(); + + int left = 0; + int right = len - 1; + + String sNew = s.toLowerCase(); + + while (left < right) { + // bug 1: forget a ) + while (left < right && !isNumChar(sNew.charAt(left))) { + left++; + } + + while (left < right && !isNumChar(sNew.charAt(right))) { + right--; + } + + if (sNew.charAt(left) != sNew.charAt(right)) { + return false; + } + + left++; + right--; + } + + return true; + } + + public boolean isNumChar(char c) { + if (c <= '9' && c >= '0' || c <= 'z' && c >= 'a' || c <= 'Z' && c >= 'A') { + return true; + } + + return false; + } + + /* + SOLUTION 2: Iterator2. + */ + public boolean isPalindrome(String s) { + if (s == null) { + return false; + } + + int len = s.length(); + + int left = 0; + int right = len - 1; + + String sNew = s.toLowerCase(); + + while (left < right) { + // bug 1: forget a ) + if (!Character.isLetterOrDigit(sNew.charAt(left))) { + left++; + // bug 2: Line 67: error: cannot find symbol: method isLetterOrDigital(char) + } else if (!Character.isLetterOrDigit(sNew.charAt(right))) { + right--; + } else if (sNew.charAt(left) != sNew.charAt(right)) { + return false; + } else { + left++; + right--; + } + } + + return true; + } +} \ No newline at end of file From 71cce9fc9f068b36fc5dc67c4fb746ea676282ca Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Tue, 30 Dec 2014 05:12:54 -0800 Subject: [PATCH 293/319] tree --- tree/Connect_2014_1229.java | 110 ++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 tree/Connect_2014_1229.java diff --git a/tree/Connect_2014_1229.java b/tree/Connect_2014_1229.java new file mode 100644 index 0000000..ef1e75e --- /dev/null +++ b/tree/Connect_2014_1229.java @@ -0,0 +1,110 @@ +package Algorithms.tree; + +import java.util.LinkedList; +import java.util.Queue; + +/** + * Definition for binary tree with next pointer. + * public class TreeLinkNode { + * int val; + * TreeLinkNode left, right, next; + * TreeLinkNode(int x) { val = x; } + * } + */ +public class Connect_2014_1229 { + /* + 1. Iterator. + */ + public void connect1(TreeLinkNode root) { + if (root == null) { + return; + } + + Queue q = new LinkedList(); + q.offer(root); + + while (!q.isEmpty()) { + int size = q.size(); + + for (int i = 0; i < size; i++) { + TreeLinkNode cur = q.poll(); + + // ERROR 2: forget to determine if root don't have left and right. + if (cur.left == null) { + return; + } + + cur.left.next = cur.right; + cur.right.next = cur.next == null ? null : cur.next.left; + // bug 1: should put the offer inside the for loop + q.offer(cur.left); + q.offer(cur.right); + } + } + } + + /* + 2. Iterator. More simple version. + */ + public void connect2(TreeLinkNode root) { + if (root == null) { + return; + } + + Queue q = new LinkedList(); + q.offer(root); + + while (!q.isEmpty()) { + int size = q.size(); + + for (int i = 0; i < size; i++) { + TreeLinkNode cur = q.poll(); + + // bug 1: should judge the size! + cur.next = (i == size - 1) ? null: q.peek(); + + if (cur.left != null) { + q.offer(cur.left); + q.offer(cur.right); + } + } + } + } + + /* + 3. A recursion version. + */ + public void connect3(TreeLinkNode root) { + if (root == null || root.left == null) { + return; + } + + root.left.next = root.right; + root.right.next = root.next == null ? null: root.next.left; + + connect(root.left); + connect(root.right); + } + + /* + 4. Another constant iterator version. + */ + public void connect(TreeLinkNode root) { + if (root == null) { + return; + } + + TreeLinkNode leftEnd = root; + while (leftEnd != null && leftEnd.left != null) { + TreeLinkNode cur = leftEnd; + while (cur != null) { + cur.left.next = cur.right; + cur.right.next = cur.next == null ? null: cur.next.left; + + cur = cur.next; + } + + leftEnd = leftEnd.left; + } + } +} \ No newline at end of file From 820ee8f75438d86215aa2e5051e177eb23703691 Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Tue, 30 Dec 2014 06:37:52 -0800 Subject: [PATCH 294/319] tree --- tree/Connect2_2014_1229.java | 92 ++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 tree/Connect2_2014_1229.java diff --git a/tree/Connect2_2014_1229.java b/tree/Connect2_2014_1229.java new file mode 100644 index 0000000..24207c1 --- /dev/null +++ b/tree/Connect2_2014_1229.java @@ -0,0 +1,92 @@ +package Algorithms.tree; + +/** + * Definition for binary tree with next pointer. + * public class TreeLinkNode { + * int val; + * TreeLinkNode left, right, next; + * TreeLinkNode(int x) { val = x; } + * } + */ +public class Connect2_2014_1229 { + // SOLUTION 1: Iteration + public void connect1(TreeLinkNode root) { + if (root == null) { + return; + } + + TreeLinkNode leftEnd = root; + + // Bug 1: don't need " && leftEnd.left != null" + while (leftEnd != null) { + TreeLinkNode cur = leftEnd; + + TreeLinkNode dummy = new TreeLinkNode(0); + TreeLinkNode pre = dummy; + while (cur != null) { + if (cur.left != null) { + pre.next = cur.left; + pre = cur.left; + } + + if (cur.right != null) { + pre.next = cur.right; + pre = cur.right; + } + + cur = cur.next; + } + leftEnd = dummy.next; + } + } + + // SOLUTION 2: REC + public void connect(TreeLinkNode root) { + if (root == null) { + return; + } + + TreeLinkNode dummy = new TreeLinkNode(0); + TreeLinkNode pre = dummy; + + if (root.left != null) { + pre.next = root.left; + pre = root.left; + } + + if (root.right != null) { + pre.right = root.right; + pre = root.right; + } + + if (root.left == null && root.right == null) { + return; + } + + // Try to find the next node; + TreeLinkNode cur = root.next; + TreeLinkNode next = null; + while (cur != null) { + if (cur.left != null) { + next = cur.left; + break; + } else if (cur.right != null) { + next = cur.right; + break; + } else { + cur = cur.next; + } + } + + pre.next = next; + + if (root.right != null && (root.right.left != null || root.right.right != null)) { + connect(root.right); + } + + if (root.left != null && (root.left.left != null || root.left.right != null)) { + connect(root.left); + } + + } +} \ No newline at end of file From 5bf7ef616b9047bffb06b5a372e6271be51c1ece Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Tue, 30 Dec 2014 07:33:33 -0800 Subject: [PATCH 295/319] generate --- list/Generate.java | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 list/Generate.java diff --git a/list/Generate.java b/list/Generate.java new file mode 100644 index 0000000..3dbce0d --- /dev/null +++ b/list/Generate.java @@ -0,0 +1,27 @@ +package Algorithms.list; + +import java.util.ArrayList; +import java.util.List; + +public class Generate { + public List> generate(int numRows) { + List> ret = new ArrayList>(); + + for (int i = 0; i < numRows; i++) { + List list = new ArrayList(); + for (int j = 0; j <= i; j++) { + if (j == 0 || i == j) { + list.add(1); + } else { + int sum = ret.get(i - 1).get(j - 1) + ret.get(i - 1).get(j); + list.add(sum); + } + } + + // BUG 1: forget this statement. + ret.add(list); + } + + return ret; + } +} \ No newline at end of file From 611bb7b24faaed16c18686de3a3b17aefc6595a1 Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Wed, 31 Dec 2014 02:16:34 -0800 Subject: [PATCH 296/319] genera --- dp/Generate.java | 31 ------------------------------- dp/GetRow.java | 27 +++++++++++++++++++++++---- 2 files changed, 23 insertions(+), 35 deletions(-) delete mode 100644 dp/Generate.java diff --git a/dp/Generate.java b/dp/Generate.java deleted file mode 100644 index 03483a4..0000000 --- a/dp/Generate.java +++ /dev/null @@ -1,31 +0,0 @@ -package Algorithms.dp; - -import java.util.ArrayList; -import java.util.List; - -public class Generate { - public List> generate(int numRows) { - List> ret = new ArrayList>(); - - if (numRows <= 0) { - return ret; - } - - for (int i = 0; i < numRows; i++) { - ArrayList list = new ArrayList(); - for (int j = 0; j < i + 1; j++) { - if (j == 0 || j == i) { - // 两边的数字就是1. - list.add(1); - } else { - // 中间的数字等于上一行的j + j -1的值 - int num = ret.get(i - 1).get(j) + ret.get(i - 1).get(j - 1); - list.add(num); - } - } - ret.add(list); - } - - return ret; - } -} \ No newline at end of file diff --git a/dp/GetRow.java b/dp/GetRow.java index 0e81ede..aa2828c 100644 --- a/dp/GetRow.java +++ b/dp/GetRow.java @@ -4,7 +4,7 @@ import java.util.List; public class GetRow { - public List getRow(int rowIndex) { + public List getRow1(int rowIndex) { List pre = new ArrayList(); List cur = new ArrayList(); @@ -12,10 +12,10 @@ public List getRow(int rowIndex) { return cur; } - // 注意这里的rowIndex跟上一题的意义不一样!这个是索引,orz... - // 所以我们要用<= + // 娉ㄦ剰杩欓噷鐨剅owIndex璺熶笂涓�鐨勬剰涔変笉涓�牱锛佽繖涓槸绱㈠紩锛宱rz... + // 鎵�互鎴戜滑瑕佺敤<= for (int i = 0; i <= rowIndex; i++) { - // 第i行有i + 1个元素 + // 绗琲琛屾湁i + 1涓厓绱� cur = new ArrayList(); for (int j = 0; j < i + 1; j++) { if (j == 0 || j == i) { @@ -29,4 +29,23 @@ public List getRow(int rowIndex) { return cur; } + + // SOLUTION 2: DO IT just inplace + public List getRow(int rowIndex) { + List ret = new ArrayList(); + + for (int i = 0; i <= rowIndex; i++) { + for (int j = i; j >= 0; j--) { + if (j == i) { + ret.add(1); + } else if (j != 0) { + // ERROR: use add instead of set + //ret.add(ret.get(j) + ret.get(j - 1)); + ret.set(j, ret.get(j) + ret.get(j - 1)); + } + } + } + + return ret; + } } \ No newline at end of file From b94329c21bbbc10beb0618b0d8b77bea08b7fc81 Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Wed, 31 Dec 2014 02:16:48 -0800 Subject: [PATCH 297/319] dist --- dp/NumDistinct.java | 220 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 dp/NumDistinct.java diff --git a/dp/NumDistinct.java b/dp/NumDistinct.java new file mode 100644 index 0000000..523ea08 --- /dev/null +++ b/dp/NumDistinct.java @@ -0,0 +1,220 @@ +package Algorithms.dp; + +public class NumDistinct { + public int numDistinct1(String S, String T) { + if (S == null || T == null) { + return 0; + } + + int lenS = S.length(); + int lenT = T.length(); + + if (lenS < lenT) { + return 0; + } + + int[][] D = new int[lenS + 1][lenT + 1]; + + // BUG 1: forget to use <= instead of <.... + for (int i = 0; i <= lenS; i++) { + for (int j = 0; j <= lenT; j++) { + // both are empty. + if (i == 0 && j == 0) { + D[i][j] = 1; + } else if (i == 0) { + // S is empty, can't form a non-empty string. + D[i][j] = 0; + } else if (j == 0) { + // T is empty. S is not empty. + D[i][j] = 1; + } else { + D[i][j] = 0; + // keep the last character of S. + if (S.charAt(i - 1) == T.charAt(j - 1)) { + D[i][j] += D[i - 1][j - 1]; + } + + // discard the last character of S. + D[i][j] += D[i - 1][j]; + } + } + } + + return D[lenS][lenT]; + } + + // SOLUTION 2: recursion version. TLE + public int numDistinct2(String S, String T) { + if (S == null || T == null) { + return 0; + } + + return rec(S, T, 0, 0); + } + + public int rec(String S, String T, int indexS, int indexT) { + int lenS = S.length(); + int lenT = T.length(); + + // base case: + if (indexT >= lenT) { + // T is empty. + return 1; + } + + if (indexS >= lenS) { + // S is empty but T is not empty. + return 0; + } + + int sum = 0; + // use the first character in S. + if (S.charAt(indexS) == T.charAt(indexT)) { + sum += rec(S, T, indexS + 1, indexT + 1); + } + + // Don't use the first character in S. + sum += rec(S, T, indexS + 1, indexT); + + return sum; + } + + // SOLUTION 3: recursion version with memory. + public int numDistinct3(String S, String T) { + if (S == null || T == null) { + return 0; + } + + int lenS = S.length(); + int lenT = T.length(); + + int[][] memory = new int[lenS + 1][lenT + 1]; + for (int i = 0; i <= lenS; i++) { + for (int j = 0; j <= lenT; j++) { + memory[i][j] = -1; + } + } + + return rec(S, T, 0, 0, memory); + } + + public int rec(String S, String T, int indexS, int indexT, int[][] memory) { + int lenS = S.length(); + int lenT = T.length(); + + // base case: + if (indexT >= lenT) { + // T is empty. + return 1; + } + + if (indexS >= lenS) { + // S is empty but T is not empty. + return 0; + } + + if (memory[indexS][indexT] != -1) { + return memory[indexS][indexT]; + } + + int sum = 0; + // use the first character in S. + if (S.charAt(indexS) == T.charAt(indexT)) { + sum += rec(S, T, indexS + 1, indexT + 1, memory); + } + + // Don't use the first character in S. + sum += rec(S, T, indexS + 1, indexT, memory); + + // record the solution. + memory[indexS][indexT] = sum; + return sum; + } + + // SOLUTION 4: improved recursion version + public int numDistinct4(String S, String T) { + if (S == null || T == null) { + return 0; + } + + int lenS = S.length(); + int lenT = T.length(); + + int[][] memory = new int[lenS + 1][lenT + 1]; + for (int i = 0; i <= lenS; i++) { + for (int j = 0; j <= lenT; j++) { + memory[i][j] = -1; + } + } + + return rec4(S, T, 0, 0, memory); + } + + public int rec4(String S, String T, int indexS, int indexT, int[][] memory) { + int lenS = S.length(); + int lenT = T.length(); + + // base case: + if (indexT >= lenT) { + // T is empty. + return 1; + } + + if (indexS >= lenS) { + // S is empty but T is not empty. + return 0; + } + + if (memory[indexS][indexT] != -1) { + return memory[indexS][indexT]; + } + + int sum = 0; + for (int i = indexS; i < lenS; i++) { + // choose which character in S to choose as the first character of T. + if (S.charAt(i) == T.charAt(indexT)) { + sum += rec4(S, T, i + 1, indexT + 1, memory); + } + } + + // record the solution. + memory[indexS][indexT] = sum; + return sum; + } + + // SOLUTION 5: improved recursion version without memory. + public int numDistinct(String S, String T) { + if (S == null || T == null) { + return 0; + } + + return rec5(S, T, 0, 0); + } + + public int rec5(String S, String T, int indexS, int indexT) { + int lenS = S.length(); + int lenT = T.length(); + + // base case: + if (indexT >= lenT) { + // T is empty. + return 1; + } + + if (indexS >= lenS) { + // S is empty but T is not empty. + return 0; + } + + int sum = 0; + for (int i = indexS; i < lenS; i++) { + // choose which character in S to choose as the first character of T. + if (S.charAt(i) == T.charAt(indexT)) { + sum += rec5(S, T, i + 1, indexT + 1); + } + } + + return sum; + } + +} \ No newline at end of file From ebb4be3995701ef17929d10f8657dc538f89c3e2 Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Wed, 31 Dec 2014 07:49:24 -0800 Subject: [PATCH 298/319] search --- array/SetZeroes.java | 61 ++++++++++++++++++++++++- divide2/SearchMatrix.java | 36 +++++++++++++++ lintcode/array/FindFirstBadVersion.java | 61 +++++++++++++++++++++++++ lintcode/array/VersionControl.java | 10 ++++ 4 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 divide2/SearchMatrix.java create mode 100644 lintcode/array/FindFirstBadVersion.java create mode 100644 lintcode/array/VersionControl.java diff --git a/array/SetZeroes.java b/array/SetZeroes.java index 61fb9f8..b303909 100644 --- a/array/SetZeroes.java +++ b/array/SetZeroes.java @@ -41,7 +41,6 @@ public static void setZeroes(int[][] matrix) { // cells whether or not set to 0. for (int i = 1; i < rows; i++) { for (int j = 1; j < cols; j++) { - // 注意了,这个矩阵是0和非0,并不是0和1. if (matrix[i][j] == 0) { // set the flag in the first line and the first column matrix[i][0] = 0; @@ -77,4 +76,64 @@ public static void setZeroes(int[][] matrix) { return; } + + // solution 2: combine the first 3 loop. + public void setZeroes2(int[][] matrix) { + if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { + return; + } + + boolean row1 = false; + boolean col1 = false; + + int rows = matrix.length; + int cols = matrix[0].length; + + // set flags. + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (matrix[i][j] != 0) { + continue; + } + + // set the flag of a column and a row. + matrix[0][j] = 0; + matrix[i][0] = 0; + + // get flag of first row. + if (i == 0) { + row1 = true; + } + + // get flag of first column. + if (j == 0) { + col1 = true; + } + } + } + + // set the matrix. + for (int i = 1; i < rows; i++) { + for (int j = 1; j < cols; j++) { + if (matrix[0][j] == 0 || matrix[i][0] == 0) { + matrix[i][j] = 0; + } + } + } + + // set first column + if (col1) { + for (int i = 0; i < rows; i++) { + // bug 1: can't use matrix[i][j] + matrix[i][0] = 0; + } + } + + // set first row. + if (row1) { + for (int i = 0; i < cols; i++) { + matrix[0][i] = 0; + } + } + } } diff --git a/divide2/SearchMatrix.java b/divide2/SearchMatrix.java new file mode 100644 index 0000000..b58055d --- /dev/null +++ b/divide2/SearchMatrix.java @@ -0,0 +1,36 @@ +package Algorithms.divide2; + +public class SearchMatrix { + public boolean searchMatrix(int[][] matrix, int target) { + if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { + return false; + } + + int rows = matrix.length; + int cols = matrix[0].length; + + int num = rows * cols; + + int left = 0; + int right = num - 1; + + while (left <= right) { + int mid = left + (right - left) / 2; + + int row = mid / cols; + int col = mid % cols; + + int n = matrix[row][col]; + + if (n == target) { + return true; + } else if (n < target) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + return false; + } +} diff --git a/lintcode/array/FindFirstBadVersion.java b/lintcode/array/FindFirstBadVersion.java new file mode 100644 index 0000000..460db23 --- /dev/null +++ b/lintcode/array/FindFirstBadVersion.java @@ -0,0 +1,61 @@ +package Algorithms.lintcode.array; + +/** + * public class VersionControl { + * public static boolean isBadVersion(int k); + * } + * you can use VersionControl.isBadVersion(k) to judge wether + * the kth code version is bad or not. +*/ +class Solution { + /** + * @param n: An integers. + * @return: An integer which is the first bad version. + */ + public int findFirstBadVersion(int n) { + // write your code here + if (n == 1) { + return 1; + } + + int left = 1; + int right = n; + + while (left + 1 < right) { + int mid = left + (right - left) / 2; + if (VersionControl.isBadVersion(mid)) { + right = mid; + } else { + left = mid; + } + } + + if (VersionControl.isBadVersion(left)) { + return left; + } + + return right; + } + + // solution 2. + public int findFirstBadVersion2(int n) { + // write your code here + if (n == 1) { + return 1; + } + + int left = 1; + int right = n; + + while (left < right) { + int mid = left + (right - left) / 2; + if (VersionControl.isBadVersion(mid)) { + right = mid; + } else { + left = mid + 1; + } + } + + return right; + } +} \ No newline at end of file diff --git a/lintcode/array/VersionControl.java b/lintcode/array/VersionControl.java new file mode 100644 index 0000000..97d4ce0 --- /dev/null +++ b/lintcode/array/VersionControl.java @@ -0,0 +1,10 @@ +package Algorithms.lintcode.array; + +public class VersionControl { + + public static boolean isBadVersion(int mid) { + // TODO Auto-generated method stub + return false; + } + +} From 7b869d0b0da32f128dd436b2fee997b8b59ef91b Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Thu, 1 Jan 2015 03:52:36 -0800 Subject: [PATCH 299/319] ip --- divide2/SearchInsert.java | 60 ++++++++++++++++++++++++++++++++++ string/RestoreIpAddresses.java | 58 ++++++++++++++++++++++++++++++-- 2 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 divide2/SearchInsert.java diff --git a/divide2/SearchInsert.java b/divide2/SearchInsert.java new file mode 100644 index 0000000..cd9a58f --- /dev/null +++ b/divide2/SearchInsert.java @@ -0,0 +1,60 @@ +package Algorithms.divide2; + +public class SearchInsert { + public int searchInsert1(int[] A, int target) { + if (A == null || A.length == 0) { + return 0; + } + + int left = 0; + int right = A.length - 1; + + while (left < right - 1) { + int mid = left + (right - left) / 2; + int num = A[mid]; + + if (num == target) { + return mid; + } else if (num < target) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + // bug 1: should use <= + if (target <= A[left]) { + return left; + // bug 2: should use <= . consider that may the result exit in left or right. + } else if (target <= A[right]) { + return right; + } + + return right + 1; + } + + // sol 2: + public int searchInsert(int[] A, int target) { + if (A == null || A.length == 0) { + return 0; + } + + int left = 0; + int right = A.length - 1; + + while (left <= right) { + int mid = left + (right - left) / 2; + int num = A[mid]; + + if (num == target) { + return mid; + } else if (num < target) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + return left; + } +} \ No newline at end of file diff --git a/string/RestoreIpAddresses.java b/string/RestoreIpAddresses.java index a7a7a27..8c144f9 100644 --- a/string/RestoreIpAddresses.java +++ b/string/RestoreIpAddresses.java @@ -35,13 +35,11 @@ public void dfs(String s, int index, ArrayList path, ArrayList r int len = s.length(); for (int i = index; i < index + 3 && i < len; i++) { - // 不可以有005这样子的IP地址。 if (s.charAt(index) == '0' && i > index) { break; } String pre = s.substring(index, i + 1); - // 过滤num > 255的情况。 int num = Integer.parseInt(pre); if (num > 255) { continue; @@ -52,4 +50,60 @@ public void dfs(String s, int index, ArrayList path, ArrayList r path.remove(path.size() - 1); } } + + // 2015.1.1 Redo: + public List restoreIpAddresses2(String s) { + List ret = new ArrayList(); + // Bug 1: not length, but length(). + if (s == null || s.length() < 4 || s.length() > 12) { + return ret; + } + + dfs(s, new ArrayList(), ret, 0); + return ret; + } + + public void dfs(String s, List path, List ret, int index) { + // THE BASE CASE: + int len = s.length(); + if (path.size() == 4) { + // Create a solution. + if (index == len) { + StringBuilder sb = new StringBuilder(); + for (String str: path) { + sb.append(str); + sb.append("."); + } + sb.deleteCharAt(sb.length() - 1); + + // bug 3: forget this statement. + ret.add(sb.toString()); + } + + return; + } + + // 2/ 25 / 255 + // bug 2: i should < len. + for (int i = index; i < index + 3 && i < len; i++) { + String sub = s.substring(index, i + 1); + if (s.charAt(index) == '0' && i != index) { + // only allow 0, not 02, 022 + break; + } + + if (!isValid(sub)) { + continue; + } + + path.add(sub); + dfs(s, path, ret, i + 1); + path.remove(path.size() - 1); + } + } + + public boolean isValid(String s) { + int num = Integer.parseInt(s); + return num >= 0 && num <= 255; + } } \ No newline at end of file From 81303acdc1ad3dda12b73207eb56fe5280946bca Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Thu, 1 Jan 2015 06:13:32 -0800 Subject: [PATCH 300/319] search --- array/SearchInRotatedSortedArray.java | 81 ++++++++++++++++++++++++ array/SearchInRotatedSortedArray2.java | 88 +++++++++++++++++++++++++- 2 files changed, 168 insertions(+), 1 deletion(-) diff --git a/array/SearchInRotatedSortedArray.java b/array/SearchInRotatedSortedArray.java index 530e50e..19c5ec4 100644 --- a/array/SearchInRotatedSortedArray.java +++ b/array/SearchInRotatedSortedArray.java @@ -37,4 +37,85 @@ public int search(int[] A, int target) { return -1; } + + // 2015.1.1 redo: + public int search1(int[] A, int target) { + if (A == null || A.length == 0) { + return -1; + } + + int l = 0; + int r = A.length - 1; + + while (l < r - 1) { + int mid = l + (r - l) / 2; + + if (A[mid] == target) { + return mid; + } + + // left side is sorted. + // BUG 1: if don't use >= , and use L < r in while loop, than there is some problem. + if (A[mid] > A[l]) { + if (target > A[mid] || target < A[l]) { + // move to right; + l = mid + 1; + } else { + r = mid - 1; + } + } else { + if (target < A[mid] || target > A[r]) { + // move to left; + r = mid - 1; + } else { + l = mid + 1; + } + } + } + + if (A[l] == target) { + return l; + } else if (A[r] == target) { + return r; + } + + return -1; + } + + public int search2(int[] A, int target) { + if (A == null || A.length == 0) { + return -1; + } + + int l = 0; + int r = A.length - 1; + + while (l <= r) { + int mid = l + (r - l) / 2; + + if (A[mid] == target) { + return mid; + } + + // left side is sorted. + // BUG 1: if don't use >= , and use L < r in while loop, than there is some problem. + if (A[mid] >= A[l]) { + if (target > A[mid] || target < A[l]) { + // move to right; + l = mid + 1; + } else { + r = mid - 1; + } + } else { + if (target < A[mid] || target > A[r]) { + // move to left; + r = mid - 1; + } else { + l = mid + 1; + } + } + } + + return -1; + } } diff --git a/array/SearchInRotatedSortedArray2.java b/array/SearchInRotatedSortedArray2.java index 4cb650e..040d341 100644 --- a/array/SearchInRotatedSortedArray2.java +++ b/array/SearchInRotatedSortedArray2.java @@ -55,6 +55,92 @@ public boolean search(int[] A, int target) { return false; } - + + /* + * 2015.1.1 Redo: + * */ + public boolean search1(int[] A, int target) { + if (A == null || A.length == 0) { + return false; + } + + int l = 0; + int r = A.length - 1; + + while (l < r - 1) { + int mid = l + (r - l) / 2; + + if (A[mid] == target) { + return true; + } + + // left sort + if (A[mid] > A[l]) { + // out of range. + if (target > A[mid] || target < A[l]) { + l = mid + 1; + } else { + r = mid - 1; + } + // right sort. + } else if (A[mid] < A[l]) { + // out of range. + if (target < A[mid] || target > A[r]) { + r = mid - 1; + } else { + l = mid + 1; + } + } else { + // move one node. + l++; + } + } + + if (A[l] == target || A[r] == target) { + return true; + } + + return false; + } + // Version 2: + public boolean search2(int[] A, int target) { + if (A == null || A.length == 0) { + return false; + } + + int l = 0; + int r = A.length - 1; + + while (l <= r) { + int mid = l + (r - l) / 2; + + if (A[mid] == target) { + return true; + } + + // left sort + if (A[mid] > A[l]) { + // out of range. + if (target > A[mid] || target < A[l]) { + l = mid + 1; + } else { + r = mid - 1; + } + // right sort. + } else if (A[mid] < A[l]) { + // out of range. + if (target < A[mid] || target > A[r]) { + r = mid - 1; + } else { + l = mid + 1; + } + } else { + // move one node. + l++; + } + } + + return false; + } } From 7a9a84becb95f8e8ed4fb8e89b6224a2506a6b2e Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Fri, 2 Jan 2015 05:51:26 -0800 Subject: [PATCH 301/319] searc --- divide2/SearchRange.java | 55 ++++++++++++++++++++++++++++++++++++++++ sort/BucketSorter.java | 51 +++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 divide2/SearchRange.java create mode 100644 sort/BucketSorter.java diff --git a/divide2/SearchRange.java b/divide2/SearchRange.java new file mode 100644 index 0000000..5ac4afa --- /dev/null +++ b/divide2/SearchRange.java @@ -0,0 +1,55 @@ +package Algorithms.divide2; + +public class SearchRange { + public int[] searchRange(int[] A, int target) { + int[] ret = {-1, -1}; + if (A == null || A.length == 0) { + return ret; + } + + int l = 0; + int r = A.length - 1; + + // Find the left bound. + while (l < r - 1) { + int mid = l + (r - l) / 2; + if (A[mid] == target) { + r = mid; + } else if (A[mid] > target) { + r = mid; + } else { + l = mid; + } + } + + if (A[l] == target) { + ret[0] = l; + } else if (A[r] == target) { + ret[0] = r; + } else { + return ret; + } + + l = 0; + r = A.length - 1; + // Find the right bound. + while (l < r - 1) { + int mid = l + (r - l) / 2; + if (A[mid] == target) { + l = mid; + } else if (A[mid] > target) { + r = mid; + } else { + l = mid; + } + } + + if (A[r] == target) { + ret[1] = r; + } else { + ret[1] = l; + } + + return ret; + } +} \ No newline at end of file diff --git a/sort/BucketSorter.java b/sort/BucketSorter.java new file mode 100644 index 0000000..fb5b189 --- /dev/null +++ b/sort/BucketSorter.java @@ -0,0 +1,51 @@ +package Algorithms.sort; + +import java.util.Arrays; + +/** + * @author yovn + * + */ +public class BucketSorter { + public void sort(int[] keys,int from,int len,int max) + { + int[] count = new int[max]; + int[] tmp = new int[len]; + + // count the keys. + for (int i = 0; i < len; i++) { + count[keys[from + i]]++; + } + + // calculate the position. + // BUG 1: i go from 1 not 0. + for (int i = 1; i < max; i++) { + count[i] = count[i] + count[i - 1]; + } + + // back the array. + System.arraycopy(keys, from, tmp, 0, len); + + // Place the objects into the right position. + for (int i = len - 1; i >= 0; i--) { + keys[--count[tmp[i]]] = tmp[i]; + } + } + /** + * @param args + */ + public static void main(String[] args) { + + int[] a={1,4,8,3,2,9,5,0,7,6,9,10,9,13,14,15,11,12,17,16}; + BucketSorter sorter=new BucketSorter(); + sorter.sort(a,0,a.length,20);//actually is 18, but 20 will also work + + + for(int i=0;i Date: Fri, 2 Jan 2015 20:46:33 -0800 Subject: [PATCH 302/319] example --- algorithm/interviews/uber/Example.java | 5 +++ divide2/Sqrt.java | 28 ++++++++++++ sort/BucketSorter.java | 1 - tree/BuildTree.java | 60 ++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 algorithm/interviews/uber/Example.java create mode 100644 divide2/Sqrt.java create mode 100644 tree/BuildTree.java diff --git a/algorithm/interviews/uber/Example.java b/algorithm/interviews/uber/Example.java new file mode 100644 index 0000000..f661837 --- /dev/null +++ b/algorithm/interviews/uber/Example.java @@ -0,0 +1,5 @@ +package Algorithms.algorithm.interviews.uber; + +public class Example { + +} diff --git a/divide2/Sqrt.java b/divide2/Sqrt.java new file mode 100644 index 0000000..7e8a9df --- /dev/null +++ b/divide2/Sqrt.java @@ -0,0 +1,28 @@ +package Algorithms.divide2; + +public class Sqrt { + public int sqrt(int x) { + if (x == 1 || x == 0) { + return x; + } + + int left = 1; + int right = x; + + while (left < right - 1) { + int mid = left + (right - left) / 2; + int quo = x / mid; + + if (quo == mid) { + return quo; + // mid is too big + } else if (quo < mid) { + right = mid; + } else { + left = mid; + } + } + + return left; + } +} \ No newline at end of file diff --git a/sort/BucketSorter.java b/sort/BucketSorter.java index fb5b189..f473fd1 100644 --- a/sort/BucketSorter.java +++ b/sort/BucketSorter.java @@ -1,6 +1,5 @@ package Algorithms.sort; -import java.util.Arrays; /** * @author yovn diff --git a/tree/BuildTree.java b/tree/BuildTree.java new file mode 100644 index 0000000..51fe4a1 --- /dev/null +++ b/tree/BuildTree.java @@ -0,0 +1,60 @@ +package Algorithms.tree; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class BuildTree { + public static void main(String[] strs) { + int[] pre = {1, 2}; + int[] in = {2, 1}; + + buildTree(pre, in); + } + + public static TreeNode buildTree(int[] preorder, int[] inorder) { + // bug 3: consider when length is 0. + if (preorder == null || inorder == null || preorder.length == 0 || preorder.length != inorder.length) { + return null; + } + + // bug 4: end index is length - 1. + return buildTree(preorder, inorder, 0, preorder.length - 1, 0, preorder.length - 1); + } + + public static TreeNode buildTree(int[] preorder, int[] inorder, int preStart, int preEnd, int inStart, int inEnd) { + // base case; + if (preStart > preEnd) { + return null; + } + + int rootVal = preorder[preStart]; + TreeNode root = new TreeNode(rootVal); + + int pos = findTarget(inorder, rootVal, inStart, inEnd); + + // bug 5: left number is pos - instart can't add 1 + int leftNum = pos - inStart; + + root.left = buildTree(preorder, inorder, preStart + 1, preStart + leftNum, inStart, pos - 1); + root.right = buildTree(preorder, inorder, preStart + leftNum + 1, preEnd, pos + 1, inEnd); + + return root; + } + + // bug 1: return type required. + public static int findTarget(int[] A, int target, int start, int end) { + for (int i = start; i <= end; i++) { + if (target == A[i]) { + return i; + } + } + + return -1; + } +} \ No newline at end of file From 0f592499e33739e3af01c1bfbcf82547a854e385 Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Fri, 2 Jan 2015 22:27:26 -0800 Subject: [PATCH 303/319] llint --- lintcode/dp/LongestCommonSubstring.java | 41 +++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 lintcode/dp/LongestCommonSubstring.java diff --git a/lintcode/dp/LongestCommonSubstring.java b/lintcode/dp/LongestCommonSubstring.java new file mode 100644 index 0000000..bcb662a --- /dev/null +++ b/lintcode/dp/LongestCommonSubstring.java @@ -0,0 +1,41 @@ +package Algorithms.lintcode.dp; + +public class LongestCommonSubstring { + /** + * @param A, B: Two string. + * @return: the length of the longest common substring. + */ + public int longestCommonSubstring(String A, String B) { + // write your code here + if (A == null || B == null) { + return 0; + } + + int lenA = A.length(); + int lenB = B.length(); + + // bug 1: use error init. + int[][] D = new int[lenA + 1][lenB + 1]; + + int max = 0; + + // BUG 2: should use <= instead of < + for (int i = 0; i <= lenA; i++) { + for (int j = 0; j <= lenB; j++) { + if (i == 0 || j == 0) { + D[i][j] = 0; + } else { + if (A.charAt(i - 1) == B.charAt(j - 1)) { + D[i][j] = D[i - 1][j - 1] + 1; + } else { + D[i][j] = 0; + } + } + + max = Math.max(max, D[i][j]); + } + } + + return max; + } +} From 2a54ee10108eff97da81d6d913788c4105231af7 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 3 Jan 2015 00:35:57 -0600 Subject: [PATCH 304/319] uber problems --- algorithm/interviews/uber/Example.java | 167 ++++++++++++++++++++++++- 1 file changed, 166 insertions(+), 1 deletion(-) diff --git a/algorithm/interviews/uber/Example.java b/algorithm/interviews/uber/Example.java index f661837..07781c3 100644 --- a/algorithm/interviews/uber/Example.java +++ b/algorithm/interviews/uber/Example.java @@ -1,5 +1,170 @@ package Algorithms.algorithm.interviews.uber; +import java.util.*; public class Example { - + /* sqrt(100) => 10,1 , sqrt(300) => 10,3 300 = 10^2 * 3 */ + // Running time: O(sqrt(n)) + public int[] sqrt(int num){ + int[] rst = {-1,-1}; + + if (num < 0){// edge case + return rst; + } + + int n = (int) Math.sqrt(num); + while (n >= 1){ + if (num % (n*n) == 0){ + rst[0] = n; + rst[1] = num/(n*n); + return rst; + } + n--; + } + return rst; + } + + /* given a number, find the next prime which is bigger than it */ + // Running time: O(nlogm) => m is an average recursion depth for each number, how to optimize it? + public int getNextPrime(int value){ + if (value <= 1){ + return 2; + } + int target = value+1; + while (!isPrime(target)){ + target++; + } + + return target; + } + public boolean isPrime(int target){ + int n = 2; + while (n*n <= target){// may overflow here! + if (target % n == 0){ + return false; + } + n++; + } + return true; + } + /* given many logs , output */ + // use two priorityqueue: O(2nlogn) ; just sort: O(2nlog2n) + public List countRecord(List records){ + if (records == null || records.size() == 0){ + return new ArrayList(); + } + List rst = new ArrayList(); + Collections.sort(records, new Comparator(){ + @Override + public int compare(record o1, record o2) { + // TODO Auto-generated method stub + return o1.log_time - o2.log_time; + } + }); + PriorityQueue endheap = new PriorityQueue(records.size(),new Comparator(){ + @Override + public int compare(Integer o1, Integer o2) { + // TODO Auto-generated method stub + return o1-o2; + } + }); + PriorityQueue startheap = new PriorityQueue(records.size(),new Comparator(){ + @Override + public int compare(Integer o1, Integer o2) { + // TODO Auto-generated method stub + return o1-o2; + } + }); + int curr,i; + for (i=0;i 0 || endheap.size() > 0){ + int curr1 = startheap.size() > 0 ? startheap.peek() : -1; + int curr2 = endheap.size() > 0 ? endheap.peek() : -1; + if (curr1 < 0 || curr1 > curr2){// only end time left + while (endheap.size() > 0 && endheap.peek() == curr2){ + curr--; + endheap.poll(); + } + rst.add(new result(curr2,curr)); + } + else if (curr2 < 0 || curr1 < curr2){// go with start time + while (startheap.size() > 0 && startheap.peek() == curr1){ + curr++; + startheap.poll(); + } + rst.add(new result(curr1,curr)); + } + else{// curr1 == curr2 + while (endheap.size() > 0 && endheap.peek() == curr2){ + curr--; + endheap.poll(); + } + while (startheap.size() > 0 && startheap.peek() == curr1){ + curr++; + startheap.poll(); + } + rst.add(new result(curr1,curr)); + } + } + + return rst; + } + // decode ways: 1-26 => 'A'-'Z' + public int numDecodings(String s){ + if (s == null || s.length() == 0){ + return 0; + } + int last = 0; + int curr = s.charAt(0) == '0' ? 0 : 1; + int next = last + curr; + int i,copy = 0; + + for (i = 0;i < s.length();i++){ + next = 0; + if (s.charAt(i) >= '1' && s.charAt(i) <= '9'){ + next = curr; + } + int value = copy*10 + s.charAt(i)-'0'; + + if (value >= 10 && value <= 26){ + next += last; + } + copy = value % 10; + + last = curr; + curr = next; + } + + return next; + } + // wordbreak => [lock,locker, erning] ; lockerning : true, lockern : false + public boolean wordBreak(String s, Set dict){ + if (dict == null || s == null || s.length() == 0 || dict.size() == 0){ + return false; + } + int m = s.length(); + int range = 0; + int i,j; + boolean[] dp = new boolean[m+1]; + dp[0] = true; + String curr; + + for (i=1;i<=s.length();i++){ + for (j=0;j Date: Fri, 2 Jan 2015 23:00:22 -0800 Subject: [PATCH 305/319] long --- lintcode/dp/LongestCommonSubsequence.java | 35 +++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 lintcode/dp/LongestCommonSubsequence.java diff --git a/lintcode/dp/LongestCommonSubsequence.java b/lintcode/dp/LongestCommonSubsequence.java new file mode 100644 index 0000000..aad494a --- /dev/null +++ b/lintcode/dp/LongestCommonSubsequence.java @@ -0,0 +1,35 @@ +package Algorithms.lintcode.dp; + +public class LongestCommonSubsequence { + /** + * @param A, B: Two strings. + * @return: The length of longest common subsequence of A and B. + */ + public int longestCommonSubsequence(String A, String B) { + // write your code here + if (A == null || B == null) { + return 0; + } + + int lenA = A.length(); + int lenB = B.length(); + int[][] D = new int[lenA + 1][lenB + 1]; + + for (int i = 0; i <= lenA; i++) { + for (int j = 0; j <= lenB; j++) { + if (i == 0 || j == 0) { + D[i][j] = 0; + } else { + if (A.charAt(i - 1) == B.charAt(j - 1)) { + D[i][j] = D[i - 1][j - 1] + 1; + } else { + D[i][j] = Math.max(D[i - 1][j], D[i][j - 1]); + } + } + } + } + + return D[lenA][lenB]; + } +} + From 930129ba163f9e21e12b0b290d49cef0fb3924a3 Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Sun, 4 Jan 2015 05:50:12 -0800 Subject: [PATCH 306/319] stack --- array/FirstMissingPositive.java | 35 +++++++++++++---- dp/MaxProfit.java | 16 ++++++++ dp/MaxProfit2.java | 22 +++++++++++ dp/MaxProfit3.java | 66 +++++++++++++++++++++++++++++++-- stack/IsValid.java | 50 +++++++++++++++++++++++++ string/Atoi.java | 41 ++++++++++++++++++++ tree/BuildTree2.java | 44 ++++++++++++++++++++++ 7 files changed, 263 insertions(+), 11 deletions(-) create mode 100644 stack/IsValid.java create mode 100644 tree/BuildTree2.java diff --git a/array/FirstMissingPositive.java b/array/FirstMissingPositive.java index 35bc8be..2c72c41 100644 --- a/array/FirstMissingPositive.java +++ b/array/FirstMissingPositive.java @@ -2,26 +2,20 @@ public class FirstMissingPositive { public static void main(String[] strs) { - int[] in = {1,2,0}; + int[] in = {1,4,2,3}; //int[] in = {3,4,-1,1}; System.out.println(firstMissingPositive(in)); } - public static int firstMissingPositive(int[] A) { + public static int firstMissingPositive1(int[] A) { if (A == null) { return 0; } - /* - 使用桶排序,将数字放置在正确的位置,如果最后发现在某个位置不存在正确的数字,说明这个数字是缺失的。 - 在排序过程中,因为要不断交换直到不能再交换为止,所以遇到目标位置已经有正确数字时,不要再交换,以 - 免发生死循环。 - */ int len = A.length; for (int i = 0; i < len; i++) { // 1. The number should be in the range. // 2. The number should be positive. - // 注意:和将要交换的值不可以相同,否则会死循环 while (A[i] <= len && A[i] > 0 && A[A[i] - 1] != A[i]) { swap(A, i, A[i] - 1); } @@ -41,4 +35,29 @@ public static void swap(int[] A, int i, int j) { A[i] = A[j]; A[j] = tmp; } + + // SOLUTION 2: + public static int firstMissingPositive(int[] A) { + // bug 3: when length is 0, return 1; + if (A == null) { + return 0; + } + + for (int i = 0; i < A.length; i++) { + // 1: A[i] is in the range; + // 2: A[i] > 0. + // 3: The target is different; + while (A[i] <= A.length && A[i] > 0 && A[A[i] - 1] != A[i]) { + swap(A, i, A[i] - 1); + } + } + + for (int i = 0; i < A.length; i++) { + if (A[i] != i + 1) { + return i + 1; + } + } + + return A.length + 1; + } } \ No newline at end of file diff --git a/dp/MaxProfit.java b/dp/MaxProfit.java index db26a1f..6d01bbb 100644 --- a/dp/MaxProfit.java +++ b/dp/MaxProfit.java @@ -16,4 +16,20 @@ public int maxProfit(int[] prices) { return maxProfit; } + + public int maxProfit2(int[] prices) { + if (prices == null) { + return 0; + } + + int maxProfit = 0; + int minValue = Integer.MAX_VALUE; + + for (int i: prices) { + minValue = Math.min(minValue, i); + maxProfit = Math.max(maxProfit, i - minValue); + } + + return maxProfit; + } } \ No newline at end of file diff --git a/dp/MaxProfit2.java b/dp/MaxProfit2.java index 4b7f576..6e5ca69 100644 --- a/dp/MaxProfit2.java +++ b/dp/MaxProfit2.java @@ -15,4 +15,26 @@ public int maxProfit(int[] prices) { return profit; } + + /* + * 2015.1.3 + * */ + public int maxProfit2(int[] prices) { + if (prices == null) { + return 0; + } + + int maxProfit = 0; + + int len = prices.length; + for (int i = 1; i < len; i++) { + int dif = prices[i] - prices[i - 1]; + + if (dif > 0) { + maxProfit += dif; + } + } + + return maxProfit; + } } \ No newline at end of file diff --git a/dp/MaxProfit3.java b/dp/MaxProfit3.java index d92cdbd..0bf412a 100644 --- a/dp/MaxProfit3.java +++ b/dp/MaxProfit3.java @@ -10,7 +10,6 @@ public int maxProfit(int[] prices) { int[] left = new int[len]; int[] right = new int[len]; - // 计算i左边的最大利润 int min = prices[0]; left[0] = 0; for (int i = 1; i < len; i++) { @@ -18,7 +17,6 @@ public int maxProfit(int[] prices) { left[i] = Math.max(left[i - 1], prices[i] - min); } - // 计算i右边的最大利润 int max = prices[len - 1]; right[len - 1] = 0; for (int i = len - 2; i >= 0; i--) { @@ -26,7 +24,6 @@ public int maxProfit(int[] prices) { right[i] = Math.max(right[i + 1], max - prices[i]); } - // 把2边的利润相加 int rst = 0; for (int i = 0; i < len; i++) { rst = Math.max(rst, left[i] + right[i]); @@ -34,4 +31,67 @@ public int maxProfit(int[] prices) { return rst; } + + // 2015.1.3: redo + public int maxProfit2(int[] prices) { + if (prices == null) { + return 0; + } + + int ret = 0; + + int len = prices.length; + int[] leftProfile = new int[len]; + int profile = 0; + + int min = Integer.MAX_VALUE; + for (int i = 0; i < len; i++) { + min = Math.min(min, prices[i]); + profile = Math.max(profile, prices[i] - min); + leftProfile[i] = profile; + } + + int max = Integer.MIN_VALUE; + profile = 0; + for (int i = len - 1; i >= 0; i--) { + max = Math.max(max, prices[i]); + profile = Math.max(profile, max - prices[i]); + + // sum the left profit and the right profit. + ret = Math.max(ret, profile + leftProfile[i]); + } + + return ret; + } + + // DP solution: + public int maxProfit3(int[] prices) { + if (prices == null || prices.length == 0) { + return 0; + } + + int ret = 0; + + int len = prices.length; + int[] leftProfile = new int[len]; + + int min = prices[0]; + leftProfile[0] = 0; + for (int i = 1; i < len; i++) { + min = Math.min(min, prices[i]); + leftProfile[i] = Math.max(leftProfile[i - 1], prices[i] - min); + } + + int max = Integer.MIN_VALUE; + int profile = 0; + for (int i = len - 1; i >= 0; i--) { + max = Math.max(max, prices[i]); + profile = Math.max(profile, max - prices[i]); + + // sum the left profit and the right profit. + ret = Math.max(ret, profile + leftProfile[i]); + } + + return ret; + } } \ No newline at end of file diff --git a/stack/IsValid.java b/stack/IsValid.java new file mode 100644 index 0000000..22107f8 --- /dev/null +++ b/stack/IsValid.java @@ -0,0 +1,50 @@ +package Algorithms.stack; + +import java.util.Stack; + +public class IsValid { + public boolean isValid(String s) { + if (s == null) { + return false; + } + + int len = s.length(); + + // bug 1: don't use s as the name of the stack. + Stack stk = new Stack(); + + for (int i = 0; i < len; i++) { + char c = s.charAt(i); + switch(c) { + case '(': + case '[': + case '{': + stk.push(c); + break; + case ')': + if (!stk.isEmpty() && stk.peek() == '(') { + stk.pop(); + } else { + return false; + } + break; + case '}': + if (!stk.isEmpty() && stk.peek() == '{') { + stk.pop(); + } else { + return false; + } + break; + case ']': + if (!stk.isEmpty() && stk.peek() == '[') { + stk.pop(); + } else { + return false; + } + break; + } + } + + return stk.isEmpty(); + } +} \ No newline at end of file diff --git a/string/Atoi.java b/string/Atoi.java index db503d1..af0714d 100644 --- a/string/Atoi.java +++ b/string/Atoi.java @@ -42,4 +42,45 @@ public int atoi(String str) { return (int)num; } + + // SOLUTION 2: the Leetcode test case is improved. + public int atoi2(String str) { + long ret = 0; + + // ___+1234__ + // Delete the leading and tailing spaces. + String sNew = str.trim(); + + if (sNew.length() == 0) { + return 0; + } + + boolean positive = true; + for (int i = 0; i < sNew.length(); i++) { + char c = sNew.charAt(i); + if (i == 0 && c == '+') { + continue; + } else if (i == 0 && c == '-') { + positive = false; + continue; + } + + if (!(c <= '9' && c >= '0')) { + break; + } + + int dig = positive ? c - '0': '0' - c; + + ret = ret * 10 + dig; + + // bug 2: should consider the out of range. + if (ret > Integer.MAX_VALUE) { + return Integer.MAX_VALUE; + } else if (ret < Integer.MIN_VALUE) { + return Integer.MIN_VALUE; + } + } + + return (int)ret; + } } \ No newline at end of file diff --git a/tree/BuildTree2.java b/tree/BuildTree2.java new file mode 100644 index 0000000..4abf538 --- /dev/null +++ b/tree/BuildTree2.java @@ -0,0 +1,44 @@ +package Algorithms.tree; + +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class BuildTree2 { + public TreeNode buildTree(int[] inorder, int[] postorder) { + if (inorder == null || postorder == null) { + return null; + } + + return dfs(inorder, postorder, 0, inorder.length - 1, 0, postorder.length - 1); + } + + public TreeNode dfs(int[] inorder, int[] postorder, int inL, int inR, int postL, int postR) { + if (inL > inR) { + return null; + } + + // create the root node. + TreeNode root = new TreeNode(postorder[postR]); + + // find the position of the root node in the inorder traversal. + int pos = 0; + for (; pos <= inR; pos++) { + if (inorder[pos] == postorder[postR]) { + break; + } + } + + int leftNum = pos - inL; + + root.left = dfs(inorder, postorder, inL, pos - 1, postL, postL + leftNum - 1); + root.right = dfs(inorder, postorder, pos + 1, inR, postL + leftNum, postR - 1); + + return root; + } +} \ No newline at end of file From fa0146982d73ded7eca9283710325e470eac1dcc Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Sun, 4 Jan 2015 06:05:14 -0800 Subject: [PATCH 307/319] del --- stack/IsValid.java | 31 +++++++++++++++++++++++++++++++ string/IsValid.java | 41 ----------------------------------------- 2 files changed, 31 insertions(+), 41 deletions(-) delete mode 100644 string/IsValid.java diff --git a/stack/IsValid.java b/stack/IsValid.java index 22107f8..a1a77cc 100644 --- a/stack/IsValid.java +++ b/stack/IsValid.java @@ -3,6 +3,37 @@ import java.util.Stack; public class IsValid { + public boolean isValid1(String s) { + if (s == null || s.length() == 0) { + return true; + } + + Stack stack = new Stack(); + int len = s.length(); + for (int i = 0; i < len; i++) { + char c = s.charAt(i); + if (stack.isEmpty()) { + if (c == ']' || c == ')' || c == '}') { + return false; + } + stack.push(c); + continue; + } + + if (c == ')' && stack.peek() == '(' + || c == ']' && stack.peek() == '[' + || c == '}' && stack.peek() == '{' + ) { + stack.pop(); + } else if (c == '(' || c == '[' || c == '{') { + stack.push(c); + } else { + return false; + } + } + + return stack.isEmpty(); + } public boolean isValid(String s) { if (s == null) { return false; diff --git a/string/IsValid.java b/string/IsValid.java deleted file mode 100644 index ec00205..0000000 --- a/string/IsValid.java +++ /dev/null @@ -1,41 +0,0 @@ -package Algorithms.string; - -import java.util.Stack; - -public class IsValid { - public boolean isValid(String s) { - if (s == null || s.length() == 0) { - return true; - } - - Stack stack = new Stack(); - int len = s.length(); - for (int i = 0; i < len; i++) { - char c = s.charAt(i); - if (stack.isEmpty()) { - // 栈为空的时候,不能放右括号 - if (c == ']' || c == ')' || c == '}') { - return false; - } - stack.push(c); - continue; - } - - // 栈不为空时,必须 要对应弹出相对应的括号 - if (c == ')' && stack.peek() == '(' - || c == ']' && stack.peek() == '[' - || c == '}' && stack.peek() == '{' - ) { - stack.pop(); - // 或者继续压入左括号 - } else if (c == '(' || c == '[' || c == '{') { - stack.push(c); - // 否则错误退出 - } else { - return false; - } - } - - return stack.isEmpty(); - } -} \ No newline at end of file From 612372025cffe125a43b94783fd5db2de724c287 Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Sun, 4 Jan 2015 06:32:08 -0800 Subject: [PATCH 308/319] pare --- string/LongestValidParentheses.java | 32 +++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/string/LongestValidParentheses.java b/string/LongestValidParentheses.java index d113a02..8b83fa5 100644 --- a/string/LongestValidParentheses.java +++ b/string/LongestValidParentheses.java @@ -50,6 +50,38 @@ public static int longestValidParentheses(String s) { } } + return max; + } + public int longestValidParentheses2(String s) { + if (s == null) { + return 0; + } + + int len = s.length(); + Stack stk = new Stack(); + + int sum = 0; + int max = 0; + for (int i = 0; i < len; i++) { + char c = s.charAt(i); + if (c == '(') { + stk.push(i); + } else { + if (stk.isEmpty()) { + // The sequence is cut off. + sum = 0; + } else { + int tmp = i - stk.pop() + 1; + if (stk.isEmpty()) { + sum += tmp; + max = Math.max(max, sum); + } else { + max = Math.max(max, i - stk.peek()); + } + } + } + } + return max; } } \ No newline at end of file From a328ac75fa17ecbcfb556b603de718a425cfbd6c Mon Sep 17 00:00:00 2001 From: piggy1991 Date: Sun, 4 Jan 2015 09:49:26 -0800 Subject: [PATCH 309/319] peak --- binarySearch/Divide.java | 76 +++++++++++++++++++++++++++++-- binarySearch/FindPeakElement.java | 66 +++++++++++++++++++++++++++ hash/Anagrams.java | 38 ++++++++++++++++ 3 files changed, 175 insertions(+), 5 deletions(-) create mode 100644 binarySearch/FindPeakElement.java diff --git a/binarySearch/Divide.java b/binarySearch/Divide.java index 4b9bd33..4f073ce 100644 --- a/binarySearch/Divide.java +++ b/binarySearch/Divide.java @@ -1,24 +1,90 @@ package Algorithms.binarySearch; public class Divide { - public int divide(int dividend, int divisor) { + public static void main(String[] strs) { + System.out.println(divide(-2147483648, -1)); + } + + public int divide1(int dividend, int divisor) { long a = Math.abs((long)dividend); // ref : http://blog.csdn.net/kenden23/article/details/16986763 - // Note: 在这里必须先取long再abs,否则int的最小值abs后也是原值 + // Note: ȡlongabsintСֵabsҲԭֵ long b = Math.abs((long)divisor); int ret = 0; - // 这里必须是= 因为相等时也可以减 + // = ΪʱҲԼ while (a >= b) { - // 判断条件是 >= + // ж >= for (long deduce = b, cnt = 1; a >= deduce; deduce <<= 1, cnt <<= 1) { a -= deduce; ret += cnt; } } - // 获取符号位。根据除数跟被除数的关系来定 + // ȡλݳĹϵ return (dividend > 0) ^ (divisor > 0) ? -ret: ret; } + + public static int divide(int dividend, int divisor) { + if (divisor == 0) { + return Integer.MAX_VALUE; + } + + // Note: ȡlongabsintСֵabsҲԭֵ + long dividendTmp = Math.abs((long)dividend); + long divisorTmp = Math.abs((long)divisor); + + // bug 3: ret should use Long to avoid overflow. + long ret = 0; + // bug 2: should use dividentTmp > divisor as the while judge. + while (dividendTmp >= divisorTmp) { + // bug 1: should use Long for tmp. + long tmp = divisorTmp; + int rst = 1; + while(tmp <= dividendTmp) { + // bug 3: the two statement should inside the while LOOP. + ret += rst; + dividendTmp -= tmp; + + tmp <<= 1; + rst <<= 1; + } + } + // bug 4: out of range: + /* + Input: -2147483648, -1 + Output: -2147483648 + Expected: 2147483647 + */ + //ret = ((dividend > 0) ^ (divisor > 0)) ? -ret: ret; + ret = ((((dividend ^ divisor) >> 31) & 1) == 1) ? -ret: ret; + + if (ret > Integer.MAX_VALUE || ret < Integer.MIN_VALUE) { + return Integer.MAX_VALUE; + } else { + return (int)ret; + } + } + + public int divide3(int dividend, int divisor) { + long a = Math.abs((long)dividend); + long b = Math.abs((long)divisor); + + long ret = 0; + + while (a >= b) { + for (long tmp = b, cnt = 1; a >= tmp; tmp <<= 1, cnt <<= 1) { + ret += cnt; + a -= tmp; + } + } + + ret = (((dividend ^ divisor) >> 31) & 1) == 1 ? -ret: ret; + if (ret > Integer.MAX_VALUE || ret < Integer.MIN_VALUE) { + return Integer.MAX_VALUE; + } + + return (int)ret; + } } \ No newline at end of file diff --git a/binarySearch/FindPeakElement.java b/binarySearch/FindPeakElement.java new file mode 100644 index 0000000..836ae1a --- /dev/null +++ b/binarySearch/FindPeakElement.java @@ -0,0 +1,66 @@ +package Algorithms.binarySearch; + +public class FindPeakElement { + public int findPeakElement1(int[] num) { + if (num == null) { + return 0; + } + + if (num.length == 1) { + return 0; + } + + for (int i = 0; i < num.length; i++) { + if (i == 0) { + if (num[i] > num[i + 1]) { + return i; + } + continue; + } + + if (i == num.length - 1) { + if (num[i] > num[i - 1]) { + return i; + } + continue; + } + + if (num[i] > num[i + 1] && num[i] > num[i - 1]) { + return i; + } + } + + return -1; + } + + public int findPeakElement(int[] num) { + if (num == null) { + return 0; + } + + if (num.length == 1) { + return 0; + } + + int l = 0; + int r = num.length - 1; + + while (l < r - 1) { + int mid = l + (r - l) / 2; + if (num[mid] > num[mid + 1] && num[mid] > num[mid - 1]) { + return mid; + } + + if (num[mid] > num[mid - 1] && num[mid] < num[mid + 1]) { + // rising area. move right; + l = mid; + } else if (num[mid] < num[mid - 1] && num[mid] > num[mid + 1]) { + r = mid; + } else { + l = mid; + } + } + + return num[l] > num[r] ? l: r; + } +} \ No newline at end of file diff --git a/hash/Anagrams.java b/hash/Anagrams.java index 13b92d6..9348692 100644 --- a/hash/Anagrams.java +++ b/hash/Anagrams.java @@ -49,4 +49,42 @@ public List anagrams(String[] strs) { return ret; } + + public static void main(String[] strs1) { + String[] strs = {"str1", "str2", "s1tr"}; + System.out.println(anagrams2(strs)); + } + + public static List anagrams2(String[] strs) { + List ret = new ArrayList(); + if (strs == null) { + return ret; + } + + HashMap> map = new HashMap>(); + for (int i = 0; i < strs.length; i++) { + String s = strs[i]; + char[] chars = s.toCharArray(); + + Arrays.sort(chars); + String sSort = new String(chars); + + if (map.containsKey(sSort)) { + map.get(sSort).add(s); + } else { + List list = new ArrayList(); + list.add(s); + map.put(sSort, list); + } + } + + for (Map.Entry> entry: map.entrySet()) { + List list = entry.getValue(); + if (list.size() > 1) { + ret.addAll(list); + } + } + + return ret; + } } \ No newline at end of file From b8e18ba5b02a75a809958a7c68b4194fdb0fa7bc Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 8 Jan 2015 01:47:11 -0800 Subject: [PATCH 310/319] recover --- permutation/PermuteUnique.java | 16 +++++--- tree/RecoverTree.java | 70 ++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/permutation/PermuteUnique.java b/permutation/PermuteUnique.java index 50a0100..4d91540 100644 --- a/permutation/PermuteUnique.java +++ b/permutation/PermuteUnique.java @@ -4,7 +4,13 @@ import java.util.List; public class PermuteUnique { - public List> permuteUnique(int[] num) { + public static void main(String[] strs) { + int[] num = {1, 1, 1, 3}; + List> ret = permuteUnique(num); + System.out.println(ret.toString()); + } + + public static List> permuteUnique(int[] num) { List> ret = new ArrayList>(); if (num == null || num.length == 0) { return ret; @@ -14,12 +20,12 @@ public List> permuteUnique(int[] num) { Arrays.sort(num); boolean[] visit = new boolean[num.length]; - dfs(num, new ArrayList(), ret, visit); + dfs1(num, new ArrayList(), ret, visit); return ret; } - public void dfs1(int[] num, ArrayList path, List> ret, boolean[] visit) { + public static void dfs1(int[] num, ArrayList path, List> ret, boolean[] visit) { int len = num.length; if (path.size() == len) { ret.add(new ArrayList(path)); @@ -30,14 +36,14 @@ public void dfs1(int[] num, ArrayList path, List> ret, bo // 只能连续地选,这样就可以避免生成重复的solution. // 例子:1 2 3 4 4 4 5 6 7 8 // 444这个的选法只能:4, 44, 444连续这三种选法 - if (visit[i] || (i != 0 && visit[i - 1] && num[i] == num[i - 1])) { + if (visit[i] || (i != 0 && !visit[i - 1] && num[i] == num[i - 1])) { continue; } // 递归以及回溯 visit[i] = true; path.add(num[i]); - dfs(num, path, ret, visit); + dfs1(num, path, ret, visit); path.remove(path.size() - 1); visit[i] = false; } diff --git a/tree/RecoverTree.java b/tree/RecoverTree.java index 87348ee..ebe39a7 100644 --- a/tree/RecoverTree.java +++ b/tree/RecoverTree.java @@ -1,5 +1,8 @@ package Algorithms.tree; +import java.util.ArrayList; +import java.util.Stack; + /** * Definition for binary tree * public class TreeNode { @@ -14,6 +17,24 @@ public class RecoverTree { TreeNode first = null; TreeNode second = null; + public static class Function { + int reference; + + Function () { + super(); + } + } + + public static void main(String[] strs) { + ArrayList list = new ArrayList(); + + list.add("string"); + list.add(1); + + Function fuc = new Function(); + + + } public void recoverTree(TreeNode root) { inOrder(root); @@ -67,4 +88,53 @@ public void inOrder(TreeNode root) { // inorder traverse. inOrder(root.right); } + + public void recoverTree1(TreeNode root) { + if (root == null) { + return; + } + + TreeNode node1 = null; + TreeNode node2 = null; + + TreeNode pre = null; + + Stack s = new Stack(); + TreeNode cur = root; + + while (true) { + while (cur != null) { + s.push(cur); + cur = cur.left; + } + + if (s.isEmpty()) { + break; + } + + TreeNode node = s.pop(); + + if (pre != null) { + // invalid order + if (pre.val > node.val) { + if (node1 == null) { + node1 = pre; + node2 = node; + } else { + node2 = node; + } + } + } + + pre = node; + + cur = node.right; + } + + int tmp = node1.val; + node1.val = node2.val; + node2.val = tmp; + + return; + } } From 157c8d9c55c4a20a0ded9082e3271b9149a82be6 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 8 Jan 2015 12:22:01 -0800 Subject: [PATCH 311/319] most flight online --- algorithm/interviews/uber/Example.java | 73 ++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/algorithm/interviews/uber/Example.java b/algorithm/interviews/uber/Example.java index 07781c3..e3fe745 100644 --- a/algorithm/interviews/uber/Example.java +++ b/algorithm/interviews/uber/Example.java @@ -167,4 +167,77 @@ public boolean wordBreak(String s, Set dict){ return dp[m]; } + // find the most plights in the sky + /* + class Point{ + int x; // start time + int y; // end time + + public Point(int x, int y){ + this.x = x; + this.y = y; + } + } + */ + public int findPeak(List flights){ + if (flights == null || flights.size() == 0){ + return 0; + } + int max = 0,i,curr = 0; + int k = flights.size(); + PriorityQueue startheap = new PriorityQueue(k,new Comparator(){ + @Override + public int compare(Integer o1, Integer o2) { + // TODO Auto-generated method stub + return o1-o2; + } + }); + PriorityQueue endheap = new PriorityQueue(k,new Comparator(){ + @Override + public int compare(Integer o1, Integer o2) { + // TODO Auto-generated method stub + return o1-o2; + } + }); + for (i=0;i flights.get(i).y){// edge case for the input + continue; + } + startheap.offer(flights.get(i).x); + endheap.offer(flights.get(i).y); + } + // get peak points via loop scan + int curr1,curr2; + while (startheap.size() > 0 && endheap.size() > 0){ + curr1 = startheap.peek(); + curr2 = endheap.peek(); + + if (curr1 < curr2){ + while (startheap.size() > 0 && startheap.peek() == curr1){ + curr++; + startheap.poll(); + } + + } + else if (curr2 < curr1){ + while (endheap.size() > 0 && endheap.peek() == curr2){ + curr--; + endheap.poll(); + } + } + else{// curr1 == curr2 + while (startheap.size() > 0 && startheap.peek() == curr1){ + curr++; + startheap.poll(); + } + while (endheap.size() > 0 && endheap.peek() == curr2){ + curr--; + endheap.poll(); + } + } + max = Math.max(max, curr); + } + + return max; + } } From c8175e1c25913dee7fc45cef51d6f34f418727b5 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 8 Jan 2015 18:53:18 -0800 Subject: [PATCH 312/319] all solutions --- algorithm/interviews/uber/Example.java | 197 +++++++++++++++++++++++++ 1 file changed, 197 insertions(+) diff --git a/algorithm/interviews/uber/Example.java b/algorithm/interviews/uber/Example.java index e3fe745..c61498b 100644 --- a/algorithm/interviews/uber/Example.java +++ b/algorithm/interviews/uber/Example.java @@ -240,4 +240,201 @@ else if (curr2 < curr1){ return max; } + /* given many logs , output */ + // use two priorityqueue: O(2nlogn) ; just sort: O(2nlog2n) + public List countRecord(List records){ + if (records == null || records.size() == 0){ + return new ArrayList(); + } + List rst = new ArrayList(); + Collections.sort(records, new Comparator(){ + @Override + public int compare(record o1, record o2) { + // TODO Auto-generated method stub + return o1.log_time - o2.log_time; + } + }); + PriorityQueue endheap = new PriorityQueue(records.size(),new Comparator(){ + @Override + public int compare(Integer o1, Integer o2) { + // TODO Auto-generated method stub + return o1-o2; + } + }); + PriorityQueue startheap = new PriorityQueue(records.size(),new Comparator(){ + @Override + public int compare(Integer o1, Integer o2) { + // TODO Auto-generated method stub + return o1-o2; + } + }); + int curr,i; + for (i=0;i 0 || endheap.size() > 0){ + int curr1 = startheap.size() > 0 ? startheap.peek() : -1; + int curr2 = endheap.size() > 0 ? endheap.peek() : -1; + if (curr1 < 0 || curr1 > curr2){// only end time left + while (endheap.size() > 0 && endheap.peek() == curr2){ + curr--; + endheap.poll(); + } + rst.add(new result(curr2,curr)); + } + else if (curr2 < 0 || curr1 < curr2){// go with start time + while (startheap.size() > 0 && startheap.peek() == curr1){ + curr++; + startheap.poll(); + } + rst.add(new result(curr1,curr)); + } + else{// curr1 == curr2 + while (endheap.size() > 0 && endheap.peek() == curr2){ + curr--; + endheap.poll(); + } + while (startheap.size() > 0 && startheap.peek() == curr1){ + curr++; + startheap.poll(); + } + rst.add(new result(curr1,curr)); + } + } + + return rst; + } + // spiral matrix + public List spiralMatrix(int[][] matrix){ + if (matrix == null || matrix.length == 0){ + return new ArrayList(); + } + List rst = new ArrayList(); + + int m = matrix.length; + int n = matrix[0].length; + int top = 0; + int bottom = m-1; + int left = 0; + int right = n-1; + int i; + int direction = 0; + while (true){ + if (direction == 0){ + for (i=left;i<=right;i++){ + rst.add(matrix[top][i]); + } + top++; + } + else if (direction == 1){ + for (i=top;i<=bottom;i++){ + rst.add(matrix[i][right]); + } + right--; + } + else if (direction == 2){ + for (i=right;i>=left;i--){ + rst.add(matrix[bottom][i]); + } + bottom--; + } + else{ + for (i=bottom;i>=top;i--){ + rst.add(matrix[i][left]); + } + left++; + } + //break + if (left > right || top > bottom){ + break; + } + // switch direction + direction = (direction+1) % 4; + } + + return rst; + } + // find the index of array in which A[i] = i, sorted array + /* problem1: no duplicate inside */ + public int findIndex(int[] num){ + if (num == null || num.length == 0){ + return -1; // defined to be the edge case number + } + int left = -1; + int right = num.length; + int mid; + + while (right - left > 1){ + mid = left + (right-left)/2; + if (num[mid] == mid){ + return mid; + } + else if (num[mid] > mid){// left + right = mid; + } + else{ + left = mid; + } + } + return -1; + } + /* problem2: duplicate exists */ + public int findIndex2(int[] num){ + if (num == null || num.length == 0){ + return -1; + } + return findMagic(num,0,num.length-1); + } + public int findMagic(int[] num, int left, int right){ + if (left < 0 || right >= num.length || left > right){ + return -1; + } + int mid,curr; + + mid = left + (right-left)/2; + if (num[mid] == mid){ + return mid; + } + else{ + // optimize here, shorten the length of binary search scope + curr = Math.min(num[mid], mid-1); + int leftIndex = findMagic(num,left,curr); + if (leftIndex >= 0){ + return leftIndex; + } + curr = Math.max(mid+1, num[mid]); + int rightIndex = findMagic(num,curr,right); + return rightIndex; + } + } + /* string shift */ + public String stringShift(String s,int shift){ + if (s == null || s.length() == 0 || shift%26 <= 0){ + return s; + } + StringBuilder sb = new StringBuilder(); + char curr; + shift = shift%26; + + for (int i=0;i= 'a' && s.charAt(i) <= 'z'){ + curr = (char)('a'+(s.charAt(i)-'a'+shift)%26); + sb.append(curr); + } + else if (s.charAt(i) >= 'A' && s.charAt(i) <= 'Z'){ + curr = (char)('A'+(s.charAt(i)-'A'+shift)%26); + sb.append(curr); + } + else{ + // throw an exception here! + } + } + + return sb.toString(); + } + } From 9c0dd103a548b4aea8b7acb856b02e83e079ea2a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 8 Jan 2015 19:16:44 -0800 Subject: [PATCH 313/319] findword --- algorithm/interviews/uber/FindWord.java | 40 +++++++++++++++++++++++++ dfs/Subsets.java | 33 ++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 algorithm/interviews/uber/FindWord.java diff --git a/algorithm/interviews/uber/FindWord.java b/algorithm/interviews/uber/FindWord.java new file mode 100644 index 0000000..26388b6 --- /dev/null +++ b/algorithm/interviews/uber/FindWord.java @@ -0,0 +1,40 @@ +package Algorithms.algorithm.interviews.uber; + +import java.util.ArrayList; + +public class FindWord { + public static void main(String[] strs) { + System.out.println(findAllStrings("xxisxhis")); + + } + + public static boolean isAWord(String s) { + if (s.equals("is")) { + return true; + } else if (s.equals("his")){ + return true; + } + return false; + } + + public static ArrayList findAllStrings(String s) { + ArrayList ret = new ArrayList(); + + if (s == null || s.length() == 0) { + return ret; + } + + int len = s.length(); + + for (int i = 0; i < len; i++) { + for (int j = i; j < len; j++) { + String sub = s.substring(i, j + 1); + if (isAWord(sub)) { + ret.add(sub); + } + } + } + + return ret; + } +} diff --git a/dfs/Subsets.java b/dfs/Subsets.java index 2247361..478fe14 100644 --- a/dfs/Subsets.java +++ b/dfs/Subsets.java @@ -31,4 +31,37 @@ public void subsets(int[] S, List path, List> ret, int in path.remove(path.size() - 1); } } + + public List> subsets2(int[] S) { + List> ret = new ArrayList>(); + if (S == null || S.length == 0) { + return ret; + } + + int len = S.length; + Arrays.sort(S); + + // forget to add (long). + long numOfSet = (long)Math.pow(2, len); + + for (int i = 0; i < numOfSet; i++) { + // bug 3: should use tmp - i. + long tmp = i; + + ArrayList list = new ArrayList(); + while (tmp != 0) { + // bug 2: use error NumberOfTrailingZeros. + int indexOfLast1 = Long.numberOfTrailingZeros(tmp); + list.add(S[indexOfLast1]); + + // clear the bit. + tmp ^= (1 << indexOfLast1); + } + + ret.add(list); + } + + return ret; + } } + From a0a0f83bf221dbc5d530d906505fb2dbd83f57b5 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 8 Jan 2015 22:30:03 -0800 Subject: [PATCH 314/319] findEqual --- algorithm/interviews/uber/FindEqualIndex.java | 57 +++++++++++++++++++ string/StrStr.java | 32 +---------- 2 files changed, 58 insertions(+), 31 deletions(-) create mode 100644 algorithm/interviews/uber/FindEqualIndex.java diff --git a/algorithm/interviews/uber/FindEqualIndex.java b/algorithm/interviews/uber/FindEqualIndex.java new file mode 100644 index 0000000..b10dbdc --- /dev/null +++ b/algorithm/interviews/uber/FindEqualIndex.java @@ -0,0 +1,57 @@ +package Algorithms.algorithm.interviews.uber; + +import java.util.ArrayList; + +public class FindEqualIndex { + public static void main(String[] str) { + int[] input = {-4,-3,-2,-1,3,4,6,7,9,10,11,12}; + System.out.println(findEqual(input)); + } + + public static ArrayList findEqual(int[] input) { + ArrayList ret = new ArrayList(); + + int l = 0; + int r = input.length - 1; + + // find the left bound. + while (l < r - 1) { + int mid = l + (r - l) / 2; + + // the value >= index. + if (input[mid] >= mid) { + r = mid; + } else { + l = mid; + } + } + + int leftBound = l == input[l] ? l: r; + + // bug:should reset l, r. + l = 0; + r = input.length - 1; + + // find the right bound. + while (l < r - 1) { + int mid = l + (r - l) / 2; + + // the value <= index. + if (input[mid] <= mid) { + // move right. + l = mid; + } else { + // move left. + r = mid; + } + } + + int rightBound = r == input[l] ? r: l; + + for (int i = leftBound; i <= rightBound; i++) { + ret.add(i); + } + + return ret; + } +} diff --git a/string/StrStr.java b/string/StrStr.java index 51accac..8a12942 100644 --- a/string/StrStr.java +++ b/string/StrStr.java @@ -7,40 +7,10 @@ public static void main(String[] strs) { System.out.println(strStr("ppa","pa")); System.out.println(findPattern("ppa","pax")); - System.out.println(findAllStrings("xxisxhis")); + //System.out.println(findAllStrings("xxisxhis")); } - public static boolean isAWord(String s) { - if (s.equals("is")) { - return true; - } else if (s.equals("his")){ - return true; - } - return false; - } - - public static ArrayList findAllStrings(String s) { - ArrayList ret = new ArrayList(); - - if (s == null || s.length() == 0) { - return ret; - } - - int len = s.length(); - - for (int i = 0; i < len; i++) { - for (int j = i; j < len; j++) { - String sub = s.substring(i, j + 1); - if (isAWord(sub)) { - ret.add(sub); - } - } - } - - return ret; - } - public static String strStr(String haystack, String needle) { if (haystack == null || needle == null) { return null; From b41b082c045e1a401423e8cd2672338449c85034 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 8 Jan 2015 22:33:19 -0800 Subject: [PATCH 315/319] bug fix --- algorithm/interviews/uber/FindEqualIndex.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/algorithm/interviews/uber/FindEqualIndex.java b/algorithm/interviews/uber/FindEqualIndex.java index b10dbdc..ff742be 100644 --- a/algorithm/interviews/uber/FindEqualIndex.java +++ b/algorithm/interviews/uber/FindEqualIndex.java @@ -6,6 +6,9 @@ public class FindEqualIndex { public static void main(String[] str) { int[] input = {-4,-3,-2,-1,3,4,6,7,9,10,11,12}; System.out.println(findEqual(input)); + + int[] input2 = {-4,-3,-2,-1,3,4,6,7,8,9,10,11}; + System.out.println(findEqual(input2)); } public static ArrayList findEqual(int[] input) { @@ -46,7 +49,7 @@ public static ArrayList findEqual(int[] input) { } } - int rightBound = r == input[l] ? r: l; + int rightBound = r == input[r] ? r: l; for (int i = leftBound; i <= rightBound; i++) { ret.add(i); From ad4b7c24409f0fc686db33dd0d6bf7d6b8b912f5 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Thu, 8 Jan 2015 23:33:57 -0800 Subject: [PATCH 316/319] sqrt --- algorithm/interviews/uber/Example.java | 51 ++++++++++++++++++- algorithm/interviews/uber/FindEqualIndex.java | 39 ++++++++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/algorithm/interviews/uber/Example.java b/algorithm/interviews/uber/Example.java index c61498b..7d47253 100644 --- a/algorithm/interviews/uber/Example.java +++ b/algorithm/interviews/uber/Example.java @@ -2,9 +2,26 @@ import java.util.*; public class Example { + public static void main(String[] strs) { + printArray(sqrt2(100)); + printArray(sqrt2(300)); + printArray(sqrt2(400)); + printArray(sqrt2(1)); + printArray(sqrt2(0)); + printArray(sqrt2(-4)); + } + + public static void printArray(int[] in) { + for (int i = 0; i < in.length; i++) { + System.out.print(in[i] + " "); + } + + System.out.println(); + } + /* sqrt(100) => 10,1 , sqrt(300) => 10,3 300 = 10^2 * 3 */ // Running time: O(sqrt(n)) - public int[] sqrt(int num){ + public static int[] sqrt(int num){ int[] rst = {-1,-1}; if (num < 0){// edge case @@ -23,6 +40,38 @@ public int[] sqrt(int num){ return rst; } + // Author: Yu Zhang. + public static int[] sqrt2(int n) { + int[] rst = {-1, -1}; + + if (n < 0) { + return rst; + } + + if (n == 0) { + rst[0] = 0; + rst[1] = 0; + return rst; + } + + int sqrNum = (int) Math.sqrt(n); + + //System.out.println("sqrNum:" + sqrNum); + + while (sqrNum >= 1) { + if (n % (sqrNum * sqrNum) == 0) { + rst[0] = n; + rst[1] = n / (sqrNum * sqrNum); + // bug: forget to return. + return rst; + } + + sqrNum--; + } + + return rst; + } + /* given a number, find the next prime which is bigger than it */ // Running time: O(nlogm) => m is an average recursion depth for each number, how to optimize it? public int getNextPrime(int value){ diff --git a/algorithm/interviews/uber/FindEqualIndex.java b/algorithm/interviews/uber/FindEqualIndex.java index ff742be..13da545 100644 --- a/algorithm/interviews/uber/FindEqualIndex.java +++ b/algorithm/interviews/uber/FindEqualIndex.java @@ -9,6 +9,9 @@ public static void main(String[] str) { int[] input2 = {-4,-3,-2,-1,3,4,6,7,8,9,10,11}; System.out.println(findEqual(input2)); + + int[] input3 = {-4, -3, -2, -1, 3, 4, 6, 7, 9, 10, 11, 13}; + System.out.println(findEqual2(input3)); } public static ArrayList findEqual(int[] input) { @@ -57,4 +60,40 @@ public static ArrayList findEqual(int[] input) { return ret; } + + /* + * Author: He Long. + */ + public static ArrayList findEqual2(int[] A) { + ArrayList res = new ArrayList(); + if (A == null || A.length == 0) { + return res; + } + int ll = 0; + int lr = A.length - 1; + while (ll <= lr) { + int m = ll + (lr - ll) / 2; + if (A[m] - m < 0) { + ll = m + 1; + } else { + lr = m - 1; + } + } + int rl = 0; + int rr = A.length - 1; + while (rl <= rr) { + int m = rl + (rr - rl) / 2; + if (A[m] - m <= 0) { + rl = m + 1; + } else { + rr = m - 1; + } + } + if (ll <= rr) { + while (ll <= rr) { + res.add(A[ll++]); + } + } + return res; + } } From 6e03613436868b939a58b525869d730829c520fa Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 9 Jan 2015 02:03:22 -0800 Subject: [PATCH 317/319] spiral order --- algorithm/interviews/uber/Example.java | 12 +++++++ array/SpiralOrder.java | 48 ++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/algorithm/interviews/uber/Example.java b/algorithm/interviews/uber/Example.java index 7d47253..6cee43a 100644 --- a/algorithm/interviews/uber/Example.java +++ b/algorithm/interviews/uber/Example.java @@ -95,6 +95,7 @@ public boolean isPrime(int target){ } return true; } + /* given many logs , output */ // use two priorityqueue: O(2nlogn) ; just sort: O(2nlog2n) public List countRecord(List records){ @@ -109,6 +110,7 @@ public int compare(record o1, record o2) { return o1.log_time - o2.log_time; } }); + PriorityQueue endheap = new PriorityQueue(records.size(),new Comparator(){ @Override public int compare(Integer o1, Integer o2) { @@ -116,6 +118,7 @@ public int compare(Integer o1, Integer o2) { return o1-o2; } }); + PriorityQueue startheap = new PriorityQueue(records.size(),new Comparator(){ @Override public int compare(Integer o1, Integer o2) { @@ -123,7 +126,9 @@ public int compare(Integer o1, Integer o2) { return o1-o2; } }); + int curr,i; + for (i=0;i 'A'-'Z' public int numDecodings(String s){ if (s == null || s.length() == 0){ @@ -216,6 +222,7 @@ public boolean wordBreak(String s, Set dict){ return dp[m]; } + // find the most plights in the sky /* class Point{ @@ -357,6 +364,7 @@ else if (curr2 < 0 || curr1 < curr2){// go with start time return rst; } + // spiral matrix public List spiralMatrix(int[][] matrix){ if (matrix == null || matrix.length == 0){ @@ -407,6 +415,7 @@ else if (direction == 2){ return rst; } + // find the index of array in which A[i] = i, sorted array /* problem1: no duplicate inside */ public int findIndex(int[] num){ @@ -431,6 +440,7 @@ else if (num[mid] > mid){// left } return -1; } + /* problem2: duplicate exists */ public int findIndex2(int[] num){ if (num == null || num.length == 0){ @@ -438,6 +448,7 @@ public int findIndex2(int[] num){ } return findMagic(num,0,num.length-1); } + public int findMagic(int[] num, int left, int right){ if (left < 0 || right >= num.length || left > right){ return -1; @@ -460,6 +471,7 @@ public int findMagic(int[] num, int left, int right){ return rightIndex; } } + /* string shift */ public String stringShift(String s,int shift){ if (s == null || s.length() == 0 || shift%26 <= 0){ diff --git a/array/SpiralOrder.java b/array/SpiralOrder.java index 7ac977a..5545e6a 100644 --- a/array/SpiralOrder.java +++ b/array/SpiralOrder.java @@ -181,4 +181,52 @@ public static List spiralOrder(int[][] matrix) { return ret; } + + // Solution 4: Use Four corners. + public List spiralOrder4(int[][] matrix) { + List ret = new ArrayList(); + if (matrix == null ||matrix.length == 0) { + // 注意在非法的时候,应该返回空解,而不是一个NULL值 + return ret; + } + + // Record how many rows and cols we still have. + int rows = matrix.length; + int cols = matrix[0].length; + + // The four corners. + int top = 0; + int left = 0; + int bottom = rows - 1; + int right = cols - 1; + + // every time we go through two rows and two cols. + for (; rows > 0 && cols > 0; rows -= 2, cols -= 2, top++, left++, bottom--, right--) { + // the first line. + for (int i = left; i <= right; i++) { + ret.add(matrix[top][i]); + } + + // the right column. + for (int i = top + 1; i < bottom; i++) { + ret.add(matrix[i][right]); + } + + // the down line; + if (rows > 1) { + for (int j = right; j >= left; j--) { + ret.add(matrix[bottom][j]); + } + } + + // the left column. + if (cols > 1) { + for (int i = bottom - 1; i > top; i --) { + ret.add(matrix[i][left]); + } + } + } + + return ret; + } } From 7adcc049960a7019d91f5e9d46f2d41b038eda5c Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 9 Jan 2015 10:40:19 -0800 Subject: [PATCH 318/319] spiralOrder --- algorithm/interviews/uber/Example.java | 617 +++++++++++++++++++++---- array/SpiralOrder.java | 49 ++ 2 files changed, 567 insertions(+), 99 deletions(-) diff --git a/algorithm/interviews/uber/Example.java b/algorithm/interviews/uber/Example.java index 6cee43a..a01c90b 100644 --- a/algorithm/interviews/uber/Example.java +++ b/algorithm/interviews/uber/Example.java @@ -3,12 +3,43 @@ import java.util.*; public class Example { public static void main(String[] strs) { - printArray(sqrt2(100)); - printArray(sqrt2(300)); - printArray(sqrt2(400)); - printArray(sqrt2(1)); - printArray(sqrt2(0)); - printArray(sqrt2(-4)); +// printArray(sqrt2(100)); +// printArray(sqrt2(300)); +// printArray(sqrt2(400)); +// printArray(sqrt2(1)); +// printArray(sqrt2(0)); +// printArray(sqrt2(-4)); + +// int start = 1; +// for (int i = 0; i < 1000; i++) { +// System.out.print(start + " "); +// start = getNextPrime2(start); +// } + +// List records = new ArrayList(); +// records.add(new Record("a", 0, 2)); +// records.add(new Record("a", 1, 3)); +// records.add(new Record("a", 3, 5)); +// records.add(new Record("a", 2, 4)); +// records.add(new Record("a", 3, 5)); +// records.add(new Record("a", 4, 8)); +// records.add(new Record("a", 5, 10)); +// +// List ret = countRecord2(records); +// +// for (LogResult logRet: ret) { +// System.out.println(logRet.time + " " + logRet.number_of_users); +// } +// +// System.out.println(findPeak2(records)); + + int[] A = {-1,0,1,2,3,5,8,9}; + System.out.println(findIndex2(A)); + + int[] A3 = {0,0,1,2,3,5,8,9}; + System.out.println(findIndex3(A3)); + + System.out.println(stringShift2("abC", 24)); } public static void printArray(int[] in) { @@ -74,18 +105,28 @@ public static int[] sqrt2(int n) { /* given a number, find the next prime which is bigger than it */ // Running time: O(nlogm) => m is an average recursion depth for each number, how to optimize it? - public int getNextPrime(int value){ + public static int getNextPrime(int value){ if (value <= 1){ return 2; } - int target = value+1; + + int target = value + 1; + + // Yu Zhang optimize. Odds will not be prime. + if (target % 2 == 0) { + target++; + } + while (!isPrime(target)){ - target++; + // Yu Zhang optimize 1: target += 2. + target += 2; + //target++; } return target; } - public boolean isPrime(int target){ + + public static boolean isPrime(int target){ int n = 2; while (n*n <= target){// may overflow here! if (target % n == 0){ @@ -96,16 +137,81 @@ public boolean isPrime(int target){ return true; } + // Yu Zhang solution: + //http://stackoverflow.com/questions/6654671/whats-the-built-in-function-that-finds-next-largest-prime-number-in-java + //https://www.youtube.com/watch?v=nkIt8M9asaM + public static int getNextPrime2 (int val) { + if (val <= 1) { + return 2; + } + + val++; + if (val % 2 == 0) { + val++; + } + + while (!isPrime2(val)) { + val += 2; + if (val < 0) { + return -1; + } + } + + return val; + } + + public static boolean isPrime2(int target){ + int n = 3; + + // yu zhang: use / to avoid overflow. + + int sqrt = (int)Math.sqrt(target); + while (n <= sqrt) { + if (target % n == 0) { + return false; + } + + // bug: should addup n; + // Yu Zhang optimize: target will never be divided by odd. + n += 2; + } + + return true; + } + + public static class Record { + String username; + int log_time; + int logout_time; + public Record(String username, int log_time, int logout_time) { + super(); + this.username = username; + this.log_time = log_time; + this.logout_time = logout_time; + } + } + + public static class LogResult { + int time; + int number_of_users; + + LogResult (int time, int number_of_users) { + this.time = time; + this.number_of_users = number_of_users; + } + } + /* given many logs , output */ - // use two priorityqueue: O(2nlogn) ; just sort: O(2nlog2n) - public List countRecord(List records){ + // use two priority queue: O(2nlogn) ; just sort: O(2nlog2n) + public List countRecord(List records){ if (records == null || records.size() == 0){ - return new ArrayList(); + return new ArrayList(); } - List rst = new ArrayList(); - Collections.sort(records, new Comparator(){ + + List rst = new ArrayList(); + Collections.sort(records, new Comparator(){ @Override - public int compare(record o1, record o2) { + public int compare(Record o1, Record o2) { // TODO Auto-generated method stub return o1.log_time - o2.log_time; } @@ -130,10 +236,11 @@ public int compare(Integer o1, Integer o2) { int curr,i; for (i=0;i 0 || endheap.size() > 0){ @@ -144,14 +251,14 @@ record tmp = records.get(i); curr--; endheap.poll(); } - rst.add(new result(curr2,curr)); + rst.add(new LogResult(curr2,curr)); } else if (curr2 < 0 || curr1 < curr2){// go with start time while (startheap.size() > 0 && startheap.peek() == curr1){ curr++; startheap.poll(); } - rst.add(new result(curr1,curr)); + rst.add(new LogResult(curr1,curr)); } else{// curr1 == curr2 while (endheap.size() > 0 && endheap.peek() == curr2){ @@ -162,13 +269,50 @@ else if (curr2 < 0 || curr1 < curr2){// go with start time curr++; startheap.poll(); } - rst.add(new result(curr1,curr)); + rst.add(new LogResult(curr1,curr)); } } return rst; } + /* given many logs , output */ + // use two priority queue: O(2nlogn) ; just sort: O(2nlog2n) + + // Yu Zhang solution. + public static List countRecord2(List records){ + ArrayList ret = new ArrayList(); + + if (records == null || records.size() == 0){ + return new ArrayList(); + } + + ArrayList timeList = new ArrayList(); + for (Record record: records) { + timeList.add(new LogResult(record.log_time, 1)); + timeList.add(new LogResult(record.logout_time, -1)); + } + + // bug: forget the right way to write comparator. + Collections.sort(timeList, new Comparator(){ + public int compare(LogResult o1, LogResult o2) { + return o1.time - o2.time; + } + }); + + int num = 0; + for (int i = 0; i < timeList.size(); i++) { + num += timeList.get(i).number_of_users; + + if (i == timeList.size() - 1 + || (timeList.get(i).time != timeList.get(i + 1).time)) { + ret.add(new LogResult(timeList.get(i).time, num)); + } + } + + return ret; + } + // decode ways: 1-26 => 'A'-'Z' public int numDecodings(String s){ if (s == null || s.length() == 0){ @@ -197,7 +341,75 @@ public int numDecodings(String s){ return next; } - // wordbreak => [lock,locker, erning] ; lockerning : true, lockern : false + + // Yu Zhang solution. + public int numDecodings2(String s) { + if (s == null || s.length() == 0) { + return 0; + } + + int len = s.length(); + int[] D = new int[len + 1]; + for (int i = 0; i <= len; i++) { + if (i == 0) { + D[i] = 1; + } else { + D[i] = 0; + if (isValidSingle(s.charAt(i - 1))) { + D[i] += D[i - 1]; + } + + if (i >= 2 && isValidTwo(s.substring(i - 2, i))) { + D[i] += D[i - 2]; + } + } + } + + return D[len]; + } + + public boolean isValidSingle(char c) { + return c != '0'; + } + + public boolean isValidTwo(String s) { + int num = Integer.parseInt(s); + return num <= 26 && num >= 10; + } + + // solution 3: + public int numDecodings3(String s) { + // bug 1: return 0 when len is 0. + if (s == null || s.length() == 0) { + return 0; + } + + int len = s.length(); + + // The result of first i digits. + int pre = 1; + int prepre = 0; + + for (int i = 1; i <= len; i++) { + // i >= 1 + int cur = 0; + if (i >= 2 && isValidTwo(s.substring(i - 2, i))) { + cur += prepre; + } + + // The digit should not be 0. + if (s.charAt(i - 1) != '0') { + cur += pre; + } + + prepre = pre; + pre = cur; + } + + return pre; + } + + // Wordbreak => [lock,locker, erning] ; lockerning : true, lockern : false public boolean wordBreak(String s, Set dict){ if (dict == null || s == null || s.length() == 0 || dict.size() == 0){ return false; @@ -223,18 +435,44 @@ public boolean wordBreak(String s, Set dict){ return dp[m]; } + // yu zhang solution. + public boolean wordBreak2(String s, Set dict) { + if(s == null || dict == null) { + return false; + } + + // bug 2: length() + int len = s.length(); + // bug 1: use boolean not int. + boolean[] D = new boolean[len + 1]; + + for (int i = 0; i <= len; i++) { + if (i == 0) { + D[i] = true; + } else { + for (int j = 0; j < i; j++) { + if (D[j] && dict.contains(s.substring(j, i))) { + D[i] = true; + break; + } + } + } + } + + return D[len]; + } + // find the most plights in the sky - /* - class Point{ - int x; // start time - int y; // end time + class Point{ + int x; // start time + int y; // end time - public Point(int x, int y){ - this.x = x; - this.y = y; - } - } - */ + public Point(int x, int y){ + this.x = x; + this.y = y; + } + } + public int findPeak(List flights){ if (flights == null || flights.size() == 0){ return 0; @@ -296,74 +534,112 @@ else if (curr2 < curr1){ return max; } + + // Yu Zhang solution. + public static int findPeak2(List records){ + ArrayList ret = new ArrayList(); + + if (records == null || records.size() == 0){ + return 0; + } + + ArrayList timeList = new ArrayList(); + for (Record record: records) { + timeList.add(new LogResult(record.log_time, 1)); + timeList.add(new LogResult(record.logout_time, -1)); + } + + // bug: forget the right way to write comparator. + Collections.sort(timeList, new Comparator(){ + public int compare(LogResult o1, LogResult o2) { + return o1.time - o2.time; + } + }); + + int num = 0; + int max = 0; + for (int i = 0; i < timeList.size(); i++) { + num += timeList.get(i).number_of_users; + + if (i == timeList.size() - 1 + || (timeList.get(i).time != timeList.get(i + 1).time)) { + ret.add(new LogResult(timeList.get(i).time, num)); + } + + max = Math.max(max, num); + } + + return max; + } + /* given many logs , output */ // use two priorityqueue: O(2nlogn) ; just sort: O(2nlog2n) - public List countRecord(List records){ - if (records == null || records.size() == 0){ - return new ArrayList(); - } - List rst = new ArrayList(); - Collections.sort(records, new Comparator(){ - @Override - public int compare(record o1, record o2) { - // TODO Auto-generated method stub - return o1.log_time - o2.log_time; - } - }); - PriorityQueue endheap = new PriorityQueue(records.size(),new Comparator(){ - @Override - public int compare(Integer o1, Integer o2) { - // TODO Auto-generated method stub - return o1-o2; - } - }); - PriorityQueue startheap = new PriorityQueue(records.size(),new Comparator(){ - @Override - public int compare(Integer o1, Integer o2) { - // TODO Auto-generated method stub - return o1-o2; - } - }); - int curr,i; - for (i=0;i 0 || endheap.size() > 0){ - int curr1 = startheap.size() > 0 ? startheap.peek() : -1; - int curr2 = endheap.size() > 0 ? endheap.peek() : -1; - if (curr1 < 0 || curr1 > curr2){// only end time left - while (endheap.size() > 0 && endheap.peek() == curr2){ - curr--; - endheap.poll(); - } - rst.add(new result(curr2,curr)); - } - else if (curr2 < 0 || curr1 < curr2){// go with start time - while (startheap.size() > 0 && startheap.peek() == curr1){ - curr++; - startheap.poll(); - } - rst.add(new result(curr1,curr)); - } - else{// curr1 == curr2 - while (endheap.size() > 0 && endheap.peek() == curr2){ - curr--; - endheap.poll(); - } - while (startheap.size() > 0 && startheap.peek() == curr1){ - curr++; - startheap.poll(); - } - rst.add(new result(curr1,curr)); - } - } - - return rst; - } +// public List countRecord(List records){ +// if (records == null || records.size() == 0){ +// return new ArrayList(); +// } +// List rst = new ArrayList(); +// Collections.sort(records, new Comparator(){ +// @Override +// public int compare(record o1, record o2) { +// // TODO Auto-generated method stub +// return o1.log_time - o2.log_time; +// } +// }); +// PriorityQueue endheap = new PriorityQueue(records.size(),new Comparator(){ +// @Override +// public int compare(Integer o1, Integer o2) { +// // TODO Auto-generated method stub +// return o1-o2; +// } +// }); +// PriorityQueue startheap = new PriorityQueue(records.size(),new Comparator(){ +// @Override +// public int compare(Integer o1, Integer o2) { +// // TODO Auto-generated method stub +// return o1-o2; +// } +// }); +// int curr,i; +// for (i=0;i 0 || endheap.size() > 0){ +// int curr1 = startheap.size() > 0 ? startheap.peek() : -1; +// int curr2 = endheap.size() > 0 ? endheap.peek() : -1; +// if (curr1 < 0 || curr1 > curr2){// only end time left +// while (endheap.size() > 0 && endheap.peek() == curr2){ +// curr--; +// endheap.poll(); +// } +// rst.add(new result(curr2,curr)); +// } +// else if (curr2 < 0 || curr1 < curr2){// go with start time +// while (startheap.size() > 0 && startheap.peek() == curr1){ +// curr++; +// startheap.poll(); +// } +// rst.add(new result(curr1,curr)); +// } +// else{// curr1 == curr2 +// while (endheap.size() > 0 && endheap.peek() == curr2){ +// curr--; +// endheap.poll(); +// } +// while (startheap.size() > 0 && startheap.peek() == curr1){ +// curr++; +// startheap.poll(); +// } +// rst.add(new result(curr1,curr)); +// } +// } +// +// return rst; +// } // spiral matrix public List spiralMatrix(int[][] matrix){ @@ -416,6 +692,56 @@ else if (direction == 2){ return rst; } + // Solution 4: Use Four corners. + // Author: Yu Zhang. + // spiral matrix + public List spiralOrder4(int[][] matrix) { + List ret = new ArrayList(); + if (matrix == null ||matrix.length == 0) { + // 注意在非法的时候,应该返回空解,而不是一个NULL值 + return ret; + } + + // Record how many rows and cols we still have. + int rows = matrix.length; + int cols = matrix[0].length; + + // The four corners. + int top = 0; + int left = 0; + int bottom = rows - 1; + int right = cols - 1; + + // every time we go through two rows and two cols. + for (; rows > 0 && cols > 0; rows -= 2, cols -= 2, top++, left++, bottom--, right--) { + // the first line. + for (int i = left; i <= right; i++) { + ret.add(matrix[top][i]); + } + + // the right column. + for (int i = top + 1; i < bottom; i++) { + ret.add(matrix[i][right]); + } + + // the down line; + if (rows > 1) { + for (int j = right; j >= left; j--) { + ret.add(matrix[bottom][j]); + } + } + + // the left column. + if (cols > 1) { + for (int i = bottom - 1; i > top; i --) { + ret.add(matrix[i][left]); + } + } + } + + return ret; + } + // find the index of array in which A[i] = i, sorted array /* problem1: no duplicate inside */ public int findIndex(int[] num){ @@ -442,11 +768,11 @@ else if (num[mid] > mid){// left } /* problem2: duplicate exists */ - public int findIndex2(int[] num){ + public static int findIndex2(int[] num){ if (num == null || num.length == 0){ return -1; } - return findMagic(num,0,num.length-1); + return findMagic2(num,0,num.length-1); } public int findMagic(int[] num, int left, int right){ @@ -472,6 +798,67 @@ public int findMagic(int[] num, int left, int right){ } } + // Yu Zhang solution: + + public static ArrayList findIndex3(int[] num){ + if (num == null || num.length == 0){ + return null; + } + + ArrayList ret = new ArrayList(); + findMagic3(num,0,num.length-1, ret); + return ret; + } + + public static int findMagic2(int[] num, int left, int right){ + if (left > right) { + return -1; + } + + int mid = left + (right - left) / 2; + + if (num[mid] == mid) { + return mid; + } + + if (num[mid] >= left) { + int ret = findMagic2(num, left, mid - 1); + if (ret != -1) { + return ret; + } + } + + if (num[mid] <= right) { + int ret = findMagic2(num, mid + 1, right); + if (ret != -1) { + return ret; + } + } + + return -1; + } + + // There are duplicate solutions. + public static void findMagic3(int[] num, int left, int right, ArrayList ret){ + if (left > right) { + return; + } + + int mid = left + (right - left) / 2; + + if (num[mid] == mid) { + ret.add(mid); + } + + if (num[mid] >= left) { + findMagic3(num, left, mid - 1, ret); + } + + if (num[mid] <= right) { + findMagic3(num, mid + 1, right, ret); + } + } + /* string shift */ public String stringShift(String s,int shift){ if (s == null || s.length() == 0 || shift%26 <= 0){ @@ -498,4 +885,36 @@ else if (s.charAt(i) >= 'A' && s.charAt(i) <= 'Z'){ return sb.toString(); } + /* string shift */ + public static String stringShift2(String s,int shift){ + if (s == null || s.length() == 0 || shift%26 <= 0){ + return s; + } + + StringBuilder sb = new StringBuilder(); + + shift = shift % 26; + + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + int num = 0; + if (c <= 'z' && c >= 'a') { + num = c - 'a'; + num += shift; + num %= 26; + num += 'a'; + } else if (c <= 'Z' && c >= 'A') { + num = c - 'A'; + num += shift; + num %= 26; + num += 'A'; + } + + char c1 = (char)num; + sb.append(c1); + } + + + return sb.toString(); + } } diff --git a/array/SpiralOrder.java b/array/SpiralOrder.java index 5545e6a..a65a4f9 100644 --- a/array/SpiralOrder.java +++ b/array/SpiralOrder.java @@ -229,4 +229,53 @@ public List spiralOrder4(int[][] matrix) { return ret; } + + // Solution 4.2: don't use rows and cols. + public List spiralOrder3(int[][] matrix) { + List ret = new ArrayList(); + if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { + return ret; + } + + int rows = matrix.length; + int cols = matrix[0].length; + + int left = 0; + int right = cols - 1; + int top = 0; + int bottom = rows - 1; + + while (left <= right && top <= bottom) { + // line top. + for (int i = left; i <= right; i++) { + ret.add(matrix[top][i]); + } + + // line right; + for (int i = top + 1; i <= bottom - 1; i++) { + ret.add(matrix[i][right]); + } + + // line bottom. + if (top != bottom) { + for (int i = right; i >= left; i--) { + ret.add(matrix[bottom][i]); + } + } + + // line left; + if (left != right) { + for (int i = bottom - 1; i >= top + 1; i--) { + ret.add(matrix[i][left]); + } + } + + left++; + right--; + top++; + bottom--; + } + + return ret; + } } From f299cda1b3bffee37f6a705b938497e73b60e65e Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Fri, 9 Jan 2015 22:53:37 -0800 Subject: [PATCH 319/319] example.com --- algorithm/interviews/uber/Example.java | 183 ++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 6 deletions(-) diff --git a/algorithm/interviews/uber/Example.java b/algorithm/interviews/uber/Example.java index a01c90b..bd1c1e1 100644 --- a/algorithm/interviews/uber/Example.java +++ b/algorithm/interviews/uber/Example.java @@ -1,8 +1,12 @@ package Algorithms.algorithm.interviews.uber; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.*; + +import Algorithms.tree.TreeNode; public class Example { - public static void main(String[] strs) { + public static void main(String[] strs) throws NoSuchAlgorithmException { // printArray(sqrt2(100)); // printArray(sqrt2(300)); // printArray(sqrt2(400)); @@ -33,15 +37,53 @@ public static void main(String[] strs) { // // System.out.println(findPeak2(records)); - int[] A = {-1,0,1,2,3,5,8,9}; - System.out.println(findIndex2(A)); +// int[] A = {-1,0,1,2,3,5,8,9}; +// System.out.println(findIndex2(A)); +// +// int[] A3 = {0,0,1,2,3,5,8,9}; +// System.out.println(findIndex3(A3)); +// +// System.out.println(stringShift2("abC", 24)); +// +// ArrayList list = new ArrayList(); +// list.add("cba"); +// list.add("abc"); +// list.add("bcd"); +// list.add("dogs"); +// list.add("xyz"); +// list.add("zab"); +// list.add("c"); +// list.add("d"); +// getSame(list); + System.out.println(getShort("www.uber.com")); + + System.out.println(getFullUrl("f626cf")); + + TreeNode root = new TreeNode(1); + TreeNode node1 = new TreeNode(5); + TreeNode node2 = new TreeNode(6); + TreeNode node3 = new TreeNode(4); + + TreeNode node4 = new TreeNode(3); + TreeNode node5 = new TreeNode(2); + TreeNode node6 = new TreeNode(1); + + root.left = node1; + root.right = node2; + + root.left.left = node3; - int[] A3 = {0,0,1,2,3,5,8,9}; - System.out.println(findIndex3(A3)); + node2.left = node4; + node2.right = node5; - System.out.println(stringShift2("abC", 24)); + node5.right = node6; + + System.out.println(getPath(root, 10)); } + static HashMap map = new HashMap(); + static HashMap mapFull = new HashMap(); + public static void printArray(int[] in) { for (int i = 0; i < in.length; i++) { System.out.print(in[i] + " "); @@ -917,4 +959,133 @@ public static String stringShift2(String s,int shift){ return sb.toString(); } + + public static void getSame(ArrayList input) { + ArrayList> ret = new ArrayList>(); + if (input == null) { + return; + } + + HashMap> map = new HashMap>(); + + for (String str: input) { + char c1 = str.charAt(0); + + int shift = c1 - 'a'; + + int len = str.length(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < len; i++) { + char c = str.charAt(i); + int num = c - 'a'; + + num -= shift; + if (num < 0) { + num += 26; + } + + num += 'a'; + sb.append((char)num); + } + + String strNew = sb.toString(); + if (map.containsKey(strNew)) { + map.get(strNew).add(str); + } else { + ArrayList list = new ArrayList(); + list.add(str); + map.put(strNew, list); + } + } + + System.out.println(map.toString()); + } + + public static String getShort(String url) throws NoSuchAlgorithmException { + if (url == null) { + return ""; + } + + if (mapFull.containsKey(url)) { + return mapFull.get(url); + } + + String original = url; + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(original.getBytes()); + byte[] digest = md.digest(); + StringBuffer sb = new StringBuffer(); + for (byte b : digest) { + sb.append(String.format("%02x", b & 0xff)); + } + + System.out.println("original:" + original); + System.out.println("digested(hex):" + sb.toString()); + + String md5 = sb.toString(); + + String shortUrl = md5.substring(0, 6); + if (map.containsKey(shortUrl)) { + for (int i = 0; i < shortUrl.length(); i++) { + StringBuilder sbChange = new StringBuilder(shortUrl); + for (char c = 'a'; c <= 'z'; c++) { + sbChange.setCharAt(i, c); + shortUrl = sbChange.toString(); + if (!map.containsKey(shortUrl)) { + break; + } + } + } + map.put(shortUrl, url); + } else { + map.put(shortUrl, url); + } + + mapFull.put(url, shortUrl); + + return "http://uber.gl/" + shortUrl; + } + + public static String getFullUrl(String url){ + if (url == null) { + return ""; + } + + if (map.containsKey(url)) { + return map.get(url); + } else { + return ""; + } + } + + public static ArrayList> getPath(TreeNode root, int target) { + ArrayList> ret = new ArrayList>(); + + getPath(root, new ArrayList(), target, ret); + return ret; + } + + public static void getPath(TreeNode root, ArrayList path, int target, + ArrayList> ret) { + if (root == null) { + return; + } + + path.add(root.val); + target -= root.val; + if (target == 0 && root.left == null && root.right == null) { + ret.add(new ArrayList(path)); + path.remove(path.size() - 1); + return; + } + + if (target < 0) { + path.remove(path.size() - 1); + return; + } + + getPath(root.left, path, target, ret); + getPath(root.right, path, target, ret); + path.remove(path.size() - 1); + } }