Easy

题目描述

长度为 n 的字符串 s 可以表示一个由 n+1 个整数组成的排列 perm,其中排列包含范围 [0, n] 内的所有整数,表示规则如下:

  • 如果 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 <= 10^5
  • s[i] 是 ‘I’ 或 ‘D’

解题思路

解题思路

这是一个贪心算法的经典应用。我们需要构造一个包含 0 到 n 的排列,使其满足给定的 DI 字符串条件。

核心观察:

  • 当遇到 ‘I’ 时,我们希望当前位置的数字尽可能小,这样下一个位置就有更多选择空间
  • 当遇到 ‘D’ 时,我们希望当前位置的数字尽可能大,这样下一个位置就有更多选择空间

贪心策略: 维护两个指针 lowhigh,分别指向当前可用数字的最小值和最大值:

  • 遇到 ‘I’:使用 low,然后 low++
  • 遇到 ‘D’:使用 high,然后 high--
  • 最后一个位置:使用剩余的那个数字(此时 low == high

这种方法保证了每一步都做出最优选择,使得后续的选择空间最大化。

算法步骤:

  1. 初始化 low = 0, high = n
  2. 遍历字符串 s,根据当前字符选择使用 low 还是 high
  3. 添加最后一个数字

时间复杂度 O(n),空间复杂度 O(1)(不计算结果数组)。

代码实现

class Solution {
public:
    vector<int> diStringMatch(string s) {
        int n = s.length();
        vector<int> result;
        int low = 0, high = n;
        
        for (char c : s) {
            if (c == 'I') {
                result.push_back(low++);
            } else {
                result.push_back(high--);
            }
        }
        
        result.push_back(low);
        return result;
    }
};
class Solution:
    def diStringMatch(self, s: str) -> List[int]:
        n = len(s)
        result = []
        low, high = 0, n
        
        for c in s:
            if c == 'I':
                result.append(low)
                low += 1
            else:
                result.append(high)
                high -= 1
        
        result.append(low)
        return result
public class Solution {
    public int[] DiStringMatch(string s) {
        int n = s.Length;
        int[] result = new int[n + 1];
        int low = 0, high = n;
        int index = 0;
        
        foreach (char c in s) {
            if (c == 'I') {
                result[index++] = low++;
            } else {
                result[index++] = high--;
            }
        }
        
        result[index] = low;
        return result;
    }
}
var diStringMatch = function(s) {
    let low = 0, high = s.length;
    let result = [];
    
    for (let i = 0; i < s.length; i++) {
        if (s[i] === 'I') {
            result.push(low++);
        } else {
            result.push(high--);
        }
    }
    
    result.push(low);
    return result;
};

复杂度分析

复杂度类型
时间复杂度O(n)
空间复杂度O(1)

其中 n 是字符串 s 的长度。时间复杂度为 O(n) 因为需要遍历一次字符串;空间复杂度为 O(1) 不考虑结果数组的存储空间。

相关题目