算法复习:快排

leedcode 215. 数组中的第K个最大元素

快排每次寻找都会确定一个元素的真实位置

快排的思想:

先定第一个位置是坑,取出第一个位置的值作为最终要确定位置的值,设置up指针和down指针

由于一开始坑的位置和up重合,直接判断坑的值和down的值大小,此时坑>down需要换坑位置,交换以后down的值付给原来的坑,新坑的位置和down重合,up后移一个

再比较,up<坑,继续后移up一个单位;此时up>坑,需要换坑的位置,此时的up值赋给旧坑,up的位置变成新坑,以此类推。

快排双指针挖坑法,递归代码:

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<stdlib.h>
#include<set>
#include<map>
using namespace std;
#define MAX 999999
#define CLR(arr,what) memset(arr,what,sizeof(arr))
void make_sit(vector<int>&donser,int start,int end)
{
    if(start==end)
        return ;
    int str_x=start,str_y=end,pare=donser[start];//str_x头指针 str_y尾指针 pares坑值
    int lable=0;//=0指示坑在前 =1指示坑在后
    while(str_x!=str_y)
    {
        if(lable==0)
        {
            if(pare<=donser[str_y])
            {
                str_y--;
                continue;
            }
            else
            {
                lable=1;//坑移到后面
                donser[str_x]=donser[str_y];
                donser[str_y]=pare;
                str_x++;
                continue;
            }
        }
        else if(lable==1)
        {
            if(pare>=donser[str_x])
            {
                str_x++;
                continue;
            }
            else
            {
                lable=0;//坑移到前面
                donser[str_y]=donser[str_x];
                donser[str_x]=pare;
                str_y--;
                continue;
            }
        }
    }
    //此时str_x==str_y正是确定了位置的一个元素,递归
    if(start<=str_x-1)
        make_sit(donser,start,str_x-1);
    if(str_x+1<=end)
        make_sit(donser,str_x+1,end);
    return;
}

void quick_sort(vector<int>&donser)//从小到大排
{
    int start=0,end=donser.size()-1;
    make_sit(donser,start,end);
    return;
}

int main()
{
    vector<int>donser;
    int N;
    cin>>N;
    while(N--)
    {
        int tmp;
        cin>>tmp;
        donser.push_back(tmp);
    }
    quick_sort(donser);
    for(int i=0;i<donser.size();i++)
        cout<<donser[i];
    cout<<endl;
    return 0;
}

/*
5
5 9 3 4 6
*/
快排递归实现
void quick_sort(vector<int>&num,int start,int end)
{
    int head=start,tail=end,hole=start;//头指针 尾指针 坑 。初始 head=start,tail=end,hole=start
    int tmp_cmp=num[hole];//取出第一个坑处元素值//坑可能在头处,可能在尾处,初始在头处
    while(head<tail)//终止条件
    {
        if(hole==head)//坑在头处,和尾指针比较
        {
            if(tmp_cmp>num[tail])//tail处小,交换坑的位置
            {
                num[hole]=num[tail];
                hole=tail;
                head++;
            }
            else//tail处大,移动tail的位置
            {
                tail--;
            }
        }
        else if(hole==tail)//坑在尾处,和头指针比较
        {
            if(tmp_cmp<num[head])//head处大,交换坑的位置
            {
                num[hole]=num[head];
                hole=head;
                tail--;
            }
            else//head处小,移动head的位置
            {
                head++;
            }
        }
    }
    num[head]=tmp_cmp;
    //此时确认head==tail处正是这一个元素的真实位置,借此二分继续查找
    if(start<=head-1)
        quick_sort(num,start,head-1);
    if(head+1<=end)
        quick_sort(num,head+1,end);
    return;
}
单独的qsort函数

215. 数组中的第K个最大元素

class Solution {
public:
    int deal(int donser[],int k,int num)
    {
        int up,down,out,sit,*lable;
        lable=new int[num];
        for(int ii=0;ii<num;ii++)
            lable[ii]=0;
        while(1)
        {
            up=0;//找up down位置
            down=num-1;
            for(int i=0;i<num;i++)
            {
                if(lable[i]==0)
                {
                    up=i;
                    break;
                }
            }
            for(int i=num-1;i>0;i--)
            {
                if(lable[i]==0)
                {
                    down=i;
                    break;
                }
            }
            out=donser[up];//要确定位置的值
            sit=up;//
            while(up<down)
            {
                if(sit==up)
                {
                    if(out<=donser[down])
                    {
                        down--;
                        continue;
                    }
                    if(out>donser[down])
                    {
                        donser[sit]=donser[down];
                        donser[down]=out;
                        sit=down;
                        up++;
                        continue;
                    }
                }
                else if(sit==down)
                {
                    if(out>=donser[up])
                    {
                        up++;
                        continue;
                    }
                    if(out<donser[up])
                    {
                        donser[sit]=donser[up];
                        donser[up]=out;
                        sit=up;
                        down--;
                        continue;
                    }
                }
            }
            lable[sit]=1;
            if(sit==num-k)
                break;
        }
        return donser[sit];
    }
    int findKthLargest(vector<int>& nums, int k) {
        int i=nums.size(),*donser;
        donser=new int[i];
        for(int c=0;c<i;c++)
            donser[c] = nums[c];
        if(i==1)
            return donser[0];
        return deal(donser,k,i);
    }
};
leedcode 215

 快速实现代码:

