How do I delete duplicates in my array merging method? - java

I have a method that takes 2 attributes which are 2 arrays and merges them in the ascending order. All that's left for me is to figure out how to delete duplicates. Here's the code:
public static int[] mergeArrays(int[] a, int[] b){
int[] c = new int[a.length+b.length];
int aIt = 0;
int bIt = 0;
while(true) {
if(aIt < a.length && bIt < b.length) {
if(a[aIt] == b[bIt]){
c[aIt+bIt] = a[aIt++];
}
else{
c[aIt+bIt] = b[bIt++];
}
} else if(aIt < a.length) {
c[aIt+bIt] = a[aIt++];
} else if(bIt < b.length) {
c[aIt+bIt] = b[bIt++];
} else {
break;
}
}
return c;
}
As you can imagine, this is an assignment, so I'm not supposed to use any external libraries, otherwise this would be a lot easier.
I tried this method, but when I run this code in the console it seems to put it in some never-ending loop which consumes my CPU core entirely until I stop the process:
public static int[] mergeArrays(int[] a, int[] b){
int[] c = new int[a.length+b.length];
int aIt = 0;
int bIt = 0;
int lastVal = 0;
while(true) {
if(c[aIt+bIt] == lastVal){
continue;
}
else{
if(aIt < a.length && bIt < b.length) {
if(a[aIt] == b[bIt]){
c[aIt+bIt] = a[aIt++];
lastVal = c[aIt+bIt];
}
else{
c[aIt+bIt] = b[bIt++];
lastVal = c[aIt+bIt];
}
} else if(aIt < a.length) {
c[aIt+bIt] = a[aIt++];
lastVal = c[aIt+bIt];
} else if(bIt < b.length) {
c[aIt+bIt] = b[bIt++];
lastVal = c[aIt+bIt];
} else {
break;
}
}
}
return c;
}
It seems as though the "continue" keyword is the problem. When I try break in its place, the code executes.
EDIT:
I've added a new array to the mergeArrays method:
public static int[] mergeArrays(int[] a, int[] b)
{
int a_size = a.length;
int b_size = b.length;
int[] c = new int[a_size + b_size];
int[] d = null;
int i = 0 , j = 0, x = -1;
for(; i < a_size && j < b_size;)
{
if(a[i] <= b[j])
{
c[++x] = a[i];
++i;
}
else
{
if(c[x] != b[j])
{
c[++x] = b[j]; // avoid duplicates
}
++j;
}
}
--i; --j;
while(++i < a_size)
{
c[++x] = a[i];
}
while(++j < b_size)
{
c[++x] = b[j];
}
d = new int[uniqueValues(c)];
for(int g=0; g<uniqueValues(c); g++){
d[g] = c[g];
}
return d;
}

Well you can certainly do these in following two steps task :
Sort both the arrays.
static void sortArray(int[] a) {
for (int lastPos = a.length - 1; lastPos >= 0; lastPos--) {
for (int index = 0; index <= lastPos - 1; index++) {
if (a[index] > a[index + 1]) {
int temp = a[index];
a[index] = a[index + 1];
a[index + 1] = temp;
}
}
}
}
Remove duplicates while merging them.
public static int[] mergeArrays(int[] a, int[] b)
{
int a_size = a.length;
int b_size = b.length;
int[] c = new int[a_size + b_size];
int i = 0 , j = 0, x = -1;
for(; i < a_size && j < b_size;)
{
if(a[i] <= b[j])
{
c[++x] = a[i];
++i;
}
else
{
if(c[x] != b[j])
{
c[++x] = b[j]; // avoid duplicates
}
++j;
}
}
--i; --j;
while(++i < a_size)
{
c[++x] = a[i];
}
while(++j < b_size)
{
c[++x] = b[j];
}
return c;
}
Count unique values in newly merged array.
static int uniqueValues(int[] c) {
int uniqueValues = c.length;
for (int i = 0; i < c.length; i++) {
while (c[i] == c[i + 1] && i + 1 < c.length && c[i] > c[i+1] ) {
i++;
uniqueValues--;
}
}
return unique;
}
Reestablish the merged array with unique value count i.e. delete the remaining elements after count finishes.
sortArray(a);
sortArray(b);
int[] c = mergeArrays(a, b);
c = deleteDuplicateEntries(c, uniqueValues(c));
Let me know if you find it useful.

Let the libraries work for you:
(Note, that outside of jshell, you have to terminate each non-empty line with ";")
int[] ai = {0, 1, 15, 16, 27, 84, 49, 4, 5 }
int[] bi = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 4, 5 }
List <Integer> li = new ArrayList<> ()
Arrays.stream (ai).forEach (i -> li.add (new Integer (i)))
Arrays.stream (bi).forEach (i -> li.add (new Integer (i)))
Collections.sort (li)
int [] res = li.stream().distinct().mapToInt (i -> i.intValue()).toArray()
result in jshell:
for (int i: res) System.out.printf (" %d", i);
0 1 2 3 4 5 6 7 8 9 10 11 12 15 16 27 49 84

