无重复字符的最长子串
class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length();
int[] cnt = new int[128];
int left = 0;
char[] chars = s.toCharArray();
int ans = 0;
for(int right = 0; right < n; right++){
cnt[chars[right]]++;
while(cnt[chars[right]] > 1){
cnt[chars[left]]--;
left++;
}
ans = Math.max(right - left + 1, ans);
}
return ans;
}
}
岛屿数量
class Solution {
public int numIslands(char[][] grid) {
int cnt = 0;
for(int i = 0; i < grid.length; i++){
for(int j = 0; j < grid[0].length; j++){
if(grid[i][j] == '1'){
dfs(grid, i, j);
cnt++;
}
}
}
return cnt;
}
public void dfs(char[][] grid, int i, int j){
if(i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] != '1')
return;
grid[i][j] = '2';
dfs(grid, i - 1, j);
dfs(grid, i + 1, j);
dfs(grid, i, j - 1);
dfs(grid, i, j + 1);
}
}
岛屿的最大面积
class Solution {
public int maxAreaOfIsland(int[][] grid) {
int maxCnt = 0;
for(int i = 0; i < grid.length; i++){
for(int j = 0; j < grid[0].length; j++){
if(grid[i][j] == 1){
int curr = dfs(grid, i, j);
maxCnt = Math.max(maxCnt, curr);
}
}
}
return maxCnt;
}
public int dfs(int[][] grid, int i, int j){
if(i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] != 1){
return 0;
}
grid[i][j] = 2;
return 1 + dfs(grid, i - 1, j) + dfs(grid, i + 1, j) + dfs(grid, i, j - 1) + dfs(grid, i, j + 1);
}
}
二叉树最大宽度
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
private int maxW = 0;
private List<Integer> firstIds = new ArrayList<>();
public int widthOfBinaryTree(TreeNode root) {
dfs(root, 1, 0);
return maxW;
}
public void dfs(TreeNode node, int id, int depth){
if(node == null) return;
if(firstIds.size() == depth){
firstIds.add(id); //记录当前层的最左侧节点id
}
maxW = Math.max(maxW, id - firstIds.get(depth) + 1);
dfs(node.left, id * 2, depth + 1);
dfs(node.right, id * 2 + 1, depth + 1);
}
}
LRU 缓存
class LRUCache {
private int capacity;
private Map<Integer, Integer> map = new LinkedHashMap<>();
public LRUCache(int capacity) {
this.capacity = capacity;
}
public int get(int key) {
Integer value = map.remove(key);
if(value == null){
return -1;
}
map.put(key, value);
return value;
}
public void put(int key, int value) {
Integer val = map.remove(key);
if(val != null){
map.put(key, value);
return;
}
if(capacity == map.size()){
int index = map.keySet().iterator().next();
map.remove(index);
}
map.put(key, value);
}
}
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
最小栈
class MinStack {
private Deque<Integer> stack;
private Deque<Integer> minStack;
public MinStack() {
stack = new ArrayDeque<>();
minStack = new ArrayDeque<>();
}
public void push(int val) {
if(minStack.isEmpty() || val <= minStack.getLast()){
minStack.addLast(val);
}
stack.addLast(val);
}
public void pop() {
if(stack.getLast().equals(minStack.getLast())){
minStack.removeLast();
}
stack.removeLast();
}
public int top() {
return stack.getLast();
}
public int getMin() {
return minStack.getLast();
}
}
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(val);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/
整数转罗马数字
class Solution {
public String intToRoman(int num) {
int[] val = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
String[] off = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
StringBuilder sb = new StringBuilder();
for(int i = 0; i < val.length; i++){
while(num >= val[i]){
num -= val[i];
sb.append(off[i]);
}
}
return sb.toString();
}
}
求根节点到叶节点数字之和
129. 求根节点到叶节点数字之和 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int sumNumbers(TreeNode root) {
if(root == null) return 0;
return dfs(root, 0);
}
public int dfs(TreeNode node, int i){
if(node == null) return 0;
int temp = i * 10 + node.val;
if(node.left == null && node.right == null){
return temp;
}
return dfs(node.left, temp) + dfs(node.right, temp);
}
}
寻找旋转排序数组中的最小值
153. 寻找旋转排序数组中的最小值 - 力扣(LeetCode)
class Solution {
public int findMin(int[] nums) {
int l = 0;
int r = nums.length - 1;
while(l < r){
int mid = l + r >>> 1;
if(nums[mid] < nums[r]){
//mid可能是最小值或者最小值在更左侧
r = mid;
}else{
// mid肯定不是最小值,最小值在右边
l = mid + 1;
}
}
return nums[l];
}
}
最长递增子序列的个数
673. 最长递增子序列的个数 - 力扣(LeetCode)
class Solution {
public int findNumberOfLIS(int[] nums) {
int n = nums.length;
int[] dp = new int[n];
int[] count = new int[n];
Arrays.fill(dp, 1);
Arrays.fill(count, 1);//以nums[i]结尾的最长递增子序列长度
int maxLen = 0;
for(int i = 0; i < n; i++){
for(int j = 0; j < i; j++){
if(nums[i] > nums[j]){
if(dp[j] + 1 > dp[i]){ //之前的序列+1更大
dp[i] = dp[j] + 1;
count[i] = count[j];
}else if(dp[j] + 1 == dp[i]){//找到了相同长度的序列
count[i] += count[j];
}
}
}
maxLen = Math.max(maxLen, dp[i]);
}
int cnt = 0;
for(int i = 0; i < n; i++){
if(maxLen == dp[i]){
cnt += count[i];
}
}
return cnt;
}
}
零钱兑换
class Solution {
public int coinChange(int[] coins, int amount) {
int n = coins.length;
int[] dp = new int[amount + 1];//dp表示凑成某个金额所需要的最少硬币数
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0] = 0;
for(int i = 0; i < n; i++){
for(int j = coins[i]; j <= amount; j++){
if(dp[j - coins[i]] != Integer.MAX_VALUE){
dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);
}
}
}
return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount];
}
}
合并 K 个升序链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
Queue<ListNode> pq = new PriorityQueue<>((p, q) -> (p.val - q.val));
for(ListNode list : lists){
if(list != null){
pq.offer(list);
}
}
//按照队首排序
ListNode dummy = new ListNode(0);
ListNode cur = dummy;
while(!pq.isEmpty()){
ListNode node = pq.poll(); //取出并删除
cur.next = node;
cur = cur.next;
if(node.next != null) pq.offer(node.next);
}
return dummy.next;
}
}
相同的树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
//如果都为空,true
if(p == null && q == null) return true;
//此外如果有一个为空,false
if(p == null || q == null) return false;
//如果不为空,但是value不同,false
if(p.val != q.val) return false;
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
}
另一棵树的子树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
if(root == null) return false;
return isSametree(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);
}
public boolean isSametree(TreeNode p, TreeNode q){
if(p == null && q == null) return true;
if(p == null || q == null) return false;
if(p.val != q.val) return false;
return isSametree(p.left, q.left) && isSametree(p.right, q.right);
}
}
不同路径
class Solution {
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(i == 0 || j == 0){
dp[i][j] = 1;
}else{
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
}
return dp[m - 1][n - 1];
}
}
字符串相加
class Solution {
public String addStrings(String num1, String num2) {
StringBuilder sb = new StringBuilder();
int n = num1.length() - 1;
int m = num2.length() - 1;
int flag = 0;
while(n >= 0 || m >= 0){
int a = n >= 0 ? num1.charAt(n) - '0' : 0;
int b = m >= 0 ? num2.charAt(m) - '0' : 0;
int sum = a + b + flag;
flag = sum / 10;
sb.append(sum % 10);
n--;
m--;
}
if(flag == 1) sb.append(1);
return sb.reverse().toString();
}
}
合并两个有序数组
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int index = m + n - 1;
while(m - 1 >= 0 && n - 1 >= 0){
if(nums1[m - 1] >= nums2[n - 1]){
nums1[index] = nums1[m - 1];
m--;
}else{
nums1[index] = nums2[n - 1];
n--;
}
index--;
}
while(n - 1 >= 0){
nums1[index] = nums2[index];
index--;
n--;
}
}
}
三数之和(重要)
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int n = nums.length;
List<List<Integer>> ans = new ArrayList<>();
Arrays.sort(nums);
for(int i = 0; i < n - 2; i++){ //相当于每次拿一个num,剩下的数通过二分是否能得到和为-num
int num = nums[i];
if(i > 0 && num == nums[i - 1]) continue;
if(num + nums[i + 1] + nums[i + 2] > 0) break;
if(num + nums[n - 2] + nums[n - 1] < 0) continue;
int l = i + 1;
int r = n - 1;
while(l < r){
if(num + nums[l] + nums[r] > 0) r--;
else if(num + nums[l] + nums[r] < 0) l++;
else{
ans.add(List.of(num, nums[l], nums[r]));
for(l++; l < r && nums[l] == nums[l - 1]; l++);
for(r--; l < r && nums[r] == nums[r + 1]; r--);
}
}
}
return ans;
}
}
二叉树的锯齿形层序遍历
103. 二叉树的锯齿形层序遍历 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
Queue<TreeNode> q = new LinkedList<>();
List<List<Integer>> ans = new ArrayList<>();
if(root != null){
q.offer(root);
}
while(!q.isEmpty()){
List<Integer> list = new ArrayList<>();
for(int i = q.size(); i > 0; i--){
TreeNode node = q.poll();
list.add(node.val);
if(node.left != null) q.offer(node.left);
if(node.right != null) q.offer(node.right);
}
if(ans.size() % 2 != 0) Collections.reverse(list);
ans.add(list);
}
return ans;
}
}
接雨水
class Solution {
public int trap(int[] height) {
int n = height.length;
int l = 0;
int r = n - 1;
int preMax = 0;
int sufMax = 0;
int sum = 0;
while(l < r){
preMax = Math.max(preMax, height[l]);
sufMax = Math.max(sufMax, height[r]);
if(preMax < sufMax){
sum += preMax - height[l];
l++;
}else{
sum += sufMax - height[r];
r--;
}
}
return sum;
}
}
复原 IP 地址
暴力匹配
class Solution {
public List<String> restoreIpAddresses(String s) {
List<String> ans = new ArrayList<>();
int n = s.length();
for(int i = 1; i < 4 && i < n; i++){
for(int j = i + 1; j < i + 4 && j < n; j++){
for(int k = j + 1; k < j + 4 && k < n; k++){
String s1 = s.substring(0, i);
String s2 = s.substring(i, j);
String s3 = s.substring(j, k);
String s4 = s.substring(k);
if(valid(s1) && valid(s2) && valid(s3) && valid(s4)){
ans.add(s1 + "." + s2 + "." + s3 + "." + s4);
}
}
}
}
return ans;
}
public boolean valid(String str){
if(str.length() == 0 || str.length() > 3) return false;
if(str.length() > 1 && str.charAt(0) == '0') return false;
int num = Integer.parseInt(str);
return num >=0 && num <= 255;
}
}
回溯法
class Solution {
List<String> ans = new ArrayList<>();
public List<String> restoreIpAddresses(String s) {
if(s.length() < 4 || s.length() > 12) return ans;
backtrack(s, 0, new ArrayList<>());
return ans;
}
public void backtrack(String s, int start, List<String> temp){
//中止条件 temp已经有四段
if(temp.size() == 4){
if(start == s.length()){
ans.add(String.join(".", temp));
}
return;
}
for(int len = 1; len <= 3; len++){
if(start + len > s.length()) break;
String str = s.substring(start, start + len);
if(isValid(str)){
temp.add(str);
backtrack(s, start + len, temp);
temp.remove(temp.size() - 1);
}
}
}
public boolean isValid(String s){
if(s.length() > 1 && s.charAt(0) == '0') return false;
int num = 0;
for(int i = 0; i < s.length(); i++){
num = num * 10 + (s.charAt(i) - '0');
}
if(num >= 0 && num <= 255) return true;
return false;
}
}
最大正方形
dpij 表示以 matrixij 为右下角的的最大正方形的边长。
class Solution {
public int maximalSquare(char[][] matrix) {
int n = matrix.length;
int m = matrix[0].length;
int[][] dp = new int[n][m];
int edge = 0;
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if(matrix[i][j] == '1'){
if(i == 0 || j == 0){ //如果是1,并且在第一行第一列,那么边长就是1
dp[i][j] = 1;
}else{ //否则以ij为右下角的正方形的边长是由上、左上、左决定的,如果当前边长想为k,这三个点至少为k-1
dp[i][j] = Math.min(Math.min(dp[i - 1][j - 1], dp[i - 1][j]), dp[i][j - 1]) + 1;
}
edge = Math.max(edge, dp[i][j]);
}
}
}
return edge * edge;
}
}
连续的子数组和
class Solution {
public boolean checkSubarraySum(int[] nums, int k) {
int n = nums.length;
int[] s = new int[n + 1];
s[0] = 0;
for(int i = 1; i <= n; i++){
s[i] = s[i - 1] + nums[i - 1];
} //计算前缀和
for(int i = 1; i <= n; i++){
for(int j = i + 1; j <= n; j++){
if((s[j] - s[i - 1]) % k == 0 && j - i >= 1){
return true;
}
}
}
return false;
}
}
class Solution {
public boolean checkSubarraySum(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
int n = nums.length;
int preSum = 0;
map.put(0, - 1);
for(int i = 0; i < n; i++){
preSum += nums[i];
int mod = preSum % k;
if(map.containsKey(mod)){ //多次遇到这个余数
if(i - map.get(mod) >= 2){
return true;
}
}else{ //如果是第一次put
map.put(mod, i);
}
}
return false;
}
}
路径总和
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root == null) return false;
if(root.left == null && root.right == null) return root.val == targetSum;
return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root == null) return false;
return travelPath(root, targetSum - root.val);
}
public boolean travelPath(TreeNode root, int count){
if(root.left == null && root.right == null && count == 0) return true;
if(root.left == null && root.right == null) return false;
if(root.left != null){
count -= root.left.val;
if(travelPath(root.left, count)) return true;
count += root.left.val;
}
if(root.right != null){
count -= root.right.val;
if(travelPath(root.right, count)) return true;
count += root.right.val;
}
return false;
}
}
从前序与中序遍历序列构造二叉树(重点)
105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
Map<Integer, Integer> map;
public TreeNode buildTree(int[] preorder, int[] inorder) {
map = new HashMap<>();
for(int i = 0; i < inorder.length; i++){
map.put(inorder[i], i);
}
return findNode(preorder, 0, preorder.length, inorder, 0, inorder.length);
}
public TreeNode findNode(int[] preorder, int preStart, int preEnd, int[]inorder, int inStart, int inEnd){
if(preStart >= preEnd || inStart >= inEnd) return null;
//从前序遍历找到根节点,找到根节点在中序遍历的位置,分割左右子树,重复以上过程
int rootIndex = map.get(preorder[preStart]); //找到中序遍历中根节点的位置
TreeNode root = new TreeNode(inorder[rootIndex]);
//分割数组
int lenofLeft = rootIndex - inStart;//左子树的长度
root.left = findNode(preorder, preStart + 1, preStart + 1 + lenofLeft, inorder, inStart, rootIndex);
root.right = findNode(preorder, preStart + 1 + lenofLeft, preEnd, inorder, rootIndex + 1, inEnd);
return root;
}
}
跳跃训练
class Solution {
public int trainWays(int num) {
int a = 1, b = 1, sum = 0;
//a存f(n),b存f(n + 1), sum计算f(n + 1)
for(int i = 0; i < num; i++){
sum = (a + b) % 1000000007;
a = b;
b = sum;
}
return a;
}
}
全排列
class Solution {
public List<List<Integer>> permute(int[] nums) {
int n = nums.length;
List<List<Integer>> ans = new ArrayList<>();
boolean[] used = new boolean[n];
dfs(ans, nums, 0, used, new ArrayList<>());
return ans;
}
public void dfs(List<List<Integer>> ans, int[] nums, int depth, boolean[] used, List<Integer> tmp){
if(depth == nums.length){
ans.add(new ArrayList(tmp));
return;
}
for(int i = 0; i < nums.length; i++){
if(!used[i]){
tmp.add(nums[i]);
used[i] = true;
dfs(ans, nums, depth + 1, used, tmp);
used[i] = false;
tmp.remove(tmp.size() - 1);
}
}
}
}
K 个一组反转链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pre = dummy;
while(true){
ListNode end = pre;
for(int i = 0; i < k && end != null; i++) end = end.next;
if(end == null) break;
ListNode cur = pre.next;
for(int i = 1; i < k; i++){
ListNode next = cur.next;
cur.next = next.next;
next.next = pre.next;
pre.next = next;
}
pre = cur;
}
return dummy.next;
}
}
最长回文子串
class Solution {
private int start = 0, end = 0;
public String longestPalindrome(String s) {
int n = s.length();
if(n < 2) return s;
for(int i = 0; i < n - 1; i++){
reform(s, i, i);
reform(s, i, i + 1);
}
return s.substring(start, end);
}
public void reform(String s, int l, int r){
while(l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)){
l--;
r++;
}
int len = r - l - 1;
if(len > end - start){
start = l + 1;
end = r;
}
}
}
划分为 K 个相等的子集
698. 划分为k个相等的子集 - 力扣(LeetCode)
class Solution {
public boolean canPartitionKSubsets(int[] nums, int k) {
int sum = 0;
for(int num : nums) sum += num;
if(sum % k != 0) return false;
int target = sum / k;
int[] bucket = new int[k];
return backTrack(nums, nums.length - 1, bucket, target);
}
public boolean backTrack(int[] nums, int index, int[] bucket, int target){
if(index < 0) return true;
for(int i = 0; i < bucket.length; i++){
if(bucket[i] + nums[index] <= target){
bucket[i] += nums[index];
if(backTrack(nums, index - 1, bucket, target)){
return true;
}
bucket[i] -= nums[index];
}
if(bucket[i] == 0) break;
}
return false;
}
}
验证二叉搜索树
二叉搜索树中序遍历是升序的
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
private long maxVal = Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
if(root == null) return true;
boolean left = isValidBST(root.left);
if(root.val > maxVal){
maxVal = root.val;
}else{
return false;
}
boolean right = isValidBST(root.right);
return left && right;
}
}
旋转链表
用 list 存链表,用新数组存旋转后的 list
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode rotateRight(ListNode head, int k) {
List<Integer> list = new ArrayList<>();
while(head != null){
list.add(head.val);
head = head.next;
}
int n = list.size();
int[] nums = new int[n + 1];
for(int i = 1; i <= n; i++){
int nextIndex = (i + k) % n;
if(nextIndex == 0){
nums[n] = list.get(i - 1);
}else{
nums[nextIndex] = list.get(i - 1);
}
}
ListNode dummy = new ListNode(0);
ListNode cur = dummy;
for(int i = 1; i <= n; i++){
cur.next = new ListNode(nums[i]);
cur = cur.next;
}
return dummy.next;
}
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if(head == null || head.next == null || k == 0) return head;
ListNode oldEnd = head;
int n = 1;
while(oldEnd.next != null){
n++;
oldEnd = oldEnd.next;
}//old已经到达尾部
k = k % n;
oldEnd.next = head; //成环
ListNode newEnd = head;
for(int i = 0; i < n - k - 1; i++){
newEnd = newEnd.next;
}
ListNode ans = newEnd.next;
newEnd.next = null;
return ans;
}
}
搜索旋转排序数组
class Solution {
public int search(int[] nums, int target) {
int n = nums.length;
int l = 0;
int r = n - 1;
while(l < r){
int mid = l + r >>> 1;
if(check(nums, target, mid)) r = mid;
else l = mid + 1;
}
return nums[l] == target ? l : -1;
}
public boolean check(int[] nums, int target, int mid){
int last = nums[nums.length - 1]; //取最后一位
int cur = nums[mid];
if(cur < last){ //mid在第二段,想要缩短r的话
return cur >= target || target > last; //要么target也在第二段并且cur>=target,要么target>last,target在第一段
}
//mid在第一段
return cur >= target && target > last;
}
}
搜索旋转排序数组 II
81. 搜索旋转排序数组 II - 力扣(LeetCode)
class Solution {
public boolean search(int[] nums, int target) {
int n = nums.length;
int l = 0;
int r = n - 1;
while(l < r){
int mid = l + r >>> 1;
if(nums[mid] == target) return true;
if(nums[mid] == nums[r]){
r--;
continue;
}
if(check(nums, target, mid, r)) r = mid;
else l = mid + 1;
}
return nums[l] == target;
}
public boolean check(int[] nums, int target, int mid, int r){
int cur = nums[mid];
int last = nums[r];
if(cur < last){
return cur >= target || target > last;
}
return cur >= target && target > last;
}
}
有序数组的单一元素
540. 有序数组中的单一元素 - 力扣(LeetCode)
class Solution {
public int singleNonDuplicate(int[] nums) {
int l = 0;
int r = nums.length - 1;
while(l < r){
int mid = l + r >>> 1;
if(mid % 2 == 1){
mid--;
}
if(nums[mid] == nums[mid + 1]){
l = mid + 2;
}else r = mid;
}
return nums[l];
}
}
x 的平方根
注意 int 溢出的问题,不过耗时非常高。
class Solution {
public int mySqrt(int x) {
if (x == 0) return 0;
long ans = 1;
// 注意:这里的 i 也必须是 long,否则 i*i 依然会先按 int 计算导致溢出
for (long i = 1; i <= x / i; i++) {
ans = i;
}
return (int) ans;
}
}
class Solution {
public int mySqrt(int x) {
if(x < 2) return x;
int l = 1, r = x / 2;
int ans = 0;
while(l <= r){
int mid = l + r >>> 1;
if(mid <= x / mid){
ans = mid;
l = mid + 1;
}else{
r = mid - 1;
}
}
return ans;
}
}
前 K 个高频元素
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
for(int num : nums){
map.put(num, map.getOrDefault(num, 0) + 1);
}
PriorityQueue<Integer> pq = new PriorityQueue<>((p, q) -> (map.get(q) - map.get(p))); //大根堆
for(Integer num : map.keySet()){
pq.offer(num);
}
int[] ans = new int[k];
for(int i = 0; i < k; i++){
ans[i] = pq.poll();
}
return ans;
}
}
最小路径和
class Solution {
public int minPathSum(int[][] grid) {
int n = grid.length;
int m = grid[0].length;
int[][] dp = new int[n][m];
dp[0][0] = grid[0][0];
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if(i == 0 && j == 0) continue;
else if(i == 0 && j != 0) dp[i][j] = dp[i][j - 1] + grid[i][j];
else if(j == 0 && i != 0) dp[i][j] = dp[i - 1][j] + grid[i][j];
else dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
}
}
return dp[n - 1][m - 1];
}
}
二叉树的层序遍历
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
Queue<TreeNode> q = new LinkedList<>();
List<List<Integer>> ans = new ArrayList<>();
if(root == null) return ans;
q.offer(root);
while(!q.isEmpty()){
List<Integer> list = new ArrayList<>();
for(int i = q.size(); i > 0; i--){
TreeNode node = q.poll();
list.add(node.val);
if(node.left != null) q.offer(node.left);
if(node.right != null) q.offer(node.right);
}
ans.add(list);
}
return ans;
}
}
有效的字母异位分词
class Solution {
public boolean isAnagram(String s, String t) {
char[] charS = s.toCharArray();
char[] charT = t.toCharArray();
int[] cntS = new int[128];
int[] cntT = new int[128];
for(char c : charS) cntS[c]++;
for(char c : charT) cntT[c]++;
for(int i = 0; i < 128; i++){
if(cntS[i] != cntT[i]){
return false;
}
}
return true;
}
}
删除被覆盖区间
class Solution {
public int removeCoveredIntervals(int[][] intervals) {
Arrays.sort(intervals, (a, b) ->(a[0] != b[0] ? a[0] - b[0] : b[1] - a[1]));
int count = intervals.length;
int maxNum = 0;
for(int[] num : intervals){
if(num[1] > maxNum){
maxNum = num[1]; //更新当前右端点最大值
}else{ //如果num[1]<= maxNum,说明当前区间会被覆盖
count--;
}
}
return count;
}
}
验证回文串
class Solution {
public boolean isPalindrome(String s) {
StringBuilder sb = new StringBuilder();
char[] ch = s.toCharArray();
//0-9 48-57 A-Z 65-90 a-z 97-
for(char c : ch){
if(c >= 'a' && c <= 'z' || c >= '0' && c <= '9'){
sb.append(c);
}else if(c >= 'A' && c <= 'Z'){
sb.append((char)(c + 32));
}else continue;
}
for(int i = 0; i < sb.length(); i++){
if(sb.charAt(i) != sb.charAt(sb.length() - i - 1)){
return false;
}
}
return true;
}
}
字符串相乘
class Solution {
public String multiply(String num1, String num2) {
if(num1.equals("0") || num2.equals("0")) return "0";
int n = num1.length();
int m = num2.length();
int[] ans = new int[n + m];
for(int i = n - 1; i >= 0; i--){
int a = num1.charAt(i) - '0';
for(int j = m - 1; j >= 0; j--){
int b = num2.charAt(j) - '0';
int p1 = i + j; //进位
int p2 = i + j + 1; //存当前位值
int sum = a * b + ans[p2];
ans[p2] = sum % 10;
ans[p1] += sum / 10;
}
}
StringBuilder sb = new StringBuilder();
for(int i = 0; i < ans.length; i++){
if(i == 0 && ans[i] == 0) continue;
sb.append(ans[i]);
}
return sb.toString();
}
}
分割等和子集
class Solution {
public boolean canPartition(int[] nums) {
int n = nums.length;
if(n == 1) return false;
int sum = 0;
for(int i = 0; i < n; i++){
sum += nums[i];
}
if(sum % 2 != 0) return false;
int target = sum / 2;
boolean[] dp = new boolean[target + 1];
dp[0] = true;
//处理过的元素和恰好为i的子集
for(int i = 1; i < n; i++){
for(int j = target; j >= nums[i]; j--){
dp[j] = dp[j] || dp[j - nums[i]];
if(dp[target]) return true;
}
}
return false;
}
}
反转链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode cur = head;
ListNode pre = null;
while(cur != null){
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
}
环形链表
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
if(head == null || head.next == null) return false;
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
if(slow == fast) return true;
}
return false;
}
}
有效的括号
class Solution {
public boolean isValid(String s) {
if(s.length() % 2 != 0) return false;
Map<Character, Character> map = new HashMap<>();
map.put('(', ')');
map.put('{', '}');
map.put('[', ']');
Deque<Character> q = new ArrayDeque<>();
char[] ch = s.toCharArray();
for(char c : ch){
if(map.containsKey(c)){
q.addLast(c);
}else{
if(q.isEmpty() || map.get(q.removeLast()) != c){
return false;
}
}
}
return q.isEmpty();
}
}
LRU 缓存
class LRUCache {
private int capacity;
private Map<Integer, Integer> map = new LinkedHashMap<>();
public LRUCache(int capacity) {
this.capacity = capacity;
}
public int get(int key) {
Integer value = map.remove(key);
if(value == null) return -1;
map.put(key, value);
return value;
}
public void put(int key, int value) {
Integer val = map.remove(key);
if(val != null){
map.put(key, value);
return;
}
if(map.size() == capacity){
Integer index = map.keySet().iterator().next();
map.remove(index);
}
map.put(key, value);
}
}
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
数组中的第 K 个最大元素
215. 数组中的第K个最大元素 - 力扣(LeetCode)
class Solution {
public int findKthLargest(int[] nums, int k) {
List<Integer> list = new ArrayList<>();
for(int num : nums){
list.add(num);
}
return searchK(list, k);
}
public int searchK(List<Integer> list, int k){
int n = list.size();
Random r = new Random();
int pivot = list.get(r.nextInt(n));
List<Integer> small = new ArrayList<>();
List<Integer> equal = new ArrayList<>();
List<Integer> big = new ArrayList<>();
for(int i : list){
if(i > pivot) big.add(i);
else if(i < pivot) small.add(i);
else equal.add(i);
}
if(k <= big.size()){
return searchK(big, k);
}
if(n - k < small.size()){
return searchK(small, k - (n - small.size()));
}
return pivot;
}
}
二叉树的层序遍历
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ans = new ArrayList<>();
if(root == null) return ans;
Deque<TreeNode> q = new ArrayDeque<>();
q.addLast(root);
while(!q.isEmpty()){
int n = q.size();
List<Integer> tmp = new ArrayList<>();
for(int i = n; i > 0; i--){
TreeNode node = q.removeFirst();
tmp.add(node.val);
if(node.left != null) q.addLast(node.left);
if(node.right != null) q.addLast(node.right);
}
ans.add(tmp);
}
return ans;
}
}