1. 程式人生 > >LeetCode Sum Question

LeetCode Sum Question

Question 1.兩個數求和問題,找出求和等於target的數對,只有一對。

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [7, 2, 11, 15], target = 9,

Because nums[0
] + nums[1] = 7 + 2 = 9, return [0, 1].

Solution 1、直接採用雙迴圈來暴力求解,但是問題是時間複雜度高。

Solution 2、對陣列先進行排序,然後根據target-nums[i]求得補數,然後在陣列中查詢補數是否存在,該方法的時間複雜度是:

(排序)O(NlogN) + (遍歷並查詢)O(NlogN),所以總的複雜度是O(NlogN)。

Solution 3、採用HashMap,時間複雜度是O(N)

#define SIZE 100000

int hash(int key) {
    int r = key % SIZE;
    return r < 0 ? r + SIZE : r;
}

void insert(int *keys, int *values, int key, int value) {
    int index = hash(key);
    while (values[index]) {
        index++;
        index %= SIZE;
    }
    keys[index] = key;
    values[index] = value;
}

int search(int *keys, int *values, int key) {
    int index = hash(key);
    while (values[index]) {
        if (keys[index] == key) {
            return values[index];
        }
        index++;
        index %= SIZE;
    }
    return 0;
}

int* twoSum(int* nums, int numsSize, int target) {
    int keys[SIZE];
    int values[SIZE] = {0};
    for (int i = 0; i < numsSize; i++) {
        int complements = target - nums[i];
        int index = search(keys, values, complements);
        if (index) {
            int *indices = (int *) malloc(sizeof(int) * 2);
            indices[0] = --index;
            indices[1] = i;
            return indices;
        }
        insert(keys, values, nums[i], i + 1);
    }
    return NULL;
}

Question 2、三數求和的問題。

Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Example:

Given array nums = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

Solution 1、暴力求解,時間複雜度O(N^3)

Solution 2、採取定一個數或者兩個數,這裡我們假定我們每次取定三個數中的第一個數。然後用兩個指標p,q指定首尾,然後往中間走,採取一個夾逼的辦法實現。時間複雜度是O(N^2)

class Solution {   
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result= new ArrayList<List<Integer>>();
        Arrays.sort(nums);
        int p,q,Balance,i,sum;
        for(i = 0;i < nums.length-2;i++)
        {
            p = i;
            Balance = i+1;
            q = nums.length-1;  
            while(q > Balance)
            {
                sum = nums[p] + nums[Balance] + nums[q];
                //小了
                if(sum < 0)
                    Balance++;
                //大了
                else if(sum > 0)
                    q--;
                else
                {
                        List<Integer> Temp = new ArrayList<Integer>();
                        Temp.add(nums[p]);
                        Temp.add(nums[Balance]);
                        Temp.add(nums[q]);
                        result.add(Temp);
                        //剪枝
                        while(nums[Balance+1] == nums[Balance] && Balance < q && Balance < nums.length-2)
                            Balance++;
                        while(nums[q-1] == nums[q] && Balance < q && q > 1)
                            q--;
                        Balance++;
                        q--;
                }
            }//while
            while(nums[i+1] == nums[i] && i < nums.length-2)
                i++;
            
        }//for
        return result;
    }
}

Question 3、找最接近給定Target的三個數。

Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

Given array nums = [-1, 2, 1, -4], and target = 1.

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

Solution 1、採用雙指標的辦法,設定一個上下邊界,每次定一個數,然後設定兩個指標從兩頭開始遍歷,不停的進行邊界的修改,最後比較上下邊界和target的差距誰小就返回誰。

class Solution {
    public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);
        int p,B,q;
        int UpBoard=10000;
        int DownBoard = -10000;
        int sum;
        for(int i = 0;i < nums.length-2;i++)
        {
            p = i;
            B = p+1;
            q = nums.length-1;
            while(B+1 <= q)
            {
                sum = nums[p] + nums[B] + nums[q];
                if(sum == target)
                    return target;
                if(sum > target)
                    q--;
                if(sum <UpBoard && sum >=target)
                    UpBoard = sum;                
                if(sum < target)
                    B++;
                if(sum >  DownBoard && sum < target)
                    DownBoard = sum;
            }
        }//for  
        int dis;
        dis = UpBoard - target;
        if(dis < target-DownBoard)
            return UpBoard;
        else
            return DownBoard;
    }   
}

Quesiont 4、4個數查詢和等於target的所有數對。

Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:

The solution set must not contain duplicate quadruplets.

Example:

Given array nums = [1, 0, -1, 0, -2, 2], and target = 0.

A solution set is:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]

Solution:和上面的差不多,只是要多重迴圈,我們可以定前兩個數,A,B,然後設定兩個指標p,q,從首尾來夾逼。

Solution
class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        int i,j;
        int p1,p2,mid,q;
        int sum;
        int tempSum;
        for(i = 0;i < nums.length;i++)
        {
            for(j = i+1;j < nums.length;j++)
            {
                p1 = i;
                p2 = j;
                mid = p2 + 1;
                q = nums.length-1;
                tempSum = nums[p1] + nums[p2];
                while(mid < q)
                {
                    sum = tempSum + nums[mid] + nums[q];
                    if(sum  == target)
                    {
                        List<Integer> Temp = new ArrayList<Integer>();
                        Temp.add(nums[p1]);
                        Temp.add(nums[p2]);
                        Temp.add(nums[mid]);
                        Temp.add(nums[q]);
                        result.add(Temp);
                        while(mid < q && mid < nums.length-2 &&  nums[mid+1] == nums[mid])
                            mid++;
                        while(mid < q && q > 1 && nums[q-1] == nums[q])
                            q--;
                        q--;
                        mid++;
                    }
                    else if(sum > target)
                        q--;
                    else
                        mid++;
                }//while
                while(j < nums.length-1 && nums[j+1] == nums[j])
                    j++;
            }
            while(i < nums.length-1 && nums[i+1] == nums[i])
                i++;
        }//for
        return result;
    }
}