Problem
I have a task that reads as follows:
Implement an IntegerList class with a Vector list object attribute that contains a collection of integers. Implement the findMedian () method which, for a given object from o of the IntegerList class, returns a number m from the vector o.list such that there are at least half of the numbers less than or equal to m, and the numbers greater than or equal to m are also at least half:
For example, for [1, 4, 1, 3, 5, 7] it will be the number 4, and for [1, 1, 1, 2, 2] it will be the number 1 and only 1. If the vector is empty then the method is supposed to throw an IllegalArgumentException exception.
What I tried?
import java.util.Vector;
public class IntegerList {
Vector<Integer> list =new Vector<Integer>();
public int findMedian(Vector<Integer>list){
if(list.size() ==0){
throw new IllegalArgumentException();
}
int result =0;
return result;
}
}
public class Main {
public static void main(String[] args){
IntegerList v = new IntegerList();
v.list.add(2);
v.list.add(3);
v.list.add(4);
v.list.add(9);
System.out.println(v.findMedian(v.list));
}
}
My question:
Why this not working?
What would you change to even better solve this problem?
It is working, but only on empty list. To make it work: we should apply what we learned ..and little try.
Voila:
public int findMedian(Vector<Integer> list) {
if (list == null || list.isEmpty()) {
throw new IllegalArgumentException("'list' is null or empty");
} // from here: list not null and list.size() > 0 ... :
// sort the "list":
java.util.Collections.sort(list); // if you may not modify the list: create a copy first! (the list remains sorted, also when leaving the method...
// return "middle" element:
return list.get(list.size()/2);
}
javadoc
Related
I have two ArrayLists array1 and array2.
In both ArrayLists there can be different numbers, but in array2 it's always just one number.
In an onClickListener I need the number of array2 to be deleted from array1.
For example:
ArrayList array1 = new Arraylist(2,1,4,6,3);
ArrayList array2 = new Arraylist(1);
Then I tried:
array1.remove(array2)
but nothing happens...
What is the best way to achieve that?
For Context:
I have three fragments, one where you can see your deck DeckKartenFragment and two where you can choose your card RadlerKarte and HopfentrunkKarte. I have two ImageViews, where you can put the chosen cards.
I want that each card can only be chosen once. For that I made two Arrays. One in which all chosen cards are deck.deck (Is stored in class deck) and one in which the current chosen card of the ImageView is deck1WelcheKarte.
//Check if card is already chosen//
if (deck.deck.contains(1) == true){
Toast.makeText(getActivity(), "example" , Toast.LENGTH_LONG).show();
deck.cardchosen.clear();
}
if (deck.deck.contains(1) == false){
deck.deck.add(1); //Add Card to deck//
deck.deck.removeAll(deck1WelcheKarte); //Remove card that was chosen before from deck//
deck1WelcheKarte.clear(); //Reset card that is chosen to current card//
deck1WelcheKarte.add(1);}}
Now if I chose my first card everything works fine, when I replace that card with a new one it still works. But when i replace that card again with my first card, the number for that first card seems to be still in deck, because my app goes to makeToast instead of add new card to deck...
for(int i : array2) {
array1.remove(i)
}
this way you dont have to chack if array2 contains any element, it also covers multiple elements
okey then try this code and copare it to yours:
public static void main(String[] args){
ArrayList<Integer> a = new ArrayList<>(6);
// ArrayList is kind of lacking right constructor so we have to insert values manually
for(int i : new int[]{1, 2, 3, 4, 5, 6}) {
a.add(i);
}
ArrayList<Integer> b = new ArrayList<>(1);
b.add(1);
// integer is important if we use int, it will remove by index
for(Integer i : b) {
a.remove(i);
}
System.out.println(a);
}
Following the previous answer, which is a good one, you have to change the type of your java.uti.ArrayList because Java Collections don't support primitive types.
Actually, when you try to add a primitive type element into the ArrayList, the value gets implicitly wrapped by an Object class of its own type, for example
This statement array1.add(1); -> It's same as -> array1.add(new Integer(1));
Here is an example to let you understand:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Test {
public static void main(String[] args) {
int myArray[] = { 2, 1, 4, 6, 3 };
List<Integer> arrayList1 = new ArrayList();
for (int elem : myArray) {
arrayList1.add(elem);
}
List<Integer> arrayList2 = new ArrayList();
arrayList2.add(2);
System.out.println("array of int: " + Arrays.toString(myArray));
System.out.println("arrayList2 (List of " + arrayList2.get(0).getClass().getName() + " ): " + arrayList2);
System.out.println("Before remove - arrayList1: " + arrayList1);
for (Object a : arrayList2) {
System.out.println("Removing element (type " + a.getClass().getName() + "): " + a);
arrayList1.remove(a);
}
System.out.println("After remove - arrayList1" + arrayList1);
}
}
Output is:
array of int: [2, 1, 4, 6, 3]
arrayList2 (List of java.lang.Integer ): [2]
Before remove - arrayList1: [2, 1, 4, 6, 3]
Removing element (type java.lang.Integer): 2
After remove - arrayList1[1, 4, 6, 3]
As you see from the code, I just printed out the name of the class which is used when you add any int to the java.util.List of Object, and they actually get wrapped by java.lang.Integer class.
I am trying to create a method that will recursively reverse an ArrayList of generics, and am running into issues with the declaration of my reversedList array (see line 4 of code below).
As the code stands, I receive the error:
cannot find symbol Class: E
The only way I have found to stop the error is by declaring reversedList inside the method, but then it will reset every time it recurses.
import java.util.ArrayList;
import java.util.List;
public class ListRecursive<E>{
public static List<E> reversedList= new ArrayList<E>();
public static <E> void reverse(ArrayList<E> inputList){
E firstitem = null;
if (inputList.size() == 0 ) {
return;
}
else {
firstitem = inputList.get(0);
inputList.remove(0);
}
reverse(inputList);
reversedList.add( firstitem );
}
Below is the main method, which creates an ArrayList of commmand line arguments and attempts to reverse it using the method above.
public static void main(String args[]){
ArrayList<String> argList = new ArrayList<>();
ArrayList<Double> numericArgs = new ArrayList<>();
for (String s : args) {
argList.add(s);
try {
numericArgs.add(Double.parseDouble(s));
}
catch (NumberFormatException e) {
System.out.println(e.getMessage() + "is not numeric...skipping");
}
}
System.out.print("Command line arguments before reversal: ");
for (int i=0; i<argList.size(); i++)
System.out.print(argList.get(i)+ " ");
System.out.println();
reverse(argList);
System.out.print("Command line arguments afterreversal: ");
for (int i=0; i<argList.size(); i++)
System.out.print(argList.get(i)+ " ");
System.out.println();
}
Presuming that you.
Wanted to do it recursively
Didn't want to destroy the original list.
And didn't want to allocate the new List external to the method.
You can do the following:
public static <E> List<E> reverse(List<E> inputList) {
List<E> ret = new ArrayList<>();
E o = inputList.remove(0);
if (inputList.size() > 0) {
ret = reverse(inputList);
}
// at this point they will be on the stack in reverse order.
// so add them to the stack in that order.
ret.add(o);
// return the orginal list to its initial state by inserting them at the beginning.
inputList.add(0, o);
return ret;
}
Calling with this.
List<Integer> ints = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
System.out.println(reverse(ints));
System.out.println(ints);
Produces this output.
[5, 4, 3, 2, 1]
[1, 2, 3, 4, 5]
A non-recursive solution would be, of course, trivial.
Note: The passed List must support List.remove() and be mutable for this to work. If you declare your list using List.of() or Arrays.asList() you must pass your list as an argument to the ArrayList<>() constructor.
First of all, if it's a utility method, why store the parameter, if not, then why is it static. You also don't need multiple instances, as method parameters in java are pass-by-reference. More importantly, recursive means your list will be limited to your call stack limit.
Try It Online
public static <E> void reverse(List<E> list) {
for (int i=0;i<list.size()/2;i++) {
E temp = list.get(i);
list.set(i, list.get(list.size()-i-1));
list.set(list.size()-i-1, temp);
}
}
This is a homework lab for school. I am trying to reverse a LinkedList, and check if it is a palindrome (the same backwards and forwards). I saw similar questions online, but not many that help me with this. I have made programs that check for palindromes before, but none that check an array or list. So, first, here is my isPalindrome method:
public static <E> boolean isPalindrome(Collection<E> c) {
Collection<E> tmp = c;
System.out.println(tmp);
Collections.reverse((List<E>) c);
System.out.println(c);
if(tmp == c) { return true; } else { return false; }
}
My professor wants us to set the method up to accept all collections which is why I used Collection and cast it as a list for the reverse method, but I'm not sure if that is done correctly. I know that it does reverse the list. Here is my main method:
public static void main(String...strings) {
Integer[] arr2 = {1,3,1,1,2};
LinkedList<Integer> ll2 = new LinkedList<Integer>(Arrays.asList(arr2));
if(isPalindrome(ll2)) { System.out.println("Successful!"); }
}
The problem is, I am testing this with an array that is not a palindrome, meaning it is not the same backwards as it is forwards. I already tested it using the array {1,3,1} and it works fine because that is a palindrome. Using {1,3,1,1,2} still returns true for palindrome, though it is clearly not. Here is my output using the {1,3,1,1,2} array:
[1, 3, 1, 1, 2]
[2, 1, 1, 3, 1]
Successful!
So, it seems to be properly reversing the List, but when it compares them, it assumes they are equal? I believe there is an issue with the tmp == c and how it checks whether they are equal. I assume it just checks if it contains the same elements, but I'm not sure. I also tried tmp.equals(c), but it returned the same results. I'm just curious is there is another method that I can use or do I have to write a method to compare tmp and c?
Thank you in advance!
Tommy
In your code c and tmp are links to same collection and tmp == c will be always true. Your must clone your collection to new instance, for example: List<E> tmp = new ArrayList(c);.
Many small points
public static <E> boolean isPalindrome(Collection<E> c) {
List<E> list = new ArrayList<>(c);
System.out.println(list);
Collections.reverse(list);
System.out.println(list);
return list.equals(new ArrayList<E>(c));
}
Reverse only works on an ordered list.
One makes a copy of the collection.
One uses equals to compare collections.
public static void main(String...strings) {
int[] arr2 = {1, 3, 1, 1, 2};
//List<Integer> ll2 = new LinkedList<>(Arrays.asList(arr2));
List<Integer> ll2 = Arrays.asList(arr2);
if (isPalindrome(ll2)) { System.out.println("Successful!"); }
}
You need to copy the Collection to a List / array. This has to be done, since the only ordering defined for a Collection is the one of the iterator.
Object[] asArray = c.toArray();
You can apply the algorithm of your choice for checking if this array is a palindrom to check, if the Collection is a palindrom.
Alternatively using LinkedList it would be more efficient to check, if the list is a palindrom without creating a new List to reverse:
public static <E> boolean isPalindrome(Collection<E> c) {
List<E> list = new LinkedList<>(c);
Iterator<E> startIterator = list.iterator();
ListIterator<E> endIterator = list.listIterator(list.size());
for (int i = list.size() / 2; i > 0; i--) {
if (!Objects.equals(startIterator.next(), endIterator.previous())) {
return false;
}
}
return true;
}
This is the follow up of compare sets
I have
Set<Set<Node>> NestedSet = new HashSet<Set<Node>>();
[[Node[0], Node[1], Node[2]], [Node[0], Node[2], Node[6]], [Node[3], Node[4], Node[5]] [Node[2], Node[6], Node[7]] ]
I want to merge the sets when there are two elements in common. For example 0,1,2 and 0,2,6 has two elements in common so merging them to form [0,1,2,6].
Again [0,1,2,6] and [2,6,7] has 2 and 6 common. so merging them and getting [0,1,2,6,7].
The final output should be :
[ [Node[0], Node[1], Node[2], Node[6], Node[7]], [Node[3], Node[4], Node[5]] ]
I tried like this :
for (Set<Node> s1 : NestedSet ) {
Optional<Set<Node>> findFirst = result.stream().filter(p -> { HashSet<Node> temp = new HashSet<>(s1);
temp.retainAll(p);
return temp.size() == 2; }).findFirst();
if (findFirst.isPresent()){
findFirst.get().addAll(s1);
}
else {
result.add(s1);
}
}
But the result I got was :
[[Node[0], Node[1], Node[2], Node[6], Node[7]], [Node[3], Node[4], Node[5]], [Node[0], Node[2], Node[6], Node[7]]]
Any idea ? Is there any way to get the desired output?
Some considerations:
Each time you apply a merge, you have to restart the procedure and iterate over the modified collection. Because of this, the iteration order of the input set is important, if you want your code to be deterministic you may want to use collections that give guarantees over their iteration order (e.g. use LinkedHashSet (not HashSet) or List.
Your current code has side effects as it modifies the supplied sets when merging. In general I think it helps to abstain from creating side effects whenever possible.
The following code does what you want:
static <T> List<Set<T>> mergeSets(Collection<? extends Set<T>> unmergedSets) {
final List<Set<T>> mergedSets = new ArrayList<>(unmergedSets);
List<Integer> mergeCandidate = Collections.emptyList();
do {
mergeCandidate = findMergeCandidate(mergedSets);
// apply the merge
if (!mergeCandidate.isEmpty()) {
// gather the sets to merge
final Set<T> mergedSet = Sets.union(
mergedSets.get(mergeCandidate.get(0)),
mergedSets.get(mergeCandidate.get(1)));
// removes both sets using their index, starts with the highest index
mergedSets.remove(mergeCandidate.get(0).intValue());
mergedSets.remove(mergeCandidate.get(1).intValue());
// add the mergedSet
mergedSets.add(mergedSet);
}
} while (!mergeCandidate.isEmpty());
return mergedSets;
}
// O(n^2/2)
static <T> List<Integer> findMergeCandidate(List<Set<T>> sets) {
for (int i = 0; i < sets.size(); i++) {
for (int j = i + 1; j < sets.size(); j++) {
if (Sets.intersection(sets.get(i), sets.get(j)).size() == 2) {
return Arrays.asList(j, i);
}
}
}
return Collections.emptyList();
}
For testing this method I created two helper methods:
static Set<Integer> set(int... ints) {
return new LinkedHashSet<>(Ints.asList(ints));
}
#SafeVarargs
static <T> Set<Set<T>> sets(Set<T>... sets) {
return new LinkedHashSet<>(Arrays.asList(sets));
}
These helper methods allow to write very readable tests, for example (using the numbers from the question):
public static void main(String[] args) {
// prints [[2, 6, 7, 0, 1]]
System.out.println(mergeSets(sets(set(0, 1, 2, 6), set(2, 6, 7))));
// prints [[3, 4, 5], [0, 2, 6, 1, 7]]
System.out.println(
mergeSets(sets(set(0, 1, 2), set(0, 2, 6), set(3, 4, 5), set(2, 6, 7))));
}
I'm not sure why you are getting that result, but I do see another problem with this code: It is order-dependent. For example, even if the code worked as intended, it would matter whether [Node[0], Node[1], Node[2]] is compared first to [Node[0], Node[2], Node[6]] or [Node[2], Node[6], Node[7]]. But Sets don't have a defined order, so the result is either non-deterministic or implementation-dependent, depending on how you look at it.
If you really want deterministic order-dependent operations here, you should be using List<Set<Node>>, rather than Set<Set<Node>>.
Here's a clean approach using recursion:
public static <T> Set<Set<T>> mergeIntersectingSets(Collection<? extends Set<T>> unmergedSets) {
boolean edited = false;
Set<Set<T>> mergedSets = new HashSet<>();
for (Set<T> subset1 : unmergedSets) {
boolean merged = false;
// if at least one element is contained in another subset, then merge the subsets
for (Set<T> subset2 : mergedSets) {
if (!Collections.disjoint(subset1, subset2)) {
subset2.addAll(subset1);
merged = true;
edited = true;
}
}
// otherwise, add the current subset as a new subset
if (!merged) mergedSets.add(subset1);
}
if (edited) return mergeIntersectingSets(mergedSets); // continue merging until we reach a fixpoint
else return mergedSets;
}
I saw similar questions that included an index in the parameters, but my requirements don't allow me to do that. Assume the array is already sorted in alphabetical order.
This is my first time asking a question so sorry if I did something wrong.
public void addElement(Object element){
LinkedListIterator iterator = new LinkedListIterator();
int counter = 1;
int compare = 0;
if(first == null)
iterator.add(element);
else
{
while(iterator.hasNext())
{
compare = getElement(counter).toString().compareToIgnoreCase(element.toString());
//getElement is a method I made to retrieve an element from the linked list
//I have tested it and I know it works. Its parameter is an index
//toString() returns a String of what the element is. example: { Fruit }
//It is in that format with the brackets {}
if(compare != -1)
iterator.add(element);
else
{
iterator.next();
counter++;
}
}
}
}
Based on your question, I don't know exactly what you're using as a comparison value. Is it a string value within the object, the name of the object reference, etc? Assuming that you're inserting an object based on some sort of name variable, this is how you could do it.
Note: I'm sure you can find some sort of existing method/api that does this for you, but I'm assuming you'd like to see how it's done.
For this example, I created a class called AnyObject to iterate and compare. It looks like this:
AnyObject class
public class AnyObject {
private String name;
private int num;
private String color;
public AnyObject(String name, int num, String color) {
this.name = name;
this.num = num;
this.color = color;
}
#Override
public String toString() {
return name;
}
}
Using this simple class, we would modify your code so it looks like this:
AlphaInsertSort Class
import java.util.*;
public class AlphaInsertSort {
public static void main(String[] args) {
ArrayList<AnyObject> myList = new ArrayList<AnyObject>();
myList.add(new AnyObject("alphaObj", 44, "blue"));
myList.add(new AnyObject("betaObj", 7, "orange"));
myList.add(new AnyObject("gammaObj", 12, "red"));
myList.add(new AnyObject("omegaObj", 99, "yellow"));
printList(myList); //helps visualize what's going on
addElement(new AnyObject("charlieObj", 105, "purple"), myList);
printList(myList);
addElement(new AnyObject("aObj", 105, "purple"), myList);
printList(myList);
myList.add(new AnyObject("thetaObj", 0, "green"));
printList(myList);
addElement(new AnyObject("zetaObj", 2, "pink"), myList);
printList(myList);
System.out.println("Finished");
}
public static void addElement(AnyObject element, ArrayList<AnyObject> myList){
ListIterator<AnyObject> iterator = null;
//int counter = 1; don't need this
int compare = 0;
AnyObject current = myList.get(0); //changed name from first to current and will use this for comparison while iterating
iterator = myList.listIterator(); //this should set iterator to start of list. There's no constructor for listIterator
System.out.println("\ncurrent is " + current.toString());
if(current == null)
iterator.add(element);
else
{
while(iterator.hasNext())
{
//compare = getElement(counter).toString().compareToIgnoreCase(element.toString());
compare = current.toString().compareToIgnoreCase(element.toString());
//for display purposes
System.out.println(current.toString() + " compared to " + element.toString() + " is " + current.toString().compareToIgnoreCase(element.toString()));
if(compare > 0) { //want to add element into list if compare is negative. Won't necessarily be -1
iterator.previous(); //will need to move back a spot before adding. Otherwise will always add element after first encountered element that doesn't come before element inserting
iterator.add(element);
break; //make sure to break. No need to continue iterating
}
else
{
current = iterator.next();
//counter++;
}
}
//if element is larger than all existing elements in list
if(!myList.contains(element)) {
iterator.add(element);
}
}
}
public static void printList(ArrayList<AnyObject> myList) {
System.out.println("List contents:");
for(AnyObject element : myList) {
System.out.println(element.toString());
}
System.out.println();
}
}
I removed the counter int because you mentioned in your instructions that you don't have the option to use an index, so there's really no point in including it. It's also worth noting that compareTo and compareToIgnoreCase don't necessarily return -1 and 1. It can return any positive and negative values, so changing your conditions would be smart. Also, compareTo returns a negative number if value that's calling the method is less than the value that it's being compared to, so you want to stop iterating and add the value when compare is negative. Also, since you don't have iterator that's 1 element ahead of the position you're currently at in your list, you need to move the iterator back 1 element when compare returns a negative integer. If you don't, your new element will always be added immediately AFTER the first element that comes after it alphabetically. This is because you can't see the next element immediately after the iterator. Does this make sense?
For instance, if you have a list of 1, 2, 4, 5, and you want to add 3 to it, you would compare 1 to 3, 2 to 3, then 4 to 3. When your iterator reaches 2, it doesn't know what the next value is. Since 3 is larger than 2, it moves on to 4. 4 is less than 3, so add(3) gets called. However, this places 3 after the element it's being compared to (4). Your list would then be 1, 2, 4, 3, 5. The easiest way to fix this is to call iterator.previous(); immediately before iterator.add(3);
Let me know if you'd like further clarification.