🔗 🟡 3106. Lexicographically Smallest String After Operations With Constraint 1515

tags: Weekly Contest 392 貪心(Greedy) 字串(String)

題意

給定一個字串 ss 和一個整數 kk

定義兩個長度相同為 nn 的字串 s1s_1s2s_2 之間的距離 distance(s1,s2)\text{distance}(s_1, s_2) 為:

  • 將字元 'a''z' 視為按 循環 順序排列。
  • 對於區間 [0,n1][0, n - 1] 中的 ii ,計算所有「 s1[i]s_1[i]s2[i]s_2[i] 之間 最小距離 」的

例如,distance("ab","cd")==4\text{distance}("ab", "cd") == 4 ,且 distance("a","z")==1\text{distance}("a", "z") == 1

你可以對字串 ss 進行 任意次 操作。在每次操作中,可以將 ss 中的一個字母 改變任意 其他小寫英文字母。

返回一個字串 tt,表示在執行一些操作後,你可以得到的 字典序最小 的字串,且滿足 distance(s,t)k\text{distance}(s, t) \leq k

約束條件

  • 1s.length1001 \leq s.length \leq 100
  • 0k20000 \leq k \leq 2000

思路:貪心(Greedy)

這個問題的關鍵在於找到一個字典序最小的字串 tt,使得 tt 與給定字串 ss 的距離不超過 kk。我們可以採用 貪心(Greedy) 策略來解決這個問題。具體來說,我們的目標是盡可能地將 ss 中的字元改變為 a\text{a},因為 a\text{a} 是字典序最小的字元。

而將 tt 中的非 a\text{a} 的字元改變為 a\text{a} ,會增加 sstt 的距離,但根據題意,距離不能超過 kk

  • 因此同樣基於貪心的思路,我們可以優先修改 ss 中前面的字元,直到增加的距離會超過 kk 為止。
  • 當能夠修改的距離不足以修改為 a\text{a} 時,則需要往前修改 kk 個字元。

具體步驟如下:

  1. 遍歷字串 ss:從頭到尾遍歷字串 ss,對於每一個字元 chch,計算將其改變為 ‘a’ 所需的距離 disdis
  2. 計算距離 disdis:這裡的距離 disdis 是指將 chch 改變為 ‘a’ 所需的步數。由於字元是循環排列的,我們需要考慮兩種情況:
    • chch 到 ‘a’ 的直接距離。
    • chch 到 ‘z’ 再到 ‘a’ 的距離(即循環距離)。
      我們取這兩種情況中的最小值作為 disdis
  3. 檢查剩餘額度 kk:如果 disdis 大於剩餘的額度 kk,則表示我們無法將 chch 改變為 ‘a’。此時,我們需要將 chch 改變為一個能夠滿足剩餘額度 kk 的字元,然後結束循環。
  4. 更新字串 ss 和剩餘額度 kk:如果 disdis 小於等於 kk,則將 chch 改變為 ‘a’,並更新剩餘額度 kk

複雜度分析

  • 時間複雜度:O(n)\mathcal{O}(n),其中 nn 是字串 ss 的長度。我們只需要遍歷一次字串 ss
  • 空間複雜度:O(n)\mathcal{O}(n)O(1)\mathcal{O}(1),取決於能不能直接改變字串 ss
1
2
3
4
5
6
7
8
9
10
11
class Solution:
def getSmallestString(self, s: str, k: int) -> str:
s = list(s)
for i, ch in enumerate(s):
dis = min(ord(ch) - ord('a'), ord('z') - ord(ch) + 1)
if dis > k: # 不足以改成 'a',就往前改
s[i] = chr(ord(ch) - k)
break
s[i] = 'a'
k -= dis
return ''.join(s)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public:
string getSmallestString(string s, int k) {
for (int i = 0; i < s.size(); i++) {
int dis = min(s[i] - 'a', 'z' - s[i] + 1);
if (dis > k) {
s[i] = s[i] - k;
break;
}
s[i] = 'a';
k -= dis;
}
return s;
}
};

寫在最後

Cover photo is remixed from @吃肥皂泡泡, thanks for their work!