I am working on a homework assignment in which I need to write a method that takes a data array and removes the minimum item from it. I am able to find the minimum item, but I am having trouble removing it. My code is below.
public Comparable removeMin() {
Iterator<T> it = iterator();
T min = it.next();
while (it.hasNext()) {
T next = it.next();
if (min.compareTo(next) > 0)
min = next;
it.remove();
}
System.out.println(min);
return min;
}
I have the print statement there just to verify that it is in fact getting the minimum item.
The code in main looks like this.
public static void main(String[] args) {
Bag<String> sbag = new Bag<String>();
sbag.add("Noriko");
sbag.add("Peter");
sbag.add("Buddy");
sbag.add("Mary");
sbag.removeMin();
}
When I run the sbag.removeMin(); command, the console prints "Buddy" which tells me that it is choosing "Buddy" as the min item. However, if I instead populate sbag with integers, it always prints the smallest integer, which indicates to me I have my code correct in that regard.
I have two questions.
1). When passing a list of strings such as above, how does Java determine which is smallest?
2). How can I fix my code so that it not only finds the minimum item, but also removes it?
First, it compares String based on the integral value of the characters in the String (e.g. ASCII) (but it does that because String implements Comparable<String>). I think you meant to return the generic type T, and you should check for an empty Collection. Finally, you need to iterate twice. Once to find the min the second to remove it.
public T removeMin() {
Iterator<T> it = iterator();
T min = (it.hasNext()) ? it.next() : null;
while (it.hasNext()) {
T next = it.next();
if (min.compareTo(next) > 0) {
min = next;
}
}
it = iterator(); // <-- start again
while (it.hasNext()) {
T next = it.next();
if (min.compareTo(next) == 0) {
it.remove();
break;
}
}
System.out.println(min);
return min;
}
It's using the ASCII code. In numeric byte values, B is lower in value than anything else you've got there.
Andto get rid of it, use array[n]="";
Related
I am doing a programming challenge I found online and write a function to help me. The function determines if there is a set of integers in a row, excluding repeated middle numbers, that increase by one in a list and returns an ArrayList of Integer's with the position of the greater number and the position of the smaller number.
public static ArrayList<Integer> stuckSet(ArrayList<Integer> list){
int posIncrease = -1;
int posDecrease = -1;
boolean found = false;
for(Integer i=list.size()-1; i>0; i--){
if(list.get(i)+1 == list.get(i-1)){
Integer val = list.get(i);
posIncrease = i;
for(Integer j=i-1; j>=0; j--){
if(list.get(j) == val+2){
posDecrease = j;
j=-1;
found = true;
}
}
i = -1;
}
}
if(posDecrease != -1){
ArrayList<Integer> returnList = new ArrayList<Integer>();
returnList.add(posDecrease);
returnList.add(posIncrease);
return returnList;
}
else{
ArrayList<Integer> returnList = new ArrayList<Integer>();
returnList.add(-1);
returnList.add(-1);
return returnList;
}
}
This is then stored in a list and I call the .get() function on it later and use that output to remove another number from a list. This produces a compiler error, "incompatible types: Boolean cannot be converted to int". However, if I print it out I get the expected output, "0".
ArrayList<Integer> stuck = stuckSet(copyList);
int posOne = copyList.remove(stuck.get(0));
I have not been able to find a solution anywhere, what am I doing wrong.
Check out the ArrayList#remove(Object o) API and you'll see:
public boolean remove(Object o)
Removes the first occurrence of the specified element from this list, if it is present. If the list does not contain the element, it is unchanged. More formally, removes the element with the lowest index i such that Objects.equals(o, get(i)) (if such an element exists). Returns true if this list contained the specified element (or equivalently, if this list changed as a result of the call).
The error from the method here:
int posOne = copyList.remove(stuck.get(0));
makes sense since this method returns a boolean, not an int.
Regarding,
I have not been able to find a solution anywhere, what am I doing wrong
Your main mistake was not going to the Java API as your first step
Working with a list of Object where one of the item has an empty String. Trying to write method which would return a sorted list. By sorting means the first item value of the list should always be an empty String.
Since I don't want to manipulate the unsorted list, I am creating a new list to sort.
So far my code is:
private List<LoggerConfig> sort(List<LoggerConfig> unSortedList) {
List<LoggerConfig> sortedList = new ArrayList<LoggerConfig>(unSortedList);
//What to do here
return sortedList;
}
Looked at lot of SO posts but very confused.
You can trust the String.compareTo to match the order you seek. Here is a Comparator :
new Comparator<LoggerConfig>() {
#Override
public int compare(LoggerConfig o1, LoggerConfig o2) {
return (o1.getName().compareTo(o2.getName()));
}
};
or directly implementing Comparable in the specific class (here Dummy)
class Dummy implements Comparable<Dummy>{
String name;
public int compareTo(Dummy o) {
return this.name.compareTo(o.name);
}
}
The why :
The String.compareTo check the first characters of both to find a difference (until the smallest length of both), if they match, the lengths are use to make the difference, the longest will be after the shortest (shortest.compareTo(longuest) will return an negative value (the length difference)).
In this case, "".compareTo("abc"), there is no character in the empty String, so the first check is skipped and the length is use to compare the Strings, so an empty String will always be seen as first compare to any "non-empty" String
An example with the previous Dummy class (just need to add the Constructor Dummy(String):
public class Main {
public static void main(String[] args) {
List<Dummy> dummies = new LinkedList<Dummy>();
dummies.add(new Dummy("abc.com.core"));
dummies.add(new Dummy(""));
dummies.add(new Dummy("abc.com.core.def"));
System.out.println("BEFORE : " + dummies);
Collections.sort(dummies);
System.out.println("AFTER : " + dummies);
}
}
Output :
BEFORE : [abc.com.core, , abc.com.core.def]
AFTER : [, abc.com.core, abc.com.core.def]
You can place this condition in your comparator so that elements with an empty value are considered "less" than other elements, so that it shows up at the beginning of the sorted list. Try something like this:
Collections.sort(sortedList, new Comparator<LoggerConfig>() {
#Override
public int compare(LoggerConfig o1, LoggerConfig o2) {
if(o1.getName().isEmpty(){
return -1;
}
if(o2.getName().isEmpty(){
return 1;
}
return (o1.getName().compareTo(o2.getName()));
}
});
I didn't test this, but this should make the idea clear. If the empty element shows up at the end of the list, swap the -1 and the 1.
If your List is huge and sorting takes a lot of time, it might be a better idea to remove the empty element before sorting, then sort, then place the element at the beginning.
The Comparator solution seems feasible to me; what you're missing is implementing the compare method so that it does what you want.
Collections.sort(sortedList, new Comparator<LoggerConfig>() {
#Override
public int compare(LoggerConfig o1, LoggerConfig o2) {
if(o1.getName().equals("")){
return -1;
} else if(o2.getName().equals("")) {
return 1;
} else {
return (o1.getName().compareTo(o2.getName()));
}
}
});
As per Java docs, the Comparator has a compare method that returns an int which is
less than 0 if the first argument is less than the second
0 if the arguments are equal
greater than 0 if the first argument is greater than the second
So the Comparator you need should return the comparison of the two strings if they're both different from "", and -1 (or 1) if the first (or second) String is empty.
My problem is, when I output this code, it's not outputting what I want which is to remove the "all". It outputs the same exact thing the first print statement did.
Here's my code:
// RemoveAll
// Spec: To remove the "all"
// ArrayList remove() exercise
import java.util.ArrayList;
public class RemoveAll
{
public static void main(String args[])
{
ArrayList<String> ray;
ray = new ArrayList<String>();
int spot = ray.size() - 1;
ray.add("all");
ray.add("all");
ray.add("fun");
ray.add("dog");
ray.add("bat");
ray.add("cat");
ray.add("all");
ray.add("dog");
ray.add("all");
ray.add("all");
System.out.println(ray);
System.out.println(ray.size());
// add in a loop to remove all occurrences of all
while (spot >= 0)
{
if (ray.get(spot).equalsIgnoreCase("all"))
{
ray.remove(spot);
}
spot = spot - 1;
}
System.out.println("\n" + ray);
System.out.println(ray.size());
}
}
Any ideas?
you are determining size() before filling list
put this after once you have list filled (i.e. after all add())
int spot = ray.size() - 1;
Another way to remove items from the list is to use an Iterator:
for(Iterator<String> i = ray.iterator(); i.hasNext(); ) {
if(i.next().equalsIgnoreCase("all")) {
i.remove();
}
}
That way you don't have to keep track of where you are in the list with respect to removed items.
Two problems. You are setting the size of spot before the array has any values in it so it will have a value of -1 when you get to
while (spot >= 0)
also you are mutating (modifying) the array while you are iterating over it which will cause all sorts of errors. The way you want to do this is using an iterator
Iterator iter = ray.iterator();
while(iter.hasNext()){
String cur = iter.next();
//logic to determin if you need to remove
iter.remove();
}
I need to write a static method in a class MinTester that computes the "smallest" string
from an ArrayList collection using a comparator object:
public static String min(ArrayList<String> list, Comparator<String> comp)
I cannot use the Collections class to compute the minimum.
Here is what I have so far.
public class MinTester
{
static String least;//This is static because it is being used in a static static context
public static String min(ArrayList<String> list, Comparator<String> comp)
{
int min = 0;
for( int i = 0; i < list.size(); i++ )
{
min = list.get(i).compareTo(list.get(i++));
if(min < 0)
{
least = list.get(i);
}
else if(min == 0)
{
least = list.get(i);
}
else
{
least = list.get(i++);
}
}
return least;
}
}
I am using the min value because I read that the compareTo method returns negative, 0, or positive whether the first string is less than, equal to, or greater than the second.
I am not getting any errors here from the method, So I try to test it in Main with this.
I get this warning: "Accessing static method min"
public static void main(String[] args)
{
// TODO code application logic here
MinTester s = new MinTester();
Comparator<String> comp = null;
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("ab");
list.add("abc");
list.add("abcd");
String a = s.min(list,comp);//Warning: Accessing static method min
System.out.println(a);
}
My output from a = "abcd". Can anyone help me figure out why I am getting "abcd" as the 'Min' string in the list? I am thinking that my error is coming from my min() method, but I am not sure where inside it or why.
If you need to find the shortest String in an ArrayList without sorting it, you can simply traverse the list and check the .length attribute of every String, always keeping track of the shortest one.
String shortest = list.get(0);
for(String str : list) {
if (str.length() < shortest.length()) {
shortest = str;
}
}
System.out.println("The shortest string: " + shortest);
EDIT :
You would use Comparator if you wanted to implement custom comparison of two strings. Comparing their length can be done in 1 line, so Comparator is really not necessary. If you absolutely need to use the Comparator, you would replace
if (str.length() < shortest.length())
by
if (comp.compare(str, shortest) < 0))
it's basically the same thing, except that you don't define the comparison by yourself but leave it up to the Comparator to decide, which String of the two is smaller. This way, if you wanted the way how the strings are compared in the future, you wouldn't have to rewrite the method, you would only supply a different Comparator.
Using Streams and Comparator-
Comparator<String> comparator = (str1, str2) -> str1.length() > str2.length() ? 1 : -1;
String smallest = Arrays.stream(input)
.sorted(comparator).findFirst().get();
Reference: Find Shortest Length String
you can just use string lengths to compare and use min method of stream:
stringSet.stream().min(Comparator.comparingInt(String::length)).get();
Some pointer, using the Comparator, to get the idea. I'm not going to solve the whole problem, as this is obviously your homework (implement the Comparator for the String lengths, understand what Comparator#compareTo(T, T) returns, read the Comparator API):
public static String min(List<String> list, Comparator<String> comp) {
String shortest = null;
for (String current : list) {
if (shortest == null) { // first iteration
shortest = current;
continue;
}
int comparisonResult = comp.compare(shortest, current);
// TODO: your task; update shortest, depending on comparisonResult
}
return shortest;
}
Don't want to do all of the work for you, so I will provide a solution in Scala:
object MinTest{
def main(args: Array[String]){
val list: util.List[String] = List("a", "ab", "abc", "abcd")
val m: String = min(list, (s1, s2) => s1.length - s2.length)
println(m) //output is: a
}
def min(list: util.List[String], comp: (String, String) => Int): String = {
if(list.isEmpty)
return null
var min = list(0)
for(i <- 0 until list.size if comp(list(i), min) < 0)
min = list(i)
min
}
}
Although this is a different language, the logic is still present. It's just your responsibility to convert it to Java.
This is simple guys, cant you just create a hashmap from a list where the number in the hashmap is the length of the string then the value in the hashmap is the string that goes with that value...
Sort by the key, select item zero, then you have it , right?
What I'm saying is put all the strings in a list.. for each loop on that list, while doing so note the string in one column and the length of that string in the other "while you're there" , sort by the length, then pick the first string that goes with that length.
You can get the length of the string element using the length method
e.g. list.get(0).length()
This should return the size of the string
Good Luck
I want to get specific combination of permutation of string like alphabet. To understand me, I'll show you the code that I using:
public class PermutationExample {
public static List<String> getPermutation(String input) {
List<String> collection = null;
if (input.length() == 1) {
collection = new ArrayList<String>();
collection.add(input);
return collection;
} else {
collection = getPermutation(input.substring(1));
Character first = input.charAt(0);
List<String> result = new ArrayList<String>();
for (String str : collection) {
for (int i = 0; i < str.length(); i++) {
String item = str.substring(0, i) + first
+ str.substring(i);
result.add(item);
}
String item = str.concat(first.toString());
result.add(item);
}
return result;
}
}
public static void main(String[] args) {
System.out.println(PermutationExample.getPermutation("ABCD"));
}
}
This code works well and i can get every combination, I can take it from the list, if I need 5-th element, I can receive it. But if the string is the alphabet ... , didn't works, it's too big. What I have to do, to get the specific element like 1221-th from all 26! combinations ?
I solved a similar problem a while ago, only in python.
If what you need is simply the n-th permutation, then you can do a lot better then generating every permutation and returning the n-th, if you try to think about generating only the permutation you need.
You can do this "simply" by figuring out what should be the element in front for the number of permutations you want, and then what should be the remaining of the elements recursively.
Assume a collection of values [0, ... ,X], for any values such that col[n] < col[n+1]
For N elements, there are N! possible permutations, the case when the collection will be perfectly reversed.
We will see the change in the head of the collection after each (N-1)! permutations, so if n < (N-1)!, the head is the head. You then have a remaining number of permutations, and you can apply the same logic recursively.
Does this help? I know it's fairly high level and you'll have to think a bit about it, but maybe it'll get you on the right track.