Related

merging 3 sorted arrays

public class array12 {
static void merge_sort(int A[], int start, int end) {
if (end - start > 1) {
int middle1 = (2 * start + end + 1) / 3 - 1;
int middle2 = 2 * middle1 - start + 1;
merge_sort(A, start, middle1);
merge_sort(A, middle1 + 1, middle2);
merge_sort(A, middle2 + 1, end);
merge(A, start, middle1, middle2, end);
}
}
static void merge(int[] x, int start, int middle1, int middle2, int end) {
int n1 = middle1 - start + 1;
int n2 = middle2 - middle1;
int n3 = end - middle2;
int left[] = new int[n1]; // defining and initialising three arrays .
int mid[] = new int[n2];
int right[] = new int[n3];
for (int i = 0; i < left.length; i++) {
left[i] = x[i + start];
}
for (int i = 0; i < mid.length; i++) {
mid[i] = x[i + middle1 + 1];
}
for (int i = 0; i < right.length; i++) {
right[i] = x[i + middle2 + 1];
}
int i = 0;
int j = 0;
int k = 0;
int c = start;
// finding minimum element from the three arrays .
while (i < n1 && j < n2 && k < n3) {
if (left[i] <= mid[j] && left[i] <= right[k]) {
x[c] = left[i];
i++;
c++;
} else if (mid[j] <= left[i] && mid[j] <= right[k]) {
x[c] = mid[j];
j++;
c++;
} else {
x[c] = right[k];
k++;
c++;
}
}
// now only two arrays are left to be compared
while (i < n1 && j < n2) {
if (left[i] <= mid[j]) {
x[c] = left[i];
i++;
c++;
} else {
x[c] = mid[j];
j++;
c++;
}
}
while (j < n2 && k < n3) {
if (mid[j] <= right[k]) {
x[c] = mid[j];
j++;
c++;
} else {
x[c] = right[k];
k++;
c++;
}
}
while (i < n1 && k < n3) {
if (left[i] <= right[k]) {
x[c] = left[i];
i++;
c++;
} else {
x[c] = right[k];
k++;
c++;
}
}
// now only single array is left out of left[] , mid[] and right[].
while (i < n1) {
x[c] = left[i];
i++;
c++;
}
while (j < n2) {
x[c] = mid[j];
j++;
c++;
}
while (k < n3) {
x[c] = right[k];
k++;
c++;
}
System.out.println("");
// printing array elements after every merge operation .
for (int e = 0; e < x.length; e++) {
System.out.print(x[e] + " ");
}
}
public static void main(String[] args) {
int[] x = new int[9];
for (int i = 0; i < x.length; i++) {
x[i] = x.length - i;
}
System.out.println("initial array is : ");
for (int i = 0; i < x.length; i++) {
System.out.print(x[i] + " ");
}
System.out.println("");
merge_sort(x, 0, x.length - 1);
System.out.println("");
System.out.println("");
System.out.println(" sorted array is : ");
for (int i = 0; i < x.length; i++) {
System.out.print(x[i] + " ");
}
}
}
I am trying to merge 3 sorted arrays . I have been able to develop code for array size equal to power of 3 . I am unable to implement it with some other array size . I have tried to change values of middle1 and middle2 but am experiencing serious trouble . Setting their values is the main concern . Merging step is quite simple and is not causing problems .
What changes are required in my code so that it may work for any array size ? Can it be implemented using this approach ? I dont want size of any of the three arrays , left[] , mid[] and right[] to be zero at any time .
Please help .
Here's a similar answer to YCF_L's, but simplified (still uses Java 8):
public static int[] sortMultipleArrays(int[]... arrays) {
return Arrays.stream(arrays)
.flatMapToInt(Arrays::stream)
.sorted()
.toArray();
}
Output:
[1, 2, 3, 5, 6, 7, 9, 10, 12, 13, 17, 20, 21, 24]
I don't follow your merge code. It seems overly complicated.
Here is a method for merging an unlimited number of sorted arrays, each a varying size.
private static int[] mergeSortedArrays(int[]... arrays) {
int totalLen = 0;
for (int[] arr : arrays)
totalLen += arr.length;
int[] idx = new int[arrays.length];
int[] merged = new int[totalLen];
for (int i = 0; i < totalLen; i++) {
int min = 0, minJ = -1;
for (int j = 0; j < arrays.length; j++)
if (idx[j] < arrays[j].length)
if (minJ == -1 || min > arrays[j][idx[j]]) {
min = arrays[j][idx[j]];
minJ = j;
}
merged[i] = min;
idx[minJ]++;
}
return merged;
}
Test
int[] a = { 3, 5, 9, 13, 17, 21 };
int[] b = { 2, 10, 20 };
int[] c = { 1, 7, 12, 24 };
int[] d = { 6 };
int[] merged = mergeSortedArrays(a, b, c, d);
System.out.println(Arrays.toString(merged));
Output
[1, 2, 3, 5, 6, 7, 9, 10, 12, 13, 17, 20, 21, 24]
If using class "Integer" instead of primitive int is not a problem you can use this, basically first do the merge and after sort them: you can do the call Arrays.sort even in the same method and call it mergeAndSort, if you want...
import java.util.Arrays;
public class Main {
public static Integer[] merge(Integer[]... arrays) {
int count = 0;
for (Integer[] array : arrays) {
count += array.length;
}
Integer[] mergedArray = (Integer[]) java.lang.reflect.Array.newInstance(arrays[0][0].getClass(), count);
int start = 0;
for (Integer[] array : arrays) {
System.arraycopy(array, 0, mergedArray, start, array.length);
start += array.length;
}
return mergedArray;
}
public static void main(String[] args) {
Integer[] array1 = {3, 5, 6, 7, 78, 100};
Integer[] array2 = {5, 6, 7, 8, 9};
Integer[] array3 = {2, 6, 7};
Integer[] merged1 = merge(array1, array2);
Arrays.sort(merged1);
Integer[] merged2 = merge(array1, array2, array3);
Arrays.sort(merged2);
printArray(merged1);
printArray(merged2);
}
public static void printArray(Integer[] x) {
System.out.println("--ToString--");
for (Integer var : x) {
System.out.println(var);
}
System.out.println("----");
}
}

