LeetCode150-滑动窗口+哈希表

面试150题-滑动窗口+哈希表

📕文章题目选自LeetCode面试150题-滑动窗口+哈希表
😊该文章内容基于作者本人思考总结,如有错误欢迎指正
🏠题单地址:https://leetcode.cn/studyplan/top-interview-150/

滑动窗口

LeetCode150-长度最小的子数组-LC209

/**
 * 题目:长度最小的子数组
 * 算法:滑动窗口
 * 解题思路:1.初始窗口大小为0 start end 都是从0开始
 *         2.while循环中end一直向右移动并且 当sum > target,start向右移动缩小窗口大小
 *         3.ans记录最小值
 */
public class LC209 {
    public static void main(String[] args) {
        int[] nums = {2,3,1,2,4,3};
        int target = 7;
        System.out.println(minSubArrayLen(target,nums));
    }
    public static int minSubArrayLen(int target, int[] nums) {
        int len = nums.length;
        int start = 0;
        int end = 0;//end值不能设为1 否则无法添加第一个元素
        int sum = 0;
        int ans = Integer.MAX_VALUE;
        while(end < len){
            sum += nums[end];
            while(sum >= target){
                ans = Math.min(ans,end - start + 1);
                sum-=nums[start++];
            }
            end++;
        }
        return ans == Integer.MAX_VALUE ? 0 : ans;
    }
}

LeetCode150-无重复字符的最长子串-LC209

class Solution {
    public int lengthOfLongestSubstring(String s) {
        if(s.length() == 1) return 1;
        int maxLength = 0;
        int right = -1;
        Set<Character> set = new HashSet<Character>();
        for(int left = 0; left < s.length() - 1;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++;
            }
            maxLength = Math.max(maxLength,right - left + 1);
        }
        return maxLength;
    }
}

LeetCode150-串联所有单词的子串-LC30

package cn.dsxriiiii.LeetCode.LC150;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ProjectName: Mounts
 * @Author: DSXRIIIII
 * @CreateDate: 2024/6/16 16:32
 * @Email: lihh53453@hundsun.com
 * @Description: 串联所有单词的子串
 * 思路:滑动窗口
 *      1.确定滑动窗口起始位置left,right
 *      2.right不断右移,移动条件为right+单个单词长度不超过s.length()
 *      3.left不断右移,移动条件为
 *                              1.right右移产生的单词在字符串中不存在 此时需要将map清空 left = right count计数器 =0
 *                              2.right右移产生单个单词数超过了words中的数量 此时while循环会判断当前right右移产生单个单词数是否一直超过了words中的数量
 *                                true:count(用来计数判断的有效个数)--,left移动
 */
public class LC30 {
    public static void main(String[] args) {
        String s = "foobarfoobarfoothe";
        String[] words = {"foo","bar","foo","the"};
        System.out.println(findSubstring(s,words));
    }

    public static List<Integer> findSubstring(String s,String[] words){
        Map<String,Integer> map = new HashMap<>();
        List<Integer> res = new ArrayList<>();
        if(s.isEmpty() || words.length == 0) return res;
        for(String word:words){
            if(!s.contains(word)) return res;
            map.put(word,map.getOrDefault(word,0) + 1);
        }
        int oneWordLength = words[0].length();
        int wordsLength = oneWordLength * words.length;
        if(wordsLength > s.length()) return res;
        for(int i = 0;i < words[0].length();i++){
            int left = i;
            int right = i;
            int count = 0;
            Map<String,Integer> subMap = new HashMap<>();
            while(right + oneWordLength  <= s.length()){
                String newWordByRight = s.substring(right,right+oneWordLength);
                right = right + oneWordLength;
                if(!map.containsKey(newWordByRight)){
                    subMap.clear();
                    left = right;
                    count = 0;
                }else{
                    subMap.put(newWordByRight,subMap.getOrDefault(newWordByRight,0) + 1);
                    count++;
                    while(subMap.getOrDefault(newWordByRight,0) > map.getOrDefault(newWordByRight,0)){
                        String newWordByLeft = s.substring(left,left + oneWordLength);
                        subMap.put(newWordByLeft,subMap.getOrDefault(newWordByLeft,0) - 1);
                        count--;
                        left = left + oneWordLength;
                    }
                    if(count == words.length){
                        res.add(left);
                    }
                }
            }
        }
        return res;
    }

