前言
执手看歌敲金钗,笑语落珠明眸睐。
忽然蝴蝶春风满,焉教冷镜瘦朱颜。
整体评价
T3是基于map的前缀和的变形题,T4是二维偏序的一道应用题。
题外话,力扣还是实现N久之前的承诺了,命名权奖励,赞一个。
T1. 三角形类型 II
思路: 模拟
class Solution {
public String triangleType(int[] nums) {
// 先判合法性
Arrays.sort(nums);
if (nums[0] + nums[1] <= nums[2]) return "none";
if (nums[0] == nums[1] && nums[1] == nums[2]) {
return "equilateral";
} else if (nums[0] == nums[1] || nums[1] == nums[2]) {
return "isosceles";
} else {
return "scalene";
}
}
}
T2. 人员站位的方案数 I
和T4一起讲
T3. 最大好子数组和
思路: 基于map的前缀和应用
这边需要以值作为key, value为最小的前缀和(需向前偏移一位)
更新的时候,需要分类讨论,v为当前值
- v − k v - k v−k
- v + k v + k v+k
class Solution {
public long maximumSubarraySum(int[] nums, int k) {
long inf = Long.MIN_VALUE / 10;
long res = inf;
// 维护最小的前缀和
Map<Long, Long> minMap = new HashMap<>();
long acc = 0;
for (int i = 0; i < nums.length; i++) {
long v = nums[i];
acc += v;
if (minMap.containsKey(v - k)) {
res = Math.max(acc - minMap.get(v - k), res);
}
if (minMap.containsKey(v + k)) {
res = Math.max(acc - minMap.get(v + k), res);
}
// 更新
if (!minMap.containsKey(v) || acc - v < minMap.get(v)) {
minMap.put(v, acc - v);
}
}
return res == inf ? 0 : res;
}
}
T4. 人员站位的方案数 II
思路: 二维偏序 + 枚举
对于偏序题,一般先固定一个维度
- 先按x坐标从小到大排序,
- 再按照y坐标从大到小排序
因为题目指定左上角,右下角
然后枚举左右端点,check是否满足需求即可。
在枚举的过程中,可以引入
单调队列优化 单调队列优化 单调队列优化
实际上只要维护最接近左端点y坐标(严格小于等于)的单变量即可, 递增状态
这样整个时间复杂度可以降为
- 排序 O ( n l o g n ) O(nlogn) O(nlogn)
- 枚举左右端点 O ( n 2 ) O(n^2) O(n2)
最终为 O ( n 2 ) O(n^2) O(n2)
class Solution {
public int numberOfPairs(int[][] points) {
// 按x从小到大,按y从大到小
Arrays.sort(points, Comparator.comparingInt((int[] p) -> p[0]).thenComparingInt(p -> -p[1]));
int res = 0;
int n = points.length;
for (int i = 0; i < n; i++) {
// 维护最接近左端点y值的值(严格小于等于)
int nearest = Integer.MIN_VALUE;
for (int j = i + 1; j < n; j++) {
if (points[j][1] <= points[i][1]) {
if (points[j][1] > nearest) {
res++;
nearest = points[j][1];
}
}
}
}
return res;
}
}
- 离散化+二维前缀和 (补充)
这个解法应该更加的直观
class Solution {
// 离散化
Map<Integer, Integer> discrete(List<Integer> ps) {
TreeSet<Integer> range = new TreeSet<>(ps);
Map<Integer, Integer> ids = new HashMap<>();
int ptr = 0;
for (var k: range) {
ids.put(k, ptr++);
}
return ids;
}
public int numberOfPairs(int[][] points) {
int n = points.length;
int res = 0;
Map<Integer, Integer> xs = discrete(Arrays.stream(points).map(p -> p[0]).collect(Collectors.toList()));
Map<Integer, Integer> ys = discrete(Arrays.stream(points).map(p -> p[1]).collect(Collectors.toList()));
int h = ys.size(), w = xs.size();
int[][] area = new int[h][w];
for (int[] p: points) {
area[ys.get(p[1])][xs.get(p[0])] = 1;
}
int[][] pre = new int[h + 1][w + 1];
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
pre[i + 1][j + 1] = pre[i + 1][j] + pre[i][j + 1] - pre[i][j] + area[i][j];
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) continue;
if (points[i][0] <= points[j][0] && points[i][1] >= points[j][1]) {
int ty = ys.get(points[i][1]), by = ys.get(points[j][1]);
int tx = xs.get(points[j][0]), bx = xs.get(points[i][0]);
int s = pre[ty + 1][tx + 1] - pre[ty + 1][bx] - pre[by][tx + 1] + pre[by][bx];
if (s == 2) {
res ++;
}
}
}
}
return res;
}
}