实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
链接:https://leetcode-cn.com/problems/implement-strstr
/*基本思想:最简单的就是对于needle来遍历haystack ,i指向haystack,j指向needle
找第一个字符相同的位置找到看后面的是否相同,不同则重新在之前找到的位置重找与needle[0]相同的位置,j从0开始,
相同就i,j同时++,继续比较
*/
class Solution {
public:
int strStr(string haystack, string needle) {
if(needle == "")
return 0;
if(haystack=="")
return -1;
if(needle == haystack)
return 0;
int i=0,j=0;
int index = -1;
while(i<haystack.size() && j<needle.size())
{
while(i<haystack.size() && haystack[i] != needle[j])
{
i++;
}
if(i==haystack.size() && j<needle.size())
return -1;
if(haystack[i] == needle[j] && j==0)
index = i;
if(i<haystack.size()-1 && j<needle.size()-1)
{
if(haystack[i+1] != needle[j+1])
{
int k=index+1;
while(k<haystack.size() && haystack[k] !=needle[0] )
{
k++;
}
i=k;
j =0;
continue;
}
}
i++;
j++;
}
if(j<needle.size())
return -1;
return index;
}
};
对于某些字符串 S,我们将执行一些替换操作,用新的字母组替换原有的字母组(不一定大小相同)。
每个替换操作具有 3 个参数:起始索引 i,源字 x 和目标字 y。规则是如果 x 从原始字符串 S 中的位置 i 开始,那么我们将用 y 替换出现的 x。如果没有,我们什么都不做。
举个例子,如果我们有 S = “abcd” 并且我们有一些替换操作 i = 2,x = “cd”,y = “ffff”,那么因为 “cd” 从原始字符串 S 中的位置 2 开始,我们将用 “ffff” 替换它。
再来看 S = “abcd” 上的另一个例子,如果我们有替换操作 i = 0,x = “ab”,y = “eee”,以及另一个替换操作 i = 2,x = “ec”,y = “ffff”,那么第二个操作将不执行任何操作,因为原始字符串中 S[2] = 'c',与 x[0] = 'e' 不匹配。
所有这些操作同时发生。保证在替换时不会有任何重叠: S = "abc", indexes = [0, 1], sources = ["ab","bc"] 不是有效的测试用例。
链接:https://leetcode-cn.com/problems/find-and-replace-in-string
/*基本思路:最先想到的暴力破解时间超限,所以可以使用映射,将要改变的下标作为map的key,source和target组合成pair作为value,
在S的长度范围内进行寻找,如果存在这个pair,则比较当前的索引对应得源是否和S一样,一样则用target,不一样就还是原来的S[i],找不到也是S[i]
*/
class Solution {
public:
string findReplaceString(string S, vector<int>& indexes, vector<string>& sources, vector<string>& targets) {
map<int,pair<string,string> > m;
pair<string, string> st;
int i;
string res="";
for(i=0;i<indexes.size();i++)
{
st=make_pair(sources[i],targets[i]);
m[indexes[i]]=st;
}
map<int,pair<string,string> >::iterator iter;
for(i=0;i<S.size();i++)
{
iter =m.find(i);
if(iter!=m.end())
{
string source = m[i].first;
string target = m[i].second;
if(S.substr(i,source.size() ) == source)
{
res+=target;
i+=source.size()-1;
}
else
res+=S[i];
}
else
res+=S[i];
}
return res;
}
};
给定两个以字符串形式表示的非负整数 num1
和 num2
,返回 num1
和 num2
的乘积,它们的乘积也表示为字符串形式。
链接:https://leetcode-cn.com/problems/multiply-strings/
/*基本思路:对应位置相乘保存到一个数组里面,然后对于数组中的数从后先前进行处理,除以10的余数就是该位的值,整数部分就是进位,前一个数要加上进位
可以按照列式子乘法计算方法理解
*/
class Solution {
public:
string multiply(string num1, string num2) {
if(num1=="" || num2=="")
return "";
if(num1=="0" || num2 == "0")
return "0";
int len = num1.size()+num2.size()-1;
int sum_v[len]={0};
int i,j;
for(i=0;i<num1.size();i++)
{
for(j=0;j<num2.size();j++)
{
sum_v[i+j] += (num1[i]-'0')*(num2[j]-'0'); //对应位置的乘数相乘
}
}
int rest = 0; //进位
for(i=len-1;i>0;i--)
{
sum_v[i]+=rest; //加上进位
rest = sum_v[i]/10;
sum_v[i] %= 10;
}
sum_v[0] += rest;
string result;
for(i=0;i<len;i++)
{
result += std::to_string(sum_v[i]); //转为字符串
}
return result;
}
};
给定一个仅包含大小写字母和空格 ' '
的字符串,返回其最后一个单词的长度。
如果不存在最后一个单词,请返回 0 。
链接:https://leetcode-cn.com/problems/length-of-last-word/
/*基本思路:找到最后一个空格的位置(rfind),然后最后一个单词就是len-position-1
注意:1.当s为空或者只有一个空格时,返回0
2.当最后一个空格在单词后面时,去除这个空格再调用该函数处理前面的字符串
可以先去除末尾的空格,然后再用此思想处理
*/
class Solution {
public:
/* int lengthOfLastWord(string s) {
int position=s.rfind (' ');
if(s==" "||s=="")
return 0;
if(position == s.size()-1)
return lengthOfLastWord(s.substr(0,position));
int len=s.size();
return len-position-1;
}*/
int lengthOfLastWord(string s) {
if(s.size()<1) return 0;
int len = s.size();
int num = 0;
int i = len-1;
while(i>=0&&s[i]==' ') i--;
while(i>=0&&s[i]!=' ')
{
num++;
i--;
}
return num;
}
};
给定两个二进制字符串,返回他们的和(用二进制表示)。
输入为非空字符串且只包含数字 1
和 0
。
链接:https://leetcode-cn.com/problems/add-binary/
/*基本思想:用异或模拟加法,然后用进位记录,逐位计算即可
*/
class Solution {
public:
string addBinary(string a, string b) {
int i = a.size()-1;
int j = b.size()-1;
string res="";
char rest='0';
while(i>=0&&j>=0)
{
res += std::to_string((a[i]-'0')^(b[j]-'0')^(rest-'0'));
if((a[i]=='1' && b[j]=='1' )||(a[i]=='1' && rest=='1')||(b[j]=='1' && rest=='1'))
rest = '1';
else
rest = '0';
cout<<res<<endl;
i--;
j--;
}
while(i>=0)
{
res += std::to_string((a[i]-'0')^(rest-'0'));
if(a[i]=='1' && rest=='1')
rest = '1';
else
rest = '0';
i--;
}
while(j>=0)
{
res += std::to_string((b[j]-'0')^(rest-'0'));
if(b[j]=='1' && rest=='1')
rest = '1';
else
rest = '0';
j--;
}
if(rest=='1')
res+=rest;
reverse(res.begin(),res.end());
return res;
}
};
验证给定的字符串是否可以解释为十进制数字。
链接:https://leetcode-cn.com/problems/valid-number/
/*基本思想:一次遍历,首先去掉首尾空格,然后每个符号开始判断,首先判断开始的+-符号,之后继续判断是数字或者是.并且统计数字和.的个数,数字个数不能为0,.的个数不能大于1个否则返回false
碰到不是数字或者. 如果是e,继续判断之后可以是+-,e后面必须要有数字所以然后判断后面是否有数字,没有返回false,遍历到最后可以到最后一位返回true
*/
class Solution {
public:
bool isNumber(string s) {
int i = 0;
//去掉首尾的空格
if( !s.empty() )
{
s.erase(0,s.find_first_not_of(" "));
s.erase(s.find_last_not_of(" ") + 1);
}
// check the significand
if(s[i] == '+' || s[i] == '-') i++; // skip the sign if exist
int count=0, point=0;
for(; (s[i]<='9' && s[i]>='0') || s[i]=='.'; i++)
s[i] == '.' ? point++:count++;
if(point>1 || count<1) // 遍历必须有数字,点的数量不能超过1个
return false;
// check the exponent if exist
if(s[i] == 'e') {
i++;
if(s[i] == '+' || s[i] == '-') i++; // e后面一位可以是+-符号
int count= 0;
for(; s[i]>='0' && s[i]<='9'; i++, count++) {} //e后面必须有数字
if(count<1)
return false;
}
return i==s.size(); // 最后可以遍历到最后一位返回true
}
};
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
链接:https://leetcode-cn.com/problems/group-anagrams/
/*基本思想:用map来统计每个字符串出现的字符,然后比较一样的放入一个vector
*/
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
vector<map<char,int>> v;
int i,j,k;
vector<vector<string>> s;
vector<string> cur_s;
map<char,int> m;
for(j=0;j<strs[0].size();j++)
{
if(m.find(strs[0][j])!=m.end())
{
m[strs[0][j]]++;
}
else
m[strs[0][j]] = 1;
}
cur_s.push_back(strs[0]);
s.push_back(cur_s);
v.push_back(m);
cur_s.clear();
for(i=1;i<strs.size();i++)
{
int flag=0;
map<char,int> m; //记录每个字符串的map
for(j=0;j<strs[i].size();j++)
{
if(m.find(strs[i][j])!=m.end())
{
m[strs[i][j]]++;
}
else
m[strs[i][j]] = 1;
}
for(k=0;k<v.size();k++) //和前面放入v的字符串比较一样的合并成一个vector 存储在s[k]
{
if(m==v[k])
{
s[k].push_back(strs[i]);
flag=1;
break;
}
}
if(flag==0)
{
cur_s.clear(); //没有和前面一样的就自成一个vector,然后放入s,也要将他的m放入v
v.push_back(m);
cur_s.push_back(strs[i]);
s.push_back(cur_s);
}
}
return s;
}
};
报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数
链接:https://leetcode-cn.com/problems/count-and-say/
/*基本思想:先令s=1开始,用pair统计连续相同的数字出现的次数,然后生成新的s,循环n-1
*/
class Solution {
public:
string countAndSay(int n) {
vector<pair<char, int>> word_count;
string res;
int i;
vector<pair<char,int> > ::iterator iter = word_count.begin();
string s = "1";
while(n>1){
int k=0;
word_count.clear();
word_count.push_back(make_pair(s[0],1));
res.clear();
for(i=1;i<s.size();i++)
{
if(s[i] == s[i-1])
word_count[k].second ++;
else
{
word_count.push_back(make_pair(s[i],1));
k++;
}
}
for(iter=word_count.begin();iter!=word_count.end();iter++)
{
res.push_back((*iter).second+'0');
res.push_back((*iter).first);
}
s = res;
n--;
}
return s;
}
};
罗马数字包含以下七种字符: I
, V
, X
, L
,C
,D
和 M
链接:
https://leetcode-cn.com/problems/roman-to-integer/
/*基本思想:简单的逻辑,主要是特殊6个特殊数字的处理,也可以用一个map映射,代码简单,对于特殊数字,就是值后面减去前面
*/
class Solution {
public:
int romanToInt(string s) {
int i;
int res=0;
for(i=0;i<s.size();i++)
{
int cur=0;
if(s[i]=='I')
{
if(s[i+1]=='V'&& i+1<s.size())
{
res = res+4;
i++;
continue;
}
else if(s[i+1]=='X'&& i+1<s.size())
{
res = res+9;
i++;
continue;
}
else
cur = 1;
}
if(s[i]=='X')
{
if(s[i+1]=='L'&& i+1<s.size())
{ res = res+40;
i++;
continue;
}
else if(s[i+1]=='C'&& i+1<s.size())
{
res = res+90;
i++;
continue;
}
else
cur = 10;
}
if(s[i]=='C')
{
if(s[i+1]=='D' && i+1<s.size())
{ res = res+400;
i++;
continue;
}
else if(s[i+1]=='M'&& i+1<s.size())
{
res = res+900;
i++;
continue;
}
else
cur = 100;
}
if(s[i]=='V')
cur=5;
if(s[i]=='L')
cur=50;
if(s[i]=='D')
cur=500;
if(s[i]=='M')
cur=1000;
res = res+cur;
}
return res;
}
};
请将给出的整数转化为罗马数字
保证输入数字的范围在1 到 3999之间。
链接:https://leetcode-cn.com/problems/integer-to-roman/
/*基本思想:对应数据找就好了,代码更简洁点就是用一个映射把数字和字母映射起来*/
class Solution {
public:
string intToRoman(int num) {
string res="";
while(num!=0)
{
if(num>=1 && num<5)
{
if(num>=4)
{
res+="IV";
num-=4;
}
else
{
res+="I";
num-=1;
}
continue;
}
if(num>=5 && num<10)
{
if(num>=9)
{
res+="IX";
num-=9;
}
else{
res+="V";
num-=5;
}
continue;
}
if(num>=10 && num<50)
{
if(num>=40)
{
res+="XL";
num-=40;
}
else
{
res+="X";
num-=10;
}
continue;
}
if(num>=50 && num<100)
{
if(num>=90)
{
num-=90;
res+="XC";
}
else
{
res+="L";
num-=50;
}
continue;
}
if(num>=100 && num<500)
{
if(num>=400){
res+="CD";
num-=400;
}
else
{
res+="C";
num-=100;
}
continue;
}
if(num>=500 && num<1000)
{
if(num>=900){
res+="CM";
num-=900;
}
else{
res+="D";
num-=500;
}
continue;
}
else
{
num-=1000;
res+="M";
continue;
}
}
return res;
}
};
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
链接:https://leetcode-cn.com/problems/zigzag-conversion/
/*
基本思想:分组假如有4行,则6个一组,统计一共有多少组,就能确定一共有多少列,然后将s分割成4,2,4,2的形式,然后进行读取存储
*/
class Solution {
public:
string convert(string s, int numRows) {
int len = s.size();
if(s.size()<=numRows || s=="" || numRows==1)
return s;
string res;
if(numRows>2){
int col =len /(2*numRows-2) + (len % (2*numRows-2)) %4 +1; //统计分了多少组
vector<vector<char>> vs;
int i,j;
int k=0;
int curindex = 0;
cout<<"l"<<len<<endl;
cout<<"col"<<col<<endl;
for(i=0;i<2*col+1;i++)
{
cout<<i<<endl;
if(i%2==0)
{
vector<char> curs;
for(j=curindex;j<numRows;j++)
{
//cout<<"==0"<<s[k]<<endl;
if(k>=s.size())
curs.push_back(' ');
else
curs.push_back(s[k++]);
}
vs.push_back(curs);
}
else
{
vector<char> curs;
for(j=curindex;j<numRows-2;j++)
{
//cout<<"!=0"<<s[k]<<endl;
if(k>=s.size())
curs.push_back(' ');
else
curs.push_back(s[k++]);
}
vs.push_back(curs);
}
}
for(i=0;i<vs.size();i++)
{
if(i%2==0 && vs[i][0]!=' ')
{
res.push_back(vs[i][0]);
vs[i].erase(vs[i].begin( ));
}
}
// cout<<res;
int n=numRows-1;
while(n>0){
//cout<<"n"<<endl;
for(i=0;i<vs.size();i++)
{
//cout<<"s"<<vs.size()<<endl;
// cout<<"vs[i]"<<vs[i].size()<<endl;
if(vs[i].size()==0)
continue;
else{
if(i%2==0 )
{
if(vs[i][0]==' ')
{
vs[i].erase(vs[i].begin( ));
}
else{
res.push_back(vs[i][0]);
vs[i].erase(vs[i].begin( ));
}
}
else
{
if(vs[i][vs[i].size()-1]==' ' )
{
vs[i].pop_back();
}
else
{
res.push_back(vs[i][vs[i].size()-1]);
vs[i].pop_back();
}
}
}
}
n--;
}
}
else
{
int i=0;
for(i=0;i<s.size();i++)
{
if(i%2==0)
res.push_back(s[i]);
}
for(i=0;i<s.size();i++)
{
if(i%2!=0)
res.push_back(s[i]);
}
}
return res;
}
};
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/
/*基本思想:利用两个指针i和j,i负责向前移动,j负责从i-1开始向前找第一个重复的位置,重复,则更新结果字符串的起始位置也就是index,标记重复,否则不重复字符串长度数量+1
*/
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int i,j,index=0;
if(s=="")
return 0;
int dp[s.size()];
dp[0]=1;
int flag=0;
for(i=1;i<s.size();i++)
{
flag=0;
for(j=i-1;j>=index;j--)
{
if(s[j]==s[i])
{
//cout<<"=="<<endl;
dp[i] = dp[i-1]-(j-index+1)+1; //找到重复的位置之后先减去重复的位置距离其实的位置长度,然后加上1(i的字符)
index = j+1;
flag=1;
break;
}
}
if(!flag)
dp[i]=dp[i-1]+1;
cout<<dp[i]<<endl;
}
return (*max_element(dp, dp+s.size()));
}
};
请你来实现一个 atoi
函数,使其能将字符串转换成整数。
链接:https://leetcode-cn.com/problems/string-to-integer-atoi/
/*基本思想:注意处理开始的空格和溢出判断即可
*/
class Solution {
public:
int myAtoi(string str) {
int sign = 1;
int i=0;
long res = 0;
long result = 0;
int n = str.size();
if(n == 0)
return 0;
//考虑前面的空格
while(i < n && str[i] == ' ') {
i++;
}
//判断第一个不为空的符号
if(i==n || (str[i]!='+' && str[i]!='-' && str[i]<'0' && str[i]>'9'))
return 0;
if(str[i]=='+')
i++;
else if(str[i] == '-')
{
sign = -1;
i++;
}
for(;i<n;i++)
{
// cout<<str[i]<<endl;
if(str[i]>='0'&& str[i]<='9')
{
result = result*10 + (str[i]-'0');
res = sign*result;
if(res>=INT_MAX)
return INT_MAX;
if(res <= INT_MIN)
return INT_MIN;
}
else
break;
}
return res;
}
};
给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。
链接:https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words
/*基本思想:用i遍历s的每一个位置,满足条件作为结果
用j遍历每一个单词进行判断,words中的单词个数为word_size
words中的每个单词的长度为len
判断条件: 首先记录words中每个单词出现的次数word_count,然后i遍历s的时候,每次在s中截取以i为开始len长度的字符串,如果没有在word_count中出现,说明没有匹配,找下一个起始位置。如果在word_count中出现,则保存在word_cur中也是记录出现次数。如果次数大于之前统计的次数,说明匹配不成功,否则,继续寻找下一个len长度的str重复(下一个str的起始位置由i和j一起控制),直到找到word_size个单词满足即为结果。
*/
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
map<string,int> word_count; //存储每个单词的次数
vector<int> res_index;
if(words.size()==0)
return res_index;
for(string word: words)
word_count[word]++;
int s_len = s.size();
int word_size = words.size();
int word_len = words[0].size();
//用i记录起始位置
for(int i=0; i<s_len-word_size*word_len+1; i++)
{
map<string,int> word_cur; //存储i为起点的字符串里指定单词的次数
int j=0;
//用j遍历words里面的单词,只有当j==word_size时,才找到了所有单词
for(; j<word_size; j++)
{
string curstr = s.substr(i+j*word_len, word_len);//以i为起点,长度为len的第j个单词
if(word_count.find(curstr) != word_count.end())
{
word_cur[curstr]++;
if(word_cur[curstr] > word_count[curstr]) //如果此单词出现次数超出,则i位置不合法
break;
}
else
break; //如果此单词不存在于word_count里,i位置不合法
}
if(j==word_size)
res_index.push_back(i);//i==word_size,则i是合法位置之一
}
return res_index;
}
};