LeetCode每日一题——Day10

本文介绍了一种算法,用于反转字符串中每个单词的字符顺序,同时保持原有的空格和单词顺序不变。通过C++和Java两种语言实现了该功能,并详细分析了Java中String类型的特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

557. 反转字符串中的单词 III

给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

示例 1:

输入:s = "Let's take LeetCode contest"
输出:"s'teL ekat edoCteeL tsetnoc"


示例 2:

输入: s = "God Ding"
输出:"doG gniD"

思路分析:

        当找到一个单词时,我们设立双指针left,right分别在单词的首尾。反转left,right所对应值即可。实现数组的原地翻转,也可开辟一个新的数组空间存放。

        但是这种方法在java中并不适用,因为在Java中String是一个不可变类型。

        我们顺便分析一下Java中String的底层源码:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

        可以看到在源码中,value数组使用了final关键字修饰,即String底层的数据结构使用的是final修饰的字符数组,所以是不能修改的。

        我们再来看看Java中的StringBuffer和StringBuilder,这里以StringBuffer为例,因为他们都是继承了AbstractStringBuilder。

public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{

    /**
     * A cache of the last value returned by toString. Cleared
     * whenever the StringBuffer is modified.
     */
    private transient char[] toStringCache;

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    /**
     * The value is used for character storage.
     */
    char[] value;

        StringBuffer的底层仅仅只是一个char字符数组,所以可以被更改。

        那我们再来想想String类型为什么是不可更改类型:

  • 在Java的堆内存中,有一个特殊的存储区域字符串常量,当创建了一个新的String对象时,假设字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用当前已经存在的对象,帮我们节省了空间。
        String s1 = "花朝九日";
        String s2 = "花朝九日";
        System.out.println(s1==s2);
        //结果为ture
  • String被许多的Java类和库用来当做参数,比如url,path等等。如果String不是固定不变的将会引起各种安全隐患。
       String resource = "mybatis-config.xml";
        //创建一个resource对象引入mybatis配置文件

        通过上面的分析,在此题中,使用Java语言必须要开辟空间。设立双指针left=0,right,当right指向空格时停下,同时right回退指向单词末尾。考虑到会漏掉最后一个单词,我们这里在s的末尾也添加一个空格。调用StringBuffer中的方法创建并翻转值为从left到right的数组。再对原来的数组进行替代即可。

    StringBuffer sb = new StringBuffer(s);
    sb.append(" ");    
    StringBuffer ts = new StringBuffer(sb.substring(left, right + 1));
    String tempString = ts.reverse().toString();

代码实现:

        原地覆盖(用C++实现)

class Solution {
public: 
    string reverseWords(string s) {
        int length = s.length();
        int i = 0;
        while (i < length) {
            int start = i;
            while (i < length && s[i] != ' ') {
                i++;
            }

            int left = start, right = i - 1;
            while (left < right) {
                swap(s[left], s[right]);
                left++;
                right--;
            }
            while (i < length && s[i] == ' ') {
                i++;
            }
        }
        return s;
    }
};

        StringBuffer方法(用Java实现)

class Solution {
   public static String reverseWords(String s) {
        StringBuffer sb = new StringBuffer(s);
        sb.append(" ");
        int left = 0;
        int right = 0;
        for (right = 0; right <= s.length(); right++) {
            if (sb.charAt(right) == ' ') {
                right--;
                StringBuffer ts = new StringBuffer(sb.substring(left, right + 1));
                String tempString = ts.reverse().toString();
                sb.replace(left, right + 1, tempString);
                right++;
                left = right + 1;
            }
        }
        return sb.substring(0,sb.length() - 1).toString();
    }
}

提交结果:

         StringBuffer方法(用Java实现)

29 / 29 个通过测试用例

状态:通过

执行用时: 13 ms

内存消耗: 42.4 MB

提交时间:1 天前

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值