蓝桥杯3月6号练习

试题 基础练习 完美的代价

问题描述

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

输入格式

第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
  第二行是一个字符串,长度为N.只包含小写字母

输出格式

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

思路:

因为考虑到最少的情况,所以是贪心算法的思想。

模拟交换的过程

Impossible的情况:1 字符串的长度是奇数,但是出现一次的字符数目大于1。

​ 2 字符串的长度是偶数,但是出现一次的字符数大于0

代码

import java.util.Scanner;

public class Main {
	static Scanner scanner = new Scanner(System.in);

	// 字符串交换函数
	static void swap(char[] arr, int s, int e) {
		char temp = arr[s];
		arr[s] = arr[e];
		arr[e] = temp;
	}

	public static void main(String[] args) {
		int n = scanner.nextInt(); // 字符串长度
		String string = scanner.next(); // 读取字符串
		char[] arr = string.toCharArray(); // 将字符串转换为字符数组
		int len = arr.length;
		int swap_count = 0; // 记录交换次数
		int once_char = 0; // 记录出现一次的字符数
		// 遍历交换
		for (int i = 0; i < n - 1; i++) { // 遍历1到n-1的字符
			for (int j = n - 1; j >= i; j--) { // 从n-1开始往前找,是贪心算法的体现
				if (i == j) { // i==j 表示没找到
					if (once_char == 1 || len % 2 == 0) {
						System.out.println("Impossible"); // 为Impossible的情况
						return;
					}
					once_char++;
					swap_count += (len / 2) - i;// 如果为奇数且只有一个出现一次的字符,那么就的模拟把他换到中间,需要移动(len/2—)-i次
				} else if (arr[i] == arr[j]) { // 找到了那个与之匹配的字符
					for (int k = j; k < n-1; k++) {
						swap(arr, k, k + 1); // 模拟交换
						swap_count++; // 交换次数加加
					}
					n--; // 固定了最有的字符,所以下次就不能再用了,因此可交换的字符长度范围要减少1
					break; // 当前的字符确定了,进行下一轮的字符判断
				}
			}
		}
		System.out.println(swap_count);
	}

}

参考学习

https://blog.csdn.net/selaotou11/article/details/104594393 题目解析

https://www.bilibili.com/video/BV1e7411T7FV?p=124 贪心算法

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页