CodeJam 2014:中继器的解决方案

时间:2014-05-05 02:58:51

标签: string algorithm

我参与了代码卡塞,我成功解决了The Repeater Challenge的小输入,但似乎无法找出多个字符串的方法。

任何人都可以给出用于多个字符串的算法。对于2个字符串(小输入),我逐字符地比较字符串并进行操作以使它们相等。然而,这种方法可能需要大量输入。

有人可以解释他们使用的算法吗?我可以看到其他用户的解决方案,但无法弄清楚他们做了什么。

3 个答案:

答案 0 :(得分:7)

我可以告诉你我的解决方案适用于小型和大型输入。 首先,我们必须看看是否有解决方案,你可以通过将所有字符串带到最简单的"形成。如果它们中的任何一个不匹配,则没有解决方案。

e.g。

aaabbbc => abc
abbbbbcc => abc
abbcca => abca

如果只给出了前两个,那么就可以找到解决方案。只要第三个被投入混合,那就不可能了。算法做了简化"是解析字符串并消除您看到的任何双字符。一旦字符串不等于批次的简化形式,就会纾困。

至于问题的实际解决方案,我只是将字符串转换为[letter,repeat]格式。例如,

qwerty => 1q,1w,1e,1r,1t,1y
qqqwweeertttyy => 3q,2w,3e,1r,3t,2y

(请注意,输出是内部结构,而不是实际的字符串)

想象一下,现在你有100个字符串,你已经通过了测试,有一个解决方案,你有[字母,重复]表示的所有字符串。现在浏览每一封信,找出最小的差异'你必须做的重复,达到相同的数字。例如,

1a, 1a, 1a => 0 diff
1a, 2a, 2a => 1 diff
1a, 3a, 10a => 9 diff (to bring everything to 3)

这样做的方式(我非常确定有一种更有效的方法)是从最小数字到最大数字并计算所有差异的总和。您无法保证该号码将成为该组号码中的一个。对于最后一个例子,你将计算差异以使一切为1(0,2,9 = 11)然后为2(1,1,8 = 10),为3(2,0,7 = 9)和所以最多10个并再次选择min。字符串限制为1000个字符,因此这是一个简单的计算。在我的中等笔记本电脑上,结果是即时的。

对字符串的每个字母重复相同的操作并总结一切,这就是你的解决方案。

答案 1 :(得分:2)

这个答案给出了一个例子来解释为什么找到重复的中位数会产生最低的成本。

假设我们有值:

1 20 30 40 100

我们正在尝试找到与所有这些值之间的总距离最短的值。

我们可能猜测最佳答案是50,成本| 50-1 | + | 50-20 | + | 50-30 | + | 50-40 | + | 50-100 | = 159。

将其拆分为左右两个总和,其中左边是目标左边所有数字的成本,右边是右边所有数字的成本。

left = |50-1|+|50-20|+|50-30|+|50-40| = 50-1+50-20+50-30+50-40 = 109
right = |50-100| = 100-50 = 50
cost = left + right = 159

现在考虑用x更改值。提供x足够小,使得相同的数字在左侧,然后值将变为:

left(x) = |50+x-1|+|50+x-20|+|50+x-30|+|50+x-40| = 109 + 4x
right(x) = |50+x-100| = 50 - x
cost(x) = left(x)+right(x) = 159+3x

因此,如果我们设置x = -1,我们会将成本降低3,因此最佳答案不是50。

如果我们移动,我们的成本将改变的金额由我们左边的数字(4)和右边的数字(1)之间的差异给出。

因此,只要这些不同,我们就可以通过向中位数移动来降低成本。

因此,中位数的成本最低。

如果存在偶数个点,例如1,100,则两个中间点之间的所有数字将产生相同的成本,因此可以选择任何这些值。

答案 2 :(得分:1)

由于Thanasis已经解释了解决方案,我在这里提供了Ruby中的源代码。它真的很短(只有400B)并完全遵循他的算法。

def solve(strs)
    form = strs.first.squeeze
    strs.map { |str|
        return 'Fegla Won' if form != str.squeeze
        str.chars.chunk { |c| c }.map { |arr|
            arr.last.size
        }
    }.transpose.map { |row|
        Range.new(*row.minmax).map { |n|
            row.map { |r|
                (r - n).abs
            }.reduce :+
        }.min
    }.reduce :+
end

gets.to_i.times { |i|
    result = solve gets.to_i.times.map { gets.chomp }
    puts "Case ##{i+1}: #{result}"
}

它在字符串上使用方法squeeze,删除所有重复的字符。这样,您只需将每个压缩线与参考(变量form)进行比较。如果存在不一致,您只需返回 Fegla Won

接下来,在char数组上使用chunk方法,该方法收集所有连续字符。这样您就可以轻松统计它们。