草庐IT

【JS】5. 最长回文子串(待更新中)

PaturNax 2023-03-28 原文

5. 最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd"
输出:"bb"

提示:

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母组成

解法一:暴力

用双重循环遍历字符串的所有起始位置与终止位置,然后判断是否是回文子串,是就更新最长长度和回文的起始位置,方便之后分隔字符串成子串。

var longestPalindrome = function(s) {
    //处理特殊情况,长度小于2的就直接返回
    let len=s.length;
    if(len<2){
        return s;
    }
    
    //初始化最长的回文长度、回文起始下标
    let maxLen=1,begin=0;
    // console.log(s.substri/\ng(begin,begin+maxLen));
    //暴力遍历所有情况
    for(let i=0;i<len-1;i++){
        for(let j=i+1;j<len;j++){
            //如果长度比之前的长,并且判断出是回文
            if(j-i+1 > maxLen && validP(s,i,j)){
                //更新长度、起始下标
                maxLen=j-i+1;
                begin=i;
            }
        }
        
    }
    return s.substring(begin,begin+maxLen);
};

//创建一个判断回文的函数,左右指针往中心靠拢
function validP(s,left,right){
    while(left<=right){
        if(s[left] != s[right]){
            return false;
        }
        left++;
        right--;
    }
    return true;
}

复杂度分析

  • 时间复杂度:\(O(n^3)\)
  • 空间复杂度:\(O(1)\)

解法二:中心扩散

令一个指针在每遍历一个字符串的下标时,创建一个中心扩散函数进行判断,当左右扩散指针不越界的情况,获取中心点为奇数或偶数(因为中心点可能为1或2个)长度,接着再选择出最长的长度,当指针遍历完后,说明所有的扩散类型都比较完了。

var longestPalindrome = function(s) {
    //处理特殊情况
    let len=s.length;
    if(len<2){
        return s;
    }
    //初始化最长长度和起始位置
    let maxLen=1,begin=0;
    //跟暴力不同,在走向字符串末尾时,一次一次地扩散尝试
    for(let i=0;i< len - 1;i++){
        //考虑奇数与偶数的情况,所以有两种扩散
        let oddLen=expandAroundCenter(s,i,i);
        let evenLen=expandAroundCenter(s,i,i+1);

        //看看奇数还是偶数的情况大,再比较之前的最长长度
        let curMaxLen=Math.max(oddLen,evenLen);
        if(curMaxLen > maxLen){
            maxLen=curMaxLen;
            //根据公式 i-(回文长度-1)/2 知道起始位置,不过这里注意是要向上取整
            begin=Math.ceil(i-(maxLen-1)/2);
        }
    }
    return s.substring(begin,begin+maxLen);
};

//中心扩散
function expandAroundCenter(s,left,right){
    while(left>=0 && right<s.length && s[left]===s[right]){
        //符合情况的就扩散
        left--,right++;
    }
    //由于先判断再循环的while,存在扩散超出回文长度的边界的情况,刚好变得不再是回文情况,所以是(right-left+1-2),而不是right-left+1
    console.log(right,left)
    return right-left-1;
}

复杂度分析

  • 时间复杂度:\(O(n^2)\)
  • 空间复杂度:\(O(1)\)

解法三:动态规划

可以知道如果判断字符串是回文子串,那么抛开前后两端,就由中间决定了以下图举例:

我要保证j>i,即右指针要大于左指针,而下面红线指示的例子就是表示抛开前后两端看中间又怎么样,以此循环。

var longestPalindrome = function(s) {
    let len=s.length;
    if(len<2){
        return s;
    }

    let maxLen=1,begin=0;

    //初始化二维dp,要注意深拷贝和浅拷贝的问题
    let dp=Array.from(new Array(len),()=> new Array(len).fill(false));

    //对角线,即长度为1的子串都是回文串
    for(var i=0;i<len;i++){
        dp[i][i]=true;
    }
    //从列开始数,不用从0开始,因为第0列本身没比较的价值
    for(var j=1;j<len;j++){
        //只用看右上角的比对情况,所以是i<j,i代表从左端往中间的值,j代表从右端往中间的值
        for(var i=0;i<j;i++){
            //如果左右两端不匹配就说明不符合
            if(s[i]!=s[j]){
                dp[i][j]=false;
            //如果两端匹配了
            }else{
                //此时的子串太短或者是没有的情况,也就没必要比下去了
                if(j-i<3){
                    dp[i][j]=true;
                //如果还太长,就继续比下去,左右两端指针继续往中间移动
                }else{
                    dp[i][j]=dp[i+1][j-1];
                }
            }
            //最后就不断更新获取最长的长度
            if(dp[i][j] && j-i+1>maxLen){
                maxLen=j-i+1;
                begin=i;
            }
        }
    }
    return s.substring(begin,begin+maxLen);
};

复杂度分析

  • 时间复杂度:\(O(n^2)\),其中 \(n\) 是字符串的长度。动态规划的状态总数为 \(O(n^2)\),对于每个状态,我们需要转移的时间为 \(O(1)\)
  • 空间复杂度:\(O(n^2)\),即存储动态规划状态需要的空间。

