LeetCode高頻算法面試題 - 001 - 兩數(shù)之和

大家好,我是漫步coding, 最近在整理2022年Redis最新面試題, 大家也可以通過我下面的博客地址在線閱讀,今天講講LeetCode高頻算法面試題 - 兩數(shù)之和。本文首發(fā)于公眾號:漫步coding

題目來源于 LeetCode 上第 1 號問題:兩數(shù)之和。題目難度為 Easy。

題目描述

給定一個整數(shù)數(shù)組 nums 和一個目標值 target,請你在該數(shù)組中找出和為目標值的那 兩個 整數(shù),并返回他們的數(shù)組下標杠人。

你可以假設(shè)每種輸入只會對應(yīng)一個答案。但是宋下,你不能重復利用這個數(shù)組中同樣的元素嗡善。

題目難度: ★

示例:

給定 nums = [2, 7, 11, 15], target = 9

因為 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

示例 2:

輸入:nums = [3,2,4], target = 6
輸出:[1,2]

示例 3:

輸入:nums = [3,3], target = 6
輸出:[0,1]

題目解析

使用查找表來解決該問題。

設(shè)置一個 map 容器 record 用來記錄元素的值與索引杨凑,然后遍歷數(shù)組 nums滤奈。

  • 每次遍歷時使用臨時變量 complement 用來保存目標值與當前值的差值
  • 在此次遍歷中查找 record ,查看是否有與 complement 一致的值撩满,如果查找成功則返回查找值的索引值與當前變量的值 i
  • 如果未找到蜒程,則在 record 保存該元素與索引值 i

代碼實現(xiàn)

tips: 以下代碼是使用Go代碼實現(xiàn)的不同解法, 文章最后可以看C++、C伺帘、Java昭躺、Python實現(xiàn)

1、暴力解法

最容易想到的方法是枚舉數(shù)組中的每一個數(shù) x伪嫁,尋找數(shù)組中是否存在 target - x领炫。

當我們使用遍歷整個數(shù)組的方式尋找 target - x 時,需要注意到每一個位于 x 之前的元素都已經(jīng)和 x 匹配過张咳,因此不需要再進行匹配帝洪。而每一個元素不能被使用兩次,所以我們只需要在 x 后面的元素中尋找 target - x脚猾。

func twoSum(nums []int, target int) []int {
    numsLen := len(nums)
    for i, num := range nums {
        for j := i + 1; j < numsLen; j++ {
            if target == num + nums[j] {
                return []int{i, j}
            }
        }
    }
    return []int{}
}

執(zhí)行結(jié)果:

  • 時間復雜度:O(N^2)葱峡,其中 N 是數(shù)組中的元素數(shù)量。最壞情況下數(shù)組中任意兩個數(shù)都要被匹配一次龙助。
  • 空間復雜度:O(1)砰奕。

內(nèi)存方面還可以,不過運行時間偏慢, 時間復雜度太高了。

image.png

2军援、使用map方式, nums 的值進行倒排索引, 以空間換時間仅淑, 時間復雜度是O(n)

func twoSum(nums []int, target int) []int {
    numsMap := make(map[int]int)

    for index, num := range nums{
        numsMap[num] = index    
    }

    for index, num := range nums {
        if preIndex, ok := numsMap[target-num];  (ok && preIndex != index) {
            return []int{preIndex, index}
        } 
        
    }
    return []int{}
}

執(zhí)行結(jié)果:

時間復雜度:O(n),我們只遍歷了包含有O(n)個元素的列表兩次胸哥。在表中進行的每次查找只花費 O(1)的時間涯竟。
空間復雜度:O(n),所需的額外空間取決于哈希表中存儲的元素數(shù)量烘嘱,該表最多需要存儲 N個 元素昆禽。

image.png

3、使用map方式, nums 的值進行倒排索引蝇庭, 一遍哈希表

事實證明,我們可以一次完成捡硅。在進行迭代并將元素插入到表中的同時哮内,我們還會回過頭來檢查表中是否已經(jīng)存在當前元素所對應(yīng)的目標元素。如果它存在壮韭,那我們已經(jīng)找到了對應(yīng)解北发,并立即將其返回。

func twoSum(nums []int, target int) []int {
    numsMap := make(map[int]int)
    for index, num := range nums {
        if preIndex, ok := numsMap[target-num]; ok {
            return []int{preIndex, index}
        }
        numsMap[num] = index
    }
    return []int{}
}

執(zhí)行結(jié)果:

時間復雜度:O(n)喷屋,我們只遍歷了包含有O(n)個元素的列表一次琳拨。在表中進行的每次查找只花費 O(1)的時間。
空間復雜度:O(n)屯曹,所需的額外空間取決于哈希表中存儲的元素數(shù)量狱庇,該表最多需要存儲 N個元素。

image.png

4恶耽、雙指針游標

雙指針的思路

  • 將原數(shù)組排好序, 設(shè)置兩個指針left, right
  • left 從0開始, right 做 len(nums) - 1 開始
  • 當nums[left] + nums[right] < target時密任,我們就沒有必要對所有的right0 ∈(left, right),因為nums[left] + nums[right0] 一定是比target小的, 所以left = left + 1后重新判斷
  • 當nums[left] + nums[right] > target時偷俭,同樣的浪讳,對left0 ∈(left, right),必然有nums[left0] + nums[right] > target, 所以right = right - 1后重新判斷
  • 當nums[left] + nums[right] = target時涌萤,就是我們想要知道的兩個數(shù)值了
  • 然后利用Map將數(shù)值轉(zhuǎn)換為之前的游標
