LeetCode:Valid Anagram

a 夏天 提交于 2019-12-15 20:25:43

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

1、题目名称

Valid Anagram (易位构词)

2、题目地址

https://leetcode.com/problems/valid-anagram/

3、题目内容

英文:Given two strings s and t, write a function to determine if t is an anagram of s.

中文:给出两个字符串,写一个函数判断t是否是s的易位构词

例如:

s = "anagram", t = "nagaram", return true.

s = "rat", t = "car", return false.

4、题目分析

易位构词游戏的规则可以参考相关的 维基百科页面 :易位构词是一类文字游戏。它的规则是将组成一个词或短句的字母重新排列顺序,原文中所有字母的每次出现都被使用一次,这样构造出另外一些新的词或短句。现在我们要判断的就是给出两个字符串s和t,判断字符串t能否由s通过易位构词产生。

5、一个超时的方法

在做这个题的时候我第一个想到的方法就是,将s和t两个字符串先转换成数组,然后分别对两个数组进行排序,再对两个排序后的数组进行逐位比较。如果发现两个数组中不一致的地方,则返回false,否则返回true。对应的Java代码如下:

/**
 * 功能说明:LeetCode 242 - Valid Anagram
 * 开发人员:Tsybius2014
 * 开发时间:2015年8月4日
 */
public class Solution {

    /**
     * 判断两个字符串是否为易位构词
     * @param s 字符串1
     * @param t 字符串2
     * @return
     */
    public boolean isAnagram(String s, String t) {
        
        if (s == null || t == null || s.length() != t.length()) {
            return false;
        }
        
        char[] charListS = s.toCharArray();
        char[] charListT = t.toCharArray();
        
        char temp;
        
        //对字符串s和t进行排序
        for (int i = 0; i < charListS.length; i++) {
            for (int j = i + 1; j < charListT.length; j++) {
                if (charListS[i] > charListS[j]) {
                    temp = charListS[i];
                    charListS[i] = charListS[j];
                    charListS[j] = temp;
                }
                if (charListT[i] > charListT[j]) {
                    temp = charListT[i];
                    charListT[i] = charListT[j];
                    charListT[j] = temp;
                }
            }
        }

        //逐个字符比较排序结果
        for (int i = 0; i < charListS.length; i++) {
            if (charListS[i] != charListT[i]) {
                return false;
            }
        }
        
        return true;
    }
}

但是,使用这段代码,OJ返回的结果是超时(Time Limit Exceeded)

6、解题方法1

我又想出了一个办法,即循环考察字符串s中的各字符,将字符串t中找到的第一个一样的字符换成字符' '。如果在替换过程中,发现t中已经没有合适的字符进行替换,则返回false。如果直到s中的字符循环完都没有返回false,可认为s与t中所用到的每个字母的数量都是一致的。

Java代码如下:

/**
 * 功能说明:LeetCode 242 - Valid Anagram
 * 开发人员:Tsybius2014
 * 开发时间:2015年8月4日
 */
public class Solution {

    /**
     * 判断两个字符串是否为易位构词
     * @param s 字符串1
     * @param t 字符串2
     * @return
     */
    public boolean isAnagram(String s, String t) {
        
        if (s == null || t == null || s.length() != t.length()) {
            return false;
        }
        
        char[] charListS = s.toCharArray();
        char[] charListT = t.toCharArray();
        
        boolean b = false;
        
        //逐个用s的字符对t进行替换
        for (int i = 0; i < charListS.length; i++) {
            b = false;
            for (int j = 0; j < charListT.length; j++) {
                if (charListS[i] == charListT[j]) {
                    charListT[j] = ' ';
                    b = true;
                    break;
                }
            }
            if (!b) {
                return false;
            }
        }
        
        return true;
    }
}

这段代码的Runtime为1640ms

7、解题方法2

其实上面提到的那个超时(TLE)的方法,如果用Arrays.sort函数对数组进行排序,就可以比自己用两个for循环要快很多。

Java代码如下:

import java.util.Arrays;

/**
 * 功能说明:LeetCode 242 - Valid Anagram
 * 开发人员:Tsybius2014
 * 开发时间:2015年8月4日
 */
public class Solution {

    /**
     * 判断两个字符串是否为易位构词
     * @param s 字符串1
     * @param t 字符串2
     * @return
     */
    public boolean isAnagram(String s, String t) {
        
        if (s == null || t == null || s.length() != t.length()) {
            return false;
        }
        
        char[] charListS = s.toCharArray();
        char[] charListT = t.toCharArray();
        
        Arrays.sort(charListS);
        Arrays.sort(charListT);
        
        for (int i = 0; i < charListS.length; i++) {
            if (charListS[i] != charListT[i]) {
                return false;
            }
        }
        
        return true;
    }
}

这个方法用了336ms

8、解题方法3

最后还有一种方法,思路是我在Discuss中看到的,即通过一个长度为26的整形数组,对应英文中的26个字母a-z。从前向后循环字符串s和t,s中出现某一字母则在该字母在数组中对应的位置上加1,t中出现则减1。如果在s和t中所有字符都循环完毕后,整型数组中的所有元素都为0,则可认为s可由易位构词生成t。

Java代码如下:

/**
 * 功能说明:LeetCode 242 - Valid Anagram
 * 开发人员:Tsybius2014
 * 开发时间:2015年8月4日
 */
public class Solution {

    /**
     * 判断两个字符串是否为易位构词
     * @param s 字符串1
     * @param t 字符串2
     * @return
     */
    public boolean isAnagram(String s, String t) {
        
        if (s == null || t == null || s.length() != t.length()) {
            return false;
        }

        //字母统计
        int[] letterCounter = new int[26];
        for (int i = 0; i < s.length(); i++) {
            letterCounter[s.charAt(i) - 'a']++;
            letterCounter[t.charAt(i) - 'a']--;
        }
        
        //如果s的各个字母数量与t一致,那么letterCounter数组的元素应该全部为0
        for (int count : letterCounter) {
            if (count != 0) {
                return false;
            }
        }
        
        return true;
    }
}

附:使用JavaScript语言实现的解题代码(2016年1月23日加入)

方法1:

/**
 * 判断两个字符串是否为易位构词
 * @param {string} s 字符串1
 * @param {string} t 字符串2
 * @return {boolean}
 */
var isAnagram = function(s, t) {
    if (s === null || t === null || s.length != t.length) {
        return false;
    }
    s = s.split('').sort(); //将字符串转换为数组后进行排序
    t = t.split('').sort();
    for (var i = 0; i < s.length; i++) {
        if (s[i] != t[i]) {
            return false;
        }
    }
    return true;
};

方法2:

/**
 * 判断两个字符串是否为易位构词
 * @param {string} s 字符串1
 * @param {string} t 字符串2
 * @return {boolean}
 */
var isAnagram = function(s, t) {
    if (s === null || t === null || s.length != t.length) {
        return false;
    }
    var counter = { };
    counter.length = 26;
    var i;
    for (i = 0; i < counter.length; i++) {
        counter[i] = 0;
    }
    for (i = 0; i < s.length; i++) {
        counter[s.charCodeAt(i) - 97]++; //获取字符串指定位置字符的ASC码
        counter[t.charCodeAt(i) - 97]--;
    }
    for (i = 0; i < counter.length; i++) {
        if (counter[i] !== 0) {
            return false;
        }
    }
    return true;
};

END

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!