剑指offer——Java版
- 以下按照出现频率进行排序
-
-
- 24 反转列表
- 03 数组中重复的数字
- 09 用两个栈实现队列
- 38 字符串的排列
- 51 数组中的逆序对
- 22 链表中倒数第k个结点
- 11 旋转数组的最小数
- 29 顺时针打印矩阵
- 07 重建二叉树
- 06 从尾到头打链表
- 04 二维数组中的查找
- 20 表示数值的字符串
- 48 最长不含重复字符的子字符串
- 40 最小的k个数
- 10-I 斐波那契数列
- 13 机器人运动轨迹
- 25 合并两个排序的链表
- 26 树的子结构
- 10-II 青蛙跳台阶问题
- 59-I 滑动窗口最大值
- 45 把数组排成最小的数
- 62 圆圈中最后剩下的数字
- 32-I 从上到下打印二叉树(从左到右放一层)
- 46 把数字翻译成字符串
- 17 打印从1到最大的n位数
- 05 替换空格
- 34 二叉树中和为某一值的路径
- 63 股票的最大利润
- 42 连续子数组的最大和
- 36 二叉搜索树与双向链表
- 57 和为s的两个数字
- 61 扑克牌中的顺子
- 14-I 剪绳子
- 50 第一个只出现一次的字符
- 57-II 和为s的连续正整数序列
- 27 二叉树的镜像
- 12 矩阵中的路径
- 39 数组中出现的次数
- 49 丑数
- 55-I 二叉树的深度
- 32-II 从上到下打印二叉树(从左到右分层)
- 30 包含min函数的栈
- 56-I 数组中数字出现次数(两个出现一次,其他都两次)
- 53-II 0~n-1中缺失的数字
- 18 删除链表的节点
- 33 二叉搜索树的后序遍历序列
- 68-II 二叉树的最近公共祖先(无序)
- 58-I 翻转单词的顺序
- 32-III 从上到下打印二叉树(之字形)
- 60 n个骰子的点数
- 66 构建乘机数组
- 58-II 左旋转字符串
- 47 礼物的最大价值
- 35 复杂链表的复制
- 67 把字符串转换成整数
- 19 正则表达式匹配
- 21 调整数组顺序使奇数位于偶数前面
- 55-II 平衡二叉树
- 64 求1+2+...+n
- 59-II 队列的最大值
- 15 二进制中1的个数
- 56-II 数组中1的个数
- 54 二叉搜索树的第k大节点
- 28 对称的二叉树
- 37 序列化二叉树
- 43 1~n整数中1出现的次数
- 68-I 二叉树搜索树的最近公共祖先
- 41 数据流的中位数
- 52 两个链表的第一个公共节点
- 65 不用加减乘除做加法
- 44 数字序列中某一位的数字
- 53-I 在排序数组中查抄数字
- 14-II 剪绳子II
- 31 栈的压入、弹出序列
- 16 数值的整数次方
以下按照出现频率进行排序
常见的结构体定义
链表
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
树
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
24 反转列表
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
简单 |
A |
链表 |
已掌握 |
24 反转列表 |
- 题目描述:
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
- 示例
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
class Solution {
public ListNode reverseList(ListNode head) {
ListNode preNode = null;
ListNode pNode = head;
ListNode pNext;
while(pNode != null){
pNext = pNode.next;
pNode.next = preNode;
preNode = pNode;
pNode = pNext;
}
return preNode;
}
}
- 知识点总结
需要三个节点来存储前中后,且要保证pNode!=null的前提下才给next赋值
03 数组中重复的数字
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
简单 |
A |
数组 |
已掌握 |
03 数组中重复的数字 |
- 题目描述:
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
- 示例
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
class Solution {
public int findRepeatNumber(int[] nums) {
for(int i = 0; i < nums.length; i++){
while(nums[i] != i){
if(nums[i] == nums[nums[i]]) return nums[i];
int temp = nums[i];
nums[i] = nums[temp];
nums[temp] = temp;
}
}
return -1;
}
}
09 用两个栈实现队列
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
简单 |
A |
队列、栈 |
已掌握 |
here |
输入:
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
输出:[null,null,3,-1]
class CQueue {
private Stack<Integer> stk1 = new Stack<>();
private Stack<Integer> stk2 = new Stack<>();
public CQueue() {
}
public void appendTail(int value) {
stk1.push(value);
}
public int deleteHead() {
if(stk2.empty()){
while(!stk1.empty()){
stk2.push(stk1.pop());
}
}
if(stk2.empty()) return -1;
return stk2.pop();
}
}
38 字符串的排列
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
中等 |
A |
回溯 |
半 |
here |
- 题目描述:
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
- 示例
输入:s = "abc"
输出:["abc","acb","bac","bca","cab","cba"]
class Solution {
List<String> res = new ArrayList<>();
public String[] permutation(String s) {
char[] arr = s.toCharArray();
Arrays.sort(arr);
StringBuilder sb = new StringBuilder();
boolean[] used = new boolean[s.length()];
backtrace(sb, used, arr);
return res.toArray(new String[res.size()]);
}
private void backtrace(StringBuilder sb, boolean[] used, char[] arr){
if(sb.length()==arr.length){
res.add(sb.toString());
return;
}
for(int i = 0; i < arr.length; i++){
if(used[i]) continue;
if(i > 0 && arr[i]==arr[i-1] && !used[i-1]) continue;
used[i] = true;
backtrace(sb.append(arr[i]), used, arr);
sb.deleteCharAt(sb.length()-1);
used[i] = false;
}
}
}
51 数组中的逆序对
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
困难 |
A |
归并排序 |
半 |
https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/ |
- 题目描述:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
- 示例
输入: [7,5,6,4]
输出: 5
class Solution {
int[] nums, tmp;
public int reversePairs(int[] nums) {
this.nums = nums;
tmp = new int[nums.length];
return mergeSort(0, nums.length-1);
}
private int mergeSort(int left, int right){
if(left >= right) return 0;
int mid = (left+right) >> 1;
int res = mergeSort(left, mid) + mergeSort(mid+1, right);
int i = left, j = mid + 1;
for(int k = left; k <= right; k++) tmp[k] = nums[k];
for(int k = left; k <= right; k++) {
if(i == mid + 1){
nums[k] = tmp[j++];
} else if (j == right + 1 || tmp[i] <= tmp[j]){
nums[k] = tmp[i++];
} else {
nums[k] = tmp[j++];
res += mid + 1 - i;
}
}
return res;
}
}
22 链表中倒数第k个结点
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
简单 |
|
|
已掌握 |
here |
- 题目描述:
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
- 示例
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
if(head == null || k <= 0) return null;
ListNode front = head;
ListNode behind = head;
while(k-->0 && front != null){
front = front.next;
}
while(front != null){
front = front.next;
behind = behind.next;
}
return behind;
}
}
11 旋转数组的最小数
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
简单 |
|
|
已掌握 |
here |
- 题目描述:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
- 示例
输入:[2,2,2,0,1]
输出:0
class Solution {
public int minArray(int[] numbers) {
int left = 0, right = numbers.length-1;
while(left < right){
int mid = (right + left) >> 1;
if(numbers[mid] < numbers[right]){
right = mid;
}
else if(numbers[mid] > numbers[right]){
left = mid + 1;
}
else right -= 1;
}
return numbers[left];
}
}
29 顺时针打印矩阵
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
简单 |
|
|
已掌握 |
here |
- 题目描述:
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
- 示例
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
class Solution {
public int[] spiralOrder(int[][] matrix) {
int m = matrix.length;
if(m == 0) return new int[0];
int n = matrix[0].length;
int[] res = new int[m * n];
int row = 0, col = 0, count = 0;
while(true){
for(int i = col; i < n; i++){
res[count++] = matrix[row][i];
}if(m == ++row) break;
for(int i = row; i < m; i++){
res[count++] = matrix[i][n-1];
}if(--n == col) break;
for(int i = n-1; i >= col; i--){
res[count++] = matrix[m-1][i];
}if(--m == row) break;
for(int i = m-1; i >= row; i--){
res[count++] = matrix[i][col];
}if(n == ++col) break;
}
return res;
}
}
07 重建二叉树
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
中等 |
A |
树的遍历和递归 |
半 |
|
- 题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
- 示例
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
class Solution {
HashMap<Integer, Integer> in_map = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
int n = inorder.length;
if(n <= 0) return null;
for(int i = 0; i <n; i++){
in_map.put(inorder[i],i);
}
return findRoot(preorder, 0, 0, n-1);
}
private TreeNode findRoot(int[] preorder, int pre_root, int in_left, int in_right){
if(in_left > in_right) return null;
TreeNode root = new TreeNode(preorder[pre_root]);
int in_root = in_map.get(root.val);
root.left = findRoot(preorder, pre_root+1, in_left, in_root-1);
root.right = findRoot(preorder, pre_root+in_root-in_left+1,in_root+1, in_right);
return root;
}
}
06 从尾到头打链表
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
简单 |
|
|
已掌握 |
here |
- 题目描述:
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)
- 示例
输入:head = [1,3,2]
输出:[2,3,1]
class Solution {
public int[] reversePrint(ListNode head) {
Stack<ListNode> stack = new Stack<>();
ListNode temp = head;
while(temp != null){
stack.push(temp);
temp = temp.next;
}
int size = stack.size();
int[] arr = new int[size];
for(int i = 0; i <size; i++){
arr[i] = stack.pop().val;
}
return arr;
}
}
04 二维数组中的查找
- 题目描述:
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 示例
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
if(matrix == null || matrix.length ==0 || matrix[0].length == 0) return false;
int i = matrix[0].length-1, j = 0;
while(i >= 0 && j < matrix.length){
if(matrix[j][i] == target) return true;
else if(matrix[j][i] > target) i--;
else j++;
}
return false;
}
}
20 表示数值的字符串
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
中等 |
|
|
半 |
here |
class Solution {
public boolean isNumber(String s) {
boolean hasDot = false, hasE = false, hasSign = false, hasNum = false;
s = s.trim();
for(int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if(c == '+' || c == '-'){
if(hasDot || hasNum || hasSign) return false;
hasSign = true;
}
else if(c == 'e' || c == 'E'){
if(!hasNum || hasE) return false;
hasE = true;
hasSign = false;
hasNum = false;
hasDot = false;
}
else if(c == '.'){
if(hasE || hasDot) return false;
hasDot = true;
}
else if(c >= '0' && c <= '9'){
hasNum = true;
}
else{
return false;
}
}
if(!hasNum) return false;
return true;
}
}
48 最长不含重复字符的子字符串
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
中等 |
A |
|
已掌握 |
here |
- 题目描述:
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
- 示例
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length(), pre = 0, max = 0;
int[] index = new int[128];
Arrays.fill(index,-1);
for(int i = 0; i < n; i++){
if(index[s.charAt(i)] >= pre){`在这里插入代码片`
pre = index[s.charAt(i)]+1;
}
index[s.charAt(i)] = i;
max = Math.max(i-pre+1, max);
}
return max;
}
}
40 最小的k个数
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
简单 |
|
快速排序、堆 |
|
|
- 题目描述:
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
- 示例
输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
int n = arr.length;
if(n==k) return arr;
if(n < k || k <= 0 || n==0) return new int[0];
int l = 0, r = n-1;
int index = partition(arr, l, r);
while(index != k-1){
if(index > k-1) r = index - 1;
else l = index + 1;
index = partition(arr, l, r);
}
return Arrays.copyOfRange(arr,0,k);
}
private int partition(int[] arr, int l, int r){
int mid = l + (r-l)/2;
if(arr[l] > arr[r]) swap(arr, l, r);
if(arr[mid] > arr[r]) swap(arr, mid, r);
if(arr[mid] > arr[l]) swap(arr, l, mid);
int key = arr[l];
while(l < r){
while(l < r && arr[r] >= key) r--;
arr[l] = arr[r];
while(l < r && arr[l] <= key) l++;
arr[r] = arr[l];
}
arr[l] = key;
return l;
}
private void swap(int[] arr, int a, int b){
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
}
10-I 斐波那契数列
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
简单 |
|
|
已掌握 |
here |
class Solution {
public int fib(int n) {
int res = 0;
if(n < 2) res = n;
else{
int fibZero = 0, fibOne = 1;
for(int i = 2; i <= n; i++){
res = (fibOne + fibZero) %(1000000007);
fibZero = fibOne;
fibOne = res;
}
}
return res;
}
}
13 机器人运动轨迹
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
中等 |
|
递归 |
已掌握 |
here |
- 题目描述:
地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
- 示例
- 解答
class Solution {
public int movingCount(int m, int n, int k) {
if(m <= 0 || n <= 0 || k < 0) return 0;
boolean[][] visit = new boolean[m][n];
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
visit[i][j] = false;
}
}
return countSquare(m, n, 0, 0, k, visit);
}
private int countSquare(int m, int n, int row, int col, int k, boolean[][] visit){
if(row < 0 || row >= m || col < 0 || col >= n || !overLine(row, col, k) || visit[row][col]) return 0;
int count = 0;
visit[row][col] = true;
count = 1 + countSquare(m, n, row+1, col, k, visit) + countSquare(m, n, row, col+1, k, visit);
return count;
}
private boolean overLine(int row, int col, int k){
int num = 0;
while(row > 0){
num += row % 10;
row = row / 10;
}while(col > 0){
num += col % 10;
col = col / 10;
}
return num > k ? false : true;
}
}
25 合并两个排序的链表
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
简单 |
|
|
已掌握 |
here |
- 题目描述:
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
- 示例
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1 == null) return l2;
if(l2 == null) return l1;
ListNode pNode = null;
if(l1.val <= l2.val){
pNode = l1;
l1 = l1.next;
}else{
pNode = l2;
l2 = l2.next;
}
ListNode head = pNode;
while(l1 != null && l2 != null){
if(l1.val <= l2.val){
pNode.next = l1;
l1 = l1.next;
pNode = pNode.next;
}else{
pNode.next = l2;
l2 = l2.next;
pNode = pNode.next;
}
}
pNode.next = (l1 == null) ? l2 : l1;
return head;
}
}
26 树的子结构
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
简单 |
|
递归 |
|
here |
- 题目描述:
输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。
- 示例
输入:A = [1,2,3], B = [3,1]
输出:false
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
boolean res = false;
if(A != null && B != null){
if(A.val == B.val) res = TreeAHasTreeB(A, B);
if(!res) res = isSubStructure(A.left, B);
if(!res) res = isSubStructure(A.right, B);
}
return res;
}
private boolean TreeAHasTreeB(TreeNode A, TreeNode B){
if(B == null) return true;
if(A == null) return false;
if(A.val != B.val) return false;
return TreeAHasTreeB(A.left, B.left) && TreeAHasTreeB(A.right, B.right);
}
}
10-II 青蛙跳台阶问题
输入:n = 7
输出:21
class Solution {
public int numWays(int n) {
int res = 0;
if(n < 0) return -1;
if(n == 0) res = 1;
if(n <= 2) res = n;
else{
int fibOne = 1,fibTwo = 1;
for(int i = 3; i <= n; i++){
res = (fibOne+fibTwo) % 1000000007;
fibOne = fibTwo;
fibTwo = res;
}
}
return res;
}
}
59-I 滑动窗口最大值
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
困难 |
|
滑动窗口 |
半 |
here |
- 题目描述:
给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。
- 示例
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int len = nums.length;
if(k == 0 || len == 0) return new int[0];
int maxNumber = nums[0];
int[] res = new int[len - k + 1];
Queue<Integer> queue = new LinkedList<Integer>();
for(int i = 0; i < k; i++){
maxNumber = Math.max(maxNumber, nums[i]);
queue.offer(nums[i]);
}res[0] = maxNumber;
for(int i = k; i < len; i++){
if(queue.peek() == maxNumber){
queue.poll();
queue.offer(nums[i]);
maxNumber = queue.peek();
for(int j = i-k+2; j <= i; j++){
maxNumber = Math.max(maxNumber, nums[j]);
}
}else{
queue.poll();
maxNumber = Math.max(maxNumber, nums[i]);
queue.offer(nums[i]);
}
res[i - k + 1] = maxNumber;
}
return res;
}
}
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums.length == 0 || k == 0) return new int[0];
Deque<Integer> deque = new LinkedList<>();
int[] res = new int[nums.length - k + 1];
for(int i = 0; i < k; i++) {
while(!deque.isEmpty() && deque.peekLast() < nums[i])
deque.pollLast();
deque.offerLast(nums[i]);
}
res[0] = deque.peekFirst();
for(int i = k; i < nums.length; i++) {
if(deque.peekFirst() == nums[i - k])
deque.pollFirst();
while(!deque.isEmpty() && deque.peekLast() < nums[i])
deque.pollLast();
deque.offerLast(nums[i]);
res[i - k + 1] = deque.peekFirst();
}
return res;
}
}
45 把数组排成最小的数
难度 |
重点度 |
知识点 |
掌握度 |
链接 |
中等 |
|
|
已掌握 |
here |
- 题目描述:
输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
- 示例
输入: [3,30,34,5,9]
输出: "3033459"
class Solution {
public String minNumber(int[] nums) {
List<String> list = new ArrayList<>();
for(int num : nums) list.add(Integer.toString(num));
Collections.sort(list, (a, b)->(a+b).compareTo(b+a));
StringBuilder sb = new StringBuilder();
for(String i:list) sb.append(i);
return sb.toString();
}
}
62 圆圈中最后剩下的数字
- 题目描述:
0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
- 示例
输入: n = 5, m = 3
输出: 3
class Solution {
public int lastRemaining(int n, int m) {
if(n < 1 ||m < 0) return -1;
int last = 0;
for(int i = 2; i <= n; i++){
last = (last + m) % i;
}
return last;
}
}
32-I 从上到下打印二叉树(从左到右放一层)
- 题目描述:
从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印
- 示例
- 解答
class Solution {
public int[] levelOrder(TreeNode root) {
if(root == null) return new int[0];
Queue<TreeNode> queue = new LinkedList<>();
List<Integer> list = new ArrayList<>();
if(root != null) queue.offer(root);
while(!queue.isEmpty()){
TreeNode pNode = queue.poll();
if(pNode.left != null) queue.offer(pNode.left);
if(pNode.right != null) queue.offer(pNode.right);
list.add(pNode.val);
}
int[] res = new int[list.size()];
for(int i = 0; i < list.size(); i++){
res[i] = list.get(i);
}
return res;
}
}
46 把数字翻译成字符串
- 题目描述:
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
- 示例
输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
class Solution {
public int translateNum(int num) {
if(num < 10) return 1;
if(num % 100 < 10 || num % 100 > 25) return translateNum(num/10);
else return translateNum(num/10) + translateNum(num/100);
}
}
17 打印从1到最大的n位数
- 题目描述:
输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
- 示例
- 解答
class Solution {
public int[] printNumbers(int n) {
int num = 1;
while(n-- > 0){
num *= 10;
}
int[] res = new int[num-1];
for(int i = 0; i < num-1; i++){
res[i] = i+1;
}
return res;
}
}
05 替换空格
- 题目描述:
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
- 示例
- 解答
class Solution {
public String replaceSpace(String s) {
StringBuilder result = new StringBuilder();
for(int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if(c == ' ') result.append("%20");
else result.append(c);
}
return result.toString();
}
}
34 二叉树中和为某一值的路径
- 题目描述:
输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。
- 示例
- 解答
class Solution {
private List<List<Integer>> res = new ArrayList<>();
private List<Integer> list = new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int target) {
int index = 0;
isSame(root, target, index);
return res;
}
private void isSame(TreeNode pNode, int target, int index){
if(pNode == null) return;
target -= pNode.val;
list.add(pNode.val);
index++;
if(target == 0 && pNode.left == null && pNode.right == null){
res.add(new ArrayList<Integer>(list));
}
isSame(pNode.left, target, index);
isSame(pNode.right, target, index);
list.remove(--index);
}
}
63 股票的最大利润
- 题目描述:
假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?
- 示例
输入: [7,1,5,3,6,4]
输出: 5
class Solution {
public int maxProfit(int[] prices) {
if(prices.length == 0) return 0;
int minPrice = prices[0], profit = 0;
for(int i = 1; i < prices.length; i++){
if(prices[i] > minPrice) profit = Math.max(prices[i] - minPrice, profit);
else minPrice = prices[i];
}
return profit;
}
}
42 连续子数组的最大和
- 题目描述:
输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
要求时间复杂度为O(n)。
- 示例
- 解答
class Solution {
public int maxSubArray(int[] nums) {
int max = nums[0], sum = 0;
for(int x:nums){
sum = Math.max(sum + x, x);
max = Math.max(sum, max);
}
return max;
}
}
36 二叉搜索树与双向链表
- 题目描述:
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
- 示例
- 解答
class Solution {
Node pre, head;
public Node treeToDoublyList(Node root) {
if(root == null) return null;
convertNode(root);
head.left = pre;
pre.right = head;
return head;
}
private void convertNode(Node cur){
if(cur != null){
convertNode(cur.left);
if(head == null){
head = cur;
}else{
pre.right = cur;
cur.left = pre;
}
pre = cur;
convertNode(cur.right);
}
}
}
57 和为s的两个数字
- 题目描述:
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
- 示例
- 解答
class Solution {
public int[] twoSum(int[] nums, int target) {
int left = 0, right = nums.length-1;
while(left < right){
if(nums[left] + nums[right] < target) left++;
else if(nums[left] + nums[right] > target) right--;
else return new int[]{nums[left],nums[right]};
}
return new int[0];
}
}
61 扑克牌中的顺子
- 题目描述:
从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。
- 示例
- 解答
class Solution {
public boolean isStraight(int[] nums) {
Arrays.sort(nums);
int zero = 0;
while(nums[zero] == 0) zero++;
if(nums[4] - nums[zero] <= 4){
for(int i = zero; i < 4; i++){
if(nums[i] == nums[i+1]) return false;
}
return true;
}
return false;
}
}
14-I 剪绳子
- 题目描述:
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m-1] 。请问 k[0]k[1]…*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
- 示例
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
class Solution {
public int cuttingRope(int n) {
if(n < 4) return n-1;
int mul = 1;
while(n > 4){
mul *= 3;
n -= 3;
}
return mul*n;
}
}
50 第一个只出现一次的字符
- 题目描述:
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
- 示例
- 解答
class Solution {
public char firstUniqChar(String s) {
if(s.length()==0) return ' ';
int[] arr = new int[26];
Arrays.fill(arr,-1);
int index = 0;
for(int i = 0; i < s.length(); i++){
arr[s.charAt(i)-'a']++;
}
while(arr[s.charAt(index)-'a'] > 0){
if(index + 1 == s.length()) return ' ';
index++;
}
return s.charAt(index);
}
}
57-II 和为s的连续正整数序列
- 题目描述:
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
- 示例
输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
class Solution {
public int[][] findContinuousSequence(int target) {
List<int[]> list = new ArrayList<int[]>();
int start = 1, end = 2,sum = start+end;
int mid = (target+1)>>1;
while(start < mid){
if(sum < target) sum += ++end;
else if(sum > target) sum -= start++;
else{
int[] arr = new int[end-start+1];
for(int i = 0; i < end-start+1; i++){
arr[i] = start+i;
}
list.add(arr);
sum -= start++;
}
}
return list.toArray(new int[list.size()][]);
}
}
27 二叉树的镜像
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]
class Solution {
public TreeNode mirrorTree(TreeNode root) {
if(root == null) return null;
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
root.left = mirrorTree(root.left);
root.right = mirrorTree(root.right);
return root;
}
}
12 矩阵中的路径
- 题目描述:
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
- 示例
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true
class Solution {
public boolean exist(char[][] board, String word) {
if(word.length() == 0) return false;
char[] strs = word.toCharArray();
for(int row = 0; row < board.length; row++){
for(int col = 0; col < board[0].length; col++){
return isExit(board, strs, row, col, 0);
}
}
return false;
}
private boolean isExit(char[][] board, char[] strs, int row, int col, int pathLength){
if(row<0 || row>=board.length || col<0 || col>=board[0].length || board[row][col]!=strs[pathLength]) return false;
if(pathLength == strs.length - 1) return true;
board[row][col]='\0';
boolean hasPath = isExit(board, strs, row-1, col, pathLength+1) || isExit(board, strs, row+1, col, pathLength+1)||isExit(board, strs, row, col-1, pathLength+1) || isExit(board, strs, row, col+1, pathLength+1);
board[row][col] = strs[pathLength];
return hasPath;
}
}
39 数组中出现的次数
- 题目描述:
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
- 示例
- 解答
class Solution {
public int majorityElement(int[] nums) {
int num = 0, count = 0;
for(int i = 0; i < nums.length; i++){
if(count==0){
num = nums[i];
count++;
} else{
if(num==nums[i]) count++;
else count--;
}
}
return num;
}
}
49 丑数
- 题目描述:
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
- 示例
输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。
class Solution {
public int nthUglyNumber(int n) {
if(n < 7) return n;
int[] ugly = new int[n];
ugly[0] = 1;
int x = 0, y = 0, z = 0, temp = 0;
for(int i = 1; i < n; i++){
temp = Math.min(ugly[x]*2, Math.min(ugly[y]*3,ugly[z]*5));
if(temp == ugly[x]*2) x++;
if(temp == ugly[y]*3) y++;
if(temp == ugly[z]*5) z++;
ugly[i] = temp;
}
return ugly[n-1];
}
}
55-I 二叉树的深度
- 题目描述:
输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。
- 示例
- 解答
class Solution {
public int maxDepth(TreeNode root) {
if(root == null) return 0;
int depth = 1;
depth += Math.max(maxDepth(root.left), maxDepth(root.right));
return depth;
}
}
32-II 从上到下打印二叉树(从左到右分层)
- 题目描述:
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
- 示例
- 解答
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> arr = new ArrayList<>();
if(root == null) return arr;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int levelSize = queue.size();
List<Integer> list = new ArrayList<>();
for(int i = 0; i < levelSize; i++){
TreeNode pNode = queue.poll();
if(pNode.left != null) queue.offer(pNode.left);
if(pNode.right != null) queue.offer(pNode.right);
list.add(pNode.val);
}
arr.add(list);
}
return arr;
}
}
30 包含min函数的栈
- 题目描述:
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
- 示例
- 解答
class MinStack {
private Stack<Integer> stack1 = new Stack<>();
private Stack<Integer> stack2 = new Stack<>();
public MinStack() {
}
public void push(int x) {
if(stack1.isEmpty()){
stack2.push(x);
}else{
stack2.push(stack2.peek() > x ? x : stack2.peek());
}
stack1.push(x);
}
public void pop() {
stack1.pop();
stack2.pop();
}
public int top() {
return stack1.peek();
}
public int min() {
return stack2.peek();
}
}
56-I 数组中数字出现次数(两个出现一次,其他都两次)
- 题目描述:
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
- 示例
- 解答
class Solution {
public int[] singleNumbers(int[] nums) {
int n = 0;
for(int num : nums) n ^= num;
int div = 1;
while((div & n) == 0) div <<= 1;
int a = 0, b = 0;
for(int num : nums){
if((num & div) != 0) a ^= num;
else b ^= num;
}
return new int[]{a,b};
}
}
53-II 0~n-1中缺失的数字
- 题目描述:
一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。
- 示例
- 解答
class Solution {
public int missingNumber(int[] nums) {
int left = 0, right = nums.length-1;
while(left <= right){
int mid = (left + right) >> 1;
if(nums[mid] == mid) left = mid + 1;
else right = mid - 1;
}return right + 1;
}
}
18 删除链表的节点
- 题目描述:
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
- 示例
- 解答
class Solution {
public ListNode deleteNode(ListNode head, int val) {
if(head.val == val){
head = head.next;
}else{
ListNode pNode = head;
ListNode pre = head;
while(pNode.val != val){
pre = pNode;
pNode = pNode.next;
}
pre.next = pNode.next;
}
return head;
}
}
33 二叉搜索树的后序遍历序列
- 题目描述:
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。
- 示例
- 解答
class Solution {
public boolean verifyPostorder(int[] postorder) {
int n = postorder.length;
if(n == 0) return true;
return isAfterOrder(postorder, 0, n-1);
}
private boolean isAfterOrder(int[] postorder, int start, int end){
int root = postorder[end];
int left = 0, i = start;
while(postorder[i] < root){
left++;i++;
}
while(i++ < end){
if(postorder[i] < root){
return false;
}
}
if(left <= 2 && (end-start-left)<=2) return true;
else if(left <= 2 && (end-start-left)>2) return isAfterOrder(postorder, start+left, end-1);
else if(left > 2 && (end-start-left)<=2) return isAfterOrder(postorder, start, start+left-1);
else return isAfterOrder(postorder, start+left, end-1) && isAfterOrder(postorder, start, start+left-1);
}
}
class Solution {
public boolean verifyPostorder(int[] postorder) {
Stack<Integer> stack = new Stack<>();
int root = Integer.MAX_VALUE;
for(int i = postorder.length - 1; i >= 0; i--) {
if(postorder[i] > root) return false;
while(!stack.isEmpty() && stack.peek() > postorder[i])
root = stack.pop();
stack.add(postorder[i]);
}
return true;
}
}
68-II 二叉树的最近公共祖先(无序)
- 题目描述:
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null) return null;
if(root == p || root == q) return root;
TreeNode left_Node = lowestCommonAncestor(root.left, p, q);
TreeNode right_Node = lowestCommonAncestor(root.right, p, q);
if(left_Node != null && right_Node != null){
return root;
}return left_Node == null ? right_Node : left_Node;
}
}
58-I 翻转单词的顺序
- 题目描述:
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. “,则输出"student. a am I”。
- 示例
- 解答
class Solution {
public String reverseWords(String s) {
s = s.trim();
int i = s.length()-1, j = i;
StringBuilder sb = new StringBuilder();
while(i >= 0){
while(i >= 0 && s.charAt(i) != ' ') i--;
sb.append(s.substring(i+1, j+1));
if(i != -1) sb.append(' ');
while(i >= 0 && s.charAt(i) == ' ') i--;
j = i;
}
return sb.toString();
}
}
32-III 从上到下打印二叉树(之字形)
- 题目描述:
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
- 示例
- 解答
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
Deque<TreeNode> deque = new LinkedList<>();
List<List<Integer>> res = new ArrayList<>();
if(root != null) deque.add(root);
while(!deque.isEmpty()) {
List<Integer> tmp = new ArrayList<>();
for(int i = deque.size(); i > 0; i--) {
TreeNode node = deque.removeFirst();
tmp.add(node.val);
if(node.left != null) deque.addLast(node.left);
if(node.right != null) deque.addLast(node.right);
}
res.add(tmp);
if(deque.isEmpty()) break;
tmp = new ArrayList<>();
for(int i = deque.size(); i > 0; i--) {
TreeNode node = deque.removeLast();
tmp.add(node.val);
if(node.right != null) deque.addFirst(node.right);
if(node.left != null) deque.addFirst(node.left);
}
res.add(tmp);
}
return res;
}
}
60 n个骰子的点数
- 题目描述:
把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。
你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。
- 示例
输入: 2
输出: [0.02778,0.05556,0.08333,0.11111,0.13889,0.16667,0.13889,0.11111,0.08333,0.05556,0.02778]
- 解答
class Solution {
public double[] dicesProbability(int n) {
double[] res = new double[]{1.0/6,1.0/6,1.0/6,1.0/6,1.0/6,1.0/6};
for(int i = 2; i <= n; i++){
double[] temp = new double[5*i+1];
for(int j = 0; j < res.length; j++){
for(int x = 0; x < 6; x++){
temp[j+x] += res[j]/6;
}
}
res = temp;
}
return res;
}
}
66 构建乘机数组
- 题目描述:
给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B[i] 的值是数组 A 中除了下标 i 以外的元素的积, 即 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。
- 示例
输入: [1,2,3,4,5]
输出: [120,60,40,30,24]
class Solution {
public int[] constructArr(int[] a) {
int[] arr = new int[a.length];
Arrays.fill(arr, 1);
int temp = 1;
for(int i = 1; i < a.length; i++){
arr[i] = a[i-1] * arr[i-1];
} for(int j = a.length-2; j >= 0; j--){
temp *= a[j+1];
arr[j] *= temp;
}
return arr;
}
}
58-II 左旋转字符串
- 题目描述:
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
- 示例
- 解答
class Solution {
public String reverseLeftWords(String s, int n) {
StringBuilder sb = new StringBuilder();
int len = s.length();
for(int i = n; i < len; i++){
sb.append(s.charAt(i));
}
for(int i = 0; i < n; i++){
sb.append(s.charAt(i));
}
return sb.toString();
}
}
47 礼物的最大价值
- 题目描述:
在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?
- 示例
- 解答
class Solution {
public int maxValue(int[][] grid) {
int m = grid.length;
if(m == 0) return 0;
int n = grid[0].length;
for(int i = 1; i < m; i++) grid[i][0] += grid[i-1][0];
for(int j = 1; j < n; j++) grid[0][j] += grid[0][j-1];
for(int i = 1; i < m; i++){
for(int j = 1; j < n; j++){
grid[i][j] += Math.max(grid[i-1][j],grid[i][j-1]);
}
}
return grid[m-1][n-1];
}
}
35 复杂链表的复制
class Solution {
public Node copyRandomList(Node head) {
if(head == null) return null;
copyOriginal(head);
nodeConnect(head);
return nodeSplit(head);
}
private void copyOriginal(Node head){
Node pNode = head;
while(pNode != null){
Node copyNode = new Node(pNode.val);
copyNode.next = pNode.next;
copyNode.random = null;
pNode.next = copyNode;
pNode = copyNode.next;
}
}
private void nodeConnect(Node head){
Node pNode = head;
while(pNode != null){
if(pNode.random != null){
pNode.next.random = pNode.random.next;
}
pNode = pNode.next.next;
}
}
private Node nodeSplit(Node head){
Node pNode = head;
Node copyHead = null;
Node copyNode = null;
if(pNode != null){
copyNode = copyHead = pNode.next;
pNode.next = copyNode.next;
pNode = pNode.next;
}
while(pNode != null){
copyNode.next = pNode.next;
copyNode = pNode.next;
pNode.next = copyNode.next;
pNode = copyNode.next;
}
return copyHead;
}
}
class Solution {
public Node copyRandomList(Node head) {
if(head == null) return null;
Node pNode = head;
while(pNode != null){
Node copyNode = new Node(pNode.val);
copyNode.next = pNode.next;
pNode.next = copyNode;
pNode = copyNode.next;
}
pNode = head;
while(pNode != null){
if(pNode.random != null){
pNode.next.random = pNode.random.next;
}
pNode = pNode.next.next;
}
pNode = head;
Node copyHead = null;
Node copyNode = null;
if(pNode != null){
copyHead = copyNode = pNode.next;
pNode.next = copyNode.next;
pNode = pNode.next;
}
while(pNode != null){
copyNode.next = pNode.next;
copyNode = pNode.next;
pNode.next = copyNode.next;
pNode = pNode.next;
}
return copyHead;
}
}
67 把字符串转换成整数
class Solution {
public int strToInt(String str) {
str = str.trim();
if(str.length()==0) return 0;
int res = 0, minus = 1, index = 0, line = Integer.MAX_VALUE/10;
if(str.charAt(0) == '+') index++;
else if(str.charAt(0) == '-'){
minus = -1; index++;
}
while(index < str.length() && str.charAt(index) >= '0' && str.charAt(index) <= '9'){
if(res > line || res == line && str.charAt(index)>'7') {
return minus == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
}
res = res * 10 + (int)(str.charAt(index++) - '0');
}
return res * minus;
}
}
19 正则表达式匹配
- 题目描述:
请实现一个函数用来匹配包含’. ‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。
- 示例
- 解答
class Solution {
public boolean isMatch(String s, String p) {
int m = s.length(), n = p.length();
boolean[][] dp = new boolean[m+1][n+1];
dp[0][0] = true;
for(int i = 2; i <= n; i += 2){
dp[0][i] = dp[0][i-2] && p.charAt(i-1) == '*';
}
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
if(p.charAt(j-1) == '*'){
dp[i][j] = dp[i][j-2] || dp[i-1][j] && s.charAt(i-1)==p.charAt(j-2) || dp[i-1][j] && p.charAt(j-2)=='.';
}else{
dp[i][j] = dp[i-1][j-1] && s.charAt(i-1)==p.charAt(j-1) || dp[i-1][j-1] && p.charAt(j-1)=='.';
}
}
}
return dp[m][n];
}
}
21 调整数组顺序使奇数位于偶数前面
class Solution {
public int[] exchange(int[] nums) {
int left = 0, right = nums.length-1;
while(left < right){
while((nums[left]%2 == 1) && left < right) left++;
while((nums[right]%2 == 0) && left < right) right--;
if(left < right){
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
left++; right--;
}
}
return nums;
}
}
55-II 平衡二叉树
class Solution {
int depth = 0;
public boolean isBalanced(TreeNode root) {
if(root == null){
depth = 0;
return true;
}
int depthLeft = 0, depthRight = 0;
boolean a = isBalanced(root.right);
depthRight = depth;
boolean b = isBalanced(root.left);
depthLeft = depth;
if(a && b){
if(depthLeft - depthRight < 2 && depthRight - depthLeft < 2){
depth = Math.max(depthLeft,depthRight) + 1;
return true;
}
}
return false;
}
}
64 求1+2+…+n
class Solution {
public int sumNums(int n) {
boolean x = n > 1 && (n += sumNums(n-1)) > 0;
return n;
}
}
class Solution {
public int sumNums(int n) {
return sum(n+1, n)>>1;
}
int sum(int a, int n){
int ans = 0;
boolean x = (n > 1) && (ans += sum(a << 1, n >> 1)) > 0;
boolean y = (n & 1 != 0) && (ans += a) > 0;
return ans;
}
}
59-II 队列的最大值
- 题目描述:
请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。
若队列为空,pop_front 和 max_value 需要返回 -1
- 示例
- 解答
class MaxQueue {
Deque<Integer> deque = new LinkedList<>();
Queue<Integer> queue = new LinkedList<>();
public MaxQueue() {
}
public int max_value() {
if(!deque.isEmpty()) return deque.peekFirst();
return -1;
}
public void push_back(int value) {
while(!deque.isEmpty() && deque.peekLast() < value) deque.pollLast();
deque.offerLast(value);
queue.offer(value);
}
public int pop_front() {
if(queue.isEmpty()) return -1;
if(queue.peek().equals(deque.peekFirst())) deque.pollFirst();
return queue.poll();
}
}
15 二进制中1的个数
public class Solution {
public int hammingWeight(int n) {
56-II 数组中1的个数
- 题目描述:
在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。
- 示例
- 解答
class Solution {
public int singleNumber(int[] nums) {
int a = 0, b = 0;
for(int n : nums){
int tempa = ~a & b & n | a & b & ~n;
b = ~a & ~b & n | a & b & ~n | ~a & b;
a = tempa;
}
return b;
}
}
54 二叉搜索树的第k大节点
class Solution {
int target = 0, res = 0;
public int kthLargest(TreeNode root, int k) {
if(root == null) return 0;
kthLargest(root.right, k);
if(res != 0) return res;
target++;
if(target == k){
res = root.val;
return res;
}
kthLargest(root.left,k);
return res;
}
}
28 对称的二叉树
- 题目描述:
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
- 示例
- 解答
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root == null) return true;
return isOk(root.left, root.right);
}
private boolean isOk(TreeNode A, TreeNode B){
if(A == null && B == null) return true;
if(A == null || B == null) return false;
if(A.val != B.val) return false;
return isOk(A.left, B.right) && isOk(A.right, B.left);
}
}
37 序列化二叉树
- 题目描述:
请实现两个函数,分别用来序列化和反序列化二叉树。
你需要设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
- 示例
- 解答
public String serialize(TreeNode root) {
if(root == null) return "[]";
StringBuilder sb = new StringBuilder();
sb.append("[");
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
while(!queue.isEmpty()){
int levelLength = queue.size();
for(int i = 0; i < levelLength; i++){
TreeNode pNode = queue.poll();
if(pNode != null){
sb.append(pNode.val).append(",");
queue.offer(pNode.left);
queue.offer(pNode.right);
}
else{
sb.append("$").append(",");
}
}
}
sb.deleteCharAt(sb.length() - 1).append("]");
return sb.toString();
}
public TreeNode deserialize(String data) {
if(data.equals("[]")) return null;
String[] strs = data.substring(1,data.length()-1).split(",");
int n = strs.length;
TreeNode[] arr = new TreeNode[n];
for(int i = 0; i < n; i++){
arr[i] = new TreeNode(0);
}
for(int i = 0; i < n; i++){
if(!strs[i].equals("$")){
arr[i].val = Integer.parseInt(strs[i]);
}
else arr[i] = null;
}
for(int i = 0, j = 1; j < n; i++){
if(arr[i] != null){
arr[i].left = arr[j++];
arr[i].right = arr[j++];
}
}
return arr[0];
}
}
43 1~n整数中1出现的次数
- 题目描述:
输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
- 示例
- 解答
class Solution {
public int countDigitOne(int n) {
int digit = 1, count = 0;
int high = n/10, low = 0, cur = n%10;
while(high!=0 || cur!=0){
if(cur==0) count += high * digit;
else if(cur==1) count += high * digit + low + 1;
else count += (high+1) * digit;
low += cur * digit;
cur = high % 10;
high /= 10;
digit *= 10;
}
return count;
}
}
68-I 二叉树搜索树的最近公共祖先
- 题目描述:
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
- 示例
- 解答
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(p.val > q.val){
TreeNode pNode = p;
p = q;
q= pNode;
}
if(root.val >= p.val && root.val <= q.val) return root;
else if(root.val > p.val && root.val > q.val) return lowestCommonAncestor(root.left, p, q);
else if(root.val < p.val && root.val < q.val) return lowestCommonAncestor(root.right, p, q);
return null;
}
}
41 数据流的中位数
- 题目描述:
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
- 示例
- 解答
class MedianFinder {
public MedianFinder() {
}
PriorityQueue<Integer> min_queue = new PriorityQueue<Integer>();
PriorityQueue<Integer> max_queue = new PriorityQueue<Integer>((a,b)->(b-a));
public void addNum(int num) {
if((min_queue.size()+max_queue.size()) % 2 == 0){
if(max_queue.size() > 0 && num < max_queue.peek()){
min_queue.offer(max_queue.poll());
max_queue.offer(num);
} else {
min_queue.offer(num);
}
} else {
if(min_queue.size()>0 && num > min_queue.peek()){
max_queue.offer(min_queue.poll());
min_queue.offer(num);
} else {
max_queue.offer(num);
}
}
}
public double findMedian() {
int size = min_queue.size()+max_queue.size();
if(size == 0) return 0;
return (size % 2) == 1 ? (double)min_queue.peek() : (double)(min_queue.peek() + max_queue.peek())/2;
}
}
52 两个链表的第一个公共节点
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode pNodeA = headA, pNodeB = headB;
while(pNodeA != pNodeB){
pNodeA = (pNodeA == null) ? headB : pNodeA.next;
pNodeB = (pNodeB == null) ? headA : pNodeB.next;
}
return pNodeA;
}
}
65 不用加减乘除做加法
- 题目描述:
写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号
- 示例
- 解答
class Solution {
public int add(int a, int b) {
while(b != 0){
int c = (a & b) << 1;
a ^= b;
b = c;
}return a;
}
}
44 数字序列中某一位的数字
- 题目描述:
数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。
请写一个函数,求任意第n位对应的数字。
- 示例
- 解答
class Solution {
public int findNthDigit(int n) {
if(n < 10) return n;
int len = 1;
long digit = 1, count = 9;
while(n > count){
n -= count;
digit *= 10;
len++;
count = digit * len * 9;
}
int num = (int)digit + (n-1)/len;
int index = (n-1)%len;
while(++index != len) num /= 10;
return num%10;
}
}
53-I 在排序数组中查抄数字
- 题目描述:
统计一个数字在排序数组中出现的次数。
- 示例
- 解答
class Solution {
public int search(int[] nums, int target) {
return findLast(nums, target) - findLast(nums,target-1);
}
private int findLast(int[] nums, int target){
int left = 0, right = nums.length - 1;
while(left <= right){
int mid = (left + right);
if(nums[mid] <= target) left = mid + 1;
else right = mid - 1;
}
return right;
}
}
14-II 剪绳子II
- 题目描述:
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m - 1] 。请问 k[0]k[1]…*k[m - 1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
- 示例
- 解答
class Solution {
public int cuttingRope(int n) {
if(n < 4) return n-1;
long mul = 1;
while(n > 4){
mul *= 3;
mul %= 1000000007;
n -= 3;
}
return (int)(mul * n % 1000000007);
}
}
31 栈的压入、弹出序列
- 题目描述:
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。
- 示例
- 解答
class Solution {
public boolean validateStackSequences(int[] pushed, int[] popped) {
if(pushed.length == 0 && popped.length == 0) return true;
if(pushed.length != popped.length) return false;
Stack<Integer> stk = new Stack<>();
int index = 0;
for(int i = 0; i < pushed.length; i++){
stk.push(pushed[i]);
while(!stk.empty() && stk.peek() == popped[index]){
stk.pop();
index++;
}
}
return stk.isEmpty();
}
}
16 数值的整数次方
- 题目描述:
实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。
- 示例
- 解答
class Solution {
public double myPow(double x, int n) {
if(x == 0.0){
return 0.0;
}
if(n == 0){
return 1.0;
}
long abs_n = n;
if(n < 0) abs_n = -abs_n;
double res = 1.0;
while(abs_n > 0){
if((abs_n & 1) == 1) res *= x;
x *= x;
abs_n >>= 1;
}
if(n < 0) res = 1 / res;
return res;
}
}