1. 程式人生 > >LeetCode第152題.乘積最大子序列

LeetCode第152題.乘積最大子序列

原題如下:

給定一個整數陣列 nums ,找出一個序列中乘積最大的連續子序列(該序列至少包含一個數)。

示例 1:

輸入: [2,3,-2,4]
輸出: 6
解釋: 子陣列 [2,3] 有最大乘積 6。
示例 2:

輸入: [-2,0,-1]
輸出: 0
解釋: 結果不能為 2, 因為 [-2,-1] 不是子陣列。

分析:

nums【i-1】 必然會得到一個 max值,,,那麼我們能不能通過nums【i-1】求得nums【i】呢,,測試 一些 資料 就知道了
比如 對於 -2,4,-3 而言, nums【1】的 max值 是4,而nums【2】的max值卻是 -24-3 為 24,== 所以可以得到結論,從i-1的max值是不能直接推出i的max值的(即我們還需要記錄其他的輔助值!!!!)==

那麼還需要的輔助變數是什麼確實是比較耐人尋味的!!!

這個 需要從目的出發來分析,如果求 i的max值有哪幾種情況呢???
1)max值就是 nums【i】(這種情況別忘了)
2)max值是從i-1的max值繼承而來的
3)max值為除了i當前外 ,之前元素連乘獲得的最大乘積 p乘以nums【i】 (ps:nums【i】為正數)即p nums【i】
4)max值為除了i當前外 ,之前元素連乘獲得的最小乘積q乘以nums【i】 (ps:nums【i】為負數)即q
nums【i】

綜上所述對於一個i位置我們需要記錄三樣東西:

1)當前位置的max值

2)包含當前位置的最大連乘值(指向0位置方向的)

3)包含當前位置的最小連乘值(指向0位置方向的)

程式碼如下(注意lz為了方便理解,開了一個vector記錄了每個位置下的上述3個數據,實際只需要3個int 記錄即可)

struct My_node{
	int max_elem;
	int and_this_max;
	int and_this_min;
};
    int max_three_nums(int &x,int &y,int &z){
		int tmp = max(x, y);
		tmp = max(tmp, z);
		return tmp;
	}
	int min_three_nums(int &x, int &y, int &z){
		int tmp = min(x, y);
		tmp = min(tmp, z);
		return tmp;
	}
	int maxProduct(vector<int>& nums) {
		if (nums.size() == 1)return nums[0];
		vector<My_node>m(nums.size());
		m[0].max_elem = nums[0]; m[0].and_this_max = nums[0]; m[0].and_this_min = nums[0];
		for (int i = 1; i <= nums.size() - 1; i++){
			int x = m[i - 1].max_elem;
			int y = m[i - 1].and_this_max*nums[i];
			int z = m[i - 1].and_this_min*nums[i];
			m[i].max_elem = max( max_three_nums(x,y,z),nums[i]);
			m[i].and_this_max = max_three_nums(y, z, nums[i]);
			m[i].and_this_min = min_three_nums(y, z, nums[i]);
		}
		return m[nums.size() - 1].max_elem;
	}