如果可能的话,制作一个序列

时间:2014-10-02 12:52:31

标签: c++ algorithm

如果此序列中任意两个连续数字之间的差值为-1或1且其第一个元素为0,则整数序列为单序列。

更准确地说:a1,a2,...,a是一个单序列,如果:

For any k (1 ≤  k < n): |a[k] - a[k+1]|=1, 
a[1]=0

给出n和s─一个中所有元素的总和。 W需要用给定的参数构造一个序列。

如果n = 8且s = 4,则其中一个序列为[0 1 2 1 0 -1 0 1]。

注意,对于给定的n和s,我们不能形成这样的序列,我们也需要告诉它不可能。否则我们需要告诉任何这样的序列。如何解决这个问题请帮忙。

2 个答案:

答案 0 :(得分:3)

首先,要确定是否可以解决,可以事先做好。由于你在每一步中都是+1或-1,你将从偶数,奇数,偶数到奇数......所以对于 n 的奇数值你只会是能够达到偶数,并且对于 n 的偶数值,您将只能达到奇数。可到达的范围也很简单:±(1 + 2 + 3 + ... + n)。

其次,如果您在每个步骤中绘制关于是向上(+1)还是向下(-1)的“决策树”,并在每个节点中绘制累计总和,您将看到您可以执行一种二进制搜索,用于在树中的一个叶子上找到总和。

如果您即将下冲,则转为+1,如果您即将超调则转为-1。棘手的部分是弄清楚你是否会出现下冲/过冲。你当前的“状态”应该由

计算

“我到目前为止所拥有的内容”+“我可以免费获得这个级别的剩余数据”。

您在“此级别”免费获得的内容为stepsLeft * previousValue

这是一些伪代码。

solve(stepsLeft, prev, acc) {
    if stepsLeft == 0, return empty list  // base case
    ifIStayHere = acc + prev*stepsLeft
    step = ifIstayHere > s ? prev-1 : prev+1
    return [step] concatenated by solve(stepsLeft-1, step, acc+step)
}

请注意,此解决方案不包含初始值0,因此请使用stepsLeft = n-1调用它。

正如你所看到的,它是θ(n),它适用于我测试过的所有情况。 (在Java中实现。)

答案 1 :(得分:3)

这是对aioobe算法的另一种看法,正式证明了正确性。

给定序列a(k),定义差序列d(k)= a(k + 1) - a(k)并观察a(1)+ a(2)+ ... + a( n)=(n-1)d(1)+(n-2)d(2)+ ... + 1d(n-1)。

参数n和s的

定理:,当且仅当(1)n(n-1)/ 2 mod 2 = s mod时,存在长度为n的单序列与s的求和2和(2)| s | ≤n(n-1)/ 2。

证明:通过感应n。基本情况,n = 1,是微不足道的。归纳地,由于d(k)∈{±1},我们观察到(1)和(2)都是必要条件,因为n-1 + n-2 + ... + 1 = n(n-1)/ 2和-1 mod 2 = 1 mod 2.相反,假设(1)和(2)。如果s≥0,则构造一个长度 - (n-1)序列,总和为s - (n-1)。如果s&lt;然后,构建长度 - (n-1)序列,总和为s +(n-1)。 (1)和(2)都满足这些结构(省略了一些繁琐的案例分析),因此从归纳假设得出它们成功。根据s≥0/ s <1,将该序列的元素增加/减少1。 0并在开头放0。

由于定理的证明是建设性的,我们可以用Python实现它。

def oneseq(n, s):
    assert isinstance(n, int)
    assert isinstance(s, int)
    nchoose2 = n*(n-1)//2
    abss = abs(s)
    if n < 1 or abss%2 != nchoose2%2 or abss > nchoose2: return None
    a = [0]
    for k in range(n-1, 0, -1):  # n-1, n-2, ..., 1
        d = 1 if s >= 0 else -1
        a.append(a[-1] + d)  # a[-1] equivalent to a[len(a) - 1]
        s -= k*d
    return a