给你一个以行程长度编码压缩的整数列表 nums 。
考虑每对相邻的两个元素[freq, val] = [nums[2*i], nums[2*i+1]]
(其中 i >= 0 ),每一对都表示解压后子列表中有 freq 个值为 val 的元素,你需要从左到右连接所有子列表以生成解压后的列表。
请你返回解压后的列表。
思路:
原数两个元素为 1 组,第一个元素为出现的次数,第二个是出现的数值。首先计算出解压之后列表的长度,然后以步长为 2 来解压原列表。
1 | public int[] decompressRLElist(int[] nums) { |
时间复杂度:$o(n + m(num数组中所有下标为偶数的元素和))$
空间复杂度:$o(1)$
1365 有多少小于当前数字的数字
给你一个数组 nums,对于其中每个元素 nums[i],请你统计数组中比它小的所有数字的数目。
换而言之,对于每个 nums[i] 你必须计算出有效的 j 的数量,其中 j 满足 j != i 且 nums[j] < nums[i] 。
以数组形式返回答案。
思路:
依次循环,暴力破解
1 | public int[] smallerNumbersThanCurrent(int[] nums) { |
- 时间复杂度:$O(N^2)$,其中 N 为数组的长度。
- 空间复杂度:$O(1)$。注意我们不计算答案数组的空间占用。
方法二 快速排序
将数组排序,利用 Array.sort 实现 Comparator 从大到小排序。然后每个左边元素的个数就是小于他的个数。
但是原数组经过排序之后,顺序就会打乱,无法标记之前的位置。因此,一开始将原数组存储在一个二维数组里面,一列是数值,一列是下标。对二维数组的数值列进行排序。
1 | public int[] smallerNumbersThanCurrent(int[] nums) { |
举例,比如原始的 nums: [1,4,2,6,2]
,初试建立的 data 是[[1,0],[4,1],[2,2],[6,3],[2,4]]
,排序之后的data 是 [[1,0],[2,2],[2,4],[4,1],[6,3]]
,在 comparator 里面,compare 比较的是 每个 data 项里的第一个元素。
1 | ret |
方法三 计数排序
到数组元素的值域为[0,100]
,所以可以考虑建立一个频次数组 cnt ,cnt[i] 表示数字 i 出现的次数。那么对于数字 ii 而言,小于它的数目就为 cnt[0…i-1] 的总和。计数排序相比于冒泡排序这类(基于数字比较)速度快
1 | public int[] smallerNumbersThanCurrent(int[] nums) { |
时间复杂度:两次循环 2N + M $o(n+m)$.
空间复杂度:除了需要存储结果的数组外,还有一个统计数组。