LeetCode.1160-找到可以由给定字符组成的字符串(Find Words That Can Be Formed by Characters)

这是小川的第411次更新,第443篇原创

看题和准备

今天介绍的是LeetCode算法题中Easy级别的第262题(顺位题号是1160)。你会得到一个字符串单词数组和一个字符串chars。如果字符串可以由字符中的字符组成(每个字符只能使用一次),则该字符串是好的。返回所有好的字符串的长度之和。

例如:

输入:words = ["cat","bt","hat","tree"],chars ="atach"
输出:6
说明:可以形成的字符串是"cat"和"hat",因此答案是3 + 3 = 6。

输入:words = ["hello","world","leetcode"],chars ="welldonehoneyr"
输出:10
说明:可以形成的字符串是"hello"和"world",因此答案是5 + 5 = 10。

注意

  • 1 <= words.length <= 1000

  • 1 <= words[i].length , chars.length <= 100

  • 所有字符串仅包含小写英文字母。

第一种解法

题目的意思是,给了一个由英文小写字母组成的字符串chars,在字符串数组words中,如果单词能够由chars中的字符组成,那么此单词就是一个好单词。

我们直接翻译题目即可,将chars理解成一个数组字典,每个字母出现的次数计数,变成一个26位长度的int数组,接着去遍历words中的单词,采用同样的原理,将单词每个字母当做字典数组的索引,出现一次就减1,如果字典数组中的元素值小于0,说明当前单词无法由chars中的字母组成,结束本此循环,直到遍历完所有单词。

public int countCharacters(String[] words, String chars) {
    // 获取字典数组
    int[] dict = stringToIntegerArray(chars);
    int sum = 0;
    for (int i=0, len=words.length; i<len; i++) {
        // 复制一份字典数组,为后面的减法做准备
        int[] temp = dict.clone();
        int len2 = words[i].length();
        // 默认当前单词是好字符串
        boolean flag = true;
        for (int j=0; j<len2; j++) {
            // 单词中的字母不在字典中,或超过使用次数
            if (--temp[words[i].charAt(j)-'a'] < 0) {
                flag = false;
                break;
            }
        }
        if (flag) {
            sum += words[i].length();
        }
    }
    return sum;
}

/**
 * 将字符串转为长度为26的int数组
 * @param s 字符串
 * @return 长度为26的int数组
 */
public int[] stringToIntegerArray(String s) {
    int[] arr = new int[26];
    for (int i=0, len=s.length(); i<len; i++) {
        arr[s.charAt(i)-'a']++;
    }
    return arr;
}

第二种解法

和第一种解法的思路类似,只是将第一种解法的数组复制替换成了另外一种写法,将当前单词也转为一个长度为26的int数组,然后比较字典数组和单词数组元素值的大小,如果单词数组当前元素值大于字典数组当前元素值,则表示单词中的某些字母不在字典中或者出现次数超过了字典中的次数。

public int countCharacters2(String[] words, String chars) {
    // 获取字典数组
    int[] dict = stringToIntegerArray(chars);
    int sum = 0, len = words.length, len2 = dict.length;
    for (int i=0; i<len; i++) {
        // 将单词也转为int数组
        int[] temp = stringToIntegerArray(words[i]);
        boolean flag = true;
        for (int j=0; j<len2; j++) {
            if (temp[j] > dict[j]) {
                flag = false;
                break;
            }
        }
        if (flag) {
            sum += words[i].length();
        }
    }
    return sum;
}

/**
 * 将字符串转为长度为26的int数组
 * @param s 字符串
 * @return 长度为26的int数组
 */
public int[] stringToIntegerArray(String s) {
    int[] arr = new int[26];
    for (int i=0, len=s.length(); i<len; i++) {
        arr[s.charAt(i)-'a']++;
    }
    return arr;
}

小结

算法专题目前已更新LeetCode算法题文章268+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。

以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!

posted @ 2019-09-22 10:33  程序员小川  阅读(1007)  评论(0编辑  收藏  举报