Array subset unequal sums - java

I have a requirement to write a function to divide an array in 2 parts {4,5,2,1,3}, such that sum in first array is greater than in second array but length of 1st array is smaller than that of second.The union of their sums is total sum and they dont have any intersection.So, an answer would be {4,5}.
import java.util.ArrayList;
import java.util.Stack;
public class DP2 {
public static void main(String args[]) {
int[] arr= {5,2,10,4,1,11};
ArrayList<Integer> list=new ArrayList<>();
//calculate sum
int finalSum=0;
/*
for(int i: arr)
finalSum+=arr[i];
*/
int len=arr.length;
int mid=(len)/2;
System.out.println(mid);
int sum=0;
//initialize 2 pointers
//will use a stack
Stack<Integer> stack = new Stack<Integer>();
int i=0,j=len-1;
int max=Integer.MIN_VALUE;
while(i < j ) {
//int max=Math.max(arr[i], arr[j]);
// System.out.println(max);
while(stack.size() < mid) {
max=Math.max(arr[i], arr[j]);
stack.push(max);
//System.out.println(stack.size());
// System.out.println(stack.peek());
i++;
j--;
}
// max=Math.max(arr[i], arr[j]);
i++;
j--;
if(stack.size() < mid && stack.peek() < max ) {
stack.pop();
stack.push(max);
}
}
while(!stack.isEmpty())
System.out.println(stack.pop());
}
}
It wont return the expected answer. It is not popping out from stack as I had coded to do. Can someone please help what I am doing wrong.

From what I can see there is nothing wrong, everything works as expected. The only problem was that the popping operation was giving you the result in reverse order. I have fixed that in the code below:
Integer[] result = new Integer[stack.size()];
for (int i1 = result.length - 1; i1 >= 0 && !stack.isEmpty(); i1--) {
result[i1] = stack.pop();
}
System.out.println(Arrays.toString(result));
Output
[4, 5]
EDIT: As requested here is a full solution to your problem:
/**
* Convert an array of primitive numbers to Integer objects.
*/
private static Integer[] intToInteger(int[] array) {
return Arrays.stream(array).boxed().toArray( Integer[]::new );
}
/**
* Converts a primitive integer array to an ArrayList.
*/
private static ArrayList<Integer> intArrayTolist(int[] array) {
return new ArrayList<>(Arrays.asList(intToInteger(array)));
}
public static void main(String[] args) {
int[] arr0 = { 5, 2, 10, 4, 1, 11 };
/* determine the size of the first array */
float quotient = (float)arr0.length / 2;
int mid = (int) Math.floor(quotient);
int size = quotient != mid ? mid : mid - 1;
/* Initialize arrays here */
Integer[] arr1 = new Integer[size];
Integer[] arr2 = new Integer[arr0.length - mid];
List<Integer> list = intArrayTolist(arr0);
/* Populate the first array with largest values
* found within the main array
*/
for (int i = 0; i < size; i++) {
/*
* Find out the largest value in the main array
* and add that value to the first array
*/
arr1[i] = java.util.Collections.max(list);
list.remove(arr1[i]);
}
arr2 = list.toArray(arr2);
int sum = Arrays.stream(arr0).sum();
System.out.println("First array: " + Arrays.toString(arr1));
System.out.println("Second array: " + Arrays.toString(arr2));
System.out.println("Sum of all numbers: " + sum);
}
Output
First array: [11, 10]
Second array: [5, 2, 4, 1]
Sum of all numbers: 33
Note that it might not be as elegant I would have hopped but it gets the job done. I will see if I can do some further cleaning and optimizing as I feel there is a lot of redundancies in there. It's just a quick mock up so you can have something that actually works.

I used recursion. This is the way I did it:
#Test
public void stackoverflow() {
int[] array = { 39, 2, 3, 40, 0, 0, 0 };
System.out.println("index is " + method(array, 0));
}
String method(int[] array, int i) {
if (i < array.length / 2 && sum(array, 0, i) > sum(array, i + 1, array.length - 1)) {
return "the sub array goes from 0 to " + i;
}
else if (i >= array.length / 2 && sum(array, array.length - 1 - i + array.length / 2, array.length - 1) > sum(array, 0, array.length - i - 2 + array.length / 2)) {
int index = array.length - 1 - i + array.length / 2;
return "the sub array goes from " + index + " to " + (array.length - 1);
}
return method(array, i + 1);
}
int sum(int[] array, int i, int j) {
int sum = 0;
for (int k = i; k <= j; k++) {
sum = sum + array[k];
}
return sum;
}
This is the explanation: you start from position 0 of the array. If the sum of the element at [0] is greater than the sum from position [1] to [n-1], you are done. If not, you call the same logic, comparing the sum from [0] to [1] versus [2] to [n-1]. Since you are looking for the smallest array, when you hit the half of the array (n/2), then you do the same starting from the end of the array.
My logic returns the index of the array. The index represents either the last element or the first element of the sub array which contains the greater sum. For example, in this case:
{ 0, 0, 0, 0, 40, 1, 2, 3 }
it will return "4". [4] is this element:
{ 0, 0, 0, 0, 40, 1, 2, 3 }
*
Is clear here that if the index > n/2, then the sub array goes from index to n-1. If not, then the sub array goes from 0 to n/2.

