Rearrange an array such that arr[i] = i - java

Input : arr = {-1, -1, 6, 1, 9, 3, 2, -1, 4, -1}
Output : [-1, 1, 2, 3, 4, -1, 6, -1, -1, 9]
Input : arr = {19, 7, 0, 3, 18, 15, 12, 6, 1, 8,
11, 10, 9, 5, 13, 16, 2, 14, 17, 4}
Output : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19]
Approach
1. Nav­i­gate the array.
Check if a[i] = -1, if yes then ignore it.
If a[i] != -1, Check if element a[i] is at its cor­rect posi­tion (i=A[i]). If yes then ignore it.
If a[i] != -1 and ele­ment a[i] is not at its cor­rect posi­tion (i!=A[i]) then place it to its correct posi­tion, but there are two conditions:
(i).Either A[i] is vacant, means A[i] = -1, then just put A[i] = i .
(ii).OR A[i] is not vacant, means A[i] = x, then int y=x put A[i] = i. Now, we need to place y to its cor­rect place, so repeat from step 3.
What would be the time complexity of below solution?
public static int[] fix(int[] A) {
for (int i = 0, x = A[i]; i < A.length; i++) {
if (x == -1 || x == i)
continue;
// check if desired place is not vacant
while (A[x] != -1 && A[x] != x) {
int y = A[x]; // store the value from desired place
A[x] = x; // place the x to its correct position
x = y; // now y will become x, now search the place for x
}
A[x] = x; // place the x to its correct position
// check if while loop hasn't set the correct value at A[i]
if (A[i] != i)
A[i] = -1; // if not then put -1 at the vacated place
}
return A;
}

I can offer you two algorithms.
First one: using extra array, time complexity is O(n), with O(n) additional memory
public static int[] fix(int[] arr) {
int[] res = new int[arr.length];
Arrays.fill(res, -1);
for (int i = 0; i < arr.length; i++)
if (arr[i] != -1)
res[arr[i]] = arr[i];
return res;
}
Second one: in place, time complexity is O(n^2) in worst case and O(n) in average case, without additional memory
public static int[] fix(int[] arr) {
int i;
while ((i = findIncorrectPosition(arr)) >= 0) {
while (arr[i] != -1 && arr[i] != i) {
swap(arr, i, arr[i]);
}
}
return arr;
}
...plus two private support methods:
private static int findIncorrectPosition(int[] arr) {
for (int i = 0; i < arr.length; i++)
if (arr[i] != -1 && arr[i] != i)
return i;
return -1;
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}

f(n) = O(n) using swapping methodology #Swift
for i in stride(from: 0, to: array.count, by: 1){
if(array[i] >= 0 && array[i] != i){
let ele = array[array[i]]
array[array[i]] = array[i]
array[i] = ele
}
}
for k in stride(from: 0, to: array.count, by:1 ){
print(" ",array[k])
}

Related

Move all zeroes in a given array to the end and replace each non-zero element with the closest greater value, if any

