代码随想录第九天打卡·leetcode·字符串2:151.翻转字符串里的单词;28. 实现 strStr();459.重复的子字符串;

151.翻转字符串里的单词

给定一个字符串,逐个翻转字符串中的每个单词。

示例 1:
输入: "the sky is blue"
输出: "blue is sky the"

示例 2:
输入: "  hello world!  "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。

示例 3:
输入: "a good   example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

分析:1\用split库函数,分隔单词,然后定义一个新的string字符串,最后再把单词倒序相加

2\要求o(1)空间复杂度,分为三步

                        移除多余空格:移除开头结尾的空格,移除中间连续的多个空格

                                        ——采用双指针的方式

                        将整个字符串反转

                        将每个单词反转

**如采用while循环:注意加上对应的 i++ (或者别的…)

**过程中字符串有增删改,需要改变字符串尾‘\0’的位置,以及字符串长度也发生改变

void reverse(char *s,int i,int j){
    char tem;
    while(i<j){
        tem=s[i];
        s[i]=s[j];
        s[j]=tem;
        i++;
        j--;
    }  
}

char* reverseWords(char* s) {
    int left=0;
    int right=strlen(s)-1;
    int tem=0;
    //移除多余空格
    while(s[left]==' ') left++;//先移除头部和尾部的空格
    while(s[right]==' ') right--;

    int i=left;
    while(i<=right){
        while (s[i]==' ' && s[i+1]==' '){
            i++;
        }
        s[tem]=s[i];
        tem++;
        i++;
    }
    s[tem]='\0';// 在新字符串的末尾添加一个空字符

    //将整个字符串反转
    reverse(s,0,strlen(s)-1);

    //将每个单词反转
    tem=0;
    i=0;
    for (tem=0;tem<=strlen(s);tem++){
        if(s[tem]==' ' || s[tem]=='\0'){
            reverse(s, i, tem-1);
            i=tem+1;
        }
    }
    
    return s;
}

28. 实现 strStr()

实现 strStr() 函数。

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回  -1。

示例 1: 输入: haystack = "hello", needle = "ll" 输出: 2

示例 2: 输入: haystack = "aaaaa", needle = "bba" 输出: -1

说明: 当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。 对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。

——kmp算法直接实现

void GetNext(char underfilt[],int next[]){
    int j=0,k=-1;
    next[0]=-1;
    int length=strlen(underfilt);

    while(j<length-1){
        if(k==-1 || underfilt[j]==underfilt[k]){
            j++;
            k++;
            next[j]=k;
        }
        else k=next[k];
    }
}

int strStr(char* haystack, char* needle) {
    int next[999];
    GetNext(needle, next);
    int i=0,j=0,m=strlen(haystack),n=strlen(needle);
    while(i<m && j<n){
        if(j==-1 || haystack[i]==needle[j]){
            i++;
            j++;
        }
        else j=next[j];
    }
    if (j>=n) return (i-n);
    else return -1;

}

459.重复的子字符串

给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。

示例 1:

  • 输入: "abab"
  • 输出: True
  • 解释: 可由子字符串 "ab" 重复两次构成。

示例 2:

  • 输入: "aba"
  • 输出: False

示例 3:

  • 输入: "abcabcabcabc"
  • 输出: True
  • 解释: 可由子字符串 "abc" 重复四次构成。 (或者子字符串 "abcabc" 重复两次构成。)

方法一:kmp算法

原理:

对于重复的情况:

void getnext(char *s,int next[]){
    int k=-1,j=0;
    next[0]=-1;
    while(j<strlen(s)){
        if(k==-1 || s[k]==s[j]){
            k++;
            j++;
            next[j]=k;
        }
        else k=next[k];
    }
}


bool repeatedSubstringPattern(char* s) {
    int next[11000];
    getnext(s, next);
    int len=strlen(s);
    int max_equal=next[len];
    if (max_equal==0) return false;//max_equal=0时,重复片段变成字符串本身重复一次了,故而需要作为特例舍去
    int slice_x=len-max_equal;
    if(max_equal%slice_x==0) return true;
    else return false;
}

方法二:移动窗口法

将s复制一遍 得到s+s,在s+s中间部分匹配s

右旋字符串

字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。

例如,对于输入字符串 "abcdefg" 和整数 2,函数应该将其转换为 "fgabcde"。

输入:输入共包含两行,第一行为一个正整数 k,代表右旋转的位数。第二行为字符串 s,代表需要旋转的字符串。

输出:输出共一行,为进行了右旋转操作后的字符串。

思路:

1、整段reverse

2、分成两个区域分别reverse

**可以输出整个字符串:

printf("%s\n", s);

#include <stdio.h>
#include <string.h>

void reverse(char *s, int left, int right)
{
    while(left <= right)
    {
        char c = s[left];
        s[left] = s[right];
        s[right] = c;
        left++;
        right--;
    }
}


int main()
{
    int k;
    scanf("%d", &k);
    char s[10000];
    scanf("%s", s);

    int len=strlen(s);
    reverse(s,0,len-1);
    reverse(s,0,k-1);
    reverse(s,k,len-1);
    
    printf("%s\n", s);


    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值