蓝桥杯基础java--完美的代价

完美的代价

给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。交换的定义是:交换两个相邻的字符。
  思路:
  1. 判断是否能够通过交换形成回文字符串。
  (1)如果字符串的长度length为奇数,那么有且仅有一个字符的频次为奇数。即出现频次是偶数的字符有 length-1
  (2)如果字符串的长度为偶数,那么所有字符的长度都应该为偶数。即出现频次是偶数的字符有 length
  
可以通过map记录字符串中每个字符出现的次数
练习: 计算一个字符串中每个字符出现次数

分析:
1.创建Map集合,key是字符串中的字符,value是字符的个数
2.遍历字符串,获取每一个字符
3.使用获取到的字符,去Map集合判断key是否存在
key存在:
通过字符(key),获取value(字符个数)
value++
put(key,value)把新的value存储到Map集合中
key不存在:
put(key,1)

        HashMap<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            if (map.containsKey(s.charAt(i)))
                map.put(s.charAt(i), map.get(s.charAt(i)) + 1);
            else
                map.put(s.charAt(i), 1);
        }

通过遍历map中的值,判断频次是偶数的字符个数。

 int count = 0;
 //遍历map中值的办法。
        for (Integer value : map.values()) {
            if (value % 2 == 0)
                count++;
        }
        if (s.length() % 2 == 0 && count == map.size())
            return true;
        if (s.length() % 2 == 1 && count == (map.size() - 1))
            return true;
        return false;

在这里插入图片描述在这里插入图片描述
i 指向第一个字母。j指向最后一个字母,进行比较。
(1)如果相同,则将i向右移,将j向左移。直到 i移到 n / 2 − 1 n/2-1 n/21的位置
(2)如果不同则在红色框框里寻找等和i相同的字符

  • 如果找到,则将j上的字符与该字符进行交换。(这里的交换不是直接将两个字符进行交换,而是通过不停与相邻元素进行交换)
  • 如果找不到,并且字符长度是奇数,说明i上的字符应该放在中间位置,但是如果我们现在将它放到中间位置,后面对字符的交换也会影响它的位置,所以我们将i位置上的字符和后面一个字符交换。放到后面再处理,等到我们将不是中间的字符全部对称完毕,该字符自然也就在中间位置。
import java.util.HashMap;
import java.util.Scanner;

public class MapTest {

    public static void main(String[] args) {
        Scanner scn = new Scanner(System.in);
        int n = scn.nextInt();
        String s = scn.next();
        if (check(s) == false)
            System.out.println("Impossible");
        else {
            char[] c = s.toCharArray();
            int count = 0;
            for (int i = 0; i <= n / 2 - 1; i++) {
                if (c[i] != c[n - 1 - i]) {
                    boolean find = false;
                    for (int k = n - 2 - i; k > i; k--) {
                        if (c[k] == c[i]) {
                            swap(c, k, n - 1 - i);
                            count += n - 1 - i - k;
                            find = true;
                            break;
                        }
                    }
                    if (find == false && n % 2 == 1) {
                        swap(c, i, i + 1);
                        count += 1;
                        i = i - 1;
                    }
                }
            }
            System.out.println(count);
        }
    }

    private static void swap(char[] c, int k, int i) {
        while (k <= i - 1) {
            adjswap(c, k, k + 1);
            k++;
        }
    }

    private static void adjswap(char[] c, int k, int i) {
        char temp = c[k];
        c[k] = c[i];
        c[i] = temp;
    }

    public static boolean check(String s) {
        HashMap<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            if (map.containsKey(s.charAt(i)))
                map.put(s.charAt(i), map.get(s.charAt(i)) + 1);
            else
                map.put(s.charAt(i), 1);
        }
        int count = 0;
        for (Integer value : map.values()) {
            if (value % 2 == 0)
                count++;
        }
        if (s.length() % 2 == 0 && count == map.size())
            return true;
        if (s.length() % 2 == 1 && count == (map.size() - 1))
            return true;
        return false;
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凭栏听雨客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值