PAT 甲1129. Recommendation System
测试点一(第二个测试点) 一直通不过,哪位大哥帮我看看55555
如果通过了,我第一时间来写题解 5555
我的解题思路如下:
1、维护一个数组Times[],Times[i]表示商品i被询问的次数,也就是输入的次数。
2、vector存放结果数组,保证每个元素在数组中都唯一出现。
3、每轮都对结果数组前k个元素中进行排序,出现的次数越多越靠前,其次就是商品编号越小越靠前。
4、每次输入都和结果数组中第K个元素进行比较,如果输入的元素优先级高于第K个元素那么就用当前输入的元素替换掉第K个元素。
#include<bits/stdc++.h>
using namespace std;
int Times[50004];
vector<int> q;
int cmp(int a, int b) {
if (Times[a] != Times[b])
return Times[a] > Times[b];
else return a < b;
}
int main() {
int N, K,temp; scanf("%d %d", &N, &K);
for (int i = 0; i < N; i++) {
scanf("%d", &temp);
Times[temp]++;
int len = q.size();
if(Times[temp] == 1)
q.push_back(temp);
if(i==0) continue;
printf("%d: %d", temp,q[0]);
for (int i = 1; i < len && i < K; i++)
printf(" %d", q[i]);
len = q.size();
if (len > K) {
///就是这个地方出现了问题,这个判断语句
if ((Times[q[K - 1]] == Times[q[len - 1]] && q[len - 1] < q[K - 1]) || Times[q[len - 1]] > Times[q[K - 1]])
q[K - 1] = q[len - 1];
sort(q.begin(), q.begin() + K, cmp);
}
else
sort(q.begin(), q.end(), cmp);
printf("\n");
}
}
有一位大哥给我提出意见:
代码这一块存在问题
if ((Times[q[K - 1]] == Times[q[len - 1]] && q[len - 1] < q[K - 1]) || Times[q[len - 1]] > Times[q[K - 1]])
其问题在于,有时候不能拿已加入的旧元素,与数组q中的第K-1个元素进行比较,比如下面的测试样例 就存在这个问题。
输入样例
13 2
5 5 6 6 7 7 8 8 1 9 9 1 1
正确输出样例为:
5: 5
6: 5
6: 5 6
7: 5 6
7: 5 6
8: 5 6
8: 5 6
1: 5 6
9: 5 6
9: 5 6
1: 5 6
1: 1 5
而我的程序输出样例为:
5: 5
6: 5
6: 5 6
7: 5 6
7: 5 6
8: 5 6
8: 5 6
1: 5 6
9: 5 6
9: 5 6
1: 5 6
1: 5 6
这是因为并不是每次输入的元素都在数组p的最后,有可能之前就存在于p中这次输入后,仅仅将该元素出现的次数+1,而不会将该元素push_back()进数组中,所以导致了上述测试样例出现错误。
所以我将q[len-1](当前数组的最后一个元素)换成了temp(当前输入的元素值)。
if (len == K && find_element(temp)) {
if ((Times[q[K - 1]] == Times[temp] && temp < q[K - 1]) || Times[temp] > Times[q[K - 1]])
q[K - 1] = temp;
sort(q.begin(), q.begin() + K, cmp);
}
这也引入了一个新的问题,就是可能在前K个元素中已经出现了当前输入的元素,temp。执行指令q[K - 1] = temp;
之后会导致前K个元素中出现两个相同的元素temp。这是不允许的所以,我还需要判断在结果素组组中前K个元素是否已经出现了temp元素。所以我就加上了一个find_elememt()函数,这样就可以通过上面的那个测试案例了。
写好之后我信誓旦旦的提交了自己代码:
#include<bits/stdc++.h>
using namespace std;
int Times[50004];
vector<int> q;
int N, K, temp;
int cmp(int a, int b) {
if (Times[a] != Times[b])
return Times[a] > Times[b];
else return a < b;
}
int find_element(int x) {
for (int i = 0; i < K&&i < q.size(); i++) {
if (q[i] == x) return 0;
}
return 1;
}
int main() {
#ifdef ONLINE_JUDGE
#else
freopen("Text.txt", "r", stdin);
#endif
scanf("%d %d", &N, &K);
for (int i = 0; i < N; i++) {
scanf("%d", &temp);
Times[temp]++;
int len = q.size();
if (Times[temp] == 1)
q.push_back(temp);
if (i == 0) continue;
printf("%d: %d", temp, q[0]);
for (int i = 1; i < len && i < K; i++)
printf(" %d", q[i]);
len = q.size();
if (len > K && find_element(temp)) {
if ((Times[q[K - 1]] == Times[temp] && temp < q[K - 1]) || Times[temp] > Times[q[K - 1]])
q[K - 1] = temp;
sort(q.begin(), q.begin() + K, cmp);
}
else
sort(q.begin(), q.end(), cmp);
printf("\n");
}
}
但是结果给了我当头一棒:
还是没有通过。然后我自己又琢磨琢磨,先把自己的代码简化,优化,首先发现结果数组其实加到K个就好了,然后我就结果数组的最大容量限制在了K。也就是push_back()的时候加上了一个限制(len<K)。
if (len<K&&Times[temp]==1)
q.push_back(temp);
优化了之后,我试探性得提交了一下代码:wocao居然AC了,测试点一也过了。但是我自己还是不知道测试点一测试的是哪种特殊的数据,不知道考察的是边界检查还是啥特殊情况。(如果想通了来更新博文,也希望大佬帮帮我,救救孩子。)
看完之后点个点个赞呗~,鼓励鼓励我早点想出来。
AC代码如下:
#include<bits/stdc++.h>
using namespace std;
int Times[50004];
vector<int> q;
int N, K, temp;
int cmp(int a, int b) {
if (Times[a] != Times[b])
return Times[a] > Times[b];
else return a < b;
}
int find_element(int x) {
for (int i = 0; i < K&&i < q.size(); i++) {
if (q[i] == x) return 0;
}
return 1;
}
int main() {
scanf("%d %d", &N, &K);
for (int i = 0; i < N; i++) {
scanf("%d", &temp);
Times[temp]++;
int len = q.size();
if (len<K&&Times[temp]==1)
q.push_back(temp);
if (i == 0) continue;
printf("%d: %d", temp, q[0]);
for (int i = 1; i < len && i < K; i++)
printf(" %d", q[i]);
len = q.size();
if (len == K && find_element(temp)) {
if ((Times[q[K - 1]] == Times[temp] && temp < q[K - 1]) || Times[temp] > Times[q[K - 1]])
q[K - 1] = temp;
sort(q.begin(), q.begin() + K, cmp);
}
else
sort(q.begin(), q.end(), cmp);
printf("\n");
}
}