做法一:直接模拟
空间复杂度:\(O(10^6)\)
// #define FILE_INPUT
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;#define rep(i, a, b) for (int i = a, END##i = b; i <= END##i; i++)
#define per(i, a, b) for (int i = a, END##i = b; i >= END##i; i--)void Init();
void Solve();signed main() {cin.sync_with_stdio(0);cin.tie(0), cout.tie(0);#ifdef FILE_INPUTfreopen("input.in", "r", stdin);#endifint T = 1;// cin >> T;while (T--) {Init();Solve();}return 0;
}using LL = long long;
using ULL = unsigned long long;const int Mod = 1e9 + 7;
const int Inf = 0x3f3f3f3f;
const LL InfLL = 0x3f3f3f3f3f3f3f3f;const int N = 1e6 + 10;
int n, b[N];void Init() {
}void Solve() {while (cin >> n) {memset(b, 0, sizeof(b));int ans, t = n + 1 >> 1;rep(i, 1, n) {int a; cin >> a;b[a]++;if (b[a] >= t) ans = a;}cout << ans << "\n";}
}
做法二:模拟(应该叫摩尔投票法?),动态规划
首先呢,最多的次数为 \(\frac{n+1}{2}\) 那么其他的数出现的次数为 \(\frac{n-1}{2}\),那么如果,我们把两个不同的数给消掉,剩下还有的数绝对就是答案了 \(\frac{n+1}{2}-\frac{n-1}{2}=1\)。
(先看代码再看这个)那么怎么让空间复杂度为 \(O(1)\) 来计算这个东西呢?我们可以先设一个数 \(lst\) 表示现在用这个数来和其他数消掉,再用 \(cnt\) 表示,现在还剩下多少个 \(lst\) 这个数,如果 \(a=lst\) 那么 \(cnt+1\) 否则 \(cnt-1\),最后剩下的那个 \(lst\) 就是解了。
如果想了解摩尔投票法可以看看这个(虽然不是我写的)。
// #define FILE_INPUT
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;#define rep(i, a, b) for (int i = a, END##i = b; i <= END##i; i++)
#define per(i, a, b) for (int i = a, END##i = b; i >= END##i; i--)void Init();
void Solve();signed main() {cin.sync_with_stdio(0);cin.tie(0), cout.tie(0);#ifdef FILE_INPUTfreopen("input.in", "r", stdin);#endifint T = 1;// cin >> T;while (T--) {Init();Solve();}return 0;
}using LL = long long;
using ULL = unsigned long long;const int Mod = 1e9 + 7;
const int Inf = 0x3f3f3f3f;
const LL InfLL = 0x3f3f3f3f3f3f3f3f;const int N = 1e6 + 10;
int n;void Init() {
}void Solve() {while (cin >> n) {int cnt = 0, ans = 0, a, lst = 0;while (n--) {cin >> a;if (a == lst) cnt++;else {if (!cnt) lst = a, cnt = 1;else cnt--;}}cout << lst << "\n";}
}
你不会以为到这里就结束了吧,还有 dp 的方法呢(虽然代码一摸一样)😁
我们设 \(f_{i}\) 表示,对于前 \(i\) 个数,出现个数至少为 \(\lceil\frac{i+1}{2}\rceil\) 的数。设 \(g_{i}\) 表示,前 \(i\) 个数中,\(f_i\) 出现的个数减去其他的数。
当 \(g_{i-1}>0\) 时,也就是有解
\[\begin{aligned}f_{i}&=f_{i-1}\\g_{i}&=\left\{ \begin{array}{rcl}g_{i-1}+1,a_i=f_i\\g_{i-1}-1,a_i\not=f_i \end{array}\right. \end{aligned}
\]
当 \(g_{i-1}=0\) 时,也就是没解,\(f_i=a_i,g_i=1\),从头开始。
代码同上。