【问题标题】:Algorithm for finding if an array is balanced [closed]查找数组是否平衡的算法[关闭]
【发布时间】:2013-05-02 02:16:28
【问题描述】:

我正在尝试创建一个程序,该程序将创建一个 10 元素数组,然后为每个元素分配随机值。然后我希望程序判断阵列是否平衡。平衡我的意思是,数组值中是否存在在某个元素处元素中的值的总和等于大于当前元素的元素中的数组值的总和。

例子

元素 (1,2,3,4) 值 (2,1,3,0) 然后程序会显示元素 1-2 与元素 3-4 平衡,因为它们都等于 4。

目前为止

import random

size = 10
mean = 0
lists = [0] * size
for i in range(size):
    var = random.randint(0,4)
    lists[i] = var

for i in lists:
    mean += i

avg = (mean)/(size)

我认为平衡元素的唯一方法是如果平均值等于 2,所以我认为我应该这样开始。

如果能在正确的方向上提供任何帮助,我将不胜感激。

【问题讨论】:

  • 制作n 元素的随机列表:lists = [randint(0, 4) for _ in range(n)]。要查找数字列表的均值/第一个样本矩:avg = sum(lists) / float(len(lists))
  • 你的变量名很混乱,比如有一个名为lists的列表,一共叫mean,……
  • 你的意思是你列表中某些元素的总和等于其他一些元素的总和,并且这两个组可能不相交吗?
  • @Lennart 是的,这就是我的意思。我知道这是一个令人困惑的问题。
  • 另外,您的逻辑令人困惑。您的示例中的平均值是 1.5,而不是 2,但它是平衡的。那么,是什么让您认为如果平均值为 2,则元素是平衡的?

标签: python arrays python-3.3


【解决方案1】:

如果我理解这个问题,最简单的解决方案是这样的:

def balanced(numbers):
    for pivot in range(len(numbers)):
        left_total = sum(numbers[:pivot])
        right_total = sum(numbers[pivot:])
        if left_total == right_total:
            return pivot
    return None

例如:

>>> numbers = [2, 1, 3, 0]
>>> balanced(numbers)
2
>>> more_numbers = [2, 1, 3, 4]
>>> balanced(numbers)

(没有打印任何内容,因为它返回了None,这意味着没有枢轴来平衡列表。)


虽然这是最简单的解决方案,但它显然不是最有效的,因为你会一遍又一遍地添加相同的数字。

如果您考虑一下,应该很容易弄清楚如何保持left_totalright_total 的总数,只调用一次sum

def balanced(numbers):
    left_total, right_total = 0, sum(numbers)
    for pivot, value in enumerate(numbers):
        if left_total == right_total:
            return pivot
        left_total += value
        right_total -= value
    return None

最后,以下是您可以围绕它构建程序的方法:

size = 10
numbers = [random.range(4) for _ in range(size)]
pivot = balanced(numbers)
if pivot is None:
    print('{} is not balanced'.format(numbers))
else:
    print('{} is balanced, because elements 1-{} equal {}-{}'.format(
        numbers, pivot+1, pivot+2, size+1))

【讨论】:

  • 关于你的最终函数的一个建议:如果列表是平衡的,在某些时候left_total 必须等于right_total,因此它们都必须等于整个列表总数的一半。因此,您可以通过计算sum(numbers)/2 一次并针对它测试left_total 来避免做一些工作。您无需随时更新right_total
【解决方案2】:

了解此类问题的一个很好的数据结构是具有累积和的数组。 element[j] - element[i] 是原始系列中 ij 的总和。如果您有原始系列[1, 2, 3, 4],则累积系列为[0, 1, 3, 6, 10]。原系列中i位置的总和是element[i] - element[0]。对于这个问题,我们只对从 0 开始的和感兴趣,所以这有点矫枉过正,但同样对其他问题更有用。

这里是累积和的代码:

def cumulative_sum(series):
    s = [0]
    for element in series:
        s.append(element + s[-1])
    return s

鉴于此,我们可以使用以下代码找到轴心点:

def find_pivot(series):
    cs = cumulative_sum(series)
    total = cs[-1]
    even_total = not (total & 1)
    if even_total:
        target = total // 2
        for i, element in enumerate(cs[1:]):
            if element == target:
                return i + 1
    return -1

请注意,如果我们知道系列总和为奇数,则没有必要尝试除以系列:那么就不存在枢轴点。

或者,您可以这样写find_pivot

def find_pivot(series):
    cs = cumulative_sum(series)
    total = cs[-1]
    even_total = not (total & 1)
    if even_total:
        target = total // 2
        try:
            return cs.index(target)
        except ValueError:
            return -1
    return -1

它的优点是循环不是在 python 中显式完成,而是在标准库的 C 代码中完成。

试用代码:

def test():
    for i in range(1, 30):
        test_values = range(i)
        j = find_pivot(test_values)
        if j >= 0:
            print "{0} == {1}".format(test_values[:j], test_values[j:])

我们得到这个输出:

[0] == []
[0, 1, 2] == [3]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] == [15, 16, 17, 18, 19, 20]

【讨论】:

    猜你喜欢
    • 2021-09-24
    • 2020-12-31
    • 1970-01-01
    • 1970-01-01
    • 2013-12-12
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 2020-01-16
    相关资源
    最近更新 更多