mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-23 04:20:16 +08:00
Change project structure to a Maven Java project + Refactor (#2816)
This commit is contained in:

committed by
GitHub

parent
8e533d2617
commit
9fb3364ccc
94
src/main/java/com/thealgorithms/searches/BinarySearch.java
Normal file
94
src/main/java/com/thealgorithms/searches/BinarySearch.java
Normal file
@ -0,0 +1,94 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.stream.IntStream;
|
||||
import com.thealgorithms.devutils.searches.SearchAlgorithm;
|
||||
|
||||
/**
|
||||
* Binary search is one of the most popular algorithms The algorithm finds the
|
||||
* position of a target value within a sorted array
|
||||
*
|
||||
* <p>
|
||||
* Worst-case performance O(log n) Best-case performance O(1) Average
|
||||
* performance O(log n) Worst-case space complexity O(1)
|
||||
*
|
||||
* @author Varun Upadhyay (https://github.com/varunu28)
|
||||
* @author Podshivalov Nikita (https://github.com/nikitap492)
|
||||
* @see SearchAlgorithm
|
||||
* @see IterativeBinarySearch
|
||||
*/
|
||||
class BinarySearch implements SearchAlgorithm {
|
||||
|
||||
/**
|
||||
* @param array is an array where the element should be found
|
||||
* @param key is an element which should be found
|
||||
* @param <T> is any comparable type
|
||||
* @return index of the element
|
||||
*/
|
||||
@Override
|
||||
public <T extends Comparable<T>> int find(T[] array, T key) {
|
||||
return search(array, key, 0, array.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method implements the Generic Binary Search
|
||||
*
|
||||
* @param array The array to make the binary search
|
||||
* @param key The number you are looking for
|
||||
* @param left The lower bound
|
||||
* @param right The upper bound
|
||||
* @return the location of the key
|
||||
*/
|
||||
private <T extends Comparable<T>> int search(T array[], T key, int left, int right) {
|
||||
if (right < left) {
|
||||
return -1; // this means that the key not found
|
||||
}
|
||||
// find median
|
||||
int median = (left + right) >>> 1;
|
||||
int comp = key.compareTo(array[median]);
|
||||
|
||||
if (comp == 0) {
|
||||
return median;
|
||||
} else if (comp < 0) {
|
||||
return search(array, key, left, median - 1);
|
||||
} else {
|
||||
return search(array, key, median + 1, right);
|
||||
}
|
||||
}
|
||||
|
||||
// Driver Program
|
||||
public static void main(String[] args) {
|
||||
// Just generate data
|
||||
Random r = ThreadLocalRandom.current();
|
||||
|
||||
int size = 100;
|
||||
int maxElement = 100000;
|
||||
|
||||
Integer[] integers
|
||||
= IntStream.generate(() -> r.nextInt(maxElement))
|
||||
.limit(size)
|
||||
.sorted()
|
||||
.boxed()
|
||||
.toArray(Integer[]::new);
|
||||
|
||||
// The element that should be found
|
||||
int shouldBeFound = integers[r.nextInt(size - 1)];
|
||||
|
||||
BinarySearch search = new BinarySearch();
|
||||
int atIndex = search.find(integers, shouldBeFound);
|
||||
|
||||
System.out.println(
|
||||
format(
|
||||
"Should be found: %d. Found %d at index %d. An array length %d",
|
||||
shouldBeFound, integers[atIndex], atIndex, size));
|
||||
|
||||
int toCheck = Arrays.binarySearch(integers, shouldBeFound);
|
||||
System.out.println(
|
||||
format(
|
||||
"Found by system method at an index: %d. Is equal: %b", toCheck, toCheck == atIndex));
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import com.thealgorithms.searches.DepthFirstSearch.Node;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author: caos321
|
||||
* @date: 31 October 2021 (Sunday)
|
||||
*/
|
||||
public class BreadthFirstSearch {
|
||||
|
||||
public static Optional<Node> search(final Node node, final String name) {
|
||||
if (node.getName().equals(name)) {
|
||||
return Optional.of(node);
|
||||
}
|
||||
|
||||
List<Node> queue = new ArrayList<>(node.getSubNodes());
|
||||
|
||||
while (!queue.isEmpty()) {
|
||||
final Node current = queue.get(0);
|
||||
|
||||
if (current.getName().equals(name)) {
|
||||
return Optional.of(current);
|
||||
}
|
||||
|
||||
queue.addAll(current.getSubNodes());
|
||||
|
||||
queue.remove(0);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public static void assertThat(final Object actual, final Object expected) {
|
||||
if (!Objects.equals(actual, expected)) {
|
||||
throw new AssertionError(String.format("expected=%s but was actual=%s", expected, actual));
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(final String[] args) {
|
||||
final Node rootNode = new Node("A", List.of(
|
||||
new Node("B", List.of(new Node("D"), new Node("F", List.of(
|
||||
new Node("H"), new Node("I")
|
||||
)))),
|
||||
new Node("C", List.of(new Node("G"))),
|
||||
new Node("E")
|
||||
));
|
||||
|
||||
{
|
||||
final String expected = "I";
|
||||
|
||||
final Node result = search(rootNode, expected)
|
||||
.orElseThrow(() -> new AssertionError("Node not found!"));
|
||||
|
||||
assertThat(result.getName(), expected);
|
||||
}
|
||||
|
||||
{
|
||||
final String expected = "G";
|
||||
|
||||
final Node result = search(rootNode, expected)
|
||||
.orElseThrow(() -> new AssertionError("Node not found!"));
|
||||
|
||||
assertThat(result.getName(), expected);
|
||||
}
|
||||
|
||||
{
|
||||
final String expected = "E";
|
||||
|
||||
final Node result = search(rootNode, expected)
|
||||
.orElseThrow(() -> new AssertionError("Node not found!"));
|
||||
|
||||
assertThat(result.getName(), expected);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author: caos321
|
||||
* @date: 31 October 2021 (Sunday)
|
||||
*/
|
||||
public class DepthFirstSearch {
|
||||
|
||||
static class Node {
|
||||
|
||||
private final String name;
|
||||
private final List<Node> subNodes;
|
||||
|
||||
public Node(final String name) {
|
||||
this.name = name;
|
||||
this.subNodes = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Node(final String name, final List<Node> subNodes) {
|
||||
this.name = name;
|
||||
this.subNodes = subNodes;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<Node> getSubNodes() {
|
||||
return subNodes;
|
||||
}
|
||||
}
|
||||
|
||||
public static Optional<Node> search(final Node node, final String name) {
|
||||
if (node.getName().equals(name)) {
|
||||
return Optional.of(node);
|
||||
}
|
||||
|
||||
return node.getSubNodes()
|
||||
.stream()
|
||||
.map(value -> search(value, name))
|
||||
.flatMap(Optional::stream)
|
||||
.findAny();
|
||||
}
|
||||
|
||||
public static void assertThat(final Object actual, final Object expected) {
|
||||
if (!Objects.equals(actual, expected)) {
|
||||
throw new AssertionError(String.format("expected=%s but was actual=%s", expected, actual));
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(final String[] args) {
|
||||
final Node rootNode = new Node("A", List.of(
|
||||
new Node("B", List.of(new Node("D"), new Node("F", List.of(
|
||||
new Node("H"), new Node("I")
|
||||
)))),
|
||||
new Node("C", List.of(new Node("G"))),
|
||||
new Node("E")
|
||||
));
|
||||
|
||||
{
|
||||
final String expected = "I";
|
||||
|
||||
final Node result = search(rootNode, expected)
|
||||
.orElseThrow(() -> new AssertionError("Node not found!"));
|
||||
|
||||
assertThat(result.getName(), expected);
|
||||
}
|
||||
|
||||
{
|
||||
final String expected = "G";
|
||||
|
||||
final Node result = search(rootNode, expected)
|
||||
.orElseThrow(() -> new AssertionError("Node not found!"));
|
||||
|
||||
assertThat(result.getName(), expected);
|
||||
}
|
||||
|
||||
{
|
||||
final String expected = "E";
|
||||
|
||||
final Node result = search(rootNode, expected)
|
||||
.orElseThrow(() -> new AssertionError("Node not found!"));
|
||||
|
||||
assertThat(result.getName(), expected);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.stream.IntStream;
|
||||
import com.thealgorithms.devutils.searches.SearchAlgorithm;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
class ExponentialSearch implements SearchAlgorithm {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Random r = ThreadLocalRandom.current();
|
||||
|
||||
int size = 100;
|
||||
int maxElement = 100000;
|
||||
|
||||
Integer[] integers
|
||||
= IntStream.generate(() -> r.nextInt(maxElement))
|
||||
.limit(size)
|
||||
.sorted()
|
||||
.boxed()
|
||||
.toArray(Integer[]::new);
|
||||
|
||||
// The element that should be found
|
||||
int shouldBeFound = integers[r.nextInt(size - 1)];
|
||||
|
||||
ExponentialSearch search = new ExponentialSearch();
|
||||
int atIndex = search.find(integers, shouldBeFound);
|
||||
|
||||
System.out.println(
|
||||
format(
|
||||
"Should be found: %d. Found %d at index %d. An array length %d",
|
||||
shouldBeFound, integers[atIndex], atIndex, size));
|
||||
|
||||
int toCheck = Arrays.binarySearch(integers, shouldBeFound);
|
||||
System.out.println(
|
||||
format(
|
||||
"Found by system method at an index: %d. Is equal: %b", toCheck, toCheck == atIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Comparable<T>> int find(T[] array, T key) {
|
||||
if (array[0] == key) {
|
||||
return 0;
|
||||
}
|
||||
if (array[array.length - 1] == key) {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
int range = 1;
|
||||
|
||||
while (range < array.length && array[range].compareTo(key) <= -1) {
|
||||
range = range * 2;
|
||||
}
|
||||
|
||||
return Arrays.binarySearch(array, range / 2, Math.min(range, array.length), key);
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import com.thealgorithms.devutils.searches.SearchAlgorithm;
|
||||
|
||||
/*
|
||||
* Fibonacci Search is a popular algorithm which finds the position of a target value in
|
||||
* a sorted array
|
||||
*
|
||||
* The time complexity for this search algorithm is O(log3(n))
|
||||
* The space complexity for this search algorithm is O(1)
|
||||
* @author Kanakalatha Vemuru (https://github.com/KanakalathaVemuru)
|
||||
*/
|
||||
public class FibonacciSearch implements SearchAlgorithm {
|
||||
|
||||
/**
|
||||
* @param array is a sorted array where the element has to be searched
|
||||
* @param key is an element whose position has to be found
|
||||
* @param <T> is any comparable type
|
||||
* @return index of the element
|
||||
*/
|
||||
@Override
|
||||
public <T extends Comparable<T>> int find(T[] array, T key) {
|
||||
int fibMinus1 = 1;
|
||||
int fibMinus2 = 0;
|
||||
int fibNumber = fibMinus1 + fibMinus2;
|
||||
int n = array.length;
|
||||
|
||||
while (fibNumber < n) {
|
||||
fibMinus2 = fibMinus1;
|
||||
fibMinus1 = fibNumber;
|
||||
fibNumber = fibMinus2 + fibMinus1;
|
||||
}
|
||||
|
||||
int offset = -1;
|
||||
|
||||
while (fibNumber > 1) {
|
||||
int i = Math.min(offset + fibMinus2, n - 1);
|
||||
|
||||
if (array[i].compareTo(key) < 0) {
|
||||
fibNumber = fibMinus1;
|
||||
fibMinus1 = fibMinus2;
|
||||
fibMinus2 = fibNumber - fibMinus1;
|
||||
offset = i;
|
||||
} else if (array[i].compareTo(key) > 0) {
|
||||
fibNumber = fibMinus2;
|
||||
fibMinus1 = fibMinus1 - fibMinus2;
|
||||
fibMinus2 = fibNumber - fibMinus1;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (fibMinus1 == 1 && array[offset + 1] == key) {
|
||||
return offset + 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Driver Program
|
||||
public static void main(String[] args) {
|
||||
Integer[] integers = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512};
|
||||
|
||||
int size = integers.length;
|
||||
Integer shouldBeFound = 128;
|
||||
FibonacciSearch fsearch = new FibonacciSearch();
|
||||
int atIndex = fsearch.find(integers, shouldBeFound);
|
||||
|
||||
System.out.println(
|
||||
"Should be found: " + shouldBeFound + ". Found " + integers[atIndex] + " at index " + atIndex + ". An array length " + size);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/*
|
||||
Problem Statement:
|
||||
Given an array, find out how many times it has to been rotated
|
||||
from its initial sorted position.
|
||||
Input-Output:
|
||||
Eg. [11,12,15,18,2,5,6,8]
|
||||
It has been rotated: 4 times
|
||||
(One rotation means putting the first element to the end)
|
||||
Note: The array cannot contain duplicates
|
||||
|
||||
Logic:
|
||||
The position of the minimum element will give the number of times the array has been rotated
|
||||
from its initial sorted position.
|
||||
Eg. For [2,5,6,8,11,12,15,18], 1 rotation gives [5,6,8,11,12,15,18,2], 2 rotations [6,8,11,12,15,18,2,5] and so on.
|
||||
Finding the minimum element will take O(N) time but, we can use Binary Search to find the mimimum element, we can reduce the complexity to O(log N).
|
||||
If we look at the rotated array, to identify the minimum element (say a[i]), we observe that a[i-1]>a[i]<a[i+1].
|
||||
|
||||
Some other test cases:
|
||||
1. [1,2,3,4] Number of rotations: 0 or 4(Both valid)
|
||||
2. [15,17,2,3,5] Number of rotations: 3
|
||||
*/
|
||||
class HowManyTimesRotated {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Scanner sc = new Scanner(System.in);
|
||||
int n = sc.nextInt();
|
||||
int[] a = new int[n];
|
||||
for (int i = 0; i < n; i++) {
|
||||
a[i] = sc.nextInt();
|
||||
}
|
||||
|
||||
System.out.println("The array has been rotated " + rotated(a) + " times");
|
||||
sc.close();
|
||||
|
||||
}
|
||||
|
||||
public static int rotated(int[] a) {
|
||||
int low = 0;
|
||||
int high = a.length - 1;
|
||||
int mid = 0; // low + (high-low)/2 = (low + high)/2
|
||||
|
||||
while (low <= high) {
|
||||
mid = low + (high - low) / 2;
|
||||
|
||||
if (a[mid] < a[mid - 1] && a[mid] < a[mid + 1]) {
|
||||
break;
|
||||
} else if (a[mid] > a[mid - 1] && a[mid] < a[mid + 1]) {
|
||||
high = mid + 1;
|
||||
} else if (a[mid] > a[mid - 1] && a[mid] > a[mid + 1]) {
|
||||
low = mid - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return mid;
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* Interpolation search algorithm implementation
|
||||
*
|
||||
* <p>
|
||||
* Worst-case performance O(n) Best-case performance O(1) Average performance
|
||||
* O(log(log(n))) if the elements are uniformly distributed if not O(n)
|
||||
* Worst-case space complexity O(1)
|
||||
*
|
||||
* @author Podshivalov Nikita (https://github.com/nikitap492)
|
||||
*/
|
||||
class InterpolationSearch {
|
||||
|
||||
/**
|
||||
* @param array is a sorted array
|
||||
* @param key is a value what shoulb be found in the array
|
||||
* @return an index if the array contains the key unless -1
|
||||
*/
|
||||
public int find(int array[], int key) {
|
||||
// Find indexes of two corners
|
||||
int start = 0, end = (array.length - 1);
|
||||
|
||||
// Since array is sorted, an element present
|
||||
// in array must be in range defined by corner
|
||||
while (start <= end && key >= array[start] && key <= array[end]) {
|
||||
// Probing the position with keeping
|
||||
// uniform distribution in mind.
|
||||
int pos = start + (((end - start) / (array[end] - array[start])) * (key - array[start]));
|
||||
|
||||
// Condition of target found
|
||||
if (array[pos] == key) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
// If key is larger, key is in upper part
|
||||
if (array[pos] < key) {
|
||||
start = pos + 1;
|
||||
} // If key is smaller, x is in lower part
|
||||
else {
|
||||
end = pos - 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Driver method
|
||||
public static void main(String[] args) {
|
||||
Random r = new Random();
|
||||
int size = 100;
|
||||
int maxElement = 100000;
|
||||
int[] integers = IntStream.generate(() -> r.nextInt(maxElement)).limit(size).sorted().toArray();
|
||||
|
||||
// the element that should be found
|
||||
Integer shouldBeFound = integers[r.nextInt(size - 1)];
|
||||
|
||||
InterpolationSearch search = new InterpolationSearch();
|
||||
int atIndex = search.find(integers, shouldBeFound);
|
||||
|
||||
System.out.println(
|
||||
String.format(
|
||||
"Should be found: %d. Found %d at index %d. An array length %d",
|
||||
shouldBeFound, integers[atIndex], atIndex, size));
|
||||
|
||||
int toCheck = Arrays.binarySearch(integers, shouldBeFound);
|
||||
System.out.println(
|
||||
format(
|
||||
"Found by system method at an index: %d. Is equal: %b", toCheck, toCheck == atIndex));
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Stream;
|
||||
import com.thealgorithms.devutils.searches.SearchAlgorithm;
|
||||
|
||||
/**
|
||||
* Binary search is one of the most popular algorithms This class represents
|
||||
* iterative version {@link BinarySearch} Iterative binary search is likely to
|
||||
* have lower constant factors because it doesn't involve the overhead of
|
||||
* manipulating the call stack. But in java the recursive version can be
|
||||
* optimized by the compiler to this version.
|
||||
*
|
||||
* <p>
|
||||
* Worst-case performance O(log n) Best-case performance O(1) Average
|
||||
* performance O(log n) Worst-case space complexity O(1)
|
||||
*
|
||||
* @author Gabriele La Greca : https://github.com/thegabriele97
|
||||
* @author Podshivalov Nikita (https://github.com/nikitap492)
|
||||
* @see SearchAlgorithm
|
||||
* @see BinarySearch
|
||||
*/
|
||||
public final class IterativeBinarySearch implements SearchAlgorithm {
|
||||
|
||||
/**
|
||||
* This method implements an iterative version of binary search algorithm
|
||||
*
|
||||
* @param array a sorted array
|
||||
* @param key the key to search in array
|
||||
* @return the index of key in the array or -1 if not found
|
||||
*/
|
||||
@Override
|
||||
public <T extends Comparable<T>> int find(T[] array, T key) {
|
||||
int l, r, k, cmp;
|
||||
|
||||
l = 0;
|
||||
r = array.length - 1;
|
||||
|
||||
while (l <= r) {
|
||||
k = (l + r) >>> 1;
|
||||
cmp = key.compareTo(array[k]);
|
||||
|
||||
if (cmp == 0) {
|
||||
return k;
|
||||
} else if (cmp < 0) {
|
||||
r = --k;
|
||||
} else {
|
||||
l = ++k;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Only a main method for test purpose
|
||||
public static void main(String[] args) {
|
||||
Random r = new Random();
|
||||
int size = 100;
|
||||
int maxElement = 100000;
|
||||
Integer[] integers
|
||||
= Stream.generate(() -> r.nextInt(maxElement)).limit(size).sorted().toArray(Integer[]::new);
|
||||
|
||||
// the element that should be found
|
||||
Integer shouldBeFound = integers[r.nextInt(size - 1)];
|
||||
|
||||
IterativeBinarySearch search = new IterativeBinarySearch();
|
||||
int atIndex = search.find(integers, shouldBeFound);
|
||||
|
||||
System.out.println(
|
||||
String.format(
|
||||
"Should be found: %d. Found %d at index %d. An array length %d",
|
||||
shouldBeFound, integers[atIndex], atIndex, size));
|
||||
|
||||
int toCheck = Arrays.binarySearch(integers, shouldBeFound);
|
||||
System.out.println(
|
||||
format(
|
||||
"Found by system method at an index: %d. Is equal: %b", toCheck, toCheck == atIndex));
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Stream;
|
||||
import com.thealgorithms.devutils.searches.SearchAlgorithm;
|
||||
|
||||
/**
|
||||
* A iterative version of a ternary search algorithm This is better way to
|
||||
* implement the ternary search, because a recursive version adds some overhead
|
||||
* to a stack. But in java the compile can transform the recursive version to
|
||||
* iterative implicitly, so there are no much differences between these two
|
||||
* algorithms
|
||||
*
|
||||
* <p>
|
||||
* Worst-case performance Θ(log3(N)) Best-case performance O(1) Average
|
||||
* performance Θ(log3(N)) Worst-case space complexity O(1)
|
||||
*
|
||||
* @author Podshivalov Nikita (https://github.com/nikitap492)
|
||||
* @see SearchAlgorithm
|
||||
* @see TernarySearch
|
||||
* @since 2018-04-13
|
||||
*/
|
||||
public class IterativeTernarySearch implements SearchAlgorithm {
|
||||
|
||||
@Override
|
||||
public <T extends Comparable<T>> int find(T[] array, T key) {
|
||||
int left = 0;
|
||||
int right = array.length - 1;
|
||||
|
||||
while (right > left) {
|
||||
|
||||
int leftCmp = array[left].compareTo(key);
|
||||
int rightCmp = array[right].compareTo(key);
|
||||
if (leftCmp == 0) {
|
||||
return left;
|
||||
}
|
||||
if (rightCmp == 0) {
|
||||
return right;
|
||||
}
|
||||
|
||||
int leftThird = left + (right - left) / 3 + 1;
|
||||
int rightThird = right - (right - left) / 3 - 1;
|
||||
|
||||
if (array[leftThird].compareTo(key) <= 0) {
|
||||
left = leftThird;
|
||||
} else {
|
||||
right = rightThird;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// just generate data
|
||||
Random r = new Random();
|
||||
int size = 100;
|
||||
int maxElement = 100000;
|
||||
Integer[] integers
|
||||
= Stream.generate(() -> r.nextInt(maxElement)).limit(size).sorted().toArray(Integer[]::new);
|
||||
|
||||
// the element that should be found
|
||||
Integer shouldBeFound = integers[r.nextInt(size - 1)];
|
||||
|
||||
IterativeTernarySearch search = new IterativeTernarySearch();
|
||||
int atIndex = search.find(integers, shouldBeFound);
|
||||
|
||||
System.out.println(
|
||||
format(
|
||||
"Should be found: %d. Found %d at index %d. An array length %d",
|
||||
shouldBeFound, integers[atIndex], atIndex, size));
|
||||
|
||||
int toCheck = Arrays.binarySearch(integers, shouldBeFound);
|
||||
System.out.println(
|
||||
format(
|
||||
"Found by system method at an index: %d. Is equal: %b", toCheck, toCheck == atIndex));
|
||||
}
|
||||
}
|
45
src/main/java/com/thealgorithms/searches/JumpSearch.java
Normal file
45
src/main/java/com/thealgorithms/searches/JumpSearch.java
Normal file
@ -0,0 +1,45 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import com.thealgorithms.devutils.searches.SearchAlgorithm;
|
||||
|
||||
public class JumpSearch implements SearchAlgorithm {
|
||||
|
||||
public static void main(String[] args) {
|
||||
JumpSearch jumpSearch = new JumpSearch();
|
||||
Integer[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
assert jumpSearch.find(array, i) == i;
|
||||
}
|
||||
assert jumpSearch.find(array, -1) == -1;
|
||||
assert jumpSearch.find(array, 11) == -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Jump Search algorithm implements
|
||||
*
|
||||
* @param array the array contains elements
|
||||
* @param key to be searched
|
||||
* @return index of {@code key} if found, otherwise <tt>-1</tt>
|
||||
*/
|
||||
@Override
|
||||
public <T extends Comparable<T>> int find(T[] array, T key) {
|
||||
int length = array.length;
|
||||
/* length of array */
|
||||
int blockSize = (int) Math.sqrt(length);
|
||||
/* block size to be jumped */
|
||||
|
||||
int limit = blockSize;
|
||||
while (key.compareTo(array[limit]) > 0 && limit < array.length - 1) {
|
||||
limit = Math.min(limit + blockSize, array.length - 1);
|
||||
}
|
||||
|
||||
for (int i = limit - blockSize; i <= limit; i++) {
|
||||
if (array[i] == key) {
|
||||
/* execute linear search */
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
/* not found */
|
||||
}
|
||||
}
|
59
src/main/java/com/thealgorithms/searches/LinearSearch.java
Normal file
59
src/main/java/com/thealgorithms/searches/LinearSearch.java
Normal file
@ -0,0 +1,59 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.stream.Stream;
|
||||
import com.thealgorithms.devutils.searches.SearchAlgorithm;
|
||||
|
||||
/**
|
||||
* Linear search is the easiest search algorithm It works with sorted and
|
||||
* unsorted arrays (an binary search works only with sorted array) This
|
||||
* algorithm just compares all elements of an array to find a value
|
||||
*
|
||||
* <p>
|
||||
* Worst-case performance O(n) Best-case performance O(1) Average performance
|
||||
* O(n) Worst-case space complexity
|
||||
*
|
||||
* @author Varun Upadhyay (https://github.com/varunu28)
|
||||
* @author Podshivalov Nikita (https://github.com/nikitap492)
|
||||
* @see BinarySearch
|
||||
* @see SearchAlgorithm
|
||||
*/
|
||||
public class LinearSearch implements SearchAlgorithm {
|
||||
|
||||
/**
|
||||
* Generic Linear search method
|
||||
*
|
||||
* @param array List to be searched
|
||||
* @param value Key being searched for
|
||||
* @return Location of the key
|
||||
*/
|
||||
@Override
|
||||
public <T extends Comparable<T>> int find(T[] array, T value) {
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if (array[i].compareTo(value) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// just generate data
|
||||
Random r = new Random();
|
||||
int size = 200;
|
||||
int maxElement = 100;
|
||||
Integer[] integers
|
||||
= Stream.generate(() -> r.nextInt(maxElement)).limit(size).toArray(Integer[]::new);
|
||||
|
||||
// the element that should be found
|
||||
Integer shouldBeFound = integers[r.nextInt(size - 1)];
|
||||
|
||||
LinearSearch search = new LinearSearch();
|
||||
int atIndex = search.find(integers, shouldBeFound);
|
||||
|
||||
System.out.println(
|
||||
String.format(
|
||||
"Should be found: %d. Found %d at index %d. An array length %d",
|
||||
shouldBeFound, integers[atIndex], atIndex, size));
|
||||
}
|
||||
}
|
101
src/main/java/com/thealgorithms/searches/LowerBound.java
Normal file
101
src/main/java/com/thealgorithms/searches/LowerBound.java
Normal file
@ -0,0 +1,101 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.stream.IntStream;
|
||||
import com.thealgorithms.devutils.searches.SearchAlgorithm;
|
||||
|
||||
/**
|
||||
* The LowerBound method is used to return an index pointing to the first
|
||||
* element in the range [first, last) which has a value not less than val, i.e.
|
||||
* the index of the next smallest number just greater than or equal to that
|
||||
* number. If there are multiple values that are equal to val it returns the
|
||||
* index of the first such value.
|
||||
*
|
||||
* <p>
|
||||
* This is an extension of BinarySearch.
|
||||
*
|
||||
* <p>
|
||||
* Worst-case performance O(log n) Best-case performance O(1) Average
|
||||
* performance O(log n) Worst-case space complexity O(1)
|
||||
*
|
||||
* @author Pratik Padalia (https://github.com/15pratik)
|
||||
* @see SearchAlgorithm
|
||||
* @see BinarySearch
|
||||
*/
|
||||
class LowerBound implements SearchAlgorithm {
|
||||
|
||||
// Driver Program
|
||||
public static void main(String[] args) {
|
||||
// Just generate data
|
||||
Random r = ThreadLocalRandom.current();
|
||||
|
||||
int size = 100;
|
||||
int maxElement = 100000;
|
||||
|
||||
Integer[] integers
|
||||
= IntStream.generate(() -> r.nextInt(maxElement))
|
||||
.limit(size)
|
||||
.sorted()
|
||||
.boxed()
|
||||
.toArray(Integer[]::new);
|
||||
|
||||
// The element for which the lower bound is to be found
|
||||
int val = integers[r.nextInt(size - 1)] + 1;
|
||||
|
||||
LowerBound search = new LowerBound();
|
||||
int atIndex = search.find(integers, val);
|
||||
|
||||
System.out.println(
|
||||
format(
|
||||
"Val: %d. Lower Bound Found %d at index %d. An array length %d",
|
||||
val, integers[atIndex], atIndex, size));
|
||||
|
||||
boolean toCheck = integers[atIndex] >= val || integers[size - 1] < val;
|
||||
System.out.println(
|
||||
format(
|
||||
"Lower Bound found at an index: %d. Is greater or max element: %b", atIndex, toCheck));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array is an array where the LowerBound value is to be found
|
||||
* @param key is an element for which the LowerBound is to be found
|
||||
* @param <T> is any comparable type
|
||||
* @return index of the LowerBound element
|
||||
*/
|
||||
@Override
|
||||
public <T extends Comparable<T>> int find(T[] array, T key) {
|
||||
return search(array, key, 0, array.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method implements the Generic Binary Search
|
||||
*
|
||||
* @param array The array to make the binary search
|
||||
* @param key The number you are looking for
|
||||
* @param left The lower bound
|
||||
* @param right The upper bound
|
||||
* @return the location of the key
|
||||
*/
|
||||
private <T extends Comparable<T>> int search(T[] array, T key, int left, int right) {
|
||||
if (right <= left) {
|
||||
return left;
|
||||
}
|
||||
|
||||
// find median
|
||||
int median = (left + right) >>> 1;
|
||||
int comp = key.compareTo(array[median]);
|
||||
|
||||
if (comp == 0) {
|
||||
return median;
|
||||
} else if (comp < 0) {
|
||||
// median position can be a possible solution
|
||||
return search(array, key, left, median);
|
||||
} else {
|
||||
// key we are looking is greater, so we must look on the right of median position
|
||||
return search(array, key, median + 1, right);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,182 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Monte Carlo Tree Search (MCTS) is a heuristic search algorithm used in
|
||||
* decition taking problems especially games.
|
||||
*
|
||||
* See more: https://en.wikipedia.org/wiki/Monte_Carlo_tree_search,
|
||||
* https://www.baeldung.com/java-monte-carlo-tree-search
|
||||
*/
|
||||
public class MonteCarloTreeSearch {
|
||||
|
||||
public class Node {
|
||||
|
||||
Node parent;
|
||||
ArrayList<Node> childNodes;
|
||||
boolean isPlayersTurn; // True if it is the player's turn.
|
||||
boolean playerWon; // True if the player won; false if the opponent won.
|
||||
int score;
|
||||
int visitCount;
|
||||
|
||||
public Node() {
|
||||
}
|
||||
|
||||
public Node(Node parent, boolean isPlayersTurn) {
|
||||
this.parent = parent;
|
||||
childNodes = new ArrayList<>();
|
||||
this.isPlayersTurn = isPlayersTurn;
|
||||
playerWon = false;
|
||||
score = 0;
|
||||
visitCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static final int WIN_SCORE = 10;
|
||||
static final int TIME_LIMIT = 500; // Time the algorithm will be running for (in milliseconds).
|
||||
|
||||
public static void main(String[] args) {
|
||||
MonteCarloTreeSearch mcts = new MonteCarloTreeSearch();
|
||||
|
||||
mcts.monteCarloTreeSearch(mcts.new Node(null, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Explores a game tree using Monte Carlo Tree Search (MCTS) and returns the
|
||||
* most promising node.
|
||||
*
|
||||
* @param rootNode Root node of the game tree.
|
||||
* @return The most promising child of the root node.
|
||||
*/
|
||||
public Node monteCarloTreeSearch(Node rootNode) {
|
||||
Node winnerNode;
|
||||
double timeLimit;
|
||||
|
||||
// Expand the root node.
|
||||
addChildNodes(rootNode, 10);
|
||||
|
||||
timeLimit = System.currentTimeMillis() + TIME_LIMIT;
|
||||
|
||||
// Explore the tree until the time limit is reached.
|
||||
while (System.currentTimeMillis() < timeLimit) {
|
||||
Node promisingNode;
|
||||
|
||||
// Get a promising node using UCT.
|
||||
promisingNode = getPromisingNode(rootNode);
|
||||
|
||||
// Expand the promising node.
|
||||
if (promisingNode.childNodes.size() == 0) {
|
||||
addChildNodes(promisingNode, 10);
|
||||
}
|
||||
|
||||
simulateRandomPlay(promisingNode);
|
||||
}
|
||||
|
||||
winnerNode = getWinnerNode(rootNode);
|
||||
printScores(rootNode);
|
||||
System.out.format("\nThe optimal node is: %02d\n", rootNode.childNodes.indexOf(winnerNode) + 1);
|
||||
|
||||
return winnerNode;
|
||||
}
|
||||
|
||||
public void addChildNodes(Node node, int childCount) {
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
node.childNodes.add(new Node(node, !node.isPlayersTurn));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses UCT to find a promising child node to be explored.
|
||||
*
|
||||
* UCT: Upper Confidence bounds applied to Trees.
|
||||
*
|
||||
* @param rootNode Root node of the tree.
|
||||
* @return The most promising node according to UCT.
|
||||
*/
|
||||
public Node getPromisingNode(Node rootNode) {
|
||||
Node promisingNode = rootNode;
|
||||
|
||||
// Iterate until a node that hasn't been expanded is found.
|
||||
while (promisingNode.childNodes.size() != 0) {
|
||||
double uctIndex = Double.MIN_VALUE;
|
||||
int nodeIndex = 0;
|
||||
|
||||
// Iterate through child nodes and pick the most promising one
|
||||
// using UCT (Upper Confidence bounds applied to Trees).
|
||||
for (int i = 0; i < promisingNode.childNodes.size(); i++) {
|
||||
Node childNode = promisingNode.childNodes.get(i);
|
||||
double uctTemp;
|
||||
|
||||
// If child node has never been visited
|
||||
// it will have the highest uct value.
|
||||
if (childNode.visitCount == 0) {
|
||||
nodeIndex = i;
|
||||
break;
|
||||
}
|
||||
|
||||
uctTemp = ((double) childNode.score / childNode.visitCount)
|
||||
+ 1.41 * Math.sqrt(Math.log(promisingNode.visitCount) / (double) childNode.visitCount);
|
||||
|
||||
if (uctTemp > uctIndex) {
|
||||
uctIndex = uctTemp;
|
||||
nodeIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
promisingNode = promisingNode.childNodes.get(nodeIndex);
|
||||
}
|
||||
|
||||
return promisingNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates a random play from a nodes current state and back propagates
|
||||
* the result.
|
||||
*
|
||||
* @param promisingNode Node that will be simulated.
|
||||
*/
|
||||
public void simulateRandomPlay(Node promisingNode) {
|
||||
Random rand = new Random();
|
||||
Node tempNode = promisingNode;
|
||||
boolean isPlayerWinner;
|
||||
|
||||
// The following line randomly determines whether the simulated play is a win or loss.
|
||||
// To use the MCTS algorithm correctly this should be a simulation of the nodes' current
|
||||
// state of the game until it finishes (if possible) and use an evaluation function to
|
||||
// determine how good or bad the play was.
|
||||
// e.g. Play tic tac toe choosing random squares until the game ends.
|
||||
promisingNode.playerWon = (rand.nextInt(6) == 0);
|
||||
|
||||
isPlayerWinner = promisingNode.playerWon;
|
||||
|
||||
// Back propagation of the random play.
|
||||
while (tempNode != null) {
|
||||
tempNode.visitCount++;
|
||||
|
||||
// Add wining scores to bouth player and opponent depending on the turn.
|
||||
if ((tempNode.isPlayersTurn && isPlayerWinner)
|
||||
|| (!tempNode.isPlayersTurn && !isPlayerWinner)) {
|
||||
tempNode.score += WIN_SCORE;
|
||||
}
|
||||
|
||||
tempNode = tempNode.parent;
|
||||
}
|
||||
}
|
||||
|
||||
public Node getWinnerNode(Node rootNode) {
|
||||
return Collections.max(rootNode.childNodes, Comparator.comparing(c -> c.score));
|
||||
}
|
||||
|
||||
public void printScores(Node rootNode) {
|
||||
System.out.println("N.\tScore\t\tVisits");
|
||||
|
||||
for (int i = 0; i < rootNode.childNodes.size(); i++) {
|
||||
System.out.println(String.format("%02d\t%d\t\t%d", i + 1,
|
||||
rootNode.childNodes.get(i).score, rootNode.childNodes.get(i).visitCount));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
class PerfectBinarySearch {
|
||||
|
||||
static int binarySearch(int[] arr, int target) {
|
||||
int low = 0;
|
||||
int high = arr.length - 1;
|
||||
|
||||
while (low <= high) {
|
||||
int mid = (low + high) / 2;
|
||||
|
||||
if (arr[mid] == target) {
|
||||
return mid;
|
||||
} else if (arr[mid] > target) {
|
||||
high = mid - 1;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PerfectBinarySearch BinarySearch = new PerfectBinarySearch();
|
||||
int[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
assert BinarySearch.binarySearch(array, -1) == -1;
|
||||
assert BinarySearch.binarySearch(array, 11) == -1;
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Program to perform Saddleback Search Given a sorted 2D array(elements are
|
||||
* sorted across every row and column, assuming ascending order) of size n*m we
|
||||
* can search a given element in O(n+m)
|
||||
*
|
||||
* <p>
|
||||
* we start from bottom left corner if the current element is greater than the
|
||||
* given element then we move up else we move right Sample Input: 5 5
|
||||
* ->Dimensions -10 -5 -3 4 9 -6 -2 0 5 10 -4 -1 1 6 12 2 3 7 8 13 100 120 130
|
||||
* 140 150 140 ->element to be searched output: 4 3 // first value is row,
|
||||
* second one is column
|
||||
*
|
||||
* @author Nishita Aggarwal
|
||||
*/
|
||||
public class SaddlebackSearch {
|
||||
|
||||
/**
|
||||
* This method performs Saddleback Search
|
||||
*
|
||||
* @param arr The **Sorted** array in which we will search the element.
|
||||
* @param row the current row.
|
||||
* @param col the current column.
|
||||
* @param key the element that we want to search for.
|
||||
* @return The index(row and column) of the element if found. Else returns
|
||||
* -1 -1.
|
||||
*/
|
||||
private static int[] find(int arr[][], int row, int col, int key) {
|
||||
|
||||
// array to store the answer row and column
|
||||
int ans[] = {-1, -1};
|
||||
if (row < 0 || col >= arr[row].length) {
|
||||
return ans;
|
||||
}
|
||||
if (arr[row][col] == key) {
|
||||
ans[0] = row;
|
||||
ans[1] = col;
|
||||
return ans;
|
||||
} // if the current element is greater than the given element then we move up
|
||||
else if (arr[row][col] > key) {
|
||||
return find(arr, row - 1, col, key);
|
||||
}
|
||||
// else we move right
|
||||
return find(arr, row, col + 1, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method
|
||||
*
|
||||
* @param args Command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// TODO Auto-generated method stub
|
||||
Scanner sc = new Scanner(System.in);
|
||||
int arr[][];
|
||||
int i, j, rows = sc.nextInt(), col = sc.nextInt();
|
||||
arr = new int[rows][col];
|
||||
for (i = 0; i < rows; i++) {
|
||||
for (j = 0; j < col; j++) {
|
||||
arr[i][j] = sc.nextInt();
|
||||
}
|
||||
}
|
||||
int ele = sc.nextInt();
|
||||
// we start from bottom left corner
|
||||
int ans[] = find(arr, rows - 1, 0, ele);
|
||||
System.out.println(ans[0] + " " + ans[1]);
|
||||
sc.close();
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Given an integer x, find the square root of x. If x is not a perfect square,
|
||||
* then return floor(√x).
|
||||
* <p>
|
||||
* For example, if x = 5, The answer should be 2 which is the floor value of √5.
|
||||
* <p>
|
||||
* The approach that will be used for solving the above problem is not going to
|
||||
* be a straight forward Math.sqrt(). Instead we will be using Binary Search to
|
||||
* find the square root of a number in the most optimised way.
|
||||
*
|
||||
* @author sahil
|
||||
*/
|
||||
public class SquareRootBinarySearch {
|
||||
|
||||
/**
|
||||
* This is the driver method.
|
||||
*
|
||||
* @param args Command line arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Scanner sc = new Scanner(System.in);
|
||||
System.out.print("Enter a number you want to calculate square root of : ");
|
||||
int num = sc.nextInt();
|
||||
long ans = squareRoot(num);
|
||||
System.out.println("The square root is : " + ans);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function calculates the floor of square root of a number. We use
|
||||
* Binary Search algorithm to calculate the square root in a more optimised
|
||||
* way.
|
||||
*
|
||||
* @param num Number
|
||||
* @return answer
|
||||
*/
|
||||
private static long squareRoot(long num) {
|
||||
if (num == 0 || num == 1) {
|
||||
return num;
|
||||
}
|
||||
long l = 1;
|
||||
long r = num;
|
||||
long ans = 0;
|
||||
while (l <= r) {
|
||||
long mid = l + (r - l) / 2;
|
||||
if (mid == num / mid) {
|
||||
return mid;
|
||||
} else if (mid < num / mid) {
|
||||
ans = mid;
|
||||
l = mid + 1;
|
||||
} else {
|
||||
r = mid - 1;
|
||||
}
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
}
|
90
src/main/java/com/thealgorithms/searches/TernarySearch.java
Normal file
90
src/main/java/com/thealgorithms/searches/TernarySearch.java
Normal file
@ -0,0 +1,90 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Stream;
|
||||
import com.thealgorithms.devutils.searches.SearchAlgorithm;
|
||||
|
||||
/**
|
||||
* A ternary search algorithm is a technique in computer science for finding the
|
||||
* minimum or maximum of a unimodal function The algorithm determines either
|
||||
* that the minimum or maximum cannot be in the first third of the domain or
|
||||
* that it cannot be in the last third of the domain, then repeats on the
|
||||
* remaining third.
|
||||
*
|
||||
* <p>
|
||||
* Worst-case performance Θ(log3(N)) Best-case performance O(1) Average
|
||||
* performance Θ(log3(N)) Worst-case space complexity O(1)
|
||||
*
|
||||
* @author Podshivalov Nikita (https://github.com/nikitap492)
|
||||
* @see SearchAlgorithm
|
||||
* @see IterativeBinarySearch
|
||||
*/
|
||||
public class TernarySearch implements SearchAlgorithm {
|
||||
|
||||
/**
|
||||
* @param arr The **Sorted** array in which we will search the element.
|
||||
* @param value The value that we want to search for.
|
||||
* @return The index of the element if found. Else returns -1.
|
||||
*/
|
||||
@Override
|
||||
public <T extends Comparable<T>> int find(T[] arr, T value) {
|
||||
return ternarySearch(arr, value, 0, arr.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param arr The **Sorted** array in which we will search the element.
|
||||
* @param key The value that we want to search for.
|
||||
* @param start The starting index from which we will start Searching.
|
||||
* @param end The ending index till which we will Search.
|
||||
* @return Returns the index of the Element if found. Else returns -1.
|
||||
*/
|
||||
private <T extends Comparable<T>> int ternarySearch(T[] arr, T key, int start, int end) {
|
||||
if (start > end) {
|
||||
return -1;
|
||||
}
|
||||
/* First boundary: add 1/3 of length to start */
|
||||
int mid1 = start + (end - start) / 3;
|
||||
/* Second boundary: add 2/3 of length to start */
|
||||
int mid2 = start + 2 * (end - start) / 3;
|
||||
|
||||
if (key.compareTo(arr[mid1]) == 0) {
|
||||
return mid1;
|
||||
} else if (key.compareTo(arr[mid2]) == 0) {
|
||||
return mid2;
|
||||
} /* Search the first (1/3) rd part of the array.*/ else if (key.compareTo(arr[mid1]) < 0) {
|
||||
return ternarySearch(arr, key, start, --mid1);
|
||||
} /* Search 3rd (1/3)rd part of the array */ else if (key.compareTo(arr[mid2]) > 0) {
|
||||
return ternarySearch(arr, key, ++mid2, end);
|
||||
} /* Search middle (1/3)rd part of the array */ else {
|
||||
return ternarySearch(arr, key, mid1, mid2);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// just generate data
|
||||
Random r = new Random();
|
||||
int size = 100;
|
||||
int maxElement = 100000;
|
||||
Integer[] integers
|
||||
= Stream.generate(() -> r.nextInt(maxElement)).limit(size).sorted().toArray(Integer[]::new);
|
||||
|
||||
// the element that should be found
|
||||
Integer shouldBeFound = integers[r.nextInt(size - 1)];
|
||||
|
||||
TernarySearch search = new TernarySearch();
|
||||
int atIndex = search.find(integers, shouldBeFound);
|
||||
|
||||
System.out.println(
|
||||
format(
|
||||
"Should be found: %d. Found %d at index %d. An array length %d",
|
||||
shouldBeFound, integers[atIndex], atIndex, size));
|
||||
|
||||
int toCheck = Arrays.binarySearch(integers, shouldBeFound);
|
||||
System.out.println(
|
||||
format(
|
||||
"Found by system method at an index: %d. Is equal: %b", toCheck, toCheck == atIndex));
|
||||
}
|
||||
}
|
82
src/main/java/com/thealgorithms/searches/UnionFind.java
Normal file
82
src/main/java/com/thealgorithms/searches/UnionFind.java
Normal file
@ -0,0 +1,82 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class UnionFind {
|
||||
|
||||
private int[] p;
|
||||
private int[] r;
|
||||
|
||||
public UnionFind(int n) {
|
||||
p = new int[n];
|
||||
r = new int[n];
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
p[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
public int find(int i) {
|
||||
int parent = p[i];
|
||||
|
||||
if (i == parent) {
|
||||
return i;
|
||||
}
|
||||
|
||||
return p[i] = find(parent);
|
||||
}
|
||||
|
||||
public void union(int x, int y) {
|
||||
int r0 = find(x);
|
||||
int r1 = find(y);
|
||||
|
||||
if (r1 == r0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (r[r0] > r[r1]) {
|
||||
p[r1] = r0;
|
||||
} else if (r[r1] > r[r0]) {
|
||||
p[r0] = r1;
|
||||
} else {
|
||||
p[r1] = r0;
|
||||
r[r0]++;
|
||||
}
|
||||
}
|
||||
|
||||
public int count() {
|
||||
List parents = new ArrayList();
|
||||
for (int i = 0; i < p.length; i++) {
|
||||
if (!parents.contains(find(i))) {
|
||||
parents.add(find(i));
|
||||
}
|
||||
}
|
||||
return parents.size();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "p " + Arrays.toString(p) + " r " + Arrays.toString(r) + "\n";
|
||||
}
|
||||
|
||||
// Tests
|
||||
public static void main(String[] args) {
|
||||
UnionFind uf = new UnionFind(5);
|
||||
System.out.println("init /w 5 (should print 'p [0, 1, 2, 3, 4] r [0, 0, 0, 0, 0]'):");
|
||||
System.out.println(uf);
|
||||
|
||||
uf.union(1, 2);
|
||||
System.out.println("union 1 2 (should print 'p [0, 1, 1, 3, 4] r [0, 1, 0, 0, 0]'):");
|
||||
System.out.println(uf);
|
||||
|
||||
uf.union(3, 4);
|
||||
System.out.println("union 3 4 (should print 'p [0, 1, 1, 3, 3] r [0, 1, 0, 1, 0]'):");
|
||||
System.out.println(uf);
|
||||
|
||||
uf.find(4);
|
||||
System.out.println("find 4 (should print 'p [0, 1, 1, 3, 3] r [0, 1, 0, 1, 0]'):");
|
||||
System.out.println(uf);
|
||||
|
||||
System.out.println("count (should print '3'):");
|
||||
System.out.println(uf.count());
|
||||
}
|
||||
}
|
99
src/main/java/com/thealgorithms/searches/UpperBound.java
Normal file
99
src/main/java/com/thealgorithms/searches/UpperBound.java
Normal file
@ -0,0 +1,99 @@
|
||||
package com.thealgorithms.searches;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.stream.IntStream;
|
||||
import com.thealgorithms.devutils.searches.SearchAlgorithm;
|
||||
|
||||
/**
|
||||
* The UpperBound method is used to return an index pointing to the first
|
||||
* element in the range [first, last) which has a value greater than val, or the
|
||||
* last index if no such element exists i.e. the index of the next smallest
|
||||
* number just greater than that number. If there are multiple values that are
|
||||
* equal to val it returns the index of the first such value.
|
||||
*
|
||||
* <p>
|
||||
* This is an extension of BinarySearch.
|
||||
*
|
||||
* <p>
|
||||
* Worst-case performance O(log n) Best-case performance O(1) Average
|
||||
* performance O(log n) Worst-case space complexity O(1)
|
||||
*
|
||||
* @author Pratik Padalia (https://github.com/15pratik)
|
||||
* @see SearchAlgorithm
|
||||
* @see BinarySearch
|
||||
*/
|
||||
class UpperBound implements SearchAlgorithm {
|
||||
|
||||
// Driver Program
|
||||
public static void main(String[] args) {
|
||||
// Just generate data
|
||||
Random r = ThreadLocalRandom.current();
|
||||
|
||||
int size = 100;
|
||||
int maxElement = 100000;
|
||||
|
||||
Integer[] integers
|
||||
= IntStream.generate(() -> r.nextInt(maxElement))
|
||||
.limit(size)
|
||||
.sorted()
|
||||
.boxed()
|
||||
.toArray(Integer[]::new);
|
||||
|
||||
// The element for which the upper bound is to be found
|
||||
int val = integers[r.nextInt(size - 1)] + 1;
|
||||
|
||||
UpperBound search = new UpperBound();
|
||||
int atIndex = search.find(integers, val);
|
||||
|
||||
System.out.println(
|
||||
format(
|
||||
"Val: %d. Upper Bound Found %d at index %d. An array length %d",
|
||||
val, integers[atIndex], atIndex, size));
|
||||
|
||||
boolean toCheck = integers[atIndex] > val || integers[size - 1] < val;
|
||||
System.out.println(
|
||||
format(
|
||||
"Upper Bound found at an index: %d. Is greater or max element: %b", atIndex, toCheck));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array is an array where the UpperBound value is to be found
|
||||
* @param key is an element for which the UpperBound is to be found
|
||||
* @param <T> is any comparable type
|
||||
* @return index of the UpperBound element
|
||||
*/
|
||||
@Override
|
||||
public <T extends Comparable<T>> int find(T[] array, T key) {
|
||||
return search(array, key, 0, array.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method implements the Generic Binary Search
|
||||
*
|
||||
* @param array The array to make the binary search
|
||||
* @param key The number you are looking for
|
||||
* @param left The lower bound
|
||||
* @param right The upper bound
|
||||
* @return the location of the key
|
||||
*/
|
||||
private <T extends Comparable<T>> int search(T[] array, T key, int left, int right) {
|
||||
if (right <= left) {
|
||||
return left;
|
||||
}
|
||||
|
||||
// find median
|
||||
int median = (left + right) >>> 1;
|
||||
int comp = key.compareTo(array[median]);
|
||||
|
||||
if (comp < 0) {
|
||||
// key is smaller, median position can be a possible solution
|
||||
return search(array, key, left, median);
|
||||
} else {
|
||||
// key we are looking is greater, so we must look on the right of median position
|
||||
return search(array, key, median + 1, right);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user