【20190304】【每天一道算法题】两数之和

问题:

给定一个整数数组 nums 和一个目标值 target ,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。


我的思路:

1. 嵌套循环:外层遍历整个数组;外层判断是否有 x+y=target 的元素(或存在 target-x 的元素)。

2. 解决值和索引对应的有效手段:哈希表。


解答:

1. C语言实现

#include<stdio.h>
#include<stdlib.h>  //system("pause")的头文件

int *twoSum(int *nums, int numSize, int target)
{
	int i=0, j=0;
	int *pBuf=(int*)malloc(2*sizeof(int));  //因为函数返回值必须是指针类型,所以这里定义的是指针类型的数组!

	for(i=0;i<numSize-1;i++)
	{
		for(j=i+1;j<numSize;j++)  //减少不必要的计算,j从i+1开始
		{
			if(target==nums[i]+nums[j])
			{
				pBuf[0]=i;
				pBuf[1]=j;
				return pBuf;
			}
		}
	}
	free(pBuf);
	return NULL;  //如果没有检索到满足条件的,那么返回NULL
}

int main(void)  //表示main函数没有参数,返回值为整型
{
	int nums[4]={2,7,11,15};
	int *pIndex=NULL;
	int target=9, numSize=4;

	pIndex=twoSum(nums, numSize, target);

	if(pIndex==NULL)
	{
		printf("Error!\n");
	}
	else
	{
		printf("The index is %d and %d!\n",pIndex[0],pIndex[1]);
		free(pIndex);
	}
	system("pause");
	return 0;
}

2. Python3实现

# 方法一:暴力法(两层遍历)。
# 第一次遍历查一个数,第二次遍历查是否存在一个数等于target-第一个数。
# 算法复杂度O(n^2)。
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:

        length = len(nums)
        for i in range(length-1):
            for j in range(i+1, length):  # 第二个数索引从 i+1 开始
                if nums[j] == target - nums[i]:
                    return [i, j]
        return None

# 方法二:哈希表。
# 保证元素及其索引相互对应最有效的方式是:哈希表。
# 算法复杂度:O(n)。

# 测试用例:nums = [3, 3, 1, 4],target = 5。虽然前两位元素重复了,但好在3并不满足条件,因此 hashmap[3]=0 再更新为 hashmap[3]=1 并不影响结果。
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:   
        hashmap = {}
        for index, num in enumerate(nums):
            if (target - num) in hashmap:
                return [index, hashmap[target-num]]
            hashmap[num] = index     # 只将不能满足条件的键值对存入。
        return None


######### 下面是两种错误示范 ##########

# 第一种:无法找到值对应的键。解决方法:把元素本身作为key,索引作为value。
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:    
        hash = dict()   # 构建哈希表的两种方式:dict() 或 {}
        length = len(nums)
        for i in range(length):   # 将元素都存入哈希表,键是相应的索引值
            hash[i] = nums[i]
        for i in range(length):
            if (target - hash[i]) in hash.values():
                j = hash.get(target - hash[i])   # 错误!.get()函数,是获得键k对应的值values。Python3中没有通过值索引键的方式,所以要转换思想,把元素值作为键,索引值作为values
                return [i, j]
        return None
		
# 第二种:出现了冲突。解决方法:不建立完整的哈希表,如果 target-num 存在于 nums 中,则直接输出索引,而不将键值对存入哈希表。
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:   
        hash = dict()  
        length = len(nums)
        for i in range(length):   
            hash[nums[i]] = i   # 使用元素值作为键,出现了冲突。例如nums=[3,3],target=6,输出了None。也不可!
        for item in nums:
            if target-item in hash.keys() and hash[target-item] != hash[item]:
                return [hash[target-item], hash[item]]
        return None

 知识点:

1. enumrate() 函数:为可迭代对象添加序号,默认从 0 开始。一般用在 for 循环中。

enumerate(iterable [,start]),其中 iterable 是可迭代对象(字符串、列表、元组、字典),start 是序号起始值。

返回值:返回枚举对象。

nums = [1, 2, 3, 4, 5]
for index, num in enumerate(nums):
    print('{}, {}'. format(index, num))

2. Python3 中 “&”、“|” 和 “and”、“or”的区别

“&”、“|” 是位运算(用于数值)

“and”、“or” 是逻辑运算(用于逻辑关系式)

Python 中的逻辑操作符有:and、or、not

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Satisfying

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值