目录
* for循环去重元素
for 循环去重的思路在于找出首次出现的唯一元素,然后按照顺序查找是否有重复。该方法适合小规模,大规模需要使用桶排序或哈希表。双重 for 循环如下代码:
cpp
#include <iostream>
using namespace std;
int main()
{
int a[] = {64,12,64,11,30,3,95,0,40,0,9};
int n = sizeof(a) / sizeof(a[0]); // 计算数组长度
cout << a[0] << " "; // 先输出第一个元素
for(int i = 1; i < n; i++) // 从第二个元素开始遍历,即 i = 1开始
{
int temp = a[i]; // temp 是当前要检查的元素
for(int j = i-1; j >= 0; j--) // 向左查找是否已经出现过相同的元素
{
if(temp==a[j]){
break; // 如果前面有相同的元素,则跳出循环
}
if(temp!=a[j] && j==0){ // 如果查找到最前面(j==0)都没找到相同的,则输出当前元素
cout << temp << " ";
}
}
}
return 0;
}
时间复杂度 :
(1)最坏时间复杂度:无重复元素,每次循环需要比较前 i - 1 个元素,例如数组:a[ ] = {1, 2, 3, 4, 5}:
i = 1,需要比较 a[1] = 2 和 a[0] = 1,即 1 次比较。
i = 2,需要比较 a[2] = 3 和 a[1] = 2、a[0] = 1,即 2 次比较。
......
比较次数 = 1 + 2 + ... + (n - 1) = (1 + (n - 1) )n / 2 = n (n - 1) / 2。
所以,最坏时间复杂度为 O(n2)。
(2)最好时间复杂度:
最坏时间复杂度:所有元素重复,每次循环 1 次比较就 break 退出循环。
比较次数 = n - 1 。
所以,最好时间复杂度为 O(n)。
(3)平均时间复杂度:
关注最高阶项,忽略常数和低阶项,所以平均时间复杂度为 O(n2)。
空间复杂度:O(1)
一、桶排序的效率
桶是一种空间换时间(占用更多内存,但速度快)的数据结构思想,通过下标映射元素值,一次访问即可完成检查。每个桶内的排序可以选择不同的算法,例如,插入排序、快速排序、归并排序等。最后,再将所有桶合并。
要注意,桶排序和堆排序不是一个概念,桶排序是 " 分桶排序合并 ",堆排序是 " 建堆取最值调整 "(完全二叉树)。另外,桶排序也不属于严格意义上的分治法,桶排序是" 分桶排序合并 ",而分治法是 "分治合"。
之前通过双层 for 循环去重元素,平均时间复杂度是 O(n2) ,效率低;而通过桶排序平均时间复杂度可以达到 O(n + k)(k为桶数量),效率高。
桶排序所需空间复杂度为 O(n+k),n 是每个桶内存储元素的平均时间, k 是桶所需空间。
桶排序不适合数据范围很大的情况,以免设置桶的数量过多。此外,如果数据元素分布不均匀,桶排序效率会下降,例如,当所有元素都集中在少数几个桶或集中在一个桶时,时间复杂度是 O(n2) 。
二、分桶过程
桶排序常结合数组、vector、链表等实现,桶数量由值域范围和桶大小决定。
桶数量 = (最大值 - 最小值) / 桶大小 + 1
例如,通过桶排序方式:
cpp
int a[] = {4,40,44,49,75,40,10,38,1,29};
最小值为 1 ,最大值为 75 ,假设每个桶大小为 10 ,则需要 8 个桶:
桶数量 = (75-1)/10 + 1 = 8
cpp
vector<vector<int>> buckets(8);
每个桶装的元素如下,进行分配:

然后,进行每个桶内排序,如果桶内元素较少可以使用【插入排序】,元素较多使用【快速排序】或【归并排序】:

最终合并结果:
1, 4, 10, 29, 38, 40, 40, 44, 49, 75
示例代码如下,最后用 sortedArr 数组存储排序后的结果,遍历该数组输出:
cpp
#include <iostream>
using namespace std;
int main()
{
int arr[] = {70,31,88,1,55,42,7,38,13,49,95,16,25,9,29,38,5,35,22,66};
int n = sizeof(arr) / sizeof(arr[0]); // 计算原数组元素个数
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
// 手动找出数组中的最大值(确定桶的遍历范围)
int maxVal = arr[0];
for (int i = 1; i < n; i++) {
if (arr[i] > maxVal) {
maxVal = arr[i];
}
}
// 创建桶数组
int bucket[1001] = {0}; // 初始化为0
// 统计每个数字出现的次数
for (int i = 0; i < n; i++) {
bucket[arr[i]]++;
}
// 按顺序存入排序结果数组
int sortedArr[100] = {0}; // 存储排序后的结果
int sortedLen = 0; // 记录排序后的元素个数
for (int i = 0; i <= maxVal; i++) {
// 按出现次数添加到结果数组
while (bucket[i] > 0) {
sortedArr[sortedLen] = i;
sortedLen++;
bucket[i]--;
}
}
for (int i = 0; i < sortedLen; i++) {
cout << sortedArr[i] << " ";
}
return 0;
}