I have a task, to remove duplicates in array, what by "remove" means to shift elements down by 1, and making the last element equal to 0,
so if I have int[] array = {1, 1, 2, 2, 3, 2}; output should be like:
1, 2, 3, 0, 0, 0
I tried this logic:
public class ArrayDuplicates {
public static void main(String[] args) {
int[] array = {1, 1, 2, 2, 3, 2};
System.out.println(Arrays.toString(deleteArrayDuplicates(array)));
}
public static int[] deleteArrayDuplicates(int[] array) {
for (int i = 0; i < array.length; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[i] == array[j]) { //this is for comparing elements
for (; i > 0; i--) {
array[j + 1] = array[j]; //this is for shifting
}
array[array.length - 1] = 0; //making last element equal to "0"
}
}
}
return array;
}
}
But it doesn't work.. Is anyone familiar with a right solution?
I appreciate your assistance and attention very much.
Your Code:
In short, the approach you have chosen calls for a third loop variable, k, to represent the index that is currently being shifted left by 1 position.
i - the current unique item's position
j - the current position being tested for equality with unique item at i
k - the current position being shifted left due to erasure at j
Suggestion:
A more efficient approach would be to eliminate the repetitive left shifting which occurs each time a duplicate is found and instead keep track of an offset based on the number of duplicates found:
private static int[] deleteArrayDuplicates(int[] array) {
int dupes = 0; // total duplicates
// i - the current unique item's position
for (int i = 0; i < array.length - 1 - dupes; i++) {
int idupes = 0; // duplicates for current value of i
// j - the current position being tested for equality with unique item at i
for (int j = i + 1; j < array.length - dupes; j++) {
if (array[i] == array[j]) {
idupes++;
dupes++;
} else if(idupes > 0){
array[j-idupes] = array[j];
}
}
}
if(dupes > 0) {
Arrays.fill(array, array.length-dupes, array.length, 0);
}
return array;
}
This has similar complexity to the answer posted by dbl, although it should be slightly faster due to eliminating some extra loops at the end. Another advantage is that this code doesn't rely on any assumptions that the input should not contain zeroes, unlike that answer.
#artshakhov:
Here is my approach, which is pretty much close enough to what you've found but using a bit fewer operations...
private static int[] deleteArrayDuplicates(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
if (array[i] == NEUTRAL) continue; //if zero is a valid input value then don't waste time with it
int idx = i + 1; //no need for third cycle, just use memorization for current shifting index.
for (int j = i + 1; j < array.length; j++) {
if (array[i] == array[j]) {
array[j] = NEUTRAL;
} else {
array[idx++] = array[j];
}
}
}
return array;
}
I just wrote the following code to answer your question. I tested it and I am getting the output you expected. If there are any special cases I may have missed, I apologize but it seemed to work for a variety of inputs including yours.
The idea behind is that we will be using a hash map to keep track if we have already seen a particular element in our array as we are looping through the array. If the map already contains that element- meaning we have already seen that element in our array- we just keep looping. However, if it is our first time seeing that element, we will update the element at the index where j is pointing to the element at the index where i is pointing to and then increment j.
So basically through the j pointer, we are able to move all the distinct elements to the front of the array while also making sure it is in the same order as it is in our input array.
Now after the first loop, our j pointer points to the first repeating element in our array. We can just set i to j and loop through the rest of the array, making them zero.
The time complexity for this algorithm is O(N). The space complexity is O(N) because of the hash table. There is probably a way to do this in O(N) time, O(1) space.
public static int[] deleteArrayDuplicates(int[] array) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
int j = 0;
for (int i = 0; i < array.length; i++) {
if (map.containsKey(array[i])) {
continue;
}
else {
map.put(array[i],1);
array[j] = array[i];
j++;
}
}
for (int i = j; i < array.length; i++) {
array[i] = 0;
}
return array;
}
Let me know if you have additional questions.
Spent a couple of hours trying to find a solution for my own, and created something like this:
public static int[] deleteArrayDuplicates(int[] array) {
for (int i = 0; i < array.length; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[j] == array[i]) { //this is for comparing elements
int tempIndex = j;
while (tempIndex + 1 < array.length) {
array[tempIndex] = array[tempIndex + 1]; //this is for shifting elements down/left by "1"
array[array.length - 1] = 0; //making last element equal to "0"
tempIndex++;
}
}
}
}
return array;
}
Code is without any API-helpers, but seems like is working now.
Try this:
public static void main(String[] args)
{
int a[]={1,1,1,2,3,4,5};
int b[]=new int[a.length];
int top=0;
for( int i : a )
{
int count=0;
for(int j=0;j<top;j++)
{
if(i == b[j])
count+=1;
}
if(count==0)
{
b[top]=i;
top+=1;
}
}
for(int i=0 ; i < b.length ; i++ )
System.out.println( b[i] );
}
Explanation:
Create an another array ( b ) of same size of the given array.Now just include only the unique elements in the array b. Add the elements of array a to array b only if that element is not present in b.
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class StackOverFlow {
public static void main(String[] args) {
int[] array = {1, 1, 2, 2, 3, 2};
Set<Integer> set=new HashSet<>();
for (int anArray : array) {
set.add(anArray);
}
int[] a=new int[array.length];
int i=0;
for (Integer s:set) {
a[i]=s;
i++;
}
System.out.println(Arrays.toString(a));
}
}
Hope this simple one may help you.
Make use of Set which doesn't allow duplicates.
We can use ARRAYLIST and Java-8 Streams features to get the output.
public static int[] deleteArrayDuplicates(int[] array) {
List<Integer> list = new ArrayList(Arrays.stream(array).boxed().distinct().collect(Collectors.toList()));
for (int i = 0; i < array.length; i++) {
if (i < list.size()) {
array[i] = list.get(i);
} else {
array[i] = 0;
}
}
return array;
}
OUTPUT
[1, 2, 3, 0, 0, 0]
Related
starting Java coder here. I was wondering how to change my code so it would sort array by always swapping the biggest value to first. Sample output should be:
[3, 1, 2, 0] [3, 2, 1, 0].
public class Sorting {
static void biggest(int[] arr, int start, int end) {
for (start = 0; start < arr.length; start++) {
for (end = start + 1; end < arr.length; end++) {
if (arr[start] < arr[end]) {
int temp = arr[end];
arr[end] = arr[start];
arr[start] = temp;
System.out.println(Arrays.toString(arr));
}
}
}
}
public static void main(String[] args) {
int[] arr = {0, 1, 2, 3};
int temp = 0;
for (int i = 0; i < 4; ++i) {
biggest(arr, temp, 4 - 1);
for (int j = 0; j < 4; ++j) {
}
++temp;
}
}
Thanks in advance,
- Em
If you just want the sort to be successful, I suggest taking advantage of Java's built in sort method then reversing the list as suggested here:
Arrays.sort(arr);
ArrayUtils.reverse(arr);
But it sounds like the spirit of your question is to modify your code for this purpose. Here's the solution I came up with:
import java.util.Arrays;
public class Sorting {
static void biggest(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(Arrays.toString(arr));
int max, maxAt = i;
for (int j = i; j < arr.length; j++) {
maxAt = arr[j] > arr[maxAt] ? j : maxAt;
}
max = arr[maxAt];
if (arr[i] < max) {
arr[maxAt] = arr[i];
arr[i] = max;
}
}
}
public static void main(String[] args) {
int[] arr = {0, 1, 2, 3};
biggest(arr);
System.out.println(Arrays.toString(arr));
}
}
First off, you had a lot of extra code that you didn't need. It's a bad idea to have a loop in your main. That should be handled by the helper function. You also had a lot of redundant declarations (like start and end). You were on the right track with your helper function, but because of your main loop your time complexity was 0(n²). Eliminating that allows mine to be O(logn). Complexity aside, the key difference in terms of logic is here in your internal loop:
for (end = start + 1; end < arr.length; end++) {
if (arr[start] < arr[end]) {
int temp = arr[end];
arr[end] = arr[start];
arr[start] = temp;
In this loop you're switching the array entry with the first one you find that's bigger. This will result in unwanted early switches (like 1 & 2). Here is my solution:
for (int j = i; j < arr.length; j++) {
maxAt = arr[j] > arr[maxAt] ? j : maxAt;
}
max = arr[maxAt];
if (arr[i] < max) {
arr[maxAt] = arr[i];
arr[i] = max;
}
The key difference is that I search for the maximum value entry following the one we're swapping. That way as we proceed through the array we will always bring forward the next biggest.
Best of luck learning Java I hope this helps!
I am trying to write a method which takes an array of ints and then rearranges the numbers in the array so that the negative numbers come first. The array does not need to be sorted in any way. The only requirement is that the solution has to be linear and it does not use an extra array.
Input:
{1, -5, 6, -4, 8, 9, 4, -2}
Output:
{-5, -2, -4, 8, 9, 1, 4, 6}
Now as a noob in Java and programming in general I am not 100% sure on what is considered a linear solution, but my guess is that it has to be a solution that does not use a loop within a loop.
I currently have an awful solution that I know doesn't work (and I also understand why) but I can't seem to think of any other solution. This task would be easy if I were allowed to use a loop within a loop or an additional array but I am not allowed to.
My code:
public static void separateArray(int[] numbers) {
int i = 0;
int j = numbers.length-1;
while(i<j){
if(numbers[i] > 0){
int temp;
temp = numbers[j];
numbers[j] = numbers[i];
numbers[i] = temp;
System.out.println(Arrays.toString(numbers));
}
i++;
j--;
}
}
You only need to change one line to get it (mostly) working. But you need to change two lines to correctly handle zeroes in the input. I have highlighted both of these minimally necessary changes with "FIXME" comments below:
public static void separateArray(int[] numbers) {
int i = 0;
int j = numbers.length-1;
while(i<j){
if(numbers[i] > 0){ // FIXME: zero is not a "negative number"
int temp;
temp = numbers[j];
numbers[j] = numbers[i];
numbers[i] = temp;
}
i++; // FIXME: only advance left side if (numbers[i] < 0)
j--; // FIXME: only decrease right side if (numbers[j] >= 0)
}
}
Your approach with two pointers, i and j is a good start.
Think about the loop invariant that you immediately set up (vacuously):
Elements in the range 0 (inclusive) to i (exclusive) are negative;
Elements in the range j (exclusive) to numbers.length (exclusive) are non-negative.
Now, you want to be able to move i and j together until they pass each other, preserving the loop invariant:
If i < numbers.length and numbers[i] < 0, you can increase i by 1;
If j >= 0 and numbers[j] >= 0, you can decrease j by 1;
If i < numbers.length and j >= 0, then numbers[i] >= 0 and numbers[j] < 0. Swap them around.
If you keep applying this strategy until i == j + 1, then you end up with the desired situation, that:
numbers[a] < 0 for a in [0..i)
numbers[a] >= 0 for a in (j..numbers.length), also written as numbers[a] >= 0 for a in (i-1..numbers.length), also written as numbers[a] >= 0 for a in [i..numbers.length).
So, you've partitioned the array so that all negative numbers are on the left of the i-th element, and all non-negative numbers are at or to the right of the i-th element.
Hopefully, this algorithm should be easy to follow, and thus to implement.
A linear solution is a solution with a run-time complexity Big-Oh(n) also noted as O(n), in other words, you have to loop through the whole array only once. To sort in linear time you can try one of the following sorting algorithms:
Pigeonhole sort
Counting sort
Radix sort
Your code works only if all the negative numbers are located in the right half side and the positives in the left half. For example, your code swaps 6 with 9 which both are positives. So, it depends on the order of your the array elements. As scottb said, try do it by your hands first then you will notice where you did wrong. Moreover, print your array out of the while
//Move positive number left and negative number right side
public class ArrangeArray {
public static void main(String[] args) {
int[] arr = { -2, 1, -3, 4, -1, 2, 1, -5, 4 };
for (int i = 0; i < arr.length; i++) {
System.out.print(" " + arr[i]);
}
int temp = 0;
for (int i = 0; i < arr.length; i++) {
// even
if (arr[i] < 0) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] > 0) {
arr[j] = arr[i] + arr[j];
arr[i] = arr[j] - arr[i];
arr[j] = arr[j] - arr[i];
break;
}
}
}
}
System.out.println("");
for (int i = 0; i < arr.length; i++) {
System.out.print(" " + arr[i]);
}
}
}
There is simple program it will help you. In this program i have take temp array and perform number of item iteration. In that i have start fill positive value from right and negative from left.
public static void rearrangePositiveAndNegativeValues() {
int[] a = {10,-2,-5,5,-8};
int[] b = new int[a.length];
int i = 0, j = a.length -1;
for (int k = 0; k < a.length ; k++) {
if (a[k] > 0) {
b[j--] = a[k];
} else {
b[i++] = a[k];
}
}
System.out.println("Rearranged Values : ");
printArray(b);
}
package ArrayProgramming;
import java.util.ArrayList;
import java.util.Arrays;
public class RearrangingpossitiveNegative {
public static void main(String[] args) {
int[] arr= {-1,3,4,5,-6,6,8,9,-4};
ArrayList<Integer> al = new ArrayList<Integer>();
for (int i=0;i<arr.length;i++) {
if(arr[i]>0) {
al.add(arr[i]);
}
}
for (int i=arr.length-1;i>=0;i--) {
if(arr[i]<0) {
al.add(arr[i]);
}
}
System.out.println(al);
}
}
from array import *
size = int(input())
arr = (array('i' , list(map(int, input().split()))))
negarr = array('i')
posarr = array('i')
for i in arr:
if i>=0:
posarr.append(i)
else:
negarr.append(i)
print(*(negarr+posarr))
we can also do it by creating two new arrays and adding elements into them as per given condition. later joining both of them to produce final result.
Merge Sort is not a new algorithm and there are solutions available to it. I was trying to write my own code but it has some logical errors.
Any insights about what i am doing wrong?
public class MergeSort {
public static void main(String[] args) {
int[] array = {5,4,8,3,7,10};
mergeSort(array);
System.out.println("Sorted array: \n");
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
public static void mergeSort(int[] array) {
if (array.length > 1) {
int[] firstHalf = new int[array.length / 2];
System.arraycopy(array, 0, firstHalf, 0, array.length / 2);
mergeSort(firstHalf);
int[] secondHalf = new int[array.length - array.length/2];
System.arraycopy(array, array.length / 2, secondHalf, 0, array.length - array.length/2);
mergeSort(secondHalf);
merge(firstHalf, secondHalf, array);
}
}
public static void merge(int[] firstHalf, int[] secondHalf, int[] array) {
int i = 0;
int j = 0;
int k = 0;
for (k = 0; k < array.length; k++) {
for (i = 0, j = 0; i < firstHalf.length && j < secondHalf.length; i++, j++) {
if (firstHalf[i] < secondHalf[j]) {
array[k] = firstHalf[i];
i++;
} else if (secondHalf[j] < firstHalf[i]) {
array[k] = secondHalf[j];
j++;
}
}
}
}
}
There are multiple issues with your merge() function:
The most obvious one, merge() does not need a nested loop. Note
that you repeatidly overriding values of array[k] with new
values.
Another issue is at each iteration of the inner loop you increase one
of i or j twice.
In addition, there are some elements that you never touch, the biggest elements in one of the arrays (consider if you have an already sorted array, so you have left=[1,2,3] right=[4,5,6]. After you figure out you need to increase only one iterator, and not both, you will still have an issue that you never touch the elements 2,3 from left).
My tip: Try to follow a step by step pseudo code when implementing the algorithm for the first time. If you feel you got it, erase it and try writing it again, without the reference.
So I know how to get the size of a combination - factorial of the size of the array (in my case) over the size of the subset of that array wanted. The issue I'm having is getting the combinations. I've read through most of the questions so far here on stackoverflow and have come up with nothing. I think the issue I'm finding is that I want to add together the elements in the combitorial subsets created. All together this should be done recursively
So to clarify:
int[] array = {1,2,3,4,5};
the subset would be the size of say 2 and combinations would be
{1,2},{1,3},{1,4},{1,5},{2,3},{2,4},{2,5},{3,4},{3,5},{4,5}
from this data I want to see if the subset say... equals 6, then the answers would be:
{1,5} and {2,4} leaving me with an array of {1,5,2,4}
so far I have this:
public static int[] subset(int[] array, int n, int sum){
// n = size of subsets
// sum = what the sum of the ints in the subsets should be
int count = 0; // used to count values in array later
int[] temp = new temp[array.length]; // will be array returned
if(array.length < n){
return false;
}
for (int i = 1; i < array.length; i++) {
for (int j = 0; j < n; j++) {
int[] subset = new int[n];
System.arraycopy(array, 1, temp, 0, array.length - 1); // should be array moved forward to get new combinations
**// unable to figure how how to compute subsets of the size using recursion so far have something along these lines**
subset[i] = array[i];
subset[i+1] = array[i+1];
for (int k = 0; k < n; k++ ) {
count += subset[k];
}
**end of what I had **
if (j == n && count == sum) {
temp[i] = array[i];
temp[i+1] = array[i+1];
}
}
} subset(temp, n, goal);
return temp;
}
How should I go about computing the possible combinations of subsets available?
I hope you will love me. Only thing you have to do is to merge results in one array, but it checks all possibilities (try to run the program and look at output) :) :
public static void main(String[] args) {
int[] array = {1, 2, 3, 4, 5};
int n = 2;
subset(array, n, 6, 0, new int[n], 0);
}
public static int[] subset(int[] array, int n, int sum, int count, int[] subarray, int pos) {
subarray[count] = array[pos];
count++;
//If I have enough numbers in my subarray, I can check, if it is equal to my sum
if (count == n) {
//If it is equal, I found subarray I was looking for
if (addArrayInt(subarray) == sum) {
return subarray;
} else {
return null;
}
}
for (int i = pos + 1; i < array.length; i++) {
int[] res = subset(array, n, sum, count, subarray.clone(), i);
if (res != null) {
//Good result returned, so I print it, here you should merge it
System.out.println(Arrays.toString(res));
}
}
if ((count == 1) && (pos < array.length - 1)) {
subset(array, n, sum, 0, new int[n], pos + 1);
}
//Here you should return your merged result, if you find any or null, if you do not
return null;
}
public static int addArrayInt(int[] array) {
int res = 0;
for (int i = 0; i < array.length; i++) {
res += array[i];
}
return res;
}
You should think about how this problem would be done with loops.
for (int i = 0; i < array.length - 1; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[i] + array[j] == sum) {
//Add the values to the array
}
}
}
Simply convert this to a recursive code.
The best way I can think to do this would be to have each recursive call run on a subset of the original array. Note that you don't need to create a new array to do this as you are doing in your code example. Just have a reference in each call to the new index in the array. So your constructor might look like this:
public static int[] subset(int[] array, int ind, int sum)
where array is the array, ind is the new starting index and sum is the sum you are trying to find
I am working on a java assignment where I need to delete an integer element in an array and shift the below elements up on space to keep them in order. The array is currently random integers in descending order. I am not allowed to use array.copy because I will need to collect array usage information as part of the assignment. I have tried a ton of different ways of doing this but cannot seem to get it working.
public static void deletionArray(int anArray[], int positionToDelete) {
for (int j = anArray[positionToDelete] - 1; j < anArray.length; j++) {
System.out.println("j is " + j);
anArray[j] = anArray[j + 1];
}
displayArray(anArray);
}
You're iterating until anArray.length (exclusive), but inside the loop, you're accessing anArray[j + 1], which will thus be equal to anArray[anArray.length] at the last iteration, which will cause an ArrayIndexOutOfBoundsException.
Iterate until anArray.length - 1 (exclusive), and decide what should be stored in the last element of the array instead of its previous value.
You're also starting at anArray[positionToDelete] - 1, instead of starting at positionToDelete.
You have two bugs there.
Since this is an assignment, I won't give a complete answer - just a hint. Your loop definition is wrong. Think about this: what happens on the first and on the last iteration of the loop? Imagine a 5-element array (numbered 0 to 4, as per Java rules), and work out the values of variables over iterations of the loop when you're erasing element number, say, 2.
Use System.arraycopy faster than a loop:
public static void deletionArray( int anArray[], int positionToDelete) {
System.arraycopy(anArray, positionToDelete + 1, anArray,
positionToDelete, anArray.length - positionToDelete - 1);
//anArray[length-1]=0; //you may clear the last element
}
public static int[] deletionArray(int anArray[], int positionToDelete) {
if (anArray.length == 0) {
throw new IlligalArgumentException("Error");
}
int[] ret = new int[anArray.length - 1];
int j = 0;
for (int i = 0; i < anArray.length; ++i) {
if (i != positionToDelete) {
ret[j] = anArray[i];
++j;
}
}
return ret;
}
Why do we reserve a new array?
Because if don't, we would use C\C++-style array: an array and a "used length" of it.
public static int deletionArray(int anArray[], int positionToDelete, int n) {
if (n == 0) {
throw new IlligalArgumentException("Error");
}
for (int i = positionToDelete; i < n - 1; ++i) {
anArray[i] = anArray[i + 1];
}
return n - 1; // the new length
}
How's this ? Please note the comment, I don't think you can delete an element in an array, just replace it with something else, this may be useful : Removing an element from an Array (Java)
Updated with 'JB Nizet' comment :
public class Driver {
public static void main (String args []){
int intArray[] = { 1,3,5,6,7,8};
int updatedArray[] = deletionArray(intArray , 3);
for (int j = 0; j < updatedArray.length; j++) {
System.out.println(updatedArray[j]);
}
}
public static int[] deletionArray(int anArray[], int positionToDelete) {
boolean isTrue = false;
for (int j = positionToDelete; j < anArray.length - 1; j++) {
if(j == positionToDelete || isTrue){
isTrue = true;
anArray[j] = anArray[j + 1];
}
}
anArray[anArray.length-1] = 0; //decide what value this should be or create a new array with just the array elements of length -> anArray.length-2
return anArray;
}
}