zoukankan      html  css  js  c++  java
  • lintcode--剑指offer

    算是大概完成了这个学期初定下的目标,终于刷完了剑指offer的题目,尽管刷了一遍之后感觉自己大部分又忘记了,很明显又要再刷一遍,因此在此再立下一个小目标,在放假前将剑指offer二刷一半吧!!!这个博客就重新将之前做的剑指offer题目整理一下,感觉之前写的太乱了,就算是自己看,感觉以后也不舒服。

    1.Interview Flow

    9. Fizz Buzz(思路:分别除3除5能否整除做操作)

     1 class Solution {
     2     public ArrayList<String> fizzBuzz(int n) {
     3         ArrayList<String> result = new ArrayList<>();
     4         if (n <= 0) {
     5             return result;
     6         }
     7         for (int i = 1; i <= n; i++) {
     8             if (i % 3 == 0 && i % 5 != 0) {
     9                 result.add("fizz");
    10             } else if (i % 5 == 0 && i % 3 != 0) {
    11                 result.add("buzz");
    12             } else if (i % 3 == 0 && i % 5 == 0) {
    13                 result.add("fizz buzz");
    14             } else {
    15                 //result.add(i + "");
    16                 //result.add(Integer.toString(i));
    17                 result.add(String.valueOf(i));
    18             }
    19         }
    20         return result;
    21     }
    22 }
    View Code

    2.Basic Knowledge

    366. Fibonacci (思路:根据 f(0)和f(1)计算出f(2), 进而计算f(3)、f(4)等等,递归会出现TLE错误)

     1 class Solution {
     2     public int fibonacci(int n) {
     3         // if (n <= 0) {
     4         //     return 0;
     5         // }
     6         // //wrong solution: we don't know the value of n, so fib[0] = 0 is wrong!!!
     7         // int[] fib = new int[n];
     8         // fib[0] = 0;
     9         // fib[1] = 1;
    10         // for (int i = 2; i < n; i++) {
    11         //     fib[i] = fib[i - 1] + fib[i - 2];
    12         // }
    13         // return fib[n - 1];
    14         int fib1 = 0;
    15         int fib2 = 1;
    16         int sum = 0;
    17         if (n == 1) {
    18             return 0;
    19         }
    20         if (n == 2) {
    21             return 1;
    22         }
    23         for (int i = 3; i <= n; i++) {
    24             sum = fib1 + fib2;
    25             fib1 = fib2;
    26             fib2 = sum;
    27         }
    28         return sum;
    29     }
    30 }
    View Code
    class Solution {
        //单例模式三个要素:①只有一个实例②必须自己创建这个实例③可以向外部提供这个实例
        //对应的程序:①私有的构造函数保证只有一个实例②类定义中含有一个私有的静态类对象
        //③公有的函数可以获取这个对象
        //懒汉模式
        /**private Solution() {}
        private static Solution instance = null;
        public static Solution getInstance() {
            if (instance == null) {
                instance = new Solution();
            }
            return instance;
        }*/
        //饿汉模式
        /**private Solution() {}
        private static Solution instance = new Solution();
        public static Solution getInstance() {
            return instance;
        }*/
        //加锁双重检查
        private Solution() {}
        private static Solution instance = null;
        public static Solution getInstance() {
            if (instance == null) {
                synchronized (Solution.class) {
                    if (instance == null) {
                        instance = new Solution();
                    }
                }
            }
            return instance;
        }
        
    }
    

    111. Climbing Stairs(思路:找规律,分别算出前几级发现规律跟Fibonacii一样)

     1 public class Solution {
     2     public int climbStairs(int n) {
     3         //we have to find the law of this problem
     4         //1(1) 2(2) 3(3) 4(5) 5(8) 6(13)
     5         //a1 + a2 = a3 
     6         //a2 + a3 = a4
     7         if (n <= 1) {
     8             return 1;
     9         }
    10         int c1 = 1;
    11         int c2 = 2;
    12         if (n == 2) {
    13             return 2;
    14         }
    15         int sum = 0;
    16         for (int i = 3; i <= n; i++) {
    17             sum = c1 + c2;
    18             c1 = c2;
    19             c2 = sum;
    20         }
    21         return sum;
    22     }
    23 }
    View Code

    204. Singleton(思路:①私有的构造函数保证只有一个实例②类定义中含有一个私有的静态类对象③公有的函数可以获取这个对象)

     1 class Solution {
     2     //单例模式三个要素:①只有一个实例②必须自己创建这个实例③可以向外部提供这个实例
     3     //对应的程序:①私有的构造函数保证只有一个实例②类定义中含有一个私有的静态类对象
     4     //③公有的函数可以获取这个对象
     5     private Solution() {
     6     }
     7 
     8     private static Solution instance = null;
     9 
    10     public static Solution getInstance() {
    11         // if (instance == null) {
    12         //     instance = new Solution();
    13         // }
    14         // return instance;
    15         return instance;
    16     }
    17 }
    View Code

    212. Space Replacement (思路:由于必须对字符数组本身进行操作,因此可以先通过空格个数计算新字符数组总长度,然后从后向前进行复制,以确保字符不会被覆盖)

     1 public class Solution {
     2     public int replaceBlank(char[] str, int length) {
     3         if (str == null || str.length <= 0) {
     4             return 0;
     5         }
     6         //this problem needs to be processed in-place, so we should process the
     7         //"str" itself, so we can copy from the end of new "str"
     8         int numOfSpace = 0;
     9         for (int i = 0; i < str.length; i++) {
    10             if (str[i] == ' ') {
    11                 numOfSpace++;
    12             }
    13         }
    14         int newLen = length + numOfSpace * 2;
    15         int i = length - 1;
    16         int j = newLen - 1;
    17         while (i >= 0 && j >= 0) {
    18             if (str[i] == ' ') {
    19                 str[j] = '0';
    20                 j--;
    21                 str[j] = '2';
    22                 j--;
    23                 str[j] = '%';
    24                 j--;
    25                 i--;
    26             } else {
    27                 str[j] = str[i];
    28                 j--;
    29                 i--;
    30             }
    31         }
    32         return newLen;
    33     }
    34 }
    View Code

    365. Count 1 in Binary (思路:把一个整数减一,再和原来的整数做与操作,会把该整数最右边的一个1变为0,因此一个整数有多少个1,便可以进行多少次这样的操作)

     1 public class Solution {
     2     public int countOnes(int num) {
     3         //(1100)&(1100 - 1 = 1011) = (1000)
     4         //把一个整数减一,再和原来的整数做与操作,会把该整数最右边的一个1变为0,
     5         //因此一个整数有多少个1,便可以进行多少次这样的操作
     6         int numOfOne = 0;
     7         while (num != 0) {
     8             numOfOne++;
     9             num = num & (num - 1);
    10         }
    11         return numOfOne;
    12     }
    13 }
    View Code

     35. Reverse Linked List(思路:定义两个指针,分别指向当前节点和前一节点,因此只需要将cur.next = pre就行了,但是要注意保存cur.next)

     1 public class Solution {
     2     public ListNode reverse(ListNode head) {
     3         if (head == null || head.next == null) {
     4             return head;
     5         }
     6         //define two points, pre and cur point to the current node and the node 
     7         //before current node, so let cur.next = pre; 
     8         ListNode pre = null;
     9         ListNode cur = head;
    10         while (cur != null) {
    11             ListNode next = cur.next;
    12             // this code is used to save cur.next, because node will be 
    13             //moved backward, but it has been changed.
    14             cur.next = pre;
    15             pre = cur;
    16             cur = next;
    17         }
    18         return pre;
    19     }
    20 }
    View Code

    36. Reverse Linked List II (思路:分三步,第一保存mNode和它之前的节点,第二步从mNode到nNode反转,第三步保存nNode,并将链表连接起来)

     1 public class Solution {
     2     public ListNode reverseBetween(ListNode head, int m , int n) {
     3         if (head == null || head.next == null || m >= n) {
     4             return head;
     5         }
     6         //Three Steps
     7         ListNode dummy = new ListNode(0);
     8         dummy.next = head;
     9         ListNode cur = dummy;
    10         //Step1: find and save mNode and the node before mNode
    11         for (int i = 1; i < m; i++) {
    12             cur = cur.next;
    13         }
    14         ListNode mPre = cur;
    15         ListNode mNode = cur.next;
    16         //Step2: reverse the list from mNode to nNode
    17         ListNode pre = cur.next;
    18         cur = pre.next;
    19         for (int i = m; i < n; i++) {
    20             ListNode next = cur.next;
    21             cur.next = pre;
    22             pre = cur;
    23             cur = next;
    24         }
    25         //Step3: save the nNode and link the list again
    26         ListNode nNode = pre;
    27         ListNode nNext = cur;
    28         mPre.next = nNode;
    29         mNode.next = nNext;
    30         return dummy.next;
    31     }
    32 }
    View Code

    28.  Search a 2D Matrix(思路: 把target跟右上角的数相比,如果小于右上角,去前一列,如果大于,去后一行)

     1 public class Solution {
     2     public boolean searchMatrix(int[][] matrix, int target) {
     3         //compare target and number of top right corner, 
     4         //if target < matrix[top right corner], then the column--
     5         //if target > matrix[rop right corner], then the row++
     6         if (matrix == null || matrix.length == 0) {
     7             return false;
     8         }
     9         if (matrix[0] == null || matrix[0].length == 0) {
    10             return false;
    11         }
    12 
    13         int row = matrix.length;
    14         int column = matrix[0].length;
    15         int i = 0;
    16         int j = column - 1;
    17 
    18         while (i < row && j >= 0) {
    19             if (target > matrix[i][j]) {
    20                 i++;
    21             } else if (target < matrix[i][j]) {
    22                 j--;
    23             } else {
    24                 return true;
    25             }
    26         }
    27         return false;
    28     }
    29 }
    View Code

    38. Search a 2D Matrix II(思路:同上,注意如果target找到,注意更换行和列,否则会死循环)

     1 public class Solution {
     2     public int searchMatrix(int[][] matrix, int target) {
     3         //it is the same as the solution of "search a 2D Matrix"
     4         //but we should notice that 21 line and 22 line, after targetNum++, the 
     5         //row and column should be changed
     6         int targetNum = 0;
     7         if (matrix == null || matrix.length == 0) {
     8             return targetNum;
     9         }
    10         if (matrix[0] == null || matrix[0].length == 0) {
    11             return targetNum;
    12         }
    13 
    14         int row = matrix.length;
    15         int column = matrix[0].length;
    16         int i = 0;
    17         int j = column - 1;
    18 
    19         while (i < row && j >= 0) {
    20             if (target == matrix[i][j]) {
    21                 targetNum++;
    22                 j--;
    23                 i++;
    24             } else if (target < matrix[i][j]) {
    25                 j--;
    26             } else {
    27                 i++;
    28             }
    29         }
    30         return targetNum;
    31     }
    32 }
    View Code

    159. Find Minimum in Rotated Sorted Array(思路: 二分查找,用nums[right] 与 nums[mid]比较,这样对数组没有旋转的情况也适用,注意nums[right] > nums[mid]的特殊处理)

     1 public class Solution {
     2     public int findMin(int[] nums) {
     3         //Example : (4 5 6 7 0 1 2) (5 0 1 2 3 4)
     4         //compare nums[right] and nums[mid] (we don't compare nums[left] and nums[mid],
     5         //because it doesn't the instance of (0 1 2 3 4 5), which the array is
     6         //not rotated) if "nums[right] < nums[mid]" means the target is in the
     7         //right part, then "left = mid + 1" (notice that "left = mid" is wrong)
     8         //else the target is in the left part
     9         if (nums == null || nums.length == 0) {
    10             return 0;
    11         }
    12 
    13         int left = 0;
    14         int right = nums.length - 1;
    15 
    16         while (left < right) {
    17             int mid = left + (right - left) / 2;
    18             if (nums[right] < nums[mid]) {
    19                 left = mid + 1;
    20             }  else {
    21                 right = mid;
    22             }
    23         }
    24         return nums[right];
    25     }
    26 }
    View Code

    160. Find Minimum in Rotated Sorted Array II (思路:有重复数字时,需要对相等的情况进行处理,就是nums[right] == nums[left],操作是"right--")

     1 public class Solution {
     2     public int findMin(int[] nums) {
     3         //it is the same as "Find Minimum in Rotated Sorted Array "
     4         //but we should notice that if duplicates exist, we should do "right--"
     5         if (nums == null || nums.length == 0) {
     6             return 0;
     7         }
     8 
     9         int left = 0;
    10         int right = nums.length - 1;
    11 
    12         while (left < right) {
    13             int mid = left + (right - left) / 2;
    14             if (nums[right] > nums[mid]) {
    15                 right = mid;
    16             } else if (nums[right] < nums[mid]) {
    17                 left = mid + 1;
    18             } else {
    19                 right--;
    20             }
    21         }
    22         return nums[right];
    23     }
    24 }
    View Code

    40.  Implement Queue by Two Stacks (思路: 将新来的数字压入栈1,从栈2中进行pop和top操作,举个实际的例子说明更易理解)

     1 public class MyQueue {
     2     Stack<Integer> stack1;
     3     Stack<Integer> stack2;
     4     //notice the importance of "stack1ToStack2", push the element to stack1, and
     5     //pop and top the element from stack2
     6     public MyQueue() {
     7         stack1 = new Stack<>();
     8         stack2 = new Stack<>();
     9     }
    10 
    11     private void stack1ToStack2() {
    12         while (!stack1.isEmpty()) {
    13             stack2.push(stack1.pop());
    14         }
    15     }
    16 
    17     public void push(int num) {
    18         stack1.push(num);
    19     }
    20 
    21     public int pop() {
    22         if (stack2.isEmpty()) {
    23             stack1ToStack2();
    24         }
    25         return stack2.pop();
    26     }
    27 
    28     public int top() {
    29         if (stack2.isEmpty()) {
    30             stack1ToStack2();
    31         }
    32         return stack2.peek();
    33     }
    34 }
    View Code

    72. Construct Binary Tree from Inorder and Postorder Traversal (思路: 首先根据后序遍历中的根节点(最后一个数字)从中序遍历中找出其位置,利用这个位置作为递归辅助函数的参数,然后先建立左子树,再建立右子树)

     1 public class Solution {
     2     public TreeNode buildTree(int[] inorder, int[] postorder) {
     3         if (inorder.length != postorder.length) {
     4             return null;
     5         }
     6         return buildTreeHelper(inorder, 0, inorder.length - 1, postorder, 0, postorder.length - 1);
     7     }
     8     //build root, build the left tree, build the right tree, notice the importance of parameters
     9     public TreeNode buildTreeHelper(int[] inorder, int inStart, int inEnd, int[] postorder, int postStart, int postEnd) {
    10         if (inStart > inEnd) {
    11             return null;
    12         }
    13         TreeNode root = new TreeNode(postorder[postEnd]);
    14         int rootIndex = findRoot(inorder, root.val);
    15         root.left = buildTreeHelper(inorder, inStart, rootIndex - 1, postorder, postStart, postStart + (rootIndex - inStart) - 1);
    16         root.right = buildTreeHelper(inorder, rootIndex + 1, inEnd, postorder, postStart + (rootIndex - inStart), postEnd - 1);
    17         return root;
    18     }
    19     //find the position of root in Inorder traversal
    20     private int findRoot(int[] inorder, int root) {
    21         if (inorder == null || inorder.length == 0) {
    22             return -1;
    23         }
    24         int rootIndex = 0;
    25         for (int i = 0; i < inorder.length; i++) {
    26             if (root == inorder[i]) {
    27                 rootIndex = i;
    28             }
    29         }
    30         return rootIndex;
    31     }
    32 }
    View Code

    73. Construct Binary Tree from Preorder and Inorder Traversal (思路:首先根据前序遍历中的根节点(第一个数字)从中序遍历中找出其位置,利用这个位置作为递归辅助函数的参数,然后先建立左子树,再建立右子树)

    public class Solution {
        public TreeNode buildTree(int[] preOrder, int[] inOrder) {
            if (preOrder.length != inOrder.length) {
                return null;
            }
            return buildTreeHelper(preOrder, 0, preOrder.length - 1, inOrder, 0, inOrder.length - 1);
        }
        //build root, build the left tree, build the right tree, notice the importance of parameters
        public TreeNode buildTreeHelper(int[] preOrder, int preStart, int preEnd, int[] inOrder, int inStart, int inEnd) {
            if (preStart > preEnd || inStart > inEnd) {
                return null;
            }
            TreeNode root = new TreeNode(preOrder[preStart]);
            int rootIndex = findRoot(inOrder, root.val);
            root.left = buildTreeHelper(preOrder, preStart + 1, preStart + (rootIndex - inStart), inOrder, inStart, rootIndex - 1);
            root.right = buildTreeHelper(preOrder, preStart + (rootIndex - inStart) + 1, preEnd, inOrder, rootIndex + 1, inEnd);
            return root;
        }
        //find the position of root in Inorder traversal
        public int findRoot(int[] inOrder, int root) {
            int rootIndex = 0;
            for (int i = 0; i < inOrder.length; i++) {
                if (root == inOrder[i]) {
                    rootIndex = i;
                }
            }
            return rootIndex;
        }
    }
    View Code

    3. Coding Quality

    373. Partition Array by Odd and Even (思路: 双指针,考虑到可扩展性,把判断部分写成子函数)

     1 public class Solution {
     2     public void partitionArray(int[] nums) {
     3         //an easy problem using twoPoints to solve
     4         //line 17 is very important, it can process the instance of the array 
     5         //that has been processed (1 3 5 2 4 6)
     6         if (nums == null || nums.length == 0) {
     7             return;
     8         }
     9         int left = 0;
    10         int right = nums.length - 1;
    11         while (left < right) {
    12             while (!divideFun(nums[left])) {
    13                 left++;
    14             }
    15             while (divideFun(nums[right])) {
    16                 right--;
    17             }
    18             if (left < right) {
    19                 int temp = nums[left];
    20                 nums[left] = nums[right];
    21                 nums[right] = temp;
    22             }
    23         }
    24     }
    25     public boolean divideFun(int num) {
    26         if (num % 2 == 0) {
    27             return true;
    28         }
    29         return false;
    30     }
    31 }
    View Code

    372. Delete Node in the Middle of Singly Linked List(思路: 改变node的值以及next, node.val = node.next.val    node.next = node.next.next)

     1 /**
     2  * Definition for ListNode.
     3  * public class ListNode {
     4  *     int val;
     5  *     ListNode next;
     6  *     ListNode(int val) {
     7  *         this.val = val;
     8  *         this.next = null;
     9  *     }
    10  * }
    11  */
    12 public class Solution {
    13     public void deleteNode(ListNode node) {
    14         if (node == null) {
    15             return;
    16         }
    17         //change the value of node and the next of node;
    18         node.val = node.next.val;
    19         node.next = node.next.next;
    20     }
    21 }
    View Code

    245. Subtree (思路:开始注意考虑所有可能为空的情况。一个函数用于判断两个树是否相同,然后先判断树1是否与树2相同,如果不同,再判断以树1左节点或者右节点为根节点的树是否与树2相同)

     1 /**
     2  * Definition of TreeNode:
     3  * public class TreeNode {
     4  *     public int val;
     5  *     public TreeNode left, right;
     6  *     public TreeNode(int val) {
     7  *         this.val = val;
     8  *         this.left = this.right = null;
     9  *     }
    10  * }
    11  */
    12 public class Solution {
    13     /**
    14      * @param T1, T2: The roots of binary tree.
    15      * @return: True if T2 is a subtree of T1, or false.
    16      */
    17     public boolean isSubtree(TreeNode root1, TreeNode root2) {
    18         //a difficult problem! we have to consider all instances
    19         //line 20 must be judged first!!!
    20         if (root2 == null) {
    21             return true;
    22         }    
    23         if (root1 == null) {
    24             return false;
    25         }
    26         if(isEqual(root1, root2)) {
    27             return true;
    28         }
    29         return isSubtree(root1.left, root2) || isSubtree(root1.right, root2);
    30     }
    31     public boolean isEqual(TreeNode root1, TreeNode root2) {
    32         //the function is to judge if two trees are equal! 
    33         if (root1 == null || root2 == null) {
    34             //nice code!!!
    35             return root1 == root2;
    36         }
    37         if (root1.val != root2.val) {
    38             return false;
    39         }
    40         return isEqual(root1.left, root2.left) && isEqual(root1.right, root2.right);
    41     }
    42 }
    View Code

     174. Remove Nth Node From End of List (思路: 定义快慢两个指针, 快指针先走n步, 然后两个指针一起走直到快指针到头,此时慢指针指向要删除节点的前一节点)

     1 /**
     2  * Definition for ListNode.
     3  * public class ListNode {
     4  *     int val;
     5  *     ListNode next;
     6  *     ListNode(int val) {
     7  *         this.val = val;
     8  *         this.next = null;
     9  *     }
    10  * }
    11  */
    12 public class Solution {
    13     /**
    14      * @param head: The first node of linked list.
    15      * @param n: An integer.
    16      * @return: The head of linked list.
    17      */
    18     ListNode removeNthFromEnd(ListNode head, int n) {
    19         //define two points slow and fast, fast move forward n steps, move slow
    20         //and fast until fast.next == null, then slow points to the node that 
    21         //we need.
    22         if (head == null || n < 1) {
    23             return null;
    24         }
    25 
    26         ListNode dummy = new ListNode(0);
    27         dummy.next = head;
    28         ListNode fast = dummy;
    29 
    30         for (int i = 0; i < n; i++) {
    31             fast = fast.next;
    32         }
    33 
    34         ListNode slow = dummy;
    35         while (fast.next != null) {
    36             fast = fast.next;
    37             slow = slow.next;
    38         }
    39 
    40         slow.next = slow.next.next;
    41 
    42         return dummy.next;
    43     }
    44 }
    View Code

    165. Merge Two Sorted Lists (思路: 递归做法,比较两个头的值,较小的就是下一节点)

     1 /**
     2  * Definition for ListNode.
     3  * public class ListNode {
     4  *     int val;
     5  *     ListNode next;
     6  *     ListNode(int val) {
     7  *         this.val = val;
     8  *         this.next = null;
     9  *     }
    10  * }
    11  */
    12 public class Solution {
    13     /**
    14      * @param ListNode l1 is the head of the linked list
    15      * @param ListNode l2 is the head of the linked list
    16      * @return: ListNode head of linked list
    17      */
    18     public ListNode mergeTwoLists(ListNode head1, ListNode head2) {
    19         //notice line 22 , if the code is "else" , it is wrong, line 25 can't be 
    20         //reached, line 21 to line 24 must be returned
    21         if (head1 == null) {
    22             return head2;
    23         } else if (head2 == null){
    24             return head1;
    25         }
    26 
    27         ListNode mergeHead = null;
    28 
    29         if (head1.val < head2.val) {
    30             mergeHead = head1;
    31             mergeHead.next = mergeTwoLists(head1.next, head2);
    32         } else {
    33             mergeHead = head2;
    34             mergeHead.next = mergeTwoLists(head1, head2.next);
    35         }
    36         return mergeHead;
    37     }
    38 }
    View Code

     371. Print Numbers by Recursion(比较难想到的题目,Mark一下)

     1 public class Solution {
     2     /**
     3      * @param n: An integer.
     4      * return : An array storing 1 to the largest number with n digits.
     5      */
     6     public List<Integer> numbersByRecursion(int n) {
     7         List<Integer> result = new ArrayList<>();
     8         if (n <= 0) {
     9             return result;
    10         }
    11         recursion(n, 0, result);
    12         return result;
    13     }
    14     //the definition of recursion
    15     public void recursion(int n, int num, List<Integer> result) {
    16         //the exit of recursion
    17         if (n == 0) {
    18             if (num > 0) {
    19                 result.add(num);
    20             }
    21             return;
    22         }
    23         //the dismantling of recursion
    24         for (int i = 0; i < 10; i++) {
    25             recursion(n - 1, num * 10 + i, result);
    26         }
    27     }
    28 }
    View Code

    140. Fast Power (比较难想到的题目,Mark一下)

     1 class Solution {
     2     public int fastPower(int a, int b, int n) {
     3         //the exit of recursion
     4         if (n == 0) {
     5             return 1 % b;
     6         }
     7         if (n == 1) {
     8             return a % b;
     9         }
    10         //the definition of recursion
    11         long result = fastPower(a, b, n / 2);
    12         //long result = fastPower(a, b, n >> 1);
    13         //the dismantling of recursion
    14         result = (result * result) % b;
    15         if (n % 2 == 1) {
    16             result = (result * a) % b;
    17         }
    18         return (int) result;
    19     }
    20 }
    View Code

     376. Binary Tree Path Sum(思路: 定义一个递归函数对树进行前序遍历,直到到达叶节点,此时,不管符不符合要求,都退回父节点,对树的另一侧进行相同的操作)

     1 /**
     2  * Definition of TreeNode:
     3  * public class TreeNode {
     4  *     public int val;
     5  *     public TreeNode left, right;
     6  *     public TreeNode(int val) {
     7  *         this.val = val;
     8  *         this.left = this.right = null;
     9  *     }
    10  * }
    11  */
    12 public class Solution {
    13     /**
    14      * @param root the root of binary tree
    15      * @param target an integer
    16      * @return all valid paths
    17      */
    18     public List<List<Integer>> binaryTreePathSum(TreeNode root, int target) {
    19         List<List<Integer>> result = new ArrayList<>();
    20         if (root == null) {
    21             return result;
    22         }
    23         List<Integer> tempList = new ArrayList<>();
    24         recHelper(result, tempList, root, target);
    25         return result;
    26     }
    27     public void recHelper(List<List<Integer>> result, List<Integer> tempList, TreeNode root, int target) {
    28         //递归函数的作用可以理解为:一直在前序遍历树直到叶节点
    29         tempList.add(root.val);
    30         //current node is the leaf node
    31         if (root.left == null && root.right == null) {
    32             if (root.val == target) {
    33                 result.add(new ArrayList<Integer>(tempList));
    34             }
    35             return;
    36         }
    37         if (root.left != null) {
    38             recHelper(result, tempList, root.left, target - root.val);
    39             //递归的思路一般比较难理解,如果程序已经运行到这里,说明已经找到一条合适的路径例如(1,2,2),或者是已经到达叶节点单仍然没有找到合适的路径,因此下一步需要退回到父节点寻找下一跳合适的路径
    40             tempList.remove(tempList.size() - 1);
    41         }
    42         if (root.right != null) {
    43             recHelper(result, tempList, root.right, target - root.val);
    44             tempList.remove(tempList.size() - 1);
    45         }
    46     }
    47 }
    View Code
    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     */
    public class Solution {
        /**
         * @param root the root of binary tree
         * @param target an integer
         * @return all valid paths
         */
         //递归函数需要有个临时链表作为参数,用于保存当前遍历的值,递归出口定义时,只要到达叶节点切记返回,递归出去了,说明到达了叶节点,此时需要返回父节点,继续从另一侧进行判断
        public List<List<Integer>> binaryTreePathSum(TreeNode root, int target) {
            List<List<Integer>> result = new ArrayList();
            if (root == null) {
                return result;
            }
            List<Integer> tempList = new ArrayList<>();
            recHelper(result, tempList, root, target);
            return result;
        }
        public void recHelper(List<List<Integer>> result, List<Integer> tempList, TreeNode root, int target) {
            //递归出口:(首先注意题目要求:路径一定是从根节点到叶节点的路径,当遍历到叶节点的时候不管符不符合target要求,必然返回,跳出当前递归,防止死循环)
            tempList.add(root.val);
            if (root.left == null && root.right == null) {
                if (root.val == target) {
                    result.add(new ArrayList<Integer>(tempList));
                }
                return;
            }
            if (root.left != null) {
                recHelper(result, tempList, root.left, target - root.val);
                //从这里开始进入递归,不断递归直到出递归,运行到这里,说明必然到达了叶节点,此时返回父节点开始判断右子节点是否满足,并且临时链表除去左子节点的值
                tempList.remove(tempList.size() - 1);
            }
            if (root.right != null) {
                recHelper(result, tempList, root.right, target - root.val);
                tempList.remove(tempList.size() - 1);
            }
        }
    }
    

    375. Clone Binary Tree (思路:简单的递归问题,先复制左子树 ,然后复制右字树)

     1 /**
     2  * Definition of TreeNode:
     3  * public class TreeNode {
     4  *     public int val;
     5  *     public TreeNode left, right;
     6  *     public TreeNode(int val) {
     7  *         this.val = val;
     8  *         this.left = this.right = null;
     9  *     }
    10  * }
    11  */
    12 public class Solution {
    13     /**
    14      * @param root: The root of binary tree
    15      * @return root of new tree
    16      */
    17     public TreeNode cloneTree(TreeNode root) {
    18         //easy problem of recursion
    19         if (root == null) {
    20             return root;
    21         }
    22         TreeNode newRoot = new TreeNode(root.val);
    23         newRoot.left = cloneTree(root.left);
    24         newRoot.right = cloneTree(root.right);
    25         return newRoot;
    26     }
    27 }
    View Code

    211. String Permutation(思路: 利用字符的ackii码,定义一个数组用以字符ackii码的形式记录源字符串中字符出现的次数,再对目标字符串进行遍历,同样的方式,只不过变成数字减一,最后判断数组是不是全为0就行)

     1 public class Solution {
     2     /**
     3      * @param A a string
     4      * @param B a string
     5      * @return a boolean
     6      */
     7     public boolean stringPermutation(String a, String b) {
     8         if (a.length() != b.length()) {
     9             return false;
    10         }
    11         int[] temp = new int[1000];
    12         for (int i = 0; i < a.length(); i++) {
    13             temp[(int) a.charAt(i)] += 1;
    14         }
    15         for (int i = 0; i < b.length(); i++) {
    16             temp[(int) b.charAt(i)] -= 1;
    17         }
    18         for (int i = 0; i < a.length(); i++) {
    19             if (temp[i] != 0) {
    20                 return false;
    21             }
    22         }
    23         return true;
    24     }
    25 }
    View Code
    public class Solution {
        /**
         * @param A a string
         * @param B a string
         * @return a boolean
         */
        public boolean Permutation(String a, String b) {
            //注意如何将字符转化为ackii码(直接强制转换),以及判断整个数组是否为0(遍历)
            if (a == null || b == null) {
                return a == b;
            }
            if (a.length() != b.length()) {
                return false;
            }
            int[] nums = new int[150];
            for (int i = 0; i < a.length(); i++) {
                nums[(int)a.charAt(i)]++;
            }
            for (int i = 0; i < b.length(); i++) {
                nums[(int)b.charAt(i)]--;
            }
            for (int i = 0; i < nums.length; i++) {
                if (nums[i] != 0) {
                    return false;
                }
            }
            return true;
        }
    }
    

    4. Thought of Solution

    69.  Binary Tree Level Order Traversal(思路:举个例子就会发现,这是一个先入先出的过程,因此定义一个队列,注意队列的大小就是当前深度的节点数目)

     1 /**
     2  * Definition of TreeNode:
     3  * public class TreeNode {
     4  *     public int val;
     5  *     public TreeNode left, right;
     6  *     public TreeNode(int val) {
     7  *         this.val = val;
     8  *         this.left = this.right = null;
     9  *     }
    10  * }
    11  */
    12 public class Solution {
    13     /**
    14      * @param root: The root of binary tree.
    15      * @return: Level order a list of lists of integer
    16      */
    17     public ArrayList<ArrayList<Integer>> levelOrder(TreeNode root) {
    18         ArrayList<ArrayList<Integer>> result = new ArrayList<>();
    19         if (root == null) {
    20             return result;
    21         }
    22 
    23         //queue is an interface, and it can be implmented by LinkedList
    24         Queue<TreeNode> queue = new LinkedList<>();
    25         queue.offer(root);
    26 
    27         while (!queue.isEmpty()) {
    28 
    29             ArrayList<Integer> level = new ArrayList<>();
    30             // the queueSize is the number of node of this level
    31             int queueSize = queue.size();
    32 
    33             for (int i = 0; i < queueSize; i++) {
    34 
    35                 TreeNode head = queue.poll();
    36                 level.add(head.val);
    37 
    38                 if (head.left != null) {
    39                     queue.offer(head.left);
    40                 }
    41                 if (head.right != null) {
    42                     queue.offer(head.right);
    43                 }
    44             }
    45             result.add(level);
    46         }
    47         return result;
    48     }
    49 }
    View Code

    70. Binary Tree Level Order Traversal II (思路: 同上,只需要最后将链表反转就行了)

     1 /**
     2  * Definition of TreeNode:
     3  * public class TreeNode {
     4  *     public int val;
     5  *     public TreeNode left, right;
     6  *     public TreeNode(int val) {
     7  *         this.val = val;
     8  *         this.left = this.right = null;
     9  *     }
    10  * }
    11  */
    12  
    13  
    14 public class Solution {
    15     /**
    16      * @param root: The root of binary tree.
    17      * @return: buttom-up level order a list of lists of integer
    18      */
    19     public ArrayList<ArrayList<Integer>> levelOrderBottom(TreeNode root) {
    20         ArrayList<ArrayList<Integer>> result = new ArrayList<>();
    21         if (root == null) {
    22             return result;
    23         }
    24 
    25         Queue<TreeNode> queue = new LinkedList<>();
    26         queue.offer(root);
    27 
    28         while (!queue.isEmpty()) {
    29 
    30             ArrayList<Integer> level = new ArrayList<>();
    31             int queueSize = queue.size();
    32 
    33             for (int i = 0; i < queueSize; i++) {
    34 
    35                 TreeNode head = queue.poll();
    36                 level.add(head.val);
    37 
    38                 if (head.left != null) {
    39                     queue.offer(head.left);
    40                 }
    41                 if (head.right != null) {
    42                     queue.offer(head.right);
    43                 } 
    44             }
    45             result.add(level);
    46         }
    47 
    48         //reverse the list;
    49         Collections.reverse(result);
    50         return result;
    51     }
    52 }
    View Code

    66. Binary Tree Preorder Traversal (思路: 前序、中序、后序三种遍历的递归方式是特别简单的,但是需要掌握非递归遍历的方法,前序的思路很简单,建立一个栈用来保存节点就行,注意往栈里面先加入右子树,再加入左子树)

     1 public class Solution {
     2     /**
     3      * @param root: The root of binary tree.
     4      * @return: Preorder in ArrayList which contains node values.
     5      */
     6     public ArrayList<Integer> preorderTraversal(TreeNode root) {
     7         //because stack is last in first out, root.right should be pushed first
     8         //the thought is the same as the level traversal;
     9         ArrayList<Integer> result = new ArrayList<>();
    10         if (root == null) {
    11             return result;
    12         }
    13 
    14         Stack<TreeNode> stack = new Stack<>();
    15         stack.push(root);
    16 
    17         while (!stack.isEmpty()) {
    18 
    19             TreeNode head = stack.pop();
    20             result.add(head.val);
    21 
    22             if (head.right != null) {
    23                 stack.push(head.right);
    24             }
    25             if (head.left != null) {
    26                 stack.push(head.left);
    27             }
    28         }
    29         return result;
    30     }
    31     /**
    32      * the method of recursion
    33      * 递归函数可以理解为将节点的值加入链表中
    34     public ArrayList<Integer> preorderTraversal(TreeNode root) {
    35         ArrayList<Integer> result = new ArrayList<>();
    36         if (root == null) {
    37             return result;
    38         }
    39         helper(result, root);
    40         return result;
    41     }
    42     public void helper(ArrayList<Integer> result, TreeNode root) {
    43         if (root == null) {
    44             return;
    45         }
    46         result.add(root.val);
    47         helper(result, root.left);
    48         helper(result, root.right);
    49     }
    50     */
    51 }
    View Code

    67. Binary Tree Inorder Traversal (思路:中序遍历跟前序遍历的思路不同,不过还是需要建立一个栈保存节点,由于是先遍历左子树,所以要先遍历到左边的叶节点,然后根据先入后出的特点,退回父节点再进行遍历)

     1 public class Solution {
     2     /**
     3      * @param root: The root of binary tree.
     4      * @return: Inorder in ArrayList which contains node values.
     5      */
     6     /**
     7     public ArrayList<Integer> inorderTraversal(TreeNode root) {
     8         ArrayList<Integer> result = new ArrayList<>();
     9         if (root == null) {
    10             return result;
    11         }
    12         helper(result, root);
    13         return result;
    14     }
    15     public void helper(ArrayList<Integer> result, TreeNode root) {
    16         if (root == null) {
    17             return;
    18         }
    19         helper(result, root.left);
    20         result.add(root.val);
    21         helper(result, root.right);
    22     }
    23     */
    24     public ArrayList<Integer> inorderTraversal(TreeNode root) {
    25         //an example will make this problem easy.
    26         ArrayList<Integer> result = new ArrayList<>();
    27         if (root == null) {
    28             return result;
    29         }
    30 
    31         Stack<TreeNode> stack = new Stack<>();
    32         TreeNode cur = root;
    33 
    34         while (cur != null || !stack.isEmpty()) {
    35             //get the left tree first
    36             while (cur != null) {
    37                 stack.push(cur);
    38                 cur = cur.left;
    39             }
    40             //get the right tree.
    41             cur = stack.pop();
    42             result.add(cur.val);
    43             cur = cur.right;
    44         }
    45         return result;
    46     }
    47 }
    View Code
     1 public class Solution {
     2     /**
     3      * @param root: The root of binary tree.
     4      * @return: Inorder in ArrayList which contains node values.
     5      */
     6     /**public ArrayList<Integer> inorderTraversal(TreeNode root) {
     7         ArrayList<Integer> result = new ArrayList<>();
     8         if (root == null) {
     9             return result;
    10         }
    11         recHelper(result, root);
    12         return result;
    13     }
    14     public void recHelper(ArrayList<Integer> result, TreeNode root) {
    15         if (root == null) {
    16             return;
    17         }
    18         recHelper(result, root.left);
    19         result.add(root.val);
    20         recHelper(result, root.right);
    21     }*/
    22     public ArrayList<Integer> inorderTraversal(TreeNode root) {
    23         //三种遍历都需要一个栈来保存节点,需要注意的是中序遍历不同,因为第一个值为左子树的左叶节点,因此需要先遍历到此处,之后再遍历右子树,注意while循环的条件
    24         ArrayList<Integer> result = new ArrayList<>();
    25         if (root == null) {
    26             return result;
    27         }
    28         Stack<TreeNode> stack = new Stack<>();
    29         TreeNode cur = root;
    30         //cur != null 保证可以进入循环
    31         while (cur != null || !stack.isEmpty()) {
    32             //遍历到最左边的叶节点(集合中第一个值)
    33             while (cur != null) {
    34                 stack.push(cur);
    35                 cur = cur.left;
    36             }
    37             //两次pop之后回到父节点
    38             cur = stack.pop();
    39             result.add(cur.val);
    40             cur = cur.right;
    41         }
    42         return result;
    43     }
    44 }

    68. Binary Tree Postorder Traversal (思路:后序遍历跟前序遍历类似,因为他们是对称的,因此跟前序遍历类似,不过需要倒着添加值,因此需要 LinkedList 的 addFirst 功能)

     1 public class Solution {
     2     /**
     3      * @param root: The root of binary tree.
     4      * @return: Postorder in ArrayList which contains node values.
     5      */
     6     /**
     7      * the method of recursion
     8      * the thought is the same as inorder and preorder
     9     public ArrayList<Integer> postorderTraversal(TreeNode root) {
    10         ArrayList<Integer> result = new ArrayList<>();
    11         if (root == null) {
    12             return result;
    13         }
    14         helper(result, root);
    15         return result;
    16     }
    17     private void helper(ArrayList<Integer> result, TreeNode root) {
    18         if (root == null) {
    19             return;
    20         }
    21         helper(result, root.left);
    22         helper(result, root.right);
    23         result.add(root.val);
    24     }
    25     */
    26     public ArrayList<Integer> postorderTraversal(TreeNode root) {
    27         ArrayList<Integer> result = new ArrayList<>();
    28         if (root == null) {
    29             return result;
    30         }
    31         //only linkedList has "addFirst", the thought is the same as preorder
    32         //because preorder and postorder is symmetrical(对称的)
    33 
    34         LinkedList<Integer> linkedList = new LinkedList<>();
    35         Stack<TreeNode> stack = new Stack<>();
    36         stack.push(root);
    37 
    38         while (!stack.isEmpty()) {
    39             TreeNode cur = stack.pop();
    40             linkedList.addFirst(cur.val);
    41             if (cur.left != null) {
    42                 stack.push(cur.left);
    43             }
    44             if (cur.right != null) {
    45                 stack.push(cur.right);
    46             }
    47         }
    48 
    49         for (int i = 0; i < linkedList.size(); i++) {
    50             result.add(linkedList.get(i));
    51         }
    52 
    53         return result;
    54     }
    55 }
    View Code

    378. Convert Binary Search Tree to Doubly Linked List (思路:递归,分别将左右子树转化为两个 doublyList , 注意建立一个新类DoublyList,有两个参数,头和尾)

    /**
     * Definition for Doubly-ListNode.
     * public class DoublyListNode {
     *     int val;
     *     DoublyListNode next, prev;
     *     DoublyListNode(int val) {
     *         this.val = val;
     *         this.next = this.prev = null;
     *     }
     * }
     */
    public class Solution {
        /**
         * @param root: The root of tree
         * @return: the head of doubly list node
         */
        class DoublyList {
            //build a new class "DoublyList", it has first (head) and last (tail)
            DoublyListNode first;
            DoublyListNode last;
            public DoublyList(DoublyListNode first, DoublyListNode last) {
                this.first = first;
                this.last = last;
            }
        }
        public DoublyListNode bstToDoublyList(TreeNode root) {
            if (root == null) {
                return null;
            }
            DoublyListNode result = recHelper(root).first;
            return result;
        }
        public DoublyList recHelper(TreeNode root) {
            if (root == null) {
                return null;
            }
            //convert the left tree to a doublyList
            DoublyList left = recHelper(root.left);
            //convert the right tree to a doublyList
            DoublyList right = recHelper(root.right);
    
            DoublyList result = new DoublyList(null, null);
            DoublyListNode node = new DoublyListNode(root.val);
    
            //if left tree is null, then the current node is the head of DoublyList
            //else, the head of the left DoublyList is the head of result
            //the right is the same.
            if (left == null) {
                result.first = node;
            } else {
                result.first = left.first;
                left.last.next = node;
                node.prev = left.last;
            }
            if (right == null) {
                result.last = node;
            } else {
                result.last = right.last;
                node.next = right.first;
                right.first.prev = node;
            }
            return result;
        }
    }
    View Code
     1 /**
     2  * Definition for Doubly-ListNode.
     3  * public class DoublyListNode {
     4  *     int val;
     5  *     DoublyListNode next, prev;
     6  *     DoublyListNode(int val) {
     7  *         this.val = val;
     8  *         this.next = this.prev = null;
     9  *     }
    10  * }
    11  */
    12 public class Solution {
    13     /**
    14      * @param root: The root of tree
    15      * @return: the head of doubly list node
    16      */
    17      //需定义一个新类来存放双链表的头和尾(即一个双链表)
    18     class DoublyList {
    19         DoublyListNode head;
    20         DoublyListNode tail;
    21         public DoublyList(DoublyListNode head, DoublyListNode tail) {
    22             this.head = head;
    23             this.tail = tail;
    24         } 
    25     }
    26     public DoublyListNode bstToDoublyList(TreeNode root) {
    27         DoublyListNode result = null;
    28         if (root == null) {
    29             return result;
    30         }
    31         result = recHelper(root).head;
    32         return result;
    33     }
    34     public DoublyList recHelper(TreeNode root) {
    35         if (root == null) {
    36             return null;
    37         }
    38         DoublyList result = new DoublyList(null, null);
    39         //这一句写成DoublyList result = null 是错的,注意null的使用 
    40         //假设已经将左子树和右子树分别转化为一个双链表,然后便将根节点连接起来(这是理解这个递归函数的思路)
    41         DoublyList leftList = recHelper(root.left);
    42         DoublyList rightList = recHelper(root.right);
    43         DoublyListNode cur = new DoublyListNode(root.val);
    44         if (leftList == null) {
    45             result.head = cur;
    46         } else {
    47             result.head = leftList.head;
    48             leftList.tail.next = cur;
    49             cur.prev = leftList.tail;
    50         }
    51         if (rightList == null) {
    52             result.tail = cur;
    53         } else {
    54             result.tail = rightList.tail;
    55             cur.next = rightList.head;
    56             rightList.head.prev = cur;
    57         }
    58         return result;
    59     }
    60 }

    374. Spiral Matrix (思路:注意循环的条件,还有就是注意每一步进行的条件)

     1 public class Solution {
     2     /**
     3      * @param matrix a matrix of m x n elements
     4      * @return an integer list
     5      */
     6     public List<Integer> spiralOrder(int[][] matrix) {
     7         List<Integer> result = new ArrayList<>();
     8         if (matrix == null || matrix.length == 0) {
     9             return result;
    10         }
    11         int row = matrix.length;
    12         int column = matrix[0].length;
    13         int start = 0;
    14         //start is the coordinates of the origin(左上角的坐标,(0,0)(1,1)等等)
    15         while (row > start * 2 && column > start * 2) {
    16             //an example can explain the judge condition
    17             //notice: the bound of cycle in the next code
    18             int endX = column - 1 - start;
    19             int endY = row - 1 - start;
    20             for (int i = start; i <= endX; i++) {
    21                 result.add(matrix[start][i]);
    22             }
    23             if (endY > start) {
    24                 for (int i = start + 1; i <= endY; i++) {
    25                     result.add(matrix[i][endX]);
    26                 }
    27             }
    28             if (endY > start && endX > start) {
    29                 for (int i = endX - 1; i >= start; i--) {
    30                     result.add(matrix[endY][i]);
    31                 }
    32             }
    33             if (endX > start && endY > start + 1) {
    34                 for (int i = endY - 1; i > start; i--) {
    35                     result.add(matrix[i][start]);
    36                 }
    37             }
    38             start++;
    39         }
    40         return result;
    41     }
    42 }
    View Code
     1 public class Solution {
     2     /**
     3      * @param matrix a matrix of m x n elements
     4      * @return an integer list
     5      */
     6     public List<Integer> spiralOrder(int[][] matrix) {
     7         //确定整个循环运行的条件,以及每一步运行的条件,最好是画图
     8         List<Integer> result = new ArrayList<>();
     9         if (matrix == null || matrix.length == 0) {
    10             return result;
    11         }
    12         if (matrix[0] == null || matrix[0].length == 0) {
    13             return result;
    14         }
    15         int row = matrix.length;
    16         int column = matrix[0].length;
    17         int start = 0;
    18         while (row > start * 2 && column > start * 2) {
    19             //定义终止行号和终止列号,start为起始的行号与列号
    20             int endX = column - 1 - start;
    21             int endY = row - 1 - start;
    22             for (int i = start; i <= endX; i++) {
    23                 result.add(matrix[start][i]);
    24             }
    25             if (endY > start) {
    26                 for (int i = start + 1; i <= endY; i++) {
    27                     result.add(matrix[i][endX]);
    28                 }
    29             }
    30             if (endX > start && endY > start) {
    31                 for (int i = endX - 1; i >= start; i--) {
    32                     result.add(matrix[endY][i]);
    33                 }
    34             }
    35             if (endY - start >= 2 && endX > start) {
    36                 for (int i = endY - 1; i > start; i--) {
    37                     result.add(matrix[i][start]);
    38                 }
    39             }
    40             start++;
    41         }
    42         return result;
    43     }
    44 }

    105. Copy List with Random Pointer (思路: 分三步,第一,复制所有节点到当前节点之后;第二,复制所有的随机指针;第三, 将链表分成两个链表)

     1 /**
     2  * Definition for singly-linked list with a random pointer.
     3  * class RandomListNode {
     4  *     int label;
     5  *     RandomListNode next, random;
     6  *     RandomListNode(int x) { this.label = x; }
     7  * };
     8  */
     9 public class Solution {
    10     /**
    11      * @param head: The head of linked list with a random pointer.
    12      * @return: A new head of a deep copy of the list.
    13      */
    14     public RandomListNode copyRandomList(RandomListNode head) {
    15         //Three steps:
    16         if (head == null) {
    17             return null;
    18         }
    19         copyNodes(head);
    20         copyRandom(head);
    21         return splitList(head);
    22     }
    23     public void copyNodes(RandomListNode head) {
    24         //Step 1 : copy all nodes
    25         RandomListNode cur = head;
    26         while (cur != null) {
    27             RandomListNode copy = new RandomListNode(cur.label);
    28             copy.next = cur.next;
    29             copy.random = null;
    30             //connect node and cloned node
    31             cur.next = copy;
    32             //copy next node
    33             cur = copy.next;
    34         }
    35     }
    36     public void copyRandom(RandomListNode head) {
    37         //Step 2 : copy the random pointer
    38         RandomListNode cur = head;
    39         while (cur != null) {
    40             RandomListNode copy = cur.next;
    41             if (cur.random != null) {
    42                 copy.random = cur.random;
    43             }
    44             //copy random pointer of next node
    45             cur = copy.next;
    46         }
    47     }
    48     public RandomListNode splitList(RandomListNode head) {
    49         //Step 3 : split it to two lists
    50         RandomListNode cur = head;
    51         RandomListNode copyCur = cur.next;
    52         RandomListNode copyHead = cur.next;
    53         //save new head of cloned list
    54         cur = copyCur.next;
    55         while (cur != null) {
    56             copyCur.next = cur.next;
    57             copyCur = copyCur.next;
    58             cur.next = copyCur.next;
    59             cur = cur.next;
    60         }
    61         return copyHead;
    62     }
    63 }
    View Code
     1 /**
     2  * Definition for singly-linked list with a random pointer.
     3  * class RandomListNode {
     4  *     int label;
     5  *     RandomListNode next, random;
     6  *     RandomListNode(int x) { this.label = x; }
     7  * };
     8  */
     9 public class Solution {
    10     /**
    11      * @param head: The head of linked list with a random pointer.
    12      * @return: A new head of a deep copy of the list.
    13      */
    14      //分为有顺序的三步:第一步复制所有节点,第二步复制随机指针,第三步将两个链表分开
    15      //需要注意的是:复制随机指针的时候需要判断是否为空;分开链表的时候,需要先将当前节点遍历到head的下一跳,防止head.next.next出现空指针
    16     public RandomListNode copyRandomList(RandomListNode head) {
    17         copyNodes(head);
    18         copyRandom(head);
    19         return splitList(head);
    20     }
    21     public void copyNodes(RandomListNode head) {
    22         if (head == null) {
    23             return;
    24         }
    25         while (head != null) {
    26             RandomListNode copy = new RandomListNode(head.label);
    27             RandomListNode temp = head.next;
    28             head.next = copy;
    29             copy.next = temp;
    30             head = copy.next;
    31         }
    32     }
    33     public void copyRandom(RandomListNode head) {
    34         if (head == null) {
    35             return;
    36         }
    37         while (head != null) {
    38             if (head.random != null) {
    39                 head.next.random = head.random.next;
    40             }
    41             head = head.next.next;
    42         }
    43     }
    44     public RandomListNode splitList(RandomListNode head) {
    45         if (head == null) {
    46             return null;
    47         }
    48         RandomListNode copyHead = head.next;
    49         RandomListNode copyCur = copyHead;
    50         head.next = copyCur.next;
    51         head = head.next;
    52         while (head != null) {
    53             copyCur.next = head.next;
    54             copyCur = copyCur.next;
    55             head.next = copyCur.next;
    56             head = head.next;
    57         }
    58         return copyHead;
    59     }
    60 }

    12. Min Stack (思路:建一个辅助栈保存当前的最小值,每次进行pop()操作时,需要把最小栈的peek也pop掉)

     1 public class MinStack {
     2     Stack<Integer> stack;
     3     Stack<Integer> minStack;
     4     public MinStack() {
     5         //an additional stack is needed to save current min
     6         stack = new Stack<>();
     7         minStack = new Stack<>();
     8     }
     9     public void push(int number) {
    10         stack.push(number);
    11         if (minStack.isEmpty()) {
    12             minStack.push(number);
    13         } else {
    14             minStack.push(Math.min(number, minStack.peek()));
    15         }
    16     }
    17     public int pop() {
    18         minStack.pop();
    19         return stack.pop();
    20     }
    21     public int min() {
    22         return minStack.peek();
    23     }
    24 }
    View Code

     381. Spiral Matrix II(思路: 按照Spiral Matrix打印的方式分成四步,同样第一步肯定是要进行的,后面的三步需要判断(举个例子就容易懂了),不过对于正方形的矩阵后面三步的判断条件是一样的,可以同时进行)

     1 public class Solution {
     2     /**
     3      * @param n an integer
     4      * @return a square matrix
     5      */
     6     public int[][] generateMatrix(int n) {
     7         if (n <= 0) {
     8             return new int[0][0];
     9         }
    10         int start = 0;
    11         int num = 1;
    12         int[][] result = new int[n][n];
    13         while (n > 0) {
    14             for (int i = start; i < n; i++) {
    15                 result[start][i] = num++;
    16             }
    17             if (n - start >= 2) { //the code of this line is important, it can
    18             //it can decide if we will start step 2 to step 4
    19             //it is easy to understand if you have an instance
    20                 for (int i = start + 1; i < n; i++) {
    21                     result[i][n - 1] = num++;
    22                 }
    23                 for (int i = n - 2; i >= start; i--) {
    24                     result[n - 1][i] = num++;
    25                 }
    26                 for (int i = n - 2; i > start; i--) {
    27                     result[i][start] = num++;
    28                 }
    29             }
    30             n = n - 1;
    31             start++;
    32         }
    33         return result;
    34     }
    35 }
    View Code

    5. Optimize Time and Space

    46. Majority Number (思路:用count记录次数,用number记录当前的数字,对数组进行遍历,如果跟number相同,count就加1.如果不同count减1,由于要找的数字次数大于一半,也就大于其他所有数字的次数之和,那么最后保存的数字必然就是我们所要的)

     1 public class Solution {
     2     /**
     3      * @param nums: a list of integers
     4      * @return: find a  majority number
     5      */
     6     public int majorityNumber(ArrayList<Integer> nums) {
     7         //整体思路:用count记录次数,用number记录当前的数字,对数组进行遍历,
     8         //如果跟number相同,count就加1,如果不同count减1,由于要找的数字次数
     9         //大于一半,也就大于其他所有数字的次数之和,
    10         //那么最后保存的数字必然就是我们所要的。
    11         if (nums == null || nums.size() == 0) {
    12             return 0;
    13         }
    14         int num = 0;
    15         int count = 0;
    16         for (int i = 0; i < nums.size(); i++) {
    17             if (count == 0) {
    18                 num = nums.get(i);
    19             }
    20             if (num == nums.get(i)) {
    21                 count++;
    22             } else {
    23                 count--;
    24             }
    25         }
    26         return num;
    27     }
    28 }
    View Code
     1 public class Solution {
     2     /**
     3      * @param nums: a list of integers
     4      * @return: find a  majority number
     5      */
     6     public int majorityNumber(ArrayList<Integer> nums) {
     7         //整体思路:用count记录次数,用number记录当前的数字,对数组进行遍历,
     8         //如果跟number相同,count就加1,如果不同count减1,由于要找的数字次数
     9         //大于一半,也就大于其他所有数字的次数之和,
    10         //那么最后保存的数字必然就是我们所要的。
    11         if (nums == null || nums.size() == 0) {
    12             return 0;
    13         }
    14         /**
    15          * int count = 1;
    16         int number = nums.get(0);
    17         for (int i = 1; i < nums.size(); i++) {
    18             if (nums.get(i) == number) {
    19                 count++;
    20             } else {
    21                 count--;
    22             }
    23             if (count == 0) {
    24                 number = nums.get(i);
    25                 count++;
    26             }
    27         }
    28         */
    29         int count = 0;
    30         int number = 0;
    31         for (int i = 0; i < nums.size(); i++) {
    32             if (count == 0) {
    33                 number = nums.get(i);
    34                 //count++;
    35             }
    36             if (number == nums.get(i)) {
    37                 count++;
    38             } else {
    39                 count--;
    40             }
    41         }
    42         return number;
    43     }
    44 }
    View Code
     1 public class Solution {
     2     /**
     3      * @param nums: a list of integers
     4      * @return: find a  majority number
     5      */
     6     public int majorityNumber(ArrayList<Integer> nums) {
     7         //整体思路:用count记录次数,用number记录当前的数字,对数组进行遍历,
     8         //如果跟number相同,count就加1,如果不同count减1,由于要找的数字次数
     9         //大于一半,也就大于其他所有数字的次数之和,
    10         //那么最后保存的数字必然就是我们所要的。
    11         /**if (nums == null || nums.size() == 0) {
    12             return -1;
    13         }
    14         int number = nums.get(0);
    15         int count = 1;
    16         for (int i = 1; i < nums.size(); i++) {
    17             if (nums.get(i) == number) {
    18                 count++;
    19             } else {
    20                 count--;
    21                 if (count < 0) {
    22                     count = 1;
    23                     number = nums.get(i);
    24                 }
    25             }
    26         }
    27         return number;
    28     }*/
    29         if (nums == null || nums.size() == 0) {
    30             return -1;
    31         }
    32         int number = 0;
    33         int count = 0;
    34         for (int i = 0; i < nums.size(); i++) {
    35             if (count == 0) {
    36                 number = nums.get(i);
    37             }
    38             if (number == nums.get(i)) {
    39                 count++;
    40             } else {
    41                 count--;
    42             }
    43         }
    44         return number;
    45     }
    46 }

    47. Majority Number II (思路: 同上,不过需要两个num和count,最后需要选择较大的count对应的num,注意判断条件的顺序)

     1 public class Solution {
     2     /**
     3      * @param nums: A list of integers
     4      * @return: The majority number that occurs more than 1/3
     5      */
     6     public int majorityNumber(ArrayList<Integer> nums) {
     7         if (nums == null || nums.size() == 0) {
     8             return 0;
     9         }
    10         int num1 = 0;
    11         int num2 = 0;
    12         int count1 = 0;
    13         int count2 = 0;
    14         for (int i = 0; i < nums.size(); i++) {
    15             /**
    16             if (count1 == 0) {
    17                 num1 = nums.get(i);
    18                 count1++;
    19             } else if (count2 == 0) {
    20                 num2 = nums.get(i);
    21                 count2++;
    22             } else if (nums.get(i) == num1) {
    23                 count1++;
    24             } else if (nums.get(i) == num2) {
    25                 count2++;
    26             } else {
    27                 count1--;
    28                 count2--;
    29             }
    30             */
    31             //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    32             //the above code is wrong, test data [1 1 1 1 2 2 3 3 4 4 4] is not accepted
    33             //so the order of 'if' is very important
    34             if (nums.get(i) == num1) {
    35                 count1++;
    36             } else if (nums.get(i) == num2) {
    37                 count2++;
    38             } else if (count1 == 0) {
    39                 num1 = nums.get(i);
    40                 count1++;
    41             } else if (count2 == 0) {
    42                 num2 = nums.get(i);
    43                 count2++;
    44             } else {
    45                 count1--;
    46                 count2--;
    47             }
    48         }
    49         count1 = 0;
    50         count2 = 0;
    51         for (int i = 0; i < nums.size(); i++) {
    52             if (nums.get(i) == num1) {
    53                 count1++;
    54             } else if (nums.get(i) == num2) {
    55                 count2++;
    56             }
    57         }
    58         return count1 > count2 ? num1 : num2;
    59     }
    60 }
    View Code

    41. Maximum Subarray (思路:定义两个变量,当前累加和和最大累加和,如果当前累加和是负的,那么从下一个数字开始继续累加,同时更新最大累加和)

     1 public class Solution {
     2     /**
     3      * @param nums: A list of integers
     4      * @return: A integer indicate the sum of max subarray
     5      */
     6     public int maxSubArray(int[] nums) {
     7         if (nums == null || nums.length == 0) {
     8             return 0;
     9         }
    10         int maxSum = nums[0];
    11         int curSum = 0;
    12         for (int i = 0; i < nums.length; i++) {
    13             //if the current sum < 0, then get the sum from next number
    14             if (curSum < 0) {
    15                 curSum = nums[i];
    16             } else {
    17                 curSum += nums[i];
    18             }
    19             if (curSum > maxSum) {
    20                 maxSum = curSum;
    21             }
    22         }
    23         return maxSum;
    24     }
    25 }
    View Code

     379.Reorder array to construct the minimum number(重新定义一种排序规则)

     1 public class Solution {
     2     /**
     3      * @param nums n non-negative integer array
     4      * @return a string
     5      */
     6     public String minNumber(int[] nums) {
     7         //边界判断
     8         if (nums == null || nums.length == 0) {
     9             return "";
    10         }
    11         //将整数数组转成字符串数组并从小到大排序(按自定义的排序规则)
    12         int numsLen = nums.length;
    13         String[] str = new String[numsLen];
    14         for (int i = 0; i < numsLen; i++) {
    15             str[i] = nums[i]+ "";
    16         }
    17         Arrays.sort(str, new CompareString());
    18         //将排序好的字符串数组连接起来
    19         String result = "";
    20         for (int i = 0; i < numsLen; i++) {
    21             result = result.concat(str[i]);
    22         }
    23         //因为返回的是整数,需要将前面为0的舍去
    24         int i = 0;
    25         while (i < numsLen && result.charAt(i) == '0') {
    26             i++;
    27         }
    28         if (i == numsLen) {
    29             return "0";
    30         }
    31         return result;//.substring(i);
    32     }
    33     //重新定义一个类来实现Comparator接口,按照升序排序
    34     class CompareString implements Comparator<String> {
    35         public int compare(String a, String b) {
    36             String ab = a.concat(b);
    37             String ba = b.concat(a);
    38             return ab.compareTo(ba);
    39         }
    40     }
    41 }
    View Code

     第二种更严谨

     1 public class Solution {
     2     /**
     3      * @param nums n non-negative integer array
     4      * @return a string
     5      */
     6     public String minNumber(int[] nums) {
     7         if (nums == null || nums.length == 0) {
     8             return null;
     9         }
    10         String[] str = new String[nums.length];
    11         for (int i = 0; i < nums.length; i++) {
    12             str[i] = nums[i] + "";
    13         }
    14         Arrays.sort(str, new CompareString());
    15         String result = "";
    16         for (int i = 0; i < nums.length; i++) {
    17             result = result.concat(str[i]);
    18         }
    19         int i = 0;
    20         while (i < result.length() && result.charAt(i) == '0') {
    21             i++;
    22         }
    23         if (i == result.length()) {
    24             return "0";
    25         }
    26         return result.substring(i);
    27     }
    28     class CompareString implements Comparator<String> {
    29         public int compare(String a, String b) {
    30             String ab = a.concat(b);
    31             String ba = b.concat(a);
    32             return ab.compareTo(ba);
    33         }
    34     }
    35 }
    View Code
     1 public class Solution {
     2     /**
     3      * @param nums n non-negative integer array
     4      * @return a string
     5      */
     6     /**public String minNumber(int[] nums) {
     7         String result = "";
     8         if (nums == null || nums.length == 0) {
     9             return result;
    10         }
    11         //为防止数字溢出的情况,需要先将数字变为字符串
    12         String[] str = new String[nums.length];
    13         for (int i = 0; i < nums.length; i++) {
    14             str[i] = nums[i] + "";
    15         }
    16         //按照指定排序规则进行排序
    17         Arrays.sort(str, new CompareString());
    18         for (int i = 0; i < str.length; i++) {
    19             result += str[i];
    20         }
    21         //将前面为0的去掉
    22         int i = 0;
    23         while (i < result.length() && result.charAt(i) == '0') {
    24             i++;
    25         }
    26         if (i == result.length()) {
    27             return "0";
    28         }
    29         return result.substring(i);
    30     }
    31     class CompareString implements Comparator<String> {
    32         public int compare(String a, String b) {
    33             String ab = a.concat(b);
    34             String ba = b.concat(a);
    35             return ab.compareTo(ba);
    36         }
    37     }*/
    38     //匿名内部类
    39     public String minNumber(int[] nums) {
    40         String result = "";
    41         if (nums == null || nums.length == 0) {
    42             return result;
    43         }
    44         String[] str = new String[nums.length];
    45         for (int i = 0; i < nums.length;  i++) {
    46             str[i] = nums[i] + "";
    47         }
    48         Arrays.sort(str, new Comparator<String>() {
    49            public int compare(String a, String b) {
    50                String ab = a.concat(b);
    51                String ba = b.concat(a);
    52                return ab.compareTo(ba);
    53            } 
    54         });
    55         for (int i = 0; i < str.length; i++) {
    56             result += str[i];
    57         }
    58         int i = 0;
    59         while (i < result.length() && result.charAt(i) == '0') {
    60             i++;
    61         }
    62         if (i == result.length()) {
    63             return "0";
    64         }
    65         return result.substring(i);
    66     }
    67 }

    532. Reverse Pairs

     1 public class Solution {
     2     /**
     3      * @param A an array
     4      * @return total of reverse pairs
     5      */
     6     long count = 0;
     7     public long reversePairs(int[] a) {
     8         if (a == null || a.length == 0) {
     9             return 0;
    10         }
    11         int[] temp = new int[a.length]; 
    12         divide(a, 0, a.length - 1, temp);
    13         return count;
    14     }
    15     public void divide(int[] a, int start, int end, int[] temp) {
    16         if (start >= end) {
    17             return;
    18         }
    19         int mid = start + (end - start) / 2;
    20         divide(a, start, mid, temp);
    21         divide(a, mid + 1, end, temp);
    22         mergeSort(a, start, end, temp);
    23     }
    24     public void mergeSort(int[] a, int start, int end, int[] temp) {
    25         if (start >= end) {
    26             return;
    27         }
    28         int mid = start + (end - start) / 2;
    29         int left = start;
    30         int right = mid + 1;
    31         for (left = start; left <= mid; left++) {
    32             while (right <= end && a[left] > a[right]) {
    33                 right++;
    34             }
    35             count += right - (mid + 1);
    36         }
    37         int leftIndex = start;
    38         int rightIndex = mid + 1;
    39         int tempIndex = start;
    40         while (leftIndex <= mid && rightIndex <= end) {
    41             if (a[leftIndex] < a[rightIndex]) {
    42                 temp[tempIndex++] = a[leftIndex++];
    43             } else {
    44                 temp[tempIndex++] = a[rightIndex++];
    45             }
    46         }
    47         while (leftIndex <= mid) {
    48             temp[tempIndex++] = a[leftIndex++];
    49         }
    50         while (rightIndex <= end) {
    51             temp[tempIndex++] = a[rightIndex++];
    52         }
    53         //复制temp到a的时候注意是start和end
    54         for (int i = start; i <= end; i++) {
    55             a[i] = temp[i];
    56         }
    57     }    
    58 } 
    View Code

    381.Spiral Matrix II

     1 public class Solution {
     2     /**
     3      * @param n an integer
     4      * @return a square matrix
     5      */
     6     public int[][] generateMatrix(int n) {
     7         int[][] result = new int[n][n];
     8         if (n <= 0) {
     9             return result;
    10         }
    11         int start = 0;
    12         int number = 1;
    13         while (n > 2 * start) {
    14             int end = n - start - 1;
    15             for (int i = start; i <= end; i++) {
    16                 result[start][i] = number++; 
    17             }
    18             if (end > start) {
    19                 for (int i = start + 1; i < end; i++) {
    20                     result[i][end] = number++;
    21                 }
    22                 for (int i = end; i > start; i--) {
    23                     result[end][i] = number++;
    24                 }
    25                 for (int i = end; i > start; i--) {
    26                     result[i][start] = number++;
    27                 }
    28             }
    29             start++;
    30         }
    31         return result;
    32     }
    33 }
    View Code

    380. Intersection of Two Linked Lists

     1 /**
     2  * Definition for singly-linked list.
     3  * public class ListNode {
     4  *     int val;
     5  *     ListNode next;
     6  *     ListNode(int x) {
     7  *         val = x;
     8  *         next = null;
     9  *     }
    10  * }
    11  */
    12 public class Solution {
    13     /**
    14      * @param headA: the first list
    15      * @param headB: the second list
    16      * @return: a ListNode
    17      */
    18     public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    19         //整体思路:首先获得两个链表的长度,然后将长的链表遍历到跟短的一样,然后两个链表同时遍历,找到共同的节点
    20         if (headA == null || headB == null) {
    21             return null;
    22         }
    23         int aLen = getListLength(headA);
    24         int bLen = getListLength(headB);
    25         if (aLen < bLen) {
    26             for (int i = aLen; i < bLen; i++) {
    27                 headB = headB.next;
    28             }
    29         } else {
    30             for (int i = bLen; i < aLen; i++) {
    31                 headA = headA.next;
    32             }
    33         }
    34         ListNode common = null;
    35         while (headA != null) {
    36             if (headA == headB) {
    37                 common = headA;
    38                 return common;
    39             }
    40             headA = headA.next;
    41             headB = headB.next;
    42         }
    43         return common;
    44     }    
    45     public int getListLength(ListNode head) {
    46         if (head == null) {
    47             return 0;
    48         }
    49         int len = 0;
    50         while (head != null) {
    51             head = head.next;
    52             len++;
    53         }
    54         return len;
    55     }
    56 }
    View Code

     3.Digit Counts(第一种:暴力解法,直接遍历,数每个数字中k的个数)

    第二种:
    当某一位的数字小于i时,那么该位出现i的次数为:更高位数字x当前位数 当某一位的数字等于i时,那么该位出现i的次数为:更高位数字x当前位数+低位数字+1 当某一位的数字大于i时,那么该位出现i的次数为:(更高位数字+1)x当前位数


    假设一个5位数N=abcde,我们现在来考虑百位上出现2的次数,即,从0到abcde的数中, 有多少个数的百位上是2。分析完它,就可以用同样的方法去计算个位,十位,千位, 万位等各个位上出现2的次数。

    当百位c为0时,比如说12013,0到12013中哪些数的百位会出现2?我们从小的数起, 200~299, 1200~1299, 2200~2299, … , 11200~11299, 也就是固定低3位为200~299,然后高位依次从0到11,共12个。再往下12200~12299 已经大于12013,因此不再往下。所以,当百位为0时,百位出现2的次数只由更高位决定, 等于更高位数字(12)x当前位数(100)=1200个。

    当百位c为1时,比如说12113。分析同上,并且和上面的情况一模一样。 最大也只能到11200~11299,所以百位出现2的次数也是1200个。

    上面两步综合起来,可以得到以下结论:

    当某一位的数字小于2时,那么该位出现2的次数为:更高位数字x当前位数
    

    当百位c为2时,比如说12213。那么,我们还是有200~299, 1200~1299, 2200~2299, … , 11200~11299这1200个数,他们的百位为2。但同时,还有一部分12200~12213, 共14个(低位数字+1)。所以,当百位数字为2时, 百位出现2的次数既受高位影响也受低位影响,结论如下:

    当某一位的数字等于2时,那么该位出现2的次数为:更高位数字x当前位数+低位数字+1
    

    当百位c大于2时,比如说12313,那么固定低3位为200~299,高位依次可以从0到12, 这一次就把12200~12299也包含了,同时也没低位什么事情。因此出现2的次数是: (更高位数字+1)x当前位数。结论如下:

    当某一位的数字大于2时,那么该位出现2的次数为:(更高位数字+1)x当前位数
     1 class Solution {
     2     /*
     3      * param k : As description.
     4      * param n : As description.
     5      * return: An integer denote the count of digit k in 1..n
     6      */
     7     // public int digitCounts(int k, int n) {
     8     //     if (k < 0 || k > 9 || n < 0) {
     9     //         return 0;
    10     //     }
    11     //     int count = 0;
    12     //     for (int i = k; i <= n; i++) {
    13     //         count += countK(k, i);
    14     //     }
    15     //     return count;
    16     // }
    17     // public int countK(int k, int num) {
    18     //     int count = 0;
    19     //     if (k < 0 || num < 0) {
    20     //         return 0;
    21     //     }
    22     //     if (k == 0 && num == 0) {
    23     //         return 1;
    24     //     }
    25     //     while (num > 0) {
    26     //         if (num % 10 == k) {
    27     //             count++;
    28     //         }
    29     //         num = num / 10;
    30     //     }
    31     //     return count;
    32     // }
    33     public int digitCounts(int k, int n) {
    34         if (k < 0 || k > 9 || n < 0) {
    35             return 0;
    36         }
    37         if (k == 0) {
    38             return count0(n);
    39         }
    40         return countOther(k, n);
    41     }
    42     public int count0(int num) {
    43         if (num < 0) {
    44             return 0;
    45         }
    46         int count = 0;
    47         for (int i = 0; i <= num; i++) {
    48             count += count0Helper(i);
    49         }
    50         return count;
    51     }
    52     public int count0Helper(int num) {
    53         if (num < 0) {
    54             return 0;
    55         }
    56         int count = 0;
    57         if (num == 0) {
    58             return 1;
    59         }
    60         while (num > 0) {
    61             if (num % 10 == 0) {
    62                 count++;
    63             }
    64             num = num / 10;
    65         }
    66         return count;
    67     }
    68     public int countOther(int k, int num) {
    69         int count = 0;
    70         int low = 0;
    71         int high = 0;
    72         int cur = 0;
    73         int factor = 1;
    74         while (num / factor > 0) {
    75             low = num - (num / factor) * factor;
    76             high = num / (factor * 10);
    77             cur = (num / factor) % 10;
    78             if (cur < k) {
    79                 count += high * factor;
    80             } else if (cur == k) {
    81                 count += high * factor + low + 1;
    82             } else {
    83                 count += (high + 1) * factor;
    84             }
    85             factor = factor * 10;
    86         }
    87         return count;
    88     }
    89 }
    View Code

    5.Kth Largest Element(思路:从大到小快速排序的过程中找第K大的元素)

     1 class Solution {
     2     /*
     3      * @param k : description of k
     4      * @param nums : array of nums
     5      * @return: description of return
     6      */
     7     public int kthLargestElement(int k, int[] nums) {
     8         //思路:进行从大到小快速排序的时候计算找第K大的元素
     9         if (nums == null || nums.length == 0 || k < 1) {
    10             return 0;
    11         }
    12         return quickSelect(nums, 0, nums.length - 1, k);
    13     }
    14     public int quickSelect(int[] nums, int start, int end, int k) {
    15         if (start > end) {
    16             return 0;
    17         }
    18         int left = start;
    19         int right = end;
    20         int mid = start + (end - start) / 2;
    21         int pivot = nums[mid];
    22         while (left <=  right) {
    23             //必须是<= 因为必须出现后面所需要的两种排序后情况
    24             while (left <= right && nums[left] > pivot) {
    25                 left++;
    26             }
    27             while (left <= right && nums[right] < pivot) {
    28                 right--;
    29             }
    30             if (left <= right) {
    31                 int temp = nums[left];
    32                 nums[left] = nums[right];
    33                 nums[right] = temp;
    34                 left++;
    35                 right--;
    36             }
    37         }
    38         //快速排序后只有两种情况:start-right-pivot-left-end 和 start-right-left-end,然后判断分别判断k在前面和后面的情况(举例说明)
    39         if (k <= right - start + 1) {
    40             return quickSelect(nums, start, right, k);
    41         } else if (k > left - start) {
    42             return quickSelect(nums, left, end, k - (left - start));
    43         } else {
    44              return nums[right + 1];
    45         }
    46     }
    47 }
    View Code

     4.Ugly Number II(丑数必然是前面的丑数乘以2,3,5的结果,那么下一个丑数必然是之前的丑数)

     1 class Solution {
     2     /**
     3      * @param n an integer
     4      * @return the nth prime number as description.
     5      */
     6     public int nthUglyNumber(int n) {
     7         //思路:丑数必然是前面的丑数乘以2,3,5的结果,那么下一个丑数必然是之前的丑数
     8         //乘以2,3,5中的最小数
     9         if (n <= 0) {
    10             return 0;
    11         }
    12         ArrayList<Integer> result = new ArrayList<>();
    13         result.add(1);
    14         int p2 = 0;
    15         int p3 = 0;
    16         int p5 = 0;
    17         for (int i = 1; i <= n; i++) {
    18             int lastUglyNum = result.get(i - 1);
    19             //找到第一个分别乘以2,3,5之后大于当前丑数的位置
    20             while (result.get(p2) * 2 <= lastUglyNum) {
    21                 p2++;
    22             }
    23             while (result.get(p3) * 3 <= lastUglyNum) {
    24                 p3++;
    25             }
    26             while (result.get(p5) * 5 <= lastUglyNum) {
    27                 p5++;
    28             }
    29             result.add(Math.min(result.get(p2) * 2, Math.min(result.get(p3) * 3, result.get(p5) * 5)));
    30         }
    31         return result.get(n - 1);
    32     }
    33 }
    View Code

    6. Skills in Interview

    97. Maximum Depth of Binary Tree(左子树和右子树中较大的深度加上根节点的深度)

     1 /**
     2  * Definition of TreeNode:
     3  * public class TreeNode {
     4  *     public int val;
     5  *     public TreeNode left, right;
     6  *     public TreeNode(int val) {
     7  *         this.val = val;
     8  *         this.left = this.right = null;
     9  *     }
    10  * }
    11  */
    12 public class Solution {
    13     /**
    14      * @param root: The root of binary tree.
    15      * @return: An integer.
    16      */
    17     public int maxDepth(TreeNode root) {
    18         if (root == null) {
    19             return 0;
    20         }
    21         //加的1为根节点
    22         //简单理解为:左子树和右子树中较大的深度加上根节点的深度
    23         return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
    24     }
    25 }
    View Code

    82.Single Number(由于异或是不同为1,相同为0,那么数组中所有的数字依次异或)

     1 public class Solution {
     2     /**
     3       *@param A : an integer array
     4       *return : a integer
     5       */
     6     public int singleNumber(int[] a) {
     7         //由于异或是不同为1,相同为0,那么数组中所有的数字依次异或,相同的异或为
     8         //0,0与目标数字异或还未目标数字,任何数字与0异或不变.
     9         if (a == null || a.length == 0) {
    10             return 0;
    11         }
    12         int num = a[0];
    13         for (int i = 1; i < a.length; i++) {
    14             num = num ^ a[i];
    15         }
    16         return num;
    17     }
    18 }
    View Code

    56.Two Sum(思路: 由于map存入相同的元素会覆盖,因此需要新建一个类来保存索引和值)

     1 class Node {
     2     int val;
     3     int key;
     4     public Node(int key, int val) {
     5         this.key = key;
     6         this.val = val;
     7     }
     8 } 
     9 public class Solution {
    10     /*
    11      * @param numbers : An array of Integer
    12      * @param target : target = numbers[index1] + numbers[index2]
    13      * @return : [index1 + 1, index2 + 1] (index1 < index2)
    14      */
    15     public int[] twoSum(int[] numbers, int target) {
    16         if (numbers == null || numbers.length == 0) {
    17             return new int[2];
    18         }
    19         ArrayList<Node> nodes = new ArrayList<>();
    20         for (int i = 0; i < numbers.length; i++) {
    21             nodes.add(new Node(i, numbers[i]));
    22         }
    23         Collections.sort(nodes, new Comparator<Node>() {
    24             public int compare(Node a, Node b) {
    25                 return a.val - b.val;
    26             }
    27         });
    28         int left = 0;
    29         int right = numbers.length - 1;
    30         int[] result = new int[2];
    31         while (left < right) {
    32             if (nodes.get(left).val + nodes.get(right).val == target) {
    33                 if (nodes.get(left).key < nodes.get(right).key) {
    34                     result[0] = nodes.get(left).key;
    35                     result[1] = nodes.get(right).key;
    36                     return result;
    37                 } else {
    38                     result[0] = nodes.get(right).key;
    39                     result[1] = nodes.get(left).key;
    40                     return result;
    41                 }
    42             } else if (nodes.get(left).val + nodes.get(right).val < target) {
    43                 left++;
    44             } else {
    45                 right--;
    46             }
    47         }
    48         return new int[2];
    49     }
    50 }
    View Code
     1 public class Solution {
     2     /*
     3      * @param numbers : An array of Integer
     4      * @param target : target = numbers[index1] + numbers[index2]
     5      * @return : [index1 + 1, index2 + 1] (index1 < index2)
     6      */
     7     public int[] twoSum(int[] numbers, int target) {
     8         if (numbers == null || numbers.length < 2) {
     9             return new int[2];
    10         }
    11         //将所有数字和它的索引加入加入集合中
    12         ArrayList<Node> nodes = new ArrayList<>();
    13         for (int i = 0; i < numbers.length; i++) {
    14             nodes.add(new Node(i, numbers[i]));
    15         }
    16         //根据值从小到大对集合进行排序
    17         Collections.sort(nodes, new Comparator<Node>(){
    18             public int compare(Node a, Node b) {
    19                 return a.val - b.val;
    20             }
    21         });
    22         //利用双指针进行寻找
    23         int[] result = new int[2];
    24         int left = 0;
    25         int right = nodes.size() - 1;
    26         while (left < right) {
    27             if (nodes.get(left).val + nodes.get(right).val == target) {
    28                 if (nodes.get(left).key < nodes.get(right).key) {
    29                     result[0] = nodes.get(left).key;
    30                     result[1] = nodes.get(right).key;
    31                 } else {
    32                     result[1] = nodes.get(left).key;
    33                     result[0] = nodes.get(right).key;
    34                 }
    35                 return result;
    36             } else if (nodes.get(left).val + nodes.get(right).val < target) {
    37                 left++;
    38             } else {
    39                 right--;
    40             }
    41         }
    42         return result;
    43     }
    44 }
    45 //建立一个新的类节点用于保存索引和值,不能用hashmap,因为hashmap只能通过键获得值,如果将值作为键,索引作为值的话,由于可能存在相同的值,hashmap将会被覆盖
    46 class Node{
    47     int val;
    48     int key;
    49     public Node(int key, int val) {
    50         this.key = key;
    51         this.val = val;
    52     }
    53 }

    53.Reverse Words in a String(用空格将字符串分开,如果中间或者前面或者后面有很多空格的话,那么数组中这个元素就为空)

     1 public class Solution {
     2     /**
     3      * @param s : A string
     4      * @return : A string
     5      */
     6     public String reverseWords(String s) {
     7         // null 表示没有传string对象, s.length() == 0 表示传了,但是什么也没有、
     8         // return "" 表示返回一个空的字符串 return " "表示传了一个空格
     9         if (s == null || s.length() == 0) {
    10             return "";
    11         }
    12         //用空格将字符串分开,如果中间或者前面或者后面有很多空格的话,那么数组中这个元素就为空
    13         //利用stringbuffer的append方法
    14         String[] wordArr = s.split(" ");
    15         StringBuffer sb = new StringBuffer();
    16         for (int i = wordArr.length - 1; i >= 0; i--) {
    17             if (wordArr[i] != " ") {
    18                 sb.append(wordArr[i]).append(" ");
    19             }
    20         }
    21         return sb.length() == 0 ? "" : sb.substring(0, sb.length() - 1);
    22     }
    23 }
    View Code
     1 public class Solution {
     2     /**
     3      * @param s : A string
     4      * @return : A string
     5      */
     6     public String reverseWords(String s) {
     7         //不用去管前导空格、尾随空格、中间空格,只需要将字符串用空格分开,然后只对字符串数组中的非空格字符串进行处理,每个后面加个空格
     8         if (s == null || s.length() == 0) {
     9             return "";
    10         }
    11         int count = 0;
    12         String[] str = s.split(" ");
    13         StringBuffer sb = new StringBuffer();
    14         for (int i = str.length - 1; i >= 0; i--) {
    15             if (str[i] != " ") {
    16                 sb.append(str[i]).append(" ");
    17                 count++;
    18             }
    19         }
    20         return count == 0 ? "" : sb.substring(0, sb.length() - 1);
    21     }
    22 }

    8.Rotate String (思路:举个简单的例子,从后面反转n个,相当于len-n、n分别反转之后再整体反转)

     1 public class Solution {
     2     /**
     3      * @param str: an array of char
     4      * @param offset: an integer
     5      * @return: nothing
     6      */
     7     public void rotateString(char[] str, int offset) {
     8         if (str == null || str.length == 0) {
     9             return;
    10         }
    11         int len = str.length;
    12         int off = offset % len;
    13         int firstEnd = len - off - 1;
    14         int secondStart = firstEnd + 1;
    15         reverse(str, 0, firstEnd);
    16         reverse(str, secondStart, str.length - 1);
    17         reverse(str, 0, str.length - 1);
    18     }
    19     //举个简单的例子,从后面反转n个,相当于len-n、n分别反转之后再整体反转
    20     public void reverse(char[] str, int start, int end) {
    21         if (str == null || str.length == 0) {
    22             return;
    23         }
    24         while (start < end) {
    25             char temp = str[start];
    26             str[start] = str[end];
    27             str[end] = temp;
    28             start++;
    29             end--;
    30         }
    31     }
    32 }
    View Code
     1 public class Solution {
     2     /**
     3      * @param str: an array of char
     4      * @param offset: an integer
     5      * @return: nothing
     6      */
     7     public void rotateString(char[] str, int offset) {
     8         if (str == null || str.length == 0) {
     9             return;
    10         }
    11         offset = offset % str.length;
    12         int len = str.length - 1;
    13         reverse(str, 0, len - offset);
    14         reverse(str, len - offset + 1, len);
    15         reverse(str, 0, len);
    16     }
    17     //举个简单的例子,从后面反转n个,相当于(0, len - n) (len - n + 1, n)分别反转之后再整体反转
    18     public void reverse(char[] str, int start, int end) {
    19         int left = start;
    20         int right = end;
    21         while (left < right) {
    22             char temp = str[left];
    23             str[left] = str[right];
    24             str[right] = temp;
    25             left++;
    26             right--;
    27         }
    28     }
    29 }

    1. A + B Problem (思路:所以:a + b = (a ^ b) + (a & b << 1))

     1 class Solution {
     2     /*
     3      * param a: The first integer
     4      * param b: The second integer
     5      * return: The sum of a and b
     6      */
     7     public int aplusb(int a, int b) {
     8         // 主要利用异或运算来完成 
     9         // 异或运算有一个别名叫做:不进位加法
    10         // 那么a ^ b就是a和b相加之后,该进位的地方不进位的结果
    11         // 然后下面考虑哪些地方要进位,自然是a和b里都是1的地方
    12         // a & b就是a和b里都是1的那些位置,a & b << 1 就是进位
    13         // 之后的结果。所以:a + b = (a ^ b) + (a & b << 1)
    14         // 令a' = a ^ b, b' = (a & b) << 1
    15         // 可以知道,这个过程是在模拟加法的运算过程,进位不可能
    16         // 一直持续,所以b最终会变为0。因此重复做上述操作就可以
    17         // 求得a + b的值。
    18         while (b != 0) {
    19             int newA = a ^ b;
    20             int newB = (a & b) << 1;
    21             a = newA;
    22             b = newB;
    23         }
    24         return a;
    25     }
    26 };
    View Code

    61.Search for a Range (思路:二分法查找出第一个和最后一个target)

     1 public class Solution {
     2     /**
     3      *@param A : an integer sorted array
     4      *@param target :  an integer to be inserted
     5      *return : a list of length 2, [index1, index2]
     6      */
     7     public int[] searchRange(int[] a, int target) {
     8         //直接用双指针做
     9         int[] result = new int[]{-1, -1};
    10         if (a == null || a.length == 0) {
    11             return result;
    12         }
    13         int left = 0;
    14         int right = a.length - 1;
    15         while (left <= right) {
    16             while (left < a.length - 1 && a[left] != target) {
    17                 left++;
    18             }
    19             while (right >= 0 && a[right] != target) {
    20                 right--;
    21             }
    22             if (left <= right) {
    23                 result[0] = left;
    24                 result[1] = right;
    25                 return result;
    26             }
    27         }
    28         return result;
    29     }
    30 }
     1 public class Solution {
     2     /**
     3      *@param A : an integer sorted array
     4      *@param target :  an integer to be inserted
     5      *return : a list of length 2, [index1, index2]
     6      */
     7     public int[] searchRange(int[] a, int target) {
     8         if (a == null || a.length == 0) {
     9             return new int[]{-1, -1};
    10         }
    11         int[] result = new int[2];
    12         result[0] = getFirstTarget(a, target, 0, a.length - 1);
    13         result[1] = getLastTarget(a, target, 0, a.length - 1);
    14         return result;
    15     }
    16     public int getFirstTarget(int[] a, int target, int start, int end) {
    17         if (a == null || a.length == 0 || start > end) {
    18             return -1;
    19         }
    20         while (start <= end) {
    21             int mid = start + (end - start) / 2;
    22             if (a[mid] == target) {
    23                 //判断是否为第一个的条件
    24                 if (mid == 0 || mid > 0 && a[mid - 1] != target) {
    25                     return mid;
    26                 } else {
    27                     end = mid - 1;
    28                 }
    29             } else if (a[mid] > target) {
    30                 end = mid - 1;
    31             } else {
    32                 start = mid + 1;
    33             }
    34         }
    35         return -1;
    36     }
    37     public int getLastTarget(int[] a, int target, int start, int end) {
    38         if (a == null || a.length == 0 || start > end) {
    39             return -1;
    40         }
    41         while (start <= end) {
    42             int mid = start + (end - start) / 2;
    43             if (a[mid] == target) {
    44                 //判断是否为最后一个的条件
    45                 if (mid == a.length - 1 || mid < a.length - 1 && a[mid + 1] != target) {
    46                     return mid;
    47                 } else {
    48                     start = mid + 1;
    49                 }
    50             } else if (a[mid] > target) {
    51                 end = mid - 1;
    52             } else {
    53                 start = mid + 1;
    54             }
    55         }
    56         return -1;
    57     }
    58 }
    View Code

    7. Two Interview Cases

    88. Lowest Common Ancestor(递归,出口为左子树或者右子树中存在任意一个节点则返回)

     1 /**
     2  * Definition of TreeNode:
     3  * public class TreeNode {
     4  *     public int val;
     5  *     public TreeNode left, right;
     6  *     public TreeNode(int val) {
     7  *         this.val = val;
     8  *         this.left = this.right = null;
     9  *     }
    10  * }
    11  */
    12 public class Solution {
    13     /**
    14      * @param root: The root of the binary search tree.
    15      * @param A and B: two nodes in a Binary.
    16      * @return: Return the least common ancestor(LCA) of the two nodes.
    17      */
    18     public TreeNode lowestCommonAncestor(TreeNode root, TreeNode node1, TreeNode node2) {
    19         //找到其中一个点则返回
    20         if (root == null || root == node1 || root == node2) {
    21             return root;
    22         }
    23         TreeNode left = lowestCommonAncestor(root.left, node1, node2);
    24         TreeNode right = lowestCommonAncestor(root.right, node1, node2);
    25         if (left != null && right != null) {
    26             //在左子树中找到了其中一个节点,在右子树中找到了另一个节点
    27             return root;
    28         }
    29         if (left != null) {
    30             return left;
    31         }
    32         if (right != null) {
    33             return right;
    34         }
    35         return null;
    36     }
    37 }
    View Code

    54.String to Integer II (注意各种输入的情况:空格、符号,以及数字是否溢出)

     1 public class Solution {
     2     /**
     3      * @param str: A string
     4      * @return An integer
     5      */
     6     public int atoi(String str) {
     7         if (str == null || str.length() == 0) {
     8             return 0;
     9         }
    10         int index = 0;
    11         int sum = 0;
    12         //sign必须为1,因为如果没有符号的话便是正的
    13         int sign = 1;
    14         //除去数字之前的空格
    15         while (index < str.length() && str.charAt(index) == ' ') {
    16             index++;
    17         }
    18         //确定数字的符号,若输入多个符号则输入有误
    19         if (index < str.length() && (str.charAt(index) == '+' || str.charAt(index) == '-')) {
    20             sign = str.charAt(index) == '+' ? 1 : -1;
    21             index++;
    22         }
    23         //判断数字是否溢出
    24         while (index < str.length() && str.charAt(index) >= '0' && str.charAt(index) <= '9' && str.charAt(index) != '.') {
    25             int num = str.charAt(index) - '0';
    26             if (sum > Integer.MAX_VALUE / 10 || (sum == Integer.MAX_VALUE / 10 && num > Integer.MAX_VALUE % 10)) {
    27                 return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
    28             }
    29             sum = sum * 10 + num;
    30             index++;
    31         }
    32         return sum * sign;
    33     }
    34 }
    View Code

    8. English Version Only

    112. Remove Duplicates from Sorted List(思路:从重复节点的第一个节点开始处理,使得他的下一节点跳过与它值相同的节点)

     1 /**
     2  * Definition for ListNode
     3  * public class ListNode {
     4  *     int val;
     5  *     ListNode next;
     6  *     ListNode(int x) {
     7  *         val = x;
     8  *         next = null;
     9  *     }
    10  * }
    11  */
    12 public class Solution {
    13     /**
    14      * @param ListNode head is the head of the linked list
    15      * @return: ListNode head of linked list
    16      */
    17     public static ListNode deleteDuplicates(ListNode head) {
    18         if (head == null) {
    19             return head;
    20         }
    21         //remove duplicates but appear once, so we should process the first node
    22         //of duplicates
    23         ListNode cur = head;
    24         while (cur.next != null) {
    25             if (cur.val == cur.next.val) {
    26                 cur.next = cur.next.next;
    27             } else {
    28                 cur = cur.next;
    29             }
    30         }
    31         return head;
    32     }
    33 }
    View Code

    113. Remove Duplicates from Sorted List II (思路:从重复节点的第一个节点的前一个节点开始处理,使得他的下一节点跳过与重复节点值相同的节点)

     1 /**
     2  * Definition for ListNode
     3  * public class ListNode {
     4  *     int val;
     5  *     ListNode next;
     6  *     ListNode(int x) {
     7  *         val = x;
     8  *         next = null;
     9  *     }
    10  * }
    11  */
    12 public class Solution {
    13     /**
    14      * @param ListNode head is the head of the linked list
    15      * @return: ListNode head of the linked list
    16      */
    17     public static ListNode deleteDuplicates(ListNode head) {
    18         if (head == null || head.next == null) {
    19             return head;
    20         }
    21         //we need a dummy to save the head, and this is the code template
    22         ListNode dummy = new ListNode(0);
    23         dummy.next = head;
    24         ListNode cur = dummy;
    25         //we should process the node before the first duplicate
    26         while (cur.next != null && cur.next.next != null) {
    27             if (cur.next.val == cur.next.next.val) {
    28                 int dupValue = cur.next.val;
    29                 while (cur.next != null && cur.next.val == dupValue) {
    30                     cur.next = cur.next.next;
    31                 }
    32             } else {
    33                 cur = cur.next;
    34             }
    35         }
    36         return dummy.next;
    37     }
    38 }
    View Code

    69. Binary Tree Level Order Traversal (思路:利用queue的先进先出)

     1 /**
     2  * Definition of TreeNode:
     3  * public class TreeNode {
     4  *     public int val;
     5  *     public TreeNode left, right;
     6  *     public TreeNode(int val) {
     7  *         this.val = val;
     8  *         this.left = this.right = null;
     9  *     }
    10  * }
    11  */
    12 public class Solution {
    13     /**
    14      * @param root: The root of binary tree.
    15      * @return: Level order a list of lists of integer
    16      */
    17     public ArrayList<ArrayList<Integer>> levelOrder(TreeNode root) {
    18         //1.边界判断
    19         ArrayList<ArrayList<Integer>> arrList = new ArrayList<>();
    20         if (root == null) {
    21             return arrList;
    22         }
    23         //2.Queue是个接口,能通过LinkedList实现不能通过ArrayList实现
    24         Queue<TreeNode> queue = new LinkedList<TreeNode>();
    25         queue.offer(root);
    26         //3.循环体
    27         while (!queue.isEmpty()) {
    28             ArrayList<Integer> level = new ArrayList<>();
    29             int qSize = queue.size(); //注意,不能直接写入for循环 i < queue.size(),否则会因为后期的offer操作改变
    30             for (int i = 0; i < qSize; i++) {
    31                 TreeNode head = queue.poll(); //poll()获取头部,并从队列中移除头部
    32                 level.add(head.val);
    33                 if (head.left != null) {
    34                     queue.offer(head.left);
    35                 }
    36                 if (head.right != null) {
    37                     queue.offer(head.right);
    38                 }
    39             }
    40             arrList.add(level);
    41         }
    42         return arrList;
    43     }
    44 }
    View Code

    50. Product of Array Exclude Itself (思路:分成前后两部分去乘)

     1 public class Solution {
     2     /**
     3      * @param A: Given an integers array A
     4      * @return: A Long array B and B[i]= A[0] * ... * A[i-1] * A[i+1] * ... * A[n-1]
     5      */
     6     public ArrayList<Long> productExcludeItself(ArrayList<Integer> a) {
     7         ArrayList<Long> arrList = new ArrayList<>();
     8         if (a == null || a.size() == 0) {
     9             return arrList;
    10         }
    11         int len = a.size();
    12         long[] array = new long[len];
    13         long[] array1 = new long[len];
    14         for (int i = 0; i < len; i++) {
    15             array[i] = a.get(i);
    16         }
    17         array1 = multiply(array, array1);
    18         for (int i = 0; i < len; i++) {
    19             arrList.add(array1[i]);
    20         }
    21         return arrList;
    22     }
    23     public long[] multiply(long[] array, long[] array1) {
    24         //divid two parts to multiply
    25         int len = array.length;
    26         array1[0] = 1;
    27         for (int i = 1; i < len; i++) {
    28             array1[i] = array1[i - 1] * array[i - 1];
    29         }
    30         long temp = 1;
    31         for (int i = len - 2; i >= 0; i--) {
    32             temp = temp * array[i + 1];
    33             array1[i] = array1[i] * temp;
    34         }
    35         return array1;
    36     }
    37 }
    View Code
     1 public class Solution {
     2     /**
     3      * @param A: Given an integers array A
     4      * @return: A Long array B and B[i]= A[0] * ... * A[i-1] * A[i+1] * ... * A[n-1]
     5      */
     6     public ArrayList<Long> productExcludeItself(ArrayList<Integer> a) {
     7         ArrayList<Long> result = new ArrayList<>();
     8         if (a == null || a.size() == 0) {
     9             return result;
    10         }
    11         long[] A = new long[a.size()];
    12         for (int i = 0; i < a.size(); i++) {
    13             A[i] = a.get(i);
    14         }
    15         long[] B = new long[a.size()];
    16         B = multiply(A, B);
    17         for (int i = 0; i < B.length; i++) {
    18             result.add(B[i]);
    19         }
    20         return result;
    21     }
    22     public long[] multiply(long[] A, long[] B) {
    23         B[0] = 1;
    24         //分两步进行:先乘上C[i]
    25         for (int i = 1; i < A.length; i++) {
    26             B[i] = B[i - 1] * A[i - 1];
    27         }
    28         long temp = 1;
    29         //再乘上D[i]
    30         for (int i = A.length - 2; i >= 0; i--) {
    31             temp *= A[i + 1];
    32             B[i] = B[i] * temp;
    33         }
    34         return B;
    35     }
    36 }
    View Code

    71. Binary Tree Zigzag Level Order Traversal (思路:建立两个栈分别用来保存两个深度的节点,如果深度是偶数,先加入left,否则先加入right)

     1 /**
     2  * Definition of TreeNode:
     3  * public class TreeNode {
     4  *     public int val;
     5  *     public TreeNode left, right;
     6  *     public TreeNode(int val) {
     7  *         this.val = val;
     8  *         this.left = this.right = null;
     9  *     }
    10  * }
    11  */
    12 
    13 
    14 public class Solution {
    15     /**
    16      * @param root: The root of binary tree.
    17      * @return: A list of lists of integer include
    18      *          the zigzag level order traversal of its nodes' values
    19      */
    20     public ArrayList<ArrayList<Integer>> zigzagLevelOrder(TreeNode root) {
    21         ArrayList<ArrayList<Integer>> result = new ArrayList<>();
    22         if (root == null) {
    23             return result;
    24         }
    25         Stack<TreeNode> curLevel = new Stack<>();
    26         Stack<TreeNode> nextLevel = new Stack<>();
    27         Stack<TreeNode> temp = new Stack<>();
    28         //define two stacks to save the node of current level and next level respectively.
    29         curLevel.push(root);
    30         boolean oddOrEven = true;
    31         //when the num of elements is odd, push the left, else push the right
    32         while (!curLevel.isEmpty()) {
    33             ArrayList<Integer> curResult = new ArrayList<>();
    34             while (!curLevel.isEmpty()) {
    35                 TreeNode node = curLevel.pop();
    36                 curResult.add(node.val);
    37                 if (oddOrEven) {
    38                     if (node.left != null) {
    39                         nextLevel.push(node.left);
    40                     }
    41                     if (node.right != null) {
    42                         nextLevel.push(node.right);
    43                     }
    44                 } else {
    45                     if (node.right != null) {
    46                         nextLevel.push(node.right);
    47                     }
    48                     if (node.left != null) {
    49                         nextLevel.push(node.left);
    50                     }
    51                 }
    52             }
    53             temp = curLevel;
    54             curLevel = nextLevel;
    55             nextLevel = temp;
    56             oddOrEven = !oddOrEven;
    57             result.add(curResult);
    58         }
    59         return result;
    60     }
    61 }
    View Code
     1 /**
     2  * Definition of TreeNode:
     3  * public class TreeNode {
     4  *     public int val;
     5  *     public TreeNode left, right;
     6  *     public TreeNode(int val) {
     7  *         this.val = val;
     8  *         this.left = this.right = null;
     9  *     }
    10  * }
    11  */
    12 
    13 
    14 public class Solution {
    15     /**
    16      * @param root: The root of binary tree.
    17      * @return: A list of lists of integer include
    18      *          the zigzag level order traversal of its nodes' values
    19      */
    20     public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
    21         List<List<Integer>> result = new ArrayList<>();
    22         if (root == null) {
    23             return result;
    24         }
    25         //建立一个栈保存当前节点
    26         Stack<TreeNode> curLevel = new Stack<>();
    27         //一个指示符向量指示添加入栈的方向
    28         boolean change = true;
    29         curLevel.push(root);
    30         while (!curLevel.isEmpty()) {
    31             List<Integer> tempList = new ArrayList<>();
    32             int stackSize = curLevel.size();
    33             //建立一个栈保存下一层极的节点
    34             Stack<TreeNode> nextLevel = new Stack<>();
    35             for (int i = 0; i < stackSize; i++) {
    36                 TreeNode temp = curLevel.pop();
    37                 tempList.add(temp.val);
    38                 if (change) {
    39                     if (temp.left != null) {
    40                         nextLevel.push(temp.left);
    41                     }
    42                     if (temp.right != null) {
    43                         nextLevel.push(temp.right);
    44                     }
    45                 } else {
    46                     if (temp.right != null) {
    47                         nextLevel.push(temp.right);
    48                     }
    49                     if (temp.left != null) {
    50                         nextLevel.push(temp.left);
    51                     }
    52                 }
    53             }
    54             curLevel = nextLevel;
    55             change = !change;
    56             result.add(tempList);
    57         }
    58         return result;
    59     }
    60 }
    View Code
     1 /**
     2  * Definition of TreeNode:
     3  * public class TreeNode {
     4  *     public int val;
     5  *     public TreeNode left, right;
     6  *     public TreeNode(int val) {
     7  *         this.val = val;
     8  *         this.left = this.right = null;
     9  *     }
    10  * }
    11  */
    12 
    13 
    14 public class Solution {
    15     /**
    16      * @param root: The root of binary tree.
    17      * @return: A list of lists of integer include
    18      *          the zigzag level order traversal of its nodes' values
    19      */
    20     public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
    21         //跟层次遍历一样,不过间隔一次进行一次反转操作就行Collections.reverse(tempList)
    22         List<List<Integer>> result = new ArrayList<>();
    23         if (root == null) {
    24             return result;
    25         }
    26         Queue<TreeNode> queue = new LinkedList<>();
    27         queue.offer(root);
    28         boolean flag = false;
    29         while (!queue.isEmpty()) {
    30             int queueSize = queue.size();
    31             ArrayList<Integer> tempList = new ArrayList<>();
    32             for (int i = 0; i < queueSize; i++) {
    33                 TreeNode temp = queue.poll();
    34                 tempList.add(temp.val);
    35                 if (temp.left != null) {
    36                     queue.offer(temp.left);
    37                 }
    38                 if (temp.right != null) {
    39                     queue.offer(temp.right);
    40                 }
    41             }
    42             if (flag) {
    43                 Collections.reverse(tempList);
    44             }
    45             flag = !flag;
    46             result.add(tempList);
    47         }
    48         return result;
    49     }
    50 }

    7.Binary Tree Serialization (思路:选择一个字符来表示为空的节点,然后将节点用逗号分开,反序列化的时候根据字符将节点分开)

     1 /**
     2  * Definition of TreeNode:
     3  * public class TreeNode {
     4  *     public int val;
     5  *     public TreeNode left, right;
     6  *     public TreeNode(int val) {
     7  *         this.val = val;
     8  *         this.left = this.right = null;
     9  *     }
    10  * }
    11  */
    12 class Solution {
    13     /**
    14      * This method will be invoked first, you should design your own algorithm
    15      * to serialize a binary tree which denote by a root node to a string which
    16      * can be easily deserialized by your own "deserialize" method later.
    17      */
    18     public String serialize(TreeNode root) {
    19         StringBuilder sb = new StringBuilder();
    20         buildString(root, sb);
    21         return sb.toString();
    22     }
    23     private void buildString(TreeNode root, StringBuilder sb) {
    24         if (root == null) {
    25             sb.append("$,");
    26         } else {
    27             sb.append(root.val).append(",");
    28             buildString(root.left, sb);
    29             buildString(root.right, sb);
    30         }
    31     }
    32     /**
    33      * This method will be invoked second, the argument data is what exactly
    34      * you serialized at method "serialize", that means the data is not given by
    35      * system, it's given by your own serialize method. So the format of data is
    36      * designed by yourself, and deserialize it here as you serialize it in
    37      * "serialize" method.
    38      */
    39     public TreeNode deserialize(String data) {
    40         Deque<String> nodes = new LinkedList<>();
    41         nodes.addAll(Arrays.asList(data.split(",")));
    42         return buildTree(nodes);
    43     }
    44     private TreeNode buildTree(Deque<String> nodes) {
    45         // we need the deque class to get the method of remove();
    46         String val = nodes.remove();
    47         if (val.equals("$")) {
    48             return null;
    49         } else {
    50             TreeNode root = new TreeNode(Integer.valueOf(val));
    51             root.left = buildTree(nodes);
    52             root.right = buildTree(nodes);
    53             return root;
    54         }
    55     }
    56 }
    View Code

    192. Wildcard Matching (思路:定义两个指针,并着重处理模式中为* 的情况)

     1 public class Solution {
     2     /**
     3      * @param s: A string
     4      * @param p: A string includes "?" and "*"
     5      * @return: A boolean
     6      */
     7     public boolean isMatch(String str, String pat) {
     8         //定义四个指针,两个分别指向str和pat,另外两个分别表示*的位置以及
     9         int indexP = 0;
    10         int indexS = 0;
    11         int indexStar = -1;
    12         int indexMatch = 0;
    13         while (indexS < str.length()) {
    14             //当两个指针指向完全相同的字符或者p指向的是?时
    15             if (indexP < pat.length() && (pat.charAt(indexP) == '?' || str.charAt(indexS) == pat.charAt(indexP))) {
    16                 indexP++;
    17                 indexS++;
    18             //如果字符不同也没有?,但是在p中遇到的是*,那么记录下*的位置,但是不改变s的指针
    19             } else if (indexP < pat.length() && pat.charAt(indexP) == '*') {
    20                 indexStar = indexP;
    21                 indexP++;
    22                 //遇到*后,用indexMatch记录匹配到的s的位置,和不用*匹配的s字符串区分
    23                 indexMatch = indexS;
    24             //如果字符不同也没有?,p指向的也不是*,但是之前遇到*的话,我们可以从indexMatch继续匹配任意字符
    25             } else if (indexStar != -1) {
    26             //如果用上一个*匹配,那么p应该退回上一个*的后面
    27                 indexP = indexStar + 1;
    28             //用*匹配的位置递增
    29                 indexMatch++;
    30             //s退回到*匹配位置
    31                 indexS = indexMatch;
    32             } else {
    33                 return false;
    34             }
    35         }
    36         // 因为1个*能匹配无限序列,如果p末尾有多个*,我们都要跳过
    37         while (indexP < pat.length() && pat.charAt(indexP) == '*') {
    38             indexP++;
    39         }
    40         return indexP ==  pat.length();
    41     }
    42 }
    View Code

    102. Linked List Cycle(思路: 定义一快一慢两个指针,如果最后两个指针相遇,说明存在环)

     1 /**
     2  * Definition for ListNode.
     3  * public class ListNode {
     4  *     int val;
     5  *     ListNode next;
     6  *     ListNode(int val) {
     7  *         this.val = val;
     8  *         this.next = null;
     9  *     }
    10  * }
    11  */ 
    12 public class Solution {
    13     /**
    14      * @param head: The first node of linked list.
    15      * @return: True if it has a cycle, or false
    16      */
    17     public boolean hasCycle(ListNode head) {  
    18         //!!!!!!!!!!!!!!!!!!!!!!!!!!
    19         //java.lang.NullPointerException this only occurs in if or while etc, means
    20         //only occurs when judging the conditions, doesn't occur in assignment 
    21         //statement(赋值语句)except fast = fast.next.next;
    22         //简单来说就是node = node.next这个语句中node不可以为空,但是node.next可以为空
    23         //!!!!!!!!!!!!!!!!!!!!!!!!!!
    24         if (head == null || head.next == null) {
    25             return false;
    26         }
    27         //define two points, slow and fast, if they can meet each other, means 
    28         //there is a cycle in this list.
    29         ListNode slow = head;
    30         ListNode fast = head.next;
    31         while (slow != null && fast != null) {
    32             if (slow == fast) {
    33                 return true;
    34             }
    35             slow = slow.next;
    36             fast = fast.next;
    37             if (fast != null) {
    38                 fast = fast.next;
    39             }
    40         }
    41         return false;
    42     }
    43 }
    View Code

    103. Linked List Cycle II (思路:根据102找到相遇的节点,这个节点必然为环路中的节点,然后根据此节点获得环路的节点个数n,然后定义一快一慢两个指针,快指针先走n步,然后两个一起走,相遇的节点就是环开始的节点)

     1 /**
     2  * Definition for ListNode.
     3  * public class ListNode {
     4  *     int val;
     5  *     ListNode next;
     6  *     ListNode(int val) {
     7  *         this.val = val;
     8  *         this.next = null;
     9  *     }
    10  * }
    11  */
    12 public class Solution {
    13     /**
    14      * @param head: The first node of linked list.
    15      * @return: The node where the cycle begins.
    16      *           if there is no cycle, return null
    17      */
    18     public ListNode detectCycle(ListNode head) {
    19         int num = getNumOfNodeInLoop(head);
    20         if (num == 0) {
    21             return null;
    22         }
    23         ListNode first = head;
    24         ListNode second = head;
    25         for (int i = 0; i < num; i++) {
    26             first = first.next;
    27         }
    28         while (first != second) {
    29             first = first.next;
    30             second = second.next;
    31         }
    32         return first;
    33     }
    34     public ListNode findMeetingNode(ListNode head) {
    35         //if there is no node or one node in list, there will not be cycle
    36         if (head == null || head.next == null) {
    37             return null;
    38         }
    39         //define two points, slow and fast, when they meet each other,
    40         //this means there is cycle
    41         ListNode slow = head;
    42         //if code is ListNode slow = head.next, this solution is accepted, but i
    43         //think it's wrong! because it doesn't include the instance of (head == head.next) 
    44         ListNode fast = slow.next;
    45         while (slow != null && fast != null) {
    46             if (slow == fast) {
    47                 return slow;
    48             }
    49             slow = slow.next;
    50             fast = fast.next;
    51             if (fast != null) {
    52                 fast = fast.next;
    53             }
    54         }
    55         return null;
    56     }
    57     public int getNumOfNodeInLoop(ListNode head) {
    58         if (head == null || head.next == null) {
    59             return 0;
    60         }
    61         //meetingNode must be one of nodes in loop,
    62         //so from meetingNode to meetingNode(second time)
    63         //is the num of nodes in loop
    64         ListNode meetingNode = findMeetingNode(head);
    65         if (meetingNode == null) {
    66             return 0;
    67         }
    68         int num = 1;
    69         ListNode node = meetingNode;
    70         while (node.next != meetingNode) {
    71             node = node.next;
    72             num++;
    73         }
    74         return num;
    75     }
    76 }
    View Code

    81. Data Stream Median(思路:建立最大堆和最小堆,最大堆的堆顶就是中位数)

     1 public class Solution {
     2     /**
     3      * @param nums: A list of integers.
     4      * @return: the median of numbers
     5      */
     6     public int[] medianII(int[] nums) {
     7         if (nums == null || nums.length == 0) {
     8             return new int[0];
     9         }
    10         int len = nums.length;
    11         PriorityQueue<Integer> maxHeap = new PriorityQueue<>(len, Collections.reverseOrder());
    12         PriorityQueue<Integer> minHeap = new PriorityQueue<>(len);
    13         int[] result = new int[len];
    14         for (int i = 0; i < nums.length; i++) {
    15             //put first num in maxHeap
    16             //然后根据大小加入最大堆和最小堆,再根据两个堆的数量进行
    17             if (maxHeap.isEmpty() || nums[i] < maxHeap.peek()) {
    18                 maxHeap.add(nums[i]); //maxHeap.offer(nums[i]) is ok too.
    19             } else {
    20                 minHeap.add(nums[i]);
    21             }
    22             if (minHeap.size() > maxHeap.size()) {
    23                 maxHeap.add(minHeap.poll());
    24             }
    25             if (maxHeap.size() > minHeap.size() + 1) {
    26                 minHeap.add(maxHeap.poll());
    27             }
    28             result[i] = maxHeap.peek();
    29         }
    30         return result;
    31     }
    32 }
    View Code

    362. Sliding Window Maximum (思路:滑动窗口的最大值一直在队列的头部)

     1 public class Solution {
     2     /**
     3      * @param nums: A list of integers.
     4      * @return: The maximum number inside the window at each moving.
     5      */
     6     public ArrayList<Integer> maxSlidingWindow(int[] nums, int k) {
     7         ArrayList<Integer> result = new ArrayList<>();
     8         if (nums == null || nums.length == 0 || k == 0) {
     9             return result;
    10         }
    11         Deque<Integer> deque = new ArrayDeque<>();
    12         for (int i = 0; i < k - 1; i++) {
    13             inDeque(deque, nums[i]);
    14         }
    15         for (int i = k - 1; i < nums.length; i++) {
    16             inDeque(deque, nums[i]);
    17             result.add(deque.peekFirst());
    18             outDeque(deque, nums[i - (k - 1)]);
    19         }
    20         return result;
    21     }
    22     public void inDeque(Deque<Integer> deque, int num) {
    23         //根据剑指offer的思路,滑动窗口的最大值在队列的首部
    24         while (!deque.isEmpty() && deque.peekLast() < num) {
    25             deque.pollLast();
    26         }
    27         deque.offer(num);
    28     }
    29     public void outDeque(Deque<Integer> deque, int num) {
    30         //accroding to the size of sliding windows
    31         if (deque.peekFirst() == num) {
    32             deque.pollFirst();
    33         }
    34     }
    35 }
    View Code

    public class Solution {
        /**
         * @param A a string
         * @param B a string
         * @return a boolean
         */
        public boolean Permutation(String a, String b) {
            //注意如何将字符转化为ackii码(直接强制转换),以及判断整个数组是否为0(遍历)
            if (a == null || b == null) {
                return a == b;
            }
            if (a.length() != b.length()) {
                return false;
            }
            int[] nums = new int[150];
            for (int i = 0; i < a.length(); i++) {
                nums[(int)a.charAt(i)]++;
            }
            for (int i = 0; i < b.length(); i++) {
                nums[(int)b.charAt(i)]--;
            }
            for (int i = 0; i < nums.length; i++) {
                if (nums[i] != 0) {
                    return false;
                }
            }
            return true;
        }
    }

  • 相关阅读:
    2021年2月4号
    2021年2月3号
    2021年2月2号
    2021年2月1日
    2021年1月31日
    2021年1月30日
    20171205xlVBA往返航班组合
    选择文件
    从VBA过渡到Python
    20171114xlVba选定单行记录并打印
  • 原文地址:https://www.cnblogs.com/muziyueyueniao/p/7123841.html
Copyright © 2011-2022 走看看