2024年美团笔试题(1)

发布于:2024-04-01 ⋅ 阅读:(70) ⋅ 点赞:(0)


一.题目描述

小美拿到了一个排列,其中初始所有元素都是红色,但有些元素被染成了白色。 

小美每次操作可以选择交换任意两个红色元素的位置。她希望操作尽可能少的次数使得数组变成非降序,你能帮帮她吗?

排列是指:一个长度为n的数组,其中1到n每个元素恰好出现了一次。 
输入描述 
第一行输入一个正整数n,代表数组的长度. 
第二行输入几个正整数ai,代表数组的元素。 
第三行输入一个长度为n的字符串,代表数组元素的染色情况。第i个字符为'R"代表第i个元素被染成红色,为"W"代表初始的白色.

1 ≤n≤ 10^5 
1<=ai<=n 
输出描述 
如果无法完成排序,请输出 -1. 
否则输出一个整数,代表操作的最小次数。 
示例 1 
输入
4
1 3 2 4 
WRRW 
输出
1
说明
第一次操作,交换 2和 3,数组变成[1,2,3,4] 


二.分析

  • 题目中写了:排列是指:一个长度为n的数组,其中1到n每个元素恰好出现了一次。也就意味着上面操作使得非降序,是指升序,不存在两个数字一样的情况
  • 每次操作可以选择交换任意两个红色元素的位置,什么意思?意味着不可以动白色的染色体
  • 需要思考什么情况下不可以完成排序:当这个位置是排序好的,比如1,2,3,4,5,而他的排序是2,1,3,4,5,我们可以看到2,1是未排序好的,当他的下标+1不是他的数据,并且它是白色染色体不可以挪动,那么是必定无法排序成功的。此时返回-1
  • 最小操作次数:1,2,4,3,5,每次都让一个数字回到它本来的位置,挪动的次数就是最少

/* 测试1
4
1 3 2 4
WRRW
1
*/
int main()
{
	int n;
	cin >> n; //录入第一行
	int* arr = new int[n];//录入第二行
	char* brr = new char[n]; //录入第三行
	for (int i = 0; i < n; i++)
		cin >> arr[i];
	for (int i = 0; i < n; i++)
		cin >> brr[i];

	for (int i = 0; i < n; i++)//排除不可能的情况
	{
		if(arr[i]!=i+1 && brr[i] == 'W')//'W'不能移动
		{
			cout << -1;
			delete []arr;
			delete[]brr;
			return 0;
		}//位置错了  if 删了   提交
	}
	//1 3 2 4
	//1 2 3 4  ,怎么次数最少?  可能是每次能处理一个正确的数字
	//4 3 2 1
	int count = 0;//计数器
	int tmp;
	for (int i = 0; i < n; i++)
	{
		while (arr[i] != i + 1)//不是正确的位置,交换
		{

            //把当前位置和它应该放的位置交换
			tmp = arr[arr[i] - 1];
			arr[arr[i] - 1] = arr[i];
			arr[i] = tmp;
			count++;
		}
	}
	cout << count;
	delete []arr;
	delete[]brr;
	return 0;
}

注意点演示:

一定要区分两种不同的移动方式:

如果只是简单地遍历一遍是不可以达到排序的效果,必须一直挪动,直到当前位置是想要的数字为之,否则不可以。

下面演示第一种和第二种移动方式的区别:(错误演示)


本篇完!

本文含有隐藏内容,请 开通VIP 后查看