Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 面试算法_Algorithm - Fatal编程技术网

Algorithm 面试算法

Algorithm 面试算法,algorithm,Algorithm,最近我被问到以下面试问题: 有两组长度相同的数字N,例如A=[3,5,9]和B=[7,5,1]。接下来,对于0..N-1范围内的每个位置i,您可以选择数字A[i]或B[i],因此在最后,您将有另一个长度为N的数组C,该数组由A和B中的元素组成。如果C中所有元素的总和小于或等于K,则该数组是好的。请编写一个算法,根据给定的数组A、B和数字K计算出好数组的总数 我提出的唯一解决方案是动态规划方法,当我们有一个大小为NxK的矩阵,M[I][j]表示如果当前和等于j,我们可以有多少个数字X[I]的组合。

最近我被问到以下面试问题: 有两组长度相同的数字N,例如A=[3,5,9]和B=[7,5,1]。接下来,对于0..N-1范围内的每个位置i,您可以选择数字A[i]或B[i],因此在最后,您将有另一个长度为N的数组C,该数组由A和B中的元素组成。如果C中所有元素的总和小于或等于K,则该数组是好的。请编写一个算法,根据给定的数组A、B和数字K计算出好数组的总数


我提出的唯一解决方案是动态规划方法,当我们有一个大小为NxK的矩阵,M[I][j]表示如果当前和等于j,我们可以有多少个数字X[I]的组合。但看起来他们希望我能想出一个公式。你能帮我一下吗?至少我应该找什么方向?谢谢你的帮助。谢谢。

所以有2^N个选择,因为在每个点上,你要么从A中选择,要么从B中选择。在具体的例子中,你给出了其中N正好是3,有8个。为了便于讨论,您可以将每组决策描述为位模式

因此,作为一种蛮力方法,我们将尝试每一个位模式

但显而易见的是,如果前几位产生的数字太大,那么每个后续可能的尾位组也会产生一个太大的数字。因此,更好的建模方法可能是一棵树,在树上你不必费心沿着已经超出你极限的四肢行走

您还可以计算从每一位到表尾可以达到的最大总数。如果在任何一点上,你的跑步总量加上你从这里获得的最大值小于K,那么你所在的每一个子树都是可以接受的,而不需要遍历。正如评论中所讨论的,每种组合都是可接受的,这种情况是这种观察的一个特例

正如下面Serge所指出的,一个相关的观察结果是使用最小值,并使用逆向逻辑取消整个子树,而不进行遍历

一个潜在的进一步优化存在于这样一个观察结果背后:只要我们以相同的方式洗牌,改变A和B的顺序就没有效果,因为加法是可交换的。因此,您可以努力确保最大值尽可能快地增长或最小值尽可能慢地增长,以尝试尽早退出遍历。实际上,您可能希望应用一种启发式方法,将绝对最大值和最小值(您已经计算过这两个值)与K进行比较

在这种情况下,递归实现是最简单的,例如(在C中)

/*假设A、B和N是已知的全局变量*/
无符号整数OfGoodArraySFromBit(
无符号整数位,
unsigned int runningTotal,
无符号整数限制)
{
//我们是否陷入了一个不可接受的子树?
如果(runningTotal>limit)返回0;
//我们已经到达叶节点了吗
//发现此子树不可接受有什么意义?
如果(位>=N)返回1;
//也许每个子树都是可以接受的?
如果(runningTotal+MAXV[bit]=0;i--)
{
MAXV[i]+=MAXV[i+1];
MINV[i]+=MINV[i+1];
}
//开始
printf(“总有效组合为%u”,numberOfGoodArraysFromBit(0,0,K));
我只是在即兴思考,可能存在更好的解决方案

“请写一个算法来计算出货物的总数 由给定数组A、B和数字K组成的数组。“

这不是目标吗

int A[];
int B[];
int N;
int K;
int Solutions = 0;

void FindSolutons(int Depth, int theSumSoFar) {
    if (theSumSoFar > K) return;
    if (Depth >= N) {
    Solutions++;
    return;
    }

    FindSolutions(Depth+1,theSumSoFar+A[Depth]);
    FindSolutions(Depth+1,theSumSoFar+B[Depth]);
}

调用
FindSolutions
,将两个参数都设置为零。返回时
解决方案将等于良好数组的数量;

这就是我试图解决问题的方法 (如果这很愚蠢,我很抱歉)

想想数组

A=[3,5,9,8,2]
B=[7,5,1,8,2]

如果 元素 0..N-1

选择的数量

2^N

然后创建新的两个数组,如

A1=[3,5,9]
B1=[7,5,1]
现在C2是10

现在所有选项的数量减少到2^(N-C1)

现在计算所有好的数字

使用“K”作为K=K-C2

不幸的是 不管你用什么方法,你都有
经过一些考虑,要计算2^(N-C1)次之和,我认为这是一个NP完全问题。考虑:

A = [0, 0, 0, ..., 0]
B = [b1, b2, b3, ..., bn]
注意,第三个集合
C=(i=0..n的A[i]或B[i])
的每一个构造都只是
A
的某个子集和
B
的某个子集的并集。在这种情况下,由于
A
的每一个子集和
0
,因此
C
的和与
B
的某个子集的和相同

现在你的问题“我们有多少种方法可以用小于
K
的和来构造
C
?”可以重述为“有多少
B
的子集和小于
K
?”。为
K=1
K=0解决这个问题可以得到
B
(两种解决方案之间的差异是总和为0的子集数)

通过类似的论证,即使在
A
包含非零元素的一般情况下,我们也可以构造一个数组
S=[b1-a1,b2-a2,b3-a3,…,bn-an]
,问题变成了“有多少
S
的子集和小于
K-sum(A)
?”


由于子集和问题是NP完全的,所以这个问题也必须是NP完全的。因此,考虑到这一点,我敢说,您提出的动态规划解决方案是您能做到的最好的,当然不存在神奇的公式。

我认为这不是一个很好的方法,在每个子集都很好的情况下,您将遍历整个树是的,我同意,如果我们首先计算一个max(a[I],B[I])数组的和,那么我们可以过滤掉这个唯一的情况。也许我们可以找到一种方法使它在最坏的情况下为O(2^(n-1))?在这种情况下,最好的优化是产生长度为n的C,C[I]=max(a[I],B[I])a
A1=[3,5,9]
B1=[7,5,1]
A = [0, 0, 0, ..., 0]
B = [b1, b2, b3, ..., bn]