0%

2022-0818

1636. 按照频率将数组升序排序 - 力扣(LeetCode)

1660838816939

先统计个数,然后按照个数进行排序

注意:

对于int[],不可以直接进行Arrays.sort(nums, (a,b)->a-b);

要么先转成Integer[]

要么用

1
2
Arrays.stream(nums).boxed().sorted((a,b)->
(counts[a] - counts[b) ).mapToInt(Integer::intValue).toArray()

来实现,先stream然后boxed最后还要mapToInt才能toArray

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {

public int[] frequencySort(int[] nums) {
int[] counts = new int[201];
for (int num : nums) {
counts[num + 100]++;
}
// int[]数组不可以直接自定义排序
// Arrays.sort(nums, (a,b)->a-b);
return Arrays.stream(nums).boxed().sorted((a,b)->
counts[a+100] != counts[b+100] ? (counts[a+100] - counts[b+100]) : (b-a)).mapToInt(Integer::intValue).toArray();
}
}

剑指 Offer 30. 包含min函数的栈 - 力扣(LeetCode)

1660838926999

维护2个数组即可,stack数组和min数组(毕竟往栈底看过去的最小值一定是确定的)

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
28
class MinStack {

/** initialize your data structure here. */
int[] min = new int[20001];
int[] stack = new int[20001];
int index = 0;
public MinStack() {

}

public void push(int x) {
min[index] = Math.min(x, index-1>=0 ? min[index-1] : Integer.MAX_VALUE);
stack[index++] = x;
}

public void pop() {
min[index-1] = Integer.MAX_VALUE;
index--;
}

public int top() {
return stack[index-1];
}

public int min() {
return min[index-1];
}
}

322. 零钱兑换 - 力扣(LeetCode)

1660838978323

时间很紧,先是相当了bfs并用记忆化处理,每次出队硬币个数最少的,类似于走迷宫了。

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
28
class Solution {
public int coinChange(int[] coins, int amount) {
Queue<int[]> queue = new PriorityQueue<>((a,b)->(a[0]-b[0]));

queue.offer(new int[]{0,0});
Set<Integer> vis = new HashSet<>();
vis.add(0);
while(!queue.isEmpty()) {
int count = queue.peek()[0];
int am = queue.poll()[1];
if (am == amount) {
return count;
}
for (int coin : coins) {
int newAmount = am + coin;
if (newAmount > amount) {
continue;
}
if (vis.contains(newAmount)) {
continue;
}
vis.add(newAmount);
queue.offer(new int[]{count+1, newAmount});
}
}
return -1;
}
}

1660839037340

性能太差了

看了答案想起来这个完全可以动态规划

因为amount的范围是0~104而非109,完全可以把amount作为一个dp状态处理, 且coin的数量也只有12个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public int coinChange(int[] coins, int amount) {
long[] dp = new long[amount+1];

for (long a = 1; a <= amount;a++) {
dp[(int)a] = Integer.MAX_VALUE;
for (int coin : coins) {
if (a - coin < 0) {
continue;
}
dp[(int)a] = Math.min(dp[(int)a], dp[(int)a-coin] + 1);
}
}
return (int)dp[amount] == Integer.MAX_VALUE ? -1 : (int)dp[amount];
}
}

1660839089263

性能一下子就上去了

再做一下优化,根据数据范围,去除long和int的强转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public int coinChange(int[] coins, int amount) {
int[] dp = new int[amount+1];

for (int a = 1; a <= amount;a++) {
dp[a] = 10001;
for (int coin : coins) {
if (a < coin) {
continue;
}
dp[a] = Math.min(dp[a], dp[a-coin] + 1);
}
}
return dp[amount] == 10001 ? -1 : dp[amount];
}
}

1660839698405

提升到11ms了

另外有个很奇怪的,下面这个的性能始终慢2ms,我感觉明明过滤了很多不必要的coins循环才对

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
class Solution {
public int coinChange(int[] coins, int amount) {
int[] dp = new int[amount+1];
int minCoin = coins[0];
for (int i = 1; i < coins.length;i++) {
minCoin= Math.min(minCoin, coins[i]);
}

Arrays.sort(coins);
for (int a = 1; a <= amount;a++) {
dp[a] = 10001;
if (a < minCoin) {
continue;
}
for (int coin : coins) {
int lastCoinSum = a-coin;
if (lastCoinSum < 0) {
break;
}
dp[a] = Math.min(dp[a], dp[lastCoinSum] + 1);
}
}
return dp[amount] == 10001 ? -1 : dp[amount];
}
}

1660839823484