    public static List<Integer> solution2(String s, String[] words) {
        List<Integer> res = new ArrayList<>();
        Map<String, Integer> wordsMap = new HashMap<>();
        if (s.isEmpty() || words.length == 0) return res;
        for (String word: words) {
            // 主串s中没有这个单词,直接返回空
            if (!s.contains(word)) return res;
            // map中保存每个单词,和它出现的次数
            wordsMap.put(word, wordsMap.getOrDefault(word, 0) + 1);
        }
        // 每个单词的长度, 总长度
        int oneLen = words[0].length(), wordsLen = oneLen * words.length;
        // 主串s长度小于单词总和,返回空
        if (wordsLen > s.length()) return res;
        // 只讨论从0,1,..., oneLen-1 开始的子串情况,
        // 每次进行匹配的窗口大小为 wordsLen,每次后移一个单词长度,由左右窗口维持当前窗口位置
        for (int i = 0; i < oneLen; ++i) {
            // 左右窗口
            int left = i, right = i, count = 0;
            // 统计每个符合要求的word
            Map<String, Integer> subMap = new HashMap<>();
            // 右窗口不能超出主串长度
            while (right + oneLen <= s.length()) {
                // 得到一个单词
                String word = s.substring(right, right + oneLen);
                // 有窗口右移
                right += oneLen;
                // words[]中没有这个单词,那么当前窗口肯定匹配失败,直接右移到这个单词后面
                if (!wordsMap.containsKey(word)) {
                    left = right;
                    // 窗口内单词统计map清空,重新统计
                    subMap.clear();
                    // 符合要求的单词数清0
                    count = 0;
                } else {
                    // 统计当前子串中这个单词出现的次数
                    subMap.put(word, subMap.getOrDefault(word, 0) + 1);
                    ++count;
                    // 如果这个单词出现的次数大于words[]中它对应的次数,又由于每次匹配和words长度相等的子串
                    // 如 ["foo","bar","foo","the"]  "| foobarfoobar| foothe"
                    // 第二个bar虽然是words[]中的单词,但是次数抄了,那么右移一个单词长度后 "|barfoobarfoo|the"
                    // bar还是不符合,所以直接从这个不符合的bar之后开始匹配,也就是将这个不符合的bar和它之前的单词(串)全移出去
                    while (subMap.getOrDefault(word, 0) > wordsMap.getOrDefault(word, 0)) {
                        // 从当前窗口字符统计map中删除从左窗口开始到数量超限的所有单词(次数减一)
                        String w = s.substring(left, left + oneLen);
                        subMap.put(w, subMap.getOrDefault(w, 0) - 1);
                        // 符合的单词数减一
                        --count;
                        // 左窗口位置右移
                        left += oneLen;
                    }
                    // 当前窗口字符串满足要求
                    if (count == words.length) res.add(left);
                }
            }
        }
        return res;
    }
}

LeetCode150-最小覆盖子串-LC76

package cn.dsxriiiii.LeetCode.LC150;

/**
 * @ProjectName: Mounts
 * @Author: DSXRIIIII
 * @CreateDate: 2024/6/17 9:55
 * @Email: lihh53453@hundsun.com
 * @Description: 最小覆盖子串
 * 思路:滑动窗口
 *      1.维护两个数组保存128位(包含大小写)
 *      2.包含函数 判断s中所有的字符数量比t的所有字符数量多
 *      3.右移条件:走到s串的结尾
 *      4.左移条件:使用包含函数 不断左指针右移 并且在数组中减少字符--;
 *      5.此时左右指针维护的最小字串长度判断并且不断更新
 */
