输入n个整数,找出其中最小的k个数。例如输入 输出示例: 需要对输入合法性进行校验。 思路:采用排序算法进行查找。三种方法:①普通排序(如冒泡排序),②快排,③堆排序。 注:由于题目只需找到最小的k个数,因此无需对所有元素进行排序,只需冒泡得到最小的k个元素即可。因此时间复杂度为O(kN)。 注:由于题目只需找到最小的k个数,因此利用快排的哨兵来寻找,对所有元素遍历采用快排,直至哨兵index与k相等,左侧所有元素即为所求。因此时间复杂度为O(NlogN)。另外需要注意输入是否有重复元素,如果有重复元素则需要多做一些记录和判断。 注:由于题目只需找到最小的k个数,因此利用堆排序算法可以很好的求解,此处利用大顶堆。因此时间复杂度为O(NlogN)。 测试用例1: 输出:
题目:
4,5,1,6,2,7,3,8
这8个数字,则最小的4个数字是1,2,3,4,
。
输入示例:[4,5,1,6,2,7,3,8], 4
1, 2, 3, 4,
规定:
解题思路:
(1)普通排序(此处采用冒泡排序)
class Solution { public: void swap(vector<int> &input, int i, int j){ int temp = input[i]; input[i] = input[j]; input[j] = temp; } vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { //(1)最基础解法:冒泡,O(N^2)->O(kN) int length = input.size();//长度 vector<int> result; if(length==0 || k<=0||k>length){ return result; } for(int i=0;i<k;i++){ for(int j=i;j<length;j++){ if(input[i]>input[j]){//将最小的换到最左边,依次进行k次 swap(input,i,j); } } } for(int i=0;i<k;i++){ result.push_back(input[i]); } return result; } };
(2)快速搜索(快排思想)
①输入无重复元素时:
class Solution { public: void swap(vector<int> &input, int i, int j){ int temp = input[i]; input[i] = input[j]; input[j] = temp; } vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { //(2)升级解法:快排,O(NlogN) int length = input.size();//长度 vector<int> result; if(length==0 || k<=0||k>length){ return result; } vector<int> input_copy = input;//复制,避免快排后原数组被修改 int pivot = 0;//哨兵index for(int i=0;i<length;i++){ input_copy = input;//复制,避免快排后原数组被修改 swap(input_copy, 0, i);//交换i与0的元素,固定哨兵pivot为数组第1个元素 pivot = 0;//哨兵index int pre = 1;//头 int beh = length-1;//尾 //快排 while(pre<=beh){//当pre超过beh后停止 if(input_copy[pre]>=input_copy[pivot]){ if(input_copy[beh]<input_copy[pivot]){//遇到等于的也跳过 swap(input_copy, pre, beh); pre++; beh--; } else beh--; } else pre++; } swap(input_copy, pre-1, pivot); pivot = pre-1;//当pivot等于k时,左侧元素即为最小的k个数字 if(pivot==k-1){ for(int i=0;i<k;i++){ result.push_back(input_copy[i]); } break;//跳出循环 } } return result; } };
②输入有重复元素时:
//改进:解决输入元素有重复的问题 class Solution { public: void swap(vector<int> &input, int i, int j){ int temp = input[i]; input[i] = input[j]; input[j] = temp; } vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { //(2)升级解法:快排,O(NlogN) int length = input.size();//长度 vector<int> result; if(length==0 || k<=0||k>length){ return result; } vector<int> input_copy = input;//复制,避免快排后原数组被修改 int pivot = 0;//哨兵index for(int i=0;i<length;i++){ input_copy = input;//复制,避免快排后原数组被修改 swap(input_copy, 0, i);//交换i与0的元素,固定哨兵pivot为数组第1个元素 pivot = 0;//哨兵index int pre = 1;//头 int beh = length-1;//尾 //快排 int repet_cnt = 0; int pre_bak = 0; while(pre<=beh){//当pre超过beh后停止 if(input_copy[pre]==input_copy[pivot]){ if(pre_bak!=pre) repet_cnt++; pre_bak = pre;//保存上一次pre,避免重复计数 if(input_copy[beh]<input_copy[pivot]){ swap(input_copy, pre, beh); pre++; beh--; } else if(input_copy[beh]==input_copy[pivot]){ if(beh!=pre) repet_cnt++; beh--;//计数后beh前移 } else beh--; } else if(input_copy[pre]>input_copy[pivot]){ if(input_copy[beh]<input_copy[pivot]){//遇到等于的也跳过 swap(input_copy, pre, beh); pre++; beh--; } else beh--; } else pre++; } swap(input_copy, pre-1, pivot); pivot = pre-1;//当pivot等于k时,左侧元素即为最小的k个数字 if(repet_cnt==0){ if(pivot==k-1){ for(int i=0;i<k;i++){ result.push_back(input_copy[i]); } break;//跳出循环 } } else{ if(pivot==k-1){ for(int i=0;i<k;i++){ result.push_back(input_copy[i]); } break;//跳出循环 } if(pivot+repet_cnt >=k-1){ for(int i=0;i<pivot;i++){ result.push_back(input_copy[i]); } for(int i=pivot;i<k;i++){ result.push_back(input_copy[pivot]); } break;//跳出循环 } } } return result; } };
(3)堆排序(完全二叉树)
class Solution { public: void swap(vector<int> &input, int i, int j){ int temp = input[i]; input[i] = input[j]; input[j] = temp; } void heapify(vector<int>&input, int index, int length){ //堆化,构造大顶堆 int maxIndex = index; while(true){ if(input[index] < input[2*index+1] && (2*index+1)<length){ //与左子节点对比 maxIndex = 2*index+1; } if(input[maxIndex] < input[2*index+2] && (2*index+2)<length){ //将最大值与右子节点对比 maxIndex = 2*index+2; } if(index==maxIndex){ break;//无需交换 } swap(input, index, maxIndex); index = maxIndex; } } void heap_sort(vector<int> &input, int length){ if(length<=1){ return; } //堆排序 for(int i=(length/2-1);i>=0;i--){ heapify(input,i, length); } } vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { //(3)高级解法:堆排,O(NlogN) int length = input.size();//长度 vector<int> result; if(length==0 || k<=0||k>length){ return result; } heap_sort(input, length);//建堆并排序 //调换root和最后的节点元素,重新对剩余堆元素进行调整 int sorted_index = length-1; while(sorted_index!=0){ swap(input,0,sorted_index--);//交换最大值和尾部元素 heap_sort(input, --length);//对除去已排序的尾部元素后重新堆化,直至所有只剩一个元素时停止 } for(int i=0;i<k;i++){ result.push_back(input[i]); } return result; } };
完整程序:
#include <stdio.h> #include <vector> using namespace std; //code block,上述任一种方法的代码块,填充至此。 int main(){ vector<int> input = {4,5,1,6,2,7,3,8}; int k =4; Solution so; vector<int> result = so.GetLeastNumbers_Solution(input, k); int length = result.size(); for(int i =0; i<length;i++){ printf("%d, ",result[i]); } return 0; }
输入输出测试:
输入:
{4,5,1,6,2,7,3,8}, 4
测试用例2:
输入:
{2,2,1,2,2,7,3,8}, 4
输出:
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算