LeetCode No.1 Two Sum

这是LeetCode题海中的第一题,就让我们从读题开始吧~

题目:给定一个整数的数组,返回两个元素的索引,这两个元素之和要等于一个给定的值target;假定每一组输入仅有唯一的解,并且同一个元素不能被使用两次。

看一个样例:

nums = [2, 7, 11, 15], target = 9;

因为nums[0] + nums[1] = 9;

所以应该返回[0, 1]


在这里我讲介绍三种解法:

第一种是最直接的蛮力算法,第二种和第三种是利用散列表提高查找速度的算法,其中第三种算法最为简洁高效~


思路一:蛮力解法

蛮力解法是很直接的!

  1. 从数组的第一个元素开始,依次遍历其后的元素;
  2. 判断这两个元素之和是否等于target,若等于则返回这两个元素的索引,否则继续遍历知道达到数组尾部;
  3. 从数组的第二个元素开始,依次遍历其后元素;
  4. 重复第二步;
  5. 从第三个,依此类推;

代码:

vector
    
    
     
      twoSum(vector
     
     
      
      & nums, int target) 
{
    for(unsigned int i = 0; i < nums.size(); ++i)
    {
        for(unsigned int j = i + 1; j < nums.size(); ++j)
        {
            if(nums[i] + nums[j] == target)
            {
                return vector
      
      
       
       {i, j};
            }
        }
    }
}
      
      
     
     
    
    

蛮力算法之所以叫蛮力算法,就是因为它很蛮,这个算法的时间复杂度高达O(n2)。


果然很慢,只击败了8%的人。。。。。


这个算法之所以很慢,就是因为它在查找我们的目标元素的时候需要依次遍历,但是我们根据target是可以知道要查找的目标元素的值的,如果我们能够很快地找到它,那算法的速度自然也就会提升!根据这个思路,我们自然想到了使用平衡搜索数或者散列表这种查找元素很快的数据结构;


思路二:利用散列表
我们利用散列表快速查找目标元素,即可在O(n)的时间内完成算法,但是这里要注意重复元素的处理,比如:

给定一个数组:[3, 2, 4], target = 6, 那么我们要的返回结果应该是[1, 2]而不是[0, 0];

当数组为:[3, 3, 7, 5], target = 6时,返回结果就是[0, 1];

代码:

vector
     
     
      
       twoSum(std::vector
      
      
       
       & nums, int target)
{
	unordered_multimap
       
       
        
         numbers;

	vector
        
        
         
          result;

	for (unsigned i = 0; i < nums.size(); ++i)
		numbers.insert({ nums[i], i });

	for (unsigned int i = 0; i < nums.size(); ++i)
	{
		auto candi_iter = numbers.find(target - nums[i]);
		
		if (candi_iter != numbers.end())
		{
			if (candi_iter->first == nums[i])
			{
				if (numbers.bucket_size(numbers.bucket(nums[i])) > 1)
				{
					for (auto iter = numbers.begin(numbers.bucket(nums[i])); iter != numbers.end(numbers.bucket(nums[i])); ++iter)
						result.push_back(iter->second);
					return result;
				}
				else
					continue;
			}
			result.push_back(i);
			result.push_back(candi_iter->second);
			return result;
		}
	}
}
        
        
       
       
      
      
     
     



可以看到,这个算法只用了9ms,复杂度下降到了O(n),散列表是不是很神奇呢!


思路三:我们可以更加简单快速的使用散列;

  1. 我们先创建一个空的散列,然后从原数组的第一个元素开始,在散列中查找它的目标元素;
  2. 如果找到,直接返回结果,否则,将这个元素插入到散列中;
  3. 依次迭代直到到达数组尾部,当然,这个题目假设一定有解;
代码:

vector
    
    
     
      twoSum3(vector
     
     
      
      & nums, int target)
{
	unordered_multimap
      
      
       
        numbers;

	for (unsigned int i = 0; i < nums.size(); ++i)
	{
		auto candi_iter = numbers.find(target - nums[i]);

		if (candi_iter != numbers.end())
		{
			return vector
       
       
        
        {candi_iter->second, i};
		}

		numbers.insert({ nums[i], i });
	}
}
       
       
      
      
     
     
    
    



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值