文章目录
151.反转字符串中的单词
题目链接:151. 反转字符串中的单词 - 力扣(LeetCode)
题目描述:给你一个字符串 s
,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s
中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
**注意:**输入字符串 s
中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
示例 1:
输入:s = "the sky is blue"
输出:"blue is sky the"
示例 2:
输入:s = " hello world "
输出:"world hello"
解释:反转后的字符串中不能存在前导空格和尾随空格。
示例 3:
输入:s = "a good example"
输出:"example good a"
解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。
解法一、辅助数组+字符串函数
先将整个字符串反转,再将每个单词反转
#define MAX_LEN 10001
void swap(char *s){
int len=strlen(s);
for(int i=0,j=len-1;i<j;i++,j--){
char temp=s[i];
s[i]=s[j];
s[j]=temp;
}
}
char* reverseWords(char* s) {
//反转整个字符串
swap(s);
char *result=(char*)malloc(sizeof(char)*MAX_LEN);
result[0]='\0';
//字符串分割函数
char *token= strtok(s," ");
while(token!=NULL){
char temp[MAX_LEN]={'\0'};
strcpy(temp,token);
swap(temp);//反转每个单词
sprintf(result+strlen(result),"%s ",temp);
token= strtok(NULL," ");
}
result[strlen(result)-1]='\0';//除去末尾的空格
return result;
}
解法二、双指针(不使用额外空间)
解题思路如下:
移除多余空格
将整个字符串反转
将每个单词反转
// 翻转字符串中指定范围的字符
void reverse(char* s, int start, int end) {
for (int i = start, j = end; i < j; i++, j--) {
int tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}
// 删除字符串两端和中间多余的空格
void removeExtraSpace(char* s) {
int start = 0; // 指向字符串开头的指针
int end = strlen(s) - 1; // 指向字符串结尾的指针
while (s[start] == ' ') start++; // 移动指针 start,直到找到第一个非空格字符
while (s[end] == ' ') end--; // 移动指针 end,直到找到第一个非空格字符
int slow = 0; // 指向新字符串的下一个写入位置的指针
for (int i = start; i <= end; i++) { // 遍历整个字符串
if (s[i] == ' ' && s[i+1] == ' ') { // 如果当前字符是空格,并且下一个字符也是空格,则跳过
continue;
}
s[slow] = s[i]; // 否则,将当前字符复制到新字符串的 slow 位置
slow++; // 将 slow 指针向后移动
}
s[slow] = '\0'; // 在新字符串的末尾添加一个空字符
}
// 翻转字符串中的单词
char * reverseWords(char * s){
removeExtraSpace(s); // 先删除字符串两端和中间的多余空格
reverse(s, 0, strlen(s) - 1); // 翻转整个字符串
int slow = 0; // 指向每个单词的开头位置的指针
for (int i = 0; i <= strlen(s); i++) { // 遍历整个字符串
if (s[i] ==' ' || s[i] == '\0') { // 如果当前字符是空格或空字符,说明一个单词结束了
reverse(s, slow, i-1); // 翻转单词
slow = i + 1; // 将 slow 指针指向下一个单词的开头位置
}
}
return s; // 返回处理后的字符串
}
卡码网:55.右旋转字符串
题目链接:55. 右旋字符串(第八期模拟笔试) (kamacoder.com)
题目描述:题目描述
字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。
例如,对于输入字符串 “abcdefg” 和整数 2,函数应该将其转换为 “fgabcde”。
输入描述
输入共包含两行,第一行为一个正整数 k,代表右旋转的位数。第二行为字符串 s,代表需要旋转的字符串。
输出描述
输出共一行,为进行了右旋转操作后的字符串。
输入示例
2
abcdefg
输出示例
fgabcde
思路
设字符串长度为l(l>k),把字符串分为长度为l-k、k两个子串,先反转两个子串,再反转整个字符串即可
#define MAX_LEN 10001
void swap(char *s,int start,int end){//交换字符串中指定区间的字符
for(int i=start,j=end;i<j;i++,j--){
char ch=s[i];
s[i]=s[j];
s[j]=ch;
}
}
int main(){
char input[MAX_LEN]={'\0'};
int k;
scanf("%d",&k);
scanf("%s",input);
input[strcspn(input,"\n")]='\0';
int len=strlen(input);
swap(input,0,len-k-1);
swap(input,len-k,len-1);
swap(input,0,len-1);
printf("%s",input);
return 0;
}
28.找出字符串中第一个匹配项的下标
题目链接:28. 找出字符串中第一个匹配项的下标
题目描述:给你两个字符串 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 <= 104
haystack
和needle
仅由小写英文字符组成
本题虽然简单,但旨在考查对KMP算法的运用,实现strStr()函数
解法一、暴力匹配
int strStr(char* haystack, char* needle) {
int n = strlen(haystack), m = strlen(needle);
for (int i = 0; i + m <= n; i++) {
bool flag = true;
for (int j = 0; j < m; j++) {
if (haystack[i + j] != needle[j]) {
flag = false;
break;
}
}
if (flag) {
return i;
}
}
return -1;
}
解法二、KMP算法
int strStr(char* haystack, char* needle) {
int n = strlen(haystack), m = strlen(needle);
if (m == 0) {
return 0;
}
int pi[m];
pi[0] = 0;
for (int i = 1, j = 0; i < m; i++) {
while (j > 0 && needle[i] != needle[j]) {
j = pi[j - 1];
}
if (needle[i] == needle[j]) {
j++;
}
pi[i] = j;
}
for (int i = 0, j = 0; i < n; i++) {
while (j > 0 && haystack[i] != needle[j]) {
j = pi[j - 1];
}
if (haystack[i] == needle[j]) {
j++;
}
if (j == m) {
return i - m + 1;
}
}
return -1;
}