算法复习:快排
leedcode 215. 数组中的第K个最大元素
快排每次寻找都会确定一个元素的真实位置
快排的思想:
先定第一个位置是坑,取出第一个位置的值作为最终要确定位置的值,设置up指针和down指针
由于一开始坑的位置和up重合,直接判断坑的值和down的值大小,此时坑>down需要换坑位置,交换以后down的值付给原来的坑,新坑的位置和down重合,up后移一个
再比较,up<坑,继续后移up一个单位;此时up>坑,需要换坑的位置,此时的up值赋给旧坑,up的位置变成新坑,以此类推。
快排双指针挖坑法,递归代码:
#include快排递归实现#include #include<string> #include #include #include<set> #include
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单独的qsort函数//终止条件 { 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 //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; }
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;iileedcode 215) lable[ii]=0; while(1) { up=0;//找up down位置 down=num-1; for(int i=0;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) donser[c] = nums[c]; if(i==1) return donser[0]; return deal(donser,k,i); } };
快速实现代码:
#include#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) donser[c] = nums[c]; qsort(donser,i,sizeof(int),qsor); return donser[i-k]; } };
结构体的快排实现
#include#include<string.h> #include 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);
leetcode 面试题45. 把数组排成最小的数
自定义快排的比较规则
#include<string.h> #includeleetcode 45#include #include #include #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 ) tp_a*=10; tp_a+=*(int *)b; long tp_b=*(int *)b; for(int i=0;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 ) tmp[i]=nums[i]; qsort(tmp,nums.size(),sizeof(int),cmp);//自定义比较函数 string result=""; for(int i=0;i ) { result+=to_string(tmp[i]); } return result; } };
想多了,根本不需要换成字符然后比较,直接补全成两串数字
#include<string.h> #includeleetcode 45#include #include #include #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 ) tp_a*=10; tp_a+=*(int *)b; long tp_b=*(int *)b; for(int i=0;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 ) tmp[i]=nums[i]; qsort(tmp,nums.size(),sizeof(int),cmp);//自定义比较函数 string result=""; for(int i=0;i ) { result+=to_string(tmp[i]); } return result; } };
优先队列和堆
优先队列有三个参数,其声明形式为:
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
和greater
,需要头文件:
#include
#include再解K-max#include #include #include 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; } };