LeetCode # 3Sum #


 



Python解答一 O(n^3) 时间复杂度不符合要求, 暴力美还是很直观:


"""
Programmer  :   EOF
Date        :   2015.04.11
File        :   3sum.py
E-mail      :   jasonleaster@gmail.com

Description :
    This is the first version which I used and try to solve
3Sum problem. It's work correctly but have a bad time complexity.

"""

class Solution:
    # @return a list of lists of length3, [[val1, val2, val3]]
    ret_list = []

    def threeSum(self, num):
        length = len(num)
        for i in range(0, length):
            for j in range(i+1, length):
                for k in range(j+1, length):
                    if num[i] + num[j] + num[k] == 0:
                        
                        tmp = self.sequence(num[i], num[j], num[k])

                        if self.same_solution(tmp) is True:
                            continue
                        else:
                            self.ret_list += [tmp]

        return self.ret_list

    # make sure that in @self.ret_list e1 < e2 < e3
    def sequence(self, a, b, c):
        ret = []
        if a < b:
            if a < c:
                ret += [a]
                if b < c:
                    ret += [b, c]
                else:
                    ret += [c, b]
            else:
                ret += [c, a, b]
        else: # a > b in this situation
            if b < c:
                ret += [b]
                if a < c:
                    ret += [a, c]
                else:
                    ret += [c, a]
            else:
                ret += [c, b, a]

        return ret

    def same_solution(self, sv):

        if len(self.ret_list) != 0 :
            row = len(self.ret_list)
            col = len(self.ret_list[0])

            for i in range(0, row):
                for j in range(0, col):
                    if self.ret_list[i][j] != sv[j]:
                        break;

                if j == col-1:
                    return True

        return False


#------------- just for testing ----------

s = Solution()
Date = [-1, 0, 1, 2, -1, -4]
print s.threeSum(Date)



解答二: 