public class LC76 {
    public static void main(String[] args) {
        String s = "aaaaaaaaaaaabbbbbcdd";
        String t = "abcdd";
        System.out.println(minWindow(s,t));
    }
    public static String minWindow(String s, String t) {
        char[] charArray = s.toCharArray();
        int nowLeft = -1;
        int nowRight = s.length();
        int left = 0;
        int[] arrT = new int[128];
        int[] arrS = new int[128];
        for(char c : t.toCharArray()){
            arrT[c]++;
        }
        for (int right = 0; right < s.length(); right++) {
            arrS[charArray[right]]++;
            while(isCover(arrS,arrT)){
                if(right - left < nowRight - nowLeft){
                    nowRight = right;
                    nowLeft = left;
                }
                arrS[charArray[left++]]--;
            }
        }
        return nowLeft < 0 ? "" : s.substring(nowLeft,nowRight+1);
    }

    private static boolean isCover(int[] s, int[] t) {
        for(int i = 'A';i <= 'Z';i++){
            if(s[i] < t[i]){
                return false;
            }
        }
        for(int i = 'a';i <= 'z';i++){
            if(s[i] < t[i]){
                return false;
            }
        }
        return true;
    }
}

滑动窗口总结

1.长度最小的子数组

初始窗口大小为0 start end 都是从0开始
while循环中end一直向右移动并且 当sum > targetstart向右移动缩小窗口大小
ans记录最小值

2,.无重复字符的最长子串

遍历字符串,每次移动左指针时从集合中移除相应字符,并且将left-1的字符移除
right从-1开始

哈希表

LeetCode150-赎金信-LC383

/**
 * @ProjectName: Mounts
 * @Description: LC383 赎金信
 * @Author: DSXRIIIII
 * @CreateDate: 2024/5/24 17:02
 * @Email: lihh53453@hundsun.com
 *
 * 解题思路:字母数组++和--
 **/
public class LC383 {
    public boolean canConstruct(String ransomNote, String magazine) {
        if(ransomNote.length() > magazine.length()){
            return false;
        }
        int[] charArr = new int[26];
        for(char a : magazine.toCharArray()){
            charArr[a -'a']++;
        }
        for(char b : ransomNote.toCharArray()){
            --charArr[b - 'a'];
            if(charArr[b - 'a'] < 0){
                return false;
            }
        }
        return true;
    }
}

LeetCode150-同构字符串-LC205

import java.util.HashMap;
import java.util.Map;

/**
 * @ProjectName: Mounts
 * @Description: LC205 同构字符串
 * @Author: DSXRIIIII
 * @CreateDate: 2024/5/24 17:12
 * @Email: lihh53453@hundsun.com
 *
 * 思路一:两个HashMap
 **/
public class LC205 {
    public boolean isIsomorphic(String s, String t) {
        if (s.length() != t.length()) {
            return false;
        }
        Map<Character, Character> mapS = new HashMap<>();
        Map<Character, Character> mapT = new HashMap<>();
        for (int index = 0; index < s.length(); index++) {
            char charS = s.charAt(index);
            char charT = t.charAt(index);
            if (!mapS.containsKey(charS)) {
                mapS.put(charS, charT);
            }
            if (!mapT.containsKey(charT)) {
                mapT.put(charT, charS);
            }
            if (mapS.get(charS) != charT || mapT.get(charT) != charS) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        String s = "paper";
        String t = "title";
        LC205 lc205 = new LC205();
        System.out.println(lc205.isIsomorphic(s, t));
    }
}

LeetCode150-单词规律-LC290

public class LC290 {
    public static boolean wordPattern(String pattern, String s) {
        String[] words = s.split(" ");
        Map<Character,String> map =new HashMap<>();
        Map<String,Character> map2 =new HashMap<>();
        for (int i = 0; i < pattern.length(); i++) {
            if(map.containsKey(pattern.charAt(i)) && !map.get(pattern.charAt(i)).equals(words[i])){
                return false;
            }
            if(map2.containsKey(words[i]) && !map2.get(words[i]).equals(pattern.charAt(i))){
                return false;
            }
            map.put(pattern.charAt(i),words[i]);
            map2.put(words[i],pattern.charAt(i));
        }
        return true;

    }

