【区间dp-回文子序列-8-2】添加最少的字符让字符串变为回文字符串

描述

给定一个字符串str,如果可以在str的任意位置添加字符,请返回在添加字符最少的情况下,让str整体都是回文字符串的一种结果。

输入描述:

输入包含一行字符串,代表str(1≤lengthstr≤5000)(1≤lengthstr​≤5000)

输出描述:

输出一行,代表返回的字符串。

示例1

输入:

ABA

输出:

ABA

示例2

输入:

AB

输出:

ABA

备注:

时间复杂度O(n2)O(n2),空间复杂度O(n2)O(n2)

与上一题:【区间dp-回文子序列-8】leet 1312. 让字符串成为回文串的最少插入次数 不同之处在于本题要求给出字符串,上一题只需要给出次数。

思考:结果字符串的最大长度=字符串长度n+ 最少插入字符次数m,所以ans=new char[n+m].

指针l和r分别指向s第一个和最后1个位置。i 和j 分别指向ans的第一个0和最后1个位置n+m-1。从两边构建ans.

如果s[l] == s[r] 则:ans[i]和ans[j]分别取这两个字符,l,r,i,j都分别前进一步,对应l++,r--,i++,j--.

如果s[l] != s[r],则ans的i,j指向的位置仍然要设置字符,只是取 l或r 一边的值:即 i++,j--,但是 i和j只能走一个

按照上面题目【区间dp-回文子序列-8】leet 1312. 让字符串成为回文串的最少插入次数 题解二 dp[l+1][r]和dp[l][r-1],可以知道此时取了最小的一边+1。

所以当dp[l+1][r]>dp[l][r-1]的时候取 s[l,r-1]的dp值 ==> 本次ans设置完了以后,后续得从字符串s[l,r-1]的字符中选择来设置ans。所以本次要用s[r]来设置ans两边位置的值。 ans右边取原值s[r], 左边补充对称的值s[r].

否则取[l+1,r], ==> ans设置完了以后 l++,ans两边要设置 l 对应位置的值

所以有以下代码:

     public static String minInsertions(String str) {
        char[] s = str.toCharArray();
        int n = s.length;
        int[][] dp = new int[n][n];
        for (int r = 0; r < n; r++) {
            for (int l = r; l >= 0; l--) {
                if (l == r) dp[l][r] = 0;
                else {
                    if (s[l] == s[r]) dp[l][r] = dp[l + 1][r - 1] ;
                    else dp[l][r] = Math.min(dp[l + 1][r], dp[l][r - 1]) + 1;
                }
            }
        }

        int m = dp[0][n - 1];

        char[] ans = new char[n + m];
        int l = 0, r = n - 1;
        int i = 0, j = ans.length - 1;

        while (i <= j) {
            if (s[l] == s[r]) { //后续从s[l+1,r-1]字符串中的字符选择了设置 ans两边的i和j 
                ans[i] = s[l];
                ans[j] = s[r];
                l++;
                r--;
            } else {
                if (dp[l + 1][r] > dp[l][r - 1]) { //取了dp[l][r - 1]值
//后续从s[l,r-1]字符串中的字符选择了设置 ans两边字符,所以本次用s[r]处的字符设置ans两端
                    ans[i] = s[r]; 
                    ans[j] = s[r];
                    r--;
                } else { //取了dp[l+1][r]值
//后续从s[l+1,r]字符串中的字符选择了设置 ans两边字符,所以本次用s[l]处的字符设置ans两端
                    ans[i] = s[l]; 
                    ans[j] = s[l];
                    l++;
                }
            }
            i++;
            j--;
        }
        return new String(ans);
    }

类似题目:

【区间dp-回文子序列-7】leet 516. 最长回文子序列

【区间dp-回文子序列-8-1】leet 1312. 让字符串成为回文串的最少插入次数

【区间dp-回文子序列-8-3】添加最少的字符让字符串变为回文字符串

【区间dp-回文子序列-8-4】SH10 回文数组

算法笔试-动态规划系列 文章被收录于专栏

动态规划相关算法笔试题

全部评论

相关推荐

繁华的街道两旁,湿漉漉的下午,两个青涩的脸庞互相张望。宽大卫衣下娇小的她,向我奔来。不约而同的卫衣,斯文的半框眼镜掩饰着一个穷臭屌丝气息。这是我和我牛爱网第一死忠粉兼专属女嘉宾最初的见面。火速恋爱,但是没有所谓的快节奏,相识半年,还是一样的热恋。吃着肉夹馍坐过西安的小三轮洱海边自行车的气球胖吃着她最喜欢的酸酸水果和小乳扇在南山某店爷爷穿孙子衣服,摸肥猫就算我在忙也要抽出时间陪她去吃他喜欢的漂亮饭生活总是平凡,但平凡不平淡还记得见面第一件事儿:“我去上个厕所。”现在早上第一件事儿:“拉*”第一次上我车的她:“我可以坐副驾吗?”现在的她:“老子把jio翘到上面得得挡到你后视镜。”这小孩,虽然花了我...
Stan_蹒跚者:确很厉害,但是有一个小问题:谁问你了?我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了
点赞 评论 收藏
分享
小厂面经,也是我的处女面(30min)1.自我介绍2.spring&nbsp;boot的自动装配原理(好多类和接口的单词都忘了全称是啥了,就说了记得的单词,流程应该说对了吧)3.有用过redis吗?主要是用在实现什么功能(说了技术派用redis的zset来实现排行榜)5.有了解过Redisson吗?讲一下对于分布式锁的了解以及在什么场景下应用(说了秒杀场景)6.对mysql有了解吗?包括它的索引优化和创建(把想起来的全说了)7.了解设计模式吗?比如单例模式,为什么要使用单例模式,它的优点是什么(昨天刚看的设计模式)8.工厂模式有了解吗?主要的使用场景是?(也是昨天刚看的)9.场景题:有7个服务器,需要在早上十点定时的向数据库中的用户表中的用户发短信,如果做到发送的消息不重复,且如果发送失败了需要知道是到哪个用户失败了,这样下次就直接从这个用户开始(我答了用spring&nbsp;task来实现定时,用分布式锁来保证只有一份服务器可以发送消息,用消息队列来存储消息,然后用消息确认机制来保证错误信息的记录,以及在数据库或者业务层面完成消息消费的幂等性)10.场景题:如果在系统启动的时间就将数据库的所有用户相关的信息都读到一个hashmap中(这个没啥思路,没答好)27届的投了一个星期终于有一个面试了,大部分公司都只招26的
inari233:已oc,拒了
查看9道真题和解析
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务