【做题也是一场游戏】1528. 重新排列字符串

379 阅读2分钟

题目地址

1528. 重新排列字符串

题目描述

给你一个字符串 s 和一个 长度相同 的整数数组 indices 。

请你重新排列字符串 s ,其中第 i 个字符需要移动到 indices[i] 指示的位置。

返回重新排列后的字符串。

示例 1:

输入:s = "codeleet", indices = [4,5,6,7,0,2,1,3]
输出:"leetcode"
解释:"codeleet" 重新排列后变为 "leetcode"

示例 2:

输入:s = "abc", indices = [0,1,2]
输出:"abc"
解释:重新排列后,每个字符都还留在原来的位置上。

示例 3:

输入:s = "aiohn", indices = [3,1,4,2,0]
输出:"nihao"

示例 4:

输入:s = "aaiougrt", indices = [4,0,2,6,7,3,1,5]
输出:"arigatou"

示例 5:

输入:s = "art", indices = [1,0,2]
输出:"rat"

提示:

  • s.length == indices.length == n
  • 1 <= n <= 100
  • s 仅包含小写英文字母。
  • 0 <= indices[i] < n
  • indices 的所有的值都是唯一的(也就是说,indices 是整数 0 到 n - 1 形成的一组排列)。

题解

1. 新建个数组,直接映射

代码如下:

class Solution {
    public String restoreString(String s, int[] indices) {
        if (s == null || s.isEmpty()) {
            return s;
        }

        char[] charArray = s.toCharArray();
        char[] targetArray = new char[charArray.length];
        for (int i = 0; i < charArray.length; i++) {
            targetArray[indices[i]] = charArray[i];
        }
        return new String(targetArray);
    }
}

时间复杂度: O(n)

空间复杂度: O(n)

2. 原地修改

(从官网copy的解释)

直观的想法是:对于下标 ii,需要把字符 s[i]s[i] 移动到 indices[i]\textit{indices}[i] 的位置上;然后,我们前进到位置 indices[i]\textit{indices}[i],并将字符 s[indices[i]]s[\textit{indices}[i]] 移动到 indices[indices[i]]\textit{indices}[\textit{indices}[i]] 的位置上。类似的过程以此类推,直到最终回到起点 ii。此时,封闭路径 iindices[i]indices[indices[i]]...ii \to \textit{indices}[i] \to \textit{indices}[\textit{indices}[i]] \to ... \to i 上的所有字符,都已经被设置成正确的值。

我们只要找到 indices[i]\textit{indices}[i] 中所有这样的封闭路径,并进行对应的移动操作,就能够得到最终的答案。

这样做有一个小小的问题:当在第二步试图把字符 s[indices[i]]s[\textit{indices}[i]] 移动到 indices[indices[i]]\textit{indices}[\textit{indices}[i]] 的位置上时,会发现字符 s[indices[i]]s[\textit{indices}[i]] 已经在第一步被覆写了。因此,在每一步移动前,需要先额外记录目标位置处字符的原有值。

另一个隐含的问题是如何避免处理重复的封闭路径。为了解决此问题,我们每处理一个封闭路径,就将该路径上的 indices\textit{indices} 数组的值设置成下标自身。这样,当某个封闭路径被处理完毕后,扫描到该路径的另一个下标时,就不会处理该封闭路径了。

代码如下

class Solution {
    public String restoreString(String s, int[] indices) {
        if (s == null || s.isEmpty()) {
            return s;
        }

        char[] charArray = s.toCharArray();

        for (int i = 0; i < indices.length; i++) {
            if (indices[i] != i) {
                char ch = charArray[i]; 
                int index = indices[i];
                while (index != i) {
                    char tempChar = charArray[index];
                    charArray[index] = ch;
                    ch = tempChar;
                    
                    int tempIndex = indices[index];
                    indices[index] = index;
                    index = tempIndex; 
                    
                }
                
                charArray[i] = ch;
                indices[i] = i;
            }
        }
        
        return new String(charArray);
    }
}

时间复杂度: O(n)

空间复杂度: O(1)