草庐IT

Python ACM 模式下的输入输出

文山湖的猫 2023-08-09 原文

#Python #数据结构与算法
与leetcode的核心代码模式不同,acm模式下需要自己编写输入与输出函数。
推荐以下几个网站练习acm模式:
牛客网:OJ在线编程常见输入输出练习场
牛客网:华为机试
AcWing

1. 输入函数模板

1.1 获取输入数据

Python输入数据主要通过input()函数实现,input()会读取控制台一行的输入,如果输入有多行的话,需要多次使用input()

# 输入为: 1 2 3 4 5
a = input()
# a = '1 2 3 4 5'

与Python2中不同,Python3中的input()会将接受的数据返回为一个string类型,如果一行中有多个数据的话,则需要使用split()进行切割。split()切割后返回一个列表。

# 输入为: 1 2 3 4 5
a = input().split() # split()默认以空字符为分隔符,包括空格、换行(\n)、制表符(\t)等
# a = ['1', '2', '3', '4', '5']
	  
# 输入为:1,2,3,4,5
b = input().split(',') # 以逗号为分隔符
# b = ['1', '2', '3', '4', '5']

因为input()返回的是string,分割后也是一个字符列表,如果输入数据是数字则需要进行类型转换。可以单个转换或是用列表批量转换,或者是使用map()并行转换。map()函数返回的是一个迭代器,不能改变值,如果需要改变值的话还需要转换成列表

# 输入为: 1 
a = int(input()) # 单个转换
	  
# 输入为:1 2 3 4 5
b = input().split() # b = ['1', '2', '3', '4', '5']
c = [int(i) for i in b] # 使用列表进行批量转换 c = [1, 2, 3, 4, 5]
d = [int(i) for i in input().split()] # 当然可以一步倒位
	  
# 使用map进行并行转换
e = map(int, input().split()) # 此时e是一个map迭代器,不能赋值,也不能索引
f = list(e) # 转换为列表,e = [1, 2, 3, 4, 5]
g = list(map(int, input().split())) # 一步到位
	  

1.2 三种情况的输入数据

情况1: 多行输入,同时未指定用例的个数,例子1

while True:
	  try:
	      data = input()
	      solve(data) # 核心函数
	  except:
	      break

情况2: 多行输入, 指定用例个数, 例子2

n = int(input()) 获取用例个数
for _ in range(n):
	  data = input()
	  solve(data) # 核心函数

情况3: 多行输入,指定某个条件退出,例子3

while True:
	  data = input()
	  if judge(data): # 判断
	      break
	  solve(data)

2. 输出函数模板

Python3的输出主要靠print()函数,就是把结果打印至终端。需要对print()函数的sepend两个参数有一定的了解,可以查看菜鸟教程
情况1: 输出单个数字

# 输出 a (a = 1)
print(a)

情况2: 输出多个数字,同时要求以分隔符隔开

# 输出 a=1, b=2, c=3
print(a, b, c) # print默认以空格为分隔符
# output:1 2 3
print(a, b, c, sep=',') # 以逗号为分隔符
# output:1,2,3

情况3:最终结果是一个列表

# 最终结果 res = [1, 2, 3]
# 1. 直接输出列表
print(res)
# 2. 输出列表, 每个元素单独输出
for i in range(len(res)):
    print(res[i])
#output: 1
#        2
#        3

# 3. 输出列表,每个元素单独输出,同时还需要在同一行输出, 以空格分隔
for i in range(len(res)):
    print(res[i], end=' ')  # end的默认值是'\n',即换行
    # output: 1 2 3 

情况4: 将字符列表合成一个字符串,需要用到join()函数

# res = ['a', 'b', 'c']
# 输出是一个字符串
print("".join(res))
# output: abc

# 输出是一个字符串,且用 * 号分隔
print("*".join(res))
# output: a*b*c
# 如果用 print(res[i], end = '*') 的话,输出就是 a*b*c*了,在末尾还多了一个*

3. 链表的输入输出

acm模式中的链表也是通过输入一个数组来模拟的,所以获取输入数据和前面没有什么不同。
主要在于定义链表结构、将输入数据转化为链表以及输出链表。
华为机试:从单向链表中删除指定值的节点
华为机试:输出单向链表中倒数第k个节点

# 定义链表结构
class ListNode:
    def __init__(self,val,next=None):
        self.val = val
        self.next = next

# 数组转链表
def nums2ListNode(nums):
    dummy = ListNode(None)
    root = ListNode(nums[0])
    dummy.next = root
    i = 1
    while i < len(nums):
        node = ListNode(nums[i])
        root.next = node
        root = root.next
        i += 1
        root.next = None
    return dummy.next

# 打印链表
nums = [1,2,3,4,5]
root = nums2ListNode(nums)
while root:
    print(root.val)
    root = root.next

4. 二叉树

4. 二叉树的输入输出

4.1 完全二叉树格式输入

acm模式中一般用输入一行数字代表一个二叉树,一般会以完全二叉树格式输入。这行数字的按照层序遍历的顺序排列,且其中空节点一般会用特定的符号表示,如0或是null
可以直接用数组表示二叉树,例如列表Tree, 将Tree[i]的左子树和右子树分别为Tree[2*i+1]Tree[2*i+2],不过会比较占用空间。

