I'm given an array of doubles, all numbers are equal except for one. My task is to find that unique number. My code returns the correct output and now I'm wondering how will I further optimize it.
This is my code:
public static double findUnique(double array[]) {
double unique = 0;
double common = 0;
for(int i=0; i<array.length; i++) {
for(int j=i+1; j<array.length; j++) {
if(array[i]==array[j]) {
common = array[i];
}
}
if(common!=array[i]) {
unique = array[i];
}
}
return unique;
}
The only thing I could think of is storing the length of the array first, but after some testing it actually took longer. Thanks.
public static double findUnique(double array[]) {
if(array.length < 3) {
throw new IllegalArgumentException("wrong array");
}
double common;
if(array[0] == array[1]) {
common = array[0];
} else {
return array[0] != array[2]? array[0]: array[1];
}
for(int i=2; i<array.length; i++) {
if(common != array[i]) {
return array[i];
}
}
throw new IllegalArgumentException("wrong array");
}
I belive that it is uneccesary to grab two new numbers in everey iteration.
Instead we could just start by grabbing the two first numbers of the array and then if those numbers are the same, we may compare the rest of the numbers to their value. So we define our common above the for loops, that way we will avoid the for loop and if statement containing: common= array[i] in every iteration. I belive this should make a difference in speed, at least if the array is crazy big.^^
Also, put the return inside the for loops so that you don't iterate the entire list even though you really found that piece of gold :):). (returning something always breaks the entire method.)
Hope I din't missunderstand anything :). Here's some code for you aswell. :)
public static double findUnique(double array[]) {
double common = 0;
if(array.length<3){
throw new IllegalArgumentException("Only two numbers exsists");
}
// Set up the common number seperately here.
if(array[0] == array[1]){
common = array[0];
}
else if(array[1] == array[2]){
return array[0];
}else{
return array[1];
}
// Now we iterate with return inside the for loop.
for(int i=2; i<array.length; i++) {
if(common!=array[i]) {
return array[i];
}
}
throw new IllegalArgumentException("All numbers are identical");
}
What if you sort the entire array first. Then just look at the first two and one last elements of the array.
Related
So I am having trouble trying to find duplicates in an array where a user enters the numbers. I want to display a dialog when they enter a number that is already in the array. It sounds simple but is confused on how to go on about this.
//Convert the string into an int
num = Integer.parseInt(inputField.getText());
// Add it to the an index
array[index] = num;
// Increment the index variable
index++;
// If the the duplicate exists
for(int i = 0; i < array.length;i++){
if(array[index] == num){
if(array[i - 1] == num){
JOptionPane.showMessageDialog(null,"Array may not contain duplicates ","Array Duplicate",JOptionPane.ERROR_MESSAGE );
break;
}
}
}
Trying to fix your code here
//Convert the string into an int
num = Integer.parseInt(inputField.getText());
boolean exsist = false;
// If the the duplicate exists
for(int i = 0; i < array.length;i++){
if(array[i] == num){
exsist = true;
JOptionPane.showMessageDialog(null,"Array may not contain duplicates ","Array Duplicate",JOptionPane.ERROR_MESSAGE );
break;
}
}
if(!exsist)
{
// Add it to the an index
array[index] = num;
// Increment the index variable
index++;
}
something like this should work
The reasoning is
not using the variable i from the for loop, this results in checking the same value all the time
the checks in the if statements are broken, the checks simply don't make sense, try to use the ior other variables that change each loop to check multiple values
there is no need to add the value before testing if it exsist, if you do so you will have to remove it after, doing it after therefore result in a faster code (even if only very very little) and a safer code since you can't fail to delete the value
After some thinking and some suggestion. I managed to solve it.
// Set orginal to true
boolean orginal = true;
//Convert the string into an int
num = Integer.parseInt(inputField.getText());
// Loop to find the duplicate
for(int i = 0; i < array.length; i++){
// Check if there's a duplicate
for(int j = 0; j < array.length; j++){
// Check if the num is equal to any of the numbers in the array
if(array[j] == num){
// Set orginal to false
orginal = false;
// Throw the duplicate exception
throw new DuplicateValueException(result);
}
}
// If there is no duplicates
if(orginal){
// Add the number to the array
array[index] = num;
// Break out the loop
break;
}
}
// Print the message
System.out.println("array["+index+"] = "+ num);
// Increment the index variable
index++;
for(int i = 0; i < array.length-1;i++){
if(array[i] == num){
JOptionPane.showMessageDialog(null,"Array may not contain duplicates ","Array Duplicate",JOptionPane.ERROR_MESSAGE );
break;
}
}
Try this!
But your code will add that number to array anyway as you are adding it before checking it.
This code makes no sense :
// Add it to the an index
array[index] = num;
// Increment the index variable
index++;
for(int i = 0; i < array.length;i++){
if(array[index] == num){
You add the num int at the index index of the array and then in the loop you want to check if index+1 == num.
In your logic you should rather check if index == num.
And anyway it is useless, you have done : array[index] = num;.
So if(array[index] == num) can be only true.
I want to display a dialog when they enter a number that is already in
the array
You should rather do the check of duplication number before adding it in the array.
The general idea would be iterating the array and if during the iteration, a element of the array is equals to num, you have not add num.
In the contrary case, if no element is equals to num, you have to add it.
It seems to be a school working, so I will not detail further the solution.
I think this will work for sure even for the case of [5->5]
index++;
// If the the duplicate exists
if (index > 0) {
for (int i = 0; i < array.length; i++) {
if (array[i] == num) {
JOptionPane.showMessageDialog(null, "Array may not contain duplicates ", "Array Duplicate", JOptionPane.ERROR_MESSAGE);
break;
}
}
}
I would like to use list.negativeNumbers(); to call out the part of a code, which counts how many negative numbers are in a list.
public void negativeNumbers(){
int negative = 0;
for (int i = 0; i <= size; i++){
if (i < 0) {
negative = negative + 1;
}
System.out.println("There are "+ negative +" negative elements in the list!");
}
}
Can you help me in creating a method, that could count negative numbers in the list the correct way?
public void negativeNumbers(){
int negative = 0;
for (int i = 0; i <= size; i++){
if (i < 0) {
negative = negative + 1;
}
System.out.println("There are "+ negative +" negative elements in the list!");
}
}
You will learn better by working out the solution for yourself.
Your code as presented is a good start but lacks:
a defined list of values to test.
a definition of the size of the list (use list.size()).
proper indexing of the list to access values to test (use list.get(i) or list[i]).
a test of each element in the list to determine its negativity. Your code tests whether the list increment variable is < 0.
negative = negative + 1 is ok, but simpler to write ++negative.
Here's a simple example:
import java.util.ArrayList;
public class negnum {
public static void main(String [] args) {
ArrayList<Integer> nums = new ArrayList();
nums.add(0);
nums.add(10);
nums.add(-10);
nums.add(20);
nums.add(-20);
nums.add(30);
nums.add(-30);
nums.add(40);
nums.add(-40);
nums.add(50);
int negs = 0;
for (int i = 0; i < nums.size(); i++){
int n = nums.get(i);
if (n < 0) {
++negs;
System.out.println(n);
}
}
System.out.println(negs +" negatives");
}
}
c:\dev>java negnum
-10
-20
-30
-40
4 negatives
If it is a list of integers you should not be doing "i < 0" but rather the number at index of i. If you were to do that, you would also want to do "< size" rather than "<= size" or else you would run into an IndexArrayOutOfBounds.
It depends on how your double linked list is implemented, but if it extends the normal List<Integer> interface it would look like:
final Integer ZERO = Integer.valueOf(0);
int countNegativeElements() {
return stream().filter(MyList::isNegative).count();
}
static boolean isNegative(Integer i) {
return i.compareTo(ZERO) < 0;
}
with streams. More traditionally with an collection for-each (or an iterator for-each):
int countNegativeElements() {
int count = 0;
for(Integer i : this) { // or iterator()
if (isNegative(i)) count++;
}
return count;
}
This does not expect concurrent modifications and is optimized for collections where iterating is the fastest access. If you have a simple type list then you can replace isNegative with a simple < 0.
This article here talks about different ways to iterate a collection.
In my code I assumed you will add the method directly to your list implementation class. Replace this or this.iterator() or this.stream() with your actual list instance if it is external.
Update:
I just saw your link to the actual linked list you are using, this would look like this (hand made iteration):
int countNegativeElements() {
Node n = start;
int count = 0;
while(n != null) {
if (n.getData() < 0) count++;
n = n.getLinkNext();
}
return count;
}
Using null since there is no hasLinkNext() which would be typical for homework :)
I don't think it is a particular good idea to work with implementations which do not fit in the Collections framework, but maybe it is required to keep the lessons simple.
So the original code is
// An (unsorted) integer list class with a method to add an
// integer to the list and a toString method that returns the contents
// of the list with indices.
//
// ****************************************************************
public class IntList {
private int[] list;
private int numElements = 0;
//-------------------------------------------------------------
// Constructor -- creates an integer list of a given size.
//-------------------------------------------------------------
public IntList(int size) {
list = new int[size];
}
//------------------------------------------------------------
// Adds an integer to the list. If the list is full,
// prints a message and does nothing.
//------------------------------------------------------------
public void add(int value) {
if (numElements == list.length) {
System.out.println("Can't add, list is full");
} else {
list[numElements] = value;
numElements++;
}
}
//-------------------------------------------------------------
// Returns a string containing the elements of the list with their
// indices.
//-------------------------------------------------------------
public String toString() {
String returnString = "";
for (int i = 0; i < numElements; i++) {
returnString += i + ": " + list[i] + "\n";
}
return returnString;
}
}
and
// ***************************************************************
// ListTest.java
//
// A simple test program that creates an IntList, puts some
// ints in it, and prints the list.
//
// ***************************************************************
import java.util.Scanner ;
public class ListTest {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
IntList myList = new IntList(10);
int count = 0;
int num;
while (count < 10) {
System.out.println("Please enter a number, enter 0 to quit:");
num = scan.nextInt();
if (num != 0) {
myList.add(num);
count++;
} else {
break;
}
}
System.out.println(myList);
}
}
I need to change the add method to sort from lowest to highest. This is what I tried doing.
// An (unsorted) integer list class with a method to add an
// integer to the list and a toString method that returns the contents
// of the list with indices.
//
// ****************************************************************
public class IntList {
private int[] list;
private int numElements = 0;
//-------------------------------------------------------------
// Constructor -- creates an integer list of a given size.
//-------------------------------------------------------------
public IntList(int size) {
list = new int[size];
}
//------------------------------------------------------------
// Adds an integer to the list. If the list is full,
// prints a message and does nothing.
//------------------------------------------------------------
public void add(int value) {
if (numElements == list.length) {
System.out.println("Can't add, list is full");
} else {
list[numElements] = value;
numElements++;
for (int i = 0; i < list.length; i++) {
if (list[i] > value) {
for (int j = list.length - 1; j > i; j--) {
list[j] = list[j - 1];
list[i] = value;
break;
}
}
}
for (in i = 0; i < list.length; i++) {
}
}
}
//-------------------------------------------------------------
// Returns a string containing the elements of the list with their
// indices.
//-------------------------------------------------------------
public String toString() {
String returnString = "";
for (int i = 0; i < numElements; i++) {
returnString += i + ": " + list[i] + "\n";
}
return returnString;
}
}
The outcome is very wrong. Any one able to steer me in the right direction? I can sort of see why what I have doesn't work, but I can't see enough to fix it.
So I realize I was not very descriptive here the first time. With the exception of the add method modifications the code was not my doing. My assignment is to only touch the add method to sort the array to print out smallest to largest. This is a beginners class and we do little to no practice my only tools for this are some basic understandings of loops and arrays.
I tried redoing it again and came up with this:
if(list[numElements-1] > value){
for(int i=0; i<numElements; i++){
if(list[i]>value){
for(int j = numElements; j>i; j-- ){
list[j] = list[j-1];
}
list[i] = value;
break;
}
}
numElements++;
}
else
{
list[numElements] = value;
numElements++;
}
my input was:8,6,5,4,3,7,1,2,9,10
the output was: 1,10,1,9,10,1,1,2,9,10
this thing is kicking my butt. I understand I want to check the input number to the array and move all numbers higher than it up one space and enter it behind those so it is sorted on entry, but doing so is proving difficult for me. I apologize if my code on here is hard to follow formatting is a little odd on here for me and time only allows for me to do my best. I think break is not breaking the for loop with i like i thought it would. Maybe that is the problem.
The biggest bug I see is using list.length in your for loop,
for(int i = 0; i <list.length; i++)
you have numElements. Also, I think it's i that needs to stop one before like,
for(int i = 0; i < numElements - 1; i++)
and then
for (int j = numElements; j > i; j--)
There are two lines that have to be moved out of the inner loop:
for (int i = 0; i < list.length; i++) {
if (list[i] > value) {
for (int j = list.length - 1; j > i; j--) {
list[j] = list[j - 1];
// list[i] = value;
// break;
}
list[i] = value;
break:
}
}
In particular, the inner break means that the loop that is supposed to move all larger elements away to make room for the new value only runs once.
You might want to include Java.util.Arrays which has its own sort function:
http://www.tutorialspoint.com/java/util/arrays_sort_int.htm
Then you can do:
public void add(int value) {
if (numElements == list.length) {
System.out.println("Can't add, list is full");
}
else {
list[numElements] = value;
numElements++;
Arrays.sort(list);
//Or: Java.util.Arrays.sort(list);
}
}
As Eliott remarked, you are getting confused between list.length (the capacity of your list) and numElements (the current size of your list). Also, though, you do not need to completely sort the list on each addition if you simply make sure to insert each new element into the correct position in the first place. You can rely on the rest of the list already to be sorted. Here's a simple and fast way to do that:
public void add(int value) {
if (numElements == list.length) {
System.out.println("Can't add, list is full");
} else {
int insertionPoint = Arrays.binarySearch(list, 0, numElements);
if (insertionPoint < 0) {
insertionPoint = -(insertionPoint + 1);
}
System.arrayCopy(list, insertionPoint, list, insertionPoint + 1,
numElements - insertionPoint);
list[insertionPoint] = value;
numElements += 1;
}
}
That will perform better (though you may not care for this assignment), and it is much easier to see what's going on, at least for me.
Here are some hints.
First, numElements indicates how many elements are currently in the list. It's best if you change it only after you have finished adding your item, like the original method did. Otherwise it may confuse you into thinking you have more elements than you really do at the moment.
There is really no need for a nested loop to do proper adding. The logic you should be following is this:
I know everything already in the list is sorted.
If my number is bigger then the biggest number (which is the one indexed by numElements-1, because the list is sorted) then I can just add my number to the next available cell in the array (indexed by numElements) and then update numElements and I'm done.
If not, I need to start from the last element in the array (careful, don't look at the length of the array. The last element is indexed by numElements-1!), going down, and move each number one cell to the right. When I hit a cell that's lower than my number, I stop.
Moving all the high numbers one cell to the right caused one cell to become "empty". This is where I'm going to put my number. Update numElements, and done.
Suppose you want to add the number 7 to this array:
┌─┬──┬──┬─┬─┐
│3│14│92│-│-│
└─┴──┴──┴─┴─┘
⬆︎ Last element
You move everything starting from the last element (92) to the right. You stop at the 3 because it's not bigger than 7.
┌─┬─┬──┬──┬─┐
│3│-│14│92│-│
└─┴─┴──┴──┴─┘
(The second element will probably still contain 14, but you're going to change that in the next step so it doesn't matter. I just put a - there to indicate it's now free for you to enter your number)
┌─┬─┬──┬──┬─┐
│3│7│14│92│-│
└─┴─┴──┴──┴─┘
⬆︎ Updated last element
This requires just one loop, without nesting. Be careful and remember that the array starts from 0, so you have to make sure not to get an ArrayIndexOutOfBoundsException if your number happens to be lower than the lowest one.
One problem I spotted is that: you are trying to insert the newly added number into the array. However your loop:
for (int i = 0; i < list.length; i++) {
if (list[i] > value) {
for (int j = list.length - 1; j > i; j--) {
list[j] = list[j - 1];
list[i] = value;
break;
}
}
}
is always looped through the total length of the array, which is always 10 in your test, rather than the actual length of the array, i.e. how many numbers are actually in the array.
For example, when you add the first element, it still loops through all 10 elements of the array, although the last 9 slots does not have value and are automatically assigned zero.
This caused your if statement always returns true:
if (list[i] > value)
if you have to write the sort algorithm yourself, use one of the commonly used sorting algorithm, which can be found in Wikipedia.
If any one was curious I finally worked it out. Thank you to everyone who replied. This is what i ended up with.
public void add(int value)
{
if(numElements == 0){
list[numElements] = value;
numElements++;
}
else{
list[numElements] = value;
for(int check = 0; check < numElements; check++){
if(list[check] > value){
for(int swap = numElements; swap> check; swap--){
list[swap] = list[swap-1];
}
list[check] = value;
break;
}
}
numElements++;
}
}
so my original is the same but we have to make another class
A Sorted Integer List
File IntList.java contains code for an integer list class. Save it to your project and study it; notice that the only things you can do are create a list of a fixed size and add an element to a list. If the list is already full, a message will be printed. File ListTest.java contains code for a class that creates an IntList, puts some values in it, and prints it. Save this to your folder and compile and run it to see how it works.
Now write a class SortedIntList that extends IntList. SortedIntList should be just like IntList except that its elements should always be in sorted order from smallest to largest. This means that when an element is inserted into a SortedIntList it should be put into its sorted place, not just at the end of the array. To do this you’ll need to do two things when you add a new element:
Walk down the array until you find the place where the new element should go. Since the list is already sorted you can just keep looking at elements until you find one that is at least as big as the one to be inserted.
Move down every element that will go after the new element, that is, everything from the one you stop on to the end. This creates a slot in which you can put the new element. Be careful about the order in which you move them or you’ll overwrite your data!
Now you can insert the new element in the location you originally stopped on.
All of this will go into your add method, which will override the add method for the IntList class. (Be sure to also check to see if you need to expand the array, just as in the IntList add() method.) What other methods, if any, do you need to override?
To test your class, modify ListTest.java so that after it creates and prints the IntList, it creates and prints a SortedIntList containing the same elements (inserted in the same order). When the list is printed, they should come out in sorted order.
if it's in ascending order I need to print "Ascending".
And if otherwise, print "Otherwise".
int [] a = new int[args.length];
for (int i = 0; i < args.length; i++)
{
a[i] = Integer.parseInt(args[i]);
}
if (a[0] <= args.length || a[0] == a[0])
{
System.out.println("Ascending");
}
else
{
System.out.println("Otherwise");
}
You seem to be having a lot more trouble with this exercise than you should. So I'll only give a hint, since this looks like homework: You should make n-1 comparisons in order to determine the order. Do that using a for loop.
To clarify: the code you presented does not contain a for loop that compares numbers, and does some comparisons that have nothing to do with verifying order of the numbers.
Hints:
The following two comparisons don't do anything useful: a[0] <= args.length and a[0] == a[0].
You need to use a loop.
For one, the expression a[0] == a[0] will always evaluate to true, meaning that your current code will always enter the first condition and print "Ascending".
For another, you can't establish that a list of n elements is in ascending order without some kind of iteration. You need to use a loop or recursion to check your array's elements against each other.
Try this code
public class Ascending
{
public static void main(String[] args)
{
int [] a = new int[args.length];
boolean otherwise = false;
for (int i = 0; i < args.length; i++)
{
a[i] = Integer.parseInt(args[i]);
}
for(int i=1;i<a.length;i++){
if(a[i-1]>a[i]){
otherwise = true;
}
}
if (!otherwise)
{
System.out.println("Ascending");
}
else
{
System.out.println("Otherwise");
}
}
}
I am trying to find the smallest value in an array of integers, but when I do I get an arrayindexoutofbounds on a place which, as far as I know, there shouldn't be a counting of array-index, only a comparison of the index and a min-value.
Part of code in question underneath:
}
System.out.println(sum);
int minste=tall[0];
for (int i : tall){
if(tall[i]<tall[0]){ //This is where the exception is made. But why?
minste=tall[i];
}
}
System.out.println(minste);
}
}
i is already an element, just use it. No need to tall[i]:
if(i < minste) {
This loop means: "For each int in tall".
In order to better understand the enhanced loop, think about it this way:
for(int i = 0; i < tall.length; i++) {
System.out.println(tall[i]);
}
Will print the same thing as:
for(int i : tall) {
System.out.println(i);
}
That's why it's recommended to use a meaningful name for the variable, instead of i, use item, so it'll be like "for each item in tall"...
Alternative solution to find the smallest value:
Use Arrays#sort
Return the first element in the array
When you're using the for-each loop, why use the indexes?
if(tall[i]<tall[0]){
tall[i] - gives the ArrayIndexOutOfBoundsException because i is an element in your array and not an index value. And that value i is definitely more than the length of your array.
All you need to do is thi
int minste = tall[0];
for (int i : tall) {
if(i < minste) {
minste = i;
}
}
You are using for-each loop, but try to use i as a index.
To work properly change your code to
int minste = tall[0];
for (int i : tall)
{
if(i < minste)
{
minste = i;
}
}
or
int minste = tall[0];
for (int i = 0; i<tall.length; i++)
{
if(tall[i] < minste)
{
minste = tall[i];
}
}