1. 程式人生 > >leetcode之問題一:Two Sum

leetcode之問題一:Two Sum

1. 問題描述

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same elements twice.

Example: Given nums = [2, 7, 11, 15], target = 9. Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].

2. 演算法思想

A. 暴力破解:對於nums中的每一個元素a,根據和求出另一個元素的值b,從nums中尋找b,若找到則退出。核心程式碼採用了2個for迴圈,時間複雜度是O(n^2)

B. 雜湊法:將nums中的每個元素進行雜湊,查詢特定元素時間複雜度只需O(1), 演算法時間複雜度是O(n).

3. 程式碼實現

A. 暴力求解

int *twoSum(int *nums, int numsSize, int target) 
{
    int *ans = (int *)malloc(sizeof(int) * 2);
    int i, j;
    int tmp;
    for(i = 0; i < numsSize; ++i)
    {
        tmp = target - nums[i];
        ans[0] = i;
        for(j = i + 1; j < numsSize; ++j)
        {
            if(tmp == nums[j])
            {
                ans[1] = j;
                return ans;
            }
        }
    }
    return NULL;
}

在這裡插入圖片描述

B. 利用C實現雜湊查詢


#include <stdlib.h>
typedef struct HashNode
{
    int key;
    int index;
}HashNode;

typedef struct HashMap
{
    int size;
    HashNode **storage;
}HashMap;

HashMap *create_hash(int size)
{
    HashMap *hashmap;
    hashmap = (HashMap *)malloc(sizeof(HashMap));
    assert(hashmap != NULL);
    hashmap -> size = size;
    hashmap -> storage = (HashNode **) malloc(sizeof(HashNode *) * size);
    assert(hashmap -> storage != NULL);
    /*for(int i = 0; i < size; ++i)
    {
        hashmap -> storage[i] = NULL;
    }*/
    memset(hashmap -> storage, 0, sizeof(HashNode *) * size);
    return hashmap;
}

void destory_hash(HashMap * hashmap)
{
    int i;
    for(i = 0; i < hashmap -> size; ++i)
    {
        if (hashmap -> storage[i] != NULL)
            free(hashmap -> storage[i]);
    }
    free(hashmap -> storage);
    free(hashmap);
}

void set_hash(HashMap *hashmap, int key, int index)
{
    int hash = abs(key) % hashmap -> size;
    HashNode *node;
    while((node = hashmap -> storage[hash]) != NULL)
    {
        if(hash < hashmap -> size - 1)
            ++hash;
        else
            hash = 0;
    }
    
    node = (HashNode *)malloc(sizeof (HashNode));
    assert(node != NULL);
    node -> key = key;
    node -> index = index;
    hashmap -> storage[hash] = node;
}

HashNode *get_hash(HashMap * hashmap, int key)
{
    int hash = abs(key) % hashmap -> size;
    HashNode *node;
    while((node = hashmap -> storage[hash]))
    {
        if(node -> key == key)
            return node;
        if(hash < hashmap -> size - 1)
            ++hash;
        else
            hash = 0;
    }
    return NULL;   
}


int *twoSum(int* nums, int numsSize, int target) 
{
    HashMap *hashmap;
    HashNode *node;
    int rest, i;
    int *result = (int *) malloc(sizeof(int )* 2);
    
    hashmap = create_hash(numsSize * 2);
    for(i = 0; i < numsSize; ++i)
    {
        rest = target - nums[i];
        node = get_hash(hashmap, rest);
        if(node != NULL)
        {
            result[0] = i;
            result[1] = node -> index;
            break;
        }
        else
            set_hash(hashmap, nums[i], i);
    }
    return result;
}

在這裡插入圖片描述

C. 利用C++的STL之map

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) 
    {
        map<int, int> hash;
        int i, part;
        vector<int> result;
        
        for(i = 0; i < nums.size(); ++i)
        {
            if(hash[target - nums[i]] != 0 && hash[target - nums[i]] - 1 != i)
            {
                result.push_back(hash[target - nums[i]] - 1);
                result.push_back(i);
                break;
            }
            hash[nums[i]] = i + 1;
        }
        
        return result;
    }
};

在這裡插入圖片描述

總結:

這是一道典型的查詢題目,查詢分為2種,靜態查詢和動態查詢。靜態查詢只涉及查詢,動態查詢還涉及元素的插入和刪除。常見的靜態查詢方法有順序查詢(暴力求解),折半查詢(關鍵字有序),雜湊查詢。常見的動態查詢有BST(AVL是其改進), B樹,B+樹,雜湊查詢。雜湊查詢因其線性時間複雜度具有極大的吸引力,但是衝突處理比較麻煩,實際情況下很難達到線性時間複雜度。