挑战五天刷完剑指offer day4-1

字符串

前几天确实进度有些慢了,三天刷了30+,一半左右,希望能挑战成功。

1.字符串的排列

全排列问题,用回溯的方法。在之前知乎的文章中有详细介绍。方法基本是一模一样的,这里就是要去重和字典序排列,那么用set可以去重和排列。

class Solution {
public:
    set <string> res;
    //标记访问
    vector<bool> used;
    //回溯
    void backtrack(string &p, string str){
       //p的长度等于str
        if(p.size()==str.size()){
            res.insert(p);
            return;
        }
        for(int i=0;i<str.size();i++){
            if(!used[i]){
              //选择
                p.push_back(str[i]);
                used[i]=true;
                backtrack(p,str);
               //回撤
                p.pop_back();
                used[i]=false;
            }
        }
        return;
    }
    vector<string> Permutation(string str) {
        used=vector<bool>(str.size(),false);
        string p;
        vector<string> ret;
        if(str.size()==0)return ret;
        backtrack(p,str);
        for(auto &e:res)
            ret.push_back(e);
        return ret;
    }
};

2.翻转单词顺序列

思路一:先整体翻转,再确定每个单词的位置,单个儿翻转:

class Solution {
public:
    string ReverseSentence(string str) {
        string s;
        if(str.size()==0)return s;
        reverse(str.begin() , str.end());
        for(int i=0; i < str.size(); i++){
            int j=i;
            while (j< str.size() && str[j]!=' ')j++;
            reverse(str.begin()+i, str.begin()+j);
            //注意翻转完之后,需要i=j
            i=j;
        }
      return str;
    }
};

3.扑克牌顺子

这道题啰啰嗦嗦半天,我实在是没读懂……看了一下题解才明白……关键点就是五张牌的max-min<5;因为还有大小王,可以看做任何数,所以若差小于4,且无重复牌,说明摸到了大小王,可以当做顺子~

class Solution {
public:
    bool IsContinuous( vector<int> numbers ) {
        if (numbers.empty()) return false;
       int max1=0,min1=14;
       set<int> q;
        for(int c:numbers){
        //如果摸到大小王,则为0,继续,不管
          if(c>0){
            if(q.count(c)>0)return false;
            q.insert(c);
            max1=max(max1,c);
            min1=min(min1,c);
          }
      }
      return max1-min1<5;
    }
};

4.把字符串转换成整数

这道题需要考虑溢出的情况:

class Solution {
public:
    int StrToInt(string str) {
        int num = 0,i=0,flag=1;
        //去掉空格
        while(str[i]==' ')i++;
        //记录符号
        if(str[i]=='-'){flag=-1;i++;}
        else if(str[i]=='+'){flag=1;i++;}
        
        while(i<str.size()){
            if(isdigit(str[i])){
                num= num* 10 + (str[i]-'0');
                i++;
                //溢出考虑
                if(num > INT_MAX && flag==1) return INT_MAX;
                else if(num > INT_MAX && flag==-1) 
                return INT_MIN;
            }else{
                return 0;
                break;
            }
        }
        return num*flag;
    }
};

牛客上的题与之类似,但是有不太一样,如果出现字母就不再转:

class Solution {
public:
    int strToInt(string str) {
      int i=0;long res=0; int flag=1;
      while(str[i]==' ')i++;
      if(str[i]=='-')flag=-1;
      if(str[i]=='-' || str[i] == '+')i++;

      while(i<str.size() && isdigit(str[i])){
          res = res * 10 + (str[i] - '0');
          if(res > INT_MAX && flag == 1)return INT_MAX;
          else if(res > INT_MAX && flag == -1)return INT_MIN;
          i++;
      }
      return res*flag;
    }
};

5.字符流中第一个不重复的字符

队列,先进先出,hashmap记录次数:

class Solution
{
public:
    queue<char> q;
    unordered_map<char,int> map;
  //Insert one char from stringstream
    void Insert(char ch)
    {
        if (map[ch]==0) {
             q.push(ch);
         }
           map[ch]++;
    }
  //return the first appearence once char in current stringstream
    char FirstAppearingOnce()
    {
        while(!q.empty()){
            char ch = q.front();
            if(map[ch]==1)return ch;
            else q.pop();
        }
          return '#';
    }
   
};

6.表示数值的字符串

1.+、-只能出现在开头或者e之后
2.e前出现e是错误的,且之前之后都必须出现数字
3. .前不能出现.或者e
4.用几个标记记录出现与否

class Solution {
public:
    //1.+-只能出现在开头或者e之后
    //2.e前出现e是错误的,且之前之后都必须出现数字
    //3. .前不能出现.或者e
    bool isNumeric(char* string)
    {
        if(string == nullptr) return false;
        bool dot =false, e=false, num =false;
        for(int i=0; i<strlen(string); i++){
            if(string[i] == '.'){
                if(e==true || dot==true){
                    return false;
                }
                dot = true;
            }
            else if(string[i] == 'e'||  string[i] == 'E'){
                if(e==true || num==false){
                    return false;
                }
                e = true;
                //防止12e这种情况发生
                num = false;
            }
            else if(string[i] >= '0' && string[i] <= '9'){
                num = true;
            }
            else if(string[i] == '+' ||  string[i] == '-'){
               if(i!=0 && string[i-1] != 'e' 
                            && string[i-  1]!='E')
                  {
                    return false;
                }
            }
            else{
                return false;
            }
        }
        //最后一位一定是数字,并且肯定出现过数字
        return num;
    }
};

数字

7.字符流中第一个不重复的字符

在这里插入图片描述
按位与找到进位位、左移进位、按位异或、递归。

class Solution {
public:
    int Add(int num1, int num2)
    {
          int n1=(num1 & num2) <<1;
          int n2 = num1 ^ num2;
        return n1 == 0? n2 : Add(n1, n2);
    }
};

8.数据流中的中位数

两个堆:

class Solution {
public:
    int size=0;
    void Insert(int num)
    {
        size++;
     minp.push(num);
     maxp.push(minp.top());
     minp.pop();
      if(minp.size() < maxp.size()){
          minp.push(maxp.top());
          maxp.pop();
      }
    }

    double GetMedian()
    { if(size == 0) return -1;
      if(size%2==0) return (minp.top()+maxp.top())*0.5;
      else return minp.top();
    }
    priority_queue<int,vector<int>,greater<int>> minp;
    priority_queue<int,vector<int>,less<int>> maxp;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值