利用排序算法解决的一些问题(C++实现)

 摘要:排序算法的一些实际应用,如小和问题,逆序对问题,基于非比较排序的相邻两数最大差值问题,以及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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值