代码随想录 Day08

Day08

字符串part02

LeetCode 151.翻转字符串里的单词

题目描述

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

**注意:**输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

示例

输入:s = “the sky is blue”
输出:“blue is sky the”

题目链接

https://leetcode.cn/problems/reverse-words-in-a-string/description/

思路

要得到目标字符串我们要做三步

  • 移除多余的空格
  • 翻转整个字符串
  • 逐个单词反转

在处理第一步上略显麻烦。

解决代码
class Solution {
    public String reverseWords(String s) {
        int newlen = 0, fast = 0;//newlen为处理空格后的字符串长度,fast为遍历当前字符串的下标
        char[] ch = s.toCharArray();
        //去除多余的空格
        while(ch[fast] == ' '){//处理前导空格
            fast++;
        }
        //处理中间和尾随空格
        while(fast < ch.length){//根据前面移除元素的方法
            if(ch[fast] != ' '){
                //正常为字符情况
                ch[newlen++] = ch[fast++];
            }
            else if(ch[fast] == ' ' && ch[fast - 1] != ' '){//保留分隔空格
                ch[newlen++] = ' ';
                fast++;
            }else if(ch[fast] == ' ' && ch[fast - 1] == ' '){//去除中间的连续空格
                fast++;
            }
        }
        if(ch[newlen - 1] == ' '){//如果末尾是空格,则总长度减1
            newlen--;
        }
        char[] ans = new char[newlen];
        for(int i = 0; i < newlen; i++){
            ans[i] = ch[i];
        }
        //反转整个字符串
        reverse(ans, 0, newlen - 1);
        //反转单词
        int last = 0;
        for(int i = 0; i < newlen; i++){
            if(ans[i] == ' '){
                reverse(ans, last, i - 1);
                last = i + 1;
            }
        }
        reverse(ans, last, newlen - 1);
        return new String(ans);
    }
    public static void reverse(char[] ch, int l, int r){
        while(l < r){
            char temp = ch[r];
            ch[r] = ch[l];
            ch[l] = temp;
            l++;
            r--;
        }
    }
}

卡码网:55.右旋转字符串

题目描述

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

例如,对于输入字符串 “abcdefg” 和整数 2,函数应该将其转换为 “fgabcde”。
输入描述
输入共包含两行,第一行为一个正整数 k,代表右旋转的位数。第二行为字符串 s,代表需要旋转的字符串。
输出描述
输出共一行,为进行了右旋转操作后的字符串。

输入示例

2
abcdefg

输出示例

fgabcde

题目链接

https://kamacoder.com/problempage.php?pid=1065

思路

要得到目标字符串, 可以分为三步

  • 翻转整个字符串
  • 反转前k个字符
  • 反转剩下的字符

当然还有一种投机的方法, 就是先把后k个放入新数组, 在放前面的。不过这样就缺少了点乐趣。

解决代码一(投机法)
import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int k = scanner.nextInt();
        String s = scanner.next();
        int len = s.length();
        char[] ch = new char[len];
        for(int i = 0; i < len; i++){
            if(len - k + i < len)
                ch[i] = s.charAt(len - k + i);
            else
                ch[i] = s.charAt(i - k);
        }
        String ans = new String(ch);
        System.out.println(ans);
    }
}
解决代码二
import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int k = scanner.nextInt();
        String s = scanner.next();
        char[] ch = s.toCharArray();
        reverse(ch, 0, ch.length - 1);
        reverse(ch, 0, k - 1);
        reverse(ch, k, ch.length - 1);
        System.out.println(new String(ch));
    }
    public static void reverse(char[] ch, int l, int r){
        while(l < r){
            char temp = ch[l];
            ch[l] = ch[r];
            ch[r] = temp;
            l++;
            r--;
        }
    }
}

LeetCode 28. 实现 strStr()

题目描述

给你两个字符串 haystackneedle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1

示例

输入:haystack = “sadbutsad”, needle = “sad”
输出:0
解释:“sad” 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。

题目链接

https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/description/

思路

可以用hn代表遍历到这两个字符串转换为数组后的下标位置, 如果不同则重置hn的大小。否则持续遍历, 直至n = needle.length

解决代码
class Solution {
    public int strStr(String haystack, String needle) {
        char[] hay = haystack.toCharArray();
        char[] need = needle.toCharArray();
        //haystack长度小于needle直接退出
        if(hay.length < need.length)
            return -1;
        //hay搜索下标为h,needle搜索下标n,hay[h] == need[n], h++,n++; n == needle.length, return h - n;
        //hay[h] != need[n], h = h - n + 1, n = 0 
        int h = 0, n = 0;
        while(n < need.length && h < hay.length){
            if(hay[h] == need[n]){
                h++;
                n++;
            }
            else{
                h = h - n + 1;
                n = 0;
            }
        }
        if(n == need.length)
            return h - n;
        else
            return -1;
    }
}

LeetCode 459.重复的子字符串

题目描述

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

示例

输入: s = “abab”
输出: true
解释: 可由子串 “ab” 重复两次构成。

题目链接

https://leetcode.cn/problems/repeated-substring-pattern/description/

思路

暴力求解思路: 遍历所有可能是子串的长度len, 长度满足0 < len <= s.length / 2。还必须满足len是主串长度的因数, 这样才能重复组成。

移动匹配思路: 若 s 由重复子串构成,则 s 一定存在于 (s + s).substring(1, 2n-1) 中。例如:

  • s = "abab"s + s = "abababab" → 去掉首尾字符后为 "bababa",其中包含原字符串 "abab"

可以这么理解

假设 s 由子串 t 重复 k 次构成(k ≥ 2),则:

  • s + s = t + t + ... + t(重复 2k 次)。
  • 去掉首尾字符后,中间的字符串仍包含至少 2k-2t,因此原字符串 s 必然存在其中。

还有一种利用KMP的解法, 但是我还没弄明白。

暴力求解
public class Solution {
    public boolean repeatedSubstringPattern(String s) {
        int n = s.length();
        // 遍历所有可能的子串长度(必须是n的因数)
        for (int k = 1; k <= n / 2; k++) {
            if (n % k != 0) continue; // 跳过非因数
            String sub = s.substring(0, k);
            boolean valid = true;
            // 检查子串是否能重复构成原字符串
            for (int i = 1; i < n / k; i++) {
                String current = s.substring(i * k, (i + 1) * k);
                if (!current.equals(sub)) {
                    valid = false;
                    break;
                }
            }
            if (valid) return true;
        }
        return false;
    }
}
移动匹配
public class Solution {
    public boolean repeatedSubstringPattern(String s) {
        String ss = s + s;
        int n = s.length();
        return ss.substring(1, 2 * n - 1).contains(s);
    }
}

你可能感兴趣的:(算法训练营,leetcode,java)