How to find number of tuples whose sum is equal or less than a given number?

I'm designing an algorithm to find the number of tuples whose sum is equal or less than a given number. I know other ways of solving it using LinkedList, so, not looking for that solution. I just want to traverse through the array and count the possible matches that satisfy the relation. I come up so far,
public static int numberOfPairs(int[] a, int k ){
int len = a.length;
if (len == 0){
return -1;
}
Arrays.sort(a);
int count = 0, left = 0, right = len -1;
while( left < right ){
if ( a[left] + a[right] <= k ){
// System.out.println(a[left] + "\t" + a[right]);
count++;
/*may be the same numbers will also satisfy the relation*/
if ( a[left] + a[left+1] <= k) {
count ++;
// System.out.println(a[left] + "\t"+a[left+1]);
}
/*now, use iteration to traverse the same elements*/
while (a[left] == a[left+1] && left < len-1 ){
left++;
}
/*may be the same numbers will also satisfy the relation*/
if ( a[right] + a[right-1] <= k) {
count ++;
// System.out.println(a[right] +"\t"+ a[right-1]);
}
/*now, use iteration to traverse
the same elements*/
while ( a[right] == a[right-1] && right >1 ){
right-- ;
}
}
// traverse through the array
left++;
right--;
}
return count;
}
This is not providing the correct solution, say, if I pass array and number as following,
int [] arr = { 3, 3, -1, 4, 2,5, 5, 1};
System.out.println(numberOfPairs(arr, 8));
The correct solution will be 15 pairs as following,
{
{-1,1}, {-1,2} , {3,-1}, {-1,4 }, {-1,5},
{2,1},{3,1 },{4,1}, { 5,1},
{3,2 },{4,2}, {2,5 },
{3,4 } , {3,5 },
{3,3}
}
How can I improve my code ? thanks.
Note: the other way I solve it using LinkedList is as following,
public static int numberOfPairs10(int[] arr, int sum){
/*1.can be the same values of i
2. can be the same valus of j for the same i*/
List<Integer> li = new ArrayList<Integer>();
List<Integer> lj;
int count = 0;
for ( int i =0; i < arr.length -1 ; i++){
if (li.contains(arr[i]) )
continue;
lj = new ArrayList<Integer>();
for (int j = i+1; j < arr.length; j++){
if (lj.contains(arr[j]))
continue;
// if ( arr[i]+ arr[j] <= sum){
if ( arr[i]+ arr[j] == sum){
count++;
lj.add(arr[j]);
}
}
li.add(arr[i]);
}
return count;
}
This is tested with just
int [] arr = { 3, 3, -1, 4, 2,5, 5, 1};
numberOfPairs(arr, 8);
and here is codes
public static int numberOfPairs(int[] a, int k ) {
int len = a.length;
int counter = 0;
boolean isCheckedLeft = false;
boolean isCheckedRight = false;
int i, j, h;
Arrays.sort(a);
for (i = 0; i < len; i++) {
isCheckedLeft = false;
for (j = i - 1; j >= 0; j--) {
if (a[i] == a[j]) {
isCheckedLeft = true;
break;
}
}
if (isCheckedLeft) {
continue;
}
for (j = i + 1; j < len; j++) {
isCheckedRight = false;
for (h = j - 1; h > i; h--) {
if (a[j] == a[h]) {
isCheckedRight = true;
break;
}
}
if (isCheckedRight) {
continue;
}
System.out.print("("+a[i]+", "+a[j]+") ");
if (a[i] + a[j] <= k) {
counter++;
}
}
}
return counter;
}
If you are not too worried about performance then you could just find all unique combinations and then filter according to your condition. For example, using Java 8 streams:
public int numberOfPairs(int[] values, int maxVal) {
return IntStream.range(0, values.length)
.flatMap(i1 -> IntStream.range(i1 + 1, values.length)
.map(i2 -> Arrays.asList(values[i1], values[i2])))
.distinct().filter(l -> l.stream().sum() <= maxVal).count();
}

