算法学习笔记之初级字符串(6.3 两题)

LeetCode刷题总结

1. 有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。

示例 1

输入: s = "anagram", t = "nagaram"
输出: true

示例 2

输入: s = "anagram", t = "nagaram"
输出: true

说明

你可以假设字符串只包含小写字母。

进阶

如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?

我的思路与解答(6ms):

class Solution {
    public boolean isAnagram(String s, String t) {
        // 先判断字符串长度是否相等,如果不相等则直接返回false
        if(s.length() != t.length()){
            return false;
        }

        // 将字符串转为char类型数组,并排序
        char[] sc = s.toCharArray();
        char[] tc = t.toCharArray();
        Arrays.sort(sc);
        Arrays.sort(tc);

        // 排序后从第一个char开始对比,若有不同则直接返回false
        for(int i = 0; i < sc.length; i++){
            if(sc[i] != tc[i]){
                return false;
            }
        }

    // 默认返回true
        return true;
    }
}

别人的解答(4ms):

class Solution {
    public boolean isAnagram(String s, String t) {
    // 定义一个int类型数组,长度为26即26个字母,用于记录 s中出现的次数 - t中出现的次数
        int []chars = new int[26];

    // 先记录s中每个字母出现次数
        for(char c : s.toCharArray()){
            chars[c-'a']++;
        }
    // 再将t中每个字母出现的次数扣除
        for(char c: t.toCharArray()){
            chars[c-'a']--;
        }
    // 如果这个字母的记录值为0,则s和t中出现的次数一样,反之次数不一样,也就是两个字符串不是有效的字母异位词
        for(int i : chars){
            if( i != 0){
                return false;
            }
        }
        return true;
    }
}

小结:

我的办法是利用了Arrays.sort()方法,思路比较简单,相同的字符串排序后肯定所有字符的顺序一定是一样的,所以只需排序后对比各个字符,性能较差。

而别人的解答,思路较为不同,是统计各个字符出现的次数,进行对比,没有用到Arrays.sort()方法,性能较好一些。

2. 验证回文字符串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明

本题中,我们将空字符串定义为有效的回文串。

示例 1

输入: "A man, a plan, a canal: Panama"
输出: true

示例 2

输入: "race a car"
输出: false

我的思路与解答(218 ms):

class Solution {
    public boolean isPalindrome(String s) {
        StringBuffer sb = new StringBuffer(s);

    // 利用StringBuffer将不是字母或者数字的字符删除,并将大写字母转换为小写字母
        for(int i = 0; i < sb.length(); i++){
            if(sb.charAt(i) >= '0' && sb.charAt(i) <= '9'){
                continue;
            }
            if(sb.charAt(i) >= 'A' && sb.charAt(i) <= 'Z'){
                // 小写字母unicode码比大写的大32
                sb.setCharAt(i, (char)(sb.charAt(i) + 32));
                continue;
            }
            if(sb.charAt(i) < 'a' || sb.charAt(i) > 'z'){
                sb.delete(i, i+1);
                i--;
            }
        }

        char[] sc = sb.toString().toCharArray();

    // 从第一个与最后一个进行循环对比
        for(int i = 0; i < sc.length/2; i++){
            if(sc[i] != sc[sc.length - i -1]){
                return false;
            }
        }
        return true;
    }
}

别人的解答(3ms):

class Solution {
    public boolean isPalindrome(String s) {
    // 若字符串为空或者内容为空则直接返回true
        if(s == null || s.length() == 0) return true;
    // 声明两个int类型的变量用来标记第一个字母和最后一个字母
        int start = 0;
        int end = s.length() - 1;
    // 判断字母是否是数字或者字母,如果不是则指向下一个字符,并将大写字母转换为小写字母
        while(start < end) {
            char c = ' ';
            while(start < end) {
                c = s.charAt(start);
                if(c >= 'a' && c <= 'z') {
                    break;
                } else if(c >= '0' && c <= '9') {
                    break;
                } else if(c >= 'A' && c <= 'Z') {
                    c = (char) (c - 'A' + 'a');
                    break;
                } else {
                    start++;
                }
            }
            
            char b = ' ';
            while(start < end) {
                b = s.charAt(end);
                if(b >= 'a' && b <= 'z') {
                    break;
                } else if(b >= '0' && b <= '9') {
                    break;
                } else if(b >= 'A' && b <= 'Z') {
                    b = (char) (b - 'A' + 'a');
                    break;
                } else {
                    end--;
                }
            }
        // 进行对比
            if(start < end) {
                if(c != b) {
                    return false;
                }
                start++;
                end--;
            }
        }
        return true;
    }
}

小结:

我的办法是利用了StringBuffer,将不是数字与字母的删除,并将大写字母转换为小写字母,再进行对比。

而别人的解答,用了两个变量来标记要对比的两个字母的位置,所以少了删除的操作,并且没有用到StringBuffer,性能比我的解答大大提高。

3. 总结

从这两题来看,我的算法知识还比较差,特别是第二题,花费了较多的性能去做了没必要的操作,要学会灵活使用变量来标记位置,不过整体思路还算清晰,需要继续努力。

4. 最后

欢迎来看我的博客 RoNnx的博客

你可能感兴趣的:(算法学习笔记之初级字符串(6.3 两题))