    public static void main(String[] args) {
        String pattern = "abba";
        String s = "dog cat cat dog";
        System.out.println(wordPattern(pattern, s));

    }
}

LeetCode150-有效的字母异位词-LC242

/**
 * @ProjectName: Mounts
 * @Description: 数组++ -- 即可
 * @Author: DSXRIIIII
 * @CreateDate: 2024/6/5 17:18
 * @Email: lihh53453@hundsun.com
 **/
public class LC242 {
    public boolean isAnagram(String s, String t) {
        if(s.length() != t.length()) return false;
        int[] c = new int[26];
        for (int i = 0; i < s.length(); i++) {
            c[s.charAt(i) - 'a']++;
            c[t.charAt(i) - 'a']--;
        }
        for (int i = 0; i < 26; i++) {
            if(c[i] != 0){
                return false;
            }
        }
        return true;
    }
}

LeetCode150-字母异位词分组-LC49

/**
 * 将str->char数组->打乱->String
 * 排序的String转换成key存储在map中 用来匹配 将匹配的结果放到list中
 * @ProjectName: Mounts
 * @Description: 字母异位词分组
 * @Author: DSXRIIIII
 * @CreateDate: 2024/6/5 17:28
 * @Email: lihh53453@hundsun.com
 **/
public class LC49 {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String,List<String>> map = new HashMap<>();
        for(String str:strs){
            char[] charArray = str.toCharArray();
            Arrays.sort(charArray);
            String key = new String(charArray);
            List<String> list = map.getOrDefault(key,new ArrayList<>());
            list.add(str);
            map.put(key,list);
        }
        return new ArrayList<List<String>>(map.values());
    }
}

LeetCode150-有效的数独-LC38

/**
 * @ProjectName: Mounts
 * @Description: 有效的数独
 * @Author: DSXRIIIII
 * @CreateDate: 2024/6/18 13:40
 * @Email: lihh53453@hundsun.com
 */
