1.7 LeetCode总结(线性表)字符串类

本文介绍了字符串处理的两个常见问题:反转字符串II和寻找字符串的最大公因子。通过具体代码展示了如何使用交换和反转函数解决这些问题,并提供了详细的解题思路。对于反转字符串,采用分块反转策略;而对于最大公因子,利用了字符串的性质进行递归查找。

编程总结

在专栏日刻一诗中有初级关于字符串处理函数的介绍,而本专栏强化学习是进阶篇,将记录一些刷题实际遇到的“坑”

字符串处理常用函数

// 交换
void swap(char *l, char *r)
{
   
   
	char tmp = *l;
	*l = *r;
	*r = tmp;
}
// 反转
void reverse(char *l, char *r)
{
   
   
	while (l < r) {
   
   
		swap(l++, r--);
	}
}

344. 反转字符串_一刷(100%)

思路:反转函数基础

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
在这里插入图片描述
提示:
1 <= s.length <= 105
s[i] 都是 ASCII 码表中的可打印字符

// 字符串首尾两两交换
// 由于是传入的指针,所以字符会改变
void reverseString(char *s, int sSize)
{
   
   
	char tmp;
	for (int i = 0; i < sSize / 2; i++) {
   
   
		tmp = s[i];
		s[i] = s[(sSize - 1) - i];
		s[(sSize - 1) - i] = tmp;
	}
}

541. 反转字符串 II

思路:反转函数应用

给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

  1. 如果剩余字符少于 k 个,则将剩余字符全部反转。
  2. 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
    在这里插入图片描述
    提示:
    1 <= s.length <= 10^4
    s 仅由小写英文组成
    1 <= k <= 10^4
void swap(char *l, char *r)
{
   
   
	char tmp = *l;
	*l = *r;
	*r = tmp;
}
void reverse(char *l, char *r)
{
   
   
	while (l < r) {
   
   
		swap(l++, r--);
	}
}
char *reverseStr(char *s, int k)
{
   
   
	int n = strlen(s);
	int resNum = n;
	for (int i = 0; i < n; i += 2 * k) {
   
    // i 以 2k 来移动
		resNum = n - i;
		if (resNum < k) {
   
   
			reverse(&s[i], &s[n - 1]); // 如果剩余字符少于 k 个,则将剩余字符全部反转
		} else if (resNum >= k) {
   
   
			reverse(&s[i], &s[i + k - 1]); // 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样
		}
	}
	return s;
}
int main(void)
{
   
   
	char s[8] = "abcdefg";
	int  k = 1;
	char *ret = reverseStr(s, k);
	printf("ret = %s\n", ret);
	return 0;
}

思路, LeetCode 的题一定要有一个统筹的观念,起初做这题时,一直陷入在各个条件的判断中,衍生了很多不必要的操作代码
下面这两个函数处理手法也可以记住:

151. 反转字符串中的单词_一刷(100%)

思路:strtok函数切割,填充使用sprintf

给你一个字符串 s ,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
提示:
1 <= s.length <= 10^4
s 包含英文大小写字母、数字和空格 ’ ’
s 中 至少存在一个 单词
在这里插入图片描述

char *reverseWords(char *s)
{
   
   
	int idx = 0;
	char *token;
	char *tmpStr = (char *)malloc(sizeof(char) * 10001);
	char *res = (char*)malloc(sizeof(char) * 10001);
	char result[10001][32] = {
   
    0 };
	strcpy(tmpStr, s); // 不要直接操作源字符串
	memset(res, 0, 10001);
	token = strtok(tmpStr, " ");
	while (token != NULL) {
   
   
		strcpy(result[idx], token);
		idx = idx + 1;
		token = strtok(NULL, " ");
	}
	for (int i = idx - 1; i >= 0; i--) {
   
    // 题目要求反转,从后往前
		sprintf(res + strlen(res), "%s ", result[i]);
	}
	free(tmpStr);
	res[strlen(res) - 1] = '\0'; // 因为前面多填充了一个空格,所以这里处理掉
	return res;
}
int main(void)
{
   
   
	char s[20] = "the  sky  is  blue";
	int len = strlen(s);
	char *res = reverseWords(s);
	printf("%s\n", res);
	return 0;
}

1071. 字符串的最大公因子

对于字符串 s 和 t,只有在 s = t + t + t + … + t + t(t 自身连接 1 次或多次)时,我们才认定 “t 能除尽 s”。
给定两个字符串 str1 和 str2 。返回 最长字符串 x,要求满足 x 能除尽 str1 且 x 能除尽 str2
示例 1:
输入:str1 = “ABCABC”, str2 = “ABC”
输出:“ABC”
示例 2:
输入:str1 = “ABABAB”, str2 = “ABAB”
输出:“AB”
示例 3:
输入:str1 = “LEET”, str2 = “CODE”
输出:“”
提示:
1 <= str1.length, str2.length <= 1000
str1 和 str2 由大写英文字母组成

思路:如果两个字符串之间存在最大公因子:

(1) 短串一定是和在长串的前strlen(短串)字符组成的子串相同;
(2) 长串不断减去短串,得到的两个字符串(原有短串和差串)同样满足(1)中关系;
(3) 当等到的两个串相同时,即为最大公因子。
(https://img-blog.csdnimg.cn/b9a00aa2104a43519a4114bcfc29ea4f.png)

char *gcdOfStrings(char *str1, char *str2)
{
   
   
	char *lger = strlen(str1) > strlen(str2) ? str1 : str2;
	char *sher = strlen(str1) > strlen(str2) ? str2 : str1;
	if (strcmp(lger, sher) == 0) {
   
   
		return sher;
	}
	if (strncmp(lger, sher, strlen(sher)) != 0) {
   
   
		return "";
	}
	// +strlen(sher) 指针后移sher的长度,去到lger中后半段
	return gcdOfStrings(lger + strlen(sher), sher);
}

28. 找出字符串中第一个匹配项的下标_一刷(100%)

思路:子串处理_双指针

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
示例 1:
输入:haystack = “sadbutsad”, needle = “sad”
输出:0
解释:“sad” 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。

示例 2:
输入:haystack = “leetcode”, needle = “leeto”
输出:-1
解释:“leeto” 没有在 “leetcode” 中出现,所以返回 -1 。

提示:
1 <= haystack.length, needle.length <= 10^4
haystack 和 needle 仅由小写英文字符组成

int strStr(char *haystack, char *needle)
{
   
   
	int len1 = strlen(haystack);
	int len2 = strlen(needle);
	int h_r = 0;
	int len = 0;
	int res = 0;
	for (int i = 0; i < len1; i++) {
   
   
		len = 0;
		if (haystack[i] != needle[0]) {
   
    // 先找到符合条件的i下标
			continue;
		}
		h_r = i; // 不要直接动i
		for (int j = 0; j < len2; j++) {
   
   
			res = h_r;
			while (haystack[h_r] == needle[j]) {
   
   
				j++;
				h_r++;
				len++;
				if (len == len2) {
   
   
					return res
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值