目录
- 一、概念
- 二、模板
- 三、例题
- 题:485. 最大连续 1 的个数
- 解:
- 题:1464. 数组中两元素的最大乘积
- 解:
- 题:153. 寻找旋转排序数组中的最小值
- 解:
- 题:154. 寻找旋转排序数组中的最小值 II
- 解:
- 题:414. 第三大的数
- 解:
- 题:628. 三个数的最大乘积
- 解:
一、概念
二、模板
求n个数m个最大值(不严格):
public int thirdMax(int[] nums) {
int a = Integer.MIN_VALUE, b = Integer.MIN_VALUE, c = Integer.MIN_VALUE; // ...
for(int num : nums) {
if(num > a) {
c = b; b = a; a = num; // 注意先后赋值顺序
}else if(num <= a && num > b) {
c = b; b = num;
}else if(num <= b && num > c) {
c = num;
}
}
return c == Integer.MIN_VALUE ? a : c;
}
求n个数m个最大值(严格):
public int thirdMax(int[] nums) {
int a = Integer.MIN_VALUE, b = Integer.MIN_VALUE, c = Integer.MIN_VALUE; // ...
for(int num : nums) {
if(num > a) {
c = b; b = a; a = num; // 注意先后赋值顺序
}else if(num < a && num > b) {
c = b; b = num;
}else if(num < b && num > c) {
c = num;
}
}
return c == Integer.MIN_VALUE ? a : c;
}
三、例题
题:485. 最大连续 1 的个数
给定一个二进制数组 nums
, 计算其中最大连续 1
的个数。
示例 1:
输入:nums = [1,1,0,1,1,1]
输出:3
解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.
示例 2:
输入:nums = [1,0,1,1,0,1]
输出:2
提示:
1 <= nums.length <= 105
nums[i] 不是 0 就是 1.
解:
解题思路:枚举
AC代码:
class Solution {
public int findMaxConsecutiveOnes(int[] nums) {
int maxCount = 0, count = 0;
for(int num : nums) {
if(num == 1) {
count ++;
}else {
maxCount = Math.max(maxCount, count);
count = 0;
}
}
return Math.max(maxCount, count);
}
}
题:1464. 数组中两元素的最大乘积
给你一个整数数组 nums
,请你选择数组的两个不同下标 i
和j
,使 (nums[i]-1)*(nums[j]-1)
取得最大值。
请你计算并返回该式的最大值。
示例 1:
输入:nums = [3,4,5,2]
输出:12
解释:如果选择下标 i=1 和 j=2(下标从 0 开始),则可以获得最大值,(nums[1]-1)*(nums[2]-1) = (4-1)*(5-1) = 3*4 = 12 。
示例 2:
输入:nums = [1,5,4,5]
输出:16
解释:选择下标 i=1 和 j=3(下标从 0 开始),则可以获得最大值 (5-1)*(5-1) = 16 。
示例 3:
输入:nums = [3,7]
输出:12
提示:
2 <= nums.length <= 500
1 <= nums[i] <= 10^3
解:
解题思路:枚举
AC代码:
class Solution {
public int maxProduct(int[] nums) {
return (getMax(nums) - 1) * (getMax(nums) - 1);
}
public int getMax(int[] nums) {
int max = 0;
int p = -1;
for(int i = 0; i < nums.length; i ++) {
if(max < nums[i]){
max = nums[i];
p = i;
}
}
nums[p] = 0;
return max;
}
}
题:153. 寻找旋转排序数组中的最小值
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。
给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
示例 1:
输入:nums = [3,4,5,1,2]
输出:1
解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。
示例 2:
输入:nums = [4,5,6,7,0,1,2]
输出:0
解释:原数组为 [0,1,2,4,5,6,7] ,旋转 4 次得到输入数组。
示例 3:
输入:nums = [11,13,15,17]
输出:11
解释:原数组为 [11,13,15,17] ,旋转 4 次得到输入数组。
提示:
n == nums.length
1 <= n <= 5000
-5000 <= nums[i] <= 5000
nums 中的所有整数 互不相同
nums 原来是一个升序排序的数组,并进行了 1 至 n 次旋转
解:
解题思路:二分
AC代码:
class Solution {
public int findMin(int[] nums) {
int l = 0, r = nums.length - 1;
if(nums[r] > nums[l]) return nums[0];
while(l < r) {
int mid = (l + r)/ 2;
if(nums[mid] < nums[r]) r = mid;
else l = mid + 1;
}
return nums[l];
}
}
题:154. 寻找旋转排序数组中的最小值 II
已知一个长度为n
的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,4,4,5,6,7]
在变化后可能得到:
- 若旋转 4 次,则可以得到 [4,5,6,7,0,1,4]
- 若旋转 7 次,则可以得到 [0,1,4,4,5,6,7]
注意,数组 [a[0], a[1], a[2], ..., a[n-1]]
旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]]
。
给你一个可能存在 重复 元素值的数组 nums
,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
示例 1:
输入:nums = [1,3,5]
输出:1
示例 2:
输入:nums = [2,2,2,0,1]
输出:0
提示:
n == nums.length
1 <= n <= 5000
-5000 <= nums[i] <= 5000
nums 原来是一个升序排序的数组,并进行了 1 至 n 次旋转
进阶:
这道题是 寻找旋转排序数组中的最小值 的延伸题目。
允许重复会影响算法的时间复杂度吗?会如何影响,为什么?
解:
解题思路:二分法
AC代码:
class Solution {
public int findMin(int[] nums) {
int l = 0, r = nums.length - 1;
while(l < r) {
int mid = (l + r) / 2;
if(nums[mid] > nums[r]) l = mid + 1; // mid不可能是答案
else if(nums[mid] < nums[r]) r = mid; // mid可能是答案
else r --;
}
return nums[l];
}
}
题:414. 第三大的数
给你一个非空数组,返回此数组中 第三大的数 。如果不存在,则返回数组中最大的数。
示例 1:
输入:[3, 2, 1]
输出:1
解释:第三大的数是 1 。
示例 2:
输入:[1, 2]
输出:2
解释:第三大的数不存在, 所以返回最大的数 2 。
示例 3:
输入:[2, 2, 3, 1]
输出:1
解释:注意,要求返回第三大的数,是指在所有不同数字中排第三大的数。
此例中存在两个值为 2 的数,它们都排第二。在所有不同数字中排第三大的数为 1 。
提示:
1 <= nums.length <= 104
-231 <= nums[i] <= 231 - 1
- 进阶:你能设计一个时间复杂度 O(n) 的解决方案吗?
解:
解题思路:枚举
AC代码:
class Solution {
public int thirdMax(int[] nums) {
long a = Long.MIN_VALUE, b = Long.MIN_VALUE, c = Long.MIN_VALUE; // 注意取值范围
for(long num : nums) {
if(num > a) {
c = b; b = a; a = num; // 注意先后赋值顺序
}else if(num < a && num > b) {
c = b; b = num;
}else if(num < b && num > c) {
c = num;
}
}
return c == Long.MIN_VALUE ? (int)a : (int)c;
}
}
题:628. 三个数的最大乘积
给你一个整型数组 nums ,在数组中找出由三个数组成的最大乘积,并输出这个乘积。
示例 1:
输入:nums = [1,2,3]
输出:6
示例 2:
输入:nums = [1,2,3,4]
输出:24
示例 3:
输入:nums = [-1,-2,-3]
输出:-6
提示:
3 <= nums.length <= 104
-1000 <= nums[i] <= 1000
解:
解题思路:
分三种情况:
- 全为正数:res = max1 * max2 * max3
- 全为负数:res = max1* max2* max3
- 有正有负:res = max(max1 * max2 * max3(两正一负), min1 * min2 * max1(两负一正))
值得注意的是:这里的最大最小不严格
,可以相等。
AC代码:
class Solution {
public int maximumProduct(int[] nums) {
int max1 = Integer.MIN_VALUE, max2 = Integer.MIN_VALUE, max3 = Integer.MIN_VALUE;
int min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE;
for(int num : nums) {
// 寻找前三个max(不严格,相等也算)
if(num > max1) {
max3 = max2; max2 = max1; max1 = num;
}else if(num <= max1 && num > max2) {
max3 = max2; max2 = num;
}else if(num <= max2 && num > max3){
max3 = num;
}
// 寻找后两个min(不严格,相等也算)
if(num < min1) {
min2 = min1; min1 = num;
}else if(num < min2 && num >= min1) {
min2 = num;
}
}
return Math.max(max1 * max2 * max3, min1 * min2 * max1);
}
}