Related

Minimum count of numbers required from given array to represent S

Given an integer S and an array arr[], the task is to find the minimum number of elements whose sum is S, such that an element of the array can be chosen only once to get sum S.
Example:
Input: arr[] = {25, 10, 5}, S = 30
Output: 2
Explanation:
Minimum possible solution is 2, (25+5)
Example:
Input: arr[] = {2, 1, 4, 3, 5, 6}, Sum= 6
Output: 1
Explanation:
Minimum possible solution is 1, (6)
I have found similar solution here but it says element of array can be used multiple times.
I have this code from the link which uses an array element multiple times, but how to restrict this to use only once?
static int Count(int S[], int m, int n)
{
int [][]table = new int[m + 1][n + 1];
// Loop to initialize the array
// as infinite in the row 0
for(int i = 1; i <= n; i++)
{
table[0][i] = Integer.MAX_VALUE - 1;
}
// Loop to find the solution
// by pre-computation for the
// sequence
for(int i = 1; i <= m; i++)
{
for(int j = 1; j <= n; j++)
{
if (S[i - 1] > j)
{
table[i][j] = table[i - 1][j];
}
else
{
// Minimum possible for the
// previous minimum value
// of the sequence
table[i][j] = Math.min(table[i - 1][j],
table[i][j - S[i - 1]] + 1);
}
}
}
return table[m][n];
}
// Driver Code
public static void main(String[] args)
{
int arr[] = { 9, 6, 5, 1 };
int m = arr.length;
System.out.print(Count(arr, m, 11));
}
The idiomatic approach for this is to loop backwards when updating the table of previous results.
static int minElementsForSum(int[] elems, int sum){
int[] minElems = new int[sum + 1];
for(int i = 1; i <= sum; i++) minElems[i] = Integer.MAX_VALUE;
for(int elem: elems)
for(int i = sum; i >= elem; i--)
if(minElems[i - elem] != Integer.MAX_VALUE)
minElems[i] = Math.min(minElems[i], minElems[i - elem] + 1);
return minElems[sum];
}
Demo

Folding an integer array in half

I am working on a method that will take an integer array and fold it in half x number of times. This method would take an integer array like this {1,2,3,4,5} and output an the array {6,6,3} if it is folded once. Or it could take the input {5,6,7,8} and output {13,13} also folded once.
If the input is folded twice then {5,6,7,8} would turn into {26}.
import java.util.Arrays;
public class Kata
{
public static int[] foldArray(int[] array, int runs)
{
int[] tempArray = array;
for(int j=0; j<runs; j++){
for(int i=0; i<tempArray.length; i++){
tempArray[i] += tempArray[tempArray.length - i];
}
}
int[] outputArray = Arrays.copyOfRange(tempArray, (tempArray.length/2));
return outputArray;
}
}
The problem with your implementation is the way in which you use tempArray:
int[] tempArray = array;
This "aliases" tempArray to the original array, so any modifications to tempArray also happen to the original array. This means that tempArray's length is not going to change from run to run, so any fold after the first one would be invalid.
You need to make tempArray a copy of the initial ⌈n/2⌉ elements on each iteration of the outer loop. To round half-length up, use this expression:
int halfLength = (tempArray.length+1)/2;
int[] tempArray = Arrays.copyOfRange(tempArray, halfLength);
This will deal with arrays of odd length.
At the end of each outer loop iteration replace array with tempArray.
You can also solve your problem recursively:
public static int[] foldArray(int[] array, int runs) {
if (runs == 0) {
return array;
}
int[] tmp;
if (array.length % 2 == 0) {
tmp = new int[array.length / 2];
for (int i = 0; i < array.length / 2; i++) {
tmp[i] = array[i];
}
} else {
tmp = new int[array.length / 2 + 1];
for (int i = 0; i < array.length / 2 + 1; i++) {
tmp[i] = array[i];
}
}
for (int i = 0; i < array.length / 2; i++) {
tmp[i] += array[array.length - i - 1];
}
return foldArray(tmp, runs - 1);
}
public static void main(String[] args) {
System.out.println(Arrays.toString(foldArray(new int[]{1, 2, 3, 4, 5}, 1)));
System.out.println(Arrays.toString(foldArray(new int[]{5, 6, 7, 8}, 1)));
System.out.println(Arrays.toString(foldArray(new int[]{5, 6, 7, 8}, 2)));
}
Note that you need to be careful with the length of the input arrays - whether it's odd or even.
Solution in JavaScript:
function fold(arr, num) {
if (num === 0 || arr.length === 1) {
return arr;
}
let result = [];
while (arr.length > 1) {
result.push(arr.shift() + arr.pop());
}
if(arr.length === 1){
result.push(arr[0]);
}
return fold(result, num - 1);
}
Example:
const arr = [1, 2, 3, 4, 5];
fold(arr, 2); --> [9,6]

How to solve for the mean in an array without the max and min?

