剑指offer2刷题(字符串类)

6 篇文章 0 订阅
本文记录了一位程序员在刷《剑指Offer2》中关于字符串类题目的学习过程,强调了专项练习的重要性,从数据结构和算法两个角度对题目进行分类。分享了对C++中std::string函数的总结,包括初始化、赋值、类型转换、查找、切割和插入等,并提供了部分题目的解题思路,如替换空格、最长不含重复字符的子字符串等。此外,还提及了使用栈解决删除字符串相邻重复项的方法以及复原IP地址的难题。
摘要由CSDN通过智能技术生成

总结教训:之前刷题太过于随机,今后专项练习;首先为了熟练掌握基本函数,先按照数据结构进行分 类刷题;每一类刷上四五道并对函数进行总结;之后的话在按照算法进行分类刷题。
此次刷题来自剑指offer2的简单中等题。

一、字符串类

1、string函数总结(遇到一个总结一个)

链接: std::basic_string
一定要熟悉这些基本函数的返回值的类型和内容(以下内容有些没有测试)

#include<string>   //string 和string.h  是不同的,后者是C语言
//初始化
string s="abc";

//赋值函数
s.assign("word");

int a = s.length(); //不包括 '\0';
//类型转换
atoi(str.c_str());//atoi()用来转换char型到int,c_str()把string	转换成char
stoi(str);//string->int;
stof(str);//string->float;

//切割
string str = s.substr(0,2);//切割字符串  s[0]~s[0+2],第二个参数默认值为字符串结束(size())

//查找
string::size_type pos =find("rl");	
//若有返回值为第一次查找到该字符的位置,若没有返回 string的公开静态成员常量npos;
pos =find_first_of("rl");
//find与find_first_of的区别是,find要求查找的字符串完全符合,后者只需要字符串中有个一字符能找到就可以
//rfind是从后往前找,find_last_of亦然。

//插入
s.insert(pos,"666");
#include<string>
#include<iostream>
using namespace std;

template<typename T>
static string strJoin( const string &delim,const T&vec) {
	ostringstream s;
	for (const auto& i : vec) {
		if (&i != &vec[0]) {
			s << delim;
		}
		s << i;
	}
	return s.str();
}
// vector->string
template<typename T>
static string getVectorString(vector<T>&list) {
	return"[" + strJoin(",", list) + "]";
}

2、题目列表

剑指 Offer 05. 替换空格

在这里插入图片描述
//偷懒解法,使用了find()和insert()两个函数

class Solution {
public:
    string replaceSpace(string s) {
        while( s.find(' ') != string::npos){
            int a=s.find(' ');
            s[a]='%';
            s.insert(a+1,"20");
        }
        return s;
    }
};

//手写遍历,另外还有双指针法。简单记一下;

class Solution {
public:
    string replaceSpace(string s) {
        int count = 0, len = s.size();
        // 统计空格数量
        for (char c : s) {
            if (c == ' ') count++;
        }
        // 修改 s 长度
        s.resize(len + 2 * count);
        // 倒序遍历修改
        for(int i = len - 1, j = s.size() - 1; i < j; i--, j--) {
            if (s[i] != ' ')
                s[j] = s[i];
            else {
                s[j - 2] = '%';
                s[j - 1] = '2';
                s[j] = '0';
                j -= 2;
            }
        }
        return s;
    }
};

作者:jyd
链接:https://leetcode.cn/problems/ti-huan-kong-ge-lcof/solution/mian-shi-ti-05-ti-huan-kong-ge-ji-jian-qing-xi-tu-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

剑指 Offer 48. 最长不含重复字符的子字符串

请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

循环暴力解法:使用了find函数,两层循环。(这应该是双指针吧,外层是左,内层是右)
第一层循环是temp的起始位置,第二层循环就是判断后续每个字符是否存在于temp中,
存在的话就终止该层循环,进行temp和ans的比较,不存在的话就将当前字符插入到temp末尾。
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        string ans;
        string temp;
        if(s.size()==0) return 0;
        for(int i=0;i<s.size();i++){
            for(int j=i;j<s.size();j++){
                if(temp.size()!=0 && temp.find(s[j])!=string::npos) break;
                else temp.push_back(s[j]);
            }
            if(temp.size()>ans.size()) ans=temp;
            temp.clear();
        }
        return ans.size();
    }
};
上述解法时间复杂度高,还有双指针/动态规划+哈希表的方法,这里给出双指针+哈希表;
时间复杂度降低,空间复杂度更高,
与上个解法不同的是,这里只需要清除重复项set.erase(s[i]);  不用clear()完了重新插入。
关于set、map等哈希表内容以后再详细了解。
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_set<char>set;
        int j = 0;
        int res = 0;
        //外层循环是左指针,内层循环是右指针。
        for (int i = 0; i < s.size(); i++){
            while(j < s.size() && set.find(s[j]) == set.end()){
                set.insert(s[j]);//没有找到就插入
                res = max(res, j - i + 1);
                j++;
            }
            set.erase(s[i]);
        }
        return res;
    }
};

1047. 删除字符串中的所有相邻重复项

之前做过的题(简单)
简单一个栈就可以解决。
在这里插入图片描述

例子:
输入"abbbccdddca"  输出  aa;  连续三个及以上的字符消除,不断循环,直至没有连续三个以上。
//好好学习下!!! 竟然如此简单,自己想了半天还是只能解决一部分问题。
void del(string& s){
    int i = 0, j = 0;
    while (i < s.size()) {
        j = i;//j为数组坐标  j到i的距离就是重复的个数
        while (j < s.size() && s[j] == s[i]){
            j++;
        }
        if (j - i >= 3){
            s.erase(i, j - i);//消除重复的
            i = i - 2;//回退2个,如1122221,1222211//最多回退两个就可以,因为三个就会消除
            if (i < 0)
                i = 0;
        }
        else
            i++;
    }  
}

93.复原IP地址

之前做过的题(较难)
会用到 DFS/递归 ,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值