How to change an integer array within a method - java

I am having an issue with a fill-in-the-code digital textbook problem. All the code is permanent and cannot be changed, so the problem can only be solved by using the area that states //Write code here.
The problem asks to implement the removeOdd method.
import java.util.Arrays;
public class RemoveTester
{
public static int removeOdd(int[] values, int size)
{
//Write code here
}
public static void main(String[] args)
{
int[] a = { 22, 98, 95, 46, 31, 53, 82, 24, 11, 19 };
int sizeBefore = 8;
int sizeAfter = removeOdd(a, sizeBefore);
System.out.print("a: [ ");
for (int i = 0; i < sizeAfter; i++)
{
System.out.print(a[i] + " ");
}
System.out.println("]");
System.out.println("Expected: [ 22 98 46 82 24 ]");
int[] b = { 23, 97, 95, 45, 31, 53, 81, 24, 11, 19 };
sizeBefore = 7;
sizeAfter = removeOdd(b, sizeBefore);
System.out.print("b: [ ");
for (int i = 0; i < sizeAfter; i++)
{
System.out.print(b[i] + " ");
}
System.out.println("]");
System.out.println("Expected: [ ]");
}
}
The way I tried to implement removeOdd is by doing:
int evenCount = 0;
for(int i = 0; i<size; i++){
if(values[i]%2==0){
evenCount++;
}
}
int[] newValues = new int[evenCount];
int newCount =0;
for(int i = 0; i<evenCount; i++){
if(values[i]%2==0){
newValues[newCount] = values[i];
newCount++;
}
}
values = newValues;
return evenCount;
When the program is compiled and ran, main prints the beginning of the original a or b arrays instead of only the even elements in a or b. I cannot find a way to alter the original arrays within the method removeOdd into the new arrays with only their even elements. I can't think of any other way to do this either. Any help would be greatly appreciated!

The other answers give a good description of what the problem is with your overall approach...that is, why your results don't make it back to the calling method.
If your code were otherwise correct, you could use it as is and just copy the result back into the original array at the end. As it is, you had one flaw in your logic. So if you fix that flaw, and then do the copy at the end, you should get the correct result:
public static int removeOdd(int[] values, int size)
{
int evenCount = 0;
for(int i = 0; i<size; i++){
if(values[i]%2==0){
evenCount++;
}
}
int[] newValues = new int[evenCount];
int newCount =0;
for(int i = 0; i<size; i++) { // <- Need to iterate over the entire input array
if(values[i]%2==0){
newValues[newCount] = values[i];
newCount++;
}
}
for (int i = 0 ; i < evenCount ; i++) // <- now copy your result to the original array
values[i] = newValues[i];
return evenCount;
}
Rather than creating an extra array to temporarily hold the even values, you can use the same logic to copy into the original array directly:
public static int removeOdd(int[] values, int size)
{
int newCount =0;
for(int i = 0; i<size; i++) {
if(values[i]%2==0){
values[newCount] = values[i];
newCount++;
}
}
return newCount;
}

Because Java is pass by value and not pass by reference, setting the value of the values argument will not change the value of the a variable.
What you have to do is remove all the odd elements from the array and shift the remaining even elements to the left so that the actual resultant form of a looks like this:
{22, 98, 46, 82, 24, 0, 0, 0, 0, 0}

As #Geoff pointed out Java is pass by value, which means when you pass your array as an argument, what you get inside the method is a reference to the array object which is different from the original reference int[] a you have inside your main method (the caller). Therefore, when you do values = newValues; you are pointing that new reference which used to point to the same object as int[] a to the array object newValues points to, thereby not updating the original array a but actually losing any reference to it.

Related

Finding the power set of a generic set

