The puzzle

题目连接: The puzzle

题目:

Kayaking is playing a puzzle game containing n different blocks. He marks the blocks with integers from 1 to n, which show the blocks’ original positions. Each time he can exchange two blocks and he wants to know how many times he needs at least to restore the puzzle.

Input
The input starts with one line contains exactly one positive integer which is the number of test cases.
Each test case contains two lines.
The first line contains an integer, which indicates the number of puzzle pieces.
The second line contains n different integers, the i-th number means the mark of the block in the i-th position.

Output
For each test case, output one line with one number represents the minimum operations.

Sample Input
2
4
2 3 4 1
4
2 1 4 3
Sample Output
3
2

大概翻译一下: 给你一共1到n, 共n个数字, 而你需要把他们排序, 排序的最终结果是下标 i上存放的数字为 i.
排序只能通过两两交换来改变下标为i处的值, 问你至少需要多少次交换

解题思路:

其实细想可以分为以下三类:

  1. 第一类: 本身就在正确的位置上, 不需要操作.
  2. 第二类: 本应在i位置上的数字在j位置上,而 j位置上的数字恰好在i位置上, 刚好相反, 直接交换, 这样i和j位置都符合要求
  3. 第三类: 本应在i位置上的数字在j位置上,而j位置上的数字在k位置上…

但是如果综合思考, 第二类和第三类是同一类, 因为他们都是需要交换的一类, i位置放的数字不是i, 一定要把i这个数字换到i上, 所以这一步是无法再简化的一步, 第二类情况只不过是第三类情况的一个特例, 可以少进行一次交换.
如果这样来看, 但凡i位置上放的不是i, 那交换次数就要加一.

AC代码:

#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#define ll long long
using namespace std;
#define MAXN 100005
int a[MAXN]; //a数组是记录当前位置i处的值a[i]
int b[MAXN]; //b数组是记录值i在a数组所处的下标b[i]
int main(void)
{
	int t; cin >> t;
	while (t--) {
		int n; scanf("%d", &n);
		int res = 0; //存放结果
		for (int i = 1; i <= n; i++) {
			scanf("%d", &a[i]);
			b[a[i]] = i;
		}
		for (int i = 1; i <= n; i++) {
			if (a[i] == i) continue; //符合条件, 不用处理
			int index = b[i]; //a[i]应放的值i在a[index]处, 需要交换
			b[a[i]] = index; b[i] = i;
			swap(a[i], a[index]); res++;
		}
		cout << res << endl;
	}
	return 0;
}

这个题想清楚思路的话实现起来其实并不会很难, 如果index部分有些不明白不妨代入假想数据去试一试, 尝试理解.

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

逍遥Fau

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

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

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

打赏作者

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

抵扣说明:

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

余额充值