日新刷题 - 2089. 找出数组排序后的目标下标

78 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

一 描述

2089. 找出数组排序后的目标下标 - 力扣(LeetCode)

给你一个下标从 0 开始的整数数组 nums 以及一个目标元素 target

目标下标 是一个满足 nums[i] == target 的下标 i

nums非递减 顺序排序后,返回由 nums 中目标下标组成的列表。如果不存在目标下标,返回一个 列表。返回的列表必须按 递增 顺序排列。

 

示例 1:

输入:nums = [1,2,5,2,3], target = 2
输出:[1,2]
解释:排序后,nums 变为 [1,2,2,3,5] 。
满足 nums[i] == 2 的下标是 1 和 2 。

示例 2:

输入:nums = [1,2,5,2,3], target = 3
输出:[3]
解释:排序后,nums 变为 [1,2,2,3,5] 。
满足 nums[i] == 3 的下标是 3 。

示例 3:

输入:nums = [1,2,5,2,3], target = 5
输出:[4]
解释:排序后,nums 变为 [1,2,2,3,5] 。
满足 nums[i] == 5 的下标是 4 。

示例 4:

输入:nums = [1,2,5,2,3], target = 4
输出:[]
解释:nums 中不含值为 4 的元素。

提示:

  • 1 <= nums.length <= 100
  • 1 <= nums[i], target <= 100

二 分析

最简单的肯定是暴力解法了

class Solution
{
public:
    vector<int> targetIndices(vector<int> &nums, int target)
    {
        vector<int> ans;
        sort(nums.begin(), nums.end());
        for (int i = 0, _ = nums.size(); i < _; ++i)
        {
            if (nums[i] == target)
                ans.push_back(i);
        }
        return ans;
    }
};

可改进的地方:

我的做法是先排序,再遍历排序后的数组来找target出现的地方。排序用时O(nlogn)O(n\log n),查找用时O(n)O(n)

优化点1: 查到已经比target大的时候就不查了

优化点2: 不采用线性查找,采用找出upper_bound和lower_bound的方法来做 采用优化点2的代码:


class Solution
{
public:
    vector<int> targetIndices(vector<int> &nums, int target)
    {
        sort(nums.begin(), nums.end());
        auto r = upper_bound(nums.begin(), nums.end(), target);
        --r;
        auto l = lower_bound(nums.begin(), nums.end(), target);
        int i = r - nums.begin();
        int j = l - nums.begin();
        vector<int> ans;
        for (int _ = j; _ <= i; ++_)
        {
            ans.push_back(_);
        }
        return ans;
    }
};

这种做法时间复杂度: 排序O(nlogn)O(n\log n),查找O(logn)O(\log n)

瓶颈在排序上,那么有没有办法比排序更快呢?

注意到:若小于target的个数为a,等于的个数为b

则答案为a,a+1,a+2,...,a+b-1a,a+1,a+2,...,a+b−1

则求出a,b即可

class Solution
{
public:
    vector<int> targetIndices(vector<int> &nums, int target)
    {
        int a{}, b{};
        for (const auto &x : nums)
        {
            a += x < target;
            b += x == target;
        }
        vector<int> ans;
        for (int _{a}; _ < a + b; ++_)
        {
            ans.push_back(_);
        }
        return ans;
    }
};