Toyan

导航

剑指offer

3.数组中重复的数字

第一种方法:修改原数组中元素的位置,时间复杂度:o(n),空间复杂度:o(1),这种方法可以找到所有的重复数字

 1 public class Solution {
 2     // Parameters:
 3     //    numbers:     an array of integers
 4     //    length:      the length of array numbers
 5     //    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
 6     //                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
 7     //    这里要特别注意~返回任意重复的一个,赋值duplication[0]
 8     // Return value:       true if the input is valid, and there are some duplications in the array number
 9     //                     otherwise false
10     public boolean duplicate(int[] numbers,int length,int[] duplication) {
11         if (numbers == null || length <= 0) {
12             return false;
13         }
14         for (int i = 0; i < length; i++) {
15             if (numbers[i] < 0 || numbers[i] > length - 1) {
16                 return false;
17             }
18         }
19         for (int i = 0; i < length; i++) {
20             while (numbers[i] != i) {
21                 if (numbers[i] == numbers[numbers[i]]) {
22                     duplication[0] = numbers[i];
23                     return true;
24                 }
25                 int temp = numbers[i];
26                 numbers[i] = numbers[temp];
27                 numbers[temp] = temp;
28             }
29         }
30         return false;
31     }
32 }
View Code

第二种方法:不修改原数组中元素的位置,时间复杂度:o(nlogn),空间复杂度:o(1),这种方法只能找到其中一个重复数字

 1 public class Solution {
 2     // Parameters:
 3     //    numbers:     an array of integers
 4     //    length:      the length of array numbers
 5     //    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
 6     //                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
 7     //    这里要特别注意~返回任意重复的一个,赋值duplication[0]
 8     // Return value:       true if the input is valid, and there are some duplications in the array number
 9     //                     otherwise false
10     public boolean duplicate(int[] numbers,int length,int[] duplication) {
11         if (numbers == null || length <= 0) {
12             return false;
13         }
14         int num = getDuplication(numbers, length);
15         if (num == -1) {
16             return false;
17         }
18         duplication[0] = num;
19         return true;
20     }
21     private int getDuplication(int[] numbers, int length) {
22         int start = 1;
23         int end = length - 1;
24         while (start <= end) {
25             int mid = start + (end - start) / 2;
26             int count = countRange(numbers, length, start, mid);
27             if (start == end) {
28                 if (count > 1) {
29                     return start;
30                 }
31                 return -1;
32             }
33             if (count > mid - start + 1) {
34                 end = mid;
35             } else {
36                 start = mid + 1;
37             }
38         }
39         return -1;
40     }
41     private int countRange(int[] nums, int length, int start, int end) {
42         int count = 0;
43         for (int i = 0; i < length; i++) {
44             if (nums[i] >= start && nums[i] <= end) {
45                 count++;
46             }
47         }
48         return count;
49     }
50 }
View Code

 

5. 替换空格

第一种方法:需要o(n)的额外空间

 1 // time:o(n)
 2 public class Solution {
 3     public String replaceSpace(StringBuffer str) {
 4         String oldStr = str.toString();
 5         char[] ch = oldStr.toCharArray();
 6         StringBuilder newStr = new StringBuilder();
 7         for (int i = 0; i < ch.length; i++) {
 8             if (ch[i] == ' ') {
 9                 newStr.append("%20");
10             } else {
11                 newStr.append(ch[i]);
12             }
13         }
14         return newStr.toString();
15     }
16 }
View Code

第二种方法:直接在原字符串中变化

 1 // time:o(n)
 2 public class Solution {
 3     public String replaceSpace(StringBuffer str) {
 4         int oldLen = str.length();
 5         int spaceNum = 0;
 6         for (int i = 0; i < oldLen; i++) {
 7             if (str.charAt(i) == ' ') {
 8                 spaceNum++;
 9             }
10         }
11         int newLen = oldLen + spaceNum * 2;
12         str.setLength(newLen);
13         while (newLen != oldLen) {
14             if (str.charAt(--oldLen) == ' ') {
15                 str.setCharAt(--newLen, '0');
16                 str.setCharAt(--newLen, '2');
17                 str.setCharAt(--newLen, '%');
18             } else {
19                 str.setCharAt(--newLen, str.charAt(oldLen));
20             }
21         }
22         return str.toString();
23     }
24 }
View Code

6. 从尾到头打印链表 

第一种方法:简单

 1 /**
 2 *    public class ListNode {
 3 *        int val;
 4 *        ListNode next = null;
 5 *
 6 *        ListNode(int val) {
 7 *            this.val = val;
 8 *        }
 9 *    }
10 *
11 */
12 import java.util.ArrayList;
13 public class Solution {
14     public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
15         ArrayList<Integer> res = new ArrayList<>();
16         while (listNode != null) {
17             res.add(0, listNode.val);
18             listNode = listNode.next;
19         }
20         return res;
21     }
22 }
View Code

第二种方法:使用栈

 1 /**
 2 *    public class ListNode {
 3 *        int val;
 4 *        ListNode next = null;
 5 *
 6 *        ListNode(int val) {
 7 *            this.val = val;
 8 *        }
 9 *    }
10 *
11 */
12 import java.util.*;
13 public class Solution {
14     public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
15         ArrayList<Integer> res = new ArrayList<>();
16         Stack<Integer> stack = new Stack<>();
17         while (listNode != null) {
18             stack.push(listNode.val);
19             listNode = listNode.next;
20         }
21         while (!stack.isEmpty()) {
22             res.add(stack.pop());
23         }
24         return res;
25     }
26 }
View Code

7. 重建二叉树

总结:

  1. 前序遍历
     1 /**
     2  * Definition for a binary tree node.
     3  * public class TreeNode {
     4  *     int val;
     5  *     TreeNode left;
     6  *     TreeNode right;
     7  *     TreeNode(int x) { val = x; }
     8  * }
     9  */
    10 // non-recursion
    11 class Solution {
    12     public List<Integer> preorderTraversal(TreeNode root) {
    13         Stack<TreeNode> stack = new Stack<>();
    14         List<Integer> res = new ArrayList<>();
    15         if (root == null) {
    16             return res;
    17         }
    18         stack.push(root);
    19         while (!stack.isEmpty()) {
    20             TreeNode node = stack.pop();
    21             res.add(node.val);
    22             if (node.right != null) {
    23                 stack.push(node.right);
    24             }
    25             if (node.left != null) {
    26                 stack.push(node.left);
    27             }
    28         }
    29         return res;
    30     }
    31 }
    View Code
     1 /**
     2  * Definition for a binary tree node.
     3  * public class TreeNode {
     4  *     int val;
     5  *     TreeNode left;
     6  *     TreeNode right;
     7  *     TreeNode(int x) { val = x; }
     8  * }
     9  */
    10 // Traverse
    11 class Solution {
    12     private List<Integer> res = new ArrayList<>();
    13     public List<Integer> preorderTraversal(TreeNode root) {
    14         if (root == null) {
    15             return res;
    16         }
    17         helper(root);
    18         return res;
    19     }
    20     private void helper(TreeNode node) {
    21         if (node == null) {
    22             return;
    23         }
    24         res.add(node.val);
    25         helper(node.left);
    26         helper(node.right);
    27     }
    28 }
    View Code
     1 /**
     2  * Definition for a binary tree node.
     3  * public class TreeNode {
     4  *     int val;
     5  *     TreeNode left;
     6  *     TreeNode right;
     7  *     TreeNode(int x) { val = x; }
     8  * }
     9  */
    10 // Divide & Conquer
    11 class Solution {
    12     public List<Integer> preorderTraversal(TreeNode root) {
    13         List<Integer> res = new ArrayList<>();
    14         if (root == null) {
    15             return res;
    16         }
    17         List<Integer> left = preorderTraversal(root.left);
    18         List<Integer> right = preorderTraversal(root.right);
    19         res.add(root.val);
    20         res.addAll(left);
    21         res.addAll(right);
    22         return res;
    23     }
    24 }
    View Code
  2. 中序遍历
     1 /**
     2  * Definition for a binary tree node.
     3  * public class TreeNode {
     4  *     int val;
     5  *     TreeNode left;
     6  *     TreeNode right;
     7  *     TreeNode(int x) { val = x; }
     8  * }
     9  */
    10 // recursion
    11 class Solution {
    12     public List<Integer> inorderTraversal(TreeNode root) {
    13         List<Integer> res = new ArrayList<>();
    14         if (root == null) {
    15             return res;
    16         }
    17         List<Integer> left = inorderTraversal(root.left);
    18         List<Integer> right = inorderTraversal(root.right);
    19         res.addAll(left);
    20         res.add(root.val);
    21         res.addAll(right);
    22         return res;
    23     }
    24 }
    View Code
     1 /**
     2  * Definition for a binary tree node.
     3  * public class TreeNode {
     4  *     int val;
     5  *     TreeNode left;
     6  *     TreeNode right;
     7  *     TreeNode(int x) { val = x; }
     8  * }
     9  */
    10 // Non-recursion
    11 class Solution {
    12     public List<Integer> inorderTraversal(TreeNode root) {
    13         Stack<TreeNode> stack = new Stack<>();
    14         List<Integer> res = new ArrayList<>();
    15         TreeNode cur = root;
    16         while (cur != null || !stack.isEmpty()) {
    17             while (cur != null) {
    18                 stack.add(cur);
    19                 cur = cur.left;
    20             }
    21             cur = stack.pop();
    22             res.add(cur.val);
    23             cur = cur.right;
    24         }
    25         return res;
    26     }
    27 }
    View Code
  3. 后序遍历
     1 /**
     2  * Definition for a binary tree node.
     3  * public class TreeNode {
     4  *     int val;
     5  *     TreeNode left;
     6  *     TreeNode right;
     7  *     TreeNode(int x) { val = x; }
     8  * }
     9  */
    10 class Solution {
    11     public List<Integer> postorderTraversal(TreeNode root) {
    12         List<Integer> res = new ArrayList<>();
    13         if (root == null) {
    14             return res;
    15         }
    16         List<Integer> left = postorderTraversal(root.left);
    17         List<Integer> right = postorderTraversal(root.right);
    18         res.addAll(left);
    19         res.addAll(right);
    20         res.add(root.val);
    21         return res;
    22     }
    23 }
    View Code

    后序遍历的非递归确实没看懂

题目:

思路:在前序遍历结果中找开始节点与结束节点,不要忘记减去startIn,对于二叉树节点为奇数个时,则循环不可能导致最后相等,因此判断递归结束条件要按照答案给出的写

 1 /**
 2  * Definition for binary tree
 3  * public class TreeNode {
 4  *     int val;
 5  *     TreeNode left;
 6  *     TreeNode right;
 7  *     TreeNode(int x) { val = x; }
 8  * }
 9  */
