2020/12/12-----剑指offer刷题

剑指offer

左旋转字符串

题目描述

汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!

解题思路

解法1:使用标准库string::substr(size_type __pos, size_type __n)string::substr(pos, n)表示截取字符串string,从pos下标开始,长度为n的子串。
比如:str = "helloworld", 那么str.substr(2,3)等于"llo"
解法2:遍历数组,利用辅助字符串
解法3:后面补上相同的字符串str;

class Solution {
public:
    string LeftRotateString(string str, int n) {
       /* if(n>str.size()) return str;
        string ret="";
        for(int i=n;i<str.size();i++){
            ret+=str[i];
        }
        for(int i=0;i<n;i++){
            ret+=str[i];
        }
        return ret;*/
        //return n>str.size()?str:str.substr(n,str.size()-n)+str.substr(0,n);
        //*str+str;
        int len=str.length();
        if(len==0) return "";
        str=str+str;
        return str.substr(n,len);
    }
};

反转单词序列

题目描述

牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
在这里插入图片描述

解题思路

解法1:先翻转整个字符串,再反转单词;注意空格
解法2:使用stringstream库函数
解法3:从后往后遍历,部分截取最后加上空格;

//使用stringstream函数,时间复杂度O(n),空间复杂度O(n);
class Solution {
public:
    string ReverseSentence(string str) {
        // 预处理
        if (str.empty()) return str;
        int i = 0, sz = str.size();
        while(i < sz && str[i] == ' ') ++i;
        if (i == sz) return str;
        istringstream ss(str);
        vector<string> ret;
        string s;
        // 拆分单词
        while (ss >> s)  
            ret.push_back(s);
        reverse(ret.begin(), ret.end());
        ostringstream oss;
        // 合并成字符串
        for (int i=0; i<ret.size()-1; ++i) 
            oss << ret[i] << ' ';
        oss << ret.back();
        return oss.str();
    }
};
//解法3:时间复杂度为O(n),空间复杂度O(n);
class Solution {
public:
    string ReverseSentence(string str) {
        if(str.empty()) return "";
        int cnt=0,sz=str.size();
        while(cnt<sz&&str[cnt]==' ') cnt++;
        if(cnt==sz) return str;
        string res="";
        int right=str.size()-1;
        int left=right;
        while(left>=0){
            while(left>=0&&str[left]==' '){
                left--;
                right=left;
            }
            while(left>=0&&str[left]!=' '){
                left--;
            }
            if(left!=right){
                res+=str.substr(left+1,right-left)+" ";
            }
        }
        //除去最后的空格
        if(!res.empty()){
            res.pop_back();
        }
        return res;
    }
};

1+2+3+…+n

题目描述
在这里插入图片描述
解题思路:

利用短路原理:a&&b,a为0,不会执行b, a||b;a为1不会执行b

代码实现

class Solution {
public:
    int Sum_Solution(int n) {
      int sum=n;;
      sum&&(sum+=Sum_Solution(n-1));
      return sum;
    }
};

不用加减乘除法做加法

题目描述:

这里是引用

解题思路:
在这里插入图片描述

class Solution {
public:
    int Add(int num1, int num2)
    {
        int result=0;
        int carry=0;
        do{
            result=num1^num2;//不带进位的加法
            carry=(num1&num2)<<1;//进位
            num1=result;
            num2=carry;
        }while(carry!=0);//进位不为0则继续执行加法处理进位;
        return result;
    }
};

把字符串转换成整数

解题思路

先判断第一位是正号还是负号;然后利用isdigit()判断是否是数字。
对于“123456”可以利用如下代码进行转化

int ans = 0;
for (int i=0; i<str.size(); ++i) {
    ans = ans * 10 + (str[i] - '0');
}

代码实现:

class Solution {
public:
    int StrToInt(string str) {
     int flag=1,i=0;
        long res=0;
        if(str[i]=='-') flag=-1;
        if(str[i]=='+'||str[i]=='-') i++;
        for(;i<str.size();i++){
            if(!isdigit(str[i])) return 0;
               res=res*10+(str[i]-'0');
        }
        return flag*res;
    }
};

删除链表中重复的节点

题目描述
在这里插入图片描述

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        //设置虚拟头节点,
        ListNode *vhead=new ListNode(-1);
        vhead->next=pHead;
        //cur用于遍历链表,pre用于指向没有重复的链表
        ListNode *cur=pHead;
        ListNode *pre=vhead;
        while(cur){
            if(cur->next&&cur->val==cur->next->val){
                cur=cur->next;
                //找到最后一个相同的节点
                while(cur->next&&cur->val==cur->next->val){
                   cur=cur->next; 
                }
                //最后一个相同的节点向后移动一位
                cur=cur->next;
                pre->next=cur;
            }else{
                    pre=cur;
                    cur=cur->next;
                }
        }
        return vhead->next;
    }
};

二叉树的下一个结点

题目描述:

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

代码实现:

/*
struct TreeLinkNode {
    int val;
    struct TreeLinkNode *left;
    struct TreeLinkNode *right;
    struct TreeLinkNode *next;
    TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
        
    }
};
*/
class Solution {
public:
    //树的中序遍历
    void min_order(TreeLinkNode *root,queue<TreeLinkNode*>&que){
        if(!root){
            return ;
        }
        min_order(root->left,que);
        que.push(root);
        min_order(root->right,que);
    }

    TreeLinkNode* GetNext(TreeLinkNode* pNode)
    {    
        if(pNode==nullptr) return nullptr;
        TreeLinkNode *root=pNode;
        while(root->next){
            root=root->next;
        }
        queue<TreeLinkNode *>que;
        min_order(root,que);
        while(que.front()!=pNode){
            que.pop();
        }
        que.pop();
        if(que.empty()) return nullptr;
        return que.front();
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值