LeetCode算法打卡--字符串

28. 实现 strStr()

实现 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;
    }
};

833. 字符串中的查找与替换

对于某些字符串 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;
    }
};

43. 字符串相乘

给定两个以字符串形式表示的非负整数 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;
    }
};

58. 最后一个单词的长度

给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度。

如果不存在最后一个单词,请返回 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;
   }
};

67. 二进制求和

给定两个二进制字符串,返回他们的和(用二进制表示)。

输入为非空字符串且只包含数字 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;
    
    }
};

65. 有效数字

验证给定的字符串是否可以解释为十进制数字。

链接: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


    }
};

49. 字母异位词分组

给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

链接: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;
    }
    
    
};

38. 报数

报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数

链接: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;
    }
};

13. 罗马数字转整数

罗马数字包含以下七种字符: I, V, X, LCD 和 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;   
    }
       
   
};

12. 整数转罗马数字

请将给出的整数转化为罗马数字

保证输入数字的范围在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;
    }
};

 

6. Z 字形变换

将一个给定字符串根据给定的行数,以从上往下、从左到右进行 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;  
    }
};

3. 无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

链接: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()));
    }
};

8. 字符串转换整数 (atoi)

请你来实现一个 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;
        
        
    }
};

30. 串联所有单词的子串

给定一个字符串 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;
    }
};


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值