2023-06-15 LeetCode:1177. 構(gòu)建回文串檢測(cè)

1177. 構(gòu)建回文串檢測(cè)

問題描述

給你一個(gè)字符串 s共螺,請(qǐng)你對(duì) s 的子串進(jìn)行檢測(cè)该肴。
每次檢測(cè),待檢子串都可以表示為 queries[i] = [left, right, k]藐不。我們可以 重新排列 子串 s[left], ..., s[right]匀哄,并從中選擇 最多 k 項(xiàng)替換成任何小寫英文字母。
如果在上述檢測(cè)過程中佳吞,子串可以變成回文形式的字符串拱雏,那么檢測(cè)結(jié)果為 true,否則結(jié)果為 false底扳。
返回答案數(shù)組 answer[]铸抑,其中 answer[i] 是第 i 個(gè)待檢子串 queries[i] 的檢測(cè)結(jié)果。

示例

輸入:s = "abcda", queries = [[3,3,0],[1,2,0],[0,3,1],[0,3,2],[0,4,1]]
輸出:[true,false,false,true,true]
解釋:
queries[0] : 子串 = "d"衷模,回文鹊汛。
queries[1] : 子串 = "bc",不是回文阱冶。
queries[2] : 子串 = "abcd"刁憋,只替換 1 個(gè)字符是變不成回文串的。
queries[3] : 子串 = "abcd"木蹬,可以變成回文的 "abba"至耻。 也可以變成 "baab",先重新排序變成 "bacd",然后把 "cd" 替換為 "ab"尘颓。
queries[4] : 子串 = "abcda"走触,可以變成回文的 "abcba"。

解題思路

核心思路:前綴和+異或運(yùn)算

  1. 首先疤苹,理解題目?jī)?nèi)容:截取字符串s中部分連續(xù)的字符互广,可以對(duì)字符進(jìn)行重新排列,并替換k個(gè)字符卧土,是否可以構(gòu)成回文字符串惫皱;
  2. 要檢測(cè)是不是回文字符串,我們就得知道當(dāng)前截取到的字符串的組成(字母的種類及個(gè)數(shù))尤莺;那么旅敷,自然而然的可以想到使用前綴和的方式:我們可以遍歷原字符串s,并記錄在頭開始到每個(gè)字符位置的字符串的字母狀態(tài)(字母的種類及個(gè)數(shù))缝裁;用后一個(gè)字母狀態(tài)減去前一個(gè)字母狀態(tài)扫皱,就可以得到截取部分的字母狀態(tài)了;
  3. 得到了字母的組成捷绑,那么如何判斷回文字符串呢韩脑?
    我們要對(duì)每種字母進(jìn)行分析,如果字母的個(gè)數(shù)是偶數(shù)粹污,那么在構(gòu)成回文字符串的時(shí)候段多,我們完全可以將這些字母均勻的放在回文字符串的兩邊;也就是說壮吩,偶數(shù)個(gè)的字母进苍,我們可以直接忽略對(duì)回文串的影響;
    如果字母的個(gè)數(shù)是奇數(shù)鸭叙,那么就要進(jìn)行具體的分析:
    如果奇數(shù)個(gè)的字母只有1個(gè)觉啊,仍然可以構(gòu)成回文串;
    如果奇數(shù)個(gè)的字母只有2個(gè)沈贝,需要修改1個(gè)字母才能構(gòu)成回文串杠人;
    如果奇數(shù)個(gè)的字母只有3個(gè),仍然是需要修改1個(gè)字母才能構(gòu)成回文串宋下;
    也就是說嗡善,如果奇數(shù)個(gè)的字母為n個(gè),需要修改2/n個(gè)字母才能構(gòu)成回文串学歧。
  4. 優(yōu)化:異或運(yùn)算
    在上述的步驟中罩引,我們統(tǒng)計(jì)了字母的種類及其個(gè)數(shù);其實(shí)枝笨,我們并不需要知道具體的數(shù)量袁铐,需要知道的是字母?jìng)€(gè)數(shù)的奇偶變化揭蜒;如果奇變奇、偶變偶昭躺,那么可能沒有變化忌锯,也有可能多了偶數(shù)個(gè)伪嫁,對(duì)回文串的構(gòu)成沒有影響领炫;如果是奇偶互變,那么肯定是發(fā)生了奇數(shù)個(gè)的變化张咳,統(tǒng)計(jì)變化的數(shù)量即可帝洪。
    另外,我們現(xiàn)在使用一個(gè)長(zhǎng)為26位的數(shù)組來存放了字母的個(gè)數(shù)脚猾,我們可以對(duì)此進(jìn)行優(yōu)化:將數(shù)組壓縮為一個(gè)二進(jìn)制數(shù)進(jìn)行存放葱峡。
    那么在遍歷字符串s,如何修改某個(gè)字母的個(gè)數(shù)狀態(tài)(現(xiàn)在只存奇偶)呢龙助?
    修改a出現(xiàn)的數(shù)量時(shí)砰奕,與二進(jìn)制數(shù)1進(jìn)行異或;
    修改b出現(xiàn)的數(shù)量時(shí)提鸟,與二進(jìn)制數(shù)10進(jìn)行異或军援;
    修改c出現(xiàn)的數(shù)量時(shí),與二進(jìn)制數(shù)100進(jìn)行異或称勋;
    修改d出現(xiàn)的數(shù)量時(shí)胸哥,與二進(jìn)制數(shù)1000進(jìn)行異或;
    以此類推...

