【备战秋招】每日一题:2023.2.25-京东机试-塔子哥的数组

为了更好的阅读体检,可以查看我的算法学习网
在线评测链接:P1054

题目内容

塔子哥是一个程序员,他正在为一个新的项目编写代码。这个项目需要对一个数组进行操作,但是这个数组的初始值不满足项目的要求。于是,塔子哥想到了一个办法:他可以修改数组中的任意一个元素,将其修改为任意值。他希望用最少的操作方式使得数组满足以下条件:

  1. 最终数组仍是一个排列。

  2. 最终数组的逆序对数量为 1 1 1

数组的逆序对是指,满足 i < j i \lt j i<j a i > a j a_i \gt a_j ai>aj 的二元组数量。

排列指长度为 n n n 的数组, 1 1 1 n n n 每个正整数恰好出现 1 1 1 次。

输入描述

第一行输入一个正整数 n n n ,代表数组的大小。

第二行输入 n n n 个正整数 a i a_i ai ,代表塔子哥拿到的数组。

2 ≤ n ≤ 1 0 5 2\le n\le 10^5 2n105

1 ≤ a i ≤ n 1\le a_i\le n 1ain

保证初始数组是一个排列。

输出描述

一个整数,代表最小的操作次数。

样例

样例一:

输入

4
3 2 1 4

输出

3

样例解释

将数组修改为 [2,1] 即可。

思路

逆序对只有一对的排列只能是从1~n中交换相邻的一对,比如:1、2、3、5、4、6这样的,所以直接枚举所有的符合条件的排列即可,先计算一下原排列和1~n中相同的位置有多少,然后再枚举交换相邻的一对的位置,再特殊处理一下,过程中取最小值即可。

代码

c++

#include <bits/stdc++.h>
using namespace std;

int n;
int a[100010];
int main()
{
	cin >> n;
	int cnt = 0;
	for(int i = 1 ; i <= n ; i ++) {
		cin >> a[i];
		cnt += a[i]==i;		//计算相同的位置
	}
	int ans = n;
	for(int i = 1 ; i < n ; i ++) {
		int t = cnt;
		t -= a[i]==i;		//特殊处理当前交换的i和i+1,要先去除原来的计算结果,再加上交换后的结果
		t -= a[i+1]==i+1;
		t += a[i]==i+1;
		t += a[i+1]==i;
		ans = min(ans, n-t);
	}
	cout << ans << endl;
}

python

n = int(input())
a = [0] + list(map(int, input().split()))
cnt = 0
for i in range(1, n+1):
	a[i] == i:
		cnt += 1
ans = n
for i in range(1, n):
	t = cnt
	if a[i] == i:
		t -= 1
	if a[i+1] == i+1:
		t -= 1
	
	if a[i] == i+1:
		t += 1
	if a[i+1] == i:
		t += 1
	
	ans = min(ans, n-t)

print(ans)

题目内容均收集自互联网,如如若此项内容侵犯了原著者的合法权益,可联系我: (CSDN网站注册用户名: 塔子哥学算法) 进行删除。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

塔子哥学算法

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

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

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

打赏作者

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

抵扣说明:

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

余额充值