Delete local maximum - java

A local maximum is an element that is greater than any of its neighboring elements. You must remove elements that are local maxima in the original array.
Input array:
[18, 1, 3, 6, 7, -5]
output array:
[1, 3, 6, -5]
public static int[] removeLocalMaxima(int[] array){
int[] result = new int[array.length];
int j = 0;
for (int i = 0; i < array.length - 1; i++, j++) {
if(array[i] > array[i + 1]){
result[j] = array[++i];
}else {
result[j] = array[i];
}
}
return Arrays.copyOf(result, j);
}
if you set it like that, then something is not working:
array = new int[1000];
Arrays.fill(array, 15);
array[0] = -20;
array[999] = 25;
array[168] = 18;
array[421] = 0;
actual = LocalMaximaRemove.removeLocalMaxima(array);
assertEquals(998, actual.length);
assertEquals(-20, actual[0]);
assertEquals(15, actual[997]);
assertEquals(0, actual[420]);

public static int[] removeLocalMaxima(int[] array){
int[] result = new int[array.length];
int j = 0;
for (int i = 0; i < array.length; i++) {
if ((i > 0 && array[i] <= array[i - 1])
|| (i != array.length - 1 && array[i] <= array[i + 1])){
result[j++] = array[i];
}
}
return Arrays.copyOf(result, j);
}
My function saves in result array only elements that are less or equal of any of its neightbors.

Related

Removing a redundant variable/shortening code

I need to remove the "min" variable and still allow the sorting program to run however, I am confused on where exactly to start.
int[] A = {13, 5, 2, 0, 3, 1, 21, 1, 8};
for (int k=0; k<A.length-1; k++) {
int min = A[k];
int minPosition = k;
for (int i=k+1; i<A.length; i++) {
if (A[i] < min) {
min = A[i];
minPosition = i;
}
}
int temp = A[k];
A[k] = A[minPosition];
A[minPosition] = temp;
}
for (int i=0; i<A.length; i++) {
System.out.println (A[i]);
}
You have both min and minPosition:
int min = A[k];
int minPosition = k;
Start by removing the declaration for min altogether (delete the line int min = A[k]), delete the line min = A[i], and finally, edit the if statement from this:
if (A[i] < min) {
...
}
to this:
if (A[i] < A[minPosition]) {
...
}
You have 2 variables that are doing the same job :
i) min which keeps track of the minimum in the array
ii) minPosition which is index of the min value.
You can simply compare everytime with the element at minPosition and swap it in the end.
class Main {
public static void main(String args[]) {
int[] A = { 13, 5, 2, 0, 3, 1, 21, 1, 8 };
for (int k = 0; k < A.length - 1; k++) {
// int min = A[k];
int minPosition = k;
for (int i = k + 1; i < A.length; i++) {
if (A[i] < A[minPosition]) {
minPosition = i;
}
}
int temp = A[k];
A[k] = A[minPosition];
A[minPosition] = temp;
}
// for (int i = 0; i < A.length; i++) {
System.out.println(Arrays.toString(A));
// }
}
}

Java Subarray with specific size from array

If I have array like [1,2,3,4] and k = 3 then output should be [1,2,3][2,3,4] which is in this order. The idea is to get subarray with k elements and then the next to start from the next element and also to have k elements
I can't think of a way to do it more generic for any value of k.
final int arr[] = new int[] { 1, 2, 3, 4 };
final int max = 2;
for (int i = 0; i < arr.length - 1; i++) {
for (int j = i + 1; j < arr.length; j++) {
for (int k = 0; k < max; k = k + 2) {
System.out.println(i + "" + j);
}
}
}
You can extract parts of an array by calling Arrays.copyOfRange() method:
int[] arr = {1, 2, 3, 4};
int k = 3;
int numberOfResults = arr.length - k + 1;
for (int i = 0; i < numberOfResults; i++) {
int[] result = Arrays.copyOfRange(arr,i,i+k);
System.out.println(Arrays.toString(result));
}

Error when setting entry of int[] array to null

