力扣Hot100刷题记录

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

扫描二维码关注公众号,回复: 17565055 查看本文章
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,从而保证树是平衡的。

解决思路

  1. 选择中间元素:对于给定的数组范围,选择中间元素作为当前子树的根节点。
  2. 递归构建左右子树
    • 以中间元素左侧的部分数组构建左子树。
    • 以中间元素右侧的部分数组构建右子树。
  3. 终止条件:当数组范围为空时,返回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];
    }
}

猜你喜欢

转载自blog.csdn.net/qq_46248151/article/details/145384389