Search in Rotated Sorted Array - 循环有序数组查找问题
两道题
33. Search in Rotated Sorted Array
https://leetcode.com/problems/search-in-rotated-sorted-array/
81. Search in Rotated Sorted Array II
https://leetcode.com/problems/search-in-rotated-sorted-array-ii/
这两道题都是属于循环有序数组的查找问题,无论是查找具体元素的下标还是检查一个目标值是否在数组中,主要的判断逻辑都是一致的。
思路
这种将有序数组翻转成循环有序数组的解决办法是将原数组分段。用首元素start、中间元素mid、尾元素end,可以将数组分为两个子数组s1,s2。
则这两个子数组中,必然有至少一个子数组是有序的。
那么如何确定那一段是有序的呢,通过分析可以看到只有3种情况:
- 当start就是A中最小的元素时,以下不等式成立:start <= mid <= end
- 当最小值位于(start, mid]时,则有:mid <= end <= start
- 当最小值出现在(mid,end]时,则有:end <= start <= mid
所以通过start, mid, end的大小关系,就可以判断出s1和s2哪个是有序的。
通过比较要查找的目标target与start,mid,end的大小关系,就可以知道target位于哪个子数组。
若target位于有序的子数组,则用二分查找就可以了。否则,对无序的子数组重复刚才的过程就可以了。
代码
package com.lingyejun.dating.chap11.toutiao; public class RotatedArrayQuery { /** * 33. Search in Rotated Sorted Array * 查找目标值下标 * * @param nums * @param target * @return */ public int searchTargetIndex(int[] nums, int target) { int start = 0; int end = nums.length - 1; while (start <= end) { // (start ... middle ... end) int mid = (start + end) / 2; if (nums[mid] == target) { return mid; } // 前半段数组是有序的 if (nums[start] < nums[mid]) { // target在前半段数组中 if (target < nums[mid] && target >= nums[start]) { // 将原数组折半,取出前半段数组 end = mid - 1; } else { // target在后半段数组中 start = mid + 1; } } // 后半段数组是有序的 else if (nums[mid] < nums[end]) { // target在后半段数组中 if (target > nums[mid] && target <= nums[end]) { // 将原数组折半,取出后半段数组 start = mid + 1; } else { // target在前半段数组中 end = mid - 1; } } else { // 此种场景{1, 0, 1, 1, 1} start = mid = end start++; } } return -1; } /** * 81. Search in Rotated Sorted Array II * * 查找是否存在目标值 * * @param nums * @param target * @return */ public static boolean searchExistsKey(int nums[], int target) { int start = 0; int end = nums.length - 1; while (start <= end) { int mid = (start + end) / 2; if (nums[mid] == target) { return true; } if (nums[start] < nums[mid]) { if (nums[start] <= target && target < nums[mid]) { end = mid - 1; } else { start = mid + 1; } } else if (nums[start] > nums[mid]) { if (nums[mid] < target && target <= nums[end]) { start = mid + 1; } else { end = mid - 1; } } else { start++; } } return false; } public static void main(String[] args) { int[] array = new int[]{1, 0, 1, 1, 1}; RotatedArrayQuery caq = new RotatedArrayQuery(); System.out.println(caq.searchTargetIndex(array, 0)); System.out.println(caq.searchExistsKey(array, 1)); } }
本篇文章如有帮助到您,请给「翎野君」点个赞,感谢您的支持。
作者:翎野君
出处:http://www.cnblogs.com/lingyejun/
若本文如对您有帮助,不妨点击一下右下角的【推荐】。
如果您喜欢或希望看到更多我的文章,可扫描二维码关注我的微信公众号《翎野君》。
转载文章请务必保留出处和署名,否则保留追究法律责任的权利。
出处:http://www.cnblogs.com/lingyejun/
若本文如对您有帮助,不妨点击一下右下角的【推荐】。
如果您喜欢或希望看到更多我的文章,可扫描二维码关注我的微信公众号《翎野君》。
转载文章请务必保留出处和署名,否则保留追究法律责任的权利。