|
|
发表于 2026-9-24 01:04:02
From FishC Mobile
|
显示全部楼层
|阅读模式
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
试试
按你的思路,把“已在正确位置(offset == 0)直接跳过、绝不执行无效自我交换”的逻辑写在最前面,代码非常干净利落:
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <iostream>
void osps_sort(std::vector<int>& arr) {
int n = arr.size();
if (n <= 1) return;
// 1. 统计频次
std::unordered_map<int, int> counts;
for (int num : arr) {
counts[num]++;
}
// 2. 提取并排序不重复的 Key
std::vector<int> unique_keys;
for (auto& pair : counts) {
unique_keys.push_back(pair.first);
}
std::sort(unique_keys.begin(), unique_keys.end());
// 3. 构建目标映射地图(前缀和)
std::unordered_map<int, int> target_map;
int cumulative = 0;
for (int key : unique_keys) {
target_map[key] = cumulative;
cumulative += counts[key]; // 预留重复元素空间
}
// 4. 精准置换(严格排除自交换)
int i = 0;
while (i < n) {
int val = arr[i];
int target_idx = target_map[val];
// 计算绝对差距 Offset
int offset = target_idx - i;
if (offset == 0) {
// 【核心优化】:位置完全正确,绝不自己跟自己交换,直接跳过看下一个
i++;
} else {
// 只有当目标位置不同时,才触发真正的物理 Swap
std::swap(arr[i], arr[target_idx]);
// 目标指针递增(消解重复值冲突)
target_map[val]++;
// 当前位置 i 换来了新元素,不递增 i,继续检查新换来的元素
}
}
}
int main() {
std::vector<int> data = {4, 2, 1, 4, 3, 2, 5, 1};
osps_sort(data);
for (int num : data) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
这次重写明确的逻辑流:
* 优先检查就位状态:一旦发现 offset == 0,算法直接触发 i++ 跳过,连 Swap 内存指令的边都不触碰。
* 零垃圾指令:所有的物理交换(std::swap)只发生在 i != target_idx 的异位元素之间,把无用功降到了绝对的 0。
|
|