Loading

代码随想录(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;
    }
}
posted @ 2023-03-16 19:19  丘野  阅读(11)  评论(0编辑  收藏  举报