Two Sum-n方优化与C++map的使用

LeetCode第一题,刚拿到题目时虽然明知道n方的遍历算法会超时,但还是不信邪的提交了一次,然而编程不存在运气,TLE不可避免。但是之后的思维方式比较直接,我并没有立刻想到O(n)的方法,想了一种先对数组进行排序,利用目标数和待选择的数的关系来减小搜索范围:

1.不存在负数:那么比目标数大的数不必搜索

2.存在负数:搜索负数和比目标大的数,或者搜索正数比目标小的数;这种情况还存在全为负数,只能按照最差的n方方式搜索。

按照这个优化思路,虽然算法严格意义上来说是n方复杂度的,但是实际性能并不一定这么差,以下是AC代码:

Two Sum-n方优化与C++map的使用
/**

 * Note: The returned array must be malloced, assume caller calls free().

 */

typedef struct newtype

{

    int num;int index;

}Data;

int cmp ( const void *a , const void *b )

{

    Data *c = (Data *)a;Data *d = (Data *)b;

    if(c->num != d->num)

        return c->num - d->num;

    else

        return d->index - c->index;

}



int* twoSum(int* nums, int numsSize, int target) {

    int *res,i,j,fuflag=numsSize,bigflag=numsSize;

    int tempgflag=0;

    int tempres;

    Data *data=(Data *)malloc(sizeof(Data)*numsSize);

    for(i=0;i<numsSize;i++)

    {

        data[i].index=i;

        data[i].num=nums[i];

    }

    res=(int *)malloc(sizeof(int)*2);

    qsort(data,numsSize,sizeof(Data),cmp);

    for(i=0;i<numsSize;i++)

    {

        if(data[i].num<0)

            fuflag=i;

        if(data[i].num<=target)

            bigflag=i;

    }

    //1.无负数,只需到比这个数小的位置

    if(fuflag==numsSize)

    {

        for (i = 0; i <=bigflag; i++)

            for (j = i+1; j <=bigflag; j++)

                if (data[i].num + data[j].num == target) {

                    if (data[i].index > data[j].index) {

                        res[0] = data[j].index + 1;

                        res[1] = data[i].index + 1;

                    } else {

                        res[1] = data[j].index + 1;

                        res[0] = data[i].index + 1;

                    }

                    break;

                }

    }

    else//2.有负数,所有数都比这个数大

    {



        for (i = 0; i <= fuflag; i++)

            for (j = bigflag + 1; j < numsSize; j++)

                if (data[i].num + data[j].num == target) {

                    tempgflag=1;

                    if (data[i].index > data[j].index) {

                        res[0] = data[j].index + 1;

                        res[1] = data[i].index + 1;

                    } else {

                        res[1] = data[j].index + 1;

                        res[0] = data[i].index + 1;

                    }

                    break;

                }

        if(tempgflag==0)

        {

            for (i = fuflag + 1; i <= bigflag; i++)

                for (j = i + 1; j <= bigflag; j++)

                    if (data[i].num + data[j].num == target) {

                        tempgflag=1;

                        if (data[i].index > data[j].index) {

                            res[0] = data[j].index + 1;

                            res[1] = data[i].index + 1;

                        } else {

                            res[1] = data[j].index + 1;

                            res[0] = data[i].index + 1;

                        }

                        break;

                    }

        }

        if (tempgflag == 0) {

            for (i = 0; i <= numsSize; i++)

                for (j = i + 1; j <= numsSize; j++)

                    if (data[i].num + data[j].num == target) {

                        if (data[i].index > data[j].index) {

                            res[0] = data[j].index + 1;

                            res[1] = data[i].index + 1;

                        } else {

                            res[1] = data[j].index + 1;

                            res[0] = data[i].index + 1;

                        }

                        break;

                    }

        }

    }

    return res;

}
n方优化

然而在提交之后看了solution才想到另外两种方法,由于确定是两个数字,所以用目标数减去当前某个数字,然后再在候选数里查找这个数!

可以用二分查找,也可以用hash表。

接下来就是使用C++ STL map来实现这个hash过程。

map的使用主要包括声明,赋值,查找,使用迭代器。

声明:

map<int, int> datamap;

赋值:

map遵循<key ,value >的原则,key是不可以重复的!

for(i=0;i<n;i++)

        datamap[nums[i]]=i;

查找:

map<int,int>::iterator it;



it=datamap.find(target-nums[i]);

使用迭代器:

map的迭代器和vector并不相同,需要使用->来获取元素不能直接使用*

if(it!=datamap.end()&&it->second!=i)

使用map的AC代码:

Two Sum-n方优化与C++map的使用
 1 class Solution {

 2 public:

 3     vector<int> twoSum(vector<int>& nums, int target) {

 4         map<int, int> datamap;

 5         vector<int> res;

 6         int i;

 7         int n=nums.size();

 8         for(i=0;i<n;i++)

 9             datamap[nums[i]]=i;

10         map<int,int>::iterator it;

11         for(i=0;i<n;i++)

12         {

13             it=datamap.find(target-nums[i]);

14             if(it!=datamap.end()&&it->second!=i)

15             {

16                 if(i>it->second){

17                     res.push_back(it->second + 1);

18                     res.push_back(i + 1);

19 

20                 }

21                 else

22                 {

23                     res.push_back(i + 1);

24                     res.push_back(it->second + 1);

25 

26                 }

27                 break;

28             }

29         }

30         return res;

31 

32     }

33 };
map

 

本想再试一下hashmap,但是由于并不是标准C++库,所以需要以下头文件和命名空间:

#include <ext/hash_map>

using namespace __gnu_cxx;

才可以在linux上的Eclispe里编译,但是提交发现leetcode的评测环境并不支持以上库,也就没有再试,但是看到网上很多推荐使用unordered_map:

#include <tr1/unordered_map>

使用方法和map,hashmap类似。

PS:

这个题目的数据并不是排好序的!

以下是几组容易wa的测试数据:[-1,-2,-3,-4,-5] -8 ,[0,3,4,0] 0,[-3,4,3,90] 0。

这个题目也是逆向思维的简单应用,并不需要复杂的算法和精妙的构思,反转一下足够。

 

你可能感兴趣的:(C++)