Ransom Note

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. 



(给定一任意字符串ransomNote和magazines字符串,实现一个函数,如果ransomNote字符串能够由magazines中所包含的字母构造,则返回true,否则返回false)

Each 
letter
 in
 the
 magazine 
string 
can
 only 
be
 used 
once
 in
 your 
ransom
 note.
(magazine字符串中的每个字母在ransomNote中只能使用一次)

Note:
You may assume that both strings contain only lowercase letters.(可以假设两个字串都是小写字母)
canConstruct(“a”, “b”) -> false
canConstruct(“aa”, “ab”) -> false
canConstruct(“aa”, “aab”) -> true

1.个人分析
统计ransomNote和magazine中每个字母的个数,如果ransomNote中的字母范围和数目都是magazine的子集,则结果返回true,否则就返回false。这里用元素个数为26的数组note[26]和mag[26]来保存各个字母的个数,字母a对应note[0],mag[0],字母b对应note[1],mag[1],依次类推。最后用note[i]<=mag[i]来判断结果。

2.个人解法

bool canConstruct(string ransomNote, string magazine)
{
    char dict[26];
    for (int i=0; i<26; ++i)
    {
        dict[i] = 'a' + i;
    }
    int note[26] = {0};
    int mag[26] = {0};

    string::iterator it;
    for (it=ransomNote.begin(); it != ransomNote.end(); ++it)
    {
        for (int i=0; i<26; ++i)
        {
            if(*it == dict[i])
                ++note[i];
        }
    }

    for (it=magazine.begin(); it != magazine.end(); ++it)
    {
        for (int i=0; i<26; ++i)
        {
            if(*it == dict[i])
                ++mag[i];
        }
    }

    for(int i=0; i<26; ++i)
    {
        if(note[i] > mag[i])
            return false;
    }

    return true;
}

结果显示自己的实现方法是正确的,而且时间复杂度为O(n),空间复杂度为O(1),唯一的不足是逻辑比较复杂,运行时间也比较慢。

3.参考解决方法

bool canConstruct(string ransomNote, string magazine)
{
    int noteLen = ransomNote.length();
    int magLen = magazine.length();
    int noteCount[26] = {0};
    int magCount[26] = {0};

    if(noteLen > magLen)
        return false;
    if(noteLen == magLen && ransomNote != magazine)
        return false;
    if(noteLen == magLen && ransomNote == magazine)
        return true;

    for (int i=0; i<noteLen; ++i)
    {
        ++noteCount[ransomNote[i] - 'a'];
    }

    for (int i=0; i<magLen; ++i)
    {
        ++magCount[magazine[i] - 'a'];
    }

    for (int i=0; i<26; ++i)
    {
        if(noteCount[i] > magCount[i])
            return false;
    }

    return true;
}

这种方法与自己的方法基本是一致的,但进行了局部优化和简化,在统计两字符串中的字母数时使用了一个技巧,即ransomNote[i] - ‘a’和magazine[i] - ‘a’作为字母的对应下标,这就省去了额外与26个字母进行比较的过程,结果显示效率比上一种方法提高了三倍多。

PS:

  • 题目的中文翻译是本人所作,如有偏差敬请指正。
  • 其中的“个人分析”和“个人解法”均是本人最初的想法和做法,不一定是对的,只是作为一个对照和记录。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值