Palindrome Partitioning DP complexity issue on memorization step - java

I have the following problem:
Given a string s, partition s such that every substring of the
partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of s.
I got the correct solution but I am missing an optimization step, more particularly the memorization step needed in DP.
public int minCut(String a) {
if (isValidPal(a)) {
return 0;
}
return minCut(a, 0, 0);
}
int min = Integer.MAX_VALUE;
private int minCut(String a, int cut, int index) {
// too many cuts already
if(cut >= min) return min;
// out of index
if (index >= a.length()) {
// what is left is a pal
if (isValidPal(a)) {
min = Math.min(min, cut);
return cut;
}
return Integer.MAX_VALUE;
}
int newCut = Integer.MAX_VALUE;
if (isValidPal(a.substring(0, index + 1))) {
// then cut
newCut = minCut(a.substring(index + 1), cut + 1, 0);
}
// continue either way
newCut = Math.min(minCut(a, cut, index + 1), newCut);
return newCut;
}
HashMap<String, Boolean> memo = new HashMap<>();
private boolean isValidPal(String s) {
if(memo.containsKey(s)) {
return memo.get(s);
}
boolean result = true;
for (int i = 0; i < s.length() / 2; i++) {
if (s.charAt(i) != s.charAt(s.length() - i - 1)) {
result = false;
break;
}
}
memo.put(s, result);
return result;
}

Try adding a memo to store the results of your computations , assuming your algorithm is correct this should do the optimization
Map<String, Integer> dp = new HashMap<>();
private int minCut(String a, int cut, int index) {
// too many cuts already
if(cut >= min) return min;
String key = cut + " " + index;
//test if the memo contains the answer if yes return it
if(dp.containsKey(key)) return dp.get(key);
// out of index
if (index >= a.length()) {
// what is left is a pal
if (isValidPal(a)) {
min = Math.min(min, cut);
return cut;
}
return Integer.MAX_VALUE;
}
int newCut = Integer.MAX_VALUE;
if (isValidPal(a.substring(0, index + 1))) {
// then cut
newCut = minCut(a.substring(index + 1), cut + 1, 0);
}
// continue either way
newCut = Math.min(minCut(a, cut, index + 1), newCut);
//put the computed answer in the memo table
dp.put(key, newCut);
return newCut;
}

i'm sorry but my answer was based on the fact that your code is correct , here is a working example of a min palindrom partitioning with memoization
import java.util.*;
class Main {
static HashMap<String, Integer> memo = new HashMap<>();
static String s;
static int f(int i, int j){
if(i == j) return 0;
if(isPalindrom(s.substring(i, j))) return 0;
String key = i + " " + j;
if(memo.containsKey(key)) return memo.get(key);
int ans = 999999;
for(int k = i; k < j; k++){
ans = Math.min(ans, f(i, k) + f(k + 1, j) + 1);
}
memo.put(key, ans);
return ans;
}
static boolean isPalindrom(String s){
return s.equals(new StringBuilder(s).reverse().toString());
}
public static void main(String[] args) {
s = "aaka";
System.out.println(f(0, s.length()));
}
}

Related

How to count all the matching sub-string using regex?

