剑指offer29题:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
首先必须注意的一点是:这道题不是考察数组的排序(所以解法1不推荐),如果N特别大的话,内存存不下;这道题正确解法是:找一个数据结构存储这K个数,如果后面的数大于这K个数的最大值,则把这个数和最大值替换。
解法一:
//解法一:自己写的,冒泡排序 //自己写的这个好像不是冒泡排序,有点像选择排序。。。。 // vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { // vector<int> result; // if(input.empty() || k==0 || k>input.size()) // { // return result; // } // //int min = input[0]; // for(int i=0;i<input.size();i++) // { // for(int j=i+1;j<input.size();j++) // { // if(input[j]<input[i]) // { // int temp; // temp = input[i]; // input[i] = input[j]; // input[j] = temp; // } // } // } // for(int i=0;i<k;i++) // { // result.push_back(input[i]); // } // return result; // }
解法2:
//解法二:牛客大佬写的,用最大堆实现,堆的大小为K,不过调用了algorithml里的make_heap这些现成的函数 //注意和解法四的区别 // vector<int> GetLeastNumbers_Solution(vector<int> input, int k) // { // if(input.empty() || k==0 || k>input.size()) // { // return vector<int>{}; // } // vector<int> result(input.begin(),input.begin()+k); // make_heap(result.begin(),result.end());//建立最大堆 // for(int i=k;i<input.size();i++) // { // if(result[0]>input[i]) // { // pop_heap(result.begin(),result.end());//把最大值移到最后一个元素 // result.pop_back(); //移除最后一个元素 // result.push_back(input[i]); // push_heap(result.begin(),result.end()); //重新选出最大值 // } // } // sort_heap(result.begin(),result.end()); // return result; // }
解法3:
//解法三:牛客大佬写的,利用自动排序的set这个数据结构,set大小为K,时间复杂度O(nlogk) //不能直接修改set容器内数据,所以只能删除某元素再插入要修改的数值。 // vector<int> GetLeastNumbers_Solution(vector<int> input, int k) // { // if(input.empty() || k==0 || k>input.size()) // { // return vector<int>{}; // } // //仿函数中的greater<T>模板,从大到小排序,首元素为最大值 // multiset<int, greater<int> > leastNums; // vector<int>::iterator vec_it=input.begin(); // for(;vec_it!=input.end();vec_it++) // { // //将前k个元素插入集合 // if(leastNums.size()<k) // leastNums.insert(*vec_it);//插入这个元素,插入时候就排好序了!!!!!!!1 // else // { // //第一个元素是最大值 // multiset<int, greater<int> >::iterator greatest_it=leastNums.begin(); // //如果后续元素<第一个元素,删除第一个,加入当前元素 // if(*vec_it<*(leastNums.begin())) // { // leastNums.erase(greatest_it);//删除首元素 // leastNums.insert(*vec_it);//插入这个元素,插入时候就排好序了!!!!!!!1 // } // } // } // return vector<int>(leastNums.begin(),leastNums.end()); // }
解法4:
//解法四:牛客大佬写的,也是最大堆实现,不过没有用algorithm里的make_heap,而是自己y用vector实现最大堆并排序 vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { if(input.empty() || k==0 || k>input.size()) { return vector<int>{}; } vector<int> result; for(int i=input.size()/2-1;i>=0;i--)//建立堆 { adjustHeap(input,i,k); //堆的大小为k } for(int i=k;i<input.size();i++)//将后面的数依次和K个数的最大值比较 { if(input[0]>input[i]) { int temp=input[i]; input[i]=input[0]; input[0]=temp; adjustHeap(input,0,k); } } for(int i=0;i<k;i++) { result.push_back(input[i]); } return result; } void adjustHeap(vector<int>&input,int i,int n)//堆调整 n为length { int left = 2*i+1; // i节点的左孩子 int right = 2*i+2; // i节点的右孩子 int largest = i; //先设置父节点和子节点三个节点中最大值的位置为父节点下标 if(left<n&&input[left]>input[largest]) { largest = left; } if(right<n&&input[right]>input[largest]) { largest = right; } if(largest!=i) //最大值不是父节点,则进行交换 { int temp; temp = input[i]; input[i] = input[largest]; input[largest] = temp; adjustHeap(input,largest,n); //递归调用,保证子树也是最大堆 } } void heapSort(vector<int>&input,int length) //堆排序 这里没用到 { for(int i=length/2-1;i>=0;i--) {//初始化堆 adjustHeap(input,i,length); } for(int i=length-1;i>0;i--) { int temp=input[i]; input[i]=input[0]; input[0]=temp; adjustHeap(input,0,i); } } };