ArrayIndexOutOfBoundExceptions on certain inputs when sorting elements of an array?

My task is to write a function that rearranges an array so that the odd numbers occur in the beginning of the array, from greatest to least, and the even numbers from least to greatest at the end. We are not allowed to use any other libraries except for the standard input and output streams.
The output works when the numbers are:
{-15, 450, 6, -9, 54}
But if I changed the elements to:
{-55, 45, 6, 11, 54}
There is an exception error. Here is my code:
public class ary1 {
public static void sort(int A[], int n) {
int tmp;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (A[0] % 2 == 0) //even
{
if (A[i] < A[j]) {
tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
} else {
if (A[i] > A[j]) {
tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
}
}
}
}
public static void showAray(int A[], int n) {
for (int i = 0; i < n; i++) {
System.out.println(A[i]);
}
}
public static void main(String args[]) {
int array1[] = {-55, 45, 6, 11, 54};
int odd = 0;
int even = 0;
for (int i = 0; i < array1.length; i++) {
if (array1[i] % 2 == 0) {
even++;
} else {
odd++;
}
}
int[] array2 = new int[even];
int[] array3 = new int[odd];
for (int i = 0, j = 0, k = 0; i < array1.length; i++) {
if (array1[i] % 2 == 0) {
array2[j++] = array1[i];
} else {
array3[k++] = array1[i];
}
}
System.out.println("Original array:\n");
showAray(array1, array1.length);
sort(array2, even);
sort(array3, odd);
for (int i = 1; i < array1.length; i++) {
if (i < odd) {
array1[i] = array3[i];
} else {
array1[i] = array2[(i + 1) - even];
}
}
System.out.println("\nAfter sorting:\n");
showAray(array1, array1.length);
}
}
I know there is a logical error here, but I can't figure out what exactly. Is there any way to change the logic to work with all integers? Thanks.
array1[i] = array2[(i + 1) - even];
EDIT - Here is the stacktrace.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
at ary.main(arytest.java:67)
Java Result: 1
Change this
array1[i] = array2[(i + 1) - even];
to
array1[i] = array2[i - odd];
I guess this is what you want

How do I find the largest negative value in an array with both positive and negative values?

