0%

leetcode数组(简单02)

11/15 LeetCode三道简单数组题:1313、1398、1365。

  • 1313题加压缩编码。遍历一遍数组并不会增加时间复杂度,可以先遍历一遍找到目标数组的维度。
  • 1398 按既定顺序创建目标数组。因为不确定插入的位置,所以使用while循环,元素后移更新,以达到更高的效率。
  • 1365 有多少小于当前数字的数字。8大排序算法得学一学,技术和思路一样重要。官方还有第三种解法、二刷再搞。

1313 解压缩编码列表

题目描述

给你一个以行程长度编码压缩的整数列表 nums 。

考虑每对相邻的两个元素 [freq, val] = [nums[2i], nums[2i+1]] (其中 i >= 0 ),每一对都表示解压后子列表中有 freq 个值为 val 的元素,你需要从左到右连接所有子列表以生成解压后的列表。

请你返回解压后的列表。

  • 示例1:
1
2
3
4
5
输入:nums = [1,2,3,4]
输出:[2,4,4,4]
解释:第一对 [1,2] 代表着 2 的出现频次为 1,所以生成数组 [2]。
第二对 [3,4] 代表着 4 的出现频次为 3,所以生成数组 [4,4,4]。
最后将它们串联到一起 [2] + [4,4,4] = [2,4,4,4]。
  • 示例 2:
1
2
3
输入:nums = [1,1,2,3]
输出:[1,3,3]
来源:力扣(LeetCode)

我的解答

考虑减少迭代次数,并且数组的容量确定无法变化,借用 Arraylist 集合存储数组,然后转为数组。

结果就是 慢的一批。渣渣。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public int[] decompressRLElist(int[] nums) {
ArrayList<Integer> list = new ArrayList<>();
for (int i=0;i<=nums.length/2-1;i++){
for (int j = 1;j<=nums[2*i];j++) {
list.add(nums[2*i+1]);
}
}
int[] arr2 = list.stream().mapToInt(Integer::valueOf).toArray();
return arr2;
}
}

改进后的解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int[] decompressRLElist(int[] nums) {
int length = 0;
for (int i=0;i<= nums.length-1;i+=2){
length += nums[i];
}
int[] arr = new int[length];
int index=0;
for (int i=0;i<=nums.length-1;i+=2) {
for (int j = 0; j <= nums[i]-1; j++) {
arr[index] = nums[i+1];
index++;
}
}
return arr;
}
}

扣友解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public int[] decompressRLElist(int[] nums) {
int len = 0;
for (int i = 0; i < nums.length; i=i+2) {
len += nums[i];
}
int[] result = new int[len];
int index = 0;
for (int i = 0; i < nums.length; i=i+2) {
for (int j = 0; j < nums[i]; j++) {
result[index] = nums[i+1];
index++;
}
}
return result;
}
}

作者:liccil76

分析一波

!!! 记住:遍历一遍数组并不会增加时间复杂度。只有循环嵌套之后时间复杂度才会变为2次。

1398 按既定顺序创建目标数组

题目描述

给你两个整数数组 nums 和 index。你需要按照以下规则创建目标数组:

目标数组 target 最初为空。
按从左到右的顺序依次读取 nums[i] 和 index[i],在 target 数组中的下标 index[i] 处插入值 nums[i] 。
重复上一步,直到在 nums 和 index 中都没有要读取的元素。
请你返回目标数组。

题目保证数字插入位置总是存在。

  • 示例 1:
1
2
3
4
5
6
7
8
9
10
输入:nums = [0,1,2,3,4], index = [0,1,2,2,1]
输出:[0,4,1,3,2]
解释:
nums index target
0 0 [0]
1 1 [0,1]
2 2 [0,1,2]
3 2 [0,1,3,2]
4 1 [0,4,1,3,2]
来源:力扣(LeetCode)

我的解答

正常思路,因为不确定插入的位置,所以使用while循环,以达到更高的效率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int[] createTargetArray(int[] nums, int[] index) {
int[] arr = new int[nums.length];
for (int i=0;i<= nums.length-1;i++){
int j=i;
while(index[i]<j){
arr[j]=arr[j-1];
j--;
}
arr[index[i]]=nums[i];
}
return arr;

}
}

官方题解

因为插入的不确定性,使用list集合,最后再把list集合转为数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int[] createTargetArray(int[] nums, int[] index) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < nums.length; ++i) {
list.add(index[i], nums[i]);
}
int[] ret = new int[nums.length];
for (int i = 0; i < nums.length; ++i) {
ret[i] = list.get(i);
}
return ret;
}
}