public class LC38 {
    public boolean isValidSudoku(char[][] board) {
        int[][] arr1 = new int[9][9];
        int[][] arr2 = new int[9][9];
        int[][][] arr3 = new int[3][3][9];
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                char c = board[i][j];
                if (c != '.') {
                    int index = c - '0' - 1;
                    arr1[i][index]++;//保存列的个数
                    arr2[j][index]++;//保存行的个数
                    arr3[i / 3][j / 3][index]++;//保存单个3*3模块的个数
                    if (arr1[i][index] > 1 || arr2[j][index]++ > 1 || arr3[i / 3][j / 3][index] > 1) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
}

LeetCode150- 螺旋矩阵-LC38

package cn.dsxriiiii.LeetCode.LC150;

import java.util.ArrayList;
import java.util.List;

/**
 * @ProjectName: Mounts
 * @Description: 螺旋矩阵
 * @Author: DSXRIIIII
 * @CreateDate: 2024/6/18 14:00
 * @Email: lihh53453@hundsun.com
 *  方法与螺旋矩阵II类似
 */
public class LC54 {
    public static void main(String[] args) {
        int[][] arr = {{2,5,8},{4,0,-1}};
        System.out.println(spiralOrder(arr));
    }
    public static List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<>();
        int up = 0;
        int down = matrix.length - 1;
        int left = 0;
        int right = matrix[0].length - 1;
        while(true){
            for(int i = left;i <= right;i++) res.add(matrix[up][i]);
            if(++up > down) break;
            for (int j = up; j <= down; j++) res.add(matrix[j][right]);
            if(--right < left) break;
            for (int m = right; m >= left ; m--) res.add(matrix[down][m]);
            if(--down < up) break;
            for (int n = down; n >= up; n--) res.add(matrix[n][left]);
            if(++left > right) break;
        }
        return res;
    }
}

LeetCode150- 旋转图像-LC48

package cn.dsxriiiii.LeetCode.LC150;

/**
 * @ProjectName: Mounts
 * @Description: 旋转图像
 * @Author: DSXRIIIII
 * @CreateDate: 2024/6/18 14:47
 * @Email: lihh53453@hundsun.com
 */
public class LC48 {
    public void rotate(int[][] matrix) {
        int len = matrix.length;
        int[][] new_matrix = new int[len][len];
        for (int i = 0; i < len; i++) {
            for (int j = 0; j < len; j++) {
                new_matrix[j][len - i - 1] = matrix[i][j];  //找到此处的数学规律即可
            }
        }
        for (int i = 0; i < len; i++) {
            System.arraycopy(new_matrix[i], 0, matrix[i], 0, len);
        }
    }
}

LeetCode150- 矩阵置零-LC73

package cn.dsxriiiii.LeetCode.LC150;

import java.util.ArrayList;
import java.util.List;

/**
 * @ProjectName: Mounts
 * @Description: 矩阵置零
 * @Author: DSXRIIIII
 * @CreateDate: 2024/6/18 14:53
 * @Email: lihh53453@hundsun.com
 */
public class LC73 {
    public void setZeroes(int[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;
        //boolean[][] arr = new boolean[len][len];
        boolean[] col = new boolean[n];
        boolean[] row = new boolean[m];
        //原本的想法是按照注释的那种 但是如果是对单行单列操作只需要一位数组就行了
        List<List<int[]>> list = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if(matrix[i][j] == 0){
                    col[j] = true;
                    row[i] = true;
                }
            }
        }
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if(col[j] || row[i]){
                    matrix[i][j] = 0;
                }
            }
        }

    }
}

LeetCode150- 字母异位词分组-LC49

package cn.dsxriiiii.LeetCode.LC150;

import java.util.*;

/**
 * @ProjectName: Mounts
 * @Description: 字母异位词分组
 * @Author: DSXRIIIII
 * @CreateDate: 2024/6/5 17:28
 * @Email: lihh53453@hundsun.com
 * 思路:哈希表
 *      1.将每个字符串排列之后得到的key是一样的
 *      2.依次放入map中的list
 *      3.最后return new ArrayList<List<String>>(map.values());将map转化为ArrayList
 **/
public class LC49 {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String,List<String>> map = new HashMap<>();
        for(String str:strs){
            char[] charArray = str.toCharArray();
            Arrays.sort(charArray);
            String key = new String(charArray);
            List<String> list = map.getOrDefault(key,new ArrayList<>());
            list.add(str);
            map.put(key,list);
        }
        return new ArrayList<List<String>>(map.values());
    }
}

LeetCode150- 字母异位词分组-LC49

package cn.dsxriiiii.LeetCode.LC150;

import java.util.HashMap;
import java.util.Map;

/**
 * @ProjectName: Mounts
 * @Description:
 * @Author: DSXRIIIII
 * @CreateDate: 2024/6/19 14:11
 * @Email: lihh53453@hundsun.com
 * 思路:哈希表
 *      1.把值和index绑定在hashmap中
 *      2.注意匹配 两数之和即 target - 其中一数
 */
public class LC1 {
    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[]{i,map.get(target - nums[i])};
            }
            map.put(nums[i],i);
        }
        return new int[0];
    }
}

LeetCode150- 两数之和-LC1

package cn.dsxriiiii.LeetCode.LC150;

