Leetcode记录库解题方法篇之一:计数法

简介

六、字符串

结论

一些很主观的东西,归根到底可能还是自己的实力不够:

计数法类似于计数排序以及哈希表的思想,一般用于有关字符的问题中,不使用字符的索引作为某个字符的标志,而是使用字符本身的ASCII码值作为暂存数组的索引。

1 242. 有效的字母异位词

题目

思路描述

  • 使用HashMap的思想
  • 遍历第一个字符串记录每一个字符的出现次数,然后遍历第二个字符串的过程中减少字符的次数,最后查看所有字符的出现次数是不是归零了。
  • 时间复杂度O(n),空间O(1)

代码实现
java代码:

class Solution {
    public boolean isAnagram(String s, String t) {
        int[] ch = new int[26];
        for(int c : s.toCharArray()){
            ch[c - 'a']++;
        }
        for(int c : t.toCharArray()){
            ch[c - 'a']--;
        }
        for(int i : ch){
            if(i != 0) return false;
        }

        return true;
    }
}

注意事项

  1. 注意事项

拓展延伸

  1. 拓展延伸

2 409. 最长回文串

题目

思路描述

  • 没用什么思想
  • 时间复杂度O(n),空间O(1)

代码实现
java代码:

class Solution {
    public int longestPalindrome(String s) {
        int[] ch = new int[58]; // 48 -> 0, 65 -> A, 97 -> a, 122 -> z
        int len = 0;
        for(char c: s.toCharArray()){
            ch[c - 'A']++;
        }

        for(int i: ch){
            if(i % 2 == 0) len += i; // 字符个数是偶数的来者不拒全都要
            if(i % 2 == 1) {
                len += i - 1; // 字符个数为奇数的,减去一变成偶数全都收下
            }
        }
        if(len < s.length()) len++; // 如果最后还小于s的长度时,随便再取一个放到正中间
        
        return len;
    }
}

注意事项

  1. 注意事项

拓展延伸

  1. 拓展延伸

3 205. 同构字符串

题目

思路描述

  • 对于一个字符串我们用它的字符j作为数组索引,然后只记录它上次出现的位置,进行遍历字符串对比。
  • 时间复杂度O(n),空间O(1)

代码实现
java代码:

class Solution {
    public boolean isIsomorphic(String s, String t) {
        int[] sc = new int[256];
        int[] tc = new int[256];

        for(int i = 0; i < s.length(); i++){
            if(sc[s.charAt(i)] == tc[t.charAt(i)]){
                sc[s.charAt(i)] = i + 1;
                tc[t.charAt(i)] = i + 1;
            } else {
                return false;
            }
        }

        return true;
    }
}

注意事项

  1. 注意事项

拓展延伸

  1. 拓展延伸

3 76. 最小覆盖子串

题目

思路描述

  • 双指针,滑动窗口,计数法
  • 时间复杂度O(n),空间复杂度O(1)

代码实现
java代码:

class Solution {
    public String minWindow(String s, String t) {
        // 双指针?滑动窗口
        int sn = s.length(), tn = t.length();
        if (sn < tn) {
            return "";
        }

        int[] charArr = new int[128];
        int cnt = tn; // t中的字母个数
        for (int i = 0; i < tn; i++) {
            charArr[t.charAt(i)]++; // 对应的字母位置计数,计数法
        }

        int l = 0, r = 0, ansL = 0, ansR = 0, min = sn + 1; // min是窗口大小,最初给一个较大的值
        while (r < sn) {
            while (r < sn && cnt != 0) {
                if (charArr[s.charAt(r)] > 0) {
                    cnt--; // 没有被覆盖的字母个数减一
                }
                charArr[s.charAt(r)]--; // 字母计数减一
                r++; // 指针右移,注意在不满足循环条件时 r 已经指向下一个位置了
            }

            if (r == sn && cnt != 0 && min == sn + 1) { // 如果r == sn 了,但是cnt还没有清空,而且也并没有进行过缩减窗口的操作,说明t中有s中没有的字母
                return "";
            }

            while (l < r && cnt == 0) { // 缩减窗口
                if (charArr[s.charAt(l)] < 0) {
                    charArr[s.charAt(l)]++;
                    l++;
                } else {
                    if (min > r - l) { // 记录新的满足要求的窗口大小
                        ansL = l;
                        ansR = r;
                        min = r - l;
                    }
                    charArr[s.charAt(l)]++; // 对应的字母位置重新计数
                    l++;
                    cnt++;
                }
            }
        }

        return s.substring(ansL, ansR);
    }
}

注意事项

  1. 注意事项

拓展延伸

  1. a
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值