# 中序遍历
def inorder_traversal(nums, index):
    if index >= len(nums) or nums[index] == -1:
        return
    left, right = 2 * index + 1, 2 * index + 2
    inorder_traversal(nums, left)
    print(nums[index], end = ' ')
    inorder_traversal(nums, right)
	  
	  
# 输入为 1 2 3 null 4 null 5
#      1
#    /   \
#   2     3
#    \     \
#     4     5
if __name__ == "__main__":
    nums = input().split()
    nums = [int(num) if num != 'null' else -1 for num in nums]
    inorder_traversal(nums, 0)

    # output: 2 4 1 3 5 

也可以用链表实现,更省空间,但操作更复杂一些。

# 定义二叉树类函数
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
	  
	  
# 由数组转二叉树
def construct_binary_tree(nums, index):
    if index >= len(nums):
        return
    # -1作为空节点
    if nums[index] == -1:
        return None
    left = index * 2 + 1
    right = index * 2 + 2
    root = TreeNode(nums[index])
    root.left = construct_binary_tree(nums, left)
    root.right = construct_binary_tree(nums, right)
    return root

# 中序遍历
def inorder_traversal(root):
    if not root: return
    inorder_traversal(root.left)
    print(root.val, end=' ')
    inorder_traversal(root.right)

# 输入为 1 2 3 null 4 null 5
#      1
#    /   \
#   2     3
#    \     \
#     4     5
if __name__ == "__main__":
	nums = input().split()
	nums = [int(num) if num != 'null' else -1 for num in nums]
	root = construct_binary_tree(nums, 0)
	inorder_traversal(root)
   # output: 2 4 1 3 5
	  

4.2 其他格式输入

有部分题目的输入格式不是完全二叉树,例如leetcode的二叉树格式,输入的数组虽然也是按照层序遍历的顺序,但并不是每一层的空节点都会表示出来,而是仅表示与非空节点连接的空节点。

# 数组转二叉树
def construct_binary_tree(nums):  # nums = ['1', '2', '3', 'null', 'null', 'null', '5']
    if nums == []: return
    root = TreeNode(nums[0])
    queue = collections.deque()
    queue.append(root)
    i = 1
    while i < len(nums):
        node = queue.popleft()
        if i < len(nums) and nums[i] != -1:
            node.left = TreeNode(nums[i])
            queue.append(node.left)
        i += 1
        if i < len(nums) and nums[i] != -1:
            node.right = TreeNode(nums[i])
            queue.append(node.right)
        i += 1
    return root
  
# 中序遍历
def inorder_traversal(root):
    if not root: return
    inorder_traversal(root.left)
    print(root.val, end=' ')
    inorder_traversal(root.right)
  
# 输入 1 null 1 null 1 2
#    1
#  /  \
#null  1
#    /   \
#   null  1
#        /
#       2
if __name__ == "__main__":
	nums = input().split()
	nums = [int(num) if num != 'null' else -1 for num in nums]
	root = construct_binary_tree(nums)
	inorder_traversal(root)
  	# 输出 1 1 2 1

参考博客

ACM模式笔试编程题Python3的输入和输出格式详解
ACM模式下链表、二叉树的输入Python实现

本文链接

http://t.csdn.cn/m7VMg

有关Python ACM 模式下的输入输出的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  4. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  5. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  6. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  7. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  8. ruby - 将 spawn() 的标准输出/标准错误重定向到 Ruby 中的字符串 - 2

    我想使用spawn(针对多个并发子进程)在Ruby中执行一个外部进程,并将标准输出或标准错误收集到一个字符串中,其方式类似于使用Python的子进程Popen.communicate()可以完成的操作。我尝试将:out/:err重定向到一个新的StringIO对象,但这会生成一个ArgumentError,并且临时重新定义$stdxxx会混淆子进程的输出。 最佳答案 如果你不喜欢popen,这是我的方法:r,w=IO.pipepid=Process.spawn(command,:out=>w,:err=>[:child,:out])

  9. ruby - Ruby 是否使用 $stdout 来写入 puts 和 return 的输出? - 2

    我想知道Ruby用来在命令行打印这些东西的输出流:irb(main):001:0>a="test"=>"test"irb(main):002:0>putsatest=>nilirb(main):003:0>a=>"test"$stdout是否用于irb(main):002:0>和irb(main):003:0>?而且,在这两次调用之间,$stdout的值是否有任何变化?另外,有人能告诉我打印/写入这些内容的Ruby源代码吗? 最佳答案 是的。而且很容易向自己测试/证明。在命令行试试这个:ruby-e'puts"foo"'>test.

  10. ruby-on-rails - 无法在 Rails 助手中捕获 block 的输出 - 2

    我在使用自定义RailsFormBuilder时遇到了问题,从昨天晚上开始我就发疯了。基本上我想对我的构建器方法之一有一个可选block,以便我可以在我的主要content_tag中显示其他内容。:defform_field(method,&block)content_tag(:div,class:'field')doconcatlabel(method,"Label#{method}")concattext_field(method)capture(&block)ifblock_given?endend当我在我的一个Slim模板中调用该方法时,如下所示:=f.form_field:e

随机推荐