-
Notifications
You must be signed in to change notification settings - Fork 0
/
wk294.java
107 lines (85 loc) · 3.36 KB
/
wk294.java
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package weekly;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.PriorityQueue;
public class wk294 {
//ranking: 979 / 6640
//简单题,注意用double不能用float精度不够
public int percentageLetter(String s, char letter) {
int c = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == letter) {
c++;
}
}
return (int) ((((double) c) / s.length()) * 100);
}
//中等题,先求差值,然后先满足差值最小的
public int maximumBags(int[] capacity, int[] rocks, int additionalRocks) {
int[] count = new int[capacity.length];
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
for (int i = 0; i < count.length; i++) {
priorityQueue.add(Math.max(capacity[i] - rocks[i], 0));
}
int ans = 0;
while (!priorityQueue.isEmpty() && priorityQueue.peek() <= additionalRocks) {
ans++;
additionalRocks -= priorityQueue.poll();
}
return ans;
}
//中等题,现将点从左往右排序,判断两点之间的斜率是不是相同
//注意计算斜率的时候用乘法判断
public int minimumLines(int[][] stockPrices) {
Arrays.sort(stockPrices, (a, b) -> a[0] - b[0]);
if (stockPrices.length == 1) return 1;
int ans = 1;
int x = stockPrices[1][0] - stockPrices[0][0];
int y = stockPrices[1][1] - stockPrices[0][1];
for (int i = 2; i < stockPrices.length; i++) {
int tx = stockPrices[i][0] - stockPrices[i - 1][0];
int ty = stockPrices[i][1] - stockPrices[i - 1][1];
if (x * ty != y * tx) {
ans++;
}
x = tx;
y = ty;
}
return ans;
}
//困难题,左右最小边界可以想到,但是前缀和的前缀和真的不好想
public int totalStrength(int[] nums) {
//先求出以i为最小值的左右边界
Deque<Integer> deque = new ArrayDeque<>();
int[] left = new int[nums.length];//左侧严格小于nums[i]的位置
int[] right = new int[nums.length];//右侧小于或等于nums[i]的位置
Arrays.fill(right, nums.length);
for (int i = 0; i < nums.length; i++) {
while (!deque.isEmpty() && nums[deque.peekLast()] >= nums[i]) right[deque.pollLast()] = i;
left[i] = deque.isEmpty() ? -1 : deque.peekLast();
deque.addLast(i);
}
int mod = (int) 1e9 + 7;
//计算前缀和\前缀和的前缀和
long[] sum = new long[nums.length + 1];
long[] ssum = new long[nums.length + 2];
for (int i = 0; i < nums.length; i++) {
sum[i + 1] = (sum[i] + nums[i]) % mod;
ssum[i + 2] = (ssum[i + 1] + sum[i + 1]) % mod;
}
//左右边界+前缀和的前缀和 优化成线性计算
long res = 0;
for (int i = 0; i < nums.length; i++) {
int l = left[i] + 1;
int r = right[i] - 1;
long all = (i - l + 1) * (ssum[r + 2] - ssum[i + 1]) - (r - i + 1) * (ssum[i + 1] - ssum[l]);
all %= mod;
res += (nums[i] * all);
res %= mod;
}
return (int) (res + mod) % mod;
}
public static void main(String[] args) {
}
}