UPDATED:
public static void main(String[] args) {
int[] data = {21, 34, 12, 88, 54, 73, 99, 100};
List<Integer> dataList = Arrays.stream(data).boxed().collect(Collectors.toList());
System.out.println(searchRange(0, 2, 20, 50, data));
System.out.println(searchRange(2, 3, 20, 80, data));
System.out.println(searchRange(0, 2, 20, 22, data));
public static boolean searchRange(int from, int to, int min, int max, int[] data) {
// slice array
data = Arrays.copyOfRange(data, from, to + 1);
Arrays.sort(data);
// System.out.println(Arrays.toString(data));
int index = findInBoundaries(data, min, max);
// System.out.println(index);
return index != -1;
}
// return -1: no elements found.
static int findInBoundaries(int[] data, int min, int max) {
int start = 0;
int end = data.length - 1;
int ans = -1;
while (start <= end) {
int mid = (start + end) / 2;
// Break if found
if (data[mid] >= min && data[mid] <= max) {
ans = mid;
break;
}
// Right move if element <= max
else if (data[mid] <= max) {
start = mid + 1;
}
// Left move
else {
end = mid - 1;
}
}
return ans;
}
Output
true
false
true
This code has been tested for more times. Unlike my first answer to hit the min and max boundaries independently, this is finding the range for the target element to determine if the subarray contains the eligible numbers.
Explanation:
To simplify the question, I define it as if any numbers of subarray is in the given range and the method should be in time complexity less than O(n^2).
Once the array is sorted, it is easy to do it in binary search. The solution starts from the middle element (int mid = (start + end) / 2) to search a number within the given range. When the element meets the range requirement, the loop terminates. If it is smaller than (or smaller than and equals to) the max value, it will search the right (larger) element, otherwise, it will search the left (smaller) element. In this case, the maximum loop times will be O(log n) where n is the size of the array.
Example:
I modified to compare the solution with normal looping by adding counters. In some cases, normal looping needs to loop through the whole array.
The sorting for normal solution is not very important so I don't do it.
// return -1: no elements found.
static void findBoundaryCompareMethods(int[] data, int min, int max) {
int start = 0;
int end = data.length - 1;
int ans = -1;
int count = 0;
while (start <= end) {
int mid = (start + end) / 2;
count++;
// Right move to find element > max
if (data[mid] >= min && data[mid] <= max) {
ans = mid;
break;
}
else if (data[mid] <= max) {
start = mid + 1;
}
// Left move
else {
end = mid - 1;
}
}
System.out.println("Method 1 Find: " + ans);
System.out.println("Method 1 Count: " + count);
ans = -1;
count = 0;
for (int i = 0; i < data.length; i++) {
count++;
if (data[i] >= min && data[i] <= max) {
ans = i;
break;
}
}
System.out.println("Method 2 Find: " + ans);
System.out.println("Method 2 Count: " + count);
}
The testing output is below. Method 1 is the answer solution and Method 2 is normal solution.
Output
Array: [12, 21, 34]
Min: 20 Max: 50
Method 1 Find: 1
Method 1 Count: 1
Method 2 Find: 1
Method 2 Count: 2
Array: [12, 88]
Min: 20 Max: 80
Method 1 Find: -1
Method 1 Count: 2
Method 2 Find: -1
Method 2 Count: 2
Array: [12, 21, 34]
Min: 20 Max: 22
Method 1 Find: 1
Method 1 Count: 1
Method 2 Find: 1
Method 2 Count: 2
Array: [12, 21, 34, 54, 73, 88, 99, 100]
Min: 70 Max: 73
Method 1 Find: 4
Method 1 Count: 3
Method 2 Find: 4
Method 2 Count: 5