代码随想录算法训练营第九天 | 151.翻转字符串里的单词 卡码网:55.右旋转字符串 28. 实现 strStr() 459.重复的子字符串

151.翻转字符串里的单词

力扣题目链接(opens new window)

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

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

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

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

 

这道题果然是考查字符串综合操作的好题,直接给绕晕过去, 要正确使用while,for,if,虽然某些情况下总能通过,使用 while:当循环次数未知且需要根据某个条件判断是否继续时。使用 for:当你已经知道循环次数或者有明确的计数器或迭代器控制时。Java中要使用stringbuilder才修改字符串,string无法修改,

首先要把前后空格以及中间多余的空格给去掉,stringbuilder添加元素是使用append。然后是整体反转,最后将每个单词翻转,注意条件。

class Solution {
   /**
     * 不使用Java内置方法实现
     * <p>
     * 1.去除首尾以及中间多余空格
     * 2.反转整个字符串
     * 3.反转各个单词
     */
    public String reverseWords(String s) {
        // System.out.println("ReverseWords.reverseWords2() called with: s = [" + s + "]");
        // 1.去除首尾以及中间多余空格
        StringBuilder sb = removeSpace(s);
        // 2.反转整个字符串
        reverseString(sb, 0, sb.length() - 1);
        // 3.反转各个单词
        reverseEachWord(sb);
        return sb.toString();
    }

    private StringBuilder removeSpace(String s) {
        // System.out.println("ReverseWords.removeSpace() called with: s = [" + s + "]");
        int start = 0;
        int end = s.length() - 1;
        while (s.charAt(start) == ' ') start++;
        while (s.charAt(end) == ' ') end--;
        StringBuilder sb = new StringBuilder();
        while (start <= end) {
            char c = s.charAt(start);
            if (c != ' ' || sb.charAt(sb.length() - 1) != ' ') {
                sb.append(c);
            }
            start++;
        }
        // System.out.println("ReverseWords.removeSpace returned: sb = [" + sb + "]");
        return sb;
    }

    /**
     * 反转字符串指定区间[start, end]的字符
     */
    public void reverseString(StringBuilder sb, int start, int end) {
        // System.out.println("ReverseWords.reverseString() called with: sb = [" + sb + "], start = [" + start + "], end = [" + end + "]");
        while (start < end) {
            char temp = sb.charAt(start);
            sb.setCharAt(start, sb.charAt(end));
            sb.setCharAt(end, temp);
            start++;
            end--;
        }
        // System.out.println("ReverseWords.reverseString returned: sb = [" + sb + "]");
    }

    private void reverseEachWord(StringBuilder sb) {
        int start = 0;
        int end = 1;
        int n = sb.length();
        while (start < n) {
            while (end < n && sb.charAt(end) != ' ') {
                end++;
            }
            reverseString(sb, start, end - 1);
            start = end + 1;
            end = start + 1;
        }
    }
}

 

右旋字符串

卡码网题目链接(opens new window)

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

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

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

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

样例输入:

2
abcdefg 

1
2

样例输出:

fgabcde

1

数据范围:1 <= k < 10000, 1 <= s.length < 1000zh

 这道题输入时nextInt() 会读取一个整数,但是它会留在输入流中一个换行符,而 nextLine() 会直接读取这个换行符作为一个空字符串。nextline会读取换行符,而nextint不会读取,所以在nextint后要使用换行符nextline,后续nextline才会读到真正的字符串,三次反转完成读取,用ch数组。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int k = in.nextInt();
        in.nextLine();
        String s = in.nextLine();
        int n=s.length();
        char[] ch=s.toCharArray();
        reverse(ch,0,n-1);
        reverse(ch,0,k-1);
        reverse(ch,k,n-1);
        System.out.println(new String(ch));
        
    }
    
    private static void reverse(char[] ch,int start,int end){
        while(start<end){
        char temp =ch[start];
        ch[start]=ch[end];
        ch[end]=temp;
        start++;
        end--;}
        
    
    }
}

 

28. 实现 strStr()

力扣题目链接(opens new window)

实现 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算法比较难懂,整体来说就是先求出next数组,然后在通过next数组在匹配不想当时可以直接返回到特定的字符,不需要从头开始匹配,。在设置next数组时,是针对于模型串,设置j为前缀,i为后缀,初始化好next数组时,先计算前后缀不相等情况下以进行回流,因此用到了while,然后计算前后缀相等情况下,j++即可,然后将j填入next[]中。

得到next数组后,然后可以在两个字符串匹配不相等的情况下,通过next数组进行回流,遍历next数组时和遍历两个字符串是否相等时,他们的判断条件里的内容一样,甚至可以直接背住

class Solution {
    //前缀表(不减一)Java实现
    public int strStr(String haystack, String needle) {
        if (needle.length() == 0) return 0;
        int[] next = new int[needle.length()];
        getNext(next, needle);

        int j = 0;
        for (int i = 0; i < haystack.length(); i++) {
            while (j > 0 && needle.charAt(j) != haystack.charAt(i)) 
                j = next[j - 1];
            if (needle.charAt(j) == haystack.charAt(i)) 
                j++;
            if (j == needle.length()) 
                return i - needle.length() + 1;
        }
        return -1;

    }
    
    private void getNext(int[] next, String s) {
        int j = 0;
        next[0] = 0;
        for (int i = 1; i < s.length(); i++) {
            while (j > 0 && s.charAt(j) != s.charAt(i)) 
                j = next[j - 1];
            if (s.charAt(j) == s.charAt(i)) 
                j++;
            next[i] = j; 
        }
    }
}

 

459.重复的子字符串

力扣题目链接(opens new window)

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

示例 1:

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

示例 2:

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

示例 3:

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

如果遇到一个字符串是否在另一个字符串中出现,和是否有重复字符串需要用到kmp算法,针对本题,当 最长相等前后缀不包含的子串的长度 可以被 字符串s的长度整除,那么不包含的子串 就是s的最小重复子串。如此的话,先求出next数组,然后判断

if(next[n-1]>0&&n%(n-next[n-1])==0)即可

class Solution {

    public boolean repeatedSubstringPattern(String s) {

        if (s.equals("")) return false;

        int[] next=new int[s.length()];

        getnext(s,next);

        int n=s.length();

        if(next[n-1]>0&&n%(n-next[n-1])==0){

            return true;

        }else{

            return false;

        }

    }

    public void getnext(String s,int[] next){

        next[0]=0;

        int j=0;

        for(int i=1;i<s.length();i++){

            while(j>0&&s.charAt(i)!=s.charAt(j)){

                j=next[j-1];

            }

            if(s.charAt(i)==s.charAt(j)){

                j++;

            }

            next[i]=j;

        }

       

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值