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) ; }
}