import java.util.HashMap;
import java.util.Map;

/**
 * @ProjectName: Mounts
 * @Description: 两数之和
 * @Author: DSXRIIIII
 * @CreateDate: 2024/6/19 14:11
 * @Email: lihh53453@hundsun.com
 * 思路:哈希表
 *      1.把值和index绑定在hashmap中
 *      2.注意匹配 两数之和即 target - 其中一数
 */
public class LC1 {
    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[]{i,map.get(target - nums[i])};
            }
            map.put(nums[i],i);
        }
        return new int[0];
    }
}

LeetCode150- 快乐数-LC202

package cn.dsxriiiii.LeetCode.LC150;

import java.util.HashSet;
import java.util.Set;

/**
 * @ProjectName: Mounts
 * @Description: 快乐数  1**2 + 9**2 = 82
 *                      8**2 + 2**2 = 68
 *                      6**2 + 8**2 = 100
 *                      1**2 + 0**2 + 0**2 = 1
 * @Author: DSXRIIIII
 * @CreateDate: 2024/6/19 14:39
 * @Email: lihh53453@hundsun.com
 * 技巧:快乐树会形成一个循环
 *      例如:4 最终会回到4
 *      最大的数999999999 也会回到810  最后811次循环就会回到起点
 * 思路:1.字符串分解 ? -> 会死循环
 *      2.怎么跳出死循环 ?
 *      3.哈希Set 把每个数都放到set中 当set有重复值则会退出循环
 *      4.快慢指针 当快指针指向慢指针说明此时走了一个循环周期  要判断这个循环是不是1引起的
 */
public class LC202 {

    public static int GetNext(int n){
        int total = 0;
        while(n != 0){
            int num = n % 10;
            total += num * num;
            n = n / 10;
        }
        return total;
    }

    public boolean isHappyBySet(int n) {
        Set<Integer> set = new HashSet<>();
        while(n != 1 && !set.contains(n)){
            set.add(n);
            n = GetNext(n);
        }
        return n == 1;
    }

    public boolean isHappyByHash(int n) {
        int slow = n,fast = n;
        do{
            slow = GetNext(slow);
            fast = GetNext(fast);
            fast = GetNext(fast);
        }while(slow != fast);

        return slow == 1;
    }

    public static void main(String[] args) {
        //System.out.println(GetNext(12));
    }
}

LeetCode150- 存在重复元素 II-LC129

/**
 * @ProjectName: Mounts
 * @Description: 存在重复元素 II
 * @Author: DSXRIIIII
 * @CreateDate: 2024/8/2 21:05
 * @Email: lihh53453@hundsun.com
 * 哈希表和滑动数组解决
 * 1.哈希表可以保存数据坐标值和数组值相互对应上
 * 2.看到固定距离就要想到滑动窗口 而滑动窗口要想到set集合 或者队列
 */
public class LC219 {
    public boolean containsNearbyDuplicate_byMap(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            if(map.containsKey(nums[i]) && i - map.get(nums[i]) <= k){
                return true;
            }
            map.put(nums[i],i);
        }
        return false;
    }

    /**
     * 假设为4 位置i = 3  5 - 4 - 1 只有比窗口大的时候才会有减的空间 因为i-k限定了
     * 0 1 2 3 4
     * 1 2 3 4 -> 3
     *   2 3 4 5
     * @param nums 初始数组
     * @param k 滑动窗口大小
     * @return boolean
     */
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        int length = nums.length;
        Set<Integer> set = new HashSet<>();
        for (int i = 0; i < length; i++) {
            if(i > k){
                set.remove(nums[i - k - 1]);
            }
            if(!set.add(nums[i])){
                return true;
            }
        }
        return false;
    }
}

LeetCode150-最长连续序列-LC128

