题目:
* 题目:
* 回文串,是一种特殊的字符串,它从左往右和从右往左读是一样的。
* 现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变为完美的回文回文串。
* 例如:mamad
* 第一次交换:mamda
* 第二次交换:madma
* 第三次交换:madam
*
* 输入格式:
* 第一行输入整数n ,表示字符串的长度(n <=8000 )
* 第二行输入字符串,长度为n,只包含小写字母
*
* 输出格式:
* 如果可能,输出最少次数
* 否则,输出Impossible
*
* 样列输入
* 5
* mamad
* 样例输出
* 3
解题思路:
- 输入
- 处理数据
- 输出
输入:
Scanner sc = new Scanner(System.in);int len = sc.nextInt();String str = sc.next();
处理数据:(多读题,解题的关键)
关键词提取:
回文串:
第一个与倒数第一一样
第二个与倒数第二一样
思考:
什么是回文串?
怎么判断它是回文串
结论:
(1)根据回文串的定义:我们需要俩个指针,一个从左往右,一个从右往左
(2)根据第一点,我们可以定义一个指针从左往右遍历,一个指针从右往左遍历找到相同的就将它丢到最后,长度--
如图当我们找到m后将m移动到最后,m不可能再次被移动【回文串特性:当前数据的第一个,与当前数据的最后一个一样】
(3)第一个与最后一个位置确定,那就可以缩短数组的长度
如果没有找到呢?
按照刚才的思路如果没有找到,我们不管它会出现什么样的情况?
我们把c假装看不见跳过对后面的数据排列,让它除掉c就是回文数,最后只需要移动c即可;
思路总结:
这题最重要是思路是将左右移动的数据:转换为只移动一个方向;我们每一次假设左边得到的数据是已经排好序的,从当前左边的数据中确定当前最后位置的数据;
在这个过程中,我们对数组的长度减少,减少交换的可能次数,保证数据只从一个方向移动,所以可以作为最少移动次数;
1、判断数据是否可以构成回文串
//判断是否为可成为回文串//将数据类型转换为数组减少charAt的调用char[] arr = str.toCharArray();//1、判断长度是否符合if (len != arr.length) {System.out.println("Impossible1");return;}//2、判断是否可以构成回文串int[] num = new int[26];for (int i = 0; i < arr.length; i++) {int k = arr[i] - 97;num[k]++;}int ans = 0;for (int i : num) {if (i % 2 == 1) {ans++;}}if (ans > 1) {System.out.println("Impossible2");return;}
2、构建回文串,记录回文数据
ans = 0;//记录移动次数int end = len - 1;for (int i = 0; i < (len+1) / 2; i++) {int j;for (j = end; j > i; j--) {if (arr[i] == arr[j]) {while (j < end) {char tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;j++;ans++;}
《《 长度-- 》》end--;break;}}if (i == j) {ans += (len-1) / 2 - i;}}
输出:ans记录次数
System.out.println(ans);
完整代码:《因为懒,所以没有使用方法》
package LanQiao.text;import java.util.Scanner;/*** 题目:* 回文串,是一种特殊的字符串,它从左往右和从右往左读是一样的。* 现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变为完美的回文回文串。* 例如:mamad* 第一次交换:mamda* 第二次交换:madma* 第三次交换:madam* <p>* 输入格式:* 第一行输入整数n ,表示字符串的长度(n <=8000 )* 第二行输入字符串,长度为n,只包含小写字母* <p>* 输出格式:* 如果可能,输出最少次数* 否则,输出Impossible* <p>* 样列输入* 5* mamad* 样例输出* 3*/
public class 回文串 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int len = sc.nextInt();String str = sc.next();//判断是否为可成为回文串//将数据类型转换为数组减少charAt的调用char[] arr = str.toCharArray();//1、判断长度是否符合if (len != arr.length) {System.out.println("Impossible1");return;}//2、判断是否可以构成回文串int[] num = new int[26];for (int i = 0; i < arr.length; i++) {int k = arr[i] - 97;num[k]++;}int ans = 0;for (int i : num) {if (i % 2 == 1) {ans++;}}if (ans > 1) {System.out.println("Impossible2");return;}ans = 0;int end = len - 1;for (int i = 0; i < (len+1) / 2; i++) {int j;for (j = end; j > i; j--) {if (arr[i] == arr[j]) {while (j < end) {char tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;j++;ans++;}end--;break;}}if (i == j) {ans += (len-1) / 2 - i;}}System.out.println(ans);}
}