算法 1.9.1 反轉字符串中的單詞 III【leetcode 557】

題目描述

給定一個字符串抱慌,你需要反轉字符串中每個單詞的字符順序歹鱼,同時仍保留空格和單詞的初始順序泣栈。

示例:
? 輸入:"Let's take LeetCode contest"
? 輸出:"s'teL ekat edoCteeL tsetnoc"

提示:
? 在字符串中卜高,每個單詞由單個空格分隔弥姻,并且字符串中不會有任何額外的空格。


數據結構

  • 字符串掺涛、字符數組

算法思維

  • 遍歷庭敦、逆序、雙指針

解題要點

  • 如何優(yōu)化實現一個單詞中的字符反轉


解題思路


一. Comprehend 理解題意
  • 單詞的順序不變
  • 顛倒每個單詞內部字符的順序

二. Choose 選擇數據結構與算法
雙指針 解法
  • 數據結構:指針薪缆、字符串
  • 算法思維:遍歷秧廉、逆序伞广、雙指針
解題思路
  1. 聲明雙指針和緩存
  2. 遍歷字符串
    ? 如果不是:讀到了字符串末尾 或者 讀到了空格
    ? ? 判斷首指針是否為空
    ? ? ? 如果為空就賦值成當前位置
    ? ? 不管首指針是否為空,尾指針都和遍歷位置對齊
    ? 如果:讀到了末尾疼电,或者讀到了空格
    ? ? 判斷首指針是否為空
    ? ? ? 如果不為空嚼锄,就逆序遍歷首尾指針之間的所有字符,存入緩沖區(qū)
    ? ? ? 每讀完一個單詞都要添加一個空格蔽豺,并且將首尾指針復原
  3. 最終去掉緩沖區(qū)末尾的空格后区丑,作為字符串返回
邊界問題
  • 為了討論最后一個字符非空的情況,將邊界條件設為:i <= s.length()
細節(jié)問題
  • 需要非空判斷
  • 遍歷完整個字符串修陡,需要判斷當前首尾指針中間是都有數據
    如果有數據沧侥,要額外寫入一次到緩存區(qū)中,避免丟失最后一個單詞

三. Code 編碼實現基本解法
class Solution {
    public String reverseWords(String s) {

        int len = s.length();

        //0.非空判斷
        if (len == 0) return "";

        //1.聲明雙指針和緩存
        int first = -1, last = -1;
        StringBuffer sb = new StringBuffer();

        char[] arr = s.toCharArray();
        //2.遍歷字符串
        for (int i = 0; i <= len; i++) {
            //3.如果不是讀到了字符串末尾魄鸦,或者讀到了空格
            if (i != len && arr[i] != ' ') {
                //4.就判斷首指針是否為空宴杀,如果為空就賦值成當前位置
                if (first == -1) {
                    first = i;
                }
                //5.不管首指針是否為空,尾指針都和遍歷位置對齊
                last = i;
            } else if (first != -1) { //6.如果讀到了末尾拾因,或者讀到了空格旺罢,且首指針不為空
                //7.逆序遍歷首尾指針之間的所有字符,存入緩沖區(qū)
                while (last >= first) {
                    sb.append(arr[last]);
                    last--;
                }
                //8.每讀完一個單詞都要添加一個空格绢记,并且將首尾指針復原
                sb.append(' ');
                first = -1;
                last = -1;
            }
        }

        //9.最終去掉緩沖區(qū)末尾的空格后主经,作為字符串返回
        return sb.substring(0,sb.length()-1);
    }
}

執(zhí)行耗時:8 ms,擊敗了 56.64% 的Java用戶
內存消耗:39 MB庭惜,擊敗了 64.81% 的Java用戶
時間復雜度:O(n) -- 兩次字符串的遍歷 O(n)
空間復雜度:O(n) -- 一個緩沖區(qū) O(n)罩驻,兩個指針 O(1)

