一、题目
题目:
给定一个乱序的数组,删除所有的重复元素,使得每个元素只出现一次,并且按照出现的次数从高到低进行排序,相同出现次数按照第一次出现顺序进行先后排序。
备注: 数组大小不超过100 数组元素值大小不超过100。
输入:
一个数组
输出:
去重排序后的数组
示例:
输入:
1,3,3,3,2,4,4,4,5
输出:
3,4,1,2,5
二、题解
基本思路是通过 Map 来记录每个元素出现的次数和记录每个元素第一次出现的位置,先按 map 的 value 降序排序,再按出现位置升序排序。
Python 代码比起 Java 要简洁一些。特地对比了一下。
package org.stone.study.algo.ex202411;
import java.util.*;
public class DedupAndSort {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 1,3,3,3,2,4,4,4,5
String[] arr = scanner.nextLine().split(",");
// 从字符串数组转化为整数数组
int[] nums = Arrays.stream(arr).mapToInt(Integer::parseInt).toArray();
int[] res = dedupAndSort(nums);
System.out.println(Arrays.toString(res));
}
public static int[] dedupAndSort(int[] nums) {
int n = nums.length;
if(n == 0) {
return new int[0];
}
// 统计每个数字出现的次数和第一次出现的位置
HashMap<Integer, Integer> cntMap = new HashMap<>();
HashMap<Integer, Integer> firstOccurMap = new HashMap<>();
for(int i = 0; i < n; i++) {
cntMap.put(nums[i], cntMap.getOrDefault(nums[i], 0) + 1);
firstOccurMap.putIfAbsent(nums[i], i);
}
// 对 map 按 value 降序排序,再按 key 在数组中的位置升序排序
List<Integer> keyList = new ArrayList<>(cntMap.keySet());
keyList.sort((a, b) -> {
int freqDiff = cntMap.get(b) - cntMap.get(a);
if(freqDiff == 0) {
return firstOccurMap.get(a) - firstOccurMap.get(b);
} else {
return freqDiff;
}
});
// 从 List 转化为数组
return keyList.stream().mapToInt(Integer::intValue).toArray();
}
}
from collections import defaultdict
def sort_by_frequency(nums):
first_occurance = {}
freq = defaultdict(int)
for index, num in enumerate(nums):
freq[num] += 1
if num not in first_occurance:
first_occurance[num] = index
# freq + first_occurance 转化为 list
freq_list = [(num, freq[num], first_occurance[num]) for num in freq]
# 按照 freq 降序,first_occurance 升序排序
freq_list.sort(key=lambda x: (-x[1], x[2]))
# 只返回 num
return [x[0] for x in freq_list]
if __name__ == "__main__":
# 1,3,3,3,2,4,4,4,5
nums = list(map(int, input().split(",")))
# 3,4,1,2,5
print(sort_by_frequency(nums))