10 public class Solution {
11     public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
12         TreeNode root = construct(pre, 0, pre.length - 1, in, 0, in.length - 1);
13         return root;
14     }
15     private TreeNode construct(int[] pre, int startPre, int endPre, int[] in, int startIn, int endIn) {
16         if (startPre > endPre || startIn > endIn) {
17             return null;
18         }
19         TreeNode root = new TreeNode(pre[startPre]);
20         for (int i = startIn; i <= endIn; i++) {
21             if (in[i] == pre[startPre]) {
22                 root.left = construct(pre, startPre + 1, startPre + i - startIn, in, startIn, i - 1);
23                 root.right = construct(pre, startPre + i - startIn + 1, endPre, in, i + 1, endIn);
24             }
25         }
26         return root;
27     }
28 }
View Code

9. 用两个栈实现队列

 1 import java.util.Stack;
 2 
 3 public class Solution {
 4     Stack<Integer> stack1 = new Stack<Integer>();
 5     Stack<Integer> stack2 = new Stack<Integer>();
 6     
 7     public void push(int node) {
 8         stack1.push(node);
 9     }
10     
11     public int pop() {
12         if (stack2.isEmpty()) {
13             stack1ToStack2();
14         }
15         return stack2.pop();
16     }
17     private void stack1ToStack2() {
18         while (!stack1.isEmpty()) {
19             stack2.push(stack1.pop());
20         }
21     }
22 }
View Code

用两个队列实现一个栈,leetcode225

10. 斐波那契数列

 1 public class Solution {
 2     public int Fibonacci(int n) {
 3         if (n == 0) {
 4             return 0;
 5         }
 6         int[] res = new int[3];
 7         res[0] = 1;
 8         res[1] = 1;
 9         for (int i = 2; i < n; i++) {
10             res[i % 3] = res[(i - 1) % 3] + res[(i - 2) % 3];
11         }
12         return res[(n - 1) % 3];
13     }
14 }
View Code

 跳台阶

 1 public class Solution {
 2     public int JumpFloor(int target) {
 3         if (target <= 1) {
 4             return 1;
 5         }
 6         int[] res = new int[3];
 7         res[0] = 1;
 8         res[1] = 1;
 9         for (int i = 2; i <= target; i++) {
10             res[i % 3] = res[(i - 1) % 3] + res[(i - 2) % 3];
11         }
12         return res[target % 3];
13     }
14 }
View Code

变态跳台阶

 1 public class Solution {
 2     public int JumpFloorII(int target) {
 3         if (target <= 1) {
 4             return 1;
 5         }
 6         int[] res = new int[3];
 7         res[0] = 1;
 8         res[1] = 1;
 9         for (int i = 2; i <= target; i++) {
10             res[i % 3] = res[(i - 1) % 3] * 2;
11         }
12         return res[target % 3];
13     }
14 }
View Code

 矩形覆盖

 1 public class Solution {
 2     public int RectCover(int target) {
 3         if (target <= 0) {
 4             return 0;
 5         }
 6         int[] result = new int[3];
 7         result[0] = 1;
 8         result[1] = 1;
 9         for (int i = 2; i <= target; i++) {
10             result[i % 3] = result[(i - 1) % 3] + result[(i - 2) % 3];
11         }
12         return result[target % 3];
13     }
14 }
View Code

 

11. 旋转数组的最小数字

 1 import java.util.ArrayList;
 2 public class Solution {
 3     public int minNumberInRotateArray(int [] array) {
 4         if (array == null || array.length == 0) {
 5             return 0;
 6         }
 7         int start = 0;
 8         int end = array.length - 1;
 9         while (start + 1 < end) {
10             int mid = start + (end - start) / 2;
11             if (array[mid] > array[end]) {
12                 start = mid;
13             } else {
14                 end = mid;
15             }
16         }
17         if (array[start] <= array[end]) {
18             return array[start];
19         } else {
20             return array[end];
21         }
22     }
23 }
View Code
1 public class Solution {
2     public int JumpFloorII(int target) {
3         int result = 1;
4         for (int i = 1; i < target; i++) {
5             result *= 2;
6         }
7         return result;
8     }
9 }
View Code

12. 矩阵中的路径

 1 public class Solution {
 2     public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
 3         if (matrix == null || matrix.length == 0) {
 4             return false;
 5         }
 6         int[] visited = new int[matrix.length];
 7         for (int i = 0; i < rows; i++) {
 8             for (int j = 0; j < cols; j++) {
 9                 if (helper(matrix, rows, cols, str, i, j, 0, visited)) {
10                     return true;
11                 }
12             }
13         }
14         return false;
15     }
16     private boolean helper(char[] matrix, int rows, int cols, char[] str, int i, int j, int k, int[] visited) {
17         int index = i * cols + j;
18         if (i < 0 || i >= rows || j < 0 || j >= cols || matrix[index] != str[k] || visited[index] == 1) {
19             return false;
20         }
21         if (k == str.length - 1) {
22             return true;
23         }
24         visited[index] = 1;
25         if (helper(matrix, rows, cols, str, i - 1, j, k + 1, visited) ||
26            helper(matrix, rows, cols, str, i + 1, j, k + 1, visited) ||
27            helper(matrix, rows, cols, str, i, j - 1, k + 1, visited) ||
28            helper(matrix, rows, cols, str, i, j + 1, k + 1, visited)) {
29             return true;
30         }
31         visited[index] = 0;
32         return false;
33     }
34 }
View Code

13. 机器人的运动范围

 1 public class Solution {
 2     public int movingCount(int threshold, int rows, int cols) {
 3         if (threshold < 0 || rows < 0 || cols < 0) {
 4             return 0;
 5         }
 6         int[] visited = new int[rows * cols];
 7         int result = helper(threshold, rows, cols, 0, 0, visited);
 8         return result;
 9     }
10     private int helper(int threshold, int rows, int cols, int row, int col, int[] visited) {
11         int count = 0;
12         if (check(threshold, rows, cols, row, col, visited)) {
13             visited[row * cols + col] = 1;
14             count = 1 + helper(threshold, rows, cols, row - 1, col, visited) +
15                         helper(threshold, rows, cols, row + 1, col, visited) +
16                         helper(threshold, rows, cols, row, col - 1, visited) +
17                         helper(threshold, rows, cols, row, col + 1, visited);
18         }
19         return count;
20     }
21     private boolean check(int threshold, int rows, int cols, int row, int col, int[] visited) {
22         if (row < 0 || row >= rows || col < 0 || col >= cols || visited[row * cols + col] == 1 ||
23            getDigitSum(row) + getDigitSum(col) > threshold) {
24             return false;
25         }
26         return true;
27     }
28     private int getDigitSum(int num) {
29         int sum = 0;
30         while (num != 0) {
31             sum += num % 10;
32             num /= 10;
33         }
34         return sum;
35     }
36 }
View Code

14. 剪绳子 

第一种方法:动态规划;第二种方法:贪婪算法

 1 public class Solution {
 2     public int maxProductAfterCutting(int length) {
 3         if (length < 2) {
 4             return 0;
 5         }
 6         if (length == 2) {
 7             return 1;
 8         }
 9         if (length == 3) {
10             return 2;
11         }
12         int[] products = new int[length + 1];
13         products[0] = 0;
14         products[1] = 1;
15         products[2] = 2;
16         products[3] = 3;
17         int max = 0;
18         for (int i = 4; i <= length; i++) {
19             max = 0;
20             for (int j = 0; j <= i / 2; j++) {
21                 max = Math.max(max, products[j] * products[i - j]);
22             }
23             products[i] = max;
24         }
25         return products[length];
26     }
27 }
View Code
 1 public class Solution {
 2     public int maxProductAfterCutting(int length) {
 3     if (length < 2) {
 4             return 0;
 5         }
 6         if (length == 2) {
 7             return 1;
 8         }
 9         if (length == 3) {
10             return 2;
11         }
12         int timesOf3 = length / 3;
13         if (length - timesOf3 * 3 == 1) {
14             timesOf3--;
15         }
16         int timesOf2 = (length - timesOf3 * 3) / 2;
17         return Math.pow(3, timesOf3) + Math.pow(2, timesOf2);
18     }
19 }
View Code

15. 二进制中1的个数

常规解法

 1 public class Solution {
 2     public int NumberOf1(int n) {
 3         int count = 0;
 4         int flag = 1;
 5         while (flag != 0) {
 6             int num = flag & n;
 7             if (num != 0) {
 8                 count++;
 9             }
10             flag = flag << 1;
11         }
12         return count;
13     }
14 }
View Code

通过减1与原本数字相与,可以得到1的个数

 1 public class Solution {
 2     public int NumberOf1(int n) {
 3         int count = 0;
 4         while (n != 0) {
 5             n = n & (n - 1);
 6             count++;
 7         }
 8         return count;
 9     }
10 }
View Code

16. 数值的整数次方

注意:底数为0,指数为负数的情况要特殊考虑

 1 public class Solution {
 2     public double Power(double base, int exponent) {
 3         if (base == 0.0 && exponent < 0) {
 4             return 0.0;
 5         }
 6         int absExponent = Math.abs(exponent);
 7         double res = getResult(base, absExponent);
 8         if (exponent < 0) {
 9             res = 1.0 / res;
10         }
11         return res;
12     }
13     private double getResult(double base, int exponent) {
14         if (exponent == 0) {
15             return 1;
16         }
17         if (exponent == 1) {
18             return base;
19         }
20         double res = getResult(base, exponent >> 1);
21         res *= res;
22         // 为运算符代替了求余来判断奇数与偶数
23         int num = exponent & 1;
24         if (num == 1) {
25             res *= base;
26         }
27         return res;
28     }
29 }
View Code

18. 删除链表的节点

注意:删除节点时要判断节点是否为null

 1 /*
 2  public class ListNode {
 3     int val;
 4     ListNode next = null;
 5 
 6     ListNode(int val) {
 7         this.val = val;
 8     }
 9 }
10 */
11 public class Solution {
12     public ListNode deleteDuplication(ListNode pHead) {
13         ListNode dummy = new ListNode(0);
14         dummy.next = pHead;
15         
16         ListNode preNode = dummy;
17         while (pHead != null && pHead.next != null) {
18             if (pHead.val == pHead.next.val) {
19                 int val = pHead.val;
20                 while (pHead != null && pHead.val == val) {
21                     pHead = pHead.next;
22                 }
23                 preNode.next = pHead;
24             } else {
25                 preNode = pHead;
26                 pHead = pHead.next;
27             }
28         }
29         return dummy.next;
30         
31     }
32 }
View Code

19. 正则表达式匹配

思路:

当模式中的第二个字符不是*时:

