算法:字符串切出最小字串,使得每个字母只会出现在一个子串中

题目要求:

给定一个字符串,要求把它切割成最小子字符串的集合,使得每一个字母只可能出现在一个子字符串中。举例如下:若给定字符串s = ‘aaabbccabnnmmng’,期待的输出结果为[[0, 8], [9, 13], [14, 14]]。因为切分后的字符串为:res = ['aaabbccab','nnmmn','g'].

解题思路:

我自己花了几个小时都没有做出来,是一位大佬告诉我他的思路,这里总结如下:
需要找到每个字母出现的第一个位置和最后一个位置,然后再取区间的最大并集即可。

解题步骤:

首先是用一个函数 get_position来找出每个字母出现的第一个位置和最后一个位置。代码如下:

def get_position(s):
    position_start = dict()
    position_end = dict()
    for i in range(len(s)):
        position_end.update({s[i]:i})
    for i in range(len(s)):
        if position_start.get(s[i],'') == '':
            print(i)
            position_start.update({s[i]:i})
    position = []
    for key in position_start:
        position.append([position_start[key],position_end[key]])
    return position

如果输入目标字符串‘'aaabbccabnnmmng',这个函数的输出为:

[[0, 7], [3, 8], [5, 6], [9, 13], [11, 12], [14, 14]]

也就是每一个字母出现的起始位置。

下一步需要给这些区间取并集,其实画在数轴上是一个比较容易理解的办法,但是如果想要让程序也能识别,可以使用条件:

  • 如果一个区间的右边界小于另一个区间的左边界,则两个区间没有交集。
  • 如果一个区间的左边界小于另一区间左边界,右边界大于另一个区间的右边界,则第一个区间一定包含第二个区间。

从上面两个规则就可以得到区间合并的函数:

from typing import List

def string_cut(string:str)->List[List[int, int]]:
    position = get_position(string) # 调用上面得到每个字母的首尾的函数
    i = 0
    result = []
    for i in position:
        if not result or result[-1][1] <i[0]:
            result.append(i)
            continue
        if result[-1][1] <i[1]:
            result[-1][1] = i[1]
    return result
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 8,494评论 0 4
  • 1 字符编码 python中的编码采用的是Unicode编码。什么是编码?就是数字和字符的一一对应的,其中字符对应...
    barriers阅读 3,150评论 0 1
  • 1. 元组概念1.1. 元组的特点1.2. 元组的定义1.3. 元组的访问1.4. 元组的查询 2. 命名元组 3...
    静堂先生阅读 4,037评论 0 1
  • 字符串 1.什么是字符串 序列:有序,不可变的。用单引号或者双引号括起来的任意字符(集)。 2.字符串中的字符 a...
    落幕丶丶阅读 4,241评论 0 0
  • 看了LED中的演讲,拖延症患者与非拖延症患者的差别是:拖延症患者的大脑里除了理性决策人之外多了一只即使信了的猴子 ...
    陆拾一啊阅读 2,338评论 0 0