I need to return the greatest negative value, and if there are no negative values, I need to return zero.
Here is what I have:
public int greatestNegative(int[] list) {
for (int i = 0; i < list.length; i++) {
if (list[i] < 0)
negativeNumbers ++;
}
int j = list.length - 1;
while (j >= 0) {
if (list[j - negativeNumbers] < 0) {
list[j] = 0;
list[j - 1] = list[j - negativeNumbers];
negativeNumbers--;
j--;
}
else{
list[j] = list[j - negativeNumbers];
j--;
}
}
}
You just need to think of this problem as 2 steps:
Only consider negative values in list[].
In the loop within negative values, update current result if (result == 0) or (value > result).
Code:
public int greatestNegative(int[] list) {
int result = 0;
for (int i = 0; i < list.length; i++) {
if (list[i] < 0) {
if (result == 0 || list[i] > result) {
result = list[i];
}
}
}
return result;
}
Just go about finding the max number with an added condition.
public static int greatestNegative(int[] list) {
int max = Integer.MIN;
boolean set = false;
for (int i = 0; i < list.length; i++) {
if (list[i] < 0 && list[i] > max) {
max = arr[i];
set = true;
}
}
if (!set)
max = 0;
return max;
}
Here is the code which return the smallest negative number
public static int greatestNegative(int[] list) {
int negativeNumbers = 0;
for (int i = 0; i < list.length; i++) {
if (list[i] < 0 && list[i] < negativeNumbers)
negativeNumbers = list[i];
}
return negativeNumbers;
}
Input : 1, 2, -3, 5, 0, -6
Output : -6
Input : 1, 2, 3, 5, 0, 6
Output : 0
If you need the greatest negative number then sort array thin search for first negative number
import java.util.Arrays;
class Main {
public static void main(String[] args) {
int arr[] = { 2, 4, 1, 7,2,-3,5,-20,-4,5,-9};
System.out.println(greatestNegative(arr));
}
private static int greatestNegative(int[] arr) {
Arrays.sort(arr);
for (int i = arr.length - 1; i >= 0; i--) {
if (isNegative (arr[i])) {
return arr[i];
}
}
return 0;
}
private static boolean isNegative (int i) {
return i < 0;
}
}
Output : -3
Please check following code, which will
first calculate small number from array,
then check is it positive? if yes return 0 else return negative.
public static int greatestNegative(int[] list)
{
int negativeNumbers = Integer.MAX_VALUE;
for (int i = 0; i < list.length; i++) {
if (list[i] < negativeNumbers)
negativeNumbers = list[i];
}
if(negativeNumbers >=0)
return 0;
else
return negativeNumbers;
}
You have to try this....
public int greatestNegative(int[] list) {
int negNum = 0;
for(int i=0; i<list.length; i++) {
if(list[i] < negNum){
negNum = list[i];
}
}
return negNum;
}
public int largNegative(int[] list) {
int negNum = 0;
boolean foundNeg = false;
for(int i=0; i<list.length; i++) {
if(list[i] < negNum && !foundNeg){
foundNeg = true;
negNum = list[i];
} else if(foundNeg && list[i] < 0 && negNum < list[i]) {
negNum = list[i];
}
}
return negNum;
}
Start by setting your "maxNegative" value to 0. Then assign the first negative number you come across. After that, only assign negative numbers that are higher. If there are no negative numbers, then your "maxNegative" will still be zero.
public static void main(String[] args) {
int arr[] = {2, -1, 4, 1, 0, 7, 2, -3, 5, 9, -4, 5, -9};
int maxNegative = 0;
for (int i = 0; i < arr.length; i++) {
if (maxNegative == 0 && arr[i] < maxNegative) {
// Set the first negative number you come across
maxNegative = arr[i];
} else if (maxNegative < arr[i] && arr[i] < 0) {
// Set greater negative numbers
maxNegative = arr[i];
}
}
System.out.println(maxNegative);
}
Results:
-1
Java 8
Then there are streams, that allow you to do this with one line of code.
public static void main(String[] args) {
int arr[] = {2, 4, 1, 0, 7, 2, -3, 5, 9, -4, 5, -9};
int maxNegative = Arrays.stream(arr).filter(a -> a < 0).max().orElse(0);
System.out.println(maxNegative);
}
Results:
-3

Is there a simpler solution for Codingbat fix45?