1. 如果字符串第一个字符和模式中的第一个字符相匹配,那么字符串和模式都后移一个字符,然后匹配剩余的

2. 如果字符串第一个字符与模式中的第一个字符不匹配,直接返回false

当模式中的第二个字符是*时:

如果字符串第一个字符与模式中的第一个字符不匹配,则模式后移两个字符,继续匹配;如果字符串第一个字符与模式中的第一个字符匹配,则有三种匹配方式:

1. 模式后移2个字符,相当于x*被忽略

2. 字符串后移1位,模式后移2个字符

3. 字符串后移1位,模式不变,继续匹配字符串下一位,因为*可以匹配多位

 1 public class Solution {
 2     public boolean match(char[] str, char[] pattern) {
 3         if (str == null || pattern == null) {
 4             return false;
 5         }
 6         int strIndex = 0;
 7         int patternIndex = 0;
 8         return matchCore(str, strIndex, pattern, patternIndex);
 9     }
10     private boolean matchCore(char[] str, int strIndex, char[] pattern, int patternIndex) {
11         // 有效性检验,str到尾,pattern也同样到尾
12         if (strIndex == str.length && patternIndex == pattern.length) {
13             return true;
14         }
15         // pattern先到尾,匹配失败
16         if (strIndex != str.length && patternIndex == pattern.length) {
17             return false;
18         }
19         // 模式第二个是*,且字符串第一个与模式第一个匹配,分三种匹配模式;如不匹配,模式后移2位
20         if (patternIndex + 1 < pattern.length && pattern[patternIndex + 1] == '*') {
21             if ((strIndex != str.length && str[strIndex] == pattern[patternIndex]) || (strIndex != str.length && pattern[patternIndex] == '.')) {
22                 return matchCore(str, strIndex + 1, pattern, patternIndex) || // 匹配1个,在匹配str中的下一个
23                     // 下面代码可以删除
24                     matchCore(str, strIndex + 1, pattern, patternIndex + 2) || // 视为模式匹配1个字符
25                     matchCore(str, strIndex, pattern, patternIndex + 2); // 模式后移两位,视为x*匹配0个字符
26             } else {
27                 return matchCore(str, strIndex, pattern, patternIndex + 2);
28             }
29         }
30         // 模式第二个不是*,且字符串第1个跟模式第1个匹配,则都后移1位,否则直接返回false
31         if ((strIndex != str.length && str[strIndex] == pattern[patternIndex]) || (strIndex != str.length && pattern[patternIndex] == '.')) {
32             return matchCore(str, strIndex + 1, pattern, patternIndex + 1);
33         }
34         return false;
35     }
36 }
View Code

注意:

1. 对于模式的第二个字符是*的情况下,情况2可以被情况1和情况3包含。执行一次情况3,在执行一次情况1相当于情况2

20. 表示数值的字符串

可以分为A、B、C三部分,其中A与C需要判断其是否含有符号,然后其余部分都与B一样进行判断即可

 1 public class Solution {
 2     private int strIndex = 0;
 3     public boolean isNumeric(char[] str) {
 4         if (str == null || str.length == 0) {
 5             return false;
 6         }
 7         boolean numeric = scanInteger(str);
 8         if (strIndex < str.length && str[strIndex] == '.') {
 9             strIndex++;
10             numeric = scanUnsignedInteger(str) || numeric;
11         }
12         if (strIndex < str.length && (str[strIndex] == 'e' || str[strIndex] == 'E')) {
13             strIndex++;
14             numeric = numeric && scanInteger(str);
15         }
16         return numeric && strIndex >= str.length;
17     }
18     private boolean scanInteger(char[] str) {
19         if (strIndex < str.length && (str[strIndex] == '+' || str[strIndex] == '-')) {
20             strIndex++;
21         }
22         return scanUnsignedInteger(str);
23     }
24     private boolean scanUnsignedInteger(char[] str) {
25         int before = strIndex;
26         while (strIndex < str.length && str[strIndex] >= '0' && str[strIndex] <= '9') {
27             strIndex++;
28         }
29         return strIndex > before;
30     }
31 }
View Code

注意:

1. || 的判断,如果前面的为true,则后面的不会判断

21. 调整数字顺序使奇数位于偶数前面

不需要保证相对顺序

 1 public class ReorderOddEven {
 2     private void helper(int[] array) {
 3         if (array == null || array.length == 0) {
 4             return;
 5         }
 6         int start = 0;
 7         int end = array.length - 1;
 8         while (start < end) {
 9             while (start < array.length && array[start] % 2 == 1) {
10                 start++;
11             }
12             while (end >= 0 && array[end] % 2 == 0) {
13                 end--;
14             }
15             if (start < end) {
16                 int temp = array[start];
17                 array[start] = array[end];
18                 array[end] = temp;
19             }
20         }
21     }
22 }
View Code

需要保证相对顺序

 1 public class Solution {
 2     public void reOrderArray(int [] array) {
 3         if (array == null || array.length == 0) {
 4             return;
 5         }
 6         int count = 0;
 7         for (int num : array) {
 8             if (num % 2 == 1) {
 9                 count++;
10             }
11         }
12         int[] newArray = new int[array.length];
13         int start = 0;
14         for (int i = 0; i < array.length; i++) {
15             if (array[i] % 2 == 1) {
16                 newArray[start++] = array[i];
17             } else {
18                 newArray[count++] = array[i];
19             }
20         }
21         for (int i = 0; i < array.length; i++) {
22             array[i] = newArray[i];
23         }
24     }
25 }
View Code
 1 public class Solution {
 2     public void reOrderArray(int [] array) {
 3         if (array == null || array.length == 0) {
 4             return;
 5         }
 6         int i = 0, j = 0;
 7         while (j < array.length) {
 8             while (i < array.length && array[i] % 2 == 1) {
 9                 i++;
10             }
11             j = i + 1;
12             while (j < array.length && array[j] % 2 == 0) {
13                 j++;
14             }
15             if (j < array.length) {
16                 int temp = array[j];
17                 for (int j2 = j - 1; j2 >= i; j2--) {
18                     array[j2 + 1] = array[j2]; // 注意
19                 }
20                 array[i++] = temp;
21             } else {
22                 break;
23             }
24         }
25     }
26 }
View Code

22. 链表中倒数第k个节点

两根指针

 1 /*
 2 public class ListNode {
 3     int val;
 4     ListNode next = null;
 5 
 6     ListNode(int val) {
 7         this.val = val;
 8     }
 9 }*/
10 public class Solution {
11     public ListNode FindKthToTail(ListNode head,int k) {
12         if (head == null || k == 0) {
13             return null;
14         }
15         ListNode pHead = head;
16         ListNode pBehind = head;
17         int start = 0;
18         while (start < k - 1) {
19             if (pHead.next != null) {
20                 pHead = pHead.next;
21                 start++;
22             } else {
23                 return null;
24             }
25         }
26         while (pHead.next != null) {
27             pHead = pHead.next;
28             pBehind = pBehind.next;
29         }
30         return pBehind;
31     }
32 }
View Code

23. 链表中环的入口节点

两根指针

 1 /*
 2  public class ListNode {
 3     int val;
 4     ListNode next = null;
 5 
 6     ListNode(int val) {
 7         this.val = val;
 8     }
 9 }
10 */
11 public class Solution {
12     public ListNode EntryNodeOfLoop(ListNode pHead) {
13         if (pHead == null || pHead.next == null) {
14             return null;
15         }
16         ListNode slow = pHead;
17         ListNode fast = pHead.next;
18         while (slow != fast) {
19             if (fast == null || fast.next == null) {
20                 return null;
21             }
22             fast = fast.next.next;
23             slow = slow.next;
24         }
25         while (pHead != slow.next) {
26             pHead = pHead.next;
27             slow = slow.next;
28         }
29         return pHead;
30     }
31 }
View Code
 1 /**
 2  * Definition for singly-linked list.
 3  * 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     public ListNode detectCycle(ListNode head) {
14         // 确认该链表是否有环,并找到环内任意一个节点
15         ListNode meetingNode = meetingNode(head);
16         if (meetingNode == null) {
17             return null;
18         }
19         ListNode node = meetingNode;
20         int count = 1;
21         // 确定环的节点个数
22         while (node.next != meetingNode) {
23             node = node.next;
24             count++;
25         }
26         // 找到环的起始节点
27         ListNode pHead = head;
28         ListNode pBehind = head;
29         for (int i = 0; i < count; i++) {
30             pHead = pHead.next;
31         }
32         while (pHead != pBehind) {
33             pHead = pHead.next;
34             pBehind = pBehind.next;
35         }
36         return pHead;
37     }
38     private ListNode meetingNode(ListNode head) {
39         if (head == null || head.next == null) {
40             return null;
41         }
42         ListNode slow = head;
43         ListNode fast = head.next;
44         while (slow != fast) {
45             if (fast == null || fast.next == null) {
46                 return null;
47             }
48             slow = slow.next;
49             fast = fast.next.next;
50         }
51         return slow;
52     }
53 }
View Code

24. 翻转链表

 1 /**
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode(int x) { val = x; }
 7  * }
 8  */
 9 class Solution {
10     public ListNode reverseList(ListNode head) {
11         ListNode prev = null;
12         while (head != null) {
13             ListNode next = head.next;
14             head.next = prev;
15             prev = head;
16             head = next;
17         }
18         return prev;
19     }
20 }
View Code

25. 合并两个排序的链表

 1 /*
 2 public class ListNode {
 3     int val;
 4     ListNode next = null;
 5 
 6     ListNode(int val) {
 7         this.val = val;
 8     }
 9 }*/
10 public class Solution {
11     public ListNode Merge(ListNode list1,ListNode list2) {
12         if (list1 == null) {
13             return list2;
14         }
15         if (list2 == null) {
16             return list1;
17         }
18         ListNode head = null;
19         if (list1.val < list2.val) {
20             head = list1;
21             head.next = Merge(list1.next, list2);
22         } else {
23             head = list2;
24             head.next = Merge(list1, list2.next);
25         }
26         return head;
27     }
28 }
View Code
 1 /*
 2 public class ListNode {
 3     int val;
 4     ListNode next = null;
 5 
 6     ListNode(int val) {
 7         this.val = val;
 8     }
 9 }*/
10 public class Solution {
11     public ListNode Merge(ListNode list1,ListNode list2) {
12         ListNode dummy = new ListNode(0);
13         ListNode head = dummy;
14         while (list1 != null && list2 != null) {
15             if (list1.val < list2.val) {
16                 head.next = list1;
17                 list1 = list1.next;
18             } else {
19                 head.next = list2;
20                 list2 = list2.next;
21             }
22             head = head.next;
23         }
24         if (list1 != null) {
25             head.next = list1;
26         }
27         if (list2 != null) {
28             head.next = list2;
29         }
30         return dummy.next;
31     }
32 }
View Code

