【面试题30】最小的k个数
【题目描述】
输入n个整数,找出其中最小的k个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。
【解决方案】
测试用例:
1. 功能测试(输入数组中有相同的数字,输入数组中没有相同的数字);
2. 边界值测试(输入的k等于1或者等于数组的长度);
3. 特殊情况测试(k小于1,k大于数组的长度,指向数组的指针为null);
解法一:基于Partition函数来解决
优点:时间复杂度为o(n);
缺点:会修改原数组;不适用于数据量较大的查找(例如,数组一次性加载不到内存中);
我的代码实现,仅供参考:
1 public static void GetLeastNums(int[] arr, int k) 2 { 3 if (arr == null || arr.Length < k || k <= 0) 4 return; 5 6 int start = 0; 7 int end = arr.Length - 1; 8 int index = Partition(arr, start, end); 9 10 while (k - 1 != index) 11 { 12 if (index > k - 1) 13 { 14 end = index - 1; 15 index = Partition(arr, start, end); 16 } 17 else 18 { 19 start = index + 1; 20 index = Partition(arr, start, end); 21 } 22 } 23 24 for (int i = 0; i < k; i++) 25 { 26 Console.Write(arr[i]); 27 } 28 } 29 30 public static int Partition(int[] arr, int start, int end) 31 { 32 int temp = arr[start]; 33 34 while (start < end) 35 { 36 while (start < end && arr[end] >= temp) 37 end--; 38 arr[start] = arr[end]; 39 40 while (start < end && arr[start] <= temp) 41 start++; 42 arr[end] = arr[start]; 43 } 44 45 arr[start] = temp; 46 47 return start; 48 }
解法二:利用大根堆的特性,在堆中保存前k个小的数,遍历数组,满足则替换
优点:不需要修改原数组;适合数据量大,所求k较小的情况;
缺点:时间复杂度为O(nlogk);
我的代码实现,仅供参考:
1 public static void GetLeastNums(int[] arr, int k) 2 { 3 if (arr == null || arr.Length < k || k <= 0) 4 return; 5 6 int[] arrK = new int[k]; 7 8 //为大根堆数组赋值 9 for (int i = 0; i < k; i++) 10 { 11 arrK[i] = arr[i]; 12 } 13 14 //构建大根堆 15 for (int j = arrK.Length / 2 - 1; j >= 0; j--) 16 { 17 MaxHeapify(arrK, j); 18 } 19 20 for (int i = k; i < arr.Length; i++) 21 { 22 //如果比大根堆的最大值还要大,则覆盖最大值,然后调整大根堆 23 if (arrK[0] > arr[i]) 24 { 25 arrK[0] = arr[i]; 26 MaxHeapify(arrK, 0); 27 } 28 } 29 30 foreach (int num in arrK) 31 Console.Write(num); 32 } 33 34 /// <summary> 35 /// 调整大根堆 36 /// </summary> 37 /// <param name="arr"></param> 38 public static void MaxHeapify(int[] arr, int currentIndex) 39 { 40 int left = currentIndex * 2 + 1; 41 int right = currentIndex * 2 + 2; 42 int large = currentIndex; 43 44 if (left < arr.Length && arr[left] > arr[large]) 45 { 46 large = left; 47 } 48 49 if (right < arr.Length && arr[right] > arr[large]) 50 { 51 large = right; 52 } 53 54 if (large != currentIndex) 55 { 56 Swap(arr, large, currentIndex); 57 58 MaxHeapify(arr, large); 59 } 60 } 61 62 public static void Swap(int[] arr, int indexA, int indexB) 63 { 64 int temp = arr[indexA]; 65 arr[indexA] = arr[indexB]; 66 arr[indexB] = temp; 67 }