• 【贪心算法-LeetCode3:无重复字符的最长子串(Java实现)】


    个人社区:https://bbs.csdn.net/forums/smile
    个人主页:https://blog.csdn.net/qq_43665602
    欢迎各位志同道合的朋友,一起学习!

    一、题目描述

    1.题目内容

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

    2.样例

    在这里插入图片描述

    二、解决方案

    看见这种求最优解的问题,可以尝试使用贪心算法,尤其对于集合覆盖问题、区间问题以及分配问题。

    贪心算法:求局部最优(当前最优),以使最终结果为最优解或者近似最优解。

    本题目的是求出给定字符串S中不含重复字符的最长子串,很自然地可以想到,我们可以通过逐步求解当前无重复最长子串,最后得到字符串S中不含重复字符的最长子串。
    需要注意子串必须是连续的,要与子序列区分。

    1.算法流程

    1)分析

    以样例1和样例2为例,我通过图解分析一下求解无重复字符最长子串的过程:
    样例1,S=“abcabcbb”,从字符串开头开始分别以当前字符为起点,确定此时的无重复字符的最长子串:
    (1)i=0:起点为a,最长子串为abc,长度为3;
    (2)i=1:起点为b,最长子串为bca,长度为3;
    (3)i=2:起点为c,最长子串为cab,长度为3;
    (4)i=3:起点为a,最长子串为abc,长度为3;
    (5)i=4:起点为b,最长子串为bc,长度为2;
    (6)i=5:起点为c,最长子串为cb,长度为2;
    (7)i=6:起点为b,最长子串为b,长度为1;
    (8)i=7:起点为b,最长子串为b,长度为1;
    可看到第一次确定的子串长度为3,此后子串长度均小于等于3,所以最长子串为abc,其长度为3。
    在这里插入图片描述
    样例2,S=“pwwkew”,从字符串开头开始分别以当前字符为起点,确定此时的无重复字符的最长子串:
    (1)i=0:起点为p,最长子串为pw,长度为2;
    (2)i=1:起点为w,最长子串为w,长度为1;
    (3)i=2:起点为w,最长子串为wke,长度为3;
    (4)i=3:起点为k,最长子串为kew,长度为3;
    (5)i=4:起点为e,最长子串为ew,长度为2;
    (6)i=5:起点为w,最长子串为w,长度为1;
    在这里插入图片描述

    可看到第三次确定的子串长度为3,此后子串长度均小于等于3,所以最长子串为wke,其长度为3。
    从上面的图示中可以清晰看到最长子串的确定过程,由此可归纳出我们的算法流程,便于代码编写。

    2)算法流程

    选择策略:确定当前最长无重复子串,遇到重复字符即说明可确定当前最长无重复子串.

    • (1)依次遍历字符串,使用集合存储每个元素(这里使用HashSet);
    • (2)如果集合中存在当前指向的字符,说明有重复:比较此时maxLen与set.size的大小决定是否更新maxLen;
    • (3)循环(1-2),如果遇到更长子串,则更新maxLen; 如果剩余子串长度小于等于maxLen则停止遍历;

    需要注意特殊情况:如果字符串为空串或者其长度为1,说明其最长无重复子串为其本身。

    2.Java代码

    1)核心代码

    class Solution {
        /**
         * 选择策略:当前最长无重复子串,遇到重复字符就重置
         */
        public int lengthOfLongestSubstring(String s) {
            if (s.length()<=1){  // 如果字符串为空串或者其长度为1,说明其最长无重复子串为其本身
                return s.length();
            }
            int n=s.length();
            Set<Character> withoutRepeat=new HashSet<>();  // 存储当前子串
            int i=0,maxLen=0;
            while (i<n){  // 依次遍历每个字符
                withoutRepeat.clear();  // 存储新的子串需要重置Set
                int j=i; 
                while (j<n){ // 寻找当前字符开始的最长子串
                    if(withoutRepeat.contains(s.charAt(j))){  // 遇到重复字符就停止寻找
                        break;
                    }
                    withoutRepeat.add(s.charAt(j));
                    j++;
                }
                if((j-i+1)>maxLen){  // 确定是否更新maxLen,j-i+1为当前子串长度
                    maxLen=j-i;
                }
                if (maxLen>=(n-i+1)){ // 如果剩余子串长度小于等于maxLen则停止遍历
                    break;
                }
                i++;
            }
            return maxLen;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    2)完整测试代码

    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * LeetCode3:无重复字符的最长子串
     */
    public class WithoutRepeat {
        public static void main(String[] args) {
            String s = "abcabcbb";
    //        String s = "bbbbbb";
    //        String s = "pwwkew";
    //        String s = "au";
            System.out.println(new RepeatSolution().lengthOfLongestSubstring(s));
        }
    }
    
    class RepeatSolution {
        /**
         * 选择策略:当前最长无重复子串,遇到重复字符就重置
         * @param s
         * @return
         */
        public int lengthOfLongestSubstring(String s) {
            if (s.length()<=1){
                return s.length();
            }
            int n=s.length();
            Set<Character> withoutRepeat=new HashSet<>();
            int i=0,maxLen=0;
            while (i<n){  // 依次遍历每个字符
                withoutRepeat.clear();
                int j=i;  // 寻找当前字符开始的最长子串
                while (j<n){
                    if(withoutRepeat.contains(s.charAt(j))){
                        break;
                    }
                    withoutRepeat.add(s.charAt(j));
                    j++;
                }
                if((j-i+1)>maxLen){
                    maxLen=j-i;
                }
                if (maxLen>=(n-i+1)){
                    break;
                }
                i++;
            }
            return maxLen;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
  • 相关阅读:
    【无标题】斜率优化dp
    mysql如何复制一张表的数据到新的表
    Unity Spine 指定导入新Spine动画的默认材质
    深入linux内核架构--slab分配器(建议收藏)
    PG::Covfefe
    Windows 启动 Idea 报错 if you already hava a 64-bit JDK ... 以及 failed to create jvm
    如何将当前文件夹里的所有python文件打包到镜像里面
    网络虚拟化之Docker的网络模式
    【Qt炫酷动画】demo04-仿Android旋转图标的等待对话框动画
    js方法:函数作为对象的属性
  • 原文地址:https://blog.csdn.net/qq_43665602/article/details/127586991