Leetcode 001. 两数之和(扩展)

1.题目要求

给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。

你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。

示例:

 

2.解法一:暴力法(for*for,O(n*n))

        分析:因为题目假设“每个输入只对应一种答案,且相同的元素不能被重复利用”,这就降低了难度。

        暴力法:使用两次for循环。第一个for循环依次遍历一次数组,每次执行过程中选取了一个数组元素nums[i], 再for循环遍历nums[i]后面的所有元素,假设取到的元素为nums[j](其中,i+1=< j <=size-1,size为所传入数组的元素个数 )同时比较过程中取到的两个元素的和算法等于target,因为每种输入只对应一种答案,且相同元素不同被重复利用,因此找到了就可以直接返回[i,j];没有找到符合题意的解,就返回[-1,-1]。

//完整代码
#include <iostream> #include <vector> using namespace std; class Solution { public: vector<int> twoSum(vector<int>& nums, int target){}; }; vector<int> twoSum(vector<int>& nums, int target) { vector<int> result; int surplus; //余数 for (int i = 0; i != nums.size() - 1; ++i) { surplus = target - nums[i];//余数 for (int j = i + 1; j != nums.size(); ++j) { if (surplus == nums[j]) { result.push_back(i); result.push_back(j); return result; } } }
//找不到则返回[-1,-1] result.push_back(
-1); result.push_back(-1); return result; }
int main() { vector<int> arr = { 2, 7, 11, 15 }; int val = 30; cout << "[" << twoSum(arr,val)[0]<< "," << twoSum(arr,val)[1] << "]" << endl; return 0; }

 

3.解法二:hash查找(复杂度O(1))

[学而不思则惘,思而不学则殆]——
 
1.为什么采用hash表的map映射可以减少一次for循环?
答: 采用map.count和find函数,哈希查找的时间复杂的为O(1).
 
2.map.count函数和map.find函数的比较
(1)数值的唯一性
map和set两种容器的底层结构都是红黑树,所以容器中不会出现相同的元素,
因此count()的结果只能为0和1,可以以此来判断键值元素是否存在(当然也可以使用find()方法判断键值是否存在)。
 
(2)返回值的比较
拿map<key,value>举例
 count( )  方法的返回值是布尔值, 返回1,键值元素存在;返回0,键值元素不存在
 find( )  方法返回值是一个迭代器,成功,返回迭代器指向要查找的元素;失败,返回的迭代器指向end。
 
//哈希函数使用示例
#include<iostream>
#include<map>
#include<string>
using namespace std;
int main()
{
    map<int,string> maps;
    if(maps.find(1)==maps.end())
    {
        cout<<"没有1这个元素"<<endl;
    }
    if(maps.count(1)==0)
    {
        cout<<"没有1这个元素"<<endl;
    }
    //添加元素1
    maps[1]="one";
    if(maps.find(1)!=maps.end())
    {
        cout<<"有1这个元素"<<endl;
    }
    if(maps.count(1))
    {
        cout<<"有1这个元素"<<endl;
    }
    return 0;
}

 

//两数之和-哈希查找
#include <iostream>
#include <vector>
#include <map>

using namespace std;

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> result;

        //map<key,value> 哈希表的映射
        map<int, int> temp_map;
        for (int i = 0; i != nums.size(); ++i)
            temp_map[nums[i]] = i;

        for (int i = 0; i != nums.size(); ++i)
        {
            int surplus = target - nums[i];
            //值为surplus的元素存在,且不为nums[i]本身
            if (temp_map.count(surplus) != 0 && temp_map[surplus] != i)
            {
                result.push_back(i);
                result.push_back(temp_map[surplus]);
                return result;
            }
        }
        result.push_back(-1);
        result.push_back(-1);
        return result;


    }
};

int main()
{
    vector<int> arr = { 2, 7, 11, 15 };
    int val = 30;
    Solution test;
    cout << "[" << test.twoSum(arr, val)[0] << "," << test.twoSum(arr, val)[1] << "]" << endl;

    return 0;
}

4.举一反三!!!

       扩展思考:给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。

       注意:这里不加上题中的限制条件。返回所有符合题意的两数的下标,相同的元素可以重复利用。但是不能是同一个元素与自身组合,这样就不符合两数的概念了。

给定 nums = [2, 7, 2,2,11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
    nums[1] + nums[2] = 7 + 2 = 9
nums[1] + nums[3] = 7 + 2 = 9 所以返回 [0, 1],[1,2],[1,3]

        修改题目的要求后,解题的大体思路是一致的,只是再返回数据的时候,处理上有些差异。因为Leetcode上没有提供这种情况下的测试用例,因此,下面给出的代码只是参考(单一用例跑通)。

        另外,由于笔者对hash表的使用尚不熟练,这个给出的解法是采用暴力法。

        

#include <iostream>
#include <vector>

using namespace std;

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target)
{
    vector<int> result;
    int surplus; //余数
    for (int i = 0; i != nums.size() - 1; ++i)
    {
        surplus = target - nums[i];//余数
        for (int j = i + 1; j != nums.size(); ++j)
        {
            if (surplus == nums[j])
            {
                result.push_back(i);
                result.push_back(j);
            }
        }
    }

        ////修改返回值的次序

    //找不到则返回[-1,-1]
    if (result.size() == 0)
    {
        result.push_back(-1);
        result.push_back(-1);
        return result;
    }

    return result;
    
}
};

int main()
{
    vector<int> arr = { 2, 7, 2, 2, 11, 15 };
    int val = 9;
    Solution test;

        ////修改了输出条件
    for (int i = 0; i != test.twoSum(arr, val).size(); i += 2)
    {
        cout << "[" << test.twoSum(arr, val)[i] << "," << test.twoSum(arr, val)[i+1] << "]" << “ ”;
    }
    cout << endl;
    

    return 0;
}

       

 

参考资料:

1:https://www.cnblogs.com/bewolf/p/5146787.html   谈谈map中的count方法

2:https://www.cnblogs.com/grandyang/p/4130379.html  [LeetCode] Two Sum 两数之和

posted @ 2018-10-29 11:24  Timothy_prayer  阅读(420)  评论(0编辑  收藏  举报