字符串是什么:字符的数组
字符串就是字符的数组——一串排好队的字符。比如 "hello" 可以看作 ['h','e','l','l','o'] 这样一个数组。每个字符在内存中连续存放,通过索引(从0开始)可以快速访问任意位置的字符。这种底层结构决定了字符串的很多特性。
不可变性:不能改,只能新建
很多语言(如 Java、Python、C#)中的字符串是不可变的:一旦创建,里面的字符就不能被修改。想改变内容?只能新建一个字符串。这就像写在纸上的字——不能擦掉重写,只能换一张新纸重抄一遍。不可变性带来了线程安全、缓存哈希值等好处,但也让频繁修改变得低效。
常用操作:遍历、拼接、截取、查找
- 遍历:用循环按索引访问每个字符,就像排队点名。
- 拼接:用
+或concat连接两个字符串,实质是创建新字符串。 - 截取:通过
substring或切片语法取出一段子串,也是复制出新字符串。 - 查找:用
indexOf或find定位子串位置,返回索引或 -1。
双指针经典:反转与回文
双指针是处理字符串的利器。反转字符串时,一个指针指向头,一个指向尾,交换字符后向中间移动,直到相遇。判断回文(正反读一样)也用类似方法:从两端向中间比较字符是否相等。双指针避免了额外空间,时间复杂度 O(n)。
复杂度与拼接性能坑
| 操作 | 时间复杂度 | 说明 |
|---|---|---|
| 按索引访问 | O(1) | 数组特性,直接定位 |
| 遍历 | O(n) | 每个字符访问一次 |
| 拼接(+) | O(n+m) | 需复制两个字符串到新内存 |
| 截取 | O(k) | k 为子串长度,复制产生新串 |
| 查找 | O(n*m) 最坏 | 朴素匹配,n 为主串长,m 为模式串长 |
注意:在循环中用 + 拼接字符串会产生大量临时对象,性能极差。应使用 StringBuilder 或 join 方法,它们维护可变缓冲区,避免重复复制。