287、寻找重复数 | Hot100 【技巧】 第100题
class Solution {
/**
*快慢指针是一种在链表或类似结构中常用的技巧,用来检测环的存在以及找到环的起点。在这个问题中,虽然我们处理的是一个数组,但我们可以将数组元素视为指向下一个元素的“指针”,从而模拟出一种链表的结构。
*/
public int findDuplicate(int[] nums) {
//快慢指针
int slow=0,fast=0;
do{
slow = nums[slow];
fast = nums[nums[fast]];
}while(slow != fast);
slow = 0;
while(slow!=fast){
slow = nums[slow];
fast = nums[fast];
}
return slow;
}
}
31、下一个排列 | Hot100 【技巧】 第99题
class Solution {
public void nextPermutation(int[] nums) {
int i = nums.length-2;
//找到第一个需要增大排列的数
while(i>= 0 && nums[i]>=nums[i+1]){
i--;
}
int j = nums.length-1;
if(i>=0){
//找到第2个需要增大排列的数
while(j>=0 && nums[i]>= nums[j]){
j--;
}
swap(nums,i,j);
}
reverse(nums,i+1);
}
private void swap(int[] nums,int i,int j){
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
private void reverse(int[] nums,int i){
int right = nums.length-1;
while(i<=right){
swap(nums,i,right);
i++;
right--;
}
}
}
75、颜色分类 | Hot100 【技巧】 第98题
class Solution {
public void sortColors(int[] nums) {
int i=0;
int left=0;//[0,left)为0
int right=nums.length-1;//(right,末尾]为2
while(i<=right){
if(nums[i]==0){
swap(nums,left,i);
i++;
left++;
}else if(nums[i]==1){
i++;
}else if(nums[i]==2){
swap(nums,right,i);
//从right交换过来的有可能是0|1,如果是0,那么i不能++
right--;
}
}
}
private void swap(int[] nums,int index,int i){
int t = nums[i];
nums[i] = nums[index];
nums[index] = t;
}
}
169、多数元素 | Hot100 【技巧】 第97题
class Solution {
public int majorityElement(int[] nums) {
//我们遍历数组 nums 中的所有元素,对于每个元素 x,在判断 x 之前,如果 count 的值为 0,我们先将 x 的值赋予 candidate,随后我们判断 x:
//如果 x 与 candidate 相等,那么计数器 count 的值增加 1;
//如果 x 与 candidate 不等,那么计数器 count 的值减少 1。
int count = 0;
int result = 0;
for(int num:nums){
if(count == 0){
result = num;
}
if(result == num){
count++;
}else{
count--;
}
}
return result;
}
}
136、只出现一次的数字 | Hot100 【技巧】 第96题
class Solution {
public int singleNumber(int[] nums) {
//1.任何数和 0 做异或运算,结果仍然是原来的数,即 a⊕0=a。
//2.任何数和其自身做异或运算,结果是 0,即 a⊕a=0。
//3.异或运算满足交换律和结合律,即 a⊕b⊕a=b⊕a⊕a=b⊕(a⊕a)=b⊕0=b。
int result = 0;
for(int num:nums){
result = result ^ num;
}
return result;
}
}
72. 编辑距离 | Hot100 【多维动态规划】 第90题
class Solution {
public int minDistance(String word1, String word2) {
int len1 = word1.length();
int len2 = word2.length();
int[][] dp = new int[len1+1][len2+1];//dp[i][j]表示word1的1~i子串转成成word2的1~j子串需要的编辑距离
dp[0][0] = 0;//0代表没有字符
int result= 0;
for(int i=1;i<=len1;i++){
dp[i][0] = i;//i长度转换到0字符串,需要删除i次
}
for(int i=1;i<=len2;i++){
dp[0][i] = i;//0字符串转换到i长度,需要插入i次
}
for(int i=1;i<=len1;i++){
for(int j=1;j<=len2;j++){
if(word1.charAt(i-1) == word2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1];
}else{
dp[i][j] = 1 + Math.min(
dp[i-1][j],//删除
Math.min(
dp[i][j-1],//插入
dp[i-1][j-1]//替换
)
);
}
}
}
return dp[len1][len2];
}
}
300. 最长回文子串 | Hot100 【多维动态规划】 第88题
题解:使用【动态规划】求解最长回文子串_哔哩哔哩_bilibili
class Solution {
public String longestPalindrome(String s) {
int n = s.length();
boolean[][] dp = new boolean[n][n];
for(int i=0;i<n;i++){
dp[i][i] = true;
}
for(int j=1;j<n;j++){
for(int i=0;i<j;i++){
if(s.charAt(i) != s.charAt(j)){
//s[i...j],对于i与j不等的,那dp[i][j]肯定不是回文串了
dp[i][j] = false;
}else{
//s[i...j],对于i与j相等的,若长度小于等于3肯定就是回文串,长度大于3那就考虑i,j内部是不是回文串
dp[i][j] = j-i+1<=3 || dp[i+1][j-1];
}
}
}
int len=0,start=0;
//找到哪一个回文串是最长的
for(int i=0;i<n;i++){
for(int j=i;j<n;j++){
if(dp[i][j]){
if(len < j-i+1){
len = j-i+1;
start = i;
}
}
}
}
return s.substring(start,start+len);
}
}
516. 最长回文子序列【多维动态规划】
题解:动态规划再显神通,LeetCode:516.最长回文子序列_哔哩哔哩_bilibili

