算法训练第八天 | 字符串part1


字符串part1:

LeetCode344、反转字符串

代码
class Solution {
    public void reverseString(char[] s) {
        for (int i = 0, j = (s.length-1); i < (s.length/2); i++, j--){
            if (i < j){
                char temp = s[j];
                s[j] = s[i];
                s[i] = temp;
            }
        }
    }
}

两个指针从两头移动到中间,每移动一次交换位置

LeetCode541、反转字符串2

代码
class Solution {
    public String reverseStr(String s, int k) {
        char[] array = s.toCharArray();
        int times = (array.length / (2*k)) + 1;
        for(int i = 0; i < times; i++){
            int left = 2*k*i;
            int right = 2*k*i + (k-1);
            if (right >= array.length){
                right = array.length - 1;
            }
            while (left < right){
                char temp = array[right];
                array[right] = array[left];
                array[left] = temp;
                left++;
                right--;
            }
        }
        return String.valueOf(array);
    }
}

class Solution {
    public String reverseStr(String s, int k) {
        char[] ch = s.toCharArray();
        for(int i = 0;i < ch.length;i += 2 * k){
            int start = i;
            // 判断尾数够不够k个来取决end指针的位置
            int end = Math.min(ch.length - 1,start + k - 1);
            while(start < end){
                
                char temp = ch[start];
                ch[start] = ch[end];
                ch[end] = temp;

                start++;
                end--;
            }
        }
        return new String(ch);
    }
}

两种不同写法的for,一种是遍历2k的次数,一种是遍历字符,每次+=2*k

【知识点】
char[] ch = s.toCharArray();
return String.valueOf(array);
//或
return new String(array);

剑指offer05、替换空格

思路

若将字符串转为数组操作,一个空格对应’%20’三个字符,则肯定要给数组扩容。
定义两个指针,从后往前填充,像追及问题,追的路程是空格个数*2,两指针相遇之时说明所有因为空格导致的路程都追上来了,则前面就没有空格了。又因为再相遇之前,后面的指针一直没追上前面的指针,所以不存在有字符没有保存就被覆盖了的问题。

public class StringOffer05 {
    
    //方法1
    public String replaceSpace(String s) {
        int originLength = s.length();
        int num = 0;
        for (int i = 0; i < s.length(); i++){
            if (s.charAt(i) == ' '){
                num++;
            }
        }
        for (int i = 0; i < num; i++){
        	s = s.concat("  ");
        }
        char[] array = s.toCharArray();
        for (int i = (originLength-1), j = (array.length-1); i >= 0; i--, j--){
            if (i == j){
                break;
            }
            if (array[i] == ' '){
                array[j] = '0';
                array[j-1] = '2';
                array[j-2] = '%';
                j -= 2;
            }else {
                array[j] = array[i];
            }
        }
        return String.valueOf(array);
    }
    
    //方法2
    public String replaceSpace(String s){
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < s.length(); i++){
            if (s.charAt(i) == ' '){
                str.append("%20");
            }else {
                str.append(s.charAt(i));
            }
        }
        return str.toString();
    }
}
【知识点】
  1. StringBuilder是可变的,append函数接字符串,字符,数字都可以
  2. StringBuilder转String用toString()函数
  3. 方法1中之所以要先求出来num,是因为如果在遍历s的过程中,就s.concat(" ")的话,s的长度则会不断变化,则会陷入死循环

LeetCode151、反转字符串中的单词

调用库函数的思路:

先split,再reverse,再concat/join
Java用split分割含一个或多个空格的字符串(正则表达式)

时间复杂度O(n)思路:
  1. 去空格,我的第一种写法是把所有空格一起考虑了,比较难想;代码随想录里给的代码是把首尾的空格与中间的空格分开考虑,比较好操作
  2. 整体反转:hello world变成dlrow olleh
  3. 单个单词反转:dlrow olleh变成world hello
  4. 2和3在实现的时候,我的写法是各写各的,代码随想录里给的代码是可以用同一个函数,定义输入字符串,反转开始字符和反转结束字符就可以。
代码
class Solution {
    public String reverseWords(String s) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < s.length(); i++){
            if (s.charAt(i) != ' '){
                stringBuilder.append(s.charAt(i));
            }
            if ((s.charAt(i) == ' ') && (i-1 >=0) && (s.charAt(i-1) != ' ')){
                int temp = i;
                while (i < s.length()){
                //这里要注意,第一遍写的时候在这里出错了,少考虑了末尾有多个空格的情况。
                //只有在判断完这个空格后还有字符的时候,才能append空格。
                    if (s.charAt(i) != ' '){
                        stringBuilder.append(' ');
                        i = temp;
                        break;
                    }
                    i++;
                }
            }
        }
        s = stringBuilder.toString();

        StringBuilder reverseAll = new StringBuilder();
        for (int i = (s.length()-1); i >=0; i--){
            reverseAll.append(s.charAt(i));
        }
        s = reverseAll.toString();

        char[] finalArray = s.toCharArray();
        for (int i = 0; i < s.length(); ){
            if (finalArray[i] == ' '){
                i++;
                continue;
            }else {
                int left = i;
                int length = 0;
                while ((i < s.length()) && (finalArray[i] != ' ')){
                    i++;
                    length++;
                }
                int right = i - 1;
                while (left < right){
                    char temp = finalArray[left];
                    finalArray[left] = finalArray[right];
                    finalArray[right] = temp;
                    left++;
                    right--;
                }
            }
        }

        return String.valueOf(finalArray);
    }
}

去空格的另外一种思路:把首尾的空格与中间的空格分开考虑

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;
        }
    }
【知识点】

char数组里,可以随意给数组里的任何一个元素赋值
对于string,string.charAt(i) = ...这个语句是不被允许的,因为string是immutable
对于stringbuilder,可以改变其中某个字符的值,方法是stringbuilder.setCharAt(位置,值)charAt()函数是取值,而不是赋值
将string转为stringbuilder:StringBuilder sb=new StringBuilder(s);
将stringbuilder转为string:s = sb.toString();

Offer58、左旋字符串

思路一:

定义两个stringbuilder,遍历字符串,一个stringbuilder存放k之前的,另一个存放k之后的,然后concat两个字符串

代码:

class Solution {
    public String reverseLeftWords(String s, int n) {
        if (s.equals(null)){return s;}
        StringBuilder left = new StringBuilder();
        StringBuilder right = new StringBuilder();
        for (int i = 0; i < n; i++){
            left.append(s.charAt(i));
        }
        for (int i = n; i < s.length(); i++){
            right.append(s.charAt(i));
        }
        return right.toString().concat(left.toString());
    }
}
思路二:

不申请额外空间,只用一个stringbuilder。
定义一个反转方法,先k之前反转,k之后反转,再整体反转:
在这里插入图片描述
或者先整体发展,再length-k之前发转,后面的k反转
在这里插入图片描述
代码:

class Solution {
    public String reverseLeftWords(String s, int n) {
        int len=s.length();
        StringBuilder sb=new StringBuilder(s);
        reverseString(sb,0,n-1);
        reverseString(sb,n,len-1);
        return sb.reverse().toString();
    }
     public void reverseString(StringBuilder sb, int start, int end) {
        while (start < end) {
            char temp = sb.charAt(start);
            sb.setCharAt(start, sb.charAt(end));
            sb.setCharAt(end, temp);
            start++;
            end--;
            }
        }
}
【知识点】

stringbuilder的整体反转操作:sb.reverse()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值