关注
bfprt算法及其相关
找到无序数组中最小的K个数
【题目】
给定一个无序的整型数组arr,找到其中最小的k个数。
【要求】
如果数组arr的长度为N,排序之后自然可以得到最小的k个数,此时时间复杂度为排序的时间复杂度即O(N*logN)。本题要求读者实现时间复杂度O(N*logK)和O(N)的方法。
利用堆:
public int[]
getMinKNumsByHeap(int[] arr, int k) {
if (k < 1 || k >
arr.length) {
return arr;
}
int[] kHeap = new int[k];
for (int i = 0; i != k;
i++) {
heapInsert(kHeap,
arr[i], i);
}
for (int i = k; i !=
arr.length; i++) {
if (arr[i] <
kHeap[0]) {
kHeap[0] = arr[i];
heapify(kHeap, 0, k);
}
}
return kHeap;
}
public void heapInsert(int[]
arr, int value, int index) {
arr[index] = value;
while (index != 0) {
int parent = (index -
1) / 2;
if (arr[parent] <
arr[index]) {
swap(arr, parent, index);
index = parent;
} else {
break;
}
}
}
public void heapify(int[]
arr, int index, int heapSize) {
int left = index * 2 + 1;
int right = index * 2 + 2;
int largest = index;
while (left <
heapSize) {
if (arr[left] >
arr[index]) {
largest = left;
}
if (right <
heapSize && arr[right] > arr[largest]) {
largest = right;
}
if (largest != index) {
swap(arr,
largest, index);
} else {
break;
}
index = largest;
left = index * 2 + 1;
right = index * 2 + 2;
}
}
public void swap(int[] arr,
int index1, int index2) {
int tmp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = tmp;
}
利用bfprt算法:
public int[]
getMinKNumsByBFPRT(int[] arr, int k) {
if (k < 1 || k >
arr.length) {
return arr;
}
int minKth =
getMinKthByBFPRT(arr, k);
int[] res = new int[k];
int index = 0;
for (int i = 0; i !=
arr.length; i++) {
if (arr[i] <
minKth) {
res[index++] = arr[i];
}
}
for (; index !=
res.length; index++) {
res[index] = minKth;
}
return res;
}
public int
getMinKthByBFPRT(int[] arr, int K) {
int[] copyArr = copyArray(arr);
return select(copyArr, 0,
copyArr.length - 1, K - 1);
}
public int[] copyArray(int[]
arr) {
int[] res = new int[arr.length];
for (int i = 0; i !=
res.length; i++) {
res[i] = arr[i];
}
return res;
}
public int select(int[] arr,
int begin, int end, int i) {
if (begin == end) {
return arr[begin];
}
int pivot =
medianOfMedians(arr, begin, end);
int[] pivotRange =
partition(arr, begin, end, pivot);
if (i >= pivotRange[0]
&& i <= pivotRange[1]) {
return arr[i];
} else if (i <
pivotRange[0]) {
return select(arr,
begin, pivotRange[0] - 1, i);
} else {
return select(arr,
pivotRange[1] + 1, end, i);
}
}
public int
medianOfMedians(int[] arr, int begin, int end) {
int num = end - begin + 1;
int offset = num % 5 == 0
? 0 : 1;
int[] mArr = new int[num
/ 5 + offset];
for (int i = 0; i <
mArr.length; i++) {
int beginI = begin +
i * 5;
int endI = beginI + 4;
mArr[i] =
getMedian(arr, beginI, Math.min(end, endI));
}
return select(mArr, 0,
mArr.length - 1, mArr.length / 2);
}
public int[] partition(int[]
arr, int begin, int end, int pivotValue) {
int small = begin - 1;
int cur = begin;
int big = end + 1;
while (cur != big) {
if (arr[cur] <
pivotValue) {
swap(arr,
++small, cur++);
} else if (arr[cur]
> pivotValue) {
swap(arr, cur, --big);
} else {
cur++;
}
}
int[] range = new int[2];
range[0] = small + 1;
range[1] = big - 1;
return range;
}
public int getMedian(int[]
arr, int begin, int end) {
insertionSort(arr, begin, end);
int sum = end + begin;
int mid = (sum / 2) +
(sum % 2);
return arr[mid];
}
public void
insertionSort(int[] arr, int begin, int end) {
for (int i = begin + 1; i
!= end + 1; i++) {
for (int j = i; j !=
begin; j--) {
if (arr[j - 1]
> arr[j]) {
swap(arr, j -
1, j);
} else {
break;
}
}
}
}
public void swap(int[] arr,
int index1, int index2) {
int tmp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = tmp;
}
查看原帖
点赞 评论
相关推荐
点赞 评论 收藏
转发
昨天 12:33
西安电子科技大学 计算机类 点赞 评论 收藏
转发
牛客热帖
- 1... 想来字节技术实习,看我这篇就够了!——保姆级面经大放送1.9W
- 2... 毕业1.3W
- 3... 25届第一份实习怎么找?1.2W
- 4... 【0429快问快答】99%牛油的疑惑解答(更新至38个问题1.1W
- 5... 0实习经验上岸字节,分享一下过程经验9682
- 6... 【奖】休息放松or学习提升,五一假期和牛牛一起“充充电”🔋8299
- 7... 美团后端日常实习一二面(已oc)6529
- 8... 准备去参加自己的婚礼6375
- 9... 为什么我不建议你学C++后端5356
- 10... 【薪资计算】SS Is All You Need4779
正在热议
# 牛友的五一计划 #
24910次浏览 449人参与
# 市场营销面经 #
1645次浏览 78人参与
# 牛客帮帮团来啦!有问必答 #
413559次浏览 7964人参与
# 晒一晒我的offer #
2853413次浏览 50142人参与
# 互联网公司评价 #
63506次浏览 902人参与
# 市场营销人求职交流聚集地 #
25437次浏览 577人参与
# 许愿池 #
66977次浏览 1485人参与
# 我的上岸简历长这样 #
142596次浏览 2862人参与
# 提前批真的不会影响正式批吗 #
18147次浏览 229人参与
# 如何看待offer收割机的行为 #
197117次浏览 3025人参与
# 国企和大厂硬件兄弟怎么选? #
28556次浏览 551人参与
# 双非本科求职如何逆袭 #
174559次浏览 2624人参与
# 非技术岗薪资爆料 #
10305次浏览 204人参与
# 找工作,你会甘心进小厂还是猛冲大厂 #
24575次浏览 244人参与
# 产品实习,你更倾向大公司or小公司 #
31517次浏览 494人参与
# 在国企工作的人,躺平了吗? #
74116次浏览 907人参与
# 浅聊一下我实习的辛苦费 #
71449次浏览 647人参与
# 简历中的项目经历要怎么写 #
383415次浏览 6426人参与
# 机械制造薪资爆料 #
262619次浏览 3204人参与
# 第一次面试 #
19522次浏览 307人参与