Looking for the optimised solution for the below problem.
Given an unsorted array, we are required to move all zeroes to the end of the array and at same time find the next closest greater number of each element(non-zero) and return the same element incase if there is no next greater element for an element in the array .
Input = {6,1,5,0,0,3,8,6,4}
Output = {8,3,6,4,8,6,4,0,0}
I tried the below :
public class next_closest_element {
public static void main(String[] arg) {
int[] input = {6, 1, 5, 0, 0, 3, 8, 6, 4};
Stack<Integer> stack = new Stack<Integer>();
int k = 0;
int count = 0;
int last_index_value =input.length-1;
for (int i = 0; i < input.length; i++) {
if (input[i] != 0) {
int j = i + 1;
boolean flag = false;
while (j < input.length && input[i] != 0) {
if (input[j] > input[i]) {
if (stack.empty() || !flag) {
stack.push(input[j]);
flag = true;
j++;
} else if (stack.peek() > input[j]) {
stack.pop();
stack.push(input[j]);
flag = true;
j++;
} else {
j++;
}
} else {
j++;
}
}
if (flag) {
input[k] = stack.peek();
k++;
}
else {
input[k]=input[i];
k++;
}
}
else{
count +=1;
}
}
while(count>0){
input[last_index_value]=0;
last_index_value--;
count--;
}
for (int s :
input) {
System.out.println(s);
}
}
}
First shoveling the zeroes to the right would be one optimisation.
Possibly replacing with next closest greater element I have interpreted as next following element (as you seemed to do, as otherwise the last 4 might have become the overwritten 5).
static int[] f(int[] values) {
// In-situ (in-place) algorithm.
int n = 0; // The count of non-zero values.
for (int i = 0; i < values.length; ++i) {
if (values[i] != 0) {
values[n] = values[i];
++n;
}
}
// Zero the rest:
// (With a second array the remaining values from n upwards would
// already be zero.)
for (int i = n; i < values.length; ++i) {
values[i] = 0;
}
// {6, 1, 5, 0, 0, 3, 8, 6, 4} -> {6, 1, 5, 3, 8, 6, 4, [n] 0, 0}
// (First optimisation.) Now we only need to deal with n non-zero values.
// Search the next (A) closest greatest (B) number, when found substitute.
// Unoptimized:
for (int i = 0; i < n; ++i) {
int ithValue = values[i];
boolean hasClosest = false;
int closest = Integer.MAX_VALUE;
for (int j = i + 1; j < n; ++j) {
int jthValue = values[j];
if (jthValue > ithValue && (!hasClosest || jthValue < closest)) {
closest = jthValue;
hasClosest = true;
values[i] = jthValue;
}
}
}
// {8, 3, 6, 4, 8, 6, 4, 0, 0}
return values;
}
public static void main(String[] args) {
int[] input = {6, 1, 5, 0, 0, 3, 8, 6, 4};
System.out.println(Arrays.toString(f(input)));
}
The last piece is not well optimized.
An other interpretation of "closest greatest:"
int[] sorted = Arrays.copyOf(values, n);
Arrays.sort(sorted);
for (int i = 0; i < n; ++i) {
int j = Arrays.binarySearch(sorted, values[i] + 1);
if (j < 0) { // Not found 1 greater.
j = ~j; // Even greater.
}
if (j < n) {
values[i] = sorted[j];
}
}
// {8, 3, 6, 4, 8, 8, 5, 0, 0}
Sorting cost O(N log N), as does the loop O(N) times binary search O(log N).
So it is faster, costing memory. But that is comparible with you stack usage.
By the way, a cleaned up version of your code could have been put on CodeReview.

Trying to swap the maximum and the minimum numbers in an array

