【LeetCode】383 Ransom Note(java)

纵饮孤独 提交于 2020-03-01 04:06:34

原题

Given
 an 
arbitrary
 ransom
 note
 string 
and 
another 
string 
containing 
letters from
 all 
the 
magazines,
 write 
a 
function 
that 
will 
return 
true 
if 
the 
ransom 
 note 
can 
be 
constructed 
from 
the 
magazines ; 
otherwise, 
it 
will 
return 
false. 



Each 
letter
 in
 the
 magazine 
string 
can
 only 
be
 used 
once
 in
 your 
ransom
 note.

Note: You may assume that both strings contain only lowercase letters.

canConstruct("a", "b") -> false
canConstruct("aa", "ab") -> false
canConstruct("aa", "aab") -> true

题目要求

题目叫做Ransom Note,勒索信,刚开始我还没理解这个题目的意思,尤其这个标题,和magazine有啥关系呢?后来仔细想想,才慢慢理解。勒索信,为了不暴露字迹,就从杂志上搜索各个需要的字母,组成单词来表达的意思。这样来说,题目也就清晰了,判断杂志上的字是否能够组成勒索信需要的那些字符。 这里需要注意的就是杂志上的字符只能被使用一次,不过不用考虑大小写的问题。 有一种最简单的理解就是对于ransomNote里每个字符出现的次数必须小于或者等于该字符在magazine出现的次数。

解法

解法一:这种解法比较简单,就是将ransomNote的字符串挨个遍历,每个字符再从magazine里遍历匹配,只是再创建了个byte数组,数组每个元素的索引表示magazine字符串的位置,元素值表示是否被校验过,0表示还未被校验过,非0就表示该位置已经被校验过。不过这种做法效率不高。

    public boolean canConstruct(String ransomNote, String magazine) {
        boolean ret = true;
        byte[] bytes = new byte[magazine.length()];
        for (int i = 0; i < ransomNote.length(); i++) {
            char c = ransomNote.charAt(i);
            boolean found = false;
            for (int j = 0; j < magazine.length(); j++) {
                if (bytes[j] == 0 && magazine.charAt(j) == c) {
                    bytes[j]++;
                    found = true;
                    break;
                }
            }
            if (!found) {
                ret = false;
                break;
            }
        }
        
        return ret;
    }

解法二:将ransomNote和magazine都从小到大排序,然后对ransomNote遍历,同时在magazine中匹配,如果匹配到了,则记住此时magazine中字符的索引,便于下次操作,因为都是排序的。如果直到magazine中字符已经大于ransomNote中字符了,就说明就再也匹配不到了,则表示匹配失败。

    public boolean canConstruct(String ransomNote, String magazine) {
        boolean ret = true;
        char[] ra = ransomNote.toCharArray();
        Arrays.sort(ra);
        char[] ma = magazine.toCharArray();
        Arrays.sort(ma);
        
        int index = 0;
        boolean found = true;
        for (int i = 0; i < ra.length && ret; i++) {
            char ri = ra[i];
            found = false;
            for (int j = index; j < ma.length; j++) {
                if (ma[j] > ri) {
                    ret = false;
                    break;
                } else if (ma[j] == ri) {
                    index++;
                    found = true;
                    break;
                } else {
                    index++;
                }
            }
            if (!found) {
                ret = false;
                break;
            }
        }
        
        return ret;
    }

解法三:这是LeetCode Discuss中的最热代码,它的原理就是列出了magazine的字母表,然后算出了出现个数,然后遍历ransomNote,保证有足够的字母可用,代码非常清晰。

    public boolean canConstruct(String ransomNote, String magazine) {
        int[] arr = new int[26];
        for (int i = 0; i < magazine.length(); i++) {
            arr[magazine.charAt(i) - 'a']++;
        }
        for (int i = 0; i < ransomNote.length(); i++) {
            if(--arr[ransomNote.charAt(i)-'a'] < 0) {
                return false;
            }
        }
        return true;
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!