I am trying to implement The Longest Increasing SubSequence using Binary Search. Well I have coded the algorithm and my test cases are getting satisfied but when I submit the code,it is failing for some test cases like for example for the following list,
29471 5242 21175 28931 2889 7275 19159 21773 1325 6901, the answer should be 4 but I am getting 5.Below is my code,
import java.util.Scanner;
public class LongestIncreasingSubSequence {
public static int BS(int[] arr,int low,int high,int key){
int mid;
while ((high - low) > 1) {
mid = (int) Math.ceil((low + high) / 2);
if (arr[mid] >= key) {
high = mid;
} else {
low = mid;
}
}
return high;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n;
n = sc.nextInt();
int arr[] = new int[n];
int LS[] = new int[arr.length];
int count = 1;
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
LS[0] = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] < LS[0]) {
LS[0] = arr[i];
} else if (arr[i] > LS[count-1]) {
LS[count++] = arr[i];
} else {
LS[BS(arr,0,count-1,arr[i])] = arr[i];
}
}
System.out.println(count);
}
}
So can anyone please tell me where I am going wrong.Thanks in advance.
There is a bug here:
LS[BS(arr,0,count-1,arr[i])] = arr[i];should be
LS[BS(LS,0,count-1,arr[i])] = arr[i]; instead, because we need to update the array with the smallest value for each length of an increasing sub sequence (that is, LS), not the original one.
With this change, it works properly on your test case (I haven't tested it on anything else, but the algorithm looks correct to me now).
Related
I'm trying to write a method which finds the smallest value in an array of Complex numbers a + ci, where a and c are both doubles. a is the real part and ci is the imaginary part. I'm trying to have it go through the array and compare each object a + ci and b + di. I was going to start by comparing the real parts and if the real parts were equal, then I would move on to the imaginary ones such that complexNumberOne < complexNumberTwo if a < b or if (a==b), c < d.
So far I have a method that can determine the smallest number in the array, but only by comparing the real parts:
import java.util.Scanner;
import java.util.Random;
private boolean arrayTest = false;
public double min(Complex[] arr) {
double min = Double.MIN_VALUE;
for(int i = 0; i < arr.length;i++) {
if(arr[i].getReal() < min) {
min = arr[i].getReal();
}
}
return min;
}
But my method to find the smallest element according the the aforementioned conditions seems to go nowhere:
public Complex smallest(Complex[] arr) {
Complex min = new Complex();
for(int i = 0; i < arr.length;i++) {
while(!arrayTest) {
if(arr[i].getReal()<arr[i+1].getReal()) {
arrayTest=true;
min = arr[i];
}else if(arr[i].getReal()==arr[i+1].getReal()) {
while(!arrayTest) {
if(arr[i].getImaginary()<arr[i+1].getImaginary()) {
arrayTest=true;
min = arr[i];
}
}
}
}
}
return min;
}
Why so many loops and nested loops?
A single scan of the array will do:
public Complex smallest(Complex[] arr) {
if (arr.length == 0) return null;
Complex min = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i].getReal() < min.getReal()) {
min = arr[i];
} else if (arr[i].getReal() == min.getReal()) {
if (arr[i].getImaginary() < min.getImaginary()) {
min = arr[i];
}
}
}
return min;
}
Also there is no need for that boolean flag arrayTest.
The code could be further simplified if you don't mind a long condition:
public Complex smallest(Complex[] arr) {
if (arr.length == 0) return null;
Complex min = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i].getReal() < min.getReal() || (arr[i].getReal() == min.getReal() && arr[i].getImaginary() < min.getImaginary())) {
min = arr[i];
}
}
return min;
}
Edit: I need to do the following with the array: sort, find minimum, find maximum, find the average.
1) How do I properly access the methods in the other class 2) What variables do I need to initialize in order to make my methods work (since I got the examples from Google)
I've tried to find examples of how to work with the numbers in an array, but I find it difficult to figure out considering the code is working with different variable names and is largely unorganized and not commented.
This is what I have so far in my methods class:
//Grades Array
int[] score = {70,90,80,85,65,55,100,70,40,77,66,55,44};
int number;
//Get
public int getNumber(){
return number;
}
//Average Grade
public static double average(int[] score, int number)
{
double average = 0;
if (score.length > 0)
{
average = number / score.length;
}
return average;
}
Here is my Main class:
public class Main {
public static void main(String[] args) {
//Average Method
OtherMethods average = new OtherMethods();
int[] number = null;
OtherMethods.average(number, 0);
System.out.println(number);
}
}
So as you can see I'm all over the place. It's largely a patchwork of examples I've tried to apply.
This is the Sort code I'm using. Adhering my variables to the ones used here would be advantageous, of course, but I'm just not sure where to begin.
//Ascending Sort Method
public static void sort(int[] score, int number)
{
for(i=0; i < num-1; i++) //For each sublist
{
min = list[i];
position = i;
for (j=i+1; j < num; j++) //Find minimum
{
if (list[j] < min)
{
min = list[j];
position = j;
}
}
temp = list[position]; //Swap
list[position] = list[i];
list[i] = temp;
}
}
Any help would be greatly appreciated.
If you're using Java 8+, Check out the functional streams and in particular IntStream.
For Example, to min/max/average:
int min = IntStream.of(score)
.min(); // or .max() or .average()
and to sort:
score = IntStream.of(score)
.sorted()
.toArray();
If your trying to sort the numbers you can do something as simple as the bubble sort, which is fairly strait forward compare n to n+1 and switch if need be:
void bubbleSort(int ar[])
{
for (int i = (ar.length - 1); i >= 0; i--)
{
for (int j = 1; j ≤ i; j++)
{
if (ar[j-1] > ar[j])
{
int temp = ar[j-1];
ar[j-1] = ar[j];
ar[j] = temp;
} } } }
or like you did above the selection sort:
void selectionSort(int[] ar){
for (int i = 0; i ‹ ar.length-1; i++)
{
int min = i;
for (int j = i+1; j ‹ ar.length; j++)
if (ar[j] ‹ ar[min]) min = j;
int temp = ar[i];
ar[i] = ar[min];
ar[min] = temp;
} }
Another thing the way you currently have this set up your getNumber() function has no real use seeing that your number variable is global to begin with.
If you want more help you will have to come up with an actual question.
I've been trying to solve this rather easy problem on SPOJ: http://www.spoj.com/problems/HS08PAUL/.
It requires the number of prime numbers (less than n) which can be expressed in the form x^2+y^4 (where x and y are integers) to be found out.
I've whipped up a brute force solution which takes up quite a while for (n ~= 1000000), resulting in a TLE (time limit exceeded) error being thrown by the engine. Here's the source code:
import java.io.*;
import java.util.*;
class HS08PAUL {
public static int[] sieve(int n){
boolean[] prime = new boolean[n+1];
int[] primeNumbers = new int[n];
int index = 0;
Arrays.fill(primeNumbers, 0);
Arrays.fill(prime,true);
prime[0] = false;
prime[1] = false;
int m = (int)Math.sqrt(n);
for(int i = 2; i <= m; i++){
if(prime[i])
for(int k = i*i; k<=n; k+=i)
prime[k] = false;
}
for(int j = 2; j <= n; j++) {
if(prime[j]) {
primeNumbers[index] = j;
index++;
}
}
return primeNumbers;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
try{
double numberOfTestCases = in.nextDouble();
while(numberOfTestCases -- > 0) {
int index = 0, y = 0, count = 0;
int num = in.nextInt();
int[] primes = sieve(num);
while(index < num/3 ) {
for(y = 1; y < 57 ; y ++) {
if(Math.ceil(Math.sqrt(primes[index] - Math.pow(y,4))) == Math.floor(Math.sqrt(primes[index] - Math.pow(y,4)))) {
count++;
break;
}
}
index++;
}
System.out.println(count);
}
}
catch(Exception e) {
}
}
}
Is there a way in which I can make this approach work?
P.S.:Please ignore the unruly exception handling.
How many numbers of the form x^2+y^4 are there below 1000000? How many prime numbers are there below 1000000? What do these two numbers tell you about how you should approach the solution?
#isnot2bad's comment is also relevant.
I am wondering why my code keeps having this "time limit exceed" on the uva-online judge page (http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2511), it is supposed to execute in 1 second but I don't know which input they use (my code works and do exactly what it supposed).. I am wondering that maybe the while loop of the testCases have something to do, because when I remove it it says wrong answer.. this is my code:
public class Main {
private static final int TAM = 10000; // TAM equals to the posible numbers of houses
private static int[] auxHouses;
private static int nHouses[];
private static int testCases;
private static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
nHouses = new int[TAM];
// First we read the input
// Read the variable of testCases
testCases = scanner.nextInt();
while (testCases > 0) {
float sol = binarySearch(testCases);
System.out.println(sol);
testCases--;
}
}
public static float binarySearch(int tC) {
int routers = 0, houses = 0;
int pivot = 0;
int hi = 0;
// While for the testCases
routers = scanner.nextInt();
houses = scanner.nextInt();
// Read the numbers of the houses
for (int i = 0; i < houses; i++) {
nHouses[i] = scanner.nextInt();
}
if (routers >= houses) {
return 0;
}
// First we sort the array
sortHouses(nHouses, houses);
// Prepare the variables of the index
int lo = 0;
hi = 2 * (nHouses[houses - 1] - nHouses[0] + 1); // 2*(loc[h-1]-loc[0]+1);
// Now we execute the binary search algorithm
while (hi > lo) {
pivot = (lo + hi) / 2;
int start = nHouses[0];
int need = 1;
for (int i = 0; i < houses; i++) {
if (nHouses[i] > start + pivot) {
start = nHouses[i];
need++;
}
}
if (need > routers) {
lo = pivot + 1;
} else {
hi = pivot;
}
}
return (float) hi / 2;
}
public static void sortHouses(int[] nhouses, int length) {
// First we check if the are actually values on the array
if (nhouses.length == 0) {
return;
}
// Copy the array of int into an auxiliary variable and the numbers of
// int in the array
auxHouses = nhouses;
int lengthArray = length;
quickSort(0, lengthArray - 1);
}
public static void quickSort(int low, int high) {
// System.out.println("Array " + Arrays.toString(auxHouses));
int i = low, j = high;
// Get the pivot element from the middle of the list
int pivot = auxHouses[low + (high - low) / 2];
// Divide into two lists
while (i <= j) {
// If the current value from the left list is smaller then the pivot
// element then get the next element from the left list
while (auxHouses[i] < pivot) {
i++;
}
// If the current value from the right list is larger then the pivot
// element then get the next element from the right list
while (auxHouses[j] > pivot) {
j--;
}
// If we have found a values in the left list which is larger then
// the pivot element and if we have found a value in the right list
// which is smaller then the pivot element then we exchange the
// values.
// As we are done we can increase i and j
if (i <= j) {
exchange(i, j);
i++;
j--;
}
}
// Recursion
if (low < j)
quickSort(low, j);
if (i < high)
quickSort(i, high);
}
private static void exchange(int i, int j) {
int temp = auxHouses[i];
auxHouses[i] = auxHouses[j];
auxHouses[j] = temp;
}
}
I have it with the quicksort implemented, but if you use Arrays.sort(..) method instead it says the same thing..TLE, what could be doing wrong?
I'm having trouble combining these two algorithms together. I've been asked to modify Binary Search to return the index that an element should be inserted into an array. I've been then asked to implement a Binary Insertion Sort that uses my Binary Search to sort an array of randomly generated ints.
My Binary Search works the way it's supposed to, returning the correct index whenever I test it alone. I wrote out Binary Insertion Sort to get a feel for how it works, and got that to work as well. As soon as I combine the two together, it breaks. I know I'm implementing them incorrectly together, but I'm not sure where my problem lays.
Here's what I've got:
public class Assignment3
{
public static void main(String[] args)
{
int[] binary = { 1, 7, 4, 9, 10, 2, 6, 12, 3, 8, 5 };
ModifiedBinaryInsertionSort(binary);
}
static int ModifiedBinarySearch(int[] theArray, int theElement)
{
int leftIndex = 0;
int rightIndex = theArray.length - 1;
int middleIndex = 0;
while(leftIndex <= rightIndex)
{
middleIndex = (leftIndex + rightIndex) / 2;
if (theElement == theArray[middleIndex])
return middleIndex;
else if (theElement < theArray[middleIndex])
rightIndex = middleIndex - 1;
else
leftIndex = middleIndex + 1;
}
return middleIndex - 1;
}
static void ModifiedBinaryInsertionSort(int[] theArray)
{
int i = 0;
int[] returnArray = new int[theArray.length + 1];
for(i = 0; i < theArray.length; i++)
{
returnArray[ModifiedBinarySearch(theArray, theArray[i])] = theArray[i];
}
for(i = 0; i < theArray.length; i++)
{
System.out.print(returnArray[i] + " ");
}
}
}
The return value I get for this when I run it is 1 0 0 0 0 2 0 0 3 5 12. Any suggestions?
UPDATE: updated ModifiedBinaryInsertionSort
static void ModifiedBinaryInsertionSort(int[] theArray)
{
int index = 0;
int element = 0;
int[] returnArray = new int[theArray.length];
for (int i = 1; i < theArray.lenght - 1; i++)
{
element = theArray[i];
index = ModifiedBinarySearch(theArray, 0, i, element);
returnArray[i] = element;
while (index >= 0 && theArray[index] > element)
{
theArray[index + 1] = theArray[index];
index = index - 1;
}
returnArray[index + 1] = element;
}
}
Here is my method to sort an array of integers using binary search.
It modifies the array that is passed as argument.
public static void binaryInsertionSort(int[] a) {
if (a.length < 2)
return;
for (int i = 1; i < a.length; i++) {
int lowIndex = 0;
int highIndex = i;
int b = a[i];
//while loop for binary search
while(lowIndex < highIndex) {
int middle = lowIndex + (highIndex - lowIndex)/2; //avoid int overflow
if (b >= a[middle]) {
lowIndex = middle+1;
}
else {
highIndex = middle;
}
}
//replace elements of array
System.arraycopy(a, lowIndex, a, lowIndex+1, i-lowIndex);
a[lowIndex] = b;
}
}
How an insertion sort works is, it creates a new empty array B and, for each element in the unsorted array A, it binary searches into the section of B that has been built so far (From left to right), shifts all elements to the right of the location in B it choose one right and inserts the element in. So you are building up an at-all-times sorted array in B until it is the full size of B and contains everything in A.
Two things:
One, the binary search should be able to take an int startOfArray and an int endOfArray, and it will only binary search between those two points. This allows you to make it consider only the part of array B that is actually the sorted array.
Two, before inserting, you must move all elements one to the right before inserting into the gap you've made.
I realize this is old, but the answer to the question is that, perhaps a little unintuitively, "Middleindex - 1" will not be your insertion index in all cases.
If you run through a few cases on paper the problem should become apparent.
I have an extension method that solves this problem. To apply it to your situation, you would iterate through the existing list, inserting into an empty starting list.
public static void BinaryInsert<TItem, TKey>(this IList<TItem> list, TItem item, Func<TItem, TKey> sortfFunc)
where TKey : IComparable
{
if (list == null)
throw new ArgumentNullException("list");
int min = 0;
int max = list.Count - 1;
int index = 0;
TKey insertKey = sortfFunc(item);
while (min <= max)
{
index = (max + min) >> 1;
TItem value = list[index];
TKey compKey = sortfFunc(value);
int result = compKey.CompareTo(insertKey);
if (result == 0)
break;
if (result > 0)
max = index - 1;
else
min = index + 1;
}
if (index <= 0)
index = 0;
else if (index >= list.Count)
index = list.Count;
else
if (sortfFunc(list[index]).CompareTo(insertKey) < 0)
++index;
list.Insert(index, item);
}
Dude, I think you have some serious problem with your code. Unfortunately, you are missing the fruit (logic) of this algorithm. Your divine goal here is to get the index first, insertion is a cake walk, but index needs some sweat. Please don't see this algorithm unless you gave your best and desperate for it. Never give up, you already know the logic, your goal is to find it in you. Please let me know for any mistakes, discrepancies etc. Happy coding!!
public class Insertion {
private int[] a;
int n;
int c;
public Insertion()
{
a = new int[10];
n=0;
}
int find(int key)
{
int lowerbound = 0;
int upperbound = n-1;
while(true)
{
c = (lowerbound + upperbound)/2;
if(n==0)
return 0;
if(lowerbound>=upperbound)
{
if(a[c]<key)
return c++;
else
return c;
}
if(a[c]>key && a[c-1]<key)
return c;
else if (a[c]<key && a[c+1]>key)
return c++;
else
{
if(a[c]>key)
upperbound = c-1;
else
lowerbound = c+1;
}
}
}
void insert(int key)
{
find(key);
for(int k=n;k>c;k--)
{
a[k]=a[k-1];
}
a[c]=key;
n++;
}
void display()
{
for(int i=0;i<10;i++)
{
System.out.println(a[i]);
}
}
public static void main(String[] args)
{
Insertion i=new Insertion();
i.insert(56);
i.insert(1);
i.insert(78);
i.insert(3);
i.insert(4);
i.insert(200);
i.insert(6);
i.insert(7);
i.insert(1000);
i.insert(9);
i.display();
}
}