Add Date 2014-09-23

Maximum Product Subarray

Find the contiguous subarray within an array (containing at least one number) which has the largest product.

For example, given the array [2,3,-2,4],
the contiguous subarray [2,3] has the largest product = 6.

简单来说就是在一个 int 数组中找一段连续的子数组,使其乘积最大,数组中包含正数、负数和0。不考虑乘积太大超出范围。

解法一:

动态规划的方法,今天在微信“待字闺中”中看到的,借来分享。遍历一遍,优于解法二,复杂度O(n).

  1. int max2(int a, int b) {
  2. if(a > b) return a;
  3. return b;
  4. }
  5.  
  6. int max3(int a, int b, int c) {
  7. return max2(max2(a, b), c);
  8. }
  9.  
  10. int min2(int a, int b) {
  11. if(a > b) return b;
  12. return a;
  13. }
  14.  
  15. int min3(int a, int b, int c) {
  16. return min2(min2(a, b), c);
  17. }
  18.  
  19. int maxProduct(int A[], int n) {
  20. int max = A[];
  21. int min = A[];
  22. int a = max;
  23. for(int i = ; i < n; ++i) {
  24. int tmpMax = max * A[i];
  25. int tmpMin = min * A[i];
  26. max = max3(tmpMax, tmpMin, A[i]);
  27. min = min3(tmpMax, tmpMin, A[i]);
  28. a = max2(max, a);
  29. }
  30. return a;
  31. }

解法二:

之前做过找连续子数组使其加和最大,比较简单,见《剑指offer》Q31。

刚开始也试图从那道题中找思路,发现不太科学…后来自己摸索出一个思路,分享一下。

首先,任何一个数字和0相乘得到的都是0;另外,不考虑0的情况下,因为数字都是整数,所以乘积的绝对值是不会变小的;再次,负负得正。

基于这三点考虑,首先基于递归的思想用0分段,也就是说,把数组 A 拆分为 [一段不包含0的数组]、[0]、[剩下的数组],并设 rel1 为不包含0的子数组得到的最大乘积,rel2 为剩下的数组得到的最大乘积,那么,数组 A 的最大乘积就是 max{rel1,0,rel2}。rel2递归的用这个思路得到。

然后,就是求一个不包含0的数组的最大乘积。由于负负得正,可以想到,如果负数的个数为偶数,那么所有的数字相乘就是那个最大乘积;如果负数的个数为奇数,那么一定是某一个负数的左边所有数字乘积或者右边所有数字乘积为最大,所以就可以从前向后遍历数组,并把所有元素相乘,用 numAll1 记录这个乘积,同时每次更新 num1 为从前到后相乘过程中最大的乘积;然后再从后向前遍历数组,用 numAll2 记录乘积,num2 记录最大值,这样整个数组的最大乘积就是 max{num1,num2}。

如果你觉得不理解为什么最大乘积的子数组一定是从第一个数字连续的一个子数组,或者是从最后一个数字连续的子数组,可以这样想:

如果这个乘积最大的子数组是中间的某一段,当然排除掉只有一个元素且为负数的情况,那么这个乘积一定是正数(这个还不懂的话自己想一下吧,简单的),如果

1.这段子数组左边(右边)是全正的,那么和左边(右边)所有的数相乘的结果一定不会比当前的结果小,所以可以从左边(右边)连续;所以这段子数组左边和右边一定都有负数!

2.这段子数组左边(右边)有偶数个负数,同1是不可能的;而且如果有多个负数,一定可以有偶数个可以包含在中间这段子数组中使乘积更大;所以一定左边和右边各有一个负数!

3.如果左边和右边各有一个负数,那么就有两个负数,这样的话把整个数组相乘的结果一定不小于中间这段子数组。

这个算法中遍历整个数组三次,复杂度为O(n).

终于把逻辑说完了,个人觉得很啰嗦,只是想说明白点,不知道大家有没明白,下面附 code,欢迎其它思路。

  1. class Solution {
  2. public:
  3. int maxProductNo0(int A[], int n) { //没有0的数组求最大乘积
  4. int num1 = A[];
  5. int numAll1 = A[];
  6. for(int i = ; i < n; ++i) {
  7. numAll1 *= A[i];
  8. num1 = numAll1 > num1 ? numAll1 : num1;
  9. }
  10.  
  11. int num2 = A[n-];
  12. int numAll2 = A[n-];
  13. for(int i = n-; i >= ; --i) {
  14. numAll2 *= A[i];
  15. num2 = numAll2 > num2 ? numAll2 : num2;
  16. }
  17. return num1 > num2 ? num1 : num2;
  18. }
  19.  
  20. int maxProduct(int A[], int n) { //求数组最大乘积
  21. if(A == NULL || n < )
  22. return ;
  23. int index0 = ;
  24. int rel1 = A[];
  25. int rel2 = A[];
  26. bool have0 = false;
  27. for(; index0 < n; ++index0) {
  28. if(A[index0] == ) {
  29. have0 = true;
  30. break;
  31. }
  32. }
  33. if(index0 > )
  34. rel1 = maxProductNo0(A, index0); //没有0的数组的最大乘积
  35. if(n-index0- > )
  36. rel2 = maxProduct(A+index0+, n-index0-); //剩下的数组的最大乘积
  37. rel1 = rel1 > rel2 ? rel1 : rel2;
  38. if(have0)
  39. rel1 = rel1 > ? rel1 : ;
  40. return rel1;
  41. }
  42. };

