刷题day7 344反转字符串、541反转字符串II、剑指Offer 05替换空格、151翻转字符串里的单词、右旋转字符串

本文详细介绍了几种字符串反转的编程技巧,包括双指针法、异或操作、Java中的StringBuilder和C++中的字符数组操作,以及处理字符串中的空格和单词反转。通过实例展示了如何在不同语言中实现字符串的右旋转和部分反转功能。
摘要由CSDN通过智能技术生成

一、344反转字符串

此题主要是明白有些不能直接用函数来将题目全部解完毕,此题主要的思路是也是大概是双指针,一个在头,一个在尾,两者一起向中间遍历,直到i> = j的时候停止,所以循环条件是while(i < j),循环内容是让两个位置的元素交换位置

先来第一种构建临时空值的方法。构建一个temp = s[i]来保存a指针的值,之后将a指针的值赋值给s[j]即b指针,之后将temp的值赋值给b指针即可,这样就成功交换了两个位置的元素值

第二种方法是新学习的异或操作的方法(^)   根据a ^= b  b ^=a  a ^= b交换两值,这是根据c = a^b那么b = a^c, a = c^b得出来的,所以照这样得出s[i] ^= s[j],      s[j] ^= s[i], s[i] ^= s[j],即可完成两位置元素的互换

代码如下:

class Solution {
    public void reverseString(char[] s) {
            int i = 0;
            int j = s.length - 1;
            while(i < j)
            {
                // char temp = s[i];
                // s[i] = s[j];
                // s[j] = temp;
                // i++;
                // j--;
                s[i] ^= s[j];
                s[j] ^= s[i];
                s[i] ^= s[j];
                i++;
                j--;
            }



    }
}

二、541反转字符串II

 这道题做的时候确实是有点绕,把我也绕进去了

主要是这道题要求的是在2k的时候为一轮,在2k之后进行剩余部分比较,如果剩余部分是小于k的那么就是进行反转,剩余部分是大于k的那么就是k的部分反转,大于k的部分抄下来,在这里我一开始理解错了,导致理解错为“卡在2k之中的大于k的部分反转”,之后才明白

首先是陌生的函数的使用,①有StringBuffer res = new StringBuffer()的使用,这是创建了一个字符串数组,一但是数组的话,调用的就是.length,字符串是调用的是.length()函数。②还有三元运算符的使用int firstk = (start + k  > length) ? length : start + k;还有int secondk = (start + 2*k > length) ? length : start + 2k;③s.substring(start,firstk),这段代码是将s从start到firstk的字符摘取出来,然后append到temp中

这道题的思路主要是先找两个位置,firstk和secondk的位置,这两个位置通过三元组与length相比来确定,如果start + k/start + 2k的位置大于length的话,那么firstk/secondk就是length的位置,反之,则反

可以拿一个具体的例子判断一下当字符串的长度是2k多一点,多的部分比k小,那么第一轮firstk的位置在(0+k)= k的位置,secondk在(0 + 2k)= 2k的位置,然后取firstk到secondk之间的字符做反转,之后如果firstk != secondk,那么就是在第一个2k中后k个字符原封不动的摘出来放在res中,这个判断条件是判断有没有2k中的后k个字符,如果有的话就是,原封不动的抄下来,如果没有的话,你可以发现firstk和secondk的值是相等的,都等于的length,所以此时是只有反转,然后start直接移动到下一轮的开头,即start += 2*k ,最后以start < length作为循环条件

具体反正拿两个例子套用一下,就明白整体的意思了

代码如下:


class Solution {
    public String reverseStr(String s, int k) {
        StringBuffer res = new StringBuffer();
        int length = s.length();
        int start = 0;
        while (start < length) {
            // 找到k处和2k处
            StringBuffer temp = new StringBuffer();
            // 与length进行判断,如果大于length了,那就将其置为length
            int firstK = (start + k > length) ? length : start + k;
            int secondK = (start + (2 * k) > length) ? length : start + (2 * k);

            //无论start所处位置,至少会反转一次
            temp.append(s.substring(start, firstK));
            res.append(temp.reverse());

            // 如果firstK到secondK之间有元素,这些元素直接放入res里即可。
            if (firstK != secondK) { //此时剩余长度一定大于k。
                res.append(s.substring(firstK, secondK));
            }
            start += (2 * k);
        }
        return res.toString();
    }
}

三、剑指offer 05替换空格(替换数字)

Java版本的代码可以说是重新开辟了一段可变的字符串空间,利用new StringBuilder()来创建

之后还是得导入控制台输入流的包import java.util.Scanner; 然后通过Scanner  in = new Scanner(System.in); 创建输入流对象  ,之后通过 String s = in.nextLine();来捕捉

