LeetCode(9), Longest Substring with At Least K Repeating Characters

Description

Find the length of the longest substring T of a given string (consists of lowercase letters only) such that every character in T appears no less than k times.

Example 1:

Input:
s = "aaabb", k = 3

Output:
3

The longest substring is "aaa", as 'a' is repeated 3 times.

Example 2:

Input:
s = "ababbc", k = 2

Output:
5

The longest substring is "ababb", as 'a' is repeated 2 times and 'b' is repeated 3 times.

Solution

Divide and Conquer

考虑使用分治法,如果能找到一个字母在整个字符串中出现的次数小于k次,那么这个字母一定不在结果中的子字符串中。
以这个字符的位置为分界点,把整个字符串分成左边left和右边right中。
同样的方法在leftright字符串中执行,最终结果为两者返回值中的最大值。

首先遍历数组,记录每一个字母出现的次数。
base case: 当所有的字符出现次数均大于k次,返回这个字符串的长度
divide: 找到出现次数小于k次的字符,以该字符为分解,把字符串分为左右两个子字符串。
conquer: 分治两个子字符串
combine: 返回左右子字符串返回结果的最大值

class Solution {
    public int longestSubstring(String s, int k) {
        return longestSubstring(s, k, 0, s.length()-1);
    }
    
    private int longestSubstring(String s, int k, int lo, int hi) {
        // count the appearences of each character
        int[] count = new int[26];
        Arrays.fill(count, 0);
        for (int i = lo; i <= hi; i++) count[s.charAt(i) - 'a']++;
        
        // base case, when all characters appeares more than k times, return the length
        int j;
        for (j = lo; j <= hi; j++) {
            if (count[s.charAt(j)-'a'] < k) break;
        }
        if (j > hi) return (hi - lo + 1);   // when all character appeare more than k times.
        
        // divide and conquer
        int left = longestSubstring(s, k, lo, j-1);
        int right = longestSubstring(s, k, j+1, hi);
        
        // combine
        return Math.max(left, right);
    }
}

Sliding Window

import collections


class Solution(object):
    """算法思路:
    快慢指针-Sliding Window
    首先slow指针一直右移直到当前char的数量不小于k,然后fast指针从slow指针开始
    往后遍历,一直到char的数量小于k,中间我们记录slow到fast之间是否所有的char
    的数量都不小于k,并且记录满足上句条件时fast的位置index,然后把slow挪到index
    上,如此循环,一直到slow指针等于s的长度。
    什么时候用sliding window? 一般使用sliding window的情景都会满足以下条件:
      - 当window满足条件时,fast再往前探不会有更优的结果
    """
    def longestSubstring(self, s, k):
        low, r, n, total = 0, 0, len(s), collections.Counter(s)

        while low < n:
            while low < n and total[s[low]] < k:
                total[s[low]] -= 1
                low += 1

            if low >= n:
                break

            high, counter, mask, index = low, collections.defaultdict(
                int), 0, low

            while high < n and total[s[high]] >= k:
                counter[s[high]] += 1

                bit = 1 << ord(s[high]) - 97
                if counter[s[high]] < k:
                    mask |= bit
                else:
                    mask &= ~bit

                if not mask:
                    index = high
                    r = max(r, high - low + 1)

                high += 1

            while low <= index:
                total[low] -= 1
                low += 1

        return r


s = Solution()
print s.longestSubstring("ababbc", 2)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值