Medium
题目描述
给你一个下标从 0 开始的整数数组 mapping,它表示一个混乱十进制系统的映射规则。mapping[i] = j 表示这个系统中数字 i 应该映射为数字 j。
一个整数的映射值是将整数中每个数字 i 替换为 mapping[i] 得到的新整数,对于所有 0 <= i <= 9。
同时给你另一个整数数组 nums。请你将数组 nums 中的数字按照它们的映射值 非递减顺序 排序后返回。
注意:
- 映射值相同的元素应该按照它们在输入中的相同相对顺序出现。
nums的元素应该按照它们的映射值排序,而不是被映射值替换。
示例 1:
输入:mapping = [8,9,4,0,2,1,3,5,7,6], nums = [991,338,38]
输出:[338,38,991]
解释:
将数字 991 按如下规则映射:
1. mapping[9] = 6,所以所有数字 9 都变成 6。
2. mapping[1] = 9,所以所有数字 1 都变成 9。
因此,991 的映射值是 669。
338 映射为 007,即去掉前导零后的 7。
38 映射为 07,去掉前导零后也是 7。
由于 338 和 38 有相同的映射值,它们应该保持相同的相对顺序,所以 338 在 38 前面。
因此,排序后的数组是 [338,38,991]。
示例 2:
输入:mapping = [0,1,2,3,4,5,6,7,8,9], nums = [789,456,123]
输出:[123,456,789]
解释:789 映射为 789,456 映射为 456,123 映射为 123。因此,排序后的数组是 [123,456,789]。
提示:
mapping.length == 100 <= mapping[i] <= 9mapping[i]的所有值都是唯一的1 <= nums.length <= 3 * 10^40 <= nums[i] < 10^9
解题思路
这道题的核心思路是先将每个数字按照映射规则转换,然后进行稳定排序。
解题步骤:
数字映射转换:对于每个数字,我们需要逐位提取数字,然后根据mapping数组进行映射。可以通过不断除以10来提取每一位数字,然后用mapping数组进行转换。
构建排序键值对:为了保持相同映射值的元素的相对顺序(稳定排序),我们需要记录原始索引。创建一个包含(映射值, 原始索引, 原始数字)的三元组数组。
排序:根据映射值进行排序,如果映射值相同则按原始索引排序,这样就能保证稳定性。
提取结果:从排序后的三元组中提取原始数字。
时间复杂度分析:
- 映射转换:O(n * log(max_num)),其中n是nums长度
- 排序:O(n * log(n))
- 总体:O(n * log(n))
这种方法简单直观,通过预处理映射值然后利用稳定排序的特性来解决问题。
代码实现
class Solution {
public:
vector<int> sortJumbled(vector<int>& mapping, vector<int>& nums) {
vector<tuple<long long, int, int>> mapped_nums;
for (int i = 0; i < nums.size(); i++) {
long long mapped_value = getMappedValue(nums[i], mapping);
mapped_nums.push_back({mapped_value, i, nums[i]});
}
sort(mapped_nums.begin(), mapped_nums.end());
vector<int> result;
for (auto& [mapped_val, idx, original] : mapped_nums) {
result.push_back(original);
}
return result;
}
private:
long long getMappedValue(int num, vector<int>& mapping) {
if (num == 0) return mapping[0];
long long mapped = 0;
long long multiplier = 1;
while (num > 0) {
int digit = num % 10;
mapped += mapping[digit] * multiplier;
multiplier *= 10;
num /= 10;
}
return mapped;
}
};
class Solution:
def sortJumbled(self, mapping: List[int], nums: List[int]) -> List[int]:
def get_mapped_value(num):
if num == 0:
return mapping[0]
mapped = 0
multiplier = 1
while num > 0:
digit = num % 10
mapped += mapping[digit] * multiplier
multiplier *= 10
num //= 10
return mapped
mapped_nums = []
for i, num in enumerate(nums):
mapped_value = get_mapped_value(num)
mapped_nums.append((mapped_value, i, num))
mapped_nums.sort()
return [original for mapped_val, idx, original in mapped_nums]
public class Solution {
public int[] SortJumbled(int[] mapping, int[] nums) {
var mappedNums = new List<(long mappedValue, int index, int original)>();
for (int i = 0; i < nums.Length; i++) {
long mappedValue = GetMappedValue(nums[i], mapping);
mappedNums.Add((mappedValue, i, nums[i]));
}
mappedNums.Sort();
int[] result = new int[nums.Length];
for (int i = 0; i < mappedNums.Count; i++) {
result[i] = mappedNums[i].original;
}
return result;
}
private long GetMappedValue(int num, int[] mapping) {
if (num == 0) return mapping[0];
long mapped = 0;
long multiplier = 1;
while (num > 0) {
int digit = num % 10;
mapped += mapping[digit] * multiplier;
multiplier *= 10;
num /= 10;
}
return mapped;
}
}
var sortJumbled = function(mapping, nums) {
const mapNumber = (num) => {
return parseInt(num.toString().split('').map(digit => mapping[parseInt(digit)]).join(''));
};
return nums.map((num, index) => ({ num, mapped: mapNumber(num), index }))
.sort((a, b) => a.mapped - b.mapped || a.index - b.index)
.map(item => item.num);
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n × log(n)) | 其中 n 是 nums 的长度,主要消耗在排序操作上 |
| 空间复杂度 | O(n) | 需要额外的数组存储映射值和索引信息 |
相关题目
- . Map Sum Pairs (Medium)