代碼示例(JAVA)

初步代碼赡鲜,使用前綴和

class Solution {
    public List<Boolean> canMakePaliQueries(String s, int[][] queries) {
        int len = s.length();
        int[][] arr = new int[len + 1][26];
        // 統(tǒng)計(jì)前綴和
        for (int i = 0; i < len; i++) {
            char c = s.charAt(i);
            arr[i + 1] = arr[i].clone();
            arr[i + 1][c - 'a']++;
        }

        List<Boolean> res = new ArrayList<>();
        for (int[] query : queries) {
            int left = query[0], right = query[1], k = query[2];
            // 統(tǒng)計(jì)奇數(shù)的數(shù)量
            int count = 0;
            for (int i = 0; i < 26; i++) {
                if ((arr[right + 1][i] - arr[left][i]) % 2 != 0) {
                    count++;
                }
            }
            // 添加結(jié)果
            res.add(count / 2  <= k);
        }
        
        return res;
    }
}

優(yōu)化:前綴和+異或運(yùn)算

class Solution {
    public List<Boolean> canMakePaliQueries(String s, int[][] queries) {
        int len = s.length();
        int[] arr = new int[len + 1];
        // 統(tǒng)計(jì)前綴和
        for (int i = 0; i < len; i++) {
            int b = 1 << (s.charAt(i) - 'a');
            arr[i + 1] = arr[i] ^ b;
        }

        List<Boolean> res = new ArrayList<>();
        for (int[] query : queries) {
            int left = query[0], right = query[1], k = query[2];
            // 統(tǒng)計(jì)奇數(shù)的數(shù)量
            int count = Integer.bitCount(arr[right + 1] ^ arr[left]);
            // 添加結(jié)果
            res.add(count / 2 <= k);
        }

        return res;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末空厌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子银酬,更是在濱河造成了極大的恐慌嘲更,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件揩瞪,死亡現(xiàn)場(chǎng)離奇詭異赋朦,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)壮韭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門北发,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人喷屋,你說我怎么就攤上這事琳拨。” “怎么了屯曹?”我有些...
    開封第一講書人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵狱庇,是天一觀的道長(zhǎng)惊畏。 經(jīng)常有香客問我,道長(zhǎng)密任,這世上最難降的妖魔是什么颜启? 我笑而不...
    開封第一講書人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮浪讳,結(jié)果婚禮上缰盏,老公的妹妹穿的比我還像新娘。我一直安慰自己淹遵,他們只是感情好口猜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著透揣,像睡著了一般济炎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辐真,一...
    開封第一講書人閱讀 51,727評(píng)論 1 305
  • 那天须尚,我揣著相機(jī)與錄音,去河邊找鬼侍咱。 笑死耐床,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的放坏。 我是一名探鬼主播咙咽,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼淤年!你這毒婦竟也來了钧敞?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤麸粮,失蹤者是張志新(化名)和其女友劉穎溉苛,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體弄诲,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡愚战,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了齐遵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寂玲。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖梗摇,靈堂內(nèi)的尸體忽然破棺而出拓哟,到底是詐尸還是另有隱情,我是刑警寧澤伶授,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布断序,位于F島的核電站流纹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏违诗。R本人自食惡果不足惜漱凝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望诸迟。 院中可真熱鬧茸炒,春花似錦、人聲如沸亮蒋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)慎玖。三九已至,卻和暖如春笛粘,著一層夾襖步出監(jiān)牢的瞬間趁怔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工薪前, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留润努,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓示括,卻偏偏與公主長(zhǎng)得像铺浇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子垛膝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容