I'm trying to swap the maximum and minimum values in an array in my program.
Here is the code:
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int myArray[] = new int[25];
for (int i = 0; i < myArray.length; i++) {
System.out.println("Enter a number: ");
myArray[i] = in.nextInt();
}
int maximum = maxNumber(myArray);
int minimum = minNumber(myArray);
System.out.println(Arrays.toString(myArray));
}
public static int maxNumber(int[] arr) {
int maximumValue = arr[0];
//finds the maximum value in an array
for (int a = 1; a < arr.length; a++) {
if (arr[a] > maximumValue) {
maximumValue = arr[a];
}
}
return maximumValue;
}
public static int minNumber(int[] arr) {
int minimumValue = arr[0];
//finds the minimum value in an array
for (int a = 1; a < arr.length; a++) {
if (arr[a] < minimumValue) {
minimumValue = arr[a];
}
}
return minimumValue;
}
I have two separate functions to find the Maximum and Minimum values, but I'm stuck on the actual swapping of the values. The two functions work as I've used them for another program, but I'm not sure if they would work for this program.
At first I was thinking of finding them by setting them equal to each other in some way, but that led to nothing.
Any help would be appreciated.
public static void main(String... args) {
Scanner scan = new Scanner(System.in);
int[] arr = new int[25];
System.out.format("Enter array int numbers (%d in total): ", arr.length);
for (int i = 0; i < arr.length; i++)
arr[i] = scan.nextInt();
System.out.println(Arrays.toString(arr));
swamMinMax(arr);
System.out.println(Arrays.toString(arr));
}
private static void swamMinMax(int[] arr) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
min = Math.min(min, arr[i]);
max = Math.max(max, arr[i]);
}
for (int i = 0; i < arr.length; i++) {
if (arr[i] == min)
arr[i] = max;
else if (arr[i] == max)
arr[i] = min;
}
}
Output:
Enter array int numbers (25 in total): 1 2 3 4 5 6 7 8 9 10 -1 -1 -1 14 15 16 17 18 19 20 21 22 23 66 66
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, 1, 1, 1, 17, 18, 19, 20, 21, 22, 23, 66, 66]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 66, 66, 66, 1, 1, 1, 17, 18, 19, 20, 21, 22, 23, -1, -1]
You were real close. I copied some of the code and commented where the changes need to be made. You can still use your existing code to populate the array from the console.
Also, kudos for assigning the first element in the array to min or max and starting your loop at 1. A lot of folks don't think about doing that.
int myArray[] = {1,10,-5,99,48,-22,43, 44,100,2};
System.out.println(Arrays.toString(myArray)); // print original array
int maxIdx = maxNumber(myArray); // get index of max
int minIdx = minNumber(myArray); // get index of min
// now swap max and min using the returned indices.
int save = myArray[maxIdx];
myArray[maxIdx] = myArray[minIdx];
myArray[minIdx] = save;
System.out.println(Arrays.toString(myArray)); // print the altered array
public static int maxNumber(int[] arr) {
int maximumValue = arr[0];
// finds the maximum value in an array
int idx = 0; //idx = 0 to start
for (int a = 1; a < arr.length; a++) {
if (arr[a] > maximumValue) {
idx = a; //save index of current max
maximumValue = arr[a];
}
}
return idx; // return index of max
}
public static int minNumber(int[] arr) {
int minimumValue = arr[0];
// finds the minimum value in an array
int idx = 0; // idx = 0 to start
for (int a = 1; a < arr.length; a++) {
if (arr[a] < minimumValue) {
idx = a; // save index of current min
minimumValue = arr[a];
}
}
return idx; // return index of min
}
This would print
[1, 10, -5, 99, 48, -22, 43, 44, 100, 2]
[1, 10, -5, 99, 48, 100, 43, 44, -22, 2]
You can use IntStream to find indexes of the maximum and minimum elements and then swap their values:
int[] arr = {1, 3, 5, 6, 4, 2, 8, 7, 9, -1, -3};
// indexes of the maximum and minimum elements
int max = IntStream.range(0, arr.length)
.boxed().max(Comparator.comparing(i -> arr[i])).orElse(-1);
int min = IntStream.range(0, arr.length)
.boxed().min(Comparator.comparing(i -> arr[i])).orElse(-1);
// swap the values
int temp = arr[max];
arr[max] = arr[min];
arr[min] = temp;
System.out.println(Arrays.toString(arr));
// [1, 3, 5, 6, 4, 2, 8, 7, -3, -1, 9]

Why does my binary search not work properly [duplicate]

