【算法训练-字符串 一】【子串问题】最长无重复子串、最长回文子串、最长公共前缀

简介: 【算法训练-字符串 一】【子串问题】最长无重复子串、最长回文子串、最长公共前缀

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是最长无重复子串或最长无重复子数组,这类题目出现频率还是很高的。

最长无重复子串【MID】

先来看字符串数据结构的题目

题干

解题思路

整体目标就是获取最大的无重复滑动窗口

  1. 双指针标识数组或字符串的位置,右指针可以理解为放大窗口指针,左指针可以理解为缩小窗口指针
  2. 定义一个set用来存储元素位置对应的值
  3. 右指针先行,如果一直无重复就一直开拓窗口并更新max值,否则移动左指针缩小窗口,直到将重复值缩到窗口以外。

如下图所示:

代码实现

基本数据结构字符串

辅助数据结构哈希表

算法迭代

技巧双指针、滑动窗口

class Solution {
    public int lengthOfLongestSubstring(String s) {
       // 1 判断入参是否为空列表
        if (s.length() == 0) {
            return 0;
        }
        // 2 定义返回结果最大值和左右指针以及滑动窗口集合
        int max = 0;
        int left = 0;
        int right = 0;
        Set<Character> set = new HashSet<>();
        // 3 滑动窗口移动并在无重复时计算最大值
        while (left < s.length() && right < s.length()) {
            // 1 无重复,右指针继续移动,重新计算最大值
            if (!set.contains(s.charAt(right))) {
                set.add(s.charAt(right++));
                max = Math.max(max, right - left);
            } else {
                // 2 有重复,左指针继续移动,直到将重复元素移出集合
                set.remove(s.charAt(left++));
            }
        }
        return max;
    }
}

复杂度分析

时间复杂度为O(N),因为遍历了字符串;空间复杂度为O(N),借助了HashSet的存储空间

最长回文子串【MID】

一道中心扩展思想解决的MID题目

题干

解题思路

  1. 每个字符都可以尝试作为中心点看,会出现两种情况:可能是类似 aba 的字符串,也可能是类似 abba 的情况
  2. 只需要分别计算出以一个和两个字符作为中心点的子串,取出较大的长度即可
  3. 从left到right开始向两边扩散、比较,如果相等则继续扩散比较;如果不相等则剪枝,不用再继续扩散比较
  4. 计算每次比较的回文子串长度,取最大

代码实现

给出代码实现基本档案

基本数据结构字符串

辅助数据结构

算法迭代

技巧双指针、中心扩散法

import java.util.*;
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param s string字符串
     * @return int整型
     */
    public String longestPalindrome(String s) {
        // 1 边界条件判断
        if (s.length() < 2) {
            return s;
        }
        // 2 初始化参数,结果参数的第一位存储起始位置,第二位存储长度
        int maxLength = 0;
        int[] result = new int[2];
        // 3
        for (int i = 0; i < s.length(); i++) {
            // 中心位置奇数情况下扩展结果
            int[] odd = centerSpread(s, i, i);
            // 中心位置偶数情况下扩展结果
            int[] even = centerSpread(s, i, i + 1);
            // 当前中心位置最大子串
            int[] curMax = odd[1] > even[1] ? odd : even;
            // 当前中心位置最大子串如果大于历史记录最大子串则暂存最大值及预期返回结果
            if (curMax[1] > maxLength) {
                maxLength = curMax[1];
                result = curMax;
            }
        }
        // 截取返回结果,本来如果起点是1,长度是2,那么结尾下标应该2(1+2-1),这里结尾为1+2=3,是因为3不会被计入,因为substring左闭右开区间,所以计算为(1+2-1+1(为开区间+1)=1+2=3)
        return s.substring(result[0], result[0] + result[1]);
    }
    // 扩散的核心方法
    public int[] centerSpread(String s, int left, int right) {
        // 双指针在边界内,且满足扩散条件
        while (left >= 0 && right <= s.length() - 1  &&
                s.charAt(left) == s.charAt(right)) {
            left--;
            right++;
        }
        // 回文子串为左右指针开区间内的部分:right-1-(left+1)+1=right-left-1
        return new int[] {left + 1, right - left - 1};
    }
}

复杂度分析

时间复杂度 O(N^2):平均需要遍历每个结点作为中心点O(N),还需要从中心点向左右扩散比较O(N)

