5720:使字符串有序的最少操作次数

This commit is contained in:
huangge1199@hotmail.com 2021-04-18 10:28:42 +08:00
parent a218effc0c
commit bd929e7d8d
3 changed files with 172 additions and 1 deletions

View File

@ -0,0 +1,117 @@
//给你一个字符串 s 下标从 0 开始你需要对 s 执行以下操作直到它变为一个有序字符串
//
//
// 找到 最大下标 i 使得 1 <= i < s.length s[i] < s[i - 1]
// 找到 最大下标 j 使得 i <= j < s.length 且对于所有在闭区间 [i, j] 之间的 k 都有 s[k] < s[i - 1]
// 交换下标为 i - 1 j 处的两个字符
// 将下标 i 开始的字符串后缀反转
//
//
// 请你返回将字符串变成有序的最少操作次数由于答案可能会很大请返回它对 109 + 7 取余 的结果
//
//
//
// 示例 1
//
// 输入s = "cba"
//输出5
//解释模拟过程如下所示
//操作 1i=2j=2交换 s[1] s[2] 得到 s="cab" 然后反转下标从 2 开始的后缀字符串得到 s="cab"
//操作 2i=1j=2交换 s[0] s[2] 得到 s="bac" 然后反转下标从 1 开始的后缀字符串得到 s="bca"
//操作 3i=2j=2交换 s[1] s[2] 得到 s="bac" 然后反转下标从 2 开始的后缀字符串得到 s="bac"
//操作 4i=1j=1交换 s[0] s[1] 得到 s="abc" 然后反转下标从 1 开始的后缀字符串得到 s="acb"
//操作 5i=2j=2交换 s[1] s[2] 得到 s="abc" 然后反转下标从 2 开始的后缀字符串得到 s="abc"
//
//
// 示例 2
//
// 输入s = "aabaa"
//输出2
//解释模拟过程如下所示
//操作 1i=3j=4交换 s[2] s[4] 得到 s="aaaab" 然后反转下标从 3 开始的后缀字符串得到 s="aaaba"
//操作 2i=4j=4交换 s[3] s[4] 得到 s="aaaab" 然后反转下标从 4 开始的后缀字符串得到 s="aaaab"
//
//
// 示例 3
//
// 输入s = "cdbea"
//输出63
//
// 示例 4
//
// 输入s = "leetcodeleetcodeleetcode"
//输出982157772
//
//
//
//
// 提示
//
//
// 1 <= s.length <= 3000
// s 只包含小写英文字母
//
// Related Topics 数学 字符串
// 👍 1 👎 0
package leetcode.editor.cn;
//5720:使字符串有序的最少操作次数
public class MinimumNumberOfOperationsToMakeStringSorted{
public static void main(String[] args) {
//测试代码
Solution solution = new MinimumNumberOfOperationsToMakeStringSorted().new Solution();
}
//力扣代码
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
public int makeStringSorted(String s) {
int mode = 1000000007;
long[] mul = new long[3000];
long[] div = new long[3000];
mul[0] = 1;
for (int i = 1; i < 3000; i++) {
mul[i] = mul[i - 1] * i % mode;
}
for (int i = 0; i < 3000; i++) {
div[i] = power(mul[i], mode - 2, mode);
}
int[] cnt = new int[26];
int length = s.length();
for (int i = 0; i < length; i++) {
cnt[s.charAt(i) - 'a']++;
}
long res = 0;
for (int i = 0; i < length; i++) {
int ch = s.charAt(i) - 'a';
for (int j = 0; j < ch; j++) {
if (cnt[j] == 0) {
continue;
}
cnt[j]--;
long num = mul[length - 1 - i];
for (int k = 0; k < 26; k++) {
num = num * div[cnt[k]] % mode;
}
res = (res + num) % mode;
cnt[j]++;
}
cnt[ch]--;
}
return (int) res;
}
private long power(long num, int index, int mode) {
if (index == 0) {
return 1;
}
long res = power(num, index / 2, mode);
res = res * res % mode;
if (index % 2 == 1) {
res = res * num % mode;
}
return res;
}
}
//leetcode submit region end(Prohibit modification and deletion)
}

View File

@ -0,0 +1,54 @@
<p>给你一个字符串 <code>s</code> <strong>下标从 0 开始</strong>)。你需要对 <code>s</code> 执行以下操作直到它变为一个有序字符串:</p>
<ol>
<li>找到 <strong>最大下标</strong> <code>i</code> ,使得 <code>1 &lt;= i &lt; s.length</code> 且 <code>s[i] &lt; s[i - 1]</code> 。</li>
<li>找到 <strong>最大下标</strong> <code>j</code> ,使得 <code>i &lt;= j &lt; s.length</code> 且对于所有在闭区间 <code>[i, j]</code> 之间的 <code>k</code> 都有 <code>s[k] &lt; s[i - 1]</code> 。</li>
<li>交换下标为 <code>i - 1</code> 和 <code>j</code> 处的两个字符。</li>
<li>将下标 <code>i</code> 开始的字符串后缀反转。</li>
</ol>
<p>请你返回将字符串变成有序的最少操作次数。由于答案可能会很大,请返回它对 <code>10<sup>9</sup> + 7</code> <strong>取余</strong> 的结果。</p>
<p> </p>
<p><strong>示例 1</strong></p>
<pre><b>输入:</b>s = "cba"
<b>输出:</b>5
<b>解释:</b>模拟过程如下所示:
操作 1i=2j=2。交换 s[1] 和 s[2] 得到 s="cab" ,然后反转下标从 2 开始的后缀字符串,得到 s="cab" 。
操作 2i=1j=2。交换 s[0] 和 s[2] 得到 s="bac" ,然后反转下标从 1 开始的后缀字符串,得到 s="bca" 。
操作 3i=2j=2。交换 s[1] 和 s[2] 得到 s="bac" ,然后反转下标从 2 开始的后缀字符串,得到 s="bac" 。
操作 4i=1j=1。交换 s[0] 和 s[1] 得到 s="abc" ,然后反转下标从 1 开始的后缀字符串,得到 s="acb" 。
操作 5i=2j=2。交换 s[1] 和 s[2] 得到 s="abc" ,然后反转下标从 2 开始的后缀字符串,得到 s="abc" 。
</pre>
<p><strong>示例 2</strong></p>
<pre><b>输入:</b>s = "aabaa"
<b>输出:</b>2
<b>解释:</b>模拟过程如下所示:
操作 1i=3j=4。交换 s[2] 和 s[4] 得到 s="aaaab" ,然后反转下标从 3 开始的后缀字符串,得到 s="aaaba" 。
操作 2i=4j=4。交换 s[3] 和 s[4] 得到 s="aaaab" ,然后反转下标从 4 开始的后缀字符串,得到 s="aaaab" 。
</pre>
<p><strong>示例 3</strong></p>
<pre><b>输入:</b>s = "cdbea"
<b>输出:</b>63</pre>
<p><strong>示例 4</strong></p>
<pre><b>输入:</b>s = "leetcodeleetcodeleetcode"
<b>输出:</b>982157772
</pre>
<p> </p>
<p><strong>提示:</strong></p>
<ul>
<li><code>1 &lt;= s.length &lt;= 3000</code></li>
<li><code>s</code> 只包含小写英文字母。</li>
</ul>
<div><div>Related Topics</div><div><li>数学</li><li>字符串</li></div></div>\n<div><li>👍 1</li><li>👎 0</li></div>

File diff suppressed because one or more lines are too long