两数之和-字节跳动/阿里巴巴/美团/富途笔试编程C/C++

 

今天中午去剪头发了,这家店不推销卡、不尬聊,全程舒适又愉快,今天顺心的事一件接一件呢~--2021年4月7日

目录

题目描述:

分析

C++代码

踩过的坑

踩坑(一)

踩坑(二)


题目描述:

给出一个整数数组,请在数组中找出两个加起来等于目标值的数,

你给出的函数twoSum 需要返回这两个数字的下标(index1,index2),需要满足 index1 小于index2.。注意:下标是从1开始的,假设给出的数组中只存在唯一解

例如,给出的数组为 {3, 7, 8, 9, 5, 12, 10},目标值为16,输出 index1=2, index2=4

(更多博文,欢迎来我的博客学习交流https://blog.csdn.net/have_a_cat

输入:[3,7,8,9,5,12,10],16

输出:[2,4]

(这是牛客网提供的一道题目,想尝试的码友们,可以通过这个链接挑战https://www.nowcoder.com/practice/20ef0972485e41019e39543e8e895b7f?tpId=188&tqId=38285&rp=1&ru=%2Factivity%2Foj&qru=%2Fta%2Fjob-code-high-week%2Fquestion-ranking&tab=answerKey)

分析

这道题目比较有趣,推出“后指针摇摆法~我自己起的名字,请大家将就看下😀

分为五个步骤:

题目给出数组numbers,,目标值target

numbers=[3,7,8,9,5,12,10]

target=16

步骤一

复制数组numbersf。(为了接下来做的操作不破坏题目给出的numbers

f=[3,7,8,9,5,12,10]

步骤二

f排序(这里使用系统自带的sort函数)

f=[3,5,7,8,9,10,12]

步骤三

f中找这两个整数(设为f[i]和f[j]),使f[i]+f[j]== target(这里就用到了“后指针摇摆法”)

先来看下这个思想(一时不懂不要紧,随后就来例子演示

思想:

初始--i为0,即f[i]为f的第一个数,也是f中最小的数;j为f.size() - 1;,即f[j]为f中的最后一个数,也是f中最大的数;

i由0依次递增1,即由小到大遍历f中的每一个数;(更多博文,欢迎来我的博客学习交流https://blog.csdn.net/have_a_cat

对每一个f[i],

若(f[i]+f[j]) < target,则j++(使f[j]更大一些,使(f[i]+f[j])更靠近target)

                            若(f[i]+f[j]) > target,则j--(使f[j]更小一些,使(f[i]+f[j])更靠近target)

                            若(f[i]+f[j]) == target,则进入步骤四

核心代码段

        int i = 0;

        int j = f.size() - 1;

        while( (2 * f[i]) < (target + 1))

        {

            while(((f[i] + f[j]) < target)&&(j < (f.size() - 1)))

            {

                j++;

            }

            while(((f[i] + f[j]) > target)&&(j > i))

            {/*(更多博文,欢迎来我的博客学习交流https://blog.csdn.net/have_a_cat)*/

                j--;

            }

            if((f[i] + f[j]) == target)

            {

                break;

            }

            i++;

        }

例子演示:

 

numbers

target

备注

执行的代码的序号

第1步

[3,5,7,8,9,10,12]

16

 

初始

第2步

[i->3,5,7,8,9,10,12]

16

 

第3步

[i->3,5,7,8,9,10, j->12]

16

 

第4步

[i->3,5,7,8,9,10, j->12]

16

(2*3)<(16+1) -->√

第5步

[i->3,5,7,8,9,10, j->12]

16

f[i]+f[j])<target;j已最右

第6步

[i->3,5,7,8,9,10, j->12]

16

f[i]+f[j])!>target

第7步

[i->3,5,7,8,9,10, j->12]

16

f[i]+f[j])!=target

第8步

[3, i->5,7,8,9,10, j->12]

16

i++

第9步

[3, i->5,7,8,9,10, j->12]

16

(2*5)<(16+1) -->√

第10步

[3, i->5,7,8,9,10, j->12]

16

f[i]+f[j])!<target

第11步

[3, i->5,7,8,9,10, j->12]

16

f[i]+f[j])>target

