leetcode刷题总结

双指针解法的应用:

1.最小覆盖字串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

思考:通过left right两个指针表明当前已遍历的字符区间,首先通过right指针找到符合条件的子串,然后通过left压缩区间,从而找到最小区间,当left收缩区间使得区间不符合条件时,right会继续往前寻找符合条件的区间,直到right遍历完成。

使用maps来记录当前遍历的区间

使用mapt来记录符合条件的区间

通过比较maps和mapt来判断是否完成区间覆盖。

使用maps保存遍历区间

class Solution {
    public String minWindow(String s, String t) {
        int left = 0, right = 0, min = Integer.MAX_VALUE, start = 0, valid = 0;
        Map<Character, Integer> maps = new HashMap<>();
        Map<Character, Integer> mapt = new HashMap<>();
        for (int i = 0; i < t.length(); i++) {
            mapt.put(t.charAt(i), mapt.getOrDefault(t.charAt(i), 0) + 1);
        }

        while (right < s.length()) {
            Character c = s.charAt(right);
            right++;
            maps.put(c, maps.getOrDefault(c, 0) + 1);
            if (mapt.containsKey(c)) {
                if (maps.get(c).equals(mapt.get(c))) {
                    valid++;
                }
            }
            while (valid == mapt.size()) {
                if (right - left < min) {
                    min = right - left;
                    start = left;
                }
                Character c1 = s.charAt(left);
                left++;
                if (mapt.containsKey(c1)) {
                    if (maps.get(c1).equals(mapt.get(c1))) {
                        valid--;
                    }
                    maps.put(c1, maps.get(c1) - 1);
                }
            }
        }
        return min == Integer.MAX_VALUE ? "" : s.substring(start, start + min);
    }
}

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

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

思考:通过left和当前遍历的字符表明目前所包含的区间,将区间对应的下标通过map记录,每遍历一个新的字符,判断字符是否存在map中,若存在获取对应的下标,如果对应的下标超过left则更新left的值,并更新当前的最长子串。

若不存在map中, 更新当前最长子串的长度。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int left = 0, max = 0;
        Map<Character, Integer> map = new HashMap<Character, Integer>();
        for (int i = 0; i < s.length(); i++) {
            int l = map.getOrDefault(s.charAt(i), -1);
            left = Math.max(left, l);
            max = Math.max(max, i - left);
            map.put(s.charAt(i), i);
        }
        return max;
    }
}

3.至多包含两个不同字符的最长字串

 思考:

// Java实现
class Solution {
        public int lengthOfLongestSubstringTwoDistinct(String s) {
        int strLength = s.length();
        if (strLength < 3) return strLength;
        int left = 0;
        int right = 0;
        Map<Character, Integer> map = new HashMap<>();

        int maxLen = 2;

        while (right < strLength) {
            map.put(s.charAt(right), right);
            right++;
            if (map.size() == 3) {
                int delIdx = Collections.min(map.values());
                map.remove(s.charAt(delIdx));
                left = delIdx + 1;
            }
            maxLen = Math.max(maxLen, right - left);
        }
        return maxLen;
    }
}

4.长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 

思考:

通过定义start end两个指针表明当前遍历区间,首先通过增大end来找到符合要求的区间,由于数据都是正整数,可以通过增加start来减少区间找到符合要求的最小区间。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        if (nums.length == 0) {
            return 0;
        }
        int start = 0, end = 0, min = Integer.MAX_VALUE;
        int sum = 0;
        while (end < nums.length) {
            sum += nums[end++];
            if (sum >= target) {
                while (sum >= target) {
                    sum -= nums[start];
                    start++;
                }
                min = Math.min(min, end - start + 1);
                
            }
        }
        return min == Integer.MAX_VALUE ? 0 :min;
    }
}

最长公共子串

s1 ="testhello",s2="eehello" 求s1和s2的最长子串

//思路,创建dp数组,dp[i][j]表示s1的前i个字符,和s2的前j个字符

    public int test(String test1, String test2) {
        int max = 0;
        int m = test1.length();
        int n = test2.length();
        int[][] dp = new int[test1.length() + 1][test2.length() + 1];
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (test1.charAt(i - 1) == test2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                    max = Math.max(max, dp[i][j]);
                }
            }
        }

        return max;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用\[1\]和引用\[2\]的内容,推荐的LeetCode刷题顺序是按照题目类型刷题,优先选择树、链表、二分查找、DFS、BFS、动态规划等常见类型的题目。可以先做2~4道简单题,然后再做中等难度的题目。在选择题目时,可以优先选择题目序号小、点赞多、提交成功率高的题目,这样可以从简单入手,节省时间。同时,LeetCode每道题目都有“模拟面试”功能,可以给自己设定时间限制,如果做不出来可以看答案,然后记住思路后再自己尝试一遍。每种类型的题目做完10+道后,可以总结规律。 根据引用\[3\]的内容,题目可以按照不同的分类进行刷题,比如数组与贪心算法、子数组与贪心算法、子序列与贪心算法、数字与贪心、单调栈法、双指针法等。可以根据自己的兴趣和需求选择相应的题目进行刷题。 综上所述,LeetCode刷题顺序可以按照题目类型或者题目分类进行选择。 #### 引用[.reference_title] - *1* [LeetCode 刷题顺序,按标签分类,科学刷题!](https://blog.csdn.net/fengyuyeguirenenen/article/details/125099023)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [leetcode 刷题指南 & 刷题顺序](https://blog.csdn.net/qijingpei/article/details/125561071)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [leetcode-刷题顺序推荐](https://blog.csdn.net/weixin_38087674/article/details/114107841)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值