I am trying to count all instances of a substring from .PBAAP.B with P A B in that sequence and can have 1-3 symbols in between them (inclusive).
The output should be 2
.P.A...B
.P..A..B
What I've tried so far is
return (int) Pattern
.compile("P.{0,2}A.{0,2}B")
.matcher(C)
.results()
.count();
But I only get output 1. My guess is that in both cases, the group is PBAAP.B. So instead of 2, I get 1.
I could write an elaborate function to achieve what I am trying to do, but I was wondering if there was a way to do it with regex.
int count = 0;
for (int i = 0; i < C.length(); i++) {
String p = Character.toString(C.charAt(i));
if (p.equalsIgnoreCase("P")) {
for (int j = X; j <= Y; j++) {
if (i + j < C.length()) {
String a = Character.toString(C.charAt(i + j));
if (a.equals("A")) {
for (int k = X; k <= Y; k++) {
if (i + j + k < C.length()) {
String b = Character.toString(C.charAt(i + j + k));
if (b.equalsIgnoreCase("B")) {
count++;
}
}
}
}
}
return count;
To my knowledge, you will only get a boolean response out of a regex match - either it is a match or it isn't. Thus, I can't think of a solution solving your problem using regex.
count() is used, if you want to check if there are multiple matches at different indices - which is not what you want. For instance, the following snippet will return 2 as th is found at 11-12 and at 20-21:
Pattern
.compile("(th)")
.matcher("let's test this together")
.results()
.count();
In order to keep the solution without regex readable and extensible, you may want to use regression.
Class to keep track of the latest match of each letter:
public class Letter {
private char letter;
private int latestMatch;
// constructor
// getters + setters
}
Class to detect different matches:
public class MatchFinder {
final static String C = "......PAA.BBBadsfjksPeAkBB";
final static Letter[] LETTERS = new Letter[3];
final static int SYMBOLS_THRESHOLD = 4;
public static void main(String[] args) {
LETTERS[0] = new Letter('P', -1);
LETTERS[1] = new Letter('A', -1);
LETTERS[2] = new Letter('B', -1);
int count = countMatches(0, C.length(), 0, 0, -1);
System.out.println(count);
}
public static int countMatches(int start, int end, int letterIndex, int currentCount, int latestMatch) {
for (int i = start; i < end; i++) {
if (i < C.length()) {
Character c = Character.toLowerCase(C.charAt(i));
if (c.equals(LETTERS[letterIndex].getLowercaseLetter()) && i > latestMatch) {
LETTERS[letterIndex].setLatestMatch(i);
if (letterIndex + 1 < LETTERS.length) {
int childStart = LETTERS[letterIndex].getLatestMatch() + 1;
return countMatches(childStart, childStart + SYMBOLS_THRESHOLD, letterIndex + 1, currentCount, -1);
}
currentCount++;
}
}
}
if (letterIndex > 0) {
int parentLetterIndex = letterIndex - 1;
int latestParentMatch = LETTERS[parentLetterIndex].getLatestMatch();
if (letterIndex > 1) {
int parentStart = LETTERS[letterIndex - 2].getLatestMatch() + 1;
return countMatches(parentStart, parentStart + SYMBOLS_THRESHOLD, parentLetterIndex, currentCount, latestParentMatch);
} else {
return countMatches(LETTERS[parentLetterIndex].getLatestMatch() + 1, C.length(), 0, currentCount, latestParentMatch);
}
}
return currentCount;
}
}

How can I build a max heap java class for an object?

I am trying to build a max heap java class for item objects, so I can solve the knapsack problem and implement greedy algorithms to do so. Item class includes weight, value, Id(to distinguish items), and most importantly a priority factor:
public class Items {
double weight;
double value;
double priorityFactor;
int ID;
//constructor for items class
public Items(int weight, int value, int id, int priorityFactor)
{
this.weight=weight;
this.value=value;
this.ID=id;
this.priorityFactor = priorityFactor;
} //end constructor
Now the issue that I'm facing is in the max heap class, which is supposed to build me a max heap tree based on the priority factor. Means that I should have an array of item objects: private Items[] array
What I'm finding difficult to implement is how can I insert those items in the array based on the priority factor. If I do this, I think I will be able to implement the greedy algorithms. How to handle this?
This is the basic code for a min/max heap (depending on the T:compareTo() method).
This only handles insertion, but I think it's what you're after.
package jc.lib.container.collection.set;
import jc.lib.lang.string.JcStringBuilder;
public class JcHeap<T extends Comparable<T>> {
private T[] mItems;
private int mItemCount = 0;
#SuppressWarnings("unchecked") public JcHeap(final int pStartCapacity) {
mItems = (T[]) new Comparable[pStartCapacity];
}
private void checkResize() {
if (mItems.length <= mItemCount) {
final int newSize = (mItems.length) * 2;
#SuppressWarnings("unchecked") final T[] tmp = (T[]) new Comparable[newSize];
if (mItems != null) System.arraycopy(mItems, 0, tmp, 0, mItemCount);
mItems = tmp;
}
}
static private int getParentIndex(final int pCurrentIndex) {
return (pCurrentIndex - 1) / 2;
}
#SuppressWarnings("unused") static private int getLeftChildIndex(final int pCurrentIndex) {
return 2 * pCurrentIndex + 1;
}
#SuppressWarnings("unused") static private int getRightChildIndex(final int pCurrentIndex) {
return 2 * pCurrentIndex + 2;
}
public void addItem(final T pItem) {
checkResize();
// insert
System.out.println("\nInserting " + pItem);
T current = pItem;
int currentIndex = mItemCount;
mItems[currentIndex] = current;
++mItemCount;
// sort
while (true) { // swap up
if (currentIndex <= 0) break;
final int parentIndex = getParentIndex(currentIndex);
final T parent = mItems[parentIndex];
System.out.print("Checking cur:" + current + " vs par:" + parent + " => " + current.compareTo(parent) + "/");
if (current.compareTo(parent) >= 0) {
System.out.println("break");
break;
}
System.out.println("swap");
System.out.println("Swapping with parent: " + parent);
final T tmp = mItems[parentIndex];
mItems[parentIndex] = mItems[currentIndex];
mItems[currentIndex] = tmp;
currentIndex = parentIndex;
current = mItems[currentIndex];
}
}
// public boolean contains(final T pItem) {
// final int index = findIndex(pItem);
// return 0 <= index && index < mItemCount;
// }
//
// public int findIndex(final T pItem) {
// int index = 0;
// int width = mItemCount;
//
// while (true) {
// System.out.println("Comparing with index " + index);
// final int cmp = pItem.compareTo(mItems[index]);
// if (cmp == 0) return index;
// else if (cmp > 0) return -1;
//
// index += mItemCount;
// width /= 2;
// if (width == 0) return -1;
// }
// }
#Override public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("\nTree View:\n");
int height = (int) (Math.log(mItemCount) / Math.log(2));
sb.append("count=" + mItemCount + " height=" + height);
int next = 1;
sb.append("\n[");
sb.append(JcStringBuilder.buildFromArray(", ", (Object[]) mItems));
// for (int c = 0; c < mItemCount; c++) {
// sb.append("\n" + mItems);
// }
sb.append("]");
for (int c = 0; c < mItemCount; c++) {
if (c + 2 > next) {
sb.append("\n");
for (int d = 0; d < height; d++) {
sb.append("\t");
}
height -= 1;
next *= 2;
// System.out.println("Next is " + next);
}
sb.append("<" + mItems[c] + ">\t");
}
return sb.toString() + "\n";
}
}