我只想说...这已经是第四个版本了    (#‵′)

...

会发现代码短了很多, 但是这里还是过不了时间复杂度.

我用了两个hash表,

后面的ret_dic是为了避免出现重复的解答.


"""
Programmer  :   EOF
Date        :   2015.04.11
File        :   3sum_opt_3.py
E-mail      :   jasonleaster@gmail.com

Description :
    This is the #fourth# version which I used and try to solve
3Sum problem. I used dictionary and try to improve the performance.
It's work correctly but also have a bad time complexity.

"""

class Solution:
    # @return a list of lists of length3, [[val1, val2, val3]]
    ret_list = []
    dic  = {}
    ret_dic  = {}

    def threeSum(self, num):
        length = len(num)

        #   Initialize the @dic and @time
        for i in range(0, length):
            if num[i] not in self.dic:
                self.dic[num[i]]  = num[i]

        num.sort()
        # Kernel part of this algorithm
        for i in range(0, length):
            for j in range(i + 1, length):
                
                #It's a old trick to use the inverse number as the index
                if -(num[i] + num[j]) in self.dic:
                    
                    if -(num[i] + num[j]) <= num[i] :
                        tmp = [-(num[i] + num[j]), num[i], num[j] ]
                    elif -(num[i] + num[j]) >= num[j] :
                        tmp = [num[i], num[j], -(num[i] + num[j])]
                    else:
                        tmp = [num[i], -(num[i] + num[j]), num[j]]


                    if str(tmp) not in self.ret_dic:
                        self.ret_dic[str(tmp)] = tmp

        for i in self.ret_dic:
            self.ret_list += [self.ret_dic[i]]

        return self.ret_list

#------------- just for testing ----------

s = Solution()
Date = [-1, 0, 1, 2, -1, -4]
print s.threeSum(Date)

Date = [4,4,3,-5,0,0,0,-2,3,-5,-5,0]
print s.threeSum(Date)


Python 解答三:

之前的两个解答都不能用的 ... 只有这个可以AC.

解答二可能由于构造dictionary的时候比较耗时, 所以时间复杂度有问题.


class Solution:
    # @return a list of lists of length 3, [[val1,val2,val3]]
    def threeSum(self, num):
        if len(num) <= 2:
            return []

        ret = []
        tar = 0
        num.sort()
        i = 0
        while i < len(num) - 2:
            j = i + 1
            k = len(num) - 1
            while j < k:
                if num[i] + num[j] + num[k] < tar:
                    j += 1
                elif num[i] + num[j] + num[k] > tar:
                    k -= 1
                else:
                    ret.append([num[i], num[j], num[k]])
                    j += 1
                    k -= 1
                    # folowing 3 while can avoid the duplications
                    while j < k and num[j] == num[j - 1]:
                        j += 1
                    while j < k and num[k] == num[k + 1]:
                        k -= 1
            while i < len(num) - 2 and num[i] == num[i + 1]:
                i += 1
            i += 1
        return ret


凯旋冲锋的 Java 解答:


package _3sum;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

public class Solution {
	public List<List<Integer>> threeSum(int[] num) {
		Arrays.sort(num);
		List<List<Integer>> result = new LinkedList<>();
		for (int i = num.length - 1; i > 1; i--) {
			if (i + 1 < num.length && num[i] == num[i + 1]) {
				continue;
			}
			for (int j = 0, k = i - 1; j < k; ) {
				int sum = num[j] + num[k] + num[i];
				if (sum < 0) {
					j++;
				} else if (sum > 0) {
					k--;
				} else {
					result.add(Arrays.asList(num[j], num[k], num[i]));
					do {
						j++;
						k--;
					} while (j < k && num[j - 1] == num[j] && num[k] == num[k + 1]);
				}
			}
		}
		return result;
	}

	public static void main(String[] args) {
		System.out.println(new Solution().threeSum(new int[]{0, 0, 0, 0, 0, 0, 0}));
	}
}



皓神的C++ 

Skip to content
 This repository
Explore
Gist
Blog
Help
@jasonleaster jasonleaster
 
 Unwatch 2
  Star 0
 Fork 920penguiner/leetcode-1
forked from haoel/leetcode
 branch: master  leetcode-1/src/3Sum/3Sum.cpp
@haoelhaoel on 31 Oct 2014 Add comments to explain the solutions
1 contributor
RawBlameHistory    188 lines (166 sloc)  5.134 kb
// Source : https://oj.leetcode.com/problems/3sum/
// Author : Hao Chen
// Date   : 2014-07-22

/********************************************************************************** 
* 
* Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? 
* Find all unique triplets in the array which gives the sum of zero.
* 
* Note:
* 
* Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
* The solution set must not contain duplicate triplets.
* 
*     For example, given array S = {-1 0 1 2 -1 -4},
* 
*     A solution set is:
*     (-1, 0, 1)
*     (-1, -1, 2)
* 
*               
**********************************************************************************/

#include <stdio.h>
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;


/*
 *   Simlar like "Two Number" problem, we can have the simlar solution.
 *
 *   Suppose the input array is S[0..n-1], 3SUM can be solved in O(n^2) time on average by 
 *   inserting each number S[i] into a hash table, and then for each index i and j,  
 *   checking whether the hash table contains the integer - (s[i]+s[j])
 *
 *   Alternatively, the algorithm below first sorts the input array and then tests all 
 *   possible pairs in a careful order that avoids the need to binary search for the pairs 
 *   in the sorted list, achieving worst-case O(n^n)
 *
 *   Solution:  Quadratic algorithm
 *   http://en.wikipedia.org/wiki/3SUM
 *
 */
vector<vector<int> > threeSum(vector<int> &num) {

    vector< vector<int> > result;

    //sort the array, this is the key
    sort(num.begin(), num.end());

    int n = num.size();

    for (int i=0; i<n-2; i++) {
        //skip the duplication
        if (i>0 && num[i-1]==num[i]) continue;
        int a = num[i];
        int low = i+1;
        int high = n-1;
        while ( low < high ) {
            int b = num[low];
            int c = num[high];
            if (a+b+c == 0) {
                //got the soultion
                vector<int> v;
                v.push_back(a);
                v.push_back(b);
                v.push_back(c);
                result.push_back(v);
                // Continue search for all triplet combinations summing to zero.
                //skip the duplication
                while(low<n && num[low]==num[low+1]) low++; 
                while(high>0 && num[high]==num[high-1]) high--; 
                low++;
                high--;
            } else if (a+b+c > 0) {
                //skip the duplication
                while(high>0 && num[high]==num[high-1]) high--;
                high--;
            } else{
                //skip the duplication
                while(low<n && num[low]==num[low+1]) low++;
                low++;
            } 
        }
    }
    return result;
}

//using combination method could meet <<Time Limit Exceeded>> error
vector<vector<int> > combination(vector<int> &v, int k);
bool isSumZero(vector<int>& v);
int sum(vector<int>& v);

vector<vector<int> > threeSum2(vector<int> &num) {
    vector< vector<int> > result;
    vector< vector<int> > r = combination(num, 3);
    for (int i=0; i<r.size(); i++){
        if (isSumZero(r[i])){
            result.push_back(r[i]);
        }
    }
    return result;
}

bool isSumZero(vector<int>& v){
    return sum(v)==0;
}

int sum(vector<int>& v){
    int s=0;
    for(int i=0; i<v.size(); i++){
        s += v[i];
    }
    return s;
}

vector<vector<int> > combination(vector<int> &v, int k) {

    vector<vector<int> > result;
    vector<int> d;
    int n = v.size();
    for (int i=0; i<n; i++){
        d.push_back( (i<k) ? 1 : 0 );
    }

    //1) from the left, find the [1,0] pattern, change it to [0,1]
    //2) move all of the 1 before the pattern to the most left side
    //3) check all of 1 move to the right
    while(1){
        vector<int> tmp;
        for(int x=0; x<n; x++){
            if (d[x]) tmp.push_back(v[x]);
        }
        sort(tmp.begin(), tmp.end());
        result.push_back(tmp);
        //step 1), find [1,0] pattern
        int i;
        bool found = false;
        int ones =0;
        for(i=0; i<n-1; i++){

            if (d[i]==1 && d[i+1]==0){
                d[i]=0; d[i+1]=1;
                found = true;
                //step 2) move all of right 1 to the most left side
                for (int j=0; j<i; j++){
                    d[j]=( ones > 0 ) ? 1 : 0;
                    ones--;
                }
                break;
            }
            if (d[i]==1) ones++;
        }
        if (!found){
            break;
        }

    }
    return result;
}


void printMatrix(vector<vector<int> > &matrix)
{
    for(int i=0; i<matrix.size(); i++){
        printf("{");
        for(int j=0; j< matrix[i].size(); j++) {
            printf("%3d ", matrix[i][j]) ;
        }
        printf("}\n");
    }
    cout << endl;
}


int main()
{
    //int a[] = {-1, 0, 1, 2, -1, 1, -4};
    int a[] = {-1, 1, 1, 1, -1, -1, 0,0,0};
    vector<int> n(a, a+sizeof(a)/sizeof(int));
    vector< vector<int> > result = threeSum(n);
    printMatrix(result);    
    return 0;
}
Status API Training Shop Blog About
© 2015 GitHub, Inc. Terms Privacy Security Contact







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值