[LeetCode-01]-Two Sum

文章目录

    • 题目相关
    • Solution
      • 1. 暴力求解
      • 2. 暴力求解方法改进
      • 3. 不可行的方案
    • 后记

每周完成一个ARTS:(Algorithm、Review、Tip、Share, ARTS)

  • Algorithm: 每周至少做一个 leetcode 的算法题
  • Review: 阅读并点评至少一篇英文技术文章
  • Tip: 学习至少一个技术技巧
  • Share: 分享一篇有观点和思考的技术文章

题目相关

【题目】原题链接
Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

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

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

【难度】Easy

Solution

1. 暴力求解

最直接的方法,进行暴力求解,进行两次遍历。代码如下:

该代码性能表现:(性能低,耗时长)

  • Your memory usage beats 92.16 % of cpp submissions.
  • Runtime: 408 ms
  • Memory Usage: 9.3 MB
    vector<int> twoSum_lowPerformance(vector<int> &nums, int target)
    {
        int nFirstPos = 0;
        int nSecondPos = 0;
        int nLen = nums.size();

        for (int i = 0; i < nLen; i++)
        {
            for (int j = 0; j < nLen; j++)
            {
                //i,j不能一样
                if (i != j)
                {
                    int temp = nums[i] + nums[j];
                    if (temp == target)
                    {
                        if (i < j)
                        {
                            nFirstPos = i;
                            nSecondPos = j;
                            break;
                        }
                        else if (i > j)
                        {
                            nFirstPos = j;
                            nSecondPos = i;
                            break;
                        }
                    }
                }
            }
        }

        vector<int> vecRet;

        if (nFirstPos != nSecondPos)
        {
            vecRet.push_back(nFirstPos);
            vecRet.push_back(nSecondPos);
            return vecRet;
        }
        else
        {
            return vecRet;
        }
    }

2. 暴力求解方法改进

上面的暴力求解中,其实在进行两次遍历时有很多可以优化的地方,比如i从1开始,进行逐个相加比较,此时应该从第二个元素开始进行比较,第一个没必要了(题目要求:同一个元素不要使用两次)。代码如下:

该代码性能表现:(性能低,耗时长)

  • Your runtime beats 40.17 % of cpp submissions.
  • Runtime: 112 ms
  • Memory Usage: 9.4 MB
    //target - first,然后在已有的数据中遍历查找
    vector<int> twoSum(vector<int> &nums, int target)
    {
        int nFirstPos = 0;
        int nSecondPos = 0;
        int nLen = nums.size();
        vector<int> vecRet;

        for (int i = 0; i < nLen; i++)
        {
            int temp = target - nums[i];

            for (int j = i + 1; j < nLen; j++)
            {
                // printf("i = %d,j = %d,temp = %d, tartget = %d\n", i, j, temp, target);
                if (temp == nums[j])
                {
                    nFirstPos = i;
                    nSecondPos = j;
                    //break; //仅有一个break只能跳出一个for循环,外围的for不能跳出
                           // 所以这里要么使用goto,要么直接return。
                    //    由于return报错,所以采用goto方式
                    if (nFirstPos != nSecondPos)
                    {
                        vecRet.push_back(nFirstPos);
                        vecRet.push_back(nSecondPos);
                        goto end;
                    }
                }
            }
        }
    end:
        return vecRet;
    }

3. 不可行的方案

通过 方案2 获知,该问题可以看成在序列中进行查找「target - first」,所以想到了二分查找,二分查找需要有序才有效,题目中没有相关有序字段,所以想到了排序。。。

先看代码,后面有分析

    //先排序
    //target - first,然后在已有的数据中进行二分查找
    // 不能这么操作,不然顺序已经改变了,后面再检测到的下标已经无效
    vector<int> twoSum_err(vector<int> &nums, int target)
    {
        int nFirstPos = 0;
        int nSecondPos = 0;
        int nLen = nums.size();

        sort(nums.begin(), nums.end(), less<int>());

        for (int i = 0; i < nLen; i++)
        {
            int temp = target - nums[i];
            std::cout << "temp = " << temp << endl;

            //二分查找?
            vector<int>::iterator index = lower_bound(nums.begin(), nums.end(), temp);

            if (index != nums.end())
            {
                nFirstPos = i;
                nSecondPos = index - nums.begin();
                break;
            }
        }

        vector<int> vecRet;
        if (nFirstPos != nSecondPos)
        {
            vecRet.push_back(nFirstPos);
            vecRet.push_back(nSecondPos);
            return vecRet;
        }
        else
        {
            return vecRet;
        }
    }

上面的代码不可行,这样能提到查找效率,但是经过排序后,原序列中的顺序已经改变了,后面返回的下标是最新的,而不是之前的,所以该方案不可行。

后记

改进的方案 在CPP中才排到40.17 %,说明还有更好的方案,没看解析,继续思考最优方案,看看自己能想到哪些。

你可能感兴趣的:(ARTS,LeetCode)