├── .classpath ├── .gitignore ├── README.md └── src └── me └── zonglun ├── AutumnRecruitment └── FireHome │ ├── Soldierqueue.java │ ├── XiaoMingsChessboard.java │ ├── coding2019 │ ├── makeFriends.java │ └── samleString.java │ └── learningSpelling.java ├── BinaryTree ├── BST.java ├── BinarySearch.java ├── BinarySearch2.java ├── BlackRedBST.java ├── FileOperations.java ├── Main.java ├── SST.java ├── SeparateChainingHashST.java ├── SequentialSearchST.java ├── TestBST.java ├── TestBinarySearch.java ├── TestRedBlackBST.java └── bible.txt ├── Graph ├── Components.java ├── DenseGraph.java ├── Edge.java ├── Graph.java ├── Path.java ├── ReadGraph.java ├── ReadWeightedGraph.java ├── ShortestPath.java ├── SparseGraph.java ├── SparseWeightedGraph.java ├── TestGraph.java ├── TestPath.java ├── TestWeightedGraph.java ├── WeightedGraph.java ├── testG.txt ├── testG1.txt └── testG2.txt ├── Sort ├── BubbleSort.java ├── GetThNumber.java ├── HeapSort1.java ├── HeapSort2.java ├── HeapSort3.java ├── IndexHeapSort.java ├── IndexMaxHeap.java ├── InsertionSort.java ├── InversionPair.java ├── MaxHeap.java ├── MergeSort.java ├── MergeSortBU.java ├── PrintableMaxHeap.java ├── QuickSort.java ├── QuickSort2Ways.java ├── QuickSortOptimize.java ├── QuickSortThreeWays.java ├── README.md ├── RadixSort.java ├── SelectionSort.java ├── ShellSort.java ├── SortTestHelper.java └── Student.java ├── SwordToOffer ├── AddFunction.java ├── ConvertBSTToLinkList.java ├── DeleteDuplicationListNode.java ├── DoublylinkedList.java ├── DuplicateNum.java ├── EntryNodeOfLoop.java ├── Fibonacci.java ├── FindContinuousSequence.java ├── FindFirstCommonNodeInList.java ├── FindGreatestSumOfSubArray.java ├── FindInPartiallySortedMatrix.java ├── FindKthInBinaryTree.java ├── FindKthToTail.java ├── FindNumbersWithSum.java ├── FindNumsAppearOnce.java ├── FindPathInBinaryTree.java ├── FirstAppearingOnce.java ├── FirstNotRepeatingChar.java ├── FlowWindows.java ├── GetLeastNumbers_Solution.java ├── GetMinStack.java ├── GetNextTreeNode.java ├── GetNumOfK.java ├── GetUglyNumber_Solution.java ├── HasSubtree.java ├── InversePairs.java ├── IsBalanced_Solution.java ├── IsContinuous.java ├── IsPopOrder.java ├── IsSymmetrical.java ├── JumpSteps.java ├── JumpStepsII.java ├── LastRemaining_Solution.java ├── LeftRotateString.java ├── ListNodeMerge.java ├── MatrxPath.java ├── MiddleNumberInDataFlow.java ├── MinNumberInRotateArray.java ├── MirrorBinaryTree.java ├── MoreThanHalfNum_Solution.java ├── MoveMachine.java ├── MultiplyArray.java ├── NextTreeNode.java ├── NumberOf1.java ├── NumberOf1Between1AndN_Solution.java ├── PermutationList.java ├── Power.java ├── PrintBinaryTreeByZ.java ├── PrintBinayTreeInOrder.java ├── PrintFromTopToBottom.java ├── PrintListFromTailToHead.java ├── PrintMatrix.java ├── PrintMinNumber.java ├── RandomListNodeClone.java ├── ReConstructBinaryTree.java ├── ReOrderArray.java ├── RectCover.java ├── RegMach.java ├── ReplaceBlank.java ├── ReverseList.java ├── ReverseSentence.java ├── SerializeBinaryTree.java ├── StrToInt.java ├── StringIsNum.java ├── Sum_SolutionN.java ├── TreeDepth.java ├── TwoStackQueue.java ├── VerifySquenceOfBST.java └── util │ ├── ListNode.java │ ├── TreeLinkNode.java │ └── TreeNode.java ├── UnionFind ├── UnionFind1.java ├── UnionFind2.java ├── UnionFind3.java ├── UnionFind4.java └── UnionFindTestHelper.java └── leetcode ├── Algorithms ├── CardinalitySort.java ├── DP │ ├── Packages01.java │ ├── question322 │ │ └── coinChange.java │ ├── question53 │ │ └── MaximumSubarray.java │ └── question70 │ │ └── ClimbingStairs.java └── greedy │ ├── Test.java │ ├── question135 │ ├── PuKePai.java │ └── candy.java │ ├── question376 │ └── wiggleSubsequence.java │ └── question455 │ └── assigncookies.java ├── FibooCiles.java ├── MinStringSum.java ├── QueueAndStack ├── BFS.java └── question200 │ └── numberOfLslands.java ├── RundomNumArray.java ├── arrayAndString ├── Main.java └── question1 │ └── TwoSum.java ├── linkedList ├── MyLinkedList.java ├── question138 │ └── copylistwithrandompointer.java ├── question141 │ └── shileCleIs.java ├── question142 │ └── linkedlistcycleii.java ├── question160 │ └── IntersectionOfTwoLinkedLists.java ├── question19 │ └── removenthnodefromendoflist.java ├── question203 │ └── removelinkedlistelements.java ├── question206 │ └── reverseLinkedList.java ├── question21 │ └── mergeTwoSortedLists.java ├── question23 │ └── mergeksortedlists.java ├── question234 │ └── palindromelinkedlist.java ├── question86 │ └── partitionList.java └── question92 │ └── reverseLinkedList2.java └── utils ├── RandomListNode.java └── StopWatch.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .settings/ 2 | bin/ 3 | *.class 4 | .project 5 | .idea/ 6 | CoderEnterView.eml 7 | CoderEnterView.iml 8 | AlgorithmsSolutions.iml 9 | out/ 10 | -------------------------------------------------------------------------------- /src/me/zonglun/AutumnRecruitment/FireHome/Soldierqueue.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.AutumnRecruitment.FireHome; 2 | 3 | /** 4 | * 士兵队列 5 | * 6 | * @author : Administrator 7 | * @create 2018-09-09 15:26 8 | * @subject : 9 | * 一队士兵在操场上排成一列,士兵总数为n,每个士兵有各自的身高。 10 | *

11 | * 士兵列队完毕后,将军走到队列的最前面。因为身高不一,有些士兵可能被前面身高更高的挡住了,这样将军就看不到他们。 12 | * 将军能看到某个士兵当且仅当他的身高严格大于他前面的所有士兵。 13 | *

14 | * 将军发现这些士兵的身高为a1,a2,a3,...,an。 15 | * 而且他恰好能看到m个士兵。将军想知道一共有多少种可能的站队方式。两种站队方式不同当且仅当至少存在一个士兵,他站在了队列的不同位置。最后方案数可能很大,输出方案数除以1000000007后的余数。 16 | *

17 | *

18 | * 输入 19 | * 输入只有两行,第一行两个数n和m,(1<=m<=n<=1000)第二行有n个数,a1到an。(1<=ai<=1000000000) 20 | * 样例输入 21 | * 4 3 22 | *

23 | * 1 1 2 3 24 | * 输出 25 | * 输出一行,问题的答案。 26 | * 样例输出 27 | * 6 28 | */ 29 | public class Soldierqueue { 30 | 31 | public static void main(String[] args) { 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/me/zonglun/AutumnRecruitment/FireHome/XiaoMingsChessboard.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.AutumnRecruitment.FireHome; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * 小明的棋盘 7 | * 8 | * @author : Administrator 9 | * @create 2018-09-08 20:23 10 | * @subject : 11 | * 12 | * 题目描述 13 | * 14 | * 小明有天看到一个放满黑子和白子交替的大小为n*m的棋盘。然而小明只喜欢只有一种颜色的棋盘,即只有黑子或者白子。小明拥有超能力可以将一个里面的矩阵的棋子的颜色反转,但是他一天最多只能使用c次超能力。如果可以将所有棋子变成一种颜色,小明就会买这个棋盘,请问小明是否会买这个棋盘。 15 | * 16 | * 输入 17 | * 第一行一个整数 T(T≤10) 表示数据组数。 18 | * 19 | * 每组数据有一行, 三个正整数 n,m,c(1≤n,m,c≤1e9)。 20 | * 21 | * 22 | * 23 | * 样例输入 24 | * 2 25 | * 26 | * 1 2 1 27 | * 28 | * 2 2 1 29 | * 30 | * 输出 31 | * 如果小明买这个棋盘输出 "Yes" 否则输出 "No". 32 | * 33 | * 34 | * 35 | * 样例输出 36 | * 37 | * Yes 38 | * No 39 | * 40 | */ 41 | public class XiaoMingsChessboard { 42 | public static void main(String[] args) { 43 | Scanner scan = new Scanner(System.in); 44 | while (scan.hasNext()) { 45 | int t = scan.nextInt(); 46 | for (int i = 0; i < t; i++) { 47 | long n = scan.nextInt(); 48 | long m = scan.nextInt(); 49 | long c = scan.nextInt(); 50 | if (n /2 + m / 2 <= c) { 51 | System.out.println("Yes"); 52 | } else { 53 | System.out.println("No"); 54 | } 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/me/zonglun/AutumnRecruitment/FireHome/coding2019/makeFriends.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.AutumnRecruitment.FireHome.coding2019; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * 交友大会 7 | * 8 | * @author : Administrator 9 | * @create 2018-09-17 21:39 10 | * @subject : 11 | * 12 | * 13 | */ 14 | public class makeFriends { 15 | public static void main(String[] args) { 16 | Scanner sc = new Scanner(System.in); 17 | while (sc.hasNext()) { 18 | int n = sc.nextInt(); 19 | for (int i = 0; i < n; i++) { 20 | int m = sc.nextInt(); 21 | int k = sc.nextInt(); 22 | System.out.println(getN(m,k)); 23 | } 24 | } 25 | } 26 | 27 | private static int getN(int n, int m) { 28 | if (1 == n || 1 == m) { 29 | return 1; 30 | } 31 | if (n <= m) { 32 | return getN(n, n - 1) + 1; 33 | 34 | } else { 35 | return getN(n, m - 1) + getN(n - m, m); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/me/zonglun/AutumnRecruitment/FireHome/coding2019/samleString.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.AutumnRecruitment.FireHome.coding2019; 2 | 3 | import java.util.HashMap; 4 | import java.util.Scanner; 5 | 6 | /** 7 | * @author : Administrator 8 | * @create 2018-09-17 21:41 9 | * @subject : 10 | * 给出两个字符串a1a2a3...an和b1b2b3...bm, 11 | * 如果存在一种映射ai=f(bi),且如果ai≠bi,f(ai)≠f(bi),我们称这两个字符串同构。 12 | * 13 | * 输入 14 | * 输入第一行包含一个t,表示数据组数,t<=20. 15 | * 16 | * 对于每组数据,输入包含两行,每一行有一个字符串。 17 | * * 每个字符串的长度不超过10000,字符串全部由小写字母组成。 18 | * * 输出 19 | * 20 | * 对于每组数据输出一行,如果字符串同构,输出“Yes”,不同构则输出“No”。 21 | * 22 | 样例输入 23 | 2 24 | abac 25 | bcbd 26 | aba 27 | abc 28 | 样例输出 29 | Yes 30 | No 31 | * 32 | */ 33 | public class samleString { 34 | public static void main(String[] args) { 35 | Scanner sc = new Scanner(System.in); 36 | while (sc.hasNext()) { 37 | int n = sc.nextInt(); 38 | for (int j = 0; j < n; j++) { 39 | String s1 = sc.nextLine(); 40 | String s2 = sc.nextLine(); 41 | HashMap map = new HashMap<>(); 42 | for (int i = 0; i < s1.length(); i++) { 43 | char a = s1.charAt(i); 44 | char b = s2.charAt(i); 45 | if (map.containsKey(a)) { 46 | if (map.get(a).equals(b)) { 47 | continue; 48 | } else { 49 | System.out.println("No"); 50 | } 51 | } else { 52 | if (!map.containsValue(b)) { 53 | map.put(a, b); 54 | } else { 55 | System.out.println("No"); 56 | } 57 | } 58 | } 59 | System.out.println("Yes"); 60 | } 61 | } 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /src/me/zonglun/AutumnRecruitment/FireHome/learningSpelling.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.AutumnRecruitment.FireHome; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * 学打字 7 | * 8 | * @author : Administrator 9 | * @create 2018-09-08 21:07 10 | * @subject : 11 | * 小明同学刚刚学习打字,现在老师叫他输入一个英文字符串。小明发现,这个英文字符串只由大写和小写的英文字母构成。小明同学只会使用Caps Lock键来切换大小写输入。 12 | *

13 | * 最开始,大写锁定处于关闭状态,小明的电脑只能输入小写英文字母。当大写锁定关闭时,按一下Caps Lock键可以打开大写锁定,之后只能输入大写字母;当大写锁定打开时,按一下Caps Lock键可以关闭大写锁定,之后只能输入小写字母。 14 | *

15 | * 现在小明想知道输入这个字符串最少需要按键多少次。 16 | *

17 | * 输入 18 | * 输入只有一行,一个字符串,字符串中只有大写字母和小写字母,字符串长度不超过100000。 19 | * 样例输入 20 | * aAAbB 21 | * 输出 22 | * 输出一行,最少的按键次数。 23 | * 案例输出为8 24 | */ 25 | public class learningSpelling { 26 | 27 | public static void main(String[] args) { 28 | Scanner sc = new Scanner(System.in); 29 | String str = sc.next(); 30 | char[] chars = str.toCharArray(); 31 | int sumNum = 0; 32 | if (Character.isUpperCase(chars[0])) { 33 | sumNum = 1; 34 | } else { 35 | sumNum = 0; 36 | } 37 | for (int i = 0; i < chars.length -1; i++) { 38 | int j = i + 1; 39 | char c = chars[i], d = chars[j]; 40 | if (Character.isUpperCase(c) ^ Character.isUpperCase(d)) { 41 | sumNum ++; 42 | } 43 | } 44 | System.out.println(sumNum + chars.length); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/me/zonglun/BinaryTree/BinarySearch.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: BinarySearch 4 | * Author: Administrator 5 | * Date: 2017/11/7 0007 21:30 6 | * Description: BinarySearch 二分查找算法 7 | */ 8 | 9 | package me.zonglun.BinaryTree; 10 | 11 | import java.util.stream.IntStream; 12 | 13 | /** 14 | * 〈一句话功能简述〉
15 | * 〈BinarySearch 二分查找算法〉 16 | * 17 | * @author Administrator 18 | * @create 2017/11/7 0007 19 | * @since 1.0.0 20 | */ 21 | public class BinarySearch { 22 | private BinarySearch() { 23 | } 24 | 25 | // 二分查找法,在有序数组arr中,查找target (值不是索引) 26 | // 如果找到target,返回相应的索引index 27 | // 如果没有找到target,返回-1 28 | public static int find(Comparable[] arr, Comparable target) { 29 | // 在arr[l...r]之中查找target 30 | int l = 0, r = arr.length - 1; 31 | while (l <= r) { // l 和 r 为索引意味着当 l = r 的时候说明这时候 32 | // int mid = (l + r) / 2; 33 | int mid = l + (r - l) / 2; 34 | // 防止极端情况下的整形溢出,使用下面的逻辑求出mid 35 | if (arr[mid].compareTo(target) == 0) 36 | return mid; 37 | // 说明 target 在 mid 的左半部分, 此时在arr【l, mid - 1】之中再次循环 38 | if (arr[mid].compareTo(target) > 0) 39 | r = mid - 1; 40 | else // 说明 target 在 mid 的右半部分 ,此时在arr【mid + 1,r】 之中再次循环 41 | l = mid + 1; 42 | } 43 | return -1; 44 | } 45 | 46 | // 测试非递归的二分查找算法 47 | public static void main(String[] args) { 48 | 49 | int N = 1000000; 50 | Integer[] arr = new Integer[N]; 51 | for (int i = 0; i < N; i++) 52 | arr[i] = i; 53 | // 对于我们的待查找数组[0...N) 54 | // 对[0...N)区间的数值使用二分查找,最终结果应该就是数字本身 55 | // 对[N...2*N)区间的数值使用二分查找,因为这些数字不在arr中,结果为-1 56 | IntStream.range(0, 2 * N).forEach(i -> { 57 | int v = BinarySearch.find(arr, i); 58 | if (i < N) 59 | assert v == i; 60 | else 61 | assert v == -1; 62 | }); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/me/zonglun/BinaryTree/BinarySearch2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: BinarySearch2 4 | * Author: Administrator 5 | * Date: 2017/11/7 0007 21:51 6 | * Description: 递归版本的二分查找算法 7 | */ 8 | 9 | package me.zonglun.BinaryTree; 10 | 11 | import me.zonglun.Sort.InsertionSort; 12 | 13 | /** 14 | * 〈一句话功能简述〉
15 | * 〈递归版本的二分查找算法〉 16 | * 17 | * @author Administrator 18 | * @create 2017/11/7 0007 19 | * @since 1.0.0 20 | */ 21 | public class BinarySearch2 { 22 | private BinarySearch2() { 23 | } 24 | 25 | private static int find(Comparable[] arr, int l, int r, Comparable target) { 26 | if (l > r) 27 | return -1; 28 | int mid = l + (r - l) / 2; 29 | if (arr[mid].compareTo(target) == 0) 30 | return mid; 31 | else if (arr[mid].compareTo(target) < 0) 32 | return find(arr, mid + 1, r, target); 33 | else 34 | return find(arr, l, mid - 1, target); 35 | } 36 | 37 | public static int find(Comparable[] arr, Comparable target) { 38 | return find(arr, 0, arr.length - 1, target); 39 | } 40 | 41 | public static void main(String[] args) { 42 | Comparable[] arr = {4, 6, 2, 1, 7, 12, 78, 94, 123, 11}; 43 | InsertionSort.sort(arr); 44 | System.out.println(BinarySearch2.find(arr, 11)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/me/zonglun/BinaryTree/SeparateChainingHashST.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: SeparateChainingHashST 4 | * Author: Administrator 5 | * Date: 2017/11/12 0012 16:47 6 | * Description: 基于拉链法的散列表 7 | */ 8 | 9 | package me.zonglun.BinaryTree; 10 | 11 | 12 | /** 13 | * 〈一句话功能简述〉
14 | * 〈基于拉链法的散列表〉 15 | * 16 | * @author Administrator 17 | * @create 2017/11/12 0012 18 | * @since 1.0.0 19 | */ 20 | public class SeparateChainingHashST { 21 | private int N; // 键值对总数 22 | private int M; // 散列表大小 23 | private SequentialSearchST[] st; // 存放链表对象的数组 24 | 25 | public SeparateChainingHashST() { 26 | this(997); 27 | } 28 | 29 | private SeparateChainingHashST(int M) { 30 | // 创建M 条链表 31 | this.M = M; 32 | st = (SequentialSearchST[]) new SequentialSearchST[M]; 33 | for (int i = 0; i < M; i++) { 34 | st[i] = new SequentialSearchST(); 35 | } 36 | } 37 | /* 38 | 散列表的hash 函数 39 | * */ 40 | private int hash(Key key) { 41 | return (key.hashCode() & 0x7fffffff) % M; 42 | } 43 | 44 | public Value get(Key key) { 45 | return (Value) st[hash(key)].get(key); 46 | } 47 | 48 | public void put(Key key, Value val) { 49 | st[hash(key)].put(key, val); 50 | } 51 | 52 | public static void main(String[] args) { 53 | SeparateChainingHashST hashTable = new SeparateChainingHashST<>(); 54 | int N = 100; 55 | int M = 10000; 56 | for (int i = 0; i < N; i++) { 57 | Integer key = (int) (Math.random() * M); 58 | Integer value = (int)(Math.random() * M); 59 | hashTable.put(key, value); 60 | hashTable.put(345,345900); 61 | long startTime = System.currentTimeMillis(); 62 | int result = hashTable.get(345); 63 | long endTime = System.currentTimeMillis(); 64 | long time = endTime - startTime; 65 | System.out.println("the time is " + time + "result is " + result); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/me/zonglun/BinaryTree/SequentialSearchST.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: SequentialSearchST 4 | * Author: Administrator 5 | * Date: 2017/11/12 0012 16:51 6 | * Description: 链式查找链表的显示 7 | */ 8 | 9 | package me.zonglun.BinaryTree; 10 | 11 | 12 | import sun.misc.Queue; 13 | 14 | /** 15 | * 〈一句话功能简述〉
16 | * 〈链式查找链表的显示〉 17 | * 18 | * @author Administrator 19 | * @create 2017/11/12 0012 20 | * @since 1.0.0 21 | */ 22 | public class SequentialSearchST { 23 | private Node first; 24 | private int N = 0; 25 | 26 | private class Node { 27 | Key key; 28 | Value val; 29 | Node next; 30 | 31 | public Node(Key key, Value val, Node next) { 32 | this.key = key; 33 | this.val = val; 34 | this.next = next; 35 | } 36 | } 37 | 38 | public Value get(Key key) { 39 | for (Node x = first; x != null; x = x.next) { 40 | if (key.equals(x.key)) { 41 | return x.val; 42 | } 43 | } 44 | return null; 45 | } 46 | 47 | public void put(Key key, Value val) { 48 | for (Node x = first; x != null; x = x.next) { 49 | if (key.equals(x.key)) { 50 | x.val = val; 51 | return; 52 | } 53 | } 54 | first = new Node(key, val, first); 55 | N++; 56 | } 57 | 58 | 59 | public int size() { 60 | return N; 61 | } 62 | 63 | public void delete(Key key) { 64 | first = delete(first, key); 65 | } 66 | 67 | private Node delete(Node x, Key key) { 68 | if (x == null) { 69 | return null; 70 | } 71 | if (x.key.equals(key)) { 72 | N--; 73 | return x.next; 74 | } 75 | x.next = delete(x.next, key); 76 | return x; 77 | } 78 | 79 | public Iterable keys() { 80 | Queue queue = new Queue<>(); 81 | for (Node x = first; x != null; x = x.next) { 82 | queue.enqueue(x.key); 83 | } 84 | return (Iterable) queue; 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /src/me/zonglun/BinaryTree/TestBinarySearch.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: TestBinarySearch 4 | * Author: Administrator 5 | * Date: 2017/11/8 0008 10:38 6 | * Description: 比较非递归和递归写法的二分查找的效率 7 | */ 8 | 9 | package me.zonglun.BinaryTree; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈 比较非递归和递归写法的二分查找的效率〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/8 0008 17 | * @since 1.0.0 18 | */ 19 | public class TestBinarySearch { 20 | 21 | private TestBinarySearch() { 22 | } 23 | 24 | public static void main(String[] args) { 25 | 26 | int N = 1000000; 27 | Integer[] arr = new Integer[N]; 28 | for (int i = 0; i < N; i++) 29 | arr[i] = i; 30 | 31 | 32 | // 测试非递归二分查找法 33 | long startTime = System.currentTimeMillis(); 34 | 35 | // 对于我们的待查找数组[0...N) 36 | // 对[0...N)区间的数值使用二分查找,最终结果应该就是数字本身 37 | // 对[N...2*N)区间的数值使用二分查找,因为这些数字不在arr中,结果为-1 38 | for (int i = 0; i < 2 * N; i++) { 39 | int v = BinarySearch.find(arr, i); 40 | if (i < N) 41 | assert v == i; 42 | else 43 | assert v == -1; 44 | } 45 | long endTime = System.currentTimeMillis(); 46 | 47 | System.out.println("Binary Search (Without Recursion): " + (endTime - startTime) + "ms"); 48 | 49 | 50 | // 测试递归的二分查找法 51 | startTime = System.currentTimeMillis(); 52 | 53 | // 对于我们的待查找数组[0...N) 54 | // 对[0...N)区间的数值使用二分查找,最终结果应该就是数字本身 55 | // 对[N...2*N)区间的数值使用二分查找,因为这些数字不在arr中,结果为-1 56 | for (int i = 0; i < 2 * N; i++) { 57 | int v = BinarySearch2.find(arr, i); 58 | if (i < N) 59 | assert v == i; 60 | else 61 | assert v == -1; 62 | } 63 | endTime = System.currentTimeMillis(); 64 | System.out.println("Binary Search (With Recursion): " + (endTime - startTime) + "ms"); 65 | 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/me/zonglun/BinaryTree/TestRedBlackBST.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: TesTRedBlackBST 4 | * Author: Administrator 5 | * Date: 2017/11/12 0012 16:17 6 | * Description: 测试红黑树 7 | */ 8 | 9 | package me.zonglun.BinaryTree; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈测试红黑树〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/12 0012 17 | * @since 1.0.0 18 | */ 19 | public class TestRedBlackBST { 20 | public static void main(String[] args) { 21 | BlackRedBST Rb = new BlackRedBST<>(); 22 | int N = 10; 23 | int M = 100; 24 | for (int i = 0; i < N; i++) { 25 | Integer key = (int) (Math.random() * M); 26 | Rb.put(key, key); 27 | System.out.print(key + " "); 28 | } 29 | System.out.println(); 30 | 31 | // 测试二分搜索树的size() 32 | System.out.println("size: " + Rb.size()); 33 | System.out.println(); 34 | System.out.println(Rb.max()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/me/zonglun/Graph/Components.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: Components 4 | * Author: Administrator 5 | * Date: 2017/11/14 0014 10:53 6 | * Description: // 求无权图的联通分量 7 | */ 8 | 9 | package me.zonglun.Graph; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈// 求无权图的联通分量〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/14 0014 17 | * @since 1.0.0 18 | */ 19 | public class Components { 20 | Graph G; // 图的引用 21 | private boolean[] visited; // 记录dfs的过程中节点是否被访问 22 | private int ccount; // 记录联通分量个数 23 | private int[] id; // 每个节点所对应的联通分量标记,相链接的ID的大小值是相同的 24 | 25 | public Components(Graph graph) { 26 | G = graph; 27 | visited = new boolean[G.V()]; // visited 开辟新的空间,大小为图里面的节点个数 28 | id = new int[G.V()]; // 在 ID 里面开辟新的空间,大小为图里面的节点个数 29 | ccount = 0; 30 | for (int i = 0; i < G.V(); i++) { 31 | visited[i] = false; // 初始化应该节点都没有被访问过 32 | id[i] = -1; // 初始化的时候使得所有的元素的值为-1 33 | } 34 | 35 | for (int i = 0; i < G.V(); i++) { 36 | if (!visited[i]) { 37 | dfs(i); // 图的深度优先遍历- 38 | ccount++; 39 | } 40 | } 41 | } 42 | 43 | int getCount() { 44 | return ccount; 45 | } 46 | 47 | boolean isConnected(int v, int w) { 48 | assert v >= 0 && v < G.V(); 49 | assert w >= 0 && w < G.V(); 50 | return id[v] == id[w]; 51 | } 52 | 53 | // 图的深度优先遍历----递归实现 54 | private void dfs(int v) { 55 | visited[v] = true; 56 | id[v] = ccount; 57 | 58 | for (int i : G.adj(v)) { 59 | if (!visited[i]) // 如果已经被访问过了则继续循环 60 | dfs(i); // 递归运行i 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/me/zonglun/Graph/DenseGraph.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: DenseGraph 4 | * Author: Administrator 5 | * Date: 2017/11/12 0012 21:42 6 | * Description: 稠密图Java展示 7 | */ 8 | 9 | package me.zonglun.Graph; 10 | 11 | import java.util.Vector; 12 | 13 | /** 14 | * 〈一句话功能简述〉
15 | * 〈稠密图Java展示〉 16 | * 17 | * @author Administrator 18 | * @create 2017/11/12 0012 19 | * @since 1.0.0 20 | */ 21 | public class DenseGraph implements Graph { 22 | 23 | private int n; // 节点数 24 | private int m; // 边数 25 | private boolean directed; // 是否为有向图 26 | // 边的链接情况--用相邻界矩阵来表示 27 | private boolean[][] g; 28 | 29 | public DenseGraph(int n, boolean directed) { 30 | assert n > 0; 31 | this.n = n; 32 | this.m = 0; 33 | this.directed = directed; 34 | // 刚开始是创建新的 n*n阶的矩阵,值都为false 35 | this.g = new boolean[n][n]; 36 | } 37 | 38 | @Override 39 | public int V() { 40 | return n; 41 | } // 返回节点的个数 42 | 43 | @Override 44 | public int E() { 45 | return m; 46 | } // 返回图中边的个数 47 | 48 | @Override 49 | public void addEdge(int v, int w) { 50 | assert v >= 0 && v < n; 51 | assert w >= 0 && w < n; 52 | if (hasEdge(v, w)) // 判断是否图中已经有了相关的图,如有则返回 53 | return; 54 | g[v][w] = true; 55 | if (!directed) // 如果不是无向图 56 | g[w][v] = true; 57 | m++; 58 | } 59 | 60 | @Override 61 | public boolean hasEdge(int v, int w) { 62 | assert v >= 0 && v < n; 63 | assert w >= 0 && w < n; 64 | return g[v][w]; 65 | } 66 | 67 | @Override 68 | public void show() { 69 | for (int i = 0; i < n; i++) { 70 | for (int j = 0; j < n; j++) 71 | System.out.print(g[i][j] + "\t"); 72 | System.out.println(); 73 | } 74 | } 75 | 76 | // 返回图中一个顶点的所有邻边 77 | // 由于java使用引用机制,返回一个Vector不会带来额外开销, 78 | @Override 79 | public Iterable adj(int v) { 80 | assert v >= 0 && v < n; 81 | Vector adjv = new Vector<>(); 82 | for (int i = 0; i < n; i++) { 83 | if (g[v][i]) { 84 | adjv.add(i); 85 | } 86 | } 87 | return adjv; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/me/zonglun/Graph/Edge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: Edge 4 | * Author: Administrator 5 | * Date: 2017/11/15 0015 19:09 6 | * Description: 对有权图的类的边进行封装 7 | */ 8 | 9 | package me.zonglun.Graph; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈对有权图的类的边进行封装〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/15 0015 17 | * @since 1.0.0 18 | */ 19 | public class Edge implements Comparable { 20 | 21 | private int a, b; 22 | private Weight weight; 23 | 24 | public Edge(int a, int b, Weight weight) { 25 | this.a = a; 26 | this.b = b; 27 | this.weight = weight; 28 | } 29 | 30 | public Edge(Edge e) { 31 | this.a = e.a; 32 | this.b = e.b; 33 | this.weight = e.weight; 34 | } 35 | 36 | public int V() { 37 | return a; 38 | } 39 | 40 | // 返回第二个元素 41 | public int W() { 42 | return b; 43 | } 44 | 45 | public Weight wt() { 46 | return weight; 47 | } 48 | 49 | public int other(int x) { 50 | assert x == a || x == b; 51 | return x == a ? b : a; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return "" + a + "-" + b + ": " + weight; 57 | } 58 | 59 | @Override 60 | public int compareTo( Edge that) { 61 | if (weight.compareTo(that.weight) < 0) 62 | return -1; 63 | else if (weight.compareTo(that.weight) > 0) 64 | return +1; 65 | else 66 | return 0; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/me/zonglun/Graph/Graph.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: Graph 4 | * Author: Administrator 5 | * Date: 2017/11/13 0013 20:36 6 | * Description: Graph 图的接口 7 | */ 8 | 9 | package me.zonglun.Graph; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈Graph 图的接口〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/13 0013 17 | * @since 1.0.0 18 | */ 19 | public interface Graph { 20 | int V(); 21 | int E(); 22 | void addEdge(int v, int w); 23 | boolean hasEdge(int v, int w); 24 | void show(); 25 | Iterable adj(int v); 26 | } 27 | -------------------------------------------------------------------------------- /src/me/zonglun/Graph/Path.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: Path 4 | * Author: Administrator 5 | * Date: 2017/11/15 0015 10:01 6 | * Description: Path 图的路径的类 7 | */ 8 | 9 | package me.zonglun.Graph; 10 | 11 | 12 | import java.util.Stack; 13 | import java.util.Vector; 14 | 15 | /** 16 | * 〈一句话功能简述〉
17 | * 〈Path 图的路径的类〉 18 | * 19 | * @author Administrator 20 | * @create 2017/11/15 0015 21 | * @since 1.0.0 22 | */ 23 | public class Path { 24 | private Graph G; // 图的引用 25 | private int s; // 起始点 26 | private boolean[] visited; // 记录dfs的过程中节点是否被访问 27 | private int[] from; // 记录路径, from[i]表示查找的路径上i的上一个节点 28 | 29 | private void dfs(int v) { 30 | visited[v] = true; 31 | for (int i : G.adj(v)) { 32 | if (!visited[i]) { 33 | from[i] = v; // 没被访问的节点的值记为v, 存贮在from【i】的数组之中。 34 | dfs(i); 35 | } 36 | } 37 | } 38 | 39 | public Path(Graph graph, int s) { 40 | G = graph; 41 | assert s >= 0 && s < G.V(); 42 | visited = new boolean[G.V()]; 43 | from = new int[G.V()]; 44 | for (int i = 0; i < G.V(); i++) { 45 | visited[i] = false; 46 | from[i] = -1; 47 | } 48 | this.s = s; 49 | // 寻路算法 50 | dfs(s); 51 | } 52 | 53 | // 查询从s点到w点是否有路径 54 | boolean hasPath(int w) { 55 | assert w >= 0 && w < G.V(); 56 | return visited[w]; 57 | } 58 | 59 | Vector path(int w) { 60 | assert hasPath(w); 61 | Stack s = new Stack<>(); 62 | // 通过from数组逆向查找到从s到w的路径, 存放到栈中 63 | int p = w; 64 | while (p != -1) { 65 | s.push(p); 66 | p = from[p]; 67 | } 68 | 69 | // 从栈中依次取出元素, 获得顺序的从s到w的路径 70 | Vector res = new Vector(); 71 | while (!s.isEmpty()) 72 | res.add(s.pop()); 73 | return res; 74 | } 75 | 76 | void showPath(int w) { 77 | assert hasPath(w); 78 | Vector vec = path(w); 79 | for (int i = 0; i < vec.size(); i++) { 80 | System.out.print(vec.elementAt(i)); 81 | if (i == vec.size() - 1) 82 | System.out.println(); 83 | else 84 | System.out.print(" -> "); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/me/zonglun/Graph/ReadGraph.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: ReadGraph 4 | * Author: Administrator 5 | * Date: 2017/11/13 0013 20:53 6 | * Description: ReadGraph 7 | */ 8 | 9 | package me.zonglun.Graph; 10 | 11 | import java.io.*; 12 | import java.util.InputMismatchException; 13 | import java.util.Locale; 14 | import java.util.NoSuchElementException; 15 | import java.util.Scanner; 16 | 17 | /** 18 | * 〈一句话功能简述〉
19 | * 〈ReadGraph 〉 20 | * 21 | * @author Administrator 22 | * @create 2017/11/13 0013 23 | * @since 1.0.0 24 | */ 25 | public class ReadGraph { 26 | 27 | private Scanner scanner; 28 | 29 | public ReadGraph(Graph graph, String filename){ 30 | 31 | readFile(filename); 32 | 33 | try { 34 | int V = scanner.nextInt(); 35 | if (V < 0) 36 | throw new IllegalArgumentException("number of vertices in a Graph must be nonnegative"); 37 | assert V == graph.V(); 38 | 39 | int E = scanner.nextInt(); 40 | if (E < 0) 41 | throw new IllegalArgumentException("number of edges in a Graph must be nonnegative"); 42 | 43 | for (int i = 0; i < E; i++) { 44 | int v = scanner.nextInt(); 45 | int w = scanner.nextInt(); 46 | assert v >= 0 && v < V; 47 | assert w >= 0 && w < V; 48 | graph.addEdge(v, w); 49 | } 50 | } 51 | catch (InputMismatchException e) { 52 | String token = scanner.next(); 53 | throw new InputMismatchException("attempts to read an 'int' value from input stream, but the next token is \"" + token + "\""); 54 | } 55 | catch (NoSuchElementException e) { 56 | throw new NoSuchElementException("attempts to read an 'int' value from input stream, but there are no more tokens available"); 57 | } 58 | } 59 | 60 | private void readFile(String filename){ 61 | assert filename != null; 62 | try { 63 | File file = new File(filename); 64 | if (file.exists()) { 65 | FileInputStream fis = new FileInputStream(file); 66 | scanner = new Scanner(new BufferedInputStream(fis), "UTF-8"); 67 | scanner.useLocale(Locale.ENGLISH); 68 | } 69 | else 70 | throw new IllegalArgumentException(filename + "doesn't exist."); 71 | } 72 | catch (IOException ioe) { 73 | throw new IllegalArgumentException("Could not open " + filename, ioe); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/me/zonglun/Graph/SparseGraph.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: SparseGraph 4 | * Author: Administrator 5 | * Date: 2017/11/12 0012 21:59 6 | * Description: SparseGraph 稀疏图利用邻接表来实现 7 | */ 8 | 9 | package me.zonglun.Graph; 10 | 11 | import java.util.Vector; 12 | 13 | /** 14 | * 〈一句话功能简述〉
15 | * 〈SparseGraph 稀疏图利用邻接表来实现〉 16 | * 17 | * @author Administrator 18 | * @create 2017/11/12 0012 19 | * @since 1.0.0 20 | */ 21 | public class SparseGraph implements Graph{ 22 | private int n; // 节点数 23 | private int m; // 边数 24 | private boolean directed; // 是否为有向图 25 | private Vector[] g; // 图的具体数据 26 | 27 | public SparseGraph(int n, boolean directed) { 28 | assert n > 0; 29 | this.n = n; 30 | this.m = 0; // 初始化没有任何边 31 | this.directed = directed; 32 | // g初始化为n个空的vector, 表示每一个g[i]都为空, 即没有任和边 33 | this.g = new Vector[n]; 34 | for (int i = 0; i < n; i++) { 35 | g[i] = new Vector<>(); 36 | } 37 | } 38 | 39 | // 返回节点的个数 40 | public int V() { 41 | return n; 42 | } 43 | 44 | // 返回图中边的个数 45 | public int E() { 46 | return m; 47 | } 48 | 49 | public void addEdge(int v, int w) { 50 | assert v >= 0 && v < n; 51 | assert w >= 0 && w < n; 52 | g[v].add(w); 53 | if (!directed) // 如果为无向图,反向也要添加 54 | g[w].add(v); 55 | m++; 56 | } 57 | 58 | public boolean hasEdge(int v, int w) { 59 | assert v >= 0 && v < n; 60 | assert w >= 0 && w < n; 61 | for (int i = 0; i < g[v].size(); i++) { 62 | if (g[v].elementAt(i) == w) 63 | return true; 64 | } 65 | return false; 66 | } 67 | 68 | @Override 69 | public void show() { 70 | for (int i = 0; i < n; i++) { 71 | System.out.print("vertex" + i +"\t"); 72 | for (int j = 0; j < g[i].size(); j++) { 73 | System.out.print(g[i].elementAt(j) + "\t"); 74 | } 75 | System.out.println(); 76 | } 77 | } 78 | 79 | // 返回图中一个顶点的所有邻边 80 | public Iterable adj(int v) { 81 | assert v >= 0 && v < n; 82 | return g[v]; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/me/zonglun/Graph/SparseWeightedGraph.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: SparseWeightedGraph 4 | * Author: Administrator 5 | * Date: 2017/11/15 0015 19:48 6 | * Description: SparseWeightedGraph 7 | */ 8 | 9 | package me.zonglun.Graph; 10 | 11 | import java.util.Vector; 12 | 13 | /** 14 | * 〈一句话功能简述〉
15 | * 〈SparseWeightedGraph〉 16 | * 17 | * @author Administrator 18 | * @create 2017/11/15 0015 19 | * @since 1.0.0 20 | */ 21 | public class SparseWeightedGraph implements WeightedGraph { 22 | 23 | private int n; // 节点数 24 | private int m; // 边数 25 | private boolean directed; // 是否为有向图 26 | private Vector>[] g; // 图的具体数据 27 | 28 | // 初始化的过程 29 | public SparseWeightedGraph(int n, boolean directed) { 30 | this.n = n; 31 | this.m = 0; 32 | this.directed = directed; 33 | g = (Vector>[]) new Vector[n]; 34 | for (int i = 0; i < n; i++) { 35 | g[i] = new Vector<>(); 36 | } 37 | } 38 | 39 | @Override 40 | public int V() { 41 | return n; 42 | } 43 | 44 | @Override 45 | public int E() { 46 | return m; 47 | } 48 | 49 | @Override 50 | // 向图中添加一个边, 权值为weight 51 | public void addEdge(Edge e){ 52 | 53 | assert e.V() >= 0 && e.V() < n ; 54 | assert e.W() >= 0 && e.W() < n ; 55 | 56 | // 注意, 由于在邻接表的情况, 查找是否有重边需要遍历整个链表 57 | // 我们的程序允许重边的出现 58 | 59 | g[e.V()].add(new Edge(e)); 60 | if( e.V() != e.W() && !directed ) 61 | g[e.W()].add(new Edge(e.W(), e.V(), e.wt())); 62 | m ++; 63 | } 64 | 65 | @Override 66 | public boolean hasEdge(int v, int w) { 67 | assert v >= 0 && v < n ; 68 | assert w >= 0 && w < n ; 69 | 70 | for( int i = 0 ; i < g[v].size() ; i ++ ) 71 | if( g[v].elementAt(i).other(v) == w ) 72 | return true; 73 | return false; 74 | } 75 | 76 | @Override 77 | public void show() { 78 | for( int i = 0 ; i < n ; i ++ ){ 79 | System.out.print("vertex " + i + ":\t"); 80 | for( int j = 0 ; j < g[i].size() ; j ++ ){ 81 | Edge e = g[i].elementAt(j); 82 | System.out.print( "( to:" + e.other(i) + ",wt:" + e.wt() + ")\t"); 83 | } 84 | System.out.println(); 85 | } 86 | } 87 | 88 | @Override 89 | public Iterable> adj(int v) { 90 | assert v >= 0 && v < n; 91 | return g[v]; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/me/zonglun/Graph/TestGraph.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: TestGraph 4 | * Author: Administrator 5 | * Date: 2017/11/13 0013 20:59 6 | * Description: nonnegative 7 | */ 8 | 9 | package me.zonglun.Graph; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈测试图例子〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/13 0013 17 | * @since 1.0.0 18 | */ 19 | public class TestGraph { 20 | public static void main(String[] args) { 21 | String fileName = "E:\\project\\java-Project\\AlgorithmsSolutions\\src\\me\\zonglun\\Graph\\testG1.txt"; 22 | SparseGraph g1 = new SparseGraph(13, false); 23 | ReadGraph readGraph1 = new ReadGraph(g1, fileName); 24 | Components components1 = new Components(g1); 25 | System.out.println("test G1 in SparseGraph: " + components1.getCount()); 26 | // g1.show(); 27 | System.out.println(); 28 | 29 | DenseGraph g2 = new DenseGraph(13, false); 30 | ReadGraph readGraph2 = new ReadGraph(g2, fileName); 31 | Components components2 = new Components(g2); 32 | System.out.println("test G1 in Dense Graph:" + components2.getCount()); 33 | // g2.show(); 34 | System.out.println(); 35 | 36 | // 使用两种图的存储方式读取testG2.txt文件 37 | String filename2 = "E:\\project\\java-Project\\AlgorithmsSolutions\\src\\me\\zonglun\\Graph\\testG2.txt"; 38 | SparseGraph g3 = new SparseGraph(6, false); 39 | ReadGraph readGraph3 = new ReadGraph(g3, filename2); 40 | Components components3 = new Components(g3); 41 | System.out.println("test G2 in Sparse Graph:" + components3.getCount()); 42 | // g3.show(); 43 | 44 | System.out.println(); 45 | 46 | DenseGraph g4 = new DenseGraph(6, false); 47 | ReadGraph readGraph4 = new ReadGraph(g4, filename2); 48 | System.out.println("test G2 in Dense Graph:"); 49 | g4.show(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/me/zonglun/Graph/TestPath.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: TestPath 4 | * Author: Administrator 5 | * Date: 2017/11/15 0015 10:35 6 | * Description: 7 | */ 8 | 9 | package me.zonglun.Graph; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/15 0015 17 | * @since 1.0.0 18 | */ 19 | public class TestPath { 20 | public static void main(String[] args) { 21 | String filename = "E:\\project\\java-Project\\AlgorithmsSolutions\\src\\me\\zonglun\\Graph\\testG.txt"; 22 | SparseGraph g = new SparseGraph(7, false); 23 | ReadGraph readGraph = new ReadGraph(g, filename); 24 | g.show(); 25 | System.out.println(); 26 | 27 | Path path = new Path(g, 0); 28 | System.out.println("DFS for path from 0 to 6: "); 29 | path.showPath(6); 30 | ShortestPath spath = new ShortestPath(g,0); 31 | System.out.println("BFS for path from 0 to 6: "); 32 | spath.showPath(6); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/me/zonglun/Graph/TestWeightedGraph.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: TestWeightedGraph 4 | * Author: Administrator 5 | * Date: 2017/11/15 0015 20:32 6 | * Description: TestWeightedGraph 7 | */ 8 | 9 | package me.zonglun.Graph; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈TestWeightedGraph〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/15 0015 17 | * @since 1.0.0 18 | */ 19 | public class TestWeightedGraph { 20 | public static void main(String[] args) { 21 | 22 | // 使用两种图的存储方式读取testG1.txt文件 23 | String filename = "E:\\project\\java-Project\\AlgorithmsSolutions\\src\\me\\zonglun\\Graph\\testG1.txt"; 24 | SparseWeightedGraph g1 = new SparseWeightedGraph<>(8, false); 25 | ReadWeightedGraph readGraph1 = new ReadWeightedGraph(g1, filename); 26 | System.out.println("test G1 in Sparse Weighted Graph:"); 27 | g1.show(); 28 | 29 | System.out.println(); 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/me/zonglun/Graph/WeightedGraph.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: WeightedGraph 4 | * Author: Administrator 5 | * Date: 2017/11/15 0015 19:46 6 | * Description: WeightedGraph抽象接口 7 | */ 8 | 9 | package me.zonglun.Graph; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈WeightedGraph抽象接口〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/15 0015 17 | * @since 1.0.0 18 | */ 19 | public interface WeightedGraph { 20 | int V(); 21 | 22 | int E(); 23 | 24 | void addEdge(Edge e); 25 | 26 | boolean hasEdge(int v, int w); 27 | 28 | void show(); 29 | 30 | Iterable> adj(int v); 31 | } 32 | -------------------------------------------------------------------------------- /src/me/zonglun/Graph/testG.txt: -------------------------------------------------------------------------------- 1 | 7 8 2 | 0 1 3 | 0 2 4 | 0 5 5 | 0 6 6 | 3 4 7 | 3 5 8 | 4 5 9 | 4 6 10 | -------------------------------------------------------------------------------- /src/me/zonglun/Graph/testG1.txt: -------------------------------------------------------------------------------- 1 | 13 13 2 | 0 5 3 | 4 3 4 | 0 1 5 | 9 12 6 | 6 4 7 | 5 4 8 | 0 2 9 | 11 12 10 | 9 10 11 | 0 6 12 | 7 8 13 | 9 11 14 | 5 3 15 | -------------------------------------------------------------------------------- /src/me/zonglun/Graph/testG2.txt: -------------------------------------------------------------------------------- 1 | 6 8 2 | 0 1 3 | 0 2 4 | 0 5 5 | 1 2 6 | 1 3 7 | 1 4 8 | 3 4 9 | 3 5 10 | -------------------------------------------------------------------------------- /src/me/zonglun/Sort/BubbleSort.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.Sort; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * 〈一句话功能简述〉
7 | * 1. 冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。 8 | * 走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。 9 | * 这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。 10 | * <1>.比较相邻的元素。如果第一个比第二个大,就交换它们两个; 11 | * <2>.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数; 12 | * <3>.针对所有的元素重复以上的步骤,除了最后一个; 13 | * <4>.重复步骤1~3,直到排序完成。 14 | * you can see more detail in https://blog.zonglun.me/?p=140 15 | * 平均时间复杂度为o(N*2) 16 | * 17 | * @author Administrator 18 | * @create 2017/11/3 0003 19 | * @since 1.0.0 20 | */ 21 | public class BubbleSort { 22 | private BubbleSort() {} 23 | 24 | public static void sort(Comparable[] arr) { 25 | int n = arr.length; 26 | int newn; 27 | do { 28 | newn = 0; 29 | for (int i = 1; i < n; i++) { 30 | if (arr[i -1].compareTo( arr[i]) > 0) { 31 | swap(arr , i - 1, i); 32 | // 记录最后一次的交换位置,在此之后的元素在下一轮扫描中均不考虑 33 | newn = i; 34 | } 35 | } 36 | n = newn; 37 | }while (newn > 0); 38 | } 39 | 40 | private static void swap(Object[] arr, int i, int j) { 41 | Object t = arr[i]; 42 | arr[i] = arr[j]; 43 | arr[j] = t; 44 | } 45 | 46 | public static void main(String[] args) { 47 | int N = 20000; 48 | 49 | // 测试1 一般测试 50 | System.out.println("Test for random array, size = " + N + " , random range [0, " + N + "]"); 51 | 52 | Integer[] arr1 = SortTestHelper.generateRandomArray(N, 0, N); 53 | Integer[] arr2 = Arrays.copyOf(arr1, arr1.length); 54 | Integer[] arr3 = Arrays.copyOf(arr1, arr1.length); 55 | 56 | SortTestHelper.testSort("me.zonglun.Sort.SelectionSort", arr1); 57 | SortTestHelper.testSort("me.zonglun.Sort.InsertionSort", arr2); 58 | SortTestHelper.testSort("me.zonglun.Sort.BubbleSort", arr3); 59 | 60 | System.out.println(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/me/zonglun/Sort/GetThNumber.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: GetThNumber 4 | * Author: Administrator 5 | * Date: 2017/11/4 0004 22:18 6 | * Description: 取出数组中第N大的元素 7 | */ 8 | 9 | package me.zonglun.Sort; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈取出数组中第N大的元素〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/4 0004 17 | * @since 1.0.0 18 | * @subject 取出一个数组中第N大的元素 19 | */ 20 | public class GetThNumber { 21 | private GetThNumber() {} 22 | 23 | // 对arr[l...r]部分进行partition操作 24 | // 返回p, 使得arr[l...p-1] < arr[p] ; arr[p+1...r] > arr[p] 25 | // partition 过程, 和快排的partition一样 26 | // 思考: 双路快排和三路快排的思想能不能用在selection算法中? :) 27 | private static int partition(Comparable[] arr, int l, int r){ 28 | 29 | // 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivot 30 | swap( arr, l , (int)(Math.random()*(r-l+1))+l ); 31 | 32 | Comparable v = arr[l]; 33 | 34 | int j = l; // arr[l+1...j] < v ; arr[j+1...i) > v 35 | for( int i = l + 1 ; i <= r ; i ++ ) 36 | if( arr[i].compareTo(v) < 0 ){ 37 | j ++; 38 | swap(arr, j, i); 39 | } 40 | 41 | swap(arr, l, j); 42 | 43 | return j; 44 | } 45 | 46 | // 求出nums[l...r]范围里第k小的数 47 | private static Comparable solve(Comparable[] nums, int l, int r, int k){ 48 | 49 | if( l == r ) 50 | return nums[l]; 51 | 52 | // partition之后, nums[p]的正确位置就在索引p上 53 | int p = partition(nums, l, r); 54 | 55 | if( k == p ) // 如果 k == p, 直接返回nums[p] 56 | return nums[p]; 57 | else if( k < p ) // 如果 k < p, 只需要在nums[l...p-1]中找第k小元素即可 58 | return solve( nums, l, p-1, k); 59 | else // 如果 k > p, 则需要在nums[p+1...r]中找第k小元素 60 | return solve( nums, p+1, r, k ); 61 | } 62 | // 寻找nums数组中第k小的元素 63 | public static Comparable solve(Comparable nums[], int n, int k) { 64 | 65 | assert k >= 0 && k < n; 66 | return solve(nums, 0, n - 1, k); 67 | } 68 | 69 | private static void swap(Object[] arr, int i, int j) { 70 | Object t = arr[i]; 71 | arr[i] = arr[j]; 72 | arr[j] = t; 73 | } 74 | 75 | // 测试 Selection 76 | public static void main(String[] args) { 77 | 78 | // 生成一个大小为n, 包含0...n-1这n个元素的随机数组arr 79 | int N = 10000; 80 | Integer[] arr = SortTestHelper.generateOrderedArray(N); 81 | 82 | // 验证selection算法, 对arr数组求第i小元素, 应该为i 83 | for( int i = 0 ; i < N ; i ++ ){ 84 | System.out.println("test " + i + " complete."); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/me/zonglun/Sort/HeapSort1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: HeapSort1 4 | * Author: Administrator 5 | * Date: 2017/11/6 0006 17:33 6 | * Description: 堆排序的第一个版本 7 | */ 8 | 9 | package me.zonglun.Sort; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈堆排序的第一个版本〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/6 0006 17 | * @since 1.0.0 18 | */ 19 | public class HeapSort1 { 20 | private HeapSort1() { 21 | } 22 | 23 | public static void sort(Comparable[] arr) { 24 | int n = arr.length; 25 | MaxHeap maxHeap = new MaxHeap<>(n); 26 | for (Comparable i : arr) { // 最大堆之中放入所有的元素 27 | maxHeap.insert(i); 28 | } 29 | for (int i = n - 1; i >= 0; i--) { // 从后往前面便利以或者排序是从小到大 30 | arr[i] = maxHeap.extractMac(); 31 | } 32 | } 33 | 34 | // 测试 HeapSort1 35 | public static void main(String[] args) { 36 | 37 | int N = 1000000; 38 | Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000); 39 | SortTestHelper.testSort("me.zonglun.Sort.HeapSort1", arr); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/me/zonglun/Sort/HeapSort2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: HeapSort2 4 | * Author: Administrator 5 | * Date: 2017/11/6 0006 19:59 6 | * Description: HeapSort2 7 | */ 8 | 9 | package me.zonglun.Sort; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈HeapSort2 〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/6 0006 17 | * @since 1.0.0 18 | */ 19 | public class HeapSort2 { 20 | 21 | private HeapSort2() {} 22 | 23 | // 对整个arr数组使用HeapSort2排序 24 | // HeapSort2, 借助我们的heapify过程创建堆 25 | // 此时, 创建堆的过程时间复杂度为O(n), 将所有元素依次从堆中取出来, 实践复杂度为O(nlogn) 26 | // 堆排序的总体时间复杂度依然是O(nlogn), 但是比HeapSort1性能更优, 因为创建堆的性能更优 27 | public static void sort(Comparable[] arr){ 28 | 29 | int n = arr.length; 30 | MaxHeap maxHeap = new MaxHeap(arr); 31 | for( int i = n-1 ; i >= 0 ; i -- ) 32 | arr[i] = maxHeap.extractMac(); 33 | } 34 | 35 | // 测试 HeapSort2 36 | public static void main(String[] args) { 37 | 38 | int N = 1000000; 39 | Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000); 40 | SortTestHelper.testSort("me.zonglun.Sort.HeapSort2", arr); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/me/zonglun/Sort/HeapSort3.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: HeapSort3 4 | * Author: Administrator 5 | * Date: 2017/11/6 0006 20:08 6 | * Description: HeapSort3 原地堆排序 7 | */ 8 | 9 | package me.zonglun.Sort; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈HeapSort3 原地堆排序〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/6 0006 17 | * @since 1.0.0 18 | */ 19 | public class HeapSort3 { 20 | private HeapSort3() { 21 | } 22 | 23 | // 交换堆中索引为i和j的两个元素 24 | private static void swap(Object[] arr, int i, int j) { 25 | Object t = arr[i]; 26 | arr[i] = arr[j]; 27 | arr[j] = t; 28 | } 29 | 30 | // 原始的shiftDown过程 31 | private static void shiftDown(Comparable[] arr, int n, int k) { 32 | 33 | while (2 * k + 1 < n) { // 左孩子不越界 34 | int j = 2 * k + 1; // 初始值为 2k + 1; 35 | if (j + 1 < n && arr[j + 1].compareTo(arr[j]) > 0) 36 | j += 1; 37 | 38 | if (arr[k].compareTo(arr[j]) >= 0) break; 39 | 40 | swap(arr, k, j); 41 | k = j; 42 | } 43 | } 44 | 45 | // 优化的shiftDown过程, 使用赋值的方式取代不断的swap, 46 | // 该优化思想和我们之前对插入排序进行优化的思路是一致的 47 | private static void shiftDown2(Comparable[] arr, int n, int k) { 48 | 49 | Comparable e = arr[k]; 50 | while (2 * k + 1 < n) { 51 | int j = 2 * k + 1; 52 | if (j + 1 < n && arr[j + 1].compareTo(arr[j]) > 0) 53 | j += 1; 54 | 55 | if (e.compareTo(arr[j]) >= 0) 56 | break; 57 | 58 | arr[k] = arr[j]; 59 | k = j; 60 | } 61 | 62 | arr[k] = e; 63 | } 64 | 65 | public static void sort(Comparable[] arr) { 66 | 67 | int n = arr.length; 68 | 69 | // 注意,此时我们的堆是从0开始索引的 70 | // 从(最后一个元素的索引-1)/2开始 71 | // 最后一个元素的索引 = n-1 72 | for (int i = (n - 1 - 1) / 2; i >= 0; i--) 73 | shiftDown2(arr, n, i); 74 | 75 | for (int i = n - 1; i > 0; i--) { 76 | swap(arr, 0, i); // 当前最大的元素放到合适的位置之中 77 | shiftDown2(arr, i, 0); // 对第零个元素进行测试 78 | } 79 | } 80 | 81 | // 测试 HeapSort 82 | public static void main(String[] args) { 83 | 84 | int N = 1000000; 85 | Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000); 86 | SortTestHelper.testSort("me.zonglun.Sort.HeapSort3", arr); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/me/zonglun/Sort/IndexHeapSort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: IndexHeapSort 4 | * Author: Administrator 5 | * Date: 2017/11/6 0006 21:43 6 | * Description: 使用最大索引堆进行堆排序, 来验证我们的最大索引堆的正确性 7 | */ 8 | 9 | package me.zonglun.Sort; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈使用最大索引堆进行堆排序, 来验证我们的最大索引堆的正确性〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/6 0006 17 | * @since 1.0.0 18 | */ 19 | // 在后续的图论中, 无论是最小生成树算法, 还是最短路径算法, 我们都需要使用索引堆进行优化:) 20 | public class IndexHeapSort { 21 | 22 | // 我们的算法类不允许产生任何实例 23 | private IndexHeapSort(){} 24 | 25 | public static void sort(Comparable[] arr){ 26 | 27 | int n = arr.length; 28 | 29 | IndexMaxHeap indexMaxHeap = new IndexMaxHeap<>(n); 30 | for( int i = 0 ; i < n ; i ++ ) 31 | indexMaxHeap.insert( i , arr[i] ); 32 | 33 | for( int i = n-1 ; i >= 0 ; i -- ) 34 | arr[i] = indexMaxHeap.extractMax(); 35 | } 36 | 37 | // 测试 Index Heap Sort 38 | public static void main(String[] args) { 39 | 40 | int N = 1000000; 41 | Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000); 42 | SortTestHelper.testSort("me.zonglun.Sort.IndexHeapSort", arr); 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/me/zonglun/Sort/InsertionSort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: InsertionSort 4 | * Author: Administrator 5 | * Date: 2017/11/3 0003 10:36 6 | * Description: InsertionSort 7 | */ 8 | 9 | package me.zonglun.Sort; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 1. 插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。 14 | * 它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。 15 | * 插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序), 16 | * 因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。 17 | * 一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下: 18 | * <1>.从第一个元素开始,该元素可以认为已经被排序; 19 | * <2>.取出下一个元素,在已经排序的元素序列中从后向前扫描; 20 | * <3>.如果该元素(已排序)大于新元素,将该元素移到下一位置; 21 | * <4>.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置; 22 | * <5>.将新元素插入到该位置后; 23 | * <6>.重复步骤2~5。 24 | * you can see more detail in https://blog.zonglun.me/?p=140 25 | * 时间复杂度为o(N*2) 26 | * @author Administrator 27 | * @create 2017/11/3 0003 28 | * @since 1.0.0 29 | */ 30 | public class InsertionSort { 31 | private InsertionSort() { 32 | } 33 | 34 | // 对arr[ ]的区间使用InsertionSort排序 35 | public static void sort(Comparable[] arr) { 36 | int n = arr.length; 37 | for (int i = 0; i < n; i++) { 38 | /*从后往前面扫,如果有小的就交换*/ 39 | for (int j = i; j > 0 && arr[j].compareTo(arr[j - 1]) < 0; j--) { 40 | swap(arr, j, j - 1); 41 | } 42 | } 43 | } 44 | 45 | // 对arr[l...r]的区间使用InsertionSort排序 46 | public static void sort(Comparable[] arr, int l, int r){ 47 | 48 | for( int i = l + 1 ; i <= r ; i ++ ){ 49 | Comparable e = arr[i]; 50 | int j = i; 51 | for( ; j > l && arr[j-1].compareTo(e) > 0 ; j--) 52 | arr[j] = arr[j-1]; 53 | arr[j] = e; 54 | } 55 | } 56 | 57 | // 交换索引为i ;和 j的两个数组的值 58 | private static void swap(Object[] arr, int i, int j) { 59 | Object temp = arr[i]; 60 | arr[i] = arr[j]; 61 | arr[j] = temp; 62 | } 63 | 64 | // 测试InsertionSort 65 | public static void main(String[] args) { 66 | 67 | int N = 20000; 68 | Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000); 69 | SortTestHelper.testSort("me.zonglun.Sort.InsertionSort", arr); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/me/zonglun/Sort/MergeSortBU.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: MergeSortBU 4 | * Author: Administrator 5 | * Date: 2017/11/3 0003 21:49 6 | * Description: 自顶向上的归并排序,不需要递归调用 7 | */ 8 | 9 | package me.zonglun.Sort; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈自顶向上的归并排序,不需要递归调用〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/3 0003 17 | * @since 1.0.0 18 | */ 19 | public class MergeSortBU { 20 | 21 | public static void sort(Comparable[] arr) { 22 | int n = arr.length; 23 | for (int size = 1; size < n; size *= 2) 24 | for (int i = 0; i < n - size; i += size + size) 25 | // 对 arr[i...i+sz-1] 和 arr[i+sz...i+2*sz-1] 进行归并 26 | // 对于arr[mid] <= arr[mid+1]的情况,不进行merge 27 | if (arr[i + size - 1].compareTo(arr[i + size]) > 0) 28 | merge(arr, i, i + size - 1, Math.min(i + 2 * size - 1, n - 1)); 29 | } 30 | 31 | private static void merge(Comparable[] arr, int l, int mid, int r) { 32 | MergeSort.merge(arr, l, mid, r); 33 | } 34 | 35 | // 测试 MergeSort BU 36 | public static void main(String[] args) { 37 | 38 | // Merge Sort BU 也是一个O(nlogn)复杂度的算法,虽然只使用两重for循环 39 | // 所以,Merge Sort BU也可以在1秒之内轻松处理100万数量级的数据 40 | // 注意:不要轻易根据循环层数来判断算法的复杂度,Merge Sort BU就是一个反例 41 | int N = 1000000; 42 | Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000); 43 | SortTestHelper.testSort("me.zonglun.Sort.MergeSortBU", arr); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/me/zonglun/Sort/QuickSortOptimize.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: QuickSortOptimize 4 | * Author: Administrator 5 | * Date: 2017/11/4 0004 14:07 6 | * Description: optimize the quickSort 7 | */ 8 | 9 | package me.zonglun.Sort; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈optimize the quickSort〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/4 0004 17 | * @since 1.0.0 18 | */ 19 | public class QuickSortOptimize { 20 | private QuickSortOptimize() { 21 | } 22 | 23 | private static int partition(Comparable[] arr, int l, int r) { 24 | 25 | // 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivot 26 | swap(arr, l, (int) (Math.random() * (r - l + 1)) + l); // 随机生成 l-r 之间的索引 27 | 28 | Comparable v = arr[l]; 29 | int j = l; // arr[l+1...j] < v ; arr[j+1...i) > v 30 | for (int i = l + 1; i <= r; i++) 31 | if (arr[i].compareTo(v) < 0) { 32 | swap(arr, j + 1, i); 33 | j++; 34 | } 35 | swap(arr, l, j); 36 | return j; 37 | } 38 | 39 | // 递归使用快速排序,对arr[l...r]的范围进行排序 40 | private static void sort(Comparable[] arr, int l, int r) { 41 | if (r < l) 42 | return; 43 | int p = partition(arr, l, r); 44 | sort(arr, l, p - 1); 45 | sort(arr, p + 1, r); 46 | } 47 | 48 | public static void sort(Comparable[] arr) { 49 | int n = arr.length; 50 | sort(arr, 0, n - 1); 51 | } 52 | 53 | private static void swap(Object[] arr, int i, int j) { 54 | Object temp = arr[i]; 55 | arr[i] = arr[j]; 56 | arr[j] = temp; 57 | } 58 | 59 | // 测试 QuickSort 60 | public static void main(String[] args) { 61 | 62 | // Quick Sort也是一个O(nlogn)复杂度的算法 63 | // 可以在1秒之内轻松处理100万数量级的数据 64 | int N = 1000000; 65 | Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000); 66 | SortTestHelper.testSort("me.zonglun.Sort.QuickSortOptimize", arr); 67 | 68 | // 测试2 测试近乎有序的数组 69 | int swapTime = 100; 70 | System.out.println("Test for nearly ordered array, size = " + N + " , swap time = " + swapTime); 71 | 72 | Integer[] arr1 = SortTestHelper.generateNearlyOrderedArray(N, swapTime); 73 | SortTestHelper.testSort("me.zonglun.Sort.QuickSortOptimize", arr1); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/me/zonglun/Sort/RadixSort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: RadixSort 4 | * Author: Administrator 5 | * Date: 2017/11/6 0006 21:50 6 | * Description: 基数排序 7 | */ 8 | 9 | package me.zonglun.Sort; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈基数排序〉 14 | * 相对于常见的比较排序,基数排序是一种分配式排序,即通过将所有数字分配到应在的位置最后再覆盖到原数组完成排序的过程。 15 | * 16 | * @author Administrator 17 | * @create 2017/11/6 0006 18 | * @since 1.0.0 19 | */ 20 | public class RadixSort { 21 | private RadixSort() { 22 | } 23 | 24 | public static void main(String[] args) { 25 | int[] A = new int[]{73, 22, 93, 43, 55, 14, 28, 65, 39, 81}; 26 | RadixSort.sort(A, 100); 27 | for (int num : A) { 28 | System.out.println(num); 29 | } 30 | 31 | int N = 1000; 32 | Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 1000); 33 | SortTestHelper.testSort("me.zonglun.Sort.RadixSort", arr); 34 | } 35 | 36 | private static void sort(int[] arr, int d) { 37 | int n = 1; //代表位数对应的数:1,10,100... 38 | int k = 0; //保存每一位排序后的结果用于下一位的排序输入 39 | int len = arr.length; 40 | int[][] bucket = new int[10][len]; //排序桶用于保存每次排序后的结果,这一位上排序结果相同的数字放在同一个桶里 41 | int[] order = new int[len];//用于保存每个桶里有多少个数字 42 | while (n < d) { 43 | for (int num : arr) { 44 | int digit = (num / n) % 10; 45 | bucket[digit][order[digit]] = num; 46 | order[digit]++; 47 | } 48 | for (int i = 0; i < len; i++)//将前一个循环生成的桶里的数据覆盖到原数组中用于保存这一位的排序结果 49 | { 50 | if (order[i] != 0)//这个桶里有数据,从上到下遍历这个桶并将数据保存到原数组中 51 | { 52 | for (int j = 0; j < order[i]; j++) { 53 | arr[k] = bucket[i][j]; 54 | k++; 55 | } 56 | } 57 | order[i] = 0;//将桶里计数器置0,用于下一次位排序 58 | } 59 | n *= 10; 60 | k = 0;//将k置0,用于下一轮保存位排序结果 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/me/zonglun/Sort/SelectionSort.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.Sort; 2 | 3 | 4 | /* 5 | * 1. 选择排序(Selection-sort)是一种简单直观的排序算法。 6 | * 它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置, 7 | * 然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕 8 | * 2. 在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换; 9 | 第二次遍历n-2个数,找到最小的数值与第二个元素交换;。。。。。 10 | 第n-1次遍历,找到最小的数值与第n-1个元素交换,排序完成。 11 | * */ 12 | public class SelectionSort { 13 | private SelectionSort () {} 14 | 15 | // 交换索引为i ;和 j的两个数组的值 16 | private static void swap(Object[] arr, int i, int j) { 17 | Object temp = arr[i]; 18 | arr[i] = arr[j]; 19 | arr[j] = temp; 20 | } 21 | 22 | 23 | private static void sort(Comparable[] arr) { 24 | int n = arr.length; 25 | for (int i = 0; i < n; i++) { 26 | // 找到【i,n)之间的最小值的索引 27 | int minIndex = i; // 最开始的最小索引定为 开始的 i 28 | for (int j = i + 1; j < n; j++) { 29 | if (arr[j].compareTo( arr[minIndex]) < 0) // 判断i之后的每个值,如果有值比其小,则最小索引改变 30 | minIndex = j; 31 | } 32 | swap(arr, i, minIndex); // 内层循环完之后交换最小索引与i的值,同时i指针前移动一位 33 | } 34 | } 35 | 36 | public static void main(String[] args) { 37 | // 测试排序算法辅助函数 38 | int N = 20000; 39 | Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000); 40 | long startTime = System.currentTimeMillis(); 41 | SelectionSort.sort(arr); 42 | long endTime = System.currentTimeMillis(); 43 | System.out.println( " SelectionSort sort for 100000 Random Numbers: " + (endTime-startTime) + "ms" ); 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /src/me/zonglun/Sort/ShellSort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: ShellSort 4 | * Author: Administrator 5 | * Date: 2017/11/3 0003 14:56 6 | * Description: ShellSort 7 | */ 8 | 9 | package me.zonglun.Sort; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈 ShellSort〉 14 | * 希尔排序的核心在于间隔序列的设定。 15 | * 既可以提前设定好间隔序列,也可以动态的定义间隔序列。动态定义间隔序列的算法是《算法(第4版》的合著者Robert Sedgewick提出的。 16 | * <1>. 选择一个增量序列t1,t2,…,tk,其中ti > tj,tk = 1; 17 | * <2>. 按增量序列个数k, 对序列进行k 趟排序 ; 18 | * <3>.每趟排序,根据对应的增量ti,将待排序列分割成若干长度为 m 的子序列, 19 | * 分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度. 20 | * 最佳情况:T(n) = O(n(log n)^2) 21 | 最坏情况:T(n) = O(n(log n)^2) 22 | 平均情况:T(n) =O(nlogn) 23 | * @author Administrator 24 | * @create 2017/11/3 0003 25 | * @since 1.0.0 26 | */ 27 | public class ShellSort { 28 | private ShellSort() { 29 | } 30 | 31 | public static void sort(Comparable[] arr) { 32 | int n = arr.length; 33 | // 计算 increment sequence: 1, 4, 13, 40, 121, 364, 1093... 34 | int h = 1; 35 | while (h < n / 3) h = 3 * h + 1; // h记为增量 36 | while (h >= 1) { 37 | for (int i = h; i < n; i++) { 38 | // 对 arr[i], arr[i-h], arr[i-2*h], arr[i-3*h]... 使用插入排序 39 | Comparable e = arr[i]; 40 | int j = i; 41 | for (; j >= h && e.compareTo(arr[j - h]) < 0; j -= h) { 42 | arr[j] = arr[j - h]; 43 | } 44 | arr[j] = e; 45 | } 46 | h /= 3; 47 | } 48 | } 49 | 50 | public static void main(String[] args) { 51 | int N = 20000; 52 | // 测试1 一般测试 53 | System.out.println("Test for random array, size = " + N + " , random range [0, " + N + "]"); 54 | Integer[] arr1 = SortTestHelper.generateRandomArray(N, 0, N); 55 | SortTestHelper.testSort("me.zonglun.Sort.ShellSort", arr1); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/me/zonglun/Sort/Student.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: Student 4 | * Author: Administrator 5 | * Date: 2017/11/2 0002 19:59 6 | * Description: this is a test class for other Sort Class 7 | */ 8 | 9 | package me.zonglun.Sort; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈this is test for other Sort Class〉 14 | * 15 | * @author Administrator 16 | * @deprecated 2017/11/2 0002 17 | * @since 1.0.0 18 | */ 19 | class Student implements Comparable{ 20 | private String name; 21 | private int score; 22 | 23 | Student(String name, int score){ 24 | this.name = name; 25 | this.score = score; 26 | } 27 | 28 | // 定义Student的compareTo函数 29 | // 如果分数相等,则按照名字的字母序排序 30 | // 如果分数不等,则分数高的靠前 31 | @Override 32 | public int compareTo(Student that) { 33 | 34 | if( this.score < that.score ) 35 | return -1; 36 | else if( this.score > that.score ) 37 | return 1; 38 | else // this.score == that.score 39 | return this.name.compareTo(that.name); 40 | } 41 | 42 | // 定义Student实例的打印输出方式 43 | @Override 44 | public String toString() { 45 | return "Student: " + this.name + " " + Integer.toString( this.score ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/AddFunction.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | /** 4 | * 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。 5 | * 6 | * @author : Administrator 7 | * @subject : 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。 8 | * @create 2018-04-24 22:17 9 | */ 10 | public class AddFunction { 11 | 12 | 13 | /** 14 | * 十进制操作:5 + 7 = 12,三步走 15 | * 第一步:相加各位的值,不算进位,得到2 16 | * 17 | * @param num1 18 | * @param num2 19 | * @return 20 | */ 21 | public int add(int num1, int num2) { 22 | while (num2 != 0) { 23 | int temp = num1 ^ num2; 24 | num2 = (num1 & num2) << 1; 25 | num1 = temp; 26 | } 27 | return num1; 28 | } 29 | 30 | public static void main(String[] args) { 31 | System.out.println(new AddFunction().add(4,6)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/ConvertBSTToLinkList.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.TreeNode; 4 | 5 | /** 6 | * 二叉搜索树与双向链表 7 | * 8 | * @author : Administrator 9 | * @subject : 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。 10 | * 要求不能创建任何新的结点,只能调整树中结点指针的指向。 11 | * @exapmle: 10 12 | * 6 14 4 <->6<->8<->10<->12<->14<->16 13 | * 4 8 12 16 14 | * @create 2018-03-18 16:00 15 | */ 16 | public class ConvertBSTToLinkList { 17 | 18 | /** 19 | * 20 | * @param pRootOfTree 21 | * @return TreeNode 22 | */ 23 | public TreeNode Convert(TreeNode pRootOfTree) { 24 | TreeNode pLastNodeInList = null; 25 | ConvertNode(pRootOfTree, pLastNodeInList); 26 | // PLastNode 是在链表的尾节点 27 | // 我们需要返回头节点 28 | TreeNode pHeadOfList = pLastNodeInList; 29 | while (pHeadOfList != null && pHeadOfList.left != null) { 30 | pHeadOfList = pHeadOfList.left; 31 | } 32 | return pHeadOfList; 33 | } 34 | 35 | private void ConvertNode(TreeNode pNode, TreeNode pLastNodeInList) { 36 | if (pNode == null) { 37 | return; 38 | } 39 | TreeNode currentNode = pNode; 40 | if (currentNode.left != null) { 41 | ConvertNode(currentNode.left, pLastNodeInList); 42 | } 43 | currentNode.left = pLastNodeInList; 44 | if (pLastNodeInList != null) { 45 | pLastNodeInList.right = currentNode; 46 | } 47 | pLastNodeInList = currentNode; 48 | 49 | if (currentNode.right != null) { 50 | ConvertNode(currentNode.right, pLastNodeInList); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/DeleteDuplicationListNode.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.ListNode; 4 | 5 | /** 6 | * 〈一句话功能简述〉
7 | * 〈链表中环的节点〉 8 | * 9 | * @author Administrator 10 | * @subject 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 11 | * 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5 12 | * @Strategies 13 | * @create 2018/3/11 0011 14 | * @since 1.0.0 15 | */ 16 | public class DeleteDuplicationListNode { 17 | 18 | /** 19 | * 使用递归来实现删除重复节点的功能 20 | * @param pHead 21 | * @return 22 | */ 23 | private ListNode deleteDuplication(ListNode pHead) { 24 | if (pHead == null || pHead.next == null) { 25 | return pHead; // 只有0个或1个结点,则返回 26 | } 27 | 28 | // 当前结点是重复结点 29 | if (pHead.val == pHead.next.val) { 30 | ListNode pNode = pHead.next; 31 | while (pNode != null && pNode.val == pHead.val) { 32 | // 跳过值与当前结点相同的全部结点,找到第一个与当前结点不同的结点 33 | pNode = pNode.next; 34 | } 35 | // 从第一个与当前结点不同的结点开始递归 36 | return deleteDuplication(pNode); 37 | } else { // 当前结点不是重复结点 38 | pHead.next = deleteDuplication(pHead.next); // 保留当前结点,从下一个结点开始递归 39 | return pHead; 40 | } 41 | } 42 | 43 | /** 44 | * 使用非递归来实现功能 45 | * @param pHead 46 | * @return ListNode 47 | */ 48 | public ListNode deleteDuplication2(ListNode pHead) { 49 | if (pHead == null || pHead.next == null) { 50 | return pHead; 51 | } 52 | 53 | // 新建一个头节点防止,第一个节点被删除 54 | ListNode newNode = new ListNode(-1); 55 | newNode.next = pHead; 56 | ListNode pre = newNode; 57 | ListNode p = pHead; 58 | ListNode next = null; 59 | while (p != null && p.next != null) { 60 | next = p.next; 61 | //如果当前节点的值和下一个节点的值相等 62 | if (p.val == next.val) { 63 | while (next != null && next.val == p.val) { 64 | next = next.next; // 指针继续后移,直到找到所有的重复的值 65 | } 66 | pre.next = next; // 指针赋值直到最后一个重复的值为止,可视为删除多余的节点 67 | p = next; 68 | } else { //如果当前节点和下一个节点值不等,则向后移动一位 69 | pre = p; 70 | p = p.next; // 指针继续后移 71 | } 72 | } 73 | return newNode.next; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/DoublylinkedList.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.TreeNode; 4 | 5 | /** 6 | * 双向链表 7 | * 8 | * @author : Administrator 9 | * @create 2018-08-25 16:09 10 | * @subject : 11 | * 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。 12 | * 要求不能创建任何新的结点,只能调整树中结点指针的指向。 13 | */ 14 | public class DoublylinkedList { 15 | 16 | public TreeNode Convert(TreeNode pRootOfTree) { 17 | if (pRootOfTree == null) { 18 | return null; 19 | } 20 | TreeNode head = null; 21 | if (pRootOfTree.left != null) { 22 | TreeNode h = Convert(pRootOfTree.left); 23 | head = h; 24 | while (h.right != null) { 25 | h = h.right; 26 | } 27 | h.right = pRootOfTree; 28 | pRootOfTree.left = h; 29 | } 30 | 31 | if (pRootOfTree.right != null) { 32 | TreeNode h = Convert(pRootOfTree.right); 33 | pRootOfTree.right = h; 34 | h.left = pRootOfTree; 35 | } 36 | 37 | return head != null ? head : pRootOfTree; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/DuplicateNum.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import java.util.HashSet; 4 | 5 | /** 6 | * 数组中重复的数字 7 | * 8 | * @author : Administrator 9 | * @subject : 在一个长度为n的数组里面,所有的数字都在0 到 n - 1 的范围内。 10 | * 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。 11 | * 请找出数组中任意一个重复的数字,其输出为第一个重复的数字2 12 | * @create 2018-04-25 21:23 13 | */ 14 | public class DuplicateNum { 15 | 16 | /** 17 | * 18 | * @param numbers 整数数组,长度为n 19 | * @param length 长度、 20 | * @param duplication 重复的数字 21 | * @return boolean 22 | */ 23 | public boolean deplicateNum(int numbers[], int length, int[] duplication) { 24 | HashSet hs = new HashSet<>(); 25 | for (int i = 0; i < length; i++) { 26 | if (!hs.add(numbers[i])) { 27 | duplication[0] = numbers[i]; 28 | return true; 29 | } 30 | } 31 | return false; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/EntryNodeOfLoop.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2018 3 | * FileName: EntryNodeOfLoop 4 | * Author: Administrator 5 | * Date: 2018/3/11 0011 16:31 6 | * Description: 链表中环的节点 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | import me.zonglun.SwordToOffer.util.ListNode; 12 | 13 | /** 14 | * 〈一句话功能简述〉
15 | * 〈链表中环的节点〉 16 | * 17 | * @author Administrator 18 | * @subject 一个链表中包含环,请找出该链表的环的入口结点。 19 | * @Strategies 20 | * @create 2018/3/11 0011 21 | * @since 1.0.0 22 | */ 23 | public class EntryNodeOfLoop { 24 | 25 | public ListNode EntryNodeOfLoop(ListNode pHead) { 26 | // 最少要三个节点成环 27 | if (pHead == null || pHead.next == null || pHead.next.next == null) 28 | return null; 29 | // 第一步,找环中相汇点。分别用p1,p2指向链表头部,p1每次走一步,p2每次走二步,直到p1==p2找到在环中的相汇点。 30 | ListNode p1 = pHead; 31 | ListNode p2 = pHead; 32 | while (p2 != null && p1 != null) { 33 | p1 = p1.next; 34 | p2 = p2.next.next; 35 | // 第二步,将相遇的这点时叫做B点,此时将p2指针重新移到链表的头部,p1任然在B点,两者以相同的速度扫描,直到相遇即 36 | // 到了链表中环的入口 37 | if (p1 == p2) { 38 | p2 = pHead; 39 | while (p1 != p2) { 40 | p1 = p1.next; 41 | p2 = p2.next; 42 | } 43 | if (p1 == p2) 44 | return p1; 45 | } 46 | } 47 | return null; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/Fibonacci.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: Fibonacci 4 | * Author: Administrator 5 | * Date: 2017/11/19 0019 22:15 6 | * Description: 斐波那契数列 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈斐波那契数列〉 14 | *@subject 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。 15 | n<=39,, 0 ----- n=0 16 | 斐波那契数列 f(n) = 1 ----- n = 1 17 | * f(n-1)+f(n-2) --- n>=2 18 | * @Strategies 不建议使用递归的方法,时间的复杂度更高, 19 | * 可使用循环的方法,先计算循环过程之中的f(3) 在算f(4)这样逐步递归 20 | * @author Administrator 21 | * @create 2017/11/19 0019 22 | * @since 1.0.0 23 | */ 24 | public class Fibonacci { 25 | private static int fibonacci(int n) { 26 | if (n <= 1) 27 | return n; 28 | int numFn1 = 0, numFn2 = 1, currentNum = 0; 29 | for (int i = 2; i <= n ; i++) { 30 | currentNum = numFn1 + numFn2; 31 | numFn1 = numFn2; 32 | numFn2 = currentNum; 33 | } 34 | return currentNum; 35 | } 36 | 37 | public static void main(String[] args) { 38 | System.out.println(Fibonacci.fibonacci(3)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/FindContinuousSequence.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * 输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序 7 | * 8 | * @author : Administrator 9 | * @subject : 输入一个递增的排序的数组和一个数字s,在数组中查找两个数,使得他们的和恰好是 10 | * s, 如果有多个则输出所有的对数 11 | * @create 2018-04-22 21:03 12 | */ 13 | public class FindContinuousSequence { 14 | 15 | public ArrayList> findContinuousSequence(int sum) { 16 | ArrayList> result = new ArrayList<>(); 17 | if (sum < 3) { 18 | return result; 19 | } 20 | int small = 1; 21 | int big = 2; 22 | int middle = (1 + sum) / 2; 23 | int curSum = 3; 24 | while (small < middle) { 25 | // 初始化条件比需要的要小,需要加大big 26 | while (curSum < sum) { 27 | big++; 28 | curSum += big; 29 | } 30 | // 找到了相对应的数组串使得其相等 31 | if (curSum == sum) { 32 | ArrayList list = new ArrayList<>(); 33 | for (int i = small; i <= big ; i++) { 34 | list.add(i); 35 | } 36 | result.add(list); 37 | } 38 | // 剩余情况是结果curSum > result,此时增加small 39 | curSum -= small; 40 | small++; 41 | } 42 | return result; 43 | } 44 | 45 | public static void main(String[] args) { 46 | System.out.println(new FindContinuousSequence().findContinuousSequence(45)); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/FindFirstCommonNodeInList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2018 3 | * FileName: FindFirstCommonNodeInList 4 | * Author: Administrator 5 | * Date: 2018/3/11 0011 14:06 6 | * Description: 输入两个链表,找出它们的第一个公共结点。 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | 12 | import java.util.Stack; 13 | 14 | /** 15 | * 〈一句话功能简述〉
16 | * 〈输入两个链表,找出它们的第一个公共结点。〉 17 | * 18 | * @author Administrator 19 | * @subject 输入两个链表,找出它们的第一个公共结点。 20 | * @Strategies 由于是单向链表,所以在两条链表之中,必定有一个节点是其公共节点,类似这种 21 | * 我们使用从尾到头的遍历,把节点放入到两个栈中,比较栈顶的元素,直到最后一个栈顶元素相同的极为所需要的元素 22 | * @example 1->2->3->4 23 | * ->8->9->10 24 | * 5->6->7 25 | * @create 2018/3/11 0011 26 | * @since 1.0.0 27 | */ 28 | public class FindFirstCommonNodeInList { 29 | 30 | private class ListNode { 31 | int val; 32 | ListNode next = null; 33 | 34 | ListNode(int val) { 35 | this.val = val; 36 | } 37 | } 38 | 39 | /** 40 | * 用两个辅助栈来实现 ,时间复杂度o(m + n) 41 | * @param pHead1 链表1头节点 42 | * @param pHead2 链表2头节点 43 | * @return ListNode 44 | */ 45 | public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) { 46 | if (pHead1 == null || pHead2 == null) 47 | return null; 48 | Stack stack1 = new Stack<>(); 49 | Stack stack2 = new Stack<>(); 50 | // 把链表的元素扔进栈中 51 | while (pHead1 != null) { 52 | stack1.push(pHead1); 53 | pHead1 = pHead1.next; 54 | } 55 | while (pHead2 != null) { 56 | stack2.push(pHead2); 57 | pHead2 = pHead2.next; 58 | } 59 | 60 | ListNode commonNode = null; 61 | 62 | while (!stack1.isEmpty() && !stack2.isEmpty() && stack1.peek().val == stack2.peek().val) { 63 | stack2.pop(); 64 | commonNode = stack1.pop(); 65 | } 66 | return commonNode; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/FindGreatestSumOfSubArray.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | /** 4 | * 连续子数组的最大的和 5 | * 6 | * @author : Administrator 7 | * @subject : 输入一个整型数组,数组里面既有正数,也有负数,数组中一个或者连续的多个整数组成一个子数组,求所有的子数组的最大值? 8 | * 并且要求时间的复杂度为o(n) 9 | * 例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。 10 | * 在如{1, -2, 3, 10, -4, 7, 2, -5} 最大的子数组为{3, 10, -4, 7, 2},因此输出该子数组的和为18 11 | * (子向量的长度至少是1) 12 | * @create 2018-03-24 20:12 13 | */ 14 | public class FindGreatestSumOfSubArray { 15 | 16 | /** 17 | * 返回整数值 18 | * @param array 19 | * @return 20 | */ 21 | public static int FindGreatestSumOfSubArray(int[] array) { 22 | if (array.length == 0) { 23 | return 0; 24 | } 25 | int curNum = 0; 26 | int countNum = array[1]; 27 | for (int i = 0; i < array.length; i++) { 28 | if (curNum <= 0) { // 如果当前子数组串累加之后,和为负数或者为零,则直接赋值给当前的元素 29 | curNum = array[i]; 30 | } else { 31 | curNum += array[i]; 32 | } 33 | if (curNum > countNum) { 34 | countNum = curNum; 35 | } 36 | } 37 | return countNum; 38 | } 39 | 40 | public static void main(String[] args) { 41 | int[] array = {1, -2, 3, 10, -4, 7, 2, -5}; 42 | int[] array2 = {6,-3,-2,7,-15,1,2,2}; 43 | int[] array3 = {-2,-8,-1,-5,-9}; 44 | System.out.println(FindGreatestSumOfSubArray(array)); 45 | System.out.println(FindGreatestSumOfSubArray(array2)); 46 | System.out.println(FindGreatestSumOfSubArray(array3)); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/FindInPartiallySortedMatrix.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: FindInPartiallySortedMatrix 4 | * Author: Administrator 5 | * Date: 2017/11/17 0017 10:33 6 | * Description: 二维数组的查找 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈二维数组的查找〉 14 | *@subject 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。 15 | * 请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数, 16 | *@example 1 2 8 9 17 | * 2 4 9 8 在这个数组中查找元素 7 则返回true;否则查找 5 返回false 18 | * 4 7 10 13 19 | * 6 8 11 15 20 | * @Strategies 21 | * 思路一: 22 | 利用二维数组由上到下,由左到右递增的规律, 23 | 那么选取右上角或者左下角的元素a[row][col]与target进行比较, 24 | 当target小于元素a[row][col]时,那么target必定在元素a所在行的左边, 25 | 即col--; 26 | 当target大于元素a[row][col]时,那么target必定在元素a所在列的下边, 27 | 即row++; 28 | 思路二: 29 | 把每一行看成有序递增的数组, 30 | 利用二分查找, 31 | 通过遍历每一行得到答案, 32 | 时间复杂度是nlogn 33 | * @author Administrator 34 | * @create 2017/11/17 0017 35 | * @since 1.0.0 36 | */ 37 | public class FindInPartiallySortedMatrix { 38 | 39 | /** 40 | * 41 | * @param target 目标值 42 | * @param array 目标数组 43 | * @return boolean 44 | */ 45 | public static boolean find(int target, int[][] array) { 46 | int row = 0; 47 | int col = array[0].length - 1; 48 | while (row <= array.length - 1 && col >= 0) { 49 | if (target == array[row][col]) { 50 | return true; 51 | } else if (target > array[row][col]) { 52 | row++; 53 | } else { 54 | col--; 55 | } 56 | } 57 | return false; 58 | } 59 | 60 | 61 | public static void main(String[] args) { 62 | int[][] arr = {{1,2,8,9},{2,4,9,8},{4,7,10,13},{6,8,11,15}}; 63 | System.out.println(FindInPartiallySortedMatrix.find(5,arr)); 64 | System.out.println(FindInPartiallySortedMatrix.find(7,arr)); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/FindKthInBinaryTree.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.TreeNode; 4 | 5 | /** 6 | * 找到二叉树的第K个节点 7 | * 8 | * @author : Administrator 9 | * @create 2018-08-21 20:17 10 | * @subject : 给定一颗二叉搜索树,请找出其中的第K小的节点。例如,(5,3,7,2,4,6,8)中, 11 | * 按结点数值大小顺序第三小结点的值为4 12 | */ 13 | public class FindKthInBinaryTree { 14 | // 计数器 15 | int index = 0; 16 | 17 | TreeNode KthNode(TreeNode pRoot, int k) { 18 | if (pRoot != null) { 19 | TreeNode node = KthNode(pRoot.left, k); 20 | if (node != null) { 21 | return node; 22 | } 23 | index++; 24 | if (index == k) { 25 | return pRoot; 26 | } 27 | node = KthNode(pRoot.right, k); 28 | if (node != null) { 29 | return node; 30 | } 31 | } 32 | return null; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/FindKthToTail.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: FindKthToTail 4 | * Author: Administrator 5 | * Date: 2017/12/14 0014 21:03 6 | * Description: 输入一个链表,输出该链表中倒数第k个结点。 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈输入一个链表,输出该链表中倒数第k个结点。〉 14 | * 15 | * @author Administrator 16 | * @subject 输入一个链表,输出该链表中倒数第k个结点。 17 | * @Strategies 18 | * 两个指针,先让第一个指针和第二个指针都指向头结点, 19 | * 然后再让第一个指正走(k-1)步,到达第k个节点。然后两个指针同时往后移动, 20 | * 当第一个结点到达末尾的时候,第二个结点所在位置就是倒数第k个节点了 21 | * @create 2017/12/14 0014 22 | * @since 1.0.0 23 | */ 24 | public class FindKthToTail { 25 | private static class ListNode { 26 | int val; 27 | ListNode next = null; 28 | 29 | ListNode(int val) { 30 | this.val = val; 31 | } 32 | ListNode append(ListNode node) { 33 | this.next = node; 34 | return this; 35 | } 36 | } 37 | 38 | public static ListNode find(ListNode head, int k) { 39 | if (head == null || k <= 0) { 40 | return null; 41 | } 42 | ListNode pre = head; 43 | ListNode last = head; 44 | for (int i = 1; i < k; i++) { 45 | if (pre.next != null) { 46 | pre = pre.next; 47 | } else { 48 | return null; 49 | } 50 | } 51 | while (pre.next != null) { 52 | pre = pre.next; 53 | last = last.next; 54 | } 55 | return last; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/FindNumbersWithSum.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。 7 | * 8 | * @author : Administrator 9 | * @create 2018-04-22 21:45 10 | */ 11 | public class FindNumbersWithSum { 12 | 13 | /** 14 | * 设置一头一尾指针,两者和相加则为s则满足,若比s大,则尾部指针向前移动, 15 | * 所和比s小, 头部指针向后移动,当两者找到第一个和等于s的值,意味着此时输出的乘积最小 16 | * @param array 17 | * @param sum 18 | * @return 19 | */ 20 | public ArrayList findNumbersWithSum(int [] array, int sum) { 21 | ArrayList list = new ArrayList<>(); 22 | if (array == null || array.length < 2) { 23 | return list; 24 | } 25 | int head = 0; 26 | int foot = array.length - 1; 27 | 28 | while (head < foot) { 29 | int curSum = array[head] + array[foot]; 30 | if (curSum == sum) { 31 | list.add(array[head]); 32 | list.add(array[foot]); 33 | return list; 34 | // 若比s大,则尾部指针向前移动, 35 | } else if (curSum > sum) { 36 | foot--; 37 | } else { 38 | head++; 39 | } 40 | } 41 | return list; 42 | } 43 | 44 | public static void main(String[] args) { 45 | int[] array = {1, 3, 4, 5, 5, 3, 7}; 46 | System.out.println(new FindNumbersWithSum().findNumbersWithSum(array,10)); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/FindPathInBinaryTree.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * 二叉树中和为某一值的路径 9 | * 10 | * @author : Administrator 11 | * @subject : 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。 12 | * 路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。 13 | * @example: 14 | * @create 2018-03-18 14:20 15 | */ 16 | public class FindPathInBinaryTree { 17 | 18 | private ArrayList> PathList = new ArrayList<>(); // 存放路径值 19 | 20 | /** 21 | * 用前序遍历的方式访问到某一节点值时候,把该节点添加到路径上,并且累加该节点的值,如果该节点为叶子节点并且路径中 22 | * 节点值的和恰好等于输入的整数,那么就符合路劲的要求,否则退回它的父节点,并将路径中的叶子节点删除,并且减去当前叶子节点的值 23 | * 可以看出保存路径的数据结构可以用栈来表示 24 | * @param root 25 | * @param target 26 | * @return ArrayList> 存贮的所有的节点路径 27 | */ 28 | public ArrayList> FindPath(TreeNode root, int target) { 29 | if (root == null) { 30 | return PathList; 31 | } 32 | find(PathList, new ArrayList<>(), root, target); 33 | return PathList; 34 | } 35 | 36 | private void find(ArrayList> pathList, ArrayList count, TreeNode root, int target) { 37 | count.add(root.val); 38 | if (root.left == null && root.right == null) { 39 | if (target == root.val) { 40 | pathList.add(count); 41 | } 42 | return; 43 | } 44 | ArrayList count2 = new ArrayList<>(count); 45 | if (root.left != null) { 46 | find(pathList, count, root.left, target - root.val); 47 | } 48 | if (root.right != null) { 49 | find(pathList, count2 ,root.right, target - root.val); 50 | } 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/FirstAppearingOnce.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | /** 4 | * @author : Administrator 5 | * @Subject: 请实现一个函数用来找出字符流中第一个只出现一次的字符。 6 | * 例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。 7 | * 当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。 8 | * 如果当前字符流没有存在出现一次的字符,返回#字符 9 | * @create 2018-05-12 19:36 10 | */ 11 | public class FirstAppearingOnce { 12 | private int[] hashTable = new int[256]; 13 | private StringBuffer s = new StringBuffer(); 14 | 15 | public void setS(StringBuffer s) { 16 | this.s = s; 17 | } 18 | 19 | // Insert one char from StringStream 20 | public void Insert(char ch) { 21 | s.append(ch); 22 | if (hashTable[ch] == 0) { 23 | hashTable[ch] = 1; 24 | } else { 25 | hashTable[ch] += 1; 26 | } 27 | } 28 | 29 | // return the first appearence once char in current stringstream 30 | public char FristAppearingOnce() { 31 | char[] str = s.toString().toCharArray(); 32 | for (char c : str) { 33 | if (hashTable[c] == 1) { 34 | return c; 35 | } 36 | } 37 | return '#'; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/FirstNotRepeatingChar.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | /* 4 | * @subejct: 在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置 5 | * @example: 例如输入 “abaccdeff" 则输出”b“ 6 | * */ 7 | public class FirstNotRepeatingChar { 8 | 9 | public int solution(String str) { 10 | char[] chars = str.toCharArray(); 11 | int[] map = new int[256]; 12 | for (int i = 0; i < chars.length; i++) { 13 | map[chars[i]]++; 14 | } 15 | for (int i = 0; i < chars.length; i++) { 16 | if (map[chars[i]] == 1) { 17 | return i; 18 | } 19 | } 20 | return -1; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/FlowWindows.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | 6 | /** 7 | * 滑动窗口的最大值 8 | * 9 | * @author : Administrator 10 | * @create 2018-08-23 11:33 11 | * @subject : 12 | * 给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。 13 | * 例如, 14 | * 如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 15 | * 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: 16 | * {[2,3,4],2,6,2,5,1}, 17 | * {2,[3,4,2],6,2,5,1}, 18 | * {2,3,[4,2,6],2,5,1}, 19 | * {2,3,4,[2,6,2],5,1}, 20 | * {2,3,4,2,[6,2,5],1}, 21 | * {2,3,4,2,6,[2,5,1]}。 22 | * 23 | * @solution: 24 | * 借助一个辅助队列,从头遍历数组,根据如下规则进行入队列或出队列操作: 25 | * 0. 如果队列为空,则当前数字入队列 26 | * 1. 如果当前数字大于队列尾,则删除队列尾, 27 | * 直到当前数字小于等于队列尾,或者队列空,然后当前数字入队列 28 | * 2. 如果当前数字小于队列尾,则当前数字入队列 29 | * 3. 如果队列头超出滑动窗口范围,则删除队列头 30 | * 这样能始终保证队列头为当前的最大值 31 | */ 32 | public class FlowWindows { 33 | 34 | public ArrayList maxInWindows(int[] num, int size) { 35 | ArrayList result = new ArrayList<>(); 36 | if (num == null || num.length == 0 || size == 0 || size > num.length) { 37 | return result; 38 | } 39 | LinkedList queue = new LinkedList<>(); 40 | for (int i = 0; i < num.length; i++) { 41 | if (!queue.isEmpty()) { 42 | // 如果队列头元素不在滑动窗口中,就删除头元素 43 | if (i >= queue.peek() + size) { 44 | queue.pop(); 45 | } 46 | 47 | // 如果当前数字大于队列尾,则删除队列尾,直到当前数字小于等于队列尾,或者队列空 48 | while (!queue.isEmpty() && num[i] >= num[queue.getLast()]) { 49 | queue.removeLast(); 50 | } 51 | } 52 | queue.offer(i); 53 | 54 | // 滑动窗口经过三个元素,获取当前的最大值,也就是队列的头元素 55 | if (i + 1 >= size) { 56 | result.add(num[queue.peek()]); 57 | } 58 | } 59 | return result; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/GetLeastNumbers_Solution.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Comparator; 5 | import java.util.PriorityQueue; 6 | 7 | /** 8 | * 最小的K的个数 9 | * 10 | * @author : Administrator 11 | * @subject : 输入n个整数,找出其中 最小的 K 个数。 12 | * 例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。 13 | * @create 2018-03-23 20:31 14 | */ 15 | public class GetLeastNumbers_Solution { 16 | 17 | /** 18 | * 采用堆排序的最大堆来做 19 | * @param input 20 | * @param k 21 | * @return 22 | */ 23 | public ArrayList getLeastNumber_solutions(int[] input, int k) { 24 | ArrayList result = new ArrayList<>(); 25 | if (k > input.length || k == 0) { 26 | return result; 27 | } 28 | PriorityQueue maxHeap = new PriorityQueue<>(k, Comparator.reverseOrder()); 29 | 30 | for (int anInput : input) { 31 | if (maxHeap.size() != k) { 32 | maxHeap.offer(anInput); 33 | } else if (maxHeap.peek() > anInput) { 34 | Integer temp = maxHeap.poll(); 35 | maxHeap.offer(anInput); 36 | } 37 | } 38 | result.addAll(maxHeap); 39 | return result; 40 | } 41 | 42 | 43 | public static void main(String[] args) { 44 | int[] input = {4, 5, 1, 6, 2, 7, 3, 8}; 45 | GetLeastNumbers_Solution gs = new GetLeastNumbers_Solution(); 46 | System.out.println(gs.getLeastNumber_solutions(input,4)); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/GetMinStack.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: GetMinStack 4 | * Author: Administrator 5 | * Date: 2017/11/16 0016 16:38 6 | * Description: 剑指offer---在栈中得到最小的元素 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | import java.util.Stack; 12 | 13 | /** 14 | * 〈一句话功能简述〉
15 | * 〈剑指offer---在栈中得到最小的元素〉 16 | * 17 | * @author xcalen 18 | * @subject 1. 设计一个特殊的栈,在实现栈的基本功能上,再实现返回栈的最小值的功能 19 | * 2. pop, push, getMIn操作时间复杂度为O(1) 20 | * 3. 时间限制:1秒 空间限制:32768K 21 | * @Strategies 设计上使用两个栈,一个用来保存当前栈中的元素--StackData;另一个栈用于保存每一步之中的最小值--记为StackMin 22 | */ 23 | public class GetMinStack { 24 | 25 | private Stack stackData = new Stack<>(); 26 | private Stack stackMin = new Stack<>(); 27 | 28 | public void push(int node) { 29 | if (stackMin.empty()) 30 | stackMin.push(node); 31 | else if (node <= this.min()) 32 | stackMin.push(node); 33 | stackData.push(node); 34 | } 35 | 36 | public void pop() { 37 | if (!stackData.empty()) { 38 | int num = stackData.pop(); 39 | if (num == this.min()) 40 | stackMin.pop(); 41 | } 42 | } 43 | 44 | public int top() { 45 | return stackData.peek(); 46 | } 47 | 48 | public int min() { 49 | if (stackMin.empty()) 50 | return -1; 51 | return stackMin.peek(); 52 | } 53 | 54 | 55 | public static void main(String[] args) { 56 | GetMinStack ps = new GetMinStack(); 57 | ps.push(34); 58 | ps.push(12); 59 | ps.push(90); 60 | ps.push(4); 61 | System.out.println(ps.min()); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/GetNextTreeNode.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.TreeLinkNode; 4 | 5 | /** 6 | * @author : Administrator 7 | * @Subject: 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。 8 | * 注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。 9 | * @create 2018-05-20 10:05 10 | */ 11 | public class GetNextTreeNode { 12 | 13 | /** 14 | * 中序遍历是指从先遍历左子树的节点-根节点-右子树的节点,每颗子树后面遍历顺序一致 15 | * 16 | * (1) 若该节点存在右子树:则下一个节点为右子树最左子节点 17 | * (2)若没有右子树 18 | * 19 | * @param pNode 节点 20 | * @return 21 | */ 22 | public TreeLinkNode GetNext(TreeLinkNode pNode) { 23 | if (pNode == null) { 24 | return null; 25 | } 26 | // 节点有右子树 下一个节点为右子树最左子节点 27 | if (pNode.right != null) { 28 | pNode = pNode.right; 29 | while (pNode.left != null) { 30 | pNode = pNode.left; 31 | } 32 | return pNode; 33 | } 34 | // 节点不是根节点。如果该节点是其父节点的左孩子,则返回父节点; 35 | // 否则继续向上遍历其父节点的父节点,重复之前的判断,返回结果。 36 | while (pNode.next != null) { 37 | if (pNode == pNode.next.left) { 38 | return pNode.next; 39 | } 40 | pNode = pNode.next; 41 | } 42 | return null; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/GetUglyNumber_Solution.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * 丑数 7 | * 8 | * @author : Administrator 9 | * @subject : 把只包含因子2、3和5的数称作丑数(Ugly Number)。 10 | * 例如6、8 都是丑数,但 14 不是,因为它包含因子7。 11 | * 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。 12 | * @create 2018-03-26 15:42 13 | */ 14 | public class GetUglyNumber_Solution { 15 | 16 | /** 17 | * 丑数解决--办法 18 | * @param index 数组 19 | * @return 数字 20 | */ 21 | public int GetUglyNumber_Solution(int index) { 22 | if (index <= 0) { 23 | return 0; 24 | } 25 | ArrayList list = new ArrayList<>(); 26 | // add 进第一个丑数 27 | list.add(1); 28 | // 三个下标用来记录丑数的位置 29 | int i2 = 0, i3 = 0, i5 = 0; 30 | while (list.size() < index) { 31 | // 三个数都是可能的丑数,取最小的放进丑数数组里面 32 | int n2 = list.get(i2) * 2; 33 | int n3 = list.get(i3) * 3; 34 | int n5 = list.get(i5) * 5; 35 | int min = Math.min(n2, Math.min(n3,n5)); 36 | list.add(min); 37 | if (min == n2) 38 | i2++; 39 | if (min == n3) { 40 | i3++; 41 | } 42 | if (min == n5) { 43 | i5++; 44 | } 45 | } 46 | return list.get(list.size() - 1); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/HasSubtree.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.TreeNode; 4 | 5 | /** 6 | * 树的子结构 7 | * 8 | * @author : Administrator 9 | * @create 2018-03-15 13:16 10 | * @subject 输入两棵二叉树A,B,判断B是不是A的子结构(ps:我们约定空树不是任意一个树的子结构),树的子结构 11 | */ 12 | public class HasSubtree { 13 | 14 | /** 15 | * 分两步,第一步在树A中查找与该根节点一样的值的节点R,第二步再来判断树A之中,以R为根节点的子树是否包含和根节点一样的结构 16 | * 17 | * @param root1 18 | * @param root2 19 | * @return boolean 20 | */ 21 | private boolean HasSubtreeInBinaryTree(TreeNode root1, TreeNode root2) { 22 | boolean result = false; 23 | if (root1 != null && root2 != null) { 24 | if (root1.val == root2.val) { 25 | result = doesTree1HaveTree2(root1, root2); 26 | } 27 | if (!result) { 28 | result = HasSubtreeInBinaryTree(root1.left, root2); 29 | } 30 | if (!result) { 31 | result = HasSubtreeInBinaryTree(root1.right, root2); 32 | } 33 | } 34 | return result; 35 | } 36 | 37 | /** 38 | * 辅助函数,判断传入的root1 是否包含root2 39 | * 40 | * @param root1 41 | * @param root2 42 | * @return boolean 43 | */ 44 | private boolean doesTree1HaveTree2(TreeNode root1, TreeNode root2) { 45 | if (root2 == null) { 46 | return true; 47 | } 48 | 49 | if (root1 == null) { 50 | return false; 51 | } 52 | 53 | if (root1.val != root2.val) { 54 | return false; 55 | } 56 | 57 | return doesTree1HaveTree2(root1.left, root2.left) && doesTree1HaveTree2(root1.right, root2.right); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/InversePairs.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | /** 4 | * @author : Administrator 5 | * @subject : 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。 6 | * 输入一个数组,求出这个数组中的逆序对的总数P。 7 | * 并将P对 1000000007 取模的结果输出。 即输出 P%1000000007 8 | * @example: 题目保证输入的数组中没有的相同的数字 9 | 数据范围: 10 | 对于%50的数据, size <= 10^4 11 | 对于%75的数据, size <= 10^5 12 | 对于%100的数据, size <= 2*10^5 13 | * @create 2018-04-05 20:23 14 | */ 15 | public class InversePairs { 16 | 17 | int count = 0; 18 | 19 | public int InversePairs(int [] array) { 20 | if (array == null || array.length == 0) { 21 | return 0; 22 | } 23 | mergeSort(array, 0, array.length - 1); 24 | return count; 25 | } 26 | 27 | private void mergeSort(int[] array, int start, int end) { 28 | if (start < end) { 29 | int mid = (start + end) >> 1; 30 | mergeSort(array, start, mid); 31 | mergeSort(array, mid + 1, end); 32 | merge(array, start,mid,end); 33 | } 34 | } 35 | 36 | /** 37 | * 将一个数组中的两个相邻有序区间合并成一个 38 | * @param array 39 | */ 40 | private void merge(int[] array, int start, int mid ,int end) { 41 | int[] temp = new int[end - start + 1]; 42 | int i = start, j = mid + 1, k = 0; 43 | while (i <= mid && j <= end) { 44 | if (array[i] <= array[j]) { 45 | temp[k++] = array[i++]; 46 | } else { 47 | temp[k++] = array[j++]; 48 | count += mid - i + 1; 49 | count %= 1000000007; 50 | } 51 | } 52 | 53 | while (i <= mid) { 54 | temp[k++] = array[i++]; 55 | } 56 | while (j <= end) { 57 | temp[k++] = array[j++]; 58 | } 59 | for (int l = 0; l < temp.length; l++) { 60 | array[start + l] = temp[l]; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/IsBalanced_Solution.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.TreeNode; 4 | 5 | /** 6 | * 输入一棵二叉树,判断该二叉树是否是平衡二叉树。 7 | * 8 | * @author : Administrator 9 | * @subject : 输入一颗二叉树的根节点,判断该数是不是平衡二叉树,如果某二叉树中任意 10 | * 节点的左右字数的深度不超过1,则此为一颗平衡二叉数。 11 | * @create 2018-04-22 14:58 12 | */ 13 | public class IsBalanced_Solution { 14 | 15 | public boolean isbalanceTree(TreeNode root) { 16 | return getBalancedDepth(root) != -1; 17 | } 18 | 19 | /** 20 | * 如果二叉树每个节点的左字数和右子树的深度不大于1,它就是平衡二叉树 21 | * 直接利用左子树减去右子树取绝对值,值大于1整颗树都不为平衡二叉树赋值为-1, 22 | * 否则这颗树的深度就是左右子树的深度的最大值再加1(其本身根节点) 23 | * @param root 24 | * @return 25 | */ 26 | private int getBalancedDepth(TreeNode root) { 27 | if (root == null) { 28 | return 0; 29 | } 30 | int left = getBalancedDepth(root.left); 31 | int right = getBalancedDepth(root.right); 32 | if (left == -1) { 33 | return -1; 34 | } 35 | if (right == -1) { 36 | return -1; 37 | } 38 | return Math.abs(left - right) > 1 ? -1 : 1 + Math.max(left, right); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/IsContinuous.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * 扑克牌的顺子 7 | * 8 | * @author : Administrator 9 | * @subject : 从扑克牌中随机抽5张牌, 判断是不是一个顺子,既这5张牌是不是连续的。 10 | * 其中:2~10 为数字的本身,A为1,J为11, Q为12,K为13,然而大王和小王可以看成是任意的数字 11 | * @create 2018-04-24 14:59 12 | */ 13 | public class IsContinuous { 14 | 15 | /** 16 | * 满足5张牌是否为顺子的几个条件 17 | * 1. 数组的长度必须为5 18 | * 2. 数组中除了0之外,没有其他的重复的数字(或者说是牌) 19 | * 3. 这个数组中的最大值-最小值 < 5 20 | * @param numbers 21 | * @return 22 | */ 23 | public boolean isContinuous(int [] numbers) { 24 | if (numbers.length < 5) { 25 | return false; 26 | } 27 | int numOfZero = 0; 28 | int numOfInterval = 0; 29 | Arrays.sort(numbers); 30 | for (int num : numbers) { 31 | if (num == 0) { 32 | numOfZero++; 33 | } 34 | } 35 | for (int i = numOfZero; i < numbers.length - 1; i++) { 36 | // 出现非零的重复的数字就false 37 | if (numbers[i] != 0 && numbers[i] == numbers[i + 1]) { 38 | return false; 39 | } 40 | // 得到相邻数字中的间隔的位置 41 | numOfInterval += numbers[i + 1] - numbers[i] - 1; 42 | } 43 | System.out.println(numOfZero); 44 | System.out.println(numOfInterval); 45 | if (numOfZero >= numOfInterval) { 46 | return true; 47 | } 48 | return false; 49 | } 50 | 51 | public static void main(String[] args) { 52 | int[] array = {0, 0, 2, 4, 6}; 53 | int[] array2 = {0, 0, 2, 3, 4,7}; 54 | int[] array3 = {0, 0, 2, 3, 5}; 55 | int[] array4 = {0, 3, 2, 6, 4}; 56 | // System.out.println(new IsContinuous().isContinuous(array)); 57 | // System.out.println(new IsContinuous().isContinuous(array2)); 58 | // System.out.println(new IsContinuous().isContinuous(array3)); 59 | System.out.println(new IsContinuous().isContinuous(array4)); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/IsPopOrder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: IsPopOrder 4 | * Author: Administrator 5 | * Date: 2017/11/16 0016 19:46 6 | * Description: IsPopOrder 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | import java.util.Stack; 12 | 13 | /** 14 | * 〈一句话功能简述〉
15 | * 〈剑指offer---IsPopOrder〉 16 | * 17 | * @author Administrator 18 | * @create 2017/11/16 0016 19 | * @subject 1. 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。 20 | * 假设压入栈的所有数字均不相等。 21 | * 例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列, 22 | * 但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的) 23 | * 2. 时间限制:1秒 空间限制:32768K 24 | * @Strategies 25 | 借用一个辅助的栈,遍历压栈顺序,先讲第一个放入栈中, 26 | 直到相等以后开始出栈,出栈一个元素,则将出栈顺序向后移动一位,直到不相等, 27 | 这样循环等压栈顺序遍历完成,如果辅助栈还不为空,说明弹出序列不是该栈的弹出顺序 28 | * @since 1.0.0 29 | */ 30 | public class IsPopOrder { 31 | 32 | public boolean isPopOrder(int[] pushA, int[] popA) { 33 | 34 | if (pushA.length == 0 || popA.length == 0) 35 | return false; 36 | Stack stack = new Stack<>(); 37 | // //用于标识弹出序列的索引值 38 | int j = 0; 39 | for (int i = 0; i <=pushA.length -1; i++) { 40 | stack.push(pushA[i]); 41 | while (!stack.empty() && stack.peek() == popA[j]) { 42 | //出栈 43 | stack.pop(); 44 | // 索引后移一位 45 | j++; 46 | } 47 | } 48 | return stack.empty(); 49 | } 50 | 51 | public static void main(String[] args) { 52 | int[] pushA = {1, 2, 3, 4, 5}; 53 | int[] popA = { 3, 4, 5, 2, 1}; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/IsSymmetrical.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.TreeNode; 4 | 5 | /** 6 | * 对称的二叉树 7 | * 8 | * @author : Administrator 9 | * @create 2018-07-01 16:43 10 | * @subject : 11 | * 请实现一个函数,用来判断一颗二叉树是不是对称的。 12 | * 注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。 13 | */ 14 | public class IsSymmetrical { 15 | 16 | /** 17 | * 符合递归的信息来看应该满足以下的结果: 18 | * 1. 根节点相同,根节点的左子树的左节点和右子树的右节点相同 19 | * 2. 左子树的右结点和右子树的左结点相同 20 | * 3. 递归循环即可 21 | * @param pRoot 22 | * @return 23 | */ 24 | public boolean check(TreeNode pRoot) { 25 | if (pRoot == null) { 26 | return true; 27 | } 28 | return checkChildTree(pRoot.left, pRoot.right); 29 | } 30 | 31 | /** 32 | * 递归判断左子树和右子树 33 | * @param nodeLeft 34 | * @param nodeRight 35 | * @return 36 | */ 37 | private boolean checkChildTree(TreeNode nodeLeft, TreeNode nodeRight) { 38 | // 左节点为空,则右节点必须为空 39 | if (nodeLeft == null) { 40 | return nodeRight == null; 41 | } 42 | // 左节点不为空,右节点为空,不为镜像二叉树 43 | if (nodeRight == null) { 44 | return false; 45 | } 46 | // 如果左右节点不相等错误 47 | // (此时的左右节点应该赋值为左子树的左节点和右子树的右节点 48 | // 或者 左子树的右结点和右子树的左结点) 49 | if (nodeLeft.val != nodeRight.val) { 50 | return false; 51 | } 52 | return checkChildTree(nodeLeft.left, nodeRight.right) && checkChildTree(nodeLeft.right, nodeRight.left); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/JumpSteps.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: JumpSteps 4 | * Author: Administrator 5 | * Date: 2017/11/20 0020 21:43 6 | * Description: 跳台阶 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈跳台阶 〉 14 | *@subject 一只青蛙一次可以跳上1级台阶,也可以跳上2级。 15 | * 求该青蛙跳上一个n级的台阶总共有多少种跳法。 16 | * 17 | * @Strategies 18 | 对于本题,前提只有 一次 1阶或者2阶的跳法。 19 | a.如果两种跳法,1阶或者2阶,那么假定第一次跳的是一阶,那么剩下的是n-1个台阶,跳法是f(n-1); 20 | b.假定第一次跳的是2阶,那么剩下的是n-2个台阶,跳法是f(n-2) 21 | c.由a\b假设可以得出总跳法为: f(n) = f(n-1) + f(n-2)  22 | d.然后通过实际的情况可以得出:只有一阶的时候 f(1) = 1 ,只有两阶的时候可以有 f(2) = 2 23 | e.可以发现最终得出的是一个斐波那契数列: 24 | * @author Administrator 25 | * @create 2017/11/20 0020 26 | * @since 1.0.0 27 | */ 28 | public class JumpSteps { 29 | private static int jumpFloor(int target) { 30 | if (target <= 2) 31 | return target; 32 | int numFn1 = 1, numFn2 = 2, currentNum = 0; 33 | for (int i = 3; i <= target ; i++) { 34 | currentNum = numFn1 + numFn2; 35 | numFn1 = numFn2; 36 | numFn2 = currentNum; 37 | } 38 | return currentNum; 39 | } 40 | 41 | public static void main(String[] args) { 42 | System.out.println(JumpSteps.jumpFloor(30)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/JumpStepsII.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: JumpStepsII 4 | * Author: Administrator 5 | * Date: 2017/11/20 0020 22:02 6 | * Description: 跳台阶2 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈跳台阶2〉 14 | *@subject 一只青蛙一次可以跳上 1 级台阶,也可以跳上 2 级……它也可以跳上 n 级台阶。 15 | * 求该青蛙跳上一个 n 级的台阶总共有多少种跳法 16 | * @Strategies 17 | 因为n级台阶,第一步有n种跳法:跳1级、跳2级、到跳n级 18 | 跳1级,剩下n-1级,则剩下跳法是f(n-1) 19 | 跳2级,剩下n-2级,则剩下跳法是f(n-2) 20 | 所以f(n)=f(n-1)+f(n-2)+...+f(1) 21 | 因为f(n-1)=f(n-2)+f(n-3)+...+f(1) 22 | 所以 f(n) = 1 (n = 1) 23 | 2*f(n-1) (n >= 2) 24 | * @author Administrator 25 | * @create 2017/11/20 0020 26 | * @since 1.0.0 27 | */ 28 | public class JumpStepsII { 29 | private static int jump(int target) { 30 | if (target <= 0) 31 | return -1; 32 | else if (target == 1) 33 | return 1; 34 | else 35 | return 2 * jump(target - 1); 36 | } 37 | 38 | private static int jump2(int target) { 39 | if (target <= 0) 40 | return -1; 41 | else 42 | return 1 << (target - 1); // 位移运算 等效为 (int) Math.pow(2, target - 1); 43 | } 44 | 45 | public static void main(String[] args) { 46 | System.out.println(JumpStepsII.jump(4)); 47 | System.out.println(JumpStepsII.jump2(8)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/LastRemaining_Solution.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | /** 4 | * 将0,1,..,n-1这n个数拍成一个圆圈,从数字0开始每次从这个园区里删除第m个数字。求出这个圆圈中剩下的最后一个数字 5 | * 6 | * @author : Administrator 7 | * @Subject: 将0,1,..,n-1这n个数拍成一个圆圈,从数字0开始每次从这个园区里删除第m个数字。 8 | * 求出这个圆圈中剩下的最后一个数字 9 | * @create 2018-04-24 16:39 10 | */ 11 | public class LastRemaining_Solution { 12 | 13 | /** 14 | * 约瑟夫环的问题(Josephuse)环的问题 15 | * @param n 总共为n个数字 16 | * @param m 每次删除第m个数字 17 | * @return 18 | */ 19 | public int lastRemaining_Solution(int n, int m) { 20 | if (n < 1 || m < 1) { 21 | return -1; 22 | } 23 | int[] array = new int[n]; 24 | int i = -1, step = 0, count = n; 25 | while (count > 0) { 26 | i++; 27 | if (i >= n) 28 | i = 0; 29 | if (array[i] == -1) 30 | continue; 31 | step++; 32 | if (step == m) { 33 | array[i] = -1; 34 | step = 0; 35 | count--; 36 | } 37 | } 38 | return i; 39 | } 40 | 41 | public static void main(String[] args) { 42 | System.out.println(new LastRemaining_Solution().lastRemaining_Solution(33,3)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/LeftRotateString.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | /** 4 | * 左旋字符串的操作 5 | * 6 | * @author : Administrator 7 | * @Subject: 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部, 8 | * 定义一个函数实现字符串左旋转操作的功能。比如输入字符串“abcdefg"和数字2, 9 | * 该函数将返回左旋转2位得到的操作”cdefgab" 10 | * @create 2018-04-24 11:19 11 | */ 12 | public class LeftRotateString { 13 | 14 | public String leftRotateString(String str,int n) { 15 | if (n > str.length()) { 16 | return ""; 17 | } 18 | String s1 = str.substring(0, n); 19 | String s2 = str.substring(n, str.length()); 20 | return s2 + s1; 21 | } 22 | 23 | public static void main(String[] args) { 24 | System.out.println(new LeftRotateString().leftRotateString("abcdefg", 2)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/ListNodeMerge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2018 3 | * FileName: ListNodeMerge 4 | * Author: Administrator 5 | * Date: 2018/3/9 0009 22:15 6 | * Description: 合并两个排序的列表 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈合并两个排序的列表〉 14 | * 15 | * @author Administrator 16 | * @create 2018/3/9 0009 17 | * @subject 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。 18 | * @example 链表1 : 1->3->5->7  链表2 : 2->4->6->8 19 | * 合并之后为: 1->2->3->4->5->6->7->8 20 | * @Strategies 21 | * @since 1.0.0 22 | */ 23 | public class ListNodeMerge { 24 | 25 | private class ListNode { 26 | int val; 27 | ListNode next = null; 28 | 29 | ListNode(int val) { 30 | this.val = val; 31 | } 32 | } 33 | 34 | /** 35 | * 利用递归来做,每次需要比较两条链表的头节点,小的放入归并之后的头节点,之后使用递归继续剩下的值和剩下的链表上的值 36 | * @param list1 链表1 37 | * @param list2 链表2 38 | * @return ListNode 39 | */ 40 | public ListNode Merge(ListNode list1, ListNode list2) { 41 | if (list1 == null) { 42 | return list2; 43 | } 44 | if (list2 == null) 45 | return list1; 46 | ListNode MergeHead = null; 47 | if (list1.val < list2.val) { 48 | MergeHead = list1; 49 | MergeHead.next = Merge(list1.next, list2); 50 | } else { 51 | MergeHead = list2; 52 | MergeHead.next = Merge(list1, list2.next); 53 | } 54 | 55 | return MergeHead; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/MatrxPath.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | /** 4 | * 矩阵中的路径 5 | * 6 | * @author : Administrator 7 | * @create 2018-08-23 11:37 8 | * @subject : 9 | * 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。 10 | * 路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。 11 | * 如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 12 | * 例如 a b c e s f c s a d e e 13 | * 这样的3 X 4 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径 14 | * ,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。 15 | */ 16 | public class MatrxPath { 17 | 18 | // 测试矩阵案例 19 | public boolean hasPath(char[] matrix, int rows, int cols, char[] str) { 20 | int flag[] = new int[matrix.length]; 21 | for (int i = 0; i < rows; i++) { 22 | for (int j = 0; j < cols; j++) { 23 | if (helper(matrix, rows, cols, i, j, str, 0, flag)) 24 | return true; 25 | } 26 | } 27 | return false; 28 | } 29 | 30 | private boolean helper(char[] matrix, int rows, int cols, int i, int j, char[] str, int k, int[] flag) { 31 | int index = i * cols + j; 32 | if (i < 0 || i >= rows || j < 0 || j >= cols || matrix[index] != str[k] || flag[index] == 1) 33 | return false; 34 | if(k == str.length - 1) return true; 35 | flag[index] = 1; 36 | if (helper(matrix, rows, cols, i - 1, j, str, k + 1, flag) 37 | || helper(matrix, rows, cols, i + 1, j, str, k + 1, flag) 38 | || helper(matrix, rows, cols, i, j - 1, str, k + 1, flag) 39 | || helper(matrix, rows, cols, i, j + 1, str, k + 1, flag)) { 40 | return true; 41 | } 42 | flag[index] = 0; 43 | return false; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/MiddleNumberInDataFlow.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import java.util.LinkedList; 4 | 5 | /** 6 | * 数据流中的中位数 7 | * 8 | * @author : Administrator 9 | * @create 2018-08-22 20:49 10 | * @subject : 11 | * 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。 12 | * 如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。 13 | * 我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。 14 | */ 15 | public class MiddleNumberInDataFlow { 16 | 17 | private LinkedList list = new LinkedList<>(); 18 | 19 | /** 20 | * 将数据插入到linkList 21 | * @param num 22 | */ 23 | public void insert(Integer num) { 24 | if (list.isEmpty() || num < list.getFirst()) { 25 | list.addFirst(num); 26 | } else { 27 | boolean isInsertSuccess = false; 28 | for (Integer i : list) { 29 | if (num < i) { 30 | int index = list.indexOf(i); 31 | list.add(index, num); 32 | isInsertSuccess = true; 33 | break; 34 | } 35 | } 36 | if (!isInsertSuccess) { 37 | list.addLast(num); 38 | } 39 | } 40 | } 41 | 42 | public Double GetMedian() { 43 | if(list.isEmpty()) { 44 | return null; 45 | } 46 | 47 | int mid = list.size() / 2; 48 | 49 | // 如果长度是偶数 50 | if((list.size() & 1) == 0) { 51 | Integer first = list.get(mid - 1); 52 | Integer second = list.get(mid); 53 | return Double.valueOf(first + second) / 2.0; 54 | } 55 | 56 | return Double.valueOf(list.get(mid)); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/MinNumberInRotateArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: MinNumberInRotateArray 4 | * Author: Administrator 5 | * Date: 2017/11/19 0019 20:09 6 | * Description: 旋转数组的最小数字 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈旋转数组的最小数字〉 14 | * 15 | * @author Administrator 16 | * @subject 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 17 | * 输入一个非递减排序(递增)的数组的一个旋转,输出旋转数组的最小元素。 18 | * 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 19 | * NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。 20 | * @create 2017/11/19 0019 21 | * @since 1.0.0 22 | */ 23 | public class MinNumberInRotateArray { 24 | private static int minNumberInRotateArray(int[] array) { 25 | if (array.length == 0) 26 | return 0; 27 | for (int anArray : array) { 28 | if (anArray < 0) 29 | return -1; 30 | } 31 | int low = 0; 32 | int high = array.length - 1; 33 | while (low < high) { 34 | int mid = low + (high - low) / 2; 35 | if (array[mid] > array[high]) 36 | low = mid + 1; 37 | else if (array[mid] == array[high]) 38 | high--; 39 | else 40 | high = mid; 41 | } 42 | return array[low]; 43 | } 44 | 45 | public static void main(String[] args) { 46 | int[] arr = {3, 4, 5, 1, 2}; 47 | int[] arr1 = {1, 0, 1, 1, 1}; 48 | int[] arr2 = {1, 1, 1, 0, 1}; 49 | System.out.println(MinNumberInRotateArray.minNumberInRotateArray(arr)); 50 | System.out.println(MinNumberInRotateArray.minNumberInRotateArray(arr1)); 51 | System.out.println(MinNumberInRotateArray.minNumberInRotateArray(arr2)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/MirrorBinaryTree.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.TreeNode; 4 | 5 | /** 6 | * 二叉树的镜像 7 | * 8 | * @author : Administrator 9 | * @subject: 操作给定的二叉树,将其变换为源二叉树的镜像 10 | * @create 2018-03-15 16:54 11 | */ 12 | public class MirrorBinaryTree { 13 | 14 | /** 15 | * 先前序遍历这颗树的每个节点,如果遍历到的结点有子节点,就交换它的两个子结点 16 | * 交换了完了所有的非叶子节点的左右子节点之后,得到镜像 17 | * 18 | * @param root 19 | */ 20 | private void Mirror(TreeNode root) { 21 | if (root == null) { 22 | return; 23 | } 24 | 25 | if (root.left == null && root.right == null) { 26 | return; 27 | } 28 | 29 | TreeNode temp = root.left; 30 | root.left = root.right; 31 | root.right = temp; 32 | // 交换根节点的左右子节点 33 | if (root.left != null) { 34 | Mirror(root.left); 35 | } 36 | if (root.right != null) { 37 | Mirror(root.right); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/MoreThanHalfNum_Solution.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 数组中出现次数超过一半的个数 8 | * 9 | * @author : Administrator 10 | * @subject : 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 11 | * 例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。 12 | * 由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出 0。 13 | * @create 2018-03-19 21:23 14 | */ 15 | public class MoreThanHalfNum_Solution { 16 | 17 | /** 18 | * 方法1:使用hashMap来使用,具体的做法是遍历数组,将其放到集合之中,存在则count++ 19 | * 然后遍历Map ,判断count的数量比数组的中间值还要大的极为所求的 20 | * @param array 21 | * @return 22 | */ 23 | public int MoreThanHalfNum(int[] array) { 24 | if (array.length == 0) { 25 | return 0; 26 | } 27 | HashMap map = new HashMap<>(); 28 | for (int anArray : array) { 29 | if (!map.containsKey(anArray)) { 30 | map.put(anArray, 1); 31 | } else { 32 | int count = map.get(anArray); 33 | map.put(anArray, ++count); 34 | } 35 | } 36 | for (Map.Entry entry : map.entrySet()) { 37 | int key = entry.getKey(); 38 | int count = entry.getValue(); 39 | if (count > (array.length >> 1)) { 40 | return key; 41 | } 42 | } 43 | return 0; 44 | } 45 | 46 | public static void main(String[] args) { 47 | int[] array = {1, 2, 3, 2, 2, 2, 5, 4, 2}; 48 | MoreThanHalfNum_Solution ms = new MoreThanHalfNum_Solution(); 49 | System.out.println(ms.MoreThanHalfNum(array)); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/MultiplyArray.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | /** 4 | * 乘积数组 5 | * 6 | * @author : Administrator 7 | * @Subject: 给定一个数组A【0,1,。。。。,n - 1】,请构建一个数组B【0,1,。。。,n - 1】 8 | * 其中B的元素B[i] = A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1] 9 | * 不允许使用除法 10 | * @example: 11 | * B0 1 A1 A2 --- A(n-2) A(n -1) 12 | * B1 A0 1 A2 --- A(n-2) A(n -1) 13 | * B2 A0 A1 1 ----- A(n-2) A(n -1) 14 | * ___ A0 A1 ---- 1 A(n-2) A(n -1) 15 | * B(n-2) A0 A1 ---- A(n-3) 1 A(n -1) 16 | * B(n-1) A0 A1 ---- A(n-3) A(n-2) 1 17 | * @create 2018-05-11 10:23 18 | */ 19 | public class MultiplyArray { 20 | 21 | /** 22 | * B[i] 的值可以看作矩阵中每行的乘积数目 23 | * @param A 24 | * @return 25 | */ 26 | public int[] mutiply(int[] A) { 27 | int length = A.length; 28 | int[] B = new int[length]; 29 | if (length != 0) { 30 | B[0] = 1; 31 | // 首先计算,下三角形的连乘 32 | for (int i = 1; i < length; i++) { 33 | B[i] = B[i - 1] * A[i - 1]; 34 | } 35 | int temp = 1; 36 | // 再来计算上三角形 37 | for (int j = length - 2; j >= 0 ; j--) { 38 | temp *= A[j + 1]; 39 | B[j] *= temp; 40 | } 41 | } 42 | return B; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/NextTreeNode.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.TreeLinkNode; 4 | 5 | /** 6 | * @author : Administrator 7 | * @create 2018-06-30 17:01 8 | * @subject :给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。 9 | * 注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。 10 | */ 11 | public class NextTreeNode { 12 | 13 | /** 14 | * (1) 若该节点存在右子树:则下一个节点为右子树最左子节点(如图节点 B ) 15 | * (2) 若该节点不存在右子树:这时分两种情况: 16 | * 2.1 该节点为父节点的左子节点,则下一个节点为其父节点 17 | * 2.2 该节点为父节点的右子节点,则沿着父节点向上遍历,知道找到一个节点的父节点的左子节点为该节点,则该节点的父节点下一个节点 18 | * @param pNode 19 | * @return 20 | */ 21 | public TreeLinkNode GetNext(TreeLinkNode pNode) { 22 | if (pNode == null) { 23 | return null; 24 | } 25 | // 节点有右子树 下一个节点为右子树最左子节点 26 | if (pNode.right != null) { 27 | pNode = pNode.right; 28 | while (pNode.left != null) { 29 | pNode = pNode.left; 30 | } 31 | return pNode; 32 | } 33 | // 节点不是根节点。如果该节点是其父节点的左孩子,则返回父节点; 34 | // 否则继续向上遍历其父节点的父节点,重复之前的判断,返回结果。 35 | while (pNode.next != null) { 36 | if (pNode == pNode.next.left) { 37 | return pNode.next; 38 | } 39 | pNode = pNode.next; 40 | } 41 | return null; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/NumberOf1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: NumberOf1 4 | * Author: Administrator 5 | * Date: 2017/11/21 0021 22:07 6 | * Description: 二进制中一的个数 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈二进制中一的个数〉 14 | *@subject 输入一个整数,输出该数二进制表示中1的个数。 15 | * 其中负数用补码表示。 16 | * 例如把 9 表示成二进制 是1001,有两位是 1。因此如果输入 9 ,该函数输出 2 17 | * @Strategies 18 | * 本题考察位运算和二进制 19 | * 20 | * @author Administrator 21 | * @create 2017/11/21 0021 22 | * @since 1.0.0 23 | */ 24 | public class NumberOf1 { 25 | 26 | /** 27 | * 如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0, 28 | * 原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。 29 | * 举例子: 30 | * 一个二进制数1100,从右边数起第三位是处于最右边的一个1。 31 | * 减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011. 32 | * 我们发现减1的结果是把最右边的一个1开始的所有位都取反了,这个时候如果我们再把原来的整数和减去1之后的结果做与运算, 33 | * 从原来整数最右边一个1那一位开始所有位都会变成0,如1100 & 1011 = 1000 34 | * .也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0. 35 | * 那么一个整数的二进制有多少个1,就可以进行多少次这样的操作 36 | */ 37 | private static int replace2(int n) { 38 | int count = 0; 39 | while (n!= 0) { 40 | count++; 41 | n = n & (n - 1); 42 | } 43 | return count; 44 | } 45 | 46 | /** 47 | * 调用系统的API来求解,利用toBinaryString 转化为二进制字符串,利用replaceAll替换掉所有的零 48 | * 然后求出其长度。 49 | */ 50 | private static int replace(int n) { 51 | return Integer.toBinaryString(n).replaceAll("0","").length(); 52 | } 53 | 54 | public static void main(String[] args) { 55 | System.out.println(NumberOf1.replace(9)); 56 | System.out.println(NumberOf1.replace2(9)); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/NumberOf1Between1AndN_Solution.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | /** 4 | * 整数中1出现的个数 5 | * 6 | * @author : Administrator 7 | * @subject : 输入一个整数,求从1 到 N 中,这n个正整数的十进制中表示 1 出现的次数 8 | * 例如输入 12, 从1 到12 之中这些整数包含了1 的数字有 1,10,11(两个1),12 所以总共是5次 9 | * @create 2018-03-24 21:07 10 | */ 11 | public class NumberOf1Between1AndN_Solution { 12 | 13 | 14 | /** 15 | * 方法1:逐渐逐一考察 1~n 的每一个数里有多少个1,用数 % 10 来判断是否此为数字上有1 的个数,用num 16 | * 每次循环之后会/10 ,退到下一子位。分别从千-百-十等位数来考察 17 | * @param n 18 | * @return 19 | */ 20 | public static int NumberOf_solutions(int n) { 21 | if (n < 1) { 22 | return 0; 23 | } 24 | 25 | int count = 0; 26 | for (int i = 1; i <= n; i++) { 27 | count += getSingleNumbOf1(i); 28 | } 29 | return count; 30 | } 31 | 32 | private static int getSingleNumbOf1(int num) { 33 | int res = 0; 34 | while (num != 0) { 35 | if (num % 10 == 1) { 36 | res++; 37 | } 38 | num = num / 10; 39 | } 40 | return res; 41 | } 42 | 43 | public static void main(String[] args) { 44 | System.out.println(NumberOf_solutions(12)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/PermutationList.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | 8 | /** 9 | * 字符串的排序 10 | * 11 | * @author : Administrator 12 | * @subject : 输入一个字符串,按字典序打印出该字符串中字符的所有排列。 13 | * 例如输入字符串 abc,则打印出由字符 a, b ,c 所能排列出来的所有字符串 abc, acb , bac , bca, cab 和 cba。 14 | * @required: 输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。 15 | * @create 2018-03-19 18:18 16 | */ 17 | public class PermutationList { 18 | 19 | /** 20 | * 21 | * @param str 22 | * @return ArrayList 23 | */ 24 | public static ArrayList Permutation(String str) { 25 | ArrayList list = new ArrayList<>(); 26 | if (str != null && str.length() > 0) { 27 | PermutationHelper(str.toCharArray(), 0, list); 28 | Collections.sort(list); 29 | } 30 | return list; 31 | } 32 | 33 | /** 34 | * 35 | * @param chars 36 | * @param i 37 | * @param list 38 | */ 39 | private static void PermutationHelper(char[] chars, int i, ArrayList list) { 40 | // 如果给定的i的值是恰好是最大长度,则添加到集合中,注意强转 41 | if (i == chars.length - 1) { 42 | list.add(String.valueOf(chars)); 43 | } else { 44 | Set charSet = new HashSet<>(); 45 | for (int j = i; j < chars.length; j++) { 46 | if (j == i || !charSet.contains(chars[j])) { 47 | charSet.add(chars[j]); 48 | swap(chars, i, j); 49 | PermutationHelper(chars, i + 1, list); 50 | swap(chars, j, i); 51 | } 52 | } 53 | } 54 | } 55 | 56 | 57 | /** 58 | * 辅助交换函数 59 | * @param chars 60 | * @param i i 索引 61 | * @param j j 索引 62 | */ 63 | private static void swap(char[] chars, int i, int j) { 64 | char temp = chars[i]; 65 | chars[i] = chars[j]; 66 | chars[j] = temp; 67 | } 68 | 69 | public static void main(String[] args) { 70 | String str = "abb"; 71 | String str2 = "abcd"; 72 | String str3 = "abca"; 73 | String str4 = "aba"; 74 | String str5 = ""; 75 | System.out.println(Permutation(str)); 76 | System.out.println(Permutation(str2)); 77 | System.out.println(Permutation(str3)); 78 | System.out.println(Permutation(str4)); 79 | System.out.println(Permutation(str5)); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/Power.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: Power 4 | * Author: Administrator 5 | * Date: 2017/11/22 0022 15:37 6 | * Description: 数值的整数次方 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈数值的整数次方〉 14 | *@subject 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。 15 | * @Strategies 16 | * 17 | * @author Administrator 18 | * @create 2017/11/22 0022 19 | * @since 1.0.0 20 | */ 21 | public class Power { 22 | 23 | 24 | private boolean invalidInput = false; 25 | /** 26 | * 1.当底数为0且指数<0时 27 | * 会出现对0求倒数的情况,需进行错误处理,设置一个全局变量; 28 | * 2.判断底数是否等于0 29 | * 由于base为double型,不能直接用==判断 30 | * 31 | */ 32 | private double pow(double base, int n) { 33 | // 当底数为0且指数<0时 , 输入不合法 34 | if (equal(base , 0.0) && n < 0) { 35 | invalidInput = true; 36 | return 0.0; 37 | } 38 | double result = 1.0; 39 | for (int i = 0; i < Math.abs(n); i++) { 40 | result *= base; 41 | } 42 | if (n < 0) 43 | result = 1 / result; 44 | return result; 45 | } 46 | 47 | private boolean equal(double num1, double num2) { 48 | return num1 - num2 > -0.00001 && num1 - num2 < 0.00001; 49 | } 50 | 51 | public static void main(String[] args) { 52 | System.out.println(new Power().pow(3.4, 5)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/PrintBinaryTreeByZ.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Stack; 7 | 8 | /** 9 | * Z字型打印二叉树 10 | * 11 | * @author : Administrator 12 | * @create 2018-07-02 10:35 13 | * @subject : 14 | * 请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印, 15 | * 第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。 16 | */ 17 | public class PrintBinaryTreeByZ { 18 | 19 | /** 20 | * 打印--就是对于一个二叉树而言: 21 | * 在奇数行是打印从左到右-- 打印 22 | * 在偶数行是从右到左打印--- 23 | * 然后利用两个栈分别存贮奇数行和偶数行的节点 24 | * @param pRoot 25 | * @return 26 | */ 27 | public ArrayList> print(TreeNode pRoot) { 28 | // 定义层级数 layer 29 | int layer = 1; 30 | // 栈1存贮奇数层节点 31 | Stack s1 = new Stack<>(); 32 | s1.push(pRoot); 33 | // s2存偶数层节点 34 | Stack s2 = new Stack<>(); 35 | ArrayList> list = new ArrayList>(); 36 | 37 | while (!s1.empty() || !s2.empty()) { 38 | // 层数是奇数 39 | if (layer % 2 != 0) { 40 | ArrayList temp = new ArrayList<>(); 41 | while (!s1.empty()) { 42 | TreeNode node = s1.pop(); 43 | if (node != null) { 44 | temp.add(node.val); 45 | System.out.print(node.val + " "); 46 | s2.push(node.left); 47 | s2.push(node.right); 48 | } 49 | } 50 | if (!temp.isEmpty()) { 51 | list.add(temp); 52 | layer++; 53 | System.out.println(); 54 | } 55 | // 层数是偶数 56 | } else { 57 | ArrayList temp = new ArrayList<>(); 58 | while (!s2.empty()) { 59 | TreeNode node = s2.pop(); 60 | if (node != null) { 61 | temp.add(node.val); 62 | System.out.println(node.val + " "); 63 | s1.push(node.right); 64 | s1.push(node.left); 65 | } 66 | } 67 | if (!temp.isEmpty()) { 68 | list.add(temp); 69 | layer++; 70 | System.out.println(); 71 | } 72 | } 73 | } 74 | return list; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/PrintBinayTreeInOrder.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | import java.util.LinkedList; 7 | import java.util.Queue; 8 | 9 | /** 10 | * 顺序打印二叉树 11 | * 12 | * @author : Administrator 13 | * @create 2018-07-02 21:03 14 | * @subject : 15 | * 从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。 16 | */ 17 | public class PrintBinayTreeInOrder { 18 | 19 | /** 20 | * 21 | * @param pRoot 22 | * @return 23 | */ 24 | public ArrayList> Print(TreeNode pRoot) { 25 | ArrayList> result = new ArrayList<>(); 26 | if (pRoot == null) { 27 | return result; 28 | } 29 | // 使用队列,先进先出 30 | Queue layer = new LinkedList<>(); 31 | // 存放每行的列表 32 | ArrayList layerList = new ArrayList<>(); 33 | layer.add(pRoot); 34 | // 记录本层打印了多少个, 记录下层打几个 35 | int start = 0, end = 1; 36 | while (!layer.isEmpty()) { 37 | TreeNode temp = layer.remove(); 38 | // 添加到本行的arrayList 39 | layerList.add(temp.val); 40 | start++; 41 | // 每打印一个节点,就把此节点的下一层的左右节点加入队列,并记录下一层要打印的个数 42 | if(temp.left!=null){ 43 | layer.add(temp.left); 44 | } 45 | if(temp.right!=null){ 46 | layer.add(temp.right); 47 | } 48 | // 判断本层打印是否完成 49 | if (start == end) { 50 | // 此时的queue中存储的都是下一层的节点,则end即为queue大小 51 | end = layer.size(); 52 | start = 0; 53 | // 把arrayList添加到结果列表arrayLists中 54 | result.add(layerList); 55 | // 重置arrayList 56 | layerList = new ArrayList(); 57 | } 58 | } 59 | return result; 60 | } 61 | 62 | private TreeNode createBinaryTreeByArray(int[] array, int index) { 63 | TreeNode tn = null; 64 | if (index < array.length) { 65 | int value = array[index]; 66 | tn = new TreeNode(value); 67 | tn.left = createBinaryTreeByArray(array, 2 * index + 1); 68 | tn.right = createBinaryTreeByArray(array, 2 * index + 2); 69 | return tn; 70 | } 71 | return tn; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/PrintFromTopToBottom.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * 从上往下打印二叉树 9 | * 10 | * @author : Administrator 11 | * @subject : 从上往下打印出二叉树的每个节点,同层节点从左至右打印。 12 | * @example :对于树: 8 13 | * 6 10 14 | * 5 7 9 11 8——>6-> 10->5->7->9->11 15 | * @create 2018-03-17 12:45 16 | */ 17 | public class PrintFromTopToBottom { 18 | 19 | /** 20 | * 考虑到可以采用队列的先进先出来实现功能 21 | * 每打印一个节点,如果该结点有子节点,则把该节点的子节点放到队列的队尾, 22 | * 接下来到队列的头部节点取出来,重复以上的打印过程 23 | * 24 | * @param root TreeNode 25 | * @return ArrayList 26 | */ 27 | public ArrayList printFromTopToBottomInBinaryTree(TreeNode root) { 28 | ArrayList list = new ArrayList<>(); 29 | ArrayList deque = new ArrayList<>(); 30 | 31 | if (root == null) { 32 | return list; 33 | } 34 | 35 | deque.add(root); 36 | while (deque.size() != 0) { 37 | TreeNode temp = deque.remove(0); // 移除索引为1 的值 38 | if (temp.left != null) { 39 | deque.add(temp.left); 40 | } 41 | if (temp.right != null) { 42 | deque.add(temp.right); 43 | } 44 | list.add(temp.val); 45 | } 46 | return list; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/PrintListFromTailToHead.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: PrintListFromTailToHead 4 | * Author: Administrator 5 | * Date: 2017/11/16 0016 22:02 6 | * Description: 输入一个链表,从尾到头打印链表每个节点的值。 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Stack; 13 | 14 | /** 15 | * 〈一句话功能简述〉
16 | * 〈输入一个链表,从尾到头打印链表每个节点的值。〉 17 | *@subject 输入一个链表,从尾到头打印链表每个节点的值 18 | * @Strategies 19 | * 思路:1. 可以借用栈的后进先出来实现 从尾到头的打印 20 | * 思路2: 使用递归来实现 21 | * @author Administrator 22 | * @create 2017/11/16 0016 23 | * @since 1.0.0 24 | */ 25 | public class PrintListFromTailToHead { 26 | 27 | private static class ListNode { 28 | int val; 29 | ListNode next = null; 30 | ListNode(int val) { 31 | this.val = val; 32 | } 33 | } 34 | 35 | private static ArrayList printList(ListNode listNode) { 36 | Stack stack = new Stack<>(); 37 | while (listNode != null) { 38 | stack.push(listNode.val); 39 | listNode = listNode.next; // 维护指针指向后一个 40 | } 41 | 42 | ArrayList list = new ArrayList<>(); 43 | while (!stack.empty()) { 44 | list.add(stack.pop()); 45 | } 46 | // System.out.println(list); 47 | return list; 48 | } 49 | 50 | private ArrayList list = new ArrayList<>(); 51 | private ArrayList printList2(ListNode listNode) { 52 | if (listNode != null) { 53 | this.printList2(listNode.next); 54 | list.add(listNode.val); 55 | } 56 | return list; 57 | } 58 | 59 | public static void main(String[] args) { 60 | ListNode node1 = new ListNode(3); 61 | ListNode node2 = new ListNode(4); 62 | ListNode node3 = new ListNode(5); 63 | ListNode node4 = new ListNode(6); 64 | node1.next = node2; 65 | node2.next = node3; 66 | node3.next = node4; 67 | printList(node1); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/PrintMatrix.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * 顺时针打印矩阵 7 | * 8 | * @author : Administrator 9 | * @subject 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字, 10 | * @expmle 例如,如果输入如下矩阵: 1 2 3 4 11 | * 5 6 7 8 12 | * 9 10 11 12 13 | * 13 14 15 16 14 | * 则依次打印出数字 1,2,3,4, 8,12,16,15,14, 13,9,5,6 ,7,11, 10. 15 | * @create 2018-03-15 22:01 16 | */ 17 | public class PrintMatrix { 18 | 19 | /** 20 | * @param matrix 21 | * @return ArrayList 22 | */ 23 | private ArrayList printMatrix(int[][] matrix) { 24 | int rows = matrix.length; 25 | int cols = matrix[0].length; 26 | ArrayList list = new ArrayList<>(); 27 | int start = 0; // start代表层数 28 | 29 | // 对于一个6 * 6的矩阵而言,最后一圈需要打印四个数字 30 | // 它的左上角坐标是(2,2),满足6 > 2 * 2 31 | while(2 * start < rows && 2 * start < cols) { // 不能写成 rows/2 的形式 32 | int endX = cols - start - 1; 33 | int endY = rows - start - 1; 34 | // 第一行是肯定要打印的 35 | for(int i = start; i <= endX; i++) { 36 | list.add(matrix[start][i]); 37 | } 38 | // 第二步的条件是终止行号大于起始行号 39 | if(start < endY) { 40 | for(int i = start + 1; i <= endY; i++) { 41 | list.add(matrix[i][endX]); 42 | } 43 | } 44 | // 第三步的条件是至少两行两列,终止行号大于起始行号 并且终止列号大于起始列号 45 | if(start < endX && start < endY) { 46 | for(int i = endX - 1; i >= start; i--) { 47 | list.add(matrix[endY][i]); 48 | } 49 | } 50 | // 第四步的条件是至少有三行两列,终止行号至少比起始行号大2,终止列号大于起始列号 51 | if(start < endX && start < endY - 1) { 52 | for(int i = endY - 1; i >= start + 1; i--) { 53 | list.add(matrix[i][start]); 54 | } 55 | } 56 | start++; // 一层一层向里打印 57 | } 58 | return list; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/PrintMinNumber.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.Comparator; 6 | 7 | /** 8 | * 把数组拍成最小的数 9 | * 10 | * @author : Administrator 11 | * @subject : 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。 12 | * 例如输入数组 {3,32,321}, 则打印出这三个数字能排成的最小数字为 321323 。 13 | * @create 2018-03-25 13:32 14 | */ 15 | public class PrintMinNumber { 16 | 17 | /** 18 | * 先对数组进行排序,对任意数字a,b,排序的规则如下: 19 | * a、b能拼接成数字ab或ba, 20 | * 如果ab <= ba, 则a排在b前面; 21 | * 如果ba < ab, 则b排在a前面; 22 | * Step2. 把排序后的数字依次打印出来,拼接数字 23 | * 排序借用Java中的Collections.sort()完成,需要自定义Comparator。排序的平均时间复杂度为O(nlogn) 24 | * 最后还需要从头遍历一遍数组,需要O(n)的时间 25 | * 因此总的时间复杂度为O(nlogn) 26 | * @param numbers 27 | * @return 28 | */ 29 | public String printMinNumber(int[] numbers) { 30 | int n; 31 | String s = ""; 32 | ArrayList list = new ArrayList<>(); 33 | for (int i = 0; i < numbers.length; i++) { 34 | list.add(numbers[i]); 35 | } 36 | Collections.sort(list, new Comparator() { 37 | @Override 38 | public int compare(Integer o1, Integer o2) { 39 | String s1 = o1 + "" + o2; 40 | String s2 = o2 + "" + o1; 41 | return s1.compareTo(s2); 42 | } 43 | }); 44 | for (int j : list) { 45 | s += j; 46 | } 47 | return s; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/RandomListNodeClone.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2018 3 | * FileName: RandomListNodeClone 4 | * Author: Administrator 5 | * Date: 2018/3/10 0010 16:42 6 | * Description: 复杂链表的复制 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈复杂链表的复制〉 14 | * 15 | * @author Administrator 16 | * @create 2018/3/10 0010 17 | * @Strategies 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点), 18 | * 返回结果为复制后复杂链表的head。 19 | * 注意,输出结果中请不要返回参数中的节点引用 20 | * @since 1.0.0 21 | */ 22 | public class RandomListNodeClone { 23 | 24 | private class RandomListNode { 25 | int label; 26 | RandomListNode next = null; 27 | RandomListNode random = null; 28 | 29 | RandomListNode(int label) { 30 | this.label = label; 31 | } 32 | } 33 | 34 | public RandomListNode clone(RandomListNode pHead) { 35 | if (pHead == null) { 36 | return null; 37 | } 38 | 39 | RandomListNode current = pHead; 40 | // 1.第一步 复制next 如原来是A->B->C 变成A->A'->B->B'->C->C' 41 | while (current != null) { 42 | RandomListNode cloneNode = new RandomListNode(current.label); // 复制值 43 | cloneNode.next = current.next; 44 | cloneNode.random = null; 45 | current.next = cloneNode; // 此三步完成了A->A'->B 后面需要将current 指向 B 46 | // 指针后移完成循环 47 | current = cloneNode.next; 48 | } 49 | 50 | current = pHead; // 重新使得现在指针指向头节点 51 | // 第二步 复制random 指针 current 是原来链表的结点 pCur.next是复制pCur的结点 52 | while (current != null) { 53 | if (current.random != null) { 54 | current.next.random = current.random.next; 55 | } 56 | current = current.next.next; // 维护指针后移 57 | } 58 | 59 | // 第三步 把这个长链表拆分成两个链表:把奇数节点链接起来为原始节点,偶数节点链接起来为克隆节点 60 | current = pHead; // 重新使得现在指针指向头节点 61 | RandomListNode cloneHead = pHead.next; 62 | RandomListNode cloneNode = cloneHead; 63 | while (current != null) { 64 | current.next = current.next.next; // 此步使得 A'->B'->C' 65 | if (cloneNode.next != null) { 66 | cloneNode.next = cloneNode.next.next; 67 | } 68 | // 上两步分别完成了两条链表,两个节点的指针指向,后面是使得其循环实现 69 | current = current.next; 70 | cloneNode = cloneNode.next; 71 | } 72 | return cloneHead; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/ReConstructBinaryTree.java: -------------------------------------------------------------------------------- 1 | 2 | package me.zonglun.SwordToOffer; 3 | 4 | import me.zonglun.SwordToOffer.util.TreeNode; 5 | 6 | /** 7 | * 〈一句话功能简述〉
8 | * 〈输入一个链表,从尾到头打印链表每个节点的值。〉 9 | * 10 | * @author Administrator 11 | * @subject 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。 12 | * 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 13 | * 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。 14 | * @Strategies 15 | * @create 2017/11/16 0016 16 | * @since 1.0.0 17 | */ 18 | public class ReConstructBinaryTree { 19 | 20 | 21 | public TreeNode reConstructionTree(int[] pre, int[] in) { 22 | return reConstructBinaryTree(pre, 0, pre.length - 1, in, 0, in.length - 1); 23 | } 24 | 25 | /** 26 | * 重建二叉树的核心函数 以一颗子树为根节点分别递归调用,重构二叉树,需要注意臂长和区间范围 27 | * @param pre 这颗子树的前序遍历 28 | * @param startPre 前序遍历中开始的节点 29 | * @param endPre 前序遍历中结束的节点 30 | * @param in 这颗子树的中序遍历 31 | * @param startIn 中序遍历中开始的节点 32 | * @param endIn 中序遍历中结束的节点 33 | * @return TreeNode 返回这颗子树的根节点 34 | */ 35 | private TreeNode reConstructBinaryTree(int[] pre, int startPre, int endPre, int[] in, int startIn, int endIn) { 36 | if (startPre > endPre || startIn > endIn) { 37 | return null; 38 | } 39 | // 找到这颗子树的根节点 40 | TreeNode root = new TreeNode(pre[startPre]); 41 | 42 | for (int i = startIn; i <= endIn; i++) { 43 | if (in[i] == pre[startPre]) { 44 | root.left = reConstructBinaryTree(pre, startPre + 1, startPre + i - startIn, in, startIn, i - 1); 45 | root.right = reConstructBinaryTree(pre, i - startIn + startPre + 1, endPre, in, i + 1, endIn); 46 | break; 47 | } 48 | } 49 | return root; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/ReOrderArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: ReOrderArray 4 | * Author: Administrator 5 | * Date: 2017/11/23 0023 22:21 6 | * Description: 调整数组顺序使得奇数位于偶数前面 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | import java.util.Arrays; 12 | 13 | /** 14 | * 〈一句话功能简述〉
15 | * 〈调整数组顺序使得奇数位于偶数前面〉 16 | * 17 | * @author Administrator 18 | * @subject 输入一个整数数组,实现一个函数来调整该数组中数字的顺序, 19 | * 使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分, 20 | * 并保证奇数和奇数,偶数和偶数之间的相对位置不变。 21 | * @create 2017/11/23 0023 22 | * @since 1.0.0 23 | */ 24 | public class ReOrderArray { 25 | 26 | /** 27 | * 要求是有序的数组 c此时的平均复杂度为o(n^2) 28 | * @param array array 29 | */ 30 | private static void reOrderArray(int[] array) { 31 | // 相对位置不变 32 | // 插入排序 33 | int count = 0; // count 是用来记录已经摆好位置的奇数的个数 34 | for (int i = 0; i < array.length; i++) { 35 | if (array[i] % 2 == 1) { 36 | int j = i; 37 | while (j > count) { // 当前奇数的索引与count比较,比count小则证明已经排队好了,不用再比较了 38 | int temp = array[j]; 39 | array[j] = array[j - 1]; 40 | array[j - 1] = temp; 41 | j--; 42 | } 43 | count++; 44 | } 45 | } 46 | } 47 | 48 | /** 49 | * 首先统计奇数的个数 50 | 然后新建一个等长数组,设置两个指针,奇数指针从0开始,偶数指针从奇数个数的末尾开始 遍历,填数 51 | * @param array 52 | */ 53 | private static void reOrderArray2(int[] array) { 54 | if (array.length == 0 || array.length == 1) { 55 | return; 56 | } 57 | int oddCount = 0, oddBegin = 0; 58 | int[] newArray = new int[array.length]; 59 | for (int i = 0; i < array.length; i++) { 60 | if (array[i] % 2 == 1) { 61 | oddCount++; // 记录原来数组中的奇数的数量 62 | } 63 | } 64 | for (int i = 0; i < array.length; i++) { 65 | if (array[i] % 2 == 1) { 66 | newArray[oddBegin++] = array[i]; 67 | } else { 68 | newArray[oddCount++] = array[i]; 69 | } 70 | } 71 | for (int i = 0; i < array.length; i++) { 72 | array[i] = newArray[i]; // 再把原数组覆盖掉 73 | } 74 | } 75 | 76 | 77 | public static void main(String[] args) { 78 | int[] arr = {1, 3, 4, 7, 8, 2, 13, 21}; 79 | // reOrderArray(arr); 80 | // System.out.println(Arrays.toString(arr)); 81 | reOrderArray2(arr); 82 | System.out.println(Arrays.toString(arr)); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/RectCover.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: RectCover 4 | * Author: Administrator 5 | * Date: 2017/11/21 0021 21:44 6 | * Description: 矩形覆盖 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | 12 | /** 13 | * 〈一句话功能简述〉
14 | * 〈矩形覆盖〉 15 | * @subject 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。 16 | * 请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 17 | * @Strategies 18 | * 其实就是一个斐波那契数列,满足公式:d(n) = d(n-1) + d(n-2) 19 | * @author Administrator 20 | * @create 2017/11/21 0021 21 | * @since 1.0.0 22 | */ 23 | public class RectCover { 24 | private static int Num(int target) { 25 | if (target < 1) 26 | return 0; 27 | else if (target <= 2) 28 | return target; 29 | else 30 | return Num(target -1) + Num(target - 2); 31 | } 32 | 33 | private static int NUm1(int target) { 34 | int tempNum = 1; 35 | int result = 2; 36 | if (target < 1) 37 | return 0; 38 | if (target == 1 || target == 2) 39 | return target; 40 | int count = 2; 41 | while (count < target) { 42 | result += tempNum; 43 | tempNum = result - tempNum; 44 | count++; 45 | } 46 | return result; 47 | } 48 | 49 | public static void main(String[] args) { 50 | System.out.println(RectCover.Num(5)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/ReplaceBlank.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: ReplaceSpace 4 | * Author: Administrator 5 | * Date: 2017/11/17 0017 19:32 6 | * Description: 替换空格 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈替换空格〉 14 | *@subject 请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy 15 | * .则经过替换之后的字符串为We%20Are%20Happy。 16 | *@Strategies 1. 使用replaceAll 的API 直接调用正则表达式来求解,但是显然不应该是算法题目要求使用的 17 | * 2. 从前往后替换,后面的字符要不断往后移动,要多次移动,所以效率低下复杂度为o(n2) 18 | 使用从后往前替换,先计算替换后的空间,使用两个指针, indexOld 为为替换前的索引,indexNew为替换后索引 19 | 两者都指向字符数组的最后一位,从后往前替换 20 | 然后从后往前移动,则每个字符只为移动一次,这样效率为o(n)更高一点 21 | * @author Administrator 22 | * @create 2017/11/17 0017 23 | * @since 1.0.0 24 | */ 25 | public class ReplaceBlank { 26 | 27 | private static String replaceBlank(StringBuffer str) { 28 | int spaceNum = 0; 29 | for (int i = 0; i < str.length(); i++) 30 | if (str.charAt(i) == ' ') 31 | spaceNum++; 32 | 33 | int indexOld = str.length() -1; 34 | int indexNew = indexOld + spaceNum * 2; // 每次替换一次空格至%20就需要多两个空间 35 | int newLength = indexNew + 1; 36 | str.setLength(newLength); // 设置新数组的长度 37 | // 拷贝数组并替换的过程 38 | while (indexOld >= 0 && indexNew > indexOld) { 39 | if (str.charAt(indexOld) == ' '){ 40 | str.setCharAt(indexNew--, '0'); 41 | str.setCharAt(indexNew--,'2'); 42 | str.setCharAt(indexNew--,'%'); 43 | }else { 44 | str.setCharAt(indexNew--,str.charAt(indexOld)); 45 | } 46 | --indexOld; // 每轮循环不能忘记维护指针前移动 47 | } 48 | return str.toString(); 49 | } 50 | 51 | /*调用 API 52 | * */ 53 | private static String replaceSpace(StringBuffer str) { 54 | return str.toString().replaceAll("\\s","%20"); 55 | } 56 | 57 | public static void main(String[] args) { 58 | StringBuffer str = new StringBuffer("We are Happy to meet you"); 59 | System.out.println(ReplaceBlank.replaceSpace(str)); 60 | System.out.println(ReplaceBlank.replaceBlank(str)); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/ReverseList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2018 3 | * FileName: ReverseList 4 | * Author: Administrator 5 | * Date: 2018/3/8 0008 22:29 6 | * Description: 反转链表 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈反转链表〉 14 | * 15 | * @author Administrator 16 | * @create 2018/3/8 0008 17 | * @subject 1. 输入一个链表,反转链表后,输出链表的所有元素。 18 | * 2. 时间限制:1秒 空间限制:32768K 19 | * @Strategies 20 | * @since 1.0.0 21 | */ 22 | public class ReverseList { 23 | 24 | private class ListNode { 25 | int val; 26 | ListNode next = null; 27 | 28 | ListNode(int val) { 29 | this.val = val; 30 | } 31 | } 32 | 33 | /** 34 | * 反转链表用循环来实现 35 | * @param head 36 | * @return ListNode 37 | */ 38 | public ListNode ReverseList(ListNode head) { 39 | if (head == null) { 40 | return null; 41 | } 42 | ListNode current = head; //即pre让节点可以反转所指方向,但反转之后如果不用next节点保存next1节点的话,此单链表就此断开了 43 | ListNode pre = null; // 用来保存待反序的第一个节点(head 和 next节点) 44 | ListNode next = null; // 用来保存已经反序的第一个结点 45 | while (current != null) { //做循环,如果当前节点不为空的话,始终执行此循环,此循环的目的就是让当前节点从指向next到指向pre 46 | next = current.next; // 首先记录当前节点的下一个节点,(保存起来) 47 | 48 | current.next = pre; // 让当前节点指向前一个节点,反序操作 49 | // head指向pre后,就继续依次反转下一个节点 50 | // 让pre,head,next依次向后移动一个节点,继续下一次的指针反转 51 | pre = current; // 让前一个节点值,取代当前的节点值。因为要继续向下走 52 | current = next; // 让下一个节点,取代当前节点。同样是向下走,为下一次循环做准备 53 | } 54 | return pre; // 如果head为null的时候,pre就为最后一个节点了,但是链表已经反转完毕,pre就是反转后链表的第一个节点 55 | // 直接输出pre就是我们想要得到的反转后的链表 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/ReverseSentence.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | /** 4 | * 输入英文反转句子中的单词的顺序,但是单词的字符的顺序保持不变 5 | * 6 | * @author : Administrator 7 | * @subject : 输入英文反转句子中的单词的顺序,但是单词的字符的顺序保持不变,输入“ I am a student." 8 | * 则输出”student. a am I“ 9 | * @create 2018-04-22 22:11 10 | */ 11 | public class ReverseSentence { 12 | 13 | /** 14 | * 1. 第一步反转句子中的所有的字符,变为”.tneduts a ma I" 15 | * 2. 第二步翻转单个单词内部的字符的顺序,可以得到“student. a am I" 16 | * @param str 17 | * @return 18 | */ 19 | public String reverseSentence(String str) { 20 | char[] chars = str.toCharArray(); 21 | // 第一步 22 | revers(chars,0,chars.length - 1); 23 | int blank = -1; 24 | // 根据空格分隔每个单词,单词内部单独反转 25 | for (int i = 0; i < chars.length; i++) { 26 | if (chars[i] == ' ') { 27 | int nextBlank = i; 28 | revers(chars, blank + 1, nextBlank - 1); 29 | blank = nextBlank; 30 | } 31 | } 32 | // 反转最后一个单词 33 | revers(chars,blank + 1, chars.length - 1); 34 | return new String(chars); 35 | } 36 | 37 | /** 38 | * 直接反转单个字符串 39 | * @param chars 40 | * @param low 41 | * @param high 42 | */ 43 | private void revers(char[] chars,int low,int high) { 44 | while (low < high) { 45 | char temp = chars[low]; 46 | chars[low] = chars[high]; 47 | chars[high] = temp; 48 | low++; 49 | high--; 50 | } 51 | } 52 | 53 | public static void main(String[] args) { 54 | System.out.println(new ReverseSentence().reverseSentence("I am a student.")); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/SerializeBinaryTree.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.TreeNode; 4 | 5 | /** 6 | * 序列化二叉树 7 | * 8 | * @author : Administrator 9 | * @create 2018-07-03 11:04 10 | * @subject : 11 | * 请实现两个函数,分别用来序列化和反序列化二叉树 12 | */ 13 | public class SerializeBinaryTree { 14 | 15 | public int index = -1; 16 | 17 | /** 18 | * 序列化二叉树--将二叉树序列化为字符串 19 | * 算法思想:根据前序遍历规则完成序列化和反序列化。 20 | * 所谓的序列化指的是遍历二叉树为字符串:所谓的反序列化指的是根据字符串重新构造成二叉树。 21 | * 前序遍历是从根节点开始的。当在遍历二叉树碰到null 的时候将其初始化为字符串“#”, 22 | * 各个节点的数值用逗号隔开, 23 | * @param root 24 | * @return 25 | */ 26 | String serializeBinary(TreeNode root) { 27 | StringBuffer sb = new StringBuffer(); 28 | if (root == null) { 29 | sb.append("#,"); 30 | return sb.toString(); 31 | } 32 | sb.append(root.val + ","); 33 | sb.append(serializeBinary(root.left)); 34 | sb.append(serializeBinary(root.right)); 35 | return sb.toString(); 36 | } 37 | 38 | /** 39 | * 反序列化二叉树--将字符串转化为二叉树 40 | * 41 | * @param str 42 | * @return 43 | */ 44 | TreeNode Deseriallize(String str) { 45 | index++; 46 | String[] strings = str.split(","); 47 | TreeNode node = null; 48 | if (!strings[index].equals("#")) { 49 | node = new TreeNode(Integer.valueOf(strings[index])); 50 | node.left = Deseriallize(str); 51 | node.right = Deseriallize(str); 52 | } 53 | return node; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/StrToInt.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | /** 4 | * 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数 5 | * 6 | * @author : Administrator 7 | * @create 2018-04-25 18:53 8 | */ 9 | public class StrToInt { 10 | 11 | // 判断是否输入合法 12 | public static boolean isInvalid = false; 13 | 14 | public int strToInt(String str) { 15 | if (str == null || str.equals("")) { 16 | isInvalid = true; 17 | return 0; 18 | } 19 | char[] arr = str.toCharArray(); 20 | int symbol = 1; 21 | if (arr[0] == '-') { 22 | symbol = -1; 23 | } 24 | int result = 0; 25 | for (int i = (arr[0] == '-' || arr[0] == '+') ? 1 : 0; i < str.length(); i++) { 26 | if (!('0' <= arr[i] && arr[i] <= '9')) { 27 | isInvalid = true; 28 | return 0; 29 | } 30 | result = result * 10 + arr[i] - '0'; 31 | if (symbol == 1 && result > Integer.MAX_VALUE) { 32 | isInvalid = true; 33 | return 0; 34 | } 35 | } 36 | return result * symbol; 37 | } 38 | 39 | public static void main(String[] args) { 40 | System.out.println(new StrToInt().strToInt("-234")); 41 | System.out.println(new StrToInt().strToInt("-234A")); 42 | System.out.println(new StrToInt().strToInt("+2147483647")); 43 | System.out.println(new StrToInt().strToInt("1a33")); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/StringIsNum.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | /** 4 | * @author : Administrator 5 | * @Subject: 请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。 6 | * 例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 7 | * 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。 8 | * @create 2018-05-11 20:21 9 | */ 10 | public class StringIsNum { 11 | 12 | /** 13 | * 表述数值的字符串情况较多,分析如下: 14 | * 15 | * 首先,第一个字符可能是正’+’,负’-‘号,也可能是数字。 16 | * 如果遇到了’.’,说明是一个小数,那么’.’后面应该是一串0到9的数字 17 | * 如果遇到了’E’,说明是一个科学记数,那么’E’后面应该是一串0到9的数字,注意E后面可以接一个负号,如:-1E-16 18 | */ 19 | private int index = 0; 20 | 21 | public boolean isNumeric(char[] str) { 22 | if (str.length < 1) { 23 | return false; 24 | } 25 | boolean flags = scanInteger(str); 26 | if (index < str.length && str[index] == '.') { 27 | index++; 28 | flags = scanUnInteger(str) || flags; 29 | } 30 | 31 | if (index < str.length && (str[index] == 'E' || str[index] == 'e')) { 32 | index++; 33 | flags = flags && scanInteger(str); 34 | } 35 | return flags && index == str.length; 36 | } 37 | 38 | private boolean scanInteger(char[] str) { 39 | if (index < str.length && (str[index] == '+' || str[index] == '-')) { 40 | index++; 41 | } 42 | return scanUnInteger(str); 43 | } 44 | 45 | /** 46 | * 判断是否存在整数 47 | * 48 | * @param str 49 | * @return 50 | */ 51 | private boolean scanUnInteger(char[] str) { 52 | int start = index; 53 | while (index < str.length && str[index] >= '0' && str[index] <= '9') { 54 | index++; 55 | } 56 | // 是否存在整数 57 | return start < index; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/Sum_SolutionN.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | /** 4 | * 求1+2+3+...+N 5 | * 6 | * @author : Administrator 7 | * @subject : 求1+2+3+...+n, 8 | * 要求不能使用乘除法、for、while、if、else、switch、case 等关键字及条件判断语句 (A?B:C) 9 | * @create 2018-04-24 21:53 10 | */ 11 | public class Sum_SolutionN { 12 | 13 | /** 14 | * A&&B, 当A为false时,不去计算B的值而直接返回false;当A为true时,计算B的值。 15 | * 对于||,如果第一个值为false,那么还要计算第二个值,如果第一个值为true,那么第二个值不再计算; 16 | * 对于&和|操作符,两边无论如何都计算 17 | * 1.需利用逻辑与的短路特性实现递归终止。 18 | * 2. 当 n==0 时,(n>0)&&((sum+=Sum_Solution(n-1))>0)只执行前面的判断,为false,然后直接返回0; 19 | * 3. 当n>0 时,执行sum+=Sum_Solution(n-1),实现递归计算Sum_Solution(n)。 20 | * @param n 21 | * @return 22 | */ 23 | public int sum_solutions(int n) { 24 | int sum = n; 25 | boolean ans = (n > 0) && ((sum += sum_solutions(n - 1)) > 0); 26 | return sum; 27 | } 28 | 29 | public static void main(String[] args) { 30 | System.out.println(new Sum_SolutionN().sum_solutions(5)); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/TreeDepth.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | import me.zonglun.SwordToOffer.util.TreeNode; 4 | 5 | /** 6 | * @author : Administrator 7 | * @subject :输入一棵二叉树,求该树的深度。 8 | * 从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。 9 | * @create 2018-04-22 11:07 10 | */ 11 | public class TreeDepth { 12 | 13 | public int TreeDepth(TreeNode root) { 14 | if (root == null) { 15 | return 0; 16 | } 17 | int TLeft = TreeDepth(root.left); 18 | int TRight = TreeDepth(root.right); 19 | return (TRight > TLeft) ? (TRight + 1) : (TLeft + 1); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/TwoStackQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: TwoStackQueue 4 | * Author: Administrator 5 | * Date: 2017/11/16 0016 21:20 6 | * Description: TwoStackQueue 7 | */ 8 | 9 | package me.zonglun.SwordToOffer; 10 | 11 | import java.util.Stack; 12 | 13 | /** 14 | * 〈一句话功能简述〉
15 | * 〈TwoStackQueue〉 16 | * @subject 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。 17 | * 18 | * @Strategies 19 | * 1. 设计上使用两个栈,一个只用来压入栈--StackPush;另一个栈只能弹出栈--记为StackPop; 20 | * 2. 栈的特点是先进后出,队列先进先出,可用来将数据存入压入栈如 1-2-3-4-5 StackPush:5-4-3-2-1 再把Stackpush的值压入StackPop 变为:Stackpop:1-2-3-4-5 这样从Stackpop里弹出的顺序和向Stackpush压入的顺序则完全一致。 21 | * 3. 注意两点:(1)Stackpush往Stackpop完全压入的时候必须一次性压入,不能出现剩余数据 22 | * (2)如果Stackpop不为空,则不能出现压栈操作 23 | * @author Administrator 24 | * @create 2017/11/16 0016 25 | * @since 1.0.0 26 | */ 27 | 28 | public class TwoStackQueue { 29 | private Stack stackPush = new Stack<>(); 30 | private Stack stackPop = new Stack<>(); 31 | 32 | public void push(int node) { 33 | stackPush.push(node); 34 | } 35 | 36 | public int pop(){ 37 | if (stackPush.empty() && stackPop.empty()) 38 | throw new RuntimeException("Queue is Empty"); 39 | if (stackPop.empty()){ 40 | while (!stackPush.empty()) 41 | stackPop.push(stackPush.pop()); 42 | } 43 | return stackPop.pop(); 44 | } 45 | 46 | public static void main(String[] args) { 47 | TwoStackQueue que = new TwoStackQueue(); 48 | que.push(34); 49 | que.push(23); 50 | que.push(245); 51 | System.out.println(que.pop()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/VerifySquenceOfBST.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer; 2 | 3 | /** 4 | * 二叉搜索树的后序遍历 5 | * 6 | * @author : Administrator 7 | * @subject : 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。 8 | * 如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。 9 | * @example : 8 10 | * 6 10 例如输入数组{5,7,6,9,11,10,8} 11 | * 5 7 9 11 12 | * @create 2018-03-17 13:52 13 | */ 14 | public class VerifySquenceOfBST { 15 | 16 | /** 17 | * 找住二叉查找树的特点:左子树<根<=右子树 使用分治思想 18 | * 19 | * @param sequence 20 | * @return boolean 21 | */ 22 | private static boolean VeritySquenceofBST(int[] sequence) { 23 | if (sequence.length == 0) { 24 | return false; 25 | } 26 | if (sequence.length == 1) { 27 | return true; 28 | } 29 | return Verity(sequence, 0, sequence.length - 1); 30 | } 31 | 32 | /** 33 | * @param sequence 数组 34 | * @param start 数组开始元素的索引 35 | * @param end 数组结束元素的索引 36 | * @return boolean true or false 37 | */ 38 | private static boolean Verity(int[] sequence, int start, int end) { 39 | if (start >= end) { 40 | return true; 41 | } 42 | // 在二叉树搜索树中左节点小于根节点 43 | int i = start; 44 | while (sequence[i] < sequence[end]) { 45 | i++; // 此时i = j < root 是数组中最后一个小于root的节点的临界值 46 | } 47 | // 在二叉树搜索树中右节点大于根节点 48 | for (int j = i; j < end; j++) { 49 | if (sequence[j] < sequence[end]) { 50 | return false; // 如果在这个临界值的右边,有小于 root 的值,则不符合二叉搜索树的定义 51 | } 52 | } 53 | // 子树递归判断 54 | return Verity(sequence, start, i - 1) && Verity(sequence, i, end - 1); 55 | } 56 | 57 | public static void main(String[] args) { 58 | int[] sequence = {5, 7, 6, 9, 11, 10, 8}; 59 | int[] sequence2 = {7, 4, 6, 5}; 60 | System.out.println(VeritySquenceofBST(sequence)); 61 | System.out.println(VeritySquenceofBST(sequence2)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/util/ListNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2018 3 | * FileName: ListNode 4 | * Author: Administrator 5 | * Date: 2018/3/11 0011 16:33 6 | * Description: 7 | */ 8 | 9 | package me.zonglun.SwordToOffer.util; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈〉 14 | * 15 | * @author Administrator 16 | * @create 2018/3/11 0011 17 | * @since 1.0.0 18 | */ 19 | public class ListNode { 20 | public int val; 21 | public ListNode next = null; 22 | 23 | public ListNode(int val) { 24 | this.val = val; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/util/TreeLinkNode.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer.util; 2 | 3 | /** 4 | * @author : Administrator 5 | * @create 2018-05-20 16:22 6 | */ 7 | public class TreeLinkNode { 8 | int val; 9 | public TreeLinkNode left = null; 10 | public TreeLinkNode right = null; 11 | public TreeLinkNode next = null; 12 | 13 | TreeLinkNode(int val) { 14 | this.val = val; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/me/zonglun/SwordToOffer/util/TreeNode.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.SwordToOffer.util; 2 | 3 | public class TreeNode { 4 | public int val ; 5 | public TreeNode left; 6 | public TreeNode right; 7 | 8 | public TreeNode(int x) { 9 | this.val = x; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/me/zonglun/UnionFind/UnionFind1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: UnionFind1 4 | * Author: Administrator 5 | * Date: 2017/11/10 0010 21:22 6 | * Description: UnionFind1 第一版本 7 | */ 8 | 9 | package me.zonglun.UnionFind; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈UnionFind1 第一版本〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/10 0010 17 | * @since 1.0.0 18 | */ 19 | public class UnionFind1 { 20 | private int[] id; 21 | private int count; 22 | 23 | UnionFind1(int n) { 24 | count = n; 25 | id = new int[n]; 26 | for (int i = 0; i < n; i++) { 27 | id[i] = i; 28 | } 29 | } 30 | // 查找过程, 查找元素p所对应的集合编号 31 | // O(1)复杂度 32 | public int find(int p) { 33 | assert p >= 0 && p < count; 34 | return id[p]; 35 | } 36 | // 查看元素p和元素q是否所属一个集合 37 | // O(1)复杂度 38 | boolean isConnected(int p, int q){ 39 | return find(p) == find(q); 40 | } 41 | 42 | // 合并元素p和元素q所属的集合 43 | // O(n) 复杂度 44 | public void unionElements(int p, int q) { 45 | int pID = find(p); 46 | int qID = find(q); 47 | if (qID == pID) 48 | return; 49 | for (int i = 0; i < count; i++) { 50 | if (id[i] == pID) 51 | id[i] = qID; 52 | } 53 | } 54 | 55 | public static void main(String[] args) { 56 | int n = 100000; 57 | // 虽然isConnected只需要O(1)的时间, 但由于union操作需要O(n)的时间 58 | // 总体测试过程的算法复杂度是O(n^2)的 59 | UnionFindTestHelper.testUF1(n); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/me/zonglun/UnionFind/UnionFind2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: UnionFind2 4 | * Author: Administrator 5 | * Date: 2017/11/10 0010 21:51 6 | * Description: UnionFind1 7 | */ 8 | 9 | package me.zonglun.UnionFind; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈UnionFind1〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/10 0010 17 | * @since 1.0.0 18 | */ 19 | public class UnionFind2 { 20 | 21 | // 我们的第二版Union-Find, 使用一个数组构建一棵指向父节点的树 22 | // parent[i]表示第一个元素所指向的父节点 23 | private int[] parent; 24 | private int count; // 数据个数 25 | 26 | public UnionFind2(int count) { 27 | parent = new int[count]; 28 | // 初始化, 每一个parent[i]指向自己, 表示每一个元素自己自成一个集合 29 | for (int i = 0; i < count; i++) { 30 | parent[i] = i; 31 | } 32 | } 33 | 34 | // 查找过程, 查找元素p所对应的集合编号 35 | // O(h)复杂度, h为树的高度 36 | private int find(int p) { 37 | assert (p >= 0 && p < count); 38 | // 不断去查询自己的父亲节点, 直到到达根节点 39 | // 根节点的特点: parent[p] == p 40 | while (p != parent[p]) 41 | p = parent[p]; 42 | return p; 43 | } 44 | 45 | boolean isConneted(int q, int p) { 46 | return find(q) == find(p); 47 | } 48 | 49 | void unionElements(int p, int q) { 50 | int pRoot = find(p); 51 | int qRoot = find(q); 52 | if (pRoot == qRoot) 53 | return; 54 | parent[pRoot] = qRoot; 55 | } 56 | 57 | public static void main(String[] args) { 58 | int n = 100000; 59 | UnionFindTestHelper.testUF2(n); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/me/zonglun/UnionFind/UnionFind3.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: UnionFind3 4 | * Author: Administrator 5 | * Date: 2017/11/10 0010 22:11 6 | * Description: UnionFind3 7 | */ 8 | 9 | package me.zonglun.UnionFind; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈UnionFind3 〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/10 0010 17 | * @since 1.0.0 18 | */ 19 | public class UnionFind3 { 20 | private int[] parent; // parent[i]表示第一个元素所指向的父节点 21 | private int[] sz; // sz[i]表示以i为根的集合中元素个数 22 | private int count; // 数据个数 23 | 24 | // 构造函数 25 | public UnionFind3(int count){ 26 | parent = new int[count]; 27 | sz = new int[count]; 28 | this.count = count; 29 | // 初始化, 每一个parent[i]指向自己, 表示每一个元素自己自成一个集合 30 | for( int i = 0 ; i < count ; i ++ ){ 31 | parent[i] = i; 32 | sz[i] = 1; 33 | } 34 | } 35 | 36 | // 查找过程, 查找元素p所对应的集合编号 37 | // O(h)复杂度, h为树的高度 38 | private int find(int p){ 39 | assert( p >= 0 && p < count ); 40 | // 不断去查询自己的父亲节点, 直到到达根节点 41 | // 根节点的特点: parent[p] == p 42 | while( p != parent[p] ) 43 | p = parent[p]; 44 | return p; 45 | } 46 | 47 | // 查看元素p和元素q是否所属一个集合 48 | // O(h)复杂度, h为树的高度 49 | public boolean isConnected( int p , int q ){ 50 | return find(p) == find(q); 51 | } 52 | 53 | // 合并元素p和元素q所属的集合 54 | // O(h)复杂度, h为树的高度 55 | public void unionElements(int p, int q){ 56 | 57 | int pRoot = find(p); 58 | int qRoot = find(q); 59 | 60 | if( pRoot == qRoot ) 61 | return; 62 | 63 | // 根据两个元素所在树的元素个数不同判断合并方向 64 | // 将元素个数少的集合合并到元素个数多的集合上 65 | if( sz[pRoot] < sz[qRoot] ){ 66 | parent[pRoot] = qRoot; 67 | sz[qRoot] += sz[pRoot]; 68 | } 69 | else{ 70 | parent[qRoot] = pRoot; 71 | sz[pRoot] += sz[qRoot]; 72 | } 73 | } 74 | 75 | public static void main(String[] args) { 76 | int n = 100000; 77 | UnionFindTestHelper.testUF3(n); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/me/zonglun/UnionFind/UnionFind4.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C), 2015-2017 3 | * FileName: UnionFind4 4 | * Author: Administrator 5 | * Date: 2017/11/10 0010 22:19 6 | * Description: UnionFind4 7 | */ 8 | 9 | package me.zonglun.UnionFind; 10 | 11 | /** 12 | * 〈一句话功能简述〉
13 | * 〈UnionFind4 〉 14 | * 15 | * @author Administrator 16 | * @create 2017/11/10 0010 17 | * @since 1.0.0 18 | */ 19 | public class UnionFind4 { 20 | private int[] rank; // rank[i]表示以i为根的集合所表示的树的层数 21 | private int[] parent; // parent[i]表示第i个元素所指向的父节点 22 | private int count; // 数据个数 23 | 24 | // 构造函数 25 | public UnionFind4(int count){ 26 | rank = new int[count]; 27 | parent = new int[count]; 28 | this.count = count; 29 | // 初始化, 每一个parent[i]指向自己, 表示每一个元素自己自成一个集合 30 | for( int i = 0 ; i < count ; i ++ ){ 31 | parent[i] = i; 32 | rank[i] = 1; 33 | } 34 | } 35 | 36 | // 查找过程, 查找元素p所对应的集合编号 37 | // O(h)复杂度, h为树的高度 38 | private int find(int p){ 39 | assert( p >= 0 && p < count ); 40 | // 不断去查询自己的父亲节点, 直到到达根节点 41 | // 根节点的特点: parent[p] == p 42 | while( p != parent[p] ) 43 | p = parent[p]; 44 | return p; 45 | } 46 | 47 | // 查看元素p和元素q是否所属一个集合 48 | // O(h)复杂度, h为树的高度 49 | public boolean isConnected( int p , int q ){ 50 | return find(p) == find(q); 51 | } 52 | 53 | // 合并元素p和元素q所属的集合 54 | // O(h)复杂度, h为树的高度 55 | public void unionElements(int p, int q){ 56 | 57 | int pRoot = find(p); 58 | int qRoot = find(q); 59 | 60 | if( pRoot == qRoot ) 61 | return; 62 | 63 | // 根据两个元素所在树的元素个数不同判断合并方向 64 | // 将元素个数少的集合合并到元素个数多的集合上 65 | if( rank[pRoot] < rank[qRoot] ){ 66 | parent[pRoot] = qRoot; 67 | } 68 | else if( rank[qRoot] < rank[pRoot]){ 69 | parent[qRoot] = pRoot; 70 | } 71 | else{ // rank[pRoot] == rank[qRoot] 72 | parent[pRoot] = qRoot; 73 | rank[qRoot] += 1; // 此时, 我维护rank的值 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/Algorithms/CardinalitySort.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.Algorithms; 2 | 3 | 4 | /** 5 | * 基数排序 6 | * 7 | * @author : Administrator 8 | * @create 2018-09-04 15:33 9 | * @subject : 10 | * 基数排序(radix sort)属于"分配式排序"(distribution sort),又称"桶子法"(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些"桶"中, 11 | * 藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m), 12 | * 其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。 13 | */ 14 | public class CardinalitySort { 15 | 16 | 17 | /** 18 | * 递归找出数组最大的值为多少, 19 | * @param array 数组 20 | * @param L 21 | * @param R 22 | * @return 23 | */ 24 | private static int findMax(int[] array, int L, int R) { 25 | if (L == R) { 26 | return array[L]; 27 | } else { 28 | int a = array[L]; 29 | int b = findMax(array, L + 1, R); 30 | if (a > b) { 31 | return a; 32 | } else { 33 | return b; 34 | } 35 | } 36 | } 37 | 38 | public static void radixSort(int[] arrays) { 39 | int max = findMax(arrays, 0, arrays.length - 1); 40 | for (int i = 1; max / i > 0; i = i * 10) { 41 | int[][] bucketes = new int[arrays.length][10]; 42 | for (int j = 0; j < arrays.length; j++) { 43 | int num = (arrays[j] / i) % 10; 44 | // 将其放入桶中 45 | bucketes[j][num] = arrays[j]; 46 | } 47 | int k = 10; 48 | for (int j = 0; j < 10; j++) { 49 | for (int l = 0; l < arrays.length; l++) { 50 | if (bucketes[l][j] != 0) { 51 | arrays[k++] = bucketes[l][i]; 52 | } 53 | } 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/Algorithms/DP/Packages01.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.Algorithms.DP; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Scanner; 5 | 6 | /** 7 | * 0-1背包问题 8 | * 9 | * @author : Administrator 10 | * @create 2018-09-13 16:21 11 | * @subject : 12 | * 13 | * 现有n件物品和一个容量为c的背包。第i件物品的重量是重量为w[i],价值是v[i]。 14 | * 已知对于一件物品必须选择取(用1表示)或者不取(用0表示),且每件物品只能被取一次(这就是“0-1”的含义)。 15 | * 求放置哪些物品进背包,可使这些物品的重量总和不超过背包容量,且价值总和最大。 16 | * @Strategies : 17 | * 18 | * 假设有5件物品,其重量分别是w={2,2,6,5,4},价值分别是v={6,3,5,4,6},背包容量为10。在数学问题中这是典型的线性规划问题,我们可以在线性约束范围内求解目标表达式。但是怎么用计算机语言实现呢?我们可以先这样考虑,当背包容量为1时,如何放置物品才能使背包中价值最大;同样当背包容量为2时,如何放置能使背包中价值最大,以此类推,直到背包容量为10。此时我们需要维护一张二维表m[i][j],其中横坐标i表示物品,纵坐标表示背包容量(1<=j<=10)。 19 | * 20 | * 21 | * m[i][j]表示当可以放入前i件物品且背包容量为j时的最大价值。当只能放入第一件物品即i=0时:若背包容量j=w[0]时,物品可以放入背包,此时m[0][j]=v[0]。当可以放入前2件物品即i=1时,我们需要进行这样的处理:若j=w[1]时,假设此时背包容量j=8,第二件物品可以被放入背包内,那么便会出现两种情况: 22 | * 23 | * x - ( p + q ) + ( y - a ) 24 | */ 25 | public class Packages01 { 26 | public static void main(String[] args) { 27 | Scanner sc = new Scanner(System.in); 28 | String expr = sc.nextLine(); 29 | char[] ss = expr.toCharArray(); 30 | ArrayList list = new ArrayList<>(); 31 | int i = 0, j = 1; 32 | for (char ca : ss) { 33 | list.add(ca); 34 | } 35 | while (i < ss.length && j < ss.length) { 36 | if (ss[i] == '-' && ss[j] == '(' && ss[j +2] == '+' && j +2 < ss.length) { 37 | list.set(j + 2, '-'); 38 | } 39 | if (ss[i] == '-' && ss[j] == '(' && ss[j +2] == '-' && j +2 < ss.length) { 40 | list.set(j +2, '+'); 41 | } 42 | if (ss[j] == '(' || ss[j] == ')') { 43 | list.remove(0); 44 | } 45 | i++; 46 | j = i + 1; 47 | } 48 | for (char s : list) { 49 | System.out.print(s); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/Algorithms/DP/question322/coinChange.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.Algorithms.DP.question322; 2 | 3 | /** 4 | * 零钱兑换 5 | * 6 | * @author : Administrator 7 | * @create 2018-09-13 10:46 8 | */ 9 | public class coinChange { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/Algorithms/DP/question53/MaximumSubarray.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.Algorithms.DP.question53; 2 | 3 | 4 | /** 5 | * @author : Administrator 6 | * @create 2018-09-12 18:57 7 | * @subject : 8 | * 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 9 | * 示例: 10 | * 11 | * 输入: [-2,1,-3,4,-1,2,1,-5,4], 12 | * 输出: 6 13 | * 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 14 | * 15 | * 进阶: 16 | * 17 | * 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。 18 | */ 19 | public class MaximumSubarray { 20 | 21 | public int maxSubArray(int[] nums) { 22 | int[] dp = new int[nums.length]; 23 | dp[0] = nums[0]; 24 | int max_res = dp[0]; 25 | for (int i = 0; i < nums.length; i++) { 26 | dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]); 27 | if (max_res < dp[i]) { 28 | max_res = dp[i]; 29 | } 30 | } 31 | return max_res; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/Algorithms/DP/question70/ClimbingStairs.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.Algorithms.DP.question70; 2 | 3 | /** 4 | * 爬楼梯 5 | * 6 | * @author : Administrator 7 | * @create 2018-09-12 15:48 8 | */ 9 | public class ClimbingStairs { 10 | public int climbStairs(int n) { 11 | if (n == 1) { 12 | return 1; 13 | } 14 | int[] dp = new int[n + 1]; 15 | dp[1] = 1; 16 | dp[2] = 2; 17 | for (int i = 3; i <= n; i++) { 18 | dp[i] = dp[i - 1] + dp[i - 2]; 19 | } 20 | return dp[n]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/Algorithms/greedy/Test.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.Algorithms.greedy; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * @author : Administrator 7 | * @create 2018-09-10 14:28 8 | */ 9 | public class Test { 10 | public static void main(String[] args) { 11 | Scanner sc = new Scanner(System.in); 12 | while (sc.hasNext()) { 13 | double n = sc.nextInt(); 14 | int m = sc.nextInt(); 15 | double sum = 0; 16 | for (int i = 0; i < m; i++) { 17 | sum += n; 18 | n = Math.sqrt(n); 19 | } 20 | System.out.printf("%.2f",sum); 21 | System.out.println(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/Algorithms/greedy/question135/PuKePai.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.Algorithms.greedy.question135; 2 | 3 | /** 4 | * 扑克牌 5 | * 6 | * @author : Administrator 7 | * @create 2018-09-09 22:27 8 | */ 9 | public class PuKePai { 10 | public static void main(String[] args) { 11 | int[] RMB = {100, 50, 20, 10, 5, 2, 1}; 12 | int num = 7; 13 | int X = 628; 14 | int count = 0; 15 | for (int i = 0; i < num; i++) { 16 | int use = X / RMB[i]; 17 | count += use; 18 | X -= RMB[i] * use; 19 | System.out.printf("需要面额为 %d的 %d张\n",RMB[i],use); 20 | System.out.printf("剩余需要支付的RMB %d\n", X); 21 | } 22 | System.out.printf("总共需要%d个数字",count); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/Algorithms/greedy/question135/candy.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.Algorithms.greedy.question135; 2 | 3 | /** 4 | * @author : Administrator 5 | * @create 2018-09-09 22:22 6 | * @subject : 7 | * 老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。 8 | *

9 | * 你需要按照以下要求,帮助老师给这些孩子分发糖果: 10 | *

11 | * 每个孩子至少分配到 1 个糖果。 12 | * 相邻的孩子中,评分高的孩子必须获得更多的糖果。 13 | * 那么这样下来,老师至少需要准备多少颗糖果呢? 14 | * 示例 1: 15 | *

16 | * 输入: [1,0,2] 17 | * 输出: 5 18 | * 解释: 你可以分别给这三个孩子分发 2、1、2 颗糖果。 19 | * 示例 2: 20 | *

21 | * 输入: [1,2,2] 22 | * 输出: 4 23 | * 解释: 你可以分别给这三个孩子分发 1、2、1 颗糖果。 24 | * 第三个孩子只得到 1 颗糖果,这已满足上述两个条件。 25 | */ 26 | public class candy { 27 | public int solution(int[] ratings) { 28 | return 0; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/Algorithms/greedy/question376/wiggleSubsequence.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.Algorithms.greedy.question376; 2 | 3 | /** 4 | * 摇摆序列 5 | * 6 | * @author : Administrator 7 | * @create 2018-09-10 11:29 8 | * @subject : 9 | * 如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。 10 | * 11 | * 例如, [1,7,4,9,2,5] 是一个摆动序列,因为差值 (6,-3,5,-7,3) 是正负交替出现的。相反, [1,4,7,2,5] 和 [1,7,4,5,5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。 12 | * 13 | * 给定一个整数序列,返回作为摆动序列的最长子序列的长度。 通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。 14 | * 15 | * 示例 1: 16 | * 17 | * 输入: [1,7,4,9,2,5] 18 | * 输出: 6 19 | * 20 | */ 21 | public class wiggleSubsequence { 22 | 23 | public int wiggleMaxLength(int[] nums) { 24 | if (nums.length < 2) { 25 | return nums.length; 26 | } 27 | 28 | return 0; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/Algorithms/greedy/question455/assigncookies.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.Algorithms.greedy.question455; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author : Administrator 7 | * @create 2018-09-09 22:47 8 | * @subject : 9 | * 假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。 10 | * 注意: 11 | * 12 | * 你可以假设胃口值为正。 13 | * 一个小朋友最多只能拥有一块饼干。 14 | * 15 | * 示例 1: 16 | * 17 | * 输入: [1,2,3], [1,1] 18 | * 19 | * 输出: 1 20 | * 21 | * 解释: 22 | * 你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。 23 | * 虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。 24 | * 所以你应该输出1。 25 | * 26 | * 示例 2: 27 | * 28 | * 输入: [1,2], [1,2,3] 29 | * 30 | * 输出: 2 31 | * 32 | * 解释: 33 | * 你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。 34 | * 你拥有的饼干数量和尺寸都足以让所有孩子满足。 35 | * 所以你应该输出2. 36 | */ 37 | public class assigncookies { 38 | public int findContentChildren(int[] g, int[] s) { 39 | // 先对数组的两个数字排序 40 | Arrays.sort(g); 41 | Arrays.sort(s); 42 | int feedChild = 0; // 满足的孩子的数量 43 | int cookie = 0; // cookie 代表尝试了几个糖果 44 | while (cookie < s.length && feedChild < g.length) { 45 | if (g[feedChild] <= s[cookie]) { 46 | feedChild++; 47 | } 48 | cookie++; 49 | } 50 | return feedChild; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/FibooCiles.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode; 2 | 3 | import me.zonglun.leetcode.utils.StopWatch; 4 | 5 | /** 6 | * @author : Administrator 7 | * @create 2018-11-20 16:31 8 | */ 9 | public class FibooCiles { 10 | 11 | private int filbees(int n) { 12 | if (n < 3) { 13 | return 1; 14 | } else { 15 | return filbees(n - 1) + filbees(n - 2); 16 | } 17 | } 18 | 19 | private int fibees(int frist, int second, int n) { 20 | if (n < 3) { 21 | return 1; 22 | } 23 | if (n == 3) { 24 | return frist + second; 25 | } else { 26 | return fibees(second, frist + second, n - 1); 27 | } 28 | } 29 | 30 | 31 | private int fibbAdls(int n) { 32 | int frist = 1; 33 | int second = 1; 34 | int ret = 0; 35 | for (int i = 3; i <= n; i++) { 36 | ret = frist + second; 37 | frist = second; 38 | second = ret; 39 | } 40 | return second; 41 | } 42 | 43 | public static void main(String[] args) { 44 | /*StopWatch timer = new StopWatch(); 45 | int s = (new FibooCiles().filbees(40)); 46 | double time = timer.elapsedTime(); 47 | System.out.println(s + " result " + " Spend time: " + time + " seconds");*/ 48 | 49 | StopWatch timer1 = new StopWatch(); 50 | int s1 = (new FibooCiles().fibbAdls(400000)); 51 | double time1 = timer1.elapsedTime(); 52 | System.out.println(s1 + " result " + " Spend time: " + time1 + " seconds"); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/MinStringSum.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode; 2 | 3 | /** 4 | * @author : Administrator 5 | * @create 2018-11-20 19:28 6 | */ 7 | 8 | import me.zonglun.leetcode.utils.StopWatch; 9 | 10 | /** 11 | * 最大子序列和的问题求解 12 | */ 13 | public class MinStringSum { 14 | 15 | /* 16 | * Cubie maxunum subsequence sum algorithm 17 | * 18 | * 任何负的 子序列都不可能是最大子序列和 的前缀 19 | * 当加上 下标 j 所在的元素 使得 当前序列的和变成负数时,根据①,可以从 j+1 处重新开始计算下一段子序列的和。 20 | */ 21 | public static int maxSubSum1(int[] a) { 22 | int maxSum = 0, thisSum = 0; 23 | for (int anA : a) { 24 | thisSum += anA; 25 | if (thisSum > maxSum) { 26 | maxSum = thisSum; 27 | } else if (thisSum < 0) { 28 | thisSum = 0; 29 | } 30 | } 31 | return maxSum; 32 | } 33 | 34 | public static void main(String[] args) { 35 | int[] a = RundomNumArray.randomArr(1000* 70); 36 | StopWatch stopWatch = new StopWatch(); 37 | int result = MinStringSum.maxSubSum1(a); 38 | double timer = stopWatch.elapsedTime(); 39 | System.out.println("result is : " + result + " spend timers=: " + timer + " seconds"); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/QueueAndStack/BFS.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.QueueAndStack; 2 | 3 | import me.zonglun.SwordToOffer.util.ListNode; 4 | 5 | import java.util.LinkedList; 6 | import java.util.Queue; 7 | 8 | /** 9 | * 广度优先搜索算法 10 | * 11 | * @author : Administrator 12 | * @create 2018-08-30 15:42 13 | */ 14 | public class BFS { 15 | class Node { 16 | int row; // 行列 17 | int column; // 列 18 | int round; // 圈数 19 | 20 | public Node(int row, int column, int round) { 21 | this.row = row; 22 | this.column = column; 23 | this.round = round; 24 | } 25 | } 26 | 27 | // 上下左右 28 | private int[][] direct = {{-1, 0}, {1, 0}, {0, 1}, {0, 1}}; 29 | private int[][] book = new int[4][4]; 30 | private int[][] array = { 31 | {1,2,3,4}, 32 | {5,6,7,8}, 33 | {9,10,11,12}, 34 | {13,14,15,16} 35 | }; 36 | 37 | public void BSTAlgorithms() { 38 | Node start = new Node(0, 0, 0); 39 | Queue queue = new LinkedList<>(); 40 | queue.offer(start); 41 | book[0][0] = 1; 42 | while (queue.size() > 0) { 43 | // 出对对出队元素进行搜索 44 | Node temp = queue.poll(); 45 | for (int i = 0; i < 4; i++) { 46 | int tx = temp.row + direct[i][0]; 47 | int ty = temp.column + direct[i][1]; 48 | if (tx < 0 || ty < 0 || tx >= 4 || ty >= 4) { 49 | continue; 50 | } 51 | if (book[tx][ty] == 1) { 52 | continue; 53 | } 54 | Node next = new Node(tx, ty, temp.round + 1); 55 | book[tx][ty] = 1; 56 | queue.offer(next); 57 | System.out.println("数值:"+array[tx][ty]+",轮次:"+(temp.round+1)); 58 | } 59 | } 60 | } 61 | 62 | public static void main(String[] args) { 63 | new BFS().BSTAlgorithms(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/QueueAndStack/question200/numberOfLslands.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.QueueAndStack.question200; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * 岛屿的个数 7 | * 8 | * @author : Administrator 9 | * @create 2018-08-30 16:03 10 | * @subject : 11 | * 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。 12 | * 一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。 13 | * 你可以假设网格的四个边均被水包围。 14 | * 输入: 15 | * 输入: 16 | * 11110 17 | * 11010 18 | * 11000 19 | * 00000 20 | * 输出: 1 21 | * 22 | * 输入: 23 | * 11000 24 | * 11000 25 | * 00100 26 | * 00011 27 | * 输出: 3 28 | */ 29 | public class numberOfLslands { 30 | 31 | public int numIslands(char[][] grid) { 32 | return 0; 33 | } 34 | 35 | public static void main(String[] args) { 36 | Set books = new HashSet(); 37 | books.add("javaJiangyi"); 38 | books.add("fuck you bbb"); 39 | books.add("gunk your name"); 40 | books.forEach(obj -> System.out.println("obj" + obj)); 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/RundomNumArray.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * @author : Administrator 7 | * @create 2018-11-20 20:58 8 | */ 9 | public class RundomNumArray { 10 | 11 | private static Random rand = new Random(47); 12 | 13 | //生成一个[i,j]之间的随机数 14 | public static int randInt(int i, int j){ 15 | return rand.nextInt(j-i+1) + i; 16 | } 17 | 18 | public static int[] algorithm1(int N) { 19 | int []a = new int[N]; 20 | for (int i = 0; i < a.length; ++i) { 21 | while (true) { 22 | a[i] = randInt(1, N); //生成[1,N]之间的一个随机数 23 | for (int j = 0; j < i; ++j) { 24 | if (a[i] == a[j]) { 25 | break;//如果这个随机数已经在前面出现过了,break,下一轮继续生成另一个随机数,直至a[i]与前面所有的数不同 26 | } 27 | } //end for 28 | 29 | 30 | break;//本次生成的a[i]在前面没有出现过, break while, i++,下一轮生成a[i+1] 31 | }//end while 32 | } 33 | return a; 34 | } 35 | 36 | 37 | public static int[] algorithm3(int N){ 38 | int[] a = new int[N]; 39 | for(int i = 1; i <= N; i++) 40 | a[i-1] = i; 41 | for(int i = 1; i < N; i++) 42 | swapReference(a, i, randInt(0, i)); 43 | return a; 44 | } 45 | 46 | //生成一个即有正数又有负数的随机数组 47 | public static int[] randomArr(int N){ 48 | int [] a = new int[N]; 49 | for(int i = 1; i <= N/2; i++) 50 | a[i-1] = i; 51 | for(int j = N; j > N/2; j--) 52 | a[j-1] = -j; 53 | for(int i = 1; i < N; i++) 54 | swapReference(a, i, randInt(0, i)); 55 | return a; 56 | } 57 | 58 | private static void swapReference(int[] a, int i, int j){ 59 | int tmp = a[i]; 60 | a[i] = a[j]; 61 | a[j] = tmp; 62 | } 63 | 64 | public static void main(String[] args) { 65 | 66 | long start3 = System.currentTimeMillis(); 67 | algorithm3(100000); 68 | System.out.println(System.currentTimeMillis() - start3); 69 | 70 | long start = System.currentTimeMillis(); 71 | algorithm1(100000); 72 | long time = System.currentTimeMillis() - start; 73 | System.out.println(time); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/arrayAndString/Main.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.arrayAndString; 2 | 3 | /** 4 | * @author : Administrator 5 | * @create 2018-08-28 20:20 6 | */ 7 | // "static void main" must be defined in a public class. 8 | public class Main { 9 | public static void main(String[] args) { 10 | // initialize 11 | String s1 = "Hello World"; 12 | System.out.println("s1 is \"" + s1 + "\""); 13 | String s2 = s1; 14 | System.out.println("s2 is another reference to s1."); 15 | String s3 = new String(s1); 16 | System.out.println("s3 is a copy of s1."); 17 | // compare using '==' 18 | System.out.println("Compared by '==':"); 19 | // true since string is immutable and s1 is binded to "Hello World" 20 | System.out.println("s1 and \"Hello World\": " + (s1 == "Hello World")); 21 | // true since s1 and s2 is the reference of the same object 22 | System.out.println("s1 and s2: " + (s1 == s2)); 23 | // false since s3 is refered to another new object 24 | System.out.println("s1 and s3: " + (s1 == s3)); 25 | // compare using 'equals' 26 | System.out.println("Compared by 'equals':"); 27 | System.out.println("s1 and \"Hello World\": " + s1.equals("Hello World")); 28 | System.out.println("s1 and s2: " + s1.equals(s2)); 29 | System.out.println("s1 and s3: " + s1.equals(s3)); 30 | // compare using 'compareTo' 31 | System.out.println("Compared by 'compareTo':"); 32 | System.out.println("s1 and \"Hello World\": " + (s1.compareTo("Hello World") == 0)); 33 | System.out.println("s1 and s2: " + (s1.compareTo(s2) == 0)); 34 | System.out.println("s1 and s3: " + (s1.compareTo(s3) == 0)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/arrayAndString/question1/TwoSum.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.arrayAndString.question1; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 两数之和 8 | * 9 | * @author : Administrator 10 | * @create 2018-09-07 11:39 11 | * @subject : 12 | * 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。 13 | * 14 | * 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。 15 | * 示例: 16 | * 17 | * 给定 nums = [2, 7, 11, 15], target = 9 18 | * 19 | * 因为 nums[0] + nums[1] = 2 + 7 = 9 20 | * 所以返回 [0, 1] 21 | */ 22 | public class TwoSum { 23 | public int[] twoSum(int[] nums, int target) { 24 | Map map = new HashMap<>(); 25 | for (int i = 0; i < nums.length; i++) { 26 | map.put(nums[i], i); 27 | } 28 | for (int i = 0; i < nums.length; i++) { 29 | int complement = target - nums[i]; 30 | if (map.containsKey(complement) && map.get(complement) != i) { 31 | return new int[]{i, map.get(complement)}; 32 | } 33 | } 34 | throw new IllegalArgumentException("NO two sum"); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/linkedList/question138/copylistwithrandompointer.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.linkedList.question138; 2 | 3 | import me.zonglun.leetcode.utils.RandomListNode; 4 | 5 | import java.util.HashMap; 6 | 7 | /** 8 | * 复制带随机指针的链表 9 | * 10 | * @author : Administrator 11 | * @create 2018-08-29 15:59 12 | * @subject : 13 | * 14 | * 给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。 15 | * 16 | * 要求返回这个链表的深度拷贝。 17 | */ 18 | public class copylistwithrandompointer { 19 | 20 | /** 21 | * 给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。 22 | * 用hash存储random节点的下标映射关系,拷贝列表,并根据映射关系对random复原 23 | * @param head 24 | * @return 25 | */ 26 | public RandomListNode copyRandomList(RandomListNode head) { 27 | if (head == null) { 28 | return null; 29 | } 30 | HashMap map = new HashMap<>(); 31 | RandomListNode dummy = new RandomListNode(0); 32 | dummy.next = head; 33 | // 复制节点 34 | while (head != null) { 35 | map.put(head, new RandomListNode(head.label)); 36 | head = head.next; 37 | } 38 | // 复制随机拷贝指针 39 | head = dummy.next; 40 | while (head != null) { 41 | map.get(head).next = map.get(head.next); 42 | map.get(head).random = map.get(head.random); 43 | head = head.next; 44 | } 45 | return map.get(dummy.next); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/linkedList/question141/shileCleIs.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.linkedList.question141; 2 | 3 | import me.zonglun.SwordToOffer.util.ListNode; 4 | 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | 8 | /** 9 | * 环形链表 10 | * 11 | * @author : Administrator 12 | * @create 2018-08-27 16:04 13 | * @subject : 14 | * 给定一个链表,判断链表中是否有环。 15 | */ 16 | class shileCleIs { 17 | 18 | /** 19 | * 方法1:使用hash表来存贮所有判断链表是否为环形链表。常用的方法是使用哈希表。 20 | * 我们遍历所有结点并在哈希表中存储每个结点的引用(或内存地址)。 21 | * 如果当前结点为空结点 null(即已检测到链表尾部的下一个结点), 22 | * 那么我们已经遍历完整个链表,并且该链表不是环形链表。 23 | * 如果当前结点的引用已经存在于哈希表中,那么返回 true(即该链表为环形链表)。 24 | * @param head 25 | * @return head 26 | * 时间复杂度:O(n)O(n), 对于含有 nn 个元素的链表,我们访问每个元素最多一次。添加一个结点到哈希表中只需要花费 O(1)O(1) 的时间。 27 | * 空间复杂度:O(n)O(n), 空间取决于添加到哈希表中的元素数目,最多可以添加 nn 个元素。 28 | */ 29 | public boolean hasCycle(ListNode head) { 30 | Set nodeSet = new HashSet<>(); 31 | while (head != null) { 32 | if (nodeSet.contains(head)) { 33 | return true; 34 | } else { 35 | nodeSet.add(head); 36 | } 37 | head = head.next; 38 | } 39 | return false; 40 | } 41 | 42 | /** 43 | * 第二种方法,双指针法, 44 | * 通过使用具有 不同速度 的快、慢两个指针遍历链表,空间复杂度可以被降低至 O(1)。慢指针每次移动一步,而快指针每次移动两步。 45 | * @param head 46 | * @return 47 | */ 48 | public boolean hasCycle2(ListNode head) { 49 | if (head == null || head.next == null) { 50 | return false; 51 | } 52 | ListNode slow = head; 53 | ListNode fast = head.next; 54 | while (slow != fast) { 55 | if (fast == null || fast.next == null) { 56 | return false; 57 | } 58 | slow = slow.next; 59 | fast = fast.next.next; 60 | } 61 | return true; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/linkedList/question142/linkedlistcycleii.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.linkedList.question142; 2 | 3 | import me.zonglun.SwordToOffer.util.ListNode; 4 | 5 | /** 6 | * 环形链表2 7 | * 8 | * @author : Administrator 9 | * @create 2018-08-27 16:06 10 | * @subject : 11 | * 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 12 | * 13 | * 说明:不允许修改给定的链表。 14 | * 15 | * 进阶: 16 | * 你是否可以不用额外空间解决此题? 17 | */ 18 | public class linkedlistcycleii { 19 | public ListNode detectCycle(ListNode head) { 20 | ListNode slow = head; 21 | ListNode fast = head; 22 | while (fast != null && fast.next != null) { 23 | slow = slow.next; 24 | fast = fast.next.next; 25 | if (fast == slow) { 26 | ListNode fast2 = head; 27 | while (fast2 != slow) { 28 | fast2 = fast2.next; 29 | slow = slow.next; 30 | } 31 | return fast2; 32 | } 33 | } 34 | return null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/linkedList/question160/IntersectionOfTwoLinkedLists.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.linkedList.question160; 2 | 3 | import me.zonglun.SwordToOffer.util.ListNode; 4 | 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | 8 | /** 9 | * 求两个链表的相交的节点 10 | * 11 | * @author : Administrator 12 | * @create 2018-08-27 16:00 13 | * @subject : 14 | *

15 | * 编写一个程序,找到两个单链表相交的起始节点。 16 | *

17 | *

18 | *

19 | * 例如,下面的两个链表: 20 | A: a1 → a2 21 | ↘ 22 | c1 → c2 → c3 23 | ↗ 24 | B: b1 → b2 → b3 25 | * 在节点 c1 开始相交。 26 | *

27 | *

28 | *

29 | * 注意: 30 | *

31 | * 如果两个链表没有交点,返回 null. 32 | * 在返回结果后,两个链表仍须保持原有的结构。 33 | * 可假定整个链表结构中没有循环。 34 | * 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。 35 | */ 36 | public class IntersectionOfTwoLinkedLists { 37 | 38 | public ListNode getIntersectionNode(ListNode headA, ListNode headB) { 39 | int lenthA = length(headA), lengthB = length(headB); 40 | while (lenthA < lengthB) { 41 | headB = headB.next; 42 | lengthB--; 43 | } 44 | while (lenthA > lengthB) { 45 | headA = headA.next; 46 | lenthA--; 47 | } 48 | while (headA != headB) { 49 | headA = headA.next; 50 | headB = headB.next; 51 | } 52 | return headB; 53 | } 54 | 55 | private int length(ListNode head) { 56 | int length = 0; 57 | while (head != null) { 58 | head = head.next; 59 | length++; 60 | } 61 | return length; 62 | } 63 | 64 | public ListNode getIntersectionNode2(ListNode headA, ListNode headB) { 65 | Set nodeSet = new HashSet<>(); 66 | while (headA != null) { 67 | nodeSet.add(headA); 68 | headA = headA.next; 69 | } 70 | while (headB != null) { 71 | if (nodeSet.contains(headB)) { 72 | return headB; 73 | } 74 | headB = headB.next; 75 | } 76 | return null; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/linkedList/question19/removenthnodefromendoflist.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.linkedList.question19; 2 | 3 | import me.zonglun.SwordToOffer.util.ListNode; 4 | 5 | /** 6 | * 删除链表的倒数第N个节点 7 | * 8 | * @author : Administrator 9 | * @create 2018-08-27 16:09 10 | * @subject : 11 | * 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。 12 | * 示例: 13 | * 14 | * 给定一个链表: 1->2->3->4->5, 和 n = 2. 15 | * 16 | * 当删除了倒数第二个节点后,链表变为 1->2->3->5. 17 | * 说明: 18 | * 给定的 n 保证是有效的。 19 | */ 20 | public class removenthnodefromendoflist { 21 | 22 | /** 23 | * 方法1 : 使用两步遍历法则, 24 | * 这个问题可以容易地简化成另一个问题:删除从列表开头数起的第 (L - n + 1)(L−n+1) 个结点, 25 | * 其中 LL 是列表的长度。只要我们找到列表的长度 LL,这个问题就很容易解决。 26 | * 首先我们将添加一个哑结点作为辅助,该结点位于列表头部。 27 | * 哑结点用来简化某些极端情况,例如列表中只含有一个结点,或需要删除列表的头部。 28 | * 在第一次遍历中, 29 | * 我们找出列表的长度 L。然后设置一个指向哑结点的指针,并移动它遍历列表, 30 | * 直至它到达第 (L -n) 个结点那里。 31 | * 我们把第 (L−n) 个结点的 next 指针重新链接至第 (L−n+2) 个结点,完成这个算法。 32 | * @param head 33 | * @param n 34 | * @return 35 | */ 36 | public ListNode removeNthFromEnd(ListNode head, int n) { 37 | ListNode dummy = new ListNode(0); 38 | dummy.next = head; 39 | int length = 0; 40 | ListNode frist = head; 41 | while (frist != null) { 42 | length++; 43 | frist = frist.next; 44 | } 45 | length -= n; 46 | frist = dummy; 47 | while (length > 0) { 48 | length--; 49 | frist = frist.next; 50 | } 51 | frist.next = frist.next.next; 52 | return dummy.next; 53 | } 54 | 55 | /** 56 | * 我们可以使用两个指针而不是一个指针。第一个指针从列表的开头向前移动 n+1n+1 步,而第二个指针将从列表的开头出发。 57 | * 现在,这两个指针被 nn 个结点分开。我们通过同时移动两个指针向前来保持这个恒定的间隔,直到第一个指针到达最后一个结点。 58 | * 此时第二个指针将指向从最后一个结点数起的第 nn 个结点。我们重新链接第二个指针所引用的结点的 next 指针指向该结点的下下个结点 59 | * @param head 60 | * @param n 61 | * @return 62 | */ 63 | public ListNode removeNthNode2(ListNode head, int n) { 64 | ListNode dummy = new ListNode(0); 65 | dummy.next = head; 66 | ListNode first = dummy; 67 | ListNode second = dummy; 68 | // 向前移动n个指针,使得其前一个指针移动的距离是后面的n个 69 | for (int i = 0; i < n + 1; i++) { 70 | first = first.next; 71 | } 72 | while (first != null) { 73 | first = first.next; 74 | second = second.next; 75 | } 76 | // 删除倒数第n个节点 77 | second.next = second.next.next; 78 | return dummy.next; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/linkedList/question203/removelinkedlistelements.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.linkedList.question203; 2 | 3 | import me.zonglun.SwordToOffer.util.ListNode; 4 | 5 | /** 6 | * 删除链表中给定元素的节点 7 | * 8 | * @author : Administrator 9 | * @create 2018-08-28 16:53 10 | * @subject : 11 | * 删除链表中等于给定值 val 的所有节点。 12 | * 示例: 13 | * 14 | * 输入: 1->2->6->3->4->5->6, val = 6 15 | * 输出: 1->2->3->4->5 16 | */ 17 | public class removelinkedlistelements { 18 | 19 | 20 | public ListNode removeElements(ListNode head, int val) { 21 | ListNode dummy = new ListNode(0); 22 | dummy.next = head; 23 | ListNode cur = head, pre = dummy; 24 | while (cur != null) { 25 | if (cur.val == val) { 26 | // 删除 27 | pre.next = cur.next; 28 | } else { 29 | pre = pre.next; 30 | } 31 | cur = cur.next; 32 | } 33 | return dummy.next; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/linkedList/question206/reverseLinkedList.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.linkedList.question206; 2 | 3 | import me.zonglun.SwordToOffer.util.ListNode; 4 | 5 | /** 6 | * 反转链表 7 | * 8 | * @author : Administrator 9 | * @create 2018-08-26 13:04 10 | * @subject : 11 | * 反转一个单链表,不可额外的申请空间 12 | * 示例: 13 | * 输入: 1->2->3->4->5->NULL 14 | * 输出: 5->4->3->2->1->NULL 15 | * 你可以迭代或递归地反转链表。你能否用两种方法解决这道题? 16 | */ 17 | public class reverseLinkedList { 18 | 19 | /** 20 | * 迭代的方法 21 | * @param head 22 | * @return 23 | */ 24 | public ListNode reverseList(ListNode head) { 25 | ListNode pre = null; 26 | while (head != null) { 27 | ListNode temp = head.next; 28 | head.next = pre; 29 | pre = head; // 备份指正 30 | head = temp; 31 | } 32 | return pre; 33 | } 34 | 35 | /** 36 | * 递归的解决方法 37 | * @param head 38 | * @return 39 | */ 40 | public ListNode reverseList2(ListNode head) { 41 | if (head == null || head.next == null) { 42 | return head; 43 | } 44 | ListNode node = reverseList(head.next); 45 | head.next.next = head; 46 | head.next = null; 47 | return node; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/linkedList/question21/mergeTwoSortedLists.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.linkedList.question21; 2 | 3 | import me.zonglun.SwordToOffer.util.ListNode; 4 | 5 | /** 6 | * 合并两个有序的链表 7 | * 8 | * @author : Administrator 9 | * @create 2018-08-29 17:10 10 | * @subject : 11 | * 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 12 | * 示例: 13 | * 14 | * 输入:1->2->4, 1->3->4 15 | * 输出:1->1->2->3->4->4 16 | */ 17 | public class mergeTwoSortedLists { 18 | 19 | public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 20 | ListNode dummy = new ListNode(0); 21 | ListNode cur = dummy; 22 | while (l1 != null && l2 != null) { 23 | if (l1.val <= l2.val) { 24 | cur.next = l1; 25 | l1 = l1.next; 26 | } else { 27 | cur.next = l2; 28 | l2 = l2.next; 29 | } 30 | cur = cur.next; 31 | } 32 | // 如果l1有剩余,单独将它接到后面 33 | if (l1 != null) { 34 | cur.next = l1; 35 | // 如果l2有剩余,单独将他接到后面 36 | } else { 37 | cur.next = l2; 38 | } 39 | return dummy.next; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/linkedList/question23/mergeksortedlists.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.linkedList.question23; 2 | 3 | import me.zonglun.SwordToOffer.util.ListNode; 4 | 5 | import java.util.Comparator; 6 | import java.util.PriorityQueue; 7 | 8 | /** 9 | * 合并K个排序链表 10 | * 11 | * @author : Administrator 12 | * @create 2018-08-29 17:23 13 | * @subject : 14 | * 合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。 15 | * 输入: 16 | * [ 17 | * 1->4->5, 18 | * 1->3->4, 19 | * 2->6 20 | * ] 21 | * 输出: 1->1->2->3->4->4->5->6 22 | */ 23 | public class mergeksortedlists { 24 | 25 | public ListNode mergeKLists(ListNode[] lists) { 26 | if (lists == null || lists.length == 0) { 27 | return null; 28 | } 29 | PriorityQueue queue = new PriorityQueue<>(lists.length, new Comparator() { 30 | @Override 31 | public int compare(ListNode o1, ListNode o2) { 32 | return o1.val - o2.val; 33 | } 34 | }); 35 | ListNode dummy = new ListNode(0); 36 | ListNode cur = dummy; 37 | for (ListNode node : lists) { 38 | if (node != null) { 39 | queue.add(node); 40 | } 41 | } 42 | while (!queue.isEmpty()) { 43 | cur.next = queue.poll(); 44 | cur = cur.next; 45 | if (cur.next != null) { 46 | queue.add(cur.next); 47 | } 48 | } 49 | return dummy.next; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/linkedList/question234/palindromelinkedlist.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.linkedList.question234; 2 | 3 | import me.zonglun.SwordToOffer.util.ListNode; 4 | 5 | /** 6 | * 回文链表 7 | * 8 | * @author : Administrator 9 | * @create 2018-08-28 19:54 10 | * @subject : 11 | * 请判断一个链表是否为回文链表。 12 | * 示例 1: 13 | * 输入: 1->2 14 | * 输出: false 15 | * 示例 2: 16 | * 输入: 1->2->2->1 17 | * 输出: true 18 | */ 19 | public class palindromelinkedlist { 20 | 21 | /** 22 | * 思路就是先找到中间的节点,然后反转,前后两端节点逐一对比 23 | * @param head 24 | * @return 25 | */ 26 | public boolean isPalindrome(ListNode head) { 27 | if (head == null) { 28 | return true; 29 | } 30 | ListNode middle = findMiddle(head); 31 | middle.next = reverse(middle.next); 32 | ListNode p1 = head, p2 = middle.next; 33 | while (p1 != null && p2 != null && p1.val == p2.val) { 34 | p1 = p1.next; 35 | p2 = p2.next; 36 | } 37 | return p2 == null; 38 | } 39 | 40 | private ListNode findMiddle(ListNode head) { 41 | if (head == null) { 42 | return null; 43 | } 44 | ListNode slow = head, fast = head.next; 45 | while (fast != null && fast.next != null) { 46 | slow = slow.next; 47 | fast = fast.next.next; 48 | } 49 | return slow; 50 | } 51 | 52 | private ListNode reverse(ListNode head) { 53 | ListNode pre = null; 54 | while (head != null) { 55 | ListNode temp = head.next; 56 | head.next = pre; 57 | pre = head; 58 | head = temp; 59 | } 60 | return pre; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/linkedList/question86/partitionList.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.linkedList.question86; 2 | 3 | import me.zonglun.SwordToOffer.util.ListNode; 4 | 5 | /** 6 | * 分割链表 7 | * 8 | * @author : Administrator 9 | * @create 2018-08-29 11:47 10 | * @subject : 11 | * 给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。 12 | * 13 | * 你应当保留两个分区中每个节点的初始相对位置。 14 | * 示例: 15 | * 输入: head = 1->4->3->2->5->2, x = 3 16 | * 输出: 1->2->2->4->3->5 17 | */ 18 | public class partitionList { 19 | 20 | public ListNode partition(ListNode head, int x) { 21 | ListNode dummy1 = new ListNode(0); 22 | ListNode dummy2 = new ListNode(0); 23 | ListNode dummyhead1 = dummy1, dummyhead2 = dummy2; 24 | while (head != null) { 25 | if (head.val < x) { 26 | dummyhead1.next = head; 27 | dummyhead1 = head; 28 | } else { 29 | dummyhead2.next = head; 30 | dummyhead2 = head; 31 | } 32 | head = head.next; 33 | } 34 | // 防止出现环节点的情况 35 | dummyhead2.next = null; 36 | dummyhead1.next = dummy2.next; 37 | return dummy1.next; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/linkedList/question92/reverseLinkedList2.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.linkedList.question92; 2 | 3 | import me.zonglun.SwordToOffer.util.ListNode; 4 | 5 | /** 6 | * 反转链表2 7 | * 8 | * @author : Administrator 9 | * @create 2018-08-26 20:44 10 | * @subject : 11 | * 反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。 12 | * 13 | * 说明: 14 | * 1 ≤ m ≤ n ≤ 链表长度。 15 | * 16 | * 示例: 17 | * 18 | * 输入: 1->2->3->4->5->NULL, m = 2, n = 4 19 | * 输出: 1->4->3->2->5->NULL 20 | */ 21 | public class reverseLinkedList2 { 22 | 23 | public ListNode reverseBetween(ListNode head, int m, int n) { 24 | if (head == null) return null; 25 | // create a dummy node to mark the head of this list 26 | ListNode dummy = new ListNode(0); 27 | dummy.next = head; 28 | // make a pointer pre as a marker for the node before reversing 29 | ListNode pre = dummy; 30 | for (int i = 0; i < m -1; i++) { 31 | pre = pre.next; 32 | } 33 | // a pointer to the beginning of a sub-list that will be reversed 34 | ListNode start = pre.next; 35 | // a pointer to a node that will be reversed 36 | ListNode then = start.next; 37 | // 1 - 2 -3 - 4 - 5 ; m=2; n =4 ---> pre = 1, start = 2, then = 3 38 | // dummy-> 1 -> 2 -> 3 -> 4 -> 5 39 | // 反转过程采用尾插法,就是将start后面的节点逐步删除,后移到反转链表的头部 40 | for (int i = 0; i < n - m; i++) { 41 | // 第一步先删除 then节点 42 | start.next = then.next; 43 | // 第二步添加两个指针,pre后面的节点的中间 44 | then.next = pre.next; 45 | pre.next = then; 46 | // 最后跟新then的值使他始终指向start的后面 47 | then = start.next; 48 | } 49 | // at the begin : dummy-> 1 -> 2 -> 3 -> 4 -> 5; pre = 1, start = 2, then = 3 50 | 51 | // first reversing : dummy->1 - 3 - 2 - 4 - 5; pre = 1, start = 2, then = 4 52 | // second reversing: dummy->1 - 4 - 3 - 2 - 5; pre = 1, start = 2, then = 5 (finish) 53 | return dummy.next; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/utils/RandomListNode.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.utils; 2 | 3 | /** 4 | * 随机指针 5 | * 6 | * @author : Administrator 7 | * @create 2018-08-29 16:01 8 | */ 9 | public class RandomListNode { 10 | public int label; 11 | public RandomListNode next, random; 12 | 13 | public RandomListNode(int x) { 14 | this.label = x; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/me/zonglun/leetcode/utils/StopWatch.java: -------------------------------------------------------------------------------- 1 | package me.zonglun.leetcode.utils; 2 | 3 | /** 4 | * @author : Administrator 5 | * @create 2018-11-20 16:29 6 | */ 7 | public class StopWatch { 8 | private final long start; 9 | 10 | public StopWatch() { 11 | start = System.currentTimeMillis(); 12 | } 13 | 14 | public double elapsedTime() { 15 | long now = System.currentTimeMillis(); 16 | return (now - start) / 1000.0; 17 | } 18 | 19 | } 20 | --------------------------------------------------------------------------------