The problem I am trying to solve is as follows:-
Given an array of ints length 3, return an array with the elements "rotated left" so {1, 2, 3} yields {2, 3, 1}
I came up with the following code:-
public int[] rotateLeft3(int[] nums) {
for(int i=0;i<2;i++)
swap(nums[i],nums[i+1]);
return nums;
}
public void swap(int a,int b)
{
int temp = a;
a = b;
b= temp;
}
However, it is not running successfully. In case of C++, I could have passed references as arguments and the problem would have been sorted then why is not happening here?
The following code is working:-
public int[] rotateLeft3(int[] nums) {
int temp = nums[0];
nums[0] = nums[1];
nums[1] = temp;
temp = nums[1];
nums[1] = nums[2];
nums[2] = temp;
return nums;
}
But this code is complete brute-force writing and I am not liking it very much. Can you please suggest how I can make the first approach work?
All parameters in java method calls are passed by value. You need to pass in the array and the two indexes you want to swap.
public void swap(int[] array, int a,int b)
{
int temp = array[a];
array[a] = array[b];
array[b]= temp;
}
As you have said the problem is passing by reference, C does it - Java doesn't. There are plenty of other ways to achieve the same ends though.
The simplest way is to pass the array and the two indexes to your swap function rather than the contents of the array at that index.
If you want a rotation that isn't limited by size, try:
public int[] rotateLeft(int[] nums){
if(nums.length == 0)
return new int[0];
int temp = nums[0];
//This loop starts at index 1 because we are moving
// elements left, and 0 can't move left.
for(int index = 1; index < nums.length; index++){
nums[index-1] = nums[index];
}
nums[nums.length-1] = temp;
}
you can also use the xor swap without the temp variable ;)
public void swap(int[] array, int ind1, int ind2) {
array[ind1] ^= array[ind2]
array[ind1] ^= (array[ind2] ^= array[ind1])
}
When you call the swap method , you are passing the values inside your array, but that method does not return the a and b values. Yes, that could be done in C/C++ with the use of pointers, but java does not have it.
Xynariz's code provide a way of doing the shift that is not limited to array size.
You can create a swap function with a single line usage pattern, but the calling format is not typical:
public int[] rotateLeft3(int[] nums) {
for(int i=0;i<2;i++)
nums[i+1] = swap(nums[i], nums[i]=nums[i+1]);
return nums;
}
// swaps any number of same type objects
public <T> T swap(T... args) {
// usage: z = swap(a, a=b, b=c, ... y=z);
return args[0];
}
This works because the first argument is passed into swap before the assignments happen in rest of the arguments.
Related
I am trying to self-learn Java, and have an issue with these arrays I have to make without ArrayLists. I tried to look online on static methods, but I can't find anything that could help me understand. I have to make 3 methods that can be used to modify arrays. So, for adding a value to the end of an array, the method should have the array and the value as parameters. It should then return a new array which is the same as the old array but with the added on value. The site I'm trying to learn this on shows me the block of code and explains what methods do, but it doesn't show me how to use them.
public class Arrays {
static void array() {
System.out.print("1, 2, 4, 7");
}
static void add() {
System.out.print(", 11");
}
public static void main(String[] args) {
System.out.println("Array:");
array();
System.out.println(" ");
System.out.println("Array with Added End:");
array();
add();
System.out.println(" ");
}
}
...for adding a value to the end of an array, the method should have the array and the value as parameters. It should then return a new array which is the same as the old array but with the added on value.
I'm going to assume that add is the method that will add something to your array and that your array is of type int[]. I'll build the method step-by-step:
method should have the array and the value as parameters
add(int[] arr, int val) {}
It should then return a new array which is the same as the old array
The return type of the method must therefore be the same as the array parameter arr. Since you stated the method must be static:
public static int[] add(int[] arr, int val)
{
// todo: make this work
}
It should then return a new array which is the same as the old array but with the added on value.
Arrays cannot be resized so you need to create a new array (which is also specified in the instructions) that is large enough to hold all the elements of arr plus one additional element. There are several ways to populate your new array:
Copying each element yourself:
public static int[] add(int[] arr, int val)
{
int[] newArray = new int[arr.length + 1];
for (int index = 0; index < arr.length; index++)
{
newArray[index] = arr[index];
}
// Arrays start at index 0 so arr.length will be the last
// position in newArray.
newArray[arr.length] = val;
return newArray;
}
Using java.util.Arrays:
public static int[] add(int[] arr, int val)
{
int[] newArray = Arrays.copyOf(arr, arr.length + 1);
newArray[arr.length] = val;
return newArray;
}
Using System.arraycopy:
public static int[] add(int[] arr, int val)
{
int[] newArray = new int[arr.length + 1];
System.arraycopy(arr, 0, newArray, 0, arr.length);
newArray[arr.length] = val;
return newArray;
}
This should be enough of an example on working with arrays to help you write the other two methods.
Working on an addBefore() method that adds a new element to the beginning of an array of ints and then causes the existing elements to increase their index by one.
This is what is showing in the console when trying to run --
java.lang.RuntimeException: Index 1 should have value 11 but instead has 0
at IntArrayListTest.main(IntArrayListTest.java:67)
Below is the code I have so far.
public class IntArrayList {
private int[] a;
private int length;
private int index;
private int count;
public IntArrayList() {
length = 0;
a = new int[4];
}
public int get(int i) {
if (i < 0 || i >= length) {
throw new ArrayIndexOutOfBoundsException(i);
}
return a[i];
}
public int size() {
return length;
}
public void set(int i, int x) {
if (i < 0 || i >= a.length) {
throw new ArrayIndexOutOfBoundsException(i);
}
a[i] = x;
}
public void add(int x) {
if (length >= a.length) {
int[] b = new int[a.length * 2];
for (int i = 0; i < a.length; i++) {
b[i] = a[i];
}
a = b;
//count += 1;
}
a[length] = x;
count++;
length = length + 1;
}
public void addBefore(int x) {
int[] b = new int[a.length*2];
for (int i = 0; i < a.length; i++) {
b[i+a.length] = a[i];
}
a = b;
a[index] = x;
length ++;
}
}
Whether you add first or last, you need to only grow the array size if it is already full.
The count field seems to be exactly the same as length, and index seems unused and meaningless as a field, so remove them both.
To rearrange values in an array, use this method:
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
You two "add" methods should then be:
public class IntArrayList {
private int[] a; // Underlying array
private int length; // Number of added elements in a
// other code
public void add(int x) {
if (length == a.length) {
int[] b = new int[a.length * 2];
System.arraycopy(a, 0, b, 0, length);
a = b;
}
a[length++] = x;
}
public void addBefore(int x) {
if (length < a.length) {
System.arraycopy(a, 0, a, 1, length);
} else {
int[] b = new int[a.length * 2];
System.arraycopy(a, 0, b, 1, length);
a = b;
}
a[0] = x;
length++;
}
}
If the answer requires you to do the looping yourself then something like this should work fine (one of a few ways to do this, but is O(n)) :
public void addBefore(int x) {
if(length + 1 >= a.length){
int[] b = new int[a.length*2];
b[0] = x;
for (int i = 0; i < length; i++) {
b[i + 1] = a[i];
}
a = b;
} else {
for (int i = length; i >= 0 ; i--) {
a[i + 1] = a[i];
}
a[0] = x;
}
length++;
}
I noticed this started running a "speed test" - not sure how useful a test like that is, as it would be based on cpu performance, rather than testing complexity of the algorithm ..
you had three problems with your solution:
you increased the length of a every time the method was called. this would quickly create an OutOfMemoryException
when you copied values from a to b, you did b[i+a.length] = a[i]; which means the values would be copied to the middle of b instead of shift just one place
at the end, you put the new value in the end of the array instead of at the beginning.
all this I was able to see because I used a debugger on your code. You need to start using this tool if you want to be able to detect and fix problems in your code.
so fixed solution would do this:
check if a is full (just like it is done with add() method) and if so, create b, and copy everything to it and so on)
move all values one place ahead. the easiest way to do it is to loop backwards from length to 0
assign new value at the beginning of the array
here is a working solution:
public void addBefore(int x) {
// increase length if a is full
if (length >= a.length) {
int[] b = new int[a.length * 2];
for (int i = 0; i < a.length; i++) {
b[i] = a[i];
}
a = b;
}
// shift all values one cell ahead
for (int i = length; i > 0; i--) {
a[i] = a[i-1];
}
// add new value as first cell
a[0] = x;
length ++;
}
}
You can use the existing Java methods from the Colt library. Here is a small example that uses a Python syntax (to make the example code small I use Jython):
from cern.colt.list import IntArrayList
a=IntArrayList()
a.add(1); a.add(2) # add two integer numbers
print "size=",a.size(),a
a.beforeInsert(0, 10) # add 10 before index 0
print "size=",a.size(),a
You can use DataMelt program to run this code. The output of the above code is:
size= 2 [1, 2]
size= 3 [10, 1, 2]
As you can see, 10 is inserted before 1 (and the size is increased)
Feel free to change the codding to Java, i.e. importing this class as
import cern.colt.list.IntArrayList
IntArrayList a= new IntArrayList()
You could use an ArrayList instead and then covert it to an Integer[] Array which could simplify your code. Here is an example below:
First create the ArrayList:
ArrayList<Integer> myNums = new ArrayList<Integer>();
Next you can add the values that you want to it, but I chose to just add the numbers 2-5, to illustrate that we can make the number 1 the first index and automatically increment each value by one index. That can simplify your addBefore() method to something such as this:
public static void addBefore(ArrayList<Integer> aList) {
int myInt = 1;
aList.add(0, myInt);
}
Since your ArrayList has ONE memory location in Java, altering the Array within a method will work (this would also work for a regular Array). We can then add any value to the beginning of the ArrayList. You can pass an Integer to this method as the second argument (int x), if you want, but I simply created the myInt primitive to simplify the code. I know that in your code you had the (int x) parameter, and you can add that to this method. You can use the ArrayList.add() method to add the int to index 0 of the Array which will increment each Array element by 1 position. Next you will need to call the method:
addBefore(myNums);//You can add the int x parameter and pass that as an arg if you want here
Next we can use the ArrayList.toArray() method in order to covert the ArrayList to an Integer Array. Here is an example below:
Integer[] integerHolder = new Integer[myNums.size()];
Integer[] numsArray = (Integer[])myNums.toArray(integerHolder);
System.out.println(Arrays.toString(numsArray));
First we create an ArrayHolder that will be the same size as your ArrayList, and then we create the Array that will store the elements of the ArrayList. We cast the myNums.toArray() to an Integer Array. The results will be as follows. The number 1 will be at index 0 and the rest of your elements will have incremented by 1 index:
[1, 2, 3, 4, 5]
You could do the entire process within the addBefore() method by converting the Array to an ArrayList within the method and adding (int x) to the 0 index of the ArrayList before converting it back into an Array. Since an ArrayList can only take a wrapper class object you'll simply need to convert the int primitive Array into the type Integer for this to work, but it simplifies your addBefore() method.
I have a programming exam in a few days so I'm doing some exercises just to practice. However, I've been stuck with this problem and I started to doubt if it's possible to do it. Write a recursive method called arrayReverse which takes in an array of integers and returns said array in reversed sorted order. So an example would be:
input: [1,2,3]
output:[3,2,1]
I wasn't able to solve it. My intuition was to take the last element of the array, put it at the beginning, i,e: index[0] and then recursively call the rest of the array but then taking the new last element and put it on index[1]. Unfortunately, the implementation was harder than I thought but I (for the sake of trying) edited the question in a way that it accepts 2 arrays and this was my code:
import java.util.Arrays;
class Test {
int[] arrayReverse(int[] m, int[] mReverse) {
if (m.length == 1) {
mReverse[mReverse.length - 1] = m[0];
return mReverse;
} else {
int lastNum = m[m.length - 1];
mReverse[mReverse.length - m.length] = lastNum;
int[] arrayMinusOne = cropArray(m);
return arrayReverse(arrayMinusOne, mReverse);
}
}
int[] cropArray(int[] m) {
int[] mCropped = new int[m.length - 1];
for (int i = 0; i < m.length - 1; i++) {
mCropped[i] = m[i];
}
return mCropped;
}
}
void demo() {
int[] helpTest4 = new int[]{1, 2, 3};
int[] emptyArray = new int[helpTest4.length];
int[] test4 = arrayReverse(helpTest4, emptyArray);
System.out.println(Arrays.toString(test4));
}
public static void main(String[] args) {
new Test().demo();
}
}
It works perfectly but I'm not satisfied with the result because of two reasons:
I wasn't able to do it completely recursive. I used a for loop in cropArray.
I couldn't do it on one array.
How can this be done?
Option1: Using only one parameter (array) in the recursive function
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
public class MyClass {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
int[] reversed = reverseArray(arr);
System.out.println(Arrays.toString(reversed));
}
public static int[] reverseArray(int[] arr)
{
if (arr.length == 0)
return arr;
// remove first element
int first = arr[0];
int[] list = Arrays.copyOfRange(arr, 1, arr.length);
//Calling Function Recursively get reversed array
int[] returnArr = reverseArray(list);
//Add original first to the last of the arrayToReturn
returnArr = Arrays.copyOf(returnArr, returnArr.length + 1);
returnArr[returnArr.length - 1] = first;
return returnArr;
}
}
Option2:
void reverseArray(int[] x){
reverse(x, 0, x.length -1);
}
void reverse(int[] x, int i, int j){
if(i<j){//Swap ith with jth element where i and j are equidistant from ends
int tmp = x[i];
x[i] = x[j];
x[j] = tmp;
reverse(x, ++i, --j);//Recursive
}
}
Test:
int[] s = new int[]{1,2,3,4,5};
reverseArray(s);
System.out.println(Arrays.toString(s));//"5,4,3,2,1"
Recursive, O(n), no temporary Array needed.
Please try the code below:
import java.util.*;
public class HelloWorld{
public static void main(String []args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int arr[]= new int[n];
for(int i=0;i<n;i++)
{
arr[i] = sc.nextInt();
}
Printsum(arr,0);
}
public static void Printsum(int arr[], int idx)
{
if(idx == arr.length)
return ;
Printsum(arr,idx+1);
System.out.println(arr[idx]);
}
}
I don't think this is a particularly good question - there is obviously a direct and clear way to do it without recursion; so the question does little to demonstrate any useful knowledge of recursion.
That said I believe the algorithm they were seeking uses the facts that:
a) reversing a 1 length array is trivial
b) you can reverse an n length array by appending the first element to the reverse the the last n-1 elements.
So code for this solution will look much simpler that what you currently have.
Ruby:
def reverse(a)
if a.empty?
return []
else
return [a.last] + reverse(a[0..-2])
end
end
a = [1, 2, 3]
reverse(a)
Taking the request literally, I have come out with a solution which only needs ONE recursive function with just ONE input/output parameter:
public static void arrayReverse(int[] input)
{
if (input.length > 0)
{
// Store locally the fist element:
int firstElement=input[0];
// Creates a sub-array and reverses it:
int[] input2=new int[input.length - 1];
System.arraycopy(input, 1, input2, 0, input2.length);
arrayReverse(input2);
// Copies back the reversed array into the current array:
System.arraycopy(input2, 0, input, 0, input2.length);
// Puts the stored fist element in the last position:
input[input.length - 1]=firstElement;
}
}
This solution is based upon a stack structure, for which it takes advantage of the machine calling stack at runtime, where the local values are stored while the function is executing.
The base case of this recursion is, of corse, the empty array.
In the generic case, the function stores locally the first element, then re-invokes itself recursively to reverse the rest of the array, and last, puts back the first element in the last position.
I'm using Java.
I need to implement a recursive function that calculates the difference between each two values and returns for me array in size 2 [MAXIMUM_DIFF, STARTINDEX].
For the following array:
arr = {1, 4, 60, -10, 2, 7, 56, -10}
The recursive method returns array in size 2: [70,2] because the maximum difference is 70 (60-(-10)=70) and the index of 60 is 2.
I have 90% from the solution:
public static int[] getMax(int[] arr) {
int [] retArr = new int[2];
if(arr.length == 1)
return retArr;
else {
return getMax(arr, retArr);
}
}
public static int[] getMax(int[] arr, int[] retArr) {
if(retArr[1] == arr.length - 1)
return retArr;
int currentMaxVal = arr[retArr[1]] - arr[retArr[1] + 1];
if(currentMaxVal > retArr[0]) {
retArr[0] = currentMaxVal;
}
retArr[1] = retArr[1] + 1;
return getMax(arr, retArr);
}
But the result is[70,7] instead of [70,2] because this line retArr[1] = retArr[1] + 1;
This is because I don't know where to save the index, So how can I save the index?
*I'm not sure about the second param of getMax(int [] arr, int []retArr)
Its can be different maybe
I cant add another parameters, Maybe to change the second param of getMax(int [] arr, int []retArr), And I can't use static variables
if(currentMaxVal > retArr[0])
{
retArr[0] = currentMaxVal;
}
retArr[1] = retArr[1] + 1;
Should be
if(currentMaxVal > retArr[0])
{
retArr[0] = currentMaxVal;
retArr[1] = currentIndex;
}
And currentIndex should be an additional parameter passed to the function. (and other references to current index updated accordingly)
UPDATE:
I think the point here is to understand "divide and conquer", where you break up the problem into a smaller problem, and then sort through for the best one. Something like this (if a bit more awkward then a normal case)
public static int[] getMax(int[] arr, int[] retArr) {
// Return case
if (retArr[1] >= arr.length - 1)
return new int[] { Integer.MIN_VALUE, retArr[1] };
// Save context
int index = retArr[1];
int value = arr[index] - arr[index + 1];
// Call recursion
retArr[1]++;
int[] temp = getMax(arr, retArr);
// Return best between current case and recursive case
if (temp[0] > value)
return temp;
else
return new int[] { value, index };
}
Each call (or stack) of the recursive function is its own context. That means variables declared in it won't be overwritten in the recursive calls. The idea is that you break a hard problem down recursively until you can't break it down any further. Then you solve it by putting together the results of each call one at a time until you have your final answer. (This works better with less trivial cases like the fibonacci sequence) Also note that anything that can be done in a loop will always be more efficient then recursion.
I am working on getting the counts of comparisons and movers when merge sorting. I think I have the recursion I need thanks to this Sort Comparisons Counter but I can not get it to print out. I am obviously very new at programming so I'd be appreciative if you could explain what it is that I am missing.
import java.util.Arrays;
public class MergeSort {
int count = 0;
/**
* #param args
*/
// Rearranges the elements of a into sorted order using
// the merge sort algorithm (recursive).
public int mergeSort(int[] a, int howMany) {
if (a.length >= 2) {
// split array into two halves
int[] left = Arrays.copyOfRange(a, 0, a.length/2);
int[] right = Arrays.copyOfRange(a, a.length/2, a.length);
// sort the two halves
howMany = mergeSort(left,howMany);
howMany = mergeSort(right, howMany);
// merge the sorted halves into a sorted whole
howMany = merge ( left, right, a, howMany);
}
return howMany;
}
// Merges the left/right elements into a sorted result.
// Precondition: left/right are sorted
public static int merge(int[] result, int[] left,
int[] right, int howMany) {
int i1 = 0; // index into left array
int i2 = 0; // index into right array
for (int i = 0; i < result.length; i++) {
if (i2 >= right.length ||
(i1 < left.length && left[i1] <= right[i2])) {
result[i] = left[i1]; // take from left
i1++;
} else {
result[i] = right[i2]; // take from right
i2++;
}
}
return howMany;
}
System.out.println(howMany); // ???
}
you need to call the method through its object wherever you wanna print. something like this (may be in your main method):
MergeSort mObj - new MergeSort();
int[] array = {1,2,3};
int count = mObj.mergeSort(array, 2);
System.out.println(count);
Basically, you need a driver method. When a java class is run, it will look for a public static void main(String[] args) method; if this method doesn't exist, nothing will happen. With what you have now, you should actually get a compile error from System.out.println(howMany); since the variable howMany only exists within the scope (brackets) of the merge method. To understand this better I'd review your notes on variable and method scope and class members. For a quick fix, remove the line at the bottom that I mentioned above, and place this method somewhere in your class:
public static void main(String[] args) {
int[] array = {2,5,8,1,3};
int howMany = mergeSort(array, 5);
System.out.println(howMany);
}
You also need to make your mergeSort method static, so change its definition to
public **static** int mergeSort(int[] a, int howMany)
I tested your code and I'm pretty sure that it doesn't give the answer you want, so be sure to check that. Best of luck learning object oriented programming!