【LeetCode】Maximum Product Subarray 求连续子数组使其乘积最大的更多相关文章

  1. [LeetCode] Maximum Product Subarray 求最大子数组乘积

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...

  2. [leetcode]523. Continuous Subarray Sum连续子数组和(为K的倍数)

    Given a list of non-negative numbers and a target integer k, write a function to check if the array ...

  3. LeetCode Maximum Product Subarray(枚举)

    LeetCode Maximum Product Subarray Description Given a sequence of integers S = {S1, S2, . . . , Sn}, ...

  4. LeetCode Maximum Product Subarray 解题报告

    LeetCode 新题又更新了.求:最大子数组乘积. https://oj.leetcode.com/problems/maximum-product-subarray/ 题目分析:求一个数组,连续子 ...

  5. 连续子数组的最大乘积及连续子数组的最大和(Java)

    1. 子数组的最大和 输入一个整形数组,数组里有正数也有负数.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值.例如数组:arr[]={1, 2, 3, -2, ...

  6. [LeetCode] Maximum Product Subarray 连续数列最大积

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...

  7. lintcode :continuous subarray sum 连续子数组之和

    题目 连续子数组求和 给定一个整数数组,请找出一个连续子数组,使得该子数组的和最大.输出答案时,请分别返回第一个数字和最后一个数字的值.(如果两个相同的答案,请返回其中任意一个) 样例 给定 [-3, ...

  8. Maximum Product Subarray 最大连续乘积子集

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...

  9. LeetCode: Maximum Product Subarray && Maximum Subarray &子序列相关

    Maximum Product Subarray Title: Find the contiguous subarray within an array (containing at least on ...

随机推荐

  1. HTTP头解读

    Http协议定义了很多与服务器交互的方法,最基本的有4种,分别是GET.POST.PUT.DELETE.一个URL地址用于描述一个网络上的资源, 而HTTP中的GET.POST.PUT. DELETE ...

  2. C#按指定长度分割字符串

    C#按指定长度分割字符串   这几天学习分析声音的波形数据,接收到的是十六进制的数据,需要将数据转换成十进制再绘图,这个过程涉及到字符串的分割,正好可以促进自己对C#相关知识的学习.说到分割字符串,我 ...

  3. android:scrollbar的一些属性

    1. activity_maim.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android ...

  4. Atitit.ati&#160;dwr的原理and设计&#160;attilax&#160;总结&#160;java&#160;php&#160;版本号

    Atitit.ati dwr的原理and设计 attilax 总结 java php 版本号 1. dwr的长处相对于ajax来说.. 1 2. DWR工作原理 1 3. Dwr的架构 2 4. 自己 ...

  5. 封装CLLocationManager定位获取经纬度

    创建调用方法,在.h文件里 #import <Foundation/Foundation.h> @interface RMMapLocation : NSObject { void (^s ...

  6. 机器学习实战之K-Means算法

    一,引言 先说个K-means算法很高大上的用处,来开始新的算法学习.我们都知道每一届的美国总统大选,那叫一个竞争激烈.可以说,谁拿到了各个州尽可能多的选票,谁选举获胜的几率就会非常大.有人会说,这跟 ...

  7. 目标检测之vibe---ViBe(Visual Background extractor)背景建模或前景检测

    ViBe算法:ViBe - a powerful technique for background detection and subtraction in video sequences 算法官网: ...

  8. asp.net 后台多线程异步处理时的 进度条实现一(Ajax+Ashx实现以及封装成控件的实现)

    (更新:有的同学说源代码不想看,说明也不想看,只想要一个demo,这边提供一下:http://url.cn/LPT50k (密码:TPHU)) 工作好长时间了,这期间许多功能也写成了不少的控件来使用, ...

  9. Layout布局位置

    - - GUILayout 这个本身就是用于自动布局的. 不用给定位置的,这也是它与GUI的区别所在.通常默认开始的位置是屏幕的左上角. 当然你也可以限定开始自动布局的位置.用 GUILayout.B ...

  10. ios何时使用self.

     本文转载至  http://blog.csdn.net/lvxiangan/article/details/27204265   何时使用self.在网上搜索或者论坛里的回复大多都是简简单单的说这与 ...