马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
题目配景
已知存在一个按非降序排列的整数数组 n u m s nums nums,数组中的值不必互不相同。
在通报给函数之前, n u m s nums nums 在预先未知的某个下标 k ( 0 < = k < n u m s . l e n g t h ) k\ (0 <= k < nums.length) k (0<=k<nums.length) 上进行了 旋转 ,使数组变为 [ n u m s [ k ] , n u m s [ k + 1 ] , . . . , n u m s [ n − 1 ] , n u m s [ 0 ] , n u m s [ 1 ] , . . . , n u m s [ k − 1 ] ] [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]] [nums[k],nums[k+1],...,nums[n−1],nums[0],nums[1],...,nums[k−1]](下标 从 0 0 0 开始 计数)。例如, [ 0 , 1 , 2 , 4 , 4 , 4 , 5 , 6 , 6 , 7 ] [0,1,2,4,4,4,5,6,6,7] [0,1,2,4,4,4,5,6,6,7] 在下标 5 5 5 处经旋转后可能变为 [ 4 , 5 , 6 , 6 , 7 , 0 , 1 , 2 , 4 , 4 ] [4,5,6,6,7,0,1,2,4,4] [4,5,6,6,7,0,1,2,4,4]。
给你 旋转后 的数组 n u m s nums nums 和一个整数 t a r g e t target target,请你编写一个函数来判定给定的目标值是否存在于数组中。假如 n u m s nums nums 中存在这个目标值 t a r g e t target target,则返回 t r u e true true,否则返回 f a l s e false false。
你必须尽可能淘汰整个操纵步骤。
数据约束
- 1 ≤ n u m s . l e n g t h ≤ 5000 1 \le nums.length \le 5000 1≤nums.length≤5000
- − 1 0 4 ≤ n u m s [ i ] ≤ 1 0 4 -10 ^ 4 \le nums \le 10 ^ 4 −104≤nums≤104
- 标题数据保证 n u m s nums nums 在预先未知的某个下标上进行了旋转
- − 1 0 4 ≤ t a r g e t ≤ 1 0 4 -10 ^ 4 \le target \le 10 ^ 4 −104≤target≤104
解题过程
这题是在 搜索旋转排序数组 的基础上增加了元素可重复这个条件,仍旧可以参考无重复元素的实现,先找到最小值,再到相应的部分数组中去找结果。
然而之前的二分答案法是每次与数组的末了一个元素比较大小,假如碰到当前元素与数组中末了一个元素重复的情况,就没有办法确定要往谁人方向继续实行了。
考虑到假如有重复元素出现上述情况,它们会在旋转之后分布在数组两头。
这时候可以反复比较范围左界限的元素和数组中末了一个元素,发现重复时就将范围中的首个元素去掉。
可能会出现两种情况,去掉的这个是要查找的目标,那它还有一个重复值在数组末尾,不影响结果;去掉的这个不是要查找的目标,那就无所谓了,也不影响结果。
这道题属于是经典的为了考知识点而一味地加限定,评价为出题把脑子出坏了。
道理很简单,去掉重复元素使得范围上可用二分查找这个过程,时间复杂度是 O ( N ) O(N) O(N) 这个量级的。
这就导致了,整个算法是无法达到 O ( l o g N ) O(logN) O(logN) 这样的程度了。
既然云云,还费劲巴拉的二分什么二分,直接遍历数组同样也只是必要 O ( N ) O(N) O(N) 的时间。
具体实现
二分查找
- class Solution {
- public boolean search(int[] nums, int target) {
- int n = nums.length;
- int left = 0, right = n - 1;
- // 去掉二分范围内首尾的重复元素,注意 left != n - 1 这个条件,别把所有元素都去掉了
- while (left != n - 1 && nums[left] == nums[n - 1]) {
- left++;
- }
- // Leetcode 33.搜索旋转排序数组
- int minIndex = findMin(nums, left, right);
- if (target > nums[n - 1]) {
- return binarySearch(nums, target, 0, minIndex);
- }
- return binarySearch(nums, target, minIndex, n);
- }
- // Leetcode 153.找到数组中的最小值
- private int findMin(int[] nums, int left, int right) {
- int n = nums.length;
- while(left < right) {
- int mid = left + ((right - left) >> 1);
- if (nums[mid] > nums[n - 1]) {
- left = mid + 1;
- } else {
- right = mid;
- }
- }
- return left;
- }
- // Leetcode 35.搜索插入位置
- private boolean binarySearch(int[] nums, int target, int left, int right) {
- while (left < right) {
- int mid = left + ((right - left) >> 1);
- if (nums[mid] < target) {
- left = mid + 1;
- } else {
- right = mid;
- }
- }
- return nums[left] == target;
- }
- }
复制代码 直接遍历
- class Solution {
- public boolean search(int[] nums, int target) {
- for (int num : nums) {
- if (num == target) {
- return true;
- }
- }
- return false;
- }
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |