【LeetCode】TwoSum - 求数组中两个数之和等于指定目标的加数下标

【LeetCode】TwoSum-求数组中两个数之和等于指定目标的加数下标


TwoSum 题目描述

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 = [2, 7, 11, 15], target = 9,
Because nums[ 0 ] + nums[ 1 ] = 2 + 7 = 9,
return [0, 1].

解决思路

思路一: 
假设数组是按序排列的,那么就算是暴力搜索,疯狂遍历也可以节省很多时间,因为 nums[0] n u m s [ 0 ] 是数组中的最小值,先取 nums[0] n u m s [ 0 ] ,然后开始遍历,若出现 nums[0]+nums[i]>target n u m s [ 0 ] + n u m s [ i ] > t a r g e t 时,显然下标大于 i i 的数无需再遍历。按着这个思路,一开始取数组中,最大的数和最小的数,分为 3 个判断:
nums[i]+nums[j]<target,i<j : 让小的数变大,继续遍历, i+1 i + 1
nums[i]+nums[j]<target,i>j n u m s [ i ] + n u m s [ j ] < t a r g e t , i > j : 让大的数变小,继续遍历, j j − −
nums[i]+nums[j]<target,i=j n u m s [ i ] + n u m s [ j ] < t a r g e t , i = j : 得到结果

思路二: 
目标要找到: A+B=target A + B = t a r g e t
从第一个开始找, nums[0] n u m s [ 0 ] 要满足要求,就希望数组中有另一个数,它的数值等于 targetnums[0] t a r g e t − n u m s [ 0 ] ,因此利用哈希表的字典查询功能,查询数组中是否有满足要求的,若有,则读取下标,结束遍历;否则继续遍历。
所以在简单的遍历思想上,加一点点小处理就可以解决了。不过这种方法每次运行的时间可能都不一样,因为若满足要求的其中一个数下标很靠前,那运行的速度就会快;若满足要求的两个数的下标都很靠后,那就相对比较费时。

下面附上完整代码:

代码块

思路一:

import java.util.Arrays;
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int head = 0,tail = nums.length-1, flag = 0;
        int[] output = new int[2];
        int[] temp = new int[nums.length];
        System.arraycopy(nums,0,temp,0,nums.length);
        Arrays.sort(temp); //对数组排序
        while(head<tail)
        {
            if(target > (temp[head]+temp[tail]))
            {
                head++;
            }
            else if(target < (temp[head]+temp[tail]))
            {
                tail--;
            }
            else
            {
                for (int i = 0; i < nums.length; i++){
                    if(nums[i] == temp[head] && flag == 0) 
                    //flag 用于避免两加数相等时找到的下标一样
                    {
                      output[0] = i;
                      flag = 1;
                    }
                    else if(nums[i] == temp[tail] && i!= output[0])
                    {
                      output[1] = i;
                    }
                }
                break;
            }
        } 
        return output;
  }
}

完成思路一的代码的过程中遇到了以下问题:
(1)创建临时数组 temp 时直接赋值 int[] temp = nums,这种赋值是地址上的赋值,因此执行sort(temp)时,改变的也是 nums 数组。后面查询过后,可以采用数组的复制,完成仅仅是数值的复制。数组的复制也有多种方法,最简单的 for 循环遍历赋值,以下列出 Java 中可用的复制方法:

  1. for 循环方法
  2. System.arraycopy()方法
  3. Arrays.copyOf()方法
  4. Object.clone()方法

代码示例:

int[] nums = {3,2,4}; // 原数组
int[] temp = new int[nums.length]; // 复制数组
// 方法1:
for(int i = 0; i<nums.length;i++)
{
    temp[i]=nums[i];
}

// 方法2:
// 参数说明:arraycopy(原数组,原书序需复制的起始位置,复制数组,复制数组放置的起始位置,复制长度)
System.arraycopy(nums, 0, temp, 0, nums.length);

// 方法3:
temp = Arrays.copyOf(nums, nums.length);

// 方法4:
temp = nums.clone();

以上方法及具体的优劣对比参考:
《Java中数组复制的几种方法 》:www.cnblogs.com/zhengbin/p/5671403.html

(2)在最后一步找回对应原数组的下标时,我一直想尽量少写代码(不会写+懒 orz),所以一开始直接使用output[0] = Arrays.binarySearch(nums,temp[head]) 查询数组下标。当然是因为有bug,所以迫使我去改了,不然没办法 Accepted 呀。错误的原因是 Arrays.binarySearch(数组,目标数值) 原理是使用二分法查询找出下标。二分法一般用于排序后的数组,对于 nums 原数组是没有排序的,因此查询的结果不稳定,会出错。

具体可看:
《JAVA之数组查询binarySearch()方法详解》:https://blog.csdn.net/a1b2c3d4123456/article/details/51097161

思路二:

import java.util.Arrays;
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int index[] = {0,0};
        HashMap<Integer, Integer> num = new HashMap<Integer,Integer>(); //创建哈希表
        for(int i=0;i<nums.length;i++) //初始化哈希表
        {
            num.put(nums[i], i);
        }
        for(int i=0;i<nums.length;i++)
        {
            int temp = target-nums[i]; // 求出另一个期望加数temp
            if(num.containsKey(temp)&&i<num.get(temp))
            //判断哈希表中是否含有与temp相等的,若是则目标找到
            {
                index[0] = i;
                index[1] = num.get(temp);
                break;
            }
        }
        return index;
  }
}

欢迎大家有更好的方法讨论分享~
小白初学编程 > <

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值