39. 计算位置 x 到 y 的最少步数
问题描述
小R有一个字符串 word,该字符串由数字和小写英文字母组成。小R想用空格替换每一个不是数字的字符。然后,他希望统计在替换后剩下的整数中,不同整数的数目。
思路解析
-
整体思路方向:
首先要对给定的字符串word进行遍历,根据字符的类型(数字或非数字)来进行相应处理,将非数字字符替换成空格,得到一个新的字符串,这个新字符串里的数字是按要求分隔开的。接着从这个新字符串中提取出所有数字,再利用集合的去重特性来统计不同数字的数量,以此实现最终目标。 -
各环节思路:
- 字符判断与替换环节:需要逐个检查字符串
word中的字符,判断其是否为数字。Python 中提供了方便的字符串方法isdigit()来做此判断。对于不是数字的字符,按照要求将其替换为空格,通过循环遍历整个字符串来完成对所有字符的这种处理,最终得到处理后的新字符串,这一步是对原始字符串按规则进行初步改造的关键思路。 - 整数提取环节:经过前面替换操作后得到的新字符串中,数字之间是由空格隔开的,此时可以利用字符串的
split()方法,依据空格这个分隔符把字符串分割开,从而得到一个包含所有数字(但此时还是字符串形式)的列表,这是将目标数字从整体字符串里分离出来的思路要点。 - 去重统计环节:为了统计不同整数的数目,考虑到集合元素的唯一性,也就是集合中不会有重复元素这一特性,我们把从前面步骤提取出来的数字列表中的元素先转换为整数类型,再添加到集合中,集合会自动去除重复的整数,最后只需统计集合中元素的个数,就能得出不同整数的数目,这是借助集合巧妙达成最终统计目的的核心思路所在。
- 字符判断与替换环节:需要逐个检查字符串
解题步骤
- 字符判断与替换步骤:
- 首先定义了一个空字符串
new_word,用于存放经过处理后的字符串结果。 - 接着使用
for循环遍历输入的字符串word中的每一个字符char。 - 通过
char.isdigit()判断字符char是否是数字,如果是数字就把该字符添加到new_word中,如果不是数字就添加一个空格到new_word中,这样就完成了按照要求对原始字符串word的替换操作,得到了新字符串new_word。
- 整数提取步骤:
这行代码利用字符串的
split()方法,以空格作为分隔符,将上一步得到的新字符串new_word进行分割,返回一个列表num_list,列表里的元素就是之前新字符串中被空格分隔开的数字(此时还是字符串形式)。 - 去重统计步骤:
- 首先使用了生成式
(int(num) for num in num_list),它会遍历num_list中的每个字符串元素,把它们逐个转换为整数类型,然后将这些整数添加到集合unique_nums中,由于集合的去重特性,重复的整数在集合中只会保留一个。 - 最后通过
len(unique_nums)来获取集合中元素的个数,这个个数就是我们最终想要统计的不同整数的数目,将其存储在变量result中。
复杂度分析
时间复杂度:
整体算法时间复杂度为O(n) 。遍历字符串 word(长度为 n)进行字符替换是O(n),分割新字符串及后续集合操作中,各部分操作时间复杂度与 n 相关或为常数级,主导的仍是O(n),随输入字符串变长,执行时间线性增长。
空间复杂度:
空间复杂度同样为O(n)。定义的新字符串、提取数字的列表及存储不同整数的集合,在最坏情况占用空间与 word 长度 n 相关,额外空间随输入字符串长度增加大致呈线性增长。
Code
import math;
def solution(x_position, y_position):
dis = abs(x_position - y_position) # 计算 x 到 y 的距离
step_count = 0
result = 2e9
for peak in range(1, dis): # 枚举步数峰值
# 等差数列求和:首项为 1, 末项为峰值
# S = peak(1+peak)/2
# 2S-peak 为走的步数, 即 peak*peak
# peak*2-1 为走的次数
diff = dis - peak*peak
if(diff < 0): # 如果已经走超了,就代表不可能存在更大的峰值
return step_count
step_count = peak*2 - 1
# 按峰值快步前进
step_count += int(diff / peak) # 记得强制类型转换,下取整
diff %= peak
if(diff != 0):
# 如果步数不够。则需要补充一步补齐
step_count += 1
result = min(step_count, result) # 更新最小步数
return step_count
if __name__ == "__main__":
# You can add more test cases here
print(solution(12, 6) == 4)
print(solution(34, 45) == 6)
print(solution(50, 30) == 8)