1. 程式人生 > 實用技巧 >leetcode演算法:1.兩數之和

leetcode演算法:1.兩數之和

給定一個整數陣列 nums和一個目標值 target,請你在該陣列中找出和為目標值的那兩個整數,並返回他們的陣列下標。

你可以假設每種輸入只會對應一個答案。但是,陣列中同一個元素不能使用兩遍。

示例:

給定 nums = [2, 7, 11, 15], target = 9
因為 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

思考

考慮空間複雜度

  1. 要求空間複雜度O(1)
  2. 允許空間複雜度O(n)

解答

  • 對於要求空間複雜度O(1)的這種情況,只能雙層迴圈暴力搜尋了,也就是看到這道題的第一簡單粗暴解法。
  • 對於允許空間複雜度O(n)的這種情況,就是典型的空間換時間了,利用一個外部map(dict)來邊檢索邊儲存。
package algo

func twoSum(nums []int, target int) []int {
	if len(nums) < 2 {	//陣列長度<2時無意義
		return nil
	}
	
	elemMap := make(map[int]int)
	for i := 0; i < len(nums); i++ {
		if j, ok := elemMap[target-nums[i]]; ok {
			return []int{j, i}	//index順序為先j後i,因為j是之前搜尋時放進去的,因此j一定在i前
		}
		elemMap[nums[i]] = i
	}
	return nil
}

func twoSum_BruteForce(nums []int, target int) []int {
	if len(nums) < 2 {
		return nil
	}
	
	for i := 0; i < len(nums); i++ {
		for j := i + 1; j < len(nums); j++ {
			if nums[i]+nums[j] == target {
				return []int{i, j}
			}
		}
	}
	return nil
}

單元測試:

package algo

import (
	"math/rand"
	"testing"
	"time"
)

func TestTwoSum(t *testing.T) {
	rand.Seed(int64(time.Now().Nanosecond()))
	for times := 0; times < 10; times++ {
		nums := []int{}
		for i := 0; i < 100; i++ {
			nums = append(nums, rand.Intn(100))
		}
		res := twoSum(nums, 128)
		if res == nil {
			t.Error("failed")
		}
	}
}

func TestTwoSum_BruteForce(t *testing.T) {
	rand.Seed(int64(time.Now().Nanosecond()))
	for times := 0; times < 10; times++ {
		nums := []int{}
		for i := 0; i < 100; i++ {
			nums = append(nums, rand.Intn(100))
		}
		res := twoSum_BruteForce(nums, 128)
		if res == nil {
			t.Error("failed")
		}
	}
}