public class FunWithArrays {
public static void main(String[] args) {
int[] myFunArray = {7, 10, 3, 0, 615, -1000};
int i;
//minimum
int min;
min = myFunArray[0];
for (i=0; i < myFunArray. length; i++) {
if (myFunArray[i] < min) {
min = myFunArray[i];
}
}
//maximum
int max;
max= myFunArray[0];
for (i=1; i < myFunArray. length; i++) {
if (myFunArray[i] > max) {
max = myFunArray[i];
}
}
System.out.println("minimum = " + min + " maximum = " + max);
//mean without outliers
double noOutliersMean = 0;
for (i=0; i < myFunArray.length; i++){
noOutliersMean = ((sum - (max + min)) /myFunArray.length );
if ( myFunArray.length < 3){
System.out.println("not enough numbers");
}
}
System.out.println("Mean without Outliers: " +noOutliersMean);
//Array reversed
int[] reversed = myFunArray;
for(int i1 = reversed.length - 1; i1 >= 0 ; i1--) {
System.out.println( "Reversed " + reversed[i1]);
}
}
}
For the mean without the outliers (max and min) the answer should be 5 my line of code gives me 1.333. What am i doing wrong?
2nd question regarding the array reversed, when printed out it gives me the right answer but each number on a separate line. How do i get it to be on 1 line in the format of ; reversed: [-1000,615,0,3,10,7]
the answer to your second question is don't print using
println
, just use print
The code should be:
System.our.print("Reversed: [")
for(int i1 = reversed.length - 1; i1 >= 0 ; i1--) {
System.out.print(reversed[i1]);
if(i1>0){
System.our.print(",");
}
}
System.out.print("]");
To answer your first question you need to provide the following:
How you are calculating sum, max and min. Even though you have mentioned without max and min.. you still are using it in your code
Think about the logic of the code when you manipulated the array...
you will see that the mean with no min or max is the same as:
the mean excluding the elements at index0 and index length-1 if the array were sorted, so that is what you have to do
sort the array
loop excluding 1st and last
calculate the mean
Example:
int[] myFunArray = { 7, 10, 3, 0, 615, -1000 };
// unsorted { 7, 10, 3, 0, 615, -1000 };
// sorted { -1000, 0, 3, 7, 10, 615 };
Arrays.sort(myFunArray);
System.out.println(Arrays.toString(myFunArray));
int acumm = 0;
double mean = 0.0;
for (int i = 1; i < myFunArray.length - 1; i++) {
acumm += myFunArray[i];
}
mean = acumm / (myFunArray.length - 2);
System.out.println(mean);

Sum consecutive even numbers and consecutive odd numbers in an array

