I created a 2D array of int[]
Now, I want to swap two int[] inside of 2D array
I have this for my code:
swap(values[row][col], values[randomRow][randomCol]);
where values is a 2D array of int[].
so values[int][int] is a int[];
I get an error message like this:
Error: The method swap(int[], int[]) is undefined for the type ShufflePic
How should I fix this?
Thanks a lot!
Java is pass-by-value. You cannot swap values like this.
Instead use this approach :
void swap(int[][] array, int row1, int col1, int row2, int col2) {
int temp = array[row1][col1];
array[row1][col1] = array[row2][col2];
array[row2][col2] = temp;
}
Now you can call swap(...) method to swap the values
swap(values, row, col, randomRow, randomCol);
mybe your method should looks like
swap(int[] arryFirst, int arryFirstRow, int arryFirstCol, int[] arrySec, int arrySecRow, int arrySecCol)
Basically, this finds the indices and swaps according to these indices. Try printing the items in the list after swapping. Of course, this technique could also be implemented for 2D arrays, but I'll leave that as a challenge for you.
public class Test {
static int[] list = {4, 5, 6, 3, 1, 2};
public static void main(String[] args) {
swap(6, 2); // test swap
}
public static void swap(int a, int b) {
int a_index = 0;
int b_index = 0;
for (int i = 0; i < list.length; i++) {
if (list[i] == a) a_index = i;
if (list[i] == b) b_index = i;
}
list[a_index] = b;
list[b_index] = a;
}
}
I created a 2D array of int[]
You did indeed do that, but you probably wanted to create a 2D array of int, not int[].
values[row][col] = 5 //2d int array
values[row][col] = new int[length] //3d int array. Probably not what you intended
Once you fix that, the other answers about passing by value should work for you.
EDIT:
If that's what you want, then this method should work:
public void swapArrays(int[][][] arr, int row1, int col1, int row2, int col2) {
int[] temp = arr[row1][col1];
arr[row1][col1] = arr[row2][col2];
arr[row2][col2] = temp;
}
You would then call this with:
swapArrays(values, row, col, randomRow, randomCol);
The reason you were getting the error is because you hadn't defined a swap function which takes in two arrays. However, even if you had, it wouldn't have functioned properly because of the pass-by-value, pass-by-reference thing. (Google it for more info on that.)
With my proposed method, it will have a reference to the entire array, enabling it to change its values. If you just passed in values[row][col], the method would only see the value stored at that index, but not access to the values array.
Related
I have the task of determining whether each value from 1, 2, 3... n is in an unordered int array. I'm not sure if this is the most efficient way to go about this, but I created an int[] called range that just has all the numbers from 1-n in order at range[i] (range[0]=1, range[1]=2, ect). Then I tried to use the containsAll method to check if my array of given numbers contains all of the numbers in the range array. However, when I test this it returns false. What's wrong with my code, and what would be a more efficient way to solve this problem?
public static boolean hasRange(int [] givenNums, int[] range) {
boolean result = true;
int n = range.length;
for (int i = 1; i <= n; i++) {
if (Arrays.asList(givenNums).containsAll(Arrays.asList(range)) == false) {
result = false;
}
}
return result;
}
(I'm pretty sure I'm supposed to do this manually rather than using the containsAll method, so if anyone knows how to solve it that way it would be especially helpful!)
Here's where this method is implicated for anyone who is curious:
public static void checkMatrix(int[][] intMatrix) {
File numberFile = new File("valid3x3") ;
intMatrix= readMatrix(numberFile);
int nSquared = sideLength * sideLength;
int[] values = new int[nSquared];
int[] range = new int[nSquared];
int valCount = 0;
for (int i = 0; i<sideLength; i++) {
for (int j=0; j<sideLength; j++) {
values[valCount] = intMatrix[i][j];
valCount++;
}
}
for (int i=0; i<range.length; i++) {
range[i] = i+1;
}
Boolean valuesThere = hasRange(values, range);
valuesThere is false when printed.
First style:
if (condition == false) // Works, but at the end you have if (true == false) or such
if (!condition) // Better: not condition
// Do proper usage, if you have a parameter, do not read it in the method.
File numberFile = new File("valid3x3") ;
intMatrix = readMatrix(numberFile);
checkMatrix(intMatrix);
public static void checkMatrix(int[][] intMatrix) {
int nSquared = sideLength * sideLength;
int[] values = new int[nSquared];
Then the problem. It is laudable to see that a List or even better a Set approach is the exact abstraction level: going into detail not sensible. Here however just that is wanted.
To know whether every element in a range [1, ..., n] is present.
You could walk through the given numbers,
and for every number look whether it new in the range, mark it as no longer new,
and if n new numbers are reached: return true.
int newRangeNumbers = 0;
boolean[] foundRangeNumbers = new boolean[n]; // Automatically false
Think of better names.
You say you have a one dimensional array right?
Good. Then I think you are thinking to complicated.
I try to explain you another way to check if all numbers in an array are in number order.
For instance you have the array with following values:
int[] array = {9,4,6,7,8,1,2,3,5,8};
First of all you can order the Array simpel with
Arrays.sort(array);
After you've done this you can loop through the array and compare with the index like (in a method):
for(int i = array[0];i < array.length; i++){
if(array[i] != i) return false;
One way to solve this is to first sort the unsorted int array like you said then run a binary search to look for all values from 1...n. Sorry I'm not familiar with Java so I wrote in pseudocode. Instead of a linear search which takes O(N), binary search runs in O(logN) so is much quicker. But precondition is the array you are searching through must be sorted.
//pseudocode
int range[N] = {1...n};
cnt = 0;
while(i<-inputStream)
int unsortedArray[cnt]=i
cnt++;
sort(unsortedArray);
for(i from 0 to N-1)
{
bool res = binarySearch(unsortedArray, range[i]);
if(!res)
return false;
}
return true;
What I comprehended from your description is that the array is not necessarily sorted (in order). So, we can try using linear search method.
public static void main(String[] args){
boolean result = true;
int[] range <- Contains all the numbers
int[] givenNums <- Contains the numbers to check
for(int i=0; i<givenNums.length; i++){
if(!has(range, givenNums[i])){
result = false;
break;
}
}
System.out.println(result==false?"All elements do not exist":"All elements exist");
}
private static boolean has(int[] range, int n){
//we do linear search here
for(int i:range){
if(i == n)
return true;
}
return false;
}
This code displays whether all the elements in array givenNums exist in the array range.
Arrays.asList(givenNums).
This does not do what you think. It returns a List<int[]> with a single element, it does not box the values in givenNums to Integer and return a List<Integer>. This explains why your approach does not work.
Using Java 8 streams, assuming you don't want to permanently sort givens. Eliminate the copyOf() if you don't care:
int[] sorted = Arrays.copyOf(givens,givens.length);
Arrays.sort(sorted);
boolean result = Arrays.stream(range).allMatch(t -> Arrays.binarySearch(sorted, t) >= 0);
public static boolean hasRange(int [] givenNums, int[] range) {
Set result = new HashSet();
for (int givenNum : givenNums) {
result.add(givenNum);
}
for (int num : range) {
result.add(num);
}
return result.size() == givenNums.length;
}
The problem with your code is that the function hasRange takes two primitive int array and when you pass primitive int array to Arrays.asList it will return a List containing a single element of type int[]. In this containsAll will not check actual elements rather it will compare primitive array object references.
Solution is either you create an Integer[] and then use Arrays.asList or if that's not possible then convert the int[] to Integer[].
public static boolean hasRange(Integer[] givenNums, Integer[] range) {
return Arrays.asList(givenNums).containsAll(Arrays.asList(range));
}
Check here for sample code and output.
If you are using ApacheCommonsLang library you can directly convert int[] to Integer[].
Integer[] newRangeArray = ArrayUtils.toObject(range);
A mathematical approach: if you know the max value (or search the max value) check the sum. Because the sum for the numbers 1,2,3,...,n is always equal to n*(n+1)/2. So if the sum is equal to that expression all values are in your array and if not some values are missing. Example
public class NewClass12 {
static int [] arr = {1,5,2,3,4,7,9,8};
public static void main(String [] args){
System.out.println(containsAllValues(arr, highestValue(arr)));
}
public static boolean containsAllValues(int[] arr, int n){
int sum = 0;
for(int k = 0; k<arr.length;k++){
sum +=arr[k];
}
return (sum == n*(n+1)/2);
}
public static int highestValue(int[]arr){
int highest = arr[0];
for(int i = 0; i < arr.length; i++) {
if(highest<arr[i]) highest = arr[i];
}
return highest;
}
}
according to this your method could look like this
public static boolen hasRange (int [] arr){
int highest = arr[0];
int sum = 0;
for(int i = 0; i < arr.length; i++) {
if(highest<arr[i]) highest = arr[i];
}
for(int k = 0; k<arr.length;k++){
sum +=arr[k];
}
return (sum == highest *(highest +1)/2);
}
So I have this piece of code declaring a three dimensional array:
public class Matrix {
private static int n;
char[][][] matrix = new char[n][n][2];
Matrix(int n){
n=3;
} }
In the constructor of the class,n gets initialized with a value(let's say 3).
The problem is that when I try to access an element of the matrix(let's say matrix[0][0][0]) I get an "ArrayIndexOutOfBoundsException".
It seems that my matrix has length of 0.
But if I try something like:
char[][][] matrix = new char[3][3][2]
it works just fine,memory is alocated for the matrix.
Also,in my program I use at some point something like this:
char[][] bidimensionalMatrix = new char[n][n];
also,works like a charm, I can access the elements of this one too.
Why is this? I am not allowed to specify the dimension of a three dimensional matrix using a variable?
You are allowed to define the size of an array with a variable. However, your constructor comes after you have initialized the array, and when the array is initialized, 'n' is 0. Remember, array sizes cannot be changed once created. Instead, you should initialize the array within your constructor.
public class Matrix {
private static int n;
char[][][] matrix;
Matrix(int num){
n = num;
matrix = new char[n][n][2];
}
}
You have to initialize the value of n before you can specify the size of the arrays.
Here is a simple class with multiple sized arrays.
class Matrix {
private int width, height, depth;
private char[][][] matrix;
public Matrix(int width, int height, int depth) {
matrix = new char[height][width][depth];
}
public void set(int i, int j, int k, char value) {
matrix[i][j][k] = value;
}
public char get(int i, int j, int k) {
return matrix[i][j][k];
}
}
Sample run
class Main {
public static void main(String[] args) {
Matrix m = new Matrix(2, 2, 2);
m.set(0, 0, 0, 'c');
System.out.println(m.get(0, 0, 0)); // c
}
}
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 9 years ago.
Ok, I was misunderstanding the problem. After reading it a couple of times I figured out randInt is actually the method itself i am using to populate the array. So when it says to call randInt its some sort of recursive call I think. This is somehow what it should look like:
static int[] randInt(int i, int j) {
int[] temp = new int[(j - i) + 1];
for ( i = 0; i < j; i++) {
temp[i] = i + 1; // here i populate the array
}
System.out.println(Arrays.toString(temp)); // this prints [1, 2, 3, 4, 5]
for ( i = 1; i < j;i++){
swapReferences(temp[i], temp[randInt(0,i)] ); //this is some sort of recursive call that swaps the references
// btw that statement does not compile, how can i pass a method as a parameter?
}
return temp;
}
static void swapReferences(int a, int b) { //these parameters are wrong, need to be changed
//Method to swap references
}
Sorry for the confusion, but I think thats how it should be correctly.
Java is pass-by-value, so reassigning the parameters as you try to do will not work.
What you need to do is to have the array itself and two integer indices as parameters:
int randInt = generate.nextInt(j-i) + 1; //this is gonna generate a # within the range of the array (so if array is size 5, generates something 1-5)
for ( i = 1; i < j;i++){
swapReferences(temp, i, randInt); //and this is my attempt at swapping the references
randInt = generate.nextInt(i) + 1 ;
}
static void swapReferences(int[] array, int a, int b){
int x = array[a];
array[a] = array[b];
array[b] = x;
}
You can mutate parameters such as arrays passed into a method, as is being done here, but you can't reassign the parameters themselves.
You are just changing the ints that a and b are pointing to, but not what the indicies the array is pointing to. You need to change your swapReferences method to take the array as input, and something like the indicies to swap
static void swapReferences(int[] arr, int indexA, int index B){
int x = arr[indexA];
a = arr[indexB];
b = x;
arr[indexA] = a;
arr[indexB] = b;
}
or
static void swapReferences(int[] arr, int indexA, int indexB){
int x = arr[indexA];
arr[indexA] = arr[indexB];
arr[indexB] = x;
}
The code below does quick sort in C.I tried to translate the same code logic into java.But, i am unable to write the equivalent Java code statement for "partition(&arr[left+1],size-left-1);" in the partition function below.Can anyone help?
#include<stdio.h>
int main()
{
int arr[8]={4,8,1,6,3,7,2,5};
partition(arr,8);//Initial Calling of partition function
int i;
for(i=0;i<8;i++)
printf("%d ",arr[i]);
return 0;
}
void partition(int arr[],int size)
{
if(size<2)
return;
int pivot=arr[rand()%size];
int left=0,right=size-1,temp=0;
while(left<right)
{
while(arr[left]<pivot)
left++;
while(arr[right]>pivot)
right--;
temp=arr[left],arr[left]=arr[right],arr[right]=temp;//swapping values
}
//partitioning and recursive calling
partition(arr,left);
partition(&arr[left+1],size-left-1);//The problem is to write an equivalent code for this
//line in Java
}
To get rid of pointers you need to specify start and end by parameters. Define you function like the following:
void partition(int arr[],int start, int end)
and instead of:
int left=0,right=size-1,temp=0;
do
int left=start,right=end,temp=0;
C allows you to use pointers to refer to a different starting point in the same array. Java does not. You can only refer to the entire array.
But you can add the starting index as a parameter.
void partition(int arr[],int offset, int length) {
...
partition(arr[], left+1, size-left-1); // check calculation, might be wrong :)
}
A solution without needing to handle pointers is to change the header like this:
void partition(int array[], int firstElement, int lastElement);
You can also try the function copyOf described here:
copyOf
But you would have to reconstruct it back together since you're working on copies, and I doubt it would be much QUICKsort anymore
public static boolean[] copyOf(boolean[] original,
int newLength)
Copies the specified array, truncating or padding with false (if necessary) so the copy has the specified length. For all indices that are valid in both the original array and the copy, the two arrays will contain identical values. For any indices that are valid in the copy but not the original, the copy will contain false. Such indices will exist if and only if the specified length is greater than that of the original array.
Parameters:
original - the array to be copied
newLength - the length of the copy to be returned
Returns:
a copy of the original array, truncated or padded with false elements to obtain the specified length
Throws:
NegativeArraySizeException - if newLength is negative
NullPointerException - if original is null
Since:
1.6
The x argument refers to the "pivot " value. In any case you need to study how this algorithm works.
public static int partition(
int[] arr, int start, int end, int x)
{
int l = start,r = end;
while (l<r ) {
if (arr[l] < x)
{
l =l +1;
}
else {
int temp = arr[l];
arr[l] = arr[r-1];
arr[r-1] = temp;
r = r-1;
}
}
return l;
}
Below is the equivalent Java code for the above (problem) partition function written in C.The initial call to partition function,say,from inside main, may be somewhat like this:partition(arr,0,arr.length-1);
Thanks for all your support and guidance
static void partition(int arr[],int first,int last)
{
int left=first;
int right=last,temp=0;
if(left>=right)
return;
Random rnd=new Random();
int pivot = arr[left + rnd.nextInt(right - left)];
while(left<right)
{
while(arr[left]<pivot)
left++;
while(arr[right]>pivot)
right--;
temp=arr[left];
arr[left]=arr[right];
arr[right]=temp;
}
partition(arr,first,left);
partition(arr,left+1,last);
}
I have a problem. I am trying to write a value-returning method that returns the number of elements in an integer array. I have the array written and have the return statement half right. I am lost at this point. how to I get the number of elements in the array, which is 9, into an int form and into the return statement?
Thank you
public class ChapterEightCode
{
public static void main(String[] args)
{
int eTotals = myArray();
System.out.println(eTotals);
}
static int myArray()
{
int[] intArray = new int[] {1,2,3,4,5,6,7,8,9};
for (int i=0; i<intArray.length; i++)
{
System.out.println(intArray[i]);
}
int eTotals = 1000;
return eTotals;
}
}
Not sure why you are looping if you're just after the array length, try this:
return intArray.length;
Use the length field of the array:
return intArray.length;
Observe this method carefully:
You're first creating an integer array, then looping through each element from 0 to length of intArray, printing the elements one by one. Then you declare an integer eTotals, set it to 1000 and then return eTotals which means, you're returning 1000 all the time.
static int myArray()
{
int[] intArray = new int[] {1,2,3,4,5,6,7,8,9};
for (int i=0; i<intArray.length; i++)
{
System.out.println(intArray[i]);
}
int eTotals = 1000;
return eTotals; // instead `return intArray.length;`
}
Why not just return intArray.length;?
if u write a "int eTotals = 1000; return eTotals;" in the last of the function myArray(),I will fell that the code before has no meaning。
Maybe u can try replace the statement "int eTotals=1000;" as "int eTotals = intArray.length;"