第12步

[3, i->5,7,8,9, j->10, 12]

16

j--

第13步

[3, i->5,7,8,9, j->10, 12]

16

f[i]+f[j])!=target

第14步

[3, 5, i->7,8,9, j->10, 12]

16

i++

第15步

[3, 5, i->7,8,9, j->10, 12]

16

(2*7)<(16+1) -->√

第16步

[3, 5, i->7,8,9, j->10, 12]

16

f[i]+f[j])!<target

第17步

[3, 5, i->7,8,9, j->10, 12]

16

f[i]+f[j])>target

第18步

[3, 5, i->7,8, j->9, 10, 12]

16

j--

第19步

[3, 5, i->7,8, j->9, 10, 12]

16

f[i]+f[j])==target

第20步

[3, 5, i->7,8, j->9, 10, 12]

16

break

看下j的轨迹,来回小范围摇摆,故我起名 “后指针摇摆法

步骤四

找到 f[i]f[j]number中的位置,用num_i记录数字f[i]number中的位置;用num_j记录数字f[j]number中的位置.

步骤五

num_inum_j放入数组result;中。

result排序(这里使用系统自带的sort函数)【注意!!!题目这里说过:“需要返回这两个数字的下标(index1,index2),需要满足 index1 小于index2

返回result(更多博文,欢迎来我的博客学习交流https://blog.csdn.net/have_a_cat

C++代码

class Solution {

public:

    /**

     *

     * @param numbers int整型vector

     * @param target int整型

     * @return int整型vector

     */

    vector<int> twoSum(vector<int>& numbers, int target) {

        // write code here

        /*1 复制数组numbers到f*/

        vector<int> f(numbers.begin(),numbers.end());

       

        /*2 对f排序(更多博文,欢迎来我的博客学习交流https://blog.csdn.net/have_a_cat)*/

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

       

        /*3 在f中找这两个整数*/

        int i = 0;

        int j = f.size() - 1;

        while( (2 * f[i]) < (target + 1))

        {

            while(((f[i] + f[j]) < target)&&(j < (f.size() - 1)))

            {

                j++;

            }

            while(((f[i] + f[j]) > target)&&(j > i))

            {

                j--;

            }

            if((f[i] + f[j]) == target)

            {

                break;

            }

            i++;

        }

       

        /*4 找到 f[i] 和 f[j]在number中的位置(更多博文,欢迎来我的博客学习交流https://blog.csdn.net/have_a_cat)*/

        int num_i = 0;

        int num_j = 0;

        for(int q = 0; q < numbers.size(); q++)

        {

            if((f[i] == numbers[q])&&(num_i == 0))

            {

                num_i = q + 1;

            }

            else{

                if((f[j] == numbers[q])&&(num_j == 0))

                {

                    num_j = q + 1;

                }

            }

        }

       

        /*5 将num_i、num_j放入输出*/

        vector<int> result;

        result.push_back(num_i);

        result.push_back(num_j);

        sort(result.begin(),result.end());/*需要返回这两个数字的下标(index1,index2),需要满足 index1 小于index2.(更多博文,欢迎来我的博客学习交流https://blog.csdn.net/have_a_cat)*/

        return result;

    }

};

踩过的坑

踩坑(一)

输入:[0,4,3,0],0

输出:[1,4](更多博文,欢迎来我的博客学习交流https://blog.csdn.net/have_a_cat

反思:这里结果是0+0==0;所以要注意步骤四中对相同数字的处理。

踩坑(二)

输入:[5,75,25],100

输出:[2,3]

反思步骤五中要对result排序,因为题目说“需要返回这两个数字的下标(index1,index2),需要满足 index1 小于index2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值