【字符串】相关类型题目整理[一]

本文探讨了剑指offer中的字符串处理问题,包括如何用最少操作替换空格,寻找最长无重复字符子串,以及计算最长回文串的长度。通过滑动窗口、哈希表和贪心策略,深入解析算法实现和技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、剑指offer 05. 替换空格

在这里插入图片描述

(一)原字符串进行修改

  • 思路:先计算出该字符串中有多少个空格,然后将字符串的空间调整为替换后的大小,然后再从字符串的最后进行移动,从最后进行移动的原因是将会花费更少次数的元素拷贝过程,提高效率

如下图所示:

在这里插入图片描述

代码如下所示:

class Solution 
{
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param s string字符串 
     * @return string字符串
     */
    string replaceSpace(string s) 
    {
        // write code here
        //先计算空格的个数
        int count=0;
        int n=s.length();
        for(int i=0;i<n;i++)
        {
            if(s[i]==' ')
            {
                count++;
            }
        }
        //重新调整s的大小
        s.resize(count*2+n);
        for(int i=n-1,j=s.size()-1;i<j;i--,j--)
        {
            if(s[i]!=' ')
            {
                s[j]=s[i];
            }
            else
            {
                s[j--]='0';
                s[j--]='2';
                s[j]='%';
            }
        }
        return s;
    }
};

二、剑指offer 48.最长不含重复字符串的子字符串

  • 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。

在这里插入图片描述

(一)滑动窗口

思路:

  • 先判断当前字符在当前子串中出现了没;
  • 如果没有出现则继续判断下一个字符;
  • 如果出现了则要判断当前子串的长度与最大子串长度哪个大;max取较大的一个数值
  • 然后删除掉从0到当前字符(包含当前字符)之间的元素;
  • 再将当前字符添加到当前子串中
  • 再最后遍历完成之后还需要再判断一次max

代码如下:

class Solution 
{
public:
    int lengthOfLongestSubstring(string s) 
    {
        int max=0;//统计子串的最大长度
        int n=s.size();
        int t;//保存当前字符在子串中出现的位置
        string str="";//当前子串
        for(int i=0;i<n;i++)
        {
            t=str.find(s[i]);//查找当前字符在子串中的位置
            if(t!=-1)//该字符在当前子串中存在
            {
                if(max<str.size())//判断子串的长度与之前记录的长度哪个值更大,取大的值
                {
                    max=str.size();
                }
                str.erase(0,t+1);//然后将当前子串清空
            }
            str+=s[i];//子串从当前字符开始重新统计
        }
        if(max<str.size())//最终还得给max的值做一次比较;
        {
            max=str.size();
        }
        return max;
    }
};

三、力扣409. 最长回文串

在这里插入图片描述

(一)统计每个字符出现的次数,遇到次数为奇数的在最终结果里减一并且进行奇数变量标记

思路:由于我们只需要统计最长的回文串的长度,所以我们可以将该题转化成统计每个字符出现的次数。
回文串的长度有两种情况:

  • 回文串中的每个字符都出现了偶数次
  • 回文串中只有一个字符出现了奇数次,别的字符都出现了偶数次

所以解决本道题,我们只需要借助一个哈希表来记录字符串中的每个字符出现的次数,一遍遍历完成之后,开始遍历哈希表的value值,从一开始遍历就将value的值加到返回的结果中,如果是偶数则继续遍历,如果是奇数就将返回的结果减一;最后不要忘了如果出现过奇数次数的字符,要将返回的结果加1.

代码如下:

class Solution 
{
public:
    int longestPalindrome(string s)
     {
        int ans=0;//返回最长回文子串的长度
        int odd=0;//判断有没有字符出现次数为奇数,0表示没有,1表示有
        unordered_map<int,int>hash;
        for(int i=0;i<s.size();i++)//遍历字符串
        {
            hash[s[i]]++;
        }
        for(auto & x:hash)
        {
            ans += x.second;
            if(x.second % 2 != 0)//如果是奇数,则将长度减一
            {
                ans--;
                odd=1;
            }
        }
        if(odd==1)//将任意一个出现次数为奇数的字符添加到最长子串中
        {
            ans+=1;
        }
        return ans;
    }
};

(二)统计字符串中被单出来的字符个数【比如aaa,两两成对必有一个a被单出来】

思路:统计字符串中所有出现次数为奇数的字符个数,如果没有,那就都是偶数,直接返回字符串的长度,如果有字符出现次数为奇数次,那么选择其中一个字符加入回文串的长度即可

代码如下:

class Solution 
{
public:
    int longestPalindrome(string s)
     {
        int ans=0;//返回最长回文子串的长度
        int count = 0;
        unordered_map<int,int>hash;
        for(int i=0;i<s.size();i++)//遍历字符串
        {
            hash[s[i]]++;
        }
        for(auto & x:hash)
        {
            if(x.second%2!=0)
            {
                count++;//统计字符次数出现奇数次的字符个数
            }
        }
        if(count == 0)
        {
            return s.size();//如果没有字符次数为奇数,那么直接返回字符串的长度
        }
        return s.size()-count+1;
    }
};

(三)贪心算法

思路:该种解法参考力扣官方题解,学到了新的编码技能

在这里插入图片描述

代码如下:


class Solution {
public:
    int longestPalindrome(string s) {
        unordered_map<int,int>hash;
        int ans=0;
        for(int i=0;i<s.length();i++)
        {
            hash[s[i]]++;
        }
        for(auto &x:hash)
        {
            ans += x.second /2 * 2;
            if(x.second % 2!=0 & ans%2==0)
            {
                ans++;
            }
        }
        return ans;
    }
};

✨✨✨

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值