Finding intersection of two sorted arrays in Java - java

public class intersect {
public static void find(int[] a, int[] b, int[] acc)
{
int position = 0;
for (int j = 0; j < a.length; j++) {
for (int k = 0; k<b.length; k++) {
if (a[j] == b[k]) {
acc[position] = b[k];
position++;
}
}
}
System.out.println(java.util.Arrays.toString(acc));
}
public static void main (String[] s)
{
int[] acc = new int[2];
int[] a = {1,2,3};
int[] b = {2,3,4};
find(a, b, acc);
}
}
I have written the above code to solve the problem.
But if you see, the function is very limited because I have to change the length of the acc every time. That means I have to know how many elements are intersecting. In this case, the array {1,2,3} and {2,3,4} have {2,3} in common, so the length of the acc would be 2.
I am sure there are millions of ways of tackling this problem, but I cannot seem to think of a way of fixing this.
Please help!

If your professor wants you to use arrays, you can use the following method:
public static int[] resize(int[] arr)
{
int len = arr.length;
int[] copy = new int[len+1];
for (int i = 0; i < len; i++)
{
copy[i] = arr[i];
}
return copy;
}
This will increase the size of the array by 1. You can use that instead. By the way, you're not using the fact that they're sorted in your find() method. What you should do is this:
public static void find(int[] a, int[] b, int[] acc)
{
int a_index = 0, b_index = 0, acc_index = -1;
int a_element, b_element;
while (a_index < a.length && b_index < b.length)
{
a_element = a[a_index]; b_element = b[b_index];
if (a_element == b_element)
{
acc = resize(acc);
acc[++acc_index] = a_element;
a_index++; b_index++;
} else if (b_element < a_element) {
b_index++;
} else {
a_index++;
}
}
System.out.println(java.util.Arrays.toString(acc));
}
This method is more efficient now. Working example.

To find intersection of 2 sorted arrays, follow the below approach :
1) Use two index variables i and j, initial values with 0
2) If array1 is smaller than array2 then increment i.
3) If array1 is greater than array2 then increment j.
4) If both are same then print any of them and increment both i and j.
check this link for more information
https://www.geeksforgeeks.org/union-and-intersection-of-two-sorted-arrays-2/
public class FindIntersection {
static void findInterSection(int array1[], int array2[], int array1NoOfElements, int
array2NoOfElements) {
int i = 0, j = 0;
while (i < array1NoOfElements && j < array2NoOfElements) {
if (array1[i] < array2[j]) {
i++;
} else if (array2[j] < array1[i]) {
j++;
}
// if both array elements are same
else {
System.out.println(array2[j++] + " ");
i++;
}
}
}
public static void main(String[] args)
{
int myFirstArray[] = { 1, 2, 4, 5, 5 };
int mySecondArray[] = { 2, 3, 5, 7 };
int m = myFirstArray.length;
int n = mySecondArray.length;
findInterSection(myFirstArray, mySecondArray, m, n);
}
}

Make your intersection array's size the size of the smaller of your original arrays. That way, you won't ever have to increase it's capacity.
Then you can use Arrays.copy to transfer your results into an appropriately sized array.

Not sure if this is the best solution, but you don't need to hard-code the size of the intersection ahead of time (which is one thing you were concerned about).
As you iterate through both arrays, you can add elements found in both sets to a StringBuilder (along with some delimiter, I used a comma in the example below). Once you're finished, you can call toString() & then split() using the delimiter afterwards to get a String[]. At that point, you can put convert those String objects to int primitives & return an int[].
public class Scratch {
public static void main(String[] s) {
int[] a = {1, 2, 3};
int[] b = {2, 3, 4};
int[] intersection = findIntersection(a, b);
System.out.println(Arrays.toString(intersection));
}
public static int[] findIntersection(int[] a, int[] b) {
StringBuilder intersectionStringBuilder = new StringBuilder();
for (int j = 0; j < a.length; j++) {
for (int k = 0; k < b.length; k++) {
if (a[j] == b[k])
intersectionStringBuilder.append(a[j] + ",");
}
}
String[] intersectionStringArray = intersectionStringBuilder.toString().split(",");
int[] intersection = new int[intersectionStringArray.length];
for (int current = 0; current < intersectionStringArray.length; current++) {
intersection[current] = Integer.parseInt(intersectionStringArray[current]);
}
return intersection;
}
}

for(int i=0;i<arr1.length;i++){
for(int j=0;j<arr2.length;j++){
if(arr1[i]==arr2[j] && !index.contains(j)){
list.add(arr1[i]);
index.add(j);
break;
}
}
}
int result[]=new int[list.size()];
int k=0;
for(int i:list){
result[k]=i;
k++;
}
for(int i=0;i<result.length;i++){
System.out.println(result[i]);
}
return result;
}

Related

error: incompatible types: int[] cannot be converted to int when trying to merge two sorted arrays