26. 树的子结构

递归遍历树

 1 /**
 2 public class TreeNode {
 3     int val = 0;
 4     TreeNode left = null;
 5     TreeNode right = null;
 6 
 7     public TreeNode(int val) {
 8         this.val = val;
 9 
10     }
11 
12 }
13 */
14 public class Solution {
15     public boolean HasSubtree(TreeNode root1,TreeNode root2) {
16         boolean result = false;
17         if (root1 != null && root2 != null) {
18             if (root1.val == root2.val) {
19                 result = DoesTree1HaveTree2(root1, root2);
20             }
21             if (!result) {
22                 result = HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
23             }
24         }
25         return result;
26     }
27     private boolean DoesTree1HaveTree2(TreeNode root1, TreeNode root2) {
28         if (root2 == null) {
29             return true;
30         }
31         if (root1 == null) {
32             return false;
33         }
34         if (root1.val != root2.val) {
35             return false;
36         }
37         return DoesTree1HaveTree2(root1.left, root2.left) && DoesTree1HaveTree2(root1.right, root2.right);
38     }
39 }
View Code

27. 二叉树的镜像

 1 /**
 2 public class TreeNode {
 3     int val = 0;
 4     TreeNode left = null;
 5     TreeNode right = null;
 6 
 7     public TreeNode(int val) {
 8         this.val = val;
 9 
10     }
11 
12 }
13 */
14 public class Solution {
15     public void Mirror(TreeNode root) {
16         if (root == null) {
17             return;
18         }
19         if (root.left == null && root.right == null) {
20             return;
21         }
22         TreeNode temp = root.left;
23         root.left = root.right;
24         root.right = temp;
25         if (root.left != null) {
26             Mirror(root.left);
27         }
28         if (root.right != null) {
29             Mirror(root.right);
30         }
31     }
32 }
View Code

28. 对称的二叉树

 1 /*
 2 public class TreeNode {
 3     int val = 0;
 4     TreeNode left = null;
 5     TreeNode right = null;
 6 
 7     public TreeNode(int val) {
 8         this.val = val;
 9 
10     }
11 
12 }
13 */
14 public class Solution {
15     boolean isSymmetrical(TreeNode pRoot) {
16         if (pRoot == null) {
17             return true;
18         }
19         return helper(pRoot.left, pRoot.right);
20     }
21     private boolean helper(TreeNode root1, TreeNode root2) {
22         if (root1 == null && root2 == null) {
23             return true;
24         }
25         if (root1 == null || root2 == null) {
26             return false;
27         }
28         if (root1.val != root2.val) {
29             return false;
30         }
31         return helper(root1.left, root2.right) && helper(root1.right, root2.left);
32     }
33 }
View Code

29. 顺时针打印矩阵

方法一

 1 import java.util.ArrayList;
 2 public class Solution {
 3     ArrayList<Integer> result = new ArrayList<>();
 4     public ArrayList<Integer> printMatrix(int [][] matrix) {
 5         if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
 6             return result;
 7         }
 8         int col = matrix[0].length;
 9         int row = matrix.length;
10         int start = 0;
11         while (start * 2 < col && start * 2 < row) {
12             printMatrixInCircle(matrix, start);
13             start++;
14         }
15         return result;
16     }
17     private void printMatrixInCircle(int[][] matrix, int start) {
18         int endX = matrix.length - 1 - start;
19         int endY = matrix[0].length - 1 - start;
20         for (int i = start; i <= endY; i++) {
21             result.add(matrix[start][i]);
22         }
23         if (start < endX) {
24             for (int i = start + 1; i  <= endX; i++) {
25                 result.add(matrix[i][endY]);
26             }
27         }
28         if (start < endX && start < endY) {
29             for (int i = endY - 1; i >= start; i--) {
30                 result.add(matrix[endX][i]);
31             }
32         }
33         if (start < endY && start < endX - 1) {
34             for (int i = endX - 1; i > start; i--) {
35                 result.add(matrix[i][start]);
36             }
37         }
38     }
39 }
View Code

方法二

 1 import java.util.ArrayList;
 2 public class Solution {
 3     public ArrayList<Integer> printMatrix(int[][] matrix) {
 4         ArrayList<Integer> res = new ArrayList<>();
 5         int row = matrix.length;
 6         int col = matrix[0].length;
 7         if (row == 0 || col == 0) {
 8             return res;
 9         }
10         int left = 0, top = 0;
11         int right = col - 1, bottom = row - 1;
12         while (left <= right && top <= bottom) {
13             for (int i = left; i <= right; i++) {
14                 res.add(matrix[top][i]);
15             }
16             for (int i = top + 1; i <= bottom; i++) {
17                 res.add(matrix[i][right]);
18             }
19             // 下面判断防止单行单列
20             if (top != bottom) {
21                 for (int i = right - 1; i >= left; i--) {
22                     res.add(matrix[bottom][i]);
23                 }
24             }
25             if (left != right) {
26                 for (int i = bottom - 1; i > top; i--) {
27                     res.add(matrix[i][left]);
28                 }
29             }
30             left++;
31             top++;
32             right--;
33             bottom--;
34         }
35         return res;
36     }
37 }
View Code

30. 包含min函数的栈

也可以采用minStack与stack的size相同

 1 import java.util.Stack;
 2 
 3 public class Solution {
 4 
 5     Stack<Integer> stack = new Stack<>();
 6     Stack<Integer> minStack = new Stack<>();
 7     public void push(int node) {
 8         stack.push(node);
 9         if (minStack.isEmpty()) {
10             minStack.push(node);
11         } else {
12             if (minStack.peek() >= node) {
13                 minStack.push(node);
14             }
15         }
16     }
17     
18     public void pop() {
19         if (stack.pop() == minStack.peek()) {
20             minStack.pop();
21         }
22     }
23     
24     public int top() {
25         return stack.peek();
26     }
27     
28     public int min() {
29         return minStack.peek();
30     }
31 }
View Code

31. 栈的压入、弹出序列

 1 import java.util.*;
 2 
 3 public class Solution {
 4     public boolean IsPopOrder(int [] pushA,int [] popA) {
 5         if (pushA == null || pushA.length == 0) {
 6             return false;
 7         }
 8         Stack<Integer> stack = new Stack<>();
 9         int popIndex = 0;
10         for (int i = 0; i < pushA.length; i++) {
11             stack.push(pushA[i]);
12             while (popIndex < popA.length && stack.peek() == popA[popIndex]) {
13                 stack.pop();
14                 popIndex++;
15             }
16         }
17         return stack.isEmpty();
18     }
19 }
View Code

32. 从上到下打印二叉树

1. 不分行从上到下打印二叉树

BFS,标配队列

 1 import java.util.*;
 2 /**
 3 public class TreeNode {
 4     int val = 0;
 5     TreeNode left = null;
 6     TreeNode right = null;
 7 
 8     public TreeNode(int val) {
 9         this.val = val;
10 
11     }
12 
13 }
14 */
15 public class Solution {
16     public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
17         ArrayList<Integer> result = new ArrayList<>();
18         if (root == null) {
19             return result;
20         }
21         LinkedList<TreeNode> queue = new LinkedList<>();
22         queue.offer(root);
23         while (!queue.isEmpty()) {
24             int size = queue.size();
25             for (int i = 0; i < size; i++) {
26                 TreeNode node = queue.poll();
27                 result.add(node.val);
28                 if (node.left != null) {
29                     queue.offer(node.left);
30                 }
31                 if (node.right != null) {
32                     queue.offer(node.right);
33                 }
34             }
35         }
36         return result;
37     }
38 }
View Code

2. 分行从上到下打印二叉树

 1 /**
 2  * Definition for a binary tree node.
 3  * public class TreeNode {
 4  *     int val;
 5  *     TreeNode left;
 6  *     TreeNode right;
 7  *     TreeNode(int x) { val = x; }
 8  * }
 9  */
10 class Solution {
11     public List<List<Integer>> levelOrder(TreeNode root) {
12         List<List<Integer>> res = new ArrayList<>();
13         if (root == null) {
14             return res;
15         }
16         Queue<TreeNode> queue = new LinkedList<>();
17         queue.offer(root);
18         while (!queue.isEmpty()) {
19             List<Integer> list = new ArrayList<>();
20             int size = queue.size();
21             for (int i = 0; i < size; i++) {
22                 TreeNode node = queue.poll();
23                 list.add(node.val);
24                 if (node.left != null) {
25                     queue.offer(node.left);
26                 }
27                 if (node.right != null) {
28                     queue.offer(node.right);
29                 }
30             }
31             res.add(list);
32         }
33         return res;
34     }
35 }
View Code

3. 之字行打印二叉树

第一种方法:

 1 /**
 2  * Definition for a binary tree node.
 3  * public class TreeNode {
 4  *     int val;
 5  *     TreeNode left;
 6  *     TreeNode right;
 7  *     TreeNode(int x) { val = x; }
 8  * }
 9  */
10 class Solution {
11     public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
12         List<List<Integer>> result = new ArrayList<>();
13         if (root == null) {
14             return result;
15         }
16         Queue<TreeNode> queue = new LinkedList<>();
17         boolean isLeftToRight = true;
18         queue.offer(root);
19         while (!queue.isEmpty()) {
20             List<Integer> level = new ArrayList<>();
21             int size = queue.size();
22             for (int i = 0; i < size; i++) {
23                 TreeNode node = queue.poll();
24                 level.add(node.val);
25                 if (node.left != null) {
26                     queue.offer(node.left);
27                 }
28                 if (node.right != null) {
29                     queue.offer(node.right);
30                 }
31             }
32             if (!isLeftToRight) {
33                 Collections.reverse(level);
34             }
35             isLeftToRight = !isLeftToRight;
36             result.add(level);
37         }
38         return result;
39     }
40 }
View Code

第二种方法:

 1 /**
 2  * Definition for a binary tree node.
 3  * public class TreeNode {
 4  *     int val;
 5  *     TreeNode left;
 6  *     TreeNode right;
 7  *     TreeNode(int x) { val = x; }
 8  * }
 9  */
10 class Solution {
11     public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
12         List<List<Integer>> res = new ArrayList<>();
13         helper(root, 0, res);
14         return res;
15     }
16     private void helper(TreeNode root, int n, List<List<Integer>> res) {
17         if (root != null) {
18             if (n >= res.size()) {
19                 List<Integer> level = new ArrayList<>();
20                 res.add(level);
21             }
22             if (n % 2 == 0) {
23                 res.get(n).add(root.val);
24             } else {
25                 res.get(n).add(0, root.val);
26             }
27             helper(root.left, n + 1, res);
28             helper(root.right, n + 1, res);
29         }
30     }
31 }
View Code

