1.考试座位
题目
现在有n个人坐成一排进行上机考试。但他们有的使用C语言,用C表示;而有的使用Java,用J表示。为了防止他们“友好交流”,老师要求任意座位相邻的两人之间使用的语言是不同的。每次可以交换相邻两人的位置,请问最少交换多少次可以满足要求?
输入:
n,表示n个同学
一串字符,C表示C语言,J表示Java
输出:
最少交换的次数
示例:
4
CCJJ
输出:
1
思路
1.首先保证C和J的个数相差小于等于1
2.使用两个指针,指向第一个和第二个元素,如果两个元素不同则移动两个指针一步,如果相同,则寻找右边的一个与第一个元素不同的,并交换到第二个元素的位置来,并记录交换次数,重复以上过程
3(之前的想法).当出现最后两个是相同的字母时,需要将倒数第二个交换到第一个位置来,需要交换次数n-2次。
3. 最后两个字母相同的情况,可以从前挨着两两交换,比如JCJCJCC, 交换三次即可(前三对交换),按照上面思路需要交换5次
代码
#include<iostream>
using namespace std;
//考试座位
int main()
{
int res = 0;
int n; //输入数据的长度
cin >> n;
string s;
cin >> s;
int c = 0, j = 0;
for (int i = 0; i < n; i++)
{
if ('C' == s[i]) c++;
else j++;
}
if (abs(c - j) > 1) return -1;
int left = 0, right = 1;
while(right != n - 1)
{
if (s[left] != s[right])
{//不需要交换
left++;
right++;
}
else
{//需要交换,去right的右边找一个和s[left]不同的元素,然后交换过来。
int right_t = right + 1;
while(s[left] == s[right_t])
{//如果相等,则找下一位
right_t++;
}
//找到和s[left]不同元素的下标right_t,交换到right下标。
while(right_t != right)
{
res++;
//swap(s[right_t], s[right_t - 1]); //交换两个数
int temp = s[right_t];
s[right_t] = s[right_t - 1];
s[right_t - 1] = temp;
right_t--;
}
left++;
right++;
}
}
//在交换完了,最后两个是一样的,需要把前面的CJ或者JC交换
if (s[left] == s[right]) res += (n - 1) / 2;
cout << res << endl;
}
2.颜色排序
题目
有一个长度为n的整数序列,并且序列上每个数字都被染上了颜色1-n的其中一种,现给该数列从小到大排序,但是每次操作只能交换相邻两个数,并且两个数的颜色要不相同,请问进行若干次之后能不能给这个序列排好序。
输入:
第一行输入T,表示有T组数据
每组数据
第一行一个n,代表序列长度,第二行是n个数,第三行表示颜色,相同数字的颜色相同
输出:
对于每组数据,可以排好序,输出Yes,否则输出No
思路
由于数组是从小到大排序,我们只需确保,相同颜色是升序即可。
步骤:先用字典存(颜色,值)
1.如果字典中没有该颜色,把(颜色,值)加入字典
2.如果有该颜色,比较当前颜色的值是否大于之前的值,是则更新颜色值,否则不能满足要求直接返回False
代码
def fun(nums, color):
color_dic = {}
for i in range(n):
# 如果字典中没有该颜色,把(颜色,值)加入字典
if not color[i] in color_dic.keys():
color_dic[color[i]] = nums[i]
# 如果有该颜色,比较当前颜色的值是否大于之前的值,是则更新颜色值,否则不能满足要求直接返回False
else:
if nums[i] >= color_dic[color[i]]:
color_dic[color[i]] = nums[i]
else:
return False
return True
T = int(input())
while(T != 0):
T -= 1
n = int(input())
nums = list(map(int, input().split()))
color = list(map(int, input().split()))
res = fun(nums, color)
if res:
print("Yes")
else:
print("No")