/**
 * @ProjectName: Mounts
 * @Description:LeetCode150-最长连续序列-LC128
 * @Author: DSXRIIIII
 * @CreateDate: 2024/8/2 21:28
 * @Email: lihh53453@hundsun.com
 * 可以将set想象成一个桶 不断++取得新的数字
 */
public class LC128 {
    public int longestConsecutive(int[] nums) {
        Set<Integer> set = new HashSet<>();
        //初始长度为0 因为要对空的数组判断
        int result = 0;
        for (int num : nums) {
            set.add(num);
        }
//        for (int num : nums) {
//            int locLen = 1;
//            int currentNum = num;
//            while (!set.contains(currentNum - 1)) {
//                currentNum += 1;
//                locLen += 1;
//            }
//            result = Math.max(locLen, result);
//        }
//        return result;
        for (int num : nums) {
            //上面的方法缺少对这个数是不是最底层的数的判断
            //因为题目要求连续那么只能是一直加1连续的数 那么-1判断的逻辑就不能少
            if(!set.contains(num - 1)){
                //有数字 保底就是1
                int locLen = 1;
                int currentNum = num;
                //不断往前走的逻辑 只要set有+1的数 就是连续并且满足条件的
                while (set.contains(currentNum + 1)) {
                    currentNum += 1;
                    locLen += 1;
                }
                result = Math.max(locLen, result);
            }
        }
        return result;
    }
}

区间

LeetCode150-汇总区间-LC228

/**
 * @ProjectName: Mounts
 * @Description: 汇总区间-LC228
 * @Author: DSXRIIIII
 * @CreateDate: 2024/8/2 21:48
 * @Email: lihh53453@hundsun.com
 * 思路:记录初始位置值 并且不断index++即可
 * 要注意while循环条件下
 * 1.确保循环条件
 * 2.确保不要死循环
 */
public class LC228 {
    public List<String> summaryRanges(int[] nums) {
        if(nums.length == 0) return new ArrayList<>();
        List<String> res = new ArrayList<>();
        int index = 0;
        while(index < nums.length){
            int start = index;
            index++;
//            while(nums[index - 1] + 1 == nums[index]){
//                index+=1;
//            }
            //这里要添加限定的范围否则index会一直增加
            while(index < nums.length && nums[index - 1] + 1 == nums[index]){
                index+=1;
            }
            int location = index - 1;
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(nums[start]);
            if(start<location){
                stringBuilder.append("->");
                stringBuilder.append(nums[location]);
            }
            res.add(stringBuilder.toString());
        }
        return res;
    }
}

LeetCode150-合并区间-LC56

/**
 * @ProjectName: Mounts
 * @Description: 合并区间-LC56
 * @Author: DSXRIIIII
 * @CreateDate: 2024/8/3 14:02
 * @Email: lihh53453@hundsun.com
 * 将新的加入结果集
 * 并且与容器内的数组进行比对
 */
public class LC56 {
    public int[][] merge(int[][] intervals) {
        if(intervals.length == 0) return new int[0][0];
        Arrays.sort(intervals, (o1, o2) -> o1[0] - o2[0]);
        List<int[]> list = new ArrayList<>();
        for(int[] arr:intervals){
            int left = arr[0],right = arr[1];
            if(list.isEmpty() || list.get(list.size() - 1)[1] < left){
                list.add(new int[]{left,right});
            }else{
                list.get(list.size() - 1)[1] = Math.max(right,list.get(list.size() - 1)[1]);
            }
        }
        return list.toArray(new int[list.size()][]);
    }

    public static void main(String[] args) {
        int [][] arr = {{1,2},{2,3}};
        List<int[]> arrayList = new ArrayList<>();
        arrayList.add(new int[]{1,2});
        arrayList.add(new int[]{2,3});
        /* 输出结果为
         * [[1, 2], [2, 3]]
         * [[I@3b07d329
         * [[1, 2], [2, 3]]
         */
        System.out.println(Arrays.deepToString(arr));
        System.out.println(arrayList.toArray(new int[arrayList.size()][]));
        System.out.println(Arrays.deepToString(arrayList.toArray(new int[arrayList.size()][])));
    }
}

