共计 2074 个字符,预计需要花费 6 分钟才能阅读完成。
题目形容
这是 LeetCode 上的 899. 有序队列 ,难度为 艰难。
Tag :「结构」、「最小表示法」
给定一个字符串 s
和一个整数 k
。你能够从 s
的前 k
个字母中抉择一个,并把它加到字符串的开端。
返回 在利用上述步骤的任意数量的挪动后,字典上最小的字符串。
示例 1:
输出:s = "cba", k = 1
输入:"acb"
解释:在第一步中,咱们将第一个字符(“c”)挪动到最初,取得字符串“bac”。在第二步中,咱们将第一个字符(“b”)挪动到最初,取得最终后果“acb”。
示例 2:
输出:s = "baaca", k = 3
输入:"aaabc"
解释:在第一步中,咱们将第一个字符(“b”)挪动到最初,取得字符串“aacab”。在第二步中,咱们将第三个字符(“c”)挪动到最初,取得最终后果“aaabc”。
提醒:
- $1 <= k <= S.length <= 1000$
s
只由小写字母组成。
最小表示法
当 $k > 1$ 时,咱们可能结构出任意的字符串计划,因而当 $k > 1$ 时,咱们能够间接通过对字符串排序来失去答案,复杂度为 $O(n\log{n})$。
当 $k = 1$ 时,咱们共有 $n$ 种候选计划(将字符串 s
看作一个首尾相接的循环字符串,共有 $n$ 个终点可枚举),枚举过程中须要与以后最优的计划进行比拟,比拟复杂度为 $O(n)$,因而整体复杂度为 $O(n^2)$。
上述的做法曾经能够通过本题,能够看出瓶颈在于对 $k = 1$ 的解决。
而实际上,对于给定字符串 s
,求其循环同构的所有计划中字典序最小的计划,能够应用「最小表示法」来做,复杂度为 $O(n)$。
最小表示法将「计划比拟」与「结构更优计划」进行联合:假如咱们以后有两字符串 a
和 b
须要进行比拟,其均为原串 s
的循环同构具体计划。假如 a
和 b
别离对应了原串下标为 i
和 j
的具体计划,且假如两字符串前 $k$ 个字符均雷同。
当两字符串第一个不同的字符大小关系为 $cs[i + k] > cs[j + k]$ 时,能够发现在下标范畴 $idx \in [i, i + k]$ 作为终点的新计划 a'
必然不会是最优计划,即必然存在下标范畴 $idx – i + j$ 作为终点的新计划 b'
比其更优,因而咱们能够间接从 $i + k + 1$ 地位结构新的更优计划,并与 b
再次比拟。而 $cs[i + k] < cs[j + k]$ 的剖析同理。
更为直白的表述为:别离从
i
和j
作为终点的字符串a
和b
,其前 $k$ 个字符雷同,而当 $cs[i + k] > cs[j + k]$ 时,咱们能够明确「以 $i + p$ 为终点的字符串」必不可能比「以 $j + p$ 为终点的字符串」更优,其中 $p \in [0, k]$。
Java 代码:
class Solution {public String orderlyQueue(String s, int _k) {char[] cs = s.toCharArray();
if (_k == 1) {
int i = 0, j = 1, k = 0, n = cs.length;
while (i < n && j < n && k < n) {char a = cs[(i + k) % n], b = cs[(j + k) % n];
if (a == b) k++;
else {if (a > b) i += k + 1;
else j += k + 1;
if (i == j) i++;
k = 0;
}
}
i = Math.min(i, j);
return s.substring(i) + s.substring(0, i);
} else {Arrays.sort(cs);
return String.valueOf(cs);
}
}
}
TypeScript 代码:
function orderlyQueue(s: string, _k: number): string {if (_k == 1) {
let i = 0, j = 1, k = 0, n = s.length
while (i < n && j < n && k < n) {const a = s[(i + k) % n], b = s[(j + k) % n]
if (a == b) k++;
else {if (a > b) i += k + 1
else j += k + 1
if (i == j) i++
k = 0
}
}
i = Math.min(i, j)
return s.substring(i) + s.substring(0, i)
} else {return [...s].sort().join('');
}
};
- 工夫复杂度:当 $k = 1$ 时,复杂度为 $O(n)$;当 $k > 1$ 时,复杂度为 $O(n\log{n})$
- 空间复杂度:当 $k > 1$ 时,须要应用额定的排序空间 $O(\log{n})$
最初
这是咱们「刷穿 LeetCode」系列文章的第 No.899
篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,局部是有锁题,咱们将先把所有不带锁的题目刷完。
在这个系列文章外面,除了解说解题思路以外,还会尽可能给出最为简洁的代码。如果波及通解还会相应的代码模板。
为了不便各位同学可能电脑上进行调试和提交代码,我建设了相干的仓库:https://github.com/SharingSou…。
在仓库地址里,你能够看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其余优选题解。
更多更全更热门的「口试 / 面试」相干材料可拜访排版精美的 合集新基地 🎉🎉
本文由 mdnice 多平台公布