力扣第一题:两数之和

力扣第一题:两数之和

题目描述

给定一个整数数组nums和一个整数目标值target,请在该数组中找出和为目标值target的两个整数,并返回他们的数组下标。

假定每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现

可按照任意顺序返回答案

输出示例

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
输入:nums = [3,2,4], target = 6
输出:[1,2]
输入:nums = [3,3], target = 6
输出:[0,1]

字符串切割

void spiltStr(string str,const string & split,vector<string>&strlist)
{
    strlist.clear();
    if(str=="")
        return;
    string strs=str+split;
    size_t pos=strs.find(split);
    int steps=split.size();

    while(pos!=strs.npos)
    {
        //substr 复制字符串,起始位置,复制字符数目
        string temp=strs.substr(0,pos);
        strlist.push_back(temp);
        strs=strs.substr(pos+steps,strs.size());
        pos=strs.find(split);
    }

}



int main()
{
    vector<int>num;
    vector<int>indexNum;
    vector<string>strlist;
    string inputStr;
    string tempStr;
    int target;

    getline(cin,inputStr);
    if(inputStr=="")
    {
        return 0;
    }

    //分割输入的字符串
    spiltStr(inputStr,"[",strlist);
    spiltStr(strlist[1],"]",strlist);
    spiltStr(strlist[0],",",strlist);

    //将vector<string>spiltStr的数值写入vector<int>nums中
    for(auto i:strlist)
    {
        num.push_back(stoi(i));
    }

    spiltStr(inputStr,"=",strlist);

    // spiltStr(strlist.back(),"=",strlist);
    target=stoi(strlist.back());


    // for(auto i:num)
    // {
    //     cout<<i<<" ";
    // }
    // cout<<endl;
    // cout<<target<<endl;

    indexNum=twoSum(num,target);

    cout<<"["<<indexNum[0]<<","<<indexNum[1]<<"]";

}

具体的实现步骤介绍可以参考我上一篇博文

初次尝试样例

#include<iostream>
#include<vector>
#include<string>
using namespace std;

vector<int> twoSum(vector<int>&nums,int target)
{
    // for(auto i:nums)
    // {
    //     cout<<i<<" ";
    // }
    // cout<<endl;
    // cout<<target<<endl;
    // cout<<"we have find the index is:"<<endl;

    vector<int>indexNum;

    for(auto iter=nums.begin();iter!=nums.end();iter++)
    {
        auto jter=iter;
        for(jter=iter++;jter!=nums.end();jter++)
        {
            // cout<<iter<<jter<<endl;
            // jter++;
            if((*iter)+(*jter)==target)
            {
                // cout<<(*iter)<<" "<<(&(*iter))<<endl;
                // cout<<(*jter)<<" "<<(&(*jter))<<endl;
                // cout<<&nums[0]<<endl;


                indexNum.push_back(&(*iter)-&nums[0]);
                indexNum.push_back(&(*jter)-&nums[0]);
                return indexNum;
            }


        }
    }


   return indexNum;

}

总结:

本来以为第一题比较简单,结果发现好家伙,自己写的嘛玩意,各种内存报错。好不容易递交上去,结果发现执行出错,陷入了深深的沉思。痛下思痛,决定去瞅瞅别人是怎么做的,果真别人做的,确实比自己好太多了。

方法一:暴力解法

vector<int> sloveForce(vector<int>nums,int target)
{
    //初始化下标
    int i,j=0;
    for(i=0;i<nums.size()-1;i++)
    {
        for(j=i+1;j<nums.size();j++)
        {
            if(nums[i]+nums[j]==target)
            {
                return {i,j};
            }
        }
    }
    return {i,j};
}

这种方法的使用的是vector的size函数,特别暴力,通过两个for循环,从而使得最后的时间复杂度达到 O( n 2 n^2 n2) ,所以最后提示耗时和内存消耗比较大,空间复杂度 O ( 1 ) O(1) O(1)

在这里插入图片描述

方法二:两遍哈希表

vector<int> sloveHash(vector<int>nums,int target)
{
    //建立hash 
    map<int,int> numSave;

    //将最好查找到的坐标存入到vector容器中
    vector<int>indexNum;
    
    for(int i=0;i<nums.size();i++)
    {
        //像map中插入元素有四种方法可以参考《C++ Primer》P384
        numSave.insert(make_pair(nums[i],i));
    }

    for(int i=0;i<nums.size();i++)
    {
        //判断相减的目标在不在hash表中,且这个找到的hash表的坐标不能是自己
        if((numSave.count(target-nums[i])>0)&&(numSave[target-nums[i]]!=i))
        {
            indexNum.push_back(i);
            indexNum.push_back(numSave[target-nums[i]]);
            return indexNum;
        }
    }
    return indexNum;

}

使用hash这个方法实在是太妙了,利用hash中的“键值对”的概念,越翻《C++ Primer》,越觉得有意思,太棒了。这个主要的依据是map函数中的count函数和其键对的思想。其时间复杂度为 O ( n ) O(n) O(n) 空间复杂度为 O ( n ) O(n) O(n)

在这里插入图片描述

方法三:两遍哈希表

vector<int> sloveHashOnce(vector<int>nums,int target)
{
    map<int,int>numSave;
    vector<int>indexNum;

    for(int i=0;i<nums.size();i++)
    {
        //判断值是否被找到
        if(numSave.count(target-nums[i])>0)
        {
            //先存入查找到的计算存在的值
            indexNum.push_back(numSave[target-nums[i]]);
            indexNum.push_back(i);
            return indexNum;
        }
    //若map中未存在当前的计数,就把这个数保存到map中,实现了之前的hash写入东西的功能
        numSave[nums[i]]=i;
    }
    return indexNum;
}

方法三的方法是在方法二的基础上进行改进,也更加精妙。两次hash还需要将键对写入hash中浪费一次for循环。而这次直接是先判别,如果存在就跳出,如果不存在,那么就将该键值对写入map中,也是很巧妙的方法。算法真的让人太好玩了,让人有做数学题的冲动。事实证明,只把《C++ Primer》理论知识看一遍是不够的,还需要实践,实操。加油,刷完100题,再回看一遍。

上一题的时间复杂度其实是 O ( 2 n ) O(2n) O(2n),本次的时间复杂度为 O ( n ) O(n) O(n),性能提升了一倍。空间复杂度则保持相同为 O ( n ) O(n) O(n)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值