383. Ransom Note

1.问题描述

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
来自 https://leetcode.com/problems/ransom-note/description/

2.题目分析

判断字符串s是否可以由m中的字母重组得到,m中的字母只能用一次。最能想到的方法就是遍历s中的每个字母,判断是否在m中出现,假如没有出现,返回false,否者删除m中的这个字符,更新后的m用于下一次的处理。由于用到字符串的查找find和删除erase,效率比较低。另一种灵活的方法就是,新建一个代表26字母个数的表,表中存储m中出现的字母个数,遍历s字符串,并对talble中的字母个数进行判断。当表中对应的字母个数为0时,返回false,否则减少表中当前字母的个数。

3.C++代码

//我的代码:(beats 18%)
bool canConstruct2(string r, string m)
{
    for (int i = 0; i < r.length(); i++)
    {
        int pos = m.find_first_of(r[i]);
        if (pos!=-1)
            m.erase(pos,1);
        else
            return false;
    }
    return true;
}
//改进后的代码:(beats 89%)
bool canConstruct(string r, string m)
{
    int talble[26] = { 0 };
    for (int i = 0; i < m.length(); i++)
        talble[m[i] - 'a']++;
    for (int j = 0; j < r.length(); j++)
    {
        if (talble[r[j] - 'a'] > 0)
            talble[r[j] - 'a']--;
        else
            return false;
    }
    return true;
}

4.string类中的查找find

根据vs的自动补全,我们可以知道string类提供了以下几种和查找相关的成员函数
根据vs的自动补全

1.string.find()

//返回字符串s1在s中的位置,如果没找到,则返回-1

#include <iostream>
using namespace std;
void main()
{
    string s = "hello";
    string s1 = "ll";
    string s2 = "l";
    int pos = s.find(s1);
    cout << "s1 position=" << pos << endl;
    pos = s.find(s2, 1);//从下标1开始查找
    cout << "s2 position=" << pos << endl;
}

2.string.find_first_of()

//从前往后查找,返回字符s1的任一字符在s中第一次出现的位置

#include <iostream>
using namespace std;
void main()
{
    string s = "abcdabcd";
    string s1 = "d";
    int pos =s.find_first_of(s1);
    cout << pos << endl;
    pos = s.find_first_of(s1,4);
    cout << pos << endl;

}

3.string.find_first_not_of()

//从前往后查找,返回字符串s1任一字符与s第一个不匹配的位置

4.string.find_last_of()

//从后往前查找,返回字符串s1与s第一个匹配的位置

5.string.find_last_not_of()

//从后往前查找,返回字符串s1与s第一个不匹配的位置

6.string.rfind()

//从后往前查找,返回在s从后往前查找s1第一次出现的位置

注意

s.find(s1) , s.rfind(s1) 这两个函数,如果完全匹配,才返回匹配的索引,即:当s中含有s1全部字母时,才返回当前索引。
s.find_first_of(s1), s.find_first_not_of(s1), s.find_last_of(s1), s.find_last_not_of(s1) 这四个函数,查找s中含有s1中任意字母的索引。

5.string类中的删除erase函数

erase函数的原型如下:
(1)string& erase ( size_t pos = 0, size_t n = npos );
(2)iterator erase ( iterator position );
(3)iterator erase ( iterator first, iterator last );
也就是说有三种用法:
(1)erase(pos,n); 删除从pos开始的n个字符,比如erase(0,1)就是删除第一个字符
(2)erase(position);删除position处的一个字符(position是个string类型的迭代器)
(3)erase(first,last);删除从first到last之间的字符(first和last都是迭代器)

猜你喜欢

转载自blog.csdn.net/qq_29689907/article/details/80218665