然后就是加入一个for循环开始扫描输入的s字符串,如果是数字的话就把number放入新的可变字符串数组 ss.append("number")【这里注意字符串要加“”】 ,否则就直接填入此时的位置值ss.append(s.charAt(i));注意这里比较位置的值是否是数字的时候引入一个新的函数方法判断:if(Character.isDigit(s.charAt(i))),最后打印出来ss数组:System.out.println(ss)

代码如下:

import java.util.Scanner;
class Main{
    public static void main(String[] args){
    StringBuilder ss = new StringBuilder();
    Scanner in = new Scanner(System.in);
    String s = in.nextLine();
    
    for(int i=0;i<s.length();i++)
    {
        if(Character.isDigit(s.charAt(i)))
        {
            ss.append("number");
        }
        
        else{
            ss.append(s.charAt(i));
        }
    }
    System.out.println(ss);
    }
}

没有java版本双指针的代码,看c++的吧

四、151翻转字符串里的单词

 

这道题在Java中分为了三部分函数处理,分别是处理字符串前后的空格以及中间多余空格的函数(要求每个单词中间只能有一个空格)、将字符串翻转的函数、还有最后一个以一个空格为划分单独翻转单词的函数

首先要定义一个总函数reverseWords来调用其他三个分段函数,最后经过处理的StringBuilder类型强制转换为String类型,使用toString函数

在 Java 中,StringBuilder 是一种可变的字符序列,它允许高效地构建和修改字符串。但通常,当你需要将结果字符串传递给其他方法或返回它时,你需要将 StringBuilder 转换为不可变的 String,因为许多标准的 Java API 都期望接收字符串而不是 StringBuilder

因此,在 sb.toString() 调用之后,你将获得一个不可变的 String 对象,可以作为 reverseWords 方法的返回值,方便在其他地方使用或返回给调用者。

 首先第一个函数是removeSpace(String s),字符串s传进来之后,先把首尾的空格去掉,使用两个while来去掉,这里要定义首尾两个指针,start = 0 ,end = s.length() - 1 ,两个while(s.charAt(start) == ‘ ’) start++;while(s.charAt(end) == ' ') end--; StringBuffer sb = new StringBuffer() ;然后下一步就是去掉两个单词中间的连续空格(这步真的出乎我的意料,想了好久才想明白,因为简简单单的两个或语句的判断,就能让连续空格消失),这步主要是从start开始先判断一下start的位置是否是包含空格的,如果他是包含空格的,那么就判断一下形成的新串sb是否也包含空格,因为这一步马上就是要把start位置的字符放到sb新串上,所以得双重或语句判断一下,也就是说他们两个有一个是空就行,所以是或语句,所以就有if(c != ' ' || sb.charAt(sb.length() - 1)  != ' ')  sb.append(c);之后start++,继续进行下一个函数

之后是翻转函数reverseString(StringBuilder sb,int start,int end),这个函数主要是借助首尾两个指针进行交换值,其中还需要借助一个空指针存值,此时还需要注意用到一个新函数setCharAt(),这个函数是用后的值代替前的值,相当于赋值操作

最后就是单独的单词翻转的函数了,其实就是声明一个start,声明一个end,end是start的下一位,判断是否是空格,如果是空格那么就是对这部分的单词进行翻转,用到上面自定义的翻转函数,然后到下一组单词,start = end+1,end = start + 1,重新进行循环

代码如下:

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;
        }
    }
}

 五、右旋转字符串

这道题主要是想不额外的开创内存,那就要想到异或的方法来翻转字符串,通过

a ^= b  b ^=a  a ^= b来交换a和b两者的值,这样循环起来,那么就能写一个独立的翻转函数

然后再找找规律,发现在把整体的字符翻转之后,再分部分翻转,正好是右旋转字符串的结果

这里还需要注意,在最开始的时候要引入一个scan的包来进行控制台的输入操作,in.nextLine()表示对输入的内容的捕捉,Scanner in = new Scanner(System.in)是控制台输入, n = Integer.parseInt(in.nextLine())这是将控制台输入的第一行转换成整数n,还有一步是将输入的字符串转换成一个字符数组:char[]  ch = s.toCharArray();

所以就有以下的代码:

import java.util.Scanner;

public  class Main{
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        int n = Integer.parseInt(in.nextLine());
        String s = in.nextLine();
        
        int m = s.length();
        char[] ch = s.toCharArray();
        reverseString(ch, 0, m-1);
        reverseString(ch, 0, n-1);
        reverseString(ch, n, m-1);
        
        System.out.println(ch);
        

        }
                public static void reverseString(char[] ch, int start, int end){
            while(start < end){
                ch[start] ^= ch[end];
                ch[end] ^= ch[start];
                ch[start] ^= ch[end];
                start++;
                end--;
            }
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值