2023 跟我一起学数据结构与算法:字符串(上)
字符串被定义为字符数组。字符数组和字符串之间的区别在于字符串以特殊字符"\0"结尾。 下面是一些字符串示例:
"this", "is", "demo007", "i", "am", "a", "developer"
字符串在内存中是如何表示的?
在 C 中,可以使用字符指针或字符数组来引用字符串。当字符串被声明为字符数组时,它们的存储方式与 C 中其他类型的数组一样。例如,如果 str[] 是一个 auto 变量,则该字符串存储在堆栈段中,如果它是一个全局或静态变量,则存储在数据段中.
对字符串执行的操作:
1. 字符串连接
将多个字符串组合在一起的过程称为串联。字符串连接是组合两个字符串的技术。
2. 在字符串中查找
对字符串执行的一个非常基本的操作是在给定的整个字符串中查找某些内容。现在,这可以是在字符串中查找给定字符,或者在另一个字符串中查找完整的字符串。
a) 查找字符串中的一个字符 :
给定一个字符串和一个字符,任务是找到该字符在字符串中的第一个位置。这些类型的问题是竞争非常激烈的编程问题,您需要找到字符串中字符的位置。
b) 在另一个字符串中查找子字符串 :
考虑有一个长度为 N 的字符串和一个长度为 M 的子字符串。然后运行一个嵌套循环,其中外循环从 0 到 (NM),内循环从 0 到 M。对于每个索引,检查子字符串是否内循环遍历的字符串是否是给定的子字符串。
3.字符串替换
很多时候,对字符串进行修改非常重要。替换字符串中的字符、单词或短语是对字符串执行的另一种非常常见的操作。
解决给定问题的最简单方法是遍历字符串S,当找到任何字符串S1作为字符串S中的子字符串时,则将其替换为S2。请按照以下步骤解决此问题:
-
初始化字符串
ans
来存储替换字符串 S 中所有出现的子字符串 S1 到 S2 后的结果字符串。 -
使用变量 i迭代字符串 S 的字符
并执行以下步骤:
- 如果字符串S的前缀子串从索引i开始等于S1,则将字符串S2添加到字符串ans中。
- 否则,将当前字符添加到字符串 ans 中。
-
完成上述步骤后,打印字符串 ans 作为结果。
4. 求字符串的长度
对字符串最常见的操作之一是查找给定字符串的长度/大小。长度定义为字符串中的字符数,称为该字符串的长度。
a )不使用任何内置方法的字符串长度:
下面是求两个字符串长度的算法:
iniSET LEN = 0 AND I = 0. Repeat Steps 3 to 4 while STRING[I] is not NULL: LEN = LEN + 1. SET I = I + 1. Exit.
6. 字符串的反转和旋转
反向操作是交换字符串中字符的位置,使第一个字符变为最后一个,第二个字符变为倒数第二个,依此类推。
a)字符串的旋转:
考虑一个字符串"demo007",现在所有可能的旋转将是:
- 7demo00
- 70demo0
- 700demo
- 700odem
- 700omde
- 700omed
b)反转字符串:
字符串的反转只不过是将字符串的最后一个元素替换为字符串的第一个位置。
7. 字符串的子序列
子序列是可以通过删除零个或多个元素从另一个序列导出的序列,而不改变剩余元素的顺序。
更一般地,我们可以说,对于大小为 n 的序列,总共可以有 (2n-1) 个非空子序列。
例如,考虑字符串"geeks",有 15 个子序列。 他们是:
g, e, e, k, s, ge, ge, gk, gs, ee, ek, es, ek, es, ks, gee, gek, ges, gek, ges, gks, eek, ees, eks, eks, geek, gees, eeks, geeks
9. 二进制字符串
二进制字符串是一种特殊的字符串,仅由两种类型的字符组成,例如 0 和 1。 例如:
vbnet输入: str = "01010101010" 输出: Yes, it is a Binary String 输入: str = "demo007" 输出: No, it is not a Binary String
10. 回文字符串
如果字符串的反转与该字符串相同,则称该字符串为回文。
例如: "abba"是回文,但"abbc"不是回文。
11. 词典模式
字典顺序模式是基于 ASCII 值的模式,或者可以按字典顺序表示。我们将字符的字典顺序视为它们的 ASCII 值的顺序。因此字符的字典顺序将是
css
"A"、"B"、"C"、...、"Y"、"Z"、"a"、"b"、"c"、...、"y"、"z"。
12. 模式搜索
模式搜索是在字符串中搜索给定的模式。这是字符串的高级内容。模式搜索算法有时也称为字符串搜索算法,并被视为字符串算法的一部分。这些算法在搜索另一个字符串中的字符串的情况下非常有用。
测试
如何替换字符串的子字符串
给定三个字符串 S、S1和S2 ,分别由N、M和K 个字符组成,任务是通过将字符串S中的所有子字符串S1替换为字符串S2来修改字符串S。
例子:
输入: S = "abababa", S1 = "aba", S2 = "a"
输出: aba
解释:
将子字符串 S[0, 2] 和 S[4, 6](= S1) 更改为字符串 S2(= "a") 将字符串 S 修改为"aba"。因此,打印"aba"。
输入: S = "geeksforgeeks",S1 ="eek",S2 ="ok"
输出: goksforgoks
go
func TestA(t *testing.T) {
// S := "abababa"
// S1 := "aba"
// S2 := "a"
S := "geeksforgeeks"
S1 := "eek"
S2 := "ok"
var s1len = len(S1)
var rest string
for i := 0; i < len(S); i++ {
var x = S[i:]
if i+s1len < len(S) {
x = S[i : i+s1len]
}
if x == S1 {
rest += S2
i = i + s1len - 1
} else {
rest += string(S[i])
}
}
fmt.Println(rest)
}
解读:
要找到 S 中的 S1 的子串,我们需要不断的遍历字符串 S , 所以我们使用一个 for ,并不断的取出 i+s1len 长度的字符串与 S 字符串比较,如果相同则将 S3 的子串放到 rest 中,如果不匹配则将原来的子串放到 rest 中,不断重复直到结束。
- 时间复杂度:我们使用了一个 for 来循环 S, 循环的次数取决于 S 字符串的长度。所以时间复杂度为 O(n);
- 空间复杂度:我们定义了
var rest string
来保存最后的结果。所以空间复杂度为 O(1)