#include <iostream>
#include <vector>
#include <list>
#include <string>
#include <unordered_map>
#include <unordered_set>
using namespace std;
void swap(vector<int>& nums,int i , int j)
{
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
void print(const vector<int>& nums)
{
for(auto num : nums)
{
cout << num << " ";
}
cout << endl;
}
vector<int> bubbleSort(const vector<int>& v)
{
vector<int>nums = v;
int n = nums.size();
for(int i = 0; i < n - 1; ++i)
{
for(int j = 0; j < n - 1 - i ; ++j)
{
if(nums[j] > nums[j + 1])
{
swap(nums,j,j + 1);
}
}
}
return nums;
}
vector<int> selectSort(const vector<int>& v)
{
vector<int>nums = v;
int n = nums.size();
for(int i = 0; i < n - 1; ++i)
{
int minIndex = i;
for(int j = i + 1; j < n; ++j)
{
if(nums[minIndex] > nums[j])
{
minIndex = j;
}
}
swap(nums,minIndex,i);
}
return nums;
}
vector<int>insertSort(const vector<int>& v)
{
vector<int>nums=v;
int n = nums.size();
for(int i = 0; i < n; ++i)
{
int tmp = nums[i];
int j = i;
while(j > 0 && tmp < nums[j-1])
{
nums[j] = nums[j-1];
--j;
}
nums[j] = tmp;
}
return nums;
}
vector<int>shellSort(const vector<int>& v)
{
int n = v.size();
vector<int>nums=v;
for(int gap = n / 2; gap > 0; gap /= 2)
{
for(int i = gap;i < n; ++i)
{
int tmp = nums[i];
int j = i;
while(nums[j-gap] > tmp)
{
nums[j] = nums[j-gap];
j-=gap;
}
nums[j] = tmp;
}
}
return nums;
}
int partition(vector<int>&nums,int left,int right)
{
int pivot = nums[right];
int start = left,end = right - 1;
while(start <= end)
{
if(nums[start] <= pivot)++start;
else if(nums[end] > pivot)--end;
else swap(nums,start++,end--);
}
swap(nums,start,right);
return start;
}
void helper(vector<int>&nums,int left,int right)
{
if(left > right)return;
int pivot = partition(nums,left,right);
helper(nums,left,pivot-1);
helper(nums,pivot+1,right);
}
vector<int> quickSort(const vector<int>& v)
{
vector<int>nums = v;
int n = nums.size();
helper(nums,0,n-1);
return nums;
}
vector<int>merge(vector<int>&n1,vector<int>&n2)
{
vector<int>res(n1.size() + n2.size());
int i = 0, j = 0, k = 0;
while(i < n1.size() && j < n2.size())
{
if(n1[i] <= n2[j])res[k++] = n1[i++];
else res[k++] = n2[j++];
}
while(i < n1.size())res[k++] = n1[i++];
while(j < n2.size())res[k++] = n2[j++];
return res;
}
vector<int>divide(vector<int>& nums,int left,int right)
{
if(left >= right)return {nums[left]};
int mid = left + (right - left) / 2;
vector<int> leftRes = divide(nums,left,mid);
vector<int> rightRes = divide(nums,mid+1,right);
return merge(leftRes,rightRes);
}
vector<int> mergeSort(const vector<int>& v)
{
vector<int>nums=v;
int n = nums.size();
return divide(nums,0,n-1);
}
void heapify(vector<int>& nums,int n, int i)
{
int largest = i;
int l = 2 * i + 1;
int r = 2 * i + 2;
if(l < n && nums[l] > nums[largest])
{
largest = l;
}
if(r < n && nums[r] > nums[largest])
{
largest = r;
}
if(largest != i)
{
swap(nums,i,largest);
heapify(nums,n,largest);
}
}
vector<int> heapSort(const vector<int>& v)
{
vector<int> nums = v;
int n = nums.size();
for(int i = n / 2 - 1; i >= 0; --i)
{
heapify(nums,n,i);
}
for(int i = n - 1; i >= 0; --i)
{
swap(nums,i,0);
heapify(nums,i,0);
}
return nums;
}
vector<int>CountSort(const vector<int>& v)
{
vector<int> nums = v;
int n = nums.size();
vector<int>output(n);
int maxVal = * max_element(nums.begin(),nums.end());
vector<int>cnt(maxVal,0);
for(int num:nums)
{
++cnt[num];
}
for(int i = 1; i <= maxVal; ++i)
{
cnt[i] += cnt[i-1];
}
for(int i = n - 1; i >= 0; --i)
{
output[cnt[nums[i]] - 1] = nums[i];
--cnt[nums[i]];
}
return output;
}
void CountSort(vector<int>& nums,int n, int exp)
{
vector<int>output(n,0);
int i = 0;
vector<int>cnt(10,0);
for(int i = 0; i < n; ++i)
{
++cnt[nums[i] / exp % 10];
}
for(int i = 1; i < 10; ++i)cnt[i] += cnt[i-1];
for(int i = n - 1; i >= 0; --i)
{
output[cnt[nums[i] / exp % 10] - 1] = nums[i];
--cnt[nums[i]/exp % 10];
}
nums = output;
}
vector<int>radixSort(const vector<int>& v)
{
vector<int> nums = v;
int m = * max_element(nums.begin(),nums.end());
int exp = 1;
while(m / exp > 0)
{
CountSort(nums,nums.size(),exp);
exp *= 10;
}
return nums;
}
vector<int> bucketSort(const std::vector<int> &nums)
{
// 思想:
// 桶排序是计数排序的一个优化,它解决了计数排序只适用于整数排序的限制,更是解决了不适用于最大值和最小值差值很大的情况.
// 桶排序的思想就是对最小值和最小值之间的元素进行瓜分,将他们分为多个区间,每个区间用一个桶(其实就是一个容器)来装.
// 前一个桶里的元素全都小于后一个桶里的元素,只需要利用别的常规排序算法将桶里面的元素进行排序使之有序即可使得原序列有序.
// 这里我们使用快速排序对桶内的元素进行排序.
// 1.遍历待排序序列获取其中最大值和最小值,并计算他们的差值d.
vector<int>data = nums;
int max = data[0];
int min = data[0];
for(int i = 1; i < data.size(); i++)
{
if(max < data[i])
{
max = data[i];
}
if(min > data[i])
{
min= data[i];
}
}
int d = max - min;
// 2.初始化桶,桶因为要频繁插入元素,所以用List数据结构,然后所有的桶放在vector容器中.
std::vector<std::list<int>> bucket_list;
// 我们将桶的个数设置为原序列元素个数.
int bucket_num = data.size();
bucket_list.resize(bucket_num);
// 3.遍历原序列,将元素放到合适的桶中.
for(int value : data)
{
// 定位元素所属的桶的索引.
// 桶所有的桶平均划分最大值和最小值d的区间,value-min是当前元素与最小值的差值(区间).
// bucket_num-1是总的区间个数,则d/(bucket_num-1)代表一个区间的长度.
// 那么整个表达式得到的index则为当前元素value所跨越的区间个数,也就是当前元素所在的桶的索引.
int index = (value-min)/(d/(bucket_num-1));
// 将当前元素放进桶里面去.
bucket_list.at(index).push_back(value);
}
// 4.对每个桶进行排序,我们采用快速排序.
// 依次将每个桶里的元素排好序后放入sorted_sequence中.
std::vector<int> sorted_sequence;
for(auto bucket : bucket_list)
{
// 因为我们之前写的快排是对vector<int>进行排序,所以我们使用一个辅助容器.
// 我们完全可以重新写一个针对list<int>的快排算法,这样会提高时间和空间复杂度,此处我们就使用现成的.
std::vector<int> auxiliary;
auxiliary.assign(bucket.begin(),bucket.end());
sort(auxiliary.begin(),auxiliary.end());
// 将当前桶内元素排好序后放入sorted_sequence容器尾部.
sorted_sequence.insert(sorted_sequence.end(),auxiliary.begin(),auxiliary.end());
}
// 5.将有序序列赋给data.
data = sorted_sequence;
return data;
}
void divide(vector<int>& nums, int left,int right,int k)
{
if(left >= right)return ;
int pivot = partition(nums,left,right);
if(pivot == nums.size() - k)return;
else if(pivot < nums.size() - k)divide(nums,pivot + 1,right,k);
else divide(nums,left,pivot-1,k);
}
int findKthLargest(const vector<int>& nums,int k)
{
vector<int>v = nums;
divide(v,0,v.size() - 1,k);
return v[v.size()-k];
}
void sortColors(vector<int>& colors)
{
int cnt0 = 0, cnt1 = 0, cnt2 = 0;
for(int i = 0; i < colors.size(); ++i)
{
if(0 == colors[i]) ++cnt0;
if(1 == colors[i]) ++cnt1;
if(2 == colors[i]) ++cnt2;
}
for(int i = 0; i < colors.size(); ++i)
{
if(i < cnt0) colors[i] = 0;
else if(i < cnt0 + cnt1) colors[i] = 1;
else colors[i] = 2;
}
return ;
}
string frequencySort(string s)
{
unordered_map<char,int>map;
unordered_set<char>set;
for(char c: s)
{
set.insert(c);
++map[c];
}
vector<string>bucket(s.size() + 1,"");
for(char c: set)
{
int freq = map[c];
bucket[freq].push_back(c);
}
string res = "";
for(int i = bucket.size() - 1; i >= 0; --i)
{
if(bucket[i].size() != 0)
{
for(char c : bucket[i])
{
for(int m = 0; m < i; ++m)
{
res.push_back(c);
}
}
}
}
return res;
}
int maxGap(vector<int>& nums)
{
if(nums.size() < 2) return 0;
int m = *(max_element(nums.begin(),nums.end()));
int exp = 1;
int R = 10;
vector<int>aux(nums.size());
while(m / exp > 0)
{
vector<int>cnt(R);
for(int i = 0; i < nums.size(); ++i)++cnt[(nums[i]/exp % 10)];
for(int i = 1; i < cnt.size(); ++i)cnt[i]+=cnt[i-1];
for(int i = nums.size() - 1;i >= 0; --i)
{
aux[--cnt[(nums[i]/exp)%10]]=nums[i];
}
for(int i = 0; i < nums.size(); ++i)
{
nums[i] = aux[i];
}
exp *= 10;
}
int res = 0;
for(int i = 1; i < aux.size(); ++i)
{
res = max(res,aux[i] - aux[i-1]);
}
return res;
}
vector<int> pancakeSort(vector<int>& arr) {
vector<int> ret;
for (int n = arr.size(); n > 1; n--) {
int index = max_element(arr.begin(), arr.begin() + n) - arr.begin();
if (index == n - 1) {
continue;
}
reverse(arr.begin(), arr.begin() + index + 1);
reverse(arr.begin(), arr.begin() + n);
ret.push_back(index + 1);
ret.push_back(n);
}
return ret;
}
int main()
{
//排序
vector<int>nums{3,345,6,3,3};
print(bubbleSort(nums));
print(selectSort(nums));
print(insertSort(nums));
print(shellSort(nums));
print(quickSort(nums));
print(mergeSort(nums));
print(heapSort(nums));
print(CountSort(nums));
print(radixSort(nums));
print(bucketSort(nums));
//LeetCode215
nums = {3,2,1,5,6,4};
int k = 2;
cout << findKthLargest(nums,k) << endl;
//LeetCode75
nums = {2,0,2,1,1,0};
sortColors(nums);
print(nums);
//LeetCode451
string s = "tree";
cout << frequencySort(s) << endl;
//LeetCode164
nums = {3,6,9,1};
cout << maxGap(nums) << endl;
//LeetCode969
cout << "====" << endl;
vector<int>arr{3,2,4,1};
print(pancakeSort(arr));
return 0;
}