对于给定的n个元素的无序数组,要求从中找出第k小的元素
二分法+快速排序
例如一列由10个元素组成的数组:[5, 7, 1, 2, 3, 9, 8, 10, 4, 6],假设找出k = 4 的元素。
将第一个元素5作为参照物, 将比5小的数放在5的左边,比5大的数放在5的右边,则数组第一次调整为【2,1,4,3】5【10,9,8,7】。
比5小的数由4个,所以将搜索范围缩小到5的左边数组即【2,1,4,3】舍弃右边的数组。
以2为参照物, 将比2小的数字放在2的左边,比2大的数字放在2的右边。则数组的第二次调整为:【1】2【4,3】。
可以看出,2为数组中第2小的数字,所以将搜索范围缩小到2的右边数组【4,3】,舍弃左边的数组。
最后一次找到第4小的数字为4。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<algorithm> 6 using namespace std; 7 int a[100001], b[100001]; 8 int i, j, m, k, l; 9 10 void Swap() 11 { 12 swap(a[i], a[j]); 13 swap(i, j); 14 } 15 16 void Operation(int START, int END) 17 { 18 i = START; 19 j = END; 20 while(i != j) 21 { 22 if(i < j) 23 { 24 if(a[i] > a[j]) 25 Swap(); 26 else 27 j--; 28 } 29 else 30 { 31 if(a[i] < a[j]) 32 Swap(); 33 else 34 j++; 35 } 36 } 37 if(i < k) 38 Operation(i + 1, END); 39 else if(i == k) 40 { 41 for(l = 1; l <= m; l++) 42 { 43 if(b[l] == a[i]) 44 { 45 cout << l << endl; 46 break; 47 } 48 } 49 } 50 else 51 Operation(START, i - 1); 52 } 53 int main() 54 { 55 cin >> m >> k; 56 for(int i = 1; i <= m; i++) 57 { 58 cin >> a[i]; 59 b[i] = a[i]; 60 } 61 Operation(1, m); 62 return 0; 63 }
如果在线性时间内找到划分的基准,则可以在最坏情况下复杂度为O(n)时找到第k小的数。
方法如下
(1)将数组a五个数为一组,分为【n/5】个组。
(2)对【n/5】个组的数进行组内排序,采用冒泡排序等任何方法均可。
(3)选择每组的中位数,将这些中位数交换到数组的最前面,此时a[0 ~(end - start)/ 5 - 1]中存的就是这些中位数。
(4)对a[0 ~(end - start)/ 5 - 1]个中位数进行排序,取出排序后这些中位数的中位数x,则x就是需要的划分标准。
(5)以x为基准再次进行二分,比较,递归寻找即可。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<algorithm> 6 using namespace std; 7 int a[100001], b[100001]; 8 int i, j, m, k, l; 9 int cmp(int x, int y) 10 { 11 return x < y; 12 } 13 void Swap() 14 { 15 swap(a[i], a[j]); 16 swap(i, j); 17 } 18 19 void Operation(int START, int END) 20 { 21 i = START; 22 j = END; 23 while(i != j) 24 { 25 if(i < j) 26 { 27 if(a[i] > a[j]) 28 Swap(); 29 else 30 j--; 31 } 32 else 33 { 34 if(a[i] < a[j]) 35 Swap(); 36 else 37 j++; 38 } 39 } 40 if(i < k) 41 Operation(i + 1, END); 42 else if(i == k) 43 { 44 for(l = 1; l <= m; l++) 45 { 46 if(b[l] == a[i]) 47 { 48 cout << l << endl; 49 break; 50 } 51 } 52 } 53 else 54 Operation(START, i - 1); 55 } 56 int main() 57 { 58 cin >> m >> k; 59 for(int i = 1; i <= m; i++) 60 { 61 cin >> a[i]; 62 b[i] = a[i]; 63 } 64 for(i = 6; i <= m + 1; i = i + 5) 65 { 66 sort(a + i - 5, a + i, cmp); 67 } 68 for(i = 1; i <= m/5; i++) 69 swap(a[i], a[i * 5 - 2]); 70 sort(a + 1, a + i, cmp); 71 swap(a[1], a[i / 2]); 72 Operation(1, m); 73 return 0; 74 }