algo. 字符串之字符串反转

开始的话:
每天三道题,养成良好的思维习惯。
一位爱生活爱技术来自火星的程序汪

这个题是什么意思呢?就是给定一组字符串比如: ′ a b c d e f g ′ 'abcdefg ' abcdefg,要求将前 3 3 3个字母移动到字符串的后面去,也就是会得到 ′ d e f g a b c ′ 'defgabc' defgabc。是不是很简单,很好理解。

做了一些算法题之后(本来准备说做了很多算法题的,后来想了一下和一些大佬们动不动就刷了 300 − 400 300-400 300400的相比都不好意思开口),很重要的一件事情就是将问题简单化,由易到难,分治等这些思想尤为关键。不要直接上来就想一步到位(这些只有那些你看不懂他算法代码的家伙才能做到吧,也是一个不断积累的过程。),慢慢来,谁让我比较笨呢!

o k ok ok, 开始吧!

迭代

和描述中所述一次移动三个似乎有很多数组移动的情况,好像很不好一下就想到怎么去很优雅的写出来(发现自己进入了一个误区,每次总是想很优雅的直接写出代码,最后才发现是慢慢改动代码才优雅的,果然还是要一步一步来,不能心急。)。那就简单来吧!三个不行我们就只移动一个好吧:就是把字符串中第一个字符 a a a移动到字符串末尾 ′ b c d e f g a ′ 'bcdefga ' bcdefga,这个还是比较好做的对吧,一个一个向前替换,需要单独记录第一个字符。话不多说上代码:

def rotate(s: list, length: int):
    """
    反转一个字符
    :param s:           输入字符串数组
    :param length:      字符串长度
    """
    first = s[0]
    for i in range(1, length):
        #   从第二个开始逐一替换掉前一个的值
        s[i - 1] = s[i]
    #   给第一个值赋值到最后下标位置
    s[length - 1] = first

s o so so e a s y easy easy 吧,那么反转三个呢?是不是就很简单了,让上面的循环三次就好了,哈哈,我真聪明!

for i in range(3):
    rotate(s, 7)
print(s)

但是呢,这并没有完,做算法题最重要的是什么?没错就是 时间复杂度空间复杂度 的分析。对于上面这样的做法,这两个指标分别是多少呢?
时间复杂度 -> O ( n ∗ m ) O(n*m) O(nm) n n n就表示前几个字符需要反转。 m m m就是字符串数组的长度了。
空间复杂度 -> O ( 1 ) O(1) O(1) 只存储了一个变量 f i r s t first first

对于空间复杂度还是很满意的,但是时间复杂度就似乎有点高了,每次都遍历了整个数组,这还是很恐怖的。

那是否有更快点的方法呢?那肯定是有的。

分治

和我之前讲的一样,先简单化:我们一个一个移动,再移动整体,问题是可以解决的对吧,没大量实践经验支撑的时候,我们就要这样从简到繁从易到难的过程,这个真的很重要,思维也是逐步养成的。那么怎么优化呢?知道 归并排序快速排序 的小伙伴肯定是知道 分治思想 的(这个思想其实也是有一种从简单出发解决复杂问题,只是有时候这种所谓的简单不好抽象出来。都是艺术 哈哈。),所以我们这个问题也是可以运用 分治思想 的。

怎么分?很自然的,要反转的那一部分作为一部分,剩下的作为另外一部分。如果我们能把这两部分分别反转了,然后合并之后再反转,是不是就解决我们这个问题了呢!

和之前的 归并排序快速排序 一样先写公式:

rotate(rotate(first_part) + rotate(second_part))

还拿上面的列子: ′ a b c d e f ′ 'abcdef' abcdef,短一点方便说明。还是前三个反转。

first_part = 'abc'
second_part = 'def'
rotate(first_part) = 'cba'
rotate(second_part ) = 'fed'
sum = rotate(first_part) + rotate(second_part ) = 'cbafed'
rotate(sum) = 'defabc'

上面过程很清晰明了了吧! 我们只需要最后一次循环的时候遍历整个数组,而之前两次迭代都是数组的一部分。是一次的累加所以时间复杂度是 O ( m ) O(m) O(m),空间复杂度也是 O ( 1 ) O(1) O(1)
r o t a t e rotate rotate方法如下:

def rotate(s: list, start: int, end: int) -> list:
    while start < end:
    	#	互换位置
        s[start], s[end] = s[end], s[start]
        start += 1
        end -= 1


s = list('abcdefg')
length = len(s)
#   移动前三个
m = 3
#   m > length 的时候等价
m %= length

rotate(s, 0, m - 1)
rotate(s, m, length - 1)
rotate(s, 0, length - 1)
print(s)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hyperopt库可以用于优化字符串类型的参数,但需要将字符串参数转换为离散的整数或枚举值。这可以通过定义一个字典映射来实现,将字符串参数映射到对应的离散值。然后,将离散值作为参数传递给Hyperopt进行优化。 以下是一个示例代码,演示如何使用Hyperopt优化字符串类型参数: ```python from hyperopt import hp, fmin, tpe # 定义字符串参数的取值范围 string_params = ['param1', 'param2', 'param3'] # 将字符串参数映射到离散值 param_space = hp.choice('param', string_params) # 定义目标函数 def objective(params): # 根据离散值获取对应的字符串参数 selected_param = string_params[params['param']] # 在这里执行你的代码,并返回一个评估指标作为目标函数的结果 # ... return evaluation_metric # 使用TPE算法进行优化 best_param = fmin(objective, space=param_space, algo=tpe.suggest, max_evals=100) # 输出最佳参数 best_string_param = string_params[best_param['param']] print("Best string parameter:", best_string_param) ``` 在上述示例中,我们首先定义了字符串参数的取值范围`string_params`。然后,使用`hp.choice`将字符串参数映射到离散的整数值。接下来,定义了目标函数`objective`,其中根据离散值获取对应的字符串参数,并执行相应的代码。最后,使用TPE算法进行优化,得到最佳的离散值参数,并将其映射回原始的字符串参数。 注意,上述示例仅演示了如何使用Hyperopt库优化字符串类型参数的一种方法。具体的实现方式可能因你的应用场景而有所不同,你可以根据需要进行适当的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值