Trying to merge two sorted arrays together but I'm receiving an error:
error: incompatible types: int[] cannot be converted to int
I did some research but I couldn't really figure out why this is happening. I know my program is having an issue with the sorted array but I'm not sure what the fix would be.
Here is my code:
public class MedianOfTwoSortedArrays
{
//[1,2],{3,4}
static int[] nums1 = new int[]{1, 3};
static int[] nums2 = new int[]{2};
public static void main(String args[])
{
System.out.println(findMedianSortedArrays(nums1, nums2));
}
public static int findMedianSortedArrays(int[] nums1, int[] nums2)
{
int[] sorted = new int[nums1.length + nums2.length];
int i = 0, j = 0, k = 0;
while (i < nums1.length && j < nums2.length)
{
if (nums1[i] < nums2[j])
{
sorted[k] = nums1[i];
i++;
}
else
{
sorted[k] = nums2[j];
j++;
}
k++;
}
while (i < nums1.length)
{
sorted[k] = nums1[i];
i++;
k++;
}
while (j < nums2.length)
{
sorted[k] = nums2[j];
j++;
k++;
}
return sorted;
}
}
Quick fix! Just change your return statement to:
return sorted[sorted.length / 2];
You were returning an int[] (the sorted array) instead of the median value of the sorted array.
I tested with an even number of elements and it returns the first of the two middle values fyi. You can verify the combined length is odd at the start of your method if you'd like. Odd works as expected. Don't forget to accept please!
You are returning array and your method says int due to which code won't even compile. Use
public static int[] findMedianSortedArrays(int[] nums1, int[] nums2)
instead of
public static int findMedianSortedArrays(int[] nums1, int[] nums2)
You have to also iterate over resultant array in main method to print values.
The first mistake you are doing is that you are returning int array and your method return type is int.
public class MedianOfTwoSortedArrays
{
//[1,2],{3,4}
static int[] nums1 = new int[]{1, 3};
static int[] nums2 = new int[]{2};
public static void main(String args[])
{
int a[] = findMedianSortedArrays(nums1, nums2);
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
}
public static int[] findMedianSortedArrays(int[] nums1, int[] nums2)
{
int[] sorted = new int[nums1.length + nums2.length];
int i = 0, j = 0, k = 0;
while (i < nums1.length && j < nums2.length)
{
if (nums1[i] < nums2[j])
{
sorted[k] = nums1[i];
i++;
}
else
{
sorted[k] = nums2[j];
j++;
}
k++;
}
while (i < nums1.length)
{
sorted[k] = nums1[i];
i++;
k++;
}
while (j < nums2.length)
{
sorted[k] = nums2[j];
j++;
k++;
}
return sorted;
}
}
you have to store the result in array and loop over it.

Brute forcing the twosum algorithm

The twosum question is:
Given nums = [2, 7, 11, 15], target = 9, Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].
I'm learning java and I'm going through some leetcode problems. I'm trying to come up with a brute force solution before I code for efficiency but my code won't seem to compile:
public class TwoSum
{
//static int[] arraynums = new int[]{2, 7, 11, 15};
//static int target = 9;
//public static void main(String args[])
//{
//TwoSum name = new TwoSum();
//name.twoSums(arraynums, target);
//}
public int twoSums(int[] nums, int target)
{
int sum = 0;
for (int i = 0; i < nums.length; i++)
{
for (int j = 0; j < nums.length; j++)
{
sum = nums[i] + nums[j];
if (sum == target)
{
System.out.println(i + " " + j);
return new int[] {i,j};
}
}
}
return new int[] {};
}
}
I know I need a return statement but I'm not sure what I should return and I'm also not sure if my main method is required.
#Alfabravo is right. you need to return an array of integer. If you don't want to return anything. just use
public void twoSum(int[] nums, int target)
You're on the right track!
In regards to adding a return statement, just add it after the println statement.
...
System.out.println(i + " " + j);
return new int[] {i,j};
...
although you need to check that i and j are not equal as they will point to the same number in nums if they are. Unless that isn't a requirement of the question. If it is you could add something like
if (sum == target && i != j)
good luck.
For leetCode you just need to complete the codes and no need to add a main function.
For your twoSum method you need to return an array with type int which contains the index of elements.
You can test like this:
public static void main(String args[]) {
int[] testData = {2, 7, 11, 15};
int target = 9;
TwoSum ts = new TwoSum();
int[] result = ts.twoSum(testData, target);
for (int i = 0; i < result.length; i++) {
System.out.println(result[i]);
}
}
public class Solution {
public int[] twoSum(int[] num, int target) {
// Take an array and the target number as parameter
// Initialize the variables
int length = num.length;
int index1 = 0;
int index2 = 0;
int i;
int j;
for (i=0; i<length; i++) {
// First loop, i starts at num[0] which is the first element in array
for (j=i+1; j<length; j++){
// Second loop, j starts at num[1], the second element
if (num[i] + num[j] == target){
// If they are equal return the index
index1 = i;
index2 = j;
}
}
}
// The result should be an array contains 2 indices
int[] result = new int[] {index1, index2};
return result;
}
}
Loop through each element x and find if there is another value that equals to target−x.
Just a small mistake when you're iterating in the next loop, just add j = i + 1. That will do it.
public int[] twoSum(int[] nums, int target) {
for(int i = 0; i < nums.length; i++){
for(int j = i + 1; j < nums.length; j++){
if (nums[i] + nums[j] == target){
return new int[] { i,j };
}
}
}
return new int[] {};
}
class Solution {
public int[] twoSum(int[] numbers, int target) {
int first = 0, sec = numbers.length-1;
while(first!=sec){
if((numbers[first]+numbers[sec])==target)
break;
else if((numbers[first]+numbers[sec])>target)
sec--;
else
first++;
}
int res[] = new int[2];
res[0] = first+1;
res[1] = sec+1;
return res;
}
}

copy specific row from one 2D array to another without system.arraycopy

