代码随想录(4)-字符串
344.反转字符串#
题目:
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
代码:
class Solution {
public void reverseString(char[] s) {
int len = s.length;
int middle = (int) (len / 2.0 );
for(int i = 0; i < middle; i++){
char c = s[i];
s[i] = s[len-1-i] ;
s[len-1-i] = c;
}
}
}
541.反转字符串 II#
题目:给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
- 如果剩余字符少于 k 个,则将剩余字符全部反转。
- 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
代码:
class Solution {
public String reverseStr(String s, int k) {
char[] cs = s.toCharArray();
int times = cs.length / (2 * k);
for(int i = 0; i < times; i++){
int start = i * 2 * k;
int end = start + k;
func(cs,start ,end);
}
int start = times * 2 * k;
int end = start + k;
if( cs.length % ( 2 * k ) < k){
end = start + cs.length % ( 2 * k );
}
func(cs,start ,end);
return new String(cs);
}
// 将字符串反转,反转下标start到end-1的范围
void func(char[] cs, int start ,int end){
int middle = (int) ( (end - start) / 2.0);
for( int j = 0; j < middle; j++){
char c = cs[ start + j];
cs[ start + j] = cs[ end - 1 - j];
cs[ end - 1 - j] = c;
}
}
}
剑指 Offer 05. 替换空格#
题目:请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
class Solution {
public String replaceSpace(String s) {
char[] t = s.toCharArray();
// 数出有几个空格
int count = 0;
for(int i = 0; i < t.length; i++)
if( t[i] == ' ') count++;
// 双指针法
int i = t.length - 1;
int j = i + count*2;
char[] ans = new char[ j+1 ];
for( ; i >= 0; i--,j--)
if( t[i] == ' ' ){
ans[j--] = '0';
ans[j--] = '2';
ans[j] = '%' ;
}else
ans[j] = t[i];
return new String( ans );
}
}
151. 反转字符串中的单词(middle)#
给你一个字符串 s ,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
新建空间#
准备一个空字符串。
从后往前遍历s,使用双指针i j,i负责遍历,j负责指向上一个空格出现的位置。
每当i指向空格就将[i+1,j-1]上的插入进新字符串,并将当前空格插入其后(需判断ans尾部是否为空格,防止插入重复的空格)。然后更新j=i。
public String reverseWords(String s) {
char[] cs = s.toCharArray();
char[] ans = new char[cs.length];
int i = cs.length - 1, j = i + 1;
int k = 0;
for( ; i >= 0; i--){
if( cs[i] == ' '){
for( int t = i + 1; t < j; t++)
ans[k++] = cs[t];
// 防止重复添加空字符
if( k > 0 && ans[k-1] != ' ')
ans[k++] = ' ';
j = i;
}
}
// 添加可能存在的第一个单词
for( int t = i + 1; t < j; t++)
ans[k++] = cs[t];
// 删除最后可能存在的空字符
if(ans[k-1] == ' ') k--;
return (new String(ans)).substring(0,k);
}
双重颠倒#
1、合并一起的多个空格
2、删除头尾的空格
3、将字符串颠倒
4、遍历字符串将每个单词颠倒
剑指 Offer 58 - II. 左旋转字符串#
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
class Solution {
public String reverseLeftWords(String s, int n) {
String temp = s.substring(0,n);
char[] chars = s.toCharArray();
for(int i = n; i < s.length(); i++ )
chars[i-n] = chars[i];
for(int i = 0; i < n; i++ )
chars[s.length() - n + i] = temp.charAt(i);
return new String(chars);
}
}
28. 找出字符串中第一个匹配项的下标#
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
KMP思路:
主函数
预处理获得needle中next数组,(当
heystack[i]
和needle[j]
匹配失败时,heystack[i]
可以继续和needle[ next[j] ]
进行比较)。下标 i 遍历 字符串 heystack
下标 j 遍历 字符串 needle
如果h[i] == n[j],
如果,j == needle.length - 1,那么返回 i - j
否则,那么下标都加一
否则如果 j != 0,那么i不变,j = next[j]
否则,i++
返回-1(此时即没有匹配)
前缀函数
设置next数组
下标 j 从 1 开始遍历 needle字符串
如果 needle[j] == neede[ next[j-1] ],那么当前字符可以跟在前面的前缀上,
如果不等于,但是前面的next[i-1]大于0。那么应该遍历靠后next[i-1]个字符中是否有符合的前缀。
class Solution {
public int strStr(String haystack, String needle) {
int j = 0;
int[] next = findNext(needle);
for(int i = 0; i < haystack.length(); i++){
if( haystack.charAt(i) == needle.charAt(j) ){
if( j == needle.length() -1) return i - j;
else j++;
}else{
if(j > 0 ) {
j = next[j-1];
i--;
}
}
}
return -1;
}
int[] findNext(String needle){
int[] next = new int[needle.length() ];
for( int i = 1; i < needle.length(); i++){
if( needle.charAt(i) == needle.charAt(next[i-1]))
next[i] = next[i-1] + 1;
else
for(int t = next[i-1];t > 0; t--){
int flag = 1;
for(int j = 0; j < t; j++ ){
if(needle.charAt(j) != needle.charAt(i-t+1 + j)){
flag = 0;
break;
}
}
if(flag == 1){
next[i] = t;
break;
}
}
}
return next;
}
}
459. 重复的子字符串#
给定一个非空的字符串 s
,检查是否可以通过由它的一个子串重复多次构成。
暴力法#
思路:一个字符串长度为n,那么最长重复次数为n,最少为2。那么可以采取暴力法依次遍历。
class Solution {
public boolean repeatedSubstringPattern(String s) {
int n = s.length();
// 遍历子串可能出现的次数
for( int i = 2; i <= n; i++){
if( n % i != 0) continue;
boolean is_repeate = true;
int len = n / i;
// 遍历字符长度
for(int j = 0; j < len; j++ ){
char c = s.charAt(j);
boolean is_diff_char = false;
// 检查次数
for(int k = 1; k < i; k++){
if( s.charAt( k*len + j) != c) {
is_repeate = false;
is_diff_char = true;
break;
}
}
if( is_diff_char ) break;
}
if( is_repeate ) return true;
}
return false;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人