Skip to content

Commit 18c8bc0

Browse files
Merge branch 'master' into fix/rotated-binary-search-edge-cases
2 parents 9e94464 + ed2928f commit 18c8bc0

4 files changed

Lines changed: 36 additions & 21 deletions

File tree

‎.github/workflows/codeql.yml‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ jobs:
3030
distribution: 'temurin'
3131

3232
- name: Initialize CodeQL
33-
uses: github/codeql-action/init@v4.38.1
33+
uses: github/codeql-action/init@v4.38.2
3434
with:
3535
languages: 'java-kotlin'
3636

3737
- name: Build
3838
run: mvn --batch-mode --update-snapshots verify
3939

4040
- name: Perform CodeQL Analysis
41-
uses: github/codeql-action/analyze@v4.38.1
41+
uses: github/codeql-action/analyze@v4.38.2
4242
with:
4343
category: "/language:java-kotlin"
4444

@@ -55,12 +55,12 @@ jobs:
5555
uses: actions/checkout@v7
5656

5757
- name: Initialize CodeQL
58-
uses: github/codeql-action/init@v4.38.1
58+
uses: github/codeql-action/init@v4.38.2
5959
with:
6060
languages: 'actions'
6161

6262
- name: Perform CodeQL Analysis
63-
uses: github/codeql-action/analyze@v4.38.1
63+
uses: github/codeql-action/analyze@v4.38.2
6464
with:
6565
category: "/language:actions"
6666
...

‎pom.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
<dependency>
4343
<groupId>org.mockito</groupId>
4444
<artifactId>mockito-core</artifactId>
45-
<version>5.23.0</version>
45+
<version>5.24.0</version>
4646
<scope>test</scope>
4747
</dependency>
4848
<dependency>

‎src/main/java/com/thealgorithms/searches/HowManyTimesRotated.java‎

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@
1616
The position of the minimum element will give the number of times the array has been rotated
1717
from its initial sorted position.
1818
Eg. For [2,5,6,8,11,12,15,18], 1 rotation gives [5,6,8,11,12,15,18,2], 2 rotations
19-
[6,8,11,12,15,18,2,5] and so on. Finding the minimum element will take O(N) time but, we can use
20-
Binary Search to find the minimum element, we can reduce the complexity to O(log N). If we look
21-
at the rotated array, to identify the minimum element (say a[i]), we observe that
22-
a[i-1]>a[i]<a[i+1].
19+
[6,8,11,12,15,18,2,5] and so on. Finding the minimum element will take O(N) time but, we can use
20+
Binary Search to reduce the complexity to O(log N): at each step compare a[mid] with a[high].
21+
If a[mid] > a[high], the minimum lies to the right, so low = mid + 1; otherwise it lies at mid
22+
or to the left, so high = mid. This converges to the minimum's index without ever reading
23+
a[mid-1] or a[mid+1], so it also works on arrays of size 0-2 and unrotated arrays.
2324
2425
Some other test cases:
2526
1. [1,2,3,4] Number of rotations: 0 or 4(Both valid)
26-
2. [15,17,2,3,5] Number of rotations: 3
27+
2. [15,17,2,3,5] Number of rotations: 2
2728
*/
2829
final class HowManyTimesRotated {
2930
private HowManyTimesRotated() {
@@ -44,20 +45,16 @@ public static void main(String[] args) {
4445
public static int rotated(int[] a) {
4546
int low = 0;
4647
int high = a.length - 1;
47-
int mid = 0; // low + (high-low)/2 = (low + high)/2
4848

49-
while (low <= high) {
50-
mid = low + (high - low) / 2;
51-
52-
if (a[mid] < a[mid - 1] && a[mid] < a[mid + 1]) {
53-
break;
54-
} else if (a[mid] > a[mid - 1] && a[mid] < a[mid + 1]) {
55-
high = mid + 1;
56-
} else if (a[mid] > a[mid - 1] && a[mid] > a[mid + 1]) {
57-
low = mid - 1;
49+
while (low < high) {
50+
int mid = low + (high - low) / 2;
51+
if (a[mid] > a[high]) {
52+
low = mid + 1;
53+
} else {
54+
high = mid;
5855
}
5956
}
6057

61-
return mid;
58+
return low;
6259
}
6360
}

‎src/test/java/com/thealgorithms/searches/HowManyTimesRotatedTest.java‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import static org.junit.jupiter.api.Assertions.assertEquals;
44

5+
import java.util.concurrent.TimeUnit;
56
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.api.Timeout;
68

79
public class HowManyTimesRotatedTest {
810

@@ -13,4 +15,20 @@ public void testHowManyTimesRotated() {
1315
int[] arr2 = {15, 17, 2, 3, 5};
1416
assertEquals(2, HowManyTimesRotated.rotated(arr2));
1517
}
18+
19+
/** An unrotated (already sorted) array should resolve to 0 rotations without hanging. */
20+
@Test
21+
@Timeout(value = 5, unit = TimeUnit.SECONDS, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
22+
public void testHowManyTimesRotatedOnUnrotatedArray() {
23+
int[] arr = {2, 5, 6, 8, 11, 12, 15, 18};
24+
assertEquals(0, HowManyTimesRotated.rotated(arr));
25+
}
26+
27+
/** Arrays of size 1 and 2 should not throw ArrayIndexOutOfBoundsException. */
28+
@Test
29+
public void testHowManyTimesRotatedOnSmallArrays() {
30+
assertEquals(0, HowManyTimesRotated.rotated(new int[] {5}));
31+
assertEquals(0, HowManyTimesRotated.rotated(new int[] {1, 2}));
32+
assertEquals(1, HowManyTimesRotated.rotated(new int[] {2, 1}));
33+
}
1634
}

0 commit comments

Comments
 (0)