1. 程式人生 > 其它 >【演算法百題之四十八】最接近數的三數之和

【演算法百題之四十八】最接近數的三數之和

技術標籤:演算法百題最接近數的三數之和演算法leetcode

【演算法百題之四十八】最接近數的三數之和

大家好,我是Lampard~~

很高興又能和大家見面了,接下來準備系列更新的是演算法題,一日一練,早日升仙!

今天的問題是:最接近數的三數之和

示例:

輸入:nums = [-1,2,1,-4], target = 1
輸出:2
解釋:與 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。

思路:由於這道題和昨天做的演算法題【三數之和】太像了,所以按照昨天的思路,很快啊,我們就找到了答案。回顧一下我們昨天解三數之和用的兩個方法:1.巧用鍵值對,2.雙指標法。

使用鍵值對,我們可以利用兩重迴圈,定義target = 0 - i- j,我們可以直接利用map【target】來判斷是否存在符合要求的答案,從而減少一道迴圈的工序。但是在這裡這個方法就行不通了,為什麼?因為我們求的是最接近,也就是說target我們不能確認是多少,因此鍵值對方式不適合這個題目。ok那麼我們使用另外的思路,雙指標法。

最終程式碼如下:

int threeSumClosest(vector<int>& nums, int target) {
	int res = INT_MAX / 2;
	sort(nums.begin(), nums.end());
	for (int i = 0; i < nums.size(); i++) {
        if(nums[i] > target) return res;
		int left = i + 1;
		int right = nums.size() - 1;
		while (left < right) {
			int curNum = nums[i] + nums[left] + nums[right];
			res = abs(curNum - target) < abs(res - target) ? curNum : res;
			if (curNum > target) {
				right--;
				continue;
			}
			
			if (curNum < target) {
				left++;
				continue;
			}

			return target;
		}
	}
	return res;
}

程式碼很簡單,首先把陣列給拍一次序,然後我們的思路是令nums【i】 + nums【left】 + nums【right】 = target,其中(i < left < right)那若nums【i】都比target大,那不用玩了,直接返回res。若能進入迴圈,我們判斷當前這三個值加起來是否比target大,若大則right--,若小left++,若剛好找到nums【i】 + nums【left】 + nums【right】 = target這怎麼辦?那就直接返回target嘛,題目要求最接近target的三個數的和。在此過程中我們就通過這三個數的和與target差值的絕對值,對res進行更新

即可。

res = abs(curNum - target) < abs(res - target) ? curNum : res;

這裡可能大家對一個地方還不是很明白,為什麼res的預設值定義位INT_MAX / 2, 首先若定義成任意一個數,那剛好就是target怎麼辦......你還讓不讓人更新找答案了。那麼定義成INT_MAX,INT_MIN行不行啊?不行,沒看到有res-target這個操作麼?target是正數INT_MIN越界,是負數INT_MAX越界,由於題目的定義target的範圍是±10000,所以INT_MAX / 2夠用了。

測試結果:

OK,今天的部落格就到這裡,謝謝大家!!!