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

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';
}
相关推荐
刃神太酷啦10 分钟前
聚焦 string:C++ 文本处理的核心利器--《Hello C++ Wrold!》(10)--(C/C++)
java·c语言·c++·qt·算法·leetcode·github
CoovallyAIHub11 分钟前
云南电网实战:YOLOv8m改进模型攻克输电线路异物检测难题技术详解
深度学习·算法·计算机视觉
蜗牛的旷野16 分钟前
华为OD机试_2025 B卷_磁盘容量排序(Python,100分)(附详细解题思路)
python·算法·华为od
Sun_light26 分钟前
链表 --- 高效离散存储的线性数据结构
前端·javascript·算法
西西弗Sisyphus27 分钟前
低秩分解的本质是通过基矩阵和系数矩阵的线性组合,以最小的存储和计算代价近似表示复杂矩阵
线性代数·算法·矩阵
物联网嵌入式小冉学长1 小时前
10.C S编程错误分析
c语言·stm32·单片机·算法·嵌入式
Frank_zhou16 小时前
算法-链表实战【删除链表的倒数第 N 个结点】中等
数据结构
王中阳Go18 小时前
从超市收银到航空调度:贪心算法如何破解生活中的最优决策谜题?
java·后端·算法
故事挺秃然19 小时前
中文分词:机械分词算法详解与实践总结
算法·nlp
车队老哥记录生活21 小时前
【MPC】模型预测控制笔记 (3):无约束输出反馈MPC
笔记·算法