java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846
排序
解题思路:时间复杂度O(
n
∗
l
o
g
2
n
n*log_2n
n ∗ l o g 2 n ),空间复杂度O(
l
o
g
2
n
log_2n
l o g 2 n ),时间和空间复杂度都用在了快速排序上
对于一堆数里面挑出3个乘积最大,是个数学问题,有3种情况
这些数都是正数,则最大的3个数乘积最大 这些数都是负数,则最大的3个数乘积最大 有正有负,则可能是两个最小的和一个最大的乘积最大,也可能是3个最大的数乘积最大
只有1个正数,则最小的两个负数和这个正数相乘乘积最大 有多个正数,也有可能两个最小负数和最大正数更大。例如有[-20000,-10000,1,2,3]这样的数组,最大乘积为
−
10000
∗
−
20000
∗
3
-10000*-20000*3
− 10000 ∗ − 20000 ∗ 3
综上所述,我们只需要找出3个最大的数,已经2个最小的数。然后取两种方案中大的即可。
3个最大的数乘积可能是最大(没有负数,或者负数乘积都特别小的情况) 2个最小加最大的数可能是最大(2个特别小的负数+一个最大正数)
有了上面的分析,我们的问题就变成了,找到数组中最大的3个数和最小的2个数
先排序,然后直接得到 快速查找算法,找到对应数字 线性搜索找最值
class Solution {
public int maximumProduct ( int [ ] nums) {
Arrays . sort ( nums) ;
int n = nums. length;
return Math . max ( nums[ 0 ] * nums[ 1 ] * nums[ n - 1 ] , nums[ n - 3 ] * nums[ n - 2 ] * nums[ n - 1 ] ) ;
}
}
选择
解题思路:时间复杂度O(
n
n
n ),空间复杂度O(
l
o
g
2
n
log_2n
l o g 2 n )
法一使用快速排序做 而对于仅仅找特定几个值的话,快速选择时间复杂度更低 对于找到第几大的值可以参考215题
🏆LeetCode215. 数组中的第K个最大元素https://blog.csdn.net/grd_java/article/details/136932454
class Solution {
public int maximumProduct ( int [ ] nums) {
int n = nums. length;
int min1 = quickSort ( nums, 0 , n- 1 , 1 ) , min2 = quickSort ( nums, 0 , n- 1 , 2 ) ;
int max1 = quickSort ( nums, 0 , n- 1 , n) ;
int max2 = quickSort ( nums, 0 , n- 1 , n- 1 ) ;
int max3 = quickSort ( nums, 0 , n- 1 , n- 2 ) ;
return Math . max ( max1* min1* min2, max1* max2* max3) ;
}
int quickSort ( int [ ] a, int left, int right, int k) {
if ( left >= right) return a[ left] ;
int x = a[ left + right >> 1 ] ;
int leftIndex = left - 1 , rightIndex = right + 1 ;
while ( leftIndex < rightIndex) {
do leftIndex++ ; while ( a[ leftIndex] < x) ;
do rightIndex-- ; while ( a[ rightIndex] > x) ;
if ( leftIndex < rightIndex) {
swap ( a, leftIndex, rightIndex) ;
}
}
if ( k <= ( rightIndex - left + 1 ) )
return quickSort ( a, left, rightIndex, k) ;
else
return quickSort ( a, rightIndex+ 1 , right, k- ( rightIndex- left+ 1 ) ) ;
}
void swap ( int [ ] a, int i, int j) {
int t = a[ i] ;
a[ i] = a[ j] ;
a[ j] = t;
}
}
线性搜索最值
解题思路:时间复杂度O(
n
n
n ),空间复杂度O(
1
1
1 )
对于一个数组的最大值和最小值,或者第二大,第2小等等。只要我们找的是边缘值(100个数,找最小的3个,找最大的3个),线性搜索效率会更高。但是如果是100个数里面找排序后最小的27个数,肯定不如快速选择和小根堆。 对于只找很少量的几个最值,线性搜索会很方便,只需要遍历一次数组
代码:可见,线性搜索,找最大的3个值就要3个if,100个就要100个if,所以只有找少数几个最值的时候可用
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) {
if ( num > max3) {
if ( num < max2) max3 = num;
else if ( num < max1) {
max3 = max2;
max2 = num;
} else {
max3 = max2;
max2 = max1;
max1 = num;
}
}
if ( num < min2) {
if ( num > min1) min2 = num;
else {
min2 = min1;
min1 = num;
}
}
}
return Math . max ( max1 * max2 * max3, max1 * min1 * min2) ;
}
}