Leetcode hot100 Java刷题
文章目录
- 快排
- 146. LRU 缓存
- acm模式树的前中后序遍历
- acm模式链表的基本操作
- 1. 两数之和
- 49. 字母异位词分组
- 128. 最长连续序列
- 283. 移动零
- 11. 盛最多水的容器
- 15. 三数之和
- 42. 接雨水
- 53. 最大子数组和
- 56. 合并区间
- 73. 矩阵置零
- 48. 旋转图像
- 141. 环形链表
- 142. 环形链表 II
- 24. 两两交换链表中的节点
- 238. 除自身以外数组的乘积
- 3. 无重复字符的最长子串
- 438. 找到字符串中所有字母异位词
- 560. 和为 K 的子数组
- 239. 滑动窗口最大值
- 160. 相交链表
- 79. 单词搜索
- 206. 反转链表
- 234. 回文链表
- 138. 随机链表的复制
- 46. 全排列
- 78. 子集
- 17. 电话号码的字母组合
- 39. 组合总和
- 22. 括号生成
- 279. 完全平方数
- 62. 不同路径
- 64. 最小路径和
- 169. 多数元素
- 94. 二叉树的中序遍历
- 二叉树的最大深度
- 226. 翻转二叉树
- 101. 对称二叉树
- 543. 二叉树的直径
- 102. 二叉树的层序遍历
- 2962. 统计最大元素出现至少 K 次的子数组
- 2302. 统计得分小于 K 的子数组数目
- 2444. 统计定界子数组的数目
- 61. 旋转链表
- LCP 09. 最小跳跃次数
- 199. 二叉树的右视图
- 215. 数组中的第K个最大元素
- 25. K 个一组翻转链表
- 21. 合并两个有序链表
- 322. 零钱兑换`在这里插入代码片`
- 55. 跳跃游戏
- 994. 腐烂的橘子
- 2294. 划分数组使最大差为 K
- 2966. 划分数组并满足最大差限制
- 1432. 改变一个整数能得到的最大差值
- 2616. 最小化数对的最大差值(很不错的一题)
快排
public class QuickSort {public static void main(String[] args) {int[] array = {64, 34, 25, 12, 22, 11, 90};System.out.println("原始数组:");printArray(array);quickSort(array, 0, array.length - 1);System.out.println("排序后的数组:");printArray(array);}// 快速排序主方法public static void quickSort(int[] array, int low, int high) {if (low < high) {// 找到分区点int pivotIndex = partition(array, low, high);// 递归对左右子数组进行排序quickSort(array, low, pivotIndex - 1); // 排序左子数组quickSort(array, pivotIndex + 1, high); // 排序右子数组}}// 分区操作public static int partition(int[] array, int low, int high) {// 选择最后一个元素作为基准int pivot = array[high];int i = low - 1; // i 是小于基准值的元素的索引for (int j = low; j < high; j++) {// 如果当前元素小于或等于基准值if (array[j] <= pivot) {i++;// 交换 array[i] 和 array[j]int temp = array[i];array[i] = array[j];array[j] = temp;}}// 交换 array[i+1] 和 array[high](基准值)int temp = array[i + 1];array[i + 1] = array[high];array[high] = temp;return i + 1; // 返回基准值的索引}// 打印数组的方法public static void printArray(int[] array) {for (int value : array) {System.out.print(value + " ");}System.out.println();}
}
优化随机选择基准元素
class Solution {public int[] sortArray(int[] nums) {randomizedQuicksort(nums, 0, nums.length - 1);return nums;}public void randomizedQuicksort(int[] nums, int l, int r) {if (l < r) {int pos = randomizedPartition(nums, l, r);randomizedQuicksort(nums, l, pos - 1);randomizedQuicksort(nums, pos + 1, r);}}public int randomizedPartition(int[] nums, int l, int r) {int i = new Random().nextInt(r - l + 1) + l; // 随机选一个作为我们的主元swap(nums, r, i);return partition(nums, l, r);}public int partition(int[] nums, int l, int r) {int pivot = nums[r];int i = l - 1;for (int j = l; j <= r - 1; ++j) {if (nums[j] <= pivot) {i = i + 1;swap(nums, i, j);}}swap(nums, i + 1, r);return i + 1;}private void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}
}
146. LRU 缓存
官方题解
public class LRUCache {class DLinkedNode {int key;int value;DLinkedNode prev;DLinkedNode next;public DLinkedNode() {}public DLinkedNode(int _key, int _value) {key = _key; value = _value;}}private Map<Integer, DLinkedNode> cache = new HashMap<Integer, DLinkedNode>();private int size;private int capacity;private DLinkedNode head, tail;public LRUCache(int capacity) {this.size = 0;this.capacity = capacity;// 使用伪头部和伪尾部节点head = new DLinkedNode();tail = new DLinkedNode();head.next = tail;tail.prev = head;}public int get(int key) {DLinkedNode node = cache.get(key);if (node == null) {return -1;}// 如果 key 存在,先通过哈希表定位,再移到头部moveToHead(node);return node.value;}public void put(int key, int value) {DLinkedNode node = cache.get(key);if (node == null) {// 如果 key 不存在,创建一个新的节点DLinkedNode newNode = new DLinkedNode(key, value);// 添加进哈希表cache.put(key, newNode);// 添加至双向链表的头部addToHead(newNode);++size;if (size > capacity) {// 如果超出容量,删除双向链表的尾部节点DLinkedNode tail = removeTail();// 删除哈希表中对应的项cache.remove(tail.key);--size;}}else {// 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部node.value = value;moveToHead(node);}}private void addToHead(DLinkedNode node) {node.prev = head;node.next = head.next;head.next.prev = node;head.next = node;}private void removeNode(DLinkedNode node) {node.prev.next = node.next;node.next.prev = node.prev;}private void moveToHead(DLinkedNode node) {removeNode(node);addToHead(node);}private DLinkedNode removeTail() {DLinkedNode res = tail.prev;removeNode(res);return res;}
}
acm模式树的前中后序遍历
https://kamacoder.com/problempage.php?pid=1021
import java.util.*;
class TreeNode{char val;TreeNode left;TreeNode right;TreeNode(char val){this.val = val;}
}public class Main{public static void main(String[] arg){Scanner in = new Scanner(System.in);int n = in.nextInt();in.nextLine(); //忽略nextInt()的换行符。List<List<String>> list = new ArrayList<>();for(int i = 0; i < n; i++){String[] line = in.nextLine().split(" ");List<String> str = Arrays.asList(line);list.add(str);} TreeNode root = builderListToTree(list);preOrderTree(root);System.out.println();inOrderTree(root);System.out.println();postOrderTree(root);System.out.println();}private static TreeNode builderListToTree(List<List<String>> list){if(list == null) return null;List<TreeNode> nodeList = new ArrayList<>();for(int i = 0; i<list.size(); i++){TreeNode node = new TreeNode(list.get(i).get(0).charAt(0));nodeList.add(node);}for(int i = 0; i< nodeList.size(); i++){int leftIndex = Integer.parseInt(list.get(i).get(1));int rightIndex = Integer.parseInt(list.get(i).get(2));if(leftIndex != 0){nodeList.get(i).left = nodeList.get(leftIndex-1);}if(rightIndex != 0){nodeList.get(i).right = nodeList.get(rightIndex-1);}}return nodeList.get(0);}private static void preOrderTree(TreeNode root){if(root == null) return;System.out.print(root.val);preOrderTree(root.left);preOrderTree(root.right);}private static void inOrderTree(TreeNode root){if(root == null) return;inOrderTree(root.left);System.out.print(root.val);inOrderTree(root.right);}private static void postOrderTree(TreeNode root){if(root == null) return;postOrderTree(root.left);postOrderTree(root.right);System.out.print(root.val);}}
acm模式链表的基本操作
https://kamacoder.com/problempage.php?pid=1017
import java.util.*;
class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);MyLinkedList list = new MyLinkedList();int len = sc.nextInt();for (int i = 0; i < len; i++) {list.addFirst(sc.nextInt());}int oNum = sc.nextInt();sc.nextLine();while(oNum-- > 0){String[] o = sc.nextLine().split(" ");if(o[0].equals("show")){list.show();}else if(o[0].equals("delete")){list.delete(Integer.parseInt(o[1]) - 1);}else if(o[0].equals("get")){list.get(Integer.parseInt(o[1]) - 1);}else if(o[0].equals("insert")){list.insert(Integer.parseInt(o[1]) - 1, Integer.parseInt(o[2]));}}}
}class ListNode{int val;ListNode next;public ListNode(){}public ListNode(int val){this.val = val;}public ListNode(int val, ListNode next){this.val = val;this.next = next;}
}class MyLinkedList {public ListNode dummyhead = new ListNode(-1, null); //链表的头public int len = 0;// 头插法public void addFirst(int val) {ListNode cur = new ListNode(val);if(len == 0){dummyhead.next = cur;len++;return;}cur.next = dummyhead.next;dummyhead.next = cur;len++;}// 删除idx位置的节点(从0开始)public void delete(int idx){if(idx > len - 1){System.out.println("delete fail");return;}ListNode cur = dummyhead;while(idx-- > 0){cur = cur.next;}cur.next = cur.next.next;System.out.println("delete OK");len--;}// 插入(从0开始)public void insert(int idx, int val){if(idx > len){System.out.println("insert fail");return;}ListNode cur = dummyhead;ListNode node = new ListNode(val);while(idx-- > 0){cur = cur.next;}node.next = cur.next;cur.next = node;System.out.println("insert OK");len++;}// 查找public void get(int idx){if(idx > len - 1){System.out.println("get fail");}ListNode cur = dummyhead;while(idx-- >= 0){cur = cur.next;}System.out.println(cur.val);}// 遍历输出public void show(){if(len == 0){System.out.println("Link list is empty");return;}ListNode cur = dummyhead;while(cur.next.next != null){cur = cur.next;System.out.print(cur.val);System.out.print(" ");}System.out.print(cur.next.val);System.out.println();}// 查长度public int size(){return len;}
}
1. 两数之和
class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer, Integer> hashmap = new HashMap<>();for (int i = 0; i < nums.length; i++) {int complement = target - nums[i];if (hashmap.containsKey(complement)) {return new int[]{i, hashmap.get(complement)};}hashmap.put(nums[i], i);}return new int[]{}; // 如果没有找到,返回空数组}
}
49. 字母异位词分组
class Solution {public List<List<String>> groupAnagrams(String[] strs) {Map<String,List<String>> hashmap=new HashMap<>();for(String str: strs){char[] array=str.toCharArray();Arrays.sort(array);String key=new String(array);List<String> list=hashmap.getOrDefault(key,new ArrayList<String>());list.add(str);hashmap.put(key,list);}return new ArrayList<List<String>>(hashmap.values());}
}
class Solution {public List<List<String>> groupAnagrams(String[] strs) {Map<String, List<String>> map = new HashMap<String, List<String>>();for (String str : strs) {int[] counts = new int[26];int length = str.length();for (int i = 0; i < length; i++) {counts[str.charAt(i) - 'a']++;}// 将每个出现次数大于 0 的字母和出现次数按顺序拼接成字符串,作为哈希表的键StringBuffer sb = new StringBuffer();for (int i = 0; i < 26; i++) {if (counts[i] != 0) {sb.append((char) ('a' + i));sb.append(counts[i]);}}String key = sb.toString();List<String> list = map.getOrDefault(key, new ArrayList<String>());list.add(str);map.put(key, list);}return new ArrayList<List<String>>(map.values());}
}
128. 最长连续序列
class Solution {public int longestConsecutive(int[] nums) {Set<Integer> num_set = new HashSet<Integer>();for (int num : nums) {num_set.add(num);}int longestStreak = 0;for (int num : num_set) {if (!num_set.contains(num - 1)) {int currentNum = num;int currentStreak = 1;while (num_set.contains(currentNum + 1)) {currentNum += 1;currentStreak += 1;}longestStreak = Math.max(longestStreak, currentStreak);}}return longestStreak;}
}
看完答案后自己写的版本
class Solution {public int longestConsecutive(int[] nums) {Set<Integer> set=new HashSet<>();for(int num:nums){set.add(num);}int maxLen=0;for(int num:set){if(!set.contains(num-1)){int currentNum=num;int currentLen=1;while(set.contains(currentNum+1)){currentLen+=1;currentNum+=1;}if (currentLen>maxLen){maxLen=currentLen;}}}return maxLen;}
}
283. 移动零
使用双指针,左指针指向当前已经处理好的序列的尾部,右指针指向待处理序列的头部。
右指针不断向右移动,每次右指针指向非零数,则将左右指针对应的数交换,同时左指针右移。
注意到以下性质:
- 左指针左边均为非零数;
- 右指针左边直到左指针处均为零。
因此每次交换,都是将左指针的零与右指针的非零数交换,且非零数的相对顺序并未改变。
class Solution {public void moveZeroes(int[] nums) {int i=0,j=0;while(j<nums.length){if(nums[j]!=0){swap(nums,i,j);i++;}j++;}}public void swap(int[] nums,int i,int j){int temp=nums[i];nums[i]=nums[j];nums[j]=temp;}
}
11. 盛最多水的容器
// class Solution {
// public int maxArea(int[] height) {
// int result=0;
// int n=height.length;
// for(int i=0;i<n-1;i++){
// for(int j=i+1;j<n;j++){
// result=Math.max( (j-i)*Math.min(height[i],height[j]) ,result );// }
// }// return result;// }
// }class Solution {public int maxArea(int[] height) {int result=0;int n=height.length;int i=0,j=n-1;while(i<j){result=Math.max( (j-i)*Math.min(height[i],height[j]) ,result );if(height[i]>height[j]){j--;}else{i++;}}return result;}
}
15. 三数之和
//没有 去重
// class Solution {
// public List<List<Integer>> threeSum(int[] nums) {
// List<List<Integer>> result=new ArrayList<>();
// Arrays.sort(nums);
// int n=nums.length;
// for(int i=0;i<n-2;i++){
// int j=i+1,k=n-1;
// while(j<k){
// if(nums[i]+nums[j]+nums[k]>0){
// k--;
// }else if(nums[i]+nums[j]+nums[k]<0){
// j++;
// }else{
// result.add(new ArrayList<>(Arrays.asList(nums[i], nums[j], nums[k])));
// k--;
// j++;
// // result.add( new ArrayList{ num[i],nums[j],nums[k] }; );
// }
// }
// }
// return result;
// }
// }class Solution {public List<List<Integer>> threeSum(int[] nums) {Set<List<Integer>> result=new HashSet<>();Arrays.sort(nums);int n=nums.length;for(int i=0;i<n-2;i++){int j=i+1,k=n-1;while(j<k){if(nums[i]+nums[j]+nums[k]>0){k--;}else if(nums[i]+nums[j]+nums[k]<0){j++;}else{result.add(new ArrayList<>(Arrays.asList(nums[i], nums[j], nums[k])));k--;j++;}}}return new ArrayList<>(result);}
}
别人的题解
class Solution {public List<List<Integer>> threeSum(int[] nums) {Arrays.sort(nums); // 先排序List<List<Integer>> res = new ArrayList<>();for (int i = 0; i < nums.length; i++) {// 跳过重复元素if (i > 0 && nums[i] == nums[i - 1]) continue;// 双指针,目标是找到 nums[l] + nums[r] = -nums[i]int l = i + 1, r = nums.length - 1;int target = -nums[i];while (l < r) {int sum = nums[l] + nums[r];if (sum == target) {res.add(Arrays.asList(nums[i], nums[l], nums[r]));l++;r--;// 跳过重复元素while (l < r && nums[l] == nums[l - 1]) l++;while (l < r && nums[r] == nums[r + 1]) r--;} else if (sum < target) {l++;} else {r--;}}}return res;}
}
42. 接雨水
//思路:对于每一个i,找其左边最高的lh和右边最高的rh,计算min(lh,rh)-height[i],再累加。有两个样例超时了
// class Solution {
// public int trap(int[] height) {
// int result=0;
// int n=height.length;
// for(int i=1;i<n-1;i++){
// int lh=0,rh=0;
// for(int l=i-1;l>=0;l--){
// lh=Math.max(lh,height[l]);
// }
// for(int r=i+1;r<n;r++){
// rh=Math.max(rh,height[r]);
// }
// int temp=Math.min(lh,rh)-height[i];
// if(temp>0){
// result+=temp;
// }
// }
// return result;
// }
// }//优化:直接找到全场最高的柱子。然后对其左右按照上面的思路分别处理//优化:动态规划 上面解法中对于每一列,我们求它左边最高的墙和右边最高的墙,都是重新遍历一遍所有高度,这里我们可以优化一下。
// 首先用两个数组,max_left [i] 代表第 i 列左边最高的墙的高度,max_right[i] 代表第 i 列右边最高的墙的高度。(一定要注意下,第 i 列左(右)边最高的墙,是不包括自身的,和 leetcode 上边的讲的有些不同)class Solution {public int trap(int[] height) {int sum = 0;int[] max_left = new int[height.length];int[] max_right = new int[height.length];for (int i = 1; i < height.length - 1; i++) {max_left[i] = Math.max(max_left[i - 1], height[i - 1]);}for (int i = height.length - 2; i >= 0; i--) {max_right[i] = Math.max(max_right[i + 1], height[i + 1]);}for (int i = 1; i < height.length - 1; i++) {int min = Math.min(max_left[i], max_right[i]);if (min > height[i]) {sum = sum + (min - height[i]);}}return sum;}}
53. 最大子数组和
class Solution {public int maxSubArray(int[] nums) {int n=nums.length;//前缀和int[] sums=new int[n];for(int i=0;i<n;i++){if(i!=0){sums[i]=sums[i-1]+nums[i];}else{sums[i]=nums[i];}}int res=-Integer.MAX_VALUE;for(int i=0;i<n;i++){res=Math.max(res,sums[i]);if(sums[i]<0){for(int j=i+1;j<n;j++){res=Math.max(res,sums[j]-sums[i]);}}}return res;}
}
上面这个代码,有几个样例超时了
在计算前缀和的时候就直接开始算就行了
class Solution {public int maxSubArray(int[] nums) {int ans = Integer.MIN_VALUE;int minPreSum = 0;int preSum = 0;for (int x : nums) {preSum += x; // 当前的前缀和ans = Math.max(ans, preSum - minPreSum); // 减去前缀和的最小值minPreSum = Math.min(minPreSum, preSum); // 维护前缀和的最小值}return ans;}
}
56. 合并区间
class Solution {public int[][] merge(int[][] intervals) {int n=intervals.length;int[][] res=new int[n][2];Arrays.sort(intervals, new Comparator<int[]>() {@Overridepublic int compare(int[] a, int[] b) {return a[0] - b[0]; // 按照第一个元素升序排序}});res[0][0]=intervals[0][0];res[0][1]=intervals[0][1];int resCount=0;for(int i=1;i<n;i++){if( intervals[i][0]<=res[resCount][1]){//可以合并res[resCount][1]=Math.max(res[resCount][1],intervals[i][1]);}else{//不能合并resCount++;res[resCount][0]=intervals[i][0];res[resCount][1]=intervals[i][1];}System.out.println(res[resCount][0]+" "+res[resCount][1]);}return Arrays.copyOfRange(res, 0, resCount+1);}
}
官方题解
class Solution {public int[][] merge(int[][] intervals) {if (intervals.length == 0) {return new int[0][2];}Arrays.sort(intervals, new Comparator<int[]>() {public int compare(int[] interval1, int[] interval2) {return interval1[0] - interval2[0];}});List<int[]> merged = new ArrayList<int[]>();for (int i = 0; i < intervals.length; ++i) {int L = intervals[i][0], R = intervals[i][1];if (merged.size() == 0 || merged.get(merged.size() - 1)[1] < L) {merged.add(new int[]{L, R});} else {merged.get(merged.size() - 1)[1] = Math.max(merged.get(merged.size() - 1)[1], R);}}return merged.toArray(new int[merged.size()][]);}
}
73. 矩阵置零
class Solution {public void setZeroes(int[][] matrix) {int m=matrix.length;int n=matrix[0].length;boolean[] row=new boolean[m];boolean[] col=new boolean[n];for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(matrix[i][j]==0){row[i]=true;col[j]=true;}}}for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(row[i] || col[j]){matrix[i][j]=0;}}}}
}
48. 旋转图像
找规律题
class Solution {public void rotate(int[][] matrix) {int n=matrix.length;for(int i=0;i<n/2;i++){//有几圈for(int j=i;j<n-i-1;j++){int a=matrix[i][j];int b=matrix[j][n-i-1];int c=matrix[n-i-1][n-j-1];int d=matrix[n-j-1][i];matrix[i][j]=d;matrix[j][n-i-1]=a;matrix[n-i-1][n-j-1]=b;matrix[n-j-1][i]=c;}} }
}//matrix[0][0] matrix[0][n-1] matrix[n-1][n-1] matrix[n-1][0] 四个值顺序交换
//matrix[0][1] matrix[1][n-1] matrix[n-1][n-2] matrix[n-2][0]
141. 环形链表
快慢指针
/*** 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) {ListNode fast=head;ListNode slow=head;while(slow!=null && fast!=null && fast.next!=null){fast=fast.next.next;slow=slow.next;if(fast==slow){return true;}}return false;}
}
142. 环形链表 II
很巧妙
ListNode ptr=head;while(ptr!=slow){ptr=ptr.next;slow=slow.next;}return ptr;
/*** Definition for singly-linked list.* class ListNode {* int val;* ListNode next;* ListNode(int x) {* val = x;* next = null;* }* }*/
public class Solution {public ListNode detectCycle(ListNode head) {ListNode fast=head;ListNode slow=head;while(slow!=null && fast!=null && fast.next!=null){fast=fast.next.next;slow=slow.next;if(fast==slow){ListNode ptr=head;while(ptr!=slow){ptr=ptr.next;slow=slow.next;}return ptr;}}return null;}
}
24. 两两交换链表中的节点
/*** 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; }* }*/public class Solution {public ListNode swapPairs(ListNode head) {if (head == null || head.next == null) {return head;}ListNode one = head;ListNode two = one.next;ListNode three = two.next;two.next = one;one.next = swapPairs(three);return two;}
}
迭代法
238. 除自身以外数组的乘积
class Solution {public int[] productExceptSelf(int[] nums) {int n=nums.length;int[] res=new int[n];int all=1;int countZero=0;int all_exclude_0=1; //除了0之外的乘for(int i=0;i<n;i++){if(nums[i]==0){countZero++;}else{all_exclude_0*=nums[i];}all*=nums[i];}if(all!=0){for(int i=0;i<n;i++){res[i]=all/nums[i];}}else{if(countZero>=2){return res;}for(int i=0;i<n;i++){if(nums[i]!=0){res[i]=0;}else{res[i]=all_exclude_0;}}}return res;}
}
上面这个解法不符合要求,用了除法,并且空间复杂度不是O(1)
3. 无重复字符的最长子串
class Solution {public int lengthOfLongestSubstring(String s) {char[] ss=s.toCharArray();Set<Character> set=new HashSet<>();int res=0;for(int left=0,right=0;right<s.length();right++){char ch=ss[right];while(left<=right && set.contains(ch)){set.remove(ss[left]);left++;}set.add(ss[right]);res=Math.max(res,right-left+1);}return res;}
}
滑动窗口模板
//外层循环扩展右边界,内层循环扩展左边界
for (int l = 0, r = 0 ; r < n ; r++) {//当前考虑的元素while (l <= r && check()) {//区间[left,right]不符合题意//扩展左边界}//区间[left,right]符合题意,统计相关信息
}
438. 找到字符串中所有字母异位词
class Solution {public List<Integer> findAnagrams(String s, String p) {List<Integer> res=new ArrayList<>();for(int i=0;i<=s.length()-p.length();i++){if(check(s.substring(i,i+p.length()),p)){res.add(i);}}return res;}public boolean check(String a, String b) {if (a.length() != b.length()) return false;int[] count = new int[26];for (char c : a.toCharArray()) count[c - 'a']++;for (char c : b.toCharArray()) {if (--count[c - 'a'] < 0) return false;}return true;}//排序太慢了// public Boolean check(String a,String b){// char[] array1=a.toCharArray();// Arrays.sort(array1);// String key1=new String(array1);// char[] array2=b.toCharArray();// Arrays.sort(array2);// String key2=new String(array2);// return key1.equals(key2); // }
}
官方题解
class Solution {public List<Integer> findAnagrams(String s, String p) {int sLen = s.length(), pLen = p.length();if (sLen < pLen) {return new ArrayList<Integer>();}List<Integer> ans = new ArrayList<Integer>();int[] sCount = new int[26];int[] pCount = new int[26];for (int i = 0; i < pLen; ++i) {++sCount[s.charAt(i) - 'a'];++pCount[p.charAt(i) - 'a'];}if (Arrays.equals(sCount, pCount)) {ans.add(0);}for (int i = 0; i < sLen - pLen; ++i) {--sCount[s.charAt(i) - 'a'];++sCount[s.charAt(i + pLen) - 'a'];if (Arrays.equals(sCount, pCount)) {ans.add(i + 1);}}return ans;}
}
560. 和为 K 的子数组
枚举法
class Solution {public int subarraySum(int[] nums, int k) {int ans=0;int n=nums.length;for(int i=0;i<n;i++){int temp=nums[i];if(temp==k){ans++;}for(int j=i+1;j<n;j++){temp+=nums[j];if(temp==k){ans++;}}}return ans; }
}
前缀和
class Solution {public int subarraySum(int[] nums, int k) {int ans=0;int n=nums.length;int[] pre=new int[n+1];pre[0]=0;pre[1]=nums[0];for(int i=1;i<n;i++){pre[i+1]=nums[i]+pre[i];}for(int i=1;i<n+1;i++){for(int j=i;j<n+1;j++){if(pre[j]-pre[i-1]==k){ans++;}}}return ans;}
}
前缀和再优化,结合两数之和的思路。以和为键,出现次数为对应的值
239. 滑动窗口最大值
class MyQueue {Deque<Integer> deque = new LinkedList<>();//弹出元素时,比较当前要弹出的数值是否等于队列出口的数值,如果相等则弹出//同时判断队列当前是否为空void poll(int val) {if (!deque.isEmpty() && val == deque.peek()) {deque.poll();}}//添加元素时,如果要添加的元素大于入口处的元素,就将入口元素弹出//保证队列元素单调递减//比如此时队列元素3,1,2将要入队,比1大,所以1弹出,此时队列:3,2void add(int val) {while (!deque.isEmpty() && val > deque.getLast()) {deque.removeLast();}deque.add(val);}//队列队顶元素始终为最大值int peek() {return deque.peek();}
}class Solution {public int[] maxSlidingWindow(int[] nums, int k) {if (nums.length == 1) {return nums;}int len = nums.length - k + 1;//存放结果元素的数组int[] res = new int[len];int num = 0;//自定义队列MyQueue myQueue = new MyQueue();//先将前k的元素放入队列for (int i = 0; i < k; i++) {myQueue.add(nums[i]);}res[num++] = myQueue.peek();for (int i = k; i < nums.length; i++) {//滑动窗口移除最前面的元素,移除是判断该元素是否放入队列myQueue.poll(nums[i - k]);//滑动窗口加入最后面的元素myQueue.add(nums[i]);//记录对应的最大值res[num++] = myQueue.peek();}return res;}
}
//解法二
//利用双端队列手动实现单调队列
/*** 用一个单调队列来存储对应的下标,每当窗口滑动的时候,直接取队列的头部指针对应的值放入结果集即可* 单调递减队列类似 (head -->) 3 --> 2 --> 1 --> 0 (--> tail) (左边为头结点,元素存的是下标)*/
class Solution {public int[] maxSlidingWindow(int[] nums, int k) {ArrayDeque<Integer> deque = new ArrayDeque<>();int n = nums.length;int[] res = new int[n - k + 1];int idx = 0;for(int i = 0; i < n; i++) {// 根据题意,i为nums下标,是要在[i - k + 1, i] 中选到最大值,只需要保证两点// 1.队列头结点需要在[i - k + 1, i]范围内,不符合则要弹出while(!deque.isEmpty() && deque.peek() < i - k + 1){deque.poll();}// 2.维护单调递减队列:新元素若大于队尾元素,则弹出队尾元素,直到满足单调性while(!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {deque.pollLast();}deque.offer(i);// 因为单调,当i增长到符合第一个k范围的时候,每滑动一步都将队列头节点放入结果就行了if(i >= k - 1){res[idx++] = nums[deque.peek()];}}return res;}
}
160. 相交链表
最开始,只关注了 node中的val
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) {* val = x;* next = null;* }* }*/
public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {List<Integer> a=new ArrayList<>();List<Integer> b=new ArrayList<>();ListNode currA=headA;ListNode currB=headB;while(currA!=null){a.add(currA.val);currA=currA.next;}while(currB!=null){b.add(currB.val);currB=currB.next;}System.out.println(a);System.out.println(b);int lenA=a.size();int lenB=b.size();int ans=0;while(lenA>0 && lenB>0){if(a.get(lenA-1)==b.get(lenB-1)){ans++;lenA--;lenB--;}else{break;}}if(ans==0){return null;}int skipA=a.size()-ans;int skipB=b.size()-ans;System.out.println(skipA);System.out.println(skipB);while(skipA>0){headA=headA.next;skipA--;}return headA; }
}
有样例过不去 ,是因为下面这个原因
将下面这里改一下就可以了
List<ListNode> a=new ArrayList<>();
List<ListNode> b=new ArrayList<>();
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) {* val = x;* next = null;* }* }*/
public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {List<ListNode> a=new ArrayList<>();List<ListNode> b=new ArrayList<>();ListNode currA=headA;ListNode currB=headB;while(currA!=null){a.add(currA);currA=currA.next;}while(currB!=null){b.add(currB);currB=currB.next;}System.out.println(a);System.out.println(b);int lenA=a.size();int lenB=b.size();int ans=0;while(lenA>0 && lenB>0){if(a.get(lenA-1)==b.get(lenB-1)){ans++;lenA--;lenB--;}else{break;}}if(ans==0){return null;}int skipA=a.size()-ans;int skipB=b.size()-ans;System.out.println(skipA);System.out.println(skipB);while(skipA>0){headA=headA.next;skipA--;}return headA; }
}
对于headA,先遍历A再遍历B
对于headB,先遍历B再遍历A
public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {ListNode A = headA, B = headB;while (A != B) {A = A != null ? A.next : headB;B = B != null ? B.next : headA;}return A;}
}
79. 单词搜索
class Solution {public boolean exist(char[][] board, String word) {char[] charWord=word.toCharArray();for(int i=0;i<board.length;i++){for(int j=0;j<board[0].length;j++){if(dfs(board,charWord,i,j,0)){return true;}}}return false;}public boolean dfs(char[][] board, char[] word,int i,int j,int now){if(i<0 || j<0 || i>=board.length || j>=board[0].length || board[i][j]!=word[now]){return false;}if(now==word.length-1){return true;}board[i][j]='\0';boolean res=dfs(board,word,i-1,j,now+1) || dfs(board,word,i+1,j,now+1) || dfs(board,word,i,j-1,now+1) || dfs(board,word,i,j+1,now+1);board[i][j]=word[now];return res;}
}
206. 反转链表
/*** 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 prev=null;ListNode curr=head;while(curr!=null){ListNode next=curr.next;curr.next=prev;prev=curr;curr=next;}return prev;}
}
假设链表为 1→2→3→∅,我们想要把它改成 ∅←1←2←3。
在遍历链表时,将当前节点的 next 指针改为指向前一个节点。由于节点没有引用其前一个节点,因此必须事先存储其前一个节点。在更改引用之前,还需要存储后一个节点。最后返回新的头引用。
递归方法
/*** 以链表1->2->3->4->5举例* @param head* @return*/public ListNode reverseList(ListNode head) {if (head == null || head.next == null) {/*直到当前节点的下一个节点为空时返回当前节点由于5没有下一个节点了,所以此处返回节点5*/return head;}//递归传入下一个节点,目的是为了到达最后一个节点ListNode newHead = reverseList(head.next);/*第一轮出栈,head为5,head.next为空,返回5第二轮出栈,head为4,head.next为5,执行head.next.next=head也就是5.next=4,把当前节点的子节点的子节点指向当前节点此时链表为1->2->3->4<->5,由于4与5互相指向,所以此处要断开4.next=null此时链表为1->2->3->4<-5返回节点5第三轮出栈,head为3,head.next为4,执行head.next.next=head也就是4.next=3,此时链表为1->2->3<->4<-5,由于3与4互相指向,所以此处要断开3.next=null此时链表为1->2->3<-4<-5返回节点5第四轮出栈,head为2,head.next为3,执行head.next.next=head也就是3.next=2,此时链表为1->2<->3<-4<-5,由于2与3互相指向,所以此处要断开2.next=null此时链表为1->2<-3<-4<-5返回节点5第五轮出栈,head为1,head.next为2,执行head.next.next=head也就是2.next=1,此时链表为1<->2<-3<-4<-5,由于1与2互相指向,所以此处要断开1.next=null此时链表为1<-2<-3<-4<-5返回节点5出栈完成,最终头节点5->4->3->2->1*/head.next.next = head;head.next = null;return newHead;}
234. 回文链表
/*** 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 boolean isPalindrome(ListNode head) {// 找到前半部分链表的尾节点并反转后半部分链表ListNode firstHalfEnd = endOfFirstHalf(head);ListNode secondHalfStart = reverseList(firstHalfEnd.next);// 判断是否回文ListNode p1 = head;ListNode p2 = secondHalfStart;boolean result = true;while (result && p2 != null) {if (p1.val != p2.val) {result = false;}p1 = p1.next;p2 = p2.next;} // 还原链表并返回结果firstHalfEnd.next = reverseList(secondHalfStart);return result; }private ListNode reverseList(ListNode head){ListNode prev=null;ListNode curr=head;while(curr!=null){ListNode next=curr.next;curr.next=prev;prev=curr;curr=next;}return prev;}private ListNode endOfFirstHalf(ListNode head) {ListNode fast = head;ListNode slow = head;while (fast.next != null && fast.next.next != null) {fast = fast.next.next;slow = slow.next;}return slow;}}
138. 随机链表的复制
/*
// Definition for a Node.
class Node {int val;Node next;Node random;public Node(int val) {this.val = val;this.next = null;this.random = null;}
}
*/class Solution {Map<Node,Node> map=new HashMap<>(); //原节点和复制节点的映射public Node copyRandomList(Node head) {if(head==null){return null;}if(!map.containsKey(head)){Node headNew=new Node(head.val);map.put(head,headNew);headNew.next=copyRandomList(head.next);headNew.random=copyRandomList(head.random);}return map.get(head);}
}
46. 全排列
class Solution {public List<List<Integer>> permute(int[] nums) {List<List<Integer>> res=new ArrayList<>();List<Integer> listnums =new ArrayList<>();for(int i:nums){listnums.add(i);}dfs(res,listnums,0);return res;}private void dfs(List<List<Integer>> res,List<Integer> nums,int x){if(x==nums.size()-1){res.add(new ArrayList<>(nums)); //不要写成res.add(nums); 在 Java 中,参数传递是 值传递,对象类型变量在传参的过程中,复制的是变量的地址。这些地址被添加到 res 变量,但实际上指向的是同一块内存地址return;}for(int i=x;i<nums.size();i++){swap(nums,x,i); // 交换,将 nums[i] 固定在第 x 位dfs(res,nums,x+1); // 开启固定第 x + 1 位元素swap(nums,x,i); // 恢复交换}}private void swap(List<Integer> nums,int i,int j){int temp=nums.get(i);nums.set(i,nums.get(j));nums.set(j,temp);}
}
78. 子集
class Solution {public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> res=new ArrayList<>();List<Integer> listnums=new ArrayList<>();for(int i:nums){listnums.add(i);}dfs(res,listnums,new ArrayList<Integer>(),0);return res;}public void dfs(List<List<Integer>> res,List<Integer> nums,List<Integer> temp,int x){if(x==nums.size()){res.add(new ArrayList<>(temp));return;}//加入第x个元素temp.add(nums.get(x));dfs(res,nums,temp,x+1);temp.remove(nums.get(x));//不加入第x个元素dfs(res,nums,temp,x+1);}
}
17. 电话号码的字母组合
class Solution {public List<String> letterCombinations(String digits) {List<String> res=new ArrayList<>();if(digits.equals("")){return res;}Map<Character,String> map=new HashMap<>();map.put('2',"abc");map.put('3',"def");map.put('4',"ghi");map.put('5',"jkl");map.put('6',"mno");map.put('7',"pqrs");map.put('8',"tuv");map.put('9',"wxyz");char []now=new char[digits.length()];dfs(res,now,digits,map,0);return res;}public void dfs(List<String> res,char[] now,String digits,Map<Character,String> map,int x){if(x==digits.length()){res.add(new String(now));return;}String tmp=map.get(digits.charAt(x));for(int i=0;i<tmp.length();i++){now[x]=tmp.charAt(i);dfs(res,now,digits,map,x+1);}}
}
39. 组合总和
class Solution {public List<List<Integer>> combinationSum(int[] candidates, int target) {List<List<Integer>> res=new ArrayList<>();List<Integer> listcandidates=new ArrayList<>();for(int i:candidates){listcandidates.add(i);}dfs(res,listcandidates,new ArrayList<Integer>(),target,0,0);return res; }public void dfs(List<List<Integer>> res,List<Integer> listcandidates,List<Integer> nowlist,int target,int now,int x){if(now>target){return;}if(now==target){res.add(new ArrayList<>(nowlist));return;}for(int i=x;i<listcandidates.size();i++){nowlist.add(listcandidates.get(i));dfs(res,listcandidates,nowlist,target,now+listcandidates.get(i),i);nowlist.remove(nowlist.size()-1);}}
}
22. 括号生成
class Solution {public List<String> generateParenthesis(int n) {List<String> res=new ArrayList<>();dfs(res,2*n,"",0,0);return res;}private void dfs(List<String> res,int all,String now,int left,int right){if(right>left || right>all/2 || left>all/2){return;}if(left+right==all){res.add(now);return;}//加左括号dfs(res,all,now+"(",left+1,right);//加右括号dfs(res,all,now+")",left,right+1);}
}
279. 完全平方数
class Solution {public int numSquares(int n) {int[] f = new int[n + 1];for (int i = 1; i <= n; i++) {int minn = Integer.MAX_VALUE;for (int j = 1; j * j <= i; j++) {minn = Math.min(minn, f[i - j * j]);}f[i] = minn + 1;}return f[n];}
}
62. 不同路径
class Solution {public int uniquePaths(int m, int n) {int[][] f=new int[m+1][n+1];if(m==1 || n==1){return 1;}f[2][1]=1;f[1][2]=1;for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){if(f[i][j]==0){f[i][j]=f[i-1][j]+f[i][j-1];}}}return f[m][n];}
}
64. 最小路径和
class Solution {public int minPathSum(int[][] grid) {int m=grid.length,n=grid[0].length;int[][] f=new int[m][n];for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(i==0 && j==0){f[i][j]=grid[i][j];continue;}if(i-1<0){f[i][j]=f[i][j-1]+grid[i][j];}else if(j-1<0){f[i][j]=f[i-1][j]+grid[i][j];}else{f[i][j]=Math.min(f[i-1][j]+grid[i][j],f[i][j-1]+grid[i][j]);}}}return f[m-1][n-1]; }
}
169. 多数元素
class Solution {public int majorityElement(int[] nums) {Arrays.sort(nums);return nums[nums.length >> 1];}
}
94. 二叉树的中序遍历
/*
class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> res=new ArrayList<>();inorder(root,res);return res;}private void inorder(TreeNode node,List<Integer> res){if(node==null){return;}inorder(node.left,res);res.add(node.val);inorder(node.right,res);}
}
*/class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> res=new ArrayList<>();Deque<TreeNode> stk=new LinkedList<>();while(root!=null || !stk.isEmpty()){while(root!=null){stk.push(root);root=root.left;}root=stk.pop();res.add(root.val);root=root.right;}return res;}
}
二叉树的最大深度
/*** 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 maxDepth(TreeNode root) {if(root==null){return 0;}int leftHeight=maxDepth(root.left);int rightHeight=maxDepth(root.right);return Math.max(leftHeight,rightHeight)+1;}
}
*///证每次拓展完的时候队列里存放的是当前层的所有节点,即我们是一层一层地进行拓展
class Solution {public int maxDepth(TreeNode root) {if (root == null) {return 0;}Queue<TreeNode> queue = new LinkedList<TreeNode>();queue.offer(root);int ans = 0;while (!queue.isEmpty()) {int size = queue.size();while (size > 0) {TreeNode node = queue.poll();if (node.left != null) {queue.offer(node.left);}if (node.right != null) {queue.offer(node.right);}size--;}ans++;}return ans;}
}
226. 翻转二叉树
/*** 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 TreeNode invertTree(TreeNode root) {if(root==null){return root;}TreeNode temp=root.left;root.left=root.right;root.right=temp;invertTree(root.left);invertTree(root.right);return root;}
}
*/class Solution {public TreeNode invertTree(TreeNode root) {if(root==null) {return null;}//将二叉树中的节点逐层放入队列中,再迭代处理队列中的元素LinkedList<TreeNode> queue = new LinkedList<TreeNode>();queue.add(root);while(!queue.isEmpty()) {//每次都从队列中拿一个节点,并交换这个节点的左右子树TreeNode tmp = queue.poll();TreeNode left = tmp.left;tmp.left = tmp.right;tmp.right = left;//如果当前节点的左子树不为空,则放入队列等待后续处理if(tmp.left!=null) {queue.add(tmp.left);}//如果当前节点的右子树不为空,则放入队列等待后续处理if(tmp.right!=null) {queue.add(tmp.right);}}//返回处理完的根节点return root;}
}
101. 对称二叉树
/*** 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 isSymmetric(TreeNode root) {List<TreeNode> queue=new LinkedList<>();queue.add(root);while(!queue.isEmpty()){int size=queue.size();while(size!=0){TreeNode node=queue.remove(0);if(node!=null){queue.add(node.left);queue.add(node.right); }size--;}//判断该层是否对称int l=0,r=queue.size()-1;while(l<r){if( (queue.get(l)!= null && queue.get(r)==null) || (queue.get(l)== null && queue.get(r)!=null) || (!(queue.get(l)== null && queue.get(r)==null)) && (queue.get(l).val!=queue.get(r).val)){return false;}l++;r--;}}return true;}
}/*
它们的两个根结点具有相同的值
每个树的右子树都与另一个树的左子树镜像对称
class Solution {public boolean isSymmetric(TreeNode root) {return check(root.left, root.right);}public boolean check(TreeNode p, TreeNode q) {if (p == null && q == null) {return true;}if (p == null || q == null) {return false;}return p.val == q.val && check(p.left, q.right) && check(p.right, q.left);}
}
*/
543. 二叉树的直径
class Solution {int ans=0;public int diameterOfBinaryTree(TreeNode root) {depth(root);return ans;}public int depth(TreeNode root){if(root==null){return 0;}int l=depth(root.left); // 左儿子为根的子树的深度int r=depth(root.right); // 右儿子为根的子树的深度ans=Math.max(l+r,ans);return Math.max(l,r)+1; // 返回该节点为根的子树的深度}
}
102. 二叉树的层序遍历
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> res=new ArrayList<>();if (root==null){return res;}Deque<TreeNode> queue=new LinkedList<>();queue.offer(root);while(!queue.isEmpty()){List<Integer> layer=new ArrayList<>();for(TreeNode temp:queue){layer.add(temp.val);} res.add(layer);int size=queue.size();while(size!=0){TreeNode node=queue.poll();if(node.left!=null){queue.offer(node.left); }if(node.right!=null){queue.offer(node.right);} size--;}}return res;}
}
2962. 统计最大元素出现至少 K 次的子数组
class Solution {public long countSubarrays(int[] nums, int k) {//滑动窗口long ans=0;int left=0;int max=0;for(int num:nums){max=Math.max(max,num);}int now=0;for(int r:nums){if(r==max){now++;}while(now==k){if(nums[left]==max){now--;}left++;}ans+=left;}return ans;}
}
2302. 统计得分小于 K 的子数组数目
class Solution {public long countSubarrays(int[] nums, long k) {long res=0;long nowSum=0;for(int left=0,right=0;right<nums.length;right++){nowSum+=nums[right];while(left<=right && nowSum*(right-left+1)>=k){nowSum-=nums[left];left++;} res+=right-left+1;}return res;}
}
2444. 统计定界子数组的数目
固定右端点,找左端点。
minI表示 离当前右端点 最近 的 minK 位置
maxI表示 离当前右端点 最近 的 maxK 位置
i0表示 离当前右端点最近 的 不在 [minK,maxK]范围的 位置
所有当前右端点, 符合条件的子数组 有 min(minI,maxI)−i0个
class Solution {public long countSubarrays(int[] nums, int minK, int maxK) {long ans = 0;int minI = -1, maxI = -1, i0 = -1;for (int i = 0; i < nums.length; i++) {int x = nums[i];if (x == minK) {minI = i; // 最近的 minK 位置}if (x == maxK) {maxI = i; // 最近的 maxK 位置}if (x < minK || x > maxK) {i0 = i; // 子数组不能包含 nums[i0]}ans += Math.max(Math.min(minI, maxI) - i0, 0);}return ans;}
}
61. 旋转链表
/*** 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 || k==0 ){return head;}ListNode curr=head;int count=0;ListNode tail=new ListNode();while(curr!=null){if(curr.next==null){tail=curr;}curr=curr.next;count++;}if(count==1 || k%count==0){return head;}k=count-(k%count);curr=head;ListNode currbefore=new ListNode();while(k!=0){k--;currbefore=curr;curr=curr.next;}tail.next=head;currbefore.next=null;return curr;}
}
LCP 09. 最小跳跃次数
class Solution {public int minJump(int[] jump) {int N = jump.length;int[] dp = new int[N];dp[N - 1] = 1; // 初始化最后一个弹簧的dp值为1for (int i = N - 2; i >= 0; --i) { // 从右向左遍历// 计算从弹簧i向右弹射的dp值dp[i] = (i + jump[i] >= N) ? 1 : dp[i + jump[i]] + 1;// 遍历当前位置更新后影响到的后面的位置for (int j = i + 1; j < N && dp[j] >= dp[i] + 1; ++j) {dp[j] = dp[i] + 1; // 更新dp[j]的值}}return dp[0]; // 返回从弹簧0开始弹出机器的最少按动次数}
}
199. 二叉树的右视图
/*** 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<Integer> rightSideView(TreeNode root) {List<Integer> res=new ArrayList<>();if(root==null){return res;}//层序遍历,找一层最右边的 Queue<TreeNode> queue=new LinkedList<>();queue.offer(root);while(!queue.isEmpty()){int size=queue.size();int temp=size;while(temp!=0){TreeNode node=queue.poll();if(temp==1){res.add(node.val);}if(node.left!=null){queue.offer(node.left);}if(node.right!=null){queue.offer(node.right);}temp--;} }return res;}
}
215. 数组中的第K个最大元素
25. K 个一组翻转链表
别人的题解
配合上面的图看,真无敌
public ListNode reverseKGroup(ListNode head, int k) {ListNode dummy = new ListNode(0);dummy.next = head;ListNode pre = dummy;ListNode end = dummy;while (end.next != null) {for (int i = 0; i < k && end != null; i++) end = end.next;if (end == null) break;ListNode start = pre.next;ListNode next = end.next;end.next = null;pre.next = reverse(start);start.next = next;pre = start;end = pre;}return dummy.next;
}private ListNode reverse(ListNode head) {ListNode pre = null;ListNode curr = head;while (curr != null) {ListNode next = curr.next;curr.next = pre;pre = curr;curr = next;}return pre;
}
21. 合并两个有序链表
/*** 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 mergeTwoLists(ListNode l1, ListNode l2) {ListNode prehead = new ListNode(-1);ListNode prev = prehead;while (l1 != null && l2 != null) {if (l1.val <= l2.val) {prev.next = l1;l1 = l1.next;} else {prev.next = l2;l2 = l2.next;}prev = prev.next;}// 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可prev.next = l1 == null ? l2 : l1;return prehead.next;}
}
322. 零钱兑换在这里插入代码片
动态规划
class Solution {public int coinChange(int[] coins, int amount) {int max=amount+1;int[] dp=new int[amount+1];Arrays.fill(dp,max);dp[0]=0;for(int i=1;i<=amount;i++){for(int j=0;j<coins.length;j++){if(coins[j]<=i){dp[i]=Math.min(dp[i],dp[i-coins[j]]+1);}}}if(dp[amount]<max){return dp[amount];}return -1; }
}
55. 跳跃游戏
贪心算法
class Solution {public boolean canJump(int[] nums) {int maxReach=0;int i=0;while(i<=maxReach){maxReach=Math.max(maxReach,nums[i]+i);if(maxReach>=nums.length-1){return true;}i++;}return false;}
}
994. 腐烂的橘子
class Solution {public int orangesRotting(int[][] grid) {Queue<Integer> queue = new LinkedList<>();int r = grid.length;int c = grid[0].length;int time = 0;int flag = 0;for (int i = 0; i < r; i++) {for (int j = 0; j < c; j++) {if (grid[i][j] == 2) {queue.add(i * c + j);flag = 1;}}}while (!queue.isEmpty()) {int size = queue.size();time++;for (int i = 0; i < size; i++) {int index = queue.poll();int row = index / c;int col = index % c;//上if ((row - 1) >= 0 && grid[row - 1][col] == 1) {grid[row - 1][col] = 2;queue.add((row - 1) * c + col);}//下if ((row + 1) < r && grid[row + 1][col] == 1) {grid[row + 1][col] = 2;queue.add((row + 1) * c + col);}//左if ((col - 1) >= 0 && grid[row][col - 1] == 1) {grid[row][col - 1] = 2;queue.add(row * c + col - 1);}//右if ((col + 1) < c && grid[row][col + 1] == 1) {grid[row][col + 1] = 2;queue.add(row * c + col + 1);}}}for (int i = 0; i < r; i++) {for (int j = 0; j < c; j++) {if (grid[i][j] == 1) {return -1;}}}return flag == 0 ? 0 : time - 1;}
}
2294. 划分数组使最大差为 K
class Solution {public int partitionArray(int[] nums, int k) {Arrays.sort(nums);int mn=-Integer.MAX_VALUE/2;int ans=0;for(int x:nums){if(x-mn>k){ans++;mn=x;}}return ans;}
}
2966. 划分数组并满足最大差限制
class Solution {public int[][] divideArray(int[] nums, int k) {Arrays.sort(nums);int[][] res=new int[nums.length/3][3];for(int i=0;i<nums.length/3;i++){if(nums[3*i+2]-nums[3*i]<=k){res[i]=new int[]{nums[3*i],nums[3*i+1],nums[3*i+2]};}else{return new int[][]{};}}return res;}
}
1432. 改变一个整数能得到的最大差值
class Solution {public int maxDiff(int num) {String ss=String.valueOf(num);char[] cs=ss.toCharArray();int max=num;for(char d:cs){if(d!='9'){max=replace(ss,d,'9');break;}}int min=num;if(cs[0]=='1'){for(int i=1;i<cs.length;i++){if(cs[i]>'1'){min=replace(ss,cs[i],'0');break;}}}else{min=replace(ss,cs[0],'1');}return max-min;}public int replace(String ss,char oldChar,char newChar){ss=ss.replace(oldChar,newChar);return Integer.parseInt(ss);}
}
2616. 最小化数对的最大差值(很不错的一题)
class Solution {public int minimizeMax(int[] nums, int p) {Arrays.sort(nums); // 对数组排序,使得相邻元素差值最小,便于贪心配对int left = 0, right = nums[nums.length - 1] - nums[0];int ans = right;// 闭区间二分查找最小可行解while (left <= right) {int mid = left + (right - left) / 2;if (canForm(nums, p, mid)) {ans = mid; // 当前值可行,记录答案right = mid - 1; // 尝试更小的差值} else {left = mid + 1; // 当前值不够,尝试更大的差值}}return ans;}// 检查是否可以在最大差值 <= x 的条件下配出至少 p 对private boolean canForm(int[] nums, int p, int x) {int count = 0;int i = 0; // 当前指针while (i < nums.length - 1) {if (Math.abs(nums[i] - nums[i + 1]) <= x) {count++;i += 2; // 这两个下标都不能再用了} else {i += 1; // 否则继续向后寻找}}return count >= p;}
}