I had the following idea to take an array and remove any duplicates. However, I am getting the error "error: incompatible types: cannot be converted to int" referring to the part of the code where I set temp[i] = null. Is it possible to do this? How can I fix this problem?
public static int[] withoutDuplicates(int[] x) {
int[] temp = new int[x.length];
int count = 0;
for (int i = x.length - 1; i >= 0; i--) {
for (int j = i-1; j >= 0; j--) {
if (temp[i] == x[j]) {
temp[i] = null;
count++;
}
}
}
int size = x.length - count;
int[] a = new int[size];
int pos = 0;
for (int i = 0; i < x.length; i++) {
if (temp[i] != null) {
a[pos] = temp[i];
pos++;
}
}
return a;
}
Stream-based solution is concise but for your task/requirements you could be using just a temporary boolean array to mark positions of duplicates:
public static int[] withoutDuplicates(int[] x) {
boolean[] duplicated = new boolean[x.length];
int count = 0;
for (int i = x.length - 1; i > 0; i--) {
for (int j = i-1; j >= 0; j--) {
if (x[i] == x[j]) {
duplicated[i] = true;
count++;
}
}
}
int size = x.length - count;
int[] a = new int[size];
for (int i = 0, pos = 0; pos < size && i < x.length; i++) {
if (!duplicated[i]) {
a[pos++] = x[i];
}
}
return a;
}
Test:
int[] arr1 = {1, 2, 3, 4, 3, 5, 2};
int[] arr2 = {1, 2, 3, 4, 0, 5, 6};
System.out.println(Arrays.toString(withoutDuplicates(arr1)));
System.out.println(Arrays.toString(withoutDuplicates(arr2)));
output
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 0, 5, 6]
You can't assign a null to a primitive type int but you can assign a null to the wrapper object Integer.
To remove the duplicates of an int array you could use something like this:
myIntArray = Arrays.stream(myIntArray).distinct().toArray();

Create a new array based on another array in Java

This returns only the array a. I need to do an array that is equal to the array a but when the element is multiple of 3 i need to add the next even number. Like a=[1,3,4,6,1], the array would look like [1,7,4,6,1]. How would I do it? Thank you.
public static void main(String[] args) {
int[] a = new int[]{10, 46, 78, 32, 3, 80, 97, 11, 39, 57};
System.out.println(Arrays.toString(a));
}
public static int[] multiplos3 (int[] a){
int[] b = new int[a.length];
int j = 0;
for (int i = 0 ; i < a.length; i++){
if (a[i] % 3 == 0){
if(a[i + 1] % 2 == 0) {
b[j] = a[i] + a[i + 1];
j++;
}
}
}
System.out.println(Arrays.toString(b));
return b;
}
}
Based on a comment:
public static void multiplos3 (int[] a){
int[] b = new int[a.length]; System.arraycopy(a, 0, b, 0, a.length);
for (int i = 0 ; i < a.length; i++){
if (a[i] % 3 == 0){
for(int j = i + 1; j < a.length; j++){
if(a[j] % 2 == 0) {
b[i] = a[i] + a[j];
break;
}
}
}
}
System.out.println(Arrays.toString(b));
}
....................................................
Instead of using a[i + 1], try using another for loop to find the next even number
for(int j = i + 1; j < a.length; j++)
if(a[j] % 2 == 0)
{
[...]
break; //stop the loop after the first even number
}
The run time complexity of above mentioned code is O(N^2)
You can implement this in O(N) by first using an additional array
Try to populate this next even numbers array by traversing from the last
Below is the code
public static void multiplos3 (int[] a){
int[] b = new int[a.length];
int[] nextEvnNosArr = new int[a.length];
for (int i = a.length - 2; i > 0; i++) {
if (a[i] %2 == 0) {
nextEvnNosArr[i] = a[i];
} else {
if (nextEvnNosArr[i + 1] % 2 == 0) {
nextEvnNosArr[i] = nextEvnNosArr[i+1];
} else {
nextEvnNosArr[i] = -1;
}
}
}
for (int i = 0 ; i < a.length; i++){
if (a[i] % 3 == 0){
if (i != a.length - 1 && nextEvnNosArr[i + 1] != -1){
b[j] = a[i] + nextEvnNosArr[i + 1];
j++;
}
}
}
}
System.out.println(Arrays.toString(b));
}

Optimized Bubble Sort

