【问题标题】:Comparison between adjacent elements in sequences序列中相邻元素之间的比较
【发布时间】:2012-05-04 00:08:53
【问题描述】:

我需要一个序列中元素之间的比较索引。该索引是一个序列中相邻元素之间所有绝对比较的总和与一个序列及其长度可以具有的最大值之间的商。

例如,序列s1 = [0, 1, 2] 和s2 = [0, 2, 1] 分别具有绝对比较[1, 1] 和[2, 1]。没有其他长度为 3 的序列的绝对比较和值高于 3 的组合。因此,s1 和 s2 的比较索引应为 2/3 和 3/3。

这些序列总是有从0 到length - 1 的整数,并且可以有不相邻的重复元素,例如[0, 1, 0, 1, 0]。这些序列的所有元素值都在其较低和最高元素值之间。

我需要一个函数来计算给定长度的序列可以具有的绝对比较和的最大值。我写的函数(最高)返回错误的结果。 我写了这段代码:

    def aux_pairs(seq):
        n = 2
        return [seq[i:i + n] for i in range(len(seq) - (n - 1))]

    def comparisons_sum(seq):
        return sum([abs(el[-1] - el[0]) for el in aux_pairs(seq)])

    def highest(seq):
        card = len(seq)
        pair = [0, card - 1]
        r = (pair * (card / 2))
        if card & 1 == 1:
            r.append(0)
        return comparisons_sum(r)

    def comparison_index(seq):
        return comparisons_sum(seq) / float(highest(seq))

【问题讨论】:

  • 我不太确定您在比较索引方面的目标是什么,您能澄清一下吗?不就是sum(comp)/len(seq)吗?
  • @Lattyware,索引可能不是描述我需要的最佳术语。分母应该是具有该长度的所有序列中具有最高 sum(com) 的序列的比较。例如,取长度 3:
  • 抱歉,我按下了回车键。继续... 取长度为 3 的序列及其总和(com): [0, 1, 0] 2 [0, 1, 2] 2 [0, 2, 1] 3 [1, 0, 1] 2 [1, 0, 2] 3 [1, 2, 0] 3 [2, 0, 1] 3 [2, 1, 0] 2 长度为 3 的 sum(com) 的最大值是 3。所以,我的 ' 的分母index' 应该是 3。
  • 对,这些序列是否已定义、是否需要生成,或者是否有算法可以解决(或者这就是问题所在)?
  • @Lattyware,我可以用给定长度的所有序列进行残酷的求和(com)演算,以获得最高值,但我想使用一些算法。问题是我该如何编写这个算法。

标签: python list sequence


【解决方案1】:

生成列表的最简单方法是:

def comparisons(seq):
    return [abs(a-b) for a, b in zip(seq, seq[1:])]

就您的比较而言,最​​大值始终是最大值,然后是最小值,重复。例如:长度为 4:

[3, 0, 3, 0]

因为这每次都会产生最大的差异。对于比较字符串(长度为length-1)中的每个项目,将存在这些最大差异之一(length-1)。因此最大值为(length-1)**2。

但是,您似乎暗示长度 3 的最大值是 3,那么为什么 [0, 2, 0] 无效(产生 [2, 2] 总和为 4)?

您提到必须包含从0 到length-1 的所有整数,但这会使您的一些示例(例如:[0, 1, 0])无效。这也与任何元素都可以重复的想法相冲突(如果长度为 n 的列表必须包含从 0 到 n-1,则它不能有重复)。

如果这种情况属实,那么你的问题就有点类似于创建抖动矩阵的问题了。

在排序范围从 0 到 len-1 的情况下,为了产生最大差异,最佳算法是从 0 向上工作,从 len-1 向下工作,将低值添加到最高的“边”列表,反之亦然:

from collections import deque
from itertools import permutations
from operator import itemgetter

def comparisons(seq):
    return [abs(a-b) for a, b in zip(seq, seq[1:])]

