11package com .fishercoder .solutions ;
22
33/**
4+ * 81. Search in Rotated Sorted Array II
5+ *
46 * Follow up for "Search in Rotated Sorted Array":
5- What if duplicates are allowed?
6-
7- Would this affect the run-time complexity? How and why?
8-
9- Write a function to determine if a given target is in the array.
7+ * What if duplicates are allowed?
8+ * Would this affect the run-time complexity? How and why?
9+ * Write a function to determine if a given target is in the array.
1010 */
1111public class _81 {
1212
13- public boolean search (int [] A , int target ) {
14- int len = A .length ;
15- if (len == 0 ) {
16- return false ;
17- }
18- if (len == 1 ) {
19- if (A [0 ] == target ) {
20- return true ;
21- } else {
13+ public static class Solution1 {
14+ public boolean search (int [] A , int target ) {
15+ int len = A .length ;
16+ if (len == 0 ) {
2217 return false ;
2318 }
24- }
25- int watershed = A [0 ];
26- int watershedIndex = 0 ;
27- for (int i = 0 ; i < len - 1 ; i ++) {
28- if (A [i ] > A [i + 1 ]) {
29- watershed = A [i ];
30- watershedIndex = i ;
31- System .out .println ("Place 1: watershed = " + watershed
32- + "\t watershedIndex = " + watershedIndex );
33- for (int j = i + 1 ; j < len ; j ++) {
34- if (A [j ] == A [i ]) {
35- watershed = A [j ];
36- watershedIndex = j ;
37- System .out .println ("Place 2: watershed = " + watershed
38- + "\t watershedIndex = " + watershedIndex );
39- } else {
40- break ;
19+ if (len == 1 ) {
20+ if (A [0 ] == target ) {
21+ return true ;
22+ } else {
23+ return false ;
24+ }
25+ }
26+ int watershed = A [0 ];
27+ int watershedIndex = 0 ;
28+ for (int i = 0 ; i < len - 1 ; i ++) {
29+ if (A [i ] > A [i + 1 ]) {
30+ watershed = A [i ];
31+ watershedIndex = i ;
32+ System .out .println ("Place 1: watershed = " + watershed
33+ + "\t watershedIndex = " + watershedIndex );
34+ for (int j = i + 1 ; j < len ; j ++) {
35+ if (A [j ] == A [i ]) {
36+ watershed = A [j ];
37+ watershedIndex = j ;
38+ System .out .println ("Place 2: watershed = " + watershed
39+ + "\t watershedIndex = " + watershedIndex );
40+ } else {
41+ break ;
42+ }
4143 }
4244 }
4345 }
44- }
45- System .out .println ("watershed = " + watershed + "\t watershedIndex = "
46- + watershedIndex );
47- if (target == watershed ) {
48- return true ;
49- } else if (target > watershed ) {
50- /*
46+ System .out .println ("watershed = " + watershed + "\t watershedIndex = "
47+ + watershedIndex );
48+ if (target == watershed ) {
49+ return true ;
50+ } else if (target > watershed ) {
51+ /*
5152 * here is the tricky part: when target is greater than watershed,
5253 * it's also possible that this list is ZERO rotated, i.e. it didn't
5354 * rotate at all! Then at this moment, watershed is not the largest
5455 * element int this array, so we need to binary search this whole
5556 * array.
5657 */
57- if (watershedIndex == 0 ) {
58- int start = 0 ;
59- int end = len - 1 ;
60- int mid = (start + end ) / 2 ;
61- while (start <= end ) {
62- if (target > A [mid ]) {
63- start = mid + 1 ;
64- mid = (start + end ) / 2 ;
65- } else if (target < A [mid ]) {
66- end = mid - 1 ;
67- mid = (start + end ) / 2 ;
68- } else if (target == A [mid ]) {
69- return true ;
58+ if (watershedIndex == 0 ) {
59+ int start = 0 ;
60+ int end = len - 1 ;
61+ int mid = (start + end ) / 2 ;
62+ while (start <= end ) {
63+ if (target > A [mid ]) {
64+ start = mid + 1 ;
65+ mid = (start + end ) / 2 ;
66+ } else if (target < A [mid ]) {
67+ end = mid - 1 ;
68+ mid = (start + end ) / 2 ;
69+ } else if (target == A [mid ]) {
70+ return true ;
71+ }
7072 }
73+ return false ;
74+ } else {
75+ return false ;
7176 }
72- return false ;
73- } else {
74- return false ;
75- }
76- } else if (target < watershed ) {
77+ } else if (target < watershed ) {
7778 /*
7879 * target could be in either part of this sorted array, then we
7980 * check if target is greater than A[0], if so, then search in the
8081 * first part, if not, then check if it is greater than A[len - 1],
8182 * if so, return -1, if not, search in the second part
8283 */
8384
84- if (target == A [0 ]) {
85- return true ;
86- } else if (target > A [0 ]) {
87- int start = 1 ;
88- int end = watershedIndex - 1 ;
89- int mid = (start + end ) / 2 ;
90- while (start <= end ) {
91- if (target > A [mid ]) {
92- start = mid + 1 ;
93- mid = (start + end ) / 2 ;
94- } else if (target < A [mid ]) {
95- end = mid - 1 ;
96- mid = (start + end ) / 2 ;
97- } else if (target == A [mid ]) {
98- return true ;
99- }
100- }
101- return false ;
102- } else if (target < A [0 ]) {
103- if (target == A [len - 1 ]) {
85+ if (target == A [0 ]) {
10486 return true ;
105- } else if (target > A [len - 1 ]) {
106- return false ;
107- } else if (target < A [len - 1 ]) {
108- int start = watershedIndex + 1 ;
109- int end = len - 2 ;
87+ } else if (target > A [0 ]) {
88+ int start = 1 ;
89+ int end = watershedIndex - 1 ;
11090 int mid = (start + end ) / 2 ;
11191 while (start <= end ) {
11292 if (target > A [mid ]) {
@@ -120,10 +100,75 @@ public boolean search(int[] A, int target) {
120100 }
121101 }
122102 return false ;
103+ } else if (target < A [0 ]) {
104+ if (target == A [len - 1 ]) {
105+ return true ;
106+ } else if (target > A [len - 1 ]) {
107+ return false ;
108+ } else if (target < A [len - 1 ]) {
109+ int start = watershedIndex + 1 ;
110+ int end = len - 2 ;
111+ int mid = (start + end ) / 2 ;
112+ while (start <= end ) {
113+ if (target > A [mid ]) {
114+ start = mid + 1 ;
115+ mid = (start + end ) / 2 ;
116+ } else if (target < A [mid ]) {
117+ end = mid - 1 ;
118+ mid = (start + end ) / 2 ;
119+ } else if (target == A [mid ]) {
120+ return true ;
121+ }
122+ }
123+ return false ;
124+ }
123125 }
124126 }
127+ return false ;
125128 }
126- return false ;
127129 }
128130
131+ public static class Solution2 {
132+ public boolean search (int [] nums , int target ) {
133+ int start = 0 ;
134+ int end = nums .length - 1 ;
135+
136+ //check each num so we will check start == end
137+ //We always get a sorted part and a half part
138+ //we can check sorted part to decide where to go next
139+ while (start <= end ) {
140+ int mid = start + (end - start ) / 2 ;
141+ if (nums [mid ] == target ) {
142+ return true ;
143+ }
144+
145+ //if left part is sorted
146+ if (nums [start ] < nums [mid ]) {
147+ if (target < nums [start ] || target > nums [mid ]) {
148+ //target is in rotated part
149+ start = mid + 1 ;
150+ } else {
151+ end = mid - 1 ;
152+ }
153+ } else if (nums [start ] > nums [mid ]) {
154+ //right part is rotated
155+
156+ //target is in rotated part
157+ if (target < nums [mid ] || target > nums [end ]) {
158+ end = mid - 1 ;
159+ } else {
160+ start = mid + 1 ;
161+ }
162+ } else {
163+ //duplicates, we know nums[mid] != target, so nums[start] != target
164+ //based on current information, we can only move left pointer to skip one cell
165+ //thus in the worst case, we would have target: 2, and array like 11111111, then
166+ //the running time would be O(n)
167+ start ++;
168+ }
169+ }
170+
171+ return false ;
172+ }
173+ }
129174}
0 commit comments