【发布时间】:2016-02-02 08:14:16
【问题描述】:
我在面试挑战中遇到了这个问题
K 条毛毛虫在 N 片叶子中觅食,每条毛毛虫 以独特的顺序从一片叶子落到另一片叶子,所有毛毛虫开始 在位置 0 的树枝上,落在位置之间的叶子上 1 和 N。每条毛虫 j 都有一个相关的跳跃编号 Aj。一种 跳跃数 j 的毛毛虫在以下位置吃树叶 j的倍数。它将按照 j、2j、3j 的顺序进行。直到它 到达叶子的末端,它会停下来并筑茧。给定 一组 A 的 K 个元素,我们需要确定个数 没吃的叶子。
约束:
1 9
1
1 9
输入格式:
N = 未吃的叶子数。
K = 毛毛虫的数量。
A = 整数数组。 跳转数字输出:
整数 nu。没吃完的叶子
示例输入:
103245输出:
4说明:
[2, 4, 5] 是 3 成员的跳跃数字集。吃掉所有 2、4 和 5 倍数的叶子。只剩下 4 片叶子,编号为 1,3,7,9。
解决这个问题的简单方法是使用一个包含所有 N 个数字的 布尔 数组,然后遍历每条毛毛虫并记住它吃过的叶子。
int uneatenusingNaive(int N, vector<int> A)
{
int eaten = 0;
vector<bool>seen(N+1, false);
for (int i = 0; i < A.size(); i++)
{
long Ai = A[i];
long j = A[i];
while (j <= N && j>0)
{
if (!seen[j])
{
seen[j] = true;
eaten++;
}
j += Ai;
}
}
return N - eaten;
}
这种方法通过了 10 个测试用例中的 8 个,并为 2 个用例给出错误答案。
另一种使用Inclusion Exclusion principle的方法,可以在here和here找到它的解释
下面是我的第二种方法的代码
int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a%b);
}
int lcm(int i, int j)
{
return i*j / gcd(i, j);
}
vector<vector<int>> mixStr(vector<vector<int>> & mix, vector<int>& A, unordered_map<int, int> & maxStart)
{
vector<vector<int>> res;
if (mix.size() == 0)
{
for (int i = 0; i < A.size(); i++)
{
vector<int> tmp;
tmp.push_back(A[i]);
res.push_back(tmp);
}
return res;
}
for (int i = 0; i<mix.size(); i++)
{
int currSlotSize = mix[i].size();
int currSlotMax = mix[i][currSlotSize - 1];
for (int j = maxStart[currSlotMax]; j < A.size(); j++)
{
vector<int> tmp(mix[i]);
tmp.push_back(A[j]);
res.push_back(tmp);
}
}
return res;
}
int uneatenLeavs(int N, int k, vector<int> A)
{
int i = 0;
vector<vector<int>> mix;
bool sign = true;
int res = N;
sort(A.begin(), A.end());
unordered_map<int,int> maxStart;
for (int i = 0; i < A.size(); i++)
{
maxStart[A[i]] = i + 1;
}
int eaten = 0;
while (mix.size() != 1)
{
mix = mixStr(mix, A, maxStart);
for (int j = 0; j < mix.size(); j++)
{
int _lcm = mix[j][0];
for (int s = 1; s < mix[j].size(); s++)
{
_lcm = lcm(mix[j][s], _lcm);
}
if (sign)
{
res -= N / _lcm;
}
else
{
res += N / _lcm;
}
}
sign = !sign;
i++;
}
return res;
}
这种方法只通过了一个 1/10 的测试用例。对于其余的测试用例超出时间限制和错误答案。
问题:
我在第一种或第二种方法中缺少什么是 100% 正确的。
【问题讨论】:
-
您提到第一种方法通过 8/10。你能提供它成功/失败的例子吗?
-
@shapiroyaacov 不幸的是,测试用例被隐藏了。
标签: c++ algorithm discrete-mathematics