用二分法求众数

一、题目引发:

Boxing Packing

Description:

Mishka has got n empty boxes. For every i (1 ≤ i ≤ n), i-th box is a cube with side length ai.

Mishka can put a box i into another box j if the following conditions are met:

  • i-th box is not put into another box;
  • j-th box doesn't contain any other boxes;
  • box i is smaller than box j (ai < aj).

Mishka can put boxes into each other an arbitrary number of times. He wants to minimize the number of visible boxes. A box is called visible iff it is not put into some another box.

Help Mishka to determine the minimum possible number of visible boxes!

理解一下就是:给定一串序列,至少要拆分成多少组互异的子序列。

进一步理解:等价于求众数的重数。

二、分治法求众数及其重数

算法描述:首先将序列排好序,取中间值,分别左右遍历得到最长连续子序列,设此长度为L。若左子区间长度大于L,则向左递归;若右子区间长度大于L,则向右递归;

算法实现:

代码:

 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<stdlib.h>
 5 const int maxn = 5000 + 10;
 6 int len[maxn];
 7 int targrt,cnt = -1;
 8 
 9 int compare(const void * a, const void * b)
10 {
11     return (*(int*)a - *(int*)b);
12 }
13 void split(int * len, int l, int r)
14 {
15     int mid = (l + r) / 2;
16     int i, j;
17     for (i = l; i <= mid; i++)
18     {
19         if (len[i] == len[mid])
20             break;
21     }
22     for (j = mid + 1; j <= r; j++)
23     {
24         if (len[j] != len[mid])
25             break;
26     }
27     if ((j - i) > cnt)
28     {
29         cnt = j - i;
30         targrt = len[mid];
31     }
32     if ((i - l) > cnt)
33         split(len, l, i - 1);
34     if ((r - j + 1) > cnt)
35         split(len, j, r);
36     return;
37 }
38 int main()
39 {
40     int n;
41     scanf("%d\n", &n);
42     for (int i = 0; i < n; i++)
43         scanf("%d", &len[i]);
44     qsort(len, n, sizeof(int),compare);
45     split(len, 0, n-1);
46     printf("%d",cnt);
47     return 0;
48 }
View Code

三、其他方法

还可以参照“桶”的思想,每个数字就是桶的编号,桶的内容就是该数的重数。但是这个数字可能很大,就要采用哈希的办法,这个方法以后再补充吧!

而且这题不用二分法也能过,采用依次遍历,时间复杂度为O(N)(二分法的时间复杂度为O(log(N))),代码实现起来非常的简单

代码:

 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn = 5000 + 10;
 6 int a[maxn];
 7 
 8 int main()
 9 {
10     int n;
11     scanf("%d", &n);
12     for (int i = 0; i < n; i++)
13         scanf("%d", &a[i]);
14     sort(a , a + n);
15     int ans = 1, cnt = 1;
16     for (int i = 1; i < n; i++)
17     {
18         if (a[i] == a[i - 1])
19         {
20             cnt++;
21             if (cnt > ans)
22                 ans = cnt;
23         }
24         else
25             cnt = 1;
26     }
27     printf("%d\n", ans);
28 }
View Code

 

转载于:https://www.cnblogs.com/lfri/p/9310876.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值