第k小数1

对于给定的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 }
原文地址:https://www.cnblogs.com/CZT-TS/p/8447696.html