I have this function and I need to optimise it so that it takes less time running:
public static int recherche(int cherche, int[] t) {
int srch = 0;
int tmp=0;
boolean result = false;
for (int i=0; i<t.length ; i++) {
if (t[i]== cherche && result == false) {
tmp++;
srch = i;
result=true;
}
}
if (tmp!=0) {
return srch ;
}
else {
return -1;
}
}
Also I can't use any library tools.
If I understand your method correctly you are searching for the index of the first occurrence of cherche in your array t, or -1 if not found.
The problem with your code is, that you keep looping even if you already found the entry. It is better to break the loop immediately. You also do not need the extra variables.
public static int recherche(int cherche, int[] t) {
int srch = -1;
for (int i = 0; i < t.length; i++) {
if (t[i] == cherche) {
srch = i;
break;
}
}
return srch;
}
If this is still too slow, you could try to store the data sorted or create some kind of index.
If you had a List instead of an Array, you could use the indexOf method, but I do not think it can be any faster for unsorted data.
It will be always O(n), because you have to check all array values in the worst case.
P.S: Please consider to use better variable names. I have no idea what t and cherche are.
There is no real optimization that can be done with this function in Java. If you know that the array t is sorted, you could use binary sort.
I cleaned your code up a bit though
public static int recherche(int cherche, int[] t) {
for (int i = 0; i < t.length; i++) {
if (t[i] == cherche) {
return i;
}
}
return -1;
}
The optimizations you can do are returning the result right after you found it and removing redundant variables.
public static int research(int searched, int[] t) {
for (int i=0; i < t.length ; i++) {
if (t[i] == searched) {
return i;
}
}
return -1;
}
Related
I have a problem with removig duplicate elements from an array in Java. I made two extra functions, one which counts how many unique elements there are and one which checks if the integer is already in the result array. Everything seems to work, but I fail a test where 0 is supposed to be 2nd in the array, but it's always moved to the end in my code. What can I do to fix this mistake?
Tester is showing this error:
Expected :is [<100>, <0>, <3>, <4>, <562>]
Actual :[<100>, <3>, <4>, <562>, <0>]
This is my code so far:
public static int[] removeDuplicates(int[] integers) {
int count = countUniques(integers);
int counter = 0;
int[] result = new int[count];
for (int integer : integers) {
Boolean isInArray = isInArray(result, integer);
if (!isInArray) {
result[counter] = integer;
counter++;
}
}
return result;
}
public static int countUniques(int[] integers) {
int i, j;
int count = 0;
for (i = 0; i < integers.length; ++i) {
for (j = 0; j < i; j++)
if (integers[i] == integers[j])
break;
if (i == j)
count++;
}
return count;
}
public static Boolean isInArray(int[] integers, int targetInteger) {
for (int integer : integers) {
if (targetInteger == integer) {
return true;
}
}
return false;
}
When you create a primitive int array it is by default filled with 0s. You can change your code to use an Integer object array. That way the default value for each element will be null.
You would then need to null check each element inside your isInArray():
public static Boolean isInArray(Integer[] integers, int targetInteger) {
for (Integer integer : integers) {
if (integer != null && targetInteger == integer) {
return true;
}
}
return false;
}
And change your result array to Integer[] result = new Integer[count]; and return Integer[] instead of int[].
If you want to return primitive array you can use streams and map Integer to int.
something like
return Arrays.stream(result).mapToInt(i-> i).toArray();
You haven't filled up the result array yet, so the end of it will be filled with zeros. You only want to loop over the part that you have filled. One way to achieve this is to pass the value of counter to your isInArray method.
public static int[] removeDuplicates(int[] integers) {
int count = countUniques(integers);
int counter = 0;
int[] result = new int[count];
for (int integer : integers) {
Boolean isInArray = isInArray(result, counter, integer);
if (!isInArray) {
result[counter] = integer;
counter++;
}
}
return result;
}
public static int countUniques(int[] integers) {
int i, j;
int count = 0;
for (i = 0; i < integers.length; ++i) {
for (j = 0; j < i; j++)
if (integers[i] == integers[j])
break;
if (i == j)
count++;
}
return count;
}
public static Boolean isInArray(int[] integers, int integersLength, int targetInteger) {
for (int i = 0; i < integersLength; i++) {
if (targetInteger == integers[i]) {
return true;
}
}
return false;
}
If you need to remove duplicates from an array, probably the simplest thing to do is to convert the array to a java.util.Set and then convert the set back to an array.
public int[] removeDups(int[] arr) {
Set<Integer> noDups = new HashSet<>(Arrays.stream(arr).boxed().collect(Collectors.toList()));
int[] newArr = noDups.stream().mapToInt(Integer::intValue).toArray();
return newArr;
}
This simplifies the process and eliminates additional issues like the one you are having with creating an array padded with zeros for the unused array index locations.
To count "unique", call this method and then return the created collection's size:
public int countUnique(int[] arr) {
return removeDups(arr).length;
}
This solution does not require the method isInArray; which by the way, should not be a public method. In my opinion, public methods should not invoke other public methods. The reason being is that requirement's change might cause the method with the dependency to break.
I want to sort the ArrayList of ArrayList<Integer>, which looks like.
ArrayList<ArrayList<Integer>> allres = new ArrayList<ArrayList<Integer>>();
Collections.sort(allres, new Comparator<ArrayList<Integer>>() {
public int compare(ArrayList<Integer> a, ArrayList<Integer> b) {
for (int i = 0; i < a.size(); i++) {
if (a.get(i) < b.get(i)) {
return -1;
} else if (a.get(i) == b.get(i)) {
continue;
} else {
return 1;
}
}
return -1;
}
});
But for some input, it is not giving the result of dictionary sort.
Comparator functions that contain 1 or -1 are error prone.
Instead, you should write it like this:
public static int lexicographically(List<Integer> a, List<Integer> b) {
for (int i = 0, end = Math.min(a.size(), b.size()); i < end; i++) {
int res = Integer.compare(a.get(i), b.get(i));
if (res != 0)
return res;
}
return Integer.compare(a.size(), b.size());
}
This style of writing comparator functions prevents various common mistakes, such as never returning 0.
The most important pattern in this style is:
Compare by the first criterion.
If the given values differ, return the comparison result and be done.
Take the next criterion, continue with step 1.
If there are no criteria left, return 0.
My professor gave us this code that creates a sorted int array and wants us to convert it to a sorted array list with strings. This is an assignment on maintenance and must reflect the original code. So, I can't use the size method, Collections.sort(), or anything that doesn't reflect the original code.
We are given
OrderedIntList() {
a = new int[10];
}
public void insert(int v) {
if(c == 0) {
a[0]= v;
c++;
} else {
int j = 0;
for (int i = 0; i < c; i++, j++) {
if(v < a[i])
break;
}
for (int i = c; i > j; i--) {
a[i] = a[i - 1];
}
a[j]= v;
c++;
}
}
This is what I have come up with to convert it to an array list
stringList() {
list = new ArrayList<String>(10);
}
public void insert(String element) {
if(c == 0) {
list.add(0, element);
c++;
} else {
int j = 0;
for (int i = 0; i < c; i++, j++) {
if(element.compareTo(list.get(i)) == -1)
break;
}
for (int i = c; i > j; i--) {
list.set(i, list.get(0));
}
list.set(j, element);
c++;
}
}
It keeps throwing an exception on
list.set(i, list.get(0));
When debugging I see that ArrayList.class is throwing the exception because the index equals the size. I can't seem to come up with a solution. Any help will be greatly appreciated.
An interesting aspect of this assignment is that arrays and lists have a significant difference in behaviour: arrays have a fixed size while lists expand as items are added. For lists, adding items anywhere other than the end is an insert and it automatically moves the items to the right to make room. That doesn't happen with an array so it needs to be done manually in the code you are refactoring.
So, in my opinion, the correct minimal refactoring of an array to a list is to turn the set into an insert and then remove the code that used to be required to shift elements. It's no longer required for a list:
public void insert(String element) {
if (c == 0) {
list.add(element);
c++;
} else {
int j = 0;
for (int i = 0; i < c; i++, j++) {
if (element.compareTo(list.get(i)) < 0 )
break;
}
list.insert(j, element);
c++;
}
}
For lists, adding to an empty list is the same as inserting at position 0. So the specially handling for an empty list is completely unnecessary. But that might be not 'reflecting the original' code.
Another more subtle difference is that this code won't cause an error if more than 10 items are inserted. To correctly reflect the behaviour of the initial code you would need to specifically add a test for that.
if (c == MAX_SIZE)
throw new ArrayIndexOutOfBoundsException(c);
It's likely your assignment is not expect you to handle that condition but it is worth knowing that the refactoring is changing the behaviour of the function if it's not included.
One solution to your problem is instead of
stringList() {
list = new ArrayList<String>(10);
}
do
stringList() {
list = new ArrayList<String>(10);
for(int i = 0; i < 10; i++){
list.add("");
}
}
because only this will achieve a list of 10 strings, the first just makes a list that has the capacity to hold 10 strings (which is more of a performance hint)
My assignment requires me to code several methods that will compare an array of first names from a .txt file.
I'm currently stuck on a BubbleSort method. Trying to get it to run.
This is my code for the BubbleSort:
public static int bubbleSort(String[] array) {
boolean swapped = false;
int compNumber = 0;
int length = length.array;
while (swapped = false) {
for (int i = 0; i < length.array-1; i++) {
if (array[i-1] > array[i]) {
String temp =
array[i-1] = array[i];
swapped = true;
}
}
}
return compNumber;
}
I don't believe I'm swapping correctly because I'm not sure how to use the temp variable (hence it being blank).
Could someone take a look at this and point me in the right direction?
Thanks very much in advance!
Not sure if your algorithm is correct, but here is the standard way to swap. If you're sorting a String array you will also need to get the numerical value (I assume the Strings contain numbers?).
Also just noticed you will get an array out of bounds exception, start at 1 if you are looking at index i-1.
One more thing, i < length.array-1 should be i < array.length
And one more thing as well, the loop should continue until no swaps were made, so it should be while (swapped == true), and re-set it to false in each iteration.
public static void bubbleSort(String[] array) {
boolean swapped = true;
int compNumber = 0;
int length = length.array;
while (swapped == true) { //note the ==
swapped = false;
for (int i = 1; i < array.length; i++) {
compNumber++;
if (Integer.parseInt(array[i-1]) > Integer.parseInt(array[i])) {
String temp = array[i-1]
array[i-1] = array[i];
array[i] = temp;
swapped = true;
}
}
}
return compNumber;
}
I have a program that is counting the frequencies of words taken from a txt file and they are being stored in an ArrayList. I am extremely unfamiliar with using a selection sort but it is the type of sort that I am being asked to use. I have looked at multiple selection sorts, but mine is falling short somewhere along the line.
This is my actual sort.
private void sort() {
for (int i = 0; i < wordArray.size() - 1; i++) {
for (int j = i + 1; j < wordArray.size(); j++) {
if (wordArray.get(i).compareTo(wordArray.get(j)) == 1) {
Word temp = wordArray.get(i);
wordArray.set(i, wordArray.get(j));
wordArray.set(j, temp);
}
}
}
}
This is my comparison of strings (I am pretty sure the logic error is in here).
public int compareTo(Word w) {
for (int i = 0; i < this.word.length() - 1; i++) {
if (i <= w.word.length() - 1) {
if (this.word.charAt(i) < w.word.charAt(i)) {
return -1;
} else if (this.word.charAt(i) > w.word.charAt(i)){
return 1;
}
}
}
return -1;
}
Word is a class that has the String variable "word". Any tips would be greatly appreciated :)
Why not just use this
public int compareTo(Word w) {
return this.word.compareTo(w.word);
}