Finding the smallest integer that appears at least k times

You are given an array A of integers and an integer k. Implement an algorithm that determines, in linear time, the smallest integer that appears at least k times in A.
I have been struggling with this problem for awhile, coding in Java, I need to use a HashTable to find the smallest integer that appears at least k times, it also must be in linear time.
This is what I attempted but it does not pass any of the tests
private static int problem1(int[] arr, int k)
{
// Implement me!
HashMap<Integer, Integer> table = new HashMap<Integer, Integer>();
int ans = Integer.MAX_VALUE;
for (int i=0; i < arr.length; i++) {
if(table.containsKey(arr[i])) {
table.put(arr[i], table.get(arr[i]) + 1);
if (k <= table.get(arr[i])) {
ans = Math.min(ans, arr[i]);
}
}else{
table.put(arr[i], 1);
}
}
return ans;
}
Here is the empty code with all of the test cases:
import java.io.*;
import java.util.*;
public class Lab5
{
/**
* Problem 1: Find the smallest integer that appears at least k times.
*/
private static int problem1(int[] arr, int k)
{
// Implement me!
return 0;
}
/**
* Problem 2: Find two distinct indices i and j such that A[i] = A[j] and |i - j| <= k.
*/
private static int[] problem2(int[] arr, int k)
{
// Implement me!
int i = -1;
int j = -1;
return new int[] { i, j };
}
// ---------------------------------------------------------------------
// Do not change any of the code below!
private static final int LabNo = 5;
private static final String quarter = "Fall 2020";
private static final Random rng = new Random(123456);
private static boolean testProblem1(int[][] testCase)
{
int[] arr = testCase[0];
int k = testCase[1][0];
int answer = problem1(arr.clone(), k);
Arrays.sort(arr);
for (int i = 0, j = 0; i < arr.length; i = j)
{
for (; j < arr.length && arr[i] == arr[j]; j++) { }
if (j - i >= k)
{
return answer == arr[i];
}
}
return false; // Will never happen.
}
private static boolean testProblem2(int[][] testCase)
{
int[] arr = testCase[0];
int k = testCase[1][0];
int[] answer = problem2(arr.clone(), k);
if (answer == null || answer.length != 2)
{
return false;
}
Arrays.sort(answer);
// Check answer
int i = answer[0];
int j = answer[1];
return i != j
&& j - i <= k
&& i >= 0
&& j < arr.length
&& arr[i] == arr[j];
}
public static void main(String args[])
{
System.out.println("CS 302 -- " + quarter + " -- Lab " + LabNo);
testProblems(1);
testProblems(2);
}
private static void testProblems(int prob)
{
int noOfLines = prob == 1 ? 100000 : 500000;
System.out.println("-- -- -- -- --");
System.out.println(noOfLines + " test cases for problem " + prob + ".");
boolean passedAll = true;
for (int i = 1; i <= noOfLines; i++)
{
int[][] testCase = null;
boolean passed = false;
boolean exce = false;
try
{
switch (prob)
{
case 1:
testCase = createProblem1(i);
passed = testProblem1(testCase);
break;
case 2:
testCase = createProblem2(i);
passed = testProblem2(testCase);
break;
}
}
catch (Exception ex)
{
passed = false;
exce = true;
}
if (!passed)
{
System.out.println("Test " + i + " failed!" + (exce ? " (Exception)" : ""));
passedAll = false;
break;
}
}
if (passedAll)
{
System.out.println("All test passed.");
}
}
private static int[][] createProblem1(int testNo)
{
int size = rng.nextInt(Math.min(1000, testNo)) + 5;
int[] numbers = getRandomNumbers(size, size);
Arrays.sort(numbers);
int maxK = 0;
for (int i = 0, j = 0; i < size; i = j)
{
for (; j < size && numbers[i] == numbers[j]; j++) { }
maxK = Math.max(maxK, j - i);
}
int k = rng.nextInt(maxK) + 1;
shuffle(numbers);
return new int[][] { numbers, new int[] { k } };
}
private static int[][] createProblem2(int testNo)
{
int size = rng.nextInt(Math.min(1000, testNo)) + 5;
int[] numbers = getRandomNumbers(size, size);
int i = rng.nextInt(size);
int j = rng.nextInt(size - 1);
if (i <= j) j++;
numbers[i] = numbers[j];
return new int[][] { numbers, new int[] { Math.abs(i - j) } };
}
private static void shuffle(int[] arr)
{
for (int i = 0; i < arr.length - 1; i++)
{
int rndInd = rng.nextInt(arr.length - i) + i;
int tmp = arr[i];
arr[i] = arr[rndInd];
arr[rndInd] = tmp;
}
}
private static int[] getRandomNumbers(int range, int size)
{
int numbers[] = new int[size];
for (int i = 0; i < size; i++)
{
numbers[i] = rng.nextInt(2 * range) - range;
}
return numbers;
}
}
private static int problem1(int[] arr, int k) {
// Implement me!
Map<Integer, Integer> table = new TreeMap<Integer, Integer>();
for (int i = 0; i < arr.length; i++) {
if (table.containsKey(arr[i])) {
table.put(arr[i], table.get(arr[i]) + 1);
} else {
table.put(arr[i], 1);
}
}
for (Map.Entry<Integer,Integer> entry : table.entrySet()) {
//As treemap is sorted, we return the first key with value >=k.
if(entry.getValue()>=k)
return entry.getKey();
}
//Not found
return -1;
}
As others have pointed out, there are a few mistakes. First, the line where you initialize ans,
int ans = 0;
You should initialize ans to Integer.MAX_VALUE so that when you find an integer that appears at least k times for the first time that ans gets set to that integer appropriately. Second, in your for loop, there's no reason to skip the first element while iterating the array so i should be initialized to 0 instead of 1. Also, in that same line, you want to iterate through the entire array, and in your loop's condition right now you have i < k when k is not the length of the array. The length of the array is denoted by arr.length so the condition should instead be i < arr.length. Third, in this line,
if (k < table.get(arr[i])){
where you are trying to check if an integer has occurred at least k times in the array so far while iterating through the array, the < operator should be changed to <= since the keyword here is at least k times, not "more than k times". Fourth, k should never change so you can get rid of this line of code,
k = table.get(arr[i]);
After applying all of those changes, your function should look like this:
private static int problem1(int[] arr, int k)
{
// Implement me!
HashMap<Integer, Integer> table = new HashMap<Integer, Integer>();
int ans = Integer.MAX_VALUE;
for (int i=0; i < arr.length; i++) {
if(table.containsKey(arr[i])) {
table.put(arr[i], table.get(arr[i]) + 1);
if (k <= table.get(arr[i])) {
ans = Math.min(ans, arr[i]);
}
}else{
table.put(arr[i], 1);
}
}
return ans;
}
Pseudo code:
collect frequencies of each number in a Map<Integer, Integer> (number and its count)
set least to a large value
iterate over entries
ignore entry if its value is less than k
if entry key is less than current least, store it as least
return least
One line implementation:
private static int problem1(int[] arr, int k) {
return Arrays.stream(arr).boxed()
.collect(groupingBy(identity(), counting()))
.entrySet().stream()
.filter(entry -> entry.getValue() >= k)
.map(Map.Entry::getKey)
.reduce(MAX_VALUE, Math::min);
}
This was able to pass all the cases! Thank you to everyone who helped!!
private static int problem1(int[] arr, int k)
{
// Implement me!
HashMap<Integer, Integer> table = new HashMap<Integer, Integer>();
int ans = Integer.MAX_VALUE;
for (int i=0; i < arr.length; i++) {
if(table.containsKey(arr[i])) {
table.put(arr[i], table.get(arr[i]) + 1);
}else{
table.put(arr[i], 1);
}
}
Set<Integer> keys = table.keySet();
for(int i : keys){
if(table.get(i) >= k){
ans = Math.min(ans,i);
}
}
if(ans != Integer.MAX_VALUE){
return ans;
}else{
return 0;
}
}

Bloom Filters: Getting higher error rates than expected

I created a bloom filter using murmur3, blake2b, and Kirsch-Mitzenmacher-optimization, as described in the second answer to this question: Which hash functions to use in a Bloom filter
However, when I was testing it, the bloom filter constantly had a much higher error rate than I was expecting.
Here is the code I used to generate the bloom filters:
public class BloomFilter {
private BitSet filter;
private int size;
private int hfNum;
private int prime;
private double fp = 232000; //One false positive every fp items
public BloomFilter(int count) {
size = (int)Math.ceil(Math.ceil(((double)-count) * Math.log(1/fp))/(Math.pow(Math.log(2),2)));
hfNum = (int)Math.ceil(((this.size / count) * Math.log(2)));
//size = (int)Math.ceil((hfNum * count) / Math.log(2.0));
filter = new BitSet(size);
System.out.println("Initialized filter with " + size + " positions and " + hfNum + " hash functions.");
}
public BloomFilter extraSecure(int count) {
return new BloomFilter(count, true);
}
private BloomFilter(int count, boolean x) {
size = (int)Math.ceil((((double)-count) * Math.log(1/fp))/(Math.pow(Math.log(2),2)));
hfNum = (int)Math.ceil(((this.size / count) * Math.log(2)));
prime = findPrime();
size = prime * hfNum;
filter = new BitSet(prime * hfNum);
System.out.println("Initialized filter with " + size + " positions and " + hfNum + " hash functions.");
}
public void add(String in) {
filter.set(getMurmur(in), true);
filter.set(getBlake(in), true);
if(this.hfNum > 2) {
for(int i = 3; i <= (hfNum); i++) {
filter.set(getHash(in, i));
}
}
}
public boolean check(String in) {
if(!filter.get(getMurmur(in)) || !filter.get(getBlake(in))) {
return false;
}
for(int i = 3; i <= hfNum; i++) {
if(!filter.get(getHash(in, i))) {
return false;
}
}
return true;
}
private int getMurmur(String in) {
int temp = murmur(in) % (size);
if(temp < 0) {
temp = temp * -1;
}
return temp;
}
private int getBlake(String in) {
int temp = new BigInteger(blake256(in), 16).intValue() % (size);
if(temp < 0) {
temp = temp * -1;
}
return temp;
}
private int getHash(String in, int i) {
int temp = ((getMurmur(in)) + (i * getBlake(in))) % size;
return temp;
}
private int findPrime() {
int temp;
int test = size;
while((test * hfNum) > size ) {
temp = test - 1;
while(!isPrime(temp)) {
temp--;
}
test = temp;
}
if((test * hfNum) < this.size) {
test++;
while(!isPrime(test)) {
test++;
}
}
return test;
}
private static boolean isPrime(int num) {
if (num < 2) return false;
if (num == 2) return true;
if (num % 2 == 0) return false;
for (int i = 3; i * i <= num; i += 2)
if (num % i == 0) return false;
return true;
}
#Override
public String toString() {
final StringBuilder buffer = new StringBuilder(size);
IntStream.range(0, size).mapToObj(i -> filter.get(i) ? '1' : '0').forEach(buffer::append);
return buffer.toString();
}
}
Here is the code I'm using to test it:
public static void main(String[] args) throws Exception {
int z = 0;
int times = 10;
while(z < times) {
z++;
System.out.print("\r");
System.out.print(z);
BloomFilter test = new BloomFilter(4000);
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
for(int i = 0; i < 4000; i++) {
test.add(blake256(Integer.toString(random.nextInt())));
}
int temp = 0;
int count = 1;
while(!test.check(blake512(Integer.toString(temp)))) {
temp = random.nextInt();
count++;
}
if(z == (times)) {
Files.write(Paths.get("counts.txt"), (Integer.toString(count)).getBytes(), StandardOpenOption.APPEND);
}else {
Files.write(Paths.get("counts.txt"), (Integer.toString(count) + ",").getBytes(), StandardOpenOption.APPEND);
}
if(z == 1) {
Files.write(Paths.get("counts.txt"), (Integer.toString(count) + ",").getBytes());
}
}
}
I expect to get a value relatively close to the fp variable in the bloom filter class, but instead I frequently get half that. Anyone know what I'm doing wrong, or if this is normal?
EDIT: To show what I mean by high error rates, when I run the code on a filter initialized with count 4000 and fp 232000, this was the output in terms of how many numbers the filter had to run through before it found a false positive:
158852,354114,48563,76875,156033,82506,61294,2529,82008,32624
This was generated using the extraSecure() method for initialization, and repeated 10 times to generate these 10 numbers; all but one of them took less than 232000 generated values to find a false positive. The average of the 10 is about 105540, and that's common no matter how many times I repeat this test.
Looking at the values it found, the fact that it found a false positive after only generating 2529 numbers is a huge issue for me, considering I'm adding 4000 data points.
I'm afraid I don't know where the bug is, but you can simplify a lot. You don't actually need prime size, you don't need SecureRandom, BigInteger, and modulo. All you need is a good 64 bit hash (seeded if possible, for example murmur):
long bits = (long) (entryCount * bitsPerKey);
int arraySize = (int) ((bits + 63) / 64);
long[] data = new long[arraySize];
int k = getBestK(bitsPerKey);
void add(long key) {
long hash = hash64(key, seed);
int a = (int) (hash >>> 32);
int b = (int) hash;
for (int i = 0; i < k; i++) {
data[reduce(a, arraySize)] |= 1L << index;
a += b;
}
}
boolean mayContain(long key) {
long hash = hash64(key, seed);
int a = (int) (hash >>> 32);
int b = (int) hash;
for (int i = 0; i < k; i++) {
if ((data[reduce(a, arraySize)] & 1L << a) == 0) {
return false;
}
a += b;
}
return true;
}
static int reduce(int hash, int n) {
// http://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
return (int) (((hash & 0xffffffffL) * n) >>> 32);
}
static int getBestK(double bitsPerKey) {
return Math.max(1, (int) Math.round(bitsPerKey * Math.log(2)));
}
Turns out the issue was that the answer on the other page wasn't completely correct, and neither was the comment below it.
The comment said:
in the paper hash_i = hash1 + i x hash2 % p, where p is a prime, hash1 and hash2 is within range of [0, p-1], and the bitset consists k * p bits.
However, looking at the paper reveals that while all the hashes are mod p, each hash function is assigned a subset of the total bitset, which I understood to mean hash1 mod p would determine a value for indices 0 through p, hash2 mod p would determine a value for indices p through 2*p, and so on and so forth until the k value chosen for the bitset is reached.
I'm not 100% sure if adding this will fix my code, but it's worth a try. I'll update this if it works.
UPDATE: Didn't help. I'm looking into what else may be causing this problem.

recursion method in the binary search

I'm trying to implement a binary algorithm but I really don't know how to write this program using a recursion method. Could someone help me please write this method?
I have already written the easiest way for me:
import Prog1Tools.IOTools;
public class BinarySearch {
public static void showArray(int[] array) {
for(int x : array) System.out.print (x + " ");
System.out.println ();
}
public static void fillArray(int[] array, int arrayFirst) {
int i = 0;
while (i < array.length){
array[i] = arrayFirst;
i++;
arrayFirst++;
}
}
public static void main(String[] args) {
int l, p, s;
int arrayEnd = IOTools.readInt("Type a last number in the array : ");
int arrayFirst = IOTools.readInt("Type a first number in the array : ");
int[] nums = new int[arrayEnd+1-arrayFirst ];
fillArray(nums, arrayFirst);
showArray(nums);
System.out.println ("Could you please choose a number from the array above? " );
l = 0;
p = arrayEnd-arrayFirst;
loop: while (l <= p) {
s = (l + p) / 2;
String question = IOTools.readString("Is your number "+nums[s] + " or higher ?[You can answer: yes or higher] ");
switch (question){
case "yes":
System.out.println("I found a number "+nums[s]+" Your number has an index "+s +" in the array");
break loop;
case "higher":
l = s + 1;
break;
}
}
}
}
I tried such method but it doesn't work
public static int recursiveBinarySearch(int[] sortedArray, int start, int end, String question) {
if (start < end) {
int mid = start + (end - start) / 2;
if (question=="higher") {
return recursiveBinarySearch(sortedArray, start, mid, question);
} else if (question=="lower") {
return recursiveBinarySearch(sortedArray, mid+1, end , question);
} else {
return mid;
}
}
return -(start + 1);
}
public boolean binaryS(int A[],int left, int right, int x){
int middle;
//check if there is any array left to search
if (left > right) return false;
//determine the middle of this array section
middle = (left + right) / 2;
//is the middle what we are looking for?
if (A[middle] == x) return true;
//search the half of the array that might contain x
if (A[middle] > x) { //search for x to the left
return binaryS(A, left, middle - 1, x);
} else { //search for x to the right
return binaryS(A, middle + 1, right, x);
}
}
Bob's answer is a nice binary search.
If you want to have user input (and keep your structure):
public static int recursiveBinarySearch(int[] sortedArray, int start, int end) {
if (start < end) {
int mid = (start + end) / 2;
String question = IOTools.readString("Is your number compared to "+sortedArray[mid] + " lower or higher?[You can answer: equal, lower or higher] ");
if (question.equals("higher")) {
return recursiveBinarySearch(sortedArray, mid+1, end, question);
} else if (question.equals("lower")) {
return recursiveBinarySearch(sortedArray, start, mid-1, question);
} else {
return mid;
}
}
System.out.println("Something went wrong...");
return -1;
}

Categories

Resources