So I have to write a method that goes in array and goes from i to j rows and copies these rows to a new array. This is what I come up so far
public static void getRows(int i, int j, int[][] array){
int another[] = new int[j-i];
int n = 0;
for (int k = 0; k < array.length; k++){
while (i <= j){
if (k == i){
another[n] = array[k][0];
}
i++;
}
}
}
First, you aren't returning or printing anything. Second, to copy multiple rows from your input your returned array should be 2d (not 1d). Create a new int[][] of j - i rows. Then copy from array to the new array. Something like,
public static int[][] getRows(int i, int j, int[][] array) {
int[][] ret = new int[j - i][];
for (int k = i; k < j; k++) {
ret[k - i] = new int[array[k].length];
for (int m = 0; m < ret[k - i].length; m++) {
ret[k - i][m] = array[k][m];
}
}
return ret;
}
Then you can invoke it (and print the results) with something like
public static void main(String[] args) {
int[][] t = { { 0, 1 }, { 2, 3 }, { 4, 5 } };
System.out.println(Arrays.deepToString(getRows(1, 3, t)));
}
Which outputs
[[2, 3], [4, 5]]
#Elliot I did it like this :)
public static int[][] getRows(int i, int j, int[][] array){
int[][] another = new int[j-i+1][];
while (i <=j){
for (int k = 0; k < another.length; k++){
another[k]=array[i];
i++;
}
}
return another;
}

how to print non repeated numbers from integer array using java and without using predefined api's? [duplicate]

