您的位置:首页 > 编程语言

编程之美 - 寻找灌水王及扩展问题

2016-03-17 20:23 183 查看
问题描述:
在一个论坛中,一个ID发的帖子超过了半数,问怎样能快速的找出这个ID。

算法描述:

书中给出了几种不同的思考方式,
1) 先排序,然后逐个统计
2) 排序后,第 N/2个元素一定是这个ID

最好的方式是第三种,每次删除两个不同的ID,那么水王的ID在剩下的列表中仍然超过一半。

或者可以这样理解 假设总共有10个帖子,6个是水王的,假设水王的ID是 1
A : [1,1,1,1,1,1]
B: [2,3,4,5]
从A中取一个,从B中取一个 删除两个,经过4轮删除后后 剩下的就是水王的ID了。

算法的实现:用一个变量记录当前操作的ID,一个变量记录这个ID出现的次数。
如果当前操作的ID和 id_list[i]相同的话,就把ID出现的次数 +1;
如果不同就ID出现的次数 -1,相当于一次删除了两个ID;
入当前ID出现的次数为 0 了,说明当前操作的ID可能不是水王的,需要把ID换成id_list[i]在继续操作

示例程序

#include <iostream>

using namespace std;

int find(int* arr, int len)
{
int i = 0;
int nCnt = 0;
int nIndex = 0;

for (i = 0; i < len; i++)
{
if (nCnt == 0)
{
nIndex = arr[i];
nCnt++;
}
else
{
if (nIndex == arr[i])
nCnt++;
else
nCnt--;
}
}
return nIndex;
}

int main()
{
int test[] = {8, 1, 1, 2, 3, 4, 5, 6,
8, 8, 8, 8, 8, 8, 8, 8,};
int nLen = sizeof(test)/sizeof(test[0]);
int nResult = -1;

nResult = find(test, nLen);
cout << "Find result = " << nResult << endl;
cin >> nResult;

return 0;
}


=================================================================

扩展问题:
在论坛中有三个ID,每个ID的发帖数都超过了1/4,快速找出这三个ID。

思考方法:
方向和一个ID是类似的,只不过将一个操作ID转换为一个操作ID列表。
或者叫水王备选ID列表,当id_list[i],与这个列表中某一个一致时,则把一致的 +1
否则,将列表中的都 -1,如果出现 0,则将该ID淘汰出水王备选列表。

示例程序:

#include <iostream>

using namespace std;

void debug_print(int index[], int count[])
{
for (int i = 0; i < 3; i++)
{
cout << index[i] << ":"<< count[i] << endl;
}
cout << "=====================================" << endl;
}

int check(int index[], int count[], int target)
{
int i = 0;
for (i = 0; i < 3; i++)
{
if ((index[i] == target) || (count[i] == 0))
return i;
}
return -1;
}

void find(int* arr, int len)
{
int i = 0, j = 0;
int curr = 0;
int nCnt[3] = {0,0,0};
int nIndex[3] = {0,0,0};

for (i = 0; i < len; i++)
{
if ((curr = check(nIndex, nCnt, arr[i])) != -1)
{
if ((nIndex[curr] == 0) || nCnt[curr] == 0) nIndex[curr]= arr[i];
nCnt[curr]++;
}
else
{
for (j = 0; j < 3; j++)
{
nCnt[j]--;
}
}
debug_print(nIndex, nCnt);
}

if ((nCnt[0] > 0) || (nCnt[1] > 0) || (nCnt[2] > 0))
{
cout << nIndex[0] << "  "<< nIndex[1] << "  "<< nIndex[2] << "  " << endl;
}
else
{
cout << "None is larger than 1/4" << endl;
}
}

int main()
{
//int test[] = {1};
//int test[] = {2, 1, 1, 2, 3, 4, 3, 3, 1, 2};  // N = 10  3:3:3:1
//int test[] = {2, 1, 3, 4,};                   // N = 4  1:2:3:4 a fail case
//int test[] = {1, 1, 1, 2, 4, 4, 3, 3, 1, 2,
//              2, 1, 1, 2, 3, 4, 3, 3, 1, 2,
//              2, 1, 1, 2, 3, 4, 3, 3, 1, 2};  // N = 30  10:8:8:4
int test[] = {1, 1, 1, 2, 3, 2, 1, 3, 1, 2};    // N = 10  5:3:2
int nLen = sizeof(test)/sizeof(test[0]);
find(test, nLen);
cin >> nLen;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: