【问题标题】:Keep getting wrong answer for Integer List challenge on Kattis even though it works just fine for the test case在 Kattis 上不断得到整数列表挑战的错误答案,即使它对测试用例工作得很好
【发布时间】:2023-02-15 04:35:05
【问题描述】:

我正在尝试解决 Kattis 上的整数列表挑战。

for _ in range(int(input())):
    operation, elements = input(), int(input())
    error = False
    if elements <= 0:
        input()
        print('error')
    else:
        inp_lst = list(map(int, input().strip('[]').split(',')))
        for op in operation:
            try:
                if op == 'R':
                    inp_lst.reverse()
                elif op == 'D':
                    inp_lst.pop(0)
            except IndexError:
                print('error')
                error = True
                break
        if not error:
            print(inp_lst)

示例输入:

4
RDD
4
[1,2,3,4]
DD
1
[42]
RRD
6
[1,1,2,3,5,8]
D
0
[]

预期输出:

[2,1]
error
[1,2,3,5,8]
error

我的代码确实得到了正确的输出,但它仍然被标记为错误。我不确定我的解决方案有什么问题。任何帮助,将不胜感激。

【问题讨论】:

  • 你期望什么,你的程序的结果是什么?
  • 您放错了指向 Kattis 的链接。所以现在你的代码似乎输出了它应该输出的内容。
  • “我的代码确实得到了正确的输出,但它仍然被标记为错误。我不确定我的解决方案有什么问题。”我们不为问题分析代码;我们回答有关已发现问题的问题。尝试找到一个输入示例没有导致正确的输出。除此之外,我们还需要问题本身的问题说明;我们需要一个问题描述,相应的代码和问题都是专注的一、具体问题(不是来自作业或竞赛问题的总体任务)。请阅读How to Askminimal reproducible example 了解更多。

标签: python python-3.x algorithm


【解决方案1】:

你的解决方案是直截了当。反转列表并删除第一个元素是一个 O(n) 操作,您可能会重复 O(len(p)) 次。显然,一个O(n * len(p))的解决方案会超时,并且会被标记为错误。

要改进解决方案,您需要认识到实际上不需要颠倒列表。您可以通过跟踪像列表头一样“起作用”的末端来操纵它。

【讨论】:

  • 好主意,但即使进行了此优化,它仍然会超时。不管什么原因把难度列为“hard”,一定有妙招。
【解决方案2】:

这是那些看似非常简单但需要大量微优化才能通过的不必要的残酷编码挑战之一。

正如this answer 中提到的,对于初学者,您不应该从字面上理解“放下”和“反转”操作。反转列表是 O(n),所以在最坏的情况下,您有一个 100k 元素列表并且操作是 R 的 100k,您正在做 1010无所作为的步骤。

更好的方法是使用 deque 和布尔值。双端队列在两端都有 O(1) 删除,布尔值在前后之间来回翻转以确定从哪一侧删除元素。如果我们以“反转”状态的列表结束,则将其反转打印。现在我们回到线性时间,但是对于 Python 来说,简单的线性时间不一定足够好,所以我们必须攻击常数因子。

我的下一个尝试是避免双端队列,而是专注于计算我需要在两端删除的元素数量,然后用切片一口气删除它们。将操作的执行和分析分开导致了更多的优化。每个测试用例的输入顺序是一个很好的提示:我们收集操作,然后是列表大小n,然后是列表内容。每当掉落物多于列表中的项目时,我们可以避免解析列表并打印error。如果列表中有与项目相同数量的掉落,我们可以打印[]并再次避免解析列表。

折腾这些微优化最终让我通过了。这是我的解决方案:

from sys import stdin

def main():
    for _ in range(int(next(stdin))):
        forward = True
        trim_from_front = 0
        trim_from_rear = 0

        for op in next(stdin):
            if op == "R":
                forward = not forward
            elif op == "
":
                break
            elif forward:
                trim_from_front += 1
            else:
                trim_from_rear += 1

        n = int(next(stdin))

        if trim_from_front + trim_from_rear > n:
            print("error")
            next(stdin)
            continue
        elif trim_from_front + trim_from_rear == n:
            print("[]")
            next(stdin)
            continue

        x = next(stdin)[1:-2].split(",", n - trim_from_rear)

        if trim_from_rear > 0:
            x.pop()

        if trim_from_front > 0:
            x = x[trim_from_front:]

        if not forward:
            x = reversed(x)

        print("[", ",".join(x), "]", sep="")


if __name__ == "__main__":
    main()

也可以看看:

【讨论】:

    【解决方案3】:

    因此,您的程序存在一些不同的问题。首先,正如其他人所提到的,您的解决方案效率很低。虽然它在理论上可行,但您对问题的处理方法完全错误。你还没有得到“正确的想法”。您失败的原因是输出格式错误。

    这条线

    print(inp_lst)
    

    当您不应该有空格时,将列表打印为用空格分隔的逗号。 kattis 逐字节比较输出,所以即使是意想不到的 ' ' 会让你失败。

    其他需要考虑的事项:
    当列表中的所有元素都被删除时,你打印“[]”吗?

    虽然这是您失败的原因,但您不会通过当前的解决方案,因为您会很快超时。虽然其他人已经发布了正确的想法和代码,但我建议您不要看它们以提高您解决问题的能力

    【讨论】:

      猜你喜欢
      • 2020-06-14
      • 1970-01-01
      • 1970-01-01
      • 2018-06-27
      • 1970-01-01
      • 1970-01-01
      • 2017-05-20
      • 2018-05-31
      • 2016-10-23
      相关资源
      最近更新 更多