题目:
思路:先排序后输出:
代码1:时间复杂度O(n^2)排序(可使用已有的排序算法,这里使用的是冒泡)。运行结果排序算法有问题
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
int len = input.size();
vector<int> output;
SortNumbers(input);
for (int i=0;i<k;i++)
output.push_back(input[i]);
return output;
}
private:
vector<int> SortNumbers(vector<int> input){
vector<int> result = input;
int n = input.size();
int temp;
for (int i = 0; i < n - 1; i++){
// 从后向前依次的比较相邻两个数的大小
for (int j = 0; j < n - 1; j++){
// 如果后面的元素小,则交换它们的位置
if (result[j + 1] < result[j]){
temp = result[j + 1];
result[j + 1] = result[j];
result[j] = temp;
}
}
}
return result;
}
};
代码2:时间复杂度O(nlogn)利用全排序函数sort(input.begin(),input.end());
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
int len = input.size();
vector<int> output;
if( k>len || k<=0 || len<=0)
return output;
sort(input.begin(),input.end());
for (int i=0;i<k;i++)
output.push_back(input[i]);
return output;
}
};
代码3:时间复杂度O(n)利用快排中的获取分割中轴点位置函数。基于数组的第K个数字来调整,则使得比k个数字小的所有数字都位于数字的左边,比第k个数字大的所有数字都位于数组的右边。这样调整后,位于数组中左边的k个数字就是最小的k个数字(这k个数字不一定是排序的)。这种思路在“数组中出现次数超过一半的数字”的题目中出现过,而我在做这道题的时候使用的是哈希表的方法,没有使用这种思路,需要用这种思路再去重新做一遍跟次数相关的题目。但这种解法会修改输入的数组,因为函数getPartition()会改变数组中数字的顺序。
class Solution {
public:
void swap(int &fir, int &sec){
int temp = fir;
fir = sec;
sec = temp;
}
int getPartition(vector<int> &input, int start, int end){
if(input.empty() || start>end) return -1;
int temp = input[end];
int j = start - 1;
for(int i=start;i<end;i++){
if(input[i] <= temp){
j++;
if(i != j)
swap(input[i],input[j]);
}
}
swap(input[j+1],input[end]);
return (j+1);
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> result;
if(input.empty() || k>input.size() || k<=0) return result;
int start = 0;
int end = input.size()-1;
int index = getPartition(input,start,end);
while(index != k-1){
if(index > k-1){
end = index - 1;
index = getPartition(input,start,end);
}
else{
start = index + 1;
index = getPartition(input,start,end);
}
}
for(int i=0;i<k;i++){
result.push_back(input[i]);
}
return result;
}
};
代码4:时间复杂度O(nlogk).代码3的思路会改变原有的数组中数字的顺序,如果题目不允许改变,这样的方法就不能用了。可以使用堆栈的方法,这样的方法很适合处理海量数据。可以先创建一个大小为k的数据容器来存储最小的k个数字,接下来每次从输入的n个整数中读入一个数。如果容器中已有的数字少于k个,则直接把这次读入的整数放入到容器中;如果容器中已有k个数字,也就是容器已满,此时不能再插入新的数字而只能替换已有的数字。找出这已有的k个数中的最大值,然后拿待插入的整数和最大值进行比较。如果待插入的值比当前已有的最大值小,则用这个数替换当前已有的最大值;如果待插入的值比当前已有的最大值还要大,那么这个数不可能是最小的k个数之一,于是抛弃这个数。
我自己先按照这个思路写了一个,但返回值与我第一种方法的一模一样,why????
class Solution {
public:
int getResultMax(vector<int> input){
int max = input[0];
int max_num = 0;
for(int i=1;i<input.size();i++){
if(input[i] > max){
max = input[i];
max_num = i;
}
}
return max,max_num;
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> result;
if(input.empty() || k<input.size() || k<=0) return result;
for(int i=0;i<k;i++){
result.push_back(input[i]);
}
int resultMax = 0;
int numMax = 0;
for(int i=k;i<input.size();i++){
resultMax,numMax = getResultMax(result);
if(input[i] < resultMax){
result[numMax] = input[i];
}
}
return result;
}
};
讨论区的写法(堆方法):
最大堆和最小堆:当父节点的键值总是大于或等于任何一个子节点的键值时为最大堆。 当父节点的键值总是小于或等于任何一个子节点的键值时为最小堆。
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> res;
if(input.size() == 0 || k==0 ||k>input.size())
return res;
for(int i=0;i<k;i++)
res.push_back(input[i]);
make_heap(res.begin(),res.end());
for(int i=k;i<input.size();i++){
if(input[i]<res[0]){
pop_heap(res.begin(),res.end());
res.pop_back();
res.push_back(input[i]);
push_heap(res.begin(),res.end());
}
}
sort_heap(res.begin(),res.end());
return res;
}
};
剑指offer中的红黑树方法:“红黑树”,它一种特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。
class Solution {
public:
typedef multiset<int,greater<int>> inSet;
typedef multiset<int,greater<int>>::iterator setIterator;
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
inSet leastNumbers;
if(k>input.size()) return vector<int> ();
vector<int>::iterator iter = input.begin();
for(; iter!=input.end();iter++){
if(leastNumbers.size()<k)
leastNumbers.insert(*iter);
else{
setIterator iterGreatest = leastNumbers.begin();
if(*iterGreatest > *iter){
leastNumbers.erase(iterGreatest);
leastNumbers.insert(*iter);
}
}
}
vector<int> ret(leastNumbers.begin(),leastNumbers.end());
return ret;
}
};