原题:5227. K 次操作后最大化顶端元素 - 力扣(LeetCode) (leetcode-cn.com)
再次读秒绝杀第三题,玩的就是心理素质。。。
前两题直接模拟就可以了,完成的比较快
第三题题目一开始翻译错误,估计不少人在这里比我WA了还多。。。
读完题目看k的范围,十分的大,显然不能通过模拟每一步来做,不然必定超时。一般这种就只能反过来,不要模拟,而是去想,对于数组中的某个数,我怎么才能取到它作为栈顶。
做题时我的思路首先是假设k很大很大,远大于nums.length。 那么显然此时必然能取到nums数组的最大值。
举个例子,比如k = nums.length + 1. 那么就可以把所有数都删除,然后最后第k步把最大的数放到栈顶。
如果k = nums.length + 2。 只要nums.length 不为1的话我们也可以把最大的数放大栈顶
如果k很大,我们就可以先把所有数删除,随便取一个数不停删除和放栈顶,直至最后一步把最大的数放到栈顶。
接着,我继续想,nums.length = 1应该也是个边界的coner case。我一开始以为当nums.length = 1 && k == 1 才是-1. 结果发现正确代码是:
if (nums.length == 1 && k % 2 == 1) {
return -1;
}
凡是奇数都是-1.
这个条件我喜提一个WA
接着,讨论如果k < nums.length
一开始我想的是直接比较前k + 1个元素就行。把前k + 1个元素比较一遍取最大值。
但是像这种输入:
[91,98,17]
k = 2
最大值就只能是91.因为如果91,98都删除那栈顶就是17了,而如果98不删除,把91加到栈顶那才是最大值,显然,当下标 等于 k - 1的时候也是需要讨论的。正确代码:
// k < nums.length
int tmpMax = Integer.MIN_VALUE;
for (int i = 0; i < k - 1; i++) {
tmpMax = Math.max(nums[i], tmpMax);
}
tmpMax = Math.max(tmpMax, nums[k]);
最后当我再次提交,发现还有最后一个case没法过,显示通过了194/ 195,并且最后的输入在比赛中不显示出来。此时时间还剩12分钟。
再次检查了一下条件,分析各种coner case。
1.k = 0 的时候
2.nums.length = 1的时候
3.k < nums.length
确信这里这里应该也没错
于是锁定在k= nums.length的时候,自己想了个例子:
[4,3,2,5]
k = 4
此时一测发现返回5。其实是不对的,因为当删除到5的时候,如果继续删除那么栈就为空了。所以只能删除前面k - 1个数。取前k - 1个数的最大值。
最终提交的代码:
public int maximumTop(int[] nums, int k) {
if (nums.length == 1 && k % 2 == 1) {
return -1;
}
if (k == 1 && nums.length > 1) {
return nums[1];
}
int max = Integer.MIN_VALUE;
for (int i = 0; i < nums.length; i++) {
max = Math.max(max, nums[i]);
}
if (k > nums.length) {
return max;
}
if (k == nums.length) {
int max1 = Integer.MIN_VALUE;
for (int i = 0; i < nums.length - 1; i++) {
max1 = Math.max(max1, nums[i]);
}
return max1;
}
// k < nums.length
int tmpMax = Integer.MIN_VALUE;
for (int i = 0; i < k - 1; i++) {
tmpMax = Math.max(nums[i], tmpMax);
}
tmpMax = Math.max(tmpMax, nums[k]);
return tmpMax;
}
比较挫,还有待加强。继续刷题!