字符串操作题解01 | #坐标移动#

坐标移动

https://www.nowcoder.com/practice/119bcca3befb405fbe58abe9c532eb29

import re
def move_coor(t):
    coord = [0, 0]
    pattern = re.compile(r"([AWDS])(\d{1,2})", re.IGNORECASE)
    commands = [pattern.fullmatch(i) for i in t.split(";")]
    commands = list(filter(None, commands))
    for i in commands:
        command, step = i.groups()
        step = int(step)
        if command.upper() == "A" and coord[0] - step >= -(2 ** 31):
            coord[0] -= step
        elif command.upper() == "D" and coord[0] + step <= 2 ** 31 - 1:
            coord[0] += step
        elif command.upper() == "W" and coord[1] + step <= 2 ** 31 - 1:
            coord[1] += step
        elif command.upper() == "S" and coord[1] - step >= -(2 ** 31):
            coord[1] -= step
    return f"{coord[0]},{coord[1]}"
final_coordinate = move_coor(input())
print(final_coordinate)

一、解题思路

  1. 理解题目要求:题目要求是根据输入的字符串表示移动指令,计算最终坐标。有四个方向的指令“A”、“W”、“S”、“D”分别表示向左、向上、向下、向右移动。每个指令后跟一个正整数,表示移动步数。
  2. 分析和处理字符串:
  3. 提取关键信息:需要从输入的字符串中提取方向(AWSD) 和步数(数字)。
  4. 拆分字符串:使用“split(";")”将输入的字符串分解成一个个操作
  5. 处理特定字符串:利用正则表达式匹配方向和步数,将输入的字符串分解成一个个操作
  6. 首先创建一个正则表达式模式,使用“re.compile()”匹配字符串中的指令和步数:pattern = re.compile(r'([AWDS])(\d{1,2})')
  7. 然后,使用列表推导式fullmatch()方法与pattern匹配每个指令,将指令放入commands列表
  8. 思考边界条件和特殊情况
  9. 输入为空:由于filter()函数作用,输入为空时,将不会进行执行步骤。
  10. 极限范围:我们需要确保计算过程中坐标值始终在-2^31 至 2^31-1 的范围内。
  11. 设计算法和数据结构:这题目中,我们使用迭代算法和列表数据结构。从初始坐标【0,0】开始,对每个匹配的命令,我们更新相应的坐标值
  12. 测试和验证:使用多个输入测试案例进行测试,确保代码在各种情况下都能正确输出。
  13. 优化:能力有限,暂无

二、举一反三

1. 理解题目要求

首先,确保完全理解题目的需求。确保明确输入和输出的格式,以及从输入获取输出的转换规则。

2. 分析和处理字符串

仔细分析题目关键点,弄清楚字符串的特点和操作需求。这个步骤可能涉及以下方面:

  • 提取关键信息,如数字、子串等。
  • 拆分、连接或重组字符串的各个部分。
  • 处理特定的子串或字符,如替换、删除、重复等。

通常,可以使用以下一些常见的功能:

  • 字符串方法和操作:split()join()replace()substringfind()len()等。
  • 字符操作:islower()isupper()isalpha()isdigit()isspace()等。
  • 正则表达式:匹配、提取和处理复杂的文本模式。
  • 自定义函数:编写特定于问题的功能。

3. 思考边界条件和特殊情况

务必考虑边界条件和特殊情况,以确保代码的正确性和健壮性。这可能包括:

  • 输入为空或异常。
  • 处理极端的范围和值。
  • 对输入数据的安全检查。

4. 设计算法和数据结构

根据问题需求选择合适的算法或数据结构。有时,最简单的方法并不一定是最有效的。例如,处理很大的字符串时,复杂度显得尤为重要。这可能涉及几种常见的策略:

  • 迭代(在某些情况下,递归可以替换为迭代)
  • 动态规划
  • 分治策略

同时,面对这种类型的问题,可能需要考虑对数据的合理组织。如果需要,可以考虑使用:

  • 数组和列表
  • 字典(键值映射)
  • 集合(无序且不重复的元素)

5. 测试和验证

在解决问题后,对代码进行测试并验证其正确性和性能。确保在不同的输入、边界条件和特殊情况下,代码都能给出正确的输出。

6. 优化

