C++逆序数(奇排列和偶排列的判定)

逆序数是判断排列性质的关键,奇数逆序数对应奇排列,偶数则对应偶排列。例如,序列53124的逆序数为6,故为偶排列。归并排序可用于优化逆序数计算,通过合并有序子序列时累加逆序数,达到O(n*log2(n))的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

逆序数简介

在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。一个排列中所有逆序总数叫做这个排列的逆序数。也就是说,对于n个不同的元素,先规定各元素之间有一个标准次序(这里规定从小到大为标准次序),于是在这n个元素的任一排列中,当某两个元素的先后次序与标准次序不同时,就说有1个逆序。一个排列中所有逆序总数叫做这个排列的逆序数。

而逆序数就是判定一个排列为奇排列还是偶排列的重点。如果逆序数为奇数,则此排列为奇排列,否则为偶排列。

举个例子,看53124这个序列,5在3前面,5在1前面,5在2前面,5在4前面,3在1前面,3在2前面,逆序数为6,故此排列为偶排列。

逆序数计算

如果直接模拟的话时间复杂度为On^2,但代码就简单的多了,可如果你想优化时间,那么就得使用到归并排序了。

:如果你尚未学习过归并排序,可以浏览此网页来学习
https://blog.youkuaiyun.com/SkeletonKing233/article/details/100676151

而逆序数的计算在我们将两个子序列合并的时候累加就可以了。

举个例子,如果我们要将这两个子序列合并的话
1,4,6,7,9
2,3,5,10,13,21
当第一个序列枚举到第2个元素4,第二个序列枚举到第1个元素2时,4 > 2为逆序,我们需要进行累加,又因为两个子序列都是有序的所以如果4 > 2,那么第一个子序列从第2个元素4开始后面的所有数都必然比2大,所以让逆序数的值加上(mid - i + 1),既从第2个元素到第5个元素中元素的个数。这样时间复杂度就减少为On * log2(n)级别的了。

# include <cstdio>
# include <iostream>
# include <cmath>
# include <cstring>
# include <algorithm>
using namespace std;

# define FOR(i, a, b) for(int i = a; i <= b; i++)
# define _FOR(i, a, b) for(int i = a; i >= b; i--)

const int NR = 
### 如何在 C++ 中对字符串进行排序 在 C++ 中,可以利用标准库中的 `<algorithm>` 头文件来实现字符串的排序功能。具体来说,`std::sort()` 是种高效且常用的算法工具,用于对数组或容器内的数据进行排序。 #### 使用 `std::sort()` 对字符数组进行排序 如果目标是对单个字符串的内容按字典顺序重新排列,则可以直接调用 `std::sort()` 函数处理该字符串内部的数据[^2]: ```cpp #include <iostream> #include <algorithm> // std::sort() int main() { std::string str = "programming"; // 调用 std::sort 排序整个字符串 std::sort(str.begin(), str.end()); std::cout << "Sorted string: " << str << std::endl; return 0; } ``` 上述代码通过指定范围 `[str.begin(), str.end())` 来操作字符串的所有字符,并将其按照字母升序排列。 #### 字符串向量的排序 当面对多个独立字符串组成的集合时(例如存储于 `std::vector<std::string>` 的情况),同样可借助 `std::sort()` 实现整体排序。默认情况下,它会依据 ASCII 或 Unicode 编码比较两个字符串之间的大小关系: ```cpp #include <iostream> #include <vector> #include <algorithm> int main() { std::vector<std::string> words = {"banana", "apple", "cherry"}; // 默认按字典顺序排序 std::sort(words.begin(), words.end()); for (const auto& word : words) { std::cout << word << "\n"; } return 0; } ``` 此示例展示了如何基于自然词法次序整理组单词列表。 #### 自定义排序规则 除了依赖内置行为外,还可以提供自定义比较函数作为第三个参数传递给 `std::sort()` ,从而改变原有的判定准则。比如下面的例子实现了忽略大小写的降序排列方式: ```cpp #include <iostream> #include <vector> #include <algorithm> #include <cctype> // toupper() bool caseInsensitiveCompare(const std::string& lhs, const std::string& rhs){ size_t minSize = std::min(lhs.size(), rhs.size()); for(size_t i=0; i<minSize; ++i){ char c1 = std::toupper(static_cast<unsigned char>(lhs[i])); char c2 = std::toupper(static_cast<unsigned char>(rhs[i])); if(c1 != c2) return c1 > c2 ; } return lhs.size() > rhs.size(); } int main(){ std::vector<std::string> fruits{"Orange","Apple","Banana"}; std::sort(fruits.begin(),fruits.end(),caseInsensitiveCompare); for(auto fruit : fruits){ std::cout<<fruit<<"\n"; } return 0; } ``` 这里创建了一个名为 `caseInsensitiveCompare` 的辅助布尔型函数,用来逐位对比两输入项间是否存在差异;旦发现不同之处即刻返回相应判断结果。最终输出显示所有项目均被转换成大写形式后再做逆序展示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值