leetcode 1647

这篇博客讨论了一种优化算法,用于统计字符串中字符出现的频率并确定最少删除次数。作者首先使用HashMap统计频率,然后用一个大数组和HashSet进行优化。经过改进,通过直接使用int[]数组和HashSet,减少了空间复杂度,并通过排序简化了频率处理过程。博客强调了在解决这类问题时如何简化数据结构和减少不必要的操作,提高了算法效率。
摘要由CSDN通过智能技术生成

这题就是先统计字符串里每个字符出现的频率,然后用一个set保存不重复的频率,遍历每个频率,不在set里直接累加,在的话就一直减直到不在set里,此时频率大于0则累加。最后答案等于字符串长度减掉累加的频率数。

class Solution {
    public int minDeletions(String s) {
        Map<Character, Integer> freq = new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            int cnt = freq.getOrDefault(s.charAt(i), 0);
            freq.put(s.charAt(i), cnt + 1);
        }
        boolean[] visited = new boolean[100001];
        int sum = 0;
        for (Map.Entry<Character, Integer> e : freq.entrySet()) {
            int index = e.getValue();
            while (index > 0 && visited[index]) {
                index--;
            }
            if (index > 0) {
                visited[index] = true;
                sum += index;
            }
        }
        return s.length() - sum;
    }
}

上面是我第一版的代码,写完之后提交发现很慢,然后回头看觉得蠢的不行,我明明只用到了每个字符的频率,那根本不需要用map,因为a-z就26个字符嘛,直接用长度26的int[]就行了。然后我这个10^5+1的数组也是开的令人窒息,直接用一个set保存频率就行了。

优化之后的代码如下。

class Solution {
    public int minDeletions(String s) {
        int[] freq = new int[26];
        for (int i = 0; i < s.length(); i++) {
            freq[s.charAt(i) - 'a']++;
        }
        Set<Integer> uniqueFreq = new HashSet<>();
        int sum = 0;
        Arrays.sort(freq);
        for (int f : freq) {
            while (uniqueFreq.contains(f) && f > 0) {
                f--;
            }
            if (f > 0) {
                sum += f;
                uniqueFreq.add(f);
            }
        }
        return s.length() - sum;
    }
}

后来我又试了一下,这里对于长为26的频率数组是否排序完全不影响结果,因为如果有多个相同频率的字符,对于结果没有影响,结果只是问长度,而不是问具体删减之后的字符串长啥样,这有点像之前的找最大公共子串,只是问长度,没问具体子串是啥,当然这个我会,后面记得填坑。

回过来,虽然排序不影响结果,但是我一开始写的时候对于怎么给int[]数组降序排序折腾了半天,Arrays.sort(int[]) 后面没法传入Collections.reverseOrder(),所以要么直接sort之后反过来,要么用Integer[]数组之后用Arrays.sort(a, Collections.reverseOrder()),注意这样的话要循环初始化每一位,不然每一位是空指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值