LWC 67: 763. Partition Labels

LWC 67: 763. Partition Labels

传送门:763. Partition Labels

Problem:

A string S of lowercase letters is given. We want to partition this string into as many parts as possible so that each letter appears in at most one part, and return a list of integers representing the size of these parts.

Example 1:

Input: S = “ababcbacadefegdehijhklij”
Output: [9,7,8]
Explanation:
The partition is “ababcbaca”, “defegde”, “hijhklij”.
This is a partition so that each letter appears in at most one part.
A partition like “ababcbacadefegde”, “hijhklij” is incorrect, because it splits S into less parts.

Note:

  • S will have length in range [1, 500].
  • S will consist of lowercase letters (‘a’ to ‘z’) only.

思路:
很暴力,直接找可以Partition的位置,如果不能Partition,继续向后搜索直到找到第一个可以Partition的位置为止,这样剩余问题就是原问题的子问题了。

初始版本如下:

    public List<Integer> partitionLabels(String S) {
        List<Integer> ans = new ArrayList<>();
        if (S.length() == 0) return ans;

        char[] cs = S.toCharArray();
        StringBuilder sb = new StringBuilder();
        int i = 0;
        for (; i < cs.length; ++i) {
            sb.append(cs[i]);
            if (part(sb, i, S)) {
                ans.add(sb.length());
                break;
            }
        }

        List<Integer> sub = partitionLabels(S.substring(i + 1));
        for (int hello : sub) ans.add(hello);
        return ans;
    }

    public boolean part(StringBuilder sb, int i, String S) {
        if (sb.toString().isEmpty()) return false;
        for (int j = i + 1; j < S.length(); ++j) {
            String letter = S.substring(j, j + 1);
            if (sb.toString().contains(letter)) return false;
        }
        return true;
    }

再精简一点,因为调用原函数,可以在for循环中完成,所以有:

    public List<Integer> partitionLabels(String S) {
        List<Integer> ans = new ArrayList<>();
        char[] cs = S.toCharArray();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < cs.length; ++i) {
            sb.append(cs[i]);
            if (part(sb, i, S)) {
                ans.add(sb.length());
                sb = new StringBuilder();
            }
        }
        return ans;
    }

    public boolean part(StringBuilder sb, int i, String S) {
        if (sb.toString().isEmpty()) return false;
        for (int j = i + 1; j < S.length(); ++j) {
            String letter = S.substring(j, j + 1);
            if (sb.toString().contains(letter)) return false;
        }
        return true;
    }

万幸此答案没有超时,实际上我们还可以采用贪心的做法,降低时间复杂度。上个版本中,还需要计算StringBuilder的字符串中的每个字符是否在后续字符中出现过,实际上没有必要,我们只要记录StringBuilder中的每个字符出现的最后一个位置在哪,这样就避免每次都判断一遍,而是利用字符的最后位置直接判断。其次很重要的一点,字符串的partition的依据是:字符串中每个字符最后出现位置的整体最大值。

Java版本:

    public List<Integer> partitionLabels(String S) {
        List<Integer> ans = new ArrayList<>();
        char[] cs  = S.toCharArray();
        int n = cs.length;
        int[] last = new int[32];
        for (int i = 0; i < n; ++i) {
            last[cs[i] - 'a'] = i;
        }
        int pre = -1;
        int max = 0;
        for (int i = 0; i < n; ++i) {
            if (last[cs[i] - 'a'] > max) max = last[cs[i] - 'a'];
            if (max == i) {
                ans.add(max - pre);
                pre = max;
                max = max + 1;
            }
        }
        return ans;
    }

Python版本:

class Solution(object):
    def partitionLabels(self, S):
        """
        :type S: str
        :rtype: List[int]
        """
        lst = {}
        n = len(S)
        for i, c in enumerate(S):
            lst[c] = i
        ans = []
        max = 0
        pre = -1
        for i in range(n):
            if lst[S[i]] > max: max = lst[S[i]]
            if max == i:
                ans.append(max - pre)
                pre = max
                max = max + 1
        return ans
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值