算法題丨4Sum

描述

Given an array S of n integers, are there elements a, b, c, and d in S 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.git

示例

Given array S = [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]
]

算法分析

難度:中
分析:給定整型數組和指定一個整型目標值,從整形數組中找出4個不一樣的元素,使得4個元素之和等於目標值,返回結果爲全部知足上述條件的元素組合。
思路:思路能夠參考3Sum,主要難度是由原先的找3個元素之和,變成了找4個元素之和。這種狀況下,其實有點像解魔方:玩五階魔方就是從五階降到四階,而後再從四階降到三階,最後再按照玩三階魔方的方法解決問題。
最終的解法,其實就是在3階解法的基礎上,在外層再套一層4階的循環,並作一些基礎的判斷,複雜度也是在3階n²基礎上*n=n³,固然,這種算法也可推廣到n階。github

代碼示例(C#)

public IList<IList<int>> FourSum(int[] nums, int target)
{
    List<IList<int>> res = new List<IList<int>>();
    if (nums.Length < 4) return res;

    //排序
    Array.Sort(nums);
    //4階判斷
    for (int i = 0; i < nums.Length - 3; i++)
    {
        //若是最近4個元素之和都大於目標值,由於數組是排序的,後續只可能更大,因此跳出循環
        if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) break;
        //當前元素和最後3個元素之和小於目標值即本輪最大值都小於目標值,則本輪不知足條件,跳過本輪
        if (nums[i] + nums[nums.Length - 1] + nums[nums.Length - 2] + nums[nums.Length - 3] < target)
            continue;
        //防止重複組合
        if (i > 0 && nums[i] == nums[i - 1]) continue;

        //3階判斷
        for (int j = i + 1; j < nums.Length - 2; j++)
        {
            //原理同4階判斷
            if (nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) break;
            if (nums[i] + nums[j] + nums[nums.Length - 1] + nums[nums.Length - 2] < target)
                continue;

            int lo = j + 1, hi = nums.Length - 1;
            while (lo < hi)
            {
                //已知元素 nums[i],nums[j],剩下2個元素作夾逼
                int sum = nums[i] + nums[j] + nums[lo] + nums[hi];
                if (sum == target)
                {
                    res.Add(new List<int> { nums[i], nums[j], nums[lo], nums[hi] });
                    while (lo < hi && nums[lo] == nums[lo + 1]) lo++;
                    while (lo < hi && nums[hi] == nums[hi - 1]) hi--;
                    lo++;
                    hi--;
                }
                //兩邊夾逼
                else if (sum < target) lo++;
                else hi--;
            }
        }
    }
    return res;
}

複雜度

  • 時間複雜度O (n³).
  • 空間複雜度O (1).

附錄

相關文章
相關標籤/搜索