I am currently implementing a generic version of the longest increasing subsequence problem in Java. The method works as intended, but when I try to use Comparable[] instead of Integer[] (or int[]), the program won't compile. The error given is "Comparable cannot be cast to Integer". I understand the error and what it means, but I don't know how to fix it. Any help would be greatly appreciated :)
I have already tried making the method's return type a generic (>), but the problem is that Java does not allow generic array creation. I've tried just using Integer[] as my return type, and while that compiles and works properly, it's not what I want.
public class LIS {
public static void main(String[] args) {
final Integer[] arr = {-1, 2, 4, 2, 33, 4, 7, 8, 10, 7, 5, 4, 5, 5, 1};
final Integer[] LIS = (Integer[]) lis(arr);
for (int i : LIS) {
System.out.print(i + " ");
}
}
public static Comparable[] lis(Comparable[] arr) {
// We use Comparable[] so we can use interchangably with any Comparable type
final int N = arr.length;
// Java conveniently initializes array values to 0:
int[] lisEndingHere = new int[N];
for (int i = 0; i < N; i++) {
lisEndingHere[i] = 1;
int curMax = 0;
for (int j = 0; j <= i; j++) {
if (arr[i].compareTo(arr[j]) <= 0) continue;
if (lisEndingHere[j] > curMax) {
curMax = lisEndingHere[j];
}
}
lisEndingHere[i] += curMax;
}
// Find and return the longest increasing subsequence:
int max = 0;
for (int i = 0; i < N; i++) {
if (lisEndingHere[i] > max) max = lisEndingHere[i];
}
Comparable[] LIS = new Comparable[max];
for (int i = N-1; i >= 0 && max != 0; i--) {
if (lisEndingHere[i] == max) {
LIS[--max] = arr[i];
}
}
return LIS;
}
}
Just change the line
final Integer[] LIS = (Integer[]) lis(arr);
to
final Comparable[] LIS = lis(arr);
and also update the for loop.
Your method returns a Comparable array, so you cant downcast to an Integer array, but since the implementation of your numbers are Integers, they are still treated as such during runtime.
Setting the result to an Integer array is against the purpose of making a generic method anyways. For something to be passed to your method, it must have a compareTo method, and inherently has a toString method, and that satisfies everything you need the program to do.
There is nothing to fix here. Here:
Integer[] LIS = (Integer[]) lis(...)
Your method lis() returns an array of Comparable objects. A Comparable array isn't an Integer array! Thus that cast can't work conceptually.
Yes, that array contains Integer objects, but the array type isn't "array of integer".
You would have to iterate the resulting array, then you can cast the individual entries. But you can't cast the array type itself into something that it isn't!
Beyond that, you could use generics with lists instead.
Related
I am trying to get pass a coding challenge. The goal is to remove duplicate (after a defined 'n-th' time) from the array.
For example,
int[] arr;
arr = new int[] {1, 2, 2, 3, 3, 3, 4, 5, 5};
arr = tester(arr,1);//return 1,4. anything having more then 1 occurrence is removed from the //array
I have 2 questions here.
I understand that although java is mainly call by value,
more detail: https://stackoverflow.com/questions/12757841/are-arrays-passed-by-value-or-passed-by-reference-in-java#:~:text=Longer%20answer%3A,object%20that%20the%20caller%20sees.
and
Is Java "pass-by-reference" or "pass-by-value"?
.
so am I not able to modify/return the value of arr without re-assigning it as I need to use the "new" keyword later on.
example:
I am not able to do the following:
tester(arr,1) //return the original value, as the method has a "new" when converting the
//arraylist into array. There seems to be no work around for this as well..
I am also only passing 2 out of 10 test case in the coding challenge, I am not very sure why. I have also attempted to error handle with string inputs, or length=0 or null, to no success. (or implemented it in hashmap for sake of time complexity)
It does not seem like my logic has an issue, I am just not sure what are the test case as it is hidden.
I believe part of the challenge requires me to return it in the original array, meaning changing the value of arr itself, but i cant find a way to do it without using the new keyword.
Any ideas anyone?
public static int[] tester(int[] data, int n)
{
ArrayList<Integer> storeNon_dup = new ArrayList<Integer>();
//nested for loop to run through the array
//store in arrayList if criteria valid
for(int i = 0; i < data.length; i++)
{
int counter = 0;
for(int j = 0; j< data.length; j++)
{
if(data[i] == data[j])
{
counter++;
}
}
//if not duplicate in n-th occurence, add to list
if(counter<=n)
{
storeNon_dup.add(data[i]);
}
}
//convert arraylist to array
int[] container = new int[storeNon_dup.size()];
for(int i = 0; i<storeNon_dup.size(); i++)
{
container[i] = storeNon_dup.get(i);
}
return container;
}
Alternate solution by using HashMap.
public static List tester(int[] data, int n) {
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
for(int i=0; i<data.length; i++) {
if(map.containsKey(data[i])) {
map.put(data[i], map.get(data[i])+1);
}else {
map.put(data[i], 1);
}
}
List lst = new ArrayList<Integer>();
for(Integer key : map.keySet()) {
if(map.get(key)<=n) {
lst.add(key);
}
}
return lst;
}
For my assignment, I need to write a method that returns the number of cows (see definition below) found between 2 arrays. If the input arrays have a different number of elements, then the method should throw an IllegalArgumentException with an appropriate message.
A bull is a common number in int arrays found at the same position while a cow is a common number in int arrays found at different position. Note that if a number is already a bull, it cannot be considered as a cow.
For example, considering the following arrays:
int[] secret = {2, 0, 6, 9};
int[] guessOne = {9, 5, 6, 2};
int[] guessTwo = {2, 0, 6, 2};
int[] guessThree = {1, 2, 3, 4, 5, 6};
int[] guessFour = {1, 3, 4, 4, 0, 5};
1) getNumOfCows(secret, guessOne) returns 2
2) getNumOfCows(secret, guessTwo) returns 0
3) getNumOfCows(secret, guessThree) returns an exception
4) getNumOfCows(guessThree, guessFour) returns 2
My method seen below works perfectly for examples 1 and 3, but there is a problem with examples 2 and 4 such that getNumOfCows(secret, guessTwo) returns 1 instead of 0 because the element at secret[0] and guessTwo[3] is considered a cow. Could anybody help me fix my code?
// A method that gets the number of cows in a guess --- TO BE FIXED
public static int getNumOfCows(int[] secretNumber, int[] guessedNumber) {
// Initialize and declare a variable that acts as a counter
int numberOfCows = 0;
// Initialize and declare an array
int[] verified = new int[secretNumber.length];
if (guessedNumber.length == secretNumber.length) {
// Loop through all the elements of both arrays to see if there is any matching digit
for (int i = 0; i < guessedNumber.length; i++) {
// Check if the digits represent a bull
if (guessedNumber[i] == secretNumber[i]) {
verified[i] = 1;
}
}
for (int i = 0; i < guessedNumber.length; i++) {
// Continue to the next iteration if the digits represent a bull
if (verified[i] == 1) {
continue;
}
else {
for (int j = 0; j < secretNumber.length; j++) {
if (guessedNumber[i] == secretNumber[j] && i != j) {
// Update the variable
numberOfCows++;
verified[i] = 1;
}
}
}
}
}
else {
// Throw an IllegalArgumentException
throw new IllegalArgumentException ("Both array must contain the same number of elements");
}
return numberOfCows;
}
First go through and mark all bulls using a separate array to make sure a position that is a bull also get counted as a cow
public static int getNumOfCows(int[] secretNumber, int[] guessedNumber) {
int max = secretNumber.length;
int cows = 0;
int[] checked = new int[max];
for (int i = 0; i < max; i++) {
if (secretNumber[i] == guessedNumber[i]) {
checked[i] = 1;
}
}
for (int i = 0; i < max; i++) {
if (checked[i] == 1) {
continue;
}
for (int j = 0; j < max; j++) {
if (secretNumber[i] == guessedNumber[j]) {
cows++;
checked[i] = 1;
}
}
}
return cows;
}
Now that this answer is accepted the original question can be voted to be closed as a duplicate
I am posting my answer from a duplicate question here and if this get approved then the other one can get closed as a duplicate.
The problem is that an element that is multiple times in at least one array will not be handled correctly.
A possible solution idea might be this one:
Create a cow list.
Iterate through both arrays and add every element that is in both arrays and has not been added yet. (note: complexity is n²)
Now that all possible cows are in the list, iterate through the array positions with the same index and if you find a bull, remove the number from the cow list.
Now the cow list contains only cows.
This solution might be a bit slower than your current one, but I think it's working properly.
public static void main(String[] args) {
int[] HwArray = new int[10];
for (int i = 0; i < HwArray.length; i++) {
HwArray[i] = i;
}
int count = 0;
for (int i = 0; i < HwArray.length; i++){
HwArray[i] = (int) (100 + Math.random() * 100);
System.out.print("HwArray[i]=" + HwArray[i]);
}
}
{
int[] reverse(int[] HwArray); {
int[] reversed = new int[HwArray.length];
for (int i=0; i<HwArray.length; i++) {
reversed[i] = HwArray[HwArray.length - 1 - i];
}
return reverse;
}
}
}
Sorry, I'm still learning. I'm trying to reverse the order of all the elements, but I keep receiving an error. Am I doing something wrong?
To be honest, you're actually not that far off. The reverse function actually seems to work okay but you have all kinds of weird syntax errors and you're not even calling the reverse method. Try doing this:
Move the reverse method inside the class where main is defined. If you want to call it directly from main you'll have to make it an static method.
Get rid of the extra curly braces on lines 17 and 25.
Remove the semicolon on line 18 when declaring reverse. It shouldn't be there.
The reverse method is trying to return a variable called reverse. That's the name of the method, you can't do that. I think you meant to return reversed.
Actually call the reverse method after you have initialized the array with random numbers. Then print the array out again to verify that it worked.
Notice that you're not actually printing out the values of the array on line 11. That should be System.out.println("HwArray[" + i + "]=" + HwArray[i]);
I think the conceptually easiest way to reverse the order of elements in an array is to swap each ith element in the first half of the array of size N with the N-ith element in the second half:
int[] reversed = new int[10];
for (int i=0; i < HwArray.length/2; ++i) {
reversed[i] = HwArray[HwArray.length-1-i];
reversed[HwArray.length-1-i] = HwArray[i];
}
Demo here:
IDEOne
There are many errors:
First of all, it should be return reversed instead of return reverse.
Then, you cannot define any method inside a method(here, method reverse is defined inside the main method)
Then, you can do one thing, remove the following two braces:
1: The opening brace just before int[] reverse(int[] HwArray)
2: The closing brace in the last line
Last, it should be int[] reverse(int[] HwArray) { instead of int[] reverse(int[] HwArray); {
Comparator<Integer> comparator = new Comparator<Integer>() {
#Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
};
// option 1
Integer[] array = new Integer[] { 11, 44, 4, 3, 123 };
Arrays.sort(array, comparator);
// option 2
int[] array2 = new int[] {11, 44, 4, 3, 123};
List<Integer>list = Ints.asList(array2);
Collections.sort(list, comparator);
array2 = Ints.toArray(list);
// option 3
List<Integer> integersList = Ints.asList(arr);
Collections.sort(integersList, Collections.reverseOrder());
Let's say I have an array in the length of n, and the only values that can appear in it are 0-9. I want to create a recursive function that returns the number of different values in the array.
For example, for the following array: int[] arr = {0,1,1,2,1,0,1} --> the function will return 3 because the only values appearing in this array are 0, 1 and 2.
The function receives an int array and returns int
something like this:
int numOfValues(int[] arr)
If you are using Java 8, you can do this with a simple one-liner:
private static int numOfValues(int[] arr) {
return (int) Arrays.stream(arr).distinct().count();
}
Arrays.stream(array) returns an IntStream consisting of the elements of the array. Then, distinct() returns an IntStream containing only the distinct elements of this stream. Finally, count() returns the number of elements in this stream.
Note that count() returns a long so we need to cast it to an int in your case.
If you really want a recursive solution, you may consider the following algorithm:
If the input array is of length 1 then the element is distinct so the answer is 1.
Otherwise, let's drop the first element and calculate the number of distinct elements on this new array (by a recursive call). Then, if the first element is contained in this new array, we do not count it again, otherwise we do and we add 1.
This should give you enough insight to implement this in code.
Try like this:
public int myFunc(int[] array) {
Set<Integer> set = new HashSet<Integer>(array.length);
for (int i : array) {
set.add(i);
}
return set.size();
}
i.e, add the elements of array inside Set and then you can return the size of Set.
public int f(int[] array) {
int[] counts = new int[10];
int distinct = 0;
for(int i = 0; i< array.length; i++) counts[array[i]]++;
for(int i = 0; i< counts.length; i++) if(counts[array[i]]!=0) distinct++;
return distinct;
}
You can even change the code to get the occurrences of each value.
You can try following code snippet,
Integer[] arr = {0,1,1,2,1,0,1};
Set<Integer> s = new HashSet<Integer>(Arrays.asList(arr));
Output: [0, 1, 2]
As you asked for a recursive implementation, this is one bad way to do that. I say bad because recursion is not the best way to solve this problem. There are other easier way. You usually use recursion when you want to evaluate the next item based on the previously generated items from that function. Like Fibonacci series.
Ofcourse you will have to clone the array before you use this function otherwise your original array would be changed (call it using countDistinct(arr.clone(), 0);)
public static int countDistinct(int[] arr, final int index) {
boolean contains = false;
if (arr == null || index == arr.length) {
return 0;
} else if (arr.length == 1) {
return 1;
} else if (arr[index] != -1) {
contains = true;
for (int i = index + 1; i < arr.length; i++) {
if (arr[index] == arr[i]) {
arr[i] = -1;
}
}
}
return countDistinct(arr, index + 1) + (contains ? 1 : 0);
}
int numOfValues(int[] arr) {
boolean[] c = new boolean[10];
int count = 0;
for(int i =0; i < arr.length; i++) {
if(!c[arr[i]]) {
c[arr[i]] = true;
count++;
}
}
return count;
}
I have looked around Stack Overflow and did some work myself with this code but doesn't matter whatever I do the answer prints to false but it has to print to true, also how can I Plot their running times as a function of their input size as scatter plots and then choose representative values of the size n, and run at least 5 tests for each size value n in the tests?
PrefixAverages1
import java.util.Arrays;
public class PrefixAverages1 {
static double array[] = new double[10];
public static void prefixAverages(){
for (int i = 0; i < 10; i++){
double s = array[i];
for (int j = 0; j < 10; j++){
s = s + array[j];
}
array[i] = s / (i + 1);
System.out.println(Arrays.toString(array));
}
}
public static double[] prefixAverages(double[] inArray) {
double[] outArray = new double[inArray.length];
return outArray;
}
public static void main(String... args) {
System.out.println(
Arrays.equals(
prefixAverages(new double[] {5, 6, 7, 8}),
new double[] {2, 2.5, 3.5, 4}
)
);
}
}
PrefixAverages2
import java.util.Arrays;
public class PrefixAverages2 {
static double array[] = new double[10];
public static void prefixAverages(){
double s = 0;
for (int i = 0; i < 10; i++){
s = s + array[i];
array[i] = s / (i + 1);
}
array[0] = 10;
System.out.println(Arrays.toString(array));
}
public static double[] prefixAverages(double[] inArray) {
double[] outArray = new double[inArray.length];
return outArray;
}
public static void main(String... args) {
System.out.println(
Arrays.equals(
prefixAverages(new double[] {3, 4, 5, 6}),
new double[] {2, 3.5, 4, 5}
)
);
}
}
First you must understand what Arrays.equals() method does. The Arrays.equals() method does comparison operation on two arrays, based on their content; not based on their size. First of all, let's look at your prefixAverages(float [] inArray) method. What you did there is just create a new float array of size equals to the size of the passing array, and then return that newly created array. And in the main method, you are comparing the returning array and a new array that you are supplying. But this is logically not correct. Since the returning array is an empty array; the Arrays.equals() method returns false, as the other array has some values in it. Even if the returning array do have some values, the Arrays.equals() method returns false if both contain different values. Always remember two arrays are equal if and only if they contain same values and the elements should be in the same order. ** Modify your program like this and it'll return **true
import java.util.Arrays;
public class PrefixAverages1 {
static double array[] = new double[10];
public static void prefixAverages(){
for (int i = 0; i < array.length; i++){
double s = array[i];
for (int j = 0; j < array.length; j++){
s = s + array[j];
}
array[i] = s / (i + 1);
System.out.println(Arrays.toString(array));
}
}
public static double[] prefixAverages(double[] inArray) {
double [] outArray = inArray;
return outArray;
}
public static void main(String... args) {
System.out.println(
Arrays.equals(
prefixAverages(new double[] {5, 6, 7, 8}),
new double[] {5, 6, 7,8}
)
);
}
}
One more thing. While using arrays in loop; always use array.length method to do comparison condition checking. Otherwise there is a high change of probability for an ArrayOutOfBoundsException condition.
I'm guessing because it's hard to understand what you are trying to do. But right now I'm not even sure how this code compiles, because you haven't defined any constructors, and you are (apparently attempting to) call a constructor (with the same name of a static class function, confusing AND bad form) with an array parameter. I'm guessing you meant to call the static method that takes a double[] parameter. (Right now, and here's the confusing part, it shouldn't compile because you should have to prefix the class name to call a static function.). Even that would fail, though, because that method returns an empty array of the same length of the input array. To top it all off, the "algorithm" section of your code is never even called.
I'd suggest just stepping through this in a debugger. That way you could see what the code is doing in real time and correct it if it's not what you meant.
Also, if you'd followed normal coding conventions (never name a function after the class; only constructors), it would be easier to spot errors like that.
Edit: I see how it compiles now. Still, naming the function after the class makes me think "constructor", along with everyone else on the planet.
The output you expect is incorrect; for the input 5, 6, 7, 8 the prefix average should be 5.0, 5.5, 6.0, 6.5.
After the first value 5, there has been one value (5). After the second value (6 + 5) there have been two values 11 (and 11 / 2 is 5.5). Then 6 (because 6+5+7 is 18) and 18/3 is 6. Finally 18+8 is 26 and 26/4 is 6.5
static double[] prefixAverages(double[] x) {
int len = x.length;
double[] arr = new double[len];
double sum = 0;
for (int i = 0; i < len; i++) {
sum += x[i];
arr[i] = sum / (i + 1);
}
System.out.println(Arrays.toString(arr));
return arr;
}