leetcode1 Two Sum题解

题目大概意思就是,我给你传进来一个vector容器和一个target,vector相当于一个数组,现在问target是有数组种哪两个数组成的,返回两个下标,注意函数的返回类型也是vector类型的,所以一定要注意.

题目刚到手的时候,发现这个与各大OJ套路不太一样啊,也就是与ACM不太一样,我还傻傻的调整输出格式什么的,而且这个是完善一个类的成员函数,而不是提交一个可以运行的完整代码,觉得还是挺新奇的.

思路分析

最开始的时候,以为这个如果数据量不是很大的时候可以桶排序暴力破解啊,我见建立了一个10000这么大的数组,先全部初始化为-1,之后遍历整个数组,如果这个数存在则将这个数在vector中的位置存入数组中.之后在遍历一遍数组判断target-num[i]的数组是否为正数,如果为正数则push_back进vector,return即可.但是提交之后发现这尼玛vector中还要负数,导致这个就失败了,但我反过来一想我建立两个大数组不就OK了吗,一个代表正数一个代表负数,之后我就又提交了一遍然后这次小的数据都通过了,出现了一个30000多的数,我突然发现我的数组还是10000大小的,我将其改为1000000,之后sublime就报段错误(核心已转移),我猜测可能是越界了,之后我慢慢缩小到50000还是报错,想想估计是套路不对吧,to
young to simple啊.

将我前几次提交的代码贴一下(RunTime Error):

#include <vector>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
using std::vector;

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {

        int RecordZ[10000];
        int RecordF[10000];
        int i,j;
        int VecLen = nums.capacity();
        int nTemp;

        vector<int> result;

        memset(RecordZ,-1,sizeof(RecordZ));
        memset(RecordF,-1,sizeof(RecordF));

        for(i=0;i<VecLen;i++)
        {
            if (nums[i]>0)
            {
                RecordZ[nums[i]] = i + 1;
            }
            else
            {
                RecordF[abs(nums[i])] = i + 1;
            }
        }

        for(i=0;i<VecLen;i++)
        {
            nTemp = target - nums[i];
            if (nTemp>0&&RecordZ[nTemp]!=-1)
            {
                result.push_back(i+1);
                result.push_back(RecordZ[nTemp]);
                return result;
            }
            else if(nTemp<0&&RecordF[abs(nTemp)]!=-1)
            {
                result.push_back(i+1);
                result.push_back(RecordF[abs(nTemp)]);
                return result;
            }
        }
    }
};

int main()
{
    Solution test;
    vector<int> Nums;
    Nums.push_back(2);
    Nums.push_back(3);
    Nums.push_back(4);
    Nums = test.twoSum(Nums, 6);
    printf("%d,%d\n",Nums[0],Nums[1]);
    return 0;
}

之后我就想大空间是不可能了,创建了一个map吧,这个可以一一对应,需要那个就查找就OK了,map的查找是二分查找,所以时间复杂度为log(n),估计得查找n-i次(i = 1,2,3,4...n),所以总体的复杂度为nlog(n),自我感觉应该没啥问题.大体思路还是差不多,只不过存储方式由数组改为了map果不其然啊AC.但是这版代码还可以继续优化,可以变得更简练,可以将两个遍历合在一起,相当于从后开始搜索,而不是从前开始搜索,比如说1,2,3,5想要组成6那么有两种取法就是(1,4)或者(4,1).如果直接从后往前查找都不用判断大小就可以直接输出了.

第一版map代码(AC)

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        map<int, int> m;//存储vector中的值和下标
        map<int, int>::iterator it;//map方法返回的都是iterator类型的数据
        vector<int> result;//存储要返回的下标
        int i;//循环变量

        for(i=0; i<nums.size(); ++i)//遍历数组将所有值都插入map中
        {
            m.insert(make_pair(nums[i], i+1));
        }
        for(i=0; i<nums.size(); ++i)//循环通过target-num[i]判断是否num[i]符合原则
        {
            int another = target - nums[i];
            it = m.find(another);
            if(it != m.end()&&(it->second!=(i+1))) //因为存在如6 = 3 + 3,所以去掉位置相同的情况
            {
                if(it->second>(i+1))//将下标从大到小排序,其实也可以用sort(m.begin(),m.end())
                {
                    result.push_back(i+1);
                    result.push_back(it->second);
                    break;
                }
                else
                {
                    result.push_back(it->second);
                    result.push_back(i+1);
                    break;
                }

            }
        }
        return result;
    }
};