I am trying to solve this CodingBat problem:
(This is a slightly harder version of the fix34 problem.) Return an array that contains exactly the same numbers as the given array, but rearranged so that every 4 is immediately followed by a 5. Do not move the 4's, but every other number may move. The array contains the same number of 4's and 5's, and every 4 has a number after it that is not a 4. In this version, 5's may appear anywhere in the original array.
fix45({5, 4, 9, 4, 9, 5}) → {9, 4, 5, 4, 5, 9}
fix45({1, 4, 1, 5}) → {1, 4, 5, 1}
fix45({1, 4, 1, 5, 5, 4, 1}) → {1, 4, 5, 1, 1, 4, 5}
I initially used a method which passed all of the sites tests, but I don't think it would work for longer arrays. The initial method used 2 loops and did not use a new array. I have created a solution which introduces a new array and a 3rd nested loop and I believe will work for all instances of the problem. However, the site states that the problems in this section can be solved with 2 loops, so I am wondering if there actually is a 2 loop solution that will work for anyinstance of the problem. Here is the question and my 3 loop solution:
public int[] fix45(int[] nums) {
int[] locations = {-1};
for (int i = 0; i < nums.length - 1; ++i) {
if (nums[i] == 4) {
JLoop:
for (int j = nums.length-1; j >= 0; --j) {
if (nums[j] == 5) {
for (int k = locations.length-1; k>=0 ; --k) {
if (locations[k] == j) {
continue JLoop;
}
}
nums[j] = nums[i + 1];
nums[i + 1] = 5;
locations[locations.length - 1] = i+1;
locations = java.util.Arrays.copyOf(locations,
locations.length + 1);
locations[locations.length-1] = -1;
break;
}
}
}
}
return nums;
}
Restarting the search for a suitable 5 from one end of the array every time a 4 is found seems wasteful. Part of the array has already been scanned and is known not to contain a 5 that can be moved. This is O(n) time and O(1) space.
public static int[] fix45(int[] nums) {
int j = 0;
for (int i = 0; i < nums.length - 1; ++i) {
if (nums[i] == 4 && nums[i + 1] != 5) {
/*
* Need to find the next movable 5 That means an element that is 5 and
* either is the first element or is preceded by anything other than 4
*/
while (nums[j] != 5 || (j != 0 && nums[j - 1] == 4)) {
j++;
}
nums[j] = nums[i + 1];
nums[i + 1] = 5;
}
}
return nums;
}
Using an extra array, here's a solution with "one loop" (loops without nested loops):
public int[] fix45(int[] nums) {
int[] otherValues = new int[nums.length];
for(int i = 0, c = 0; i < nums.length; i++)
if(nums[i] != 4 && nums[i] != 5)
otherValues[c++] = nums[i];
for(int i = 0, c = 0; i < nums.length; i++)
if(nums[i] == 4)
nums[++i] = 5;
else
nums[i] = otherValues[c++];
return nums;
}
We fix the fours, take out the non-fours and non-fives, and put the values all back in in order.
To improve the space usage (perhaps not by much), you can count the number of fours before you make the extra array.
public int[] fix45(int[] nums) {
int t=0;
for(int i=0; i< nums.length ; i++)
for(int j=0;j<nums.length ; j++)
if(nums[i]==5 && nums[j]==4)
{
t=nums[j+1];
nums[j+1]=nums[i];
nums[i]=t;
}
return nums;
}
The following method will run in O(n) time using O(n) space:
public int[] fix45(int[] nums) {
if (nums == null || nums.length <= 1) {
return nums;
}
// store all the 5s pos
int[] pos = new int[nums.length];
int j = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 5) {
pos[j++] = i;
}
}
j = 0;
for (int i = 0; i <= nums.length - 2; i++) {
if (nums[i] == 4 && nums[i + 1] != 5) {
if (j >= pos.length) {
System.err
.println("No more 5s: there are more 4 than 5 in the input array");
break;
}
// fix45 swapping
nums[pos[j++]] = nums[i + 1];
nums[i + 1] = 5;
}
}
return nums;
}
public int[] fix45(int[] nums) {
int idx4 = -1;
int idx5 = -1;
while (true) {
while (true) { // find a 4 without a 5 after it
idx4 = find(nums, 4, ++idx4);
if (idx4 == -1) // done if no more 4's
return nums;
if (nums[idx4+1] != 5)
break;
}
while (true) { // find a 5 without a 4 before it
idx5 = find(nums, 5, ++idx5);
if (idx5 == 0 || nums[idx5-1] != 4)
break;
}
nums[idx5] = nums[idx4+1]; // swap the 4 and 5
nums[idx4+1] = 5;
}
}
public int find(int[] nums, int num, int start) {
for (int i = start; i < nums.length; i++)
if (nums[i] == num)
return i;
return -1;
Fix after dansalmos remark:
public int[] fix45(int[] nums) {
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 4) {
if(nums[i+1] == 5) continue;
for( int j = 0; i < nums.length; j++){
if(nums[j] == 5 && (j==0 || nums[j-1] != 4)){
nums[j] = nums[i+1];
nums[i+1] = 5;
break;
}
}
}
}
return nums;
}
public int[] fix45(int[] nums) {
if (nums.length < 2) {
return nums;
}
int index = 0;
int index2 = 0;
int index3 = 0;
int[] only5 = fives(nums);
int[] after4 = new int[count4(nums)];
for (int a = 0; a < nums.length - 1; a++) {
if (nums[a] == 4) {
after4[index] = nums[a + 1];
index++;
nums[a + 1] = only5[index2];
index2++;
}
}
//This while loop gets the frst number that is not a 5 that is after a 4
while (nums[0] == 5) {
nums[0] = after4[index3];
index3++;
}
if (nums[nums.length - 2] != 4 && nums[nums.length - 1] == 5) {
nums[nums.length - 1] = after4[index3];
index3++;
}
for (int b = 1; b < nums.length; b++) {
if (nums[b] == 5 && nums[b - 1] != 4) {
nums[b] = after4[index3];
index3++;
}
}
return nums;
}
public int count4(int[] nums) {
int cnt = 0;
for (int e : nums) {
if (e == 4) {
cnt++;
}
}
return cnt;
}
public int[] fives(int[] nums) {
int index = 0;
int[] only5 = new int[count4(nums)];
for (int e : nums) {
if (e == 5) {
only5[index] = e;
index++;
}
}
return only5;
}
//long solution, scroll up
I realise this thread is years old, but I just wanted to add my solution:
public int[] fix45(int[] nums){
int notAFourOrFive = 0;
int[] ary = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 4) {
ary[i] = 4;
ary[i+1] = 5;
}
else if (nums[i] != 5) {
notAFourOrFive = nums[i];
}
}
for (int j = 0; j < ary.length; j++) {
if (ary[j] == 0) {
ary[j] = notAFourOrFive;
}
}
return ary;
}
Seeing as the amount of 4s and 5s are equal, it is safe to add them to a new array whenever a 4 is found. It is safe to use i+1 in this case, because a 4 never comes at the end of the array. It is also safe to set the 'other' number whenever a non-4 or non-5 is reached, because all the other numbers are the same, in each test.
public int[] fix45(int[] nums)
{
for(int i=0; i<nums.length; i++)
{
if(nums[i]==5)
{
for(int j=0; j<nums.length; j++)
if(nums[j]==4&&nums[j+1]!=5)
{
f(nums, i, j+1);
}
}
}
return nums;
}
///this "helper" function swaps 2 elements of the array
public void f(int []nums , int m, int n)
{
int t= nums[m];
nums[m] =nums[n];
nums[n] = t;
}
public int[] fix45(int[] nums) {
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 5 && i == 0 || nums[i] == 5 && nums[i - 1] != 4) {
int a5 = i;
for (int j = 0; j < nums.length; j++) {
if (nums[j] == 4 && nums[j + 1] != 5) {
int temp = nums[j + 1];
nums[j + 1] = 5;
nums[a5] = temp;
break;
}
}
}
}
return nums;
}
Here's a simple solution that works that I have found.
Simply create ArrayLists that track the 4's and 5's, and swap the values.
How's this for easy to understand?
public int[] fix45(int[] nums)
{
//Create a copy array to manipulate and eventually return.
int[] ret = nums;
//Create two ArrayLists that let us track for and five positions.
ArrayList<Integer> fourPositions = new ArrayList<Integer>();
ArrayList<Integer> fivePositions = new ArrayList<Integer>();
//Get the positions of fours and fives and add them to their respective ArrayLists.
for (int i = 0; i < ret.length; i++)
{
if (ret[i] == 4)
{
fourPositions.add(i);
}
if (ret[i] == 5)
{
fivePositions.add(i);
}
}
//Swap all of the places right after the fours with a respective number of the fives,
for (int i = 0; i < fourPositions.size(); i++)
{
int temp = ret[fourPositions.get(i) + 1];
ret[fourPositions.get(i) + 1] = ret[fivePositions.get(i)];
ret[fivePositions.get(i)] = temp;
}
//Return the array.
return ret;
}
This solution uses LinkedHashSet. I think O-notation for time is O(n), and for space is also O(n).
public int[] fix45(int[] nums) {
Set<Integer> ind4 = new LinkedHashSet<>();
Set<Integer> ind5 = new LinkedHashSet<>();
//Store positions for all fours and fives except those fives
//that immediately follow number four.
for (int i = 0; i < nums.length; ++i) {
if (nums[i] == 4){
ind4.add(i);
if (i + 1 < nums.length && nums[i + 1] == 5){
i++;
}
}else if (nums[i] == 5){
ind5.add(i);
}
}
Iterator<Integer> iter5ind = ind5.iterator();
for (Integer i : ind4){
if (i + 1 > nums.length || !iter5ind.hasNext()) break;
if (nums[i + 1] == 5){
continue;
}
int j = iter5ind.next();
int tmp = nums[i + 1];
nums[i + 1] = nums[j];
nums[j] = tmp;
}
return nums;
}
import java.util.Arrays;
public class Fix45 {
public static void main(String[] args) {
assertArrays(new int[]{9, 4, 5, 4, 5, 9}, new int[]{5, 4, 9, 4, 9, 5});
assertArrays(new int[]{1, 4, 5, 4, 5}, new int[]{5, 4, 5, 4, 1});
assertArrays(new int[]{1, 1, 4, 5, 4, 5}, new int[]{5, 5, 4, 1, 4, 1});
assertArrays(new int[]{4, 5, 4, 5, 1}, new int[]{4, 5, 4, 1, 5});
assertArrays(new int[]{4, 5, 4, 5, 2}, new int[]{4, 2, 4, 5, 5});
}
public static int[] fix45(int[] nums) {
for (int i = 0; i < nums.length; i++) {
if(nums[i] == 4 && nums[i + 1] != 5){
int location = i + 1;
for (int j = 0; j < nums.length; j++) {
if(nums[j] == 4 && nums[j + 1] == 5){
j++;
continue;
}
if (nums[j] == 5) {
int temp = nums[j];
nums[j] = nums[location];
nums[location] = temp;
}
}
}
}
return nums;
}
private static void assertArrays(int[] expected, int[] input) {
int[] actual = fix45(input);
System.out.println(Arrays.toString(actual));
boolean status = Arrays.equals(expected, actual);
System.out.println(status);
}
}
There are so many complicated code in here. I think we simplified like this :
public int[] fix45(int[] nums) {
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 4) {
for (int j = 0; j < nums.length; j++) {
if (nums[j] == 5) {
if (j > 0 && nums[j - 1] != 4) {
int tmp = nums[i + 1];
nums[i + 1] = 5;
nums[j] = tmp;
} else if (j == 0) {
int tmp = nums[i + 1];
nums[i + 1] = 5;
nums[j] = tmp;
}
}
}
}
}
return nums;
}
I just want to add My Solution, as far I tested on CodingBat and passed all test and without use of 2 for loops
public int[] fix45(int[] nums) {
if (nums.length == 0 || nums.length == 1 || nums.length == 2) {
return nums;
}
int indexof4 = 0, indexof5 = 0;
int indexToWorkonForRplcmnt = -1;
while (indexof4 < nums.length && indexof5 < nums.length) {
if ((indexof4 + 1) < nums.length && nums[indexof4] == 4 && nums[indexof4 + 1] != 5) {
indexToWorkonForRplcmnt = indexof4 + 1;
// System.out.println("IndexOf4:"+indexToWorkonForRplcmnt);
} else {
indexof4++;
}
if ((indexof5) < nums.length && nums[indexof5] == 5) {
if (indexof5 == 0 && nums[indexof5] == 5) {
// System.out.println("IndexOf5:"+indexof5);
} else if (nums[indexof5 - 1] != 4 && nums[indexof5] == 5) {
// System.out.println("IndexOf5:"+indexof5);
} else {
indexof5++;
}
} else {
indexof5++;
}
if (indexToWorkonForRplcmnt != -1 && (indexof5) < nums.length && nums[indexof5] == 5) {
System.out.println("IndexOf4:" + indexToWorkonForRplcmnt);
System.out.println("IndexOf5:" + indexof5);
int temp = nums[indexToWorkonForRplcmnt];
nums[indexToWorkonForRplcmnt] = nums[indexof5];
nums[indexof5] = temp;
indexToWorkonForRplcmnt = -1;
indexof4++;
indexof5++;
}
}
return nums;
}
Here is simple answer :)
public int[] fix45(int[] nums) {
int p5=0;//tracker for 5's
for(int i=0;i<nums.length;i++){
if(nums[i] == 4){// got a 4
for(int j = p5 ;j<nums.length;j++){
//finding a 5 for that 4 at nums[i]
if(nums[j] == 5 && ( (j > 0 && nums[j-1]!=4 ) || (j==0) )){
// found 5 and checking if it is not preceded by a 4
//swap if not preceded by a 4
int temp = nums[i+1];
nums[i+1] = nums[j];
nums[j] = temp;
p5 = j;//set the tracker to where we found 5 for nums[i]
break;//break out of loop
}
}
}
}
return nums;
}
It can be done in one while loop also !
public int[] fix45(int[] nums) {
int start = 0;
int end = nums.length-1;
boolean is4 = false;
boolean is5 = false;
while( start < nums.length ){
if(nums[start] == 4 && nums[start+1]!=5){
is4 = true;
}
if(nums[end] == 5 && (end == 0 || (end-1>=0 && nums[end-1]!=4))){
is5 = true;
}
if(is4 && is5){
int temp = nums[start+1];
nums[start+1] = nums[end];
nums[end] = temp;
is4 = false;
is5 = false;
end = nums.length-1;
}
if(is4){
end--;
continue;
}
start++;
}
return nums;
}
public int[] fix45(int[] nums) {
int[] array = new int[nums.length];
int temp = 0;
for (int i = 0; i < array.length; i++) {
if (nums[i]==4) {
array[i] = 4;
array[i+1]= 5;
}
}
for (int i = 0; i < array.length; i++) {
if (nums[i]!=4 && nums[i]!=5) {
temp = nums[i];
}
for (int j = 0; j < array.length; j++) {
if (array[j]==0) {
array[j]=temp;
}
}
}
return array;
}
Simplest probably:
for(int i = 0; i < nums.length; i++){
if(nums[i] == 5 && i == 0 || nums[i] == 5 && nums[i-1] != 4){
int pos5 = i;
for(int j = 0; j < nums.length; j++){
if(nums[j] == 4 && nums[j+1] != 5){
int temp = nums[j+1];
nums[j+1] = 5;
nums[pos5] = temp;
break;
}
}
}
}
return nums;

Categories