So the goal is to rotate the elements in an array right a times.
As an example; if a==2, then array = {0,1,2,3,4} would become array = {3,4,0,1,2}
Here's what I have:
for (int x = 0; x <= array.length-1; x++){
array[x+a] = array[x];
}
However, this fails to account for when [x+a] is greater than the length of the array. I read that I should store the ones that are greater in a different Array but seeing as a is variable I'm not sure that's the best solution.
Thanks in advance.
Add a modulo array length to your code:
// create a newArray before of the same size as array
// copy
for(int x = 0; x <= array.length-1; x++){
newArray[(x+a) % array.length ] = array[x];
}
You should also create a new Array to copy to, so you do not overwrite values, that you'll need later on.
In case you don't want to reinvent the wheel (maybe it's an exercise but it can be good to know), you can use Collections.rotate.
Be aware that it requires an array of objects, not primitive data type (otherwise you'll swap arrays themselves in the list).
Integer[] arr = {0,1,2,3,4};
Collections.rotate(Arrays.asList(arr), 2);
System.out.println(Arrays.toString(arr)); //[3, 4, 0, 1, 2]
Arraycopy is an expensive operation, both time and memory wise.
Following would be an efficient way to rotate array without using extra space (unlike the accepted answer where a new array is created of the same size).
public void rotate(int[] nums, int k) { // k = 2
k %= nums.length;
// {0,1,2,3,4}
reverse(nums, 0, nums.length - 1); // Reverse the whole Array
// {4,3,2,1,0}
reverse(nums, 0, k - 1); // Reverse first part (4,3 -> 3,4)
// {3,4,2,1,0}
reverse(nums, k, nums.length - 1); //Reverse second part (2,1,0 -> 0,1,2)
// {3,4,0,1,2}
}
public void reverse(int[] nums, int start, int end) {
while (start < end) {
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start++;
end--;
}
}
Another way is copying with System.arraycopy.
int[] temp = new int[array.length];
System.arraycopy(array, 0, temp, a, array.length - a);
System.arraycopy(array, array.length-a, temp, 0, a);
I think the fastest way would be using System.arrayCopy() which is native method:
int[] tmp = new int[a];
System.arraycopy(array, array.length - a, tmp, 0, a);
System.arraycopy(array, 0, array, a, array.length - a);
System.arraycopy(tmp, 0, array, 0, a);
It also reuses existing array. It may be beneficial in some cases.
And the last benefit is the temporary array size is less than original array. So you can reduce memory usage when a is small.
Time Complexity = O(n)
Space Complexity = O(1)
The algorithm starts with the first element of the array (newValue) and places it at its position after the rotation (newIndex). The element that was at the newIndex becomes oldValue. After that, oldValue and newValue are swapped.
This procedure repeats length times.
The algorithm basically bounces around the array placing each element at its new position.
unsigned int computeIndex(unsigned int len, unsigned int oldIndex, unsigned int times) {
unsigned int rot = times % len;
unsigned int forward = len - rot;
// return (oldIndex + rot) % len; // rotating to the right
return (oldIndex + forward) % len; // rotating to the left
}
void fastArrayRotation(unsigned short *arr, unsigned int len, unsigned int rotation) {
unsigned int times = rotation % len, oldIndex, newIndex, length = len;
unsigned int setIndex = 0;
unsigned short newValue, oldValue, tmp;
if (times == 0) {
return;
}
while (length > 0) {
oldIndex = setIndex;
newValue = arr[oldIndex];
while (1) {
newIndex = computeIndex(len, oldIndex, times);
oldValue = arr[newIndex];
arr[newIndex] = newValue;
length--;
if (newIndex == setIndex) { // if the set has ended (loop detected)
break;
}
tmp = newValue;
newValue = oldValue;
oldValue = tmp;
oldIndex = newIndex;
}
setIndex++;
}
}
int[] rotate(int[] array, int r) {
final int[] out = new int[array.length];
for (int i = 0; i < array.length; i++) {
out[i] = (i < r - 1) ? array[(i + r) % array.length] : array[(i + r) % array.length];
}
return out;
}
The following rotate method will behave exactly the same as the rotate method from the Collections class used in combination with the subList method from the List interface, i.e. rotate (n, fromIndex, toIndex, dist) where n is an array of ints will give the same result as Collections.rotate (Arrays.asList (n).subList (fromIndex, toIndex), dist) where n is an array of Integers.
First create a swap method:
public static void swap (int[] n, int i, int j){
int tmp = n[i];
n[i] = n[j];
n[j] = tmp;
}
Then create the rotate method:
public static void rotate (int[] n, int fromIndex, int toIndex,
int dist){
if(fromIndex > toIndex)
throw new IllegalArgumentException ("fromIndex (" +
fromIndex + ") > toIndex (" + toIndex + ")");
if (fromIndex < toIndex){
int region = toIndex - fromIndex;
int index;
for (int i = 0; i < dist % region + ((dist < 0) ? region : 0);
i++){
index = toIndex - 1;
while (index > fromIndex)
swap (n, index, --index);
}
}
}
Java solution wrapped in a method:
public static int[] rotate(final int[] array, final int rIndex) {
if (array == null || array.length <= 1) {
return new int[0];
}
final int[] result = new int[array.length];
final int arrayLength = array.length;
for (int i = 0; i < arrayLength; i++) {
int nIndex = (i + rIndex) % arrayLength;
result[nIndex] = array[i];
}
return result;
}
For Left Rotate its very simple
Take the difference between length of the array and number of position to shift.
For Example
int k = 2;
int n = 5;
int diff = n - k;
int[] array = {1, 2, 3, 4, 5};
int[] result = new int[array.length];
System.arraycopy(array, 0, result, diff, k);
System.arraycopy(array, k, result, 0, diff);
// print the output
Question : https://www.hackerrank.com/challenges/ctci-array-left-rotation
Solution :
This is how I tried arrayLeftRotation method with complexity o(n)
looping once from k index to (length-1 )
2nd time for 0 to kth index
public static int[] arrayLeftRotation(int[] a, int n, int k) {
int[] resultArray = new int[n];
int arrayIndex = 0;
//first n-k indexes will be populated in this loop
for(int i = k ; i
resultArray[arrayIndex] = a[i];
arrayIndex++;
}
// 2nd k indexes will be populated in this loop
for(int j=arrayIndex ; j<(arrayIndex+k); j++){
resultArray[j]=a[j-(n-k)];
}
return resultArray;
}
package com.array.orderstatistics;
import java.util.Scanner;
public class ArrayRotation {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int r = scan.nextInt();
int[] a = new int[n];
int[] b = new int[n];
for (int i = 0; i < n; i++) {
a[i] = scan.nextInt();
}
scan.close();
if (r % n == 0) {
printOriginalArray(a);
} else {
r = r % n;
for (int i = 0; i < n; i++) {
b[i] = a[(i + r) < n ? (i + r) : ((i + r) - n)];
System.out.print(b[i] + " ");
}
}
}
private static void printOriginalArray(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
}
Following routine rotates an array in java:
public static int[] rotateArray(int[] array, int k){
int to_move = k % array.length;
if(to_move == 0)
return array;
for(int i=0; i< to_move; i++){
int temp = array[array.length-1];
int j=array.length-1;
while(j > 0){
array[j] = array[--j];
}
array[0] = temp;
}
return array;
}
You can do something like below
class Solution {
public void rotate(int[] nums, int k) {
if (k==0) return;
if (nums == null || nums.length == 0) return;
for(int i=0;i<k;i++){
int j=nums.length-1;
int temp = nums[j];
for(;j>0;j--){
nums[j] = nums[j-1];
}
nums[0] = temp;
}
}
}
In the above solution, k is the number of times you want your array to rotate from left to right.
Question : Rotate array given a specific distance .
Method 1 :
Turn the int array to ArrayList. Then use Collections.rotate(list,distance).
class test1 {
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 5, 6 };
List<Integer> list = Arrays.stream(a).boxed().collect(Collectors.toList());
Collections.rotate(list, 3);
System.out.println(list);//[4, 5, 6, 1, 2, 3]
}// main
}
I use this, just loop it a times
public void rotate(int[] arr) {
int temp = arr[arr.length - 1];
for(int i = arr.length - 1; i > 0; i--) {
arr[i] = arr[i - 1];
}
arr[0] = temp;
}
I'm having a bit of a problem writing a recursive function that sorts an array in java recursively . Right now it appears as though I have an infinite loop, and I can't seem to figure out where.
The primary function "rec_piv" searches from index1 to the pivot point and sorts the first half, then switches from the pivot point to the length of the array and sorts the second half. All of the comparisons are recorded by an int. [The array is of random size from 2 to 2014]
Thanks very much in advance!
public class Recursive_pivot {
private Random random_size = new Random();
private int size = random_size.nextInt(1024) + 2;
public int[] a = new int[size];
private Random elements = new Random();
/* variable for rec_piv */
public int temp=0;
public int temp2=0;
private Random rand_pivot = new Random();
private int pivot = rand_pivot.nextInt(size) + 2;
private int first_half =a[0+1];
private int second_half=a[pivot+1];
private int first_index=0; //first half of the array
private int second_index=pivot; //second half of the array
//The pivot is randomly chosen.
public int comparisons =0; //count the number of comparisons.
public void fill(){
for (int q=0; q<a.length; q++) {
/* filling the array */
a[q] = elements.nextInt(100 ) + 1;
}
}
public void rec_piv(int first_index, int second_index) {
if(first_index < pivot) {
if(first_half > a[first_index]) {
comparisons++;
temp = a[first_index];
a[first_index] = a[first_half];
a[first_half] = temp;
}
rec_piv(first_index+1, second_index);
}
if(second_index < a.length) {
if(second_half > a[second_index]) {
comparisons++;
temp2 = a[second_index];
a[second_index] = a[second_half];
a[second_half] = temp2;
}
rec_piv(first_index, second_index+1);
}
} //end of rec_piv
}//end of class.
You are trying to do a QSort here is a simple version of it.
public void quickSort(int array[], int start, int end)
{
int i = start; // index of left-to-right scan
int k = end; // index of right-to-left scan
if (end - start >= 1) // check that there are at least two elements to sort
{
int pivot = array[start];
while (k > i)
{
while (array[i] <= pivot && i <= end && k > i)
i++;
while (array[k] > pivot && k >= start && k >= i)
k--;
if (k > i)
swap(array, i, k);
}
swap(array, start, k);
quickSort(array, start, k - 1); // quicksort the left partition
quickSort(array, k + 1, end); // quicksort the right partition
}
else // if there is only one element in the partition, do not do any sorting
{
return; // the array is sorted, so exit
}
}
public void swap(int array[], int index1, int index2)
// pre: array is full and index1, index2 < array.length
// post: the values at indices 1 and 2 have been swapped
{
int temp = array[index1]; // store the first value in a temp
array[index1] = array[index2]; // copy the value of the second into the first
array[index2] = temp; // copy the value of the temp into the second
}
from this site.
http://www.mycstutorials.com/articles/sorting/quicksort
How do I add say 1000, 10000, 1000000, or 10000000 individual data items to a search algorithm?
Code:
public class BinarySearch {
int binarySearch(int[] array, int value, int left, int right) {
if (left > right)
return -1;
int middle = (left + right) / 2;
if (array[middle] == value)
return middle;
else if (array[middle] > value)
return binarySearch(array, value, left, middle - 1);
else
return binarySearch(array, value, middle + 1, right);
}
}
So, if I understand correctly, you want to try your algorithm with different amounts of integers in your array.
public int[] makeArray(int size, int minNum, int maxNum) {
int [] arr = new int[size];
Random r = new Random();
for (int i = 0; i < size; i++) {
arr[i] = minNum + r.nextInt(maxNum);
}
Arrays.sort(arr);
return arr;
}
So if you want to have 10000 numbers ranging from 100 to 500, then you would call:
int[] arr = makeArray(10000, 100, 500);
Actually, I recommend making a helper method to start off your searches like so:
public int binarySearch(int[] array, int value) {
return binarySearch(array, value, 0, array.length - 1);
}
Then you can look in arr for a value (e.g., 5):
int i = binarySearch(arr, 5);
It seems that you are asking how to populate the array. Here is one way to do it:
final Random rnd = new Random();
final int n = 100000;
final int[] array = new int[n];
for (int i = 0; i < n; ++i) {
array[i] = rnd.nextInt();
}
Arrays.sort(array);
If an array contains 1,7,7,3,6 and if user asks what 2nd largest element is the output should be 7(not 6) since duplicate values are treated as distinct.
This is my code.
I am using Deterministic search to find the suitable pivot .
Its complexity is O(n).
I am stuck at the error generated by my code .
Please do help me.
import java.util.Random;
import java.util.Scanner;
public class deven {
public static void main(String args[]){
Scanner in=new Scanner(System.in);
int len=in.nextInt();
int n=in.nextInt();
int array[]=new int[len];
for (int i = 0; i < len; i++) {
array[i]=in.nextInt();
}
System.out.println(select(array,len,n));
}
static int below[];
static int above[];
static int pivot;
static int i;
static int j;
static int x;
static int y;
static int index;
static Random rand=new Random();
static int select(int array[],int len,int n){
if(len==1)
return array[0];
pivot=pivot(array, len);
below=new int[len];
above=new int[len];
//System.out.println("Block");
x=0;
y=0;
int temp=0;
for(i=0;i<len;i++){
if(array[i]>pivot){
below[x++]=array[i];
}
else if(array[i]<pivot){
above[y++]=array[i];
}
else {
if(temp!=0){
below[x++]=array[i];
}
temp=1;
}
}
i = x;
j = len - y;
if(n<i) return select(below,x,n);
else if(n>=j) return(select(above,y,n-j));
else return(pivot);
}
static int pivot(int array[],int len){
if(len==1){
return array[0];
}
int numOfGroups=len/5;
if(len%5!=0){
numOfGroups++;
}
int setOfMedians[]=new int[numOfGroups];
for (int i = 0 ; i < numOfGroups ; i++)
{
int[] subset;
if(array.length % 5 > 0)
{
if (i == numOfGroups - 1)
{
subset = new int[array.length % 5];
}
else
{
subset = new int[5];
}
}
else
{
subset = new int[5];
}
for (int j = 0; j < subset.length ; j++)
{
subset[j] = array[5*i+j];
}
setOfMedians[i] = median(subset);
}
int goodpivot=select(setOfMedians, numOfGroups,numOfGroups/2 );
return goodpivot;
}
static int median(int[] array)
{
if (array.length == 1)
{
return array[0];
}
int smallerCount = 0;
for (int i = 0 ; i < array.length ; i++)
{
for (int j = 0 ; j < array.length ; j++)
{
if (array[i] < array[j])
{
smallerCount++;
}
}
if (smallerCount == (array.length - 1)/2)
{
return array[i];
}
smallerCount = 0;
}
return -1;
}
}
Input
6
3
1 2 3 1 2 3
Output
Exception in thread "main" java.lang.StackOverflowError
at deven.pivot(deven.java:99)
at deven.select(deven.java:34)
at deven.pivot(deven.java:102)
at deven.select(deven.java:34)
at deven.select(deven.java:59)
at deven.select(deven.java:59)
at deven.select(deven.java:59)
If you maintained an equalsCount in addition to your smallerCount, you should be able to detect whether your candidate value is the median when it is also a duplicate.
(Explanation)
You appear to be deliberately returning -1 as an invalid value when your median method fails unexpectedly. It would be more proper to throw an exception of some sort, but what you really want is for it to never reach that point.
Your algorithm fails when the median is a duplicate. In the set { 1, 2, 2, 2, 3 }, for example, 2 is the obvious median, but there's never a point where there are exactly 2 values "smaller than" any of the values being verified.
If you count both smaller and equal values, then you can know your candidate to be a median if either your current test passes, or if the smaller count is less than the midpoint AND the smaller + equal count is greater than the midpoint.
The problem is your median method. It should not return -1. In the last line of the median method, instead of
return -1;
change it to
return array[rand.nextInt(array.length)];
Please note that this fix is just an attempt to fix the error you have. It's not a good fix in the sense that median method does not return the median. I think the application should be refactored. The idea of the fix is actually in the pivot method. A good pivot is the median. But if you cannot find the median efficiently, then a pivot can be a random choice among the array.
Update:
Let's fix the median method:
static int median(int[] array) {
if (array.length == 0) {
throw new IllegalArgumentException("array cannot be empty.");
}
int mid = array.length / 2;
for (int candidate : array) {
int lower = 0;
int higher = 0;
for (int value : array) {
if (value < candidate) {
lower++;
}
else if (value > candidate) {
higher++;
}
}
if (lower <= mid && higher <= mid) {
return candidate;
}
}
throw new IllegalStateException();
}
I'm trying to implement multi-threading using merge sort. I have it making new threads at the point where it cuts an array in half.
The array is sorted depending on the:
[size of the array] vs [how many times I create new threads]
For instance: the array will be sorted if I let it create merely two threads on an array of size 70, but if I let it create 6, it will come back unsorted. One thing I thought it might be is that the threads weren't sync'd, but I used threadName.join()
here is some code: merge.java
import java.util.Random;
public class merge implements Runnable {
int[] list;
int length;
int countdown;
public merge(int size, int[] newList, int numberOfThreadReps, int firstMerge) {
length = size;
countdown = numberOfThreadReps;
list = newList;
if (firstMerge == 1)
threadMerge(0, length - 1);
}
public void run() {
threadMerge(0, length - 1);
}
public void printList(int[] list, int size) {
for (int i = 0; i < size; i++) {
System.out.println(list[i]);
}
}
public void regMerge(int low, int high) {
if (low < high) {
int middle = (low + high) / 2;
regMerge(low, middle);
regMerge(middle + 1, high);
mergeJoin(low, middle, high);
}
}
public void mergeJoin(int low, int middle, int high) {
int[] helper = new int[length];
for (int i = low; i <= high; i++) {
helper[i] = list[i];
}
int i = low;
int j = middle + 1;
int k = low;
while (i <= middle && j <= high) {
if (helper[i] <= helper[j]) {
list[k] = helper[i];
i++;
} else {
list[k] = helper[j];
j++;
}
k++;
}
while (i <= middle) {
list[k] = helper[i];
k++;
i++;
}
helper = null;
}
public void threadMerge(int low, int high) {
if (countdown > 0) {
if (low < high) {
countdown--;
int middle = (low + high) / 2;
int[] first = new int[length / 2];
int[] last = new int[length / 2 + ((length % 2 == 1) ? 1 : 0)];
for (int i = 0; i < length / 2; i++)
first[i] = list[i];
for (int i = 0; i < length / 2 + ((length % 2 == 1) ? 1 : 0); i++)
last[i] = list[i + length / 2];
merge thread1 = new merge(length / 2, first, countdown, 0);// 0
// is
// so
// that
// it
// doesn't
// call
// threadMerge
// twice
merge thread2 = new merge(length / 2
+ ((length % 2 == 1) ? 1 : 0), last, countdown, 0);
Thread merge1 = new Thread(thread1);
Thread merge2 = new Thread(thread2);
merge1.start();
merge2.start();
try {
merge1.join();
merge2.join();
} catch (InterruptedException ex) {
System.out.println("ERROR");
}
for (int i = 0; i < length / 2; i++)
list[i] = thread1.list[i];
for (int i = 0; i < length / 2 + ((length % 2 == 1) ? 1 : 0); i++)
list[i + length / 2] = thread2.list[i];
mergeJoin(low, middle, high);
} else {
System.out.println("elsd)");
}
} else {
regMerge(low, high);
}
}
}
proj4.java
import java.util.Random;
public class proj4 {
public static void main(String[] args) {
int size = 70000;
int threadRepeat = 6;
int[] list = new int[size];
list = fillList(list, size);
list = perm(list, size);
merge mergy = new merge(size, list, threadRepeat, 1);
// mergy.printList(mergy.list,mergy.length);
for (int i = 0; i < mergy.length; i++) {
if (mergy.list[i] != i) {
System.out.println("error)");
}
}
}
public static int[] fillList(int[] list, int size) {
for (int i = 0; i < size; i++)
list[i] = i;
return list;
}
public static int[] perm(int[] list, int size) {
Random generator = new Random();
int rand = generator.nextInt(size);
int temp;
for (int i = 0; i < size; i++) {
rand = generator.nextInt(size);
temp = list[i];
list[i] = list[rand];
list[rand] = temp;
}
return list;
}
}
so TL;DR my array isn't getting sorted by a multithreaded merge sort based on the size of the array and the number of times I split the array by using threads...why is that?
Wow. This was an interesting exercise in masochism. I'm sure you've moved on but I thought for posterity...
The bug in the code is in mergeJoin with the middle argument. This is fine for regMerge but in threadMerge the middle passed in is (low + high) / 2 instead of (length / 2) - 1. Since in threadMerge low is always 0 and high is length - 1 and the first array has (length / 2) size. This means that for lists with an odd number of entries, it will often fail depending on randomization.
There are also a number of style issues which makes this program significantly more complicated and error prone:
The code passes around a size of the arrays when Java has a convenient list.length call which would be more straightforward and safer.
The code duplicates calculations (see length/2) in a number of places.
The code should be able to sort inside the array without creating sub-arrays.
Classes should start with an uppercase letter (Merge instead of merge)
firstMerge should be a boolean
The code names the Thread variable merge1 and the merge variable thread1. Gulp.
The merge constructor calling threadMerge(0,length -1) is strange. I would just put that call after the new call back in proj4. Then firstMerge can be removed.
I would consider switching to having high be one past the maximum value instead of the maximum. We tend to think like for (int i = 0; i < 10; i++) more than i <= 9. Then the code can have j go from low to < middle and k from middle to < high. Better symmetry.
Best of luck.