two_sum leetcode1

题目的简介

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].

就是为了取得一个数组中任意两个不相同的数的和和所给数相同的这两个数字
的位置,返回的是一个数组有两个元素

c 语言的解法

(利用的是自己构建hash list;利用的是链式)
链式:当求余的时候余数相同,形成链表查找的时候利用链表查找

#include <stdio.h>
#include <stdlib.h>

typedef struct hash_list_node* hlp;//hash_list_point哈希节点指针
typedef struct hash_list_node
{
    int index;
    hlp next;
}hln;
//构建hash节点包括指向下一个的指针和存储的值
void hash_list_free(hlp hash_list,int list_length_prime)
{
    int address = 0;
    for(address = 0;address < list_length_prime;++address)
    {
        hlp next_node = hash_list[address].next;
        while(next_node != NULL)
        {
            hlp tempt = next_node;
            next_node = next_node->next;
            free(tempt);
        }
    }
}
//清空hash 表(hln类型的数组)每一个节点都进行内存的释放free

int *twoSum(int *numbers,int n,int target)
{
    if(numbers == NULL | n < 2)
        return NULL;
    int index = 0;
    int hash_length = 293;
//hash表的长度决定的是整个程序的运行速度
//hash表的长度为素数
    hlp hash_list = (hlp)malloc(sizeof(hln) * hash_length);
    if(hash_list == NULL)
        return NULL;
    for(index = 0;index < hash_length;++index)
    {
        hash_list[index].index = -1;
        hash_list[index].next = NULL;
    }
//初始化hash表的值
    for(index = 0;index < n;++index)
    {
        int hp = abs(numbers[index] % hash_length);//hash_list_position
//将numbers中的值映射到hash表中来
        if(hash_list[hp].index == -1)//如果为空则直接映射到
            hash_list[hp].index = index;
        else//不是空则作为链表
        {
            hlp new_hash_node = (hlp)malloc(sizeof(hln));
//设置一个指向hln的指针(同时创建内存hln一个节点)
            if(new_hash_node == NULL)//创建失败
            {
                hash_list_free(hash_list,293);
                return NULL;
            }
            new_hash_node->index = index;
            new_hash_node->next = hash_list[hp].next;
            hash_list[hp].next = new_hash_node;
        }
    }
    int* rect = (int*)malloc(sizeof(int)*2);
//创建返回的数组存储的是要求的位置信息
    for(index = 0;index < n;++index)
    {
        int bias = abs((target - numbers[index]) % hash_length);
//遍历找到另一半
//其中在hash表中用的是数值求出的位置信息
        if(hash_list[bias].index == -1)
            continue;
        if(numbers[hash_list[bias].index] == (target - numbers[index]) && hash_list[bias].index != index)
        {
            rect[0] = index;
            rect[1] = hash_list[bias].index;
            hash_list_free(hash_list,hash_length);
            return rect;
        }
        else
        {
            hlp link_node = hash_list[bias].next;
            while(link_node != NULL)
            {
                if(numbers[link_node->index] == (target - numbers[index]))
                {
                    rect[0] = index;
                    rect[1] = link_node->index;
                    hash_list_free(hash_list,hash_length);
                    return rect;
                }
                else
                {
                    link_node = link_node->next;
                }
            }
        }
    }
    hash_list_free(hash_list,hash_length);
    return NULL;
}

利用hash表将numbers中的数据的位置存储在hash中
当遍历numbers的时候,通过target数与当前的numbers的值的差值求出要找的
数的值,利用存储在hash表的情况的过程,找到hash表的一个‘单元号’,单元号的第一户我们判断是否为要的值,如果不是的话,我们通过遍历链表来找出本‘单元’的各户的值

python的解法

1 comb()函数

comb函数是一个generator,可以返回一个数列中的真子集

def comb(l,n):
    if n == 0:
        yield ()
    else:
        for i in range(len(l)):
            for r in comb(l[i + 1:],n - 1):
                yield (l[i],) + r
print(f.__next__())
#每一次都会返回所有结果的一个数
#l 为 一个 list[ ]
#n 为所要的子集的数列的个数

2 enumerate_list()函数