LeetCode150-插入区间-LC57

/**
 * @ProjectName: Mounts
 * @Description: 插入区间-LC57
 * @Author: DSXRIIIII
 * @CreateDate: 2024/8/3 14:41
 * @Email: lihh53453@hundsun.com
 * 这里选择最简单的插入然后排序的方法
 * 在排序的过程中也可以选择二分法将nlog(n) -> log(n)
 */
public class LC57 {
    public int[][] insert(int[][] intervals, int[] newInterval) {
        int[][] arr = Arrays.copyOf(intervals, intervals.length + 1);
        arr[arr.length - 1] = new int[2];
        arr[arr.length - 1][0] = newInterval[0];
        arr[arr.length - 1][1] = newInterval[1];
        //Arrays.sort(arr,(num1,num2)->num1[0] - num2[0]);
        Arrays.sort(arr, Comparator.comparingInt(num -> num[0]));
        List<int[]> res = new ArrayList<>();
        for(int[] array:arr){
            int left = array[0],right = array[1];
            if(res.isEmpty() || res.get(res.size() - 1)[1] < left){
                res.add(new int[]{left,right});
            }else {
                res.get(res.size() - 1)[1] = Math.max(right,res.get(res.size() - 1)[1]);
            }
        }
        return res.toArray(new int[res.size()][]);
    }

    public static void main(String[] args) {
        int[][] arr1 = {{1,2},{2,3}};
        int[][] arr2 = Arrays.copyOf(arr1, arr1.length + 1);
        System.out.println(Arrays.deepToString(arr2));
    }
}

LeetCode150-用最少数量的箭引爆气球-LC452

/**
 * @ProjectName: Mounts
 * @Description: LC452-用最少数量的箭引爆气球
 * @Author: DSXRIIIII
 * @CreateDate: 2024/8/3 15:04
 * @Email: lihh53453@hundsun.com
 * 这一题也可以为合并区间的一种写法 采用交集
 */
public class LC452 {
    public int[][] findMinArrowShots(int[][] points) {
        Arrays.sort(points, Comparator.comparingInt(i -> i[1]));//并交集不同之处 确保不比对的值为最小
        List<int[]> res = new ArrayList<>();
        for(int[] arr: points){
            int left = arr[0],right = arr[1];
            if(res.isEmpty() || res.get(res.size() - 1)[1] < left){
                res.add(new int[]{left,right});
            }else {
                res.get(res.size() - 1)[0] = Math.min(res.get(res.size() - 1)[0],left);//并交集不同之处
            }
        }
        return res.toArray(new int[res.size()][]);
    }

    public static void main(String[] args) {
        int[][] arr = {{3,9},{7,12},{3,8},{6,8},{9,10},{2,9},{0,9},{3,9},{0,6},{2,8}};
        Arrays.sort(arr, Comparator.comparingInt(i -> i[1]));
        System.out.println(Arrays.deepToString(arr));
        LC452 lc452 = new LC452();
        System.out.println(Arrays.deepToString(lc452.findMinArrowShots(arr)));
    }
}

总结

做区间题时需要考虑并交集的选择

  1. 首先为了方便插入数据,需要创建一个List数组
  2. 在根据不同并交集的选择 对一号位或者二号位排序
  3. 当数组列表为空或者右边界比新值小就添加到结果列表
  4. 否则更新左边界(交集,边界值取最小)/右边界(并集,边界值取最大)

    1.将列表转换成int[][]方法res.toArray(new int[res.size()][])
    2.排序方法Arrays.sort(points, Comparator.comparingInt(i -> i[1]));
    或者Arrays.sort(intervals, (o1, o2) -> o1[0] – o2[0])
    推荐使用Comparator

博客内容均系原创,未经允许严禁转载!
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