I have a code that sums the consecutive even numbers and consecutive odd numbers, then adds them to an arraylist. This process should be repeated until there are no more consecutive odd or even numbers in the list. Then returns the size of the arraylist.
I used nested for loops and the problem is the loops check the same index which doesn't make sense.
Here's my code:
public static int SumGroups(int[] arr) {
ArrayList<Integer> arl = new ArrayList<Integer>();
int even = 0, odd = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] % 2 == 0) {
even += arr[i];
if (arr[j] % 2 == 0) {
even += arr[j];
} else {
arl.add(even);
even = 0;
break;
}
} else {
odd += arr[i];
if (arr[j] % 2 != 0) {
odd += arr[j];
} else {
arl.add(odd);
odd = 0;
break;
}
}
}
}
return arl.size();
}
My Question is:
How to prevent loops from checking the same index ?
in other words, how to make my code sums the consecutive even numbers and consecutive odd numbers ?
Input:
int arr[]={2, 1, 2, 2, 6, 5, 0, 2, 0, 5, 5, 7, 7, 4, 3, 3, 9};
Output:
6 // [2, 1, 10, 5, 30, 15]
I think the following code should solve the problem, if you do not want to output the size simply return `sums` instead of `sums.size()`
public static int sumGroupsRecursively(int[] arr) {
List<Integer> numbersToSum = IntStream.of(arr).boxed().collect(Collectors.toList());
List<Integer> currentSumList = sumSublist(numbersToSum);
List<Integer> nextSumList = sumSublist(currentSumList);
while (currentSumList.size() != nextSumList.size()) {
currentSumList = nextSumList;
nextSumList = sumSublist(currentSumList);
}
return nextSumList.size();
}
public static List<Integer> sumSublist(List<Integer> list) {
int current = list.get(0);
int currentSum = 0;
List<Integer> sums = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
if (current % 2 == list.get(i) % 2) {
currentSum += list.get(i);
} else {
sums.add(currentSum);
current = list.get(i);
currentSum = current;
}
}
sums.add(currentSum);
return sums;
}
If you need to do this in one function what I would discourage because it is harder to read you could use code like this.
public static Integer sumSublist(int[] arr) {
List<Integer> sums = new ArrayList<>();
sums.add(0);
int i = 0;
while (i < arr.length - 1) {
int current = arr[i];
int currentSum = 0;
while (current % 2 == arr[i] % 2) {
currentSum += arr[i];
if (i >= arr.length - 1) {
break;
}
i++;
}
if (currentSum % 2 == sums.get(sums.size()-1) % 2) {
sums.set(sums.size() - 1, sums.get(sums.size()-1) + currentSum);
} else {
sums.add(currentSum);
}
}
return sums.size();
}
You are entering your first for loop passing in arr. Inside the first for loop you enter a second for loop passing in arr a second time. This means that you enter the second for loop as many times as there are elements in arr and transverse arr in the second for loop every single time.
for example, if arr.length() was 2 you would transverse arr 3 times. Once in your outer for loop and twice (once for each element in arr) in your inner loop.
Second, by adding both the odd and even numbers to your arraylist, you are doing nothing but reconstructing arr but in an arraylist rather than array. Therefor, returning arl.size() is the exact same as returning arr.length() which is already known and much easier to do.
Despite that, here is how I would calculate the sum of the odd and evens. I add both to different arraylists. You'll need to figure out exactly what you need to return though because your description is off.
public void test(){
int[] arr = new int[5];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
int testOfEven = 6;
int testOfOdd = 9;
int sumOfEven = 0;
int sumOfOdd = 0;
ArrayList evens = new ArrayList<Integer>();
ArrayList odds = new ArrayList<Integer>();
for(int i = 0; i < arr.length; i++)
{
if ((arr[i]%2) == 0)
{
evens.add(arr[i]);
sumOfEven += arr[i];
}
else
{
odds.add(arr[i]);
sumOfOdd += arr[i];
}
}
assertEquals(testOfEven, sumOfEven);
assertEquals(testOfOdd, sumOfOdd);
}
after playing some time, here is my version:
public static int SumGroups(final int[] arr) {
if (arr.length > 0) {
int n, sum, psum;
psum = sum = n = arr[0] & 1; // parity of first number in sequence
int s = 1; // at least one element in array
int f = 0; // discard first parity change
for (int i = 1; i < arr.length; i++) {
if (n == (arr[i] & 1)) {
sum = (sum + n) & 1; // both even or odd, just increase sum
} else {
s += (psum ^ sum) & f; // compare sums parity
psum = sum; // store current sum's parity
sum = n = arr[i] & 1; // new first number in sequence
f = 1; // do not discard sums parity next time
}
}
s += (psum ^ sum) & f; // array ended, check parity of last sum
return s;
}
return 0;
}
I've put comments, but still some additional notes:
basic idea is the same as #PKuhn, just checked for some edge cases (empty array, integer overflow)
we don't need to have array of sums, we need just previous sum and check parity of it with newly calculated one
sum = (sum + n) & 1 - we don't need to calculate whole sum, we need just parity of the sum
s += (psum ^ sum) & f - we need to increase swap counter only if parity changed, xor helps us to get 1 if changed and 0 if not
Here is the list of tests which I've used:
Assert.assertEquals(6, SumGroups(new int[] { 2, 1, 2, 2, 6, 5, 0, 2, 0, 5, 5, 7, 7, 4, 3, 3, 9 }));
Assert.assertEquals(6, SumGroups(new int[] { 0, 0, 0, 0, 2, 1, 2, 2, 6, 5, 0, 2, 0, 5, 5, 7, 7, 4, 3, 3, 9 }));
Assert.assertEquals(1, SumGroups(new int[] { 2, 3, 3 }));
Assert.assertEquals(1, SumGroups(new int[] { 2 }));
Assert.assertEquals(1, SumGroups(new int[] { 2, 2 }));
Assert.assertEquals(1, SumGroups(new int[] { 2, 3, 3, 3, 3, 2 }));
Assert.assertEquals(2, SumGroups(new int[] { 3, 2, 2 }));
Assert.assertEquals(2, SumGroups(new int[] { 1, 3, 3, 2, 2 }));
Assert.assertEquals(2, SumGroups(new int[] { 1, 2, 3, 3, 2, 3, 3, 2 }));
Assert.assertEquals(1, SumGroups(new int[] { 3, 3, 2, 2 }));
Assert.assertEquals(1, SumGroups(new int[] { Integer.MAX_VALUE, Integer.MAX_VALUE }));
Assert.assertEquals(1, SumGroups(new int[] { Integer.MAX_VALUE, Integer.MAX_VALUE, 2 }));
Assert.assertEquals(1, SumGroups(new int[] { Integer.MAX_VALUE, Integer.MAX_VALUE, 3 }));
public void findEvenOdd(int a[]){
Boolean flip = false;
int sum = 0, i, m = 0;
for (i = 0; i < a.length; i++) {
if (flip) {
System.out.print(sum + "\t");
sum = a[i];
flip = !flip;
if (i + 1 < a.length && (a[i] % 2 != a[i + 1] % 2))
flip = !flip;
m++;
} else {
sum += a[i];
if (i + 1 < a.length && (a[i] % 2 != a[i + 1] % 2))
flip = !flip;
m++;
}
}
if(m!=a.length-1)
System.out.print(a[a.length-1] + "\t");
}

How to rotate an array?

