【题目描述】
给你一个按 非递减顺序 排列的数组 nums ,返回正整数数目和负整数数目中的最大值。换句话讲,如果 nums 中正整数的数目是 pos ,而负整数的数目是 neg ,返回 pos 和 neg二者中的最大值。注意:0 既不是正整数也不是负整数。
示例 1:
输入:nums = [-2,-1,-1,1,2,3]
输出:3
解释:共有 3 个正整数和 3 个负整数。计数得到的最大值是 3 。
示例 2:
输入:nums = [-3,-2,-1,0,0,1,2]
输出:3
解释:共有 2 个正整数和 3 个负整数。计数得到的最大值是 3 。
示例 3:
输入:nums = [5,20,66,1314]
输出:4
解释:共有 4 个正整数和 0 个负整数。计数得到的最大值是 4 。
提示:
1 <= nums.length <= 2000
-2000 <= nums[i] <= 2000
nums 按 非递减顺序 排列。
【题目链接】. - 力扣(LeetCode)
【解题代码】
package array;public class MaximumCount {public static void main(String[] args) {//int[] nums = new int[]{-2, -1, -1, 1, 2, 3};int[] nums = new int[]{-3, -2, -1, 0, 0, 1, 2};//int[] nums = new int[]{5, 20, 66, 1314};long start = System.currentTimeMillis();int result = new MaximumCount().maximumCount(nums);System.out.println("函数运行时间:" + (System.currentTimeMillis() - start) + "MS");System.out.println("函数运行结果:" + result);}public int maximumCount(int[] nums) {int i = 0, j = nums.length - 1;while (i <= j) {int n = i + (j - i) / 2;if (nums[n] < 0) {i = n + 1;} else { j = n - 1;}}while (i < nums.length && nums[i] == 0) {i++;}return Math.max(j + 1, nums.length - i);}
}
【解题思路】
拿到题目,分析一下,感觉可以类似二分检索的方式:设置首尾两个索引值i,j,如果中间索引n值小于0,那么将i设置为n+1,否则(n值大于等于0)将j设置为n-1,循环结束后,索引j及之前的数据应该都是小于0的值,索引i及之后的数据都是大于等于0的数。再将i跳过之后等于0的数值即可。按照这个思路,很快完成代码编写,并提交成功
【解题步骤】
- 采用二分查找算法,首先定义首尾索引两个变量;
int i = 0, j = nums.length - 1;
- 二分查找算法的终止条件,索引值i大于等于索引值j
while (i <= j) {
- 获取索引值i和j中间索引值n
int n = i + (j - i) / 2;
- 如果nums[n]小于0,那么将i设置为n + 1,如果nums[n]大于等于0,那么将j设置为n - 1
if (nums[n] < 0) {i = n + 1; } else { // 如果nums[n]大于等于0,那么将j设置为n - 1j = n - 1; }
- 循环结束后,向后跳过所有等于0的数值
while (i < nums.length && nums[i] == 0) {i++; }
- 负数的数量等于j+1, 正数的数量等于nums.length - i,取两者最大值
return Math.max(j + 1, nums.length - i);
【思考总结】
- 二分查找算法定义:二分查找算法(英语:binary search algorithm),也称折半搜索算法是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。二分查找算法在最坏情况下是对数时间复杂度的,需要进行logn次比较操作
- 按照大神Donald Knuth所说“思路很简单,细节是魔鬼”,二分查找算法需要特别关注中间索引值这些细节方面。比如如果写成“int n = (i + j) / 2;” ,可能会存在溢出的bug,第一篇二分搜索论文是 1946 年发表,然而第一个没有 bug 的二分查找法却是在 1962 年才出现,中间用了 16 年的时间。
- 对于二分查找等经典算法,要学会灵活运用,根据实际情况进行调整
- LeetCode解题之前,一定不要看题解,看了就“破功”了!