📜  M操作后按字典顺序最小的字符串(1)

📅  最后修改于: 2023-12-03 15:17:49.465000             🧑  作者: Mango

M操作后按字典顺序最小的字符串

简介

在字符串S中执行一些操作。我们可以执行任意次数的以下两个操作:

  1. 选择字符串S中任意的字符并将其更改为任何其他小写英文字母。
  2. 将字符串S中任意一个字符都可以添加任意数量的相同字符。

在执行任意数量的操作后,返回使S成为字典顺序最小的字符串的字典序。

示例 1:

输入:S = "cba", indexes = [0,1,2], sources = ["a","b","c"], targets = ["x","y","z"]
输出:"axb"

解释:
在操作之前,S = "cba"
操作 1:我们选择位置 i=2,并将字符 c 更改为 z 。然后,S = "zbax"。
操作 2:我们选择位置 i=2,并将字符 b 更改为 y 。然后,S = "zyax"。
操作 2:我们选择位置 i=1,并将字符 y 更改为 x 。然后,S = "zxax"。
方法

为了使排列最小,我们需要按照以下步骤执行操作:

首先,将每个要替换的字符作为键,每个替换后的字符作为值存储在字典中。

接下来,从左到右遍历索引数组,并在索引中找到要替换的字符。

为了使S成为字典顺序最小的字符串,我们必须按照以下方式进行操作:

  1. 从左到右遍历索引数组,并尽可能少的修改目标字符串;
  2. 在进行替换操作时,我们必须尽可能使用要替换的最小字符。

为了这两个条件,我们可以利用贪心算法。

Python代码实现
class Solution:
    def findReplaceString(self, S: str, indexes: List[int], sources: List[str], targets: List[str]) -> str:
        dic = {i:v for i,v in zip(indexes, zip(sources, targets))}
        indexes.sort()
        for i in range(len(indexes)):
            if S.startswith(dic[indexes[i]][0], indexes[i]):
                S = S[:indexes[i]] + dic[indexes[i]][1] + S[indexes[i] + len(dic[indexes[i]][0]):]
                # 检查现在字符串中的每个字符,如果新字符比旧字符小,则替换新字符
                for j in range(i + 1, len(indexes)):
                    if indexes[j] > indexes[i] + len(dic[indexes[i]][1]) - 1: 
                        break
                    if S[indexes[j]] > dic[indexes[i]][1]:
                        S = S[:indexes[j]] + dic[indexes[i]][1] + S[indexes[j] + 1:]
        return S
Java代码实现
class Solution {
    public String findReplaceString(String S, int[] indexes, String[] sources, String[] targets) {
        HashMap<Integer, String[]> dic = new HashMap<>();
        for (int i = 0; i < indexes.length; i++) {
            dic.put(indexes[i], new String[]{sources[i], targets[i]});
        }
        Arrays.sort(indexes);
        for (int i = 0; i < indexes.length; i++) {
            int index = indexes[i];
            String[] sAndT = dic.get(index);
            String s = sAndT[0], t = sAndT[1];
            if (S.substring(index).startsWith(s)) {
                S = S.substring(0, index) + t + S.substring(index + s.length());
                // 检查现在字符串中的每个字符,如果新字符比旧字符小,则替换新字符
                for (int j = i + 1; j < indexes.length && indexes[j] <= index + t.length() - 1; j++) {
                    if (S.charAt(indexes[j]) > t.charAt(j + index - (index + s.length()))) {
                        S = S.substring(0, indexes[j]) + t.charAt(j + index - (index + s.length())) + S.substring(indexes[j] + 1);
                    }
                }
            }
        }
        return S;
    }
}
复杂度分析

时间复杂度:$O(nlogn)$,其中n是索引数组的长度。排序索引数组需要$O(nlogn)$的时间。对于每个索引,需要$O(k)$的时间,其中k是替换的字符串的最大长度,检查现有字符串中的每个字符并替换它们所需的时间为$O(k(n-i))$。

空间复杂度:$O(n)$,存储了索引数组长度的字典。