作者:LeetCode-Solution

分析两波

爷的程序时间复杂度击败100%,很是流弊了。官方86%,不太行。

1365 有多少小于当前数字的数字

题目描述

给你一个数组 nums,对于其中每个元素 nums[i],请你统计数组中比它小的所有数字的数目。

换而言之,对于每个 nums[i] 你必须计算出有效的 j 的数量,其中 j 满足 j != i 且 nums[j] < nums[i] 。

以数组形式返回答案。

  • 示例 1:
1
2
3
4
5
6
7
8
输入:nums = [8,1,2,2,3]
输出:[4,0,1,1,3]
解释:
对于 nums[0]=8 存在四个比它小的数字:(1,2,2 和 3)。
对于 nums[1]=1 不存在比它小的数字。
对于 nums[2]=2 存在一个比它小的数字:(1)。
对于 nums[3]=2 存在一个比它小的数字:(1)。
对于 nums[4]=3 存在三个比它小的数字:(1,2 和 2)。
  • 示例 2:
1
2
输入:nums = [6,5,4,8]
输出:[2,1,0,3]
  • 示例 3:
1
2
输入:nums = [7,7,7,7]
输出:[0,0,0,0]

我的解答

最简单的暴力解法。时间复杂度O(n^2),空间复杂度O(1)。

我简单的脑子和简单的知识面真只能想到这个。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public int numIdenticalPairs(int[] nums) {
int re=0;
for(int i=0;i<=nums.length-2;i++){
for (int j=i+1;j<=nums.length-1;j++){
if (nums[i]==nums[j]){
re++;
}
}
}

return re;
}
}

官方解答

  • 解法二:快速排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public int[] smallerNumbersThanCurrent(int[] nums) {
int n = nums.length;
int[][] data = new int[n][2];
for (int i = 0; i < n; i++) {
data[i][0] = nums[i];
data[i][1] = i;
}
Arrays.sort(data, new Comparator<int[]>() {
public int compare(int[] data1, int[] data2) {
return data1[0] - data2[0];
}
});

int[] ret = new int[n];
int prev = -1;
for (int i = 0; i < n; i++) {
if (prev == -1 || data[i][0] != data[i - 1][0]) {
prev = i;
}
ret[data[i][1]] = prev;
}
return ret;
}
}

作者:LeetCode-Solution

扣友解答1

作者说:解法二还可以更直观一点。实际上在排序数组中做“smaller than”的统计是很简单的,使用二维数组排序本质虽然相同,但是容易产生误解。

数组排序的操作涉及stream流、toArray()、sorted(),都需要学习巩固,包括后面集合转数组的操作,我并看不懂。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public int[] smallerNumbersThanCurrent(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
int[] sorted = Arrays.stream(nums).sorted().toArray();
for (int i = 0; i < sorted.length; i++) {
if (i == 0 || sorted[i] != sorted[i - 1]) {
map.put(sorted[i], i);
}
}
return Arrays.stream(nums).map(num -> map.get(num)).toArray();
}
}
作者: Edward Elric

扣友解答2

作者说:思路差不多, 但是写法我的就很low了。

这个解法,我徒手看依然看不懂。包括copyofRange方法、containskey方法,但后面的那个循环让我理解了解答一的具体实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public int[] smallerNumbersThanCurrent(int[] nums) {
int[] temp = Arrays.copyOfRange(nums, 0, nums.length);
Arrays.sort(temp);
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < temp.length; i++) {
if (!map.containsKey(temp[i])) {
map.put(temp[i], i);
}
}
for (int i = 0; i < nums.length; i++) {
temp[i] = map.get(nums[i]);
}
return temp;
}
作者: NOCurd

分析三波

官方解答用二维数组排序并不是直接能想到的思维方式,反观评论里扣友的思路更为清晰。我之所以懂了思路仍然还是不能下手,是因为大部分集合、排序的操作我实在太过陌生,javaEE过了一遍、回头找笔记甚至也不能全不读懂、更别说自己独立的使用了。需要积累的还很多、慢慢的来。

还有就是,目前只能刷简单题,简单题不必过多赘述,以后只记录一下自己不会的题,一眼看出正确解答的编出来就完事了,现在这么菜都能做、以后也肯定可以做。

以上。

-------------感谢阅读没事常来-------------