33. 二叉搜索树的后序遍历序列

 1 public class Solution {
 2     public boolean VerifySquenceOfBST(int [] sequence) {
 3         if (sequence == null || sequence.length == 0) {
 4             return false;
 5         }
 6         return helper(sequence, 0, sequence.length - 1);
 7     }
 8     private boolean helper(int[] sequence, int start, int end) {
 9         // 递归的退出条件
10         if (start >= end) {
11             return true;
12         }
13         // 找出小于根节点的索引
14         int i = end;
15         while (i > start && sequence[i - 1] > sequence[end]) {
16             i--;
17         }
18         // 验证左子树是否符合二叉搜索树的条件
19         for (int j = start; j < i; j++) {
20             if (sequence[j] > sequence[end]) {
21                 return false;
22             }
23         }
24         // 递归验证左子树和右子树
25         return helper(sequence, start, i - 1) && helper(sequence, i, end - 1);
26     }
27 }
View Code

34. 二叉树中和为某一值的路径

 1 import java.util.ArrayList;
 2 /**
 3 public class TreeNode {
 4     int val = 0;
 5     TreeNode left = null;
 6     TreeNode right = null;
 7 
 8     public TreeNode(int val) {
 9         this.val = val;
10 
11     }
12 
13 }
14 */
15 public class Solution {
16     public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
17         ArrayList<ArrayList<Integer>> result = new ArrayList<>();
18         if (root == null) {
19             return result;
20         }
21         ArrayList<Integer> list = new ArrayList<>();
22         list.add(root.val);
23         DFShelper(root, root.val, target, list, result);
24         return result;
25     }
26     private void DFShelper(TreeNode root, int curSum, int target, ArrayList<Integer> list, ArrayList<ArrayList<Integer>> result) {
27         if (root.left == null && root.right == null) {
28             if (curSum == target) {
29                 result.add(new ArrayList<>(list));
30             }
31         }
32         if (root.left != null) {
33             list.add(root.left.val);
34             DFShelper(root.left, curSum + root.left.val, target, list, result);
35             list.remove(list.size() - 1);
36         }
37         if (root.right != null) {
38             list.add(root.right.val);
39             DFShelper(root.right, curSum + root.right.val, target, list, result);
40             list.remove(list.size() - 1);
41         }
42     }
43 }
View Code

注意:

1. 每次添加list到result里,记住用new

35. 复杂链表的复制

 1 /*
 2 public class RandomListNode {
 3     int label;
 4     RandomListNode next = null;
 5     RandomListNode random = null;
 6 
 7     RandomListNode(int label) {
 8         this.label = label;
 9     }
10 }
11 */
12 public class Solution {
13     public RandomListNode Clone(RandomListNode pHead) {
14         if (pHead == null) {
15             return pHead;
16         }
17         cloneNext(pHead);
18         cloneRandom(pHead);
19         return splitList(pHead);
20     }
21     private void cloneNext(RandomListNode pHead) {
22         RandomListNode head = pHead;
23         while (head != null) {
24             RandomListNode cloneNode = new RandomListNode(head.label);
25             cloneNode.next = head.next;
26             head.next = cloneNode;
27             head = cloneNode.next;
28         }
29     }
30     private void cloneRandom(RandomListNode pHead) {
31         RandomListNode head = pHead;
32         while (head != null) {
33             RandomListNode cloneNode = head.next;
34             if (head.random != null) {
35                 cloneNode.random = head.random.next;
36             }
37             head = cloneNode.next;
38         }
39     }
40     private RandomListNode splitList(RandomListNode pHead) {
41         RandomListNode newNode = pHead.next;
42         while (pHead != null) {
43             RandomListNode cloneNode = pHead.next;
44             pHead.next = cloneNode.next;
45             pHead = pHead.next;
46             if (cloneNode.next != null) {
47                 cloneNode.next = pHead.next;
48             }
49         }
50         return newNode;
51     }
52 }
View Code
 1 import java.util.*;
 2 /*
 3 public class RandomListNode {
 4     int label;
 5     RandomListNode next = null;
 6     RandomListNode random = null;
 7 
 8     RandomListNode(int label) {
 9         this.label = label;
10     }
11 }
12 */
13 public class Solution {
14     public RandomListNode Clone(RandomListNode pHead) {
15         if (pHead == null) {
16             return pHead;
17         }
18         Map<RandomListNode, RandomListNode> mapping = new HashMap<>();
19         RandomListNode dummy = new RandomListNode(0);
20         RandomListNode prev = dummy;
21         RandomListNode newNode;
22         while (pHead != null) {
23             if (mapping.containsKey(pHead)) {
24                 newNode = mapping.get(pHead);
25             } else {
26                 newNode = new RandomListNode(pHead.label);
27                 mapping.put(pHead, newNode);
28             }
29             prev.next = newNode;
30             if (pHead.random != null) {
31                 if (mapping.containsKey(pHead.random)) {
32                     newNode.random = mapping.get(pHead.random);
33                 } else {
34                     newNode.random = new RandomListNode(pHead.random.label);
35                     mapping.put(pHead.random, newNode.random);
36                 }
37             }
38             prev = prev.next;
39             pHead = pHead.next;
40         }
41         return dummy.next;
42     }
43 }
View Code

36. 二叉搜索树与双向链表

 方法一. 采用stack

 1 import java.util.*;
 2 /**
 3 public class TreeNode {
 4     int val = 0;
 5     TreeNode left = null;
 6     TreeNode right = null;
 7 
 8     public TreeNode(int val) {
 9         this.val = val;
10 
11     }
12 
13 }
14 */
15 public class Solution {
16     public TreeNode Convert(TreeNode root) {
17         if (root == null) {
18             return root;
19         }
20         Stack<TreeNode> stack = new Stack<>();
21         TreeNode p = root;
22         TreeNode pre = null;
23         boolean isFirst = true;
24         while (p != null || !stack.isEmpty()) {
25             while (p != null) {
26                 stack.push(p);
27                 p = p.left;
28             }
29             p = stack.pop();
30             if (isFirst) {
31                 root = p;
32                 pre = p;
33                 isFirst = false;
34             } else {
35                 pre.right = p;
36                 p.left = pre;
37                 pre = p;
38             }
39             p = p.right;
40         }
41         return root;
42     }
43 }
View Code

方法二和三:

 1 /**
 2 public class TreeNode {
 3     int val = 0;
 4     TreeNode left = null;
 5     TreeNode right = null;
 6 
 7     public TreeNode(int val) {
 8         this.val = val;
 9 
10     }
11 
12 }
13 */
14 public class Solution {
15     public TreeNode Convert(TreeNode root) {
16         if (root == null || (root.left == null && root.right == null)) {
17             return root;
18         }
19         TreeNode left = Convert(root.left);
20         TreeNode p = left;
21         while (p != null && p.right != null) {
22             p = p.right;
23         }
24         if (left != null) {
25             p.right = root;
26             root.left = p;
27         }
28         TreeNode right = Convert(root.right);
29         if (right != null) {
30             root.right = right;
31             right.left = root;
32         }
33         return left != null ? left : root;
34     }
35 }
View Code
 1 /**
 2 public class TreeNode {
 3     int val = 0;
 4     TreeNode left = null;
 5     TreeNode right = null;
 6 
 7     public TreeNode(int val) {
 8         this.val = val;
 9 
10     }
11 
12 }
13 */
14 public class Solution {
15     TreeNode leftLast = null;
16     public TreeNode Convert(TreeNode root) {
17         if (root == null) {
18             return root;
19         }
20         if (root.left == null && root.right == null) {
21             leftLast = root;
22             return root;
23         }
24         TreeNode left = Convert(root.left);
25         if (left != null) {
26             leftLast.right = root;
27             root.left = leftLast;
28         }
29         leftLast = root; // 当根节点只含左子树时,则该根节点为最后一个节点
30         TreeNode right = Convert(root.right);
31         if (right != null) {
32             root.right = right;
33             right.left = root;
34         }
35         return left != null ? left : root;
36     }
37 }
View Code

注意:

1. 第三种方法的leftLast = root;  // 当根节点只含左子树时,则该根节点为最后一个节点

37. 序列化二叉树

 1 /*
 2 public class TreeNode {
 3     int val = 0;
 4     TreeNode left = null;
 5     TreeNode right = null;
 6 
 7     public TreeNode(int val) {
 8         this.val = val;
 9 
10     }
11 
12 }
13 */
14 public class Solution {
15     int index = -1;
16     String Serialize(TreeNode root) {
17         StringBuilder sb = new StringBuilder();
18         if (root == null) {
19             sb.append("#,");
20             return sb.toString();
21         }
22         sb.append(root.val + ",");
23         sb.append(Serialize(root.left));
24         sb.append(Serialize(root.right));
25         return sb.toString();
26   }
27     TreeNode Deserialize(String str) {
28         index++;
29         String[] strr = str.split(",");
30         TreeNode node = null;
31         if (!strr[index].equals("#")) {
32             node = new TreeNode(Integer.valueOf(strr[index]));
33             node.left = Deserialize(str);
34             node.right = Deserialize(str);
35         }
36         return node;
37         
38   }
39 }
View Code

38. 字符串的排列

 1 import java.util.*;
 2 public class Solution {
 3     public ArrayList<String> Permutation(String str) {
 4         ArrayList<String> result = new ArrayList<>();
 5         if (str == null || str.length() == 0) {
 6             return result;
 7         }
 8         StringBuilder sb = new StringBuilder();
 9         char[] strs = str.toCharArray();
10         Arrays.sort(strs);
11         int[] visited = new int[str.length()];
12         dfsHelper(strs, visited, sb, result);
13         return result;
14     }
15     private void dfsHelper(char[] str, int[] visited, StringBuilder sb, ArrayList<String> result) {
16         if (str.length == sb.length()) {
17             result.add(new String(sb.toString()));
18         }
19         for (int i = 0; i < str.length; i++) {
20             if (visited[i] == 1 || (i != 0 && str[i] == str[i - 1] && visited[i - 1] == 0)) {
21                 continue;
22             }
23             sb.append(str[i]);
24             visited[i] = 1;
25             dfsHelper(str, visited, sb, result);
26             sb.deleteCharAt(sb.length() - 1);
27             visited[i] = 0;
28         }
29     }
30 }
View Code

