让数组有序的最少交换次数

Trick : 让数组有序的最少交换次数

Problem One

1224. 交换瓶子 - AcWing题库

有 N 个瓶子,编号 1∼N,放在架子上。

比如有 5 个瓶子:

复制代码
2 1 3 5 4

要求每次拿起 2 个瓶子,交换它们的位置。

经过若干次后,使得瓶子的序号为:

复制代码
1 2 3 4 5

对于这么简单的情况,显然,至少需要交换 2 次就可以复位。

如果瓶子更多呢?你可以通过编程来解决。


记录每个位置的元素应该去的位置,会形成若干环。对于每个环,内部交换即可,交换次数即为 : 环的长度 - 1 。因为每次交换都会让一个位置有序,环的长度会减 -1。

cpp 复制代码
int const N = 11000;
int n, a[N], to[N], vis[N];

void solve(){
    cin >> n;
    for(int i = 1; i <= n; i ++){
        cin >> a[i];
        to[i] = a[i];
    }
    int res = 0;
    for(int i = 1; i <= n; i ++){
        if(vis[i]) continue ;
        int len = 0, now = i;
        while(vis[now] == false){
            vis[now] = true;
            len ++;
            now = to[now];
        }
        res += len - 1;
    }
    cout << res << '\n';
}

Problem Two

C-Sort4_2024牛客暑期多校训练营4 (nowcoder.com)

Given a permutation † \textstyle ^\dagger † of length n \textstyle n n. In one operation, you can choose at most four elements from the permutation and swap their positions arbitrarily. What is the minimum number of operations required to sort the permutation in ascending order?

† \textstyle ^\dagger † A permutation of length n \textstyle n n is an array consisting of n \textstyle n n distinct integers from 1 \textstyle 1 1 to n \textstyle n n in arbitrary order. For example, 2 , 3 , 1 , 5 , 4 \textstyle 2,3,1,5,4 2,3,1,5,4 is a permutation, but 1 , 2 , 2 \textstyle 1,2,2 1,2,2 is not a permutation ( 2 \textstyle 2 2 appears twice in the array), and 1 , 3 , 4 \textstyle 1,3,4 1,3,4 is also not a permutation ( n = 3 \textstyle n=3 n=3 but there is 4 \textstyle 4 4 in the array).


不用于 Problem One, 本题每次可以选 4 4 4 个元素进行位置交换。

我们还是维护交换环,可以发现如下规律 :

对于长度为 1 1 1 的交换环,不需要进行操作 ;

对于长度为 2 2 2 的交换环,可以每次处理两个 ;

对于长度 ≥ 3 \geq3 ≥3 的交换环,我们每次操作可以让环的长度减 3 3 3,直到环的长度 ≤ 4 \leq 4 ≤4 时,如果长度为 3 3 3 或 4 4 4 , 一次操作 ;长度为 2 2 2 的,统一处理即可。

cpp 复制代码
void solve(){
    int n;
    cin >> n;
    vector<int> a(n + 1), vis(n + 1), to(n + 1);
    for(int i = 1; i <= n; i ++){
        cin >> a[i];
        to[i] = a[i];
    }
    int res = 0, s = 0; // s : 2 环的数量
    for(int i = 1; i <= n; i ++){
        if(vis[i] || a[i] == i) continue ;
        int len = 0, now = i;
        while(vis[now] == false){
            len ++;
            vis[now] = true;
            now = to[now];
        }
        if(len % 3 == 2) len -= 2, s ++;
        else if(len % 3 == 1) len -= 4, res ++;
        res += len / 3;
    }
    cout << res + (s + 1) / 2 << '\n';
}
相关推荐
Kisorge3 分钟前
【电机控制器】 基于STSPIN32G4的FOC控制
stm32·嵌入式硬件·算法
Elivs16 分钟前
RMSNorm函数
人工智能·算法·机器学习
敲上瘾38 分钟前
redis常用数据类型与操作方法
数据结构·数据库·redis·缓存
tudousisi22241 分钟前
P4447 [AHOI2018初中组] 分组 题解复盘
算法
SNAKEpc1213842 分钟前
OpenGL(十一)- 变换管线
c语言·c++·算法·矩阵·图形渲染
牢姐与蒯1 小时前
c++高级数据结构之图(基本概念,存储结构,BFS,DFS,最小生成树)
数据结构·c++·
Tongzhi20261 小时前
考勤数据本地化存储:通芝科技无感考勤一体机的数据安全逻辑
大数据·数据结构·科技·均值算法·数据库开发·推荐算法
她说可以呀2 小时前
Spring-ai-Rag-多文件格式生成 List<Document>
数据结构·list
饼饼学习空间智能3 小时前
遥操作数据能否提升机器人自主化水平?详解模仿学习、仿真放大与Sim2Real闭环
人工智能·算法
间歇性努力持续性发呆的野生快乐选手3 小时前
dfs回溯,bfs枚举,完全背包
c++·算法·深度优先·宽度优先