763划分字母区间解题记录

先用贪心做一做。题目可以翻译为——在确保当前部分的所有字母都不再出现在后面的前提下,尽早分割。但是怎么确保当前部分的所有字母都不再出现呢?我们可以**记录每个字母最后出现的位置,然后一旦这个字符串包含的字符都在某个范围内结束了,立马分割。**就我现在而言感觉这个思路比较难想到。

func partitionLabels(s string) []int {
    // 每个字符的距离记录到map
    m := make(map[rune]int, 26)
    for i,v := range s {
        m[v] = i
    }

    start := 0 // 本次字符串起始位置
    maxi := 0 // 已经包含的字符最长在哪里结束
    var res []int
    for i,v := range s {
        maxi = max(maxi, m[v])
        if i==maxi {
            res = append(res, maxi-start+1)
            start = maxi+1
        }
    }

    return res
}

也可以用哈希表+滑动窗口来做。先记录下每个字母的出现次数,然后对滑动窗口中的每个字母判断次数是否用尽为 0,如果这个窗口内的所有字母次数都为 0,这个窗口就是符合条件的窗口。时间复杂度为 O(n)

func partitionLabels(s string) []int {
    m := make(map[byte]int, 0)
    for _, v := range s {
        m[byte(v)]++
    }

    // 判断目前滑动窗口内有哪些字母
    visit := make([]bool,26) // 使用后不用置0,因为后续不会在出现以前使用过的字符了

    res := make([]int, 0)
    lastlen := 0
    for i:=0; i<len(s); i++ {
        m[s[i]]--
        visit[s[i]-'a'] = true
        sum := 0 // 当字符串被分离出去时,所有被vistied的map都应该是0
        for j, v := range visit {
            if v {
                sum += m[byte('a'+j)]
            }
        }
        if sum == 0 {
            res = append(res, (i+1) - lastlen)
            lastlen = i+1
        }
    } 

    return res
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值