【二分】C017_LC_比较字符串最小字母出现频次(暴力 / 二分优化)

一、Problem

我们来定义一个函数 f(s),其中传入参数 s 是一个非空字符串;该函数的功能是统计 s 中(按字典序比较)最小字母的出现频次。

例如,若 s = “dcce”,那么 f(s) = 2,因为最小的字母是 “c”,它出现了 2 次。

现在,给你两个字符串数组待查表 queries 和词汇表 words,请你返回一个整数数组 answer 作为答案,其中每个 answer[i] 是满足 f(queries[i]) < f(W) 的词的数目,W 是词汇表 words 中的词。

输入:queries = ["cbd"], words = ["zaaaz"]
输出:[1]
解释:查询 f("cbd") = 1,而 f("zaaaz") = 3 所以 f("cbd") < f("zaaaz")。

提示:

1 <= queries.length <= 2000
1 <= words.length <= 2000
1 <= queries[i].length, words[i].length <= 10
queries[i][j], words[i][j] 都是小写英文字母

二、Solution

方法一:暴力

没啥可说的…

class Solution {
    int f(char[] w) {
        int[] mp = new int[258];
        for (char c : w) 
            mp[c]++;
        Arrays.sort(w);
        return mp[w[0]];
    }
    public int[] numSmallerByFrequency(String[] qs, String[] ws) {
        List<Integer> l = new LinkedList<>();
        for (String w : ws)
            l.add(f(w.toCharArray()));
    
        List<Integer> ans = new ArrayList<>();
        for (String q : qs) {
            int cnt = f(q.toCharArray()), b = 0;
            for (int c : l) if (c > cnt) {
                b++;
            }
            ans.add(b);
        }
        int[] a = new int[ans.size()];
        for (int i = 0; i <a.length; i++) 
            a[i] = ans.get(i);
        return a;
    }
}

可优化的地方有二:

  • 方法 f f ,里利用一个遍历 min 记录字典序最小字符。
  • 利用 fori 来遍历 qs,然后嵌套遍历 ws,省去开一个 List 来装载结果。

复杂度分析

  • 时间复杂度: O ( q s × w s ) O(qs × ws) ,qs 表示查询的组数
  • 空间复杂度: O ( w s ) O(ws)

方法二:二分优化

由于是在 words[] 中找的是比 f(query[i]) 小的所有字符串的数量,所以可用 f 先求出 words 中所有的值到数组 a 中,然后排序,遍历 query 的时候用二分法在 a 中统计所有大于 query[i] 的数量。

class Solution {
    int f(String s) {
        int min = 'z'+5, cnt = 0;
        for (char c : s.toCharArray()) {
            if (c < min) {
                min = c;
                cnt = 0;
            } else if (c == min){
                cnt++;
            }
        }
        return cnt;
    }
    public int[] numSmallerByFrequency(String[] qs, String[] ws) {
        int m = ws.length, a[] = new int[m];
        for (int i = 0; i < m; i++)
            a[i] = f(ws[i]);
        Arrays.sort(a);

        int n = qs.length, ans[] = new int[n];
        for (int i = 0; i < n; i++) {
            int tar = f(qs[i]), l = 0, r = m-1;
            while (l < r) {
                int mid = l + r >>> 1;
                if (a[mid] > tar) {
                    r = mid;
                } else {
                    l = mid + 1;
                }
            }
            ans[i] = tar >= a[l] ? 0 : m - l;
        }
        return ans;
    }
}

复杂度分析

  • 时间复杂度: O ( N l o g ( N ) ) O(Nlog(N)) ,N = max(m, n)
  • 空间复杂度: O ( n ) O(n)

猜你喜欢

转载自blog.csdn.net/qq_43539599/article/details/106882328