LeetCode每日一题之无序数组--两数之和

前言

大家好,今天是LeetCode每日一题的第六天,给大家分享的是 无序数组–两数之和,难度系数一颗星!废话不多数,先上题目!

1.1 题目要求

题目类型两数之和

题目内容:给定一个整数数组 numbers,从数组中找出两个数满足相加之和等于目标数target

注意事项

  1. 假设每个输入只对应唯一的答案,而且不可以重复使用相同的元素
  2. 返回两数的下标值,以数组形式返回

1.2 解题方法

1.2.1 使用暴力算法
1.解题思路

题干分析

  • 假设存在一个整型数组nums,假设数组中存在两个元素:nums[i]和nums[j],满足从数组中找出两个数满足相加之和等于目标数target,即nums[i] + nums[j] = target;
    初始状态:[0, 1, 2, 3, ... , n-1]
                        ​i                         j  
    某一时刻: [0, 1, 2, 3, ... , n-1]
                           i  +  j = target
  • 题干中要求不可以重复使用相同的元素,即nums[i]和nums[j]不能为同一个元素,或者说 i 下标不等于 j下标;
  • 题干中还要求返回两数的下标值,以数组形式返回,即返回值为 [i,j]
2.代码实现
  • 测试代码
package com.kuang.leetcode7;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName TwoNumbersSum1
 * @Description 计算两数之和--无序数组
 * @Author 狂奔の蜗牛rz
 * @Date 2021/8/19
*/
public class TwoNumbersSum1 {

    //主方法测试
    public static void main(String[] args) {
        //初始化整型数组元素
        int[] arr = {1,3,5,2,4,6};
        //预估结果: 4+6=10, 返回值为4,5 (使用Arrays数组工具类的toString方法将返回值转换为字符串形式)
        System.out.println("暴力算法测试结果:"+ Arrays.toString(solution1(arr,10))); //测试结果: [4,5]
    }

    /**
     * 求两数之和 第一版
     * @param nums 整型数组
     * @param target 目标值
     * @return
     */
    public static int[] solution1(int[] nums, int target) {
        //外层循环遍历
        for (int i = 0; i < nums.length; i++) {
            //内层循环遍历
//            for(int j = 1; j < nums.length; j++) {
            /**
             *  第一轮循环: [0, 1, 2, 3, ..., n-1]
             *    外层循环: i->
             *    内层循环:     j->
             * 第二轮循环: [0, 1, 2, 3, ..., n-1]
             *    外层循环:    i ->
             *    内层循环:    j ->
             *  由于第二轮外层循环i从1开始, 而j的初值为1, 所以第二轮内层循环初始位置也是1,
             *  这样就出现两个指针位置重合的情况, 即本轮循环中j下标会走i下标走过的值,
             *  解决方案:
             *  为了保证两者不重合, 降低算法计算次数, 可以将j初值赋值为i+1, 即 j = i + 1
             */
            for(int j = i + 1; j < nums.length; j++) {
                //判断i下标元素和j下标元素相加之和是否等于target目标值
                if(nums[i] + nums[j] == target) {
                   //返回值为创建一个新的整型数组, 包含i和j下标
                   return new int[]{i,j};
                }
            }
        }
        //若target值不存在, 则返回值为一个元素值为0的整形数组
        return new int[0];
    }

}
  • 测试结果

在这里插入图片描述

结果与预测结果一致!

1.2.2 使用改进算法
1.解题思路

我们发现,需要确认i下标和j下标元素在数组中同时存在,这样才能保证target目标数存在, 但这样的时间复杂度为 O(n^2);

那怎样才能降低时间复杂度呢

解决方案:

其实我们完全不必要同时验证i下标和j下标元素存在, 为什么这样说?

  • 由于要满足 nums[i] + nums[j] == target条件,我们只需求出 target 和 num[i] 的差值是否存在,即验证 nums[j] 是否存在
2.代码实现
  • 测试代码
package com.kuang.leetcode7;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName TwoNumbersSum1
 * @Description 计算两数之和--无序数组
 * @Author 狂奔の蜗牛rz
 * @Date 2021/8/19
*/
public class TwoNumbersSum {

    //主方法测试
    public static void main(String[] args) {
        //初始化整型数组元素
        int[] arr = {1,3,5,2,4,6};
        //预估结果: 4+6=10, 返回值为4,5 (使用Arrays数组工具类的toString方法将返回值转换为字符串形式)
        System.out.println("改进算法测试结果:"+Arrays.toString(solution2(arr,10))); //测试结果: [4,5]
    }

    /**
     * 求两数之和 第二版
     * @param nums 整型数组
     * @param target 目标值
     * @return
     */
    public static int[] solution2(int[] nums, int target) {
        //创建一个key-value都为Integer类型的Map集合
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        //外层循环遍历
        for (int i = 0; i < nums.length; i++) {
            //判断map集合汇总是否包含target和nums[i]的差值的Key下标
            /**
             * 假设存在下面这样一个整型数组
             *         [1, 3, 5, 2, 4, 6]
             * 初始状态: i->
             * 指针右移: ------|----------->
             * 遍历到5:        i
             * 指针右移: ----------------|-->
             * 遍历到6:                  i
             * 假设i指针遍历到元素5位置, target和nums[i]的差值就已存在,那么就结束遍历;
             * 最坏情况也是遍历到元素6, 即把整个数组遍历一遍, 那么其时间复杂度为O(n)
             */
            if(map.containsKey(target - nums[i])) {
                /**
                 * 若map中Key值存在, 则返回一个新的整型数组,
                 * 其元素值为target和nums[i]的差值对应的value值和i下标
                 */
                return new int[]{map.get(target - nums[i]),i};
            }
            //若该轮遍历的i下标不符合条件, 将key值为nums[i], value值为i存入map集合中
            map.put(nums[i], i);
        }
        //若map中的Key值不存在, 则返回值为一个元素值为0的整形数组
        return new int[0];
    }

}
  • 测试结果

在这里插入图片描述

结果与预测结果一致!


好了,今天LeetCode每日一题—无序数组–两数之和到这里就结束了,欢迎大家学习和讨论,点赞和收藏!


参考视频链接:https://www.bilibili.com/video/BV1Ey4y1x7J3 (国内算法宝典-LeetCode算法50讲)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狂奔の蜗牛rz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值