zoukankan      html  css  js  c++  java
  • 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 两数之和

  • 相关阅读:
    973. K Closest Points to Origin
    919. Complete Binary Tree Inserter
    993. Cousins in Binary Tree
    20. Valid Parentheses
    141. Linked List Cycle
    912. Sort an Array
    各种排序方法总结
    509. Fibonacci Number
    374. Guess Number Higher or Lower
    238. Product of Array Except Self java solutions
  • 原文地址:https://www.cnblogs.com/paulprayer/p/9869637.html
Copyright © 2011-2022 走看看