代码随想录--第四章字符串

翻转字符串Ⅰ

这题本质还是双指针,跳出条件是两个指针相遇,即右指针不再大于左指针。

package String;

/**
 * 功能:
 * 作者:RNG·Cryin
 * 日期:2024-08-13 16:20
 */
public class ZiFuChuanFanZhuan {

    public void solution(char[] s){
        int len = s.length;
        for (int i = 0 ,j = len - 1; i < j ;i++,j--){
            s[i] ^= s[j] ;
            s[j] ^= s[i] ;
            s[i] ^= s[j] ;
        }

    }

    public static void main(String[] args) {
        char[] s = {'x','d','l','z','w','m'};
        ZiFuChuanFanZhuan ziFuChuanFanZhuan = new ZiFuChuanFanZhuan();
        ziFuChuanFanZhuan.solution(s);

        System.out.println();

    }

}

这题最省内存的操作是,利用异或运算交换两个char !!!然后循环就好了。这里的异或操作,是在位(bit)上的操作。

class Solution {
    public void reverseString(char[] s) {
        int l = 0;
        int r = s.length - 1;
        while (l < r) {
            s[l] ^= s[r];  //构造 a ^ b 的结果,并放在 a 中
            s[r] ^= s[l];  //将 a ^ b 这一结果再 ^ b ,存入b中,此时 b = a, a = a ^ b
            s[l] ^= s[r];  //a ^ b 的结果再 ^ a ,存入 a 中,此时 b = a, a = b 完成交换
            l++;
            r--;
        }
    }
}

翻转字符串Ⅱ

这题的需求就是为了绕你而绕,很奇怪的需求。题目的意思其实概括为 每隔2k个反转前k个,尾数不够k个也反转! 处理的时候第一步把字符串转成字符数组, char [] ch = s.toCharArray()。这题就是情况多,需要多考虑,如果最后一组不足2k个,大于k个。或者甚至还不足k个。这两种情况可以合并成int end = Math.min(ch.length - 1, start + k - 1) 就解决了。因为什么,因为我不管你有多少个,我就只反转k个。

package String;

import static java.lang.Math.min;

/**
 * 功能:
 * 作者:RNG·Cryin
 * 日期:2024-08-13 16:46
 */
public class ZiFuFanZhuan2 {

    public void rever(char[] s ,int start,int end){
        int i =start;
        int j =end;
        while(i < j){
            s[i] ^= s[j];
            s[j] ^= s[i];
            s[i] ^= s[j];
            i++;
            j--;
        }
    }

    public String solution(String s, int k){
        char[] ch = s.toCharArray();
        for (int i = 0 ; i<s.length(); i += 2*k){
            int end = min(i+k-1,s.length()-1);
            rever(ch,i,end);
        }
        return new String(ch);

    }

    public static void main(String[] args) {
        String s ="AaBbCcDdEe";
        ZiFuFanZhuan2 ziFuFanZhuan2 = new ZiFuFanZhuan2();
        String news = ziFuFanZhuan2.solution(s, 2);
        System.out.println(news);
    }


}

翻转单词

处理空格的思路是双指针,快指针扫描整个字符串遇到空格跳过,慢指针指向要覆盖的位置。

package String;

/**
 * 功能:
 * 作者:RNG·Cryin
 * 日期:2024-08-20 13:53
 */
public class FanZhuanDanCi {

    public String solution(String s){
        char[] chars = s.toCharArray();
        // 清理多余空格
        chars = removeSpaces(chars);
        // 翻转整个新字符串
        reverse(chars,0,chars.length-1);
        // 翻转单词。
        reverseWords(chars);
        //返回字符串类型
        return new String(chars);
    }

    public char[] removeSpaces(char[] chars){
        int slow = 0 ;
        for (int fast = 0;  fast < chars.length; fast++ ){
            if (chars[fast] != ' '){
                if (slow != 0){
                    chars[slow++] = ' ';
                }
                while(fast < chars.length && chars[fast] != ' '){   //防数组越界报错!
                    chars[slow++] = chars[fast++];
                }
            }
        }

        char[] newchars = new char[slow];
        System.arraycopy(chars,0,newchars,0,slow);
        return newchars;
    }

    public void reverse(char[] chars,int left, int right){

        while (left < right){
            chars[left] ^= chars[right];
            chars[right] ^= chars[left];
            chars[left] ^= chars[right];

            left++;
            right--;
        }

    }

    public void reverseWords(char[] chars){
        int start = 0;
        for (int end = 1; end <= chars.length; end++  ){
            if (end == chars.length  ||  chars[end] == ' '){
                reverse(chars,start,end-1);
                start = end+1;
            }
        }
    }

    public static void main(String[] args) {
        String s = "a good       example";
        FanZhuanDanCi fanZhuanDanCi = new FanZhuanDanCi();
        System.out.println(fanZhuanDanCi.solution(s));

    }

}

KMP

笔记太多,不展示了。

package String;

/**
 * 功能:
 * 作者:RNG·Cryin
 * 日期:2024-08-13 17:07
 */
public class ZuiChangZiChuanWeiZhi {

    public int KMP(String fuchuan, String zichuan){

        int[] next = new int[zichuan.length()];
        getNext(next,zichuan);
        int j = 0;
        for (int i = 0 ; i< fuchuan.length();i++){
            //不相等
            while(j>0 && fuchuan.charAt(i) != zichuan.charAt(j) ){
                j = next[j-1];
            }
            if (fuchuan.charAt(i) == zichuan.charAt(j)){
                j++ ;
            }

            if (j == zichuan.length()){
                return i - j+1;
            }
        }

        //没有找到子串,也就没有子串的位置,返回-1
        return -1;
    }

    public void getNext(int[] next,String zichuan){

        int j=0;
        next[0] = 0 ;
        for (int i =1;i<zichuan.length();i++){
            //先考虑不相等
            while(j>0 && zichuan.charAt(i) != zichuan.charAt(j)){
                j = next[j-1];
            }
            //相等
            if (zichuan.charAt(i) == zichuan.charAt(j)){
                j++;
            }
            next[i] = j;
        }

    }

    public static void main(String[] args) {


    }


}

重复子串

直接背结论,就是前缀串和后缀串岔开的部分就是重复子串,不过好在这题只需要判断不需要找出。就是next数组生成后多一行背的结论。

package String;

/**
 * 功能:
 * 作者:RNG·Cryin
 * 日期:2024-08-19 20:32
 */
public class ChongFuZiChuan {

    public boolean solution(String s){

        char[] chars = s.toCharArray();
        int[] next = new int[s.length()];
        int len = s.length();
        next[0] = 0;
        int j = 0;
        //构建next数组
        for (int i = 1; i< s.length(); i++){
            while(j>0 && chars[i] != chars[j]){
                j = next[j-1];
            }
            if (chars[i] == chars[j]){
                j++ ;
            }
            next[i] = j;
        }
        for (int i= 0 ; i < len; i++)
        System.out.println(next[i]);
        //判断重复子串
        if (next[len - 1] > 0 &&  len % (len - next[len - 1]) == 0 ){
            return true;
        }
        return false;

    }

    public static void main(String[] args) {
        String s = "abcabcabcabc";
        ChongFuZiChuan chongFuZiChuan = new ChongFuZiChuan();
        System.out.println(chongFuZiChuan.solution(s));
    }
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值