数据结构——字符串

1.leetcode 151

题目链接:

. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/reverse-words-in-a-string/题目评价:极好的字符串题目,考察逆转、删除空格,解法多次使用了双指针法

cpp 复制代码
class Solution {
public:
    //逆转字符串s中起始l到末尾r的子串
    void reverse(string& s,int l,int r)
    {
        char tmp = 0;
        while (l < r)
        {
            tmp = s[l];
            s[l] = s[r];
            s[r] = tmp;
            l++; r--;
        }
    }
    

   /* 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。*/
    string reverseWords(string s) {
       //先清除空格,再总体逆转整个字符串,再逐个逆转每个单词
        removeBlanks(s);
        reverse(s, 0, s.length()-1);
        reverseEachWord(s);
        return s;
    }

 //删除前置后置空格,以及单词间冗杂的空格,时间复杂度为O(n)
    void removeBlanks(string& s)
    {
        //erase时间复杂度为O(n),遍历+erase时间复杂度为O(n^2),采用双指针法时间复杂度为O(n)
        int slow=0;  //慢指针指向新字符串元素
        int fast=0;  //快指针遍历字符串
        for (fast = 0; fast < s.length(); fast++)
        {
            //有两类字符:字母-下个字母->放字母,字母-空格->放字母+空格
            if (s[fast] != ' ')
            {
                if (fast == s.length() - 1 || s[fast + 1] != ' ')
                    s[slow++] = s[fast];
                else
                {
                    s[slow++] = s[fast];
                    s[slow++] = ' ';
                }
            }
        }
        //除末尾多余空格
        if (s[slow - 1] == ' ') slow--;
        s.resize(slow);  //slow指示新字符串的大小
    }

    //在删除空格的基础上,实现每个单词逆转,核心是判断单词的开头与结尾,单词开头要么是第一个字符要么是空格之后的第一个字符
    //单词的结尾要么是最后一个字符,要么是空格后的第一个字符
    void reverseEachWord(string& s)
    {
        int l = 0, r = 0;
        for (int r = 0; r <= s.length(); r++)
        {
            if (s[r] == ' '||r==s.length())
            {
                reverse(s, l, r - 1);
                l = r + 1;
            }
        }
    }
};

2. 替换数字(第八期模拟笔试)

时间限制:1.000S 空间限制:128MB

题目描述

给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。 例如,对于输入字符串 "a1b2c3",函数应该将其转换为 "anumberbnumbercnumber"。

输入描述

输入一个字符串 s,s 仅包含小写字母和数字字符。

输出描述

打印一个新的字符串,其中每个数字字符都被替换为了number

输入示例

a1b2c3

输出示例

anumberbnumbercnumber

提示信息

数据范围:

1 <= s.length < 10000。

cpp 复制代码
class solution {
public:
	string convert(string & s)
	{
		//1.识别数字,扩容[number6位扣除数字1位]
		int i = 0;
		while (i<s.length())
		{
			if (s[i] >= '0' && s[i] <= '9')
			{
				int pi = s.length() - 1;
				//1.识别数字,扩容[number6位扣除数字1位],记录需要移动的次数
				int move = s.length()-1 - i;
				s.resize(s.length() + 5);
				//2.双指针,分别指向新老字符串的末尾,把待转化数字后面的字符搬到字符串尾部
				int pj = s.length() - 1;
				while (move--)
				{
					s[pj] = s[pi];
					pj--;
					pi--;
				}
				//3.放进number
				string tmp = "rebmun";
				for (int i = 0; i < 6; i++)
					s[pj - i] = tmp[i];
                //4.移动i
				i += 6;
			}
			else 
			i++;
		}
		return s;
		
	}
};

3. 右旋字符串(第八期模拟笔试)

时间限制:1.000S 空间限制:128MB

题目描述

字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。

例如,对于输入字符串 "abcdefg" 和整数 2,函数应该将其转换为 "fgabcde"。

输入描述

输入共包含两行,第一行为一个正整数 k,代表右旋转的位数。第二行为字符串 s,代表需要旋转的字符串。

输出描述

输出共一行,为进行了右旋转操作后的字符串。

输入示例

2
abcdefg

输出示例

fgabcde

提示信息

数据范围:

1 <= k < 10000,

1 <= s.length < 10000

cpp 复制代码
class solution {
public:
	void Reverse(string& s, int i, int j)
	{
		char c = 0;
		while (i < j)
		{
			c = s[i];
			s[i] = s[j];
			s[j] = c;
			i++;
			j--;
		}
	}
	string RightReverse(string& s,int k)
	{
		//先局部翻转,再总体翻转 原理表示如:A1B1A2B2->B1A1B2A2->A2B2A1B1
		int len = s.length();
		Reverse(s, 0, len - k - 1);
		Reverse(s, len - k, len - 1);
		Reverse(s, 0, len - 1);
		return s;
	}
};

4. KMP算法

cpp 复制代码
//实现字符串的匹配(即在文本串中寻找模式串子串)
class KMP {
	int* next; //next数组含义:next[i]记录前i字符构成的子串中最长公共前后缀,指示模式串与文本串不匹配时模式串下一个比较字符
public:

	int KMP_Match(string s1 = "", string s2 = " ")
	{
		int* next = new int[s2.length()];
		getNext(s2, next);
		int i = 0, j = 0; //i遍历文本串,j遍历模式串
		for (int i = 0; i < s1.length(); i++)
		{
			while (j > 0 && s1[i] != s2[j]) {
				j = next[j - 1];
			}
			if (s1[i] == s2[j]) j++;
			if (j == s2.length())  //匹配
			{
				return i + 1 - s2.length();
			}
		}
		return -1;
	};

	void getNext(string s,int* next)
	{
		//i:前缀尾,j:后缀尾,注意 i指示当前最长公共前后缀的长度!!!
		//初始化
		if (!next)  next = new int[s.length()];
		next[0] = 0;  //next数组第一个位置设为0
		int i = 0, j;
		for ( j = 1; j < s.length(); j++){
		
			 //前后缀不匹配,循环前缀尾取上一个next的值,直至前后缀匹配或前缀到头
				while(i>0&&s[i]!=s[j])
				i = next[i - 1];  
				//前后缀匹配
				if (s[i] == s[j])
					i++; //公共前后缀长度加一
			
			next[j]=i;//更新next数组
		}

	}
};
相关推荐
xiaoshiguang32 小时前
LeetCode:222.完全二叉树节点的数量
算法·leetcode
爱吃西瓜的小菜鸡2 小时前
【C语言】判断回文
c语言·学习·算法
别NULL2 小时前
机试题——疯长的草
数据结构·c++·算法
TT哇2 小时前
*【每日一题 提高题】[蓝桥杯 2022 国 A] 选素数
java·算法·蓝桥杯
ZSYP-S4 小时前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring
yuanbenshidiaos4 小时前
C++----------函数的调用机制
java·c++·算法
唐叔在学习4 小时前
【唐叔学算法】第21天:超越比较-计数排序、桶排序与基数排序的Java实践及性能剖析
数据结构·算法·排序算法
ALISHENGYA4 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(switch语句)
数据结构·算法
chengooooooo4 小时前
代码随想录训练营第二十七天| 贪心理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和
算法·leetcode·职场和发展
jackiendsc4 小时前
Java的垃圾回收机制介绍、工作原理、算法及分析调优
java·开发语言·算法