14天刷爆LeetCode算法学习计划——Day03 双指针(2)

一、前言

盲目刷题只会让自己心态爆炸,所以本期14天算法学习计划,也是LeetCode上的 *[算法]*学习计划,在本专栏的每一篇文章都会整理每一天的题目并给出详细题解,以及知识点的整理

二、知识点

戳下方链接查看⬇⬇⬇

14天刷爆LeetCode算法学习计划——Day02双指针(1)

三、LeetCode167. 两数之和 II - 输入有序数组

1.题目

LeetCode167. 两数之和 II -输入有序数组
给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。
以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
你所设计的解决方案必须只使用常量级的额外空间。

示例 1:
输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此index1 = 1, index2 = 2 。返回 [1, 2] 。

示例 2:
输入:numbers = [2,3,4], target = 6
输出:[1,3]
解释:2 与 4 之和等于目标数 6 。因此index1 = 1, index2 = 3 。返回 [1, 3] 。

示例 3:
输入:numbers = [-1,0], target = -1
输出:[1,2]
解释:-1 与 0 之和等于目标数 -1 。因此index1 = 1, index2 = 2 。返回 [1, 2] 。

2.解题思路(含图)

  • 我们可以定义左右指针,并将左右指针指向的值的和赋值给一个变量sum
  • 当我们的 sum 比 targer(要求的和)小 的话,由于数组按照递增的顺序,既然此时right指向的已经是数组最大值了,那么只能将left指向的值变得更大,即 left的值加1

在这里插入图片描述

  • 当我们的sum 比 target(要求的和)大的话,由于数组按照递增的顺序,既然此时left指向的已经是数组最小值了,那么只能将right指向的值变得更小,即 right的值减1

在这里插入图片描述

  • 重复操作,直至 sum = target
    在这里插入图片描述

3.注意事项

  • 数组的下标值是从1开始记录的,所以在输出时 left 和 right 的值要加1

  • 由于此时要输出的是数组形式,所以返回值不能是一个值,而要是数组,即 return new int[] {left + 1,right + 1}

4.代码实现

class Solution {
    public int[] twoSum(int[] numbers, int target) {
    	//定义左指针
        int left = 0;
        //定义右指针
        int right = numbers.length - 1;
        //求下标值
        while(left < right){
        	//用变量sum接收左右指针指向元素的和,使代码更简洁
            int sum = numbers[left] + numbers[right];
            //指针指向元素的和比目标数大
            if(sum > target){
                right--;
            }
            //指针指向元素的和比目标数小
            else if(sum < target){
                left++;
            }
            //指针指向元素的和比目标数相等
            else{
            	//以数组形式返回下标值
                return new int[] {left+1,right+1};
            }
        }
        //如果找不到,就返回元素都是-1的数组
        return new int[] {-1,-1};
    }
}

5.验证代码

在这里插入图片描述

6.时间复杂度和空间复杂度

  • 时间复杂度:O(n)

  • 空间复杂度:O(1)

7.其它解法

1️⃣二分查找

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        for (int i = 0; i < numbers.length; ++i) {
            int low = i + 1, high = numbers.length - 1;
            while (low <= high) {
                int mid = (high - low) / 2 + low;
                if (numbers[mid] == target - numbers[i]) {
                    return new int[]{i + 1, mid + 1};
                } else if (numbers[mid] > target - numbers[i]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
        }
        return new int[]{-1, -1};
    }
}

  • 时间复杂度:O(nlogn)

  • 空间复杂度:O(1)

2️⃣暴力求解(我的第一次尝试)

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int[] result = new int[2];
        for(int index1 =0; index1 <= numbers.length-  1; index1++){
            for(int index2 = index1+1; index2 <= numbers.length - 1; index2++){
                if(numbers[index1] + numbers[index2] == target){
                    result[0] = index1 + 1;
                    result[1] = index2 + 1;
                }
            }

        }
        return result;
    }
}  

四、结语

本题的暴力解法应该是大家的第一想法,但是如何优化代码,并降低时间复杂度就需要用到算法了,本题一定要明白双指针的含义才能在下次看到题目时不会再只用暴力求解的方式去解决问题了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Alita11101_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值