蓝桥杯练习系统之基础训练Java版(2-19)—— 完美的代价

蓝桥杯练习系统之基础训练Java版(2-19)—— 完美的代价

**难度等级:中等**

**关键字:贪心算法**

问题描述:

回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回
文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
  交换的定义是:交换两个相邻的字符
  例如mamad
  第一次交换 ad : mamda
  第二次交换 md : madma
  第三次交换 ma : madam (回文!完美!)

输入格式:

第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)

第二行是一个字符串,长度为N.只包含小写字母

输出格式:

如果可能,输出最少的交换次数。
否则输出Impossible

样例输入:

5
mamad

样例输出:

3

思路探索:

代码如下:

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        String str = sc.next();
        
        int oddNum = 0;		//用来判断是否只有一个奇数
        int count = 0;		//交换的次数
        int []cnt = new int[26];;	//将字符串转换成数组的形式
        char[] chars = str.toCharArray();
    	int len = n - 1;
    	int flag = 0;
        
    	//用数组存储数组元素下标对应的序号字母出现的次数
    	for(int i = 0; i < str.length(); i++) {
            cnt[str.charAt(i)-'a']++;
        }
    	//统计只出现奇数次的字母的个数
        for(int i = 0; i < 26; i++) {
            if(cnt[i] % 2 == 1)
                oddNum++;
        }
    	
        for (int i = 0; i < len; i++) {
        	
            for (int j = len; j >= i; j--) {
                if(i == j){		//在chars[i]数组中没有找到相同的字符
                	/*
                	 * 字符串的长度为偶数,且存在出现次数为奇数个的字符或者存在两个出现次数为奇数个的字符
                	 */
                    if((n % 2 == 0 && oddNum >= 1) || (oddNum > 1)) {
                        System.out.println("Impossible");
                        return;
                    }
                    count += n / 2 - i;		//将奇数次的字符交换到中间位置的次数
                }
            	
                if(chars[i] == chars[j]) {	//如果找到了,将chars[j]交换到最后
                    for(int k = j; k < len; k++) {
                        char temp = chars[k];
                        chars[k] = chars[k + 1];
                        chars[k + 1] = temp;
                        count++;
                    }
                    len--;//末尾递减
                    break;
                }
            }
        }
        System.out.println(count);
    }
}

希望能对您有帮助!谢谢。(还有更简单的方法,但是难理解,后续更新…)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值