Binary search implementation in Java - java

if(this.passenger.validatePassengerDetails() && checkEngine() && this.capacity <= 200) {
if(Arrays.binarySearch(airlineClassAir, "flightClass") >=0 && (destination.equals("tx") || destination.equals("ca"))) {
int index = Arrays.binarySearch(airlineClassAir, "flightClass");
int amount = airlineClassPriceAir[index];
double totalAmount = amount + amount* (18/100);
I am trying to understand how the binary search is being implemented here? Can someone explain if(Arrays.binarySearch(airlineClassAir, "flightless") >=0 is trying to do here?

As documented on Arrays.binarySearch(Object[], Object) (emphasis mine):
Returns:
index of the search key, if it is contained in the array; otherwise,
(-(insertion point) - 1). The insertion point is
defined as the point at which the key would be inserted into the
array: the index of the first element greater than the key, or
a.length if all elements in the array are less than the specified
key. Note that this guarantees that the return value will be >= 0 if
and only if the key is found.
In other words, you compare with >= 0 to check if the value exists in the array. Be aware though of the requirement that the array must be sorted (an earlier version of your answer showed it wasn't sorted), otherwise the behaviour is undefined: it might find the item, or it might return a negative value even if the value exists.
To explicitly answer the question, the expression Arrays.binarySearch(airlineClassAir, "flightless") >=0 will be true if airlineClassAir contains the string "flightless", and false otherwise (assuming it is sorted, otherwise it might return false even if the value is in the array).
Personally, if your requirement is to check for existence and there are no other uses of that array, I would use a Set<String> and use its contains method instead, as that expresses intent more clearly.

Related

Compare Two Strings with Greater than or Lower than Android Studio

i want to compare Two Strings
X = Users Input
Y = System Input
if X is Greater than Y
than show greater than
if X is lower than Y
than show Lower than
Here is my code but it is not working
if (X.compareTo(Y)>-1)
{
Toast.makeText(Activity2.this, "Greater Than", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(Activity2.this, "Lower Than", Toast.LENGTH_SHORT).show();
}
I suppose your > -1 is a clever way of testing for "is equal to or greater than". I suggest avoiding such clever code. Writing stupid-simple code (KISS) makes reading and, more to the point here, debugging much easier.
The compareTo method of Comparable interface returns exactly zero if equal. If not equal, the method returns some number greater than zero, or some number less than zero.
To quote the Javadoc:
Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
So change your test to check every single possibility to see how the String#compareTo implementation’s behavior does not match your expectations. Make four checks, for equals zero, greater than zero, less than zero, and a fall-through to catch if you ever mistype the first three.
By the way, variable names should start with a lowercase letter, per Java naming conventions. So x, not X.
int comparison = x.compareTo( y ) ;
if ( comparison == 0 ) {
…
} else if ( comparison > 0 ) {
…
} else if ( comparison < 0 ) {
…
} else {
… Oops, the “if” tests must be flawed. We should never reach this point.
}

Given a sorted array (that is sorted in terms of the absolute value) and a number, find the position of the number

Say we have an array
a[] ={1,2,-3,3,-3,-3,4,-4,5}
And find the position of 3 (which would be 3)
There are be no multiple indexes for an answer.
It must be efficient, and NOT linear.
I was thinking of doing a Binary Search of the array, but instead of comparing the raw values, I wanted to compare the absolute values; abs(a[i]) and abs(n) [n is the input number]. Then if the values are equal, I do another comparison, now with the raw values a[i] and n.
But I run into a problem where, if I am in the above situation with the same array {1,2,-3,3,-3,-3,4,-4,5}, and am looking for 3, there are multiple -3 that get in the way (thus, I would have to check if the raw values a[i] and n does not work, I have to check a[i+1] and a[i-1].)
Ok im just rambling now. Am i thinking too hard for this?
Help me out thanks!!! :D
It is a modified binary search problem. The difference between this and regular binary search is that you need to find and test all of the elements that compare as equal according to the sorting criterion.
I would:
use a tweaked binary search algorithm to find the index of the left-most element that matches
iterate through the indexes until you find the element are looking for, or an element whose absolute value no longer matches.
That should be O(logN) for the first step. The second step is O(1) on average if you assume that the element values are evenly distributed. (The worst case for the second step is O(N); e.g. when the elements all have the same absolute value, and the one you want is the last in the array.)
Here's the method to solve your problem:
/**
* #param a array sorted by absolute value
* #param key value to find (must be positive)
* #return position of the first occurence of the key or -1 if key not found
*/
public static int binarySearch(int[] a, int key) {
int low = 0;
int high = a.length-1;
while (low <= high) {
int mid = (low + high) >>> 1;
int midVal = Math.abs(a[mid]);
if (midVal < key)
low = mid + 1;
else if (midVal > key || (midVal == key && mid > 0 && Math.abs(a[mid-1]) == key))
high = mid - 1;
else
return mid; // key found
}
return -1; // key not found.
}
It's a modification of Arrays.binarySearch from JDK. There are several changes. First, we compare absolute values. Second, as you want not any key position, but the first one, I modified a condition: if we found a key we check whether the previous array item has the same value. If yes, then we continue search. This way algorithm remains O(log N) even for special cases where too many values which are equal to key.

Number Guessing Game Over Intervals

I have just started my long path to becoming a better coder on CodeChef. People begin with the problems marked 'Easy' and I have done the same.
The Problem
The problem statement defines the following -:
n, where 1 <= n <= 10^9. This is the integer which Johnny is keeping secret.
k, where 1 <= k <= 10^5. For each test case or instance of the game, Johnny provides exactly k hints to Alice.
A hint is of the form op num Yes/No, where -
op is an operator from <, >, =.
num is an integer, again satisfying 1 <= num <= 10^9.
Yes or No are answers to the question: Does the relation n op num hold?
If the answer to the question is correct, Johnny has uttered a truth. Otherwise, he is lying.
Each hint is fed to the program and the program determines whether it is the truth or possibly a lie. My job is to find the minimum possible number of lies.
Now CodeChef's Editorial answer uses the concept of segment trees, which I cannot wrap my head around at all. I was wondering if there is an alternative data structure or method to solve this question, maybe a simpler one, considering it is in the 'Easy' category.
This is what I tried -:
class Solution //Represents a test case.
{
HashSet<SolutionObj> set = new HashSet<SolutionObj>(); //To prevent duplicates.
BigInteger max = new BigInteger("100000000"); //Max range.
BigInteger min = new BigInteger("1"); //Min range.
int lies = 0; //Lies counter.
void addHint(String s)
{
String[] vals = s.split(" ");
set.add(new SolutionObj(vals[0], vals[1], vals[2]));
}
void testHints()
{
for(SolutionObj obj : set)
{
//Given number is not in range. Lie.
if(obj.bg.compareTo(min) == -1 || obj.bg.compareTo(max) == 1)
{
lies++;
continue;
}
if(obj.yesno)
{
if(obj.operator.equals("<"))
{
max = new BigInteger(obj.bg.toString()); //Change max value
}
else if(obj.operator.equals(">"))
{
min = new BigInteger(obj.bg.toString()); //Change min value
}
}
else
{
//Still to think of this portion.
}
}
}
}
class SolutionObj //Represents a single hint.
{
String operator;
BigInteger bg;
boolean yesno;
SolutionObj(String op, String integer, String yesno)
{
operator = op;
bg = new BigInteger(integer);
if(yesno.toLowerCase().equals("yes"))
this.yesno = true;
else
this.yesno = false;
}
#Override
public boolean equals(Object o)
{
if(o instanceof SolutionObj)
{
SolutionObj s = (SolutionObj) o; //Make the cast
if(this.yesno == s.yesno && this.bg.equals(s.bg)
&& this.operator.equals(s.operator))
return true;
}
return false;
}
#Override
public int hashCode()
{
return this.bg.intValue();
}
}
Obviously this partial solution is incorrect, save for the range check that I have done before entering the if(obj.yesno) portion. I was thinking of updating the range according to the hints provided, but that approach has not borne fruit. How should I be approaching this problem, apart from using segment trees?
Consider the following approach, which may be easier to understand. Picture the 1d axis of integers, and place on it the k hints. Every hint can be regarded as '(' or ')' or '=' (greater than, less than or equal, respectively).
Example:
-----(---)-------(--=-----)-----------)
Now, the true value is somewhere on one of the 40 values of this axis, but actually only 8 segments are interesting to check, since anywhere inside a segment the number of true/false hints remains the same.
That means you can scan the hints according to their ordering on the axis, and maintain a counter of the true hints at that point.
In the example above it goes like this:
segment counter
-----------------------
-----( 3
--- 4
)-------( 3
-- 4
= 5 <---maximum
----- 4
)----------- 3
) 2
This algorithm only requires to sort the k hints and then scan them. It's near linear in k (O(k*log k), with no dependance on n), therefore it should have a reasonable running time.
Notes:
1) In practice the hints may have non-distinct positions, so you'll have to handle all hints of the same type on the same position together.
2) If you need to return the minimum set of lies, then you should maintain a set rather than a counter. That shouldn't have an effect on the time complexity if you use a hash set.
Calculate the number of lies if the target number = 1 (store this in a variable lies).
Let target = 1.
Sort and group the statements by their respective values.
Iterate through the statements.
Update target to the current statement group's value. Update lies according to how many of those statements would become either true or false.
Then update target to that value + 1 (Why do this? Consider when you have > 5 and < 7 - 6 may be the best value) and update lies appropriately (skip this step if the next statement group's value is this value).
Return the minimum value for lies.
Running time:
O(k) for the initial calculation.
O(k log k) for the sort.
O(k) for the iteration.
O(k log k) total.
My idea for this problem is similar to how Eyal Schneider view it. Denoting '>' as greater, '<' as less than and '=' as equals, we can sort all the 'hints' by their num and scan through all the interesting points one by one.
For each point, we keep in all the number of '<' and '=' from 0 to that point (in one array called int[]lessAndEqual), number of '>' and '=' from that point onward (in one array called int[]greaterAndEqual). We can easily see that the number of lies in a particular point i is equal to
lessAndEqual[i] + greaterAndEqual[i + 1]
We can easily fill the lessAndEqual and greaterAndEqual arrays by two scan in O(n) and sort all the hints in O(nlogn), which result the time complexity is O(nlogn)
Note: special treatment should be taken for the case when the num in hint is equals. Also notice that the range for num is 10^9, which require us to have some forms of point compression to fit the array into the memory

How to check if an array has two different pairs of matching values?

public static boolean hasTwoPair(int[] arrayOfInts){
}
The method is supposed to return true if it can find two different pairs of matching int values. So if the array was {2,2,4,7,7}, it should return true because it has two 2s and two 7s.
It only applies to different pair values though. If it was {2,2,2,2,5}, it would return false because they are not different pair values.
EDIT: This is what I have so far for the body of the method:
boolean pairFound = false;
int pairValue;
for(int s = 0; s < arrayOfInts.length - 1; s++){
pairValue = arrayOfInts[s];
for(int c = s + 1; c < arrayOfInts.length; c++){
if(pairValue == arrayOfInts[c])
pairFound = true;
}
}
return false; //placeholder
I'm not sure where to go from here.
Since you haven't actually tried any code, I'll give a description of how to solve this problem, but no actual code.
Start with a boolean like pairFound that's initialized to false and change to true when you find your first pair. Additionally, you'll need an int (pairValue to keep track of the value of the first pair found (if you found one).
Iterate through, looking for a pair. If you find a pair, and pairFound is false, set pairFound to true, and set pairValue to the value of your first found pair. Now keep iterating through.
If you find a pair and pairFound is true and the pair is != pairValue, then return true;. If you iterate through everything and haven't returned true yet, then you can return false.
Based on your updated question, you're pretty close.
boolean pairFound = false;
int pairValue = Integer.MIN_VALUE;
//or some value that arrayOfInts will never have based on context
for(int s = 0; s < arrayOfInts.length - 1; s++){
if(arrayOfInts[s] == pairValue) {
continue;
}
for(int c = s + 1; c < arrayOfInts.length; c++){
if(arrayOfInts[s] == arrayOfInts[c]) {
if(arrayOfInts[s] != pairValue) {
if(pairFound) {
return true;
}
pairValue = arrayOfInts[s];
pairFound = true;
break;
}
}
}
}
return false;
This task asks you to build a list of counts:
Create a data structure (say, a Map<Integer,Integer>) containing a count for each number from the array.
Go through the map, and count the number of entries with the count of two and above.
If you counted two or more items, return true; otherwise, return false.
The counts for your first example would look like this:
V #
- -
2 - 2
4 - 1
7 - 2
You have two items (2 and 7) with counts of 2, so return true.
The counts for your second example look like this:
V #
- -
2 - 4
5 - 1
There is only one item with the count above 2, so return false.
If you use a HashMap, this algorithm produces an answer in O(n).
Sort the array. Then look for the first two consecutive values that match. If found, skip to the first entry that is different from the matched pair and repeat. If you reach the end of the array before either the first or second search succeeds, return false.
You don't need to sort the array, that would give O(n*log(n)) complexity. But your current solution is even worse since it's yielding O(n^2) complexity. But you also don't need a HashMap. A Set and an integer is enough:
For each array element do
Check: is the element already in the set?
If not put it into the set
If yes check if it's equal to your last found Int pair (yes, use a boxed Int, not a primitive int here, to be able to initialize it with null)
If it's equal continue
If it's not equal
If the last found pair is null set it to elements value
Otherwise you're done and you have at least 2 different pairs
If you iterated over the list without reaching the last condition you don't have 2 different pairs
As for the Set implementation I would recommend a HashSet
There is more to say here though. If you implement it like this you make no assumption about integers and indexable arrays. All you need is a list of comparable elements. So you could make the signature of your method much more generic:
public static boolean hasTwoPair(Iterable<E> iterable)
But since arrays don't support generics and the Iterable interface every client of this method would have to transform Array parameters to an Iterable with the asList() method. If that's too inconvenient you can provide another method:
public static <T> boolean hasTwoPair(T[] array)
In general it's a good idea to use the most generic type possible when you design API's (also see Item 40 and 52 in "Effective Java, Second Edition")

Implementing array with min-value ints

I currently have a nxn array of ints. I plan to initialize all the cells within the array with infinity and later change it if a value being compared to the cell is lower than the value inside the cell. Here is the pseudo-code of what I came up with so far, using -1 to represent infinity. What do you think? Is this the most efficient way, any bugs?
if(table[i][j] == -1 || (table[i][j] != -1 && table[i][j] > value)
then table[i][j] = value
I would instead start with Integer.MAX_VALUE. This way, the code could be simpler :
if(table[i][j] > value) {
table[i][j]=value;
}
Notice that, were your array to contain doubles, you could even go as far as using Double.POSITIVE_INFINITY.
If you are sure that the value -1 can be treated as a "reserved" value, you should be fine with such approach.
You could also consider encapsulating the datatype in some PossiblyInfinitInteger which has a boolean of whether or not it is set to infinity. Perhaps an overkill, I don't know.
if(table [i][j] == -1 || table[i][j] > value) then ... does the same. I'm not sure, but the compiler may take care of this.
If -1 is reserved, and the values cannot be less than 0, your approach is correct, just compare table[i][j] < value and not visa versa.
If using -1 as a reserved value is a problem, use Integer.MAX_VALUE:
if(table[i][j] == Integer.MAX_VALUE) then table[i][j] = value;

Categories