【LeetCode】1. Two Sum

来源:互联网 发布:网络维护外包费用 编辑:程序博客网 时间:2024/06/15 04:40

一、问题描述

Description:
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 element twice.

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

二、问题分析及算法表示
作为一个刚刚接触算法的人来说,我看到题目的第一眼想到的就是两层循环遍历,再匹配target最终返回结果。这种暴力解题的方法毫无疑问是能顺利求解的,但是要耗费大量的时间,在阅读了一系列博客后我仿照大佬们的做法利用了哈希解题,虽然一开始结合自己在数据结构课上学到的印象并不深的哈希算法仍然很难理解,但是在经过多次的实践和思考后慢慢的体会到了算法的神奇之处。

三、算法及源代码

1.暴力求解

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

2.自定义的hash链
(1)先找出该数组中的最小值min,{min,max=target-min}即为解的可能范围,len=max-min+1即为解空间的大小。
(2)创建len长度的链表作为hash表并赋初值-1
(3)根据每一个数的大小寻找该数保存的位置,而该位置保存的是该数在原来数组中的下标位置,也就是将两个数组的数值和下标,利用hash保存数据是为了判断与该数字相加得到target的对应数字是否存在;而保存原数组下标是为了按照题目要求准确返回两个目标数据的位置。
(4)如,target=8,若遍历到i=3时,a[3]=5,此时先判断table[8-3]是否存在,若存在则表示与3相匹配的数字存在,则目标结果为这两个数,此时返回的数据则为i和table[5](即原大小为5的数在原数组中的位置);若不存在,则在table[3]中记录3,代表3在原数组中的位置。

int* twoSum(int* nums, int numsSize, int target) {    int min = nums[0];    int i=1;    for(i=1;i<numsSize;i++){        if(nums[i]<min){            min = nums[i];        }    }    int max = target-min;    int len = max-min+1;    int *table = malloc(len*sizeof(int));    int *indice = malloc(2*sizeof(int));    for(i=0;i<len;i++){        table[i] = -1;    }//hash初值    for(i=0;i<numsSize;i++){        if(nums[i]<=max){            if(table[target-nums[i]-min]!=-1){                       indice[0] = table[target-nums[i]-min];                       indice[1] = i;                        return indice;                                                                                                                                                                                          }            table[nums[i]-min] = i;        }    }     free(table);    return indice;  }

3.hashset解题
因为不熟悉c语言,决定还是用java中的类。
同以上方法的主要原理一样,但是java由于有封装的public boolean add(Object o)方法,可以直接用它来进行判断该数的对应数字是否已经存在。用add方法添加一个数,若该数即hash表中的位置已经存在该对象,则返回false;否则返回true并成功添加此对象。
注意这里的hashset中保存的都是一个对象,它并没有如上述方法一样保存对象数据在原数组中的坐标。
因此在返回false的情况下,表示该数的对应数在i之前存在,还要对i之前的数与该数进行相加匹配,从而得到答案。虽然比暴力破解简单了不少,但是这里依然是用到了两层循环,于是便有了下面的hashmap。

public class p1hashset {    public int[] twoSum(int[] nums, int target) {        int index[] = new int[]{0,1};        Set nset = new HashSet();        for(int i=0;i<nums.length;i++){            if(nset.add(target-nums[i])){                nset.remove(target-nums[i]);                nset.add(nums[i]);            }            else{                index[1]=i;                for(int j=0;j<i;j++){                    if(target==(nums[i]+nums[j])){                        index[0]=j;                        return index;                    }                }                return index;            }        }        return index;    }

4.hashmap解题
hashmap与hashset最大的不同便是hashmap保存了一个键值对,public Object put(Object Key,Object value)方法用来将元素添加到map中。其中,key可以视为方法2中的数值大小,而保存的value则代表方法2中的下标位置大小。
通过containsKey(target-nums[i])检测该数字的对应数是否存在,若存在则返回该数的i和其对应数的get(target-nums[i]);若不存在则put(nums[i], i)。

public class p1hashmap {    public int[] twoSum(int[] nums, int target) {        int[] index = new int[]{0,1};        HashMap<Integer,Integer> hm = new HashMap<Integer,Integer>();        for(int i=0;i<nums.length;i++){            if(hm.containsKey(target-nums[i])){                index[1] = i;                index[0] = hm.get(target-nums[i]);                return index;            }            else{                hm.put(nums[i], i);            }        }        return index;    }}
虽然理解了该题用hashset和hashmap的解题方法,两者的区别点击[这篇文章](http://www.importnew.com/6931.html)但是我本人对他们的原理仍然有许多的不明白之处,比如要重写的equals()和hashCode()方法,又比如产生碰撞时的处理方法和获取对象的方法。总的来说这个暑假的第一篇博客总算是开始了,决定开始刷leetcode,决定开始写博客,决定要开始做一些事情。when luck comes you are ready.
原创粉丝点击