題目描述(簡單題)
我們的目標是:給定確定數組和一個目標和,在數組中找兩個數字相加等於目標和的項目,輸出這兩個數字的下標。
解法一 雙重循環
本解法傾向於暴力解法,並且比較耗費空間,因爲添加了一個多餘的vector作爲中間存儲區。
時間複雜度:因爲是兩層 for 循環,
空間複雜度:
C++ 解法:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target)
{
vector<int> result;
for(int i=0;i<nums.size();i++)
{
int tmp=target-nums[i];
for(int j=i+1;j<nums.size();j++)
{
if(nums[j]==tmp)
{
result.push_back(j);
result.push_back(i);
}
}
}
return result;
}
};
Golang解法:
func twoSum(nums []int, target int) []int {
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 []int{}
}
解法二 利用哈希表
在上邊的解法中,我們可以觀察下第二個 for 循環步驟。
for j:=i+1;j<len(nums);j++{
if nums[i]+nums[j]==target{
那麼,我們如果換一種理解方式和思路,可以得到下面的結論:
for j:=i+1;j<len(nums);j++{
sub = target - nums[i]
if nums[j]==target{
第二層 for 循環無非是遍歷所有的元素,看哪個元素等於 sub ,時間複雜度爲 。
那麼,有沒有一種方法,不用遍歷就可以找到元素裏有沒有等於 sub 的?
hash table !!!!
我們可以使用哈希表來解決這個問題。
我們可以把數組的每個元素保存爲 hash 的 key,下標保存爲 hash 的 value 。
這樣僅剩下需判斷 sub 在不在 hash 的 key 裏就可以了,而此時的時間複雜度僅爲 !
需要注意的地方是,還需判斷找到的元素不是當前元素,因爲題目裏講一個元素只能用一次。
時間複雜度:比解法一少了一個 for 循環,降爲。
空間複雜度:所謂的空間換時間,這裏就能體現出來, 開闢了一個 hash table ,空間複雜度變爲。
C++解法:
class Solution
{
public:
vector<int> twoSum(vector<int> &nums, int target)
{
//Key是數字,value是該數字的index
unordered_map<int, int> hash;
vector<int> result;
int numsSize = int(nums.size());
for (int i = 0; i < numsSize; i++)
{
int numberToFind = target - nums[i];
//如果找到numberToFind,就return
if (hash.find(numberToFind) != hash.end())
{
result.push_back(hash[numberToFind]);
result.push_back(i);
return result;
}
//如果沒有找到,把該數字的index放到hash表中
hash[nums[i]] = i;
}
return result;
}
};
Golang解法:
func twoSum(nums []int, target int) []int {
num_map := make(map[int]int)
result_list := make([]int, 2)
for index_value, first_num := range nums {
second_value := target - first_num
if second_index, ok := num_map[second_value]; ok {
result_list[0] = second_index
result_list[1] = index_value
return result_list
}
num_map[first_num]=index_value
}
return result_list
}
解法三 合併循環的方式
看解法二中,兩個 for 循環,他們長的一樣,我們當然可以把它合起來。複雜度上不會帶來什麼變化,變化僅僅是不需要判斷是不是當前元素了,因爲當前元素還沒有添加進 hash 裏。
C++解法:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
map<int, int> index_map;
vector<int> ans;
for (int i = 0; i < nums.size(); ++i) {
if (index_map.count(nums[i])) {
ans.push_back(index_map[nums[i]]);
ans.push_back(i);
return ans;
}
index_map[target - nums[i]] = i;
}
return ans;
}
};
Golang解法:
func twoSum(nums []int, target int) []int {
num_map := make(map[int]int)
result_list := make([]int, 2)
for index_value, first_num := range nums {
second_value := target - first_num
if second_index, ok := num_map[second_value]; ok {
result_list[0] = second_index
result_list[1] = index_value
return result_list
}
num_map[first_num]=index_value
}
return result_list
}
參考鏈接聲明
關於Java的解法可以主要品讀上述的文章。
成長,就是一個不動聲色的過程,一個人熬過一些苦,才能無所不能。