刷题计划day8 字符串上【反转字符串】【反转字符串 II】【反转字符串中的单词】

⚡刷题计划day8继续,可以点个免费的赞哦~

往期可看专栏,关注不迷路,

您的支持是我的最大动力🌹~

目录

⚡刷题计划day8继续,可以点个免费的赞哦~

往期可看专栏,关注不迷路,

您的支持是我的最大动力🌹~

题目一:344. 反转字符串

双指针

题目二:541. 反转字符串 II

法一:

法二:StringBuffer

题目三:151. 反转字符串中的单词

法一:Stack栈

法二:


题目一:344. 反转字符串

leetcode:344. 反转字符串(https://leetcode.cn/problems/reverse-string/description/)

题外话,这题c++和java都有库函数直接调用就可以,但这样,就不清楚反转字符串的原理了。

但是也不是说库函数就不能用,是要分场景的。

如果在现场面试中,我们什么时候使用库函数,什么时候不要用库函数呢?

如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。

毕竟面试官一定不是考察你对库函数的熟悉程度。

如果库函数仅仅是 解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,可以考虑使用库函数。


双指针

直接将数组首与末进行交换即可

//写法一
class Solution {
    public void reverseString(char[] s) {
    	int len = s.length;
		for(int i=0;i<len/2;i++){
				char temp = s[i];
				s[i] = s[len-i-1];
				s[len-i-1] = temp;
		}
    }
}
//写法二
class Solution {
    public void reverseString(char[] s) {
        int l = 0;
        int r = s.length - 1;
        while(l < r){
            char temp = s[l];
            s[l] = s[r];
            s[r] = temp;
            l++;
            r--;
        }
    }
}

题目二:541. 反转字符串 II

leetcode:541. 反转字符串 II

(https://leetcode.cn/problems/reverse-string-ii/description/)

其实在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。

因为要找的也就是每2 * k 区间的起点,这样写,程序会高效很多。

法一:

AC代码

class Solution {
    public String reverseStr(String s, int k) {
       char[] c = s.toCharArray();
       for(int i=0;i<c.length;i+=2*k){
          int start = i;
          int end = Math.min(c.length-1,i+k-1);
          //循环部分
          while (start<end){
             char temp = c[start];
             c[start] = c[end];
             c[end] = temp;

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

//循环部分也可使用异或,不需要使用第三个变量来暂存其中一个值
while(start < end){
    // 通过异或运算交换c[start]和c[end]的值
    // 第一次异或,c[start]变为c[start]和c[end]的异或结果
    c[start] ^= c[end];
    // 第二次异或,c[end]变为c[start]原始的值
    c[end] ^= c[start]; // 此时c[start]的原始值已经存储在c[end]
    // 第三次异或,c[start]恢复为c[end]原始的值
    c[start] ^= c[end]; // 此时c[start]和c[end]的值已经交换

    // 移动start和end指针,准备下一次交换
    start++;
    end--;
}

法二:StringBuffer

//解法一
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();
    }
}

题目三:151. 反转字符串中的单词

leetcode:151. 反转字符串中的单词

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

这道题目可以说是综合考察了字符串的多种操作。

中等题

想一下,我们将整个字符串都反转过来,那么单词的顺序指定是倒序了,只不过单词本身也倒序了,那么再把单词反转一下,单词不就正过来了。

所以解题思路如下:

  • 移除多余空格

  • 将整个字符串反转

  • 将每个单词反转

举个例子,源字符串为:"the sky is blue "

  • 移除多余空格 : "the sky is blue"

  • 字符串反转:"eulb si yks eht"

  • 单词反转:"blue is sky the"

这样我们就完成了翻转字符串里的单词。


详细见代码注释

法一:Stack栈

class Solution {
    public String reverseWords(String s) {
        // 去除字符串两端的空白字符
        s = s.trim();
        
        // 将字符串转换成字符数组
        char[] ch = s.toCharArray();
        // 创建一个新的字符数组用于存储反转后的字符
        char[] c2 = new char[s.length()];
        int j = 0; // 用于记录c2数组的当前索引
        
        // 反转字符串中的字符顺序
        for(int i = ch.length - 1; i >= 0; i--) {
            // 将ch数组的字符按反转顺序放入c2数组
            c2[j++] = ch[i];
        }

        // 创建一个栈用于存储单词字符
        Stack<Character> st = new Stack<>();
        // 创建一个新的字符数组用于存储最终结果
        char[] c3 = new char[s.length()];
        int k = 0; // 用于记录c3数组的当前索引

        // 遍历c2数组,使用栈来反转单词顺序
        for (int i = 0; i < c2.length; i++) {
            // 如果当前字符不是空格,则压入栈中
            if (c2[i] != ' ') {
                st.push(c2[i]);
            } else {
                // 如果当前字符是空格,弹出栈中所有字符直到遇到空格
                // 这意味着已经收集完一个单词的字符
                while (!st.isEmpty()) {
                    c3[k++] = st.pop(); // 弹出栈顶元素并放入c3数组
                }
                // 添加空格到c3,除了在最后一个单词之后
                // 这里检查i是否为c2数组的倒数第二个位置,以及下一个字符是否为空格
                if (i < c2.length - 1 && c2[i + 1] != ' ') {
                    c3[k++] = ' '; // 添加空格
                }
            }
        }
        // 弹出栈中剩余的所有字符到c3数组
        // 这将收集最后一个单词(如果有的话)
        while (!st.isEmpty()) {
            c3[k++] = st.pop();
        }

        // 将c3数组转换成字符串,并去除两端的空白字符
        // 这是最终反转单词顺序后的字符串
        return new String(c3).trim();
    }
}

法二:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值