
1.栈与队列(简单)
01-用两个栈实现队列
class CQueue {
Deque<Integer> stack1;
Deque<Integer> stack2;
public CQueue() {
stack1 = new LinkedList<>();
stack2 = new LinkedList<>();
}
public void appendTail(int value) {
stack1.push(value);
}
public int deleteHead() {
if(stack2.isEmpty()) {
if(stack1.isEmpty()) {
return -1;
}
while(!stack1.isEmpty()) {
stack2.push(stack1.pop());
}
}
return stack2.pop();
}
}
02-包含min函数的栈
class MinStack {
Deque<Integer> stack1;
Deque<Integer> stack2;
public MinStack() {
stack1 = new LinkedList<>();
stack2 = new LinkedList<>();
}
public void push(int x) {
stack1.push(x);
if(x < min()) {
stack2.push(x);
} else {
stack2.push(min());
}
}
public void pop() {
stack1.pop();
stack2.pop();
}
public int top() {
return stack1.peek();
}
public int min() {
if(stack2.isEmpty()) {
return Integer.MAX_VALUE;
}
return stack2.peek();
}
}
2.链表(简单)
03-从尾到头打印链表
class Solution {
private int[] result;
private int length;
public int[] reversePrint(ListNode head) {
if(head == null) return new int[]{};
dfs(head, 0);
return result;
}
public void dfs(ListNode node, int index) {
if(node == null) {
result = new int[length];
return;
}
length++;
dfs(node.next, index + 1);
result[length - index - 1] = node.val;
}
}
04-反转链表
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null) return null;
ListNode prev = null, next = head.next;
while(next != null) {
head.next = prev;
prev = head;
head = next;
next = head.next;
}
head.next = prev;
return head;
}
}
05-复杂链表的复制
class Solution {
public Node copyRandomList(Node head) {
if(head == null) return null;
Map<Node, Node> map = new HashMap<>();
for(Node node = head; node != null; node = node.next) {
map.put(node, new Node(node.val));
}
for(Node node = head; node != null; node = node.next) {
map.get(node).next = map.get(node.next);
map.get(node).random = map.get(node.random);
}
return map.get(head);
}
}
3.字符串(简单)
06-替换空格
class Solution {
public String replaceSpace(String s) {
StringBuilder sb = new StringBuilder();
for(char c : s.toCharArray()) {
if(c == ' ') {
sb.append("%20");
} else {
sb.append(c);
}
}
return sb.toString();
}
}
07-左旋转字符串
class Solution {
public String reverseLeftWords(String s, int n) {
return s.substring(n) + s.substring(0, n);
}
}
4.查找算法(简单)
08-数组中重复的数字
class Solution {
public int findRepeatNumber(int[] nums) {
int[] hash = new int[nums.length];
for(int i = 0; i < nums.length; i++) {
if(++hash[nums[i]] > 1) {
return nums[i];
}
}
return -1;
}
}
09-在排序数组中查找数字 I
class Solution {
public int search(int[] nums, int target) {
int left = 0, right = nums.length, count = 0;
while(left < right) {
int mid = left + (right - left) / 2;
if(nums[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
while(left < nums.length && nums[left++] == target) {
count++;
}
return count;
}
}
10- (0~n-1)中缺失的数字
class Solution {
public int missingNumber(int[] nums) {
int n = nums.length, left = 0, right = n - 1;
while(left < right) {
int mid = left + (right - left) / 2;
if(nums[mid] == mid) {
left = mid + 1;
} else {
right = mid;
}
}
return left == nums[n - 1] ? n : left;
}
}
class Solution {
public int missingNumber(int[] nums) {
int result = nums.length;
for(int i = 0; i < nums.length; i++) {
result ^= nums[i];
result ^= i;
}
return result;
}
}
5.查找算法(中等)
11-二维数组中的查找
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
int n = matrix.length;
if(n == 0) {
return false;
}
int i = 0, j = matrix[0].length - 1;
while(i < n && j >= 0) {
if(matrix[i][j] == target) {
return true;
}
if(matrix[i][j] < target) {
i++;
} else {
j--;
}
}
return false;
}
}
12-旋转数组的最小数字
class Solution {
public int minArray(int[] numbers) {
int left = 0, right = numbers.length - 1;
while(left < right) {
int mid = left + (right - left) / 2;
if(numbers[right] < numbers[mid]) {
left = mid + 1;
continue;
}
if(numbers[right] > numbers[mid]) {
right = mid;
continue;
}
right--;
}
return numbers[left];
}
}
13-第一个只出现一次的字符
class Solution {
public char firstUniqChar(String s) {
int[] hash = new int[26];
for(char c : s.toCharArray()) {
hash[c - 'a']++;
}
for(char c : s.toCharArray()) {
if(hash[c - 'a'] == 1) {
return c;
}
}
return ' ';
}
}
6.搜索与回溯算法(简单)
14-从上到下打印二叉树
class Solution {
public int[] levelOrder(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
List<Integer> list = new LinkedList<>();
if(root != null) queue.add(root);
while(!queue.isEmpty()) {
TreeNode node = queue.poll();
list.add(node.val);
if(node.left != null) {
queue.offer(node.left);
}
if(node.right != null) {
queue.offer(node.right);
}
}
return list.stream().mapToInt(Integer::intValue).toArray();
}
}
15-从上到下打印二叉树 II
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new LinkedList<>();
Queue<TreeNode> queue = new LinkedList<>();
if(root == null) {
return result;
}
queue.offer(root);
while(!queue.isEmpty()) {
List<Integer> list = new LinkedList<>();
int size = queue.size();
for(int i = 0; i < size; i++) {
TreeNode node = queue.poll();
list.add(node.val);
if(node.left != null) {
queue.offer(node.left);
}
if(node.right != null) {
queue.offer(node.right);
}
}
result.add(list);
}
return result;
}
}
16-从上到下打印二叉树 III
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new LinkedList<>();
LinkedList<TreeNode> queue = new LinkedList<>();
boolean flag = true;
if(root == null) {
return result;
}
queue.offer(root);
while(!queue.isEmpty()) {
List<Integer> list = new LinkedList<>();
int size = queue.size();
for(int i = 0; i < size; i++) {
TreeNode node;
if(flag) {
node = queue.pollFirst();
} else {
node = queue.pollLast();
}
list.add(node.val);
if(flag) {
if(node.left != null) {
queue.offerLast(node.left);
}
if(node.right != null) {
queue.offerLast(node.right);
}
} else {
if(node.right != null) {
queue.offerFirst(node.right);
}
if(node.left != null) {
queue.offerFirst(node.left);
}
}
}
flag = !flag;
result.add(list);
}
return result;
}
}
7.搜索与回溯算法(简单)
17-树的子结构
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
if(A == null || B == null) return false;
return dfs(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);
}
public boolean dfs(TreeNode A, TreeNode B) {
if(B == null) return true;
if(A == null) return false;
return A.val == B.val && dfs(A.left, B.left) && dfs(A.right, B.right);
}
}
18-二叉树的镜像
class Solution {
public TreeNode mirrorTree(TreeNode root) {
dfs(root);
return root;
}
public void dfs(TreeNode root) {
if(root == null) return;
TreeNode left = root.right;
TreeNode right = root.left;
root.left = left;
root.right = right;
dfs(root.left);
dfs(root.right);
}
}
19-对称的二叉树
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root == null) return true;
return dfs(root.left, root.right);
}
public boolean dfs(TreeNode left, TreeNode right) {
if(left == null && right == null) {
return true;
}
if(left == null || right == null) {
return false;
}
return left.val == right.val && dfs(left.left, right.right) && dfs(left.right, right.left);
}
}
8.动态规划(简单)
20-斐波那契数列
class Solution {
public int fib(int n) {
if(n <= 1) return n;
int[] dp = new int[n + 1];
dp[1] = 1;
for(int i = 2; i <= n; i++) {
dp[i] = (dp[i - 1] + dp[i - 2]) % 1000000007;
}
return dp[n];
}
}
21-青蛙跳台阶问题
class Solution {
public int numWays(int n) {
if(n <= 1) return 1;
int[] dp = new int[n + 1];
dp[0] = 1;
dp[1] = 1;
for(int i = 2; i <= n; i++) {
dp[i] = (dp[i - 1] + dp[i - 2]) % 1000000007;
}
return dp[n];
}
}
22-股票的最大利润
class Solution {
public int maxProfit(int[] prices) {
if(prices.length == 0) {
return 0;
}
int ans = 0, min = prices[0];
for(int i = 1; i < prices.length; i++) {
if(min < prices[i]) {
ans = Math.max(ans, prices[i] - min);
} else {
min = prices[i];
}
}
return ans;
}
}
9.动态规划(中等)
23-连续子数组的最大和
class Solution {
public int maxSubArray(int[] nums) {
int res = nums[0], sum = 0;
for(int num : nums) {
if(sum <= 0) {
sum = num;
} else {
sum += num;
}
res = Math.max(res, sum);
}
return res;
}
}
24-礼物的最大价值
class Solution {
public int maxValue(int[][] grid) {
int n = grid.length, m = grid[0].length;
int[][] dp = new int[n + 1][m + 1];
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1];
}
}
return dp[n][m];
}
}
10.动态规划(中等)
25-把数字翻译成字符串
class Solution {
public int translateNum(int num) {
char[] cs = String.valueOf(num).toCharArray();
int n = cs.length;
int[] dp = new int[n + 1];
dp[0] = 1;
dp[1] = 1;
for(int i = 2; i <= n; i++) {
int j = (cs[i - 2] - '0') * 10 + (cs[i - 1] - '0');
if(j >= 10 && j <= 25) {
dp[i] = dp[i - 1] + dp[i - 2];
} else {
dp[i] = dp[i - 1];
}
}
return dp[n];
}
}
26-最长不含重复字符的子字符串
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> set = new HashSet<>();
char[] cs = s.toCharArray();
int res = 0;
for(int left = 0, right = 0; right < cs.length; right++) {
while(set.contains(cs[right])) {
set.remove(cs[left++]);
}
set.add(cs[right]);
res = Math.max(res, set.size());
}
return res;
}
}
11.双指针(简单)
27-删除链表的节点
class Solution {
public ListNode deleteNode(ListNode head, int val) {
if(head == null) {
return null;
}
if(head.val == val) {
return head.next;
}
head.next = deleteNode(head.next, val);
return head;
}
}
28-链表中倒数第k个节点
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode left = head, right = head;
for(int i = 0; i < k; i++) {
right = right.next;
}
while(right != null) {
left = left.next;
right = right.next;
}
return left;
}
}
12.双指针(简单)
29-合并两个排序的链表
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1 == null) return l2;
if(l2 == null) return l1;
if(l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
}
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
30-两个链表的第一个公共节点
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null) {
return null;
}
ListNode a = headA, b = headB;
while(a != b) {
a = a == null ? headB : a.next;
b = b == null ? headA : b.next;
}
return a;
}
}
13.双指针(简单)
31-调整数组顺序使奇数位于偶数前面
class Solution {
public int[] exchange(int[] nums) {
for(int i = 0, j = 0; i < nums.length; i++) {
if((nums[i] & 1) == 1) {
int temp = nums[j];
nums[j] = nums[i];
nums[i] = temp;
j++;
}
}
return nums;
}
}
32-和为s的两个数字
class Solution {
public int[] twoSum(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while(left < right) {
int sum = nums[left] + nums[right];
if(sum == target) {
return new int[]{nums[left], nums[right]};
}
if(sum < target) {
left++;
} else {
right--;
}
}
return new int[]{};
}
}
33-翻转单词顺序
class Solution {
public String reverseWords(String s) {
StringBuilder sb = new StringBuilder();
String[] strings = s.split(" ");
for(int i = strings.length - 1; i >= 0; i--) {
if("".equals(strings[i].trim())) {
continue;
}
sb.append(strings[i].trim() + " ");
}
return sb.toString().trim();
}
}
14.搜索与回溯算法(中等)
34-矩阵中的路径
class Solution {
public boolean exist(char[][] board, String word) {
int n = board.length, m = board[0].length;
boolean[][] visited = new boolean[n][m];
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if(dfs(board, word, visited, i, j, 0)) {
return true;
}
}
}
return false;
}
public boolean dfs(char[][] board, String word, boolean[][] visited, int i, int j, int z) {
int n = board.length, m = board[0].length;
if(i < 0 || j < 0 || i >= n || j >= m || visited[i][j] || board[i][j] != word.charAt(z)) {
return false;
}
if(word.length() - 1 == z) {
return true;
}
int[][] moves = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
visited[i][j] = true;
for(int[] move : moves) {
int k = i + move[0];
int v = j + move[1];
if(dfs(board, word, visited, k, v, z + 1)) {
return true;
}
}
visited[i][j] = false;
return false;
}
}
35-机器人的运动范围
class Solution {
public int movingCount(int m, int n, int k) {
boolean[][] visited = new boolean[m][n];
return dfs(visited, k, 0, 0);
}
public int dfs(boolean[][] visited, int k, int i, int j) {
int m = visited.length, n = visited[0].length;
if(i < 0 || j < 0 || i >= m || j >= n || visited[i][j] || (i%10 + i/10 + j%10 + j/10) > k) {
return 0;
}
visited[i][j] = true;
return dfs(visited, k, i + 1, j) + dfs(visited, k, i - 1, j) +
dfs(visited, k, i, j + 1) + dfs(visited, k, i, j - 1) + 1;
}
}
15.搜索与回溯算法(中等)
36-二叉树中和为某一值的路径
class Solution {
private List<List<Integer>> list = new LinkedList<>();
private List<Integer> track = new LinkedList<>();
public List<List<Integer>> pathSum(TreeNode root, int target) {
dfs(root, target, 0);
return list;
}
public void dfs(TreeNode root, int target, int count) {
if(root == null) {
return;
}
count += root.val;
track.add(root.val);
if(count == target && root.left == null && root.right == null) {
list.add(new LinkedList(track));
track.remove(track.size() - 1);
return;
}
dfs(root.left, target, count);
dfs(root.right, target, count);
track.remove(track.size() - 1);
}
}
37-二叉搜索树与双向链表
class Solution {
private Node head, prev;
public Node treeToDoublyList(Node root) {
if(root == null) return null;
dfs(root);
head.left = prev;
prev.right = head;
return head;
}
public void dfs(Node node) {
if(node == null) {
return;
}
dfs(node.left);
if(prev == null) {
head = node;
} else {
prev.right = node;
}
node.left = prev;
prev = node;
dfs(node.right);
}
}
38-二叉搜索树的第k大节点
class Solution {
private int n = 0, result = 0;
public int kthLargest(TreeNode root, int k) {
traverse(root, k);
return result;
}
public void traverse(TreeNode root, int k) {
if(root == null) {
return;
}
traverse(root.right, k);
if(k == ++n) {
result = root.val;
return;
}
traverse(root.left, k);
}
}
16.排序(简单)
39-把数组排成最小的数
class Solution {
public String minNumber(int[] nums) {
List<String> list = new LinkedList<>();
for(int num : nums) {
list.add(String.valueOf(num));
}
list.sort((a, b) -> (a + b).compareTo(b + a));
return String.join("", list);
}
}
40-扑克牌中的顺子
class Solution {
public boolean isStraight(int[] nums) {
int zero = 0, diff = 0;
Arrays.sort(nums);
for(int i = 0; i < nums.length - 1; i++) {
if(nums[i] == 0) {
zero++;
continue;
}
if(nums[i + 1] == nums[i]) {
return false;
}
if(nums[i + 1] - nums[i] > 1) {
diff += nums[i + 1] - nums[i] - 1;
}
}
return zero >= diff;
}
}
17.排序(中等)
41-最小的k个数
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
if(arr.length == k) {
return arr;
}
Arrays.sort(arr);
int[] res = new int[k];
for(int i = 0; i < k; i++) {
res[i] = arr[i];
}
return res;
}
}
42-数据流中的中位数
class MedianFinder {
PriorityQueue<Integer> left;
PriorityQueue<Integer> right;
public MedianFinder() {
left = new PriorityQueue<>((a, b) -> (a - b));
right = new PriorityQueue<>((a, b) -> (b - a));
}
public void addNum(int num) {
left.offer(num);
right.offer(left.poll());
if(left.size() + 1 < right.size()) {
left.offer(right.poll());
}
}
public double findMedian() {
if(left.size() == right.size()) {
return (double)(left.peek() + right.peek()) / 2;
}
return (double)right.peek();
}
}
18.搜索与回溯算法(中等)
43-二叉树的深度
class Solution {
public int maxDepth(TreeNode root) {
return dfs(root, 0);
}
public int dfs(TreeNode root, int deep) {
if(root == null) {
return deep;
}
return Math.max(
dfs(root.left, deep + 1),
dfs(root.right, deep + 1)
);
}
}
44-平衡二叉树
class Solution {
private boolean flag = true;
public boolean isBalanced(TreeNode root) {
dfs(root);
return flag;
}
public int dfs(TreeNode node) {
if(node == null || !flag) {
return 0;
}
int left = dfs(node.left);
int right = dfs(node.right);
if(Math.abs(left - right) > 1) {
flag = false;
return 0;
}
return Math.max(left, right) + 1;
}
}
19.搜索与回溯算法(中等)
45-求1+2+…+n
class Solution {
public int sumNums(int n) {
int sum = n;
boolean flag = n > 0 && (sum += sumNums(n - 1)) > 0;
return sum;
}
}
46-二叉搜索树的最近公共祖先
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null) return null;
if(p.val < root.val && q.val < root.val) {
return lowestCommonAncestor(root.left, p, q);
}
if(p.val > root.val && q.val > root.val) {
return lowestCommonAncestor(root.right, p, q);
}
return root;
}
}
47-二叉树的最近公共祖先
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 = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if(left != null && right != null) {
return root;
}
if(left != null) return left;
if(right != null) return right;
return null;
}
}
20.分治算法(中等)
48-重建二叉树
class Solution {
private Map<Integer, Integer> map = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
for(int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i);
}
return createTree(preorder, 0, 0, inorder.length - 1);
}
public TreeNode createTree(int[] preorder, int preIndex, int left, int right) {
if(left > right) return null;
TreeNode root = new TreeNode(preorder[preIndex]);
int inIndex = map.get(preorder[preIndex]);
root.left = createTree(preorder, preIndex + 1, left, inIndex - 1);
root.right = createTree(preorder, preIndex + inIndex - left + 1, inIndex + 1, right);
return root;
}
}
49-数值的整数次方
class Solution {
public double myPow(double x, int n) {
double result = 1;
long v = n;
if(v < 0) {
x = 1 / x;
v = -v;
}
while(v > 0) {
if((v & 1) == 1) {
result *= x;
}
v >>= 1;
x *= x;
}
return result;
}
}
50-二叉搜索树的后序遍历序列
class Solution {
public boolean verifyPostorder(int[] postorder) {
Deque<Integer> stack = new LinkedList<>();
int preValue = Integer.MAX_VALUE;
for(int i = postorder.length - 1; i >= 0; i--) {
if(postorder[i] > preValue) {
return false;
}
while(!stack.isEmpty() && postorder[i] < stack.peek()) {
preValue = stack.pop();
}
stack.push(postorder[i]);
}
return true;
}
}
21.位运算(简单)
51-二进制中1的个数
public class Solution {
public int hammingWeight(int n) {
int count = 0;
while(n != 0) {
count += n & 1;
n >>>= 1;
}
return count;
}
}
52-不用加减乘除做加法
class Solution {
public int add(int a, int b) {
if(a == 0) return b;
return add((a & b) << 1, a ^ b);
}
}
22.位运算(中等)
53-数组中数字出现的次数
class Solution {
public int[] singleNumbers(int[] nums) {、
int sum = 0;
for(int num : nums) {
sum ^= num;
}
int flag = sum & (-sum), res = 0;
for(int num : nums) {
if((flag & num) != 0) {
res ^= num;
}
}
return new int[]{res, sum ^ res};
}
}
54-数组中数字出现的次数 II
class Solution {
public int singleNumber(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
for(int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
for(Map.Entry<Integer, Integer> entry : map.entrySet()) {
if(entry.getValue() == 1) {
return entry.getKey();
}
}
return -1;
}
}
23.数学(简单)
55-数组中出现次数超过一半的数字
class Solution {
public int majorityElement(int[] nums) {
int result = 0, count = 0;
for(int i = 0; i < nums.length; i++) {
if(count == 0) {
result = nums[i];
count++;
} else {
if(result == nums[i]) {
count++;
} else {
count--;
}
}
}
return result;
}
}
56-构建乘积数组
class Solution {
public int[] constructArr(int[] a) {
int n = a.length;
int[] b = new int[n];
for(int i = 0, pre = 1; i < n; pre *= a[i], i++) {
b[i] = pre;
}
for(int i = n - 1, pre = 1; i >= 0; pre *= a[i], i--) {
b[i] *= pre;
}
return b;
}
}
24.数学(中等)
57-剪绳子
class Solution {
public int cuttingRope(int n) {
if(n <= 3) {
return n - 1;
}
int m = 1;
while(n > 4) {
n -= 3;
m *= 3;
}
return n * m;
}
}
58-和为s的连续正数序列
class Solution {
public int[][] findContinuousSequence(int target) {
List<int[]> list = new LinkedList<>();
for(int left = 1, right = 1, sum = 0; right < target; right++) {
sum += right;
while(sum > target) {
sum -= left++;
}
if(sum == target) {
int[] nums = new int[right - left + 1];
for(int i = 0; i < nums.length; i++) {
nums[i] = left + i;
}
list.add(nums);
}
}
int[][] result = new int[list.size()][];
for(int i = 0; i < list.size(); i++) {
result[i] = list.get(i);
}
return result;
}
}
59-圆圈中最后剩下的数字
class Solution {
public int lastRemaining(int n, int m) {
int res = 0;
for (int i = 2; i <= n; i++) {
res = (res + m) % i;
}
return res;
}
}
25.模拟(中等)
60-顺时针打印矩阵
class Solution {
public int[] spiralOrder(int[][] matrix) {
if(matrix.length == 0) {
return new int[]{};
}
int n = matrix.length, m = matrix[0].length;
boolean[][] visited = new boolean[n + 2][m + 2];
List<Integer> list = new LinkedList<>();
int i = 1, j = 1, flag = 0, mul = n * m;
for(int k = 0; k < n + 2; k++) {
for(int v = 0; v < m + 2; v++) {
if(k == 0 || v == 0 || k == n + 1 || v == m + 1) {
visited[k][v] = true;
}
}
}
while(list.size() < mul) {
if(visited[i][j + 1] && flag == 0 || visited[i + 1][j] && flag == 1
|| visited[i][j - 1] && flag == 2 || visited[i - 1][j] && flag == 3) {
flag = flag == 3 ? 0 : flag + 1;
}
list.add(matrix[i - 1][j - 1]);
visited[i][j] = true;
if(flag == 0) j++;
if(flag == 1) i++;
if(flag == 2) j--;
if(flag == 3) i--;
}
int[] result = new int[list.size()];
for(int v = 0; v < list.size(); v++) {
result[v] = list.get(v);
}
return result;
}
}
61-栈的压入、弹出序列
class Solution {
public boolean validateStackSequences(int[] pushed, int[] popped) {
Deque<Integer> stack = new LinkedList<>();
int n = pushed.length;
for(int i = 0, j = 0; i < n; i++) {
stack.push(pushed[i]);
while(j < n && !stack.isEmpty() && stack.peek() == popped[j]) {
stack.pop();
j++;
}
}
return stack.isEmpty();
}
}
26.字符串(中等)
62-表示数值的字符串
class Solution {
public boolean isNumber(String s) {
if(s.contains("F") || s.contains("f")
|| s.contains("D") || s.contains("d")) {
return false;
}
try {
Double.valueOf(s);
} catch(Exception e) {
return false;
}
return true;
}
}
63-把字符串转换成整数
class Solution {
public int strToInt(String str) {
str = str.trim();
long result = 0;
int flag = 0;
for(int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if(flag == 0) {
if(c == '+' || c == '-' || c >= '0' && c <= '9') {
flag = c == '-' ? -1 : 1;
if(!(c == '+' || c == '-')) {
result = c - '0';
}
} else {
return 0;
}
} else {
if(c >= '0' && c <= '9') {
result = result * 10 + (c - '0');
if(flag == 1 && result >= Integer.MAX_VALUE)
return Integer.MAX_VALUE;
if(flag == -1 && result - 1 >= Integer.MAX_VALUE)
return Integer.MIN_VALUE;
} else {
break;
}
}
}
return flag == -1 ? (int)-result : (int)result;
}
}
27.栈与队列(困难)
64-滑动窗口的最大值
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums.length == 0) return new int[]{};
int[] res = new int[nums.length - k + 1];
LinkedList<Integer> queue = new LinkedList<>();
for(int i = 0; i < nums.length; i++) {
if(!queue.isEmpty() && i - queue.peekFirst() >= k) {
queue.pollFirst();
}
while(!queue.isEmpty() && nums[i] > nums[queue.peekLast()]) {
queue.pollLast();
}
queue.offerLast(i);
if(i >= k - 1) {
res[i - k + 1] = nums[queue.peekFirst()];
}
}
return res;
}
}
65-队列的最大值
class MaxQueue {
Deque<Integer> queue;
Deque<Integer> stack;
public MaxQueue() {
queue = new LinkedList<>();
stack = new LinkedList<>();
}
public int max_value() {
if(stack.isEmpty()) {
return -1;
}
return stack.peek();
}
public void push_back(int value) {
queue.offer(value);
while(!stack.isEmpty() && value > stack.peekLast()) {
stack.pollLast();
}
stack.offer(value);
}
public int pop_front() {
if(queue.isEmpty()) {
return -1;
}
int value = queue.pop();
if(value == stack.peek()) {
stack.pop();
}
return value;
}
}
28.搜索与回溯算法(困难)
66-序列化二叉树
public class Codec {
private String[] values;
private int i;
public String serialize(TreeNode root) {
if(root == null) {
return "#,";
}
StringBuilder sb = new StringBuilder();
sb.append(root.val + ",");
sb.append(serialize(root.left));
sb.append(serialize(root.right));
return sb.toString();
}
public TreeNode deserialize(String data) {
values = data.split(",");
return helper();
}
public TreeNode helper() {
String value = values[i++];
if("#".equals(value)) {
return null;
}
TreeNode root = new TreeNode(Integer.valueOf(value));
root.left = helper();
root.right = helper();
return root;
}
}
67-字符串的排列
class Solution {
private Set<String> set = new HashSet<>();
private char[] cs;
public String[] permutation(String s) {
cs = s.toCharArray();
dfs(0);
return set.toArray(new String[]{});
}
public void dfs(int i) {
if(i == cs.length) {
set.add(new String(cs));
return;
}
for(int j = i; j < cs.length; j++) {
swap(i, j);
dfs(i + 1);
swap(i, j);
}
}
public void swap(int i, int j) {
char c = cs[i];
cs[i] = cs[j];
cs[j] = c;
}
}
29.动态规划(困难)
68-正则表达式匹配
class Solution {
public boolean isMatch(String s, String p) {
return s.matches(p);
}
}
69-丑数
class Solution {
public int nthUglyNumber(int n) {
int[] dp = new int[n + 1];
int i = 1, j = 1, k = 1;
dp[1] = 1;
for(int v = 2; v <= n; v++) {
int min = Math.min(dp[i] * 2, Math.min(dp[j] * 3, dp[k] * 5));
if(min == dp[i] * 2) i++;
if(min == dp[j] * 3) j++;
if(min == dp[k] * 5) k++;
dp[v] = min;
}
return dp[n];
}
}
70-n个骰子的点数
class Solution {
public double[] dicesProbability(int n) {
double[] res = new double[6];
Arrays.fill(res, 1.0 / 6.0);
for(int i = 2; i <= n; i++) {
double[] tmp = new double[i * 6 - (i - 1)];
for(int j = 0; j < res.length; j++) {
for(int k = 0; k < 6; k++) {
tmp[k + j] += res[j] * 1.0 / 6.0;
}
}
res = tmp;
}
return res;
}
}
30.分治算法(困难)
71-打印从1到最大的n位数
class Solution {
public int[] printNumbers(int n) {
int m = (int) Math.pow(10, n);
int[] a = new int[m - 1];
for(int i = 0;i < m - 1; i++){
a[i] = i + 1;
}
return a;
}
}
72-数组中的逆序对
class Solution {
private int count = 0;
public int reversePairs(int[] nums) {
sort(nums, 0, nums.length - 1);
return count;
}
public int[] sort(int[] nums, int left, int right) {
if(left < right) {
int mid = left + (right - left) / 2;
sort(nums, left, mid);
sort(nums, mid + 1, right);
merge(nums, left, mid, right);
}
return nums;
}
public void merge(int[] nums, int left, int mid, int right) {
int[] memo = new int[right - left + 1];
int i = left, j = mid + 1, k = 0;
while(i <= mid && j <= right) {
if(nums[i] <= nums[j]) {
memo[k++] = nums[i++];
} else {
count += mid - i + 1;
memo[k++] = nums[j++];
}
}
while(i <= mid) {
memo[k++] = nums[i++];
}
while(j <= right) {
memo[k++] = nums[j++];
}
for(int v = 0; v < memo.length; v++) {
nums[left + v] = memo[v];
}
}
}
31.数学(困难)
73-剪绳子 II
class Solution {
public int cuttingRope(int n) {
if(n <= 3) {
return n - 1;
}
long m = 1;
while(n > 4) {
n -= 3;
m *= 3;
m = m > 1000000007 ? m % 1000000007 : m;
}
return (int) (m * n % 1000000007);
}
}
74-1~n 整数中 1 出现的次数
75-数字序列中某一位的数字
class Solution {
public int findNthDigit(int n) {
long start = 1, count = 9;
int digit = 1;
while(n > count) {
start *= 10;
digit += 1;
n -= count;
count = start * digit * 9;
}
long num = start + (n - 1) / digit;
return Long.toString(num).charAt((n - 1) % digit) - '0';
}
}