摘要:排序算法的一些实际应用,如小和问题,逆序对问题,基于非比较排序的相邻两数最大差值问题,以及STL库自定义比较器问题。
class Sort_Use
{
public:
int Small_Sum(std::vector<int>& nums); // 小和问题
int Small_Sum1(std::vector<int>& nums);
int Reverse_Order(std::vector<int>& nums); // 逆序对问题
int Reverse_Order1(std::vector<int>& nums);
int Max_Gap(std::vector<int>& nums); // 若排序后,相邻两数最大差值,不能用非基于比较的排序
int Max_Gap1(std::vector<int>& nums);
private:
int Merge_sort(std::vector<int>& nums,int L,int R);
int Merges(std::vector<int>& nums,int L,int mid,int R);
int Reverse_Order(std::vector<int>& nums,int L,int R);
int Reverse_Order(std::vector<int>& nums,int L,int mid,int R);
};
class Student
{
private:
string name;
int age;
int Id;
public:
Student(string name,int age,int Id):name(name),age(age),Id(Id){}
string get_name()
{
return name;
}
int get_age()
{
return age;
}
int get_Id()
{
return Id;
}
};
class Order_By_Id_Asc
{
public:
bool operator() (Student& s1,Student& s2)
{
return s1.get_Id() < s2.get_Id();
}
};
class Order_By_Id_Desc
{
public:
bool operator() (Student& s1,Student& s2)
{
return s1.get_Id()>s2.get_Id();
}
};
/*********************************************
*函数功能:小和问题,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。
*参数说明
* 输入:[1,3,4,2,5]
* 输出:16
*时间复杂度:O(NlogN) 空间复杂度 O(N)
*题目来源:
*作者:guoliang zheng
*日期:2018-12-22-21.58
***********************************************/
int Sort_Use::Small_Sum(std::vector<int>& nums)
{
if(nums.size()<2) return 0;
return Merge_sort(nums,0,nums.size()-1);
}
int Sort_Use::Merge_sort(std::vector<int>& nums,int L,int R)
{
if(L>=R) return 0;
int mid=L+((R-L)>>1);
return Merge_sort(nums,L,mid)+Merge_sort(nums,mid+1,R)+Merges(nums,L,mid,R);
}
int Sort_Use::Merges(std::vector<int>& nums,int L,int mid,int R)
{
std::vector<int> help(R-L+1,0);
int res=0;
int i=L;
int j=mid+1;
int index=0;
while(i<=mid && j<=R)
{
res+=nums[i]<nums[j]?nums[i]*(R-j+1):0;
help[index++]=nums[i]<nums[j]?nums[i++]:nums[j++];
}
while(i<=mid)
{
help[index++]=nums[i++];
}
while(j<=R)
{
help[index++]=nums[j++];
}
for(int i=0;i<R-L+1;i++)
{
nums[i+L]=help[i];
}
return res;
}
/*********************************************
*函数功能:小和问题,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。
*参数说明
* 输入:[1,3,4,2,5]
* 输出:16
*时间复杂度:O(N^2) 空间复杂度 O(1)
*题目来源:
*作者:guoliang zheng
*日期:2018-12-22-21.58
***********************************************/
int Sort_Use::Small_Sum1(std::vector<int>& nums)
{
if(nums.size()<2) return 0;
int res=0;
int len=nums.size();
for(int i=1;i<len;i++)
{
for(int j=i-1;j>=0;j--)
{
if(nums[i]>nums[j])
{
res+=nums[j];
}
}
}
return res;
}
/*********************************************
*函数功能:逆序对问题,左边的数如果比右边的数大,则两个数构成一个逆序对。
*参数说明
* 输入:[8,5,4,2,7]
* 输出:7
*时间复杂度:O(NlogN) 空间复杂度 O(N)
*题目来源:
*作者:guoliang zheng
*日期:2018-12-23-09.24
***********************************************/
int Sort_Use::Reverse_Order(std::vector<int>& nums)
{
if(nums.size()<2) return 0;
return Reverse_Order(nums,0,nums.size()-1);
}
int Sort_Use::Reverse_Order(std::vector<int>& nums,int L,int R)
{
if(L>=R) return 0;
int mid=L+((R-L)>>1);
return Reverse_Order(nums,L,mid)+Reverse_Order(nums,mid+1,R)+Reverse_Order(nums,L,mid,R);
}
int Sort_Use::Reverse_Order(std::vector<int>& nums,int L,int mid,int R)
{
vector<int> help(R-L+1,0);
int res=0;
int i=L;
int j=mid+1;
int index=0;
while(i<=mid && j<=R)
{
res+=nums[i]>nums[j]?(mid-i+1):0;
help[index++]=nums[i]>nums[j]?nums[j++]:nums[i++];
}
while(i<=mid)
{
help[index++]=nums[i++];
}
while(j<=R)
{
help[index++]=nums[j++];
}
for(int k=0;k<R-L+1;k++)
{
nums[k+L]=help[k];
}
return res;
}
/*********************************************
*函数功能:逆序对问题,左边的数如果比右边的数大,则两个数构成一个逆序对。
*参数说明
* 输入:[8,5,4,2,7]
* 输出:7
*时间复杂度:O(N^2) 空间复杂度 O(N)
*题目来源:
*作者:guoliang zheng
*日期:2018-12-23-09.24
***********************************************/
int Sort_Use::Reverse_Order1(std::vector<int>& nums)
{
if(nums.size()<2) return 0;
int res=0;
int len=nums.size();
for(int i=0;i<len-1;i++)
{
for(int j=i+1;j<len;j++)
{
if(nums[i]>nums[j])
{
res++;
}
}
}
return res;
}
/*********************************************
*函数功能:给定一个数组,如果排序后,相邻两个数的最大差值,
*参数说明
* 输入:[42,61,15,36,52,4,24,50,24,54]
* 输出:12
*时间复杂度:O(N) 空间复杂度 O(N)
*题目来源:
*作者:guoliang zheng
*日期:2018-12-23-10.07
***********************************************/
int Sort_Use::Max_Gap(std::vector<int>& nums)
{
if(nums.size()<2) return 0;
int MAX=nums[0];
int MIN=nums[0];
int len=nums.size();
for(int i=1;i<len;i++)
{
MAX=max(MAX,nums[i]);
MIN=min(MIN,nums[i]);
}
if(MAX==MIN) return 0;
vector<int> max_vec(len+1,0);
vector<int> min_vec(len+1,0);
vector<bool> has_num(len+1,false);
for(int i=0;i<len;i++)
{
int pos=(nums[i]-MIN)*len/(MAX-MIN);
max_vec[pos]=has_num[pos]?max(max_vec[pos],nums[i]):nums[i];
min_vec[pos]=has_num[pos]?min(min_vec[pos],nums[i]):nums[i];
has_num[pos]=true;
}
int res=0;
int last_max=max_vec[0];
for(int i=1;i<len+1;i++)
{
if(has_num[i])
{
res=max(res,min_vec[i]-last_max);
last_max=max_vec[i];
}
}
return res;
}
/*********************************************
*函数功能:给定一个数组,如果排序后,相邻两个数的最大差值,
*参数说明
* 输入:[42,61,15,36,52,4,24,50,24,54]
* 输出:12
*时间复杂度:O(NlogN) 空间复杂度 O(1)
*题目来源:
*作者:guoliang zheng
*日期:2018-12-23-10.07
***********************************************/
int Sort_Use::Max_Gap1(std::vector<int>& nums)
{
if(nums.size()<2) return 0;
sort(nums.begin(),nums.end());
int res=INT_MIN;
int len=nums.size();
for(int i=1;i<len;i++)
{
res=max(res,nums[i]-nums[i-1]);
}
return res;
}