2.3 寻找发帖"水王"

问题一:有一个发帖数目最多的超级水王,其发帖数目超过帖子总数的一半,如果现在有一个论坛所有发帖的列表,找出这个水王

  1. 方法一
    最直接的的方法就是先排序,因为超级水王发帖数目超过一半,那么ID列表中的第N/2项就是超级水王的ID号,即ID[N/2]。时间是复杂为O(NlogN) + O(1)。

  2. 方法二
    为避免排序,降低时间复杂度,如果每次删除两个不同的ID号,不论有没有包含超级水王的ID,剩下的ID列表中依然满足条件—超级水王的发帖数目超过一半,但是问题的规模却缩小了。不断重复这个过程,最后ID列表中就只剩下超级水王的帖子了,就可以得到答案。时间复杂度为O(N),空间复杂度为常数项。

代码如下:

#include <iostream>
#include <cstring>

using namespace std;
const int N = 5;

int main()
{
    string Id[N] = {"1", "2", "3", "1", "1"};//初始化
    string resId;
    int times = 0;
    for(int i = 0; i < N; ++i){
        if(times == 0){
            resId = Id[i];
            ++times;
        }
        else{
            if(Id[i] == resId)
                ++times;
            else
                --times;
        }
    }

    cout << resId << endl;
    return 0;
}

问题二:有三个发帖数目最多的小水王,每个水王发帖数目超过帖子总数的四分之一,找出这三个水王

  1. 解决方法
    从问题一我们可以知道,每次删除四个不同的ID号,剩下列表中依然满足三个小水王发帖数目超过帖子总数的四分之一,不管有没有包含小水王的ID号。代码如下:
#include <iostream>
#include <cstring>

using namespace std;
const int N = 11;

int main()
{
    string Id[N] = {"1", "2", "3", "1", "1", "2", "2", "3", "3", "4","5"};//初始化
    string resId[3];
    int times[3] = {0, 0, 0};
    for(int i = 0; i < N; ++i){
        if(Id[i] == resId[0]){
            ++times[0];
        }
        else if(Id[i] == resId[1]){
            ++times[1];
        }
        else if(Id[i] == resId[2]){
            ++times[2];
        }
        else if(times[0] == 0){
            resId[0] = Id[i];
            ++times[0];
        }
        else if(times[1] == 0){
            resId[1] = Id[i];
            ++times[1];
        }
        else if(times[2] == 0){
            resId[2] = Id[i];
            ++times[2];
        }
        else{
            --times[0];
            --times[1];
            --times[2];
        }
    }

    cout << resId[0] << " "<< resId[1] << " " << resId[2] << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值