如果需要,优化代码以提高性能。这可能包括改进算法、使用高效的数据结构、减少空间复杂度、内存分配等。

三、知识补充

正则表达式(Regular Expression)

是一种描述字符串结构模式的符号表示,用于对字符串进行匹配、查找和替换等操作。正则表达式主要包含以下构成要素:

  1. 文本字符:匹配字符本身。例如:正则表达式 abc 将匹配字符串 "abc"。
  2. 元字符:具有特殊含义的字符。例如:. 表示任意字符,* 表示匹配前一个字符 0 次或多次等。
  3. 字符类:用方括号 [] 括起一组字符以表示匹配其中任意一个字符。例如,正则表达式 [abc] 将匹配字符 "a"、"b" 或 "c"。
  4. 量词:用于指定匹配字符的出现次数。例如,a{2,4} 表示匹配字符 "a" 连续出现2到4次。
  5. 锚字符:用于表示特定位置匹配。例如: ^ 表示字符串开头,$ 表示字符串结尾。
  6. 分组:用圆括号括起要在一起处理的一部分正则表达式。例如:(ab)+ 将匹配 "ab", "abab", "ababab" 等。

常用的re模块函数:

  1. re.search(pattern, string, flags=0)在字符串中搜索模式的第一个匹配项。如果找到了匹配项,则返回一个匹配对象(Match object);如果没有找到匹配项,则返回 None。
  2. re.match(pattern, string, flags=0)从字符串的开头匹配模式。如果成功匹配,返回匹配对象;否则,返回 None。
  3. re.fullmatch(pattern, string, flags=0)检查整个字符串是否与给定的模式相匹配。如果成功匹配,返回匹配对象;否则,返回 None。
  4. re.findall(pattern, string, flags=0)在字符串中查找模式的所有非重叠匹配项,并以列表形式返回。
  5. re.finditer(pattern, string, flags=0)在字符串中查找模式的所有非重叠匹配项,并返回一个迭代器,每次迭代都会生成一个匹配对象。
  6. re.split(pattern, string, maxsplit=0, flags=0)按模式匹配的子串将字符串分割,并返回一个包含分割后的子串的列表。可以通过 maxsplit 参数指定最大分割次数。
  7. re.sub(pattern, repl, string, count=0, flags=0)在字符串中查找模式的所有匹配项,并将这些匹配项替换为指定的字符串或函数返回的结果。可以通过 count 参数指定最大替换次数。
  8. re.compile(pattern, flags=0)将给定的模式编译为一个正则表达式对象(Pattern object),以便重复使用。
  9. re.escape(pattern)对字符串中的所有非字母数字符进行转义,这样就可以在正则表达式中将字符串作为字面文本进行匹配。

关于标志(Flags)参数:

flags 参数是re模块中可选的一种机制,它可以用来修改正则表达式的匹配行为。以下是一些常用的标志:

  • re.IGNORECASEre.I:使匹配对大小写不敏感。
  • re.MULTILINEre.M:使 ^$ 分别匹配每行的开头和结尾,而不仅仅是整个字符串的开头和结尾。
  • re.DOTALLre.S:使点号(.)匹配任意字符,包括换行符。

示例:

import re

pattern = re.compile(r'\d+')            # 匹配一个或多个连续数字
string = '12 dogs, 24 cats, 35 birds'

result = pattern.findall(string)        # 查找所有匹配项
print(result)                           # 输出:['12', '24', '35']

repl = lambda x: str(int(x.group(0)) * 2)
result = pattern.sub(repl, string)      # 用匹配到的数字翻倍替换所有匹配项
print(result)                           # 输出:'24 dogs, 48 cats, 70 birds'
###举例###

string = 'My phone number is 123-456-7890.'  # 输入字符串
pattern = r'\d{3}-\d{3}-\d{4}'  # 匹配模式:美国手机号

# 示例 1 - re.search()
search_result = re.search(pattern, string)  # 在字符串中搜索模式的第一个匹配项
print(search_result)  # 输出:<re.Match object; span=(19, 31), match='123-456-7890'>
# 此处,re.search() 在字符串中找到了手机号,并返回了一个包含匹配项的匹配对象。

# 示例 2 - re.match()
match_result = re.match(pattern, string)  # 从字符串开头开始匹配模式
print(match_result)  # 输出:None
# re.match() 返回 None,因为字符串开头与模式不匹配(手机号并非在开头)。

