IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 力扣第1278题:分割回文串③(Java)——阿里2021.4.12笔试第二题 -> 正文阅读

[数据结构与算法]力扣第1278题:分割回文串③(Java)——阿里2021.4.12笔试第二题

一、前言

? ? ? ? 前面说了,从今天开始写一些比较难的题目,那么今天就来挑战回文串啦。回文串的题目还是难度标识都是困难,今天这道题目确实也没有百分百独立做出,但是经过我写完后的思考,我还是想把我的看法罗列一下。

二、题目内容

????????三、题目分析

? ? ? ? 读一下题目,发现它让我们解决的是最少分割产生回文子串的问题,因为是用动态规划解决,所以第一步还是为了确定状态转移方程的形式。经过这几天的刷题,很容易就知道dp[i][j]描述的是前i个数分割成j个数所产生的最小划分。那么dp就应该这样定义:

int len=s.length();
int [][]dp=new int [len+1][k+1];

? ? ? ? 跟原来一样,为了防止下标问题,我们依然从1开始,到length结束。将初始值设置?

成比较大的值

       for (int i = 0; i < dp.length; i++) {
            Arrays.fill(dp[i], len);
        }

? ? ? ? 之后两个循环,第一个i的范围从1到s.length(),进入循环后需要判断i和k的大小,然后取较小的那个作为第二个循环j的范围,因为如果k大于i,那么就是要将i个数分成k个,明显违背原则。

之后进入第二层循环后需要判断一下,当j=1的初始情况,如果j等于1,就是将前i个数分成j个,也就是不需要分割,那么就需要修改了,我们需要从两边开始逐一相互对照,最后返回一个值赋值给dp[i][j],那么对于求赋值次数的值,我们可以另外写一个函数,很简单,直接上代码:

 public int change(String s,int left,int right){//字符串s,左下标left,右下标right
        int cnt=0;
        while(left<right)
        {
            if(s.charAt(left++)!=s.charAt(right--))
                cnt++;

        }
        return cnt;
    }

那么刚刚那个第二层循环j=1的初始情况就可以写成,dp[i][j]=change(s,0,i-1);

????????当j不等于1的时候呢?当我们要求dp[i][j]的时候,只需要找出前m个字符 分割成j -1个子串所修改的最小字符数+最后一个子串所需要修改字符数。(最后一个子 串就是前i个字符-前m个字符)所以再写一层循环

  for(int m=j-1;m<i;m++)
 {
   dp[i][j] = Math.min(dp[i][j], dp[m][j - 1] + change(s, m, i - 1));
 }

?最后返回dp[len][k]即可

四、完整代码

 public int change(String s,int left,int right){
        int cnt=0;
        while(left<right)
        {
            if(s.charAt(left++)!=s.charAt(right--))
                cnt++;

        }
        return cnt;
    }
    public int palindromePartition(String s, int k) {
        int len=s.length();

        int [][]dp=new int [len+1][k+1];
        for (int i = 0; i < dp.length; i++) {
            Arrays.fill(dp[i], len);
        }
        //前i个数,分割成j个回文字符串
        for(int i=1;i<=len;i++)
        {
            int l=Math.min(i,k);
            for(int j=1;j<=l;j++)
            {
                if(j==1)
                    dp[i][j]=change(s,j-1,i-1);
                else
                {
                    for(int m=j-1;m<i;m++)
                    {
                       dp[i][j] = Math.min(dp[i][j], dp[m][j - 1] + change(s, m, i - 1));
                    }
                }
            }
        }
        return dp[len][k];
    }

?

?

五、可优化部分

? ? ? ? 在本题中,除了三层循环耗时较多外,每次都需要计算的change值也占据的大量时间,其中也包含了重复运算。所以我们可以先用一个二维数组把每个字符串修改所需要的次数都记录起来,在主函数使用的时候直接取数组值即可,而不必进行函数运算。

    public int palindromePartition(String s, int k) {
        int len=s.length();
        int [][]palind=new int [len][len];
        for(int j=len-2;j>=0;j--)
        {
            for(int i=j+1;i<len;i++)
            {
                palind[j][i]=palind[j+1][i-1]+(s.charAt(i)==s.charAt(j)?0:1);
            }
        }
        int [][]dp=new int[len+1][k+1];
        for(int i=1;i<dp.length;i++)
            Arrays.fill(dp[i],Integer.MAX_VALUE);
        for(int i=1;i<=len;i++)
        {
            int l=Math.min(i,k);
            for(int j=1;j<=l;j++)
            {
                if(j==1)
                    dp[i][j]=palind[j-1][i-1];
                else
                    for(int m=j-1;m<i;m++)
                    {
                        dp[i][j]=Math.min(dp[i][j],dp[m][j-1]+palind[m][i-1]);
                    }
            }
        }
        return dp[len][k];
    }

六、感想

? ? ? ? 没啥说的了,这题好难,我看了老久...每日一题,明天继续。

?

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-10-13 11:40:49  更:2021-10-13 11:41:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:36:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码