空间复杂度 O(1):只用到常量

最长公共前缀【EASY】

来道EASY题散散心

题干

解题思路

当字符串数组长度为 0 时则公共前缀为空,直接返回;令最长公共前缀 ans 的值为第一个字符串,进行初始化;

遍历后面的字符串,依次将其与 ans 进行比较,两两找出公共前缀,最终结果即为最长公共前缀;如果查找过程中出现了 ans 为空的情况,则公共前缀不存在直接返回;

代码实现

基本数据结构字符串

辅助数据结构

算法迭代

技巧指针

import java.util.*;
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param strs string字符串一维数组
     * @return string字符串
     */
    public String longestCommonPrefix (String[] strs) {
        // 1 入参判断,如果数组列表为空,则返回空
        if (strs.length <= 0) {
            return "";
        }
        // 2 初始化第一个字符串为最长公共前缀
        String commonPrefix = strs[0];
        for (int i = 1; i < strs.length; i++) {
            // 两两比较字符串,更新最长公共前缀
            commonPrefix = twoStrLongestCommonPrefix(commonPrefix, strs[i]);
            // 如果最长公共前缀为"",则停止比较,返回""
            if(commonPrefix==""){
                return "";
            }
        }
        return commonPrefix;
    }
    // 比较两个字符串的最长公共前缀
    private String twoStrLongestCommonPrefix(String str1, String str2) {
        // 1 定义下标及下标最大移动范围
        int index = 0;
        int maxLength = Math.min(str1.length(), str2.length());
        // 2 下标移动两两比较字符串对应字符,只要在索引范围内且字符相同就继续移动
        while (index < maxLength && str1.charAt(index) == str2.charAt(index)) {
            index++;
        }
        // 3 返回两个子串的最长公共前缀
        return str1.substring(0, index);
    }
}

复杂度分析

时间复杂度:O(mn),其中 m是字符串数组中的字符串的平均长度,n 是字符串的数量。最坏情况下,字符串数组中的每个字符串的每个字符都会被比较一次。

空间复杂度:O(1)。使用的额外空间复杂度为常数

相关文章
|
4月前
|
算法
【算法】滑动窗口——最小覆盖子串
【算法】滑动窗口——最小覆盖子串
|
4月前
|
算法
【算法】滑动窗口——找到字符串中所有字母异位词
【算法】滑动窗口——找到字符串中所有字母异位词
|
2月前
|
存储 机器学习/深度学习 算法
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
蓝桥杯Python编程练习题的集合,涵盖了从基础到提高的多个算法题目及其解答。
127 3
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
|
1月前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
2月前
|
算法
两个字符串匹配出最长公共子序列算法
本文介绍了最长公共子序列(LCS)问题的算法实现,通过动态规划方法求解两个字符串的最长公共子序列,并提供了具体的编程实现细节和示例。
103 1
两个字符串匹配出最长公共子序列算法
|
2月前
|
机器学习/深度学习 算法 决策智能
【机器学习】揭秘深度学习优化算法:加速训练与提升性能
【机器学习】揭秘深度学习优化算法:加速训练与提升性能
|
2月前
|
算法
数据结构与算法二:栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式
这篇文章讲解了栈的基本概念及其应用,并详细介绍了中缀表达式转换为后缀表达式的算法和实现步骤。
68 3
|
2月前
|
存储 算法 Java
数据结构与算法学习八:前缀(波兰)表达式、中缀表达式、后缀(逆波兰)表达式的学习,中缀转后缀的两个方法,逆波兰计算器的实现
前缀(波兰)表达式、中缀表达式和后缀(逆波兰)表达式的基本概念、计算机求值方法,以及如何将中缀表达式转换为后缀表达式,并提供了相应的Java代码实现和测试结果。
135 0
数据结构与算法学习八:前缀(波兰)表达式、中缀表达式、后缀(逆波兰)表达式的学习,中缀转后缀的两个方法,逆波兰计算器的实现
|
2月前
|
算法 Java C++
【贪心算法】算法训练 ALGO-1003 礼物(C/C++)
【贪心算法】算法训练 ALGO-1003 礼物(C/C++)
【贪心算法】算法训练 ALGO-1003 礼物(C/C++)
|
2月前
|
算法 C++
蓝桥 算法训练 共线(C++)
蓝桥 算法训练 共线(C++)