基础练习 完美的代价

来源:互联网 发布:小甲鱼python解压密码 编辑:程序博客网 时间:2024/05/22 16:42
问题描述
  回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
  交换的定义是:交换两个相邻的字符
  例如mamad
  第一次交换 ad : mamda
  第二次交换 md : madma
  第三次交换 ma : madam (回文!完美!)
输入格式
  第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
  第二行是一个字符串,长度为N.只包含小写字母
输出格式
  如果可能,输出最少的交换次数。
  否则输出Impossible
样例输入
5
mamad
样例输出

3



贪心算法


思路:

先判断出现字母的个数为奇数的数量_count,若_count>1,就是impossible;如果_count为零,就是所有的都能配对成功,左边开始固定一个字母,就从右边对称位置开始往左边搜,第一个遇到一样的字母的就向右移到对应的位置。一直如此重复就解出来了;

单是_count=1时,寻找时会遇到找不到的情况,应为这个字母就是放在最中间,这个时候就要从右边开始固定,开始从左边开始位置向右边找,这样的话中间的那一个最后自己就到最中间去了;


接下来设定一种理想情况,就是不会被破坏的情况,就是最后回文中靠近两边的字母一定是更早到达对应的位置,因为如果是中间的元素更早到达平衡位置,你再调外侧的元素内侧一定会被打乱,所以假设一种理想情况,即不会被打乱的情况,那么假设此时移动的次数为理想距离;如果移动配对两侧的元素,他就是理想距离,但是配对两侧的元素的时候由于移动会使一些字母偏离理想距离,又会使一些字母更靠近理想距离,为什么呢,应为这样的操作会使字母往中间靠拢,有元素大于理想距离,就一定有元素小于理想距离,所以移动的总次数一定不会超过理想距离,所以这样的策略一定是对的。

/** *  */package 基础练习;import java.awt.Checkbox;import java.util.Scanner;/** * @author Administrator 问题描述 *         回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的, *         请你计算最少的交换次数使得该串变成一个完美的回文串。 交换的定义是:交换两个相邻的字符 例如mamad 第一次交换 ad : mamda *         第二次交换 md : madma 第三次交换 ma : madam (回文!完美!) 输入格式 *         第一行是一个整数N,表示接下来的字符串的长度(N <= 8000) 第二行是一个字符串,长度为N.只包含小写字母 输出格式 *         如果可能,输出最少的交换次数。 否则输出Impossible 样例输入 5 mamad 样例输出 3 */public class 完美的代价 {/** * @param args */private static int change = 0; // 改变的次数private static int old = 0; // 记录出现奇数次字符private static char charold = 0;// 记录奇数字符public static void main(String[] args) {// TODO Auto-generated method stubScanner sc = new Scanner(System.in);int N = Integer.parseInt(sc.nextLine());String s = sc.nextLine();char str[] = s.toCharArray();Boolean flag = check(str); // 是否可以组成回文if (!flag) {System.out.println("Impossible");} else {for (int i = 0; i < N / 2; i++) {if (str[i] != charold) {// 从右开始找对称int j = 0;for (j = N - 1 - i; j > i; j--) {if (str[i] == str[j])// 找到break;}change += N - 1 - i - j; // 移动次数for (int j2 = j; j2 < N - 1; j2++) {str[j2] = str[j2 + 1];}str[N - 1 - i] = str[i];// 对称点}// 从左边开始else {int j = 0;for (j = i; j < N - 1 - i; j++) {if (str[j] == str[N - 1 - i])break;// 找到}change += j - i;// 移动次数for (int j2 = j; j2 < i; j2--) {str[j2] = str[j2 - 1];}str[i] = str[N - 1 - i]; // 对称点}}System.out.println(change);}}private static boolean check(char[] str) {int arr[] = new int[26];for (int i = 0; i < str.length; i++) {arr[str[i] - 'a']++;}for (int i = 0; i < 26; i++) {if (arr[i] % 2 == 1) {old++;charold = (char) (i + 'a');}}if (old > 1)return false;return true;}}

提交到蓝桥杯系统只得了60分。 有四个没有ac不知道什么原因。还在研究中。。。。


0 0
原创粉丝点击