下面这种方法很巧妙,通过swap方法实现

 1 import java.util.*;
 2 public class Solution {
 3     public ArrayList<String> Permutation(String str) {
 4         ArrayList<String> result = new ArrayList<>();
 5         if (str == null || str.length() == 0) {
 6             return result;
 7         }
 8         dfsHelper(str.toCharArray(), 0, result);
 9         Collections.sort(result);
10         return result;
11     }
12     private void dfsHelper(char[] str, int index, ArrayList<String> result) {
13         if (index == str.length - 1) {
14             String val = String.valueOf(str);
15             if (!result.contains(val)) {
16                 result.add(val);
17             }
18         }
19         for (int i = index; i < str.length; i++) {
20             swap(str, i, index);
21             dfsHelper(str, index + 1, result);
22             swap(str, i, index);
23         }
24     }
25     private void swap(char[] str, int i, int j) {
26         if (i != j) {
27             char temp = str[i];
28             str[i] = str[j];
29             str[j] = temp;
30         }
31     }
32 }
View Code

39. 数组中出现次数超过一半的数字

投票算法

 1 public class Solution {
 2     public int MoreThanHalfNum_Solution(int [] array) {
 3         if (array == null || array.length == 0) {
 4             return 0;
 5         }
 6         int target = array[0];
 7         int count = 1;
 8         for (int i = 1; i < array.length; i++) {
 9             if (count == 0) {
10                 target = array[i];
11                 count++;
12             } else if (array[i] == target) {
13                 count++;
14             } else {
15                 count--;
16             }
17         }
18         count = 0;
19         for (int i = 0; i < array.length; i++) {
20             if (array[i] == target) {
21                 count++;
22             }
23         }
24         return count > array.length / 2 ? target : 0;
25     }
26 }
View Code

40. 最小的k个数

方法一:采用最大堆

 1 import java.util.*;
 2 public class Solution {
 3     public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
 4         ArrayList<Integer> result = new ArrayList<>();
 5         if (input == null || input.length == 0 || input.length < k) {
 6             return result;
 7         }
 8         Queue<Integer> maxHeap = new PriorityQueue<>(input.length, new Comparator<Integer>() {
 9             public int compare(Integer o1, Integer o2) {
10                 return o2 - o1;
11             }
12         });
13         for (int num : input) {
14             maxHeap.offer(num);
15             if (maxHeap.size() > k) {
16                 maxHeap.poll();
17             }
18         }
19         for (int num : maxHeap) {
20             result.add(num);
21         }
22         return result;
23     }
24 }
View Code

方法二:采用最小堆

 1 import java.util.*;
 2 public class Solution {
 3     public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
 4         ArrayList<Integer> result = new ArrayList<>();
 5         if (input == null || input.length == 0 || input.length < k) {
 6             return result;
 7         }
 8         Queue<Integer> minHeap = new PriorityQueue<>();
 9         for (int num : input) {
10             minHeap.offer(num);
11         }
12         for (int i = 0; i < k; i++) {
13             result.add(minHeap.poll());
14         }
15         return result;
16     }
17 }
View Code

41. 数据流中的中位数

 1 import java.util.*;
 2 public class Solution {
 3     Queue<Integer> minHeap = new PriorityQueue<>();
 4     Queue<Integer> maxHeap = new PriorityQueue<>(new Comparator<Integer>() {
 5         public int compare(Integer o1, Integer o2) {
 6             return o2 - o1;
 7         }
 8     });
 9     int count = 0;
10 
11     public void Insert(Integer num) {
12         if (count % 2 == 0) {
13             if (maxHeap.size() != 0 && num < maxHeap.peek()) {
14                 maxHeap.offer(num);
15                 minHeap.offer(maxHeap.poll());
16             } else {
17                 minHeap.offer(num);
18             }
19         } else {
20             if (minHeap.size() != 0 && num > minHeap.peek()) {
21                 minHeap.offer(num);
22                 maxHeap.offer(minHeap.poll());
23             } else {
24                 maxHeap.offer(num);
25             }
26         }
27         count++;
28     }
29 
30     public Double GetMedian() {
31         if (count % 2 == 0) {
32             return new Double((minHeap.peek() + maxHeap.peek()) / 2.0);
33         } else {
34             return new Double(minHeap.peek());
35         }
36     }
37 
38 
39 }
View Code

42. 连续子数组的最大和

 1 public class Solution {
 2     public int FindGreatestSumOfSubArray(int[] array) {
 3         int max = Integer.MIN_VALUE;
 4         int minSum = 0;
 5         int sum = 0;
 6         for (int i = 0; i < array.length; i++) {
 7             sum += array[i];
 8             max = Math.max(max, sum - minSum);
 9             minSum = Math.min(minSum, sum);
10         }
11         return max;
12     }
13 }
View Code

注意:

1. 先求最大值,在求解目前的最小和

以下还有一个方法:

 1 public class Solution {
 2     public int FindGreatestSumOfSubArray(int[] array) {
 3         if (array == null || array.length == 0) {
 4             return -1;
 5         }
 6         int curSum = 0;
 7         int max = Integer.MIN_VALUE;
 8         for (int num : array) {
 9             if (curSum <= 0) {
10                 curSum = num; // 如果当前和已经小于零,则可以直接抛弃以前的和
11             } else {
12                 curSum += num;
13             }
14             max = Math.max(max, curSum);
15         }
16         return max;
17     }
18 }
View Code

43. 1~n整数中1出现的次数

 1 public class Solution {
 2     public int NumberOf1Between1AndN_Solution(int n) {
 3         int ones = 0;
 4         for (int m = 1; m <= n; m *= 10) {
 5             int a = n / m;
 6             int b = n % m;
 7             ones += (a + 8) / 10 * m + (a % 10 == 1 ? b + 1: 0);
 8         }
 9         return ones;
10     }
11 }
View Code

45. 把数组排成最小的数

 1 import java.util.*;
 2 
 3 public class Solution {
 4     public String PrintMinNumber(int [] numbers) {
 5         String result = "";
 6         List<Integer> list = new ArrayList<>();
 7         for (int num : numbers) {
 8             list.add(num);
 9         }
10         Collections.sort(list, new Comparator<Integer>() {
11             public int compare(Integer o1, Integer o2) {
12                 String str1 = o1 + "" + o2;
13                 String str2 = o2 + "" + o1;
14                 return str1.compareTo(str2);
15             }
16         });
17         for (int num : list) {
18             result += num;
19         }
20         return result;
21     }
22 }
View Code

46. 把数字翻译成字符串

 1 public class Solution {
 2     public int getTranslationCount(int number) {
 3         if (number < 0) {
 4             return 0;
 5         }
 6         String str = number + "";
 7         return getTranslationCount(str);
 8     }
 9     private int getTranslationCount(String str) {
10         int len = str.length();
11         int[] counts = new int[len];
12         int count = 0;
13         for (int i = len - 1; i >= 0; i--) {
14             if (i < len - 1) {
15                 count = counts[i + 1];
16             } else {
17                 count = 1;
18             }
19             if (i < len - 1) {
20                 int digits1 = str.charAt(i) - '0';
21                 int digits2 = str.charAt(i + 1) - '0';
22                 int num = digits1 * 10 + digits2;
23                 if (num > 9 && num < 26) {
24                     if (i < len - 2) {
25                         count += counts[i + 2];
26                     } else {
27                         count += 1;
28                     }
29                 }
30             }
31             counts[i] = count;
32         }
33         return counts[0];
34     }
35 }
View Code

47. 礼物的最大价值

方法一:没有优化

 1 public class digitAtIndex {
 2     private static int getMaxValue(int[][] matrix) {
 3         int row = matrix.length;
 4         int col = matrix[0].length;
 5         if (matrix == null || row == 0 || col == 0) {
 6             return 0;
 7         }
 8         int[][] maxValues = new int[row][col];
 9         for (int i = 0; i < row; i++) {
10             for (int j = 0; j < col; j++) {
11                 int left = 0;
12                 int up = 0;
13                 if (j > 0) {
14                     left = maxValues[i][j - 1];
15                 }
16                 if (i > 0) {
17                     up = maxValues[i - 1][j];
18                 }
19                 maxValues[i][j] = Math.max(left, up) + matrix[i][j];
20             }
21         }
22         int maxValue = maxValues[row - 1][col - 1];
23         return maxValue;
24     }
25     public static void main(String[] args) {
26         int[][] number = {{1, 10, 3, 8}, {12, 2, 9, 6}, {5, 7, 4, 11}, {3, 7, 16, 5}};
27         System.out.println(getMaxValue(number));
28     }
29 }
View Code

方法二. 优化后的代码,由于没有必要存储第i-2行的数值,所以最大价值的数组可以表示为一位数组,意义如下

  • 数组的前面j个数字分别表示当前第i行的前面j个格子的礼物的最大价值
  • 之后的数字表示分别保存前面第i-1行的n-j个格子礼物的最大价值
 1 public class Solution {
 2     private static int getMaxValue2(int[][] matrix) {
 3         int row = matrix.length;
 4         int col = matrix[0].length;
 5         if (matrix == null || row == 0 || col == 0) {
 6             return 0;
 7         }
 8         int[] maxValues = new int[col];
 9         for (int i = 0; i < row; i++) {
10             for (int j = 0; j < col; j++) {
11                 int left = 0;
12                 int up = 0;
13                 if (i > 0) {
14                     up = maxValues[j];
15                 }
16                 if (j > 0) {
17                     left = maxValues[j - 1];
18                 }
19                 maxValues[j] = Math.max(left, up) + matrix[i][j];
20             }
21         }
22         return maxValues[col - 1];
23     }
24     public static void main(String[] args) {
25         int[][] number = {{1, 10, 3, 8}, {12, 2, 9, 6}, {5, 7, 4, 11}, {3, 7, 16, 5}};
26         System.out.println(getMaxValue2(number));
27     }
28 }
View Code

48. 最长不含重复字符的子字符串

方法一:不太明白curLength的更新

 1 public class longestSubstring {
 2     private static int longestSubstring(String str) {
 3         if (str == null || str.length() == 0) {
 4             return -1;
 5         }
 6         int[] position = new int[26];
 7         for (int i = 0; i < 26; i++) {
 8             position[i] = -1;
 9         }
10         int curLength = 0;
11         int maxLength = 0;
12         for (int i = 0; i < str.length(); i++) {
13             int preIndex = position[str.charAt(i) - 'a'];
14             if (preIndex < 0 || i - preIndex > curLength) {
15                 curLength++;
16             } else {
17                 if (curLength > maxLength) {
18                     maxLength = curLength;
19                 }
20                 curLength = i - preIndex;
21             }
22             position[str.charAt(i) - 'a'] = i;
23         }
24         if (curLength > maxLength) {
25             maxLength = curLength;
26         }
27         return maxLength;
28     }
29     public static void main(String[] args) {
30         String str = "arabcacfr";
31         System.out.println(longestSubstring(str));
32     }
33 }
View Code

