题目描述
由范围 [0,n]
内所有整数组成的 n + 1
个整数的排列序列可以表示为长度为 n
的字符串 s
,其中:
- 如果
perm[i] < perm[i + 1]
,那么s[i] == 'I'
- 如果
perm[i] > perm[i + 1]
,那么s[i] == 'D'
给定一个字符串 s ,重构排列 perm 并返回它。如果有多个有效排列perm,则返回其中 任何一个 。
示例 1:
输入:s = “IDID”
输出:[0,4,1,3,2]
示例 2:
输入:s = “III”
输出:[0,1,2,3]
示例 3:
输入:s = “DDI”
输出:[3,2,0,1]
提示:
- 1 <= s.length <= 105
- s 只包含字符 “I” 或 “D”
答案
我的答案
class Solution {
public int[] diStringMatch(String s) {
int[] arr = new int[s.length()+1];
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
}
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i)=='D'){
int x = i;
while (i < s.length()&&s.charAt(i)=='D'){
i++;
}
sort(arr,x,i);
}
}
return arr;
}
public void sort(int[] arr,int begin,int end){
while (begin<end){
int temp = arr[begin];
arr[begin] = arr[end];
arr[end] = temp;
begin++;
end--;
}
}
}
官方答案
方法一:贪心
思路
考虑 perm[0] 的值,根据题意:
- 如果 s[0]=‘I’,那么令 perm[0]=0,则无论 perm[1] 为何值都满足 perm[0]<perm[1];
- 如果 s[0]=‘D’,那么令 perm[0]=n,则无论 perm[1] 为何值都满足 perm[0]>perm[1];
确定好 perm[0] 后,剩余的 n−1 个字符和 n 个待确定的数就变成了一个和原问题相同,但规模为 n-1 的问题。因此我们可以继续按照上述方法确定 perm[1]:如果 s[1]=‘I’,那么令 perm[1] 为剩余数字中的最小数;如果 s[1]=‘D’,那么令 perm[1] 为剩余数字中的最大数。如此循环直至剩下一个数,填入 perm[n] 中。
代码实现时,由于每次都选择的是最小数和最大数,我们可以用两个变量 lo 和 hi 表示当前剩余数字中的最小数和最大数。
代码
class Solution {
public int[] diStringMatch(String s) {
int n = s.length(), lo = 0, hi = n;
int[] perm = new int[n + 1];
for (int i = 0; i < n; ++i) {
perm[i] = s.charAt(i) == 'I' ? lo++ : hi--;
}
perm[n] = lo; // 最后剩下一个数,此时 lo == hi
return perm;
}
}
复杂度分析
-
时间复杂度:O(n),其中 n 是字符串 s 的长度。
-
空间复杂度:O(1),返回值不计入空间复杂度。