四. Consider 思考更優(yōu)解
改變算法思維
  • 使用遍歷的方式反轉字符效率太低
  • 使用 StringBuffer 作為緩沖區(qū)存取數據,消耗時間和空間
  • 題目給定了條件:“每個單詞由單個空格分隔”
    因此可以使用 雙指針 + 字符數組 的方式直接 原地反轉 字符

五. Code 編碼實現最優(yōu)解
優(yōu)化解法:原地反轉
class solution{
    //使用雙指針护赊,原地反轉單詞
    public String reverseWords(String s) {
        if (s == null || s.length() == 0) {//邊界檢查
            return s;
        }
        char[] chars = s.toCharArray();
        int len = chars.length;
        //指向單詞的初始字符
        int start = 0;
        int end = 0;//指向單詞的結尾字符或者是終止索引
        //截取單詞進行 單詞翻轉
        for (int i = 0; i < len; i++) {
            if (chars[i] == ' ') {//如果查詢到了空格惠遏,一個單詞結束
                end = i - 1;
                reverse(chars, start, end);
                start = i + 1;//反轉單詞之后把start指向下一個單詞的起始
            } else if (i == len - 1) {//如果查詢到了數組最后一個字符,一個單詞結束
                reverse(chars, start, len - 1);
            }
        }
        return new String(chars);
    }

    //雙指針原地翻轉方法骏啰,給定反轉的源數組节吮,給定起始索引和終止索引
    public void reverse(char[] s, int start, int end) {
        while (start < end) {//如果起始索引小于終止索引计维,進行反轉
            //交換雙指針對應的字符
            char temp = s[start];
            s[start] = s[end];
            s[end] = temp;

            start++;
            end--;
        }
    }

}

執(zhí)行耗時:3 ms财异,擊敗了 99.88% 的Java用戶
內存消耗:39.2 MB璃谨,擊敗了 34.70% 的Java用戶
時間復雜度:O(n) -- 字符串的遍歷 O(n)
空間復雜度:O(1) -- 字符數組 O(1)婉称,雙指針 O(1)

六. Change 變形與延伸

=== 待續(xù) ===

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末踩寇,一起剝皮案震驚了整個濱河市媒咳,隨后出現的幾起案子空免,更是在濱河造成了極大的恐慌顽染,老刑警劉巖草丧,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狸臣,死亡現場離奇詭異,居然都是意外死亡昌执,警方通過查閱死者的電腦和手機烛亦,發(fā)現死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門诈泼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人煤禽,你說我怎么就攤上這事铐达。” “怎么了檬果?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵娶桦,是天一觀的道長。 經常有香客問我汁汗,道長衷畦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任知牌,我火速辦了婚禮祈争,結果婚禮上,老公的妹妹穿的比我還像新娘角寸。我一直安慰自己菩混,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布扁藕。 她就那樣靜靜地躺著沮峡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪亿柑。 梳的紋絲不亂的頭發(fā)上邢疙,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音望薄,去河邊找鬼疟游。 笑死,一個胖子當著我的面吹牛痕支,可吹牛的內容都是我干的颁虐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼卧须,長吁一口氣:“原來是場噩夢啊……” “哼另绩!你這毒婦竟也來了?” 一聲冷哼從身側響起花嘶,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤笋籽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后察绷,有當地人在樹林里發(fā)現了一具尸體干签,經...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡津辩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年拆撼,在試婚紗的時候發(fā)現自己被綠了容劳。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡闸度,死狀恐怖竭贩,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情莺禁,我是刑警寧澤留量,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站哟冬,受9級特大地震影響楼熄,放射性物質發(fā)生泄漏。R本人自食惡果不足惜浩峡,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一可岂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧翰灾,春花似錦缕粹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至咽块,卻和暖如春绘面,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背侈沪。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工飒货, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人峭竣。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓塘辅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親皆撩。 傳聞我的和親對象是個殘疾皇子扣墩,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內容