This question already has answers here:
What is the difference between Linear search and Binary search?
(11 answers)
Closed 2 years ago.
Given an array of elements of length N, ranging from 0 to N – 1. All elements may not be present in the array. If element is not present then there will be -1 present in the array. Rearrange the array such that A[i] = i and if i is not present, display -1 at that place
So that is the question, but my binarySearch is not working, why?
for(int i = 0; i < size; i++) {
int res = i;
// System.out.println(Arrays.binarySearch(arr,res));
int result = Arrays.binarySearch(arr,res);
if(result == -1)
arr[i] = -1;
else {
arr[i] = i;
}
}
for(int i = 0; i < size; i++) {
System.out.print(arr[i]+" ");
}
Binary search works only with sorted arrays. Try using a different search algorithm
If you can use additional array, the solution may be as follows:
Create resulting array
Fill resulting array with -1
Iterate over input array and fill appropriate numbers in the resulting array.
// input array
int[] arr = {-1, 2, 3, 0};
// prepare new resulting array
int[] res = new int[arr.length];
// fill with -1
// Arrays.fill(res, -1); // use this shortcut if you're allowed to use library
for (int i = 0; i < res.length; i++) {
res[i] = -1;
}
// rearrange
for (int i = 0; i < arr.length; i++) {
if (arr[i] != -1) {
res[arr[i]] = arr[i];
}
}
System.out.println("input data: " + Arrays.toString(arr));
System.out.println("rearranged: " + Arrays.toString(res));
Output:
input data: [-1, 2, 3, 0]
rearranged: [0, -1, 2, 3]
Update
Recursive solution without using extra array:
public static void test() {
int[] arr = {-1, 4, 2, 0, 1, 3};
System.out.println("input data: " + Arrays.toString(arr));
// rearrange
for (int i = 0; i < arr.length; i++) {
if (arr[i] != -1 && arr[i] != i) {
swapAtIndex(arr, i);
}
}
System.out.println("rearranged: " + Arrays.toString(arr));
}
private static void swapAtIndex(int[] arr, int i) {
int t = arr[i];
if (t != -1 && t != i) {
int t2 = arr[t];
arr[t] = t;
arr[i] = t2;
if (t2 != -1) {
swapAtIndex(arr, i); // continue swapping at the same index
}
}
}
output:
input data: [-1, 4, 2, 0, 1, 3]
rearranged: [0, 1, 2, 3, 4, -1]
For the input array without -1, you'll get a sorted array after rearrangement:
input data: [5, 4, 2, 0, 1, 3]
rearranged: [0, 1, 2, 3, 4, 5]

Given an array of integers, reverse every maximal strictly ascending subarray

How would I rearrange the elements of a given array of integers in place so that the elements of every maximal strictly ascending subarray are reversed?
For example, given the array { 5, 7, 10, 4, 2, 7, 8, 1, 3 }, after executing this method, the elements of the array would be { 10, 7, 5, 4, 8, 7, 2, 3, 1 }.
My attempt only sorts the integers in descending order. How can I make these nested loops identify the maximal strictly ascending subarrays? I believe the outer loop should have to repeatedly find the end of the current ascending sequence, while the inner loop reverses the subarray up to that point.
public class MyClass {
public static void main(String args[]) {
int[] arr = {5, 7, 10, 4, 2, 7, 8, 1, 3};
for (int i=0; i<arr.length-1; i++) {
if (arr[i] < arr[i+1]) {
int t = arr[i+1];
arr[i+1] = arr[i];
arr[i] = t;
}
for (int j=0; j<arr.length-1; j++) {
if (arr[j] < arr[j+1]) {
int t = arr[j+1];
arr[j+1] = arr[j];
arr[j] = t;
}
}
}
String result = Arrays.toString(arr);
System.out.println(result); // [10, 8, 7, 7, 5, 4, 3, 2, 1]
}
}
I see why you are using nested loop. But I think you'll need to keep track of start and end instead of just swapping. Here's how I solved it using a stack:
public static void main(String[] args) {
System.out.println(Arrays.toString(reverseAscendingSubArray(new int[]{5, 7, 10, 4, 2, 7, 8, 1, 3})));
}
private static int[] reverseAscendingSubArray(int[] arr) {
Stack<Integer> stack = new Stack<>();
int[] result = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
if (i == 0 || arr[i - 1] < arr[i]) {
stack.push(arr[i]);
} else {
for (int j = stack.size(); j > 0; j--) {
result[i - j] = stack.pop();
}
stack.push(arr[i]);
}
}
if (!stack.empty()) {
for (int j = stack.size(); j > 0; j--) {
result[arr.length - j] = stack.pop();
}
}
return result;
}
Output
[10, 7, 5, 4, 8, 7, 2, 3, 1]
Explanation
I keep pushing elements into the stack until the current element is greater than the previous one. As soon as I get something smaller than the previous, I pop all elements from the stack and write them to a new array. This pushing and popping will reverse the elements.
You can try using bubble sort as in the code below.
public static void reverseAscendingSubarrays(int[] items){
int start = -1;
int stop = -1;
for (int i = 0; i < items.length; i++){
if (i != items.length - 1){
if (items[i] <= items[i + 1]){
if (start == -1) {
start = i;
}
}
else {
if (start != -1) {
stop = i;
}
}
}
else{
if (start != -1){
stop = i;
}
}
if (start != -1 && stop != -1){
//sort array from start to stop (uses bubble sort - inefficient for large arrays)
for (int n = 0; n < stop - start + 1; n++)
for (int j = start; j < stop; j++){
if (items[j] < items[j+1]){
//swap
int temp = items[j];
items[j] =items[j+1];
items[j+1] = temp;
}
}
start = -1;
stop = -1;
}
}
}