为了使得所给的list变成一个generator的object
并且返回的是所给的list的位置和value

def enumerate_list(l):
    for i ,value in enumerate(l):
        yield (i,),value
l = [1,2,3]
print(enumerate_list(l).__next__())
#((0,), 1) 可以看到格式是这样的,当给定一个list我们得到的格式

3 dict_append()函数

创建一个dict 将所给数列的数据的2倍与target的差作为:key
因为相加和为target的两个数据*2与target的差的值的绝对值(abs)相同
得到是这样类型的dict
{key : [((0,),1)],[ ],key :[ ]...... }
类似的结构

def dict_append(d,key,value):
    d[key] = d.get(key.[]) + [value]
#get函数是在dict中找到key的值对应的list,如果不存在返回一个list[ ]

4 dict_add_by_distance()函数

dict_add_by_distance( ) 函数
传入的是被generator的tuble( (0, ),value )这种类型的
abs(2 * tuble[1] - target):如果存在两个值相加为target则这个值相同
{key : [((0,),1)],[ ],key :[ ]...... }得到的最后数据结构
如果是在一个key里面的则可能是所要tuble 则tuble[0][0]则为所求的信息

def dict_add_by_distance(d,l,target):
    for tuble in l:
        dict_append(d,abs(2 * tuble[1] - target),tuble)

5 find_pairs(),find_all_pairs()函数

通过得到的dict取得其中的每一个元素判断几种特殊的情况 :
1.存在类似于 5 + 3 = 8 和 4 + 4 = 8的情况
2.单独存在4 + 4 = 8的情况

def find_pairs(l,target,size):
    if len(l) <= 1:
        return
#length为1的情况就是说在每一个dict中的list中元素只有一个
#就是说明这个值的2倍与target的差值这个值相同的元素只有一个
    smaller = [tuble[0] for tuble in l if 2 *tuble[1] <= target ]
    bigger = [tuble[0] for tuble in l if 2 *tuble[1] >= target]
    for i in smaller:
        for j in bigger:
            if len(i) + len(j) != size:
                continue
#为了判断的情况是情况 1 见上文
            e = i + j
#得到的是一个tuble中包含两个值分别为要求的位置
            if len(frozenset(e)) != size:
                continue
#如果两个值相同set中自动去掉相同的元素
            yield tuple(sorted(e))
#排序

def find_all_pairs(d,target,size):
    for i in d.values():
        for e in find_pairs(i,target,size):
            yield e

主函数

整个函数的进程我们可以知道
举个例子num = [1,2,3] target = 3
1.先把给到的num变成generator //enumerate_list(num)
并且变成((0,),value)这种类型的样子
2.dict_add_by_distance( ) 中利用dict_append( )
利用的是generator num中的数据*2 - target得到的数字作为key
其中的每个key对应的是一个list
{key:[((0,),value)...] }每一个key中有一个list 每一个list中有的是多个tuble
每一个tuble代表的是2倍-target的值=key,并且具有的是tuble[0]为一个位置的tuble
tuble[1]value
3.得到了处理好的数据{key:[((0,),value)...] }:
之后进行寻找把每一个list拿出来如果list只有一个值的话则表示只有一个值不符合
4.返回之后的为tuble再list化

def two_sum(num,target):
    d = {}
    dict_add_by_distance(d,enumerate_list(num),target)
    return list(list(set(find_all_pairs(d,target,2)))[0])

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,719评论 0 33
  • # 第一优先级规则声明: # 除了梦境,每一个意识主进程都必须与一个身体参与的机械进程相匹配,否则结束意识主进程。...
    李洞BarryLi阅读 3,838评论 0 1
  • The Python Data Model If you learned another object-orien...
    plutoese阅读 1,704评论 0 51
  • Python 是一种相当高级的语言,通过 Python 解释器把符合语法的程序代码转换成 CPU 能够执行的机器码...
    Python程序媛阅读 1,888评论 0 3
  • 感赏 昨天下午下班,我想去游泳,问老公去不去,他说去,主要是陪我,主观上他是不想去的,我呢,是想让他动起来。我赶快...
    妈妈随笔阅读 175评论 0 0