I had been given a question to utilize java generics and create a Set class. I have been able to perform other functions such as union, intersection, complement etc using this Set class.
But the problem i have been facing is with finding all the power sets. I am required to return a set (i.e the power set). I have been trying to solve this since yesterday but to no avail. I have tried implementing binary method to find the power sets. Everything that i have done so far is based on the requirements of the question!
public class Set<T extends Comparable> {
private ArrayList<T> theSet;
public Set(T[] theElements){
theSet = new ArrayList<>();
for(int i=0; i < theElements.length; i++){
if(!checker(theElements[i]))
theSet.add(theElements[i]);
}
}
public ArrayList<T> getTheSet() {
return theSet;
}
public Set powerSet(){
long powerSetSize = (long)Math.pow(2, theSet.size());
int counter, j;
Set[] powerSet = new Set[(int)Math.pow(2, theSet.size())];
T[] currentArray = null;
for(counter=0; counter<powerSetSize; counter++){
for(j=0; j<theSet.size(); j++){
currentArray = (T[]) new Comparable[j+1];
if((counter & (1 << j)) > 0)
currentArray[j] = theSet.get(j);
}
powerSet[counter] = new Set<>(currentArray);
}
return new Set<>((T[])powerSet);
}
public String toString(){
String str = "{";
for(int i=0; i<theSet.size(); i++){
if(i < theSet.size()-1)
str += theSet.get(i)+", ";
else
str += theSet.get(i)+"}";
}
return str;
}
}
You could try the following:
First create and Array of Integers with length of your basic set, setting every Integer to zero. Keep in mind that every Element is numbered due to its position in your basic set +1, because you need an empty Element, which is then zero. Then of course first create a Set of Sets, that you are going to return as your powerset. After that cycle through your array of Integers as follows: Create a Set out of the current Integer-Array by parsing every Integer to its corresponding element of the Set. Then add one to the first Integer of your Integer-Array. If the number is then greater than the length of your basic Set, add one to the next Integer of your Array, setting the "overflowing" Integer equal to the next Integer in the Array +1.
This should allow you to cycle through every possible combination for the powerset and add them to the Set.
public Set<Set<T>> powerSet(){
int[] num = new int[list.size()];
Arrays.fill(num,0);
Set<Set<T>> powerSet = new Set<>();
do{
powerSet.list.add(parse(num));
}while (addNum(num)); //Loops through every possibility
powerSet.list.add(parse(num));
//Because the method returns false when this was the last possible increment
return powerSet;
}
//Transforms a int[] into the corresponding Set
private Set<T> parse(int[] e){
Set<T> s = new Set<>();
for (int i = 0; i < e.length; i++) {
if(e[i]!=0){
s.list.add(list.get(e[i]-1)); //Every Element has its number
}
}
return s;
}
//Increments the counter
//Returns false if this was the last possible increment
private boolean addNum(int[] e){
e[0]++;
for (int i = 0; i < e.length; i++) {
if(e[i]>e.length-i){
e[i] = 0;
e[i+1]++;
}
}
for (int i = e.length-1; i != 0; i--) {
if(e[i]>=e[i-1]&&e[i]!=0){
e[i-1] = e[i]+1;
}
}
if(e[e.length-1]==1){
return false;
}
return true;
}
Output for [3,43,65,32] (printed out every Set of the powerset):
[]
[3]
[43]
[65]
[32]
[43, 3]
[65, 3]
[32, 3]
[65, 43]
[32, 43]
[32, 65]
[65, 43, 3]
[32, 43, 3]
[32, 65, 3]
[32, 65, 43]
[32, 65, 43, 3]
Although this may not be the most elegant way of solving the problem, it appears to work. I also don't know the requirements of the question. So maybe this answer isn't even suitable.

In Java code i the method i created only put the first duplicate instance to a new array

