关于LeetCode中Ransom Note一题的理解

原创 2016年08月29日 17:20:40

题目如下:


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”翻译成中文的意思是“勒索信”。一般的在影视剧中出现的勒索信上的文字好像大都是从报纸或者杂志上剪切下来的,这没准就是这道题目最初的灵感来源。题干的意思是说给定两个字符串分别为ransomNote和magazine,我们要写一个function来判断ransomNote是否能由magazine字符串中的字母组成,而且每个出现在magazine中的字母只能在ransomNote中出现一次。而且你可以假设你处理的这两个小些字符串只包含小写字母。下面举几个例子:

(1)ransomNote为“a”,magazine为“b”,此时magazine中没有字母“a”,所以要返回false;

(2)ransomNote为“aa”,magazine为“ab”,此时magazine中虽然有字母“a”,但是只有一个“a”,而ransomNote需要两个“a”,magazine中“a”的数量不够,所以要返回false;

(3)ransomNote为“aa”,magazine为“aab”,此时magazine中包含ransomNote需要的两个“a”,所以要返回true;

    好,到这里按例又该分析一波思路了。如果我们要判断ransomNote是否可以由magazine中的字母组成,我们只需要判断在ransomNote中出现的每种字母,在magazine中是否有足够数量的同种字母与之对应。也就是说,假如在ransomNote中字母“a”出现了两次,那么字母“a”在magazine中只要出现大于等于2次就肯定能满足ransomNote的需要。那么,为了记录ransomNote和magazine中每种字母和其对应数量的关系,我们就会用到HashMap这种数据结构。将ransomNote和magazine中字母与出现次数的信息分别存入两个HashMap后,我们就可以通过比较两个HashMap中key值对应的value值的大小来判断ransomNote是否能由magazine构成。需要注意的是,比较使用的key值都是ransomNote对应的HashMap中的key值,这一点不要忘了。下面照例是已经Accepted的代码:

<span style="font-size:14px;">    public boolean canConstruct(String ransomNote, String magazine) {
         int ransomNoteLength = ransomNote.length();
        int magazineLength = magazine.length();
        if (magazineLength < ransomNoteLength){
            return false;
        }
        HashMap<String, Integer> ransomNoteMap = new HashMap<String, Integer>();
        HashMap<String, Integer> magazineMap = new HashMap<String, Integer>();
        ArrayList<String> temp = new ArrayList<String>();
        for (int i=0;i<ransomNoteLength;i++){
            String memeber = ransomNote.charAt(i)+"";
            if (!ransomNoteMap.containsKey(memeber)){
                ransomNoteMap.put(memeber,1);
                temp.add(memeber);
            }else{
                ransomNoteMap.put(memeber,ransomNoteMap.get(memeber)+1);
            }
        }

        for (int j=0;j<magazineLength;j++){
            String member2 = magazine.charAt(j)+"";
            if (!magazineMap.containsKey(member2)){
                magazineMap.put(member2,1);
            }else{
                magazineMap.put(member2,magazineMap.get(member2)+1);
            }
        }

        if (magazineMap.size()<ransomNoteMap.size()){
            return false;
        }else{
            for (String a:
                 temp) {
                if (magazineMap.get(a)==null || ransomNoteMap.get(a).intValue() > magazineMap.get(a).intValue() ){
                    return false;
                }
            }
        }

        return true;
    }</span>

    听了这么多废话,下面是喜闻乐见的LeetCode讨论区正片时间。正片中的方法在之前的博客中也有介绍过,由于字符串是由26个小写英文字母组成的,所以我们可以声明一个大小为26的int类型数组,代表26个英文字母和它们出现的次数,其实这里用“出现的次数”代表数组中的数字是不太妥当的,数组中数字的变化更像是生产者和消费者的关系,magazine是生产者,生产出一种字母就在其对应的位置上“加一”,ransomNote是消费者,每“消费”一个字母就在其对应的位置上“减一”。如果ransomNote能够由magazine构成,那么数组所有的位置上肯定都是非负的,如果是负数说明ransomNote消费的,magazine根本生产不了那么多,产能不足自然无法构成ransomNote。大致就是这么一个道理,代码如下:

<span style="font-size:14px;">    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;
    }</span>

   做多了我们就会发现其实LeetCode中有许多问题都是一个套路的,多学会一点套路就能多解决一点问题。


[LeetCode-383]Ransom Note(java)

Given
 an 
arbitrary
 ransom
 note
 string 
and 
another 
string 
containing 
letters from
 all 
the...

leetcode 383. Ransom Note

1. 题目分析  题目描述: Given an arbitrary ransom note string and another string containing letters from all...

[LeetCode]383. Ransom Note(赎金票据)

383. Ransom NoteGiven an arbitrary ransom note string and another string containing letters from all...

LeetCode-383. Ransom Note

问题描述 Given an arbitrary ransom note string and another string containing letters from all the magaz...

LeetCode之路:383. Ransom Note

LeetCode之路:383. Ransom Note 一、引言这是一道非常“时髦”的题目,正好最近也在发生勒索病毒的事情。因此这个标题: Ransom Note 我百度翻译是“勒索信”的含...

[LeetCode]242.Valid Anagram&383. Ransom Note&389. Find the Difference

242.Valid Anagram 383. Ransom Note 389. Find the Difference

leetcode383. Ransom Note

383. Ransom NoteGiven an arbitrary ransom note string and another string containing letters from all...

【LeetCode】383 Ransom Note(java)

原题 题目要求 解法 原题Given
 an 
arbitrary
 ransom
 note
 string 
and 
another 
string 
containing 
letters f...
  • styshoo
  • styshoo
  • 2016年08月17日 17:35
  • 2881

LeetCode笔记:383. Ransom Note

一个字符串是否可以由另一个字符串中的字母组成

LeetCode 383. Ransom Note

题目 : Given an arbitrary ransom note string and another string containing letters from all the magaz...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于LeetCode中Ransom Note一题的理解
举报原因:
原因补充:

(最多只允许输入30个字)