[每日一题]96:两数之和

107 阅读1分钟

文章目录


题目一

描述如下:

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

方法一:暴力(会超时)

复杂度分析:

  • 时间复杂度O(n²)
  • 空间复杂度O(1)

代码实现

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> ans;
        for(int i = 0; i < nums.size(); ++i){
              for(int j = i + 1; j < nums.size(); ++j){
                  if(nums[i] + nums[j] == target){
                      ans.push_back(i);
                      ans.push_back(j);
                      return ans;
                  }
              }
        }
        return ans;
    }
};

方法二:排序+双指针法

  1. 为了保存下标信息另开了一个数组
  2. 这里先将数组排序好O(nlogn)
  3. 利用双指针法遍历一遍O(n)得到结果
  4. 再从原数组中得到对应数值的下标

复杂度分析:

  • 时间复杂度O(nlogn)
  • 空间复杂度O(n)

代码实现:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> num = nums;
        vector<int> v(2);

        int n = num.size();
        int i = 0, j = n - 1;
        sort(num.begin(), num.end());
        
        while (i < j){
            if(num[i]+num[j] < target){
                ++i;
            }
            else if((num[i]+num[j]) > target){
                --j;
            }
            else{
                break;
            }
        }
        if(i < j){
            for(int x = 0; x < nums.size(); x++){
                if(i < n && num[i] == nums[x]) {
                    v[0] = x;
                    i = n;
                }
                else if(j < n && num[j] == nums[x]) {
                    v[1] = x;
                    j = n;
                }
                if(i == n && j == n) return v;
            }
        }
        return v;
    }
};

方法三:hash法

  • 利用unordered_map数组构造映射,遍历nums[i]时,看target-nums[i]是否存在hash表中即可

复杂度分析:

  • 时间复杂度O(nlogn)
  • 空间复杂度O(n)

代码实现:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> ans;
        unordered_map<int, int> m;
        for(int i = 0; i < nums.size(); ++i){
            if(m[target-nums[i]]){
                ans.push_back(i);
                ans.push_back(m[target-nums[i]] - 1);
                return ans;
            }
            m[nums[i]] = i+1;
            //将hash表对应下标+1,防止处理下标为0的情况
        }
        return ans;
    }
};

题目二

描述如下:

给定一个已按照 升序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。

函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。

你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。

示例 1:

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

示例 2:

输入:numbers = [2,3,4], target = 6
输出:[1,3]

方法一:双指针

复杂度分析:

  • 时间复杂度:O(n),其中 n 是数组的长度。两个指针移动的总次数最多为 n 次。
  • 空间复杂度:O(1)。

代码如下:

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        vector<int> ans;
        for (int i = 0, j = numbers.size()-1; i < j;){
            if (numbers[i]+numbers[j] == target){
                ans.push_back(i+1);
                ans.push_back(j+1);
                return ans;
            }
            else if (numbers[i]+numbers[j] < target){
                ++i;
            }
            else {
                --j;
            }
        }
        return ans;
    }
};

题目二

描述如下:

给定一个二叉搜索树和一个目标结果,如果 BST 中存在两个元素且它们的和等于给定的目标结果,则返回 true。

案例 1:

输入: 
    5
   / \
  3   6
 / \   \
2   4   7

Target = 9

输出: True

方法一:排序+双指针

  1. 利用数组,先对二叉树中序遍历,形成一个有序的数组。
  2. 在数组两边同时往中间推进,看两个数加起来是否等于Target

代码实现:

class Solution {
    vector<int> v;

    void BinaryTreePrevOrder (TreeNode* root){
        if (root == nullptr) return;
        BinaryTreePrevOrder(root->left);
        v.push_back(root->val);
        BinaryTreePrevOrder(root->right);
    }
public:
    bool findTarget(TreeNode* root, int k) {
        BinaryTreePrevOrder(root);
        int i = 0, j = v.size()-1;
        while (i < j){
            if(v[i] + v[j] == k) return true;
            else if(v[i] + v[j] < k) {
                ++i;
            }
            else {
                --j;
            }                
        }
        return false;
    }
};

如有帮助到你,欢迎点赞留言鼓励哟~~