PAT sort with swap(0, *) (索引排序)

PAT sort with swap(0, *) (索引排序)

稍微有点难度的一道题,开始写一个给超时了,直接把for循环套在了while里,硬生生的把复杂度从O(mN)拉到了O(N^2)

为了解决这道题,首先需要知道一些知识:
N个数字的排列由若干个独立的环构成。
这句话什么意思?
比如对于一个从 ( 0 , N − 1 ) (0,N-1) (0,N1)的排列,表示成数组的形式,记为 A [ N ] A[N] A[N],令 j = A [ i ] j=A[i] j=A[i],那么沿着 A [ j ] A[j] A[j]这个路径下去,最后会回到起点。
总体来说就是如果 A [ i ] = s A[i]=s A[i]=s A [ A [ . . . . A [ A [ s ] ] . . . . ] ] = s A[A[....A[A[s]]....]] = s A[A[....A[A[s]]....]]=s

根据这个题的意思,我们每次交换0和任意一个元素,肯定想到的就是
和与0这个位置对应的元素所在的位置交换,比如0的位置在7,7的位置在1,我们就要交换这两个位置,那么7就被放到了正确的位置,0就在位置1,重复进行。

运气好的话一趟就能把整个序列的元素有序,那么交换的次数就是 N − 1 N-1 N1这么多次,为什么呢,因为每次可以使得一个元素有序,但是最后一次是使得剩下的最后两个元素同时有序,所以是 N − 1 N-1 N1次。
如果运气不好,还没有交换完的时候,0就回到了他的正确位置,也就是说 A [ 0 ] = 0 A[0]=0 A[0]=0了,那么我就可以考虑对于还没有交换完的剩下的环,我们把0加进去,然后让0随便同其中一个元素交换位置(同哪一个元素交换不重要),然后继续沿着这个环重复上述操作,知道0又到达了他的正确位置。这种情况下要交换多少次呢,首先假设这个环的元素是 N i N_i Ni,加上0之后为 N i + 1 N_i+1 Ni+1,再根据上面所说的可得到交换次数是 N i + 1 − 1 + 1 = N i + 1 N_i+1-1+1=N_i+1 Ni+11+1=Ni+1,最后的加一是什么呢,就是把0同任意元素交换的一次也加上。

当然写的时候我们只需要统计每个环的个数,包含0的环交换次数就是环内元素个数 N N N减去1,不包含0的环就是 N + 1 N+1 N+1
由于环是相互独立的,只有一个环是包含0的。

#include <iostream>
using namespace std;
const int max_n = 1e5;

int N;
int pos[max_n + 10];

int main() {
	cin >> N;
	for (int i = 0; i < N; i++) {
	// 其实并不需要用的输入的数列,只需要知道每个元素的位置就行了,所以只需要一个位置数组。pos[i]代表第i个元素的位置。
		int num; scanf("%d", &num);
		pos[num] = i;
	}
	int res = 0;
	for (int i = 0; i < N; i++) {
        int now = pos[i];
        int Elements = 1;
        if (now == pos[now]) continue;
        //沿着环统计环内元素的个数,也就是索引排序的写法。
        while (now != pos[now]) {
            int nxt = pos[now];
            pos[now] = now;
            pos[i] = nxt;
            now = pos[i];
            Elements++;
        }
        //只有一个环是包含0的,就是从0开始的这个。
        if(i == 0) res += Elements - 1;
        else res += Elements + 1;
    }
    cout << res << endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值