# 示例 3 - re.fullmatch()
fullmatch_result = re.fullmatch(pattern, string)  # 检查整个字符串是否与给定模式完全匹配
print(fullmatch_result)  # 输出:None
# re.fullmatch() 返回 None,因为整个字符串与模式不完全匹配(不仅仅是手机号)。

# 示例 4 - re.findall()
findall_result = re.findall(pattern, string)  # 查找字符串中的所有模式匹配项
print(findall_result)  # 输出:['123-456-7890']
# 此处,re.findall() 返回一个列表,包含字符串中所有匹配的手机号。

# 示例 5 - re.finditer()
finditer_result = re.finditer(pattern, string)  # 查找字符串中的所有非重叠模式匹配项
for match in finditer_result:  # 遍历匹配对象迭代器
    print(match)  # 输出:<re.Match object; span=(19, 31), match='123-456-7890'>
# 此处,re.finditer() 返回一个迭代器,我们循环遍历它来打印找到的每个匹配对象。


string = '1 fish, 2 fish, red fish, blue fish'  # 输入字符串
pattern = r'\d+ fish'  # 匹配模式:包含数字和 "fish" 的子串

# 示例 6 - re.split()
split_result = re.split(pattern, string)  # 按模式匹配的子串将字符串进行分割
print(split_result)  # 输出:['', ', ', 'red fish, blue fish']
# 在此,re.split() 将字符串按照包含数字和 "fish" 的子串进行分割。

# 示例 7 - re.sub()
sub_result = re.sub(pattern, 'replaced', string)  # 将字符串中匹配模式的子串替换为 'replaced'
print(sub_result)  # 输出:'replaced, replaced, red fish, blue fish'
# 在此,re.sub() 将找到的所有匹配子串替换为 'replaced'。

# 示例 8 - re.compile()
compiled_pattern = re.compile(r'\d{2,3}-\d{2,3}-\d{4}')  # 将模式编译为一个正则表达式对象
result = compiled_pattern.search("Call me at 555-123-4567.")  # 在字符串中搜索模式的第一个匹配项。
print(result)  # 输出:<re.Match object; span=(11, 23), match='555-123-4567'>
# 在这里,我们首先通过 re.compile() 将模式编译为一个正则表达式对象,以便多次使用。
# 然后我们使用 compiled_pattern.search() 对字符串进行搜索。

# 示例 9 - re.escape()
text = "# ... (content) [source]"  # 输入字符串
escaped_text = re.escape(text)  # 对字符串中所有非字母数字符进行转义
print(escaped_text)  # 输出:'\#\ \.\.\. \(content\) \[source\]'
# 在此,我们使用 re.escape() 将非字母数字符转义,结果字符串中的 '#'、'.'、'(' 等字符前面都添加了一个 '\'。

列表推导式

(List Comprehension)是一种简洁的构造列表的方法。使用一个输入序列,列表推导式可以生成新的列表,每个生成的元素是对输入序列中的元素应用一定表达式或条件的结果。它的基本结构为:[expression for item in iterable if condition]。列表推导式通常包含以下构成要素:

  1. expression: 表达式,用于计算新列表中的元素。此表达式取决于输入序列中的 item
  2. for item in iterable: 迭代,用于遍历输入序列中的每个元素。
  3. if condition: 可选部分,用于通过某种条件筛选输入序列中的元素。只有满足条件的元素才返回表达式的结果。

例如,一段使用列表推导式的代码:

squares = [x * x for x in range(5)]

这里的列表推导式生成了一个名为 squares 的列表,每个元素为 range(5) 中元素的平方。因此,squares 的值为:[0, 1, 4, 9, 16]

再举一个带条件筛选的例子:

even_squares = [x * x for x in range(5) if x % 2 == 0]

这段代码产生的 even_squares 列表中的元素是 range(5) 中偶数对应的平方。因此,even_squares 的值为:[0, 4, 16]

#23届找工作求助阵地#
算法学习分析与整理 文章被收录于专栏

个人学习算法的文档整理与思考,举一反三,相爱相杀。

全部评论

相关推荐

07-22 11:07
门头沟学院 Java
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
07-25 13:59
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务