LeetCode總結-K-Sum問題

最近在刷 LeetCode 上的題為找工作提前做準備享潜,在刷 Array 類問題的 Easy 難度的題的時候覺得還好,大部分的題還是能夠想得出來排龄,但是在刷到 Medium 難度的時候惜互,明顯感覺難度提升了吴菠,其中有一類題型連續(xù)出現(xiàn)引起了我的注意橄教,就是 K Sum 問題清寇。

K Sum問題就是喘漏,給出一個數(shù)作為 target,和一個數(shù)組作為待查數(shù)組华烟,在這個待查數(shù)組里找出 K 個數(shù)之和等于 target.

最簡單的 2 Sum

2 Sum應該是最簡單的了翩迈,但是它是解決我們后面 3 Sum和 4 Sum 問題的最小子問題了。如果一開始就用暴力循環(huán)的方法當然是做的出來盔夜,但是负饲,一是 LeetCode 可能會判超時(在 3 Sum 和 4 Sum 問題中確實會超時) ,二是暴力窮舉也沒什么意思喂链。最簡單的窮舉法是 O(n^2) 的時間復雜度返十,那么我們可以將數(shù)組排好序后,用頭尾兩個指針一次迭代即可找出椭微,時間復雜度降為了 O(nlogn).

3 Sum 問題

接下來就是3 Sum問題了吧慢,用暴力法 LeetCode 已經(jīng)給出了超時的提醒了,所以O(n^3)的時間復雜度肯定是不能接受的赏表,那么我們可以想像如何分解問題,畢竟3 Sum=2 Sum + 1 Sum匈仗,那么我們完全可以用將上面 2 Sum 問題的解法嵌入到一層循環(huán)中瓢剿,也就是先排序然后一個指針從頭開始循環(huán),在數(shù)組的其他數(shù)中找出 2個數(shù)的和加上這個指針指向的數(shù)的和等于 target就行了悠轩,也就是說我們已經(jīng)有了循環(huán)指針指向的這個數(shù) V间狂,那么我們只需要在其他書中找出 num1+num2=target-V就行了,這就又把問題帶回到了2 Sum上火架,中不過多了一層循環(huán)鉴象,時間復雜度就降為了 O(n^2)。

代碼實例:

/*注題目
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: The solution set must not contain duplicate triplets.
*/
public class Solution {
   public static List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result=new ArrayList<>();
        Arrays.sort(nums);
        for(int i=0;i<nums.length-2;i++)
        {
            if(i>0&&nums[i]==nums[i-1]) //跳過相同的數(shù)以避免相同的List的產(chǎn)生
            {
                continue;
            }
            find(result,nums,i+1,nums.length-1,nums[i]);
        }
       return result;
   }
    public static void find(List<List<Integer>> res,int[] nums,int start,int end,int target)
    {
        int l=start,r=end;
        while(l<r)
        {
            if(target+nums[l]+nums[r]==0)
            {
                List<Integer> list=new ArrayList<>();
                list.add(target);
                list.add(nums[l]);
                list.add(nums[r]);
                res.add(list);
                while(l<r&&nums[l]==nums[l+1])//跳過相同的數(shù)
                {
                    l++;
                }
                while(l<r&&nums[r]==nums[r-1])//跳過相同的數(shù)
                {
                    r--;
                }
                l++;
                r--;
            }else if(target+nums[l]+nums[r]<0)//如果和小于0(target),l右移擴大和
            {
                l++;
            }else//否則左移縮小和
            {
                r--;
            }
        }
    }
        
}

3Sum Closest 問題

3Sum Closest 問題是3 Sum 問題的一個變種何鸡,意思就是給出一個 target纺弊,找出數(shù)組中最接近 target的 3 個數(shù)之和。這道題和 3 Sum 很像骡男,不同的是需要用一個臨時變量來保存當前最接近 target 的值,值得注意的是我們需要求 3個數(shù)的和減去 target 的差的絕對值來求最接近 target 的數(shù)。

/*
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
    For example, given array S = {-1 2 1 -4}, and target = 1.

    The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
*/
public class Solution {
     public static int threeSumClosest(int[] nums, int target) {
        int result=Integer.MAX_VALUE;//用來保存當前最接近target的值
        Arrays.sort(nums);
        for(int i=0;i<nums.length-2;i++)
        {
            int temp=find(nums,i+1,nums.length-1,target,nums[i]);
            if(i==0)
            {
                result=temp;
                continue;
            }
            if(Math.abs(temp-target)<Math.abs(result-target))
            {
                result=temp;
            }
        }
        return result;
    }

    public static int find(int[] nums,int start,int end,int target,int curV)
    {
        int result=Integer.MAX_VALUE;
        int l=start,r=end;
        int c=Integer.MAX_VALUE;
        while(l<r&&c!=0)
        {
            if(Math.abs(curV+nums[l]+nums[r]-target)<c)
            {
                result =curV+nums[l]+nums[r];
                c=Math.abs(curV+nums[l]+nums[r]-target);
            }
            if(curV+nums[l]+nums[r]>target)
            {
                r--;
            }else
            {
                l++;
            }
        }
        return result;
    }
}

4 Sum 問題

