1. 程式人生 > >第一週演算法設計與分析:Container with most water

第一週演算法設計與分析:Container with most water

題目來自此處

描述如下:

Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.

Note: You may not slant the container and n is at least 2.

O(n^2)演算法:

一開始是想從前往後掃描,一條邊不斷與右邊剩餘的所有邊匹配。但是這種演算法在資料較多的情況下超時。

所以還是放棄這種懶惰做法敲打

O(n)演算法:

這個其實是一個求面積最大化的問題。考慮一個初始值——使x軸上的邊最大化作為寬度,高度是min(a1,an)。

然後,作為高度的兩條邊,不斷往中心推進,直到左端大於右端,則停止迭代。其中比較關鍵的地方在於,在迭代過程中左端高度與右端高度的比較,如果左端的高度小於右端的高度,表明左端的高度是作為整體面積的高度,那麼他跟右端之間所有邊組成的容器都以他為高度(然而可能還有更矮的),這些可能的組合不可能比目前組合的面積大。所以捨棄左端與這些邊的組合,即左端往右移。反之如果左端的高度大於右端的,那麼右端往左移。

關鍵的程式碼如下:

int maxArea(vector<int> height)
{
	int cur_i = 0;
	int cur_j = height.size()-1;
	int water_max = (height.size()-1)*min(height[i],height[j]);
	while(cur_i<cur_j)
	{
		water_max = max(water_max,min(height[cur_i],height[cur_j])*(cur_j-cur_i));
		if(height[cur_i]<height[cur_j])
			cur_i++;
		else
			cur_j--;

	}
	cout<<water_max<<endl;
	return water_max;
}

height包含所有邊。

大概就這樣咯~想個演算法真的可以想到頭皮發麻~