最终版代码来了(AC)

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        map<int, int> m;//存储vector中的值和下标
        map<int, int>::iterator it;//map方法返回的都是iterator类型的数据
        vector<int> result;//存储要返回的下标
        int i;//循环变量
        for(i=0; i<nums.size(); ++i)
        {
            int another = target - nums[i];
            it = m.find(another);
            if(it == m.end())   // 没找到,加入缓冲区
            {
                m.insert(make_pair(nums[i], i+1));
            }
            else
            {
                result.push_back(it->second);
                result.push_back(i+1);
                break;
            }
        }
        return result;
    }
};


反过来想也可以将vector输入到map中,之后从小到大排好序,定义两个变量i指向队头j指向队尾,之后将Num[i]+Num[j]的值与target判断大小,如果相等则输出,如果大于则j--,否则i++.

bool cmp(pair<int,int> &p1, pair<int,int> &p2) {
    return p1.first < p2.first;
}

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<pair<int,int>> v;
        for(int i=0; i<nums.size(); ++i)
            v.push_back(make_pair(nums[i], i+1));

        sort(v.begin(), v.end(), cmp);  

        int i = 0;//队头
        int j = v.size()-1;//队尾
        vector<int> res;
        while(i < j) {//其实和快排差不多,都是两个指针分别像左向右
            int sum = v[i].first + v[j].first;
            if(sum == target) {
                res.push_back(v[i].second);
                res.push_back(v[j].second);
                break;
            }
            else if(sum < target)
                ++i;
            else
                --j;
        }

        sort(res.begin(), res.end());

        return res;
    }
};

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-28 15:10:42

leetcode1 Two Sum题解的相关文章

LeetCode: Two Sum 题解

Given an array of integers, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that

leetcode-1 Two Sum 找到数组中两数字和为指定和

 问题描述:在一个数组(无序)中快速找出两个数字,使得两个数字之和等于一个给定的值.假设数组中肯定存在至少一组满足要求. <剑指Offer>P214(有序数组) <编程之美>P176 Que:Given an array of integers, find twonumbers such that they add up to a specific target number. The function twoSum should return indices ofthe tw

LeetCode1 Two Sum **

题目: Given an array of integers, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note t

01Two Sum题解

Tow Sum 原题概述: 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 =

Hdoj 1003.Max Sum 题解

Problem Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14. Input The first line of the input contains

LeetCode 1 Two Sum 题解

Problem: Given an array of integers, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please n

leetcode1 Two Sum的JavaScript解答总结

一.问题描述 翻译: 给定一个整数数组,找出其中两个数满足相加等于你指定的目标数字.你可以假设每一个输入只有一个结果.举例:输入:nums=[2, 7, 11, 15], target = 9输出:[0,1] 二.解答1.每出现一个值x,直接在数组中寻找是否有等于(target-x)的值 1 /** 2 * @param {number[]} nums 3 * @param {number} target 4 * @return {number[]} 5 */ 6 var twoSum = fu

HDU1003 Max Sum 题解 动态规划 最大字段和扩展

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003 题目大意: 求解一个序列的最大字段和,已经最前面的那个最大子段的起止坐标. 解题思路: 定义状态 \(f[i]\) 为以 \(a[i]\) 结尾的最大字段和,则有状态转移方程: \[f[i] = \max(0, f[i-1]) + a[i]\] 同时定义状态 \(s[i]\) 表示以 \(a[i]\) 结尾的最大字段的最左边元素的坐标,则有: 当 \(f[i] \lt 0\) 时,\(s[i]

CF33C Wonderful Randomized Sum 题解

原题链接 简要题意: 你可以无限次的把该数组的一个前缀和后缀 \(\times -1\),问最终的最大序列和. 这题盲目WA了数次才知道本质 这题89个数据吊打std CF真好啊,发现一个错后面就不测了 下面,就以我艰辛的思维历程来构造本篇博客. 算法一 盲猜:所有数都可以变成正数. 然后绝对值相加. 连样例也没测. 然后,\(\frac{2}{89} pts\). 只过了前两个样例,第三个就死了. #pragma GCC optimize(2) #include<bits/stdc++.h>