方法二:

 1 import java.util.HashMap;
 2 import java.util.Map;
 3 
 4 public class myTest {
 5     private static int longestSubstring(String str) {
 6         if (str == null || str.length() == 0) {
 7             return -1;
 8         }
 9         Map<Character, Integer> mapping = new HashMap<>();
10         int max = 0;
11         for (int i = 0, j = 0; i < str.length(); i++) {
12             // 比较巧妙
13             /**
14              * "arabcacfr"
15              * 当遇到最后一个字母r时,此时该字母前面也出现过
16              * j = 3,即上一次重复字母出现位置+1
17              * 与字母r上一次出现的位置+1,进行比较,取值最大的
18              * 以上过程保证了该子串不会出现重复字母
19              */
20             if (mapping.containsKey(str.charAt(i))) {
21                 j = Math.max(j, mapping.get(str.charAt(i)) + 1);
22             }
23             mapping.put(str.charAt(i), i);
24             max = Math.max(max, i - j + 1);
25         }
26         return max;
27     }
28     public static void main(String[] args) {
29         String str = "arabcacfr";
30         System.out.println(longestSubstring(str));
31     }
32 }
View Code

49. 丑数

 1 import java.util.*;
 2 public class Solution {
 3     public int GetUglyNumber_Solution(int index) {
 4         if (index == 0) {
 5             return 0;
 6         }
 7         ArrayList<Integer> uglys = new ArrayList<>();
 8         uglys.add(1);
 9         int index2 = 0;
10         int index3 = 0;
11         int index5 = 0;
12         for (int i = 1; i < index; i++) {
13             int num2 = uglys.get(index2) * 2;
14             int num3 = uglys.get(index3) * 3;
15             int num5 = uglys.get(index5) * 5;
16             int min = Math.min(num2, Math.min(num3, num5));
17             uglys.add(min);
18             // 当为6时,index2与index3都要变化
19             if (min == num2) {
20                 index2++;
21             } 
22             if (min == num3) {
23                 index3++;
24             } 
25             if (min == num5) {
26                 index5++;
27             }
28         }
29         return uglys.get(index - 1);
30     }
31 }
View Code

50. 第一个只出现一次的字符

 1 public class Solution {
 2     public int FirstNotRepeatingChar(String str) {
 3         if (str == null || str.length() == 0) {
 4             return -1;
 5         }
 6         int[] position = new int[256];
 7         for (int i = 0; i < str.length(); i++) {
 8             position[str.charAt(i)]++;
 9         }
10         for (int i = 0; i < str.length(); i++) {
11             if (position[str.charAt(i)] == 1) {
12                 return i;
13             }
14         }
15         return -1;
16     }
17 }
View Code

51. 数组中的逆序对

 

52. 两个链表的第一个公共节点

方法一:

 1 /*
 2 public class ListNode {
 3     int val;
 4     ListNode next = null;
 5 
 6     ListNode(int val) {
 7         this.val = val;
 8     }
 9 }*/
10 public class Solution {
11     public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
12         if (pHead1 == null || pHead2 == null) {
13             return null;
14         }
15         ListNode tail1 = pHead1;
16         while (tail1.next != null) {
17             tail1 = tail1.next;
18         }
19         tail1.next = pHead1;
20         ListNode result = helper(pHead2);
21         tail1.next = null;
22         return result;
23     }
24     private ListNode helper(ListNode head) {
25         ListNode fast = head.next;
26         ListNode slow = head;
27         while (slow != fast) {
28             if (fast == null || fast.next == null) {
29                 return null;
30             }
31             fast = fast.next.next;
32             slow = slow.next;
33         }
34         while (head != slow.next) {
35             head = head.next;
36             slow = slow.next;
37         }
38         return head;
39     }
40 }
View Code

方法二:

 1 /*
 2 public class ListNode {
 3     int val;
 4     ListNode next = null;
 5 
 6     ListNode(int val) {
 7         this.val = val;
 8     }
 9 }*/
10 public class Solution {
11     public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
12         if (pHead1 == null || pHead2 == null) {
13             return null;
14         }
15         ListNode p1 = pHead1;
16         ListNode p2 = pHead2;
17         while (p1 != p2) {
18             p1 = p1 == null ? pHead2 : p1.next;
19             p2 = p2 == null ? pHead1 : p2.next;
20         }
21         return p1;
22     }
23 }
View Code

方法三:

 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     public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
14         if (headA == null || headB == null) {
15             return null;
16         }
17         Stack<ListNode> stackA = new Stack<>();
18         Stack<ListNode> stackB = new Stack<>();
19         while (headA != null || headB != null) {
20             if (headA != null) {
21                 stackA.push(headA);
22                 headA = headA.next;
23             }
24             if (headB != null) {
25                 stackB.push(headB);
26                 headB = headB.next;
27             }
28         }
29         ListNode common = null;
30         while (!stackA.isEmpty() && !stackB.isEmpty()) {
31             ListNode nodeA = stackA.pop();
32             ListNode nodeB = stackB.pop();
33             if (nodeA.val != nodeB.val) {
34                 break;
35             }
36             common = new ListNode(nodeA.val);
37         }
38         return common;
39     }
40 }
View Code

方法四:

 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     public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
14         if (headA == null || headB == null) {
15             return null;
16         }
17         int lenA = 0;
18         int lenB = 0;
19         ListNode nodeA = headA;
20         ListNode nodeB = headB;
21         while (nodeA != null || nodeB != null) {
22             if (nodeA != null) {
23                 lenA++;
24                 nodeA = nodeA.next;
25             }
26             if (nodeB != null) {
27                 lenB++;
28                 nodeB = nodeB.next;
29             }
30         }
31         int steps = Math.abs(lenA - lenB);
32         while (steps != 0) {
33             if (lenA > lenB) {
34                 headA = headA.next;
35             } else {
36                 headB = headB.next;
37             }
38             steps--;
39         }
40         while (headA != null && headB != null) {
41             if (headA.val == headB.val) {
42                 return headA;
43             }
44             headA = headA.next;
45             headB = headB.next;
46         }
47         return null;
48     }
49 }
View Code

53. 在排序数字中查找数字

一. 数字在排序数组中出现的次数

 1 public class Solution {
 2     public int GetNumberOfK(int [] array , int k) {
 3         if (array == null || array.length == 0) {
 4             return 0;
 5         }
 6         int start = findFirst(array, k);
 7         int end = findEnd(array, k);
 8         if (start == -1 || end == -1) {
 9             return 0;
10         }
11         return end - start + 1;
12     }
13     private int findFirst(int[] array, int k) {
14         int start = 0;
15         int end = array.length - 1;
16         while (start + 1 < end) {
17             int mid = start + (end - start) / 2;
18             if (array[mid] >= k) {
19                 end = mid;
20             } else {
21                 start = mid;
22             }
23         }
24         if (array[start] == k) {
25             return start;
26         } else if (array[end] == k) {
27             return end;
28         }
29         return -1;
30     }
31     private int findEnd(int[] array, int k) {
32         int start = 0;
33         int end = array.length - 1;
34         while (start + 1 < end) {
35             int mid = start + (end - start) / 2;
36             if (array[mid] <= k) {
37                 start = mid;
38             } else {
39                 end = mid;
40             }
41         }
42         if (array[end] == k) {
43             return end;
44         } else if (array[start] == k) {
45             return start;
46         }
47         return -1;
48     }
49 }
View Code

二. 0 ~ n - 1中缺失的数字

 1 class test {
 2     private static int getMissingNumber(int[] array) {
 3         if (array == null || array.length == 0) {
 4             return -1;
 5         }
 6         int start = 0;
 7         int end = array.length - 1;
 8         while (start + 1 < end) {
 9             int mid = start + (end - start) / 2;
10             if (array[mid] != mid) {
11                 if (mid == 0 || array[mid - 1] == mid - 1) {
12                     return mid;
13                 }
14                 end = mid;
15             } else {
16                 start = mid;
17             }
18         }
19         if (array[start] != start) {
20             return start;
21         }
22         if (array[end] != end) {
23             return end;
24         }
25         return -1;
26     }
27     public static void main (String[] args) {
28         int[] array = {0, 1, 2, 3, 5, 6, 7, 8, 9};
29         int[] array1 = {0, 1, 2, 3, 4, 5, 6, 8, 9};
30         System.out.println(getMissingNumber(array));
31         System.out.println(getMissingNumber(array1));
32     }
33 }
View Code

三. 数组中数值与下标值相等的元素

 1 public class NumberSameAsIndex {
 2     private static int numberSameAsIndex(int[] array) {
 3         if (array == null || array.length == 0) {
 4             return -1;
 5         }
 6         int start = 0;
 7         int end = array.length - 1;
 8         while (start + 1 < end) {
 9             int mid = start + (end - start) / 2;
10             if (array[mid] == mid) {
11                 return mid;
12             } else if (array[mid] < mid) {
13                 start = mid;
14             } else {
15                 end = mid;
16             }
17         }
18         if (array[start] == start) {
19             return start;
20         }
21         return end;
22     }
23     public static void main(String[] args) {
24         int[] array = {-3, -1, 1, 3, 5};
25         System.out.println(numberSameAsIndex(array));
26     }
27 }
View Code

54. 二叉搜索树的第k大节点

 1 /**
 2  * @author hta
 3  * @since 下午6:20 17-11-26
 4  */
 5 public class test {
 6     static class TreeNode {
 7         TreeNode left = null;
 8         TreeNode right = null;
 9         int val;
10         TreeNode (int val) {
11             this.val = val;
12         }
13     }
14     private static int globalK = 0;
15     private static TreeNode KthNode (TreeNode root, int k) {
16         if (root == null || k == 0) {
17             return null;
18         }
19         globalK = k;
20         return KthNodeHelper(root);
21     }
22     private static TreeNode KthNodeHelper(TreeNode root) {
23         TreeNode target = null;
24         if (root.left != null) {
25             target = KthNodeHelper(root.left);
26         }
27         if (target == null) {
28             if (globalK == 1) {
29                 target = root;
30             }
31             globalK--;
32         }
33         if (target == null && root.right != null) {
34             target = KthNodeHelper(root.right);
35         }
36         return target;
37     }
38     public static void main (String[] args) {
39         TreeNode root = new TreeNode(5);
40         TreeNode left = new TreeNode(3);
41         TreeNode right = new TreeNode(7);
42         root.left = left;
43         root.right = right;
44         left.left = new TreeNode(2);
45         left.right = new TreeNode(4);
46         right.left = new TreeNode(6);
47         right.right = new TreeNode(8);
48         System.out.println(KthNode(root, 3).val);
49     }
50 }
View Code

55. 二叉树的深度

