算法入门 02二分查找(简单 - 第四题)LeetCode 167

Posted 英雄哪里出来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法入门 02二分查找(简单 - 第四题)LeetCode 167相关的知识,希望对你有一定的参考价值。


一、题目

1、题目描述

  给定一个升序排列的数组长度为 n ( n ≤ 1 0 4 ) n(n \\le 10^4) n(n104) 的整数数组 n u m b e r s numbers numbers ,要求从数组中找出两个数满足相加之和等于目标数 t a r g e t target target 。返回这两个数的下标(假设下标从 1 开始,并且答案一定存在,且不能用相同元素)。
  样例: n u m b e r s = [ 2 , 5 , 11 , 19 ] numbers = [2,5,11,19] numbers=[2,5,11,19], target = 13,输出 [ 1 , 3 ] [1, 3] [1,3]

2、基础框架

  • c++ 版本给出的基础框架代码如下,输入数组参数类型是vector<int>,返回参数也是一个数组vector<int>,按照题目要求,需要返回一个长度为 2 的数组;
class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
    }
};

3、原题链接

LeetCode 167. 两数之和 II - 输入有序数组

二、解题报告

1、思路分析

  首先,我们一定可以通过两层枚举 i i i j j j ( i < j ) (i \\lt j) (i<j),然后判断 numbers[i] + numbers[j] == target是否成立,如果成立,那么 [ i + 1 , j + 1 ] [i+1, j+1] [i+1,j+1] 就是我们要求的答案了。但是这么做,时间复杂度是 O ( n 2 ) O(n^2) O(n2) 的。
  然而, 考虑到数组有序,第二层循环我们可以采用二分查找降低时间复杂度,继续考虑等式:numbers[i] + numbers[j] == target,假设第一层循环枚举后, i i i 成为已知数, j j j 成为未知数,那么,我们可以得到:numbers[j] == target - numbers[i],而且 j j j 的范围已知,于是可以通过二分查找数组 numbers,找到这个 j j j 的位置。

2、时间复杂度

  • 第一层枚举 O ( n ) O(n) O(n),第二层二分查找 O ( l o g 2 n ) O(log_2n) O(log2n),两个操作是乘的关系,所以总的时间复杂度为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)

3、代码详解

class Solution {
public:
    
    int find(vector<int>& numbers, int indexStart, int target) { // (1)
        int l = indexStart;
        int r = numbers.size() - 1;
        while(l <= r) {
            int mid = (l + r) >> 1;
            if(target == numbers[mid]) {
                return mid;
            }else if(target > numbers[mid]) {
                l = mid + 1;
            }else {
                r = mid - 1;
            }
        }
        return -1;
    }
    vector<int> twoSum(vector<int>& numbers, int target) {
        vector <int> ans;
        for(int i = 0; i < numbers.size(); ++i) {                // (2)
            int x = find(numbers, i+1, target - numbers[i]);   
            if(x != -1) {
                ans.push_back(i + 1);                            // (3)
                ans.push_back(idx + 1);
                return ans;
            }
        }
        return ans;
    }
};
  • ( 1 ) (1) (1) int find(vector<int>& numbers, int indexStart, int target)实现的是二分查找函数,查找的是从数组numbersindexStart下标开始到结尾中存在的target所在的下标,不存在则返回 -1
  • ( 2 ) (2) (2) 枚举数组numbers的每个位置i,期望找到numbers[i] + numbers[x] = target,其中 x x x 是未知数,需要我们求的,并且它满足 x > i x \\gt i x>i,由于数组有序,就可以用二分查找了,二分查找的值就是target - numbers[i]
  • ( 3 ) (3) (3) 得到的 x x x 如果不为 -1,那么 i i i x x x 就是两个满足题意的目标,又因为题目要求下标从 1 开始,所以都加上 1;
  • 关于二分查找的内容,可以参考这个题:【算法专题(01)二分查找(01) 简单】LeetCode 704

三、本题小知识

将一个本来已经实现的功能提出来,让调用方去调用,能够大大的增加代码的可读性,这就是面向函数编程;


以上是关于算法入门 02二分查找(简单 - 第四题)LeetCode 167的主要内容,如果未能解决你的问题,请参考以下文章

从零开始学算法:4.二分查找

⭐算法入门⭐《二分枚举》中等02 —— LeetCode 面试题 10.09. 排序矩阵查找

第四题:冒泡排序(Bubble Sort)

⭐算法入门⭐《二分枚举》简单06 —— LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置

算法专题(01)二分查找(02) 简单LeetCode 35

LeetCode算法第四题