func twoSum(nums []int, target int) []int {
    type Node struct{
        Value int
        Next  *Node
    }
     // 用鏈表是解決數(shù)組重復問題
    numsMap := make(map[int]*Node)
    var current *Node
    for index, num := range nums{
        if _, ok := numsMap[num]; ok{
            current = numsMap[num]
            for {
                if current.Next == nil{
                    current.Next = &Node{index, nil}
                    break
                }

                current = current.Next
            }
        }else{
            numsMap[num] = &Node{index, nil}
        }
    }

    sort.Ints(nums)
    left := 0
    right := len(nums) - 1
    for {
        if left >= right{
            break
        }

        sum := nums[left] + nums[right]
        if sum == target{
            if nums[left] == nums[right]{
                return []int{numsMap[nums[left]].Value, numsMap[nums[left]].Next.Value}
            }else{
                return []int{numsMap[nums[left]].Value, numsMap[nums[right]].Value}
            }

        }

        if sum < target{
            left ++

        }else{
            right --
        }
    }
    return []int{}
}

執(zhí)行結(jié)果:

因為要排序淹遵,時間復雜度也比較高, 需要Map存儲游標,空間復雜度也比較高, 算是一個不太好的實現(xiàn)方式负溪。

image.png

其他語言版本

C++

// 1. Two Sum
// 時間復雜度:O(n)
// 空間復雜度:O(n)
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> record;
        for(int i = 0 ; i < nums.size() ; i ++){
       
            int complement = target - nums[i];
            if(record.find(complement) != record.end()){
                int res[] = {i, record[complement]};
                return vector<int>(res, res + 2);
            }

            record[nums[i]] = i;
        }
        return {};
    }
};

執(zhí)行結(jié)果

[圖片上傳失敗...(image-51924b-1653220059347)]

C

// 1. Two Sum
// 時間復雜度:O(n)
// 空間復雜度:O(n)
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
    int *ans=(int *)malloc(2 * sizeof(int));
    int i,j;
    bool flag=false; 
    for(i=0;i<numsSize-1;i++)
    {
        for(j=i+1;j<numsSize;j++)
        {
            if(nums[i]+nums[j] == target)
            {
                ans[0]=i;
                ans[1]=j;
                flag=true;
            }
        }
    }
    if(flag){
        *returnSize = 2;
    }
    else{
        *returnSize = 0;
    }
    return ans;
}

執(zhí)行結(jié)果

image.png

Java

// 1. Two Sum
// https://leetcode.com/problems/two-sum/description/
// 時間復雜度:O(n)
// 空間復雜度:O(n)
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int l = nums.length;
        int[] ans=new int[2];
        int i,j;
        for(i=0;i<l-1;i++)
        {
            for(j=i+1;j<l;j++)
            {
                if(nums[i]+nums[j] == target)
                {
                    ans[0]=i;
                    ans[1]=j;
                }
            }
        }
        
        return ans;
        
    }
}

執(zhí)行結(jié)果

image.png

Python

# 1. Two Sum
# https://leetcode.com/problems/two-sum/description/
# 時間復雜度:O(n)
# 空間復雜度:O(n)
class Solution(object):
    def twoSum(self, nums, target):
        l = len(nums)
        print(nums)
        ans=[]
        for i in range(l-1):
            for j in range(i+1,l):
                if nums[i]+nums[j] == target:
                    ans.append(i)
                    ans.append(j)
                    print([i,j])
                    break
        return ans

執(zhí)行結(jié)果

image.png

結(jié)語

綜合來看透揣, 選擇方式3比較好: 使用map方式, nums 的值進行倒排索引, 一遍哈希表, Go的實現(xiàn)在內(nèi)存方面和時間復雜度都還可以笙以, Python相對表現(xiàn)就差很多淌实。

幾種語言運行效果對比

Go程序在內(nèi)存方面表現(xiàn)最佳, Python在內(nèi)存和運行時間表現(xiàn) 比較其他的語言都比較差。

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市拆祈,隨后出現(xiàn)的幾起案子恨闪,更是在濱河造成了極大的恐慌,老刑警劉巖放坏,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咙咽,死亡現(xiàn)場離奇詭異,居然都是意外死亡淤年,警方通過查閱死者的電腦和手機钧敞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來麸粮,“玉大人溉苛,你說我怎么就攤上這事∨澹” “怎么了愚战?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長齐遵。 經(jīng)常有香客問我寂玲,道長,這世上最難降的妖魔是什么梗摇? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任拓哟,我火速辦了婚禮,結(jié)果婚禮上伶授,老公的妹妹穿的比我還像新娘断序。我一直安慰自己,他們只是感情好谎砾,可當我...
    茶點故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布逢倍。 她就那樣靜靜地躺著,像睡著了一般景图。 火紅的嫁衣襯著肌膚如雪较雕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天挚币,我揣著相機與錄音亮蒋,去河邊找鬼。 笑死妆毕,一個胖子當著我的面吹牛慎玖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播笛粘,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼趁怔,長吁一口氣:“原來是場噩夢啊……” “哼湿硝!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起润努,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤关斜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后铺浇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痢畜,經(jīng)...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年鳍侣,在試婚紗的時候發(fā)現(xiàn)自己被綠了丁稀。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,687評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡倚聚,死狀恐怖线衫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情秉沼,我是刑警寧澤桶雀,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布,位于F島的核電站唬复,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏全肮。R本人自食惡果不足惜敞咧,卻給世界環(huán)境...
    茶點故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望辜腺。 院中可真熱鬧休建,春花似錦、人聲如沸评疗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽百匆。三九已至砌些,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間加匈,已是汗流浹背存璃。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留雕拼,地道東北人纵东。 一個月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像啥寇,于是被迫代替她去往敵國和親偎球。 傳聞我的和親對象是個殘疾皇子洒扎,可洞房花燭夜當晚...
    茶點故事閱讀 43,576評論 2 349

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