#include<algorithm>
#include<string.h>
int qsor(const void *a,const void *b)
{
    return *(int *)a-*(int *)b;
}
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        int i=nums.size(),*donser;
        donser=new int[i];
        for(int c=0;c<i;c++)
            donser[c] = nums[c];
        qsort(donser,i,sizeof(int),qsor);
        return donser[i-k];
    }
};
View Code

 结构体的快排实现

#include<algorithm>
#include<string.h>
#include<stdlib.h>
struct donser
{
    int i;
    int j;
};
int qsor(const void* a,const void*b)
{
    return (*(donser *)a).i-(*(donser *)b).i;
}
......
struct donser my[1000];
......
qsort(my,ii*2,sizeof(donser),qsor);
View Code

leetcode 面试题45. 把数组排成最小的数

自定义快排的比较规则

#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<string>
int cmp(const void * a,const void * b)
{
    int len_a=0,len_b=0,tmp_a=*(int *)a,tmp_b=*(int *)b;
    if(tmp_a==0||tmp_b==0)//先判断防止出现0
        return tmp_a-tmp_b;
    stack<char>aa,bb;
    //求出a和b的位数 每一位压栈
    while(tmp_a!=0)
    {
        aa.push((tmp_a-(tmp_a/10)*10)+'0');
        tmp_a/=10;
        len_a++;
    }
    while(tmp_b!=0)
    {
        bb.push((tmp_b-(tmp_b/10)*10)+'0');
        tmp_b/=10;
        len_b++;
    }
    //把aa和bb比较,位数不足的用首数字补全
    char A_start=aa.top(),B_start=bb.top();
    while(aa.size()||bb.size())
    {
        char A=A_start;
        if(aa.size())
        {
            A=aa.top();
            aa.pop();
        }
        char B=B_start;
        if(bb.size())
        {
            B=bb.top();
            bb.pop();
        }
        if(A==B)
            continue;
        return A-B;
    }
    //长度不同但是补齐以后相同,单独比较
    long tp_a=*(int *)a;
    for(int i=0;i<len_b;i++)
        tp_a*=10;
    tp_a+=*(int *)b;
    long tp_b=*(int *)b;
    for(int i=0;i<len_a;i++)
        tp_b*=10;
    tp_b+=*(int *)a;
    return tp_a-tp_b;
}
class Solution {
public:
    string minNumber(vector<int>& nums) {
        //int tmp[101];
        for(int i=0;i<nums.size();i++)
            tmp[i]=nums[i];
        qsort(tmp,nums.size(),sizeof(int),cmp);//自定义比较函数
        string result="";
        for(int i=0;i<nums.size();i++)
        {
            result+=to_string(tmp[i]);
        }
        return result;
    }
};
leetcode 45

 想多了,根本不需要换成字符然后比较,直接补全成两串数字

#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<string>
int cmp(const void * a,const void * b)
{
    int len_a=0,len_b=0,tmp_a=*(int *)a,tmp_b=*(int *)b;
    if(tmp_a==0||tmp_b==0)//先判断防止出现0
        return tmp_a-tmp_b;
    //求出a和b的位数 每一位压栈
    while(tmp_a!=0)
    {
        tmp_a/=10;
        len_a++;
    }
    while(tmp_b!=0)
    {
        tmp_b/=10;
        len_b++;
    }
    //长度不同但是补齐以后相同,单独比较
    long tp_a=*(int *)a;
    for(int i=0;i<len_b;i++)
        tp_a*=10;
    tp_a+=*(int *)b;
    long tp_b=*(int *)b;
    for(int i=0;i<len_a;i++)
        tp_b*=10;
    tp_b+=*(int *)a;
    return tp_a-tp_b;
}
class Solution {
public:
    string minNumber(vector<int>& nums) {
        int tmp[101];
        for(int i=0;i<nums.size();i++)
            tmp[i]=nums[i];
        qsort(tmp,nums.size(),sizeof(int),cmp);//自定义比较函数
        string result="";
        for(int i=0;i<nums.size();i++)
        {
            result+=to_string(tmp[i]);
        }
        return result;
    }
};
leetcode 45

优先队列和堆

优先队列有三个参数,其声明形式为:

priority_queue< type, container, function >

成员函数
假设type类型为int,则:

bool empty() const
返回值为true,说明队列为空;
int size() const
返回优先队列中元素的数量;
void pop()
删除队列顶部的元素,也即根节点
int top()
返回队列中的顶部元素,但不删除该元素;
void push(int arg)
将元素arg插入到队列之中;

大顶堆
//构造一个空的优先队列(此优先队列默认为大顶堆) priority_queue<int> big_heap;
//另一种构建大顶堆的方法 priority_queue<int,vector<int>,less<int> > big_heap2;
小顶堆
//构造一个空的优先队列,此优先队列是一个小顶堆 priority_queue<int,vector<int>,greater<int> > small_heap;

需要注意的是,如果使用less<int>greater<int>,需要头文件:

  • #include <functional>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;

class Solution
{
public:
    int findKthLargest(vector<int> &nums, int k)
    {
        int result = 0;
        int numsSize = int(nums.size());
        if (numsSize == 0 || k > numsSize)
        {
            return 0;
        }

        priority_queue<int, vector<int>, greater<int>> store;
        //堆中维持k个最大数
        for (int i = 0; i < numsSize; i++)
        {
            store.push(nums[i]);
            if (int(store.size()) > k)
            {
                store.pop();
            }
        }

        result = store.top();
        return result;
    }
};
再解K-max


原文地址:https://www.cnblogs.com/dzzy/p/12241585.html