def best_order(n):
    temp = deque([0, n-1])
    low = 1
    high = n-2
    while low < high:
        left = temp[0]
        right = temp[-1]
        if left < right:
            temp.append(low)
            temp.appendleft(high)
        else:
            temp.append(high)
            temp.appendleft(low)
        low += 1
        high -= 1
    if len(temp) < n:
        temp.append(low)
    return list(temp)

def brute_force(n):
    getcomp = itemgetter(2)
    return max([(list(a), comparisons(a), sum(comparisons(a))) for a in permutations(range(n))], key=getcomp)

for i in range(2, 6):
    print("Algorithmic:", best_order(i), comparisons(best_order(i)), sum(comparisons(best_order(i))))
    print("Brute Force:", *brute_force(i))

这给了我们:

Algorithmic: [0, 1] [1] 1
Brute Force: [0, 1] [1] 1
Algorithmic: [0, 2, 1] [2, 1] 3
Brute Force: [0, 2, 1] [2, 1] 3
Algorithmic: [2, 0, 3, 1] [2, 3, 2] 7
Brute Force: [1, 3, 0, 2] [2, 3, 2] 7
Algorithmic: [3, 0, 4, 1, 2] [3, 4, 3, 1] 11
Brute Force: [1, 3, 0, 4, 2] [2, 3, 4, 2] 11

表明该算法与蛮力方法相匹配以产生可能的最佳结果。

以下是更通用的解决方案:

from collections import deque

def comparisons(seq):
    return [abs(a-b) for a, b in zip(seq, seq[1:])]

def best_order(seq):
    pool = deque(sorted(seq))
    temp = deque([pool.popleft(), pool.pop()])
    try:
        while pool:
            if temp[0] < temp[-1]:
                temp.append(pool.popleft())
                temp.appendleft(pool.pop())
            else:
                temp.append(pool.pop())
                temp.appendleft(pool.popleft())
    except IndexError:
        pass
    return list(temp)

i = [0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 1, 2, 2]
print("Algorithmic:", best_order(i), comparisons(best_order(i)), sum(comparisons(best_order(i))))
for n in range(2, 6):
    i = list(range(n))
    print("Algorithmic:", best_order(i), comparisons(best_order(i)), sum(comparisons(best_order(i))))

这给出了:

Algorithmic: [2, 1, 3, 0, 5, 0, 6, 0, 4, 1, 2, 1, 2] [1, 2, 3, 5, 5, 6, 6, 4, 3, 1, 1, 1] 38
Algorithmic: [0, 1] [1] 1
Algorithmic: [0, 2, 1] [2, 1] 3
Algorithmic: [2, 0, 3, 1] [2, 3, 2] 7
Algorithmic: [3, 0, 4, 1, 2] [3, 4, 3, 1] 11

尽可能匹配之前的结果。

【讨论】:

  • @MarcosdaSilvaSampaio 查看我的更新,我想这就是你要找的。​​span>
  • 太棒了!我只会更改permutations(range(n))。我需要包含一些有效的序列,例如 [0, 1, 0] 和 [1, 0, 1]。
  • @MarcosdaSilvaSampaio 好吧,那部分仅用于蛮力,用于比较。此外,如果允许有重复数字的序列,这将不起作用,早期的解决方案 ((length(seq)-1)**2) 是最好的,因为您可以使用[length(seq)-1, 0, length(seq)-1, 0, ...]。重复字符的实际情况是什么?
  • 重复字符的条件: 1. 只有不相邻的字符 2. 一个序列的最大值是长度 - 1 - 重复字符的个数。
  • 也许这个功能可以帮助你理解我的序列:def translate(seq): return [sorted(list(set(seq))).index(x) for x in seq]。我对所有序列都使用这个函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-05
  • 2021-04-28
  • 1970-01-01
  • 1970-01-01
  • 2017-11-19
  • 2020-08-15
  • 2012-06-21
相关资源
最近更新 更多