leetcode算法题:统计给定字符串中的所有子字符串中的唯一字符个数和

LeetCode上面的一道算法题

我们定义了一个函数 countUniqueChars(s) 来统计字符串 s 中的唯一字符,并返回唯一字符的个数。例如:s = “LEETCODE” ,则其中 “L”, “T”,“C”,“O”,“D” 都是唯一字符,因为它们只出现一次,所以 countUniqueChars(s) = 5 。本题将会给你一个字符串 s ,我们需要返回 countUniqueChars(t) 的总和,其中 t 是 s 的子字符串。注意,某些子字符串可能是重复的,但你统计时也必须算上这些重复的子字符串(也就是说,你必须统计 s 的所有子字符串中的唯一字符)。由于答案可能非常大,请将结果 mod 10 ^ 9 + 7 后再返回。

解题思路

  1. 第一种解题思路:拿输入字符串对其每一个字符都去前后分别寻找相同字符,则有[j…i…k]这样的一个区间,前方未找到则j为-1,后方未找到则k为字符串长度。对于这样的一个区间一共存在多少个含有该字符的子集呢?
    举个例子比如字符串ABCDE

对于A 它的区间为[-1…0…5],有以下情况A AB ABC ABCD ABCDE
对于B 它的区间为[-1…1…5],有以下情况B BC BCD BCDE / AB ABC ABCD ABCDE
对于C 它的区间为[-1…2…5],有以下情况C CD CDE / BC BCD BCDE / ABC ABCD ABCDE
我们可以发现对于给定区间[j…i…k]它含有唯一字符的子集为(i - j)*(k - i)即可理解为以该唯一字符下标为基准,左边含有的字符数乘以右边含有的字符数即为它们可以组合的只含有一个该字符的子集数
2. 第二种解题思路:对于字符串s,循环遍历得到它全部的子集,分别去统计每一个子集中包含的唯一字符数。

java代码实现

class Solution {

    /**
     * 最优解:前后搜索比较法 
     */
    public static int uniqueLetterString(String s) {
        long num = 0;
        int j, k;
        for (int i = 0; i < s.length(); i++) {
            j = i - 1;
            k = i + 1;

            while (j >= 0) {
                if (s.charAt(i) == s.charAt(j)) {
                    break;
                }
                j--;
            }

            while (k < s.length()) {
                if (s.charAt(i) == s.charAt(k)) {
                    break;
                }

                k++;
            }

            num += (i - j) * (k - i);
        }

        return (int)num % 1000000007;
    }

    /**
     * 测试一半超时不通过:利用截取获取连续的子字符串,统计 s 的所有子字符串中的唯一字符
     */
    public int uniqueLetterString2(String s) {
        if(s == null){
            return 0;
        }

        long num = 0;
        for(int i = 0 ; i < s.length() ; i++ ){
            for(int j = i + 1 ; j < s.length() + 1 ; j++){
                String t = s.substring(i , j);
                num += countUniqueChars(t);
            }
        }

        return (int)num % 1000000007;
    }


    /**
     * 统计字符串 s 中的唯一字符,并返回唯一字符的个数
     */
    public int countUniqueChars(String t){
        int num = 0;
        Set<Integer> sameIndex = new TreeSet<>();

        for(int i = 0; i < t.length(); i++){
            if(sameIndex.contains(i) == true){
                continue;
            }

            boolean sameFalg = false;
            for(int j = i + 1; j < t.length(); j ++){
                 if(t.charAt(i) == t.charAt(j)){
                     sameIndex.add(j);
                     if(sameFalg == false) sameFalg = true;
                 }
            }

            if(sameFalg == false){
                num ++;
            }
        }

        return num;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值