剑指Offer28 最小的K个数

Posted Juntaran

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指Offer28 最小的K个数相关的知识,希望对你有一定的参考价值。

包含了Partition函数的多种用法

以及大顶堆操作

  1 /*************************************************************************
  2     > File Name: 28_KLeastNumbers.cpp
  3     > Author: Juntaran
  4     > Mail: [email protected]
  5     > Created Time: 2016年08月31日 星期三 19时45分41秒
  6  ************************************************************************/
  7 
  8 #include <stdio.h>
  9 #include <bits/stdc++.h>
 10 
 11 using namespace std;
 12 
 13 
 14 // 大顶堆求最小K个数
 15 typedef multiset<int, greater<int> > intSet;
 16 typedef multiset<int, greater<int> >::iterator setIterator;
 17 
 18 void GetKLeastNumbers2(int* data, intSet& leastNumbers, int length, int k)
 19 {
 20     leastNumbers.clear();
 21     
 22     if (k<1 || length<k)
 23         return;
 24     
 25     for (int i = 0; i < length; ++i)
 26     {
 27         if (leastNumbers.size() < k)
 28             leastNumbers.insert(data[i]);
 29         
 30         else
 31         {
 32             setIterator Greatest = leastNumbers.begin();
 33             if (data[i] < *(leastNumbers.begin()))
 34             {
 35                 leastNumbers.erase(Greatest);
 36                 leastNumbers.insert(data[i]);
 37             }
 38         }
 39     }
 40     
 41     for (setIterator iter = leastNumbers.begin(); iter != leastNumbers.end(); ++iter)
 42     {
 43         printf("%d ", *iter); 
 44     }
 45     printf("\n");
 46 }
 47 
 48 
 49 void swap(int* p, int* q)
 50 {
 51     int temp = *p;
 52     *p = *q;
 53     *q = temp;
 54 }
 55 
 56 // Partition函数应用
 57 int Partition(int* data, int length, int start, int end)
 58 {
 59     if (data==NULL || length<=0 || start<0 || end>=length)
 60         return -1;
 61     
 62     // 令数组第一个数字为标杆
 63     int index = start;                
 64     
 65     // 标杆与数组最后一个元素交换
 66     swap(&data[index], &data[end]);
 67     
 68     int small = start - 1;
 69     for (index = start; index < end; ++index)
 70     {
 71         if (data[index] < data[end])
 72         {
 73             ++ small;
 74             if (small != index)
 75             {
 76                 swap(&data[index], &data[small]);
 77             }
 78         }
 79     }
 80     ++ small;
 81     swap(&data[small], &data[end]);
 82     
 83     return small;
 84 }
 85 
 86 // 利用Partiton实现快排
 87 void quickSort(int* data, int length, int start, int end)
 88 {
 89     if (start==end || data==NULL || length<=0)
 90         return;
 91     
 92     int index = Partition(data, length, start, end);
 93     // printf("index is %d\n", index);
 94     if (index > start)
 95         quickSort(data, length, start, index-1);
 96     if (index < end)
 97         quickSort(data, length, index+1, end);
 98 }
 99 
100 // 利用Partition寻找出现次数超过一半的数 (中位数)
101 int GetMoreThanHalf(int* input, int length)
102 {
103     if (input==NULL || length<=0)
104         return -1;
105     int start = 0;
106     int end   = length - 1;
107     int index = Partition(input, length, start, end);
108     int middle = length >> 1;
109     while (index != middle)
110     {
111         if (index > middle)
112         {
113             end = index - 1;
114             index = Partition(input, length, start, end);
115         }
116         else
117         {
118             start = index + 1;
119             index = Partition(input, length, start, end);
120         }
121     }
122     int ret = input[middle];
123     // 检验是否正确
124     int count2 = 0;
125     for (int i = 0; i < length; ++i)
126     {
127         if (input[i] == ret)
128             count2 ++;
129     }
130     if (count2*2 > length)
131     {
132         printf("middle number is %d\n", input[middle]);
133         return ret;
134     }
135     else
136     {
137         printf("Not Find\n");
138         return -1;
139     }
140 }
141 
142 
143 // 利用Partition寻找第K小的数
144 int GetKthNumber(int* input, int length, int k)
145 {
146     if (input==NULL || length<=0 || k<=0 || k>length)
147         return -1;
148     int start = 0;
149     int end   = length - 1;
150     int index = Partition(input, length, start, end);
151     while (index != k - 1)
152     {
153         if (index > k-1)
154         {
155             end = index-1;
156             index = Partition(input, length, start, end);
157         }
158         else
159         {
160             start = index + 1;
161             index = Partition(input, length, start, end);
162         }
163     }
164     printf("Kth is %d\n", input[index]);
165     return input[index];
166 }
167 
168 
169 // 利用Partition寻找最小K个数
170 void GetKLeastNumbers(int* input, int length, int* output, int k)
171 {
172     if (input==NULL || output==NULL || length<=0 || k<=0 || k>length)
173     {
174         return;
175     }
176     int start = 0;
177     int end   = length - 1;
178     int index = Partition(input, length, start, end);
179     while (index != k - 1)
180     {
181         if (index > k-1)
182         {
183             end = index - 1;
184             index = Partition(input, length, start, end);
185         }
186         else
187         {
188             start = index + 1;
189             index = Partition(input, length, start, end);
190         }
191         // printf("index is %d\n", index);
192     }
193     for (int i = 0; i < k; ++i)
194         output[i] = input[i];
195     
196     for (int i = 0; i < k; ++i)
197         printf("%d ", output[i]);
198     printf("\n");
199 }
200 
201 // 利用大顶堆寻找最小K个数
202 
203 
204 int main()
205 {
206     int k = 5;
207     int nums[] = {3,5,5,5,6,5,7,1,2,9};
208     int length = 10;
209     int output[k] = {0};
210     
211     // 快速排序
212     quickSort(nums, length, 0, length-1);
213     for (int i = 0; i < length; ++i)
214         printf("%d ", nums[i]);
215     printf("\n");
216     
217     // 求最小K个数
218     GetKLeastNumbers(nums, length, output, k);
219     
220     // 求第K大的数
221     GetKthNumber(nums, length, k);
222     
223     // 求数组中超过一半的数(中位数)
224     GetMoreThanHalf(nums, length);
225     
226     // 大顶堆求最小K个数
227     intSet leastNumbers;
228     GetKLeastNumbers2(nums, leastNumbers, length, k);
229 }

 

以上是关于剑指Offer28 最小的K个数的主要内容,如果未能解决你的问题,请参考以下文章

剑指offer--40最小的k个数

剑指offer--40最小的k个数

剑指offer---最小的K个数

剑指 Offer 40. 最小的k个数

最小的K个数-剑指Offer

剑指offer:最小k个数