zoukankan      html  css  js  c++  java
  • Two Sum-n方优化与C++map的使用

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

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

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

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

    /**
     * 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代码:

     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。

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

  • 相关阅读:
    Extjs Ext.extend函数的使用
    Silverlight 4 用户名密码验证提示
    Balsamiq Mockups
    自定义RDLC报表的数据集(手工编辑rdlc文件,配置数据集)
    VS2010 帮助文档离线安装
    为 Silverlight 客户端生成服务
    将Win7电脑改造成无线路由
    RDLC报表:每页显示N条记录
    C# 禁止ALT+F4
    让C#程序run anywhere 脱离.net Framework框架环境
  • 原文地址:https://www.cnblogs.com/holyprince/p/4602007.html
Copyright © 2011-2022 走看看