一. 二叉树深度

 1 /**
 2 public class TreeNode {
 3     int val = 0;
 4     TreeNode left = null;
 5     TreeNode right = null;
 6  
 7     public TreeNode(int val) {
 8         this.val = val;
 9  
10     }
11  
12 }
13 */
14 public class Solution {
15     public int TreeDepth(TreeNode root) {
16         if (root == null) {
17             return 0;
18         }
19         int leftDepth = TreeDepth(root.left);
20         int rightDepth = TreeDepth(root.right);
21         return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
22     }
23 }
View Code
 1 /**
 2 public class TreeNode {
 3     int val = 0;
 4     TreeNode left = null;
 5     TreeNode right = null;
 6 
 7     public TreeNode(int val) {
 8         this.val = val;
 9 
10     }
11 
12 }
13 */
14 public class Solution {
15     private int depth = 0;
16     public int TreeDepth(TreeNode root) {
17         depthHelper(root, 1);
18         return depth;
19     }
20     private void depthHelper(TreeNode root, int curDepth) {
21         if (root == null) {
22             return;
23         }
24         if (depth < curDepth) {
25             depth = curDepth;
26         }
27         depthHelper(root.left, curDepth + 1);
28         depthHelper(root.right, curDepth + 1);
29     }
30 }
View Code

二. 平衡二叉树

 1 public class Solution {
 2     private class ResultType {
 3         boolean isBalanced;
 4         int maxDepth;
 5         ResultType(boolean isBalanced, int maxDepth) {
 6             this.isBalanced = isBalanced;
 7             this.maxDepth = maxDepth;
 8         }
 9     }
10     public boolean IsBalanced_Solution(TreeNode root) {
11         if (root == null) {
12             return true;
13         }
14         return helper(root).isBalanced;
15     }
16     private ResultType helper(TreeNode root) {
17         if (root == null) {
18             return new ResultType(true, 0);
19         }
20         ResultType left = helper(root.left);
21         ResultType right = helper(root.right);
22         if (!left.isBalanced || !right.isBalanced) {
23             return new ResultType(false, -1);
24         }
25         if (Math.abs(left.maxDepth - right.maxDepth) > 1) {
26             return new ResultType(false, -1);
27         }
28         return new ResultType(true, Math.max(left.maxDepth, right.maxDepth) + 1);
29     }
30 }
View Code

56. 数组中数字的出现次数

一. 数组中只出现一次的两个数字

思路:仿照只出现一次的一个数字的过程,将数组按照最后异或结果的某一位是否为1将数组划分为两个数组

 1 //num1,num2分别为长度为1的数组。传出参数
 2 //将num1[0],num2[0]设置为返回结果
 3 public class Solution {
 4     public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
 5         if (array == null || array.length == 0) {
 6             return;
 7         }
 8         int result = 0;
 9         for (int num : array) {
10             result ^= num;
11         }
12         int indexOfBit1 = findIndex(result);
13         for (int num : array) {
14             if (isBit1(num, indexOfBit1)) {
15                 num1[0] ^= num;
16             } else {
17                 num2[0] ^= num;
18             }
19         }
20     }
21     private int findIndex(int result) {
22         int index = 0;
23         while ((result & 1) == 0 && index < 32) {
24             result = result >> 1;
25             index++;
26         }
27         return index;
28     }
29     private boolean isBit1(int num, int index) {
30         num = num >> index;
31         if ((num & 1) == 1) {
32             return true;
33         }
34         return false;
35     }
36 }
View Code

二. 数组中唯一只出现一次的数字

 1 /**
 2  * @author hta
 3  * @since 下午9:07 17-11-26
 4  */
 5 public class FindNumberAppearingOnce {
 6     private static int findNumberAppearingOnce(int[] array) {
 7         if (array == null || array.length == 0) {
 8             return -1;
 9         }
10         int[] bitSum = new int[32];
11         for (int i = 0; i < array.length; i++) {
12             int bitMask = 1;
13             // 记得bit的顺序
14             for (int j = 31; j >= 0; j--) {
15                 int bit = array[i] & bitMask;
16                 if (bit != 0) {
17                     bitSum[j]++;
18                 }
19                 bitMask <<= 1;
20             }
21         }
22         int result = 0;
23         // 记得bit的顺序
24         for (int i = 0; i < 32; i++) {
25             result <<= 1;
26             result += bitSum[i] % 3;
27         }
28         return result;
29     }
30     public static void main(String[] args) {
31         int[] array = {1, 1, 1, 2, 2, 2, 3, 5, 5, 5};
32         System.out.println(findNumberAppearingOnce(array));
33     }
34 }
View Code

57. 和为s的数字

一. 和为s的两个数字

 1 import java.util.ArrayList;
 2 public class Solution {
 3     public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
 4         ArrayList<Integer> result = new ArrayList<>();
 5         if (array == null || array.length == 0) {
 6             return result;
 7         }
 8         int start = 0;
 9         int end = array.length - 1;
10         while (start < end) {
11             int curSum = array[start] + array[end];
12             if (curSum == sum) {
13                 result.add(array[start]);
14                 result.add(array[end]);
15                 return result;
16             } else if (curSum > sum) {
17                 end--;
18             } else {
19                 start++;
20             }
21         }
22         return result;
23     }
24 }
View Code

二. 和为s的连续正数序列

 1 import java.util.ArrayList;
 2 public class Solution {
 3     public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
 4         ArrayList<ArrayList<Integer>> result = new ArrayList<>();
 5         if (sum < 3) {
 6             return result;
 7         }
 8         int small = 1;
 9         int big = 2;
10         int middle = (sum + 1) / 2;
11         int curSum = small + big;
12         while (small < middle) {
13             if (curSum == sum) {
14                 result.add(getList(small, big));
15             }
16             while (curSum > sum && small < middle) {
17                 curSum -= small;
18                 small++;
19                 if (curSum == sum) {
20                     result.add(getList(small, big));
21                 }
22             }
23             big++;
24             curSum += big;
25         }
26         return result;
27     }
28     private ArrayList<Integer> getList(int small, int big) {
29         ArrayList<Integer> list = new ArrayList<>();
30         for (int i = small; i <= big; i++) {
31             list.add(i);
32         }
33         return list;
34     }
35 }
View Code

58. 翻转字符串

一. 翻转单词顺序

 1 public class Solution {
 2     public String ReverseSentence(String str) {
 3         if (str.trim().equals("")) {
 4             return str;
 5         }
 6         String[] strs = str.split(" ");
 7         StringBuffer sb = new StringBuffer();
 8         for (int i = strs.length - 1; i >= 0; i--) {
 9             sb.append(strs[i]);
10             if (i > 0) {
11                 sb.append(" ");
12             }
13         }
14         return sb.toString();
15     }
16 }
View Code

二. 左旋转字符串

 1 public class Solution {
 2     public String LeftRotateString(String str,int n) {
 3         if (str == null || str.length() == 0 || n == 0) {
 4             return str;
 5         }
 6         n %= str.length();
 7         char[] chars = str.toCharArray();
 8         reverse(chars, 0, n - 1);
 9         reverse(chars, n, str.length() - 1);
10         reverse(chars, 0, str.length() - 1);
11         return new String(chars);
12     }
13     private void reverse(char[] chars, int start, int end) {
14         for (int i = start, j = end; i < j; i++, j--) {
15             char temp = chars[i];
16             chars[i] = chars[j];
17             chars[j] = temp;
18         }
19     }
20 }
View Code

59. 队列的最大值

一. 滑动窗口的最大值

 1 import java.util.*;
 2 public class Solution {
 3     public ArrayList<Integer> maxInWindows(int [] num, int size) {
 4         ArrayList<Integer> result = new ArrayList<>();
 5         if (num == null || num.length == 0 || size == 0) {
 6             return result;
 7         }
 8         int index = 0;
 9         while (index <= num.length - size) {
10             int max = Integer.MIN_VALUE;
11             for (int i = index; i < index + size; i++) {
12                 max = Math.max(max, num[i]);
13             }
14             result.add(max);
15             index++;
16         }
17         return result;
18     }
19 }
View Code
 1 import java.util.*;
 2 public class Solution {
 3     public ArrayList<Integer> maxInWindows(int [] num, int size) {
 4         ArrayList<Integer> result = new ArrayList<>();
 5         if (num.length < size || size < 1) {
 6             return result;
 7         }
 8         ArrayDeque<Integer> index = new ArrayDeque<>();
 9         int begin;
10         for (int i = 0; i < num.length; i++) {
11             begin = i - size + 1;
12             if (index.isEmpty()) {
13                 index.offer(i);
14             } else if (begin > index.peek()) {
15                 index.poll();
16             }
17             while (!index.isEmpty() && num[i] >= num[index.peekLast()]) {
18                 index.pollLast();
19             }
20             index.add(i);
21             if (begin >= 0) {
22                 result.add(num[index.peek()]);
23             }
24         }
25         return result;
26     }
27 }
View Code

二. 队列的最大值

 1 import java.util.ArrayDeque;
 2 
 3 public class QueueWithMax {
 4     private class InternalData {
 5         int index;
 6         int number;
 7         InternalData(int index, int number) {
 8             this.index = index;
 9             this.number = number;
10         }
11     }
12     private ArrayDeque<InternalData> queue;
13     private ArrayDeque<InternalData> maxQueue;
14     private int curIndex;
15     QueueWithMax() {
16         queue = new ArrayDeque<>();
17         maxQueue = new ArrayDeque<>();
18     }
19 
20     public void offer(int num) {
21         while (!maxQueue.isEmpty() && num >= maxQueue.peekLast().number) {
22             maxQueue.pollLast();
23         }
24         InternalData internalData = new InternalData(curIndex, num);
25         queue.offer(internalData);
26         maxQueue.offer(internalData);
27         curIndex++;
28     }
29 
30     public int poll() throws Exception {
31         if (maxQueue.isEmpty()) {
32             throw new Exception("queue is empty");
33         }
34         if (queue.peek().index == maxQueue.peek().index) {
35             maxQueue.poll();
36         }
37         return queue.poll().number;
38     }
39 
40     public int max() throws Exception {
41         if (maxQueue.isEmpty()) {
42             throw new Exception("queue is empty");
43         }
44         return maxQueue.peek().number;
45     }
46 }
47 class test {
48     public static void main(String[] args) throws Exception {
49         int[] array = {7, 8, 5, 4, 3, 6, 9};
50         QueueWithMax queue = new QueueWithMax();
51         queue.offer(array[0]);
52         queue.offer(array[1]);
53         queue.offer(array[2]);
54         queue.offer(array[6]);
55         queue.offer(array[5]);
56         queue.poll();
57         System.out.println(queue.max());
58     }
59 }
View Code

60. n个骰子的点数

 

 

posted on 2017-12-04 18:26  Toyan  阅读(326)  评论(0编辑  收藏  举报