首页 > 编程语言 >【小航的算法日记】 线性枚举(一) - 最值算法

【小航的算法日记】 线性枚举(一) - 最值算法

时间:2022-11-29 10:38:57浏览次数:39  
标签:小航 nums int 示例 VALUE 算法 num 数组 最值


目录

  • ​​一、概念​​
  • ​​二、模板​​
  • ​​三、例题​​
  • ​​题: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

解:

解题思路:

分三种情况:

  1. 全为正数:res = max1 * max2 * max3
  2. 全为负数:res = max1* max2* max3
  3. 有正有负: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);
}
}


标签:小航,nums,int,示例,VALUE,算法,num,数组,最值
From: https://blog.51cto.com/u_15895329/5894194

相关文章

  • 【小航的算法日记】因子和
    目录​​一、概念​​​​二、模板​​​​三、例题​​​​题:1390.四因数​​​​解:​​一、概念因子和二、模板看例题三、例题题:1390.四因数给你一个整数数组​​nums......
  • 【小航的算法日记】最小公倍数
    目录​​一、概念​​​​二、模板​​​​三、例题​​​​题:1819.序列中不同最大公约数的数目​​​​解:​​一、概念推导:由算术基本定理得:则,(1)X(2)得:即:二、模板给定两个......
  • 【小航的算法日记】变量交换算法
    目录​​一、概念​​​​二、模板​​​​三、例题​​​​题:面试题16.01.交换数字​​​​解:​​​​题:面试题05.07.配对交换​​​​解:​​内容摘自英雄哥,详情请看......
  • 【小航的算法日记】线性枚举(二) - 统计法入门
    目录​​一、概念​​​​二、模板​​​​三、例题​​​​题:1550.存在连续三个奇数的数组​​​​解:​​​​题:1295.统计位数为偶数的数字​​​​解:​​​​题:540.有......
  • 【小航的算法日记】进制转换(二) - 进阶
    目录​​一、概念​​​​二、模板​​​​三、例题​​​​题:202.快乐数​​​​解:​​​​题:168.Excel表列名称​​​​解:​​​​题:171.Excel表列序号​​​​解:​​......
  • 【小航的算法日记】进制转换(一) - 入门
    目录​​一、概念​​​​二、模板​​​​三、例题​​​​题:剑指Offer15.二进制中1的个数​​​​解:​​​​题:258.各位相加​​​​解:​​​​题:1290.二进制链表转......
  • 【小航的算法日记】字符串算法(二) - 字符串比较
    目录​​一、概念​​​​二、模板​​​​三、例题​​​​题:剑指Offer05.替换空格​​​​解:​​​​题:面试题10.05.稀疏数组搜索​​​​解:​​​​题:1763.最长的......
  • 【小航的算法日记】线段树
    本内容取经于:https://leetcode.cn/problems/my-calendar-i/solution/by-lfool-xvpv/一、概念概念区分:线段树解决的是「区间和」的问题,且该「区间」会被修改前缀和解决的是......
  • 【小航的算法日记】字符串
    目录​​一、概念​​​​二、模板​​​​三、例题​​​​题:344.反转字符串​​​​解:​​​​题:541.反转字符串II​​​​解:​​​​题:剑指Offer05.替换空格​​​......
  • 【小航的算法日记】哈希
    一、概念哈希表、哈希函数、哈希碰撞二、模板三、例题题:242.有效的字母异位词给定两个字符串s和t,编写一个函数来判断t是否是s的字母异位词。注意:若s和t中每个......