剑指offer刷题——字符串

剑指Offer(二):替换空格

题目

请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

1、思路

最简单的方法就是从头到尾遍历,但是时间复杂度为O(n^2)。

本文采用一种时间复杂度为O(n)的方法。

我们可以先遍历一次字符串,这样就可以统计出字符串空格的总数,并可以由此计算出替换之后的字符串的总长度。每替换一个空格,长度增加2,因此替换以后字符串的长度等于原来的长度加上2乘以空格数目。以"We are happy"为例,"We are happy"这个字符串的长度为14(包括结尾符号"\n"),里面有两个空格,因此替换之后字符串的长度是18。

我们从字符串的尾部开始复制和替换。首先准备两个指针,P1和P2,P1指向原始字符串的末尾,而P2指向替换之后的字符串的末尾。接下来我们向前移动指针P1,逐个把它指向的字符复制到P2指向的位置,直到碰到第一个空格为止。碰到第一个空格之后,把P1向前移动1格,在P2之前插入字符串"%20"。由于"%20"的长度为3,同时也要把P2向前移动3格。

移动示意图:

剑指Offer(二):替换空格

2、编程实现

C++:

 

class Solution {
public:
	void replaceSpace(char *str,int length) {
		if(str == NULL || length <= 0){
            return;
        }
        /*original_length为字符串str的实际长度*/
        int original_length = 0;			//原始长度
        int number_blank = 0;				//空格数
        int i;
        while(str[i++] != '\0'){				//遍历字符串
            ++original_length;				//长度+1
            if(str[i] == ' '){
                ++number_blank;				//遇到空格+1
            }
        }
        /*new_length为把空格替换成'%20'之后的长度*/
        int new_length = original_length + 2 * number_blank;
        
        int index_original = original_length-1;	//原始字符串末尾索引值
        int index_new = new_length-1;				//计算长度后的字符串末尾索引值
        
        /*index_original指针开始向前移动,如果遇到空格,替换成'%20',否则进行复制操作*/
        while(index_original >= 0 && index_new > index_original){
            if(str[index_original] == ' '){
                str[index_new--] = '0';
                str[index_new--] = '2';
                str[index_new--] = '%';
            }
            else{
                str[index_new--] = str[index_original];
            }
            --index_original;
        }
	}
};

剑指Offer(二十七):字符串的排列 

题目

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

输入描述:

输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

1、思路

我们求整个字符串的排列,可以看成两步:首先求所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符交换。如下图所示:

剑指Offer(二十七):字符串的排列

上图就是分别把第一个字符a和后面的b、c等字符交换的情形。首先固定第一个字符,求后面所有字符的排列。这个时候我们仍把后面的所有字符分为两部分:后面的字符的第一个字符,以及这个字符之后的所有字符。然后把第一个字符逐一和它后面的字符交换。

这个思路,是典型的递归思路。

2、代码

C++:

class Solution {
public:
    vector<string> Permutation(string str) {
        //判断输入
        if(str.length() == 0){
            return result;
        }
        PermutationCore(str, 0);
        //对结果进行排序
        sort(result.begin(), result.end());
        return result;
    }
    
private:
    void PermutationCore(string str, int begin){
        //递归结束的条件:第一位和最后一位交换完成
        if(begin == str.length()){
            result.push_back(str);
            return;
        }
        for(int i = begin; i < str.length(); i++){
            //如果字符串相同,则不交换
            if(i != begin && str[i] == str[begin]){
                continue;
            }
            //位置交换
            swap(str[begin], str[i]);
            //递归调用,前面begin+1的位置不变,后面的字符串全排列
            PermutationCore(str, begin + 1);
        }
    }
    vector<string> result;
};

 剑指Offer(三十四):第一个只出现一次的字符

题目

在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置。

1、思路

建立一个哈希表,第一次扫描的时候,统计每个字符的出现次数。第二次扫描的时候,如果该字符出现的次数为1,则返回这个字符的位置。

2、代码

C++:

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        int length = str.size();
        if(length == 0){
            return -1;
        }
        map<char, int> item;
        for(int i = 0; i < length; i++){
            item[str[i]]++;
        }
        for(int i = 0; i < length; i++){
            if(item[str[i]] == 1){
                return i;
            }
        }
        return -1;
    }
};

 剑指Offer(四十四):翻转单词顺序序列

题目

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

1、思路

观察字符串变化规律,你会发现这道题很简单。只需要对每个单词做翻转,然后再整体做翻转就得到了正确的结果。

2、代码

C++:

class Solution {
public:
    string ReverseSentence(string str) {
        string result = str;
        int length = result.size();
        if(length == 0){
            return "";
        }
        // 追加一个空格,作为反转标志位
        result += ' ';
        int mark = 0;
        // 根据空格,反转所有单词
        for(int i = 0; i < length + 1; i++){
            if(result[i] == ' '){
                Reverse(result, mark, i - 1);
                mark = i + 1;
            }
        }
        // 去掉添加的空格
        result = result.substr(0, length);
        // 整体反转
        Reverse(result, 0, length - 1);
        
        return result;
    }
private:
    void Reverse(string &str, int begin, int end){
        while(begin < end){
            swap(str[begin++], str[end--]);
        }
    }
};

稍微改动一下

class Solution {
public:
    string ReverseSentence(string str) {
        string result=str;
        int length = result.size();
        if(length<=0){
            return "";
        }
        int mark = 0;
        Reverse(result,0,length-1);
        for(int i=0;i<length+1;i++){
            if(result[i]==' '||result[i] == '\0'){
                Reverse(result,mark,i-1);
                mark = i+1;
            }
        }
        return result;
    }
private:
    void Reverse(string &str,int start,int end){
        while(start<end){
            swap(str[start++],str[end--]);
        }
    }
};

剑指Offer(四十三):左旋转字符串

题目

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

1、思路

例如:输入字符串"abcdefg"和数字2,该函数将返回左旋转2位得到的结果"cdefgab";

 

第一步:翻转字符串“ab”,得到"ba";

第二步:翻转字符串"cdefg",得到"gfedc";

第三步:翻转字符串"bagfedc",得到"cdefgab";

或者:

第一步:翻转整个字符串"abcdefg",得到"gfedcba"

第二步:翻转字符串“gfedc”,得到"cdefg"

第三步:翻转字符串"ba",得到"ab"

2、代码

C++:

class Solution {
public:
    string LeftRotateString(string str, int n) {
        string result = str;
        int length = result.size();
        if(length < 0){
            return NULL;
        }
        if(0 <= n <= length){
            int pFirstBegin = 0, pFirstEnd = n - 1;
            int pSecondBegin = n, pSecondEnd = length - 1;
            ReverseString(result, pFirstBegin, pFirstEnd);
            ReverseString(result, pSecondBegin, pSecondEnd);
            ReverseString(result, pFirstBegin, pSecondEnd);
        }
        return result;
    }
private:
    void ReverseString(string &str, int begin, int end){
        while(begin < end){
            swap(str[begin++], str[end--]);
        }
    }
};

答案来自 :https://blog.csdn.net/c406495762/article/details/79247243

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值