• 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 两数之和

  • 相关阅读:
    tailf,tail -f,tail -F区别
    Java多线程知识总结(一)
    MyBatis使用总结
    mina学习总结
    好书推荐
    Hessian总结
    Spring总结
    SpringMVC总结
    判断两个IP是否处于同一子网(网段)
    Delphi Json之树遍历
  • 原文地址:https://www.cnblogs.com/paulprayer/p/9869637.html
Copyright © 2020-2023  润新知