• 算法复习:快排


    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
    
    
    
  • 相关阅读:
    Python3练习题系列(02)
    英语口语学习笔记(09)
    Python3练习题系列(01)
    (转)chm格式的电子书打开是空白的解决办法
    SQL Server 创建链接服务器
    (转)js正则表达式之中文验证
    (转)SQL语句中的N'xxxx'是什么意思
    (转)C#之玩转反射
    (转)抽象工厂学习笔记
    (转)单例模式(Singleton)
  • 原文地址:https://www.cnblogs.com/dzzy/p/12241585.html
Copyright © 2020-2023  润新知