java完美回文串的代价_[蓝桥杯][基础练习VIP]完美的代价-题解(Java代码)

思路:回文字符串就是 字符从字符串成中间折叠对称的字符串。

*       如:abdba、abcdcba....等等。

* 我们会发现一个规律,每一个字符都是成对存在、除了中间的那一个字符,其他的都是成对存在。

* 因此,我们可以用这个特性判断该字符串是否可以构成回文字符串-->实现方法tally

*     我们确定可以该字符串可以构成回文字符串后,接下来就是对没有形成回文字符串的字符进行移动,以最小的移动步数

* 构成回文字符串,如:mamad它可以构成回文字符串,我们的目标就是把它变成madam。

* 结合回文和观察的规律发现:回文是i位置上的字符等于str.length - i位置上的字符。这样我们可以推理,我们把每一个位置上的字符

* 都以最小的步数构成 str[i] == str[str.length - i]。那总体上来说是不是可以做到最小步数把非回文字符串变成回文字符串了。

* 其实这个方法可以用一些方法来证明它的正确性,我的数学意识太差,不知道用什么方法去证明,如果有大佬可以推导出证明过程,可以留言给我吗?。

* 这个方法的答案是正确的。

* 实现细节:我们以中间为节点。找左边的字符,看看在右边(这个右边相对与中间点左边当前的字符)是否有与其想同的字符,相同就进行移动。

*     例子:mamad,aadmm。

*     对于mamad,我们可以从左边开始找,发现第一个 m和第三个m相等,然后就把第三个m移动到d的位置。一直重复这个动作,

* 最后就可以得到madam了。

*     对于aadmm我们从左边开始找,发现到admma之后,第二个d、在字符串中没有第二个与它相同,所以不可能发生移动。

* 然后就结束了,因为我们在左边找,看右边是否与左边的字符相等,相等就移动。为什么这样子做呢?因为回文字符串就是

* 以中间点进行一个分界线,以这条分界线对称。所以我们可以左右两边找,先找左边,在找右边。

*/

b16108df8a56a57ae46abe4912ff40a8.png

注意事项:

注意思路,就是每一个字符移动的最小步数,和起来就是总的最小步数

参考代码://统计字母出现的次数,判断是否有条件构成回文

public boolean tally(char[] array) {

int statistics[] = new int[26];

for (int i = 0; i 

statistics[array[i] - 'a'] += 1;

}

int record = 0;

for (int i = 0; i 

if (statistics[i] % 2 == 1) {

record += 1;

}

}

if (record > 1) {

return true;

}

return false;

}

public String change(String arg) {

char array[] = arg.toCharArray();

if (tally(array)) {

return "Impossible";

}

int number = 0;// 移动次数

for (int i = 0; i 

for (int j = array.length - (i + 1); j > i; j--) {

//左边找

if (array[i] == array[j]) {

// 把寻找到的字符array[j]移动到array.length - (i + 1)这个位置

for (int j2 = j; j2 

char character = array[j2];

array[j2] = array[j2 + 1];

array[j2 + 1] = character;

}

// 统计次数

number += array.length - (i + 1) - j;

break;//找到了最近的就结束

}

//右边找

if (array[array.length - (i + 1)] == array[array.length - (j+1)]) {

//把寻找到的字符array[array.length - (j+1)] 往 i移动

for (int j2 = array.length - (j+1); j2 > i; j2--) {

char a = array[j2];

array[j2] = array[j2 - 1];

array[j2 - 1] = a;

}

//统计次数

number += array.length - (j + 1) - i;

break;//找到了最近的就结束

}

}

}

return number + "";

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值