How to transform an array to the table in Java?

Suppose, I have an array like
[1,2,3,4,5,6,7,8,9,10,11,12]
Are there any standard methods to transform it to the table with N columns?
For example, if N=3:
[[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
or if N=4:
[[1,2,3,4],[5,6,7,8],[9,10,11,12]]
etc.
With Java 8, you can use an IntStream to generate the corresponding indexes that you'll give to Arrays.copyOfRange.
I answered a sort of a similar question and you can find the logic there but here's it's slightly modified to take the array as parameter:
static List<int[]> partitionIntoList(int[] arr, int pageSize) {
return IntStream.range(0, (arr.length + pageSize - 1) / pageSize)
.mapToObj(i -> Arrays.copyOfRange(arr, i * pageSize, min(pageSize * (i + 1), arr.length)))
.collect(toList());
}
static int[][] partitionIntoArray(int[] arr, int pageSize) {
return IntStream.range(0, (arr.length + pageSize - 1) / pageSize)
.mapToObj(i -> Arrays.copyOfRange(arr, i * pageSize, min(pageSize * (i + 1), arr.length)))
.toArray(int[][]::new);
}
Note that if pageSize does not partition perfectly the input's size, the remaining elements are added in the last int array.
For example,
partitionIntoArray(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, 4);
outputs:
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
and if you take a page size of 5, the two last elements will be added to a third array:
[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12]]
Hope it helps! :)
Just using for loops:
int[] array = {1,2,3,4,5,6,7,8,9,10,11,12};
int n = 3;
int m = (int) Math.ceil( ( (double) array.length ) / n );
int[][] table = new int[m][n];
int k = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (k < array.length) {
table[i][j] = array[k];
k++;
}
}
}
The output should be what you are asking for.
Not really but you can create one easily using some math and a loop:
public int[][] getTable(int[] arr, int n) {
int[][] table = new int[(int)Math.ceil(arr.length / (float)n)][n];
for (int i = 0, row = 0, column = 0; i < arr.length; i++) {
if (i % n == 0 && i != 0) {
row++;
column = 0;
}
table[row][column++] = arr[i];
}
return table;
}
We could do it this way :
int n = 5; // what ever size you want to break it with
int[] bytes = {1,2,3,4,5,6,7,8,9,10,11,12};
int length = bytes.length;
int counter = 0;
int newSize = length % n == 0 ? length/n : (length/n)+1;
int[][] newArray = new int[newSize][n];
for (int i = 0; i < length - n + 1; i += n)
newArray[counter++] = Arrays.copyOfRange(bytes, i, i + n);
if (length % n != 0)
newArray[counter] = Arrays.copyOfRange(bytes, length - length % n, length);

Categories