I would like to know how else I can optimize bubble sort so that it overlooks elements that have already been sorted, even after the first pass.
Eg. [4, 2, 3, 1, 5, 6] --> [2, 3, 1, **4, 5, 6**]
We observe that [4,5,6] are already in sorted order, how can I modify my code so that it overlooks this 3 elements in the next pass? Which means the sort would be more efficient? Do you suggest a recursive method?
public static void bubbleSort(int[] a) {
for (int i = 1; i < a.length; i++) {
boolean is_sorted = true;
for (int j = 0; j < a.length; j++) {
if (a[j] > a[j + 1]) {
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
is_sorted = false;
}
}
if (is_sorted) return;
}
}
First of all, you have an out-of-bounds access:
for (int j = 0; j < a.length; j++) {
if (a[j] > a[j + 1]) {
for j == a.length-1, so the loop condition should rather be j < a.length-1.
But, in Bubble sort, you know that after k passes, the largest k elements are sorted at the k last entries of the array, so the conventional Bubble sort uses
public static void bubbleSort(int[] a) {
for (int i = 1; i < a.length; i++) {
boolean is_sorted = true;
// skip the already sorted largest elements
for (int j = 0; j < a.length - i; j++) {
if (a[j] > a[j + 1]) {
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
is_sorted = false;
}
}
if (is_sorted) return;
}
}
Now, that would still do a lot of unnecessary iterations when the array has a long sorted tail of largest elements, say you have k,k-1,...,1 as the first k elements and k+1 to 100000000 in order after that. The standard Bubble sort will pass k times through (almost) the entire array.
But if you remember where you made your last swap, you know that after that index, there are the largest elements in order, so
public static void bubbleSort(int[] a) {
int lastSwap = a.length - 1;
for (int i = 1; i < a.length; i++) {
boolean is_sorted = true;
int currentSwap = -1;
for (int j = 0; j < lastSwap; j++) {
if (a[j] > a[j + 1]) {
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
is_sorted = false;
currentSwap = j;
}
}
if (is_sorted) return;
lastSwap = currentSwap;
}
}
would sort the above example with only one pass through the entire array, and the remaining passes only through a (short) prefix.
Of course, in general, that won't buy you much, but then optimising a Bubble sort is a rather futile exercise anyway.
public static void BubbleSorter(params int[] input) {
int newSize = input.Length - 1, size = 0;
bool swap;
do {
swap = false;
for (int j = 0; j < newSize; j++) {
if (input[j] > input[j + 1]) {
int temp = input[j + 1];
input[j + 1] = input[j];
input[j] = temp;
swap = true;
size = j;
}
}
newSize = size;
} while (swap);
DisplayArrayElements(input);
}
public static Integer[] optimizedBubbleSort(Integer[] input) {
long startTime = System.nanoTime();
boolean swapped = true;
for (int pass = input.length - 1; pass >= 0 && swapped; pass--) {
swapped = false;
for (int i = 0; i < pass; i++) {
if (input[i] > input[i + 1]) {
int temp = input[i];
input[i] = input[i + 1];
input[i + 1] = temp;
swapped = true;
}
}
}
System.out.println("Time taken for OPTIMIZED bubbleSort: "
+ (System.nanoTime() - startTime));
return input;
}
you should use a variable "size" for the inner loop and change it to the latest swapped element in each cycle.This way your inner loop goes up to the latest "swapped" element and passes the rest that are unswapped (aka in their correctplace). i.e
do {
int newsize = 0;
for (int i = 1; i < size; i++) {
if (a[i - 1] > a[i]) {
int temp;
temp = a[i - 1];
a[i - 1] = a[i];
a[i] = temp;
newsize = i;
}
}
size = newsize;
} while (size > 0);
In the above example, the array got sorted after 3rd pass, but we will still continue with the 4th, 5th pass. Suppose if the array is already sorted, then there will be no swapping (because adjacent elements are always in order), but still we will continue with the passes and there will still be (n-1) passes.
If we can identify, that the array is sorted, then we should stop execution of further passes. This is the optimization over the original bubble sort algorithm.
If there is no swapping in a particular pass, it means the array has become sorted, so we should not perform the further passes. For this we can have a flag variable which is set to true before each pass and is made false when a swapping is performed.
void bubbleSort(int *arr, int n) {
for (int i = 0; i < n; i++) {
bool flag = false;
for (int j = 0; j < n - i - 1; j++) {
if (array[j] > array[j + 1]) {
flag = true;
int temp = array[j + 1];
array[j + 1] = array[j];
array[j] = temp;
}
}
// No Swapping happened, array is sorted
if (!flag) {
return;
}
}
}
You can use a single do-while-loop instead of two nested for-loops and move the logic into the internal if-statement. Subsequent passes are shorter by the pass index.
public static void bubbleSort(int[] arr) {
boolean swapped = false;
int i = 0, pass = 0;
do {
if (i < arr.length - 1 - pass) {
if (arr[i] > arr[i + 1]) {
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
swapped = true;
}
i++;
} else {
i = 0;
pass++;
swapped = false;
}
} while (i < arr.length - 1 - pass || swapped);
}
public static void main(String[] args) {
int[] arr = {6, 1, 5, 8, 4, 3, 9, 2, 0, 7};
System.out.println(Arrays.toString(arr));
bubbleSort(arr);
System.out.println(Arrays.toString(arr));
}
Output:
[6, 1, 5, 8, 4, 3, 9, 2, 0, 7]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
See also: Bubble sort output is incorrect
public class Tester {
static boolean bubbleFlag = true;
public static void main(String[] args) {
int array[] = new int[]{1, 9, 2, 3, 4, 5, 6};
bubbleSort(array);
}
private static void bubbleSort(int... array) {
System.out.println("Before Sorting: " + Arrays.toString(array));
for (int i = 0; i < array.length - 1; i++) {
if (i > 0) if (bubbleFlag) break;
for (int j = 0; j < array.length - i - 1; j++) {
if (array[j] > array[j + 1]) array = swap(j, j + 1, array);
System.out.println("Iteration "+j+" :"+Arrays.toString(array));
}
bubbleFlag = true;
}
}
private static int[] swap(int i1, int i2, int... is) {
bubbleFlag = false;
is[i1] = is[i1] + is[i2];
is[i2] = is[i1] - is[i2];
is[i1] = is[i1] - is[i2];
return is;
}
}
Output:
Before Sorting: [1, 9, 2, 3, 4, 5, 6]
Iteration 0 :[1, 9, 2, 3, 4, 5, 6]
Iteration 1 :[1, 2, 9, 3, 4, 5, 6]
Iteration 2 :[1, 2, 3, 9, 4, 5, 6]
Iteration 3 :[1, 2, 3, 4, 9, 5, 6]
Iteration 4 :[1, 2, 3, 4, 5, 9, 6]
Iteration 5 :[1, 2, 3, 4, 5, 6, 9]
I devised a method that reduces the number of iterations by excluding parts at the beginning and end of the array that have been ordered in previous loops.
static int[] bubbleSortOptimized(int arr[]) {
int start = 0, stop = arr.length - 1, control = 0;
boolean ordered, nsCaught;
while (true) {
ordered = true;
nsCaught = false;
for (int i = start; i < stop; i++) {
if (i > 1) {
if (!nsCaught && arr[i - 2] > arr[i - 1]) {
ordered = false;
start = i - 2;
nsCaught = true;
}
}
if (arr[i] > arr[i + 1]) {
int hold = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = hold;
control = i;
}
}
System.out.println(Arrays.toString(arr));
if (ordered) return arr;
stop = control;
}
}
But as #Daniel Fischer said in an earlier answer, it doesn't do a lot with larger arrays.
I think this is what you need. The key is to consider the
array only till the index where last swap occurred (newn).
public static void bubbleSort(int[] a) {
int i, n, newn;
n = a.length;
while (n > 0) {
newn = 0;
for (i = 1; i < n; i++) {
if (a[i - 1] > a[i]) {
temp = a[i];
a[i] = a[i - 1];
a[i - 1] = temp;
newn = i;
}
}
n = newn;
}
return a;
}
Here is the simplest, best and optimal Bubble Sort Algorithm using a while loop. It sorts the numbers in the given array form left to right in ascending order. It is very simple to understand and easy to implement.
private static int[] bubbleSort(int[] array) {
int length = array.length - 1;
int index = 0;
while (index < length) {
if (array[index] > array[index + 1]) {
swap(array, index, index + 1);
}
index++;
if (index == length) {
index = 0;
length--;
}
}
return array;
}
private static void swap(int[] array, int index1, int index2) {
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
public static void main(String[] args) {
int[] arr = {4, 2, 3, 1, 5, 6};
System.out.println(Arrays.toString(arr));
bubbleSort(arr);
System.out.println(Arrays.toString(arr));
}
Output:
[4, 2, 3, 1, 5, 6]
[1, 2, 3, 4, 5, 6]
I don't have code, but you could use n bits to keep track of where swaps were performed in the last pass. Or, less effectively, use a single variable to track where the first swap was performed. We don't need to re-compare elements that were not swapped - they are the same elements in the same order, so we know the comparisons will be the same, and we can safely skip them.
Intuitively I feel, even with the above optimization, bubble sort would still not beat the comparisons of a binary insertion sort, and would introduce a lot more branch logic (on top of the auxiliary space) to keep track of the swaps. So this is probably not worth investigating, unless someone is curious.
Optimized bubble sort with just 1 for Loop
/*Advanced BUBBLE SORT with ONE PASS*/
/*Authored by :: Brooks Tare AAU*/
public class Bubble {
public int[] bubble(int b[]) {
int temp, temp1;
for (int i = 0; i < b.length - 1; i++) {
if (b[i] > b[i + 1]) {
///swap(b[i],b[i+1]);
temp = b[i];
b[i] = b[i + 1];
b[i + 1] = temp;
// Checking if there is any number(s) greater
// than the current number. If there is swap them.
while (i > 0) {
if (b[i] < b[i - 1]) {
///swap(b[i]<b[i-1])
temp1 = b[i];
b[i] = b[i - 1];
b[i - 1] = temp1;
i--;
} else if (b[i] > b[i - 1]) {
i--;
}
}
} else {
continue;
}
}
return b;
}
///the following is a function to display the Array
public void see(int[] a) {
for (int j = 0; j < a.length; j++) {
System.out.print(a[j] + ",");
}
}
public static void main(String[] args) {
///You can change the Array to your preference..
// u can even make it dynamic
int b[] = {5, 1, 4, 2, 0, 3};
int v[] = new int[100];
Bubble br = new Bubble();
v = br.bubble(b);
br.see(v);
}
}

Categories

Resources