I was asked to write my own implementation to remove duplicated values in an array. Here is what I have created. But after tests with 1,000,000 elements it took very long time to finish. Is there something that I can do to improve my algorithm or any bugs to remove ?
I need to write my own implementation - not to use Set, HashSet etc. Or any other tools such as iterators. Simply an array to remove duplicates.
public static int[] removeDuplicates(int[] arr) {
int end = arr.length;
for (int i = 0; i < end; i++) {
for (int j = i + 1; j < end; j++) {
if (arr[i] == arr[j]) {
int shiftLeft = j;
for (int k = j+1; k < end; k++, shiftLeft++) {
arr[shiftLeft] = arr[k];
}
end--;
j--;
}
}
}
int[] whitelist = new int[end];
for(int i = 0; i < end; i++){
whitelist[i] = arr[i];
}
return whitelist;
}
you can take the help of Set collection
int end = arr.length;
Set<Integer> set = new HashSet<Integer>();
for(int i = 0; i < end; i++){
set.add(arr[i]);
}
now if you will iterate through this set, it will contain only unique values. Iterating code is like this :
Iterator it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
If you are allowed to use Java 8 streams:
Arrays.stream(arr).distinct().toArray();
Note: I am assuming the array is sorted.
Code:
int[] input = new int[]{1, 1, 3, 7, 7, 8, 9, 9, 9, 10};
int current = input[0];
boolean found = false;
for (int i = 0; i < input.length; i++) {
if (current == input[i] && !found) {
found = true;
} else if (current != input[i]) {
System.out.print(" " + current);
current = input[i];
found = false;
}
}
System.out.print(" " + current);
output:
1 3 7 8 9 10
Slight modification to the original code itself, by removing the innermost for loop.
public static int[] removeDuplicates(int[] arr){
int end = arr.length;
for (int i = 0; i < end; i++) {
for (int j = i + 1; j < end; j++) {
if (arr[i] == arr[j]) {
/*int shiftLeft = j;
for (int k = j+1; k < end; k++, shiftLeft++) {
arr[shiftLeft] = arr[k];
}*/
arr[j] = arr[end-1];
end--;
j--;
}
}
}
int[] whitelist = new int[end];
/*for(int i = 0; i < end; i++){
whitelist[i] = arr[i];
}*/
System.arraycopy(arr, 0, whitelist, 0, end);
return whitelist;
}
There exists many solution of this problem.
The sort approach
You sort your array and resolve only unique items
The set approach
You declare a HashSet where you put all item then you have only unique ones.
You create a boolean array that represent the items all ready returned, (this depend on your data in the array).
If you deal with large amount of data i would pick the 1. solution. As you do not allocate additional memory and sorting is quite fast. For small set of data the complexity would be n^2 but for large i will be n log n.
Since you can assume the range is between 0-1000 there is a very simple and efficient solution
//Throws an exception if values are not in the range of 0-1000
public static int[] removeDuplicates(int[] arr) {
boolean[] set = new boolean[1001]; //values must default to false
int totalItems = 0;
for (int i = 0; i < arr.length; ++i) {
if (!set[arr[i]]) {
set[arr[i]] = true;
totalItems++;
}
}
int[] ret = new int[totalItems];
int c = 0;
for (int i = 0; i < set.length; ++i) {
if (set[i]) {
ret[c++] = i;
}
}
return ret;
}
This runs in linear time O(n). Caveat: the returned array is sorted so if that is illegal then this answer is invalid.
class Demo
{
public static void main(String[] args)
{
int a[]={3,2,1,4,2,1};
System.out.print("Before Sorting:");
for (int i=0;i<a.length; i++ )
{
System.out.print(a[i]+"\t");
}
System.out.print ("\nAfter Sorting:");
//sorting the elements
for(int i=0;i<a.length;i++)
{
for(int j=i;j<a.length;j++)
{
if(a[i]>a[j])
{
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
//After sorting
for(int i=0;i<a.length;i++)
{
System.out.print(a[i]+"\t");
}
System.out.print("\nAfter removing duplicates:");
int b=0;
a[b]=a[0];
for(int i=0;i<a.length;i++)
{
if (a[b]!=a[i])
{
b++;
a[b]=a[i];
}
}
for (int i=0;i<=b;i++ )
{
System.out.print(a[i]+"\t");
}
}
}
OUTPUT:Before Sortng:3 2 1 4 2 1 After Sorting:1 1 2 2 3 4
Removing Duplicates:1 2 3 4
Since this question is still getting a lot of attention, I decided to answer it by copying this answer from Code Review.SE:
You're following the same philosophy as the bubble sort, which is
very, very, very slow. Have you tried this?:
Sort your unordered array with quicksort. Quicksort is much faster
than bubble sort (I know, you are not sorting, but the algorithm you
follow is almost the same as bubble sort to traverse the array).
Then start removing duplicates (repeated values will be next to each
other). In a for loop you could have two indices: source and
destination. (On each loop you copy source to destination unless they
are the same, and increment both by 1). Every time you find a
duplicate you increment source (and don't perform the copy).
#morgano
import java.util.Arrays;
public class Practice {
public static void main(String[] args) {
int a[] = { 1, 3, 3, 4, 2, 1, 5, 6, 7, 7, 8, 10 };
Arrays.sort(a);
int j = 0;
for (int i = 0; i < a.length - 1; i++) {
if (a[i] != a[i + 1]) {
a[j] = a[i];
j++;
}
}
a[j] = a[a.length - 1];
for (int i = 0; i <= j; i++) {
System.out.println(a[i]);
}
}
}
**This is the most simplest way**
What if you create two boolean arrays: 1 for negative values and 1 for positive values and init it all on false.
Then you cycle thorugh the input array and lookup in the arrays if you've encoutered the value already.
If not, you add it to the output array and mark it as already used.
package com.pari.practice;
import java.util.HashSet;
import java.util.Iterator;
import com.pari.sort.Sort;
public class RemoveDuplicates {
/**
* brute force- o(N square)
*
* #param input
* #return
*/
public static int[] removeDups(int[] input){
boolean[] isSame = new boolean[input.length];
int sameNums = 0;
for( int i = 0; i < input.length; i++ ){
for( int j = i+1; j < input.length; j++){
if( input[j] == input[i] ){ //compare same
isSame[j] = true;
sameNums++;
}
}
}
//compact the array into the result.
int[] result = new int[input.length-sameNums];
int count = 0;
for( int i = 0; i < input.length; i++ ){
if( isSame[i] == true) {
continue;
}
else{
result[count] = input[i];
count++;
}
}
return result;
}
/**
* set - o(N)
* does not guarantee order of elements returned - set property
*
* #param input
* #return
*/
public static int[] removeDups1(int[] input){
HashSet myset = new HashSet();
for( int i = 0; i < input.length; i++ ){
myset.add(input[i]);
}
//compact the array into the result.
int[] result = new int[myset.size()];
Iterator setitr = myset.iterator();
int count = 0;
while( setitr.hasNext() ){
result[count] = (int) setitr.next();
count++;
}
return result;
}
/**
* quicksort - o(Nlogn)
*
* #param input
* #return
*/
public static int[] removeDups2(int[] input){
Sort st = new Sort();
st.quickSort(input, 0, input.length-1); //input is sorted
//compact the array into the result.
int[] intermediateResult = new int[input.length];
int count = 0;
int prev = Integer.MIN_VALUE;
for( int i = 0; i < input.length; i++ ){
if( input[i] != prev ){
intermediateResult[count] = input[i];
count++;
}
prev = input[i];
}
int[] result = new int[count];
System.arraycopy(intermediateResult, 0, result, 0, count);
return result;
}
public static void printArray(int[] input){
for( int i = 0; i < input.length; i++ ){
System.out.print(input[i] + " ");
}
}
public static void main(String[] args){
int[] input = {5,6,8,0,1,2,5,9,11,0};
RemoveDuplicates.printArray(RemoveDuplicates.removeDups(input));
System.out.println();
RemoveDuplicates.printArray(RemoveDuplicates.removeDups1(input));
System.out.println();
RemoveDuplicates.printArray(RemoveDuplicates.removeDups2(input));
}
}
Output:
5 6 8 0 1 2 9 11
0 1 2 5 6 8 9 11
0 1 2 5 6 8 9 11
I have just written the above code for trying out. thanks.
public static int[] removeDuplicates(int[] arr){
HashSet<Integer> set = new HashSet<>();
final int len = arr.length;
//changed end to len
for(int i = 0; i < len; i++){
set.add(arr[i]);
}
int[] whitelist = new int[set.size()];
int i = 0;
for (Iterator<Integer> it = set.iterator(); it.hasNext();) {
whitelist[i++] = it.next();
}
return whitelist;
}
Runs in O(N) time instead of your O(N^3) time
Not a big fun of updating user input, however considering your constraints...
public int[] removeDup(int[] nums) {
Arrays.sort(nums);
int x = 0;
for (int i = 0; i < nums.length; i++) {
if (i == 0 || nums[i] != nums[i - 1]) {
nums[x++] = nums[i];
}
}
return Arrays.copyOf(nums, x);
}
Array sort can be easily replaced with any nlog(n) algorithm.
This is simple way to sort the elements in the array
public class DublicatesRemove {
public static void main(String args[]) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("enter size of the array");
int l = Integer.parseInt(br.readLine());
int[] a = new int[l];
// insert elements in the array logic
for (int i = 0; i < l; i++)
{
System.out.println("enter a element");
int el = Integer.parseInt(br.readLine());
a[i] = el;
}
// sorting elements in the array logic
for (int i = 0; i < l; i++)
{
for (int j = 0; j < l - 1; j++)
{
if (a[j] > a[j + 1])
{
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
// remove duplicate elements logic
int b = 0;
a[b] = a[0];
for (int i = 1; i < l; i++)
{
if (a[b] != a[i])
{
b++;
a[b]=a[i];
}
}
for(int i=0;i<=b;i++)
{
System.out.println(a[i]);
}
}
}
Okay, so you cannot use Set or other collections. One solution I don't see here so far is one based on the use of a Bloom filter, which essentially is an array of bits, so perhaps that passes your requirements.
The Bloom filter is a lovely and very handy technique, fast and space-efficient, that can be used to do a quick check of the existence of an element in a set without storing the set itself or the elements. It has a (typically small) false positive rate, but no false negative rate. In other words, for your question, if a Bloom filter tells you that an element hasn't been seen so far, you can be sure it hasn't. But if it says that an element has been seen, you actually need to check. This still saves a lot of time if there aren't too many duplicates in your list (for those, there is no looping to do, except in the small probability case of a false positive --you typically chose this rate based on how much space you are willing to give to the Bloom filter (rule of thumb: less than 10 bits per unique element for a false positive rate of 1%).
There are many implementations of Bloom filters, see e.g. here or here, so I won't repeat that in this answer. Let us just assume the api described in that last reference, in particular, the description of put(E e):
true if the Bloom filter's bits changed as a result of this operation. If the bits changed, this is definitely the first time object has been added to the filter. If the bits haven't changed, this might be the first time object has been added to the filter. (...)
An implementation using such a Bloom filter would then be:
public static int[] removeDuplicates(int[] arr) {
ArrayList<Integer> out = new ArrayList<>();
int n = arr.length;
BloomFilter<Integer> bf = new BloomFilter<>(...); // decide how many bits and how many hash functions to use (compromise between space and false positive rate)
for (int e : arr) {
boolean might_contain = !bf.put(e);
boolean found = false;
if (might_contain) {
// check if false positive
for (int u : out) {
if (u == e) {
found = true;
break;
}
}
}
if (!found) {
out.add(e);
}
}
return out.stream().mapToInt(i -> i).toArray();
}
Obviously, if you can alter the incoming array in place, then there is no need for an ArrayList: at the end, when you know the actual number of unique elements, just arraycopy() those.
For a sorted Array, just check the next index:
//sorted data!
public static int[] distinct(int[] arr) {
int[] temp = new int[arr.length];
int count = 0;
for (int i = 0; i < arr.length; i++) {
int current = arr[i];
if(count > 0 )
if(temp[count - 1] == current)
continue;
temp[count] = current;
count++;
}
int[] whitelist = new int[count];
System.arraycopy(temp, 0, whitelist, 0, count);
return whitelist;
}
You need to sort your array then then loop and remove duplicates. As you cannot use other tools you need to write be code yourself.
You can easily find examples of quicksort in Java on the internet (on which this example is based).
public static void main(String[] args) throws Exception {
final int[] original = new int[]{1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1};
System.out.println(Arrays.toString(original));
quicksort(original);
System.out.println(Arrays.toString(original));
final int[] unqiue = new int[original.length];
int prev = original[0];
unqiue[0] = prev;
int count = 1;
for (int i = 1; i < original.length; ++i) {
if (original[i] != prev) {
unqiue[count++] = original[i];
}
prev = original[i];
}
System.out.println(Arrays.toString(unqiue));
final int[] compressed = new int[count];
System.arraycopy(unqiue, 0, compressed, 0, count);
System.out.println(Arrays.toString(compressed));
}
private static void quicksort(final int[] values) {
if (values.length == 0) {
return;
}
quicksort(values, 0, values.length - 1);
}
private static void quicksort(final int[] values, final int low, final int high) {
int i = low, j = high;
int pivot = values[low + (high - low) / 2];
while (i <= j) {
while (values[i] < pivot) {
i++;
}
while (values[j] > pivot) {
j--;
}
if (i <= j) {
swap(values, i, j);
i++;
j--;
}
}
if (low < j) {
quicksort(values, low, j);
}
if (i < high) {
quicksort(values, i, high);
}
}
private static void swap(final int[] values, final int i, final int j) {
final int temp = values[i];
values[i] = values[j];
values[j] = temp;
}
So the process runs in 3 steps.
Sort the array - O(nlgn)
Remove duplicates - O(n)
Compact the array - O(n)
So this improves significantly on your O(n^3) approach.
Output:
[1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1]
[1, 1, 1, 2, 4, 4, 7, 8, 8, 9, 9]
[1, 2, 4, 7, 8, 9, 0, 0, 0, 0, 0]
[1, 2, 4, 7, 8, 9]
EDIT
OP states values inside array doesn't matter really. But I can assume that range is between 0-1000. This is a classic case where an O(n) sort can be used.
We create an array of size range +1, in this case 1001. We then loop over the data and increment the values on each index corresponding to the datapoint.
We can then compact the resulting array, dropping values the have not been incremented. This makes the values unique as we ignore the count.
public static void main(String[] args) throws Exception {
final int[] original = new int[]{1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1, 1000, 1000};
System.out.println(Arrays.toString(original));
final int[] buckets = new int[1001];
for (final int i : original) {
buckets[i]++;
}
final int[] unique = new int[original.length];
int count = 0;
for (int i = 0; i < buckets.length; ++i) {
if (buckets[i] > 0) {
unique[count++] = i;
}
}
final int[] compressed = new int[count];
System.arraycopy(unique, 0, compressed, 0, count);
System.out.println(Arrays.toString(compressed));
}
Output:
[1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1, 1000, 1000]
[1, 2, 4, 7, 8, 9, 1000]
public static void main(String args[]) {
int[] intarray = {1,2,3,4,5,1,2,3,4,5,1,2,3,4,5};
Set<Integer> set = new HashSet<Integer>();
for(int i : intarray) {
set.add(i);
}
Iterator<Integer> setitr = set.iterator();
for(int pos=0; pos < intarray.length; pos ++) {
if(pos < set.size()) {
intarray[pos] =setitr.next();
} else {
intarray[pos]= 0;
}
}
for(int i: intarray)
System.out.println(i);
}
I know this is kinda dead but I just wrote this for my own use. It's more or less the same as adding to a hashset and then pulling all the elements out of it. It should run in O(nlogn) worst case.
public static int[] removeDuplicates(int[] numbers) {
Entry[] entries = new Entry[numbers.length];
int size = 0;
for (int i = 0 ; i < numbers.length ; i++) {
int nextVal = numbers[i];
int index = nextVal % entries.length;
Entry e = entries[index];
if (e == null) {
entries[index] = new Entry(nextVal);
size++;
} else {
if(e.insert(nextVal)) {
size++;
}
}
}
int[] result = new int[size];
int index = 0;
for (int i = 0 ; i < entries.length ; i++) {
Entry current = entries[i];
while (current != null) {
result[i++] = current.value;
current = current.next;
}
}
return result;
}
public static class Entry {
int value;
Entry next;
Entry(int value) {
this.value = value;
}
public boolean insert(int newVal) {
Entry current = this;
Entry prev = null;
while (current != null) {
if (current.value == newVal) {
return false;
} else if(current.next != null) {
prev = current;
current = next;
}
}
prev.next = new Entry(value);
return true;
}
}
int tempvar=0; //Variable for the final array without any duplicates
int whilecount=0; //variable for while loop
while(whilecount<(nsprtable*2)-1) //nsprtable can be any number
{
//to check whether the next value is idential in case of sorted array
if(temparray[whilecount]!=temparray[whilecount+1])
{
finalarray[tempvar]=temparray[whilecount];
tempvar++;
whilecount=whilecount+1;
}
else if (temparray[whilecount]==temparray[whilecount+1])
{
finalarray[tempvar]=temparray[whilecount];
tempvar++;
whilecount=whilecount+2;
}
}
Hope this helps or solves the purpose.
package javaa;
public class UniqueElementinAnArray
{
public static void main(String[] args)
{
int[] a = {10,10,10,10,10,100};
int[] output = new int[a.length];
int count = 0;
int num = 0;
//Iterate over an array
for(int i=0; i<a.length; i++)
{
num=a[i];
boolean flag = check(output,num);
if(flag==false)
{
output[count]=num;
++count;
}
}
//print the all the elements from an array except zero's (0)
for (int i : output)
{
if(i!=0 )
System.out.print(i+" ");
}
}
/***
* If a next number from an array is already exists in unique array then return true else false
* #param arr Unique number array. Initially this array is an empty.
* #param num Number to be search in unique array. Whether it is duplicate or unique.
* #return true: If a number is already exists in an array else false
*/
public static boolean check(int[] arr, int num)
{
boolean flag = false;
for(int i=0;i<arr.length; i++)
{
if(arr[i]==num)
{
flag = true;
break;
}
}
return flag;
}
}
public static int[] removeDuplicates(int[] arr) {
int end = arr.length;
HashSet<Integer> set = new HashSet<Integer>(end);
for(int i = 0 ; i < end ; i++){
set.add(arr[i]);
}
return set.toArray();
}
You can use an auxiliary array (temp) which in indexes are numbers of main array. So the time complexity will be liner and O(n). As we want to do it without using any library, we define another array (unique) to push non-duplicate elements:
var num = [2,4,9,4,1,2,24,12,4];
let temp = [];
let unique = [];
let j = 0;
for (let i = 0; i < num.length; i++){
if (temp[num[i]] !== 1){
temp[num[i]] = 1;
unique[j++] = num[i];
}
}
console.log(unique);
If you are looking to remove duplicates using the same array and also keeping the time complexity of O(n). Then this should do the trick. Also, would only work if the array is sorted.
function removeDuplicates_sorted(arr){
let j = 0;
for(let x = 0; x < arr.length - 1; x++){
if(arr[x] != arr[x + 1]){
arr[j++] = arr[x];
}
}
arr[j++] = arr[arr.length - 1];
arr.length = j;
return arr;
}
Here is for an unsorted array, its O(n) but uses more space complexity then the sorted.
function removeDuplicates_unsorted(arr){
let map = {};
let j = 0;
for(var numbers of arr){
if(!map[numbers]){
map[numbers] = 1;
arr[j++] = numbers;
}
}
arr.length = j;
return arr;
}
Note to other readers who desire to use the Set method of solving this problem: If original ordering must be preserved, do not use HashSet as in the top result. HashSet does not guarantee the preservation of the original order, so LinkedHashSet should be used instead-this keeps track of the order in which the elements were inserted into the set and returns them in that order.
This is an interview question.
public class Test4 {
public static void main(String[] args) {
int a[] = {1, 2, 2, 3, 3, 3, 6,6,6,6,6,66,7,65};
int newlength = lengthofarraywithoutduplicates(a);
for(int i = 0 ; i < newlength ;i++) {
System.out.println(a[i]);
}//for
}//main
private static int lengthofarraywithoutduplicates(int[] a) {
int count = 1 ;
for (int i = 1; i < a.length; i++) {
int ch = a[i];
if(ch != a[i-1]) {
a[count++] = ch;
}//if
}//for
return count;
}//fix
}//end1
But, it's always better to use Stream :
int[] a = {1, 2, 2, 3, 3, 3, 6,6,6,6,6,66,7,65};
int[] array = Arrays.stream(a).distinct().toArray();
System.out.println(Arrays.toString(array));//[1, 2, 3, 6, 66, 7, 65]
How about this one, only for the sorted Array of numbers, to print the Array without duplicates, without using Set or other Collections, just an Array:
public static int[] removeDuplicates(int[] array) {
int[] nums = new int[array.length];
int addedNumber = 0;
int j = 0;
for(int i=0; i < array.length; i++) {
if (addedNumber != array[i]) {
nums[j] = array[i];
j++;
addedNumber = nums[j-1];
}
}
return Arrays.copyOf(nums, j);
}
An array of 1040 duplicated numbers processed in 33020 nanoseconds(0.033020 millisec).
public static void main(String[] args) {
Integer[] intArray = { 1, 1, 1, 2, 4, 2, 3, 5, 3, 6, 7, 3, 4, 5 };
Integer[] finalArray = removeDuplicates(intArray);
System.err.println(Arrays.asList(finalArray));
}
private static Integer[] removeDuplicates(Integer[] intArray) {
int count = 0;
Integer[] interimArray = new Integer[intArray.length];
for (int i = 0; i < intArray.length; i++) {
boolean exists = false;
for (int j = 0; j < interimArray.length; j++) {
if (interimArray[j]!=null && interimArray[j] == intArray[i]) {
exists = true;
}
}
if (!exists) {
interimArray[count] = intArray[i];
count++;
}
}
final Integer[] finalArray = new Integer[count];
System.arraycopy(interimArray, 0, finalArray, 0, count);
return finalArray;
}
I feel Android Killer's idea is great, but I just wondered if we can leverage HashMap. So I did a little experiment. And I found HashMap seems faster than HashSet.
Here is code:
int[] input = new int[1000000];
for (int i = 0; i < input.length; i++) {
Random random = new Random();
input[i] = random.nextInt(200000);
}
long startTime1 = new Date().getTime();
System.out.println("Set start time:" + startTime1);
Set<Integer> resultSet = new HashSet<Integer>();
for (int i = 0; i < input.length; i++) {
resultSet.add(input[i]);
}
long endTime1 = new Date().getTime();
System.out.println("Set end time:"+ endTime1);
System.out.println("result of set:" + (endTime1 - startTime1));
System.out.println("number of Set:" + resultSet.size() + "\n");
long startTime2 = new Date().getTime();
System.out.println("Map start time:" + startTime1);
Map<Integer, Integer> resultMap = new HashMap<Integer, Integer>();
for (int i = 0; i < input.length; i++) {
if (!resultMap.containsKey(input[i]))
resultMap.put(input[i], input[i]);
}
long endTime2 = new Date().getTime();
System.out.println("Map end Time:" + endTime2);
System.out.println("result of Map:" + (endTime2 - startTime2));
System.out.println("number of Map:" + resultMap.size());
Here is result:
Set start time:1441960583837
Set end time:1441960583917
result of set:80
number of Set:198652
Map start time:1441960583837
Map end Time:1441960583983
result of Map:66
number of Map:198652
This is not using Set, Map, List or any extra collection, only two arrays:
package arrays.duplicates;
import java.lang.reflect.Array;
import java.util.Arrays;
public class ArrayDuplicatesRemover<T> {
public static <T> T[] removeDuplicates(T[] input, Class<T> clazz) {
T[] output = (T[]) Array.newInstance(clazz, 0);
for (T t : input) {
if (!inArray(t, output)) {
output = Arrays.copyOf(output, output.length + 1);
output[output.length - 1] = t;
}
}
return output;
}
private static <T> boolean inArray(T search, T[] array) {
for (T element : array) {
if (element.equals(search)) {
return true;
}
}
return false;
}
}
And the main to test it
package arrays.duplicates;
import java.util.Arrays;
public class TestArrayDuplicates {
public static void main(String[] args) {
Integer[] array = {1, 1, 2, 2, 3, 3, 3, 3, 4};
testArrayDuplicatesRemover(array);
}
private static void testArrayDuplicatesRemover(Integer[] array) {
final Integer[] expectedResult = {1, 2, 3, 4};
Integer[] arrayWithoutDuplicates = ArrayDuplicatesRemover.removeDuplicates(array, Integer.class);
System.out.println("Array without duplicates is supposed to be: " + Arrays.toString(expectedResult));
System.out.println("Array without duplicates currently is: " + Arrays.toString(arrayWithoutDuplicates));
System.out.println("Is test passed ok?: " + (Arrays.equals(arrayWithoutDuplicates, expectedResult) ? "YES" : "NO"));
}
}
And the output:
Array without duplicates is supposed to be: [1, 2, 3, 4]
Array without duplicates currently is: [1, 2, 3, 4]
Is test passed ok?: YES

combining and sorting two arrays Java?

So basically there are two separate presorted arrays, and you have to combine them and sort them (without sort() methods of course). Here is my code:
public static void main(String[] args) {
int a [] = {3,5,7,9,12,14, 15};
int b [] = {6 ,7, 10};
int j = 0;
//output array should be 3,5,6,7,7,9,10,12,14,15
int c [] = new int[a.length+b.length];//10 values
for (int i = 0;i<b.length;i++){
while(b[i]>a[j]){
c[j] = a[j] ;
j++;
}
if(b[i] == a[j]){
c[j] = b[i];
c[j+1] = a[j];
}
c[j] = b[i];
j++;
}
for(int i = 0;i<c.length;i++)
System.out.println(c[i]);
}
I'm guessing the zeros I am getting are from a mistake in one of the booleans (< & >), but I cant seem to figure it out. It works fine for the first 4, but once I get to the repeating 7's, it just goes crazy.
Please help me understand, don't just change the code.
This is how it should be in a simple way:
public static void main(String[] args) {
int a [] = {3,5,7,9,12,14, 15};
int b [] = {6 ,7, 10};
int j = 0, k = 0;
//output array should be 3,5,6,7,7,9,10,12,14,15
int c [] = new int[a.length+b.length];//10 values
// we're filling c with the next appropriate number
// we start with checking a[0] and b[0] till we add
// all the elements
for (int i = 0; i < c.length; i++) {
// if both "a" and "b" have elements left to check
if (j < a.length && k < b.length) {
// check if "b" has a smaller element
if (b[k] < a[j]) {
// if so add it to "c"
c[i] = b[k];
k++;
}
// if "a" has a smaller element
else {
// add it to "c"
c[i] = a[j];
j++;
}
}
// if there are no more elements to check in "a"
// but there are still elements to check in "b"
else if (k < b.length) {
// add those elements in "b" to "c"
c[i] = b[k];
k++;
}
// if there are no more elements to check in "b"
// but there are still elements to check in "a"
else {
// add those elements in "a" to "c"
c[i] = a[j];
j++;
}
}
for(int i = 0; i < c.length; i++)
System.out.println(c[i]);
}
Hope it helps.
You can try this code.
public static void main(String[] args) {
int a[] = { 3, 5, 7, 9, 12, 14, 15 };
int b[] = { 6, 7, 10 };
// output array should be 3,5,6,7,7,9,10,12,14,15
int alen = a.length;
int blen = b.length;
int c[] = new int[a.length + b.length];// 10 values
int s[] = null;
int[] l = null;
if (alen < blen) {
s = a;
l = b;
} else {
s = b;
l = a;
}
// Constructing Combined Array
for (int i = 0, p = 0; i < c.length; i++, p++) {
if (i == s.length) {
p = 0;
}
if (i < s.length) {
c[i] = s[p];
} else {
c[i] = l[p];
}
}
//Sorting the C array
for (int i = 1; i < c.length; i++) {
int j = i;
int B = c[i];
while ((j > 0) && (c[j - 1] > B)) {
c[j] = c[j - 1];
j--;
}
c[j] = B;
}
for (int i = 0; i < c.length; i++)
System.out.print(c[i]);
}
Actually it's better to say merging (not combining) two arrays.
Simple algorithm (taken from this article) for merging sorted arrays A and B[0..n-1] into result C[0..m+n-1]:
Introduce read-indices i, j to traverse arrays A[0..m-1] and B, accordingly. Introduce write-index k to store position of the first free cell in the resulting array. By default i = j = k = 0.
At each step: if both indices are in range (i < m and j < n), choose minimum of (A[i], B[j]) and write it to C[k]. Otherwise go to step 4.
Increase k and index of the array, algorithm located minimal value at, by one. Repeat step 2.
Copy the rest values from the array, which index is still in range, to the resulting array.
Hope it helps.
Use ai and bi for the indices in both source arrays and ci as the index for the destination array.
You only need one loop.
Try to keep this very clear and advance in c by exactly one element at each iteration.
In the loop, check wether the end of one array was reached. If so, just take an element from the other array. Otherwise, take only the smaller element of a[ai] and b[bi] and increment the corresponding index.
It is very easy to make mistakes in mergesort (or in any code where two arrays need to be walked in parallel) by thinking "hey I can go along with a while loop instead of just doing a single if", but then you typically have two loops nested in a third one, and for each of the loops you have to do the right bounds checks, and there is typically no significant gain in performance.
p.s. Doing one main loop and then two cleanup loops after the main loop is fine, just avoid nested loops if they are not necessary, in particular in interviews where this may also cause confusion when calculating the runtime.
Try this, your error is you are using the same cellular index for array A and array C:
public class MainClass {
public static void main(String[] args) {
int[] arrayA = { 23, 47, 81, 95 };
int[] arrayB = { 7, 14, 39, 55, 62, 74 };
int[] arrayC = new int[10];
merge(arrayA, arrayA.length, arrayB, arrayB.length, arrayC);
for (int i : arrayC) {
System.out.println(i);
}
}
public static void merge(int[] arrayA, int sizeA, int[] arrayB, int sizeB, int[] arrayC) {
int arrayAIndex = 0, arrayBIndex = 0, arrayCIndex = 0;
while (arrayAIndex < sizeA && arrayBIndex < sizeB)
if (arrayA[arrayAIndex] < arrayB[arrayBIndex])
arrayC[arrayCIndex++] = arrayA[arrayAIndex++];
else
arrayC[arrayCIndex++] = arrayB[arrayBIndex++];
while (arrayAIndex < sizeA)
arrayC[arrayCIndex++] = arrayA[arrayAIndex++];
while (arrayBIndex < sizeB)
arrayC[arrayCIndex++] = arrayB[arrayBIndex++];
}
}
This is another version
// size of C array must be equal or greater than
// sum of A and B arrays' sizes
public void merge(int[] A, int[] B, int[] C) {
int i, j, k, m, n;
i = 0;
j = 0;
k = 0;
m = A.length;
n = B.length;
while (i < m && j < n) {
if (A[i] <= B[j]) {
C[k] = A[i];
i++;
} else {
C[k] = B[j];
j++;
}
k++;
}
if (i < m) {
for (int p = i; p < m; p++) {
C[k] = A[p];
k++;
}
} else {
for (int p = j; p < n; p++) {
C[k] = B[p];
k++;
}
}
}
public class Combinearray {
public static void main(String[] args) {
int[] array1= {5,4,6,2,1};
int[] array2= {2,5,8,4,1,6,4};
int m=array1.length;
int n=array2.length;
int[] array3=new int[m+n];
int a=1;
for(int i=0;i<m;i++) {
array3[i]=array1[i];//array1 is copied to array3
}
for(int i=0;i<n;i++) {
array3[m-1+a]=array2[i];//array2 is copied to array3
a++;
}
//array3 is combined array
int l=array3.length;
int temp[]=new int[l];
for(int i=0;i<l;i++) {
for(int j=i+1;j<l;j++) {
if(array3[i]>array3[j]) {
temp[i]=array3[i];
array3[i]=array3[j];
array3[j]=temp[i];
}
}
}
System.out.println("sorted array is ");
System.out.print("[");
for(int i=0;i<l;i++) {
System.out.print(array3[i]+" ");
}
System.out.print("]");
}
}

Categories