解题思路:

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

*       如: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、在字符串中没有第二个与它相同,所以不可能发生移动。

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

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

*/

无标题.png

注意事项:

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

参考代码:

//统计字母出现的次数,判断是否有条件构成回文
	public boolean tally(char[] array) {
		int statistics[] = new int[26];
		for (int i = 0; i < array.length; i++) {
			statistics[array[i] - 'a'] += 1;
		}
		int record = 0;
		for (int i = 0; i < statistics.length; 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 < array.length / 2; 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 < array.length - (i + 1); 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 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 6 条评论

张仁翔 9月前 回复TA
膜拜大佬
猿来是你 1年前 回复TA
你已经可以升本了
李大超 2年前 回复TA
有个小不懂,第27、28行,位置 i 和位置 j 的值相等,所以要把 j 交换到 length - i - 1,但是如果位置 i 和位置 length - i - 1 的值也相等呢,不是就不用交换了吗?
东星耀阳 2年前 回复TA
好解释  牛逼
三玖是天 3年前 回复TA
不一定要除了中间吧,所有字母都成队,一样可以组成回文
车厘子 4年前 回复TA
膜拜大佬