I have the following problem to test:
Rotate an array of n elements to the right by k steps.
For instance, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to
[5,6,7,1,2,3,4]. How many different ways do you know to solve this problem?
My solution in intermediate array:
With Space is O(n) and time is O(n), I can create a new array and then copy elements to the new array. Then change the original array by using System.arraycopy().
public void rotate(int[] nums, int k) {
if (k > nums.length)
k = k % nums.length;
int[] result = new int[nums.length];
for (int i = 0; i < k; i++) {
result[i] = nums[nums.length - k + i];
}
int j = 0;
for (int i = k; i < nums.length; i++) {
result[i] = nums[j];
j++;
}
System.arraycopy(result, 0, nums, 0, nums.length);
}
But is there a better way we can do it with bubble rotate (like bubble sort) in O(1) space?
Method 1 - The Reversal Algorithm(Good One):
Algorithm:
rotate(arr[], d, n)
reverse(arr[], l, n);
reverse(arr[], 1, n-d) ;
reverse(arr[], n - d + 1, n);
Let AB are the two parts of the input array where A = arr[0..n-d-1] and B = arr[n-d..n-1]. The idea of the algorithm is:
Reverse all to get (AB) r = BrAr.
Reverse A to get BrA. /* Ar is reverse of A */
Reverse B to get BA. /* Br is reverse of B */
For arr[] = [1, 2, 3, 4, 5, 6, 7], d =2 and n = 7
A = [1, 2, 3, 4, 5] and B = [ 6, 7]
Reverse all, we get BrAr = [7, 6, 5, 4, 3, 2, 1]
Reverse A, we get ArB = [7, 6, 1, 2, 3, 4, 5]
Reverse B, we get ArBr = [6, 7, 5, 4, 3, 1, 2]
Here is the Code Snippet:
void righttRotate(int arr[], int d, int n)
{
reverseArray(arr, 0, n-1);
reverseArray(arr, 0, n-d-1);
reverseArray(arr, n-d, n-1);
}
void reverseArray(int arr[], int start, int end)
{
int i;
int temp;
while(start < end)
{
temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
}
Method 2 - A Juggling Algorithm
Divide the array in different sets where number of sets is equal to GCD of n and d and move the elements within sets.
If GCD is 1, then elements will be moved within one set only, we just start with temp = arr[0] and keep moving arr[I+d] to arr[I] and finally store temp at the right place.
Here is an example for n =12 and d = 3. GCD is 3 and
Let arr[] be {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
Elements are first moved in first set
arr[] after this step --> {4 2 3 7 5 6 10 8 9 1 11 12}
Then in second set.
arr[] after this step --> {4 5 3 7 8 6 10 11 9 1 2 12}
Finally in third set.
arr[] after this step --> {4 5 6 7 8 9 10 11 12 1 2 3}
Here is the code:
void leftRotate(int arr[], int d, int n)
{
int i, j, k, temp;
int gcd = gcd(d, n);
for (i = 0; i < gcd; i++)
{
/* move i-th values of blocks */
temp = arr[i];
j = i;
while(1)
{
k = j + d;
if (k >= n)
k = k - n;
if (k == i)
break;
arr[j] = arr[k];
j = k;
}
arr[j] = temp;
}
}
int gcd(int a,int b)
{
if(b==0)
return a;
else
return gcd(b, a%b);
}
Time complexity: O(n)
Auxiliary Space: O(1)
Method 3 - Rotate one by one:
righttRotate(arr[], d, n)
start
For i = 0 to i < d
Right rotate all elements of arr[] by one
end
To rotate by one, store arr[n-1] in a temporary variable temp, move arr[1] to arr[2], arr[2] to arr[3] …and finally temp to arr[0]
Let us take the same example arr[] = [1, 2, 3, 4, 5, 6, 7], d = 2, rotate arr[] by one 2 times. We get [7, 1, 2, 3, 4, 5, 6] after first rotation and [ 6, 7, 1, 2, 3, 4, 5] after second rotation.
Her is Code Snippet:
void leftRotate(int arr[], int d, int n)
{
int i;
for (i = 0; i < d; i++)
leftRotatebyOne(arr, n);
}
void leftRotatebyOne(int arr[], int n)
{
int i, temp;
temp = arr[n-n];
for (i = 0; i < n-1; i++)
arr[i] = arr[i+1];
arr[n - 1] = temp;
}
Time complexity: O(n*d)
Auxiliary Space: O(1)
The following code will do your job. This is for right rotate.
public void rightrotate(int[] nums, int k) {
k %= nums.length;
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
}
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--;
}
}
If you want to do left rotate just use the following
public void leftrotate(int[] nums, int k) {
k %= nums.length;
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
reverse(nums, 0, nums.length - 1);
}
When k is negative, it rotates to the left.
Space is O(1) and time is O(n)
static void rotate(int[] num, int k) {
int n = num.length;
k = k % n;
if (k < 0) k += n;
int[] result = new int[n];
System.arraycopy(num, 0, result, k, n - k);
System.arraycopy(num, n - k, result, 0, k);
System.arraycopy(result, 0, num, 0, n);
}
ArrayUtil class is used to provide following utilities in primitive array
swap array elements
reverse array between startIndex and endIndex
leftRotate array by shift
Algorithm for array rotation by shift-
If we have to reverse array by shift value then take mod(%) with array length so that shift will become smaller than array length.
Reverse array between index 0 and shift-1
Reverse array between index shift and length-1.
Reverse complete array between index 0 and length-1.
Space Complexity: In-place Algorithm, No extra space needed so O(1).
Time Complexity : Array reversal of size k take O(k/2) i.e swapping k/2 pairs of elements.
Array Reversal time- O(k) for k size array.
Total time in Rotation-
O(1) ..........for step 1
O(shift) ......for step 2
O(n - shift) ...for step 3
O(n) ...........for step 4
Total Time for array Rotation: O(1) + O(shift) + O(n-shift) + O(n) = O(n)
public class Solution {
public static void main(String[] args) {
int k = 3;
int a[] = {1,2,3,4,5,6,7};
ArrayUtil.leftRotate(a, k);
for (int i : a)
System.out.println(i);
}
}
class ArrayUtil {
public static final boolean checkIndexOutOfRange(int[] array, int index) {
if (index < 0 || index > array.length)
return true;
return false;
}
public static final void swap(int[] array, int i, int j) {
if (checkIndexOutOfRange(array, i) || checkIndexOutOfRange(array, j))
return;
int t = array[i];
array[i] = array[j];
array[j] = t;
}
public static final void reverse(int[] array, int startIndex, int endIndex) {
if (checkIndexOutOfRange(array, startIndex) || checkIndexOutOfRange(array, endIndex))
return;
while (startIndex < endIndex) {
swap(array, startIndex, endIndex);
startIndex++;
endIndex--;
}
}
public static final void reverse(int[] array) {
reverse(array, 0, array.length - 1);
}
public static final void leftRotate(int[] array, int shift) {
int arrayLength = array.length;
if (shift >= arrayLength)
shift %= arrayLength;
reverse(array, 0, shift - 1);
reverse(array, shift, arrayLength - 1);
reverse(array);
}
}
Partial Code for ONE time array rotation
last=number_holder[n-1];
first=number_holder[0];
//rotation
number_holder[0]=last;
for(i=1;i<n;i++)
{
last=number_holder[i];
number_holder[i]=first;
first=last;
}
Display the array
for(i=1;i<n;i++)
{
System.out.println(number_holder[i]);
}
AFAIK, there are three ways to rotate an array with O(1) extra space, or put it another way, to swap two contiguous subarray.
reverse approach. reverse both part, then reverse all. most easy to code.
successively swap two contiguous block, until all items are in place.
juggling rotate, shell sort like. -- worse cache performance.
C++ has builtin function std::rotate(), which takes three iterator first, middle, last,
and return new_middle, which is where the old first element lies in the rotated
sequence.
I have checked the implementation on my computer, which use second approach I listed above.
(line 1246 in /usr/lib/gcc/i686-pc-cygwin/5.4.0/include/c++/bits/stl_algo.h).
Below is my implementation of rotate, with test program.
#include <iostream>
#include <vector>
// same logic with STL implementation, but simpler, since no return value needed.
template <typename Iterator>
void rotate_by_gcd_like_swap(Iterator first, Iterator mid, Iterator last) {
if (first == mid) return;
Iterator old = mid;
for (; mid != last;) {
std::iter_swap(first, mid);
++first, ++mid;
if (first == old) old = mid; // left half exhausted
else if (mid == last) mid = old;
}
}
// same logic with STL implementation
template <typename Iterator>
Iterator rotate_by_gcd_like_swap_then_return_new_mid(Iterator first, Iterator mid, Iterator last) {
if (first == mid) return last;
if (mid == last) return first;
Iterator old = mid;
for(;;) {
std::iter_swap(first, mid);
++first, ++mid;
if (first == old) old = mid;
if (mid == last) break;
}
Iterator result = first; // when first time `mid == last`, the position of `first` is the new `mid`.
for (mid = old; mid != last;) {
std::iter_swap(first, mid);
++first, ++mid;
if (first == old) old = mid;
else if (mid == last) mid = old;
}
return result;
}
int main() {
using std::cout;
std::vector<int> v {0,1,2,3,4,5,6,7,8,9};
cout << "before rotate: ";
for (auto x: v) cout << x << ' '; cout << '\n';
int k = 7;
rotate_by_gcd_like_swap(v.begin(), v.begin() + k, v.end());
cout << " after rotate: ";
for (auto x: v) cout << x << ' '; cout << '\n';
cout << "sz = " << v.size() << ", k = " << k << '\n';
}
Above solutions talk about shifting array elements either by reversing them or any other alternative.
I've unique solution. How about determining the starting position of element after n rotations. Once we know that, then simply insert elements from that index and increment counter using modulus operation. Using this method we can avoid using extra array operations and so on.
Here is my code:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
void rotateLeft(int n,int r) {
vector<long int> vec(n);
int j = n;
// get the position of starting index after r left rotations.
while(r!=0) {
--j;
if(j==0)
j = n;
--r;
}
for(long int i=0;i<n;++i) {
// simply read the input from there and increment j using modulus operator.
cin>>vec[j];
j = (j+1)%n;
}
// print the array
for(long int i=0;i<n;++i)
cout<<vec[i]<<" ";
}
int rotateRight (int n,int r) {
// get the position of starting index after r left rotations.
int j = r % n;
vector<long int> vec(n);
for(int i=0;i<n;i++) {
cin>>vec[j];
j=(j+1)%n;
}
for(int i=0;i<n;i++)
cout<<vec[i]<<" ";
}
int main() {
long int n,r; // n stands from number of elements in array and r stands for rotations.
cin>>n>>r;
// Time Complexity: O(n+r) Space Complexity: O(1)
rotateLeft(n,r);
// Time Complexity: O(n) Space Complexity: O(1)
rotateRight(n,r);
return 0;
}
Python code:
def reverse(arr,start , end):
while(start <= end):
arr[start] , arr[end] = arr[end] , arr[start]
start = start+1
end = end-1
arr = [1,2,3,4,5,6,7]
n = 7
k = 2
reverse(arr,0,n-1)
# [7,6,5,4,3,2,1]
reverse(arr,0,n-1-k)
# [3,4,5,6,7,2,1]
reverse(arr,n-k,n-1)
# [3,4,5,6,7,1,2]
print arr
# [3, 4, 5, 6, 7, 8, 9, 1, 2]
In Ruby Its very simple, Please take a look, Its one line.
def array_rotate(arr)
i, j = arr.length - 1, 0
arr[j],arr[i], i, j = arr[i], arr[j], i - 1, j + 1 while(j<arr.length/2)
puts "#{arr}"
end
Input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
Output: [20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
1.using a temp array and O(n) time
public static void rotateAnArrayUsingTemp(int arr[], int d, int n) {
int temp[] = new int[d];
int tempIndex = 0;
for (int i = 0; i < d; i++) {
temp[i] = arr[i];
}
for (int i = 0; i < arr.length - d; i++) {
arr[i] = arr[i + d];
}
for (int i = arr.length - d; i < arr.length; i++) {
arr[i] = temp[tempIndex++];
}
}
This is a simple solution to rotate an array.
public class ArrayRotate {
public int[] rotateArray(int array[], int k) {
int newArray[] = new int[array.length];
for (int i = 0; i < array.length; i++) {
newArray[(i + k) % array.length] = array[i];
}
System.arraycopy(newArray, 0, array, 0, array.length);
return newArray;
}
public static void main(String[] args) {
int array[] = { 1, 2, 3, 4, 5, 6, 7 };
ArrayRotate rotate = new ArrayRotate();
rotate.display(rotate.rotateArray(array, 3));
}
public void display(int array[]) {
for (int i : array) {
System.out.print(i + ",");
}
}
}
Runtime complexity is O(n)
There are several other algorithm to achieve the same.
using temp array
Rotate One By one
Juggling algorithm
reversal method
This solution is O(1) space and O(N) time. It is in C#, takes an array parameter and rotates it in place. The algorithm goes through the first s (the shift) elements, starting with the first element moves it to the s_th position, then moves the s_th to the 2s_th position etc. If each of the first s elements rotates back to itself then there will be (arrayLength / s) * s = arrayLength loops, and at the end the array will be rotated by s. If the first s elements do not rotate back themselves, then there will still be cycles, say if s = 4, there could be one cycle which is 1-3-1 and the second 2-4-2, the line - if (ind == indAtBeg), checks for a cycle and terminates the while loop. The variable loopCount increments, when there is a rotation starting at any of the first s elements.
public static void rotateArrayByS(int[] ar, int s)
{
int len = ar.Length, ind = 0, temp1 = ar[0],
temp2 /*temp1 and temp2 for switching elements*/,
loopCount /*rotations starting at the first s elemtns of ar*/ = 0;
s %= len;
while (loopCount < s)
{
int indAtBeg = ind;
temp1 = ar[ind];
bool done = false;
while (!done)
{
if (ind < s)
loopCount++;
ind = (ind + s) % len;
//cycle detected
if (ind == indAtBeg)
done = true;
//switch the elements
temp2 = ar[ind];
ar[ind] = temp1;
temp1 = temp2;
}
++ind;
}
}
#include <stdio.h>
int
main(void)
{
int arr[7] = {1,2,3,4,5,6,7};
int new_arr[7] = {0};
int k = 3;
int len = 7;
int i=0;
for (i = (len-1); i>=0; i--) {
if ((i+k) >= len) {
new_arr[(i+k-len)] = arr[i];
} else {
new_arr[(i+k)] = arr[i];
}
}
for (i=0;i<len;i++) {
printf("%d ", new_arr[i]);
}
return 0;
}
Time complexity O(n)
Space complexity O(2*n).
Thanks.
Here is the complete Java code for left and right array rotation by k steps
import java.util.*;
public class ArrayRotation {
private static Scanner sc;
public static void main(String[] args) {
int n,k;
sc = new Scanner(System.in);
System.out.print("Enter the size of array: ");
n = sc.nextInt();
int[] a = new int[n];
System.out.print("Enter the "+n+" elements in the list: ");
for(int i=0;i<n;i++)
a[i] = sc.nextInt();
System.out.print("Enter the number of left shifts to array: ");
k = sc.nextInt();
System.out.print("Array before "+k+" shifts: ");
display(a);
leftRoation(a,k);
System.out.println();
System.out.print("Array after "+k+" left shifts: ");
display(a);
rightRoation(a,k);
System.out.println();
System.out.print("Array after "+k+" right shifts: ");
display(a);
}
public static void leftRoation(int[] a, int k){
int temp=0, j;
for(int i=0;i<k;i++){
temp = a[0];
// j=0; // both codes work i.e. for loop and while loop as well
// while(j<a.length-1){
// a[j]=a[j+1];
// j++;
// }
for(j=0;j<a.length-1;j++)
a[j]=a[j+1];
a[j]=temp;
}
}
public static void rightRoation(int[] a, int k){
int temp=0, j;
for(int i=0;i<k;i++){
temp = a[a.length-1];
for(j=a.length-1;j>0;j--)
a[j]=a[j-1];
a[j]=temp;
}
}
public static void display(int[] a){
for(int i=0;i<a.length;i++)
System.out.print(a[i]+" ");
}
}
/****************** Output ********************
Enter the size of array: 5
Enter the 5 elements in the list: 1 2 3 4 5
Enter the number of left and right shifts to array: 2
Array before 2 shifts: 1 2 3 4 5
Array after 2 left shifts: 3 4 5 1 2
Array after 2 right shifts: 1 2 3 4 5 // here the left shifted array is taken as input and hence after right shift it looks same as original array.
**********************************************/
My solution... (a: the array, n : size of array, k: number of shifts) :
public static int[] arrayLeftRotation(int[] a, int n, int k) {
if (k == 0) return a;
for (int i = 0; i < k; i++) {
int retenue = a[0];
int[] copie = java.util.Arrays.copyOfRange(a, 1, n );
for (int y = 0; y <= copie.length - 1 ; y++) {
a[y] = copie[y];
}
a[n-1] = retenue;
}
return a;
}
Java implementation for right rotation
public int[] solution(int[] A, int K) {
int len = A.length;
//Create an empty array with same length as A
int arr[] = new int[len];
for (int i = 0; i < len; i++) {
int nextIndex = i + K;
if (nextIndex >= len) {
// wraps the nextIndex by same number of K steps
nextIndex = nextIndex % len;
}
arr[nextIndex] = A[i];
}
return arr;
}
>>> k = 3
>>> arr = [1,2,3,4,5,6,7]
>>> actual_rot = k % len(arr)
>>> left_ar = arr[:-actual_rot]
>>> right_ar = arr[-actual_rot:]
>>> result = right_ar + left_ar
>>> result
[5, 6, 7, 1, 2, 3, 4]
A better way to rotate an array by k steps is:
a = [1,2,3,4,5,6]
b = a[:]
k = 2
for i in range(len(a)):
a[(i + k) % len(a)] = b[i]## (rotate right by k steps)
#a[(i - k) % len(a)] = b[i]## (rotate left by k steps)
print(a)
o/p:
[6, 5, 1, 2, 3, 4]
how to rotate an array, IN this function first argument - array, the second argument is
a number or integer.
def rotLeft(a, d):
data = a
n = d
get = data[n:len(data)]
remains = data[0:n]
data.clear()
for i in get:
data.append(i)
for x in remains:
data.append(x)
return data
This is rotating the array to the right by k steps, where k is non-negative
for (int i = 0; i < k; i++) {
for (int j = nums.length - 1; j > 0; j--) {
int temp = nums[j];
nums[j] = nums[j - 1];
nums[j - 1] = temp;
}
}
return nums;
if (k > arr.length) {
k = k % arr.length;
}
int n = arr.length - k;
int count = 0;
outer:
for (int i = arr.length - 1; i >= n; i--) {
int temp = arr[i];
inner:
for (int j = i - 1; j >= 0; j--) {
arr[j + 1] = arr[j];
if (j == 0) {
int temp2 = arr[j];
arr[j] = temp;
i = arr.length;
count++;
if (count == k) {
break outer;
}
}
}
}
Here I have solved the same problem in go.
Try to run in go playground...
sample code.
func rotate(a []int, k int) {
for j := 0; j < k ; j++ {
temp := a[len(a)-1]
for i := len(a) - 1; i > 0; i-- {
a[i] = a[i-1]
}
a[0] = temp
}
}
If you are looking for the soltuion of Codility - Cyclic Rotation Problem then, here is the JavaScript code which gave 100% for me.
function solution(A, K) {
const L = A.length - (K % A.length); // to get the rotation length value below array length (since rotation of product of array length gives same array)
const A1 = A.slice(L); // last part of array which need to be get to front after L times rotation
const A2 = A.slice(0, L); // part which rotate L times to right side
const Result = [...A1, ...A2]; // reverse and join both array by spreading
return Result;
}
Rotate an array of n elements to the right by k steps.
For instance, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].
In JS the solution will be 2 part, in two line:
function rotateArray(array,k){
// remove the rotation part
const splice = [...array].splice(0,k); //... for make a clone;
// add reversed version of the what left
return array.concat(splice.reverse()) from original array.
}

Categories

Resources