763. 划分字母区间(贪心算法)


763. 划分字母区间

题目

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

在这里插入图片描述
提示:

  • S的长度在[1, 500]之间。
  • S只包含小写字母 ‘a’ 到 ‘z’ 。

解题思路

  • 1、记录每个字母在S中最后出现的下标
  • 2、从下标0开始尝试分段,左边界left是0
  • 3、“同一个字母必须在同一片段中”,所以初始right是该段首字母最后出现的位置
  • 4、动态遍历left到right,如果有字符最后出现的下标大于right,更新right
  • 5、遍历完成后,一个分段就生成了。计数区间长度,更新left = right + 1,转3继续。

代码


class Solution {
   public  List<Integer> partitionLabels(String S) {

        Map<Character,Integer> map=new HashMap<>();//用来存放每个元素的最后出现的位置下标

        char[] s = S.toCharArray();//toCharArray() 方法将字符串转换为字符数组。

        for (int i = 0; i <s.length ; i++) {
                map.put(s[i],i);//一轮遍历完了以后,元素最后一次出现的位置被存放到了map中。
        }

        int left=0;
        int right=map.get(s[0]);//right被初始化为第一个元素最后出现的位置

        List<Integer> result=new ArrayList<>();

        while (left<=right){//之所要等号,是考虑到数组的第一个元素有且仅有一个,这样left和right都是0,如果没有等号就进不了循环
            for (int i = left; i <right ; i++) {
                if (map.get(s[i])>right){//如果在初始的left--right区间内,有元素的最后出现位置大于初始的right,则更新right。
                    right=map.get(s[i]);
                }
            }
            result.add(right-left+1);//第1、2、3、4...个区间的长度

            left=right+1;//上面的循环结束后,求出了第一个区间,第二个区间的left为上一轮得到的right+1,这轮的初始right为map.get(right+1)

            if (left-1==(s.length-1)){//如果已经到了最后一个区间了:那么上轮循环结束后的right+1就是s的length。 即这一轮的left-1==上一轮的right ==s.length-1
                right=left-1; //让right比left小1 跳出循环
            }else{
                right=map.get(s[right+1]);
            }


        }


        return result;
    }
}

文章作者: fFee-ops
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 fFee-ops !
评论
  目录