LeetCode 3Sum&&3Sum Closest&&4Sum

終於做了決定,開始做LeetCode,上來先做了3題都是關於sum的,這三題我認爲都是從同一個問題變過來的,很多人都知道一個經典的問題就是給你一個數組a和一個數字tar,問你這個數組中有沒有兩個數的和等於這個給定的數字tar,顯然要用O(N)的方法,這個問題的答案就是先排序,然後定義兩個邊界l和r,l一開始等於0,r一開始等於n-1,每次把邊界指的兩個數相加和給定的數tar比較一下,如果比tar小,那麼l++,比tar大,那麼r--,如果等於那麼l++,r--。那麼問題來了,爲什麼a[l]+a[r]<tar的時候,只需要l++就好了,這是這個做法的關鍵,這是因爲當a[l]+a[r]<tar的時候,肯定有a[l]+a[k]<=a[l]+a[r]<tar,k=[l+1,r-1],因爲數組是排好序的。同理也可以說明r--的原因。

這樣說來的話,可以用O(N)的方法解決數組中是否有2個數的和等於給定一個數的問題,那麼三個數只需要枚舉一個數a[i],用這個tar減去枚舉的這個數,然後再用O(N)的時間判斷剩下的數有沒有兩個數的和等於tar-a[i]。時間複雜度是O(N*N)。

還有一個問題就是判重,實話說判重花了我很多時間。主要就是有兩點:

第一,枚舉i後,j一定是i+1開始枚舉。

第二,對於枚舉的i,j,k如果我發現當前枚舉的量和上次循環枚舉的值是相等的。那麼這次直接continue。

3sum的代碼如下:

class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
        int i ,j,k;
        int n=num.size();
		vector<int>ans;
		vector<vector<int> >cl;
		sort(num.begin(),num.end());
		for(i=0;i<n;i++)
       	{
	     	if(num[i]==num[i-1]&&i>0)
	     	continue;
	 		for(j=i+1,k=n-1;j<k;)
	 		{
			 	if(num[j]==num[j-1]&&j>i+1)
			 	{
	 				j++;
	     			continue;
			 	}
			 	if(num[k]==num[k+1]&&k<n-1)
			 	{
	 				k--;
	 				continue;
	 			}
			 	if(num[j]+num[k]+num[i]==0)
			 	{
				 	ans.push_back(num[i]);
				 	ans.push_back(num[j]);
				 	ans.push_back(num[k]);
				 	cl.push_back(ans);
				 	ans.clear();
				 	j++;
				 	k--;
 				}
			 	else if(num[j]+num[k]+num[i]<0)	
	 				j++;
	 			else 
	 				k--;
 			}  	
       	}
       	return cl;
    }
};


接下來是3sumclosest,讓你找出3個數的和與tar最接近,我覺得這個問題出的很好,他真的是考察了你到底是否真正理解O(N)的方法處理兩個數的和等於一個tar。因爲每次變化,l++或者r--,都是往tar的方向靠近(小於tar則增大,增大可能增的太大,如比tar小4變成了大5,大於tar則減小),而排除了往tar的反方向。所以closest的做法就由此產生了,我把所有能靠近tar的情況遍歷一邊,把每次與tar的差距選擇一個最小的就是答案。

3sumclosest 代碼如下:

class Solution {
int abs(int x)
{
    return x>0?x:-x;
}
public:
    int threeSumClosest(vector<int> &num, int target) {
        int n=num.size();
        int i,j,k;
        sort(num.begin(),num.end());
        int min=100000000;
        int ans;
        for(i=0;i<n;i++)
        {
            for(j=i+1,k=n-1;j<k;)
            {
                if(abs(num[i]+num[j]+num[k]-target)<min)
                {
                	min=abs(num[i]+num[j]+num[k]-target);
                	
                	ans=num[i]+num[j]+num[k];
                }
                if(num[j]+num[k]+num[i]>target)
                    k--;
                else if(num[j]+num[k]+num[i]<target)
                    j++;
				else 
					return target;
            }
            
        }
        return ans;
    }
};


最後4sum如果用O(N^3)的複雜度能過的話,這題也算是簡單了,和3sum一樣的去重法,一樣的思想,代碼如下:

class Solution {
public:
    vector<vector<int> > fourSum(vector<int> &num, int target) {
        int n=num.size();
        vector<vector<int> >ans;
        int i,k,j,l;
        vector<int>tmp;
        sort(num.begin(),num.end());
        for(i=0;i<n;i++)
        {
            if(i>0&&num[i]==num[i-1])
			    continue;

            for(j=i+1;j<n;j++)
            {
				if(j>i+1&&num[j]==num[j-1])
                    continue;
                int sum=target-num[i]-num[j];
                for(k=j+1,l=n-1;k<l;)
                {
					if(k>j+1&&num[k]==num[k-1])
                    {
                    	k++;
						continue;
                    }
                    if(l<n-1&&num[l]==num[l+1])
                    {
    					l--;
       	 				continue;
                    }
                    if(num[k]+num[l]==sum)
                    {
                        tmp.clear();
						tmp.push_back(num[i]);
                        tmp.push_back(num[j]);
                        tmp.push_back(num[k]);
                        tmp.push_back(num[l]);
                        ans.push_back(tmp);
                        k++;
                        l--;
                    }
                    else  if(num[k]+num[l]<sum)
						k++;
                    else 
                        l--;
                }
            }
        }
        return ans;   
    }
};



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章