[
  {
    "path": "README.md",
    "content": "来到这里的朋友们，很高兴你们能看到小灰的拙作。\n小灰把书中各个章节所涉及到的代码，都总结到了这个项目当中，让大家可以更方便地学习和调试。\n小伙伴们对代码有哪些问题和意见，也欢迎向小灰提出，在这里感谢大家的支持！\n\n最后，欢迎大家关注小灰的技术公众号，直接在微信上搜索 “程序员小灰” 即可看到。\n\n祝大家在算法的道路上学有所成！\n\n针对《漫画算法》的第一次印刷版本，小灰整理了一个勘误表，欢迎大家指正：http://mp.weixin.qq.com/s?__biz=MzIxMjE5MTE1Nw==&mid=505714242&idx=1&sn=59526f45b94db2f4be750273431e8867&chksm=0c99e4983bee6d8eb4beed7f6143bbbc00659f32056b37db1d3f1b925ca6867d7d2c34d6ad64#rd\n"
  },
  {
    "path": "src/chapter1/part2/TimeComplex.java",
    "content": "package chapter1.part2;\r\n\r\n/**\r\n * Created by weimengshu on 2018/8/24.\r\n */\r\npublic class TimeComplex {\r\n\r\n    void eat1(int n){\r\n        for(int i=0; i<n; i++){;\r\n            System.out.println(\"等待一天\");\r\n            System.out.println(\"等待一天\");\r\n            System.out.println(\"吃一寸面包\");\r\n        }\r\n    }\r\n\r\n    void eat2(int n){\r\n        for(int i=n; i>1; i/=2){\r\n            System.out.println(\"等待一天\");\r\n            System.out.println(\"等待一天\");\r\n            System.out.println(\"等待一天\");\r\n            System.out.println(\"等待一天\");\r\n            System.out.println(\"吃一半面包\");\r\n        }\r\n    }\r\n\r\n    void eat3(int n){\r\n        System.out.println(\"等待一天\");\r\n        System.out.println(\"吃一个鸡腿\");\r\n    }\r\n\r\n    void eat4(int n){\r\n        for(int i=0; i<n; i++){\r\n            for(int j=0; j<i; j++){\r\n                System.out.println(\"等待一天\");\r\n            }\r\n            System.out.println(\"吃一寸面包\");\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter1/part3/SpaceComplex.java",
    "content": "package chapter1.part3;\r\n\r\n/**\r\n * Created by weimengshu on 2018/8/24.\r\n */\r\npublic class SpaceComplex {\r\n\r\n    void fun1(int n){\r\n        int var = 3;\r\n        //do something\r\n    }\r\n\r\n    void fun2(int n){\r\n        int[] array = new int[n];\r\n        //do something\r\n    }\r\n\r\n    void fun3(int n){\r\n        int[][] matrix = new int[n][n];\r\n        //do something\r\n    }\r\n\r\n    void fun4(int n){\r\n        if(n<=0){\r\n            return;\r\n        }\r\n        fun4(n-1);\r\n        //do something\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter2/part1/MyArray.java",
    "content": "package chapter2.part1;\r\n\r\n/**\r\n * Created by weimengshu on 2018/8/24.\r\n */\r\npublic class MyArray {\r\n\r\n    private int[] array;\r\n    private int size;\r\n\r\n    public MyArray(int capacity){\r\n        this.array = new int[capacity];\r\n        size = 0;\r\n    }\r\n\r\n    /**\r\n     * 数组插入元素\r\n     * @param index  插入的位置\r\n     * @param element  插入的元素\r\n     */\r\n    public void insert(int index, int element) throws Exception {\r\n        //判断访问下标是否超出范围\r\n        if(index<0 || index>size){\r\n            throw new IndexOutOfBoundsException(\"超出数组实际元素范围！\");\r\n        }\r\n        //如果实际元素达到数组容量上线，数组扩容\r\n        if(size >= array.length){\r\n            resize();\r\n        }\r\n        //从右向左循环，逐个元素向右挪一位。\r\n        for(int i=size-1; i>=index; i--){\r\n            array[i+1] = array[i];\r\n        }\r\n        //腾出的位置放入新元素\r\n        array[index] = element;\r\n        size++;\r\n    }\r\n\r\n    /**\r\n     * 数组扩容\r\n     */\r\n    public void resize(){\r\n        int[] arrayNew = new int[array.length*2];\r\n        //从旧数组拷贝到新数组\r\n        System.arraycopy(array, 0, arrayNew, 0, array.length);\r\n        array = arrayNew;\r\n    }\r\n\r\n    /**\r\n     * 数组删除元素\r\n     * @param index  删除的位置\r\n     */\r\n    public int delete(int index) throws Exception {\r\n        //判断访问下标是否超出范围\r\n        if(index<0 || index>=size){\r\n            throw new IndexOutOfBoundsException(\"超出数组实际元素范围！\");\r\n        }\r\n        int deletedElement = array[index];\r\n        //从左向右循环，逐个元素向左挪一位。\r\n        for(int i=index; i<size-1; i++){\r\n            array[i] = array[i+1];\r\n        }\r\n        size--;\r\n        return deletedElement;\r\n    }\r\n\r\n    /**\r\n     * 输出数组\r\n     */\r\n    public void output(){\r\n        for(int i=0; i<size; i++){\r\n            System.out.println(array[i]);\r\n        }\r\n    }\r\n\r\n    public static void main(String[] args) throws Exception {\r\n        MyArray myArray = new MyArray(4);\r\n        myArray.insert(0,3);\r\n        myArray.insert(1,7);\r\n        myArray.insert(2,9);\r\n        myArray.insert(3,5);\r\n        myArray.insert(1,6);\r\n        myArray.insert(5,8);\r\n        myArray.delete(3);\r\n        myArray.output();\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter2/part2/MyLinkedList.java",
    "content": "package chapter2.part2;\r\n\r\n/**\r\n * Created by weimengshu on 2018/8/24.\r\n */\r\npublic class MyLinkedList {\r\n\r\n    //头节点指针\r\n    private Node head;\r\n    //尾节点指针\r\n    private Node last;\r\n    //链表实际长度\r\n    private int size;\r\n\r\n    /**\r\n     * 链表插入元素\r\n     * @param index  插入位置\r\n     * @param data  插入元素\r\n     */\r\n    public void insert(int index, int data) throws Exception {\r\n        if (index<0 || index>size) {\r\n            throw new IndexOutOfBoundsException(\"超出链表节点范围！\");\r\n        }\r\n        Node insertedNode = new Node(data);\r\n        if(size == 0){\r\n            //空链表\r\n            head = insertedNode;\r\n            last = insertedNode;\r\n        } else if(index == 0){\r\n            //插入头部\r\n            insertedNode.next = head;\r\n            head = insertedNode;\r\n        }else if(size == index){\r\n            //插入尾部\r\n            last.next = insertedNode;\r\n            last = insertedNode;\r\n        }else {\r\n            //插入中间\r\n            Node prevNode = get(index-1);\r\n            insertedNode.next = prevNode.next;\r\n            prevNode.next = insertedNode;\r\n        }\r\n        size++;\r\n    }\r\n\r\n    /**\r\n     * 链表删除元素\r\n     * @param index  删除的位置\r\n     */\r\n    public Node remove(int index) throws Exception {\r\n        if (index<0 || index>=size) {\r\n            throw new IndexOutOfBoundsException(\"超出链表节点范围！\");\r\n        }\r\n        Node removedNode = null;\r\n        if(index == 0){\r\n            //删除头节点\r\n            removedNode = head;\r\n            head = head.next;\r\n            if(size == 1){\r\n                last = null;\r\n            }\r\n        }else if(index == size-1){\r\n            //删除尾节点\r\n            Node prevNode = get(index-1);\r\n            removedNode = prevNode.next;\r\n            prevNode.next = null;\r\n            last = prevNode;\r\n        }else {\r\n            //删除中间节点\r\n            Node prevNode = get(index-1);\r\n            Node nextNode = prevNode.next.next;\r\n            removedNode = prevNode.next;\r\n            prevNode.next = nextNode;\r\n        }\r\n        size--;\r\n        return removedNode;\r\n    }\r\n\r\n    /**\r\n     * 链表查找元素\r\n     * @param index  查找的位置\r\n     */\r\n    public Node get(int index) throws Exception {\r\n        if (index<0 || index>=size) {\r\n            throw new IndexOutOfBoundsException(\"超出链表节点范围！\");\r\n        }\r\n        Node temp = head;\r\n        for(int i=0; i<index; i++){\r\n            temp = temp.next;\r\n        }\r\n        return temp;\r\n    }\r\n\r\n    /**\r\n     * 输出链表\r\n     */\r\n    public void output(){\r\n        Node temp = head;\r\n        while (temp!=null) {\r\n            System.out.println(temp.data);\r\n            temp = temp.next;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * 链表节点\r\n     */\r\n    private static class Node {\r\n        int data;\r\n        Node next;\r\n\r\n        Node(int data) {\r\n            this.data = data;\r\n        }\r\n    }\r\n\r\n    public static void main(String[] args) throws Exception {\r\n        MyLinkedList myLinkedList = new MyLinkedList();\r\n        myLinkedList.insert(0,3);\r\n        myLinkedList.insert(0,4);\r\n        myLinkedList.insert(2,9);\r\n        myLinkedList.insert(3,5);\r\n        myLinkedList.insert(1,6);\r\n        myLinkedList.remove(0);\r\n        myLinkedList.output();\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter2/part3/MyQueue.java",
    "content": "package chapter2.part3;\r\n\r\n/**\r\n * Created by weimengshu on 2018/8/24.\r\n */\r\npublic class MyQueue {\r\n\r\n    private int[] array;\r\n    private int front;\r\n    private int rear;\r\n\r\n    public MyQueue(int capacity){\r\n        this.array = new int[capacity];\r\n    }\r\n\r\n    /**\r\n     * 入队\r\n     * @param element  入队的元素\r\n     */\r\n    public void enQueue(int element) throws Exception {\r\n        if((rear+1)%array.length == front){\r\n            throw new Exception(\"队列已满！\");\r\n        }\r\n        array[rear] = element;\r\n        rear =(rear+1)%array.length;\r\n    }\r\n\r\n    /**\r\n     * 出队\r\n     */\r\n    public int deQueue() throws Exception {\r\n        if(rear == front){\r\n            throw new Exception(\"队列已空！\");\r\n        }\r\n        int deQueueElement = array[front];\r\n        front =(front+1)%array.length;\r\n        return deQueueElement;\r\n    }\r\n\r\n    /**\r\n     * 输出队列\r\n     */\r\n    public void output(){\r\n        for(int i=front; i!=rear; i=(i+1)%array.length){\r\n            System.out.println(array[i]);\r\n        }\r\n    }\r\n\r\n    public static void main(String[] args) throws Exception {\r\n        MyQueue myQueue = new MyQueue(6);\r\n        myQueue.enQueue(3);\r\n        myQueue.enQueue(5);\r\n        myQueue.enQueue(6);\r\n        myQueue.enQueue(8);\r\n        myQueue.enQueue(1);\r\n        myQueue.deQueue();\r\n        myQueue.deQueue();\r\n        myQueue.deQueue();\r\n        myQueue.enQueue(2);\r\n        myQueue.enQueue(4);\r\n        myQueue.enQueue(9);\r\n        myQueue.output();\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter3/part2/BinaryTreeTraversal.java",
    "content": "package chapter3.part2;\r\n\r\nimport java.util.Arrays;\r\nimport java.util.LinkedList;\r\n\r\n/**\r\n * Created by weimengshu on 2018/9/22.\r\n */\r\npublic class BinaryTreeTraversal {\r\n\r\n    /**\r\n     * 构建二叉树\r\n     * @param inputList   输入序列\r\n     */\r\n    public static TreeNode createBinaryTree(LinkedList<Integer> inputList){\r\n        TreeNode node = null;\r\n        if(inputList==null || inputList.isEmpty()){\r\n            return null;\r\n        }\r\n        Integer data = inputList.removeFirst();\r\n        //这里的判空很关键。如果元素是空，说明该节点不存在，跳出这一层递归；如果元素非空，继续递归构建该节点的左右孩子。\r\n        if(data != null){\r\n            node = new TreeNode(data);\r\n            node.leftChild = createBinaryTree(inputList);\r\n            node.rightChild = createBinaryTree(inputList);\r\n        }\r\n        return node;\r\n    }\r\n\r\n    /**\r\n     * 二叉树前序遍历\r\n     * @param node   二叉树节点\r\n     */\r\n    public static void preOrderTraversal(TreeNode node){\r\n        if(node == null){\r\n            return;\r\n        }\r\n        System.out.println(node.data);\r\n        preOrderTraversal(node.leftChild);\r\n        preOrderTraversal(node.rightChild);\r\n    }\r\n\r\n    /**\r\n     * 二叉树中序遍历\r\n     * @param node   二叉树节点\r\n     */\r\n    public static void inOrderTraversal(TreeNode node){\r\n        if(node == null){\r\n            return;\r\n        }\r\n        inOrderTraversal(node.leftChild);\r\n        System.out.println(node.data);\r\n        inOrderTraversal(node.rightChild);\r\n    }\r\n\r\n\r\n    /**\r\n     * 二叉树后序遍历\r\n     * @param node   二叉树节点\r\n     */\r\n    public static void postOrderTraversal(TreeNode node){\r\n        if(node == null){\r\n            return;\r\n        }\r\n        postOrderTraversal(node.leftChild);\r\n        postOrderTraversal(node.rightChild);\r\n        System.out.println(node.data);\r\n    }\r\n\r\n    /**\r\n     * 二叉树节点\r\n     */\r\n    private static class TreeNode {\r\n        int data;\r\n        TreeNode leftChild;\r\n        TreeNode rightChild;\r\n\r\n        TreeNode(int data) {\r\n            this.data = data;\r\n        }\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        LinkedList<Integer> inputList = new LinkedList<Integer>(Arrays.asList(new Integer[]{3,2,9,null,null,10,null,null,8,null,4,}));\r\n        TreeNode treeNode = createBinaryTree(inputList);\r\n        System.out.println(\"前序遍历：\");\r\n        preOrderTraversal(treeNode);\r\n        System.out.println(\"中序遍历：\");\r\n        inOrderTraversal(treeNode);\r\n        System.out.println(\"后序遍历：\");\r\n        postOrderTraversal(treeNode);\r\n    }\r\n\r\n}\r\n"
  },
  {
    "path": "src/chapter3/part2/BinaryTreeTraversalLevel.java",
    "content": "package chapter3.part2;\r\n\r\nimport java.util.Arrays;\r\nimport java.util.LinkedList;\r\nimport java.util.Queue;\r\n\r\n/**\r\n * Created by weimengshu on 2018/9/22.\r\n */\r\npublic class BinaryTreeTraversalLevel {\r\n\r\n    /**\r\n     * 构建二叉树\r\n     * @param inputList   输入序列\r\n     */\r\n    public static TreeNode createBinaryTree(LinkedList<Integer> inputList){\r\n        TreeNode node = null;\r\n        if(inputList==null || inputList.isEmpty()){\r\n            return null;\r\n        }\r\n        Integer data = inputList.removeFirst();\r\n        //这里的判空很关键。如果元素是空，说明该节点不存在，跳出这一层递归；如果元素非空，继续递归构建该节点的左右孩子。\r\n        if(data != null){\r\n            node = new TreeNode(data);\r\n            node.leftChild = createBinaryTree(inputList);\r\n            node.rightChild = createBinaryTree(inputList);\r\n        }\r\n        return node;\r\n    }\r\n\r\n    /**\r\n     * 二叉树层序遍历\r\n     * @param root   二叉树根节点\r\n     */\r\n    public static void levelOrderTraversal(TreeNode root){\r\n        Queue<TreeNode> queue = new LinkedList<TreeNode>();\r\n        queue.offer(root);\r\n        while(!queue.isEmpty()){\r\n            TreeNode node = queue.poll();\r\n            System.out.println(node.data);\r\n            if(node.leftChild != null){\r\n                queue.offer(node.leftChild);\r\n            }\r\n            if(node.rightChild != null){\r\n                queue.offer(node.rightChild);\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * 二叉树节点\r\n     */\r\n    private static class TreeNode {\r\n        int data;\r\n        TreeNode leftChild;\r\n        TreeNode rightChild;\r\n\r\n        TreeNode(int data) {\r\n            this.data = data;\r\n        }\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        LinkedList<Integer> inputList = new LinkedList<Integer>(Arrays.asList(new Integer[]{3,2,9,null,null,10,null,null,8,null,4,}));\r\n        TreeNode treeNode = createBinaryTree(inputList);\r\n        System.out.println(\"层序遍历：\");\r\n        levelOrderTraversal(treeNode);\r\n    }\r\n\r\n}\r\n"
  },
  {
    "path": "src/chapter3/part2/BinaryTreeTraversalStack.java",
    "content": "package chapter3.part2;\r\n\r\nimport java.util.Arrays;\r\nimport java.util.LinkedList;\r\nimport java.util.Stack;\r\n\r\n/**\r\n * Created by weimengshu on 2018/9/22.\r\n */\r\npublic class BinaryTreeTraversalStack {\r\n\r\n    /**\r\n     * 构建二叉树\r\n     * @param inputList   输入序列\r\n     */\r\n    public static TreeNode createBinaryTree(LinkedList<Integer> inputList){\r\n        TreeNode node = null;\r\n        if(inputList==null || inputList.isEmpty()){\r\n            return null;\r\n        }\r\n        Integer data = inputList.removeFirst();\r\n        //这里的判空很关键。如果元素是空，说明该节点不存在，跳出这一层递归；如果元素非空，继续递归构建该节点的左右孩子。\r\n        if(data != null){\r\n            node = new TreeNode(data);\r\n            node.leftChild = createBinaryTree(inputList);\r\n            node.rightChild = createBinaryTree(inputList);\r\n        }\r\n        return node;\r\n    }\r\n\r\n    /**\r\n     * 二叉树非递归前序遍历\r\n     * @param root   二叉树根节点\r\n     */\r\n    public static void preOrderTraveralWithStack(TreeNode root){\r\n        Stack<TreeNode> stack = new Stack<TreeNode>();\r\n        TreeNode treeNode = root;\r\n        while(treeNode!=null || !stack.isEmpty()){\r\n            //迭代访问节点的左孩子，并入栈\r\n            while (treeNode != null){\r\n                System.out.println(treeNode.data);\r\n                stack.push(treeNode);\r\n                treeNode = treeNode.leftChild;\r\n            }\r\n            //如果节点没有左孩子，则弹出栈顶节点，访问节点右孩子\r\n            if(!stack.isEmpty()){\r\n                treeNode = stack.pop();\r\n                treeNode = treeNode.rightChild;\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * 二叉树节点\r\n     */\r\n    private static class TreeNode {\r\n        int data;\r\n        TreeNode leftChild;\r\n        TreeNode rightChild;\r\n\r\n        TreeNode(int data) {\r\n            this.data = data;\r\n        }\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        LinkedList<Integer> inputList = new LinkedList<Integer>(Arrays.asList(new Integer[]{3,2,9,null,null,10,null,null,8,null,4,}));\r\n        TreeNode treeNode = createBinaryTree(inputList);\r\n        preOrderTraveralWithStack(treeNode);\r\n    }\r\n\r\n}\r\n"
  },
  {
    "path": "src/chapter3/part3/HeapOperator.java",
    "content": "package chapter3.part3;\r\n\r\n/**\r\n * Created by weimengshu on 2018/7/13.\r\n */\r\nimport java.util.Arrays;\r\n\r\npublic class HeapOperator {\r\n\r\n    /**\r\n     * 上浮调整\r\n     * @param array     待调整的堆\r\n     */\r\n    public static void upAdjust(int[] array) {\r\n        int childIndex = array.length-1;\r\n        int parentIndex = (childIndex-1)/2;\r\n        // temp保存插入的叶子节点值，用于最后的赋值\r\n        int temp = array[childIndex];\r\n        while (childIndex > 0 && temp < array[parentIndex])\r\n        {\r\n            //无需真正交换，单向赋值即可\r\n            array[childIndex] = array[parentIndex];\r\n            childIndex = parentIndex;\r\n            parentIndex = (parentIndex-1) / 2;\r\n        }\r\n        array[childIndex] = temp;\r\n    }\r\n\r\n    /**\r\n     * 下沉调整\r\n     * @param array     待调整的堆\r\n     * @param parentIndex    要下沉的父节点\r\n     * @param length    堆的有效大小\r\n     */\r\n    public static void downAdjust(int[] array, int parentIndex, int length) {\r\n        // temp保存父节点值，用于最后的赋值\r\n        int temp = array[parentIndex];\r\n        int childIndex = 2 * parentIndex + 1;\r\n        while (childIndex < length) {\r\n            // 如果有右孩子，且右孩子小于左孩子的值，则定位到右孩子\r\n            if (childIndex + 1 < length && array[childIndex + 1] < array[childIndex]) {\r\n                childIndex++;\r\n            }\r\n            // 如果父节点小于任何一个孩子的值，直接跳出\r\n            if (temp <= array[childIndex])\r\n                break;\r\n            //无需真正交换，单向赋值即可\r\n            array[parentIndex] = array[childIndex];\r\n            parentIndex = childIndex;\r\n            childIndex = 2 * childIndex + 1;\r\n        }\r\n        array[parentIndex] = temp;\r\n    }\r\n\r\n    /**\r\n     * 构建堆\r\n     * @param array     待调整的堆\r\n     */\r\n    public static void buildHeap(int[] array) {\r\n        // 从最后一个非叶子节点开始，依次下沉调整\r\n        for (int i = (array.length-2)/2; i >= 0; i--) {\r\n            downAdjust(array, i, array.length);\r\n        }\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        int[] array = new int[] {1,3,2,6,5,7,8,9,10,0};\r\n        upAdjust(array);\r\n        System.out.println(Arrays.toString(array));\r\n\r\n        array = new int[] {7,1,3,10,5,2,8,9,6};\r\n        buildHeap(array);\r\n        System.out.println(Arrays.toString(array));\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter3/part4/PriorityQueue.java",
    "content": "package chapter3.part4;\r\n\r\n/**\r\n * Created by weimengshu on 2018/7/13.\r\n */\r\nimport java.util.Arrays;\r\n\r\npublic class PriorityQueue {\r\n\r\n    private int[] array;\r\n    private int size;\r\n\r\n    public PriorityQueue(){\r\n        //队列初始长度32\r\n        array = new int[32];\r\n    }\r\n\r\n    /**\r\n     * 入队\r\n     * @param key  入队元素\r\n     */\r\n    public void enQueue(int key) {\r\n        //队列长度超出范围，扩容\r\n        if(size >= array.length){\r\n            resize();\r\n        }\r\n        array[size++] = key;\r\n        upAdjust();\r\n    }\r\n\r\n    /**\r\n     * 出队\r\n     */\r\n    public int deQueue() throws Exception {\r\n        if(size <= 0){\r\n            throw new Exception(\"the queue is empty !\");\r\n        }\r\n        //获取堆顶元素\r\n        int head = array[0];\r\n        //最后一个元素移动到堆顶\r\n        array[0] = array[--size];\r\n        downAdjust();\r\n        return head;\r\n    }\r\n\r\n    /**\r\n     * 上浮调整\r\n     */\r\n    private void upAdjust() {\r\n        int childIndex = size-1;\r\n        int parentIndex = (childIndex-1)/2;\r\n        // temp保存插入的叶子节点值，用于最后的赋值\r\n        int temp = array[childIndex];\r\n        while (childIndex > 0 && temp > array[parentIndex])\r\n        {\r\n            //无需真正交换，单向赋值即可\r\n            array[childIndex] = array[parentIndex];\r\n            childIndex = parentIndex;\r\n            parentIndex = (parentIndex-1) / 2;\r\n        }\r\n        array[childIndex] = temp;\r\n    }\r\n\r\n    /**\r\n     * 下沉调整\r\n     */\r\n    private void downAdjust() {\r\n        // temp保存父节点值，用于最后的赋值\r\n        int parentIndex = 0;\r\n        int temp = array[parentIndex];\r\n        int childIndex = 1;\r\n        while (childIndex < size) {\r\n            // 如果有右孩子，且右孩子大于左孩子的值，则定位到右孩子\r\n            if (childIndex + 1 < size && array[childIndex + 1] > array[childIndex]) {\r\n                childIndex++;\r\n            }\r\n            // 如果父节点大于任何一个孩子的值，直接跳出\r\n            if (temp >= array[childIndex])\r\n                break;\r\n            //无需真正交换，单向赋值即可\r\n            array[parentIndex] = array[childIndex];\r\n            parentIndex = childIndex;\r\n            childIndex = 2 * childIndex + 1;\r\n        }\r\n        array[parentIndex] = temp;\r\n    }\r\n\r\n    /**\r\n     * 队列扩容\r\n     */\r\n    private void resize() {\r\n        //队列容量翻倍\r\n        int newSize = this.size * 2;\r\n        this.array = Arrays.copyOf(this.array, newSize);\r\n    }\r\n\r\n    public static void main(String[] args) throws Exception {\r\n        PriorityQueue priorityQueue = new PriorityQueue();\r\n        priorityQueue.enQueue(3);\r\n        priorityQueue.enQueue(5);\r\n        priorityQueue.enQueue(10);\r\n        priorityQueue.enQueue(2);\r\n        priorityQueue.enQueue(7);\r\n        System.out.println(\"出队元素：\" + priorityQueue.deQueue());\r\n        System.out.println(\"出队元素：\" + priorityQueue.deQueue());\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter4/part2/BubbleSort.java",
    "content": "package chapter4.part2;\r\n\r\nimport java.util.Arrays;\r\n\r\npublic class BubbleSort {\r\n\r\n    public static void sort(int array[])\r\n    {\r\n        int tmp  = 0;\r\n        //记录最后一次交换的位置\r\n        int lastExchangeIndex = 0;\r\n        //无序数列的边界，每次比较只需要比到这里为止\r\n        int sortBorder = array.length - 1;\r\n        for(int i = 0; i < array.length; i++)\r\n        {\r\n            //有序标记，每一轮的初始是true\r\n            boolean isSorted = true;\r\n\r\n            for(int j = 0; j < sortBorder; j++)\r\n            {\r\n                if(array[j] > array[j+1])\r\n                {\r\n                    tmp = array[j];\r\n                    array[j] = array[j+1];\r\n                    array[j+1] = tmp;\r\n                    //有元素交换，所以不是有序，标记变为false\r\n                    isSorted = false;\r\n                    //把无序数列的边界更新为最后一次交换元素的位置\r\n                    lastExchangeIndex = j;\r\n                }\r\n            }\r\n            sortBorder = lastExchangeIndex;\r\n            if(isSorted){\r\n                break;\r\n            }\r\n        }\r\n    }\r\n\r\n    public static void main(String[] args){\r\n        int[] array = new int[]{3,4,2,1,5,6,7,8};\r\n        sort(array);\r\n        System.out.println(Arrays.toString(array));\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter4/part2/CockTailSort.java",
    "content": "package chapter4.part2;\r\n\r\nimport java.util.Arrays;\r\n\r\npublic class CockTailSort {\r\n\r\n    public static void sort(int array[])\r\n    {\r\n        int tmp  = 0;\r\n        for(int i=0; i<array.length/2; i++)\r\n        {\r\n            //有序标记，每一轮的初始是true\r\n            boolean isSorted = true;\r\n            //奇数轮，从左向右比较和交换\r\n            for(int j=i; j<array.length-i-1; j++)\r\n            {\r\n                if(array[j] > array[j+1])\r\n                {\r\n                    tmp = array[j];\r\n                    array[j] = array[j+1];\r\n                    array[j+1] = tmp;\r\n                    //有元素交换，所以不是有序，标记变为false\r\n                    isSorted = false;\r\n                }\r\n            }\r\n            if(isSorted){\r\n                break;\r\n            }\r\n\r\n            //偶数轮之前，重新标记为true\r\n            isSorted = true;\r\n            //偶数轮，从右向左比较和交换\r\n            for(int j=array.length-i-1; j>i; j--)\r\n            {\r\n                if(array[j] < array[j-1])\r\n                {\r\n                    tmp = array[j];\r\n                    array[j] = array[j-1];\r\n                    array[j-1] = tmp;\r\n                    //有元素交换，所以不是有序，标记变为false\r\n                    isSorted = false;\r\n                }\r\n            }\r\n            if(isSorted){\r\n                break;\r\n            }\r\n        }\r\n    }\r\n\r\n    public static void main(String[] args){\r\n        int[] array = new int[]{2,3,4,5,6,7,8,1};\r\n        sort(array);\r\n        System.out.println(Arrays.toString(array));\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter4/part3/QuickSort.java",
    "content": "package chapter4.part3;\r\n\r\n/**\r\n * Created by weimengshu on 2018/7/13.\r\n */\r\nimport java.util.Arrays;\r\n\r\npublic class QuickSort {\r\n\r\n    public static void quickSort(int[] arr, int startIndex, int endIndex) {\r\n        // 递归结束条件：startIndex大等于endIndex的时候\r\n        if (startIndex >= endIndex) {\r\n            return;\r\n        }\r\n        // 得到基准元素位置\r\n        int pivotIndex = partition(arr, startIndex, endIndex);\r\n        // 根据基准元素，分成两部分递归排序\r\n        quickSort(arr, startIndex, pivotIndex - 1);\r\n        quickSort(arr, pivotIndex + 1, endIndex);\r\n    }\r\n\r\n    /**\r\n     * 分治（双边循环法）\r\n     * @param arr     待交换的数组\r\n     * @param startIndex    起始下标\r\n     * @param endIndex    结束下标\r\n     */\r\n    private static int partition(int[] arr, int startIndex, int endIndex) {\r\n        // 取第一个位置的元素作为基准元素（也可以选择随机位置）\r\n        int pivot = arr[startIndex];\r\n        int left = startIndex;\r\n        int right = endIndex;\r\n\r\n        while( left != right) {\r\n            //控制right指针比较并左移\r\n            while(left<right && arr[right] > pivot){\r\n                right--;\r\n            }\r\n            //控制left指针比较并右移\r\n            while( left<right && arr[left] <= pivot) {\r\n                left++;\r\n            }\r\n            //交换left和right指向的元素\r\n            if(left<right) {\r\n                int p = arr[left];\r\n                arr[left] = arr[right];\r\n                arr[right] = p;\r\n            }\r\n        }\r\n\r\n        //pivot和指针重合点交换\r\n        arr[startIndex] = arr[left];\r\n        arr[left] = pivot;\r\n\r\n        return left;\r\n    }\r\n\r\n    /**\r\n     * 分治（单边循环法）\r\n     * @param arr     待交换的数组\r\n     * @param startIndex    起始下标\r\n     * @param endIndex    结束下标\r\n     */\r\n    private static int partitionV2(int[] arr, int startIndex, int endIndex) {\r\n        // 取第一个位置的元素作为基准元素（也可以选择随机位置）\r\n        int pivot = arr[startIndex];\r\n        int mark = startIndex;\r\n\r\n        for(int i=startIndex+1; i<=endIndex; i++){\r\n            if(arr[i]<pivot){\r\n                mark ++;\r\n                int p = arr[mark];\r\n                arr[mark] = arr[i];\r\n                arr[i] = p;\r\n            }\r\n        }\r\n\r\n        arr[startIndex] = arr[mark];\r\n        arr[mark] = pivot;\r\n        return mark;\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        int[] arr = new int[] {4,4,6,5,3,2,8,1};\r\n        quickSort(arr, 0, arr.length-1);\r\n        System.out.println(Arrays.toString(arr));\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter4/part3/QuickSortWithStack.java",
    "content": "package chapter4.part3;\r\n\r\n/**\r\n * Created by weimengshu on 2018/7/13.\r\n */\r\nimport java.util.Arrays;\r\nimport java.util.HashMap;\r\nimport java.util.Map;\r\nimport java.util.Stack;\r\n\r\npublic class QuickSortWithStack {\r\n\r\n    public static void quickSort(int[] arr, int startIndex, int endIndex) {\r\n        // 用一个集合栈来代替递归的函数栈\r\n        Stack<Map<String, Integer>> quickSortStack = new Stack<Map<String, Integer>>();\r\n        // 整个数列的起止下标，以哈希的形式入栈\r\n        Map rootParam = new HashMap();\r\n        rootParam.put(\"startIndex\", startIndex);\r\n        rootParam.put(\"endIndex\", endIndex);\r\n        quickSortStack.push(rootParam);\r\n\r\n        // 循环结束条件：栈为空时结束\r\n        while (!quickSortStack.isEmpty()) {\r\n            // 栈顶元素出栈，得到起止下标\r\n            Map<String, Integer> param = quickSortStack.pop();\r\n            // 得到基准元素位置\r\n            int pivotIndex = partition(arr, param.get(\"startIndex\"), param.get(\"endIndex\"));\r\n            // 根据基准元素分成两部分, 把每一部分的起止下标入栈\r\n            if(param.get(\"startIndex\") <  pivotIndex -1){\r\n                Map<String, Integer> leftParam = new HashMap<String, Integer>();\r\n                leftParam.put(\"startIndex\",  param.get(\"startIndex\"));\r\n                leftParam.put(\"endIndex\", pivotIndex -1);\r\n                quickSortStack.push(leftParam);\r\n            }\r\n            if(pivotIndex + 1 < param.get(\"endIndex\")){\r\n                Map<String, Integer> rightParam = new HashMap<String, Integer>();\r\n                rightParam.put(\"startIndex\", pivotIndex + 1);\r\n                rightParam.put(\"endIndex\", param.get(\"endIndex\"));\r\n                quickSortStack.push(rightParam);\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * 分治（单边循环法）\r\n     * @param arr     待交换的数组\r\n     * @param startIndex    起始下标\r\n     * @param endIndex    结束下标\r\n     */\r\n    private static int partition(int[] arr, int startIndex, int endIndex) {\r\n        // 取第一个位置的元素作为基准元素（也可以选择随机位置）\r\n        int pivot = arr[startIndex];\r\n        int mark = startIndex;\r\n\r\n        for(int i=startIndex+1; i<=endIndex; i++){\r\n            if(arr[i]<pivot){\r\n                mark ++;\r\n                int p = arr[mark];\r\n                arr[mark] = arr[i];\r\n                arr[i] = p;\r\n            }\r\n        }\r\n\r\n        arr[startIndex] = arr[mark];\r\n        arr[mark] = pivot;\r\n        return mark;\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        int[] arr = new int[] {4,7,6,5,3,2,8,1};\r\n        quickSort(arr, 0, arr.length-1);\r\n        System.out.println(Arrays.toString(arr));\r\n    }\r\n\r\n}\r\n"
  },
  {
    "path": "src/chapter4/part4/HeapSort.java",
    "content": "package chapter4.part4;\r\n\r\n/**\r\n * Created by weimengshu on 2018/7/13.\r\n */\r\nimport java.util.Arrays;\r\n\r\npublic class HeapSort {\r\n\r\n    /**\r\n     * 下沉调整\r\n     * @param array     待调整的堆\r\n     * @param parentIndex    要下沉的父节点\r\n     * @param length    堆的有效大小\r\n     */\r\n    public static void downAdjust(int[] array, int parentIndex, int length) {\r\n        // temp保存父节点值，用于最后的赋值\r\n        int temp = array[parentIndex];\r\n        int childIndex = 2 * parentIndex + 1;\r\n        while (childIndex < length) {\r\n            // 如果有右孩子，且右孩子大于左孩子的值，则定位到右孩子\r\n            if (childIndex + 1 < length && array[childIndex + 1] > array[childIndex]) {\r\n                childIndex++;\r\n            }\r\n            // 如果父节点大于等于任何一个孩子的值，直接跳出\r\n            if (temp >= array[childIndex])\r\n                break;\r\n            //无需真正交换，单向赋值即可\r\n            array[parentIndex] = array[childIndex];\r\n            parentIndex = childIndex;\r\n            childIndex = 2 * childIndex + 1;\r\n        }\r\n        array[parentIndex] = temp;\r\n    }\r\n\r\n    /**\r\n     * 堆排序(升序)\r\n     * @param array     待调整的堆\r\n     */\r\n    public static void heapSort(int[] array) {\r\n        // 1.把无序数组构建成最大堆。\r\n        for (int i = (array.length-2)/2; i >= 0; i--) {\r\n            downAdjust(array, i, array.length);\r\n        }\r\n        System.out.println(Arrays.toString(array));\r\n        // 2.循环交换集合尾部元素到堆顶，并调节堆产生新的堆顶。\r\n        for (int i = array.length - 1; i > 0; i--) {\r\n            // 最后一个元素和第一元素进行交换\r\n            int temp = array[i];\r\n            array[i] = array[0];\r\n            array[0] = temp;\r\n            // 下沉调整最大堆\r\n            downAdjust(array, 0, i);\r\n        }\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        int[] arr = new int[] {1,3,2,6,5,7,8,9,10,0};\r\n        heapSort(arr);\r\n        System.out.println(Arrays.toString(arr));\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter4/part5/BucketSort.java",
    "content": "package chapter4.part5;\r\n\r\n/**\r\n * Created by weimengshu on 2018/7/13.\r\n */\r\nimport java.util.ArrayList;\r\nimport java.util.Arrays;\r\nimport java.util.Collections;\r\nimport java.util.LinkedList;\r\n\r\npublic class BucketSort {\r\n\r\n    public static double[] bucketSort(double[] array){\r\n\r\n        //1.得到数列的最大值和最小值，并算出差值d\r\n        double max = array[0];\r\n        double min = array[0];\r\n        for(int i=1; i<array.length; i++) {\r\n            if(array[i] > max) {\r\n                max = array[i];\r\n            }\r\n            if(array[i] < min) {\r\n                min = array[i];\r\n            }\r\n        }\r\n        double d = max - min;\r\n\r\n        //2.初始化桶\r\n        int bucketNum = array.length;\r\n        ArrayList<LinkedList<Double>> bucketList = new ArrayList<LinkedList<Double>>(bucketNum);\r\n        for(int i = 0; i < bucketNum; i++){\r\n            bucketList.add(new LinkedList<Double>());\r\n        }\r\n\r\n        //3.遍历原始数组，将每个元素放入桶中\r\n        for(int i = 0; i < array.length; i++){\r\n            int num = (int)((array[i] - min)  * (bucketNum-1) / d);\r\n            bucketList.get(num).add(array[i]);\r\n        }\r\n\r\n        //4.对每个桶内部进行排序\r\n        for(int i = 0; i < bucketList.size(); i++){\r\n            //JDK底层采用了归并排序或归并的优化版本\r\n            Collections.sort(bucketList.get(i));\r\n        }\r\n\r\n        //5.输出全部元素\r\n        double[] sortedArray = new double[array.length];\r\n        int index = 0;\r\n        for(LinkedList<Double> list : bucketList){\r\n            for(double element : list){\r\n                sortedArray[index] = element;\r\n                index++;\r\n            }\r\n        }\r\n        return sortedArray;\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        double[] array = new double[] {4.12,6.421,0.0023,3.0,2.123,8.122,4.12, 10.09};\r\n        double[] sortedArray = bucketSort(array);\r\n        System.out.println(Arrays.toString(sortedArray));\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter4/part5/CountSort.java",
    "content": "package chapter4.part5;\r\n\r\n/**\r\n * Created by weimengshu on 2018/7/13.\r\n */\r\nimport java.util.Arrays;\r\n\r\npublic class CountSort {\r\n\r\n    public static int[] countSort(int[] array) {\r\n        //1.得到数列的最大值\r\n        int max = array[0];\r\n        for(int i=1; i<array.length; i++){\r\n            if(array[i] > max){\r\n                max = array[i];\r\n            }\r\n        }\r\n        //2.根据数列最大值确定统计数组的长度\r\n        int[] countArray = new int[max+1];\r\n        //3.遍历数列，填充统计数组\r\n        for(int i=0; i<array.length; i++){\r\n            countArray[array[i]]++;\r\n        }\r\n        //4.遍历统计数组，输出结果\r\n        int index = 0;\r\n        int[] sortedArray = new int[array.length];\r\n        for(int i=0; i<countArray.length; i++){\r\n            for(int j=0; j<countArray[i]; j++){\r\n                sortedArray[index++] = i;\r\n            }\r\n        }\r\n        return sortedArray;\r\n    }\r\n\r\n    public static int[] countSortV2(int[] array) {\r\n        //1.得到数列的最大值和最小值，并算出差值d\r\n        int max = array[0];\r\n        int min = array[0];\r\n        for(int i=1; i<array.length; i++) {\r\n            if(array[i] > max) {\r\n                max = array[i];\r\n            }\r\n            if(array[i] < min) {\r\n                min = array[i];\r\n            }\r\n        }\r\n        int d = max - min;\r\n        //2.创建统计数组并统计对应元素个数\r\n        int[] countArray = new int[d+1];\r\n        for(int i=0; i<array.length; i++) {\r\n            countArray[array[i]-min]++;\r\n        }\r\n        //3.统计数组做变形，后面的元素等于前面的元素之和\r\n        for(int i=1;i<countArray.length;i++) {\r\n            countArray[i] += countArray[i-1];\r\n        }\r\n        //4.倒序遍历原始数列，从统计数组找到正确位置，输出到结果数组\r\n        int[] sortedArray = new int[array.length];\r\n        for(int i=array.length-1;i>=0;i--) {\r\n            sortedArray[countArray[array[i]-min]-1]=array[i];\r\n            countArray[array[i]-min]--;\r\n        }\r\n        return sortedArray;\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        int[] array = new int[] {4,4,6,5,3,2,8,1,7,5,6,0,10};\r\n        int[] sortedArray = countSort(array);\r\n        System.out.println(Arrays.toString(sortedArray));\r\n\r\n        array = new int[] {95,94,91,98,99,90,99,93,91,92};\r\n        sortedArray = countSort(array);\r\n        System.out.println(Arrays.toString(sortedArray));\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter5/part10/BigNumberSum.java",
    "content": "package chapter5.part10;\r\n\r\n/**\r\n * Created by weimengshu on 2018/10/20.\r\n */\r\npublic class BigNumberSum {\r\n\r\n    /**\r\n     * 大整数求和\r\n     * @param bigNumberA  大整数A\r\n     * @param bigNumberB  大整数B\r\n     */\r\n    public static String bigNumberSum(String bigNumberA, String bigNumberB) {\r\n        //1.把两个大整数用数组逆序存储，数组长度等于较大整数位数+1\r\n        int maxLength = bigNumberA.length() > bigNumberB.length() ? bigNumberA.length() : bigNumberB.length();\r\n        int[] arrayA = new int[maxLength+1];\r\n        for(int i=0; i< bigNumberA.length(); i++){\r\n            arrayA[i] = bigNumberA.charAt(bigNumberA.length()-1-i) - '0';\r\n        }\r\n        int[] arrayB = new int[maxLength+1];\r\n        for(int i=0; i< bigNumberB.length(); i++){\r\n            arrayB[i] = bigNumberB.charAt(bigNumberB.length()-1-i) - '0';\r\n        }\r\n        //2.构建result数组，数组长度等于较大整数位数+1\r\n        int[] result = new int[maxLength+1];\r\n        //3.遍历数组，按位相加\r\n        for(int i=0; i<result.length; i++){\r\n            int temp = result[i];\r\n            temp += arrayA[i];\r\n            temp += arrayB[i];\r\n            //判断是否进位\r\n            if(temp >= 10){\r\n                temp = temp-10;\r\n                result[i+1] = 1;\r\n            }\r\n            result[i] = temp;\r\n        }\r\n        //4.把result数组再次逆序并转成String\r\n        StringBuilder sb = new StringBuilder();\r\n        //是否找到大整数的最高有效位\r\n        boolean findFirst = false;\r\n        for (int i = result.length - 1; i >= 0; i--) {\r\n            if(!findFirst){\r\n                if(result[i] == 0){\r\n                    continue;\r\n                }\r\n                findFirst = true;\r\n            }\r\n            sb.append(result[i]);\r\n        }\r\n        return sb.toString();\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        System.out.println(bigNumberSum(\"426709752318\", \"95481253129\"));\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter5/part11/GoldMining.java",
    "content": "package chapter5.part11;\r\n\r\n/**\r\n * Created by weimengshu on 2018/10/26.\r\n */\r\npublic class GoldMining {\r\n\r\n    /**\r\n     * 获得金矿最优收益\r\n     * @param w  工人数量\r\n     * @param p  金矿开采所需工人数量\r\n     * @param g  金矿储量\r\n     */\r\n    public static int getBestGoldMiningV3(int w, int[] p, int[] g){\r\n        //创建当前结果\r\n        int[] results = new int[w+1];\r\n        //填充一维数组\r\n        for(int i=1; i<=g.length; i++){\r\n            for(int j=w; j>=1; j--){\r\n               if(j>=p[i-1]){\r\n                    results[j] = Math.max(results[j],  results[j-p[i-1]]+ g[i-1]);\r\n                }\r\n            }\r\n        }\r\n        //返回最后一个格子的值\r\n        return results[w];\r\n    }\r\n\r\n    /**\r\n     * 获得金矿最优收益\r\n     * @param w  工人数量\r\n     * @param p  金矿开采所需工人数量\r\n     * @param g  金矿储量\r\n     */\r\n    public static int getBestGoldMiningV2(int w, int[] p, int[] g){\r\n        //创建表格\r\n        int[][] resultTable = new int[g.length+1][w+1];\r\n        //填充表格\r\n        for(int i=1; i<=g.length; i++){\r\n            for(int j=1; j<=w; j++){\r\n                if(j<p[i-1]){\r\n                    resultTable[i][j] = resultTable[i-1][j];\r\n                }else{\r\n                    resultTable[i][j] = Math.max(resultTable[i-1][j],  resultTable[i-1][j-p[i-1]]+ g[i-1]);\r\n                }\r\n            }\r\n        }\r\n        //返回最后一个格子的值\r\n        return resultTable[g.length][w];\r\n    }\r\n\r\n    /**\r\n     * 获得金矿最优收益\r\n     * @param w  工人数量\r\n     * @param n  可选金矿数量\r\n     * @param p  金矿开采所需工人数量\r\n     * @param g  金矿储量\r\n     */\r\n    public static int getBestGoldMining(int w, int n, int[] p, int[] g){\r\n        if(w==0 || n==0){\r\n            return 0;\r\n        }\r\n        if(w<p[n-1]){\r\n            return getBestGoldMining(w, n-1, p, g);\r\n        }\r\n        return Math.max(getBestGoldMining(w, n-1, p, g), getBestGoldMining(w-p[n-1], n-1, p, g)+g[n-1]);\r\n    }\r\n\r\n\r\n    public static void main(String[] args) {\r\n        int w = 10;\r\n        int[] p = {5, 5, 3, 4 ,3};\r\n        int[] g = {400, 500, 200, 300 ,350};\r\n        System.out.println(\"最优收益：\" + getBestGoldMining(w, g.length, p, g));\r\n    }\r\n\r\n}\r\n"
  },
  {
    "path": "src/chapter5/part12/FindLostNum.java",
    "content": "package chapter5.part12;\r\n\r\n/**\r\n * Created by weimengshu on 2018/10/10.\r\n */\r\npublic class FindLostNum {\r\n\r\n    public static int[] findLostNum(int[] array) {\r\n        //用于存储两个出现奇数次的整数\r\n        int result[] = new int[2];\r\n        //第一次整体异或\r\n        int xorResult = 0;\r\n        for(int i=0;i<array.length;i++){\r\n            xorResult^=array[i];\r\n        }\r\n        //如果异或结果为0，说明输入数组不符合题目\r\n        if(xorResult == 0){\r\n            return null;\r\n        }\r\n        //确定两个整数的不同位，以此来做分组\r\n        int separator = 1;\r\n        while (0==(xorResult&separator)){\r\n            separator<<=1;\r\n        }\r\n        //第二次分组异或\r\n        for(int i=0;i<array.length;i++){\r\n            if(0==(array[i]&separator)){\r\n                result[0]^=array[i];\r\n            }else {\r\n                result[1]^=array[i];\r\n            }\r\n        }\r\n\r\n        return result;\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        int[] array = {4,1,2,2,5,1,4,3};\r\n        int[] result = findLostNum(array);\r\n        System.out.println(result[0] + \",\" + result[1]);\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter5/part2/LinkedListCycle.java",
    "content": "package chapter5.part2;\r\n\r\n/**\r\n * Created by weimengshu on 2018/8/24.\r\n */\r\npublic class LinkedListCycle {\r\n\r\n    /**\r\n     * 判断是否有环\r\n     * @param head  链表头节点\r\n     */\r\n    public static boolean isCycle(Node head) {\r\n        Node p1 = head;\r\n        Node p2 = head;\r\n        while (p2!=null && p2.next!=null){\r\n            p1 = p1.next;\r\n            p2 = p2.next.next;\r\n            if(p1 == p2){\r\n                return true;\r\n            }\r\n        }\r\n        return false;\r\n    }\r\n\r\n    /**\r\n     * 链表节点\r\n     */\r\n    private static class Node {\r\n        int data;\r\n        Node next;\r\n        Node(int data) {\r\n            this.data = data;\r\n        }\r\n    }\r\n\r\n    public static void main(String[] args) throws Exception {\r\n        Node node1 = new Node(5);\r\n        Node node2 = new Node(3);\r\n        Node node3 = new Node(7);\r\n        Node node4 = new Node(2);\r\n        Node node5 = new Node(6);\r\n        node1.next = node2;\r\n        node2.next = node3;\r\n        node3.next = node4;\r\n        node4.next = node5;\r\n        node5.next = node2;\r\n\r\n        System.out.println(isCycle(node1));\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter5/part3/MinStack.java",
    "content": "package chapter5.part3;\r\n\r\nimport java.util.Stack;\r\n\r\n/**\r\n * Created by weimengshu on 2018/8/24.\r\n */\r\npublic class MinStack {\r\n\r\n    private Stack<Integer> mainStack = new Stack<Integer>();\r\n    private Stack<Integer> minStack = new Stack<Integer>();\r\n\r\n    /**\r\n     * 入栈操作\r\n     * @param element  入栈的元素\r\n     */\r\n    public void push(int element) {\r\n        mainStack.push(element);\r\n        //如果辅助栈为空，或新元素小于等于辅助栈栈顶，则新元素压入辅助栈\r\n        if (minStack.empty() || element  <= minStack.peek()) {\r\n            minStack.push(element);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * 出栈操作\r\n     */\r\n    public Integer pop() {\r\n        //如果出栈元素和辅助栈栈顶元素值相等，辅助栈出栈\r\n        if (mainStack.peek().equals(minStack.peek())) {\r\n            minStack.pop();\r\n        }\r\n        return mainStack.pop();\r\n    }\r\n\r\n    /**\r\n     * 获取栈的最小元素\r\n     */\r\n    public int getMin() throws Exception {\r\n        if (mainStack.empty()) {\r\n            throw new Exception(\"stack is empty\");\r\n        }\r\n\r\n        return minStack.peek();\r\n    }\r\n\r\n    public static void main(String[] args) throws Exception {\r\n        MinStack stack = new MinStack();\r\n        stack.push(4);\r\n        stack.push(9);\r\n        stack.push(7);\r\n        stack.push(3);\r\n        stack.push(8);\r\n        stack.push(5);\r\n        System.out.println(stack.getMin());\r\n        stack.pop();\r\n        stack.pop();\r\n        stack.pop();\r\n        System.out.println(stack.getMin());\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter5/part4/GreatestCommonDivisor.java",
    "content": "package chapter5.part4;\r\n\r\n/**\r\n * Created by weimengshu on 2018/10/6.\r\n */\r\npublic class GreatestCommonDivisor {\r\n\r\n    public static int getGreatestCommonDivisor(int a, int b){\r\n        int big = a>b ? a:b;\r\n        int small = a<b ? a:b;\r\n        if(big%small == 0){\r\n            return small;\r\n        }\r\n        for(int i= small/2; i>1; i--){\r\n            if(small%i==0 && big%i==0){\r\n                return i;\r\n            }\r\n        }\r\n        return  1;\r\n    }\r\n\r\n    public static int getGreatestCommonDivisorV2(int a, int b){\r\n        int big = a>b ? a:b;\r\n        int small = a<b ? a:b;\r\n        if(big%small == 0){\r\n            return small;\r\n        }\r\n        return getGreatestCommonDivisorV2(big%small, small);\r\n    }\r\n\r\n    public static int getGreatestCommonDivisorV3(int a, int b){\r\n        if(a == b){\r\n            return a;\r\n        }\r\n        int big = a>b ? a:b;\r\n        int small = a<b ? a:b;\r\n        return getGreatestCommonDivisorV3(big - small, small);\r\n    }\r\n\r\n    public static int gcd(int a, int b){\r\n        if(a == b){\r\n            return a;\r\n        }\r\n        if((a&1)==0 && (b&1)==0){\r\n            return gcd(a >> 1, b >> 1)<<1;\r\n        } else if((a&1)==0 && (b&1)!=0){\r\n            return gcd(a >> 1, b);\r\n        } else if((a&1)!=0 && (b&1)==0){\r\n            return gcd(a, b >> 1);\r\n        } else {\r\n            int big = a>b ? a:b;\r\n            int small = a<b ? a:b;\r\n            return gcd(big - small, small);\r\n        }\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        System.out.println(gcd(25, 5));\r\n        System.out.println(gcd(100, 80));\r\n        System.out.println(gcd(27, 14));\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter5/part5/PowerOf2.java",
    "content": "package chapter5.part5;\r\n\r\n/**\r\n * Created by weimengshu on 2018/10/10.\r\n */\r\npublic class PowerOf2 {\r\n\r\n    public static boolean isPowerOf2(int num) {\r\n        int temp = 1;\r\n        while(temp<=num){\r\n            if(temp == num){\r\n                return true;\r\n            }\r\n            temp = temp*2;\r\n        }\r\n        return false;\r\n    }\r\n\r\n    public static boolean isPowerOf2V2(int num) {\r\n        int temp = 1;\r\n        while(temp<=num){\r\n            if(temp == num){\r\n                return true;\r\n            }\r\n            temp = temp<<1;\r\n        }\r\n        return false;\r\n    }\r\n\r\n    public static boolean isPowerOf2V3(int num) {\r\n        return (num&num-1) == 0;\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        System.out.println(isPowerOf2V3(32));\r\n        System.out.println(isPowerOf2V3(19));\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter5/part6/MaxSortedDistance.java",
    "content": "package chapter5.part6;\r\n\r\n/**\r\n * Created by weimengshu on 2018/7/13.\r\n */\r\n\r\npublic class MaxSortedDistance {\r\n\r\n    public static int getMaxSortedDistance(int[] array){\r\n\r\n        //1.得到数列的最大值和最小值\r\n        int max = array[0];\r\n        int min = array[0];\r\n        for(int i=1; i<array.length; i++) {\r\n            if(array[i] > max) {\r\n                max = array[i];\r\n            }\r\n            if(array[i] < min) {\r\n                min = array[i];\r\n            }\r\n        }\r\n        int d = max - min;\r\n        //如果max和min相等，说明数组所有元素都相等，返回0\r\n        if(d == 0){\r\n            return 0;\r\n        }\r\n\r\n        //2.初始化桶\r\n        int bucketNum = array.length;\r\n        Bucket[] buckets = new Bucket[bucketNum];\r\n        for(int i = 0; i < bucketNum; i++){\r\n            buckets[i] = new Bucket();\r\n        }\r\n\r\n        //3.遍历原始数组，确定每个桶的最大最小值\r\n        for(int i = 0; i < array.length; i++){\r\n            //确定数组元素所归属的桶下标\r\n            int index = ((array[i] - min)  * (bucketNum-1) / d);\r\n            if(buckets[index].min==null || buckets[index].min>array[i]){\r\n                buckets[index].min = array[i];\r\n            }\r\n            if(buckets[index].max==null || buckets[index].max<array[i]){\r\n                buckets[index].max = array[i];\r\n            }\r\n        }\r\n\r\n        //4.遍历桶，找到最大差值\r\n        int leftMax = buckets[0].max;\r\n        int maxDistance = 0;\r\n        for (int i=1; i<buckets.length; i++) {\r\n            if (buckets[i].min == null) {\r\n                continue;\r\n            }\r\n            if (buckets[i].min - leftMax > maxDistance) {\r\n                maxDistance = buckets[i].min - leftMax;\r\n            }\r\n            leftMax = buckets[i].max;\r\n        }\r\n\r\n        return maxDistance;\r\n    }\r\n\r\n    /**\r\n     * 桶\r\n     */\r\n    private static class Bucket {\r\n        Integer min;\r\n        Integer max;\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        int[] array = new int[] {2,6,3,4,5,10,9};\r\n        System.out.println(getMaxSortedDistance(array));\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter5/part7/StackQueue.java",
    "content": "package chapter5.part7;\r\n\r\nimport java.util.Stack;\r\n\r\n/**\r\n * Created by weimengshu on 2018/8/24.\r\n */\r\npublic class StackQueue {\r\n\r\n    private Stack<Integer> stackA = new Stack<Integer>();\r\n    private Stack<Integer> stackB = new Stack<Integer>();\r\n\r\n    /**\r\n     * 入队操作\r\n     * @param element  入队的元素\r\n     */\r\n    public void enQueue(int element) {\r\n        stackA.push(element);\r\n    }\r\n\r\n    /**\r\n     * 出队操作\r\n     */\r\n    public Integer deQueue() {\r\n        if(stackB.isEmpty()){\r\n            if(stackA.isEmpty()){\r\n                return null;\r\n            }\r\n            transfer();\r\n        }\r\n        return stackB.pop();\r\n    }\r\n\r\n    /**\r\n     * 栈A元素转移到栈B\r\n     */\r\n    private void transfer(){\r\n        while (!stackA.isEmpty()){\r\n            stackB.push(stackA.pop());\r\n        }\r\n    }\r\n\r\n    public static void main(String[] args) throws Exception {\r\n        StackQueue stackQueue = new StackQueue();\r\n        stackQueue.enQueue(1);\r\n        stackQueue.enQueue(2);\r\n        stackQueue.enQueue(3);\r\n        System.out.println(stackQueue.deQueue());\r\n        System.out.println(stackQueue.deQueue());\r\n        stackQueue.enQueue(4);\r\n        System.out.println(stackQueue.deQueue());\r\n        System.out.println(stackQueue.deQueue());\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter5/part8/FindNearestNumber.java",
    "content": "package chapter5.part8;\r\n\r\nimport java.util.Arrays;\r\n\r\n/**\r\n * Created by weimengshu on 2017/8/10.\r\n */\r\npublic class FindNearestNumber {\r\n\r\n    public static int[] findNearestNumber(int[] numbers){\r\n        //1.从后向前查看逆序区域，找到逆序区域的前一位，也就是数字置换的边界\r\n        int index = findTransferPoint(numbers);\r\n        //如果数字置换边界是0，说明整个数组已经逆序，无法得到更大的相同数字组成的整数，返回null\r\n        if(index == 0){\r\n            return null;\r\n        }\r\n        //2.把逆序区域的前一位和逆序区域中刚刚大于它的数字交换位置\r\n        //拷贝入参，避免直接修改入参\r\n        int[] numbersCopy = Arrays.copyOf(numbers, numbers.length);\r\n        exchangeHead(numbersCopy, index);\r\n        //3.把原来的逆序区域转为顺序\r\n        reverse(numbersCopy, index);\r\n        return numbersCopy;\r\n    }\r\n\r\n    private static int findTransferPoint(int[] numbers){\r\n        for(int i=numbers.length-1; i>0; i--){\r\n            if(numbers[i] > numbers[i-1]){\r\n                return i;\r\n            }\r\n        }\r\n        return 0;\r\n    }\r\n\r\n    private static int[] exchangeHead(int[] numbers, int index){\r\n        int head = numbers[index-1];\r\n        for(int i=numbers.length-1; i>0; i--){\r\n            if(head < numbers[i]){\r\n                numbers[index-1] =  numbers[i];\r\n                numbers[i] = head;\r\n                break;\r\n            }\r\n        }\r\n        return numbers;\r\n    }\r\n\r\n    private static int[] reverse(int[] num, int index){\r\n        for(int i=index,j=num.length-1; i<j; i++,j--){\r\n            int temp = num[i];\r\n            num[i] = num[j];\r\n            num[j] = temp;\r\n        }\r\n        return num;\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        int[] numbers = {1,2,3,4,5};\r\n        //打印12345之后的10个全排列整数\r\n        for(int i=0; i<10;i++){\r\n            numbers = findNearestNumber(numbers);\r\n            outputNumbers(numbers);\r\n        }\r\n    }\r\n\r\n    //输出数组\r\n    private static void outputNumbers(int[] numbers){\r\n        for(int i : numbers){\r\n            System.out.print(i);\r\n        }\r\n        System.out.println();\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter5/part9/RemoveKDigits.java",
    "content": "package chapter5.part9;\r\n\r\n/**\r\n * Created by weimengshu on 2018/10/20.\r\n */\r\npublic class RemoveKDigits {\r\n\r\n    /**\r\n     * 删除整数的k个数字，获得删除后的最小值\r\n     * @param num  原整数\r\n     * @param k  删除数量\r\n     */\r\n    public static String removeKDigits(String num, int k) {\r\n        for(int i=0; i<k; i++){\r\n            boolean hasCut = false;\r\n            //从左向右遍历，找到比自己右侧数字大的数字并删除\r\n            for(int j=0; j<num.length()-1;j++){\r\n                if(num.charAt(j) > num.charAt(j+1)){\r\n                    num = num.substring(0, j) + num.substring(j+1,num.length());\r\n                    hasCut = true;\r\n                    break;\r\n                }\r\n            }\r\n            //如果没有找到要删除的数字，则删除最后一个数字\r\n            if(!hasCut){\r\n                num = num.substring(0, num.length()-1);\r\n            }\r\n        }\r\n        //清除整数左侧的数字0\r\n        int start = 0;\r\n        for(int j=0; j<num.length()-1; j++){\r\n            if(num.charAt(j) != '0'){\r\n                break;\r\n            }\r\n            start++;\r\n        }\r\n        num = num.substring(start, num.length()) ;\r\n        //如果整数的所有数字都被删除了，直接返回0\r\n        if(num.length() == 0){\r\n            return \"0\";\r\n        }\r\n        return num;\r\n    }\r\n\r\n    /**\r\n     * 删除整数的k个数字，获得删除后的最小值\r\n     * @param num  原整数\r\n     * @param k  删除数量\r\n     */\r\n    public static String removeKDigitsV2(String num, int k) {\r\n        //新整数的最终长度 = 原整数长度 - k\r\n        int newLength = num.length() - k;\r\n        //创建一个栈，用于接收所有的数字\r\n        char[] stack = new char[num.length()];\r\n        int top = 0;\r\n        for (int i = 0; i < num.length(); ++i) {\r\n            //遍历当前数字\r\n            char c = num.charAt(i);\r\n            //当栈顶数字大于遍历到的当前数字，栈顶数字出栈（相当于删除数字）\r\n            while (top > 0 && stack[top-1] > c && k > 0) {\r\n                top -= 1;\r\n                k -= 1;\r\n            }\r\n            //如果遇到数字0，且栈为空，0不入栈\r\n            if('0' == c && top == 0){\r\n                newLength--;\r\n                if(newLength <= 0){\r\n                    return \"0\";\r\n                }\r\n                continue;\r\n            }\r\n            //遍历到的当前数字入栈\r\n            stack[top++] = c;\r\n        }\r\n        // 用栈构建新的整数字符串\r\n        return newLength<=0 ? \"0\" : new String(stack, 0, newLength);\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        System.out.println(removeKDigits(\"1593212\", 3));\r\n        System.out.println(removeKDigits(\"30200\", 1));\r\n        System.out.println(removeKDigits(\"10\", 2));\r\n        System.out.println(removeKDigits(\"541270936\", 3));\r\n        System.out.println(removeKDigits(\"1593212\", 4));\r\n        System.out.println(removeKDigits(\"1000020000000010\", 2));\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter6/part2/MyBitmap.java",
    "content": "package chapter6.part2;\r\n\r\n/**\r\n * Created by weimengshu on 2017/8/10.\r\n */\r\npublic class MyBitmap {\r\n\r\n    //每一个word是一个long类型元素，对应64位二进制\r\n    private long[] words;\r\n    //bitmap的位数大小\r\n    private int size;\r\n\r\n    public MyBitmap(int size) {\r\n        this.size = size;\r\n        this.words = new long[(getWordIndex(size-1) + 1)];\r\n    }\r\n\r\n    /**\r\n     * 判断bitmap某一位的状态\r\n     * @param bitIndex  位图的第bitIndex位\r\n     */\r\n    public boolean getBit(int bitIndex) {\r\n        if(bitIndex<0 || bitIndex>size-1){\r\n            throw new IndexOutOfBoundsException(\"超过bitmap有效范围\");\r\n        }\r\n        int wordIndex = getWordIndex(bitIndex);\r\n        return (words[wordIndex] & (1L << bitIndex)) != 0;\r\n    }\r\n\r\n    /**\r\n     * 把bitmap某一位设为真\r\n     * @param bitIndex  位图的第bitIndex位\r\n     */\r\n    public void setBit(int bitIndex) {\r\n        if(bitIndex<0 || bitIndex>size-1){\r\n            throw new IndexOutOfBoundsException(\"超过bitmap有效范围\");\r\n        }\r\n        int wordIndex = getWordIndex(bitIndex);\r\n        words[wordIndex] |= (1L << bitIndex);\r\n    }\r\n\r\n    /**\r\n     * 定位bitmap某一位所对应的word\r\n     * @param bitIndex  位图的第bitIndex位\r\n     */\r\n    private int getWordIndex(int bitIndex) {\r\n        //右移6位，相当于除以64\r\n        return bitIndex >> 6;\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        MyBitmap bitMap = new MyBitmap(128);\r\n        bitMap.setBit(126);\r\n        bitMap.setBit(75);\r\n        System.out.println(bitMap.getBit(126));\r\n        System.out.println(bitMap.getBit(78));\r\n    }\r\n\r\n}\r\n"
  },
  {
    "path": "src/chapter6/part3/LRUCache.java",
    "content": "package chapter6.part3;\r\n\r\nimport java.util.HashMap;\r\n\r\n\r\npublic class LRUCache {\r\n\r\n    private Node head;\r\n    private Node end;\r\n    //缓存存储上限\r\n    private int limit;\r\n\r\n    private HashMap<String, Node> hashMap;\r\n\r\n    public LRUCache(int limit) {\r\n        this.limit = limit;\r\n        hashMap = new HashMap<String, Node>();\r\n    }\r\n\r\n    public String get(String key) {\r\n        Node node = hashMap.get(key);\r\n        if (node == null){\r\n            return null;\r\n        }\r\n        refreshNode(node);\r\n        return node.value;\r\n    }\r\n\r\n    public void put(String key, String value) {\r\n        Node node = hashMap.get(key);\r\n        if (node == null) {\r\n            //如果key不存在，插入key-value\r\n            if (hashMap.size() >= limit) {\r\n                String oldKey = removeNode(head);\r\n                hashMap.remove(oldKey);\r\n            }\r\n            node = new Node(key, value);\r\n            addNode(node);\r\n            hashMap.put(key, node);\r\n        }else {\r\n            //如果key存在，刷新key-value\r\n            node.value = value;\r\n            refreshNode(node);\r\n        }\r\n    }\r\n\r\n    public void remove(String key) {\r\n        Node node = hashMap.get(key);\r\n        if(node == null){\r\n            return;\r\n        }\r\n        removeNode(node);\r\n        hashMap.remove(key);\r\n    }\r\n\r\n    /**\r\n     * 刷新被访问的节点位置\r\n     * @param  node 被访问的节点\r\n     */\r\n    private void refreshNode(Node node) {\r\n        //如果访问的是尾节点，无需移动节点\r\n        if (node == end) {\r\n            return;\r\n        }\r\n        //移除节点\r\n        removeNode(node);\r\n        //重新插入节点\r\n        addNode(node);\r\n    }\r\n\r\n    /**\r\n     * 删除节点\r\n     * @param  node 要删除的节点\r\n     */\r\n    private String removeNode(Node node) {\r\n        if(node == head && node == end){\r\n            //移除唯一的节点\r\n            head = null;\r\n            end = null;\r\n        }else if(node == end){\r\n            //移除尾节点\r\n            end = end.pre;\r\n            end.next = null;\r\n        }else if(node == head){\r\n            //移除头节点\r\n            head = head.next;\r\n            head.pre = null;\r\n        }else {\r\n            //移除中间节点\r\n            node.pre.next = node.next;\r\n            node.next.pre = node.pre;\r\n        }\r\n        return node.key;\r\n    }\r\n\r\n    /**\r\n     * 尾部插入节点\r\n     * @param  node 要插入的节点\r\n     */\r\n    private void addNode(Node node) {\r\n        if(end != null) {\r\n            end.next = node;\r\n            node.pre = end;\r\n            node.next = null;\r\n        }\r\n        end = node;\r\n        if(head == null){\r\n            head = node;\r\n        }\r\n    }\r\n\r\n    class Node {\r\n        Node(String key, String value){\r\n            this.key = key;\r\n            this.value = value;\r\n        }\r\n        public Node pre;\r\n        public Node next;\r\n        public String key;\r\n        public String value;\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        LRUCache lruCache = new LRUCache(5);\r\n        lruCache.put(\"001\", \"用户1信息\");\r\n        lruCache.put(\"002\", \"用户2信息\");\r\n        lruCache.put(\"003\", \"用户3信息\");\r\n        lruCache.put(\"004\", \"用户4信息\");\r\n        lruCache.put(\"005\", \"用户5信息\");\r\n        lruCache.get(\"002\");\r\n        lruCache.put(\"004\", \"用户4信息更新\");\r\n        lruCache.put(\"006\", \"用户6信息\");\r\n        System.out.println(lruCache.get(\"001\"));\r\n        System.out.println(lruCache.get(\"006\"));\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/chapter6/part4/AStar.java",
    "content": "package chapter6.part4;\r\nimport java.util.ArrayList;\r\nimport java.util.List;\r\n\r\npublic class AStar {\r\n\r\n    //迷宫地图\r\n    public static final int[][] MAZE = {\r\n            { 0, 0, 0, 0, 0, 0, 0 },\r\n            { 0, 0, 0, 1, 0, 0, 0 },\r\n            { 0, 0, 0, 1, 0, 0, 0 },\r\n            { 0, 0, 0, 1, 0, 0, 0 },\r\n            { 0, 0, 0, 0, 0, 0, 0 }\r\n    };\r\n\r\n    /**\r\n     * A星寻路主逻辑\r\n     * @param start  迷宫起点\r\n     * @param end  迷宫终点\r\n     */\r\n    public static Grid aStarSearch(Grid start, Grid end) {\r\n        ArrayList<Grid> openList = new ArrayList<Grid>();\r\n        ArrayList<Grid> closeList = new ArrayList<Grid>();\r\n        //把起点加入 openList\r\n        openList.add(start);\r\n        //主循环，每一轮检查一个当前方格节点\r\n        while (openList.size() > 0) {\r\n            // 在openList中查找 F值最小的节点作为当前方格节点\r\n            Grid currentGrid = findMinGird(openList);\r\n            // 当前方格节点从openList中移除\r\n            openList.remove(currentGrid);\r\n            // 当前方格节点进入 closeList\r\n            closeList.add(currentGrid);\r\n            // 找到所有邻近节点\r\n            List<Grid> neighbors = findNeighbors(currentGrid, openList, closeList);\r\n            for (Grid grid : neighbors) {\r\n                //邻近节点不在openList中，标记父亲、G、H、F，并放入openList\r\n                grid.initGrid(currentGrid, end);\r\n                openList.add(grid);\r\n            }\r\n            //如果终点在openList中，直接返回终点格子\r\n            for (Grid grid : openList){\r\n                if ((grid.x == end.x) && (grid.y == end.y)) {\r\n                    return grid;\r\n                }\r\n            }\r\n        }\r\n        //openList用尽，仍然找不到终点，说明终点不可到达，返回空\r\n        return null;\r\n    }\r\n\r\n    private static Grid findMinGird(ArrayList<Grid> openList) {\r\n        Grid tempGrid = openList.get(0);\r\n        for (Grid grid : openList) {\r\n            if (grid.f < tempGrid.f) {\r\n                tempGrid = grid;\r\n            }\r\n        }\r\n        return tempGrid;\r\n    }\r\n\r\n    private static ArrayList<Grid> findNeighbors(Grid grid, List<Grid> openList, List<Grid> closeList) {\r\n        ArrayList<Grid> gridList = new ArrayList<Grid>();\r\n        if (isValidGrid(grid.x, grid.y-1, openList, closeList)) {\r\n            gridList.add(new Grid(grid.x, grid.y - 1));\r\n        }\r\n        if (isValidGrid(grid.x, grid.y+1, openList, closeList)) {\r\n            gridList.add(new Grid(grid.x, grid.y + 1));\r\n        }\r\n        if (isValidGrid(grid.x-1, grid.y, openList, closeList)) {\r\n            gridList.add(new Grid(grid.x - 1, grid.y));\r\n        }\r\n        if (isValidGrid(grid.x+1, grid.y, openList, closeList)) {\r\n            gridList.add(new Grid(grid.x + 1, grid.y));\r\n        }\r\n        return gridList;\r\n    }\r\n\r\n    private static boolean isValidGrid(int x, int y, List<Grid> openList, List<Grid> closeList) {\r\n        //是否超过边界\r\n        if (x < 0 || x >= MAZE.length || y < 0 || y >= MAZE[0].length) {\r\n            return false;\r\n        }\r\n        //是否有障碍物\r\n        if(MAZE[x][y] == 1){\r\n            return false;\r\n        }\r\n        //是否已经在openList中\r\n        if(containGrid(openList, x, y)){\r\n            return false;\r\n        }\r\n        //是否已经在closeList中\r\n        if(containGrid(closeList, x, y)){\r\n            return false;\r\n        }\r\n        return true;\r\n    }\r\n\r\n    private static boolean containGrid(List<Grid> grids, int x, int y) {\r\n        for (Grid grid : grids) {\r\n            if ((grid.x == x) && (grid.y == y)) {\r\n                return true;\r\n            }\r\n        }\r\n        return false;\r\n    }\r\n\r\n    static class Grid {\r\n        public int x;\r\n        public int y;\r\n        public int f;\r\n        public int g;\r\n        public int h;\r\n        public Grid parent;\r\n\r\n        public Grid(int x, int y) {\r\n            this.x = x;\r\n            this.y = y;\r\n        }\r\n\r\n        public void initGrid(Grid parent, Grid end){\r\n            this.parent = parent;\r\n            this.g = parent.g + 1;\r\n            this.h = Math.abs(this.x - end.x) + Math.abs(this.y - end.y);\r\n            this.f = this.g + this.h;\r\n        }\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        //设置起点和终点\r\n        Grid startGrid = new Grid(2, 1);\r\n        Grid endGrid = new Grid(2, 5);\r\n        //搜索迷宫终点\r\n        Grid resultGrid = aStarSearch(startGrid, endGrid);\r\n        //回溯迷宫路径\r\n        ArrayList<Grid> path = new ArrayList<Grid>();\r\n        while (resultGrid != null) {\r\n            path.add(new Grid(resultGrid.x, resultGrid.y));\r\n            resultGrid = resultGrid.parent;\r\n        }\r\n        //输出迷宫和路径，路径用星号表示\r\n        for (int i = 0; i < MAZE.length; i++) {\r\n            for (int j = 0; j < MAZE[0].length; j++) {\r\n                if (containGrid(path, i, j)) {\r\n                    System.out.print(\"*, \");\r\n                } else {\r\n                    System.out.print(MAZE[i][j] + \", \");\r\n                }\r\n            }\r\n            System.out.println();\r\n        }\r\n    }\r\n}  "
  },
  {
    "path": "src/chapter6/part5/Redpackage.java",
    "content": "package chapter6.part5;\r\n\r\nimport java.math.BigDecimal;\r\nimport java.util.*;\r\n\r\n/**\r\n* Created by weimengshu on 2018/4/8.\r\n*/\r\npublic class Redpackage {\r\n\r\n    /**\r\n     * 拆分红包\r\n     * @param totalAmount  总金额（以分为单位）\r\n     * @param totalPeopleNum  总人数\r\n     */\r\n    public static List<Integer> divideRedPackage(Integer totalAmount, Integer totalPeopleNum){\r\n        List<Integer> amountList = new ArrayList<Integer>();\r\n        Integer restAmount = totalAmount;\r\n        Integer restPeopleNum = totalPeopleNum;\r\n        Random random = new Random();\r\n        for(int i=0; i<totalPeopleNum-1; i++){\r\n            //随机范围：[1，剩余人均金额的两倍)，左闭右开\r\n            int amount = random.nextInt(restAmount / restPeopleNum * 2 - 1) + 1;\r\n            restAmount -= amount;\r\n            restPeopleNum --;\r\n            amountList.add(amount);\r\n        }\r\n        amountList.add(restAmount);\r\n        return amountList;\r\n    }\r\n\r\n    /**\r\n     * 拆分红包V2\r\n     * @param totalAmount  总金额（以分为单位）\r\n     * @param totalPeopleNum  总人数\r\n     */\r\n    public static List<Integer> divideRedPackageV2(Integer totalAmount, Integer totalPeopleNum){\r\n        List<Integer> amountList = new ArrayList<Integer>();\r\n        Set<Integer> segments = new HashSet<Integer>();\r\n        Random random = new Random();\r\n        for(int i = 0; i< totalPeopleNum-1; i++){\r\n            int segment =  random.nextInt(totalAmount-2) + 1;\r\n            int delta = random.nextInt(1)==0 ? 1 : -1;\r\n            while(segments.contains(segment) || segment == 0){\r\n                segment = (segment+delta)%totalAmount;\r\n            }\r\n            segments.add(segment);\r\n        }\r\n\r\n        List<Integer> segmentList = new ArrayList<Integer>(segments);\r\n        Collections.sort(segmentList);\r\n        for(int i=0; i<segmentList.size(); i++){\r\n            Integer amount;\r\n            if(i==0){\r\n                amount = segmentList.get(0);\r\n            }else {\r\n                amount = segmentList.get(i) - segmentList.get(i-1) ;\r\n            }\r\n            amountList.add(amount);\r\n        }\r\n        amountList.add(totalAmount - segmentList.get(segmentList.size()-1));\r\n\r\n        return amountList;\r\n    }\r\n\r\n    public static void main(String[] args){\r\n        List<Integer> amountList = divideRedPackage(1000, 10);\r\n        for(Integer amount : amountList){\r\n            System.out.println(\"抢到金额：\" + new BigDecimal(amount).divide(new BigDecimal(100)));\r\n        }\r\n    }\r\n}\r\n"
  }
]