There are several topics related to “Searching for a value in a rotated sorted array” in LeetCode. This is an extension of the topic related to “Finding the minimum value in a rotated sorted array”.
The core idea of solving the problem is: binary search.
The first questionSearch rotation sort array
Key words:
- Sorted in ascending order
- Different elements
- Return -1 if not found
In the code, I still consider repeating elements. First, there is no additional burden on running the code. Secondly, the solution of this problem and the solution of the next problem are unified.
Please refer to the comments for details. The reader should think more about the examples in the notes and exclude some sections by contradiction.
To sum up. There are four possibilities for analyzing an interval:
- The left element of the interval is less than the right element
- The left element of the interval is larger than the middle element
- The middle element is larger than the right element
- The left, middle, and right elements of the interval are equal
Take full advantage of what we know, narrow the search area as much as possible.
The solution is as follows (code submission approved)
func search(nums []int, target int) int {
l := len(nums)
if l == 0 {
return - 1
}
if l == 1 {
if nums[0] == target {
return 0
}
return - 1
}
var (
low int
high = l- 1
)
OuterLoop:
for low <= high {
// Middle position
mid := low + (high-low)>>1
v := nums[mid]
/ / found
if v == target {
return mid
}
// The left end of the interval is smaller than the right end of the element.
/ / as /..., 1, 2, 3, 4, 5,...
if nums[low] < nums[high] {
if v < target {
low = mid+1
} else {
high = mid- 1
}
continue
}
[...,5,6,7,1,2,3,4,...] , 5 > 1.
if nums[low] > v {
// Target may exist in index range (mid,high)
if target < nums[low] && v < target {
low = mid+1
} else { // Target may exist in index range [low, mid]
high = mid- 1
}
continue
}
// the middle element of the interval is larger than the right element, such as [...,2,3,4,5,6,7,1...]
if v > nums[high] {
// Target may exist in index range [low,mid]
if target < v && nums[high] < target {
high = mid- 1
} else { // Target may exist in index range (mid, high)
low = mid+1
}
continue
}
Nums [mid] == nums[high]
for i := low; i < high; i++ {
// A different value is encountered
// It could be one of the following
/ / /..., 9,5,6,9,9,9,9,9,9,...
/ / /..., 9,9,9,9,9,9,5,6,9,...
/ / /..., 9,10,11,9,9,9,9,9,9,...
/ / /..., 9,9,9,9,9,9,10,11,9,...
/ / /..., 9,10,2,9,9,9,9,9,9,...
/ / /..., 9,9,9,9,9,9,11,2,9,...
ifnums[i] ! = nums[i+1] {
low = i+1
if i+1 < mid {
// Index interval [low, I] and [mid,high] are equal, and not equal to target.
// just continue searching in index interval [I +1, mid-1].
high = mid- 1
} else { // I +1 > mid. I +1 == mid
// Index range [low, I] and index high are equal, and not equal to target.
// Just continue searching in index interval [I +1, high-1].
high--
}
continue OuterLoop
}
}
// The elements in the for loop above are all equal
/ / not found
break
}
return - 1
}
Copy the code
The second questionSearch rotated sorted array II
Key words:
- In non-descending order
- Element values need not be different
- Returns true if found, false otherwise
This is definitely going to be a case of repeating elements. In this code, the logic is the same except that the return value is different, because the solution already takes into account repeating elements.
The solution is as follows (code submission approved)
func search(nums []int, target int) bool {
l := len(nums)
if l == 0 {
return false
}
var (
low int
high = l- 1
)
OuterLoop:
for low <= high {
mid := low + (high-low)>>1
v := nums[mid]
if v == target {
return true
}
if nums[low] < nums[high] {
if v < target {
low = mid+1
} else {
high = mid- 1
}
continue
}
if nums[low] > v {
if target < nums[low] && v < target {
low = mid+1
} else {
high = mid- 1
}
continue
}
if v > nums[high] {
if target < v && nums[high] < target {
high = mid- 1
} else {
low = mid+1
}
continue
}
for i := low; i < high; i++ {
ifnums[i] ! = nums[i+1] {
low = i+1
if i+1 < mid {
high = mid- 1
} else { // I +1 > mid. I +1 == mid
high--
}
continue OuterLoop
}
}
break
}
return false
}
Copy the code
The third questionSearch rotation array
Key words:
- Sorted in ascending order
- There are duplicate elements
- To return the index. If there are multiple elements of the same type, the smallest index is returned. There is one more implicit detail, which returns -1 if not found.
The logic is similar to the first problem. I just made some adjustments for that problem.
The solution is as follows (code submission approved)
func search(arr []int, target int) int {
l := len(arr)
if l == 0 {
return - 1
}
var (
low int
high = l- 1
k = - 1
)
OuterLoop:
for low <= high {
mid := low + (high-low)>>1
v := arr[mid]
if v == target {
k = mid // Record the target index
}
if arr[low] < arr[high] {
// when v == target, try to find a smaller index
if v >= target {
high = mid- 1
} else { // v < target
low = mid+1
}
continue
}
if arr[low] > v {
if target < arr[low] && v < target {
low = mid+1
} else {
high = mid- 1
}
continue
}
if v > arr[high] {
if target < v && arr[high] < target {
high = mid- 1
} else {
low = mid+1
}
continue
}
if arr[low] == target {
// Low is the minimum index
k = low
break
}
for i := low; i < high; i++ {
ifarr[i] ! = arr[i+1] {
low = i+1
if i+1 < mid {
high = mid- 1
} else { // I +1 > mid. There is no I +1 == mid
high--
}
continue OuterLoop
}
}
// There is no need to look again
break
}
return k
}
Copy the code