leetcode 763 : 划分字母区间

该博客介绍了LeetCode中的763题,即如何将一个只包含小写字母的字符串划分为最多含有相同字母的片段,并提供了四种不同的解题思路,包括使用HashMap记录字符最大下标、利用字符数组优化、减少循环次数以及转化为合并区间问题的思考。文章通过Java代码详细阐述了解决方案,并展示了执行时间和内存消耗。

leetcode 763 : 划分字母区间

字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。

示例:

输入:S = "ababcbacadefegdehijhklij"
输出:[9,7,8]
解释:
划分结果为 "ababcbaca", "defegde", "hijhklij"。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少。

提示:

  • S的长度在[1, 500]之间。

  • S只包含小写字母 'a''z'

Related Topics

贪心

哈希表

双指针字符串

思路 1:

  • 第一步,先把每一个字符的最大值保存到hashmap中。

  • 第二步,每遍历一个字符,跟这个区间的内部的最大下标比较,直到将这个区间内的字符找完为止。

    public List<Integer> partitionLabels(String s) {
        HashMap<Character,Integer> map = new HashMap<>();
        ArrayList<Integer> result = new ArrayList<>();
        //保持每一个字母的最大下标
        for(int i = 0 ; i < s.length();i++){
            map.put(s.charAt(i),i);
        }
        //因为map里面存储的是最大下标
        //每遍历一个字符 都更新这个最大值 保证同一个字母出现在同一个区间
    ​
        int start = 0;
        int end = 0;
        for(int i = 0; i < s.length();i++){
            end = Math.max(end,map.get(s.charAt(i)));
            if(i == end){ //说明这个区间内已经计算完毕
                result.add(end - start + 1);
                end++;
                start = end;
            }
        }
        return result;
    }
    解答成功:
                执行耗时:8 ms,击败了19.79% 的Java用户
                内存消耗:41.1 MB,击败了5.02% 的Java用户

思路2 :

由于只有小写字符,使用hashmap的话,存取计算哈希值,效率不如直接使用一个长度26的数组。

public List<Integer> partitionLabels(String s) {
    int[] indexs = new int[26];
    ArrayList<Integer> result = new ArrayList<>();
    //保持每一个字母的最大下标
    //int length = s.length();
    for(int i = 0 ; i <s.length();i++){
        indexs[s.charAt(i) - 'a'] = i;
    }
    //因为map里面存储的是最大下标
    //每遍历一个字符 都更新这个最大值 保证同一个字母出现在同一个区间
​
    int start = 0;
    int end = 0;
    for(int i = 0; i < s.length();i++){
        end = Math.max(end,indexs[s.charAt(i)-'a']);
        if(i == end){ //说明这个区间内已经计算完毕
            result.add(end - start + 1);
            end++;
            start = end;
        }
    }
    return result;
}
执行耗时:4 ms,击败了56.85% 的Java用户
            内存消耗:40.2 MB,击败了5.02% 的Java用户

思路3:

将s.length() 换成length时间效率有些许提高。

public List<Integer> partitionLabels(String s) {
    int[] indexs = new int[26];
    ArrayList<Integer> result = new ArrayList<>();
    //保持每一个字母的最大下标
    int length = s.length();
    for(int i = 0 ; i <length;i++){
        indexs[s.charAt(i) - 'a'] = i;
    }
    //因为map里面存储的是最大下标
    //每遍历一个字符 都更新这个最大值 保证同一个字母出现在同一个区间
​
    int start = 0;
    int end = 0;
    for(int i = 0; i < length;i++){
        end = Math.max(end,indexs[s.charAt(i)-'a']);
        if(i == end){ //说明这个区间内已经计算完毕
            result.add(end - start + 1);
            end++;
            start = end;
        }
    }
    return result;
}
解答成功:
            执行耗时:2 ms,击败了98.98% 的Java用户
            内存消耗:39.8 MB,击败了5.02% 的Java用户

思路4:

leetcode评论区看到,找到每一个字母的区间范围,这个题就变成合并区间范围这个题(第56题)。

但这个思路时间复杂度应该挺高的。 但想法确实不错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值