4 Sum問題也顯而易見了螃成,就是求 4 個數(shù)的和等于target朗儒,那么我們可以如法炮制,前面的3 Sum我們是固定一個數(shù)吮炕,然后求兩個數(shù)的和腊脱,將其分解為 2 Sum + 1 Sum,呢么 4 Sum 我們可以同樣的先固定兩個數(shù)龙亲,與另外兩個活動的數(shù)相加等于target陕凹,也就輸 4 Sum=3 Sum+1Sum悍抑。再在3 Sum的基礎上嵌套一層循環(huán)就可以達到目的了,時間復雜度也降低為了O(n^3)捆姜。

/*
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.

For example, 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]
]
*/
public class Solution {
    public static List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> res=new ArrayList<>();
        Arrays.sort(nums);
        for(int i=0;i<nums.length-3;i++)//固定第一個數(shù)
        {
            if(i>0&&nums[i]==nums[i-1])//跳過相同的數(shù)
            {
                continue;
            }
            for(int j=i+1;j<nums.length-2;j++)//固定第二個數(shù)
            {
                if(j>i+1&&nums[j]==nums[j-1])//跳過相同的數(shù)
                {
                    continue;
                }
                find(nums,res,j+1,nums.length-1,target,nums[i],nums[j]);
            }
        }
        return res;
    }
    public static void find(int[] nums,List<List<Integer>> res,int start,int end,int target,int v1,int v2)
    {
        int l=start,r=end;
        while(l<r)
        {
            if(nums[l]+nums[r]+v1+v2==target)
            {
                List<Integer> list=new ArrayList<>();
                list.add(nums[l]);
                list.add(nums[r]);
                list.add(v1);
                list.add(v2);
                res.add(list);
                while(l<r&&nums[l]==nums[l+1])
                {
                   l++;
                }
                while(l<r&&nums[r]==nums[r-1])
                {
                   r--;
                }
                l++;
                r--;
            }else if(nums[l]+nums[r]+v1+v2<target)
            {
                l++;
            }else
            {
                r--;
            }
        }
    }
    
}

總結

做了 30 多到題传趾,發(fā)現(xiàn)一個規(guī)律,如果排序后不使用二分查找或者雙指針利用排序特性的話泥技,那么排序書沒有意義的浆兰,同時利用 Hash 特性也可以在增大空間復雜的同時減小時間復雜度。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末珊豹,一起剝皮案震驚了整個濱河市簸呈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌店茶,老刑警劉巖蜕便,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異贩幻,居然都是意外死亡轿腺,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門丛楚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來族壳,“玉大人,你說我怎么就攤上這事趣些》戮#” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵坏平,是天一觀的道長拢操。 經(jīng)常有香客問我,道長舶替,這世上最難降的妖魔是什么令境? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮坎穿,結果婚禮上展父,老公的妹妹穿的比我還像新娘。我一直安慰自己玲昧,他們只是感情好栖茉,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著孵延,像睡著了一般吕漂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上尘应,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天惶凝,我揣著相機與錄音吼虎,去河邊找鬼。 笑死苍鲜,一個胖子當著我的面吹牛思灰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播混滔,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼洒疚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了坯屿?” 一聲冷哼從身側響起油湖,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎领跛,沒想到半個月后乏德,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡吠昭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年喊括,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片矢棚。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡瘾晃,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出幻妓,到底是詐尸還是另有隱情,我是刑警寧澤劫拢,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布肉津,位于F島的核電站,受9級特大地震影響舱沧,放射性物質(zhì)發(fā)生泄漏妹沙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一熟吏、第九天 我趴在偏房一處隱蔽的房頂上張望距糖。 院中可真熱鬧,春花似錦牵寺、人聲如沸悍引。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽趣斤。三九已至,卻和暖如春黎休,著一層夾襖步出監(jiān)牢的瞬間浓领,已是汗流浹背玉凯。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留联贩,地道東北人漫仆。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像泪幌,于是被迫代替她去往敵國和親盲厌。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 背景 一年多以前我在知乎上答了有關LeetCode的問題, 分享了一些自己做題目的經(jīng)驗座菠。 張土汪:刷leetcod...
    土汪閱讀 12,744評論 0 33
  • 最近刷題發(fā)現(xiàn)k sum問題是非常經(jīng)典的一種題型狸眼,看過別人代碼后,總結求解k sum問題的通常思路浴滴。文章參考知乎le...
    BeLLESS閱讀 1,731評論 0 0
  • LeetCode 刷題隨手記 - 第一部分 前 256 題(非會員)拓萌,僅算法題,的吐槽 https://leetc...
    蕾娜漢默閱讀 17,778評論 2 36
  • 主食:燒烤升略,涮鍋一體 價位:98元每位微王,支持團購 位置:領先市場電影院6層 店面:四人桌,六人桌品嚣,包間12人 桌 ...
    可苦可樂21314閱讀 358評論 0 0
  • 子曰:自天子以至于庶人炕倘,壹是以修身為本。 金無赤足翰撑,人無完人罩旋。克己修身的深度很大程度上決定了一個人取得成就的高度眶诈。...
    堅冰至_Monsol閱讀 922評論 0 6