class Solution {
public int longestPalindromeSubseq(String s) {
int n = s.length();
int[][] dp = new int[n][n];
for(int i=0;i<n;i++){
dp[i][i] = 1;
}
//dp[i][j]表示字符串[i,j]区间中,最长的回文子串有多长
for(int i=n-1;i>=0;i--){
for(int j=i+1;j<n;j++){
if(s.charAt(i) == s.charAt(j)){
dp[i][j] = dp[i+1][j-1]+2;
}else{
dp[i][j] = Math.max(dp[i][j-1],dp[i+1][j]);
}
}
}
return dp[0][n-1];
}
}
32. 最长有效括号 | Hot100 【动态规划】 第90题
class Solution {
public int longestValidParentheses(String s) {
int n = s.length();
//dp[i] 表示以下标 i 字符结尾的最长有效括号的长度
int[] dp = new int[n];
int result = 0;
for(int i=1;i<n;i++){
if(s.charAt(i) == ')'){
if(s.charAt(i-1) == '('){
//字符串形如 “……()”
//我们可以推出:dp[i]=dp[i−2]+2
dp[i] = ((i>=2) ? dp[i-2] : 0) + 2;
}else if(i - dp[i-1] > 0 && s.charAt(i-dp[i-1]-1) == '('){
//字符串形如 “……))”
//我们可以推出:如果 s[i−dp[i−1]−1]=‘(’,那么dp[i]=dp[i−1]+dp[i−dp[i−1]−2]+2
//s[i−dp[i−1]−1]表示()(())这里嵌套括号前的有小括号长度,即字符0,1
dp[i] = dp[i-1] + ((i-dp[i-1]) >= 2 ? dp[i-dp[i-1]-2] : 0) + 2;
}
result = Math.max(dp[i],result);
}
}
return result;
}
}
300. 最长递增子序列 | Hot100 【动态规划】 第87题
class Solution {
public int lengthOfLIS(int[] nums) {
int[] dp = new int[nums.length];
dp[0] = 1;
//dp[i]表示以i结尾的最大递增序列数
int max = 1;
for(int i=1;i<nums.length;i++){
dp[i] = 1;
for(int j=0;j<i;j++){
if(nums[i]>nums[j]){
dp[i] = Math.max(dp[i],dp[j]+1);
}
}
max = Math.max(max,dp[i]);
}
return max;
}
}
118. 杨辉三角 | Hot100 【动态规划】 第82题
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> result = new ArrayList();
List<Integer> first = new ArrayList<>();
first.add(1);
result.add(first);
if(numRows==1)return result;
List<Integer> second = new ArrayList<>();
second.add(1);
second.add(1);
result.add(second);
for(int i=3;i<=numRows;i++){
List<Integer> list = new ArrayList<>();
for(int j=0;j<i;j++){
if(j == 0 || j == i-1){
list.add(1);
}else{
list.add(result.get(result.size()-1).get(j-1)+result.get(result.size()-1).get(j));
}
}
result.add(list);
}
return result;
}
}
70. 爬楼梯 | Hot100 【动态规划】 第81题
class Solution {
public int climbStairs(int n) {
//爬到第n级台阶有两种可能,一种是从第n-1级台阶爬1次,一种是从第n-2级台阶爬2次
int[] dp = new int[n+1];
if(n==1)return 1;
dp[1] = 1;
dp[2] = 2;
for(int i = 3;i<dp.length;i++){
dp[i] = dp[i-1]+dp[i-2];
}
return dp[n];
}
}
763. 划分字母区间 | Hot100 【贪心算法】 第80题
class Solution {
public List<Integer> partitionLabels(String s) {
//看力扣官方题解
int[] endIndex = new int[26];
List<Integer> result = new ArrayList<>();
for(int i = 0;i<s.length();i++){
//记录每个字符最后一此出现在原始字符串的索引
endIndex[s.charAt(i)-'a'] = i;
}
int start = 0,end=0;
for(int i = 0;i<s.length();i++){
end = Math.max(end,endIndex[s.charAt(i)-'a']);
if(i == end){
result.add(end-start+1);
start = end+1;
}
}
return result;
}
}
45.跳跃游戏 II | Hot100 【贪心算法】 第79题
class Solution {
public int jump(int[] nums) {
int maxPos = 0,end=0;
int step = 0;
for(int i=0;i<nums.length-1;i++){
//为啥i<num.length-1,题目保证总是可以到达最后一个元素,所以当i走到了最后一个元素
maxPos = Math.max(maxPos,nums[i]+i);
if(end == i){
end = maxPos;
step++;
}
}
return step;
}
}
55.跳跃游戏 | Hot100 【贪心算法】 第78题
class Solution {
public boolean canJump(int[] nums) {
int target = nums.length-1;
for(int i=nums.length-2;i>=0;i--){
if(i + nums[i] >= target){
//i到target的可达性分析
//如果第i个位置走nums[i]步>=target,说明是可以通过i走到target
target = i;
}
}
//只有直到头结点都能可达,那才算是可以跳跃
return target == 0;
}
}
121. 买卖股票的最佳时机 | Hot100 【贪心算法】 第77题
class Solution {
public int maxProfit(int[] prices) {
int minPrice = Integer.MAX_VALUE;
int maxProfit = 0;
for(int i=0;i<prices.length;i++){
if(prices[i]<minPrice){
//这一步为啥不会进行max利润的更新,是因为这一天卖出必然亏(prices[i]是最低价)
minPrice = prices[i];
}else if(prices[i]-minPrice > maxProfit){
maxProfit = prices[i] - minPrice;
}
}
return maxProfit;
}
}
215. 数组中的第K个最大元素 | Hot100 【堆】 第74题
class Solution {
/**
由此可以发现每次经过「快排划分」操作后,我们一定可以确定一个元素的最终位置,即 x 的最终位置为 q,
并且保证 a[l⋯q−1] 中的每个元素小于等于 a[q],且 a[q] 小于等于 a[q+1⋯r] 中的每个元素。
所以只要某次划分的 q 为倒数第 k 个下标的时候,我们就已经找到了答案。
我们只关心这一点,至于 a[l⋯q−1] 和 a[q+1⋯r] 是否是有序的,我们不关心。
*/
public int findKthLargest(int[] nums, int k) {
return quick_select(nums,0,nums.length-1,nums.length-k);
}
public int quick_select(int[] nums,int l,int r,int k){
if(l==r)return nums[k];
int i = l-1,j = r+1;
int x = nums[l];
while(i<j){
do i++;while(nums[i] < x);
do j--;while(nums[j] > x);
if(i<j)swap(nums,i,j);
}
if(k<=j){
//倒数第k个数在左边,递归左区间
return quick_select(nums,l,j,k);
}else{
//倒数第k个数在右边,递归右区间
return quick_select(nums,j+1,r,k);
}
}
private void swap(int[] nums,int i,int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
739. 每日温度 | Hot100 【栈】 第72题
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
Deque<Integer> stack = new LinkedList<>();
int[] res = new int[temperatures.length];
for(int i=0;i<temperatures.length;i++){
while(!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]){
int index = stack.pop();
res[index] = i-index;
}
stack.push(i);
}
return res;
}
}
394.字符串解码 | Hot100 【栈】 第71题
class Solution {
public String decodeString(String s) {
Deque<Integer> stack_num = new LinkedList<>(); // 数字栈
Deque<String> stack_str = new LinkedList<>(); //[的外层字符串
char[] arr = s.toCharArray();
int multi = 0;
StringBuilder sb = new StringBuilder();
for(char c:arr){
if(c >= '0' && c <= '9'){
multi = multi*10+Integer.parseInt(c+""); //累加数字
}else if(c == '['){
stack_num.push(multi); //数字入栈
stack_str.push(sb.toString()); //外层字符串入栈
//重置,准备统计[后续的操作数和字符串
multi = 0;
sb = new StringBuilder();
}else if(c == ']'){
//出栈,开始累加字符串了
Integer num = stack_num.pop();
String str = stack_str.pop();
//当前内部的字符串,需要操作num次
String nowStr = sb.toString();
StringBuilder temp = new StringBuilder();
for(int i=0;i<num;i++){
temp.append(nowStr);
}
sb = new StringBuilder(str+temp.toString()); //拼接外层字符串
}else{
sb.append(c);// 累加外层字母
}
}
return sb.toString();
}
}
155.最小栈 | Hot100 【栈】 第70题
class MinStack {
private List<Integer> list;//栈的存储结构
private List<Integer> minList;//与栈同步插入删除的list,不过插入的时候重复插入最小值
private int min_value = Integer.MAX_VALUE;
public MinStack() {
this.list = new ArrayList<>();
this.minList = new ArrayList<>();
}
public void push(int val) {
list.add(val);
if(minList.size()==0){
minList.add(val);
}else{
minList.add(Math.min(minList.get(minList.size()-1),val));
}
}
public void pop() {
int b = list.get(list.size()-1);
list.remove(list.size()-1);
minList.remove(minList.size()-1);
}
public int top() {
return list.get(list.size()-1);
}
public int getMin() {
return minList.get(minList.size()-1);
}
}
20.有效的括号 | Hot100 【栈】 第69题
class Solution {
public boolean isValid(String s) {
Deque<Character> stack = new LinkedList<>();
for(int i=0;i<s.length();i++){
Character c = s.charAt(i);
if(c == '(' || c == '{' || c == '['){
stack.push(c);
}else{
if(stack.isEmpty()){
return false;
}else{
Character a = stack.pop();
if(c == ')' && a != '('){
return false;
}else if(c == '}' && a!='{'){
return false;
}else if(c == ']' && a!='['){
return false;
}
}
}
}
return stack.isEmpty();
}
}
153.寻找旋转排序数组中的最小值 | Hot100 【二分查找】 第67题
class Solution {
public int findMin(int[] nums) {
int left = 0,right = nums.length-1;
int result = Integer.MAX_VALUE;
while(left<=right){
int mid = (left+right)/2;
if(nums[mid]<nums[right]){
//说明最小值不会出现在mid~right,mid在最小值元素的→侧,所以舍弃右边区间
right = mid-1;
}else{
//说明最小值不会出现在left~mid,mid在最小值元素的←侧,所以舍弃左边区间
left = mid+1;
}
result = Math.min(nums[mid],result);
}
return result;
}
}
33. 搜索旋转排序数组 | Hot100 【二分查找】 第66题
class Solution {
public int search(int[] nums, int target) {
//首先,我们要知道三个区间,left~mid,mid~right,left比mid小,那么left~mid有序,mid小于right,mid~right有序
int left=0,right=nums.length-1;
while(left<=right){
int mid = (left+right)/2;
if(nums[mid] == target)return mid;
if(nums[left] <= nums[mid]){
if(nums[left]<=target && target<=nums[mid]){
//left~mid有序
right = mid-1;
}else{
left = mid+1;
}
}else{
if(nums[mid]<=target && target<=nums[right]){
//mid~right有序
left = mid+1;
}else{
right = mid-1;
}
}
}
return -1;
}
}
34. 在排序数组中查找元素的第一个和最后一个位置 | Hot100 【二分查找】 第65题
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] result = new int[]{-1,-1};
int leftIndex=-1,rightIndex=-1;
int left=0,right=nums.length-1;
while(left<=right){
int mid = (left+right)/2;
if(nums[mid] == target){
leftIndex = mid;
right = mid-1;//这是要往左继续找到target
}else if(nums[mid] < target){
left = mid+1;
}else{
right = mid-1;
}
}
left=0;
right=nums.length-1;
while(left<=right){
int mid = (left+right)/2;
if(nums[mid] == target){
rightIndex = mid;
left = mid+1;//这是要往右继续找到target
}else if(nums[mid] < target){
left = mid+1;
}else{
right = mid-1;
}
}
result[0] = leftIndex;
result[1] = rightIndex;
return result;
}
}
74、搜索二维矩阵 | Hot100 【二分查找】 第64题
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int left=0,right = matrix.length-1;
int i=0;
//用二分先定位出这个数据可能在哪一行
while(left<=right){
if (left == right){
i = left;
break;
}
i = (left+right)/2;
if(target == matrix[i][matrix[0].length-1]){
return true;
}
if(target == matrix[i][0]){
return true;
}
if(target>matrix[i][0] && target<matrix[i][matrix[0].length-1]){
break;
}
if(matrix[i][matrix[0].length-1] < target){
left = i+1;
}else{
right = i-1;
}
}
//在找到的这一行上用二分搜索
left = 0;
right = matrix[0].length-1;
while(left<=right){
int mid = (left+right)/2;
if(target == matrix[i][mid]){
return true;
}
if(target < matrix[i][mid]){
right = mid-1;
}else{
left = mid+1;
}
}
return false;
}
}
35、搜索插入位置 | Hot100 【二分查找】 第63题
class Solution {
public int searchInsert(int[] nums, int target) {
int left=0,right=nums.length-1;
while(left <= right){
int mid = (left+right)/2;
if(nums[mid]==target){
return mid;
}
if(nums[mid]<target){
left = mid+1;
}else{
right = mid-1;
}
}
return left;
}
}
46、全排列 | Hot100 【回溯】 第55题
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
List<Integer> data = new ArrayList<>();
for(int num:nums){
data.add(num);
}
dfs(result,data,0);
return result;
}
public void dfs(List<List<Integer>> result,List<Integer> data,int first){
if(first == data.size()){
result.add(new ArrayList<>(data));
return;
}
for (int i = first; i < n; i++) {
Collections.swap(output, first, i); // 交换元素
backtrack(n, output, res, first + 1); // 递归填下一个位置
Collections.swap(output, first, i); // 撤销交换(回溯)
}
}
}
200、岛屿数量 | Hot100 【图论】 第51题
给你一个由 '1'
(陆地)和 '0'
(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
class Solution {
public int numIslands(char[][] grid) {
int result=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);
result++;
}
}
}
return result;
}
public void dfs(char[][] grid,int i,int j){
if(!checkIndex(grid,i,j))return;
if(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);
}
public boolean checkIndex(char[][] grid,int i,int j){
return (i>=0&&i<grid.length)
&&
(j>=0&&j<grid[0].length);
}
}
124、二叉树中的最大路径和 | Hot100 【二叉树】 第50题
二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。
路径和 是路径中各节点值的总和。
给你一个二叉树的根节点 root
,返回其 最大路径和 。
class Solution {
int result = Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
maxPathSumExcludeRoot(root);
return result;
}
public int maxPathSumExcludeRoot(TreeNode root) {
if(root == null)return 0;
int val = root.val;
int a = Math.max(maxPathSumExcludeRoot(root.left),0);
int b = Math.max(maxPathSumExcludeRoot(root.right),0);
int nodeSum = a+b+val;//左中右
int resultSum = val+Math.max(a,b);//左中或右中
result = Math.max(Math.max(resultSum,nodeSum),result);//选择 左中右/左中/右中 这条路
return resultSum;//向上贡献只能选择一条子树,不存在左中右再向上结合其他节点形成新路径
}
}
437、二叉树的最近公共祖先 | Hot100 【二叉树】 第49题
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null)return null;
//为啥这里直接返回,因为就算如果root下面有p或者q,那么最近祖先必然是当前的root呀,所以直接返回,已经包含了这种情况
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 && right != null){
return right;
}
else{
//left == null && right != null
return left;
}
}
}
437、路径总和 III | Hot100 【二叉树】 第48题
给定一个二叉树的根节点 root
,和一个整数 targetSum
,求该二叉树里节点值之和等于 targetSum
的 路径 的数目。
路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
class Solution {
public int pathSum(TreeNode root, int targetSum) {
int result = 0;
if(root==null)return 0;
//路径可以不经过根结点
result += rootSum(root,targetSum);//先求经过根结点的路径
result += pathSum(root.left,targetSum);//再求经过只包含左子树的路径
result += pathSum(root.right,targetSum);//再求经过只包含右子树的路径
return result;
}
public int rootSum(TreeNode root,long targetSum){
int result = 0;
if(root == null)return 0;
if(targetSum == root.val)result++;
result += rootSum(root.left,targetSum-root.val);
result += rootSum(root.right,targetSum-root.val);
return result;
}
}
105、从前序与中序遍历序列构造二叉树 | Hot100 【二叉树】 第47题
给定两个整数数组 preorder
和 inorder
,其中 preorder
是二叉树的先序遍历, inorder
是同一棵树的中序遍历,请构造二叉树并返回其根节点。
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
// 创建一个哈希表来存储中序遍历的值及其对应的索引
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i);
}
// 调用辅助函数,传入初始的索引范围和哈希表
return buildTree(preorder, inorder, 0, preorder.length - 1, 0, inorder.length - 1, map);
}
public TreeNode buildTree(int[] preorder, int[] inorder, int preStart, int preEnd, int inStart, int inEnd, Map<Integer, Integer> map) {
// 基本情况:如果索引超出范围,则返回 null
if (preStart > preEnd || inStart > inEnd) {
return null;
}
// 前序遍历的第一个节点是当前子树的根节点
int rootValue = preorder[preStart];
TreeNode root = new TreeNode(rootValue);
// 在中序遍历中找到根节点的位置
int inIndex = map.get(rootValue);
// 计算左子树的大小
int leftSubtreeSize = inIndex - inStart;
// 划分区间
// 左子树的索引范围
int leftInStart = inStart;
int leftInEnd = inIndex - 1;
int leftPreStart = preStart + 1;
int leftPreEnd = leftPreStart + leftSubtreeSize - 1;
// 右子树的索引范围
int rightInStart = inIndex + 1;
int rightInEnd = inEnd;
int rightPreStart = leftPreEnd + 1;
int rightPreEnd = preEnd;
// 递归构造左子树
root.left = buildTree(preorder, inorder, leftPreStart, leftPreEnd, leftInStart, leftInEnd, map);
// 递归构造右子树
root.right = buildTree(preorder, inorder, rightPreStart, rightPreEnd, rightInStart, rightInEnd, map);
return root;
}
}
114、二叉树展开为链表 | Hot100 【二叉树】 第46题
给你二叉树的根结点 root
,请你将它展开为一个单链表:
- 展开后的单链表应该同样使用
TreeNode
,其中right
子指针指向链表中下一个结点,而左子指针始终为null
。 - 展开后的单链表应该与二叉树 先序遍历 顺序相同。
class Solution {
public void flatten(TreeNode root) {
Deque<TreeNode> stack = new LinkedList<>();
List<TreeNode> list = new ArrayList<>();
while(!stack.isEmpty() || root != null){
while(root != null){
list.add(root);
stack.push(root);
root = root.left;
}
root = stack.pop();
root = root.right;
}
for(int i=0;i<list.size()-1;i++){
list.get(i).right = list.get(i+1);
list.get(i).left = null;
}
}
}
199、二叉树的右视图 | Hot100 【二叉树】 第45题
给定一个二叉树的 根节点 root
,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
class Solution {
public List<Integer> rightSideView(TreeNode root) {
//主要逻辑就是层序遍历,取每一层的最后一个节点加入到结果集中
List<Integer> list = new ArrayList<>();
if(root == null)return list;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int size = queue.size();
for(int i=0;i<size;i++){
TreeNode node = queue.poll();
if(node.left!=null){
queue.offer(node.left);
}
if(node.right!=null){
queue.offer(node.right);
}
if(i==size-1){
list.add(node.val);
}
}
}
return list;
}
}
230、二叉搜索树中第k小的元素 | Hot100 【二叉树】 第44题
给定一个二叉搜索树的根节点 root
,和一个整数 k
,请你设计一个算法查找其中第 k
小的元素(从 1 开始计数)。
class Solution {
public int kthSmallest(TreeNode root, int k) {
Deque<TreeNode> stack = new LinkedList<>();
while(!stack.isEmpty() || root!=null){
while(root != null){
stack.push(root);
root = root.left;
}
TreeNode node = stack.pop();
k--;
if(k==0){
return node.val;
}
root = node.right;
}
return root.val;
}
}
98、验证二叉搜索树 | Hot100 【二叉树】 第43题
给你一个二叉树的根节点 root
,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
- 节点的左子树只包含 小于 当前节点的数。
- 节点的右子树只包含 大于 当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
class Solution {
public boolean isValidBST(TreeNode root) {
Deque<TreeNode> stack = new LinkedList<>();
long inOrder = Long.MIN_VALUE;
while(!stack.isEmpty() || root != null){
while(root != null){
stack.push(root);
root = root.left;
}
TreeNode node = stack.pop();
if(node.val <= inOrder){
return false;
}
inOrder = (long)node.val;
root = node.right;
}
return true;
}
}
108、将有序数组转换为二叉搜索树 | Hot100 【二叉树】 第42题
给你一个整数数组 nums
,其中元素已经按 升序 排列,请你将其转换为一棵 平衡 二叉搜索树。
将一个升序排列的整数数组转换为一棵平衡二叉搜索树(BST),可以通过递归的方法实现。关键在于每次选择数组的中间元素作为当前子树的根节点,这样可以确保左右子树的高度差不超过1,从而保证树是平衡的。
解决思路
- 选择中间元素:对于给定的数组范围,选择中间元素作为当前子树的根节点。
- 递归构建左右子树:
- 以中间元素左侧的部分数组构建左子树。
- 以中间元素右侧的部分数组构建右子树。
- 终止条件:当数组范围为空时,返回
null
。
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return build(nums,0,nums.length-1);
}
public TreeNode build(int[] nums,int l,int r){
if(l > r){
return null;
}
int mid = l + (r-l)/2;
TreeNode root = new TreeNode(nums[mid]);
root.left = build(nums,l,mid-1);
root.right = build(nums,mid+1,r);
return root;
}
}
102、二叉树的层序遍历 | Hot100 【二叉树】 第41题
给你二叉树的根节点 root
,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
List<List<Integer>> result = new ArrayList<>();
if(root == null)return result;
while(!queue.isEmpty()){
List<Integer> list = new ArrayList<>();
int size = queue.size();
for(int i=0;i<size;i++){
TreeNode node = queue.poll();
list.add(node.val);
if(node.left!=null)queue.add(node.left);
if(node.right!=null)queue.add(node.right);
}
result.add(list);
}
return result;
}
}
543、二叉树的直径 | Hot100 【二叉树】 第40题
给你一棵二叉树的根节点,返回该树的 直径 。
二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root
。
两节点之间路径的 长度 由它们之间边数表示。
class Solution {
private int ans = 0;
public int diameterOfBinaryTree(TreeNode root) {
depth(root);
return ans;
}
public int depth(TreeNode root){
if(root == null)return 0;
int left = depth(root.left);
int right = depth(root.right);
ans = Math.max(left+right,ans);
return Math.max(left,right)+1;
}
}
101、对称二叉树 | Hot100 【二叉树】 第39题
给你一个二叉树的根节点 root
, 检查它是否轴对称。
class Solution {
public boolean isSymmetric(TreeNode root) {
if (root == null) {
return true; // 空树是对称的
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root.left);
queue.offer(root.right);
while (!queue.isEmpty()) {
TreeNode t1 = queue.poll();
TreeNode t2 = queue.poll();
if (t1 == null && t2 == null) {
continue; // 两个子树都为空,继续下一个
}
if (t1 == null || t2 == null) {
return false; // 只有一个子树为空,不是对称的
}
if (t1.val != t2.val) {
return false; // 节点值不相等,不是对称的
}
// 将对应的子节点加入队列
queue.offer(t1.left);
queue.offer(t2.right);
queue.offer(t1.right);
queue.offer(t2.left);
}
return true;
}
}
226、翻转二叉树 | Hot100 【二叉树】 第38题
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root==null)return null;
TreeNode left = root.left;
TreeNode right = root.right;
root.left = invertTree(right);
root.right = invertTree(left);
return root;
}
}
104、二叉树的最大深度 | Hot100 【二叉树】 第37题
给定一个二叉树 root
,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
class Solution {
public int maxDepth(TreeNode root) {
if(root==null)return 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int depth = 0;
while(!queue.isEmpty()){
int currentLevelNodes = queue.size();
for(int i=0;i<currentLevelNodes;i++){
TreeNode node = queue.poll();
if(node.left!=null){
queue.offer(node.left);
}
if(node.right!=null){
queue.offer(node.right);
}
}
depth++;
}
return depth;
}
}
94、二叉树的中序遍历 | Hot100 【二叉树】 第36题
中序遍历,访问顺序:左子树 -> 根节点 -> 右子树
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
Deque<TreeNode> stack = new LinkedList<>();
TreeNode current = root;
while (current != null || !stack.isEmpty()) {
// 先走到最左边
while (current != null) {
stack.push(current);
current = current.left;
}
// 弹出栈顶元素并访问
current = stack.pop();
list.add(current.val);
// 转向右子树
current = current.right;
}
return list;
}
}
146、LRU缓存 | Hot100 【链表】 第35题
class LRUCache {
class LinkNode {
int key;
int value;
LinkNode prev;
LinkNode next;
public LinkNode(){
}
public LinkNode(int _key,int _value){
key = _key;
value = _value;
}
}
private Map<Integer,LinkNode> map = new HashMap<>();
private int size;
private int capacity;
private LinkNode head,tail;
public LRUCache(int capacity) {
this.size = 0;
this.capacity = capacity;
head = new LinkNode();
tail = new LinkNode();
head.next = tail;
tail.prev = head;
}
public int get(int key) {
LinkNode node = map.get(key);
if(node == null){
return -1;
}
moveToHead(node);
return node.value;
}
public void put(int key, int value) {
LinkNode node = map.get(key);
if(node == null){
node = new LinkNode(key,value);
map.put(key,node);
addToHead(node);
size++;
if(size>capacity){
LinkNode tailNode = removeTail();
map.remove(tailNode.key);
}
}else{
node.value = value;
moveToHead(node);
}
}
public void removeNode(LinkNode node){
node.prev.next = node.next;
node.next.prev = node.prev;
}
public void addToHead(LinkNode node){
node.next = head.next;
node.prev = head;
head.next.prev = node;
head.next = node;
}
public void moveToHead(LinkNode node){
removeNode(node);
addToHead(node);
}
public LinkNode removeTail(){
LinkNode node = tail.prev;
removeNode(node);
return node;
}
}
148、排序链表 | Hot100 【链表】 第33题
class Solution {
public ListNode sortList(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode slow = head;
ListNode fast = head.next;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
}
ListNode first = head;
ListNode second = slow.next;
slow.next = null;
first = sortList(first);
second = sortList(second);
return merge(first,second);
}
public ListNode merge(ListNode first,ListNode second){
ListNode dummpy = new ListNode(-1);
ListNode temp = dummpy;
while(first != null && second != null){
if(first.val <= second.val){
temp.next = first;
first = first.next;
}else{
temp.next = second;
second = second.next;
}
temp = temp.next;
}
if(first!=null){
temp.next = first;
}else{
temp.next = second;
}
return dummpy.next;
}
}
138、随机链表的复制 | Hot100 【链表】 第32题
class Solution {
public Node copyRandomList(Node head) {
Map<Node,Node> map = new HashMap<>();
Node temp = head;
while(temp != null){
map.put(temp,new Node(temp.val));
temp = temp.next;
}
temp = head;
while(temp != null){
map.get(temp).next = map.get(temp.next);
map.get(temp).random = map.get(temp.random);
temp = temp.next;
}
return map.get(head);
}
}
24、两两交换链表中的结点 | Hot100 【链表】 第30题
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode node = new ListNode(0);
node.next=head;
ListNode temp = node;
while(temp.next != null && temp.next.next!=null){
ListNode node1 = temp.next;
ListNode node2 = temp.next.next;
temp.next = node2;
node1.next = node2.next;
node2.next = node1;
temp = node1;
}
return node.next;
}
}
19、删除链表的倒数第N个结点 | Hot100 【链表】 第29题
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode slow,fast = head;
for(int i=0;i<n;i++){
fast = fast.next;
}
ListNode result = new ListNode(0);
slow = result;
slow.next = head;
while(fast != null){
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return result.next;
}
}
2、两数相加 | Hot100 【链表】 第28题
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode p1=l1,p2=l2;
ListNode node = new ListNode(0);
ListNode first = node;
int carry = 0;
while(p1!=null || p2 != null){
int sum;
if(p1 == null){
sum = p2.val + carry;
p2 = p2.next;
}else if(p2 == null){
sum = p1.val + carry;
p1 = p1.next;
}else{
sum = p1.val + p2.val + carry;
p1 = p1.next;
p2 = p2.next;
}
node.val = (sum % 10);
carry = sum / 10;
if(p1!=null || p2 != null){
node.next = new ListNode(0);
node = node.next;
}
}
if(carry != 0){
node.next = new ListNode(carry);
}
return first;
}
}
21、合并两个有序链表 II | Hot100 【链表】 第27题
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode l1 = list1;
ListNode l2 = list2;
ListNode node = new ListNode(-1);
ListNode first = node;
while(l1!=null && l2!=null){
if(l1.val <= l2.val){
node.next = l1;
l1 = l1.next;
}else{
node.next = l2;
l2 = l2.next;
}
node = node.next;
}
if(l1 == null){
node.next = l2;
}else{
node.next = l1;
}
return first.next;
}
}
142、环形链表 II | Hot100 【链表】 第26题
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head == null)return null;
ListNode slow = head;
ListNode fast = head;
while(fast != null){
slow = slow.next;
if(fast.next != null){
fast = fast.next.next;
}else{
return null;
}
if(slow == fast){
ListNode ptr = head;
while(ptr!=slow){
ptr = ptr.next;
slow = slow.next;
}
return ptr;
}
}
return null;
}
}
141、环形链表 | Hot100 【链表】 第25题
public class Solution {
public boolean hasCycle(ListNode head) {
if(head == null || head.next == null)return false;
ListNode slow = head;
ListNode fast = head;
while(slow!=fast){
if(fast == null || fast.next == null)return false;
slow = slow.next;
fast = fast.next.next;
}
return true;
}
}
234、回文链表 | Hot100 【链表】 第24题
class Solution {
public boolean isPalindrome(ListNode head) {
//快慢指针确定中间节点
ListNode slow = head,fast = head;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
}
ListNode second = null;
if(fast==null){
//偶数节点,slow直接指向第二个链表头部
second = reverseList(slow);
}else{
//奇数节点,slow指向中间节点
second = reverseList(slow.next);
}
ListNode first = head;
while(second!=null){
if(first.val != second.val){
return false;
}
first = first.next;
second = second.next;
}
return true;
}
private ListNode reverseList(ListNode head){
ListNode temp = head;
ListNode prev = null;
ListNode next = null;
while(temp != null){
next = temp.next;
temp.next = prev;
prev = temp;
temp = next;
}
return prev;
}
}
206、反转链表 | Hot100 【链表】 第23题
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
class Solution {
public ListNode reverseList(ListNode head) {
ListNode cur = head;
ListNode prev = null;
while(cur != null){
ListNode next = cur.next;
cur.next = prev;
prev = cur;
cur = next;
}
return prev;
}
}
160、相交链表 | Hot100 【链表】 第22题
/**
* 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) {
ListNode tempA=headA,tempB=headB;
while(tempA!=tempB){
if(tempA == null){
tempA = headB;
}else{
tempA = tempA.next;
}
if(tempB == null){
tempB = headA;
}else{
tempB = tempB.next;
}
}
return tempA;
}
}
240、搜索二维矩阵 II | Hot100 【矩阵】 第21题
编写一个高效的算法来搜索 m x n
矩阵 matrix
中的一个目标值 target
。该矩阵具有以下特性:
- 每行的元素从左到右升序排列。
- 每列的元素从上到下升序排列。
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
//从右上角开始搜索
int x = 0,y=matrix[0].length-1;
while(x<matrix.length && y>=0){
if(target == matrix[x][y]){
return true;
}
if(target > matrix[x][y]){
x++;
}else{
y--;
}
}
return false;
}
}
48、旋转图像 | Hot100 【矩阵】 第20题
给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
class Solution {
public void rotate(int[][] matrix) {
//水平翻转
for(int i=0;i<matrix.length/2;i++){
for(int j=0;j<matrix[0].length;j++){
int temp = matrix[i][j];
matrix[i][j] = matrix[matrix.length-i-1][j];
matrix[matrix.length-i-1][j] = temp;
}
}
//主对角线翻转
for(int i=0;i<matrix.length;i++){
for(int j=0;j<i;j++){
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
}
}
54、螺旋矩阵 | Hot100 【矩阵】 第19题
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> list = new ArrayList<>();
//定义4个边界
int top=0,bottom=matrix.length-1,left=0,right=matrix[0].length-1;
while(left<=right && top <= bottom){
for(int i=left;i<=right && check(top,bottom,left,right);i++){
list.add(matrix[top][i]);
}
top++;
for(int i=top;i<=bottom && check(top,bottom,left,right);i++){
list.add(matrix[i][right]);
}
right--;
for(int i=right;i>=left && check(top,bottom,left,right);i--){
list.add(matrix[bottom][i]);
}
bottom--;
for(int i=bottom;i>=top && check(top,bottom,left,right);i--){
list.add(matrix[i][left]);
}
left++;
}
return list;
}
private boolean check(int top,int bottom,int left,int right){
return left<=right && top <= bottom;
}
}
73、矩阵置零 | Hot100 【矩阵】 第18题
class Solution {
public void setZeroes(int[][] matrix) {
boolean[] hang = new boolean[matrix.length];
boolean[] lie = new boolean[matrix[0].length];
for(int i=0;i<matrix.length;i++){
for(int j=0;j<matrix[0].length;j++){
if(matrix[i][j]==0){
hang[i]=true;
lie[j]=true;
}
}
}
for(int i=0;i<matrix.length;i++){
for(int j=0;j<matrix[0].length;j++){
if(hang[i] || lie[j]){
matrix[i][j]=0;
}
}
}
}
}
238、除自身以外数组的乘积 | Hot100 【普通数组】 第16题
class Solution {
public int[] productExceptSelf(int[] nums) {
int[] leftMul = new int[nums.length];
int[] rightMul = new int[nums.length];
leftMul[0] = 1;
rightMul[nums.length-1] = 1;
for(int i=1;i<nums.length;i++){
leftMul[i] = leftMul[i-1]*nums[i-1];
}
for(int i=nums.length-2;i>=0;i--){
rightMul[i] = rightMul[i+1]*nums[i+1];
}
int[] answer = new int[nums.length];
for(int i=0;i<nums.length;i++){
answer[i] = leftMul[i]*rightMul[i];
}
return answer;
}
}
189、轮转数组 | Hot100 【普通数组】 第15题
class Solution {
public void rotate(int[] nums, int k) {
k = k % nums.length;
reverse(nums,0,nums.length-1);
reverse(nums,0,k-1);
reverse(nums,k,nums.length-1);
}
public void swap(int[] nums,int i,int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
public void reverse(int[] nums,int start,int end){
if(start>end)return;
while(start<end){
swap(nums,start,end);
start++;end--;
}
}
}
56、合并区间 | Hot100 【普通数组】 第14题
class Solution {
public int[][] merge(int[][] intervals) {
List<int[]> list = new ArrayList<>();
//先根据区间左端点排序
Arrays.sort(intervals,new Comparator<int[]>(){
public int compare(int[] num1,int[] num2){
return num1[0]-num2[0];
}
});
for(int i=0;i<intervals.length;i++){
int curIntervalLeft = intervals[i][0];
int curIntervalRight = intervals[i][1];
if(list.size()==0){
list.add(new int[]{curIntervalLeft,curIntervalRight});
continue;
}
int[] endInterval = list.get(list.size()-1);
if(endInterval[1]>=curIntervalLeft){
//它们重合,我们需要用当前区间的右端点更新数组 merged 中最后一个区间的右端点,将其置为二者的较大值。
endInterval[1] = Math.max(curIntervalRight,endInterval[1]);
}else{
//当前区间的左端点在数组 merged 中最后一个区间的右端点之后,那么它们不会重合,我们可以直接将这个区间加入数组 merged 的末尾;
list.add(new int[]{curIntervalLeft,curIntervalRight});
}
}
return list.toArray(new int[list.size()][]);
}
}
53、最大子数组和 | Hot100 【普通数组】 第13题
class Solution {
public int maxSubArray(int[] nums) {
int pre = 0;
int result = nums[0];
for(int num:nums){
//若前面的序列加起来贡献小,就舍弃前面的序列,从当前num开始往后加
pre = Math.max(pre+num,num);
result = Math.max(pre,result);
}
return result;
}
}
560、和为K的子数组 | Hot100 【子串】 第10题
class Solution {
public int subarraySum(int[] nums, int k) {
int pre=0,count=0;
Map<Integer,Integer> map = new HashMap<>();
map.put(0,1);
for(int i=0;i<nums.length;i++){
pre += nums[i];
if(map.containsKey(pre-k)){
count += map.get(pre-k);
}
map.put(pre,map.getOrDefault(pre,0)+1);
}
return count;
}
}
438、找到字符串中所有字母异位词 | Hot100 【滑动窗口】 第9题
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> list = new ArrayList<>();
if(s.length()<p.length()){
return list;
}
int[] pCount = new int[26];
for(int i=0;i<p.length();i++){
pCount[p.charAt(i)-'a']++;
}
int[] sCount = new int[26];
for(int i=0;i<p.length()-1;i++){
sCount[s.charAt(i)-'a']++;
}
for(int left=0,right=p.length()-1;right<s.length();left++,right++){
sCount[s.charAt(right)-'a']++;
if(Arrays.equals(sCount,pCount)){
list.add(left);
}
sCount[s.charAt(left)-'a']--;
}
return list;
}
}
3、无重复字符的最长子串 | Hot100 【滑动窗口】 第8题
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> set = new HashSet<>();
int result = 0;
int right = -1;
for(int left=0;left<s.length();left++){
if(left!=0){
set.remove(s.charAt(left-1));
}
while(right+1<s.length() && !set.contains(s.charAt(right+1))){
set.add(s.charAt(right+1));
right++;
}
result = Math.max(result,right-left+1);
}
return result;
}
}
15、三数之和 | Hot100 【双指针】 第6题
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
for(int i=0;i<nums.length;i++){
if(i>0 && nums[i]==nums[i-1])continue;
int left=i+1,right=nums.length-1;
int target = -nums[i];
while(left<right){
if(nums[left]+nums[right] == target){
result.add(Arrays.asList(nums[i],nums[left],nums[right]));
left++;
right--;
while(left<right && nums[left]==nums[left-1])left++;
while(left<right && nums[right]==nums[right+1])right--;
}else if(nums[left]+nums[right] < target){
left++;
}else{
right--;
}
}
}
return result;
}
}
11、盛最多水的容器 | Hot100 【双指针】 第5题
class Solution {
public int maxArea(int[] height) {
int left=0,right=height.length-1;
int area = calArea(height,left,right);
while(left<=right){
if(height[left]<height[right]){
left++;
}else{
right--;
}
if(left>=right)break;
area = Math.max(calArea(height,left,right),area);
}
return area;
}
private int calArea(int[] height,int left,int right){
return Math.min(height[left],height[right])*(right-left);
}
}
283、移动零 | Hot100 【双指针】 第4题
class Solution {
public void moveZeroes(int[] nums) {
//本题采用双指针
int slow = 0,fast=0;//使用快慢指针,
while(fast < nums.length){
//慢指针目标指向0元素,等待与快指针交换
//快指针目标指向非0元素(0元素后的非0元素),等待与慢指针交换
//如果当前元素是非0元素
if(nums[fast]!=0){
//遇到了非0元素,要判断是否需要交换
if(nums[slow]==0){
swap(nums,slow,fast);
}
slow++;
fast++;
//如果当前元素是0元素,slow要停下来
}else{
fast++;
}
}
}
private void swap(int[] nums, int left, int right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
}
}
128、最长连续序列 | Hot100 【哈希】 第3题
class Solution {
public int longestConsecutive(int[] nums) {
Set<Integer> num_set = new HashSet<>();
for(int num:nums){
num_set.add(num);
}
int cur_num = 0,cur_count = 0;
int result=0;
for(int num:num_set){
if(!num_set.contains(num-1)){
cur_num = num;
cur_count = 0;
while(num_set.contains(cur_num)){
cur_count++;
cur_num++;
}
result = Math.max(cur_count,result);
}
}
return result;
}
}
49、字母异位词分组 | Hot100 【哈希】 第2题
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String,List<String>> map = new HashMap<>();
for(String str : strs){
char[] array = str.toCharArray();
Arrays.sort(array);
String key = new String(array);
List<String> temp = null;
if(map.containsKey(key)){
temp = map.get(key);
}else{
temp = new ArrayList<String>();
}
temp.add(str);
map.put(key,temp);
}
return new ArrayList<List<String>>(map.values());
}
}
1、两数之和 | Hot100 【哈希】 第1题
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap<>();
for(int i=0;i<nums.length;i++){
if(map.containsKey(target-nums[i])){
return new int[]{map.get(target-nums[i]),i};
}
map.put(nums[i],i);
}
return new int[0];
}
}