剑指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 }
第二种方法:不修改原数组中元素的位置,时间复杂度: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 }
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 }
第二种方法:直接在原字符串中变化
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 }
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 }
第二种方法:使用栈
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 }
7. 重建二叉树
总结:
- 前序遍历
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 }
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 }
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 }
- 中序遍历
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 }
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 }
- 后序遍历
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 }
后序遍历的非递归确实没看懂
题目:
思路:在前序遍历结果中找开始节点与结束节点,不要忘记减去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 }
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 }
用两个队列实现一个栈,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 }
跳台阶
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 }
变态跳台阶
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 }
矩形覆盖
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
通过减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 }
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 }
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 }
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 }
注意:
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 }
注意:
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 }
需要保证相对顺序
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
方法二
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 }
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 }
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 }
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 }
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 }
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 }
第二种方法:
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 }
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 }
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 }
注意:
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 }
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 }
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 }
方法二和三:
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 }
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 }
注意:
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 }
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 }
下面这种方法很巧妙,通过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 }
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 }
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 }
方法二:采用最小堆
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 }
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 }
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 }
注意:
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 }
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 }
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 }
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 }
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 }
方法二. 优化后的代码,由于没有必要存储第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 }
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 }
方法二:
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 }
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 }
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 }
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 }
方法二:
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 }
方法三:
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 }
方法四:
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 }
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 }
二. 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 }
三. 数组中数值与下标值相等的元素
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 }
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 }
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 }
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 }
二. 平衡二叉树
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 }
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 }
二. 数组中唯一只出现一次的数字
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 }
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 }
二. 和为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 }
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 }
二. 左旋转字符串
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 }
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 }
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 }
二. 队列的最大值
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 }
60. n个骰子的点数