解法四:Manacher算法(马拉车算法)

太难了,后面解决。

有关【JS】5. 最长回文子串(待更新中)的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  3. objective-c - 在设置 Cocoa Pods 和安装 Ruby 更新时出错 - 2

    我正在尝试为我的iOS应用程序设置cocoapods但是当我执行命令时:sudogemupdate--system我收到错误消息:当前已安装最新版本。中止。当我进入cocoapods的下一步时:sudogeminstallcocoapods我在MacOS10.8.5上遇到错误:ERROR:Errorinstallingcocoapods:cocoapods-trunkrequiresRubyversion>=2.0.0.我在MacOS10.9.4上尝试了同样的操作,但出现错误:ERROR:Couldnotfindavalidgem'cocoapods'(>=0),hereiswhy:U

  4. ruby-on-rails - Rails Associations 的更新方法是什么? - 2

    这太简单了,太荒谬了,我在任何地方都找不到关于它的任何信息,包括API文档和Rails源代码:我有一个:belongs_to关联,我开始理解当您没有关联时您在Controller中调用的正常模型方法与您有关联时调用的方法略有不同。例如,我的关联在创建Controller操作时运行良好:@user=current_user@building=Building.new(params[:building])respond_todo|format|if@user.buildings.create(params[:building])#etcetera但我找不到关于更新如何工作的文档:@user

  5. ruby-on-rails - OSX Yosemite 更新破坏了 pow.cx - 2

    升级到OSXYosemite后,我现有的pow.cx安装不起作用。升级到最新的pow.cx无效。通过事件监视器重新启动它也没有成功。 最佳答案 卸载(!)并重新安装解决了这个问题。curlget.pow.cx/uninstall.sh|shcurlget.pow.cx|sh 关于ruby-on-rails-OSXYosemite更新破坏了pow.cx,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/q

  6. ruby - 将 Gitlab 从 9.3.7 更新到 9.3.8 安装 re2 时出错 - 2

    我们在Ubuntu14.04和Gitlab9.3.7上运行,运行良好。我们正在尝试更新到Gitlabv9.3.8的最新安全补丁,但它给我们这个错误:Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension.currentdirectory:/home/git/gitlab/vendor/bundle/ruby/2.3.0/gems/re2-1.0.0/ext/re2/usr/local/bin/ruby-r./siteconf20170720-19622-15i0edf.rbextconf.rbcheckingformain(

  7. ruby-on-rails - Rails 更新属性 - 2

    我遇到了以下问题。我有一个名为user的模型,它有一个名为activated的列。我试图通过激活的方法更新该值?但它给我错误:验证失败:密码不能为空,密码太短(最少6个字符)这对我来说没有意义,因为我没有接触密码字段!我只想更新激活的列。我把我认为相关的代码放在这里,但如果你认为你需要更多,请问:)非常感谢您!型号:attr_accessor:passwordattr_accessible:name,:email,:password,:password_confirmation,:activatedhas_many:sucu_votesemail_regex=/\A[\w+\-.]+@

  8. ruby-on-rails - 如果存在则更新,否则什么也不做? - 2

    当且仅当模型存在时,我才尝试更新模型的值。如果没有,我什么都不做。搜索似乎只返回更新或创建问题/答案,但我不想创建。我知道我可以用一个简单的方法来做到这一点:found=Model.find_by_id(id)iffoundupdatestuffend但是,我觉得有一种方法可以在一次调用中完成此操作,而无需分配任何临时本地值或执行if。如果记录不存在,我该如何编写一个Rails调用来更新记录而不出现嘈杂错误?最新的Rails3.x 最佳答案 您可以使用try在对find_by_id或where的结果调用update_attribut

  9. ruby-on-rails - 如何在记录更新期间从验证中排除密码字段? ( rails 3.0.4, ruby 1.9.2) - 2

    我有一个允许更新用户记录的表单。它包含:password和:password_confirmation字段,但我不希望在数据库中已存储加密密码时对它们运行验证。View文件中的字段:'ConfirmPassword'%>在互联网上搜索时,我发现了这段代码,我认为它是针对以前版本的Ruby/Rails的。(我会把它放在我的用户模型中。)validates_presence_of:password,:on=>create由于我的用户模型中密码验证的语法不同(如下),我对我需要的语法感到困惑。validates:password,:presence=>true,:confirmation=>

  10. ruby-on-rails - Assets 管道损坏 : Not compiling on the fly css and js files - 2

    我开始了一个新的Rails3.2.5项目,Assets管道不再工作了。CSS和Javascript文件不再编译。这是尝试生成Assets时日志的输出:StartedGET"/assets/application.css?body=1"for127.0.0.1at2012-06-1623:59:11-0700Servedasset/application.css-200OK(0ms)[2012-06-1623:59:11]ERRORNoMethodError:undefinedmethod`each'fornil:NilClass/Users/greg/.rbenv/versions/1

随机推荐