I want to remove the duplicates by putting them in a new array but somehow I only get a first instance and a bunch of zeros.
Here is my code:
public class JavaApplication7 {
public static void main(String[] args) {
int[] arr = new int[] {1,1,2,2,2,2,3,4,5,6,7,8};
int[] res = removeD(arr);
for (int i = 0; i < res.length; i++) {
System.out.print(res[i] + " ");
}
}
public static int[] removeD(int[] ar) {
int[] tempa = new int[ar.length];
for (int i = 0; i < ar.length; i++) {
if (ar[i] == ar[i+1]) {
tempa[i] = ar[i];
return tempa;
}
}
return null;
}
}
expected: 1,2
result: 1,0,0,0,0,0,0....
why dont you make use of HashSet?
final int[] arr = new int[] { 1, 1, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8 };
final Set<Integer> set = new HashSet<>();
for (final int i : arr) {
// makes use of Integer's hashCode() and equals()
set.add(Integer.valueOf(i));
}
// primitive int array without zeros
final int[] newIntArray = new int[set.size()];
int counter = 0;
final Iterator<Integer> iterator = set.iterator();
while (iterator.hasNext()) {
newIntArray[counter] = iterator.next().intValue();
counter++;
}
for (final int i : newIntArray) {
System.out.println(i);
}
Edit
if you want your array to be ordered
final int[] arr = new int[] { 9, 9, 8, 8, 1, 1, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8 };
Set<Integer> set = new HashSet<>();
for (final int i : arr) {
// makes use of Integer's hashCode() and equals()
set.add(Integer.valueOf(i));
}
// priomitive int array without zeros
final int[] newIntArray = new int[set.size()];
int counter = 0;
// SetUtils.orderedSet(set) requires apache commons collections
set = SetUtils.orderedSet(set);
final Iterator<Integer> iterator = set.iterator();
while (iterator.hasNext()) {
newIntArray[counter] = iterator.next().intValue();
counter++;
}
for (final int i : newIntArray) {
System.out.println(i);
}
A couple of points to help you:
1) With this: for(int i =0; i<ar.length; i++){ - you will get an IndexOutOfBoundsException because you are checking [i+1]. Hint: it is only the last element that will cause this...
2) Because you're initialising the second array with the length of the original array, every non-duplicate will be a 0 in it, as each element is initialised with a 0 by default. So perhaps you need to find how many duplicates there are first, before setting the size.
3) As mentioned in the comments, you are returning the array once the first duplicate is found, so remove that and just return the array at the end of the method.
4) You will also get multiple 2s because when you check i with i+1, it will find 3 2s and update tempa with each of them, so you'll need to consider how to not to include duplicates you've already found - based on your expected result.
These points should help you get the result you desire - if I (or someone else) just handed you the answer, you wouldn't learn as much as if you researched it yourself.
Here:
int[] tempa = new int[ar.length];
That creates a new array with the same size as the incoming one. All slots in that array are initialized with 0s!
When you then put some non-0 values into the first slots, sure, those stick, but so do the 0s in all the later slots that you don't "touch".
Thus: you either have to use a data structure where you can dynamically add new elements (like List/ArrayList), or you have to first iterate the input array to determine the exact count of objects you need, to then create an appropriately sized array, to then fill that array.
Return statement
As both commenters said, you return from the method as soon as you find your first duplicate. To resolve that issue, move the return to the end of the method.
Index problems
You will then run into another issue, an ArrayIndexOutOfBoundsException because when you are checking your last item (i = ar.length - 1) which in your example would be 11 you are then comparing if ar[11] == ar[12] but ar has size 12 so index 12 is out of the bounds of the array. You could solve that by changing your exit condition of the for loop to i < ar.length - 1.
Zeros
The zeros in your current output come from the initialization. You initialize your tempa with int[ar.length] this means in the memory it will reserve space for 12 ints which are initialized with zero. You will have the same problem after resolving both issues above. Your output would look like this: 1 0 2 2 2 0 0 0 0 0 0 0. This is because you use the same index for tempa and ar. You could solve that problem in different ways. Using a List, Filtering the array afterwards, etc. It depends what you want to do exactly.
The code below has the two first issues solved:
public class JavaApplication7 {
public static void main(String[] args) {
int[] arr = new int[] { 1, 1, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8 };
int[] res = removeD(arr);
for (int i = 0; i < res.length; i++) {
System.out.print(res[i] + " ");
}
}
public static int[] removeD(int[] ar) {
int[] tempa = new int[ar.length];
for (int i = 0; i < ar.length - 1; i++) {
if (ar[i] == ar[i + 1]) {
tempa[i] = ar[i];
}
}
return tempa;
}
}
There were a some error mentioned already:
return exits the method.
with arr[i+1] the for condition should bei+1 < arr.length`.
the resulting array may be smaller.
So:
public static int[] removeD(int[] ar) {
// Arrays.sort(ar);
int uniqueCount = 0;
for (int i = 0; i < ar.length; ++i) {
if (i == 0 || ar[i] != ar[i - 1]) {
++uniqueCount;
}
}
int[] uniques = new int[uniqueCount];
int uniqueI = 0;
for (int i = 0; i < ar.length; ++i) {
if (i == 0 || ar[i] != ar[i - 1]) {
uniques[uniqueI] = arr[i];
++uniqueI;
}
}
return uniques;
}

Sorting user defined array by string using selection sort in java

I'm working on an assignment and I need to perform a binary search. But somehow I think I have problems in my selection sort. Here i have an user defined class called Record. It has the following properties:
class Record{
String studentId;
int assignment;
int exam;
int total;
String grade;
}
I have getters for those properties. Now there is another class called GradeBook in which there is a an array of type Record. I manually loaded the record array via a method called loadFromTables as follows:
private void loadFromTables(){
String[] students = {
"S10","S20","S30","S40","S50", "S60",
"S08","S18","S28","S38","S48", "S58",
"S06","S16","S26","S36","S46", "S56",
};
int[] assignment = {
0, 10, 20, 30, 30, 40,
0, 10, 20, 30, 30, 40,
0, 10, 20, 30, 30, 40,
};
int[] exam = {
0, 39, 44, 44, 54, 59,
1, 40, 45, 45, 55, 60,
2, 41, 46, 46, 56, 58,
};
nrecords = students.length;
gradeBook = new Record[nrecords];
for (int i = 0; i < nrecords; i++ ) {
int t = assignment[i] + exam[i];
String g = calculateGrade(t);
Record r = new Record( students[i], assignment[i], exam[i], t, g );
gradeBook[i] = r;
}
}
Now I want to do binary search to find a Record by the property studentId. But first I'd have to sort the Record array. I am told to use Selection sort. So, I do this and I think this is where the problem lies but I can't seem to figure out where..:
private void sortById(){
//Selection Sort
for(int i=0; i<nrecords-1; i++){
int index = i;
for(int j=i+1; j<nrecords; j++){
if((gradeBook[index].studentId).compareTo(gradeBook[j].studentId) > 0){
index = j;
}
Record temp = gradeBook[i];
gradeBook[i] = gradeBook[index];
gradeBook[index] = temp;
}
}
}
And here is the code of binary search that I used although i think the binary search has been implemented correctly. Because i tried to do it with bubble sort and that did precisely what i wanted.
public Record find(String id){
//Binary Search
int low = 0;
int high = nrecords - 1;
Record record = null;
while(low <= high){
int mid = (high + low)/2;
if(id.compareTo(gradeBook[mid].studentId) == 0){
record = new Record(id, gradeBook[mid].assignment, gradeBook[mid].exam, gradeBook[mid].total, gradeBook[mid].grade);
return record;
}
else if(id.compareTo(gradeBook[mid].studentId) > 0){
low = mid + 1;
}
else if(id.compareTo(gradeBook[mid].studentId) < 0){
high = mid - 1;
}
}
return record;
}
Thanks in advance. I know the problem is in selection sort and it's eating my head. Appreciate your suggestions! :)
In selection sort, We first iterate through the sub-array and find the minimum element in the sub-array, then at last in each iteration, Swap the current and minimum element.
Problem in your code is here.
for(int j=i+1; j<nrecords; j++){
if((gradeBook[index].studentId).compareTo(gradeBook[j].studentId) > 0){
index = j;
}
Record temp = gradeBook[i];
gradeBook[i] = gradeBook[index];
gradeBook[index] = temp;
}
You have found minimum element correctly but you are doing swaps in the iterations when you find a lexicographic smaller string than the current one. So in this loop, you just need to find the minimum element and swap operation should be done after execution of this loop.
Corrected Code :
private void sortById(){
//Selection Sort
for(int i=0; i<nrecords-1; i++){
int index = i;
for(int j=i+1; j<nrecords; j++){
if((gradeBook[index].studentId).compareTo(gradeBook[j].studentId) > 0){
index = j;
}
Record temp = gradeBook[i];
gradeBook[i] = gradeBook[index];
gradeBook[index] = temp;
}
}
}

How do I pass int values from one method to another

I'm trying to find the lowest time in minutes of the array int [] times, but I can't figure out how to make the second method work; I'm not getting any output.
public static void main(String[] arguments) {
String[] names = { "Elena", "Thomas", "Hamilton", "Suzie", "Phil",
"Matt", "Alex", "Emma", "John", "James", "Emily", "Daniel",
"Neda", "Aaron", "Kate" };
int[] times = { 321, 273, 278, 329, 445, 402, 388, 275, 243, 334, 412,
393, 299, 343, 317, 265 };
for (int i = 0; i < names.length; i++)
System.out.println(names[i] + ":" + times[i]);
}
I don't know what it's missing but i know i should get the lowest time in minutes: which is 243 (int [] times). I "believe" i need to pass the int time values from the first method to the second method...since i feel the second method array is empty. However, that, i don't know how to do. Help?
public static int getMinIndex(int[] values) {
int minValue = Integer.MAX_VALUE;
int minIndex = -1;
for (int i = 0; i < values.length; i++)
if (values[i] < minValue) {
minValue = values[i];
minIndex = i;
}
return minIndex; //not returning anything.
}
The logic of your program is:
1. Declaring an array of names.
2. Declaring an array of times.
3. Writing the names and times through a loop to the console.
You also wrote a method to retrieve the minimum value within an int array,
but you did not include that in your program, which starts from the first line of the main method.
So the first question would be, where would you like to use the minimum value.
and the second question would be, what would you like to do with the minimum value.
Suppose you want to show the min value on the console,
simply write:
System.out.println(getMinValue(times));
This way the method's return value is passed to the static method of System.out as an argument, suppose you want to do something else, pass it to another method that accepts int arrays.
Write this in your main method
int min_index = getMinIndex(times);
You forget to call method. Here min_index contains the integer value that you have to return from the method.
First, I would suggest you really want a getMinValue(int... arr)
public static int getMinValue(int... values) {
// Handle null and the empty array
if (values == null || values.length < 1) {
return -1;
}
// start at the first element
int minValue = values[0];
for (int i = 1; i < values.length; i++) {
if (values[i] < minValue) {
minValue = values[i];
}
}
// return the minimum value
return minValue;
}
Then you would call it with
public static void main(String[] args) {
System.out.println(getMinValue(4, 0, 2, 3));
int[] arr = { 5, 6, 7, 8, 3, 2 };
System.out.println(getMinValue(arr));
}
Output is
0
2

Reverse order of single dimensional array in Java [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I reverse an int array in Java?
I need to reverse the order of the given numbers in the array without using a temp.
public class Reverse
{
public static void main (String[] args)
{
int[] num = { 12, 34, 50, 67, 88 }, cl, cl2;
for (i=0; i < a.length; i++)
{
cl = a[i];
cl2 = a[(a.length - 1 )-1];
System.out.println (cl1 + " " + cl2);
}
}
}
Since it only seems that you're printing the values out, you can iterate over your array backwards.
for(int i = a.length - 1; i >= 0; i--) {
// relevant code here
}
you can use Collections#reverse to inline a reverse sort of the integer array,
Collections.reverse(Arrays.asList(num));
The answers given are perfect. But i just added another answer in case if you want to store the reverse array into the original array without using any temp. use this.
public class Reverse
{
public static void main (String[] args)
{
int[] a = { 12, 34, 50, 67, 88 };
int i, j;
for (i = 0, j = a.length - 1; i < j; i++, j--)
{
a[i]=a[i]+a[j];
a[j]=a[i]-a[j];
a[i]=a[i]-a[j];
}
}
}

Categories