1. 程式人生 > >LeetCode 561. Array Partition I(easy難度c++)

LeetCode 561. Array Partition I(easy難度c++)

return 可能 hid 使用 ide 復雜度 wid () ger

題目:
Given an array of 2n integers, your task is to group these integers into n pairs of integer, say (a1, b1), (a2, b2), …, (an, bn) which makes sum of min(ai, bi) for all i from 1 to n as large as possible.

Example 1:
Input: [1,4,3,2]

Output: 4
Explanation: n is 2, and the maximum sum of pairs is 4.
Note:
n is a positive integer, which is in the range of [1, 10000].
All the integers in the array will be in the range of [-10000, 10000].

思路:
就是給2n個數分組,兩兩一組,使得每一組中最小的那個數的和最大。這個問題其實很有趣,最終我們要做的事情就是選出來的的數字是兩個數中最小的,但卻要盡可能的大,這樣才能使得n個數字求和之後得到的結果最大。不妨這樣想,先把這些數字數字排序,得到由小到大的有序數組,從最大的數字挑起,最大的數字顯然最後不會參與求和,那它該挑誰走才能為最後的加和貢獻一個大的數字呢?顯然是第二大的數;由此類推,第三大應該和第四大數字配對,也就是說對有序數組兩兩分組即可。問題的關鍵變為選擇高效的排序算法
關於為何要這麽選數字,嚴格證明如下:

  • 假設對於每一對i,bi >= ai。
  • 定義Sm = min(a1,b1)+ min(a2,b2)+ … + min(an,bn)。最大的Sm是這個問題的答案。由於bi >= ai,Sm = a1 + a2 + … + an。
  • 定義Sa = a1 + b1 + a2 + b2 + … + an + bn。對於給定的輸入,Sa是常數。
  • 定義di = | ai - bi |。由於bi >= ai,di = bi-ai, bi = ai+di。
  • 定義Sd = d1 + d2 + … + dn。
  • 所以Sa = a1 + (a1 + d1) + a2 + (a2 + d2) + … + an + (an + di) = 2Sm + Sd , 所以Sm =(Sa-Sd)/ 2。為得到最大Sm,給定Sa為常數,需要使Sd盡可能小。
  • 所以這個問題就是在數組中找到使di(ai和bi之間的距離)的和盡可能小的對。顯然,相鄰元素的這些距離之和是最小的

排序問題是個老生常談的問題,我最開始用的冒泡排序,但是最後的4組測試數據沒有通過,報錯超時,因為O(n^2)的復雜度處理較長序列時是很費時間的,但是冒泡排序作經典的排序算法,應當掌握,代碼如下:

技術分享
 1 class Solution {
 2 public:
 3     int arrayPairSum(vector<int>& nums) {
 4         int temp;
 5         for(int i=1;i<nums.size();i++)
 6         {
 7           for(int j=0;j<nums.size()-i-1;j++)
 8           {
 9               if(nums[j]>nums[j+1])
10               {
11                   temp = nums[j];
12                   nums[j]=nums[j+1];
13                   nums[j+1]=temp;
14               }
15           }
16         }
17         sort (nums.begin(), nums.end());
18         int sum=0;
19         for(int i=0;i<nums.size();i=i+2)
20            sum+=nums[i];
21        return sum;
22     }
23 };
View Code

技術分享

最後報錯超時,於是我改用快排,代碼如下

但是最優解應當是使用STL模板中的sort()函數,直接通過所有測試數據,代碼簡單。時間復雜度O(n*logn),這已經是排序算法中最優的復雜度了,但是在面試過程中是否允許使用STL應當征求面試官的意見。sort()函數的使用參見 http://www.cplusplus.com/reference/algorithm/sort/?kw=sort

代碼如下:

技術分享
 1 class Solution {
 2 public:
 3     int arrayPairSum(vector<int>& nums) {
 4         sort (nums.begin(), nums.end());
 5         int sum=0;
 6         for(int i=0;i<nums.size();i=i+2)
 7            sum+=nums[i];
 8        return sum;
 9       
10     }
11 };
View Code

LeetCode 561. Array Partition I(easy難度c++)