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;
    }
}

posted @ 2017-07-05 22:27  木子月月鸟  阅读(267)  评论(0编辑  收藏  举报