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类提供了以下几种和查找相关的成员函数
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都是迭代器)