Java 蓝桥杯 完美的代价

问题描述

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

输入
输入描述:
  第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
  第二行是一个字符串,长度为N.只包含小写字母
输入样例:
5
mamad

输出

输出描述:
  如果可能,输出最少的交换次数。
  否则输出Impossible
输出样例:
3

HINT:时间限制:1.0s 内存限制:512.0MB

解题思路

首先要判断输入的是不是回文数,就先判断每个字母出现的次数以及奇数字母的个数,若奇数次数的字母个数大于1的话就不能构成回文数,在判断交换次数时还要注意如果是1位或者2位字符串的话就直接返回0,因为1,2位的就是回文数不用交换,接下来就是判断每次首字母在后面出现的次数了,如果首字母只有一次的话就把他放到中间,其余的再进行循环运算,就相当于在中间的两边加字符

代码

import java.util.Locale;
import java.util.Scanner;
import java.util.regex.Pattern;

public class Main {
    
    

    public static void main(String[] args) {
    
    
        Scanner scanner=new Scanner(System.in);
        int m=scanner.nextInt();
        String n=scanner.next();
        if (panduan(n)){
    
    
            System.out.println(cishu(n));
        }else {
    
    
            System.out.println("Impossible");
        }
    }
    public static boolean panduan(String n){
    
    
        //判断是否构成回文数 就是判断字母出现为奇数次数的个数
        boolean panduan=true;
        int [] num=new int[26];
        int geshu=0;//记录奇数次的个数
        for (int i=0;i<n.length();i++){
    
    
            num[n.charAt(i)-'a']++;//得到每个字母对应的数值
        }
        //统计奇数次字母出现的个数
        for (int i=0;i< num.length;i++){
    
    
            if (num[i]%2==1){
    
    
                geshu++;
            }
        }
        if (geshu>1){
    
    
            panduan=false;//若大于1 则不能形成回文数
        }
        return panduan;
    }
    //如果为回文数 则判断交换次数
    public static  int cishu(String n){
    
    
        int cishu=0;
        if(n.length()==1 || n.length()==2){
    
    //只有1位和2位的字符串 就是回文数 返回0次
            return 0;
        }
        cishu=n.lastIndexOf(n.charAt(0));//每次首字母最后出现位置的索引
        if (cishu==0){
    
    
            return n.length()/2 + cishu(n.substring(1,n.length()));//如果首字母只出现了首字母放到中间 
            //substring的作用为截取第1位到最后一位的字符串。
        }else {
    
    
            StringBuilder stringBuilder=new StringBuilder(n);//如果不为1次的话移动的次数就是 长度-cishu-1 然后再删除计算过的。
            stringBuilder.deleteCharAt(cishu);//删除已经计算过的
            //deleteCharAt为移除此位置的字符
            stringBuilder.deleteCharAt(0);
            return n.length()-cishu-1 + cishu(stringBuilder.toString());
        }
    }
}

流程图

Created with Raphaël 2.3.0 开始 输入字符串的长度m以及字符串n 定义panduan为真,一个26位的数组,用geshu记录奇数次字符的个数 依次计算每个字母对应的数值 奇数次字符的个数大于1 panduan为假 定义cishu来接收字母的索引 如果只有一个或者两个字符 返回0 结束 计算每次首字母在后面出现位置的索引 如果只出现了一次 循环计算需要的次数 构成回文数 输出需要的次数 输出Impossible 建立一个stringBuilder来简便操作字符串 删除已经计算过的和首位字符 重新计算需要的次数 yes yes no yes no yes no

Guess you like

Origin blog.csdn.net/joreng/article/details/121495742
Recommended