持续创作,加速成长!这是我参与「掘金日新计划 · 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出现的地方。排序用时,查找用时
优化点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;
}
};
这种做法时间复杂度: 排序,查找
瓶颈在排序上,那么有没有办法比排序更快呢?
有
注意到:若小于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;
}
};