I am trying to find the the Longest Common Sub-sequence between two things of type comparable. I have the algorithm down, but I could like to add these items to a list via a recursion method call, but I do not know how I would add the last item to the list this way.
Here is my code:
public static <E extends Comparable<E>>List<E> getLongestCommonSubSeq(
List<E> x,
List<E> y )
{
int m = x.size() +1;
int n = y.size() +1;
String[][] b =new String [m][n];
int[][] c = new int[m][n];
for(int i=1;i<m;i++) {
c[i][0] = 0;
}
for(int j = 0;j<n;j++) {
c[0][j]= 0;
}
for(int i=1; i<m;i++) {
for(int j=1;j<n;j++) {
if(x.get(i).equals(y.get(j))) {
c[i][j] = c[i-1][j-1]+1;
b[i][j]="NW";
}
else if(c[i-1][j] >= c[i][j-1]) {
c[i][j]=c[i-1][j];
b[i][j]="N";
}
else {
c[i][j] = c[i][j-1];
b[i][j]= "W";
}
}
}
return getLCS( m,n, b, x );
}
public static <E extends Comparable<E>> List<E> getLCS(
int i,
int j,
String[][] b,
List<E> x )
{
if(i==0 || j ==0)
return null;
if(b[i][j].equals("NW")) {
// This can't be done because add returns a boolean type
return getLCS(i-1,j-1, b, x) .add(x.get(i));
}
if(b[i][j].equals("N")) {
return getLCS(i-1,j, b, x);
}
if(b[i][j].equals("W")) {
return getLCS(i, j-1, b, x);
}
return null;
}
public static <E extends Comparable<E>>List<E> getLCS(int i, int j, String[][] b, List<E> x){
List<E> ret = new ArrayList<E>();
if(i==0 || j ==0)
return ret;
if(b[i][j].equals("NW")) {
// This can't be done because add returns a boolean type
ret=getLCS(i-1,j-1, b, x);
ret.add(x.get(i));
}else if(b[i][j].equals("N")) {
ret = getLCS(i-1,j, b, x);
}else if(b[i][j].equals("W")) {
ret= getLCS(i, j-1, b, x);
}
return ret;
}
I was implementing it a little wrong
Related
class BubbleSort<T> extends ArraySort<T>
{
public void iSort(T[] inArray) {
int n = inArray.length;
int k;
for (int m = n; m >= 0; m--) {
for (int i = 0; i < n - 1; i++) {
k = i + 1;
if (compare(inArray[i], inArray[k])) {
T temp;
temp = inArray[i];
inArray[i] = inArray[k];
inArray[k] = temp;
}
}
}
print(inArray);
}
public static <T extends Comparable<T>> boolean compare(T a, T b) {
if (a.compareTo(b) > 0) {
return true;
} return false;
}
I'm getting (T extends comparable < T >, T extends comparable < T >) in the type bubblesort< T > is not applicable for the arguments (T,T) error!
The quick fix is telling me to change method compare(T,T)< T > to compare(T,T), but that wouldn't resolve my problem. It works perfectly fine when I enter in actual value of elements, for example, compare(3, 5) or compare("hi", "hello") instead of compare(inArray[i], inArray[k]).
I would appreciate it a lot if someone could explain why it's doing that and give me a solution.
You've already defined your class with a generic type T, so there's no point in declaring a separate one for the method:
class BubbleSort<T extends Comparable<T>> extends ArraySort<T> {
public void iSort(T[] inArray) {
int n = inArray.length;
int k;
for (int m = n; m >= 0; m--) {
for (int i = 0; i < n - 1; i++) {
k = i + 1;
if (compare(inArray[i], inArray[k])) {
T temp;
temp = inArray[i];
inArray[i] = inArray[k];
inArray[k] = temp;
}
}
}
print(inArray);
}
public static boolean compare(T a, T b) {
if (a.compareTo(b) > 0) {
return true;
}
return false;
}
}
Anyway, you should denote T extends Comparable<T> in the class declaration rather than in the method.
It is printing out a few permutations but the rest are null and I'm not sure why. I need to but all the permutations into String[] and I can't import any other package except for util.Arrays. Please help!
import java.util.Arrays;
public class DIE
{
public static String[] printPermutations(String s)
{
int l = s.length();
int f = factorial(l);
int count = 0;
String[] array = new String[f];
permute("", s, array, 0);
Arrays.sort(array);
return array;
}
private static String[] permute(String x, String s, String [] array, int count)
{
int l = s.length();
if (l == 0)
{
array[count] = (x + s);
}
for (int i = 0; i < l; i++)
{
permute(x + s.charAt(i), s.substring(0, i) +
s.substring(i +1, s.length()), array, count);
count++;
}
return array;
}
public static int factorial(int l)
{
if (l == 1)
{
return 1;
}
else
{
int result = l * factorial(l - 1);
return result;
}
}
/*
Do not edit anything below this comment.
*/
public static void main(String[] args)
{
String[] permutations = printPermutations(args[0]);
for(String p : permutations)
{
System.out.println(p);
}
}
}
Your count variable is wrong. Within the outermost call to permute("", "abc", ...) it is incremented only by one, even though the call to the next level permute("a", "bc", ...) creates two permutations!
There are two possible solutions:
Instead of a String[] to collect your result use a List<String>. Then you don't need to manually count the number of permutations.
let permute return the new count (instead of the result array, that one is never used anyway)
For permute to return the new count the method would look like this:
private static int permute(String x, String s, String [] array, int count)
{
int l = s.length();
if (l == 0)
{
array[count++] = x;
}
for (int i = 0; i < l; i++)
{
count = permute(x + s.charAt(i), s.substring(0, i) +
s.substring(i +1, s.length()), array, count);
}
return count;
}
Using a List<String> would need some more changes, but the permute function would be smaller:
public static List<String> printPermutations(String s)
{
int l = s.length();
int f = factorial(l);
List<String> result = new ArrayList<>(f);
permute("", s, result);
Collections.sort(result);
return result;
}
private static void permute(String x, String s, List<String> result)
{
int l = s.length();
if (l == 0)
{
result.add(x);
}
for (int i = 0; i < l; i++)
{
permute(x + s.charAt(i), s.substring(0, i) +
s.substring(i +1, s.length()), result);
}
}
And some small changes in the main method due to the changed result of printPermutations (IMHO a very bad named method: it prints out nothing, it creates the permutations together with a helper method)
I am developing a big example case for teaching generics. A group of classes and interfaces that mimic the collections class in Java. Here's one of the source files:
package edu.brandeis.cosi12b.listdemo;
public class ArrayList<E extends Comparable<E>> extends AbstractList<E> implements List<E> {
private E[] list;
private int size;
private int capacity;
public ArrayList() {
this(20);
}
#SuppressWarnings("unchecked")
public ArrayList(int initialCapacity) {
list = (E[]) (new Object[initialCapacity]);
size = 0;
capacity = initialCapacity;
}
public int capacity() {
return capacity;
}
public int size() {
return size;
}
public void add(E val) {
list[size] = val;
size++;
}
public String toString() {
StringBuffer s = new StringBuffer();
s.append("[");
for (int i = 0; i < size - 1; i++) {
s.append(list[i]);
s.append(", ");
}
s.append(list[size - 1]);
s.append("]");
return (s.toString());
}
public void set(int index, E value) {
expandIfNecessary(index);
for (int i = size; i > index; i--) {
list[i] = list[i - 1];
}
list[index] = value;
if (index > size)
size = index + 1;
}
#SuppressWarnings("unchecked")
private void expandIfNecessary(int index) {
if (index < capacity)
return;
int newCapacity = capacity * 2 + index;
E[] oldArray = list;
list = (E[]) (new Object[newCapacity]);
for (int i = 0; i < size; i++)
list[i] = oldArray[i];
capacity = newCapacity;
}
public E get(int index) {
if (index < 0 || index >= size)
throw new ArrayIndexOutOfBoundsException("i: " + index + " s: " + size);
return list[index];
}
public void remove(int index) {
for (int i = index; i < size; i++)
list[i] = list[i + 1];
size--;
}
public boolean isEmpty() {
return size() == 0;
}
public int indexOf(E value) {
for (int i = 0; i < size; i++) {
if (list[i] == value)
return i;
}
return -1;
}
public boolean contains(E value) {
return (indexOf(value) != -1);
}
#Override
public void add(int index, E value) {
// TODO Auto-generated method stub
}
}
When I run this in a test case I get this error. I know it's something pretty subtle and it exceeds my knowledge of Java.
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;
at edu.brandeis.cosi12b.listdemo.ArrayList.<init>(ArrayList.java:14)
at edu.brandeis.cosi12b.listdemo.ArrayList.<init>(ArrayList.java:9)
at edu.brandeis.cosi12b.listdemo.TestSuite.arrayListtest1(TestSuite.java:134)
at edu.brandeis.cosi12b.listdemo.TestSuite.runArrayListTests(TestSuite.java:15)
at edu.brandeis.cosi12b.listdemo.TestSuite.runAll(TestSuite.java:9)
at edu.brandeis.cosi12b.listdemo.ListDemo.runTests(ListDemo.java:13)
at edu.brandeis.cosi12b.listdemo.ListDemo.main(ListDemo.java:6)
Use
list = (E[]) new Comparable<?>[initialCapacity];
and
list = (E[]) (new Comparable<?>[newCapacity]);
Java doesn't have fully reified generics at runtime (it uses erasure), so it doesn't actually know what E is - only that it extends Comparable, so that is what the compiler inserts for the casts.
The bytecode generated by the compiler for your code looks like this if decompiled:
list (Comparable[]) new Object[initialCapacity];
which fails.
I am trying to use a generic method to sort an array. I am receiving an error on Lab6Sort(octArr); that says classname cannot be applied to Shape[].
public static void main(String[] args) {
Shape[] octArr = new Shape[10];
for(int i = 0; i < 10; i++){
octArr[i] = new L6MPerRegOct(Math.floor(Math.random() * 1000) / 10);
}
Lab6Sort(octArr);
}
.
.
public static <AnyType> void Lab6Sort (AnyType [] arr, Comparator<? super AnyType> cmp)
It seems that I need a second argument, but I am unsure what this should be.
Here is the complete code:
public class L6MPerRegOct extends Shape {
public static void main(String[] args) {
Shape[] octArr = new Shape[10];
for(int i = 0; i < 10; i++){
octArr[i] = new L6MPerRegOct(Math.floor(Math.random() * 1000) / 10);
}
Lab6Sort(octArr);
}
private double sideLength;
public L6MPerRegOct(double len){
sideLength = len;
}
public double area(){
return 2 * sideLength*sideLength * (1 + Math.sqrt(2));
}
public static <AnyType> void Lab6Sort (AnyType [] arr, Comparator<? super AnyType> cmp)
{
int j, minIndex, n = arr.length;
AnyType temp;
for ( int index = 0; index < n - 1; index++ ) {
minIndex = index;
for (j = index + 1; j < n; j++) {
if (cmp.compare(arr[index], arr[minIndex]) < 0)
minIndex = j;
}
if (minIndex != index) {
temp = arr[index];
arr[index] = arr[minIndex];
arr[minIndex] = temp;
}
}
public abstract class Shape implements Comparable<Shape>
{
public abstract double area( );
public abstract double perimeter( );
public int compareTo( Shape rhs )
{
double diff = area( ) - rhs.area( );
if( diff == 0 )
return 0;
else if( diff < 0 )
return -1;
else
return 1;
}
public double semiperimeter( )
{
return perimeter( ) / 2;
}
}
You need to pass it an instance of a Comparator, e.g.
Lab6Sort(octArr, new Comparator<Shape>() {
#Override
public int compare(Shape o1, Shape o2) {
return 0;
}
});
Or define the Comparator in a separate class, if you want to reuse it
public class ShapeComparator implements Comparator<Shape> {
#Override
public int compare(Shape o1, Shape o2) {
return 0;
}
}
class ShapeComparator implements Comparator<Shape> {
#Override
public int compare(Shape o1, Shape o2) {
return 0;
}
}
My merge sort doesn't seem to be working correctly. When I display the sorted list, it is not sorted and elements are added, where there is supposed to be 9 there is 49.
Anyone see where Im going wrong?
public static <E extends Comparable<E>> void mergeSort(List<E> A) {
int n = A.size();
if (n > 1) {
int half = n / 2;
List<E> B = copyPartialArray(A, 0, half);
List<E> C = copyPartialArray(A, half, n);
mergeSort(B);
mergeSort(C);
merge(B, C, A);
}
}
public static <E extends Comparable<E>> void merge(List<E> B, List<E> C, List<E> A) {
int n1 = B.size();
int n2 = C.size();
int i = 0;
int j = 0;
int k = 0;
while (i < n1 && j < n2) {
if (B.get(i).compareTo(C.get(j)) < 0) {
A.add(k, B.get(i));
i++;
}
else {
A.add(k, C.get(j));
j++;
}
k++;
}
if (i == n1)
for (int p = j; p < n2; p++) {
A.add(k, C.get(p)); k++;
}
else if (j == n2)
for (int p = i; p < n1; p++) {
A.add(k, B.get(p)); k++;
}
}
private static <E extends Comparable<E>> List<E> copyPartialArray(List<E> A, int first, int last) {
int n = last - first;
List<E> copy = new ArrayList<E>(n);
for (int i = 0; i < n; i++)
copy.add(i, A.get(first + i));
return copy;
}
This answer will try to make you realise what's wrong.
It's clear that mergeSort won't do anything to a one element array, but what happens if there are two (for instance [2,1])? You mention there are more elements than before in the result list (list A). Why? What's merge doing to that list? Hint.