第一次参加夜猫双周赛,实在太困了,眼皮都睁不开。盼星星、盼月亮判了一个礼拜的比赛,每天晚上都盼到兴奋的睡不着,临场了却打起了瞌睡…………我是该哭还是该笑😭
很独特的体验,毕竟是大年三十的晚上。
这场比赛也太难了,勉强做对了前两道,被罚时四次,太打击信心了……
去分数预测网站看了一下,这次要降8 分,我真的哭死了,再也不要晚上比赛了。
简单题,但又是双指针题,我真的瑟瑟发抖。
我和双指针命中犯克。
每次这种双指针题,都要调试老半天处理边界情况,再加上中途 nums1、nums2、i、j 看的眼花,写着写着就写混了,调试了半个小时勉强过关。
下次吸取教训,如果第一题开局不利,这场比赛果断不提交,扣分的感觉好难受😭
代码都不好意思贴了,自己看着想吐:
/**
性能啊、可读性、代码简洁度啊,我已经不 care 了,能 AC 就行
*/
class Solution {
public int getCommon(int[] nums1, int[] nums2) {
int m = nums1.length, n = nums2.length;
int i = 0, j = 0;
while(i < m && j < n){
while(nums1[i] < nums2[j]) {
if(++i > m - 1)return -1;
}
if(nums1[i] == nums2[j]) return nums1[i];
while(nums2[j] < nums1[i]){
if(++j > n - 1)return -1;
}
if(nums1[i] == nums2[j])return nums1[i];
}
return -1;
}
public static void main(String[] args) {
int a = new Solution().getCommon(new int[]{1, 6}, new int[]{2,3,4,5});
System.out.println(a);
}
}说实话,我一开始这连这道题也看不懂。但是剩下的两道,瞄两眼不是我能搞定的,果断回来啃第二题。
考虑到每次操作都不会改变数组和,且每个数只可能增大 k 或者减小 k,所以两个数组对应位置的差,必须能整除 k,且所有的差的和必须是 0;
然后开一个小顶堆,一个大顶堆,依次取堆顶玩消除。
时间复杂度,我实在估算估算不出来,太困了。但是直觉告诉我应该不会 TLE。比较蛋疼的有两个点:
代码很丑,大家不要笑我,毕竟能 AC,我已经很知足了:
class Solution {
public long minOperations(int[] nums1, int[] nums2, int k) {
int n = nums1.length;
long ret = 0, sum = 0;
int[] diffs = new int[n];
PriorityQueue<Integer> pqPos = new PriorityQueue<>((o1, o2)->o2-o1);
PriorityQueue<Integer> pqNeg = new PriorityQueue<>();
for(int i = 0; i < n; i++){
int diff = nums1[i] - nums2[i];
if(k == 0){
if(diff != 0)return -1;
continue;
}
if(diff % k != 0)return -1;
diffs[i] = diff / k;
sum += diff;
if(diff > 0)pqPos.offer(i);
if(diff < 0)pqNeg.offer(i);
}
if(k == 0)return 0;
if(sum != 0)return -1;
while(!pqNeg.isEmpty() && !pqPos.isEmpty()){
int posId = pqPos.poll(), negId = pqNeg.poll();
int pos = diffs[posId], neg = diffs[negId];
int count = Math.min(pos, -neg);
diffs[posId] -= count;
diffs[negId] += count;
ret += count;
if(diffs[posId] > 0) pqPos.offer(posId);
if(diffs[negId] < 0) pqNeg.offer(negId);
}
return ret;
}
}
昨晚赛场上完全慌了,只想着第二题必须通过,然后患得患失,胡乱提交🤣。
其实这个优先队列完全是画蛇添足。
我在赛场上也担心过,用队列模拟,会不会导致超时,我当时没有答案,只是提交撞运气。现在想来,完全可能会超时:假设 k 是 1,然后第一个数相差无穷大,剩下的数相差 -1,这样肯定会超时。这此经历再次说明:没想清楚千万不要动手。
的代码如下:
class Solution {
public long minOperations(int[] nums1, int[] nums2, int k) {
int n = nums1.length;
if(k == 0){
for(int i = 0; i < n; i++) if(nums1[i] != nums2[i]) return -1;
return 0;
}
long posSum = 0, sum = 0;
for(int i = 0; i < n; i++){
int diff = nums1[i] - nums2[i];
if(diff % k != 0)return -1;
diff /= k;
if(diff > 0)posSum += diff;
sum += diff;
}
return sum == 0 ? posSum : -1;
}
}估计再给我四个小时,我能想出状态转移方程。┓( ´∀` )┏
或者根本不是用动态规划做。
瞬间感觉这段时间图论白学了。这道题居然来了个无限网格。好家伙,你都无限了,你让我辛苦学的 BFS、DFS、并查集、最短路、生成树,面子往哪里搁?┓( ´∀` )┏
做完第二题,只剩 20 分钟了,我盯着这道题发呆到 12 点。
直觉告诉我,四种移动方向的坐标,里面有某种玄机,但是天知道是什么玄机。
睡了睡了。